feat(fe): 宠物照片替代默认头像,身份卡移到首页门面卡
- 首页/我的/切换条:上传过照片就用照片,没有才退回 emoji - 报告页分享海报:先异步加载头像再开画,画成圆形头像 - 一起生活的天数改成从到家日期算,没填就显示「-」并可点去补 - 身份卡入口从「我的」页移到首页门面卡右上角 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -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}
|
||||
|
||||
@@ -199,6 +199,16 @@ Page({
|
||||
},
|
||||
// 去建档页改阶段。改完回来 onShow 会重新拉一次漂移状态,提示自然消失。
|
||||
// 不在首页直接改:改阶段之后要不要套新方案是同一件事,放在一起做才连贯
|
||||
// 点「一起生活的天数」空态,去建档页补到家日期
|
||||
onDaysTap() {
|
||||
const id = this.data.pet && this.data.pet.id;
|
||||
if (!this.data.daysTogether && id) wx.navigateTo({ url: '/pages/petform/petform?id=' + id });
|
||||
},
|
||||
// 身份卡:门面卡右上角进,用当前宠物
|
||||
goIDCard() {
|
||||
const id = this.data.pet && this.data.pet.id;
|
||||
if (id) wx.navigateTo({ url: '/pages/idcard/idcard?id=' + id });
|
||||
},
|
||||
goStageUpdate() {
|
||||
const id = this.data.pet && this.data.pet.id;
|
||||
if (id) wx.navigateTo({ url: '/pages/petform/petform?id=' + id });
|
||||
|
||||
@@ -21,9 +21,15 @@
|
||||
<text wx:if="{{zodiac}}">{{zodiac}}</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="hero-arrow"><pt-icon name="next" size="{{28}}"></pt-icon></view>
|
||||
<view wx:if="{{pet.id}}" class="hero-idcard" catchtap="goIDCard">
|
||||
<pt-icon name="user" size="{{30}}"></pt-icon>身份卡
|
||||
</view>
|
||||
</view>
|
||||
<!-- 一起生活的天数从到家日算。没填到家日就显示「-」,点一下去补 -->
|
||||
<view wx:if="{{pet.id}}" class="hero-days {{daysTogether ? '' : 'hero-days-empty'}}" catchtap="onDaysTap">
|
||||
<block wx:if="{{daysTogether}}">我们一起生活的第 <text class="hd-n">{{daysTogether}}</text> 天</block>
|
||||
<block wx:else>还没填到家日期,一起生活的天数显示 <text class="hd-n">-</text></block>
|
||||
</view>
|
||||
<view wx:if="{{daysTogether}}" class="hero-days">我们一起生活的第 <text class="hd-n">{{daysTogether}}</text> 天</view>
|
||||
</view>
|
||||
|
||||
<!-- 阶段漂移。系统只负责发现,换不换由用户点 —— 偷偷换会让他莫名发现
|
||||
|
||||
@@ -87,3 +87,16 @@
|
||||
.drift-focus{font-size:var(--fs-sm);color:var(--primary-ink);line-height:1.6;margin-top:6rpx}
|
||||
.drift-size{font-size:var(--fs-cap);color:var(--primary-dark);opacity:.8;margin-top:6rpx}
|
||||
.drift-cta{margin-top:var(--sp-4)}
|
||||
|
||||
/* 没填到家日期时的天数空态:压成灰、可点去补 */
|
||||
.hero-days-empty{background:var(--surface-2);color:var(--muted)}
|
||||
.hero-days-empty .hd-n{color:var(--muted)}
|
||||
|
||||
/* 门面卡右上角的身份卡入口。原来那里是个 next 箭头(点整卡进编辑),
|
||||
身份卡做成小胶囊,和整卡点击分开 */
|
||||
.hero-idcard{
|
||||
flex:none;align-self:flex-start;display:flex;align-items:center;gap:4rpx;
|
||||
padding:8rpx var(--sp-3);border-radius:var(--r-full);
|
||||
background:var(--primary-soft);color:var(--primary-dark);
|
||||
font-size:var(--fs-cap);font-weight:var(--fw-b);
|
||||
}
|
||||
|
||||
@@ -56,12 +56,6 @@ Page({
|
||||
goDecorate() {
|
||||
wx.navigateTo({ url: '/pages/decorate/decorate' });
|
||||
},
|
||||
// 身份卡:当前这只的
|
||||
goIDCard() {
|
||||
const id = store.currentPetId();
|
||||
if (!id) return wx.showToast({ title: '先选一只毛孩子', icon: 'none' });
|
||||
wx.navigateTo({ url: '/pages/idcard/idcard?id=' + id });
|
||||
},
|
||||
goPlan() {
|
||||
wx.navigateTo({ url: '/pages/plan/plan' });
|
||||
},
|
||||
|
||||
@@ -17,7 +17,10 @@
|
||||
<view class="link" bindtap="onAddPet">+ 添加</view>
|
||||
</view>
|
||||
<view wx:for="{{pets}}" wx:key="id" class="pet-row" data-id="{{item.id}}" bindtap="onPickPet">
|
||||
<view class="pet-emoji">{{item.emoji}}</view>
|
||||
<view class="pet-emoji">
|
||||
<image wx:if="{{item.avatar_url}}" class="pet-emoji-img" src="{{item.avatar_url}}" mode="aspectFill"></image>
|
||||
<block wx:else>{{item.emoji}}</block>
|
||||
</view>
|
||||
<view class="pet-info">
|
||||
<view class="tt-b">{{item.name}}</view>
|
||||
<view class="tt-p">{{item.age}}|{{item.weight}}|{{item.stage}}</view>
|
||||
@@ -33,10 +36,6 @@
|
||||
<view class="pr-ic"><pt-icon name="user" size="{{34}}"></pt-icon></view>
|
||||
<text class="pr-label">宠物档案</text><view class="pr-arrow"><pt-icon name="next" size="{{28}}"></pt-icon></view>
|
||||
</view>
|
||||
<view class="profile-row" bindtap="goIDCard">
|
||||
<view class="pr-ic"><pt-icon name="user" size="{{34}}"></pt-icon></view>
|
||||
<text class="pr-label">身份卡</text><text class="pr-val">可保存、分享</text><view class="pr-arrow"><pt-icon name="next" size="{{28}}"></pt-icon></view>
|
||||
</view>
|
||||
<view class="profile-row" bindtap="goPlan">
|
||||
<view class="pr-ic"><pt-icon name="plan" size="{{34}}"></pt-icon></view>
|
||||
<text class="pr-label">养护计划</text><view class="pr-arrow"><pt-icon name="next" size="{{28}}"></pt-icon></view>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
|
||||
.pet-row{display:flex;align-items:center;gap:var(--sp-3);padding:var(--sp-3) 0;border-bottom:1rpx solid var(--line)}
|
||||
.pet-row:last-child{border-bottom:0}
|
||||
.pet-emoji{
|
||||
.pet-emoji{overflow:hidden;
|
||||
width:76rpx;height:76rpx;border-radius:var(--r-sm);flex:none;
|
||||
display:flex;align-items:center;justify-content:center;
|
||||
background:var(--primary-soft);font-size:40rpx;
|
||||
@@ -9,3 +9,4 @@
|
||||
.pet-info{flex:1;min-width:0}
|
||||
|
||||
.me-preview{margin-bottom:var(--sp-5)}
|
||||
.pet-emoji-img{width:100%;height:100%;display:block}
|
||||
|
||||
@@ -23,13 +23,16 @@ function zodiac(birthday) {
|
||||
|
||||
// 一起生活了多少天。优先用到家日期——「我们一起生活的第 N 天」说的是
|
||||
// 它到你家之后的日子,不是它出生之后的日子。没填到家日就退回建档日。
|
||||
// 一起生活了多少天,只从「到家日期」算 —— 没填到家日就返回 null(首页显示「-」)。
|
||||
// 原来会退回建档日兜底,但那是「在这个 App 上建档的日子」,不是「它到你家的日子」,
|
||||
// 领养多年后才装 App 的会算出个很小的数,反而误导
|
||||
function daysTogether(pet) {
|
||||
const from = (pet && (pet.arrived_at || pet.created_at)) || '';
|
||||
if (!from) return 0;
|
||||
const from = (pet && pet.arrived_at) || '';
|
||||
if (!from) return null;
|
||||
const d = new Date(String(from).slice(0, 10) + 'T00:00:00');
|
||||
if (isNaN(d.getTime())) return 0;
|
||||
if (isNaN(d.getTime())) return null;
|
||||
const days = Math.floor((Date.now() - d.getTime()) / 86400000) + 1;
|
||||
return days > 0 ? days : 0;
|
||||
return days > 0 ? days : null;
|
||||
}
|
||||
|
||||
// 性别徽章。后端存的是「男孩 / 女孩 / 不确定」
|
||||
|
||||
Reference in New Issue
Block a user