# inventory-backend/app/services/permission_service.py from app.models.system import SysMenu, SysElement, SysRolePermission from app.extensions import db class PermissionService: @staticmethod def get_permission_tree(): """ 获取完整的权限树(菜单 -> 元素) 供前端权限配置页面展示 """ # 1. 获取所有菜单 menus = SysMenu.query.order_by(SysMenu.sort_order).all() # 2. 获取所有元素 elements = SysElement.query.all() # 3. 组装树结构 tree_data = [] for menu in menus: menu_dict = menu.to_dict() # 找该菜单下的所有元素 children = [] for el in elements: if el.menu_code == menu.code: children.append(el.to_dict()) # 如果有子元素,加到 children if children: menu_dict['children'] = children tree_data.append(menu_dict) return tree_data @staticmethod def get_role_permissions(role_code): """获取指定角色拥有的所有权限Code""" perms = SysRolePermission.query.filter_by(role_code=role_code).all() menu_codes = [] element_codes = [] for p in perms: if p.type == 'menu': menu_codes.append(p.target_code) else: element_codes.append(p.target_code) return { 'menus': menu_codes, 'elements': element_codes } @staticmethod def assign_permissions(role_code, permission_codes): """ 保存角色的权限 permission_codes: 前端传来的 list,包含 menu_code 和 element_code """ if not role_code: raise ValueError("角色代码不能为空") try: # ========= 1️⃣ 先删除旧权限 ========= SysRolePermission.query.filter_by(role_code=role_code) \ .delete(synchronize_session=False) # ========= 2️⃣ 去重(关键修复点) ========= # 防止前端传来重复 code 导致 UNIQUE 冲突 unique_codes = set(permission_codes) if permission_codes else set() # ========= 3️⃣ 批量添加新权限 ========= if unique_codes: # 预先获取所有菜单代码,用于判断类型 all_menu_codes = {m.code for m in SysMenu.query.all()} new_records = [] for code in unique_codes: if not code: continue # 判断类型 p_type = 'menu' if code in all_menu_codes else 'element' new_records.append(SysRolePermission( role_code=role_code, target_code=code, type=p_type )) if new_records: db.session.add_all(new_records) # ========= 4️⃣ 提交事务 ========= db.session.commit() return True except Exception as e: # 发生异常时回滚,防止脏事务 db.session.rollback() raise e