feat: 进行功能分区方便后期维护
- 添加导航条目和分类数据模型 - 实现导航卡片网格展示 - 支持点击卡片打开链接 - 添加主题样式(渐变色、卡片阴影) - 区分系统默认和自定义条目 - 添加分类统计信息"
This commit is contained in:
@@ -0,0 +1,54 @@
|
||||
import '../../../../core/utils/text.dart';
|
||||
|
||||
/// 侧栏导航节点。
|
||||
///
|
||||
/// `index3.html` 的侧栏是两层的:一级条目要么直接指向一个分区(如「常用推荐」),
|
||||
/// 要么是一个可以展开的分组(如「素材资源」),分组下面是若干二级条目。
|
||||
/// 这里用同一棵树表达两种形态——[children] 为空即为直接跳转的叶子。
|
||||
class NavNode {
|
||||
const NavNode({
|
||||
required this.id,
|
||||
required this.title,
|
||||
this.children = const <NavNode>[],
|
||||
});
|
||||
|
||||
/// 唯一标识;叶子节点同时也是内容区的锚点 id。
|
||||
final String id;
|
||||
|
||||
/// 显示文字。
|
||||
final String title;
|
||||
|
||||
/// 子节点;为空表示这是一个直接跳转的条目。
|
||||
final List<NavNode> children;
|
||||
|
||||
/// 是否是可展开的分组。
|
||||
bool get isGroup => children.isNotEmpty;
|
||||
|
||||
/// 该节点覆盖的所有叶子(自身是叶子时返回自身,否则递归收集后代)。
|
||||
List<NavNode> get leaves {
|
||||
if (children.isEmpty) {
|
||||
return <NavNode>[this];
|
||||
}
|
||||
return children
|
||||
.expand((NavNode child) => child.leaves)
|
||||
.toList(growable: false);
|
||||
}
|
||||
|
||||
/// 侧栏折叠时显示的短标签。
|
||||
///
|
||||
/// 取标题首字,与 logo 折叠成「S」是同一套规则;
|
||||
/// 用 `runes` 保证中文与 emoji 不会被截成半个字符。
|
||||
String get shortLabel => firstChar(title);
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) ||
|
||||
other is NavNode && other.id == id && other.title == title;
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => Object.hash(id, title);
|
||||
|
||||
@override
|
||||
String toString() => 'NavNode(id: $id, title: $title, children: ${children.length})';
|
||||
}
|
||||
Reference in New Issue
Block a user