feat: 进行功能分区方便后期维护
- 添加导航条目和分类数据模型 - 实现导航卡片网格展示 - 支持点击卡片打开链接 - 添加主题样式(渐变色、卡片阴影) - 区分系统默认和自定义条目 - 添加分类统计信息"
This commit is contained in:
@@ -0,0 +1,24 @@
|
||||
/// 网格列数计算。
|
||||
///
|
||||
/// `index3.html` 的 `.grid` 用的是 CSS Grid 的
|
||||
/// `repeat(auto-fill, minmax(220px, 1fr))`;Flutter 没有等价写法,
|
||||
/// 这里把它的规则换算成「给定可用宽度能放几列」,写成纯函数便于单测。
|
||||
///
|
||||
/// 原型没有媒体查询,所以这里也不做断点分支——宽度由调用方传入。
|
||||
abstract final class AppBreakpoints {
|
||||
/// 给定可用宽度与最小单元宽度,算出网格能放几列。
|
||||
///
|
||||
/// 等价于 CSS:`列数 = floor((可用宽度 + 间距) / (最小单元 + 间距))`。
|
||||
static int gridColumnsFor(
|
||||
double availableWidth, {
|
||||
double minItemWidth = 220,
|
||||
double gap = 16,
|
||||
}) {
|
||||
if (availableWidth <= minItemWidth) {
|
||||
return 1;
|
||||
}
|
||||
final int columns =
|
||||
((availableWidth + gap) / (minItemWidth + gap)).floor();
|
||||
return columns < 1 ? 1 : columns;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,162 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
/// 尺寸与动效常量。
|
||||
///
|
||||
/// 数值逐条对应 `index3.html` 的 CSS 变量与规则,组件里不再出现魔法数字。
|
||||
abstract final class AppSizes {
|
||||
// ---- 侧栏 ----
|
||||
|
||||
/// 侧栏展开宽度(`--sidebar-width`,230px)。
|
||||
static const double sidebarWidth = 230;
|
||||
|
||||
/// 侧栏折叠宽度(`--sidebar-collapsed-width`,64px)。
|
||||
static const double sidebarCollapsedWidth = 64;
|
||||
|
||||
/// 侧栏内边距(`padding: 20px 12px 12px 12px`)。
|
||||
static const double sidebarPaddingTop = 20;
|
||||
static const double sidebarPaddingHorizontal = 12;
|
||||
static const double sidebarPaddingBottom = 12;
|
||||
|
||||
/// 折叠后的左右内边距(`padding: 20px 8px 12px 8px`)。
|
||||
static const double sidebarCollapsedPaddingHorizontal = 8;
|
||||
|
||||
/// logo 区域高度与下方间距(`.sidebar-header`,`height:40px; margin-bottom:24px`)。
|
||||
static const double sidebarHeaderHeight = 40;
|
||||
static const double sidebarHeaderGap = 24;
|
||||
|
||||
/// 侧栏展开 / 折叠的动画(`width .3s cubic-bezier(.4, 0, .2, 1)`)。
|
||||
///
|
||||
/// 该贝塞尔曲线就是 Material 的 standard easing,Flutter 里对应
|
||||
/// [Curves.fastOutSlowIn]。
|
||||
static const Duration sidebarTransition = Duration(milliseconds: 300);
|
||||
|
||||
// ---- 导航项 ----
|
||||
|
||||
/// 导航项圆角(`border-radius: 8px`)。
|
||||
static const double navItemRadius = 8;
|
||||
|
||||
/// 导航项内边距(`.nav-link`,`padding: 11px 16px`)。
|
||||
static const double navItemPaddingVertical = 11;
|
||||
static const double navItemPaddingHorizontal = 16;
|
||||
|
||||
/// 导航项之间的间距(`.nav-item-wrapper`,`margin-bottom: 4px`)。
|
||||
static const double navItemGap = 4;
|
||||
|
||||
/// 折叠状态下导航项的内边距(`padding: 12px 0`)。
|
||||
static const double navItemCollapsedPaddingVertical = 12;
|
||||
|
||||
/// 子菜单项内边距与字号(`.sub-menu .nav-link`,`padding: 8px 16px`)。
|
||||
static const double subNavItemPaddingVertical = 8;
|
||||
static const double subNavItemPaddingHorizontal = 16;
|
||||
|
||||
/// 子菜单相对父级的缩进(`.sub-menu`,`padding-left: 16px`)。
|
||||
static const double subMenuIndent = 16;
|
||||
|
||||
/// 子菜单展开 / 收起的动画时长(`transition: .3s`)。
|
||||
static const Duration subMenuTransition = Duration(milliseconds: 300);
|
||||
|
||||
/// 折叠箭头的点击热区宽度。
|
||||
static const double navArrowBoxWidth = 18;
|
||||
|
||||
// ---- 侧栏底部 ----
|
||||
|
||||
/// 底部分隔线与内边距(`.sidebar-footer`)。
|
||||
static const double sidebarFooterPaddingTop = 12;
|
||||
static const double sidebarFooterMarginTop = 8;
|
||||
|
||||
/// 提交按钮内边距(`.submit-btn`,`padding: 10px 16px`)。
|
||||
static const double submitButtonPaddingVertical = 10;
|
||||
static const double submitButtonPaddingHorizontal = 16;
|
||||
|
||||
// ---- 主内容区 ----
|
||||
|
||||
/// 主内容区内边距(`padding: 24px 40px 40px 40px`)。
|
||||
static const double contentPaddingTop = 24;
|
||||
static const double contentPaddingHorizontal = 40;
|
||||
static const double contentPaddingBottom = 40;
|
||||
|
||||
// ---- 顶部控制栏 ----
|
||||
|
||||
/// 顶栏最大宽度与垂直间距(`.top-bar`,`max-width: 750px; margin-bottom: 36px`)。
|
||||
static const double topBarMaxWidth = 750;
|
||||
static const double topBarGap = 16;
|
||||
static const double topBarMarginBottom = 36;
|
||||
|
||||
/// 折叠按钮尺寸与圆角(`.toggle-btn`,44×44,圆角 12px)。
|
||||
static const double toggleButtonSize = 44;
|
||||
static const double toggleButtonRadius = 12;
|
||||
|
||||
// ---- 搜索框 ----
|
||||
|
||||
/// 搜索框高度与内边距(`.search-box`,`height:44px; padding: 0 20px`)。
|
||||
static const double searchHeight = 44;
|
||||
static const double searchPaddingHorizontal = 20;
|
||||
|
||||
/// 搜索框圆角(`border-radius: 12px`)。
|
||||
static const double searchRadius = 12;
|
||||
|
||||
/// 聚焦光晕宽度(`0 0 0 3px`)。
|
||||
static const double focusRingWidth = 3;
|
||||
|
||||
// ---- 分组与卡片 ----
|
||||
|
||||
/// 分组标题与网格之间的间距(`margin-bottom: 16px`)。
|
||||
static const double sectionTitleGap = 16;
|
||||
|
||||
/// 标题前的竖条尺寸(`width: 4px; height: 16px`)。
|
||||
static const double sectionAccentWidth = 4;
|
||||
static const double sectionAccentHeight = 16;
|
||||
|
||||
/// 竖条与标题文字的间距(`margin-right: 8px`)。
|
||||
static const double sectionAccentGap = 8;
|
||||
|
||||
/// 竖条圆角(`border-radius: 2px`)。
|
||||
static const double sectionAccentRadius = 2;
|
||||
|
||||
/// 分组之间的间距(`.grid` 的 `margin-bottom: 36px`)。
|
||||
static const double sectionGap = 36;
|
||||
|
||||
/// 网格间距(`gap: 16px`)。
|
||||
static const double gridGap = 16;
|
||||
|
||||
/// 网格单元最小宽度(`minmax(220px, 1fr)`)。
|
||||
static const double gridMinItemWidth = 220;
|
||||
|
||||
/// 卡片圆角(`border-radius: 10px`)。
|
||||
static const double cardRadius = 10;
|
||||
|
||||
/// 卡片内边距(`padding: 14px 16px`)。
|
||||
static const double cardPaddingVertical = 14;
|
||||
static const double cardPaddingHorizontal = 16;
|
||||
|
||||
/// 卡片悬停时上移的距离(`translateY(-2px)`)。
|
||||
static const double cardHoverLift = 2;
|
||||
|
||||
/// 卡片图标尺寸(`.card-icon`,36px)。
|
||||
static const double cardIconSize = 36;
|
||||
|
||||
/// 卡片图标圆角(`border-radius: 8px`)。
|
||||
static const double cardIconRadius = 8;
|
||||
|
||||
/// 图标与文字之间的间距(`margin-right: 12px`)。
|
||||
static const double cardIconGap = 12;
|
||||
|
||||
/// 卡片标题与描述的间距(`margin-top: 2px`)。
|
||||
static const double cardTitleGap = 2;
|
||||
|
||||
// ---- 回到顶部 ----
|
||||
|
||||
/// 按钮尺寸(`.back-to-top`,44×44,圆角 50%)。
|
||||
static const double backToTopSize = 44;
|
||||
|
||||
/// 距视口右下角的距离(`bottom: 30px; right: 30px`)。
|
||||
static const double backToTopOffset = 30;
|
||||
|
||||
/// 悬停时上移距离(`translateY(-3px)`)。
|
||||
static const double backToTopHoverLift = 3;
|
||||
|
||||
// ---- 通用 ----
|
||||
|
||||
/// 通用过渡时长(CSS 里的 `transition: 0.2s`)。
|
||||
static const Duration transition = Duration(milliseconds: 200);
|
||||
}
|
||||
Reference in New Issue
Block a user