277 lines
7.4 KiB
JavaScript
277 lines
7.4 KiB
JavaScript
import { defineStore } from 'pinia'
|
|
import { ref, computed } from 'vue'
|
|
|
|
export const useTaskStore = defineStore('task', () => {
|
|
// 状态
|
|
const tasks = ref([])
|
|
const currentFilter = ref('all') // all, pending, completed, overdue
|
|
const currentSort = ref('dueDate') // dueDate, priority, created
|
|
const searchKeyword = ref('')
|
|
|
|
// 计算属性
|
|
const filteredTasks = computed(() => {
|
|
let filtered = tasks.value
|
|
|
|
// 按状态过滤
|
|
if (currentFilter.value === 'pending') {
|
|
filtered = filtered.filter(task => !task.completed)
|
|
} else if (currentFilter.value === 'completed') {
|
|
filtered = filtered.filter(task => task.completed)
|
|
} else if (currentFilter.value === 'overdue') {
|
|
const now = new Date()
|
|
filtered = filtered.filter(task =>
|
|
!task.completed &&
|
|
task.dueDate &&
|
|
new Date(task.dueDate) < now
|
|
)
|
|
}
|
|
|
|
// 按关键词搜索
|
|
if (searchKeyword.value) {
|
|
const keyword = searchKeyword.value.toLowerCase()
|
|
filtered = filtered.filter(task =>
|
|
task.title.toLowerCase().includes(keyword) ||
|
|
task.description.toLowerCase().includes(keyword) ||
|
|
task.tags.some(tag => tag.toLowerCase().includes(keyword))
|
|
)
|
|
}
|
|
|
|
// 排序
|
|
filtered.sort((a, b) => {
|
|
switch (currentSort.value) {
|
|
case 'priority':
|
|
const priorityOrder = { high: 3, medium: 2, low: 1 }
|
|
return (priorityOrder[b.priority] || 0) - (priorityOrder[a.priority] || 0)
|
|
case 'created':
|
|
return new Date(b.createdAt) - new Date(a.createdAt)
|
|
case 'dueDate':
|
|
default:
|
|
if (!a.dueDate && !b.dueDate) return 0
|
|
if (!a.dueDate) return 1
|
|
if (!b.dueDate) return -1
|
|
return new Date(a.dueDate) - new Date(b.dueDate)
|
|
}
|
|
})
|
|
|
|
return filtered
|
|
})
|
|
|
|
const taskStats = computed(() => {
|
|
const total = tasks.value.length
|
|
const completed = tasks.value.filter(task => task.completed).length
|
|
const pending = total - completed
|
|
const overdue = tasks.value.filter(task =>
|
|
!task.completed &&
|
|
task.dueDate &&
|
|
new Date(task.dueDate) < new Date()
|
|
).length
|
|
|
|
return {
|
|
total,
|
|
completed,
|
|
pending,
|
|
overdue,
|
|
completionRate: total > 0 ? Math.round((completed / total) * 100) : 0
|
|
}
|
|
})
|
|
|
|
// 方法
|
|
const addTask = (taskData) => {
|
|
const newTask = {
|
|
id: Date.now().toString(),
|
|
title: taskData.title,
|
|
description: taskData.description || '',
|
|
priority: taskData.priority || 'medium',
|
|
dueDate: taskData.dueDate || null,
|
|
tags: taskData.tags || [],
|
|
completed: false,
|
|
createdAt: new Date().toISOString(),
|
|
updatedAt: new Date().toISOString()
|
|
}
|
|
|
|
tasks.value.unshift(newTask)
|
|
saveToStorage()
|
|
return newTask
|
|
}
|
|
|
|
const updateTask = (id, updates) => {
|
|
const index = tasks.value.findIndex(task => task.id === id)
|
|
if (index !== -1) {
|
|
tasks.value[index] = {
|
|
...tasks.value[index],
|
|
...updates,
|
|
updatedAt: new Date().toISOString()
|
|
}
|
|
saveToStorage()
|
|
return tasks.value[index]
|
|
}
|
|
return null
|
|
}
|
|
|
|
const deleteTask = (id) => {
|
|
const index = tasks.value.findIndex(task => task.id === id)
|
|
if (index !== -1) {
|
|
tasks.value.splice(index, 1)
|
|
saveToStorage()
|
|
return true
|
|
}
|
|
return false
|
|
}
|
|
|
|
const toggleTask = (id) => {
|
|
const task = tasks.value.find(task => task.id === id)
|
|
if (task) {
|
|
task.completed = !task.completed
|
|
task.updatedAt = new Date().toISOString()
|
|
saveToStorage()
|
|
return task
|
|
}
|
|
return null
|
|
}
|
|
|
|
const setFilter = (filter) => {
|
|
currentFilter.value = filter
|
|
}
|
|
|
|
const setSort = (sort) => {
|
|
currentSort.value = sort
|
|
}
|
|
|
|
const setSearchKeyword = (keyword) => {
|
|
searchKeyword.value = keyword
|
|
}
|
|
|
|
const clearCompleted = () => {
|
|
tasks.value = tasks.value.filter(task => !task.completed)
|
|
saveToStorage()
|
|
}
|
|
|
|
const getTaskById = (id) => {
|
|
return tasks.value.find(task => task.id === id)
|
|
}
|
|
|
|
const getTasksByTag = (tag) => {
|
|
return tasks.value.filter(task => task.tags.includes(tag))
|
|
}
|
|
|
|
const getOverdueTasks = () => {
|
|
const now = new Date()
|
|
return tasks.value.filter(task =>
|
|
!task.completed &&
|
|
task.dueDate &&
|
|
new Date(task.dueDate) < now
|
|
)
|
|
}
|
|
|
|
const getTodayTasks = () => {
|
|
const today = new Date().toDateString()
|
|
return tasks.value.filter(task =>
|
|
!task.completed &&
|
|
task.dueDate &&
|
|
new Date(task.dueDate).toDateString() === today
|
|
)
|
|
}
|
|
|
|
// 本地存储
|
|
const saveToStorage = () => {
|
|
try {
|
|
uni.setStorageSync('tasks', JSON.stringify(tasks.value))
|
|
} catch (error) {
|
|
console.error('保存任务数据失败:', error)
|
|
}
|
|
}
|
|
|
|
const loadFromStorage = () => {
|
|
try {
|
|
const stored = uni.getStorageSync('tasks')
|
|
if (stored) {
|
|
tasks.value = JSON.parse(stored)
|
|
}
|
|
} catch (error) {
|
|
console.error('加载任务数据失败:', error)
|
|
}
|
|
}
|
|
|
|
// 初始化示例数据
|
|
const initSampleData = () => {
|
|
if (tasks.value.length === 0) {
|
|
const sampleTasks = [
|
|
{
|
|
id: '1',
|
|
title: '完成项目需求分析',
|
|
description: '分析用户需求,制定详细的功能规格说明',
|
|
priority: 'high',
|
|
dueDate: new Date(Date.now() + 2 * 24 * 60 * 60 * 1000).toISOString(),
|
|
tags: ['工作', '项目'],
|
|
completed: false,
|
|
createdAt: new Date(Date.now() - 3 * 24 * 60 * 60 * 1000).toISOString(),
|
|
updatedAt: new Date(Date.now() - 3 * 24 * 60 * 60 * 1000).toISOString()
|
|
},
|
|
{
|
|
id: '2',
|
|
title: '准备会议材料',
|
|
description: '准备下周团队会议的PPT和资料',
|
|
priority: 'medium',
|
|
dueDate: new Date(Date.now() + 1 * 24 * 60 * 60 * 1000).toISOString(),
|
|
tags: ['工作', '会议'],
|
|
completed: false,
|
|
createdAt: new Date(Date.now() - 2 * 24 * 60 * 60 * 1000).toISOString(),
|
|
updatedAt: new Date(Date.now() - 2 * 24 * 60 * 60 * 1000).toISOString()
|
|
},
|
|
{
|
|
id: '3',
|
|
title: '购买生活用品',
|
|
description: '去超市购买日用品和食材',
|
|
priority: 'low',
|
|
dueDate: null,
|
|
tags: ['生活', '购物'],
|
|
completed: true,
|
|
createdAt: new Date(Date.now() - 5 * 24 * 60 * 60 * 1000).toISOString(),
|
|
updatedAt: new Date(Date.now() - 1 * 24 * 60 * 60 * 1000).toISOString()
|
|
},
|
|
{
|
|
id: '4',
|
|
title: '学习新技术',
|
|
description: '学习Vue 3和Pinia状态管理',
|
|
priority: 'medium',
|
|
dueDate: new Date(Date.now() + 7 * 24 * 60 * 60 * 1000).toISOString(),
|
|
tags: ['学习', '技术'],
|
|
completed: false,
|
|
createdAt: new Date(Date.now() - 1 * 24 * 60 * 60 * 1000).toISOString(),
|
|
updatedAt: new Date(Date.now() - 1 * 24 * 60 * 60 * 1000).toISOString()
|
|
}
|
|
]
|
|
tasks.value = sampleTasks
|
|
saveToStorage()
|
|
}
|
|
}
|
|
|
|
return {
|
|
// 状态
|
|
tasks,
|
|
currentFilter,
|
|
currentSort,
|
|
searchKeyword,
|
|
|
|
// 计算属性
|
|
filteredTasks,
|
|
taskStats,
|
|
|
|
// 方法
|
|
addTask,
|
|
updateTask,
|
|
deleteTask,
|
|
toggleTask,
|
|
setFilter,
|
|
setSort,
|
|
setSearchKeyword,
|
|
clearCompleted,
|
|
getTaskById,
|
|
getTasksByTag,
|
|
getOverdueTasks,
|
|
getTodayTasks,
|
|
loadFromStorage,
|
|
initSampleData
|
|
}
|
|
})
|