Files
DevFlow/src/stores/project/ideas.ts
T

83 lines
2.8 KiB
TypeScript

import { ideaApi } from '@/api'
import type { IdeaQuery } from '@/api/types'
import { t } from '@/i18n/i18n-helpers'
import { runWithCatch } from '@/composables/useStoreAction'
import { state } from './state'
/** 灵感 CRUD 子 store(共享全局 state) */
export function createIdeasStore() {
/**
* 加载灵感列表。
*
* status/keyword/order_by 下沉后端 WHERE,取代前端 computed filter。
* - 传 `query` → 多条件查询(状态/关键词/排序/分页)。
* - 不传 → 全量(created_at DESC,等价旧行为)。
*
* 成功时清 state.error(load 后不残留旧错误),失败由 runWithCatch 置 error。
*/
async function loadIdeas(query?: IdeaQuery) {
state.error = null
await runWithCatch(state, t('ideas.err.loadFailed'), async () => {
state.ideas = await ideaApi.list(query)
})
}
async function createIdea(input: { title: string; description?: string; priority?: number; tags?: string; source?: string }) {
const record = await runWithCatch(state, t('ideas.err.createFailed'), async () => {
const r = await ideaApi.create(input)
state.ideas.push(r)
return r
})
return record ?? null
}
async function updateIdea(id: string, field: string, value: string) {
await ideaApi.update(id, field, value)
const idx = state.ideas.findIndex(i => i.id === id)
if (idx >= 0) {
(state.ideas[idx] as any)[field] = value
}
}
async function deleteIdea(id: string): Promise<boolean> {
// 返成功布尔(失败时 runWithCatch 已置 state.error),调用方据此保留选中态
const ok = await runWithCatch(state, t('ideas.err.deleteFailed'), async () => {
await ideaApi.delete(id)
state.ideas = state.ideas.filter(i => i.id !== id)
return true
})
return ok === true
}
async function evaluateIdea(id: string) {
const record = await ideaApi.evaluate(id)
const idx = state.ideas.findIndex(i => i.id === id)
if (idx >= 0) state.ideas[idx] = record
return record
}
async function promoteIdea(id: string) {
// 不再内部全量 loadIdeas(会把 store.ideas 冲成全集、冲掉当前筛选视图)。
// 由视图(Ideas.vue promoteToProject)操作后按当前 buildIdeaQuery() 主动重载。
return await ideaApi.promote(id)
}
async function relateIdeas(subjectId: string, targetIds: string[]) {
await runWithCatch(state, t('ideas.err.relateFailed'), async () => {
await ideaApi.relateIdeas(subjectId, targetIds)
// 后端原子更新受影响灵感,原全量 loadIdeas 会冲掉当前筛选视图;
// 改由视图(Ideas.vue onUpdateRelated)按当前 query 重载。
})
}
return {
loadIdeas,
createIdea,
updateIdea,
deleteIdea,
evaluateIdea,
promoteIdea,
relateIdeas,
}
}