feat: implement RBAC and field masking for system_user module
Co-authored-by: aider (openai/DeepSeek-V3.2-Thinking) <aider@aider.chat>
This commit is contained in:
@ -16,23 +16,33 @@
|
||||
border
|
||||
style="width: 100%"
|
||||
>
|
||||
<el-table-column prop="username" label="用户标识" min-width="180" />
|
||||
<el-table-column v-if="hasColumnPermission('username')" prop="username" label="用户标识" min-width="180" />
|
||||
|
||||
<el-table-column prop="department" label="所属部门" width="150">
|
||||
<el-table-column v-if="hasColumnPermission('department')" prop="department" label="所属部门" width="150">
|
||||
<template #default="scope">
|
||||
<el-tag>{{ scope.row.department }}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column prop="role" label="系统角色" width="180">
|
||||
<el-table-column v-if="hasColumnPermission('role')" prop="role" label="系统角色" width="180">
|
||||
<template #default="scope">
|
||||
{{ formatRole(scope.row.role) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column prop="email" label="邮箱" min-width="200" />
|
||||
<el-table-column v-if="hasColumnPermission('email')" prop="email" label="邮箱" min-width="200" />
|
||||
|
||||
<el-table-column label="操作" width="180" fixed="right">
|
||||
<el-table-column v-if="hasColumnPermission('status')" prop="status" label="状态" width="100" align="center">
|
||||
<template #default="scope">
|
||||
<el-tag :type="scope.row.status === 'active' ? 'success' : 'danger'">
|
||||
{{ scope.row.status === 'active' ? '启用' : '禁用' }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column v-if="hasColumnPermission('created_at')" prop="created_at" label="创建时间" width="160" />
|
||||
|
||||
<el-table-column v-if="userStore.hasPermission('system_user:operation')" label="操作" width="180" fixed="right">
|
||||
<template #default="scope">
|
||||
<el-button link type="primary" size="small" @click="handleEdit(scope.row)">编辑</el-button>
|
||||
<el-popconfirm title="确定要删除该用户吗?" @confirm="handleDelete(scope.row)">
|
||||
@ -61,7 +71,7 @@
|
||||
<el-input
|
||||
v-model="form.cn_name"
|
||||
placeholder="请输入中文姓名 (如: 张三)"
|
||||
:disabled="isEdit"
|
||||
:disabled="isEdit || !userStore.hasPermission('system_user:operation')"
|
||||
@input="handleNameInput"
|
||||
/>
|
||||
</el-form-item>
|
||||
@ -70,7 +80,7 @@
|
||||
<el-input
|
||||
v-model="form.username"
|
||||
placeholder="自动生成,可修改 (如: zhangsan)"
|
||||
:disabled="isEdit"
|
||||
:disabled="isEdit || !userStore.hasPermission('system_user:operation')"
|
||||
>
|
||||
<template #append>
|
||||
<span v-if="!isEdit" style="font-size: 12px; color: #999;">重复自动+1</span>
|
||||
@ -84,6 +94,7 @@
|
||||
type="password"
|
||||
show-password
|
||||
:placeholder="isEdit ? '不修改请留空' : '设置初始密码'"
|
||||
:disabled="!userStore.hasPermission('system_user:operation')"
|
||||
/>
|
||||
</el-form-item>
|
||||
|
||||
@ -95,13 +106,14 @@
|
||||
filterable
|
||||
allow-create
|
||||
default-first-option
|
||||
:disabled="!userStore.hasPermission('system_user:operation')"
|
||||
>
|
||||
<el-option v-for="item in departmentOptions" :key="item" :label="item" :value="item" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="系统角色" prop="role">
|
||||
<el-select v-model="form.role" placeholder="授予权限" style="width: 100%">
|
||||
<el-select v-model="form.role" placeholder="授予权限" style="width: 100%" :disabled="!userStore.hasPermission('system_user:operation')">
|
||||
<el-option
|
||||
v-for="option in roleOptions"
|
||||
:key="option.value"
|
||||
@ -112,14 +124,14 @@
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="邮箱" prop="email">
|
||||
<el-input v-model="form.email" placeholder="请输入邮箱" />
|
||||
<el-input v-model="form.email" placeholder="请输入邮箱" :disabled="!userStore.hasPermission('system_user:operation')" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<template #footer>
|
||||
<div class="dialog-footer">
|
||||
<el-button @click="dialogVisible = false">取消</el-button>
|
||||
<el-button type="primary" @click="onSubmit" :loading="submitLoading">
|
||||
<el-button v-if="userStore.hasPermission('system_user:operation')" type="primary" @click="onSubmit" :loading="submitLoading">
|
||||
{{ isEdit ? '确认修改' : '确认创建' }}
|
||||
</el-button>
|
||||
</div>
|
||||
@ -135,6 +147,27 @@ import { useUserStore } from '@/stores/user'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import { pinyin } from 'pinyin-pro' // ★ 务必安装: npm install pinyin-pro
|
||||
|
||||
const userStore = useUserStore()
|
||||
|
||||
// 列与权限Code的映射关系(数据库中的code)
|
||||
const permissionMap: Record<string, string> = {
|
||||
username: 'system_user:username',
|
||||
department: 'system_user:department',
|
||||
role: 'system_user:role',
|
||||
email: 'system_user:email',
|
||||
status: 'system_user:status',
|
||||
created_at: 'system_user:created_at',
|
||||
}
|
||||
|
||||
// 检查列权限
|
||||
const hasColumnPermission = (prop: string) => {
|
||||
if (userStore.role === 'SUPER_ADMIN' || userStore.username === 'IRIS') {
|
||||
return true
|
||||
}
|
||||
const code = permissionMap[prop]
|
||||
return code ? userStore.hasPermission(code) : false
|
||||
}
|
||||
|
||||
const userStore = useUserStore()
|
||||
const tableLoading = ref(false)
|
||||
const submitLoading = ref(false)
|
||||
@ -241,6 +274,7 @@ const getList = async () => {
|
||||
tableData.value = res.data || []
|
||||
extractDepartments(tableData.value)
|
||||
} catch (error) {
|
||||
// 错误已由全局拦截器统一处理
|
||||
console.error('Fetch users failed:', error)
|
||||
} finally {
|
||||
tableLoading.value = false
|
||||
@ -317,7 +351,7 @@ const onSubmit = async () => {
|
||||
dialogVisible.value = false
|
||||
getList()
|
||||
} catch (error) {
|
||||
// request 拦截器会处理错误
|
||||
// 错误已由全局拦截器统一处理
|
||||
} finally {
|
||||
submitLoading.value = false
|
||||
}
|
||||
@ -342,6 +376,7 @@ const handleDelete = async (row: any) => {
|
||||
ElMessage.success('删除成功')
|
||||
getList()
|
||||
} catch (error) {
|
||||
// 错误已由全局拦截器统一处理
|
||||
}
|
||||
}
|
||||
|
||||
@ -378,4 +413,4 @@ onMounted(() => {
|
||||
text-align: right;
|
||||
margin-top: 20px;
|
||||
}
|
||||
</style>
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user