更新角色管理相关内容

This commit is contained in:
2026-09-09 15:04:34 +08:00
parent de7225b61e
commit fef0233cc4
24 changed files with 1442 additions and 116 deletions
@@ -13,12 +13,17 @@
</el-tag>
</el-descriptions-item>
<el-descriptions-item label="分类">
<el-tag :type="roleDetail.cid === 1 ? 'warning' : 'primary'" size="small">
{{ roleDetail.cid === 1 ? "平台角色" : "租户角色" }}
<el-tag v-if="roleDetail.cid === 1" type="danger" size="small">平台角色</el-tag>
<el-tag v-else-if="Number(roleDetail.is_custom) === 1" type="warning" size="small">
自定义角色
</el-tag>
<el-tag v-else type="primary" size="small">租户角色</el-tag>
</el-descriptions-item>
<el-descriptions-item label="权限列表">
<div v-if="menuNames.length > 0" style="max-height: 300px; overflow-y: auto;">
<div v-if="!roleDetail.rights" style="color: var(--el-text-color-secondary);">
全权限(未做限制)
</div>
<div v-else-if="menuNames.length > 0" style="max-height: 300px; overflow-y: auto;">
<el-tag
v-for="(name, index) in menuNames"
:key="index"
@@ -49,7 +54,7 @@
<script setup lang="ts">
import { ref, watch, computed } from "vue";
import { ElMessage } from "element-plus";
import { getPlatformRoleById } from "@/api/platformRole";
import { getRoleById } from "@/api/role";
import { getAllMenus } from "@/api/menu";
interface Props {
@@ -76,7 +81,7 @@ watch(
visible.value = val;
if (val && props.roleId) {
await loadRoleDetail();
await loadMenus(roleDetail.value.cid);
await loadMenus();
}
}
);
@@ -132,7 +137,7 @@ const loadRoleDetail = async () => {
loading.value = true;
try {
const res = await getPlatformRoleById(props.roleId);
const res = await getRoleById(props.roleId);
if (res.code === 200) {
roleDetail.value = res.data || {};
} else {
@@ -146,12 +151,10 @@ const loadRoleDetail = async () => {
}
};
// 加载菜单树:租户角色(cid=2)只展示租户端菜单;平台角色展示全部权限
const loadMenus = async (cid?: number) => {
// 加载菜单树:租户端只展示租户端菜单(cid=2)
const loadMenus = async () => {
try {
const isTenant = cid === undefined || cid === 2;
const params = isTenant ? { cid: 2 } : {};
const res = await getAllMenus(params);
const res = await getAllMenus({ cid: 2 });
if (res.code === 200) {
allMenus.value = res.data || [];
}
@@ -1,5 +1,10 @@
<template>
<el-dialog v-model="visible" :title="isEdit ? '编辑角色' : '添加角色'" width="600px" @close="handleClose">
<el-dialog
v-model="visible"
:title="isEdit ? '编辑租户角色' : '添加自定义角色'"
width="600px"
@close="handleClose"
>
<el-form :model="form" :rules="rules" ref="formRef" label-width="100px">
<el-form-item label="角色名称" prop="name">
<el-input v-model="form.name" placeholder="请输入角色名称" maxlength="50" show-word-limit />
@@ -12,12 +17,13 @@
</el-radio-group>
</el-form-item>
<el-form-item label="分类" prop="cid">
<el-radio-group v-model="form.cid" @change="onCidChange">
<el-radio :label="2">租户角色</el-radio>
<el-radio :label="1">平台角色</el-radio>
</el-radio-group>
<div class="form-tip">租户角色仅显示租户端菜单;平台角色显示全部权限</div>
<el-form-item label="角色类型">
<el-tag :type="form.is_custom ? 'warning' : 'primary'" size="small">
{{ form.is_custom ? "自定义角色" : "系统预置租户角色" }}
</el-tag>
<div class="form-tip">
当前为租户端,仅可维护本租户的自定义角色:权限范围限定在租户端菜单,数据按租户隔离,平台端不可见。
</div>
</el-form-item>
<el-form-item label="权限设置" prop="rights">
@@ -46,7 +52,7 @@
<script setup lang="ts">
import { ref, watch, nextTick } from "vue";
import { ElMessage } from "element-plus";
import { createPlatformRole, updatePlatformRole } from "@/api/platformRole";
import { createRole, updateRole } from "@/api/role";
import { getAllMenus } from "@/api/menu";
interface Props {
@@ -71,10 +77,11 @@ const menuTree = ref<any[]>([]);
const isAllSelected = ref(false);
const isExpandAll = ref(false);
// 租户端只处理租户角色(cid=2),分类固定,不再提供平台角色选项
const form = ref({
name: "",
status: 1,
cid: 2,
is_custom: 1,
rights: [] as number[],
});
@@ -148,12 +155,10 @@ const toggleSelectAll = () => {
// --- 数据加载与监听 ---
// 加载菜单树数据
// 租户角色(cid=2)只展示租户端菜单;平台角色(cid=1)展示全部权限
// 加载菜单树数据:租户端只展示租户端菜单(cid=2),平台菜单不在此分配
const loadMenus = async () => {
try {
const params = form.value.cid === 2 ? { cid: 2 } : {};
const res = await getAllMenus(params);
const res = await getAllMenus({ cid: 2 });
if (res.code === 200) {
menuTree.value = res.data || [];
}
@@ -163,18 +168,6 @@ const loadMenus = async () => {
}
};
// 切换分类时重新加载菜单树并回显已选权限
const onCidChange = async () => {
if (!visible.value) return;
await loadMenus();
nextTick(() => {
if (treeRef.value) {
treeRef.value.setCheckedKeys(form.value.rights);
updateSelectStatus();
}
});
};
// 解析权限数据
const parseRights = (rights: any): number[] => {
if (!rights) return [];
@@ -205,7 +198,7 @@ watch(
form.value = {
name: props.role.name,
status: props.role.status,
cid: props.role.cid === 1 ? 1 : 2,
is_custom: props.role.is_custom ? 1 : 0,
rights: parseRights(props.role.rights),
};
// 设置树的回显
@@ -234,7 +227,7 @@ const resetForm = () => {
form.value = {
name: "",
status: 1,
cid: 2,
is_custom: 1,
rights: [],
};
if (formRef.value) formRef.value.clearValidate();
@@ -255,25 +248,20 @@ const handleSubmit = async () => {
// 只获取完全选中的节点(不包含半选父节点)
const checkedKeys = treeRef.value.getCheckedKeys();
// 租户端只提交基础字段,cid/tenant_id/is_custom 由服务端按当前租户写入
const submitData: any = {
name: form.value.name,
status: form.value.status,
cid: form.value.cid,
rights: checkedKeys,
};
// 编辑时添加 id 字段
if (isEdit.value && props.role) {
submitData.id = props.role.id;
}
submitting.value = true;
let res;
if (isEdit.value && props.role) {
res = await updatePlatformRole(props.role.id, submitData);
res = await updateRole(props.role.id, submitData);
} else {
res = await createPlatformRole(submitData);
res = await createRole(submitData);
}
if (res.code === 200) {
+14 -28
View File
@@ -5,7 +5,7 @@
<div class="header-actions">
<el-button type="primary" @click="handleAdd">
<el-icon><Plus /></el-icon>
添加角色
添加自定义角色
</el-button>
<el-button @click="refresh">
<el-icon><Refresh /></el-icon>
@@ -19,8 +19,8 @@
<div class="filter-bar">
<el-radio-group v-model="typeFilter">
<el-radio-button :value="'all'">全部</el-radio-button>
<el-radio-button :value="1">平台角色</el-radio-button>
<el-radio-button :value="2">租户角色</el-radio-button>
<el-radio-button :value="'custom'">自定义角色</el-radio-button>
</el-radio-group>
</div>
@@ -39,11 +39,13 @@
min-width="150"
align="center"
/>
<el-table-column prop="cid" label="类型" width="120" align="center">
<el-table-column prop="cid" label="类型" width="150" align="center">
<template #default="{ row }">
<el-tag :type="row.cid === 1 ? 'warning' : 'primary'" size="small">
{{ row.cid === 1 ? "平台角色" : "租户角色" }}
<el-tag v-if="row.cid === 1" type="danger" size="small">平台角色</el-tag>
<el-tag v-else-if="Number(row.is_custom) === 1" type="warning" size="small">
自定义角色
</el-tag>
<el-tag v-else type="primary" size="small">租户角色</el-tag>
</template>
</el-table-column>
<el-table-column prop="status" label="状态" width="100" align="center">
@@ -71,7 +73,6 @@
详情
</el-button>
<el-button
v-if="userInfo?.id === 2"
size="small"
type="primary"
link
@@ -81,7 +82,7 @@
编辑
</el-button>
<el-button
v-if="userInfo?.id === 2"
v-if="Number(row.is_custom) === 1"
size="small"
type="danger"
link
@@ -114,23 +115,18 @@
import { ref, computed, onMounted } from "vue";
import { ElMessage, ElMessageBox } from "element-plus";
import { Plus, View, Edit, Delete, Refresh } from "@element-plus/icons-vue";
import {
getAllPlatformRoles,
deletePlatformRole,
} from "@/api/platformRole";
import { getAllRoles, deleteRole } from "@/api/role";
import RoleEditDialog from "./components/edit.vue";
import RoleDetailDialog from "./components/detail.vue";
import { useAuthStore } from "@/stores/auth";
// 使用 auth store 获取用户信息
const authStore = useAuthStore();
const roles = ref<any[]>([]);
const loading = ref(false);
const error = ref("");
const typeFilter = ref<string | number>("all");
const displayRoles = computed(() => {
// custom = 本租户自建的自定义角色;2 = 租户角色(含系统预置)
if (typeFilter.value === "all") return roles.value;
if (typeFilter.value === "custom") return roles.value.filter((r) => Number(r.is_custom) === 1);
return roles.value.filter((r) => Number(r.cid) === Number(typeFilter.value));
});
@@ -139,22 +135,12 @@ const detailDialogVisible = ref(false);
const currentRole = ref<any>(null);
const currentRoleId = ref<number | null>(null);
// 获取用户信息
const userInfo = authStore.user;
if (userInfo && userInfo.id) {
// console.log('用户名:', userInfo.username || userInfo.nickname);
// console.log('用户ID:', userInfo.id);
// console.log('角色:', userInfo.role);
} else {
// console.log('未找到用户信息或用户未登录');
}
// 获取角色列表
// 获取角色列表:仅返回当前登录租户名下的租户角色(服务端按租户隔离)
const fetchRoles = async () => {
loading.value = true;
error.value = "";
try {
const res = await getAllPlatformRoles();
const res = await getAllRoles();
if (res.code === 200) {
roles.value = res.data || [];
// console.log('角色列表:', roles.value);
@@ -207,7 +193,7 @@ async function handleDelete(row: any) {
loading.value = true;
try {
const res = await deletePlatformRole(row.id);
const res = await deleteRole(row.id);
if (res.code === 200) {
ElMessage.success("删除成功");
fetchRoles();