// pages/tasks/index.js import request from '../../utils/request'; Page({ data: { tasks: [], groupedTasks: [], progress: 0, completingTask: null, remark: '' }, onLoad() { this.fetchTodayTasks(); }, onShow() { if (typeof this.getTabBar === 'function' && this.getTabBar()) { this.getTabBar().setData({ selected: 1 }); } // Refresh on show this.fetchTodayTasks(); }, fetchTodayTasks() { request.get('/plant/todayTask').then(res => { // Check if res is array (list of PlantTaskVO) const list = Array.isArray(res) ? res : (res.list || []); this.processTaskData(list); }).catch(err => { console.error('Fetch tasks failed', err); wx.stopPullDownRefresh(); }); }, processTaskData(plantTaskVOList) { let totalPacketTasks = 0; let completedPacketTasks = 0; const groups = plantTaskVOList.map(vo => { const plant = vo.MyPlant || vo.myPlant; if (!plant) return null; // Parse Image let imageUrl = ''; if (plant.imgList && plant.imgList.length > 0) { let url = plant.imgList[0].url; if (url && !url.startsWith('http') && !url.startsWith('/') && !url.startsWith('wxfile')) { imageUrl = '/assets/' + url; } else { imageUrl = url; } } const plantGroup = { plantName: plant.name, plantImage: imageUrl, tasks: [], // Placeholder, will fill below hasOverdue: vo.hasExpired }; const rawTasks = vo.tasks || []; // 1. Update Global Counters rawTasks.forEach(t => { totalPacketTasks++; if (t.status == 2 || t.status == 3) { completedPacketTasks++; } }); // 2. Filter and Map Tasks for Display const displayTasks = rawTasks .filter(t => t.status == 1 || t.status == 2) .map(t => { // Status: 1 Pending, 2 Done const isCompleted = t.status == 2; // Parse Icon let taskIcon = null; if (t.icon && t.icon.startsWith('{')) { try { taskIcon = JSON.parse(t.icon); } catch (e) { } } // Check overdue (only for pending tasks) let isOverdue = false; let overdueDays = 0; if (!isCompleted && t.dueDate) { const due = new Date(t.dueDate); const today = new Date(); today.setHours(0, 0, 0, 0); if (due < today) { isOverdue = true; const diffTime = Math.abs(today - due); overdueDays = Math.ceil(diffTime / (1000 * 60 * 60 * 24)); } } return { id: t.id, taskType: t.name, taskIcon: taskIcon, isOverdue: isOverdue, overdueDays: overdueDays, plantName: plant.name, isCompleted: isCompleted, original: t }; }); // Sorting Removed: Tasks stay in original order // displayTasks.sort((a, b) => { // if (a.isCompleted === b.isCompleted) return 0; // return a.isCompleted ? 1 : -1; // }); plantGroup.tasks = displayTasks; if (plantGroup.tasks.length === 0) return null; return plantGroup; }).filter(g => g !== null); // Calculate Progress let progress = 0; if (totalPacketTasks > 0) { progress = Math.round((completedPacketTasks / totalPacketTasks) * 100); } // Sorting Groups: Overdue first groups.sort((a, b) => { if (a.hasOverdue && !b.hasOverdue) return -1; if (!a.hasOverdue && b.hasOverdue) return 1; return 0; }); this.setData({ groupedTasks: groups, progress, tasks: groups }); wx.stopPullDownRefresh(); }, handleTaskClick(e) { const task = e.currentTarget.dataset.task; if (task.isCompleted) return; this.setData({ completingTask: task, remark: '' }); }, onPopupVisibleChange(e) { const visible = e.detail ? e.detail.visible : e.currentTarget.dataset.visible; if (!visible) { this.setData({ completingTask: null }); } }, onRemarkInput(e) { this.setData({ remark: e.detail.value }); }, handleConfirmComplete() { if (!this.data.completingTask) return; const taskId = this.data.completingTask.id; const remark = this.data.remark || ''; wx.showLoading({ title: '提交中...' }); request.post('/plant/completeTask', { taskId: taskId, remark: remark }).then(() => { wx.hideLoading(); wx.showToast({ title: '已完成', icon: 'success' }); // Optimistic UI Update const groups = this.data.groupedTasks; let updated = false; for (let g of groups) { const t = g.tasks.find(x => x.id === taskId); if (t) { t.isCompleted = true; t.isOverdue = false; // Do NOT sort. Just update status. updated = true; break; } } if (updated) { this.setData({ groupedTasks: groups, tasks: groups, completingTask: null, remark: '' }); } else { this.setData({ completingTask: null, remark: '' }); } // Sync with backend this.fetchTodayTasks(); }).catch(err => { wx.hideLoading(); console.error('Complete task failed', err); wx.showToast({ title: '操作失败', icon: 'none' }); }); }, gotoGarden() { wx.switchTab({ url: '/pages/garden/index' }); } })