li.shaoyi hace 2 años
padre
commit
4328bd77a3
Se han modificado 33 ficheros con 689 adiciones y 495 borrados
  1. 0 5
      oem/gstj/config/appconfig.j2
  2. 0 5
      oem/qxst/config/appconfig.j2
  3. 0 5
      oem/sbyj/config/appconfig.j2
  4. 0 5
      oem/zrwyt/config/appconfig.j2
  5. 32 70
      src/packages/gstj/views/goods/list/Index.vue
  6. 32 70
      src/packages/mobile/views/goods/list/Index.vue
  7. 74 27
      src/packages/mobile/views/transfer/list/Index.vue
  8. 6 2
      src/packages/pc/components/base/table-filter/index.less
  9. 1 1
      src/packages/pc/components/base/table-filter/index.vue
  10. 4 0
      src/packages/pc/components/layouts/footer/index.less
  11. 9 4
      src/packages/pc/components/layouts/footer/index.vue
  12. 1 1
      src/packages/pc/components/modules/goods-detail/chart/index.less
  13. 1 1
      src/packages/pc/components/modules/goods-detail/chart/index.vue
  14. 10 10
      src/packages/pc/components/modules/goods-detail/index.vue
  15. 1 1
      src/packages/pc/components/modules/goods-detail/order/delisting/index.vue
  16. 1 1
      src/packages/pc/components/modules/goods-detail/order/index.less
  17. 2 2
      src/packages/pc/components/modules/goods-detail/order/index.vue
  18. 0 30
      src/packages/pc/components/modules/trade/index.vue
  19. 7 1
      src/packages/pc/views/market/trade/goods/index.vue
  20. 57 74
      src/packages/pc/views/market/trade/goods/list/index.vue
  21. 1 1
      src/packages/pc/views/market/trade/goods/list/listing/index.less
  22. 23 25
      src/packages/pc/views/market/trade/goods/list/listing/index.vue
  23. 0 5
      src/packages/pc/views/market/trade/presell/ballot/detail/index.vue
  24. 28 8
      src/packages/pc/views/market/trade/presell/ballot/index.vue
  25. 57 69
      src/packages/pc/views/market/trade/presell/transfer/index.vue
  26. 46 0
      src/packages/pc/views/market/trade/presell/transfer/listing/index.less
  27. 213 0
      src/packages/pc/views/market/trade/presell/transfer/listing/index.vue
  28. 3 0
      src/packages/qxst/router/index.ts
  29. 42 66
      src/packages/qxst/views/goods/list/Index.vue
  30. 4 4
      src/services/websocket/quote.ts
  31. 30 1
      src/stores/modules/futures.ts
  32. 2 1
      src/stores/modules/global.ts
  33. 2 0
      src/stores/modules/goods.ts

+ 0 - 5
oem/gstj/config/appconfig.j2

@@ -1,5 +0,0 @@
-{
-  "version": "1.0.0",
-  "versionCode": "100000",
-  "apiUrl": "{apiUrl}"
-}

+ 0 - 5
oem/qxst/config/appconfig.j2

@@ -1,5 +0,0 @@
-{
-  "version": "1.0.0",
-  "versionCode": "100000",
-  "apiUrl": "{apiUrl}"
-}

+ 0 - 5
oem/sbyj/config/appconfig.j2

@@ -1,5 +0,0 @@
-{
-  "version": "1.0.0",
-  "versionCode": "100000",
-  "apiUrl": "{apiUrl}"
-}

+ 0 - 5
oem/zrwyt/config/appconfig.j2

@@ -1,5 +0,0 @@
-{
-  "version": "1.0.0",
-  "versionCode": "100000",
-  "apiUrl": "{apiUrl}"
-}

+ 32 - 70
src/packages/gstj/views/goods/list/Index.vue

@@ -3,7 +3,7 @@
         <template #header>
             <app-navbar title="订单挂牌" :show-back-button="false" />
         </template>
-        <app-list :columns="columns" :data-list="tableList" @row-click="rowClick">
+        <app-list :columns="columns" :data-list="futuresStore.marketGoodsList" @row-click="rowClick">
             <!-- 商品名称/代码 -->
             <template #goodsname="{ row }">
                 <span>{{ row.goodsname }}</span>
@@ -11,63 +11,65 @@
             </template>
             <!-- 买价 -->
             <template #bid="{ row }">
-                <span :class="row.bidColor">{{ row.bid }}</span>
+                <span :class="row.bidColor">{{ handleNumberValue(formatDecimal(row.bid, row.decimalplace)) }}</span>
             </template>
             <!-- 买量 -->
             <template #bidvolume="{ row }">
-                <span :class="row.bidvolumeColor">{{ row.bidvolume }}</span>
+                <span :class="row.bidvolumeColor">{{ handleNumberValue(row.bidvolume) }}</span>
             </template>
             <!-- 卖价 -->
             <template #ask="{ row }">
-                <span :class="row.askColor">{{ row.ask }}</span>
+                <span :class="row.askColor">{{ handleNumberValue(formatDecimal(row.ask, row.decimalplace)) }}</span>
             </template>
             <!-- 卖量 -->
             <template #askvolume="{ row }">
-                <span :class="row.askvolumeColor">{{ row.askvolume }}</span>
+                <span :class="row.askvolumeColor">{{ handleNumberValue(row.askvolume) }}</span>
             </template>
             <!-- 当前价 -->
             <template #last="{ row }">
-                <span :class="row.lastColor">{{ row.last }}</span>
+                <span :class="row.lastColor">{{ handleNumberValue(formatDecimal(row.last, row.decimalplace)) }}</span>
             </template>
             <!-- 涨跌 -->
             <template #rise="{ row }">
-                <span :class="row.lastColor">{{ row.rise }}</span>
+                <span :class="row.lastColor">{{ formatDecimal(row.rise, row.decimalplace) }}</span>
             </template>
-            <!-- 幅 -->
+            <!-- 涨跌幅 -->
             <template #change="{ row }">
-                <span :class="row.lastColor">{{ row.change }}</span>
+                <span :class="row.lastColor">{{ parsePercent(row.change) }}</span>
             </template>
             <!-- 今开 -->
             <template #opened="{ row }">
-                <span :class="row.openedColor">{{ row.opened }}</span>
+                <span :class="row.openedColor">{{ handleNumberValue(formatDecimal(row.opened, row.decimalplace)) }}</span>
             </template>
             <!-- 最低 -->
             <template #lowest="{ row }">
-                <span :class="row.lowestColor">{{ row.lowest }}</span>
+                <span :class="row.lowestColor">{{ handleNumberValue(formatDecimal(row.lowest, row.decimalplace)) }}</span>
             </template>
             <!-- 最高 -->
             <template #highest="{ row }">
-                <span :class="row.highestColor">{{ row.highest }}</span>
+                <span :class="row.highestColor">{{ handleNumberValue(formatDecimal(row.highest, row.decimalplace)) }}</span>
+            </template>
+            <!-- 振幅 -->
+            <template #amplitude="{ value }">
+                <span>{{ parsePercent(value) }}</span>
             </template>
             <!-- 涨停 -->
             <template #limitup="{ value }">
-                <span class="g-price-up">{{ value }}</span>
+                <span class="g-price-up">{{ handleNumberValue(value) }}</span>
             </template>
             <!-- 跌停 -->
             <template #limitdown="{ value }">
-                <span class="g-price-down">{{ value }}</span>
+                <span class="g-price-down">{{ handleNumberValue(value) }}</span>
             </template>
         </app-list>
     </app-view>
 </template>
 
 <script lang="ts" setup>
-import { computed, onUnmounted, watch } from 'vue'
-import { parsePercent, handleNumberValue } from '@/filters'
-import { useRequest } from '@/hooks/request'
+import { onUnmounted, onActivated, watch } from 'vue'
+import { parsePercent, handleNumberValue, formatDecimal } from '@/filters'
 import { useNavigation } from '../../../router/navigation'
-import { queryQuoteGoodsList } from '@/services/api/swap'
-import { useFuturesStore, useUserStore } from '@/stores'
+import { useFuturesStore } from '@/stores'
 import quoteSocket from '@/services/websocket/quote'
 import AppList from '../../../components/base/list/index.vue'
 
@@ -79,53 +81,8 @@ const props = defineProps({
 })
 
 const { router } = useNavigation()
-const futuresStore = useFuturesStore()
-const userStore = useUserStore()
 const subscribe = quoteSocket.createSubscribe()
-
-const { dataList, run } = useRequest(queryQuoteGoodsList, {
-    params: {
-        usertype: userStore.userType ?? 0,
-        marketids: props.marketId.toString()
-    },
-    onSuccess: (res) => {
-        const goodsCodes = res.data.map((e) => e.goodscode)
-        if (goodsCodes.length) {
-            subscribe.start(...goodsCodes)
-        }
-    }
-})
-
-const tableList = computed(() => {
-    return dataList.value.map((item) => {
-        const quote = futuresStore.getGoodsQuote(item.goodscode)
-        const { goodsname, bid, bidColor, bidvolume, ask, askColor, askvolume, limitdown, limitup, lastColor, openedColor, lowestColor, highestColor, last, presettle, rise, change, amplitude, highest, lowest, opened } = quote.value ?? {}
-        return {
-            ...item,
-            goodsname,
-            lastColor,
-            openedColor,
-            lowestColor,
-            highestColor,
-            askColor,
-            bidColor,
-            bid: handleNumberValue(bid),
-            bidvolume: handleNumberValue(bidvolume),
-            ask: handleNumberValue(ask),
-            askvolume: handleNumberValue(askvolume),
-            last: handleNumberValue(last),
-            rise: rise?.toFixed(item.decimalplace),
-            change: parsePercent(change),
-            opened: handleNumberValue(opened),
-            presettle: handleNumberValue(presettle),
-            lowest: handleNumberValue(lowest),
-            highest: handleNumberValue(highest),
-            amplitude: parsePercent(amplitude),
-            limitdown: handleNumberValue(limitdown),
-            limitup: handleNumberValue(limitup),
-        }
-    })
-})
+const futuresStore = useFuturesStore()
 
 const columns: Model.TableColumn[] = [
     { prop: 'goodsname', label: '商品名称/代码' },
@@ -141,8 +98,8 @@ const columns: Model.TableColumn[] = [
     { prop: 'lowest', label: '最低' },
     { prop: 'highest', label: '最高' },
     { prop: 'amplitude', label: '振幅' },
-    { prop: 'limitup', label: '涨停' },
-    { prop: 'limitdown', label: '跌停' },
+    { prop: 'limitup', label: '涨停' },
+    { prop: 'limitdown', label: '跌停' },
 ]
 
 const rowClick = (row: Model.QuoteGoodsListRsp) => {
@@ -154,12 +111,17 @@ const rowClick = (row: Model.QuoteGoodsListRsp) => {
     })
 }
 
+const getMarketGoodsList = () => {
+    futuresStore.setMarketId(props.marketId)
+    const goodsCodes = futuresStore.marketGoodsList.map((e) => e.goodscode)
+    subscribe.start(...goodsCodes)
+}
+
 watch(() => props.marketId, () => {
     subscribe.stop()
-    run({
-        marketids: props.marketId.toString()
-    })
+    getMarketGoodsList()
 })
 
+onActivated(() => getMarketGoodsList())
 onUnmounted(() => subscribe.stop())
 </script>

+ 32 - 70
src/packages/mobile/views/goods/list/Index.vue

@@ -3,7 +3,7 @@
         <template #header>
             <app-navbar title="订单挂牌" :show-back-button="marketId === 50102" />
         </template>
-        <app-list :columns="columns" :data-list="tableList" @row-click="rowClick">
+        <app-list :columns="columns" :data-list="futuresStore.marketGoodsList" @row-click="rowClick">
             <!-- 商品名称/代码 -->
             <template #goodsname="{ row }">
                 <span>{{ row.goodsname }}</span>
@@ -11,63 +11,65 @@
             </template>
             <!-- 买价 -->
             <template #bid="{ row }">
-                <span :class="row.bidColor">{{ row.bid }}</span>
+                <span :class="row.bidColor">{{ handleNumberValue(formatDecimal(row.bid, row.decimalplace)) }}</span>
             </template>
             <!-- 买量 -->
             <template #bidvolume="{ row }">
-                <span :class="row.bidvolumeColor">{{ row.bidvolume }}</span>
+                <span :class="row.bidvolumeColor">{{ handleNumberValue(row.bidvolume) }}</span>
             </template>
             <!-- 卖价 -->
             <template #ask="{ row }">
-                <span :class="row.askColor">{{ row.ask }}</span>
+                <span :class="row.askColor">{{ handleNumberValue(formatDecimal(row.ask, row.decimalplace)) }}</span>
             </template>
             <!-- 卖量 -->
             <template #askvolume="{ row }">
-                <span :class="row.askvolumeColor">{{ row.askvolume }}</span>
+                <span :class="row.askvolumeColor">{{ handleNumberValue(row.askvolume) }}</span>
             </template>
             <!-- 当前价 -->
             <template #last="{ row }">
-                <span :class="row.lastColor">{{ row.last }}</span>
+                <span :class="row.lastColor">{{ handleNumberValue(formatDecimal(row.last, row.decimalplace)) }}</span>
             </template>
             <!-- 涨跌 -->
             <template #rise="{ row }">
-                <span :class="row.lastColor">{{ row.rise }}</span>
+                <span :class="row.lastColor">{{ formatDecimal(row.rise, row.decimalplace) }}</span>
             </template>
-            <!-- 幅 -->
+            <!-- 涨跌幅 -->
             <template #change="{ row }">
-                <span :class="row.lastColor">{{ row.change }}</span>
+                <span :class="row.lastColor">{{ parsePercent(row.change) }}</span>
             </template>
             <!-- 今开 -->
             <template #opened="{ row }">
-                <span :class="row.openedColor">{{ row.opened }}</span>
+                <span :class="row.openedColor">{{ handleNumberValue(formatDecimal(row.opened, row.decimalplace)) }}</span>
             </template>
             <!-- 最低 -->
             <template #lowest="{ row }">
-                <span :class="row.lowestColor">{{ row.lowest }}</span>
+                <span :class="row.lowestColor">{{ handleNumberValue(formatDecimal(row.lowest, row.decimalplace)) }}</span>
             </template>
             <!-- 最高 -->
             <template #highest="{ row }">
-                <span :class="row.highestColor">{{ row.highest }}</span>
+                <span :class="row.highestColor">{{ handleNumberValue(formatDecimal(row.highest, row.decimalplace)) }}</span>
+            </template>
+            <!-- 振幅 -->
+            <template #amplitude="{ value }">
+                <span>{{ parsePercent(value) }}</span>
             </template>
             <!-- 涨停 -->
             <template #limitup="{ value }">
-                <span class="g-price-up">{{ value }}</span>
+                <span class="g-price-up">{{ handleNumberValue(value) }}</span>
             </template>
             <!-- 跌停 -->
             <template #limitdown="{ value }">
-                <span class="g-price-down">{{ value }}</span>
+                <span class="g-price-down">{{ handleNumberValue(value) }}</span>
             </template>
         </app-list>
     </app-view>
 </template>
 
 <script lang="ts" setup>
-import { computed, onUnmounted, watch } from 'vue'
-import { parsePercent, handleNumberValue } from '@/filters'
-import { useRequest } from '@/hooks/request'
+import { onUnmounted, onActivated, watch } from 'vue'
+import { parsePercent, handleNumberValue, formatDecimal } from '@/filters'
 import { useNavigation } from '../../../router/navigation'
-import { queryQuoteGoodsList } from '@/services/api/swap'
-import { useFuturesStore, useUserStore } from '@/stores'
+import { useFuturesStore } from '@/stores'
 import quoteSocket from '@/services/websocket/quote'
 import AppList from '../../../components/base/list/index.vue'
 
@@ -79,53 +81,8 @@ const props = defineProps({
 })
 
 const { router } = useNavigation()
-const futuresStore = useFuturesStore()
-const userStore = useUserStore()
 const subscribe = quoteSocket.createSubscribe()
-
-const { dataList, run } = useRequest(queryQuoteGoodsList, {
-    params: {
-        usertype: userStore.userType ?? 0,
-        marketids: props.marketId.toString()
-    },
-    onSuccess: (res) => {
-        const goodsCodes = res.data.map((e) => e.goodscode)
-        if (goodsCodes.length) {
-            subscribe.start(...goodsCodes)
-        }
-    }
-})
-
-const tableList = computed(() => {
-    return dataList.value.map((item) => {
-        const quote = futuresStore.getGoodsQuote(item.goodscode)
-        const { goodsname, bid, bidColor, bidvolume, ask, askColor, askvolume, limitdown, limitup, lastColor, openedColor, lowestColor, highestColor, last, presettle, rise, change, amplitude, highest, lowest, opened } = quote.value ?? {}
-        return {
-            ...item,
-            goodsname,
-            lastColor,
-            openedColor,
-            lowestColor,
-            highestColor,
-            askColor,
-            bidColor,
-            bid: handleNumberValue(bid),
-            bidvolume: handleNumberValue(bidvolume),
-            ask: handleNumberValue(ask),
-            askvolume: handleNumberValue(askvolume),
-            last: handleNumberValue(last),
-            rise: rise?.toFixed(item.decimalplace),
-            change: parsePercent(change),
-            opened: handleNumberValue(opened),
-            presettle: handleNumberValue(presettle),
-            lowest: handleNumberValue(lowest),
-            highest: handleNumberValue(highest),
-            amplitude: parsePercent(amplitude),
-            limitdown: handleNumberValue(limitdown),
-            limitup: handleNumberValue(limitup),
-        }
-    })
-})
+const futuresStore = useFuturesStore()
 
 const columns: Model.TableColumn[] = [
     { prop: 'goodsname', label: '商品名称/代码' },
@@ -141,8 +98,8 @@ const columns: Model.TableColumn[] = [
     { prop: 'lowest', label: '最低' },
     { prop: 'highest', label: '最高' },
     { prop: 'amplitude', label: '振幅' },
-    { prop: 'limitup', label: '涨停' },
-    { prop: 'limitdown', label: '跌停' },
+    { prop: 'limitup', label: '涨停' },
+    { prop: 'limitdown', label: '跌停' },
 ]
 
 const rowClick = (row: Model.QuoteGoodsListRsp) => {
@@ -154,12 +111,17 @@ const rowClick = (row: Model.QuoteGoodsListRsp) => {
     })
 }
 
+const getMarketGoodsList = () => {
+    futuresStore.setMarketId(props.marketId)
+    const goodsCodes = futuresStore.marketGoodsList.map((e) => e.goodscode)
+    subscribe.start(...goodsCodes)
+}
+
 watch(() => props.marketId, () => {
     subscribe.stop()
-    run({
-        marketids: props.marketId.toString()
-    })
+    getMarketGoodsList()
 })
 
+onActivated(() => getMarketGoodsList())
 onUnmounted(() => subscribe.stop())
 </script>

+ 74 - 27
src/packages/mobile/views/transfer/list/Index.vue

@@ -3,55 +3,96 @@
         <template #header>
             <app-navbar title="定金转让" :show-back-button="false" />
         </template>
-        <app-list :columns="columns" :data-list="dataList" @row-click="rowClick">
+        <app-list :columns="columns" :data-list="futuresStore.marketGoodsList" @row-click="rowClick">
             <!-- 商品名称/代码 -->
-            <template #goodscode="{ row }">
+            <template #goodsname="{ row }">
                 <span>{{ row.goodsname }}</span>
                 <span class="text-small">{{ row.goodscode }}</span>
             </template>
-            <template #last="{ row }">
-                <span :class="row.lastColor">{{ row.last }}</span>
+            <!-- 买价 -->
+            <template #bid="{ row }">
+                <span :class="row.bidColor">{{ handleNumberValue(formatDecimal(row.bid, row.decimalplace)) }}</span>
+            </template>
+            <!-- 买量 -->
+            <template #bidvolume="{ row }">
+                <span :class="row.bidvolumeColor">{{ handleNumberValue(row.bidvolume) }}</span>
             </template>
+            <!-- 卖价 -->
             <template #ask="{ row }">
-                <span :class="row.askColor">{{ row.ask }}</span>
+                <span :class="row.askColor">{{ handleNumberValue(formatDecimal(row.ask, row.decimalplace)) }}</span>
+            </template>
+            <!-- 卖量 -->
+            <template #askvolume="{ row }">
+                <span :class="row.askvolumeColor">{{ handleNumberValue(row.askvolume) }}</span>
+            </template>
+            <!-- 当前价 -->
+            <template #last="{ row }">
+                <span :class="row.lastColor">{{ handleNumberValue(formatDecimal(row.last, row.decimalplace)) }}</span>
+            </template>
+            <!-- 涨跌 -->
+            <template #rise="{ row }">
+                <span :class="row.lastColor">{{ formatDecimal(row.rise, row.decimalplace) }}</span>
+            </template>
+            <!-- 涨跌幅 -->
+            <template #change="{ row }">
+                <span :class="row.lastColor">{{ parsePercent(row.change) }}</span>
+            </template>
+            <!-- 今开 -->
+            <template #opened="{ row }">
+                <span :class="row.openedColor">{{ handleNumberValue(formatDecimal(row.opened, row.decimalplace)) }}</span>
+            </template>
+            <!-- 最低 -->
+            <template #lowest="{ row }">
+                <span :class="row.lowestColor">{{ handleNumberValue(formatDecimal(row.lowest, row.decimalplace)) }}</span>
+            </template>
+            <!-- 最高 -->
+            <template #highest="{ row }">
+                <span :class="row.highestColor">{{ handleNumberValue(formatDecimal(row.highest, row.decimalplace)) }}</span>
+            </template>
+            <!-- 振幅 -->
+            <template #amplitude="{ value }">
+                <span>{{ parsePercent(value) }}</span>
+            </template>
+            <!-- 涨停 -->
+            <template #limitup="{ value }">
+                <span class="g-price-up">{{ handleNumberValue(value) }}</span>
+            </template>
+            <!-- 跌停 -->
+            <template #limitdown="{ value }">
+                <span class="g-price-down">{{ handleNumberValue(value) }}</span>
             </template>
         </app-list>
     </app-view>
 </template>
 
 <script lang="ts" setup>
-import { onMounted, computed } from 'vue'
-import { handleNumberValue } from '@/filters'
+import { onActivated, onUnmounted } from 'vue'
+import { parsePercent, handleNumberValue, formatDecimal } from '@/filters'
 import { useNavigation } from '../../../router/navigation'
 import { useFuturesStore } from '@/stores'
 import quoteSocket from '@/services/websocket/quote'
 import AppList from '../../../components/base/list/index.vue'
 
 const { router } = useNavigation()
-const futuresStore = useFuturesStore()
-
-const dataList = computed(() => {
-    const list = futuresStore.goodsQuoteList.filter((e) => e.marketid === 49201)
-    return list.map((e) => ({
-        lastColor: e.lastColor,
-        askColor: e.askColor,
-        goodscode: e.goodscode,
-        goodsid: e.goodsid,
-        goodsname: e.goodsname,
-        ask: handleNumberValue(e.ask),
-        last: handleNumberValue(e.last),
-        askvolume: handleNumberValue(e.askvolume),
-    }))
-})
-
-const goodsCodes = dataList.value.map((e) => e.goodscode.toUpperCase())
 const subscribe = quoteSocket.createSubscribe()
+const futuresStore = useFuturesStore()
 
 const columns: Model.TableColumn[] = [
-    { prop: 'goodscode', label: '商品名称/代码' },
-    { prop: 'last', label: '最新价' },
+    { prop: 'goodsname', label: '商品名称/代码' },
+    { prop: 'bid', label: '买价' },
+    { prop: 'bidvolume', label: '买量' },
     { prop: 'ask', label: '卖价' },
     { prop: 'askvolume', label: '卖量' },
+    { prop: 'last', label: '当前价' },
+    { prop: 'rise', label: '涨跌' },
+    { prop: 'change', label: '幅度' },
+    { prop: 'opened', label: '今开' },
+    { prop: 'presettle', label: '昨结' },
+    { prop: 'lowest', label: '最低' },
+    { prop: 'highest', label: '最高' },
+    { prop: 'amplitude', label: '振幅' },
+    { prop: 'limitup', label: '涨停价' },
+    { prop: 'limitdown', label: '跌停价' },
 ]
 
 const rowClick = ({ goodsid }: Model.GoodsQuote) => {
@@ -63,5 +104,11 @@ const rowClick = ({ goodsid }: Model.GoodsQuote) => {
     })
 }
 
-onMounted(() => subscribe.start(...goodsCodes))
+onActivated(() => {
+    futuresStore.setMarketId(49201)
+    const goodsCodes = futuresStore.marketGoodsList.map((e) => e.goodscode)
+    subscribe.start(...goodsCodes)
+})
+
+onUnmounted(() => subscribe.stop())
 </script>

+ 6 - 2
src/packages/pc/components/base/table-filter/index.less

@@ -1,7 +1,7 @@
 .app-table-filter {
     display: flex;
     flex-wrap: wrap;
-    gap: 12px;
+    gap: 8px;
 
     .el-form-item {
         margin: 0;
@@ -18,7 +18,11 @@
     }
 
     .el-button {
-        min-width: 80px;
+        min-width: 60px;
+
+        +.el-button {
+            margin-left: 8px;
+        }
     }
 
     .el-date-editor.el-input__wrapper {

+ 1 - 1
src/packages/pc/components/base/table-filter/index.vue

@@ -1,5 +1,5 @@
 <template>
-  <el-form class="el-form--filter app-table-filter">
+  <el-form class="el-form--filter app-table-filter" size="small">
     <el-form-item v-if="$slots.before">
       <slot name="before"></slot>
     </el-form-item>

+ 4 - 0
src/packages/pc/components/layouts/footer/index.less

@@ -43,5 +43,9 @@
 
     &__right {
         border-left: 1px solid #363f45;
+
+        &:empty {
+            display: none;
+        }
     }
 }

+ 9 - 4
src/packages/pc/components/layouts/footer/index.vue

@@ -41,17 +41,22 @@
                 </el-select>
             </app-auth-component>
         </div>
-        <div class="app-footer__right" v-if="$route.name === 'market_trade_goods'">
-            <app-listing />
+        <div class="app-footer__right">
+            <component :is="GoodsListing" v-if="globalStore.showGoodsListing" />
+            <component :is="TransferListing" v-if="globalStore.showTransferListing" />
         </div>
     </div>
 </template>
 
 <script lang="ts" setup>
-import { useAccountStore } from '@/stores'
+import { defineAsyncComponent } from 'vue'
+import { useAccountStore, useGlobalStore } from '@/stores'
 import AppAuthComponent from '@pc/components/modules/auth-component/index.vue'
-import AppListing from '@pc/components/modules/listing/index.vue'
 
+const GoodsListing = defineAsyncComponent(() => import('@pc/views/market/trade/goods/list/listing/index.vue')) // 订单挂牌
+const TransferListing = defineAsyncComponent(() => import('@pc/views/market/trade/presell/transfer/listing/index.vue')) // 转让挂牌
+
+const globalStore = useGlobalStore()
 const { accountList, currentAccount, currentAccountId, loading, getAccountList } = useAccountStore()
 </script>
 

+ 1 - 1
src/packages/pc/views/market/trade/goods/list/detail/components/chart/index.less → src/packages/pc/components/modules/goods-detail/chart/index.less

@@ -1,4 +1,4 @@
-.market-trade-goods-detail-chart {
+.app-goods-detail-chart {
     display: flex;
     height: 100%;
 

+ 1 - 1
src/packages/pc/views/market/trade/goods/list/detail/components/chart/index.vue → src/packages/pc/components/modules/goods-detail/chart/index.vue

@@ -1,5 +1,5 @@
 <template>
-    <div class="market-trade-goods-detail-chart">
+    <div class="app-goods-detail-chart">
         <div class="block-left">
             <Chart v-bind="{ goodsCode }" />
         </div>

+ 10 - 10
src/packages/pc/views/market/trade/goods/list/detail/index.vue → src/packages/pc/components/modules/goods-detail/index.vue

@@ -1,7 +1,7 @@
-<!-- 交易市场-订单交易-详情 -->
+<!-- 商品详情 -->
 <template>
     <teleport to="#appPageTeleport">
-        <app-view class="market-trade-goods-detail g-view-detail">
+        <app-view class="g-view-detail">
             <template #header>
                 <div class="g-view-detail__header">
                     <div class="iconbar">
@@ -14,14 +14,14 @@
                         </li>
                     </ul>
                     <div class="buttonbar">
-                        <!-- <template v-if="active">
-                            <el-button type="info" style="min-width: 60px;">刷新</el-button>
-                            <el-button type="primary" @click="active = false">买卖大厅</el-button>
-                        </template>
-                        <el-button type="primary" @click="active = true" v-else>图表</el-button> -->
                         <template v-if="market">
-                            <span style="color: #3a87f7;padding: 10px;">市场状态:{{ getRunStatusName(market.runstatus) }}</span>
+                            <span style="color: #3a87f7;padding:0 10px;">
+                                市场状态:{{ getRunStatusName(market.runstatus) }}
+                            </span>
                         </template>
+                        <slot name="headerRight"></slot>
+                        <!-- <el-button type="primary" @click="active = false" v-if="active">买卖大厅</el-button>
+                        <el-button type="primary" @click="active = true" v-else>图表</el-button> -->
                     </div>
                 </div>
             </template>
@@ -39,8 +39,8 @@ import { useRequest } from '@/hooks/request'
 import { queryMarketRun } from '@/services/api/market'
 import { useFuturesStore } from '@/stores'
 
-const Chart = defineAsyncComponent(() => import('./components/chart/index.vue'))
-const Order = defineAsyncComponent(() => import('./components/order/index.vue'))
+const Chart = defineAsyncComponent(() => import('./chart/index.vue'))
+const Order = defineAsyncComponent(() => import('./order/index.vue'))
 
 const props = defineProps({
     goodsId: {

+ 1 - 1
src/packages/pc/views/market/trade/goods/list/detail/components/order/delisting/index.vue → src/packages/pc/components/modules/goods-detail/order/delisting/index.vue

@@ -1,4 +1,4 @@
-<!-- 交易市场-订单交易-买卖大厅-摘牌 -->
+<!-- 买卖大厅-摘牌 -->
 <template>
     <app-drawer title="摘牌" v-model:show="show" :width="400" :loading="loading" :refresh="refresh">
         <el-form ref="formRef" class="el-form--vertical" label-width="100px" :model="formData" :rules="formRules">

+ 1 - 1
src/packages/pc/views/market/trade/goods/list/detail/components/order/index.less → src/packages/pc/components/modules/goods-detail/order/index.less

@@ -1,4 +1,4 @@
-.market-trade-goods-detail-order {
+.app-goods-detail-order {
     display: flex;
     height: 100%;
     overflow: hidden;

+ 2 - 2
src/packages/pc/views/market/trade/goods/list/detail/components/order/index.vue → src/packages/pc/components/modules/goods-detail/order/index.vue

@@ -1,6 +1,6 @@
-<!-- 交易市场-订单交易-买卖大厅 -->
+<!-- 商品详情-买卖大厅 -->
 <template>
-    <div class="market-trade-goods-detail-order">
+    <div class="app-goods-detail-order">
         <app-table class="sell" :data="sellList" v-model:columns="sellColumns" :row-key="rowKey"
             :expand-row-keys="expandKeys" @row-click="rowClick" showIndex>
             <!-- 展开行 -->

+ 0 - 30
src/packages/pc/components/modules/trade/index.vue

@@ -1,30 +0,0 @@
-<!-- 期货交易 -->
-<template>
-  <app-drawer v-model:show="show">
-    <template #default>
-      {{ selectedRow }}
-    </template>
-    <template #footer>
-      <el-button @click="cancel">取消</el-button>
-      <el-button @click="cancel" type="primary">提交</el-button>
-    </template>
-  </app-drawer>
-</template>
-
-<script lang="ts" setup>
-import { ref } from 'vue'
-import AppDrawer from '../../base/drawer/index.vue'
-
-defineProps({
-  selectedRow: {
-    type: Object,
-    default: () => ({})
-  }
-})
-
-const show = ref(true);
-
-const cancel = () => {
-  show.value = false;
-}
-</script>

+ 7 - 1
src/packages/pc/views/market/trade/goods/index.vue

@@ -1,13 +1,19 @@
 <!-- 市场-订单交易 -->
 <template>
-    <app-auth-component direction="bottom" v-bind="{ code }"/>
+    <app-auth-component direction="bottom" v-bind="{ code }" />
 </template>
 
 <script lang="ts" setup>
+import { onMounted, onUnmounted } from 'vue'
+import { useGlobalStore } from '@/stores'
 import AppAuthComponent from '@pc/components/modules/auth-component/index.vue'
 
 defineProps({
     code: String
 })
 
+const globalStore = useGlobalStore()
+
+onMounted(() => globalStore.showGoodsListing = true)
+onUnmounted(() => globalStore.showGoodsListing = false)
 </script>

+ 57 - 74
src/packages/pc/views/market/trade/goods/list/index.vue

@@ -1,115 +1,91 @@
 <!-- 交易市场-订单交易 -->
 <template>
-    <app-table :data="tableList" v-model:columns="tableColumns" :loading="loading" @row-click="onRowClick" showIndex>
+    <app-table :data="marketGoodsList" v-model:columns="tableColumns" @row-click="onRowClick" showIndex>
         <!-- 规格 -->
         <template #spec="{ row }">
             {{ handleNumberValue(row.agreeunit, getGoodsUnitName(row.goodunitid)) }}
         </template>
+        <!-- 买价 -->
+        <template #bid="{ row }">
+            <span :class="row.bidColor">{{ handleNumberValue(formatDecimal(row.bid, row.decimalplace)) }}</span>
+        </template>
+        <!-- 买量 -->
+        <template #bidvolume="{ row }">
+            <span :class="row.bidvolumeColor">{{ handleNumberValue(row.bidvolume) }}</span>
+        </template>
         <!-- 卖价 -->
         <template #ask="{ row }">
-            <span :class="row.askColor">{{ row.ask }}</span>
+            <span :class="row.askColor">{{ handleNumberValue(formatDecimal(row.ask, row.decimalplace)) }}</span>
         </template>
-        <!-- 买价 -->
-        <template #bid="{ row }">
-            <span :class="row.bidColor">{{ row.bid }}</span>
+        <!-- 卖量 -->
+        <template #askvolume="{ row }">
+            <span :class="row.askvolumeColor">{{ handleNumberValue(row.askvolume) }}</span>
         </template>
         <!-- 当前价 -->
         <template #last="{ row }">
-            <span :class="row.lastColor">{{ row.last }}</span>
+            <span :class="row.lastColor">{{ handleNumberValue(formatDecimal(row.last, row.decimalplace)) }}</span>
         </template>
         <!-- 涨跌 -->
         <template #rise="{ row }">
-            <span :class="row.lastColor">{{ row.rise }}</span>
+            <span :class="row.lastColor">{{ formatDecimal(row.rise, row.decimalplace) }}</span>
         </template>
         <!-- 涨跌幅 -->
         <template #change="{ row }">
-            <span :class="row.lastColor">{{ row.change }}</span>
+            <span :class="row.lastColor">{{ parsePercent(row.change) }}</span>
         </template>
         <!-- 开盘 -->
         <template #opened="{ row }">
-            <span :class="row.openedColor">{{ row.opened }}</span>
+            <span :class="row.openedColor">{{ handleNumberValue(formatDecimal(row.opened, row.decimalplace)) }}</span>
         </template>
         <!-- 最低 -->
         <template #lowest="{ row }">
-            <span :class="row.lowestColor">{{ row.lowest }}</span>
+            <span :class="row.lowestColor">{{ handleNumberValue(formatDecimal(row.lowest, row.decimalplace)) }}</span>
         </template>
         <!-- 最高 -->
         <template #highest="{ row }">
-            <span :class="row.highestColor">{{ row.highest }}</span>
+            <span :class="row.highestColor">{{ handleNumberValue(formatDecimal(row.highest, row.decimalplace)) }}</span>
+        </template>
+        <!-- 振幅 -->
+        <template #amplitude="{ value }">
+            <span>{{ parsePercent(value) }}</span>
+        </template>
+        <!-- 涨停 -->
+        <template #limitup="{ value }">
+            <span class="g-price-up">{{ handleNumberValue(value) }}</span>
+        </template>
+        <!-- 跌停 -->
+        <template #limitdown="{ value }">
+            <span class="g-price-down">{{ handleNumberValue(value) }}</span>
+        </template>
+        <template #footer>
+            <component ref="componentRef" v-bind="{ goodsId: selectedGoodsId }" :is="componentMap.get(componentId)"
+                @closed="closeComponent" v-if="componentId" />
         </template>
     </app-table>
-    <component ref="componentRef" v-bind="{ goodsId }" :is="componentMap.get(componentId)" @closed="closeComponent"
-        v-if="componentId" />
 </template>
 
 <script lang="ts" setup>
-import { shallowRef, computed, onMounted, onUnmounted, defineAsyncComponent } from 'vue'
-import { parsePercent, handleNumberValue } from '@/filters'
+import { shallowRef, onMounted, onUnmounted, defineAsyncComponent } from 'vue'
+import { parsePercent, handleNumberValue, formatDecimal } from '@/filters'
 import { useComponent } from '@/hooks/component'
 import { getGoodsUnitName } from '@/constants/unit'
-import { useFuturesStore, useGoodsStore } from '@/stores'
+import { useFuturesStore } from '@/stores'
 import quoteSocket from '@/services/websocket/quote'
 import AppTable from '@pc/components/base/table/index.vue'
 
 const componentMap = new Map<string, unknown>([
-    ['detail', defineAsyncComponent(() => import('./detail/index.vue'))], // 详情
+    ['detail', defineAsyncComponent(() => import('@pc/components/modules/goods-detail/index.vue'))], // 详情
 ])
 
 const props = defineProps({
     code: String
 })
 
-const marketIds = (()=>{
-    switch (props.code) {
-        case 'market_trade_goods_50101':
-            return '50101'
-        case 'market_trade_goods_50102':
-            return '50102'
-        default:
-            break;
-    }
-})()
-
-const futuresStore = useFuturesStore()
-const goodsStore = useGoodsStore()
 const subscribe = quoteSocket.createSubscribe()
+const { setMarketId, $toRefs } = useFuturesStore()
+const { marketGoodsList, selectedGoodsId } = $toRefs()
 
-const { loading, goodsId, quoteGoodsList } = goodsStore.$toRefs()
-const { componentRef, componentId, openComponent, closeComponent } = useComponent(() => goodsStore.getQuoteGoodsList({
-    marketids: marketIds
-}), false)
-
-const tableList = computed(() => {
-    return quoteGoodsList.value.map((item) => {
-        const quote = futuresStore.getGoodsQuote(item.goodscode)
-        const { bid, bidColor, bidvolume, ask, askColor, askvolume, goodunitid, agreeunit, limitdown, limitup, lastColor, openedColor, lowestColor, highestColor, last, presettle, rise, change, amplitude, highest, lowest, opened, decimalplace } = quote.value ?? {}
-        return {
-            ...item,
-            lastColor,
-            openedColor,
-            lowestColor,
-            highestColor,
-            askColor,
-            bidColor,
-            bid: handleNumberValue(bid?.toFixed(decimalplace)),
-            bidvolume: handleNumberValue(bidvolume),
-            ask: handleNumberValue(ask?.toFixed(decimalplace)),
-            askvolume: handleNumberValue(askvolume),
-            last: handleNumberValue(last?.toFixed(decimalplace)),
-            rise: rise?.toFixed(item.decimalplace),
-            change: parsePercent(change),
-            opened: handleNumberValue(opened?.toFixed(decimalplace)),
-            presettle: handleNumberValue(presettle?.toFixed(decimalplace)),
-            lowest: handleNumberValue(lowest?.toFixed(decimalplace)),
-            highest: handleNumberValue(highest?.toFixed(decimalplace)),
-            amplitude: parsePercent(amplitude),
-            limitdown: handleNumberValue(limitdown?.toFixed(decimalplace)),
-            limitup: handleNumberValue(limitup?.toFixed(decimalplace)),
-            agreeunit,
-            goodunitid
-        }
-    })
-})
+const { componentRef, componentId, openComponent, closeComponent } = useComponent(() => true, false)
 
 const tableColumns = shallowRef<Model.TableColumn[]>([
     { prop: 'goodscode', label: '代码' },
@@ -127,20 +103,27 @@ const tableColumns = shallowRef<Model.TableColumn[]>([
     { prop: 'highest', label: '最高' },
     { prop: 'lowest', label: '最低' },
     { prop: 'amplitude', label: '振幅' },
-    { prop: 'limitup', label: '涨停价', className: 'g-price-up' },
-    { prop: 'limitdown', label: '跌停价', className: 'g-price-down' },
+    { prop: 'limitup', label: '涨停价' },
+    { prop: 'limitdown', label: '跌停价' },
 ])
 
-const onRowClick = (row: Model.OrderQuoteRsp) => {
-    goodsId.value = row.goodsid
+const onRowClick = (row: Model.GoodsQuote) => {
+    selectedGoodsId.value = row.goodsid
     openComponent('detail')
 }
 
 onMounted(() => {
-    goodsStore.getQuoteGoodsList({ marketids: marketIds }).then(() => {
-        const goodsCodes = goodsStore.quoteGoodsList.map((e) => e.goodscode)
-        subscribe.start(...goodsCodes)
-    })
+    switch (props.code) {
+        case 'market_trade_goods_50101':
+            setMarketId(50101)
+            break
+        case 'market_trade_goods_50102':
+            setMarketId(50102)
+            break
+    }
+    const goodsCodes = marketGoodsList.value.map((e) => e.goodscode)
+    subscribe.start(...goodsCodes)
 })
+
 onUnmounted(() => subscribe.stop())
 </script>

+ 1 - 1
src/packages/pc/components/modules/listing/index.less → src/packages/pc/views/market/trade/goods/list/listing/index.less

@@ -1,4 +1,4 @@
-.app-listing {
+.goods-listing {
     display: flex;
     height: 100%;
     background-color: #14181B;

+ 23 - 25
src/packages/pc/components/modules/listing/index.vue → src/packages/pc/views/market/trade/goods/list/listing/index.vue

@@ -1,15 +1,15 @@
 <template>
-    <div class="app-listing">
-        <div class="app-listing__forex">
-            <Forex v-bind="{ goodsCode: goodsStore.goodsCode }" @price-click="onPriceClick" />
+    <div class="goods-listing">
+        <div class="goods-listing__forex" v-if="selectedGoods">
+            <Forex v-bind="{ goodsCode: selectedGoods.goodscode }" @price-click="onPriceClick" />
         </div>
-        <div class="app-listing__form">
-            <h4 class="header-title">订单挂牌</h4>
+        <div class="goods-listing__form">
+            <h4 class="header-title">订单交易</h4>
             <el-form ref="formRef" class="el-form--vertical" label-width="60px" :model="formData" :rules="formRules">
                 <el-form-item prop="GoodsID" label="商品">
-                    <el-select placeholder="请选择" v-model="goodsStore.goodsId">
-                        <el-option :label="item.goodsname" :value="item.goodsid"
-                            v-for="(item, index) in goodsStore.quoteGoodsList" :key="index" />
+                    <el-select placeholder="请选择" v-model="selectedGoodsId">
+                        <el-option :label="item.goodsname" :value="item.goodsid" v-for="(item, index) in marketGoodsList"
+                            :key="index" />
                     </el-select>
                 </el-form-item>
                 <el-form-item prop="BuyOrSell" label="方向">
@@ -22,15 +22,16 @@
                 <el-form-item prop="OrderPrice" label="价格">
                     <div class="el-form-item--col">
                         <el-input-number ref="priceRef" placeholder="请输入" :min="0" :step="priceStep"
-                            :precision="quote?.decimalplace" v-model="formData.OrderPrice" @keyup.enter="qtyInputFocus" />
-                        <div v-if="quote">
+                            :precision="selectedGoods?.decimalplace" v-model="formData.OrderPrice"
+                            @keyup.enter="qtyInputFocus" />
+                        <div v-if="selectedGoods">
                             <div class="row-price g-price-up">
                                 <Icon icon="Top" />
-                                <span>{{ quote.limitup }}</span>
+                                <span>{{ selectedGoods.limitup }}</span>
                             </div>
                             <div class="row-price g-price-down">
                                 <Icon icon="Bottom" />
-                                <span>{{ quote.limitdown }}</span>
+                                <span>{{ selectedGoods.limitdown }}</span>
                             </div>
                         </div>
                     </div>
@@ -48,7 +49,7 @@
             <div class="footer-btnbar">
                 <template v-if="formData.BuyOrSell === BuyOrSell.Buy">
                     <el-button ref="submitRef" type="primary" :loading="loading"
-                        :disabled="!goodsStore.goodsId || !formData.OrderQty"
+                        :disabled="!selectedGoodsId || !formData.OrderQty"
                         @click="onSubmit(EBuildType.BUILDTYPE_OPEN)">订立买入</el-button>
                     <el-button type="primary" :loading="loading"
                         :disabled="!formData.OrderQty || !sellQty || (formData.OrderQty > sellQty)"
@@ -59,7 +60,7 @@
                 </template>
                 <template v-if="formData.BuyOrSell === BuyOrSell.Sell">
                     <el-button ref="submitRef" type="primary" :loading="loading"
-                        :disabled="!goodsStore.goodsId || !formData.OrderQty"
+                        :disabled="!selectedGoodsId || !formData.OrderQty"
                         @click="onSubmit(EBuildType.BUILDTYPE_OPEN)">订立卖出</el-button>
                     <el-button type="primary" :loading="loading"
                         :disabled="!formData.OrderQty || !buyQty || (formData.OrderQty > buyQty)"
@@ -80,12 +81,12 @@ import { EPriceMode, EListingSelectType, EDelistingType, EBuildType, EValidType,
 import { BuyOrSell, getBuyOrSellList } from '@/constants/order'
 import { useOrder } from '@/business/trade'
 import { usePosition } from '@/business/position'
-import { useGoodsStore, useFuturesStore } from '@/stores'
+import { useFuturesStore } from '@/stores'
 import Forex from '@pc/components/modules/quote/forex/index.vue'
 import Icon from '@pc/components/base/icon/index.vue'
 
-const goodsStore = useGoodsStore()
 const futuresStore = useFuturesStore()
+const { selectedGoodsId, selectedGoods, marketGoodsList } = futuresStore.$toRefs()
 const { formData, loading, formSubmit } = useOrder()
 const { getOrderQty } = usePosition(50)
 const formRef = shallowRef<FormInstance>()
@@ -96,12 +97,9 @@ const priceRef = shallowRef()
 const qtyRef = shallowRef()
 const submitRef = shallowRef()
 
-// 商品盘面
-const quote = computed(() => futuresStore.getGoodsQuote(goodsStore.goodsCode).value)
-
 // 价格步长
 const priceStep = computed(() => {
-    const { quoteminunit = 0, decimalplace = 0 } = quote.value ?? {}
+    const { quoteminunit = 0, decimalplace = 0 } = selectedGoods.value ?? {}
     if (quoteminunit) {
         return quoteminunit * Math.pow(10, decimalplace * -1)
     }
@@ -109,10 +107,10 @@ const priceStep = computed(() => {
 })
 
 // 买方向持仓数量
-const buyQty = computed(() => getOrderQty(BuyOrSell.Buy, goodsStore.goodsCode))
+const buyQty = computed(() => getOrderQty(BuyOrSell.Buy, selectedGoodsId.value))
 
 // 卖方向持仓数量
-const sellQty = computed(() => getOrderQty(BuyOrSell.Sell, goodsStore.goodsCode))
+const sellQty = computed(() => getOrderQty(BuyOrSell.Sell, selectedGoodsId.value))
 
 const formRules: FormRules = {
     OrderPrice: [{
@@ -172,7 +170,7 @@ const onSubmit = (buildType: number) => {
                 '*若存在价格匹配的反方向委托订单,系统将会自动撤销。',
                 '是否立即挂牌?'
             ).then(() => {
-                const { marketid = 0, goodsid = 0 } = quote.value ?? {}
+                const { marketid = 0, goodsid = 0 } = selectedGoods.value ?? {}
                 /// 获取对应的市场ID
                 formData.MarketID = marketid
                 formData.PriceMode = EPriceMode.PRICEMODE_LIMIT
@@ -196,12 +194,12 @@ const onSubmit = (buildType: number) => {
 }
 
 const goodsChange = () => {
-    const { last = 0, presettle = 0 } = quote.value ?? {}
+    const { last = 0, presettle = 0 } = selectedGoods.value ?? {}
     formData.OrderPrice = last || presettle
     formData.OrderQty = qtyStep.value
 }
 
-watch(() => goodsStore.goodsId, () => goodsChange())
+watch(selectedGoodsId, () => goodsChange())
 onMounted(() => goodsChange())
 </script>
 

+ 0 - 5
src/packages/pc/views/market/trade/presell/ballot/detail/index.vue

@@ -45,11 +45,6 @@
             </template>
         </div>
         <template #footer v-if="selectedRow.presalestatus === 2">
-            <div class="price">
-                <span class="price-text">发行价:</span>
-                <span class="price-unit">¥</span>
-                <span class="price-integer">{{ selectedRow.refprice?.toFixed(2) }}</span>
-            </div>
             <el-button type="info" @click="onCancel(false)">取消</el-button>
             <el-button type="primary" @click="onSubmit">我要认购</el-button>
             <component ref="componentRef" v-bind="{ selectedRow }" :is="componentMap.get(componentId)"

+ 28 - 8
src/packages/pc/views/market/trade/presell/ballot/index.vue

@@ -1,13 +1,13 @@
 <!-- 交易市场-预售转让-预售中签 -->
 <template>
     <app-table :data="dataList" v-model:columns="tableColumns" :loading="loading" @row-click="onRowClick" showIndex>
-        <!-- <template #headerLeft>
+        <template #headerLeft>
             <app-filter :options="filterOptons" />
-        </template> -->
-        <template #goodsname='{ row }'>
-            {{ row.goodscode }}/{{ row.goodsname }}
         </template>
-        <template #presalestatus='{ value }'>
+        <template #attachmenturl="{ value }">
+            <el-image :src="getFileUrl(value)" style="width: 48px;height: 48px;" lazy />
+        </template>
+        <template #presalestatus="{ value }">
             {{ getWRPresaleStatusName(value) }}
         </template>
         <template #footer>
@@ -19,35 +19,55 @@
 
 <script lang="ts" setup>
 import { shallowRef, defineAsyncComponent } from 'vue'
+import { getFileUrl } from '@/filters'
 import { useComponent } from '@/hooks/component'
 import { useRequest } from '@/hooks/request'
-import { getWRPresaleStatusName } from '@/constants/order'
+import { useDataFilter } from '@/hooks/datatable'
+import { getWRPresaleStatusList, getWRPresaleStatusName } from '@/constants/order'
 import { queryPresaleAuctions } from '@/services/api/presale'
 import AppTable from '@pc/components/base/table/index.vue'
+import AppFilter from '@pc/components/base/table-filter/index.vue'
 
 const componentMap = new Map<string, unknown>([
     ['detail', defineAsyncComponent(() => import('./detail/index.vue'))], // 详情
 ])
 
+const { filterOptons, getQueryParams } = useDataFilter<Model.PresaleAuctionsReq>()
 const { componentRef, componentId, openComponent, closeComponent } = useComponent(() => run(), false)
 const selectedRow = shallowRef<Model.PresaleAuctionsRsp>()
 
 const { dataList, run, loading } = useRequest(queryPresaleAuctions, {
     params: {
         presalemode: 5,
-        // presalestatusstr: '1'
     }
 })
 
 const tableColumns = shallowRef<Model.TableColumn[]>([
     { prop: 'attachmenturl', label: '图片' },
-    { prop: 'goodsname', label: '商品代码/名称' },
+    { prop: 'goodscode', label: '代码' },
+    { prop: 'goodsname', label: '名称' },
     { prop: 'refprice', label: '价格' },
     { prop: 'starttime', label: '开始时间' },
     { prop: 'endtime', label: '结束时间' },
     { prop: 'presalestatus', label: '预售状态' },
 ])
 
+filterOptons.selectList = [
+    {
+        key: 'presalestatusstr',
+        options: getWRPresaleStatusList(),
+    },
+]
+
+filterOptons.buttonList = [
+    { lable: '查询', className: 'el-button--info', onClick: () => onSearch() },
+    { lable: '重置', className: 'el-button--info', onClick: () => onSearch(true) }
+]
+
+const onSearch = (clear = false) => {
+    getQueryParams((qs) => run(qs), clear)
+}
+
 const onRowClick = (row: Model.PresaleAuctionsRsp) => {
     selectedRow.value = row
     openComponent('detail')

+ 57 - 69
src/packages/pc/views/market/trade/presell/transfer/index.vue

@@ -1,104 +1,88 @@
-<!-- 交易市场-订单交易 -->
+<!-- 交易市场-预售转让-定金转让 -->
 <template>
-    <app-table :data="tableList" v-model:columns="tableColumns" :loading="loading" @row-click="onRowClick" showIndex>
-        <!-- 规格 -->
-        <template #goodscode="{ row }">
-            {{ row.goodscode }}/{{ row.goodsname }}
-        </template>
+    <app-table :data="marketGoodsList" v-model:columns="tableColumns" @row-click="onRowClick" showIndex>
         <!-- 规格 -->
         <template #spec="{ row }">
             {{ handleNumberValue(row.agreeunit, getGoodsUnitName(row.goodunitid)) }}
         </template>
+        <!-- 买价 -->
+        <template #bid="{ row }">
+            <span :class="row.bidColor">{{ handleNumberValue(formatDecimal(row.bid, row.decimalplace)) }}</span>
+        </template>
+        <!-- 买量 -->
+        <template #bidvolume="{ row }">
+            <span :class="row.bidvolumeColor">{{ handleNumberValue(row.bidvolume) }}</span>
+        </template>
         <!-- 卖价 -->
         <template #ask="{ row }">
-            <span :class="row.askColor">{{ row.ask }}</span>
+            <span :class="row.askColor">{{ handleNumberValue(formatDecimal(row.ask, row.decimalplace)) }}</span>
         </template>
-        <!-- 买价 -->
-        <template #bid="{ row }">
-            <span :class="row.bidColor">{{ row.bid }}</span>
+        <!-- 卖量 -->
+        <template #askvolume="{ row }">
+            <span :class="row.askvolumeColor">{{ handleNumberValue(row.askvolume) }}</span>
         </template>
         <!-- 当前价 -->
         <template #last="{ row }">
-            <span :class="row.lastColor">{{ row.last }}</span>
+            <span :class="row.lastColor">{{ handleNumberValue(formatDecimal(row.last, row.decimalplace)) }}</span>
         </template>
         <!-- 涨跌 -->
         <template #rise="{ row }">
-            <span :class="row.lastColor">{{ row.rise }}</span>
+            <span :class="row.lastColor">{{ formatDecimal(row.rise, row.decimalplace) }}</span>
         </template>
         <!-- 涨跌幅 -->
         <template #change="{ row }">
-            <span :class="row.lastColor">{{ row.change }}</span>
+            <span :class="row.lastColor">{{ parsePercent(row.change) }}</span>
         </template>
         <!-- 开盘 -->
         <template #opened="{ row }">
-            <span :class="row.openedColor">{{ row.opened }}</span>
+            <span :class="row.openedColor">{{ handleNumberValue(formatDecimal(row.opened, row.decimalplace)) }}</span>
         </template>
         <!-- 最低 -->
         <template #lowest="{ row }">
-            <span :class="row.lowestColor">{{ row.lowest }}</span>
+            <span :class="row.lowestColor">{{ handleNumberValue(formatDecimal(row.lowest, row.decimalplace)) }}</span>
         </template>
         <!-- 最高 -->
         <template #highest="{ row }">
-            <span :class="row.highestColor">{{ row.highest }}</span>
+            <span :class="row.highestColor">{{ handleNumberValue(formatDecimal(row.highest, row.decimalplace)) }}</span>
+        </template>
+        <!-- 振幅 -->
+        <template #amplitude="{ value }">
+            <span>{{ parsePercent(value) }}</span>
+        </template>
+        <!-- 涨停 -->
+        <template #limitup="{ value }">
+            <span class="g-price-up">{{ handleNumberValue(value) }}</span>
+        </template>
+        <!-- 跌停 -->
+        <template #limitdown="{ value }">
+            <span class="g-price-down">{{ handleNumberValue(value) }}</span>
+        </template>
+        <template #footer>
+            <component ref="componentRef" v-bind="{ goodsId: selectedGoodsId }" :is="componentMap.get(componentId)"
+                @closed="closeComponent" v-if="componentId" />
         </template>
     </app-table>
-    <component ref="componentRef" v-bind="{ goodsId }" :is="componentMap.get(componentId)" @closed="closeComponent"
-        v-if="componentId" />
 </template>
 
 <script lang="ts" setup>
-import { shallowRef, computed, onMounted, onUnmounted, defineAsyncComponent } from 'vue'
-import { parsePercent, handleNumberValue } from '@/filters'
+import { shallowRef, onMounted, onUnmounted, defineAsyncComponent } from 'vue'
+import { parsePercent, handleNumberValue, formatDecimal } from '@/filters'
 import { useComponent } from '@/hooks/component'
 import { getGoodsUnitName } from '@/constants/unit'
-import { useFuturesStore, useGoodsStore } from '@/stores'
+import { useFuturesStore, useGlobalStore } from '@/stores'
 import quoteSocket from '@/services/websocket/quote'
 import AppTable from '@pc/components/base/table/index.vue'
 
 const componentMap = new Map<string, unknown>([
-    
+    ['detail', defineAsyncComponent(() => import('@pc/components/modules/goods-detail/index.vue'))], // 详情
 ])
 
-const futuresStore = useFuturesStore()
-const goodsStore = useGoodsStore()
 const subscribe = quoteSocket.createSubscribe()
+const globalStore = useGlobalStore()
+const { setMarketId, $toRefs } = useFuturesStore()
+const { marketGoodsList, selectedGoodsId } = $toRefs()
 
-const { loading, goodsId, quoteGoodsList } = goodsStore.$toRefs()
-const { componentRef, componentId, openComponent, closeComponent } = useComponent(() => goodsStore.getQuoteGoodsList({
-    marketids: '49201'
-}), false)
-
-const tableList = computed(() => {
-    return quoteGoodsList.value.map((item) => {
-        const quote = futuresStore.getGoodsQuote(item.goodscode)
-        const { bid, bidColor, bidvolume, ask, askColor, askvolume, goodunitid, agreeunit, limitdown, limitup, lastColor, openedColor, lowestColor, highestColor, last, presettle, rise, change, amplitude, highest, lowest, opened, decimalplace } = quote.value ?? {}
-        return {
-            ...item,
-            lastColor,
-            openedColor,
-            lowestColor,
-            highestColor,
-            askColor,
-            bidColor,
-            bid: handleNumberValue(bid?.toFixed(decimalplace)),
-            bidvolume: handleNumberValue(bidvolume),
-            ask: handleNumberValue(ask?.toFixed(decimalplace)),
-            askvolume: handleNumberValue(askvolume),
-            last: handleNumberValue(last?.toFixed(decimalplace)),
-            rise: rise?.toFixed(item.decimalplace),
-            change: parsePercent(change),
-            opened: handleNumberValue(opened?.toFixed(decimalplace)),
-            presettle: handleNumberValue(presettle?.toFixed(decimalplace)),
-            lowest: handleNumberValue(lowest?.toFixed(decimalplace)),
-            highest: handleNumberValue(highest?.toFixed(decimalplace)),
-            amplitude: parsePercent(amplitude),
-            limitdown: handleNumberValue(limitdown?.toFixed(decimalplace)),
-            limitup: handleNumberValue(limitup?.toFixed(decimalplace)),
-            agreeunit,
-            goodunitid
-        }
-    })
-})
+const { componentRef, componentId, openComponent, closeComponent } = useComponent(() => true, false)
 
 const tableColumns = shallowRef<Model.TableColumn[]>([
     { prop: 'goodscode', label: '代码' },
@@ -116,20 +100,24 @@ const tableColumns = shallowRef<Model.TableColumn[]>([
     { prop: 'highest', label: '最高' },
     { prop: 'lowest', label: '最低' },
     { prop: 'amplitude', label: '振幅' },
-    { prop: 'limitup', label: '涨停价', className: 'g-price-up' },
-    { prop: 'limitdown', label: '跌停价', className: 'g-price-down' },
+    { prop: 'limitup', label: '涨停价' },
+    { prop: 'limitdown', label: '跌停价' },
 ])
 
-const onRowClick = (row: Model.OrderQuoteRsp) => {
-    goodsId.value = row.goodsid
+const onRowClick = (row: Model.GoodsQuote) => {
+    selectedGoodsId.value = row.goodsid
     openComponent('detail')
 }
 
 onMounted(() => {
-    goodsStore.getQuoteGoodsList({ marketids: '49201' }).then(() => {
-        const goodsCodes = goodsStore.quoteGoodsList.map((e) => e.goodscode)
-        subscribe.start(...goodsCodes)
-    })
+    setMarketId(49201)
+    const goodsCodes = marketGoodsList.value.map((e) => e.goodscode)
+    subscribe.start(...goodsCodes)
+    globalStore.showTransferListing = true
+})
+
+onUnmounted(() => {
+    globalStore.showTransferListing = false
+    subscribe.stop()
 })
-onUnmounted(() => subscribe.stop())
 </script>

+ 46 - 0
src/packages/pc/views/market/trade/presell/transfer/listing/index.less

@@ -0,0 +1,46 @@
+.goods-listing {
+    display: flex;
+    height: 100%;
+    background-color: #14181B;
+
+    &__forex {
+        width: 200px;
+        padding: 5px 10px;
+
+        .app-quote-forex {
+            height: 100%;
+
+            li {
+                cursor: pointer;
+            }
+        }
+    }
+
+    &__form {
+        width: 300px;
+        padding: 10px;
+        border-left: 1px solid #363f45;
+
+        .header-title {
+            text-align: center;
+            margin-bottom: 15px;
+        }
+
+        .row-price {
+            display: flex;
+            align-items: center;
+            font-size: 12px;
+            line-height: normal;
+        }
+
+        .footer-btnbar {
+            display: flex;
+            justify-content: center;
+        }
+
+        .el-radio {
+            --el-radio-text-color: #7a8a94;
+            --el-color-primary: #3a87f7;
+        }
+    }
+}

+ 213 - 0
src/packages/pc/views/market/trade/presell/transfer/listing/index.vue

@@ -0,0 +1,213 @@
+<template>
+    <div class="goods-listing">
+        <div class="goods-listing__forex" v-if="selectedGoods">
+            <Forex v-bind="{ goodsCode: selectedGoods.goodscode }" @price-click="onPriceClick" />
+        </div>
+        <div class="goods-listing__form">
+            <h4 class="header-title">定金转让</h4>
+            <el-form ref="formRef" class="el-form--vertical" label-width="60px" :model="formData" :rules="formRules">
+                <el-form-item prop="GoodsID" label="商品">
+                    <el-select placeholder="请选择" v-model="selectedGoodsId">
+                        <el-option :label="item.goodsname" :value="item.goodsid" v-for="(item, index) in marketGoodsList"
+                            :key="index" />
+                    </el-select>
+                </el-form-item>
+                <el-form-item prop="BuyOrSell" label="方向">
+                    <el-radio-group v-model="formData.BuyOrSell">
+                        <el-radio v-for="(item, index) in getBuyOrSellList()" :key="index" :label="item.value">
+                            {{ item.label }}
+                        </el-radio>
+                    </el-radio-group>
+                </el-form-item>
+                <el-form-item prop="OrderPrice" label="价格">
+                    <div class="el-form-item--col">
+                        <el-input-number ref="priceRef" placeholder="请输入" :min="0" :step="priceStep"
+                            :precision="selectedGoods?.decimalplace" v-model="formData.OrderPrice"
+                            @keyup.enter="qtyInputFocus" />
+                        <div v-if="selectedGoods">
+                            <div class="row-price g-price-up">
+                                <Icon icon="Top" />
+                                <span>{{ selectedGoods.limitup }}</span>
+                            </div>
+                            <div class="row-price g-price-down">
+                                <Icon icon="Bottom" />
+                                <span>{{ selectedGoods.limitdown }}</span>
+                            </div>
+                        </div>
+                    </div>
+                </el-form-item>
+                <el-form-item prop="OrderQty" label="数量">
+                    <div class="g-qty-group">
+                        <el-input-number ref="qtyRef" placeholder="请输入" :min="0" :precision="0" :step="qtyStep"
+                            v-model="formData.OrderQty" @keyup.enter="submitFocus" />
+                        <el-radio-group size="small" v-model="qtyStep" @change="onRadioChange">
+                            <el-radio v-for="(value, index) in qtyStepList" :key="index" :label="value" border />
+                        </el-radio-group>
+                    </div>
+                </el-form-item>
+                <el-form-item>
+                    <el-button ref="submitRef" type="primary" :loading="loading" @click="onSubmit"
+                        v-if="formData.BuyOrSell === BuyOrSell.Buy">订立买入</el-button>
+                    <el-button ref="submitRef" type="primary" :loading="loading"
+                        :disabled="!formData.OrderQty || !enableqty || (formData.OrderQty > enableqty)" @click="onSubmit"
+                        v-if="formData.BuyOrSell === BuyOrSell.Sell">
+                        <span>转让卖出</span>
+                        <span v-if="enableqty">(≤{{ enableqty }})</span>
+                    </el-button>
+                </el-form-item>
+            </el-form>
+        </div>
+    </div>
+</template>
+
+<script lang="ts" setup>
+import { shallowRef, computed, watch, onMounted } from 'vue'
+import { ElMessage, ElMessageBox, FormInstance, FormRules } from 'element-plus'
+import { EPriceMode, EListingSelectType, EDelistingType, EBuildType, EValidType } from '@/constants/client'
+import { BuyOrSell, getBuyOrSellList } from '@/constants/order'
+import { useRequest } from '@/hooks/request'
+import { queryMineTradePositionExs } from '@/services/api/transfer'
+import { useOrder } from '@/business/trade'
+import { useFuturesStore } from '@/stores'
+import Forex from '@pc/components/modules/quote/forex/index.vue'
+import Icon from '@pc/components/base/icon/index.vue'
+
+const futuresStore = useFuturesStore()
+const { selectedGoodsId, selectedGoods, marketGoodsList } = futuresStore.$toRefs()
+const { formData, loading, formSubmit } = useOrder()
+const formRef = shallowRef<FormInstance>()
+const qtyStepList = [1, 10, 100] // 数量步长列表
+const qtyStep = shallowRef(qtyStepList[0]) // 数量步长
+
+const priceRef = shallowRef()
+const qtyRef = shallowRef()
+const submitRef = shallowRef()
+
+// 获取转让持仓
+const { dataList: positionList, run: getMineTradePositionExs } = useRequest(queryMineTradePositionExs, {
+    manual: true,
+    onSuccess: (res) => {
+        const [firstItem] = res.data
+        if (firstItem) {
+            formData.OrderPrice = firstItem.presaleprice
+        }
+    }
+})
+
+// 可用数量
+const enableqty = computed(() => {
+    const [firstItem] = positionList.value
+    return firstItem ? firstItem.buycurpositionqty - firstItem.buyfrozenqty : 0
+})
+
+// 价格步长
+const priceStep = computed(() => {
+    const { quoteminunit = 0, decimalplace = 0 } = selectedGoods.value ?? {}
+    if (quoteminunit) {
+        return quoteminunit * Math.pow(10, decimalplace * -1)
+    }
+    return 1
+})
+
+const formRules: FormRules = {
+    OrderPrice: [{
+        required: true,
+        type: 'number',
+        validator: (rule, value, callback) => {
+            if (value) {
+                callback()
+            } else {
+                callback(new Error('请输入价格'))
+            }
+        }
+    }],
+    OrderQty: [{
+        required: true,
+        validator: (rule, value, callback) => {
+            if (value) {
+                callback()
+            } else {
+                callback(new Error('请输入挂牌数量'))
+            }
+        }
+    }],
+}
+
+// 价格输入框获取焦点
+const priceInputFocus = () => {
+    priceRef.value.focus()
+}
+
+// 数量输入框获取焦点
+const qtyInputFocus = () => {
+    qtyRef.value.focus()
+}
+
+// 提交按钮获取焦点
+const submitFocus = () => {
+    submitRef.value.ref.focus()
+}
+
+const onRadioChange = (value: number) => {
+    formData.OrderQty = value
+    qtyInputFocus()
+}
+
+const onPriceClick = (buyorsell: BuyOrSell, value: number) => {
+    formData.BuyOrSell = buyorsell === BuyOrSell.Sell ? BuyOrSell.Buy : BuyOrSell.Sell
+    formData.OrderPrice = value
+    priceInputFocus()
+}
+
+// 提交挂牌
+const onSubmit = () => {
+    formRef.value?.validate((valid) => {
+        if (valid) {
+            ElMessageBox.confirm(
+                '*若存在价格匹配的反方向委托订单,系统将会自动撤销。',
+                '是否立即挂牌?'
+            ).then(() => {
+                const { marketid = 0, goodsid = 0 } = selectedGoods.value ?? {}
+                formData.MarketID = marketid
+                formData.GoodsID = goodsid
+                formData.TimevalidType = EValidType.VALIDTYPE_YZ
+                formData.PriceMode = EPriceMode.PRICEMODE_LIMIT
+                formData.ListingSelectType = EListingSelectType.LISTINGSELECTTYPE_DELISTINGTHENLISTING
+                formData.BuildType = formData.BuyOrSell === BuyOrSell.Sell ? EBuildType.BUILDTYPE_CLOSE : EBuildType.BUILDTYPE_OPEN
+                formData.DelistingType = EDelistingType.DELISTINGTYPE_PRICE
+
+                formSubmit().then(() => {
+                    ElMessage.success('挂牌成功')
+                    getMineTradePositionExs({
+                        goodsid: selectedGoodsId.value
+                    })
+                }).catch((err) => {
+                    ElMessage.error('挂牌失败:' + err)
+                }).finally(() => {
+                    priceInputFocus()
+                })
+            })
+        }
+    })
+}
+
+const goodsChange = () => {
+    const { last = 0, presettle = 0 } = selectedGoods.value ?? {}
+    formData.OrderPrice = last || presettle
+    formData.OrderQty = qtyStep.value
+
+    if (selectedGoodsId.value) {
+        getMineTradePositionExs({
+            goodsid: selectedGoodsId.value
+        })
+    }
+}
+
+watch(selectedGoodsId, () => goodsChange())
+
+onMounted(() => goodsChange())
+</script>
+
+<style lang="less">
+@import './index.less';
+</style>

+ 3 - 0
src/packages/qxst/router/index.ts

@@ -45,6 +45,9 @@ const routes: Array<RouteRecordRaw> = [
             path: 'goods',
             name: 'home-goods',
             component: () => import('../views/goods/list/Index.vue'),
+            props: {
+              marketId: 50101
+            }
           },
           {
             path: 'mine',

+ 42 - 66
src/packages/qxst/views/goods/list/Index.vue

@@ -3,7 +3,7 @@
         <template #header>
             <app-navbar title="订单挂牌" :show-back-button="false" />
         </template>
-        <app-list :columns="columns" :data-list="tableList" @row-click="rowClick">
+        <app-list :columns="columns" :data-list="futuresStore.marketGoodsList" @row-click="rowClick">
             <!-- 商品名称/代码 -->
             <template #goodsname="{ row }">
                 <span>{{ row.goodsname }}</span>
@@ -11,114 +11,78 @@
             </template>
             <!-- 买价 -->
             <template #bid="{ row }">
-                <span :class="row.bidColor">{{ row.bid }}</span>
+                <span :class="row.bidColor">{{ handleNumberValue(formatDecimal(row.bid, row.decimalplace)) }}</span>
             </template>
             <!-- 买量 -->
             <template #bidvolume="{ row }">
-                <span :class="row.bidvolumeColor">{{ row.bidvolume }}</span>
+                <span :class="row.bidvolumeColor">{{ handleNumberValue(row.bidvolume) }}</span>
             </template>
             <!-- 卖价 -->
             <template #ask="{ row }">
-                <span :class="row.askColor">{{ row.ask }}</span>
+                <span :class="row.askColor">{{ handleNumberValue(formatDecimal(row.ask, row.decimalplace)) }}</span>
             </template>
             <!-- 卖量 -->
             <template #askvolume="{ row }">
-                <span :class="row.askvolumeColor">{{ row.askvolume }}</span>
+                <span :class="row.askvolumeColor">{{ handleNumberValue(row.askvolume) }}</span>
             </template>
             <!-- 当前价 -->
             <template #last="{ row }">
-                <span :class="row.lastColor">{{ row.last }}</span>
+                <span :class="row.lastColor">{{ handleNumberValue(formatDecimal(row.last, row.decimalplace)) }}</span>
             </template>
             <!-- 涨跌 -->
             <template #rise="{ row }">
-                <span :class="row.lastColor">{{ row.rise }}</span>
+                <span :class="row.lastColor">{{ formatDecimal(row.rise, row.decimalplace) }}</span>
             </template>
-            <!-- 幅 -->
+            <!-- 涨跌幅 -->
             <template #change="{ row }">
-                <span :class="row.lastColor">{{ row.change }}</span>
+                <span :class="row.lastColor">{{ parsePercent(row.change) }}</span>
             </template>
             <!-- 今开 -->
             <template #opened="{ row }">
-                <span :class="row.openedColor">{{ row.opened }}</span>
+                <span :class="row.openedColor">{{ handleNumberValue(formatDecimal(row.opened, row.decimalplace)) }}</span>
             </template>
             <!-- 最低 -->
             <template #lowest="{ row }">
-                <span :class="row.lowestColor">{{ row.lowest }}</span>
+                <span :class="row.lowestColor">{{ handleNumberValue(formatDecimal(row.lowest, row.decimalplace)) }}</span>
             </template>
             <!-- 最高 -->
             <template #highest="{ row }">
-                <span :class="row.highestColor">{{ row.highest }}</span>
+                <span :class="row.highestColor">{{ handleNumberValue(formatDecimal(row.highest, row.decimalplace)) }}</span>
+            </template>
+            <!-- 振幅 -->
+            <template #amplitude="{ value }">
+                <span>{{ parsePercent(value) }}</span>
             </template>
             <!-- 涨停 -->
             <template #limitup="{ value }">
-                <span class="g-price-up">{{ value }}</span>
+                <span class="g-price-up">{{ handleNumberValue(value) }}</span>
             </template>
             <!-- 跌停 -->
             <template #limitdown="{ value }">
-                <span class="g-price-down">{{ value }}</span>
+                <span class="g-price-down">{{ handleNumberValue(value) }}</span>
             </template>
         </app-list>
     </app-view>
 </template>
 
 <script lang="ts" setup>
-import { computed, onUnmounted } from 'vue'
-import { parsePercent, handleNumberValue } from '@/filters'
-import { useRequest } from '@/hooks/request'
+import { onUnmounted, onActivated, watch } from 'vue'
+import { parsePercent, handleNumberValue, formatDecimal } from '@/filters'
 import { useNavigation } from '../../../router/navigation'
-import { queryQuoteGoodsList } from '@/services/api/swap'
-import { useFuturesStore, useUserStore } from '@/stores'
+import { useFuturesStore } from '@/stores'
 import quoteSocket from '@/services/websocket/quote'
 import AppList from '../../../components/base/list/index.vue'
 
-const { router } = useNavigation()
-const futuresStore = useFuturesStore()
-const userStore = useUserStore()
-const subscribe = quoteSocket.createSubscribe()
-
-const { dataList } = useRequest(queryQuoteGoodsList, {
-    params: {
-        usertype: userStore.userType ?? 0,
-        marketids: '50101'
-    },
-    onSuccess: (res) => {
-        const goodsCodes = res.data.map((e) => e.goodscode)
-        if (goodsCodes.length) {
-            subscribe.start(...goodsCodes)
-        }
+const props = defineProps({
+    marketId: {
+        type: Number,
+        required: true
     }
 })
 
-const tableList = computed(() => {
-    return dataList.value.map((item) => {
-        const quote = futuresStore.getGoodsQuote(item.goodscode)
-        const { goodsname, bid, bidColor, bidvolume, ask, askColor, askvolume, limitdown, limitup, lastColor, openedColor, lowestColor, highestColor, last, presettle, rise, change, amplitude, highest, lowest, opened } = quote.value ?? {}
-        return {
-            ...item,
-            goodsname,
-            lastColor,
-            openedColor,
-            lowestColor,
-            highestColor,
-            askColor,
-            bidColor,
-            bid: handleNumberValue(bid),
-            bidvolume: handleNumberValue(bidvolume),
-            ask: handleNumberValue(ask),
-            askvolume: handleNumberValue(askvolume),
-            last: handleNumberValue(last),
-            rise: rise?.toFixed(item.decimalplace),
-            change: parsePercent(change),
-            opened: handleNumberValue(opened),
-            presettle: handleNumberValue(presettle),
-            lowest: handleNumberValue(lowest),
-            highest: handleNumberValue(highest),
-            amplitude: parsePercent(amplitude),
-            limitdown: handleNumberValue(limitdown),
-            limitup: handleNumberValue(limitup),
-        }
-    })
-})
+const { router } = useNavigation()
+const subscribe = quoteSocket.createSubscribe()
+const futuresStore = useFuturesStore()
 
 const columns: Model.TableColumn[] = [
     { prop: 'goodsname', label: '商品名称/代码' },
@@ -134,8 +98,8 @@ const columns: Model.TableColumn[] = [
     { prop: 'lowest', label: '最低' },
     { prop: 'highest', label: '最高' },
     { prop: 'amplitude', label: '振幅' },
-    { prop: 'limitup', label: '涨停' },
-    { prop: 'limitdown', label: '跌停' },
+    { prop: 'limitup', label: '涨停' },
+    { prop: 'limitdown', label: '跌停' },
 ]
 
 const rowClick = (row: Model.QuoteGoodsListRsp) => {
@@ -147,5 +111,17 @@ const rowClick = (row: Model.QuoteGoodsListRsp) => {
     })
 }
 
+const getMarketGoodsList = () => {
+    futuresStore.setMarketId(props.marketId)
+    const goodsCodes = futuresStore.marketGoodsList.map((e) => e.goodscode)
+    subscribe.start(...goodsCodes)
+}
+
+watch(() => props.marketId, () => {
+    subscribe.stop()
+    getMarketGoodsList()
+})
+
+onActivated(() => getMarketGoodsList())
 onUnmounted(() => subscribe.stop())
 </script>

+ 4 - 4
src/services/websocket/quote.ts

@@ -55,7 +55,7 @@ export default new (class {
         })
 
         if (goodsList.length) {
-            console.log('开始行情订阅', goodsList)
+            //console.log('开始行情订阅', goodsList)
             this.connect().then(() => {
                 const content = subscribeListToByteArrary(goodsList, '2_TOKEN_NEKOT_', Long.fromNumber(2))
 
@@ -66,8 +66,8 @@ export default new (class {
                     },
                     success: (raw) => {
                         if (raw.content) {
-                            parseSubscribeRsp(raw.content).then((res) => {
-                                console.log('行情订阅成功', res)
+                            parseSubscribeRsp(raw.content).then(() => {
+                                //console.log('行情订阅成功', res)
                             }).catch(() => {
                                 console.error('报文解析失败', raw)
                             })
@@ -109,7 +109,7 @@ export default new (class {
             stop: () => {
                 const flag = this.subscribeMap.delete(uuid)
                 if (flag) {
-                    console.log('删除订阅', uuid)
+                    //console.log('删除订阅', uuid)
                 }
                 this.subscribe()
                 return flag

+ 30 - 1
src/stores/modules/futures.ts

@@ -1,4 +1,4 @@
-import { reactive, computed, toRefs, onUnmounted } from 'vue'
+import { shallowRef, reactive, computed, toRefs, onUnmounted } from 'vue'
 import { v4 } from 'uuid'
 import { handlePriceColor } from '@/filters'
 import { queryErmcpGoods, queryQuoteDay } from '@/services/api/goods'
@@ -14,13 +14,39 @@ import moment from 'moment'
 export const useFuturesStore = defineStore(() => {
     // 行情监听集合
     const quoteWatchMap = new Map<string, { keys: string[]; callback: (value: Partial<Model.QuoteDayRsp>) => void; }>()
+    // 市场ID
+    const marketIds = shallowRef<number[]>([])
 
     const state = reactive({
         loading: false,
         goodsList: <Model.GoodsRsp[]>[], // 商品列表
         goodsQuoteList: <Model.GoodsQuote[]>[], // 商品行情列表
+        selectedGoodsId: <number | undefined>undefined, // 当前选中的商品ID
     })
 
+    // 指定市场ID的商品列表
+    const marketGoodsList = computed(() => {
+        const list = state.goodsQuoteList.filter((e) => marketIds.value.includes(e.marketid))
+        return list.sort((a, b) => a.goodscode.localeCompare(b.goodscode)) // 根据 goodscode 字母升序排序
+    })
+
+    // 当前选中的商品
+    const selectedGoods = computed(() => state.goodsQuoteList.find((e) => e.goodsid === state.selectedGoodsId))
+
+    // 设置市场ID
+    const setMarketId = (...values: number[]) => {
+        marketIds.value = values
+        const list = marketGoodsList.value
+        if (list.length) {
+            // 查找当前选中的商品ID
+            if (!list.every((e) => e.goodsid === state.selectedGoodsId)) {
+                state.selectedGoodsId = list[0].goodsid
+            }
+        } else {
+            state.selectedGoodsId = undefined
+        }
+    }
+
     // 获取商品列表
     const getGoodsList = () => {
         timerTask.clearTimeout('quoteDay')
@@ -324,6 +350,9 @@ export const useFuturesStore = defineStore(() => {
 
     return {
         ...toRefs(state),
+        marketGoodsList,
+        selectedGoods,
+        setMarketId,
         getQuotePrice,
         getGoodsList,
         getGoodsQuote,

+ 2 - 1
src/stores/modules/global.ts

@@ -9,7 +9,8 @@ export const useGlobalStore = defineStore(() => {
 
     const state = reactive({
         appName: document.title,
-        show: false,
+        showGoodsListing: false, // 是否显示订单交易挂牌
+        showTransferListing: false, // 是否显示定金转让挂牌
         clientWidth: 0, // 客户端宽度
         isMobile: false, // 是否移动设备
     })

+ 2 - 0
src/stores/modules/goods.ts

@@ -44,6 +44,8 @@ export const useGoodsStore = defineStore(() => {
             // 查找当前选中的商品
             if (!data.every((e) => e.goodsid === state.goodsId)) {
                 state.goodsId = data[0].goodsid
+            } else {
+                state.goodsId = undefined
             }
         } finally {
             state.loading = false