foreign-admin-ui/src/views/profile/user/index.vue

447 lines
11 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<div class="client">
<!-- 搜索组件 -->
<ClientSearch
:search-form="clientSearchForm"
:search-options="clientSearchOptions"
@search="handleSearch"
@reset="handleReset"
>
<template #button="{ form }">
<el-button type="primary" @click="handleAdd()" v-auth="'user_createUser'">
添加客户
</el-button>
</template>
</ClientSearch>
<!-- 表格组件 -->
<ClientTable :table-data="clientTree" :columns="clientTableColumns">
<template #status="{ row }">
{{ row.status === 1 ? '正常' : '禁用' }}
</template>
<template #action="{ row }">
<el-button type="primary" size="small" @click="handleChange(row)" v-anth="'user_editUser'">
修改
</el-button>
</template>
</ClientTable>
<!-- 分页组件 -->
<ClientPagination
v-model="currentPage"
v-model:pageSizeValue="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 }" style="margin-left: 0">
<div class="phone-email">
<div class="tab-btn">
<el-button
:type="activeTab === 'email' ? 'primary' : 'default'"
size="small"
@click="activeTab = 'email'"
>
邮箱
</el-button>
<el-button
:type="activeTab === 'phone' ? 'primary' : 'default'"
size="small"
@click="activeTab = 'phone'"
>
手机号
</el-button>
</div>
<div class="group">
<el-form-item prop="email" v-if="activeTab === 'email'">
<el-input v-model="clientForm.email" placeholder="请输入邮箱" />
</el-form-item>
<el-form-item prop="phone" class="phone-item" v-if="activeTab === 'phone'">
<el-select v-model="clientForm.countryCode" placeholder="请选择国家区号">
<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="clientForm.phone" placeholder="请输入手机号" />
</el-form-item>
</div>
</div>
</template>
</ClientForm>
</ClientDialog>
</template>
<script lang="ts" setup>
defineOptions({
name: 'User'
})
// 组件
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'
/**
* @description 定义搜索数据
*/
const clientSearchOptions = ref(clientSearch)
const clientSearchForm = ref({
username: '',
status: 1,
startDateTime: '',
endDateTime: '',
})
/**
* @description 定义表格数据
*/
const clientTree = ref<any[]>([])
/**
* @description 定义分页数据
*/
const total = ref(0)
const currentPage = ref(1)
const pageSize = ref(10)
/**
* @description 定义dialog数据
*/
const dialogTitle = ref('')
const dialogVisible = ref(false)
const dialogType = ref('add')
/**
* @description 定义dialog中form的数据
*/
const clientForm = ref({
//手续费模板
feeTemplate: '',
//风控模板
riskTemplate: '',
//所属上级名
agentUsername: '',
email: '',
phone: '',
countryCode: '+86',
//是否升级
isUpgrade: 1,
//是否变更客户名
userName: '',
status: 1,
})
// 定义客户表单配置
const clientFormRef = ref()
const clientFormRules = ref(rules())
// 定义客户表单选项是否已获取
const optionsFetched = ref(false)
const useId = ref('')
const clientFormOptions = computed(() => {
return dialogType.value === 'add' ? clientAddFormItem : clientChangeFormItem
})
const clientFormOptionsMap = ref<any>({
feeTemplate: [],
riskTemplate: [],
agentUsername: [],
isUpgrade: [
{ label: '是', value: 1 },
{ label: '否', value: 2 },
],
status: [
{ label: '正常', value: 1 },
{ label: '禁用', value: 2 },
],
})
// 定义客户表单选项切换
const activeTab = ref('email')
/**
* @description 统一数据处理方法
*/
// 映射对象为数组通用方法
const mapObjectToOptions = (obj: Record<string, string>) => {
return Object.entries(obj).map(([label, value]) => ({
label, // 模板/代理名称
value, // 模板/代理ID
}))
}
/**
* @description 统一获取数据方法
*/
const getClientList = async () => {
const params = {
page: currentPage.value,
page_size: pageSize.value,
username: clientSearchForm.value.username,
status: clientSearchForm.value.status || '',
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,
//注册时间
createdTime: item.created_at,
// 映射所属代理用户名
agentUsername: item.par_uid === item.parent?.id ? item.parent?.username : '',
}))
//分页数据
total.value = Number(data.total)
currentPage.value = Number(data.current_page)
pageSize.value = Number(data.per_page)
}
// 获取客户表单选项
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)
}
}
//
/**
* @description 页面加载后获取数据
*/
onMounted(async () => {
await getClientList()
})
/**
* @description 搜索方法
*/
const handleSearch = async () => {
try {
await getClientList()
} catch (err) {
console.error('获取客户列表失败', err)
}
}
const handleReset = async () => {
// 重置搜索表单
clientSearchForm.value = {
username: '',
status: '正常',
startDateTime: '',
endDateTime: '',
}
try {
await getClientList()
} catch (err) {
console.error('获取客户列表失败', err)
}
}
// 添加客户
const handleAdd = () => {
// 打开添加客户弹窗
dialogVisible.value = true
dialogTitle.value = '添加客户'
dialogType.value = 'add'
clientForm.value = {
//手续费模板
feeTemplate: '',
//风控模板
riskTemplate: '',
//所属上级名
agentUsername: '',
email: '',
phone: '',
countryCode: '+86',
//是否升级
isUpgrade: 1,
//是否变更客户名
userName: '',
status: 1,
}
getOptions()
}
/**
* @description 表格方法
*/
const handleChange = (row: any) => {
// 打开修改客户弹窗
dialogVisible.value = true
dialogTitle.value = '修改客户'
dialogType.value = 'change'
useId.value = row.id
clientForm.value = {
//手续费模板
feeTemplate: row.wallet_capital.fee_setting_id,
//风控模板
riskTemplate: row.wallet_capital.risk_control_id,
userName: row.username,
status: row.status,
isUpgrade: 2,
} as any
console.log('rowrowrowrowrowrowrowrowrow', clientForm.value)
getOptions()
}
/**
* @description 分页方法
*/
const handlePaginationChange = (page: { currentPage: number; pageSize: number }) => {
currentPage.value = page.currentPage
pageSize.value = page.pageSize
handleSearch()
}
/**
* @description 客户弹窗方法
*/
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 getClientList()
dialogVisible.value = false
} else {
const params = {
user_id: useId.value,
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 getClientList()
dialogVisible.value = false
}
} catch (err) {
console.error('客户表单验证失败', err)
}
}
const handleCancel = () => {
// 关闭弹窗
dialogVisible.value = false
}
const handleClose = () => {
// 关闭弹窗
dialogVisible.value = false
}
</script>
<style scoped lang="scss">
:deep(.el-form-item__content) {
margin-left: 0 !important;
}
.phone-email {
display: flex;
flex: 1;
.tab-btn {
display: flex;
margin-right: 10px;
.el-button {
height: 32px;
margin-left: 0;
}
}
.group {
display: flex;
flex: 1;
.el-form-item {
flex: 1;
}
.phone-item {
:deep(.el-form-item__content) {
flex-wrap: nowrap;
}
.el-select {
width: 120px;
}
}
}
}
</style>