新增: 工具工作流补全(diff_files工具 + 技能清单注入 + 工作流进度共享 + human端到端测试 + 知识库MCP工具)

This commit is contained in:
lxy
2026-08-08 21:24:53 +08:00
parent 6ba6daf188
commit 9eb2995a74
14 changed files with 807 additions and 93 deletions
+56 -7
View File
@@ -310,6 +310,22 @@
</section>
</div>
<!-- B-41 工作流实时进度:最近一次执行的 DAG + 节点状态高亮(共享 workflow store 派生) -->
<section v-if="hasWfProgress" class="panel wf-progress-panel">
<div class="panel-header">
<h2>{{ $t('projectDetail.workflowProgressTitle') }}</h2>
</div>
<div class="wf-progress">
<span v-if="wfProgress.runningNode">{{ $t('taskDetail.workflowStepRunning', { node: wfProgress.runningNode }) }}</span>
<span v-else-if="wfProgress.doneCount > 0" class="wf-progress-count">
{{ $t('taskDetail.workflowStepsProgress', { done: wfProgress.doneCount, total: wfProgress.totalNodes }) }}
</span>
<span v-if="wfProgress.result === 'completed'" class="wf-progress-hint">{{ $t('taskDetail.workflowCompletedHint') }}</span>
<span v-if="wfProgress.result === 'failed'" class="wf-progress-hint wf-progress-hint-fail">{{ $t('taskDetail.workflowFailedHint') }}</span>
</div>
<WorkflowDagDisplay v-if="wfDagJson" :dag-json="wfDagJson" :node-statuses="wfProgress.nodeStatuses" />
</section>
<!-- 工作流日志:无记录时折叠为摘要(标题 + 计数),有记录才展开列表 -->
<section v-if="formattedEvents.length > 0 || !workflowLogCollapsed" class="panel workflow-log-panel">
<div class="panel-header">
@@ -396,7 +412,7 @@ import { useI18n } from 'vue-i18n'
import { Message } from '@arco-design/web-vue'
import { open } from '@tauri-apps/plugin-dialog'
import { useProjectStore } from '@/stores/project'
import { projectApi, taskApi } from '@/api'
import { projectApi, taskApi, workflowApi } from '@/api'
import { moduleApi, type ProjectModuleRecord } from '@/api/module'
import { formatDate } from '@/utils/time'
import { parseStack } from '@/utils/project'
@@ -406,6 +422,7 @@ import ConfirmDialog from '@/components/ConfirmDialog.vue'
import ApprovalDialog from '@/components/project/ApprovalDialog.vue'
import FileExplorer from '@/components/project/FileExplorer.vue'
import DependencyGraph from '@/components/project/DependencyGraph.vue'
import WorkflowDagDisplay from '@/components/workflow/WorkflowDagDisplay.vue'
import { useConfirm } from '@/composables/useConfirm'
import { useRendered } from '@/composables/useMarkdown'
import type { ProjectId, TaskRecord } from '@/api/types'
@@ -416,7 +433,6 @@ const store = useProjectStore()
const { t, locale } = useI18n()
const logListRef = ref<HTMLElement | null>(null)
const showApprovalDialog = ref(false)
let unlisten: (() => void) | null = null
// Tab 导航:概览(项目信息/任务/工作流日志) vs 文件浏览器(Batch 10)。
// P1-g+ 问题10④:activeTab 持久化 localStorage(按项目隔离,切换项目不串扰)。
@@ -672,6 +688,26 @@ const formattedEvents = computed<LogEntry[]>(() => {
})
})
// ── B-41 工作流实时进度 ──
// ProjectDetail 无工作流推进入口,但审批弹窗/日志面板已接 liveEvents;此处展示最近一次
// 工作流的 DAG + 节点状态高亮(共享 workflow store 派生,与 TaskDetail 同源),
// 手动跑工作流时也能看到节点实时进度。无事件(本次会话没跑过)时整个面板不渲染。
const wfDagJson = ref('')
const latestWfExecId = computed(() => {
const evs = store.liveEvents
return evs.length > 0 ? evs[evs.length - 1].execution_id : null
})
const wfProgress = computed(() => store.workflowProgress(latestWfExecId.value))
const hasWfProgress = computed(() => Object.keys(wfProgress.value.nodeStatuses).length > 0)
watch(latestWfExecId, async (id) => {
wfDagJson.value = ''
if (!id) return
try {
const record = await workflowApi.getExecution(id)
if (record?.dag_json) wfDagJson.value = record.dag_json
} catch { /* 静默 */ }
}, { immediate: true })
// ── 新建任务 ──
const showNewTaskModal = ref(false)
const newTaskTitle = ref('')
@@ -822,7 +858,7 @@ onMounted(async () => {
// 来源灵感回溯:项目有 idea_id 但 store.ideas 为空(本页未 load 过)时补拉,
// 否则 sourceIdea computed 永远找不到对应灵感记录
await store.loadIdeas()
unlisten = await store.startEventListener()
await store.startEventListener()
await checkPath()
})
@@ -838,10 +874,9 @@ watch(projectId, async (newId) => {
watch(() => currentProject.value?.path, () => { checkPath() })
onUnmounted(() => {
if (unlisten) {
unlisten()
unlisten = null
}
// 用 store.stopEventListener 统一停全局监听并复位句柄(直接调 unlisten() 停监听但
// 不复位 _eventUnlisten,后续 startEventListener 幂等会误返回已死句柄,共享化后必查)
store.stopEventListener()
})
</script>
@@ -1205,6 +1240,20 @@ onUnmounted(() => {
}
.workflow-log-panel { flex: 0 0 auto; }
/* B-41 工作流实时进度面板(与 TaskDetail wf-progress 同款视觉) */
.wf-progress-panel { flex: 0 0 auto; }
.wf-progress {
display: flex;
flex-direction: column;
gap: 2px;
margin-top: 6px;
font-size: 12px;
color: var(--df-text-secondary);
}
.wf-progress-count { color: var(--df-text-dim); }
.wf-progress-hint { color: var(--df-success); }
.wf-progress-hint-fail { color: var(--df-danger); }
/* ===== 面板 ===== */
/* .panel / .panel-header 基础样式已收敛至全局 components.css(DRY 收口 B-260619),
此处仅保留本组件特有 .task-count。 */