소스 검색

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

marymelisa 4 년 전
부모
커밋
63175341c0
19개의 변경된 파일1264개의 추가작업 그리고 194개의 파일을 삭제
  1. 10 1
      src/services/proto/warehousetrade/index.ts
  2. 10 0
      src/services/proto/warehousetrade/interface.ts
  3. 44 41
      src/views/market/spot_trade/warehouse_pre_sale/warehouse_pre_sale_blocs/components/buy/index.vue
  4. 473 0
      src/views/market/spot_trade/warehouse_pre_sale/warehouse_pre_sale_blocs/components/delisting/index.vue
  5. 12 0
      src/views/market/spot_trade/warehouse_pre_sale/warehouse_pre_sale_blocs/components/delisting/interface.ts
  6. 47 0
      src/views/market/spot_trade/warehouse_pre_sale/warehouse_pre_sale_blocs/components/delisting/setup.ts
  7. 0 0
      src/views/market/spot_trade/warehouse_pre_sale/warehouse_pre_sale_blocs/components/detail/index.vue
  8. 116 0
      src/views/market/spot_trade/warehouse_pre_sale/warehouse_pre_sale_blocs/components/post-buying/addPermance.vue
  9. 155 0
      src/views/market/spot_trade/warehouse_pre_sale/warehouse_pre_sale_blocs/components/post-buying/friend.vue
  10. 32 19
      src/views/market/spot_trade/warehouse_pre_sale/warehouse_pre_sale_blocs/components/post-buying/index.vue
  11. 3 1
      src/views/market/spot_trade/warehouse_pre_sale/warehouse_pre_sale_blocs/components/post-buying/interface.ts
  12. 139 0
      src/views/market/spot_trade/warehouse_pre_sale/warehouse_pre_sale_blocs/components/post-buying/permancePlanTmp.vue
  13. 38 4
      src/views/market/spot_trade/warehouse_pre_sale/warehouse_pre_sale_blocs/components/post-buying/setup.ts
  14. 44 41
      src/views/market/spot_trade/warehouse_pre_sale/warehouse_pre_sale_blocs/components/sell/index.vue
  15. 133 84
      src/views/market/spot_trade/warehouse_receipt_trade/warehouse_receipt_trade_blocs/components/delisting/index.vue
  16. 1 0
      src/views/market/spot_trade/warehouse_receipt_trade/warehouse_receipt_trade_blocs/components/delisting/interface.ts
  17. 6 2
      src/views/market/spot_trade/warehouse_receipt_trade/warehouse_receipt_trade_blocs/components/delisting/setup.ts
  18. 0 0
      src/views/market/spot_trade/warehouse_receipt_trade/warehouse_receipt_trade_blocs/components/detail/index.vue
  19. 1 1
      src/views/market/spot_trade/warehouse_receipt_trade/warehouse_receipt_trade_blocs/components/sell/index.vue

+ 10 - 1
src/services/proto/warehousetrade/index.ts

@@ -1,7 +1,7 @@
 import {
     DeliveryOrderReq,
     HdWRDealOrderReq,
-    HdWROrderReq, PaymentArrearsReq, WarehouseRepurchaseReq, WRListingCancelOrderReq, WROutApplyCancelReq,
+    HdWROrderReq, PaymentArrearsReq, WarehouseRepurchaseReq, WrBargainApplyReq, WRListingCancelOrderReq, WROutApplyCancelReq,
     WROutApplyReq, WROutCancelReq, WROutConfirmReq, WRTradeFinanceBuyCancelReq
 } from "@/services/proto/warehousetrade/interface";
 import { protoMiddleware } from "@/services/socket/protobuf/buildReq";
@@ -25,6 +25,15 @@ export const hdWROrder = (param: HdWROrderReq): Promise<any> => {
 export const HdWRDealOrder = (param: HdWRDealOrderReq): Promise<any> => {
     return protoMiddleware<HdWRDealOrderReq>(param, 'HdWRDealOrderReq', 'HdWRDealOrderRsp', HeadEnum.tradeMode17)
 }
+/**
+ * 议价摘牌请求
+ *
+ * @param param
+ * @constructor
+ */
+export const wrBargainApply = (param: WrBargainApplyReq): Promise<any> => {
+    return protoMiddleware<WrBargainApplyReq>(param, 'HdWRDealOrderReq', 'HdWRDealOrderRsp', HeadEnum.tradeMode17)
+}
 
 /**
  * 出入库请求

+ 10 - 0
src/services/proto/warehousetrade/interface.ts

@@ -75,6 +75,16 @@ export interface HdWRDealOrderReq {
     ProductDetailID: number; // uint64 金融机构产品组合ID(融资购买时有效)
 
 }
+
+export interface WrBargainApplyReq {
+    WRTradeOrderID: number; // 关联委托单ID
+    ApplyQty: number; // 摘牌数量
+    UserID: string; //摘牌人用户ID
+    AccountID: string; //摘牌资金账号
+    BuyOrSell: string; //摘牌方向
+    ApplyPrice: string; //申请价格
+    ApplyRemark: string; //申请备注
+}
 // 持仓单摘牌应答 0 22 18
 export interface HdWRDealOrderRsp {
     RetCode: number; // int32 返回码

+ 44 - 41
src/views/market/spot_trade/warehouse_pre_sale/warehouse_pre_sale_blocs/components/buy/index.vue

@@ -1,43 +1,42 @@
 <template>
-    <!-- 仓单贸易 贸易圈挂牌 卖-->
-    <div>
-        <a-table
-            :columns="columns"
-            :class="['srcollYTable', isBottom ? 'condSecondTabTableHalfTop' : 'condSecondTabTableHalfTopNoBottom', 'halfBottom']"
-            :scroll="{ x: '100%', y: isBottom ? 'calc((100vh- 443px)/2 - 14px)' : 'calc((100vh - 196px)/2 - 16px)' }"
-            :pagination="false"
-            :loading="loading"
-            :expandedRowKeys="expandedRowKeys"
-            :customRow="Rowclick"
-            rowKey="key"
-            :data-source="tableList"
-        >
-            <template #index="{ index }">
-                <span>{{ index + 1 }}</span>
-            </template>
-            <!-- 议价 -->
-            <template #canbargain="{ text }">
-                <span>{{ text ? '是' : '否' }}</span>
-            </template>
-            <!-- 整单 -->
-            <template #canpart="{ text }">
-                <span>{{ text ? '是' : '否' }}</span>
-            </template>
-            <!-- 挂牌有效期 -->
-            <template #validtime="{ text }">
-                <span>{{ formatTime(text, 'd') }}</span>
-            </template>
-        </a-table>
-        <!-- 右键 -->
-        <contextMenu :contextMenu="contextMenu" @cancel="closeContext" :list="filterBtn(firstBtn)"></contextMenu>
-        <component
-            :is="componentId"
-            v-if="componentId"
-            :enumName="name"
-            :selectedRow="selectedRow"
-            @cancel="closeComponent"
-        ></component>
-    </div>
+  <!-- 仓单贸易 贸易圈挂牌 卖-->
+  <div>
+    <a-table :columns="columns"
+             :class="['srcollYTable', isBottom ? 'condSecondTabTableHalfTop' : 'condSecondTabTableHalfTopNoBottom', 'halfBottom']"
+             :scroll="{ x: '100%', y: isBottom ? 'calc((100vh- 443px)/2 - 14px)' : 'calc((100vh - 196px)/2 - 16px)' }"
+             :pagination="false"
+             :loading="loading"
+             :expandedRowKeys="expandedRowKeys"
+             :customRow="Rowclick"
+             rowKey="key"
+             :data-source="tableList">
+      <template #index="{ index }">
+        <span>{{ index + 1 }}</span>
+      </template>
+      <!-- 议价 -->
+      <template #canbargain="{ text }">
+        <span>{{ text ? '是' : '否' }}</span>
+      </template>
+      <!-- 整单 -->
+      <template #canpart="{ text }">
+        <span>{{ text ? '是' : '否' }}</span>
+      </template>
+      <!-- 挂牌有效期 -->
+      <template #validtime="{ text }">
+        <span>{{ formatTime(text, 'd') }}</span>
+      </template>
+    </a-table>
+    <!-- 右键 -->
+    <contextMenu :contextMenu="contextMenu"
+                 @cancel="closeContext"
+                 :list="filterBtn(firstBtn)"></contextMenu>
+    <component :is="componentId"
+               v-if="componentId"
+               :componentId="componentId"
+               :selectedRow="selectedRow"
+               :buyOrSell="BuyOrSell.Buy"
+               @cancel="closeComponent"></component>
+  </div>
 </template>
 
 <script lang="ts">
@@ -54,9 +53,12 @@ import { BuyOrSell } from '@/common/constants/enumCommon';
 import { formatTime } from '@/common/methods';
 
 export default defineComponent({
-    name: EnumRouterName.warehouse_receipt_trade_floating_price,
+    name: 'warehouse_receipt_trade_blocs_buy',
     components: {
         contextMenu,
+        warehouse_receipt_trade_blocs_delisting: defineAsyncComponent(() => import('../delisting/index.vue')),
+        warehouse_receipt_trade_blocs_bargain_delisting: defineAsyncComponent(() => import('../delisting/index.vue')),
+        warehouse_receipt_trade_blocs_detail: defineAsyncComponent(() => import('@/views/market/spot_trade/components/detail/index.vue')),
     },
     setup() {
         const isBottom = getShowBottomValue();
@@ -70,7 +72,7 @@ export default defineComponent({
         const queryTableAction = () => {
             const param: QueryOrderQuoteMyqReq = {
                 buyorsell: BuyOrSell.buy,
-                haswr: 0,
+                haswr: 1,
             };
             queryTable(queryQueryOrderQuoteMyq, param);
         };
@@ -120,6 +122,7 @@ export default defineComponent({
             search,
             formatTime,
             filterBtn,
+            BuyOrSell,
         };
     },
 });

+ 473 - 0
src/views/market/spot_trade/warehouse_pre_sale/warehouse_pre_sale_blocs/components/delisting/index.vue

@@ -0,0 +1,473 @@
+<template>
+  <!--仓单贸易 贸易圈挂牌 摘牌-->
+  <Drawer :title="isBargin() ? '议价摘牌' : '摘牌'"
+          :placement="'right'"
+          :visible="visible"
+          @cancel="cancel"
+          class="top">
+    <div class="post_buying">
+      <a-form class="inlineForm dialogForm"
+              ref="formRef"
+              :model="formState"
+              :rules="rules">
+        <div class="formBar">
+          <a-row :gutter="24">
+            <a-col :span="24">
+              <a-form-item label="交易账户"
+                           name="accountid">
+                <a-select class="inlineFormSelect"
+                          style="width: 260px"
+                          v-model:value="formState.accountid"
+                          placeholder="请选择">
+                  <a-select-option v-for="item in accountList"
+                                   :value="item.accountid"
+                                   :key="item.accountid">{{item.accountid}}</a-select-option>
+                </a-select>
+              </a-form-item>
+            </a-col>
+          </a-row>
+          <a-row :gutter="24">
+            <a-col :span="24">
+              <a-form-item label="挂牌方">
+                <span class="white ml8">{{selectedRow.username}}</span>
+              </a-form-item>
+            </a-col>
+            <a-col :span="24">
+              <a-form-item label="挂牌数量">
+                <span class="white ml8">{{selectedRow.orderqty}}{{selectedRow.enumdicname}}</span>
+              </a-form-item>
+            </a-col>
+          </a-row>
+          <a-col :span="24"
+                 v-if="isBargin()">
+            <a-form-item label="摘牌价格"
+                         name="price">
+              <a-input-number class="commonInput"
+                              style="width: 260px"
+                              :min="0"
+                              v-model:value="formState.price" />
+            </a-form-item>
+          </a-col>
+          <a-col :span="24"
+                 v-else>
+            <a-form-item label="摘牌价格">
+              <span class="white ml8">{{selectedRow.fixedprice}}</span>
+            </a-form-item>
+          </a-col>
+          <a-col :span="24"
+                 v-if="!isBuy()">
+            <a-form-item label="现货仓单"
+                         name="LadingBillId">
+              <a-select class="inlineFormSelect"
+                        style="width: 260px"
+                        v-model:value="formState.LadingBillId"
+                        placeholder="请选择">
+                <a-select-option v-for="item in wrHoldList"
+                                 :value="item.id"
+                                 :key="item.id">{{item.name}}</a-select-option>
+              </a-select>
+            </a-form-item>
+          </a-col>
+
+          <a-row :gutter="24"
+                 v-if="isCanpart()">
+            <a-col :span="24">
+              <a-form-item label="摘牌数量"
+                           class="relative"
+                           name="num">
+                <a-input-number class="dialogInput yellowInput"
+                                style="width: 260px"
+                                :min="0"
+                                :max="getMaxNum()"
+                                v-model:value="formState.num" />
+                <span class="input-enumdicname-absolute">{{selectedRow.enumdicname}}</span>
+                <div class="labelTip">({{selectedRow.minivalue}}{{selectedRow.enumdicname}}起)</div>
+              </a-form-item>
+            </a-col>
+          </a-row>
+          <a-row :gutter="24"
+                 v-if="isCanpart()">
+            <a-col :span="24"
+                   class="mt-20">
+              <a-form-item>
+                <a-slider ::min="0"
+                          v-model:value="formState.num"
+                          :max="selectedRow.orderqty"
+                          class="formSlider"
+                          style="width: 260px" />
+                <div class="unit">
+                  <span>0</span>
+                  <span>{{getMaxNum()}}{{selectedRow.enumdicname}}</span>
+                </div>
+              </a-form-item>
+            </a-col>
+            <a-col :span="12">&nbsp;</a-col>
+          </a-row>
+          <a-col :span="24"
+                 v-if="!isCanpart()">
+            <a-form-item label="摘牌数量">
+              <span class="white ml8">{{selectedRow.orderqty}}{{selectedRow.enumdicname}}</span>
+            </a-form-item>
+          </a-col>
+          <a-row :gutter="24">
+            <a-col :span="24"
+                   class="mt-20">
+              <a-form-item label="摘牌金额">
+                <span class="white ml8">{{getMoney()}}</span>
+              </a-form-item>
+            </a-col>
+          </a-row>
+          <a-row :gutter="24">
+            <a-col :span="12">
+              <a-form-item label="履约保证金">
+                <span class="white ml8">{{getCanUseMoney(getSelectedAccount())}}</span>
+              </a-form-item>
+            </a-col>
+            <a-col :span="12">
+              <a-form-item label="可用资金">
+                <span class="white ml8">{{getCanUseMoney(getSelectedAccount())}}</span>
+              </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">{{isBuy() ? '卖出' : '买入'}}</a-button>
+              <a-button class="ml10 cancelBtn"
+                        @click="cancel">取消</a-button>
+            </a-form-item>
+          </a-col>
+        </a-row>
+      </a-form>
+    </div>
+  </Drawer>
+</template>
+
+<script lang="ts">
+import { defineComponent, PropType, ref } from 'vue';
+import { Des } from '@/common/components/commonDes';
+import { _closeModal } from '@/common/setup/modal/modal';
+import { ModalEnum } from '@/common/constants/modalNameEnum';
+import Drawer from '@/common/components/drawer/index.vue';
+import { PlusOutlined, MinusOutlined } from '@ant-design/icons-vue';
+import { hdWROrder } from '@/services/proto/warehousetrade';
+import { requestResultLoadingAndInfo } from '@/common/methods/request/resultInfo';
+import { DGFactoryItems, HdWRDealOrderReq, WrBargainApplyReq, WRGoodsInfo } from '@/services/proto/warehousetrade/interface';
+import { getAccountTypeList, getSelectedAccountId, getUserId } from '@/services/bus/account';
+import { v4 as uuidv4 } from 'uuid';
+import moment, { Moment } from 'moment';
+import { getMarketRunByTradeMode } from '@/services/bus/market';
+import { QueryOrderQuoteMyqQsp, WrOrderQuote } from '@/services/go/wrtrade/interface';
+
+import { validateAction } from '@/common/setup/form';
+
+import { EnumRouterName } from '@/common/constants/enumRouterName';
+
+import { BuyOrSell } from '@/common/constants/enumCommon';
+import { getCanUseMoney } from '@/services/bus/account';
+import { TempWrOrderQuoteDetail } from '@/views/market/spot_trade/components/post_buying/interface';
+import { handleForm, handleSpotWarrant } from './setup';
+import { getRules } from '@/services/bus/rules';
+import { ListingForm } from './interface';
+import { HdWRDealOrder, wrBargainApply } from '@/services/proto/warehousetrade';
+import Long from 'long';
+
+export default defineComponent({
+    emits: ['cancel', 'update'],
+    name: 'warehouse_receipt_trade_blocs_delisting_tab',
+    components: { Des, Drawer, PlusOutlined, MinusOutlined },
+    props: {
+        selectedRow: {
+            type: Object as PropType<QueryOrderQuoteMyqQsp>,
+            default: {},
+        },
+        buyOrSell: {
+            type: Number as PropType<BuyOrSell>,
+            default: BuyOrSell.buy,
+        },
+        componentId: {
+            type: String,
+            default: '',
+        },
+    },
+    setup(props, context) {
+        const { visible, cancel } = _closeModal(context);
+        const { rules, formState, formRef } = handleForm();
+        const loading = ref<boolean>(false);
+        const accountList = getAccountTypeList([2]);
+        // 现货仓单
+        const { wrHoldList, allWrHoldList } = handleSpotWarrant(props.buyOrSell, props.selectedRow, loading);
+        if (accountList.length) {
+            formState.accountid = accountList[0].accountid;
+        }
+
+        function getSelectedAccount() {
+            return accountList.find((e) => e.accountid === formState.accountid)!;
+        }
+        // 摘牌金额
+        function getMoney() {
+            const price = isBargin() ? formState.price : props.selectedRow.fixedprice;
+            if (price) {
+                return (price * formState.num).toFixed(2);
+            } else {
+                return '--';
+            }
+        }
+        function getMaxNum() {
+            const qty = props.selectedRow.orderqty;
+            let result = 0;
+            if (isBuy()) {
+                // 交易规则
+                const rules = getRules();
+                const { buymarginvalue } = rules[0];
+                const canUseMoney = Number(getCanUseMoney(getSelectedAccount()));
+                if (canUseMoney && !isNaN(canUseMoney)) {
+                    const num = +(canUseMoney / buymarginvalue).toFixed(0);
+                    // 买 最大可摘数量=min{挂牌数量,可用资金/(履约保证金比例)}
+                    result = Math.min(qty, num);
+                }
+            } else {
+                // 卖出 最大可摘数量=min{挂牌数量,仓单可用数量}
+                const id = formState.LadingBillId;
+                if (id) {
+                    const item = allWrHoldList.value.find((el) => el.ladingbillid === id)!;
+                    result = Math.min(qty, item.enableqty);
+                }
+            }
+            return result;
+        }
+        function isBuy() {
+            return props.buyOrSell === BuyOrSell.buy;
+        }
+        // 是否部分摘牌
+        function isCanpart() {
+            return props.selectedRow.canpart === 1;
+        }
+        // 是否议价 摘牌
+        function isBargin() {
+            return props.componentId === 'warehouse_receipt_trade_blocs_bargain_delisting';
+        }
+        if (isBargin()) {
+            formState.price = props.selectedRow.fixedprice;
+        }
+
+        function submit() {
+            validateAction<ListingForm>(formRef, formState).then((res) => {
+                if (isBargin()) {
+                    // 议价摘牌
+                    const param: WrBargainApplyReq = {
+                        WRTradeOrderID: Long.fromString(props.selectedRow.wrtradeorderid),
+                        ApplyQty: 10,
+                        UserID: String(getUserId()),
+                        AccountID: getSelectedAccountId().toString(),
+                        BuyOrSell: props.buyOrSell.toString(),
+                        ApplyPrice: formState.price.toString(),
+                        ApplyRemark: '',
+                    };
+                    requestResultLoadingAndInfo(wrBargainApply, param, loading, ['议价摘牌成功', '议价摘牌失败:']).then(() => {
+                        cancel(true);
+                    });
+                } else {
+                    // 首先确定  这是仓单贸易的有仓单挂摘牌 HasWr = 1
+                    // 其次判断  摘牌 1。摘买 (需要通过自己的仓单进行摘买)  2。摘卖 (不需要通过仓单)
+                    const param: HdWRDealOrderReq = {
+                        UserID: getUserId(), // uint32 用户ID
+                        AccountID: getSelectedAccountId(), // uint64 资金账号
+                        RelatedWRTradeOrderID: props.selectedRow.wrtradeorderid, // uint64 关联委托单号(摘牌委托关联挂牌委托单ID)
+                        WRTransferUserID: props.selectedRow.userid, // uint32 仓单受让用户
+                        OrderQty: res.num as number, // uint64 委托数量
+                        OrderSrc: 0, // uint32 委托来源
+                        ClientSerialNo: uuidv4(), // string 客户端流水号
+                        ClientOrderTime: moment(new Date()).format('YYYY-MM-DD HH:mm:ss'), // string 客户端委托时间
+                        ClientType: 4, // uint32 终端类型
+                        OperatorID: getUserId(), // uint64 操作员账号ID
+                        BuyOrSell: 0, // uint32 买卖方向
+                        ApplyID: 0, // uint64 申请ID
+                        // LadingBillId: 0, // uint64 提单id(wrholdlb的LadingBillId字段),卖的时候填写
+                        SubNum: 0, // uint64 提单子单号(wrholdlb的SubNum字段),卖的时候填写
+                        WRFactorTypeId: Long.fromString(props.selectedRow.wrfactortypeid), // uint64 仓单要素ID(wrholdlb的WRFactorTypeId字段),卖的时候填写
+                        TradeDate: moment().format('YYYYMMDD'), // string 交易日
+                        DeliveryMonth: '', // string 交收月
+                        HasWr: 0, // uint32 是否有仓单-0:没有仓单 1:有仓单
+                        IsFinancing: 0, // uint32 是否融资购买(买摘牌时有效)-0:否 1:是
+                        ProductDetailID: res.caseId, // uint64 金融机构产品组合ID(融资购买时有效)
+                    };
+                    // 摘买方向
+                    if (isBuy()) {
+                        param.BuyOrSell = 1;
+                        param.LadingBillId = res.LadingBillId;
+                    } else {
+                        param.BuyOrSell = 0;
+                    }
+
+                    requestResultLoadingAndInfo(HdWRDealOrder, param, loading, ['摘牌成功', '摘牌失败:']).then(() => {
+                        cancel(true);
+                    });
+                }
+            });
+        }
+        return {
+            submit,
+            cancel,
+            visible,
+            accountList,
+            rules,
+            formState,
+            formRef,
+            getSelectedAccount,
+            getCanUseMoney,
+            getMoney,
+            isBuy,
+            isBargin,
+            wrHoldList,
+            loading,
+            getMaxNum,
+            isCanpart,
+        };
+    },
+});
+</script>
+
+<style lang="less">
+.post_buying {
+    width: 100%;
+    height: 100%;
+    .flex;
+    flex-direction: column;
+    position: relative;
+    overflow: hidden;
+    .ant-form {
+        height: 100%;
+    }
+    .condition {
+        width: 100%;
+        height: 48px;
+        margin: 0 16px;
+        padding: 10px 0;
+        border-bottom: 1px solid @m-black6;
+        .inlineflex;
+        .conditionBtn {
+            align-self: center;
+            align-items: center;
+            border: 0;
+            min-width: 80px;
+            height: 28px;
+            line-height: 28px;
+            background: @m-black7;
+            .rounded-corners(3px);
+            font-size: 14px;
+            color: @m-blue0;
+            &:hover {
+                background: @m-black7-hover;
+                color: @m-blue0-hover;
+            }
+        }
+        .conditionBtn + .conditionBtn {
+            margin-left: 10px;
+        }
+    }
+}
+
+.unit {
+    margin-left: 70px;
+    width: 260px;
+    .flex;
+    justify-content: space-between;
+    font-size: 14px;
+    color: @m-grey41;
+    height: 14px;
+    line-height: 14px;
+}
+.listedBtn {
+    width: 120px;
+    height: 30px;
+    line-height: 30px;
+    background: linear-gradient(0deg, @m-blue2 0%, @m-blue0 100%);
+    border-radius: 3px;
+    color: @m-white0;
+    font-size: 14px;
+    text-align: center;
+    border: 0;
+    &:hover {
+        background: linear-gradient(0deg, @m-blue0-hover 0%, @m-blue2-hover 100%);
+        color: @m-white0-hover;
+    }
+}
+.cancelBtn:extend(.listedBtn) {
+    background: linear-gradient(0deg, @m-grey12 0%, @m-grey13 100%) !important;
+    &:hover {
+        background: linear-gradient(0deg, @m-grey12-hover 0%, @m-grey13-hover 100%) !important;
+        color: @m-white0-hover;
+    }
+}
+.ml10 {
+    margin-left: 10px;
+}
+.ant-form.dialogForm .ant-row.ant-form-item {
+    margin-bottom: 14px;
+}
+.mt20 {
+    margin-top: 20px;
+}
+.mt-10 {
+    margin-top: -10px;
+}
+.ant-input-suffix {
+    position: absolute;
+    right: -25px;
+}
+.minusBtn,
+.plusBtn {
+    width: 15px;
+    height: 32px;
+    line-height: 32px;
+    font-size: 15px;
+    color: @m-blue15;
+    cursor: pointer;
+}
+.minusBtn {
+    position: absolute;
+    top: -6px;
+    left: 14px;
+    z-index: 1;
+}
+.plusBtn {
+    position: absolute;
+    top: -6px;
+    right: 14px;
+    z-index: 1;
+}
+.stepper {
+    padding-left: 30px;
+    padding-right: 30px;
+    text-align: center;
+    color: @m-yellow1;
+    font-size: 16px;
+}
+.ant-slider.formSlider {
+    width: 260px !important;
+    margin-left: 70px;
+    .ant-slider-rail {
+        margin-right: 0;
+        padding-right: 0;
+        height: 3px !important;
+        border-radius: 2px !important;
+        background-color: @m-blue14;
+    }
+    .ant-slider-track {
+        height: 3px;
+        background-color: @m-blue0;
+    }
+    .ant-slider-step {
+        height: 3px;
+    }
+    .ant-progress-text {
+        display: none;
+    }
+}
+</style>

+ 12 - 0
src/views/market/spot_trade/warehouse_pre_sale/warehouse_pre_sale_blocs/components/delisting/interface.ts

@@ -0,0 +1,12 @@
+export interface ListingForm {
+    accountid: undefined | number,
+    price: number,
+    num: number,
+    LadingBillId: string,
+    case: string,
+    caseId: number,
+}
+export interface Wrhold {
+    id: string,
+    name: string,
+}

+ 47 - 0
src/views/market/spot_trade/warehouse_pre_sale/warehouse_pre_sale_blocs/components/delisting/setup.ts

@@ -0,0 +1,47 @@
+import { BuyOrSell } from "@/common/constants/enumCommon";
+import { queryResultLoadingAndInfo } from "@/common/methods/request/resultInfo";
+import { queryHoldLB } from "@/services/go/wrtrade";
+import { QueryOrderQuoteMyqQsp, WrHoldLB } from "@/services/go/wrtrade/interface";
+import { Wrhold } from "@/views/market/spot_trade/spot_trade_order_transaction/components/delisting/interface";
+import { reactive, Ref, ref, UnwrapRef } from "vue";
+import { ListingForm } from "./interface";
+
+
+
+export function handleForm() {
+    const formRef = ref();
+    const formState: UnwrapRef<ListingForm> = reactive({
+        accountid: undefined,
+        price: 0,
+        num: 0,
+        LadingBillId: '',
+        case: '',
+        caseId: 0
+    })
+    const rules = {
+        accountid: [{ required: true, message: '请选择交易账户' }],
+        LadingBillId: [{ required: true, message: '请选择现货仓单' }],
+        caseId: [{ required: true, message: '请选择融资方案' }],
+        num: [{ required: true, message: '请输入摘牌数量', trigger: 'blur', type: 'number', },
+        { min: 1, message: '请输入摘牌数量' }],
+
+    }
+    return { rules, formState, formRef }
+}
+
+
+export function handleSpotWarrant(buyOrSell: BuyOrSell, selectedRow: QueryOrderQuoteMyqQsp, loading: Ref<boolean>) {
+    const wrHoldList = ref<Wrhold[]>([])
+    const allWrHoldList = ref<WrHoldLB[]>([])
+    if (buyOrSell === BuyOrSell.sell) {
+        queryResultLoadingAndInfo(queryHoldLB, loading).then(res => {
+            allWrHoldList.value = res
+            wrHoldList.value = res.filter((e: WrHoldLB) => e.wrfactortypeid === String(selectedRow.wrfactortypeid)).map((e: WrHoldLB) => {
+                const { wrholdeno, enableqty, ladingbillid, enumdicname } = e
+                return { id: ladingbillid, name: `${wrholdeno}(${enableqty}${enumdicname})` }
+            })
+        })
+    }
+
+    return { wrHoldList, allWrHoldList }
+}

+ 0 - 0
src/views/market/spot_trade/warehouse_pre_sale/warehouse_pre_sale_blocs/components/detail/index.vue


+ 116 - 0
src/views/market/spot_trade/warehouse_pre_sale/warehouse_pre_sale_blocs/components/post-buying/addPermance.vue

@@ -0,0 +1,116 @@
+<template>
+  <!--新增履约模板-->
+  <Drawer :title="'新增履约模板'"
+          :placement="'right'"
+          :visible="visible"
+          @cancel="cancel"
+          class="top486">
+    <a-spin :spinning="loading">
+
+    </a-spin>
+  </Drawer>
+</template>
+
+<script lang="ts">
+import { defineComponent, PropType, ref } from 'vue';
+import { Des } from '@/common/components/commonDes';
+import { _closeModal } from '@/common/setup/modal/modal';
+import Drawer from '@/common/components/drawer/index.vue';
+import { PlusOutlined, MinusOutlined, SearchOutlined } from '@ant-design/icons-vue';
+import { QueryWrFriendApplyRsp } from '@/services/go/wrtrade/interface';
+import { TempWrOrderQuoteDetail } from '@/views/market/spot_trade/components/post_buying/interface';
+import { queryQueryWrFriend } from '@/services/go/wrtrade';
+import { message } from 'ant-design-vue';
+
+interface FriendList extends QueryWrFriendApplyRsp {
+    checked: boolean;
+}
+
+export default defineComponent({
+    emits: ['cancel', 'update'],
+    name: 'warehouse_receipt_trade_blocs_delisting',
+    components: { Des, Drawer, PlusOutlined, MinusOutlined, SearchOutlined },
+    setup(props, context) {
+        const { visible, cancel } = _closeModal(context);
+        const loading = ref<boolean>(false);
+        const searchValue = ref<string>('');
+        const myFriends = ref<FriendList[]>([]);
+        // 查询好友列表
+        function queryMyFriend(value?: string) {
+            loading.value = true;
+            queryQueryWrFriend(value)
+                .then((res) => {
+                    if (res) {
+                        myFriends.value = [];
+                        res.forEach((el) => {
+                            myFriends.value.push({ ...el, checked: false });
+                        });
+                    }
+                })
+                .catch((err: string) => message.error(err))
+                .finally(() => {
+                    loading.value = false;
+                });
+        }
+        queryMyFriend();
+        function getViewFriends() {
+            if (searchValue.value) {
+                return myFriends.value.filter((el) => String(el.frienduserid).includes(searchValue.value));
+            } else {
+                return myFriends.value;
+            }
+        }
+        function submit() {
+            const result: string[] = [];
+            myFriends.value.forEach((el) => {
+                if (el.checked) {
+                    result.push(el.frienduserid);
+                }
+            });
+            if (result.length) {
+                context.emit('update', result);
+            } else {
+                message.warn('请选择朋友');
+            }
+        }
+        function handleSearch(value: string) {
+            // const findResult = myFriends.value.find((e) => String(e.frienduserid).includes(value));
+            // if (findResult) {
+            //     searchFriend.value = [findResult];
+            // } else {
+            //     queryMyFriend(value);
+            // }
+        }
+        return {
+            loading,
+            myFriends,
+            cancel,
+            visible,
+            submit,
+            searchValue,
+            getViewFriends,
+        };
+    },
+});
+</script>
+
+<style lang="less" scoped>
+.listed {
+    padding: 18px 20px 0;
+    .formBar {
+        height: calc(100% - 120px);
+        padding: 0 20px 0 13px;
+        margin-top: 16px;
+        background: #08131f;
+        border: 1px solid #10202f;
+        .item {
+            width: 100%;
+            height: 50px;
+            line-height: 50px;
+            border-bottom: 1px solid #10202f;
+            font-size: 16px;
+            color: #ffffff;
+        }
+    }
+}
+</style>

+ 155 - 0
src/views/market/spot_trade/warehouse_pre_sale/warehouse_pre_sale_blocs/components/post-buying/friend.vue

@@ -0,0 +1,155 @@
+<template>
+    <!--选择朋友-->
+    <Drawer :title="'选择朋友'" :placement="'right'" :visible="visible" @cancel="cancel" class="top486">
+        <a-spin :spinning="loading">
+            <div class="listed">
+                <a-form class="inlineForm dialogForm">
+                    <a-input-search
+                        placeholder="搜索朋友编码或名称"
+                        class="searchFriendInput noSuffixInput"
+                        enter-button
+                        v-model:value="searchValue"
+                        @search="handleSearch"
+                    >
+                        <template #prefix>
+                            <SearchOutlined />
+                        </template>
+                    </a-input-search>
+                    <div class="formBar ant-checkbox-group commonCheckboxGroup whitebgCheckbox">
+                        <!-- <a-checkbox-group class="commonCheckboxGroup"> -->
+                        <div class="ant-checkbox-wrapper" style="width: 100%">
+                            <div
+                                class="item"
+                                v-for="(item, index) in getViewFriends()"
+                                :key="index + '11'"
+                            >
+                                <a-checkbox v-model:checked="item.checked">
+                                    <span class="txt">{{item.frienduserid}} {{ item.friendname }}</span>
+                                </a-checkbox>
+                            </div>
+                        </div>
+                        <!-- </a-checkbox-group> -->
+                    </div>
+                    <a-row :gutter="24">
+                        <a-col :span="24" class="fixedBtns">
+                            <a-form-item class="btnCenter">
+                                <a-button class="listedBtn" @click="submit">确定</a-button>
+                            </a-form-item>
+                        </a-col>
+                    </a-row>
+                </a-form>
+            </div>
+        </a-spin>
+    </Drawer>
+</template>
+
+<script lang="ts">
+import { defineComponent, PropType, ref } from 'vue';
+import { Des } from '@/common/components/commonDes';
+import { _closeModal } from '@/common/setup/modal/modal';
+import Drawer from '@/common/components/drawer/index.vue';
+import { PlusOutlined, MinusOutlined, SearchOutlined } from '@ant-design/icons-vue';
+import { QueryWrFriendApplyRsp } from '@/services/go/wrtrade/interface';
+import { TempWrOrderQuoteDetail } from '@/views/market/spot_trade/components/post_buying/interface';
+import { queryQueryWrFriend } from '@/services/go/wrtrade';
+import { message } from 'ant-design-vue';
+
+interface FriendList extends QueryWrFriendApplyRsp {
+    checked: boolean;
+}
+
+export default defineComponent({
+    emits: ['cancel', 'update'],
+    name: 'warehouse_receipt_trade_blocs_delisting',
+    components: { Des, Drawer, PlusOutlined, MinusOutlined, SearchOutlined },
+    setup(props, context) {
+        const { visible, cancel } = _closeModal(context);
+        const loading = ref<boolean>(false);
+        const searchValue = ref<string>('');
+        const myFriends = ref<FriendList[]>([]);
+        // 查询好友列表
+        function queryMyFriend(value?: string) {
+            loading.value = true;
+            queryQueryWrFriend(value)
+                .then((res) => {
+                    if (res) {
+                        myFriends.value = [];
+                        res.forEach((el) => {
+                            myFriends.value.push({ ...el, checked: false });
+                        });
+                    }
+                })
+                .catch((err: string) => message.error(err))
+                .finally(() => {
+                    loading.value = false;
+                });
+        }
+        queryMyFriend();
+        function getViewFriends() {
+            if (searchValue.value) {
+                return myFriends.value.filter((el) => String(el.frienduserid).includes(searchValue.value));
+            } else {
+                return myFriends.value;
+            }
+        }
+        function submit() {
+            const result: string[] = [];
+            myFriends.value.forEach((el) => {
+                if (el.checked) {
+                    result.push(el.frienduserid);
+                }
+            });
+            if (result.length) {
+                context.emit('update', result);
+            } else {
+                message.warn('请选择朋友');
+            }
+        }
+        function handleSearch(value: string) {
+            // const findResult = myFriends.value.find((e) => String(e.frienduserid).includes(value));
+            // if (findResult) {
+            //     searchFriend.value = [findResult];
+            // } else {
+            //     queryMyFriend(value);
+            // }
+        }
+        return {
+            loading,
+            myFriends,
+            cancel,
+            visible,
+            submit,
+            searchValue,
+            getViewFriends,
+        };
+    },
+});
+</script>
+
+<style lang="less" scoped>
+.listed {
+    padding: 18px 20px 0;
+    .formBar {
+        height: calc(100% - 120px);
+        padding: 0 20px 0 13px;
+        margin-top: 16px;
+        background: @m-grey63;
+        border: 1px solid @m-black45;
+        .item {
+            width: 100%;
+            height: 50px;
+            line-height: 50px;
+            border-bottom: 1px solid @m-black45;
+            font-size: 16px;
+            color: @m-white6;
+        }
+    }
+}
+.ant-checkbox-group.commonCheckboxGroup {
+    .ant-checkbox-wrapper {
+        span.txt {
+            color: @m-white11;
+        }
+    }
+}
+</style>

+ 32 - 19
src/views/market/spot_trade/warehouse_pre_sale/warehouse_pre_sale_blocs/components/post-buying/index.vue

@@ -1,6 +1,6 @@
 <template>
     <!--仓单贸易 贸易圈挂牌 挂牌求购 -->
-    <Drawer :title="'挂牌求购'" :placement="'right'" :visible="visible" @cancel="cancel" class="top">
+    <Drawer :title="'挂牌求购'" :placement="'right'" :visible="visible" @cancel="cancel" class="top486">
         <div class="post_buying">
             <a-form class="inlineForm dialogForm" ref="formRef" :model="formState" :rules="rules">
                 <div class="formBar">
@@ -44,22 +44,22 @@
                         </a-col>
 
                         <a-col :span="24">
-                            <a-form-item label="起摘数量" class="relative">
-                                <a-input
+                            <a-form-item label="起摘数量" name="delistingQty">
+                                <a-input-number
                                     class="commonInput"
-                                    :suffix="selectedRow.enumdicname"
-                                    :min="selectedRow.minivalue"
+                                    v-model:value="formState.delistingQty"
+                                    :min="0"
                                     style="width: 260px"
                                 />
                                 <span class="input-enumdicname">{{selectedRow.enumdicname}}</span>
                             </a-form-item>
                         </a-col>
                         <a-col :span="24">
-                            <a-form-item label="履约保证金" class="relative">
-                                <a-input
+                            <a-form-item label="履约保证金" name="margin">
+                                <a-input-number
                                     class="commonInput"
-                                    :suffix="selectedRow.enumdicname"
-                                    :min="selectedRow.minivalue"
+                                    v-model:value="formState.margin"
+                                    :min="0"
                                     style="width: 260px"
                                 />
                                 <span class="input-enumdicname">%</span>
@@ -67,7 +67,7 @@
                         </a-col>
                         <a-col :span="24">
                             <a-form-item label="挂牌有效期" name="DeliveryMonth">
-                                <a-date-picke
+                                <a-date-picker
                                     style="width: 260px"
                                     v-model:value="formState.DeliveryMonth"
                                     :allowClear="false"
@@ -76,17 +76,12 @@
                             </a-form-item>
                         </a-col>
 
-                        <a-col :span="24">
+                        <a-col :span="24" @click="openPermance">
                             <a-form-item label="履约方式">
                                 <span class="white ml8">选择履约模板</span>
                             </a-form-item>
                         </a-col>
-                        <a-col :span="24">
-                            <a-form-item label="指定朋友">
-                                <span class="white ml8">选择朋友</span>
-                            </a-form-item>
-                        </a-col>
-                        <a-col :span="24">
+                        <a-col :span="24" @click="openFriend">
                             <a-form-item label="指定朋友">
                                 <span class="white ml8">选择朋友</span>
                             </a-form-item>
@@ -119,6 +114,10 @@
             </a-form>
         </div>
     </Drawer>
+    <!-- 选择朋友 -->
+    <Friend v-if="showFriend" @cancel="chooseFriend" @update="chooseFriend" />
+    <!-- 选择履约模板 -->
+    <Permance v-if="showPermance" @cancel="choosePermance" @update="choosePermance" />
 </template>
 
 <script lang="ts">
@@ -136,7 +135,7 @@ import { v4 as uuidv4 } from 'uuid';
 import moment, { Moment } from 'moment';
 import { getMarketRunByTradeMode } from '@/services/bus/market';
 import { QueryOrderQuoteMyqQsp, WrOrderQuote } from '@/services/go/wrtrade/interface';
-import { handleForm } from './setup';
+import { handleForm, hanldeOpenAndCloseComponent } from './setup';
 import { validateAction } from '@/common/setup/form';
 import { FormParam } from './interface';
 import { EnumRouterName } from '@/common/constants/enumRouterName';
@@ -144,11 +143,13 @@ import { EnumRouterName } from '@/common/constants/enumRouterName';
 import { BuyOrSell } from '@/common/constants/enumCommon';
 import { getCanUseMoney } from '@/services/bus/account';
 import { TempWrOrderQuoteDetail } from '@/views/market/spot_trade/components/post_buying/interface';
+import Friend from './friend.vue';
+import Permance from './permancePlanTmp.vue';
 
 export default defineComponent({
     emits: ['cancel', 'update'],
     name: ModalEnum.spot_trade_warehouse_post_buying,
-    components: { Des, Drawer, PlusOutlined, MinusOutlined },
+    components: { Des, Drawer, PlusOutlined, MinusOutlined, Friend, Permance },
     props: {
         selectedRow: {
             type: Object as PropType<TempWrOrderQuoteDetail>,
@@ -158,6 +159,10 @@ export default defineComponent({
     setup(props, context) {
         const { visible, cancel } = _closeModal(context);
         const { rules, formState, formRef } = handleForm();
+        // 选择朋友
+        const { show: showFriend, selected: frineds, close: chooseFriend, open: openFriend } = hanldeOpenAndCloseComponent<number[]>();
+        // 履约模板
+        const { show: showPermance, selected: selectedPermance, close: choosePermance, open: openPermance } = hanldeOpenAndCloseComponent<number>();
         const loading = ref<boolean>(false);
         const accountList = getAccountTypeList([2]);
         if (accountList.length) {
@@ -244,6 +249,14 @@ export default defineComponent({
             formRef,
             getSelectedAccount,
             getCanUseMoney,
+
+            showFriend,
+            chooseFriend,
+            openFriend,
+
+            showPermance,
+            choosePermance,
+            openPermance,
         };
     },
 });

+ 3 - 1
src/views/market/spot_trade/warehouse_pre_sale/warehouse_pre_sale_blocs/components/post-buying/interface.ts

@@ -4,7 +4,9 @@ export interface FormParam {
     accountid: undefined | number,
     FixedPrice: number,
     OrderQty: number,
-    PriceMove: number,
+    delistingQty: number,
+    margin: number,
     DeliveryMonth: Moment,
+    vidaliteTime: Moment,
 }
 

+ 139 - 0
src/views/market/spot_trade/warehouse_pre_sale/warehouse_pre_sale_blocs/components/post-buying/permancePlanTmp.vue

@@ -0,0 +1,139 @@
+<template>
+    <!--选择履约模板-->
+    <Drawer
+        :title="'选择履约模板'"
+        :placement="'right'"
+        :visible="visible"
+        @cancel="cancel"
+        class="top486"
+    >
+        <span class="add-permance" @click="open">
+            <svg class="icon svg-icon" aria-hidden="true">
+                <use xlink:href="#icon-xinjianzengjiaxinzeng-20" />
+            </svg>
+        </span>
+        <a-spin :spinning="loading">
+            <div class="moduleContent">
+                <div class="itemBar" v-for="item in tableList" :key="item.autoid">
+                    <div class="itemName">{{item.templatename}}</div>
+                    <div class="rulesCont">
+                        <a-row>
+                            <a-col :span="24" class="ruleCol">
+                                <div class="line" v-for="sub in item.LstStep" :key="sub.autoid">
+                                    <div class="name">{{sub.steptypename}}</div>
+                                    <div class="time">{{sub.stepdate}}</div>
+                                </div>
+                            </a-col>
+                        </a-row>
+                    </div>
+                </div>
+            </div>
+        </a-spin>
+    </Drawer>
+    <Add v-if="show" @cancel="close" @update="close" />
+</template>
+
+<script lang="ts">
+import { defineComponent, PropType, ref } from 'vue';
+import { Des } from '@/common/components/commonDes';
+import { _closeModal } from '@/common/setup/modal/modal';
+import Drawer from '@/common/components/drawer/index.vue';
+import { PlusOutlined, MinusOutlined, SearchOutlined } from '@ant-design/icons-vue';
+import { QueryPermancePlanTmpReq, QueryPermancePlanTmpRsp, QueryWrFriendApplyRsp } from '@/services/go/wrtrade/interface';
+import { TempWrOrderQuoteDetail } from '@/views/market/spot_trade/components/post_buying/interface';
+import { queryQueryPermancePlanTmp, queryQueryWrFriend } from '@/services/go/wrtrade';
+import { message } from 'ant-design-vue';
+import { getUsrId } from '@/services/bus/user';
+import { queryResultLoadingAndInfo } from '@/common/methods/request/resultInfo';
+import { queryTableList } from '@/common/setup/table';
+import Add from './addPermance.vue';
+import { hanldeOpenAndCloseComponent } from './setup';
+
+export default defineComponent({
+    emits: ['cancel', 'update'],
+    name: 'queryQueryPermancePlanTmp',
+    components: { Des, Drawer, Add },
+    setup(props, context) {
+        const { visible, cancel } = _closeModal(context);
+        // 新增模板
+        const { show, close, open } = hanldeOpenAndCloseComponent();
+
+        const param: QueryPermancePlanTmpReq = {
+            userid: getUsrId(),
+            tmptype: '2',
+        };
+        const { loading, tableList, queryTable } = queryTableList<QueryPermancePlanTmpRsp>();
+        queryTable(queryQueryPermancePlanTmp, param);
+
+        return {
+            loading,
+            cancel,
+            visible,
+            tableList,
+            show,
+            close,
+            open,
+        };
+    },
+});
+</script>
+
+
+<style lang="less" scoped>
+.add-permance {
+    position: absolute;
+    top: 10px;
+    right: 20px;
+    .icon {
+        font-size: 20px;
+        color: @m-blue25;
+    }
+}
+.moduleContent {
+    padding: 10px 20px 0;
+    width: 470px;
+    height: 100%;
+    overflow-y: auto;
+    .itemBar {
+        width: 100%;
+        padding: 0 14px 6px;
+        margin-bottom: 10px;
+        .flex;
+        flex-direction: column;
+        background: @m-blue34;
+        .rounded-corners(5px);
+        .itemName {
+            width: 100%;
+            height: 40px;
+            line-height: 40px;
+            border-bottom: 1px solid @m-blue20;
+            color: @m-white11;
+            font-size: 16px;
+        }
+    }
+}
+/*滚动条样式*/
+::-webkit-scrollbar {
+    //width: 10px;
+    height: 4px;
+}
+/* 滚动的滑块 */
+::-webkit-scrollbar-thumb {
+    border-radius: 2px;
+    background-color: @m-blue35;
+}
+/* 滚动条两端的按钮 */
+::-webkit-scrollbar-button {
+    background-color: transparent;
+    display: none;
+}
+/* 内层滚动槽 */
+::-webkit-scrollbar-track-piece {
+    background-color: transparent;
+}
+/* 边角 */
+::-webkit-scrollbar-corner,
+.el-input::-webkit-scrollbar-corner {
+    background-color: @m-blue35;
+}
+</style>

+ 38 - 4
src/views/market/spot_trade/warehouse_pre_sale/warehouse_pre_sale_blocs/components/post-buying/setup.ts

@@ -6,17 +6,51 @@ const formState: UnwrapRef<FormParam> = reactive({
     accountid: undefined,
     FixedPrice: 0,
     OrderQty: 0,
-    PriceMove: 0,
-    DeliveryMonth: moment()
+    delistingQty: 0,
+    margin: 0,
+    DeliveryMonth: moment(),
+    vidaliteTime: moment(),
 })
 export function handleForm() {
+    function validateMargin(value: any, errInfo: string) {
+        if (value) {
+            return Promise.resolve();
+        } else {
+            return Promise.reject('履约保证金比例大于0');
+        }
+    }
     const formRef = ref();
     const rules = {
         FixedPrice: [{ required: true, message: '请输入挂牌价格', trigger: 'blur', type: 'number', }],
-        OrderQty: [{ required: true, message: '请输入挂牌数量', trigger: 'blur', type: 'number', min: 1 }],
-        PriceMove: [{ required: true, message: '请输入基差', trigger: 'blur', type: 'number' }],
+        OrderQty: [
+            { required: true, message: '请输入挂牌数量', trigger: 'blur', type: 'number' },
+            { min: 1, message: '挂牌挂牌数量不能小于1', }
+        ],
+        delistingQty: [
+            { required: true, message: '请输入起摘数量', trigger: 'blur', type: 'number' },
+            { min: 1, message: '起摘数量不能小于1', }
+        ],
+        margin: [
+            { required: true, message: '请输入履约保证金', trigger: 'blur', type: 'number' },
+            { validator: validateMargin, trigger: 'blur' }
+        ],
         accountid: [{ required: true, message: '请输入交易账号' }],
     }
     return { rules, formState, formRef }
 }
 
+// 处理组件打开与关闭通用逻辑
+export function hanldeOpenAndCloseComponent<T>() {
+    const show = ref<boolean>(false)
+    const selected = ref<T>() // 选中的朋友 id 列表
+    function close(value: any) {
+        if (value) {
+            selected.value = value
+        }
+        show.value = false
+    }
+    function open() {
+        show.value = true
+    }
+    return { show, selected, close, open }
+}

+ 44 - 41
src/views/market/spot_trade/warehouse_pre_sale/warehouse_pre_sale_blocs/components/sell/index.vue

@@ -1,43 +1,42 @@
 <template>
-    <!-- 仓单贸易 贸易圈挂牌 买-->
-    <div>
-        <a-table
-            :columns="columns"
-            :class="['srcollYTable', isBottom ? 'condSecondTabTableHalfTop' : 'condSecondTabTableHalfTopNoBottom']"
-            :scroll="{ x: '100%', y: isBottom ? 'calc((100vh- 443px)/2 - 14px)' : 'calc((100vh - 196px)/2 - 16px)' }"
-            :pagination="false"
-            :loading="loading"
-            :expandedRowKeys="expandedRowKeys"
-            :customRow="Rowclick"
-            rowKey="key"
-            :data-source="tableList"
-        >
-            <template #index="{ index }">
-                <span>{{ index + 1 }}</span>
-            </template>
-            <!-- 议价 -->
-            <template #canbargain="{ text }">
-                <span>{{ text ? '是' : '否' }}</span>
-            </template>
-            <!-- 整单 -->
-            <template #canpart="{ text }">
-                <span>{{ text ? '是' : '否' }}</span>
-            </template>
-            <!-- 挂牌有效期 -->
-            <template #validtime="{ text }">
-                <span>{{ formatTime(text, 'd') }}</span>
-            </template>
-        </a-table>
-        <!-- 右键 -->
-        <contextMenu :contextMenu="contextMenu" @cancel="closeContext" :list="filterBtn(firstBtn)"></contextMenu>
-        <component
-            :is="componentId"
-            v-if="componentId"
-            :enumName="name"
-            :selectedRow="selectedRow"
-            @cancel="closeComponent"
-        ></component>
-    </div>
+  <!-- 仓单贸易 贸易圈挂牌 买-->
+  <div>
+    <a-table :columns="columns"
+             :class="['srcollYTable', isBottom ? 'condSecondTabTableHalfTop' : 'condSecondTabTableHalfTopNoBottom']"
+             :scroll="{ x: '100%', y: isBottom ? 'calc((100vh- 443px)/2 - 14px)' : 'calc((100vh - 196px)/2 - 16px)' }"
+             :pagination="false"
+             :loading="loading"
+             :expandedRowKeys="expandedRowKeys"
+             :customRow="Rowclick"
+             rowKey="key"
+             :data-source="tableList">
+      <template #index="{ index }">
+        <span>{{ index + 1 }}</span>
+      </template>
+      <!-- 议价 -->
+      <template #canbargain="{ text }">
+        <span>{{ text ? '是' : '否' }}</span>
+      </template>
+      <!-- 整单 -->
+      <template #canpart="{ text }">
+        <span>{{ text ? '否' : '是' }}</span>
+      </template>
+      <!-- 挂牌有效期 -->
+      <template #validtime="{ text }">
+        <span>{{ formatTime(text, 'd') }}</span>
+      </template>
+    </a-table>
+    <!-- 右键 -->
+    <contextMenu :contextMenu="contextMenu"
+                 @cancel="closeContext"
+                 :list="filterBtn(firstBtn)"></contextMenu>
+    <component :is="componentId"
+               v-if="componentId"
+               :componentId="componentId"
+               :selectedRow="selectedRow"
+               :buyOrSell="BuyOrSell.sell"
+               @cancel="closeComponent"></component>
+  </div>
 </template>
 
 <script lang="ts">
@@ -54,9 +53,12 @@ import { BuyOrSell } from '@/common/constants/enumCommon';
 import { formatTime } from '@/common/methods';
 
 export default defineComponent({
-    name: EnumRouterName.warehouse_receipt_trade_floating_price,
+    name: 'warehouse_receipt_trade_blocs_sell',
     components: {
         contextMenu,
+        warehouse_receipt_trade_blocs_delisting: defineAsyncComponent(() => import('../delisting/index.vue')),
+        warehouse_receipt_trade_blocs_bargain_delisting: defineAsyncComponent(() => import('../delisting/index.vue')),
+        warehouse_receipt_trade_blocs_detail: defineAsyncComponent(() => import('@/views/market/spot_trade/components/detail/index.vue')),
     },
     setup() {
         const isBottom = getShowBottomValue();
@@ -70,7 +72,7 @@ export default defineComponent({
         const queryTableAction = () => {
             const param: QueryOrderQuoteMyqReq = {
                 buyorsell: BuyOrSell.sell,
-                haswr: 0,
+                haswr: 1,
             };
             queryTable(queryQueryOrderQuoteMyq, param);
         };
@@ -120,6 +122,7 @@ export default defineComponent({
             search,
             formatTime,
             filterBtn,
+            BuyOrSell,
         };
     },
 });

+ 133 - 84
src/views/market/spot_trade/warehouse_receipt_trade/warehouse_receipt_trade_blocs/components/delisting/index.vue

@@ -1,6 +1,6 @@
 <template>
   <!--仓单贸易 贸易圈挂牌 摘牌-->
-  <Drawer :title="'摘牌'"
+  <Drawer :title="isBargin() ? '议价摘牌' : '摘牌'"
           :placement="'right'"
           :visible="visible"
           @cancel="cancel"
@@ -34,22 +34,28 @@
             </a-col>
             <a-col :span="24">
               <a-form-item label="挂牌数量">
-                <span class="white ml8">{{selectedRow.orderqty}}</span>
+                <span class="white ml8">{{selectedRow.orderqty}}{{selectedRow.enumdicname}}</span>
               </a-form-item>
             </a-col>
           </a-row>
-          <a-col :span="24">
+          <a-col :span="24"
+                 v-if="isBargin()">
             <a-form-item label="摘牌价格"
-                         name="OrderQty">
+                         name="price">
               <a-input-number class="commonInput"
                               style="width: 260px"
                               :min="0"
-                              v-model:value="formState.OrderQty" />
-              <span class="input-enumdicname">{{selectedRow.enumdicname}}</span>
+                              v-model:value="formState.price" />
             </a-form-item>
           </a-col>
-
-          <a-col :span="24">
+          <a-col :span="24"
+                 v-else>
+            <a-form-item label="摘牌价格">
+              <span class="white ml8">{{selectedRow.fixedprice}}</span>
+            </a-form-item>
+          </a-col>
+          <a-col :span="24"
+                 v-if="!isBuy()">
             <a-form-item label="现货仓单"
                          name="LadingBillId">
               <a-select class="inlineFormSelect"
@@ -63,7 +69,8 @@
             </a-form-item>
           </a-col>
 
-          <a-row :gutter="24">
+          <a-row :gutter="24"
+                 v-if="isCanpart()">
             <a-col :span="24">
               <a-form-item label="摘牌数量"
                            class="relative"
@@ -71,14 +78,15 @@
                 <a-input-number class="dialogInput yellowInput"
                                 style="width: 260px"
                                 :min="0"
-                                :max="99999"
+                                :max="getMaxNum()"
                                 v-model:value="formState.num" />
                 <span class="input-enumdicname-absolute">{{selectedRow.enumdicname}}</span>
                 <div class="labelTip">({{selectedRow.minivalue}}{{selectedRow.enumdicname}}起)</div>
               </a-form-item>
             </a-col>
           </a-row>
-          <a-row :gutter="24">
+          <a-row :gutter="24"
+                 v-if="isCanpart()">
             <a-col :span="24"
                    class="mt-20">
               <a-form-item>
@@ -89,12 +97,18 @@
                           style="width: 260px" />
                 <div class="unit">
                   <span>0</span>
-                  <span>99999{{selectedRow.enumdicname}}</span>
+                  <span>{{getMaxNum()}}{{selectedRow.enumdicname}}</span>
                 </div>
               </a-form-item>
             </a-col>
             <a-col :span="12">&nbsp;</a-col>
           </a-row>
+          <a-col :span="24"
+                 v-if="!isCanpart()">
+            <a-form-item label="摘牌数量">
+              <span class="white ml8">{{selectedRow.orderqty}}{{selectedRow.enumdicname}}</span>
+            </a-form-item>
+          </a-col>
           <a-row :gutter="24">
             <a-col :span="24"
                    class="mt-20">
@@ -143,8 +157,8 @@ import Drawer from '@/common/components/drawer/index.vue';
 import { PlusOutlined, MinusOutlined } from '@ant-design/icons-vue';
 import { hdWROrder } from '@/services/proto/warehousetrade';
 import { requestResultLoadingAndInfo } from '@/common/methods/request/resultInfo';
-import { DGFactoryItems, WRGoodsInfo } from '@/services/proto/warehousetrade/interface';
-import { getAccountTypeList, getUserId } from '@/services/bus/account';
+import { DGFactoryItems, HdWRDealOrderReq, WrBargainApplyReq, WRGoodsInfo } from '@/services/proto/warehousetrade/interface';
+import { getAccountTypeList, getSelectedAccountId, getUserId } from '@/services/bus/account';
 import { v4 as uuidv4 } from 'uuid';
 import moment, { Moment } from 'moment';
 import { getMarketRunByTradeMode } from '@/services/bus/market';
@@ -158,10 +172,14 @@ import { BuyOrSell } from '@/common/constants/enumCommon';
 import { getCanUseMoney } from '@/services/bus/account';
 import { TempWrOrderQuoteDetail } from '@/views/market/spot_trade/components/post_buying/interface';
 import { handleForm, handleSpotWarrant } from './setup';
+import { getRules } from '@/services/bus/rules';
+import { ListingForm } from './interface';
+import { HdWRDealOrder, wrBargainApply } from '@/services/proto/warehousetrade';
+import Long from 'long';
 
 export default defineComponent({
     emits: ['cancel', 'update'],
-    name: 'warehouse_receipt_trade_blocs_delisting',
+    name: 'warehouse_receipt_trade_blocs_delisting_tab',
     components: { Des, Drawer, PlusOutlined, MinusOutlined },
     props: {
         selectedRow: {
@@ -182,88 +200,116 @@ export default defineComponent({
         const { rules, formState, formRef } = handleForm();
         const loading = ref<boolean>(false);
         const accountList = getAccountTypeList([2]);
+        // 现货仓单
+        const { wrHoldList, allWrHoldList } = handleSpotWarrant(props.buyOrSell, props.selectedRow, loading);
         if (accountList.length) {
             formState.accountid = accountList[0].accountid;
         }
+
         function getSelectedAccount() {
-            return accountList.find((e) => e.accountid === formState.accountid);
+            return accountList.find((e) => e.accountid === formState.accountid)!;
+        }
+        // 摘牌金额
+        function getMoney() {
+            const price = isBargin() ? formState.price : props.selectedRow.fixedprice;
+            if (price) {
+                return (price * formState.num).toFixed(2);
+            } else {
+                return '--';
+            }
+        }
+        function getMaxNum() {
+            const qty = props.selectedRow.orderqty;
+            let result = 0;
+            if (isBuy()) {
+                // 交易规则
+                const rules = getRules();
+                const { buymarginvalue } = rules[0];
+                const canUseMoney = Number(getCanUseMoney(getSelectedAccount()));
+                if (canUseMoney && !isNaN(canUseMoney)) {
+                    const num = +(canUseMoney / buymarginvalue).toFixed(0);
+                    // 买 最大可摘数量=min{挂牌数量,可用资金/(履约保证金比例)}
+                    result = Math.min(qty, num);
+                }
+            } else {
+                // 卖出 最大可摘数量=min{挂牌数量,仓单可用数量}
+                const id = formState.LadingBillId;
+                if (id) {
+                    const item = allWrHoldList.value.find((el) => el.ladingbillid === id)!;
+                    result = Math.min(qty, item.enableqty);
+                }
+            }
+            return result;
         }
-        function getMoney() {}
         function isBuy() {
             return props.buyOrSell === BuyOrSell.buy;
         }
+        // 是否部分摘牌
+        function isCanpart() {
+            return props.selectedRow.canpart === 1;
+        }
         // 是否议价 摘牌
         function isBargin() {
             return props.componentId === 'warehouse_receipt_trade_blocs_bargain_delisting';
         }
-        // 现货仓单
-        const { wrHoldList } = handleSpotWarrant(props.buyOrSell, props.selectedRow, loading);
+        if (isBargin()) {
+            formState.price = props.selectedRow.fixedprice;
+        }
+
         function submit() {
-            // const marketInfo = getMarketRunByTradeMode(17);
-            // if (marketInfo) {
-            //     validateAction<FormParam>(formRef, formState).then((res) => {
-            //         // 现在增加一种挂牌求购的情况
-            //         // 这种求购模式会生成一种仓单贸易商品
-            //         const wrGoodsInfo: WRGoodsInfo = {
-            //             GoodsID: props.selectedRow.goodsid, // uint32 配置商品ID
-            //             GoodsCode: props.selectedRow.goodscode, // string 配置商品代码
-            //             PriceFactor: 1, // double 商品价格系数
-            //             PriceMove: 0, // double 商品升贴水值
-            //             WeightRatio: 1, // double 商品重量系数
-            //         };
-            //         const param = {
-            //             AccountID: res.accountid, // 默认内部资金账号第一个
-            //             ClientSerialNo: uuidv4(), // 客户端流水号
-            //             // OperateSrc: 2,
-            //             ClientType: 4,
-            //             // MarketID: marketInfo.marketid,
-            //             LadingBillId: 0, // 提单id(wrholdlb的LadingBillId字段),卖的时候填写 uint64
-            //             // LadingBillId: 'uint642081626946446000001', // 提单id(wrholdlb的LadingBillId字段),卖的时候填写 uint64
-            //             TradeDate: moment(marketInfo.tradedate).format('YYYYMMDD'), // 交易日 string
-            //             // SubNum: '0', // 提单子单号
-            //             SubNum: 0,
-            //             // WRFactorTypeId: '2121626946446000001', // 仓单要素ID(wrholdlb的WRFactorTypeId字段),卖的时候填写 uint64
-            //             WRFactorTypeId: props.selectedRow.wrfactortypeid ? props.selectedRow.wrfactortypeid : 0, // 仓单要素ID(wrholdlb的WRFactorTypeId字段),卖的时候填写 uint64
-            //             IsSpecified: 0, // 是否指定对手 0:不指定 1:指定 uint32
-            //             // MatchUserIDs: 0, // 仓单贸易对手资金账号ID集合(指定对手时填写) uint32
-            //             OrderQty: res.OrderQty, // 委托数量(可挂部分数据量) ======
-            //             DeliveryGoodsID: props.selectedRow.deliverygoodsid, // 交割商品商品ID  // 有仓单求购
-            //             WRPriceType: isFloat() ? 2 : 1, // 价格方式 1:固定价 2:浮动价
-            //             FixedPrice: res.FixedPrice, // 固定价格
-            //             PriceFactor: 1, // 价格系数(浮动价时填写)
-            //             PriceMove: res.PriceMove, // 升贴水(浮动价时填写)
-            //             TimevalidType: 4, // 时间有效类型 1:当日有效 2:本周有效 3:指定时间有效 4:一直有效
-            //             // ValidTime: moment('2021-08-25 00:00:00').format('YYYY-MM-DD HH:mm:ss'), // 有效期限
-            //             ClientOrderTime: moment().format('YYYY-MM-DD HH:mm:ss'),
-            //             FirstRatio: 0, // 首付比例
-            //             PerformanceTemplateID: 0, // 履约计划模板ID
-            //             UserID: getUserId(),
-            //             OperatorID: getUserId(), // 操作员账号ID
-            //             BuyOrSell: 0, // 买卖方向 0买1卖
-            //             PriceDisplayMode: 1, // 浮动价显示方式 1:合并显示 2:分开显示
-            //             CanBargain: 0, // 挂牌是否可议价0:不可1:可-摘牌是否议价
-            //             Attachment1: '', // 附件1
-            //             Attachment2: '', // 附件2
-            //             Remark: '', // 备注
-            //             ApplyID: 0, // 申请ID
-            //             WRTradeGoods: isFloat() ? [wrGoodsInfo] : [],
-            //             CanPart: 1, // 是否允许部份摘牌0:不允许;1:允许
-            //             WRStandardID: props.selectedRow.wrstandardid,
-            //             HasWr: isWR(), // 无仓单挂牌  是否有无仓单
-            //             DeliveryMonth: isWR() ? '' : moment(res.DeliveryMonth).format('YYYY-MM'),
-            //             FactoryItems: props.selectedRow.wrResult != undefined ? props.selectedRow.wrResult.flatMap((it) => {
-            //                 return {
-            //                     DGFactoryItemTypeID: it.dgfactoryitemtypeid, // uint64 要素项类型ID
-            //                     DGFactoryItemID: it.dgfactoryitemid, // uint64 预约要素项类型值
-            //                     ItemTypeMode: 1, // uint32 要素项类型模式
-            //                 };
-            //             }): [], // DGFactoryItems 要素类型明细集合(没有仓单要素ID填写)
-            //         };
-            //         requestResultLoadingAndInfo(hdWROrder, param, loading, ['求购成功', '求购失败:']).then(() => {
-            //             cancel(true);
-            //         });
-            //     });
-            // }
+            validateAction<ListingForm>(formRef, formState).then((res) => {
+                if (isBargin()) {
+                    // 议价摘牌
+                    const param: WrBargainApplyReq = {
+                        WRTradeOrderID: Long.fromString(props.selectedRow.wrtradeorderid),
+                        ApplyQty: 10,
+                        UserID: String(getUserId()),
+                        AccountID: getSelectedAccountId().toString(),
+                        BuyOrSell: props.buyOrSell.toString(),
+                        ApplyPrice: formState.price.toString(),
+                        ApplyRemark: '',
+                    };
+                    requestResultLoadingAndInfo(wrBargainApply, param, loading, ['议价摘牌成功', '议价摘牌失败:']).then(() => {
+                        cancel(true);
+                    });
+                } else {
+                    // 首先确定  这是仓单贸易的有仓单挂摘牌 HasWr = 1
+                    // 其次判断  摘牌 1。摘买 (需要通过自己的仓单进行摘买)  2。摘卖 (不需要通过仓单)
+                    const param: HdWRDealOrderReq = {
+                        UserID: getUserId(), // uint32 用户ID
+                        AccountID: getSelectedAccountId(), // uint64 资金账号
+                        RelatedWRTradeOrderID: props.selectedRow.wrtradeorderid, // uint64 关联委托单号(摘牌委托关联挂牌委托单ID)
+                        WRTransferUserID: props.selectedRow.userid, // uint32 仓单受让用户
+                        OrderQty: res.num as number, // uint64 委托数量
+                        OrderSrc: 0, // uint32 委托来源
+                        ClientSerialNo: uuidv4(), // string 客户端流水号
+                        ClientOrderTime: moment(new Date()).format('YYYY-MM-DD HH:mm:ss'), // string 客户端委托时间
+                        ClientType: 4, // uint32 终端类型
+                        OperatorID: getUserId(), // uint64 操作员账号ID
+                        BuyOrSell: 0, // uint32 买卖方向
+                        ApplyID: 0, // uint64 申请ID
+                        // LadingBillId: 0, // uint64 提单id(wrholdlb的LadingBillId字段),卖的时候填写
+                        SubNum: 0, // uint64 提单子单号(wrholdlb的SubNum字段),卖的时候填写
+                        WRFactorTypeId: Long.fromString(props.selectedRow.wrfactortypeid), // uint64 仓单要素ID(wrholdlb的WRFactorTypeId字段),卖的时候填写
+                        TradeDate: moment().format('YYYYMMDD'), // string 交易日
+                        DeliveryMonth: '', // string 交收月
+                        HasWr: 1, // uint32 是否有仓单-0:没有仓单 1:有仓单
+                        IsFinancing: 0, // uint32 是否融资购买(买摘牌时有效)-0:否 1:是
+                        ProductDetailID: res.caseId, // uint64 金融机构产品组合ID(融资购买时有效)
+                    };
+                    // 摘买方向
+                    if (isBuy()) {
+                        param.BuyOrSell = 1;
+                        param.LadingBillId = res.LadingBillId;
+                    } else {
+                        param.BuyOrSell = 0;
+                    }
+
+                    requestResultLoadingAndInfo(HdWRDealOrder, param, loading, ['摘牌成功', '摘牌失败:']).then(() => {
+                        cancel(true);
+                    });
+                }
+            });
         }
         return {
             submit,
@@ -279,6 +325,9 @@ export default defineComponent({
             isBuy,
             isBargin,
             wrHoldList,
+            loading,
+            getMaxNum,
+            isCanpart,
         };
     },
 });

+ 1 - 0
src/views/market/spot_trade/warehouse_receipt_trade/warehouse_receipt_trade_blocs/components/delisting/interface.ts

@@ -1,5 +1,6 @@
 export interface ListingForm {
     accountid: undefined | number,
+    price: number,
     num: number,
     LadingBillId: string,
     case: string,

+ 6 - 2
src/views/market/spot_trade/warehouse_receipt_trade/warehouse_receipt_trade_blocs/components/delisting/setup.ts

@@ -12,6 +12,7 @@ export function handleForm() {
     const formRef = ref();
     const formState: UnwrapRef<ListingForm> = reactive({
         accountid: undefined,
+        price: 0,
         num: 0,
         LadingBillId: '',
         case: '',
@@ -21,7 +22,8 @@ export function handleForm() {
         accountid: [{ required: true, message: '请选择交易账户' }],
         LadingBillId: [{ required: true, message: '请选择现货仓单' }],
         caseId: [{ required: true, message: '请选择融资方案' }],
-        // num: [{ required: true, message: '请输入摘牌数量', trigger: 'blur', type: 'number', min: 1, ma: data.orderqty }],
+        num: [{ required: true, message: '请输入摘牌数量', trigger: 'blur', type: 'number', },
+        { min: 1, message: '请输入摘牌数量' }],
 
     }
     return { rules, formState, formRef }
@@ -30,8 +32,10 @@ export function handleForm() {
 
 export function handleSpotWarrant(buyOrSell: BuyOrSell, selectedRow: QueryOrderQuoteMyqQsp, loading: Ref<boolean>) {
     const wrHoldList = ref<Wrhold[]>([])
+    const allWrHoldList = ref<WrHoldLB[]>([])
     if (buyOrSell === BuyOrSell.sell) {
         queryResultLoadingAndInfo(queryHoldLB, loading).then(res => {
+            allWrHoldList.value = res
             wrHoldList.value = res.filter((e: WrHoldLB) => e.wrfactortypeid === String(selectedRow.wrfactortypeid)).map((e: WrHoldLB) => {
                 const { wrholdeno, enableqty, ladingbillid, enumdicname } = e
                 return { id: ladingbillid, name: `${wrholdeno}(${enableqty}${enumdicname})` }
@@ -39,5 +43,5 @@ export function handleSpotWarrant(buyOrSell: BuyOrSell, selectedRow: QueryOrderQ
         })
     }
 
-    return { wrHoldList }
+    return { wrHoldList, allWrHoldList }
 }

+ 0 - 0
src/views/market/spot_trade/warehouse_receipt_trade/warehouse_receipt_trade_blocs/components/detail/index.vue


+ 1 - 1
src/views/market/spot_trade/warehouse_receipt_trade/warehouse_receipt_trade_blocs/components/sell/index.vue

@@ -19,7 +19,7 @@
       </template>
       <!-- 整单 -->
       <template #canpart="{ text }">
-        <span>{{ text ? '是' : '否' }}</span>
+        <span>{{ text ? '否' : '是' }}</span>
       </template>
       <!-- 挂牌有效期 -->
       <template #validtime="{ text }">