feat: 进行功能分区方便后期维护
- 添加导航条目和分类数据模型 - 实现导航卡片网格展示 - 支持点击卡片打开链接 - 添加主题样式(渐变色、卡片阴影) - 区分系统默认和自定义条目 - 添加分类统计信息"
This commit is contained in:
@@ -0,0 +1,116 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import '../../../../core/constants/app_sizes.dart';
|
||||
import '../../../../core/theme/app_colors.dart';
|
||||
import 'link_search_field.dart';
|
||||
|
||||
/// 顶部控制栏:折叠按钮 + 搜索框。
|
||||
///
|
||||
/// 对应 `index3.html` 的 `.top-bar`:整体宽 750px 并且**水平居中**
|
||||
/// (`margin: 0 auto 36px auto`),下方与第一组卡片留 36px。
|
||||
class TopBar extends StatelessWidget {
|
||||
const TopBar({
|
||||
super.key,
|
||||
required this.searchController,
|
||||
required this.searchHint,
|
||||
required this.sidebarCollapsed,
|
||||
required this.onToggleSidebar,
|
||||
});
|
||||
|
||||
/// 搜索框控制器。
|
||||
final TextEditingController searchController;
|
||||
|
||||
/// 搜索框占位文案。
|
||||
final String searchHint;
|
||||
|
||||
/// 侧栏当前是否折叠,用于按钮的提示文案。
|
||||
final bool sidebarCollapsed;
|
||||
|
||||
/// 折叠 / 展开侧栏。
|
||||
final VoidCallback onToggleSidebar;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.only(bottom: AppSizes.topBarMarginBottom),
|
||||
child: Center(
|
||||
child: ConstrainedBox(
|
||||
constraints: const BoxConstraints(
|
||||
maxWidth: AppSizes.topBarMaxWidth,
|
||||
),
|
||||
child: Row(
|
||||
children: <Widget>[
|
||||
_ToggleButton(
|
||||
collapsed: sidebarCollapsed,
|
||||
onTap: onToggleSidebar,
|
||||
),
|
||||
const SizedBox(width: AppSizes.topBarGap),
|
||||
Expanded(
|
||||
child: LinkSearchField(
|
||||
controller: searchController,
|
||||
hintText: searchHint,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// 折叠按钮(`.toggle-btn`)。
|
||||
class _ToggleButton extends StatefulWidget {
|
||||
const _ToggleButton({required this.collapsed, required this.onTap});
|
||||
|
||||
final bool collapsed;
|
||||
final VoidCallback onTap;
|
||||
|
||||
@override
|
||||
State<_ToggleButton> createState() => _ToggleButtonState();
|
||||
}
|
||||
|
||||
class _ToggleButtonState extends State<_ToggleButton> {
|
||||
bool _hovered = false;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final Color foreground = _hovered
|
||||
? AppColors.primary
|
||||
: AppColors.textSecondary;
|
||||
|
||||
return Tooltip(
|
||||
// 原型写的是 title="展开/折叠侧边栏",文案固定。
|
||||
message: '展开/折叠侧边栏',
|
||||
child: MouseRegion(
|
||||
cursor: SystemMouseCursors.click,
|
||||
onEnter: (_) => setState(() => _hovered = true),
|
||||
onExit: (_) => setState(() => _hovered = false),
|
||||
child: GestureDetector(
|
||||
onTap: widget.onTap,
|
||||
child: AnimatedContainer(
|
||||
duration: AppSizes.transition,
|
||||
// `.toggle-btn { transition: all 0.2s }`。
|
||||
curve: Curves.ease,
|
||||
width: AppSizes.toggleButtonSize,
|
||||
height: AppSizes.toggleButtonSize,
|
||||
alignment: Alignment.center,
|
||||
decoration: BoxDecoration(
|
||||
color: AppColors.surface,
|
||||
border: Border.all(
|
||||
color: _hovered ? AppColors.primary : AppColors.border,
|
||||
),
|
||||
borderRadius: BorderRadius.circular(AppSizes.toggleButtonRadius),
|
||||
boxShadow: AppColors.cardShadow,
|
||||
),
|
||||
// 原型这里就是一个 ☰ 字符(font-size: 18px)。
|
||||
child: Text(
|
||||
'☰',
|
||||
style: TextStyle(fontSize: 18, color: foreground),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user