Add one-way task completion and exportable pet identity cards
This commit is contained in:
@@ -0,0 +1,42 @@
|
||||
const { profile, renderCard, saveToAlbum } = require("../../utils/pet-card");
|
||||
const { toast } = require("../../utils/api");
|
||||
Component({
|
||||
properties: { pet: { type: Object, value: {} } },
|
||||
data: { card: {}, saving: false },
|
||||
observers: {
|
||||
pet(value) {
|
||||
this.setData({ card: profile(value || {}) });
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
edit() {
|
||||
this.triggerEvent("edit", { id: this.data.pet.id });
|
||||
},
|
||||
async generate() {
|
||||
const canvas = await new Promise((resolve, reject) =>
|
||||
this.createSelectorQuery()
|
||||
.select("#card-canvas")
|
||||
.fields({ node: true, size: true })
|
||||
.exec((result) =>
|
||||
result[0] && result[0].node
|
||||
? resolve(result[0].node)
|
||||
: reject(new Error("卡片还未准备好,请重试")),
|
||||
),
|
||||
);
|
||||
return renderCard(canvas, this.data.pet);
|
||||
},
|
||||
async save() {
|
||||
if (this.data.saving) return;
|
||||
this.setData({ saving: true });
|
||||
try {
|
||||
const path = await this.generate();
|
||||
if (await saveToAlbum(path))
|
||||
wx.showToast({ title: "身份卡已保存到相册", icon: "success" });
|
||||
} catch (error) {
|
||||
toast(error);
|
||||
} finally {
|
||||
this.setData({ saving: false });
|
||||
}
|
||||
},
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"component": true,
|
||||
"usingComponents": { "app-icon": "/components/app-icon/index" }
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
<view class="identity">
|
||||
<view class="id-top"><view class="brand"><image src="/assets/logo-corgi-v2.png" /><view><text class="brand-name">肉垫计划</text><text class="brand-en">PAWPRINT ID</text></view></view><text class="id-title">毛孩身份卡</text></view>
|
||||
<view class="id-body" bindtap="edit" aria-role="button" aria-label="编辑宠物档案">
|
||||
<view class="portrait"><image wx:if="{{card.avatar_url}}" src="{{card.avatar_url}}" mode="aspectFill" /><app-icon wx:else size="80" color="#d18b67" /></view>
|
||||
<view class="details"><text class="pet-name">{{card.name}}</text><text class="breed">{{card.breed||'品种未填写'}} · {{card.genderLabel}}</text><view class="facts"><view><text class="label">生日</text><text class="value">{{card.birthday}}</text></view><view><text class="label">体重</text><text class="value">{{card.weightLabel}}</text></view></view><view class="coat"><text class="label">毛色</text><text class="value">{{card.coat||'未填写'}}</text></view></view>
|
||||
</view>
|
||||
<view class="id-bottom"><view><text class="label">陪伴编号</text><text class="number">{{card.cardNumber}}</text></view><text class="motto">把陪伴,认真记下来</text></view>
|
||||
</view>
|
||||
<view class="card-actions"><button bindtap="edit">编辑档案</button><button class="save" bindtap="save" loading="{{saving}}" disabled="{{saving}}">{{saving?'正在生成…':'保存身份卡'}}</button></view>
|
||||
<canvas type="2d" id="card-canvas" class="export-canvas" />
|
||||
@@ -0,0 +1,164 @@
|
||||
:host {
|
||||
display: block;
|
||||
margin-bottom: 30rpx;
|
||||
}
|
||||
.identity {
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
border-radius: 28rpx;
|
||||
border: 1rpx solid #ead8ca;
|
||||
padding: 25rpx;
|
||||
background: linear-gradient(125deg, #fff3e5, #f0e9f8);
|
||||
box-shadow: 0 14rpx 35rpx #79543a0b;
|
||||
color: #604a40;
|
||||
}
|
||||
.id-top {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding-bottom: 20rpx;
|
||||
border-bottom: 1rpx solid #dfcdbf;
|
||||
}
|
||||
.brand {
|
||||
display: flex;
|
||||
gap: 9rpx;
|
||||
align-items: center;
|
||||
}
|
||||
.brand image {
|
||||
width: 44rpx;
|
||||
height: 44rpx;
|
||||
}
|
||||
.brand-name,
|
||||
.brand-en {
|
||||
display: block;
|
||||
}
|
||||
.brand-name {
|
||||
font-size: 18rpx;
|
||||
font-weight: 600;
|
||||
color: #795a4b;
|
||||
}
|
||||
.brand-en {
|
||||
font-size: 11rpx;
|
||||
letter-spacing: 2rpx;
|
||||
color: #a48d7e;
|
||||
}
|
||||
.id-title {
|
||||
font-size: 23rpx;
|
||||
letter-spacing: 3rpx;
|
||||
font-weight: 600;
|
||||
}
|
||||
.id-body {
|
||||
display: flex;
|
||||
gap: 24rpx;
|
||||
padding: 24rpx 0;
|
||||
}
|
||||
.portrait {
|
||||
width: 166rpx;
|
||||
height: 180rpx;
|
||||
flex: none;
|
||||
border: 6rpx solid #fffaf4;
|
||||
border-radius: 18rpx;
|
||||
overflow: hidden;
|
||||
background: #fffaf4;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
.portrait image {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
.details {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
}
|
||||
.pet-name {
|
||||
display: block;
|
||||
font-size: 34rpx;
|
||||
font-weight: 600;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.breed {
|
||||
display: block;
|
||||
font-size: 21rpx;
|
||||
color: #886c5f;
|
||||
margin: 2rpx 0 12rpx;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.facts {
|
||||
display: flex;
|
||||
gap: 22rpx;
|
||||
}
|
||||
.facts > view {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
}
|
||||
.label {
|
||||
display: block;
|
||||
font-size: 17rpx;
|
||||
color: #a48d7e;
|
||||
}
|
||||
.value {
|
||||
display: block;
|
||||
font-size: 21rpx;
|
||||
font-weight: 500;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.coat {
|
||||
margin-top: 9rpx;
|
||||
}
|
||||
.id-bottom {
|
||||
border-top: 1rpx solid #dfcdbf;
|
||||
padding-top: 15rpx;
|
||||
display: flex;
|
||||
align-items: flex-end;
|
||||
justify-content: space-between;
|
||||
gap: 10rpx;
|
||||
}
|
||||
.number {
|
||||
display: block;
|
||||
font-size: 18rpx;
|
||||
letter-spacing: 1rpx;
|
||||
color: #795a4b;
|
||||
}
|
||||
.motto {
|
||||
font-size: 16rpx;
|
||||
color: #886c5f;
|
||||
max-width: 200rpx;
|
||||
text-align: right;
|
||||
}
|
||||
.card-actions {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
gap: 16rpx;
|
||||
margin-top: 12rpx;
|
||||
}
|
||||
.card-actions button {
|
||||
margin: 0;
|
||||
padding: 9rpx 20rpx;
|
||||
border: 1rpx solid #ead8ca;
|
||||
border-radius: 99rpx;
|
||||
background: #fffaf4;
|
||||
color: #886c5f;
|
||||
font-size: 22rpx;
|
||||
line-height: 1.5;
|
||||
}
|
||||
.card-actions .save {
|
||||
background: #fff0e2;
|
||||
color: #b95738;
|
||||
border-color: #f1d6c4;
|
||||
}
|
||||
.export-canvas {
|
||||
position: fixed;
|
||||
left: -2000px;
|
||||
top: 0;
|
||||
width: 600px;
|
||||
height: 380px;
|
||||
pointer-events: none;
|
||||
}
|
||||
Reference in New Issue
Block a user