feat(fe+be): 身份卡加公章、修性别符号、电话显示全、照护卡标题两行
- 修正性别 ♂/♀:用名字字号量宽度再定位,不再怼到名字上(之前用小字号量偏了) - 正反两张卡右上角各盖一枚「肉垫计划 · 官方认证」红色公章(双圈+五角星,微旋转半透明) - 照护卡标题改成两行「X星地球移民 / 居民身份卡」(按猫狗取 喵/汪/宠) - 正面「物ID」改为「ID」 - 后端 IDCard.Phone 返回完整手机号,不再脱敏 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -135,16 +135,20 @@ Page({
|
||||
ctx.lineWidth = 8;
|
||||
ctx.stroke();
|
||||
|
||||
// 名字 + 性别(头像右侧)
|
||||
// 名字 + 性别(头像右侧)。性别符号必须用「名字的字号」量宽度再定位,
|
||||
// 否则换成小字号后 measureText 量出的宽度偏小,符号会怼到名字上
|
||||
const nx = avX + avD + 28;
|
||||
const nm = c.name || '毛孩子';
|
||||
ctx.textAlign = 'left';
|
||||
ctx.fillStyle = '#2D2925';
|
||||
ctx.font = '700 52px sans-serif';
|
||||
ctx.fillText(c.name || '毛孩子', nx, avY + 44);
|
||||
ctx.fillText(nm, nx, avY + 46);
|
||||
const nmW = ctx.measureText(nm).width;
|
||||
if (c.gender) {
|
||||
ctx.fillStyle = c.gender === '女孩' ? '#E86A9B' : '#5B9BE8';
|
||||
ctx.font = '30px sans-serif';
|
||||
ctx.fillText(c.gender === '女孩' ? '♀' : '♂', nx + ctx.measureText(c.name || '毛孩子').width + 12, avY + 44);
|
||||
const isF = c.gender === '女孩';
|
||||
ctx.fillStyle = isF ? '#E86A9B' : '#5B9BE8';
|
||||
ctx.font = '600 34px sans-serif';
|
||||
ctx.fillText(isF ? '♀' : '♂', nx + nmW + 16, avY + 44);
|
||||
}
|
||||
// 头像右的资料行
|
||||
const kvF = (label, value, yy) => {
|
||||
@@ -201,19 +205,23 @@ Page({
|
||||
ctx.textAlign = 'left';
|
||||
ctx.fillStyle = '#9C7A3E';
|
||||
ctx.font = '22px sans-serif';
|
||||
ctx.fillText('物ID ' + (c.id_no || ''), fx + 34, fY + fH - 56);
|
||||
ctx.fillText('ID ' + (c.id_no || ''), fx + 34, fY + fH - 56);
|
||||
if (c.days > 0) {
|
||||
ctx.fillText('和主人一起生活的第 ' + c.days + ' 天', fx + 34, fY + fH - 22);
|
||||
}
|
||||
|
||||
// 正面印章(右上角)
|
||||
this.drawStamp(ctx, fx + cardW2 - 78, fY + 82);
|
||||
|
||||
// ══════════ 照护卡(白 + 蓝)══════════
|
||||
const bY = fY + fH + 40, bH = 566;
|
||||
this.roundRect(ctx, fx, bY, cardW2, bH, 30);
|
||||
ctx.fillStyle = '#FFFFFF';
|
||||
ctx.fill();
|
||||
|
||||
// 蓝色标题条
|
||||
const hb = 64;
|
||||
// 蓝色标题条(两行:「X星地球移民 / 居民身份卡」)
|
||||
const star = c.species === '狗狗' ? '汪' : c.species === '猫猫' ? '喵' : '宠';
|
||||
const hb = 92;
|
||||
const gb = ctx.createLinearGradient(fx, bY, fx + cardW2, bY);
|
||||
gb.addColorStop(0, '#5AA0E8');
|
||||
gb.addColorStop(1, '#7FB6F0');
|
||||
@@ -222,8 +230,10 @@ Page({
|
||||
ctx.fill();
|
||||
ctx.textAlign = 'center';
|
||||
ctx.fillStyle = '#fff';
|
||||
ctx.font = '700 28px sans-serif';
|
||||
ctx.fillText('照护信息', W / 2, bY + 24 + 42);
|
||||
ctx.font = '700 30px sans-serif';
|
||||
ctx.fillText(star + '星地球移民', W / 2, bY + 24 + 40);
|
||||
ctx.font = '700 26px sans-serif';
|
||||
ctx.fillText('居民身份卡', W / 2, bY + 24 + 76);
|
||||
|
||||
// 照护行(标签 + 值,不放图标)
|
||||
const rowX = fx + 44;
|
||||
@@ -267,6 +277,9 @@ Page({
|
||||
ctx.fillText('待发布', qrX + qrD / 2, qrY + qrD / 2 + 24);
|
||||
}
|
||||
|
||||
// 背面印章(右上角,压在蓝条右侧)
|
||||
this.drawStamp(ctx, fx + cardW2 - 78, bY + 70);
|
||||
|
||||
// 只导出到实际内容底部,避免卡片下面拖一条空白
|
||||
const dpr = this._dpr || 2;
|
||||
const contentH = bY + bH + pad;
|
||||
@@ -297,6 +310,49 @@ Page({
|
||||
ctx.closePath();
|
||||
},
|
||||
|
||||
// 五角星路径(调用方负责 fill/stroke)
|
||||
star(ctx, cx, cy, rO, rI, n) {
|
||||
ctx.beginPath();
|
||||
for (let i = 0; i < n * 2; i++) {
|
||||
const r = i % 2 === 0 ? rO : rI;
|
||||
const a = -Math.PI / 2 + (i * Math.PI) / n;
|
||||
const x = cx + r * Math.cos(a), y = cy + r * Math.sin(a);
|
||||
if (i === 0) ctx.moveTo(x, y);
|
||||
else ctx.lineTo(x, y);
|
||||
}
|
||||
ctx.closePath();
|
||||
},
|
||||
|
||||
// 红色公章:双圈 + 顶部五角星 + 「肉垫计划 / 官方认证」,略微旋转、半透明
|
||||
drawStamp(ctx, cx, cy) {
|
||||
ctx.save();
|
||||
ctx.translate(cx, cy);
|
||||
ctx.rotate(-0.16);
|
||||
ctx.globalAlpha = 0.68;
|
||||
ctx.strokeStyle = '#CE4534';
|
||||
ctx.fillStyle = '#CE4534';
|
||||
ctx.lineWidth = 4;
|
||||
ctx.beginPath();
|
||||
ctx.arc(0, 0, 52, 0, Math.PI * 2);
|
||||
ctx.stroke();
|
||||
ctx.lineWidth = 1.5;
|
||||
ctx.beginPath();
|
||||
ctx.arc(0, 0, 43, 0, Math.PI * 2);
|
||||
ctx.stroke();
|
||||
this.star(ctx, 0, -23, 11, 4.6, 5);
|
||||
ctx.fill();
|
||||
ctx.textAlign = 'center';
|
||||
ctx.textBaseline = 'middle';
|
||||
ctx.font = '700 25px sans-serif';
|
||||
ctx.fillText('肉垫计划', 0, 10);
|
||||
ctx.font = '13px sans-serif';
|
||||
ctx.fillText('官方认证', 0, 32);
|
||||
ctx.restore();
|
||||
ctx.globalAlpha = 1;
|
||||
ctx.textAlign = 'left';
|
||||
ctx.textBaseline = 'alphabetic';
|
||||
},
|
||||
|
||||
// 微信取手机号:新版 getPhoneNumber 返回动态 code,后端换成真实手机号存库,
|
||||
// 拿回后重新取卡(此时电话就有了)并重画
|
||||
onGetPhone(e) {
|
||||
|
||||
Reference in New Issue
Block a user