优化: 图像模型兜底防御+任务UI(状态多选+跳详情)+token popover遮挡

This commit is contained in:
lxy
2026-08-10 13:46:26 +08:00
parent 256af4e736
commit 9407f821b9
7 changed files with 182 additions and 14 deletions
+77 -1
View File
@@ -295,8 +295,24 @@
<h2>{{ $t('projectDetail.taskListTitle') }}</h2>
<span class="task-count">{{ $t('projectDetail.taskCount', { n: projectTasks.length }) }}</span>
</div>
<div class="task-filter-chips">
<button
v-for="s in taskStatusFilters"
:key="s.key"
class="filter-chip"
:class="{ 'is-active': activeTaskStatuses.length === 0 || activeTaskStatuses.includes(s.key) }"
@click="toggleTaskStatus(s.key)"
>
{{ s.icon }} {{ s.label }}
</button>
</div>
<div class="task-list">
<div class="task-card" v-for="task in projectTasks" :key="task.id">
<div
class="task-card"
v-for="task in filteredProjectTasks"
:key="task.id"
@click="router.push('/tasks/' + task.id)"
>
<div class="task-top">
<span class="task-title">{{ task.title }}</span>
<span class="task-status" :class="taskStatusClass(task.status)">{{ $t(taskStatusLabel(task.status)) }}</span>
@@ -572,6 +588,30 @@ async function loadProjectTasks() {
}
// taskStatusLabel / taskStatusClass 由 ../constants/project 提供
// 任务状态多选过滤
const taskStatusFilters = computed(() => [
{ key: 'todo', icon: '📝', label: t('tasks.statusFilter.todo') },
{ key: 'in_progress', icon: '🔨', label: t('tasks.statusFilter.in_progress') },
{ key: 'in_review', icon: '👀', label: t('tasks.statusFilter.in_review') },
{ key: 'testing', icon: '🧪', label: t('tasks.statusFilter.testing') },
{ key: 'done', icon: '✅', label: t('tasks.statusFilter.done') },
{ key: 'blocked', icon: '🚫', label: t('tasks.statusFilter.blocked') },
{ key: 'cancelled', icon: '🗑️', label: t('tasks.statusFilter.cancelled') },
])
const activeTaskStatuses = ref<string[]>([])
function toggleTaskStatus(key: string) {
const idx = activeTaskStatuses.value.indexOf(key)
if (idx >= 0) {
activeTaskStatuses.value.splice(idx, 1)
} else {
activeTaskStatuses.value.push(key)
}
}
const filteredProjectTasks = computed(() => {
if (activeTaskStatuses.value.length === 0) return projectTasks.value
return projectTasks.value.filter(t => activeTaskStatuses.value.includes(t.status))
})
// ── 工程列表(概览内 CRUD)──
// 多工程(monorepo/多模块)在概览内增删改 + 扫描;复用 moduleApi + ConfirmDialog(删除确认)
// + arco Message(反馈)。切到文件 Tab 时 FileExplorer 因 v-if 重挂载自动重拉,无需手动同步。
@@ -1330,6 +1370,36 @@ onUnmounted(() => {
/* .panel / .panel-header 基础样式已收敛至全局 components.css(DRY 收口 B-260619),
此处仅保留本组件特有 .task-count。 */
.task-count { font-size: 12px; color: var(--df-text-dim); }
.task-filter-chips {
display: flex;
flex-wrap: wrap;
gap: 4px;
margin-bottom: 8px;
}
.task-filter-chips .filter-chip {
display: inline-flex;
align-items: center;
gap: 3px;
padding: 2px 8px;
border: 0.5px solid var(--df-border);
border-radius: 10px;
background: transparent;
color: var(--df-text-dim);
font-size: 10px;
cursor: pointer;
transition: all 0.15s;
white-space: nowrap;
}
.task-filter-chips .filter-chip:hover {
background: var(--df-bg-card);
color: var(--df-text);
border-color: var(--df-accent);
}
.task-filter-chips .filter-chip.is-active {
background: var(--df-accent-soft);
color: var(--df-accent);
border-color: var(--df-accent);
}
/* A2[PD-P1-3]:工作流日志「全局事件」标注(次要小字标签) */
.global-event-tag {
@@ -1346,7 +1416,13 @@ onUnmounted(() => {
.task-card {
padding: 14px 0;
border-bottom: 0.5px solid var(--df-border);
cursor: pointer;
transition: background 0.15s;
margin: 0 -12px;
padding: 10px 12px;
border-radius: var(--df-radius);
}
.task-card:hover { background: var(--df-bg-card-hover); }
.task-card:last-child { border-bottom: none; }
.task-top { display: flex; justify-content: space-between; align-items: center; margin-bottom: 6px; }
.task-title { font-size: 14px; font-weight: 500; color: var(--df-text); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }