diff --git a/easyflow-ui-admin/app/src/components/ai-chat/useChatDocumentUploads.test.ts b/easyflow-ui-admin/app/src/components/ai-chat/useChatDocumentUploads.test.ts index e77e9b20..b22e0508 100644 --- a/easyflow-ui-admin/app/src/components/ai-chat/useChatDocumentUploads.test.ts +++ b/easyflow-ui-admin/app/src/components/ai-chat/useChatDocumentUploads.test.ts @@ -16,6 +16,7 @@ vi.mock('./mediaApi', () => mediaApi); describe('useChatDocumentUploads', () => { afterEach(() => { vi.restoreAllMocks(); + vi.unstubAllGlobals(); Object.values(mediaApi).forEach((mock) => mock.mockReset()); }); @@ -68,6 +69,44 @@ describe('useChatDocumentUploads', () => { ); }); + it('uses getRandomValues when randomUUID is unavailable', async () => { + const getRandomValues = vi.fn((values: Uint8Array) => { + values.fill(171); + return values; + }); + vi.stubGlobal('crypto', { getRandomValues }); + mediaApi.uploadAgentChatDocument.mockImplementation( + async (file, _context, uploadId) => ({ + data: { + attachmentRef: 'document:chrome-90', + mimeType: file.type, + name: file.name, + size: file.size, + status: 'READY', + uploadId, + }, + errorCode: 0, + }), + ); + + const uploads = useChatDocumentUploads(); + await uploads.addFiles( + [new File(['document'], 'chrome-90.pdf', { type: 'application/pdf' })], + { agentId: 'agent-1', mode: 'FORMAL', sessionId: 'session-1' }, + ); + + expect(getRandomValues).toHaveBeenCalled(); + expect(mediaApi.uploadAgentChatDocument).toHaveBeenCalledWith( + expect.any(File), + { agentId: 'agent-1', mode: 'FORMAL', sessionId: 'session-1' }, + expect.stringMatching(/^[a-f0-9]{32}$/), + ); + expect(uploads.items.value[0]).toMatchObject({ + status: 'ready', + uploadId: expect.stringMatching(/^[a-f0-9]{32}$/), + }); + }); + it('exposes a server read failure without continuing to poll', async () => { mediaApi.uploadAgentChatDocument.mockResolvedValue({ data: { diff --git a/easyflow-ui-admin/packages/effects/common-ui/package.json b/easyflow-ui-admin/packages/effects/common-ui/package.json index 405c7731..faf6419e 100644 --- a/easyflow-ui-admin/packages/effects/common-ui/package.json +++ b/easyflow-ui-admin/packages/effects/common-ui/package.json @@ -32,6 +32,7 @@ "@easyflow/icons": "workspace:*", "@easyflow/locales": "workspace:*", "@easyflow/types": "workspace:*", + "@easyflow/utils": "workspace:*", "@incremark/theme": "1.0.2", "@incremark/vue": "1.0.2", "@vueuse/core": "catalog:", diff --git a/easyflow-ui-admin/packages/effects/common-ui/src/components/chat-timeline/useChatDocumentUploads.ts b/easyflow-ui-admin/packages/effects/common-ui/src/components/chat-timeline/useChatDocumentUploads.ts index d9159ba6..99f2bd58 100644 --- a/easyflow-ui-admin/packages/effects/common-ui/src/components/chat-timeline/useChatDocumentUploads.ts +++ b/easyflow-ui-admin/packages/effects/common-ui/src/components/chat-timeline/useChatDocumentUploads.ts @@ -2,6 +2,8 @@ import type { ChatDocumentAttachment } from './types'; import { computed, ref } from 'vue'; +import { uuid } from '@easyflow/utils'; + const MAX_DOCUMENTS = 3; const MAX_TOTAL_BYTES = 30 * 1024 * 1024; const MAX_OFFICE_BYTES = 20 * 1024 * 1024; @@ -61,7 +63,7 @@ function createLocalId() { } function createUploadId() { - return crypto.randomUUID().replaceAll('-', ''); + return uuid().replaceAll('-', ''); } function extensionOf(file: File) { @@ -170,11 +172,11 @@ export function createChatDocumentUploads(api: ChatDocumentUploadApi) { context: ChatDocumentUploadContext, ) { if (!item.file) return; - item.uploadId ||= createUploadId(); item.status = 'uploading'; item.error = undefined; const currentLifecycle = lifecycle; try { + item.uploadId ||= createUploadId(); const response = await api.upload(item.file, context, item.uploadId); if (response.errorCode !== 0 || !response.data) { throw new Error(response.message || '文档上传失败'); diff --git a/easyflow-ui-admin/pnpm-lock.yaml b/easyflow-ui-admin/pnpm-lock.yaml index 618137da..1d610abd 100644 --- a/easyflow-ui-admin/pnpm-lock.yaml +++ b/easyflow-ui-admin/pnpm-lock.yaml @@ -1441,6 +1441,9 @@ importers: '@easyflow/types': specifier: workspace:* version: link:../../types + '@easyflow/utils': + specifier: workspace:* + version: link:../../utils '@incremark/theme': specifier: 1.0.2 version: 1.0.2