feat: 进行功能分区方便后期维护
- 添加导航条目和分类数据模型 - 实现导航卡片网格展示 - 支持点击卡片打开链接 - 添加主题样式(渐变色、卡片阴影) - 区分系统默认和自定义条目 - 添加分类统计信息"
This commit is contained in:
@@ -0,0 +1,93 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import '../../../../core/constants/app_breakpoints.dart';
|
||||
import '../../../../core/constants/app_sizes.dart';
|
||||
import '../../../../core/theme/app_colors.dart';
|
||||
import '../../../../core/theme/app_text_styles.dart';
|
||||
import '../../domain/models/link_item.dart';
|
||||
import '../../domain/models/link_section.dart';
|
||||
import 'link_card.dart';
|
||||
|
||||
/// 一个分组:标题 + 自适应网格。
|
||||
class LinkSectionView extends StatelessWidget {
|
||||
const LinkSectionView({
|
||||
super.key,
|
||||
required this.section,
|
||||
required this.onOpen,
|
||||
});
|
||||
|
||||
/// 分组数据。
|
||||
final LinkSection section;
|
||||
|
||||
/// 打开某个站点。
|
||||
final ValueChanged<LinkItem> onOpen;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: <Widget>[
|
||||
_SectionTitle(title: section.title),
|
||||
const SizedBox(height: AppSizes.sectionTitleGap),
|
||||
LayoutBuilder(
|
||||
builder: (BuildContext context, BoxConstraints constraints) {
|
||||
final int columns = AppBreakpoints.gridColumnsFor(
|
||||
constraints.maxWidth,
|
||||
minItemWidth: AppSizes.gridMinItemWidth,
|
||||
gap: AppSizes.gridGap,
|
||||
);
|
||||
final double itemWidth =
|
||||
(constraints.maxWidth - AppSizes.gridGap * (columns - 1)) /
|
||||
columns;
|
||||
|
||||
return Wrap(
|
||||
spacing: AppSizes.gridGap,
|
||||
runSpacing: AppSizes.gridGap,
|
||||
children: <Widget>[
|
||||
for (final LinkItem item in section.items)
|
||||
SizedBox(
|
||||
width: itemWidth,
|
||||
child: LinkCard(item: item, onOpen: () => onOpen(item)),
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// 分组标题:左侧一条 4×16 的主色竖条 + 文字(`.section-title::before`)。
|
||||
class _SectionTitle extends StatelessWidget {
|
||||
const _SectionTitle({required this.title});
|
||||
|
||||
final String title;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Row(
|
||||
children: <Widget>[
|
||||
Container(
|
||||
width: AppSizes.sectionAccentWidth,
|
||||
height: AppSizes.sectionAccentHeight,
|
||||
decoration: BoxDecoration(
|
||||
color: AppColors.primary,
|
||||
borderRadius: BorderRadius.circular(AppSizes.sectionAccentRadius),
|
||||
),
|
||||
),
|
||||
const SizedBox(width: AppSizes.sectionAccentGap),
|
||||
// 用 Flexible 包住:窄屏(侧栏展开后主内容只剩一百多像素)时
|
||||
// 「素材资源 - UI 设计」这类长标题会溢出,这里退化成省略号。
|
||||
Flexible(
|
||||
child: Text(
|
||||
title,
|
||||
style: AppTextStyles.sectionTitle,
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user