Index.vue 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  1. <template>
  2. <app-view class="home-main">
  3. <template #header>
  4. <app-navbar :title="globalStore.getSystemInfo('appName')" :show-back-button="false" />
  5. </template>
  6. <Banner :data-list="topBanners" />
  7. <PullRefresh class="home-main__container" v-model="refreshing" @refresh="onRefresh">
  8. <app-block>
  9. <Cell title="通知公告" value="更多" :to="{ name: 'notice-list' }" icon="volume" is-link />
  10. </app-block>
  11. <app-block class="home-main__chart" v-if="userStore.accountName && goodsGroup.length">
  12. <Swipe :show-indicators="false" :loop="false">
  13. <SwipeItem v-for="(list, i) in goodsGroup" :key="i">
  14. <ul>
  15. <template v-for="(item, n) in list" :key="n">
  16. <li :class="[item.lastColor, item.goodsid === selectedGoods?.goodsid ? 'is-active' : '']"
  17. @click="onTabChange(item)">
  18. <div>
  19. <b style="color: #444;">{{ item.goodsname }}</b>
  20. </div>
  21. <div>
  22. <b>{{ item.last }}</b>
  23. </div>
  24. <div>
  25. <span>{{ item.rise }}</span>
  26. <span>{{ item.change }}</span>
  27. </div>
  28. </li>
  29. </template>
  30. </ul>
  31. </SwipeItem>
  32. </Swipe>
  33. <component :is="LineChart" :goodscode="selectedGoods.refgoodscode" v-if="showChart && selectedGoods" />
  34. </app-block>
  35. <app-block class="home-main__news">
  36. <CellGroup class="article">
  37. <Cell class="home-main__titlebar" title="市场资讯" value="更多" icon="fire" :to="{ name: 'news-list' }" is-link />
  38. <template v-for="(item, index) in newsList" :key="index">
  39. <Cell class="article-item" :title="item.title" :value="formatDate(item.publishdate, 'MM/DD')"
  40. :to="{ name: 'news-detail', query: { id: item.id } }" />
  41. </template>
  42. </CellGroup>
  43. </app-block>
  44. </PullRefresh>
  45. </app-view>
  46. </template>
  47. <script lang="ts" setup>
  48. import { shallowRef, defineAsyncComponent, computed, nextTick, watch } from 'vue'
  49. import { Cell, CellGroup, PullRefresh, Swipe, SwipeItem } from 'vant'
  50. import { formatDate, parsePercent, handleNumberValue, formatDecimal } from '@/filters'
  51. import { queryQuoteGoodsList } from '@/services/api/swap'
  52. import { queryImageConfigs } from '@/services/api/common'
  53. import { queryNewTitles } from "@/services/api/news"
  54. import { useGlobalStore, useUserStore, useFuturesStore } from '@/stores'
  55. import quoteSocket from '@/services/websocket/quote'
  56. import Banner from '@mobile/components/base/banner/index.vue'
  57. const LineChart = defineAsyncComponent(() => import('@mobile/components/modules/echarts/line/index.vue'))
  58. const subscribe = quoteSocket.createSubscribe()
  59. const globalStore = useGlobalStore()
  60. const userStore = useUserStore()
  61. const futuresStore = useFuturesStore()
  62. const refreshing = shallowRef(false) // 是否处于加载中状态
  63. const topBanners = shallowRef<string[]>([]) // 轮播图列表
  64. const newsList = shallowRef<Model.NewTitlesRsp[]>([]) // 资讯列表
  65. const goodsList = shallowRef<Model.QuoteGoodsListRsp[]>([]) // 掉期商品列表
  66. const selectedGoods = shallowRef<Model.QuoteGoodsListRsp>() // 选中的掉期商品
  67. const showChart = shallowRef(false)
  68. // 掉期商品组
  69. const goodsGroup = computed(() => {
  70. const arr = []
  71. const list = goodsList.value.map(({ goodsid, goodsname, refgoodscode }) => {
  72. const quote = futuresStore.getGoodsQuote(refgoodscode)
  73. const { lastColor, last = 0, rise = 0, change, decimalplace } = quote.value ?? {}
  74. return {
  75. goodsid,
  76. goodsname,
  77. refgoodscode,
  78. lastColor,
  79. last: handleNumberValue(formatDecimal(last, decimalplace)),
  80. rise: handleNumberValue(formatDecimal(rise, decimalplace)),
  81. change: parsePercent(change)
  82. }
  83. })
  84. // 分割成三个一组
  85. for (let i = 0; i < list.length; i += 3) {
  86. arr.push(list.slice(i, i + 3))
  87. }
  88. return arr
  89. })
  90. // 切换掉期商品
  91. const onTabChange = (item: unknown) => {
  92. showChart.value = false
  93. selectedGoods.value = item as Model.QuoteGoodsListRsp
  94. nextTick(() => {
  95. showChart.value = true
  96. })
  97. }
  98. // 下拉刷新
  99. const onRefresh = () => {
  100. if (!topBanners.value.length) {
  101. queryImageConfigs({
  102. data: {
  103. imageType: 1,
  104. }
  105. }).then((res) => {
  106. topBanners.value = res.data.map((e) => e.imagepath)
  107. })
  108. }
  109. // 市场资讯
  110. queryNewTitles({
  111. data: {
  112. page: 1,
  113. pagesize: 10,
  114. }
  115. }).then((res) => {
  116. newsList.value = res.data
  117. }).finally(() => {
  118. refreshing.value = false
  119. })
  120. }
  121. onRefresh()
  122. watch(() => userStore.accountName, (accountName) => {
  123. if (accountName) {
  124. if (goodsList.value.length) {
  125. const goodsCodes = goodsList.value.map((e) => e.refgoodscode)
  126. subscribe.start(...goodsCodes)
  127. } else {
  128. // 掉期商品
  129. queryQuoteGoodsList({
  130. data: {
  131. usertype: userStore.userType ?? 0,
  132. marketids: userStore.getMarketId('TRADEMODE_TJMD').toString()
  133. }
  134. }).then((res) => {
  135. if (res.data.length) {
  136. const goodsCodes = res.data.map((e) => e.refgoodscode)
  137. goodsList.value = res.data
  138. selectedGoods.value = res.data[0]
  139. showChart.value = true
  140. subscribe.start(...goodsCodes)
  141. }
  142. })
  143. }
  144. }
  145. }, {
  146. immediate: true
  147. })
  148. </script>
  149. <style lang="less">
  150. @import "./index.less";
  151. </style>