by-crm/frontend/src/views/Dealer.vue
2026-01-27 18:03:26 +08:00

387 lines
12 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="dealer-page">
<el-card>
<template #header>
<div class="card-header">
<span>经销商管理</span>
<el-button type="primary" @click="handleAdd">
<el-icon><Plus /></el-icon>
新增经销商
</el-button>
</div>
</template>
<!-- 查询表单 -->
<el-form :inline="true" :model="queryForm" class="query-form">
<el-form-item label="经销商名称">
<el-input v-model="queryForm.name" placeholder="请输入经销商名称" clearable />
</el-form-item>
<el-form-item label="经销商账号">
<el-input v-model="queryForm.code" placeholder="请输入经销商账号" clearable />
</el-form-item>
<el-form-item label="状态" style="width: 180px;">
<el-select v-model="queryForm.status" placeholder="请选择状态" clearable>
<el-option label="启用" :value="1" />
<el-option label="禁用" :value="0" />
</el-select>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="handleQuery">
<el-icon><Search /></el-icon>
查询
</el-button>
<el-button @click="handleReset">重置</el-button>
</el-form-item>
</el-form>
<!-- 数据表格 -->
<el-table :data="tableData" border stripe v-loading="loading">
<el-table-column prop="name" label="经销商名称" />
<el-table-column prop="code" label="经销商账号" />
<el-table-column prop="contactPerson" label="联系人" />
<el-table-column prop="contactPhone" label="联系电话" />
<el-table-column prop="email" label="邮箱" />
<el-table-column prop="status" label="状态">
<template #default="{ row }">
<el-tag :type="row.status === 1 ? 'success' : 'danger'">
{{ row.status === 1 ? '启用' : '禁用' }}
</el-tag>
</template>
</el-table-column>
<el-table-column prop="createdAt" label="创建时间" width="180" />
<el-table-column label="操作" width="240" fixed="right">
<template #default="{ row }">
<el-button link type="primary" @click="handleEdit(row)">编辑</el-button>
<el-button link type="warning" @click="handleResetPassword(row)">重置密码</el-button>
<el-button link type="danger" @click="handleDelete(row)">删除</el-button>
</template>
</el-table-column>
</el-table>
</el-card>
<!-- 新增/编辑对话框 -->
<el-dialog
v-model="dialogVisible"
:title="dialogTitle"
width="600px"
@close="handleDialogClose"
>
<el-form ref="formRef" :model="formData" :rules="rules" label-width="100px">
<el-form-item label="经销商名称" prop="name">
<el-input v-model="formData.name" placeholder="请输入经销商名称" />
</el-form-item>
<el-form-item label="经销商账号" prop="code">
<el-input v-model="formData.code" placeholder="请输入经销商账号" />
</el-form-item>
<el-form-item label="联系人" prop="contactPerson">
<el-input v-model="formData.contactPerson" placeholder="请输入联系人" />
</el-form-item>
<el-form-item label="联系电话" prop="contactPhone">
<el-input v-model="formData.contactPhone" placeholder="请输入联系电话" />
</el-form-item>
<el-form-item label="邮箱" prop="email">
<el-input v-model="formData.email" placeholder="请输入邮箱" />
</el-form-item>
<el-form-item label="状态" prop="status">
<el-radio-group v-model="formData.status">
<el-radio :label="1">启用</el-radio>
<el-radio :label="0">禁用</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="初始密码" prop="password" v-if="!formData.id">
<el-input
v-model="formData.password"
type="password"
placeholder="请输入初始密码不填默认为a123456"
show-password
/>
<div style="color: #909399; font-size: 12px; margin-top: 4px">
长度6-20位不填则默认密码为 a123456
</div>
</el-form-item>
</el-form>
<template #footer>
<el-button @click="dialogVisible = false">取消</el-button>
<el-button type="primary" @click="handleSubmit">确定</el-button>
</template>
</el-dialog>
<!-- 重置密码对话框 -->
<el-dialog
v-model="resetPasswordDialogVisible"
title="重置密码"
width="500px"
@close="handleResetPasswordDialogClose"
>
<el-form ref="resetPasswordFormRef" :model="resetPasswordForm" :rules="resetPasswordRules" label-width="100px">
<el-form-item label="经销商名称">
<el-input v-model="resetPasswordForm.dealerName" disabled />
</el-form-item>
<el-form-item label="新密码" prop="newPassword">
<el-input
v-model="resetPasswordForm.newPassword"
type="password"
placeholder="请输入新密码6-20位"
show-password
/>
</el-form-item>
<el-form-item label="确认密码" prop="confirmPassword">
<el-input
v-model="resetPasswordForm.confirmPassword"
type="password"
placeholder="请再次输入新密码"
show-password
/>
</el-form-item>
</el-form>
<template #footer>
<el-button @click="resetPasswordDialogVisible = false">取消</el-button>
<el-button type="primary" @click="handleResetPasswordSubmit">确定</el-button>
</template>
</el-dialog>
</div>
</template>
<script setup lang="ts">
import { ref, reactive, onMounted, computed } from 'vue'
import { ElMessage, ElMessageBox, type FormInstance, type FormRules } from 'element-plus'
import { getDealerList, createDealer, updateDealer, deleteDealer } from '@/api/dealer'
import { resetPassword } from '@/api/auth'
import { hashPassword } from '@/utils/crypto'
import type { Dealer } from '@/types'
const loading = ref(false)
const tableData = ref<Dealer[]>([])
const dialogVisible = ref(false)
const resetPasswordDialogVisible = ref(false)
const dialogTitle = computed(() => (formData.id ? '编辑经销商' : '新增经销商'))
const formRef = ref<FormInstance>()
const resetPasswordFormRef = ref<FormInstance>()
const queryForm = reactive({
name: '',
code: '',
status: undefined as number | undefined
})
const formData = reactive<Partial<Dealer> & { id?: number; password?: string }>({
name: '',
code: '',
contactPerson: '',
contactPhone: '',
email: '',
status: 1,
password: ''
})
const rules: FormRules = {
name: [{ required: true, message: '请输入经销商名称', trigger: 'blur' }],
code: [{ required: true, message: '请输入经销商账号', trigger: 'blur' }],
contactPerson: [{ required: true, message: '请输入联系人', trigger: 'blur' }],
contactPhone: [{ required: true, message: '请输入联系电话', trigger: 'blur' }],
password: [
{
validator: (_rule, value, callback) => {
// 密码可选,如果填写则校验长度
if (value && (value.length < 6 || value.length > 20)) {
callback(new Error('密码长度必须在6-20位之间'))
} else {
callback()
}
},
trigger: 'blur'
}
]
}
// 重置密码表单
const resetPasswordForm = reactive({
userId: 0,
dealerName: '',
newPassword: '',
confirmPassword: ''
})
const resetPasswordRules: FormRules = {
newPassword: [
{ required: true, message: '请输入新密码', trigger: 'blur' },
{ min: 6, max: 20, message: '新密码长度必须在6-20位之间', trigger: 'blur' }
],
confirmPassword: [
{ required: true, message: '请再次输入新密码', trigger: 'blur' },
{
validator: (_rule, value, callback) => {
if (value !== resetPasswordForm.newPassword) {
callback(new Error('两次输入的密码不一致'))
} else {
callback()
}
},
trigger: 'blur'
}
]
}
// 查询数据
const fetchData = async () => {
loading.value = true
try {
const res = await getDealerList(queryForm)
tableData.value = res
} catch (error) {
console.error('查询失败', error)
} finally {
loading.value = false
}
}
// 查询按钮
const handleQuery = () => {
fetchData()
}
// 重置按钮
const handleReset = () => {
queryForm.name = ''
queryForm.code = ''
queryForm.status = undefined
fetchData()
}
// 新增按钮
const handleAdd = () => {
dialogVisible.value = true
}
// 编辑按钮
const handleEdit = (row: Dealer) => {
Object.assign(formData, row)
dialogVisible.value = true
}
// 删除按钮
const handleDelete = async (row: Dealer) => {
try {
await ElMessageBox.confirm(
'确定要删除该经销商吗?',
'提示',
{
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}
)
await deleteDealer(row.id)
ElMessage.success('删除成功')
fetchData()
} catch (error) {
// 取消删除
}
}
// 提交表单
const handleSubmit = async () => {
if (!formRef.value) return
await formRef.value.validate(async (valid) => {
if (valid) {
try {
if (formData.id) {
await updateDealer(formData.id, formData)
ElMessage.success('更新成功')
} else {
// 处理密码:如果未填写则使用默认密码 a123456并进行加密
const submitData = { ...formData }
if (!submitData.password || submitData.password.trim() === '') {
submitData.password = 'a123456'
}
// 对密码进行 SHA-256 哈希后再传输
submitData.password = await hashPassword(submitData.password)
await createDealer(submitData)
ElMessage.success('创建成功')
}
dialogVisible.value = false
fetchData()
} catch (error) {
console.error('提交失败', error)
}
}
})
}
// 重置密码按钮
const handleResetPassword = (row: Dealer) => {
resetPasswordForm.userId = row.userId
resetPasswordForm.dealerName = row.name
resetPasswordDialogVisible.value = true
}
// 提交重置密码
const handleResetPasswordSubmit = async () => {
if (!resetPasswordFormRef.value) return
await resetPasswordFormRef.value.validate(async (valid) => {
if (valid) {
try {
// 对密码进行 SHA-256 哈希后再传输
const hashedPassword = await hashPassword(resetPasswordForm.newPassword)
await resetPassword({
userId: resetPasswordForm.userId,
newPassword: hashedPassword
})
ElMessage.success('密码重置成功')
resetPasswordDialogVisible.value = false
} catch (error) {
console.error('重置密码失败', error)
}
}
})
}
// 重置密码对话框关闭
const handleResetPasswordDialogClose = () => {
resetPasswordFormRef.value?.resetFields()
Object.assign(resetPasswordForm, {
userId: 0,
dealerName: '',
newPassword: '',
confirmPassword: ''
})
}
// 对话框关闭
const handleDialogClose = () => {
formRef.value?.resetFields()
Object.assign(formData, {
name: '',
code: '',
contactPerson: '',
contactPhone: '',
email: '',
status: 1,
password: ''
})
delete formData.id
}
onMounted(() => {
fetchData()
})
</script>
<style scoped>
.dealer-page {
width: 100%;
}
.card-header {
display: flex;
justify-content: space-between;
align-items: center;
}
.query-form {
margin-bottom: 20px;
}
</style>