219 lines
5.3 KiB
TypeScript
219 lines
5.3 KiB
TypeScript
// utils/todoStorage.ts
|
|
|
|
export interface ITodo {
|
|
id: string;
|
|
text: string;
|
|
completed: boolean;
|
|
priority: 'high' | 'medium' | 'low';
|
|
createdAt: number;
|
|
completedAt?: number;
|
|
category?: string;
|
|
deadline?: number;
|
|
note?: string;
|
|
}
|
|
|
|
export interface ITodoStats {
|
|
total: number;
|
|
completed: number;
|
|
pending: number;
|
|
completionRate: number;
|
|
todayCompleted: number;
|
|
}
|
|
|
|
class TodoStorage {
|
|
private readonly STORAGE_KEY = 'pure_todo_data';
|
|
private readonly STATS_KEY = 'pure_todo_stats';
|
|
|
|
// 获取所有待办事项
|
|
getAllTodos(): ITodo[] {
|
|
try {
|
|
const data = wx.getStorageSync(this.STORAGE_KEY);
|
|
return data ? JSON.parse(data) : [];
|
|
} catch (error) {
|
|
console.error('获取待办事项失败:', error);
|
|
return [];
|
|
}
|
|
}
|
|
|
|
// 保存所有待办事项
|
|
saveAllTodos(todos: ITodo[]): void {
|
|
try {
|
|
wx.setStorageSync(this.STORAGE_KEY, JSON.stringify(todos));
|
|
this.updateStats(todos);
|
|
} catch (error) {
|
|
console.error('保存待办事项失败:', error);
|
|
}
|
|
}
|
|
|
|
// 添加新待办事项
|
|
addTodo(
|
|
text: string,
|
|
priority: 'high' | 'medium' | 'low' = 'medium',
|
|
category?: string,
|
|
deadline?: number,
|
|
note?: string
|
|
): ITodo {
|
|
const todos = this.getAllTodos();
|
|
const newTodo: ITodo = {
|
|
id: this.generateId(),
|
|
text: text.trim(),
|
|
completed: false,
|
|
priority,
|
|
createdAt: Date.now(),
|
|
category,
|
|
deadline,
|
|
note
|
|
};
|
|
|
|
todos.unshift(newTodo);
|
|
this.saveAllTodos(todos);
|
|
return newTodo;
|
|
}
|
|
|
|
// 更新待办事项
|
|
updateTodo(id: string, updates: Partial<ITodo>): boolean {
|
|
const todos = this.getAllTodos();
|
|
const index = todos.findIndex(todo => todo.id === id);
|
|
|
|
if (index !== -1) {
|
|
todos[index] = { ...todos[index], ...updates };
|
|
if (updates.completed !== undefined) {
|
|
todos[index].completedAt = updates.completed ? Date.now() : undefined;
|
|
}
|
|
this.saveAllTodos(todos);
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
// 删除待办事项
|
|
deleteTodo(id: string): boolean {
|
|
const todos = this.getAllTodos();
|
|
const filteredTodos = todos.filter(todo => todo.id !== id);
|
|
|
|
if (filteredTodos.length !== todos.length) {
|
|
this.saveAllTodos(filteredTodos);
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
// 切换完成状态
|
|
toggleTodo(id: string): boolean {
|
|
const todos = this.getAllTodos();
|
|
const todo = todos.find(t => t.id === id);
|
|
|
|
if (todo) {
|
|
return this.updateTodo(id, {
|
|
completed: !todo.completed,
|
|
completedAt: !todo.completed ? Date.now() : undefined
|
|
});
|
|
}
|
|
return false;
|
|
}
|
|
|
|
// 获取统计信息
|
|
getStats(): ITodoStats {
|
|
try {
|
|
const data = wx.getStorageSync(this.STATS_KEY);
|
|
return data ? JSON.parse(data) : this.calculateStats();
|
|
} catch (error) {
|
|
return this.calculateStats();
|
|
}
|
|
}
|
|
|
|
// 计算统计信息
|
|
private calculateStats(): ITodoStats {
|
|
const todos = this.getAllTodos();
|
|
const total = todos.length;
|
|
const completed = todos.filter(todo => todo.completed).length;
|
|
const pending = total - completed;
|
|
const completionRate = total > 0 ? Math.round((completed / total) * 100) : 0;
|
|
|
|
// 计算今日完成的任务
|
|
const today = new Date();
|
|
today.setHours(0, 0, 0, 0);
|
|
const todayCompleted = todos.filter(todo =>
|
|
todo.completed && todo.completedAt && todo.completedAt >= today.getTime()
|
|
).length;
|
|
|
|
return {
|
|
total,
|
|
completed,
|
|
pending,
|
|
completionRate,
|
|
todayCompleted
|
|
};
|
|
}
|
|
|
|
// 更新统计信息
|
|
private updateStats(todos: ITodo[]): void {
|
|
const stats = this.calculateStats();
|
|
try {
|
|
wx.setStorageSync(this.STATS_KEY, JSON.stringify(stats));
|
|
} catch (error) {
|
|
console.error('更新统计信息失败:', error);
|
|
}
|
|
}
|
|
|
|
// 生成唯一ID
|
|
private generateId(): string {
|
|
return Date.now().toString(36) + Math.random().toString(36).substr(2);
|
|
}
|
|
|
|
// 按优先级获取待办事项
|
|
getTodosByPriority(priority?: 'high' | 'medium' | 'low'): ITodo[] {
|
|
const todos = this.getAllTodos();
|
|
if (priority) {
|
|
return todos.filter(todo => todo.priority === priority);
|
|
}
|
|
return todos;
|
|
}
|
|
|
|
// 获取今日待办事项
|
|
getTodayTodos(): ITodo[] {
|
|
const todos = this.getAllTodos();
|
|
const today = new Date();
|
|
today.setHours(0, 0, 0, 0);
|
|
|
|
return todos.filter(todo => {
|
|
const todoDate = new Date(todo.createdAt);
|
|
todoDate.setHours(0, 0, 0, 0);
|
|
return todoDate.getTime() === today.getTime();
|
|
});
|
|
}
|
|
|
|
// 清空所有数据
|
|
clearAllData(): void {
|
|
try {
|
|
wx.removeStorageSync(this.STORAGE_KEY);
|
|
wx.removeStorageSync(this.STATS_KEY);
|
|
} catch (error) {
|
|
console.error('清空数据失败:', error);
|
|
}
|
|
}
|
|
|
|
// 导出数据
|
|
exportData(): string {
|
|
const todos = this.getAllTodos();
|
|
const stats = this.getStats();
|
|
return JSON.stringify({ todos, stats, exportTime: Date.now() });
|
|
}
|
|
|
|
// 导入数据
|
|
importData(dataString: string): boolean {
|
|
try {
|
|
const data = JSON.parse(dataString);
|
|
if (data.todos && Array.isArray(data.todos)) {
|
|
this.saveAllTodos(data.todos);
|
|
return true;
|
|
}
|
|
return false;
|
|
} catch (error) {
|
|
console.error('导入数据失败:', error);
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
|
|
export const todoStorage = new TodoStorage();
|