ソースを参照

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

zhou.xiaoning 4 年 前
コミット
1c803581c4
28 ファイル変更2874 行追加7 行削除
  1. 2 0
      src/common/constants/enumOrderComponents.ts
  2. 7 7
      src/layout/components/bottom.vue
  3. 61 0
      src/views/order/swap_the_order/components/swap_commodity_contract_bargain/components/commodity_contract_bargain_cancel_order/index.vue
  4. 95 0
      src/views/order/swap_the_order/components/swap_commodity_contract_bargain/components/commodity_contract_bargain_refuse_order/index.vue
  5. 4 0
      src/views/order/swap_the_order/components/swap_commodity_contract_bargain/components/commodity_contract_bargain_refuse_order/interface.ts
  6. 15 0
      src/views/order/swap_the_order/components/swap_commodity_contract_bargain/components/commodity_contract_bargain_refuse_order/setup.ts
  7. 62 0
      src/views/order/swap_the_order/components/swap_commodity_contract_bargain/components/commodity_contract_bargain_submit_order/index.vue
  8. 141 0
      src/views/order/swap_the_order/components/swap_commodity_contract_bargain/index.vue
  9. 10 0
      src/views/order/swap_the_order/components/swap_commodity_contract_bargain/setup.ts
  10. 74 0
      src/views/order/swap_the_order/components/swap_commodity_contract_commission/components/cancel/index.vue
  11. 105 0
      src/views/order/swap_the_order/components/swap_commodity_contract_commission/index.vue
  12. 108 0
      src/views/order/swap_the_order/components/swap_commodity_contract_make_deal/index.vue
  13. 402 0
      src/views/order/swap_the_order/components/swap_commodity_contract_summary/components/commodity_contract_summary_deal_closed/index.vue
  14. 10 0
      src/views/order/swap_the_order/components/swap_commodity_contract_summary/components/commodity_contract_summary_deal_closed/interface.ts
  15. 35 0
      src/views/order/swap_the_order/components/swap_commodity_contract_summary/components/commodity_contract_summary_deal_closed/setup.ts
  16. 415 0
      src/views/order/swap_the_order/components/swap_commodity_contract_summary/components/commodity_contract_summary_order_closed/index.vue
  17. 10 0
      src/views/order/swap_the_order/components/swap_commodity_contract_summary/components/commodity_contract_summary_order_closed/interface.ts
  18. 32 0
      src/views/order/swap_the_order/components/swap_commodity_contract_summary/components/commodity_contract_summary_order_closed/setup.ts
  19. 428 0
      src/views/order/swap_the_order/components/swap_commodity_contract_summary/components/commodity_contract_summary_settlement/index.vue
  20. 11 0
      src/views/order/swap_the_order/components/swap_commodity_contract_summary/components/commodity_contract_summary_settlement/interface.ts
  21. 209 0
      src/views/order/swap_the_order/components/swap_commodity_contract_summary/components/commodity_contract_summary_settlement/setup.ts
  22. 200 0
      src/views/order/swap_the_order/components/swap_commodity_contract_summary/components/commodity_contract_summary_transfer/index.vue
  23. 5 0
      src/views/order/swap_the_order/components/swap_commodity_contract_summary/components/commodity_contract_summary_transfer/interface.ts
  24. 26 0
      src/views/order/swap_the_order/components/swap_commodity_contract_summary/components/commodity_contract_summary_transfer/setup.ts
  25. 31 0
      src/views/order/swap_the_order/components/swap_commodity_contract_summary/components/setup.ts
  26. 168 0
      src/views/order/swap_the_order/components/swap_commodity_contract_summary/index.vue
  27. 146 0
      src/views/order/swap_the_order/components/swap_commodity_contract_summary/setup.ts
  28. 62 0
      src/views/order/swap_the_order/index.vue

+ 2 - 0
src/common/constants/enumOrderComponents.ts

@@ -8,6 +8,8 @@ export enum enumOrderComponents {
 
 	commodity_contract = 'commodity_contract', // 商品合约
 
+	swap_the_order = 'swap_the_order', // 掉期订单
+
 	financing_manager = 'financing_manager', // 融资管理
 
 	performance_information = 'performance_information', // 履约信息

+ 7 - 7
src/layout/components/bottom.vue

@@ -51,12 +51,13 @@ export default defineComponent({
         firstMenu,
         quoteTable,
         thirdMenu,
-        [enumOrderComponents.spot_warrant]: defineAsyncComponent(() => import('@/views/order/spot_warran/index.vue')),
-        [enumOrderComponents.funding_information]: defineAsyncComponent(() => import('@/views/order/funding_information/index.vue')),
-        [enumOrderComponents.performance_information]: defineAsyncComponent(() => import('@/views/order/performance_information/index.vue')),
-        [enumOrderComponents.pre_sale_warehouse_receipt]: defineAsyncComponent(() => import('@/views/order/pre_sale_warehouse_receipt/index.vue')),
-        [enumOrderComponents.financing_manager]: defineAsyncComponent(() => import('@/views/order/financing_manager/index.vue')),
-        [enumOrderComponents.commodity_contract]: defineAsyncComponent(() => import('@/views/order/commodity_contract/index.vue')),
+        [enumOrderComponents.spot_warrant]: defineAsyncComponent(() => import('@/views/order/spot_warran/index.vue')), // 现货仓单
+        [enumOrderComponents.funding_information]: defineAsyncComponent(() => import('@/views/order/funding_information/index.vue')), // 资金信息
+        [enumOrderComponents.performance_information]: defineAsyncComponent(() => import('@/views/order/performance_information/index.vue')), // 履约信息
+        [enumOrderComponents.pre_sale_warehouse_receipt]: defineAsyncComponent(() => import('@/views/order/pre_sale_warehouse_receipt/index.vue')), // 预售仓单
+        [enumOrderComponents.financing_manager]: defineAsyncComponent(() => import('@/views/order/financing_manager/index.vue')), // 融资管理
+        [enumOrderComponents.commodity_contract]: defineAsyncComponent(() => import('@/views/order/commodity_contract/index.vue')), // 商品合约
+        [enumOrderComponents.swap_the_order]: defineAsyncComponent(() => import('@/views/order/swap_the_order/index.vue')), // 掉期订单
     },
     setup() {
         const { orderList, componentId } = handleOrderData();
@@ -121,7 +122,6 @@ export default defineComponent({
     height: 40px;
 }
 
-
 .layout-bottom {
     display: flex;
     width: 100%;

+ 61 - 0
src/views/order/swap_the_order/components/swap_commodity_contract_bargain/components/commodity_contract_bargain_cancel_order/index.vue

@@ -0,0 +1,61 @@
+<template>
+  <!-- 商品合约 议价单 撤单 -->
+  <div></div>
+</template>
+
+<script lang="ts">
+import Drawer from '@/common/components/drawer/index.vue';
+import { requestResultLoadingAndInfo } from '@/common/methods/request/resultInfo';
+import { _closeModal } from '@/common/setup/modal/modal';
+import { geLoginID_number } from '@/services/bus/login';
+import { QueryTjmdTransferApplyRsp } from '@/services/go/Tjmd/interface';
+import { tradeHoldTransferApplyAuditReq } from '@/services/proto/warehousetrade';
+import { TradeHoldTransferApplyAuditReqType } from '@/services/proto/warehousetrade/interface';
+import { Modal } from 'ant-design-vue';
+import { defineComponent, PropType, ref } from 'vue';
+
+export default defineComponent({
+    name: 'commodity_contract_bargain_cancel_order',
+    components: { Drawer },
+    emits: ['cancel', 'update'],
+    props: {
+        selectedRow: {
+            type: Object as PropType<QueryTjmdTransferApplyRsp>,
+            default: {},
+        },
+    },
+    setup(props, context) {
+        const { visible, cancel } = _closeModal(context);
+        const loading = ref<boolean>(false);
+
+        function submit() {
+            const param: TradeHoldTransferApplyAuditReqType = {
+                ApplyID: props.selectedRow.applyid,
+                ApplyStatus: 1, // 1:撤销2:拒绝3:通过
+                AuditSrc: 2,
+                AuditorID: geLoginID_number()!.toString(),
+                AuditRemark: '',
+            };
+            requestResultLoadingAndInfo(tradeHoldTransferApplyAuditReq, param, loading, ['撤单成功', '撤单失败:']).then(() => {
+                // Bus.$emit('spotTrade', true);
+                cancel(true);
+            });
+        }
+
+        Modal.confirm({
+            title: '撤单',
+            content: '是否确认撤单!',
+            onOk: submit,
+            onCancel: cancel,
+        });
+
+        return {
+            visible,
+            cancel,
+        };
+    },
+});
+</script>
+
+<style lang="less" scoped>
+</style>;

+ 95 - 0
src/views/order/swap_the_order/components/swap_commodity_contract_bargain/components/commodity_contract_bargain_refuse_order/index.vue

@@ -0,0 +1,95 @@
+<template>
+  <!-- 商品合约 议价单 撤单 -->
+  <a-modal class="commonModal reasonModal"
+           title="原因"
+           v-model:visible="visible"
+           centered
+           @click="cancel"
+           :maskClosable="false">
+    <template #footer>
+      <a-button key="submit"
+                @click="cancel"
+                class="cancelBtn">取消</a-button>
+      <a-button key="submit"
+                type="primary"
+                @click="submit">提交</a-button>
+    </template>
+    <a-form class="inlineForm"
+            ref="formRef"
+            :model="formState"
+            :rules="rules">
+      <a-row :gutter="24">
+        <a-col :span="24">
+          <a-form-item label="原因"
+                       class="relative"
+                       name="AuditRemark">
+            <a-textarea class="dialogInput"
+                        style="width: 100%"
+                        placeholder="请输入原因"
+                        v-model:value="formState.AuditRemark"
+                        readonly
+                        :autosize="{ minRows: 8, maxRows: 24 }" />
+          </a-form-item>
+        </a-col>
+      </a-row>
+    </a-form>
+  </a-modal>
+</template>
+
+<script lang="ts">
+import Drawer from '@/common/components/drawer/index.vue';
+import { requestResultLoadingAndInfo } from '@/common/methods/request/resultInfo';
+import { validateAction } from '@/common/setup/form/validateAction';
+import { _closeModal } from '@/common/setup/modal/modal';
+import { geLoginID_number } from '@/services/bus/login';
+import { QueryTjmdTransferApplyRsp } from '@/services/go/Tjmd/interface';
+import { tradeHoldTransferApplyAuditReq } from '@/services/proto/warehousetrade';
+import { TradeHoldTransferApplyAuditReqType } from '@/services/proto/warehousetrade/interface';
+import { defineComponent, PropType, ref } from 'vue';
+import { FormState } from './interface';
+import { handleForm } from './setup';
+
+export default defineComponent({
+    name: 'commodity_contract_bargain_refuse_order',
+    components: { Drawer },
+    emits: ['cancel', 'update'],
+    props: {
+        selectedRow: {
+            type: Object as PropType<QueryTjmdTransferApplyRsp>,
+            default: {},
+        },
+    },
+    setup(props, context) {
+        const { visible, cancel } = _closeModal(context);
+        const loading = ref<boolean>(false);
+        const { rules, formState, formRef } = handleForm();
+        function submit() {
+            validateAction<FormState>(formRef, formState).then((res) => {
+                const param: TradeHoldTransferApplyAuditReqType = {
+                    ApplyID: props.selectedRow.applyid,
+                    ApplyStatus: 2, // 1:撤销2:拒绝3:通过
+                    AuditSrc: 2,
+                    AuditorID: geLoginID_number()!.toString(),
+                    AuditRemark: res.AuditRemark,
+                };
+                requestResultLoadingAndInfo(tradeHoldTransferApplyAuditReq, param, loading, ['撤单成功', '撤单失败:']).then(() => {
+                    // Bus.$emit('spotTrade', true);
+                    cancel(true);
+                });
+            });
+        }
+
+        return {
+            visible,
+            cancel,
+            submit,
+            rules,
+            formState,
+            formRef,
+        };
+    },
+});
+</script>
+
+<style lang="less" scoped>
+</style>;

+ 4 - 0
src/views/order/swap_the_order/components/swap_commodity_contract_bargain/components/commodity_contract_bargain_refuse_order/interface.ts

@@ -0,0 +1,4 @@
+
+export interface FormState {
+    AuditRemark: string,
+}

+ 15 - 0
src/views/order/swap_the_order/components/swap_commodity_contract_bargain/components/commodity_contract_bargain_refuse_order/setup.ts

@@ -0,0 +1,15 @@
+import { reactive, ref, UnwrapRef } from "vue";
+import { FormState } from "./interface";
+
+export function handleForm() {
+    const formRef = ref();
+    const formState: UnwrapRef<FormState> = reactive({
+        AuditRemark: '',
+    })
+    const rules = {
+        AuditRemark: [
+            { require, message: '请输入拒绝原因', trigger: 'blur', },
+        ],
+    }
+    return { rules, formState, formRef }
+}

+ 62 - 0
src/views/order/swap_the_order/components/swap_commodity_contract_bargain/components/commodity_contract_bargain_submit_order/index.vue

@@ -0,0 +1,62 @@
+<template>
+  <!-- 商品合约 议价单 撤单 -->
+  <div></div>
+</template>
+
+<script lang="ts">
+import Drawer from '@/common/components/drawer/index.vue';
+import { requestResultLoadingAndInfo } from '@/common/methods/request/resultInfo';
+import { _closeModal } from '@/common/setup/modal/modal';
+import { geLoginID_number } from '@/services/bus/login';
+import { QueryTjmdTransferApplyRsp } from '@/services/go/Tjmd/interface';
+import { tradeHoldTransferApplyAuditReq } from '@/services/proto/warehousetrade';
+import { TradeHoldTransferApplyAuditReqType } from '@/services/proto/warehousetrade/interface';
+import { Modal } from 'ant-design-vue';
+import { defineComponent, PropType, ref } from 'vue';
+
+export default defineComponent({
+    name: 'commodity_contract_bargain_submit_order',
+    components: { Drawer },
+    emits: ['cancel', 'update'],
+    props: {
+        selectedRow: {
+            type: Object as PropType<QueryTjmdTransferApplyRsp>,
+            default: {},
+        },
+    },
+    setup(props, context) {
+        const { visible, cancel } = _closeModal(context);
+        const loading = ref<boolean>(false);
+
+        function submit() {
+            console.log(geLoginID_number());
+            const param: TradeHoldTransferApplyAuditReqType = {
+                ApplyID: props.selectedRow.applyid,
+                ApplyStatus: 3, // 1:撤销2:拒绝3:通过
+                AuditSrc: 2,
+                AuditorID: geLoginID_number()!.toString(),
+                AuditRemark: '',
+            };
+            requestResultLoadingAndInfo(tradeHoldTransferApplyAuditReq, param, loading, ['同意成功', '同意失败:']).then(() => {
+                // Bus.$emit('spotTrade', true);
+                cancel(true);
+            });
+        }
+
+        Modal.confirm({
+            title: '撤单',
+            content: '是否确认撤单!',
+            onOk: submit,
+            onCancel: cancel,
+        });
+
+        return {
+            visible,
+            cancel,
+        };
+    },
+});
+</script>
+
+<style lang="less" scoped>
+</style>;

+ 141 - 0
src/views/order/swap_the_order/components/swap_commodity_contract_bargain/index.vue

@@ -0,0 +1,141 @@
+<template>
+  <!-- 商品订单 - 议价单 -->
+  <section>
+    <a-table :columns="columns"
+             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="handleBtnList(record, btnList)"
+                 :record="record"
+                 class="btn-list-sticky"
+                 @click="openComponent" />
+      </template>
+      <template #applytime="{ text }">
+        <span>{{ formatTime(text) }}</span>
+      </template>
+      <template #transferamount="{ record , text}">
+        <div>
+          <!-- 审核拒绝 -->
+          <a-tooltip placement="bottom"
+                     v-if="record.applystatus === 4"
+                     overlayClassName="toolTipTableColumn">
+            <template #title>
+              <span>{{ getScfContractStatusName(text) }}</span>
+            </template>
+            <span
+                  :class="record.applystatus === 4 ? 'red' : 'white'">{{ record.transferamount }}</span>
+            <ExclamationCircleOutlined class="ml10 red"
+                                       v-if="record.applystatus === 4" />
+          </a-tooltip>
+          <span v-else>{{ record.transferamount }}</span>
+        </div>
+      </template>
+      <template #buyorsell="{ text }">
+        <span>{{ getBuyOrSellName(text) }}</span>
+      </template>
+      <template #applystatus="{ text }">
+        <span>{{ getScfContractStatusName(text) }}</span>
+      </template>
+    </a-table>
+    <component :is="componentId"
+               v-if="componentId"
+               :selectedRow="selectedRow"
+               :tableList="tableList"
+               @cancel="closeComponent"></component>
+  </section>
+</template>
+
+<script lang="ts">
+import { BtnListType } from '@/common/components/btnList/interface';
+import { ApplyType } from '@/common/constants/enumCommon';
+import { getBuyOrSellName, getScfContractStatusName } from '@/common/constants/enumsName';
+import { BtnList, defineAsyncComponent, defineComponent, queryTableList } from '@/common/export/commonTable';
+import { formatTime } from '@/common/methods';
+import { handleDeliveryRelation } from '@/common/setup/deliveryRelation';
+import { getRecordItemTab } from '@/common/setup/order/orderData';
+import { expandIcon } from '@/common/setup/table/clolumn';
+import { handleComposeOrderTable } from '@/common/setup/table/compose';
+import { ComposeOrderTableParam } from '@/common/setup/table/interface';
+import { getAccoutIdList } from '@/services/bus/account';
+import { QueryTradePositionRsp } from '@/services/go/ermcp/order/interface';
+import { queryTjmdTransferApply } from '@/services/go/Tjmd';
+import { QueryTjmdTransferApplyReq, QueryTjmdTransferApplyRsp } from '@/services/go/Tjmd/interface';
+import Bus from '@/utils/eventBus/index';
+import { ExclamationCircleOutlined } from '@ant-design/icons-vue';
+import { ref } from 'vue';
+import { columns } from './setup';
+
+export default defineComponent({
+    name: 'commodity_contract_bargain',
+    components: {
+        ExclamationCircleOutlined,
+        BtnList,
+        commodity_contract_bargain_submit_order: defineAsyncComponent(() => import('./components/commodity_contract_bargain_submit_order/index.vue')),
+        commodity_contract_bargain_cancel_order: defineAsyncComponent(() => import('./components/commodity_contract_bargain_cancel_order/index.vue')),
+        commodity_contract_bargain_refuse_order: defineAsyncComponent(() => import('./components/commodity_contract_bargain_refuse_order/index.vue')),
+    },
+    setup() {
+        // 类型 1-我的申请 2-对方申请
+        const margainType = ref<ApplyType>(ApplyType.my);
+        // 表格列表数据
+        const { loading, tableList, queryTable } = queryTableList<QueryTjmdTransferApplyRsp>();
+        // 交割商品
+        handleDeliveryRelation();
+        // 获取列表数据
+        const queryTableAction = () => {
+            const param: QueryTjmdTransferApplyReq = {
+                applytype: margainType.value,
+                accountids: getAccoutIdList(),
+            };
+            queryTable(queryTjmdTransferApply, param);
+        };
+        // 表格通用逻辑
+        const param: ComposeOrderTableParam = {
+            queryFn: () => queryTableAction(),
+            recordList: getRecordItemTab(),
+        };
+        // 切换 我的申请和对方申请
+        Bus.$onOnly('bargain', (value: ApplyType) => {
+            margainType.value = value;
+            queryTableAction();
+        });
+        function handleBtnList(record: QueryTjmdTransferApplyRsp, btnList: BtnListType[]) {
+            if (record.applystatus === 1) {
+                if (margainType.value === ApplyType.my) {
+                    // 我的申请
+                    return btnList.filter((e) => e.code === 'commodity_contract_bargain_cancel_order');
+                } else {
+                    // 对方的申请
+                    return btnList.filter((e) => e.code !== 'commodity_contract_bargain_cancel_order');
+                }
+            } else {
+                return [];
+            }
+        }
+        return {
+            ...handleComposeOrderTable<QueryTradePositionRsp>(param),
+            columns,
+            loading,
+            tableList,
+            formatTime,
+            expandIcon,
+            handleBtnList,
+            getBuyOrSellName,
+            getScfContractStatusName,
+        };
+    },
+});
+</script>
+
+<style lang="less">
+</style>;

+ 10 - 0
src/views/order/swap_the_order/components/swap_commodity_contract_bargain/setup.ts

@@ -0,0 +1,10 @@
+export const columns = [
+    { title: '订单合约', dataIndex: 'goodsname', key: 'goodsname', align: 'center', width: 120 },
+    { title: '方向', dataIndex: 'buyorsell', key: 'buyorsell', align: 'center', width: 120, slots: { customRender: 'buyorsell' } },
+    { title: '协议价', dataIndex: 'transferprice', key: 'transferprice', width: 120, align: 'center' },
+    { title: '数量', dataIndex: 'qty', key: 'qty', align: 'center', width: 120, slots: { customRender: 'qty' } },
+    { title: '金额', dataIndex: 'transferamount', key: 'transferamount', width: 120, align: 'center', slots: { customRender: 'transferamount' } },
+    { title: '状态', dataIndex: 'applystatus', key: 'applystatus', width: 120, align: 'center', slots: { customRender: 'applystatus' } },
+    { title: '关联持仓', dataIndex: 'tradeid', key: 'tradeid', width: 120, align: 'center', slots: { customRender: 'tradeid' } },
+    { title: '时间', dataIndex: 'applytime', key: 'applytime', width: 120, align: 'center', slots: { customRender: 'applytime' } },
+];

+ 74 - 0
src/views/order/swap_the_order/components/swap_commodity_contract_commission/components/cancel/index.vue

@@ -0,0 +1,74 @@
+<template>
+  <!-- 现货仓单 现货明细 撤单 -->
+  <div></div>
+</template>
+
+<script lang="ts">
+import { defineComponent, PropType, ref } from 'vue';
+import Drawer from '@/common/components/drawer/index.vue';
+import { WrOrderDetail } from '@/services/go/wrtrade/interface';
+import { getInTaAccount, getUserId } from '@/services/bus/account';
+import { requestResultLoadingAndInfo } from '@/common/methods/request/resultInfo';
+import { wRListingCancelOrder } from '@/services/proto/warehousetrade';
+import { v4 as uuidv4 } from 'uuid';
+import moment from 'moment';
+import { ModalEnum } from '@/common/constants/modalNameEnum';
+import { _closeModal } from '@/common/setup/modal/modal';
+import { WRListingCancelOrderReq } from '@/services/proto/warehousetrade/interface';
+import * as Long from 'long';
+import { geLoginID_number } from '@/services/bus/login';
+import { Modal } from 'ant-design-vue';
+import Bus from '@/utils/eventBus/index';
+import { cancelOrderReq } from '@/services/socket/order';
+import { QueryTradeOrderDetailRsp } from '@/services/go/ermcp/order/interface';
+
+export default defineComponent({
+    name: ModalEnum.spot_warrant_pending_order_cancel_order,
+    components: { Drawer },
+    emits: ['cancel', 'update'],
+    props: {
+        selectedRow: {
+            type: Object as PropType<QueryTradeOrderDetailRsp>,
+            default: {},
+        },
+    },
+    setup(props, context) {
+        const { visible, cancel } = _closeModal(context);
+        const loading = ref<boolean>(false);
+
+        function submit() {
+            const param = {
+                // ClientSerialNo: uuidv4(), // string 客户端流水号
+                // ClientOrderTime: moment().format('YYYY-MM-DD HH:mm:ss'), // string 客户端委托时间
+                // ClientType: 4, // uint32 终端类型
+                // OperateType: 5, // 操作类型
+                OldOrderId: Long.fromString(props.selectedRow.orderid),
+                AccountID: getInTaAccount(), // uint64 资金账号
+                // OrderSrc: 1, // uint32 委托来源
+                OperatorID: Number(geLoginID_number()), // uint64 操作员账号ID
+                MarketID: props.selectedRow.marketid,
+                GoodsID: props.selectedRow.goodsid,
+            };
+            requestResultLoadingAndInfo(cancelOrderReq, param, loading, ['撤单成功', '撤单失败:']).then(() => {
+                Bus.$emit('spotTrade', true);
+                cancel(true);
+            });
+        }
+
+        Modal.confirm({
+            title: '撤单',
+            content: '是否确认撤单?',
+            onOk: submit,
+            onCancel: cancel,
+        });
+
+        return {
+            visible,
+            cancel,
+        };
+    },
+});
+</script>
+
+<style lang="less" scoped>
+</style>;

+ 105 - 0
src/views/order/swap_the_order/components/swap_commodity_contract_commission/index.vue

@@ -0,0 +1,105 @@
+<template>
+  <!-- 商品订单 - 委托 -->
+  <section>
+    <a-table :columns="columns"
+             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="filterBtnList(btnList, record)"
+                 :record="record"
+                 class="btn-list-sticky"
+                 @click="openComponent" />
+      </template>
+      <!-- 类型 -->
+      <template #buildtype="{ record }">
+        <a>{{ getBuyOrSellTypeName(record.buyorsell) }}</a>
+      </template>
+      <!-- 状态 -->
+      <template #orderstatus="{ record }">
+        <a>{{ getOrderStatusName(record.orderstatus) }}</a>
+      </template>
+
+      <template #ordertime="{ text }">
+        <a>{{ formatTime(text) }}</a>
+      </template>
+    </a-table>
+    <component :is="componentId"
+               v-if="componentId"
+               :selectedRow="selectedRow"
+               @cancel="closeComponent"></component>
+  </section>
+</template>
+
+<script lang="ts">
+import { BtnListType } from '@/common/components/btnList/interface';
+import { enumOrderComponents } from '@/common/constants/enumOrderComponents';
+import { getBuyOrSellTypeName, getOrderStatusName } from '@/common/constants/enumsName';
+import { BtnList, defineAsyncComponent, defineComponent, queryTableList } from '@/common/export/commonTable';
+import { formatTime } from '@/common/methods';
+import { getRecordItemTab } from '@/common/setup/order/orderData';
+import { expandIcon } from '@/common/setup/table/clolumn';
+import { handleComposeOrderTable } from '@/common/setup/table/compose';
+import { ComposeOrderTableParam } from '@/common/setup/table/interface';
+import { queryTradeOrderDetail } from '@/services/go/ermcp/order';
+import { QueryTradeOrderDetailRsp } from '@/services/go/ermcp/order/interface';
+import { WrPerformancePlan } from '@/services/go/wrtrade/interface';
+import Bus from '@/utils/eventBus/index';
+
+export default defineComponent({
+    name: enumOrderComponents.commodity_contract_commission,
+    components: {
+        BtnList,
+        commodity_contract_commission_cancel_order: defineAsyncComponent(() => import('./components/cancel/index.vue')),
+    },
+    setup() {
+        // 表格列表数据
+        const { loading, tableList, queryTable } = queryTableList<QueryTradeOrderDetailRsp>();
+        // 获取列表数据
+        const queryTableAction = () => {
+            queryTable(queryTradeOrderDetail, {});
+        };
+        // 表格通用逻辑
+        const param: ComposeOrderTableParam = {
+            queryFn: queryTableAction,
+            tableName: 'table_pcweb_spot_trade_bottom_commodity_contract_commission',
+            recordList: getRecordItemTab(),
+        };
+        function filterBtnList(list: BtnListType[], record: QueryTradeOrderDetailRsp) {
+            //委托状态 - 1:委托请求 2:待冻结 3:委托成功 4:委托失败 5:配对成功 6:已撤 7:已成 8:成交失败 9:委托拒绝 1number;
+            const arr = [3, 7];
+            if (!arr.includes(record.orderstatus)) {
+                return list.filter((e) => e.code !== 'commodity_contract_commission_cancel_order');
+            } else {
+                return list;
+            }
+        }
+        // 挂牌
+        Bus.$on('spotTrade', () => {
+            queryTableAction();
+        });
+        return {
+            ...handleComposeOrderTable<WrPerformancePlan>(param),
+            loading,
+            tableList,
+            formatTime,
+            expandIcon,
+            getBuyOrSellTypeName,
+            getOrderStatusName,
+            filterBtnList,
+        };
+    },
+});
+</script>
+
+<style lang="less">
+</style>;

+ 108 - 0
src/views/order/swap_the_order/components/swap_commodity_contract_make_deal/index.vue

@@ -0,0 +1,108 @@
+<template>
+  <!-- 商品订单 - 成交 -->
+  <section>
+    <a-table :columns="columns"
+             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" />
+      </template>
+      <!-- 类型 -->
+      <template #buyorsell="{ text }">
+        <span>{{ getBuyOrSellTypeName(text) }}</span>
+      </template>
+      <template #tradeprice="{ text, record }">
+        <span>{{ handleType(record, text)}}</span>
+      </template>
+      <template #matchaccountid="{ text, record }">
+        <span>{{ handleType(record, text)}}</span>
+      </template>
+      <!-- 状态 -->
+      <template #orderstatus="{ record }">
+        <a>{{ getOrderStatusName(record.orderstatus) }}</a>
+      </template>
+      <template #createtime="{ record }">
+        <a>{{ formatTime(record.createtime) }}</a>
+      </template>
+    </a-table>
+    <component :is="componentId"
+               v-if="componentId"
+               :selectedRow="selectedRow"
+               @cancel="closeComponent"></component>
+  </section>
+</template>
+
+<script lang="ts">
+import { enumOrderComponents } from '@/common/constants/enumOrderComponents';
+import { getBuildTypeName, getBuyOrSellTypeName, getOrderStatusName } from '@/common/constants/enumsName';
+import { BtnList, defineComponent, queryTableList } from '@/common/export/commonTable';
+import { formatTime } from '@/common/methods';
+import { getRecordItemTab } from '@/common/setup/order/orderData';
+import { expandIcon } from '@/common/setup/table/clolumn';
+import { handleComposeOrderTable } from '@/common/setup/table/compose';
+import { ComposeOrderTableParam } from '@/common/setup/table/interface';
+import { queryTradeDetail } from '@/services/go/ermcp/order';
+import { QueryTradeDetailRsp } from '@/services/go/ermcp/order/interface';
+import Bus from '@/utils/eventBus/index';
+import { handleNoneValue } from '@/common/setup/table/tableQuote';
+
+export default defineComponent({
+    name: enumOrderComponents.commodity_contract_make_deal,
+    components: {
+        BtnList,
+    },
+    setup() {
+        // 表格列表数据
+        const { loading, tableList, queryTable } = queryTableList<QueryTradeDetailRsp>();
+        // 获取列表数据
+        const queryTableAction = () => {
+            queryTable(queryTradeDetail, {});
+        };
+        // 表格通用逻辑
+        const param: ComposeOrderTableParam = {
+            queryFn: queryTableAction,
+            tableName: 'table_pcweb_spot_trade_bottom_commodity_contract_make_deal',
+            recordList: getRecordItemTab(),
+        };
+        // fix: #2063
+        function handleType(record: QueryTradeDetailRsp, value: string | number) {
+            let result: number | string = '--';
+            if (value) {
+                result = record.tradetype === 22 ? '--' : value;
+            }
+            return result;
+        }
+        Bus.$on('spotTrade', () => {
+            queryTableAction();
+        });
+        return {
+            ...handleComposeOrderTable<QueryTradeDetailRsp>(param),
+            loading,
+            tableList,
+            formatTime,
+            expandIcon,
+            getBuildTypeName,
+            getOrderStatusName,
+            getBuyOrSellTypeName,
+            handleNoneValue,
+            handleType,
+        };
+    },
+});
+</script>
+
+<style lang="less">
+</style>;

+ 402 - 0
src/views/order/swap_the_order/components/swap_commodity_contract_summary/components/commodity_contract_summary_deal_closed/index.vue

@@ -0,0 +1,402 @@
+<template>
+  <!-- 协议平仓-->
+  <Drawer :title="'协议平仓'"
+          :placement="'right'"
+          class="bottom486"
+          :visible="visible"
+          @cancel="cancel">
+    <div class="listed c_c_s_s">
+      <a-form class="inlineForm dialogForm"
+              ref="formRef"
+              :model="formState"
+              :rules="rules">
+        <div class="formBar">
+          <div class="formtop">
+            <div class="firstTitle">
+              <span>合约:{{selectedRow.goodscode}}/{{selectedRow.goodsname}}</span>
+            </div>
+            <div class="secondLine">
+              <div class="left">持仓单号/方向</div>
+              <div class="middle">数量/价格/金额</div>
+              <div class="right">到期日/盈亏</div>
+            </div>
+            <a-checkbox-group class="commonCheckboxGroup"
+                              v-model:value="checked"
+                              @change="checkGroupChange">
+              <div class="lineBar"
+                   v-for="item in tableList"
+                   :key="item.tradeid">
+                <div class="line1">
+                  <div class>
+                    <a-checkbox @change="checkboxChange(item)"
+                                :value="item.tradeid"></a-checkbox>
+                  </div>
+                  <div class="name">{{ item.tradeid }}
+                  </div>
+                  <div class="date">{{formatTime(item.expiredate, 'd')}}</div>
+                </div>
+                <div class="line2">
+                  <div class="left">{{item.buyorsell === BuyOrSell.buy ? '买入' : '卖出'}}</div>
+                  <div class="middle">
+                    <div>{{item.holderqty}}</div>
+                    <div>{{item.holderprice}}</div>
+                    <div>{{item.holderamount}}</div>
+                  </div>
+                  <div class="right red">
+                    {{useProfit(item, goodscode)}}</div>
+                </div>
+              </div>
+            </a-checkbox-group>
+          </div>
+        </div>
+        <div class="fixedBtns">
+          <a-row :gutter="24">
+            <a-col :span="24"
+                   class="mt12">
+              <a-form-item label="协议价"
+                           name="price"
+                           class="inputIconBox mb10 not-copy">
+                <a-input-number class="commonInput not-copy"
+                                v-model:value="formState.price"
+                                style="width: 200px"
+                                :min="0" />
+                <MinusOutlined @click="decreasePrice" />
+                <PlusOutlined @click="increasePirce" />
+              </a-form-item>
+            </a-col>
+            <a-col :span="24">
+              <a-form-item label="平仓金额"
+                           class="mb10 not-copy ">
+                <span class="white">{{getMoney()}}</span>
+              </a-form-item>
+            </a-col>
+          </a-row>
+          <a-form-item class="btnCenter mt10">
+            <a-button class="listedBtn"
+                      :loading="loading"
+                      :disabled="loading"
+                      @click="submit">提交</a-button>
+            <a-button class="ml10 cancelBtn"
+                      @click="cancel">取消</a-button>
+          </a-form-item>
+        </div>
+      </a-form>
+    </div>
+  </Drawer>
+</template>
+
+<script lang="ts">
+import Drawer from '@/common/components/drawer/index.vue';
+import UploadImg from '@/common/components/uploadImg/index.vue';
+import { BuyOrSell } from '@/common/constants/enumCommon';
+import { ModalEnum } from '@/common/constants/modalNameEnum';
+import { requestResultLoadingAndInfo } from '@/common/methods/request/resultInfo';
+import { validateAction } from '@/common/setup/form';
+import { _closeModal } from '@/common/setup/modal/modal';
+import { queryTableList } from '@/common/setup/table';
+import { getUserId } from '@/services/bus/account';
+import { geLoginID_number } from '@/services/bus/login';
+import { QueryTradePositionRsp } from '@/services/go/ermcp/order/interface';
+import { queryTradeHolderDetail } from '@/services/go/order';
+import { QueryTradeHolderDetailReq } from '@/services/go/order/interface';
+import { tradeHoldTransferApply } from '@/services/proto/warehousetrade';
+import { TradeHoldTransferApplyReq } from '@/services/proto/warehousetrade/interface';
+import { MinusOutlined, PlusOutlined } from '@ant-design/icons-vue';
+import { message } from 'ant-design-vue';
+import Long from 'long';
+import { defineComponent, PropType } from 'vue';
+import { BargainList, FormState } from './interface';
+import { handleForm, usePrice } from './setup';
+import { formatTime } from '@/common/methods';
+import { useProfit, useCheckd } from '../setup';
+import { QueryQuoteGoodsListRsp } from '@/services/go/Tjmd/interface';
+import { findGoodsCode } from '../../setup';
+
+export default defineComponent({
+    name: ModalEnum.commodity_contract_summary_settlement,
+    components: { Drawer, UploadImg, PlusOutlined, MinusOutlined },
+    emits: ['cancel', 'update'],
+    props: {
+        selectedRow: {
+            type: Object as PropType<QueryTradePositionRsp>,
+            default: {},
+        },
+        buyOrSell: {
+            type: Number as PropType<BuyOrSell>,
+            default: BuyOrSell.buy,
+        },
+        swapList: {
+            type: Array as PropType<QueryQuoteGoodsListRsp[]>,
+            default: [],
+        },
+    },
+    setup(props, context) {
+        const { visible, cancel } = _closeModal(context);
+        const { rules, formState, formRef } = handleForm();
+        const goodscode = findGoodsCode(props.selectedRow.goodsid, props.selectedRow.goodscode, props.swapList);
+
+        // 选中逻辑
+        const { checked, selected, checkGroupChange, checkboxChange } = useCheckd();
+
+        // 表格列表数据
+        const { loading, tableList, queryTable } = queryTableList<BargainList>();
+        const param: QueryTradeHolderDetailReq = {
+            buyorsell: props.selectedRow.buyorsell,
+            userid: getUserId(),
+            goodsid: props.selectedRow.goodsid,
+        };
+        // 平仓金额
+        function getMoney() {
+            let result = '--';
+            if (selected.value && formState.price) {
+                const { holderqty, agreeunit, decimalplace } = selected.value;
+                result = (+formState.price * holderqty * agreeunit).toFixed(decimalplace);
+            }
+            return result;
+        }
+        queryTable(queryTradeHolderDetail, param).then((res) => {
+            tableList.value = res.map((e, i) => {
+                if (i === 0) {
+                    checked.value = e.tradeid;
+                    const result = { ...e, checked: true };
+                    selected.value = result;
+                    return result;
+                } else {
+                    return { ...e, checked: false };
+                }
+            });
+        });
+
+        const toFixed0 = (value: number) => +value.toFixed(0);
+
+        function submit() {
+            if (!selected.value) {
+                message.warn('请选择持仓');
+                return;
+            }
+            validateAction<FormState>(formRef, formState).then((res) => {
+                const param: TradeHoldTransferApplyReq = {
+                    TradeID: Long.fromString(selected.value!.tradeid),
+                    BuyorSell: selected.value!.buyorsell,
+                    TransferPrice: res.price,
+                    ApplySrc: 2,
+                    ApplicantID: geLoginID_number()!,
+                    Remark: '',
+                };
+                requestResultLoadingAndInfo(tradeHoldTransferApply, param, loading, ['协议平仓成功', '协议平仓失败:']).then(() => {
+                    cancel(true);
+                });
+            });
+        }
+        return {
+            visible,
+            cancel,
+            submit,
+            tableList,
+            loading,
+            toFixed0,
+            rules,
+            formState,
+            formRef,
+            ...usePrice(formState),
+            checked,
+            checkGroupChange,
+            checkboxChange,
+            BuyOrSell,
+            formatTime,
+            useProfit,
+            goodscode,
+            getMoney,
+        };
+    },
+});
+</script>
+
+<style lang="less" scoped>
+.c_c_s_s {
+    background: @m-black40;
+    width: 100%;
+    height: 100%;
+    position: relative;
+    .formBar {
+        padding: 0;
+        height: calc(100% - 170px);
+        background: @m-black41;
+        .formtop {
+            width: 100%;
+            padding: 0 20px;
+            .flex;
+            flex-direction: column;
+            .firstTitle {
+                width: calc(100% + 40px);
+                height: 40px;
+                line-height: 40px;
+                margin-left: -20px;
+                padding: 0 20px;
+                font-size: 14px;
+                color: @m-white6;
+                border-bottom: 1px solid @m-black42;
+            }
+            .secondLine {
+                width: 100%;
+                height: 40px;
+                line-height: 40px;
+                display: inline-flex;
+                > div {
+                    flex: 1;
+                    font-size: 14px;
+                    color: @m-grey1;
+                }
+                .left {
+                    text-align: left;
+                }
+                .middle {
+                    text-align: center;
+                }
+                .right {
+                    text-align: right;
+                }
+            }
+            .lineBar {
+                width: 100%;
+                min-height: 100px;
+                padding-left: 15px;
+                padding-right: 10px;
+                background: @m-blue19;
+                margin-bottom: 10px;
+                .rounded-corners(5px);
+                .line1 {
+                    display: inline-flex;
+                    user-select: none;
+                    width: 100%;
+                    height: 40px;
+                    line-height: 40px;
+                    font-size: 12px;
+                    color: @m-white6;
+                    white-space: nowrap;
+                    text-overflow: ellipsis;
+                    overflow: hidden;
+                    border-bottom: 1px solid @m-blue20;
+                    > div {
+                        align-self: center;
+                        align-items: center;
+                    }
+                    .name {
+                        margin-left: 10px;
+                    }
+                    .date {
+                        flex: 1;
+                        text-align: right;
+                        font-size: 14px;
+                        color: @m-grey1;
+                    }
+                }
+                .line2 {
+                    width: 100%;
+                    user-select: none;
+                    padding: 12px 0 14px 0;
+                    display: inline-flex;
+                    .left {
+                        width: 25%;
+                        color: @m-white6;
+                        font-size: 14px;
+                        white-space: nowrap;
+                        text-overflow: ellipsis;
+                        overflow: hidden;
+                        line-height: 34px;
+                        // }
+                    }
+                    .middle {
+                        width: 50%;
+                        display: inline-flex;
+                        justify-content: space-between;
+                        padding: 0 10px;
+                        font-size: 16px;
+                        color: @m-white6;
+                        line-height: 34px;
+                        > div {
+                            white-space: nowrap;
+                        }
+                    }
+                    .right {
+                        width: 25%;
+                        font-size: 16px;
+                        text-align: right;
+                        line-height: 34px;
+                        white-space: nowrap;
+                    }
+                }
+            }
+        }
+    }
+    .fixedBtns {
+        padding-top: 0;
+        left: 0;
+        right: 0;
+        padding-left: 20px;
+        padding-right: 20px;
+    }
+    .formbottom {
+        width: 100%;
+        .flex;
+        flex-direction: column;
+        background: @m-black40;
+        padding: 0 18px 0 20px;
+        .line1 {
+            width: 100%;
+            padding: 0 12px 0 16px;
+            height: 36px;
+            line-height: 36px;
+            display: inline-flex;
+            justify-content: space-between;
+            color: @m-grey1;
+            font-size: 14px;
+        }
+        .line2 {
+            width: 100%;
+            height: 35px;
+            line-height: 34px;
+            padding-left: 15px;
+            padding-right: 10px;
+            background: @m-black43;
+            .rounded-corners(5px);
+            font-size: 14px;
+            color: @m-grey1;
+            display: inline-flex;
+            justify-content: space-between;
+            > div {
+                align-self: baseline;
+                align-items: baseline;
+            }
+            .right {
+                display: inline-flex;
+                color: @m-yellow6;
+                div:last-child {
+                    font-size: 16px;
+                    margin-left: 2px;
+                }
+            }
+        }
+        .line3 {
+            margin-top: 16px;
+            width: 100%;
+            height: 15px;
+            line-height: 15px;
+            font-size: 14px;
+            text-align: right;
+            color: @m-white6;
+        }
+    }
+    .inputIconBox {
+        .ant-form-item-children {
+            .anticon-plus {
+                right: 156px;
+            }
+        }
+    }
+}
+</style>;
+
+function queryTradeHolderDetail(queryTradeHolderDetail: any, param: { applytype: number; }) {
+  throw new Error('Function not implemented.');
+}

+ 10 - 0
src/views/order/swap_the_order/components/swap_commodity_contract_summary/components/commodity_contract_summary_deal_closed/interface.ts

@@ -0,0 +1,10 @@
+import { QueryTradeHolderDetailRsp } from "@/services/go/order/interface";
+
+export interface FormState {
+    price: number,
+}
+
+
+export interface BargainList extends QueryTradeHolderDetailRsp {
+    checked: boolean
+}

+ 35 - 0
src/views/order/swap_the_order/components/swap_commodity_contract_summary/components/commodity_contract_summary_deal_closed/setup.ts

@@ -0,0 +1,35 @@
+import { validateCommon } from "@/common/setup/validate";
+import { RuleObject } from "ant-design-vue/lib/form/interface";
+import { reactive, ref, UnwrapRef } from "vue";
+import { FormState } from "./interface";
+
+export function handleForm() {
+    const formRef = ref();
+    const v_num = async (rule: RuleObject, value: number) => {
+        return validateCommon(value, '请输入协议价');
+    };
+    const formState: UnwrapRef<FormState> = reactive({
+        price: 0,
+    })
+    const rules = {
+        price: [
+            { require, message: '请输入协议价', trigger: 'blur', type: 'number', validator: v_num },
+        ],
+    }
+    return { rules, formState, formRef }
+}
+
+export function usePrice(formState: UnwrapRef<FormState>) {
+    function increasePirce() {
+        formState.price++
+    }
+    function decreasePrice() {
+        if (formState.price) {
+            formState.price--
+        }
+    }
+    return { increasePirce, decreasePrice }
+}
+
+
+

+ 415 - 0
src/views/order/swap_the_order/components/swap_commodity_contract_summary/components/commodity_contract_summary_order_closed/index.vue

@@ -0,0 +1,415 @@
+<template>
+  <!-- 平仓-->
+  <Drawer :title="'平仓'"
+          :placement="'right'"
+          class="bottom486"
+          :visible="visible"
+          @cancel="cancel">
+    <div class="listed c_c_s_s">
+      <a-form class="inlineForm dialogForm"
+              ref="formRef"
+              :model="formState"
+              :rules="rules">
+        <div class="formBar">
+          <div class="formtop">
+            <div class="firstTitle">
+              <span>合约:{{ selectedRow.goodscode }}/{{ selectedRow.goodsname }}</span>
+            </div>
+            <div class="secondLine">
+              <div class="left">持仓单号/方向</div>
+              <div class="middle">数量/价格/金额</div>
+              <div class="right">到期日/盈亏</div>
+            </div>
+            <a-checkbox-group class="commonCheckboxGroup"
+                              v-model:value="checked"
+                              @change="checkGroupChange">
+              <div class="lineBar"
+                   v-for="item in tableList"
+                   :key="item.tradeid">
+                <div class="line1">
+                  <div class>
+                    <a-checkbox @change="checkboxChange(item)"
+                                :disabled="item.holderdays"
+                                :value="item.tradeid"></a-checkbox>
+                  </div>
+                  <div class="name">{{ item.tradeid }}
+                    <template v-if="item.holderdays">
+                      <span class="red">{{item.holderdays}}</span>天后可平
+                    </template>
+                  </div>
+                  <div class="date">{{ formatTime(item.expiredate, 'd') }}</div>
+                </div>
+                <div class="line2">
+                  <div class="left">{{ item.buyorsell === BuyOrSell.buy ? '买入' : '卖出' }}</div>
+                  <div class="middle">
+                    <div>{{ item.holderqty }}</div>
+                    <div>{{ item.holderprice }}</div>
+                    <div>{{ item.holderamount }}</div>
+                  </div>
+                  <div class="right red">
+                    {{useProfit(item, goodscode)}}</div>
+                </div>
+              </div>
+            </a-checkbox-group>
+          </div>
+        </div>
+        <div class="fixedBtns">
+          <a-row :gutter="24">
+            <a-col :span="24"
+                   class="mt12">
+              <a-form-item label="估算价"
+                           class="inputIconBox mb10 not-copy">
+                <!-- 估算价取标的商品行情的最新价 -->
+                <span class="white">{{getQuoteDayInfoByCodeFindPrice(goodscode)}}</span>
+              </a-form-item>
+            </a-col>
+            <a-col :span="24">
+              <a-form-item label="估算金额"
+                           class="mb10 not-copy">
+                <span class="white">{{selected ? getMoney() : '--'}}</span>
+              </a-form-item>
+            </a-col>
+          </a-row>
+          <a-form-item class="btnCenter mt10">
+            <a-button class="listedBtn"
+                      :loading="loading"
+                      :disabled="loading"
+                      @click="submit">提交</a-button>
+            <a-button class="ml10 cancelBtn"
+                      @click="cancel">取消</a-button>
+          </a-form-item>
+        </div>
+      </a-form>
+    </div>
+  </Drawer>
+</template>
+
+<script lang="ts">
+import Drawer from '@/common/components/drawer/index.vue';
+import UploadImg from '@/common/components/uploadImg/index.vue';
+import { BuyOrSell } from '@/common/constants/enumCommon';
+import { ModalEnum } from '@/common/constants/modalNameEnum';
+import { requestResultLoadingAndInfo } from '@/common/methods/request/resultInfo';
+import { validateAction } from '@/common/setup/form';
+import { _closeModal } from '@/common/setup/modal/modal';
+import { queryTableList } from '@/common/setup/table';
+import { getSelectedAccountId, getUserId } from '@/services/bus/account';
+import { geLoginID_number } from '@/services/bus/login';
+import { QueryTradePositionRsp } from '@/services/go/ermcp/order/interface';
+import { queryTradeHolderDetail } from '@/services/go/order';
+import { QueryTradeHolderDetailReq } from '@/services/go/order/interface';
+import { holderClose } from '@/services/proto/warehousetrade';
+import { HolderCloseReq } from '@/services/proto/warehousetrade/interface';
+import { MinusOutlined, PlusOutlined } from '@ant-design/icons-vue';
+import { message } from 'ant-design-vue';
+import Long from 'long';
+import { defineComponent, PropType } from 'vue';
+import { BargainList, FormState } from './interface';
+import { handleForm, usePrice } from './setup';
+import { formatTime } from '@/common/methods';
+import { useProfit, useCheckd } from '../setup';
+import { QueryQuoteGoodsListRsp } from '@/services/go/Tjmd/interface';
+import { findGoodsCode } from '../../setup';
+import { getQuoteDayInfoByCodeFindPrice } from '@/services/bus/goods';
+
+export default defineComponent({
+    name: ModalEnum.commodity_contract_summary_settlement,
+    components: { Drawer, UploadImg, PlusOutlined, MinusOutlined },
+    emits: ['cancel', 'update'],
+    props: {
+        selectedRow: {
+            type: Object as PropType<QueryTradePositionRsp>,
+            default: {},
+        },
+        buyOrSell: {
+            type: Number as PropType<BuyOrSell>,
+            default: BuyOrSell.buy,
+        },
+        swapList: {
+            type: Array as PropType<QueryQuoteGoodsListRsp[]>,
+            default: [],
+        },
+    },
+    setup(props, context) {
+        const goodscode = findGoodsCode(props.selectedRow.goodsid, props.selectedRow.goodscode, props.swapList);
+
+        const { visible, cancel } = _closeModal(context);
+        const { rules, formState, formRef } = handleForm();
+        // 选中逻辑
+        const { checked, selected, checkGroupChange, checkboxChange } = useCheckd();
+
+        // 表格列表数据
+        const { loading, tableList, queryTable } = queryTableList<BargainList>();
+        const param: QueryTradeHolderDetailReq = {
+            buyorsell: props.selectedRow.buyorsell,
+            userid: getUserId(),
+            goodsid: props.selectedRow.goodsid,
+        };
+        // 估算金额=估算价*平仓数量*合约单位。
+        function getMoney() {
+            let result = '--';
+            const lastPrice = getQuoteDayInfoByCodeFindPrice(goodscode);
+            if (lastPrice && lastPrice !== '--' && selected.value) {
+                const { holderqty, agreeunit, decimalplace } = selected.value;
+                result = (+lastPrice * holderqty * agreeunit).toFixed(decimalplace);
+            }
+            return result;
+        }
+
+        queryTable(queryTradeHolderDetail, param).then((res) => {
+            let index = 0; // 默认勾选
+            tableList.value = res.map((e, i) => {
+                if (index === i) {
+                    if (e.holderdays === 0) {
+                        checked.value = e.tradeid;
+                        const result = { ...e, checked: true };
+                        selected.value = result;
+                        index = -1;
+                        return result;
+                    } else {
+                        index++;
+                        return { ...e, checked: false };
+                    }
+                } else {
+                    return { ...e, checked: false };
+                }
+            });
+        });
+
+        const toFixed0 = (value: number) => +value.toFixed(0);
+
+        function submit() {
+            if (!selected.value) {
+                message.warn('请选择持仓');
+                return;
+            }
+            validateAction<FormState>(formRef, formState).then((res) => {
+                const param: HolderCloseReq = {
+                    TradeID: Long.fromString(selected.value!.tradeid),
+
+                    // ClientSerialNo: 'string', // string 客户端流水号
+                    // ClientOrderTime: 'string', // string 客户端委托时间
+                    // ClientType: 0, // uint32 终端类型
+                    LoginID: geLoginID_number()!, // uint64 登陆账号
+                    AccountID: getSelectedAccountId(), // uint64 交易账号
+                    GoodsID: selected.value!.goodsid,
+                    MarketID: selected.value!.marketid, // uint32 市场ID
+                    BuyOrSell: selected.value!.buyorsell,
+                    // OrderSrc: 0, // uint32 单据来源
+                    OperatorID: geLoginID_number()!, // uint64 操作员账号ID
+                };
+                requestResultLoadingAndInfo(holderClose, param, loading, ['平仓成功', '平仓失败:']).then(() => {
+                    cancel(true);
+                });
+            });
+        }
+        return {
+            visible,
+            cancel,
+            submit,
+            tableList,
+            loading,
+            toFixed0,
+            rules,
+            formState,
+            formRef,
+            ...usePrice(formState),
+            checked,
+            checkGroupChange,
+            checkboxChange,
+            BuyOrSell,
+            formatTime,
+            useProfit,
+            goodscode,
+            getQuoteDayInfoByCodeFindPrice,
+            getMoney,
+            selected,
+        };
+    },
+});
+</script>
+
+<style lang="less" scoped>
+.c_c_s_s {
+    background: @m-black40;
+    width: 100%;
+    height: 100%;
+    position: relative;
+    .formBar {
+        padding: 0;
+        height: calc(100% - 170px);
+        background: @m-black41;
+        .formtop {
+            width: 100%;
+            padding: 0 20px;
+            .flex;
+            flex-direction: column;
+            .firstTitle {
+                width: calc(100% + 40px);
+                height: 40px;
+                line-height: 40px;
+                margin-left: -20px;
+                padding: 0 20px;
+                font-size: 14px;
+                color: @m-white6;
+                border-bottom: 1px solid @m-black42;
+            }
+            .secondLine {
+                width: 100%;
+                height: 40px;
+                line-height: 40px;
+                display: inline-flex;
+                > div {
+                    flex: 1;
+                    font-size: 14px;
+                    color: @m-grey1;
+                }
+                .left {
+                    text-align: left;
+                }
+                .middle {
+                    text-align: center;
+                }
+                .right {
+                    text-align: right;
+                }
+            }
+            .lineBar {
+                width: 100%;
+                min-height: 100px;
+                padding-left: 15px;
+                padding-right: 10px;
+                background: @m-blue19;
+                margin-bottom: 10px;
+                .rounded-corners(5px);
+                .line1 {
+                    display: inline-flex;
+                    user-select: none;
+                    width: 100%;
+                    height: 40px;
+                    line-height: 40px;
+                    font-size: 12px;
+                    color: @m-white6;
+                    white-space: nowrap;
+                    text-overflow: ellipsis;
+                    overflow: hidden;
+                    border-bottom: 1px solid @m-blue20;
+                    > div {
+                        align-self: center;
+                        align-items: center;
+                    }
+                    .name {
+                        margin-left: 10px;
+                    }
+                    .date {
+                        flex: 1;
+                        text-align: right;
+                        font-size: 14px;
+                        color: @m-grey1;
+                    }
+                }
+                .line2 {
+                    width: 100%;
+                    user-select: none;
+                    padding: 12px 0 14px 0;
+                    display: inline-flex;
+                    .left {
+                        width: 25%;
+                        color: @m-white6;
+                        font-size: 14px;
+                        white-space: nowrap;
+                        text-overflow: ellipsis;
+                        overflow: hidden;
+                        line-height: 34px;
+                        // }
+                    }
+                    .middle {
+                        width: 50%;
+                        display: inline-flex;
+                        justify-content: space-between;
+                        padding: 0 10px;
+                        font-size: 16px;
+                        color: @m-white6;
+                        line-height: 34px;
+                        > div {
+                            white-space: nowrap;
+                        }
+                    }
+                    .right {
+                        width: 25%;
+                        font-size: 16px;
+                        text-align: right;
+                        line-height: 34px;
+                        white-space: nowrap;
+                    }
+                }
+            }
+        }
+    }
+    .fixedBtns {
+        padding-top: 0;
+        left: 0;
+        right: 0;
+        padding-left: 20px;
+        padding-right: 20px;
+    }
+    .formbottom {
+        width: 100%;
+        .flex;
+        flex-direction: column;
+        background: @m-black40;
+        padding: 0 18px 0 20px;
+        .line1 {
+            width: 100%;
+            padding: 0 12px 0 16px;
+            height: 36px;
+            line-height: 36px;
+            display: inline-flex;
+            justify-content: space-between;
+            color: @m-grey1;
+            font-size: 14px;
+        }
+        .line2 {
+            width: 100%;
+            height: 35px;
+            line-height: 34px;
+            padding-left: 15px;
+            padding-right: 10px;
+            background: @m-black43;
+            .rounded-corners(5px);
+            font-size: 14px;
+            color: @m-grey1;
+            display: inline-flex;
+            justify-content: space-between;
+            > div {
+                align-self: baseline;
+                align-items: baseline;
+            }
+            .right {
+                display: inline-flex;
+                color: @m-yellow6;
+                div:last-child {
+                    font-size: 16px;
+                    margin-left: 2px;
+                }
+            }
+        }
+        .line3 {
+            margin-top: 16px;
+            width: 100%;
+            height: 15px;
+            line-height: 15px;
+            font-size: 14px;
+            text-align: right;
+            color: @m-white6;
+        }
+    }
+    .inputIconBox {
+        .ant-form-item-children {
+            .anticon-plus {
+                right: 156px;
+            }
+        }
+    }
+}
+</style>;

+ 10 - 0
src/views/order/swap_the_order/components/swap_commodity_contract_summary/components/commodity_contract_summary_order_closed/interface.ts

@@ -0,0 +1,10 @@
+import { QueryTradeHolderDetailRsp } from "@/services/go/order/interface";
+
+export interface FormState {
+    price: number,
+}
+
+
+export interface BargainList extends QueryTradeHolderDetailRsp {
+    checked: boolean
+}

+ 32 - 0
src/views/order/swap_the_order/components/swap_commodity_contract_summary/components/commodity_contract_summary_order_closed/setup.ts

@@ -0,0 +1,32 @@
+import { validateCommon } from "@/common/setup/validate";
+import { RuleObject } from "ant-design-vue/lib/form/interface";
+import { reactive, ref, UnwrapRef } from "vue";
+import { FormState } from "./interface";
+
+export function handleForm() {
+    const formRef = ref();
+    const v_num = async (rule: RuleObject, value: number) => {
+        return validateCommon(value, '请输入协议价');
+    };
+    const formState: UnwrapRef<FormState> = reactive({
+        price: 0,
+    })
+    const rules = {
+        price: [
+            { require, message: '请输入协议价', trigger: 'blur', type: 'number', validator: v_num },
+        ],
+    }
+    return { rules, formState, formRef }
+}
+
+export function usePrice(formState: UnwrapRef<FormState>) {
+    function increasePirce() {
+        formState.price++
+    }
+    function decreasePrice() {
+        if (formState.price) {
+            formState.price--
+        }
+    }
+    return { increasePirce, decreasePrice }
+}

+ 428 - 0
src/views/order/swap_the_order/components/swap_commodity_contract_summary/components/commodity_contract_summary_settlement/index.vue

@@ -0,0 +1,428 @@
+<template>
+  <!-- 交收-->
+  <Drawer :title="'交收'"
+          :placement="'right'"
+          class="bottom486"
+          :visible="visible"
+          @cancel="cancel">
+    <div class="listed c_c_s_s">
+      <a-form class="inlineForm dialogForm"
+              ref="formRef">
+        <div class="formBar">
+          <div class="formtop">
+            <div class="firstTitle">
+              <span>合约 {{selectedRow.goodscode}}&nbsp;&nbsp;</span>
+              <span>合约数量 {{selectedRow.enableqty}}&nbsp;&nbsp;</span>
+              <span>可交收数量 {{getCanSettlementNum()}} {{selectedRow.goodunit}}</span>
+            </div>
+            <div class="secondLine">
+              <div class="left">持有人/商品/仓库</div>
+              <div class="middle">升贴水/数量</div>
+              <div class="right">选择数量</div>
+            </div>
+            <a-checkbox-group class="commonCheckboxGroup"
+                              v-model:value="checked"
+                              @change="checkGroupChange">
+              <div class="lineBar"
+                   v-for="(item, index) in tableList"
+                   :key="index + '11'">
+                <div class="line1">
+                  <div class>
+                    <a-checkbox @change="checkboxChange(item)"
+                                :value="item.ladingbillid"></a-checkbox>
+                  </div>
+                  <div class="name">{{item.username}}</div>
+                </div>
+                <div class="line2">
+                  <div class="left">
+                    <div>{{item.wrtypename}}</div>
+                    <div>{{item.warehousename}}</div>
+                  </div>
+                  <div class="middle">
+                    <div>{{item.pricemove}}</div>
+                    <div>{{toFixed0(item.avalidqty)}}{{item.enumdicname}}</div>
+                  </div>
+                  <div class="right">
+                    <template class="inputNumberBlock"
+                              :class="isChecked(item.ladingbillid) ? '' : 'disabled'">
+                      <a-input-number class="dialogInput dialogInput34"
+                                      v-model:value="item.num"
+                                      style="width: 130px !important; height: 34px;"
+                                      :disabled="!isChecked(item.ladingbillid)"
+                                      :max="toFixed0(item.avalidqty)"
+                                      :min="0"></a-input-number>
+                      <MinusOutlined @click="decrease(item)" />
+                      <PlusOutlined @click="increase(item)" />
+                    </template>
+                  </div>
+                </div>
+              </div>
+            </a-checkbox-group>
+          </div>
+        </div>
+        <div class="fixedBtns">
+          <div class="formbottom">
+            <div class="line1">
+              <div>
+                <span>已点选数量</span>
+                <span class="white">{{selctedNum()}} {{selectedRow.goodunit}}</span>
+                <span>,需合约数量</span>
+                <span class="white">{{getNeedContractNum()}}</span>
+              </div>
+              <div class="yellow">升贴水{{selected ? selected.pricemove * selected.num : '--'}}</div>
+            </div>
+            <div class="line2"
+                 v-if="isBaseSpread()">
+              <div>点价合约</div>
+              <div class="right">
+                <div>{{selected.pgoodscode ? selected.pgoodscode : ''}}</div>
+                <div>{{getDeliveryGoodsPrice()}}</div>
+              </div>
+            </div>
+            <div v-if="isBaseSpread()"
+                 class="line3">预估货款:{{getEstimatedPayment()}}</div>
+          </div>
+
+          <a-form-item class="btnCenter mt10">
+            <a-button class="listedBtn"
+                      :loading="loading"
+                      :disabled="loading"
+                      @click="submit">提交</a-button>
+          </a-form-item>
+        </div>
+      </a-form>
+    </div>
+  </Drawer>
+</template>
+
+<script lang="ts">
+import { defineComponent, PropType, ref } from 'vue';
+import Drawer from '@/common/components/drawer/index.vue';
+import { ModalEnum } from '@/common/constants/modalNameEnum';
+import { _closeModal } from '@/common/setup/modal/modal';
+
+import UploadImg from '@/common/components/uploadImg/index.vue';
+import { getSelectedAccountId } from '@/services/bus/account';
+
+import { BuyOrSell } from '@/common/constants/enumCommon';
+import Long from 'long';
+import { QueryTradePositionRsp } from '@/services/go/ermcp/order/interface';
+import { PlusOutlined, MinusOutlined } from '@ant-design/icons-vue';
+import { handleCheck, getTableList, handleCalculation } from './setup';
+import { DeliveryOrder } from '@/services/proto/warehousetrade';
+import { v4 } from 'uuid';
+import moment from 'moment';
+import { DeliveryOrderReq } from '@/services/proto/warehousetrade/interface';
+import { geLoginID_number } from '@/services/bus/login';
+import { message } from 'ant-design-vue';
+import { getGoodsByCode } from '@/services/bus/goods';
+
+export default defineComponent({
+    name: ModalEnum.commodity_contract_summary_settlement,
+    components: { Drawer, UploadImg, PlusOutlined, MinusOutlined },
+    emits: ['cancel', 'update'],
+    props: {
+        selectedRow: {
+            type: Object as PropType<QueryTradePositionRsp>,
+            default: {},
+        },
+        buyOrSell: {
+            type: Number as PropType<BuyOrSell>,
+            default: BuyOrSell.buy,
+        },
+    },
+    setup(props, context) {
+        const { visible, cancel } = _closeModal(context);
+        const loading = ref<boolean>(false);
+        const { goodsid } = props.selectedRow;
+        // 合约交收可点选仓单
+        const { tableList } = getTableList(goodsid);
+        // check 是否选中逻辑
+        const { checked, selected, deliveryGoods, checkGroupChange, isChecked, checkboxChange, isBaseSpread } = handleCheck();
+        // 各种计算
+        const { getStepValue, getCanSettlementNum, getNeedContractNum, getEstimatedPayment, XQty, PQty, getDeliveryGoodsPrice, increase, decrease, selctedNum } = handleCalculation(props.selectedRow);
+
+        const toFixed0 = (value: number) => +value.toFixed(0);
+
+        function submit() {
+            if (!selected.value) {
+                message.warn('请选择合约');
+                return;
+            }
+            if (!selected.value.num) {
+                message.warn('请输入选择数量');
+                return;
+            }
+
+            if (deliveryGoods.value) {
+                loading.value = true;
+                console.log(deliveryGoods.value);
+                const param: DeliveryOrderReq = {
+                    ClientSerialNo: v4(), // 客户端流水号
+                    ClientOrderTime: moment(new Date()).format('YYYY-MM-DD HH:mm:ss'), // 客户端委托时间
+                    ClientType: 4, // 终端类型
+                    // goodsID: props.selectedRow.goodsid,
+                    // market
+                    AccountID: getSelectedAccountId(),
+                    XGoodsID: getGoodsByCode(selected.value.xgoodscode)!.goodsid,
+                    DeliveryGoodsID: deliveryGoods.value.deliverygoodsid,
+                    XQty: Long.fromNumber(XQty()),
+                    PQty: Long.fromNumber(PQty()),
+                    OperateType: 0,
+                    OrderSrc: 0,
+                    OperatorID: Number(geLoginID_number()),
+                    DeliveryQty: selected.value.num,
+                    DeliveryOrderDetail: {
+                        AccountID: selected.value.accountid,
+                        Qty: selected.value.num,
+                        LadingBillID: Long.fromString(selected.value.ladingbillid),
+                        WRFactorTypeID: Long.fromString(selected.value.wrfactortypeid),
+                        SubNum: selected.value.subnum,
+                    },
+                };
+                if (isBaseSpread()) {
+                    param.PGoodsID = deliveryGoods.value.pgoodsid;
+                } else {
+                    // param.PGoodsID = 0;
+                    param.PQty = 0;
+                }
+                console.log('param', param);
+                DeliveryOrder(param)
+                    .then((res) => {
+                        console.log('res', res);
+                        message.success('提交成功');
+                        cancel(true);
+                    })
+                    .catch((err) => {
+                        console.log('err', err);
+                        message.error(err);
+                    })
+                    .finally(() => {
+                        loading.value = false;
+                    });
+            } else {
+                message.warn('未找到对应的交割商品');
+            }
+        }
+        return {
+            visible,
+            cancel,
+            submit,
+            tableList,
+            loading,
+            checkGroupChange,
+            checkboxChange,
+            checked,
+            isChecked,
+            isBaseSpread,
+            getStepValue,
+            getCanSettlementNum,
+            getNeedContractNum,
+            getEstimatedPayment,
+            getDeliveryGoodsPrice,
+            increase,
+            decrease,
+            selctedNum,
+            selected,
+            toFixed0,
+        };
+    },
+});
+</script>
+
+<style lang="less" scoped>
+.c_c_s_s {
+    background: @m-black40;
+    width: 100%;
+    height: 100%;
+    position: relative;
+    .formBar {
+        padding: 0;
+        height: calc(100% - 172px);
+        background: @m-black41;
+        .formtop {
+            width: 100%;
+            padding: 0 20px;
+            .flex;
+            flex-direction: column;
+            .firstTitle {
+                width: calc(100% + 40px);
+                height: 40px;
+                line-height: 40px;
+                margin-left: -20px;
+                padding: 0 20px;
+                font-size: 14px;
+                color: @m-white6;
+                border-bottom: 1px solid @m-black42;
+            }
+            .secondLine {
+                width: 100%;
+                height: 40px;
+                line-height: 40px;
+                display: inline-flex;
+                > div {
+                    flex: 1;
+                    font-size: 14px;
+                    color: @m-grey1;
+                }
+                .left {
+                    text-align: left;
+                }
+                .middle {
+                    text-align: center;
+                }
+                .right {
+                    text-align: right;
+                }
+            }
+            .lineBar {
+                width: 100%;
+                min-height: 100px;
+                padding-left: 15px;
+                padding-right: 10px;
+                background: @m-blue19;
+                margin-bottom: 10px;
+                .rounded-corners(5px);
+                .line1 {
+                    display: inline-flex;
+                    user-select: none;
+                    width: 100%;
+                    height: 40px;
+                    line-height: 40px;
+                    font-size: 16px;
+                    color: @m-white6;
+                    white-space: nowrap;
+                    text-overflow: ellipsis;
+                    overflow: hidden;
+                    border-bottom: 1px solid @m-blue20;
+                    > div {
+                        align-self: center;
+                        align-items: center;
+                    }
+                    .name {
+                        margin-left: 10px;
+                    }
+                }
+                .line2 {
+                    width: 100%;
+                    user-select: none;
+                    padding: 12px 0 14px 0;
+                    display: inline-flex;
+                    > div {
+                        flex: 2;
+                    }
+                    .left {
+                        .flex;
+                        flex-direction: column;
+                        max-width: 40%;
+                        > div {
+                            width: 100%;
+                            height: 17px;
+                            line-height: 17px;
+                            color: @m-white6;
+                            font-size: 14px;
+                            white-space: nowrap;
+                            text-overflow: ellipsis;
+                            overflow: hidden;
+                        }
+                    }
+                    .middle {
+                        flex: 1;
+                        display: inline-flex;
+                        justify-content: space-between;
+                        padding: 0 10px;
+                        font-size: 16px;
+                        color: @m-white6;
+                        line-height: 34px;
+                        > div {
+                            white-space: nowrap;
+                        }
+                    }
+                    .right {
+                        .inputNumberBlock {
+                            float: right;
+                            display: block;
+                            width: 130px;
+                            position: relative;
+                            .anticon {
+                                color: @m-blue15;
+                                font-size: 15px;
+                                z-index: 2;
+                                line-height: 34px;
+                                cursor: pointer;
+                            }
+                            .anticon-minus {
+                                .position(absolute, 0, auto, 0, 10px);
+                            }
+                            .anticon-plus {
+                                .position(absolute, 0, 10px, 0, auto);
+                            }
+                        }
+                        .disabled {
+                            .anticon {
+                                color: @m-grey51;
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+    .fixedBtns {
+        padding-top: 0;
+        left: 0;
+        right: 0;
+    }
+    .formbottom {
+        width: 100%;
+        .flex;
+        flex-direction: column;
+        background: @m-black40;
+        padding: 0 18px 0 20px;
+        .line1 {
+            width: 100%;
+            padding: 0 12px 0 16px;
+            height: 36px;
+            line-height: 36px;
+            display: inline-flex;
+            justify-content: space-between;
+            color: @m-grey1;
+            font-size: 14px;
+        }
+        .line2 {
+            width: 100%;
+            height: 35px;
+            line-height: 34px;
+            padding-left: 15px;
+            padding-right: 10px;
+            background: @m-black43;
+            .rounded-corners(5px);
+            font-size: 14px;
+            color: @m-grey1;
+            display: inline-flex;
+            justify-content: space-between;
+            > div {
+                align-self: baseline;
+                align-items: baseline;
+            }
+            .right {
+                display: inline-flex;
+                color: @m-yellow6;
+                div:last-child {
+                    font-size: 16px;
+                    margin-left: 2px;
+                }
+            }
+        }
+        .line3 {
+            margin-top: 16px;
+            width: 100%;
+            height: 15px;
+            line-height: 15px;
+            font-size: 14px;
+            text-align: right;
+            color: @m-white6;
+        }
+    }
+}
+</style>;

+ 11 - 0
src/views/order/swap_the_order/components/swap_commodity_contract_summary/components/commodity_contract_summary_settlement/interface.ts

@@ -0,0 +1,11 @@
+import { WrDeliveryAvalidHoldLB } from "@/services/go/wrtrade/interface";
+
+export interface FormState {
+    // price: number,
+    num: number,
+}
+
+export interface DBType extends WrDeliveryAvalidHoldLB {
+    checked: boolean;
+    num: number;
+}

+ 209 - 0
src/views/order/swap_the_order/components/swap_commodity_contract_summary/components/commodity_contract_summary_settlement/setup.ts

@@ -0,0 +1,209 @@
+import { handleDeliveryRelation } from "@/common/setup/deliveryRelation";
+import { getSelectedAccountId } from "@/services/bus/account";
+import { getGoodsByCode, getQuoteDayInfoByCode } from "@/services/bus/goods";
+import { QueryDeliveryRelationRsp } from "@/services/go/delivery/interface";
+import { QueryTradePositionRsp } from "@/services/go/ermcp/order/interface";
+import { queryWrDeliveryAvalidHoldLB } from "@/services/go/wrtrade";
+import { QueryWrDeliveryAvalidHoldLBReq } from "@/services/go/wrtrade/interface";
+import { ref } from "vue";
+import { DBType } from "./interface";
+
+// 选中的交收合约
+const selected = ref<DBType>()
+const checked = ref<string>();
+// 交割商品
+const deliveryGoods = ref<QueryDeliveryRelationRsp | undefined>();
+
+// 查询合约交收可点选仓单
+export function getTableList(goodsid: number) {
+    // 交割商品
+    const { getItemDeliveryRelationByGoodsId } = handleDeliveryRelation()
+    const param: QueryWrDeliveryAvalidHoldLBReq = {
+        goodsid,
+        accountid: getSelectedAccountId(),
+    };
+    const tableList = ref<DBType[]>([]);
+    queryWrDeliveryAvalidHoldLB(param).then((res) => {
+        tableList.value = res.map((e, i) => {
+            if (i) {
+                return { ...e, checked: false, num: 0 };
+            } else {
+                // 默认勾选第一个
+                checked.value = e.ladingbillid
+                const result = { ...e, checked: true, num: 0 };
+                selected.value = result
+                deliveryGoods.value = getItemDeliveryRelationByGoodsId(e.goodsid).value
+                return result
+            }
+        });
+    });
+    return { tableList }
+}
+
+
+
+export function handleCheck() {
+    // 交割商品
+    const { getItemDeliveryRelationByGoodsId } = handleDeliveryRelation()
+
+    function checkGroupChange(checkedValue: string[]) {
+        checked.value = checkedValue[checkedValue.length - 1];
+    }
+    function isChecked(value: string) {
+        return value === checked.value;
+    }
+    function checkboxChange(item: DBType) {
+        selected.value = item;
+        deliveryGoods.value = getItemDeliveryRelationByGoodsId(item.goodsid).value
+    }
+    // true 基差点价; false 挂牌点选
+    function isBaseSpread() {
+        if (deliveryGoods.value) {
+            // 1和3是订单交易 挂牌转让
+            // 2和4是基差点价
+            const arr = [2, 4]
+            return arr.includes(deliveryGoods.value.deliverytype)
+        } else {
+            return false
+        }
+    }
+    return { checked, selected, deliveryGoods, checkGroupChange, isChecked, checkboxChange, isBaseSpread }
+}
+
+export function handleCalculation(selectedRow: QueryTradePositionRsp) {
+    // 商品合约单位
+    const { enableqty } = selectedRow
+    function getDecimalplace() {
+        let result = 2;
+        const goods = selected.value?.pgoodscode
+        if (goods) {
+            const item = getGoodsByCode(goods)
+            item && (result = item.decimalplace)
+        }
+        return result
+    }
+    function getAgreeunit(goodscode: string) {
+        let result = 1
+        // const goodscode = selectedRow.goodscode
+        // if (goodscode) {
+        const item = getGoodsByCode(goodscode)
+        if (item) {
+            result = item.agreeunit
+        }
+        // }
+        return result
+    }
+
+
+    function selctedNum() {
+        return selected.value ? selected.value.num.toFixed(0) : '--'
+    }
+    // 选中数量的 最小变动值 = 合约单位 * 最小交割系数 * 仓单商品的单位r2
+    function getStepValue() {
+        const agreeunit = getAgreeunit(selectedRow.goodscode)
+        if (deliveryGoods.value) {
+            const { rratio2, mindeliveryqty } = deliveryGoods.value
+            return agreeunit * mindeliveryqty * rratio2
+        } else {
+            return agreeunit
+        }
+    }
+    // 可交收数量 = 合约可用手数 * 合约单位 * 最小交割系数 * (仓单商品的单位r2/合约商品的单位r1)
+    function getCanSettlementNum() {
+        if (deliveryGoods.value) {
+            const agreeunit = getAgreeunit(selectedRow.goodscode)
+            const { rratio1, rratio2, mindeliveryqty } = deliveryGoods.value
+            const result = enableqty * agreeunit * mindeliveryqty * (rratio2 / rratio1)
+            return result.toFixed(0)
+        } else {
+            return '--'
+        }
+    }
+    // (选中的数量 / (合约单位 * 最小交割系数 * (仓单商品的单位r2/合约商品的单位r1)))
+    function XQty() {
+        let result = 0
+        if (selected.value?.num) {
+            if (deliveryGoods.value) {
+                const agreeunit = getAgreeunit(selectedRow.goodscode)
+                const { rratio1, rratio2, mindeliveryqty, xdeliveryratio, pdeliveryratio } = deliveryGoods.value
+                result = selected.value.num / (agreeunit * mindeliveryqty * (rratio2 / rratio1))
+            }
+        }
+        return result
+    }
+    // 需要合约手数 = (选中的数量 / (合约单位 * 最小交割系数 * (仓单商品的单位r2/合约商品的单位r1))) / (p1合约系数 / x合约系数)
+    function PQty() {
+        let result = XQty()
+        if (result) {
+            if (deliveryGoods.value) {
+                const { xdeliveryratio, pdeliveryratio } = deliveryGoods.value
+                result = result / pdeliveryratio / xdeliveryratio
+            }
+        }
+        return result
+    }
+    // 需要合约手数 = (选中的数量 / (合约单位 * 最小交割系数 * (仓单商品的单位r2/合约商品的单位r1))) / (p1合约系数 / x合约系数)
+    function getNeedContractNum() {
+        const result = PQty()
+        return result ? result.toFixed(0) : '--'
+    }
+    // 预估货款 = 需要合约手数  * 合约交割价 * 合约单位 + 升贴水
+    function getEstimatedPayment() {
+        const num = getNeedContractNum()
+        const price = getDeliveryGoodsPrice()
+        let result = 0
+        if (selected.value) {
+            if (num !== '--' && price !== '--') {
+                if (deliveryGoods.value) {
+                    const agreeunit = getAgreeunit(selected.value.pgoodscode)
+                    result = (Number(num) * Number(price) * agreeunit) + (selected.value.pricemove * selected.value.num)
+                }
+            }
+        }
+        return result ? result.toFixed(getDecimalplace()) : '--'
+    }
+    /**
+     * 合约交割价取价规则
+     * 1.优先实时结算价
+     * 2.其次卖一价
+     * 3.再次是买一价与成交价中的最高价
+     * 4.最后取昨日结算价
+     * 所有权(X): 不取交割价,默认设为0,不影响交割流程
+     */
+    function getDeliveryGoodsPrice() {
+        const goodscode = selected.value?.pgoodscode
+        if (!goodscode) return '--'
+        const item = getQuoteDayInfoByCode(goodscode);
+        const has = (value: any) => value && value !== '--'
+        let result = 0
+        if (item) {
+            const { settle, ask, bid, last, presettle } = item
+            if (has(settle)) {
+                result = settle
+            } else if (has(ask)) {
+                result = ask
+            } else if (has(bid) && has(last)) {
+                result = Math.max(bid, last)
+            } else if (has(presettle)) {
+                result = presettle
+            }
+        }
+        return has(result) ? result.toFixed(getDecimalplace()) : '--'
+    }
+
+    // 增加
+    function increase(value: DBType) {
+        if (value.num < value.avalidqty) {
+            value.num += getStepValue()
+            value.num = +value.num.toFixed(getDecimalplace())
+        }
+    }
+    // 减少
+    function decrease(value: DBType) {
+        if (value.num > 0) {
+            value.num -= getStepValue()
+            value.num = +value.num.toFixed(getDecimalplace())
+        }
+    }
+    return { getStepValue, getCanSettlementNum, getNeedContractNum, getEstimatedPayment, XQty, PQty, getDeliveryGoodsPrice, increase, decrease, selctedNum }
+}

+ 200 - 0
src/views/order/swap_the_order/components/swap_commodity_contract_summary/components/commodity_contract_summary_transfer/index.vue

@@ -0,0 +1,200 @@
+<template>
+  <!-- 转让-->
+  <Drawer :title="'转让'"
+          :placement="'right'"
+          :visible="visible"
+          class="delistingBottom"
+          @cancel="cancel">
+    <div class="listed">
+      <a-form class="inlineForm dialogForm"
+              ref="formRef"
+              :model="formState"
+              :rules="rules">
+        <div class="formBar">
+          <a-row :gutter="24">
+            <a-col :span="12">
+              <a-form-item label="合约"
+                           name="goodsid">
+                <a-select class="inlineFormSelect"
+                          :default-value="selectedRow.goodsid"
+                          v-model:value="formState.goodsid"
+                          style="width: 100%">
+                  <a-select-option v-for="item in tableList"
+                                   :value="item.goodsid"
+                                   :key="item.goodsid">{{item.goodsname}}
+                  </a-select-option>
+                </a-select>
+              </a-form-item>
+            </a-col>
+            <a-col :span="12">
+              <a-form-item label="挂牌价"
+                           name="price">
+                <a-input-number class="commonInput"
+                                v-model:value="formState.price"
+                                style="width: 100%" />
+              </a-form-item>
+            </a-col>
+            <a-col :span="12">
+              <a-form-item label="挂牌数量"
+                           name="num">
+                <a-input-number class="commonInput"
+                                :max="getMax()"
+                                v-model:value="formState.num"
+                                style="width: 100%" />
+                <span class="input-enumdicname">{{selectedRow.enumdicname}}</span>
+              </a-form-item>
+            </a-col>
+            <a-col :span="12">
+              <a-form-item label="挂牌金额">
+                <a-input class="commonInput"
+                         :value="getMoney()"
+                         style="width: 100%" />
+              </a-form-item>
+            </a-col>
+            <a-col :span="24"
+                   class="mt-20">
+              <a-form-item>
+                <a-slider :min="0"
+                          v-model:value="formState.num"
+                          :max="getMax()"
+                          class="formSlider"
+                          style="width: 180px" />
+                <div class="unit">
+                  <span>0</span>
+                  <span>{{getMax()}}{{selectedRow.enumdicname}}</span>
+                </div>
+              </a-form-item>
+            </a-col>
+          </a-row>
+        </div>
+        <a-row :gutter="24">
+          <a-col :span="24"
+                 class="fixedBtns">
+            <a-form-item class="btnCenter">
+              <a-button class="listedBtn"
+                        :loading="loading"
+                        :disabled="loading"
+                        @click="submit">提交</a-button>
+            </a-form-item>
+          </a-col>
+        </a-row>
+      </a-form>
+    </div>
+  </Drawer>
+</template>
+
+<script lang="ts">
+import { defineComponent, PropType, ref } from 'vue';
+import Drawer from '@/common/components/drawer/index.vue';
+import { WrPerformancePlan, WrPosition } from '@/services/go/wrtrade/interface';
+import { ModalEnum } from '@/common/constants/modalNameEnum';
+import { _closeModal } from '@/common/setup/modal/modal';
+import { handleForm } from './setup';
+import { validateAction } from '@/common/setup/form';
+import { FormState } from './interface';
+import UploadImg from '@/common/components/uploadImg/index.vue';
+import { getUploadImg } from '@/common/setup/upload';
+import { PerformanceContractedApplyReq, PerformanceDelayApplyReq } from '@/services/proto/performance/interface';
+import { getSelectedAccount, getSelectedAccountId, getUserId } from '@/services/bus/account';
+import { requestResultLoadingAndInfo } from '@/common/methods/request/resultInfo';
+import { performanceContractedApply, performanceDelayApply } from '@/services/proto/performance';
+import { BuyOrSell, DelistingType, PriceType } from '@/common/constants/enumCommon';
+import Long from 'long';
+import { OrderReq } from '@/services/socket/order/interface';
+import { v4 as uuidv4 } from 'uuid';
+import moment from 'moment';
+import { geLoginID_number } from '@/services/bus/login';
+import { LongType } from '@/services/socket/login/interface';
+import { Order } from '@/services/socket/order';
+import { QueryTradePositionRsp } from '@/services/go/ermcp/order/interface';
+
+export default defineComponent({
+    name: ModalEnum.commodity_contract_summary_transfer,
+    components: { Drawer, UploadImg },
+    emits: ['cancel', 'update'],
+    props: {
+        selectedRow: {
+            type: Object as PropType<QueryTradePositionRsp>,
+            default: {},
+        },
+        tableList: {
+            type: Array as PropType<QueryTradePositionRsp[]>,
+            default: [],
+        },
+    },
+    setup(props, context) {
+        const { visible, cancel } = _closeModal(context);
+        const loading = ref<boolean>(false);
+        const { rules, formState, formRef } = handleForm();
+        formState.goodsid = props.selectedRow.goodsid;
+        function getSelectedGoods() {
+            return props.tableList.find((e) => e.goodsid === formState.goodsid)!;
+        }
+        function getMax() {
+            return getSelectedGoods().enableqty;
+        }
+        function getMoney() {
+            return (formState.price * formState.num).toFixed(getSelectedGoods().decimalplace);
+        }
+        function submit() {
+            // 挂牌请求 通过合约汇总 挂牌转让
+            validateAction<FormState>(formRef, formState).then((res) => {
+                const param: OrderReq = {
+                    ClientSerialNo: uuidv4(), // 客户端流水号
+                    ClientOrderTime: moment(new Date()).format('YYYY-MM-DD HH:mm:ss'), // 客户端委托时间
+                    ClientType: 4, // 终端类型
+                    LoginID: geLoginID_number()!, // 登陆账号
+                    AccountID: getSelectedAccountId(), // 交易账号
+                    GoodsID: res.goodsid, // 商品ID
+                    MarketID: getSelectedGoods().marketid, // 市场ID
+                    ValidType: 1, // 校验类型 当日有效
+                    OperateType: 1, // 操作类型: 申请
+                    OrderSrc: 1, // 单据来源: 客户端下单
+                    OrderPrice: res.price, // 委托价格                      (需要填入)
+                    OperatorID: Number(geLoginID_number()),
+                    // MarketMaxSub: number // 市价允许最大偏差(做市)
+                    OrderQty: res.num, // 委托数量                          (需要填入)
+                    BuyOrSell: 1, // 买卖方向  0 买 1 卖
+                    BuildType: 2, // 下单类型  1 建 2 平
+                    // CurtQuotePrice: 0, // 保留,计算冻结金额使用
+                    // SpPrice: 0 ,// 止盈价格
+                    // SlPrice: 0 , // 止损价格
+                    PriceMode: PriceType.limit, // 取价方式
+                    TimevalidType: 1, // 时间有效类型 单日有效
+                    TriggerType: 1, // 预埋单触发类型
+                    // TriggerPrice: number // 预埋单触发价格
+                    ListingSelectType: 1, // 挂牌点选类型 1:挂牌 2:摘牌 3:先摘后挂
+                    DelistingType: DelistingType.selected, // 摘牌类型 2:点选成交
+                    // RelatedID: number // 关联单号
+                    OptionType: 1, // 期权类型(1:认购(看涨)2:认沽(看跌))
+                    // Premium: number // 权利金
+                    // TriggerOperator: number // 触发条件(1:大于等于2:小于等于)
+                    // ServiceTime: string // 服务端时间
+                    // CouponTypeID: number // 优惠券类型ID(买方)
+                    // UsedQty: number // 使用数量
+                    // ValidTime: string // 指定有效日期
+                    // ReceiveInfoID: number // 收货地址ID
+                    OrderFlag: 1,
+                };
+                requestResultLoadingAndInfo(Order, param, loading, ['挂牌成功', '挂牌失败:']).then(() => {
+                    cancel(true);
+                });
+            });
+        }
+        return {
+            visible,
+            cancel,
+            submit,
+            loading,
+            rules,
+            formState,
+            formRef,
+            getMoney,
+            getMax,
+        };
+    },
+});
+</script>
+
+<style lang="less" scoped>
+</style>;

+ 5 - 0
src/views/order/swap_the_order/components/swap_commodity_contract_summary/components/commodity_contract_summary_transfer/interface.ts

@@ -0,0 +1,5 @@
+export interface FormState {
+    price: number,
+    num: number,
+    goodsid: number,
+}

+ 26 - 0
src/views/order/swap_the_order/components/swap_commodity_contract_summary/components/commodity_contract_summary_transfer/setup.ts

@@ -0,0 +1,26 @@
+import { validateCommon } from "@/common/setup/validate";
+import { RuleObject } from "ant-design-vue/lib/form/interface";
+import { reactive, ref, UnwrapRef } from "vue";
+import { FormState } from "./interface";
+
+export function handleForm() {
+    const formRef = ref();
+    const formState: UnwrapRef<FormState> = reactive({
+        price: 0,
+        num: 0,
+        goodsid: 0,
+    })
+    const v_num = async (rule: RuleObject, value: number) => {
+        return validateCommon(value, '请输入挂牌价');
+    };
+    const rules = {
+        price: [
+            { require, trigger: 'blur', type: 'number', validator: v_num },
+        ],
+        num: [
+            { require, message: '请输入挂牌数量', trigger: 'blur', type: 'number' },
+            { message: '挂牌数量小于1', min: 1, type: 'number' }
+        ],
+    }
+    return { rules, formState, formRef }
+}

+ 31 - 0
src/views/order/swap_the_order/components/swap_commodity_contract_summary/components/setup.ts

@@ -0,0 +1,31 @@
+import { BuyOrSell } from "@/common/constants/enumCommon";
+import { getQuoteDayInfoByCodeFindPrice } from "@/services/bus/goods";
+import { ref } from "vue";
+import { BargainList } from "./commodity_contract_summary_deal_closed/interface";
+
+// 计算盈亏
+// 浮动盈亏	持仓单:
+// 收益权=(最新价-持仓价)*持仓数量*合约单位*方向(买[1]:卖[-1])(*汇率)
+// 所有权=(最新价*持仓数量*合约单位(*汇率) - 持仓金额)
+export function useProfit(item: BargainList, goodcode: string) {
+    // 最新价
+    const lastPrice = getQuoteDayInfoByCodeFindPrice(goodcode);
+    if (lastPrice && lastPrice !== '--') {
+        const { holderprice, holderqty, agreeunit, decimalplace, buyorsell } = item
+        const temp = buyorsell === BuyOrSell.buy ? 1 : -1
+        return ((+lastPrice - holderprice) * holderqty * agreeunit * temp).toFixed(decimalplace)
+    } else {
+        return lastPrice
+    }
+}
+export function useCheckd() {
+    const checked = ref<string>();
+    const selected = ref<BargainList>()
+    function checkGroupChange(checkedValue: string[]) {
+        checked.value = checkedValue[checkedValue.length - 1];
+    }
+    function checkboxChange(item: BargainList) {
+        selected.value = item;
+    }
+    return { checked, selected, checkGroupChange, checkboxChange }
+}

+ 168 - 0
src/views/order/swap_the_order/components/swap_commodity_contract_summary/index.vue

@@ -0,0 +1,168 @@
+<template>
+  <!-- 商品订单 - 合约汇总 -->
+  <section>
+    <a-table :columns="tabColumns"
+             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="handleBtnList(record,btnList)"
+                 :record="record"
+                 class="btn-list-sticky"
+                 @click="openComponent" />
+      </template>
+      <template #createtime="{ record }">
+        <a>{{ formatTime(record.createtime) }}</a>
+      </template>
+      <!-- 现价 -->
+      <template #lastprice="{ record }">
+        <a>{{ getLastprice(record) }}</a>
+      </template>
+      <!-- 均价 -->
+      <template #averageprice="{ text }">
+        <a>{{ handleNoneValue(text)}}</a>
+      </template>
+      <!-- 持仓盈亏 -->
+      <template #profitloss="{ record }">
+        <span>{{ record.averageprice ? useProfitloss(record) : '--' }}</span>
+      </template>
+      <template #buyorsell="{ record }">
+        <span>{{ getBuyOrSellName(record.buyorsell) }}</span>
+      </template>
+      <template #marketamount="{ record, text }">
+        <span>{{ isDiaoQi(record) ? '--' : text }}</span>
+      </template>
+    </a-table>
+    <component :is="componentId"
+               v-if="componentId"
+               :selectedRow="selectedRow"
+               :tableList="tableList"
+               :swapList="swapList"
+               @cancel="closeComponent"></component>
+  </section>
+</template>
+
+<script lang="ts">
+import { BtnListType } from '@/common/components/btnList/interface';
+import { TradeMode } from '@/common/constants/enumCommon';
+import { enumOrderComponents } from '@/common/constants/enumOrderComponents';
+import { BtnList, defineAsyncComponent, defineComponent, ModalEnum, queryTableList } from '@/common/export/commonTable';
+import { formatTime } from '@/common/methods';
+import { handleDeliveryRelation } from '@/common/setup/deliveryRelation';
+import { getRecordItemTab } from '@/common/setup/order/orderData';
+import { expandIcon } from '@/common/setup/table/clolumn';
+import { handleComposeOrderTable } from '@/common/setup/table/compose';
+import { ComposeOrderTableParam } from '@/common/setup/table/interface';
+import { handleSubcriteQuote } from '@/common/setup/table/tableQuote';
+import { findGoodsTradeModeById, getQuoteDayInfoByCodeFindPrice, getQutoGoodsByTradeMode } from '@/services/bus/goods';
+import { useHolderprice, useProfitloss } from '@/services/bus/holdPosition';
+import { queryTradePosition } from '@/services/go/ermcp/order';
+import { QueryTradePositionRsp } from '@/services/go/ermcp/order/interface';
+import { getBuyOrSellName, getChannelBuildName } from '@/common/constants/enumsName';
+import { isInvestment } from '@/views/market/spot_trade/spot_trade_order_transaction/spot_trade_order_transaction_swap/components/setup';
+import { useIsDiaoQi, findGoodsCode } from './setup';
+// import { getSwapList } from '@/views/market/spot_trade/spot_trade_order_transaction/spot_trade_order_transaction_swap/setup';
+import { ref } from 'vue';
+import { QueryQuoteGoodsListRsp } from '@/services/go/Tjmd/interface';
+import Bus from '@/utils/eventBus/index';
+import { tabColumns, getSwapList } from './setup';
+import { handleNoneValue } from '@/common/setup/table/tableQuote';
+
+export default defineComponent({
+    name: enumOrderComponents.commodity_contract_summary,
+    components: {
+        BtnList,
+        [ModalEnum.commodity_contract_summary_settlement]: defineAsyncComponent(() => import('./components/commodity_contract_summary_settlement/index.vue')),
+        [ModalEnum.commodity_contract_summary_transfer]: defineAsyncComponent(() => import('./components/commodity_contract_summary_transfer/index.vue')),
+        commodity_contract_summary_deal_closed: defineAsyncComponent(() => import('./components/commodity_contract_summary_deal_closed/index.vue')),
+        commodity_contract_summary_order_closed: defineAsyncComponent(() => import('./components/commodity_contract_summary_order_closed/index.vue')),
+    },
+    setup() {
+        // 表格列表数据
+        const { loading, tableList, queryTable } = queryTableList<QueryTradePositionRsp>();
+        const { subscribeAction } = handleSubcriteQuote();
+        // 交割商品
+        handleDeliveryRelation();
+        const swapList = ref<QueryQuoteGoodsListRsp[]>([]);
+        // 挂牌点选商品
+        //         const { deliverGoods, getQuoteList, goodsList, } = handleDeliveryRelation([1, 3]);
+        //         // 参考行情商品
+        // const goodsList = getQutoGoodsByTradeMode(TradeMode.quote99);
+
+        // 获取列表数据
+        const queryTableAction = () => {
+            Promise.all([queryTable(queryTradePosition), getSwapList()]).then((res) => {
+                swapList.value = res[1];
+                tableList.value = res[0];
+                const goodsSet = new Set<string>();
+                res[0].forEach((el) => {
+                    // 商品掉期取参考行情最新价,挂牌点选取自己行情的最新价
+                    const goodscode = findGoodsCode(el.goodsid, el.goodscode, swapList.value);
+                    if (goodscode) {
+                        goodsSet.add(goodscode);
+                    }
+                });
+                //  行情订阅
+                subscribeAction([...goodsSet]);
+            });
+        };
+        Bus.$on('spotTrade', queryTableAction);
+        // 表格通用逻辑
+        const param: ComposeOrderTableParam = {
+            queryFn: queryTableAction,
+            tableName: 'table_pcweb_spot_trade_bottom_commodity_contract_summary',
+            recordList: getRecordItemTab(),
+        };
+        // 现价
+        function getLastprice(record: QueryTradePositionRsp) {
+            let result: number | string = '--';
+            const goodscode = findGoodsCode(record.goodsid, record.goodscode, swapList.value);
+            if (goodscode) {
+                result = getQuoteDayInfoByCodeFindPrice(goodscode);
+            }
+            return result;
+        }
+        function isDiaoQi(record: QueryTradePositionRsp) {
+            return findGoodsTradeModeById(record.goodsid) === TradeMode.DiaoQi;
+        }
+        function handleBtnList(record: QueryTradePositionRsp, btnList: BtnListType[]) {
+            // 挂牌点选
+            const listing = ['commodity_contract_summary_transfer', 'commodity_contract_summary_settlement'];
+            // 贸易圈
+            // 只有机构 才有平仓
+            const diaoqi = isInvestment() ? ['commodity_contract_summary_deal_closed', 'commodity_contract_summary_order_closed'] : ['commodity_contract_summary_deal_closed'];
+            const arr = isDiaoQi(record) ? diaoqi : listing;
+            return btnList.filter((e) => arr.includes(e.code));
+        }
+        return {
+            ...handleComposeOrderTable<QueryTradePositionRsp>(param),
+            loading,
+            tableList,
+            formatTime,
+            expandIcon,
+            getLastprice,
+            useHolderprice,
+            useProfitloss,
+            handleBtnList,
+            tabColumns,
+            getBuyOrSellName,
+            swapList,
+            findGoodsCode,
+            isDiaoQi,
+            handleNoneValue,
+        };
+    },
+});
+</script>
+
+<style lang="less">
+</style>;

+ 146 - 0
src/views/order/swap_the_order/components/swap_commodity_contract_summary/setup.ts

@@ -0,0 +1,146 @@
+// 获取最新价
+
+import { TradeMode } from "@/common/constants/enumCommon";
+import { queryTableList } from "@/common/setup/table";
+import { findGoodsTradeModeById } from "@/services/bus/goods";
+import { getMarketIdsByTradeMode } from "@/services/bus/market";
+import { getUserAccountType } from "@/services/bus/user";
+import { queryQuoteGoodsList } from "@/services/go/Tjmd";
+import { QueryQuoteGoodsListReq, QueryQuoteGoodsListRsp } from "@/services/go/Tjmd/interface";
+
+export const useIsDiaoQi = (goodsid: number) => {
+    return findGoodsTradeModeById(goodsid) === TradeMode.DiaoQi
+}
+
+
+// 商品掉期取参考行情最新价,挂牌点选取自己行情的最新价
+export function findGoodsCode(goodsid: number, goodscode: string, swapList: QueryQuoteGoodsListRsp[]) {
+    const result = useIsDiaoQi(goodsid) ? swapList.find((el) => goodsid === goodsid)?.refgoodscode : goodscode;
+    return result ? result : ''
+}
+
+export function getSwapList() {
+    const { loading, queryTable } = queryTableList<QueryQuoteGoodsListRsp>();
+    // 组装 参数
+    const marketids = getMarketIdsByTradeMode(TradeMode.DiaoQi)
+    const param: QueryQuoteGoodsListReq = {
+        usertype: getUserAccountType(),
+    }
+    if (marketids) {
+        param.marketids = marketids
+    }
+    return queryTable(queryQuoteGoodsList, param)
+}
+
+export const tabColumns = [
+    {
+        key: '10th',
+        dataIndex: 'goodsname',
+        title: '订单合约',
+        align: 'center',
+        slots: {
+            customRender: 'goodsname',
+        },
+        width: 120,
+    },
+    {
+        key: '7th',
+        dataIndex: 'buyorsell',
+        title: '方向',
+        align: 'center',
+        slots: {
+            customRender: 'buyorsell',
+        },
+        width: 120,
+    },
+    {
+        key: '8th',
+        dataIndex: 'curpositionqty',
+        title: '持有数量',
+        align: 'center',
+        slots: {
+            customRender: 'curpositionqty',
+        },
+        width: 120,
+    },
+    {
+        key: '9th',
+        dataIndex: 'enableqty',
+        title: '可用数量',
+        align: 'center',
+        slots: {
+            customRender: 'enableqty',
+        },
+        width: 120,
+    },
+    {
+        key: '0th',
+        dataIndex: 'frozenqty',
+        title: '冻结数量',
+        align: 'center',
+        slots: {
+            customRender: 'frozenqty',
+        },
+        width: 120,
+    },
+    {
+        key: '1th',
+        dataIndex: 'averageprice',
+        title: '均价',
+        align: 'center',
+        slots: {
+            customRender: 'averageprice',
+        },
+        width: 120,
+    },
+    {
+        key: '2th',
+        dataIndex: 'lastprice',
+        title: '现价',
+        align: 'center',
+        slots: {
+            customRender: 'lastprice',
+        },
+        width: 120,
+    },
+    {
+        key: '3th',
+        dataIndex: 'curholderamount',
+        title: '持仓金额',
+        align: 'center',
+        slots: {
+            customRender: 'curholderamount',
+        },
+        width: 120,
+    },
+    // {
+    //     key: '4th',
+    //     dataIndex: 'usedmargin',
+    //     title: '占用保证金',
+    //     align: 'center',
+    //     slots: {
+    //         customRender: 'usedmargin',
+    //     },
+    //     width: 130,
+    // },
+    {
+        key: '5th',
+        dataIndex: 'marketamount',
+        title: '市值',
+        align: 'center',
+        slots: {
+            customRender: 'marketamount',
+        },
+        width: 120,
+    },
+    {
+        key: '6th',
+        dataIndex: 'profitloss',
+        title: '浮动盈亏',
+        align: 'center',
+        slots: {
+            customRender: 'profitloss',
+        },
+        width: 120,
+    },
+];

+ 62 - 0
src/views/order/swap_the_order/index.vue

@@ -0,0 +1,62 @@
+<template>
+  <!-- 掉期订单 -->
+  <section class="spot_warran">
+    <component :is="componentId"
+               v-if="componentId"></component>
+    <thirdMenu :list="tabList"
+               @selectMenu="changeTab"
+               :value="'title'">
+      <!-- 议价单 -->
+      <div class="goods-apply"
+           v-if="componentId === BARGIN">
+        <!-- <span @click="changeBargain(ApplyType.my)">我的议价</span>
+                <span @click="changeBargain(ApplyType.counterpart)">对方议价</span>-->
+        <a-radio-group class="conditionCommonRadioGroup"
+                       v-model:value="bargainValue">
+          <a-radio @focus="changeBargain(ApplyType.my)"
+                   :value="ApplyType.my">我的申请</a-radio>
+          <a-radio @focus="changeBargain(ApplyType.counterpart)"
+                   :value="ApplyType.counterpart">对方申请</a-radio>
+        </a-radio-group>
+      </div>
+    </thirdMenu>
+  </section>
+</template>
+
+<script lang="ts">
+import { defineAsyncComponent, defineComponent, ref } from 'vue';
+import { enumOrderComponents } from '@/common/constants/enumOrderComponents';
+import thirdMenu from '@/common/components/thirdMenu/index.vue';
+import { handleOrderDetailList } from '@/common/setup/order/orderData';
+import Bus from '@/utils/eventBus/index';
+import { ApplyType } from '@/common/constants/enumCommon';
+
+const BARGIN = 'swap_commodity_contract_bargain';
+
+export default defineComponent({
+    name: enumOrderComponents.swap_the_order,
+    components: {
+        thirdMenu,
+        swap_commodity_contract_summary: defineAsyncComponent(() => import('./components/swap_commodity_contract_summary/index.vue')), // 合约汇总
+        swap_commodity_contract_commission: defineAsyncComponent(() => import('./components/swap_commodity_contract_commission/index.vue')), // 委托
+        swap_commodity_contract_make_deal: defineAsyncComponent(() => import('./components/swap_commodity_contract_make_deal/index.vue')), // 成交
+        [BARGIN]: defineAsyncComponent(() => import('./components/swap_commodity_contract_bargain/index.vue')), // 议价单
+    },
+    setup() {
+        // 切换 我的
+        function changeBargain(value: ApplyType) {
+            Bus.$emit('bargain', value);
+        }
+        const bargainValue = ref<ApplyType>(ApplyType.my);
+        return { ...handleOrderDetailList(enumOrderComponents.swap_the_order), changeBargain, BARGIN, ApplyType, bargainValue };
+    },
+});
+</script>
+
+<style lang="less">
+.goods-apply {
+    position: absolute;
+    bottom: 2px;
+    right: 20px;
+}
+</style>;