拓冰建站拓冰建站
首页 / 资讯中心 / 正文

AionUi 对话发送草稿箱:AI 回复期间消息排队交互的完整设计与源码实现

AionUi 对话发送草稿箱AI 回复期间消息排队交互的完整设计与源码实现【免费下载链接】AionUi免费、本地、开源的 24/7 全天候 Cowork 应用以及适用于 Gemini CLI、Claude Code、Codex、OpenCode、Qwen Code、Goose CLI、Auggie 等的 OpenClaw | 喜欢就点star吧项目地址: https://gitcode.com/iOfficeAI/AionUi本文围绕 AionUiiOfficeAI/AionUi 开源仓库对话模块中的「发送草稿箱」原「排队面板」展开系统梳理其从交互优化需求PRDdocs/prds/conversations/send-drafts.md到渲染层落地的完整链路包括每条草稿的常驻操作、立即发送插队、自动/手动双模式、清空防误触、拖拽排序与窄栏适配等七项功能规格并结合CommandQueuePanel组件、useConversationCommandQueue状态 hook 与配套单元测试逐层讲解其数据模型、持久化策略、发送门控与容错机制。读完本文你将掌握该功能的交互设计决策、状态机原理与源码级实现细节可直接用于理解或二次开发同类消息暂存/排队能力。一、背景与目标从「排队面板」到「发送草稿箱」在 AionUi 中AI如 Gemini CLI、Claude Code、Codex、OpenCode、Qwen Code、Goose CLI、Auggie 等 Agent 运行时正在回复时用户仍可继续输入并发送消息这些消息会进入一个位于对话输入区上方的排队面板等待发出。这一能力原本已经存在支持入队、编辑、删除、清空、当前 turn 结束后自动发送以及拖拽调整顺序。但根据微信群用户反馈旧交互存在三个明显痛点每条排队消息只有「删除」直接可见「编辑」被折叠进「⋯」更多菜单要点两下才找得到没有「立即发送」能力——排队的消息只能等 AI 回复结束后被动等待用户无法让某一条马上发出去排队面板缺少「是否自动发送」的总控开关用户无法选择我先攒着、想发再发。因此本次优化的核心目标是把排队面板重新定位成一个「发送草稿箱」AI 忙时用户写下的消息先存到这里用户可以清楚看到并随手操作立即发送 / 编辑 / 删除 / 调序并且可以选择让草稿箱自动依次发出、还是手动由用户逐条发。按 PRD 约定整个改造不改后端全部在渲染层完成涉及范围为对话输入区上方的排队面板。三个关键名词约定发送草稿箱面板的新名字指 AI 回复期间用户已发送、正在等待发出的消息集合下文沿用旧代码中的「排队 / 队列」时指同一事物草稿草稿箱里的单条待发消息含文字与文件以及会话引用自动 / 手动草稿箱的两种发送模式见 F-DRAFT-03。在源码中该功能对应的实现文件为面板 UIpackages/desktop/src/renderer/components/chat/CommandQueuePanel.tsx状态与执行逻辑packages/desktop/src/renderer/pages/conversation/platforms/useConversationCommandQueue.ts接入点ACP 平台发送框AcpSendBox.tsx、AionRS 平台发送框AionrsSendBox.tsx。二、功能规格全景七项 F-DRAFT 需求PRD 将本次改造拆解为七个功能点其中两项为新增、四项为优化、一项为保留编号功能类型F-DRAFT-01每条草稿的三个常驻操作立即发送 / 编辑 / 删除优化F-DRAFT-02立即发送打断当前回复插队发出新增F-DRAFT-03自动 / 手动发送模式新增F-DRAFT-04草稿箱标题行与说明优化F-DRAFT-05清空草稿箱防误触优化F-DRAFT-06拖拽调整顺序保留F-DRAFT-07窄栏 / 移动端适配新增下文逐项说明其用户故事、正常流程、异常情况与验收标准并在对应小节后给出源码实现证据。三、(F-DRAFT-01) 每条草稿的三个常驻操作用户故事每条排队的消息都能一眼看到「立即发送 / 编辑 / 删除」三个操作随手就能点不用翻菜单。正常流程用户视角AI 回复期间用户发送的消息进入发送草稿箱逐条列在输入框上方每条草稿右侧常驻三个操作按钮鼠标不悬停也始终可见立即发送见 F-DRAFT-02编辑把这条草稿的文字与文件放回输入框供修改该草稿从箱中移除改完重新发送即重新入箱删除把这条草稿从箱中移除不再发出三个操作在移动端、窄栏下同样常驻可点不依赖 hover。异常情况草稿箱为空时面板整体不显示。验收标准三个按钮无需 hover 或展开菜单即常驻可见「编辑」不再藏在「⋯」菜单里「删除」将该条从草稿箱移除「编辑」将该条内容与文件回填输入框并从箱中移除三个按钮在移动端 / 窄栏下均可直接点击。源码实现在CommandQueuePanel.tsx中每条草稿卡片的右侧渲染了三个renderQueueActionIconButton图标按钮分别为SendOne立即发送accent主色强调、Edit编辑、Delete删除danger危险色三者均以sizemini、圆形文本按钮形式常驻显示不依赖 hover。按钮通过aria-label提供无障碍访问文案来自 i18n 的conversation.commandQueue.sendNow / edit / remove键。当items.length 0时组件直接return null即草稿箱为空时面板整体不渲染对应代码。四、(F-DRAFT-02) 立即发送打断当前回复插队发出用户故事当用户发现某条消息在排队、但希望它马上就走时点一下就立刻发出去。正常流程用户视角用户点击某条草稿的「立即发送」系统打断 AI 当前正在进行的回复将该条草稿立即出队并发送用户能理解这打断了当前回复——不额外弹提示条草稿箱里剩余的草稿行为完全不变原本自动就继续自动依次发原本手动就继续等待用户逐条发发送模式、内容、顺序都不受这次插队影响。边界说明「立即发送」只作用于被点击的这一条。它是一次让这条插队立刻走的动作不是模式切换不引入「暂停 / 继续」这类额外状态。异常情况AI 当前没有正在进行的回复已空闲时直接发送该条无需打断。验收标准点击「立即发送」会中止 AI 当前回复并立刻发出该条草稿不出现已插队 / 队列已暂停之类的提示条剩余草稿的发送模式、内容、顺序均不因这次插队而改变AI 空闲时点击「立即发送」直接发出不产生打断副作用。源码实现hook 中的sendNow(commandId)先按commandId定位目标草稿仅删除目标项其余项保持原 mode、顺序与 paused 标志然后直接调用onExecuteRef.current(target)执行发送useConversationCommandQueue.ts。发送失败时如果错误可归类为会话忙classifyConversationBusyError草稿会被放回队列头部并进入 busy-wait 等待状态其他错误则恢复该条并将队列置为暂停态同时弹出提示下一条排队指令启动失败。请编辑、调整顺序或移除后再继续。这保证了立即发送失败时用户的消息不会丢失而是回到草稿箱待处理。五、(F-DRAFT-03) 自动 / 手动发送模式用户故事用户能选择草稿箱是「AI 回完自动帮我依次发」还是「先攒着、我想发再发」。正常流程用户视角草稿箱标题行右侧有一个模式切换按钮显示当前模式自动 / 手动点一下即切到另一模式无需二次确认自动模式AI 每结束一轮回复草稿箱自动把下一条发出去一条接一条直到发完用户无需操作手动模式草稿只暂存在箱中、不自动发出由用户逐条点「立即发送」决定何时发。作用范围会话级纯前端模式是每个对话各自记录的A 对话设手动不影响 B 对话每个对话启动时默认「自动」PRD 设计当前仓库实现中默认值见下文差异说明该设置与现有排队内容一样保存在前端会话级存储中应用运行期间切走再切回该对话模式与草稿都保留整个应用关闭重开后重置草稿与模式都回到初始与现有排队行为一致。异常情况草稿箱为空时面板不显示但模式设置在后台保留下次有草稿入箱时按该模式运作。验收标准切换按钮显示当前模式、点击即切换无二次确认自动模式下 AI 每轮结束后自动依次发出草稿手动模式下草稿不自动发出新对话默认自动模式模式按对话独立记录互不影响应用关闭重开后模式回到默认。源码实现类型层面定义ConversationCommandQueueMode auto | manualuseConversationCommandQueue.ts。toggleMode()在auto与manual之间翻转并记录mode-changed日志L1019-L1032。自动发送的主循环位于组件内一个useEffect中仅当mode auto、执行门控可执行、未暂停、无正在等待的 turn 且队列非空时取出队首草稿发送并通过turnCompleted事件驱动每轮结束后发下一条的节奏L1080-L1164。此外还实现了后台 runner对话切走组件卸载后drainBackgroundCommandQueue仍会监听ipcBridge.conversation.turnCompleted事件继续把自动模式的队列发完L432-L561。PRD 与实现的差异说明PRD 设计新对话默认自动而从当前仓库源码看createDefaultQueueState()返回的默认 mode 为manualnormalizeQueueMode()也把非auto的值一律归一为manualL100-L106。可以推断实现侧选择了更保守的默认值——避免用户未察觉时消息被自动发出。若要以 PRD 的默认自动落地只需调整默认状态与归一化逻辑属纯前端改动。六、(F-DRAFT-04) 草稿箱标题行与说明用户故事用户一眼看懂这个面板是什么、当前处于什么模式需要时能查到自动 / 手动的含义。标题行布局草稿箱框内顶部一行自左到右标题「发送草稿箱」 数量徽标显示当前草稿条数模式切换按钮F-DRAFT-03帮助「?」hover 显示说明——草稿箱是什么以及自动 / 手动分别的含义更多「⋯」见 F-DRAFT-05。帮助文案tooltip发送草稿箱AI 回复期间你发的消息会先存到这里。 自动AI 回复结束后自动依次发送草稿箱里的消息。 手动消息只暂存、不自动发由你逐条点「立即发送」。验收标准标题行显示「发送草稿箱」与草稿数量「?」hover 出说明覆盖草稿箱含义与两种模式。源码实现标题行位于CommandQueuePanel.tsx。左侧为自定义DraftBoxActionIconSVG 图标 标题i18nconversation.commandQueue.title中文为「草稿箱」与数量徽标直接渲染items.length右侧为模式切换按钮与「⋯」下拉菜单。值得注意的是当前实现把帮助入口与模式切换按钮合二为一Tooltip包裹模式按钮hover 即显示三行帮助文案helpIntro/helpAuto/helpManual组件注释明确说明模式切换按钮兼作帮助入口因此无需单独的「?」按钮L505-L526。这与 PRD 中单独「?」帮助按钮的设计略有出入属实现侧的等价简化——更省宽度且语义信息没有丢失。中文帮助文案见conversation.json的commandQueue.help*键。七、(F-DRAFT-05) 清空草稿箱防误触用户故事能一次清空整箱草稿但不要轻易误点到。正常流程用户视角「清空草稿箱」放在标题行「⋯」更多菜单里菜单项以危险色红呈现点击后再弹一次二次确认确认后才清空全部草稿。验收标准「清空草稿箱」位于「⋯」菜单内而非标题行直接可点菜单项以危险色呈现点击后需二次确认才执行清空。源码实现moreMenu下拉菜单中清空项Menu.Item的内联样式使用color: rgb(var(--danger-6))呈现危险色CommandQueuePanel.tsx。点击后调用Modal.confirm弹出二次确认框标题确定清空发送草稿箱、正文所有待发送的消息都会被移除且无法恢复。确认按钮同样以status: danger呈现L434-L444。确认后执行onClear对应 hook 中的clear()——它会重置所有等待标记并清除持久化状态L748-L756。八、(F-DRAFT-06) 拖拽调整顺序保留能力用户故事用户能调整草稿的发送先后顺序。正常流程用户视角每条草稿最前有一个拖拽手柄hover 时显现按住可上下拖动调整顺序顺序即草稿箱自动 / 手动发出的先后次序。验收标准桌面端 hover 草稿时显现拖拽手柄可上下拖动排序排序结果即后续发送次序。源码实现拖拽基于dnd-kit/core与dnd-kit/sortableverticalListSortingStrategy。每条草稿的拖拽手柄是一个带Drag图标的按钮默认opacity-0group-hover:opacity-100即在 hover 时显现CommandQueuePanel.tsx。为了把拖动限制在队列容器内组件实现了createRestrictToQueueContainerModifier与restrictToVerticalAxis组合使用保证拖拽不会超出面板边界L43-L62。onReorder(activeCommandId, overCommandId)对应 hook 中纯函数reorderQueuedCommand——按 id 找到起止索引后 splice 移动L326-L342。排序结果即队列顺序也就是自动 / 手动发送时的出队次序。九、(F-DRAFT-07) 窄栏 / 移动端适配用户故事在小屏、移动端或团队并排 Agent 视图下草稿箱在窄栏里也摆得下、点得到。适配策略约 300px 宽及以下标题「发送草稿箱」收成一个图标 数量徽标hover / 长按显示全名省出宽度模式切换按钮始终保留核心功能文字压到「自动 / 手动」两字「?」帮助并入「⋯」菜单窄栏头部只保留一个「⋯」其中包含「使用说明」与「清空草稿箱」每条草稿的三个操作按钮不变消息文字自动截断拖拽手柄在窄栏隐藏改为长按整条拖动。验收标准窄栏下标题收成图标 徽标、切换按钮保留「?」并入「⋯」菜单、头部仅一个「⋯」每条三个操作按钮仍可点击、文字自动截断团队并排 Agent 视图下草稿箱布局不溢出、不错位。源码实现CommandQueuePanel接收isMobile属性。窄栏时左侧标题用Tooltip包裹的DraftBoxActionIcon图标代替文字标题hover 显示全名L485-L496「⋯」菜单在isMobile时额外加入一个help菜单项把帮助内容以多行文本形式放进菜单L452-L466。拖拽方面移动端dragViaCard为 true隐藏手柄、改为长按整条 200ms触发拖动PointerSensor的activationConstraint在移动端为{ delay: 200, tolerance: 6 }桌面端为{ distance: 8 }200ms 的延迟同时也避免普通点击操作按钮被误判为拖拽L360-L367。列表容器最大高度在移动端为min(48vh, 320px)桌面端为min(36vh, 320px)L560-L562。十、源码级纵深状态模型、持久化与执行门控10.1 数据模型与常量队列项类型ConversationCommandQueueItem包含五个字段useConversationCommandQueue.ts字段类型说明idstring唯一标识uuid()生成inputstring消息正文filesChatFileRef[]附件文件引用按chatFileRefKey去重sessionsSessionRef[]会话引用必须随消息存活否则 Agent 静默丢失会话块created_atnumber入队时间戳队列状态ConversationCommandQueueState { items, isPaused, mode }。配套的硬性容量上限常量超出即拒绝入队并弹提示MAX_QUEUED_COMMANDS 20最多 20 条MAX_QUEUED_COMMAND_INPUT_LENGTH 20_000单条正文最长 20000 字符MAX_QUEUED_COMMAND_FILES 50单条最多 50 个文件MAX_QUEUED_COMMAND_STATE_BYTES 256 * 1024整个队列持久化状态不超过 256KB。入队前会通过validateQueuedCommandItem做完整校验失败原因枚举包括emptyInput / inputTooLong / tooManyFiles / queueFull / queueTooLarge每种都有对应的 i18n 提示文案中文见conversation.json。10.2 会话级持久化sessionStorage模式与草稿按对话隔离存储存储键为conversation-command-queue/${conversation_id}写入window.sessionStorageL110、L303-L319。这与 PRD 的会话级存储设计完全一致应用运行期间切走再切回模式与草稿从 sessionStorage 恢复保留整个应用关闭重开后 sessionStorage 清空草稿与模式回到初始当队列为空、未暂停且为默认模式时持久化键会被主动删除避免残留脏数据。读取时使用normalizeQueueState做严格的数据净化逐条校验 id/input/files/created_at 类型非法的sessions引用被丢弃而非让整条消息作废丢失过期引用可恢复丢失用户输入不可恢复并再次套用容量上限L168-L200。10.3 执行门控Execution Gate队列是否允许出队发送由getCommandQueueExecutionGate统一裁决常规场景下canExecute !isBusy在团队运行时场景下则透传runtimeGatecanSendMessage !isProcessing与团队并排 Agent 视图的运行时状态联动L387-L409。hook 内部用一组 ref 状态机跟踪waitingForTurnStart / waitingForTurnCompletion / waitingForBusyRelease并通过conversation.turnCompleted事件精确感知一轮回复结束从而决定何时发送下一条L621-L680。发送失败时按忙等待 / 真失败分流忙则把草稿放回队首继续等真失败则暂停队列并提示用户编辑、重排或移除问题项。10.4 与发送框的接线在 ACP 平台发送框AcpSendBox.tsx中useConversationCommandQueue被接入L421-L431CommandQueuePanel渲染在输入区上方L783其isBusy判断为isCancelling || runtimeGate.isProcessing || !runtimeGate.canSendMessageL249。发送框还提供「存到草稿箱」能力AI 处理中时直接发送被拦截用户可按⌘ Enter / Ctrl Enter将输入存为草稿对应 i18naddToQueueShortcut。10.5 配套测试该功能在仓库中有完整的测试覆盖可作为行为契约参考CommandQueuePanel.dom.test.tsx面板交互常驻操作、模式切换、清空确认、拖拽等的 DOM 级测试conversationCommandQueueMode.dom.test.tsx自动 / 手动模式行为conversationCommandQueueDrain.dom.test.tsxturn 结束后自动出队发送链路conversationCommandQueueGate.test.ts执行门控裁决逻辑conversationCommandQueueSessions.test.ts与conversationCommandQueueChatFileRef.test.ts会话引用与文件引用的持久化保真。十一、待讨论事项与落地取舍PRD 在「待讨论模块」中记录了两个问题可作为后续迭代方向参考控件形态已定模式切换采用「单按钮状态切换」按钮显示当前模式点击切到另一模式不采用拨动开关或分段按钮。当前实现与此一致——标题行右侧就是一个带模式文字与SortTwo图标的胶囊按钮。是否需要「全局默认模式」当前为纯会话级、新对话默认PRD 规划为自动当前实现为手动。若后续收到每次开新对话都要重设太麻烦的反馈可再评估增加一个全局默认值设置项。此项本期不做。此外实现相对 PRD 有两处值得注意的取舍默认模式PRD 设计默认「自动」当前源码默认「手动」见 F-DRAFT-03 差异说明建议以仓库实际行为为准进行体验评估帮助入口PRD 规划独立「?」按钮当前实现将帮助 tooltip 合并到模式切换按钮上窄栏下再并入「⋯」菜单兼顾了信息可达性与宽度占用。结语AionUi 的「发送草稿箱」是一个纯渲染层、不改后端的典型交互升级它把原本被动等待的排队面板升级为具备常驻操作、立即插队、自动/手动双模式、防误触清空、拖拽排序与窄栏适配的完整消息暂存与发送控制台。从CommandQueuePanel的 UI 实现到useConversationCommandQueue的状态机、持久化与执行门控再到覆盖行为契约的单元测试整个能力链路清晰可查。若你正在设计同类AI 忙碌时的消息缓冲交互这份 PRD 与其落地源码是极具参考价值的完整范例。【免费下载链接】AionUi免费、本地、开源的 24/7 全天候 Cowork 应用以及适用于 Gemini CLI、Claude Code、Codex、OpenCode、Qwen Code、Goose CLI、Auggie 等的 OpenClaw | 喜欢就点star吧项目地址: https://gitcode.com/iOfficeAI/AionUi创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门