huangbin 4 gadi atpakaļ
vecāks
revīzija
9d81b91d83

+ 88 - 0
src/common/setup/table/tableQuote.ts

@@ -0,0 +1,88 @@
+import { addSubscribeQuotation, removeSubscribeQuotation } from '@/services/socket/quota';
+import TimerUtils from '@/utils/timer/timerUtil';
+import { v4 } from 'uuid';
+import { onBeforeUnmount, onMounted, Ref, ref, watchEffect } from "vue";
+
+/**
+ * 处理行情按需订阅
+ * @param tableList 全部表格数据
+ * @param codeKey 需要订阅商品code对应的key
+ * @param itemTableHeight 表格每一行的高度
+ * @param selector 当前的滚动区域的选择器
+ */
+export function handleSubcriteQuote<T extends object>(tableList: Ref<T[]>, codeKey = 'goodscode', itemTableHeight = 35, selector = '.ant-table-body') {
+    const beforeScrollTop = ref<number>(0)
+    const uuid = v4();
+    onMounted(() => {
+        listenSrcoll(document.querySelector(selector)!)
+    });
+    onBeforeUnmount(() => {
+        removeSubscribeQuotation(uuid);
+        TimerUtils.clearTimeout('subscribeQuote')
+    })
+    // 第一次自动订阅当前可视区域的数据
+    const stop = watchEffect(() => {
+        const len = tableList.value.length
+        if (len) {
+            const end = len > 16 ? 16 : len;
+            subscribeAction(0, end)
+        }
+    })
+    function listenSrcoll(ele: Element) {
+        ele.addEventListener('scroll', (event: any) => {
+            stop && stop()
+            debounceSroll(event)
+        }, true)
+    }
+    // 判断滚动方向
+    function srollDrection(event: any) {
+        const { scrollTop, offsetHeight } = event.target
+        const diffSrollTop = scrollTop - beforeScrollTop.value
+        if (diffSrollTop === 0) {
+            // 横向滚动
+            return
+        } else if (diffSrollTop > 0) {
+            // 向下滚动
+            caclcuteSubcribeNum(scrollTop, offsetHeight)
+        } else {
+            // 向上滚动
+            caclcuteSubcribeNum(scrollTop, offsetHeight)
+        }
+        beforeScrollTop.value = scrollTop
+    }
+    /**
+     *
+     * @param scrollTop 当前滚动条所处的位置
+     * @param offsetHeight 当前滚动范围的可视区域的高度
+     */
+    function caclcuteSubcribeNum(scrollTop: number, offsetHeight: number) {
+        // 可视区域的列表行数
+        const rowNum = Math.ceil(offsetHeight / itemTableHeight) - 1;
+        const tableIndex = scrollTop < itemTableHeight ? 0 : Math.ceil(scrollTop / itemTableHeight)
+        // 开始订阅
+        subscribeAction(tableIndex, tableIndex + rowNum)
+    }
+    // 防抖
+    function debounceSroll(event: any) {
+        TimerUtils.clearTimeout('subscribeQuote')
+        TimerUtils.setTimeout(() => {
+            srollDrection(event)
+        }, 200, 'subscribeQuote')
+    }
+    // 开始订阅
+    function subscribeAction(start: number, end: number) {
+        removeSubscribeQuotation(uuid);
+        const result: Array<{ exchangeCode: 250, goodsCode: string, subState: 0 }> = []
+        for (let i = start; i < end; i++) {
+            const obj = tableList.value[i] as unknown as any
+            if (Reflect.has(obj, codeKey)) {
+                result.push({ exchangeCode: 250, goodsCode: obj[codeKey], subState: 0 })
+            } else {
+                console.warn(`订阅商品的code对应的key${codeKey}不存在,请手动传入!`)
+            }
+
+        }
+        console.log('开始订阅', result)
+        addSubscribeQuotation(uuid, result);
+    }
+}

+ 4 - 4
src/services/socket/quota/adapter/byteUtils.ts

@@ -1,4 +1,4 @@
-import { subscribeInfoType } from '@/services/socket/quota/interface';
+import { SubscribeInfoType } from '@/services/socket/quota/interface';
 
 /**
  * 将无符号整型数值型转化为二进制数组的方法
@@ -56,10 +56,10 @@ function stringToByteArray(value: string, isLittleEndian: boolean): Uint8Array {
 
 /**
  * 将某个订阅商品转为二进制
- * @param param subscribeInfoType
+ * @param param SubscribeInfoType
  * @returns {Uint8Array}
  */
-function subscribeInfoToByteArrary(param: subscribeInfoType): Uint8Array {
+function subscribeInfoToByteArrary(param: SubscribeInfoType): Uint8Array {
     const { subState, exchangeCode, goodsCode } = param;
     const dataArray = new Uint8Array(66);
 
@@ -86,7 +86,7 @@ function subscribeInfoToByteArrary(param: subscribeInfoType): Uint8Array {
  * @param token
  * @param loginId 登录id
  */
-export function subscribeInfosToByteArrary(arr: subscribeInfoType[], token: string, loginId: any): Uint8Array {
+export function subscribeInfosToByteArrary(arr: SubscribeInfoType[], token: string, loginId: any): Uint8Array {
     const count = arr.length;
     const dataArray = new Uint8Array(76 + 66 * count);
     // 处理登录账号id

+ 4 - 4
src/services/socket/quota/adapter/index.ts

@@ -7,13 +7,13 @@ import { QueryQuoteDayRsp } from '@/services/go/quote/interface';
 import { mergeObj } from '@/utils/objHandle';
 import { Package40 } from '@/utils/websocket/package';
 import Long from 'long';
-import { subscribeInfoType } from '../interface';
+import { SubscribeInfoType } from '../interface';
 import { byteArrayToUInt, subscribeInfosToByteArrary } from './byteUtils';
 
 /**
  * 构建行情订阅请求包
  */
-export function buildSubscribePeq(subscribeInfos: subscribeInfoType[]): Package40 {
+export function buildSubscribePeq(subscribeInfos: SubscribeInfoType[]): Package40 {
     // 如果是登录状态,就走正常行情链路. 否则走游客
     const loginId = isLogin() ? getLongTypeLoginID() : Long.fromNumber(2);
     const token = isLogin() ? getToken() : '2_TOKEN_NEKOT_';
@@ -26,7 +26,7 @@ export function buildSubscribePeq(subscribeInfos: subscribeInfoType[]): Package4
  * 解析行情订阅请求包
  * @param rspPackage
  */
-export function parseSubscribeRsp(rspPackage: any): Promise<string | subscribeInfoType[]> {
+export function parseSubscribeRsp(rspPackage: any): Promise<string | SubscribeInfoType[]> {
     return new Promise((resolve, reject) => {
         const content = rspPackage.content;
         if (content.length === 0) {
@@ -54,7 +54,7 @@ export function parseSubscribeRsp(rspPackage: any): Promise<string | subscribeIn
         if (!count || count > (content.length - 4) / 66) {
             reject('行情订阅返回数据不正确');
         }
-        const result: subscribeInfoType[] = [];
+        const result: SubscribeInfoType[] = [];
         let position = 4;
         for (let i = 0; i < count; i++) {
             const dataArray = content.subarray(position, position + 66);

+ 8 - 8
src/services/socket/quota/index.ts

@@ -1,16 +1,16 @@
-import { funCode } from '@/services/funcode/index';
 import APP from '@/services';
+import { funCode } from '@/services/funcode/index';
 import { buildSubscribePeq, parseSubscribeRsp } from '@/services/socket/quota/adapter/index';
 import { Callback } from '@/utils/websocket/index';
-import { subscribeInfoType } from './interface';
+import { SubscribeInfoType } from './interface';
 
-const subscribeGoodsList = new Map<string, subscribeInfoType[]>(); // 订阅商品数据中心池
+const subscribeGoodsList = new Map<string, SubscribeInfoType[]>(); // 订阅商品数据中心池
 
 /**
  * 重组订阅商品(包括去重,组合)
  */
-function recombinationSubscribeGoods(): subscribeInfoType[] {
-    const result: subscribeInfoType[] = [];
+function recombinationSubscribeGoods(): SubscribeInfoType[] {
+    const result: SubscribeInfoType[] = [];
     const goodsCodeSet = new Set<string>();
     for (const item of subscribeGoodsList.values()) {
         item.forEach((e) => {
@@ -38,10 +38,10 @@ function actionSubcribe() {
                     }
                 })
                 .catch((err) => {
-                    console.log(err);
+                    console.log('订阅失败:', err);
                 });
         },
-        onFail: (err) => console.log(err),
+        onFail: (err) => console.log('订阅失败:', err),
     } as Callback);
 }
 
@@ -49,7 +49,7 @@ function actionSubcribe() {
  * 添加行情订阅
  * @param subscribeInfos
  */
-export function addSubscribeQuotation(uuid: string, subscribeInfos: subscribeInfoType[]) {
+export function addSubscribeQuotation(uuid: string, subscribeInfos: SubscribeInfoType[]) {
     APP.connectQuote().then(() => {
         subscribeGoodsList.set(uuid, subscribeInfos);
         actionSubcribe();

+ 1 - 1
src/services/socket/quota/interface.ts

@@ -1,7 +1,7 @@
 /**
  * 订阅商品信息
  */
-export interface subscribeInfoType {
+export interface SubscribeInfoType {
     exchangeCode: number; // 交易所代码, 1 Byte MTP 2.0 由于交易所代码服务端未下发,暂时写死250
     goodsCode: string; // 商品代码,64 Byte,不足位使用'\0'补齐
     subState: number; // 订阅成功标志;1为成功,0为失败,订阅的时候填0, 1 Byte

+ 1 - 0
src/utils/timer/timerUtil.ts

@@ -16,6 +16,7 @@ export interface TimeoutTimerNames {
     debounceInput: string; // 输入框防抖
     debounceOnSearch: string; // 搜索框防抖
     overtimeOut: string; // 超时,如果太久没有操作界面,则退出登录
+    subscribeQuote: string; //按需订阅防抖
 }
 
 class TimerUtils {

+ 100 - 98
src/views/market/spot_trade/components/buy-sell-market/index.vue

@@ -1,101 +1,104 @@
 <template>
-    <!-- 买卖大厅 -->
-    <div class="buy-sell-market">
-        <div class="buy-sell-market-title">
-            <a class="backIcon" @click="cancel">
-                <LeftOutlined />
-            </a>
-            <div class="titleBtn">
-                <div class="name">{{selectedRow.deliverygoodsname}}</div>
-                <div class="arrowRightIcon"></div>
-            </div>
-            <div class="titleBtn titleBtn2">
-                <div class="arrowLeftIcon"></div>
-                <div class="name">{{selectedRow.wrgoodsname}}</div>
-                <div class="arrowRightIcon"></div>
-            </div>
-            <div class="titleBtn titleBtn2">
-                <div class="arrowLeftIcon"></div>
-                <div class="name">{{selectedRow.warehousename}}</div>
-                <div class="arrowRightIcon"></div>
-            </div>
-            <div class="titleBtn titleBtn3" v-if="!isWR(enumName)">
-                <div class="arrowLeftIcon"></div>
-                <div class="name">
-                    <a-month-picker
-                        :allowClear="false"
-                        v-model:value="time"
-                        @change="timeChange"
-                        class="commonDatePicker conditionPicker"
-                    />
-                </div>
-                <DownOutlined />
-            </div>
-            <div class="green bdf1 ml20">
-                <div class="numBlock ml15" v-if="isFloat()">
-                    <div class="first">卖基差</div>
-                    <div class="last">{{selectedRow.sellpricemove}}</div>
-                </div>
-                <div class="numBlock ml15" v-else>
-                    <div class="first">卖价</div>
-                    <div class="last">{{selectedRow.sellprice}}</div>
-                </div>
-                <div class="numBlock">
-                    <div class="first">卖量</div>
-                    <div class="last">{{selectedRow.sellqty}}</div>
-                </div>
-            </div>
-            <div class="red ml35">
-                <div class="numBlock" v-if="isFloat()">
-                    <div class="first">买基差</div>
-                    <div class="last">{{selectedRow.buypricemove}}</div>
-                </div>
-                <div class="numBlock" v-else>
-                    <div class="first">买价</div>
-                    <div class="last">{{selectedRow.buyprice}}</div>
-                </div>
-                <div class="numBlock">
-                    <div class="first">买量</div>
-                    <div class="last">{{selectedRow.buyqty}}</div>
-                </div>
-            </div>
-            <div class="market" v-if="isFloat()">
-                <div class="first">{{selectedRow.goodscode}}</div>
-                <div class="last red">{{getGoodsPrice()}}</div>
-                <LineChartOutlined />
-            </div>
-            <BtnList :btnList="firstBtn" :record="selectedRow" @click="openComponent" />
+  <!-- 买卖大厅 -->
+  <div class="buy-sell-market">
+    <div class="buy-sell-market-title">
+      <a class="backIcon"
+         @click="cancel">
+        <LeftOutlined />
+      </a>
+      <div class="titleBtn">
+        <div class="name">{{selectedRow.deliverygoodsname}}</div>
+        <div class="arrowRightIcon"></div>
+      </div>
+      <div class="titleBtn titleBtn2">
+        <div class="arrowLeftIcon"></div>
+        <div class="name">{{selectedRow.wrgoodsname}}</div>
+        <div class="arrowRightIcon"></div>
+      </div>
+      <div class="titleBtn titleBtn2">
+        <div class="arrowLeftIcon"></div>
+        <div class="name">{{selectedRow.warehousename}}</div>
+        <div class="arrowRightIcon"></div>
+      </div>
+      <div class="titleBtn titleBtn3"
+           v-if="!isWR(enumName)">
+        <div class="arrowLeftIcon"></div>
+        <div class="name">
+          <a-month-picker :allowClear="false"
+                          v-model:value="time"
+                          @change="timeChange"
+                          class="commonDatePicker conditionPicker" />
         </div>
-        <a-row class="buySellHall">
-            <a-col :span="12" v-if="sellMarket.isMarket">
-                <Sell
-                    :enumName="enumName"
-                    ref="sellRef"
-                    :parantSelectedRow="selectedRow"
-                    :time="time"
-                    :btnList="handleBtnList(sellMarket.btnList)"
-                />
-            </a-col>
-            <a-col :span="12" v-if="buyMarket.isMarket">
-                <Buy
-                    :enumName="enumName"
-                    ref="buyRef"
-                    :time="time"
-                    :parantSelectedRow="selectedRow"
-                    :btnList="handleBtnList(buyMarket.btnList)"
-                />
-            </a-col>
-        </a-row>
-        <component
-            :is="componentId"
-            v-if="componentId"
-            :selectedRow="selectedRow"
-            :goodsPrice="getGoodsPrice()"
-            :enumName="enumName"
-            :time="time"
-            @cancel="closeComponent"
-        ></component>
+        <DownOutlined />
+      </div>
+      <div class="green bdf1 ml20">
+        <div class="numBlock ml15"
+             v-if="isFloat()">
+          <div class="first">卖基差</div>
+          <div class="last">{{selectedRow.sellpricemove}}</div>
+        </div>
+        <div class="numBlock ml15"
+             v-else>
+          <div class="first">卖价</div>
+          <div class="last">{{selectedRow.sellprice}}</div>
+        </div>
+        <div class="numBlock">
+          <div class="first">卖量</div>
+          <div class="last">{{selectedRow.sellqty}}</div>
+        </div>
+      </div>
+      <div class="red ml35">
+        <div class="numBlock"
+             v-if="isFloat()">
+          <div class="first">买基差</div>
+          <div class="last">{{selectedRow.buypricemove}}</div>
+        </div>
+        <div class="numBlock"
+             v-else>
+          <div class="first">买价</div>
+          <div class="last">{{selectedRow.buyprice}}</div>
+        </div>
+        <div class="numBlock">
+          <div class="first">买量</div>
+          <div class="last">{{selectedRow.buyqty}}</div>
+        </div>
+      </div>
+      <div class="market"
+           v-if="isFloat()">
+        <div class="first">{{selectedRow.goodscode}}</div>
+        <div class="last red">{{getGoodsPrice()}}</div>
+        <LineChartOutlined />
+      </div>
+      <BtnList :btnList="firstBtn"
+               :record="selectedRow"
+               @click="openComponent" />
     </div>
+    <a-row class="buySellHall">
+      <a-col :span="12"
+             v-if="sellMarket.isMarket">
+        <Sell :enumName="enumName"
+              ref="sellRef"
+              :parantSelectedRow="selectedRow"
+              :time="time"
+              :btnList="handleBtnList(sellMarket.btnList)" />
+      </a-col>
+      <a-col :span="12"
+             v-if="buyMarket.isMarket">
+        <Buy :enumName="enumName"
+             ref="buyRef"
+             :time="time"
+             :parantSelectedRow="selectedRow"
+             :btnList="handleBtnList(buyMarket.btnList)" />
+      </a-col>
+    </a-row>
+    <component :is="componentId"
+               v-if="componentId"
+               :selectedRow="selectedRow"
+               :goodsPrice="getGoodsPrice()"
+               :enumName="enumName"
+               :time="time"
+               @cancel="closeComponent"></component>
+  </div>
 </template>
 
 <script lang="ts">
@@ -109,7 +112,7 @@ import Buy from './components/buy/index.vue';
 import Sell from './components/sell/index.vue';
 import { LineChartOutlined, DownOutlined } from '@ant-design/icons-vue';
 import { handleModalComponent } from '@/common/setup/asyncComponent';
-import { onMounted, PropType, ref } from 'vue';
+import { onBeforeUnmount, onMounted, PropType, ref } from 'vue';
 import { handleSpotBtnList } from '../../setup';
 import { v4 } from 'uuid';
 import { addSubscribeQuotation, removeSubscribeQuotation } from '@/services/socket/quota';
@@ -165,7 +168,7 @@ export default defineComponent({
             const arr = [{ exchangeCode: 250, goodsCode: props.selectedRow.goodscode, subState: 0 }];
             addSubscribeQuotation(uuid, arr);
         }
-        onMounted(() => {
+        onBeforeUnmount(() => {
             removeSubscribeQuotation(uuid);
             TimerUtils.clearInterval('buyAndSellMartet');
             TimerUtils.clearTimeout('debounce');
@@ -227,5 +230,4 @@ export default defineComponent({
 });
 </script>
 <style lang="less">
-
 </style>

+ 10 - 39
src/views/market/spot_trade/spot_trade_order_transaction/setup.ts

@@ -1,4 +1,5 @@
 import { TradeMode } from "@/common/constants/enumCommon"
+import { initData } from "@/common/methods"
 import { getMarketByTradeMode } from "@/services/bus/market"
 import { queryDeliveryRelation } from "@/services/go/delivery"
 import { QueryDeliveryRelationRsp } from "@/services/go/delivery/interface"
@@ -22,49 +23,19 @@ export function handleDeliveryRelation(param: deliverytype[]) {
     function getDeliverGoods() {
         return allDeliverGoods.value.filter(e => param.includes(e.deliverytype as deliverytype))
     }
-    // initData(() => {
-    //     if (allDeliverGoods.value.length === 0) {
-    //         // 从服务交割商品
-    //         queryAction()
-    //     } else {
-    //         // 从缓存中获取交割商品
-    //         deliverGoods.value = getDeliverGoods()
-    //     }
-    // })
+    initData(() => {
+        if (allDeliverGoods.value.length === 0) {
+            // 从服务交割商品
+            queryAction()
+        } else {
+            // 从缓存中获取交割商品
+            deliverGoods.value = getDeliverGoods()
+        }
+    })
     // 更新交割商品
     function updateGeliverGoods() {
         queryAction()
     }
-    deliverGoods.value.length = 0
-    for (let i = 0; i < 200; i++) {
-        const obj = {
-            wrfactortypeid: '2121628355212000001',
-            buyprice: 1000,
-            buyqty: 1,
-            sellprice: 1,
-            sellqty: 1,
-            wrfactortypename: '广州一号仓,广州铜,优,广州',
-            deliverygoodsid: 1,
-            wrstandardid: 1,
-            warehouseid: 2,
-            deliverygoodsname: '铜',
-            deliverygoodscode: 'CU',
-            warehousename: '广州一号仓',
-            warehousecode: 'GZ0001',
-            wrstandardname: '广州黄铜',
-            wrstandardcode: 'CU',
-            wrgoodsname: '广州黄铜-广州铜-优-广州',
-            buypricemove: 0,
-            sellpricemove: 0,
-            goodsid: 0,
-            goodscode: '--',
-            deliverymonth: '0',
-            enumdicname: '吨',
-            minivalue: 1,
-            key: `${i}`,
-        }
-        deliverGoods.value.push(obj)
-    }
 
     return { deliverGoods, updateGeliverGoods }
 }

+ 4 - 1
src/views/market/spot_trade/spot_trade_order_transaction/spot_trade_order_transaction_basis_difference/index.vue

@@ -31,7 +31,8 @@ import { handleComposeTable } from '@/views/market/spot_trade/setup';
 import Bus from '@/utils/eventBus/index';
 import Filter from '../../components/filter/index.vue';
 import { handleDeliveryRelation } from '../setup';
-
+import { handleSubcriteQuote } from '@/common/setup/table/tableQuote';
+import { QueryDeliveryRelationRsp } from '@/services/go/delivery/interface';
 export default defineComponent({
     name: EnumRouterName.spot_trade_order_transaction_basis_difference,
     components: {
@@ -45,6 +46,8 @@ export default defineComponent({
         // 表格列表数据
         const { loading, tableList, queryTable } = queryTableList<WrOrderQuote>();
         const { deliverGoods } = handleDeliveryRelation([2, 4]);
+        // 行情按需订阅
+        handleSubcriteQuote<QueryDeliveryRelationRsp>(deliverGoods);
         // 获取列表数据
         const queryTableAction = () => {
             const param: QueryOrderQuoteReq = {

+ 8 - 16
src/views/market/spot_trade/spot_trade_order_transaction/spot_trade_order_transaction_listing_transfer/index.vue

@@ -32,8 +32,9 @@ import { handleComposeTable } from '@/views/market/spot_trade/setup';
 import Bus from '@/utils/eventBus/index';
 import Filter from '../../components/filter/index.vue';
 import { handleDeliveryRelation } from '../setup';
-import { ref } from 'vue';
-import { onMounted } from '@vue/runtime-core';
+import { ref, onMounted } from 'vue';
+import { handleSubcriteQuote } from '@/common/setup/table/tableQuote';
+import { QueryDeliveryRelationRsp } from '@/services/go/delivery/interface';
 
 export default defineComponent({
     name: EnumRouterName.spot_trade_order_transaction_listing_transfer,
@@ -46,21 +47,12 @@ export default defineComponent({
     },
     setup() {
         // 表格列表数据
-        const { loading, tableList, queryTable } = queryTableList<WrOrderQuote>();
+        const { loading, tableList, queryTable } = queryTableList<QueryDeliveryRelationRsp>();
         const tableRef = ref<any>(null);
-        onMounted(() => {
-            // tableRef.value!.srcollYTable.addEventListener('sroll', (event: Event) => {
-            //     console.log('======='), event;
-            // });
-            console.log('document.querySelector)', document.querySelector('.ant-table-body'));
-            document.querySelector('.ant-table-body')!.addEventListener('sroll', (event: Event) => {
-                console.log('======='), event;
-            });
-        });
+
         const { deliverGoods } = handleDeliveryRelation([1, 3]);
-        window.addEventListener('srcol', () => {
-            console.log('=======');
-        });
+        // 行情按需订阅
+        handleSubcriteQuote<QueryDeliveryRelationRsp>(deliverGoods);
         // 获取列表数据
         const queryTableAction = () => {
             const param: QueryOrderQuoteReq = {
@@ -78,7 +70,7 @@ export default defineComponent({
             isDetail: false,
         };
         return {
-            ...handleComposeTable<WrOrderQuote>(param),
+            ...handleComposeTable<QueryDeliveryRelationRsp>(param),
             loading,
             tableList,
             deliverGoods,