li.shaoyi 9 months ago
parent
commit
84a434c5e5
22 changed files with 1209 additions and 152 deletions
  1. 3 3
      src/constants/order.ts
  2. 2 2
      src/packages/pc/components/base/table/index.vue
  3. 1 1
      src/packages/pc/components/modules/select-account/index.vue
  4. 1 1
      src/packages/pc/components/modules/select-bank/index.vue
  5. 1 1
      src/packages/pc/components/modules/select-cusbank/index.vue
  6. 1 1
      src/packages/pc/components/modules/select-goods/index.vue
  7. 1 1
      src/packages/pc/components/modules/select-institution/index.vue
  8. 1 1
      src/packages/pc/components/modules/select-investor/index.vue
  9. 1 1
      src/packages/pc/components/modules/select-member/index.vue
  10. 323 0
      src/packages/pc/views/investor/custom/accountcfg/components/add/index.vue
  11. 72 0
      src/packages/pc/views/investor/custom/accountcfg/components/add/select-investor/index.vue
  12. 57 0
      src/packages/pc/views/investor/custom/accountcfg/components/delete/index.vue
  13. 247 0
      src/packages/pc/views/investor/custom/accountcfg/components/edit/index.vue
  14. 95 54
      src/packages/pc/views/investor/custom/accountcfg/index.vue
  15. 44 48
      src/packages/pc/views/investor/custom/tradecfg/components/add/index.vue
  16. 26 23
      src/packages/pc/views/investor/custom/tradecfg/components/edit/index.vue
  17. 11 9
      src/packages/pc/views/investor/custom/tradecfg/index.vue
  18. 1 1
      src/packages/pc/views/member/subinstitution/transfer/components/edit/select-level/index.vue
  19. 21 0
      src/services/api/investor/index.ts
  20. 21 0
      src/services/api/member/index.ts
  21. 89 5
      src/types/model/investor.d.ts
  22. 190 0
      src/types/model/member.d.ts

+ 3 - 3
src/constants/order.ts

@@ -31,8 +31,8 @@ export function getBuyOrSellName(value?: number) {
  * 费用算法
  */
 export enum FeeAlgorithm {
-    Fixed = 0, // 固定值
-    Ratio = 1 // 比率
+    Ratio = 1, // 比率
+    Fixed = 2 // 固定值
 }
 
 /**
@@ -41,8 +41,8 @@ export enum FeeAlgorithm {
  */
 export function getFeeAlgorithmList() {
     return [
-        { label: '固定值', value: FeeAlgorithm.Fixed },
         { label: '比率', value: FeeAlgorithm.Ratio },
+        { label: '固定值', value: FeeAlgorithm.Fixed }
     ]
 }
 

+ 2 - 2
src/packages/pc/components/base/table/index.vue

@@ -31,7 +31,7 @@
         <!-- 数据列 -->
         <template v-for="(item, index) in columns" :key="index">
           <el-table-column :align="item.align ?? 'center'" :min-width="120" :width="item.width"
-            :label="t(item.formatLabel ? item.formatLabel() : item.label)" :prop="item.field" :fixed="item.fixed || false"
+            :label="t(item.formatLabel?.() ?? item.label)" :prop="item.field" :fixed="item.fixed || false"
             :sortable="item.sortable" :show-overflow-tooltip="item.field !== 'operate'" v-if="item.show ?? true">
             <template #default="{ row, $index }">
               <slot :name="item.field" :row="row" :value="row[item.field]" :index="$index">
@@ -113,7 +113,7 @@ export default defineComponent({
 
     // 选择列是否可以勾选,通过 callback 改变选中值
     const selectable = (row: unknown) => {
-      let isSelected  = true
+      let isSelected = true
       const callback = (value: boolean) => {
         isSelected = value
       }

+ 1 - 1
src/packages/pc/components/modules/select-account/index.vue

@@ -59,7 +59,7 @@ const remoteMethod = (query: string) => {
 
 const onChange = (value?: number) => {
     const item = dataList.value.find((e) => e.accountid === value)
-    emit('change', toRaw(item))
+    emit('change', item && toRaw(item))
 }
 
 defineExpose({

+ 1 - 1
src/packages/pc/components/modules/select-bank/index.vue

@@ -71,7 +71,7 @@ const remoteMethod = (query: string) => {
 }
 
 const onChange = (item?: Model.BankInfoByCusBankRsp) => {
-    emit('change', toRaw(item))
+    emit('change', item && toRaw(item))
 }
 
 watch(() => props.selected, (e) => {

+ 1 - 1
src/packages/pc/components/modules/select-cusbank/index.vue

@@ -31,7 +31,7 @@ const { dataList } = useRequest(getAllBankCus)
 
 const onChange = (value: string) => {
     const item = dataList.value.find((item) => item.cusbankid === value)
-    emit('change', toRaw(item))
+    emit('change', item && toRaw(item))
 }
 </script>
 

+ 1 - 1
src/packages/pc/components/modules/select-goods/index.vue

@@ -63,7 +63,7 @@ const remoteMethod = (query: string) => {
 
 const onChange = (value?: number) => {
     const item = dataList.value.find((e) => e.goodsId === value)
-    emit('change', toRaw(item))
+    emit('change', item && toRaw(item))
 }
 
 defineExpose({

+ 1 - 1
src/packages/pc/components/modules/select-institution/index.vue

@@ -68,7 +68,7 @@ const remoteMethod = (query: string) => {
 
 const onChange = (value?: number) => {
     const item = dataList.value.find((e) => e.userid === value)
-    emit('change', toRaw(item))
+    emit('change', item && toRaw(item))
 }
 
 defineExpose({

+ 1 - 1
src/packages/pc/components/modules/select-investor/index.vue

@@ -64,7 +64,7 @@ const remoteMethod = (query: string) => {
 
 const onChange = (value?: number) => {
     const item = dataList.value.find((e) => e.userId === value)
-    emit('change', toRaw(item))
+    emit('change', item && toRaw(item))
 }
 
 defineExpose({

+ 1 - 1
src/packages/pc/components/modules/select-member/index.vue

@@ -72,7 +72,7 @@ const remoteMethod = (query: string) => {
 
 const onChange = (value?: number) => {
     const item = dataList.value.find((e) => e.userid === value)
-    emit('change', toRaw(item))
+    emit('change', item && toRaw(item))
 }
 
 defineExpose({

+ 323 - 0
src/packages/pc/views/investor/custom/accountcfg/components/add/index.vue

@@ -0,0 +1,323 @@
+<!-- 交易商管理-个性化管理-资金账户个性化-新增 -->
+<template>
+    <app-drawer :title="t('investor.custom.tradecfg.edit.title')" width="1100" v-model:show="show" :refresh="refresh"
+        :loading="loading">
+        <el-form ref="formRef" label-width="140px" :model="formData" :rules="formRules" :show-message="false">
+            <fieldset class="g-fieldset el-form--horizontal">
+                <legend class="g-fieldset__legend">{{ t('investor.custom.tradecfg.edit.subtitle1') }}</legend>
+                <el-form-item label="交易商" prop="userid">
+                    <select-investor v-model="formData.userid" @change="onInvestorChange" />
+                </el-form-item>
+                <el-form-item label="资金账户" prop="accountid">
+                    <el-select v-model="formData.accountid" @change="onAccountChange">
+                        <template v-for="(value, index) in accountData?.accountids" :key="index">
+                            <el-option :label="value" :value="value" />
+                        </template>
+                    </el-select>
+                </el-form-item>
+                <el-form-item label="市场" prop="marketid">
+                    <el-select v-model="formData.marketid" @change="onMarketChange">
+                        <template v-for="(item, index) in marketData?.markets" :key="index">
+                            <el-option :label="item.marketname" :value="item.marketid" />
+                        </template>
+                    </el-select>
+                </el-form-item>
+                <el-form-item label="商品" prop="goodsid">
+                    <el-select v-model="formData.goodsid" @change="onGoodsChange">
+                        <template v-for="(item, index) in goodsData?.goods" :key="index">
+                            <el-option :label="item.goodsname" :value="item.goodsid" />
+                        </template>
+                    </el-select>
+                </el-form-item>
+                <el-form-item label="保证金类别" prop="paramid">
+                    <el-select v-model="formData.paramid" @change="onResultChange" clearable>
+                        <template v-for="(item, index) in resultData?.results" :key="index">
+                            <el-option :label="item.enumdicname" :value="item.enumitemname" />
+                        </template>
+                    </el-select>
+                </el-form-item>
+            </fieldset>
+            <app-table :data="resultData?.rulesConfigVos" :columns="ruleColumns">
+                <!-- 平台 -->
+                <template #paramvalue="{ row }">
+                    <span v-if="row.ruleid === 105">{{ feetypeEnum.getEnumTypeName(row.paramvalue) }}</span>
+                    <span v-else>{{ row.paramvalue || 0 }}</span>
+                </template>
+                <!-- 会员 -->
+                <template #dvalue="{ row }">
+                    <span v-if="row.ruleid === 105">
+                        {{ handleNoneValue(feetypeEnum.getEnumTypeName(row.dvalue)) }}
+                    </span>
+                    <span v-else>{{ handleNoneValue(row.dvalue) }}</span>
+                </template>
+                <!-- 分组 -->
+                <template #gvalue="{ row }">
+                    <span v-if="row.ruleid === 105">
+                        {{ handleNoneValue(feetypeEnum.getEnumTypeName(row.gvalue)) }}
+                    </span>
+                    <span v-else>{{ handleNoneValue(row.gvalue) }}</span>
+                </template>
+                <!-- 个性化 -->
+                <template #cvalue="{ row, index }">
+                    <template v-if="formData.ruleList[index]">
+                        <el-select v-model="formData.ruleList[index].paramvalue" clearable v-if="row.ruleid === 105">
+                            <template v-for="item in feetypeEnum.getEnumOptions()" :key="item.id">
+                                <el-option :label="item.label" :value="item.value" />
+                            </template>
+                        </el-select>
+                        <el-input-number v-model="formData.ruleList[index].paramvalue" :min="0"
+                            :placeholder="t('common.pleaseenter')" v-else />
+                    </template>
+                </template>
+            </app-table>
+            <app-table :data="resultData?.feesConfigVos" :columns="feeColumns">
+                <!-- 平台 -->
+                <template #exchangevalue="{ row }">
+                    <template v-if="row.feealgorithm">
+                        <span>{{ scfRiskMode.getEnumTypeName(row.feealgorithm) }}:</span>
+                        <span>{{ row.exchangevalue + (row.feealgorithm === 1 && '‱') }}</span>
+                    </template>
+                    <template v-else>
+                        {{ handleNoneValue() }}
+                    </template>
+                </template>
+                <!-- 会员 -->
+                <template #dvalue="{ row }">
+                    <template v-if="row.drithm">
+                        <span>{{ scfRiskMode.getEnumTypeName(row.drithm) }}:</span>
+                        <span>{{ row.dvalue + (row.drithm === 1 && '‱') }}</span>
+                    </template>
+                    <template v-else>
+                        {{ handleNoneValue() }}
+                    </template>
+                </template>
+                <!-- 分组 -->
+                <template #gvalue="{ row }">
+                    <template v-if="row.grithm">
+                        <span>{{ scfRiskMode.getEnumTypeName(row.grithm) }}:</span>
+                        <span>{{ row.gvalue + (row.grithm === 1 && '‱') }}</span>
+                    </template>
+                    <template v-else>
+                        {{ handleNoneValue() }}
+                    </template>
+                </template>
+                <!-- 最小值 -->
+                <template #memberminvalue="{ row }">
+                    {{ row.memberminvalue + (row.feealgorithm === 1 && '‱') }}
+                </template>
+                <!-- 最大值 -->
+                <template #membermaxvalue="{ row }">
+                    {{ row.membermaxvalue + (row.feealgorithm === 1 && '‱') }}
+                </template>
+                <!-- 服务费 -->
+                <template #fee="{ row, index }">
+                    <template v-if="formData.feeList[index]">
+                        <el-input-number v-model="formData.feeList[index].paramvalue" :min="row.memberminvalue"
+                            :max="row.membermaxvalue" :placeholder="t('common.pleaseenter')" />
+                    </template>
+                </template>
+            </app-table>
+        </el-form>
+        <template #footer>
+            <el-button @click="onCancel(false)">{{ t('operation.close') }}</el-button>
+            <el-button type="primary" @click="onSubmit">{{ t('operation.save') }}</el-button>
+        </template>
+    </app-drawer>
+</template>
+
+<script lang="ts" setup>
+import { ref, reactive, computed } from 'vue'
+import { ElMessage, FormInstance, FormRules } from 'element-plus'
+import { handleNoneValue } from '@/filters'
+import { useEnum } from '@/hooks/enum'
+import { useRequest } from '@/hooks/request'
+import { loadSelectOption, tradeConfigAdd } from '@/services/api/member'
+import { i18n } from '@/stores'
+import AppDrawer from '@pc/components/base/drawer/index.vue'
+import AppTable from '@pc/components/base/table/index.vue'
+import SelectInvestor from './select-investor/index.vue'
+
+const feetypeEnum = useEnum('feetype')
+const scfRiskMode = useEnum('SCFRiskMode')
+
+const { global: { t } } = i18n
+const formRef = ref<FormInstance>()
+const show = ref(true)
+const refresh = ref(false)
+const loading = ref(false)
+
+const formData = reactive<Model.TradeConfigAddReq>({
+    memberuserid: 1,
+    feeList: [],
+    ruleList: [],
+    tradetype: 1
+})
+
+// 获取资金账户列表
+const { data: accountData, run: getAccountIds } = useRequest(loadSelectOption, {
+    manual: true,
+    params: {
+        memberuserid: 1
+    }
+})
+
+// 获取市场列表
+const { data: marketData, run: getMarketList } = useRequest(loadSelectOption, {
+    manual: true,
+    params: {
+        memberuserid: 1
+    }
+})
+
+// 获取商品列表
+const { data: goodsData, run: getGoodsList } = useRequest(loadSelectOption, {
+    manual: true,
+    params: {
+        memberuserid: 1
+    }
+})
+
+// 获取保证金类别列表
+const { data: resultData, run: getResultList } = useRequest(loadSelectOption, {
+    manual: true,
+    params: {
+        memberuserid: 1
+    },
+    onSuccess: (res) => {
+        formData.ruleList = []
+        formData.feeList = []
+
+        res.data.rulesConfigVos.forEach((e) => {
+            formData.ruleList.push({
+                paramid: e.ruleid,
+            })
+        })
+
+        res.data.feesConfigVos.forEach((e) => {
+            formData.feeList.push({
+                feealgorithm: e.feealgorithm,
+                paramid: e.tradefeeid,
+            })
+        })
+    }
+})
+
+const ruleColumns = computed<Model.TableColumn[]>(() => [
+    { field: 'rulename', label: '扩展项' },
+    { field: 'paramvalue', label: '平台' },
+    { field: 'dvalue', label: '会员' },
+    { field: 'gvalue', label: '分组' },
+    { field: 'cvalue', label: '个性化' },
+])
+
+const feeColumns = computed<Model.TableColumn[]>(() => [
+    { field: 'tradefeename', label: '费用项' },
+    { field: 'exchangevalue', label: '平台' },
+    { field: 'dvalue', label: '会员' },
+    { field: 'gvalue', label: '分组' },
+    { field: 'feealgorithm', label: '费用算法', formatValue: (val) => scfRiskMode.getEnumTypeName(val) },
+    { field: 'memberminvalue', label: '最小值' },
+    { field: 'fee', label: '服务费', width: 200 },
+    { field: 'membermaxvalue', label: '最大值' },
+])
+
+// 表单验证规则
+const formRules: FormRules = {
+    userid: [{ required: true }],
+    accountid: [{ required: true }],
+    marketid: [{ required: true }],
+    goodsid: [{ required: true }],
+}
+
+// 选择交易商
+const onInvestorChange = (item?: Model.InitAccTradeRsp) => {
+    formData.accountid = undefined
+    formData.marketid = undefined
+    formData.goodsid = undefined
+    formData.paramid = undefined
+    formData.feealgorithm = undefined
+    accountData.value = undefined
+    marketData.value = undefined
+    goodsData.value = undefined
+    resultData.value = undefined
+    if (item) {
+        getAccountIds({
+            userid: item.userid,
+        })
+    }
+}
+
+// 选择资金账户
+const onAccountChange = (value: number) => {
+    formData.marketid = undefined
+    formData.goodsid = undefined
+    formData.paramid = undefined
+    formData.feealgorithm = undefined
+    marketData.value = undefined
+    goodsData.value = undefined
+    resultData.value = undefined
+    getMarketList({
+        userid: formData.userid,
+        accountid: value,
+    })
+}
+
+// 选择市场
+const onMarketChange = (value: number) => {
+    formData.goodsid = undefined
+    formData.paramid = undefined
+    formData.feealgorithm = undefined
+    goodsData.value = undefined
+    resultData.value = undefined
+    getGoodsList({
+        userid: formData.userid,
+        accountid: formData.accountid,
+        marketid: value,
+    })
+}
+
+// 选择商品
+const onGoodsChange = (value: number) => {
+    formData.paramid = undefined
+    formData.feealgorithm = undefined
+    getResultList({
+        userid: formData.userid,
+        accountid: formData.accountid,
+        marketid: formData.marketid,
+        goodsid: value
+    })
+}
+
+// 选择保证金类别
+const onResultChange = (value?: number) => {
+    const res = resultData.value?.results.find((e) => e.enumitemname === value)
+    formData.feealgorithm = res?.marginalgorithm
+}
+
+const onSubmit = () => {
+    formRef.value?.validate((valid) => {
+        if (valid) {
+            if (formData.paramid || formData.ruleList.some((e) => e.paramid === 105 && e.paramvalue)) {
+                loading.value = true
+                tradeConfigAdd({
+                    data: formData
+                }).then(() => {
+                    ElMessage.success(t('common.tips3'))
+                    onCancel(true)
+                }).catch((err) => {
+                    ElMessage.error(t('common.tips4') + err)
+                }).finally(() => {
+                    loading.value = false
+                })
+            } else {
+                ElMessage.warning('保证金类别,交易规则,交易服务费均未设置')
+            }
+        }
+    })
+}
+
+const onCancel = (isRefresh = false) => {
+    show.value = false
+    refresh.value = isRefresh
+}
+</script>

+ 72 - 0
src/packages/pc/views/investor/custom/accountcfg/components/add/select-investor/index.vue

@@ -0,0 +1,72 @@
+<!-- 选择交易商 -->
+<template>
+    <app-remote-select v-model="selectedValue" :options="dataList"
+        :option-props="{ label: 'accountname', value: 'userid' }" :remote-method="remoteMethod" @change="onChange"
+        @reset="onReset">
+        <template #default="{ option }">
+            <div style="display: flex;justify-content: space-between;">
+                <span>{{ option.userid }}</span>
+                <span>{{ option.accountname }}</span>
+            </div>
+        </template>
+    </app-remote-select>
+</template>
+
+<script lang="ts" setup>
+import { computed, toRaw, PropType } from 'vue'
+import { useRequest } from '@/hooks/request'
+import { initAccTrade } from '@/services/api/investor'
+import AppRemoteSelect from '@pc/components/base/remote-select/index.vue'
+
+const props = defineProps({
+    modelValue: Number,
+    params: {
+        type: Object as PropType<Model.InitAccTradeReq>
+    },
+})
+
+const emit = defineEmits(['update:modelValue', 'change'])
+
+const selectedValue = computed({
+    get: () => props.modelValue,
+    set: (val) => emit('update:modelValue', val)
+})
+
+const { dataList, loading, run } = useRequest(initAccTrade, {
+    manual: true,
+    params: props.params,
+    onSuccess: (res) => {
+        if (!res.data.some((e) => e.userid.toString() === selectedValue.value?.toString())) {
+            selectedValue.value = undefined
+            onChange()
+        }
+    }
+})
+
+const onReset = () => {
+    if (!loading.value) {
+        run()
+    }
+}
+
+const remoteMethod = (query: string) => {
+    if (!loading.value) {
+        if (query) {
+            run({
+                searchName: query
+            })
+        } else if (!dataList.value.length) {
+            onReset()
+        }
+    }
+}
+
+const onChange = (value?: number) => {
+    const item = dataList.value.find((e) => e.userid === value)
+    emit('change', item && toRaw(item))
+}
+
+defineExpose({
+    onReset
+})
+</script>

+ 57 - 0
src/packages/pc/views/investor/custom/accountcfg/components/delete/index.vue

@@ -0,0 +1,57 @@
+<!-- 交易商管理-个性化管理-资金账户个性化-删除 -->
+<template>
+    <app-drawer :title="t('common.alert')" v-model:show="show" :loading="loading" :refresh="refresh">
+        <div class="g-text-message">{{ t('investor.custom.tradecfg.delete.tips') }}</div>
+        <template #footer>
+            <el-button @click="onCancel(false)">{{ t('operation.cancel') }}</el-button>
+            <el-button type="primary" @click="onSubmit">{{ t('operation.confirm') }}</el-button>
+        </template>
+    </app-drawer>
+</template>
+
+<script lang="ts" setup>
+import { shallowRef, PropType } from 'vue'
+import { ElMessage } from 'element-plus'
+import { accTradeConfigDelete } from '@/services/api/investor'
+import AppDrawer from '@pc/components/base/drawer/index.vue'
+import { i18n } from '@/stores'
+
+const props = defineProps({
+    record: {
+        type: Object as PropType<Model.AccTradeConfigViewRsp>,
+        required: true
+    }
+})
+
+const { global: { t } } = i18n
+const show = shallowRef(true)
+const refresh = shallowRef(false)
+const loading = shallowRef(false)
+
+const onCancel = (isRefresh = false) => {
+    show.value = false
+    refresh.value = isRefresh
+}
+
+const onSubmit = () => {
+    loading.value = true
+    accTradeConfigDelete({
+        data: {
+            memberuserid: props.record.memberuserid,
+            userid: props.record.userid,
+            marketid: props.record.marketid,
+            accountid: props.record.accountid,
+            goodsid: props.record.goodsid,
+            tradetype: props.record.tradetype,
+        }
+    }).then(() => {
+        ElMessage.success(t('common.tips5'))
+        onCancel(true)
+    }).catch((err) => {
+        ElMessage.error(t('common.tips6') + err)
+        onCancel()
+    }).finally(() => {
+        loading.value = false
+    })
+}
+</script>

+ 247 - 0
src/packages/pc/views/investor/custom/accountcfg/components/edit/index.vue

@@ -0,0 +1,247 @@
+<!-- 交易商管理-个性化管理-资金账户个性化-编辑 -->
+<template>
+    <app-drawer :title="t('investor.custom.tradecfg.edit.title')" width="1100" v-model:show="show" :refresh="refresh"
+        :loading="loading">
+        <el-form ref="formRef" label-width="140px" :model="formData" :show-message="false">
+            <fieldset class="g-fieldset el-form--horizontal">
+                <legend class="g-fieldset__legend">{{ t('investor.custom.tradecfg.edit.subtitle1') }}</legend>
+                <el-form-item label="交易商">
+                    {{ handleNoneValue(investorItem?.name) }}
+                </el-form-item>
+                <el-form-item label="资金账户">
+                    {{ handleNoneValue(accountItem?.name) }}
+                </el-form-item>
+                <el-form-item label="商品">
+                    {{ handleNoneValue(goodsItem?.name) }}
+                </el-form-item>
+                <el-form-item :label="t('investor.custom.tradecfg.edit.paramid')" prop="paramid">
+                    <el-select v-model="formData.paramid" @change="onResultChange" clearable>
+                        <template v-for="(item, index) in resultData?.results" :key="index">
+                            <el-option :label="item.enumdicname" :value="item.enumitemname" />
+                        </template>
+                    </el-select>
+                </el-form-item>
+            </fieldset>
+            <app-table :data="record.druleList" :columns="ruleColumns">
+                <!-- 平台 -->
+                <template #paramvalue="{ row }">
+                    <span v-if="row.ruleid === 105">{{ feetypeEnum.getEnumTypeName(row.paramvalue) }}</span>
+                    <span v-else>{{ row.paramvalue || 0 }}</span>
+                </template>
+                <!-- 会员 -->
+                <template #dvalue="{ row }">
+                    <span v-if="row.ruleid === 105">
+                        {{ handleNoneValue(feetypeEnum.getEnumTypeName(row.dvalue)) }}
+                    </span>
+                    <span v-else>{{ handleNoneValue(row.dvalue) }}</span>
+                </template>
+                <!-- 分组 -->
+                <template #gvalue="{ row }">
+                    <span v-if="row.ruleid === 105">
+                        {{ handleNoneValue(feetypeEnum.getEnumTypeName(row.gvalue)) }}
+                    </span>
+                    <span v-else>{{ handleNoneValue(row.gvalue) }}</span>
+                </template>
+                <!-- 个性化 -->
+                <template #cvalue="{ row, index }">
+                    <template v-if="formData.ruleList[index]">
+                        <el-select v-model="formData.ruleList[index].paramvalue" clearable v-if="row.ruleid === 105">
+                            <template v-for="item in feetypeEnum.getEnumOptions()" :key="item.id">
+                                <el-option :label="item.label" :value="item.value" />
+                            </template>
+                        </el-select>
+                        <el-input-number v-model="formData.ruleList[index].paramvalue"
+                            :placeholder="t('common.pleaseenter')" v-else />
+                    </template>
+                </template>
+            </app-table>
+            <app-table :data="record.dfeeList" :columns="feeColumns">
+                <!-- 平台 -->
+                <template #exchangevalue="{ row }">
+                    <template v-if="row.feealgorithm">
+                        <span>{{ scfRiskMode.getEnumTypeName(row.feealgorithm) }}:</span>
+                        <span>{{ row.exchangevalue + (row.feealgorithm === 1 && '‱') }}</span>
+                    </template>
+                    <template v-else>
+                        {{ handleNoneValue() }}
+                    </template>
+                </template>
+                <!-- 会员 -->
+                <template #dvalue="{ row }">
+                    <template v-if="row.drithm">
+                        <span>{{ scfRiskMode.getEnumTypeName(row.drithm) }}:</span>
+                        <span>{{ row.dvalue + (row.drithm === 1 && '‱') }}</span>
+                    </template>
+                    <template v-else>
+                        {{ handleNoneValue() }}
+                    </template>
+                </template>
+                <!-- 分组 -->
+                <template #gvalue="{ row }">
+                    <template v-if="row.grithm">
+                        <span>{{ scfRiskMode.getEnumTypeName(row.grithm) }}:</span>
+                        <span>{{ row.gvalue + (row.grithm === 1 && '‱') }}</span>
+                    </template>
+                    <template v-else>
+                        {{ handleNoneValue() }}
+                    </template>
+                </template>
+                <!-- 最小值 -->
+                <template #memberminvalue="{ row }">
+                    {{ row.memberminvalue + (row.feealgorithm === 1 && '‱') }}
+                </template>
+                <!-- 最大值 -->
+                <template #membermaxvalue="{ row }">
+                    {{ row.membermaxvalue + (row.feealgorithm === 1 && '‱') }}
+                </template>
+                <!-- 服务费 -->
+                <template #fee="{ row, index }">
+                    <template v-if="formData.feeList[index]">
+                        <el-input-number v-model="formData.feeList[index].paramvalue" :min="row.memberminvalue"
+                            :max="row.membermaxvalue" :placeholder="t('common.pleaseenter')" />
+                    </template>
+                </template>
+            </app-table>
+        </el-form>
+        <template #footer>
+            <el-button @click="onCancel(false)">{{ t('operation.close') }}</el-button>
+            <el-button type="primary" @click="onSubmit">{{ t('operation.save') }}</el-button>
+        </template>
+    </app-drawer>
+</template>
+
+<script lang="ts" setup>
+import { reactive, shallowRef, PropType, computed } from 'vue'
+import { ElMessage, FormInstance } from 'element-plus'
+import { handleNoneValue } from '@/filters'
+import { useEnum } from '@/hooks/enum'
+import { useRequest } from '@/hooks/request'
+import { getAccTradeTree } from '@/services/api/investor'
+import { tradeConfigEdit } from '@/services/api/member'
+import { loadSelectOption } from '@/services/api/member'
+import AppDrawer from '@pc/components/base/drawer/index.vue'
+import AppTable from '@pc/components/base/table/index.vue'
+import { i18n } from '@/stores'
+
+const props = defineProps({
+    record: {
+        type: Object as PropType<Model.AccTradeConfigViewRsp>,
+        required: true
+    }
+})
+
+const feetypeEnum = useEnum('feetype')
+const scfRiskMode = useEnum('SCFRiskMode')
+
+const { global: { t } } = i18n
+const formRef = shallowRef<FormInstance>()
+const show = shallowRef(true)
+const refresh = shallowRef(false)
+const loading = shallowRef(false)
+
+const formData = reactive<Model.TradeConfigAddReq>({
+    memberuserid: props.record.memberuserid,
+    accountid: props.record.accountid,
+    feeList: [],
+    goodsid: props.record.goodsid,
+    marketid: props.record.marketid,
+    ruleList: [],
+    paramid: props.record.paramid,
+    tradetype: props.record.tradetype,
+    userid: props.record.userid,
+    feealgorithm: props.record.feealgorithm,
+})
+
+// 获取树列表
+const { dataList: nodeList } = useRequest(getAccTradeTree)
+
+// 交易商对象
+const investorItem = computed(() => nodeList.value.find((e) => e.pid === '-1' && e.userid === formData.userid))
+
+// 资金账户对象
+const accountItem = computed(() => nodeList.value.find((e) => e.pid === investorItem.value?.id && e.accountid === formData.accountid))
+
+// 商品对象
+const goodsItem = computed(() => nodeList.value.find((e) => e.pid === accountItem.value?.id && e.goodsid === formData.goodsid))
+
+// 获取保证金类别列表
+const { data: resultData } = useRequest(loadSelectOption, {
+    params: {
+        memberuserid: formData.marketid,
+        userid: formData.userid,
+        accountid: formData.accountid,
+        marketid: formData.marketid,
+        goodsid: formData.goodsid
+    },
+    onSuccess: (res) => {
+        res.data.rulesConfigVos.forEach((e) => {
+            const rule = props.record.druleList.find((d) => d.ruleid === e.ruleid)
+            formData.ruleList.push({
+                paramid: e.ruleid,
+                paramvalue: rule?.cvalue
+            })
+        })
+
+        res.data.feesConfigVos.forEach((e) => {
+            const fee = props.record.dfeeList.find((d) => d.tradefeeid === e.tradefeeid)
+            formData.feeList.push({
+                feealgorithm: e.feealgorithm,
+                paramid: e.tradefeeid,
+                paramvalue: fee?.cvalue
+            })
+        })
+    }
+})
+
+const ruleColumns = computed<Model.TableColumn[]>(() => [
+    { field: 'rulename', label: '扩展项' },
+    { field: 'paramvalue', label: '平台' },
+    { field: 'dvalue', label: '会员' },
+    { field: 'gvalue', label: '分组' },
+    { field: 'cvalue', label: '个性化' },
+])
+
+const feeColumns = computed<Model.TableColumn[]>(() => [
+    { field: 'tradefeename', label: '费用项' },
+    { field: 'exchangevalue', label: '平台' },
+    { field: 'dvalue', label: '会员' },
+    { field: 'gvalue', label: '分组' },
+    { field: 'feealgorithm', label: '费用算法', formatValue: (val) => scfRiskMode.getEnumTypeName(val) },
+    { field: 'memberminvalue', label: '最小值' },
+    { field: 'fee', label: '服务费', width: 200 },
+    { field: 'membermaxvalue', label: '最大值' },
+])
+
+// 选择保证金类别
+const onResultChange = (value?: number) => {
+    const res = resultData.value?.results.find((e) => e.enumitemname === value)
+    formData.feealgorithm = res?.marginalgorithm
+}
+
+const onSubmit = () => {
+    formRef.value?.validate((valid) => {
+        if (valid) {
+            if (formData.paramid || formData.ruleList.some((e) => e.paramid === 105 && e.paramvalue)) {
+                loading.value = true
+                tradeConfigEdit({
+                    data: formData
+                }).then(() => {
+                    ElMessage.success(t('common.tips3'))
+                    onCancel(true)
+                }).catch((err) => {
+                    ElMessage.error(t('common.tips4') + err)
+                }).finally(() => {
+                    loading.value = false
+                })
+            } else {
+                ElMessage.warning('保证金类别,交易规则,交易服务费均未设置')
+            }
+        }
+    })
+}
+
+const onCancel = (isRefresh = false) => {
+    show.value = false
+    refresh.value = isRefresh
+}
+</script>

+ 95 - 54
src/packages/pc/views/investor/custom/accountcfg/index.vue

@@ -3,15 +3,17 @@
     <app-view>
         <template #header>
             <el-form ref="formRef" class="el-form--filter" :model="qs" :rules="formRules" :show-message="false">
-                <el-form-item label="交易商" prop="usergroupid">
-                    <el-select v-model="selectedInvestor" value-key="id" :validate-event="false" @change="onGroupChange">
+                <el-form-item label="交易商" prop="userid">
+                    <el-select v-model="selectedInvestor" value-key="id" :validate-event="false"
+                        @change="onGroupChange">
                         <template v-for="item in investorList" :key="item.id">
                             <el-option :label="item.name" :value="item" />
                         </template>
                     </el-select>
                 </el-form-item>
-                <el-form-item label="资金账户" prop="marketid">
-                    <el-select v-model="selectedAccount" value-key="id" :validate-event="false" @change="onMarketChange">
+                <el-form-item label="资金账户" prop="accountid">
+                    <el-select v-model="selectedAccount" value-key="id" :validate-event="false"
+                        @change="onMarketChange">
                         <template v-for="item in accountList" :key="item.id">
                             <el-option :label="item.name" :value="item" />
                         </template>
@@ -30,30 +32,36 @@
             </el-form>
         </template>
         <div style="display: flex;justify-content: space-between;">
-            <app-operation :data-list="getActionButtons(['investor_custom_tradecfg_add'])" @click="openComponent" />
+            <app-operation :data-list="getActionButtons(['investor_custom_accountcfg_add'])" @click="openComponent" />
             <app-operation
-                :data-list="getActionButtons(['investor_custom_tradecfg_modify', 'investor_custom_tradecfg_delete'])"
+                :data-list="getActionButtons(['investor_custom_accountcfg_modify', 'investor_custom_accountcfg_delete'])"
                 @click="openComponent" v-if="data" />
         </div>
         <template v-if="data">
-            <app-table-details :title="t('common.baseinfo')" :data="data" :label-width="160" :cell-props="detailProps"
-                :column="3" />
+            <app-table-details title="基本信息设置" :data="data" :label-width="160" :cell-props="detailProps" :column="2" />
             <app-table :data="data.druleList" :columns="ruleColumns">
                 <template #headerLeft>
-                    <b>{{ t('investor.custom.tradecfg.subtitle') }}</b>
+                    <b>交易规则设置</b>
                 </template>
-                <!-- 商品设置值 -->
+                <!-- 平台 -->
                 <template #paramvalue="{ row }">
                     <span v-if="row.ruleid === 105">{{ feetypeEnum.getEnumTypeName(row.paramvalue) }}</span>
                     <span v-else>{{ row.paramvalue || 0 }}</span>
                 </template>
-                <!-- 会员设置值 -->
+                <!-- 会员 -->
                 <template #dvalue="{ row }">
                     <span v-if="row.ruleid === 105">
                         {{ handleNoneValue(feetypeEnum.getEnumTypeName(row.dvalue)) }}
                     </span>
                     <span v-else>{{ handleNoneValue(row.dvalue) }}</span>
                 </template>
+                <!-- 分组 -->
+                <template #gvalue="{ row }">
+                    <span v-if="row.ruleid === 105">
+                        {{ handleNoneValue(feetypeEnum.getEnumTypeName(row.gvalue)) }}
+                    </span>
+                    <span v-else>{{ handleNoneValue(row.gvalue) }}</span>
+                </template>
                 <!-- 个性化 -->
                 <template #cvalue="{ row }">
                     <span v-if="row.ruleid === 105">
@@ -64,23 +72,33 @@
             </app-table>
             <app-table :data="data.dfeeList" :columns="feeColumns">
                 <template #headerLeft>
-                    <b>{{ t('investor.custom.tradecfg.subtitle1') }}</b>
+                    <b>交易服务费设置</b>
                 </template>
-                <!-- 商品设置值 -->
+                <!-- 平台 -->
                 <template #exchangevalue="{ row }">
                     <template v-if="row.feealgorithm">
-                        <span v-if="row.feealgorithm === 1">{{ parseTenThousand(row.exchangevalue) }}</span>
-                        <span v-else>{{ row.exchangevalue }}</span>
+                        <span>{{ scfRiskMode.getEnumTypeName(row.feealgorithm) }}:</span>
+                        <span>{{ row.exchangevalue + (row.feealgorithm === 1 && '‱') }}</span>
                     </template>
                     <template v-else>
                         {{ handleNoneValue() }}
                     </template>
                 </template>
-                <!-- 会员设置值 -->
+                <!-- 会员 -->
                 <template #dvalue="{ row }">
                     <template v-if="row.drithm">
-                        <span v-if="row.drithm === 1">{{ parseTenThousand(row.dvalue) }}</span>
-                        <span v-else>{{ row.dvalue }}</span>
+                        <span>{{ scfRiskMode.getEnumTypeName(row.drithm) }}:</span>
+                        <span>{{ row.dvalue + (row.drithm === 1 && '‱') }}</span>
+                    </template>
+                    <template v-else>
+                        {{ handleNoneValue() }}
+                    </template>
+                </template>
+                <!-- 分组 -->
+                <template #gvalue="{ row }">
+                    <template v-if="row.grithm">
+                        <span>{{ scfRiskMode.getEnumTypeName(row.grithm) }}:</span>
+                        <span>{{ row.gvalue + (row.grithm === 1 && '‱') }}</span>
                     </template>
                     <template v-else>
                         {{ handleNoneValue() }}
@@ -89,8 +107,8 @@
                 <!-- 个性化 -->
                 <template #cvalue="{ row }">
                     <template v-if="row.crithm">
-                        <span v-if="row.crithm === 1">{{ parseTenThousand(row.cvalue) }}</span>
-                        <span v-else>{{ row.cvalue }}</span>
+                        <span>{{ scfRiskMode.getEnumTypeName(row.crithm) }}:</span>
+                        <span>{{ row.cvalue + (row.crithm === 1 && '‱') }}</span>
                     </template>
                     <template v-else>
                         {{ handleNoneValue() }}
@@ -107,26 +125,27 @@
 <script lang="ts" setup>
 import { shallowRef, computed, nextTick, toRaw } from 'vue'
 import { ElMessage, FormInstance, FormRules } from 'element-plus'
-import { parseTenThousand, handleNoneValue } from '@/filters'
-import { getFeeAlgorithmName } from '@/constants/order'
+import { handleNoneValue } from '@/filters'
 import { useEnum } from '@/hooks/enum'
 import { useRequest } from '@/hooks/request'
 import { useOperation } from '@/hooks/operation'
-import { getAccTradeTree, tradeConfigView } from '@/services/api/investor'
+import { getAccTradeTree, accTradeConfigView } from '@/services/api/investor'
 import { CellProp } from '@pc/components/base/table-details/types'
 import AppTable from '@pc/components/base/table/index.vue'
 import AppOperation from '@pc/components/base/operation/index.vue'
 import AppTableDetails from '@pc/components/base/table-details/index.vue'
 import { i18n } from '@/stores'
 
-const { componentMap, componentId, openComponent, closeComponent, getActionButtons } = useOperation<Model.TradeConfigViewRsp>({
+const { componentMap, componentId, openComponent, closeComponent, getActionButtons } = useOperation<Model.AccTradeConfigViewRsp>({
     onClose: (componentId) => {
         getNodeList()
-        if (componentId === 'investor_custom_tradecfg_modify') {
+        if (componentId === 'investor_custom_accountcfg_modify') {
             onSearch()
         }
-        if (componentId === 'investor_custom_tradecfg_delete') {
-            qs.value = {}
+        if (componentId === 'investor_custom_accountcfg_delete') {
+            selectedInvestor.value = undefined
+            selectedAccount.value = undefined
+            selectedGoods.value = undefined
             data.value = undefined
         }
     }
@@ -134,19 +153,21 @@ const { componentMap, componentId, openComponent, closeComponent, getActionButto
 
 const customerTypeEnum = useEnum('customerType')
 const feetypeEnum = useEnum('feetype')
+const scfRiskMode = useEnum('SCFRiskMode')
 
 const { global: { t } } = i18n
 const formRef = shallowRef<FormInstance>()
-const qs = shallowRef<Partial<Model.TradeConfigViewReq>>({})
+const qs = shallowRef<Partial<Model.AccTradeConfigViewReq>>({})
+
 const info = shallowRef<Partial<{
-    groupName: string,
-    marketName: string,
+    userName: string,
+    accountName: string,
     goodsName: string
 }>>({})
 
-const selectedInvestor = shallowRef<Model.InvestorTreeRsp>() // 选中的交易商对象
-const selectedAccount = shallowRef<Model.InvestorTreeRsp>() // 选中的资金账户对象
-const selectedGoods = shallowRef<Model.InvestorTreeRsp>() // 选中的商品对象
+const selectedInvestor = shallowRef<Model.AccTradeTreeRsp>() // 选中的交易商对象
+const selectedAccount = shallowRef<Model.AccTradeTreeRsp>() // 选中的资金账户对象
+const selectedGoods = shallowRef<Model.AccTradeTreeRsp>() // 选中的商品对象
 
 // 交易商列表
 const investorList = computed(() => nodeList.value.filter((e) => e.pid === '-1'))
@@ -161,7 +182,7 @@ const { dataList: nodeList, run: getNodeList } = useRequest(getAccTradeTree, {
     }
 })
 
-const { data, run } = useRequest(tradeConfigView, {
+const { data, run } = useRequest(accTradeConfigView, {
     manual: true,
     onError: (err) => {
         ElMessage.error(err)
@@ -169,32 +190,50 @@ const { data, run } = useRequest(tradeConfigView, {
 })
 
 const detailProps: CellProp[] = [
-    { prop: 'usergroupid', label: 'investor.custom.tradecfg.usergroupid1', formatValue: () => info.value.groupName },
-    { prop: 'marketid', label: 'investor.custom.tradecfg.marketid1', formatValue: () => info.value.marketName },
-    { prop: 'goodsid', label: 'investor.custom.tradecfg.goodsid1', formatValue: () => info.value.goodsName },
-    { prop: 'paramid', label: 'investor.custom.tradecfg.paramid', formatValue: (val) => customerTypeEnum.getEnumTypeName(val) },
-    { prop: 'marketmarginvaluedisplay', label: 'investor.custom.tradecfg.marketmarginvaluedisplay' },
+    { prop: 'usergroupid', label: '交易商', formatValue: () => info.value.userName },
+    { prop: 'usergroupid', label: '资金账户', formatValue: () => info.value.accountName },
+    { prop: 'usergroupid', label: '商品', formatValue: () => info.value.goodsName },
+    { prop: 'paramid', label: '保证金类别', formatValue: (val) => customerTypeEnum.getEnumTypeName(val) },
 ]
 
 const ruleColumns = computed<Model.TableColumn[]>(() => [
-    { field: 'rulename', label: 'investor.custom.tradecfg.rulename' },
-    { field: 'paramvalue', label: 'investor.custom.tradecfg.paramvalue' },
-    { field: 'dvalue', label: 'investor.custom.tradecfg.dvalue', show: qs.value.usergroupid !== 0 },
-    { field: 'cvalue', label: 'investor.custom.tradecfg.cvalue' },
+    { field: 'rulename', label: '扩展项' },
+    { field: 'paramvalue', label: '平台' },
+    { field: 'dvalue', label: '会员' },
+    { field: 'gvalue', label: '分组' },
+    { field: 'cvalue', label: '个性化' },
 ])
 
 const feeColumns = computed<Model.TableColumn[]>(() => [
-    { field: 'tradefeename', label: 'investor.custom.tradecfg.tradefeename' },
-    { field: 'feealgorithm', label: 'investor.custom.tradecfg.feealgorithm', formatValue: (val) => getFeeAlgorithmName(val) },
-    { field: 'exchangevalue', label: 'investor.custom.tradecfg.exchangevalue' },
-    { field: 'dvalue', label: 'investor.custom.tradecfg.dvalue', show: qs.value.usergroupid !== 0 },
-    { field: 'cvalue', label: 'investor.custom.tradecfg.cvalue' },
+    { field: 'tradefeename', label: '费用项' },
+    { field: 'exchangevalue', label: '平台' },
+    { field: 'dvalue', label: '会员' },
+    { field: 'gvalue', label: '分组' },
+    { field: 'cvalue', label: '个性化' },
 ])
 
 // 表单验证规则
 const formRules: FormRules = {
-    usergroupid: [{ required: true }],
-    marketid: [{ required: true }],
+    userid: [{
+        required: true,
+        validator: (rule, value, callback) => {
+            if (selectedInvestor.value) {
+                callback()
+            } else {
+                callback(new Error('请选择交易商'))
+            }
+        },
+    }],
+    accountid: [{
+        required: true,
+        validator: (rule, value, callback) => {
+            if (selectedAccount.value) {
+                callback()
+            } else {
+                callback(new Error('请选择资金账户'))
+            }
+        },
+    }],
     goodsid: [{ required: true }],
 }
 
@@ -211,16 +250,18 @@ const onMarketChange = () => {
 
 const onSearch = () => {
     qs.value = {
-        usergroupid: selectedInvestor.value?.usergroupid,
-        marketid: selectedAccount.value?.marketid,
+        userid: selectedGoods.value?.userid,
+        accountid: selectedGoods.value?.accountid,
+        marketid: selectedGoods.value?.marketid,
         goodsid: selectedGoods.value?.goodsid,
+        tradetype: selectedGoods.value?.tradetype
     }
     nextTick(() => {
         formRef.value?.validate((valid) => {
             if (valid) {
                 info.value = {
-                    groupName: selectedInvestor.value?.name,
-                    marketName: selectedAccount.value?.name,
+                    userName: selectedInvestor.value?.name,
+                    accountName: selectedAccount.value?.name,
                     goodsName: selectedGoods.value?.name,
                 }
                 run(qs.value)

+ 44 - 48
src/packages/pc/views/investor/custom/tradecfg/components/add/index.vue

@@ -13,23 +13,21 @@
                     </el-select>
                 </el-form-item>
                 <el-form-item :label="t('investor.custom.tradecfg.edit.marketid')" prop="marketid">
-                    <el-select v-model="formData.marketid" :empty-values="[null, undefined, 0]"
-                        @change="onMarketChange">
+                    <el-select v-model="formData.marketid" @change="onMarketChange">
                         <template v-for="(item, index) in marketData?.markets" :key="index">
                             <el-option :label="item.marketname" :value="item.marketid" />
                         </template>
                     </el-select>
                 </el-form-item>
                 <el-form-item :label="t('investor.custom.tradecfg.edit.goodsid')" prop="goodsid">
-                    <el-select v-model="formData.goodsid" :empty-values="[null, undefined, 0]" @change="onGoodsChange">
+                    <el-select v-model="formData.goodsid" @change="onGoodsChange">
                         <template v-for="(item, index) in goodsData?.goods" :key="index">
                             <el-option :label="item.goodsname" :value="item.goodsid" />
                         </template>
                     </el-select>
                 </el-form-item>
                 <el-form-item :label="t('investor.custom.tradecfg.edit.paramid')" prop="paramid">
-                    <el-select v-model="formData.paramid" :empty-values="[null, undefined, 0]" @change="onResultChange"
-                        clearable>
+                    <el-select v-model="formData.paramid" @change="onResultChange" clearable>
                         <template v-for="(item, index) in resultData?.results" :key="index">
                             <el-option :label="item.enumdicname" :value="item.enumitemname" />
                         </template>
@@ -52,13 +50,12 @@
                 <!-- 个性化 -->
                 <template #cvalue="{ row, index }">
                     <template v-if="formData.ruleList[index]">
-                        <el-select v-model="formData.ruleList[index].paramvalue" :empty-values="[null, undefined, 0]"
-                            v-if="row.ruleid === 105">
+                        <el-select v-model="formData.ruleList[index].paramvalue" clearable v-if="row.ruleid === 105">
                             <template v-for="item in feetypeEnum.getEnumOptions()" :key="item.id">
                                 <el-option :label="item.label" :value="item.value" />
                             </template>
                         </el-select>
-                        <el-input-number v-model="formData.ruleList[index].paramvalue"
+                        <el-input-number v-model="formData.ruleList[index].paramvalue" :min="0"
                             :placeholder="t('common.pleaseenter')" v-else />
                     </template>
                 </template>
@@ -107,7 +104,7 @@
 </template>
 
 <script lang="ts" setup>
-import { ref, computed } from 'vue'
+import { ref, reactive, computed } from 'vue'
 import { ElMessage, FormInstance, FormRules } from 'element-plus'
 import { handleNoneValue } from '@/filters'
 import { getFeeAlgorithmName } from '@/constants/order'
@@ -126,13 +123,10 @@ const show = ref(true)
 const refresh = ref(false)
 const loading = ref(false)
 
-const formData = ref<Model.TraderPersonAddReq>({
+const formData = reactive<Model.TraderPersonAddReq>({
     feeList: [],
     flag: 0,
-    goodsid: 0,
-    marketid: 0,
-    ruleList: [],
-    usergroupid: 0
+    ruleList: []
 })
 
 // 分组树列表
@@ -155,21 +149,19 @@ const { data: goodsData, run: getGoodsList } = useRequest(initInvestorPerson, {
 const { data: resultData, run: getResultList } = useRequest(initInvestorPerson, {
     manual: true,
     onSuccess: (res) => {
-        formData.value.ruleList = []
-        formData.value.feeList = []
+        formData.ruleList = []
+        formData.feeList = []
 
         res.data.rulesConfigVos.forEach((e) => {
-            formData.value.ruleList.push({
-                paramid: e.ruleid,
-                paramvalue: 0
+            formData.ruleList.push({
+                paramid: e.ruleid
             })
         })
 
         res.data.feesConfigVos.forEach((e) => {
-            formData.value.feeList.push({
+            formData.feeList.push({
                 feealgorithm: e.feealgorithm,
-                paramid: e.tradefeeid,
-                paramvalue: 0
+                paramid: e.tradefeeid
             })
         })
     }
@@ -178,7 +170,7 @@ const { data: resultData, run: getResultList } = useRequest(initInvestorPerson,
 const ruleColumns = computed<Model.TableColumn[]>(() => [
     { field: 'rulename', label: 'investor.custom.tradecfg.edit.rulename' },
     { field: 'paramvalue', label: 'investor.custom.tradecfg.edit.paramvalue' },
-    { field: 'dvalue', label: 'investor.custom.tradecfg.edit.dvalue', show: formData.value.usergroupid !== 0 },
+    { field: 'dvalue', label: 'investor.custom.tradecfg.edit.dvalue', show: formData.usergroupid !== 0 },
     { field: 'cvalue', label: 'investor.custom.tradecfg.edit.cvalue' },
 ])
 
@@ -186,7 +178,7 @@ const feeColumns = computed<Model.TableColumn[]>(() => [
     { field: 'tradefeename', label: 'investor.custom.tradecfg.edit.tradefeename' },
     { field: 'feealgorithm', label: 'investor.custom.tradecfg.edit.feealgorithm', formatValue: (val) => getFeeAlgorithmName(val) },
     { field: 'exchangevalue', label: 'investor.custom.tradecfg.edit.exchangevalue' },
-    { field: 'dvalue', label: 'investor.custom.tradecfg.edit.dvalue', show: formData.value.usergroupid !== 0 },
+    { field: 'dvalue', label: 'investor.custom.tradecfg.edit.dvalue', show: formData.usergroupid !== 0 },
     { field: 'memberminvalue', label: 'investor.custom.tradecfg.edit.memberminvalue' },
     { field: 'fee', label: 'investor.custom.tradecfg.edit.fee', width: 200 },
     { field: 'membermaxvalue', label: 'investor.custom.tradecfg.edit.membermaxvalue' },
@@ -201,10 +193,10 @@ const formRules: FormRules = {
 
 // 选择分组
 const onGroupChange = (value: number) => {
-    formData.value.marketid = 0
-    formData.value.goodsid = 0
-    formData.value.paramid = 0
-    formData.value.feealgorithm = 0
+    formData.marketid = undefined
+    formData.goodsid = undefined
+    formData.paramid = undefined
+    formData.feealgorithm = undefined
     goodsData.value = undefined
     resultData.value = undefined
     getMarketList({
@@ -214,24 +206,24 @@ const onGroupChange = (value: number) => {
 
 // 选择市场
 const onMarketChange = (value: number) => {
-    formData.value.goodsid = 0
-    formData.value.paramid = 0
-    formData.value.feealgorithm = 0
+    formData.goodsid = undefined
+    formData.paramid = undefined
+    formData.feealgorithm = undefined
     goodsData.value = undefined
     resultData.value = undefined
     getGoodsList({
-        usergroupid: formData.value.usergroupid,
+        usergroupid: formData.usergroupid,
         marketid: value,
     })
 }
 
 // 选择商品
 const onGoodsChange = (value: number) => {
-    formData.value.paramid = 0
-    formData.value.feealgorithm = 0
+    formData.paramid = undefined
+    formData.feealgorithm = undefined
     getResultList({
-        marketid: formData.value.marketid,
-        usergroupid: formData.value.usergroupid,
+        marketid: formData.marketid,
+        usergroupid: formData.usergroupid,
         goodsid: value
     })
 }
@@ -239,23 +231,27 @@ const onGoodsChange = (value: number) => {
 // 选择保证金类别
 const onResultChange = (value?: number) => {
     const res = resultData.value?.results.find((e) => e.enumitemname === value?.toString())
-    formData.value.feealgorithm = res?.marginalgorithm
+    formData.feealgorithm = res?.marginalgorithm
 }
 
 const onSubmit = () => {
     formRef.value?.validate((valid) => {
         if (valid) {
-            loading.value = true
-            traderPersonAdd({
-                data: formData.value
-            }).then(() => {
-                ElMessage.success(t('common.tips3'))
-                onCancel(true)
-            }).catch((err) => {
-                ElMessage.error(t('common.tips4') + err)
-            }).finally(() => {
-                loading.value = false
-            })
+            if (formData.paramid || formData.ruleList.some((e) => e.paramid === 105 && e.paramvalue)) {
+                loading.value = true
+                traderPersonAdd({
+                    data: formData
+                }).then(() => {
+                    ElMessage.success(t('common.tips3'))
+                    onCancel(true)
+                }).catch((err) => {
+                    ElMessage.error(t('common.tips4') + err)
+                }).finally(() => {
+                    loading.value = false
+                })
+            } else {
+                ElMessage.warning('保证金类别,交易规则,交易服务费均未设置')
+            }
         }
     })
 }

+ 26 - 23
src/packages/pc/views/investor/custom/tradecfg/components/edit/index.vue

@@ -15,15 +15,14 @@
                     {{ handleNoneValue(goodsItem?.name) }}
                 </el-form-item>
                 <el-form-item :label="t('investor.custom.tradecfg.edit.paramid')" prop="paramid">
-                    <el-select v-model="formData.paramid" :empty-values="[null, undefined, 0]" @change="onResultChange"
-                        clearable>
+                    <el-select v-model="formData.paramid" @change="onResultChange" clearable>
                         <template v-for="(item, index) in resultData?.results" :key="index">
                             <el-option :label="item.enumdicname" :value="item.enumitemname" />
                         </template>
                     </el-select>
                 </el-form-item>
             </fieldset>
-            <app-table :data="resultData?.rulesConfigVos" :columns="ruleColumns">
+            <app-table :data="record.druleList" :columns="ruleColumns">
                 <!-- 商品设置值 -->
                 <template #paramvalue="{ row }">
                     <span v-if="row.ruleid === 105">{{ feetypeEnum.getEnumTypeName(row.paramvalue) }}</span>
@@ -39,7 +38,7 @@
                 <!-- 个性化 -->
                 <template #cvalue="{ row, index }">
                     <template v-if="formData.ruleList[index]">
-                        <el-select v-model="formData.ruleList[index].paramvalue" :empty-values="[null, undefined, 0]" v-if="row.ruleid === 105">
+                        <el-select v-model="formData.ruleList[index].paramvalue" clearable v-if="row.ruleid === 105">
                             <template v-for="item in feetypeEnum.getEnumOptions()" :key="item.id">
                                 <el-option :label="item.label" :value="item.value" />
                             </template>
@@ -49,7 +48,7 @@
                     </template>
                 </template>
             </app-table>
-            <app-table :data="resultData?.feesConfigVos" :columns="feeColumns">
+            <app-table :data="record.dfeeList" :columns="feeColumns">
                 <!-- 商品设置值 -->
                 <template #exchangevalue="{ row }">
                     <template v-if="row.feealgorithm">
@@ -96,7 +95,6 @@
 import { reactive, shallowRef, PropType, computed } from 'vue'
 import { ElMessage, FormInstance } from 'element-plus'
 import { handleNoneValue } from '@/filters'
-import { getFeeAlgorithmName } from '@/constants/order'
 import { useEnum } from '@/hooks/enum'
 import { useRequest } from '@/hooks/request'
 import { traderPersonAdd, getInvestorTree, initInvestorPerson } from '@/services/api/investor'
@@ -112,6 +110,7 @@ const props = defineProps({
 })
 
 const feetypeEnum = useEnum('feetype')
+const scfRiskMode = useEnum('SCFRiskMode')
 
 const { global: { t } } = i18n
 const formRef = shallowRef<FormInstance>()
@@ -144,16 +143,16 @@ const goodsItem = computed(() => nodeList.value.find((e) => e.pid === marketItem
 // 获取保证金类别列表
 const { data: resultData } = useRequest(initInvestorPerson, {
     params: {
-        usergroupid: formData.usergroupid,
-        marketid: formData.marketid,
-        goodsid: formData.goodsid
+        usergroupid: props.record.usergroupid,
+        marketid: props.record.marketid,
+        goodsid: props.record.goodsid
     },
     onSuccess: (res) => {
         res.data.rulesConfigVos.forEach((e) => {
             const rule = props.record.druleList.find((d) => d.ruleid === e.ruleid)
             formData.ruleList.push({
                 paramid: e.ruleid,
-                paramvalue: rule ? rule.cvalue : 0
+                paramvalue: rule?.cvalue
             })
         })
 
@@ -162,7 +161,7 @@ const { data: resultData } = useRequest(initInvestorPerson, {
             formData.feeList.push({
                 feealgorithm: e.feealgorithm,
                 paramid: e.tradefeeid,
-                paramvalue: fee ? fee.cvalue : 0
+                paramvalue: fee?.cvalue
             })
         })
     }
@@ -177,7 +176,7 @@ const ruleColumns = computed<Model.TableColumn[]>(() => [
 
 const feeColumns = computed<Model.TableColumn[]>(() => [
     { field: 'tradefeename', label: 'investor.custom.tradecfg.edit.tradefeename' },
-    { field: 'feealgorithm', label: 'investor.custom.tradecfg.edit.feealgorithm', formatValue: (val) => getFeeAlgorithmName(val) },
+    { field: 'feealgorithm', label: 'investor.custom.tradecfg.edit.feealgorithm', formatValue: (val) => scfRiskMode.getEnumTypeName(val) },
     { field: 'exchangevalue', label: 'investor.custom.tradecfg.edit.exchangevalue' },
     { field: 'dvalue', label: 'investor.custom.tradecfg.edit.dvalue', show: formData.usergroupid !== 0 },
     { field: 'memberminvalue', label: 'investor.custom.tradecfg.edit.memberminvalue' },
@@ -194,17 +193,21 @@ const onResultChange = (value?: number) => {
 const onSubmit = () => {
     formRef.value?.validate((valid) => {
         if (valid) {
-            loading.value = true
-            traderPersonAdd({
-                data: formData
-            }).then(() => {
-                ElMessage.success(t('common.tips3'))
-                onCancel(true)
-            }).catch((err) => {
-                ElMessage.error(t('common.tips4') + err)
-            }).finally(() => {
-                loading.value = false
-            })
+            if (formData.paramid || formData.ruleList.some((e) => e.paramid === 105 && e.paramvalue)) {
+                loading.value = true
+                traderPersonAdd({
+                    data: formData
+                }).then(() => {
+                    ElMessage.success(t('common.tips3'))
+                    onCancel(true)
+                }).catch((err) => {
+                    ElMessage.error(t('common.tips4') + err)
+                }).finally(() => {
+                    loading.value = false
+                })
+            } else {
+                ElMessage.warning('保证金类别,交易规则,交易服务费均未设置')
+            }
         }
     })
 }

+ 11 - 9
src/packages/pc/views/investor/custom/tradecfg/index.vue

@@ -69,8 +69,8 @@
                 <!-- 商品设置值 -->
                 <template #exchangevalue="{ row }">
                     <template v-if="row.feealgorithm">
-                        <span v-if="row.feealgorithm === 1">{{ parseTenThousand(row.exchangevalue) }}</span>
-                        <span v-else>{{ row.exchangevalue }}</span>
+                        <span>{{ scfRiskMode.getEnumTypeName(row.feealgorithm) }}:</span>
+                        <span>{{ row.exchangevalue + (row.feealgorithm === 1 && '‱') }}</span>
                     </template>
                     <template v-else>
                         {{ handleNoneValue() }}
@@ -79,8 +79,8 @@
                 <!-- 会员设置值 -->
                 <template #dvalue="{ row }">
                     <template v-if="row.drithm">
-                        <span v-if="row.drithm === 1">{{ parseTenThousand(row.dvalue) }}</span>
-                        <span v-else>{{ row.dvalue }}</span>
+                        <span>{{ scfRiskMode.getEnumTypeName(row.drithm) }}:</span>
+                        <span>{{ row.dvalue + (row.drithm === 1 && '‱') }}</span>
                     </template>
                     <template v-else>
                         {{ handleNoneValue() }}
@@ -89,8 +89,8 @@
                 <!-- 个性化 -->
                 <template #cvalue="{ row }">
                     <template v-if="row.crithm">
-                        <span v-if="row.crithm === 1">{{ parseTenThousand(row.cvalue) }}</span>
-                        <span v-else>{{ row.cvalue }}</span>
+                        <span>{{ scfRiskMode.getEnumTypeName(row.crithm) }}:</span>
+                        <span>{{ row.cvalue + (row.crithm === 1 && '‱') }}</span>
                     </template>
                     <template v-else>
                         {{ handleNoneValue() }}
@@ -108,7 +108,6 @@
 import { shallowRef, computed, nextTick, toRaw } from 'vue'
 import { ElMessage, FormInstance, FormRules } from 'element-plus'
 import { parseTenThousand, handleNoneValue } from '@/filters'
-import { getFeeAlgorithmName } from '@/constants/order'
 import { useEnum } from '@/hooks/enum'
 import { useRequest } from '@/hooks/request'
 import { useOperation } from '@/hooks/operation'
@@ -126,7 +125,9 @@ const { componentMap, componentId, openComponent, closeComponent, getActionButto
             onSearch()
         }
         if (componentId === 'investor_custom_tradecfg_delete') {
-            qs.value = {}
+            selectedGroup.value = undefined
+            selectedMarket.value = undefined
+            selectedGoods.value = undefined
             data.value = undefined
         }
     }
@@ -134,10 +135,12 @@ const { componentMap, componentId, openComponent, closeComponent, getActionButto
 
 const customerTypeEnum = useEnum('customerType')
 const feetypeEnum = useEnum('feetype')
+const scfRiskMode = useEnum('SCFRiskMode')
 
 const { global: { t } } = i18n
 const formRef = shallowRef<FormInstance>()
 const qs = shallowRef<Partial<Model.TradeConfigViewReq>>({})
+
 const info = shallowRef<Partial<{
     groupName: string,
     marketName: string,
@@ -185,7 +188,6 @@ const ruleColumns = computed<Model.TableColumn[]>(() => [
 
 const feeColumns = computed<Model.TableColumn[]>(() => [
     { field: 'tradefeename', label: 'investor.custom.tradecfg.tradefeename' },
-    { field: 'feealgorithm', label: 'investor.custom.tradecfg.feealgorithm', formatValue: (val) => getFeeAlgorithmName(val) },
     { field: 'exchangevalue', label: 'investor.custom.tradecfg.exchangevalue' },
     { field: 'dvalue', label: 'investor.custom.tradecfg.dvalue', show: qs.value.usergroupid !== 0 },
     { field: 'cvalue', label: 'investor.custom.tradecfg.cvalue' },

+ 1 - 1
src/packages/pc/views/member/subinstitution/transfer/components/edit/select-level/index.vue

@@ -63,7 +63,7 @@ const remoteMethod = (query: string) => {
 
 const onChange = (value?: number) => {
     const item = dataList.value.find((e) => e.userid === value)
-    emit('change', toRaw(item))
+    emit('change', item && toRaw(item))
 }
 
 defineExpose({

+ 21 - 0
src/services/api/investor/index.ts

@@ -303,6 +303,27 @@ export function getAccTradeTree(options: CommonFetchOptions<{ response: Model.Ac
 }
 
 /**
+ * 交易商管理-->个性化管理-->资金账户个性化--> 详情
+ */
+export function accTradeConfigView(options: CommonFetchOptions<{ request: Model.AccTradeConfigViewReq; response: Model.AccTradeConfigViewRsp; }>) {
+    return httpClient.commonRequest('/investor/accTradeConfigView', 'get', options)
+}
+
+/**
+ * 交易商管理-->个性化管理-->资金账户个性化--> 新增初始化交易商信息
+ */
+export function initAccTrade(options: CommonFetchOptions<{ request: Model.InitAccTradeReq; response: Model.InitAccTradeRsp[]; }>) {
+    return httpClient.commonRequest('/investor/initAccTrade', 'get', options)
+}
+
+/**
+ * 交易商管理-->个性化管理-->资金账户个性化--> 删除
+ */
+export function accTradeConfigDelete(options: CommonFetchOptions<{ request: Model.AccTradeConfigDeleteReq; }>) {
+    return httpClient.commonRequest('/investor/accTradeConfigDelete', 'get', options)
+}
+
+/**
  * 交易商管理-->交易商批量转移-->新增
  */
 export function investorTransferAdd(options: CommonFetchOptions<{ request: Partial<Model.InvestorTransferAddReq>; }>) {

+ 21 - 0
src/services/api/member/index.ts

@@ -356,4 +356,25 @@ export function organSonBackTranfor(options: CommonFetchOptions<{ request: Model
  */
 export function organSonExecuteTransfer(options: CommonFetchOptions = {}) {
     return httpClient.commonRequest('/organSon/executeTransfer', 'get', options)
+}
+
+/**
+ * 会员机构管理-->机构管理-->账户个性化设置-->新增初始化列表信息
+ */
+export function loadSelectOption(options: CommonFetchOptions<{ request: Partial<Model.LoadSelectOptionReq>; response: Model.LoadSelectOptionRsp; }>) {
+    return httpClient.commonRequest('/organDetail/loadSelectOption', 'get', options)
+}
+
+/**
+ * 会员机构管理-->机构管理-->账户个性化设置-->新增
+ */
+export function tradeConfigAdd(options: CommonFetchOptions<{ request: Model.TradeConfigAddReq; }>) {
+    return httpClient.commonRequest('/organDetail/tradeConfigAdd', 'post', options)
+}
+
+/**
+ * 会员机构管理-->机构管理-->账户个性化设置-->修改
+ */
+export function tradeConfigEdit(options: CommonFetchOptions<{ request: Model.TradeConfigAddReq; }>) {
+    return httpClient.commonRequest('/organDetail/tradeConfigEdit', 'post', options)
 }

+ 89 - 5
src/types/model/investor.d.ts

@@ -729,18 +729,18 @@ declare namespace Model {
         feeList: {
             feealgorithm: number; // 费用算法 - 1:比率 2:固定
             paramid: number; // 个性化参数ID - 1. 参照交易模式规则费用对应-参考表 可个性化类型 2.保证金类保存交易所创建的投资者客户类别ID
-            paramvalue: number; // 参数值(保证金类此项为空)
+            paramvalue?: number; // 参数值(保证金类此项为空)
         }[];
         feealgorithm?: number;
         flag: number; // 新增0,修改1
-        goodsid: number;
-        marketid: number;
+        goodsid?: number;
+        marketid?: number;
         paramid?: number;
         ruleList: {
             paramid: number; // 个性化参数ID - 1. 参照交易模式规则费用对应-参考表 可个性化类型 2.保证金类保存交易所创建的投资者客户类别ID
-            paramvalue: number; // 参数值(保证金类此项为空)
+            paramvalue?: number; // 参数值(保证金类此项为空)
         }[];
-        usergroupid: number;
+        usergroupid?: number;
     }
 
     /** 交易商管理-->个性化管理-->交易商个性化-->删除 请求 */
@@ -956,6 +956,90 @@ declare namespace Model {
         userid: number;
     }
 
+    /** 交易商管理-->个性化管理-->资金账户个性化--> 详情 请求 */
+    interface AccTradeConfigViewReq {
+        accountid: number;
+        goodsid: number;
+        marketid: number;
+        memberuserid?: number;
+        ruletype?: number;
+        tradetype: number;
+        usergroupid?: number;
+        usergroupid2?: number;
+        userid: number;
+    }
+
+    /** 交易商管理-->个性化管理-->资金账户个性化--> 详情 响应 */
+    interface AccTradeConfigViewRsp {
+        accountid: number; // 资金账号
+        accountname: string;
+        autoid: number; // 自增ID
+        createtime: string; // 创建时间
+        creatorid: number; // 创建人
+        dfeeList: {
+            crithm: number;
+            cvalue: number;
+            drithm: number;
+            dvalue: number;
+            exchangevalue: number;
+            feealgorithm: number;
+            grithm: number;
+            gvalue: number;
+            membermaxvalue: number;
+            memberminvalue: number;
+            qtydecimalplace: number;
+            tradefeeid: number;
+            tradefeename: string;
+        }[];
+        druleList: {
+            cvalue: number;
+            defaultvalue: number;
+            dvalue: number;
+            gvalue: number;
+            paramvalue: number;
+            qtydecimalplace: number;
+            regexpress: string;
+            remark: string;
+            ruleid: number;
+            rulename: string;
+        }[];
+        feealgorithm: number; // 费用算法 - 1:比率 2:固定
+        goodsid: number; // 商品ID
+        goodsname: string;
+        marketid: number; // 市场ID
+        marketname: string;
+        memberuserid: number; // 所属会员ID
+        paramid: number; // 个性化参数ID - 1. 参照交易模式规则费用对应-参考表 可个性化类型 2.保证金类保存交易所创建的投资者客户类别ID
+        paramvalue: number; // 参数值(保证金类此项为空)
+        ruletype: number; // 参数类型 -1.保证金类 2.交易规则 3.交易费用
+        tradetype: number; // 交易类型[交易费用] - 1:投资者自营 2:做市
+        userid: number; // 用户ID
+    }
+
+    /** 交易商管理-->个性化管理-->资金账户个性化--> 新增初始化交易商信息 请求 */
+    interface InitAccTradeReq {
+        searchName?: string;
+    }
+
+    /** 交易商管理-->个性化管理-->资金账户个性化--> 新增初始化交易商信息 响应 */
+    interface InitAccTradeRsp {
+        accountname: string;
+        userid: number;
+    }
+
+    /** 交易商管理-->个性化管理-->资金账户个性化--> 删除 请求 */
+    interface AccTradeConfigDeleteReq {
+        accountid: number;
+        goodsid: number;
+        marketid: number;
+        memberuserid: number;
+        ruletype?: number;
+        tradetype: number;
+        usergroupid?: number;
+        usergroupid2?: number;
+        userid: number;
+    }
+
     /** 交易商管理-->交易商批量转移-->新增 请求 */
     interface InvestorTransferAddReq {
         diversioninlevel: number; // 转入类型

+ 190 - 0
src/types/model/member.d.ts

@@ -1817,4 +1817,194 @@ declare namespace Model {
     interface OrganSonBackTranforReq {
         autoid: number;
     }
+
+    /** 会员机构管理-->机构管理-->账户个性化设置-->新增初始化列表信息 请求 */
+    interface LoadSelectOptionReq {
+        accountid: number;
+        goodsid: number;
+        marketid: number;
+        memberuserid: number;
+        ruletype: number;
+        tradetype: number;
+        usergroupid: number;
+        usergroupid2: number;
+        userid: number;
+    }
+
+    /** 会员机构管理-->机构管理-->账户个性化设置-->新增初始化列表信息 响应 */
+    interface LoadSelectOptionRsp {
+        accountids: number[];
+        feesConfigVos: {
+            crithm: number;
+            cvalue: number;
+            drithm: number;
+            dvalue: number;
+            exchangevalue: number;
+            feealgorithm: number;
+            grithm: number;
+            gvalue: number;
+            membermaxvalue: number;
+            memberminvalue: number;
+            qtydecimalplace: number;
+            tradefeeid: number;
+            tradefeename: string;
+        }[];
+        goods: {
+            agreeunit: number; // 期货合约乘数
+            areauserid: number; // 所属机构
+            auditaccountid: number; // 审核操作员账号
+            audittime: string; // 审核时间
+            cancelaccountid: number; // 注销操作员账号
+            canceltime: string; // 注销时间
+            closepricemode: number; // 强平价格方式 - 1:市价 2:最新价 3:涨跌停(未实现)
+            closepriceparam: number; // 强平最新价浮动比例 - 方式为2时使用 (<1)买 上浮 (1+x)最新价卖 下浮 (1-x)最新价
+            createtime: string; // 创建时间
+            creatorid: number; // 创建人
+            currencyid: number; // 报价货币ID
+            cutmode: number; // 斩仓方式 - 1:不斩仓 2:自动斩仓 3:半自动斩仓
+            decimalplace: number; // 报价小数位
+            delistingdate: string; // 实际退市时间(状态:待退市, 预售一口价、预售大宗直接改为退市)
+            delistingmode: number; // 退市方式 - 1:退市平仓 2:退市交收 3:不处理(仅期权币币兑换) 4:退市发货(所有权)
+            deliveryflag: number; // 交割标志 - 0:不可交割 1:可交割
+            forceclosemode: number; // 定期强平方式 - 1:无 2:每日 3:每周 4:每月[收益权]
+            forceclosevalue: number; // 定期强平参数 [收益权]
+            goodscode: string; // 期货合约代码(内部)
+            goodscurrencyid: number; // 合约货币ID
+            goodsgroupid: number; // 期货品种ID
+            goodsid: number; // 期货合约ID(自增ID SEQ_GOODS)
+            goodsname: string; // 期货合约名称
+            goodsquotetype: number; // 合约报价类型: 1-直接报价 2-间接报价
+            goodsstatus: number; // 商品状态- 1:待审核 2:未上市 3:上市 4:已注销 5:审核拒绝 6:退市 7:待退市
+            goodstradetype: number; // 商品交易权限类型 - 1:可建可平 2:可建不可平 3:不可建可平 4:不可建不可平
+            goodunitid: number; // 报价单位ID
+            hasquoter: number; // 是否有报价商 - 0:无报价商 1:有报价商
+            hqprotecttime: number; // 行情保护时间(秒)
+            innerdealmode: number; // 内部成交方式[通道交易] - 1:净头寸 2:开平 3:平今
+            isbuylimited: number; // 是否限制建仓量 - 0:不限制 1:限制
+            isvisible: number; // 游客是否可见 - 0:不可见 1:可见
+            lasttradedate: string; // 最后交易日期
+            listingdate: string; // 交易开始日期
+            marginalgorithm: number; // 持仓定金方式(49) - 1:比率 2.固定(52)
+            marketid: number; // 所属市场ID
+            modifierid: number; // 修改人
+            modifystatus: number; // 变更状态 - 1:未变更 2:变更中 3:待审核 4:已审核
+            modifytime: string; // 修改时间
+            newtransferdepositratio: number; // 转让定金比例(新)(49*)
+            outerdealmode: number; // 外部成交方式[通道交易]- 1:净头寸 2:开平 3:平今
+            outgoodscode: string; // 期货合约代码(外部)
+            pictureurl: string; // 商品图片(逗号)
+            presaleflag: number; // 发售标识(49) - 1:未预售 2:预售完成 3:预售申请中 4:预售中
+            presaleprice: number; // 发售价订货价(49)
+            provideraccountid: number; // 发售方资金账户ID(49)供货商资金账户ID(50)
+            provideruserid: number; // 发售方用户ID(49)供货商(50)
+            providerusername: string;
+            qtydecimalplace: number; // 成交量小数位
+            quotegear: number; // 行情档位(1-10)
+            quoteminunit: number; // 行情最小变动单位 [整数,报价小数位一起使用]
+            quoteshowtype: number; // 行情报价类型: 1:成交价 2:买卖中间价 3:含买价 4:含卖价 做市模式固定为3:含买价
+            quoteshowtypeinterval: number; // 行情报价间隔时间(秒)(成交价时为0)
+            refgoodscode: string; // 参考商品代码
+            refgoodsid: number; // 参考商品ID
+            remark: string; // 备注
+            swapdays: number; // 掉期天数
+            transferdepositratio: number; // 转让定金比例(49)持仓定金(52)
+        }[];
+        markets: {
+            auctionwrtype: number; // 仓单类型(现货交易) - 1:无仓单 2:有仓单 3;有无仓单均可
+            buyspotrighttype: number;
+            canacceptquote: number; // 确认行权是否接收行情 - 0:不接受 1:接受 [可确认权的挂牌期权市场可配置]
+            cangoodsexercise: number; // [期权]是否可现货行权- 0:否 1:是 是否交收
+            cangoodsexercisetype: number; // 可现货行权期权类型 - 1:认购 2认沽 3:认购认沽 [CanGoodsExercise = 1时可设置]
+            canmanualquotestrike: number; // 是否可手动报行权价- 0:否 1:是 [期权]
+            canmutistage: number; // 是否可多段运行 – 0:不可 1:可 [挂牌期权]
+            canpreexercise: number; // [期权]是否可预申报- 0:否 1:是
+            clearinterval: number; // 待开市间隔(交易市场开盘前多久发市场待开市信号(单位分钟))
+            contracttmp: string; // 合同模板[荷兰式][竞价式][仓单贸易]
+            deliverymode: number; // 交收方式(50模式) 1:配对交收 2:强平日交收
+            exchareaid: number; // 所属交易所,可以没有
+            financemarketid: number; // 融资回购市场ID [仓单贸易]
+            forceclosemode: number; // 定期强平方式 - 1:到期结 2:日结 3:周结 4:月结 [收益权] 枚举-forceCloseMode
+            forceclosevalue: number; // 定期强平参数 [收益权](周结、月结)
+            goodstype: number; // 商品类型 - 1:交易商品 2:仓单商品
+            hasrebate: number; // 是否返利[竞价式] 0:不返,1:返利 – 根据系统参数088显示或隐藏
+            hastradecredit: number; // 是否交易授信[做市收益权] - 0:不授信 1:授信
+            haswr: number; // [竞拍]是否需要仓单 - 0:不需要 1:需要- 作废
+            isdeductmargin: number; // 竞拍违约是否扣除保证金[竞拍-降价式] - 0:不扣 1:扣除
+            isdeliverybuyerpayonline: number; // 交收买方是否线上支付(50模式) - 0:否 1:是
+            isdeliverysellercanapply: number; // 卖方是否可申请交收(50模式 - DeliveryMode = 2时) - 0:否 1:是
+            isrecordsource: number; // 是否记录成交源 - 0:不记录 1:记录 [所有权]
+            isreleasemargin: number; // 成交参与保证金是否释放[竞价式] - 0:不释放 1释放
+            isupdatereckonprice: number; // 输入结算价标识 - 0:系统生成 1:手工输入(自动) 2:手工输入(手动)
+            marginformula: number; // 持仓保证金公式 - 1:双边收 2:净头寸收 3:大小边差异收 4:大边收 5:卖持仓收(仅期权)
+            marginformula2: number; // 持仓保证金公式(仅受托竞价) - 1:双边收 2:净头寸收 3:大小边差异收 4:大边收 5:卖持仓收(仅期权)
+            marketid: number; // 市场ID正常5位,前三位固定:两位表示交易模式, 一位表示交易属性(1:收益权,2:所有权) 其它特殊市场:0-系统 1-交割服务 2-账户服务3-履约服务 4-仓单服务 5-积分服务 6-银行服务
+            marketname: string; // 市场名称
+            marketserviceid: number; // 市场服务ID
+            marketstatus: number; // 生效状态(ValidStatus枚举): 1:待生效 2:正常 3:注销
+            markettype: number; // 市场类型- 1:非交易服务 2:交易服务
+            matchermode: number; // 指定对手模式[仓单贸易模式专用] - 1:任意对手 - 作废
+            openmethod: number; // 开盘模式 - 0 自动 1手动
+            otcuserid: number; // 场外期权做市商[场外期权]
+            outersynctime: string; // 外部同步时间点(h24:mi:ss)[场外期权]
+            paylaterflag: number; // 是否支持后付 - 0:不支持 1;支持 - [挂牌点选 所有权、预售挂牌支持]
+            pendingflag: number; // 待开市时间标识[通道交易-对冲] - 0:当日 1:上日
+            pendingtime: string; // 待开市时间通道交易-对冲
+            performancetempid: number; // 履约计划模板ID - 作废
+            premiumquotemode: number; // 权利金报价方式 - 1:自动 2:手动
+            rebateratio: number; // 返利比率[竞价式]
+            reckonorder: number; // 结算顺序
+            reckonpricealgorithm: number; // 结算价算法: 1:最后多少笔成交价加权平均 2:最后多少秒成交价加权平均 3:全天加权平均 4:最后一口价 5.买一价 6.卖一价 7.买一卖一均价 8.外部结算价
+            reckonpriceparam: number; // 结算价参数
+            reckontime: string; // 结算时间通道交易-对冲
+            riskcontrolmode: number; // 风控方式(52模式) 1:按单风控 2:按账户风控
+            roleprioritytype: number; // 角色优先类型 - 1:无 2:报价商优先 3:非报价商优先 [16:挂牌点选]
+            roletype: number;
+            selllistingauditflag: number; // 卖挂牌是否需要审核(仓单贸易) - 0:不需要 1:需要
+            spotrighttype: number;
+            trademarkettype: number; // 交易市场类型 - 1:合约市场 2:外部市场 3:仓单市场
+            trademode: number; // 交易模式 - 10:做市 13:竞价 15:通道交易 16:挂牌点选 17:仓单贸易 18:期权 19:竞拍-降价式 20:竞拍-竞价式 21:竞拍-大宗式 22:受托竞价
+            tradeproperty: number; // 交易属性 - 1:收益权(可做空) 2:所有权(不可做空) 3:期权 4:现货 5:参考行情 6:通道交易 7:币交易 8:场外期权
+            tradetype: number; // 下单方式[通道交易] - 1:直接转单 2:净头寸下单
+            updatereckonpriceinterval: number; // 输入结算价时长(分钟) [1:手工输入(自动)]
+        }[];
+        results: {
+            enumdicname: string;
+            enumitemname: number;
+            marginalgorithm: number;
+            marketmarginvalue: number;
+        }[];
+        rulesConfigVos: {
+            cvalue: number;
+            defaultvalue: number;
+            dvalue: number;
+            gvalue: number;
+            paramvalue: number;
+            qtydecimalplace: number;
+            regexpress: string;
+            remark: string;
+            ruleid: number;
+            rulename: string;
+        }[];
+    }
+
+    /** 会员机构管理-->机构管理-->账户个性化设置-->新增 请求 */
+    interface TradeConfigAddReq {
+        memberuserid: number;
+        accountid?: number;
+        feeList: {
+            feealgorithm: number; // 费用算法 - 1:比率 2:固定
+            paramid: number; // 个性化参数ID - 1. 参照交易模式规则费用对应-参考表 可个性化类型 2.保证金类保存交易所创建的投资者客户类别ID
+            paramvalue?: number; // 参数值(保证金类此项为空)
+        }[];
+        feealgorithm?: number;
+        goodsid?: number;
+        marketid?: number;
+        paramid?: number;
+        ruleList: {
+            paramid: number; // 个性化参数ID - 1. 参照交易模式规则费用对应-参考表 可个性化类型 2.保证金类保存交易所创建的投资者客户类别ID
+            paramvalue?: number; // 参数值(保证金类此项为空)
+        }[];
+        tradetype: number;
+        userid?: number;
+    }
 }