li.shaoyi il y a 2 ans
Parent
commit
f78a26ca90
43 fichiers modifiés avec 674 ajouts et 325 suppressions
  1. BIN
      public/html/ht_cg.docx
  2. BIN
      public/html/ht_xh_b.docx
  3. BIN
      public/html/ht_xh_s.docx
  4. 6 0
      public/manifest.json
  5. 23 25
      src/business/auth/index.ts
  6. 1 1
      src/business/common/index.ts
  7. 15 1
      src/business/market/index.ts
  8. 24 0
      src/filters/index.ts
  9. 0 0
      src/packages/mobile/assets/iconfont/iconfont.js
  10. BIN
      src/packages/mobile/assets/icons/ccwl.png
  11. BIN
      src/packages/mobile/assets/icons/cpjg.png
  12. BIN
      src/packages/mobile/assets/icons/cpjs.png
  13. BIN
      src/packages/mobile/assets/icons/futures.png
  14. BIN
      src/packages/mobile/assets/icons/home-active.png
  15. BIN
      src/packages/mobile/assets/icons/home.png
  16. BIN
      src/packages/mobile/assets/icons/htzr.png
  17. BIN
      src/packages/mobile/assets/icons/mine-active.png
  18. BIN
      src/packages/mobile/assets/icons/mine.png
  19. BIN
      src/packages/mobile/assets/icons/ptgz.png
  20. BIN
      src/packages/mobile/assets/icons/purchase-active.png
  21. BIN
      src/packages/mobile/assets/icons/purchase.png
  22. BIN
      src/packages/mobile/assets/icons/spot.png
  23. BIN
      src/packages/mobile/assets/icons/supply-demand-active.png
  24. BIN
      src/packages/mobile/assets/icons/supply-demand.png
  25. BIN
      src/packages/mobile/assets/icons/wdrw.png
  26. 7 10
      src/packages/mobile/components/layouts/page/index.less
  27. 0 1
      src/packages/mobile/views/bank/statement/index.vue
  28. 4 26
      src/packages/mobile/views/boot/index.vue
  29. 177 0
      src/packages/mobile/views/home/components/main/index.backup.vue
  30. 31 41
      src/packages/mobile/views/home/components/main/index.less
  31. 27 39
      src/packages/mobile/views/home/components/main/index.vue
  32. 10 7
      src/packages/mobile/views/home/index.less
  33. 8 12
      src/packages/mobile/views/home/index.vue
  34. 43 0
      src/packages/mobile/views/market/list/components/quote/index.vue
  35. 6 14
      src/packages/mobile/views/market/list/components/spot/index.vue
  36. 1 0
      src/packages/mobile/views/market/list/index.less
  37. 4 0
      src/packages/mobile/views/market/list/index.vue
  38. 1 1
      src/packages/mobile/views/mine/order/detail/purchasetrade/index.vue
  39. 14 0
      src/services/api/goods/index.ts
  40. 10 7
      src/services/subscribe/index.ts
  41. 105 15
      src/stores/modules/futures.ts
  42. 27 0
      src/types/model/market.d.ts
  43. 130 125
      src/types/model/quote.d.ts

BIN
public/html/ht_cg.docx


BIN
public/html/ht_xh_b.docx


BIN
public/html/ht_xh_s.docx


+ 6 - 0
public/manifest.json

@@ -23,6 +23,12 @@
         /*开发者邮箱地址*/
         "url" : "" /*开发者个人主页地址*/
     },
+    "app-plus" : {
+        "modules" : {
+            "Barcode" : {},
+            "Camera" : {}
+        }
+    },
     "permissions" : {
         "Accelerometer" : {
             "description" : "访问加速度感应器"

+ 23 - 25
src/business/auth/index.ts

@@ -2,7 +2,7 @@ import { ref } from 'vue'
 import { v4 } from 'uuid'
 import { timerTask } from '@/utils/timer'
 import { useStore } from '@/stores'
-import { initBaseData, checkTokenLoop } from '@/business/common'
+import { checkTokenLoop } from '@/business/common'
 import socket from '@/services/socket'
 import cryptojs from 'crypto-js'
 
@@ -74,37 +74,35 @@ function useAutoLogin() {
 }
 
 export function useAuth(autoLogin = false) {
-    const { loginStore } = useStore()
+    const { enumStore, errorInfoStore, loginStore, userStore, futuresStore, menuStore, accountStore } = useStore()
     const { getAutoLoginData, setAutoLoginData } = useAutoLogin()
     const loading = ref(false)
     const user = ref<Proto.LoginReq>(getAutoLoginData(autoLogin))
 
     // 用户登录
-    const login = () => {
-        const { LoginID, LoginPWD } = user.value
-        if (LoginID && LoginPWD) {
-            return new Promise<void>((resolve, reject) => {
-                loading.value = true
-                const catchError = (err: string) => {
-                    loading.value = false
-                    reject(err)
-                }
+    const login = async () => {
+        try {
+            loading.value = true
+            await enumStore.getAllEnumList()
+            await errorInfoStore.getErrorInfoList()
+
+            const { LoginID, LoginPWD } = user.value
+            if (LoginID && LoginPWD) {
+                await loginStore.userLogin(user.value)
+                await Promise.all([userStore.getUserData(), menuStore.getUserMenuList()])
 
-                loginStore.userLogin(user.value).then(() => {
-                    initBaseData().then(() => {
-                        setAutoLoginData(user.value)
-                        checkTokenLoop()
-                        resolve()
-                    }).catch((err) => {
-                        catchError(err)
-                    })
-                }).catch((err) => {
-                    setAutoLoginData()
-                    catchError(err)
-                })
-            })
+                futuresStore.getGoodsList()
+                accountStore.getAccountList()
+                setAutoLoginData(user.value)
+                checkTokenLoop()
+            } else {
+                throw '登录失败'
+            }
+        } catch (err) {
+            loading.value = false
+            setAutoLoginData()
+            return Promise.reject(err)
         }
-        return Promise.reject('登录失败')
     }
 
     // 用户登出

+ 1 - 1
src/business/common/index.ts

@@ -4,7 +4,7 @@ import { tokenCheck } from '@/services/api/account'
 import eventBus from '@/services/bus'
 
 /**
- * 初始化业务数据
+ * 初始化业务数据(暂无用,后期优化废除)
  */
 export async function initBaseData() {
     const { enumStore, errorInfoStore, loginStore, userStore, futuresStore, menuStore, accountStore } = useStore()

+ 15 - 1
src/business/market/index.ts

@@ -1,6 +1,8 @@
-import { shallowRef } from 'vue'
+import { shallowRef, computed } from 'vue'
 import { useDataTable } from '@/hooks/datatable'
 import { querySpotGoodsPrice, querySpotgoodsPrice } from '@/services/api/market'
+import { useFuturesStore } from '@/stores'
+import subscribe from '@/services/subscribe'
 
 // 现货行情
 export function useSpotGoodsPrice() {
@@ -58,4 +60,16 @@ export function useSpotGoodsPriceList() {
         pageCount,
         getSpotGoodsPriceList,
     }
+}
+
+// 期货行情列表
+export function useFuturesList() {
+    const { quoteList } = useFuturesStore()
+    const dataList = computed(() => quoteList.value.filter((e) => e.marketid === 99201))
+    const quoteSubscribe = subscribe.addQuoteSubscribe(dataList.value.map((e) => e.goodscode))
+
+    return {
+        dataList,
+        quoteSubscribe,
+    }
 }

+ 24 - 0
src/filters/index.ts

@@ -148,6 +148,30 @@ export function formatDate(value?: string, format = 'YYYY-MM-DD HH:mm:ss') {
 }
 
 /**
+ * 更换数字单位
+ * @param value
+ * @returns
+ */
+export function changeUnit(value: number) {
+    const k = 10000
+    const sizes = ['', '万', '亿', '万亿']
+
+    if (value > k) {
+        /**
+         * Math.floor() 不为整数数字【向下取整】
+         * Math.log() 取数字的对数 通常为Math.log(y)/Math.log(x) 取以x为底y的对数
+         * Math.pow(x,y) 取x为底数的y次幂
+         */
+        const i = Math.floor(Math.log(value) / Math.log(k))
+        const num = ((value / Math.pow(k, i)))
+        const unit = sizes[i]
+        return (Math.floor(num * 100) / 100).toString() + unit
+    } else {
+        return (Math.floor(value * 100) / 100).toString()
+    }
+}
+
+/**
  * Des密钥
  * 手机发送验证码时加密方法
  * @param mobile

Fichier diff supprimé car celui-ci est trop grand
+ 0 - 0
src/packages/mobile/assets/iconfont/iconfont.js


BIN
src/packages/mobile/assets/icons/ccwl.png


BIN
src/packages/mobile/assets/icons/cpjg.png


BIN
src/packages/mobile/assets/icons/cpjs.png


BIN
src/packages/mobile/assets/icons/futures.png


BIN
src/packages/mobile/assets/icons/home-active.png


BIN
src/packages/mobile/assets/icons/home.png


BIN
src/packages/mobile/assets/icons/htzr.png


BIN
src/packages/mobile/assets/icons/mine-active.png


BIN
src/packages/mobile/assets/icons/mine.png


BIN
src/packages/mobile/assets/icons/ptgz.png


BIN
src/packages/mobile/assets/icons/purchase-active.png


BIN
src/packages/mobile/assets/icons/purchase.png


BIN
src/packages/mobile/assets/icons/spot.png


BIN
src/packages/mobile/assets/icons/supply-demand-active.png


BIN
src/packages/mobile/assets/icons/supply-demand.png


BIN
src/packages/mobile/assets/icons/wdrw.png


+ 7 - 10
src/packages/mobile/components/layouts/page/index.less

@@ -5,12 +5,12 @@
     will-change: transform, opacity;
 }
 
-.route-in-leave-active,
+.route-in-leave-to,
 .route-in-enter-active,
-.route-out-enter-active,
-.route-out-leave-active {
+.route-out-leave-active,
+.route-out-enter-to {
     pointer-events: none;
-    transition: transform 300ms;
+    transition: transform 220ms;
 }
 
 .route-in-leave-from {
@@ -20,9 +20,7 @@
     }
 }
 
-.route-in-leave-active {
-    transition: transform 280ms;
-
+.route-in-leave-to {
     &::after {
         content: '';
         position: fixed;
@@ -33,12 +31,11 @@
         height: 100vh;
         background-color: rgba(0, 0, 0, .5);
         opacity: 1;
-        transition: opacity 300ms;
+        transition: opacity 220ms;
     }
 }
 
 .route-in-enter-from {
-    z-index: 1;
     transform: translate3d(100%, 0, 0);
 }
 
@@ -72,7 +69,7 @@
         height: 100vh;
         background-color: rgba(0, 0, 0, .5);
         opacity: 0;
-        transition: opacity 300ms;
+        transition: opacity 220ms;
     }
 }
 

+ 0 - 1
src/packages/mobile/views/bank/statement/index.vue

@@ -26,7 +26,6 @@
 
 <script lang="ts" setup>
 import { shallowRef } from 'vue'
-import { Button } from 'vant'
 import { formatDate } from '@/filters'
 import { useNavigation } from '@/hooks/navigation'
 import { getAccountBusinessCodeName } from '@/constants/bank'

+ 4 - 26
src/packages/mobile/views/boot/index.vue

@@ -19,10 +19,7 @@ import { reactive } from 'vue'
 import { useRoute, useRouter } from 'vue-router'
 import { Swipe, SwipeItem } from 'vant'
 import { showLoading } from '@/utils/vant'
-import { initBaseData } from '@/business/common'
 import { useAuth } from '@/business/auth'
-import service from '@/services'
-import socket from '@/services/socket'
 import plus from '@/utils/h5plus'
 
 const route = useRoute()
@@ -37,30 +34,9 @@ const state = reactive({
   rate: 100, // 目标进度
 })
 
-// 初始化数据
-const onLoad = (async () => {
-  // 等待服务初始化
-  await service.onReady()
-  // 等待连接交易服务
-  await socket.connectTrade()
-  // 等待业务数据初始化
-  await initBaseData()
-})()
-
 // 等待加载数据
-const autoLogin = async (loading = false) => {
+const autoLogin = (loading = false) => {
   const toast = loading ? showLoading() : undefined
-  const complete = () => {
-    toast?.close()
-    localStorage.setItem('thj_app_guide', 'false')
-    plus.exitFullSreen()
-  }
-
-  await onLoad.catch(() => {
-    complete()
-    router.replace({ name: 'UserLogin' })
-  })
-
   login().then(() => {
     const redirect = route.query.redirect
     if (redirect) {
@@ -71,7 +47,9 @@ const autoLogin = async (loading = false) => {
   }).catch(() => {
     router.replace({ name: 'UserLogin' })
   }).finally(() => {
-    complete()
+    toast?.close()
+    localStorage.setItem('thj_app_guide', 'false')
+    plus.exitFullSreen()
   })
 }
 

+ 177 - 0
src/packages/mobile/views/home/components/main/index.backup.vue

@@ -0,0 +1,177 @@
+<template>
+  <app-scroll-view class="home-main">
+    <template #afterHeader>
+      <app-navbar title="铁合金掌上行" :show-back-button="false" />
+    </template>
+    <app-statusbar class="home-main__header">
+      <div class="home-main__banner home-main__banner--header">
+        <Swipe :autoplay="5000" indicator-color="white" lazy-render>
+          <SwipeItem v-for="(item, index) in topBanners" :key="index">
+            <img :src="getImageUrl(item.imagepath)" />
+          </SwipeItem>
+        </Swipe>
+      </div>
+    </app-statusbar>
+    <PullRefresh class="home-main__container" v-model="refreshing" @refresh="onRefresh">
+      <app-block class="home-main__iconbar bg">
+        <ul>
+          <li @click="routerTo('product')">
+            <img src="@mobile/assets/icons/cpjs.png" />
+            <span>产品介绍</span>
+          </li>
+          <li @click="routerTo('Market')">
+            <img src="@mobile/assets/icons/cpjg.png" />
+            <span>产品价格</span>
+          </li>
+          <li @click="routerTo('NavigationPTGZ')">
+            <img src="@mobile/assets/icons/ptgz.png" />
+            <span>平台规则</span>
+          </li>
+        </ul>
+        <ul>
+          <li @click="routerTo('credit-signin')">
+            <img src="@mobile/assets/icons/wdrw.png" />
+            <span>我的任务</span>
+          </li>
+          <li @click="routerTo('contract')">
+            <img src="@mobile/assets/icons/htzr.png" />
+            <span>合同转让</span>
+          </li>
+          <li @click="routerTo('rules-ccwl')">
+            <img src="@mobile/assets/icons/ccwl.png" />
+            <span>仓储物流</span>
+          </li>
+        </ul>
+      </app-block>
+      <app-block class="home-main__market flex" v-if="false">
+        <div class="left">
+          <h2>合金指数</h2>
+          <span>{{ formatDate(marketRun.tradedate, "YYYY-MM-DD") }}</span>
+        </div>
+        <div class="right">
+          <Swipe :autoplay="10 * 1000" :show-indicators="false" vertical>
+            <SwipeItem v-for="(items, i) in groupList" :key="i">
+              <table cellspacing="0" cellpadding="0">
+                <tbody>
+                  <tr v-for="(item, n) in items" :key="i + n">
+                    <td>{{ item.wrstandardname }}</td>
+                    <td>{{ handleNumberValue(item.prespotgoodsprice) }}</td>
+                    <td>{{ handleNumberValue(item.todayspotgoodsprice) }}</td>
+                    <td>{{ parsePercent(item.chg) }}</td>
+                  </tr>
+                </tbody>
+              </table>
+            </SwipeItem>
+          </Swipe>
+        </div>
+      </app-block>
+      <app-block class="home-main__banner home-main__banner--body" v-if="false">
+        <Swipe :autoplay="5000" indicator-color="white" lazy-render>
+          <SwipeItem v-for="(item, index) in bodyBanners" :key="index">
+            <img :src="getImageUrl(item.imagepath)" />
+          </SwipeItem>
+        </Swipe>
+      </app-block>
+      <app-block class="home-main__news">
+        <CellGroup class="article">
+          <Cell class="titlebar" title-class="titlebar-title" value-class="titlebar-more" value="更多"
+            :to="{ name: 'news-list' }" is-link>
+            <template #title>
+              <img src="@mobile/assets/icons/fire.png" />
+              <span>市场资讯</span>
+            </template>
+          </Cell>
+          <template v-for="(item, index) in newsList" :key="index">
+            <Cell class="article-item" title-class="article-item__title" value-class="article-item__time"
+              :title="item.title" :value="formatDate(item.creaedate, 'MM/DD')" :to="{
+                name: 'news-details',
+                params: { item: JSON.stringify(item) },
+              }" />
+          </template>
+        </CellGroup>
+      </app-block>
+    </PullRefresh>
+  </app-scroll-view>
+</template>
+
+<script lang="ts" setup>
+import { shallowRef, computed } from "vue";
+import { Cell, CellGroup, Swipe, SwipeItem, PullRefresh } from "vant";
+import {
+  getImageUrl,
+  formatDate,
+  parsePercent,
+  handleNumberValue,
+} from "@/filters";
+import { useNavigation } from "@/hooks/navigation";
+import { queryImageConfigs } from "@/services/api/common";
+import { querySiteColumnDetail } from "@/services/api/news";
+import { useSpotGoodsPrice } from "@/business/market";
+import { queryMarketRun } from "@/services/api/goods";
+
+const { routerTo } = useNavigation();
+const { dataList, getSpotGoodsPrice } = useSpotGoodsPrice();
+const refreshing = shallowRef(false); // 是否处于加载中状态
+const topBanners = shallowRef<Model.ImageConfigsRsp[]>([]); // 轮播图列表
+const bodyBanners = shallowRef<Model.ImageConfigsRsp[]>([]); // 轮播图列表
+const newsList = shallowRef<Model.SiteColumnDetailRsp[]>([]); // 资讯列表
+const marketRun = shallowRef<Partial<Model.MarketRunRsp>>({}); // 市场
+
+// 合金指数组列表(4条记录为一组)
+const groupList = computed(() => {
+  const result: Model.SpotGoodsPriceRsp[][] = [];
+  for (let i = 0; i < dataList.value.length; i += 4) {
+    result.push(dataList.value.slice(i, i + 4));
+  }
+  return result;
+});
+
+// 下拉刷新
+const onRefresh = () => {
+  // 合金指数
+  getSpotGoodsPrice();
+  // 市场信息
+  queryMarketRun({
+    success: (res) => {
+      marketRun.value = res.data[0];
+    },
+  });
+  // 市场资讯
+  querySiteColumnDetail({
+    data: {
+      page: 1,
+      pagesize: 10,
+    },
+    success: (res) => {
+      newsList.value = res.data;
+    },
+    complete: () => {
+      refreshing.value = false;
+    },
+  });
+};
+
+queryImageConfigs({
+  data: {
+    imageType: 1,
+  },
+  success: (res) => {
+    topBanners.value = res.data;
+  },
+});
+
+queryImageConfigs({
+  data: {
+    imageType: 10,
+  },
+  success: (res) => {
+    bodyBanners.value = res.data;
+  },
+});
+
+onRefresh();
+</script>
+
+<style lang="less">
+@import "./index.less";
+</style>

+ 31 - 41
src/packages/mobile/views/home/components/main/index.less

@@ -65,62 +65,52 @@
                 text-align: center;
 
                 img {
-                    width: .8rem;
-                    height: .8rem;
+                    width: .76rem;
+                    height: .76rem;
                 }
 
                 span {
                     font-size: .24rem;
+                    margin-top: .04rem;
                 }
             }
         }
     }
 
     &__market {
-        .left {
-            display: flex;
-            flex-direction: column;
-            justify-content: center;
-            align-items: center;
-            padding: .24rem;
-            border-right: 1px solid #eee;
-
-            h2 {
-                font-size: .36rem;
-                color: #00577C;
-            }
+        .scrollbar {
+            width: 100%;
+            padding: .2rem;
 
-            span {
-                font-size: .24rem;
-                color: #666;
+            &-title {
+                display: flex;
+                align-items: center;
+                margin-bottom: .1rem;
+
+                img {
+                    width: .24rem;
+                    height: .24rem;
+                    margin-right: .08rem;
+                }
+
+                span {
+                    font-size: .24rem;
+                    font-weight: bold;
+                    color: #C30D23;
+                }
             }
         }
 
-        .right {
-            flex: 1;
-            padding: 0 .24rem;
-            height: 2rem;
-
-            .van-swipe {
-                height: 100%;
+        .van-swipe {
+            height: 32px;
+            background-color: #f6f6f6;
 
-                &-item {
-                    display: flex;
-                    align-items: center;
-
-                    table {
-                        width: 100%;
-                        font-size: .24rem;
-
-                        tr {
-                            td {
-                                line-height: .4rem;
-                                width: 25%;
-                                text-align: center;
-                            }
-                        }
-                    }
-                }
+            ul {
+                display: flex;
+                justify-content: space-around;
+                align-items: center;
+                height: inherit;
+                font-size: .24rem;
             }
         }
     }

+ 27 - 39
src/packages/mobile/views/home/components/main/index.vue

@@ -43,27 +43,30 @@
           </li>
         </ul>
       </app-block>
-      <app-block class="home-main__market flex" v-if="false">
-        <div class="left">
-          <h2>合金指数</h2>
-          <span>{{ formatDate(marketRun.tradedate, "YYYY-MM-DD") }}</span>
-        </div>
-        <div class="right">
-          <Swipe :autoplay="10 * 1000" :show-indicators="false" vertical>
-            <SwipeItem v-for="(items, i) in groupList" :key="i">
-              <table cellspacing="0" cellpadding="0">
-                <tbody>
-                  <tr v-for="(item, n) in items" :key="i + n">
-                    <td>{{ item.wrstandardname }}</td>
-                    <td>{{ handleNumberValue(item.prespotgoodsprice) }}</td>
-                    <td>{{ handleNumberValue(item.todayspotgoodsprice) }}</td>
-                    <td>{{ parsePercent(item.chg) }}</td>
-                  </tr>
-                </tbody>
-              </table>
+      <app-block class="home-main__market" v-if="dataList.length">
+        <section class="scrollbar">
+          <h4 class="scrollbar-title">
+            <img src="@mobile/assets/icons/futures.png" />
+            <span>期货行情</span>
+          </h4>
+          <Swipe :autoplay="8000" :show-indicators="false" :touchable="false" vertical>
+            <SwipeItem
+              v-for="({ goodsname, last, lasttime, presettle, change, amplitude, holdvolume, lastvolume, decimalplace }, i) in dataList"
+              :key="i">
+              <ul>
+                <li>{{ goodsname }}</li>
+                <li style="color:#999">{{ formatDate(lasttime, 'HH:mm') }}</li>
+                <li :class="handlePriceColor(last, presettle)">{{ handleNumberValue(formatDecimal(last, decimalplace)) }}
+                </li>
+                <li :class="handlePriceColor(last, presettle)">{{ handleNumberValue(formatDecimal(change, decimalplace))
+                }}</li>
+                <li :class="handlePriceColor(last, presettle)">{{ parsePercent(amplitude) }}</li>
+                <li :class="handlePriceColor(last, presettle)">{{ changeUnit(lastvolume) }}</li>
+                <li :class="handlePriceColor(last, presettle)">{{ changeUnit(holdvolume) }}</li>
+              </ul>
             </SwipeItem>
           </Swipe>
-        </div>
+        </section>
       </app-block>
       <app-block class="home-main__banner home-main__banner--body" v-if="false">
         <Swipe :autoplay="5000" indicator-color="white" lazy-render>
@@ -95,41 +98,25 @@
 </template>
 
 <script lang="ts" setup>
-import { shallowRef, computed } from "vue";
+import { shallowRef } from "vue";
 import { Cell, CellGroup, Swipe, SwipeItem, PullRefresh } from "vant";
-import {
-  getImageUrl,
-  formatDate,
-  parsePercent,
-  handleNumberValue,
-} from "@/filters";
+import { formatDecimal, getImageUrl, formatDate, handlePriceColor, parsePercent, handleNumberValue, changeUnit } from "@/filters";
 import { useNavigation } from "@/hooks/navigation";
 import { queryImageConfigs } from "@/services/api/common";
 import { querySiteColumnDetail } from "@/services/api/news";
-import { useSpotGoodsPrice } from "@/business/market";
+import { useFuturesList } from "@/business/market";
 import { queryMarketRun } from "@/services/api/goods";
 
 const { routerTo } = useNavigation();
-const { dataList, getSpotGoodsPrice } = useSpotGoodsPrice();
+const { dataList, quoteSubscribe } = useFuturesList();
 const refreshing = shallowRef(false); // 是否处于加载中状态
 const topBanners = shallowRef<Model.ImageConfigsRsp[]>([]); // 轮播图列表
 const bodyBanners = shallowRef<Model.ImageConfigsRsp[]>([]); // 轮播图列表
 const newsList = shallowRef<Model.SiteColumnDetailRsp[]>([]); // 资讯列表
 const marketRun = shallowRef<Partial<Model.MarketRunRsp>>({}); // 市场
 
-// 合金指数组列表(4条记录为一组)
-const groupList = computed(() => {
-  const result: Model.SpotGoodsPriceRsp[][] = [];
-  for (let i = 0; i < dataList.value.length; i += 4) {
-    result.push(dataList.value.slice(i, i + 4));
-  }
-  return result;
-});
-
 // 下拉刷新
 const onRefresh = () => {
-  // 合金指数
-  getSpotGoodsPrice();
   // 市场信息
   queryMarketRun({
     success: (res) => {
@@ -170,6 +157,7 @@ queryImageConfigs({
 });
 
 onRefresh();
+quoteSubscribe.start();
 </script>
 
 <style lang="less">

+ 10 - 7
src/packages/mobile/views/home/index.less

@@ -9,17 +9,20 @@
 
             &.is-active {
                 color: var(--tabbar-icon-active);
+
+                // .app-iconfont__icon {
+                //     animation: icon-scale 300ms;
+                // }
             }
 
-            .g-icon {
-                img {
-                    width: .56rem;
-                    height: .56rem;
+            .app-iconfont {
+                &__icon {
+                    font-size: .56rem;
                 }
-            }
 
-            span {
-                margin-top: 0 !important;
+                &__label {
+                    margin-top: .04rem;
+                }
             }
         }
     }

+ 8 - 12
src/packages/mobile/views/home/index.vue

@@ -35,30 +35,26 @@ const tabList: Tabbar[] = [
   {
     name: 'home',
     label: '首页',
-    iconType: 'image',
-    icon: require('@mobile/assets/icons/home.png'),
-    activeIcon: require('@mobile/assets/icons/home-active.png'),
+    icon: 'icon-home',
+    activeIcon: 'icon-home-active',
   },
   {
     name: 'purchase',
     label: '采购',
-    iconType: 'image',
-    icon: require('@mobile/assets/icons/purchase.png'),
-    activeIcon: require('@mobile/assets/icons/purchase-active.png'),
+    icon: 'icon-purchase',
+    activeIcon: 'icon-purchase-active',
   },
   // {
   //   name: 'supplyDemand',
   //   label: '供求',
-  //   iconType: 'image',
-  //   icon: require('@mobile/assets/icons/supply-demand.png'),
-  //   activeIcon: require('@mobile/assets/icons/supply-demand-active.png'),
+  //   icon: 'icon-supply-demand',
+  //   activeIcon: 'icon-supply-demand-active',
   // },
   {
     name: 'mine',
     label: '我的',
-    iconType: 'image',
-    icon: require('@mobile/assets/icons/mine.png'),
-    activeIcon: require('@mobile/assets/icons/mine-active.png'),
+    icon: 'icon-mine',
+    activeIcon: 'icon-mine-active',
   }
 ]
 

+ 43 - 0
src/packages/mobile/views/market/list/components/quote/index.vue

@@ -0,0 +1,43 @@
+<template>
+    <div class="market-quote">
+        <app-list :columns="columns" :data-list="dataList" v-if="dataList.length">
+            <!-- 最新价 -->
+            <template #last="{ row }">
+                <span :class="handlePriceColor(row.last, row.presettle)">{{
+                        handleNumberValue(formatDecimal(row.last, row.decimalplace))
+                }}</span>
+            </template>
+            <!-- 涨跌幅 -->
+            <template #change="{ row }">
+                <span :class="handlePriceColor(row.last, row.presettle)">{{
+                        handleNumberValue(formatDecimal(row.change, row.decimalplace))
+                }}</span>
+            </template>
+            <!-- 涨跌幅 -->
+            <template #amplitude="{ row }">
+                <span :class="handlePriceColor(row.last, row.presettle)">{{ parsePercent(row.amplitude) }}</span>
+            </template>
+        </app-list>
+        <Empty v-else />
+    </div>
+</template>
+
+<script lang="ts" setup>
+import { onMounted, onUnmounted } from 'vue'
+import { Empty } from 'vant'
+import { formatDecimal, handlePriceColor, handleNumberValue, parsePercent } from '@/filters'
+import { useFuturesList } from '@/business/market'
+import AppList from '@mobile/components/base/list/index.vue'
+
+const { dataList, quoteSubscribe } = useFuturesList()
+
+const columns: Model.TableColumn[] = [
+    { prop: 'goodsname', label: '名称' },
+    { prop: 'last', label: '最新价' },
+    { prop: 'change', label: '涨跌' },
+    { prop: 'amplitude', label: '涨跌幅' },
+]
+
+onMounted(() => quoteSubscribe.start())
+onUnmounted(() => quoteSubscribe.stop())
+</script>

+ 6 - 14
src/packages/mobile/views/market/list/components/spot/index.vue

@@ -1,31 +1,23 @@
 <template>
-    <PullRefresh v-model="refreshing" @refresh="onRefresh" style="height:100%">
+    <div class="market-spot">
         <app-list :columns="columns" :data-list="dataList" v-if="dataList.length" />
         <Empty v-else />
-    </PullRefresh>
+    </div>
 </template>
 
 <script lang="ts" setup>
-import { shallowRef } from 'vue'
-import { PullRefresh, Empty } from 'vant'
+import { Empty } from 'vant'
 import { useSpotGoodsPriceList } from '@/business/market'
 import AppList from '@mobile/components/base/list/index.vue'
 
 const { dataList, getSpotGoodsPriceList } = useSpotGoodsPriceList()
-const refreshing = shallowRef(false) // 是否处于加载中状态
 
 const columns: Model.TableColumn[] = [
     { prop: 'wrstandardname', label: '名称' },
-    { prop: 'spotgoodsprice', label: '最新价' },
+    { prop: 'spotgoodsprice', label: '招标价' },
+    { prop: 'spotgoodsqty', label: '招标量' },
     { prop: 'tradedate', label: '日期' },
 ]
 
-// 下拉刷新
-const onRefresh = () => {
-    getSpotGoodsPriceList().finally(() => {
-        refreshing.value = false
-    })
-}
-
-onRefresh()
+getSpotGoodsPriceList()
 </script>

+ 1 - 0
src/packages/mobile/views/market/list/index.less

@@ -7,6 +7,7 @@
         &__content {
             flex: 1;
             overflow-y: auto;
+            padding-top: .2rem;
         }
 
         .van-tab__panel {

+ 4 - 0
src/packages/mobile/views/market/list/index.vue

@@ -7,6 +7,9 @@
             <Tab title="现货">
                 <app-spot />
             </Tab>
+            <Tab title="郑商所">
+                <app-quote />
+            </Tab>
         </Tabs>
     </app-view>
 </template>
@@ -14,6 +17,7 @@
 <script lang="ts" setup>
 import { Tab, Tabs } from 'vant'
 import AppSpot from './components/spot/index.vue'
+import AppQuote from './components/quote/index.vue'
 </script>
 
 <style lang="less">

+ 1 - 1
src/packages/mobile/views/mine/order/detail/purchasetrade/index.vue

@@ -10,7 +10,7 @@
                 <Cell title="数量" :value="detail.tradeqty" />
                 <Cell title="预付款(含定金)" :value="handleNumberValue(detail.payeddeposit.toFixed(2))" />
                 <Cell title="付款比例" :value="parsePercent(detail.depositrate)" />
-                <Cell title="购买价" :value="handleNumberValue(detail.transferprice.toFixed(2))" />
+                <Cell title="预付金" :value="handleNumberValue(detail.transferprice.toFixed(2))" />
                 <Cell title="实际价" :value="handleNumberValue(detail.lastprice.toFixed(2))" />
                 <Cell title="尾款" :value="handleNumberValue(detail.remainamount.toFixed(2))" />
                 <Cell title="状态" :value="detail.thjorderstatusdisplay" />

+ 14 - 0
src/services/api/goods/index.ts

@@ -9,6 +9,20 @@ export function queryGoodsList(params: HttpParams<{ rsp: Model.GoodsRsp[] }>) {
 }
 
 /**
+ * 查询企业风管期货商品信息
+ */
+export function queryErmcpGoods(params: HttpParams<{ req: Model.GoodsReq, rsp: Model.GoodsRsp[] }>) {
+    return httpRequest('/Ermcp/GetErmcpGoods', 'get', params);
+}
+
+/**
+ * 获取商品盘面信息
+ */
+export function queryQuoteDay(params: HttpParams<{ req: Model.QuoteDayReq, rsp: Model.QuoteDayRsp[] }>) {
+    return httpRequest('/Quote/QueryQuoteDay', 'get', params);
+}
+
+/**
  * 查询采购列表
  */
 export function queryTHJWrstandard(params: HttpParams<{ req: Model.THJWrstandardReq, rsp: Model.THJWrstandardRsp[] }>) {

+ 10 - 7
src/services/subscribe/index.ts

@@ -24,13 +24,16 @@ export default new (class {
     private quoteSubscribe = () => {
         const subscribeData: Proto.QuoteReq[] = []
 
-        this.quoteSubscribeMap.forEach((value) => {
-            const item = value.map((code) => ({
-                goodsCode: code,
-                exchangeCode: 250,
-                subState: 0
-            }))
-            subscribeData.push(...item)
+        this.quoteSubscribeMap.forEach((values) => {
+            values.forEach((code) => {
+                if (!subscribeData.some((e) => e.goodsCode === code)) {
+                    subscribeData.push({
+                        goodsCode: code,
+                        exchangeCode: 250,
+                        subState: 0
+                    })
+                }
+            })
         })
 
         if (subscribeData.length) {

+ 105 - 15
src/stores/modules/futures.ts

@@ -1,21 +1,21 @@
 import { computed, toRefs, shallowReadonly } from 'vue'
 import { timerInterceptor } from '@/utils/timer'
-import { queryGoodsList } from '@/services/api/goods'
-import { useLoginStore } from './login'
+import { queryErmcpGoods, queryQuoteDay } from '@/services/api/goods'
 import { VueStore } from '../base'
+import { timerTask } from '@/utils/timer'
 import eventBus from '@/services/bus'
 import moment from 'moment'
 
 interface StoreState {
     loading: boolean;
     goodsList: Model.GoodsRsp[]; // 商品列表
-    quoteDayList: Model.QuoteDay[]; // 盘面列表
+    quoteDayList: Model.QuoteDayRsp[]; // 盘面列表
 }
 
 /**
  * 期货存储类
  */
-const store = new (class extends VueStore<StoreState> {
+const store = new (class extends VueStore<StoreState>{
     constructor() {
         const state: StoreState = {
             loading: false,
@@ -39,24 +39,93 @@ const store = new (class extends VueStore<StoreState> {
         })
     }
 
-    private quotes: Proto.Quote[] = [] // 行情数据
+    /** 行情数据 */
+    private quotes: Proto.Quote[] = []
 
-    /** 处理行情数据 */
+    /** 期货行情列表 */
+    private quoteList = computed(() => {
+        return this.state.goodsList.reduce((res, cur) => {
+            const { goodscode, goodsname, goodsgroupid, marketid, decimalplace } = cur
+            const {
+                last = 0,
+                bid = 0,
+                ask = 0,
+                bidvolume = 0,
+                askvolume = 0,
+                totalvolume = 0,
+                lastvolume = 0,
+                holdvolume = 0,
+                holdincrement = 0,
+                presettle = 0,
+                totalturnover = 0,
+                opened = 0,
+                highest = 0,
+                lowest = 0,
+                lasttime = '',
+            } = this.actions.getQuoteDayInfoByCode(goodscode).value ?? {}
+
+            const change = last - presettle // 涨跌额/涨跌: 最新价 - 昨结价
+
+            const item: Model.Futures = {
+                marketid,
+                goodsgroupid,
+                goodscode,
+                goodsname,
+                decimalplace,
+                last,
+                lasttime,
+                amplitude: change ? change / presettle : 0, // 涨跌幅/幅度: (最新价 - 昨结价) / 昨结价
+                change,
+                bid,
+                ask,
+                bidvolume,
+                askvolume,
+                totalvolume,
+                lastvolume,
+                holdvolume,
+                holdincrement,
+                presettle,
+                totalturnover,
+                opened,
+                highest,
+                lowest,
+            }
+            res.push(item)
+            return res
+        }, [] as Model.Futures[])
+    })
+
+    /**
+     * 处理行情数据
+     */
     private handleQuote = timerInterceptor.setThrottle(() => {
+        const goodsList = this.state.goodsList
         const quoteList = this.state.quoteDayList
+
         this.quotes.forEach((item) => {
+            const goods = goodsList.find((e) => e.goodscode.toUpperCase() === item.goodscode?.toUpperCase())
             const quote = quoteList.find((e) => e.goodscode.toUpperCase() === item.goodscode?.toUpperCase())
-            const last = item.last ?? 0
             const lasttime = (item.date && item.time) ? moment(item.date + item.time, 'YYYYMMDDHHmmss').format('YYYY-MM-DD HH:mm:ss') : ''
 
+            // 处理报价小数位
+            const last = (() => {
+                const decimal = goods?.decimalplace ?? 0
+                const num = Math.pow(10, decimal)
+                if (item.last) {
+                    return item.last / num
+                }
+                return 0
+            })()
+
             if (quote) {
                 Object.entries(item).forEach(([key, value]) => {
                     // 只更新存在的属性
                     if (Reflect.has(quote, key)) {
-                        const prop = key as keyof Model.QuoteDay;
+                        const prop = key as keyof Model.QuoteDayRsp;
                         (<K extends typeof prop>(key: K) => quote[key] = value)(prop);
                     }
                 })
+                quote.last = last
                 // 处理最高最低价
                 if (last) {
                     if (last > quote.highest) {
@@ -73,7 +142,6 @@ const store = new (class extends VueStore<StoreState> {
             } else {
                 console.warn('行情推送的商品 ' + item.goodscode + ' 缺少盘面信息')
                 quoteList.push({
-                    Lastturnover: 0,
                     ask: item.ask ?? 0,
                     ask2: item.ask2 ?? 0,
                     ask3: item.ask3 ?? 0,
@@ -168,6 +236,7 @@ const store = new (class extends VueStore<StoreState> {
                     last,
                     lastlot: 0,
                     lasttime,
+                    Lastturnover: 0,
                     lastvolume: item.lastvolume ?? 0,
                     limitdown: item.limitlow ?? 0,
                     limitup: item.limithigh ?? 0,
@@ -201,18 +270,38 @@ const store = new (class extends VueStore<StoreState> {
         })
     }, 200)
 
+    getters = {
+        quoteList: this.quoteList
+    }
+
     actions = {
         // 获取商品列表
         getGoodsList: () => {
-            const { getUserId } = useLoginStore()
             this.state.loading = true
-
-            return queryGoodsList({
-                data: {
-                    userid: getUserId()
-                },
+            return queryErmcpGoods({
                 success: (res) => {
+                    const codes = res.data.map((e) => e.goodscode)
                     this.state.goodsList = res.data
+
+                    // 获取商品盘面信息
+                    const getQuoteDay = () => {
+                        return queryQuoteDay({
+                            data: {
+                                goodsCodes: codes.join(',')
+                            },
+                            success: (res) => {
+                                this.state.quoteDayList = res.data
+                            },
+                            complete: () => {
+                                // 每5分钟获取一次盘面
+                                timerTask.setTimeout(() => getQuoteDay(), 5 * 60 * 1000, 'quoteDay')
+                            }
+                        })
+                    }
+
+                    if (codes.length) {
+                        getQuoteDay()
+                    }
                 },
                 complete: () => {
                     this.state.loading = false
@@ -236,6 +325,7 @@ const store = new (class extends VueStore<StoreState> {
 export function useFuturesStore() {
     return shallowReadonly({
         ...toRefs(store.state),
+        ...store.getters,
         ...store.actions,
         ...store.methods,
     })

+ 27 - 0
src/types/model/market.d.ts

@@ -9,9 +9,36 @@ declare namespace Model {
     interface SpotgoodsPriceRsp {
         prespotgoodsprice: number; // 上日价格
         spotgoodsprice: number; // 当前价格
+        spotgoodsqty: number; // 招标量
         tradedate: string; // 交易日(yyyyMMdd)
         wrstandardcode: string; // 现货商品代码
         wrstandardid: number; // 现货商品ID(通用则为0)
         wrstandardname: string; // 现货商品名称
     }
+
+    /** 期货行情 */
+    interface Futures {
+        marketid: number; // 所属市场ID
+        goodsgroupid: number; // 所属商品组ID
+        goodscode: string; // 商品代码
+        goodsname: string; // 商品名称
+        decimalplace: number;//报价小数位
+        last: number; // 最新价
+        lasttime: string; // 行情时间(只有现价变化行情时间才变化)
+        amplitude: number; // 涨跌幅
+        change: number; // 涨跌
+        bid: number; // 买价
+        ask: number; // 卖价
+        bidvolume: number; // 买量
+        askvolume: number; // 卖量
+        totalvolume: number; // 总量
+        lastvolume: number; // 现量
+        holdvolume: number; // 持仓量
+        holdincrement: number; // 日增
+        presettle: number; // 昨结价
+        totalturnover: number; // 金额
+        opened: number; // 开盘
+        highest: number; // 最高
+        lowest: number; // 最低
+    }
 }

+ 130 - 125
src/types/model/quote.d.ts

@@ -1,129 +1,134 @@
 declare namespace Model {
-    /** 商品盘面 */
-    interface QuoteDay {
-        Lastturnover: number;
-        ask: number;
-        ask2: number;
-        ask3: number;
-        ask4: number;
-        ask5: number;
-        ask6: number;
-        ask7: number;
-        ask8: number;
-        ask9: number;
-        ask10: number;
-        askorderid: number;
-        askorderid2: number;
-        askorderid3: number;
-        askorderid4: number;
-        askorderid5: number;
-        askordervolume: number;
-        askordervolume2: number;
-        askordervolume3: number;
-        askordervolume4: number;
-        askordervolume5: number;
-        askordervolume6: number;
-        askordervolume7: number;
-        askordervolume8: number;
-        askordervolume9: number;
-        askordervolume10: number;
-        askqueueinfo: string;
-        askvolume: number;
-        askvolume2: number;
-        askvolume3: number;
-        askvolume4: number;
-        askvolume5: number;
-        askvolume6: number;
-        askvolume7: number;
-        askvolume8: number;
-        askvolume9: number;
-        askvolume10: number;
-        averageprice: number;
-        bid: number;
-        bid2: number;
-        bid3: number;
-        bid4: number;
-        bid5: number;
-        bid6: number;
-        bid7: number;
-        bid8: number;
-        bid9: number;
-        bid10: number;
-        bidorderid: number;
-        bidorderid2: number;
-        bidorderid3: number;
-        bidorderid4: number;
-        bidorderid5: number;
-        bidordervolume: number;
-        bidordervolume2: number;
-        bidordervolume3: number;
-        bidordervolume4: number;
-        bidordervolume5: number;
-        bidordervolume6: number;
-        bidordervolume7: number;
-        bidordervolume8: number;
-        bidordervolume9: number;
-        bidordervolume10: number;
-        bidqueueinfo: string;
-        bidvolume: number;
-        bidvolume2: number;
-        bidvolume3: number;
-        bidvolume4: number;
-        bidvolume5: number;
-        bidvolume6: number;
-        bidvolume7: number;
-        bidvolume8: number;
-        bidvolume9: number;
-        bidvolume10: number;
-        calloptionpremiums: number;
-        calloptionpremiums2: number;
-        calloptionpremiums3: number;
-        calloptionpremiums4: number;
-        calloptionpremiums5: number;
-        cleartime: number;
-        exchangecode: number;
-        exchangedate: number;
-        goodscode: string;
-        grepmarketprice: number;
-        highest: number;
-        holdincrement: number;
-        holdvolume: number;
-        iep: number;
-        iev: number;
-        inventory: number;
-        iscleared: number;
-        issettled: number;
-        last: number;
-        lastlot: number;
-        lasttime: string;
-        lastvolume: number;
-        limitdown: number;
-        limitup: number;
-        lowest: number;
-        nontotalholdervolume: number;
-        nontotallot: number;
-        nontotalturnover: number;
-        nontotalvolume: number;
-        opened: number;
-        opentime: string;
-        orderid: number;
-        preclose: number;
-        preholdvolume: number;
-        presettle: number;
-        publictradetype: string;
-        putoptionpremiums: number;
-        putoptionpremiums2: number;
-        putoptionpremiums3: number;
-        putoptionpremiums4: number;
-        putoptionpremiums5: number;
-        settle: number;
-        strikeprice: number;
-        totalaskvolume: number;
-        totalbidvolume: number;
-        totallot: number;
-        totalturnover: number;
-        totalvolume: number;
-        utclasttime: string;
+    /** 获取商品盘面信息 请求 */
+    interface QuoteDayReq {
+        goodsCodes: string; // 此参数不填则查所有;商品代码列表,格式:CU2102,CU2103,AL2107
+    }
+
+    /** 获取商品盘面信息 响应 */
+    interface QuoteDayRsp {
+        ask: number; // 卖1
+        ask10: number; // 卖10
+        ask2: number; // 卖2
+        ask3: number; // 卖3
+        ask4: number; // 卖4
+        ask5: number; // 卖5
+        ask6: number; // 卖6
+        ask7: number; // 卖7
+        ask8: number; // 卖8
+        ask9: number; // 卖9
+        askorderid: number; // 卖单号1
+        askorderid2: number; // 卖单号2
+        askorderid3: number; // 卖单号3
+        askorderid4: number; // 卖单号4
+        askorderid5: number; // 卖单号5
+        askordervolume: number; // 卖单量1
+        askordervolume10: number; // 卖单量10
+        askordervolume2: number; // 卖单量2
+        askordervolume3: number; // 卖单量3
+        askordervolume4: number; // 卖单量4
+        askordervolume5: number; // 卖单量5
+        askordervolume6: number; // 卖单量6
+        askordervolume7: number; // 卖单量7
+        askordervolume8: number; // 卖单量8
+        askordervolume9: number; // 卖单量9
+        askqueueinfo: string; // 大利市卖港股用
+        askvolume: number; // 卖量1
+        askvolume10: number; // 卖量10
+        askvolume2: number; // 卖量2
+        askvolume3: number; // 卖量3
+        askvolume4: number; // 卖量4
+        askvolume5: number; // 卖量5
+        askvolume6: number; // 卖量6
+        askvolume7: number; // 卖量
+        askvolume8: number; // 卖量8
+        askvolume9: number; // 卖量9
+        averageprice: number; // 均价
+        bid: number; // 买1
+        bid10: number; // 买10
+        bid2: number; // 买2
+        bid3: number; // 买3
+        bid4: number; // 买4
+        bid5: number; // 买5
+        bid6: number; // 买6
+        bid7: number; // 买7
+        bid8: number; // 买8
+        bid9: number; // 买9
+        bidorderid: number; // 买单号1
+        bidorderid2: number; // 买单号2
+        bidorderid3: number; // 买单号3
+        bidorderid4: number; // 买单号4
+        bidorderid5: number; // 买单号5
+        bidordervolume: number; // 买单量1
+        bidordervolume10: number; // 买单量10
+        bidordervolume2: number; // 买单量2
+        bidordervolume3: number; // 买单量3
+        bidordervolume4: number; // 买单量4
+        bidordervolume5: number; // 买单量5
+        bidordervolume6: number; // 买单量6
+        bidordervolume7: number; // 买单量7
+        bidordervolume8: number; // 买单量8
+        bidordervolume9: number; // 买单量9
+        bidqueueinfo: string; // 大利市买港股用
+        bidvolume: number; // 买量1
+        bidvolume10: number; // 买量10
+        bidvolume2: number; // 买量2
+        bidvolume3: number; // 买量3
+        bidvolume4: number; // 买量4
+        bidvolume5: number; // 买量5
+        bidvolume6: number; // 买量6
+        bidvolume7: number; // 买量7
+        bidvolume8: number; // 买量8
+        bidvolume9: number; // 买量9
+        calloptionpremiums: number; // 认购期权1
+        calloptionpremiums2: number; // 认购期权2
+        calloptionpremiums3: number; // 认购期权3
+        calloptionpremiums4: number; // 认购期权4
+        calloptionpremiums5: number; // 认购期权5
+        cleartime: number; // 清盘时间
+        exchangecode: number; // 交易所代码
+        exchangedate: number; // 交易日
+        goodscode: string; // 商品代码
+        grepmarketprice: number; // 暗盘价 港股专用
+        highest: number; // 最高价
+        holdincrement: number; // 单笔持仓
+        holdvolume: number; // 持仓
+        iep: number; // 平衡价 港股专用
+        iev: number; // 平衡量 港股专用
+        inventory: number; // 库存
+        iscleared: number; // 是否清盘标志
+        issettled: number; // 是否结算标志
+        last: number; // 最新价
+        lastlot: number; // 最新成交手数
+        lasttime: string; // 行情时间(只有现价变化行情时间才变化)
+        Lastturnover: number; // 最新成交金额
+        lastvolume: number; // 最新成交量
+        limitdown: number; // 跌停价
+        limitup: number; // 涨停价
+        lowest: number; // 最低价
+        nontotalholdervolume: number; // 非交易持仓量
+        nontotallot: number; // 非交易总手数
+        nontotalturnover: number; // 非交易总金额
+        nontotalvolume: number; // 非交易总量
+        opened: number; // 开盘价
+        opentime: string; // 开盘时间
+        orderid: number; // 序号
+        preclose: number; // 昨收
+        preholdvolume: number; // 昨持仓
+        presettle: number; // 昨结价
+        publictradetype: string; // 公共交易标志类型 港股专用
+        putoptionpremiums: number; // 认沽期权1
+        putoptionpremiums2: number; // 认沽期权2
+        putoptionpremiums3: number; // 认沽期权3
+        putoptionpremiums4: number; // 认沽期权4
+        putoptionpremiums5: number; // 认沽期权5
+        settle: number; // 结算价
+        strikeprice: number; // 发行价
+        totalaskvolume: number; // 内盘
+        totalbidvolume: number; // 外盘
+        totallot: number; // 总手数
+        totalturnover: number; // 总金额
+        totalvolume: number; // 总量
+        utclasttime: string; // utc的行情时间
     }
 
     /** K线历史数据 */

Certains fichiers n'ont pas été affichés car il y a eu trop de fichiers modifiés dans ce diff