feat: 进行功能分区方便后期维护
- 添加导航条目和分类数据模型 - 实现导航卡片网格展示 - 支持点击卡片打开链接 - 添加主题样式(渐变色、卡片阴影) - 区分系统默认和自定义条目 - 添加分类统计信息"
This commit is contained in:
@@ -0,0 +1,59 @@
|
||||
import 'link_item.dart';
|
||||
import 'link_section.dart';
|
||||
import 'nav_node.dart';
|
||||
|
||||
/// 首页一次性需要的全部数据。
|
||||
///
|
||||
/// 打包成一个聚合对象:页面只调用一次仓库、只持有一份状态,
|
||||
/// 后续换成后端接口时也只需要在一个响应里组装出它。
|
||||
class HomeData {
|
||||
const HomeData({
|
||||
required this.siteName,
|
||||
required this.searchHint,
|
||||
required this.navNodes,
|
||||
required this.sections,
|
||||
});
|
||||
|
||||
/// 站点名,显示在侧栏顶部与浏览器标题。
|
||||
final String siteName;
|
||||
|
||||
/// 搜索框占位文案。
|
||||
final String searchHint;
|
||||
|
||||
/// 侧栏导航树。
|
||||
final List<NavNode> navNodes;
|
||||
|
||||
/// 内容区分组。
|
||||
///
|
||||
/// 数量可能少于导航叶子:原型里 `#icon`、`#stock`、`#dev`、`#api`
|
||||
/// 没有对应元素,点击时什么也不会发生。
|
||||
final List<LinkSection> sections;
|
||||
|
||||
/// 导航树里的全部叶子,按自上而下的顺序展开。
|
||||
List<NavNode> get navLeaves => navNodes
|
||||
.expand((NavNode node) => node.leaves)
|
||||
.toList(growable: false);
|
||||
|
||||
/// 全部站点(扁平化)。
|
||||
List<LinkItem> get allItems => <LinkItem>[
|
||||
for (final LinkSection section in sections) ...section.items,
|
||||
];
|
||||
|
||||
/// 站点总数。
|
||||
int get itemCount =>
|
||||
sections.fold(0, (int sum, LinkSection s) => sum + s.itemCount);
|
||||
|
||||
/// 原型把 `.active` 写死在第一个导航条目上,这里取同一个值的来源。
|
||||
String? get activeSectionId =>
|
||||
navLeaves.isEmpty ? null : navLeaves.first.id;
|
||||
|
||||
/// 按 id 取分区;原型里没有对应元素时返回 null。
|
||||
LinkSection? sectionById(String id) {
|
||||
for (final LinkSection section in sections) {
|
||||
if (section.id == id) {
|
||||
return section;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user