feat: 实现动态菜单功能,替换硬编码菜单
1. 后端新增menu字段接口和route权限字段,重构权限接口返回菜单树 2. 前端替换硬编码侧边菜单为动态渲染,新增菜单store和图标映射逻辑 3. 调整权限路由元信息和初始化权限数据
This commit is contained in:
parent
0045ae18cb
commit
12a577f9a3
@ -107,6 +107,70 @@ async def get_permission_tree(
|
|||||||
return tree
|
return tree
|
||||||
|
|
||||||
|
|
||||||
|
@router.get("/menu", response_model=list[PermissionTreeResponse])
|
||||||
|
async def get_menu(
|
||||||
|
db: AsyncSession = Depends(get_db),
|
||||||
|
current_user: User = Depends(get_current_user),
|
||||||
|
):
|
||||||
|
"""获取当前用户的菜单树形结构(仅包含有路由的权限)"""
|
||||||
|
# 获取用户角色的权限
|
||||||
|
result = await db.execute(
|
||||||
|
select(Role)
|
||||||
|
.options(selectinload(Role.permissions))
|
||||||
|
.filter(Role.id == current_user.role_id)
|
||||||
|
)
|
||||||
|
role = result.scalar_one_or_none()
|
||||||
|
|
||||||
|
if not role:
|
||||||
|
raise HTTPException(status_code=404, detail="角色不存在")
|
||||||
|
|
||||||
|
# 获取用户有权限的权限编码集合
|
||||||
|
user_permission_codes = {perm.code for perm in role.permissions}
|
||||||
|
|
||||||
|
# 获取所有顶级模块和二级模块权限(有route字段的)
|
||||||
|
result = await db.execute(
|
||||||
|
select(Permission)
|
||||||
|
.filter(Permission.route.isnot(None))
|
||||||
|
)
|
||||||
|
all_menu_permissions = result.scalars().all()
|
||||||
|
|
||||||
|
# 过滤用户有权限的菜单
|
||||||
|
user_menu_permissions = []
|
||||||
|
for perm in all_menu_permissions:
|
||||||
|
# 检查用户是否有该权限或其子权限
|
||||||
|
has_access = False
|
||||||
|
for user_perm_code in user_permission_codes:
|
||||||
|
if user_perm_code.startswith(perm.code):
|
||||||
|
has_access = True
|
||||||
|
break
|
||||||
|
if has_access:
|
||||||
|
user_menu_permissions.append(perm)
|
||||||
|
|
||||||
|
# 转换为字典,便于查找
|
||||||
|
perm_dict = {perm.id: {
|
||||||
|
"id": perm.id,
|
||||||
|
"name": perm.name,
|
||||||
|
"code": perm.code,
|
||||||
|
"parentid": perm.parentid,
|
||||||
|
"route": perm.route,
|
||||||
|
"description": perm.description,
|
||||||
|
"children": []
|
||||||
|
} for perm in user_menu_permissions}
|
||||||
|
|
||||||
|
# 构建树形结构
|
||||||
|
tree = []
|
||||||
|
for perm_id, perm_data in perm_dict.items():
|
||||||
|
parentid = perm_data["parentid"]
|
||||||
|
if parentid == 0:
|
||||||
|
# 顶级节点
|
||||||
|
tree.append(perm_data)
|
||||||
|
elif parentid in perm_dict:
|
||||||
|
# 子节点,添加到父节点的 children
|
||||||
|
perm_dict[parentid]["children"].append(perm_data)
|
||||||
|
|
||||||
|
return tree
|
||||||
|
|
||||||
|
|
||||||
@router.get("/{permission_id}", response_model=PermissionResponse)
|
@router.get("/{permission_id}", response_model=PermissionResponse)
|
||||||
async def get_permission(
|
async def get_permission(
|
||||||
permission_id: int,
|
permission_id: int,
|
||||||
@ -227,7 +291,7 @@ async def get_current_user_permissions(
|
|||||||
db: AsyncSession = Depends(get_db),
|
db: AsyncSession = Depends(get_db),
|
||||||
current_user: User = Depends(get_current_user),
|
current_user: User = Depends(get_current_user),
|
||||||
):
|
):
|
||||||
"""获取当前登录用户的权限列表"""
|
"""获取当前登录用户的权限列表和菜单"""
|
||||||
# 获取用户角色的权限
|
# 获取用户角色的权限
|
||||||
result = await db.execute(
|
result = await db.execute(
|
||||||
select(Role)
|
select(Role)
|
||||||
@ -239,9 +303,54 @@ async def get_current_user_permissions(
|
|||||||
if not role:
|
if not role:
|
||||||
raise HTTPException(status_code=404, detail="角色不存在")
|
raise HTTPException(status_code=404, detail="角色不存在")
|
||||||
|
|
||||||
# 返回用户权限信息
|
# 获取用户有权限的权限编码集合
|
||||||
|
user_permission_codes = {perm.code for perm in role.permissions}
|
||||||
|
|
||||||
|
# 获取所有顶级模块和二级模块权限(有route字段的)
|
||||||
|
result = await db.execute(
|
||||||
|
select(Permission)
|
||||||
|
.filter(Permission.route.isnot(None))
|
||||||
|
)
|
||||||
|
all_menu_permissions = result.scalars().all()
|
||||||
|
|
||||||
|
# 过滤用户有权限的菜单
|
||||||
|
user_menu_permissions = []
|
||||||
|
for perm in all_menu_permissions:
|
||||||
|
# 检查用户是否有该权限或其子权限
|
||||||
|
has_access = False
|
||||||
|
for user_perm_code in user_permission_codes:
|
||||||
|
if user_perm_code.startswith(perm.code):
|
||||||
|
has_access = True
|
||||||
|
break
|
||||||
|
if has_access:
|
||||||
|
user_menu_permissions.append(perm)
|
||||||
|
|
||||||
|
# 转换为字典,便于查找
|
||||||
|
perm_dict = {perm.id: {
|
||||||
|
"id": perm.id,
|
||||||
|
"name": perm.name,
|
||||||
|
"code": perm.code,
|
||||||
|
"parentid": perm.parentid,
|
||||||
|
"route": perm.route,
|
||||||
|
"description": perm.description,
|
||||||
|
"children": []
|
||||||
|
} for perm in user_menu_permissions}
|
||||||
|
|
||||||
|
# 构建树形结构
|
||||||
|
menu_tree = []
|
||||||
|
for perm_id, perm_data in perm_dict.items():
|
||||||
|
parentid = perm_data["parentid"]
|
||||||
|
if parentid == 0:
|
||||||
|
# 顶级节点
|
||||||
|
menu_tree.append(perm_data)
|
||||||
|
elif parentid in perm_dict:
|
||||||
|
# 子节点,添加到父节点的 children
|
||||||
|
perm_dict[parentid]["children"].append(perm_data)
|
||||||
|
|
||||||
|
# 返回用户权限信息和菜单
|
||||||
return RolePermissionResponse(
|
return RolePermissionResponse(
|
||||||
role_id=role.id,
|
role_id=role.id,
|
||||||
role_name=role.name,
|
role_name=role.name,
|
||||||
permissions=[PermissionResponse.from_orm(p) for p in role.permissions]
|
permissions=[PermissionResponse.from_orm(p) for p in role.permissions],
|
||||||
)
|
menu=menu_tree
|
||||||
|
)
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
from sqlalchemy.ext.asyncio import AsyncSession
|
from sqlalchemy.ext.asyncio import AsyncSession
|
||||||
from sqlalchemy import select, text
|
from sqlalchemy import select, text
|
||||||
from models import Role, User, Permission
|
from models import Role, User, Permission, SystemSetting
|
||||||
from utils.password import get_password_hash
|
from utils.password import get_password_hash
|
||||||
|
|
||||||
|
|
||||||
@ -32,6 +32,14 @@ async def ensure_permission_table_structure(db: AsyncSession):
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"添加 parentid 字段失败: {e}")
|
print(f"添加 parentid 字段失败: {e}")
|
||||||
|
|
||||||
|
# 添加 route 字段
|
||||||
|
if 'route' not in existing_columns:
|
||||||
|
try:
|
||||||
|
await db.execute(text("ALTER TABLE permission ADD COLUMN IF NOT EXISTS route VARCHAR(255)"))
|
||||||
|
print("添加 route 字段成功")
|
||||||
|
except Exception as e:
|
||||||
|
print(f"添加 route 字段失败: {e}")
|
||||||
|
|
||||||
# 删除旧字段(如果存在)
|
# 删除旧字段(如果存在)
|
||||||
for old_column in ['module', 'submodule', 'action']:
|
for old_column in ['module', 'submodule', 'action']:
|
||||||
if old_column in existing_columns:
|
if old_column in existing_columns:
|
||||||
@ -53,21 +61,21 @@ async def init_permissions(db: AsyncSession):
|
|||||||
# ========================================
|
# ========================================
|
||||||
# 顶级模块
|
# 顶级模块
|
||||||
# ========================================
|
# ========================================
|
||||||
{"name": "权限管理", "code": "perm", "parentid": 0, "description": "权限管理模块"},
|
{"name": "权限管理", "code": "perm", "parentid": 0, "route": "/admin/permissions", "description": "权限管理模块"},
|
||||||
{"name": "系统设置", "code": "system", "parentid": 0, "description": "系统设置模块"},
|
{"name": "系统设置", "code": "system", "parentid": 0, "route": "/admin/settings", "description": "系统设置模块"},
|
||||||
|
|
||||||
# ========================================
|
# ========================================
|
||||||
# 权限管理 -> 二级子模块
|
# 权限管理 -> 二级子模块
|
||||||
# ========================================
|
# ========================================
|
||||||
{"name": "用户管理", "code": "perm:user", "parentid": 1, "description": "用户管理子模块"},
|
{"name": "用户管理", "code": "perm:user", "parentid": 1, "route": "/admin/users", "description": "用户管理子模块"},
|
||||||
{"name": "角色管理", "code": "perm:role", "parentid": 1, "description": "角色管理子模块"},
|
{"name": "角色管理", "code": "perm:role", "parentid": 1, "route": "/admin/roles", "description": "角色管理子模块"},
|
||||||
{"name": "权限配置", "code": "perm:config", "parentid": 1, "description": "权限配置子模块"},
|
{"name": "权限配置", "code": "perm:config", "parentid": 1, "route": "/admin/permissions", "description": "权限配置子模块"},
|
||||||
|
|
||||||
# ========================================
|
# ========================================
|
||||||
# 系统设置 -> 二级子模块
|
# 系统设置 -> 二级子模块
|
||||||
# ========================================
|
# ========================================
|
||||||
{"name": "基础配置", "code": "system:basic", "parentid": 2, "description": "系统基础配置"},
|
{"name": "基础配置", "code": "system:basic", "parentid": 2, "route": "/admin/settings", "description": "系统基础配置"},
|
||||||
{"name": "高级配置", "code": "system:advanced", "parentid": 2, "description": "系统高级配置"},
|
{"name": "高级配置", "code": "system:advanced", "parentid": 2, "route": "/admin/settings", "description": "系统高级配置"},
|
||||||
|
|
||||||
# ========================================
|
# ========================================
|
||||||
# 用户管理操作(parentid=3)
|
# 用户管理操作(parentid=3)
|
||||||
@ -143,6 +151,9 @@ async def init_permissions(db: AsyncSession):
|
|||||||
if existing_perm.parentid != perm_data["parentid"]:
|
if existing_perm.parentid != perm_data["parentid"]:
|
||||||
existing_perm.parentid = perm_data["parentid"]
|
existing_perm.parentid = perm_data["parentid"]
|
||||||
update_needed = True
|
update_needed = True
|
||||||
|
if existing_perm.route != perm_data.get("route"):
|
||||||
|
existing_perm.route = perm_data.get("route")
|
||||||
|
update_needed = True
|
||||||
if existing_perm.description != perm_data["description"]:
|
if existing_perm.description != perm_data["description"]:
|
||||||
existing_perm.description = perm_data["description"]
|
existing_perm.description = perm_data["description"]
|
||||||
update_needed = True
|
update_needed = True
|
||||||
@ -383,6 +394,60 @@ async def init_test_user(db: AsyncSession):
|
|||||||
print("测试用户初始化/更新完成")
|
print("测试用户初始化/更新完成")
|
||||||
|
|
||||||
|
|
||||||
|
async def init_system_settings(db: AsyncSession):
|
||||||
|
"""初始化系统设置数据"""
|
||||||
|
# 定义需要初始化的系统设置
|
||||||
|
system_settings = [
|
||||||
|
{
|
||||||
|
"key": "系统标题",
|
||||||
|
"value": "图书管理系统",
|
||||||
|
"type": "string",
|
||||||
|
"description": "系统显示标题"
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
# 检查现有系统设置
|
||||||
|
result = await db.execute(select(SystemSetting))
|
||||||
|
existing_settings = result.scalars().all()
|
||||||
|
existing_setting_keys = {setting.key: setting for setting in existing_settings}
|
||||||
|
|
||||||
|
# 创建或更新系统设置
|
||||||
|
created_count = 0
|
||||||
|
updated_count = 0
|
||||||
|
|
||||||
|
for setting_data in system_settings:
|
||||||
|
setting_key = setting_data["key"]
|
||||||
|
if setting_key not in existing_setting_keys:
|
||||||
|
# 设置不存在,需要创建
|
||||||
|
db.add(SystemSetting(**setting_data))
|
||||||
|
created_count += 1
|
||||||
|
else:
|
||||||
|
# 设置存在,检查是否需要更新
|
||||||
|
existing_setting = existing_setting_keys[setting_key]
|
||||||
|
update_needed = False
|
||||||
|
|
||||||
|
if existing_setting.value != setting_data["value"]:
|
||||||
|
existing_setting.value = setting_data["value"]
|
||||||
|
update_needed = True
|
||||||
|
if existing_setting.type != setting_data["type"]:
|
||||||
|
existing_setting.type = setting_data["type"]
|
||||||
|
update_needed = True
|
||||||
|
if existing_setting.description != setting_data.get("description"):
|
||||||
|
existing_setting.description = setting_data.get("description")
|
||||||
|
update_needed = True
|
||||||
|
|
||||||
|
if update_needed:
|
||||||
|
updated_count += 1
|
||||||
|
|
||||||
|
if created_count > 0 or updated_count > 0:
|
||||||
|
await db.commit()
|
||||||
|
print(f"创建了 {created_count} 个系统设置,更新了 {updated_count} 个系统设置")
|
||||||
|
else:
|
||||||
|
print("系统设置数据已存在且无需更新,跳过初始化")
|
||||||
|
|
||||||
|
print("系统设置数据初始化/更新完成")
|
||||||
|
|
||||||
|
|
||||||
async def init_all_data(db: AsyncSession):
|
async def init_all_data(db: AsyncSession):
|
||||||
"""初始化所有数据"""
|
"""初始化所有数据"""
|
||||||
print("开始初始化数据库数据...")
|
print("开始初始化数据库数据...")
|
||||||
@ -392,4 +457,5 @@ async def init_all_data(db: AsyncSession):
|
|||||||
await init_role_permissions(db)
|
await init_role_permissions(db)
|
||||||
await init_admin_user(db)
|
await init_admin_user(db)
|
||||||
await init_test_user(db)
|
await init_test_user(db)
|
||||||
|
await init_system_settings(db)
|
||||||
print("数据库数据初始化完成")
|
print("数据库数据初始化完成")
|
||||||
|
|||||||
@ -59,6 +59,7 @@ class Permission(Base):
|
|||||||
name = Column(String(100), nullable=False, comment="权限名称")
|
name = Column(String(100), nullable=False, comment="权限名称")
|
||||||
code = Column(String(100), nullable=False, unique=True, comment="权限编码")
|
code = Column(String(100), nullable=False, unique=True, comment="权限编码")
|
||||||
parentid = Column(Integer, default=0, comment="父权限ID(0表示顶级模块)")
|
parentid = Column(Integer, default=0, comment="父权限ID(0表示顶级模块)")
|
||||||
|
route = Column(String(255), nullable=True, comment="前端路由路径")
|
||||||
description = Column(String(255), nullable=True, comment="权限描述")
|
description = Column(String(255), nullable=True, comment="权限描述")
|
||||||
createtime = Column(DateTime, default=datetime.utcnow, comment="创建时间")
|
createtime = Column(DateTime, default=datetime.utcnow, comment="创建时间")
|
||||||
updatetime = Column(
|
updatetime = Column(
|
||||||
|
|||||||
@ -139,6 +139,7 @@ class PermissionBase(BaseModel):
|
|||||||
name: str = Field(..., max_length=100, description="权限名称")
|
name: str = Field(..., max_length=100, description="权限名称")
|
||||||
code: str = Field(..., max_length=100, description="权限编码")
|
code: str = Field(..., max_length=100, description="权限编码")
|
||||||
parentid: int = Field(0, description="父权限ID(0表示顶级模块)")
|
parentid: int = Field(0, description="父权限ID(0表示顶级模块)")
|
||||||
|
route: Optional[str] = Field(None, max_length=255, description="前端路由路径")
|
||||||
description: Optional[str] = Field(None, max_length=255, description="权限描述")
|
description: Optional[str] = Field(None, max_length=255, description="权限描述")
|
||||||
|
|
||||||
|
|
||||||
@ -165,6 +166,7 @@ class PermissionTreeResponse(BaseModel):
|
|||||||
name: str = Field(..., description="权限名称")
|
name: str = Field(..., description="权限名称")
|
||||||
code: str = Field(..., description="权限编码")
|
code: str = Field(..., description="权限编码")
|
||||||
parentid: int = Field(..., description="父权限ID")
|
parentid: int = Field(..., description="父权限ID")
|
||||||
|
route: Optional[str] = Field(None, description="前端路由路径")
|
||||||
description: Optional[str] = Field(None, description="权限描述")
|
description: Optional[str] = Field(None, description="权限描述")
|
||||||
children: list = Field([], description="子权限列表")
|
children: list = Field([], description="子权限列表")
|
||||||
|
|
||||||
@ -183,6 +185,7 @@ class RolePermissionResponse(BaseModel):
|
|||||||
role_id: int = Field(..., description="角色ID")
|
role_id: int = Field(..., description="角色ID")
|
||||||
role_name: str = Field(..., description="角色名称")
|
role_name: str = Field(..., description="角色名称")
|
||||||
permissions: list[PermissionResponse] = Field(..., description="权限列表")
|
permissions: list[PermissionResponse] = Field(..., description="权限列表")
|
||||||
|
menu: list = Field([], description="菜单树形结构")
|
||||||
|
|
||||||
|
|
||||||
# 系统设置相关模型
|
# 系统设置相关模型
|
||||||
|
|||||||
@ -9,47 +9,34 @@
|
|||||||
text-color="#e2e8f0"
|
text-color="#e2e8f0"
|
||||||
active-text-color="#38bdf8"
|
active-text-color="#38bdf8"
|
||||||
>
|
>
|
||||||
<!-- 权限管理一级菜单 -->
|
<!-- 动态渲染菜单 -->
|
||||||
<el-sub-menu
|
<template v-for="menu in auth.menu" :key="menu.id">
|
||||||
v-if="hasAnyPermission"
|
<!-- 有子菜单的顶级菜单 -->
|
||||||
index="/admin/permissions"
|
<el-sub-menu
|
||||||
>
|
v-if="menu.children && menu.children.length > 0"
|
||||||
<template #title>
|
:index="menu.route"
|
||||||
<el-icon><Key /></el-icon>
|
|
||||||
<span>权限管理</span>
|
|
||||||
</template>
|
|
||||||
<el-menu-item
|
|
||||||
v-if="hasUserPermission"
|
|
||||||
index="/admin/users"
|
|
||||||
:route="{ name: 'admin-users' }"
|
|
||||||
>
|
>
|
||||||
<span>用户管理</span>
|
<template #title>
|
||||||
</el-menu-item>
|
<el-icon><component :is="getIcon(menu.code)" /></el-icon>
|
||||||
|
<span>{{ menu.name }}</span>
|
||||||
|
</template>
|
||||||
|
<el-menu-item
|
||||||
|
v-for="child in menu.children"
|
||||||
|
:key="child.id"
|
||||||
|
:index="child.route"
|
||||||
|
>
|
||||||
|
<span>{{ child.name }}</span>
|
||||||
|
</el-menu-item>
|
||||||
|
</el-sub-menu>
|
||||||
|
<!-- 无子菜单的顶级菜单 -->
|
||||||
<el-menu-item
|
<el-menu-item
|
||||||
v-if="hasRolePermission"
|
v-else
|
||||||
index="/admin/roles"
|
:index="menu.route"
|
||||||
:route="{ name: 'admin-roles' }"
|
|
||||||
>
|
>
|
||||||
<span>角色管理</span>
|
<el-icon><component :is="getIcon(menu.code)" /></el-icon>
|
||||||
|
<span>{{ menu.name }}</span>
|
||||||
</el-menu-item>
|
</el-menu-item>
|
||||||
<el-menu-item
|
</template>
|
||||||
v-if="hasPermissionPermission"
|
|
||||||
index="/admin/permissions"
|
|
||||||
:route="{ name: 'admin-permissions' }"
|
|
||||||
>
|
|
||||||
<span>权限管理</span>
|
|
||||||
</el-menu-item>
|
|
||||||
</el-sub-menu>
|
|
||||||
|
|
||||||
<!-- 系统设置一级菜单 -->
|
|
||||||
<el-menu-item
|
|
||||||
v-if="hasSystemPermission"
|
|
||||||
index="/admin/settings"
|
|
||||||
:route="{ name: 'admin-settings' }"
|
|
||||||
>
|
|
||||||
<el-icon><Setting /></el-icon>
|
|
||||||
<span>系统设置</span>
|
|
||||||
</el-menu-item>
|
|
||||||
</el-menu>
|
</el-menu>
|
||||||
</el-aside>
|
</el-aside>
|
||||||
<el-container>
|
<el-container>
|
||||||
@ -72,9 +59,9 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { computed, onMounted, ref } from "vue";
|
import { computed, onMounted, ref, markRaw } from "vue";
|
||||||
import { useRoute, useRouter } from "vue-router";
|
import { useRoute, useRouter } from "vue-router";
|
||||||
import { Key, Setting } from "@element-plus/icons-vue";
|
import { Key, Setting, Folder } from "@element-plus/icons-vue";
|
||||||
import { ElMessage } from "element-plus";
|
import { ElMessage } from "element-plus";
|
||||||
import { useAuthStore } from "@/modules/admin/stores/auth";
|
import { useAuthStore } from "@/modules/admin/stores/auth";
|
||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
@ -87,25 +74,21 @@ const sysTitle = ref("");
|
|||||||
const active = computed(() => route.path);
|
const active = computed(() => route.path);
|
||||||
const pageTitle = computed(() => (route.meta.title as string) || "");
|
const pageTitle = computed(() => (route.meta.title as string) || "");
|
||||||
|
|
||||||
const hasUserPermission = computed(() => {
|
// 图标映射
|
||||||
return auth.permissions.some(p => p.code.startsWith("perm:user"));
|
const iconMap: Record<string, any> = {
|
||||||
});
|
"perm": markRaw(Key),
|
||||||
|
"system": markRaw(Setting),
|
||||||
|
};
|
||||||
|
|
||||||
const hasRolePermission = computed(() => {
|
function getIcon(code: string) {
|
||||||
return auth.permissions.some(p => p.code.startsWith("perm:role"));
|
// 查找匹配的图标
|
||||||
});
|
for (const key in iconMap) {
|
||||||
|
if (code.startsWith(key)) {
|
||||||
const hasPermissionPermission = computed(() => {
|
return iconMap[key];
|
||||||
return auth.permissions.some(p => p.code.startsWith("perm:config"));
|
}
|
||||||
});
|
}
|
||||||
|
return Folder;
|
||||||
const hasSystemPermission = computed(() => {
|
}
|
||||||
return auth.permissions.some(p => p.code.startsWith("system:"));
|
|
||||||
});
|
|
||||||
|
|
||||||
const hasAnyPermission = computed(() => {
|
|
||||||
return hasUserPermission.value || hasRolePermission.value || hasPermissionPermission.value;
|
|
||||||
});
|
|
||||||
|
|
||||||
async function getSysTitle() {
|
async function getSysTitle() {
|
||||||
const baseURL = import.meta.env.VITE_API_BASE || "/api";
|
const baseURL = import.meta.env.VITE_API_BASE || "/api";
|
||||||
@ -115,10 +98,9 @@ async function getSysTitle() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
try {
|
try {
|
||||||
getSysTitle();
|
await getSysTitle();
|
||||||
if (!auth.user) {
|
if (!auth.user) {
|
||||||
await auth.fetchProfile();
|
await auth.fetchProfile();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -19,16 +19,28 @@ export type Permission = {
|
|||||||
description?: string | null;
|
description?: string | null;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type MenuItem = {
|
||||||
|
id: number;
|
||||||
|
name: string;
|
||||||
|
code: string;
|
||||||
|
parentid: number;
|
||||||
|
route: string;
|
||||||
|
description?: string;
|
||||||
|
children: MenuItem[];
|
||||||
|
};
|
||||||
|
|
||||||
export type RolePermissionResponse = {
|
export type RolePermissionResponse = {
|
||||||
role_id: number;
|
role_id: number;
|
||||||
role_name: string;
|
role_name: string;
|
||||||
permissions: Permission[];
|
permissions: Permission[];
|
||||||
|
menu: MenuItem[];
|
||||||
};
|
};
|
||||||
|
|
||||||
export const useAuthStore = defineStore("auth", () => {
|
export const useAuthStore = defineStore("auth", () => {
|
||||||
const token = ref<string>(localStorage.getItem("access_token") || "");
|
const token = ref<string>(localStorage.getItem("access_token") || "");
|
||||||
const user = ref<UserProfile | null>(null);
|
const user = ref<UserProfile | null>(null);
|
||||||
const permissions = ref<Permission[]>([]);
|
const permissions = ref<Permission[]>([]);
|
||||||
|
const menu = ref<MenuItem[]>([]);
|
||||||
|
|
||||||
const isAuthenticated = computed(() => Boolean(token.value));
|
const isAuthenticated = computed(() => Boolean(token.value));
|
||||||
|
|
||||||
@ -52,7 +64,8 @@ export const useAuthStore = defineStore("auth", () => {
|
|||||||
async function fetchPermissions() {
|
async function fetchPermissions() {
|
||||||
const { data } = await http.get<RolePermissionResponse>("/permissions/user/me");
|
const { data } = await http.get<RolePermissionResponse>("/permissions/user/me");
|
||||||
permissions.value = data.permissions || [];
|
permissions.value = data.permissions || [];
|
||||||
return permissions.value;
|
menu.value = data.menu || [];
|
||||||
|
return { permissions: permissions.value, menu: menu.value };
|
||||||
}
|
}
|
||||||
|
|
||||||
async function loginAndFetchData() {
|
async function loginAndFetchData() {
|
||||||
@ -76,6 +89,7 @@ export const useAuthStore = defineStore("auth", () => {
|
|||||||
}
|
}
|
||||||
user.value = null;
|
user.value = null;
|
||||||
permissions.value = [];
|
permissions.value = [];
|
||||||
|
menu.value = [];
|
||||||
setToken("");
|
setToken("");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -83,6 +97,7 @@ export const useAuthStore = defineStore("auth", () => {
|
|||||||
token,
|
token,
|
||||||
user,
|
user,
|
||||||
permissions,
|
permissions,
|
||||||
|
menu,
|
||||||
permissionCodes,
|
permissionCodes,
|
||||||
isAuthenticated,
|
isAuthenticated,
|
||||||
setToken,
|
setToken,
|
||||||
|
|||||||
@ -41,7 +41,7 @@ const router = createRouter({
|
|||||||
{
|
{
|
||||||
path: "permissions",
|
path: "permissions",
|
||||||
name: "admin-permissions",
|
name: "admin-permissions",
|
||||||
meta: { title: "权限管理", permission: "perm:config" },
|
meta: { title: "菜单管理", permission: "perm:menu" },
|
||||||
component: () =>
|
component: () =>
|
||||||
import("@/modules/admin/views/permissions/PermissionManage.vue"),
|
import("@/modules/admin/views/permissions/PermissionManage.vue"),
|
||||||
},
|
},
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user