Files
xianyan/lib/core/services/recent_route_service.dart
Developer f91be94e9c refactor: 完成项目架构重构,统一模块导入路径
- 清理大量废弃的 barrel 导出文件,移除冗余的中间导出层
- 修复所有相对路径导入错误,统一调整为扁平化模块引用
- 更新多平台 pubspec 版本号与依赖库版本
- 补充后端功能问题管理后台与脚本工具
- 调整部分页面的快捷方式文案适配新功能
- 更新部分翻译覆盖率与API文档
2026-06-12 08:53:57 +08:00

144 lines
4.5 KiB
Dart
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// ============================================================
// 闲言APP — 最近路由服务(单一数据源)
// 创建时间: 2026-05-24
// 更新时间: 2026-06-12
// 作用: 统一管理最近访问路由和自定义路由消除KvStorage双写问题
// 上次更新: 从 navigation/ 子目录上移至 services/ 目录
// ============================================================
import 'dart:convert';
import 'package:xianyan/core/storage/kv_storage.dart';
import 'package:xianyan/core/utils/logger.dart';
import 'package:xianyan/core/utils/safe_json.dart';
class RecentRouteService {
static const _kRecentRoutes = 'tool_center_recent_routes';
static const _kCustomRoute = 'tool_center_custom_route';
static const _kRouteCounts = 'tool_center_route_counts';
static const _maxRecentCount = 10;
/// 已知的动态路由前缀,归一化时截取到此前缀长度
static const _dynamicRoutePrefixes = <String>[
'/chat-flow/',
'/chat-settings/',
'/article/',
'/category/',
'/user/',
'/weather/',
'/poetry/',
'/daily-fortune/',
'/tool/',
'/about/',
'/transfer-chat/',
];
/// 归一化路由:将动态段路由转换为基础路由
/// 例如 /chat-flow/123 → /chat-flow, /editor?text=xxx → /editor
static String _normalizeRoute(String route) {
var normalized = route;
final queryIndex = normalized.indexOf('?');
if (queryIndex > 0) {
normalized = normalized.substring(0, queryIndex);
}
for (final prefix in _dynamicRoutePrefixes) {
if (normalized.startsWith(prefix) && normalized.length > prefix.length) {
return prefix.substring(0, prefix.length - 1);
}
}
if (normalized.endsWith('/') && normalized.length > 1) {
normalized = normalized.substring(0, normalized.length - 1);
}
return normalized;
}
static List<String> getRecentRoutes() {
try {
final raw = KvStorage.getString(_kRecentRoutes);
if (raw != null && raw.isNotEmpty) {
final decoded = jsonDecode(raw) as List<dynamic>;
return decoded.map((e) => e.toString()).toList();
}
} catch (e) {
Log.w('最近路由: 读取失败 $e');
}
return [];
}
static Future<void> addRecentRoute(String route) async {
final normalized = _normalizeRoute(route);
if (normalized.isEmpty || normalized == '/' || normalized.startsWith('/onboarding')) return;
try {
final updated = List<String>.from(getRecentRoutes())
..remove(normalized)
..insert(0, normalized);
if (updated.length > _maxRecentCount) {
updated.removeRange(_maxRecentCount, updated.length);
}
await KvStorage.setString(_kRecentRoutes, jsonEncode(updated));
_incrementRouteCount(normalized);
} catch (e) {
Log.w('最近路由: 记录失败 $e');
}
}
static String? getCustomRoute() {
try {
return KvStorage.getString(_kCustomRoute);
} catch (e) {
return null;
}
}
static Future<void> setCustomRoute(String route) async {
try {
await KvStorage.setString(_kCustomRoute, route);
} catch (e) {
Log.e('最近路由: 保存自定义路由失败 $e');
}
}
/// 删除指定路由(归一化后匹配)
static Future<void> removeRecentRoute(String route) async {
final normalized = _normalizeRoute(route);
try {
final updated = List<String>.from(getRecentRoutes())..remove(normalized);
await KvStorage.setString(_kRecentRoutes, jsonEncode(updated));
Log.i('最近路由: 删除 → $normalized');
} catch (e) {
Log.w('最近路由: 删除失败 $e');
}
}
static Map<String, int> getRouteCounts() {
try {
final raw = KvStorage.getString(_kRouteCounts);
if (raw != null && raw.isNotEmpty) {
final decoded = jsonDecode(raw) as Map<String, dynamic>;
return decoded.map((k, v) => MapEntry(k, SafeJson.parseInt(v)));
}
} catch (e) {
Log.w('最近路由: 读取访问次数失败 $e');
}
return {};
}
static List<String> getFrequentRoutes() {
final counts = getRouteCounts();
if (counts.isEmpty) return getRecentRoutes();
final sorted = counts.entries.toList()
..sort((a, b) => b.value.compareTo(a.value));
return sorted.map((e) => e.key).toList();
}
static void _incrementRouteCount(String route) {
try {
final counts = getRouteCounts();
counts[route] = (counts[route] ?? 0) + 1;
KvStorage.setString(_kRouteCounts, jsonEncode(counts));
} catch (e) {
Log.w('最近路由: 更新访问次数失败 $e');
}
}
}