li.shaoyi před 2 roky
rodič
revize
cf4462ecb7

+ 2 - 2
oem/tc/config/appconfig.json

@@ -1,8 +1,8 @@
 {
   "appId": "com.muchinfo.tc",
   "appName": "探茶",
-  "version": "1.0.0",
-  "versionCode": "100000",
+  "version": "1.0.1",
+  "versionCode": "100001",
   "apiUrl": "http://192.168.31.204:8080/cfg?key=test_204",
   "tradeChannel": "ws",
   "modules": [

+ 23 - 0
public/config/router.json

@@ -235,6 +235,29 @@
                         "component": "views/footer/capital/inoutapply/index.vue"
                     }
                 ]
+            },
+            {
+                "authType": 2,
+                "sort": 7,
+                "title": "持仓过户",
+                "code": "bottom_inout",
+                "component": "views/footer/index.vue",
+                "children": [
+                    {
+                        "authType": 2,
+                        "sort": 1,
+                        "title": "我的转入",
+                        "code": "bottom_inout_in",
+                        "component": "views/footer/inout/in/index.vue"
+                    },
+                    {
+                        "authType": 2,
+                        "sort": 2,
+                        "title": "我的转出",
+                        "code": "bottom_inout_out",
+                        "component": "views/footer/inout/out/index.vue"
+                    }
+                ]
             }
         ]
     },

+ 141 - 0
public/proto/mtp.js

@@ -5081,6 +5081,10 @@ var $root = ($protobuf.roots["default"] || ($protobuf.roots["default"] = new $pr
       ClientTicket: {
         type: "string",
         id: 11
+      },
+      TransferType: {
+        type: "uint32",
+        id: 12
       }
     }
   },
@@ -8673,6 +8677,143 @@ var $root = ($protobuf.roots["default"] || ($protobuf.roots["default"] = new $pr
       }
     }
   },
+  HolderTransferDetail: {
+    fields: {
+      OutLoginID: {
+        type: "uint32",
+        id: 1
+      },
+      InLoginID: {
+        type: "uint32",
+        id: 2
+      },
+      GoodsID: {
+        type: "uint32",
+        id: 3
+      },
+      BuyOrSell: {
+        type: "uint32",
+        id: 4
+      },
+      Qty: {
+        type: "uint64",
+        id: 5
+      },
+      TransferPrice: {
+        type: "double",
+        id: 6
+      },
+      FreezeDays: {
+        type: "uint32",
+        id: 7
+      },
+      TransferType: {
+        type: "uint32",
+        id: 8
+      },
+      OutAccountID: {
+        type: "uint64",
+        id: 9
+      },
+      InAccountID: {
+        type: "uint64",
+        id: 10
+      },
+      ApplyID: {
+        type: "uint64",
+        id: 11
+      }
+    }
+  },
+  HolderTransferApplyReq: {
+    fields: {
+      Header: {
+        type: "MessageHead",
+        id: 1
+      },
+      HolderTransferDetails: {
+        rule: "repeated",
+        type: "HolderTransferDetail",
+        id: 2
+      },
+      ClientSerialNo: {
+        type: "string",
+        id: 3
+      },
+      ClientType: {
+        type: "uint32",
+        id: 4
+      }
+    }
+  },
+  HolderTransferApplyRsp: {
+    fields: {
+      Header: {
+        type: "MessageHead",
+        id: 1
+      },
+      RetCode: {
+        type: "int32",
+        id: 2
+      },
+      RetDesc: {
+        type: "string",
+        id: 3
+      },
+      ClientSerialNo: {
+        type: "string",
+        id: 4
+      }
+    }
+  },
+  HolderTransferConfirmReq: {
+    fields: {
+      Header: {
+        type: "MessageHead",
+        id: 1
+      },
+      ApplyID: {
+        type: "uint64",
+        id: 2
+      },
+      UserID: {
+        type: "uint32",
+        id: 3
+      },
+      ClientSerialNo: {
+        type: "string",
+        id: 4
+      },
+      ClientType: {
+        type: "uint32",
+        id: 5
+      }
+    }
+  },
+  HolderTransferConfirmRsp: {
+    fields: {
+      Header: {
+        type: "MessageHead",
+        id: 1
+      },
+      RetCode: {
+        type: "int32",
+        id: 2
+      },
+      RetDesc: {
+        type: "string",
+        id: 3
+      },
+      ApplyID: {
+        type: "uint64",
+        id: 4
+      },
+      ClientSerialNo: {
+        type: "string",
+        id: 5
+      }
+    }
+  },
   SubCommand: {
     fields: {
       CommandCode: {

+ 48 - 3
public/proto/mtp.proto

@@ -1532,6 +1532,7 @@ message ManageProtoTransferReq {
 		optional double HoldPrice = 9; // 持仓价格[所有权]
 		optional uint32 FreezeDays = 10; // 冻结天数
 		optional string ClientTicket = 11; // 客户端流水号
+		optional uint32 TransferType = 12; // 转让类型-1.协议转让
 }
 // 管理端协议转让响应
 message ManageProtoTransferRsp {
@@ -2641,12 +2642,12 @@ message DefaultTransferProcessReq {
 		optional uint64 AccountID = 3; // 交易账号,必填
 		optional uint32 GoodsID = 4; // 商品ID,必填
 		optional uint32 ReceiverUserID = 5; // 转入方用户ID,必填
-		optional uint64 ReceiverAccountID = 6; // 接收方账号ID,必填
-		optional double Amount = 7; // 接收方支付金额,两位小数,可正可负可0,必填
+		optional uint64 ReceiverAccountID = 6; // 转入方账号ID,必填
+		optional double Amount = 7; // 转入方支付金额,两位小数,可正可负可0,必填
 		optional string ClientSerialNo = 8; // 客户端流水号
 		optional uint32 ClientType = 9; // 终端类型
 }
-// 违约转让处理接口请求
+// 违约转让处理接口响应
 message DefaultTransferProcessRsp {
 	optional MessageHead Header = 1; // 消息头
 	optional int32 RetCode = 2; // 返回码
@@ -2656,6 +2657,50 @@ message DefaultTransferProcessRsp {
 		optional uint32 GoodsID = 6; // 商品ID,必填
 		optional string ClientSerialNo = 7; // 客户端流水号
 }
+// 持仓过户明细
+message HolderTransferDetail {
+		optional uint32 OutLoginID = 1; // 转出方登录账号,必填
+		optional uint32 InLoginID = 2; // 转入方登录账号,必填
+		optional uint32 GoodsID = 3; // 商品ID,必填
+		optional uint32 BuyOrSell = 4; // 转出方买卖方向,必填
+		optional uint64 Qty = 5; // 转让数量,必填
+		optional double TransferPrice = 6; // 转让价格,必填
+		optional uint32 FreezeDays = 7; // 冻结天数
+		optional uint32 TransferType = 8; // 转让类型-1.协议转让
+		optional uint64 OutAccountID = 9; // 转出方资金帐号,内部使用,不需要填写
+		optional uint64 InAccountID = 10; // 转入方资金帐号,内部使用,不需要填写
+		optional uint64 ApplyID = 11; // 申请单号,内部使用,不需要填写
+}
+// 持仓过户申请接口请求
+message HolderTransferApplyReq {
+	optional MessageHead Header = 1;
+		repeated HolderTransferDetail HolderTransferDetails = 2; // 持仓过户明细,必填
+		optional string ClientSerialNo = 3; // 客户端流水号
+		optional uint32 ClientType = 4; // 终端类型
+}
+// 持仓过户申请接口响应
+message HolderTransferApplyRsp {
+	optional MessageHead Header = 1; // 消息头
+	optional int32 RetCode = 2; // 返回码
+	optional string RetDesc = 3; // 描述信息
+		optional string ClientSerialNo = 4; // 客户端流水号
+}
+// 持仓过户确认接口请求
+message HolderTransferConfirmReq {
+	optional MessageHead Header = 1;
+		optional uint64 ApplyID = 2; // 申请ID,必填
+		optional uint32 UserID = 3; // 用户ID,必填
+		optional string ClientSerialNo = 4; // 客户端流水号
+		optional uint32 ClientType = 5; // 终端类型
+}
+// 持仓过户确认接口响应
+message HolderTransferConfirmRsp {
+	optional MessageHead Header = 1; // 消息头
+	optional int32 RetCode = 2; // 返回码
+	optional string RetDesc = 3; // 描述信息
+		optional uint64 ApplyID = 4; // 申请ID,必填
+		optional string ClientSerialNo = 5; // 客户端流水号
+}
 // 账户操作子指令
 message SubCommand {
 		optional uint32 CommandCode = 1; // 子指令操作码

+ 5 - 0
src/constants/funcode.ts

@@ -130,4 +130,9 @@ export enum FunCode {
     DeliveryClientOperatorRsp = 196744, // 交收终端操作接口响应
     OfflineDeliveryApplyCancelOrderReq = 196745,    // MAKE_FID(0, 3, 137)  线下交收申请撤销接口请求(196745)
     OfflineDeliveryApplyCancelOrderRsp = 196746,   // MAKE_FID(0, 3, 138) // 线下交收申请撤销接口响应(196746)
+
+    HolderTransferApplyReq = 196751, // 持仓过户申请接口请求
+    HolderTransferApplyRsp = 196752, // 持仓过户申请接口响应
+    HolderTransferConfirmReq = 196753, // 持仓过户确认接口请求
+    HolderTransferConfirmRsp = 196754, // 持仓过户确认接口响应
 } 

+ 1 - 1
src/packages/mobile/views/bank/sign/components/edit/Index.vue

@@ -162,7 +162,7 @@ const formSubmit = () => {
         if (CenterErrMsg.value != '') {
             obj['smsSerialNo'] = CenterErrMsg.value
         }
-        formData.extend_info = JSON.stringify(obj)
+        formData.extendInfo = JSON.stringify(obj)
 
         onSubmit().then(() => {
             hideLoading()

+ 1 - 1
src/packages/mobile/views/bank/wallet/components/deposit/Index.vue

@@ -153,7 +153,7 @@ const formSubmit = () => {
             }
         })
         obj['certificate_photo_url'] = certificate_photo_url.value
-        formData.extend_info = JSON.stringify(obj)
+        formData.extendInfo = JSON.stringify(obj)
 
         let isComplete = false // 请求是否结束
         const complete = () => {

+ 1 - 1
src/packages/mobile/views/bank/wallet/components/withdraw/Index.vue

@@ -109,7 +109,7 @@ const formSubmit = () => {
             obj[e.fieldcode] = e.value
         }
     })
-    formData.extend_info = JSON.stringify(obj)
+    formData.extendInfo = JSON.stringify(obj)
     fullloading((hideLoading) => {
         let isComplete = false // 请求是否结束
         const complete = () => {

+ 1 - 1
src/packages/pc/components/layouts/page/index.vue

@@ -122,7 +122,7 @@ const footerStyles = computed(() => {
     }
     default: {
       return {
-        height: '360px'
+        height: '380px'
       }
     }
   }

+ 1 - 1
src/packages/pc/components/modules/quote/chart/kline/index.less

@@ -34,7 +34,7 @@
     }
 
     &__indicator {
-        height: 30%;
+        height: 38%;
 
         .app-tabs__container {
             overflow: hidden;

+ 1 - 1
src/packages/pc/views/account/sign/components/sign/index.vue

@@ -160,7 +160,7 @@ const formSubmit = () => {
                 if (CenterErrMsg.value != '') {
                     obj['smsSerialNo'] = CenterErrMsg.value
                 }
-                formData.extend_info = JSON.stringify(obj)
+                formData.extendInfo = JSON.stringify(obj)
 
                 onSubmit().then(() => {
                     ElMessage.success(bankInfo.value?.signstatus != undefined ? '签约信息修改成功' : '签约提交成功,请耐心等待审核。')

+ 1 - 1
src/packages/pc/views/footer/capital/summary/deposit/index.vue

@@ -107,7 +107,7 @@ const formSubmit = () => {
                     }
                 })
                 obj['certificate_photo_url'] = certificate_photo_url.value
-                formData.extend_info = JSON.stringify(obj)
+                formData.extendInfo = JSON.stringify(obj)
 
                 let isComplete = false // 请求是否结束
                 const complete = () => {

+ 1 - 1
src/packages/pc/views/footer/capital/summary/withdraw/index.vue

@@ -105,7 +105,7 @@ const formSubmit = () => {
                     formData.BranchBankName = e.value
                 }
             })
-            formData.extend_info = JSON.stringify(obj)
+            formData.extendInfo = JSON.stringify(obj)
             if (formData.CusBankID) {
                 let isComplete = false // 请求是否结束
                 const complete = () => {

+ 1 - 0
src/packages/pc/views/footer/goods/detail/index.vue

@@ -54,6 +54,7 @@ const tableColumns = shallowRef<Model.TableColumn[]>([
     { prop: 'goodsname', label: '商品' },
     { prop: 'buyorsell', label: '方向' },
     { prop: 'holderqty', label: '持仓数量' },
+    { prop: 'freezeqty', label: '冻结数量' },
     { prop: 'holderprice', label: '持仓价格' },
     { prop: 'holderamount', label: '持仓金额' },
     { prop: 'tradeid', label: '成交单号' },

+ 70 - 0
src/packages/pc/views/footer/inout/in/index.vue

@@ -0,0 +1,70 @@
+<!-- 持仓过户-我的转入 -->
+<template>
+    <app-table :data="dataList" v-model:columns="tableColumns">
+        <!-- 挂牌类型 -->
+        <template #buyorsell="{ value }">
+            {{ getBuyOrSellName(value) }}
+        </template>
+        <!-- 最新价 -->
+        <template #lastprice="{ row }">
+            <span :class="row.lastColor">
+                {{ handleNumberValue(formatDecimal(row.lastprice, row.decimalplace)) }}
+            </span>
+        </template>
+        <!-- 市值-->
+        <template #marketValue="{ value }">
+            {{ formatDecimal(value) }}
+        </template>
+        <!-- 浮动盈亏-->
+        <template #closepl="{ row }">
+            <span :class="row.closeplColor">{{ formatDecimal(row.closepl, row.decimalplace) }}</span>
+        </template>
+        <!-- 操作 -->
+        <template #operate="{ row }">
+            <app-auth-operation :code="code" :menus="handleOperateButtons(row)" :options="{ selectedRow: row }" />
+        </template>
+    </app-table>
+</template>
+
+<script lang="ts" setup>
+import { shallowRef } from 'vue'
+import { handleNumberValue, formatDecimal } from '@/filters'
+import { getBuyOrSellName } from '@/constants/order'
+import { useRequest } from '@/hooks/request'
+import { queryInTradePositionTransfer } from '@/services/api/transfer'
+import AppTable from '@pc/components/base/table/index.vue'
+import AppAuthOperation from '@pc/components/modules/auth-operation/index.vue'
+
+defineProps({
+    code: String
+})
+
+const { dataList } = useRequest(queryInTradePositionTransfer)
+
+const tableColumns = shallowRef<Model.TableColumn[]>([
+    { prop: 'goodsname', label: '订单合约' },
+    { prop: 'buyorsell', label: '方向' },
+    { prop: 'curpositionqty', label: '持有数量' },
+    { prop: 'enableqty', label: '可用数量' },
+    { prop: 'frozenqty', label: '预扣数量' },
+    { prop: 'averageprice', label: '均价' },
+    { prop: 'lastprice', label: '现价' },
+    { prop: 'curholderamount', label: '持仓金额' },
+    { prop: 'marketValue', label: '市值' },
+    { prop: 'closepl', label: '参考损益' },
+    { prop: 'operate', label: '操作', fixed: 'right', width: 140 },
+])
+
+const handleOperateButtons = (row: Model.TradePositionRsp) => {
+    const buttons = ['bottom_goods_position_transfer']
+    switch (row.trademode) {
+        case 16:
+            buttons.push('bottom_goods_position_delivery16')
+            break;
+        case 50:
+            buttons.push('bottom_goods_position_delivery50')
+            break;
+    }
+    return buttons
+}
+</script>

+ 127 - 0
src/packages/pc/views/footer/inout/out/add/index.vue

@@ -0,0 +1,127 @@
+<!-- 持仓过户-我的转入-新增 -->
+<template>
+    <app-drawer title="新增" v-model:show="show" :width="800" :loading="loading" :refresh="refresh">
+        <el-form ref="formRef" class="el-form--horizontal" label-width="100px" :model="formData" :rules="formRules"
+            @submit.prevent>
+            <el-form-item prop="InLoginID" label="转入客户">
+                <el-select placeholder="请输入" v-model="formData.InLoginID" :loading="searchLoading"
+                    :remote-method="remoteMethod" filterable remote clearable>
+                    <template v-for="(item, index) in userList" :key="index">
+                        <el-option :label="item.customername" :value="item.userid" />
+                    </template>
+                </el-select>
+            </el-form-item>
+            <el-form-item prop="GoodsID" label="转让商品">
+                <el-select placeholder="请选择" v-model="selectedGoods" value-key="goodsid">
+                    <template v-for="(item, index) in goodsList" :key="index">
+                        <el-option :label="`${item.goodscode}/${item.goodsname}`" :value="item" />
+                    </template>
+                </el-select>
+            </el-form-item>
+            <el-form-item prop="TransferPrice" label="转让价格">
+                <el-input-number placeholder="请输入" v-model="formData.TransferPrice" />
+            </el-form-item>
+            <el-form-item prop="Qty" label="转让数量">
+                <el-input-number placeholder="请输入" v-model="formData.Qty" />
+            </el-form-item>
+            <el-form-item prop="FreezeDays" label="冻结天数">
+                <el-input-number placeholder="请输入" v-model="formData.FreezeDays" />
+            </el-form-item>
+            <el-form-item label="可用数量">
+                <span>0</span>
+            </el-form-item>
+        </el-form>
+        <template #footer>
+            <el-button type="info" @click="onCancel(false)">取消</el-button>
+            <el-button type="primary" @click="onCancelSumit()">提交</el-button>
+        </template>
+    </app-drawer>
+</template>
+
+<script lang="ts" setup>
+import { shallowRef, reactive, computed } from 'vue'
+import { FormInstance, FormRules, ElMessage } from 'element-plus'
+import { BuyOrSell } from '@/constants/order'
+import { useRequest } from '@/hooks/request'
+import { holderTransferApply } from '@/services/api/trade'
+import { getUserInfo } from '@/services/api/user'
+import { usePosition } from '@/business/position'
+import AppDrawer from '@pc/components/base/drawer/index.vue'
+
+const { positionList } = usePosition(16)
+const formRef = shallowRef<FormInstance>()
+const loading = shallowRef(false)
+const show = shallowRef(true)
+const refresh = shallowRef(false)
+
+// 可用商品列表
+const goodsList = computed(() => positionList.value.filter((e) => e.enableqty > 0))
+// 选中的商品
+const selectedGoods = shallowRef<Model.TradePositionRsp>()
+
+const formData = reactive<Partial<Proto.HolderTransferDetail>>({
+    OutLoginID: 0, // 转出方登录账号,必填
+    BuyOrSell: BuyOrSell.Buy, // 转出方买卖方向,必填
+    TransferType: 1, // 转让类型-1.协议转让
+})
+
+const formRules: FormRules = {
+    goodsId: [{
+        required: true,
+        message: '请选择委托商品'
+    }],
+    price: [{
+        required: true,
+        validator: (rule, value, callback) => {
+            if (value) {
+                callback()
+            } else {
+                callback(new Error('请输入撤销价格'))
+            }
+        }
+    }]
+}
+
+const { loading: searchLoading, dataList: userList, run: searchUser } = useRequest(getUserInfo, {
+    manual: true
+})
+
+// 远程搜索转入客户
+const remoteMethod = (query: string) => {
+    if (query) {
+        searchUser({
+            param: query
+        })
+    }
+}
+
+const onCancel = (isRefresh = false) => {
+    show.value = false
+    refresh.value = isRefresh
+}
+
+const onCancelSumit = () => {
+    formRef.value?.validate(async (valid) => {
+        if (valid) {
+            const { marketid, goodsid } = selectedGoods.value ?? {}
+            formData.GoodsID = goodsid
+            loading.value = true
+            holderTransferApply({
+                data: {
+                    Header: {
+                        MarketID: marketid
+                    },
+                    HolderTransferDetails: [formData]
+                }
+            }).then(() => {
+                ElMessage.success('提交成功')
+                onCancel(true)
+            }).catch((err) => {
+                ElMessage.error('提交失败:' + err)
+            }).finally(() => {
+                loading.value = false
+            })
+        }
+    })
+}
+</script>

+ 83 - 0
src/packages/pc/views/footer/inout/out/index.vue

@@ -0,0 +1,83 @@
+<!-- 持仓过户-我的转入 -->
+<template>
+    <app-table :data="dataList" v-model:columns="tableColumns">
+        <template #headerRight>
+            <div class="buttonbar">
+                <el-button type="primary" size="small" @click="openComponent('add')">新增</el-button>
+            </div>
+        </template>
+        <!-- 挂牌类型 -->
+        <template #buyorsell="{ value }">
+            {{ getBuyOrSellName(value) }}
+        </template>
+        <!-- 最新价 -->
+        <template #lastprice="{ row }">
+            <span :class="row.lastColor">
+                {{ handleNumberValue(formatDecimal(row.lastprice, row.decimalplace)) }}
+            </span>
+        </template>
+        <!-- 市值-->
+        <template #marketValue="{ value }">
+            {{ formatDecimal(value) }}
+        </template>
+        <!-- 浮动盈亏-->
+        <template #closepl="{ row }">
+            <span :class="row.closeplColor">{{ formatDecimal(row.closepl, row.decimalplace) }}</span>
+        </template>
+        <!-- 操作 -->
+        <template #footer>
+            <component ref="componentRef" :is="componentMap.get(componentId)" @closed="closeComponent" v-if="componentId" />
+        </template>
+    </app-table>
+</template>
+
+<script lang="ts" setup>
+import { shallowRef, defineAsyncComponent } from 'vue'
+import { handleNumberValue, formatDecimal } from '@/filters'
+import { getBuyOrSellName } from '@/constants/order'
+import { useComponent } from '@/hooks/component'
+import { useRequest } from '@/hooks/request'
+import { queryOutTradepositiontransfer } from '@/services/api/transfer'
+import AppTable from '@pc/components/base/table/index.vue'
+
+defineProps({
+    code: String
+})
+
+const componentMap = new Map<string, unknown>([
+    ['add', defineAsyncComponent(() => import('./add/index.vue'))], // 新增
+])
+
+const { componentRef, componentId, openComponent, closeComponent } = useComponent(() => {
+    run()
+})
+
+const { dataList, run } = useRequest(queryOutTradepositiontransfer)
+
+const tableColumns = shallowRef<Model.TableColumn[]>([
+    { prop: 'goodsname', label: '订单合约' },
+    { prop: 'buyorsell', label: '方向' },
+    { prop: 'curpositionqty', label: '持有数量' },
+    { prop: 'enableqty', label: '可用数量' },
+    { prop: 'frozenqty', label: '预扣数量' },
+    { prop: 'averageprice', label: '均价' },
+    { prop: 'lastprice', label: '现价' },
+    { prop: 'curholderamount', label: '持仓金额' },
+    { prop: 'marketValue', label: '市值' },
+    { prop: 'closepl', label: '参考损益' },
+    { prop: 'operate', label: '操作', fixed: 'right', width: 140 },
+])
+
+const handleOperateButtons = (row: Model.TradePositionRsp) => {
+    const buttons = ['bottom_goods_position_transfer']
+    switch (row.trademode) {
+        case 16:
+            buttons.push('bottom_goods_position_delivery16')
+            break;
+        case 50:
+            buttons.push('bottom_goods_position_delivery50')
+            break;
+    }
+    return buttons
+}
+</script>

+ 32 - 8
src/packages/pc/views/market/trade/goods/list/listing/index.vue

@@ -5,7 +5,7 @@
         </div>
         <div class="goods-listing__form">
             <h4 class="header-title">订单交易</h4>
-            <el-form ref="formRef" class="el-form--vertical" label-width="60px" :model="formData" :rules="formRules">
+            <el-form ref="formRef" class="el-form--vertical" label-width="60px" :show-message="false" :model="formData" :rules="formRules">
                 <el-form-item prop="GoodsID" label="商品">
                     <el-select placeholder="请选择" v-model="selectedGoodsId" filterable>
                         <el-option :label="item.goodsname" :value="item.goodsid" v-for="(item, index) in marketGoodsList"
@@ -44,8 +44,10 @@
                         <el-radio-group size="small" v-model="qtyStep" :validate-event="false" @change="onRadioChange">
                             <el-radio v-for="(value, index) in qtyStepList" :key="index" :label="value" border />
                         </el-radio-group>
-                        <div style="line-height: 1;font-size: 12px;color: #7a8a94;"
-                            v-if="settingStore.getSettingValue('showOrderEnableQty')">预估可订立量:{{ enableQty }}
+                        <div style="display: flex;flex-direction: column;line-height: normal;font-size: 12px;color: #7a8a94;"
+                            v-if="settingStore.getSettingValue('showOrderEnableQty')">
+                            <span>预估可订立量:{{ total.enableQty }}</span>
+                            <span>预扣保证金:{{ total.deposit.toFixed(2) }}</span>
                         </div>
                     </div>
                 </el-form-item>
@@ -114,23 +116,45 @@ const priceStep = computed(() => {
     return 1
 })
 
-// 订立可用数量
-const enableQty = computed(() => {
+const deposit = computed(() => {
+    const { marketmarginalgorithm = 0, marketmarginvalue = 0, agreeunit = 0 } = selectedGoods.value ?? {}
+
+    const fixed = agreeunit * marketmarginvalue
+    const ratio = fixed * (formData.OrderPrice ?? 0)
+
+    if (marketmarginalgorithm === 1) {
+        return (formData.OrderQty ?? 0) * ratio
+    }
+    if (marketmarginalgorithm === 2) {
+        return (formData.OrderQty ?? 0) * fixed
+    }
+
+    return 0
+})
+
+const total = computed(() => {
     const { avaiableMoney = 0 } = accountStore.currentAccount
     const { marketmarginalgorithm = 0, marketmarginvalue = 0, agreeunit = 0 } = selectedGoods.value ?? {}
 
+    const result = {
+        enableQty: 0,
+        deposit: 0
+    }
+
     const fixed = agreeunit * marketmarginvalue
     const ratio = fixed * (formData.OrderPrice ?? 0)
 
     if (fixed && ratio) {
         if (marketmarginalgorithm === 1) {
-            return Math.trunc(avaiableMoney / ratio) || 0
+            result.deposit = (formData.OrderQty ?? 0) * ratio || 0
+            result.enableQty = Math.trunc(avaiableMoney / ratio) || 0
         }
         if (marketmarginalgorithm === 2) {
-            return Math.trunc(avaiableMoney / fixed) || 0
+            result.deposit = (formData.OrderQty ?? 0) * fixed || 0
+            result.enableQty = Math.trunc(avaiableMoney / fixed) || 0
         }
     }
-    return 0
+    return result
 })
 
 // 买方向持仓数量

+ 31 - 0
src/services/api/trade/index.ts

@@ -353,4 +353,35 @@ export function offlineDeliveryApplyCancelOrder(config: RequestConfig<Partial<Pr
         requestCode: 'OfflineDeliveryApplyCancelOrderReq',
         responseCode: 'OfflineDeliveryApplyCancelOrderRsp',
     })
+}
+
+/**
+ * 持仓过户申请接口
+ */
+export function holderTransferApply(config: RequestConfig<Proto.HolderTransferApplyReq>) {
+    return http.mqRequest<Proto.HolderTransferApplyRsp>({
+        data: {
+            ClientSerialNo: v4(),
+            ClientType: ClientType.Web,
+            ...config.data
+        },
+        requestCode: 'HolderTransferApplyReq',
+        responseCode: 'HolderTransferApplyRsp',
+    })
+}
+
+/**
+ * 持仓过户确认接口
+ */
+export function holderTransferConfirm(config: RequestConfig<Proto.HolderTransferConfirmReq>) {
+    return http.mqRequest<Proto.HolderTransferConfirmRsp>({
+        data: {
+            UserID: loginStore.userId,
+            ClientSerialNo: v4(),
+            ClientType: ClientType.Web,
+            ...config.data
+        },
+        requestCode: 'HolderTransferConfirmReq',
+        responseCode: 'HolderTransferConfirmRsp',
+    })
 }

+ 26 - 0
src/services/api/transfer/index.ts

@@ -101,4 +101,30 @@ export function queryMineTradeGoodsDeliveryOfflines(config: RequestConfig<Model.
             ...config.data
         },
     })
+}
+
+/**
+ * 获取持仓过户申请表信息 - 我的转入
+ */
+export function queryInTradePositionTransfer(config: RequestConfig<Model.InTradePositionTransferReq> = {}) {
+    return http.commonRequest<Model.InTradePositionTransferRsp[]>({
+        url: '/Zhongrong/QueryInTradePositionTransfer',
+        params: {
+            userid: loginStore.userId,
+            ...config.data
+        },
+    })
+}
+
+/**
+ * 获取持仓过户申请表信息 - 我的转出
+ */
+export function queryOutTradepositiontransfer(config: RequestConfig<Model.OutTradepositiontransferReq> = {}) {
+    return http.commonRequest<Model.OutTradepositiontransferRsp[]>({
+        url: '/Zhongrong/QueryOutTradepositiontransfer',
+        params: {
+            userid: loginStore.userId,
+            ...config.data
+        },
+    })
 }

+ 10 - 0
src/services/api/user/index.ts

@@ -105,4 +105,14 @@ export function updateUserHeadUrl(config: RequestConfig<Model.UserHeadUrlReq> =
         url: '/User/UpdateUserHeadUrl',
         data: config.data,
     })
+}
+
+/**
+ * 登录账号、手机号精确查询用户
+ */
+export function getUserInfo(config: RequestConfig<Model.UserInfoReq> = {}) {
+    return http.commonRequest<Model.UserInfoRsp[]>({
+        url: '/Zhongrong/GetUserInfo',
+        params: config.data
+    })
 }

+ 0 - 1
src/types/model/common.d.ts

@@ -1,5 +1,4 @@
 import { AuthType, UrlType } from '@/constants/enum/menu'
-import { NumberFormatResult } from 'vue-i18n';
 
 declare global {
     namespace Model {

+ 102 - 0
src/types/model/transfer.d.ts

@@ -326,4 +326,106 @@ declare namespace Model {
         reqtradedate: string; // 申请交易日
         userid: number; // 申请用户ID
     }
+
+    /** 获取持仓过户申请表信息 - 我的转入 请求 */
+    interface InTradePositionTransferReq {
+        userid?: number; // 用户ID
+        page?: number; // 页码
+        pagesize?: number; // 每页条数
+    }
+
+    /** 获取持仓过户申请表信息 - 我的转入 响应 */
+    interface InTradePositionTransferRsp {
+        applicantid: number; // 申请人ID
+        applyid: number; // 申请ID(185+Unix秒时间戳(10位)+2位(MarketServiceID)+xxxx)
+        applyremark: string; // 申请备注
+        applystatus: string; // 状态
+        applytime: string; // 申请时间
+        auditorid: number; // 审核人
+        auditremark: string; // 审核备注
+        audittime: string; // 审核时间
+        buyorsell: number; // 买卖 - 0:买 1:卖
+        clientticket: string; // 客户端流水号
+        closeexchagechargevalue: number; // 平仓交易所手续费设置值(转出方)
+        closefeealgorithm: number; // 平仓手续费收取方式(转出方) 1:比率 2:固定
+        closememberchargevalue: number; // 平仓会员手续费设置值(转出方)
+        confirmdate: string; // 确认时间
+        freezedays: number; // 冻结天数(T+N)
+        goodscuramount: number; // 商品实时价金额
+        goodscurprice: number; // 商品实时价格
+        goodsdisplay: string; // 商品名称
+        goodsid: number; // 商品ID
+        inaccountid: number; // 转入方资金ID(确认方)
+        incharge: number; // 转入方手续费
+        inloginid: number; // 转入方登录账号
+        inuserid: number; // 转入方用户ID(确认方)
+        marketid: number; // 市场ID
+        openexchagechargevalue: number; // 建仓交易所手续费设置值
+        openfeealgorithm: number; // 建仓手续费收取方式 1:比率 2:固定
+        openmemberchargevalue: number; // 建仓会员手续费设置值
+        outaccountid: number; // 转出方资金ID(申请方)
+        outcharge: number; // 转出方手续费
+        outloginid: number; // 转出方登录账号
+        outuserid: number; // 转出方用户ID(申请方)
+        outusername: string; // 转出方
+        qty: number; // 转让数量
+        retcode: number; // 错误代码
+        retremark: string; // 返回信息
+        tradedate: string; // 交易日
+        transferamount: number; // 转让总金额
+        transferapplystatus: number; // 过户申请状态 - 1: 待审核 2:待确认 3:确认处理中 4:已确认 5:申请失败 6:系统撤销 7:审核拒绝- 枚举"transferapplystatus"
+        transferprice: number; // 转让价格
+        transfertype: number; // 转让类型 - 1.协议转让
+    }
+
+    /** 获取持仓过户申请表信息 - 我的转出 请求 */
+    interface OutTradepositiontransferReq {
+        userid?: number; // 用户ID
+        page?: number; // 页码
+        pagesize?: number; // 每页条数
+    }
+
+    /** 获取持仓过户申请表信息 - 我的转出 响应 */
+    interface OutTradepositiontransferRsp {
+        applicantid: number; // 申请人ID
+        applyid: number; // 申请ID(185+Unix秒时间戳(10位)+2位(MarketServiceID)+xxxx)
+        applyremark: string; // 申请备注
+        applystatus: string; // 状态
+        applytime: string; // 申请时间
+        auditorid: number; // 审核人
+        auditremark: string; // 审核备注
+        audittime: string; // 审核时间
+        buyorsell: number; // 买卖 - 0:买 1:卖
+        clientticket: string; // 客户端流水号
+        closeexchagechargevalue: number; // 平仓交易所手续费设置值(转出方)
+        closefeealgorithm: number; // 平仓手续费收取方式(转出方) 1:比率 2:固定
+        closememberchargevalue: number; // 平仓会员手续费设置值(转出方)
+        confirmdate: string; // 确认时间
+        freezedays: number; // 冻结天数(T+N)
+        goodscuramount: number; // 商品实时价金额
+        goodscurprice: number; // 商品实时价格
+        goodsdisplay: string; // 商品名称
+        goodsid: number; // 商品ID
+        inaccountid: number; // 转入方资金ID(确认方)
+        incharge: number; // 转入方手续费
+        inloginid: number; // 转入方登录账号
+        inuserid: number; // 转入方用户ID(确认方)
+        inusername: string; // 转入方
+        marketid: number; // 市场ID
+        openexchagechargevalue: number; // 建仓交易所手续费设置值
+        openfeealgorithm: number; // 建仓手续费收取方式 1:比率 2:固定
+        openmemberchargevalue: number; // 建仓会员手续费设置值
+        outaccountid: number; // 转出方资金ID(申请方)
+        outcharge: number; // 转出方手续费
+        outloginid: number; // 转出方登录账号
+        outuserid: number; // 转出方用户ID(申请方)
+        qty: number; // 转让数量
+        retcode: number; // 错误代码
+        retremark: string; // 返回信息
+        tradedate: string; // 交易日
+        transferamount: number; // 转让总金额
+        transferapplystatus: number; // 过户申请状态 - 1: 待审核 2:待确认 3:确认处理中 4:已确认 5:申请失败 6:系统撤销 7:审核拒绝- 枚举"transferapplystatus"
+        transferprice: number; // 转让价格
+        transfertype: number; // 转让类型 - 1.协议转让
+    }
 }

+ 11 - 0
src/types/model/user.d.ts

@@ -118,4 +118,15 @@ declare namespace Model {
         // 用户ID
         userid: number
     }
+
+    /** 登录账号、手机号精确查询用户 请求 */
+    interface UserInfoReq {
+        param: string; // 登录账号或手机号
+    }
+
+    /** 登录账号、手机号精确查询用户 响应 */
+    interface UserInfoRsp {
+        customername: string; // 客户名称
+        userid: number; // 用户ID
+    }
 }

+ 3 - 3
src/types/proto/bank.d.ts

@@ -37,7 +37,7 @@ declare global {
             MobilePhone: string; // 移动电话
             IdentifyCode: string; // 验证码
             email: string; // 电子邮箱
-            extend_info: string; // 扩展信息(JSON串,参考配置要求进行填充)
+            extendInfo: string; // 扩展信息(JSON串,参考配置要求进行填充)
         }
 
         /** 签约应答 */
@@ -114,7 +114,7 @@ declare global {
             Desc: string; // 备注
             IdentifyCode: string; // 验证码
             BranchBankName: string; // 收款支行名称
-            extend_info: string; // 扩展信息(JSON串,参考配置要求进行填充)
+            extendInfo: string; // 扩展信息(JSON串,参考配置要求进行填充)
             Remark: string; // 备注
             ExchTicket: string; // 交易所流水号
         }
@@ -155,7 +155,7 @@ declare global {
             OpenCardBankId: string; // 银行卡行号
             BankAccoutNum: string; // 银行卡号
             BankAccoutName: string; // 银行卡户名
-            extend_info: string; // 扩展信息(JSON串,参考配置要求进行填充)
+            extendInfo: string; // 扩展信息(JSON串,参考配置要求进行填充)
         }
 
         /** 入金应答 */

+ 61 - 10
src/types/proto/trade.d.ts

@@ -603,7 +603,7 @@ declare global {
 
         // 补充定金接口请求
         interface SupplementDepositReq {
-            Header?: MessageHead;
+            Header?: IMessageHead;
             TradeID?: string | Long; // 成交单号,必填
             BuyOrSell?: number; // 买卖方向,必填
             UserID?: number; // 用户ID,必填
@@ -616,7 +616,7 @@ declare global {
 
         // 补充定金接口响应
         interface SupplementDepositRsp {
-            Header: MessageHead; // 消息头
+            Header: IMessageHead; // 消息头
             RetCode: number; // 返回码
             RetDesc: string; // 描述信息
             TradeID: number; // 成交单号,必填
@@ -627,7 +627,7 @@ declare global {
 
         // 退返定金接口请求
         interface RefundedDepositReq {
-            Header?: MessageHead;
+            Header?: IMessageHead;
             TradeID?: string | Long; // 成交单号,必填
             BuyOrSell?: number; // 买卖方向,必填
             UserID?: number; // 用户ID,必填
@@ -640,7 +640,7 @@ declare global {
 
         // 退返定金接口响应
         interface RefundedDepositRsp {
-            Header: MessageHead; // 消息头
+            Header: IMessageHead; // 消息头
             RetCode: number; // 返回码
             RetDesc: string; // 描述信息
             TradeID: number; // 成交单号,必填
@@ -657,7 +657,7 @@ declare global {
 
         // 按单做市交收申请接口请求
         interface MarketOrderDeliveryApplyReq {
-            Header?: MessageHead;
+            Header?: IMessageHead;
             UserID?: number; // 用户ID,必填
             AccountID?: number; // 交易账号,必填
             BuyOrSell?: number; // 方向,必填
@@ -668,7 +668,7 @@ declare global {
 
         // 按单做市交收申请接口响应
         interface MarketOrderDeliveryApplyRsp {
-            Header: MessageHead; // 消息头
+            Header: IMessageHead; // 消息头
             RetCode: number; // 返回码
             RetDesc: string; // 描述信息
             UserID: number; // 用户ID,必填
@@ -684,7 +684,7 @@ declare global {
 
         // 交收终端操作接口请求
         interface DeliveryClientOperatorReq {
-            Header?: MessageHead;
+            Header?: IMessageHead;
             UserID?: number; // 用户ID,必填
             AccountID?: number; // 交易账号,必填
             DeliveryOrderID?: string | Long; // 交收单号,必填
@@ -702,7 +702,7 @@ declare global {
 
         // 交收终端操作接口响应
         interface DeliveryClientOperatorRsp {
-            Header: MessageHead; // 消息头
+            Header: IMessageHead; // 消息头
             RetCode: number; // 返回码
             RetDesc: string; // 描述信息
             DeliveryOrderID: number; // 交收单号,必填
@@ -710,18 +710,20 @@ declare global {
             AccountID: number; // 交易账号,必填
             ClientSerialNo: string; // 客户端流水号
         }
+
         // 线下交收申请撤销接口请求 0 3 137
         interface OfflineDeliveryApplyCancelOrderReq {
-            Header?: MessageHead; // 消息头
+            Header?: IMessageHead; // 消息头
             UserID?: number; // 用户ID,必填
             AccountID?: number; // 交易账号,必填
             DeliveryOrderID?: string | Long; // 交收单号,必填
             ClientSerialNo?: string; // 客户端流水号
             ClientType?: number; // 终端类型
         }
+
         // 线下交收申请撤销接口响应 0 3 138
         interface OfflineDeliveryApplyCancelOrderRsp {
-            Header: MessageHead; // 消息头
+            Header: IMessageHead; // 消息头
             RetCode: number; // 返回码
             RetDesc: string; // 描述信息
             DeliveryOrderID: number; // 交收单号,必填
@@ -729,5 +731,54 @@ declare global {
             AccountID: number; // 交易账号,必填
             ClientSerialNo: string; // 客户端流水号
         }
+
+        /** 持仓过户明细 */
+        interface HolderTransferDetail {
+            OutLoginID: number; // 转出方登录账号,必填
+            InLoginID: number; // 转入方登录账号,必填
+            GoodsID: number; // 商品ID,必填
+            BuyOrSell: number; // 转出方买卖方向,必填
+            Qty: number; // 转让数量,必填
+            TransferPrice: number; // 转让价格,必填
+            FreezeDays: number; // 冻结天数
+            TransferType: number; // 转让类型-1.协议转让
+            OutAccountID?: number; // 转出方资金帐号,内部使用,不需要填写
+            InAccountID?: number; // 转入方资金帐号,内部使用,不需要填写
+            ApplyID?: number; // 申请单号,内部使用,不需要填写
+        }
+
+        /** 持仓过户申请接口请求 */
+        interface HolderTransferApplyReq {
+            Header?: IMessageHead; // 消息头
+            HolderTransferDetails: Partial<HolderTransferDetail>[]; // 持仓过户明细,必填
+            ClientSerialNo?: string; // 客户端流水号
+            ClientType?: number; // 终端类型
+        }
+
+        /** 持仓过户申请接口响应 */
+        interface HolderTransferApplyRsp {
+            Header: IMessageHead; // 消息头
+            RetCode: number; // 返回码
+            RetDesc: string; // 描述信息
+            ClientSerialNo: string; // 客户端流水号
+        }
+
+        /** 持仓过户确认接口请求 */
+        interface HolderTransferConfirmReq {
+            Header?: IMessageHead; // 消息头
+            ApplyID: number; // 申请ID,必填
+            UserID: number; // 用户ID,必填
+            ClientSerialNo: string; // 客户端流水号
+            ClientType: number; // 终端类型
+        }
+
+        /** 持仓过户确认接口响应 */
+        interface HolderTransferConfirmRsp {
+            Header: IMessageHead; // 消息头
+            RetCode: number; // 返回码
+            RetDesc: string; // 描述信息
+            ApplyID: number; // 申请ID,必填
+            ClientSerialNo: string; // 客户端流水号
+        }
     }
 }