优化: 会话入口与对话交互打磨

- 完成卡点开子代理轨迹浮层,任务抽屉关联会话跳转
- 提及片段编辑差分三向判定,不再错位
- 长回复折叠完成瞬间锚定消息顶,视口不跳
- 空编辑/技能无匹配/回填覆盖草稿均有提示确认
- 队列编辑态切会话重置,刷新快捷键不再误触
- git 变更面板去重缓存,项目卡骨架与溢出重测
This commit is contained in:
lxy
2026-10-03 17:57:43 +08:00
parent 890ceef0ec
commit f67e65633b
8 changed files with 433 additions and 19 deletions
+47 -1
View File
@@ -65,6 +65,19 @@
<router-link :to="`/ideas/${task.idea_id}`" class="project-link" @click="$emit('close')">{{ ideaTitle }}</router-link>
</span>
</div>
<!-- S4 关联会话:后端审计表反查的主会话,无关联时入口隐藏;点击关抽屉 + 跳会话 -->
<div v-if="taskConversations.length > 0" class="info-item">
<span class="label">{{ $t('taskDetail.relatedConversations') }}</span>
<span class="value conv-links">
<a
v-for="c in taskConversations"
:key="c.conversation_id"
class="conv-link"
:title="`${c.tool_name} · ${formatDate(c.requested_at)}`"
@click.prevent="handleOpenConversation(c.conversation_id)"
>{{ c.title || c.conversation_id }}</a>
</span>
</div>
<div v-if="task.branch_name" class="info-item">
<span class="label">{{ $t('taskDetail.branch') }}</span>
<span class="value">
@@ -169,10 +182,11 @@ import { ref, computed, watch } from 'vue'
import { useRouter } from 'vue-router'
import { useI18n } from 'vue-i18n'
import { Drawer } from '@arco-design/web-vue'
import { taskApi, projectApi, ideaApi } from '@/api'
import { taskApi, projectApi, ideaApi, aiApi } from '@/api'
import { useProjectStore } from '@/stores/project'
import { formatDate } from '@/utils/time'
import { useRendered } from '@/composables/useMarkdown'
import { useAiConversations } from '@/composables/ai/useAiConversations'
import { taskStatusLabel, taskStatusClass, priorityLabel, priorityClass, ADVANCE_MAP } from '@/constants/project'
import type { AdvanceAction } from '@/constants/project'
import type { TaskRecord, ProjectRecord, IdeaRecord } from '@/api/types'
@@ -192,6 +206,11 @@ const { t } = useI18n()
const router = useRouter()
const store = useProjectStore()
const { showToast } = useToast()
const { openConversation } = useAiConversations()
// 关联会话引用(S4:审计表反查,无关联=空数组 → 入口隐藏)
type TaskConvRef = { conversation_id: string; title: string | null; tool_name: string; requested_at: string }
const taskConversations = ref<TaskConvRef[]>([])
const loading = ref(true)
const errorMsg = ref('')
@@ -248,6 +267,9 @@ async function load() {
if (!tid) return
loading.value = true
errorMsg.value = ''
taskConversations.value = [] // 新一轮加载先清旧引用,防切换任务后残留上一任务的会话
// 关联会话为辅助入口,旁路加载不阻塞主数据;失败静默(入口不显示即降级)
void loadTaskConversations(tid)
try {
const [t, ps, ideasList] = await Promise.all([
taskApi.get(tid),
@@ -268,6 +290,21 @@ async function load() {
}
}
/** S4:拉当前任务的关联会话(独立于主 try,查失败不拖垮抽屉);响应回来校验 taskId 未变 */
async function loadTaskConversations(tid: string) {
try {
const refs = await aiApi.listTaskConversations(tid)
if (tid !== props.taskId) return // 任务已切换,旧任务响应丢弃
taskConversations.value = refs
} catch { taskConversations.value = [] }
}
/** 点击关联会话:先关抽屉(面板在抽屉下层,不关会被遮挡),再走 openConversation 跳转 */
async function handleOpenConversation(convId: string) {
emit('close')
await openConversation(convId)
}
async function loadChildren() {
const cur = task.value
if (!cur || cur.parent_id) { children.value = []; return }
@@ -356,4 +393,13 @@ async function confirmSubtask() {
.dr-badges { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.dr-header-actions { display: flex; align-items: center; gap: 6px; flex-shrink: 0; }
.loading-hint { text-align: center; padding: 40px 0; }
/* 关联会话:多会话纵向排列,链接样式对齐 .project-link 语义(TaskDrawer 内无其 scoped 定义) */
.conv-links { display: flex; flex-direction: column; gap: 4px; }
.conv-link {
color: var(--df-accent);
font-weight: 500;
cursor: pointer;
word-break: break-all;
}
.conv-link:hover { text-decoration: underline; }
</style>