import { reactive, computed } from 'vue' import { knowledgeApi } from '../api' import type { KnowledgeRecord, KnowledgeDetailPayload, KnowledgeEventRecord, CreateKnowledgeInput, UpdateKnowledgeInput, KnowledgeConfig, } from '../api/types' // ── 全局响应式状态(单例) ── const state = reactive({ items: [] as KnowledgeRecord[], candidates: [] as KnowledgeRecord[], config: null as KnowledgeConfig | null, loading: false, error: null as string | null, }) // 7 种知识类型(snake_case,与后端 KnowledgeKind 对齐) // 仅存 key + icon;展示文案(label)走 i18n: $t('knowledge.kind.') export const KNOWLEDGE_KINDS = [ { key: 'review_rule', icon: '🔍' }, { key: 'prompt_template', icon: '💬' }, { key: 'pitfall', icon: '⚠️' }, { key: 'architecture_pattern', icon: '🏛️' }, { key: 'diagnosis', icon: '🩺' }, { key: 'deployment_note', icon: '🚀' }, { key: 'workflow_optimization', icon: '⚡' }, ] as const /** 解析 tags JSON 字符串为 string[] */ export function parseTags(tags: string | null): string[] { if (!tags) return [] try { const arr = JSON.parse(tags) return Array.isArray(arr) ? arr : [] } catch { return [] } } export function useKnowledgeStore() { // ── 加载列表(默认排除 archived) ── async function loadList(status?: string) { state.loading = true state.error = null try { state.items = await knowledgeApi.list(status ?? null) } catch (e: any) { state.error = e?.toString() ?? '加载知识库失败' } finally { state.loading = false } } // ── 加载审核收件箱(候选列表) ── async function loadCandidates() { try { state.candidates = await knowledgeApi.listCandidates() } catch (e: any) { state.error = e?.toString() ?? '加载收件箱失败' } } async function search(query: string, kind?: string) { state.loading = true state.error = null try { state.items = await knowledgeApi.search({ query, kind }) } catch (e: any) { state.error = e?.toString() ?? '检索失败' } finally { state.loading = false } } async function create(input: CreateKnowledgeInput) { const record = await knowledgeApi.create(input) // 手动录入默认 candidate,刷新收件箱 await loadCandidates() return record } async function updateStatus(id: string, status: string) { await knowledgeApi.updateStatus(id, status) // 从 items 和 candidates 中同步移除 state.items = state.items.filter(k => k.id !== id) state.candidates = state.candidates.filter(k => k.id !== id) } async function archive(id: string) { await knowledgeApi.archive(id) state.items = state.items.filter(k => k.id !== id) state.candidates = state.candidates.filter(k => k.id !== id) } // ── 配置 ── async function loadConfig() { try { state.config = await knowledgeApi.getConfig() } catch (e: any) { state.error = e?.toString() ?? '加载配置失败' } } async function saveConfig(config: KnowledgeConfig) { await knowledgeApi.saveConfig(config) state.config = config } async function extractNow() { await knowledgeApi.extractNow() await loadCandidates() } // ── 生命线:详情 / 编辑 / 事件查询(按需调用,不入全局 state) ── async function getDetail(id: string): Promise { return knowledgeApi.getDetail(id) } async function update(id: string, input: UpdateKnowledgeInput): Promise { const updated = await knowledgeApi.update(id, input) // 同步刷新内存中的列表/收件箱条目 const patch = (arr: KnowledgeRecord[]) => { const idx = arr.findIndex(k => k.id === id) if (idx >= 0) arr[idx] = { ...arr[idx], ...updated } } patch(state.items) patch(state.candidates) return updated } async function getEvents(knowledgeId: string, eventType?: string, limit?: number): Promise { return knowledgeApi.events(knowledgeId, eventType, limit) } // 候选数量(供侧栏 badge 用) const candidateCount = computed(() => state.candidates.length) return reactive({ // 状态用 getter 实时读 state(防快照不跟随,同 project store 模式) get items() { return state.items }, get candidates() { return state.candidates }, get config() { return state.config }, get loading() { return state.loading }, get error() { return state.error }, candidateCount, // actions loadList, loadCandidates, search, create, updateStatus, archive, loadConfig, saveConfig, extractNow, getDetail, update, getEvents, }) }