feat(auth): access token 缩到 2 小时 + refresh token 机制 #3
@@ -343,3 +343,17 @@ page{scrollbar-width:none;-ms-overflow-style:none}
|
|||||||
.msg{max-width:88%;border-radius:var(--r-md);padding:var(--sp-3) var(--sp-4);font-size:var(--fs-md);line-height:1.55}
|
.msg{max-width:88%;border-radius:var(--r-md);padding:var(--sp-3) var(--sp-4);font-size:var(--fs-md);line-height:1.55}
|
||||||
.msg.ai{background:var(--green-soft);align-self:flex-start}
|
.msg.ai{background:var(--green-soft);align-self:flex-start}
|
||||||
.msg.user{background:var(--primary-soft);align-self:flex-end}
|
.msg.user{background:var(--primary-soft);align-self:flex-end}
|
||||||
|
|
||||||
|
/* 没有宠物时的引导块。四个主页面都会 currentPetId 为空直接 return,
|
||||||
|
留下一堆空卡片却不解释为什么——用户以为是坏了。 */
|
||||||
|
.no-pet{
|
||||||
|
background:#fff;border-radius:var(--r-lg);box-shadow:var(--sd-1);
|
||||||
|
padding:var(--sp-6) var(--sp-5);text-align:center;margin-bottom:var(--sp-4);
|
||||||
|
}
|
||||||
|
.no-pet-ic{
|
||||||
|
width:104rpx;height:104rpx;border-radius:var(--r-md);margin:0 auto var(--sp-3);
|
||||||
|
display:flex;align-items:center;justify-content:center;
|
||||||
|
background:var(--primary-soft);color:var(--primary-ink);
|
||||||
|
}
|
||||||
|
.no-pet-b{font-size:var(--fs-lg);font-weight:var(--fw-b)}
|
||||||
|
.no-pet-p{color:var(--muted);font-size:var(--fs-sm);margin:var(--sp-2) 0 var(--sp-4);line-height:1.6}
|
||||||
|
|||||||
@@ -584,10 +584,15 @@ Component({
|
|||||||
|
|
||||||
async createAndClose(rec) {
|
async createAndClose(rec) {
|
||||||
const id = store.currentPetId();
|
const id = store.currentPetId();
|
||||||
if (!rec || !id) {
|
if (!rec) {
|
||||||
this.close();
|
this.close();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
// 没建档时点「保存」原来是静默关掉弹层,用户以为存上了,其实什么都没发生
|
||||||
|
if (!id) {
|
||||||
|
wx.showToast({ title: '先建一份宠物档案再记录', icon: 'none' });
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (this.data.saving) return;
|
if (this.data.saving) return;
|
||||||
this.setData({ saving: true });
|
this.setData({ saving: true });
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -80,7 +80,7 @@ Page({
|
|||||||
.then((res) => {
|
.then((res) => {
|
||||||
this.setData({ [`posts[${i}].like_count`]: res.like_count, [`posts[${i}].liked`]: true });
|
this.setData({ [`posts[${i}].like_count`]: res.like_count, [`posts[${i}].liked`]: true });
|
||||||
})
|
})
|
||||||
.catch(() => {});
|
.catch((e) => toastErr(e, '点赞失败'));
|
||||||
},
|
},
|
||||||
openComments(e) {
|
openComments(e) {
|
||||||
this.setData({ sheetPostId: e.currentTarget.dataset.id, sheetType: 'comments', sheetShow: true });
|
this.setData({ sheetPostId: e.currentTarget.dataset.id, sheetType: 'comments', sheetShow: true });
|
||||||
|
|||||||
@@ -154,7 +154,7 @@ Page({
|
|||||||
this.setTasks(tasks);
|
this.setTasks(tasks);
|
||||||
this.loadSummary();
|
this.loadSummary();
|
||||||
})
|
})
|
||||||
.catch(() => {});
|
.catch((e) => toastErr(e, '操作失败'));
|
||||||
},
|
},
|
||||||
completeTasks() {
|
completeTasks() {
|
||||||
const id = store.currentPetId();
|
const id = store.currentPetId();
|
||||||
@@ -165,7 +165,7 @@ Page({
|
|||||||
this.setTasks((tasks || []).map(mapTask));
|
this.setTasks((tasks || []).map(mapTask));
|
||||||
this.loadSummary();
|
this.loadSummary();
|
||||||
})
|
})
|
||||||
.catch(() => {});
|
.catch((e) => toastErr(e, '操作失败'));
|
||||||
},
|
},
|
||||||
openSheet(e) {
|
openSheet(e) {
|
||||||
this.openSheetType(e.currentTarget.dataset.type);
|
this.openSheetType(e.currentTarget.dataset.type);
|
||||||
@@ -185,6 +185,11 @@ Page({
|
|||||||
onAddPet() {
|
onAddPet() {
|
||||||
this.openSheetType('addPet');
|
this.openSheetType('addPet');
|
||||||
},
|
},
|
||||||
|
// 没建档时点门面卡应该去「添加」,而不是打开一个空的编辑表单
|
||||||
|
onHeroTap() {
|
||||||
|
if (this.data.pet && this.data.pet.id) this.openSheetType('editPet');
|
||||||
|
else this.openSheetType('addPet');
|
||||||
|
},
|
||||||
onEditPet() {
|
onEditPet() {
|
||||||
this.openSheetType('editPet');
|
this.openSheetType('editPet');
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -16,7 +16,7 @@
|
|||||||
<pet-switch bind:add="onAddPet"></pet-switch>
|
<pet-switch bind:add="onAddPet"></pet-switch>
|
||||||
|
|
||||||
<!-- 门面:完成度环 + 当下状态。点进去编辑档案 -->
|
<!-- 门面:完成度环 + 当下状态。点进去编辑档案 -->
|
||||||
<view class="card hero-card" bindtap="onEditPet">
|
<view class="card hero-card" bindtap="onHeroTap">
|
||||||
<view class="hero-row">
|
<view class="hero-row">
|
||||||
<stat-ring percent="{{summary.health_pct}}" size="{{168}}">
|
<stat-ring percent="{{summary.health_pct}}" size="{{168}}">
|
||||||
<view class="ring-num">{{summary.health_pct}}<text class="ring-unit">%</text></view>
|
<view class="ring-num">{{summary.health_pct}}<text class="ring-unit">%</text></view>
|
||||||
@@ -24,7 +24,7 @@
|
|||||||
</stat-ring>
|
</stat-ring>
|
||||||
<view class="hero-main">
|
<view class="hero-main">
|
||||||
<view class="hero-title">{{pet.name || '还没有毛孩子'}}</view>
|
<view class="hero-title">{{pet.name || '还没有毛孩子'}}</view>
|
||||||
<view class="hero-sub">{{undoneText}}</view>
|
<view class="hero-sub">{{pet.id ? undoneText : '点这里建一份档案,任务和提醒会自动排好'}}</view>
|
||||||
<view class="chip-row">
|
<view class="chip-row">
|
||||||
<view wx:for="{{heroChips}}" wx:key="text" class="chip {{item.tone}}">
|
<view wx:for="{{heroChips}}" wx:key="text" class="chip {{item.tone}}">
|
||||||
<pt-icon name="{{item.icon}}" size="{{22}}"></pt-icon>{{item.text}}
|
<pt-icon name="{{item.icon}}" size="{{22}}"></pt-icon>{{item.text}}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
const store = require('../../utils/store.js');
|
const store = require('../../utils/store.js');
|
||||||
const api = require('../../utils/api.js');
|
const api = require('../../utils/api.js');
|
||||||
|
const { toastErr } = require('../../utils/ui.js');
|
||||||
|
|
||||||
// "2026-07-04" → "7月4日"
|
// "2026-07-04" → "7月4日"
|
||||||
function fmtMD(date) {
|
function fmtMD(date) {
|
||||||
@@ -131,7 +132,7 @@ Page({
|
|||||||
// 计划明细勾选
|
// 计划明细勾选
|
||||||
toggleTimelineTask(e) {
|
toggleTimelineTask(e) {
|
||||||
const id = e.currentTarget.dataset.id;
|
const id = e.currentTarget.dataset.id;
|
||||||
api.togglePlanTask(id).then(() => this.loadTimeline()).catch(() => {});
|
api.togglePlanTask(id).then(() => this.loadTimeline()).catch((e) => toastErr(e, '操作失败'));
|
||||||
},
|
},
|
||||||
// AI 计划
|
// AI 计划
|
||||||
onAiInput(e) {
|
onAiInput(e) {
|
||||||
|
|||||||
@@ -4,6 +4,13 @@
|
|||||||
<view class="page-body">
|
<view class="page-body">
|
||||||
<pet-switch bind:add="onAddPet"></pet-switch>
|
<pet-switch bind:add="onAddPet"></pet-switch>
|
||||||
|
|
||||||
|
<view wx:if="{{!pet.id}}" class="no-pet">
|
||||||
|
<view class="no-pet-ic"><pt-icon name="community" size="{{52}}"></pt-icon></view>
|
||||||
|
<view class="no-pet-b">还没有毛孩子的档案</view>
|
||||||
|
<view class="no-pet-p">建好档会按它的年龄阶段自动排好 30 天计划和疫苗驱虫提醒。</view>
|
||||||
|
<view class="btn btn-dark" bindtap="onAddPet"><pt-icon name="plus" size="{{30}}"></pt-icon>建一份档案</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
<seg-tabs variant="solid" items="{{planTabs}}" current="{{planView}}" bind:change="switchPlanView"></seg-tabs>
|
<seg-tabs variant="solid" items="{{planTabs}}" current="{{planView}}" bind:change="switchPlanView"></seg-tabs>
|
||||||
|
|
||||||
<!-- 路线图 -->
|
<!-- 路线图 -->
|
||||||
|
|||||||
@@ -4,6 +4,13 @@
|
|||||||
<view class="page-body">
|
<view class="page-body">
|
||||||
<pet-switch bind:add="onAddPet"></pet-switch>
|
<pet-switch bind:add="onAddPet"></pet-switch>
|
||||||
|
|
||||||
|
<view wx:if="{{!pet.id}}" class="no-pet">
|
||||||
|
<view class="no-pet-ic"><pt-icon name="community" size="{{52}}"></pt-icon></view>
|
||||||
|
<view class="no-pet-b">还没有毛孩子的档案</view>
|
||||||
|
<view class="no-pet-p">建好档才能记体重、便便、饮食这些,趋势图也是从这些记录里长出来的。</view>
|
||||||
|
<view class="btn btn-dark" bindtap="onAddPet"><pt-icon name="plus" size="{{30}}"></pt-icon>建一份档案</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
<view class="card">
|
<view class="card">
|
||||||
<view class="section-head"><view class="sh-title">记一笔</view></view>
|
<view class="section-head"><view class="sh-title">记一笔</view></view>
|
||||||
<view class="quick-grid cols-3">
|
<view class="quick-grid cols-3">
|
||||||
|
|||||||
@@ -4,6 +4,13 @@
|
|||||||
<view class="page-body">
|
<view class="page-body">
|
||||||
<pet-switch bind:add="onAddPet"></pet-switch>
|
<pet-switch bind:add="onAddPet"></pet-switch>
|
||||||
|
|
||||||
|
<view wx:if="{{!pet.id}}" class="no-pet">
|
||||||
|
<view class="no-pet-ic"><pt-icon name="community" size="{{52}}"></pt-icon></view>
|
||||||
|
<view class="no-pet-b">还没有毛孩子的档案</view>
|
||||||
|
<view class="no-pet-p">成长报告和账单都基于记录生成,先建个档开始记吧。</view>
|
||||||
|
<view class="btn btn-dark" bindtap="onAddPet"><pt-icon name="plus" size="{{30}}"></pt-icon>建一份档案</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
<view class="card report-card">
|
<view class="card report-card">
|
||||||
<view class="section-head"><view class="sh-title">本周成长报告</view><view class="tag">{{report.health_status || '稳定成长'}}</view></view>
|
<view class="section-head"><view class="sh-title">本周成长报告</view><view class="tag">{{report.health_status || '稳定成长'}}</view></view>
|
||||||
<view class="rc-text">{{report.summary || '暂无本周数据'}}</view>
|
<view class="rc-text">{{report.summary || '暂无本周数据'}}</view>
|
||||||
|
|||||||
Reference in New Issue
Block a user