QinGang_interested/lib/common/route_service.dart

267 lines
8.2 KiB
Dart
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

// 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<RouteModel> _allRoutes = [];
/// 对外暴露全部顶级 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 (_) {}
}
/// 返回所有顶级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;
}
// 遍历查找(按 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<RouteModel> getRoutesForTab(RouteModel tab) {
final routes = <RouteModel>[];
_collectVisibleLeafRoutes(tab, routes);
return routes;
}
/// 关键修改:如果当前节点不可见,则不再递归其 children按你的要求
void _collectVisibleLeafRoutes(RouteModel route, List<RouteModel> 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<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();
}
}
// 未找到 -> 返回空字符串(调用方需做好空串处理)
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<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 '';
for (final c in children) {
// 若该子节点可见并有 menuUrl直接返回
if ((c.showFlag == 1) && (c.menuUrl ?? '').isNotEmpty) {
return c.menuUrl;
}
// return '';
}
return '';
}
}