461 lines
13 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// pages/list/list.ts
import { todoStorage, ITodo, ITodoStats } from '../../utils/todoStorage';
Component({
data: {
activeTab: 'list',
todos: [] as ITodo[],
filteredTodos: [] as ITodo[],
stats: {} as ITodoStats,
searchText: '',
filterStatus: 'all' as 'all' | 'pending' | 'completed',
filterPriority: 'all' as 'all' | 'high' | 'medium' | 'low',
sortBy: 'createdAt' as 'createdAt' | 'priority' | 'text',
pendingCount: 0,
completedCount: 0,
completionRate: 0,
showAddSheet: false,
showDateTimePicker: false,
newTodoText: '',
newTodoPriority: 'medium' as 'high' | 'medium' | 'low',
newTodoCategory: '',
newTodoDeadline: 0,
newTodoNote: '',
dateTimeRange: [
[], // 年月日
[] // 时分
] as string[][],
dateTimeValue: [0, 0] as number[]
},
lifetimes: {
attached() {
this.loadData();
}
},
pageLifetimes: {
show() {
this.loadData();
}
},
methods: {
// 加载数据
loadData() {
const todos = todoStorage.getAllTodos();
const stats = todoStorage.getStats();
this.setData({ todos, stats });
this.applyFilters();
},
// 筛选和排序任务
applyFilters() {
let filtered = [...this.data.todos];
// 搜索筛选
if (this.data.searchText) {
filtered = filtered.filter(todo =>
todo.text.toLowerCase().includes(this.data.searchText.toLowerCase())
);
}
// 状态筛选
if (this.data.filterStatus === 'pending') {
filtered = filtered.filter(todo => !todo.completed);
} else if (this.data.filterStatus === 'completed') {
filtered = filtered.filter(todo => todo.completed);
}
// 优先级筛选
if (this.data.filterPriority !== 'all') {
filtered = filtered.filter(todo => todo.priority === this.data.filterPriority);
}
// 排序
filtered.sort((a, b) => {
switch (this.data.sortBy) {
case 'createdAt':
return b.createdAt - a.createdAt;
case 'priority': {
const priorityOrder = { high: 3, medium: 2, low: 1 };
return priorityOrder[b.priority] - priorityOrder[a.priority];
}
case 'text':
return a.text.localeCompare(b.text);
default:
return 0;
}
});
// 计算统计数据
const pendingCount = filtered.filter(todo => !todo.completed).length;
const completedCount = filtered.filter(todo => todo.completed).length;
const completionRate = filtered.length > 0 ? Math.round((completedCount / filtered.length) * 100) : 0;
this.setData({
filteredTodos: filtered,
pendingCount,
completedCount,
completionRate
});
},
// 搜索输入
onSearchInput(e: any) {
this.setData({ searchText: e.detail.value }, () => {
this.applyFilters();
});
},
// 状态筛选
onStatusFilterChange(e: any) {
this.setData({ filterStatus: e.currentTarget.dataset.value }, () => {
this.applyFilters();
});
},
// 优先级筛选
onPriorityFilterChange(e: any) {
this.setData({ filterPriority: e.currentTarget.dataset.value }, () => {
this.applyFilters();
});
},
// 排序
onSortChange(e: any) {
this.setData({ sortBy: e.currentTarget.dataset.value }, () => {
this.applyFilters();
});
},
// 显示添加半屏
showAddSheet() {
this.initDateTimeRange();
this.setData({
showAddSheet: true,
newTodoText: '',
newTodoPriority: 'medium',
newTodoCategory: '',
newTodoDeadline: 0,
newTodoNote: ''
});
},
// 隐藏添加半屏
hideAddSheet() {
this.setData({ showAddSheet: false });
},
// 阻止事件冒泡
stopPropagation() {
// 空函数,用于阻止事件冒泡
},
// 输入新任务
onNewTodoInput(e: any) {
this.setData({ newTodoText: e.detail.value });
},
// 输入备注
onNewTodoNoteInput(e: any) {
this.setData({ newTodoNote: e.detail.value });
},
// 设置优先级
onPriorityChange(e: any) {
this.setData({ newTodoPriority: e.currentTarget.dataset.value });
},
// 设置分类
onCategoryChange(e: any) {
this.setData({ newTodoCategory: e.currentTarget.dataset.value });
},
// 初始化日期时间选择器
initDateTimeRange() {
const now = new Date();
const year = now.getFullYear();
const month = now.getMonth();
const date = now.getDate();
// 生成日期选项今天及之后30天
const dateOptions = [];
for (let i = 0; i < 30; i++) {
const d = new Date(year, month, date + i);
const dateStr = this.formatDateOption(d);
dateOptions.push(dateStr);
}
// 生成时间选项
const timeOptions = [];
for (let h = 0; h < 24; h++) {
for (let m = 0; m < 60; m += 30) {
const timeStr = `${h.toString().padStart(2, '0')}:${m.toString().padStart(2, '0')}`;
timeOptions.push(timeStr);
}
}
this.setData({
dateTimeRange: [dateOptions, timeOptions],
dateTimeValue: [0, 16] // 默认选择今天 08:00
});
},
// 格式化日期选项
formatDateOption(date: Date): string {
const now = new Date();
const today = new Date(now.getFullYear(), now.getMonth(), now.getDate());
const tomorrow = new Date(today.getTime() + 24 * 60 * 60 * 1000);
if (date.getTime() === today.getTime()) {
return '今天';
} else if (date.getTime() === tomorrow.getTime()) {
return '明天';
} else {
return `${date.getMonth() + 1}${date.getDate()}`;
}
},
// 显示日期时间选择器
showDateTimePicker() {
// 先触发选择器
const that = this;
wx.showActionSheet({
itemList: ['今天', '明天', '后天', '自定义日期'],
success(res) {
const now = new Date();
let selectedDate = new Date();
switch(res.tapIndex) {
case 0: // 今天
selectedDate = new Date(now.getFullYear(), now.getMonth(), now.getDate(), 18, 0);
break;
case 1: // 明天
selectedDate = new Date(now.getFullYear(), now.getMonth(), now.getDate() + 1, 18, 0);
break;
case 2: // 后天
selectedDate = new Date(now.getFullYear(), now.getMonth(), now.getDate() + 2, 18, 0);
break;
case 3: // 自定义
that.showCustomDatePicker();
return;
}
that.setData({
newTodoDeadline: selectedDate.getTime()
});
}
});
},
// 显示自定义日期选择器
showCustomDatePicker() {
const now = new Date();
const currentDate = `${now.getFullYear()}-${(now.getMonth() + 1).toString().padStart(2, '0')}-${now.getDate().toString().padStart(2, '0')}`;
const currentTime = `${now.getHours().toString().padStart(2, '0')}:${now.getMinutes().toString().padStart(2, '0')}`;
wx.showModal({
title: '选择截止时间',
content: '请在系统设置中选择日期和时间',
showCancel: true,
cancelText: '取消',
confirmText: '使用当前时间',
success: (res) => {
if (res.confirm) {
// 使用当前时间加1小时作为默认截止时间
const deadline = new Date();
deadline.setHours(deadline.getHours() + 1);
this.setData({
newTodoDeadline: deadline.getTime()
});
}
}
});
},
// 清除截止时间
clearDeadline() {
this.setData({
newTodoDeadline: 0
});
},
// 隐藏日期时间选择器
hideDateTimePicker() {
this.setData({ showDateTimePicker: false });
},
// 日期时间选择器改变
onDateTimeChange(e: any) {
const [dateIndex, timeIndex] = e.detail.value;
const { dateTimeRange } = this.data;
// 计算选择的日期时间
const now = new Date();
const selectedDate = new Date(now.getFullYear(), now.getMonth(), now.getDate() + dateIndex);
const timeStr = dateTimeRange[1][timeIndex];
const [hours, minutes] = timeStr.split(':').map(Number);
selectedDate.setHours(hours, minutes, 0, 0);
this.setData({
dateTimeValue: [dateIndex, timeIndex],
newTodoDeadline: selectedDate.getTime(),
showDateTimePicker: false
});
},
// 格式化日期时间显示
formatDateTime(timestamp: number): string {
const date = new Date(timestamp);
const now = new Date();
const today = new Date(now.getFullYear(), now.getMonth(), now.getDate());
const tomorrow = new Date(today.getTime() + 24 * 60 * 60 * 1000);
let dateStr = '';
if (date.toDateString() === today.toDateString()) {
dateStr = '今天';
} else if (date.toDateString() === tomorrow.toDateString()) {
dateStr = '明天';
} else {
dateStr = `${date.getMonth() + 1}${date.getDate()}`;
}
const timeStr = `${date.getHours().toString().padStart(2, '0')}:${date.getMinutes().toString().padStart(2, '0')}`;
return `${dateStr} ${timeStr}`;
},
// 添加新任务
addTodo() {
const { newTodoText, newTodoPriority, newTodoCategory, newTodoDeadline, newTodoNote } = this.data;
if (newTodoText.trim() === '') {
wx.showToast({
title: '请输入任务内容',
icon: 'none'
});
return;
}
todoStorage.addTodo(
newTodoText.trim(),
newTodoPriority,
newTodoCategory || undefined,
newTodoDeadline || undefined,
newTodoNote.trim() || undefined
);
this.hideAddSheet();
this.loadData();
wx.showToast({
title: '任务已添加',
icon: 'success'
});
},
// 切换任务状态
toggleTodo(e: any) {
const id = e.currentTarget.dataset.id;
todoStorage.toggleTodo(id);
this.loadData();
},
// 编辑任务
editTodo(e: any) {
const id = e.currentTarget.dataset.id;
const todo = this.data.todos.find(t => t.id === id);
if (todo) {
wx.showModal({
title: '编辑任务',
content: '编辑功能开发中,敬请期待!',
showCancel: false
});
}
},
// 删除任务
deleteTodo(e: any) {
const id = e.currentTarget.dataset.id;
wx.showModal({
title: '确认删除',
content: '确定要删除这个任务吗?',
success: (res) => {
if (res.confirm) {
todoStorage.deleteTodo(id);
this.loadData();
wx.showToast({
title: '已删除',
icon: 'success'
});
}
}
});
},
// 清空已完成任务
clearCompleted() {
wx.showModal({
title: '确认清空',
content: '确定要清空所有已完成的任务吗?此操作不可恢复。',
success: (res) => {
if (res.confirm) {
const todos = this.data.todos.filter(todo => !todo.completed);
todoStorage.saveAllTodos(todos);
this.loadData();
wx.showToast({
title: '已清空',
icon: 'success'
});
}
}
});
},
// 导出数据
exportData() {
const data = todoStorage.exportData();
wx.setClipboardData({
data: data,
success: () => {
wx.showToast({
title: '数据已复制到剪贴板',
icon: 'success'
});
}
});
},
// 格式化时间
formatTime(timestamp: number): string {
const date = new Date(timestamp);
const now = new Date();
const diff = now.getTime() - date.getTime();
const days = Math.floor(diff / (1000 * 60 * 60 * 24));
if (days === 0) {
return '今天';
} else if (days === 1) {
return '昨天';
} else if (days < 7) {
return `${days}天前`;
} else {
return date.toLocaleDateString();
}
},
// 标签页切换
onTabChange(e: any) {
const targetPage = e.detail.value;
if (targetPage === 'home') {
wx.switchTab({ url: '/pages/index/index' });
} else if (targetPage === 'statistics') {
wx.switchTab({ url: '/pages/statistics/statistics' });
} else if (targetPage === 'settings') {
wx.switchTab({ url: '/pages/settings/settings' });
}
}
}
});