li.shaoyi 4 年 前
コミット
5abd922f5b

+ 62 - 1
src/assets/styles/mixin.less

@@ -938,7 +938,7 @@
             padding         : 0 8px;
             background-color: @m-grey21  !important;
             border          : 0;
-            color           : @m-white1;
+            color           : @m-white1  !important;
 
             .ant-select-selection-placeholder {
                 color: @m-grey10;
@@ -1851,6 +1851,67 @@
     background: @m-grey21;
 }
 
+// 提示框
+.mtp-modal-confirm {
+    top           : 50%;
+    width         : 300px !important;
+    padding-bottom: 0;
+    margin-top    : -100px;
+
+    .ant-modal-content {
+        background: @m-black27;
+        height    : auto;
+        .rounded-corners(10px);
+
+        .ant-modal-body {
+            color     : @m-blue0;
+            text-align: center;
+            font-size : 20px;
+        }
+
+        .ant-modal-footer {
+            border    : 0;
+            text-align: center;
+            padding   : 0 16px 24px 16px;
+
+            .ant-btn {
+                width        : 120px;
+                height       : 30px;
+                line-height  : 28px;
+                border-radius: 3px;
+                background   : linear-gradient(0deg, @m-grey12 0%, @m-grey13 100%);
+                font-size    : 16px;
+                color        : @m-white0;
+                margin-right : 20px;
+                border       : 0;
+
+                &:hover {
+                    background: linear-gradient(0deg, @m-grey12-hover 0%, @m-grey13-hover 100%);
+                    color     : @m-white0-hover;
+                }
+            }
+
+            .ant-btn-primary {
+                width        : 120px;
+                height       : 30px;
+                line-height  : 28px;
+                border       : 0;
+                background   : linear-gradient(0deg, @m-blue2 0%, @m-blue0 100%);
+                border-radius: 3px;
+                font-size    : 16px;
+                color        : @m-white0;
+                margin-right : 0;
+                margin-left  : 0;
+
+                &:hover {
+                    background: linear-gradient(0deg, @m-blue2-hover 0%, @m-blue0-hover 100%);
+                    color     : @m-white0-hover;
+                }
+            }
+        }
+    }
+}
+
 .ant-modal-confirm-confirm {
     top           : 50%;
     padding-bottom: 0;

+ 5 - 9
src/common/components/capitalInfo/index.vue

@@ -1,21 +1,15 @@
 <template>
   <div class="capital-info">
     <!-- 资金信息 -->
-    <a-select class="capitalSelect"
-              style="width: 180px"
-              @change="accountChange"
-              v-model:value="selectedAccountId">
-      <a-select-option v-for="item in getAllTaAccount()"
-                       :value="item.accountid"
-                       :key="item.accountid">{{item.accountid}}</a-select-option>
+    <a-select class="capitalSelect" style="width: 180px" @change="accountChange" v-model:value="selectedAccountId">
+      <a-select-option v-for="item in getAllTaAccount()" :value="item.accountid" :key="item.accountid">{{item.accountid}}</a-select-option>
     </a-select>
     <div class="numBlocks">
       <div class="capitalItem">
         <div class="firstLine">
           <div>余额</div>
           <div>
-            <i class="iconfont icon-zhengyan"
-               @click="showAction"></i>
+            <i class="iconfont icon-zhengyan" @click="showAction"></i>
           </div>
         </div>
         <div class="numBar">{{showValue(data.currentbalance)}}</div>
@@ -70,6 +64,8 @@ export default defineComponent({
             const item = getAllTaAccount().find((e) => e.accountid === id) as AccountListItem;
             Object.assign(data, getMoney(item));
             setSelectedAccount(item);
+            // 通知资金账户变化
+            Bus.$emit('taAccountChangedNtf');
         }
         // 资金变化,重新加载数据
         Bus.$on('moneyChangedNtf_UI', () => {

+ 1 - 1
src/common/components/echart/echart-kline/index.vue

@@ -322,7 +322,7 @@ export default defineComponent({
             loading.value = true;
             const params: QueryHistoryDatas = {
                 cycleType: props.cycleType,
-                goodsCode: props.quoteData.goodscode,
+                goodsCode: props.quoteData.goodscode.toUpperCase(),
                 count: 1440,
             };
             // 查询K线数据

+ 1 - 0
src/services/go/ermcp/purchase/interface.ts

@@ -78,4 +78,5 @@ export interface Ermcp3SellBuyContract {
     wrstandardcode: string;//品类代码
     wrstandardid: number;//品类ID
     wrstandardname: string;//品类名称
+    bizsubjectid: number; //归属业务部门ID
 }

+ 1 - 1
src/utils/eventBus/index.ts

@@ -20,7 +20,7 @@ interface EnentNamesOnlyOneValue {
     userLogout: string; //接收到用户登出应答
     posChangedNtf: string; //接收到头寸变化通知
     moneyChangedNtf: string; //接收到资金变化通知
-
+    taAccountChangedNtf: string; //接收到资金账户通知
     bargain: string; // 议价单
 
     orderCanceledNtf: string; //接收到委托单撤单通知

+ 1 - 0
src/views/business/purchase/list/all/index.vue

@@ -59,6 +59,7 @@ export default defineComponent({
         filterCustomTable,
         MtpTableButton,
         detail: defineAsyncComponent(() => import('../../components/detail/index.vue')), // 详情
+        purchase_pending_trade: defineAsyncComponent(() => import('@/views/market/futures/compoments/futures-trade/index.vue')), // 套保交易
         purchase_pending_someprice: defineAsyncComponent(() => import('../../components/someprice/index.vue')), //点价登记
         purchase_performance_settlement: defineAsyncComponent(() => import('../../components/settlement/index.vue')), //交收登记
         purchase_performance_funds: defineAsyncComponent(() => import('../../components/funds/index.vue')), // 款项登记

+ 5 - 0
src/views/market/futures/compoments/futures-trade/index.less

@@ -22,6 +22,11 @@
             &-input-content {
                 display    : flex;
                 align-items: center;
+
+                .ant-input[disabled] {
+                    color           : #fff;
+                    background-color: transparent;
+                }
             }
         }
 

+ 33 - 20
src/views/market/futures/compoments/futures-trade/index.vue

@@ -6,15 +6,18 @@
         <div class="futures_trade__form">
           <a-form class="inlineForm" ref="formRef" :model="formData" :rules="rules">
             <a-form-item label="账号">
-              <a-select class="inlineFormSelect" placeholder="请选择" v-model:value="formData.AccountID">
+              <a-select class="inlineFormSelect" placeholder="请选择" v-model:value="formData.AccountID" @change="getPositionList">
                 <a-select-option v-for="item in accountList" :value="item.accountid" :key="item.accountid">{{ item.accountname }} - {{item.accountid}}</a-select-option>
               </a-select>
             </a-form-item>
             <a-form-item label="合约">
-              <a-select class="inlineFormSelect" placeholder="请选择" :filterOption="filterOption" show-search v-model:value="formData.GoodsID" @change="goodsChange">
+              <a-select class="inlineFormSelect" placeholder="请选择" :disabled="isHedging" :filterOption="filterOption" v-model:value="formData.GoodsID" @change="goodsChange" show-search>
                 <a-select-option v-for="item in goodsList" :value="item.goodsid" :key="item.goodsid">{{ item.goodsname }}</a-select-option>
               </a-select>
             </a-form-item>
+            <a-form-item label="现货合同" v-if="isHedging">
+              <span class="white">{{ selectedRow.spotcontractid }}</span>
+            </a-form-item>
             <a-form-item label="价格类型">
               <a-select class="inlineFormSelect" placeholder="请选择" v-model:value="selectedPriceType" @change="priceTypeChange">
                 <a-select-option v-for="item in priceTypeList" :value="item.priceType" :key="item.priceType">{{ item.priceName }}</a-select-option>
@@ -32,7 +35,7 @@
               </template>
             </a-form-item>
             <a-form-item class="inputIconBox" label="交易数量" name="OrderQty">
-              <a-input-number class="commonInput" :min="1" v-model:value="formData.OrderQty" style="width:100%" />
+              <a-input-number class="commonInput" decimalSeparator="0" :min="1" v-model:value="formData.OrderQty" style="width:100%" />
               <MinusOutlined @click="minusQty" />
               <PlusOutlined @click="plusQty" />
             </a-form-item>
@@ -48,11 +51,11 @@
             <span>卖出</span>
           </a-button>
           <!--如果有持仓则显示按钮-->
-          <a-button :loading="loading" @click="submit('close')" v-show="positionList.length">
+          <a-button :loading="loading" @click="submit('close')" v-show="positionList.length && !isHedging">
             <span>平仓</span>
           </a-button>
         </div>
-        <div class="futures_trade__table tableDatas" v-show="positionList.length">
+        <div class="futures_trade__table tableDatas" v-show="positionList.length && !isHedging">
           <a-table class="dialogTable" :columns="getColumns()" :data-source="positionList" :rowKey="(record,index)=>index" :pagination="false" :row-selection="{ selectedRowKeys: selectedRowKeys, onChange: onSelectChange, type:'radio' }"></a-table>
         </div>
       </div>
@@ -68,13 +71,15 @@ import { Des } from '@/common/components/commonDes';
 import Drawer from '@/common/components/drawer/index.vue';
 import { _closeModal } from '@/common/setup/modal/modal';
 import { MinusOutlined, PlusOutlined } from '@ant-design/icons-vue';
-import { defineComponent, ref, computed } from 'vue';
+import { defineComponent, ref, computed, PropType } from 'vue';
 import { handleForm, getColumns } from './setup';
 import { channelOrderReq } from '@/services/proto/futures';
 import { requestResultLoadingAndInfo } from '@/common/methods/request/resultInfo';
 import { BuyOrSell, BuildType, PriceType } from '@/common/constants/enumCommon';
 import { validateAction } from '@/common/setup/form';
 import { GoodsQuote } from '@/services/go/ermcp/goodsInfo/interface';
+import { QueryErmcpTradePositionRsp } from '@/services/go/ermcp/futures/interface';
+import { Ermcp3SellBuyContract } from '@/services/go/ermcp/purchase/interface';
 import { getGoodsQuoteList } from '@/services/bus/goods';
 import { message } from 'ant-design-vue';
 
@@ -83,25 +88,22 @@ export default defineComponent({
     name: 'trader',
     components: { Des, Drawer, PlusOutlined, MinusOutlined },
     props: {
-        // 商品ID
-        goodsId: {
-            type: Number,
-            default: 0,
-        },
-        // 交易所ID
-        exchangeId: {
-            type: Number,
-            default: 0,
+        selectedRow: {
+            type: Object as PropType<GoodsQuote & QueryErmcpTradePositionRsp & Ermcp3SellBuyContract>,
+            default: () => {},
         },
     },
     setup(props, context) {
+        // 是否套保交易 (根据参数 spotcontractid 来判断)
+        const isHedging = Boolean(props.selectedRow.spotcontractid);
+
         const goodsList = getGoodsQuoteList();
         const getGoods = (id: number) => goodsList.find((item) => item.goodsid === id)!;
         // 当前选中的商品合约
-        const selectedGoods = ref<GoodsQuote>(getGoods(props.goodsId));
+        const selectedGoods = ref<GoodsQuote>(getGoods(props.selectedRow.goodsid));
 
         const { visible, cancel } = _closeModal(context);
-        const { rules, formData, accountList, allPositionList } = handleForm(selectedGoods.value);
+        const { rules, formData, accountList, allPositionList, getPositionList } = handleForm(selectedGoods.value);
         const formRef = ref();
         const loading = ref<boolean>(false);
 
@@ -111,10 +113,10 @@ export default defineComponent({
             selectedRowKeys.value = keys;
             // 选中的单据数据
             const { enableqty, positionaverageprice } = positionList.value[keys[0]];
+            // 更新价格和数量
             formData.OrderPrice = positionaverageprice;
             formData.OrderQty = enableqty;
-
-            // 限价
+            // 指定价格类型显示为限价
             selectedPriceType.value = 3;
         };
 
@@ -224,6 +226,15 @@ export default defineComponent({
             let successMsg = '成功';
             let failMsg = '失败';
 
+            const { saleuserid, spotcontractid, bizsubjectid } = props.selectedRow;
+            // 判断是否套保交易
+            if (isHedging) {
+                formData.HedgeFlag = 4;
+                formData.SaleUserID = saleuserid;
+                formData.SpotContractID = Number(spotcontractid);
+                formData.BizSubjectID = bizsubjectid;
+            }
+
             // 按钮提交类型
             switch (submitType) {
                 case 'buy': {
@@ -257,7 +268,7 @@ export default defineComponent({
 
                     // 判断平仓数量
                     if (formData.OrderQty > curpositionqty) {
-                        message.error('交易数量不能大于可用持仓数量');
+                        message.error('交易数量不能大于持仓可用数量');
                         return;
                     }
 
@@ -291,10 +302,12 @@ export default defineComponent({
             rules,
             formRef,
             formData,
+            isHedging,
             goodsList,
             buyPrice,
             sellPrice,
             selectedGoods,
+            getPositionList,
             goodsChange,
             selectedRowKeys,
             priceTypeList,

+ 9 - 7
src/views/market/futures/compoments/futures-trade/setup.ts

@@ -11,6 +11,7 @@ import { RuleObject } from 'ant-design-vue/es/form/interface';
 import { getAccountTypeList } from '@/services/bus/account';
 import { queryErmcpTradePosition } from '@/services/go/ermcp/futures';
 import { QueryErmcpTradePositionRsp } from '@/services/go/ermcp/futures/interface';
+import { getSelectedAccountId } from '@/services/bus/account';
 
 export function getColumns() {
     const columns = [
@@ -65,7 +66,7 @@ export function handleForm(selectedRow: GoodsQuote) {
         ClientOrderTime: moment(new Date()).format('YYYY-MM-DD HH:mm:ss'), // string 客户端委托时间
         ClientType: 4, // uint32 终端类型
         LoginID: geLoginID_number()!, // uint64 登陆账号
-        AccountID: 0, // uint64 交易账号
+        AccountID: getSelectedAccountId(), // uint64 交易账号
         GoodsID: selectedRow.goodsid, // uint32 商品ID
         MarketID: selectedRow.marketid, // uint32 市场ID
         ValidType: 1, // int32 有效类型 - 1当日有效
@@ -84,15 +85,15 @@ export function handleForm(selectedRow: GoodsQuote) {
 
     // 账号列表
     const accountList = getAccountTypeList([1]);
-    if (accountList.length) {
-        formData.AccountID = accountList[0].accountid;
-    }
 
     // 所有持仓列表
     const allPositionList = ref<QueryErmcpTradePositionRsp[]>([]);
-    queryErmcpTradePosition().then((res) => {
-        allPositionList.value = res;
-    })
+    const getPositionList = (id: number) => {
+        queryErmcpTradePosition({ accountID: id }).then((res) => {
+            allPositionList.value = res;
+        })
+    }
+    getPositionList(formData.AccountID)
 
     // 验证交易价格
     const verifyOrderPrice = async (rule: RuleObject, value: number) => {
@@ -113,6 +114,7 @@ export function handleForm(selectedRow: GoodsQuote) {
         accountList,
         allPositionList,
         formData,
+        getPositionList,
     }
 }
 

+ 1 - 1
src/views/market/futures/index.vue

@@ -9,7 +9,7 @@
     <ThridMenu :list="tabList" @selectMenu="changeTab" />
     <!-- 右键 -->
     <contextMenu :contextMenu="contextMenu" @cancel="closeContext" :list="buttons"></contextMenu>
-    <component :is="componentId" v-if="componentId" :exchangeId="exchangeId" :selectedRow="selectedRow" :goodsId="selectedRow.goodsid" @cancel="closeComponent"></component>
+    <component :is="componentId" v-if="componentId" :selectedRow="selectedRow" @cancel="closeComponent"></component>
   </div>
 </template>
 

+ 2 - 2
src/views/order/commodity_contract/components/commodity_contract_commission/components/cancel/index.vue

@@ -1,6 +1,6 @@
 <template>
-    <!-- 现货仓单 现货明细 撤单 -->
-    <div></div>
+  <!-- 现货仓单 现货明细 撤单 -->
+  <div></div>
 </template>
 
 <script lang="ts">

+ 1 - 1
src/views/order/futures_information/components/futures_information_entrust/columns.tsx

@@ -64,7 +64,7 @@ export function getColumns() {
             key: 'orderlogincode'
         },
         {
-            title: '扯淡人',
+            title: '撤单人',
             key: 'cancellogincode'
         },
     ];

+ 15 - 1
src/views/order/futures_information/components/futures_information_entrust/index.vue

@@ -4,7 +4,7 @@
     <a-table :columns="getColumns()" class="srcollYTable expandLeftTable" :scroll="{ x: '100%', y: '190px' }" :pagination="false" :loading="loading" :expandedRowKeys="expandedRowKeys" :customRow="Rowclick" :expandIcon="expandIcon" :expandIconAsCell="false" rowKey="key" :data-source="tableList">
       <!-- 额外的展开行 -->
       <template v-if="btnList.length" #expandedRowRender="{ record }">
-        <BtnList :btnList="btnList" :record="record" class="btn-list-sticky" @click="openComponent" />
+        <BtnList :btnList="handleBtnList(btnList,record)" :record="record" class="btn-list-sticky" @click="openComponent" />
       </template>
     </a-table>
     <component :is="componentId" v-if="componentId" :selectedRow="selectedRow" @cancel="closeComponent"></component>
@@ -16,20 +16,33 @@ import { defineComponent } from 'vue';
 import { queryTableList, BtnList } from '@/common/export/commonTable';
 import { handleComposeOrderTable } from '@/common/setup/table/compose';
 import { ComposeOrderTableParam } from '@/common/setup/table/interface';
+import { BtnListType } from '@/common/components/btnList/interface';
 import { expandIcon } from '@/common/setup/table/clolumn';
 import { getRecordItemTab } from '@/common/setup/order/orderData';
 import { queryErmcpOrderDetails } from '@/services/go/ermcp/futures';
 import { QueryErmcpOrderDetailsRsp } from '@/services/go/ermcp/futures/interface';
 import { getColumns } from './columns';
+import { cancel } from './setup';
 
 export default defineComponent({
     components: {
         BtnList,
+        cancel,
     },
     setup() {
         // 表格列表数据
         const { loading, tableList, queryTable } = queryTableList<QueryErmcpOrderDetailsRsp>();
 
+        // 处理根据状态显示对应按钮
+        const handleBtnList = (btnList: BtnListType[], item: QueryErmcpOrderDetailsRsp) => {
+            switch (item.channelinnerorderstatus) {
+                case 9: // 全部成交
+                    return btnList.filter((e) => e.code !== 'cancel');
+                default:
+                    return btnList;
+            }
+        };
+
         // 表格通用逻辑
         const param: ComposeOrderTableParam = {
             queryFn: () => queryTable(queryErmcpOrderDetails),
@@ -38,6 +51,7 @@ export default defineComponent({
 
         return {
             ...handleComposeOrderTable(param),
+            handleBtnList,
             getColumns,
             loading,
             expandIcon,

+ 68 - 0
src/views/order/futures_information/components/futures_information_entrust/setup.tsx

@@ -0,0 +1,68 @@
+import { defineComponent, PropType, ref } from 'vue';
+import { QueryErmcpOrderDetailsRsp } from '@/services/go/ermcp/futures/interface';
+import { cancelOrderReq } from '@/services/socket/order';
+import { message } from 'ant-design-vue';
+import { geLoginID_number } from '@/services/bus/login';
+import { CancelOrderReq } from '@/services/socket/order/interface/index';
+import { getSelectedAccountId } from '@/services/bus/account';
+
+// 期货订单-委托撤单
+export const cancel = defineComponent({
+    emits: ['cancel'],
+    props: {
+        selectedRow: {
+            type: Object as PropType<QueryErmcpOrderDetailsRsp>,
+            default: {},
+        },
+    },
+    setup(props, { emit }) {
+        const loading = ref(false);
+        const show = ref(true);
+
+        // 取消
+        const cancel = () => {
+            emit('cancel');
+        }
+
+        // 提交
+        const submit = () => {
+            loading.value = true;
+            const { orderid, marketid, goodsid } = props.selectedRow;
+            const param: CancelOrderReq = {
+                OldOrderId: Number(orderid),
+                AccountID: getSelectedAccountId(), // uint64 资金账号
+                OperatorID: geLoginID_number() ?? 0, // uint64 操作员账号ID
+                MarketID: marketid,
+                GoodsID: goodsid,
+            };
+            return cancelOrderReq(param).then(() => {
+                message.error('撤单成功');
+            }).catch(() => {
+                message.error('撤单失败');
+            }).finally(() => {
+                loading.value = false;
+                emit('cancel', true);
+            })
+        }
+
+        return {
+            loading,
+            show,
+            submit,
+            cancel,
+        }
+    },
+    render() {
+        const slots = {
+            footer: () => {
+                return <>
+                    <a-button class='cancelBtn' loading={this.loading} onClick={this.cancel}>取消</a-button>
+                    <a-button type='primary' loading={this.loading} onClick={this.submit}>确认撤单</a-button>
+                </>
+            }
+        }
+        return <a-modal class='mtp-modal-confirm' v-model={[this.show, 'visible']} maskClosable={false} closable={false} v-slots={slots}>
+            <span>是否撤单操作?</span>
+        </a-modal>
+    }
+});

+ 3 - 3
src/views/order/futures_information/components/futures_information_position/index.vue

@@ -7,7 +7,7 @@
         <BtnList :btnList="btnList" :record="record" class="btn-list-sticky" @click="openComponent" />
       </template>
     </a-table>
-    <component :is="componentId" v-if="componentId" :goodsId="selectedRow.goodsid" @cancel="closeComponent"></component>
+    <component :is="componentId" v-if="componentId" :selectedRow="selectedRow" @cancel="closeComponent"></component>
   </section>
 </template>
 
@@ -41,8 +41,8 @@ export default defineComponent({
             recordList: getRecordItemTab(),
         };
 
-        // 注册头寸变化事件,待通知调用
-        Bus.$on('posChangedNtf_UI', () => {
+        // 注册资金变化事件,待通知调用
+        Bus.$on('moneyChangedNtf_UI', () => {
             // 重新加载数据
             queryTableAction();
         });

+ 25 - 2
src/views/order/futures_information/index.vue

@@ -8,9 +8,11 @@
 </template>
 
 <script lang="ts">
-import { defineAsyncComponent, defineComponent } from 'vue';
+import { defineAsyncComponent, defineComponent, nextTick } from 'vue';
 import thirdMenu from '@/common/components/thirdMenu/index.vue';
 import { handleOrderDetailList } from '@/common/setup/order/orderData';
+import Bus from '@/utils/eventBus/index';
+
 export default defineComponent({
     components: {
         thirdMenu,
@@ -19,7 +21,28 @@ export default defineComponent({
         futures_information_success: defineAsyncComponent(() => import('./components/futures_information_success/index.vue')), // 成交
     },
     setup() {
-        return { ...handleOrderDetailList('futures_information') };
+        const { componentId, tabList, changeTab } = handleOrderDetailList('futures_information');
+
+        // 组件重新加载
+        function componentReload() {
+            const code = componentId.value;
+            componentId.value = '';
+            nextTick(() => {
+                componentId.value = code;
+            });
+        }
+
+        // 注册账户变化事件,待通知调用
+        Bus.$onOnly('taAccountChangedNtf', () => {
+            // 重新加载组件
+            componentReload();
+        });
+
+        return {
+            componentId,
+            tabList,
+            changeTab,
+        };
     },
 });
 </script>