功能优化

This commit is contained in:
DelLevin-Home
2026-03-09 14:14:38 +08:00
parent c894921472
commit 7c970cde49
7 changed files with 496 additions and 705 deletions

View File

@@ -9,7 +9,7 @@ import '../models/data_models.dart';
/// 自定义左侧弹出菜单 - 极简主义设计
class CustomDrawer extends StatelessWidget {
const CustomDrawer({super.key});
CustomDrawer({super.key});
@override
Widget build(BuildContext context) {
@@ -27,6 +27,11 @@ class CustomDrawer extends StatelessWidget {
const Divider(height: 0.5, thickness: 0.5, color: Color(0xFFE5E5E5)),
// 日历热力图区域
_buildCalendarSection(context),
const Divider(height: 0.5, thickness: 0.5, color: Color(0xFFE5E5E5)),
// 菜单项列表
Expanded(
child: ListView(
@@ -411,6 +416,197 @@ class CustomDrawer extends StatelessWidget {
void _showToast(BuildContext context, String message) {
ToastUtil.show(context, message);
}
/// 构建日历热力图区域
Widget _buildCalendarSection(BuildContext context) {
return StatefulBuilder(
builder: (context, setState) {
return Consumer<AppProvider>(
builder: (context, provider, child) {
// 使用 StatefulBuilder 的状态来管理选中的月份
final selectedMonth = _calendarSelectedMonth ?? DateTime.now();
// 合并所有数据按日期
final Map<DateTime, _DailyData> dailyData = {};
for (final movie in provider.movies.where((m) => !m.isDeleted)) {
final date = DateTime(movie.createdAt.year, movie.createdAt.month, movie.createdAt.day);
dailyData.putIfAbsent(date, () => _DailyData()).movies++;
}
for (final book in provider.books.where((b) => !b.isDeleted)) {
final date = DateTime(book.createdAt.year, book.createdAt.month, book.createdAt.day);
dailyData.putIfAbsent(date, () => _DailyData()).books++;
}
for (final note in provider.notes.where((n) => !n.isDeleted)) {
final date = DateTime(note.createdAt.year, note.createdAt.month, note.createdAt.day);
dailyData.putIfAbsent(date, () => _DailyData()).notes++;
}
// 计算最大数量用于颜色强度
int maxCount = 0;
for (final data in dailyData.values) {
final count = data.total;
if (count > maxCount) maxCount = count;
}
if (maxCount == 0) maxCount = 1;
final year = selectedMonth.year;
final month = selectedMonth.month;
final daysInMonth = DateTime(year, month + 1, 0).day;
final firstWeekday = DateTime(year, month, 1).weekday % 7;
return Container(
width: double.infinity,
padding: const EdgeInsets.all(20),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
// 标题和月份切换
Row(
children: [
const Icon(
Icons.calendar_today,
size: 16,
color: Color(0xFF666666),
),
const SizedBox(width: 8),
// 上个月按钮
GestureDetector(
onTap: () {
setState(() {
_calendarSelectedMonth = DateTime(year, month - 1);
});
},
child: const Icon(
Icons.chevron_left,
size: 20,
color: Color(0xFF666666),
),
),
const SizedBox(width: 8),
Text(
'$year年$month月',
style: const TextStyle(
fontSize: 13,
fontWeight: FontWeight.w500,
color: Color(0xFF666666),
),
),
const SizedBox(width: 8),
// 下个月按钮
GestureDetector(
onTap: () {
setState(() {
_calendarSelectedMonth = DateTime(year, month + 1);
});
},
child: const Icon(
Icons.chevron_right,
size: 20,
color: Color(0xFF666666),
),
),
],
),
const SizedBox(height: 12),
// 星期标题 - 使用与日期相同的Wrap布局
Wrap(
spacing: 4,
runSpacing: 4,
children: const ['', '', '', '', '', '', '']
.map((d) => SizedBox(
width: 32,
height: 20,
child: Text(
d,
textAlign: TextAlign.center,
style: const TextStyle(fontSize: 10, color: Color(0xFF999999)),
),
))
.toList(),
),
const SizedBox(height: 4),
// 日历网格
Wrap(
spacing: 4,
runSpacing: 4,
children: [
// 空白填充
...List.generate(firstWeekday, (_) => const SizedBox(width: 32, height: 28)),
// 日期
...List.generate(daysInMonth, (index) {
final day = index + 1;
final date = DateTime(year, month, day);
final data = dailyData[date];
final count = data?.total ?? 0;
// 计算颜色强度
double opacity = 0.1;
if (count > 0) {
opacity = 0.3 + (count / maxCount * 0.7);
opacity = opacity.clamp(0.3, 1.0);
}
return Container(
width: 32,
height: 28,
decoration: BoxDecoration(
color: count > 0
? const Color(0xFF1A1A1A).withOpacity(opacity)
: const Color(0xFFF5F5F5),
borderRadius: BorderRadius.circular(4),
),
child: Center(
child: Text(
day.toString(),
style: TextStyle(
fontSize: 10,
color: count > 0 ? Colors.white : const Color(0xFF666666),
),
),
),
);
}),
],
),
// 图例
const SizedBox(height: 12),
Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
const Text('', style: TextStyle(fontSize: 10, color: Color(0xFF999999))),
const SizedBox(width: 4),
...List.generate(4, (index) {
final opacity = 0.2 + (index * 0.2);
return Container(
width: 10,
height: 10,
margin: const EdgeInsets.symmetric(horizontal: 1),
decoration: BoxDecoration(
color: const Color(0xFF1A1A1A).withOpacity(opacity),
borderRadius: BorderRadius.circular(2),
),
);
}),
const SizedBox(width: 4),
const Text('', style: TextStyle(fontSize: 10, color: Color(0xFF999999))),
],
),
],
),
);
});
});
}
// 日历选中的月份状态(用于 StatefulBuilder
static DateTime? _calendarSelectedMonth;
}
/// 回顾项数据类
@@ -427,3 +623,12 @@ class _MemoryItem {
this.imagePath,
});
}
/// 每日数据
class _DailyData {
int movies = 0;
int books = 0;
int notes = 0;
int get total => movies + books + notes;
}