Files
lab/frontend/src/views/UserView.vue
2026-09-21 12:51:08 +08:00

171 lines
5.5 KiB
Vue

<template>
<el-card>
<div class="toolbar">
<div class="spacer" />
<el-button type="success" @click="openDialog()">
<el-icon><Plus /></el-icon>&nbsp;新增用户
</el-button>
</div>
<el-table :data="rows" v-loading="loading">
<el-table-column prop="id" label="ID" width="70" />
<el-table-column prop="username" label="用户名" width="140" />
<el-table-column prop="realName" label="姓名" width="120" />
<el-table-column prop="roleLabel" label="角色" width="100">
<template #default="{ row }">
<el-tag :type="row.role === 'ADMIN' ? 'danger' : row.role === 'TEACHER' ? 'warning' : 'info'">
{{ row.roleLabel }}
</el-tag>
</template>
</el-table-column>
<el-table-column prop="email" label="邮箱" min-width="180" />
<el-table-column prop="phone" label="电话" width="140" />
<el-table-column label="状态" width="90" align="center">
<template #default="{ row }">
<el-tag :type="row.enabled ? 'success' : 'info'">{{ row.enabled ? '启用' : '禁用' }}</el-tag>
</template>
</el-table-column>
<el-table-column label="操作" width="170" fixed="right">
<template #default="{ row }">
<el-button size="small" @click="openDialog(row)">编辑</el-button>
<el-button size="small" type="danger" @click="remove(row)">删除</el-button>
</template>
</el-table-column>
</el-table>
<el-dialog v-model="dialogVisible" :title="form.id ? '编辑用户' : '新增用户'" width="480px">
<el-form ref="formRef" :model="form" :rules="rules" label-width="90px">
<el-form-item label="用户名" prop="username">
<el-input v-model="form.username" :disabled="Boolean(form.id)" />
</el-form-item>
<el-form-item v-if="!form.id" label="初始密码" prop="password">
<el-input v-model="form.password" type="password" show-password />
</el-form-item>
<el-form-item v-else label="重置密码">
<el-input v-model="form.password" type="password" show-password placeholder="留空则不修改" />
</el-form-item>
<el-form-item label="姓名" prop="realName">
<el-input v-model="form.realName" />
</el-form-item>
<el-form-item label="角色" prop="role">
<el-select v-model="form.role">
<el-option label="管理员" value="ADMIN" />
<el-option label="教师" value="TEACHER" />
<el-option label="学生" value="STUDENT" />
</el-select>
</el-form-item>
<el-form-item label="邮箱">
<el-input v-model="form.email" />
</el-form-item>
<el-form-item label="电话">
<el-input v-model="form.phone" />
</el-form-item>
<el-form-item v-if="form.id" label="启用">
<el-switch v-model="form.enabled" />
</el-form-item>
</el-form>
<template #footer>
<el-button @click="dialogVisible = false">取消</el-button>
<el-button type="primary" @click="submit">保存</el-button>
</template>
</el-dialog>
</el-card>
</template>
<script setup lang="ts">
import { onMounted, reactive, ref } from 'vue'
import { ElMessage, ElMessageBox, type FormInstance, type FormRules } from 'element-plus'
import { userApi } from '@/api'
import type { Role, UserVO } from '@/types'
interface UserForm {
id?: number
username?: string
password?: string
realName?: string
role?: Role
email?: string
phone?: string
enabled?: boolean
}
const loading = ref(false)
const rows = ref<UserVO[]>([])
const dialogVisible = ref(false)
const formRef = ref<FormInstance>()
const form = reactive<UserForm>({ role: 'STUDENT', enabled: true })
/** 表单校验规则 */
const rules: FormRules = {
username: [{ required: true, message: '请输入用户名', trigger: 'blur' }],
password: [{ required: true, message: '请输入密码', trigger: 'blur' }],
realName: [{ required: true, message: '请输入姓名', trigger: 'blur' }],
role: [{ required: true, message: '请选择角色', trigger: 'change' }]
}
/**
* 加载用户列表。
*/
async function load(): Promise<void> {
loading.value = true
try {
rows.value = await userApi.list()
} finally {
loading.value = false
}
}
/**
* 打开新增/编辑对话框。
*
* @param row 行数据
*/
function openDialog(row?: UserVO): void {
Object.keys(form).forEach((key) => delete (form as Record<string, unknown>)[key])
if (row) {
Object.assign(form, row, { password: '' })
} else {
Object.assign(form, { role: 'STUDENT', enabled: true })
}
dialogVisible.value = true
}
/**
* 保存用户。
*/
async function submit(): Promise<void> {
const valid = await formRef.value?.validate().catch(() => false)
if (!valid) {
return
}
if (form.id) {
const payload: Record<string, unknown> = { ...form }
delete payload.username
if (!payload.password) {
delete payload.password
}
await userApi.update(form.id, payload)
ElMessage.success('修改成功')
} else {
await userApi.create(form as Record<string, unknown>)
ElMessage.success('新增成功')
}
dialogVisible.value = false
await load()
}
/**
* 删除用户。
*
* @param row 行数据
*/
async function remove(row: UserVO): Promise<void> {
await ElMessageBox.confirm(`确认删除用户「${row.realName}」吗?`, '提示', { type: 'warning' })
await userApi.remove(row.id)
ElMessage.success('删除成功')
await load()
}
onMounted(load)
</script>