This commit is contained in:
李远 2026-03-14 17:04:54 +08:00
parent 27be2e59ca
commit c8e9b79bce
9 changed files with 756 additions and 241 deletions

View File

@ -9,4 +9,9 @@ export async function getMarketListApi(params: searchParams): Promise<any> {
//获取代理点差配置
export async function getPointDiffConfigApi(params: pointDiffConfigParams): Promise<any> {
return request.get<any>('/agent/getSelfVarietyPointDiffConfig',{...params})
}
}
//获取所属上级列表
export async function getParAgentListApi(params: pointDiffConfigParams): Promise<any> {
return request.get<any>('/agent/getParAgentListByRoleId',{...params})
}

View File

@ -4,5 +4,6 @@ export interface searchParams {
}
//获取代理点差配置
export interface pointDiffConfigParams {
user_id: number | string
user_id?: number | null
role_id?: number | string
}

View File

@ -9,7 +9,7 @@
<!-- 下拉选择框 -->
<el-select v-else-if="item.type === 'select'" v-model="formData[item.prop]"
:placeholder="item.placeholder" :disabled="item.disabled" clearable style="width: 100%">
:placeholder="item.placeholder" :disabled="item.disabled" clearable style="width: 100%" @change="handleItemChange(item.prop, formData[item.prop])">
<el-option v-for="option in props.optionsMap?.[item.prop] || []" :key="option.value"
:label="option.label" :value="option.value">
<template v-if="option.icon" #label>
@ -80,7 +80,11 @@ interface Props {
const formRef = ref<FormInstance>()
const props = defineProps<Props>()
const emit = defineEmits(['form-item-change'])
const handleItemChange = (field: string, value: any) => {
emit('form-item-change', field, value)
}
//
defineExpose({
validate: () => formRef.value?.validate(),

View File

@ -56,9 +56,6 @@
<!-- 操作按钮 -->
<el-form-item>
<el-button type="primary" @click="$emit('search')">
<el-icon>
<Search />
</el-icon>
{{ buttonConfig.searchText || '查询' }}
</el-button>
<el-button @click="$emit('reset')">

View File

@ -179,7 +179,7 @@ const fetchAgentPointDiffConfig = async (id: number | string) => {
try {
const data = await getPointDiffConfigApi(params)
//
agentPointTree.value = data.data.map((item: any) => ({
agentPointTree.value = data.map((item: any) => ({
...item,
varietyName: item.name,
varietyCode: item.code,

View File

@ -1,17 +1,19 @@
<template>
<div class="market">
<!-- 搜索 -->
<MarketSearch :search-form="marketSearchForm" :search-options="marketSearchOptions" @search="handleSearch"
@reset="handleReset">
<template #button="{ form }">
<el-button type="primary" @click="handleAddAgent()">
添加代理
<el-button type="primary" @click="handleAddMarket()">
添加
</el-button>
<el-button type="primary" @click="handleEditAgent(row)">
<el-button type="primary" @click="handleEditMarket()">
编辑
</el-button>
</template>
</MarketSearch>
<!-- 表格 -->
<MarketTable :table-data="marketTree" :columns="marketTableColumnsOptions" row-key="id">
<template #pointSpread="{ row }">
<el-button type="primary" size="small" @click="handleViewPointDiff(row)">
@ -19,19 +21,10 @@
</el-button>
</template>
</MarketTable>
<AgentPagination v-model="marketSearchForm.page" v-model:page-size-value="marketSearchForm.pageSize"
:total="marketSearchForm.total" @pagination-change="handlePaginationChange" />
<MarketDialog :visible="dialogVisible" :title="dialogTitle" :type="dialogType" @submit="handleSubmit"
@cancel="handleCancel" @close="handleClose" :fullscreen="dialogFullscreen"
:class="{ isAddOrEdit: 'isAddOrEdit-dialog' }">
<MarketForm :form-data="marketForm" :form-rules="marketFormRules" :form-items="marketFormItemOptions"
:options-map="marketFormOptionsMap" v-if="isAddOrEdit" />
<MarketTable :table-data="marketPointTree" :columns="marketPointTableColumnsOptions" row-key="id" />
</MarketDialog>
</div>
</template>
<script lang="ts" setup>
<script setup lang="ts">
//
import MarketSearch from '@/components/common/Search.vue'
import MarketTable from '@/components/common/Table.vue'
@ -39,251 +32,142 @@ import MarketPagination from '@/components/common/Pagination.vue'
import MarketDialog from '@/components/common/Dialog.vue'
import MarketForm from '@/components/common/Form.vue'
//
import { getMarketListApi, getPointDiffConfigApi } from '@/api/modules/account/market'
//
import { marketSearch, marketTableColumns } from './options'
//
import { marketSearch, marketTableColumns, marketFormItem, marketPointTableColumns } from './options'
//
import { getMarketListApi } from '@/api/modules/account/market'
/**
* @description 搜索配置
*/
const marketSearchForm = ref<any>({
accountName: '',
page: 1,
pageSize: 10,
* @description 定义搜索数据
*/
const marketSearchForm = ref({
accountName: ''
})
const marketSearchOptions = ref<any>(marketSearch)
const marketSearchOptions = ref(marketSearch)
/**
* @description 表格配置
*/
const marketTableColumnsOptions = ref<any>(marketTableColumns)
const marketTree = ref<any>([
{
id: 1,
agentRelation: "一级代理", //
accountName: "代理001", //
level: "一级", //
basicAccount: "500000.00", //
margin: "100000.00", //
stopOrderMargin: "50000.00", //
positionTransferMargin: "30000.00", //
pointSpreadCommission: "8520.68", //
pointSpread: "0.58", //
commissionRatio: "0.05%", //
commissionReturn: "4260.34", //
closeProfitLoss: "12850.72", //
riskMargin: "20000.00", //
serviceFee: "1500.00" //
},
{
id: 2,
agentRelation: "二级代理", //
accountName: "代理002", //
level: "二级", //
basicAccount: "200000.00", //
margin: "50000.00", //
stopOrderMargin: "20000.00", //
positionTransferMargin: "10000.00", //
pointSpreadCommission: "3680.25", //
pointSpread: "0.32", //
commissionRatio: "0.03%", //
commissionReturn: "1104.08", //
closeProfitLoss: "4820.15", //
riskMargin: "8000.00", //
serviceFee: "600.00" //
}
])
* @description 定义表格数据
*/
const marketTree = ref([])
const marketTableColumnsOptions = ref(marketTableColumns)
/**
* @description 分页配置
*/
const total = ref<number>(0)
* @description 定义分页数据
*/
const total = ref(0)
const page = ref(1)
const pageSize = ref(10)
/**
* @description dialog配置
*/
const dialogVisible = ref<boolean>(false)
const dialogTitle = ref<string>('')
const dialogType = ref<string>('add')
const dialogFullscreen = ref(false)
* @description 定义dialog数据
*/
/**
* @description 点差表格配置
*/
const marketPointTree = ref<any>([])
const marketPointTableColumnsOptions = ref<any>(marketPointTableColumns)
* @description 数据处理方法
*/
//
const mapMarketTree = (data: any) => {
return data.map((item: any) => ({
...item,
id:item.id, //id
agentRelation:item.path_name,//
accountName: item.username,//
level: item.role_id,//
basicAccount: item.wallet_capital.amount,//
margin: item.wallet_capital.bail,//
stopOrderMargin: item.wallet_capital.bail_stop_order,//
positionTransferMargin: item.wallet_capital.bail_change_order,//
positionRatio: item.wallet_capital.toucun_percent,//
pointSpreadCommission: item.wallet_capital.commission_point_diff,//
commissionRatio: item.wallet_capital.fee_handling_percent,//
commissionReturn: item.wallet_capital.commission_fee_handling,//
floatProfitLoss:"后续添加",//
closeProfitLoss: item.wallet_capital.closing_profit,//
riskMargin: item.wallet_capital.risk,//
serviceFee: item.wallet_capital.service//
}))
}
/**
* @description 表单数据
*/
const isAddOrEdit = ref<boolean>(false)
const marketForm = ref<any>({
accountName: '',
level: '',
parentAccountName: '',
position: '',
commissionRatio: '',
})
const marketFormItemOptions = ref<any>(marketFormItem)
const marketFormRules = ref<any>()
const marketFormOptionsMap = ref<any>({
})
/**
* @description 统一获取数据
*/
* @description 统一数据获取
*/
//
const fetchMarketList = async () => {
const getMarketList = async () => {
const params = {
page: marketSearchForm.value.page,
page_size: marketSearchForm.value.pageSize,
page: page.value,
page_size: pageSize.value,
user_name: marketSearchForm.value.accountName
}
const data = await getMarketListApi(params)
//
marketTree.value = data.data.map((item: any) => ({
...item,
agentRelation: item.path_name || '--', //
accountName: item.username || '', //
level: item.role_id || '', // role_id 1-> 2->
basicAccount: item.wallet_capital?.amount || '0.00000', //
margin: item.wallet_capital?.bail || '0.00000', //
stopOrderMargin: item.wallet_capital?.bail_stop_order || '0.00000', //
positionTransferMargin: item.wallet_capital?.bail_change_order || '0.00000', //
pointSpreadCommission: item.wallet_capital?.commission_point_diff || '0.00000', //
commissionRatio: item.wallet_capital?.toucun_percent || '0.00000', //
commissionReturn: item.wallet_capital?.commission_fee_handling || '0.00000', //
closeProfitLoss: item.wallet_capital?.closing_profit || '0.00000', //
riskMargin: item.wallet_capital?.risk || '0.00000', //
serviceFee: item.wallet_capital?.service || '0.00000' //
}))
console.log('data', data);
//
marketTree.value = mapMarketTree(data.data)
//
total.value = Number(data.total)
marketSearchForm.value.page = Number(data.current_page)
marketSearchForm.value.pageSize = Number(data.per_page)
}
//
const fetchPointDiffConfig = async () => {
const params = {
user_id: marketForm.value.id
}
const data = await getPointDiffConfigApi(params)
total.value = data.total
page.value = data.current_page
pageSize.value = data.per_page
}
/**
* @description 组件挂载时获取数据
*/
* @description 页面加载完成后需要获取的数据
*/
onMounted(() => {
fetchMarketList()
getMarketList()
})
/**
* @description 搜索
*/
* @description search方法
*/
//
const handleSearch = async () => {
await fetchMarketList()
}
const handleReset = () => {
marketSearchForm.value.accountName = ''
handleSearch()
await getMarketList()
}
/**
* @description 处理弹窗类型
*/
const handleDialogType = (type: string) => {
console.log('handleDialogType', type)
if (type === 'add') {
isAddOrEdit.value = true
} else {
isAddOrEdit.value = false
//
const handleReset = async () => {
marketSearchForm.value = {
accountName: ''
}
page.value = 1
pageSize.value = 10
await getMarketList()
}
/**
* @description 新增做市商
*/
const handleAddAgent = () => {
dialogVisible.value = true
dialogTitle.value = '新增做市商'
dialogType.value = 'add'
handleDialogType(dialogType.value)
//
const handleAddMarket = async () => {
console.log('添加做市商');
}
/**
* @description 编辑做市商
*/
const handleEditAgent = (row: any) => {
dialogVisible.value = true
dialogTitle.value = '编辑做市商'
dialogType.value = 'edit'
marketForm.value = { ...row }
handleDialogType(dialogType.value)
}
//
const handleEditMarket = async () => {
console.log('编辑做市商');
/**
* @description 查看点差
*/
const handleViewPointDiff = (row: any) => {
dialogVisible.value = true
dialogTitle.value = '查看点差'
dialogType.value = 'view'
handleDialogType(dialogType.value)
}
/**
* @description 分页变更
*/
const handlePaginationChange = (params: any) => {
marketSearchForm.value.page = params.currentPage
marketSearchForm.value.pageSize = params.pageSize
handleSearch()
}
/**
* @description 提交表单
*/
const handleSubmit = async () => {
if (dialogType.value === 'add') {
} else if (dialogType.value === 'edit') {
}
dialogVisible.value = false
handleSearch()
* @description 表格方法
*/
//
const handleViewPointDiff = async (row: any) => {
console.log('查看点差', row);
}
/**
* @description 取消操作
*/
const handleCancel = () => {
dialogVisible.value = false
dialogType.value = 'add'
}
/**
* @description 关闭弹窗
*/
const handleClose = () => {
dialogVisible.value = false
dialogType.value = 'add'
}
* @description dialog方法
*/
</script>
<style scoped lang="scss">
.el-form {
.el-form-item {
flex: none !important;
}
}
.market {
.search-container {
:deep(.el-form) {
@ -293,15 +177,4 @@ const handleClose = () => {
}
}
}
:deep(.el-dialog) {
.el-dialog__footer {
display: none;
}
}
:deep(.edit-dialog) {
.el-dialog__footer {
display: block;
}
}
</style>

View File

@ -1,13 +1,14 @@
//做市商搜索配置
export const marketSearch = [
{ label: '账户名', prop: 'accountName', type: 'input', placeholder: '请输入账户名', width: '340px', },
{ label: '账户名', prop: 'accountName', type: 'input' as const, placeholder: '请输入账户名', width: '340px', },
]
export const marketTableColumns = [
// id
{ label: 'ID', prop: 'id', align: 'center' as const },
//代理关系
{ label: '代理关系', prop: 'agentRelation', align: 'center' as const },
{ label: '代理关系', prop: 'agentRelation', align: 'center' as const, width: '200px' },
//账户名
{ label: '账户名', prop: 'accountName', align: 'center' as const },
//级别
@ -20,6 +21,8 @@ export const marketTableColumns = [
{ label: '停止接单保证金', prop: 'stopOrderMargin', align: 'center' as const, width: '160px' },
//持仓转移保证金
{ label: '持仓转移保证金', prop: 'positionTransferMargin', align: 'center' as const, width: '160px' },
//头寸比率
{ label: '头寸比率', prop: 'positionRatio', align: 'center' as const },
//点差返佣
{ label: '点差返佣', prop: 'pointSpreadCommission', align: 'center' as const },
//点差
@ -28,10 +31,10 @@ export const marketTableColumns = [
{ label: '手续费比例', prop: 'commissionRatio', align: 'center' as const },
//手续费返佣
{ label: '手续费返佣', prop: 'commissionReturn', align: 'center' as const },
//平仓盈亏
{ label: '平仓盈亏', prop: 'closeProfitLoss', align: 'center' as const },
//浮动盈亏
{ label: '浮动盈亏', prop: 'floatProfitLoss', align: 'center' as const },
//平仓盈亏
{ label: '平仓盈亏', prop: 'closeProfitLoss', align: 'center' as const },
//风险金
{ label: '风险金', prop: 'riskMargin', align: 'center' as const },
//服务费
@ -40,17 +43,16 @@ export const marketTableColumns = [
//做市商添加配置
export const marketFormItem = [
//注册方式
{ prop: 'phoneOrEmail', label: '', type: 'slot' as const, slotName: 'phoneOrEmail' },
//账户名称
{ label: '账户名称', prop: 'accountName', type: 'input', placeholder: '请输入账户名称', },
//级别
{
label: '级别', prop: 'level', type: 'select', placeholder: '请选择级别', options: [
{ label: '一级', value: '1' },
{ label: '二级', value: '2' },
{ label: '三级', value: '3' },
]
},
{ label: '级别', prop: 'level', type: 'select', placeholder: '请选择级别'},
//所属上级
{ label: '所属上级', prop: 'parentAccountName', type: 'select', placeholder: '请输入所属上级账户名称', },
// 风控模板
{ label: '风控模板', prop: 'riskControlTemplate', type: 'select', placeholder: '请选择风控模板'},
//头寸
{ label: '头寸', prop: 'position', type: 'input', placeholder: '请输入头寸', },
//手续费
@ -60,5 +62,20 @@ export const marketPointTableColumns = ([
{ prop: 'varietyName', label: '名称', align: 'center' as const },
{ prop: 'varietyCode', label: '编号', align: 'center' as const },
{ prop: 'pointDifference', label: '可分配点差', align: 'center' as const },
{ prop: 'assignedPointDifference', label: '已分配点差', align: 'center' as const },
{ prop: 'assignedPointDifference', label: '已分配点差', align: 'center' as const, slotName:'assignedPointDiff' ,width:'160px',height:'600px'},
])
// 国家码选项
interface CountryItem {
name: string
code: string
}
export const countryOptions = ref<CountryItem[]>([
{ name: '中国', code: '+86' },
{ name: '中国台湾', code: '+886' },
{ name: '中国香港', code: '+852' },
{ name: '中国澳门', code: '+853' },
{ name: '韩国', code: '+82' },
{ name: '美国', code: '+1' },
{ name: '新加坡', code: '+65' }
])

View File

@ -0,0 +1,95 @@
// rules.ts
import type { FormRules } from 'element-plus'
// 接收上级上限参数
export const rules = (parentLimit: any = { position: 0, commissionRatio: 0 }): FormRules => {
return {
//手机号
phone: [
{ required: true, message: '请输入手机号', trigger: ['blur'] },
{ pattern: /^1[3-9]\d{9}$/, message: '请输入正确的手机号格式', trigger: ['blur'] },
],
//邮箱
email: [
{ required: true, message: '请输入邮箱地址', trigger: ['blur'] },
{ type: 'email', message: '请输入正确的邮箱格式', trigger: ['blur'] }
],
accountName: [
{ required: true, message: '请输入账户名称', trigger: 'blur' },
{ min: 2, max: 50, message: '账户名称长度需在2-50个字符之间', trigger: 'blur' }
],
level: [
{ required: true, message: '请选择级别', trigger: 'change' }
],
parentAccountName: [
{ required: true, message: '请选择所属上级', trigger: 'change' }
],
// 头寸:新增「不超过上级」校验
position: [
{ required: true, message: '请输入头寸', trigger: 'blur' },
{ pattern: /^-?\d+(\.\d+)?$/, message: '头寸需为数字(支持整数/小数/负数)', trigger: 'blur' },
{
validator: (rule, value, callback) => {
if (!value) return callback()
const inputVal = Number(value)
const maxVal = parentLimit.position
if (inputVal > maxVal) {
callback(new Error(`头寸不能大于上级的 ${maxVal}`))
} else {
callback()
}
},
trigger: 'blur'
}
],
// 手续费:新增「不超过上级」校验
commissionRatio: [
{ required: true, message: '请输入手续费', trigger: 'blur' },
{ pattern: /^\d+(\.\d+)?$/, message: '手续费需为非负数字(支持整数/小数)', trigger: 'blur' },
{ min: 0, max: 100, message: '手续费范围需在0-100之间', trigger: 'blur' },
{
validator: (rule, value, callback) => {
if (!value) return callback()
const inputVal = Number(value)
const maxVal = parentLimit.commissionRatio
if (inputVal > maxVal) {
callback(new Error(`手续费不能大于上级的 ${maxVal}`))
} else {
callback()
}
},
trigger: 'blur'
}
],
// 新增:批量校验已分配点差
pointDiffList: [
{
validator: (rule, value, callback) => {
// value 是 marketPointTree 数组
if (!value || value.length === 0) {
return callback() // 没有点差数据时不校验
}
// 遍历所有点差行,校验必填和数值合法性
for (const row of value) {
// 校验必填
if (row.assignedPointDifference === '' || row.assignedPointDifference === undefined) {
return callback(new Error(`品种【${row.varietyName || row.name}】的已分配点差不能为空`))
}
// 校验数值格式(非负数字)
const numVal = Number(row.assignedPointDifference)
if (isNaN(numVal) || numVal < 0) {
return callback(new Error(`品种【${row.varietyName || row.name}】的已分配点差需为非负数字`))
}
// 可选:校验不超过上级点差
if (row.pointDifference && numVal > Number(row.pointDifference)) {
return callback(new Error(`品种【${row.varietyName || row.name}】的已分配点差不能超过可分配点差 ${row.pointDifference}`))
}
}
callback()
},
trigger: 'change' // 数据变化时触发
}
]
}
}

View File

@ -0,0 +1,523 @@
<template>
<div class="market">
<MarketSearch :search-form="marketSearchForm" :search-options="marketSearchOptions" @search="handleSearch"
@reset="handleReset">
<template #button="{ form }">
<el-button type="primary" @click="handleAddAgent()">
添加代理
</el-button>
<el-button type="primary" @click="handleEditAgent(tableRow)" :disabled="!tableRow">
编辑
</el-button>
</template>
</MarketSearch>
<MarketTable :table-data="marketTree" :columns="marketTableColumnsOptions" row-key="id"
@row-click="handleRowClick">
<template #pointSpread="{ row }">
<el-button type="primary" size="small" @click="handleViewPointDiff(row)">
查看
</el-button>
</template>
</MarketTable>
<MarketPagination v-model="marketSearchForm.page" v-model:page-size-value="marketSearchForm.pageSize"
:total="total" @pagination-change="handlePaginationChange" />
<MarketDialog :visible="dialogVisible" :title="dialogTitle" :type="dialogType"
:class="{ 'showForm-dialog': dialogType !== 'view' }" @confirm="handleSubmit" @cancel="handleCancel"
@close="handleClose" :fullscreen="dialogFullscreen">
<MarketForm :form-data="marketForm" :form-rules="marketFormRules" :form-items="marketFormItemOptions"
:options-map="marketFormOptionsMap" ref="marketFormRef" @form-item-change="handleFormItemChange"
v-if="dialogType !== 'view'">
</MarketForm>
<MarketTable :table-data="marketPointTree" :columns="marketPointTableColumnsOptions" row-key="id">
<template #assignedPointDiff="{ row }">
<el-form-item prop="assignedPointDifference">
<el-input v-if="dialogType !== 'view'" v-model.number="row.assignedPointDifference" size="small"
placeholder="请输入点差" />
</el-form-item>
</template>
</MarketTable>
</MarketDialog>
</div>
</template>
<script lang="ts" setup>
//
import MarketSearch from '@/components/common/Search.vue'
import MarketTable from '@/components/common/Table.vue'
import MarketPagination from '@/components/common/Pagination.vue'
import MarketDialog from '@/components/common/Dialog.vue'
import MarketForm from '@/components/common/Form.vue'
//
import { getMarketListApi, getPointDiffConfigApi, getParAgentListApi } from '@/api/modules/account/market'
//
import { marketSearch, marketTableColumns, marketFormItem, marketPointTableColumns, countryOptions } from './options'
import { rules } from './rules'
/**
* @description 搜索配置
*/
const marketSearchForm = ref<any>({
accountName: '',
page: 1,
pageSize: 10,
})
const marketSearchOptions = ref<any>(marketSearch)
/**
* @description 表格配置
*/
const marketTableColumnsOptions = ref<any>(marketTableColumns)
//
const tableRow = ref<any>(null)
const tableRowId = ref<number | null>(null)
const tableRowRoleId = ref<number | null>(null)
const marketTree = ref<any>([])
/**
* @description 分页配置
*/
const total = ref<number>(0)
/**
* @description dialog配置
*/
const dialogVisible = ref<boolean>(false)
const dialogTitle = ref<string>('')
const dialogType = ref<string>('add')
const dialogFullscreen = ref(false)
const activeTab = ref('email')
/**
* @description 点差表格配置
*/
const marketPointTree = ref<any>([])
const marketPointTableColumnsOptions = ref<any>(marketPointTableColumns)
/**
* @description 表单数据
*/
const marketForm = ref<any>({
accountName: '',
level: '',
parentAccountName: '',
position: '',
commissionRatio: '',
assignedPointDifference: '',
pointDiffList: [] //
})
//
const walletCapital = ref<any>({
position: 0,
commissionRatio: 0,
})
const marketFormOptionsMap = ref<any>({
level: [
{ label: '平台', value: '1' },
{ label: '承包商', value: '2' },
{ label: '特殊做市', value: '3' },
{ label: '普通做市', value: '4' },
{ label: '一级代理', value: '5' },
],
parentAccountName: [] //
})
const showForm = ref<boolean>(true)
const marketFormRef = ref<any>()
const marketFormItemOptions = ref<any>(marketFormItem)
const marketFormRules = ref<any>(rules(walletCapital.value))
const pointDiffData = ref<any>({})
/**
* 级别映射工具函数全局复用
* @param roleId 级别数字1/2/3/4/5
* @returns 对应的文字标签
*/
const getLevelLabel = (roleId: number | string): string => {
const levelMap: Record<string | number, string> = {
'1': '平台',
'2': '承包商',
'3': '特殊做市',
'4': '普通做市',
'5': '一级代理'
}
return levelMap[roleId] || '未知级别'
}
/**
* @description 点击表格行时存储选中行的ID和数据
*/
const handleRowClick = (row: any) => {
tableRow.value = row
tableRowId.value = row.id
tableRowRoleId.value = row.role_id
console.log('点击行数据', row)
}
/**
* @description 监听表单字段变化获取所属上级列表 / 点差数据
*/
const handleFormItemChange = (field: string, value: any) => {
// level
if (field === 'level') {
const levelRoleMap: Record<string, number> = {
'1': 1, //
'2': 2, //
'3': 3, //
'4': 4, //
'5': 5 //
}
const roleId = levelRoleMap[value]
if (roleId) {
fetchParAgentList(roleId)
} else {
marketFormOptionsMap.value.parentAccountName = []
//
marketForm.value.parentAccountName = ''
marketPointTree.value = []
}
}
// parentAccountName ID
if (field === 'parentAccountName' && value) {
// value id fetchParAgentList value: item.id
fetchPointDiffConfigByParentId(value)
//
const parentAgent = marketFormOptionsMap.value.parentAccountName.find(
(item: any) => item.value === value
)
walletCapital.value.position = parentAgent.position
walletCapital.value.commissionRatio = parentAgent.commissionRatio
} else if (field === 'parentAccountName' && !value) {
//
marketPointTree.value = []
}
}
/**
* @description 统一获取数据
*/
//
const fetchMarketList = async () => {
const params = {
page: marketSearchForm.value.page,
page_size: marketSearchForm.value.pageSize,
user_name: marketSearchForm.value.accountName
}
const data = await getMarketListApi(params)
//
marketTree.value = data.data.map((item: any) => ({
...item,
agentRelation: item.path_name || '--', //
accountName: item.username || '', //
level: getLevelLabel(item.role_id), // role_id 1-> 2->
basicAccount: item.wallet_capital?.amount || '0.00000', //
margin: item.wallet_capital?.bail || '0.00000', //
stopOrderMargin: item.wallet_capital?.bail_stop_order || '0.00000', //
positionTransferMargin: item.wallet_capital?.bail_change_order || '0.00000', //
pointSpreadCommission: item.wallet_capital?.commission_point_diff || '0.00000', //
commissionRatio: item.wallet_capital?.toucun_percent || '0.00000', //
commissionReturn: item.wallet_capital?.commission_fee_handling || '0.00000', //
closeProfitLoss: item.wallet_capital?.closing_profit || '0.00000', //
riskMargin: item.wallet_capital?.risk || '0.00000', //
serviceFee: item.wallet_capital?.service || '0.00000' //
}))
//
total.value = Number(data.total)
marketSearchForm.value.page = Number(data.current_page)
marketSearchForm.value.pageSize = Number(data.per_page)
}
//
const fetchPointDiffConfig = async () => {
const params = {
user_id: tableRowId.value
}
try {
const data = await getPointDiffConfigApi(params)
//
marketPointTree.value = data.map((item: any) => ({
...item,
varietyName: item.name,
varietyCode: item.code,
pointDifference: item.point_diff,
assignedPointDifference: item.target_point_diff
}))
} catch (err) {
console.error('获取代理点差配置失败', err)
}
}
//
const fetchParAgentList = async (roleId?: number) => {
const params = { role_id: roleId }
try {
const data = await getParAgentListApi(params)
marketFormOptionsMap.value.parentAccountName = data.map((item: any) => ({
label: item.accountName || item.username, //
value: item.id, // IDrow.parent_id
position: item.wallet_capital.toucun_percent,
commissionRatio: item.wallet_capital.toucun_percent
}))
} catch (err) {
console.error('获取所属上级列表失败', err)
marketFormOptionsMap.value.parentAccountName = []
}
}
// ID
const fetchPointDiffConfigByParentId = async (parentId: number) => {
if (!parentId) {
marketPointTree.value = []
return
}
const params = { user_id: parentId }
try {
const data = await getPointDiffConfigApi(params)
marketPointTree.value = data.map((item: any) => ({
...item,
varietyName: item.name,
varietyCode: item.code,
pointDifference: item.target_point_diff, //
assignedPointDifference: '' //
}))
} catch (err) {
console.error('获取上级点差配置失败', err)
marketPointTree.value = []
}
}
/**
* @description 组件挂载时获取数据
*/
onMounted(() => {
fetchMarketList()
})
/**
* @description 搜索
*/
const handleSearch = async () => {
await fetchMarketList()
}
const handleReset = () => {
marketSearchForm.value.accountName = ''
handleSearch()
}
/**
* @description 处理弹窗类型
*/
const handleDialogType = (type: string) => {
if (type === "view") {
dialogFullscreen.value = true
showForm.value = false
} else {
dialogFullscreen.value = false
showForm.value = true
}
}
/**
* @description 新增做市商
*/
const handleAddAgent = () => {
dialogVisible.value = true
dialogTitle.value = '新增做市商'
dialogType.value = 'add'
handleDialogType(dialogType.value)
//
marketForm.value = {
accountName: '',
level: '',
parentAccountName: '',
position: '',
commissionRatio: '',
}
//
marketFormOptionsMap.value.parentAccountName = []
marketPointTree.value = []
}
/**
* @description 编辑做市商
*/
const handleEditAgent = (row: any) => {
if (!row) return
dialogVisible.value = true
dialogTitle.value = '编辑做市商'
dialogType.value = 'edit'
handleDialogType(dialogType.value)
// 1. value
const levelValueMap: Record<string | number, string> = {
'1': '1', '2': '2', '3': '3', '4': '4', '5': '5'
}
const levelValue = levelValueMap[row.role_id] || ''
// 2. path IDpath : "/1/30/33" ID
const pathSegments = row.path.split('/').filter(Boolean) // ['1', '30', '33']
const parentId = pathSegments.length >= 2 ? Number(pathSegments[pathSegments.length - 2]) : null
// 3.
marketForm.value = {
...row,
level: levelValue,
parentAccountName: parentId // ID
}
// 4.
const levelRoleMap: Record<string, number> = {
'1': 1, '2': 2, '3': 3, '4': 4, '5': 5
}
const roleId = levelRoleMap[levelValue]
if (roleId) {
fetchParAgentList(roleId)
}
// 5.
if (parentId) {
fetchPointDiffConfigByParentId(parentId)
} else {
marketPointTree.value = []
}
}
/**
* @description 查看点差
*/
const handleViewPointDiff = (row: any) => {
tableRowId.value = row.id
dialogVisible.value = true
dialogTitle.value = '查看点差'
dialogType.value = 'view'
handleDialogType(dialogType.value)
fetchPointDiffConfig()
}
/**
* @description 分页变更
*/
const handlePaginationChange = (params: any) => {
marketSearchForm.value.page = params.currentPage
marketSearchForm.value.pageSize = params.pageSize
handleSearch()
}
/**
* @description 提交表单新增/编辑做市商
*/
const handleSubmit = async () => {
// idkeyconst pointDiffList = []
marketPointTree.value.forEach((row: any) => {
if (row.assignedPointDifference || row.assignedPointDifference === 0) {
pointDiffData.value[row.id] = row.assignedPointDifference
}
console.log('pointDiffData', pointDiffData.value)
})
await marketFormRef.value?.validate()
if (dialogType.value === 'add') {
//
const params = {
username: '',
}
} else if (dialogType.value === 'edit') {
//
} else {
//
}
}
/**
* @description 取消操作
*/
const handleCancel = () => {
dialogVisible.value = false
dialogType.value = 'add'
}
/**
* @description 关闭弹窗
*/
const handleClose = () => {
dialogVisible.value = false
dialogType.value = 'add'
}
</script>
<style scoped lang="scss">
.el-form {
.el-form-item {
flex: none !important;
}
}
.market {
.search-container {
:deep(.el-form) {
.el-form-item {
flex: none;
}
}
}
:deep(.el-dialog) {
.el-dialog__footer {
display: none;
}
}
:deep(.showForm-dialog) {
.el-dialog__footer {
display: block;
}
}
.phone-email {
display: flex;
:deep(.el-form-item__content) {
flex-wrap: nowrap;
}
.tab-btn {
display: flex;
margin-right: 10px;
.el-button {
margin-left: 0;
background-color: transparent;
border: 1px solid #DCDFE6;
color: #303133;
height: 32px;
}
.active {
background-color: #409EFF;
color: #fff;
}
}
.email-item {
.el-input {
width: 100%;
}
}
.phone-item {
.el-select {
width: 120px;
margin-right: 10px;
}
}
}
}
</style>