diff --git a/inventory-backend/app/__init__.py b/inventory-backend/app/__init__.py index 8985260..461b127 100644 --- a/inventory-backend/app/__init__.py +++ b/inventory-backend/app/__init__.py @@ -161,6 +161,8 @@ def create_app(): PermissionService.cleanup_legacy_stocktake_menus() PermissionService.init_audit_menu() PermissionService.init_stocktake_menus() + # 初始化所有菜单的层级结构 + PermissionService.init_all_menus() except Exception as e: print(f"⚠️ 菜单初始化跳过: {e}") diff --git a/inventory-backend/app/services/permission_service.py b/inventory-backend/app/services/permission_service.py index 16bacf1..805dea3 100644 --- a/inventory-backend/app/services/permission_service.py +++ b/inventory-backend/app/services/permission_service.py @@ -388,3 +388,111 @@ class PermissionService: db.session.rollback() print(f"⚠️ 清理旧版菜单失败: {str(e)}") return False + + @staticmethod + def init_all_menus(): + """ + 初始化所有菜单的层级结构,确保权限配置页面显示正确的树形结构 + 按照侧边栏顺序:基础信息 -> 入库 -> 盘点 -> 出库 -> BOM -> 借库 -> 报废 -> 系统 + """ + try: + role_code = 'SUPER_ADMIN' + + # 定义菜单结构 (code, name, path, parent_code, sort_order) + menu_defs = [ + # 顶级菜单 (按侧边栏顺序) + ('material_mgmt', '基础信息管理', '/material', None, 10), + ('inventory_mgmt', '入库管理', '/inventory', None, 20), + ('stocktake_mgmt', '盘点管理', '/stocktake', None, 30), + ('outbound_mgmt', '出库管理', '/outbound', None, 40), + ('bom_mgmt', 'BOM管理', '/bom', None, 50), + ('operation_mgmt', '借库管理', '/operation', None, 60), + ('scrap_mgmt', '报废管理', '/scrap', None, 70), + ('system_mgmt', '系统管理', '/system', None, 80), + + # 基础信息子菜单 + ('material_base', '基础信息', '/material/index', 'material_mgmt', 1), + + # 入库管理子菜单 + ('inbound_buy', '采购入库', '/inventory/buy', 'inventory_mgmt', 1), + ('inbound_semi', '半成品入库', '/inventory/semi', 'inventory_mgmt', 2), + ('inbound_product', '成品入库', '/inventory/product', 'inventory_mgmt', 3), + ('inbound_service', '服务权益', '/inventory/service', 'inventory_mgmt', 4), + ('inbound_summary', '入库记录', '/inventory/summary', 'inventory_mgmt', 5), + + # 盘点管理子菜单 + ('inventory_stocktake', '盲盘作业', '/stocktake/operation', 'stocktake_mgmt', 1), + ('stock_adjustment', '盈亏调整', '/stocktake/adjustment', 'stocktake_mgmt', 2), + + # 出库管理子菜单 + ('outbound_selection', '出库选单', '/outbound/selection', 'outbound_mgmt', 1), + ('outbound_create', '扫码出库', '/outbound/create', 'outbound_mgmt', 2), + ('outbound_list', '出库记录', '/outbound/index', 'outbound_mgmt', 3), + + # BOM管理子菜单 + ('bom_manage', 'BOM配方管理', '/bom/manage', 'bom_mgmt', 1), + + # 借库管理子菜单 + ('op_borrow', '借库操作', '/operation/borrow', 'operation_mgmt', 1), + ('op_return', '归还操作', '/operation/repair', 'operation_mgmt', 2), + ('op_records', '借还记录', '/operation/records', 'operation_mgmt', 3), + + # 报废管理子菜单 + ('scrap_create', '新建报废', '/scrap/create', 'scrap_mgmt', 1), + ('scrap_list', '报废记录', '/scrap/index', 'scrap_mgmt', 2), + + # 系统管理子菜单 + ('system_user', '员工账号管理', '/system/user-create', 'system_mgmt', 1), + ('system_permission', '权限分配', '/system/permission', 'system_mgmt', 2), + ('system_audit', '审计日志', '/system/audit', 'system_mgmt', 3), + ] + + # 创建或更新菜单 + menu_map = {} # code -> menu obj + + for code, name, path, parent_code, sort_order in menu_defs: + menu = SysMenu.query.filter_by(code=code).first() + if not menu: + menu = SysMenu(code=code, name=name, path=path, sort_order=sort_order, is_visible=True) + db.session.add(menu) + db.session.flush() + print(f"✅ 菜单已创建: {name} ({code})") + else: + # 更新已有菜单的属性 + menu.name = name + menu.path = path + menu.sort_order = sort_order + + menu_map[code] = menu + + # 设置 parent_id + for code, name, path, parent_code, sort_order in menu_defs: + if parent_code and parent_code in menu_map: + menu = menu_map[code] + parent = menu_map[parent_code] + menu.parent_id = parent.id + + # 为超级管理员分配所有菜单权限 + for code, name, path, parent_code, sort_order in menu_defs: + if parent_code is None: # 只分配顶级菜单 + existing_perm = SysRolePermission.query.filter_by( + role_code=role_code, + target_code=code, + type='menu' + ).first() + if not existing_perm: + new_perm = SysRolePermission( + role_code=role_code, + target_code=code, + type='menu' + ) + db.session.add(new_perm) + + db.session.commit() + print(f"✅ 所有菜单初始化完成") + return True + + except Exception as e: + db.session.rollback() + print(f"❌ 初始化菜单失败: {str(e)}") + raise e