深色模式、首页设置页面和功能优化

This commit is contained in:
Developer
2026-04-02 07:06:55 +08:00
parent f0a62ed68b
commit 954d173329
88 changed files with 12157 additions and 7578 deletions

View File

@@ -6,9 +6,11 @@ library;
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:get/get.dart';
import '../../../constants/app_constants.dart';
import '../../../utils/http/http_client.dart';
import '../../../services/network_listener_service.dart';
import '../../../services/get/theme_controller.dart';
import 'server_info_dialog.dart';
class EntirePage extends StatefulWidget {
@@ -20,6 +22,7 @@ class EntirePage extends StatefulWidget {
class _EntirePageState extends State<EntirePage>
with NetworkListenerMixin, SingleTickerProviderStateMixin {
final ThemeController _themeController = Get.find<ThemeController>();
Map<String, dynamic>? _statsData;
String? _errorMessage;
late AnimationController _animationController;
@@ -124,31 +127,36 @@ class _EntirePageState extends State<EntirePage>
@override
Widget build(BuildContext context) {
return AnnotatedRegion<SystemUiOverlayStyle>(
value: SystemUiOverlayStyle.dark,
child: Scaffold(
backgroundColor: const Color(0xFFF2F2F7),
appBar: _buildAppBar(),
body: _buildBody(),
),
);
return Obx(() {
final isDark = _themeController.isDarkMode;
return AnnotatedRegion<SystemUiOverlayStyle>(
value: isDark ? SystemUiOverlayStyle.light : SystemUiOverlayStyle.dark,
child: Scaffold(
backgroundColor: isDark
? const Color(0xFF1A1A1A)
: const Color(0xFFF2F2F7),
appBar: _buildAppBar(isDark),
body: _buildBody(isDark),
),
);
});
}
PreferredSizeWidget _buildAppBar() {
PreferredSizeWidget _buildAppBar(bool isDark) {
return AppBar(
backgroundColor: Colors.white,
backgroundColor: isDark ? const Color(0xFF2A2A2A) : Colors.white,
elevation: 0,
leading: IconButton(
icon: const Icon(
icon: Icon(
Icons.arrow_back_ios,
color: AppConstants.primaryColor,
color: isDark ? Colors.white : AppConstants.primaryColor,
),
onPressed: () => Navigator.pop(context),
),
title: const Text(
title: Text(
'全站统计',
style: TextStyle(
color: Colors.black,
color: isDark ? Colors.white : Colors.black,
fontSize: 17,
fontWeight: FontWeight.w600,
),
@@ -156,9 +164,9 @@ class _EntirePageState extends State<EntirePage>
centerTitle: true,
actions: [
IconButton(
icon: const Icon(
icon: Icon(
Icons.info_outline,
color: AppConstants.primaryColor,
color: isDark ? Colors.white : AppConstants.primaryColor,
),
onPressed: _showServerInfo,
tooltip: '服务器信息',
@@ -166,64 +174,68 @@ class _EntirePageState extends State<EntirePage>
],
bottom: PreferredSize(
preferredSize: const Size.fromHeight(0.5),
child: Container(height: 0.5, color: const Color(0xFFE5E5EA)),
child: Container(
height: 0.5,
color: isDark ? Colors.grey[700] : const Color(0xFFE5E5EA),
),
),
);
}
Widget _buildBody() {
Widget _buildBody(bool isDark) {
if (_errorMessage != null) {
return _buildErrorView();
return _buildErrorView(isDark);
}
if (_statsData == null) {
return _buildSkeletonView();
return _buildSkeletonView(isDark);
}
return _buildStatsContent();
return _buildStatsContent(isDark);
}
Widget _buildSkeletonBox({
double width = double.infinity,
double height = 16,
double radius = 8,
bool isDark = false,
}) {
return Container(
width: width,
height: height,
decoration: BoxDecoration(
color: const Color(0xFFE5E5EA),
color: isDark ? Colors.grey[700] : const Color(0xFFE5E5EA),
borderRadius: BorderRadius.circular(radius),
),
);
}
Widget _buildSkeletonView() {
Widget _buildSkeletonView(bool isDark) {
return FadeTransition(
opacity: _fadeAnimation,
child: ListView(
padding: const EdgeInsets.all(16),
children: [
_buildSkeletonHeaderCard(),
_buildSkeletonHeaderCard(isDark),
const SizedBox(height: 16),
_buildSkeletonSection(),
_buildSkeletonSection(isDark),
const SizedBox(height: 16),
_buildSkeletonSection(),
_buildSkeletonSection(isDark),
const SizedBox(height: 16),
_buildSkeletonSection(),
_buildSkeletonSection(isDark),
const SizedBox(height: 16),
_buildSkeletonBuildTimeCard(),
_buildSkeletonBuildTimeCard(isDark),
const SizedBox(height: 32),
],
),
);
}
Widget _buildSkeletonHeaderCard() {
Widget _buildSkeletonHeaderCard(bool isDark) {
return Container(
padding: const EdgeInsets.all(20),
decoration: BoxDecoration(
color: const Color(0xFFE5E5EA),
color: isDark ? Colors.grey[700] : const Color(0xFFE5E5EA),
borderRadius: BorderRadius.circular(12),
),
child: Column(
@@ -231,20 +243,25 @@ class _EntirePageState extends State<EntirePage>
children: [
Row(
children: [
_buildSkeletonBox(width: 28, height: 28, radius: 14),
_buildSkeletonBox(
width: 28,
height: 28,
radius: 14,
isDark: isDark,
),
const SizedBox(width: 12),
_buildSkeletonBox(width: 100, height: 22),
_buildSkeletonBox(width: 100, height: 22, isDark: isDark),
],
),
const SizedBox(height: 12),
_buildSkeletonBox(width: 200, height: 14),
_buildSkeletonBox(width: 200, height: 14, isDark: isDark),
const SizedBox(height: 16),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
_buildSkeletonBox(width: 60, height: 40),
_buildSkeletonBox(width: 60, height: 40),
_buildSkeletonBox(width: 60, height: 40),
_buildSkeletonBox(width: 60, height: 40, isDark: isDark),
_buildSkeletonBox(width: 60, height: 40, isDark: isDark),
_buildSkeletonBox(width: 60, height: 40, isDark: isDark),
],
),
],
@@ -252,15 +269,15 @@ class _EntirePageState extends State<EntirePage>
);
}
Widget _buildSkeletonSection() {
Widget _buildSkeletonSection(bool isDark) {
return Container(
padding: const EdgeInsets.all(16),
decoration: BoxDecoration(
color: Colors.white,
color: isDark ? const Color(0xFF2A2A2A) : Colors.white,
borderRadius: BorderRadius.circular(12),
boxShadow: [
BoxShadow(
color: Colors.black.withValues(alpha: 0.04),
color: Colors.black.withValues(alpha: isDark ? 0.3 : 0.04),
blurRadius: 8,
offset: const Offset(0, 2),
),
@@ -271,9 +288,14 @@ class _EntirePageState extends State<EntirePage>
children: [
Row(
children: [
_buildSkeletonBox(width: 20, height: 20, radius: 10),
_buildSkeletonBox(
width: 20,
height: 20,
radius: 10,
isDark: isDark,
),
const SizedBox(width: 8),
_buildSkeletonBox(width: 80, height: 16),
_buildSkeletonBox(width: 80, height: 16, isDark: isDark),
],
),
const SizedBox(height: 16),
@@ -284,18 +306,21 @@ class _EntirePageState extends State<EntirePage>
childAspectRatio: 1.0,
crossAxisSpacing: 12,
mainAxisSpacing: 12,
children: List.generate(9, (index) => _buildSkeletonCountItem()),
children: List.generate(
9,
(index) => _buildSkeletonCountItem(isDark),
),
),
],
),
);
}
Widget _buildSkeletonCountItem() {
Widget _buildSkeletonCountItem(bool isDark) {
return Container(
padding: const EdgeInsets.all(10),
decoration: BoxDecoration(
color: const Color(0xFFF2F2F7),
color: isDark ? const Color(0xFF333333) : const Color(0xFFF2F2F7),
borderRadius: BorderRadius.circular(12),
),
child: Column(
@@ -309,31 +334,39 @@ class _EntirePageState extends State<EntirePage>
width: double.infinity,
height: 28,
radius: 8,
isDark: isDark,
),
),
const SizedBox(width: 8),
Expanded(
child: _buildSkeletonBox(width: double.infinity, height: 22),
child: _buildSkeletonBox(
width: double.infinity,
height: 22,
isDark: isDark,
),
),
],
),
),
const SizedBox(height: 4),
Expanded(flex: 1, child: _buildSkeletonBox(width: 50, height: 12)),
Expanded(
flex: 1,
child: _buildSkeletonBox(width: 50, height: 12, isDark: isDark),
),
],
),
);
}
Widget _buildSkeletonBuildTimeCard() {
Widget _buildSkeletonBuildTimeCard(bool isDark) {
return Container(
padding: const EdgeInsets.all(16),
decoration: BoxDecoration(
color: Colors.white,
color: isDark ? const Color(0xFF2A2A2A) : Colors.white,
borderRadius: BorderRadius.circular(12),
boxShadow: [
BoxShadow(
color: Colors.black.withValues(alpha: 0.04),
color: Colors.black.withValues(alpha: isDark ? 0.3 : 0.04),
blurRadius: 8,
offset: const Offset(0, 2),
),
@@ -341,15 +374,15 @@ class _EntirePageState extends State<EntirePage>
),
child: Row(
children: [
_buildSkeletonBox(width: 40, height: 40, radius: 10),
_buildSkeletonBox(width: 40, height: 40, radius: 10, isDark: isDark),
const SizedBox(width: 12),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
_buildSkeletonBox(width: 60, height: 14),
_buildSkeletonBox(width: 60, height: 14, isDark: isDark),
const SizedBox(height: 4),
_buildSkeletonBox(width: 150, height: 16),
_buildSkeletonBox(width: 150, height: 16, isDark: isDark),
],
),
),
@@ -358,7 +391,7 @@ class _EntirePageState extends State<EntirePage>
);
}
Widget _buildErrorView() {
Widget _buildErrorView(bool isDark) {
return Center(
child: Padding(
padding: const EdgeInsets.all(24),
@@ -381,7 +414,10 @@ class _EntirePageState extends State<EntirePage>
const SizedBox(height: 16),
Text(
_errorMessage ?? '加载失败',
style: const TextStyle(color: Color(0xFF8E8E93), fontSize: 14),
style: TextStyle(
color: isDark ? Colors.grey[400] : const Color(0xFF8E8E93),
fontSize: 14,
),
textAlign: TextAlign.center,
),
const SizedBox(height: 24),
@@ -406,7 +442,7 @@ class _EntirePageState extends State<EntirePage>
);
}
Widget _buildStatsContent() {
Widget _buildStatsContent(bool isDark) {
return FadeTransition(
opacity: _fadeAnimation,
child: RefreshIndicator(
@@ -417,13 +453,13 @@ class _EntirePageState extends State<EntirePage>
children: [
_buildHeaderCard(),
const SizedBox(height: 16),
_buildHotSection(),
_buildHotSection(isDark),
const SizedBox(height: 16),
_buildCountSection(),
_buildCountSection(isDark),
const SizedBox(height: 16),
_buildTopContentSection(),
_buildTopContentSection(isDark),
const SizedBox(height: 16),
_buildBuildTimeCard(),
_buildBuildTimeCard(isDark),
const SizedBox(height: 32),
],
),
@@ -543,13 +579,13 @@ class _EntirePageState extends State<EntirePage>
);
}
Widget _buildCountSection() {
Widget _buildCountSection(bool isDark) {
return _buildSection('数量统计', Icons.format_list_numbered, [
_buildCountGrid(),
]);
_buildCountGrid(isDark),
], isDark);
}
Widget _buildCountGrid() {
Widget _buildCountGrid(bool isDark) {
final counts = [
{
'label': '项目',
@@ -634,6 +670,7 @@ class _EntirePageState extends State<EntirePage>
item['icon'] as IconData,
item['color'] as Color,
item['showIcon'] as bool,
isDark,
);
},
);
@@ -645,15 +682,16 @@ class _EntirePageState extends State<EntirePage>
IconData icon,
Color color,
bool showIcon,
bool isDark,
) {
return Container(
padding: const EdgeInsets.all(10),
decoration: BoxDecoration(
color: Colors.white,
color: isDark ? const Color(0xFF2A2A2A) : Colors.white,
borderRadius: BorderRadius.circular(12),
boxShadow: [
BoxShadow(
color: Colors.black.withValues(alpha: 0.04),
color: Colors.black.withValues(alpha: isDark ? 0.3 : 0.04),
blurRadius: 8,
offset: const Offset(0, 2),
),
@@ -682,10 +720,10 @@ class _EntirePageState extends State<EntirePage>
Expanded(
child: Text(
value,
style: const TextStyle(
style: TextStyle(
fontSize: 22,
fontWeight: FontWeight.bold,
color: Colors.black,
color: isDark ? Colors.white : Colors.black,
),
textAlign: TextAlign.center,
),
@@ -700,7 +738,10 @@ class _EntirePageState extends State<EntirePage>
child: Center(
child: Text(
label,
style: const TextStyle(fontSize: 12, color: Color(0xFF3C3C43)),
style: TextStyle(
fontSize: 12,
color: isDark ? Colors.grey[400] : const Color(0xFF3C3C43),
),
maxLines: 1,
overflow: TextOverflow.ellipsis,
textAlign: TextAlign.center,
@@ -712,13 +753,14 @@ class _EntirePageState extends State<EntirePage>
);
}
Widget _buildHotSection() {
Widget _buildHotSection(bool isDark) {
return _buildSection('热度统计', Icons.trending_up, [
_buildHotItem(
'累计热度',
_statsData?['cumulative_hits']?.toString() ?? '0',
Icons.local_fire_department,
const Color(0xFFFF9500),
isDark,
),
const SizedBox(height: 12),
_buildHotItem(
@@ -726,19 +768,26 @@ class _EntirePageState extends State<EntirePage>
_statsData?['cumulative_likes']?.toString() ?? '0',
Icons.favorite,
const Color(0xFFFF2D55),
isDark,
),
]);
], isDark);
}
Widget _buildHotItem(String label, String value, IconData icon, Color color) {
Widget _buildHotItem(
String label,
String value,
IconData icon,
Color color,
bool isDark,
) {
return Container(
padding: const EdgeInsets.all(16),
decoration: BoxDecoration(
color: Colors.white,
color: isDark ? const Color(0xFF2A2A2A) : Colors.white,
borderRadius: BorderRadius.circular(12),
boxShadow: [
BoxShadow(
color: Colors.black.withValues(alpha: 0.04),
color: Colors.black.withValues(alpha: isDark ? 0.3 : 0.04),
blurRadius: 8,
offset: const Offset(0, 2),
),
@@ -762,18 +811,18 @@ class _EntirePageState extends State<EntirePage>
children: [
Text(
label,
style: const TextStyle(
style: TextStyle(
fontSize: 14,
color: Color(0xFF8E8E93),
color: isDark ? Colors.grey[400] : const Color(0xFF8E8E93),
),
),
const SizedBox(height: 4),
Text(
value,
style: const TextStyle(
style: TextStyle(
fontSize: 24,
fontWeight: FontWeight.bold,
color: Colors.black,
color: isDark ? Colors.white : Colors.black,
),
),
],
@@ -784,13 +833,14 @@ class _EntirePageState extends State<EntirePage>
);
}
Widget _buildTopContentSection() {
Widget _buildTopContentSection(bool isDark) {
return _buildSection('热门内容', Icons.star, [
_buildTopContentItem(
'今日热门',
_statsData?['top_hits_day'],
Icons.today,
const Color(0xFFFF9500),
isDark,
),
const SizedBox(height: 12),
_buildTopContentItem(
@@ -798,6 +848,7 @@ class _EntirePageState extends State<EntirePage>
_statsData?['top_hits_month'],
Icons.calendar_month,
const Color(0xFF007AFF),
isDark,
),
const SizedBox(height: 12),
_buildTopContentItem(
@@ -805,6 +856,7 @@ class _EntirePageState extends State<EntirePage>
_statsData?['top_hits_total'],
Icons.history,
const Color(0xFF5856D6),
isDark,
),
const SizedBox(height: 12),
_buildTopContentItem(
@@ -812,8 +864,9 @@ class _EntirePageState extends State<EntirePage>
_statsData?['top_like'],
Icons.thumb_up,
const Color(0xFF34C759),
isDark,
),
]);
], isDark);
}
Widget _buildTopContentItem(
@@ -821,6 +874,7 @@ class _EntirePageState extends State<EntirePage>
dynamic data,
IconData icon,
Color color,
bool isDark,
) {
final hasData = data != null && data is Map<String, dynamic>;
final content = hasData ? data['name']?.toString() ?? '暂无数据' : '暂无数据';
@@ -828,11 +882,11 @@ class _EntirePageState extends State<EntirePage>
return Container(
padding: const EdgeInsets.all(16),
decoration: BoxDecoration(
color: Colors.white,
color: isDark ? const Color(0xFF2A2A2A) : Colors.white,
borderRadius: BorderRadius.circular(12),
boxShadow: [
BoxShadow(
color: Colors.black.withValues(alpha: 0.04),
color: Colors.black.withValues(alpha: isDark ? 0.3 : 0.04),
blurRadius: 8,
offset: const Offset(0, 2),
),
@@ -857,10 +911,10 @@ class _EntirePageState extends State<EntirePage>
children: [
Text(
label,
style: const TextStyle(
style: TextStyle(
fontSize: 14,
fontWeight: FontWeight.w600,
color: Colors.black,
color: isDark ? Colors.white : Colors.black,
),
),
const SizedBox(height: 8),
@@ -869,8 +923,8 @@ class _EntirePageState extends State<EntirePage>
style: TextStyle(
fontSize: 13,
color: hasData
? const Color(0xFF3C3C43)
: const Color(0xFF8E8E93),
? (isDark ? Colors.grey[400] : const Color(0xFF3C3C43))
: (isDark ? Colors.grey[500] : const Color(0xFF8E8E93)),
height: 1.5,
),
maxLines: 3,
@@ -884,7 +938,7 @@ class _EntirePageState extends State<EntirePage>
);
}
Widget _buildBuildTimeCard() {
Widget _buildBuildTimeCard(bool isDark) {
final buildTime = _statsData?['build_time']?.toString() ?? '未知';
int days = 0;
@@ -900,11 +954,11 @@ class _EntirePageState extends State<EntirePage>
return Container(
padding: const EdgeInsets.all(16),
decoration: BoxDecoration(
color: Colors.white,
color: isDark ? const Color(0xFF2A2A2A) : Colors.white,
borderRadius: BorderRadius.circular(12),
boxShadow: [
BoxShadow(
color: Colors.black.withValues(alpha: 0.04),
color: Colors.black.withValues(alpha: isDark ? 0.3 : 0.04),
blurRadius: 8,
offset: const Offset(0, 2),
),
@@ -930,12 +984,12 @@ class _EntirePageState extends State<EntirePage>
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text(
Text(
'建站时间',
style: TextStyle(
fontSize: 14,
fontWeight: FontWeight.w600,
color: Colors.black,
color: isDark ? Colors.white : Colors.black,
),
),
const SizedBox(height: 4),
@@ -943,9 +997,11 @@ class _EntirePageState extends State<EntirePage>
children: [
Text(
buildTime,
style: const TextStyle(
style: TextStyle(
fontSize: 16,
color: Color(0xFF3C3C43),
color: isDark
? Colors.grey[400]
: const Color(0xFF3C3C43),
),
),
const SizedBox(width: 8),
@@ -977,14 +1033,19 @@ class _EntirePageState extends State<EntirePage>
);
}
Widget _buildSection(String title, IconData icon, List<Widget> children) {
Widget _buildSection(
String title,
IconData icon,
List<Widget> children,
bool isDark,
) {
return Container(
decoration: BoxDecoration(
color: Colors.white,
color: isDark ? const Color(0xFF2A2A2A) : Colors.white,
borderRadius: BorderRadius.circular(12),
boxShadow: [
BoxShadow(
color: Colors.black.withValues(alpha: 0.04),
color: Colors.black.withValues(alpha: isDark ? 0.3 : 0.04),
blurRadius: 8,
offset: const Offset(0, 2),
),
@@ -1001,10 +1062,10 @@ class _EntirePageState extends State<EntirePage>
const SizedBox(width: 8),
Text(
title,
style: const TextStyle(
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.w600,
color: Colors.black,
color: isDark ? Colors.white : Colors.black,
),
),
],