瀏覽代碼

Merge branch 'master' of http://47.101.159.18:3000/Muchinfo/MTP20_WEB_GLOBAL

zhou.xiaoning 2 年之前
父節點
當前提交
1fef8e6f56
共有 100 個文件被更改,包括 1021 次插入749 次删除
  1. 4 0
      .env.qxst
  2. 6 1
      android/fxgl.txt
  3. 3 1
      package.json
  4. 23 23
      public/config/router.json
  5. 12 15
      src/business/bank/index.ts
  6. 2 2
      src/business/performance/index.ts
  7. 6 2
      src/business/trade/index.ts
  8. 9 8
      src/constants/funcode.ts
  9. 81 65
      src/hooks/echarts/candlestick/index.ts
  10. 1 1
      src/hooks/echarts/candlestick/options.ts
  11. 1 1
      src/hooks/echarts/candlestick/types.ts
  12. 1 1
      src/hooks/echarts/timeline/dataset.ts
  13. 33 20
      src/hooks/echarts/timeline/index.ts
  14. 2 2
      src/hooks/echarts/timeline/options.ts
  15. 二進制
      src/packages/gstj/assets/images/boot-1080p.png
  16. 二進制
      src/packages/gstj/assets/images/boot-480p.png
  17. 二進制
      src/packages/gstj/assets/images/boot-720p.png
  18. 二進制
      src/packages/gstj/assets/images/hongbao-open.png
  19. 二進制
      src/packages/gstj/assets/images/hongbao.png
  20. 二進制
      src/packages/gstj/assets/images/level-bg.png
  21. 二進制
      src/packages/gstj/assets/images/lottery/lottery-bg.png
  22. 二進制
      src/packages/gstj/assets/images/lottery/lottery-hongbao.png
  23. 二進制
      src/packages/gstj/assets/images/lottery/lottery-money.png
  24. 二進制
      src/packages/gstj/assets/images/lottery/lottery-red-envelope.png
  25. 二進制
      src/packages/gstj/assets/images/lottery/lottery-title.png
  26. 10 0
      src/packages/gstj/assets/themes/global/global.less
  27. 2 2
      src/packages/gstj/views/account/certification/Index.vue
  28. 15 42
      src/packages/gstj/views/goods/detail/components/listing/Index.vue
  29. 14 39
      src/packages/gstj/views/goods/trade/components/delisting/index.vue
  30. 15 19
      src/packages/gstj/views/goods/trade/index.vue
  31. 0 25
      src/packages/gstj/views/home/main/Index.vue
  32. 3 3
      src/packages/gstj/views/mine/Index.vue
  33. 1 1
      src/packages/gstj/views/order/delivery/components/offline/detail/Index.vue
  34. 15 14
      src/packages/gstj/views/spot/detail/Index.vue
  35. 2 1
      src/packages/gstj/views/spot/detail/components/listing/index.vue
  36. 4 3
      src/packages/gstj/views/spot/list/Index.vue
  37. 二進制
      src/packages/mobile/assets/images/boot-1080p.png
  38. 二進制
      src/packages/mobile/assets/images/boot-480p.png
  39. 二進制
      src/packages/mobile/assets/images/boot-720p.png
  40. 10 0
      src/packages/mobile/assets/themes/global/global.less
  41. 2 2
      src/packages/mobile/components/modules/quote/price/index.vue
  42. 2 2
      src/packages/mobile/views/account/certification/Index.vue
  43. 8 3
      src/packages/mobile/views/ballot/detail/components/delisting/index.vue
  44. 19 8
      src/packages/mobile/views/bank/sign/Index.vue
  45. 12 3
      src/packages/mobile/views/bank/sign/components/edit/Index.vue
  46. 14 41
      src/packages/mobile/views/goods/detail/components/listing/Index.vue
  47. 14 39
      src/packages/mobile/views/goods/trade/components/delisting/index.vue
  48. 15 19
      src/packages/mobile/views/goods/trade/index.vue
  49. 3 3
      src/packages/mobile/views/mine/Index.vue
  50. 3 3
      src/packages/mobile/views/order/delivery/components/offline/detail/Index.vue
  51. 2 1
      src/packages/mobile/views/order/list/components/goodsorder/detail/Index.vue
  52. 2 2
      src/packages/mobile/views/order/list/components/goodsorder/list/Index.vue
  53. 2 2
      src/packages/mobile/views/order/list/components/goodstrade/list/Index.vue
  54. 2 1
      src/packages/mobile/views/order/list/components/presale/detail/Index.vue
  55. 3 1
      src/packages/mobile/views/order/list/components/pricingorder/detail/Index.vue
  56. 1 1
      src/packages/mobile/views/order/list/components/transferorder/detail/Index.vue
  57. 3 3
      src/packages/mobile/views/order/performance/Index.vue
  58. 1 1
      src/packages/mobile/views/order/performance/components/breach/Index.vue
  59. 6 6
      src/packages/mobile/views/order/performance/components/detail/Index.vue
  60. 0 1
      src/packages/mobile/views/order/performance/components/detail/index.less
  61. 2 2
      src/packages/mobile/views/order/performance/components/modify/Index.vue
  62. 2 2
      src/packages/mobile/views/order/position/components/goods/close/Index.vue
  63. 2 2
      src/packages/mobile/views/order/position/components/presale/detail/Index.vue
  64. 0 1
      src/packages/mobile/views/order/position/components/pricing/list/Index.vue
  65. 35 1
      src/packages/mobile/views/order/position/components/spot/listing/Index.vue
  66. 2 2
      src/packages/mobile/views/order/position/components/transfer/list/Index.vue
  67. 2 2
      src/packages/mobile/views/order/position/components/transfer/listing/Index.vue
  68. 25 0
      src/packages/mobile/views/spot/add/components/buy/index.vue
  69. 47 0
      src/packages/mobile/views/spot/add/components/preformance/index.vue
  70. 35 1
      src/packages/mobile/views/spot/add/components/sell/index.vue
  71. 15 14
      src/packages/mobile/views/spot/detail/Index.vue
  72. 38 2
      src/packages/mobile/views/spot/detail/components/listing/index.vue
  73. 4 3
      src/packages/mobile/views/spot/list/Index.vue
  74. 2 2
      src/packages/pc/assets/themes/default/default.less
  75. 1 0
      src/packages/pc/components/base/drawer/index.less
  76. 6 2
      src/packages/pc/components/base/table/index.less
  77. 1 1
      src/packages/pc/components/layouts/footer/index.less
  78. 6 1
      src/packages/pc/components/modules/listing/index.less
  79. 31 61
      src/packages/pc/components/modules/listing/index.vue
  80. 5 1
      src/packages/pc/components/modules/quote/chart/kline/index.less
  81. 1 1
      src/packages/pc/components/modules/quote/chart/timeline/index.less
  82. 1 1
      src/packages/pc/components/modules/quote/chart/timeline/index.vue
  83. 1 1
      src/packages/pc/components/modules/quote/forex/index.less
  84. 6 0
      src/packages/pc/components/modules/quote/price/index.less
  85. 2 2
      src/packages/pc/components/modules/quote/tik/index.vue
  86. 5 5
      src/packages/pc/views/account/address/components/edit/index.vue
  87. 0 87
      src/packages/pc/views/account/address/components/new/index.vue
  88. 6 4
      src/packages/pc/views/account/address/index.vue
  89. 0 75
      src/packages/pc/views/account/receipt/components/new/index.vue
  90. 5 3
      src/packages/pc/views/account/receipt/index.vue
  91. 8 4
      src/packages/pc/views/account/sign/components/cancel/index.vue
  92. 91 0
      src/packages/pc/views/account/sign/components/certification/index.vue
  93. 13 9
      src/packages/pc/views/account/sign/components/sign/index.vue
  94. 17 8
      src/packages/pc/views/account/sign/index.vue
  95. 2 2
      src/packages/pc/views/auth/components/layout/index.vue
  96. 159 0
      src/packages/pc/views/auth/forget/index.vue
  97. 7 1
      src/packages/pc/views/auth/login/index.less
  98. 6 4
      src/packages/pc/views/auth/login/index.vue
  99. 4 4
      src/packages/pc/views/footer/capital/summary/deposit/index.vue
  100. 37 5
      src/packages/pc/views/footer/capital/summary/index.vue

+ 4 - 0
.env.qxst

@@ -0,0 +1,4 @@
+VUE_APP_ENV = 'qxst'
+VUE_APP_TITLE = 黔鑫生态
+VUE_APP_ROOT = src/packages/qxst/
+VUE_APP_HOST = localhost

+ 6 - 1
android/fxgl.txt

@@ -17,4 +17,9 @@ http://103.40.249.126:18280/cfg?key=mtp_20
 
 甘肃碳交
 cn.muchinfo.cgeex_trial_v1.0.0.apk
-http://8.130.36.162:8280/cfg?key=mtp_20 
+http://8.130.36.162:8280/cfg?key=mtp_20
+
+
+黔鑫生态
+cn.muchinfo.qxst_demo_v1.0.0.apk
+http://8.130.72.213:8280/cfg?key=mtp_20

+ 3 - 1
package.json

@@ -7,10 +7,12 @@
     "dev:mobile": "vue-cli-service serve --mode mobile",
     "dev:gstj": "vue-cli-service serve --mode gstj",
     "dev:sbyj": "vue-cli-service serve --mode sbyj",
+    "dev:qxst": "vue-cli-service serve --mode qxst",
     "build:pc": "vue-cli-service build --mode pc",
     "build:mobile": "vue-cli-service build --mode mobile",
     "build:gstj": "vue-cli-service build --mode gstj",
     "build:sbyj": "vue-cli-service build --mode sbyj",
+    "build:qxst": "vue-cli-service build --mode qxst",
     "lint": "vue-cli-service lint"
   },
   "dependencies": {
@@ -62,4 +64,4 @@
     "vconsole": "^3.14.6",
     "worker-loader": "^3.0.8"
   }
-}
+}

+ 23 - 23
public/config/router.json

@@ -7,29 +7,6 @@
         "children": [
             {
                 "authType": 2,
-                "sort": 1,
-                "title": "资金信息",
-                "code": "bottom_capital",
-                "component": "views/footer/index.vue",
-                "children": [
-                    {
-                        "authType": 2,
-                        "sort": 1,
-                        "title": "资金汇总",
-                        "code": "bottom_capital_summary",
-                        "component": "views/footer/capital/summary/index.vue"
-                    },
-                    {
-                        "authType": 2,
-                        "sort": 2,
-                        "title": "资金流水",
-                        "code": "bottom_capital_statement",
-                        "component": "views/footer/capital/statement/index.vue"
-                    }
-                ]
-            },
-            {
-                "authType": 2,
                 "sort": 2,
                 "title": "商品订单",
                 "code": "bottom_goods",
@@ -124,6 +101,29 @@
                         "component": "views/footer/performance/sell/index.vue"
                     }
                 ]
+            },
+            {
+                "authType": 2,
+                "sort": 1,
+                "title": "资金信息",
+                "code": "bottom_capital",
+                "component": "views/footer/index.vue",
+                "children": [
+                    {
+                        "authType": 2,
+                        "sort": 1,
+                        "title": "资金汇总",
+                        "code": "bottom_capital_summary",
+                        "component": "views/footer/capital/summary/index.vue"
+                    },
+                    {
+                        "authType": 2,
+                        "sort": 2,
+                        "title": "资金流水",
+                        "code": "bottom_capital_statement",
+                        "component": "views/footer/capital/statement/index.vue"
+                    }
+                ]
             }
         ]
     },

+ 12 - 15
src/business/bank/index.ts

@@ -1,12 +1,11 @@
 import { reactive, shallowRef, computed } from 'vue'
-import { useAccountStore, useUserStore, useLoginStore } from '@/stores'
+import { useAccountStore, useUserStore } from '@/stores'
 import { t2bBankWithdraw, queryBankAccountSign, t2bBankDeposit, queryCusBankSignBank, t2bBankSign, t2bBankCancelSign, accountFundInfoReq } from '@/services/api/bank'
 import { SignStatus } from '@/constants/bank'
 import { decryptAES } from '@/services/websocket/package/crypto'
 import moment from "moment"
 
 const accountStore = useAccountStore()
-const loginStore = useLoginStore()
 
 // 提现请求
 export function useDoWithdraw() {
@@ -126,7 +125,6 @@ export function useDoBankSign() {
     /// 查询签约银行信息
     const request = queryCusBankSignBank().then((res) => {
         if (res.data.length) {
-            console.log(res.data)
             const data = res.data[0]
             cusSignBank.value = data
             formData.Currency = data.currency
@@ -142,7 +140,10 @@ export function useDoBankSign() {
 
     /// 判断是否有签约信息 有就做修改
     queryBankAccountSign().then((res) => {
-        bankInfo.value = res.data[0]
+        console.log(res.data)
+        bankInfo.value = res.data.filter(obj => {
+            return ![SignStatus.Rescinded].includes(obj.signstatus)
+        })[0]
         if (bankInfo.value) {
             ({
                 currency: formData.Currency,
@@ -211,24 +212,19 @@ export function useDoCancelBankSign() {
     /// 获取当前是否已签约
     const sign = shallowRef<Model.BankAccountSignRsp[]>([])
 
-    const request = queryBankAccountSign({
-        data: {
-            userid: loginStore.userId
-        }
-    }).then((res) => {
-        if (res.data.length) {
+    const formRefresh = () => {
+        console.log('formRefresh')
+        queryBankAccountSign().then((res) => {
             bankInfo.value = res.data[0];
             ({
                 currency: formData.Currency,
                 cusbankid: formData.CusBankID,
                 accountcode: formData.AccountCode,
             } = bankInfo.value ?? {})
-        }
-    })
+        })
+    }
 
     const cancelSubmit = async () => {
-        await request
-        // await request
         loading.value = true
         /// 发起请求
         return t2bBankCancelSign({
@@ -246,7 +242,8 @@ export function useDoCancelBankSign() {
         cancelSubmit,
         formData,
         sign,
-        bankInfo
+        bankInfo,
+        formRefresh
     }
 }
 

+ 2 - 2
src/business/performance/index.ts

@@ -11,11 +11,11 @@ const loginStore = useLoginStore()
 const accountStore = useAccountStore()
 
 // 违约申请请求
-export function usePerformanceContractedApply(buyaccountid: number) {
+export function usePerformanceContractedApply(buyorsell: number) {
     const loading = shallowRef(false)
 
     const formData = ref<Partial<Proto.PerformanceContractedApplyReq>>({
-        BreachType: buyaccountid === accountStore.currentAccountId ? 2 : 1
+        BreachType: buyorsell+1
     })
 
     const formSubmit = async () => {

+ 6 - 2
src/business/trade/index.ts

@@ -24,6 +24,7 @@ import {
 import { formatDate } from "@/filters";
 import Long from 'long'
 import { BuyOrSell } from '@/constants/order'
+import eventBus from '@/services/bus'
 
 const loginStore = useLoginStore()
 const accountStore = useAccountStore()
@@ -569,19 +570,22 @@ export function useOrder() {
         BuildType: EBuildType.BUILDTYPE_OPEN,
         TimevalidType: EValidType.VALIDTYPE_DR,
         OrderFlag: 1,
+        OrderQty: 1,
     })
 
     const formSubmit = async () => {
         try {
             loading.value = true
-
-            return await order({
+            const res = await order({
                 data: {
                     ...formData,
                     ClientSerialNo: v4(),
                     ClientOrderTime: formatDate(new Date().toISOString()),
                 }
             })
+            // 推送委托回应通知
+            eventBus.$emit('OrderRsp', res)
+            return res
         } finally {
             loading.value = false
         }

+ 9 - 8
src/constants/funcode.ts

@@ -51,6 +51,7 @@ export enum FunCode {
     ListingOrderChangeNtf = 131176, // 挂牌委托变更广播通知
     OrderDealedNtf = 131081, // 委托单成交通知
     MarketStatusChangeNtf = 131089, // 市场状态变更通知
+    PosChangedNtf = 131075, // 头寸变化通知
 
     // 行情内容
     QuoteBeat = 0x12, // 心跳
@@ -116,12 +117,12 @@ export enum FunCode {
     PerformanceModifyContactReq = 1310735, // 履约修改联络信息请求
     PerformanceModifyContactRsp = 1310736, // 履约修改联络信息回应
 
-    SupplementDepositReq        = 196731, // 补充定金接口请求
-	SupplementDepositRsp        = 196732, // 补充定金接口响应
-	RefundedDepositReq          = 196733, // 退返定金接口请求
-	RefundedDepositRsp          = 196734, // 退返定金接口响应
-	MarketOrderDeliveryApplyReq = 196739, // 按单做市交收申请接口请求
-	MarketOrderDeliveryApplyRsp = 196740, // 按单做市交收申请接口响应
-	DeliveryClientOperatorReq   = 196743, // 交收终端操作接口请求
-	DeliveryClientOperatorRsp   = 196744, // 交收终端操作接口响应
+    SupplementDepositReq = 196731, // 补充定金接口请求
+    SupplementDepositRsp = 196732, // 补充定金接口响应
+    RefundedDepositReq = 196733, // 退返定金接口请求
+    RefundedDepositRsp = 196734, // 退返定金接口响应
+    MarketOrderDeliveryApplyReq = 196739, // 按单做市交收申请接口请求
+    MarketOrderDeliveryApplyRsp = 196740, // 按单做市交收申请接口响应
+    DeliveryClientOperatorReq = 196743, // 交收终端操作接口请求
+    DeliveryClientOperatorRsp = 196744, // 交收终端操作接口响应
 } 

+ 81 - 65
src/hooks/echarts/candlestick/index.ts

@@ -37,7 +37,7 @@ export function useCandlestickChart(goodscode: string) {
             cci: '--'
         }
 
-        if (dataIndex.value > -1) {
+        if (dataIndex.value > -1 && dataset.candlestick.source.length > dataIndex.value) {
             const { open, close, highest, lowest, ma5, ma10, ma15 } = dataset.candlestick.source[dataIndex.value];
             const { macd, dif, dea } = dataset.macd.source[dataIndex.value];
             const { vol } = dataset.vol.source[dataIndex.value];
@@ -125,77 +125,93 @@ export function useCandlestickChart(goodscode: string) {
             const oldTime = lastIndex === -1 ? moment(lasttime) : moment(candlestick.source[lastIndex].date); // 历史行情最后时间
             const diffTime = moment(lasttime).valueOf() - oldTime.valueOf(); // 计算时间差
 
-            if (diffTime > cycleMilliseconds * 2) {
-                // 时间间隔超过两个周期,重新请求历史数据
-                //timerInterceptor.debounce(() => initData(cycleType.value), 1000, 'updateChart');
+            // if (diffTime > cycleMilliseconds * 2) {
+            //     // 时间间隔超过两个周期,重新请求历史数据,待优化
+            //     timerInterceptor.debounce(() => {
+            //         queryHistoryDatas({
+            //             data: {
+            //                 cycleType: options.cycleType,
+            //                 goodsCode: goodscode,
+            //                 count: 1440,
+            //             }
+            //         }).then((res) => {
+            //             // 日期升序排序
+            //             const data = res.data.sort((a, b) => moment(a.ts).valueOf() - moment(b.ts).valueOf());
+            //             if (data.length) {
+            //                 dataIndex.value = data.length - 1
+            //                 clearData()
+            //                 handleData(data, updateOptions)
+            //             }
+            //         })
+            //     }, 1000, 'updateChart')
+            // } else {
+            // 判断时间差是否大于周期时间
+            if (lastIndex === -1 || diffTime > cycleMilliseconds) {
+                oldTime.add(cycleMilliseconds, 'ms');
+                const lastDate = oldTime.format('YYYY-MM-DD HH:mm:ss');
+
+                // 新增K线数据
+                candlestick.source.push({
+                    date: lastDate,
+                    open: last,
+                    close: last,
+                    lowest: last,
+                    highest: last,
+                    ma5: '-',
+                    ma10: '-',
+                    ma15: '-',
+                })
+
+                // 新增MACD数据
+                macd.source.push({
+                    date: lastDate,
+                    ema12: 0,
+                    ema26: 0,
+                    dif: 0,
+                    dea: 0,
+                    macd: 0,
+                })
+
+                // 新增VOL数据
+                vol.source.push({
+                    date: lastDate,
+                    vol: 0,
+                })
+
+                // 新增KDJ数据
+                kdj.source.push({
+                    date: lastDate,
+                    k: '-',
+                    d: '-',
+                    j: '-',
+                })
+
+                // 新增CCI数据
+                cci.source.push({
+                    date: lastDate,
+                    cci: '-',
+                })
             } else {
-                // 判断时间差是否大于周期时间
-                if (lastIndex === -1 || diffTime > cycleMilliseconds) {
-                    oldTime.add(cycleMilliseconds, 'ms');
-                    const lastDate = oldTime.format('YYYY-MM-DD HH:mm:ss');
-
-                    // 新增K线数据
-                    candlestick.source.push({
-                        date: lastDate,
-                        open: last,
-                        close: last,
-                        lowest: last,
-                        highest: last,
-                        ma5: '-',
-                        ma10: '-',
-                        ma15: '-',
-                    })
-
-                    // 新增MACD数据
-                    macd.source.push({
-                        date: lastDate,
-                        ema12: 0,
-                        ema26: 0,
-                        dif: 0,
-                        dea: 0,
-                        macd: 0,
-                    })
-
-                    // 新增VOL数据
-                    vol.source.push({
-                        date: lastDate,
-                        vol: 0,
-                    })
-
-                    // 新增KDJ数据
-                    kdj.source.push({
-                        date: lastDate,
-                        k: '-',
-                        d: '-',
-                        j: '-',
-                    })
-
-                    // 新增CCI数据
-                    cci.source.push({
-                        date: lastDate,
-                        cci: '-',
-                    })
-                } else {
-                    // 更新列表中最后一条记录的数据
-                    const record = candlestick.source[lastIndex];
-                    if (record.lowest > last) {
-                        record.lowest = last; // 更新最低价
-                    }
-                    if (record.highest < last) {
-                        record.highest = last; // 更新最高价
-                    }
-                    record.close = last; // 更新收盘价
+                // 更新列表中最后一条记录的数据
+                const record = candlestick.source[lastIndex];
+                if (record.lowest > last) {
+                    record.lowest = last; // 更新最低价
                 }
-
-                // 计算各项指标
-                calcIndicator(lastIndex === -1 ? 0 : lastIndex);
-                updateOptions();
+                if (record.highest < last) {
+                    record.highest = last; // 更新最高价
+                }
+                record.close = last; // 更新收盘价
             }
+
+            // 计算各项指标
+            calcIndicator(lastIndex === -1 ? 0 : lastIndex);
+            updateOptions();
+            // }
         }
     }
 
     // 监听行情推送
-    watch(() => quote.value?.last, () => {
+    watch(() => quote.value, () => {
         if (!loading.value && !isEmpty.value) {
             updateChart();
         }

+ 1 - 1
src/hooks/echarts/candlestick/options.ts

@@ -388,7 +388,7 @@ export function useOptions(dataset: EchartsDataset) {
                 source: cci.source,
             },
         }
-    }, 500)
+    }, 100)
 
     // 监听主题变化
     watch(appTheme, () => {

+ 1 - 1
src/hooks/echarts/candlestick/types.ts

@@ -77,7 +77,7 @@ export type CCI = {
  * 图表配置项
  */
 export interface EchartsOptions {
-    cycleType: Number; // 周期类型
+    cycleType: number; // 周期类型
     colors: Colors;
     candlestick: ECOption;
     macd: ECOption;

+ 1 - 1
src/hooks/echarts/timeline/dataset.ts

@@ -98,7 +98,7 @@ export function useDataset() {
     // 计算图表最高最低指标线
     const calcMarkLine = () => {
         const { close } = dataset.timeline.source;
-        const point = Math.pow(10, -dataset.decimal) * 10; // 图表上下保留10个报价点数
+        const point = Math.pow(10, -dataset.decimal) * 20; // 图表上下保留20个报价点数
         let max = Math.max(...close); // 取历史行情最高价
         let min = Math.min(...close); // 取历史行情最低价
 

+ 33 - 20
src/hooks/echarts/timeline/index.ts

@@ -64,32 +64,45 @@ export function useTimelineChart(goodscode: string) {
             const oldTime = lastIndex === -1 ? moment(lasttime) : moment(dataset.rawDate[lastIndex]) // 历史行情最后时间
             const diffTime = moment(lasttime).valueOf() - oldTime.valueOf() // 计算时间差
 
-            if (diffTime > cycleMilliseconds * 2) {
-                // 时间间隔超过两个周期,重新请求历史数据
-                //timerInterceptor.debounce(() => initData(), 1000, 'updateChart')
-            } else {
-                // 判断时间差是否大于周期时间
-                if (lastIndex === -1 || diffTime > cycleMilliseconds) {
-                    oldTime.add(cycleMilliseconds, 'ms')
-                    const lastDate = oldTime.format('YYYY-MM-DD HH:mm:ss')
-
-                    // 新增分时数据
-                    dataset.rawDate.push(lastDate)
-                    close.push(last)
-                    ma5.push('-')
-                } else {
-                    close[lastIndex] = last // 更新最后一条记录的收盘价
-                }
+            // if (diffTime > cycleMilliseconds * 2) {
+            //     // 时间间隔超过两个周期,重新请求历史数据,待优化
+            //     timerInterceptor.debounce(() => {
+            //         queryTSData({
+            //             data: {
+            //                 goodsCode: goodscode
+            //             }
+            //         }).then((res) => {
+            //             const { historyDatas } = res.data
+            //             if (historyDatas.length) {
+            //                 dataIndex.value = historyDatas.length - 1
+            //                 clearData()
+            //                 handleData(res.data, updateOptions)
+            //             }
+            //         })
+            //     }, 1000, 'updateChart')
+            // } else {
+            // 判断时间差是否大于周期时间
+            if (lastIndex === -1 || diffTime > cycleMilliseconds) {
+                oldTime.add(cycleMilliseconds, 'ms')
+                const lastDate = oldTime.format('YYYY-MM-DD HH:mm:ss')
 
-                // 更新各种指标
-                calcIndicator(lastIndex === -1 ? 0 : lastIndex)
-                updateOptions()
+                // 新增分时数据
+                dataset.rawDate.push(lastDate)
+                close.push(last)
+                ma5.push('-')
+            } else {
+                close[lastIndex] = last // 更新最后一条记录的收盘价
             }
+
+            // 更新各种指标
+            calcIndicator(lastIndex === -1 ? 0 : lastIndex)
+            updateOptions()
+            // }
         }
     }
 
     // 监听行情推送
-    watch(() => quote.value?.last, () => {
+    watch(() => quote.value, () => {
         if (!loading.value && !isEmpty.value) {
             updateChart()
         }

+ 2 - 2
src/hooks/echarts/timeline/options.ts

@@ -80,7 +80,7 @@ export function useOptions(dataset: EchartsDataset) {
             grid: {
                 left: '10px',
                 right: '10px',
-                top: '15px',
+                top: '20px',
                 bottom: '10px',
                 containLabel: true,
             },
@@ -243,7 +243,7 @@ export function useOptions(dataset: EchartsDataset) {
                 },
             ],
         }
-    }, 500)
+    }, 100)
 
     // 监听主题变化
     watch(appTheme, () => {

二進制
src/packages/gstj/assets/images/boot-1080p.png


二進制
src/packages/gstj/assets/images/boot-480p.png


二進制
src/packages/gstj/assets/images/boot-720p.png


二進制
src/packages/gstj/assets/images/hongbao-open.png


二進制
src/packages/gstj/assets/images/hongbao.png


二進制
src/packages/gstj/assets/images/level-bg.png


二進制
src/packages/gstj/assets/images/lottery/lottery-bg.png


二進制
src/packages/gstj/assets/images/lottery/lottery-hongbao.png


二進制
src/packages/gstj/assets/images/lottery/lottery-money.png


二進制
src/packages/gstj/assets/images/lottery/lottery-red-envelope.png


二進制
src/packages/gstj/assets/images/lottery/lottery-title.png


+ 10 - 0
src/packages/gstj/assets/themes/global/global.less

@@ -145,6 +145,12 @@
                 margin-bottom: .1rem;
             }
 
+            &__desc {
+                font-size: .24rem;
+                color: #999;
+                margin-bottom: .1rem;
+            }
+
             &__price {
                 color: #f2270c;
 
@@ -281,6 +287,10 @@
             }
         }
 
+        .desc {
+            padding: 0 .24rem;
+        }
+
         .qty {
             font-size: .24rem;
             color: #999;

+ 2 - 2
src/packages/gstj/views/account/certification/Index.vue

@@ -28,8 +28,8 @@
         </Form>
         <img src="../../../assets/images/certification.png" />
         <template #footer>
-            <div class="g-form__footer">
-                <Button type="primary" @click="formRef?.submit" round block>提交实名认证</Button>
+            <div class="g-form__footer inset">
+                <Button type="danger" @click="formRef?.submit" round block>提交实名认证</Button>
             </div>
         </template>
     </app-view>

+ 15 - 42
src/packages/gstj/views/goods/detail/components/listing/Index.vue

@@ -15,11 +15,10 @@
                                 :auto-fixed="false" :decimal-length="quote?.decimalplace" :step="priceStep" />
                         </template>
                     </Field>
-                    <Field name="OrderQty" :rules="formRules.OrderQty"
-                        :label="`数量(${getGoodsUnitName(quote?.goodunitid)})`">
+                    <Field name="OrderQty" :rules="formRules.OrderQty" label="数量">
                         <template #input>
                             <div class="goods-listing__stepper">
-                                <Stepper v-model="orderQty" theme="round" button-size="22" :min="0" :step="qtyStep"
+                                <Stepper v-model="formData.OrderQty" theme="round" button-size="22" :min="0" :step="qtyStep"
                                     integer />
                                 <RadioGroup v-model="qtyStep" direction="horizontal" @change="onRadioChange">
                                     <Radio v-for="(value, index) in qtyStepList" :key="index" :name="value">{{ value }}
@@ -42,13 +41,13 @@
                         <Button type="primary" block square @click="onBeforeSubmit(BuyOrSell.Sell)">订立卖出</Button>
                     </template>
                     <template v-if="buildType === EBuildType.BUILDTYPE_CLOSE">
-                        <Button type="danger" :disabled="(sellQty === 0) || (orderQty > sellQty)" block square
-                            @click="onBeforeSubmit(BuyOrSell.Buy)">
+                        <Button type="danger" :disabled="!formData.OrderQty || !sellQty || (formData.OrderQty > sellQty)"
+                            block square @click="onBeforeSubmit(BuyOrSell.Buy)">
                             <span>转让买入</span>
                             <span v-if="sellQty">(≤{{ sellQty }})</span>
                         </Button>
-                        <Button type="primary" :disabled="(buyQty === 0) || (orderQty > buyQty)" block square
-                            @click="onBeforeSubmit(BuyOrSell.Sell)">
+                        <Button type="primary" :disabled="!formData.OrderQty || !buyQty || (formData.OrderQty > buyQty)"
+                            block square @click="onBeforeSubmit(BuyOrSell.Sell)">
                             <span>转让卖出</span>
                             <span v-if="buyQty">(≤{{ buyQty }})</span>
                         </Button>
@@ -63,7 +62,6 @@
 import { shallowRef, defineAsyncComponent, onMounted, computed } from 'vue'
 import { Form, FormInstance, Button, CellGroup, FieldRule, Field, Stepper, RadioGroup, Radio } from 'vant'
 import { fullloading, dialog } from '@/utils/vant'
-import { getGoodsUnitName } from '@/constants/unit'
 import { BuyOrSell } from '@/constants/order'
 import { useOrder } from '@/business/trade'
 import { useRequest } from '@/hooks/request'
@@ -93,8 +91,8 @@ const quote = futuresStore.getQuoteInfo(props.goodsCode)
 const formRef = shallowRef<FormInstance>()
 const showModal = shallowRef(true)
 const refresh = shallowRef(true) // 是否刷新父组件数据
-const orderQty = shallowRef(1) // 数量
-const qtyStep = shallowRef(1) // 数量步长
+const qtyStepList = [1, 5, 10, 20, 30, 50] // 数量步长列表
+const qtyStep = shallowRef(qtyStepList[0]) // 数量步长
 
 const { dataList: positionList } = useRequest(queryTradePosition, {
     params: {
@@ -102,9 +100,6 @@ const { dataList: positionList } = useRequest(queryTradePosition, {
     },
 })
 
-// 合约乘数
-const agreeunit = computed(() => quote.value?.agreeunit ?? 0)
-
 // 价格步长
 const priceStep = computed(() => {
     const { quoteminunit = 0, decimalplace = 0 } = quote.value ?? {}
@@ -114,34 +109,16 @@ const priceStep = computed(() => {
     return 1
 })
 
-// 数量步长列表
-const qtyStepList = computed(() => {
-    return [
-        agreeunit.value * 1,
-        agreeunit.value * 5,
-        agreeunit.value * 10,
-        agreeunit.value * 20,
-        agreeunit.value * 30,
-        agreeunit.value * 50,
-    ]
-})
-
 // 买方向持仓数量
 const buyQty = computed(() => {
     const item = positionList.value.find((e) => e.goodscode === props.goodsCode && e.buyorsell === BuyOrSell.Buy)
-    if (item) {
-        return item.enableqty * agreeunit.value
-    }
-    return 0
+    return item?.enableqty ?? 0
 })
 
 // 卖方向持仓数量
 const sellQty = computed(() => {
     const item = positionList.value.find((e) => e.goodscode === props.goodsCode && e.buyorsell === BuyOrSell.Sell)
-    if (item) {
-        return item.enableqty * agreeunit.value
-    }
-    return 0
+    return item?.enableqty ?? 0
 })
 
 // 表单验证规则
@@ -153,11 +130,9 @@ const formRules: { [key in keyof Proto.OrderReq]?: FieldRule[] } = {
         }
     }],
     OrderQty: [{
+        message: '请输入数量',
         validator: () => {
-            if (orderQty.value) {
-                return orderQty.value % agreeunit.value === 0 ? true : '只能输入合约乘数的整数倍'
-            }
-            return '请输入数量'
+            return !!formData.OrderQty
         }
     }],
 }
@@ -215,7 +190,7 @@ const onSellClick = (index: number) => {
 }
 
 const onRadioChange = (value: number) => {
-    orderQty.value = value
+    formData.OrderQty = value
 }
 
 // 提交挂牌
@@ -235,7 +210,6 @@ const onSubmit = () => {
         formData.TimevalidType = EValidType.VALIDTYPE_DR
         formData.OperateType = EOrderOperateType.ORDEROPERATETYPE_NORMAL
         formData.BuildType = props.buildType
-        formData.OrderQty = orderQty.value / agreeunit.value // 数量÷合约乘数
 
         fullloading((hideLoading) => {
             formSubmit().then(() => {
@@ -260,10 +234,9 @@ const closed = (isRefresh = true) => {
 }
 
 onMounted(() => {
-    const { last = 0, agreeunit = 0, presettle = 0 } = quote.value ?? {}
+    const { last = 0, presettle = 0 } = quote.value ?? {}
     formData.OrderPrice = last || presettle
-    orderQty.value = agreeunit
-    qtyStep.value = qtyStepList.value[0]
+    formData.OrderQty = qtyStep.value
 })
 
 // 暴露组件属性给父组件调用

+ 14 - 39
src/packages/gstj/views/goods/trade/components/delisting/index.vue

@@ -23,7 +23,7 @@
                     </Field>
                     <Field label="剩余数量">
                         <template #input>
-                            <span>{{ selectedRow.orderqty }} {{ getGoodsUnitName(quote?.goodunitid) }}</span>
+                            <span>{{ selectedRow.orderqty }}</span>
                         </template>
                     </Field>
                     <Field label="摘牌方向">
@@ -34,7 +34,7 @@
                     <Field name="OrderQty" :rules="formRules.OrderQty" label="摘牌数量">
                         <template #input>
                             <div class="goods-delisting__stepper">
-                                <Stepper v-model="orderQty" theme="round" button-size="22" :min="0" :step="qtyStep"
+                                <Stepper v-model="formData.OrderQty" theme="round" button-size="22" :min="0" :step="qtyStep"
                                     :max="selectedRow.orderqty" integer />
                                 <RadioGroup v-model="qtyStep" direction="horizontal" @change="onRadioChange">
                                     <Radio v-for="(value, index) in qtyStepList" :key="index" :name="value">{{ value }}
@@ -54,16 +54,16 @@
                 <div class="g-form__footer">
                     <template v-if="selectedRow.buyorsell === BuyOrSell.Buy">
                         <Button type="danger" block square @click="onBeforeSubmit(EBuildType.BUILDTYPE_OPEN)">订立卖出</Button>
-                        <Button type="primary" :disabled="(buyQty === 0) || (orderQty > buyQty)" block square
-                            @click="onBeforeSubmit(EBuildType.BUILDTYPE_CLOSE)">
+                        <Button type="primary" :disabled="!formData.OrderQty || !buyQty || (formData.OrderQty > buyQty)"
+                            block square @click="onBeforeSubmit(EBuildType.BUILDTYPE_CLOSE)">
                             <span>转让卖出</span>
                             <span v-if="buyQty">(≤{{ buyQty }})</span>
                         </Button>
                     </template>
                     <template v-if="selectedRow.buyorsell === BuyOrSell.Sell">
                         <Button type="danger" block square @click="onBeforeSubmit(EBuildType.BUILDTYPE_OPEN)">订立买入</Button>
-                        <Button type="primary" :disabled="(sellQty === 0) || (orderQty > sellQty)" block square
-                            @click="onBeforeSubmit(EBuildType.BUILDTYPE_CLOSE)">
+                        <Button type="primary" :disabled="!formData.OrderQty || !sellQty || (formData.OrderQty > sellQty)"
+                            block square @click="onBeforeSubmit(EBuildType.BUILDTYPE_CLOSE)">
                             <span>转让买入</span>
                             <span v-if="sellQty">(≤{{ sellQty }})</span>
                         </Button>
@@ -79,7 +79,6 @@ import { shallowRef, PropType, onMounted, computed } from 'vue'
 import { Form, FormInstance, Button, CellGroup, Field, FieldRule, Stepper, RadioGroup, Radio } from 'vant'
 import { fullloading, dialog } from '@/utils/vant'
 import { BuyOrSell, getBuyOrSellName } from '@/constants/order'
-import { getGoodsUnitName } from '@/constants/unit'
 import { useAccountStore, useFuturesStore } from '@/stores'
 import { EBuildType, EDelistingType, EListingSelectType, EOrderOperateType, EPriceMode, EValidType } from '@/constants/client'
 import { useOrder } from '@/business/trade'
@@ -102,8 +101,8 @@ const quote = futuresStore.getQuoteInfo(props.selectedRow.goodsid)
 const formRef = shallowRef<FormInstance>()
 const showModal = shallowRef(true)
 const refresh = shallowRef(false) // 是否刷新父组件数据
-const orderQty = shallowRef(1) // 数量
-const qtyStep = shallowRef(1) // 数量步长
+const qtyStepList = [1, 5, 10, 20, 30, 50] // 数量步长列表
+const qtyStep = shallowRef(qtyStepList[0]) // 数量步长
 
 const { dataList: positionList } = useRequest(queryTradePosition, {
     params: {
@@ -111,53 +110,30 @@ const { dataList: positionList } = useRequest(queryTradePosition, {
     },
 })
 
-// 合约乘数
-const agreeunit = computed(() => quote.value?.agreeunit ?? 0)
-
-// 数量步长列表
-const qtyStepList = computed(() => {
-    return [
-        agreeunit.value * 1,
-        agreeunit.value * 5,
-        agreeunit.value * 10,
-        agreeunit.value * 20,
-        agreeunit.value * 30,
-        agreeunit.value * 50,
-    ]
-})
-
 // 买方向持仓数量
 const buyQty = computed(() => {
     const item = positionList.value.find((e) => e.goodsid === props.selectedRow.goodsid && e.buyorsell === BuyOrSell.Buy)
-    if (item) {
-        return item.enableqty * agreeunit.value
-    }
-    return 0
+    return item?.enableqty ?? 0
 })
 
 // 卖方向持仓数量
 const sellQty = computed(() => {
     const item = positionList.value.find((e) => e.goodsid === props.selectedRow.goodsid && e.buyorsell === BuyOrSell.Sell)
-    if (item) {
-        return item.enableqty * agreeunit.value
-    }
-    return 0
+    return item?.enableqty ?? 0
 })
 
 // 表单验证规则
 const formRules: { [key in keyof Proto.OrderReq]?: FieldRule[] } = {
     OrderQty: [{
+        message: '请输入摘牌数量',
         validator: () => {
-            if (orderQty.value) {
-                return orderQty.value % agreeunit.value === 0 ? true : '只能输入合约乘数的整数倍'
-            }
-            return '请输入摘牌数量'
+            return !!formData.OrderQty
         }
     }],
 }
 
 const onRadioChange = (value: number) => {
-    orderQty.value = value
+    formData.OrderQty = value
 }
 
 // 提交摘牌
@@ -181,7 +157,6 @@ const onSubmit = () => {
         formData.DelistingType = EDelistingType.DELISTINGTYPE_SELECTED
         formData.TimevalidType = EValidType.VALIDTYPE_DR
         formData.OperateType = EOrderOperateType.ORDEROPERATETYPE_NORMAL
-        formData.OrderQty = orderQty.value / agreeunit.value // 数量÷合约乘数
 
         fullloading((hideLoading) => {
             formSubmit().then(() => {
@@ -206,7 +181,7 @@ const closed = (isRefresh = false) => {
 }
 
 onMounted(() => {
-    orderQty.value = agreeunit.value
+    formData.OrderQty = qtyStep.value
 })
 
 // 暴露组件属性给父组件调用

+ 15 - 19
src/packages/gstj/views/goods/trade/index.vue

@@ -1,14 +1,17 @@
 <template>
     <app-view class="g-form">
         <template #header>
-            <app-navbar :title="quote ? quote.goodscode + '/' + quote.goodsname : '买卖大厅'" />
+            <app-navbar :title="quote ? quote.goodscode + '/' + quote.goodsname : '买卖大厅'">
+                <template #footer>
+                    <Tabs v-model:active="tabIndex" @click="onRefresh">
+                        <Tab title="卖大厅" :name="BuyOrSell.Sell" />
+                        <Tab title="买大厅" :name="BuyOrSell.Buy" />
+                    </Tabs>
+                </template>
+            </app-navbar>
         </template>
         <app-pull-refresh ref="pullRefreshRef" v-model:loading="loading" v-model:error="error" v-model:pageIndex="pageIndex"
             :page-count="pageCount" @refresh="onRefresh">
-            <Tabs v-model:active="tabIndex" @click="onTabChange">
-                <Tab title="卖大厅" :name="BuyOrSell.Sell" />
-                <Tab title="买大厅" :name="BuyOrSell.Buy" />
-            </Tabs>
             <div class="trade-section sell" v-if="dataList.length">
                 <app-list :columns="columns" :data-list="dataList">
                     <template #username="{ row }">
@@ -29,7 +32,7 @@
 </template>
 
 <script lang="ts" setup>
-import { shallowRef, defineAsyncComponent } from 'vue'
+import { shallowRef, defineAsyncComponent, watch } from 'vue'
 import { showToast, Tabs, Tab, Button } from 'vant'
 import { useNavigation } from '../../../router/navigation'
 import { useComponent } from '@/hooks/component'
@@ -63,20 +66,13 @@ const columns: Model.TableColumn[] = [
     { prop: 'operate', label: '摘牌' },
 ]
 
-const { componentRef, componentId, openComponent, closeComponent } = useComponent(() => onTabChange())
+const { componentRef, componentId, openComponent, closeComponent } = useComponent(() => onRefresh())
 
 const { pageIndex, loading, run, pageCount } = useRequest(queryWrTradeOrderDetail, {
     params: {
-        pagesize: 20,
         goodsid,
         buyorsell: tabIndex.value
     },
-    onSuccess: (res) => {
-        if (pageIndex.value === 1) {
-            dataList.value = []
-        }
-        dataList.value.push(...res.data)
-    },
     onError: () => {
         error.value = true
     }
@@ -88,11 +84,6 @@ const onRefresh = () => {
     })
 }
 
-const onTabChange = () => {
-    pageIndex.value = 1
-    onRefresh()
-}
-
 const onDelisting = (row: Model.WrTradeOrderDetailRsp) => {
     selectedRow.value = row
     /// 不能与自己成交
@@ -102,4 +93,9 @@ const onDelisting = (row: Model.WrTradeOrderDetailRsp) => {
     }
     openComponent('delisting')
 }
+
+// 监听行情变动
+watch(() => quote.value, () => {
+    onRefresh()
+})
 </script>

+ 0 - 25
src/packages/gstj/views/home/main/Index.vue

@@ -30,39 +30,14 @@
 import { shallowRef } from "vue";
 import { Cell, CellGroup, PullRefresh } from "vant";
 import { formatDate } from "@/filters";
-import { useNavigation } from '../../../router/navigation';
 import { queryImageConfigs } from "@/services/api/common";
 import { queryNewTitles } from "@/services/api/news";
-import { useLoginStore } from '@/stores'
 import Banner from '../../../components/base/banner/index.vue'
-import Iconfont from '../../../components/base/iconfont/index.vue'
 
-const loginStore = useLoginStore();
-const { routerTo, setGlobalUrlParams } = useNavigation();
 const refreshing = shallowRef(false); // 是否处于加载中状态
 const topBanners = shallowRef<string[]>([]); // 轮播图列表
 const newsList = shallowRef<Model.NewTitlesRsp[]>([]); // 资讯列表
 
-// 跳转导航页面
-const switchTab = (tabIndex: number) => {
-  if (loginStore.token) {
-    setGlobalUrlParams({ tabIndex })
-    switch (tabIndex) {
-      case 1:
-        routerTo('home-presale', true)
-        break
-      case 2:
-        routerTo('home-transfer', true)
-        break
-      case 3:
-        routerTo('home-goods', true)
-        break
-    }
-  } else {
-    routerTo('user-login')
-  }
-}
-
 // 下拉刷新
 const onRefresh = () => {
   if (!topBanners.value.length) {

+ 3 - 3
src/packages/gstj/views/mine/Index.vue

@@ -13,7 +13,8 @@
                         <div class="profile-user__info">
                             <div class="top">
                                 <span>{{ userStore.accountName }}</span>
-                                <Icon name="checked" color="var(--van-tag-success-color)" v-if="authStatus" />
+                                <Icon name="checked" color="var(--van-tag-success-color)"
+                                    v-if="authStatus === AuthStatus.Certified" />
                                 <Icon name="warning" color="var(--van-tag-warning-color)" v-else />
                             </div>
                             <div class="bottom">{{ loginStore.loginId }}</div>
@@ -68,8 +69,7 @@
         </app-block>
         <app-block class="g-navmenu">
             <CellGroup>
-                <Cell is-link :to="{ name: 'account-certification' }"
-                    v-if="[AuthStatus.Uncertified, AuthStatus.Rejected].includes(authStatus)">
+                <Cell is-link :to="{ name: 'account-certification' }" v-if="authStatus !== AuthStatus.Certified">
                     <template #title>
                         <Iconfont icon="icon-shimingrenzheng">实名认证</Iconfont>
                     </template>

+ 1 - 1
src/packages/gstj/views/order/delivery/components/offline/detail/Index.vue

@@ -7,7 +7,7 @@
             </template>
             <div class="g-form__container">
                 <CellGroup title="线下交收单信息">
-                    <Cell title="商品代码/名称" :value="selectedRow.goodscode+'/'+selectedRow.goodsnamedisplay" />
+                    <Cell title="商品代码/名称" :value="selectedRow.goodsnamedisplay" />
                     <Cell title="交收方向" :value="selectedRow.buyorselldisplay" />
                     <Cell title="交收数量" :value="selectedRow.deliveryqty" />
                     <Cell title="交收价格" :value="selectedRow.deliveryprice" />

+ 15 - 14
src/packages/gstj/views/spot/detail/Index.vue

@@ -6,7 +6,10 @@
         <Banner :data-list="topBanners" />
         <div class="g-detail__buy" v-if="quoteItem">
             <div class="title">
-                <span>{{ quoteItem.wrstandardname }}</span>
+                <span>{{ quoteItem.wrstandardcode }} / {{ quoteItem.wrstandardname }}</span>
+            </div>
+            <div class="desc">
+                <span>{{ quoteItem.warehousename }}</span>
             </div>
             <div class="info">
                 <ul>
@@ -26,16 +29,12 @@
                         <span>买量</span>
                         <span>{{ quoteItem.buyqty }}</span>
                     </li>
-                    <li>
-                        <span>仓库</span>
-                        <span>{{ quoteItem.warehousename }}</span>
-                    </li>
                 </ul>
             </div>
         </div>
         <div class="trade">
             <div class="trade-section sell" v-if="sellList.length">
-                <Cell title="卖" />
+                <Cell title="卖出挂牌" />
                 <app-list :columns="columns" :data-list="sellList">
                     <template #operate="{ row }">
                         <Button size="small" round @click="delistingListing(row, BuyOrSell.Buy)">买入</Button>
@@ -43,7 +42,7 @@
                 </app-list>
             </div>
             <div class="trade-section buy" v-if="buyList.length">
-                <Cell title="买" />
+                <Cell title="买入挂牌" />
                 <app-list :columns="columns" :data-list="buyList">
                     <template #operate="{ row }">
                         <Button size="small" round @click="delistingListing(row, BuyOrSell.Sell)">卖出</Button>
@@ -57,16 +56,18 @@
             </template>
         </div>
         <template #footer>
-            <div class="g-detail__footer">
-                <div class="price" v-if="quoteItem">
+            <div class="g-form__footer">
+                <!-- <div class="price" v-if="quoteItem">
                     <span class="price-text">参考价:</span>
                     <span class="price-unit">¥</span>
                     <span class="price-integer">{{ quoteItem.spotgoodsprice }}</span>
-                </div>
-                <div class="submit">
-                    <span class="submit-button warning" @click="toggleListing(BuyOrSell.Sell)">我要卖</span>
-                    <span class="submit-button danger" @click="toggleListing(BuyOrSell.Buy)">我要买</span>
-                </div>
+                </div> -->
+                <!-- <div class="submit"> -->
+                <Button block type="primary" square class="submit-button warning"
+                    @click="toggleListing(BuyOrSell.Sell)">我要卖</Button>
+                <Button block type="danger" square class="submit-button danger"
+                    @click="toggleListing(BuyOrSell.Buy)">我要买</Button>
+                <!-- </div> -->
             </div>
             <component ref="componentRef" :is="componentMap.get(componentId)" v-bind="{ quoteItem, quoteDetail, buyorsell }"
                 @closed="closeComponent" v-if="componentId" />

+ 2 - 1
src/packages/gstj/views/spot/detail/components/listing/index.vue

@@ -37,7 +37,8 @@
             </Field>
         </Form>
         <template #footer>
-            <Button type="danger" block round @click="formRef?.submit">确定</Button>
+            <Button :type="buyorsell === BuyOrSell.Sell ? 'primary' : 'danger'" block round
+                @click="formRef?.submit">确定</Button>
         </template>
     </app-popup>
 </template>

+ 4 - 3
src/packages/gstj/views/spot/list/Index.vue

@@ -17,13 +17,14 @@
                             <img :src="getFirstImage(item.thumurls)" />
                         </div>
                         <div class="goods-info">
-                            <div class="goods-info__title">{{ item.wrstandardname }}</div>
-                            <div class="goods-info__price">
+                            <div class="goods-info__title">{{ item.wrstandardcode }} / {{ item.wrstandardname }}</div>
+                            <div class="goods-info__desc">{{ item.warehousename }}</div>
+                            <div class="goods-info__price" v-if="item.sellprice">
                                 <Tag type="danger" plain>卖价</Tag>
                                 <span class="unit">¥</span>
                                 <span class="integer">{{ item.sellprice }}</span>
                             </div>
-                            <div class="goods-info__price">
+                            <div class="goods-info__price" v-if="item.buyprice">
                                 <Tag type="warning" plain>买价</Tag>
                                 <span class="unit">¥</span>
                                 <span class="integer">{{ item.buyprice }}</span>

二進制
src/packages/mobile/assets/images/boot-1080p.png


二進制
src/packages/mobile/assets/images/boot-480p.png


二進制
src/packages/mobile/assets/images/boot-720p.png


+ 10 - 0
src/packages/mobile/assets/themes/global/global.less

@@ -145,6 +145,12 @@
                 margin-bottom: .1rem;
             }
 
+            &__desc {
+                font-size: .24rem;
+                color: #999;
+                margin-bottom: .1rem;
+            }
+
             &__price {
                 color: #f2270c;
 
@@ -281,6 +287,10 @@
             }
         }
 
+        .desc {
+            padding: 0 .24rem;
+        }
+
         .qty {
             font-size: .24rem;
             color: #999;

+ 2 - 2
src/packages/mobile/components/modules/quote/price/index.vue

@@ -14,7 +14,7 @@
                 <ul>
                     <li>
                         <span>开盘</span>
-                        <span>{{ handleNumberValue(quote.opened) }}</span>
+                        <span :class="quote.openedColor">{{ handleNumberValue(quote.opened) }}</span>
                     </li>
                     <li>
                         <span>最高</span>
@@ -62,7 +62,7 @@
                 </li>
                 <li>
                     <span>均价</span>
-                    <span>{{ handleNumberValue(quote.averageprice) }}</span>
+                    <span :class="quote.averagepriceColor">{{ handleNumberValue(quote.averageprice) }}</span>
                 </li>
                 <li>
                     <span>振幅</span>

+ 2 - 2
src/packages/mobile/views/account/certification/Index.vue

@@ -28,8 +28,8 @@
         </Form>
         <img src="../../../assets/images/certification.png" />
         <template #footer>
-            <div class="g-form__footer">
-                <Button type="primary" @click="formRef?.submit" round block>提交实名认证</Button>
+            <div class="g-form__footer inset">
+                <Button type="danger" @click="formRef?.submit" round block>提交实名认证</Button>
             </div>
         </template>
     </app-view>

+ 8 - 3
src/packages/mobile/views/ballot/detail/components/delisting/index.vue

@@ -12,6 +12,11 @@
                         :auto-fixed="false" integer />
                 </template>
             </Field>
+            <Field label="最大申购量">
+                <template #input>
+                    <span>{{ detail.buymaxqty }}</span>
+                </template>
+            </Field>
             <Field label="预售定金">
                 <template #input>
                     <span>{{ deposit }}</span>
@@ -57,11 +62,11 @@ const formRules: { [key in keyof Proto.OrderReq]?: FieldRule[] } = {
     OrderQty: [{
         message: '请输入数量',
         validator: (val) => {
-            const enable = props.detail.presaleqty - props.detail.presaledqty
-            if (val <= enable) {
+            const buymaxqty = props.detail.buymaxqty
+            if (val <= buymaxqty) {
                 return true
             }
-            return '委托数量不能大于' + `${enable}`
+            return '委托数量不能大于' + `${buymaxqty}`
         }
     }],
 }

+ 19 - 8
src/packages/mobile/views/bank/sign/Index.vue

@@ -20,30 +20,34 @@
             <div class="g-form__footer" v-if="bankInfo">
                 <Button type="warning" round block @click="formSubmit"
                     v-if="bankInfo.signstatus === SignStatus.Signed">解约</Button>
-                <Button type="danger" round block @click="openComponent('edit')"
-                    v-if="[SignStatus.Unsigned, SignStatus.Refuse, SignStatus.Signed].includes(bankInfo.signstatus)">修改</Button>
+                <Button type="danger" round block @click="showComponent('edit')"
+                    v-if="[SignStatus.Unsigned, SignStatus.Refuse, SignStatus.Signed, SignStatus.Rescinded].includes(bankInfo.signstatus)">修改</Button>
             </div>
         </template>
-        <component ref="componentRef" :is="componentMap.get(componentId)" @closed="closeComponent" v-if="componentId" />
+        <component ref="componentRef" v-bind="{ isedit }" :is="componentMap.get(componentId)" @closed="closeComponent" v-if="componentId" />
     </app-view>
 </template>
 
 <script lang="ts" setup>
-import { onActivated, defineAsyncComponent } from 'vue'
+import { defineAsyncComponent, onActivated } from 'vue'
 import { CellGroup, Cell, Button, Empty, showFailToast } from 'vant'
 import { fullloading, dialog } from '@/utils/vant'
 import { useComponent } from '@/hooks/component'
 import { getSignStatusName, SignStatus } from '@/constants/bank'
 import { useDoCancelBankSign } from '@/business/bank'
 import { useNavigation } from '../../../router/navigation'
+import { useErrorInfoStore } from '@/stores'
+import { shallowRef } from 'vue'
 
 const componentMap = new Map<string, unknown>([
     ['edit', defineAsyncComponent(() => import('./components/edit/Index.vue'))],
 ])
 
-const { componentRef, componentId, openComponent, closeComponent } = useComponent(() => formRefresh())
-const { cancelSubmit, formRefresh, bankInfo } = useDoCancelBankSign()
+const { componentRef, componentId, openComponent, closeComponent } = useComponent()
+const { cancelSubmit, bankInfo, formRefresh } = useDoCancelBankSign()
 const { router } = useNavigation()
+/// 是否为编辑
+const isedit = shallowRef(false)
 
 const formSubmit = () => {
     dialog({
@@ -53,17 +57,24 @@ const formSubmit = () => {
         fullloading((hideLoading) => {
             cancelSubmit().then(() => {
                 hideLoading()
-                dialog('约提交成功,请耐心等待审核。').then(() => {
+                dialog('约提交成功,请耐心等待审核。').then(() => {
                     router.back()
                 })
             }).catch((err) => {
-                showFailToast(err)
+                const { getErrorInfoByCode } = useErrorInfoStore()
+                showFailToast(getErrorInfoByCode(Number(err)) ?? '')
             })
         })
     })
 }
 
+const showComponent = (code: string) => {
+    isedit.value = true
+    openComponent(code)
+}
+
 onActivated(() => formRefresh())
+
 </script>
 
 <style lang="less">

+ 12 - 3
src/packages/mobile/views/bank/sign/components/edit/Index.vue

@@ -2,7 +2,7 @@
     <app-modal direction="right" height="100%" v-model:show="showModal" :refresh="refresh">
         <app-view class="g-form">
             <template #header>
-                <app-navbar :title="bankInfo ? '修改签约账户' : '添加签约账户'" @back="closed" />
+                <app-navbar :title="isedit ? '修改签约账户' : '添加签约账户'" @back="closed" />
             </template>
             <Form ref="formRef" class="g-form__container" @submit="formSubmit">
                 <CellGroup inset>
@@ -37,6 +37,7 @@ import { fullloading, dialog } from '@/utils/vant'
 import { useDoBankSign } from '@/business/bank'
 import AppSelect from '../../../../../components/base/select/index.vue'
 import { validateRules } from '@/constants/regex'
+import { useErrorInfoStore } from '@/stores'
 import AppModal from '@/components/base/modal/index.vue'
 
 const { formData, onSubmit, banklist, bankInfo } = useDoBankSign()
@@ -44,6 +45,13 @@ const showModal = shallowRef(true)
 const refresh = shallowRef(false) // 是否刷新父组件数据
 const formRef = shallowRef<FormInstance>()
 
+const props = defineProps({
+    isedit: {
+        type: Boolean,
+        required: true,
+    }
+})
+
 // 表单验证规则
 const formRules: { [key in keyof Proto.t2bBankSignReq]?: FieldRule[] } = {
     OpenBankAccId: [{
@@ -76,11 +84,12 @@ const formSubmit = () => {
     fullloading((hideLoading) => {
         onSubmit().then(() => {
             hideLoading()
-            dialog(bankInfo ? '签约信息修改成功' : '签约提交成功,请耐心等待审核。').then(() => {
+            dialog(props.isedit ? '签约信息修改提交成功' : '签约提交成功,请耐心等待审核。').then(() => {
                 closed(true)
             })
         }).catch((err) => {
-            showFailToast(err)
+            const { getErrorInfoByCode } = useErrorInfoStore()
+            showFailToast(getErrorInfoByCode(Number(err)) ?? '')
         })
     })
 }

+ 14 - 41
src/packages/mobile/views/goods/detail/components/listing/Index.vue

@@ -15,11 +15,10 @@
                                 :auto-fixed="false" :decimal-length="quote?.decimalplace" :step="priceStep" />
                         </template>
                     </Field>
-                    <Field name="OrderQty" :rules="formRules.OrderQty"
-                        :label="`数量(${getGoodsUnitName(quote?.goodunitid)})`">
+                    <Field name="OrderQty" :rules="formRules.OrderQty" label="数量">
                         <template #input>
                             <div class="goods-listing__stepper">
-                                <Stepper v-model="orderQty" theme="round" button-size="22" :min="0" :step="qtyStep"
+                                <Stepper v-model="formData.OrderQty" theme="round" button-size="22" :min="0" :step="qtyStep"
                                     integer />
                                 <RadioGroup v-model="qtyStep" direction="horizontal" @change="onRadioChange">
                                     <Radio v-for="(value, index) in qtyStepList" :key="index" :name="value">{{ value }}
@@ -42,13 +41,13 @@
                         <Button type="primary" block square @click="onBeforeSubmit(BuyOrSell.Sell)">订立卖出</Button>
                     </template>
                     <template v-if="buildType === EBuildType.BUILDTYPE_CLOSE">
-                        <Button type="danger" :disabled="(sellQty === 0) || (orderQty > sellQty)" block square
-                            @click="onBeforeSubmit(BuyOrSell.Buy)">
+                        <Button type="danger" :disabled="!formData.OrderQty || !sellQty || (formData.OrderQty > sellQty)"
+                            block square @click="onBeforeSubmit(BuyOrSell.Buy)">
                             <span>转让买入</span>
                             <span v-if="sellQty">(≤{{ sellQty }})</span>
                         </Button>
-                        <Button type="primary" :disabled="(buyQty === 0) || (orderQty > buyQty)" block square
-                            @click="onBeforeSubmit(BuyOrSell.Sell)">
+                        <Button type="primary" :disabled="!formData.OrderQty || !buyQty || (formData.OrderQty > buyQty)"
+                            block square @click="onBeforeSubmit(BuyOrSell.Sell)">
                             <span>转让卖出</span>
                             <span v-if="buyQty">(≤{{ buyQty }})</span>
                         </Button>
@@ -63,7 +62,6 @@
 import { shallowRef, defineAsyncComponent, onMounted, computed } from 'vue'
 import { Form, FormInstance, Button, CellGroup, FieldRule, Field, Stepper, RadioGroup, Radio } from 'vant'
 import { fullloading, dialog } from '@/utils/vant'
-import { getGoodsUnitName } from '@/constants/unit'
 import { BuyOrSell } from '@/constants/order'
 import { useOrder } from '@/business/trade'
 import { useRequest } from '@/hooks/request'
@@ -93,8 +91,8 @@ const quote = futuresStore.getQuoteInfo(props.goodsCode)
 const formRef = shallowRef<FormInstance>()
 const showModal = shallowRef(true)
 const refresh = shallowRef(true) // 是否刷新父组件数据
-const orderQty = shallowRef(1) // 数量
-const qtyStep = shallowRef(1) // 数量步长
+const qtyStepList = [1, 5, 10, 20, 30, 50] // 数量步长列表
+const qtyStep = shallowRef(qtyStepList[0]) // 数量步长
 
 const { dataList: positionList } = useRequest(queryTradePosition, {
     params: {
@@ -102,9 +100,6 @@ const { dataList: positionList } = useRequest(queryTradePosition, {
     },
 })
 
-// 合约乘数
-const agreeunit = computed(() => quote.value?.agreeunit ?? 0)
-
 // 价格步长
 const priceStep = computed(() => {
     const { quoteminunit = 0, decimalplace = 0 } = quote.value ?? {}
@@ -114,34 +109,16 @@ const priceStep = computed(() => {
     return 1
 })
 
-// 数量步长列表
-const qtyStepList = computed(() => {
-    return [
-        agreeunit.value * 1,
-        agreeunit.value * 5,
-        agreeunit.value * 10,
-        agreeunit.value * 20,
-        agreeunit.value * 30,
-        agreeunit.value * 50,
-    ]
-})
-
 // 买方向持仓数量
 const buyQty = computed(() => {
     const item = positionList.value.find((e) => e.goodscode === props.goodsCode && e.buyorsell === BuyOrSell.Buy)
-    if (item) {
-        return item.enableqty * agreeunit.value
-    }
-    return 0
+    return item?.enableqty ?? 0
 })
 
 // 卖方向持仓数量
 const sellQty = computed(() => {
     const item = positionList.value.find((e) => e.goodscode === props.goodsCode && e.buyorsell === BuyOrSell.Sell)
-    if (item) {
-        return item.enableqty * agreeunit.value
-    }
-    return 0
+    return item?.enableqty ?? 0
 })
 
 // 表单验证规则
@@ -153,11 +130,9 @@ const formRules: { [key in keyof Proto.OrderReq]?: FieldRule[] } = {
         }
     }],
     OrderQty: [{
+        message: '请输入数量',
         validator: () => {
-            if (orderQty.value) {
-                return orderQty.value % agreeunit.value === 0 ? true : '只能输入合约乘数的整数倍'
-            }
-            return '请输入数量'
+            return !!formData.OrderQty
         }
     }],
 }
@@ -215,7 +190,7 @@ const onSellClick = (index: number) => {
 }
 
 const onRadioChange = (value: number) => {
-    orderQty.value = value
+    formData.OrderQty = value
 }
 
 // 提交挂牌
@@ -235,7 +210,6 @@ const onSubmit = () => {
         formData.TimevalidType = EValidType.VALIDTYPE_DR
         formData.OperateType = EOrderOperateType.ORDEROPERATETYPE_NORMAL
         formData.BuildType = props.buildType
-        formData.OrderQty = orderQty.value / agreeunit.value // 数量÷合约乘数
 
         fullloading((hideLoading) => {
             formSubmit().then(() => {
@@ -262,8 +236,7 @@ const closed = (isRefresh = true) => {
 onMounted(() => {
     const { last = 0, agreeunit = 0, presettle = 0 } = quote.value ?? {}
     formData.OrderPrice = last || presettle
-    orderQty.value = agreeunit
-    qtyStep.value = qtyStepList.value[0]
+    formData.OrderQty = qtyStep.value
 })
 
 // 暴露组件属性给父组件调用

+ 14 - 39
src/packages/mobile/views/goods/trade/components/delisting/index.vue

@@ -23,7 +23,7 @@
                     </Field>
                     <Field label="剩余数量">
                         <template #input>
-                            <span>{{ selectedRow.orderqty }} {{ getGoodsUnitName(quote?.goodunitid) }}</span>
+                            <span>{{ selectedRow.orderqty }}</span>
                         </template>
                     </Field>
                     <Field label="摘牌方向">
@@ -34,7 +34,7 @@
                     <Field name="OrderQty" :rules="formRules.OrderQty" label="摘牌数量">
                         <template #input>
                             <div class="goods-delisting__stepper">
-                                <Stepper v-model="orderQty" theme="round" button-size="22" :min="0" :step="qtyStep"
+                                <Stepper v-model="formData.OrderQty" theme="round" button-size="22" :min="0" :step="qtyStep"
                                     :max="selectedRow.orderqty" integer />
                                 <RadioGroup v-model="qtyStep" direction="horizontal" @change="onRadioChange">
                                     <Radio v-for="(value, index) in qtyStepList" :key="index" :name="value">{{ value }}
@@ -54,16 +54,16 @@
                 <div class="g-form__footer">
                     <template v-if="selectedRow.buyorsell === BuyOrSell.Buy">
                         <Button type="danger" block square @click="onBeforeSubmit(EBuildType.BUILDTYPE_OPEN)">订立卖出</Button>
-                        <Button type="primary" :disabled="(buyQty === 0) || (orderQty > buyQty)" block square
-                            @click="onBeforeSubmit(EBuildType.BUILDTYPE_CLOSE)">
+                        <Button type="primary" :disabled="!formData.OrderQty || !buyQty || (formData.OrderQty > buyQty)"
+                            block square @click="onBeforeSubmit(EBuildType.BUILDTYPE_CLOSE)">
                             <span>转让卖出</span>
                             <span v-if="buyQty">(≤{{ buyQty }})</span>
                         </Button>
                     </template>
                     <template v-if="selectedRow.buyorsell === BuyOrSell.Sell">
                         <Button type="danger" block square @click="onBeforeSubmit(EBuildType.BUILDTYPE_OPEN)">订立买入</Button>
-                        <Button type="primary" :disabled="(sellQty === 0) || (orderQty > sellQty)" block square
-                            @click="onBeforeSubmit(EBuildType.BUILDTYPE_CLOSE)">
+                        <Button type="primary" :disabled="!formData.OrderQty || !sellQty || (formData.OrderQty > sellQty)"
+                            block square @click="onBeforeSubmit(EBuildType.BUILDTYPE_CLOSE)">
                             <span>转让买入</span>
                             <span v-if="sellQty">(≤{{ sellQty }})</span>
                         </Button>
@@ -79,7 +79,6 @@ import { shallowRef, PropType, onMounted, computed } from 'vue'
 import { Form, FormInstance, Button, CellGroup, Field, FieldRule, Stepper, RadioGroup, Radio } from 'vant'
 import { fullloading, dialog } from '@/utils/vant'
 import { BuyOrSell, getBuyOrSellName } from '@/constants/order'
-import { getGoodsUnitName } from '@/constants/unit'
 import { useAccountStore, useFuturesStore } from '@/stores'
 import { EBuildType, EDelistingType, EListingSelectType, EOrderOperateType, EPriceMode, EValidType } from '@/constants/client'
 import { useOrder } from '@/business/trade'
@@ -102,8 +101,8 @@ const quote = futuresStore.getQuoteInfo(props.selectedRow.goodsid)
 const formRef = shallowRef<FormInstance>()
 const showModal = shallowRef(true)
 const refresh = shallowRef(false) // 是否刷新父组件数据
-const orderQty = shallowRef(1) // 数量
-const qtyStep = shallowRef(1) // 数量步长
+const qtyStepList = [1, 5, 10, 20, 30, 50] // 数量步长列表
+const qtyStep = shallowRef(qtyStepList[0]) // 数量步长
 
 const { dataList: positionList } = useRequest(queryTradePosition, {
     params: {
@@ -111,53 +110,30 @@ const { dataList: positionList } = useRequest(queryTradePosition, {
     },
 })
 
-// 合约乘数
-const agreeunit = computed(() => quote.value?.agreeunit ?? 0)
-
-// 数量步长列表
-const qtyStepList = computed(() => {
-    return [
-        agreeunit.value * 1,
-        agreeunit.value * 5,
-        agreeunit.value * 10,
-        agreeunit.value * 20,
-        agreeunit.value * 30,
-        agreeunit.value * 50,
-    ]
-})
-
 // 买方向持仓数量
 const buyQty = computed(() => {
     const item = positionList.value.find((e) => e.goodsid === props.selectedRow.goodsid && e.buyorsell === BuyOrSell.Buy)
-    if (item) {
-        return item.enableqty * agreeunit.value
-    }
-    return 0
+    return item?.enableqty ?? 0
 })
 
 // 卖方向持仓数量
 const sellQty = computed(() => {
     const item = positionList.value.find((e) => e.goodsid === props.selectedRow.goodsid && e.buyorsell === BuyOrSell.Sell)
-    if (item) {
-        return item.enableqty * agreeunit.value
-    }
-    return 0
+    return item?.enableqty ?? 0
 })
 
 // 表单验证规则
 const formRules: { [key in keyof Proto.OrderReq]?: FieldRule[] } = {
     OrderQty: [{
+        message: '请输入摘牌数量',
         validator: () => {
-            if (orderQty.value) {
-                return orderQty.value % agreeunit.value === 0 ? true : '只能输入合约乘数的整数倍'
-            }
-            return '请输入摘牌数量'
+            return !!formData.OrderQty
         }
     }],
 }
 
 const onRadioChange = (value: number) => {
-    orderQty.value = value
+    formData.OrderQty = value
 }
 
 // 提交摘牌
@@ -181,7 +157,6 @@ const onSubmit = () => {
         formData.DelistingType = EDelistingType.DELISTINGTYPE_SELECTED
         formData.TimevalidType = EValidType.VALIDTYPE_DR
         formData.OperateType = EOrderOperateType.ORDEROPERATETYPE_NORMAL
-        formData.OrderQty = orderQty.value / agreeunit.value // 数量÷合约乘数
 
         fullloading((hideLoading) => {
             formSubmit().then(() => {
@@ -206,7 +181,7 @@ const closed = (isRefresh = false) => {
 }
 
 onMounted(() => {
-    orderQty.value = agreeunit.value
+    formData.OrderQty = qtyStep.value
 })
 
 // 暴露组件属性给父组件调用

+ 15 - 19
src/packages/mobile/views/goods/trade/index.vue

@@ -1,14 +1,17 @@
 <template>
     <app-view class="g-form">
         <template #header>
-            <app-navbar :title="quote ? quote.goodscode + '/' + quote.goodsname : '买卖大厅'" />
+            <app-navbar :title="quote ? quote.goodscode + '/' + quote.goodsname : '买卖大厅'">
+                <template #footer>
+                    <Tabs v-model:active="tabIndex" @click="onRefresh">
+                        <Tab title="卖大厅" :name="BuyOrSell.Sell" />
+                        <Tab title="买大厅" :name="BuyOrSell.Buy" />
+                    </Tabs>
+                </template>
+            </app-navbar>
         </template>
         <app-pull-refresh ref="pullRefreshRef" v-model:loading="loading" v-model:error="error" v-model:pageIndex="pageIndex"
             :page-count="pageCount" @refresh="onRefresh">
-            <Tabs v-model:active="tabIndex" @click="onTabChange">
-                <Tab title="卖大厅" :name="BuyOrSell.Sell" />
-                <Tab title="买大厅" :name="BuyOrSell.Buy" />
-            </Tabs>
             <div class="trade-section sell" v-if="dataList.length">
                 <app-list :columns="columns" :data-list="dataList">
                     <template #username="{ row }">
@@ -29,7 +32,7 @@
 </template>
 
 <script lang="ts" setup>
-import { shallowRef, defineAsyncComponent } from 'vue'
+import { shallowRef, defineAsyncComponent, watch } from 'vue'
 import { showToast, Tabs, Tab, Button } from 'vant'
 import { useNavigation } from '../../../router/navigation'
 import { useComponent } from '@/hooks/component'
@@ -63,20 +66,13 @@ const columns: Model.TableColumn[] = [
     { prop: 'operate', label: '摘牌' },
 ]
 
-const { componentRef, componentId, openComponent, closeComponent } = useComponent(() => onTabChange())
+const { componentRef, componentId, openComponent, closeComponent } = useComponent(() => onRefresh())
 
 const { pageIndex, loading, run, pageCount } = useRequest(queryWrTradeOrderDetail, {
     params: {
-        pagesize: 20,
         goodsid,
         buyorsell: tabIndex.value
     },
-    onSuccess: (res) => {
-        if (pageIndex.value === 1) {
-            dataList.value = []
-        }
-        dataList.value.push(...res.data)
-    },
     onError: () => {
         error.value = true
     }
@@ -88,11 +84,6 @@ const onRefresh = () => {
     })
 }
 
-const onTabChange = () => {
-    pageIndex.value = 1
-    onRefresh()
-}
-
 const onDelisting = (row: Model.WrTradeOrderDetailRsp) => {
     selectedRow.value = row
     /// 不能与自己成交
@@ -102,4 +93,9 @@ const onDelisting = (row: Model.WrTradeOrderDetailRsp) => {
     }
     openComponent('delisting')
 }
+
+// 监听行情变动
+watch(() => quote.value, () => {
+    onRefresh()
+})
 </script>

+ 3 - 3
src/packages/mobile/views/mine/Index.vue

@@ -13,7 +13,8 @@
                         <div class="profile-user__info">
                             <div class="top">
                                 <span>{{ userStore.accountName }}</span>
-                                <Icon name="checked" color="var(--van-tag-success-color)" v-if="authStatus" />
+                                <Icon name="checked" color="var(--van-tag-success-color)"
+                                    v-if="authStatus === AuthStatus.Certified" />
                                 <Icon name="warning" color="var(--van-tag-warning-color)" v-else />
                             </div>
                             <div class="bottom">{{ loginStore.loginId }}</div>
@@ -68,8 +69,7 @@
         </app-block>
         <app-block class="g-navmenu">
             <CellGroup>
-                <Cell is-link :to="{ name: 'account-certification' }"
-                    v-if="[AuthStatus.Uncertified, AuthStatus.Rejected].includes(authStatus)">
+                <Cell is-link :to="{ name: 'account-certification' }" v-if="authStatus !== AuthStatus.Certified">
                     <template #title>
                         <Iconfont icon="icon-shimingrenzheng">实名认证</Iconfont>
                     </template>

+ 3 - 3
src/packages/mobile/views/order/delivery/components/offline/detail/Index.vue

@@ -7,11 +7,11 @@
             </template>
             <div class="g-form__container">
                 <CellGroup title="线下交收单信息">
-                    <Cell title="商品代码/名称" :value="selectedRow.goodscode+'/'+selectedRow.goodsnamedisplay" />
+                    <Cell title="商品代码/名称" :value="selectedRow.goodsnamedisplay" />
                     <Cell title="交收方向" :value="selectedRow.buyorselldisplay" />
                     <Cell title="交收数量" :value="selectedRow.deliveryqty" />
-                    <Cell title="交收价格" :value="selectedRow.deliveryprice" />
-                    <Cell title="交收货款" :value="selectedRow.deliveryamount" />
+                    <Cell title="交收价格" :value="selectedRow.orderstatus === 1 ? '--' : selectedRow.deliveryprice" />
+                    <Cell title="交收货款" :value="selectedRow.orderstatus === 1 ? '--' : selectedRow.deliveryamount" />
                     <Cell title="交收对手方" :value="selectedRow.matchusername" />
                     <Cell title="交收信息" :value="selectedRow.deliveryinfo" />
                     <Cell title="申请时间" :value="selectedRow.reqtime" />

+ 2 - 1
src/packages/mobile/views/order/list/components/goodsorder/detail/Index.vue

@@ -51,8 +51,9 @@ const onCancelSumit = () => {
         message: '确认要撤销吗?',
         showCancelButton: true,
     }).then(() => {
+        const { marketid, goodsid } = props.selectedRow
         /// 市场ID
-        formData.Header = { MarketID: props.selectedRow.marketid }
+        formData.Header = { MarketID: marketid, GoodsID: goodsid }
         formData.OldOrderId = props.selectedRow.orderid
 
         /// loding....

+ 2 - 2
src/packages/mobile/views/order/list/components/goodsorder/list/Index.vue

@@ -97,8 +97,8 @@ const onCancelSumit = (item: Model.TradeOrderDetailRsp) => {
         message: '确认要撤销吗?',
         showCancelButton: true,
     }).then(() => {
-
-        formData.Header = { MarketID: item.marketid, GoodsID: item.goodsid }
+        const { marketid, goodsid } = item
+        formData.Header = { MarketID: marketid, GoodsID: goodsid }
         formData.OldOrderId = item.orderid
 
         /// loding....

+ 2 - 2
src/packages/mobile/views/order/list/components/goodstrade/list/Index.vue

@@ -19,8 +19,8 @@
                             <span>{{ formatDate(item.tradetime, 'YYYY-MM-DD') }}</span>
                         </li>
                         <li>
-                            <span>类型</span>
-                            <span>{{ getBuildTypeName(item.buildtype) }}{{ getBuyOrSellName(item.buyorsell) }}</span>
+                            <span>类型/方向</span>
+                            <span>{{ getBuildTypeName(item.buildtype) }}/{{ getBuyOrSellName(item.buyorsell) }}</span>
                         </li>
                         <li>
                             <span>成交价格</span>

+ 2 - 1
src/packages/mobile/views/order/list/components/presale/detail/Index.vue

@@ -12,6 +12,7 @@
                     <Cell title="认购价" :value="selectedRow.orderprice" />
                     <Cell title="认购金额" :value="(selectedRow.orderprice * selectedRow.orderqty).toFixed(2)" />
                     <Cell title="定金方式" :value="selectedRow.presaledepositalgorithm === 1 ? '比率' : '固定'" />
+                    <Cell title="定金比例" :value="parsePercent(selectedRow.presaledepositvalue)" />
                     <Cell title="预售定金" :value="selectedRow.freezemargin" />
                     <Cell title="发售方" :value="selectedRow.sellname" />
                     <Cell title="开始日期" :value="formatDate(selectedRow.starttime, 'YYYY-MM-DD')" />
@@ -30,7 +31,7 @@
 <script lang="ts" setup>
 import { shallowRef, PropType } from 'vue'
 import { CellGroup, Cell } from 'vant'
-import { handleNumberValue, formatDate } from '@/filters'
+import { handleNumberValue, formatDate, parsePercent } from '@/filters'
 import { getOrderStatusName } from '@/constants/order'
 import AppModal from '@/components/base/modal/index.vue'
 

+ 3 - 1
src/packages/mobile/views/order/list/components/pricingorder/detail/Index.vue

@@ -46,12 +46,14 @@ const props = defineProps({
 })
 
 const onCancelSumit = () => {
+    console.log('goodsid')
     dialog({
         message: '确认要撤销吗?',
         showCancelButton: true,
     }).then(() => {
+        const { marketid, goodsid } = props.selectedRow
         /// 市场ID
-        formData.Header = { MarketID: props.selectedRow.marketid }
+        formData.Header = { MarketID: marketid, GoodsID: goodsid }
         formData.OldOrderId = props.selectedRow.orderid
 
         /// loding....

+ 1 - 1
src/packages/mobile/views/order/list/components/transferorder/detail/Index.vue

@@ -26,7 +26,7 @@
 
 <script lang="ts" setup>
 import { shallowRef, PropType } from 'vue'
-import { CellGroup, Cell } from 'vant'
+import { CellGroup, Cell, Button } from 'vant'
 import AppModal from '@/components/base/modal/index.vue'
 import { getOrderStatusName } from '@/constants/order'
 import { dialog, fullloading } from '@/utils/vant'

+ 3 - 3
src/packages/mobile/views/order/performance/Index.vue

@@ -25,7 +25,7 @@
                     <div class="g-order-list__content">
                         <ul>
                             <li>
-                                <span>时间</span>
+                                <span>日期</span>
                                 <span>{{ formatDate(item.createtime, 'YYYY-MM-DD') }}</span>
                             </li>
                             <li>
@@ -52,10 +52,10 @@
                                 <span>卖方已收</span>
                                 <span>{{ item.sellreceivedamount }}</span>
                             </li>
-                            <li>
+                            <!-- <li>
                                 <span>步骤到期日期</span>
                                 <span>{{ formatDate(item.curstepdeadline, 'YYYY-MM-DD') }}</span>
-                            </li>
+                            </li> -->
                         </ul>
                     </div>
                     <div class="g-order-list__btnbar">

+ 1 - 1
src/packages/mobile/views/order/performance/components/breach/Index.vue

@@ -45,7 +45,7 @@ const props = defineProps({
     }
 })
 
-const { formData, formSubmit } = usePerformanceContractedApply(props.selectedRow.buyaccountid)
+const { formData, formSubmit } = usePerformanceContractedApply(props.selectedRow.buyorsell)
 const formRef = shallowRef<FormInstance>()
 
 const onUploadSuccess = (filePath: string) => {

+ 6 - 6
src/packages/mobile/views/order/performance/components/detail/Index.vue

@@ -7,7 +7,7 @@
             </template>
             <div class="order-detail__container g-form__container">
                 <CellGroup title="履约信息">
-                    <Cell title="类型" :value="selectedRow.typename" />
+                    <Cell title="类型" :value="getPerformanceTypeName(selectedRow.performancetype)" />
                     <Cell title="商品" :value="selectedRow.wrstandardname" />
                     <Cell title="仓库" :value="selectedRow.warehousename" />
                     <Cell title="数量" :value="selectedRow.qty" />
@@ -16,8 +16,8 @@
                     <Cell title="卖方" :value="selectedRow.sellusername" />
                     <Cell title="买方已付" :value="formatDecimal(selectedRow.buypaidamount)" />
                     <Cell title="卖方已收" :value="formatDecimal(selectedRow.sellreceivedamount)" />
-                    <Cell title="当前步骤" :value="selectedRow.curstepname" />
-                    <Cell title="步骤到期时间" :value="formatDate(selectedRow.curstepdeadline)" />
+                    <Cell title="当前步骤" :value="handleNoneValue(selectedRow.curstepname)" />
+                    <!-- <Cell title="步骤到期时间" :value="formatDate(selectedRow.curstepdeadline)" /> -->
                     <Cell title="开始时间" :value="formatDate(selectedRow.starttime)" />
                     <Cell title="关联单号" :value="selectedRow.relatedorderid" />
                     <Cell title="履约单号" :value="selectedRow.performanceplanid" />
@@ -34,7 +34,7 @@
                             <p class="remaindays">{{ remaindays(item) }}</p>
                             <p class="endtime" v-if="item.stepstatus != 2">{{ handleNoneValue(item.endtime) }}</p>
                         </div>
-                        <div class="planstep-info__dwn" v-if="item.stepstatus === 1">
+                        <div class="planstep-info__dwn" v-if="[1, 4].includes(item.stepstatus)">
                             <p class="remaindays">{{ item.stepdays }}天</p>
                         </div>
                     </div>
@@ -61,7 +61,7 @@ import { fullloading } from '@/utils/vant'
 import { formatDate, formatDecimal, handleNoneValue } from '@/filters'
 import { usePerformanceDelayApply, usePerformanceManualConfirm } from '@/business/performance'
 import { queryWrPerformancePlanStep } from '@/services/api/performance'
-import { getPerformanceStepStatusName } from '@/constants/order'
+import { getPerformanceStepStatusName, getPerformanceTypeName } from '@/constants/order'
 
 import AppModal from '@/components/base/modal/index.vue'
 import { useRequest } from '@/hooks/request'
@@ -102,7 +102,7 @@ const styles= (status: number) => {
 
 const remaindays = (item: Model.WrPerformancePlanStep) => {
     let days = ''
-    if ([2].includes(item.stepstatus)) {
+    if ([2, 4].includes(item.stepstatus)) {
         days = `剩余${item.remaindays}天`
     }
     else if ([3, 6].includes(item.stepstatus)) {

+ 0 - 1
src/packages/mobile/views/order/performance/components/detail/index.less

@@ -17,7 +17,6 @@
       justify-content: space-between;
       align-items: center;
       align-content: center;
-      text-align: center;
       padding: 10px 0px;
 
       :nth-child(1){

+ 2 - 2
src/packages/mobile/views/order/performance/components/modify/Index.vue

@@ -9,9 +9,9 @@
                 <CellGroup title="履约信息">
                     <Field name="Contract" label="联络信息" type="textarea" autosize :maxlength="50" v-model="Contract"
                         placeholder="请输入联络信息" :rules="formRules.Contract" />
-                    <Field name="Receive" label="收货地址" type="textarea" autosize v-model="Receive" :rules="formRules.Receive"
+                    <Field name="Receive" v-if="selectedRow.buyorsell === 0" label="收货地址" type="textarea" autosize v-model="Receive" :rules="formRules.Receive"
                         placeholder="请输入收货地址" right-icon="add-o" @click-right-icon="showContact = true" />
-                    <Field name="Receipt" label="发票信息" type="textarea" autosize v-model="Receipt" placeholder="必填"
+                    <Field name="Receipt" v-if="selectedRow.buyorsell === 0" label="发票信息" type="textarea" autosize v-model="Receipt" placeholder="必填"
                         :rules="formRules.Receipt" right-icon="add-o" @click-right-icon="showReceipt = true" />
                 </CellGroup>
             </Form>

+ 2 - 2
src/packages/mobile/views/order/position/components/goods/close/Index.vue

@@ -16,7 +16,7 @@
                     <Cell title="持仓均价" :value="formatDecimal(selectedRow.averageprice)" />
                     <Cell title="参考损益">
                         <template #value>
-                            <span :class="closepl ? 'g-price-up' : 'g-price-down'">{{ formatDecimal(closepl) }}</span>
+                            <span :class="handlePriceColor(closepl, 0.0)">{{ formatDecimal(closepl) }}</span>
                         </template>
                     </Cell>
                 </CellGroup>
@@ -50,7 +50,7 @@ import { shallowRef, PropType, onMounted, computed } from 'vue'
 import AppModal from '@/components/base/modal/index.vue'
 import { CellGroup, Cell, Button, FieldRule, Form, Field, Stepper } from 'vant'
 import { getBuyOrSellName, BuyOrSell } from '@/constants/order'
-import { formatDecimal, handleNumberValue } from '@/filters'
+import { formatDecimal, handleNumberValue, handlePriceColor } from '@/filters'
 import { useOrder } from '@/business/trade'
 import { dialog, fullloading } from '@/utils/vant'
 import { useFuturesStore } from '@/stores'

+ 2 - 2
src/packages/mobile/views/order/position/components/presale/detail/Index.vue

@@ -14,7 +14,7 @@
                     <Cell title="认购数量" :value="selectedRow.tradeqty" />
                     <Cell title="预售价" :value="selectedRow.openprice" />
                     <Cell title="总货款" :value="selectedRow.tradeamount" />
-                    <Cell title="转让定金比例" :value="selectedRow.transferdepositratio" />
+                    <Cell title="转让定金比例" :value="parsePercent(selectedRow.transferdepositratio)" />
                     <Cell title="转让订金" :value="selectedRow.transferdeposit" />
                     <Cell title="未付订金" :value="selectedRow.depositremain" />
                     <Cell title="支付状态" :value="getPayStatusName(selectedRow.paystatus)" />
@@ -29,7 +29,7 @@
 import { shallowRef, PropType } from 'vue'
 import { CellGroup, Cell } from 'vant'
 import AppModal from '@/components/base/modal/index.vue'
-import { formatDate } from '@/filters'
+import { formatDate, parsePercent } from '@/filters'
 import { getPayStatusName } from '@/constants/order'
 
 defineProps({

+ 0 - 1
src/packages/mobile/views/order/position/components/pricing/list/Index.vue

@@ -104,5 +104,4 @@ const onClosed = (item: Model.TradePositionRsp) => {
     router.push({ name: 'pricing-detail', query: { goodscode: item.goodscode, buyOrSell: buyOrSell, buildType: BuildType.Close } })
 }
 
-
 </script>

+ 35 - 1
src/packages/mobile/views/order/position/components/spot/listing/Index.vue

@@ -14,6 +14,8 @@
                     <Cell title="可用量" :value="selectedRow.enableqty" />
                 </CellGroup>
                 <CellGroup title="挂牌信息" inset>
+                    <Field name="PerformanceTemplateID" label="履约模板" placeholder="请选择" v-model="formData.PerformanceTemplateID" :rules="formRules.PerformanceTemplateID"
+                 @click="showPerformancePlan = true" is-link readonly />
                     <Field name="OrderQty" :rules="formRules.OrderQty" label="挂牌数量">
                         <template #input>
                             <Stepper v-model="formData.OrderQty" theme="round" button-size="22"
@@ -33,17 +35,23 @@
                     <Button block square type="danger" @click="formRef?.submit">卖出</Button>
                 </div>
             </template>
+            <component :is="PerformanceTmp" v-model:show="showPerformancePlan" @change="onPerformanceTmpChange" />
         </app-view>
     </app-modal>
 </template>
 
 <script lang="ts" setup>
-import { shallowRef, PropType, onMounted } from 'vue'
+import { shallowRef, PropType, onMounted, defineAsyncComponent } from 'vue'
 import { CellGroup, Cell, Button, Stepper, Field, Form, FormInstance, FieldRule } from 'vant'
 import { fullloading } from '@/utils/vant'
 import { useHdWROrder } from '@/business/trade'
+import { onBeforeRouteLeave } from 'vue-router'
 import AppModal from '@/components/base/modal/index.vue'
 
+const PerformanceTmp = defineAsyncComponent(() => import('../../../../../spot/add/components/preformance/index.vue'))
+const showPerformancePlan = shallowRef(false)
+const performance = shallowRef<Partial<Model.PerformancePlanRsp>>({}) //选中的履约模板
+
 const props = defineProps({
     selectedRow: {
         type: Object as PropType<Model.HoldLBRsp>,
@@ -58,6 +66,12 @@ const refresh = shallowRef(false) // 是否刷新父组件数据
 
 // 表单验证规则
 const formRules: { [key in keyof Proto.HdWROrderReq]?: FieldRule[] } = {
+    PerformanceTemplateID: [{
+        message: '请选择履约模板',
+        validator: () => {
+            return !!formData.PerformanceTemplateID
+        }
+    }],
     FixedPrice: [{
         message: '请输入价格',
         validator: () => {
@@ -78,6 +92,16 @@ const formRules: { [key in keyof Proto.HdWROrderReq]?: FieldRule[] } = {
     }],
 }
 
+// 选择履约模板
+const onPerformanceTmpChange = (item: Model.PermancePlanTmpRsp) => {
+    performance.value = item
+    formData.PerformanceTemplateID = item.autoid
+    if (formData.PerformanceTemplateID) {
+        formRef.value?.validate('PerformanceTemplateID')
+    }
+    showPerformancePlan.value = false
+}
+
 const onSubmit = () => {
     const { wrstandardid, subnum, deliverygoodsid, ladingbillid = '0', wrfactortypeid = '0' } = props.selectedRow ?? {}
     formData.WRStandardID = wrstandardid
@@ -110,4 +134,14 @@ onMounted(() => {
 defineExpose({
     closed,
 })
+
+// 离开页面前关闭组件
+onBeforeRouteLeave((to, from, next) => {
+    if (showPerformancePlan.value) {
+        showPerformancePlan.value = false
+        next(false)
+    } else {
+        next()
+    }
+})
 </script>

+ 2 - 2
src/packages/mobile/views/order/position/components/transfer/list/Index.vue

@@ -24,7 +24,7 @@
                         </li>
                         <li>
                             <span>持仓金额</span>
-                            <span>{{ item.buycurholderamount }}</span>
+                            <span>{{ formatDecimal(item.buycurholderamount) }}</span>
                         </li>
                         <li>
                             <span>转让定金比例</span>
@@ -68,7 +68,7 @@
 import { shallowRef, defineAsyncComponent } from 'vue'
 import { Button } from 'vant'
 import { fullloading, dialog } from '@/utils/vant'
-import { parsePercent } from '@/filters'
+import { parsePercent, formatDecimal } from '@/filters'
 import { useComponent } from '@/hooks/component'
 import { useRequest } from '@/hooks/request'
 import { queryMineTradePositionExs } from '@/services/api/transfer'

+ 2 - 2
src/packages/mobile/views/order/position/components/transfer/listing/Index.vue

@@ -5,7 +5,7 @@
             <template #header>
                 <app-navbar title="转让" @back="closed" />
             </template>
-            <Form ref="formRef" class="g-form__container" @submit="onSubmit">
+            <Form ref="formRef" :label-width="100" class="g-form__container" @submit="onSubmit">
                 <CellGroup inset>
                     <Field label="商品代码/名称">
                         <template #input>
@@ -35,7 +35,7 @@
                     <Field name="OrderPrice" :rules="formRules.OrderPrice" label="转让价">
                         <template #input>
                             <Stepper v-model="formData.OrderPrice" theme="round" :min="quote?.limitdown"
-                                :max="quote?.limitup" :decimal-length="2" :auto-fixed="false" button-size="22" />
+                                :max="quote?.limitup" :step="Math.pow(10, -selectedRow.decimalplace)" :decimal-length="selectedRow.decimalplace" :auto-fixed="false" button-size="22" />
                         </template>
                     </Field>
                     <Field name="OrderQty" :rules="formRules.OrderQty" label="转让数量">

+ 25 - 0
src/packages/mobile/views/spot/add/components/buy/index.vue

@@ -13,6 +13,8 @@
                         </template>
                     </Field>
                 </template>
+                <Field name="PerformanceTemplateID" label="履约模板" placeholder="请选择" v-model="formData.PerformanceTemplateID" :rules="formRules.PerformanceTemplateID"
+                 @click="showPerformancePlan = true" is-link readonly />
                 <Field name="FixedPrice" :rules="formRules.FixedPrice" label="价格">
                     <template #input>
                         <Stepper v-model="formData.FixedPrice" theme="round" :min="0" :decimal-length="2" :default-value="0"
@@ -38,6 +40,7 @@
             </div>
         </template>
         <component :is="WarehouseReceipt" v-model:show="showWarehouseReceipt" @change="onChange" />
+        <component :is="PerformanceTmp" v-model:show="showPerformancePlan" @change="onPerformanceTmpChange" />
     </app-view>
 </template>
 
@@ -50,12 +53,15 @@ import { useNavigation } from '../../../../../router/navigation'
 import { useHdWROrder } from '@/business/trade'
 
 const WarehouseReceipt = defineAsyncComponent(() => import('./warehouse-receipt.vue'))
+const PerformanceTmp = defineAsyncComponent(() => import('../preformance/index.vue'))
 
 const { routerBack } = useNavigation()
 const { formData, listingSubmit, amount } = useHdWROrder()
 const formRef = shallowRef<FormInstance>()
 const showWarehouseReceipt = shallowRef(false)
+const showPerformancePlan = shallowRef(false)
 const selectedRow = shallowRef<Partial<Model.HoldLBRsp>>({}) //选中的现货仓单
+const performance = shallowRef<Partial<Model.PerformancePlanRsp>>({}) //选中的履约模板
 
 // 表单验证规则
 const formRules: { [key in keyof Proto.HdWROrderReq]?: FieldRule[] } = {
@@ -65,6 +71,12 @@ const formRules: { [key in keyof Proto.HdWROrderReq]?: FieldRule[] } = {
             return !!selectedRow.value.wrfactortypeid
         }
     }],
+    PerformanceTemplateID: [{
+        message: '请选择履约模板',
+        validator: () => {
+            return !!formData.PerformanceTemplateID
+        }
+    }],
     FixedPrice: [{
         message: '请输入价格',
         validator: () => {
@@ -96,6 +108,16 @@ const onChange = (item: Model.HoldLBRsp) => {
     showWarehouseReceipt.value = false
 }
 
+// 选择履约模板
+const onPerformanceTmpChange = (item: Model.PermancePlanTmpRsp) => {
+    performance.value = item
+    formData.PerformanceTemplateID = item.autoid
+    if (formData.PerformanceTemplateID) {
+        formRef.value?.validate('PerformanceTemplateID')
+    }
+    showPerformancePlan.value = false
+}
+
 // 表单提交
 const formSubmit = () => {
     const { wrstandardid, subnum, deliverygoodsid, ladingbillid = '0', wrfactortypeid = '0' } = selectedRow.value
@@ -120,6 +142,9 @@ onBeforeRouteLeave((to, from, next) => {
     if (showWarehouseReceipt.value) {
         showWarehouseReceipt.value = false
         next(false)
+    } else if (showPerformancePlan.value) {
+        showPerformancePlan.value = false
+        next(false)
     } else {
         next()
     }

+ 47 - 0
src/packages/mobile/views/spot/add/components/preformance/index.vue

@@ -0,0 +1,47 @@
+<template>
+    <app-modal direction="right" height="100%">
+        <app-view class="g-form">
+            <template #header>
+                <app-navbar title="选择履约模板" />
+            </template>
+            <RadioGroup class="g-form__container" v-model="checkedRow" v-if="dataList.length">
+                <CellGroup v-for="(item, index) in dataList" :key="index" @click="onChange(item)" inset>
+                    <Cell>
+                        <template #title>
+                            <Radio :name="item" checked-color="#ee0a24">
+                                <ul style="margin-left: .2rem;">
+                                    <li>
+                                        <span>名称:</span>
+                                        <span>{{ item.templatename }}</span>
+                                    </li>
+                                    <ul v-for="(step, i) in item.LstStep" :key="i">
+                                        <span>{{ step.stepinfo }}</span>
+                                        <span>{{ step.stepdate }}</span>
+                                    </ul>
+                                </ul>
+                            </Radio>
+                        </template>
+                    </Cell>
+                </CellGroup>
+            </RadioGroup>
+        </app-view>
+    </app-modal>
+</template>
+
+<script lang="ts" setup>
+import { shallowRef } from 'vue'
+import { RadioGroup, Radio, Cell, CellGroup } from 'vant'
+import { useRequest } from '@/hooks/request'
+import { queryPermancePlanTmp } from '@/services/api/performance'
+import AppModal from '@/components/base/modal/index.vue'
+
+const emit = defineEmits(['update:show', 'change'])
+const checkedRow = shallowRef<Model.PermancePlanTmpRsp>()
+const { dataList } = useRequest(queryPermancePlanTmp)
+
+// 选择履约模板
+const onChange = (item: Model.PermancePlanTmpRsp) => {
+    checkedRow.value = item
+    emit('change', item)
+}
+</script>

+ 35 - 1
src/packages/mobile/views/spot/add/components/sell/index.vue

@@ -2,6 +2,8 @@
     <app-view class="g-form">
         <Form ref="formRef" class="g-form__container" @submit="formSubmit">
             <CellGroup inset>
+                <Field name="PerformanceTemplateID" label="履约模板" placeholder="请选择" v-model="formData.PerformanceTemplateID" :rules="formRules.PerformanceTemplateID"
+                 @click="showPerformancePlan = true" is-link readonly />
                 <Field name="DeliveryGoodsID" label="品类" :rules="formRules.DeliveryGoodsID" is-link>
                     <template #input>
                         <app-select v-model="formData.DeliveryGoodsID" :options="ftDeliveryGoodsList"
@@ -52,11 +54,13 @@
                 <Button type="danger" @click="formRef?.submit" square block>提交</Button>
             </div>
         </template>
+        <component :is="PerformanceTmp" v-model:show="showPerformancePlan" @change="onPerformanceTmpChange" />
     </app-view>
 </template>
 
 <script lang="ts" setup>
-import { shallowRef, computed } from 'vue'
+import { shallowRef, computed, defineAsyncComponent } from 'vue'
+import { onBeforeRouteLeave } from 'vue-router'
 import { CellGroup, Button, Field, Form, FormInstance, Stepper, FieldRule, showSuccessToast, showFailToast } from 'vant'
 import { fullloading } from '@/utils/vant'
 import { BuyOrSell } from '@/constants/order'
@@ -67,10 +71,14 @@ import { useHdWROrder } from '@/business/trade'
 import { useAccountStore } from '@/stores'
 import AppSelect from '../../../../../components/base/select/index.vue'
 
+const PerformanceTmp = defineAsyncComponent(() => import('../preformance/index.vue'))
+
 const { routerBack } = useNavigation()
 const { formData, listingSubmit, amount } = useHdWROrder()
 const accountStore = useAccountStore()
 const formRef = shallowRef<FormInstance>()
+const showPerformancePlan = shallowRef(false)
+const performance = shallowRef<Partial<Model.PerformancePlanRsp>>({}) //选中的履约模板
 
 const { dataList: ftDeliveryGoodsList } = useRequest(queryFtDeliveryGoods)
 const { dataList: wrStandardFactoryItems, run: getWrStandardFactoryItems } = useRequest(queryWrStandardFactoryItem, { manual: true })
@@ -84,6 +92,12 @@ const warehouseList = computed(() => {
 
 // 表单验证规则
 const formRules: { [key in keyof Proto.HdWROrderReq]?: FieldRule[] } = {
+    PerformanceTemplateID: [{
+        message: '请选择履约模板',
+        validator: () => {
+            return !!formData.PerformanceTemplateID
+        }
+    }],
     DeliveryGoodsID: [{
         message: '请选择品类',
         validator: () => {
@@ -116,6 +130,16 @@ const formRules: { [key in keyof Proto.HdWROrderReq]?: FieldRule[] } = {
     }],
 }
 
+// 选择履约模板
+const onPerformanceTmpChange = (item: Model.PermancePlanTmpRsp) => {
+    performance.value = item
+    formData.PerformanceTemplateID = item.autoid
+    if (formData.PerformanceTemplateID) {
+        formRef.value?.validate('PerformanceTemplateID')
+    }
+    showPerformancePlan.value = false
+}
+
 // 选择品类时触发
 const onDeliveryGoodsChange = (deliverygoodsid: number) => {
     const item = ftDeliveryGoodsList.value.find((e) => e.deliverygoodsid === deliverygoodsid)
@@ -156,4 +180,14 @@ const formSubmit = () => {
         })
     })
 }
+
+// 离开页面前关闭组件
+onBeforeRouteLeave((to, from, next) => {
+    if (showPerformancePlan.value) {
+        showPerformancePlan.value = false
+        next(false)
+    } else {
+        next()
+    }
+})
 </script>

+ 15 - 14
src/packages/mobile/views/spot/detail/Index.vue

@@ -6,7 +6,10 @@
         <Banner :data-list="topBanners" />
         <div class="g-detail__buy" v-if="quoteItem">
             <div class="title">
-                <span>{{ quoteItem.wrstandardname }}</span>
+                <span>{{ quoteItem.wrstandardcode }} / {{ quoteItem.wrstandardname }}</span>
+            </div>
+            <div class="desc">
+                <span>{{ quoteItem.warehousename }}</span>
             </div>
             <div class="info">
                 <ul>
@@ -26,16 +29,12 @@
                         <span>买量</span>
                         <span>{{ quoteItem.buyqty }}</span>
                     </li>
-                    <li>
-                        <span>仓库</span>
-                        <span>{{ quoteItem.warehousename }}</span>
-                    </li>
                 </ul>
             </div>
         </div>
         <div class="trade">
             <div class="trade-section sell" v-if="sellList.length">
-                <Cell title="卖" />
+                <Cell title="卖出挂牌" />
                 <app-list :columns="columns" :data-list="sellList">
                     <template #operate="{ row }">
                         <Button size="small" round @click="delistingListing(row, BuyOrSell.Buy)">买入</Button>
@@ -43,7 +42,7 @@
                 </app-list>
             </div>
             <div class="trade-section buy" v-if="buyList.length">
-                <Cell title="买" />
+                <Cell title="买入挂牌" />
                 <app-list :columns="columns" :data-list="buyList">
                     <template #operate="{ row }">
                         <Button size="small" round @click="delistingListing(row, BuyOrSell.Sell)">卖出</Button>
@@ -57,16 +56,18 @@
             </template>
         </div>
         <template #footer>
-            <div class="g-detail__footer">
-                <div class="price" v-if="quoteItem">
+            <div class="g-form__footer">
+                <!-- <div class="price" v-if="quoteItem">
                     <span class="price-text">参考价:</span>
                     <span class="price-unit">¥</span>
                     <span class="price-integer">{{ quoteItem.spotgoodsprice }}</span>
-                </div>
-                <div class="submit">
-                    <span class="submit-button warning" @click="toggleListing(BuyOrSell.Sell)">我要卖</span>
-                    <span class="submit-button danger" @click="toggleListing(BuyOrSell.Buy)">我要买</span>
-                </div>
+                </div> -->
+                <!-- <div class="submit"> -->
+                <Button block type="primary" square class="submit-button warning"
+                    @click="toggleListing(BuyOrSell.Sell)">我要卖</Button>
+                <Button block type="danger" square class="submit-button danger"
+                    @click="toggleListing(BuyOrSell.Buy)">我要买</Button>
+                <!-- </div> -->
             </div>
             <component ref="componentRef" :is="componentMap.get(componentId)" v-bind="{ quoteItem, quoteDetail, buyorsell }"
                 @closed="closeComponent" v-if="componentId" />

+ 38 - 2
src/packages/mobile/views/spot/detail/components/listing/index.vue

@@ -2,6 +2,8 @@
     <app-popup class="supply-demand-listing" :title="buyorsell === BuyOrSell.Sell ? '我要卖' : '我要买'" v-model:show="showModal"
         :refresh="refresh">
         <Form class="supply-demand-listing__form" ref="formRef" @submit="onSubmit">
+            <Field name="PerformanceTemplateID" label="履约模板" placeholder="请选择" v-model="formData.PerformanceTemplateID" :rules="formRules.PerformanceTemplateID"
+                 @click="showPerformancePlan = true" is-link readonly />
             <Field name="FixedPrice" :rules="formRules.FixedPrice" label="挂牌价格">
                 <template #input>
                     <Stepper v-model="formData.FixedPrice" theme="round" :decimal-length="2" :auto-fixed="false"
@@ -37,13 +39,15 @@
             </Field>
         </Form>
         <template #footer>
-            <Button type="danger" block round @click="formRef?.submit">确定</Button>
+            <Button :type="buyorsell === BuyOrSell.Sell ? 'primary' : 'danger'" block round
+                @click="formRef?.submit">确定</Button>
         </template>
+        <component :is="PerformanceTmp" v-model:show="showPerformancePlan" @change="onPerformanceTmpChange" />
     </app-popup>
 </template>
 
 <script lang="ts" setup>
-import { shallowRef, PropType, onMounted } from 'vue'
+import { shallowRef, PropType, onMounted, defineAsyncComponent } from 'vue'
 import { Form, Field, Stepper, Button, FieldRule, FormInstance } from 'vant'
 import { fullloading, dialog } from '@/utils/vant'
 import { useAccountStore } from '@/stores'
@@ -51,7 +55,10 @@ import { BuyOrSell } from '@/constants/order'
 import { queryHoldLB } from '@/services/api/order'
 import { useHdWROrder } from '@/business/trade'
 import AppPopup from '../../../../../components/base/popup/index.vue'
+import { onBeforeRouteLeave } from 'vue-router'
+
 //import AppSelect from '../../../../../components/base/select/index.vue'
+const PerformanceTmp = defineAsyncComponent(() => import('../../../add/components/preformance/index.vue'))
 
 const props = defineProps({
     quoteItem: {
@@ -64,6 +71,7 @@ const props = defineProps({
     }
 })
 
+const showPerformancePlan = shallowRef(false)
 const { formData, listingSubmit, amount } = useHdWROrder()
 const accountStore = useAccountStore()
 const formRef = shallowRef<FormInstance>()
@@ -71,9 +79,17 @@ const refresh = shallowRef(false) // 是否刷新父组件数据
 const showModal = shallowRef(true)
 //const dataList = shallowRef<Model.HoldLBRsp[]>([]) //现货仓单列表
 const selectedRow = shallowRef<Model.HoldLBRsp>() //选中的现货仓单
+const performance = shallowRef<Partial<Model.PerformancePlanRsp>>({}) //选中的履约模板
+
 
 // 表单验证规则
 const formRules: { [key in keyof Proto.HdWROrderReq]?: FieldRule[] } = {
+    PerformanceTemplateID: [{
+        message: '请选择履约模板',
+        validator: () => {
+            return !!formData.PerformanceTemplateID
+        }
+    }],
     FixedPrice: [{
         message: '请输入价格',
         validator: () => {
@@ -101,6 +117,16 @@ const formRules: { [key in keyof Proto.HdWROrderReq]?: FieldRule[] } = {
     }],
 }
 
+// 选择履约模板
+const onPerformanceTmpChange = (item: Model.PermancePlanTmpRsp) => {
+    performance.value = item
+    formData.PerformanceTemplateID = item.autoid
+    if (formData.PerformanceTemplateID) {
+        formRef.value?.validate('PerformanceTemplateID')
+    }
+    showPerformancePlan.value = false
+}
+
 // 选择仓单
 // const onConfirm = (value: string) => {
 //     selectedRow.value = dataList.value.find((e) => e.wrid === value)
@@ -158,6 +184,16 @@ onMounted(() => {
 defineExpose({
     closed,
 })
+
+// 离开页面前关闭组件
+onBeforeRouteLeave((to, from, next) => {
+    if (showPerformancePlan.value) {
+        showPerformancePlan.value = false
+        next(false)
+    } else {
+        next()
+    }
+})
 </script>
 
 <style lang="less">

+ 4 - 3
src/packages/mobile/views/spot/list/Index.vue

@@ -17,13 +17,14 @@
                             <img :src="getFirstImage(item.thumurls)" />
                         </div>
                         <div class="goods-info">
-                            <div class="goods-info__title">{{ item.wrstandardname }}</div>
-                            <div class="goods-info__price">
+                            <div class="goods-info__title">{{ item.wrstandardcode }} / {{ item.wrstandardname }}</div>
+                            <div class="goods-info__desc">{{ item.warehousename }}</div>
+                            <div class="goods-info__price" v-if="item.sellprice">
                                 <Tag type="danger" plain>卖价</Tag>
                                 <span class="unit">¥</span>
                                 <span class="integer">{{ item.sellprice }}</span>
                             </div>
-                            <div class="goods-info__price">
+                            <div class="goods-info__price" v-if="item.buyprice">
                                 <Tag type="warning" plain>买价</Tag>
                                 <span class="unit">¥</span>
                                 <span class="integer">{{ item.buyprice }}</span>

+ 2 - 2
src/packages/pc/assets/themes/default/default.less

@@ -33,7 +33,7 @@
 
     --el-color-primary: #26487c;
     --el-color-primary-light-3: #29538c;
-    --el-color-primary-light-5: #70abd8;
+    --el-color-primary-light-5: #98acbb;
     --el-color-primary-light-7: #c6e2ff;
     --el-color-primary-light-8: #d9ecff;
     --el-color-primary-light-9: #ecf5ff;
@@ -187,7 +187,7 @@
 
             &__content {
                 align-items: flex-start;
-                padding-right: 80px;
+                padding-right: 48px;
             }
 
             &--row {

+ 1 - 0
src/packages/pc/components/base/drawer/index.less

@@ -36,6 +36,7 @@
     &__body {
         flex: 1;
         overflow-y: auto;
+        line-height: normal;
         background-color: #0f1a25;
         padding: 24px;
         padding-bottom: 0;

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

@@ -92,8 +92,12 @@
 
             td.el-table {
 
-                &__cell:not(&__expanded-cell):first-child,
-                &__cell:is(&__expand-column)+td {
+                // &__cell:not(&__expanded-cell):first-child,
+                // &__cell:is(&__expand-column)+td {
+                //     background-color: var(--el-table-header-bg-color);
+                // }
+
+                &__cell:not(&__expanded-cell):first-child {
                     background-color: var(--el-table-header-bg-color);
                 }
 

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

@@ -1,6 +1,6 @@
 .app-footer {
     display: flex;
-    height: 300px;
+    height: 330px;
     color: #fff;
     background-color: #0e0e0f;
     border-top: 1px solid #363f45;

+ 6 - 1
src/packages/pc/components/modules/listing/index.less

@@ -17,7 +17,7 @@
     }
 
     &__form {
-        width: 240px;
+        width: 260px;
         padding: 10px;
         border-left: 1px solid #363f45;
 
@@ -30,5 +30,10 @@
             display: flex;
             justify-content: center;
         }
+
+        .el-radio {
+            --el-radio-text-color: #7a8a94;
+            --el-color-primary: #3a87f7;
+        }
     }
 }

+ 31 - 61
src/packages/pc/components/modules/listing/index.vue

@@ -5,8 +5,7 @@
         </div>
         <div class="app-listing__form">
             <h4 class="header-title">订单挂牌</h4>
-            <el-form ref="formRef" class="el-form--vertical" size="small" label-width="50px" :model="formData"
-                :rules="formRules">
+            <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"
@@ -15,9 +14,9 @@
                 </el-form-item>
                 <el-form-item prop="BuyOrSell" label="方向">
                     <el-radio-group v-model="formData.BuyOrSell">
-                        <el-radio-button v-for="(item, index) in getBuyOrSellList()" :key="index" :label="item.value">
+                        <el-radio v-for="(item, index) in getBuyOrSellList()" :key="index" :label="item.value">
                             {{ item.label }}
-                        </el-radio-button>
+                        </el-radio>
                     </el-radio-group>
                 </el-form-item>
                 <el-form-item prop="OrderPrice" label="价格">
@@ -25,33 +24,32 @@
                         v-model="formData.OrderPrice" />
                 </el-form-item>
                 <el-form-item prop="OrderQty" label="数量">
-                    <div class="el-form-item--col">
-                        <div class="g-qty-group">
-                            <el-input-number placeholder="请输入" :min="agreeunit" :step="qtyStep" v-model="orderQty" />
-                            <el-radio-group size="small" v-model="qtyStep" @change="onRadioChange"
-                                v-if="qtyStepList.length">
-                                <el-radio v-for="(value, index) in qtyStepList" :key="index" :label="value" border />
-                            </el-radio-group>
-                        </div>
-                        <span>{{ getGoodsUnitName(quote?.goodunitid) }}</span>
+                    <div class="g-qty-group">
+                        <el-input-number placeholder="请输入" :min="0" :precision="0" :step="qtyStep"
+                            v-model="formData.OrderQty" />
+                        <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>
             <div class="footer-btnbar">
                 <template v-if="formData.BuyOrSell === BuyOrSell.Buy">
-                    <el-button type="primary" size="small" :loading="loading" :disabled="!goodsStore.goodsId"
+                    <el-button type="primary" :loading="loading" :disabled="!goodsStore.goodsId || !formData.OrderQty"
                         @click="onSubmit(EBuildType.BUILDTYPE_OPEN)">订立买入</el-button>
-                    <el-button type="primary" size="small" :loading="loading"
-                        :disabled="(sellQty === 0) || (orderQty > sellQty)" @click="onSubmit(EBuildType.BUILDTYPE_CLOSE)">
+                    <el-button type="primary" :loading="loading"
+                        :disabled="!formData.OrderQty || !sellQty || (formData.OrderQty > sellQty)"
+                        @click="onSubmit(EBuildType.BUILDTYPE_CLOSE)">
                         <span>转让买入</span>
                         <span v-if="sellQty">(≤{{ sellQty }})</span>
                     </el-button>
                 </template>
                 <template v-if="formData.BuyOrSell === BuyOrSell.Sell">
-                    <el-button type="primary" size="small" :loading="loading" :disabled="!goodsStore.goodsId"
+                    <el-button type="primary" :loading="loading" :disabled="!goodsStore.goodsId || !formData.OrderQty"
                         @click="onSubmit(EBuildType.BUILDTYPE_OPEN)">订立卖出</el-button>
-                    <el-button type="primary" size="small" :loading="loading"
-                        :disabled="(buyQty === 0) || (orderQty > buyQty)" @click="onSubmit(EBuildType.BUILDTYPE_CLOSE)">
+                    <el-button type="primary" :loading="loading"
+                        :disabled="!formData.OrderQty || !buyQty || (formData.OrderQty > buyQty)"
+                        @click="onSubmit(EBuildType.BUILDTYPE_CLOSE)">
                         <span>转让卖出</span>
                         <span v-if="buyQty">(≤{{ buyQty }})</span>
                     </el-button>
@@ -66,7 +64,6 @@ import { shallowRef, computed, watch } from 'vue'
 import { ElMessage, ElMessageBox, FormInstance, FormRules } from 'element-plus'
 import { EPriceMode, EListingSelectType, EDelistingType, EBuildType, EValidType, EOrderOperateType } from '@/constants/client'
 import { BuyOrSell, getBuyOrSellList } from '@/constants/order'
-import { getGoodsUnitName } from '@/constants/unit'
 import { useRequest } from '@/hooks/request'
 import { queryTradePosition } from '@/services/api/order'
 import { useOrder } from '@/business/trade'
@@ -78,8 +75,8 @@ const goodsStore = useGoodsStore()
 const futuresStore = useFuturesStore()
 const { formData, loading, formSubmit } = useOrder()
 const formRef = shallowRef<FormInstance>()
-const orderQty = shallowRef(1) // 数量
-const qtyStep = shallowRef(1) // 数量步长
+const qtyStepList = [1, 10, 100] // 数量步长列表
+const qtyStep = shallowRef(qtyStepList[0]) // 数量步长
 
 // 持仓列表
 const { dataList: positionList, run: getTradePosition } = useRequest(queryTradePosition, {
@@ -91,9 +88,6 @@ const { dataList: positionList, run: getTradePosition } = useRequest(queryTradeP
 // 商品盘面
 const quote = computed(() => futuresStore.getQuoteInfo(goodsStore.goodsCode).value)
 
-// 合约乘数
-const agreeunit = computed(() => quote.value?.agreeunit ?? 0)
-
 // 价格步长
 const priceStep = computed(() => {
     const { quoteminunit = 0, decimalplace = 0 } = quote.value ?? {}
@@ -103,34 +97,16 @@ const priceStep = computed(() => {
     return 1
 })
 
-// 数量步长列表
-const qtyStepList = computed(() => {
-    if (agreeunit.value) {
-        return [
-            agreeunit.value * 1,
-            agreeunit.value * 10,
-            agreeunit.value * 100,
-        ]
-    }
-    return []
-})
-
 // 买方向持仓数量
 const buyQty = computed(() => {
     const item = positionList.value.find((e) => e.goodscode === goodsStore.goodsCode && e.buyorsell === BuyOrSell.Buy)
-    if (item) {
-        return item.enableqty * agreeunit.value
-    }
-    return 0
+    return item?.enableqty ?? 0
 })
 
 // 卖方向持仓数量
 const sellQty = computed(() => {
     const item = positionList.value.find((e) => e.goodscode === goodsStore.goodsCode && e.buyorsell === BuyOrSell.Sell)
-    if (item) {
-        return item.enableqty * agreeunit.value
-    }
-    return 0
+    return item?.enableqty ?? 0
 })
 
 const formRules: FormRules = {
@@ -148,21 +124,17 @@ const formRules: FormRules = {
     OrderQty: [{
         required: true,
         validator: (rule, value, callback) => {
-            if (orderQty.value) {
-                if (orderQty.value % agreeunit.value === 0) {
-                    callback()
-                } else {
-                    callback(new Error('只能输入合约乘数的整数倍'))
-                }
+            if (value) {
+                callback()
             } else {
-                callback(new Error('请输入牌数量'))
+                callback(new Error('请输入挂牌数量'))
             }
         }
     }],
 }
 
 const onRadioChange = (value: number) => {
-    orderQty.value = value
+    formData.OrderQty = value
 }
 
 const onBuyClick = (price: number) => {
@@ -193,12 +165,11 @@ const onSubmit = (buildType: number) => {
                 formData.TimevalidType = EValidType.VALIDTYPE_DR
                 formData.OperateType = EOrderOperateType.ORDEROPERATETYPE_NORMAL
                 formData.BuildType = buildType
-                formData.OrderQty = orderQty.value / agreeunit.value // 数量÷合约乘数
 
                 formSubmit().then(() => {
-                    ElMessage.success('提交成功')
+                    ElMessage.success('挂牌成功')
                 }).catch((err) => {
-                    ElMessage.error('提交失败:' + err)
+                    ElMessage.error('挂牌失败:' + err)
                 })
             })
         }
@@ -206,16 +177,15 @@ const onSubmit = (buildType: number) => {
 }
 
 watch(() => goodsStore.goodsId, () => {
-    const { last = 0, agreeunit = 0, presettle = 0 } = quote.value ?? {}
+    const { last = 0, presettle = 0 } = quote.value ?? {}
     formData.OrderPrice = last || presettle
-    orderQty.value = agreeunit
-    qtyStep.value = qtyStepList.value[0]
+    formData.OrderQty = qtyStep.value
 }, {
     immediate: true
 })
 
-// 接收资金变动通知
-eventBus.$on('MoneyChangedNotify', () => getTradePosition())
+// 接收持仓变化通知
+eventBus.$on('PosChangedNtf', () => getTradePosition())
 </script>
 
 <style lang="less">

+ 5 - 1
src/packages/pc/components/modules/quote/chart/kline/index.less

@@ -21,7 +21,7 @@
             display: flex;
             color: #7a8a94;
             font-size: 12px;
-            padding: 4px 4%;
+            padding: 10px;
             margin: 0;
 
             &-item {
@@ -35,6 +35,10 @@
     &__indicator {
         height: 30%;
 
+        .app-tabs__container {
+            overflow: hidden;
+        }
+
         .tabs {
             width: 100%;
             font-size: 12px;

+ 1 - 1
src/packages/pc/components/modules/quote/chart/timeline/index.less

@@ -21,7 +21,7 @@
             display: flex;
             color: #7a8a94;
             font-size: 12px;
-            padding: 4px 4%;
+            padding: 10px;
             margin: 0;
 
             &-item {

+ 1 - 1
src/packages/pc/components/modules/quote/chart/timeline/index.vue

@@ -8,7 +8,7 @@
         </template>
         <template v-else>
             <div class="app-echats-timeline__container">
-                <ul class="legend" v-if="false">
+                <ul class="legend">
                     <li class="legend-item">MA5: {{ selectedItem.ma5 }}</li>
                 </ul>
                 <app-echarts :option="options.timeline" v-model:dataIndex="dataIndex" @ready="initOptions" />

+ 1 - 1
src/packages/pc/components/modules/quote/forex/index.less

@@ -16,7 +16,7 @@
             display: flex;
             font-size: 12px;
             text-align: center;
-            padding: 5px;
+            padding: 3px 5px;
 
             &.is-active {
                 background-color: #262d33;

+ 6 - 0
src/packages/pc/components/modules/quote/price/index.less

@@ -31,6 +31,12 @@
                     font-size: 18px;
                     text-align: center;
                     margin-right: 20px;
+
+                    span.g-price-up {
+                        &::before {
+                            content: '+';
+                        }
+                    }
                 }
 
                 &-right {

+ 2 - 2
src/packages/pc/components/modules/quote/tik/index.vue

@@ -38,7 +38,7 @@ const { run: getHistoryTikDatas } = useRequest(queryHistoryTikDatas, {
     manual: true,
     params: {
         goodsCode: props.goodsCode,
-        count: 20
+        count: 10
     },
     onSuccess: (res) => {
         dataList.value = res.data
@@ -63,7 +63,7 @@ useRequest(queryMarketRun, {
 watch(() => quote.value?.last, () => {
     if (quote.value) {
         const list = dataList.value
-        if (list.length > 19) {
+        if (list.length > 9) {
             // 移除列表最后一条记录
             list.pop()
         }

+ 5 - 5
src/packages/pc/views/account/address/components/edit/index.vue

@@ -6,18 +6,18 @@
             <el-form-item label="收货人" prop="ReceiverName">
                 <el-input placeholder="请输入" v-model="formData.ReceiverName" />
             </el-form-item>
-            <el-form-item label="证件类型" prop="CardTypeID">
+            <!-- <el-form-item label="证件类型" prop="CardTypeID">
                 <el-select v-model="formData.CardTypeID">
                     <el-option :label="item.label" :value="item.value" v-for="(item, index) in certificateTypeList.slice(0, 1)"
                         :key="index" />
                 </el-select>
-            </el-form-item>
+            </el-form-item> -->
             <el-form-item label="联系电话" prop="PhoneNum">
                 <el-input placeholder="请输入" v-model="formData.PhoneNum" />
             </el-form-item>
-            <el-form-item label="证件号码" prop="CardNum">
+            <!-- <el-form-item label="证件号码" prop="CardNum">
                 <el-input placeholder="请输入" v-model="formData.CardNum" />
-            </el-form-item>
+            </el-form-item> -->
             <el-form-item class="el-form-item--row" label="收货地址" prop="area">
                 <app-region class="el-form-item--col" v-model:province="formData.ProvinceID"
                     v-model:city="formData.CityID" v-model:district="formData.DistrictID" />
@@ -48,7 +48,7 @@ const props = defineProps({
     }
 })
 
-const { loading, formData, certificateTypeList, addOrUpdate } = useAddressForm(props.selectedRow)
+const { loading, formData, addOrUpdate } = useAddressForm(props.selectedRow)
 const show = ref(true)
 const refresh = ref(false)
 const formRef = ref<FormInstance>()

+ 0 - 87
src/packages/pc/views/account/address/components/new/index.vue

@@ -1,87 +0,0 @@
-<!-- 账户管理-收货地址管理-编辑 -->
-<template>
-    <app-drawer title='新增地址' :width="880" v-model:show="show" :loading="loading"
-        :refresh="refresh">
-        <el-form ref="formRef" class="el-form--horizontal" label-width="100px" :model="formData" :rules="formRules">
-            <el-form-item label="收货人" prop="ReceiverName">
-                <el-input placeholder="请输入" v-model="formData.ReceiverName" />
-            </el-form-item>
-            <el-form-item label="证件类型" prop="CardTypeID">
-                <el-select v-model="formData.CardTypeID">
-                    <el-option :label="item.label" :value="item.value" v-for="(item, index) in certificateTypeList.slice(0, 1)"
-                        :key="index" />
-                </el-select>
-            </el-form-item>
-            <el-form-item label="联系电话" prop="PhoneNum">
-                <el-input placeholder="请输入" v-model="formData.PhoneNum" />
-            </el-form-item>
-            <el-form-item label="证件号码" prop="CardNum">
-                <el-input placeholder="请输入" v-model="formData.CardNum" />
-            </el-form-item>
-            <el-form-item class="el-form-item--row" label="收货地址" prop="area">
-                <app-region class="el-form-item--col" v-model:province="formData.ProvinceID"
-                    v-model:city="formData.CityID" v-model:district="formData.DistrictID" />
-            </el-form-item>
-            <el-form-item class="el-form-item--row" prop="Address">
-                <el-input placeholder="请输入" v-model="formData.Address" />
-            </el-form-item>
-        </el-form>
-        <template #footer>
-            <el-button type="info" @click="onCancel(false)">取消</el-button>
-            <el-button type="primary" @click="onSubmit">提交</el-button>
-        </template>
-    </app-drawer>
-</template>
-
-<script lang="ts" setup>
-import { ref } from 'vue'
-import { ElMessage } from 'element-plus'
-import type { FormInstance, FormRules } from 'element-plus'
-import { useAddressForm } from '@/business/user/address'
-import AppDrawer from '@pc/components/base/drawer/index.vue'
-import AppRegion from '@pc/components/base/region/index.vue'
-
-const { loading, formData, certificateTypeList, addOrUpdate } = useAddressForm()
-const show = ref(true)
-const refresh = ref(false)
-const formRef = ref<FormInstance>()
-
-const formRules: FormRules = {
-    ReceiverName: [{ required: true, message: '请输入收货人', trigger: 'blur' }],
-    CardTypeID: [{ required: true, message: '请选择证件类型' }],
-    PhoneNum: [{ required: true, message: '请输入联系电话', trigger: 'blur' }],
-    CardNum: [{ required: true, message: '请输入证件号码', trigger: 'blur' }],
-    Address: [{ required: true, message: '请输入详细地址', trigger: 'blur' }],
-    area: [
-        {
-            required: true,
-            validator: (rule, value, callback) => {
-                const ids = [10, 18, 34] // 香港、台湾、澳门没有市区选择
-                if ((formData.ProvinceID && formData.CityID && formData.DistrictID) || ids.includes(formData.ProvinceID ?? 0)) {
-                    callback()
-                } else {
-                    callback(new Error('请选择收货地区'))
-                }
-            }
-        }
-    ],
-}
-
-const onCancel = (isRefresh = false) => {
-    show.value = false
-    refresh.value = isRefresh
-}
-
-const onSubmit = () => {
-    formRef.value?.validate((valid) => {
-        if (valid) {
-            addOrUpdate().then(() => {
-                ElMessage.success('提交成功')
-                onCancel(true)
-            }).catch((err) => {
-                ElMessage.error('提交失败:' + err)
-            })
-        }
-    })
-}
-</script>

+ 6 - 4
src/packages/pc/views/account/address/index.vue

@@ -45,7 +45,6 @@ const componentMap = new Map<string, unknown>([
     ['edit', defineAsyncComponent(() => import('./components/edit/index.vue'))],
     ['default', defineAsyncComponent(() => import('./components/default/index.vue'))],
     ['delete', defineAsyncComponent(() => import('./components/delete/index.vue'))],
-    ['new', defineAsyncComponent(() => import('./components/new/index.vue'))],
 ])
 
 const { rowKey, expandKeys, selectedRow, rowClick } = useComposeTable<Model.UserReceiveInfoRsp>({ rowKey: 'autoid' })
@@ -58,14 +57,17 @@ const { componentRef, componentId, openComponent, closeComponent } = useComponen
 
 const tableColumns = shallowRef<Model.TableColumn[]>([
     { prop: 'receivername', label: '收货人' },
-    { prop: 'cardtypeid', label: '证件类型' },
-    { prop: 'cardnum', label: '证件号码' },
+    // { prop: 'cardtypeid', label: '证件类型' },
+    // { prop: 'cardnum', label: '证件号码' },
     { prop: 'phonenum', label: '联系电话' },
     { prop: 'address', label: '收货地址' },
     { prop: 'isdefault', label: '是否默认' },
 ])
 
 filterOptons.buttonList = [
-    { lable: '新增地址', className: 'el-button--primary', onClick: () => openComponent('new') },
+    { lable: '新增地址', className: 'el-button--primary', onClick: () => {
+        selectedRow.value = undefined
+        openComponent('edit') 
+    }},
 ]
 </script>

+ 0 - 75
src/packages/pc/views/account/receipt/components/new/index.vue

@@ -1,75 +0,0 @@
-<!-- 账户管理-发票信息管理-编辑 -->
-<template>
-    <app-drawer title='新增发票' :width="460" v-model:show="show" :loading="loading"
-        :refresh="refresh">
-        <el-form ref="formRef" class="el-form--vertical" label-width="100px" :model="formData" :rules="formRules">
-            <el-form-item label="发票类型" prop="ReceiptType">
-                <el-radio-group v-model="formData.ReceiptType">
-                    <el-radio :label="1">个人</el-radio>
-                    <el-radio :label="2">企业</el-radio>
-                </el-radio-group>
-            </el-form-item>
-            <el-form-item label="发票抬头" prop="UserName">
-                <el-input placeholder="请输入" v-model="formData.UserName" />
-            </el-form-item>
-            <template v-if="formData.ReceiptType === 2">
-                <el-form-item label="税号" prop="TaxpayerID">
-                    <el-input placeholder="请输入" v-model="formData.TaxpayerID" />
-                </el-form-item>
-                <el-form-item label="开户银行" prop="ReceiptBank">
-                    <el-input placeholder="请输入" v-model="formData.ReceiptBank" />
-                </el-form-item>
-                <el-form-item label="银行账号" prop="ReceiptAccount">
-                    <el-input placeholder="请输入" v-model="formData.ReceiptAccount" />
-                </el-form-item>
-                <el-form-item label="企业地址" prop="Address">
-                    <el-input placeholder="请输入" v-model="formData.Address" />
-                </el-form-item>
-                <el-form-item label="企业电话" prop="ContactInfo">
-                    <el-input placeholder="请输入" v-model="formData.ContactInfo" />
-                </el-form-item>
-            </template>
-        </el-form>
-        <template #footer>
-            <el-button type="info" @click="onCancel(false)">取消</el-button>
-            <el-button type="primary" @click="onSubmit">提交</el-button>
-        </template>
-    </app-drawer>
-</template>
-
-<script lang="ts" setup>
-import { ref } from 'vue'
-import { ElMessage } from 'element-plus'
-import type { FormInstance, FormRules } from 'element-plus'
-import { useInvoiceForm } from '@/business/user/invoice'
-import AppDrawer from '@pc/components/base/drawer/index.vue'
-
-const { loading, formData, addOrUpdate } = useInvoiceForm()
-const show = ref(true)
-const refresh = ref(false)
-const formRef = ref<FormInstance>()
-
-const formRules: FormRules = {
-    ReceiptType: [{ required: true, message: '请选择发票类型' }],
-    UserName: [{ required: true, message: '请输入发票抬头', trigger: 'blur' }],
-    TaxpayerID: [{ required: true, message: '请输入税号', trigger: 'blur' }],
-}
-
-const onCancel = (isRefresh = false) => {
-    show.value = false
-    refresh.value = isRefresh
-}
-
-const onSubmit = () => {
-    formRef.value?.validate((valid) => {
-        if (valid) {
-            addOrUpdate().then(() => {
-                ElMessage.success('提交成功')
-                onCancel(true)
-            }).catch((err) => {
-                ElMessage.error('提交失败:' + err)
-            })
-        }
-    })
-}
-</script>

+ 5 - 3
src/packages/pc/views/account/receipt/index.vue

@@ -34,7 +34,6 @@ import AppFilter from '@pc/components/base/table-filter/index.vue'
 
 const componentMap = new Map<string, unknown>([
     ['edit', defineAsyncComponent(() => import('./components/edit/index.vue'))],
-    ['new', defineAsyncComponent(() => import('./components/new/index.vue'))],
     ['delete', defineAsyncComponent(() => import('./components/delete/index.vue'))],
 ])
 
@@ -53,10 +52,13 @@ const tableColumns = shallowRef<Model.TableColumn[]>([
     { prop: 'receiptbank', label: '开户银行' },
     { prop: 'receiptaccount', label: '银行账号' },
     { prop: 'contactinfo', label: '企业电话' },
-    { prop: 'information', label: '企业信息' },
+    { prop: 'address', label: '企业地址' },
 ])
 
 filterOptons.buttonList = [
-    { lable: '新增发票', className: 'el-button--primary', onClick: () => openComponent('new') },
+    { lable: '新增发票', className: 'el-button--primary', onClick: () => { 
+        selectedRow.value = undefined
+        openComponent('new') 
+    } },
 ]
 </script>

+ 8 - 4
src/packages/pc/views/account/sign/components/cancel/index.vue

@@ -3,7 +3,7 @@
     <app-drawer title="提示" v-model:show="show" :loading="loading" :refresh="refresh">
         <div>确认要解约吗?</div>
         <template #footer>
-            <el-button @click="onCancel(false)" plain>取消</el-button>
+            <el-button type="info" @click="onCancel(false)">取消</el-button>
             <el-button type="primary" @click="onCancelSumit()">提交</el-button>
         </template>
     </app-drawer>
@@ -15,14 +15,14 @@ import { ElMessage } from 'element-plus'
 import { useDoCancelBankSign } from '@/business/bank'
 import AppDrawer from '@pc/components/base/drawer/index.vue'
 
-defineProps({
+const props = defineProps({
     selectedRow: {
         type: Object as PropType<Model.BankAccountSignRsp>,
         required: true
     }
 })
 
-const { cancelSubmit, loading } = useDoCancelBankSign()
+const { cancelSubmit, loading, formData } = useDoCancelBankSign()
 
 const show = ref(true)
 const refresh = ref(false)
@@ -33,12 +33,16 @@ const onCancel = (isRefresh = false) => {
 }
 
 const onCancelSumit = () => {
+    const { cusbankid, currency, accountcode } = props.selectedRow
+    formData.Currency = currency
+    formData.CusBankID = cusbankid
+    formData.AccountCode = accountcode
     /// 提交
     cancelSubmit().then(() => {
         ElMessage.success('提交成功')
         onCancel(true)
     }).catch((err) => {
-        ElMessage.error('提交失败:' + err)
+        ElMessage.error(err)
     })
 }
 </script>

+ 91 - 0
src/packages/pc/views/account/sign/components/certification/index.vue

@@ -0,0 +1,91 @@
+<!-- 账户管理-实名认证 -->
+<template>
+    <app-drawer title="实名认证" v-model:show="show" :width="500" :loading="loading" :refresh="refresh">
+        <el-form ref="formRef" class="el-form--vertical" label-width="100px" :rules="formRules">
+            <el-form-item prop="username" label="姓名">
+                <el-input placeholder="请输入用户姓名" v-model="formData.username" name="username" :rules="formRules.username" />
+            </el-form-item>
+            <el-form-item prop="cardnum" label="证件号码">
+                <el-input placeholder="请输入证件号码" v-model="formData.cardnum" name="cardnum" :rules="formRules.cardnum" />
+            </el-form-item>
+            <el-form-item label="证件类型" prop="cardtype">
+                <el-select v-model="formData.cardtype">
+                    <el-option :label="item.label" :value="item.value" v-for="(item, index) in enums" :key="index" />
+                </el-select>
+            </el-form-item>
+            <el-form-item label="证件正面照片">
+                <app-upload :file-types="['image']" type-message="请选择正确的图片类型" @change="b_afterRead"
+                    :rules="formRules.cardfrontphotourl" />
+            </el-form-item>
+            <el-form-item label="证件反面照片">
+                <app-upload :file-types="['image']" type-message="请选择正确的图片类型" @change="f_afterRead"
+                    :rules="formRules.cardbackphotourl" />
+            </el-form-item>
+        </el-form>
+        <template #footer>
+            <el-button type="info" @click="onCancel(false)">取消</el-button>
+            <el-button type="primary" @click="onSubmit">提交</el-button>
+        </template>
+    </app-drawer>
+</template>  
+
+<script lang="ts" setup>
+import { ref, computed } from 'vue'
+import { ElMessage, FormInstance, FormRules } from 'element-plus'
+import { getCertificateTypeList } from "@/constants/account";
+import { addAuthReq } from '@/business/user'
+import AppUpload from '@pc/components/base/upload/index.vue'
+import AppDrawer from '@pc/components/base/drawer/index.vue'
+
+const show = ref(true)
+const refresh = ref(false)
+const formRef = ref<FormInstance>()
+const { formData, formSubmit, loading } = addAuthReq()
+
+/// 获取对应的证件枚举类型
+const enums = computed(() => { return getCertificateTypeList().map(obj => { return { label: obj.label, value: obj.value } }) })
+
+const b_afterRead = (filePath: string) => {
+    formData.cardfrontphotourl = filePath
+}
+
+const f_afterRead = (filePath: string) => {
+    formData.cardbackphotourl = filePath
+}
+
+// 表单验证规则
+const formRules: FormRules = {
+    username: [{
+        required: true,
+        message: '请输入用户姓名',
+        trigger: 'blur'
+    }],
+    cardnum: [{
+        required: true,
+        message: '请输入证件号码',
+        trigger: 'blur'
+    }],
+    cardbackphotourl: [{
+        required: true,
+        message: '请上传证件背面照片',
+    }],
+    cardfrontphotourl: [{
+        required: true,
+        message: '请上传证件正面照片',
+    }],
+}
+
+const onCancel = (isRefresh = false) => {
+    show.value = false
+    refresh.value = isRefresh
+}
+
+const onSubmit = () => {
+    formSubmit().then(() => {
+        ElMessage.success('实名认证提交请求成功')
+        onCancel(true)
+    }).catch((err) => {
+        ElMessage.error('实名认证提交请求失败:' + err)
+    })
+}
+</script>

+ 13 - 9
src/packages/pc/views/account/sign/components/sign/index.vue

@@ -2,25 +2,27 @@
 <template>
     <app-drawer :title="bankInfo ? '修改签约账户' : '添加签约账户'" :width="460" v-model:show="show" :loading="loading"
         :refresh="refresh">
-        <el-form ref="formRef" class="el-form--vertical" label-width="100px" :model="bankInfo" :rules="formRules">
+        <el-form ref="formRef" class="el-form--vertical" label-width="100px" :model="formData" :rules="formRules">
             <el-form-item label="开户银行" prop="OpenBankAccId">
                 <el-select v-model="formData.OpenBankAccId">
-                    <el-option :label="item.bankname" :value="item.bankid" v-for="(item, index) in banklist"
-                        :key="index" />
+                    <el-option :label="item.bankname" :value="item.bankid" v-for="(item, index) in banklist" :key="index" />
                 </el-select>
             </el-form-item>
             <el-form-item label="银行卡号" prop="BankAccountNo">
-                <el-input name="BankAccountNo" placeholder="银行卡账户名" v-model="formData.BankAccountNo" :rules="formRules.BankAccountNo"/>
+                <el-input name="BankAccountNo" placeholder="银行卡号" :maxlength="30" v-model="formData.BankAccountNo"
+                    :rules="formRules.BankAccountNo" />
             </el-form-item>
             <el-form-item label="姓名" prop="BankAccountName">
-                <el-input name="BankAccountName" placeholder="银行卡账户名" v-model="formData.BankAccountName" :rules="formRules.BankAccountName"/>
+                <el-input name="BankAccountName" readonly placeholder="银行卡账户名" v-model="formData.BankAccountName"
+                    :rules="formRules.BankAccountName" />
             </el-form-item>
             <el-form-item label="支行名称" prop="BranchBankName">
-                <el-input name="BranchBankName" placeholder="请输入银行卡支行名称" v-model="formData.OpenBankName" :rules="formRules.OpenBankName"/>
+                <el-input name="BranchBankName" placeholder="请输入银行卡支行名称" :maxlength="20" v-model="formData.OpenBankName"
+                    :rules="formRules.OpenBankName" />
             </el-form-item>
         </el-form>
         <template #footer>
-            <el-button type="info" @click="onCancel(false)" plain>取消</el-button>
+            <el-button type="info" @click="onCancel(false)">取消</el-button>
             <el-button type="primary" @click="formSubmit">{{ bankInfo ? '修改' : '提交' }}</el-button>
         </template>
     </app-drawer>
@@ -31,8 +33,9 @@ import { ref } from 'vue'
 import { ElMessage } from 'element-plus'
 import type { FormInstance, FormRules } from 'element-plus'
 import { useDoBankSign } from '@/business/bank'
-import AppDrawer from '@pc/components/base/drawer/index.vue'
+import { useErrorInfoStore } from '@/stores'
 import { validateRules } from '@/constants/regex'
+import AppDrawer from '@pc/components/base/drawer/index.vue'
 
 const formRules: FormRules = {
     OpenBankAccId: [{
@@ -78,7 +81,8 @@ const formSubmit = () => {
         ElMessage.success(bankInfo ? '签约信息修改成功' : '签约提交成功,请耐心等待审核。')
         onCancel(true)
     }).catch((err) => {
-        ElMessage.error('提交失败:' + err)
+        const { getErrorInfoByCode } = useErrorInfoStore()
+        ElMessage(getErrorInfoByCode(Number(err)) ?? '')
     })
 }
 

+ 17 - 8
src/packages/pc/views/account/sign/index.vue

@@ -3,7 +3,9 @@
     <app-table :data="dataList" v-model:columns="tableColumns" :loading="loading" :row-key="rowKey"
         :expand-row-keys="expandKeys" @row-click="rowClick">
         <template #header>
-            <app-filter :options="filterOptons" />
+            <el-button type="primary" v-if="authStatus === AuthStatus.Certified"
+                @click="openComponent('sign')">添加签约账户</el-button>
+            <el-button type="warning" v-else @click="openComponent('certification')">实名认证</el-button>
         </template>
         <!-- 证件类型 -->
         <template #cardtype="{ value }">
@@ -28,25 +30,26 @@
 </template>
 
 <script lang="ts" setup>
-import { shallowRef, defineAsyncComponent } from 'vue'
+import { shallowRef, defineAsyncComponent, onMounted } from 'vue'
 import { useComponent } from '@/hooks/component'
 import { useComposeTable } from '@pc/components/base/table'
 import { useRequest } from '@/hooks/request'
-import { useDataFilter } from '@/hooks/datatable'
 import { queryBankAccountSign } from '@/services/api/bank'
 import { getSignStatusName, SignStatus } from '@/constants/bank'
 import { getCertificateTypeCodeName } from '@/constants/account'
+import { queryUserAccount } from '@/services/api/account'
+import { AuthStatus } from '@/constants/account'
 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>([
     ['cancel', defineAsyncComponent(() => import('./components/cancel/index.vue'))],
     ['sign', defineAsyncComponent(() => import('./components/sign/index.vue'))],
+    ['certification', defineAsyncComponent(() => import('./components/certification/index.vue'))], // 实名认证
 ])
 
 const { rowKey, expandKeys, rowClick, selectedRow } = useComposeTable<Model.BankAccountSignRsp>({ rowKey: 'applyexchticket' })
-const { filterOptons } = useDataFilter<Model.BankAccountSignReq>()
 const { loading, dataList, run } = useRequest(queryBankAccountSign, {})
+const authStatus = shallowRef(AuthStatus.Uncertified) // 实名认证状态
 
 const { componentRef, componentId, openComponent, closeComponent } = useComponent(() => {
     run()
@@ -64,7 +67,13 @@ const tableColumns = shallowRef<Model.TableColumn[]>([
     { prop: 'signstatus', label: '状态' },
 ])
 
-filterOptons.buttonList = [
-    { lable: '添加签约账户', className: 'el-button--primary', onClick: () => openComponent('sign') },
-]
+onMounted(() => {
+    if (authStatus.value !== AuthStatus.Certified) {
+        // 获取用户账号信息
+        queryUserAccount().then((res) => {
+            authStatus.value = res.data.hasauth
+        })
+    }
+})
+
 </script>

+ 2 - 2
src/packages/pc/views/auth/components/layout/index.vue

@@ -15,9 +15,9 @@
         </div>
       </div>
     </div>
-    <div class="sign-layout__footer">
+    <!-- <div class="sign-layout__footer">
       <span>Copyright ©{{ year }} 深圳市多元世纪信息技术股份有限公司 版权所有 粤ICP备00000000号</span>
-    </div>
+    </div> -->
   </div>
 </template>
 

+ 159 - 0
src/packages/pc/views/auth/forget/index.vue

@@ -0,0 +1,159 @@
+<template>
+    <el-form ref="formRef" :model="formData" :rules="formRules">
+        <el-form-item prop="mobile">
+            <el-input placeholder="请输入手机号码" type="number" v-model="formData.mobile" :rules="formRules.mobile" />
+        </el-form-item>
+        <el-form-item prop="vcode">
+            <el-input placeholder="请输入短信验证码" type="number" v-model="formData.vcode" :rules="formRules.vcode">
+                <template #append>
+                    <el-button size="small" type="primary" :disabled="isCountdown" @click="sendVerifyCode">
+                        <span v-if="isCountdown">重新发送({{ seconds }})</span>
+                        <span v-else>获取验证码</span>
+                    </el-button>
+                </template>
+            </el-input>
+        </el-form-item>
+        <el-form-item prop="password">
+            <el-input placeholder="请输入新密码" type="password" v-model="formData.password" :rules="formRules.password" />
+        </el-form-item>
+        <el-form-item prop="confirmpassword">
+            <el-input placeholder="请输入确认密码" type="password" v-model="formData.confirmpassword"
+                :rules="formRules.confirmpassword" />
+        </el-form-item>
+        <el-form-item>
+            <el-button type="primary" @click="formSubmit">重置密码</el-button>
+            <el-button @click="onClose" style="margin-left: auto;">返回</el-button>
+        </el-form-item>
+    </el-form>
+</template>
+
+<script lang="ts" setup>
+import { reactive, ref } from 'vue'
+import { ElMessage, FormInstance, FormRules } from 'element-plus'
+import { getEncryptMobile } from '@/filters'
+import { validateRules } from '@/constants/regex'
+import { queryLoginId } from '@/services/api/account'
+import { resetPassword, sendResetVerifyCode } from '@/services/api/common'
+import cryptojs from 'crypto-js'
+import service from '@/services'
+
+const emit = defineEmits(['close'])
+const formRef = ref<FormInstance>()
+const seconds = ref(60) //倒计时剩余时间
+const isCountdown = ref(false) // 是否正在倒计时
+
+// 表单数据
+const formData = reactive<Model.ResetPasswordReq & { confirmpassword: string }>({
+    logincode: '',
+    mobile: '',
+    vcode: '',
+    password: '',
+    confirmpassword: '',
+})
+
+// 表单验证规则
+const formRules: FormRules = {
+    mobile: [{
+        required: true,
+        validator: (rule, value, callback) => {
+            if (value && validateRules.phone.validate(value)) {
+                callback()
+            }
+            callback(new Error(validateRules.phone.message))
+        }
+    }],
+    password: [{
+        required: true,
+        validator: (rule, value, callback) => {
+            if (validateRules.password.validate(value)) {
+                callback()
+            }
+            callback(new Error('密码必须是任意两种字符组合,长度最少6位'))
+        }
+    }],
+    vcode: [{
+        required: true,
+        message: '请输入短信验证码',
+    }],
+    confirmpassword: [{
+        required: true,
+        validator: (rule, value, callback) => {
+            if (formData.password === value) {
+                callback()
+            }
+            callback(new Error('新密码和确认密码不一致'))
+        }
+    }],
+}
+
+// 发送手机验证码
+const sendVerifyCode = () => {
+    formRef.value?.validateField('mobile', (valid) => {
+        if (valid) {
+            service.onReady().then(() => {
+                sendResetVerifyCode({
+                    data: {
+                        mobile: getEncryptMobile(formData.mobile),
+                        businessType: 1
+                    }
+                }).then(() => {
+                    isCountdown.value = true
+                    // 开始倒计时
+                    const countDown = window.setInterval(() => {
+                        seconds.value--
+                        if (seconds.value <= 0) {
+                            clearInterval(countDown)
+                            isCountdown.value = false
+                        }
+                    }, 1000)
+                }).catch(() => {
+                    ElMessage.error('发送失败')
+                })
+            }).catch((err) => {
+                ElMessage.error(err)
+            })
+        }
+    })
+}
+
+const formSubmit = () => {
+    formRef.value?.validate(async (valid) => {
+        if (valid) {
+            queryLoginId({
+                data: {
+                    username: formData.mobile
+                }
+            }).then((res) => {
+                const { mobile, password, vcode } = formData
+                const logincode = res.data
+                const encryptedData = cryptojs.SHA256(logincode + password).toString()
+                const encryptedHex = cryptojs.enc.Hex.parse(encryptedData).toString().toLocaleLowerCase()
+
+                resetPassword({
+                    data: {
+                        logincode,
+                        mobile: getEncryptMobile(mobile),
+                        password: encryptedHex,
+                        vcode,
+                    }
+                }).then((res) => {
+                    if (res.code === '0') {
+                        ElMessage.success('密码重置成功,请重新登录。')
+                        onClose()
+                    } else {
+                        ElMessage.error(res.message)
+                    }
+                }).catch((err) => {
+                    ElMessage.error(err)
+                })
+            }).catch((err) => {
+                ElMessage.error(err)
+            })
+        }
+    })
+}
+
+const onClose = () => {
+    emit('close')
+}
+</script>

+ 7 - 1
src/packages/pc/views/auth/login/index.less

@@ -1 +1,7 @@
-.user-login {}
+.user-login {
+    .text-link {
+        color: #666;
+        cursor: pointer;
+        margin-left: auto;
+    }
+}

+ 6 - 4
src/packages/pc/views/auth/login/index.vue

@@ -1,6 +1,6 @@
 <template>
-  <sign-layout class="user-login" title="登录">
-    <el-form ref="formRef" :model="formData" :rules="formRules">
+  <sign-layout class="user-login" :title="islogin ? '登录' : '重置密码'">
+    <el-form ref="formRef" :model="formData" :rules="formRules" v-if="islogin">
       <el-form-item prop="userName">
         <el-input placeholder="用户名/账号/手机号" v-model="formData.userName"></el-input>
       </el-form-item>
@@ -10,15 +10,16 @@
       </el-form-item>
       <el-form-item>
         <el-checkbox label="false" v-model="remember">记住账号</el-checkbox>
+        <span class="text-link" @click="islogin = false">忘记密码?</span>
       </el-form-item>
       <el-form-item>
         <el-button class="submit" type="primary" :loading="loading" @click="formSubmit">
           <span v-if="loading">正在登录</span>
           <span v-else>登录</span>
         </el-button>
-        <!-- <el-button>注册</el-button> -->
       </el-form-item>
     </el-form>
+    <Forget @close="islogin = true" v-else></Forget>
   </sign-layout>
 </template>
 
@@ -31,6 +32,7 @@ import { ClientType } from '@/constants/client'
 import { useLogin } from '@/business/login'
 import { useMenuStore } from '@/stores'
 import SignLayout from '../components/layout/index.vue'
+import Forget from "../forget/index.vue";
 
 const { formData, remember, userLogin } = useLogin()
 const route = useRoute()
@@ -38,7 +40,7 @@ const router = useRouter()
 const menuStore = useMenuStore()
 const formRef = shallowRef<FormInstance>()
 const loading = shallowRef(false)
-//const remember = shallowRef(false) // 记住账号
+const islogin = shallowRef(true)
 
 const formRules: FormRules = {
   userName: [

+ 4 - 4
src/packages/pc/views/footer/capital/summary/deposit/index.vue

@@ -1,12 +1,13 @@
 <!-- 资金信息-资金汇总-充值 -->
 <template>
-    <app-drawer title="充值" v-model:show="show" :loading="loading" :refresh="refresh">
+    <app-drawer title="充值" :width="500" v-model:show="show" :loading="loading" :refresh="refresh">
         <el-form ref="formRef" class="el-form--vertical" label-width="100px" label-position="left" :model="formData"
             :rules="formRules">
             <el-form-item prop="Amount" label="充值金额">
-                <el-input-number placeholder="请输入" v-model="formData.Amount" />
+                <el-input-number placeholder="请输入" :max="9999999999" :precision="2" v-model="formData.Amount"
+                    :rules="formRules.Amount" />
             </el-form-item>
-            <el-form-item label="凭证">
+            <el-form-item label="凭证" prop="filePath">
                 <app-upload :file-types="['image']" type-message="请选择正确的图片类型" @change="onUploadChange" />
             </el-form-item>
         </el-form>
@@ -41,7 +42,6 @@ const formRules: FormRules = {
 }
 
 const onUploadChange = (file: { filePath: string }) => {
-    console.log(file.filePath)
     extendInfo.certificate_photo_url = file.filePath
 }
 

+ 37 - 5
src/packages/pc/views/footer/capital/summary/index.vue

@@ -9,8 +9,8 @@
         <!-- 展开行 -->
         <template #expand>
             <div class="buttonbar">
-                <el-button type="danger" size="small" @click="openComponent('deposit')">充值</el-button>
-                <el-button type="primary" size="small" @click="openComponent('withdraw')">提现</el-button>
+                <el-button type="danger" size="small" @click="doInOutMoney('deposit')">充值</el-button>
+                <el-button type="primary" size="small" @click="doInOutMoney('withdraw')">提现</el-button>
             </div>
         </template>
         <template #footer>
@@ -21,12 +21,16 @@
 </template>
 
 <script lang="ts" setup>
-import { shallowRef, defineAsyncComponent } from 'vue'
+import { shallowRef, defineAsyncComponent, onMounted } from 'vue'
 import { useAccountStore } from '@/stores'
 import { useComponent } from '@/hooks/component'
 import { useComposeTable } from '@pc/components/base/table'
-import AppTable from '@pc/components/base/table/index.vue'
 import { getTradeStatusName } from '@/constants/order'
+import { AuthStatus } from '@/constants/account'
+import { queryBankAccountSign } from '@/services/api/bank'
+import { queryUserAccount } from '@/services/api/account'
+import AppTable from '@pc/components/base/table/index.vue'
+import { ElMessage } from 'element-plus'
 
 const componentMap = new Map<string, unknown>([
     ['deposit', defineAsyncComponent(() => import('./deposit/index.vue'))], // 充值
@@ -34,6 +38,7 @@ const componentMap = new Map<string, unknown>([
 ])
 
 const accountStore = useAccountStore()
+const authStatus = shallowRef(AuthStatus.Uncertified) // 实名认证状态
 const { selectedRow, rowKey, expandKeys, rowClick } = useComposeTable<Model.TaAccountsRsp>({ rowKey: 'accountid' })
 const { componentRef, componentId, openComponent, closeComponent } = useComponent()
 
@@ -42,10 +47,37 @@ const tableColumns = shallowRef<Model.TableColumn[]>([
     { prop: 'balance', label: '期初余额', decimal: 2 },
     { prop: 'currentbalance', label: '期末余额', decimal: 2 },
     { prop: 'avaiableMoney', label: '可用资金', decimal: 2 },
-    { prop: 'oriusedmargin', label: '占用资金', decimal: 2 },
+    { prop: 'usedmargin', label: '占用资金', decimal: 2 },
     { prop: 'freezeMargin', label: '冻结资金', decimal: 2 },
     { prop: 'inamount', label: '今日入金', decimal: 2 },
     { prop: 'outamount', label: '今日出金', decimal: 2 },
     { prop: 'tradestatus', label: '状态' },
 ])
+
+/// 进行出入金操作判断
+const doInOutMoney = (code: string) => {
+    if (authStatus.value === AuthStatus.Certified) {
+        queryBankAccountSign().then((res) => {
+            const { signstatus } = res.data[0] ?? {}
+            /// 只有已签约的情况下才可以进行出入金
+            if (signstatus && signstatus === 4) {
+                openComponent(code)
+            } else {
+                ElMessage({ showClose: true, message: '请先添加签约账户信息!', })
+            }
+        })
+    } else {
+        ElMessage({ showClose: true, message: '请先实名认证,再进行该操作!' })
+    }
+}
+
+onMounted(() => {
+    accountStore.getAccountList()
+    if (authStatus.value !== AuthStatus.Certified) {
+        // 获取用户账号信息
+        queryUserAccount().then((res) => {
+            authStatus.value = res.data.hasauth
+        })
+    }
+})
 </script>

部分文件因文件數量過多而無法顯示