const store = require('../../utils/store.js'); const api = require('../../utils/api.js'); function buildCells(year, month, taskedDays, today) { const first = new Date(year, month - 1, 1); const lead = (first.getDay() + 6) % 7; // 周一为一周起点 const daysInMonth = new Date(year, month, 0).getDate(); const set = {}; (taskedDays || []).forEach((d) => (set[d] = true)); const cells = []; for (let i = 0; i < lead; i++) cells.push({ day: 0 }); for (let d = 1; d <= daysInMonth; d++) { cells.push({ day: d, tasked: !!set[d], today: d === today }); } return cells; } Page({ data: { pet: {}, planView: 'timeline', plan: null, calCells: [], calLabel: '', calLoaded: false, aiInput: '', aiPlan: null, aiBusy: false, sheetShow: false, sheetType: '', }, onLoad() { this._unsub = store.subscribe((pet) => { this.setData({ pet, calLoaded: false }); this.loadTimeline(); if (this.data.planView === 'calendar') this.loadCalendar(); }); }, onUnload() { if (this._unsub) this._unsub(); }, onShow() { if (typeof this.getTabBar === 'function' && this.getTabBar()) { this.getTabBar().setData({ selected: 1 }); } store .ready() .then(() => { this.setData({ pet: store.getPet() }); this.loadTimeline(); }) .catch((e) => wx.showToast({ title: e.message || '加载失败', icon: 'none' })); }, loadTimeline() { const id = store.currentPetId(); if (!id) return; api .getPlan(id) .then((plan) => this.setData({ plan })) .catch(() => this.setData({ plan: null })); }, loadCalendar() { const id = store.currentPetId(); if (!id) return; api .planCalendar(id) .then((res) => { this.setData({ calCells: buildCells(res.year, res.month, res.tasked_days, res.today), calLabel: `${res.year} 年 ${res.month} 月`, calLoaded: true, }); }) .catch(() => {}); }, switchPlanView(e) { const view = e.currentTarget.dataset.view; this.setData({ planView: view }); if (view === 'calendar' && !this.data.calLoaded) this.loadCalendar(); }, // 计划明细勾选 toggleTimelineTask(e) { const id = e.currentTarget.dataset.id; api.togglePlanTask(id).then(() => this.loadTimeline()).catch(() => {}); }, // AI 计划 onAiInput(e) { this.setData({ aiInput: e.detail.value }); }, genAIPlan() { const id = store.currentPetId(); const input = (this.data.aiInput || '').trim(); if (!id || !input) { wx.showToast({ title: '先描述一下情况', icon: 'none' }); return; } this.setData({ aiBusy: true }); wx.showLoading({ title: 'AI 生成中...' }); api .createAIPlan(id, input) .then((plan) => { wx.hideLoading(); this.setData({ aiPlan: plan, aiBusy: false }); }) .catch((err) => { wx.hideLoading(); this.setData({ aiBusy: false }); wx.showToast({ title: err.message || '生成失败', icon: 'none' }); }); }, applyAIPlan() { const p = this.data.aiPlan; if (!p) return; api .applyAIPlan(p.id) .then(() => wx.showToast({ title: '已加入我的计划', icon: 'success' })) .catch((err) => wx.showToast({ title: err.message || '加入失败', icon: 'none' })); }, openSheet(e) { const type = e.currentTarget.dataset.type; if (!type) return; // 无关联动作的计划项只可勾选,不弹层 this.setData({ sheetType: type, sheetShow: true }); }, closeSheet() { this.setData({ sheetShow: false }); }, onAddPet() { this.setData({ sheetType: 'addPet', sheetShow: true }); }, onFab() { this.setData({ sheetType: 'ai', sheetShow: true }); }, });