feat(role): 新增角色权限分配功能并优化界面显示

refactor(menu): 重构菜单类型枚举和权限数据结构
fix(log): 修复日志类型显示和查询问题
style(common): 重命名部门树格式化函数为通用树格式化函数
perf(store): 移除控制台日志输出
docs(tsconfig): 添加Vite客户端类型注释
chore(package): 调整依赖项顺序
This commit is contained in:
zhangtao
2025-07-20 15:39:00 +08:00
parent 5de06e5bc6
commit 7204e011d9
33 changed files with 1507 additions and 1034 deletions
@@ -39,7 +39,7 @@ class MenuModel(ModelBase):
keep_alive = Column(Boolean, default=True, nullable=False, comment="是否缓存(True:是 False:否)")
always_show = Column(Boolean, default=False, nullable=False, comment="是否始终显示(True:是 False:否)")
title = Column(String(50), nullable=True, comment="菜单标题")
params = Column(String(200), nullable=True, comment="路由参数")
params = Column(Text, nullable=True, comment="路由参数(JSON数组: [{\"key\": \"\", \"value\": \"\"}])")
affix = Column(Boolean, default=False, nullable=False, comment="是否固定标签页(True:是 False:否)")
# 层级关系
@@ -13,6 +13,7 @@ class OperationLogModel(ModelBase):
__table_args__ = ({'comment': '操作日志表'})
id = Column(Integer, primary_key=True, autoincrement=True, comment='主键ID')
type = Column(Integer, nullable=True, comment="日志类型(1登录日志 2操作日志)", index=True)
request_path = Column(String(255), nullable=True, comment="请求路径", index=True)
request_method = Column(String(10), nullable=True, comment="请求方式", index=True)
request_payload = Column(Text, nullable=True, comment="请求体")
@@ -11,6 +11,7 @@ class OperationLogQueryParams:
def __init__(
self,
type: Optional[int] = Query(None, description="日志类型(1:登录日志, 2:操作日志)"),
request_path: Optional[str] = Query(None, description="请求路径"),
request_method: Optional[str] = Query(None, description="请求方法"),
request_ip: Optional[str] = Query(None, description="请求IP"),
@@ -29,6 +30,7 @@ class OperationLogQueryParams:
self.request_method = request_method
self.request_ip = request_ip
self.response_code = response_code
self.type = type
# 时间范围查询
if start_time and end_time:
@@ -10,7 +10,7 @@ from app.core.base_schema import BaseSchema
class MenuCreateSchema(BaseModel):
"""菜单创建模型"""
name: str = Field(..., max_length=50, description="菜单名称")
type: int = Field(..., ge=1, le=3, description="菜单类型(1:目录 2:菜单 3:按钮)")
type: int = Field(..., ge=1, le=4, description="菜单类型(1:目录 2:菜单 3:按钮 4:外链)")
icon: Optional[str] = Field(default=None, max_length=100, description="菜单图标")
order: int = Field(default=1, ge=0, description="显示顺序")
permission: Optional[str] = Field(default=None, max_length=100, description="权限标识")
@@ -23,7 +23,7 @@ class MenuCreateSchema(BaseModel):
hidden: bool = Field(default=False, description="是否隐藏(True:是 False:否)")
always_show: bool = Field(default=False, description="是否始终显示(True:是 False:否)")
title: Optional[str] = Field(default=None, max_length=50, description="菜单标题")
params: Optional[str] = Field(default=None, max_length=200, description="路由参数")
params: Optional[list[dict[str, str]]] = Field(default=None, description="路由参数,格式为[{key: string, value: string}]")
affix: bool = Field(default=False, description="是否固定标签页(True:是 False:否)")
parent_id: Optional[int] = Field(default=None, ge=0, description="父菜单ID")
description: Optional[str] = Field(default=None, max_length=500, description="备注说明")
@@ -8,6 +8,7 @@ from app.core.base_schema import BaseSchema
class OperationLogCreateSchema(BaseModel):
"""日志创建模型"""
type: Optional[int] = Field(default=None, description="日志类型(1登录日志 2操作日志)")
request_path: Optional[str] = Field(default=None, description="请求路径")
request_method: Optional[str] = Field(default=None, description="请求方法")
request_payload: Optional[str] = Field(default=None, description="请求负载")
@@ -65,6 +65,7 @@ class OperationLogService:
# 操作日志字段映射
mapping_dict = {
'id': '编号',
'type': '日志类型',
'request_path': '请求URL',
'request_method': '请求方式',
'request_payload': '请求参数',
@@ -87,5 +88,7 @@ class OperationLogService:
for item in data:
# 处理状态
item['response_code'] = '成功' if item.get('response_code') == 200 else '失败'
# 处理日志类型
item['type'] = '操作日志' if item.get('type') == 1 else '登录日志'
return ExcelUtil.export_list2excel(list_data=operation_log_list, mapping_dict=mapping_dict)
+3
View File
@@ -60,9 +60,11 @@ class OperationLogRoute(APIRoute):
process_time = time.time() - start_time
# 获取当前用户ID,如果是登录接口则为空
log_type = 1 # 1:登录日志 2:操作日志
current_user_id = None
if "user_id" in request.scope:
current_user_id = request.scope.get("user_id")
log_type = 2
request_ip = None
x_forwarded_for = request.headers.get('X-Forwarded-For')
@@ -81,6 +83,7 @@ class OperationLogRoute(APIRoute):
auth = AuthSchema(db=session)
await OperationLogService.create_log_service(data=OperationLogCreateSchema(
type = log_type,
request_path = request.url.path,
request_method = request.method,
request_payload = payload,
+3 -3
View File
@@ -1500,7 +1500,7 @@
"route_name": null,
"route_path": null,
"component_path": null,
"parent_id": 62,
"parent_id": 71,
"status": true,
"keep_alive": false,
"hidden": false,
@@ -1535,7 +1535,7 @@
{
"id": 74,
"name": "接口管理",
"type": 2,
"type": 4,
"icon": "api",
"order": 1,
"permission": "common:docs:query",
@@ -1556,7 +1556,7 @@
{
"id": 75,
"name": "文档管理",
"type": 2,
"type": 4,
"icon": "el-icon-Document",
"order": 2,
"permission": "common:redoc:query",