This commit is contained in:
李远 2026-03-16 18:32:34 +08:00
parent 05650ed956
commit 08cc5486dc
1 changed files with 0 additions and 398 deletions

View File

@ -1,398 +0,0 @@
<template>
<div class="client">
<!-- 搜索组件 -->
<ClientSearch :search-form="clientSearchForm" :search-options="clientSearchOptions" @search="handleSearch"
@reset="handleReset">
<template #button="{ form }">
<el-button type="primary" @click="handleAdd()">
添加客户
</el-button>
</template>
</ClientSearch>
<ClientTable :table-data="clientTree" :columns="clientTableColumns" row-key="id" :tree-props="treeProps">
<template #status="{ row }">
<el-switch :model-value="row.status === 1" :active-value="true" :inactive-value="false" active-text="启用"
inactive-text="禁用" />
</template>
<template #action="{ row }">
<el-button type="primary" size="small" @click="handleChange(row)">
修改
</el-button>
</template>
</ClientTable>
<ClientPagination :modelValue="clientSearchForm.currentPage" :pageSizeValue="clientSearchForm.pageSize"
:total="total" @pagination-change="handlePaginationChange" />
</div>
<!-- 客户弹窗 -->
<ClientDialog :visible="dialogVisible" :title="dialogTitle" :type="dialogType" @confirm="handleSubmit"
@cancel="handleCancel" @close="handleClose">
<ClientForm :form-data="clientForm" :form-rules="clientFormRules" :form-items="clientFormOptions"
:options-map="clientFormOptionsMap" ref="clientFormRef">
<template #phoneOrEmail="{ formData }">
<div class="phone-email">
<div class="tab-btn">
<el-button type="primary" size="small" :class="{ 'active': activeTab === 'email' }"
@click="activeTab = 'email'">
邮箱
</el-button>
<el-button type="primary" class="phone" size="small"
:class="{ 'active': activeTab === 'phone' }" @click="activeTab = 'phone'">
手机号
</el-button>
</div>
<el-form-item prop="email" v-if="activeTab === 'email'" class="email-item">
<el-input v-model="formData.email" placeholder="请输入邮箱"></el-input>
</el-form-item>
<el-form-item prop="phone" v-else class="phone-item">
<el-select v-model="formData.countryCode" :teleported="false" value-key="code" placeholder="国家"
class="country-select">
<el-option v-for="item in countryOptions" :key="item.code" :label="item.code"
:value="item.code">
<div class="country-option">
<span class="country-name">{{ item.name }}</span>
<span class="country-code">{{ item.code }}</span>
</div>
</el-option>
</el-select>
<el-input v-model="formData.phone" placeholder="请输入手机号" clearable />
</el-form-item>
</div>
</template>
</ClientForm>
</ClientDialog>
</template>
<script lang="ts" setup>
// 组件
import ClientSearch from '@/components/common/Search.vue'
import ClientTable from '@/components/common/Table.vue'
import ClientPagination from '@/components/common/Pagination.vue'
import ClientDialog from '@/components/common/Dialog.vue'
import ClientForm from '@/components/common/Form.vue'
// 接口
import { getClientListApi, getFeeTemplateOptionsApi, getRiskTemplateOptionsApi, getAgentOptionsApi, createClientApi, editClientApi } from '@/api/modules/account/client'
// 配置
import { clientSearch, clientAddFormItem, clientChangeFormItem, countryOptions, clientTableColumns } from './options'
import { rules } from './rules'
//定义客户搜索表单配置
const clientSearchOptions = ref(clientSearch)
const clientSearchForm = ref({
currentPage: 1,
pageSize: 1,
username: '',
status: '正常',
startDateTime: '',
endDateTime: '',
})
//定义表格配置
const clientTree = ref<any[]>([])
const treeProps = ref({
children: 'parent',
label: 'username'
})
// 定义分页配置
const total = ref(0)
// 定义dialog配置
const dialogTitle = ref('')
const dialogVisible = ref(false)
const dialogType = ref('add')
const clientForm = ref({
//手续费模板
feeTemplate: '',
//风控模板
riskTemplate: '',
//所属上级名
agentUsername: '',
email: '',
phone: '',
countryCode: '+86',
//是否升级
isUpgrade: 1,
//是否变更客户名
userName: '',
status: 1,
id: '',
})
// 定义客户表单配置
const clientFormRef = ref()
const clientFormRules = ref(rules())
const clientFormOptions = ref<any[]>(clientAddFormItem)
// 定义客户表单选项切换
const activeTab = ref('email')
// 定义客户表单选项类型
interface FormOption {
label: string;
value: string | number;
}
interface ClientFormOptionsMap {
feeTemplate: FormOption[];
riskTemplate: FormOption[];
agentUsername: FormOption[];
isUpgrade: FormOption[];
status: FormOption[];
}
const clientFormOptionsMap = ref<ClientFormOptionsMap>({
feeTemplate: [],
riskTemplate: [],
agentUsername: [],
isUpgrade: [
{ label: '是', value: 1 },
{ label: '否', value: 2 }
],
status: [
{ label: '正常', value: 1 },
{ label: '禁用', value: 2 }
],
})
// 获取账户列表
const fetchClientList = async () => {
const params = {
page: clientSearchForm.value.currentPage,
page_size: clientSearchForm.value.pageSize,
username: clientSearchForm.value.username,
status: clientSearchForm.value.status === '正常' ? 1 : 2,
reg_start_time: clientSearchForm.value.startDateTime.length > 0 ? `${clientSearchForm.value.startDateTime} 0:00:00` : '',
reg_end_time: clientSearchForm.value.endDateTime.length > 0 ? `${clientSearchForm.value.endDateTime} 23:59:59` : '',
}
const data = await getClientListApi(params)
clientTree.value = data.data.map(item => ({
...item,
// 映射所属代理用户名
agentUsername: item.par_uid === item.parent?.id ? item.parent?.username : '',
}));
//把接口返回的分页字段赋值给分页组件
total.value = Number(data.total)
clientSearchForm.value.currentPage = Number(data.current_page)
clientSearchForm.value.pageSize = Number(data.per_page)
}
onMounted(async () => {
await fetchClientList()
})
/**
* @description: 搜索事件
*/
// 搜索
const handleSearch = async () => {
try {
await fetchClientList()
} catch (err) {
console.error('获取客户列表失败', err)
}
}
// 搜索重置
const handleReset = () => {
clientSearchForm.value = {
currentPage: 1,
pageSize: 1,
username: '',
status: '正常',
startDateTime: '',
endDateTime: '',
}
fetchClientList() // 重置后自动刷新列表
}
// 客户表单选项切换
const handleDialogType = (type: string) => {
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 () => {
// 已获取过选项则直接返回,避免重复请求
if (optionsFetched.value) return
try {
const [agentRes, feeTemplateRes, riskTemplateRes] = await Promise.all([
getAgentOptionsApi(),
getFeeTemplateOptionsApi(),
getRiskTemplateOptionsApi()
])
// 修正映射:label=名称,value=ID
clientFormOptionsMap.value.agentUsername = mapObjectToOptions(agentRes 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 // 标记已获取
} catch (error) {
console.error('获取表单选项失败:', error)
ElMessage.error('获取表单选项失败,请稍后重试')
}
}
/**
* @description: 表格修改事件
*/
const handleChange = async (row: any) => {
dialogVisible.value = true
dialogTitle.value = '修改客户'
dialogType.value = 'edit'
handleDialogType(dialogType.value)
//获取表单选项
await getOptions()
// 核心:将选中行的数值赋值给表单,尤其是id
clientForm.value = {
id: row.id, // 关键:传递用户ID
feeTemplate: row.feeTemplate || '', // 回显手续费模板
riskTemplate: row.riskTemplate || '', // 回显风控模板
agentUsername: row.agentUsername || '', // 回显所属上级
email: row.email || '', // 回显邮箱
phone: row.phone || '', // 回显手机号
countryCode: row.countryCode || '+86', // 回显国家码
isUpgrade: row.isUpgrade || 1, // 回显是否升级
userName: row.username || '', // 回显用户名
status: row.status || 1, // 回显状态
}
}
// 分页事件
const handlePaginationChange = (page: { currentPage: number, pageSize: number }) => {
clientSearchForm.value.currentPage = page.currentPage
clientSearchForm.value.pageSize = page.pageSize
handleSearch()
}
/**
* @description: dialog事件
*/
// 客户添加
const handleAdd = async () => {
dialogVisible.value = true
dialogType.value = 'add'
dialogTitle.value = '添加客户'
handleDialogType(dialogType.value)
//获取表单选项
await getOptions()
}
const handleSubmit = async () => {
try {
await clientFormRef.value?.validate()
if (dialogType.value === 'add') {
const params = {
reg_type: activeTab.value === 'email' ? 1 : 2,
email: clientForm.value.email,
mobile: clientForm.value.phone,
parent_id: clientForm.value.agentUsername,
risk_control_id: clientForm.value.riskTemplate,
fee_setting_id: clientForm.value.feeTemplate,
}
await createClientApi(params)
await fetchClientList()
dialogVisible.value = false
} else {
const params = {
user_id: clientForm.value.id,
risk_control_id: clientForm.value.riskTemplate,
fee_setting_id: clientForm.value.feeTemplate,
username: clientForm.value.userName,
is_levelup: clientForm.value.isUpgrade,
status: clientForm.value.status,
}
await editClientApi(params)
await fetchClientList()
dialogVisible.value = false
}
} catch (err) {
console.error('客户表单验证失败', err)
}
}
const resetForm = () => {
clientForm.value = {
//手续费模板
feeTemplate: '',
//风控模板
riskTemplate: '',
//所属上级
agentUsername: '',
email: '',
phone: '',
countryCode: '+86',
//是否升级
isUpgrade: 1,
//是否变更客户名
userName: '',
status: 1,
id: '',
}
}
// 弹窗取消
const handleCancel = () => {
dialogVisible.value = false
dialogType.value = 'add'
resetForm()
}
// 弹窗关闭
const handleClose = () => {
dialogVisible.value = false
dialogType.value = 'add'
resetForm()
}
</script>
<style scoped>
.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>