修复: 安全加固+DRY 收敛+文档同步+测试补齐
安全: - ScriptNode 默认黑名单兜底(rm/del/format/shutdown/mkfs/dd) - bind_directory 分段 .. 检测替代 contains 子串(对齐 tool_registry) - ai_providers 白名单移除 api_key(防 update_field 旁路写明文) DRY: - useAiEvents 抽 cleanupTerminatedConversation 统一三分支收尾 - 新增 useStoreAction 工具,4 个 store 替换 38 处 try/catch 样板 文档: - df-core → df-types 批量替换(ARCHITECTURE/PROGRESS/SQLite-CRUD) - INDEX 补齐 9 漏列文档(单对话并行多轮/跑题试验/工程系统设计等) - Agent架构说明 死链修复(../构想审查/) - AI对话引擎工具清单改为数量+按风险分组(不再用固定数字) - ARCH 状态标签 设计阶段 → Phase 2 验证 测试: - df-relay 新增 registry_test: ConnRegistry 路由 + RelayState + 16 项单测
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
import { projectApi } from '@/api'
|
||||
import type { ImportProjectInput, ProjectQuery } from '@/api/project'
|
||||
import { t } from '@/i18n/i18n-helpers'
|
||||
import { runWithCatch } from '@/composables/useStoreAction'
|
||||
import { state, clearError } from './state'
|
||||
|
||||
/** 项目 CRUD 子 store(共享全局 state) */
|
||||
@@ -12,36 +13,29 @@ export function createProjectsStore() {
|
||||
async function loadProjects(query?: ProjectQuery) {
|
||||
state.loading = true
|
||||
state.error = null
|
||||
try {
|
||||
await runWithCatch(state, t('projects.err.loadFailed'), async () => {
|
||||
state.projects = await projectApi.list(query)
|
||||
} catch (e: any) {
|
||||
state.error = e?.toString() ?? t('projects.err.loadFailed')
|
||||
} finally {
|
||||
state.loading = false
|
||||
}
|
||||
})
|
||||
state.loading = false
|
||||
}
|
||||
|
||||
async function createProject(name: string, description = '', ideaId?: string, path?: string, stack?: string) {
|
||||
try {
|
||||
const record = await projectApi.create({ name, description, idea_id: ideaId, path, stack })
|
||||
state.projects.push(record)
|
||||
return record
|
||||
} catch (e: any) {
|
||||
state.error = e?.toString() ?? t('projects.err.createFailed')
|
||||
return null
|
||||
}
|
||||
const record = await runWithCatch(state, t('projects.err.createFailed'), async () => {
|
||||
const r = await projectApi.create({ name, description, idea_id: ideaId, path, stack })
|
||||
state.projects.push(r)
|
||||
return r
|
||||
})
|
||||
return record ?? null
|
||||
}
|
||||
|
||||
/** 导入历史项目(选已存在目录,后端创建+绑定+探测栈+读 README 首段一步完成) */
|
||||
async function importProject(input: ImportProjectInput) {
|
||||
try {
|
||||
const record = await projectApi.importProject(input)
|
||||
const record = await runWithCatch(state, t('projects.err.importFailed'), async () => {
|
||||
const r = await projectApi.importProject(input)
|
||||
await loadProjects() // 刷新列表(后端已 insert,统一走 load 避免本地数组与后端不一致)
|
||||
return record
|
||||
} catch (e: any) {
|
||||
state.error = e?.toString() ?? t('projects.err.importFailed')
|
||||
return null
|
||||
}
|
||||
return r
|
||||
})
|
||||
return record ?? null
|
||||
}
|
||||
|
||||
async function updateProject(id: string, field: string, value: string) {
|
||||
@@ -61,20 +55,16 @@ export function createProjectsStore() {
|
||||
}
|
||||
|
||||
async function deleteProject(id: string) {
|
||||
try {
|
||||
await runWithCatch(state, t('projects.err.deleteFailed'), async () => {
|
||||
await projectApi.delete(id) // 软删 → 回收站(可恢复)
|
||||
state.projects = state.projects.filter(p => p.id !== id)
|
||||
} catch (e: any) {
|
||||
state.error = e?.toString() ?? t('projects.err.deleteFailed')
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
async function loadDeletedProjects() {
|
||||
try {
|
||||
await runWithCatch(state, t('projects.err.loadTrashFailed'), async () => {
|
||||
state.deletedProjects = await projectApi.listDeleted()
|
||||
} catch (e: any) {
|
||||
state.error = e?.toString() ?? t('projects.err.loadTrashFailed')
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
async function restoreProject(id: string) {
|
||||
|
||||
Reference in New Issue
Block a user