83 lines
2.8 KiB
TypeScript
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,
|
|
}
|
|
}
|