关怀模式

This commit is contained in:
Developer
2026-04-02 22:30:49 +08:00
parent 09fee0694c
commit 7872f2e78a
70 changed files with 4884 additions and 2752 deletions

View File

@@ -1,4 +1,5 @@
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import '../../constants/app_constants.dart';
import '../../config/app_config.dart';
import '../../utils/http/http_client.dart';
@@ -6,6 +7,7 @@ import '../../models/poetry_model.dart';
import '../../controllers/load/locally.dart';
import '../../controllers/history_controller.dart';
import '../../services/network_listener_service.dart';
import '../../services/get/theme_controller.dart';
/// 时间: 2026-03-25
/// 功能: 热门页面
@@ -22,6 +24,7 @@ class PopularPage extends StatefulWidget {
class _PopularPageState extends State<PopularPage>
with SingleTickerProviderStateMixin {
late TabController _tabController;
final ThemeController _themeController = Get.find<ThemeController>();
final List<Map<String, dynamic>> _tabCategories = [
{'label': '总榜', 'icon': Icons.bar_chart},
{'label': '日榜', 'icon': Icons.today},
@@ -53,58 +56,81 @@ class _PopularPageState extends State<PopularPage>
@override
Widget build(BuildContext context) {
return Column(
children: [
// 黑色分割线
Container(height: 1, color: Colors.black.withValues(alpha: 0.1)),
// Tab栏
Container(
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 4),
child: TabBar(
controller: _tabController,
tabs: _tabCategories
.map(
(category) => Tab(
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
Icon(category['icon'], size: 16),
const SizedBox(width: 6),
Text(category['label']),
],
return Obx(() {
final isDark = _themeController.isDarkModeRx.value;
final themeColor = _themeController.currentThemeColor;
return Column(
children: [
// 分割线
Container(
height: 1,
color: isDark ? Colors.grey[800] : Colors.black.withAlpha(10),
),
// Tab栏
Container(
color: isDark ? Colors.grey[900] : Colors.white,
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 4),
child: TabBar(
controller: _tabController,
tabs: _tabCategories
.map(
(category) => Tab(
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
Icon(category['icon'], size: 16),
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.bold),
)
.toList(),
labelColor: themeColor,
unselectedLabelColor: isDark
? Colors.grey[400]
: Colors.grey[600],
indicatorColor: themeColor,
indicatorWeight: 3,
labelStyle: const TextStyle(fontWeight: FontWeight.bold),
),
),
),
// 内容区域
Expanded(
child: TabBarView(
controller: _tabController,
children: _tabCategories.map((category) {
return _buildRankContent(category['label']);
}).toList(),
// 内容区域
Expanded(
child: Container(
color: isDark ? const Color(0xFF121212) : Colors.grey[50],
child: TabBarView(
controller: _tabController,
children: _tabCategories.map((category) {
return _buildRankContent(
category['label'],
isDark,
themeColor,
);
}).toList(),
),
),
),
),
],
);
],
);
});
}
Widget _buildRankContent(String category) {
Widget _buildRankContent(String category, bool isDark, Color themeColor) {
if (_loading) {
return const Center(
return Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
CircularProgressIndicator(),
SizedBox(height: 16),
Text('正在加载排行榜...'),
CircularProgressIndicator(color: themeColor),
const SizedBox(height: 16),
Text(
'正在加载排行榜...',
style: TextStyle(
color: isDark ? Colors.grey[300] : Colors.grey[600],
),
),
],
),
);
@@ -115,12 +141,25 @@ class _PopularPageState extends State<PopularPage>
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Icon(Icons.error_outline, size: 64, color: Colors.grey),
Icon(
Icons.error_outline,
size: 64,
color: isDark ? Colors.grey[500] : Colors.grey[400],
),
const SizedBox(height: 16),
Text(_errorMessage, style: const TextStyle(color: Colors.grey)),
Text(
_errorMessage,
style: TextStyle(
color: isDark ? Colors.grey[400] : Colors.grey[600],
),
),
const SizedBox(height: 16),
ElevatedButton(
onPressed: _loadRankList,
style: ElevatedButton.styleFrom(
backgroundColor: themeColor,
foregroundColor: Colors.white,
),
child: const Text('🔄 重试'),
),
],
@@ -129,17 +168,29 @@ class _PopularPageState extends State<PopularPage>
}
if (_rankList.isEmpty) {
return const Center(
return Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(Icons.bar_chart, size: 64, color: Colors.grey),
SizedBox(height: 16),
Text('暂无排行数据', style: TextStyle(color: Colors.grey)),
SizedBox(height: 8),
Icon(
Icons.bar_chart,
size: 64,
color: isDark ? Colors.grey[500] : Colors.grey[400],
),
const SizedBox(height: 16),
Text(
'暂无排行数据',
style: TextStyle(
color: isDark ? Colors.grey[400] : Colors.grey[600],
),
),
const SizedBox(height: 8),
Text(
'换个时间段试试吧',
style: TextStyle(color: Colors.grey, fontSize: 12),
style: TextStyle(
color: isDark ? Colors.grey[500] : Colors.grey[600],
fontSize: 12,
),
),
],
),
@@ -147,6 +198,7 @@ class _PopularPageState extends State<PopularPage>
}
return RefreshIndicator(
color: themeColor,
onRefresh: () async => await _loadRankList(forceRefresh: true),
child: NotificationListener<ScrollNotification>(
onNotification: (scrollNotification) {
@@ -167,14 +219,24 @@ class _PopularPageState extends State<PopularPage>
itemCount: _rankList.length + (_showBottomIndicator ? 1 : 0),
itemBuilder: (context, index) {
if (index == _rankList.length) {
return const Center(
return Center(
child: Padding(
padding: EdgeInsets.all(16),
child: Text('到底了', style: TextStyle(color: Colors.grey)),
padding: const EdgeInsets.all(16),
child: Text(
'到底了',
style: TextStyle(
color: isDark ? Colors.grey[500] : Colors.grey[600],
),
),
),
);
}
return _buildRankItem(_rankList[index], index + 1);
return _buildRankItem(
_rankList[index],
index + 1,
isDark,
themeColor,
);
},
),
),
@@ -223,19 +285,23 @@ class _PopularPageState extends State<PopularPage>
}
}
Widget _buildRankItem(PoetryModel poetry, int index) {
Widget _buildRankItem(
PoetryModel poetry,
int index,
bool isDark,
Color themeColor,
) {
final rank = poetry.rank > 0 ? poetry.rank : index;
final isTopThree = rank <= 3;
return Card(
margin: const EdgeInsets.only(bottom: 12),
elevation: isTopThree ? 4 : 2,
color: isDark ? Colors.grey[850] : Colors.white,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(12),
side: BorderSide(
color: isTopThree
? AppConstants.primaryColor
: AppConstants.primaryColor.withValues(alpha: 0.2),
color: isTopThree ? themeColor : themeColor.withAlpha(20),
width: isTopThree ? 2 : 1,
),
),
@@ -254,16 +320,12 @@ class _PopularPageState extends State<PopularPage>
width: 40,
height: 40,
decoration: BoxDecoration(
color: isTopThree
? AppConstants.primaryColor
: AppConstants.primaryColor.withValues(alpha: 0.3),
color: isTopThree ? themeColor : themeColor.withAlpha(30),
borderRadius: BorderRadius.circular(20),
border: isTopThree
? null
: Border.all(
color: AppConstants.primaryColor.withValues(
alpha: 0.2,
),
color: themeColor.withAlpha(20),
width: 1,
),
),
@@ -273,9 +335,7 @@ class _PopularPageState extends State<PopularPage>
style: TextStyle(
color: isTopThree
? Colors.white
: AppConstants.primaryColor.withValues(
alpha: 0.8,
),
: themeColor.withAlpha(80),
fontWeight: FontWeight.bold,
fontSize: 16,
),
@@ -292,8 +352,11 @@ class _PopularPageState extends State<PopularPage>
// 标题
Text(
poetry.name,
style: Theme.of(context).textTheme.titleMedium
?.copyWith(fontWeight: FontWeight.bold),
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 16,
color: isDark ? Colors.white : Colors.black87,
),
maxLines: 2,
overflow: TextOverflow.ellipsis,
),
@@ -310,16 +373,14 @@ class _PopularPageState extends State<PopularPage>
vertical: 2,
),
decoration: BoxDecoration(
color: AppConstants.primaryColor.withValues(
alpha: 0.1,
),
color: themeColor.withAlpha(10),
borderRadius: BorderRadius.circular(8),
),
child: Text(
poetry.alias,
style: TextStyle(
fontSize: 10,
color: AppConstants.primaryColor,
color: themeColor,
),
),
),
@@ -331,7 +392,9 @@ class _PopularPageState extends State<PopularPage>
poetry.url,
style: TextStyle(
fontSize: 12,
color: Colors.grey[600],
color: isDark
? Colors.grey[400]
: Colors.grey[600],
),
overflow: TextOverflow.ellipsis,
),
@@ -347,21 +410,29 @@ class _PopularPageState extends State<PopularPage>
'👁',
poetry.hitsTotal.toString(),
'总浏览',
isDark,
),
const SizedBox(width: 16),
_buildStatItem('💖', poetry.like.toString(), '点赞'),
_buildStatItem(
'💖',
poetry.like.toString(),
'点赞',
isDark,
),
const SizedBox(width: 16),
if (_tabController.index == 1)
_buildStatItem(
'📅',
poetry.hitsDay.toString(),
'今日',
isDark,
),
if (_tabController.index == 2)
_buildStatItem(
'📊',
poetry.hitsMonth.toString(),
'本月',
isDark,
),
],
),
@@ -382,14 +453,14 @@ class _PopularPageState extends State<PopularPage>
vertical: 6,
),
decoration: BoxDecoration(
color: Colors.orange[700],
color: themeColor,
borderRadius: const BorderRadius.only(
topLeft: Radius.circular(12),
bottomRight: Radius.circular(12),
),
boxShadow: [
BoxShadow(
color: Colors.black.withValues(alpha: 0.15),
color: Colors.black.withAlpha(15),
blurRadius: 4,
offset: const Offset(0, 2),
),
@@ -424,7 +495,7 @@ class _PopularPageState extends State<PopularPage>
);
}
Widget _buildStatItem(String icon, String value, String label) {
Widget _buildStatItem(String icon, String value, String label, bool isDark) {
return Row(
mainAxisSize: MainAxisSize.min,
children: [
@@ -432,10 +503,20 @@ class _PopularPageState extends State<PopularPage>
const SizedBox(width: 4),
Text(
value,
style: const TextStyle(fontSize: 12, fontWeight: FontWeight.w500),
style: TextStyle(
fontSize: 12,
fontWeight: FontWeight.w500,
color: isDark ? Colors.grey[300] : Colors.black87,
),
),
const SizedBox(width: 2),
Text(label, style: TextStyle(fontSize: 10, color: Colors.grey[600])),
Text(
label,
style: TextStyle(
fontSize: 10,
color: isDark ? Colors.grey[500] : Colors.grey[600],
),
),
],
);
}