Files
lunar-mini/mini/pages/bazi/bazi.js
T
gouki 87f5fa2478
Publish Mini Program Dev Version / publish (push) Successful in 1m8s
refactor(mini): 个人中心改为登录+二级菜单结构
- 个人中心仅保留登录管理、我的数据/功能菜单与关于信息
- 新增偏好设置二级页 preferences(原偏好设置统一收敛至此)
- 新增我的收藏二级页 bookmarks,支持删除与跳转日详情
- 生辰管理拆分为二级页 birth-profiles,未登录时提示引导登录
- 八字页入口改为直达生辰管理页;修复 fortune 非 tabBar 页误用 switchTab
2026-08-10 11:52:15 +00:00

154 lines
7.5 KiB
JavaScript

const { birthInfoToBazi, analyzeElementBalance } = require('../../utils/core/index.js');
const birthProfile = require('../../utils/birth-profile.js');
// 空态演示用的示例生辰(虚构,仅作排盘样式展示)
const DEMO_BIRTH = { year: 1990, month: 8, day: 8, hour: 10, minute: 30, gender: 'male', ziSect: 'lateZiNextDay' };
// 五行 → 样式类名
const ELEMENT_CLASS = { '木': 'el-wood', '火': 'el-fire', '土': 'el-earth', '金': 'el-metal', '水': 'el-water' };
// 八字知识词条:逐字段详细说明
const GLOSSARY = [
{ term: '四柱八字', desc: '用天干地支记录出生年、月、日、时的方法,年、月、日、时各一对干支,合称"四柱",共八个字,故称"八字"。它源于古代干支纪时体系,是传统历法文化的一部分。' },
{ term: '天干地支', desc: '天干共十个(甲乙丙丁戊己庚辛壬癸),地支共十二个(子丑寅卯辰巳午未申酉戌亥),是古人用于纪年、纪月、纪日、纪时的符号系统,也是传统历法的基础。' },
{ term: '年柱', desc: '出生年份的干支。传统上以立春为界划分年份(立春前出生按上一年)。年柱在民俗说法中对应祖辈与少年时期。' },
{ term: '月柱', desc: '出生月份的干支。月份以节气划分(如立春至惊蛰为正月),并非公历或农历的自然月。民俗说法中对应父母与青年时期。' },
{ term: '日柱', desc: '出生当日的干支,按六十甲子循环纪日。日柱的天干代表本人(日主),是整个命盘分析的核心。' },
{ term: '时柱', desc: '出生时辰的干支。古人将一昼夜分为十二个时辰,每个时辰合今两小时(如子时为 23:00-01:00)。' },
{ term: '日主', desc: '日柱的天干,代表命主本人。日主的五行属性(木火土金水)是分析命盘五行强弱与十神关系的出发点。' },
{ term: '十神', desc: '以日主为参照,按五行生克关系对其他干支的十种称谓:比肩、劫财、食神、伤官、偏财、正财、七杀、正官、偏印、正印。它是古代的一种关系分类符号,用于描述干支之间的生克比和。' },
{ term: '五行', desc: '木、火、土、金、水五种基本元素,源于古代哲学,认为万物由五行构成并相生相克(木生火、火生土、土生金、金生水、水生木;木克土、土克水、水克火、火克金、金克木)。五行分析统计八字中各元素的数量与强弱。' },
{ term: '藏干', desc: '又称"人元",指每个地支内部按传统规则所含的一个至三个天干。例如寅中藏甲、丙、戊。排盘时作为辅助信息列出。' },
{ term: '纳音', desc: '将六十甲子两两配对归入五行所得的三十种称谓,如"甲子乙丑海中金"、"丙寅丁卯炉中火"。年命纳音(年柱纳音)在民俗中常被用来称呼人的"命",如"金命"、"火命"。' },
{ term: '空亡', desc: '六十甲子分为六旬,每旬十个干支配十二地支,余下两个地支无天干相配,称为该旬"空亡"。这是干支纪法本身的结构性概念,此处仅作历法知识展示。' },
{ term: '大运', desc: '传统上以月柱为基础、按十年一换的节奏推演出的干支序列,用来描述人生不同阶段的节律。属于传统民俗推演方法,供文化了解。' },
{ term: '流年', desc: '即每一年的干支(如 2026 年为丙午年)。传统做法将流年与本命干支对照,观察逐年的变化关系。' },
{ term: '子时流派', desc: '子时(23:00-01:00)横跨两天,晚子时(23:00-24:00)出生者的日柱按当天还是次日起算,历代流派说法不一。可在"我的-设置"中选择。' }
];
/** 根据出生信息构建排盘展示数据 */
function buildChart({ year, month, day, hour, minute, gender, ziSect }) {
const bazi = birthInfoToBazi({ year, month, day, hour, minute, gender, ziSect });
const elementAnalysis = analyzeElementBalance(bazi.eightChar);
const pillars = [
{ label: '年柱', ...bazi.eightChar.yearPillar },
{ label: '月柱', ...bazi.eightChar.monthPillar },
{ label: '日柱', ...bazi.eightChar.dayPillar },
{ label: '时柱', ...bazi.eightChar.hourPillar }
].map(p => ({
label: p.label,
ganzhi: p.ganzhi,
tenStar: p.tenStar || '日主',
heavenStem: p.heavenStem,
earthBranch: p.earthBranch,
stemClass: ELEMENT_CLASS[p.elementStem] || '',
branchClass: ELEMENT_CLASS[p.elementBranch] || '',
hideStems: (p.hideStems || []).map(h => h.stem + (h.tenStar ? `(${h.tenStar})` : '')).join(' '),
nayin: p.nayin
}));
const total = elementAnalysis.total || 1;
const elements = [
{ name: '木', count: elementAnalysis.wood, percent: Math.round(elementAnalysis.wood / total * 100), cls: 'el-wood' },
{ name: '火', count: elementAnalysis.fire, percent: Math.round(elementAnalysis.fire / total * 100), cls: 'el-fire' },
{ name: '土', count: elementAnalysis.earth, percent: Math.round(elementAnalysis.earth / total * 100), cls: 'el-earth' },
{ name: '金', count: elementAnalysis.metal, percent: Math.round(elementAnalysis.metal / total * 100), cls: 'el-metal' },
{ name: '水', count: elementAnalysis.water, percent: Math.round(elementAnalysis.water / total * 100), cls: 'el-water' }
];
return { bazi, pillars, elements, elementAnalysis };
}
Page({
data: {
isDemo: true,
profiles: [],
activeProfileId: '',
profile: null,
bazi: null,
pillars: [],
elements: [],
elementAnalysis: {},
glossary: GLOSSARY,
showGlossary: false
},
onShow() {
this.refresh();
},
refresh() {
const render = () => {
const profiles = birthProfile.getProfiles();
if (profiles.length === 0) {
this.showDemo();
} else {
this.showProfile(profiles, birthProfile.getActiveProfile());
}
};
// 已登录时先同步云端档案,失败静默回退本地
if (birthProfile.isLoggedIn()) {
birthProfile.syncFromServer().then(render).catch(render);
} else {
render();
}
},
/** 空态:展示示例排盘 */
showDemo() {
const chart = buildChart(DEMO_BIRTH);
this.setData({
isDemo: true,
profiles: [],
activeProfileId: '',
profile: null,
showGlossary: true,
...chart
});
},
/** 已绑定:展示所选档案的排盘 */
showProfile(profiles, profile) {
if (!profile) return;
const [year, month, day] = profile.birthday.split('-').map(Number);
const [hour, minute] = profile.birthTime.split(':').map(Number);
const settings = wx.getStorageSync('lunar-settings') || {};
const chart = buildChart({
year, month, day, hour, minute,
gender: profile.gender,
ziSect: settings.ziHourSect || 'lateZiNextDay'
});
// 保存八字供运势页使用
wx.setStorageSync('lunar-user-bazi', chart.bazi);
this.setData({
isDemo: false,
profiles,
activeProfileId: profile.id,
profile,
showGlossary: false,
...chart
});
},
selectProfile(e) {
const id = e.currentTarget.dataset.id;
const profile = this.data.profiles.find(p => p.id === id);
if (!profile) return;
birthProfile.setActiveProfile(id);
this.showProfile(this.data.profiles, profile);
},
toggleGlossary() {
this.setData({ showGlossary: !this.data.showGlossary });
},
goSettings() {
wx.navigateTo({ url: '/pages/birth-profiles/birth-profiles' });
},
goFortune() {
wx.navigateTo({ url: '/pages/fortune/fortune' });
}
});