From 18e92b1cc68ad576ef015af4aec68ba9a4c0402e Mon Sep 17 00:00:00 2001 From: chiyi Date: Sat, 4 Jul 2026 23:47:03 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E5=A4=8D=E5=88=B6=E5=8A=9F?= =?UTF-8?q?=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/views/ImagesView.vue | 30 ++++++++++++++++++++++++++ frontend/src/views/PlaygroundView.vue | 30 ++++++++++++++++++++++++++ frontend/src/views/UserLogsView.vue | 31 +++++++++++++++++++++++++++ 3 files changed, 91 insertions(+) diff --git a/frontend/src/views/ImagesView.vue b/frontend/src/views/ImagesView.vue index ca371f5..046d70a 100644 --- a/frontend/src/views/ImagesView.vue +++ b/frontend/src/views/ImagesView.vue @@ -47,6 +47,32 @@ async function copyLink(name) { flash(await copyText(absUrl(name)) ? '链接已复制' : '复制失败') } +async function copyImage(url) { + try { + const blob = await (await fetch(url)).blob() + const pngBlob = blob.type === 'image/png' + ? blob + : await new Promise((resolve, reject) => { + createImageBitmap(blob).then(async (bitmap) => { + const canvas = document.createElement('canvas') + canvas.width = bitmap.width + canvas.height = bitmap.height + const ctx = canvas.getContext('2d') + if (!ctx) { reject(new Error('no canvas ctx')); return } + ctx.drawImage(bitmap, 0, 0) + canvas.toBlob((out) => { + if (out) resolve(out) + else reject(new Error('png convert failed')) + }, 'image/png') + }).catch(reject) + }) + await navigator.clipboard.write([new ClipboardItem({ 'image/png': pngBlob })]) + flash('图片已复制') + } catch { + flash('复制失败') + } +} + async function copyPrompt(f) { if (!f.prompt) return flash(await copyText(f.prompt) ? '指令已复制' : '复制失败') @@ -168,6 +194,10 @@ onUnmounted(() => window.removeEventListener('keydown', onKey))
+ diff --git a/frontend/src/views/PlaygroundView.vue b/frontend/src/views/PlaygroundView.vue index e85c1d5..328fc5b 100644 --- a/frontend/src/views/PlaygroundView.vue +++ b/frontend/src/views/PlaygroundView.vue @@ -272,6 +272,32 @@ async function copyPrompt(item) { flash(await copyText(text) ? '指令已复制' : '复制失败') } +async function copyImage(url) { + try { + const blob = await (await fetch(url)).blob() + const pngBlob = blob.type === 'image/png' + ? blob + : await new Promise((resolve, reject) => { + createImageBitmap(blob).then((bitmap) => { + const canvas = document.createElement('canvas') + canvas.width = bitmap.width + canvas.height = bitmap.height + const ctx = canvas.getContext('2d') + if (!ctx) { reject(new Error('no canvas ctx')); return } + ctx.drawImage(bitmap, 0, 0) + canvas.toBlob((out) => { + if (out) resolve(out) + else reject(new Error('png convert failed')) + }, 'image/png') + }).catch(reject) + }) + await navigator.clipboard.write([new ClipboardItem({ 'image/png': pngBlob })]) + flash('图片已复制') + } catch { + flash('复制失败') + } +} + // ---- generate (concurrent — no lock) ---- // 生图 can request 1–4 images at once: each is an independent task/charge. const count = ref(1) @@ -686,6 +712,10 @@ onUnmounted(() => {