79 lines
2.7 KiB
TypeScript
79 lines
2.7 KiB
TypeScript
import { taskApi } from '@/api'
|
|
import type { TaskQuery, ProjectId } from '@/api/types'
|
|
import { t } from '@/i18n/i18n-helpers'
|
|
import { runWithCatch, runWithCatchGuarded } from '@/composables/useStoreAction'
|
|
import { state } from './state'
|
|
|
|
/** 任务 CRUD 子 store(共享全局 state) */
|
|
export function createTasksStore() {
|
|
// 并发 loadTasks 竞态守卫(快速切筛选/搜索防旧响应晚到覆盖新结果,
|
|
// 对齐 knowledge store 的 _itemsSeq 模式)。旧请求的失败也不污染当前视图。
|
|
let _tasksSeq = 0
|
|
|
|
/**
|
|
* 加载任务列表。
|
|
*
|
|
* **双签名向后兼容**
|
|
* - `loadTasks(projectId?)`:旧签名,仅项目过滤(等价 `loadTasks({ project_id: projectId })`)。
|
|
* - `loadTasks(query?)`:新签名,多条件(status/keyword/...)走后端 WHERE。
|
|
*
|
|
* 不传 → 全量未删任务(created_at DESC,等价改造前 list_active)。
|
|
* status/keyword 下沉后端 WHERE(P1/P2),取代 Tasks.vue 旧的前端内存 filter。
|
|
*/
|
|
async function loadTasks(queryOrProjectId?: TaskQuery | string) {
|
|
const seq = ++_tasksSeq
|
|
await runWithCatchGuarded(state, t('tasks.err.loadFailed'), () => seq === _tasksSeq, async () => {
|
|
const result = await taskApi.list(queryOrProjectId)
|
|
if (seq === _tasksSeq) state.tasks = result
|
|
})
|
|
}
|
|
|
|
async function createTask(input: {
|
|
project_id: ProjectId
|
|
title: string
|
|
description?: string
|
|
priority?: number
|
|
branch_name?: string
|
|
assignee?: string
|
|
idea_id?: string
|
|
/** 父任务 ID(1 级嵌套,可空);传空串后端视为 None */
|
|
parent_id?: string | null
|
|
}) {
|
|
const record = await runWithCatch(state, t('tasks.err.createFailed'), async () => {
|
|
const r = await taskApi.create(input)
|
|
state.tasks.push(r)
|
|
return r
|
|
})
|
|
return record ?? null
|
|
}
|
|
|
|
async function updateTask(id: string, field: string, value: string) {
|
|
await runWithCatch(state, t('tasks.err.updateFailed'), async () => {
|
|
await taskApi.update(id, field, value)
|
|
const idx = state.tasks.findIndex(t => t.id === id)
|
|
if (idx >= 0) {
|
|
(state.tasks[idx] as any)[field] = value
|
|
}
|
|
})
|
|
}
|
|
|
|
async function deleteTask(id: string): Promise<boolean> {
|
|
// 返成功布尔(失败时 runWithCatch 已置 state.error),快捷删除据此 toast 反馈
|
|
const ok = await runWithCatch(state, t('tasks.err.deleteFailed'), async () => {
|
|
// 后端已级联软删子任务(delete_task 返回 { ok, cascaded });
|
|
// 本地同步移除父任务 + 其直接子任务(1 级嵌套,防悬挂 parent_id)
|
|
await taskApi.delete(id)
|
|
state.tasks = state.tasks.filter(t => t.id !== id && t.parent_id !== id)
|
|
return true
|
|
})
|
|
return ok === true
|
|
}
|
|
|
|
return {
|
|
loadTasks,
|
|
createTask,
|
|
updateTask,
|
|
deleteTask,
|
|
}
|
|
}
|