From d5f6dc6990ae1265753190b2459724f2731ebef1 Mon Sep 17 00:00:00 2001 From: mesalogo Date: Wed, 23 Sep 2026 23:44:08 +0800 Subject: [PATCH] fix: hide queue attachment action for messages without attachments Derive attachment presence from saved queue inputs and only show the preview action when attachments exist. Cover queue metadata and button visibility with regression tests. Release note: Queued messages without attachments no longer show the View attachments button. --- docs/features/document-processing/ui-design.md | 2 +- src/main/assistant/assistant-database.test.ts | 16 ++++++++++++++++ src/main/assistant/assistant-database.ts | 11 +++++++++++ src/renderer/src/App.tsx | 1 + src/renderer/src/ConversationInputQueue.test.tsx | 13 +++++++++++++ src/renderer/src/ConversationInputQueue.tsx | 2 +- src/shared/assistant-contracts.ts | 1 + 7 files changed, 44 insertions(+), 2 deletions(-) diff --git a/docs/features/document-processing/ui-design.md b/docs/features/document-processing/ui-design.md index 73ea2de8..35a24e1e 100644 --- a/docs/features/document-processing/ui-design.md +++ b/docs/features/document-processing/ui-design.md @@ -64,7 +64,7 @@ | 草稿图片,发送原图 | 打开原图;已有 OCR 结果时可查看 | 提取图片文字、移除 | | 草稿图片,发送提取文字 | 查看解析结果、打开原图 | 改为发送原图、使用当前设置重新提取文字、移除 | | 历史消息附件 | 查看已保存结果、打开原件 | 需要重解析或改变发送方式时先添加到当前可编辑草稿;不修改原消息 | -| 已入队附件 | 查看入队时冻结的结果与发送方式 | 修改整条输入使用“恢复到草稿”,按 L-H7 合并;不直接修改队列附件 | +| 已入队附件 | 仅有附件时显示“查看附件”,查看入队时冻结的结果与发送方式;无附件时隐藏入口 | 修改整条输入使用“恢复到草稿”,按 L-H7 合并;不直接修改队列附件 | | 知识文档 | 查看解析结果、打开来源、管理分块 | 使用当前设置重新解析;失败时使用重试,不再并列一个同义重解析按钮;来源同步仍属于来源级操作 | | 设置测试结果 | 查看正文、图片、详情及原件 | 重新测试、关闭;没有加入草稿、知识库或发送操作 | diff --git a/src/main/assistant/assistant-database.test.ts b/src/main/assistant/assistant-database.test.ts index ba559e1c..fe6d68ad 100644 --- a/src/main/assistant/assistant-database.test.ts +++ b/src/main/assistant/assistant-database.test.ts @@ -4618,6 +4618,22 @@ describe('AssistantDatabase', () => { } ]) + for (const [payload, hasAttachments] of [ + [{ prompt: 'text' }, false], + [{ input: { attachments: [] } }, false], + [{ input: { attachments: [{ id: 'attachment' }] } }, true], + [{ attachments: [{ id: 'attachment' }] }, true] + ] as const) { + const queued = initial.enqueueConversationUserInput({ + conversationId, + label: 'Attachment visibility', + payloadJson: JSON.stringify(payload) + }) + expect(queued.hasAttachments).toBe(hasAttachments) + expect(initial.listConversationQueueItems(conversationId)[0]?.hasAttachments).toBe(hasAttachments) + initial.cancelConversationQueueItem(queued.id) + } + const first = initial.enqueueConversationUserInput({ conversationId, label: '第一条消息', diff --git a/src/main/assistant/assistant-database.ts b/src/main/assistant/assistant-database.ts index 1852489d..0e2f3225 100644 --- a/src/main/assistant/assistant-database.ts +++ b/src/main/assistant/assistant-database.ts @@ -782,7 +782,18 @@ function toSchedule(row: ScheduleWithTaskRow): AssistantSchedule { function toConversationQueueItem( row: ConversationQueueRow ): ConversationQueueItem { + let hasAttachments = false + if (row.source === 'user' && row.payload_json) { + try { + const payload = JSON.parse(row.payload_json) + const input = payload?.input ?? payload + hasAttachments = Array.isArray(input?.attachments) && input.attachments.length > 0 + } catch { + // Invalid queued payloads are reported when previewed or dispatched. + } + } return { + hasAttachments, id: row.id, conversationId: row.conversation_id, source: row.source, diff --git a/src/renderer/src/App.tsx b/src/renderer/src/App.tsx index 4ea1516b..d168eeef 100644 --- a/src/renderer/src/App.tsx +++ b/src/renderer/src/App.tsx @@ -311,6 +311,7 @@ function sameConversationQueueItems( item.id === candidate.id && item.conversationId === candidate.conversationId && item.source === candidate.source && + item.hasAttachments === candidate.hasAttachments && item.label === candidate.label && item.createdAt === candidate.createdAt && item.scheduleRunId === candidate.scheduleRunId && diff --git a/src/renderer/src/ConversationInputQueue.test.tsx b/src/renderer/src/ConversationInputQueue.test.tsx index fa8d26f7..dc205a29 100644 --- a/src/renderer/src/ConversationInputQueue.test.tsx +++ b/src/renderer/src/ConversationInputQueue.test.tsx @@ -81,6 +81,19 @@ describe('ConversationInputQueue', () => { ) }) + it.each([undefined, false, true])('shows attachment preview only for attached inputs (%s)', (hasAttachments) => { + render( + + ) + expect(screen.queryByTitle('查看附件') !== null).toBe(hasAttachments === true) + }) + it('uses run-now wording while idle and reports action errors', async () => { const onError = vi.fn() render( diff --git a/src/renderer/src/ConversationInputQueue.tsx b/src/renderer/src/ConversationInputQueue.tsx index ecbf8dbd..933c9875 100644 --- a/src/renderer/src/ConversationInputQueue.tsx +++ b/src/renderer/src/ConversationInputQueue.tsx @@ -93,7 +93,7 @@ export const ConversationInputQueue = memo( {item.error && {item.error}} - {item.source === 'user' && } + {item.source === 'user' && item.hasAttachments && } {onRestore && item.source === 'user' && }