新增: 多会话并发前端 UI 阶段3/4(F-09 收尾)

后端 per-conv 并发已就绪(d899c58 + CR-03~07),前端呈现层收尾:

阶段3 多会话生成态:
- stores/ai.ts generatingConvId 单值 → generatingConvs:Set + add/remove/isGenerating helper
- useAiEvents 5 处迁移(Completed/Error/路由标记改 per-conv Set 操作,
  AiError 精确清出错会话非全局清空,修原 = null 误清其他会话)
- ConversationSidebar 多会话并行生成脉冲指示(isGenerating 各会话独立)

阶段4 独立窗口多会话:
- useAiWindow label ai-detached → ai-detached-{convId}(per-conv 独立窗口)
- localStorage 单 key → per-conv key(防多会话串扰,读路径兼容旧 key 回退)

vue-tsc EXIT 0 + generatingConvId 零代码残留(仅注释)
This commit is contained in:
2026-06-19 20:15:37 +08:00
parent 19eb14ffc8
commit 7d5402951b
12 changed files with 181 additions and 53 deletions

View File

@@ -192,8 +192,9 @@ const messagesContainer = ref<HTMLDivElement>()
const toolCardListRef = ref<InstanceType<typeof ToolCardList>>()
// 当前视图是否正在生成(切走后台生成时光标不显示)
// F-09: 多会话并发 — isGenerating(active) 替代单值比对
const isViewingGenerating = computed(() =>
store.state.streaming && store.state.generatingConvId === store.state.activeConversationId
store.state.streaming && store.isGenerating(store.state.activeConversationId)
)
function isLastAi(msg: AiMessage): boolean {
@@ -347,10 +348,10 @@ watch(() => store.state.streaming, (s) => {
if (rafId !== null) { cancelAnimationFrame(rafId); rafId = null }
if (s) {
// UX-260616-03: 新一轮生成开始 → 收起上一轮已完成的旧工具卡,聚焦当前生成内容。
// 仅当前视图正在生成时触发(generatingConvId 对齐 activeConversationId),
// 仅当前视图正在生成时触发(isGenerating(activeConversationId)),
// 切走后台生成/恢复会话(streaming 初值已 true 的 onMounted 路径)不误触。
// buildActiveToolIds/collapseAllToolLists 是 function 声明,提升可用。
if (store.state.generatingConvId === store.state.activeConversationId) {
if (store.isGenerating(store.state.activeConversationId)) {
collapseAllToolLists(buildActiveToolIds(store.state.messages))
}
} else {