feat(admin): 新增全套运营管理功能,修复核心路由bug及后端seed问题

修复Vue Admin布局中RouterView未绑定唯一key的问题,解决RBAC系统资源页面切换后内容不刷新的ISSUE-001故障,新增routeViewKey工具函数区分路由实例
完善路由配置,新增admin空路径路由,修复路由命名空路径告警
新增媒体管理、运维发布/重置页面,补全全站路由注册与动态路由过滤逻辑
新增玩法、线索、管家、系统资源管理的全套工具函数、业务组件及单元测试用例
修复后端app/seed.py中媒体资源重复检测未考虑会话内pending资源的bug,新增对应测试验证修复逻辑
修正alembic迁移版本0015的依赖关系,删除废弃的旧迁移文件
优化后端系统接口的字典序列化逻辑,简化重复代码
添加QA验收报告与相关测试截图,完善项目测试覆盖
This commit is contained in:
duanshuwen committed 2026-08-26 18:48:48 +08:00
1 parent fa6fd2a8eb
commit efab6d1398
73 files changed
+3963 -788

No files matched your search

+6 -32
View File
@@ -61,47 +61,21 @@ def _audit(db: Session, request: Request, action: str, entity: str, entity_id: s
def _role_dict(role: AdminRole, menu_ids: list[str] | None = None, dept_ids: list[str] | None = None) -> dict:
return {
"id": role.id,
"name": role.name,
"code": role.code,
"dataScope": role.dataScope,
"description": role.description,
"isActive": role.isActive,
**model_dict(role),
"menuIds": menu_ids or [],
"deptIds": dept_ids or [],
"createdAt": role.createdAt,
"updatedAt": role.updatedAt,
}
def _menu_dict(menu: AdminMenu) -> dict:
return {
"id": menu.id,
"parentId": menu.parentId,
"name": menu.name,
"type": menu.type,
"path": menu.path,
"component": menu.componentKey,
"permission": menu.permissionCode,
"icon": menu.icon,
"sortOrder": menu.sortOrder,
"isVisible": menu.isVisible,
"isActive": menu.isActive,
"createdAt": menu.createdAt,
"updatedAt": menu.updatedAt,
}
data = model_dict(menu)
data["component"] = data.pop("componentKey")
data["permission"] = data.pop("permissionCode")
return data
def _dept_dict(dept: AdminDepartment) -> dict:
return {
"id": dept.id,
"parentId": dept.parentId,
"name": dept.name,
"sortOrder": dept.sortOrder,
"isActive": dept.isActive,
"createdAt": dept.createdAt,
"updatedAt": dept.updatedAt,
}
return model_dict(dept)
def _ensure_ids_exist(db: Session, model, ids: list[str], label: str) -> None:
+2
View File
@@ -24,6 +24,8 @@ def create_media(db: Session, url: str | None, group: str, name: str | None = No
if not url:
return
media = db.scalar(select(MediaAsset).where(MediaAsset.url == url))
if media is None:
media = next((item for item in db.new if isinstance(item, MediaAsset) and item.url == url), None)
if media:
media.group = group
media.name = name