feat(fe): 宠物照片替代默认头像,身份卡移到首页门面卡

- 首页/我的/切换条:上传过照片就用照片,没有才退回 emoji
- 报告页分享海报:先异步加载头像再开画,画成圆形头像
- 一起生活的天数改成从到家日期算,没填就显示「-」并可点去补
- 身份卡入口从「我的」页移到首页门面卡右上角

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Blizzard
2026-07-30 17:08:32 +08:00
parent cbfcaada55
commit 11c4d490e6
10 changed files with 79 additions and 22 deletions
@@ -207,6 +207,18 @@ Component({
const pet = this.data.pet || {};
const p = this.data.poster || {};
// 头像是远程图,异步加载。加载完(或没有头像)再往下画,
// 否则头像会画不上。加载失败当没有头像处理
const loadAvatar = () =>
new Promise((res) => {
if (!pet.avatar_url) return res(null);
const img = node.createImage();
img.onload = () => res(img);
img.onerror = () => res(null);
img.src = pet.avatar_url;
});
loadAvatar().then((avatar) => {
const bg = ctx.createLinearGradient(0, 0, W, H);
bg.addColorStop(0, '#FFF7E8');
bg.addColorStop(1, '#FFFFFF');
@@ -220,9 +232,22 @@ Component({
ctx.font = '600 40px sans-serif';
ctx.fillText((pet.name || '毛孩子') + ' 的成长报告', W / 2, 96);
ctx.font = '96px sans-serif';
ctx.fillText(pet.emoji || '🐾', W / 2, 216);
// 上传过照片就画圆形头像,没有才退回 emoji(默认头像太丑)
const avD = 132, avX = (W - avD) / 2, avY = 132;
if (avatar) {
ctx.save();
ctx.beginPath();
ctx.arc(W / 2, avY + avD / 2, avD / 2, 0, Math.PI * 2);
ctx.closePath();
ctx.clip();
ctx.drawImage(avatar, avX, avY, avD, avD);
ctx.restore();
} else {
ctx.font = '96px sans-serif';
ctx.fillText(pet.emoji || '🐾', W / 2, 216);
}
ctx.textAlign = 'center';
ctx.fillStyle = '#8D8277';
ctx.font = '24px sans-serif';
ctx.fillText([pet.age, pet.weight, pet.stage].filter(Boolean).join(' | '), W / 2, 268);
@@ -255,7 +280,7 @@ Component({
ctx.font = '22px sans-serif';
ctx.fillText('生成自 · 肉垫计划', W / 2, 780);
// canvas 2d 是同步绘制,画完直接导出
// 头像加载完(或没有)才走到这里,此刻画布已完整
wx.canvasToTempFilePath(
{
canvas: node,
@@ -265,6 +290,7 @@ Component({
},
this,
);
}); // loadAvatar().then
});
});
},
@@ -2,7 +2,10 @@
<view wx:for="{{pets}}" wx:key="id"
class="pet-chip {{item.id === currentId ? 'active' : ''}}"
data-id="{{item.id}}" bindtap="onPick">
<view class="mini-avatar">{{item.emoji}}</view>{{item.name}}
<view class="mini-avatar">
<image wx:if="{{item.avatar_url}}" class="mini-avatar-img" src="{{item.avatar_url}}" mode="aspectFill"></image>
<block wx:else>{{item.emoji}}</block>
</view>{{item.name}}
</view>
<view wx:if="{{showAdd}}" class="pet-chip" bindtap="onAdd">
<view class="mini-avatar"><pt-icon name="plus" size="{{30}}"></pt-icon></view>添加
@@ -3,3 +3,5 @@
}
.pet-switch .pet-chip{margin-right:20rpx}
.pet-switch .pet-chip:last-child{margin-right:0}
.mini-avatar{overflow:hidden}
.mini-avatar-img{width:100%;height:100%;display:block}