QinGang_interested/lib/common/route_service.dart

267 lines
8.2 KiB
Dart
Raw Normal View History

2026-03-06 16:15:20 +08:00
// route_service.dart
import 'dart:convert';
import 'package:flutter/foundation.dart';
2025-12-12 09:11:30 +08:00
import 'package:qhd_prevention/common/route_model.dart';
2026-03-06 16:15:20 +08:00
import 'package:qhd_prevention/tools/tools.dart';
class RouteService extends ChangeNotifier {
2025-12-12 09:11:30 +08:00
static final RouteService _instance = RouteService._internal();
factory RouteService() => _instance;
RouteService._internal();
2026-03-06 16:15:20 +08:00
// 存储顶级菜单(直接从接口解析的数组)
2025-12-12 09:11:30 +08:00
List<RouteModel> _allRoutes = [];
2026-03-06 16:15:20 +08:00
/// 对外暴露全部顶级 routes如果需要遍历所有顶级项
List<RouteModel> get allRoutes => _allRoutes;
/// 初始化路由配置(允许传 null
void initializeRoutes(List<dynamic>? routeList) {
_allRoutes = [];
if (routeList == null) return;
for (final item in routeList) {
try {
if (item is Map<String, dynamic>) {
_allRoutes.add(RouteModel.fromJson(item));
} else if (item is Map) {
_allRoutes.add(RouteModel.fromJson(Map<String, dynamic>.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 (_) {}
}
2025-12-12 09:11:30 +08:00
2026-03-06 16:15:20 +08:00
/// 返回所有顶级parentId == '0' 或 parentId 为空的菜单作为主Tab不在这里筛 visible
List<RouteModel> 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;
2025-12-12 09:11:30 +08:00
}
2026-03-06 16:15:20 +08:00
// 遍历查找(按 menuUrl
2025-12-12 09:11:30 +08:00
RouteModel? findRouteByPath(String path) {
2026-03-06 16:15:20 +08:00
if (path.isEmpty) return null;
final needle = path.trim();
2025-12-12 09:11:30 +08:00
for (final route in _allRoutes) {
2026-03-06 16:15:20 +08:00
final found = _findRouteRecursive(route, needle);
2025-12-12 09:11:30 +08:00
if (found != null) return found;
}
return null;
}
RouteModel? _findRouteRecursive(RouteModel route, String path) {
2026-03-06 16:15:20 +08:00
// 如果当前节点不可见,则按照你的要求:不再查找其子级(直接返回 null
if (!route.visible) return null;
final routeUrl = route.menuUrl.trim();
if (routeUrl == path) return route;
2025-12-12 09:11:30 +08:00
for (final child in route.children) {
final found = _findRouteRecursive(child, path);
if (found != null) return found;
}
return null;
}
2026-03-06 16:15:20 +08:00
// 获取某个Tab下的所有可显示路由visible == true且收集叶子节点
2025-12-12 09:11:30 +08:00
List<RouteModel> getRoutesForTab(RouteModel tab) {
final routes = <RouteModel>[];
2026-03-06 16:15:20 +08:00
_collectVisibleLeafRoutes(tab, routes);
2025-12-12 09:11:30 +08:00
return routes;
}
2026-03-06 16:15:20 +08:00
/// 关键修改:如果当前节点不可见,则不再递归其 children按你的要求
void _collectVisibleLeafRoutes(RouteModel route, List<RouteModel> collector) {
if (!route.visible) return; // 如果父节点不可见,跳过整个子树
if (route.isLeaf) {
2025-12-12 09:11:30 +08:00
collector.add(route);
2026-03-06 16:15:20 +08:00
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<String> perms) {
for (final p in perms) {
if (hasPerm(p)) return true;
}
return false;
}
Map<String, bool> permsMap(List<String> perms) {
final Map<String, bool> 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<String> collectAllPerms() {
final List<String> 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<String> 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();
2025-12-12 09:11:30 +08:00
}
}
2026-03-06 16:15:20 +08:00
// 未找到 -> 返回空字符串(调用方需做好空串处理)
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;
2025-12-12 09:11:30 +08:00
}
2026-03-06 16:15:20 +08:00
return null;
2025-12-12 09:11:30 +08:00
}
2026-03-06 16:15:20 +08:00
/// 在整个路由列表中查找 menuPerm 完全匹配的节点(只返回可见节点)
RouteModel? _findRouteInAllByPerm(List<RouteModel> 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 '';
2025-12-12 09:11:30 +08:00
2026-03-06 16:15:20 +08:00
for (final c in children) {
// 若该子节点可见并有 menuUrl直接返回
if ((c.showFlag == 1) && (c.menuUrl ?? '').isNotEmpty) {
return c.menuUrl;
}
// return '';
}
return '';
}
}