Files
gouki 50975e0627
Publish Mini Program Dev Version / publish (push) Failing after 11s
Build and Publish Server / build (push) Successful in 2m55s
feat(bazi): 八字页重构——空态示例排盘+字段术语表+文化声明,生辰档案绑定
- 八字页:未绑定生辰时展示虚构示例排盘(1990-08-08 10:30男)与15条字段说明,
  附传统文化声明文案;已绑定时支持多档案切换,排盘增强(十神/藏干/纳音/五行配色/命盘概览)
- 个人中心:新增生辰管理卡片,每用户免费绑定3个出生年月;登录改为真实微信登录
- 服务端:新增 BirthProfile 模型与 /api/user/birth-profiles 增删查接口,AutoMigrate 建表
- 前端:新增 birth-profile.js 本地存储优先+登录后云端双向同步
- 修复:个人中心 tabBar 页面入口误用 navigateTo 改为 switchTab
2026-08-09 23:21:58 +00:00

148 lines
4.5 KiB
JavaScript

// 生辰档案管理工具
// 本地存储优先;已登录(存在 token)时与服务端双向同步
const { request } = require('./request.js');
const STORAGE_KEY = 'lunar-birth-profiles';
// 每个用户可免费绑定的生辰数量上限
const MAX_PROFILES = 3;
/** 读取本地生辰档案列表 */
function getProfiles() {
return wx.getStorageSync(STORAGE_KEY) || [];
}
/** 保存本地生辰档案列表 */
function saveProfiles(profiles) {
wx.setStorageSync(STORAGE_KEY, profiles);
}
/** 获取当前激活的档案(第一个为默认) */
function getActiveProfile() {
const profiles = getProfiles();
if (profiles.length === 0) return null;
const activeId = wx.getStorageSync('lunar-birth-active-id');
return profiles.find(p => p.id === activeId) || profiles[0];
}
/** 设置激活档案 */
function setActiveProfile(id) {
wx.setStorageSync('lunar-birth-active-id', id);
}
/** 新增生辰档案(本地),超出上限或重复时返回错误信息 */
function addProfile(profile) {
const profiles = getProfiles();
if (profiles.length >= MAX_PROFILES) {
return { ok: false, msg: `最多可免费绑定 ${MAX_PROFILES} 个生辰` };
}
const dup = profiles.find(p => p.birthday === profile.birthday && p.birthTime === profile.birthTime);
if (dup) {
return { ok: false, msg: '该生辰已绑定,请勿重复添加' };
}
const item = {
id: `local-${Date.now()}`,
name: profile.name || '未命名',
gender: profile.gender || 'male',
birthday: profile.birthday,
birthTime: profile.birthTime,
serverId: 0,
createdAt: Date.now()
};
profiles.push(item);
saveProfiles(profiles);
if (!getActiveProfile()) setActiveProfile(item.id);
return { ok: true, profile: item };
}
/** 删除生辰档案(本地) */
function removeProfile(id) {
const profiles = getProfiles().filter(p => p.id !== id);
saveProfiles(profiles);
if (wx.getStorageSync('lunar-birth-active-id') === id) {
setActiveProfile(profiles.length > 0 ? profiles[0].id : '');
}
}
/** 是否已登录(存在有效 token) */
function isLoggedIn() {
return !!wx.getStorageSync('token');
}
/** 推送单个档案到服务端(静默失败,不影响本地) */
function pushProfileToServer(profile) {
if (!isLoggedIn()) return Promise.resolve(null);
return request({
url: '/api/user/birth-profiles',
method: 'POST',
data: {
name: profile.name,
gender: profile.gender === 'female' ? 2 : 1,
birthday: profile.birthday,
birthTime: profile.birthTime
}
}).then(res => {
if (res && res.code === 0 && res.data && res.data.profile) {
// 回填 serverId
const profiles = getProfiles();
const target = profiles.find(p => p.id === profile.id);
if (target) {
target.serverId = res.data.profile.id;
saveProfiles(profiles);
}
return res.data.profile;
}
return null;
}).catch(() => null);
}
/** 删除服务端档案(静默失败) */
function removeProfileFromServer(profile) {
if (!isLoggedIn() || !profile.serverId) return Promise.resolve();
return request({
url: `/api/user/birth-profiles/${profile.serverId}`,
method: 'DELETE'
}).catch(() => null);
}
/** 从服务端拉取档案并与本地合并(以服务端为准) */
function syncFromServer() {
if (!isLoggedIn()) return Promise.resolve(getProfiles());
return request({ url: '/api/user/birth-profiles' })
.then(res => {
if (!res || res.code !== 0 || !Array.isArray(res.data && res.data.profiles)) {
return getProfiles();
}
const serverList = res.data.profiles.map(sp => ({
id: `server-${sp.id}`,
serverId: sp.id,
name: sp.name || '未命名',
gender: sp.gender === 2 ? 'female' : 'male',
birthday: sp.birthday,
birthTime: sp.birthTime,
createdAt: sp.createdAt ? new Date(sp.createdAt).getTime() : 0
}));
// 本地尚未成功推送的档案保留,按 (birthday+birthTime) 去重
const merged = [...serverList];
getProfiles().forEach(lp => {
const exists = merged.some(m => m.birthday === lp.birthday && m.birthTime === lp.birthTime);
if (!exists) merged.push(lp);
});
saveProfiles(merged.slice(0, MAX_PROFILES));
return getProfiles();
})
.catch(() => getProfiles());
}
module.exports = {
MAX_PROFILES,
getProfiles,
getActiveProfile,
setActiveProfile,
addProfile,
removeProfile,
isLoggedIn,
pushProfileToServer,
removeProfileFromServer,
syncFromServer
};