Files
Navius/frontend/lib/main.dart
CNWei 4075519075 feat: 实现导航页基础功能
- 添加导航条目和分类数据模型
- 实现导航卡片网格展示
- 支持点击卡片打开链接
- 添加主题样式(渐变色、卡片阴影)
- 区分系统默认和自定义条目
- 添加分类统计信息"
2026-09-06 21:44:33 +08:00

246 lines
7.3 KiB
Dart
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import 'package:flutter/material.dart';
import 'models/nav_item.dart';
import 'models/category.dart';
import 'data/mock_data.dart';
import 'package:web/web.dart' as web;
import 'data/nav_data.dart';
import 'theme/app_theme.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Navius 导航',
theme: AppTheme.lightTheme,
home: NaviusHomePage(),
);
}
}
class NaviusHomePage extends StatelessWidget {
const NaviusHomePage({super.key});
@override
Widget build(BuildContext context) {
// 获取分类数据
final categories = MockData.getCategories();
return Scaffold(
appBar: PreferredSize(
preferredSize: const Size.fromHeight(120),
child: Container(
decoration: BoxDecoration(
gradient: AppTheme.appBarGradient,
borderRadius: const BorderRadius.only(
bottomLeft: Radius.circular(30),
bottomRight: Radius.circular(30),
),
),
child: SafeArea(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
// 标题
const Text(
'Navius 导航',
style: TextStyle(
fontSize: 28,
fontWeight: FontWeight.bold,
color: Colors.white,
letterSpacing: 1.5,
),
),
const SizedBox(height: 4),
Text(
'${categories.length} 个分类 · ${_getTotalEntries(categories)} 个导航',
style: const TextStyle(
fontSize: 14,
color: Colors.white70,
),
),
],
),
),
),
),
body: ListView.builder(
padding: const EdgeInsets.all(16),
itemCount: categories.length,
itemBuilder: (context, index) {
final category = categories[index];
return CategorySection(category: category);
},
),
);
}
// 计算总导航数
static int _getTotalEntries(List<Category> categories) {
int total = 0;
for (var category in categories) {
total += category.entries.length;
}
return total;
}
}
// 分类区块组件
class CategorySection extends StatelessWidget {
final Category category;
const CategorySection({super.key, required this.category});
@override
Widget build(BuildContext context) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
// 分类标题(美化版)
Padding(
padding: const EdgeInsets.symmetric(vertical: 16),
child: Row(
children: [
// 分类名称
Text(
category.name,
style: const TextStyle(
fontSize: 20,
fontWeight: FontWeight.w700,
color: Color(0xFF1E293B),
letterSpacing: 0.5,
),
),
const SizedBox(width: 12),
// 条目数量
Container(
padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 2),
decoration: BoxDecoration(
color: AppTheme.systemTagColor,
borderRadius: BorderRadius.circular(12),
),
child: Text(
'${category.entries.length}',
style: const TextStyle(
fontSize: 12,
color: AppTheme.systemTagTextColor,
fontWeight: FontWeight.w600,
),
),
),
const Spacer(),
// 系统标签
if (category.isSystem)
Container(
padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 4),
decoration: BoxDecoration(
color: AppTheme.systemTagColor,
borderRadius: BorderRadius.circular(12),
),
child: const Text(
'系统分类',
style: TextStyle(
fontSize: 11,
color: AppTheme.systemTagTextColor,
fontWeight: FontWeight.w500,
),
),
),
],
),
),
// 导航网格4列
GridView.builder(
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 4,
childAspectRatio: 1.0,
crossAxisSpacing: 16,
mainAxisSpacing: 16,
),
itemCount: category.entries.length,
itemBuilder: (context, index) {
final item = category.entries[index];
return NavItemCard(item: item);
},
),
const SizedBox(height: 8),
],
);
}
}
// 单个导航卡片组件
class NavItemCard extends StatelessWidget {
final NavItem item;
const NavItemCard({super.key, required this.item});
@override
Widget build(BuildContext context) {
return Container(
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(16),
boxShadow: AppTheme.cardShadow,
),
child: InkWell(
onTap: () {
web.window.open(item.url, '_blank');
},
borderRadius: BorderRadius.circular(16),
hoverColor: AppTheme.primaryColor.withOpacity(0.05),
splashColor: AppTheme.primaryColor.withOpacity(0.1),
child: Padding(
padding: const EdgeInsets.all(8),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
// 图标(增大)
Text(
item.icon,
style: const TextStyle(fontSize: 36),
),
const SizedBox(height: 10),
// 标题
Text(
item.title,
style: const TextStyle(
fontSize: 14,
fontWeight: FontWeight.w500,
color: Color(0xFF1E293B),
),
textAlign: TextAlign.center,
maxLines: 1,
overflow: TextOverflow.ellipsis,
),
const SizedBox(height: 4),
// 系统标签(改进样式)
if (item.isSystem)
Container(
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 2),
decoration: BoxDecoration(
color: AppTheme.systemTagColor,
borderRadius: BorderRadius.circular(10),
),
child: Text(
'默认',
style: TextStyle(
fontSize: 9,
color: AppTheme.systemTagTextColor,
fontWeight: FontWeight.w600,
),
),
),
],
),
),
),
);
}
}