From d9a80d7f8a15ff20df376f4fce8588bae41057de Mon Sep 17 00:00:00 2001 From: Blizzard Date: Fri, 31 Jul 2026 18:15:45 +0800 Subject: [PATCH] =?UTF-8?q?style(fe):=20=E8=BA=AB=E4=BB=BD=E5=8D=A1?= =?UTF-8?q?=E6=8C=89=E5=8F=82=E8=80=83=E5=9B=BE=E6=94=B6=E6=8B=BE=20?= =?UTF-8?q?=E2=80=94=20=E5=8E=BB=E6=A0=87=E9=A2=98/=E6=AD=A3=E5=8F=8D?= =?UTF-8?q?=E9=9D=A2=E6=A0=87=E7=AD=BE/=E7=96=AB=E8=8B=97=EF=BC=8C?= =?UTF-8?q?=E5=8D=A1=E9=AB=98=E6=8C=89=E5=86=85=E5=AE=B9=E8=87=AA=E9=80=82?= =?UTF-8?q?=E5=BA=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 去掉顶部「宠物身份卡」大标题和「· 正面 ·/· 背面 ·」灰字,只留两张卡 - 正面卡高度按性格/介绍有无动态算,消掉中间大块空白 - 性格标签为空时整段不画 - 照护卡去掉「疫苗情况」行 - 导出只裁到实际内容底部,卡片下面不再拖空白 Co-Authored-By: Claude Opus 5 --- pets-fe/pages/idcard/idcard.js | 100 +++++++++++++++++---------------- 1 file changed, 51 insertions(+), 49 deletions(-) diff --git a/pets-fe/pages/idcard/idcard.js b/pets-fe/pages/idcard/idcard.js index 43444bf..08a7a25 100644 --- a/pets-fe/pages/idcard/idcard.js +++ b/pets-fe/pages/idcard/idcard.js @@ -69,6 +69,7 @@ Page({ } catch (e) { dpr = 2; } + this._dpr = dpr; node.width = W * dpr; node.height = H * dpr; const ctx = node.getContext('2d'); @@ -93,18 +94,14 @@ Page({ const cardW = W - pad * 2; const fx = pad, cardW2 = cardW; - - // 顶部标题 - ctx.textAlign = 'center'; - ctx.fillStyle = '#8A5A18'; - ctx.font = '700 40px sans-serif'; - ctx.fillText('🐾 宠物身份卡 🐾', W / 2, 66); + const tags = (c.personality || '').split(',').filter(Boolean); // ══════════ 正面卡(暖黄)══════════ - ctx.fillStyle = '#C7A36A'; - ctx.font = '22px sans-serif'; - ctx.fillText('· 正面 ·', W / 2, 116); - const fY = 140, fH = 700; + // 高度按内容算,避免留一大块空白 + let fH = 420; + if (tags.length) fH += 90; + if (c.intro) fH += 90; + const fY = pad; const gf = ctx.createLinearGradient(fx, fY, fx, fY + fH); gf.addColorStop(0, '#FFF7E0'); gf.addColorStop(1, '#FFE7AE'); @@ -186,56 +183,53 @@ Page({ kvF('毛色', c.color, avY + 168); kvF('年龄', c.age, avY + 206); - // 性格标签 - let ty = avY + avD + 34; - ctx.textAlign = 'left'; - ctx.fillStyle = '#8A5A18'; - ctx.font = '600 24px sans-serif'; - ctx.fillText('🐾 性格标签', fx + 34, ty); - const tags = (c.personality || '').split(',').filter(Boolean); - const tagColors = [['#FFE7A8', '#8A5A18'], ['#D6E9FF', '#2E6DA8'], ['#FFD9DE', '#C24A63']]; - let tx = fx + 34; - ty += 42; - tags.forEach((t, i) => { - ctx.font = '23px sans-serif'; - const tw = ctx.measureText(t).width + 32; - const col = tagColors[i % tagColors.length]; - ctx.fillStyle = col[0]; - this.roundRect(ctx, tx, ty - 28, tw, 40, 20); - ctx.fill(); - ctx.fillStyle = col[1]; + // 性格标签(没有就不画,避免留空行) + let ty = fY + 320; + if (tags.length) { ctx.textAlign = 'left'; - ctx.fillText(t, tx + 16, ty); - tx += tw + 14; - }); + ctx.fillStyle = '#8A5A18'; + ctx.font = '600 24px sans-serif'; + ctx.fillText('🐾 性格标签', fx + 34, ty); + ty += 44; + const tagColors = [['#FFE7A8', '#8A5A18'], ['#D6E9FF', '#2E6DA8'], ['#FFD9DE', '#C24A63']]; + let tx = fx + 34; + tags.forEach((t, i) => { + ctx.font = '23px sans-serif'; + const tw = ctx.measureText(t).width + 32; + const col = tagColors[i % tagColors.length]; + ctx.fillStyle = col[0]; + this.roundRect(ctx, tx, ty - 28, tw, 40, 20); + ctx.fill(); + ctx.fillStyle = col[1]; + ctx.textAlign = 'left'; + ctx.fillText(t, tx + 16, ty); + tx += tw + 14; + }); + ty += 46; + } // 介绍 quote if (c.intro) { - const qy = ty + 30; ctx.fillStyle = 'rgba(255,255,255,.6)'; - this.roundRect(ctx, fx + 34, qy, cardW2 - 68, 60, 16); + this.roundRect(ctx, fx + 34, ty, cardW2 - 68, 60, 16); ctx.fill(); ctx.fillStyle = '#7A5A2E'; ctx.font = '25px sans-serif'; ctx.textAlign = 'left'; - ctx.fillText('“ ' + c.intro + ' ”', fx + 54, qy + 40); + ctx.fillText('“ ' + c.intro + ' ”', fx + 54, ty + 40); } - // 底部:身份ID + 一起生活天数 + // 底部:身份ID + 一起生活天数(贴卡片底边) ctx.textAlign = 'left'; ctx.fillStyle = '#9C7A3E'; ctx.font = '22px sans-serif'; - ctx.fillText('物ID ' + (c.id_no || ''), fx + 34, fY + fH - 60); + ctx.fillText('物ID ' + (c.id_no || ''), fx + 34, fY + fH - 56); if (c.days > 0) { - ctx.fillText('和主人一起生活的第 ' + c.days + ' 天', fx + 34, fY + fH - 26); + ctx.fillText('和主人一起生活的第 ' + c.days + ' 天', fx + 34, fY + fH - 22); } - // ══════════ 背面卡(白 + 蓝)══════════ - const bY = fY + fH + 46, bH = 620; - ctx.textAlign = 'center'; - ctx.fillStyle = '#C7A36A'; - ctx.font = '22px sans-serif'; - ctx.fillText('· 背面 ·', W / 2, bY - 16); + // ══════════ 照护卡(白 + 蓝)══════════ + const bY = fY + fH + 40, bH = 566; this.roundRect(ctx, fx, bY, cardW2, bH, 30); ctx.fillStyle = '#FFFFFF'; ctx.fill(); @@ -267,12 +261,11 @@ Page({ ctx.fillText(value || '—', rowX + 170, yy); }; let ry = bY + 140; - kvB('👤', '主人', c.owner, ry); ry += 46; - kvB('📞', '联系电话', c.phone || '未验证', ry); ry += 46; - kvB('💉', '疫苗情况', c.vaccine_state, ry); ry += 46; - kvB('📝', '备注', c.notes || '无', ry); ry += 46; - kvB('🏛', '发证机构', c.org || '肉垫计划', ry); ry += 46; - kvB('📅', '有效期', c.validity || '永久有效', ry); ry += 40; + kvB('👤', '主人', c.owner, ry); ry += 48; + kvB('📞', '联系电话', c.phone || '未验证', ry); ry += 48; + kvB('📝', '备注', c.notes || '无', ry); ry += 48; + kvB('🏛', '发证机构', c.org || '肉垫计划', ry); ry += 48; + kvB('📅', '有效期', c.validity || '永久有效', ry); ry += 42; // 走失联系框 + 小程序码 const lostY = ry + 16, lostH = bY + bH - lostY - 30; @@ -302,9 +295,18 @@ Page({ ctx.fillText('待发布', qrX + qrD / 2, qrY + qrD / 2 + 24); } + // 只导出到实际内容底部,避免卡片下面拖一条空白 + const dpr = this._dpr || 2; + const contentH = bY + bH + pad; wx.canvasToTempFilePath( { canvas: node, + x: 0, + y: 0, + width: W, + height: contentH, + destWidth: W * dpr, + destHeight: contentH * dpr, fileType: 'png', success: (r) => this.setData({ cardImg: r.tempFilePath }), fail: () => wx.showToast({ title: '生成失败,稍后再试', icon: 'none' }),