You've already forked agentic-coding-workflow
Web优化 2
This commit is contained in:
@@ -1,10 +1,7 @@
|
||||
<template>
|
||||
<NCard title="产物与会话历史">
|
||||
<NSpin :show="loading">
|
||||
<NCollapse
|
||||
v-if="hasAnyContent"
|
||||
:default-expanded-names="defaultExpandedNames"
|
||||
>
|
||||
<NCollapse v-if="hasAnyContent" :default-expanded-names="defaultExpandedNames">
|
||||
<!-- 产物:按阶段分组 -->
|
||||
<NCollapseItem
|
||||
v-for="phase in ARTIFACT_PHASES"
|
||||
@@ -15,81 +12,46 @@
|
||||
<template #header>
|
||||
<div class="flex items-center gap-2">
|
||||
<span class="font-medium">{{ PHASE_TITLE[phase] }}产物</span>
|
||||
<NTag
|
||||
size="tiny"
|
||||
:type="phase === currentPhase ? 'primary' : 'default'"
|
||||
>
|
||||
<NTag size="tiny" :type="phase === currentPhase ? 'primary' : 'default'">
|
||||
{{ artifactsByPhase[phase].length }}
|
||||
</NTag>
|
||||
<span
|
||||
v-if="phase === currentPhase"
|
||||
class="text-xs text-blue-500"
|
||||
>当前</span>
|
||||
<span v-if="phase === currentPhase" class="text-xs text-blue-500">当前</span>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<NList
|
||||
v-if="artifactsByPhase[phase].length > 0"
|
||||
:show-divider="false"
|
||||
>
|
||||
<NListItem
|
||||
v-for="a in artifactsByPhase[phase]"
|
||||
:key="a.id"
|
||||
>
|
||||
<NThing
|
||||
class="cursor-pointer"
|
||||
@click="toggleArtifact(a)"
|
||||
>
|
||||
<NList v-if="artifactsByPhase[phase].length > 0" :show-divider="false">
|
||||
<NListItem v-for="a in artifactsByPhase[phase]" :key="a.id">
|
||||
<NThing class="cursor-pointer" @click="toggleArtifact(a)">
|
||||
<template #header>
|
||||
<span
|
||||
class="text-sm font-medium"
|
||||
:class="selectedArtifact?.id === a.id ? 'text-blue-600' : ''"
|
||||
>v{{ a.version }}</span>
|
||||
<NTag
|
||||
v-if="a.source_message_id"
|
||||
size="tiny"
|
||||
class="ml-1"
|
||||
>v{{ a.version }}</span
|
||||
>
|
||||
AI
|
||||
</NTag>
|
||||
<NTag v-if="a.source_message_id" size="tiny" class="ml-1"> AI </NTag>
|
||||
</template>
|
||||
<template #header-extra>
|
||||
<span class="text-xs text-gray-400">
|
||||
{{ formatDate(a.created_at) }}
|
||||
</span>
|
||||
</template>
|
||||
<span
|
||||
v-if="a.note"
|
||||
class="text-xs text-gray-500"
|
||||
>{{ a.note }}</span>
|
||||
<span v-if="a.note" class="text-xs text-gray-500">{{ a.note }}</span>
|
||||
</NThing>
|
||||
</NListItem>
|
||||
</NList>
|
||||
<NEmpty
|
||||
v-else
|
||||
description="暂无产物"
|
||||
size="small"
|
||||
/>
|
||||
<NEmpty v-else description="暂无产物" size="small" />
|
||||
|
||||
<!-- 选中产物内容预览 -->
|
||||
<div
|
||||
v-if="selectedArtifact && selectedArtifact.phase === phase"
|
||||
class="mt-3"
|
||||
>
|
||||
<div v-if="selectedArtifact && selectedArtifact.phase === phase" class="mt-3">
|
||||
<NDivider />
|
||||
<!-- eslint-disable-next-line vue/no-v-html -->
|
||||
<div
|
||||
class="prose prose-sm max-w-none"
|
||||
v-html="renderedArtifact"
|
||||
/>
|
||||
<!-- eslint-disable vue/no-v-html -->
|
||||
<div class="prose prose-sm max-w-none" v-html="renderedArtifact" />
|
||||
<!-- eslint-enable vue/no-v-html -->
|
||||
</div>
|
||||
</NCollapseItem>
|
||||
|
||||
<!-- AI 对话 -->
|
||||
<NCollapseItem
|
||||
name="conversations"
|
||||
:disabled="conversations.length === 0"
|
||||
>
|
||||
<NCollapseItem name="conversations" :disabled="conversations.length === 0">
|
||||
<template #header>
|
||||
<div class="flex items-center gap-2">
|
||||
<span class="font-medium">AI 对话</span>
|
||||
@@ -99,18 +61,9 @@
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<NList
|
||||
v-if="conversations.length > 0"
|
||||
:show-divider="false"
|
||||
>
|
||||
<NListItem
|
||||
v-for="c in conversations"
|
||||
:key="c.id"
|
||||
>
|
||||
<NThing
|
||||
class="cursor-pointer"
|
||||
@click="goConversation(c)"
|
||||
>
|
||||
<NList v-if="conversations.length > 0" :show-divider="false">
|
||||
<NListItem v-for="c in conversations" :key="c.id">
|
||||
<NThing class="cursor-pointer" @click="goConversation(c)">
|
||||
<template #header>
|
||||
<span
|
||||
class="text-sm font-medium"
|
||||
@@ -127,18 +80,11 @@
|
||||
</NThing>
|
||||
</NListItem>
|
||||
</NList>
|
||||
<NEmpty
|
||||
v-else
|
||||
description="暂无对话"
|
||||
size="small"
|
||||
/>
|
||||
<NEmpty v-else description="暂无对话" size="small" />
|
||||
</NCollapseItem>
|
||||
|
||||
<!-- ACP 会话 -->
|
||||
<NCollapseItem
|
||||
name="acp-sessions"
|
||||
:disabled="acpSessions.length === 0"
|
||||
>
|
||||
<NCollapseItem name="acp-sessions" :disabled="acpSessions.length === 0">
|
||||
<template #header>
|
||||
<div class="flex items-center gap-2">
|
||||
<span class="font-medium">ACP 会话</span>
|
||||
@@ -148,14 +94,8 @@
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<NList
|
||||
v-if="acpSessions.length > 0"
|
||||
:show-divider="false"
|
||||
>
|
||||
<NListItem
|
||||
v-for="s in acpSessions"
|
||||
:key="s.id"
|
||||
>
|
||||
<NList v-if="acpSessions.length > 0" :show-divider="false">
|
||||
<NListItem v-for="s in acpSessions" :key="s.id">
|
||||
<NThing
|
||||
:class="workspaceSlug ? 'cursor-pointer' : ''"
|
||||
@click="workspaceSlug ? goAcpSession(s) : undefined"
|
||||
@@ -173,19 +113,11 @@
|
||||
</NThing>
|
||||
</NListItem>
|
||||
</NList>
|
||||
<NEmpty
|
||||
v-else
|
||||
description="暂无会话"
|
||||
size="small"
|
||||
/>
|
||||
<NEmpty v-else description="暂无会话" size="small" />
|
||||
</NCollapseItem>
|
||||
</NCollapse>
|
||||
|
||||
<NEmpty
|
||||
v-else-if="!loading"
|
||||
description="暂无历史产物与会话"
|
||||
size="small"
|
||||
/>
|
||||
<NEmpty v-else-if="!loading" description="暂无历史产物与会话" size="small" />
|
||||
</NSpin>
|
||||
</NCard>
|
||||
</template>
|
||||
@@ -210,6 +142,7 @@ import { chatApi, type Conversation } from '@/api/chat'
|
||||
import { acpApi, type AcpSession } from '@/api/acp'
|
||||
import type { Artifact, ArtifactPhase, Phase } from '@/api/projects'
|
||||
import { md } from '@/utils/markdown'
|
||||
import { formatDate, formatDateTime } from '@/utils/date'
|
||||
import { useRequirementsStore } from '@/stores/requirements'
|
||||
import SessionStatusBadge from '@/components/acp/SessionStatusBadge.vue'
|
||||
|
||||
@@ -258,8 +191,9 @@ const artifactsByPhase = computed(() => {
|
||||
return map
|
||||
})
|
||||
|
||||
const hasAnyContent = computed(() =>
|
||||
artifacts.value.length > 0 || conversations.value.length > 0 || acpSessions.value.length > 0,
|
||||
const hasAnyContent = computed(
|
||||
() =>
|
||||
artifacts.value.length > 0 || conversations.value.length > 0 || acpSessions.value.length > 0,
|
||||
)
|
||||
|
||||
// 默认展开有内容的第一项(优先当前阶段)
|
||||
@@ -313,14 +247,6 @@ function goAcpSession(s: AcpSession) {
|
||||
})
|
||||
}
|
||||
|
||||
function formatDate(d: string) {
|
||||
return new Date(d).toLocaleDateString('zh-CN')
|
||||
}
|
||||
|
||||
function formatDateTime(d: string) {
|
||||
return new Date(d).toLocaleString('zh-CN', { hour12: false })
|
||||
}
|
||||
|
||||
async function refresh() {
|
||||
loading.value = true
|
||||
try {
|
||||
|
||||
Reference in New Issue
Block a user