First commit
This commit is contained in:
170
frontend/src/views/UserView.vue
Normal file
170
frontend/src/views/UserView.vue
Normal file
@@ -0,0 +1,170 @@
|
||||
<template>
|
||||
<el-card>
|
||||
<div class="toolbar">
|
||||
<div class="spacer" />
|
||||
<el-button type="success" @click="openDialog()">
|
||||
<el-icon><Plus /></el-icon> 新增用户
|
||||
</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>
|
||||
Reference in New Issue
Block a user