From 35529e3738ce3c460211b79f1f4133b94f305740 Mon Sep 17 00:00:00 2001 From: Poker Design Developer Date: Mon, 1 Jun 2026 22:20:57 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E5=A4=A7=E5=B0=8F=E7=8E=8B=E8=A7=92?= =?UTF-8?q?=E6=A0=87=E4=B8=8D=E6=98=BE=E7=A4=BA=20&=20=E5=AF=BC=E5=87=BA?= =?UTF-8?q?=E6=95=B4=E5=89=AF=E7=89=8C=E5=A4=B1=E6=95=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/apps/exports/utils.py | 12 ++++++------ frontend/src/utils/cardRenderer.js | 11 ++++++++++- frontend/src/views/Editor.vue | 9 ++++++--- 3 files changed, 22 insertions(+), 10 deletions(-) diff --git a/backend/apps/exports/utils.py b/backend/apps/exports/utils.py index 471a534..344be6d 100644 --- a/backend/apps/exports/utils.py +++ b/backend/apps/exports/utils.py @@ -363,14 +363,14 @@ def draw_back(canvas, design, asset): body_w = w - 2 * body_pad_x body_h = h - body_pad_y_top - body_pad_y_bot - image_dx = float(design.get('image_dx', 0)) - image_dy = float(design.get('image_dy', 0)) - image_scale = float(design.get('image_scale', 1)) - offset_x = int(body_w * image_dx) - offset_y = int(body_h * image_dy) - if asset: try: + image_dx = float(design.get('image_dx', 0)) + image_dy = float(design.get('image_dy', 0)) + image_scale = float(design.get('image_scale', 1)) + offset_x = int(body_w * image_dx) + offset_y = int(body_h * image_dy) + img = asset.copy() if image_scale != 1: sw = max(1, int(img.width * image_scale)) diff --git a/frontend/src/utils/cardRenderer.js b/frontend/src/utils/cardRenderer.js index 756fa9c..38453bb 100644 --- a/frontend/src/utils/cardRenderer.js +++ b/frontend/src/utils/cardRenderer.js @@ -316,16 +316,25 @@ async function drawJokerBody(ctx, w, h, which, design, project) { const labelSize = Math.max(20, Math.round(w * 0.06)) const textSize = Math.max(16, Math.round(w * 0.045)) const pad = Math.max(10, w * 0.04) + + // 左上角标 ctx.font = `bold ${labelSize}px ${design.font_family || 'Times New Roman'}, serif` ctx.fillText('JOKER', pad, pad) ctx.fillText(label, pad, pad + textSize + 4) - // 右下:旋转 180° 平移 + + // 右下角标 + ctx.save() ctx.translate(w - pad, h - pad) ctx.rotate(Math.PI) + ctx.fillStyle = '#FFFFFF' + ctx.textAlign = 'left' + ctx.textBaseline = 'top' ctx.font = `bold ${labelSize}px ${design.font_family || 'Times New Roman'}, serif` ctx.fillText('JOKER', 0, 0) ctx.fillText(label, 0, textSize + 4) ctx.restore() + + ctx.restore() } async function drawBackSide(ctx, w, h, design, project) { diff --git a/frontend/src/views/Editor.vue b/frontend/src/views/Editor.vue index 8719347..38ad480 100644 --- a/frontend/src/views/Editor.vue +++ b/frontend/src/views/Editor.vue @@ -241,10 +241,13 @@ async function onNameBlur() { async function exportAll() { try { const r = await axios.post(`/api/projects/${project.value.id}/export/`, - { resolution: 'standard', cards: 'all' }, - { responseType: 'blob' } + { resolution: 'standard', cards: 'all' } ) - download(r.data, `${project.value.name || 'cards'}.zip`) + const { download_url, failed } = r.data + if (failed && failed.length > 0) { + alert('部分牌导出失败: ' + failed.map(f => f.card).join(', ')) + } + window.open(download_url, '_blank') } catch (e) { alert('导出失败: ' + e.message) }