init: 毛孩子计划 小程序 + Go 后端 + 内嵌后台
- pets-fe: 微信原生小程序(首页/计划/记录/报告/社区/引导), 服务端驱动、无假数据;弹层改用 scroll-view,打开时隐藏自定义 tabBar - pets-be: Gin + GORM(MySQL, sundynix_ 前缀) + MinIO,统一响应/分页, 微信 code2session 登录,provider-neutral AI(DeepSeek),go:embed React 后台 - 修复:分段选择类型不匹配(字符串 vs 数字)导致选不中 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,100 @@
|
||||
// 全局状态:登录、宠物列表、当前宠物;服务端驱动 + 发布订阅
|
||||
const api = require('./api.js');
|
||||
|
||||
const state = {
|
||||
user: null,
|
||||
pets: [],
|
||||
currentId: 0,
|
||||
};
|
||||
|
||||
const listeners = new Set();
|
||||
let bootstrapPromise = null;
|
||||
|
||||
function getPets() {
|
||||
return state.pets;
|
||||
}
|
||||
function getPet() {
|
||||
return state.pets.find((p) => p.id === state.currentId) || state.pets[0] || {};
|
||||
}
|
||||
function currentPetId() {
|
||||
const p = getPet();
|
||||
return p && p.id;
|
||||
}
|
||||
|
||||
function notify() {
|
||||
const pet = getPet();
|
||||
listeners.forEach((fn) => {
|
||||
try {
|
||||
fn(pet);
|
||||
} catch (e) {
|
||||
/* noop */
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function subscribe(fn) {
|
||||
listeners.add(fn);
|
||||
return () => listeners.delete(fn);
|
||||
}
|
||||
|
||||
// 登录 + 拉宠物列表(只跑一次)
|
||||
function ready() {
|
||||
if (!bootstrapPromise) {
|
||||
bootstrapPromise = (async () => {
|
||||
const res = await api.login();
|
||||
state.user = res.user;
|
||||
await loadPets();
|
||||
})().catch((e) => {
|
||||
bootstrapPromise = null; // 允许重试
|
||||
throw e;
|
||||
});
|
||||
}
|
||||
return bootstrapPromise;
|
||||
}
|
||||
|
||||
async function loadPets() {
|
||||
const pets = await api.getPets();
|
||||
state.pets = pets || [];
|
||||
if (!state.currentId && state.pets[0]) {
|
||||
state.currentId = state.pets[0].id;
|
||||
}
|
||||
// 当前宠物被删或不存在时回退第一只
|
||||
if (!state.pets.find((p) => p.id === state.currentId) && state.pets[0]) {
|
||||
state.currentId = state.pets[0].id;
|
||||
}
|
||||
notify();
|
||||
return state.pets;
|
||||
}
|
||||
|
||||
function switchPet(id) {
|
||||
if (state.currentId === id) return;
|
||||
state.currentId = id;
|
||||
notify();
|
||||
}
|
||||
|
||||
// 本地更新当前宠物字段(服务端已改动后同步 UI)
|
||||
function patchCurrent(patch) {
|
||||
const pet = getPet();
|
||||
Object.assign(pet, patch);
|
||||
notify();
|
||||
}
|
||||
|
||||
function setUser(u) {
|
||||
state.user = u;
|
||||
}
|
||||
function getUser() {
|
||||
return state.user;
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
ready,
|
||||
loadPets,
|
||||
getPets,
|
||||
getPet,
|
||||
currentPetId,
|
||||
switchPet,
|
||||
patchCurrent,
|
||||
subscribe,
|
||||
setUser,
|
||||
getUser,
|
||||
};
|
||||
Reference in New Issue
Block a user