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' && }