feat:增加统计模块年份选择功能
This commit is contained in:
@@ -7,6 +7,7 @@ import 'package:flisp_app/widgets/common.dart';
|
||||
import 'package:flisp_app/widgets/flisp_widget.dart';
|
||||
import 'package:flisp_app/widgets/stats.dart';
|
||||
import 'package:flisp_app/widgets/todo_widget.dart';
|
||||
import 'package:flisp_app/widgets/year_selector.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class StatsPage extends StatefulWidget {
|
||||
@@ -18,7 +19,8 @@ class StatsPage extends StatefulWidget {
|
||||
|
||||
class StatsPageState extends State<StatsPage> {
|
||||
final double chartHeight = 400;
|
||||
final double statsHeight = 160;
|
||||
final double statsHeight = 120;
|
||||
int currentYear = DateTime.now().year;
|
||||
final FlispService flispService = FlispService();
|
||||
final TodoService todoService = TodoService();
|
||||
|
||||
@@ -33,11 +35,15 @@ class StatsPageState extends State<StatsPage> {
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
allFlisps = flispService.getAllFlisps();
|
||||
refreshStats();
|
||||
}
|
||||
|
||||
void refreshStats() {
|
||||
allFlisps = flispService.getAllFlispsByYear(currentYear);
|
||||
getFlispMonthlyStats(allFlisps);
|
||||
getFlispCategoryStats(allFlisps);
|
||||
|
||||
allTodos = todoService.getAllTodos();
|
||||
allTodos = todoService.getAllTodosByYear(currentYear);
|
||||
getTodoMonthlyStats(allTodos);
|
||||
getTodoMonthlyCompleteStats(allTodos);
|
||||
getTodoCategoryStats(allTodos);
|
||||
@@ -109,10 +115,15 @@ class StatsPageState extends State<StatsPage> {
|
||||
Widget _buildFlispStats(BuildContext context) {
|
||||
return Column(
|
||||
children: [
|
||||
buildChartTitle(context, '闪灵统计', Icons.analytics),
|
||||
const SizedBox(height: 3),
|
||||
buildChartDivider(context),
|
||||
const SizedBox(height: 3),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
children: [
|
||||
Icon(Icons.analytics, color: Theme.of(context).colorScheme.primary),
|
||||
const SizedBox(width: 3),
|
||||
const Text('闪灵统计'),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 5),
|
||||
Expanded(child: buildFlispStatsCard(allFlisps)),
|
||||
],
|
||||
);
|
||||
@@ -159,10 +170,15 @@ class StatsPageState extends State<StatsPage> {
|
||||
Widget _buildTodoStats(BuildContext context) {
|
||||
return Column(
|
||||
children: [
|
||||
buildChartTitle(context, '待办统计', Icons.analytics),
|
||||
const SizedBox(height: 3),
|
||||
buildChartDivider(context),
|
||||
const SizedBox(height: 3),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
children: [
|
||||
Icon(Icons.analytics, color: Theme.of(context).colorScheme.primary),
|
||||
const SizedBox(width: 3),
|
||||
const Text('待办统计'),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 5),
|
||||
Expanded(child: buildTodoStatsCard(allTodos)),
|
||||
],
|
||||
);
|
||||
@@ -212,14 +228,25 @@ class StatsPageState extends State<StatsPage> {
|
||||
padding: EdgeInsets.all(10),
|
||||
child: Column(
|
||||
children: [
|
||||
YearSelector(
|
||||
initialYear: DateTime.now().year,
|
||||
minYear: 2000,
|
||||
maxYear: 2100,
|
||||
onYearChanged: (year) => {
|
||||
setState(() {
|
||||
currentYear = year;
|
||||
refreshStats();
|
||||
})
|
||||
},
|
||||
),
|
||||
SizedBox(
|
||||
height: statsHeight,
|
||||
child: BuildCard(child: _buildFlispStats(context)),
|
||||
child: _buildFlispStats(context),
|
||||
),
|
||||
SizedBox(height: 10),
|
||||
SizedBox(
|
||||
height: statsHeight,
|
||||
child: BuildCard(child: _buildTodoStats(context)),
|
||||
child: _buildTodoStats(context),
|
||||
),
|
||||
SizedBox(height: 10),
|
||||
SizedBox(
|
||||
|
||||
@@ -19,6 +19,13 @@ class FlispService {
|
||||
return box.values.toList();
|
||||
}
|
||||
|
||||
List<Flisp> getAllFlispsByYear(int year) {
|
||||
return box.values
|
||||
.toList()
|
||||
.where((flisp) => flisp.createTime.year == year)
|
||||
.toList();
|
||||
}
|
||||
|
||||
Future<bool> updateFlisp(Flisp flisp) async {
|
||||
try {
|
||||
await flisp.save();
|
||||
|
||||
@@ -19,6 +19,13 @@ class TodoService {
|
||||
return box.values.toList();
|
||||
}
|
||||
|
||||
List<Todo> getAllTodosByYear(int year) {
|
||||
return box.values
|
||||
.toList()
|
||||
.where((todo) => todo.createTime.year == year)
|
||||
.toList();
|
||||
}
|
||||
|
||||
Future<bool> updateTodo(Todo todo) async {
|
||||
try {
|
||||
await todo.save();
|
||||
|
||||
@@ -212,3 +212,21 @@ Widget buildToggleSwitch<T extends Enum>({
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
Widget circleIconButton({
|
||||
required IconData icon,
|
||||
required VoidCallback onPressed,
|
||||
required BuildContext context,
|
||||
}) {
|
||||
return ElevatedButton(
|
||||
onPressed: onPressed,
|
||||
style: ElevatedButton.styleFrom(
|
||||
shape: CircleBorder(),
|
||||
elevation: 0,
|
||||
backgroundColor: Theme.of(context).colorScheme.primary,
|
||||
padding: EdgeInsets.zero,
|
||||
minimumSize: const Size(0, 0),
|
||||
),
|
||||
child: Icon(icon, color: Colors.white),
|
||||
);
|
||||
}
|
||||
|
||||
119
lib/widgets/year_selector.dart
Normal file
119
lib/widgets/year_selector.dart
Normal file
@@ -0,0 +1,119 @@
|
||||
import 'package:flisp_app/widgets/common.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class YearSelector extends StatefulWidget {
|
||||
final int initialYear;
|
||||
final int? minYear;
|
||||
final int? maxYear;
|
||||
final Function(int) onYearChanged;
|
||||
|
||||
const YearSelector({
|
||||
super.key,
|
||||
required this.initialYear,
|
||||
required this.onYearChanged,
|
||||
this.minYear,
|
||||
this.maxYear,
|
||||
});
|
||||
|
||||
@override
|
||||
State<YearSelector> createState() => _YearSelectorState();
|
||||
}
|
||||
|
||||
// SingleTickerProviderStateMixin 动画控制器
|
||||
class _YearSelectorState extends State<YearSelector>
|
||||
with SingleTickerProviderStateMixin {
|
||||
late int _currentYear;
|
||||
|
||||
// 用于动画效果
|
||||
late AnimationController _animationController;
|
||||
late Animation<double> _scaleAnimation;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_currentYear = widget.initialYear;
|
||||
|
||||
// 初始化动画控制器
|
||||
_animationController = AnimationController(
|
||||
vsync: this,
|
||||
duration: const Duration(milliseconds: 200),
|
||||
);
|
||||
|
||||
// 缩放动画
|
||||
_scaleAnimation = Tween<double>(begin: 1.0, end: 1.1).animate(
|
||||
CurvedAnimation(parent: _animationController, curve: Curves.easeInOut),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_animationController.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
/// 切换到上一年
|
||||
void _previousYear() {
|
||||
if (widget.minYear == null || _currentYear > widget.minYear!) {
|
||||
_animateYearChange(() {
|
||||
setState(() {
|
||||
_currentYear--;
|
||||
});
|
||||
widget.onYearChanged(_currentYear);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/// 切换到下一年
|
||||
void _nextYear() {
|
||||
if (widget.maxYear == null || _currentYear < widget.maxYear!) {
|
||||
_animateYearChange(() {
|
||||
setState(() {
|
||||
_currentYear++;
|
||||
});
|
||||
widget.onYearChanged(_currentYear);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/// 年份变化时的动画效果
|
||||
void _animateYearChange(VoidCallback onComplete) {
|
||||
_animationController.forward().then((_) {
|
||||
onComplete();
|
||||
_animationController.reverse();
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
circleIconButton(
|
||||
context: context,
|
||||
icon: Icons.chevron_left,
|
||||
onPressed: () => _previousYear(),
|
||||
),
|
||||
// 年份显示
|
||||
AnimatedBuilder(
|
||||
animation: _scaleAnimation,
|
||||
builder: (context, child) {
|
||||
return Transform.scale(scale: _scaleAnimation.value, child: child);
|
||||
},
|
||||
child: Text(
|
||||
'$_currentYear',
|
||||
style: TextStyle(
|
||||
fontSize: 18,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: Theme.of(context).primaryColor,
|
||||
),
|
||||
),
|
||||
),
|
||||
circleIconButton(
|
||||
context: context,
|
||||
icon: Icons.chevron_right,
|
||||
onPressed: () => _nextYear(),
|
||||
)
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user