diff --git a/packages/ui/src/components/image-mode/ImageImage2ImageWorkspace.vue b/packages/ui/src/components/image-mode/ImageImage2ImageWorkspace.vue index 7b6e7bd8..4b62b51c 100644 --- a/packages/ui/src/components/image-mode/ImageImage2ImageWorkspace.vue +++ b/packages/ui/src/components/image-mode/ImageImage2ImageWorkspace.vue @@ -1436,6 +1436,7 @@ const queueSessionSave = () => { .catch((e) => { console.error('[ImageImage2ImageWorkspace] Failed to persist image session:', e) }) + return sessionSaveChain } const getImageDimensionsFromSource = (src: string): Promise<{ width: number; height: number }> => @@ -1719,6 +1720,7 @@ const handleUploadChange = async (data: ImageUploadChangePayload) => { session.updateInputImage(null, '') uploadStatus.value = 'idle' uploadProgress.value = 0 + await queueSessionSave() return } @@ -1741,10 +1743,11 @@ const handleUploadChange = async (data: ImageUploadChangePayload) => { const reader = new FileReader() - reader.onload = () => { + reader.onload = async () => { const dataUrl = reader.result as string const base64 = dataUrl.split(',')[1] session.updateInputImage(base64, file.type) + await queueSessionSave() uploadStatus.value = 'success' uploadProgress.value = 100 toast.success(t('imageWorkspace.upload.uploadSuccess')) @@ -1765,11 +1768,11 @@ const handleUploadChange = async (data: ImageUploadChangePayload) => { } // 弹窗中的上传处理 -const handleModalUploadChange = (data: ImageUploadChangePayload) => { +const handleModalUploadChange = async (data: ImageUploadChangePayload) => { // 复用原有的上传逻辑 - handleUploadChange(data); + await handleUploadChange(data); // 上传成功后关闭弹窗 - if (data?.file && data.file.status === "finished") { + if (uploadStatus.value === 'success') { setTimeout(() => { showUploadModal.value = false; }, 1000); diff --git a/tests/e2e/session-persistence/image-image2image-persistence.spec.ts b/tests/e2e/session-persistence/image-image2image-persistence.spec.ts new file mode 100644 index 00000000..d89b495e --- /dev/null +++ b/tests/e2e/session-persistence/image-image2image-persistence.spec.ts @@ -0,0 +1,51 @@ +import { test, expect } from '../fixtures' +import * as path from 'path' + +test.describe('Image Image2Image - Session Persistence', () => { + const gotoMode = async (page: any, route: string) => { + await page.goto('/') + await page.waitForLoadState('networkidle') + await page.goto(route) + await page.waitForLoadState('networkidle') + await page.waitForTimeout(1500) + } + + const getInputImageState = async (page: any) => + page.evaluate(() => { + const app = (document.querySelector('#app') as any)?.__vue_app__ + const session = app?.config?.globalProperties?.$pinia?.state?.value?.imageImage2ImageSession + + return { + inputImageB64Len: session?.inputImageB64 ? session.inputImageB64.length : 0, + inputImageId: session?.inputImageId || null, + inputImageMime: session?.inputImageMime || '', + } + }) + + test('上传输入图后刷新页面,预览和 session 都应该保留', async ({ page }) => { + const seedPath = path.join(process.cwd(), 'tests/e2e/fixtures/images/text2image-output.png') + + await gotoMode(page, '/#/image/image2image') + + await page.getByTestId('image-image2image-open-upload').click() + const upload = page.getByTestId('image-image2image-upload') + await upload.locator('input[type="file"]').setInputFiles(seedPath) + + await expect(page.getByTestId('image-image2image-input-preview')).toBeVisible({ timeout: 30000 }) + + const beforeReload = await getInputImageState(page) + expect(beforeReload.inputImageB64Len).toBeGreaterThan(0) + expect(beforeReload.inputImageMime).toBe('image/png') + + await page.reload() + await page.waitForLoadState('networkidle') + await page.waitForTimeout(1500) + + await expect(page.getByTestId('image-image2image-input-preview')).toBeVisible({ timeout: 30000 }) + + const afterReload = await getInputImageState(page) + expect(afterReload.inputImageB64Len).toBeGreaterThan(0) + expect(afterReload.inputImageId).toBeTruthy() + expect(afterReload.inputImageMime).toBe('image/png') + }) +})