const api = require('../../../services/api') const app = getApp() Page({ data: { item: null, streak: 0, records: [], year: 0, month: 0, days: [], loading: true, showActions: false, themeMode: 'light' }, onShow() { this.setData({ themeMode: app.globalData.themeMode }) }, onLoad(options) { const now = new Date() this.setData({ id: options.id, year: now.getFullYear(), month: now.getMonth() + 1 }) this.loadData() }, async loadData() { const { id, year, month } = this.data try { const [item, streak, records] = await Promise.all([ api.get('/api/checkin/items/' + id), api.get('/api/checkin/streak/' + id), api.get('/api/checkin/records?itemId=' + id + '&start=' + year + '-' + String(month).padStart(2,'0') + '-01&end=' + year + '-' + String(month).padStart(2,'0') + '-31'), ]) const days = this.buildCalendar(year, month, records.map(r => r.checkDate.slice(0,10))) this.setData({ item, streak: streak.streak, records, days, loading: false }) } catch(e) { wx.showToast({ title: '加载失败', icon: 'none' }); this.setData({ loading: false }) } }, buildCalendar(y, m, recordDates) { const daysInMonth = new Date(y, m, 0).getDate() const firstDay = new Date(y, m - 1, 1).getDay() const today = new Date().toISOString().slice(0, 10) const days = [] for (let i = 0; i < firstDay; i++) days.push({ empty: true }) for (let d = 1; d <= daysInMonth; d++) { const dateStr = y + '-' + String(m).padStart(2,'0') + '-' + String(d).padStart(2,'0') days.push({ day: d, checked: recordDates.includes(dateStr), isToday: dateStr === today, dateStr }) } return days }, prevMonth() { let { year, month } = this.data if (month === 1) { year--; month = 12 } else month-- this.setData({ year, month, loading: true }); this.loadData() }, nextMonth() { let { year, month } = this.data if (month === 12) { year++; month = 1 } else month++ this.setData({ year, month, loading: true }); this.loadData() }, toggleActions() { this.setData({ showActions: !this.data.showActions }) }, async onDelete() { wx.showModal({ title: '确认删除', content: '确定删除这个打卡项?历史记录将保留。', success: async (res) => { if (res.confirm) { try { await api.del('/api/checkin/items/' + this.data.id); wx.navigateBack() } catch(e) { wx.showToast({ title: '删除失败', icon: 'none' }) } } }}) }, async onTogglePause() { const { id, item } = this.data if (!item) return try { await api.post('/api/checkin/items/' + id + '/' + (item.status==='active'?'pause':'resume')); this.loadData() } catch(e) { wx.showToast({ title: '操作失败', icon: 'none' }) } }, })