384 lines
11 KiB
Vue
384 lines
11 KiB
Vue
<template>
|
||
<div class="employee-add">
|
||
<el-card>
|
||
<template>
|
||
<div class="card-header">
|
||
<span>添加代理</span>
|
||
<el-button @click="$router.push('/admin/employees')">
|
||
<el-icon>
|
||
<Back />
|
||
</el-icon>返回列表
|
||
</el-button>
|
||
</div>
|
||
</template>
|
||
|
||
<el-steps :active="activeStep" finish-status="success" simple class="steps">
|
||
<el-step title="填写信息" />
|
||
<el-step title="确认信息" />
|
||
<el-step title="完成" />
|
||
</el-steps>
|
||
|
||
<!-- 第一步:填写信息 -->
|
||
<div v-if="activeStep === 1" class="step-content">
|
||
<el-form ref="formRef" :model="form" :rules="rules" label-width="100px" class="add-form">
|
||
<el-form-item label="姓名" prop="name">
|
||
<el-input v-model="form.name" placeholder="请输入代理姓名" :prefix-icon="User" clearable />
|
||
</el-form-item>
|
||
|
||
<el-form-item label="密码" prop="password">
|
||
<el-input v-model="form.password" type="password" placeholder="请输入密码(至少6位)" :prefix-icon="Lock"
|
||
show-password clearable />
|
||
</el-form-item>
|
||
|
||
<el-form-item label="确认密码" prop="confirmPassword">
|
||
<el-input v-model="form.confirmPassword" type="password" placeholder="请再次输入密码" :prefix-icon="Lock"
|
||
show-password clearable />
|
||
</el-form-item>
|
||
|
||
<el-form-item label="手机号" prop="phone">
|
||
<el-input v-model="form.phone" placeholder="请输入手机号" :prefix-icon="Lock" maxlength="11" clearable
|
||
show-word-limit />
|
||
</el-form-item>
|
||
<el-form-item>
|
||
<el-button type="primary" @click="nextStep" :loading="checking">
|
||
下一步,确认信息
|
||
</el-button>
|
||
</el-form-item>
|
||
</el-form>
|
||
|
||
<!-- 工号预览(动态生成) -->
|
||
<el-card shadow="never" class="preview-card">
|
||
<template #header>
|
||
<span>工号预览</span>
|
||
</template>
|
||
<div class="preview-content">
|
||
<div class="preview-item">
|
||
<span class="label">工号格式:</span>
|
||
<span class="value">5位数字,自动生成</span>
|
||
</div>
|
||
<div class="preview-item">
|
||
<span class="label">账号格式:</span>
|
||
<span class="value">dl_ + 工号(如 dl_00001)</span>
|
||
</div>
|
||
<div class="preview-item">
|
||
<span class="label">示例工号:</span>
|
||
<el-tag size="small">{{ previewEmployeeId }}</el-tag>
|
||
</div>
|
||
<div class="preview-item">
|
||
<span class="label">示例账号:</span>
|
||
<el-tag size="small" type="success">{{ previewUsername }}</el-tag>
|
||
</div>
|
||
</div>
|
||
</el-card>
|
||
</div>
|
||
|
||
<!-- 第二步:确认信息 -->
|
||
<div v-if="activeStep === 2" class="step-content">
|
||
<el-descriptions :column="1" border class="confirm-info">
|
||
<el-descriptions-item label="姓名">{{ form.name }}</el-descriptions-item>
|
||
<el-descriptions-item label="工号">{{ previewEmployeeId }}</el-descriptions-item>
|
||
<el-descriptions-item label="登录账号">{{ previewUsername }}</el-descriptions-item>
|
||
<el-descriptions-item label="手机号">{{ form.phone }}</el-descriptions-item>
|
||
<el-descriptions-item label="初始积分">0</el-descriptions-item>
|
||
<el-descriptions-item label="角色">代理</el-descriptions-item>
|
||
<el-descriptions-item label="状态">正常</el-descriptions-item>
|
||
</el-descriptions>
|
||
|
||
<div class="step-actions">
|
||
<el-button @click="prevStep">上一步</el-button>
|
||
<el-button type="primary" @click="submitForm" :loading="submitting">
|
||
确认添加
|
||
</el-button>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 第三步:完成 -->
|
||
<div v-if="activeStep === 3" class="step-content result">
|
||
<el-result icon="success" :title="`添加成功`" :sub-title="`代理 ${resultData?.name} (${resultData?.username}) 已添加`">
|
||
<template #extra>
|
||
<div class="result-info" ref="resultInfoRef">
|
||
<el-alert type="info" :closable="false" show-icon>
|
||
<p class="title-center">进销存系统</p>
|
||
<p>登录网址:https://psi.buzhiyushu.cn/</p>
|
||
<p>工号:{{ resultData?.employee_id }}</p>
|
||
<p>账号:{{ resultData?.username }}</p>
|
||
<p>初始密码:{{ form.password }}</p>
|
||
<p>手机号:{{ form.phone }}</p>
|
||
<p style="color: #f56c6c; margin-top: 10px;">请妥善保管账号信息!</p>
|
||
</el-alert>
|
||
</div>
|
||
<div class="result-actions">
|
||
<el-button type="primary" @click="resetForm">继续添加</el-button>
|
||
<el-button @click="$router.push('/admin/employees')">查看列表</el-button>
|
||
<el-button type="success" @click="copyResultInfo">
|
||
<el-icon>
|
||
<DocumentCopy />
|
||
</el-icon>
|
||
一键复制
|
||
</el-button>
|
||
</div>
|
||
</template>
|
||
</el-result>
|
||
</div>
|
||
</el-card>
|
||
</div>
|
||
</template>
|
||
|
||
<script setup>
|
||
import { ref, reactive, computed, onMounted } from 'vue'
|
||
import { useRouter } from 'vue-router'
|
||
import { ElMessage } from 'element-plus'
|
||
import { User, Lock, Back, DocumentCopy } from '@element-plus/icons-vue'
|
||
import request from '@/utils/request'
|
||
import { copyToClipboard } from '@/utils/clipboard'
|
||
import { useUserStore } from '@/store/user'
|
||
|
||
const router = useRouter()
|
||
const userStore = useUserStore()
|
||
const activeStep = ref(1)
|
||
const checking = ref(false)
|
||
const submitting = ref(false)
|
||
const formRef = ref(null)
|
||
const resultData = ref(null)
|
||
const resultInfoRef = ref(null)
|
||
|
||
// 表单数据
|
||
const form = reactive({
|
||
name: '',
|
||
password: '',
|
||
confirmPassword: '',
|
||
phone: ''
|
||
})
|
||
|
||
// 表单验证规则
|
||
const validatePass = (rule, value, callback) => {
|
||
if (value === '') {
|
||
callback(new Error('请输入密码'))
|
||
} else if (value.length < 6) {
|
||
callback(new Error('密码长度不能小于6位'))
|
||
} else {
|
||
if (form.confirmPassword !== '') {
|
||
formRef.value?.validateField('confirmPassword')
|
||
}
|
||
callback()
|
||
}
|
||
}
|
||
|
||
const validatePass2 = (rule, value, callback) => {
|
||
if (value === '') {
|
||
callback(new Error('请再次输入密码'))
|
||
} else if (value !== form.password) {
|
||
callback(new Error('两次输入密码不一致'))
|
||
} else {
|
||
callback()
|
||
}
|
||
}
|
||
|
||
const rules = {
|
||
name: [
|
||
{ required: true, message: '请输入代理姓名', trigger: 'blur' },
|
||
{ min: 2, max: 20, message: '姓名长度应为2-20个字符', trigger: 'blur' }
|
||
],
|
||
password: [
|
||
{ validator: validatePass, trigger: 'blur' }
|
||
],
|
||
confirmPassword: [
|
||
{ validator: validatePass2, trigger: 'blur' }
|
||
],
|
||
phone: [
|
||
{ required: true, message: '请输入手机号', trigger: 'blur' },
|
||
{ pattern: /^1[3-9]\d{9}$/, message: '请输入正确的手机号', trigger: 'blur' }
|
||
]
|
||
}
|
||
|
||
// 预览工号和账号(模拟)
|
||
const previewEmployeeId = ref('00001')
|
||
const previewUsername = computed(() => `dl_${previewEmployeeId.value}`)
|
||
|
||
// 获取下一个可用工号
|
||
const fetchNextEmployeeId = async () => {
|
||
try {
|
||
// 这里可以调用接口获取下一个工号
|
||
// 如果没有接口,使用模拟数据
|
||
const res = await request.get('/admin/employee/list', { params: { page: 1, page_size: 1 } })
|
||
if (res.code === 200 && res.data.list.length > 0) {
|
||
const lastId = res.data.list[0].employee_id
|
||
const seq = parseInt(lastId) + 1
|
||
previewEmployeeId.value = String(seq).padStart(5, '0')
|
||
}
|
||
} catch (error) {
|
||
// console.error('获取工号失败:', error)
|
||
// 使用模拟数据
|
||
previewEmployeeId.value = String(Math.floor(Math.random() * 90000 + 10000)).padStart(5, '0')
|
||
}
|
||
}
|
||
|
||
// 下一步
|
||
const nextStep = async () => {
|
||
if (!formRef.value) return
|
||
|
||
await formRef.value.validate()
|
||
activeStep.value = 2
|
||
}
|
||
|
||
// 上一步
|
||
const prevStep = () => {
|
||
activeStep.value = 1
|
||
}
|
||
|
||
// 提交表单
|
||
const submitForm = async () => {
|
||
submitting.value = true
|
||
try {
|
||
// 动态构建请求参数,fid 来自 login 响应的 id,about_id 来自 login 响应的 about_id
|
||
const currentInfo = userStore.getAdminInfo()
|
||
const params = {
|
||
name: form.name,
|
||
password: form.password,
|
||
phone: form.phone,
|
||
}
|
||
if (currentInfo?.id) {
|
||
params.fid = currentInfo.id
|
||
}
|
||
if (currentInfo?.about_id) {
|
||
params.about_id = currentInfo.about_id
|
||
}
|
||
const res = await request.post('/admin/employee/add', params)
|
||
|
||
if (res.code === 200) {
|
||
resultData.value = res.data
|
||
activeStep.value = 3
|
||
ElMessage.success('添加成功')
|
||
}
|
||
} catch (error) {
|
||
// console.error('添加代理失败:', error)
|
||
ElMessage.error('添加失败,请重试')
|
||
} finally {
|
||
submitting.value = false
|
||
}
|
||
}
|
||
|
||
// 重置表单
|
||
const resetForm = () => {
|
||
form.name = ''
|
||
form.password = ''
|
||
form.confirmPassword = ''
|
||
form.phone = ''
|
||
activeStep.value = 1
|
||
resultData.value = null
|
||
fetchNextEmployeeId()
|
||
}
|
||
// 一键复制结果信息
|
||
const copyResultInfo = async () => {
|
||
if (!resultData.value) return
|
||
|
||
const text = `书海寻源代理系统
|
||
登录网址:https://wallet.buzhiyushu.cn/
|
||
工号:${resultData.value.employee_id}
|
||
账号:${resultData.value.username}
|
||
初始密码:${form.password}
|
||
手机号:${form.phone}
|
||
|
||
请妥善保管账号信息!`
|
||
|
||
await copyToClipboard(text, '账号信息已复制到剪贴板')
|
||
}
|
||
// 初始化
|
||
onMounted(() => {
|
||
fetchNextEmployeeId()
|
||
})
|
||
</script>
|
||
|
||
<style scoped>
|
||
.employee-add {
|
||
padding: 0;
|
||
}
|
||
|
||
.card-header {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
font-size: 16px;
|
||
font-weight: 600;
|
||
color: #303133;
|
||
}
|
||
|
||
.steps {
|
||
margin: 20px 0 40px;
|
||
}
|
||
|
||
.step-content {
|
||
min-height: 300px;
|
||
padding: 20px 0;
|
||
}
|
||
|
||
.add-form {
|
||
width: 500px;
|
||
margin: 0 auto;
|
||
}
|
||
|
||
.preview-card {
|
||
width: 500px;
|
||
margin: 30px auto 0;
|
||
background-color: #f8f9fa;
|
||
}
|
||
|
||
.preview-content {
|
||
padding: 10px;
|
||
}
|
||
|
||
.preview-item {
|
||
margin-bottom: 10px;
|
||
display: flex;
|
||
align-items: center;
|
||
}
|
||
|
||
.preview-item .label {
|
||
width: 80px;
|
||
color: #666;
|
||
font-size: 13px;
|
||
}
|
||
|
||
.preview-item .value {
|
||
color: #333;
|
||
font-size: 13px;
|
||
}
|
||
|
||
.confirm-info {
|
||
width: 500px;
|
||
margin: 0 auto;
|
||
}
|
||
|
||
.step-actions {
|
||
margin-top: 30px;
|
||
text-align: center;
|
||
}
|
||
|
||
.result {
|
||
display: flex;
|
||
justify-content: center;
|
||
}
|
||
|
||
.result-info {
|
||
margin: 20px 0;
|
||
text-align: left;
|
||
}
|
||
|
||
.result-actions {
|
||
margin-top: 20px;
|
||
display: flex;
|
||
gap: 10px;
|
||
justify-content: center;
|
||
}
|
||
|
||
:deep(.el-descriptions__label) {
|
||
width: 120px;
|
||
}
|
||
|
||
.title-center {
|
||
text-align: center;
|
||
font-weight: bold;
|
||
font-size: 16px;
|
||
margin-bottom: 10px;
|
||
}
|
||
</style> |