181 lines
5.1 KiB
TypeScript
181 lines
5.1 KiB
TypeScript
import { defineStore } from 'pinia'
|
|
import { ref, computed } from 'vue'
|
|
import { taskApi, type TaskResponse } from '@/api/tasks'
|
|
import type { TaskFormData, TaskFilters } from '@/api/types'
|
|
import { matchWithPinyin } from '@/utils/pinyin'
|
|
import { formatDate } from '@/utils/date'
|
|
|
|
export const useTaskStore = defineStore('task', () => {
|
|
const allTasks = ref<TaskResponse[]>([])
|
|
const loading = ref(false)
|
|
const filters = ref<TaskFilters>({
|
|
status: 'all',
|
|
sort_by: 'priority',
|
|
sort_order: 'desc'
|
|
})
|
|
|
|
// 所有任务
|
|
const tasks = computed(() => {
|
|
let result = [...allTasks.value]
|
|
|
|
// 搜索过滤(支持拼音)
|
|
if (filters.value.search?.trim()) {
|
|
const keyword = filters.value.search.trim()
|
|
result = result.filter(t =>
|
|
matchWithPinyin(t.title, keyword) ||
|
|
(t.description && matchWithPinyin(t.description, keyword)) ||
|
|
t.tags?.some(tag => matchWithPinyin(tag.name, keyword))
|
|
)
|
|
}
|
|
|
|
// 状态筛选
|
|
if (filters.value.status === 'active') {
|
|
result = result.filter(t => !t.is_completed)
|
|
} else if (filters.value.status === 'completed') {
|
|
result = result.filter(t => t.is_completed)
|
|
}
|
|
|
|
// 分类筛选
|
|
if (filters.value.category_id) {
|
|
result = result.filter(t => t.category_id === filters.value.category_id)
|
|
}
|
|
|
|
// 排序
|
|
if (filters.value.sort_by) {
|
|
result.sort((a, b) => {
|
|
let comparison = 0
|
|
|
|
if (filters.value.sort_by === 'priority') {
|
|
const priorityOrder: Record<string, number> = { q1: 4, q2: 3, q3: 2, q4: 1 }
|
|
const aOrder = priorityOrder[a.priority] || 0
|
|
const bOrder = priorityOrder[b.priority] || 0
|
|
comparison = aOrder - bOrder
|
|
} else if (filters.value.sort_by === 'due_date') {
|
|
if (!a.due_date && !b.due_date) comparison = 0
|
|
else if (!a.due_date) comparison = 1
|
|
else if (!b.due_date) comparison = -1
|
|
else comparison = new Date(a.due_date).getTime() - new Date(b.due_date).getTime()
|
|
} else {
|
|
comparison = new Date(b.created_at).getTime() - new Date(a.created_at).getTime()
|
|
}
|
|
|
|
return filters.value.sort_order === 'asc' ? -comparison : comparison
|
|
})
|
|
}
|
|
|
|
return result
|
|
})
|
|
|
|
// 计算进行中和已完成的任务数量(基于所有任务)
|
|
const activeTasks = computed(() => allTasks.value.filter(t => !t.is_completed))
|
|
const completedTasks = computed(() => allTasks.value.filter(t => t.is_completed))
|
|
const totalTasks = computed(() => allTasks.value)
|
|
|
|
// 按日期分组的任务(用于月视图)
|
|
const tasksByDate = computed(() => {
|
|
const grouped = new Map<string, TaskResponse[]>()
|
|
const today = new Date()
|
|
const todayStr = formatDate(today)
|
|
|
|
allTasks.value.forEach(task => {
|
|
let dateKey: string
|
|
if (task.due_date) {
|
|
dateKey = formatDate(new Date(task.due_date))
|
|
} else {
|
|
// 无截止日期的任务显示在当天
|
|
dateKey = todayStr
|
|
}
|
|
|
|
if (!grouped.has(dateKey)) {
|
|
grouped.set(dateKey, [])
|
|
}
|
|
grouped.get(dateKey)!.push(task)
|
|
})
|
|
|
|
return grouped
|
|
})
|
|
|
|
async function fetchTasks() {
|
|
loading.value = true
|
|
try {
|
|
// 一次获取所有任务,在前端进行筛选和排序
|
|
allTasks.value = await taskApi.getTasks({ status: 'all' })
|
|
} catch (error) {
|
|
console.error('获取任务列表失败:', error)
|
|
} finally {
|
|
loading.value = false
|
|
}
|
|
}
|
|
|
|
async function createTask(data: TaskFormData) {
|
|
try {
|
|
const newTask = await taskApi.createTask(data)
|
|
allTasks.value.unshift(newTask)
|
|
return newTask
|
|
} catch (error) {
|
|
console.error('创建任务失败:', error)
|
|
return null
|
|
}
|
|
}
|
|
|
|
async function updateTask(id: number, data: TaskFormData) {
|
|
try {
|
|
const updatedTask = await taskApi.updateTask(id, data)
|
|
const index = allTasks.value.findIndex((t: TaskResponse) => t.id === id)
|
|
if (index !== -1) {
|
|
allTasks.value[index] = updatedTask
|
|
}
|
|
return updatedTask
|
|
} catch (error) {
|
|
console.error('更新任务失败:', error)
|
|
return null
|
|
}
|
|
}
|
|
|
|
async function deleteTask(id: number) {
|
|
try {
|
|
await taskApi.deleteTask(id)
|
|
allTasks.value = allTasks.value.filter((t: TaskResponse) => t.id !== id)
|
|
return true
|
|
} catch (error) {
|
|
console.error('删除任务失败:', error)
|
|
return false
|
|
}
|
|
}
|
|
|
|
async function toggleTask(id: number) {
|
|
try {
|
|
const updatedTask = await taskApi.toggleTask(id)
|
|
const index = allTasks.value.findIndex((t: TaskResponse) => t.id === id)
|
|
if (index !== -1) {
|
|
allTasks.value[index] = updatedTask
|
|
}
|
|
return updatedTask
|
|
} catch (error) {
|
|
console.error('切换任务状态失败:', error)
|
|
return null
|
|
}
|
|
}
|
|
|
|
function setFilters(newFilters: TaskFilters) {
|
|
filters.value = { ...filters.value, ...newFilters }
|
|
// 筛选现在在前端完成,不需要重新请求
|
|
}
|
|
|
|
return {
|
|
tasks,
|
|
loading,
|
|
filters,
|
|
activeTasks,
|
|
completedTasks,
|
|
totalTasks: allTasks,
|
|
tasksByDate,
|
|
fetchTasks,
|
|
createTask,
|
|
updateTask,
|
|
deleteTask,
|
|
toggleTask,
|
|
setFilters
|
|
}
|
|
})
|