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