dsh-metaphysics 0.18.3 → 0.19.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +25 -0
- package/README.md +13 -12
- package/client.js +565 -25
- package/engine/almanac.js +137 -3
- package/engine/chenggu.js +74 -4
- package/engine/convert.js +137 -0
- package/engine/geo.js +1 -1
- package/engine/index.js +59 -9
- package/engine/zeri.js +29 -2
- package/index.js +15 -5
- package/locale/en.json +1 -1
- package/locale/zh.json +1 -1
- package/package.json +2 -2
package/client.js
CHANGED
|
@@ -746,7 +746,7 @@ function resolveAddress(input) {
|
|
|
746
746
|
|
|
747
747
|
const DETAIL = /(区|县|镇|乡|村|小区|街道|路|号|巷|弄|组|队)/;
|
|
748
748
|
|
|
749
|
-
const USER_AGENT = 'dsh-metaphysics/0.
|
|
749
|
+
const USER_AGENT = 'dsh-metaphysics/0.19.0 (+https://github.com/xuanfu-web/dsh-metaphysics)';
|
|
750
750
|
|
|
751
751
|
async function onlineLookup(text, { timeoutMs = 2500 } = {}) {
|
|
752
752
|
if (typeof fetch !== 'function') return null;
|
|
@@ -5732,6 +5732,7 @@ return { TRIGRAM, YAO_POSITION, MOVING_NATURE, HEX64, HEX_BY_CORE, ZIWEI_STARS,
|
|
|
5732
5732
|
|
|
5733
5733
|
__mods.almanac = (function () {
|
|
5734
5734
|
const { solarToLunar } = __mods.lunar;
|
|
5735
|
+
const { nayinOf } = __mods.nayin;
|
|
5735
5736
|
const { toJDN, fromJDN, dayGanzhiIndex, ganzhiName, termWindow, termInstantJd, partsToJd, STEMS, BRANCHES, TERM_NAMES } = __mods.calendar;
|
|
5736
5737
|
const { HEX64 } = __mods['interpret-data'];
|
|
5737
5738
|
const { assertCivil, daysInMonth } = __mods.validate;
|
|
@@ -5803,6 +5804,80 @@ function lunarMonthText(month, isLeap = false) {
|
|
|
5803
5804
|
return `${isLeap ? '闰' : ''}${MONTH_TEXT[month - 1] || month}月`;
|
|
5804
5805
|
}
|
|
5805
5806
|
|
|
5807
|
+
const TIAN_SHEN = ['青龙', '明堂', '天刑', '朱雀', '金匮', '天德', '白虎', '玉堂', '天牢', '玄武', '司命', '勾陈'];
|
|
5808
|
+
const TIAN_SHEN_TYPE = {
|
|
5809
|
+
青龙: '黄道', 明堂: '黄道', 金匮: '黄道', 天德: '黄道', 玉堂: '黄道', 司命: '黄道',
|
|
5810
|
+
天刑: '黑道', 朱雀: '黑道', 白虎: '黑道', 天牢: '黑道', 玄武: '黑道', 勾陈: '黑道',
|
|
5811
|
+
};
|
|
5812
|
+
const TIAN_SHEN_OFFSET = { 子: 4, 丑: 2, 寅: 0, 卯: 10, 辰: 8, 巳: 6, 午: 4, 未: 2, 申: 0, 酉: 10, 戌: 8, 亥: 6 };
|
|
5813
|
+
|
|
5814
|
+
function tianShenOf(branch, anchorBranch) {
|
|
5815
|
+
const b = BRANCHES.indexOf(branch);
|
|
5816
|
+
const off = TIAN_SHEN_OFFSET[anchorBranch];
|
|
5817
|
+
if (b < 0 || off == null) return null;
|
|
5818
|
+
const name = TIAN_SHEN[(b + off) % 12];
|
|
5819
|
+
const type = TIAN_SHEN_TYPE[name];
|
|
5820
|
+
return { name, type, luck: type === '黄道' ? '吉' : '凶' };
|
|
5821
|
+
}
|
|
5822
|
+
|
|
5823
|
+
const MANSIONS = {
|
|
5824
|
+
角: { luck: '吉', zheng: '木', animal: '蛟', gong: '东' }, 亢: { luck: '凶', zheng: '金', animal: '龙', gong: '东' },
|
|
5825
|
+
氐: { luck: '凶', zheng: '土', animal: '貉', gong: '东' }, 房: { luck: '吉', zheng: '日', animal: '兔', gong: '东' },
|
|
5826
|
+
心: { luck: '凶', zheng: '月', animal: '狐', gong: '东' }, 尾: { luck: '吉', zheng: '火', animal: '虎', gong: '东' },
|
|
5827
|
+
箕: { luck: '吉', zheng: '水', animal: '豹', gong: '东' }, 斗: { luck: '吉', zheng: '木', animal: '獬', gong: '北' },
|
|
5828
|
+
牛: { luck: '凶', zheng: '金', animal: '牛', gong: '北' }, 女: { luck: '凶', zheng: '土', animal: '蝠', gong: '北' },
|
|
5829
|
+
虚: { luck: '凶', zheng: '日', animal: '鼠', gong: '北' }, 危: { luck: '凶', zheng: '月', animal: '燕', gong: '北' },
|
|
5830
|
+
室: { luck: '吉', zheng: '火', animal: '猪', gong: '北' }, 壁: { luck: '吉', zheng: '水', animal: '獝', gong: '北' },
|
|
5831
|
+
奎: { luck: '凶', zheng: '木', animal: '狼', gong: '西' }, 娄: { luck: '吉', zheng: '金', animal: '狗', gong: '西' },
|
|
5832
|
+
胃: { luck: '吉', zheng: '土', animal: '彘', gong: '西' }, 昴: { luck: '凶', zheng: '日', animal: '鸡', gong: '西' },
|
|
5833
|
+
毕: { luck: '吉', zheng: '月', animal: '乌', gong: '西' }, 觜: { luck: '凶', zheng: '火', animal: '猴', gong: '西' },
|
|
5834
|
+
参: { luck: '吉', zheng: '水', animal: '猿', gong: '西' }, 井: { luck: '吉', zheng: '木', animal: '犴', gong: '南' },
|
|
5835
|
+
鬼: { luck: '凶', zheng: '金', animal: '羊', gong: '南' }, 柳: { luck: '凶', zheng: '土', animal: '獐', gong: '南' },
|
|
5836
|
+
星: { luck: '凶', zheng: '日', animal: '马', gong: '南' }, 张: { luck: '吉', zheng: '月', animal: '鹿', gong: '南' },
|
|
5837
|
+
翼: { luck: '凶', zheng: '火', animal: '蛇', gong: '南' }, 轸: { luck: '吉', zheng: '水', animal: '蚓', gong: '南' },
|
|
5838
|
+
};
|
|
5839
|
+
const XIU_GROUPS = {
|
|
5840
|
+
A: ['虚', '毕', '翼', '箕', '奎', '鬼', '氐'],
|
|
5841
|
+
B: ['房', '危', '觜', '轸', '斗', '娄', '柳'],
|
|
5842
|
+
C: ['星', '心', '室', '参', '角', '牛', '胃'],
|
|
5843
|
+
D: ['昴', '张', '尾', '壁', '井', '亢', '女'],
|
|
5844
|
+
};
|
|
5845
|
+
const XIU_GROUP_OF = { 子: 'A', 辰: 'A', 申: 'A', 丑: 'B', 巳: 'B', 酉: 'B', 寅: 'C', 午: 'C', 戌: 'C', 卯: 'D', 未: 'D', 亥: 'D' };
|
|
5846
|
+
|
|
5847
|
+
function xiuOf(dayBranch, weekdayIndex) {
|
|
5848
|
+
const g = XIU_GROUP_OF[dayBranch];
|
|
5849
|
+
if (!g) return null;
|
|
5850
|
+
const name = XIU_GROUPS[g][weekdayIndex];
|
|
5851
|
+
const info = MANSIONS[name];
|
|
5852
|
+
return info ? { name, ...info } : null;
|
|
5853
|
+
}
|
|
5854
|
+
|
|
5855
|
+
const DIR_OF = { 坎: '正北', 艮: '东北', 震: '正东', 巽: '东南', 离: '正南', 坤: '西南', 兑: '正西', 乾: '西北' };
|
|
5856
|
+
const POS_XI = { 甲: '艮', 乙: '乾', 丙: '坤', 丁: '离', 戊: '巽', 己: '艮', 庚: '乾', 辛: '坤', 壬: '离', 癸: '巽' };
|
|
5857
|
+
const POS_CAI = { 甲: '艮', 乙: '艮', 丙: '坤', 丁: '坤', 戊: '坎', 己: '坎', 庚: '震', 辛: '震', 壬: '离', 癸: '离' };
|
|
5858
|
+
const POS_FU = { 甲: '坎', 乙: '坤', 丙: '乾', 丁: '巽', 戊: '艮', 己: '坎', 庚: '坤', 辛: '乾', 壬: '巽', 癸: '艮' };
|
|
5859
|
+
const POS_YANG_GUI = { 甲: '坤', 乙: '坤', 丙: '兑', 丁: '乾', 戊: '艮', 己: '坎', 庚: '离', 辛: '艮', 壬: '震', 癸: '巽' };
|
|
5860
|
+
const POS_YIN_GUI = { 甲: '艮', 乙: '坎', 丙: '乾', 丁: '兑', 戊: '坤', 己: '坤', 庚: '艮', 辛: '离', 壬: '巽', 癸: '震' };
|
|
5861
|
+
const posOf = (map, stem) => (map[stem] ? { gua: map[stem], dir: DIR_OF[map[stem]] } : null);
|
|
5862
|
+
|
|
5863
|
+
const TAI_SHEN = {
|
|
5864
|
+
甲子: '占门碓 外东南', 乙丑: '碓磨厕 外东南', 丙寅: '厨灶炉 外正南', 丁卯: '仓库门 外正南', 戊辰: '房床栖 外正南',
|
|
5865
|
+
己巳: '占门床 外正南', 庚午: '占碓磨 外正南', 辛未: '厨灶厕 外西南', 壬申: '仓库炉 外西南', 癸酉: '房床门 外西南',
|
|
5866
|
+
甲戌: '占门栖 外西南', 乙亥: '碓磨床 外西南', 丙子: '厨灶碓 外西南', 丁丑: '仓库厕 外正西', 戊寅: '房床炉 外正西',
|
|
5867
|
+
己卯: '占大门 外正西', 庚辰: '碓磨栖 外正西', 辛巳: '厨灶床 外正西', 壬午: '仓库碓 外西北', 癸未: '房床厕 外西北',
|
|
5868
|
+
甲申: '占门炉 外西北', 乙酉: '碓磨门 外西北', 丙戌: '厨灶栖 外西北', 丁亥: '仓库床 外西北', 戊子: '房床碓 外正北',
|
|
5869
|
+
己丑: '占门厕 外正北', 庚寅: '碓磨炉 外正北', 辛卯: '厨灶门 外正北', 壬辰: '仓库栖 外正北', 癸巳: '占房床 房内北',
|
|
5870
|
+
甲午: '占门碓 房内北', 乙未: '碓磨厕 房内北', 丙申: '厨灶炉 房内北', 丁酉: '仓库门 房内北', 戊戌: '房床栖 房内中',
|
|
5871
|
+
己亥: '占门床 房内中', 庚子: '占碓磨 房内南', 辛丑: '厨灶厕 房内南', 壬寅: '仓库炉 房内南', 癸卯: '房床门 房内西',
|
|
5872
|
+
甲辰: '占门栖 房内东', 乙巳: '碓磨床 房内东', 丙午: '厨灶碓 房内东', 丁未: '仓库厕 房内东', 戊申: '房床炉 房内中',
|
|
5873
|
+
己酉: '占大门 外东北', 庚戌: '碓磨栖 外东北', 辛亥: '厨灶床 外东北', 壬子: '仓库碓 外东北', 癸丑: '房床厕 外东北',
|
|
5874
|
+
甲寅: '占门炉 外东北', 乙卯: '碓磨门 外正东', 丙辰: '厨灶栖 外正东', 丁巳: '仓库床 外正东', 戊午: '房床碓 外正东',
|
|
5875
|
+
己未: '占门厕 外正东', 庚申: '碓磨炉 外东南', 辛酉: '厨灶门 外东南', 壬戌: '仓库栖 外东南', 癸亥: '占房床 外东南',
|
|
5876
|
+
};
|
|
5877
|
+
|
|
5878
|
+
const LIUHE = { 子: '丑', 丑: '子', 寅: '亥', 亥: '寅', 卯: '戌', 戌: '卯', 辰: '酉', 酉: '辰', 巳: '申', 申: '巳', 午: '未', 未: '午' };
|
|
5879
|
+
const SANHE = { 申: '申子辰', 子: '申子辰', 辰: '申子辰', 亥: '亥卯未', 卯: '亥卯未', 未: '亥卯未', 寅: '寅午戌', 午: '寅午戌', 戌: '寅午戌', 巳: '巳酉丑', 酉: '巳酉丑', 丑: '巳酉丑' };
|
|
5880
|
+
|
|
5806
5881
|
function dailyHexagram(year, month, day) {
|
|
5807
5882
|
const names = Object.keys(HEX64);
|
|
5808
5883
|
if (!names.length) return null;
|
|
@@ -5858,7 +5933,41 @@ function buildAlmanac(input) {
|
|
|
5858
5933
|
return `${p.year}-${String(p.month).padStart(2, '0')}-${String(p.day).padStart(2, '0')}`;
|
|
5859
5934
|
};
|
|
5860
5935
|
|
|
5861
|
-
const
|
|
5936
|
+
const weekdayIdx = (jdn + 1) % 7;
|
|
5937
|
+
const weekday = ['日', '一', '二', '三', '四', '五', '六'][weekdayIdx];
|
|
5938
|
+
const dayGod = tianShenOf(dayBranch, BRANCHES[monthBranchIdx]);
|
|
5939
|
+
const xiu = xiuOf(dayBranch, weekdayIdx);
|
|
5940
|
+
const taiShen = TAI_SHEN[dayGz.name] || null;
|
|
5941
|
+
const hourBase = (STEMS.indexOf(dayGz.stem) % 5) * 2;
|
|
5942
|
+
const hours = BRANCHES.map((zhi, i) => {
|
|
5943
|
+
const gan = STEMS[(hourBase + i) % 10];
|
|
5944
|
+
const gz = ganzhiName(hourComposite((hourBase + i) % 10, i));
|
|
5945
|
+
const shen = tianShenOf(zhi, dayBranch);
|
|
5946
|
+
return {
|
|
5947
|
+
zhi,
|
|
5948
|
+
name: `${zhi}时`,
|
|
5949
|
+
ganZhi: gz.name,
|
|
5950
|
+
gan,
|
|
5951
|
+
shen: shen ? shen.name : null,
|
|
5952
|
+
type: shen ? shen.type : null,
|
|
5953
|
+
luck: shen ? shen.luck : null,
|
|
5954
|
+
};
|
|
5955
|
+
});
|
|
5956
|
+
const sanheGroup = SANHE[dayBranch] || '';
|
|
5957
|
+
const liuheBranch = LIUHE[dayBranch] || null;
|
|
5958
|
+
const lucky = {
|
|
5959
|
+
liuhe: liuheBranch ? SHENGXIAO[BRANCHES.indexOf(liuheBranch)] : null,
|
|
5960
|
+
sanhe: [...sanheGroup].filter((b) => b !== dayBranch).map((b) => SHENGXIAO[BRANCHES.indexOf(b)]),
|
|
5961
|
+
};
|
|
5962
|
+
const positions = {
|
|
5963
|
+
caiShen: CAI_SHEN[dayGz.stem] || null,
|
|
5964
|
+
xiShen: XI_SHEN[dayGz.stem] || null,
|
|
5965
|
+
fuShen: posOf(POS_FU, dayGz.stem),
|
|
5966
|
+
yangGui: posOf(POS_YANG_GUI, dayGz.stem),
|
|
5967
|
+
yinGui: posOf(POS_YIN_GUI, dayGz.stem),
|
|
5968
|
+
xiShenFull: posOf(POS_XI, dayGz.stem),
|
|
5969
|
+
caiShenFull: posOf(POS_CAI, dayGz.stem),
|
|
5970
|
+
};
|
|
5862
5971
|
const lunarText = `农历${springGz.name}年${lunarMonthText(lunar.month, lunar.isLeap)}${dayText(lunar.day)}`;
|
|
5863
5972
|
const boundaryNote = yearGz.name !== springGz.name
|
|
5864
5973
|
? `年界:本条按立春界作${yearGz.name}年·属${SHENGXIAO[BRANCHES.indexOf(yearGz.branch)]}(命理排盘用);春节界为${springGz.name}年·属${SHENGXIAO[BRANCHES.indexOf(springGz.branch)]},两种都对,取用场合不同`
|
|
@@ -5870,7 +5979,7 @@ function buildAlmanac(input) {
|
|
|
5870
5979
|
date: `${year}-${String(month).padStart(2, '0')}-${String(day).padStart(2, '0')}`,
|
|
5871
5980
|
weekday: `星期${weekday}`,
|
|
5872
5981
|
...(boundaryNote ? { boundaryNote } : {}),
|
|
5873
|
-
scope: '
|
|
5982
|
+
scope: '通行口径:宜忌按建除十二神简表;已收录值日十二神(黄道/黑道)、时辰吉凶、二十八宿、胎神、吉神方位、纳音、六合三合吉配;逐日全量吉神凶煞与彭祖百忌未收录',
|
|
5874
5983
|
},
|
|
5875
5984
|
lunar: {
|
|
5876
5985
|
year: springYear,
|
|
@@ -5891,7 +6000,13 @@ function buildAlmanac(input) {
|
|
|
5891
6000
|
prev: prevTerm ? { name: termName(prevTerm), date: fmtJdDate(prevTerm.jd) } : null,
|
|
5892
6001
|
next: nextTerm ? { name: termName(nextTerm), date: fmtJdDate(nextTerm.jd) } : null,
|
|
5893
6002
|
},
|
|
5894
|
-
positions
|
|
6003
|
+
positions,
|
|
6004
|
+
dayGod,
|
|
6005
|
+
xiu,
|
|
6006
|
+
taiShen,
|
|
6007
|
+
nayin: { day: nayinOf(dayGanzhiIndex(jdn)) },
|
|
6008
|
+
lucky,
|
|
6009
|
+
hours,
|
|
5895
6010
|
zhiXing,
|
|
5896
6011
|
yi: ZHIXING_YI[zhiXing].slice(),
|
|
5897
6012
|
ji: ZHIXING_JI[zhiXing].slice(),
|
|
@@ -5904,6 +6019,7 @@ function buildAlmanac(input) {
|
|
|
5904
6019
|
sources: [
|
|
5905
6020
|
'农历与节气:本地天文历法(定朔 + 节气黄经)',
|
|
5906
6021
|
'建除十二神与冲煞:传统通行口径',
|
|
6022
|
+
'值日/时家十二神(青龙…勾陈)、二十八宿、胎神、吉神方位:通行表',
|
|
5907
6023
|
'宜忌:建除十二神通行简表(非逐日全量黄历)',
|
|
5908
6024
|
'每日一卦:按公历日期确定性取卦(同日同卦)',
|
|
5909
6025
|
],
|
|
@@ -5918,7 +6034,14 @@ function monthComposite(stemIdx, branchIdx) {
|
|
|
5918
6034
|
return 0;
|
|
5919
6035
|
}
|
|
5920
6036
|
|
|
5921
|
-
|
|
6037
|
+
function hourComposite(stemIdx, branchIdx) {
|
|
6038
|
+
for (let i = 0; i < 60; i++) {
|
|
6039
|
+
if (i % 10 === stemIdx && i % 12 === branchIdx) return i;
|
|
6040
|
+
}
|
|
6041
|
+
return 0;
|
|
6042
|
+
}
|
|
6043
|
+
|
|
6044
|
+
return { ZHIXING, ZHIXING_YI, ZHIXING_JI, SHENGXIAO, hourToBranch, zhixingOf, lunarMonthText, TIAN_SHEN, TIAN_SHEN_TYPE, tianShenOf, MANSIONS, xiuOf, dailyHexagram, buildAlmanac };
|
|
5922
6045
|
})();
|
|
5923
6046
|
|
|
5924
6047
|
__mods.star = (function () {
|
|
@@ -6108,6 +6231,65 @@ function lunarMonthText(month, isLeap = false) {
|
|
|
6108
6231
|
return `${isLeap ? '闰' : ''}${MONTH_TEXT[month - 1] || month}月`;
|
|
6109
6232
|
}
|
|
6110
6233
|
|
|
6234
|
+
const CHENGGU_SONG = {
|
|
6235
|
+
21: { text: '短命非业谓大空,平生灾难事重重;凶祸频临陷逆境,终世困苦事不成。', plain: '起点低、阻力大,凡事难一气呵成;宜守稳借力,不宜孤注一掷。' },
|
|
6236
|
+
22: { text: '身寒骨冷苦伶仃,此命推来行乞人;劳劳碌碌无度日,终年打拱过平生。', plain: '早年资源薄、亲缘淡,靠勤苦与人缘翻身,最忌自弃。' },
|
|
6237
|
+
23: { text: '此命推来骨格轻,求谋作事事难成;妻儿兄弟应难许,别处他乡作散人。', plain: '独自谋事难成,宜合伙或依附平台;离乡发展反有出路。' },
|
|
6238
|
+
24: { text: '此命推来福禄无,门庭困苦总难荣;六亲骨肉皆无靠,流浪他乡作老翁。', plain: '六亲助力少,别指望祖业,早做打算、靠双手积累。' },
|
|
6239
|
+
25: { text: '此命推来祖业微,门庭营度似稀奇;六亲骨肉如冰炭,一世勤劳自把持。', plain: '家底薄、亲缘冷,一生靠自己操持,勤俭则安。' },
|
|
6240
|
+
26: { text: '平生衣禄苦中求,独自营谋事不休;离祖出门宜早计,晚来衣禄自无休。', plain: '白手起家之格:早离乡、晚渐稳,不必怕慢。' },
|
|
6241
|
+
27: { text: '一生作事少商量,难靠祖宗作主张;独马单枪空做去,早年晚岁总无长。', plain: '主意要自己拿,靠人不如靠己;早定方向才不空忙。' },
|
|
6242
|
+
28: { text: '一生行事似飘蓬,祖宗产业在梦中;若不过房改名姓,也当移徒二三通。', plain: '祖业难守,适合外出或改换环境,动中求安。' },
|
|
6243
|
+
29: { text: '初年运限未曾亨,纵有功名在后成;须过四旬才可立,移居改姓始为良。', plain: '功名在后,四十前后才立得住,忌中途频繁换道。' },
|
|
6244
|
+
30: { text: '劳劳碌碌苦中求,东奔西走何日休;若使终身勤与俭,老来稍可免忧愁。', plain: '东奔西走的劳碌格,靠勤俭积攒,晚年才得清闲。' },
|
|
6245
|
+
31: { text: '忙忙碌碌苦中求,何日云开见日头;难得祖基家可立,中年衣食渐无忧。', plain: '先难后易:祖基难得,中年衣食转宽,守住本业即可。' },
|
|
6246
|
+
32: { text: '初年运蹇事难谋,渐有财源如水流;到得中年衣食旺,那时名利一齐收。', plain: '幼年蹇滞,中年后财源渐旺,名利可期。' },
|
|
6247
|
+
33: { text: '早年做事事难成,百年勤劳枉费心;半世自如流水去,后来运到始得金。', plain: '前半程多试错,后半程才见成果,急不得。' },
|
|
6248
|
+
34: { text: '此命福气果如何,僧道门中衣禄多;离祖出家方为妙,朝晚拜佛念弥陀。', plain: '与清静行当、宗教或专门技艺有缘,离祖发展更顺。' },
|
|
6249
|
+
35: { text: '生平福量不周全,祖业根基觉少传;营事生涯宜守旧,时来衣食胜从前。', plain: '福量不齐,宜守旧业、少折腾;时运到了自然宽裕。' },
|
|
6250
|
+
36: { text: '不须劳碌过平生,独自成家福不轻;早有福星常照命,任君行去百般成。', plain: '不必太劳碌,福气随身,行事多能成。' },
|
|
6251
|
+
37: { text: '此命般般事不成,弟兄少力自孤行;虽然祖业须微有,来得明时去不明。', plain: '单打独斗吃力、兄弟少力;宜合作,钱财要明算账。' },
|
|
6252
|
+
38: { text: '一身骨肉最清高,早入簧门姓氏标;待到年将三十六,蓝衫脱去换红袍。', plain: '读书与专业路线见长,三十六前后有转机与体面。' },
|
|
6253
|
+
39: { text: '此命终身运不通,劳劳作事尽皆空;苦心竭力成家计,到得那时在梦中。', plain: '早年空忙,成家立业偏晚;重在坚持,不宜频繁改行。' },
|
|
6254
|
+
40: { text: '平生衣禄是绵长,件件心中自主张;前面风霜多受过,后来必定享安康。', plain: '先苦后甜:衣食渐稳,事在自主,晚景安康。' },
|
|
6255
|
+
41: { text: '此命推来自不同,为人能干异凡庸;中年还有逍遥福,不比前时运来通。', plain: '能干出众,早年只是运会未到;中年有逍遥之福。' },
|
|
6256
|
+
42: { text: '得宽怀处且宽怀,何用双眉皱不开;若使中年命运济,那时名利一起来。', plain: '心宽则顺;中年运济,名利自来,不必过虑。' },
|
|
6257
|
+
43: { text: '为人心性最聪明,作事轩昂近贵人;衣禄一生天注定,不须劳碌是丰亨。', plain: '聪明近贵,易得贵人提携,衣禄有天定之说。' },
|
|
6258
|
+
44: { text: '万事由天莫苦求,须知福碌赖人修;当年财帛难如意,晚景欣然便不优。', plain: '少壮难如意,晚景反安;福禄也靠人修,不必强求。' },
|
|
6259
|
+
45: { text: '名利推求竟若何,前番辛苦后奔波;命中难养男和女,骨肉扶持也不多。', plain: '中年前后仍奔波,子女缘与骨肉助力偏薄,凡事多自扛。' },
|
|
6260
|
+
46: { text: '东西南北尽皆通,出姓移居更觉隆;衣禄无穷无数定,中年晚景一般同。', plain: '外出、迁居更旺;衣禄不愁,中晚年境况相近。' },
|
|
6261
|
+
47: { text: '此命推求旺末年,妻荣子贵自怡然;平生原有滔滔福,可卜财源若水泉。', plain: '晚运佳:妻荣子贵,福厚财源长。' },
|
|
6262
|
+
48: { text: '初年运道未曾通,几许蹉跎命亦穷;兄弟六亲无依靠,一生事业晚来整。', plain: '早年蹉跎、六亲少靠,事业晚成,忌半途而废。' },
|
|
6263
|
+
49: { text: '此命推来福不轻,自成自立显门庭;从来富贵人钦敬,使婢差奴过一生。', plain: '自立门户、显耀门庭,中年后受人敬重。' },
|
|
6264
|
+
50: { text: '为利为名终日劳,中年福禄也多遭;老来自有财星照,不比前番目下高。', plain: '为名利终日奔忙,中年多波折;老来财星照,压力渐轻。' },
|
|
6265
|
+
51: { text: '一世荣华事事通,不须劳碌自亨通;兄弟叔侄皆如意,家业成时福禄宏。', plain: '事多顺遂,兄弟叔侄得力,家业易成。' },
|
|
6266
|
+
52: { text: '一世亨通事事能,不须劳苦自然宁;宗族有光欣喜甚,家产丰盈自称心。', plain: '诸事能干、少劳而宁;宗族有光,家产丰盈。' },
|
|
6267
|
+
53: { text: '此格推来福泽宏,兴家立业在其中;一生衣食安排定,却是人间一福翁。', plain: '兴家立业之格,衣食安稳,是人间有福之人。' },
|
|
6268
|
+
54: { text: '此格详采福泽宏,诗书满腹看功成;丰衣足食多安稳,正是人间有福人。', plain: '读书人格局:功名可期,衣食安稳。' },
|
|
6269
|
+
55: { text: '策马扬鞭争名利,少年作事费筹论;一朝福禄源源至,富贵荣华显六亲。', plain: '少年费筹谋,一朝福至;富贵显亲,属于厚积薄发。' },
|
|
6270
|
+
56: { text: '此格推来礼义通,一身福禄用无穷;甜酸苦辣皆尝过,滚滚财源盈而丰。', plain: '福禄厚:人生百味都经过,之后财源稳而丰。' },
|
|
6271
|
+
57: { text: '福禄丰盈万事全,一身荣耀乐天年;名扬威震人争羡,此世逍遥宛似仙。', plain: '万事较全,名望与荣耀随行,晚运逍遥。' },
|
|
6272
|
+
58: { text: '平生衣食自然来,名利双全富贵偕;金榜题名登甲第,紫袍玉带走金阶。', plain: '衣食自来、名利双全;有科第与体面之象。' },
|
|
6273
|
+
59: { text: '细推此格秀而清,必定才高学业成;甲第之中应有分,扬鞭走马显威荣。', plain: '才高学业成,有科第之份,前程显达。' },
|
|
6274
|
+
60: { text: '一朝金榜快题名,显祖荣宗大器成;衣禄定然无欠缺,田园财帛更丰盈。', plain: '金榜题名、显祖荣宗;衣禄丰足,田园财帛皆旺。' },
|
|
6275
|
+
61: { text: '不作朝中金榜客,定为世上大财翁;聪明天付经书熟,名显高褂自是荣。', plain: '不入仕途也能成富;聪明博学,自有显名之荣。' },
|
|
6276
|
+
62: { text: '此命生来福不穷,读书必定显亲宗;紫衣玉带为卿相,富贵荣华孰与同。', plain: '福泽不穷;读书可显亲,有卿相之象。' },
|
|
6277
|
+
63: { text: '命主为官福禄长,得来富贵实非常;名题雁塔传金榜,大显门庭天下扬。', plain: '仕途顺、福禄长;富贵非常,门庭显扬。' },
|
|
6278
|
+
64: { text: '此格威权不可当,紫袍金带尘高堂;荣华富贵谁能及,万古留名姓氏扬。', plain: '掌权之格:富贵与声名俱隆,留名后世。' },
|
|
6279
|
+
65: { text: '细推此命福非轻,富贵荣华孰与争;定国安邦人极品,威声显赫震寰瀛。', plain: '贵重之命;有定国安邦之器,声威远震。' },
|
|
6280
|
+
66: { text: '此格人间一福人,堆金积玉满堂春;从来富贵有天定,金榜题名更显亲。', plain: '堆金积玉、富贵天定;又有金榜显亲之象。' },
|
|
6281
|
+
67: { text: '此命生来福自宏,田园家业最高隆;平生衣禄盈丰足,一路荣华万事通。', plain: '福厚家隆:田园家业兴旺,衣禄丰足,一路荣华。' },
|
|
6282
|
+
68: { text: '富贵由天莫苦求,万事家计不须谋;十年不比前番事,祖业根基千古留。', plain: '家计不必苦谋;祖业根基可留,运势比前十年更好。' },
|
|
6283
|
+
69: { text: '君是人间福禄星,一生富贵众人钦;总然衣禄由天定,安享荣华过一生。', plain: '人间福禄星:富贵受人钦敬,安享荣华。' },
|
|
6284
|
+
70: { text: '此命推来福不轻,何须愁虑苦劳心;荣华富贵已天定,正笏垂绅拜紫宸。', plain: '不必愁虑劳心;荣华富贵已定,有朝堂之象。' },
|
|
6285
|
+
71: { text: '此命生成大不同,公侯卿相在其中;一生自有逍遥福,富贵荣华极品隆。', plain: '公侯卿相之格:福厚逍遥,富贵极品。' },
|
|
6286
|
+
72: { text: '此命推来天下隆,必定人间一主公;富贵荣华数不尽,定为乾坤一蛟龙。', plain: '极贵之格;但四表上限为七两一钱,此档基本不可达,仅备档。' },
|
|
6287
|
+
};
|
|
6288
|
+
|
|
6289
|
+
function songOf(qian) {
|
|
6290
|
+
return CHENGGU_SONG[qian] || null;
|
|
6291
|
+
}
|
|
6292
|
+
|
|
6111
6293
|
function bandVerdict(qian) {
|
|
6112
6294
|
if (qian >= 55) return { band: '上上', text: '骨重沉实,根基深厚,一生多逢贵人,谋事易成;守正持重,福泽可久。' };
|
|
6113
6295
|
if (qian >= 45) return { band: '上', text: '骨重充实,中年前后渐入佳境,事业家宅两旺;忌骄忌躁,善守即善成。' };
|
|
@@ -6139,6 +6321,7 @@ function buildChenggu(input) {
|
|
|
6139
6321
|
}
|
|
6140
6322
|
const total = wYear + wMonth + wDay + wHour;
|
|
6141
6323
|
const verdict = bandVerdict(total);
|
|
6324
|
+
const song = songOf(total);
|
|
6142
6325
|
const jdn = toJDN(year, month, day);
|
|
6143
6326
|
|
|
6144
6327
|
return {
|
|
@@ -6161,15 +6344,19 @@ function buildChenggu(input) {
|
|
|
6161
6344
|
},
|
|
6162
6345
|
total: { qian: total, label: formatWeight(total) },
|
|
6163
6346
|
verdict,
|
|
6347
|
+
song: song
|
|
6348
|
+
? { qian: total, label: formatWeight(total), title: `称骨歌·${formatWeight(total)}`, text: song.text, plain: song.plain, source: '通行本《称骨歌》' }
|
|
6349
|
+
: { qian: total, label: formatWeight(total), title: `称骨歌·${formatWeight(total)}`, text: '', plain: '该骨重未见通行本歌诀(表内应落在二两一钱至七两二钱之间)。', source: '通行本《称骨歌》' },
|
|
6164
6350
|
sources: [
|
|
6165
6351
|
'骨重表:通行本袁天罡称骨(六十甲子年 / 十二月 / 三十日 / 十二时辰)',
|
|
6166
|
-
'
|
|
6352
|
+
'歌诀:通行本《称骨歌》原文照录(各版本有异文,断句标点已统一)',
|
|
6353
|
+
'释义:白话自撰,非歌诀原文,只作字面直解',
|
|
6167
6354
|
],
|
|
6168
|
-
disclaimer: '
|
|
6355
|
+
disclaimer: '骨重与歌诀均为通行本口径,属民俗娱乐参考;释义为白话解释,不构成命运断言。',
|
|
6169
6356
|
};
|
|
6170
6357
|
}
|
|
6171
6358
|
|
|
6172
|
-
return { YEAR_WEIGHT, MONTH_WEIGHT, DAY_WEIGHT, HOUR_WEIGHT, formatWeight, lunarDayText, lunarMonthText, buildChenggu };
|
|
6359
|
+
return { YEAR_WEIGHT, MONTH_WEIGHT, DAY_WEIGHT, HOUR_WEIGHT, formatWeight, lunarDayText, lunarMonthText, CHENGGU_SONG, songOf, buildChenggu };
|
|
6173
6360
|
})();
|
|
6174
6361
|
|
|
6175
6362
|
__mods.xiaoliuren = (function () {
|
|
@@ -6240,26 +6427,52 @@ const { buildAlmanac, SHENGXIAO } = __mods.almanac;
|
|
|
6240
6427
|
const TASKS = {
|
|
6241
6428
|
嫁娶: { yi: ['嫁娶', '结亲', '订盟', '纳采'], related: ['会亲友', '裁衣'], category: 'marriage' },
|
|
6242
6429
|
订婚: { yi: ['订盟', '纳采'], related: ['嫁娶', '会亲友'], category: 'marriage' },
|
|
6430
|
+
领证: { yi: ['嫁娶', '纳采'], related: ['订盟', '会亲友'], category: 'marriage' },
|
|
6431
|
+
提亲: { yi: ['纳采', '订盟'], related: ['会亲友'], category: 'marriage' },
|
|
6432
|
+
收送聘金: { yi: ['纳采', '订盟'], related: ['嫁娶'], category: 'marriage' },
|
|
6433
|
+
满月酒: { yi: ['祭祀', '祈福'], related: ['会亲友'], category: 'celebration' },
|
|
6243
6434
|
开业: { yi: ['开市', '立券', '交易'], related: ['纳财', '挂匾'], category: 'business' },
|
|
6435
|
+
交易: { yi: ['交易', '立券'], related: ['开市', '纳财'], category: 'business' },
|
|
6436
|
+
投资: { yi: ['纳财', '交易'], related: ['立券'], category: 'business' },
|
|
6437
|
+
签订合同: { yi: ['立券', '交易'], related: ['纳财', '开市'], category: 'contract' },
|
|
6438
|
+
签约: { yi: ['立券', '交易'], related: ['纳财', '开市'], category: 'contract' },
|
|
6439
|
+
纳财: { yi: ['纳财', '收账'], related: ['开市', '立券'], category: 'contract' },
|
|
6244
6440
|
入宅: { yi: ['入宅', '移徙'], related: ['安床', '修造', '扫舍'], category: 'move' },
|
|
6245
6441
|
搬家: { yi: ['移徙', '入宅'], related: ['安床', '修造'], category: 'move' },
|
|
6442
|
+
搬家入宅: { yi: ['入宅', '移徙'], related: ['安床', '扫舍'], category: 'move' },
|
|
6246
6443
|
动土: { yi: ['动土', '修造'], related: ['竖柱', '上梁'], category: 'construction' },
|
|
6247
6444
|
装修: { yi: ['修造', '修饰垣墙'], related: ['动土'], category: 'construction' },
|
|
6445
|
+
装修建造: { yi: ['修造', '动土'], related: ['竖柱', '上梁'], category: 'construction' },
|
|
6446
|
+
试车买车: { yi: ['交易', '纳财'], related: ['出行'], category: 'purchase' },
|
|
6248
6447
|
安葬: { yi: ['安葬', '破土'], related: ['立碑', '埋穴'], category: 'burial' },
|
|
6249
6448
|
出行: { yi: ['出行'], related: ['上任', '赴任'], category: 'travel' },
|
|
6449
|
+
旅行: { yi: ['出行'], related: ['上任', '赴任'], category: 'travel' },
|
|
6450
|
+
赴任: { yi: ['上任', '赴任'], related: ['出行'], category: 'travel' },
|
|
6451
|
+
访亲友: { yi: ['会亲友'], related: ['出行'], category: 'visit' },
|
|
6452
|
+
入学: { yi: ['入学'], related: ['开市', '修造'], category: 'study' },
|
|
6250
6453
|
祭祀: { yi: ['祭祀'], related: ['祈福', '求嗣'], category: 'worship' },
|
|
6251
|
-
签约: { yi: ['立券', '交易'], related: ['纳财', '开市'], category: 'contract' },
|
|
6252
6454
|
求医: { yi: ['求医', '疗病'], related: ['针灸'], category: 'medical' },
|
|
6253
|
-
|
|
6455
|
+
};
|
|
6456
|
+
|
|
6457
|
+
const TASK_GROUPS = {
|
|
6458
|
+
常用: ['嫁娶', '搬家入宅', '出行', '开业', '签订合同', '祭祀'],
|
|
6459
|
+
婚嫁: ['嫁娶', '订婚', '领证', '提亲', '收送聘金', '满月酒'],
|
|
6460
|
+
生活: ['搬家', '入宅', '旅行', '访亲友', '入学', '求医', '祭祀'],
|
|
6461
|
+
建造: ['动土', '装修', '装修建造', '安葬', '试车买车'],
|
|
6462
|
+
工商: ['开业', '交易', '投资', '签订合同', '签约', '纳财', '赴任'],
|
|
6254
6463
|
};
|
|
6255
6464
|
|
|
6256
6465
|
const ZHIXING_FAVOR = {
|
|
6257
6466
|
marriage: ['满', '定', '成', '开'],
|
|
6467
|
+
celebration: ['满', '成', '开', '平'],
|
|
6258
6468
|
business: ['开', '成', '满', '收'],
|
|
6259
6469
|
move: ['定', '成', '开', '除'],
|
|
6260
6470
|
construction: ['建', '除', '成', '开'],
|
|
6471
|
+
purchase: ['成', '开', '满'],
|
|
6261
6472
|
burial: ['除', '定', '闭', '破'],
|
|
6262
6473
|
travel: ['建', '成', '开', '除'],
|
|
6474
|
+
visit: ['满', '平', '定', '成'],
|
|
6475
|
+
study: ['成', '开', '建'],
|
|
6263
6476
|
worship: ['除', '满', '平', '定', '执', '成', '开'],
|
|
6264
6477
|
contract: ['定', '成', '收', '开'],
|
|
6265
6478
|
medical: ['除', '开'],
|
|
@@ -6353,7 +6566,133 @@ function buildZeri(input) {
|
|
|
6353
6566
|
};
|
|
6354
6567
|
}
|
|
6355
6568
|
|
|
6356
|
-
return { TASKS, buildZeri };
|
|
6569
|
+
return { TASKS, TASK_GROUPS, buildZeri };
|
|
6570
|
+
})();
|
|
6571
|
+
|
|
6572
|
+
__mods.convert = (function () {
|
|
6573
|
+
const { solarToLunar } = __mods.lunar;
|
|
6574
|
+
const { fromJDN, toJDN } = __mods.calendar;
|
|
6575
|
+
const { buildAlmanac } = __mods.almanac;
|
|
6576
|
+
const { assertCivil, daysInMonth } = __mods.validate;
|
|
6577
|
+
|
|
6578
|
+
const WEEK = ['日', '一', '二', '三', '四', '五', '六'];
|
|
6579
|
+
const MONTH_TEXT = ['正', '二', '三', '四', '五', '六', '七', '八', '九', '十', '冬', '腊'];
|
|
6580
|
+
const DAY_TENS = ['初', '十', '廿'];
|
|
6581
|
+
const DAY_UNITS = ['十', '一', '二', '三', '四', '五', '六', '七', '八', '九'];
|
|
6582
|
+
|
|
6583
|
+
function dayText(day) {
|
|
6584
|
+
if (day === 10) return '初十';
|
|
6585
|
+
if (day === 20) return '二十';
|
|
6586
|
+
if (day === 30) return '三十';
|
|
6587
|
+
return `${DAY_TENS[Math.floor(day / 10)]}${DAY_UNITS[day % 10]}`;
|
|
6588
|
+
}
|
|
6589
|
+
|
|
6590
|
+
function lunarText(year, month, day, isLeap) {
|
|
6591
|
+
return `农历${year}年${isLeap ? '闰' : ''}${MONTH_TEXT[month - 1] || month}月${dayText(day)}`;
|
|
6592
|
+
}
|
|
6593
|
+
|
|
6594
|
+
function lunarNewYearJdn(lunarYear) {
|
|
6595
|
+
const from = toJDN(lunarYear, 1, 20);
|
|
6596
|
+
const to = toJDN(lunarYear, 2, 25);
|
|
6597
|
+
for (let jdn = from; jdn <= to; jdn++) {
|
|
6598
|
+
const p = fromJDN(jdn);
|
|
6599
|
+
const l = solarToLunar(p.year, p.month, p.day);
|
|
6600
|
+
if (l.lunarYear === lunarYear && l.month === 1 && l.day === 1) return jdn;
|
|
6601
|
+
}
|
|
6602
|
+
return null;
|
|
6603
|
+
}
|
|
6604
|
+
|
|
6605
|
+
function lunarMonths(lunarYear) {
|
|
6606
|
+
const first = lunarNewYearJdn(lunarYear);
|
|
6607
|
+
if (first == null) return [];
|
|
6608
|
+
const out = [];
|
|
6609
|
+
let cur = first;
|
|
6610
|
+
for (let i = 0; i < 14; i++) {
|
|
6611
|
+
const p = fromJDN(cur);
|
|
6612
|
+
const l = solarToLunar(p.year, p.month, p.day);
|
|
6613
|
+
if (i > 0 && l.month === 1 && !l.isLeap) break;
|
|
6614
|
+
let next = null;
|
|
6615
|
+
for (let k = 29; k <= 31; k++) {
|
|
6616
|
+
const d = fromJDN(cur + k);
|
|
6617
|
+
const l2 = solarToLunar(d.year, d.month, d.day);
|
|
6618
|
+
if (l2.day === 1) { next = cur + k; break; }
|
|
6619
|
+
}
|
|
6620
|
+
if (next == null) break;
|
|
6621
|
+
out.push({ month: l.month, isLeap: l.isLeap, startJdn: cur, length: next - cur });
|
|
6622
|
+
cur = next;
|
|
6623
|
+
}
|
|
6624
|
+
return out;
|
|
6625
|
+
}
|
|
6626
|
+
|
|
6627
|
+
function buildConvert(input) {
|
|
6628
|
+
const mode = input.mode === 'lunar2solar' ? 'lunar2solar' : 'solar2lunar';
|
|
6629
|
+
let solar;
|
|
6630
|
+
let lunar;
|
|
6631
|
+
let note = null;
|
|
6632
|
+
if (mode === 'solar2lunar') {
|
|
6633
|
+
solar = { year: input.year, month: input.month, day: input.day };
|
|
6634
|
+
assertCivil(solar, '公农历转换');
|
|
6635
|
+
if (solar.day > daysInMonth(solar.year, solar.month)) {
|
|
6636
|
+
throw new Error(`非法日期:${solar.year} 年 ${solar.month} 月没有 ${solar.day} 日`);
|
|
6637
|
+
}
|
|
6638
|
+
lunar = solarToLunar(solar.year, solar.month, solar.day);
|
|
6639
|
+
} else {
|
|
6640
|
+
const y = Number(input.lunarYear);
|
|
6641
|
+
const m = Number(input.lunarMonth);
|
|
6642
|
+
const d = Number(input.lunarDay);
|
|
6643
|
+
if (![y, m, d].every(Number.isInteger)) throw new Error('农历转换需要 lunarYear / lunarMonth / lunarDay');
|
|
6644
|
+
if (m < 1 || m > 12) throw new Error('农历月份须在 1–12');
|
|
6645
|
+
const months = lunarMonths(y);
|
|
6646
|
+
if (!months.length) throw new Error(`农历 ${y} 年超出本地历法覆盖范围(1900–2100)`);
|
|
6647
|
+
const isLeap = input.isLeapMonth === true;
|
|
6648
|
+
const hit = months.find((x) => x.month === m && x.isLeap === isLeap);
|
|
6649
|
+
if (!hit) {
|
|
6650
|
+
const leapMonths = months.filter((x) => x.isLeap).map((x) => `闰${MONTH_TEXT[x.month - 1]}月`);
|
|
6651
|
+
throw new Error(`农历 ${y} 年没有${leapMonths.length ? `该月(该年闰月为 ${leapMonths.join('、')})` : '闰月'}:${isLeap ? '请确认闰月标记' : '请确认月份'}`);
|
|
6652
|
+
}
|
|
6653
|
+
if (d < 1 || d > hit.length) throw new Error(`农历 ${y} 年${isLeap ? '闰' : ''}${MONTH_TEXT[m - 1]}月只有 ${hit.length} 天,没有 ${d} 日`);
|
|
6654
|
+
const p = fromJDN(hit.startJdn + d - 1);
|
|
6655
|
+
solar = { year: p.year, month: p.month, day: p.day };
|
|
6656
|
+
const check = solarToLunar(p.year, p.month, p.day);
|
|
6657
|
+
if (check.month !== m || check.day !== d || check.isLeap !== isLeap) {
|
|
6658
|
+
note = '反查结果与目标农历日不完全一致,已按本地历法实际月首回推';
|
|
6659
|
+
}
|
|
6660
|
+
lunar = check;
|
|
6661
|
+
}
|
|
6662
|
+
|
|
6663
|
+
const a = buildAlmanac(solar);
|
|
6664
|
+
const jdn = toJDN(solar.year, solar.month, solar.day);
|
|
6665
|
+
const solarText = `${solar.year}-${String(solar.month).padStart(2, '0')}-${String(solar.day).padStart(2, '0')}`;
|
|
6666
|
+
return {
|
|
6667
|
+
system: 'convert',
|
|
6668
|
+
meta: {
|
|
6669
|
+
mode,
|
|
6670
|
+
solarDate: solarText,
|
|
6671
|
+
weekday: `星期${WEEK[(jdn + 1) % 7]}`,
|
|
6672
|
+
...(note ? { note } : {}),
|
|
6673
|
+
scope: '公农历互转按本地定朔历(1900–2100);农历闰月须显式指定,不自动猜同名月',
|
|
6674
|
+
},
|
|
6675
|
+
solar: { year: solar.year, month: solar.month, day: solar.day, text: solarText },
|
|
6676
|
+
lunar: {
|
|
6677
|
+
year: lunar.lunarYear,
|
|
6678
|
+
month: lunar.month,
|
|
6679
|
+
day: lunar.day,
|
|
6680
|
+
isLeap: lunar.isLeap,
|
|
6681
|
+
text: lunarText(lunar.lunarYear, lunar.month, lunar.day, lunar.isLeap),
|
|
6682
|
+
},
|
|
6683
|
+
ganzhi: {
|
|
6684
|
+
year: a.ganzhi.year,
|
|
6685
|
+
month: a.ganzhi.month,
|
|
6686
|
+
day: a.ganzhi.day,
|
|
6687
|
+
shengXiao: a.ganzhi.shengXiao,
|
|
6688
|
+
springYear: a.ganzhi.springYear,
|
|
6689
|
+
},
|
|
6690
|
+
sources: ['农历:本地定朔 + 节气黄经历法(engine/lunar.js)', '干支与生肖:与黄历同口径(年按立春界,另列春节界)'],
|
|
6691
|
+
disclaimer: '历法换算为确定性计算;民俗历法各版本在极少数日期(交节当日、闰月边界)存在日界差异,已注明口径。',
|
|
6692
|
+
};
|
|
6693
|
+
}
|
|
6694
|
+
|
|
6695
|
+
return { buildConvert };
|
|
6357
6696
|
})();
|
|
6358
6697
|
|
|
6359
6698
|
__mods['interpret-plain'] = (function () {
|
|
@@ -8526,6 +8865,7 @@ const { buildChenggu } = __mods.chenggu;
|
|
|
8526
8865
|
const { buildXiaoliuren } = __mods.xiaoliuren;
|
|
8527
8866
|
const { buildStar } = __mods.star;
|
|
8528
8867
|
const { buildNumerology } = __mods.numerology;
|
|
8868
|
+
const { buildConvert } = __mods.convert;
|
|
8529
8869
|
const { buildTrend } = __mods.trend;
|
|
8530
8870
|
const { buildFengshui } = __mods.fengshui;
|
|
8531
8871
|
const { buildName } = __mods.name;
|
|
@@ -9080,6 +9420,26 @@ function computeRaw(args = {}) {
|
|
|
9080
9420
|
const result = buildChenggu({ year: dt.year, month: dt.month, day: dt.day, hour, minute: hasTime ? dt.minute : 0 });
|
|
9081
9421
|
return { ...result, summary: chengguText(result) };
|
|
9082
9422
|
}
|
|
9423
|
+
if (system === 'convert') {
|
|
9424
|
+
const mode = args.mode === 'lunar2solar' ? 'lunar2solar' : 'solar2lunar';
|
|
9425
|
+
let result;
|
|
9426
|
+
if (mode === 'lunar2solar') {
|
|
9427
|
+
if (args.lunarYear == null || args.lunarMonth == null || args.lunarDay == null) {
|
|
9428
|
+
throw fail('E_INPUT', '农历转公历需要 lunarYear / lunarMonth / lunarDay(闰月另加 isLeapMonth: true)');
|
|
9429
|
+
}
|
|
9430
|
+
result = buildConvert({
|
|
9431
|
+
mode,
|
|
9432
|
+
lunarYear: Number(args.lunarYear),
|
|
9433
|
+
lunarMonth: Number(args.lunarMonth),
|
|
9434
|
+
lunarDay: Number(args.lunarDay),
|
|
9435
|
+
isLeapMonth: args.isLeapMonth === true,
|
|
9436
|
+
});
|
|
9437
|
+
} else {
|
|
9438
|
+
const dt = parseDateTime(args.datetime);
|
|
9439
|
+
result = buildConvert({ mode, year: dt.year, month: dt.month, day: dt.day });
|
|
9440
|
+
}
|
|
9441
|
+
return { ...result, summary: convertText(result) };
|
|
9442
|
+
}
|
|
9083
9443
|
if (system === 'xiaoliuren') {
|
|
9084
9444
|
const dt = args.datetime ? parseDateTime(args.datetime) : null;
|
|
9085
9445
|
const result = buildXiaoliuren({
|
|
@@ -9163,21 +9523,34 @@ function computeRaw(args = {}) {
|
|
|
9163
9523
|
return { ...result, summary: nameText(result) };
|
|
9164
9524
|
}
|
|
9165
9525
|
if (!system) {
|
|
9166
|
-
throw fail('E_INPUT', '缺少 system,可选:bazi(四柱八字)、ziwei(紫微斗数)、liuyao(六爻)、meihua(梅花易数)、daliuren(大六壬)、qimen(奇门遁甲)、hepan(合盘)、tarot(塔罗)、almanac(黄历)、zeri(择日)、chenggu(称骨)、xiaoliuren(小六壬)、star(星座)、numerology(生命数字)、trend(人生 K 线)、fengshui(风水)、name
|
|
9526
|
+
throw fail('E_INPUT', '缺少 system,可选:bazi(四柱八字)、ziwei(紫微斗数)、liuyao(六爻)、meihua(梅花易数)、daliuren(大六壬)、qimen(奇门遁甲)、hepan(合盘)、tarot(塔罗)、almanac(黄历)、zeri(择日)、chenggu(称骨)、xiaoliuren(小六壬)、star(星座)、numerology(生命数字)、trend(人生 K 线)、fengshui(风水)、name(起名)、convert(公农历互转)。');
|
|
9167
9527
|
}
|
|
9168
|
-
throw fail('E_SYSTEM', `未知体系「${system}」,可选:bazi(四柱八字)、ziwei(紫微斗数)、liuyao(六爻)、meihua(梅花易数)、daliuren(大六壬)、qimen(奇门遁甲)、hepan(合盘)、tarot(塔罗)、almanac(黄历)、zeri(择日)、chenggu(称骨)、xiaoliuren(小六壬)、star(星座)、numerology(生命数字)、trend(人生 K 线)、fengshui(风水)、name
|
|
9528
|
+
throw fail('E_SYSTEM', `未知体系「${system}」,可选:bazi(四柱八字)、ziwei(紫微斗数)、liuyao(六爻)、meihua(梅花易数)、daliuren(大六壬)、qimen(奇门遁甲)、hepan(合盘)、tarot(塔罗)、almanac(黄历)、zeri(择日)、chenggu(称骨)、xiaoliuren(小六壬)、star(星座)、numerology(生命数字)、trend(人生 K 线)、fengshui(风水)、name(起名)、convert(公农历互转)。`);
|
|
9169
9529
|
}
|
|
9170
9530
|
|
|
9171
9531
|
function almanacText(r) {
|
|
9172
9532
|
const g = r.ganzhi;
|
|
9173
9533
|
const jq = r.jieQi && r.jieQi.next ? ` 下一节:${r.jieQi.next.name} ${r.jieQi.next.date}` : '';
|
|
9534
|
+
const god = r.dayGod ? `值日:${r.dayGod.name}(${r.dayGod.type}·${r.dayGod.luck})` : '';
|
|
9535
|
+
const xiu = r.xiu ? `二十八宿:${r.xiu.name}宿(${r.xiu.luck}·${r.xiu.zheng}·${r.xiu.animal})` : '';
|
|
9536
|
+
const tai = r.taiShen ? `胎神:${r.taiShen}` : '';
|
|
9537
|
+
const pos = r.positions
|
|
9538
|
+
? `吉神方位:喜神${r.positions.xiShen || '—'} 财神${r.positions.caiShen || '—'} 福神${r.positions.fuShen ? r.positions.fuShen.dir : '—'} 阳贵${r.positions.yangGui ? r.positions.yangGui.dir : '—'} 阴贵${r.positions.yinGui ? r.positions.yinGui.dir : '—'}`
|
|
9539
|
+
: '';
|
|
9540
|
+
const lucky = r.lucky ? `吉配生肖:六合${r.lucky.liuhe || '—'} 三合${(r.lucky.sanhe || []).join('、') || '—'}` : '';
|
|
9541
|
+
const nayin = r.nayin && r.nayin.day ? `日柱纳音:${r.nayin.day.name}` : '';
|
|
9542
|
+
const hours = (r.hours || []).map((h) => `${h.zhi}${h.ganZhi.slice(0, 1)}·${h.shen}${h.luck === '吉' ? '吉' : '凶'}`).join(' ');
|
|
9174
9543
|
return [
|
|
9175
9544
|
`【黄历】${r.meta.date} ${r.meta.weekday} ${r.lunar.text}`,
|
|
9176
9545
|
`干支:${g.year}年 ${g.month}月 ${g.day}日 属${g.shengXiao}`,
|
|
9177
9546
|
...(r.meta.boundaryNote ? [` ${r.meta.boundaryNote}`] : []),
|
|
9178
|
-
`建除:${r.zhiXing}日 冲:${r.chong.text}${r.chong.sha ? `(${r.chong.sha})` : ''}
|
|
9547
|
+
`建除:${r.zhiXing}日 冲:${r.chong.text}${r.chong.sha ? `(${r.chong.sha})` : ''} ${god}`,
|
|
9548
|
+
[xiu, nayin, tai].filter(Boolean).join(' '),
|
|
9179
9549
|
`宜:${r.yi.join('、')}`,
|
|
9180
9550
|
`忌:${r.ji.join('、')}`,
|
|
9551
|
+
pos,
|
|
9552
|
+
lucky,
|
|
9553
|
+
hours ? `时辰吉凶:${hours}` : '',
|
|
9181
9554
|
`节气:上一节 ${r.jieQi.prev ? `${r.jieQi.prev.name} ${r.jieQi.prev.date}` : '—'}${jq}`,
|
|
9182
9555
|
r.dailyHexagram ? `每日一卦:${r.dailyHexagram.name} ${r.dailyHexagram.meaning || ''}` : '',
|
|
9183
9556
|
`口径:${r.meta.scope}`,
|
|
@@ -9200,13 +9573,17 @@ function zeriText(r) {
|
|
|
9200
9573
|
}
|
|
9201
9574
|
|
|
9202
9575
|
function chengguText(r) {
|
|
9203
|
-
|
|
9576
|
+
const s = r.song || {};
|
|
9577
|
+
const lines = [
|
|
9204
9578
|
`【称骨】${r.input.solar} ${r.lunar.text}`,
|
|
9205
9579
|
`四项:${r.weights.year.label} ${r.weights.month.label} ${r.weights.day.label} ${r.weights.hour.label}`,
|
|
9206
9580
|
`合计:${r.total.label}(${r.verdict.band})`,
|
|
9207
|
-
|
|
9208
|
-
'
|
|
9209
|
-
|
|
9581
|
+
`歌诀(${r.total.label}):${s.text || '—'}`,
|
|
9582
|
+
`释义:${s.plain || '—'}`,
|
|
9583
|
+
`分档白话:${r.verdict.text}`,
|
|
9584
|
+
'口径:骨重与歌诀为通行本口径(各版本歌诀有异文),释义为白话自撰,属民俗娱乐参考。',
|
|
9585
|
+
];
|
|
9586
|
+
return lines.join('\n');
|
|
9210
9587
|
}
|
|
9211
9588
|
|
|
9212
9589
|
function xiaoliurenText(r) {
|
|
@@ -9229,6 +9606,17 @@ function starText(r) {
|
|
|
9229
9606
|
].join('\n');
|
|
9230
9607
|
}
|
|
9231
9608
|
|
|
9609
|
+
function convertText(r) {
|
|
9610
|
+
const g = r.ganzhi;
|
|
9611
|
+
const dir = r.meta.mode === 'lunar2solar' ? '农历 → 公历' : '公历 → 农历';
|
|
9612
|
+
return [
|
|
9613
|
+
`【公农历转换·${dir}】${r.lunar.text} ⇄ ${r.solar.text} ${r.meta.weekday}`,
|
|
9614
|
+
`干支:${g.year}年 ${g.month}月 ${g.day}日 属${g.shengXiao}${g.springYear && g.springYear !== g.year ? `(春节界为${g.springYear}年)` : ''}`,
|
|
9615
|
+
...(r.meta.note ? [`注:${r.meta.note}`] : []),
|
|
9616
|
+
`口径:${r.meta.scope}`,
|
|
9617
|
+
].join('\n');
|
|
9618
|
+
}
|
|
9619
|
+
|
|
9232
9620
|
function numerologyText(r) {
|
|
9233
9621
|
return [
|
|
9234
9622
|
`【生命数字】${r.meta.date}(西方数字学,与八字/紫微不可互证)`,
|
|
@@ -9323,7 +9711,7 @@ function renderText(result) {
|
|
|
9323
9711
|
return parts.filter(Boolean).join('\n\n');
|
|
9324
9712
|
}
|
|
9325
9713
|
|
|
9326
|
-
return { interpret, DIRECTIONS, DIRECTION_DEFAULT, BRIGHTNESS, flowOf, geocodeAddress, resolveAddress, buildBazi, buildLiuyao, tossLines, followup, pastSignals, verifyFit, rectifyBirth, crossCheck, crossText, buildAlmanac, buildZeri, buildChenggu, buildXiaoliuren, buildStar, buildNumerology, buildTrend, buildFengshui, buildName, parseDateTime, compute, interpretText, renderText };
|
|
9714
|
+
return { interpret, DIRECTIONS, DIRECTION_DEFAULT, BRIGHTNESS, flowOf, geocodeAddress, resolveAddress, buildBazi, buildLiuyao, tossLines, followup, pastSignals, verifyFit, rectifyBirth, crossCheck, crossText, buildAlmanac, buildZeri, buildChenggu, buildXiaoliuren, buildStar, buildNumerology, buildConvert, buildTrend, buildFengshui, buildName, parseDateTime, compute, interpretText, renderText };
|
|
9327
9715
|
})();
|
|
9328
9716
|
|
|
9329
9717
|
const Engine = __mods.index;
|
|
@@ -9829,8 +10217,63 @@ return { interpret, DIRECTIONS, DIRECTION_DEFAULT, BRIGHTNESS, flowOf, geocodeAd
|
|
|
9829
10217
|
.mp-fu.miss .mp-fu-h{color:var(--red)}
|
|
9830
10218
|
.mp-fu-ev{margin-top:5px;font-size:12px;color:var(--muted);font-family:system-ui,sans-serif}
|
|
9831
10219
|
.mp-quick{margin:12px 16px;border:1px solid var(--line);border-radius:8px;background:var(--card);padding:12px 14px}
|
|
10220
|
+
.mp-cg{margin:12px 16px;border:1px solid var(--line);border-radius:8px;background:var(--card);padding:12px 14px;font-family:system-ui,sans-serif}
|
|
10221
|
+
.mp-cg-h{display:flex;align-items:baseline;gap:10px;flex-wrap:wrap;margin-bottom:9px}
|
|
10222
|
+
.mp-cg-h b{font-size:13px;color:var(--ink);font-weight:600}
|
|
10223
|
+
.mp-cg-h span{font-size:11.5px;color:var(--muted)}
|
|
10224
|
+
.mp-cg-w{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:1px;background:var(--line);border:1px solid var(--line);border-radius:6px;overflow:hidden}
|
|
10225
|
+
.mp-cg .cg-cell{background:var(--card);padding:7px 9px}
|
|
10226
|
+
.mp-cg .cg-cell em{display:block;font-style:normal;font-size:10.5px;color:var(--muted);margin-bottom:2px}
|
|
10227
|
+
.mp-cg .cg-cell b{font-size:13.5px;color:var(--ink);font-weight:600;font-variant-numeric:tabular-nums}
|
|
10228
|
+
.mp-cg-tot{display:flex;align-items:baseline;gap:8px;margin:10px 0 4px}
|
|
10229
|
+
.mp-cg-tot em{font-style:normal;font-size:11px;color:var(--muted)}
|
|
10230
|
+
.mp-cg-tot b{font-size:19px;color:var(--lu);font-weight:700;letter-spacing:.02em}
|
|
10231
|
+
.mp-cg-tot i{font-style:normal;font-size:10.5px;color:var(--muted);border:1px solid var(--line);border-radius:999px;padding:1px 7px}
|
|
10232
|
+
.mp-cg-song{margin-top:8px;padding:10px 12px;border-left:3px solid var(--quan);background:var(--band);border-radius:0 6px 6px 0}
|
|
10233
|
+
.mp-cg-song-h{font-size:11px;color:var(--muted);margin-bottom:5px}
|
|
10234
|
+
.mp-cg-verse{font-family:var(--kai,system-ui),serif;font-size:15px;line-height:2;color:var(--ink);letter-spacing:.03em}
|
|
10235
|
+
.mp-cg-verse span{display:block}
|
|
10236
|
+
.mp-cg-miss{color:var(--muted);font-size:12.5px}
|
|
10237
|
+
.mp-cg-plain{margin-top:7px;font-size:12.5px;line-height:1.85;color:var(--ink2)}
|
|
10238
|
+
.mp-cg-plain em,.mp-cg-band em{font-style:normal;font-size:10.5px;color:var(--muted);border:1px solid var(--line);border-radius:3px;padding:0 4px;margin-right:6px;vertical-align:1px}
|
|
10239
|
+
.mp-cg-band{margin-top:8px;font-size:12.5px;line-height:1.8;color:var(--ink2)}
|
|
10240
|
+
.mp-cg-note{margin-top:9px;padding-top:8px;border-top:1px dashed var(--line);font-size:11px;line-height:1.7;color:var(--muted)}
|
|
10241
|
+
@media print{.mp-cg{break-inside:avoid}}
|
|
10242
|
+
@media (max-width:640px){.mp-cg-w{grid-template-columns:repeat(2,minmax(0,1fr))}}
|
|
9832
10243
|
.mp-quick-h{font-size:13px;color:var(--lu);margin-bottom:6px;font-family:system-ui,sans-serif}
|
|
9833
10244
|
.mp-quick-pre{margin:0;white-space:pre-wrap;word-break:break-word;font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:13px;line-height:1.9;color:var(--ink2)}
|
|
10245
|
+
.mp-al{margin:12px 16px;border:1px solid var(--line);border-radius:8px;background:var(--card);padding:12px 14px;font-family:system-ui,sans-serif}
|
|
10246
|
+
.mp-al-h{display:flex;align-items:baseline;gap:10px;flex-wrap:wrap;border-bottom:1px solid var(--hair);padding-bottom:8px;margin-bottom:9px}
|
|
10247
|
+
.mp-al-h b{font-size:18px;color:var(--ink);font-weight:700;font-variant-numeric:tabular-nums}
|
|
10248
|
+
.mp-al-h i{font-style:normal;font-size:12px;color:var(--muted)}
|
|
10249
|
+
.mp-al-gz{font-size:12.5px;color:var(--ink2);margin-bottom:9px;display:flex;align-items:center;gap:8px;flex-wrap:wrap}
|
|
10250
|
+
.mp-al-badge{font-size:11px;border:1px solid var(--line);border-radius:999px;padding:1px 8px}
|
|
10251
|
+
.mp-al-badge.good{color:var(--lu);border-color:var(--lu)}
|
|
10252
|
+
.mp-al-badge.bad{color:var(--ji);border-color:var(--ji)}
|
|
10253
|
+
.mp-al-yiji{display:grid;grid-template-columns:1fr 1fr;gap:10px;margin:6px 0 9px}
|
|
10254
|
+
.mp-al-col em,.mp-al-row>em{font-style:normal;font-size:10.5px;color:var(--muted);display:block;margin-bottom:4px}
|
|
10255
|
+
.mp-al-chips{display:flex;flex-wrap:wrap;gap:4px}
|
|
10256
|
+
.mp-al-chip{font-size:11.5px;padding:1px 7px;border:1px solid var(--line);border-radius:999px;color:var(--ink2);white-space:nowrap}
|
|
10257
|
+
.mp-al-grid{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:1px;background:var(--line);border:1px solid var(--line);border-radius:6px;overflow:hidden;margin:8px 0}
|
|
10258
|
+
.mp-al-cell{background:var(--card);padding:6px 8px;min-width:0}
|
|
10259
|
+
.mp-al-cell em{display:block;font-style:normal;font-size:10.5px;color:var(--muted);margin-bottom:2px}
|
|
10260
|
+
.mp-al-cell b{font-size:12.5px;color:var(--ink);font-weight:600;line-height:1.45;display:block}
|
|
10261
|
+
.mp-al-row{margin:9px 0}
|
|
10262
|
+
.mp-al-hours{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:5px}
|
|
10263
|
+
.mp-al-hour{display:flex;align-items:baseline;gap:3px;border:1px solid var(--hair);border-radius:5px;padding:3px 6px;font-size:11px;color:var(--ink2);background:var(--band)}
|
|
10264
|
+
.mp-al-hour i{font-style:normal;font-weight:600;color:var(--ink)}
|
|
10265
|
+
.mp-al-hour em{font-style:normal;color:var(--muted)}
|
|
10266
|
+
.mp-al-hour b{font-weight:500}
|
|
10267
|
+
.mp-al-hour u{text-decoration:none;margin-left:auto;font-size:10.5px}
|
|
10268
|
+
.mp-al-hour.good{border-color:var(--lu);color:var(--lu)}
|
|
10269
|
+
.mp-al-hour.good i{color:var(--lu)}
|
|
10270
|
+
.mp-al-hour.bad{border-color:var(--hair)}
|
|
10271
|
+
.mp-al-hour.bad u{color:var(--ji)}
|
|
10272
|
+
.mp-al-hex{margin-top:8px;font-size:12px;color:var(--ink2)}
|
|
10273
|
+
.mp-al-hex b{color:var(--quan)}
|
|
10274
|
+
.mp-al-note{margin-top:9px;padding-top:8px;border-top:1px dashed var(--line);font-size:11px;line-height:1.7;color:var(--muted)}
|
|
10275
|
+
@media print{.mp-al{break-inside:avoid}}
|
|
10276
|
+
@media (max-width:640px){.mp-al{margin:10px;padding:10px}.mp-al-grid{grid-template-columns:repeat(2,minmax(0,1fr))}.mp-al-yiji{grid-template-columns:1fr}}.mp-quick-pre{margin:0;white-space:pre-wrap;word-break:break-word;font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:13px;line-height:1.9;color:var(--ink2)}
|
|
9834
10277
|
.mp-it-dis{padding:11px 16px;border-top:1px solid var(--line);background:var(--band);font-size:12px;line-height:1.75;color:var(--muted);font-family:system-ui,sans-serif}
|
|
9835
10278
|
|
|
9836
10279
|
@media (max-width:640px){
|
|
@@ -10881,6 +11324,31 @@ return { interpret, DIRECTIONS, DIRECTION_DEFAULT, BRIGHTNESS, flowOf, geocodeAd
|
|
|
10881
11324
|
</section>`;
|
|
10882
11325
|
};
|
|
10883
11326
|
|
|
11327
|
+
pp.chengguHTML = function (r) {
|
|
11328
|
+
if (!r) return '';
|
|
11329
|
+
const w = r.weights || {};
|
|
11330
|
+
const song = r.song || {};
|
|
11331
|
+
const cells = ['year', 'month', 'day', 'hour'].map((k) => {
|
|
11332
|
+
const x = w[k] || { label: '', qian: 0 };
|
|
11333
|
+
const name = String(x.label || '').split(' ')[0] || '';
|
|
11334
|
+
const val = String(x.label || '').split(' ')[1] || '';
|
|
11335
|
+
return `<div class="cg-cell"><em>${esc(name)}</em><b>${esc(val)}</b></div>`;
|
|
11336
|
+
}).join('');
|
|
11337
|
+
const verse = String(song.text || '');
|
|
11338
|
+
const lines = verse ? verse.replace(/[。]$/, '').split(';').map((s, i) => `<span>${esc(s)}${i === 0 ? ';' : '。'}</span>`).join('') : '';
|
|
11339
|
+
const band = r.verdict && r.verdict.band ? r.verdict.band : '';
|
|
11340
|
+
return `<section class="mp-cg" aria-label="称骨结果">
|
|
11341
|
+
<div class="mp-cg-h"><b>称骨</b><span>${esc(r.lunar && r.lunar.text ? r.lunar.text : '')}</span></div>
|
|
11342
|
+
<div class="mp-cg-w">${cells}</div>
|
|
11343
|
+
<div class="mp-cg-tot"><em>骨重合计</em><b>${esc(r.total && r.total.label ? r.total.label : '')}</b>${band ? `<i>${esc(band)}</i>` : ''}</div>
|
|
11344
|
+
<div class="mp-cg-song"><div class="mp-cg-song-h">称骨歌 · ${esc(r.total && r.total.label ? r.total.label : '')}</div>
|
|
11345
|
+
<div class="mp-cg-verse">${lines || '<span class="mp-cg-miss">该骨重未见通行本歌诀</span>'}</div>
|
|
11346
|
+
<div class="mp-cg-plain"><em>释义</em>${esc(song.plain || '')}</div></div>
|
|
11347
|
+
${r.verdict && r.verdict.text ? `<div class="mp-cg-band"><em>分档</em>${esc(r.verdict.text)}</div>` : ''}
|
|
11348
|
+
<div class="mp-cg-note">骨重与歌诀为通行本口径(各版本歌诀有异文,断句标点已统一);释义为白话自撰,只作字面直解,属民俗娱乐参考,不构成命运断言。</div>
|
|
11349
|
+
</section>`;
|
|
11350
|
+
};
|
|
11351
|
+
|
|
10884
11352
|
pp.baziHTML = function (r) {
|
|
10885
11353
|
const cols = [['year', '年柱'], ['month', '月柱'], ['day', '日柱'], ['hour', '时柱']];
|
|
10886
11354
|
const SHORT = { year: '年', month: '月', day: '日', hour: '时' };
|
|
@@ -11067,11 +11535,43 @@ return { interpret, DIRECTIONS, DIRECTION_DEFAULT, BRIGHTNESS, flowOf, geocodeAd
|
|
|
11067
11535
|
return (html || '') + pp.interpretHTML(it, opt);
|
|
11068
11536
|
};
|
|
11069
11537
|
|
|
11538
|
+
pp.almanacHTML = function (r) {
|
|
11539
|
+
if (!r || !r.meta) return pp.quickHTML(r);
|
|
11540
|
+
const g = r.ganzhi || {};
|
|
11541
|
+
const god = r.dayGod || null;
|
|
11542
|
+
const chips = (list, cls) => (list || []).map((x) => `<span class="mp-al-chip${cls ? ` ${cls}` : ''}">${esc(x)}</span>`).join('');
|
|
11543
|
+
const cell = (k, v) => (v ? `<div class="mp-al-cell"><em>${esc(k)}</em><b>${esc(v)}</b></div>` : '');
|
|
11544
|
+
const xiu = r.xiu ? `${r.xiu.name}宿(${r.xiu.luck}·${r.xiu.zheng}·${r.xiu.animal})` : '';
|
|
11545
|
+
const nayin = r.nayin && r.nayin.day ? r.nayin.day.name : '';
|
|
11546
|
+
const chong = r.chong ? `${r.chong.text}${r.chong.sha ? ` ${r.chong.sha}` : ''}` : '';
|
|
11547
|
+
const hours = (r.hours || []).map((h) => `<span class="mp-al-hour ${h.luck === '吉' ? 'good' : 'bad'}">`
|
|
11548
|
+
+ `<i>${esc(h.zhi)}</i><em>${esc((h.ganZhi || '').slice(0, 1))}</em><b>${esc(h.shen || '')}</b>`
|
|
11549
|
+
+ `<u>${esc(h.luck || '')}</u></span>`).join('');
|
|
11550
|
+
const pos = r.positions || {};
|
|
11551
|
+
const posRow = (k, v) => (v ? `<span class="mp-al-chip">${esc(k)}·${esc(typeof v === 'string' ? v : v.dir || '')}</span>` : '');
|
|
11552
|
+
const lucky = r.lucky || {};
|
|
11553
|
+
const godBadge = god ? `<span class="mp-al-badge ${god.luck === '吉' ? 'good' : 'bad'}">${esc(god.name)}·${esc(god.type)}·${esc(god.luck)}</span>` : '';
|
|
11554
|
+
return `<section class="mp-al" aria-label="黄历">
|
|
11555
|
+
<div class="mp-al-h"><b>${esc(r.meta.date || '')}</b><i>${esc(r.meta.weekday || '')} ${esc((r.lunar || {}).text || '')}</i></div>
|
|
11556
|
+
<div class="mp-al-gz">${esc(g.year || '')}年 ${esc(g.month || '')}月 ${esc(g.day || '')}日 属${esc(g.shengXiao || '')} 建除 ${esc(r.zhiXing || '')}日 ${godBadge}</div>
|
|
11557
|
+
<div class="mp-al-yiji">
|
|
11558
|
+
<div class="mp-al-col"><em>宜</em><div class="mp-al-chips">${chips(r.yi)}</div></div>
|
|
11559
|
+
<div class="mp-al-col"><em>忌</em><div class="mp-al-chips">${chips(r.ji)}</div></div>
|
|
11560
|
+
</div>
|
|
11561
|
+
<div class="mp-al-grid">${cell('二十八宿', xiu)}${cell('日柱纳音', nayin)}${cell('胎神', r.taiShen)}${cell('冲煞', chong)}</div>
|
|
11562
|
+
<div class="mp-al-row"><em>吉神方位</em><div class="mp-al-chips">${posRow('喜神', pos.xiShen)}${posRow('财神', pos.caiShen)}${posRow('福神', pos.fuShen)}${posRow('阳贵', pos.yangGui)}${posRow('阴贵', pos.yinGui)}</div></div>
|
|
11563
|
+
<div class="mp-al-row"><em>时刻吉凶</em><div class="mp-al-hours">${hours}</div></div>
|
|
11564
|
+
<div class="mp-al-row"><em>吉配生肖</em><div class="mp-al-chips">${lucky.liuhe ? `<span class="mp-al-chip">六合·${esc(lucky.liuhe)}</span>` : ''}${chips(lucky.sanhe || [])}</div></div>
|
|
11565
|
+
${r.dailyHexagram ? `<div class="mp-al-hex">每日一卦:<b>${esc(r.dailyHexagram.name)}</b> ${esc(r.dailyHexagram.meaning || '')}</div>` : ''}
|
|
11566
|
+
<div class="mp-al-note">${esc((r.meta && r.meta.scope) || '')}</div>
|
|
11567
|
+
</section>`;
|
|
11568
|
+
};
|
|
11569
|
+
|
|
11070
11570
|
pp.quickHTML = function (r) {
|
|
11071
11571
|
if (!r) return '';
|
|
11072
11572
|
const LABEL = {
|
|
11073
11573
|
almanac: '黄历', zeri: '择日', chenggu: '称骨', xiaoliuren: '小六壬',
|
|
11074
|
-
star: '星座', numerology: '生命数字', trend: '人生 K 线', fengshui: '风水', name: '起名',
|
|
11574
|
+
star: '星座', numerology: '生命数字', trend: '人生 K 线', fengshui: '风水', name: '起名', convert: '公农历转换',
|
|
11075
11575
|
};
|
|
11076
11576
|
const title = LABEL[r.system] || '速查';
|
|
11077
11577
|
const text = r.summary || '';
|
|
@@ -11341,7 +11841,8 @@ const TABS = [
|
|
|
11341
11841
|
{ k: 'qimen', label: '奇门', timeLabel: '起局时刻', hint: '奇门时家转盘:用起局时刻定节气、三元与局数;换局规则决定符头与节气如何对齐。' },
|
|
11342
11842
|
{ k: 'hepan', label: '合盘', timeLabel: '你的出生时刻', hint: '合盘按「日主 + 夫妻宫 + 五行互补」看两个人的相处与互补,需要双方出生信息。' },
|
|
11343
11843
|
{ k: 'tarot', label: '塔罗', timeLabel: '', hint: '塔罗不看时间,只记录抽牌时刻与你的提问。' },
|
|
11344
|
-
{ k: 'almanac', label: '黄历', timeLabel: '', hint: '
|
|
11844
|
+
{ k: 'almanac', label: '黄历', timeLabel: '', hint: '黄历按公历日期查农历、干支、宜忌、时辰吉凶、二十八宿与吉神方位;只做本地计算。' },
|
|
11845
|
+
{ k: 'convert', label: '农历', timeLabel: '', hint: '公农历互转:公历生日可反查农历;只知道农历生日时,可转成公历再排盘。' },
|
|
11345
11846
|
{ k: 'zeri', label: '择日', timeLabel: '', hint: '择日把区间内每天的建除宜忌与事项适配打分排序,并按属相排除冲煞日。' },
|
|
11346
11847
|
{ k: 'chenggu', label: '称骨', timeLabel: '出生时刻', hint: '称骨按农历年、月、日、时的骨重求和;时辰必填。' },
|
|
11347
11848
|
{ k: 'xiaoliuren', label: '小六壬', timeLabel: '起课时刻', hint: '小六壬用农历月/日/时掐指,也可用三个随机数起课。' },
|
|
@@ -11363,7 +11864,7 @@ const TIME_KIND = {
|
|
|
11363
11864
|
ziwei: 'birth', bazi: 'birth', hepan: 'birth',
|
|
11364
11865
|
liuyao: 'cast', meihua: 'cast', daliuren: 'cast', qimen: 'cast',
|
|
11365
11866
|
tarot: 'none',
|
|
11366
|
-
almanac: 'date', zeri: 'date', star: 'date', numerology: 'date',
|
|
11867
|
+
almanac: 'date', zeri: 'date', star: 'date', numerology: 'date', convert: 'date',
|
|
11367
11868
|
chenggu: 'birth', trend: 'birth', fengshui: 'birth', name: 'birth',
|
|
11368
11869
|
xiaoliuren: 'cast',
|
|
11369
11870
|
};
|
|
@@ -11398,6 +11899,9 @@ function App() {
|
|
|
11398
11899
|
const [task, setTask] = useState('开业');
|
|
11399
11900
|
const [days, setDays] = useState('30');
|
|
11400
11901
|
const [shengXiao, setShengXiao] = useState('');
|
|
11902
|
+
const [convMode, setConvMode] = useState('solar2lunar');
|
|
11903
|
+
const [lunarDate, setLunarDate] = useState('');
|
|
11904
|
+
const [leapMonth, setLeapMonth] = useState(false);
|
|
11401
11905
|
const [xlrMode, setXlrMode] = useState('time');
|
|
11402
11906
|
const [num1, setNum1] = useState(''); const [num2, setNum2] = useState(''); const [num3, setNum3] = useState('');
|
|
11403
11907
|
const [toAge, setToAge] = useState('60');
|
|
@@ -11503,6 +12007,24 @@ function App() {
|
|
|
11503
12007
|
delete args.datetime;
|
|
11504
12008
|
}
|
|
11505
12009
|
}
|
|
12010
|
+
if (k === 'convert') {
|
|
12011
|
+
args.system = 'convert';
|
|
12012
|
+
if (convMode === 'lunar2solar') {
|
|
12013
|
+
const m = /^(\d{4})-(\d{1,2})-(\d{1,2})$/.exec(String(lunarDate).trim());
|
|
12014
|
+
if (!m) {
|
|
12015
|
+
setError('农历转公历请按「农历年-月-日」填写,例如 2026-9-17;闰月单独勾选。');
|
|
12016
|
+
return;
|
|
12017
|
+
}
|
|
12018
|
+
args.mode = 'lunar2solar';
|
|
12019
|
+
args.lunarYear = Number(m[1]);
|
|
12020
|
+
args.lunarMonth = Number(m[2]);
|
|
12021
|
+
args.lunarDay = Number(m[3]);
|
|
12022
|
+
args.isLeapMonth = leapMonth;
|
|
12023
|
+
delete args.datetime;
|
|
12024
|
+
} else {
|
|
12025
|
+
args.mode = 'solar2lunar';
|
|
12026
|
+
}
|
|
12027
|
+
}
|
|
11506
12028
|
if (k === 'tarot') args.count = Number(count);
|
|
11507
12029
|
if (k === 'hepan') {
|
|
11508
12030
|
args.chart = hpChart;
|
|
@@ -11871,8 +12393,24 @@ function App() {
|
|
|
11871
12393
|
})) : null,
|
|
11872
12394
|
tab === 'zeri' ? field('所办事项', h('select', {
|
|
11873
12395
|
className: 'mp-input', value: task, onChange: (e) => setTask(e.target.value),
|
|
11874
|
-
}, [
|
|
11875
|
-
|
|
12396
|
+
}, [
|
|
12397
|
+
['常用', ['嫁娶', '搬家入宅', '出行', '开业', '签订合同', '祭祀']],
|
|
12398
|
+
['婚嫁', ['嫁娶', '订婚', '领证', '提亲', '收送聘金', '满月酒']],
|
|
12399
|
+
['生活', ['搬家', '入宅', '旅行', '访亲友', '入学', '求医', '祭祀']],
|
|
12400
|
+
['建造', ['动土', '装修', '装修建造', '安葬', '试车买车']],
|
|
12401
|
+
['工商', ['开业', '交易', '投资', '签订合同', '签约', '纳财', '赴任']],
|
|
12402
|
+
].map(([g, items]) => h('optgroup', { key: g, label: g },
|
|
12403
|
+
items.map((t) => h('option', { key: `${g}-${t}`, value: t }, t)))))) : null,
|
|
12404
|
+
tab === 'convert' ? field('转换方向', h('div', { className: 'mp-seg' },
|
|
12405
|
+
h('button', { className: convMode === 'solar2lunar' ? 'on' : '', onClick: () => setConvMode('solar2lunar') }, '公历 → 农历'),
|
|
12406
|
+
h('button', { className: convMode === 'lunar2solar' ? 'on' : '', onClick: () => setConvMode('lunar2solar') }, '农历 → 公历'))) : null,
|
|
12407
|
+
(tab === 'convert' && convMode === 'lunar2solar') ? field('农历日期', h('input', {
|
|
12408
|
+
className: 'mp-input', value: lunarDate, placeholder: '如 2026-9-17',
|
|
12409
|
+
onChange: (e) => setLunarDate(e.target.value),
|
|
12410
|
+
})) : null,
|
|
12411
|
+
(tab === 'convert' && convMode === 'lunar2solar') ? h('label', {
|
|
12412
|
+
className: 'mp-check',
|
|
12413
|
+
}, h('input', { type: 'checkbox', checked: leapMonth, onChange: (e) => setLeapMonth(e.target.checked) }), ' 闰月') : null,
|
|
11876
12414
|
tab === 'zeri' ? field('看多少天', h('input', {
|
|
11877
12415
|
className: 'mp-input', type: 'number', min: 1, max: 60, value: days,
|
|
11878
12416
|
onChange: (e) => setDays(e.target.value),
|
|
@@ -11997,7 +12535,9 @@ function App() {
|
|
|
11997
12535
|
: result.kind === 'hepan' ? (result.r.chart === 'ziwei' ? PP.ziweiHepanHTML(result.r) : PP.hepanHTML(result.r))
|
|
11998
12536
|
: result.kind === 'tarot' ? PP.tarotHTML(result.r)
|
|
11999
12537
|
: result.kind === 'liuyao' ? PP.liuyaoHTML(result.r)
|
|
12000
|
-
: result.kind === '
|
|
12538
|
+
: result.kind === 'chenggu' ? PP.chengguHTML(result.r)
|
|
12539
|
+
: result.kind === 'almanac' ? PP.almanacHTML(result.r)
|
|
12540
|
+
: result.kind === 'trend' ? PP.trendHTML(result.r)
|
|
12001
12541
|
: PP.quickHTML(result.r),
|
|
12002
12542
|
result.it,
|
|
12003
12543
|
{ folded: defaultFolded() },
|