// route_service.dart import 'dart:convert'; import 'package:flutter/foundation.dart'; import 'package:qhd_prevention/common/route_model.dart'; import 'package:qhd_prevention/tools/tools.dart'; class RouteService extends ChangeNotifier { static final RouteService _instance = RouteService._internal(); factory RouteService() => _instance; RouteService._internal(); // 存储顶级菜单(直接从接口解析的数组) List _allRoutes = []; /// 对外暴露全部顶级 routes(如果需要遍历所有顶级项) List get allRoutes => _allRoutes; /// 初始化路由配置(允许传 null) void initializeRoutes(List? routeList) { _allRoutes = []; if (routeList == null) return; for (final item in routeList) { try { if (item is Map) { _allRoutes.add(RouteModel.fromJson(item)); } else if (item is Map) { _allRoutes.add(RouteModel.fromJson(Map.from(item))); } } catch (e) { debugPrint('RouteService: parse route item failed: $e'); } } // 对顶级和子节点进行排序(如果有 sort 字段) try { _allRoutes.sort((a, b) => a.sort.compareTo(b.sort)); for (final r in _allRoutes) { _sortRecursive(r); } } catch (_) {} notifyListeners(); } void _sortRecursive(RouteModel node) { try { node.children.sort((a, b) => a.sort.compareTo(b.sort)); for (final c in node.children) { _sortRecursive(c); } } catch (_) {} } /// 返回所有顶级(parentId == '0' 或 parentId 为空)的菜单作为主Tab(不在这里筛 visible) List get mainTabs { final tabs = _allRoutes.where((m) { final isTop = m.parentId == '0' || m.parentId.isEmpty; return isTop && m.visible; // 只取可见的顶级项 }).toList(); try { tabs.sort((a, b) => a.sort.compareTo(b.sort)); } catch (_) {} return tabs; } // 遍历查找(按 menuUrl) RouteModel? findRouteByPath(String path) { if (path.isEmpty) return null; final needle = path.trim(); for (final route in _allRoutes) { final found = _findRouteRecursive(route, needle); if (found != null) return found; } return null; } RouteModel? _findRouteRecursive(RouteModel route, String path) { // 如果当前节点不可见,则按照你的要求:不再查找其子级(直接返回 null) if (!route.visible) return null; final routeUrl = route.menuUrl.trim(); if (routeUrl == path) return route; for (final child in route.children) { final found = _findRouteRecursive(child, path); if (found != null) return found; } return null; } // 获取某个Tab下的所有可显示路由(visible == true,且收集叶子节点) List getRoutesForTab(RouteModel tab) { final routes = []; _collectVisibleLeafRoutes(tab, routes); return routes; } /// 关键修改:如果当前节点不可见,则不再递归其 children(按你的要求) void _collectVisibleLeafRoutes(RouteModel route, List collector) { if (!route.visible) return; // 如果父节点不可见,跳过整个子树 if (route.isLeaf) { collector.add(route); return; } for (final child in route.children) { _collectVisibleLeafRoutes(child, collector); } } // --------------------- 权限检查相关 --------------------- /// 判断整个路由树(所有顶级及其子孙)是否存在 menuPerms == perm 且可见的节点 /// 如果父节点不可见,会跳过该父及其子树(按你的要求) bool hasPerm(String perm) { if (perm.isEmpty) return false; final needle = perm.trim(); bool found = false; void visit(RouteModel m) { if (found) return; // 若父节点不可见,跳过(不再遍历子节点) if (!m.visible) return; final mp = (m.menuPerms ?? '').trim(); if (mp.isNotEmpty && mp == needle) { found = true; return; } for (final c in m.children) { visit(c); if (found) return; } } for (final top in _allRoutes) { visit(top); if (found) break; } return found; } bool hasAnyPerms(List perms) { for (final p in perms) { if (hasPerm(p)) return true; } return false; } Map permsMap(List perms) { final Map map = {}; for (final p in perms) { map[p] = hasPerm(p); } return map; } /// 尝试按 menuPerms 找到第一个匹配的 RouteModel(若需要路由信息) /// 如果某个父节点不可见,则不会进入其子树 RouteModel? findRouteByPerm(String perm) { if (perm.isEmpty) return null; final needle = perm.trim(); RouteModel? result; void visit(RouteModel m) { // printLongString(json.encode(m.toJson())); if (result != null) return; if (!m.visible) return; // 父不可见,跳过 final mp = (m.menuPerms ?? '').trim(); if (mp.isNotEmpty && mp == needle) { result = m; return; } for (final c in m.children) { visit(c); if (result != null) return; } } for (final top in _allRoutes) { visit(top); if (result != null) break; } return result; } /// 可返回所有收集到的 menuPerms(仅包含可见节点及其可见子节点) List collectAllPerms() { final List perms = []; void visit(RouteModel m) { if (!m.visible) return; // 父不可见则跳过子树 final mp = (m.menuPerms ?? '').trim(); if (mp.isNotEmpty) perms.add(mp); for (final c in m.children) visit(c); } for (final top in _allRoutes) visit(top); return perms; } /// 严格查找某个子树(仅包含可见节点及其可见子节点) static Future getMenuPath(parentPerm,targetPerm) async { try { final routeService = RouteService(); // 如果子节点为'',那么查父节点children中第一个 if (targetPerm.isEmpty) { final route = routeService.findRouteByPerm(parentPerm); if (route != null) { // 优先在该节点的子孙中找第一个可见且有 menuUrl 的节点 final childUrl = findFirstVisibleChildUrl(route); if (childUrl.isNotEmpty) return childUrl; return ''; } } //branchCompany-plan-execute-inspection-records RouteModel? parent = routeService.findRouteByPerm(parentPerm); if (parent != null) { // 在 parent 子树中严格查找 targetPerm final RouteModel? foundInParent = _findRouteInSubtreeByPerm(parent, targetPerm); if (foundInParent != null && foundInParent.menuUrl.trim().isNotEmpty) { return foundInParent.menuUrl.trim(); } } // 未找到 -> 返回空字符串(调用方需做好空串处理) return ''; } catch (e, st) { debugPrint('_getMenuPath error: $e\n$st'); return ''; } } /// 在给定节点的子树中(含自身)查找 menuPerm 完全匹配的节点(只返回可见节点) static RouteModel? _findRouteInSubtreeByPerm(RouteModel node, String perm) { if (node.menuPerms.trim() == perm && node.visible) return node; for (final c in node.children) { final res = _findRouteInSubtreeByPerm(c, perm); if (res != null) return res; } return null; } /// 在整个路由列表中查找 menuPerm 完全匹配的节点(只返回可见节点) RouteModel? _findRouteInAllByPerm(List roots, String perm) { for (final r in roots) { final res = _findRouteInSubtreeByPerm(r, perm); if (res != null) return res; } return null; } /// 递归在 node 的子孙中按顺序查找第一个 visible 且有 menuUrl 的节点 /// 如果没找到返回空字符串 static String findFirstVisibleChildUrl(RouteModel node) { final children = node.children; if (children == null || children.isEmpty) return ''; for (final c in children) { // 若该子节点可见并有 menuUrl,直接返回 if ((c.showFlag == 1) && (c.menuUrl ?? '').isNotEmpty) { return c.menuUrl; } // return ''; } return ''; } }