init: 毛孩子计划 小程序 + Go 后端 + 内嵌后台
- pets-fe: 微信原生小程序(首页/计划/记录/报告/社区/引导), 服务端驱动、无假数据;弹层改用 scroll-view,打开时隐藏自定义 tabBar - pets-be: Gin + GORM(MySQL, sundynix_ 前缀) + MinIO,统一响应/分页, 微信 code2session 登录,provider-neutral AI(DeepSeek),go:embed React 后台 - 修复:分段选择类型不匹配(字符串 vs 数字)导致选不中 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,55 @@
|
||||
const store = require('../../utils/store.js');
|
||||
const api = require('../../utils/api.js');
|
||||
|
||||
function completion(pet) {
|
||||
if (!pet) return 0;
|
||||
const fields = ['name', 'emoji', 'type', 'gender', 'birthday', 'weight', 'stage', 'age', 'color', 'breed'];
|
||||
const filled = fields.filter((f) => pet[f]).length;
|
||||
return Math.round((filled / fields.length) * 100);
|
||||
}
|
||||
|
||||
Page({
|
||||
data: {
|
||||
pet: {},
|
||||
user: {},
|
||||
summary: { pets: 0, records: 0, reminders: 0, pro_status: 'none' },
|
||||
profilePct: 0,
|
||||
sheetShow: false,
|
||||
sheetType: '',
|
||||
},
|
||||
onLoad() {
|
||||
this._unsub = store.subscribe((pet) => this.setData({ pet, profilePct: completion(pet) }));
|
||||
},
|
||||
onUnload() {
|
||||
if (this._unsub) this._unsub();
|
||||
},
|
||||
onShow() {
|
||||
store
|
||||
.ready()
|
||||
.then(() => {
|
||||
const pet = store.getPet();
|
||||
this.setData({ pet, user: store.getUser() || {}, profilePct: completion(pet) });
|
||||
this.loadSummary();
|
||||
})
|
||||
.catch((e) => wx.showToast({ title: e.message || '加载失败', icon: 'none' }));
|
||||
},
|
||||
loadSummary() {
|
||||
api.userSummary().then((summary) => this.setData({ summary })).catch(() => {});
|
||||
},
|
||||
openSheet(e) {
|
||||
this.setData({ sheetType: e.currentTarget.dataset.type, sheetShow: true });
|
||||
},
|
||||
onAddPet() {
|
||||
this.setData({ sheetType: 'addPet', sheetShow: true });
|
||||
},
|
||||
onEditPet() {
|
||||
this.setData({ sheetType: 'editPet', sheetShow: true });
|
||||
},
|
||||
closeSheet() {
|
||||
this.setData({ sheetShow: false });
|
||||
this.loadSummary();
|
||||
},
|
||||
onFab() {
|
||||
this.setData({ sheetType: 'ai', sheetShow: true });
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"usingComponents": {
|
||||
"nav-bar": "/components/nav-bar/nav-bar",
|
||||
"bottom-sheet": "/components/bottom-sheet/bottom-sheet",
|
||||
"fab": "/components/fab/fab"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
<nav-bar title="我的" show-back="{{true}}"></nav-bar>
|
||||
|
||||
<scroll-view class="page-scroll" scroll-y="{{true}}" enhanced="{{true}}" show-scrollbar="{{false}}">
|
||||
<view class="page-body">
|
||||
<view class="profile-header">
|
||||
<view class="avatar ph-avatar">{{pet.emoji}}</view>
|
||||
<view class="ph-name">{{pet.name}}</view>
|
||||
<view class="muted ph-meta">{{pet.age}}|{{pet.weight}}|{{pet.stage}}</view>
|
||||
<view wx:if="{{pet.breed || pet.color}}" class="muted ph-meta">{{pet.breed}}{{pet.breed && pet.color ? ' · ' : ''}}{{pet.color}}</view>
|
||||
</view>
|
||||
|
||||
<button class="btn btn-ghost btn-block" style="margin-bottom:28rpx" bindtap="onAddPet">+ 添加毛孩子</button>
|
||||
|
||||
<view class="profile-list">
|
||||
<view class="profile-row" bindtap="onEditPet">宠物档案(编辑)<text class="pr-val">已完善 {{profilePct}}% ›</text></view>
|
||||
<view class="profile-row">提醒设置 <text class="pr-val">{{summary.reminders}} 条</text></view>
|
||||
<view class="profile-row">健康记录 <text class="pr-val">{{summary.records}} 条</text></view>
|
||||
<view class="profile-row">多宠物管理 <text class="pr-val">{{summary.pets}} 只</text></view>
|
||||
</view>
|
||||
|
||||
<view class="profile-list">
|
||||
<view class="profile-row">会员权益 <text class="pr-val">{{summary.pro_status === 'active' ? '已开通' : '未开通'}}</text></view>
|
||||
<view class="profile-row">数据导出 <text class="pr-val">PDF</text></view>
|
||||
<view class="profile-row">意见反馈 <text class="pr-val">去填写</text></view>
|
||||
<view class="profile-row">关于我们 <text class="pr-val">v0.2</text></view>
|
||||
</view>
|
||||
|
||||
<button class="btn btn-primary btn-block" data-type="pro" bindtap="openSheet">开通 Pro</button>
|
||||
</view>
|
||||
</scroll-view>
|
||||
|
||||
<fab bind:tap="onFab"></fab>
|
||||
<bottom-sheet show="{{sheetShow}}" type="{{sheetType}}" bind:close="closeSheet"></bottom-sheet>
|
||||
@@ -0,0 +1,18 @@
|
||||
.page-body{padding:8rpx 40rpx calc(60rpx + env(safe-area-inset-bottom))}
|
||||
|
||||
.profile-header{text-align:center;padding:24rpx 0 32rpx}
|
||||
.ph-avatar{margin:0 auto 20rpx;width:152rpx;height:152rpx;font-size:76rpx;border-radius:56rpx}
|
||||
.ph-name{font-size:44rpx;font-weight:800}
|
||||
.ph-meta{font-size:26rpx;margin-top:10rpx}
|
||||
|
||||
.profile-list{background:#fff;border-radius:48rpx;box-shadow:var(--shadow);overflow:hidden;margin-bottom:28rpx}
|
||||
.profile-row{
|
||||
display:flex;align-items:center;justify-content:space-between;min-height:104rpx;padding:0 32rpx;
|
||||
border-bottom:1rpx solid var(--line);font-size:28rpx;font-weight:800;
|
||||
}
|
||||
.profile-row:last-child{border-bottom:0}
|
||||
.pr-val{color:var(--muted);font-weight:700;font-size:26rpx}
|
||||
|
||||
/* 页面不自身滚动,改由 page-scroll 承载滚动(隐藏滚动条)*/
|
||||
page{height:100vh;overflow:hidden;display:flex;flex-direction:column}
|
||||
.page-scroll{flex:1;min-height:0}
|
||||
Reference in New Issue
Block a user