2026-08-28 15:06:01 +08:00
|
|
|
|
<template>
|
|
|
|
|
|
<el-card>
|
|
|
|
|
|
<el-tabs v-model="tab">
|
|
|
|
|
|
<!-- 用户 -->
|
|
|
|
|
|
<el-tab-pane label="用户" name="users">
|
|
|
|
|
|
<div style="margin-bottom:10px">
|
|
|
|
|
|
<el-button type="primary" @click="openUser()">新增用户</el-button>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<el-table :data="users" border size="small">
|
|
|
|
|
|
<el-table-column prop="id" label="ID" width="60" />
|
|
|
|
|
|
<el-table-column prop="username" label="用户名" min-width="120" />
|
|
|
|
|
|
<el-table-column prop="name" label="姓名" min-width="110" />
|
|
|
|
|
|
<el-table-column prop="roleId" label="角色ID" width="80" />
|
|
|
|
|
|
<el-table-column prop="status" label="状态" width="90" />
|
|
|
|
|
|
<el-table-column label="操作" width="140">
|
|
|
|
|
|
<template #default="{row}">
|
|
|
|
|
|
<el-button size="small" @click="openUser(row)">编辑</el-button>
|
|
|
|
|
|
<el-button size="small" type="danger" @click="delUser(row)">删除</el-button>
|
|
|
|
|
|
</template>
|
|
|
|
|
|
</el-table-column>
|
|
|
|
|
|
</el-table>
|
|
|
|
|
|
</el-tab-pane>
|
|
|
|
|
|
|
2026-08-29 15:30:25 +08:00
|
|
|
|
<!-- 角色(只读,不允许新增/编辑/删除) -->
|
2026-08-28 15:06:01 +08:00
|
|
|
|
<el-tab-pane label="角色" name="roles">
|
2026-08-29 15:30:25 +08:00
|
|
|
|
<p class="tip">角色为系统预置,只读查看。</p>
|
2026-08-28 15:06:01 +08:00
|
|
|
|
<el-table :data="roles" border size="small">
|
|
|
|
|
|
<el-table-column prop="id" label="ID" width="60" />
|
|
|
|
|
|
<el-table-column prop="name" label="名称" min-width="120" />
|
|
|
|
|
|
<el-table-column prop="code" label="编码" min-width="130" />
|
|
|
|
|
|
<el-table-column prop="remark" label="备注" min-width="150" />
|
2026-08-29 15:30:25 +08:00
|
|
|
|
<el-table-column prop="permissionCodes" label="权限" min-width="200">
|
|
|
|
|
|
<template #default="{row}">{{ (row.permissionCodes||[]).join(', ') || '-' }}</template>
|
2026-08-28 15:06:01 +08:00
|
|
|
|
</el-table-column>
|
|
|
|
|
|
</el-table>
|
|
|
|
|
|
</el-tab-pane>
|
|
|
|
|
|
|
2026-08-29 15:30:25 +08:00
|
|
|
|
<!-- 权限菜单(只读,不允许新增/编辑/删除) -->
|
2026-08-28 15:06:01 +08:00
|
|
|
|
<el-tab-pane label="权限菜单" name="perms">
|
2026-08-29 15:30:25 +08:00
|
|
|
|
<p class="tip">权限菜单为系统预置,只读查看。</p>
|
2026-08-28 15:06:01 +08:00
|
|
|
|
<el-table :data="perms" border size="small">
|
|
|
|
|
|
<el-table-column prop="id" label="ID" width="60" />
|
|
|
|
|
|
<el-table-column prop="code" label="编码" min-width="150" />
|
|
|
|
|
|
<el-table-column prop="name" label="名称" min-width="120" />
|
|
|
|
|
|
<el-table-column prop="type" label="类型" width="80" />
|
|
|
|
|
|
<el-table-column prop="path" label="路径" min-width="120" />
|
|
|
|
|
|
<el-table-column prop="sort" label="排序" width="70" />
|
|
|
|
|
|
</el-table>
|
|
|
|
|
|
</el-tab-pane>
|
|
|
|
|
|
</el-tabs>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 用户编辑 -->
|
|
|
|
|
|
<el-dialog v-model="u.show" :title="u.id?'编辑用户':'新增用户'" width="420px">
|
|
|
|
|
|
<el-form :model="u" label-width="80px">
|
2026-08-29 15:30:25 +08:00
|
|
|
|
<el-form-item label="用户名"><el-input v-model="u.username" :disabled="u.id===1" /></el-form-item>
|
|
|
|
|
|
<el-form-item v-if="!u.id" label="密码"><el-input v-model="u.password" type="password" show-password placeholder="至少6位,不能纯数字" /></el-form-item>
|
|
|
|
|
|
<el-form-item v-else label="重置密码"><el-input v-model="u.password" type="password" show-password placeholder="留空则不修改;至少6位,不能纯数字" /></el-form-item>
|
2026-08-28 15:06:01 +08:00
|
|
|
|
<el-form-item label="姓名"><el-input v-model="u.name" /></el-form-item>
|
|
|
|
|
|
<el-form-item label="角色">
|
|
|
|
|
|
<el-select v-model="u.roleId" style="width:100%">
|
2026-08-29 15:30:25 +08:00
|
|
|
|
<el-option v-for="rl in roles" :key="rl.id" :label="rl.name" :value="rl.id" />
|
2026-08-28 15:06:01 +08:00
|
|
|
|
</el-select>
|
|
|
|
|
|
</el-form-item>
|
|
|
|
|
|
<el-form-item label="状态">
|
|
|
|
|
|
<el-select v-model="u.status" style="width:100%">
|
|
|
|
|
|
<el-option label="启用" value="ENABLED" /><el-option label="禁用" value="DISABLED" />
|
|
|
|
|
|
</el-select>
|
|
|
|
|
|
</el-form-item>
|
|
|
|
|
|
</el-form>
|
|
|
|
|
|
<template #footer><el-button @click="u.show=false">取消</el-button><el-button type="primary" @click="saveUser">保存</el-button></template>
|
|
|
|
|
|
</el-dialog>
|
|
|
|
|
|
</el-card>
|
2026-08-28 17:23:44 +08:00
|
|
|
|
<PageHelp :data="helpRbac" />
|
2026-08-28 15:06:01 +08:00
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
|
|
<script setup>
|
|
|
|
|
|
import { ref, reactive, onMounted } from 'vue'
|
|
|
|
|
|
import { ElMessage, ElMessageBox } from 'element-plus'
|
|
|
|
|
|
import request from '../utils/request'
|
2026-08-28 17:23:44 +08:00
|
|
|
|
import PageHelp from '../components/PageHelp.vue'
|
|
|
|
|
|
import { helpRbac } from '../help'
|
2026-08-28 15:06:01 +08:00
|
|
|
|
|
|
|
|
|
|
const tab = ref('users')
|
|
|
|
|
|
const users = ref([]), roles = ref([]), perms = ref([])
|
|
|
|
|
|
const u = reactive({ show: false, id: 0, username: '', password: '', name: '', roleId: 0, status: 'ENABLED' })
|
|
|
|
|
|
|
|
|
|
|
|
async function loadAll() {
|
|
|
|
|
|
users.value = (await request.get('/users')) || []
|
|
|
|
|
|
roles.value = (await request.get('/roles')) || []
|
|
|
|
|
|
perms.value = (await request.get('/permissions')) || []
|
|
|
|
|
|
}
|
|
|
|
|
|
function openUser(row) { Object.assign(u, row ? { ...row, show: true, password: '' } : { show: true, id: 0, username: '', password: '', name: '', roleId: roles.value[0]?.id || 0, status: 'ENABLED' }) }
|
2026-08-29 15:30:25 +08:00
|
|
|
|
// 前端密码规则校验(与后端一致):>=6位 且不能纯数字
|
|
|
|
|
|
function pwdOk(pwd) {
|
|
|
|
|
|
if (pwd.length < 6) return '密码长度至少 6 位'
|
|
|
|
|
|
if (/^\d+$/.test(pwd)) return '密码不能是纯数字'
|
|
|
|
|
|
return ''
|
|
|
|
|
|
}
|
2026-08-28 15:06:01 +08:00
|
|
|
|
async function saveUser() {
|
2026-08-29 15:30:25 +08:00
|
|
|
|
// 新增必须设置密码
|
|
|
|
|
|
if (!u.id) {
|
|
|
|
|
|
const err = pwdOk(u.password || '')
|
|
|
|
|
|
if (err) return ElMessage.error(err)
|
|
|
|
|
|
} else if (u.password) {
|
|
|
|
|
|
const err = pwdOk(u.password)
|
|
|
|
|
|
if (err) return ElMessage.error(err)
|
|
|
|
|
|
}
|
2026-08-28 15:06:01 +08:00
|
|
|
|
if (u.id) await request.put('/users', { ...u })
|
|
|
|
|
|
else await request.post('/users', { ...u })
|
|
|
|
|
|
ElMessage.success('保存成功'); u.show = false; loadAll()
|
|
|
|
|
|
}
|
|
|
|
|
|
async function delUser(row) {
|
2026-08-29 15:30:25 +08:00
|
|
|
|
if (row.id === 1) return ElMessage.warning('系统管理员不可删除')
|
2026-08-28 15:06:01 +08:00
|
|
|
|
await ElMessageBox.confirm('确认删除该用户?', '提示', { type: 'warning' })
|
|
|
|
|
|
await request.delete(`/users/${row.id}`); loadAll()
|
|
|
|
|
|
}
|
|
|
|
|
|
onMounted(loadAll)
|
2026-08-29 15:30:25 +08:00
|
|
|
|
</script>
|
|
|
|
|
|
|
|
|
|
|
|
<style scoped>
|
|
|
|
|
|
.tip { color: #909399; font-size: 13px; margin: 0 0 10px; }
|
|
|
|
|
|
</style>
|