Files
wushu/lib/views/active/category_page.dart
2026-04-01 04:45:33 +08:00

268 lines
8.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 '../../constants/app_constants.dart';
import 'tags/corr_page.dart';
/// 时间: 2026-04-01
/// 功能: 分类页面
/// 介绍: 展示诗词分类,包括场景分类和朝代分类
/// 最新变化: 重新设计iOS风格布局减少间距加大字体显示分类数量
class CategoryPage extends StatefulWidget {
const CategoryPage({super.key});
@override
State<CategoryPage> createState() => _CategoryPageState();
}
class _CategoryPageState extends State<CategoryPage>
with SingleTickerProviderStateMixin {
late TabController _tabController;
final List<Map<String, dynamic>> _tabCategories = [
{'label': '场景分类', 'icon': Icons.category},
{'label': '朝代分类', 'icon': Icons.history},
];
static const sceneData = {
"节日": ["七夕节", "中秋节", "元宵节", "寒食节", "清明节", "端午节", "重阳节", "春节", "节日"],
"季节": ["三月", "二月", "冬天", "夏天", "春天", "春季", "秋天"],
"古籍": [
"三国志",
"三国演义",
"三字经",
"中庸",
"列子",
"史记",
"后汉书",
"吕氏春秋",
"商君书",
"围炉夜话",
"增广贤文",
"墨子",
"孙子兵法",
"孟子",
"小窗幽记",
"尚书",
"左传",
"幼学琼林",
"庄子",
"战国策",
"文心雕龙",
"易传",
"晋书",
"汉书",
"淮南子",
"礼记",
"管子",
"红楼梦",
"老子",
"荀子",
"菜根谭",
"警世通言",
"论语",
"资治通鉴",
"韩非子",
"鬼谷子",
"古籍",
"格言联璧",
],
"情感": ["伤感", "励志", "友情", "思乡", "思念", "感恩", "爱国", "爱情", "离别"],
"景物": ["庐山", "泰山", "西湖", "长江", "黄河", "边塞", "田园", "山水", "夜景"],
"天文气象": ["写云", "写雨", "写雪", "写风", "星星", "月亮", "流星"],
"动植物": ["写鸟", "柳树", "桃花", "梅花", "竹子", "荷花", "菊花"],
"语言文学": ["对联", "谚语", "一言", "读书", "哲理"],
"其他": ["母亲", "老师", "户外", "礼物", ""],
};
static const dynastyData = {
"主要朝代": ["唐代", "宋代", "元代", "明代", "清代"],
"古代朝代": ["南北朝", "五代", "隋代"],
"近现代": ["近现代", "用户投稿", "管理员测试"],
"其他": ["暂无朝代"],
};
@override
void initState() {
super.initState();
_tabController = TabController(length: _tabCategories.length, vsync: this);
}
@override
void dispose() {
_tabController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Column(
children: [
// Tab栏
Container(
color: Colors.white,
padding: const EdgeInsets.symmetric(horizontal: 16),
child: TabBar(
controller: _tabController,
tabs: _tabCategories
.map(
(category) => Tab(
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
Icon(category['icon'], size: 18),
const SizedBox(width: 6),
Text(category['label']),
],
),
),
)
.toList(),
labelColor: AppConstants.primaryColor,
unselectedLabelColor: Colors.grey[600],
indicatorColor: AppConstants.primaryColor,
indicatorWeight: 3,
labelStyle: const TextStyle(
fontWeight: FontWeight.w600,
fontSize: 16,
),
unselectedLabelStyle: const TextStyle(
fontWeight: FontWeight.normal,
fontSize: 16,
),
),
),
Container(height: 0.5, color: const Color(0xFFE5E5EA)),
// 内容区域
Expanded(
child: Container(
color: const Color(0xFFF2F2F7),
child: TabBarView(
controller: _tabController,
children: [
_buildCategoryList(sceneData, _tabCategories[0]['label']),
_buildCategoryList(dynastyData, _tabCategories[1]['label']),
],
),
),
),
],
);
}
Widget _buildCategoryList(
Map<String, List<String>> data,
String categoryType,
) {
return ListView.separated(
padding: const EdgeInsets.symmetric(vertical: 8),
itemCount: data.keys.length,
separatorBuilder: (context, index) => const SizedBox(height: 8),
itemBuilder: (context, index) {
final category = data.keys.elementAt(index);
final items = data[category]!;
return Container(
margin: const EdgeInsets.symmetric(horizontal: 16),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(12),
boxShadow: [
BoxShadow(
color: Colors.black.withValues(alpha: 0.04),
blurRadius: 8,
offset: const Offset(0, 2),
),
],
),
child: Material(
color: Colors.transparent,
borderRadius: BorderRadius.circular(12),
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [
Expanded(
child: Text(
category,
style: const TextStyle(
fontSize: 18,
fontWeight: FontWeight.w600,
color: Colors.black,
),
),
),
Container(
padding: const EdgeInsets.symmetric(
horizontal: 10,
vertical: 4,
),
decoration: BoxDecoration(
color: AppConstants.primaryColor.withValues(
alpha: 0.1,
),
borderRadius: BorderRadius.circular(12),
),
child: Text(
'${items.length}',
style: TextStyle(
fontSize: 13,
color: AppConstants.primaryColor,
fontWeight: FontWeight.w600,
),
),
),
],
),
const SizedBox(height: 12),
Wrap(
spacing: 10,
runSpacing: 10,
children: items.map((item) {
return _buildCategoryChip(item, categoryType);
}).toList(),
),
],
),
),
),
);
},
);
}
Widget _buildCategoryChip(String label, String categoryType) {
return GestureDetector(
onTap: () {
final searchType = categoryType == '朝代分类' ? 'alias' : 'keywords';
Navigator.push(
context,
MaterialPageRoute(
builder: (_) => CorrPage(label: label, searchType: searchType),
),
);
},
child: Container(
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 10),
decoration: BoxDecoration(
color: AppConstants.primaryColor.withValues(alpha: 0.1),
borderRadius: BorderRadius.circular(20),
border: Border.all(
color: AppConstants.primaryColor.withValues(alpha: 0.3),
width: 1,
),
),
child: Text(
label,
style: TextStyle(
color: AppConstants.primaryColor,
fontSize: 14,
fontWeight: FontWeight.w500,
),
),
),
);
}
}