const store = require('../../utils/store.js'); const api = require('../../utils/api.js'); const { toastErr } = require('../../utils/ui.js'); function todayStr() { const d = new Date(); const p = (n) => (n < 10 ? '0' + n : '' + n); return d.getFullYear() + '-' + p(d.getMonth() + 1) + '-' + p(d.getDate()); } function mapTask(t) { return { id: t.id, title: t.title, sub: t.description, priority: t.priority, done: t.done, sheet: t.sheet_type, }; } // 快速记录入口。颜色按类别分组(体重/疫苗=橙、便便/饮食=绿、异常/用药=蓝、消费/照片=紫), // 靠颜色和图标区分,不再靠 emoji。 const QUICK_ITEMS = [ { type: 'weight', icon: 'weight', label: '体重', tone: 'tone-1' }, { type: 'poop', icon: 'poop', label: '便便', tone: 'tone-2' }, { type: 'food', icon: 'food', label: '饮食', tone: 'tone-2' }, { type: 'symptom', icon: 'symptom', label: '异常', tone: 'tone-3' }, { type: 'cost', icon: 'cost', label: '消费', tone: 'tone-4' }, { type: 'medicine', icon: 'medicine', label: '用药', tone: 'tone-3' }, { type: 'photo', icon: 'photo', label: '照片', tone: 'tone-4' }, { type: 'vaccine', icon: 'vaccine', label: '疫苗', tone: 'tone-1' }, ]; // 门面上的状态 chip:健康状态 + 最多两条洞察 function heroChips(summary) { const chips = []; if (summary.health_status) { chips.push({ text: summary.health_status, icon: 'check', tone: 'green' }); } (summary.insights || []).slice(0, 2).forEach((it) => { if (it && it.bold) chips.push({ text: it.bold, icon: 'trend', tone: '' }); }); return chips; } Page({ data: { pet: {}, summary: { greeting: '', insights: [], week: [], advice: '', health_pct: 0, health_status: '正常' }, tasks: [], quickItems: QUICK_ITEMS, heroChips: [], undoneText: '', firstArticle: null, selectedDate: '', taskLabel: '今日任务', todayDate: '', sheetShow: false, sheetType: '', }, onLoad() { this.setData({ todayDate: todayStr() }); this._unsub = store.subscribe((pet) => { this.setData({ pet }); // 首次由 onShow 统一加载,这里只处理之后的「切换宠物 / 数据变更」,避免重复请求 if (!this._inited) return; this.loadAll(); }); }, onUnload() { if (this._unsub) this._unsub(); }, onShow() { if (typeof this.getTabBar === 'function' && this.getTabBar()) { this.getTabBar().setData({ selected: 0 }); } store .ready() .then(() => { this._inited = true; this.setData({ pet: store.getPet() }); this.loadAll(); }) .catch((e) => wx.showToast({ title: e.message || '加载失败', icon: 'none' })); }, loadAll() { this.loadSummary(); this.loadTasks(); if (!this.data.firstArticle) { api .listArticles() .then((list) => { if (list && list[0]) { this.setData({ firstArticle: { id: list[0].id, icon: list[0].icon, title: list[0].title, desc: list[0].description } }); } }) .catch(() => {}); } }, loadSummary() { const id = store.currentPetId(); if (!id) return; api .homeSummary(id) .then((summary) => this.setData({ summary, heroChips: heroChips(summary) })) .catch((e) => toastErr(e)); }, loadTasks() { const id = store.currentPetId(); if (!id) return; const date = this.data.selectedDate || this.data.todayDate; api .getTasks(id, date) .then((tasks) => this.setTasks((tasks || []).map(mapTask))) .catch((e) => toastErr(e)); }, // 任务列表落地时顺手算「还有几件事没做完」,门面上要用 setTasks(tasks) { const undone = tasks.filter((t) => !t.done).length; this.setData({ tasks, undoneText: tasks.length === 0 ? '这天还没有安排' : undone > 0 ? '还有 ' + undone + ' 件事没做完' : '今天的事都做完啦', }); }, onTapDay(e) { const { date, active } = e.currentTarget.dataset; if (!date) return; const parts = date.split('-'); this.setData({ selectedDate: date, taskLabel: active ? '今日任务' : +parts[1] + '月' + +parts[2] + '日', }); this.loadTasks(); }, backToToday() { this.setData({ selectedDate: this.data.todayDate, taskLabel: '今日任务' }); this.loadTasks(); }, onTapTask(e) { const i = e.currentTarget.dataset.index; const t = this.data.tasks[i]; if (t.sheet) { this.openSheetType(t.sheet); return; } api .toggleTask(t.id) .then((res) => { const tasks = this.data.tasks.slice(); tasks[i] = Object.assign({}, tasks[i], { done: res.done }); this.setTasks(tasks); this.loadSummary(); }) .catch(() => {}); }, completeTasks() { const id = store.currentPetId(); if (!id) return; api .completeAllTasks(id) .then((tasks) => { this.setTasks((tasks || []).map(mapTask)); this.loadSummary(); }) .catch(() => {}); }, openSheet(e) { this.openSheetType(e.currentTarget.dataset.type); }, openSheetType(type) { this.setData({ sheetType: type, sheetShow: true }); }, closeSheet() { // 只关闭。数据变更由 bind:saved 或 store 的宠物变更通知触发刷新, // 不必每次关弹层(哪怕只是看了眼 AI)都全量重拉一遍 this.setData({ sheetShow: false }); }, onSheetSave() { this.loadTasks(); this.loadSummary(); }, onAddPet() { this.openSheetType('addPet'); }, onEditPet() { this.openSheetType('editPet'); }, onFab() { wx.navigateTo({ url: '/pages/ai/ai' }); }, goProfile() { wx.navigateTo({ url: '/pages/profile/profile' }); }, goLearn() { wx.navigateTo({ url: '/pages/learn/learn' }); }, // 首页那张卡片直接打开这篇文章正文 openFirstArticle() { const a = this.data.firstArticle; if (a && a.id) wx.navigateTo({ url: `/pages/article/article?id=${a.id}` }); else this.goLearn(); }, goRecord() { wx.switchTab({ url: '/pages/record/record' }); }, onShareAppMessage() { return { title: '肉垫计划 · 每天照顾好毛孩子', path: '/pages/home/home' }; }, onShareTimeline() { return { title: '肉垫计划 · 每天照顾好毛孩子' }; }, });