generated from dellevin/template
优化webdav恢复
This commit is contained in:
@@ -264,6 +264,14 @@ class _MainContentPageState extends State<MainContentPage> {
|
||||
Navigator.pop(context);
|
||||
}
|
||||
|
||||
// 下载了数据则刷新界面
|
||||
if (result.success && result.needReload && context.mounted) {
|
||||
final provider = context.read<AppProvider>();
|
||||
await provider.loadMovies();
|
||||
await provider.loadBooks();
|
||||
await provider.loadNotes();
|
||||
}
|
||||
|
||||
// 显示结果
|
||||
if (context.mounted) {
|
||||
final isSuccess = result.success;
|
||||
|
||||
@@ -233,76 +233,25 @@ class _ProfilePageState extends State<ProfilePage> {
|
||||
final notes = provider.notes;
|
||||
|
||||
final movieCount = movies.where((m) => !m.isDeleted).length;
|
||||
final watchedCount = movies.where((m) => m.status == 'watched' && !m.isDeleted).length;
|
||||
final watchingCount = movies.where((m) => m.status == 'watching' && !m.isDeleted).length;
|
||||
final wantToWatchCount = movies.where((m) => m.status == 'want_to_watch' && !m.isDeleted).length;
|
||||
|
||||
final bookCount = books.length;
|
||||
final readCount = books.where((b) => b.status == 'read').length;
|
||||
final readingCount = books.where((b) => b.status == 'reading').length;
|
||||
final wantToReadCount = books.where((b) => b.status == 'want_to_read').length;
|
||||
|
||||
final noteCount = notes.length;
|
||||
|
||||
final movieRatings = movies
|
||||
.where((m) => m.rating != null && !m.isDeleted)
|
||||
.map((m) => m.rating!);
|
||||
final avgMovieRating = movieRatings.isNotEmpty
|
||||
? movieRatings.reduce((a, b) => a + b) / movieRatings.length
|
||||
: 0.0;
|
||||
|
||||
final bookRatings = books
|
||||
.where((b) => b.rating != null)
|
||||
.map((b) => b.rating!);
|
||||
final avgBookRating = bookRatings.isNotEmpty
|
||||
? bookRatings.reduce((a, b) => a + b) / bookRatings.length
|
||||
: 0.0;
|
||||
|
||||
|
||||
return Padding(
|
||||
padding: const EdgeInsets.fromLTRB(24, 16, 24, 24),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
// 主统计卡片
|
||||
Container(
|
||||
padding: const EdgeInsets.all(20),
|
||||
decoration: BoxDecoration(
|
||||
color: const Color(0xFFF8F8F8),
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||
children: [
|
||||
_buildStatCard('观影', movieCount, '场', Icons.movie_outlined),
|
||||
_buildStatCard('阅读', bookCount, '本', Icons.menu_book_outlined),
|
||||
_buildStatCard('笔记', noteCount, '条', Icons.note_outlined),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
const SizedBox(height: 24),
|
||||
|
||||
// 详情统计
|
||||
_buildSectionTitle('观影详情'),
|
||||
const SizedBox(height: 12),
|
||||
_buildDetailGrid([
|
||||
_buildDetailItem('已看', watchedCount, Icons.check_circle_outline),
|
||||
_buildDetailItem('在看', watchingCount, Icons.play_circle_outline),
|
||||
_buildDetailItem('想看', wantToWatchCount, Icons.bookmark_border),
|
||||
_buildDetailItem('均分', avgMovieRating > 0 ? avgMovieRating.toStringAsFixed(1) : '-', Icons.star_outline),
|
||||
]),
|
||||
|
||||
const SizedBox(height: 20),
|
||||
|
||||
_buildSectionTitle('阅读详情'),
|
||||
const SizedBox(height: 12),
|
||||
_buildDetailGrid([
|
||||
_buildDetailItem('已读', readCount, Icons.check_circle_outline),
|
||||
_buildDetailItem('在读', readingCount, Icons.play_circle_outline),
|
||||
_buildDetailItem('想读', wantToReadCount, Icons.bookmark_border),
|
||||
_buildDetailItem('均分', avgBookRating > 0 ? avgBookRating.toStringAsFixed(1) : '-', Icons.star_outline),
|
||||
]),
|
||||
],
|
||||
child: Container(
|
||||
padding: const EdgeInsets.all(20),
|
||||
decoration: BoxDecoration(
|
||||
color: const Color(0xFFF8F8F8),
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||
children: [
|
||||
_buildStatCard('观影', movieCount, '场', Icons.movie_outlined),
|
||||
_buildStatCard('阅读', bookCount, '本', Icons.menu_book_outlined),
|
||||
_buildStatCard('笔记', noteCount, '条', Icons.note_outlined),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
@@ -354,63 +303,6 @@ class _ProfilePageState extends State<ProfilePage> {
|
||||
);
|
||||
}
|
||||
|
||||
/// 详情网格
|
||||
Widget _buildDetailGrid(List<Widget> children) {
|
||||
return Container(
|
||||
padding: const EdgeInsets.all(16),
|
||||
decoration: BoxDecoration(
|
||||
color: const Color(0xFFFAFAFA),
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||
children: children,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/// 详情项
|
||||
Widget _buildDetailItem(String label, dynamic value, IconData icon) {
|
||||
return Column(
|
||||
children: [
|
||||
Icon(
|
||||
icon,
|
||||
size: 18,
|
||||
color: const Color(0xFF999999),
|
||||
),
|
||||
const SizedBox(height: 6),
|
||||
Text(
|
||||
'$value',
|
||||
style: const TextStyle(
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.w600,
|
||||
color: Color(0xFF1A1A1A),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 2),
|
||||
Text(
|
||||
label,
|
||||
style: const TextStyle(
|
||||
fontSize: 11,
|
||||
color: Color(0xFF999999),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
/// 区块标题
|
||||
Widget _buildSectionTitle(String title) {
|
||||
return Text(
|
||||
title,
|
||||
style: const TextStyle(
|
||||
fontSize: 12,
|
||||
fontWeight: FontWeight.w500,
|
||||
color: Color(0xFF999999),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/// 功能菜单
|
||||
Widget _buildMenuSection() {
|
||||
return Container(
|
||||
|
||||
@@ -96,6 +96,16 @@ class _StatisticsPageState extends State<StatisticsPage> {
|
||||
final readingBooks = books.where((b) => b.status == 'reading').length;
|
||||
final wantToReadBooks = books.where((b) => b.status == 'want_to_read').length;
|
||||
|
||||
final movieRatings = movies.where((m) => m.rating != null && !m.isDeleted).map((m) => m.rating!);
|
||||
final avgMovieRating = movieRatings.isNotEmpty
|
||||
? movieRatings.reduce((a, b) => a + b) / movieRatings.length
|
||||
: null;
|
||||
|
||||
final bookRatings = books.where((b) => b.rating != null).map((b) => b.rating!);
|
||||
final avgBookRating = bookRatings.isNotEmpty
|
||||
? bookRatings.reduce((a, b) => a + b) / bookRatings.length
|
||||
: null;
|
||||
|
||||
final children = <Widget>[];
|
||||
|
||||
// 数据总览
|
||||
@@ -106,25 +116,25 @@ class _StatisticsPageState extends State<StatisticsPage> {
|
||||
|
||||
// 影视状态分布
|
||||
if (_showMovies) {
|
||||
children.add(_buildSectionTitle('影视状态分布'));
|
||||
children.add(_buildSectionTitle('影视'));
|
||||
children.add(const SizedBox(height: 16));
|
||||
children.add(_buildStatusDistribution([
|
||||
_StatusData('已看', watchedMovies, const Color(0xFF1A1A1A)),
|
||||
_StatusData('在看', watchingMovies, const Color(0xFF666666)),
|
||||
_StatusData('想看', wantToWatchMovies, const Color(0xFF999999)),
|
||||
]));
|
||||
], avgRating: avgMovieRating));
|
||||
children.add(const SizedBox(height: 32));
|
||||
}
|
||||
|
||||
// 书籍状态分布
|
||||
if (_showBooks) {
|
||||
children.add(_buildSectionTitle('书籍状态分布'));
|
||||
children.add(_buildSectionTitle('书籍'));
|
||||
children.add(const SizedBox(height: 16));
|
||||
children.add(_buildStatusDistribution([
|
||||
_StatusData('已读', readBooks, const Color(0xFF1A1A1A)),
|
||||
_StatusData('在读', readingBooks, const Color(0xFF666666)),
|
||||
_StatusData('想读', wantToReadBooks, const Color(0xFF999999)),
|
||||
]));
|
||||
], avgRating: avgBookRating));
|
||||
children.add(const SizedBox(height: 32));
|
||||
}
|
||||
|
||||
@@ -295,7 +305,7 @@ class _StatisticsPageState extends State<StatisticsPage> {
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildStatusDistribution(List<_StatusData> data) {
|
||||
Widget _buildStatusDistribution(List<_StatusData> data, {double? avgRating}) {
|
||||
final total = data.fold(0, (sum, item) => sum + item.count);
|
||||
|
||||
return Container(
|
||||
@@ -305,26 +315,41 @@ class _StatisticsPageState extends State<StatisticsPage> {
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
),
|
||||
child: Column(
|
||||
children: data.map((item) {
|
||||
final percentage = total > 0 ? (item.count / total * 100).toStringAsFixed(1) : '0';
|
||||
return Padding(
|
||||
padding: const EdgeInsets.only(bottom: 12),
|
||||
child: Row(
|
||||
children: [
|
||||
...data.map((item) {
|
||||
final percentage = total > 0 ? (item.count / total * 100).toStringAsFixed(1) : '0';
|
||||
return Padding(
|
||||
padding: const EdgeInsets.only(bottom: 12),
|
||||
child: Row(
|
||||
children: [
|
||||
Container(
|
||||
width: 10, height: 10,
|
||||
decoration: BoxDecoration(color: item.color, borderRadius: BorderRadius.circular(2)),
|
||||
),
|
||||
const SizedBox(width: 12),
|
||||
Text(item.label, style: const TextStyle(fontSize: 14, color: Color(0xFF1A1A1A))),
|
||||
const Spacer(),
|
||||
Text('${item.count}', style: const TextStyle(fontSize: 14, fontWeight: FontWeight.w600, color: Color(0xFF1A1A1A))),
|
||||
const SizedBox(width: 8),
|
||||
Text('($percentage%)', style: const TextStyle(fontSize: 13, color: Color(0xFF999999))),
|
||||
],
|
||||
),
|
||||
);
|
||||
}),
|
||||
if (avgRating != null) ...[
|
||||
const Divider(height: 1, color: Color(0xFFE8E8E8)),
|
||||
const SizedBox(height: 12),
|
||||
Row(
|
||||
children: [
|
||||
Container(
|
||||
width: 10, height: 10,
|
||||
decoration: BoxDecoration(color: item.color, borderRadius: BorderRadius.circular(2)),
|
||||
),
|
||||
const SizedBox(width: 12),
|
||||
Text(item.label, style: const TextStyle(fontSize: 14, color: Color(0xFF1A1A1A))),
|
||||
const Icon(Icons.star, size: 16, color: Color(0xFF999999)),
|
||||
const SizedBox(width: 10),
|
||||
const Text('平均评分', style: TextStyle(fontSize: 14, color: Color(0xFF1A1A1A))),
|
||||
const Spacer(),
|
||||
Text('${item.count}', style: const TextStyle(fontSize: 14, fontWeight: FontWeight.w600, color: Color(0xFF1A1A1A))),
|
||||
const SizedBox(width: 8),
|
||||
Text('($percentage%)', style: const TextStyle(fontSize: 13, color: Color(0xFF999999))),
|
||||
Text(avgRating.toStringAsFixed(1), style: const TextStyle(fontSize: 14, fontWeight: FontWeight.w600, color: Color(0xFF1A1A1A))),
|
||||
],
|
||||
),
|
||||
);
|
||||
}).toList(),
|
||||
],
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user