9.2 KiB
| date | topic |
|---|---|
| 2026-07-02 | private-board-restrictions-and-scheme-b-bubbles |
Summary
收尾私董会(@board)模块的 UI 细节与单会话状态约束。三处改动:(1) 限制一个对话只能存在一个私董会,新建私董会必须从新会话发起;(2) 将 BoardBannerCard(私董会开始卡片)从带边框 / 紫条 / 进度条 / 专家 chip 的重样式简化为单行标题 + 副标题;(3) 给所有 AssistantText 渲染添加方案 B 风格的浅灰圆角矩形气泡,与方案 B 截图保持一致。
Problem Frame
私董会功能自 2026-06 上线以来已能正确触发多轮讨论,但 UI 上仍残留三处粗糙点:
- 单会话多私董会无约束。
ChatInput.vue:75的"私董会"按钮@click直接showBoardModal = true,对当前会话是否已经存在私董会无任何判断。后端在board_started事件中没有按会话做去重,连续两次SendMessage("@board:...")会在同一会话里创建第二个私董会,叠加在第一个未结束的私董会之上,boardState.experts被覆盖、轮次错乱、StickyModeHeader头像数与实际不符。 BoardBannerCard样式过重。BoardBannerCard.vue:55-137使用了background / border / border-radius / box-shadow四件套 + 4px 紫条 + 进度条 + 专家 chip pill,与方案 B 整体"克制、不重样式"的取向冲突。方案 B 截图(参考docs/.../2026-06-18-chat-area-vi-redesign-requirements.md中的方案 B 示意)的"开始"标题区域是单行文本,不带装饰。- 方案 B 气泡未落地。方案 B 截图中的"专家发言"区域是有浅灰圆角矩形气泡包裹内容(不是无气泡),与 ChatGPT / Notion AI 风格一致。当前
AssistantText.vue:1-30的内容区.assistant-text没有背景 / 边框 / 圆角,气泡效果完全缺失。
Key Decisions
-
私董会限制的"已存在"判断以
boardState.status为准:status === 'discussing' | 'concluding'时禁止在当前会话再次发起;status === 'completed' | 'dissolved' | null时允许(已完成 / 已解散的旧私董会不阻塞新私董会)。判断点放在ChatInput.vue"私董会"按钮@click处(最自然的 UX 拦截点),不放在BoardMeetingModal内部(避免用户填表后才发现不能发起)。 -
私董会限制的反馈方式是 a-modal 弹窗 + 快捷新建按钮。点击"私董会"按钮时若检测到已有私董会,弹出
a-modal,标题"当前会话已存在私董会",副文"请新建会话来创建新的私董会",按钮"我知道了" + "新建会话"。"新建会话"按钮直接调用chatStore.createConversation()并chatStore.selectConversation(newId),让用户立即在新会话里继续操作。 -
BoardBannerCard 简化为单行标题 + 副标题。完全去掉
BankOutlined图标、专家 chip 列表、4px 紫条、进度条、卡片背景 / 边框 / 圆角 / 阴影。最终输出形如:私董会 — 利用 agent 实现私董会的功能,应该用什么功能来打动客户 轮次:第 1 / 5 轮标题字号 =
var(--font-base)加粗 + 主题文本;副标题字号 =var(--font-xs)+var(--text-tertiary)。StickyModeHeader顶部的紫色"私董会"徽章 + 主题 + 专家头像组保持不变,承担需要"重样式"的展示职责。 -
方案 B 浅灰气泡应用到所有 assistant 消息。具体范围:
role === 'assistant'的所有MessageShell内的内容(普通 chat、@team 阶段、@board 发言、Debate、Plan exec、Tool result 等)都加同款浅灰圆角矩形气泡;role === 'user'的用户消息气泡保留现有UserBubble.vue的右对齐独立样式,不加 AssistantText 风格的浅灰块。气泡使用 token 颜色(var(--bg-secondary)或var(--bg-elevated)系)+ 圆角var(--radius-md)+ 内边距var(--space-3) var(--space-4),确保与方案 B 截图视觉一致;颜色与边框用 CSS 变量绑定,禁止硬编码#f3f4f6/#fbfbfa/#ededec等值。 -
气泡内的代码块、表格、行内代码样式保持不变。
AssistantText.vue:257-401的pre / hljs / code / table样式已经在 dark-on-light 配色上做了适配(--code-bg/--code-fg/--code-keyword等 token),气泡背景换浅灰后这些 token 自动适配,不需要单独再改。 -
不触碰 StickyModeHeader 顶部条。顶部条的紫色边框、徽章、4 个专家头像等不属于本次改动范围。
Requirements
单会话私董会限制
- R1.
ChatInput.vue的"私董会"按钮@click处理函数在打开BoardMeetingModal前,先检查chatStore.boardState.value:若非 null 且status === 'discussing' | 'concluding',触发 a-modal 弹窗,不打开BoardMeetingModal。 - R2. a-modal 弹窗内容:标题"当前会话已存在私董会",副文案"请新建会话来创建新的私董会",按钮"我知道了"(关闭弹窗)+ "新建会话"(主操作)。"新建会话"按钮点击后:(a) 关闭弹窗;(b) 调用
chatStore.createConversation();(c)await chatStore.selectConversation(newId);(d) 不自动打开BoardMeetingModal,由用户在新会话中再次点击"私董会"按钮继续。 - R3. 若
boardState.value === null或status === 'completed' | 'dissolved',保持当前行为:showBoardModal = true直接打开BoardMeetingModal,不弹提示。 - R4. 判定不依赖后端 /
is_board标记 /conv.is_board——以前端chatStore.boardState.value实时状态为权威源,避免 reload 后误判。
私董会开始卡片简化
- R5.
BoardBannerCard.vue重构为单行标题 + 副标题:保留topic / maxRounds / currentRoundprops(向后兼容调用方),不再使用expertsprops(删除 prop)。 - R6. 模板输出仅两行:第一行
私董会 — {topic}(无 BankOutlined、无边框、无背景、无圆角、无 4px 紫条);第二行轮次:第 {currentRound} / {maxRounds} 轮(小灰字)。 - R7.
<style scoped>中删除.board-banner-card/.board-banner-card__bar/.board-banner-card__chip等所有重样式相关类;保留.board-banner-card__title/.board-banner-card__meta两条最小样式。 - R8.
useMessageRenderer.ts中board_started的渲染路径不变(仍然渲染BoardBannerCard组件),确保 streaming 期间与 reload 后的视觉一致。
AssistantText 浅灰气泡
- R9.
MessageShell.vue的.message-shell__content增加浅灰气泡样式:仅当role === 'assistant'时生效(user角色不触发);background: var(--bg-secondary)+border-radius: var(--radius-md)+padding: var(--space-3) var(--space-4)+border: 1px solid var(--border-color)+color: var(--text-primary)。 - R10. 气泡样式不使用
!important,不覆盖组件内已有的代码块 / 表格 / 路由 tag 样式(这些样式已经在 R-9 之外独立维护)。 - R11. 浅灰气泡不影响
BoardRoundCard内AssistantText的渲染(已统一走MessageShell槽位)。 - R12. 私董会专家发言(
board_speech/board_summary)、普通 chat assistant 消息、@team 阶段消息、Debate 消息都通过MessageShell+AssistantText渲染,因此统一获得 R-9 浅灰气泡,无需逐个组件加样式。 - R13. 气泡宽度继承
.message-shell__content的现有width: 100%; max-width: 100%——气泡跟随消息列宽自适应,不强制固定最大宽度。
Scope Boundaries
Deferred for later
- 后端按会话去重
board_started:本次只做前端拦截,不改后端逻辑。后端允许同一会话收到多次board_started是当前事实,本次不做接口变更;前端的"未在新会话发起"拦截在功能上等价于"阻止重复发起"。如果未来需要在多端 / 多浏览器同步场景下做强一致,再考虑后端校验。 - StickyModeHeader 顶部条的视觉细化(徽章大小、专家头像间距、紫色边框粗细)不在本次范围。
- BoardConclusionCard / DebateBannerCard / TeamPlanCard 等其他 board 模式组件的样式统一:本次只改
BoardBannerCard,其他卡片样式留待后续迭代。
Outside this product's identity
- 不调整方案 B 调色板(
expertIdentity.ts的 12 色 PALETTE)和专家头像首字符规则。 - 不调整私董会后端流程(
BoardOrchestrator/chatStream事件顺序)。 - 不调整 AssistantText 的 markdown 渲染逻辑、代码高亮、表格样式。
Dependencies / Assumptions
- 假设:
chatStore.createConversation()存在并返回新会话 id(chatStore.ts:310已确认)。 - 假设:
chatStore.selectConversation(id)可异步调用(chatStore.ts:218已确认)。 - 假设:
BoardState.status类型为"discussing" | "concluding" | "completed" | "dissolved"(chatStream.ts:65已确认),"已存在私董会"判断取discussing | concluding。 - 假设:
--bg-secondary/--radius-md/--space-3/--space-4/--border-color/--text-primary已在tokens.css中定义并被前端使用(styles/tokens.css已确认存在)。 - 不确定性:私董会可能存在的中间状态(
forming/executing/synthesizing等)目前不在BoardState.status联合中;如果未来增加新 status,本次"已存在"判断需扩展。