const completion = require("../../utils/task-completion"); const { secure } = require("../../utils/api"); const { localDate } = require("../../utils/date"); const environment = require("../../utils/environment"); function dateLabel() { const now = new Date(); return `${now.getMonth() + 1}月${now.getDate()}日 周${"日一二三四五六"[now.getDay()]}`; } function accountKey() { const state = getApp().globalData || {}; return (state.user && state.user.id) || state.token || ""; } Page({ data: { locationName: "当前位置", headerSubtitle: dateLabel() + " · 轻触获取天气", pets: [], selected: [], tasks: [], taskBusyIds: [], completingAll: false, undoneCount: 0, walkCount: 0, name: "铲屎官", loading: true, ready: false, phase: "auth", error: "", }, onLoad() { const cached = getApp().homeSnapshot; if (cached && cached.account === accountKey() && cached.date === localDate()) { this.setData({ ...cached.data, ready: true, phase: "ready", loading: false }); } }, onShow() { this.applyEnvironment(environment.cached()); this.load(); }, onHide() { this.rememberHome(); }, onUnload() { this.rememberHome(); this.disposed = true; }, rememberHome() { if (!this.data.ready || !accountKey()) return; const { pets, selected, tasks, undoneCount, walkCount, name } = this.data; getApp().homeSnapshot = { account: accountKey(), date: localDate(), data: { pets, selected, tasks, undoneCount, walkCount, name }, }; }, updateEnvironmentLabel() { this.setData({ headerSubtitle: dateLabel() + " · " + (this.weatherLabel || "轻触获取天气"), }); }, applyEnvironment(value) { if (this.disposed) return; if (value) { this.weatherLabel = value.weatherLabel; this.setData({ locationName: value.locationName }); } this.updateEnvironmentLabel(); }, async refreshEnvironment(event) { if (this.environmentBusy) return; this.environmentBusy = true; const tapped = !!event; const cached = environment.cached(); if (!cached) { this.weatherLabel = "正在获取天气"; this.updateEnvironmentLabel(); } try { this.applyEnvironment(await environment.refresh(tapped)); } catch (error) { if (this.disposed) return; if (cached) { this.applyEnvironment(cached); } else { const denied = /denied|deny|auth/.test( error.errMsg || error.message || "", ); this.setData({ locationName: denied ? "开启定位" : "定位暂不可用" }); this.weatherLabel = denied ? "轻触开启定位" : "轻触重试"; this.updateEnvironmentLabel(); } if (tapped) toast(error); } finally { this.environmentBusy = false; } }, async load() { if (this.loadPromise) return this.loadPromise; this.loadPromise = this.loadHome().finally(() => { this.loadPromise = null; }); return this.loadPromise; }, async loadHome() { this.setData({ loading: true, error: "", phase: this.data.ready ? "data" : "auth", }); let authenticated = false; try { await getApp().login(); authenticated = true; if (this.disposed) return; this.setData({ phase: "data" }); const [pets, tasks, walks, me] = await Promise.all([ secure("/pets"), secure("/tasks"), secure("/walks"), secure("/me"), ]); if (this.disposed) return; const chosen = wx.getStorageSync("walk_pet_ids") || [], month = localDate().slice(0, 7); this.setData({ pets, selected: chosen.filter((id) => pets.some((p) => p.id === id)), tasks: tasks.items, undoneCount: tasks.items.filter((t) => !t.completed).length, walkCount: walks.filter((w) => w.started_at.slice(0, 7) === month) .length, name: me.nickname || "毛孩家长", loading: false, ready: true, phase: "ready", }); this.rememberHome(); // Location permission and weather never hold up the first usable screen. this.refreshEnvironment(); } catch (error) { if (this.disposed) return; this.setData({ loading: false, phase: !authenticated && !this.data.ready ? "auth-error" : "data-error", error: error.message || "暂时没能连接,请稍后重试", }); } }, addPet() { wx.navigateTo({ url: "/pages/pet-edit/pet-edit" }); }, pick(e) { this.setData({ selected: e.detail.selected }); wx.setStorageSync("walk_pet_ids", e.detail.selected); }, start() { if (!this.data.selected.length) { wx.showToast({ title: "先选择一起出门的狗狗", icon: "none" }); return; } wx.redirectTo({ url: "/pages/walk/walk" }); }, goTasks() { wx.redirectTo({ url: "/pages/tasks/tasks" }); }, goWalks() { wx.navigateTo({ url: "/pages/walk-records/walk-records" }); }, complete(e) { return completion.complete( this, this.data.tasks.find((t) => t.id === e.currentTarget.dataset.id), ); }, completeAll() { return completion.completeAll(this); }, });