优化: ProjectDetail多工程列表 + ProjectCard list padding + provider usage诊断

ProjectDetail 概览加工程列表(moduleApi.listProjectModules 显所有 module 名/路径,只读,多工程可见,不只项目级 bind_directory)

ProjectCard list padding 1×(原 0.7× 紧凑文字贴边,panel 14/16px)

openai_helpers apply_openai_sse usage 诊断 tracing(确认 deepseek 报 cache/usage 否,定位 completion 0)

i18n projectDetail.modulesLabel zh/en
This commit is contained in:
lxy
2026-08-03 02:28:21 +08:00
parent a031521776
commit 8e4c7c68cf
5 changed files with 71 additions and 2 deletions
+2 -2
View File
@@ -176,8 +176,8 @@ watch(() => props.view, () => nextTick(measureDesc))
}
.card-desc-toggle:hover { text-decoration: underline; }
/* list 视图:更紧凑的内边距,单屏容纳更多卡片 */
.project-card--list { padding: calc(var(--df-pad-panel) * 0.7); }
/* list 视图:padding 同 card(1× panel,文字不贴边);list 紧凑靠 line-clamp 2 + grid 单列,不靠缩 padding */
.project-card--list { padding: var(--df-pad-panel); }
.card-footer {
display: flex;
+2
View File
@@ -68,6 +68,8 @@ export default {
approvalInvert: 'Invert',
// Tech stack
techStackLabel: 'Tech Stack',
// Module list (multi-module read-only display)
modulesLabel: 'Modules ({n})',
// Tab navigation
tabOverview: '📋 Overview',
},
+2
View File
@@ -68,6 +68,8 @@ export default {
approvalInvert: '反选',
// 技术栈
techStackLabel: '技术栈',
// 工程列表(多工程只读展示)
modulesLabel: '工程({n})',
// Tab 导航
tabOverview: '📋 概览',
},
+57
View File
@@ -117,6 +117,17 @@
</span>
</div>
<!-- 工程列表(多工程只读展示;CRUD 在文件 Tab) -->
<div class="info-item" v-if="modules.length">
<span class="label">{{ $t('projectDetail.modulesLabel', { n: modules.length }) }}</span>
<div class="module-list-overview">
<div v-for="m in modules" :key="m.id" class="module-row-overview">
<span class="module-name-overview">{{ m.name }}</span>
<span class="module-path-overview" :title="m.path">{{ m.path }}</span>
</div>
</div>
</div>
<!-- 技术栈 -->
<div class="info-item" v-if="parseStack(currentProject.stack).length">
<span class="label">{{ $t('projectDetail.techStackLabel') }}</span>
@@ -291,6 +302,7 @@ 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 { moduleApi, type ProjectModuleRecord } from '@/api/module'
import { formatDate } from '@/utils/time'
import { parseStack } from '@/utils/project'
import { parseScores as parseScoresJson, assessmentClass, assessmentLabel as assessmentLabelI18n, scoreTier } from '@/utils/ideaEval'
@@ -419,6 +431,18 @@ async function loadProjectTasks() {
}
// taskStatusLabel / taskStatusClass 由 ../constants/project 提供
// ── 工程列表(只读展示)──
// 多工程(monorepo/多模块)在 FileExplorer 文件 Tab 内 CRUD,概览仅按 project_id 拉取展示。
// 0 工程 v-if 隐藏,单工程也显(与多工程同列表)。
const modules = ref<ProjectModuleRecord[]>([])
async function loadModules() {
try {
modules.value = await moduleApi.listProjectModules(projectId.value)
} catch {
modules.value = []
}
}
// ── 工作流 ──
// demoDag + runDemoWorkflow 已下线(R-PD-2):"script" 节点不再注册到 NodeRegistry
// 前端构造含 script 节点的 DagDef 会在后端 build_dag 失败报错。
@@ -592,6 +616,8 @@ onMounted(async () => {
await store.loadProjects()
// 本项目任务独立拉取(不调 store.loadTasks,避免被 Tasks 视图分页/筛选污染)
await loadProjectTasks()
// 工程列表独立拉取(FileExplorer 文件 Tab 内 CRUD,概览只读展示)
await loadModules()
// 来源灵感回溯:项目有 idea_id 但 store.ideas 为空(本页未 load 过)时补拉,
// 否则 sourceIdea computed 永远找不到对应灵感记录
await store.loadIdeas()
@@ -604,6 +630,7 @@ watch(projectId, async (newId) => {
if (!newId) return
activeTab.value = readStoredTab(newId)
await loadProjectTasks()
await loadModules()
})
// 目录变更(重定位后)重新检测存在性
@@ -650,6 +677,36 @@ onUnmounted(() => {
font-style: italic;
}
/* ===== 工程列表(概览只读展示;对齐 .info-item label固定宽 + value) ===== */
.module-list-overview {
display: flex;
flex-direction: column;
gap: 4px;
flex: 1;
min-width: 0;
}
.module-row-overview {
display: flex;
align-items: baseline;
gap: 8px;
min-width: 0;
}
.module-name-overview {
font-size: 13px;
color: var(--df-text);
font-weight: 500;
flex-shrink: 0;
}
.module-path-overview {
font-size: 12px;
font-family: 'SF Mono', 'Fira Code', monospace;
color: var(--df-text-dim);
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
min-width: 0;
}
.status-badge {
display: inline-block;
padding: 2px 8px;