This commit is contained in:
parent
6d180b94a8
commit
05650ed956
|
|
@ -49,8 +49,8 @@ export async function changePasswordApi(params: ChangePasswordParams) {
|
||||||
* 退出登录
|
* 退出登录
|
||||||
* @returns Promise<void> 无返回值
|
* @returns Promise<void> 无返回值
|
||||||
*/
|
*/
|
||||||
export async function logoutApi() {
|
export async function logoutApi(params: { device_no: string }) {
|
||||||
return request.post<void>('/logout');
|
return request.post<void>('/logout', params);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -59,7 +59,8 @@ const handleChangePassword = () => {
|
||||||
|
|
||||||
const handleLogout = () => {
|
const handleLogout = () => {
|
||||||
// 示例:退出登录逻辑
|
// 示例:退出登录逻辑
|
||||||
userStore.logout()
|
const deviceNo = getStorage('device_no') as string
|
||||||
|
userStore.logout({ device_no: deviceNo })
|
||||||
}
|
}
|
||||||
|
|
||||||
// 处理菜单项点击
|
// 处理菜单项点击
|
||||||
|
|
|
||||||
|
|
@ -55,7 +55,7 @@ const clearUserInfo = () => {
|
||||||
removeStorage('userInfo');
|
removeStorage('userInfo');
|
||||||
removeStorage('menusInfo');
|
removeStorage('menusInfo');
|
||||||
removeStorage('permissionsInfo');
|
removeStorage('permissionsInfo');
|
||||||
|
removeStorage('device_no');
|
||||||
console.log('用户信息已清空');
|
console.log('用户信息已清空');
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -100,9 +100,9 @@ const register = async (params: RegisterParams) => {
|
||||||
/**
|
/**
|
||||||
* 退出登录
|
* 退出登录
|
||||||
*/
|
*/
|
||||||
const logout = async () => {
|
const logout = async (params: { device_no: string }) => {
|
||||||
try {
|
try {
|
||||||
await logoutApi();
|
await logoutApi(params);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('退出登录接口调用失败', error);
|
console.error('退出登录接口调用失败', error);
|
||||||
} finally {
|
} finally {
|
||||||
|
|
|
||||||
|
|
@ -9,10 +9,11 @@
|
||||||
</el-button>
|
</el-button>
|
||||||
</template>
|
</template>
|
||||||
</ClientSearch>
|
</ClientSearch>
|
||||||
<ClientTable :table-data="clientTree" :columns="clientTableColumns" row-key="id" :tree-props="treeProps">
|
|
||||||
|
<!-- 表格组件 -->
|
||||||
|
<ClientTable :table-data="clientTree" :columns="clientTableColumns">
|
||||||
<template #status="{ row }">
|
<template #status="{ row }">
|
||||||
<el-switch :model-value="row.status === 1" :active-value="true" :inactive-value="false" active-text="启用"
|
<el-switch :model-value="row.status === 1" :active-value="true" :inactive-value="false" />
|
||||||
inactive-text="禁用" />
|
|
||||||
</template>
|
</template>
|
||||||
<template #action="{ row }">
|
<template #action="{ row }">
|
||||||
<el-button type="primary" size="small" @click="handleChange(row)">
|
<el-button type="primary" size="small" @click="handleChange(row)">
|
||||||
|
|
@ -20,8 +21,9 @@
|
||||||
</el-button>
|
</el-button>
|
||||||
</template>
|
</template>
|
||||||
</ClientTable>
|
</ClientTable>
|
||||||
<ClientPagination :modelValue="clientSearchForm.currentPage" :pageSizeValue="clientSearchForm.pageSize"
|
<!-- 分页组件 -->
|
||||||
:total="total" @pagination-change="handlePaginationChange" />
|
<ClientPagination v-model="currentPage" v-model:pageSizeValue="pageSize" :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"
|
||||||
|
|
@ -31,21 +33,21 @@
|
||||||
<template #phoneOrEmail="{ formData }">
|
<template #phoneOrEmail="{ formData }">
|
||||||
<div class="phone-email">
|
<div class="phone-email">
|
||||||
<div class="tab-btn">
|
<div class="tab-btn">
|
||||||
<el-button type="primary" size="small" :class="{ 'active': activeTab === 'email' }"
|
<el-button :type="activeTab === 'email' ? 'primary' : 'default'" size="small"
|
||||||
@click="activeTab = 'email'">
|
@click="activeTab = 'email'">
|
||||||
邮箱
|
邮箱
|
||||||
</el-button>
|
</el-button>
|
||||||
<el-button type="primary" class="phone" size="small"
|
<el-button :type="activeTab === 'phone' ? 'primary' : 'default'" size="small"
|
||||||
:class="{ 'active': activeTab === 'phone' }" @click="activeTab = 'phone'">
|
@click="activeTab = 'phone'">
|
||||||
手机号
|
手机号
|
||||||
</el-button>
|
</el-button>
|
||||||
</div>
|
</div>
|
||||||
<el-form-item prop="email" v-if="activeTab === 'email'" class="email-item">
|
<div class="group">
|
||||||
<el-input v-model="formData.email" placeholder="请输入邮箱"></el-input>
|
<el-form-item prop="email" v-if="activeTab === 'email'">
|
||||||
|
<el-input v-model="clientForm.email" placeholder="请输入邮箱" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item prop="phone" v-else class="phone-item">
|
<el-form-item prop="phone" class="phone-item" v-if="activeTab === 'phone'">
|
||||||
<el-select v-model="formData.countryCode" :teleported="false" value-key="code" placeholder="国家"
|
<el-select v-model="clientForm.countryCode" placeholder="请选择国家区号">
|
||||||
class="country-select">
|
|
||||||
<el-option v-for="item in countryOptions" :key="item.code" :label="item.code"
|
<el-option v-for="item in countryOptions" :key="item.code" :label="item.code"
|
||||||
:value="item.code">
|
:value="item.code">
|
||||||
<div class="country-option">
|
<div class="country-option">
|
||||||
|
|
@ -54,9 +56,10 @@
|
||||||
</div>
|
</div>
|
||||||
</el-option>
|
</el-option>
|
||||||
</el-select>
|
</el-select>
|
||||||
<el-input v-model="formData.phone" placeholder="请输入手机号" clearable />
|
<el-input v-model="clientForm.phone" placeholder="请输入手机号" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</ClientForm>
|
</ClientForm>
|
||||||
</ClientDialog>
|
</ClientDialog>
|
||||||
|
|
@ -76,31 +79,38 @@ import { getClientListApi, getFeeTemplateOptionsApi, getRiskTemplateOptionsApi,
|
||||||
import { clientSearch, clientAddFormItem, clientChangeFormItem, countryOptions, clientTableColumns } from './options'
|
import { clientSearch, clientAddFormItem, clientChangeFormItem, countryOptions, clientTableColumns } from './options'
|
||||||
import { rules } from './rules'
|
import { rules } from './rules'
|
||||||
|
|
||||||
//定义客户搜索表单配置
|
/**
|
||||||
|
* @description 定义搜索数据
|
||||||
|
*/
|
||||||
const clientSearchOptions = ref(clientSearch)
|
const clientSearchOptions = ref(clientSearch)
|
||||||
const clientSearchForm = ref({
|
const clientSearchForm = ref({
|
||||||
currentPage: 1,
|
|
||||||
pageSize: 1,
|
|
||||||
username: '',
|
username: '',
|
||||||
status: '正常',
|
status: '正常',
|
||||||
startDateTime: '',
|
startDateTime: '',
|
||||||
endDateTime: '',
|
endDateTime: '',
|
||||||
})
|
})
|
||||||
|
|
||||||
//定义表格配置
|
/**
|
||||||
|
* @description 定义表格数据
|
||||||
|
*/
|
||||||
const clientTree = ref<any[]>([])
|
const clientTree = ref<any[]>([])
|
||||||
const treeProps = ref({
|
|
||||||
children: 'parent',
|
|
||||||
label: 'username'
|
|
||||||
})
|
|
||||||
|
|
||||||
// 定义分页配置
|
/**
|
||||||
|
* @description 定义分页数据
|
||||||
|
*/
|
||||||
const total = ref(0)
|
const total = ref(0)
|
||||||
|
const currentPage = ref(1)
|
||||||
|
const pageSize = ref(10)
|
||||||
|
|
||||||
// 定义dialog配置
|
/**
|
||||||
|
* @description 定义dialog数据
|
||||||
|
*/
|
||||||
const dialogTitle = ref('')
|
const dialogTitle = ref('')
|
||||||
const dialogVisible = ref(false)
|
const dialogVisible = ref(false)
|
||||||
const dialogType = ref('add')
|
const dialogType = ref('add')
|
||||||
|
/**
|
||||||
|
* @description 定义dialog中form的数据
|
||||||
|
*/
|
||||||
const clientForm = ref({
|
const clientForm = ref({
|
||||||
//手续费模板
|
//手续费模板
|
||||||
feeTemplate: '',
|
feeTemplate: '',
|
||||||
|
|
@ -116,28 +126,18 @@ const clientForm = ref({
|
||||||
//是否变更客户名
|
//是否变更客户名
|
||||||
userName: '',
|
userName: '',
|
||||||
status: 1,
|
status: 1,
|
||||||
id: '',
|
|
||||||
})
|
})
|
||||||
|
|
||||||
// 定义客户表单配置
|
// 定义客户表单配置
|
||||||
const clientFormRef = ref()
|
const clientFormRef = ref()
|
||||||
const clientFormRules = ref(rules())
|
const clientFormRules = ref(rules())
|
||||||
const clientFormOptions = ref<any[]>(clientAddFormItem)
|
// 定义客户表单选项是否已获取
|
||||||
// 定义客户表单选项切换
|
const optionsFetched = ref(false)
|
||||||
const activeTab = ref('email')
|
const useId = ref('')
|
||||||
// 定义客户表单选项类型
|
const clientFormOptions = computed(() => {
|
||||||
interface FormOption {
|
return dialogType.value === 'add' ? clientAddFormItem : clientChangeFormItem;
|
||||||
label: string;
|
})
|
||||||
value: string | number;
|
const clientFormOptionsMap = ref<any>({
|
||||||
}
|
|
||||||
interface ClientFormOptionsMap {
|
|
||||||
feeTemplate: FormOption[];
|
|
||||||
riskTemplate: FormOption[];
|
|
||||||
agentUsername: FormOption[];
|
|
||||||
isUpgrade: FormOption[];
|
|
||||||
status: FormOption[];
|
|
||||||
}
|
|
||||||
const clientFormOptionsMap = ref<ClientFormOptionsMap>({
|
|
||||||
feeTemplate: [],
|
feeTemplate: [],
|
||||||
riskTemplate: [],
|
riskTemplate: [],
|
||||||
agentUsername: [],
|
agentUsername: [],
|
||||||
|
|
@ -150,62 +150,12 @@ const clientFormOptionsMap = ref<ClientFormOptionsMap>({
|
||||||
{ label: '禁用', value: 2 }
|
{ label: '禁用', value: 2 }
|
||||||
],
|
],
|
||||||
})
|
})
|
||||||
|
// 定义客户表单选项切换
|
||||||
|
const activeTab = ref('email')
|
||||||
|
|
||||||
// 获取账户列表
|
|
||||||
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: 搜索事件
|
* @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>) => {
|
const mapObjectToOptions = (obj: Record<string, string>) => {
|
||||||
return Object.entries(obj).map(([label, value]) => ({
|
return Object.entries(obj).map(([label, value]) => ({
|
||||||
|
|
@ -214,8 +164,34 @@ const mapObjectToOptions = (obj: Record<string, string>) => {
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
//统一获取表单选项
|
/**
|
||||||
const optionsFetched = ref(false)
|
* @description 统一获取数据方法
|
||||||
|
*/
|
||||||
|
const getClientList = async () => {
|
||||||
|
const params = {
|
||||||
|
page: currentPage.value,
|
||||||
|
page_size: pageSize.value,
|
||||||
|
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,
|
||||||
|
//注册时间
|
||||||
|
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 () => {
|
const getOptions = async () => {
|
||||||
// 已获取过选项则直接返回,避免重复请求
|
// 已获取过选项则直接返回,避免重复请求
|
||||||
if (optionsFetched.value) return
|
if (optionsFetched.value) return
|
||||||
|
|
@ -227,7 +203,7 @@ const getOptions = async () => {
|
||||||
getRiskTemplateOptionsApi()
|
getRiskTemplateOptionsApi()
|
||||||
])
|
])
|
||||||
|
|
||||||
// 修正映射:label=名称,value=ID
|
// label=名称,value=ID
|
||||||
clientFormOptionsMap.value.agentUsername = mapObjectToOptions(agentRes as Record<string, string>)
|
clientFormOptionsMap.value.agentUsername = mapObjectToOptions(agentRes as Record<string, string>)
|
||||||
clientFormOptionsMap.value.feeTemplate = mapObjectToOptions(feeTemplateRes as Record<string, string>)
|
clientFormOptionsMap.value.feeTemplate = mapObjectToOptions(feeTemplateRes as Record<string, string>)
|
||||||
clientFormOptionsMap.value.riskTemplate = mapObjectToOptions(riskTemplateRes as Record<string, string>)
|
clientFormOptionsMap.value.riskTemplate = mapObjectToOptions(riskTemplateRes as Record<string, string>)
|
||||||
|
|
@ -235,57 +211,90 @@ const getOptions = async () => {
|
||||||
optionsFetched.value = true // 标记已获取
|
optionsFetched.value = true // 标记已获取
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('获取表单选项失败:', error)
|
console.error('获取表单选项失败:', error)
|
||||||
ElMessage.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
|
||||||
|
getOptions()
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @description: 表格修改事件
|
* @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 }) => {
|
const handlePaginationChange = (page: { currentPage: number, pageSize: number }) => {
|
||||||
clientSearchForm.value.currentPage = page.currentPage
|
currentPage.value = page.currentPage
|
||||||
clientSearchForm.value.pageSize = page.pageSize
|
pageSize.value = page.pageSize
|
||||||
handleSearch()
|
handleSearch()
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @description: dialog事件
|
* @description 客户弹窗方法
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// 客户添加
|
|
||||||
const handleAdd = async () => {
|
|
||||||
dialogVisible.value = true
|
|
||||||
dialogType.value = 'add'
|
|
||||||
dialogTitle.value = '添加客户'
|
|
||||||
handleDialogType(dialogType.value)
|
|
||||||
//获取表单选项
|
|
||||||
await getOptions()
|
|
||||||
}
|
|
||||||
|
|
||||||
const handleSubmit = async () => {
|
const handleSubmit = async () => {
|
||||||
try {
|
try {
|
||||||
await clientFormRef.value?.validate()
|
await clientFormRef.value?.validate()
|
||||||
|
|
@ -299,11 +308,11 @@ const handleSubmit = async () => {
|
||||||
fee_setting_id: clientForm.value.feeTemplate,
|
fee_setting_id: clientForm.value.feeTemplate,
|
||||||
}
|
}
|
||||||
await createClientApi(params)
|
await createClientApi(params)
|
||||||
await fetchClientList()
|
await getClientList()
|
||||||
dialogVisible.value = false
|
dialogVisible.value = false
|
||||||
} else {
|
} else {
|
||||||
const params = {
|
const params = {
|
||||||
user_id: clientForm.value.id,
|
user_id: useId.value,
|
||||||
risk_control_id: clientForm.value.riskTemplate,
|
risk_control_id: clientForm.value.riskTemplate,
|
||||||
fee_setting_id: clientForm.value.feeTemplate,
|
fee_setting_id: clientForm.value.feeTemplate,
|
||||||
username: clientForm.value.userName,
|
username: clientForm.value.userName,
|
||||||
|
|
@ -311,87 +320,54 @@ const handleSubmit = async () => {
|
||||||
status: clientForm.value.status,
|
status: clientForm.value.status,
|
||||||
}
|
}
|
||||||
await editClientApi(params)
|
await editClientApi(params)
|
||||||
await fetchClientList()
|
await getClientList()
|
||||||
dialogVisible.value = false
|
dialogVisible.value = false
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error('客户表单验证失败', err)
|
console.error('客户表单验证失败', err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const resetForm = () => {
|
|
||||||
clientForm.value = {
|
|
||||||
//手续费模板
|
|
||||||
feeTemplate: '',
|
|
||||||
//风控模板
|
|
||||||
riskTemplate: '',
|
|
||||||
//所属上级
|
|
||||||
agentUsername: '',
|
|
||||||
email: '',
|
|
||||||
phone: '',
|
|
||||||
countryCode: '+86',
|
|
||||||
//是否升级
|
|
||||||
isUpgrade: 1,
|
|
||||||
//是否变更客户名
|
|
||||||
userName: '',
|
|
||||||
status: 1,
|
|
||||||
id: '',
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 弹窗取消
|
|
||||||
const handleCancel = () => {
|
const handleCancel = () => {
|
||||||
|
// 关闭弹窗
|
||||||
dialogVisible.value = false
|
dialogVisible.value = false
|
||||||
dialogType.value = 'add'
|
|
||||||
resetForm()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 弹窗关闭
|
|
||||||
const handleClose = () => {
|
const handleClose = () => {
|
||||||
|
// 关闭弹窗
|
||||||
dialogVisible.value = false
|
dialogVisible.value = false
|
||||||
dialogType.value = 'add'
|
|
||||||
resetForm()
|
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped lang="scss">
|
||||||
.phone-email {
|
.phone-email {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
flex: 1;
|
||||||
:deep(.el-form-item__content) {
|
|
||||||
flex-wrap: nowrap;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tab-btn {
|
.tab-btn {
|
||||||
display: flex;
|
display: flex;
|
||||||
margin-right: 10px;
|
margin-right: 10px;
|
||||||
|
|
||||||
.el-button {
|
.el-button {
|
||||||
margin-left: 0;
|
|
||||||
background-color: transparent;
|
|
||||||
border: 1px solid #DCDFE6;
|
|
||||||
color: #303133;
|
|
||||||
height: 32px;
|
height: 32px;
|
||||||
|
margin-left: 0;
|
||||||
}
|
|
||||||
|
|
||||||
.active {
|
|
||||||
background-color: #409EFF;
|
|
||||||
color: #fff;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.email-item {
|
.group {
|
||||||
.el-input {
|
display: flex;
|
||||||
width: 100%;
|
flex: 1;
|
||||||
}
|
|
||||||
|
.el-form-item {
|
||||||
|
flex: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
.phone-item {
|
.phone-item {
|
||||||
|
:deep(.el-form-item__content) {
|
||||||
|
flex-wrap: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
.el-select {
|
.el-select {
|
||||||
width: 120px;
|
width: 110px;
|
||||||
margin-right: 10px;
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -52,7 +52,7 @@ export const clientSearch = [
|
||||||
export const clientTableColumns = [
|
export const clientTableColumns = [
|
||||||
{ prop: 'id', label: 'ID', align: 'center' as const },
|
{ prop: 'id', label: 'ID', align: 'center' as const },
|
||||||
{ prop: 'username', label: '用户名', align: 'center' as const },
|
{ prop: 'username', label: '用户名', align: 'center' as const },
|
||||||
{ prop: 'created_at', label: '注册时间', align: 'center' as const },
|
{ prop: 'createdTime', label: '注册时间', align: 'center' as const },
|
||||||
{ prop: 'agentUsername', label: '所属代理', align: 'center' as const },
|
{ prop: 'agentUsername', label: '所属代理', align: 'center' as const },
|
||||||
{ label: '状态', slotName: 'status', align: 'center' as const },
|
{ label: '状态', slotName: 'status', align: 'center' as const },
|
||||||
{ label: '操作', slotName: 'action', align: 'center' as const }
|
{ label: '操作', slotName: 'action', align: 'center' as const }
|
||||||
|
|
@ -62,10 +62,10 @@ export const clientTableColumns = [
|
||||||
export const clientAddFormItem = [
|
export const clientAddFormItem = [
|
||||||
// { prop: 'clientName', label: '客户名称', type: 'input' as const, placeholder: '客户名称' },
|
// { prop: 'clientName', label: '客户名称', type: 'input' as const, placeholder: '客户名称' },
|
||||||
// { prop: 'isUpgrade', label: '是否升级为代理', type: 'radio' as const, placeholder: '是否升级为代理' },
|
// { prop: 'isUpgrade', label: '是否升级为代理', type: 'radio' as const, placeholder: '是否升级为代理' },
|
||||||
|
{ prop: 'phoneOrEmail', label: '', type: 'slot' as const, slotName: 'phoneOrEmail' },
|
||||||
{ prop: 'feeTemplate', label: '手续费模板', type: 'select' as const, placeholder: '选择手续费模板' },
|
{ prop: 'feeTemplate', label: '手续费模板', type: 'select' as const, placeholder: '选择手续费模板' },
|
||||||
{ prop: 'riskTemplate', label: '风控模板', type: 'select' as const, placeholder: '选择风控模板' },
|
{ prop: 'riskTemplate', label: '风控模板', type: 'select' as const, placeholder: '选择风控模板' },
|
||||||
{ prop: 'agentUsername', label: '所属上级', type: 'select' as const, placeholder: '所属上级' },
|
{ prop: 'agentUsername', label: '所属上级', type: 'select' as const, placeholder: '所属上级' },
|
||||||
{ prop: 'phoneOrEmail', label: '', type: 'slot' as const, slotName: 'phoneOrEmail' },
|
|
||||||
]
|
]
|
||||||
|
|
||||||
//定义修改客户form配置
|
//定义修改客户form配置
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,398 @@
|
||||||
|
<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>
|
||||||
|
|
@ -88,6 +88,22 @@ const loginRules = ref<FormRules>({
|
||||||
|
|
||||||
//方法
|
//方法
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 生成时间戳拼接6位随机数字的字符串
|
||||||
|
* @returns {string} 格式示例:1710688800000123456
|
||||||
|
*/
|
||||||
|
function generateTimestampWithRandomNum() {
|
||||||
|
// 1. 获取当前时间戳(毫秒级)
|
||||||
|
const timestamp = Date.now();
|
||||||
|
|
||||||
|
// 2. 生成6位随机数字(范围:000000 ~ 999999)
|
||||||
|
// Math.random()生成0~1的随机数,乘以1000000后取整,不足6位补0
|
||||||
|
const random6Num = Math.floor(Math.random() * 1000000).toString().padStart(6, '0');
|
||||||
|
|
||||||
|
// 3. 拼接并返回
|
||||||
|
return timestamp + random6Num;
|
||||||
|
}
|
||||||
|
|
||||||
// 登录
|
// 登录
|
||||||
const handleLogin = async () => {
|
const handleLogin = async () => {
|
||||||
if (!loginFormRef.value) return;
|
if (!loginFormRef.value) return;
|
||||||
|
|
@ -120,15 +136,19 @@ const handleLogin = async () => {
|
||||||
else if (currentTab === 'password') {
|
else if (currentTab === 'password') {
|
||||||
// 校验密码+验证码
|
// 校验密码+验证码
|
||||||
await loginFormRef.value.validateField(['password', 'code']);
|
await loginFormRef.value.validateField(['password', 'code']);
|
||||||
|
// 生成device_no并保存到变量(关键修改1)
|
||||||
|
const deviceNo = generateTimestampWithRandomNum();
|
||||||
// 登录参数
|
// 登录参数
|
||||||
const loginParams = {
|
const loginParams = {
|
||||||
email: loginForm.value.email,
|
email: loginForm.value.email,
|
||||||
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: loginForm.value.password
|
password: loginForm.value.password,
|
||||||
|
device_no: deviceNo
|
||||||
};
|
};
|
||||||
await userStore.login(loginParams);
|
await userStore.login(loginParams);
|
||||||
|
setStorage('device_no', deviceNo);
|
||||||
activeTab.value = 'email'; // 重置tab
|
activeTab.value = 'email'; // 重置tab
|
||||||
hideTab.value = false;
|
hideTab.value = false;
|
||||||
loginForm.value = { // 清空表单
|
loginForm.value = { // 清空表单
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue