This commit is contained in:
parent
76ca0186dd
commit
27be2e59ca
|
|
@ -0,0 +1,23 @@
|
||||||
|
import { request } from '@/api';
|
||||||
|
import type { searchParams, pointDiffConfigParams } from '@/api/types/account/agent'
|
||||||
|
|
||||||
|
// 获取代理列表
|
||||||
|
export async function getAgentListApi(params: searchParams): Promise<any> {
|
||||||
|
return request.get<any>('/agent/getAgentList2', { ...params })
|
||||||
|
}
|
||||||
|
//获取代理点差配置
|
||||||
|
export async function getPointDiffConfigApi(params: pointDiffConfigParams): Promise<any> {
|
||||||
|
return request.get<any>('/agent/getSelfVarietyPointDiffConfig',{...params})
|
||||||
|
}
|
||||||
|
//获取风控模板选项
|
||||||
|
export async function getRiskTemplateOptionsApi(): Promise<any> {
|
||||||
|
return request.get<any>('/agent/getRiskControlOptions')
|
||||||
|
}
|
||||||
|
//获取手续费模板选项
|
||||||
|
export async function getFeeTemplateOptionsApi(): Promise<any> {
|
||||||
|
return request.get<any>('user/getFeeSettingOptions')
|
||||||
|
}
|
||||||
|
//编辑代理点差
|
||||||
|
export async function editPointDiffConfigApi(params: pointDiffConfigParams): Promise<any> {
|
||||||
|
return request.post<any>('/agent/editAgent',{...params})
|
||||||
|
}
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
import { request } from '@/api';
|
import { request } from '@/api';
|
||||||
import type { accountSearchParams, accountListResponse, accountCreateParams } from '@/api/types/account'
|
import type { searchParams, accountListResponse, accountCreateParams } from '@/api/types/account/client'
|
||||||
|
|
||||||
// 获取客户列表
|
// 获取客户列表
|
||||||
export async function getClientListApi(params: accountSearchParams): Promise<accountListResponse> {
|
export async function getClientListApi(params: searchParams): Promise<accountListResponse> {
|
||||||
return request.get<accountListResponse>('/user/getUserList', { ...params })
|
return request.get<accountListResponse>('/user/getUserList', { ...params })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,12 @@
|
||||||
|
import { request } from '@/api';
|
||||||
|
import type{ searchParams,pointDiffConfigParams } from '@/api/types/account/market'
|
||||||
|
|
||||||
|
// 查询做市商列表
|
||||||
|
export async function getMarketListApi(params: searchParams): Promise<any> {
|
||||||
|
return request.get<any>('agent/getAgentList', { ...params })
|
||||||
|
}
|
||||||
|
|
||||||
|
//获取代理点差配置
|
||||||
|
export async function getPointDiffConfigApi(params: pointDiffConfigParams): Promise<any> {
|
||||||
|
return request.get<any>('/agent/getSelfVarietyPointDiffConfig',{...params})
|
||||||
|
}
|
||||||
|
|
@ -3,7 +3,7 @@ import type {
|
||||||
MenuFormParams,
|
MenuFormParams,
|
||||||
DeleteMenuParams,
|
DeleteMenuParams,
|
||||||
MenuListResponse
|
MenuListResponse
|
||||||
} from '@/api/types/menu';
|
} from '@/api/types/system/menu';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取菜单列表
|
* 获取菜单列表
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@ import type {
|
||||||
GetRolePermissionParams,
|
GetRolePermissionParams,
|
||||||
RoleListResponse,
|
RoleListResponse,
|
||||||
PermissionIdsResponse
|
PermissionIdsResponse
|
||||||
} from '@/api/types/role';
|
} from '@/api/types/system/role';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取角色列表
|
* 获取角色列表
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,5 @@
|
||||||
/**
|
// 通用查询参数
|
||||||
* @description 客户列表查询参数
|
export interface searchParams {
|
||||||
* @param {accountSearchParams} params - 查询参数类型
|
|
||||||
* @response {accountListResponse} 客户列表响应类型
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
// 客户列表查询参数
|
|
||||||
export interface accountSearchParams {
|
|
||||||
page?: number
|
page?: number
|
||||||
page_size?: number
|
page_size?: number
|
||||||
username?: string
|
username?: string
|
||||||
|
|
@ -14,6 +8,14 @@ export interface accountSearchParams {
|
||||||
reg_end_time?: string
|
reg_end_time?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 客户列表查询参数
|
||||||
|
* @param {accountSearchParams} params - 查询参数类型
|
||||||
|
* @response {accountListResponse} 客户列表响应类型
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
// 定义列表项的类型
|
// 定义列表项的类型
|
||||||
interface UserItem {
|
interface UserItem {
|
||||||
id: number;
|
id: number;
|
||||||
|
|
@ -33,6 +35,7 @@ export interface accountListResponse {
|
||||||
data: UserItem[];
|
data: UserItem[];
|
||||||
total: number;
|
total: number;
|
||||||
per_page: number;
|
per_page: number;
|
||||||
|
current_page: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -53,3 +56,8 @@ export interface accountCreateParams {
|
||||||
is_levelup?: number;
|
is_levelup?: number;
|
||||||
status?: number;
|
status?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//获取代理点差配置
|
||||||
|
export interface pointDiffConfigParams {
|
||||||
|
user_id: number | string
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,16 @@
|
||||||
|
// 通用查询参数
|
||||||
|
export interface searchParams {
|
||||||
|
page?: number
|
||||||
|
page_size?: number
|
||||||
|
username?: string
|
||||||
|
status?: string | number
|
||||||
|
reg_start_time?: string
|
||||||
|
reg_end_time?: string
|
||||||
|
user_name?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//获取代理点差配置
|
||||||
|
export interface pointDiffConfigParams {
|
||||||
|
user_id: number | string
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,58 @@
|
||||||
|
// 通用查询参数
|
||||||
|
export interface searchParams {
|
||||||
|
page?: number
|
||||||
|
page_size?: number
|
||||||
|
username?: string
|
||||||
|
status?: string | number
|
||||||
|
reg_start_time?: string
|
||||||
|
reg_end_time?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 客户列表查询参数
|
||||||
|
* @param {accountSearchParams} params - 查询参数类型
|
||||||
|
* @response {accountListResponse} 客户列表响应类型
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
// 定义列表项的类型
|
||||||
|
interface UserItem {
|
||||||
|
id: number;
|
||||||
|
username: string;
|
||||||
|
par_uid: number;
|
||||||
|
created_at: string; // 时间字符串类型
|
||||||
|
status: number;
|
||||||
|
parent: ParentUser; // 嵌套的父级用户对象
|
||||||
|
}
|
||||||
|
|
||||||
|
// 定义完整响应数据的类型
|
||||||
|
interface UserResponse {
|
||||||
|
data: UserItem[]; // 数据是 UserItem 类型的数组
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface accountListResponse {
|
||||||
|
data: UserItem[];
|
||||||
|
total: number;
|
||||||
|
per_page: number;
|
||||||
|
current_page: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 客户创建类型
|
||||||
|
* @param {accountCreateParams} params - 创建参数类型
|
||||||
|
* @response {void} 无响应体
|
||||||
|
*/
|
||||||
|
// 客户创建类型
|
||||||
|
export interface accountCreateParams {
|
||||||
|
reg_type?: number
|
||||||
|
email?: string
|
||||||
|
mobile?: string
|
||||||
|
parent_id?: number | string
|
||||||
|
fee_setting_id?: number | string
|
||||||
|
risk_control_id?: number | string
|
||||||
|
user_id?: string;
|
||||||
|
username?: string;
|
||||||
|
is_levelup?: number;
|
||||||
|
status?: number;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
// 查询参数
|
||||||
|
export interface searchParams {
|
||||||
|
user_name?: string
|
||||||
|
}
|
||||||
|
//获取代理点差配置
|
||||||
|
export interface pointDiffConfigParams {
|
||||||
|
user_id: number | string
|
||||||
|
}
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import type { ApiResponse } from './index';
|
import type { ApiResponse } from '../index';
|
||||||
|
|
||||||
/** 菜单基础参数类型(新增/编辑通用) */
|
/** 菜单基础参数类型(新增/编辑通用) */
|
||||||
export interface MenuFormParams {
|
export interface MenuFormParams {
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import type { ApiResponse } from './index';
|
import type { ApiResponse } from '../index';
|
||||||
|
|
||||||
// 角色基础参数(创建/编辑通用)
|
// 角色基础参数(创建/编辑通用)
|
||||||
export interface RoleFormParams {
|
export interface RoleFormParams {
|
||||||
|
|
@ -1,9 +1,8 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="pagination-container">
|
<div class="pagination-container">
|
||||||
<el-pagination v-model:current-page="currentPage" v-model:page-size="pageSize" :page-sizes="pageSizes"
|
<el-pagination v-model:current-page="currentPage" v-model:page-size="pageSize" :page-sizes="pageSizes"
|
||||||
:total="total" :disabled="disabled" :background="background" :small="small"
|
:total="total" :disabled="disabled" :background="background" size="small" :layout="layout"
|
||||||
:hide-on-single-page="hideOnSinglePage" :layout="layout" @size-change="handleSizeChange"
|
@size-change="handleSizeChange" @current-change="handleCurrentChange" />
|
||||||
@current-change="handleCurrentChange" />
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|
@ -32,7 +31,7 @@ const props = defineProps({
|
||||||
// 可选的每页条数
|
// 可选的每页条数
|
||||||
pageSizes: {
|
pageSizes: {
|
||||||
type: Array,
|
type: Array,
|
||||||
default: () => [10, 20, 50, 100]
|
default: () => [1, 10, 20, 50, 100] as unknown[]
|
||||||
},
|
},
|
||||||
// 是否禁用分页
|
// 是否禁用分页
|
||||||
disabled: {
|
disabled: {
|
||||||
|
|
@ -44,16 +43,6 @@ const props = defineProps({
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: true
|
default: true
|
||||||
},
|
},
|
||||||
// 是否为小型分页
|
|
||||||
small: {
|
|
||||||
type: Boolean,
|
|
||||||
default: false
|
|
||||||
},
|
|
||||||
// 只有一页时是否隐藏
|
|
||||||
hideOnSinglePage: {
|
|
||||||
type: Boolean,
|
|
||||||
default: true
|
|
||||||
},
|
|
||||||
// 分页布局(Element Plus 原生配置)
|
// 分页布局(Element Plus 原生配置)
|
||||||
layout: {
|
layout: {
|
||||||
type: String,
|
type: String,
|
||||||
|
|
@ -112,5 +101,6 @@ const handleCurrentChange = (val: number) => {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
bottom: 20px;
|
bottom: 20px;
|
||||||
right: 20px;
|
right: 20px;
|
||||||
|
z-index: 1000;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
||||||
|
|
@ -45,3 +45,10 @@ const props = withDefaults(defineProps<Props>(), {
|
||||||
highlightCurrentRow: true,
|
highlightCurrentRow: true,
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.table-container {
|
||||||
|
max-height: calc(100vh - 180px);
|
||||||
|
overflow: auto;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
|
||||||
|
|
@ -115,7 +115,7 @@ const staticMenuList = ref<ElMenuItem[]>(
|
||||||
{
|
{
|
||||||
id: 33,
|
id: 33,
|
||||||
label: '做市商管理',
|
label: '做市商管理',
|
||||||
path: '3-3', // index="3-3"
|
path: '/account/market-maker', // index="3-3"
|
||||||
icon: ''
|
icon: ''
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
|
||||||
|
|
@ -110,6 +110,14 @@ const routes = [
|
||||||
meta: {
|
meta: {
|
||||||
title: '代理管理', // 左侧菜单显示的标题
|
title: '代理管理', // 左侧菜单显示的标题
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'market-maker',
|
||||||
|
name: 'MarketMaker',
|
||||||
|
component: () => import('@/views/account/market-maker/index.vue'),
|
||||||
|
meta: {
|
||||||
|
title: '做市商管理', // 左侧菜单显示的标题
|
||||||
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -4,19 +4,29 @@
|
||||||
@reset="handleReset">
|
@reset="handleReset">
|
||||||
</AgentSearch>
|
</AgentSearch>
|
||||||
|
|
||||||
<AgentTable :table-data="agentTree" :columns="agentTableColumnsOptions" row-key="id" />
|
<AgentTable :table-data="agentTree" :columns="agentTableColumnsOptions" row-key="id">
|
||||||
|
<template #status="{ row }">
|
||||||
|
<el-switch :model-value="row.status === 1" :active-value="true" :inactive-value="false" active-text="启用"
|
||||||
|
inactive-text="禁用" />
|
||||||
|
</template>
|
||||||
|
<template #pointDifference="{ row }">
|
||||||
|
<el-button type="primary" size="small" @click="handlePointDifference(row)">
|
||||||
|
查看
|
||||||
|
</el-button>
|
||||||
|
</template>
|
||||||
|
<template #edit="{ row }">
|
||||||
|
<el-button type="primary" size="small" @click="handleEdit(row)">
|
||||||
|
编辑
|
||||||
|
</el-button>
|
||||||
|
</template>
|
||||||
|
</AgentTable>
|
||||||
|
|
||||||
<AgentPagination v-model="agentSearchForm.page" v-model:page-size-value="agentSearchForm.pageSize"
|
<AgentPagination v-model="agentSearchForm.page" v-model:page-size-value="agentSearchForm.pageSize"
|
||||||
:total="agentSearchForm.total" @pagination-change="handlePaginationChange" />
|
:total="agentSearchForm.total" @pagination-change="handlePaginationChange" />
|
||||||
|
<AgentDialog :visible="dialogVisible" :title="dialogTitle" :type="dialogType" :fullscreen="dialogFullscreen" @submit="handleSubmit"
|
||||||
<AgentDialog :visible="dialogVisible" :title="dialogTitle" :type="dialogType" :fullscreen="true"
|
@cancel="handleCancel" @close="handleClose" :class="{ 'edit-dialog': isEdit }">
|
||||||
@cancel="handleCancel" @close="handleClose">
|
<AgentForm :form-data="agentForm" :form-rules="agentFormRules" :form-items="agentFormItems"
|
||||||
<template #header>
|
:options-map="agentFormOptionsMap" v-if="isEdit" />
|
||||||
<div class="dialog-header">
|
|
||||||
<span class="dialog-title">查看点差</span>
|
|
||||||
<span class="dialog-close-text" @click="dialogVisible = false">关闭</span>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
<AgentTable :table-data="agentPointTree" :columns="agentPointTableColumnsOptions" row-key="id" />
|
<AgentTable :table-data="agentPointTree" :columns="agentPointTableColumnsOptions" row-key="id" />
|
||||||
</AgentDialog>
|
</AgentDialog>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -27,9 +37,13 @@ import AgentSearch from '@/components/common/Search.vue'
|
||||||
import AgentTable from '@/components/common/Table.vue'
|
import AgentTable from '@/components/common/Table.vue'
|
||||||
import AgentPagination from '@/components/common/Pagination.vue'
|
import AgentPagination from '@/components/common/Pagination.vue'
|
||||||
import AgentDialog from '@/components/common/Dialog.vue'
|
import AgentDialog from '@/components/common/Dialog.vue'
|
||||||
|
import AgentForm from '@/components/common/Form.vue'
|
||||||
|
|
||||||
|
//接口
|
||||||
|
import { getAgentListApi, getPointDiffConfigApi, getRiskTemplateOptionsApi, getFeeTemplateOptionsApi,editPointDiffConfigApi } from '@/api/modules/account/agent'
|
||||||
|
|
||||||
// 引入配置
|
// 引入配置
|
||||||
import { agentSearch, agentTableColumns, agentPointTableColumns } from './options'
|
import { agentSearch, agentTableColumns, agentPointTableColumns, PointDiffFormItem } from './options'
|
||||||
|
|
||||||
//定义客户搜索表单配置
|
//定义客户搜索表单配置
|
||||||
const agentSearchOptions = ref(agentSearch)
|
const agentSearchOptions = ref(agentSearch)
|
||||||
|
|
@ -39,7 +53,7 @@ const agentSearchForm = ref({
|
||||||
startDateTime: '',
|
startDateTime: '',
|
||||||
endDateTime: '',
|
endDateTime: '',
|
||||||
page: 1,
|
page: 1,
|
||||||
pageSize: 10,
|
pageSize: 100,
|
||||||
total: 100,
|
total: 100,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
@ -48,12 +62,266 @@ const agentTree = ref<any[]>([])
|
||||||
const agentTableColumnsOptions = ref(agentTableColumns)
|
const agentTableColumnsOptions = ref(agentTableColumns)
|
||||||
|
|
||||||
// 定义弹窗配置
|
// 定义弹窗配置
|
||||||
const dialogVisible = ref(true)
|
const dialogVisible = ref(false)
|
||||||
const dialogTitle = ref('查看点差')
|
const dialogTitle = ref('查看点差')
|
||||||
|
const dialogFullscreen = ref(false)
|
||||||
const dialogType = ref('add')
|
const dialogType = ref('add')
|
||||||
const dialogWidth = ref('100%')
|
|
||||||
const agentPointTree = ref<any[]>([])
|
const agentPointTree = ref<any[]>([])
|
||||||
const agentPointTableColumnsOptions = ref(agentPointTableColumns)
|
const agentPointTableColumnsOptions = ref(agentPointTableColumns)
|
||||||
|
|
||||||
|
// 定义弹窗表单配置
|
||||||
|
const isEdit = ref(false)
|
||||||
|
const agentFormItems = ref(PointDiffFormItem)
|
||||||
|
const agentFormRules = ref({
|
||||||
|
username: [{ required: true, message: '请输入代理名称', trigger: ['blur'] }],
|
||||||
|
parentUsername: [{ required: true, message: '请输入所属上级', trigger: ['blur'] }],
|
||||||
|
feeRate: [{ required: true, message: '请输入手续费', trigger: ['blur'] }],
|
||||||
|
riskTemplate: [{ required: true, message: '请选择风控模板', trigger: ['change'] }],
|
||||||
|
feeTemplate: [{ required: true, message: '请选择手续费模板', trigger: ['change'] }],
|
||||||
|
})
|
||||||
|
const agentForm = ref({
|
||||||
|
username: '',
|
||||||
|
parentUsername: '',
|
||||||
|
feeRate: '',
|
||||||
|
riskTemplate: '',
|
||||||
|
feeTemplate: '',
|
||||||
|
})
|
||||||
|
const agentFormOptionsMap = ref<any>({
|
||||||
|
riskTemplate: [],
|
||||||
|
feeTemplate: [],
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 统一获取数据
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* 处理字符串数值:转数字 + 相加 + 保留五位小数
|
||||||
|
* @param {Array<string>} strNums - 待处理的字符串数值数组(如 ["0.00000", "0.00000"])
|
||||||
|
* @returns {number} 相加后保留五位小数的数字(最终结果)
|
||||||
|
*/
|
||||||
|
function sumStrNumsWith5Decimals(strNums: string[]) {
|
||||||
|
// 1. 初始化总和
|
||||||
|
let total = 0;
|
||||||
|
|
||||||
|
// 2. 遍历数组,逐个转换并累加
|
||||||
|
strNums.forEach(strNum => {
|
||||||
|
// 转数字(处理空值/非数字,兜底为0)
|
||||||
|
const num = parseFloat(strNum) || 0;
|
||||||
|
total += num;
|
||||||
|
});
|
||||||
|
|
||||||
|
// 3. 保留五位小数(四舍五入),转回数字类型
|
||||||
|
const result = parseFloat(total.toFixed(5));
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 映射对象为数组通用方法
|
||||||
|
const mapObjectToOptions = (obj: Record<string, string>) => {
|
||||||
|
console.log('obj', obj)
|
||||||
|
return Object.entries(obj).map(([label, value]) => ({
|
||||||
|
label, // 模板/代理名称
|
||||||
|
value // 模板/代理ID
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
|
//获取代理列表
|
||||||
|
const fetchAgentList = async () => {
|
||||||
|
const params = {
|
||||||
|
page: agentSearchForm.value.page,
|
||||||
|
page_size: agentSearchForm.value.pageSize,
|
||||||
|
user_name: agentSearchForm.value.username,
|
||||||
|
reg_start_time: agentSearchForm.value.startDateTime.length > 0 ? `${agentSearchForm.value.startDateTime} 0:00:00` : '',
|
||||||
|
reg_end_time: agentSearchForm.value.endDateTime.length > 0 ? `${agentSearchForm.value.endDateTime} 23:59:59` : '',
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
const data = await getAgentListApi(params)
|
||||||
|
//分页数据
|
||||||
|
agentSearchForm.value.total = data.total || 0
|
||||||
|
agentSearchForm.value.pageSize = Number(data.per_page) || 0
|
||||||
|
|
||||||
|
// 表格数据
|
||||||
|
agentTree.value = data.data.map((item: any) => {
|
||||||
|
|
||||||
|
//针对当前item提取需要相加的字段(每次循环都重新取当前行数据)
|
||||||
|
const walletNums = [
|
||||||
|
// 兜底空值,避免undefined导致计算错误
|
||||||
|
item.wallet_capital?.commission_fee_handling || '0.00000',
|
||||||
|
item.wallet_capital?.commission_point_diff || '0.00000'
|
||||||
|
];
|
||||||
|
// 计算当前行的累加值
|
||||||
|
const rebateTotalAmount = sumStrNumsWith5Decimals(walletNums);
|
||||||
|
|
||||||
|
return {
|
||||||
|
...item,
|
||||||
|
createTime: item.created_at || '',
|
||||||
|
feeRate: item.wallet_capital.fee_handling_percent,
|
||||||
|
rebateRate: item.wallet_capital.commission_fee_handling,
|
||||||
|
pointDifference: item.wallet_capital.commission_point_diff,
|
||||||
|
rebateTotalAmount: rebateTotalAmount,
|
||||||
|
clientCount: item.son_user.length,
|
||||||
|
level: item.role.title,
|
||||||
|
parentUsername: item.par_uid === item.parent.id ? item.parent.username : '',
|
||||||
|
}
|
||||||
|
})
|
||||||
|
} catch (err) {
|
||||||
|
console.error('获取代理列表失败', err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//获取代理点差配置
|
||||||
|
const fetchAgentPointDiffConfig = async (id: number | string) => {
|
||||||
|
console.log(id)
|
||||||
|
const params = {
|
||||||
|
user_id: id
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
const data = await getPointDiffConfigApi(params)
|
||||||
|
// 表格数据
|
||||||
|
agentPointTree.value = data.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 optionsFetched = ref(false)
|
||||||
|
const getOptions = async () => {
|
||||||
|
// 已获取过选项则直接返回,避免重复请求
|
||||||
|
if (optionsFetched.value) return
|
||||||
|
|
||||||
|
try {
|
||||||
|
const [riskTemplateRes, feeTemplateRes] = await Promise.all([
|
||||||
|
getRiskTemplateOptionsApi(), // 风控模板请求 → 对应 riskTemplateRes
|
||||||
|
getFeeTemplateOptionsApi(), // 手续费模板请求 → 对应 feeTemplateRes
|
||||||
|
])
|
||||||
|
console.log('获取表单选项:', riskTemplateRes, feeTemplateRes)
|
||||||
|
// 修正映射:label=名称,value=ID
|
||||||
|
|
||||||
|
agentFormOptionsMap.value.riskTemplate = mapObjectToOptions(feeTemplateRes as Record<string, string>)
|
||||||
|
agentFormOptionsMap.value.feeTemplate = riskTemplateRes.map((item: any) => ({
|
||||||
|
label: item.name,
|
||||||
|
value: item.id
|
||||||
|
}))
|
||||||
|
|
||||||
|
optionsFetched.value = true // 标记已获取
|
||||||
|
} catch (error) {
|
||||||
|
console.error('获取表单选项失败:', error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 页面加载完成后获取数据
|
||||||
|
*/
|
||||||
|
onMounted(() => {
|
||||||
|
fetchAgentList()
|
||||||
|
})
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 搜索方法
|
||||||
|
*/
|
||||||
|
const handleSearch = () => {
|
||||||
|
fetchAgentList()
|
||||||
|
}
|
||||||
|
const handleReset = () => {
|
||||||
|
// 处理重置逻辑
|
||||||
|
agentSearchForm.value = {
|
||||||
|
username: '',
|
||||||
|
status: '正常',
|
||||||
|
startDateTime: '',
|
||||||
|
endDateTime: '',
|
||||||
|
page: 1,
|
||||||
|
pageSize: 10,
|
||||||
|
total: 100,
|
||||||
|
}
|
||||||
|
fetchAgentList()
|
||||||
|
}
|
||||||
|
const handleDialogType = (type: string) => {
|
||||||
|
console.log('handleDialogType', type)
|
||||||
|
if (type === 'edit') {
|
||||||
|
isEdit.value = true
|
||||||
|
dialogFullscreen.value = false
|
||||||
|
} else {
|
||||||
|
isEdit.value = false
|
||||||
|
dialogFullscreen.value = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 查看点差方法
|
||||||
|
*/
|
||||||
|
const handlePointDifference = (row: any) => {
|
||||||
|
dialogVisible.value = true
|
||||||
|
dialogTitle.value = '查看点差'
|
||||||
|
dialogType.value = 'view'
|
||||||
|
handleDialogType(dialogType.value)
|
||||||
|
console.log(dialogType.value)
|
||||||
|
fetchAgentPointDiffConfig(row.id)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 编辑方法
|
||||||
|
*/
|
||||||
|
const handleEdit = (row: any) => {
|
||||||
|
dialogVisible.value = true
|
||||||
|
dialogTitle.value = '编辑点差'
|
||||||
|
dialogType.value = 'edit'
|
||||||
|
dialogFullscreen.value = false
|
||||||
|
handleDialogType(dialogType.value)
|
||||||
|
console.log(dialogType.value)
|
||||||
|
getOptions()
|
||||||
|
// fetchAgentPointDiffConfig(row.id)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 分页方法
|
||||||
|
*/
|
||||||
|
const handlePaginationChange = (page: { currentPage: number, pageSize: number }) => {
|
||||||
|
agentSearchForm.value.page = page.currentPage
|
||||||
|
agentSearchForm.value.pageSize = page.pageSize
|
||||||
|
handleSearch()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description dialog方法
|
||||||
|
*/
|
||||||
|
|
||||||
|
const handleSubmit = async () => {
|
||||||
|
if (dialogType.value === 'edit') {
|
||||||
|
const params = {
|
||||||
|
user_id: "",
|
||||||
|
toucun_percent: "",
|
||||||
|
point_diffs_json: "",
|
||||||
|
fee_handling_percent: "",
|
||||||
|
}
|
||||||
|
await editPointDiffConfigApi(params)
|
||||||
|
await fetchAgentList()
|
||||||
|
dialogVisible.value = false
|
||||||
|
} else {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 弹窗取消
|
||||||
|
const handleCancel = () => {
|
||||||
|
dialogVisible.value = false
|
||||||
|
dialogType.value = 'view'
|
||||||
|
}
|
||||||
|
|
||||||
|
// 弹窗关闭
|
||||||
|
const handleClose = () => {
|
||||||
|
dialogVisible.value = false
|
||||||
|
dialogType.value = 'view'
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
|
|
@ -63,5 +331,11 @@ const agentPointTableColumnsOptions = ref(agentPointTableColumns)
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
:deep(.edit-dialog) {
|
||||||
|
.el-dialog__footer {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
||||||
|
|
@ -25,17 +25,19 @@ export const agentSearch = [
|
||||||
|
|
||||||
// 定义表格列配置
|
// 定义表格列配置
|
||||||
export const agentTableColumns = [
|
export const agentTableColumns = [
|
||||||
{ prop: 'id', label: 'ID', align: 'center' as const },
|
{ prop: 'id', label: 'ID', align: 'center' as const, width: '80px' },
|
||||||
{ prop: 'username', label: '代理名称', align: 'center' as const },
|
{ prop: 'username', label: '代理名称', align: 'center' as const },
|
||||||
{ prop: 'registerTime', label: '注册时间', align: 'center' as const },
|
{ prop: 'createTime', label: '注册时间', align: 'center' as const },
|
||||||
{ prop: 'status', label: '状态', align: 'center' as const },
|
{ slotName: 'status', label: '状态', align: 'center' as const },
|
||||||
{ prop: 'pointDifference', label: '点差', align: 'center' as const },
|
|
||||||
{ prop: 'feeRate', label: '手续费', align: 'center' as const },
|
{ prop: 'feeRate', label: '手续费', align: 'center' as const },
|
||||||
{ prop: 'rebateRate', label: '手续费返佣', align: 'center' as const },
|
{ prop: 'rebateRate', label: '手续费返佣', align: 'center' as const },
|
||||||
{ prop: 'pointDifference2', label: '点差', align: 'center' as const },
|
{ prop: 'pointDifference', label: '点差返佣', align: 'center' as const },
|
||||||
|
{ slotName: 'pointDifference', label: '点差', align: 'center' as const },
|
||||||
{ prop: 'rebateTotalAmount', label: '返佣总金额', align: 'center' as const },
|
{ prop: 'rebateTotalAmount', label: '返佣总金额', align: 'center' as const },
|
||||||
{ prop: 'clientCount', label: '客户数量', align: 'center' as const },
|
{ prop: 'clientCount', label: '客户数量', align: 'center' as const },
|
||||||
{ prop: 'level', label: '级别', align: 'center' as const },
|
{ prop: 'level', label: '级别', align: 'center' as const },
|
||||||
|
{ prop: 'parentUsername', label: '所属上级', align: 'center' as const },
|
||||||
|
{ slotName: 'edit', label: '编辑', align: 'center' as const },
|
||||||
|
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
@ -46,3 +48,17 @@ export const agentPointTableColumns = [
|
||||||
{ prop: 'pointDifference', 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 },
|
||||||
]
|
]
|
||||||
|
|
||||||
|
//编辑点差form配置
|
||||||
|
export const PointDiffFormItem = [
|
||||||
|
//代理名称
|
||||||
|
{ prop: 'username', label: '代理名称', type: 'input' as const, placeholder: '代理名称', width: '120px' },
|
||||||
|
//所属上级
|
||||||
|
{ prop: 'parentUsername', label: '所属上级', type: 'input' as const, placeholder: '所属上级', width: '120px' },
|
||||||
|
//手续费
|
||||||
|
{ prop: 'feeRate', label: '手续费', type: 'input' as const, placeholder: '手续费', width: '120px' },
|
||||||
|
//风控模板
|
||||||
|
{ prop: 'riskTemplate', label: '风控模板', type: 'select' as const, placeholder: '风控模板', width: '120px' },
|
||||||
|
//手续费模板
|
||||||
|
{ prop: 'feeTemplate', label: '手续费模板', type: 'select' as const, placeholder: '手续费模板', width: '120px' },
|
||||||
|
]
|
||||||
|
|
|
||||||
|
|
@ -20,8 +20,8 @@
|
||||||
</el-button>
|
</el-button>
|
||||||
</template>
|
</template>
|
||||||
</ClientTable>
|
</ClientTable>
|
||||||
<ClientPagination v-model="currentPage" v-model:page-size-value="pageSize" :total="total"
|
<ClientPagination :modelValue="clientSearchForm.currentPage" :pageSizeValue="clientSearchForm.pageSize"
|
||||||
@pagination-change="handlePaginationChange" />
|
:total="total" @pagination-change="handlePaginationChange" />
|
||||||
</div>
|
</div>
|
||||||
<!-- 客户弹窗 -->
|
<!-- 客户弹窗 -->
|
||||||
<ClientDialog :visible="dialogVisible" :title="dialogTitle" :type="dialogType" @confirm="handleSubmit"
|
<ClientDialog :visible="dialogVisible" :title="dialogTitle" :type="dialogType" @confirm="handleSubmit"
|
||||||
|
|
@ -79,8 +79,8 @@ import { rules } from './rules'
|
||||||
//定义客户搜索表单配置
|
//定义客户搜索表单配置
|
||||||
const clientSearchOptions = ref(clientSearch)
|
const clientSearchOptions = ref(clientSearch)
|
||||||
const clientSearchForm = ref({
|
const clientSearchForm = ref({
|
||||||
page: 1,
|
currentPage: 1,
|
||||||
pageSize: 10,
|
pageSize: 1,
|
||||||
username: '',
|
username: '',
|
||||||
status: '正常',
|
status: '正常',
|
||||||
startDateTime: '',
|
startDateTime: '',
|
||||||
|
|
@ -91,12 +91,11 @@ const clientSearchForm = ref({
|
||||||
const clientTree = ref<any[]>([])
|
const clientTree = ref<any[]>([])
|
||||||
const treeProps = ref({
|
const treeProps = ref({
|
||||||
children: 'parent',
|
children: 'parent',
|
||||||
|
label: 'username'
|
||||||
})
|
})
|
||||||
|
|
||||||
// 定义分页配置
|
// 定义分页配置
|
||||||
const total = ref(0)
|
const total = ref(0)
|
||||||
const pageSize = ref(1)
|
|
||||||
const currentPage = ref(1)
|
|
||||||
|
|
||||||
// 定义dialog配置
|
// 定义dialog配置
|
||||||
const dialogTitle = ref('')
|
const dialogTitle = ref('')
|
||||||
|
|
@ -136,6 +135,7 @@ interface ClientFormOptionsMap {
|
||||||
riskTemplate: FormOption[];
|
riskTemplate: FormOption[];
|
||||||
agentUsername: FormOption[];
|
agentUsername: FormOption[];
|
||||||
isUpgrade: FormOption[];
|
isUpgrade: FormOption[];
|
||||||
|
status: FormOption[];
|
||||||
}
|
}
|
||||||
const clientFormOptionsMap = ref<ClientFormOptionsMap>({
|
const clientFormOptionsMap = ref<ClientFormOptionsMap>({
|
||||||
feeTemplate: [],
|
feeTemplate: [],
|
||||||
|
|
@ -145,12 +145,16 @@ const clientFormOptionsMap = ref<ClientFormOptionsMap>({
|
||||||
{ label: '是', value: 1 },
|
{ label: '是', value: 1 },
|
||||||
{ label: '否', value: 2 }
|
{ label: '否', value: 2 }
|
||||||
],
|
],
|
||||||
|
status: [
|
||||||
|
{ label: '正常', value: 1 },
|
||||||
|
{ label: '禁用', value: 2 }
|
||||||
|
],
|
||||||
})
|
})
|
||||||
|
|
||||||
// 获取账户列表
|
// 获取账户列表
|
||||||
const fetchClientList = async () => {
|
const fetchClientList = async () => {
|
||||||
const params = {
|
const params = {
|
||||||
page: clientSearchForm.value.page,
|
page: clientSearchForm.value.currentPage,
|
||||||
page_size: clientSearchForm.value.pageSize,
|
page_size: clientSearchForm.value.pageSize,
|
||||||
username: clientSearchForm.value.username,
|
username: clientSearchForm.value.username,
|
||||||
status: clientSearchForm.value.status === '正常' ? 1 : 2,
|
status: clientSearchForm.value.status === '正常' ? 1 : 2,
|
||||||
|
|
@ -163,12 +167,12 @@ const fetchClientList = async () => {
|
||||||
// 映射所属代理用户名
|
// 映射所属代理用户名
|
||||||
agentUsername: item.par_uid === item.parent?.id ? item.parent?.username : '',
|
agentUsername: item.par_uid === item.parent?.id ? item.parent?.username : '',
|
||||||
}));
|
}));
|
||||||
//把接口返回的分页字段赋值
|
//把接口返回的分页字段赋值给分页组件
|
||||||
total.value = data.total; // 总条数
|
total.value = Number(data.total)
|
||||||
pageSize.value = Number(data.per_page); // 转成数字,和组件保持一致
|
clientSearchForm.value.currentPage = Number(data.current_page)
|
||||||
|
clientSearchForm.value.pageSize = Number(data.per_page)
|
||||||
}
|
}
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
console.log('客户列表', clientTree.value)
|
|
||||||
await fetchClientList()
|
await fetchClientList()
|
||||||
})
|
})
|
||||||
/**
|
/**
|
||||||
|
|
@ -179,7 +183,6 @@ onMounted(async () => {
|
||||||
const handleSearch = async () => {
|
const handleSearch = async () => {
|
||||||
try {
|
try {
|
||||||
await fetchClientList()
|
await fetchClientList()
|
||||||
console.log('客户列表', clientSearchForm.value)
|
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error('获取客户列表失败', err)
|
console.error('获取客户列表失败', err)
|
||||||
}
|
}
|
||||||
|
|
@ -188,13 +191,14 @@ const handleSearch = async () => {
|
||||||
// 搜索重置
|
// 搜索重置
|
||||||
const handleReset = () => {
|
const handleReset = () => {
|
||||||
clientSearchForm.value = {
|
clientSearchForm.value = {
|
||||||
page: 1,
|
currentPage: 1,
|
||||||
pageSize: 10,
|
pageSize: 1,
|
||||||
username: '',
|
username: '',
|
||||||
status: '正常',
|
status: '正常',
|
||||||
startDateTime: '',
|
startDateTime: '',
|
||||||
endDateTime: '',
|
endDateTime: '',
|
||||||
}
|
}
|
||||||
|
fetchClientList() // 重置后自动刷新列表
|
||||||
}
|
}
|
||||||
|
|
||||||
// 客户表单选项切换
|
// 客户表单选项切换
|
||||||
|
|
@ -202,26 +206,36 @@ const handleDialogType = (type: string) => {
|
||||||
clientFormOptions.value = type === 'add' ? clientAddFormItem : clientChangeFormItem
|
clientFormOptions.value = type === 'add' ? clientAddFormItem : clientChangeFormItem
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 映射对象为数组通用方法
|
||||||
|
const mapObjectToOptions = (obj: Record<string, string>) => {
|
||||||
|
return Object.entries(obj).map(([label, value]) => ({
|
||||||
|
label, // 模板/代理名称
|
||||||
|
value // 模板/代理ID
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
//统一获取表单选项
|
//统一获取表单选项
|
||||||
|
const optionsFetched = ref(false)
|
||||||
const getOptions = async () => {
|
const getOptions = async () => {
|
||||||
|
// 已获取过选项则直接返回,避免重复请求
|
||||||
|
if (optionsFetched.value) return
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// 并行请求,提升性能
|
|
||||||
const [agentRes, feeTemplateRes, riskTemplateRes] = await Promise.all([
|
const [agentRes, feeTemplateRes, riskTemplateRes] = await Promise.all([
|
||||||
getAgentOptionsApi(),
|
getAgentOptionsApi(),
|
||||||
getFeeTemplateOptionsApi(),
|
getFeeTemplateOptionsApi(),
|
||||||
getRiskTemplateOptionsApi()
|
getRiskTemplateOptionsApi()
|
||||||
]);
|
])
|
||||||
|
|
||||||
const agentOptions = mapObjectToOptions(agentRes as Record<string, string>);
|
// 修正映射:label=名称,value=ID
|
||||||
const feeTemplateOptions = mapObjectToOptions(feeTemplateRes as Record<string, string>);
|
clientFormOptionsMap.value.agentUsername = mapObjectToOptions(agentRes as Record<string, string>)
|
||||||
const riskTemplateOptions = mapObjectToOptions(riskTemplateRes as Record<string, string>);
|
clientFormOptionsMap.value.feeTemplate = mapObjectToOptions(feeTemplateRes as Record<string, string>)
|
||||||
|
clientFormOptionsMap.value.riskTemplate = mapObjectToOptions(riskTemplateRes as Record<string, string>)
|
||||||
|
|
||||||
// 更新表单选项
|
optionsFetched.value = true // 标记已获取
|
||||||
clientFormOptionsMap.value.agentUsername = agentOptions;
|
|
||||||
clientFormOptionsMap.value.feeTemplate = feeTemplateOptions;
|
|
||||||
clientFormOptionsMap.value.riskTemplate = riskTemplateOptions;
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('获取表单选项失败:', error);
|
console.error('获取表单选项失败:', error)
|
||||||
|
ElMessage.error('获取表单选项失败,请稍后重试')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -252,8 +266,9 @@ const handleChange = async (row: any) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
// 分页事件
|
// 分页事件
|
||||||
const handlePaginationChange = (page: number) => {
|
const handlePaginationChange = (page: { currentPage: number, pageSize: number }) => {
|
||||||
clientSearchForm.value.page = page
|
clientSearchForm.value.currentPage = page.currentPage
|
||||||
|
clientSearchForm.value.pageSize = page.pageSize
|
||||||
handleSearch()
|
handleSearch()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -261,15 +276,6 @@ const handlePaginationChange = (page: number) => {
|
||||||
* @description: dialog事件
|
* @description: dialog事件
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
// 映射对象为数组通用方法
|
|
||||||
const mapObjectToOptions = (obj: Record<string, string>) => {
|
|
||||||
return Object.entries(obj).map(([label, value]) => ({
|
|
||||||
label: label, // 模板名称作为显示标签
|
|
||||||
value: value // 模板ID作为对应值
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
|
|
||||||
// 客户添加
|
// 客户添加
|
||||||
const handleAdd = async () => {
|
const handleAdd = async () => {
|
||||||
dialogVisible.value = true
|
dialogVisible.value = true
|
||||||
|
|
@ -296,7 +302,6 @@ const handleSubmit = async () => {
|
||||||
await fetchClientList()
|
await fetchClientList()
|
||||||
dialogVisible.value = false
|
dialogVisible.value = false
|
||||||
} else {
|
} else {
|
||||||
console.log('编辑客户', clientForm.value)
|
|
||||||
const params = {
|
const params = {
|
||||||
user_id: clientForm.value.id,
|
user_id: clientForm.value.id,
|
||||||
risk_control_id: clientForm.value.riskTemplate,
|
risk_control_id: clientForm.value.riskTemplate,
|
||||||
|
|
|
||||||
|
|
@ -74,6 +74,7 @@ export const clientChangeFormItem = [
|
||||||
{ prop: 'riskTemplate', label: '风控模板', type: 'select' as const, placeholder: '选择风控模板' },
|
{ prop: 'riskTemplate', label: '风控模板', type: 'select' as const, placeholder: '选择风控模板' },
|
||||||
{ prop: 'changeName', label: '客户名称', type: 'input' as const, placeholder: '客户名称' },
|
{ prop: 'changeName', label: '客户名称', type: 'input' as const, placeholder: '客户名称' },
|
||||||
{ prop: 'isUpgrade', label: '是否升级为代理', type: 'radio' as const, placeholder: '是否升级为代理', labelWidth: '140px' },
|
{ prop: 'isUpgrade', label: '是否升级为代理', type: 'radio' as const, placeholder: '是否升级为代理', labelWidth: '140px' },
|
||||||
|
{ prop: 'status', label: '选择状态', type: 'radio' as const, placeholder: '请选择状态', labelWidth: '140px' },
|
||||||
]
|
]
|
||||||
|
|
||||||
// 国家码选项
|
// 国家码选项
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,10 @@ export const rules = (): FormRules => {
|
||||||
isUpgrade: [
|
isUpgrade: [
|
||||||
{ required: true, message: '请选择是否升级为代理', trigger: ['blur'] },
|
{ required: true, message: '请选择是否升级为代理', trigger: ['blur'] },
|
||||||
],
|
],
|
||||||
|
//选择状态
|
||||||
|
status: [
|
||||||
|
{ required: true, message: '请选择状态', trigger: ['blur'] },
|
||||||
|
],
|
||||||
//客户名称
|
//客户名称
|
||||||
changeName: [
|
changeName: [
|
||||||
{ required: true, message: '请输入客户名称', trigger: ['blur'] },
|
{ required: true, message: '请输入客户名称', trigger: ['blur'] },
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,307 @@
|
||||||
<template>
|
<template>
|
||||||
<div>
|
<div class="market">
|
||||||
<h1>做市商管理</h1>
|
<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(row)">
|
||||||
|
编辑
|
||||||
|
</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)">
|
||||||
|
查看
|
||||||
|
</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>
|
</div>
|
||||||
</template>
|
</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 } from '@/api/modules/account/market'
|
||||||
|
|
||||||
|
// 配置
|
||||||
|
import { marketSearch, marketTableColumns, marketFormItem, marketPointTableColumns } from './options'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 搜索配置
|
||||||
|
*/
|
||||||
|
const marketSearchForm = ref<any>({
|
||||||
|
accountName: '',
|
||||||
|
page: 1,
|
||||||
|
pageSize: 10,
|
||||||
|
})
|
||||||
|
const marketSearchOptions = ref<any>(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 total = ref<number>(0)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description dialog配置
|
||||||
|
*/
|
||||||
|
|
||||||
|
const dialogVisible = ref<boolean>(false)
|
||||||
|
const dialogTitle = ref<string>('')
|
||||||
|
const dialogType = ref<string>('add')
|
||||||
|
const dialogFullscreen = ref(false)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 点差表格配置
|
||||||
|
*/
|
||||||
|
const marketPointTree = ref<any>([])
|
||||||
|
const marketPointTableColumnsOptions = ref<any>(marketPointTableColumns)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @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 统一获取数据
|
||||||
|
*/
|
||||||
|
|
||||||
|
//获取做市商列表
|
||||||
|
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: 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: marketForm.value.id
|
||||||
|
}
|
||||||
|
const data = await getPointDiffConfigApi(params)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 组件挂载时获取数据
|
||||||
|
*/
|
||||||
|
onMounted(() => {
|
||||||
|
fetchMarketList()
|
||||||
|
})
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 搜索
|
||||||
|
*/
|
||||||
|
const handleSearch = async () => {
|
||||||
|
await fetchMarketList()
|
||||||
|
}
|
||||||
|
const handleReset = () => {
|
||||||
|
marketSearchForm.value.accountName = ''
|
||||||
|
handleSearch()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 处理弹窗类型
|
||||||
|
*/
|
||||||
|
const handleDialogType = (type: string) => {
|
||||||
|
console.log('handleDialogType', type)
|
||||||
|
if (type === 'add') {
|
||||||
|
isAddOrEdit.value = true
|
||||||
|
} else {
|
||||||
|
isAddOrEdit.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 新增做市商
|
||||||
|
*/
|
||||||
|
const handleAddAgent = () => {
|
||||||
|
dialogVisible.value = true
|
||||||
|
dialogTitle.value = '新增做市商'
|
||||||
|
dialogType.value = 'add'
|
||||||
|
handleDialogType(dialogType.value)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 编辑做市商
|
||||||
|
*/
|
||||||
|
const handleEditAgent = (row: any) => {
|
||||||
|
dialogVisible.value = true
|
||||||
|
dialogTitle.value = '编辑做市商'
|
||||||
|
dialogType.value = 'edit'
|
||||||
|
marketForm.value = { ...row }
|
||||||
|
handleDialogType(dialogType.value)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @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 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(.edit-dialog) {
|
||||||
|
.el-dialog__footer {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,64 @@
|
||||||
|
//做市商搜索配置
|
||||||
|
|
||||||
|
export const marketSearch = [
|
||||||
|
{ label: '账户名', prop: 'accountName', type: 'input', placeholder: '请输入账户名', width: '340px', },
|
||||||
|
]
|
||||||
|
|
||||||
|
export const marketTableColumns = [
|
||||||
|
{ label: 'ID', prop: 'id', align: 'center' as const },
|
||||||
|
//代理关系
|
||||||
|
{ label: '代理关系', prop: 'agentRelation', align: 'center' as const },
|
||||||
|
//账户名
|
||||||
|
{ label: '账户名', prop: 'accountName', align: 'center' as const },
|
||||||
|
//级别
|
||||||
|
{ label: '级别', prop: 'level', align: 'center' as const },
|
||||||
|
//基本账户
|
||||||
|
{ label: '基本账户', prop: 'basicAccount', align: 'center' as const },
|
||||||
|
//保证金
|
||||||
|
{ label: '保证金', prop: 'margin', align: 'center' as const },
|
||||||
|
//停止接单保证金
|
||||||
|
{ label: '停止接单保证金', prop: 'stopOrderMargin', align: 'center' as const, width: '160px' },
|
||||||
|
//持仓转移保证金
|
||||||
|
{ label: '持仓转移保证金', prop: 'positionTransferMargin', align: 'center' as const, width: '160px' },
|
||||||
|
//点差返佣
|
||||||
|
{ label: '点差返佣', prop: 'pointSpreadCommission', align: 'center' as const },
|
||||||
|
//点差
|
||||||
|
{ label: '点差', slotName: 'pointSpread', align: 'center' as const },
|
||||||
|
//手续费比例
|
||||||
|
{ 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: 'riskMargin', align: 'center' as const },
|
||||||
|
//服务费
|
||||||
|
{ label: '服务费', prop: 'serviceFee', align: 'center' as const },
|
||||||
|
]
|
||||||
|
|
||||||
|
//做市商添加配置
|
||||||
|
export const marketFormItem = [
|
||||||
|
{ label: '账户名称', prop: 'accountName', type: 'input', placeholder: '请输入账户名称', },
|
||||||
|
//级别
|
||||||
|
{
|
||||||
|
label: '级别', prop: 'level', type: 'select', placeholder: '请选择级别', options: [
|
||||||
|
{ label: '一级', value: '1' },
|
||||||
|
{ label: '二级', value: '2' },
|
||||||
|
{ label: '三级', value: '3' },
|
||||||
|
]
|
||||||
|
},
|
||||||
|
//所属上级
|
||||||
|
{ label: '所属上级', prop: 'parentAccountName', type: 'select', placeholder: '请输入所属上级账户名称', },
|
||||||
|
//头寸
|
||||||
|
{ label: '头寸', prop: 'position', type: 'input', placeholder: '请输入头寸', },
|
||||||
|
//手续费
|
||||||
|
{ label: '手续费', prop: 'commissionRatio', type: 'input', placeholder: '请输入手续费', },
|
||||||
|
]
|
||||||
|
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 },
|
||||||
|
])
|
||||||
|
|
@ -126,7 +126,7 @@ const handleLogin = async () => {
|
||||||
mobile: loginForm.value.phone,
|
mobile: loginForm.value.phone,
|
||||||
login_type: getStorage('loginType', 'session') === 'email' ? 1 : 2,
|
login_type: getStorage('loginType', 'session') === 'email' ? 1 : 2,
|
||||||
code: loginForm.value.code,
|
code: loginForm.value.code,
|
||||||
password: md5Encrypt(loginForm.value.password)
|
password: loginForm.value.password
|
||||||
};
|
};
|
||||||
await userStore.login(loginParams);
|
await userStore.login(loginParams);
|
||||||
activeTab.value = 'email'; // 重置tab
|
activeTab.value = 'email'; // 重置tab
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue