This commit is contained in:
李远 2026-03-16 18:47:20 +08:00
parent 08cc5486dc
commit a73ec399f7
2 changed files with 411 additions and 318 deletions

View File

@ -1,341 +1,93 @@
<template>
<div class="agent">
<AgentSearch :search-form="agentSearchForm" :search-options="agentSearchOptions" @search="handleSearch"
@reset="handleReset">
</AgentSearch>
<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"
:total="agentSearchForm.total" @pagination-change="handlePaginationChange" />
<AgentDialog :visible="dialogVisible" :title="dialogTitle" :type="dialogType" :fullscreen="dialogFullscreen" @submit="handleSubmit"
@cancel="handleCancel" @close="handleClose" :class="{ 'edit-dialog': isEdit }">
<AgentForm :form-data="agentForm" :form-rules="agentFormRules" :form-items="agentFormItems"
:options-map="agentFormOptionsMap" v-if="isEdit" />
<AgentTable :table-data="agentPointTree" :columns="agentPointTableColumnsOptions" row-key="id" />
</AgentDialog>
<!-- 搜索 -->
<MarketSearch :search-form="searchForm" :search-options="searchOptions" @search="handleSearch" />
<!-- 表格 -->
<!-- <MarketTable :table-data="tableData" :table-columns="tableColumns" @change="handleChange" /> -->
<!-- 分页 -->
<!-- <MarketPagination :pagination="pagination" @change="handlePaginationChange" /> -->
</div>
<!-- 弹窗 -->
<!-- 编辑/查看表单 -->
</template>
<script lang="ts" setup>
//
import AgentSearch from '@/components/common/Search.vue'
import AgentTable from '@/components/common/Table.vue'
import AgentPagination from '@/components/common/Pagination.vue'
import AgentDialog from '@/components/common/Dialog.vue'
import AgentForm from '@/components/common/Form.vue'
//
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 { getAgentListApi, getPointDiffConfigApi, getRiskTemplateOptionsApi, getFeeTemplateOptionsApi,editPointDiffConfigApi } from '@/api/modules/account/agent'
//
import { agentSearch, agentTableColumns, agentPointTableColumns, PointDiffFormItem } from './options'
//
const agentSearchOptions = ref(agentSearch)
const agentSearchForm = ref({
/**
* @description 定义搜索数据
*/
const searchForm = ref({
username: '',
status: '正常',
startDateTime: '',
endDateTime: '',
page: 1,
pageSize: 100,
total: 100,
})
//
const agentTree = ref<any[]>([])
const agentTableColumnsOptions = ref(agentTableColumns)
//
const dialogVisible = ref(false)
const dialogTitle = ref('查看点差')
const searchOptions = ref()
/**
* @description 定义表格数据
*/
const AgentTree = ref([])
const agentTableColumnsOptions = ref()
/**
* @description 定义分页数据
*/
const total = ref(0)
const pageSize = ref(10)
const currentPage = ref(1)
/**
* @description 定义弹窗数据
*/
const dialogVisible = ref<boolean>(false)
const dialogTitle = ref<string>('')
const dialogType = ref<string>('edit')
const dialogFullscreen = ref(false)
const dialogType = ref('add')
const agentPointTree = ref<any[]>([])
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 统一获取数据
* @description 定义弹窗form数据
*/
const agentForm = ref({})
const agentFormRules = ref()
const agentFormRef = ref()
const agentFormItemOptions = ref()
const agentFormOptionsMap = ref()
/**
* 处理字符串数值转数字 + 相加 + 保留五位小数
* @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.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方法
* @description 定义弹窗表格数据
*/
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 {
}
}
/**
* @description 定义通用数据处理方法
*/
//
const handleCancel = () => {
dialogVisible.value = false
dialogType.value = 'view'
}
/**
* @description 定义通用数据获取方法
*/
/**
* @description 页面加载完成需要调用的方法
*/
//
const handleClose = () => {
dialogVisible.value = false
dialogType.value = 'view'
}
/**
* @description 定义搜索方法
*/
/**
* @description 定义表格方法
*/
/**
* @description 定义分页方法
*/
/**
* @description 定义dialog方法
*/
</script>
<style scoped lang="scss">
.agent {
:deep(.el-dialog) {
.el-dialog__footer {
display: none;
}
}
:deep(.edit-dialog) {
.el-dialog__footer {
display: block;
}
}
}
</style>
<style scoped lang="scss"></style>

View File

@ -0,0 +1,341 @@
<template>
<div class="agent">
<AgentSearch :search-form="agentSearchForm" :search-options="agentSearchOptions" @search="handleSearch"
@reset="handleReset">
</AgentSearch>
<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"
:total="agentSearchForm.total" @pagination-change="handlePaginationChange" />
<AgentDialog :visible="dialogVisible" :title="dialogTitle" :type="dialogType" :fullscreen="dialogFullscreen" @submit="handleSubmit"
@cancel="handleCancel" @close="handleClose" :class="{ 'edit-dialog': isEdit }">
<AgentForm :form-data="agentForm" :form-rules="agentFormRules" :form-items="agentFormItems"
:options-map="agentFormOptionsMap" v-if="isEdit" />
<AgentTable :table-data="agentPointTree" :columns="agentPointTableColumnsOptions" row-key="id" />
</AgentDialog>
</div>
</template>
<script lang="ts" setup>
//
import AgentSearch from '@/components/common/Search.vue'
import AgentTable from '@/components/common/Table.vue'
import AgentPagination from '@/components/common/Pagination.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, PointDiffFormItem } from './options'
//
const agentSearchOptions = ref(agentSearch)
const agentSearchForm = ref({
username: '',
status: '正常',
startDateTime: '',
endDateTime: '',
page: 1,
pageSize: 100,
total: 100,
})
//
const agentTree = ref<any[]>([])
const agentTableColumnsOptions = ref(agentTableColumns)
//
const dialogVisible = ref(false)
const dialogTitle = ref('查看点差')
const dialogFullscreen = ref(false)
const dialogType = ref('add')
const agentPointTree = ref<any[]>([])
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.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>
<style scoped lang="scss">
.agent {
:deep(.el-dialog) {
.el-dialog__footer {
display: none;
}
}
:deep(.edit-dialog) {
.el-dialog__footer {
display: block;
}
}
}
</style>