Переглянути джерело

Merge branch 'mtp_v6' of http://47.101.159.18:3000/Muchinfo/MTP2.0_WEB into mtp_v6

huangbin 4 роки тому
батько
коміт
51cb5cb2ed

+ 39 - 0
public/proto/mtp.proto

@@ -2054,4 +2054,43 @@ message HolderCloseRsp {
         optional string RetDesc = 3; // string 描述信息
         optional uint64 OrderID = 4; // uint64 一级生成的订单号
         optional string OrderTime = 5; // string 接收委托交易的时间
+}
+
+// 交易委托请求 0 3 31
+message ChannelOrderReq {
+	optional MessageHead Header = 1; // MessageHead
+	optional string ClientSerialNo = 2; // string 客户端流水号
+	optional string ClientOrderTime = 3; // string 客户端委托时间
+	optional uint32 ClientType = 4; // uint32 终端类型
+	optional uint64 LoginID = 5; // uint64 登陆账号
+	optional uint64 AccountID = 6; // uint64 交易账号
+	optional uint32 GoodsID = 7; // uint32 商品ID
+	optional uint32 MarketID = 8; // uint32 市场ID
+	optional int32 ValidType = 9; // int32 有效类型 - 1当日有效
+	optional uint32 ChannelOperateType = 10; // uint32 操作类型:
+	optional uint32 ChannelOrderSrc = 11; // uint32 单据来源委托来源 -  1:客户端 2:管理端 3:风控服务 
+	optional uint32 HedgeFlag = 12; // uint32 投机套保标志 - 0:无 1:投机 2:套保 3:套利 4:套期保值 5:单边 6:移仓 7:错单处理 8:跨期套利
+	optional uint64 OperatorID = 13; // uint64 操作员账号ID
+	optional double OrderPrice = 14; // double 委托价格
+	optional uint64 OrderQty = 15; // uint64 委托数量
+	optional uint32 BuyOrSell = 16; // uint32 买卖方向(买卖 - 0:买 1:卖 )
+	optional uint32 ChannelBuildType = 17; // uint32 下单类型(开平标志 - 0:无 1:建仓 2:平仓)
+	optional uint32 CloseType = 18; // uint32 平仓方式(平仓方式 - 0:无 1:平今 2:平昨)
+	optional uint32 PriceMode = 19; // uint32 取价方式 - 1:市价 2: 限价
+	optional uint32 TimeValidType = 20; // uint32 时间有效类型
+	optional uint64 RelatedID = 21; // uint64 关联单号
+	optional string ServiceTime = 22; // string 服务端时间
+	optional string validtime = 23; // string 有效时间
+	optional uint64 CloseTodayQty = 24; // uint64 平今仓数量
+	optional uint64 SpotContractID = 25; // uint64 现货合同ID - 为4:套期保值时填写
+	optional uint64 SaleUserID = 26; // uint64 业务员ID
+	optional uint64 BizSubjectID = 27; // uint64 归属业务部门ID
+}
+// 交易委托应答 0 3 32
+message ChannelOrderRsp {
+	optional MessageHead Header = 1; // MessageHead 消息头
+	optional int32 RetCode = 2; // int32 返回码
+	optional string RetDesc = 3; // string 描述信息
+	optional uint64 OrderID = 4; // uint64 一级生成的订单号
+	optional string OrderTime = 5; // string 接收委托交易的时间
 }

+ 24 - 0
src/common/setup/table/interface.ts

@@ -1,6 +1,30 @@
 import { EnumRouterName } from "@/common/constants/enumRouterName";
 import { ColumnType, TableKey } from "@/common/methods/table/interface";
 import { OperationTabMenu } from "@/services/go/commonService/interface";
+import { Ref } from 'vue';
+
+/**
+ * 表格行情列表
+ */
+export interface TableQuote {
+    goodscode: string; // 商品代码
+    goodsname: string; // 商品名称
+    decimalplace: number;
+    last?: Ref; // 最新价
+    bid?: Ref; // 买价
+    ask?: Ref; // 卖价
+    bidvolume?: Ref; // 买量
+    askvolume?: Ref; // 卖量
+    totalvolume?: Ref; // 总量
+    lastvolume?: Ref; // 现量
+    holdvolume?: Ref; // 持仓量
+    holdincrement?: Ref; // 日增
+    presettle?: Ref; // 昨结价
+    totalturnover?: Ref; // 金额
+    opened?: Ref; // 开盘
+    highest?: Ref; // 最高
+    lowest?: Ref; // 最低
+}
 
 export interface TableEventCB {
     clickCB?: Function; // 单击事件回调函数

+ 26 - 12
src/common/setup/table/tableQuote.ts

@@ -82,7 +82,7 @@ export function handleSubcriteOnDemandQuote<T extends object>(tableList: Ref<T[]
         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)) {
+            if (Object.prototype.hasOwnProperty.call(obj, codeKey)) {
                 result.push({ exchangeCode: 250, goodsCode: obj[codeKey], subState: 0 })
             } else {
                 console.warn(`订阅商品的code对应的key${codeKey}不存在,请手动传入!`)
@@ -140,20 +140,34 @@ export function handleQuotePriceColor(value: number, presettle: number) {
     return result
 }
 
-// 涨跌 最新价 - 昨结价
-export function quoteChange(record: QueryQuoteDayRsp, decimalplace = 2) {
-    const { presettle, last } = record
-    let result = '--'
-    if (isPrice(last, presettle)) {
-        result = (last - presettle).toFixed(decimalplace)
+// 涨跌额/涨跌 最新价 - 昨结价
+export function quoteChange<T>(record: T, decimalplace = 2) {
+    type Key = keyof T;
+    const presettle = record['presettle' as Key];
+    const last = record['last' as Key];
+
+    if (typeof presettle === 'number' && typeof last === 'number') {
+        const calc = last - presettle;
+        if (calc !== 0) {
+            return calc.toFixed(decimalplace);
+        }
     }
-    return result
+    return '--';
 }
 
-// 幅度(最新价 - 昨结价) / 昨结价) *  100 %
-export function quoteAmplitude(record: QueryQuoteDayRsp, decimalplace = 2) {
-    const result = quoteChange(record, decimalplace)
-    return result === '--' ? '--' : (+result / record.presettle * 100).toFixed(decimalplace) + '%'
+// 涨跌幅/幅度((最新价 - 昨结价) / 昨结价) *  100 %
+export function quoteAmplitude<T>(record: T, decimalplace = 2) {
+    type Key = keyof T;
+    const presettle = record['presettle' as Key];
+    const result = quoteChange(record, decimalplace);
+
+    if (typeof presettle === 'number' && result !== '--') {
+        const calc = Number(result) / presettle * 100;
+        if (!isNaN(calc)) {
+            return calc.toFixed(decimalplace) + '%';
+        }
+    }
+    return '--';
 }
 
 // 振幅 (最高价 - 最低价 ) / 最新价  * 100 %

+ 4 - 0
src/services/funcode/index.ts

@@ -233,4 +233,8 @@ export const funCode: Code = {
     HolderCloseReq: 196713,
     /// 按单平仓应答(196714)
     HolderCloseRsp: 196714,
+
+    // 期货交易
+    ChannelOrderReq: 196639, // 交易委托请求 0 3 31
+    ChannelOrderRsp: 196640, // 交易委托应答 0 3 32
 };

+ 12 - 0
src/services/proto/futures/index.ts

@@ -0,0 +1,12 @@
+import { getUserId } from "@/services/bus/user";
+import { geLoginID_number } from "@/services/bus/login";
+import { ChannelOrderReq, ChannelOrderRsp } from "./interface";
+import { protoMiddleware } from "@/services/socket/protobuf/buildReq";
+
+/**
+ * 期货交易委托请求
+ * @param param
+ */
+export const channelOrderReq = (param: ChannelOrderReq): Promise<ChannelOrderRsp> => {
+    return protoMiddleware<ChannelOrderReq>(param, 'ChannelOrderReq', 'ChannelOrderRsp', 2)
+}

+ 37 - 0
src/services/proto/futures/interface.ts

@@ -0,0 +1,37 @@
+// 交易委托请求 0 3 31
+export interface ChannelOrderReq {
+    ClientSerialNo: string; // string 客户端流水号
+    ClientOrderTime: string; // string 客户端委托时间
+    ClientType: number; // uint32 终端类型
+    LoginID: number; // uint64 登陆账号
+    AccountID: number; // uint64 交易账号
+    GoodsID: number; // uint32 商品ID
+    MarketID: number; // uint32 市场ID
+    ValidType: number; // int32 有效类型 - 1当日有效
+    ChannelOperateType: number; // uint32 操作类型:
+    ChannelOrderSrc: number; // uint32 单据来源委托来源 -  1:客户端 2:管理端 3:风控服务 
+    HedgeFlag: number; // uint32 投机套保标志 - 0:无 1:投机 2:套保 3:套利 4:套期保值 5:单边 6:移仓 7:错单处理 8:跨期套利
+    OperatorID: number; // uint64 操作员账号ID
+    OrderPrice: number; // double 委托价格
+    OrderQty: number; // uint64 委托数量
+    BuyOrSell: number; // uint32 买卖方向(买卖 - 0:买 1:卖 )
+    ChannelBuildType: number; // uint32 下单类型(开平标志 - 0:无 1:建仓 2:平仓)
+    CloseType: number; // uint32 平仓方式(平仓方式 - 0:无 1:平今 2:平昨)
+    PriceMode: number; // uint32 取价方式 - 1:市价 2: 限价
+    TimeValidType: number; // uint32 时间有效类型
+    RelatedID: number; // uint64 关联单号
+    ServiceTime: string; // string 服务端时间
+    validtime: string; // string 有效时间
+    CloseTodayQty: number; // uint64 平今仓数量
+    SpotContractID: number; // uint64 现货合同ID - 为4:套期保值时填写
+    SaleUserID: number; // uint64 业务员ID
+    BizSubjectID: number; // uint64 归属业务部门ID
+}
+
+// 交易委托应答 0 3 32
+export interface ChannelOrderRsp {
+    RetCode: number; // int32 返回码
+    RetDesc: string; // string 描述信息
+    OrderID: number; // uint64 一级生成的订单号
+    OrderTime: string; // string 接收委托交易的时间
+}

+ 9 - 3
src/views/market/futures/compoments/futures-trade/index.vue

@@ -10,7 +10,9 @@
             </a-select>
           </a-form-item>
           <a-form-item label="合约">
-            <a-select class="inlineFormSelect" placeholder="请选择"></a-select>
+            <a-select class="inlineFormSelect" placeholder="请选择" v-model:value="formState.goodscode">
+              <a-select-option v-for="item in tableList" :value="item.goodscode" :key="item.goodscode">{{ item.goodsname }}</a-select-option>
+            </a-select>
           </a-form-item>
           <a-form-item label="交易价格">
             <a-input-number class="commonInput" />
@@ -78,7 +80,7 @@ import { getAccountTypeList } from '@/services/bus/account';
 import { MinusOutlined, PlusOutlined } from '@ant-design/icons-vue';
 import moment, { Moment } from 'moment';
 import { defineComponent, PropType, ref } from 'vue';
-import { TempWrOrderQuoteDetail } from './interface';
+import { TempTableQuoteDetail } from './interface';
 import { handleForm } from './setup';
 
 export default defineComponent({
@@ -87,9 +89,13 @@ export default defineComponent({
     components: { Des, Drawer, PlusOutlined, MinusOutlined },
     props: {
         selectedRow: {
-            type: Object as PropType<TempWrOrderQuoteDetail>,
+            type: Object as PropType<TempTableQuoteDetail>,
             default: {},
         },
+        tableList: {
+            type: Array as PropType<TempTableQuoteDetail[]>,
+            default: [],
+        },
     },
     setup(props, context) {
         const { visible, cancel } = _closeModal(context);

+ 3 - 2
src/views/market/futures/compoments/futures-trade/interface.ts

@@ -1,8 +1,9 @@
-import { WrOrderQuote } from "@/services/go/wrtrade/interface";
+import { TableQuote } from '@/common/setup/table/interface';
 import { Moment } from "moment";
 
 export interface FormParam {
     accountid: undefined | number,
+    goodscode: undefined | string,
     FixedPrice: number,
     OrderQty: number,
     PriceMove: number,
@@ -11,6 +12,6 @@ export interface FormParam {
 }
 
 
-export interface TempWrOrderQuoteDetail extends WrOrderQuote {
+export interface TempTableQuoteDetail extends TableQuote {
     wrResult: { dgfactoryitemtypeid: number; dgfactoryitemid: number }[]
 }

+ 8 - 6
src/views/market/futures/compoments/futures-trade/setup.ts

@@ -1,11 +1,12 @@
 import { useVerifyListingBasis, useVerifyListingNum } from '@/hooks/form/verify';
 import moment from "moment";
 import { onBeforeUnmount, reactive, ref, UnwrapRef } from "vue";
-import { FormParam, TempWrOrderQuoteDetail } from "./interface";
+import { FormParam, TempTableQuoteDetail } from "./interface";
 
 function initFormData(): FormParam {
     return {
         accountid: undefined,
+        goodscode: undefined,
         FixedPrice: 0,
         OrderQty: 0,
         PriceMove: 0,
@@ -14,12 +15,13 @@ function initFormData(): FormParam {
     }
 }
 const formState: UnwrapRef<FormParam> = reactive(initFormData())
-export function handleForm(selectedRow: TempWrOrderQuoteDetail) {
+export function handleForm(selectedRow: TempTableQuoteDetail) {
     const formRef = ref();
-    formState.OrderQty = selectedRow.minivalue
+    formState.OrderQty = selectedRow.decimalplace;
+    formState.goodscode = selectedRow.goodscode;
 
-    const { v_num } = useVerifyListingNum<FormParam, 'DelistMinQty'>(formState, 'DelistMinQty', selectedRow.minivalue);
-    const { v_basis } = useVerifyListingBasis(selectedRow, 'goodsid');
+    const { v_num } = useVerifyListingNum<FormParam, 'DelistMinQty'>(formState, 'DelistMinQty', selectedRow.decimalplace);
+    const { v_basis } = useVerifyListingBasis(selectedRow, 'goodscode');
 
     const rules = {
         FixedPrice: [{ required: true, message: '请输入挂牌价格', trigger: 'blur', type: 'number', }],
@@ -28,7 +30,7 @@ export function handleForm(selectedRow: TempWrOrderQuoteDetail) {
         accountid: [{ required: true, message: '请输入交易账号' }],
     }
     onBeforeUnmount(() => {
-        Object.assign(formState, initFormData(), { OrderQty: selectedRow.minivalue })
+        Object.assign(formState, initFormData(), { OrderQty: selectedRow.decimalplace })
     })
     return { rules, formState, formRef }
 }

+ 7 - 80
src/views/market/futures/index.vue

@@ -1,50 +1,15 @@
 <template>
   <!--期货-->
   <div class="topTableHeight">
-    <a-table :columns="getColumnsList()" :class="['srcollYTable', isBottom ? 'condSecondTabTable' : 'condSecondTabTableNoBottom', tableList.length ? 'noPlaceHolder' : 'hasPlaceHolder']" :scroll="{ x: '100%', y: isBottom ? 'calc(100vh- 443px)' : 'calc(100vh - 196px)' }" :pagination="false" :loading="loading" :customRow="Rowclick" rowKey="key" :data-source="tableList">
-      <template #totalturnover="{ text }">
-        <span>{{changeUnit(text)}}</span>
-      </template>
-      <!-- 涨跌 -->
-      <template #change="{ record }">
-        <span>{{quoteChange(record, record.decimalplace)}}</span>
-      </template>
-      <!-- 幅度 -->
-      <template #amplitude="{ record }">
-        <span>{{quoteAmplitude(record, record.decimalplace)}}</span>
-      </template>
-      <!-- 振幅 -->
-      <template #vibration="{ record }">
-        <span>{{quoteAmplituOfVibration(record, record.decimalplace)}}</span>
-      </template>
+    <a-table :columns="getColumnsList()" :class="['srcollYTable', isBottom ? 'condSecondTabTable' : 'condSecondTabTableNoBottom', tableList.length ? 'noPlaceHolder' : 'hasPlaceHolder']" :scroll="{ x: '100%', y: isBottom ? 'calc(100vh- 443px)' : 'calc(100vh - 196px)' }" :pagination="false" :loading="loading" :customRow="Rowclick" rowKey="goodscode" :data-source="tableList">
       <template #index="{ index }">
         <span>{{index + 1}}</span>
       </template>
-      <!-- 买价 -->
-      <template #bid="{ text, record }">
-        <span :class="handleQuotePriceColor(text, record.presettle)">{{text}}</span>
-      </template>
-      <!-- 卖价 -->
-      <template #ask="{ text, record }">
-        <span :class="handleQuotePriceColor(text, record.presettle)">{{text}}</span>
-      </template>
-      <!-- 最新价 -->
-      <template #last="{ text, record }">
-        <span :class="handleQuotePriceColor(text, record.presettle)">{{text}}</span>
-      </template>
-      <!-- 最低价 -->
-      <template #lowest="{ text, record }">
-        <span :class="handleQuotePriceColor(text, record.presettle)">{{text}}</span>
-      </template>
-      <!-- 最高价 -->
-      <template #highest="{ text, record }">
-        <span :class="handleQuotePriceColor(text, record.presettle)">{{text}}</span>
-      </template>
     </a-table>
     <ThridMenu :list="tabList" :selectedKey="index" @selectMenu="changeTab" />
     <!-- 右键 -->
     <contextMenu :contextMenu="contextMenu" @cancel="closeContext" :list="buttons"></contextMenu>
-    <component :is="componentId" v-if="componentId" :selectedRow="selectedRow" @cancel="closeComponent"></component>
+    <component :is="componentId" v-if="componentId" :tableList="tableList" :selectedRow="selectedRow" @cancel="closeComponent"></component>
   </div>
 </template>
 
@@ -53,9 +18,8 @@ import { TabList } from '@/common/components/description/interface';
 import ThridMenu from '@/common/components/thirdMenu/index.vue';
 import { getShowBottomValue } from '@/common/config/constrolBottom';
 import { handleModalComponent } from '@/common/setup/asyncComponent';
-import { handleQuotePriceColor, handleSubcriteOnDemandQuote, quoteAmplitude, quoteAmplituOfVibration, quoteChange } from '@/common/setup/table/tableQuote';
+import { handleSubcriteOnDemandQuote } from '@/common/setup/table/tableQuote';
 import { QueryQuoteDayRsp } from '@/services/go/quote/interface';
-import { ref, reactive, Ref, toRefs } from 'vue';
 import { getColumnsList, useExternalexchange } from './setup';
 import { getTableButton } from '@/common/setup/table/button';
 import { contextMenu, defineAsyncComponent, defineComponent } from '@/common/export/commonTable';
@@ -64,9 +28,6 @@ import { TableEventCB } from '@/common/setup/table/interface';
 import { getTableEvent } from '@/common/export/table';
 import { ContextMenuTemp } from '@/common/components/contextMenu/interface';
 import { BtnListType } from '@/common/components/btnList/interface';
-import APP from '@/services';
-import { Goods } from '@/services/go/ermcp/goodsInfo/interface';
-import { getQuoteDayInfoByCode } from '@/services/bus/goods';
 
 export default defineComponent({
     name: 'spot_trade_order_transaction_swap',
@@ -76,36 +37,14 @@ export default defineComponent({
         trade: defineAsyncComponent(() => import('./compoments/futures-trade/index.vue')),
     },
     setup() {
-        interface Quote {
-            goodscode: string;
-            goodsname: string;
-            decimalplace: number;
-            last?: Ref;
-            presettle?: Ref;
-        }
-
-        const goodsList = APP.get('Goods') as Goods[];
-        const tableList = reactive<Quote[]>([]);
-        const quoteList = ref<QueryQuoteDayRsp[]>([]);
-
-        goodsList.forEach((el) => {
-            const quote = getQuoteDayInfoByCode(el.goodscode);
-            if (quote) {
-                quoteList.value.push(quote);
-            }
-            tableList.push({
-                goodscode: el.goodscode,
-                goodsname: el.goodsname,
-                decimalplace: el.decimalplace,
-            });
-        });
-
         const isBottom = getShowBottomValue();
         const buttons = getTableButton();
         console.log('buttons', buttons);
-        const { index, loading, tabList, hanldeQuoteData } = useExternalexchange();
+        const { index, loading, tabList, tableList, quoteList, hanldeQuoteData, hanldeTableData } = useExternalexchange();
         // 行情按需订阅
         let stopSubcribe = handleSubcriteOnDemandQuote<QueryQuoteDayRsp>(quoteList);
+        hanldeTableData();
+
         function changeTab(index: number, current: TabList) {
             hanldeQuoteData(index);
             console.log(index, current);
@@ -113,17 +52,9 @@ export default defineComponent({
             stopSubcribe();
             // 重新发起订阅
             stopSubcribe = handleSubcriteOnDemandQuote<QueryQuoteDayRsp>(quoteList);
+            hanldeTableData();
         }
 
-        quoteList.value.forEach((item) => {
-            const refs = toRefs(item);
-            const index = tableList.findIndex((e) => e.goodscode === item.goodscode);
-            if (index > -1) {
-                tableList[index].last = refs.last;
-                tableList[index].presettle = refs.presettle;
-            }
-        });
-
         // 右键逻辑
         const { contextMenu, closeContext: closeContextAction } = handleContextMenu();
         // 右键回调函数
@@ -152,10 +83,6 @@ export default defineComponent({
             changeTab,
             tableList,
             isBottom,
-            handleQuotePriceColor,
-            quoteChange,
-            quoteAmplitude,
-            quoteAmplituOfVibration,
             getColumnsList,
             buttons,
             contextMenu,

+ 0 - 228
src/views/market/futures/setup.ts

@@ -1,228 +0,0 @@
-import { TabList } from '@/common/components/description/interface';
-import { initData } from '@/common/methods';
-import APP from '@/services';
-import { getQuoteDayInfoByCode } from '@/services/bus/goods';
-import { Ermcp3GoodsGroup, Goods } from '@/services/go/ermcp/goodsInfo/interface';
-import { QueryQuoteDayRsp } from '@/services/go/quote/interface';
-import { Externalexchange } from '@/services/go/useInfo/interface';
-import { ref } from 'vue';
-
-
-export function getColumnsList() {
-    const columns = [
-        { title: '序号', key: 'index', width: 80 },
-        { title: '代码', key: 'goodscode' },
-        { title: '名称', key: 'goodsname' },
-
-        { title: '买价', key: 'bid' },
-        { title: '买量', key: 'bidvolume' },
-        { title: '卖价', key: 'ask' },
-        { title: '卖量', key: 'askvolume' },
-
-        { title: '当前价', key: 'last' },
-        { title: '涨跌', key: 'change' }, // 最新价 - 昨结价
-        { title: '幅度', key: 'amplitude' }, // (最新价 - 昨结价) / 100 %
-        { title: '开盘', key: 'opened' },
-        { title: '最高', key: 'highest' },
-        { title: '最低', key: 'lowest' },
-
-        { title: '结算', key: 'settle' },
-
-        { title: '昨结算', key: 'presettle' },
-
-        // { title: '振幅', key: 'vibration' }, // (最高价 - 最低价 ) / 最新价  * 100 %
-        // { title: '总量', key: 'totalvolume' },
-        // { title: '现量', key: 'lastvolume' },
-        // { title: '持仓量', key: 'holdvolume' },
-        // { title: '日增', key: 'holdincrement' },
-        // { title: '金额', key: 'totalturnover' },
-    ];
-
-    return columns.map(el => {
-        return { dataIndex: el.key, width: 100, align: 'center', slots: { customRender: el.key, }, ...el }
-    })
-}
-
-// 外部交易所
-export const useExternalexchange = () => {
-    const loading = ref<boolean>(false)
-    const index = ref<string>('0');
-    // 外部交易所 数据
-    const externalexchangeList = ref<Externalexchange[]>([])
-    const tabList = ref<TabList[]>([])
-    // 盘面数据
-    const tableList = ref<QueryQuoteDayRsp[]>([
-    ])
-    // 获取 商品数据
-    const useGoodsList = (exchareaid: number) => {
-        const goodsList = APP.get('Goods') as Goods[];
-        const goodsGroups = APP.get('goodsgroups') as Ermcp3GoodsGroup[]
-        // 商品组
-        const selectedGoodsGroups = goodsGroups.filter(e => e.exexchangeid === exchareaid).map(el => el.goodsgroupid)
-        return goodsList.filter(e => {
-            return e.goodsstatus === 3 && selectedGoodsGroups.includes(e.goodsgroupid)
-        })
-
-    }
-
-    initData(() => {
-        externalexchangeList.value = APP.get('externalexchange')
-        const list = externalexchangeList.value.map((e: Externalexchange) => {
-            return { lable: e.exexchangename, code: e.exexchangecode };
-        }) as TabList[]
-
-        tabList.value = list
-        if (list.length) {
-            hanldeQuoteData(0)
-        }
-    })
-    function hanldeQuoteData(index: number) {
-        const id = getExternalId(index)
-        // 找到 交易所 下的商品列表
-        const goodsList = useGoodsList(id)
-        // 找到 盘面数据
-        getQuoteData(goodsList)
-    }
-    function getQuoteData(goodsList: Goods[]) {
-        tableList.value.length = 0
-        // 找到盘面数据
-        goodsList.forEach(el => {
-            const quote = getQuoteDayInfoByCode(el.goodscode);
-            if (quote) {
-                tableList.value.push(quote)
-            } else {
-                tableList.value.push({
-                    ask: 0,
-                    ask1number: 0,
-                    ask2: 0,
-                    ask3: 0,
-                    ask4: 0,
-                    ask5: 0,
-                    ask6: 0,
-                    ask7: 0,
-                    ask8: 0,
-                    ask9: 0,
-                    askorderid: 0,
-                    askorderid2: 0,
-                    askorderid3: 0,
-                    askorderid4: 0,
-                    askorderid5: 0,
-                    askordervolume: 0,
-                    askordervolume1number: 0,
-                    askordervolume2: 0,
-                    askordervolume3: 0,
-                    askordervolume4: 0,
-                    askordervolume5: 0,
-                    askordervolume6: 0,
-                    askordervolume7: 0,
-                    askordervolume8: 0,
-                    askordervolume9: 0,
-                    askqueueinfo: '',
-                    askvolume: 0,
-                    askvolume1number: 0,
-                    askvolume2: 0,
-                    askvolume3: 0,
-                    askvolume4: 0,
-                    askvolume5: 0,
-                    askvolume6: 0,
-                    askvolume7: 0,
-                    askvolume8: 0,
-                    askvolume9: 0,
-                    averageprice: 0,
-                    bid: 0,
-                    bid1number: 0,
-                    bid2: 0,
-                    bid3: 0,
-                    bid4: 0,
-                    bid5: 0,
-                    bid6: 0,
-                    bid7: 0,
-                    bid8: 0,
-                    bid9: 0,
-                    bidorderid: 0,
-                    bidorderid2: 0,
-                    bidorderid3: 0,
-                    bidorderid4: 0,
-                    bidorderid5: 0,
-                    bidordervolume: 0,
-                    bidordervolume1number: 0,
-                    bidordervolume2: 0,
-                    bidordervolume3: 0,
-                    bidordervolume4: 0,
-                    bidordervolume5: 0,
-                    bidordervolume6: 0,
-                    bidordervolume7: 0,
-                    bidordervolume8: 0,
-                    bidordervolume9: 0,
-                    bidqueueinfo: '',
-                    bidvolume: 0,
-                    bidvolume1number: 0,
-                    bidvolume2: 0,
-                    bidvolume3: 0,
-                    bidvolume4: 0,
-                    bidvolume5: 0,
-                    bidvolume6: 0,
-                    bidvolume7: 0,
-                    bidvolume8: 0,
-                    bidvolume9: 0,
-                    calloptionpremiums: 0,
-                    calloptionpremiums2: 0,
-                    calloptionpremiums3: 0,
-                    calloptionpremiums4: 0,
-                    calloptionpremiums5: 0,
-                    cleartime: 0,
-                    exchangecode: 0,
-                    exchangedate: 0,
-                    goodscode: '',
-                    refgoodscode: '',
-                    grepmarketprice: 0,
-                    highest: 0,
-                    holdincrement: 0,
-                    holdvolume: 0,
-                    iep: 0,
-                    iev: 0,
-                    inventory: 0,
-                    iscleared: 0,
-                    issettled: 0,
-                    last: 0,
-                    lastlot: 0,
-                    lasttime: '',
-                    lastturnover: 0,
-                    lastvolume: 0,
-                    limitdown: 0,
-                    limitup: 0,
-                    lowest: 0,
-                    nontotalholdervolume: 0,
-                    nontotallot: 0,
-                    nontotalturnover: 0,
-                    nontotalvolume: 0,
-                    opened: 0,
-                    opentime: '',
-                    orderid: 0,
-                    preclose: 0,
-                    preholdvolume: 0,
-                    presettle: 0,
-                    publictradetype: '',
-                    putoptionpremiums: 0,
-                    putoptionpremiums2: 0,
-                    putoptionpremiums3: 0,
-                    putoptionpremiums4: 0,
-                    putoptionpremiums5: 0,
-                    settle: 0,
-                    strikeprice: 0,
-                    totalaskvolume: 0,
-                    totalbidvolume: 0,
-                    totallot: 0,
-                    totalturnover: 0,
-                    totalvolume: 0,
-                    utclasttime: '',
-                })
-            }
-        })
-    }
-    function getExternalId(index: number) {
-        return externalexchangeList.value[index].autoid
-    }
-
-    return { index, loading, tabList, tableList, hanldeQuoteData }
-}

+ 279 - 0
src/views/market/futures/setup.tsx

@@ -0,0 +1,279 @@
+import { TabList } from '@/common/components/description/interface';
+import { initData } from '@/common/methods';
+import APP from '@/services';
+import { getQuoteDayInfoByCode } from '@/services/bus/goods';
+import { Ermcp3GoodsGroup, Goods } from '@/services/go/ermcp/goodsInfo/interface';
+import { QueryQuoteDayRsp } from '@/services/go/quote/interface';
+import { Externalexchange } from '@/services/go/useInfo/interface';
+import { ref, toRefs } from 'vue';
+import { quoteChange, quoteAmplitude } from '@/common/setup/table/tableQuote';
+import { TableQuote } from '@/common/setup/table/interface';
+
+/**
+ * 处理空数据
+ */
+function formatValue<Key extends keyof TableQuote>(value: TableQuote[Key]) {
+    return value > 0 ? value : '--';
+}
+
+/**
+ * 处理行情价格颜色
+ */
+function handleQuotePriceColor<T, Key extends keyof TableQuote>(text: T, value: TableQuote[Key], presettle: TableQuote['presettle']) {
+    let className = ''
+    if (presettle && value !== presettle) {
+        if (value > presettle) {
+            className = 'up-quote-color'
+        } else {
+            className = 'down-quote-color'
+        }
+    }
+    return <span class={className}>{text}</span>;
+}
+
+export function getColumnsList() {
+    const columns = [
+        {
+            title: '序号',
+            key: 'index',
+            width: 80
+        },
+        {
+            title: '代码',
+            key: 'goodscode',
+        },
+        {
+            title: '名称',
+            key: 'goodsname'
+        },
+        {
+            title: '最新价',
+            key: 'last',
+            customRender: ({ record }: { record: TableQuote }) => {
+                const text = formatValue(record.last);
+                return handleQuotePriceColor(text, record.last, record.presettle);
+            }
+        },
+        {
+            title: '涨跌幅%',
+            key: 'amplitude',
+            customRender: ({ record }: { record: TableQuote }) => {
+                const text = quoteAmplitude(record);
+                return handleQuotePriceColor(text, record.last, record.presettle);
+            }
+        },
+        {
+            title: '涨跌额',
+            key: 'change',
+            customRender: ({ record }: { record: TableQuote }) => {
+                const text = quoteChange(record, record.decimalplace);
+                return handleQuotePriceColor(text, record.last, record.presettle);
+            }
+        },
+        {
+            title: '买价',
+            key: 'bid',
+            customRender: ({ record }: { record: TableQuote }) => {
+                const text = formatValue(record.bid);
+                return handleQuotePriceColor(text, record.bid, record.presettle);
+            }
+        },
+        {
+            title: '卖价',
+            key: 'ask',
+            customRender: ({ record }: { record: TableQuote }) => {
+                const text = formatValue(record.ask);
+                return handleQuotePriceColor(text, record.ask, record.presettle);
+            }
+        },
+        {
+            title: '买量',
+            key: 'bidvolume',
+            customRender: ({ record }: { record: TableQuote }) => {
+                const text = formatValue(record.bidvolume);
+                return handleQuotePriceColor(text, record.bidvolume, record.presettle);
+            }
+        },
+        {
+            title: '卖量',
+            key: 'askvolume',
+            customRender: ({ record }: { record: TableQuote }) => {
+                const text = formatValue(record.askvolume);
+                return handleQuotePriceColor(text, record.askvolume, record.presettle);
+            }
+        },
+        {
+            title: '总量',
+            key: 'totalvolume',
+            customRender: ({ record }: { record: TableQuote }) => {
+                return formatValue(record.totalvolume);
+            }
+        },
+        {
+            title: '现量',
+            key: 'lastvolume',
+            customRender: ({ record }: { record: TableQuote }) => {
+                const text = formatValue(record.lastvolume);
+                return handleQuotePriceColor(text, record.lastvolume, record.presettle);
+            }
+        },
+        {
+            title: '持仓量',
+            key: 'holdvolume',
+            customRender: ({ record }: { record: TableQuote }) => {
+                return formatValue(record.holdvolume);
+            }
+        },
+        {
+            title: '日增',
+            key: 'holdincrement',
+            customRender: ({ record }: { record: TableQuote }) => {
+                const text = formatValue(record.holdincrement);
+                return handleQuotePriceColor(text, record.holdincrement, record.presettle);
+            }
+        },
+        {
+            title: '昨结价',
+            key: 'presettle',
+            customRender: ({ record }: { record: TableQuote }) => {
+                return formatValue(record.presettle);
+            }
+        },
+        {
+            title: '金额',
+            key: 'totalturnover',
+            customRender: ({ record }: { record: TableQuote }) => {
+                return formatValue(record.totalturnover);
+            }
+        },
+        {
+            title: '开盘',
+            key: 'opened',
+            customRender: ({ record }: { record: TableQuote }) => {
+                const text = formatValue(record.opened);
+                return handleQuotePriceColor(text, record.opened, record.presettle);
+            }
+        },
+        {
+            title: '最高',
+            key: 'highest',
+            customRender: ({ record }: { record: TableQuote }) => {
+                const text = formatValue(record.highest);
+                return handleQuotePriceColor(text, record.highest, record.presettle);
+            }
+        },
+        {
+            title: '最低',
+            key: 'lowest',
+            customRender: ({ record }: { record: TableQuote }) => {
+                const text = formatValue(record.lowest);
+                return handleQuotePriceColor(text, record.lowest, record.presettle);
+            }
+        },
+    ];
+
+    return columns.map(el => {
+        return {
+            dataIndex: el.key,
+            width: 100,
+            align: 'center',
+            slots: { customRender: el.key, },
+            ...el
+        }
+    })
+}
+
+// 外部交易所
+export const useExternalexchange = () => {
+    const loading = ref<boolean>(false)
+    const index = ref<string>('0');
+    // 盘面数据
+    const quoteList = ref<QueryQuoteDayRsp[]>([]);
+    // 表格数据
+    const tableList = ref<TableQuote[]>([]);
+    // 外部交易所 数据
+    const externalexchangeList = ref<Externalexchange[]>([])
+    const tabList = ref<TabList[]>([])
+
+    // 获取 商品数据
+    const useGoodsList = (exchareaid: number) => {
+        // 商品列表
+        const goodsList = APP.get('Goods') as Goods[];
+        const goodsGroups = APP.get('goodsgroups') as Ermcp3GoodsGroup[]
+        // 商品组
+        const selectedGoodsGroups = goodsGroups.filter(e => e.exexchangeid === exchareaid).map(el => el.goodsgroupid)
+        return goodsList.filter(e => {
+            return e.goodsstatus === 3 && selectedGoodsGroups.includes(e.goodsgroupid)
+        })
+    }
+
+    initData(() => {
+        externalexchangeList.value = APP.get('externalexchange')
+        const list = externalexchangeList.value.map((e: Externalexchange) => {
+            return { lable: e.exexchangename, code: e.exexchangecode };
+        }) as TabList[]
+
+        tabList.value = list
+        if (list.length) {
+            hanldeQuoteData(0)
+        }
+    })
+    function hanldeQuoteData(index: number) {
+        const id = getExternalId(index)
+        // 找到 交易所 下的商品列表
+        const goodsList = useGoodsList(id)
+
+        // 重置表格数据
+        tableList.value = goodsList.map((el) => {
+            return {
+                goodscode: el.goodscode,
+                goodsname: el.goodsname,
+                decimalplace: el.decimalplace,
+            }
+        })
+
+        // 找到 盘面数据
+        getQuoteData(goodsList)
+    }
+    function getQuoteData(goodsList: Goods[]) {
+        quoteList.value.length = 0
+        // 找到盘面数据
+        goodsList.forEach(el => {
+            const quote = getQuoteDayInfoByCode(el.goodscode);
+            if (quote) {
+                quoteList.value.push(quote)
+            }
+        })
+    }
+
+    // 处理表格行情数据
+    function hanldeTableData() {
+        quoteList.value.forEach((quote) => {
+            const refs = toRefs(quote);
+            const index = tableList.value.findIndex((e) => e.goodscode === quote.goodscode);
+            if (index > -1) {
+                const item = tableList.value[index];
+                item.last = refs.last; // 最新价
+                item.bid = refs.bid; // 买价
+                item.ask = refs.ask; // 卖价
+                item.bidvolume = refs.bidvolume; // 买量
+                item.askvolume = refs.askvolume; // 卖量
+                item.totalvolume = refs.totalvolume; // 总量
+                item.lastvolume = refs.lastvolume; // 现量
+                item.holdvolume = refs.holdvolume; // 持仓量
+                item.holdincrement = refs.holdincrement; // 日增
+                item.presettle = refs.presettle; // 昨结价
+                item.totalturnover = refs.totalturnover; // 金额
+                item.opened = refs.opened; // 开盘
+                item.highest = refs.highest; // 最高
+                item.lowest = refs.lowest; // 最低
+            }
+        });
+    }
+
+    function getExternalId(index: number) {
+        return externalexchangeList.value[index].autoid
+    }
+
+    return { index, loading, tabList, tableList, quoteList, hanldeQuoteData, hanldeTableData }
+}

+ 13 - 4
tsconfig.json

@@ -15,10 +15,19 @@
         "baseUrl": "./",
         "isolatedModules": true,
         "paths": {
-            "@/*": ["src/*"]
+            "@/*": [
+                "src/*"
+            ]
         },
         "strictPropertyInitialization": false
     },
-    "include": ["src/**/*.ts", "src/**/*.vue", "babel.config.js"],
-    "exclude": ["node_modules"]
-}
+    "include": [
+        "src/**/*.ts",
+        "src/**/*.tsx",
+        "src/**/*.vue",
+        "babel.config.js"
+    ],
+    "exclude": [
+        "node_modules"
+    ]
+}

+ 3 - 3
vue.config.js

@@ -64,7 +64,7 @@ module.exports = {
 								warnings: false,
 								drop_console: true, //console
 								drop_debugger: false,
-								pure_funcs: [ 'console.log' ] //移除console
+								pure_funcs: ['console.log'] //移除console
 							}
 						}
 					})
@@ -106,7 +106,7 @@ module.exports = {
 			//   'vuex': 'Vuex'
 			// } // 防止将某些 import 的包(package)打包到 bundle 中,而是在运行时(runtime)再去从外部获取这些扩展依赖(用于csdn引入)
 			resolve: {
-				extensions: [ '.js', '.vue', '.json', '.ts' ], //文件优先解析后缀名顺序
+				extensions: ['.js', '.vue', '.json', '.ts', '.tsx'], //文件优先解析后缀名顺序
 				alias: {
 					'@': path.resolve('./src')
 				}, // 别名配置
@@ -161,7 +161,7 @@ module.exports = {
 		port: 8888,
 		https: false,
 		hotOnly: false,
-		before: () => {}
+		before: () => { }
 	},
 	// 第三方插件配置
 	pluginOptions: {}