feat:增加待办排序UI功能
This commit is contained in:
@@ -111,3 +111,5 @@ enum TodoTab {
|
|||||||
|
|
||||||
const TodoTab(this.label);
|
const TodoTab(this.label);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum TodoSortMode { time, priority }
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ class TodoPageState extends State<TodoPage> {
|
|||||||
|
|
||||||
late List<Todo> _todos;
|
late List<Todo> _todos;
|
||||||
TodoTab _currentTab = TodoTab.active;
|
TodoTab _currentTab = TodoTab.active;
|
||||||
|
late TodoSortMode _selectedMode = TodoSortMode.time;
|
||||||
|
|
||||||
// 获取过滤后的待办事项
|
// 获取过滤后的待办事项
|
||||||
List<Todo> get _activeTodos => getActiveTodos(_currentTab, _todos);
|
List<Todo> get _activeTodos => getActiveTodos(_currentTab, _todos);
|
||||||
@@ -37,7 +38,13 @@ class TodoPageState extends State<TodoPage> {
|
|||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
_todos = todoService.getAllTodos();
|
_refreshTodos();
|
||||||
|
}
|
||||||
|
|
||||||
|
void _refreshTodos() {
|
||||||
|
setState(() {
|
||||||
|
_todos = todoService.getAllTodos(_selectedMode);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -45,6 +52,7 @@ class TodoPageState extends State<TodoPage> {
|
|||||||
return Column(
|
return Column(
|
||||||
children: [
|
children: [
|
||||||
_buildTodoTabs(),
|
_buildTodoTabs(),
|
||||||
|
_buildTodoSegment(),
|
||||||
Expanded(child: _buildActiveTodoList(context)),
|
Expanded(child: _buildActiveTodoList(context)),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
@@ -62,6 +70,36 @@ class TodoPageState extends State<TodoPage> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Widget _buildTodoSegment() {
|
||||||
|
final colors = Theme.of(context).colorScheme;
|
||||||
|
|
||||||
|
return SegmentedButton<TodoSortMode>(
|
||||||
|
showSelectedIcon: false,
|
||||||
|
emptySelectionAllowed: false,
|
||||||
|
multiSelectionEnabled: false,
|
||||||
|
segments: [
|
||||||
|
ButtonSegment<TodoSortMode>(
|
||||||
|
value: TodoSortMode.time,
|
||||||
|
icon: Icon(Icons.access_time_filled, size: 16),
|
||||||
|
label: const Text('时间', style: TextStyle(fontSize: 12)),
|
||||||
|
),
|
||||||
|
ButtonSegment<TodoSortMode>(
|
||||||
|
value: TodoSortMode.priority,
|
||||||
|
icon: Icon(Icons.flag_outlined, size: 16,),
|
||||||
|
label: const Text('优先级', style: TextStyle(fontSize: 12)),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
selected: {_selectedMode},
|
||||||
|
onSelectionChanged: (Set<TodoSortMode> newSelection) {
|
||||||
|
setState(() {
|
||||||
|
_selectedMode = newSelection.first;
|
||||||
|
});
|
||||||
|
_refreshTodos();
|
||||||
|
},
|
||||||
|
style: buildSegmentStyle(colors),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
Widget _buildActiveTodoList(BuildContext context) {
|
Widget _buildActiveTodoList(BuildContext context) {
|
||||||
return _activeTodos.isEmpty
|
return _activeTodos.isEmpty
|
||||||
? buildEmptyState(context, _currentTab)
|
? buildEmptyState(context, _currentTab)
|
||||||
@@ -142,9 +180,7 @@ class TodoPageState extends State<TodoPage> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
setState(() {
|
_refreshTodos();
|
||||||
_todos = todoService.getAllTodos();
|
|
||||||
});
|
|
||||||
|
|
||||||
if (isSuccess) {
|
if (isSuccess) {
|
||||||
showSuccessDialog(context, isEditing ? '更新成功' : '添加成功');
|
showSuccessDialog(context, isEditing ? '更新成功' : '添加成功');
|
||||||
@@ -157,9 +193,7 @@ class TodoPageState extends State<TodoPage> {
|
|||||||
await notifyService.cancelNotification(todo.id);
|
await notifyService.cancelNotification(todo.id);
|
||||||
bool isSuccess = await todoService.deleteTodo(todo);
|
bool isSuccess = await todoService.deleteTodo(todo);
|
||||||
|
|
||||||
setState(() {
|
_refreshTodos();
|
||||||
_todos = todoService.getAllTodos();
|
|
||||||
});
|
|
||||||
|
|
||||||
if (isSuccess) {
|
if (isSuccess) {
|
||||||
showSuccessDialog(context, '删除成功');
|
showSuccessDialog(context, '删除成功');
|
||||||
|
|||||||
@@ -15,9 +15,29 @@ class TodoService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
List<Todo> getAllTodos() {
|
List<Todo> getAllTodos(TodoSortMode mode) {
|
||||||
|
if (mode == TodoSortMode.time) {
|
||||||
return box.values.toList()
|
return box.values.toList()
|
||||||
..sort((a, b) => b.updateTime.compareTo(a.updateTime));
|
..sort((a, b) {
|
||||||
|
// 先按是否有 dueDate 分组:有时间的排前面
|
||||||
|
if (a.dueDate != null && b.dueDate == null) {
|
||||||
|
return -1; // a有时间,b没有时间,a排在前面
|
||||||
|
} else if (a.dueDate == null && b.dueDate != null) {
|
||||||
|
return 1; // a没有时间,b有时间,b排在前面
|
||||||
|
}
|
||||||
|
// 都有 dueDate,按 dueDate 排序
|
||||||
|
else if (a.dueDate != null && b.dueDate != null) {
|
||||||
|
return a.dueDate!.compareTo(b.dueDate!); // 最近的在前面
|
||||||
|
}
|
||||||
|
// 都没有 dueDate,按 updateTime 排序
|
||||||
|
else {
|
||||||
|
return b.updateTime.compareTo(a.updateTime); // 最近的在前面
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
return box.values.toList()
|
||||||
|
..sort((a, b) => b.priorityIndex.compareTo(a.priorityIndex));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
List<Todo> getAllTodosByYear(int year) {
|
List<Todo> getAllTodosByYear(int year) {
|
||||||
|
|||||||
@@ -213,6 +213,41 @@ Widget buildToggleSwitch<T extends Enum>({
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ButtonStyle buildSegmentStyle(ColorScheme colors) {
|
||||||
|
return ButtonStyle(
|
||||||
|
side: WidgetStateProperty.all<BorderSide>(
|
||||||
|
const BorderSide(color: Colors.transparent, width: 0),
|
||||||
|
),
|
||||||
|
iconColor: WidgetStateProperty.resolveWith<Color>(
|
||||||
|
(Set<WidgetState> states) {
|
||||||
|
if (states.contains(WidgetState.selected)) {
|
||||||
|
return colors.onPrimary;
|
||||||
|
}
|
||||||
|
return Colors.grey;
|
||||||
|
},
|
||||||
|
),
|
||||||
|
backgroundColor: WidgetStateProperty.resolveWith<Color>((
|
||||||
|
Set<WidgetState> states,
|
||||||
|
) {
|
||||||
|
if (states.contains(WidgetState.selected)) {
|
||||||
|
return colors.primary;
|
||||||
|
}
|
||||||
|
return Colors.grey.shade200;
|
||||||
|
}),
|
||||||
|
foregroundColor: WidgetStateProperty.resolveWith<Color>((
|
||||||
|
Set<WidgetState> states,
|
||||||
|
) {
|
||||||
|
if (states.contains(WidgetState.selected)) {
|
||||||
|
return colors.onPrimary;
|
||||||
|
}
|
||||||
|
return colors.onSurface;
|
||||||
|
}),
|
||||||
|
shape: WidgetStateProperty.all<RoundedRectangleBorder>(
|
||||||
|
RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
Widget circleIconButton({
|
Widget circleIconButton({
|
||||||
required IconData icon,
|
required IconData icon,
|
||||||
required VoidCallback onPressed,
|
required VoidCallback onPressed,
|
||||||
|
|||||||
Reference in New Issue
Block a user