dsh-metaphysics 0.22.0 → 0.38.2
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 +650 -413
- package/README.md +81 -18
- package/client.js +2975 -100
- package/docs/assets/dsh-metaphysics-group.png +0 -0
- package/engine/bazi.js +79 -2
- package/engine/classics.js +380 -0
- package/engine/followup.js +58 -0
- package/engine/geo.js +1 -1
- package/engine/index.js +168 -8
- package/engine/interpret-knowledge.js +448 -277
- package/engine/interpret-plain.js +131 -6
- package/engine/interpret.js +208 -7
- package/engine/liuyao.js +847 -237
- package/engine/mbti.js +417 -0
- package/engine/qimen-interpret.js +37 -2
- package/engine/qimen.js +128 -1
- package/engine/ziwei.js +198 -13
- package/index.js +21 -16
- package/locale/en.json +1 -1
- package/locale/zh.json +1 -1
- package/package.json +19 -15
- package//345/221/275/347/220/206/346/216/222/347/233/230.html +18737 -0
package/client.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
window.__ModuleLoader__.load({
|
|
2
2
|
id: 'dsh-metaphysics',
|
|
3
|
+
version: '0.38.2',
|
|
3
4
|
factory(require) {
|
|
4
5
|
const React = (function () {
|
|
5
6
|
try { return require('react'); } catch (e) { return globalThis.React; }
|
|
@@ -746,7 +747,7 @@ function resolveAddress(input) {
|
|
|
746
747
|
|
|
747
748
|
const DETAIL = /(区|县|镇|乡|村|小区|街道|路|号|巷|弄|组|队)/;
|
|
748
749
|
|
|
749
|
-
const USER_AGENT = 'dsh-metaphysics/0.
|
|
750
|
+
const USER_AGENT = 'dsh-metaphysics/0.23.0 (+https://github.com/xuanfu-web/dsh-metaphysics)';
|
|
750
751
|
|
|
751
752
|
async function onlineLookup(text, { timeoutMs = 2500 } = {}) {
|
|
752
753
|
if (typeof fetch !== 'function') return null;
|
|
@@ -2509,6 +2510,379 @@ function qtLine(e) {
|
|
|
2509
2510
|
return { QT_BRANCHES, QT_MONTHS, QT_BASE_URL, QT_NOTE, QT, qtOf, qtLine };
|
|
2510
2511
|
})();
|
|
2511
2512
|
|
|
2513
|
+
__mods.classics = (function () {
|
|
2514
|
+
|
|
2515
|
+
const CLASSIC_BOOKS = {
|
|
2516
|
+
ziping: { name: '子平真诠', author: '清·沈孝瞻', base: 'https://www.diancang.xyz/xuanxuewushu/zipingzhenquan/' },
|
|
2517
|
+
ditian: { name: '滴天髓', author: '明·京图(通行本)', base: 'https://www.diancang.xyz/xuanxuewushu/ditiansui/' },
|
|
2518
|
+
sanming: { name: '三命通会', author: '明·万民英', base: 'https://www.diancang.xyz/xuanxuewushu/sanmingtonghui/' },
|
|
2519
|
+
};
|
|
2520
|
+
|
|
2521
|
+
const CLASSICS = [
|
|
2522
|
+
{
|
|
2523
|
+
id: 'zp-yongshen',
|
|
2524
|
+
book: 'ziping',
|
|
2525
|
+
chapter: '八、论用神',
|
|
2526
|
+
scene: '用神',
|
|
2527
|
+
tags: [],
|
|
2528
|
+
quote: '八字用神,专求月令,以日干配月令地支,而生克不同,格局分焉。财官印食,此用神之善而顺用之者也;煞伤劫刃,用神之不善而逆用之者也。',
|
|
2529
|
+
plain: '用神从月令里找:财、官、印、食四吉神顺用(生之护之),煞、伤、劫、刃四凶神逆用(制之化之)。',
|
|
2530
|
+
url: 'https://www.diancang.xyz/xuanxuewushu/zipingzhenquan/53628.html',
|
|
2531
|
+
},
|
|
2532
|
+
{
|
|
2533
|
+
id: 'zp-zhenguan',
|
|
2534
|
+
book: 'ziping',
|
|
2535
|
+
chapter: '三十一、论正官',
|
|
2536
|
+
scene: '格局',
|
|
2537
|
+
tags: ['正官'],
|
|
2538
|
+
quote: '以刑冲破害为忌,则以生之护之为喜矣。存其喜而去其忌则贵,而贵之中又有高低者,何也?',
|
|
2539
|
+
plain: '正官格最忌刑冲破害,喜财生官、印护官;去忌存喜才谈得上贵,贵的层次还要看财印是否并透、有无伤官七煞混杂。',
|
|
2540
|
+
url: 'https://www.diancang.xyz/xuanxuewushu/zipingzhenquan/53651.html',
|
|
2541
|
+
},
|
|
2542
|
+
{
|
|
2543
|
+
id: 'zp-cai',
|
|
2544
|
+
book: 'ziping',
|
|
2545
|
+
chapter: '三十三、论财',
|
|
2546
|
+
scene: '格局',
|
|
2547
|
+
tags: ['财'],
|
|
2548
|
+
quote: '财为我克,使用之物也,以能生官,所以为美。为财帛,为妻妾,为才能,为驿马,皆财类也。',
|
|
2549
|
+
plain: '财是我所克、能为我用之物,因能生官而美;它同时代表钱财、配偶、才能、走动,不只「钱」一项。',
|
|
2550
|
+
url: 'https://www.diancang.xyz/xuanxuewushu/zipingzhenquan/53653.html',
|
|
2551
|
+
},
|
|
2552
|
+
{
|
|
2553
|
+
id: 'zp-yin',
|
|
2554
|
+
book: 'ziping',
|
|
2555
|
+
chapter: '三十五、论印绶',
|
|
2556
|
+
scene: '格局',
|
|
2557
|
+
tags: ['印'],
|
|
2558
|
+
quote: '印绶喜其生身,正偏同为美格,故财与印不分偏正,同为一格而论之。',
|
|
2559
|
+
plain: '印能生身,正印偏印都算美格,不分偏正而论;印格的关键在身印强弱与官杀、食伤、财的配合。',
|
|
2560
|
+
url: 'https://www.diancang.xyz/xuanxuewushu/zipingzhenquan/53655.html',
|
|
2561
|
+
},
|
|
2562
|
+
{
|
|
2563
|
+
id: 'zp-shishen',
|
|
2564
|
+
book: 'ziping',
|
|
2565
|
+
chapter: '三十七、论食神',
|
|
2566
|
+
scene: '格局',
|
|
2567
|
+
tags: ['食神'],
|
|
2568
|
+
quote: '食神本属泄气,以其能生正财,所以喜之。故食神生财,美格也。财要有根,不必偏正叠出,如身强食旺而财透,大贵之格。',
|
|
2569
|
+
plain: '食神本是泄气,可贵在能生财;食神生财要财有根,身强、食旺、财透三者齐,格局才大。',
|
|
2570
|
+
url: 'https://www.diancang.xyz/xuanxuewushu/zipingzhenquan/53657.html',
|
|
2571
|
+
},
|
|
2572
|
+
{
|
|
2573
|
+
id: 'zp-pianguan',
|
|
2574
|
+
book: 'ziping',
|
|
2575
|
+
chapter: '三十九、论偏官',
|
|
2576
|
+
scene: '格局',
|
|
2577
|
+
tags: ['七杀', '偏官'],
|
|
2578
|
+
quote: '煞以攻身,似非美物,百大贵之格,多存七煞。盖控制得宜,煞为我用,如大英雄大豪杰,似难驾驭,而处之有方,则惊天动地之功,忽焉而就。',
|
|
2579
|
+
plain: '七煞攻身,看着不美,但大贵之格多有七煞——能控制住就为我所用,像驾驭豪杰,处之有方就能成大事。',
|
|
2580
|
+
url: 'https://www.diancang.xyz/xuanxuewushu/zipingzhenquan/53659.html',
|
|
2581
|
+
},
|
|
2582
|
+
{
|
|
2583
|
+
id: 'zp-shangguan',
|
|
2584
|
+
book: 'ziping',
|
|
2585
|
+
chapter: '四十一、论伤官',
|
|
2586
|
+
scene: '格局',
|
|
2587
|
+
tags: ['伤官'],
|
|
2588
|
+
quote: '伤官虽非吉神,实为秀气,故文人学士,多于伤官格内得之。而夏木见水,冬金见火,则又为秀之尤秀者也。',
|
|
2589
|
+
plain: '伤官不是吉神,却是秀气所在,文人多出伤官格;夏木得水、冬金得火,是秀气里更秀的两种。',
|
|
2590
|
+
url: 'https://www.diancang.xyz/xuanxuewushu/zipingzhenquan/53661.html',
|
|
2591
|
+
},
|
|
2592
|
+
{
|
|
2593
|
+
id: 'zp-yangren',
|
|
2594
|
+
book: 'ziping',
|
|
2595
|
+
chapter: '四十三、论阳刃',
|
|
2596
|
+
scene: '格局',
|
|
2597
|
+
tags: ['劫财', '阳刃'],
|
|
2598
|
+
quote: '阳刃者,劫我正财之神,乃正财之七煞也。禄前一位,惟五阳有之,故为阳刃。不曰劫而曰刃,劫之甚也。刃宜伏制,官煞皆宜,财印相随,尤为贵显。',
|
|
2599
|
+
plain: '阳刃是劫财之极(只有五阳干有),宜用官煞制伏;财印相随而不相碍,格局更显。',
|
|
2600
|
+
url: 'https://www.diancang.xyz/xuanxuewushu/zipingzhenquan/53663.html',
|
|
2601
|
+
},
|
|
2602
|
+
{
|
|
2603
|
+
id: 'zp-lujie',
|
|
2604
|
+
book: 'ziping',
|
|
2605
|
+
chapter: '四十五、论建禄月劫',
|
|
2606
|
+
scene: '格局',
|
|
2607
|
+
tags: ['比肩', '建禄', '月劫'],
|
|
2608
|
+
quote: '故建禄与月劫,可同一格,不必加分,皆以透干支,别取财官煞食为用。',
|
|
2609
|
+
plain: '建禄、月劫同看一格,月令本身不算用神,要另看透出的财官煞食取用。',
|
|
2610
|
+
url: 'https://www.diancang.xyz/xuanxuewushu/zipingzhenquan/53665.html',
|
|
2611
|
+
},
|
|
2612
|
+
{
|
|
2613
|
+
id: 'zp-qihou',
|
|
2614
|
+
book: 'ziping',
|
|
2615
|
+
chapter: '十四、论用神配气候得失',
|
|
2616
|
+
scene: '调候',
|
|
2617
|
+
tags: [],
|
|
2618
|
+
quote: '论命惟以月令用神为主,然亦须配气候而互参之。譬如英雄豪杰,生得其时,自然事半功倍;遭时不顺,虽有奇才,成功不易。',
|
|
2619
|
+
plain: '月令用神为主,但必须配气候参看;同样的格局,生在得时的气候里事半功倍,逆着气候就费劲。',
|
|
2620
|
+
url: 'https://www.diancang.xyz/xuanxuewushu/zipingzhenquan/53634.html',
|
|
2621
|
+
},
|
|
2622
|
+
{
|
|
2623
|
+
id: 'zp-chengbai',
|
|
2624
|
+
book: 'ziping',
|
|
2625
|
+
chapter: '九、论用神成败救应',
|
|
2626
|
+
scene: '格局',
|
|
2627
|
+
tags: [],
|
|
2628
|
+
quote: '成中有败,必是带忌;败中有成,全凭救应。',
|
|
2629
|
+
plain: '成格不等于一路顺:成中带忌(官逢财又逢伤、官被合之类)就打了折;败格也未必无救——印来解伤、合来清煞,败中还能转成。',
|
|
2630
|
+
url: 'https://www.diancang.xyz/xuanxuewushu/zipingzhenquan/53629.html',
|
|
2631
|
+
},
|
|
2632
|
+
{
|
|
2633
|
+
id: 'zp-bianhua',
|
|
2634
|
+
book: 'ziping',
|
|
2635
|
+
chapter: '十、论用神变化',
|
|
2636
|
+
scene: '格局',
|
|
2637
|
+
tags: [],
|
|
2638
|
+
quote: '故若丁生亥月,本为正官,支全卯未,则化为印。己生申月,本属伤官。藏庚透壬,则化为财。凡此之类皆用神之变化也。',
|
|
2639
|
+
plain: '用神本从月令取,但月令藏干不一:丁生亥月本为正官,支会卯未就化为印;己生申月本属伤官,庚藏壬透就化为财。起点相同,合化一变,取用也跟着变(原文只说变化之由,不断定某盘必化)。',
|
|
2640
|
+
url: 'https://www.diancang.xyz/xuanxuewushu/zipingzhenquan/53630.html',
|
|
2641
|
+
},
|
|
2642
|
+
{
|
|
2643
|
+
id: 'dt-hannuan',
|
|
2644
|
+
book: 'ditian',
|
|
2645
|
+
chapter: '通神论·寒暖',
|
|
2646
|
+
scene: '调候',
|
|
2647
|
+
tags: [],
|
|
2648
|
+
quote: '天道有寒暖,生育万物,人道行之,不可过也。',
|
|
2649
|
+
plain: '天有寒暖才能生养万物,人命里寒暖也不能过——过寒过热都要调。',
|
|
2650
|
+
url: 'https://www.diancang.xyz/xuanxuewushu/ditiansui/153091.html',
|
|
2651
|
+
},
|
|
2652
|
+
{
|
|
2653
|
+
id: 'dt-zaoshi',
|
|
2654
|
+
book: 'ditian',
|
|
2655
|
+
chapter: '通神论·燥湿',
|
|
2656
|
+
scene: '调候',
|
|
2657
|
+
tags: [],
|
|
2658
|
+
quote: '地道有燥湿,生成品汇,人道得之,不可偏也。',
|
|
2659
|
+
plain: '地有燥湿才有品类生成,人命得燥湿之气也不能偏。',
|
|
2660
|
+
url: 'https://www.diancang.xyz/xuanxuewushu/ditiansui/153091.html',
|
|
2661
|
+
},
|
|
2662
|
+
{
|
|
2663
|
+
id: 'dt-shuaiwang',
|
|
2664
|
+
book: 'ditian',
|
|
2665
|
+
chapter: '通神论·衰旺',
|
|
2666
|
+
scene: '调候',
|
|
2667
|
+
tags: [],
|
|
2668
|
+
quote: '能知旺衰之真机,其于三命之奥,思过半矣。',
|
|
2669
|
+
plain: '真正看懂旺衰的机关,命理之奥就过了一半——旺衰不是数个数,要看真机。',
|
|
2670
|
+
url: 'https://www.diancang.xyz/xuanxuewushu/ditiansui/153091.html',
|
|
2671
|
+
},
|
|
2672
|
+
{
|
|
2673
|
+
id: 'dt-zhonghe',
|
|
2674
|
+
book: 'ditian',
|
|
2675
|
+
chapter: '通神论·中和',
|
|
2676
|
+
scene: '调候',
|
|
2677
|
+
tags: [],
|
|
2678
|
+
quote: '既识中和之正理,而于五行之妙,有全能焉。',
|
|
2679
|
+
plain: '懂得中和的道理,五行的妙处就都在其中了。',
|
|
2680
|
+
url: 'https://www.diancang.xyz/xuanxuewushu/ditiansui/153091.html',
|
|
2681
|
+
},
|
|
2682
|
+
{
|
|
2683
|
+
id: 'dt-guansha',
|
|
2684
|
+
book: 'ditian',
|
|
2685
|
+
chapter: '通神论·官杀',
|
|
2686
|
+
scene: '十神',
|
|
2687
|
+
tags: ['正官', '七杀'],
|
|
2688
|
+
quote: '官杀混杂来问我,有可有不可。',
|
|
2689
|
+
plain: '官杀混杂不是一律不好,要看能不能去留取清。',
|
|
2690
|
+
url: 'https://www.diancang.xyz/xuanxuewushu/ditiansui/153091.html',
|
|
2691
|
+
},
|
|
2692
|
+
{
|
|
2693
|
+
id: 'dt-shangguan',
|
|
2694
|
+
book: 'ditian',
|
|
2695
|
+
chapter: '通神论·伤官',
|
|
2696
|
+
scene: '十神',
|
|
2697
|
+
tags: ['伤官'],
|
|
2698
|
+
quote: '伤官见官最难辨,可见不可见。',
|
|
2699
|
+
plain: '伤官见官是最难分辨的一条:有的能见,有的不能见,不能一句「伤官见官为祸百端」了事。',
|
|
2700
|
+
url: 'https://www.diancang.xyz/xuanxuewushu/ditiansui/153091.html',
|
|
2701
|
+
},
|
|
2702
|
+
{
|
|
2703
|
+
id: 'dt-yueling',
|
|
2704
|
+
book: 'ditian',
|
|
2705
|
+
chapter: '通神论·月令',
|
|
2706
|
+
scene: '用神',
|
|
2707
|
+
tags: [],
|
|
2708
|
+
quote: '月令乃提纲之府,譬之宅也,人元为用事之神,宅之定向也,不可以不卜。',
|
|
2709
|
+
plain: '月令像宅子,藏干是用事之神,像宅子的朝向,必须细看。',
|
|
2710
|
+
url: 'https://www.diancang.xyz/xuanxuewushu/ditiansui/153091.html',
|
|
2711
|
+
},
|
|
2712
|
+
{
|
|
2713
|
+
id: 'dt-tiyong',
|
|
2714
|
+
book: 'ditian',
|
|
2715
|
+
chapter: '通神论·体用',
|
|
2716
|
+
scene: '用神',
|
|
2717
|
+
tags: [],
|
|
2718
|
+
quote: '道有体用,不可以一端论也,要在扶之抑之得其宜。',
|
|
2719
|
+
plain: '体用不能只看一头,关键是扶抑得宜。',
|
|
2720
|
+
url: 'https://www.diancang.xyz/xuanxuewushu/ditiansui/153091.html',
|
|
2721
|
+
},
|
|
2722
|
+
{
|
|
2723
|
+
id: 'dt-jingshen',
|
|
2724
|
+
book: 'ditian',
|
|
2725
|
+
chapter: '通神论·精神',
|
|
2726
|
+
scene: '用神',
|
|
2727
|
+
tags: [],
|
|
2728
|
+
quote: '人有精神,不可以一偏求也,要在损之益之得其中。',
|
|
2729
|
+
plain: '看精神不能偏执一端,要在损益之间求其中。',
|
|
2730
|
+
url: 'https://www.diancang.xyz/xuanxuewushu/ditiansui/153091.html',
|
|
2731
|
+
},
|
|
2732
|
+
{
|
|
2733
|
+
id: 'smt-zhenguan',
|
|
2734
|
+
book: 'sanming',
|
|
2735
|
+
chapter: '卷五·论正官',
|
|
2736
|
+
scene: '格局',
|
|
2737
|
+
tags: ['正官'],
|
|
2738
|
+
quote: '正官者,乃甲见辛、乙见庚之例。阴阳配合,相制有用,成其道也。故正官为六格之首,止许一位,多则不宜。',
|
|
2739
|
+
plain: '正官取「克我而阴阳相配」,有制而能成用;六格以正官居首,只宜一位,多见就杂。',
|
|
2740
|
+
url: 'https://www.diancang.xyz/xuanxuewushu/sanmingtonghui/7582.html',
|
|
2741
|
+
},
|
|
2742
|
+
{
|
|
2743
|
+
id: 'smt-zhengcai',
|
|
2744
|
+
book: 'sanming',
|
|
2745
|
+
chapter: '卷六·论正财',
|
|
2746
|
+
scene: '格局',
|
|
2747
|
+
tags: ['财'],
|
|
2748
|
+
quote: '正财者,乃甲见己、乙见戊之例。受我克制,为我之妻,譬人娶妻,妻赍财嫁我,我必精神康强,而后可享用,若衰微不振,虽妻财丰厚,但能目视,终不得用。',
|
|
2749
|
+
plain: '正财是我克制之物,古人以「娶妻带财」作比:自身精神康强才受用得起,身弱不振,财再厚也只是看着。',
|
|
2750
|
+
url: 'https://www.diancang.xyz/xuanxuewushu/sanmingtonghui/7645.html',
|
|
2751
|
+
},
|
|
2752
|
+
{
|
|
2753
|
+
id: 'smt-yinshou',
|
|
2754
|
+
book: 'sanming',
|
|
2755
|
+
chapter: '卷六·论印绶',
|
|
2756
|
+
scene: '格局',
|
|
2757
|
+
tags: ['印'],
|
|
2758
|
+
quote: '印绶者,乃五行生我之名。如甲乙在亥子月,丙丁在寅卯月之类,乃我气之源,为生气,为父母,能护我官星,使无伤克',
|
|
2759
|
+
plain: '印是生我之气,像源头与父母:它能护住官星,使官不受伤克;反过来说,印重就怕财来破。',
|
|
2760
|
+
url: 'https://www.diancang.xyz/xuanxuewushu/sanmingtonghui/7655.html',
|
|
2761
|
+
},
|
|
2762
|
+
{
|
|
2763
|
+
id: 'smt-shishen',
|
|
2764
|
+
book: 'sanming',
|
|
2765
|
+
chapter: '卷六·论食神',
|
|
2766
|
+
scene: '格局',
|
|
2767
|
+
tags: ['食神'],
|
|
2768
|
+
quote: '凡命遇财煞之地,食神旺相,煞被食制,不敢为祸,财被食生,充裕不竭,故食神一名寿星,一名爵星,良有以也。',
|
|
2769
|
+
plain: '食神旺,一头制煞、一头生财:煞被制住不敢为祸,财被生起不至枯竭;所以食神又叫寿星、爵星。',
|
|
2770
|
+
url: 'https://www.diancang.xyz/xuanxuewushu/sanmingtonghui/7663.html',
|
|
2771
|
+
},
|
|
2772
|
+
{
|
|
2773
|
+
id: 'smt-shangguan',
|
|
2774
|
+
book: 'sanming',
|
|
2775
|
+
chapter: '卷六·论伤官',
|
|
2776
|
+
scene: '格局',
|
|
2777
|
+
tags: ['伤官'],
|
|
2778
|
+
quote: '伤官虽凶,乃我所生,自家之物,伤尽则能生财,财旺则能生官,造化展转有情。',
|
|
2779
|
+
plain: '伤官虽称凶,却是我自己生出来的:伤尽(柱中不见官星)反能生财,财旺再生官,辗转还是有情。',
|
|
2780
|
+
url: 'https://www.diancang.xyz/xuanxuewushu/sanmingtonghui/7662.html',
|
|
2781
|
+
},
|
|
2782
|
+
{
|
|
2783
|
+
id: 'smt-yangren',
|
|
2784
|
+
book: 'sanming',
|
|
2785
|
+
chapter: '卷六·论阳刃',
|
|
2786
|
+
scene: '格局',
|
|
2787
|
+
tags: ['阳刃', '劫财'],
|
|
2788
|
+
quote: '阳者,阴阳之阳,刃者,刀刃之刃,即禄前一位,言旺越其分,故险。',
|
|
2789
|
+
plain: '阳刃指禄前一位,旺过了本分,所以险;甲丙戊庚壬五阳干才有刃,阴干见伤官同论。',
|
|
2790
|
+
url: 'https://www.diancang.xyz/xuanxuewushu/sanmingtonghui/7671.html',
|
|
2791
|
+
},
|
|
2792
|
+
{
|
|
2793
|
+
id: 'smt-jianlu',
|
|
2794
|
+
book: 'sanming',
|
|
2795
|
+
chapter: '卷六·论建禄',
|
|
2796
|
+
scene: '格局',
|
|
2797
|
+
tags: ['建禄', '比肩', '月劫'],
|
|
2798
|
+
quote: '凡命月令建禄,难招祖业,必主平生见财不聚,却病少寿长,行运再见比肩,克妻妨父损子',
|
|
2799
|
+
plain: '月令建禄是日主临官之地,身旺而财官难取:古说难承祖业、见财不聚,但病少寿长;再走比肩运,古书说克妻妨父损子(属于旧说的重话,本插件只记原文、不作断语)。',
|
|
2800
|
+
url: 'https://www.diancang.xyz/xuanxuewushu/sanmingtonghui/7672.html',
|
|
2801
|
+
},
|
|
2802
|
+
];
|
|
2803
|
+
|
|
2804
|
+
const BY_ID = CLASSICS.reduce((m, e) => { m[e.id] = e; return m; }, {});
|
|
2805
|
+
|
|
2806
|
+
const GEJU_KEY = {
|
|
2807
|
+
正官格: '正官',
|
|
2808
|
+
七杀格: '七杀',
|
|
2809
|
+
偏官格: '偏官',
|
|
2810
|
+
正财格: '财',
|
|
2811
|
+
偏财格: '财',
|
|
2812
|
+
正印格: '印',
|
|
2813
|
+
偏印格: '印',
|
|
2814
|
+
食神格: '食神',
|
|
2815
|
+
伤官格: '伤官',
|
|
2816
|
+
阳刃格: '阳刃',
|
|
2817
|
+
月劫格: '月劫',
|
|
2818
|
+
建禄格: '建禄',
|
|
2819
|
+
};
|
|
2820
|
+
|
|
2821
|
+
function classicOf(id) {
|
|
2822
|
+
return BY_ID[id] || null;
|
|
2823
|
+
}
|
|
2824
|
+
|
|
2825
|
+
function tagOf(gejuName) {
|
|
2826
|
+
const name = String(gejuName || '');
|
|
2827
|
+
if (GEJU_KEY[name]) return GEJU_KEY[name];
|
|
2828
|
+
const bare = name.replace(/格$/, '');
|
|
2829
|
+
return GEJU_KEY[bare + '格'] || bare;
|
|
2830
|
+
}
|
|
2831
|
+
|
|
2832
|
+
function pick(tag, book) {
|
|
2833
|
+
return CLASSICS.find((e) => e.scene === '格局' && e.tags.includes(tag) && (!book || e.book === book)) || null;
|
|
2834
|
+
}
|
|
2835
|
+
|
|
2836
|
+
function chapterTitle(e) {
|
|
2837
|
+
return e.chapter.replace(/^.*[、·]/, '').replace(/^论/, '');
|
|
2838
|
+
}
|
|
2839
|
+
|
|
2840
|
+
function classicsFor(r, limit = 5) {
|
|
2841
|
+
if (!r) return [];
|
|
2842
|
+
const out = [];
|
|
2843
|
+
const seen = new Set();
|
|
2844
|
+
const push = (entry, why) => {
|
|
2845
|
+
if (!entry || seen.has(entry.id) || out.length >= limit) return;
|
|
2846
|
+
seen.add(entry.id);
|
|
2847
|
+
out.push({ ...entry, why });
|
|
2848
|
+
};
|
|
2849
|
+
const gejuList = Array.isArray(r.geju) ? r.geju : (r.frame && Array.isArray(r.frame.geju) ? r.frame.geju : []);
|
|
2850
|
+
for (const g of gejuList) {
|
|
2851
|
+
if (!g || (g.kind && g.kind !== '月令格')) continue;
|
|
2852
|
+
const tag = tagOf(g.name);
|
|
2853
|
+
const primary = pick(tag, 'ziping') || pick(tag);
|
|
2854
|
+
if (primary) push(primary, `你的月令格局是「${g.name}」,故取${CLASSIC_BOOKS[primary.book].name}「${chapterTitle(primary)}」一条`);
|
|
2855
|
+
const alt = CLASSICS.find((e) => e.scene === '格局' && e.tags.includes(tag) && (!primary || e.book !== primary.book));
|
|
2856
|
+
if (alt) push(alt, `同是「${g.name}」,${CLASSIC_BOOKS[alt.book].name}「${chapterTitle(alt)}」另有取法,可对照读`);
|
|
2857
|
+
}
|
|
2858
|
+
const cli = r.climate || (r.frame && r.frame.yongshen && (r.frame.yongshen.climate || r.frame.yongshen.tiaohou));
|
|
2859
|
+
if (cli && cli.kind && cli.kind !== '平和') {
|
|
2860
|
+
const cold = !!(cli.cold || cli.kind.indexOf('寒') >= 0);
|
|
2861
|
+
const hot = !!(cli.hot || cli.kind.indexOf('热') >= 0);
|
|
2862
|
+
push(classicOf(cold ? 'dt-hannuan' : 'dt-zaoshi'), `本盘气候判为「${cli.kind}」,故取${CLASSIC_BOOKS.ditian.name}寒暖燥湿一条`);
|
|
2863
|
+
push(classicOf('zp-qihou'), '气候与月令用神要互参,故取子平真诠「用神配气候」一条');
|
|
2864
|
+
if (hot) push(classicOf('dt-hannuan'), '本盘偏热,寒暖一条正对');
|
|
2865
|
+
}
|
|
2866
|
+
const huagi = gejuList.find((g) => g && g.kind === '化气格');
|
|
2867
|
+
const combo = gejuList.find((g) => g && g.kind === '组合');
|
|
2868
|
+
if (huagi) {
|
|
2869
|
+
push(classicOf('zp-bianhua'), `本盘列有「${huagi.name}」:用神由月令合化而变,总纲一位改取${CLASSIC_BOOKS.ziping.name}论用神变化`);
|
|
2870
|
+
} else if (combo) {
|
|
2871
|
+
push(classicOf('zp-chengbai'), `本盘另有「${combo.name}」组合:成格还要看带忌与救应,总纲一位改取${CLASSIC_BOOKS.ziping.name}论用神成败救应`);
|
|
2872
|
+
} else {
|
|
2873
|
+
push(classicOf('zp-yongshen'), '用神从月令取、四吉顺用四凶逆用,是通用总纲');
|
|
2874
|
+
}
|
|
2875
|
+
return out;
|
|
2876
|
+
}
|
|
2877
|
+
|
|
2878
|
+
function classicsText(rows) {
|
|
2879
|
+
if (!rows || !rows.length) return '';
|
|
2880
|
+
return rows.map((e) => `《${CLASSIC_BOOKS[e.book].name}·${e.chapter}》「${e.quote}」`).join('\n');
|
|
2881
|
+
}
|
|
2882
|
+
|
|
2883
|
+
return { CLASSIC_BOOKS, CLASSICS, classicOf, classicsFor, classicsText };
|
|
2884
|
+
})();
|
|
2885
|
+
|
|
2512
2886
|
__mods.geju = (function () {
|
|
2513
2887
|
|
|
2514
2888
|
const { judgeClimate, arbitrate } = __mods.tiaohou;
|
|
@@ -2849,7 +3223,7 @@ __mods.bazi = (function () {
|
|
|
2849
3223
|
const { STEMS, BRANCHES, TERM_NAMES, ganzhiName, dayGanzhiIndex, jdToParts, partsToJd, sexagenaryIndex, termWindow, previousJie, nextJie, equationOfTime, formatJd, xunKongOf } = __mods.calendar;
|
|
2850
3224
|
const { resolveAddress } = __mods.geo;
|
|
2851
3225
|
const { computeBaziShensha } = __mods.shensha;
|
|
2852
|
-
const { assertCivil } = __mods.validate;
|
|
3226
|
+
const { assertCivil, daysInMonth } = __mods.validate;
|
|
2853
3227
|
const { applyDst } = __mods.dst;
|
|
2854
3228
|
const { nayinOf } = __mods.nayin;
|
|
2855
3229
|
const { SANHE } = __mods.sanhe;
|
|
@@ -3092,10 +3466,23 @@ function buildBazi(input) {
|
|
|
3092
3466
|
let startAgeMonths = Math.round(totalMonths % 12);
|
|
3093
3467
|
if (startAgeMonths >= 12) { startAgeMonths -= 12; startAgeYears += 1; }
|
|
3094
3468
|
|
|
3469
|
+
const JIAO_YEAR_DAYS = 365.2422;
|
|
3470
|
+
const JIAO_SCALE = JIAO_YEAR_DAYS / 3;
|
|
3471
|
+
const jiaoFromTerm = forward ? nextJieTerm : prevJieTerm;
|
|
3472
|
+
const jiaoJd = jd + spanDays * JIAO_SCALE;
|
|
3473
|
+
const jiaoParts = jdToParts(jiaoJd);
|
|
3474
|
+
const addYearsClamped = (p, n) => {
|
|
3475
|
+
const y = p.year + n;
|
|
3476
|
+
return { year: y, month: p.month, day: Math.min(p.day, daysInMonth(y, p.month)), hour: p.hour, minute: p.minute };
|
|
3477
|
+
};
|
|
3478
|
+
|
|
3095
3479
|
const dayun = [];
|
|
3480
|
+
const dayunWindows = [];
|
|
3096
3481
|
for (let i = 1; i <= 8; i++) {
|
|
3097
3482
|
const idx = (((monthIdx + (forward ? i : -i)) % 60) + 60) % 60;
|
|
3098
3483
|
const g = ganzhiName(idx);
|
|
3484
|
+
const fromJd = partsToJd(addYearsClamped(jiaoParts, (i - 1) * 10));
|
|
3485
|
+
const toJd = partsToJd(addYearsClamped(jiaoParts, i * 10));
|
|
3099
3486
|
dayun.push({
|
|
3100
3487
|
step: i,
|
|
3101
3488
|
startAge: startAgeYears + (i - 1) * 10,
|
|
@@ -3104,7 +3491,10 @@ function buildBazi(input) {
|
|
|
3104
3491
|
branch: g.branch,
|
|
3105
3492
|
stemTenGod: tenGod(dayStem, g.stem),
|
|
3106
3493
|
nayin: nayin(idx),
|
|
3494
|
+
fromDate: formatJd(fromJd),
|
|
3495
|
+
toDate: formatJd(toJd),
|
|
3107
3496
|
});
|
|
3497
|
+
dayunWindows.push({ step: i, ganzhi: g.name, fromJd, toJd });
|
|
3108
3498
|
}
|
|
3109
3499
|
|
|
3110
3500
|
const thisYear = Number(input.nowYear) || new Date().getFullYear();
|
|
@@ -3245,6 +3635,45 @@ function buildBazi(input) {
|
|
|
3245
3635
|
l.luck = scoreLuck(l.ganzhi, frame);
|
|
3246
3636
|
}
|
|
3247
3637
|
|
|
3638
|
+
const NATAL_LABEL = { year: '年柱', month: '月柱', day: '日柱', hour: '时柱' };
|
|
3639
|
+
const stemOvercomes = (a, b) => OVERCOMES[STEM_ELEMENT[a]] === STEM_ELEMENT[b];
|
|
3640
|
+
const tianKeDiChong = (a, b) => {
|
|
3641
|
+
if (typeof a !== 'string' || typeof b !== 'string' || a.length < 2 || b.length < 2) return false;
|
|
3642
|
+
if (!(a[0] in STEM_ELEMENT) || !(b[0] in STEM_ELEMENT)) return false;
|
|
3643
|
+
return (stemOvercomes(a[0], b[0]) || stemOvercomes(b[0], a[0])) && hasPair(BRANCH_CHONG, a[1], b[1]);
|
|
3644
|
+
};
|
|
3645
|
+
const lichunJd = (y) => {
|
|
3646
|
+
const t = termWindow(y, { jieOnly: true }).find((x) => x.index === 2 && jdToParts(x.jd).year === y);
|
|
3647
|
+
return t ? t.jd : partsToJd({ year: y, month: 2, day: 4 });
|
|
3648
|
+
};
|
|
3649
|
+
for (const l of liunian) {
|
|
3650
|
+
const yStart = lichunJd(l.year);
|
|
3651
|
+
const yEnd = lichunJd(l.year + 1);
|
|
3652
|
+
const active = dayunWindows.filter((w) => w.fromJd < yEnd && w.toJd > yStart);
|
|
3653
|
+
const signals = [];
|
|
3654
|
+
for (const w of active) {
|
|
3655
|
+
if (w.ganzhi === l.ganzhi) {
|
|
3656
|
+
signals.push({ type: '岁运并临', target: `第${w.step}步大运`, detail: `大运与流年同为${l.ganzhi}` });
|
|
3657
|
+
} else if (tianKeDiChong(w.ganzhi, l.ganzhi)) {
|
|
3658
|
+
signals.push({ type: '运年反吟', target: `第${w.step}步大运`, detail: `大运${w.ganzhi}与流年${l.ganzhi}天克地冲` });
|
|
3659
|
+
}
|
|
3660
|
+
}
|
|
3661
|
+
for (const key of ['year', 'month', 'day', 'hour']) {
|
|
3662
|
+
const g = pillars[key].ganzhi;
|
|
3663
|
+
if (!g) continue;
|
|
3664
|
+
if (l.ganzhi === g) {
|
|
3665
|
+
signals.push({ type: '流年伏吟', target: NATAL_LABEL[key], detail: `流年${l.ganzhi}与${NATAL_LABEL[key]}同干支` });
|
|
3666
|
+
} else if (tianKeDiChong(l.ganzhi, g)) {
|
|
3667
|
+
signals.push({ type: '流年反吟', target: NATAL_LABEL[key], detail: `流年${l.ganzhi}与${NATAL_LABEL[key]}${g}天克地冲` });
|
|
3668
|
+
}
|
|
3669
|
+
}
|
|
3670
|
+
l.suiyun = {
|
|
3671
|
+
dayun: active.map((w) => ({ step: w.step, ganzhi: w.ganzhi })),
|
|
3672
|
+
signals,
|
|
3673
|
+
note: '只标干支重复与天克地冲这类变动信号,不判吉凶;大运按该年立春到次年立春的区间取,交运落在年内时前后两步并列',
|
|
3674
|
+
};
|
|
3675
|
+
}
|
|
3676
|
+
|
|
3248
3677
|
const p = jdToParts(jd);
|
|
3249
3678
|
|
|
3250
3679
|
const mStemIdx = STEMS.indexOf(pillars.month.stem);
|
|
@@ -3299,6 +3728,17 @@ function buildBazi(input) {
|
|
|
3299
3728
|
rule: `${isYangYear ? '阳' : '阴'}年${gender === 'male' ? '男' : '女'}${forward ? '顺排' : '逆排'}`,
|
|
3300
3729
|
startAge: { years: startAgeYears, months: startAgeMonths },
|
|
3301
3730
|
toNextJieDays: Math.round(spanDays * 100) / 100,
|
|
3731
|
+
jiao: {
|
|
3732
|
+
at: formatJd(jiaoJd),
|
|
3733
|
+
jd: Math.round(jiaoJd * 1e6) / 1e6,
|
|
3734
|
+
scaleDaysPerDay: JIAO_SCALE,
|
|
3735
|
+
yearDays: JIAO_YEAR_DAYS,
|
|
3736
|
+
spanDays: Math.round(spanDays * 1e4) / 1e4,
|
|
3737
|
+
from: { name: jiaoFromTerm.name, time: formatJd(jiaoFromTerm.jd) },
|
|
3738
|
+
frame: solar.offsetMinutes ? '真太阳时' : '平太阳时',
|
|
3739
|
+
offsetMinutes: solar.offsetMinutes,
|
|
3740
|
+
note: '三日折一年:出生到节令的真实间隔按 365.2422/3 放大后加到出生时刻;同一比例即「一日折四月、一时辰折十日」,每步大运在同月同日同时刻换',
|
|
3741
|
+
},
|
|
3302
3742
|
list: dayun,
|
|
3303
3743
|
},
|
|
3304
3744
|
strength,
|
|
@@ -3360,8 +3800,133 @@ const GENERATES = { 木: '火', 火: '土', 土: '金', 金: '水', 水: '木' }
|
|
|
3360
3800
|
const OVERCOMES = { 木: '土', 土: '水', 水: '火', 火: '金', 金: '木' };
|
|
3361
3801
|
|
|
3362
3802
|
const LIUSHEN = ['青龙', '朱雀', '勾陈', '螣蛇', '白虎', '玄武'];
|
|
3803
|
+
const LIUQIN_NAMES = ['父母', '兄弟', '子孙', '妻财', '官鬼'];
|
|
3363
3804
|
const LIUSHEN_START = { 甲: 0, 乙: 0, 丙: 1, 丁: 1, 戊: 2, 己: 3, 庚: 4, 辛: 4, 壬: 5, 癸: 5 };
|
|
3364
3805
|
|
|
3806
|
+
const ZHI_CHONG_PAIRS = [['子', '午'], ['丑', '未'], ['寅', '申'], ['卯', '酉'], ['辰', '戌'], ['巳', '亥']];
|
|
3807
|
+
const ZHI_HE_PAIRS = [['子', '丑'], ['寅', '亥'], ['卯', '戌'], ['辰', '酉'], ['巳', '申'], ['午', '未']];
|
|
3808
|
+
const CHONG_OF = Object.fromEntries(ZHI_CHONG_PAIRS.flatMap(([a, b]) => [[a, b], [b, a]]));
|
|
3809
|
+
const TRIGRAM_OPPOSITE = { 乾: '巽', 巽: '乾', 坎: '离', 离: '坎', 艮: '坤', 坤: '艮', 震: '兑', 兑: '震' };
|
|
3810
|
+
|
|
3811
|
+
const JIN_TUI_PAIRS = [['寅', '卯'], ['巳', '午'], ['申', '酉'], ['亥', '子'], ['丑', '辰'], ['辰', '未'], ['未', '戌'], ['戌', '丑']];
|
|
3812
|
+
const JIN_OF = new Map(JIN_TUI_PAIRS);
|
|
3813
|
+
const TUI_OF = new Map(JIN_TUI_PAIRS.map(([a, b]) => [b, a]));
|
|
3814
|
+
|
|
3815
|
+
function jinTuiOf(from, to) {
|
|
3816
|
+
if (!from || !to || from === to) return null;
|
|
3817
|
+
if (JIN_OF.get(from) === to) return '进';
|
|
3818
|
+
if (TUI_OF.get(from) === to) return '退';
|
|
3819
|
+
return null;
|
|
3820
|
+
}
|
|
3821
|
+
|
|
3822
|
+
function pairThirds(branches, table) {
|
|
3823
|
+
const cnt = new Map();
|
|
3824
|
+
for (const b of branches) cnt.set(b, (cnt.get(b) || 0) + 1);
|
|
3825
|
+
const hits = [];
|
|
3826
|
+
for (const [a, b] of table) {
|
|
3827
|
+
const na = cnt.get(a) || 0;
|
|
3828
|
+
const nb = cnt.get(b) || 0;
|
|
3829
|
+
if (!na && !nb) continue;
|
|
3830
|
+
if (na !== 1 || nb !== 1) return null;
|
|
3831
|
+
cnt.set(a, 0);
|
|
3832
|
+
cnt.set(b, 0);
|
|
3833
|
+
hits.push([a, b]);
|
|
3834
|
+
}
|
|
3835
|
+
return hits.length * 2 === branches.length ? hits : null;
|
|
3836
|
+
}
|
|
3837
|
+
|
|
3838
|
+
function hexBranches(hex) {
|
|
3839
|
+
const inner = NAJIA[hex.lower].inner.slice();
|
|
3840
|
+
const outer = NAJIA[hex.upper].outer.slice();
|
|
3841
|
+
return { inner, outer, all: [...inner, ...outer] };
|
|
3842
|
+
}
|
|
3843
|
+
|
|
3844
|
+
function hexBody(hex) {
|
|
3845
|
+
const { inner, outer, all } = hexBranches(hex);
|
|
3846
|
+
const chongPairs = pairThirds(all, ZHI_CHONG_PAIRS);
|
|
3847
|
+
const hePairs = pairThirds(all, ZHI_HE_PAIRS);
|
|
3848
|
+
return {
|
|
3849
|
+
name: hex.name,
|
|
3850
|
+
upper: hex.upper,
|
|
3851
|
+
lower: hex.lower,
|
|
3852
|
+
inner,
|
|
3853
|
+
outer,
|
|
3854
|
+
chong: Boolean(chongPairs),
|
|
3855
|
+
he: Boolean(hePairs),
|
|
3856
|
+
chongPairs: chongPairs || [],
|
|
3857
|
+
hePairs: hePairs || [],
|
|
3858
|
+
};
|
|
3859
|
+
}
|
|
3860
|
+
|
|
3861
|
+
function bodyRelations(ben, bian = null, moving = []) {
|
|
3862
|
+
const b = hexBody(ben);
|
|
3863
|
+
const out = {
|
|
3864
|
+
ben: { name: b.name, chong: b.chong, he: b.he, chongPairs: b.chongPairs, hePairs: b.hePairs, inner: b.inner, outer: b.outer },
|
|
3865
|
+
bian: null,
|
|
3866
|
+
fuYin: { inner: false, outer: false },
|
|
3867
|
+
fanYin: { inner: null, outer: null }, // null 或 { by: ['chong'|'pair'] }
|
|
3868
|
+
yaoFuYin: [],
|
|
3869
|
+
yaoFanYin: [],
|
|
3870
|
+
jinTui: [], // [{ position, from, to, type: '进'|'退' }]
|
|
3871
|
+
};
|
|
3872
|
+
if (!bian) return out;
|
|
3873
|
+
|
|
3874
|
+
const v = hexBody(bian);
|
|
3875
|
+
out.bian = { name: v.name, chong: v.chong, he: v.he, chongPairs: v.chongPairs, hePairs: v.hePairs, inner: v.inner, outer: v.outer };
|
|
3876
|
+
|
|
3877
|
+
for (const side of ['inner', 'outer']) {
|
|
3878
|
+
const x = b[side];
|
|
3879
|
+
const y = v[side];
|
|
3880
|
+
const tri = side === 'inner' ? [ben.lower, bian.lower] : [ben.upper, bian.upper];
|
|
3881
|
+
const changed = tri[0] !== tri[1];
|
|
3882
|
+
if (changed && x.every((z, i) => z === y[i])) {
|
|
3883
|
+
out.fuYin[side] = true;
|
|
3884
|
+
continue;
|
|
3885
|
+
}
|
|
3886
|
+
const by = [];
|
|
3887
|
+
if (changed && x.every((z, i) => CHONG_OF[z] === y[i])) by.push('chong');
|
|
3888
|
+
if (changed && TRIGRAM_OPPOSITE[tri[0]] === tri[1]) by.push('pair');
|
|
3889
|
+
if (by.length) out.fanYin[side] = { by };
|
|
3890
|
+
}
|
|
3891
|
+
|
|
3892
|
+
for (const p of moving) {
|
|
3893
|
+
const i = p - 1;
|
|
3894
|
+
if (!(i >= 0 && i < 6)) continue;
|
|
3895
|
+
const x = i < 3 ? b.inner[i] : b.outer[i - 3];
|
|
3896
|
+
const y = i < 3 ? v.inner[i] : v.outer[i - 3];
|
|
3897
|
+
if (x === y) out.yaoFuYin.push(p);
|
|
3898
|
+
else if (CHONG_OF[x] === y) out.yaoFanYin.push(p);
|
|
3899
|
+
const jt = jinTuiOf(x, y);
|
|
3900
|
+
if (jt) out.jinTui.push({ position: p, from: x, to: y, type: jt });
|
|
3901
|
+
}
|
|
3902
|
+
return out;
|
|
3903
|
+
}
|
|
3904
|
+
|
|
3905
|
+
function bodyLabels(body) {
|
|
3906
|
+
if (!body || !body.ben) return [];
|
|
3907
|
+
const fuYin = body.fuYin || {};
|
|
3908
|
+
const fanYin = body.fanYin || {};
|
|
3909
|
+
const yaoFuYin = body.yaoFuYin || [];
|
|
3910
|
+
const yaoFanYin = body.yaoFanYin || [];
|
|
3911
|
+
const out = [];
|
|
3912
|
+
if (body.ben.chong) out.push('六冲卦');
|
|
3913
|
+
if (body.ben.he) out.push('六合卦');
|
|
3914
|
+
if (body.bian) {
|
|
3915
|
+
if (body.bian.chong) out.push('变六冲');
|
|
3916
|
+
else if (body.bian.he) out.push('变六合');
|
|
3917
|
+
}
|
|
3918
|
+
const sides = [['inner', '内卦'], ['outer', '外卦']];
|
|
3919
|
+
for (const [k, label] of sides) if (fuYin[k]) out.push(`${label}伏吟`);
|
|
3920
|
+
for (const [k, label] of sides) if (fanYin[k]) out.push(`${label}反吟`);
|
|
3921
|
+
if (yaoFuYin.length) out.push(`爻伏吟 ${yaoFuYin.join('、')}`);
|
|
3922
|
+
if (yaoFanYin.length) out.push(`爻反吟 ${yaoFanYin.join('、')}`);
|
|
3923
|
+
const jin = (body.jinTui || []).filter((x) => x.type === '进').map((x) => x.position);
|
|
3924
|
+
const tui = (body.jinTui || []).filter((x) => x.type === '退').map((x) => x.position);
|
|
3925
|
+
if (jin.length) out.push(`化进神 ${jin.join('、')}`);
|
|
3926
|
+
if (tui.length) out.push(`化退神 ${tui.join('、')}`);
|
|
3927
|
+
return out;
|
|
3928
|
+
}
|
|
3929
|
+
|
|
3365
3930
|
function liuqin(palaceElement, branchElement) {
|
|
3366
3931
|
if (palaceElement === branchElement) return '兄弟';
|
|
3367
3932
|
if (GENERATES[branchElement] === palaceElement) return '父母';
|
|
@@ -3416,6 +3981,166 @@ function hexagramFromBits(bits) {
|
|
|
3416
3981
|
return HEXAGRAM_INDEX.get(`${upper}|${lower}`);
|
|
3417
3982
|
}
|
|
3418
3983
|
|
|
3984
|
+
const PURE_BY_PALACE = new Map();
|
|
3985
|
+
for (const h of HEXAGRAM_INDEX.values()) if (h.order === 0) PURE_BY_PALACE.set(h.palace, h);
|
|
3986
|
+
|
|
3987
|
+
const YONGSHEN_RULES = Object.freeze({
|
|
3988
|
+
wealth: { liuqin: '妻财', ask: '求财、收入、订单' },
|
|
3989
|
+
career: { liuqin: '官鬼', ask: '工作、职位、考核' },
|
|
3990
|
+
health: { liuqin: '官鬼', ask: '病与压力(子孙为医药)' },
|
|
3991
|
+
study: { liuqin: '父母', ask: '考试、证书、文书合同' },
|
|
3992
|
+
love: { liuqin: null, ask: '感情:男看妻财、女看官鬼' },
|
|
3993
|
+
travel: { liuqin: null, ask: '出行以世爻为用,父母为舟车' },
|
|
3994
|
+
general: { liuqin: null, ask: '未指明所问之事' },
|
|
3995
|
+
});
|
|
3996
|
+
|
|
3997
|
+
const WUXING_SAY = {
|
|
3998
|
+
飞生伏: '飞神生伏神,伏神借得上力',
|
|
3999
|
+
伏生飞: '伏神生飞神,力气往外泄',
|
|
4000
|
+
飞克伏: '飞神克伏神,伏神受压难出',
|
|
4001
|
+
伏克飞: '伏神克飞神,伏神能自出',
|
|
4002
|
+
比和: '飞伏比和,同气相求',
|
|
4003
|
+
};
|
|
4004
|
+
|
|
4005
|
+
const RELATION_LABEL = {
|
|
4006
|
+
飞生伏: '伏神得飞神生',
|
|
4007
|
+
伏生飞: '伏神泄气于飞神',
|
|
4008
|
+
飞克伏: '伏神受飞神克',
|
|
4009
|
+
伏克飞: '伏神克飞神可出',
|
|
4010
|
+
比和: '飞伏比和',
|
|
4011
|
+
};
|
|
4012
|
+
|
|
4013
|
+
function wuxingBetween(min, max) {
|
|
4014
|
+
if (GENERATES[max] === min) return '飞生伏';
|
|
4015
|
+
if (GENERATES[min] === max) return '伏生飞';
|
|
4016
|
+
if (OVERCOMES[max] === min) return '飞克伏';
|
|
4017
|
+
if (OVERCOMES[min] === max) return '伏克飞';
|
|
4018
|
+
return '比和';
|
|
4019
|
+
}
|
|
4020
|
+
|
|
4021
|
+
const sideOf = (position) => (position <= 3 ? 'inner' : 'outer');
|
|
4022
|
+
|
|
4023
|
+
function yongshenOf(result, opts = {}) {
|
|
4024
|
+
const r = result && typeof result === 'object' ? result : {};
|
|
4025
|
+
const ben = r.ben && typeof r.ben === 'object' ? r.ben : {};
|
|
4026
|
+
const lines = Array.isArray(ben.lines) ? ben.lines : [];
|
|
4027
|
+
const direction = YONGSHEN_RULES[opts.direction] ? opts.direction : 'general';
|
|
4028
|
+
const rule = YONGSHEN_RULES[direction];
|
|
4029
|
+
const gender = opts.gender === 'female' ? 'female' : 'male';
|
|
4030
|
+
const body = r.body && typeof r.body === 'object' ? r.body : {};
|
|
4031
|
+
const kongArr = Array.isArray(r.xunKong)
|
|
4032
|
+
? r.xunKong
|
|
4033
|
+
: (typeof r.xunKong === 'string' ? r.xunKong.split('') : []);
|
|
4034
|
+
|
|
4035
|
+
const direct = LIUQIN_NAMES.includes(opts.liuqin) ? opts.liuqin : null;
|
|
4036
|
+
const byShi = !direct && direction === 'travel';
|
|
4037
|
+
const liuqinName = direct || (byShi ? '世' : (direction === 'love' ? (gender === 'female' ? '官鬼' : '妻财') : rule.liuqin));
|
|
4038
|
+
const base = {
|
|
4039
|
+
direction,
|
|
4040
|
+
gender,
|
|
4041
|
+
ask: rule.ask,
|
|
4042
|
+
byShi,
|
|
4043
|
+
liuqin: liuqinName,
|
|
4044
|
+
found: [],
|
|
4045
|
+
missing: false,
|
|
4046
|
+
fushen: [],
|
|
4047
|
+
labels: [],
|
|
4048
|
+
};
|
|
4049
|
+
if (!liuqinName) { base.labels = ['用神未取(未指明所问之事)']; return base; }
|
|
4050
|
+
|
|
4051
|
+
const found = byShi
|
|
4052
|
+
? lines.filter((l) => l.position === ben.shi)
|
|
4053
|
+
: lines.filter((l) => l.liuqin === liuqinName);
|
|
4054
|
+
base.found = found.map((l) => ({
|
|
4055
|
+
position: l.position,
|
|
4056
|
+
name: l.name,
|
|
4057
|
+
liuqin: l.liuqin,
|
|
4058
|
+
branch: l.branch,
|
|
4059
|
+
element: l.element,
|
|
4060
|
+
ganzhi: l.ganzhi,
|
|
4061
|
+
moving: Boolean(l.moving),
|
|
4062
|
+
liushen: l.liushen,
|
|
4063
|
+
shi: l.position === ben.shi,
|
|
4064
|
+
ying: l.position === ben.ying,
|
|
4065
|
+
kong: kongArr.includes(l.branch),
|
|
4066
|
+
}));
|
|
4067
|
+
|
|
4068
|
+
const labels = [];
|
|
4069
|
+
const label = byShi ? '用神 世爻' : `用神 ${liuqinName}`;
|
|
4070
|
+
labels.push(label);
|
|
4071
|
+
const jin = (body.jinTui || []).filter((x) => x.type === '进').map((x) => x.position);
|
|
4072
|
+
const tui = (body.jinTui || []).filter((x) => x.type === '退').map((x) => x.position);
|
|
4073
|
+
const yaoFu = body.yaoFuYin || [];
|
|
4074
|
+
const yaoFan = body.yaoFanYin || [];
|
|
4075
|
+
|
|
4076
|
+
if (found.length) {
|
|
4077
|
+
labels.push(`${label}在 ${found.map((l) => `${l.position}爻`).join('、')}`);
|
|
4078
|
+
if (found.length > 1) labels.push(`用神两现 ${found.map((l) => l.position).join('、')}`);
|
|
4079
|
+
if (found.some((l) => l.position === ben.shi)) labels.push('用神持世');
|
|
4080
|
+
if (found.some((l) => l.position === ben.ying)) labels.push('用神临应');
|
|
4081
|
+
if (found.some((l) => l.moving)) labels.push('用神发动');
|
|
4082
|
+
if (found.some((l) => kongArr.includes(l.branch))) labels.push('用神空亡');
|
|
4083
|
+
if (found.some((l) => jin.includes(l.position))) labels.push('用神化进神');
|
|
4084
|
+
if (found.some((l) => tui.includes(l.position))) labels.push('用神化退神');
|
|
4085
|
+
if (found.some((l) => yaoFu.includes(l.position))) labels.push('用神爻伏吟');
|
|
4086
|
+
if (found.some((l) => yaoFan.includes(l.position))) labels.push('用神爻反吟');
|
|
4087
|
+
} else {
|
|
4088
|
+
base.missing = true;
|
|
4089
|
+
const palace = String(ben.palace || '').replace(/宫$/, '');
|
|
4090
|
+
const pure = PURE_BY_PALACE.get(palace) || null;
|
|
4091
|
+
if (pure) {
|
|
4092
|
+
for (let i = 0; i < 6; i++) {
|
|
4093
|
+
const isInner = i < 3;
|
|
4094
|
+
const nj = NAJIA[isInner ? pure.lower : pure.upper];
|
|
4095
|
+
const branch = isInner ? nj.inner[i] : nj.outer[i - 3];
|
|
4096
|
+
const gan = isInner ? nj.gan[0] : nj.gan[1];
|
|
4097
|
+
const element = BRANCH_ELEMENT[branch];
|
|
4098
|
+
if (liuqin(pure.palaceElement, element) !== liuqinName) continue;
|
|
4099
|
+
const fei = lines[i] || null;
|
|
4100
|
+
const relation = fei ? wuxingBetween(element, fei.element) : null;
|
|
4101
|
+
base.fushen.push({
|
|
4102
|
+
position: i + 1,
|
|
4103
|
+
liuqin: liuqinName,
|
|
4104
|
+
branch,
|
|
4105
|
+
element,
|
|
4106
|
+
ganzhi: gan + branch,
|
|
4107
|
+
relation,
|
|
4108
|
+
fei: fei ? { position: fei.position, liuqin: fei.liuqin, branch: fei.branch, element: fei.element, ganzhi: fei.ganzhi } : null,
|
|
4109
|
+
});
|
|
4110
|
+
}
|
|
4111
|
+
}
|
|
4112
|
+
if (base.fushen.length) {
|
|
4113
|
+
labels.push(`用神不上卦·伏于 ${base.fushen.map((f) => `${f.position}爻`).join('、')}`);
|
|
4114
|
+
if (base.fushen.length > 1) labels.push(`伏神两现 ${base.fushen.map((f) => f.position).join('、')}`);
|
|
4115
|
+
const rels = [...new Set(base.fushen.map((f) => f.relation).filter(Boolean))];
|
|
4116
|
+
for (const rel of rels) labels.push(RELATION_LABEL[rel] || `伏神${rel}`);
|
|
4117
|
+
} else {
|
|
4118
|
+
labels.push('用神不上卦');
|
|
4119
|
+
}
|
|
4120
|
+
}
|
|
4121
|
+
|
|
4122
|
+
const sides = found.length ? [...new Set(found.map((l) => sideOf(l.position)))] : [];
|
|
4123
|
+
if (body.ben) {
|
|
4124
|
+
if (body.ben.chong) labels.push('用神在六冲卦');
|
|
4125
|
+
if (body.ben.he) labels.push('用神在六合卦');
|
|
4126
|
+
if (body.bian && body.bian.chong) labels.push('用神逢变六冲');
|
|
4127
|
+
if (body.bian && body.bian.he) labels.push('用神逢变六合');
|
|
4128
|
+
}
|
|
4129
|
+
for (const side of sides) {
|
|
4130
|
+
if (body.fuYin && body.fuYin[side]) labels.push(`用神在${side === 'inner' ? '内' : '外'}卦伏吟`);
|
|
4131
|
+
if (body.fanYin && body.fanYin[side]) {
|
|
4132
|
+
const by = (body.fanYin[side].by || []).includes('chong') ? '地支全冲' : '八卦正对';
|
|
4133
|
+
labels.push(`用神在${side === 'inner' ? '内' : '外'}卦反吟`);
|
|
4134
|
+
labels.push(`反吟来源:${by}`);
|
|
4135
|
+
}
|
|
4136
|
+
}
|
|
4137
|
+
|
|
4138
|
+
base.labels = labels;
|
|
4139
|
+
base.relationSay = base.fushen.map((f) => WUXING_SAY[f.relation]).filter(Boolean);
|
|
4140
|
+
base.side = sides.length === 1 ? (sides[0] === 'inner' ? '内卦' : '外卦') : null;
|
|
4141
|
+
return base;
|
|
4142
|
+
}
|
|
4143
|
+
|
|
3419
4144
|
function tossLines(random = Math.random) {
|
|
3420
4145
|
const lines = [];
|
|
3421
4146
|
for (let i = 0; i < 6; i++) {
|
|
@@ -3531,10 +4256,253 @@ function buildLiuyao(input = {}) {
|
|
|
3531
4256
|
lines: bianRows,
|
|
3532
4257
|
}
|
|
3533
4258
|
: null,
|
|
4259
|
+
body: (() => {
|
|
4260
|
+
const body = bodyRelations(ben, bian, moving.map((i) => i + 1));
|
|
4261
|
+
body.labels = bodyLabels(body);
|
|
4262
|
+
return body;
|
|
4263
|
+
})(),
|
|
4264
|
+
};
|
|
4265
|
+
}
|
|
4266
|
+
|
|
4267
|
+
const ZHI_ELEMENT = {
|
|
4268
|
+
子: '水', 丑: '土', 寅: '木', 卯: '木', 辰: '土', 巳: '火',
|
|
4269
|
+
午: '火', 未: '土', 申: '金', 酉: '金', 戌: '土', 亥: '水',
|
|
4270
|
+
};
|
|
4271
|
+
const ELEMENT_SHENG = { 木: '火', 火: '土', 土: '金', 金: '水', 水: '木' };
|
|
4272
|
+
const ELEMENT_KE = { 木: '土', 土: '水', 水: '火', 火: '金', 金: '木' };
|
|
4273
|
+
const MONTH_STATE_ORDER = ['旺', '相', '休', '囚', '死'];
|
|
4274
|
+
const MONTH_STATE_SAY = {
|
|
4275
|
+
旺: '与月令同气,当令得时',
|
|
4276
|
+
相: '受月令之生,气有余',
|
|
4277
|
+
休: '生月令而气泄,力减',
|
|
4278
|
+
囚: '克月令而力困',
|
|
4279
|
+
死: '被月令所克,气受制',
|
|
4280
|
+
};
|
|
4281
|
+
const DAY_RELATION_ORDER = ['日生', '日克', '比和', '泄', '耗'];
|
|
4282
|
+
const DAY_RELATION_SAY = {
|
|
4283
|
+
日生: '日辰生扶,当天有人托着',
|
|
4284
|
+
日克: '日辰克制,当天被压一头',
|
|
4285
|
+
比和: '与日辰同气,当天得到同类之助',
|
|
4286
|
+
泄: '生扶日辰,气往外走',
|
|
4287
|
+
耗: '克制日辰,力有所耗',
|
|
4288
|
+
};
|
|
4289
|
+
|
|
4290
|
+
function zhiElementOf(branch) {
|
|
4291
|
+
return ZHI_ELEMENT[branch] || null;
|
|
4292
|
+
}
|
|
4293
|
+
|
|
4294
|
+
function monthStateOf(element, monthElement) {
|
|
4295
|
+
if (!element || !monthElement) return 'unknown';
|
|
4296
|
+
if (element === monthElement) return '旺';
|
|
4297
|
+
if (ELEMENT_SHENG[monthElement] === element) return '相';
|
|
4298
|
+
if (ELEMENT_SHENG[element] === monthElement) return '休';
|
|
4299
|
+
if (ELEMENT_KE[element] === monthElement) return '囚';
|
|
4300
|
+
if (ELEMENT_KE[monthElement] === element) return '死';
|
|
4301
|
+
return 'unknown';
|
|
4302
|
+
}
|
|
4303
|
+
|
|
4304
|
+
function dayRelationOf(element, dayElement) {
|
|
4305
|
+
if (!element || !dayElement) return 'unknown';
|
|
4306
|
+
if (element === dayElement) return '比和';
|
|
4307
|
+
if (ELEMENT_SHENG[dayElement] === element) return '日生';
|
|
4308
|
+
if (ELEMENT_KE[dayElement] === element) return '日克';
|
|
4309
|
+
if (ELEMENT_SHENG[element] === dayElement) return '泄';
|
|
4310
|
+
if (ELEMENT_KE[element] === dayElement) return '耗';
|
|
4311
|
+
return 'unknown';
|
|
4312
|
+
}
|
|
4313
|
+
|
|
4314
|
+
function yongshenStrength(result, useGod, opts = {}) {
|
|
4315
|
+
if (!useGod || !Array.isArray(useGod.found) || !useGod.found.length) return null;
|
|
4316
|
+
const monthBranch = opts.monthBranch || null;
|
|
4317
|
+
const dayBranch = opts.dayBranch || (result && result.dayGanZhi ? result.dayGanZhi.branch : null);
|
|
4318
|
+
if (!monthBranch && !dayBranch) return null;
|
|
4319
|
+
const monthElement = monthBranch ? zhiElementOf(monthBranch) : null;
|
|
4320
|
+
const dayElement = dayBranch ? zhiElementOf(dayBranch) : null;
|
|
4321
|
+
const kong = Array.isArray(result && result.xunKong)
|
|
4322
|
+
? result.xunKong
|
|
4323
|
+
: (result && typeof result.xunKong === 'string' ? result.xunKong.split('') : []);
|
|
4324
|
+
|
|
4325
|
+
const lines = useGod.found.map((l) => {
|
|
4326
|
+
const element = l.element || zhiElementOf(l.branch);
|
|
4327
|
+
const monthChong = !!(monthBranch && CHONG_OF[l.branch] === monthBranch);
|
|
4328
|
+
const dayChong = !!(dayBranch && CHONG_OF[l.branch] === dayBranch);
|
|
4329
|
+
const monthState = monthStateOf(element, monthElement);
|
|
4330
|
+
const dayRelation = dayRelationOf(element, dayElement);
|
|
4331
|
+
const isEmpty = kong.includes(l.branch);
|
|
4332
|
+
return {
|
|
4333
|
+
position: l.position,
|
|
4334
|
+
branch: l.branch,
|
|
4335
|
+
element,
|
|
4336
|
+
monthState,
|
|
4337
|
+
monthSay: MONTH_STATE_SAY[monthState] || '',
|
|
4338
|
+
monthChong,
|
|
4339
|
+
dayRelation,
|
|
4340
|
+
daySay: DAY_RELATION_SAY[dayRelation] || '',
|
|
4341
|
+
dayChong,
|
|
4342
|
+
kong: isEmpty,
|
|
4343
|
+
moving: !!l.moving,
|
|
4344
|
+
chongTag: monthChong ? '月破'
|
|
4345
|
+
: dayChong ? (isEmpty ? '冲空' : (l.moving ? '逢日辰冲' : '暗动')) : '',
|
|
4346
|
+
};
|
|
4347
|
+
});
|
|
4348
|
+
|
|
4349
|
+
const labels = [];
|
|
4350
|
+
const states = [...new Set(lines.map((l) => l.monthState))].filter((x) => x !== 'unknown');
|
|
4351
|
+
states.sort((a, b) => MONTH_STATE_ORDER.indexOf(a) - MONTH_STATE_ORDER.indexOf(b));
|
|
4352
|
+
for (const st of states) labels.push(`用神月建${st}`);
|
|
4353
|
+
if (lines.some((l) => l.monthChong)) labels.push('用神月破');
|
|
4354
|
+
const rels = [...new Set(lines.map((l) => l.dayRelation))].filter((x) => x !== 'unknown');
|
|
4355
|
+
rels.sort((a, b) => DAY_RELATION_ORDER.indexOf(a) - DAY_RELATION_ORDER.indexOf(b));
|
|
4356
|
+
for (const rel of rels) {
|
|
4357
|
+
labels.push(rel === '日生' ? '用神得日辰生'
|
|
4358
|
+
: rel === '日克' ? '用神受日辰克'
|
|
4359
|
+
: rel === '比和' ? '用神与日辰比和'
|
|
4360
|
+
: rel === '泄' ? '用神泄于日辰' : '用神耗日辰');
|
|
4361
|
+
}
|
|
4362
|
+
for (const tag of [...new Set(lines.map((l) => l.chongTag))].filter(Boolean)) {
|
|
4363
|
+
labels.push(tag === '月破' ? '' : `用神${tag}`);
|
|
4364
|
+
}
|
|
4365
|
+
const clean = labels.filter(Boolean).filter((x, i, arr) => arr.indexOf(x) === i);
|
|
4366
|
+
|
|
4367
|
+
return {
|
|
4368
|
+
month: monthBranch ? { branch: monthBranch, element: monthElement } : null,
|
|
4369
|
+
day: dayBranch ? { branch: dayBranch, element: dayElement } : null,
|
|
4370
|
+
lines,
|
|
4371
|
+
labels: clean,
|
|
4372
|
+
note: '月建主这一段的旺衰,日辰看当天是扶是克;两处都只给状态标签,不折成分数,也不单独断吉凶。',
|
|
3534
4373
|
};
|
|
3535
4374
|
}
|
|
3536
4375
|
|
|
3537
|
-
|
|
4376
|
+
function hexagramStrength(result, opts = {}) {
|
|
4377
|
+
const rows = (result && result.ben && Array.isArray(result.ben.lines))
|
|
4378
|
+
? result.ben.lines
|
|
4379
|
+
: (result && Array.isArray(result.lines) ? result.lines : []);
|
|
4380
|
+
if (!rows.length) return null;
|
|
4381
|
+
const monthBranch = opts.monthBranch || null;
|
|
4382
|
+
const dayBranch = opts.dayBranch || (result.dayGanZhi ? result.dayGanZhi.branch : null);
|
|
4383
|
+
if (!monthBranch && !dayBranch) return null;
|
|
4384
|
+
const monthElement = monthBranch ? zhiElementOf(monthBranch) : null;
|
|
4385
|
+
const dayElement = dayBranch ? zhiElementOf(dayBranch) : null;
|
|
4386
|
+
const kong = Array.isArray(result.xunKong)
|
|
4387
|
+
? result.xunKong
|
|
4388
|
+
: (typeof result.xunKong === 'string' ? result.xunKong.split('') : []);
|
|
4389
|
+
const shiPos = result.ben ? result.ben.shi : null;
|
|
4390
|
+
const yingPos = result.ben ? result.ben.ying : null;
|
|
4391
|
+
|
|
4392
|
+
const lines = rows.map((l) => {
|
|
4393
|
+
const element = l.element || zhiElementOf(l.branch);
|
|
4394
|
+
const monthChong = !!(monthBranch && CHONG_OF[l.branch] === monthBranch);
|
|
4395
|
+
const dayChong = !!(dayBranch && CHONG_OF[l.branch] === dayBranch);
|
|
4396
|
+
const monthState = monthStateOf(element, monthElement);
|
|
4397
|
+
const dayRelation = dayRelationOf(element, dayElement);
|
|
4398
|
+
const isEmpty = kong.includes(l.branch);
|
|
4399
|
+
return {
|
|
4400
|
+
position: l.position,
|
|
4401
|
+
name: l.name,
|
|
4402
|
+
branch: l.branch,
|
|
4403
|
+
element,
|
|
4404
|
+
liuqin: l.liuqin ?? null,
|
|
4405
|
+
shi: l.position === shiPos,
|
|
4406
|
+
ying: l.position === yingPos,
|
|
4407
|
+
moving: !!l.moving,
|
|
4408
|
+
kong: isEmpty,
|
|
4409
|
+
monthState,
|
|
4410
|
+
monthSay: MONTH_STATE_SAY[monthState] || '',
|
|
4411
|
+
monthChong,
|
|
4412
|
+
dayRelation,
|
|
4413
|
+
daySay: DAY_RELATION_SAY[dayRelation] || '',
|
|
4414
|
+
dayChong,
|
|
4415
|
+
chongTag: monthChong ? '月破'
|
|
4416
|
+
: dayChong ? (isEmpty ? '冲空' : (l.moving ? '逢日辰冲' : '暗动')) : '',
|
|
4417
|
+
};
|
|
4418
|
+
});
|
|
4419
|
+
|
|
4420
|
+
const counts = {};
|
|
4421
|
+
for (const st of MONTH_STATE_ORDER) counts[st] = lines.filter((l) => l.monthState === st).length;
|
|
4422
|
+
|
|
4423
|
+
const labels = [];
|
|
4424
|
+
for (const st of MONTH_STATE_ORDER) if (counts[st]) labels.push(`全卦${st}${counts[st]}爻`);
|
|
4425
|
+
const shiLine = lines.find((l) => l.shi) || null;
|
|
4426
|
+
const yingLine = lines.find((l) => l.ying) || null;
|
|
4427
|
+
if (shiLine && shiLine.monthState !== 'unknown') labels.push(`世爻月建${shiLine.monthState}`);
|
|
4428
|
+
if (yingLine && yingLine.monthState !== 'unknown') labels.push(`应爻月建${yingLine.monthState}`);
|
|
4429
|
+
const tagCount = (tag) => lines.filter((l) => l.chongTag === tag).length;
|
|
4430
|
+
for (const tag of ['月破', '暗动', '冲空', '逢日辰冲']) {
|
|
4431
|
+
const n = tagCount(tag);
|
|
4432
|
+
if (n) labels.push(`${tag}${n}爻`);
|
|
4433
|
+
}
|
|
4434
|
+
|
|
4435
|
+
return {
|
|
4436
|
+
month: monthBranch ? { branch: monthBranch, element: monthElement } : null,
|
|
4437
|
+
day: dayBranch ? { branch: dayBranch, element: dayElement } : null,
|
|
4438
|
+
lines,
|
|
4439
|
+
counts,
|
|
4440
|
+
strongest: lines.filter((l) => l.monthState === '旺').map((l) => l.position),
|
|
4441
|
+
weakest: lines.filter((l) => l.monthState === '死' || l.monthChong).map((l) => l.position),
|
|
4442
|
+
shi: shiLine ? { position: shiLine.position, branch: shiLine.branch, monthState: shiLine.monthState, dayRelation: shiLine.dayRelation } : null,
|
|
4443
|
+
ying: yingLine ? { position: yingLine.position, branch: yingLine.branch, monthState: yingLine.monthState, dayRelation: yingLine.dayRelation } : null,
|
|
4444
|
+
labels,
|
|
4445
|
+
note: '月建主这一段的旺衰、日辰管当天的扶克,六爻逐一给状态;判定与用神旺衰同一套,只多了世应与动爻标记。只报状态、不折分数,也不单独断吉凶。',
|
|
4446
|
+
};
|
|
4447
|
+
}
|
|
4448
|
+
|
|
4449
|
+
const JIN_VERDICT = { 旺: '后劲足', 相: '后劲足', 休: '后劲有限', 囚: '后劲有限', 死: '进得虚' };
|
|
4450
|
+
const TUI_VERDICT = { 旺: '退得缓', 相: '退得缓', 休: '退得实', 囚: '退得实', 死: '退得实' };
|
|
4451
|
+
|
|
4452
|
+
function jinTuiPower(result, opts = {}) {
|
|
4453
|
+
const items = result && result.body && Array.isArray(result.body.jinTui) ? result.body.jinTui : [];
|
|
4454
|
+
if (!items.length) return null;
|
|
4455
|
+
const rows = result && result.ben && Array.isArray(result.ben.lines) ? result.ben.lines : [];
|
|
4456
|
+
const monthBranch = opts.monthBranch || null;
|
|
4457
|
+
const dayBranch = opts.dayBranch || (result && result.dayGanZhi ? result.dayGanZhi.branch : null);
|
|
4458
|
+
const monthElement = monthBranch ? zhiElementOf(monthBranch) : null;
|
|
4459
|
+
const dayElement = dayBranch ? zhiElementOf(dayBranch) : null;
|
|
4460
|
+
const kong = Array.isArray(result && result.xunKong)
|
|
4461
|
+
? result.xunKong
|
|
4462
|
+
: (result && typeof result.xunKong === 'string' ? result.xunKong.split('') : []);
|
|
4463
|
+
|
|
4464
|
+
const lines = items.map((x) => {
|
|
4465
|
+
const line = rows[x.position - 1] || null;
|
|
4466
|
+
const element = (line && line.element) || zhiElementOf(x.from);
|
|
4467
|
+
const monthState = monthStateOf(element, monthElement);
|
|
4468
|
+
const monthChong = !!(monthBranch && CHONG_OF[x.from] === monthBranch);
|
|
4469
|
+
const dayChong = !!(dayBranch && CHONG_OF[x.from] === dayBranch);
|
|
4470
|
+
const dayRelation = dayRelationOf(element, dayElement);
|
|
4471
|
+
const isEmpty = kong.includes(x.from);
|
|
4472
|
+
const verdict = !monthBranch ? '只报趋势'
|
|
4473
|
+
: monthChong ? '月破失据'
|
|
4474
|
+
: ((x.type === '进' ? JIN_VERDICT : TUI_VERDICT)[monthState] || '未定');
|
|
4475
|
+
const monthSay = monthBranch
|
|
4476
|
+
? `月建${monthBranch}(${monthElement})对${element}为${monthState}`
|
|
4477
|
+
: '缺月建,只看日辰';
|
|
4478
|
+
const daySay = dayRelation === 'unknown' ? '' : `日辰${dayBranch}(${dayElement})${dayRelation}`;
|
|
4479
|
+
const extra = [monthChong ? '又遭月破' : '', isEmpty ? '旬空待填' : '', dayChong ? '逢日辰冲' : ''].filter(Boolean);
|
|
4480
|
+
return {
|
|
4481
|
+
position: x.position,
|
|
4482
|
+
from: x.from,
|
|
4483
|
+
to: x.to,
|
|
4484
|
+
type: x.type,
|
|
4485
|
+
element,
|
|
4486
|
+
monthState,
|
|
4487
|
+
monthChong,
|
|
4488
|
+
dayRelation,
|
|
4489
|
+
dayChong,
|
|
4490
|
+
kong: isEmpty,
|
|
4491
|
+
verdict,
|
|
4492
|
+
say: `${x.from}→${x.to}(${x.type}):${monthSay}${daySay ? `,${daySay}` : ''}${extra.length ? `,${extra.join('、')}` : ''} → ${verdict}`,
|
|
4493
|
+
};
|
|
4494
|
+
});
|
|
4495
|
+
|
|
4496
|
+
return {
|
|
4497
|
+
month: monthBranch ? { branch: monthBranch, element: monthElement } : null,
|
|
4498
|
+
day: dayBranch ? { branch: dayBranch, element: dayElement } : null,
|
|
4499
|
+
lines,
|
|
4500
|
+
labels: lines.map((l) => `${l.position}爻化${l.type}·${l.verdict}`),
|
|
4501
|
+
note: '进退只说这一爻往哪边走;力重是把它放回月建日辰,看有没有托着——得令则进得动、退得慢,失令则进得虚、退得实,月破压过一切。仍不直接定吉凶:用神化进为喜,忌神化进反而是忌。',
|
|
4502
|
+
};
|
|
4503
|
+
}
|
|
4504
|
+
|
|
4505
|
+
return { jinTuiOf, hexBody, bodyRelations, bodyLabels, HEXAGRAM_COUNT, hexagramFromBits, YONGSHEN_RULES, yongshenOf, tossLines, buildLiuyao, zhiElementOf, monthStateOf, dayRelationOf, yongshenStrength, hexagramStrength, jinTuiPower };
|
|
3538
4506
|
})();
|
|
3539
4507
|
|
|
3540
4508
|
__mods.ziwei = (function () {
|
|
@@ -4011,19 +4979,24 @@ function buildZiwei(input) {
|
|
|
4011
4979
|
shensha: '长生、博士随大限顺逆;将前、岁前恒顺行;天伤恒在交友、天使恒在疾厄',
|
|
4012
4980
|
masters: '命主按命宫地支,身主按生年地支',
|
|
4013
4981
|
liunian: '流年命宫取该年地支宫;三方四正为本宫与 +4/+8/+6;并给该年所属大限与小限',
|
|
4982
|
+
flyComposite: '三方四正取本宫、对宫与两个三合宫共四宫,四宫宫干各化禄权科忌共 16 条,按落宫归堆标会聚(双忌会、禄忌同宫、三化会、自化);只描会照,不折吉凶',
|
|
4014
4983
|
changqu: '昌曲落宫只由时支决定,故与丑未的关系(夹/三合/同宫/无关)是结构性结论;absorb 的「清/杂」是启发式标记,依据昌曲化忌与会煞,不是断语',
|
|
4015
4984
|
},
|
|
4016
4985
|
};
|
|
4017
4986
|
|
|
4018
4987
|
chart.patterns = detectPatterns(chart);
|
|
4019
4988
|
chart.daxianList = daxianList(chart);
|
|
4989
|
+
chart.fly = flyStars(chart);
|
|
4990
|
+
chart.flyChains = flyChains(chart, { from: '命宫' });
|
|
4991
|
+
chart.flyComposite = flyComposite(chart, { from: '命宫' });
|
|
4020
4992
|
enrichLiunian(chart);
|
|
4021
4993
|
chart.flow = flowOf(chart, input.asOf);
|
|
4022
4994
|
chart.patternSummary = {
|
|
4023
4995
|
count: chart.patterns.length,
|
|
4024
4996
|
good: chart.patterns.filter((p) => p.tone === 'good').map((p) => p.name),
|
|
4997
|
+
neutral: chart.patterns.filter((p) => p.tone === 'neutral').map((p) => p.name),
|
|
4025
4998
|
bad: chart.patterns.filter((p) => p.tone === 'bad').map((p) => p.name),
|
|
4026
|
-
note: '
|
|
4999
|
+
note: '格局只描述结构,不作吉凶断语;同一命盘可并存吉格、中性结构与忌格',
|
|
4027
5000
|
};
|
|
4028
5001
|
return chart;
|
|
4029
5002
|
}
|
|
@@ -4063,7 +5036,7 @@ function detectPatterns(chart) {
|
|
|
4063
5036
|
|
|
4064
5037
|
const lu = starBranchOf(chart, '禄存');
|
|
4065
5038
|
const ma = starBranchOf(chart, '天马');
|
|
4066
|
-
if (lu >= 0 && ma >= 0 && (lu === ma || fix(lu - ma) === 6)) add('禄马交驰', `禄存在${
|
|
5039
|
+
if (lu >= 0 && ma >= 0 && (lu === ma || fix(lu - ma) === 6)) add('禄马交驰', `禄存在${BRANCHES[lu]},天马在${BRANCHES[ma]}`);
|
|
4067
5040
|
|
|
4068
5041
|
const huo = starBranchOf(chart, '火星');
|
|
4069
5042
|
const ling = starBranchOf(chart, '铃星');
|
|
@@ -4071,11 +5044,8 @@ function detectPatterns(chart) {
|
|
|
4071
5044
|
if (fix(soulIdx - 1) === ling && fix(soulIdx + 1) === huo) add('火铃夹命', '铃星与火星夹命');
|
|
4072
5045
|
|
|
4073
5046
|
const ji = chart.palaces.find((p) => p.stars.some((s) => s.mutagen === '忌'));
|
|
4074
|
-
if (ji) {
|
|
4075
|
-
|
|
4076
|
-
if (fix(jb - 1) === starBranchOf(chart, '擎羊') && fix(jb + 1) === starBranchOf(chart, '陀罗')) {
|
|
4077
|
-
add('羊陀夹忌', `化忌在${ji.branch},擎羊陀罗夹之`);
|
|
4078
|
-
}
|
|
5047
|
+
if (ji && lu >= 0 && BRANCHES.indexOf(ji.branch) === lu) {
|
|
5048
|
+
add('羊陀夹忌', `化忌与禄存在${ji.branch}同宫,擎羊陀罗夹之`);
|
|
4079
5049
|
}
|
|
4080
5050
|
|
|
4081
5051
|
const lctw = ['铃星', '文昌', '陀罗', '武曲'].map((n) => starBranchOf(chart, n));
|
|
@@ -4094,7 +5064,9 @@ function detectPatterns(chart) {
|
|
|
4094
5064
|
const jia = (a, b) => {
|
|
4095
5065
|
const ba = starBranchOf(chart, a);
|
|
4096
5066
|
const bb = starBranchOf(chart, b);
|
|
4097
|
-
|
|
5067
|
+
if (ba < 0 || bb < 0) return false;
|
|
5068
|
+
return (fix(ba + 1) === soulIdx && fix(bb - 1) === soulIdx)
|
|
5069
|
+
|| (fix(bb + 1) === soulIdx && fix(ba - 1) === soulIdx);
|
|
4098
5070
|
};
|
|
4099
5071
|
const mutagensIn = (indices) => {
|
|
4100
5072
|
const set = new Set();
|
|
@@ -4125,7 +5097,7 @@ function detectPatterns(chart) {
|
|
|
4125
5097
|
if (jia('左辅', '右弼')) add('左右夹命', '左辅、右弼夹命宫');
|
|
4126
5098
|
if (jia('文昌', '文曲')) add('昌曲夹命', '文昌、文曲夹命宫');
|
|
4127
5099
|
if (jia('天魁', '天钺')) add('魁钺夹命', '天魁、天钺夹命宫');
|
|
4128
|
-
if (jia('擎羊', '陀罗')) add('羊陀夹命',
|
|
5100
|
+
if (jia('擎羊', '陀罗')) add('羊陀夹命', `禄存在${BRANCHES[soulIdx]}守命,擎羊陀罗前后夹之`);
|
|
4129
5101
|
|
|
4130
5102
|
const muts = mutagensIn(sanfang);
|
|
4131
5103
|
if (muts.has('禄') && muts.has('权') && muts.has('科')) add('三奇嘉会', '化禄、化权、化科会于命宫三方四正');
|
|
@@ -4138,9 +5110,10 @@ function detectPatterns(chart) {
|
|
|
4138
5110
|
const lianzhen = starBranchOf(chart, '廉贞');
|
|
4139
5111
|
const tianxiang = starBranchOf(chart, '天相');
|
|
4140
5112
|
const qingyang = starBranchOf(chart, '擎羊');
|
|
4141
|
-
if (lianzhen >= 0 &&
|
|
4142
|
-
&&
|
|
4143
|
-
|
|
5113
|
+
if (lianzhen >= 0 && tianxiang >= 0 && qingyang >= 0
|
|
5114
|
+
&& lianzhen === tianxiang && qingyang === tianxiang && tianxiang === soulIdx
|
|
5115
|
+
&& (tianxiang === 0 || tianxiang === 6)) {
|
|
5116
|
+
add('刑囚夹印', `廉贞天相同守命宫${BRANCHES[tianxiang]},擎羊同宫`);
|
|
4144
5117
|
}
|
|
4145
5118
|
if (near.has('贪狼') && (near.has('火星') || near.has('铃星'))) {
|
|
4146
5119
|
add('火贪铃贪', `贪狼与${near.has('火星') ? '火星' : '铃星'}会于命宫三方四正`);
|
|
@@ -4196,6 +5169,162 @@ function daxianList(chart) {
|
|
|
4196
5169
|
.sort((a, b) => a.ages[0] - b.ages[0]);
|
|
4197
5170
|
}
|
|
4198
5171
|
|
|
5172
|
+
const FLY_TYPES = ['禄', '权', '科', '忌'];
|
|
5173
|
+
|
|
5174
|
+
function flyStarOf(stem, type) {
|
|
5175
|
+
const map = MUTAGEN[stem];
|
|
5176
|
+
if (!map) return null;
|
|
5177
|
+
for (const [star, t] of Object.entries(map)) if (t === type) return star;
|
|
5178
|
+
return null;
|
|
5179
|
+
}
|
|
5180
|
+
|
|
5181
|
+
function flyStars(chart) {
|
|
5182
|
+
const palaces = chart.palaces || [];
|
|
5183
|
+
return palaces.map((p) => ({
|
|
5184
|
+
palace: p.palace,
|
|
5185
|
+
branch: p.branch,
|
|
5186
|
+
stem: p.stem,
|
|
5187
|
+
flies: FLY_TYPES.map((type) => {
|
|
5188
|
+
const star = flyStarOf(p.stem, type);
|
|
5189
|
+
const b = star ? starBranchOf(chart, star) : -1;
|
|
5190
|
+
const target = b >= 0 ? palaces.find((x) => x.branch === BRANCHES[b]) : null;
|
|
5191
|
+
return {
|
|
5192
|
+
type,
|
|
5193
|
+
star,
|
|
5194
|
+
to: target ? target.palace : null,
|
|
5195
|
+
toBranch: target ? target.branch : null,
|
|
5196
|
+
self: !!(target && target.palace === p.palace),
|
|
5197
|
+
};
|
|
5198
|
+
}),
|
|
5199
|
+
}));
|
|
5200
|
+
}
|
|
5201
|
+
|
|
5202
|
+
function flyChain(chart, { from = '命宫', type = '忌', maxSteps = 12 } = {}) {
|
|
5203
|
+
const palaces = chart.palaces || [];
|
|
5204
|
+
const start = palaces.find((p) => p.palace === from) || palaces[0];
|
|
5205
|
+
if (!start) return null;
|
|
5206
|
+
const steps = [];
|
|
5207
|
+
const seen = new Set([start.palace]);
|
|
5208
|
+
let cur = start;
|
|
5209
|
+
let ended = 'max';
|
|
5210
|
+
for (let i = 0; i < Math.max(1, maxSteps); i++) {
|
|
5211
|
+
const star = flyStarOf(cur.stem, type);
|
|
5212
|
+
if (!star) { ended = 'no-star'; break; }
|
|
5213
|
+
const b = starBranchOf(chart, star);
|
|
5214
|
+
if (b < 0) { ended = 'off-chart'; break; }
|
|
5215
|
+
const to = palaces.find((x) => x.branch === BRANCHES[b]);
|
|
5216
|
+
steps.push({ from: cur.palace, fromBranch: cur.branch, fromStem: cur.stem, star, type, to: to.palace, toBranch: to.branch });
|
|
5217
|
+
if (seen.has(to.palace)) { ended = 'cycle'; break; }
|
|
5218
|
+
seen.add(to.palace);
|
|
5219
|
+
cur = to;
|
|
5220
|
+
}
|
|
5221
|
+
return {
|
|
5222
|
+
from: start.palace,
|
|
5223
|
+
type,
|
|
5224
|
+
steps,
|
|
5225
|
+
path: [start.palace, ...steps.map((s) => s.to)],
|
|
5226
|
+
ended,
|
|
5227
|
+
closed: ended === 'cycle',
|
|
5228
|
+
};
|
|
5229
|
+
}
|
|
5230
|
+
|
|
5231
|
+
function flyChains(chart, { from = '命宫', maxSteps = 12 } = {}) {
|
|
5232
|
+
const out = {};
|
|
5233
|
+
for (const type of FLY_TYPES) out[type] = flyChain(chart, { from, type, maxSteps });
|
|
5234
|
+
return out;
|
|
5235
|
+
}
|
|
5236
|
+
|
|
5237
|
+
const PALACE_SUFFIX = (p) => `${p}${String(p).endsWith('宫') ? '' : '宫'}`;
|
|
5238
|
+
|
|
5239
|
+
function flyComposite(chart, { from = '命宫' } = {}) {
|
|
5240
|
+
const palaces = chart.palaces || [];
|
|
5241
|
+
const src = palaces.find((p) => p.palace === from) || palaces[0];
|
|
5242
|
+
if (!src) return null;
|
|
5243
|
+
const names = Array.isArray(src.sanfang) && src.sanfang.length
|
|
5244
|
+
? [...new Set(src.sanfang)].slice(0, 4)
|
|
5245
|
+
: [src.palace];
|
|
5246
|
+
|
|
5247
|
+
const sources = [];
|
|
5248
|
+
for (const name of names) {
|
|
5249
|
+
const p = palaces.find((x) => x.palace === name);
|
|
5250
|
+
if (!p) continue;
|
|
5251
|
+
sources.push({
|
|
5252
|
+
palace: p.palace,
|
|
5253
|
+
branch: p.branch,
|
|
5254
|
+
stem: p.stem,
|
|
5255
|
+
flies: FLY_TYPES.map((type) => {
|
|
5256
|
+
const star = flyStarOf(p.stem, type);
|
|
5257
|
+
const b = star ? starBranchOf(chart, star) : -1;
|
|
5258
|
+
const target = b >= 0 ? palaces.find((x) => x.branch === BRANCHES[b]) : null;
|
|
5259
|
+
return {
|
|
5260
|
+
type,
|
|
5261
|
+
star,
|
|
5262
|
+
to: target ? target.palace : null,
|
|
5263
|
+
toBranch: target ? target.branch : null,
|
|
5264
|
+
self: !!(target && target.palace === p.palace),
|
|
5265
|
+
};
|
|
5266
|
+
}),
|
|
5267
|
+
});
|
|
5268
|
+
}
|
|
5269
|
+
|
|
5270
|
+
const targets = [];
|
|
5271
|
+
for (const p of palaces) {
|
|
5272
|
+
const incoming = [];
|
|
5273
|
+
for (const s of sources) {
|
|
5274
|
+
for (const f of s.flies) {
|
|
5275
|
+
if (f.to === p.palace) {
|
|
5276
|
+
incoming.push({ from: s.palace, fromBranch: s.branch, fromStem: s.stem, type: f.type, star: f.star, self: f.self });
|
|
5277
|
+
}
|
|
5278
|
+
}
|
|
5279
|
+
}
|
|
5280
|
+
if (!incoming.length) continue;
|
|
5281
|
+
targets.push({
|
|
5282
|
+
palace: p.palace,
|
|
5283
|
+
branch: p.branch,
|
|
5284
|
+
incoming,
|
|
5285
|
+
types: [...new Set(incoming.map((x) => x.type))],
|
|
5286
|
+
count: incoming.length,
|
|
5287
|
+
});
|
|
5288
|
+
}
|
|
5289
|
+
targets.sort((a, b) => b.count - a.count || BRANCHES.indexOf(a.branch) - BRANCHES.indexOf(b.branch));
|
|
5290
|
+
|
|
5291
|
+
const jiAt = (t) => t.incoming.filter((x) => x.type === '忌').length;
|
|
5292
|
+
const groups = {
|
|
5293
|
+
doubleJi: targets.filter((t) => jiAt(t) >= 2),
|
|
5294
|
+
luJi: targets.filter((t) => t.types.includes('禄') && t.types.includes('忌')),
|
|
5295
|
+
tripleHua: targets.filter((t) => t.types.length >= 3),
|
|
5296
|
+
selfHua: targets.filter((t) => t.incoming.some((x) => x.self)),
|
|
5297
|
+
};
|
|
5298
|
+
|
|
5299
|
+
const labels = [];
|
|
5300
|
+
for (const t of groups.doubleJi) labels.push(`${['', '', '双忌', '三忌', '四忌'][jiAt(t)] || `${jiAt(t)}忌`}会${PALACE_SUFFIX(t.palace)}`);
|
|
5301
|
+
for (const t of groups.luJi) labels.push(`禄忌同宫${PALACE_SUFFIX(t.palace)}`);
|
|
5302
|
+
const HUA_NUM = { 3: '三化会', 4: '四化会' };
|
|
5303
|
+
for (const t of groups.tripleHua) labels.push(`${HUA_NUM[t.types.length] || `${t.types.length}化会`}${PALACE_SUFFIX(t.palace)}`);
|
|
5304
|
+
for (const t of groups.selfHua) labels.push(`${PALACE_SUFFIX(t.palace)}自化`);
|
|
5305
|
+
|
|
5306
|
+
const byType = {};
|
|
5307
|
+
for (const type of FLY_TYPES) {
|
|
5308
|
+
byType[type] = sources
|
|
5309
|
+
.map((s) => {
|
|
5310
|
+
const f = s.flies.find((x) => x.type === type);
|
|
5311
|
+
return f && f.to ? { from: s.palace, star: f.star, to: f.to, self: f.self } : null;
|
|
5312
|
+
})
|
|
5313
|
+
.filter(Boolean);
|
|
5314
|
+
}
|
|
5315
|
+
|
|
5316
|
+
return {
|
|
5317
|
+
from: src.palace,
|
|
5318
|
+
sanfang: sources.map((s) => s.palace),
|
|
5319
|
+
sources,
|
|
5320
|
+
targets,
|
|
5321
|
+
groups,
|
|
5322
|
+
byType,
|
|
5323
|
+
labels,
|
|
5324
|
+
note: '三方四正取本宫、对宫与两个三合宫共四宫,四宫宫干各化禄权科忌共 16 条飞化,按落宫归堆;只在落宫相同(会照)时标会聚,单条飞出不另立标签。只描会照与方向,不折吉凶,也未叠大限流年四化。',
|
|
5325
|
+
};
|
|
5326
|
+
}
|
|
5327
|
+
|
|
4199
5328
|
function enrichLiunian(chart) {
|
|
4200
5329
|
for (const ln of chart.liunian) {
|
|
4201
5330
|
const stem = ln.ganzhi[0];
|
|
@@ -4298,7 +5427,7 @@ function flowOf(chart, asOf) {
|
|
|
4298
5427
|
};
|
|
4299
5428
|
}
|
|
4300
5429
|
|
|
4301
|
-
return { PALACE_NAMES, BRIGHTNESS, MUTAGEN, LUCUN, KUI_YUE, MING_ZHU, SHEN_ZHU, triadOf, HUO_START, LING_START, TIANMA, XIANCHI, HUAGAI, JIANGXING, GUCHEN, GUASU, posuIndex, XIAOXIAN_START, CHANGSHENG_NAMES, BOSHI_NAMES, JIANGQIAN_NAMES, SUIQI_NAMES, CHANGSHENG_START, hourBranchIndex, ziweiTianfuIndex, xiaoxianAge, buildZiwei, detectPatterns, daxianList, enrichLiunian, asOfParts, flowOf };
|
|
5430
|
+
return { PALACE_NAMES, BRIGHTNESS, MUTAGEN, LUCUN, KUI_YUE, MING_ZHU, SHEN_ZHU, triadOf, HUO_START, LING_START, TIANMA, XIANCHI, HUAGAI, JIANGXING, GUCHEN, GUASU, posuIndex, XIAOXIAN_START, CHANGSHENG_NAMES, BOSHI_NAMES, JIANGQIAN_NAMES, SUIQI_NAMES, CHANGSHENG_START, hourBranchIndex, ziweiTianfuIndex, xiaoxianAge, buildZiwei, detectPatterns, PATTERN_TONE, daxianList, FLY_TYPES, flyStarOf, flyStars, flyChain, flyChains, flyComposite, enrichLiunian, asOfParts, flowOf };
|
|
4302
5431
|
})();
|
|
4303
5432
|
|
|
4304
5433
|
__mods.tarot = (function () {
|
|
@@ -6494,6 +7623,90 @@ function gatePalaceRelation(gate, palace) {
|
|
|
6494
7623
|
if (SHENG[pe] === ge) return { type: '宫生门', gate: ge, palace: pe, note: `${pe}生${ge}` };
|
|
6495
7624
|
return { type: '比和', gate: ge, palace: pe, note: `${ge}与${pe}比和` };
|
|
6496
7625
|
}
|
|
7626
|
+
|
|
7627
|
+
const STEM_ELEMENT = {
|
|
7628
|
+
甲: '木', 乙: '木', 丙: '火', 丁: '火', 戊: '土',
|
|
7629
|
+
己: '土', 庚: '金', 辛: '金', 壬: '水', 癸: '水',
|
|
7630
|
+
};
|
|
7631
|
+
|
|
7632
|
+
function stemPalaceRelation(stem, palace) {
|
|
7633
|
+
const se = STEM_ELEMENT[stem];
|
|
7634
|
+
const pe = PALACE_ELEMENT[palace];
|
|
7635
|
+
if (!se || !pe) return { type: 'unknown', stem: se || null, palace: pe || null, note: '缺少干或宫的五行,无法判断' };
|
|
7636
|
+
if (KE[se] === pe) return { type: '干克宫', stem: se, palace: pe, note: `${se}克${pe},天盘干克宫` };
|
|
7637
|
+
if (KE[pe] === se) return { type: '宫克干', stem: se, palace: pe, note: `${pe}克${se},宫克天盘干` };
|
|
7638
|
+
if (SHENG[se] === pe) return { type: '干生宫', stem: se, palace: pe, note: `${se}生${pe},干泄气于宫` };
|
|
7639
|
+
if (SHENG[pe] === se) return { type: '宫生干', stem: se, palace: pe, note: `${pe}生${se},宫来生干` };
|
|
7640
|
+
return { type: '比和', stem: se, palace: pe, note: `${se}与${pe}比和` };
|
|
7641
|
+
}
|
|
7642
|
+
|
|
7643
|
+
const JI_XING = {
|
|
7644
|
+
戊: { palace: '3', zhi: '卯', basis: '甲子戊,子刑卯' },
|
|
7645
|
+
己: { palace: '2', zhi: '未', basis: '甲戌己,戌刑未' },
|
|
7646
|
+
庚: { palace: '8', zhi: '寅', basis: '甲申庚,申刑寅' },
|
|
7647
|
+
辛: { palace: '9', zhi: '午', basis: '甲午辛,午自刑' },
|
|
7648
|
+
壬: { palace: '4', zhi: '辰', basis: '甲辰壬,辰自刑' },
|
|
7649
|
+
癸: { palace: '4', zhi: '巳', basis: '甲寅癸,寅刑巳' },
|
|
7650
|
+
};
|
|
7651
|
+
const RU_MU = {
|
|
7652
|
+
乙: { palace: '2', zhi: '未', basis: '乙木墓于未,未在坤二宫' },
|
|
7653
|
+
丙: { palace: '6', zhi: '戌', basis: '丙火墓于戌,戌在乾六宫' },
|
|
7654
|
+
丁: { palace: '6', zhi: '戌', basis: '丁火墓于戌,戌在乾六宫' },
|
|
7655
|
+
};
|
|
7656
|
+
|
|
7657
|
+
function jiXingOf(palaces) {
|
|
7658
|
+
const out = [];
|
|
7659
|
+
for (const p of palaces || []) {
|
|
7660
|
+
const hit = JI_XING[p.tianPan];
|
|
7661
|
+
if (hit && hit.palace === String(p.palace)) out.push({ palace: p.palace, stem: p.tianPan, zhi: hit.zhi, basis: hit.basis });
|
|
7662
|
+
}
|
|
7663
|
+
return out;
|
|
7664
|
+
}
|
|
7665
|
+
|
|
7666
|
+
function ruMuOf(palaces) {
|
|
7667
|
+
const out = [];
|
|
7668
|
+
for (const p of palaces || []) {
|
|
7669
|
+
const hit = RU_MU[p.tianPan];
|
|
7670
|
+
if (hit && hit.palace === String(p.palace)) out.push({ palace: p.palace, stem: p.tianPan, zhi: hit.zhi, basis: hit.basis });
|
|
7671
|
+
}
|
|
7672
|
+
return out;
|
|
7673
|
+
}
|
|
7674
|
+
|
|
7675
|
+
const QIMEN_CONDITION_TABLES = Object.freeze({
|
|
7676
|
+
jiXing: Object.freeze(Object.fromEntries(Object.entries(JI_XING).map(([k, v]) => [k, { ...v }]))),
|
|
7677
|
+
ruMu: Object.freeze(Object.fromEntries(Object.entries(RU_MU).map(([k, v]) => [k, { ...v }]))),
|
|
7678
|
+
});
|
|
7679
|
+
|
|
7680
|
+
const BRANCH_ELEMENT = {
|
|
7681
|
+
子: '水', 丑: '土', 寅: '木', 卯: '木', 辰: '土', 巳: '火',
|
|
7682
|
+
午: '火', 未: '土', 申: '金', 酉: '金', 戌: '土', 亥: '水',
|
|
7683
|
+
};
|
|
7684
|
+
function monthState(element, monthElement) {
|
|
7685
|
+
if (!element || !monthElement) return 'unknown';
|
|
7686
|
+
if (element === monthElement) return '旺';
|
|
7687
|
+
if (SHENG[monthElement] === element) return '相';
|
|
7688
|
+
if (SHENG[element] === monthElement) return '休';
|
|
7689
|
+
if (KE[element] === monthElement) return '囚';
|
|
7690
|
+
if (KE[monthElement] === element) return '死';
|
|
7691
|
+
return 'unknown';
|
|
7692
|
+
}
|
|
7693
|
+
function monthElementOf(branch) {
|
|
7694
|
+
return BRANCH_ELEMENT[branch] || null;
|
|
7695
|
+
}
|
|
7696
|
+
function groupByState(items, monthElement) {
|
|
7697
|
+
const out = { 旺: [], 相: [], 休: [], 囚: [], 死: [] };
|
|
7698
|
+
for (const it of items || []) {
|
|
7699
|
+
const st = monthState(it.element, monthElement);
|
|
7700
|
+
if (out[st]) out[st].push(it.name);
|
|
7701
|
+
}
|
|
7702
|
+
return out;
|
|
7703
|
+
}
|
|
7704
|
+
const QIMEN_STATE_TABLES = Object.freeze({
|
|
7705
|
+
gate: Object.freeze({ ...GATE_ELEMENT }),
|
|
7706
|
+
star: Object.freeze({ ...STAR_ELEMENT }),
|
|
7707
|
+
branch: Object.freeze({ ...BRANCH_ELEMENT }),
|
|
7708
|
+
stem: Object.freeze({ ...STEM_ELEMENT }),
|
|
7709
|
+
});
|
|
6497
7710
|
function getDiPan(type, num) {
|
|
6498
7711
|
const result = {};
|
|
6499
7712
|
let gong = num;
|
|
@@ -6666,6 +7879,9 @@ function buildQimen(input) {
|
|
|
6666
7879
|
const maZhi = maMap[hourGz[1]] || '';
|
|
6667
7880
|
const maGong = ZHI_TO_GONG[maZhi] || '';
|
|
6668
7881
|
|
|
7882
|
+
const monthBranch = (snapshot.monthGanZhi || '')[1] || '';
|
|
7883
|
+
const monthElement = BRANCH_ELEMENT[monthBranch] || null;
|
|
7884
|
+
|
|
6669
7885
|
const centerPalace = {
|
|
6670
7886
|
palace: '5',
|
|
6671
7887
|
diPan: diPan['5'] || '',
|
|
@@ -6677,7 +7893,11 @@ function buildQimen(input) {
|
|
|
6677
7893
|
palaceElement: PALACE_ELEMENT['5'],
|
|
6678
7894
|
gateElement: null,
|
|
6679
7895
|
starElement: STAR_ELEMENT['天禽'],
|
|
7896
|
+
stemElement: STEM_ELEMENT[tianPan['5']] || null,
|
|
6680
7897
|
gateRelation: { type: 'unknown', note: '中宫无门,不参与门宫关系' },
|
|
7898
|
+
stemRelation: stemPalaceRelation(tianPan['5'], '5'),
|
|
7899
|
+
starState: monthState(STAR_ELEMENT['天禽'], monthElement),
|
|
7900
|
+
stemState: monthState(STEM_ELEMENT[tianPan['5']], monthElement),
|
|
6681
7901
|
kong: false,
|
|
6682
7902
|
ma: false,
|
|
6683
7903
|
center: true,
|
|
@@ -6694,7 +7914,12 @@ function buildQimen(input) {
|
|
|
6694
7914
|
palaceElement: PALACE_ELEMENT[gong],
|
|
6695
7915
|
gateElement: GATE_ELEMENT[bm.baMen[gong]] || null,
|
|
6696
7916
|
starElement: STAR_ELEMENT[jx.jiuXing[gong]] || null,
|
|
7917
|
+
stemElement: STEM_ELEMENT[tianPan[gong]] || null,
|
|
6697
7918
|
gateRelation: gatePalaceRelation(bm.baMen[gong], gong),
|
|
7919
|
+
stemRelation: stemPalaceRelation(tianPan[gong], gong),
|
|
7920
|
+
gateState: monthState(GATE_ELEMENT[bm.baMen[gong]], monthElement),
|
|
7921
|
+
starState: monthState(STAR_ELEMENT[jx.jiuXing[gong]], monthElement),
|
|
7922
|
+
stemState: monthState(STEM_ELEMENT[tianPan[gong]], monthElement),
|
|
6698
7923
|
kong: kongGong.includes(gong),
|
|
6699
7924
|
ma: maGong === gong,
|
|
6700
7925
|
}));
|
|
@@ -6722,6 +7947,16 @@ function buildQimen(input) {
|
|
|
6722
7947
|
zhiShi: { gate: bm.zhiShiMen, gong: bm.zhiShiGong },
|
|
6723
7948
|
kongWang: kongZhi,
|
|
6724
7949
|
ma: { zhi: maZhi, gong: maGong },
|
|
7950
|
+
conditions: {
|
|
7951
|
+
jiXing: jiXingOf(palaces),
|
|
7952
|
+
ruMu: ruMuOf(palaces),
|
|
7953
|
+
},
|
|
7954
|
+
month: { branch: monthBranch, element: monthElement },
|
|
7955
|
+
states: {
|
|
7956
|
+
gate: groupByState(palaces.filter((p) => p.gate).map((p) => ({ name: p.gate, element: p.gateElement })), monthElement),
|
|
7957
|
+
star: groupByState(palaces.map((p) => ({ name: p.star, element: p.starElement })), monthElement),
|
|
7958
|
+
stem: groupByState(palaces.filter((p) => p.tianPan).map((p) => ({ name: p.tianPan, element: p.stemElement })), monthElement),
|
|
7959
|
+
},
|
|
6725
7960
|
palaces,
|
|
6726
7961
|
centerPalace,
|
|
6727
7962
|
rules: [
|
|
@@ -6733,7 +7968,7 @@ function buildQimen(input) {
|
|
|
6733
7968
|
};
|
|
6734
7969
|
}
|
|
6735
7970
|
|
|
6736
|
-
return { buildSnapshot, wuxingRelation, gatePalaceRelation, buildQimen };
|
|
7971
|
+
return { buildSnapshot, wuxingRelation, gatePalaceRelation, stemPalaceRelation, jiXingOf, ruMuOf, QIMEN_CONDITION_TABLES, monthState, monthElementOf, groupByState, QIMEN_STATE_TABLES, buildQimen };
|
|
6737
7972
|
})();
|
|
6738
7973
|
|
|
6739
7974
|
__mods['qimen-interpret'] = (function () {
|
|
@@ -6769,6 +8004,18 @@ const YONG_SHEN = {
|
|
|
6769
8004
|
travel: { label: '出行', primary: ['九天'], secondary: ['驿马'], note: '出行以九天为主,兼看驿马' },
|
|
6770
8005
|
};
|
|
6771
8006
|
|
|
8007
|
+
function stemRelationLine(r) {
|
|
8008
|
+
const groups = new Map();
|
|
8009
|
+
for (const p of r.palaces || []) {
|
|
8010
|
+
const rel = p.stemRelation || null;
|
|
8011
|
+
if (!rel || rel.type === 'unknown' || !p.tianPan) continue;
|
|
8012
|
+
if (!groups.has(rel.type)) groups.set(rel.type, []);
|
|
8013
|
+
groups.get(rel.type).push(`${p.palace}宫${p.tianPan}`);
|
|
8014
|
+
}
|
|
8015
|
+
const order = ['干克宫', '宫克干', '干生宫', '宫生干', '比和'];
|
|
8016
|
+
return order.filter((k) => groups.has(k)).map((k) => `${k} ${groups.get(k).join('、')}`).join(';') || '—';
|
|
8017
|
+
}
|
|
8018
|
+
|
|
6772
8019
|
const REL_TEXT = {
|
|
6773
8020
|
生: '主体力量流向环境或趋势',
|
|
6774
8021
|
克: '主体对环境或趋势构成压力、有改造意图',
|
|
@@ -6859,15 +8106,36 @@ function interpretQimen(r, opts = {}) {
|
|
|
6859
8106
|
else if (rel.type === '宫制门') controlled.push(`${p.palace}宫(宫${rel.palace}克${p.gate}${rel.gate})`);
|
|
6860
8107
|
}
|
|
6861
8108
|
const kongCells = r.palaces.filter((p) => p.kong).map((p) => `${p.palace}宫`);
|
|
8109
|
+
const jiXing = (r.conditions && r.conditions.jiXing) || [];
|
|
8110
|
+
const ruMu = (r.conditions && r.conditions.ruMu) || [];
|
|
6862
8111
|
sections.push({
|
|
6863
8112
|
key: 'conditions',
|
|
6864
8113
|
label: '宫位条件',
|
|
6865
8114
|
text: `门迫(同宫内门克宫):${forced.length ? forced.join('、') : '本盘无'};`
|
|
6866
8115
|
+ `宫制门(宫克门,属「制」不为迫):${controlled.length ? controlled.join('、') : '无'}。`
|
|
8116
|
+
+ `击刑(天盘六仪落刑宫):${jiXing.length ? jiXing.map((x) => `${x.palace}宫${x.stem}(${x.basis})`).join('、') : '本盘无'};`
|
|
8117
|
+
+ `入墓(天盘三奇落墓宫):${ruMu.length ? ruMu.map((x) => `${x.palace}宫${x.stem}(${x.basis})`).join('、') : '本盘无'}。`
|
|
6867
8118
|
+ (kongCells.length ? `空亡:${kongCells.join('、')}——落空之宫事多不实。` : '无落空之宫。')
|
|
6868
|
-
+
|
|
8119
|
+
+ `这三项都只作宫位条件:门迫、击刑、入墓不自动等同于用神受制,取象时看它们落在哪个符号上。`,
|
|
6869
8120
|
});
|
|
6870
8121
|
|
|
8122
|
+
const mo = r.month || null;
|
|
8123
|
+
const st = r.states || null;
|
|
8124
|
+
if (mo && st) {
|
|
8125
|
+
const order = ['旺', '相', '休', '囚', '死'];
|
|
8126
|
+
const line = (g) => order.filter((k) => g && Array.isArray(g[k]) && g[k].length)
|
|
8127
|
+
.map((k) => `${k} ${g[k].join('、')}`).join(';') || '—';
|
|
8128
|
+
sections.push({
|
|
8129
|
+
key: 'states',
|
|
8130
|
+
label: '月令旺衰',
|
|
8131
|
+
text: `月令 ${mo.branch}(${mo.element}):`
|
|
8132
|
+
+ `门 ${line(st.gate)}。星 ${line(st.star)}。天盘干 ${line(st.stem)}。`
|
|
8133
|
+
+ `旺为同月令之气,相为月令所生,休为生月令,囚为克月令,死为月令所克。`
|
|
8134
|
+
+ `干宫的落宫关系另算:${stemRelationLine(r)}。`
|
|
8135
|
+
+ `这一层只说明门、星、干自身力量强弱,不合吉凶:门旺而宫克门,仍受宫制;星旺而落宫死地,也难全其用。`,
|
|
8136
|
+
});
|
|
8137
|
+
}
|
|
8138
|
+
|
|
6871
8139
|
if (unresolved.length) {
|
|
6872
8140
|
sections.push({
|
|
6873
8141
|
key: 'tendency',
|
|
@@ -6881,7 +8149,7 @@ function interpretQimen(r, opts = {}) {
|
|
|
6881
8149
|
key: 'tendency',
|
|
6882
8150
|
label: '最终倾向',
|
|
6883
8151
|
text: `在当前输入、规则集与所问之事下:若以「${primary.key}」为用神,用神宫对值符宫为「${rel}」,整体${tone};`
|
|
6884
|
-
+ `若${ys.label}
|
|
8152
|
+
+ `若${ys.label}实际取另一个候选,或时间范围不同,解读边界随之变化。未决项:天盘干与地盘的十干克应(100 组)未纳入本规则集,干宫生克只作落宫条件。`,
|
|
6885
8153
|
});
|
|
6886
8154
|
}
|
|
6887
8155
|
|
|
@@ -7602,6 +8870,407 @@ function buildNumerology(input) {
|
|
|
7602
8870
|
return { NUMBER_MEANING, reduceNumber, buildNumerology };
|
|
7603
8871
|
})();
|
|
7604
8872
|
|
|
8873
|
+
__mods.mbti = (function () {
|
|
8874
|
+
const { fail } = __mods.fail;
|
|
8875
|
+
|
|
8876
|
+
const DIMENSIONS = [
|
|
8877
|
+
{
|
|
8878
|
+
key: 'EI',
|
|
8879
|
+
left: 'E',
|
|
8880
|
+
right: 'I',
|
|
8881
|
+
name: '能量方向',
|
|
8882
|
+
leftSay: '向外:和人打交道时来电,边说边想',
|
|
8883
|
+
rightSay: '向内:独处时回血,先想清楚再开口',
|
|
8884
|
+
tie: 'I',
|
|
8885
|
+
note: '不是「会不会社交」,而是社交之后你更有电还是更耗电。',
|
|
8886
|
+
},
|
|
8887
|
+
{
|
|
8888
|
+
key: 'SN',
|
|
8889
|
+
left: 'S',
|
|
8890
|
+
right: 'N',
|
|
8891
|
+
name: '信息接收',
|
|
8892
|
+
leftSay: '具体:先看事实、细节和已有经验',
|
|
8893
|
+
rightSay: '联想:先看模式、隐喻和下一步可能',
|
|
8894
|
+
tie: 'N',
|
|
8895
|
+
note: '不是「聪明与否」,而是你先抓住哪一头。',
|
|
8896
|
+
},
|
|
8897
|
+
{
|
|
8898
|
+
key: 'TF',
|
|
8899
|
+
left: 'T',
|
|
8900
|
+
right: 'F',
|
|
8901
|
+
name: '决策依据',
|
|
8902
|
+
leftSay: '逻辑:先看是否站得住、是否一致',
|
|
8903
|
+
rightSay: '价值:先看人在其中会不会被伤到',
|
|
8904
|
+
tie: 'F',
|
|
8905
|
+
note: '不是「冷血或情绪化」,而是权衡时先放哪把尺子。',
|
|
8906
|
+
},
|
|
8907
|
+
{
|
|
8908
|
+
key: 'JP',
|
|
8909
|
+
left: 'J',
|
|
8910
|
+
right: 'P',
|
|
8911
|
+
name: '生活节奏',
|
|
8912
|
+
leftSay: '收束:先定计划,喜欢事情有个了结',
|
|
8913
|
+
rightSay: '开放:先留着口子,喜欢事情还能变',
|
|
8914
|
+
tie: 'P',
|
|
8915
|
+
note: '不是「勤快或懒散」,而是面对不确定时更愿意钉死还是留着。',
|
|
8916
|
+
},
|
|
8917
|
+
];
|
|
8918
|
+
|
|
8919
|
+
const QUESTIONS = [
|
|
8920
|
+
{ id: 'e1', dim: 'EI', side: 'E', text: '在一个都是陌生人的场合,你会主动找几个人聊起来。' },
|
|
8921
|
+
{ id: 's1', dim: 'SN', side: 'S', text: '别人讲一件事,你更关心具体发生了什么、细节对不对得上。' },
|
|
8922
|
+
{ id: 't1', dim: 'TF', side: 'T', text: '朋友来问你两难的选择,你会先把利弊摆清楚再谈感受。' },
|
|
8923
|
+
{ id: 'j1', dim: 'JP', side: 'J', text: '出门前你习惯把行程和要带的东西先定下来。' },
|
|
8924
|
+
{ id: 'e2', dim: 'EI', side: 'I', text: '忙完一整天,你更想一个人安静待着,而不是再约一轮。' },
|
|
8925
|
+
{ id: 's2', dim: 'SN', side: 'N', text: '你常从一个现象跳到「再往下可能还会怎样」的联想上。' },
|
|
8926
|
+
{ id: 't2', dim: 'TF', side: 'F', text: '做决定时,你更在意这件事对身边人的实际影响。' },
|
|
8927
|
+
{ id: 'j2', dim: 'JP', side: 'P', text: '计划临时被打乱,你多半能顺势改,不太难受。' },
|
|
8928
|
+
{ id: 'e3', dim: 'EI', side: 'E', text: '想事情的时候,你更习惯说给人听,说着说着就清楚了。' },
|
|
8929
|
+
{ id: 's3', dim: 'SN', side: 'S', text: '你更信「做过、验证过」的办法,而不是听起来很新的办法。' },
|
|
8930
|
+
{ id: 't3', dim: 'TF', side: 'T', text: '规则一旦定了,哪怕对自己不方便,你也倾向照着走。' },
|
|
8931
|
+
{ id: 'j3', dim: 'JP', side: 'J', text: '有一件事没做完,你心里会一直悬着,想先把它收尾。' },
|
|
8932
|
+
{ id: 'e4', dim: 'EI', side: 'I', text: '电话响了或有人临时找来,你第一反应是先缓一下再应对。' },
|
|
8933
|
+
{ id: 's4', dim: 'SN', side: 'N', text: '你容易被「这背后是什么道理」这类问题勾住。' },
|
|
8934
|
+
{ id: 't4', dim: 'TF', side: 'F', text: '别人情绪不好时,你直觉是先接住情绪,而不是先讲道理。' },
|
|
8935
|
+
{ id: 'j4', dim: 'JP', side: 'P', text: '你常常边走边看,事到临头再定具体怎么做。' },
|
|
8936
|
+
{ id: 'e5', dim: 'EI', side: 'E', text: '人多的场合待久了,你通常越待越有精神。' },
|
|
8937
|
+
{ id: 's5', dim: 'SN', side: 'S', text: '你记事情偏向记「原话、原样、当时的情形」。' },
|
|
8938
|
+
{ id: 't5', dim: 'TF', side: 'T', text: '和人争论时,你更在意谁的推理有漏洞,而不是谁伤了面子。' },
|
|
8939
|
+
{ id: 'j5', dim: 'JP', side: 'J', text: '你喜欢把待办列出来,一条条划掉。' },
|
|
8940
|
+
{ id: 'e6', dim: 'EI', side: 'I', text: '有新想法时,你更愿意先自己消化一轮,再拿出去讲。' },
|
|
8941
|
+
{ id: 's6', dim: 'SN', side: 'N', text: '比起照现状做好,你更享受把现状改成一个更好的样子。' },
|
|
8942
|
+
{ id: 't6', dim: 'TF', side: 'F', text: '要做取舍时,你会想「这样是不是对人不公平」。' },
|
|
8943
|
+
{ id: 'j6', dim: 'JP', side: 'P', text: '临出发才收拾行李,你也觉得没什么问题。' },
|
|
8944
|
+
];
|
|
8945
|
+
|
|
8946
|
+
const FUNCTION_STACKS = {
|
|
8947
|
+
ISTJ: ['Si', 'Te', 'Fi', 'Ne'],
|
|
8948
|
+
ISFJ: ['Si', 'Fe', 'Ti', 'Ne'],
|
|
8949
|
+
INFJ: ['Ni', 'Fe', 'Ti', 'Se'],
|
|
8950
|
+
INTJ: ['Ni', 'Te', 'Fi', 'Se'],
|
|
8951
|
+
ISTP: ['Ti', 'Se', 'Ni', 'Fe'],
|
|
8952
|
+
ISFP: ['Fi', 'Se', 'Ni', 'Te'],
|
|
8953
|
+
INFP: ['Fi', 'Ne', 'Si', 'Te'],
|
|
8954
|
+
INTP: ['Ti', 'Ne', 'Si', 'Fe'],
|
|
8955
|
+
ESTP: ['Se', 'Ti', 'Fe', 'Ni'],
|
|
8956
|
+
ESFP: ['Se', 'Fi', 'Te', 'Ni'],
|
|
8957
|
+
ENFP: ['Ne', 'Fi', 'Te', 'Si'],
|
|
8958
|
+
ENTP: ['Ne', 'Ti', 'Fe', 'Si'],
|
|
8959
|
+
ESTJ: ['Te', 'Si', 'Ne', 'Fi'],
|
|
8960
|
+
ESFJ: ['Fe', 'Si', 'Ne', 'Ti'],
|
|
8961
|
+
ENFJ: ['Fe', 'Ni', 'Se', 'Ti'],
|
|
8962
|
+
ENTJ: ['Te', 'Ni', 'Se', 'Fi'],
|
|
8963
|
+
};
|
|
8964
|
+
|
|
8965
|
+
const FUNCTIONS = {
|
|
8966
|
+
Si: '内感觉:拿过去的经验当尺子,稳、细、记得住。',
|
|
8967
|
+
Se: '外感觉:对眼前的具体变化反应快,先动手再说。',
|
|
8968
|
+
Ni: '内直觉:把零碎线索收成一个方向感,先看到终局。',
|
|
8969
|
+
Ne: '外直觉:从一个点炸开很多可能,擅长另起一条路。',
|
|
8970
|
+
Ti: '内思考:要自己把逻辑盘通,讲得出为什么才认。',
|
|
8971
|
+
Te: '外思考:要事情跑起来,讲流程、指标和结果。',
|
|
8972
|
+
Fi: '内情感:先问「这符不符合我在意的东西」,价值感很强。',
|
|
8973
|
+
Fe: '外情感:先读空气、先顾关系,擅长把人和在一起。',
|
|
8974
|
+
};
|
|
8975
|
+
|
|
8976
|
+
const TYPES = {
|
|
8977
|
+
ISTJ: {
|
|
8978
|
+
title: '检查者',
|
|
8979
|
+
keywords: '稳、准、守得住',
|
|
8980
|
+
oneLine: '答应的事会做完,讨厌临时改口和半成品。',
|
|
8981
|
+
strengths: ['流程感强,细节不漏', '说到做到,扛得住长期重复', '遇到混乱先立规矩'],
|
|
8982
|
+
blindspots: ['对「新办法」先起疑,容易错过转弯的机会', '把责任揽太多,难受也说不出口'],
|
|
8983
|
+
work: '适合规则清楚、可累积经验的岗位:审计、运维、法务、工程管理。',
|
|
8984
|
+
love: '表达朴素但稳定,重视承诺;需要对方把需求说明白,别指望你自己猜。',
|
|
8985
|
+
study: '靠体系与刷题推进,把知识整理成清单会明显提速。',
|
|
8986
|
+
growth: '练一件「没有标准答案」的事,容许自己在过程中改主意。',
|
|
8987
|
+
},
|
|
8988
|
+
ISFJ: {
|
|
8989
|
+
title: '守护者',
|
|
8990
|
+
keywords: '暖、细、记得住人',
|
|
8991
|
+
oneLine: '会默默把别人的需要记在心里,然后提前做好。',
|
|
8992
|
+
strengths: ['照顾细节与情绪', '记性好,了解身边人的习惯', '愿意做没人愿意做的收尾'],
|
|
8993
|
+
blindspots: ['习惯先委屈自己,之后积成怨', '对方没察觉你的付出时容易失落'],
|
|
8994
|
+
work: '适合需要耐心与责任心的岗位:护理、教育、行政、客户成功、人事。',
|
|
8995
|
+
love: '用做事表达感情,需要被明确看见与感谢;也要练习直接要。',
|
|
8996
|
+
study: '喜欢有例题、有反馈的学习方式,做学习小组的稳定输出者很合适。',
|
|
8997
|
+
growth: '练习说「这件事我做不到」,先照顾自己的电量。',
|
|
8998
|
+
},
|
|
8999
|
+
INFJ: {
|
|
9000
|
+
title: '提倡者',
|
|
9001
|
+
keywords: '深、理想、看穿人心',
|
|
9002
|
+
oneLine: '关心人为什么这么活,愿意为一个「值得」的目标长期投入。',
|
|
9003
|
+
strengths: ['能从细节里读出动机', '表达有感染力,适合讲清意义', '对长期方向有耐心'],
|
|
9004
|
+
blindspots: ['标准高,容易对现实失望', '想得太深而迟迟不开口,外人看不出你在乎'],
|
|
9005
|
+
work: '适合内容、咨询、教育、公益、产品策略这类「讲清一件事」的岗位。',
|
|
9006
|
+
love: '要的是深谈与理解,浅社交会耗电;需要对方给得起精神上的回应。',
|
|
9007
|
+
study: '适合主题式深挖,写读书笔记与建立自己的框架比刷题更有效。',
|
|
9008
|
+
growth: '把理想拆成这周能交付的一小步,别只在脑子里完成它。',
|
|
9009
|
+
},
|
|
9010
|
+
INTJ: {
|
|
9011
|
+
title: '建筑师',
|
|
9012
|
+
keywords: '远、冷静、自己搭系统',
|
|
9013
|
+
oneLine: '先看清全局再动手,讨厌无效沟通和低效流程。',
|
|
9014
|
+
strengths: ['长期规划清晰', '能独立啃下复杂问题', '对标准挑剔,产品因此更硬'],
|
|
9015
|
+
blindspots: ['说话直,容易让人觉得被否定', '对「慢」和「情绪」耐心不足'],
|
|
9016
|
+
work: '适合战略、研发、系统设计、投资研究这类需要独立判断的岗位。',
|
|
9017
|
+
love: '表达感情偏克制,用解决问题的方式示好;需要对方接受你的独处需求。',
|
|
9018
|
+
study: '自学效率高,适合先建框架再补细节;警惕只读不产出。',
|
|
9019
|
+
growth: '在给方案之前先接一句对方的感受,合作阻力会小很多。',
|
|
9020
|
+
},
|
|
9021
|
+
ISTP: {
|
|
9022
|
+
title: '巧匠',
|
|
9023
|
+
keywords: '手快、冷静、先修再说',
|
|
9024
|
+
oneLine: '遇到问题先上手拆开看,不爱开长会。',
|
|
9025
|
+
strengths: ['动手能力强,现场判断快', '压力下不慌,能抓住关键', '讲实际,不绕弯'],
|
|
9026
|
+
blindspots: ['对长期计划不感兴趣,容易拖到最后', '话少,别人不知道你在想什么'],
|
|
9027
|
+
work: '适合现场性强的岗位:工程、设备、急救、运维、技术支持、手艺型工作。',
|
|
9028
|
+
love: '不擅长说,但会用行动帮忙;需要对方接受你「不解释」的习惯。',
|
|
9029
|
+
study: '边做边学最快,先碰真实设备或真实项目,再回头补理论。',
|
|
9030
|
+
growth: '给重要的事留一个检查点,别全靠临场反应。',
|
|
9031
|
+
},
|
|
9032
|
+
ISFP: {
|
|
9033
|
+
title: '探险家',
|
|
9034
|
+
keywords: '真、敏感、跟着感觉走',
|
|
9035
|
+
oneLine: '在意「这件事对不对味」,不喜欢被安排得太死。',
|
|
9036
|
+
strengths: ['审美与体感准', '待人温和,不强加于人', '在真实情境里学得快'],
|
|
9037
|
+
blindspots: ['不愿冲突,把不满压着', '长期目标容易停在「想」这一步'],
|
|
9038
|
+
work: '适合与美、身体、具体对象打交道的岗位:设计、摄影、餐饮、康复、手作。',
|
|
9039
|
+
love: '用陪伴和小惊喜表达在意,讨厌被审问;需要空间也需要被确认。',
|
|
9040
|
+
study: '先看示例、先动手,理论放在用到的时候补,效率更高。',
|
|
9041
|
+
growth: '给在意的事定一个可交付的日期,把感觉变成作品。',
|
|
9042
|
+
},
|
|
9043
|
+
INFP: {
|
|
9044
|
+
title: '调停者',
|
|
9045
|
+
keywords: '柔、较真、心里有一杆秤',
|
|
9046
|
+
oneLine: '对人真诚,对自己在意的事格外较真,讨厌虚伪。',
|
|
9047
|
+
strengths: ['共情与想象力都好', '写与表达有个人味道', '能为价值观长期坚持'],
|
|
9048
|
+
blindspots: ['容易把「不够好」归到自己身上', '计划性弱,想法多而落地慢'],
|
|
9049
|
+
work: '适合创作、教育、心理、内容、公益这类能表达价值的岗位;强规则环境会耗电。',
|
|
9050
|
+
love: '看重真诚与被理解,愿意为对方调整;需要明确的回应,别长期猜。',
|
|
9051
|
+
study: '靠兴趣驱动,给自己找「为什么学」比逼自己更有效;用短周期输出防拖延。',
|
|
9052
|
+
growth: '把心里的标准写下来,分「必须有」和「有更好」,少一点全或无。',
|
|
9053
|
+
},
|
|
9054
|
+
INTP: {
|
|
9055
|
+
title: '逻辑家',
|
|
9056
|
+
keywords: '想透、好问、自己盘逻辑',
|
|
9057
|
+
oneLine: '喜欢把问题拆到原理层,讨厌「一直这样所以就这样」。',
|
|
9058
|
+
strengths: ['抽象思考强,能发现系统里的漏洞', '学新领域快', '不轻易被权威说服'],
|
|
9059
|
+
blindspots: ['想得多做得少,收尾困难', '指出问题时不修饰,容易树敌'],
|
|
9060
|
+
work: '适合研究、算法、架构、分析、写作这类需要反复推演的岗位。',
|
|
9061
|
+
love: '用分享想法表达亲近,需要对方能聊得深;别让讨论变成辩论。',
|
|
9062
|
+
study: '先弄清原理再练,适合自己搭知识树;给自己设「讲给别人听」的交付点。',
|
|
9063
|
+
growth: '给探索设时间盒,到点就交出一个能用的版本。',
|
|
9064
|
+
},
|
|
9065
|
+
ESTP: {
|
|
9066
|
+
title: '企业家',
|
|
9067
|
+
keywords: '快、敢、临场能打',
|
|
9068
|
+
oneLine: '看到机会先动手,比开会讨论更信现场反馈。',
|
|
9069
|
+
strengths: ['行动快,敢试错', '会看人、会周旋', '压力下反而清醒'],
|
|
9070
|
+
blindspots: ['耐心不足,容易留一堆半成品', '对长期代价估计偏轻'],
|
|
9071
|
+
work: '适合销售、商务、创业、现场运营、竞技类岗位;文牍型工作会闷。',
|
|
9072
|
+
love: '热烈直接,喜欢一起做事;需要对方接受你「说到就到」的节奏。',
|
|
9073
|
+
study: '靠实战与竞赛驱动,做项目比听课有效;需要有人帮你收尾。',
|
|
9074
|
+
growth: '动手前多问一句「三个月后这件事还成立吗」。',
|
|
9075
|
+
},
|
|
9076
|
+
ESFP: {
|
|
9077
|
+
title: '表演者',
|
|
9078
|
+
keywords: '热、会带气氛、活在当下',
|
|
9079
|
+
oneLine: '在人群里自带气氛,喜欢真实可感的体验。',
|
|
9080
|
+
strengths: ['感染力强,能把场子撑起来', '对人和现场的细节敏感', '愿意尝试新鲜事'],
|
|
9081
|
+
blindspots: ['对长期枯燥的事耐力有限', '不太愿意面对冲突背后的结构问题'],
|
|
9082
|
+
work: '适合面向人的岗位:活动、销售、主持、文旅、服务、内容出镜。',
|
|
9083
|
+
love: '表达直接,喜欢一起玩;需要对方给你稳定感,也别把自由当借口。',
|
|
9084
|
+
study: '边玩边学最有效,把知识做成游戏、演示或小组活动。',
|
|
9085
|
+
growth: '留一件「不好玩但重要」的事,按周推进。',
|
|
9086
|
+
},
|
|
9087
|
+
ENFP: {
|
|
9088
|
+
title: '竞选者',
|
|
9089
|
+
keywords: '亮、点子多、对人好奇',
|
|
9090
|
+
oneLine: '对人和可能性都很好奇,容易同时点亮很多盏灯。',
|
|
9091
|
+
strengths: ['联想快,能给人新视角', '真诚热情,容易建立信任', '擅长起头与鼓舞'],
|
|
9092
|
+
blindspots: ['兴趣转移快,收尾吃力', '情绪起伏大,容易被细节拖垮'],
|
|
9093
|
+
work: '适合创意、品牌、内容、培训、早期项目这类需要不断开新局的地方。',
|
|
9094
|
+
love: '需要新鲜感与被看见,愿意为对方想很多;要练习把承诺落到实处。',
|
|
9095
|
+
study: '用主题和讨论驱动,找学习搭子比一个人硬啃有效。',
|
|
9096
|
+
growth: '同时只开三条线,其余写进「以后再说」清单。',
|
|
9097
|
+
},
|
|
9098
|
+
ENTP: {
|
|
9099
|
+
title: '辩论家',
|
|
9100
|
+
keywords: '机敏、爱拆、想法往外冒',
|
|
9101
|
+
oneLine: '喜欢把既有说法掰开看,享受把问题换个角度。',
|
|
9102
|
+
strengths: ['反应快,能现场找到漏洞', '对新领域上手快', '擅长把复杂事讲得好玩'],
|
|
9103
|
+
blindspots: ['为辩而辩,容易伤人', '起头多、收尾少'],
|
|
9104
|
+
work: '适合咨询、产品、创业、策略、媒体这类需要不断破局的地方。',
|
|
9105
|
+
love: '用斗嘴表达亲近,需要对方接得住;别把关系也当成辩论场。',
|
|
9106
|
+
study: '讨论与质疑中理解最快,适合做分享者;给自己定交付时间。',
|
|
9107
|
+
growth: '挑一件「不新但重要」的事,把它做完再开下一个。',
|
|
9108
|
+
},
|
|
9109
|
+
ESTJ: {
|
|
9110
|
+
title: '总经理',
|
|
9111
|
+
keywords: '务实、能扛、把事推到底',
|
|
9112
|
+
oneLine: '目标定了就拆任务、定人、定时间,讨厌含糊。',
|
|
9113
|
+
strengths: ['组织与推进力强', '标准清楚,团队知道该做什么', '对结果负责'],
|
|
9114
|
+
blindspots: ['节奏太紧,忽视人的感受', '对新方法的容忍度低'],
|
|
9115
|
+
work: '适合管理、运营、项目、供应链、政务这类要「把事办成」的岗位。',
|
|
9116
|
+
love: '用承担责任表达在意,需要对方直接说需求;记得留不安排的时间。',
|
|
9117
|
+
study: '目标拆解 + 打卡推进最有效,适合带小组复习。',
|
|
9118
|
+
growth: '在下判断前多问一句「有没有我没想到的难处」。',
|
|
9119
|
+
},
|
|
9120
|
+
ESFJ: {
|
|
9121
|
+
title: '执政官',
|
|
9122
|
+
keywords: '周到、热络、把人放在心上',
|
|
9123
|
+
oneLine: '习惯先照顾气氛和关系,让事情在人情里办成。',
|
|
9124
|
+
strengths: ['组织人际与活动', '记得住每个人的状况', '愿意为集体做脏活累活'],
|
|
9125
|
+
blindspots: ['太在意别人评价,容易内耗', '对「不合群」的选项排斥'],
|
|
9126
|
+
work: '适合人力、行政、教育、客户、医护、社群运营这类以人为中心的岗位。',
|
|
9127
|
+
love: '投入、周到,需要明确的回应与稳定;别把照顾变成控制。',
|
|
9128
|
+
study: '在小组里学得最好,讲给别人听会记得更牢。',
|
|
9129
|
+
growth: '练习在不解释的情况下做一次自己的选择。',
|
|
9130
|
+
},
|
|
9131
|
+
ENFJ: {
|
|
9132
|
+
title: '主人公',
|
|
9133
|
+
keywords: '暖、会带人、看得见潜力',
|
|
9134
|
+
oneLine: '天然想把人和事往好的方向推,愿意为别人多走一步。',
|
|
9135
|
+
strengths: ['洞察他人需求', '善于组织与鼓舞', '把长期关系经营得住'],
|
|
9136
|
+
blindspots: ['过度承担别人的情绪', '为了和谐压下自己的判断'],
|
|
9137
|
+
work: '适合教育、管理、培训、公益、品牌这类「带人成长」的岗位。',
|
|
9138
|
+
love: '投入且会照顾,需要对方也主动;别把付出当成默认义务。',
|
|
9139
|
+
study: '教别人是最好的学法,适合做学习小组的组织者。',
|
|
9140
|
+
growth: '把「我该帮」和「不该我扛」分开,先照顾自己的电量。',
|
|
9141
|
+
},
|
|
9142
|
+
ENTJ: {
|
|
9143
|
+
title: '指挥官',
|
|
9144
|
+
keywords: '决断、看清、把盘做大',
|
|
9145
|
+
oneLine: '看得远也敢拍板,喜欢把资源调到最该去的地方。',
|
|
9146
|
+
strengths: ['目标与路径清楚', '能在压力下决断', '擅长组织复杂局面'],
|
|
9147
|
+
blindspots: ['节奏压人,忽略情绪成本', '把「效率」当成唯一标准'],
|
|
9148
|
+
work: '适合管理、创业、投资、战略、大型项目这类要定方向并扛结果的岗位。',
|
|
9149
|
+
love: '用规划和承担表达在意,需要对方能对话;记得把「安排」换成「商量」。',
|
|
9150
|
+
study: '先建目标与评估标准,按里程碑推进;警惕只搭框架不落细节。',
|
|
9151
|
+
growth: '定期问自己「这件事赢了,人会怎样」,把人的成本算进去。',
|
|
9152
|
+
},
|
|
9153
|
+
};
|
|
9154
|
+
|
|
9155
|
+
const SCALE_SAY = {
|
|
9156
|
+
1: '完全不像',
|
|
9157
|
+
2: '不太像',
|
|
9158
|
+
3: '说不准',
|
|
9159
|
+
4: '有点像',
|
|
9160
|
+
5: '很像我',
|
|
9161
|
+
};
|
|
9162
|
+
|
|
9163
|
+
function mbtiPaper() {
|
|
9164
|
+
return {
|
|
9165
|
+
system: 'mbti',
|
|
9166
|
+
needAnswers: true,
|
|
9167
|
+
scale: SCALE_SAY,
|
|
9168
|
+
total: QUESTIONS.length,
|
|
9169
|
+
dimensions: DIMENSIONS.map((d) => ({ key: d.key, name: d.name, left: d.left, right: d.right, leftSay: d.leftSay, rightSay: d.rightSay, note: d.note })),
|
|
9170
|
+
questions: QUESTIONS.map((q, i) => ({ no: i + 1, id: q.id, dim: q.dim, text: q.text })),
|
|
9171
|
+
note: '这是一份 MBTI 风格的问卷(不是官方 MBTI 量表):每题按 1(完全不像我)到 5(很像我)打分,把 24 个分数按顺序交给 answers 即可出类型。题目只作自我参照,不适合用来评价别人的能力或做招聘、晋升等决定。',
|
|
9172
|
+
};
|
|
9173
|
+
}
|
|
9174
|
+
|
|
9175
|
+
function normalizeAnswers(answers) {
|
|
9176
|
+
if (!Array.isArray(answers)) {
|
|
9177
|
+
throw fail('E_INPUT', 'answers 必须是数组:每题 1–5 分,按 questions 的顺序给;答题前先不带 answers 调一次,拿到题目');
|
|
9178
|
+
}
|
|
9179
|
+
if (answers.length > QUESTIONS.length) {
|
|
9180
|
+
throw fail('E_INPUT', `answers 最多 ${QUESTIONS.length} 个(对应 ${QUESTIONS.length} 题),收到 ${answers.length} 个`);
|
|
9181
|
+
}
|
|
9182
|
+
const out = [];
|
|
9183
|
+
for (let i = 0; i < QUESTIONS.length; i += 1) {
|
|
9184
|
+
const raw = answers[i];
|
|
9185
|
+
if (raw === undefined || raw === null || raw === '') {
|
|
9186
|
+
out.push(null);
|
|
9187
|
+
continue;
|
|
9188
|
+
}
|
|
9189
|
+
const v = Number(raw);
|
|
9190
|
+
if (!Number.isInteger(v) || v < 1 || v > 5) {
|
|
9191
|
+
throw fail('E_RANGE', `第 ${i + 1} 题的分值必须是 1–5 的整数(1 完全不像,5 很像我),收到「${raw}」`);
|
|
9192
|
+
}
|
|
9193
|
+
out.push(v);
|
|
9194
|
+
}
|
|
9195
|
+
return out;
|
|
9196
|
+
}
|
|
9197
|
+
|
|
9198
|
+
function strengthOf(pct, answered) {
|
|
9199
|
+
if (!answered) return '未作答';
|
|
9200
|
+
if (pct <= 0.12) return '临界';
|
|
9201
|
+
if (pct <= 0.3) return '轻微';
|
|
9202
|
+
if (pct <= 0.6) return '明显';
|
|
9203
|
+
return '很强';
|
|
9204
|
+
}
|
|
9205
|
+
|
|
9206
|
+
function buildMbti(input = {}) {
|
|
9207
|
+
const answers = normalizeAnswers(input.answers);
|
|
9208
|
+
const answeredAll = answers.filter((v) => v !== null).length;
|
|
9209
|
+
if (answeredAll < 12) {
|
|
9210
|
+
throw fail('E_INPUT', `至少答 ${12} 题才能出口径(现答 ${answeredAll} 题);可以先不带 answers 调一次,把题目发给用户逐题打分`);
|
|
9211
|
+
}
|
|
9212
|
+
const dims = DIMENSIONS.map((d) => {
|
|
9213
|
+
let sum = 0;
|
|
9214
|
+
let answered = 0;
|
|
9215
|
+
QUESTIONS.forEach((q, i) => {
|
|
9216
|
+
const v = answers[i];
|
|
9217
|
+
if (v === null || q.dim !== d.key) return;
|
|
9218
|
+
answered += 1;
|
|
9219
|
+
sum += (v - 3) * (q.side === d.left ? 1 : -1);
|
|
9220
|
+
});
|
|
9221
|
+
const maxAbs = answered * 2;
|
|
9222
|
+
const pct = maxAbs ? Math.abs(sum) / maxAbs : 0;
|
|
9223
|
+
const picked = sum > 0 ? d.left : sum < 0 ? d.right : d.tie;
|
|
9224
|
+
return {
|
|
9225
|
+
key: d.key,
|
|
9226
|
+
name: d.name,
|
|
9227
|
+
left: d.left,
|
|
9228
|
+
right: d.right,
|
|
9229
|
+
leftSay: d.leftSay,
|
|
9230
|
+
rightSay: d.rightSay,
|
|
9231
|
+
note: d.note,
|
|
9232
|
+
sum,
|
|
9233
|
+
answered,
|
|
9234
|
+
maxAbs,
|
|
9235
|
+
pct: Math.round(pct * 1000) / 1000,
|
|
9236
|
+
picked,
|
|
9237
|
+
strength: strengthOf(pct, answered),
|
|
9238
|
+
tie: sum === 0,
|
|
9239
|
+
};
|
|
9240
|
+
});
|
|
9241
|
+
const type = dims.map((d) => d.picked).join('');
|
|
9242
|
+
const profile = TYPES[type];
|
|
9243
|
+
if (!profile) throw fail('E_SYSTEM', `内部错误:类型 ${type} 没有对应文案`);
|
|
9244
|
+
const stack = (FUNCTION_STACKS[type] || []).map((f) => ({ code: f, say: FUNCTIONS[f] || '' }));
|
|
9245
|
+
return {
|
|
9246
|
+
system: 'mbti',
|
|
9247
|
+
type,
|
|
9248
|
+
title: profile.title,
|
|
9249
|
+
keywords: profile.keywords,
|
|
9250
|
+
oneLine: profile.oneLine,
|
|
9251
|
+
dims: dims.map(({ sum, maxAbs, answered, ...rest }) => ({ ...rest, sum, maxAbs, answered })),
|
|
9252
|
+
profile: {
|
|
9253
|
+
title: profile.title,
|
|
9254
|
+
keywords: profile.keywords,
|
|
9255
|
+
oneLine: profile.oneLine,
|
|
9256
|
+
strengths: profile.strengths.slice(),
|
|
9257
|
+
blindspots: profile.blindspots.slice(),
|
|
9258
|
+
work: profile.work,
|
|
9259
|
+
love: profile.love,
|
|
9260
|
+
study: profile.study,
|
|
9261
|
+
growth: profile.growth,
|
|
9262
|
+
stack,
|
|
9263
|
+
},
|
|
9264
|
+
answered: answeredAll,
|
|
9265
|
+
skipped: QUESTIONS.length - answeredAll,
|
|
9266
|
+
total: QUESTIONS.length,
|
|
9267
|
+
note: '四维各 6 题、李克特 1–5 计分,按维度净分取字母(平手时取 I / N / F / P 一侧并标「临界」)。这是 MBTI 风格的问卷测算,不是官方量表;类型只作自我参照,不是能力评价,也不用它给人下结论。',
|
|
9268
|
+
};
|
|
9269
|
+
}
|
|
9270
|
+
|
|
9271
|
+
return { DIMENSIONS, QUESTIONS, FUNCTION_STACKS, FUNCTIONS, TYPES, mbtiPaper, buildMbti };
|
|
9272
|
+
})();
|
|
9273
|
+
|
|
7605
9274
|
__mods.chenggu = (function () {
|
|
7606
9275
|
const { solarToLunar } = __mods.lunar;
|
|
7607
9276
|
const { ganzhiName, toJDN, dayGanzhiIndex } = __mods.calendar;
|
|
@@ -8132,6 +9801,89 @@ const STRENGTH_PLAIN = {
|
|
|
8132
9801
|
身弱: '底子偏薄,先修恢复力再谈冲刺,硬撑的性价比最低',
|
|
8133
9802
|
};
|
|
8134
9803
|
|
|
9804
|
+
const PLAIN_BODY = {
|
|
9805
|
+
六冲卦: '这一卦是「六冲」,事情起落快,急事反而好办,拖久了的人事容易散。',
|
|
9806
|
+
六合卦: '这一卦是「六合」,容易谈成,也容易黏住不放。',
|
|
9807
|
+
变六冲: '往下走会散,收尾别拖。',
|
|
9808
|
+
变六合: '往下走会合,事情倾向于延续下去。',
|
|
9809
|
+
内卦伏吟: '事情卡在原地打转,想动但动不了。',
|
|
9810
|
+
外卦伏吟: '外面那层没变,看起来在动,其实格局照旧。',
|
|
9811
|
+
内卦反吟: '反复在自己这一头,改了又改回来。',
|
|
9812
|
+
外卦反吟: '外面反复,对方或环境会来回拉扯。',
|
|
9813
|
+
化进神: '有一爻在往上走,顺着这股劲推比往回拉顺。',
|
|
9814
|
+
化退神: '有一爻在往后退,别按原来的势头硬推。',
|
|
9815
|
+
};
|
|
9816
|
+
|
|
9817
|
+
function usePlainOf(ug) {
|
|
9818
|
+
if (!ug || !ug.liuqin) return '';
|
|
9819
|
+
if (ug.found.length) {
|
|
9820
|
+
const pos = ug.found.map((f) => `第${f.position}爻`).join('、');
|
|
9821
|
+
const moving = ug.found.some((f) => f.moving);
|
|
9822
|
+
const who = ug.byShi ? '代表你自己' : `就是「${ug.liuqin}」这一类事`;
|
|
9823
|
+
return `你问的这件事,在卦里对应${pos}${who}——${moving ? '这一爻还在动,说明事情正在推进' : '这一爻没动,先按现状看'}。`;
|
|
9824
|
+
}
|
|
9825
|
+
if (ug.fushen.length) {
|
|
9826
|
+
const f = ug.fushen[0];
|
|
9827
|
+
return `你问的这件事,卦面上没有直接露出来,得往深处找:它藏在第${f.position}爻下面(伏神),与上面的关系是「${f.relation || '—'}」,要借力才出得来。`;
|
|
9828
|
+
}
|
|
9829
|
+
return '';
|
|
9830
|
+
}
|
|
9831
|
+
|
|
9832
|
+
function useStrengthPlain(st) {
|
|
9833
|
+
if (!st || !st.lines || !st.lines.length) return '';
|
|
9834
|
+
const dead = st.lines.filter((l) => /死|囚/.test(l.monthState) || l.monthChong);
|
|
9835
|
+
const live = st.lines.filter((l) => /旺|相/.test(l.monthState));
|
|
9836
|
+
const when = st.month && st.month.branch ? `眼下这阵子(${st.month.branch}月)` : '起卦这段日子';
|
|
9837
|
+
if (dead.length && !live.length) return `${when}对这件事不太帮忙,气有点被压着——先别急着硬推,等风向转。`;
|
|
9838
|
+
if (live.length && !dead.length) return `${when}对这件事是帮着的,气正在往上走,能推就趁现在。`;
|
|
9839
|
+
return `${when}对这件事有帮有压,一半的力要自己挣——结果更看你怎么走。`;
|
|
9840
|
+
}
|
|
9841
|
+
|
|
9842
|
+
function jinTuiPlain(r) {
|
|
9843
|
+
const jp = r && r.jinTuiPower;
|
|
9844
|
+
if (!jp || !Array.isArray(jp.lines) || !jp.lines.length) return '';
|
|
9845
|
+
const sayOf = (l) => (l.verdict === '后劲足' ? '时令托着,后劲足'
|
|
9846
|
+
: l.verdict === '后劲有限' ? '时令不太托,后劲有限'
|
|
9847
|
+
: l.verdict === '进得虚' ? '时令最背,进也是虚进'
|
|
9848
|
+
: l.verdict === '退得缓' ? '时令还托着,退得慢'
|
|
9849
|
+
: l.verdict === '退得实' ? '时令也不托,退得实'
|
|
9850
|
+
: l.verdict === '月破失据' ? '又正好逢月破,进退都站不稳'
|
|
9851
|
+
: '缺月建,先只当方向看');
|
|
9852
|
+
return `动爻的进退还要看时令:${jp.lines.map((l) => `${l.position}爻${l.from}→${l.to}${l.type},${sayOf(l)}`).join(';')}。`;
|
|
9853
|
+
}
|
|
9854
|
+
|
|
9855
|
+
function hexStrengthPlain(hs) {
|
|
9856
|
+
if (!hs || !hs.counts) return '';
|
|
9857
|
+
const up = (hs.counts.旺 || 0) + (hs.counts.相 || 0);
|
|
9858
|
+
const down = (hs.counts.囚 || 0) + (hs.counts.死 || 0);
|
|
9859
|
+
const when = hs.month && hs.month.branch ? `按${hs.month.branch}月这段时令看` : '按起卦这天看';
|
|
9860
|
+
const shi = hs.shi && hs.shi.monthState !== 'unknown' ? `代表你的世爻在${hs.shi.monthState}` : '';
|
|
9861
|
+
if (up >= 4 && down === 0) return `${when},整张卦六爻的气多数是顺的,${shi},眼下算是好推的时候。`;
|
|
9862
|
+
if (down >= 4 && up === 0) return `${when},整张卦六爻的气多数被压着,${shi},这几天更适合等而不是冲。`;
|
|
9863
|
+
return `${when},整张卦六爻有顺有逆(旺相 ${up} 爻、囚死 ${down} 爻)${shi ? `,${shi}` : ''},成不成要看具体哪一爻在动。`;
|
|
9864
|
+
}
|
|
9865
|
+
|
|
9866
|
+
function flyCompositePlain(fc) {
|
|
9867
|
+
if (!fc || !Array.isArray(fc.targets)) return '';
|
|
9868
|
+
const hub = fc.targets.find((t) => t.count >= 2);
|
|
9869
|
+
const self = fc.groups && fc.groups.selfHua && fc.groups.selfHua.length
|
|
9870
|
+
? '其中有的宫自己化出去又落回自己,容易表现为「想得多、落得少」。'
|
|
9871
|
+
: '';
|
|
9872
|
+
if (!hub) return `把命宫连同对宫、两个三合宫一起看,四股力飞出去没有挤到同一处,这几件事之间牵连不深。${self}`;
|
|
9873
|
+
return `把命宫连同对宫与两个三合宫一起看,${hub.incoming.length} 股力最后挤在「${String(hub.palace).replace(/宫$/, '')}」这件事上——这件事会把好几个方面的劲都吸过来。${self}`;
|
|
9874
|
+
}
|
|
9875
|
+
|
|
9876
|
+
function bodyPlainOf(labels) {
|
|
9877
|
+
const keyOf = (l) => Object.keys(PLAIN_BODY).find((k) => l === k || l.startsWith(`${k} `)) || '';
|
|
9878
|
+
const primary = labels.find((l) => keyOf(l));
|
|
9879
|
+
const main = primary ? PLAIN_BODY[keyOf(primary)] : '';
|
|
9880
|
+
const extra = labels
|
|
9881
|
+
.filter((l) => l !== primary && /^化[进退]神 /.test(l))
|
|
9882
|
+
.map((l) => PLAIN_BODY[keyOf(l)])
|
|
9883
|
+
.filter(Boolean);
|
|
9884
|
+
return main + extra.join('');
|
|
9885
|
+
}
|
|
9886
|
+
|
|
8135
9887
|
const DIR_SECTION = {
|
|
8136
9888
|
wealth: '「工作与职业选择」与「时间窗」',
|
|
8137
9889
|
career: '「事业发展」与「时间窗」',
|
|
@@ -8174,22 +9926,31 @@ function buildAnswer(r, ask, ctx = {}) {
|
|
|
8174
9926
|
const body = r.body || {};
|
|
8175
9927
|
const bureau = r.bureau || {};
|
|
8176
9928
|
const md = r.lifeMaster || '';
|
|
9929
|
+
const ji = r.flyChains && r.flyChains.忌;
|
|
9930
|
+
const plainFly = ji && ji.steps.length
|
|
9931
|
+
? `还有一条线值得留意:${ji.path.map((p) => p.replace(/宫$/, '')).join(' → ')}——这几件事在你身上是连着转的,一件卡住,容易牵动下一件。`
|
|
9932
|
+
: '';
|
|
8177
9933
|
return [
|
|
8178
9934
|
head + `先说结论:你的命宫落${s(soul.branch, '—')}宫` +
|
|
8179
9935
|
`${bureau.name ? `、${bureau.name}` : ''}${md ? `,命主${md}` : ''}` +
|
|
8180
9936
|
`${body.lands ? `,身宫落在「${body.lands}」——这张盘的重心在这件事上` : ''}。`,
|
|
9937
|
+
plainFly,
|
|
9938
|
+
flyCompositePlain(r.flyComposite),
|
|
8181
9939
|
`具体到你问的这件事,重点看${where}。`,
|
|
8182
|
-
].join('');
|
|
9940
|
+
].filter(Boolean).join('');
|
|
8183
9941
|
}
|
|
8184
9942
|
|
|
8185
9943
|
if (r.system === 'liuyao') {
|
|
8186
9944
|
const ben = r.ben || {};
|
|
8187
9945
|
const moving = (r.cast && r.cast.movingPositions) || [];
|
|
8188
9946
|
const bian = r.bian || {};
|
|
9947
|
+
const labels = (r.body && Array.isArray(r.body.labels)) ? r.body.labels : [];
|
|
9948
|
+
const plainBody = bodyPlainOf(labels);
|
|
8189
9949
|
return [
|
|
8190
9950
|
head + `先说结论:本卦是${s(ben.name, '—')}` +
|
|
8191
9951
|
`${ben.palace ? `(${ben.palace})` : ''}` +
|
|
8192
|
-
`${moving.length ? `,第 ${moving.join('、')} 爻动,变为${s(bian.name, '—')}` : ',六爻安静没有动爻'}
|
|
9952
|
+
`${moving.length ? `,第 ${moving.join('、')} 爻动,变为${s(bian.name, '—')}` : ',六爻安静没有动爻'}。` +
|
|
9953
|
+
`${plainBody}${usePlainOf(r.useGod)}${useStrengthPlain(r.useGodStrength)}${jinTuiPlain(r)}${hexStrengthPlain(r.hexStrength)}`,
|
|
8193
9954
|
'断卦的落点在「世爻」(代表你)和「动爻」(事情的推动点),下面「看盘顺序」就按这个次序展开。',
|
|
8194
9955
|
].join('');
|
|
8195
9956
|
}
|
|
@@ -8206,21 +9967,36 @@ function buildPlain(r, ask, ctx = {}) {
|
|
|
8206
9967
|
const avoid = join(ys.avoid);
|
|
8207
9968
|
const strength = STRENGTH_PLAIN[st.level] || '力量偏中性';
|
|
8208
9969
|
const tiaohou = ys.tiaohou && ys.tiaohou.note ? `另外,${ys.tiaohou.note},所以「暖一点、亮一点」的环境通常更舒服。` : '';
|
|
9970
|
+
const sy = (r.liunian || []).find((l) => l.suiyun && Array.isArray(l.suiyun.signals) && l.suiyun.signals.length);
|
|
9971
|
+
const syPlain = sy
|
|
9972
|
+
? `再往后看,${sy.year} 年${sy.ganzhi}是${sy.suiyun.signals.map((x) => x.type).join('、')}——传统上把它当作「变化感强一点」的提示,既不是好消息也不是坏消息,遇上时多留个心眼就好。`
|
|
9973
|
+
: '';
|
|
8209
9974
|
return `你的命局属于「${s(st.level, '中性')}」:${strength}。` +
|
|
8210
9975
|
`${favor ? `能补${favor}的环境(行业、方位、作息、相处的人)会让你省力;${avoid ? `而${avoid}偏重的场合容易空耗,能绕就绕。` : ''}` : ''}` +
|
|
8211
|
-
tiaohou;
|
|
9976
|
+
tiaohou + syPlain;
|
|
8212
9977
|
}
|
|
8213
9978
|
if (r.system === 'ziwei') {
|
|
8214
9979
|
const soul = r.soul || {};
|
|
8215
9980
|
const body = r.body || {};
|
|
8216
|
-
|
|
8217
|
-
|
|
9981
|
+
const ji = r.flyChains && r.flyChains.忌;
|
|
9982
|
+
const plainFly = ji && ji.steps.length
|
|
9983
|
+
? `另外有一条线值得留意:${ji.path.map((p) => p.replace(/宫$/, '')).join(' → ')}——这几件事在你身上是连着转的,一件事卡住,容易牵动下一件。`
|
|
9984
|
+
: '';
|
|
9985
|
+
return [
|
|
9986
|
+
`紫微看的是「你与环境怎么互动」。命宫落${s(soul.branch, '—')}宫,说明你做事的第一反应是从这个宫位的气质出发` +
|
|
9987
|
+
`${body.lands ? `;身宫在「${body.lands}」,意味着真正让你上心的,是${body.lands}这件事` : ''}。`,
|
|
9988
|
+
plainFly,
|
|
9989
|
+
flyCompositePlain(r.flyComposite),
|
|
9990
|
+
].filter(Boolean).join('');
|
|
8218
9991
|
}
|
|
8219
9992
|
if (r.system === 'liuyao') {
|
|
8220
9993
|
const ben = r.ben || {};
|
|
8221
9994
|
const moving = (r.cast && r.cast.movingPositions) || [];
|
|
9995
|
+
const labels = (r.body && Array.isArray(r.body.labels)) ? r.body.labels : [];
|
|
9996
|
+
const plainBody = bodyPlainOf(labels);
|
|
8222
9997
|
return `${s(ben.name, '这一卦')}讲的是一个「${moving.length ? '正在动、还会变' : '暂时不动、先看清'}」的局面——` +
|
|
8223
|
-
`${moving.length ? '有动爻,说明事情还有转圜空间,不是死局。' : '六爻安静,说明当下更该观察而不是硬推。'}
|
|
9998
|
+
`${moving.length ? '有动爻,说明事情还有转圜空间,不是死局。' : '六爻安静,说明当下更该观察而不是硬推。'}` +
|
|
9999
|
+
`${plainBody}${usePlainOf(r.useGod)}${useStrengthPlain(r.useGodStrength)}${jinTuiPlain(r)}${hexStrengthPlain(r.hexStrength)}`;
|
|
8224
10000
|
}
|
|
8225
10001
|
return '';
|
|
8226
10002
|
}
|
|
@@ -8361,10 +10137,10 @@ const KNOWLEDGE = [
|
|
|
8361
10137
|
id: 'bazi-suiyun',
|
|
8362
10138
|
system: 'bazi', dims: ['overall', 'career'],
|
|
8363
10139
|
gist: '大运管十年基调,流年管当年触发。',
|
|
8364
|
-
detail: '
|
|
10140
|
+
detail: '大运像换了条路,流年像这条路上某一段的天气。岁运并临(当值大运与流年干支相同)、运年反吟(大运与流年天克地冲)、流年伏吟(流年与原局某柱干支相同)与流年反吟(流年与原局某柱天克地冲),是传统上标记「变动较大」的年份,属于提示而非断语。本插件逐年标出四类信号:当值大运按该年立春到次年立春的区间取,交运落在年内时前后两步并列;只标干支重复与对冲,不折分数。',
|
|
8365
10141
|
source: '岁运并临、伏吟反吟见《三命通会》《渊海子平》',
|
|
8366
10142
|
status: 'variant',
|
|
8367
|
-
note: '
|
|
10143
|
+
note: '「岁运并临主大凶」是流传最广也最被滥用的说法,本插件只作变动提示,不断吉凶;大运与原局之间的伏吟反吟未逐年标注,四柱十神层面的引化也未叠入。',
|
|
8368
10144
|
},
|
|
8369
10145
|
{
|
|
8370
10146
|
id: 'bazi-liuqin',
|
|
@@ -8393,6 +10169,34 @@ const KNOWLEDGE = [
|
|
|
8393
10169
|
status: 'settled',
|
|
8394
10170
|
},
|
|
8395
10171
|
|
|
10172
|
+
{
|
|
10173
|
+
id: 'bazi-sanming-duizhao',
|
|
10174
|
+
system: 'bazi', dims: ['overall', 'career'],
|
|
10175
|
+
gist: '同一个格,子平真诠讲怎么用,三命通会讲怎么取。',
|
|
10176
|
+
detail: '两书不是谁替代谁:子平真诠以月令取用神、论顺逆成败,重「用」;三命通会按十神逐格立论,重「取」与「忌」。同看正官格,前者问财印护官、伤煞混杂,后者先说「止许一位,多则不宜」。本插件把两条并列,不合并成一句断语。',
|
|
10177
|
+
source: '《子平真诠》论正官等篇;《三命通会》卷五、卷六论十神',
|
|
10178
|
+
status: 'variant',
|
|
10179
|
+
note: '两书成书年代与流派不同,用语有出入;本插件照录通行本,不做校勘改字,也不替两家调和。',
|
|
10180
|
+
},
|
|
10181
|
+
{
|
|
10182
|
+
id: 'bazi-geju-chengbai',
|
|
10183
|
+
system: 'bazi', dims: ['overall', 'career'],
|
|
10184
|
+
gist: '格有成有败:成中带忌会打折,败中有救还能转成。',
|
|
10185
|
+
detail: '月令取到格只是起点。成格要看有没有带忌——官逢财又逢伤、官透而被合、财旺生官又逢伤,都会把成格打折;败格也看有没有救应——印来解伤、合来清煞、劫来解财,败中可转。所以判格不能只报一个格名。',
|
|
10186
|
+
source: '《子平真诠》九、论用神成败救应',
|
|
10187
|
+
status: 'variant',
|
|
10188
|
+
note: '各家对成格条件与带忌轻重的排序不同(有先看刑冲、有先看合化),本插件只把原文与成败方向并列摆出,不逐盘判成破。',
|
|
10189
|
+
},
|
|
10190
|
+
{
|
|
10191
|
+
id: 'bazi-huagi-bianhua',
|
|
10192
|
+
system: 'bazi', dims: ['overall', 'career'],
|
|
10193
|
+
gist: '月令用神会因合化而变:同一个起点,取用可以不同。',
|
|
10194
|
+
detail: '用神本从月令取,但月令藏干不一,透出的字不同、支会合局不同,取用就跟着变:丁生亥月本为正官,支全卯未化为印;己生申月本属伤官,藏庚透壬化为财。所以看到化气格,要回头核对月令与合局,不能只按本气定格。',
|
|
10195
|
+
source: '《子平真诠》十、论用神变化;化气条件各家另论',
|
|
10196
|
+
status: 'variant',
|
|
10197
|
+
note: '化气格成立条件各家宽严不一(是否要求月令为化神、日主是否允许有根),本插件只列条件、附原文,不据此断定化气已成。',
|
|
10198
|
+
},
|
|
10199
|
+
|
|
8396
10200
|
{
|
|
8397
10201
|
id: 'ziwei-sanfang',
|
|
8398
10202
|
system: 'ziwei', dims: ['overall', 'career'],
|
|
@@ -8445,13 +10249,40 @@ const KNOWLEDGE = [
|
|
|
8445
10249
|
status: 'variant',
|
|
8446
10250
|
note: '空劫是否见禄反吉,各家说法不一,本插件只提示变动性质,不判吉凶。',
|
|
8447
10251
|
},
|
|
10252
|
+
{
|
|
10253
|
+
id: 'ziwei-feixing',
|
|
10254
|
+
system: 'ziwei', dims: ['overall', 'career'],
|
|
10255
|
+
gist: '宫干定四化,星落哪宫,这一宫的力就往哪边走。',
|
|
10256
|
+
detail: '生年四化是先天带的,飞星四化是宫位自己去找的:每一宫的宫干定出禄权科忌四颗星,那几颗星落在哪一宫,就是这一宫的力气往哪边使。所以同一个「化忌」,从命宫飞出去和从财帛飞出去,说的是两件事。',
|
|
10257
|
+
source: '《紫微斗数全书》四化篇;中州派宫干四化传法',
|
|
10258
|
+
status: 'variant',
|
|
10259
|
+
note: '飞星派(如钦天四化)把宫干四化当主线,三合派只作辅助;庚干四化各派另有异说,本插件取中州派常用表。飞星串连与三方四正复合飞化现已给出,但未叠大限流年四化。',
|
|
10260
|
+
},
|
|
10261
|
+
{
|
|
10262
|
+
id: 'ziwei-sanfang-fei',
|
|
10263
|
+
system: 'ziwei', dims: ['overall', 'career'],
|
|
10264
|
+
gist: '三方四正一起飞,看四股力会到哪一宫。',
|
|
10265
|
+
detail: '单宫飞化只看本宫宫干把四化送去哪里;三方四正复合飞化把本宫、对宫与两个三合宫共四宫的宫干四化同时摊开,约 16 条,按落宫归堆,落到同一宫的就是会照。会在一处的化越多,那一宫被牵动的力道越集中;两忌以上会宫、禄忌同宫、三化以上会宫、宫干化出又落回本宫(自化),是这一层最常取的几种情形。',
|
|
10266
|
+
source: '《紫微斗数全书》四化篇;飞星派三方四正同飞说',
|
|
10267
|
+
status: 'variant',
|
|
10268
|
+
note: '飞星派对「三方四正一起飞」是否成立、会照要不要折成分数,各家口径不一;本插件只做落宫归堆与会照标记,不折分数,也未叠大限流年四化。',
|
|
10269
|
+
},
|
|
10270
|
+
{
|
|
10271
|
+
id: 'ziwei-jichuanji',
|
|
10272
|
+
system: 'ziwei', dims: ['overall'],
|
|
10273
|
+
gist: '忌转忌:化忌落进哪一宫,就从那一宫再化出去。',
|
|
10274
|
+
detail: '串连是跟着同一支化逐宫走:命宫化忌入父母,父母宫的宫干再化忌往下一宫,直到绕回走过的宫成环。环越短,越容易在同一组宫位上反复;走不出去(传统说「忌出不去」)不等于凶,只是这条力没有别的出口。',
|
|
10275
|
+
source: '《紫微斗数全书》四化篇;忌转忌串连法',
|
|
10276
|
+
status: 'variant',
|
|
10277
|
+
note: '串连几跳为止、是否允许借对宫飞化,各派不一;本插件只跟单一支化逐宫走,走满 12 宫或成环即停。',
|
|
10278
|
+
},
|
|
8448
10279
|
|
|
8449
10280
|
{
|
|
8450
10281
|
id: 'liuyao-yongshen',
|
|
8451
|
-
system: 'liuyao', dims: ['overall'],
|
|
8452
|
-
gist: '
|
|
8453
|
-
detail: '
|
|
8454
|
-
source: '
|
|
10282
|
+
system: 'liuyao', dims: ['overall', 'work', 'wealth', 'love', 'health', 'study'],
|
|
10283
|
+
gist: '问什么就以哪一类六亲为用神,这一步定错,后面全盘白算。',
|
|
10284
|
+
detail: '取用按所问之事:求财与男命妻缘看妻财,工作职位考核看官鬼,文书合同学历看父母,健康以官鬼为病、子孙为医药,出行以世爻为用,感情男看妻财、女看官鬼。用神在卦上就取那一爻,出现两处记「两现」;用神不上卦,按本宫首卦同六亲的爻位取伏神,再看飞伏生克。本插件把这些位置与动变、旬空、卦体标签一一对上,但不替你选两现之中的主用。',
|
|
10285
|
+
source: '《卜筮正宗》用神章、伏神章;《增删卜易》用神章',
|
|
8455
10286
|
status: 'settled',
|
|
8456
10287
|
},
|
|
8457
10288
|
{
|
|
@@ -8473,10 +10304,29 @@ const KNOWLEDGE = [
|
|
|
8473
10304
|
{
|
|
8474
10305
|
id: 'liuyao-fushen',
|
|
8475
10306
|
system: 'liuyao', dims: ['overall'],
|
|
8476
|
-
gist: '
|
|
8477
|
-
detail: '
|
|
8478
|
-
source: '
|
|
8479
|
-
status: '
|
|
10307
|
+
gist: '用神不上卦,就去本宫首卦的同位取伏神。',
|
|
10308
|
+
detail: '本卦六爻里没有用神那一类六亲,就叫用神不上卦。取法是回到本卦所属宫的首卦(八纯卦),找出该六亲所在的爻位,那一爻即伏神,本卦同一爻位上的爻叫飞神。伏神要「得出」才有用:飞神生伏神、伏神克飞神、日月生扶都算得力;飞神克伏神则受压难出。本插件给出伏神爻位、干支五行与飞伏生克关系,不出具体的出伏日期。',
|
|
10309
|
+
source: '《卜筮正宗》伏神章;《增删卜易》伏神篇',
|
|
10310
|
+
status: 'variant',
|
|
10311
|
+
note: '首卦里同一六亲也可能出现两次(如乾宫乾为天的父母在三爻与上爻),此时取哪一爻为伏神各家不一;本插件把候选都列出并标「伏神两现」,不代选。伏神出伏的应期各家分歧更大,故不输出日期。',
|
|
10312
|
+
},
|
|
10313
|
+
{
|
|
10314
|
+
id: 'liuyao-yongshen-shuai',
|
|
10315
|
+
system: 'liuyao', dims: ['overall', 'work'],
|
|
10316
|
+
gist: '用神旺不旺,看月建给的气与日辰当天的扶克。',
|
|
10317
|
+
detail: '月建管「这一段时令」:爻五行与月支五行同气为旺、受月令生为相、生月令为休、克月令为囚、被月令克为死。日辰管「当天这一股力」:日辰生爻为生、克爻为克、同气为比和,反过来则是爻泄日、爻耗日。此外月建冲爻叫月破,日辰冲静爻叫暗动、冲旬空之爻叫冲空。本插件把这几项折成标签逐爻列出,不折成分数。',
|
|
10318
|
+
source: '《增删卜易》月建章、日辰章;《卜筮正宗》月建论',
|
|
10319
|
+
status: 'variant',
|
|
10320
|
+
note: '月破、暗动、冲空三者各家取法不完全一致(有派别把日冲动爻也叫暗动,有派别只认旺相之爻暗动);本插件按「月建冲=月破、日冲静爻=暗动、日冲旬空=冲空」这一套给标签,并注明用了哪一支月建。',
|
|
10321
|
+
},
|
|
10322
|
+
{
|
|
10323
|
+
id: 'liuyao-quanggu-shuai',
|
|
10324
|
+
system: 'liuyao', dims: ['overall', 'work'],
|
|
10325
|
+
gist: '全卦逐爻看月建,才看得出气聚在哪一头。',
|
|
10326
|
+
detail: '月建管这一段时令的旺衰、日辰管当天的扶克,落到全部六爻逐爻判定:每爻都出月令五态(旺相休囚死)与日辰五关系,并标月破、暗动、冲空。世爻、应爻、动爻与旬空另标,五态分布能看出气是聚在世应还是散在旁爻——用神只是其中一处落点,不看全卦容易把一处当全局。',
|
|
10327
|
+
source: '《增删卜易》月建章、日辰章;《卜筮正宗》六爻旺衰论',
|
|
10328
|
+
status: 'variant',
|
|
10329
|
+
note: '各家对月破、暗动、冲空的取法不完全一致,是否给六爻折力重(分数)分歧更大;本插件只给状态标签与五态分布,不折分数。',
|
|
8480
10330
|
},
|
|
8481
10331
|
{
|
|
8482
10332
|
id: 'liuyao-yingqi',
|
|
@@ -8496,6 +10346,59 @@ const KNOWLEDGE = [
|
|
|
8496
10346
|
status: 'settled',
|
|
8497
10347
|
},
|
|
8498
10348
|
|
|
10349
|
+
{
|
|
10350
|
+
id: 'liuyao-liuchong',
|
|
10351
|
+
system: 'liuyao', dims: ['overall'],
|
|
10352
|
+
gist: '六冲卦讲「散」:起落快、来去急。',
|
|
10353
|
+
detail: '六冲不按「爻位相邻」判,而是看六个地支能不能正好配成子午、寅申、辰戌三组对冲。按纳甲实排,八纯卦之外天雷无妄、雷天大壮也成六冲。冲不是单纯的坏:近病逢冲主速愈、久病逢冲才忌;求财问婚,冲多主聚不住。',
|
|
10354
|
+
source: '《卜筮正宗》六冲章;《增删卜易》卦体说',
|
|
10355
|
+
status: 'variant',
|
|
10356
|
+
note: '通行口诀多把六冲限为八纯卦,本插件按纳甲地支实配判定,故多出无妄与大壮两支;《增删卜易》卦例里这两卦确被称作六冲,可互证。',
|
|
10357
|
+
},
|
|
10358
|
+
{
|
|
10359
|
+
id: 'liuyao-liuhe',
|
|
10360
|
+
system: 'liuyao', dims: ['overall', 'love'],
|
|
10361
|
+
gist: '六合卦讲「成」:容易谈拢,也容易黏住。',
|
|
10362
|
+
detail: '六个地支正好配成子丑、寅亥、卯戌、辰酉、巳申、午未三组相合,即六合卦,共天地否、地天泰、地雷复、雷地豫、山火贲、水泽节、泽水困、火山旅八支。六合主和合、拖延:谈事情容易成,也容易久拖不决;问病则忌缠绵。',
|
|
10363
|
+
source: '《卜筮正宗》六合章',
|
|
10364
|
+
status: 'settled',
|
|
10365
|
+
},
|
|
10366
|
+
{
|
|
10367
|
+
id: 'liuyao-fanyin',
|
|
10368
|
+
system: 'liuyao', dims: ['overall', 'work'],
|
|
10369
|
+
gist: '反吟主反复:去了又来、定了又改。',
|
|
10370
|
+
detail: '卦反吟有两种成法:一是变卦某宫的三爻地支与本卦对应宫正好全冲;二是本卦之宫与变卦之宫在后天八卦上正对(乾巽、坎离、艮坤、震兑)。爻反吟则是动爻变出的地支回头冲本爻。无论哪种,取象都是反复、翻覆、旧事重提。',
|
|
10371
|
+
source: '《增删卜易》反吟伏吟篇;《卜筮正宗》',
|
|
10372
|
+
status: 'variant',
|
|
10373
|
+
note: '各家对「卦反吟」是否只认地支全冲有分歧;本插件的八卦正对一路,是从《增删卜易》卦例(如山地剥之坤为地、风天小畜之乾为天)反推出来的。',
|
|
10374
|
+
},
|
|
10375
|
+
{
|
|
10376
|
+
id: 'liuyao-fuyin',
|
|
10377
|
+
system: 'liuyao', dims: ['overall'],
|
|
10378
|
+
gist: '伏吟主呻吟:事情在原地打转。',
|
|
10379
|
+
detail: '卦变了,纳甲地支却没变,叫卦伏吟。纳甲上只有乾与震共用子寅辰、午申戌一套地支,所以卦伏吟只会出在乾与震互换的卦上,例如天雷无妄之雷天大壮、天风姤之雷风恒。动爻变出的地支与本爻同支,则是爻伏吟。伏吟取象是欲动不动、原地反复,常指人想动而形势不许。',
|
|
10380
|
+
source: '《增删卜易》伏吟篇;《卜筮正宗》',
|
|
10381
|
+
status: 'variant',
|
|
10382
|
+
note: '另有「伏吟以用神受困论」的说法,不限于卦体;本插件只报卦体层面的伏吟与动爻伏吟,不推断吉凶轻重。',
|
|
10383
|
+
},
|
|
10384
|
+
{
|
|
10385
|
+
id: 'liuyao-jintui',
|
|
10386
|
+
system: 'liuyao', dims: ['overall'],
|
|
10387
|
+
gist: '动爻变出同五行顺次之支,为化进神;反向为化退神。',
|
|
10388
|
+
detail: '动爻变出的地支与本爻同五行、且在顺次上往前一步,叫化进神;倒退一步叫化退神。八对是:寅→卯(木)、巳→午(火)、申→酉(金)、亥→子(水),土一支成环,丑→辰→未→戌→丑。同五行但不相邻(如寅→辰)不算。进神取象是这一爻代表的人或事有后劲、势在往前;退神取象是渐渐退气、按原势头推会落空。',
|
|
10389
|
+
source: '《增删卜易》进神退神章',
|
|
10390
|
+
status: 'settled',
|
|
10391
|
+
},
|
|
10392
|
+
{
|
|
10393
|
+
id: 'liuyao-jintui-yong',
|
|
10394
|
+
system: 'liuyao', dims: ['overall', 'work'],
|
|
10395
|
+
gist: '化进化退要看是用神还是忌神,还要叠月建日辰。',
|
|
10396
|
+
detail: '进神退神本身只说明这一爻的向外趋势:用神化进为得力,忌神化进则为患加剧;用神化退是力衰,忌神化退反而是解脱。传统还要看它在本月令衰旺、有没有日辰生扶,空亡或受克时进者未必能进。本插件把进退与爻位标出来,再按月建五态给一档力重——得令则进得动、退得慢,失令则进得虚、退得实,月破压过一切;只给档位,不折成加权分数,吉凶仍落在用神与忌神那一层判。',
|
|
10397
|
+
source: '《增删卜易》进神退神章、用神章',
|
|
10398
|
+
status: 'variant',
|
|
10399
|
+
note: '土之进退次序各家说法不完全一致,有以丑→辰→未→戌为进、也有只取辰戌丑未相对者;本插件按丑辰未戌成环处理,并用《增删卜易》卦例中「未土化戌土为进」「戌土化未土为退」对拍。',
|
|
10400
|
+
},
|
|
10401
|
+
|
|
8499
10402
|
{
|
|
8500
10403
|
id: 'meihua-tiyong',
|
|
8501
10404
|
system: 'meihua', dims: ['overall'],
|
|
@@ -8521,6 +10424,50 @@ const KNOWLEDGE = [
|
|
|
8521
10424
|
status: 'variant',
|
|
8522
10425
|
note: '三种取局法在节气交接前后差异最明显,本插件同时实现三种,可在参数里指定。',
|
|
8523
10426
|
},
|
|
10427
|
+
{
|
|
10428
|
+
id: 'qimen-jixing',
|
|
10429
|
+
system: 'qimen', dims: ['overall', 'work'],
|
|
10430
|
+
gist: '六仪落刑宫叫击刑,是宫位条件不是判决。',
|
|
10431
|
+
detail: '六仪按所配地支相刑:甲子戊落震三(子刑卯)、甲戌己落坤二(戌刑未)、甲申庚落艮八(申刑寅)、甲午辛落离九(午自刑)、甲辰壬落巽四(辰自刑)、甲寅癸落巽四(寅刑巳)。天盘六仪落到自己那一宫即击刑,取象是受制、掣肘、旧账翻出来,多用来量这个符号本身使不使得上力。',
|
|
10432
|
+
source: '《烟波钓叟歌》刑格注;《奇门遁甲统宗》',
|
|
10433
|
+
status: 'variant',
|
|
10434
|
+
note: '有流派只论天盘六仪击刑,也有把地盘一并算的;本插件只判天盘,且只作宫位条件,不自动断用神受制。',
|
|
10435
|
+
},
|
|
10436
|
+
{
|
|
10437
|
+
id: 'qimen-rumu',
|
|
10438
|
+
system: 'qimen', dims: ['overall'],
|
|
10439
|
+
gist: '三奇落墓宫叫入墓:力量收进去,不容易使出来。',
|
|
10440
|
+
detail: '按五行墓库推:乙木墓在未(未属坤二宫),丙丁火墓在戌(戌属乾六宫)。天盘乙奇落坤二、丙奇或丁奇落乾六,即三奇入墓。取象是收束、藏起来、事情压住不动;好坏要看所问之事——问收藏、问了结,入墓未必是坏事。',
|
|
10441
|
+
source: '《奇门遁甲统宗》三奇入墓条;五行墓库见《五行大义》',
|
|
10442
|
+
status: 'variant',
|
|
10443
|
+
note: '各家对入墓范围说法不一:有只论三奇,也有把六仪、八门、九星一并论墓的;本插件只判天盘三奇,其余留白。',
|
|
10444
|
+
},
|
|
10445
|
+
{
|
|
10446
|
+
id: 'qimen-wangshuai',
|
|
10447
|
+
system: 'qimen', dims: ['overall', 'work'],
|
|
10448
|
+
gist: '门、星与天盘干按月令分旺相休囚死,只说明力量强弱。',
|
|
10449
|
+
detail: '旺相休囚死以月支五行为尺:与月令同气为旺,月令所生为相,生月令为休,克月令为囚,被月令所克为死。八门、九星与天盘干(三奇六仪)各按自身五行对月令,得出该符号当下「使不使得上力」。比如午月火旺,景门(火)旺、生门死门(土)相、休门(水)囚、开门惊门(金)死,天盘丙丁(火)旺、庚辛(金)死。',
|
|
10450
|
+
source: '《奇门遁甲统宗》门星旺衰条;五行旺相休囚死见《五行大义》',
|
|
10451
|
+
status: 'settled',
|
|
10452
|
+
},
|
|
10453
|
+
{
|
|
10454
|
+
id: 'qimen-wangshuai-yong',
|
|
10455
|
+
system: 'qimen', dims: ['overall', 'work'],
|
|
10456
|
+
gist: '旺衰是助力,不单独定吉凶:门旺而宫克门仍受制。',
|
|
10457
|
+
detail: '月令旺衰只回答「这个符号自身有多少气」,不回答「事情成不成」。取象时要和宫位关系叠起来看:门旺但同宫门克宫(门迫),力量被宫位掣肘;门囚但宫生门,仍得宫助。星同理,旺星落宫若被克,也难全其用。',
|
|
10458
|
+
source: '《奇门遁甲统宗》;《烟波钓叟歌》门宫生克注',
|
|
10459
|
+
status: 'variant',
|
|
10460
|
+
note: '有流派按时令而非月令论门星旺衰,也有以落宫五行当令者;本插件统一按月支五行判,并在解读里明确只作强度参考。',
|
|
10461
|
+
},
|
|
10462
|
+
{
|
|
10463
|
+
id: 'qimen-gan-shengke',
|
|
10464
|
+
system: 'qimen', dims: ['overall', 'work'],
|
|
10465
|
+
gist: '天盘干落宫论生克:干克宫主进取,宫克干受制,比和相安。',
|
|
10466
|
+
detail: '天盘干(三奇六仪)落到某宫,就看干的五行与该宫五行的生克:干克宫,是符号压向环境、偏进取与主动;宫克干,是环境反过来管住符号、偏受制与掣肘;干生宫,力量往外泄;宫生干,环境给力;比和,两下相安。这一层与门宫关系(门迫、宫制门)并列,各说各的,不互相替换;两者同时成立时分别列出,不折成一个分数。',
|
|
10467
|
+
source: '《奇门遁甲统宗》干宫生克条;《烟波钓叟歌》门宫生克注',
|
|
10468
|
+
status: 'variant',
|
|
10469
|
+
note: '各家对「干与宫」的取象宽窄不一:有只论干宫、有连天盘干加地盘干(十干克应)一并论的。本插件只判天盘干与所落宫,十干克应 100 组未做。',
|
|
10470
|
+
},
|
|
8524
10471
|
{
|
|
8525
10472
|
id: 'tarot-orientation',
|
|
8526
10473
|
system: 'tarot', dims: ['overall'],
|
|
@@ -8530,24 +10477,24 @@ const KNOWLEDGE = [
|
|
|
8530
10477
|
status: 'variant',
|
|
8531
10478
|
note: '逆位是否参与解读本身就有分歧(有牌阵传统完全不用逆位)。本插件按削弱加内向综合取象,并在开头声明。',
|
|
8532
10479
|
},
|
|
10480
|
+
{
|
|
10481
|
+
id: 'bazi-dayun-jiaoqi',
|
|
10482
|
+
system: 'bazi', dims: [],
|
|
10483
|
+
gist: '交运按「三日折一年」放大到日、时:起运时刻与每步换运日期都给。',
|
|
10484
|
+
detail: '把「出生 → 起运那一侧节令」的真实间隔按 365.2422/3(约 121.7474 倍)放大,加到出生时刻上就是交运时刻;同一比例也兑现「一日折四月、一时辰折十日」。每步大运在同月同日同时刻换,闰日退到 2 月 28 日。年长取回归年 365.2422 日,故与按 360 日折算的流派会差一两天。',
|
|
10485
|
+
source: '《渊海子平》起运法(三日折一年);《三命通会》论行运',
|
|
10486
|
+
status: 'variant',
|
|
10487
|
+
note: '各家对「一年折几日」「交运日是否按 360 日计」取法不一,本插件固定 365.2422 日并把口径写进结果(dayun.jiao.yearDays)。出生时刻或经度一变,交运日会前后移一两天;月柱在交节边界时尤其要复核。',
|
|
10488
|
+
},
|
|
8533
10489
|
{
|
|
8534
10490
|
id: 'liuyao-yingqi-exact',
|
|
8535
10491
|
system: 'liuyao', dims: [],
|
|
8536
10492
|
gist: '具体应期(哪一天应验)本插件尚未推算。',
|
|
8537
10493
|
detail: '应期需要综合用神旺衰、动变、旬空出空、日月冲合多层条件,且各家取法不同。当前只给时间窗口的方向性提示,不给具体日期——与其给一个看起来精确、实则拍脑袋的日子,不如留白。',
|
|
8538
|
-
source: '待补:《卜筮正宗》应期章逐条实现 + 138
|
|
10494
|
+
source: '待补:《卜筮正宗》应期章逐条实现 + 已录 128 条卦例对拍(源 138 条)',
|
|
8539
10495
|
status: 'todo',
|
|
8540
10496
|
note: '扩展方向:用《卜筮正宗》卦例里有明确应验日期的条目做回归,先验证再输出。',
|
|
8541
10497
|
},
|
|
8542
|
-
{
|
|
8543
|
-
id: 'bazi-dayun-jiaoqi',
|
|
8544
|
-
system: 'bazi', dims: [],
|
|
8545
|
-
gist: '起运时间按「三日折一年」折算,未做交运日的时辰级校正。',
|
|
8546
|
-
detail: '传统折算为三天折一年、一天折四月、一时辰折十天。本插件按此折算到年月,不含交运当日的时辰细分,因此起运年份在边界处可能相差一年内。',
|
|
8547
|
-
source: '《渊海子平》起运法;交运日细算各家不一',
|
|
8548
|
-
status: 'todo',
|
|
8549
|
-
note: '扩展方向:补交运日的时辰级推算,并用已知案例核对。',
|
|
8550
|
-
},
|
|
8551
10498
|
];
|
|
8552
10499
|
|
|
8553
10500
|
function knowledgeFor(system, dimKey) {
|
|
@@ -8571,6 +10518,7 @@ __mods.interpret = (function () {
|
|
|
8571
10518
|
|
|
8572
10519
|
const { HEX64, HEX_BY_CORE, TRIGRAM, YAO_POSITION, MOVING_NATURE, ZIWEI_STARS, WUXING_INDUSTRY, WUXING_ORGAN, TENGOD_STYLE, LIUREN_JIANG, TAROT_ELEMENT_FOCUS, DISCLAIMER } = __mods['interpret-data'];
|
|
8573
10520
|
const { MUTAGEN } = __mods.ziwei;
|
|
10521
|
+
const { bodyLabels, yongshenOf } = __mods.liuyao;
|
|
8574
10522
|
|
|
8575
10523
|
const DIMENSIONS = [
|
|
8576
10524
|
{ key: 'overall', label: '整体运势' },
|
|
@@ -8864,9 +10812,25 @@ function baziInterpret(r) {
|
|
|
8864
10812
|
const why = (lk.reasons || []).slice(0, 2).join(',');
|
|
8865
10813
|
return `${l.year} ${l.ganzhi}·${l.stemTenGod || ''}·${lk.tier || '平'}${why ? `(${why})` : ''}`;
|
|
8866
10814
|
}).join(';');
|
|
8867
|
-
|
|
10815
|
+
const jiaoLine = r.dayun && r.dayun.jiao && r.dayun.jiao.at
|
|
10816
|
+
? `起运交运时刻 ${r.dayun.jiao.at}(${r.dayun.jiao.frame};三日折一年,距${r.dayun.jiao.from.name} ${r.dayun.jiao.spanDays} 天)。每步大运在同月同日同时刻换,逐年日期见下方大运表「交运」列。\n`
|
|
10817
|
+
: '';
|
|
10818
|
+
return `${jiaoLine}当前大运:${pick(cur, 'ganzhi', '—')}(${curSpan})。后续两步:${nextTwo}。\n近五年流年:${years || '—'}。\n读法:大运管"这十年的大环境",流年管"今年的具体天气";两者打架时,以能否动到用神为准。`;
|
|
8868
10819
|
})(),
|
|
8869
10820
|
},
|
|
10821
|
+
(() => {
|
|
10822
|
+
const hits = (r.liunian || []).filter((l) => l.suiyun && Array.isArray(l.suiyun.signals) && l.suiyun.signals.length);
|
|
10823
|
+
return {
|
|
10824
|
+
key: 'suiyun', label: '岁运提示',
|
|
10825
|
+
text: hits.length
|
|
10826
|
+
? hits.map((l) => {
|
|
10827
|
+
const stem = (l.suiyun.dayun || []).map((d) => `第${d.step}步${d.ganzhi}`).join('、');
|
|
10828
|
+
return `${l.year} ${l.ganzhi}(${stem || '未到起运'}):${l.suiyun.signals.map((s) => s.detail).join(';')}`;
|
|
10829
|
+
}).join('\n') +
|
|
10830
|
+
'\n读法:岁运并临、运年反吟与流年伏吟/反吟只说明干支层面重复或对冲,传统上当作「变动感较强」的信号;本插件不据此判吉凶,要落到具体年份,仍看该年是否动到用神。'
|
|
10831
|
+
: '近十年没有岁运并临、运年反吟或流年伏吟/反吟。「岁运并临主大凶」这类说法流传很广,本插件只把它当变动提示,没有命中就不作额外解读。',
|
|
10832
|
+
};
|
|
10833
|
+
})(),
|
|
8870
10834
|
{
|
|
8871
10835
|
key: 'checks', label: '交叉校验',
|
|
8872
10836
|
text: (() => {
|
|
@@ -8912,6 +10876,10 @@ function baziInterpret(r) {
|
|
|
8912
10876
|
key: 'geju', label: '格局依据',
|
|
8913
10877
|
text: (Array.isArray(frame.geju) ? frame.geju : []).map((g) => `${g.name}(${g.kind}):${g.evidence}`).join(';') || '未取到格局',
|
|
8914
10878
|
},
|
|
10879
|
+
...(Array.isArray(r.classics) && r.classics.length ? [{
|
|
10880
|
+
key: 'classics', label: '古籍原文',
|
|
10881
|
+
text: r.classics.map((e) => `《${CLASSIC_BOOKS[e.book].name}·${e.chapter}》「${e.quote}」——${e.plain}`).join('\n'),
|
|
10882
|
+
}] : []),
|
|
8915
10883
|
{
|
|
8916
10884
|
key: 'quant', label: '量化口径',
|
|
8917
10885
|
text: `本报告的量化只到「档位」:事业看十神权重(${topName} ${top[0]?.[1] ?? '—'})、财富看财星权重(${groups['财'] ?? 0})、感情看配偶星权重(${spouseKey} ${groups[spouseKey] ?? 0});大运/流年用「大吉 / 吉 / 平 / 忌」四档。不换算金额、不给健康诊断——那需要地域、家庭、行业与体检数据,命盘本身推不出来。`,
|
|
@@ -8931,8 +10899,8 @@ function baziInterpret(r) {
|
|
|
8931
10899
|
];
|
|
8932
10900
|
const tables = [
|
|
8933
10901
|
{
|
|
8934
|
-
key: 'dayun', title: '大运表', columns: ['大运', '年龄', '十神', '档位', '理由'],
|
|
8935
|
-
rows: list.map((d) => [d.ganzhi, `${d.startAge}–${d.startAge + 9}`, d.stemTenGod || '', d.luck?.tier || '平', (d.luck?.reasons || []).join(',')]),
|
|
10902
|
+
key: 'dayun', title: '大运表', columns: ['大运', '年龄', '交运', '十神', '档位', '理由'],
|
|
10903
|
+
rows: list.map((d) => [d.ganzhi, `${d.startAge}–${d.startAge + 9}`, d.fromDate || '—', d.stemTenGod || '', d.luck?.tier || '平', (d.luck?.reasons || []).join(',')]),
|
|
8936
10904
|
},
|
|
8937
10905
|
{
|
|
8938
10906
|
key: 'liunian', title: '流年表(近十年)', columns: ['年份', '干支', '十神', '档位', '与原局'],
|
|
@@ -9143,7 +11111,7 @@ function ziweiInterpret(r) {
|
|
|
9143
11111
|
},
|
|
9144
11112
|
{
|
|
9145
11113
|
key: 'limits', label: '未纳入',
|
|
9146
|
-
text: '
|
|
11114
|
+
text: '本盘没有计算:小限与大限的加权、流日流时的具体事项定位、双星组合的强弱细分,以及「三方四正一起飞」的复合飞化(这里只跟单一支化逐宫串连)。四化表取中州派常用口径,其他流派(如飞星派)结论会不同;这些不改变盘面事实,只影响轻重,所以只作方向参考。',
|
|
9147
11115
|
},
|
|
9148
11116
|
];
|
|
9149
11117
|
if (natalSihua.length) {
|
|
@@ -9160,6 +11128,70 @@ function ziweiInterpret(r) {
|
|
|
9160
11128
|
});
|
|
9161
11129
|
}
|
|
9162
11130
|
|
|
11131
|
+
{
|
|
11132
|
+
const fc = r.flyChains;
|
|
11133
|
+
const word = (p) => `${p}${String(p).endsWith('宫') ? '' : '宫'}`;
|
|
11134
|
+
if (fc) {
|
|
11135
|
+
const chainOf = (t) => {
|
|
11136
|
+
const ch = fc[t];
|
|
11137
|
+
if (!ch || !ch.steps.length) return `${t}:命宫这一干不化${t}星`;
|
|
11138
|
+
const hops = ch.steps
|
|
11139
|
+
.map((s) => `${word(s.from)}(${s.fromStem})化${t}${s.star}→${word(s.to)}(${s.toBranch})`)
|
|
11140
|
+
.join(';');
|
|
11141
|
+
return `${t}:${hops}${ch.closed ? `,绕回${word(ch.path[ch.path.length - 1])}成环` : ''}`;
|
|
11142
|
+
};
|
|
11143
|
+
const selfs = (r.fly || []).flatMap((p) => (p.flies || [])
|
|
11144
|
+
.filter((f) => f.self)
|
|
11145
|
+
.map((f) => `${word(p.palace)}(${p.stem})化${f.type}${f.star}落回本宫`));
|
|
11146
|
+
const ji = fc.忌;
|
|
11147
|
+
const jiRead = ji && ji.steps.length
|
|
11148
|
+
? `忌这一条最值得盯:${word(ji.from)}化忌入${word(ji.steps[0].to)},${word(ji.steps[0].to)}的宫干再化忌往下一宫去,${ji.closed ? `最后绕回${word(ji.path[ji.path.length - 1])}` : '走到没有可落的星就停下'}——` +
|
|
11149
|
+
`这条线就是你反复着力的那一圈,` +
|
|
11150
|
+
`${ji.closed ? '环越短越容易在同一组宫位上打转(传统说「忌出不去」)' : '没成环表示这条力还有落点没走完'}。`
|
|
11151
|
+
: '命宫这一干化忌未上盘,忌线不成立。';
|
|
11152
|
+
sections.push({
|
|
11153
|
+
key: 'fly', label: '四化飞星',
|
|
11154
|
+
text: `生年四化说的是「一出场就带着什么」,飞星四化说的是「这一宫自己会去找谁」:宫干定出四颗化星,星落到哪一宫,这一宫的力就往哪边使。` +
|
|
11155
|
+
`从命宫出发,四条线各串一遍——${chainOf('禄')};${chainOf('权')};${chainOf('科')};${chainOf('忌')}。` +
|
|
11156
|
+
`${jiRead}` +
|
|
11157
|
+
`另外,四化落回本宫的是自化:${selfs.length ? selfs.join('、') + '——自己化出去又回到自己,常表现为「说得多、落得少」或一阵一阵的劲头' : '本盘没有自化'}。` +
|
|
11158
|
+
`这一层只描方向与牵引,不断吉凶:同样是化忌入某宫,落在生年忌上还是落在生年禄上,味道完全不同,得并着生年四化看。`,
|
|
11159
|
+
});
|
|
11160
|
+
}
|
|
11161
|
+
}
|
|
11162
|
+
|
|
11163
|
+
{
|
|
11164
|
+
const fc = r.flyComposite;
|
|
11165
|
+
const word = (p) => `${p}${String(p).endsWith('宫') ? '' : '宫'}`;
|
|
11166
|
+
if (fc && Array.isArray(fc.sources) && fc.sources.length >= 2) {
|
|
11167
|
+
const hubs = fc.targets.filter((t) => t.count >= 2);
|
|
11168
|
+
const hubText = hubs.length
|
|
11169
|
+
? hubs.slice(0, 5).map((t) => `${word(t.palace)}收了 ${t.incoming.map((x) => `${word(x.from)}化${x.type}${x.star}`).join('、')}`).join(';')
|
|
11170
|
+
: '四宫化出去之后没有落在同一宫,力是散开的';
|
|
11171
|
+
const readings = [];
|
|
11172
|
+
if (fc.groups.doubleJi.length) {
|
|
11173
|
+
readings.push(`${fc.groups.doubleJi.map((t) => word(t.palace)).join('、')}收到两个以上的忌——同一件事被反复牵动,传统看作那一宫的事务容易拖着不放`);
|
|
11174
|
+
}
|
|
11175
|
+
if (fc.groups.luJi.length) {
|
|
11176
|
+
readings.push(`${fc.groups.luJi.map((t) => word(t.palace)).join('、')}禄忌同宫:好处与在意的地方绑在一起,越想要的东西越容易反复`);
|
|
11177
|
+
}
|
|
11178
|
+
if (fc.groups.tripleHua.length) {
|
|
11179
|
+
readings.push(`${fc.groups.tripleHua.map((t) => word(t.palace)).join('、')}三化以上会宫:那一宫同时被几种力牵住,常常是这张盘最忙的地方`);
|
|
11180
|
+
}
|
|
11181
|
+
if (fc.groups.selfHua.length) {
|
|
11182
|
+
readings.push(`${fc.groups.selfHua.map((t) => word(t.palace)).join('、')}自化:宫干化出去又落回自己,表现为力气绕回原处`);
|
|
11183
|
+
}
|
|
11184
|
+
sections.push({
|
|
11185
|
+
key: 'flyComposite',
|
|
11186
|
+
label: '三方四正飞化',
|
|
11187
|
+
text: `上一节是命宫一条线往下追;这一节把命宫连同对宫与两个三合宫(${fc.sanfang.join('、')})一起飞:四宫各化禄权科忌,共 16 条飞化(星未上盘的只记星不记落宫),按落宫归堆。` +
|
|
11188
|
+
`${hubText}。` +
|
|
11189
|
+
`${readings.length ? `${readings.join(';')}。` : ''}` +
|
|
11190
|
+
`读法上,会在一处的化越多,那一宫被牵动的力道越集中;落单的飞化只说明方向,不单独取象。这一层同样只描会照与方向,不折吉凶,也没有叠大限与流年四化。`,
|
|
11191
|
+
});
|
|
11192
|
+
}
|
|
11193
|
+
}
|
|
11194
|
+
|
|
9163
11195
|
if (r.flow) {
|
|
9164
11196
|
const f = r.flow;
|
|
9165
11197
|
const at = (p) => `${p.ganzhi || '—'}${p.palace ? `落${p.palace}` : ''}`;
|
|
@@ -9261,7 +11293,7 @@ const LIUQIN_USE = {
|
|
|
9261
11293
|
兄弟: '同事、同行、竞争者,多与破财相关',
|
|
9262
11294
|
};
|
|
9263
11295
|
|
|
9264
|
-
function liuyaoInterpret(r) {
|
|
11296
|
+
function liuyaoInterpret(r, ask) {
|
|
9265
11297
|
const ben = isObj(r.ben) ? r.ben : {};
|
|
9266
11298
|
const bian = isObj(r.bian) ? r.bian : {};
|
|
9267
11299
|
const lines = Array.isArray(ben.lines) ? ben.lines : [];
|
|
@@ -9278,6 +11310,8 @@ function liuyaoInterpret(r) {
|
|
|
9278
11310
|
const movingLiuqin = moving?.liuqin || '';
|
|
9279
11311
|
const movingLiushen = moving?.liushen || '';
|
|
9280
11312
|
const dayGZ = pick(r.dayGanZhi, 'name', '');
|
|
11313
|
+
const bd = isObj(r.body) ? r.body : {};
|
|
11314
|
+
const bodyLabelList = (bd && Array.isArray(bd.labels)) ? bd.labels : bodyLabels(bd);
|
|
9281
11315
|
const cnt = (k) => lines.filter((l) => l.liuqin === k).length;
|
|
9282
11316
|
const lineEv = (l) => (l ? `${l.position}爻${l.liuqin}${l.liushen ? '·' + l.liushen : ''}${l.moving ? '(动)' : ''}` : '—');
|
|
9283
11317
|
const ev = (...xs) => xs.filter((x) => x != null && x !== '');
|
|
@@ -9299,9 +11333,112 @@ function liuyaoInterpret(r) {
|
|
|
9299
11333
|
`⑥ 看变卦:${bian.name ? `变出「${bian.name}」,是事情后续的走向` : '本卦无变,以静卦论'}。以上每一步都能在下方「依据」里对上号。`,
|
|
9300
11334
|
].join('\n'),
|
|
9301
11335
|
});
|
|
11336
|
+
if (bodyLabelList.length) {
|
|
11337
|
+
const sideOf = (o) => [o && o.inner ? '内卦' : '', o && o.outer ? '外卦' : ''].filter(Boolean).join('、');
|
|
11338
|
+
const fanYinSides = sideOf(bd.fanYin || {});
|
|
11339
|
+
const fanYinBy = ['inner', 'outer'].map((k) => bd.fanYin && bd.fanYin[k] && bd.fanYin[k].by).filter(Boolean).flat();
|
|
11340
|
+
const bodyText = [];
|
|
11341
|
+
if (bd.ben && bd.ben.chong) bodyText.push('本卦是六冲卦:六爻地支正好配成子午、寅申、辰戌三组对冲,传统读作「散」——事情起落快、成得急也散得急,急事与近病反而喜欢这股冲开的力量,拖了很久的人事则不容易凝聚。');
|
|
11342
|
+
if (bd.ben && bd.ben.he) bodyText.push('本卦是六合卦:六爻地支两两相合(子丑、寅亥、卯戌、辰酉、巳申、午未),传统读作「成」——容易谈拢,也容易拖住不放。');
|
|
11343
|
+
if (bd.bian && bd.bian.chong) bodyText.push('变卦也是六冲:往后走偏「散」,收尾容易一拍两散,也可能是速战速决。');
|
|
11344
|
+
else if (bd.bian && bd.bian.he) bodyText.push('变卦是六合:往后走偏「合」,收尾倾向于合拢、或者就这么延续下去。');
|
|
11345
|
+
if (sideOf(bd.fuYin || {})) bodyText.push(`${sideOf(bd.fuYin || {})}伏吟:卦变了,纳甲地支却没变(六十四卦里只有乾与震共用子寅辰/午申戌,所以卦伏吟只会出在乾↔震互换)——传统说「伏吟主呻吟」,人想动、事情在原地打转,宜先看清楚再迈步。`);
|
|
11346
|
+
if (fanYinSides) bodyText.push(`${fanYinSides}反吟:变卦与本卦相冲,来源有两种——${fanYinBy.includes('chong') ? '地支三爻全冲' : ''}${fanYinBy.includes('chong') && fanYinBy.includes('pair') ? ',或' : ''}${fanYinBy.includes('pair') ? '本卦之宫与变卦之宫在后天八卦上正对(乾巽、坎离、艮坤、震兑)' : ''}。传统说「反吟主反复」,去而复来、方案改来改去。`);
|
|
11347
|
+
if (bd.yaoFanYin && bd.yaoFanYin.length) bodyText.push(`动爻反吟(第${bd.yaoFanYin.join('、')}爻):变出的地支回头冲本爻,变化点本身在反复——动了又翻回来,等于绕一圈回到原处。`);
|
|
11348
|
+
if (bd.yaoFuYin && bd.yaoFuYin.length) bodyText.push(`动爻伏吟(第${bd.yaoFuYin.join('、')}爻):变出的地支与本爻同支,动了等于没动,想推的事会卡在同一道坎上。`);
|
|
11349
|
+
const jinYao = (bd.jinTui || []).filter((x) => x.type === '进');
|
|
11350
|
+
const tuiYao = (bd.jinTui || []).filter((x) => x.type === '退');
|
|
11351
|
+
if (jinYao.length) bodyText.push(`化进神(第${jinYao.map((x) => x.position).join('、')}爻:${jinYao.map((x) => `${x.from}→${x.to}`).join('、')}):变出的地支与本爻同五行、且顺着往前一步,传统读作「进」——这一爻代表的人或事有后劲,往前走比退回去顺。`);
|
|
11352
|
+
if (tuiYao.length) bodyText.push(`化退神(第${tuiYao.map((x) => x.position).join('、')}爻:${tuiYao.map((x) => `${x.from}→${x.to}`).join('、')}):变出的地支与本爻同五行、却倒着退一步,传统读作「退」——这一爻代表的人或事渐渐退气,别按原来的势头去推。`);
|
|
11353
|
+
const jp = r.jinTuiPower;
|
|
11354
|
+
if (jp && Array.isArray(jp.lines) && jp.lines.length) {
|
|
11355
|
+
bodyText.push(`进退的力重(放回月建日辰看):${jp.lines.map((l) => `第${l.position}爻${l.say}`).join(';')}。进退只管方向,走不走得动看时令托不托着;用神化进为喜,忌神化进反而是忌。`);
|
|
11356
|
+
}
|
|
11357
|
+
bodyText.push('这些标签只说明卦体的动势,不直接定吉凶:同一支六冲,近病问的是速愈、久病问的是凶险;同一爻化进,也得看用神旺不旺、有没有月建日辰托着。');
|
|
11358
|
+
sections.push({ key: 'body', label: '卦体关系', text: bodyText.join('\n') });
|
|
11359
|
+
}
|
|
11360
|
+
|
|
11361
|
+
const ug = yongshenOf(r, {
|
|
11362
|
+
direction: (ask && ask.direction) || (r.useGod && r.useGod.direction) || 'general',
|
|
11363
|
+
gender: (r.useGod && r.useGod.gender) || 'male',
|
|
11364
|
+
});
|
|
11365
|
+
if (ug && ug.liuqin) {
|
|
11366
|
+
const useText = [];
|
|
11367
|
+
useText.push(`所问方向取${ug.byShi ? '世爻' : ug.liuqin}为用神(${ug.ask})${ug.direction === 'love' ? `;感情按${ug.gender === 'female' ? '女命看官鬼' : '男命看妻财'}取,性别未给时按男命算` : ''}。`);
|
|
11368
|
+
if (ug.found.length) {
|
|
11369
|
+
useText.push(`用神在卦上:${ug.found.map((f) => `${f.position}爻${f.ganzhi}${f.element}${f.liuqin}${f.liushen ? `·${f.liushen}` : ''}${f.shi ? '(持世)' : ''}${f.ying ? '(临应)' : ''}${f.moving ? '(发动)' : ''}${f.kong ? '(旬空)' : ''}`).join('、')}${ug.side ? `,落在${ug.side}` : ''}。`);
|
|
11370
|
+
if (ug.found.length > 1) useText.push('用神两现:传统取动者、取持世者、取旬空待填者,各派权重不同;这里只把几处都列出来,不替你选哪一爻当主用。');
|
|
11371
|
+
} else if (ug.fushen.length) {
|
|
11372
|
+
useText.push(`用神不上卦:本卦六爻里没有${ug.liuqin},按「用神不上卦则于本宫首卦内寻之」,到${String(pick(ben, 'palace', '')).replace(/宫$/, '')}宫首卦取伏神——${ug.fushen.map((f) => `${f.position}爻${f.ganzhi}${f.element},伏于飞神${f.fei ? `${f.fei.liuqin}${f.fei.ganzhi}${f.fei.element}` : '—'}之下`).join(';')}。`);
|
|
11373
|
+
if (ug.relationSay.length) useText.push(`飞伏生克:${ug.relationSay.join(';')}。伏神要得出才算有力,藏在忌神之下且被克,则虽有如无。`);
|
|
11374
|
+
} else {
|
|
11375
|
+
useText.push(`用神不上卦,且本宫首卦里也没找到${ug.liuqin},这一问在卦面上没有直接对应物,只能借日月或改日再占。`);
|
|
11376
|
+
}
|
|
11377
|
+
|
|
11378
|
+
const link = [];
|
|
11379
|
+
if (bd.ben && bd.ben.chong) link.push('用神在六冲卦里:六冲主散,急事与近病借这股冲开的力量,缓事、久拖的人事则不容易凝聚');
|
|
11380
|
+
if (bd.ben && bd.ben.he) link.push('用神在六合卦里:六合主成,容易谈拢,也容易黏住不放');
|
|
11381
|
+
if (bd.bian && bd.bian.chong) link.push('用神逢变六冲:往后走向偏散,收尾容易一拍两散,也可能是速战速决');
|
|
11382
|
+
else if (bd.bian && bd.bian.he) link.push('用神逢变六合:往后走向偏合,倾向于合拢或就这么延续');
|
|
11383
|
+
for (const side of ['inner', 'outer']) {
|
|
11384
|
+
const nm = side === 'inner' ? '内卦' : '外卦';
|
|
11385
|
+
if (bd.fuYin && bd.fuYin[side]) link.push(`用神在${nm}伏吟:动而地支未变,想推的事卡在原地`);
|
|
11386
|
+
if (bd.fanYin && bd.fanYin[side]) link.push(`用神在${nm}反吟:变卦与本卦相冲,用神这一头去而复来、定了又改`);
|
|
11387
|
+
}
|
|
11388
|
+
const jinYong = (bd.jinTui || []).filter((x) => x.type === '进' && ug.found.some((f) => f.position === x.position));
|
|
11389
|
+
const tuiYong = (bd.jinTui || []).filter((x) => x.type === '退' && ug.found.some((f) => f.position === x.position));
|
|
11390
|
+
if (jinYong.length) link.push(`用神化进神(${jinYong.map((x) => `${x.from}→${x.to}`).join('、')}):这一爻有后劲,顺着推比退回去顺`);
|
|
11391
|
+
if (tuiYong.length) link.push(`用神化退神(${tuiYong.map((x) => `${x.from}→${x.to}`).join('、')}):这一爻渐渐退气,别按原来的势头硬推`);
|
|
11392
|
+
if (ug.found.some((f) => f.kong)) link.push('用神旬空:事情先悬着,传统说空要出空、填实才算落地');
|
|
11393
|
+
if (ug.found.some((f) => (bd.yaoFanYin || []).includes(f.position))) link.push('用神这一爻动而反吟:变化点本身在反复,动了又翻回来');
|
|
11394
|
+
if (ug.found.some((f) => (bd.yaoFuYin || []).includes(f.position))) link.push('用神这一爻动而伏吟:动了等于没动,容易卡在同一道坎上');
|
|
11395
|
+
if (link.length) useText.push(`与卦体对起来看:${link.join(';')}。`);
|
|
11396
|
+
const strength = r.useGodStrength;
|
|
11397
|
+
if (strength && strength.lines && strength.lines.length) {
|
|
11398
|
+
const head = strength.month && strength.month.branch
|
|
11399
|
+
? `月建 ${strength.month.branch}(${strength.month.element})`
|
|
11400
|
+
: '没有月建(未给起卦时间),只按日辰看';
|
|
11401
|
+
const body = strength.lines.map((l) => {
|
|
11402
|
+
const chong = l.monthChong ? ',遭月建冲(月破)'
|
|
11403
|
+
: l.dayChong ? (l.kong ? ',日辰冲空' : l.moving ? ',逢日辰冲' : ',日辰冲而暗动') : '';
|
|
11404
|
+
return `${l.position}爻${l.branch}${l.element}:月建${l.monthState}(${l.monthSay}),${l.dayRelation}(${l.daySay})${chong}`;
|
|
11405
|
+
});
|
|
11406
|
+
useText.push(`时令对用神:${head},日辰 ${strength.day ? `${strength.day.branch}(${strength.day.element})` : '—'}。${body.join(';')}。`);
|
|
11407
|
+
useText.push('月建看这一段时令站在哪一边,日辰看当天那股力量是扶还是克;两处同时看,只报状态,不折成分数。');
|
|
11408
|
+
}
|
|
11409
|
+
useText.push('这一层只把用神、卦体与时令对起来,应期与成败还要看动爻变化与月建日辰的进退节奏,所以这里不折成分数、不断成败。');
|
|
11410
|
+
sections.push({ key: 'yongshen', label: '用神落位与卦体', text: useText.join('\n') });
|
|
11411
|
+
}
|
|
11412
|
+
|
|
11413
|
+
{
|
|
11414
|
+
const hs = r.hexStrength;
|
|
11415
|
+
if (hs && Array.isArray(hs.lines) && hs.lines.length) {
|
|
11416
|
+
const head = hs.month && hs.month.branch
|
|
11417
|
+
? `月建 ${hs.month.branch}(${hs.month.element})`
|
|
11418
|
+
: '没有月建(未给起卦时间)';
|
|
11419
|
+
const day = hs.day && hs.day.branch ? `日辰 ${hs.day.branch}(${hs.day.element})` : '日辰 —';
|
|
11420
|
+
const rows = hs.lines.map((l) => {
|
|
11421
|
+
const who = l.shi ? '(世)' : l.ying ? '(应)' : '';
|
|
11422
|
+
const flags = `${l.moving ? '·动' : ''}${l.kong ? '·旬空' : ''}`;
|
|
11423
|
+
return `${l.position}爻${l.liuqin ? l.liuqin : ''}${l.branch}${l.element}${who}${flags}:月建${l.monthState},${l.dayRelation}${l.chongTag ? `,${l.chongTag}` : ''}`;
|
|
11424
|
+
});
|
|
11425
|
+
const order = ['旺', '相', '休', '囚', '死'];
|
|
11426
|
+
const dist = order.filter((k) => hs.counts[k]).map((k) => `${k}${hs.counts[k]}`).join('、');
|
|
11427
|
+
const shi = hs.shi ? `世爻在${hs.shi.position}爻(月建${hs.shi.monthState},${hs.shi.dayRelation})` : '';
|
|
11428
|
+
const ying = hs.ying ? `应爻在${hs.ying.position}爻(月建${hs.ying.monthState},${hs.ying.dayRelation})` : '';
|
|
11429
|
+
sections.push({
|
|
11430
|
+
key: 'hexStrength',
|
|
11431
|
+
label: '全卦逐爻旺衰',
|
|
11432
|
+
text: `整张卦按${head}、${day}逐爻过一遍:${rows.join(';')}。五态分布:${dist}——${[shi, ying].filter(Boolean).join(',')}。` +
|
|
11433
|
+
`气旺的爻对应的事推进起来省力,气弱或遭月破的爻对应的事宜缓;这只是六爻全貌,用神那几爻的细节仍以上一节为准,两处不冲突时再看动爻把哪一头带动。` +
|
|
11434
|
+
`判定与用神旺衰同一套(月令五态、日辰五关系、月破/暗动/冲空),只报状态,不折成分数。`,
|
|
11435
|
+
});
|
|
11436
|
+
}
|
|
11437
|
+
}
|
|
11438
|
+
|
|
9302
11439
|
sections.push({
|
|
9303
11440
|
key: 'limits', label: '未纳入',
|
|
9304
|
-
text: '
|
|
11441
|
+
text: '本卦没有计算:用神两现时该取哪一爻的权重、伏神出伏的应期。化进/化退的力重只按月建五态给「得令/失令」这类档位,不折成加权分数,也不叠动变连环;这些都会改变"旺不旺"的判断,所以这里只给取象与方向。',
|
|
9305
11442
|
});
|
|
9306
11443
|
|
|
9307
11444
|
const dimensions = [
|
|
@@ -9315,6 +11452,7 @@ function liuyaoInterpret(r) {
|
|
|
9315
11452
|
moving ? `动爻 ${lineEv(moving)}` : '无动爻',
|
|
9316
11453
|
`日辰 ${dayGZ || '—'}`,
|
|
9317
11454
|
`卦宫 ${pick(ben, 'palace', '—')}·${palaceEl || '—'}`,
|
|
11455
|
+
bodyLabelList.length ? `卦体 ${bodyLabelList.join('、')}` : '卦体 无六冲六合伏吟反吟',
|
|
9318
11456
|
),
|
|
9319
11457
|
},
|
|
9320
11458
|
{
|
|
@@ -9703,6 +11841,7 @@ const BUILDERS = {
|
|
|
9703
11841
|
const { interpretQimen } = __mods['qimen-interpret'];
|
|
9704
11842
|
const { buildAnswer, buildPlain, buildGlossary, buildFollowups, dimensionPlain } = __mods['interpret-plain'];
|
|
9705
11843
|
const { knowledgeFor, caveatsFor, STATUS_LABEL } = __mods['interpret-knowledge'];
|
|
11844
|
+
const { CLASSIC_BOOKS } = __mods.classics;
|
|
9706
11845
|
|
|
9707
11846
|
function enrichPlain(result, r, ask) {
|
|
9708
11847
|
if (!result) return result;
|
|
@@ -9798,7 +11937,7 @@ function interpret(r, opts) {
|
|
|
9798
11937
|
if (!fn) return null;
|
|
9799
11938
|
let body;
|
|
9800
11939
|
try {
|
|
9801
|
-
body = fn(r);
|
|
11940
|
+
body = fn(r, ask);
|
|
9802
11941
|
} catch (e) {
|
|
9803
11942
|
return {
|
|
9804
11943
|
moduleType: MODULE_TYPE[r.system] || 'natal',
|
|
@@ -9990,7 +12129,54 @@ function followup(r, question) {
|
|
|
9990
12129
|
return { question: q, ...result };
|
|
9991
12130
|
}
|
|
9992
12131
|
|
|
9993
|
-
|
|
12132
|
+
const SYSTEM_LABEL = {
|
|
12133
|
+
bazi: '八字(四柱)',
|
|
12134
|
+
ziwei: '紫微斗数',
|
|
12135
|
+
liuyao: '六爻',
|
|
12136
|
+
meihua: '梅花易数',
|
|
12137
|
+
daliuren: '大六壬',
|
|
12138
|
+
qimen: '奇门遁甲',
|
|
12139
|
+
tarot: '塔罗',
|
|
12140
|
+
hepan: '合盘',
|
|
12141
|
+
chenggu: '称骨',
|
|
12142
|
+
almanac: '黄历',
|
|
12143
|
+
zeri: '择日',
|
|
12144
|
+
star: '星座',
|
|
12145
|
+
numerology: '生命数字',
|
|
12146
|
+
mbti: '十六型人格',
|
|
12147
|
+
trend: '人生 K 线',
|
|
12148
|
+
fengshui: '风水',
|
|
12149
|
+
name: '起名',
|
|
12150
|
+
convert: '公农历互转',
|
|
12151
|
+
};
|
|
12152
|
+
|
|
12153
|
+
function askPrompt(r, opts = {}) {
|
|
12154
|
+
const label = SYSTEM_LABEL[r && r.system] || (r && r.system) || '未知体系';
|
|
12155
|
+
const asked = String((opts && opts.question) || '').trim();
|
|
12156
|
+
const question = asked || '请先总览这张盘,指出最值得注意的一两处,并说明各自的依据。';
|
|
12157
|
+
const limit = Number.isFinite(opts && opts.maxChars) && opts.maxChars >= 400 ? opts.maxChars : 3000;
|
|
12158
|
+
const raw = String((r && r.summary) || '').trim();
|
|
12159
|
+
const truncated = raw.length > limit;
|
|
12160
|
+
const summary = truncated ? `${raw.slice(0, limit)}…(摘要已截断)` : raw;
|
|
12161
|
+
|
|
12162
|
+
const lines = [
|
|
12163
|
+
'【命理追问】下面这张盘是命理插件刚排好的,请就着它回答我的问题;不用重新排盘,盘面字段已经够用。',
|
|
12164
|
+
`体系:${label}`,
|
|
12165
|
+
`所问:${question}`,
|
|
12166
|
+
'',
|
|
12167
|
+
'——盘面摘要——',
|
|
12168
|
+
summary || '(这张盘没有摘要字段,请先让我重新排一次。)',
|
|
12169
|
+
'',
|
|
12170
|
+
'——回答要求——',
|
|
12171
|
+
'1) 尽量引用到具体的柱、宫或爻,再说判断,别只给结论;',
|
|
12172
|
+
'2) 盘面里没有依据的地方直接说「这盘里看不出来」,不要补外部假设;',
|
|
12173
|
+
'3) 用概率和倾向的说法,别给绝对化的断言,也别把传统说法当成事实。',
|
|
12174
|
+
];
|
|
12175
|
+
const text = lines.join('\n');
|
|
12176
|
+
return { text, question, system: (r && r.system) || '', label, chars: text.length, truncated };
|
|
12177
|
+
}
|
|
12178
|
+
|
|
12179
|
+
return { followup, askPrompt };
|
|
9994
12180
|
})();
|
|
9995
12181
|
|
|
9996
12182
|
__mods.crosscheck = (function () {
|
|
@@ -10280,19 +12466,19 @@ return { matchEvent, rectifyBirth, RECTIFY_KINDS };
|
|
|
10280
12466
|
|
|
10281
12467
|
__mods.index = (function () {
|
|
10282
12468
|
const { buildBazi } = __mods.bazi;
|
|
10283
|
-
const { buildLiuyao, tossLines } = __mods.liuyao;
|
|
12469
|
+
const { buildLiuyao, tossLines, bodyLabels, yongshenOf, yongshenStrength, hexagramStrength, jinTuiPower } = __mods.liuyao;
|
|
10284
12470
|
const { buildZiwei, BRIGHTNESS, flowOf, asOfParts } = __mods.ziwei;
|
|
10285
12471
|
const { drawTarot } = __mods.tarot;
|
|
10286
12472
|
const { buildMeihua } = __mods.meihua;
|
|
10287
12473
|
const { buildDaliuren } = __mods.daliuren;
|
|
10288
12474
|
const { buildHepan } = __mods.hepan;
|
|
10289
12475
|
const { buildZiweiHepan } = __mods['ziwei-hepan'];
|
|
10290
|
-
const { buildQimen } = __mods.qimen;
|
|
12476
|
+
const { buildQimen, buildSnapshot } = __mods.qimen;
|
|
10291
12477
|
const { geocodeAddress, resolveAddress } = __mods.geo;
|
|
10292
12478
|
const { toJDN, ganzhiName, dayGanzhiIndex } = __mods.calendar;
|
|
10293
12479
|
const { randomOf, isSeed } = __mods.random;
|
|
10294
12480
|
const { interpret, DIRECTIONS, DIRECTION_DEFAULT } = __mods.interpret;
|
|
10295
|
-
const { followup } = __mods.followup;
|
|
12481
|
+
const { followup, askPrompt } = __mods.followup;
|
|
10296
12482
|
const { crossCheck, crossText } = __mods.crosscheck;
|
|
10297
12483
|
const { pastSignals, verifyFit } = __mods.verify;
|
|
10298
12484
|
const { rectifyBirth } = __mods.rectify;
|
|
@@ -10302,7 +12488,9 @@ const { buildChenggu } = __mods.chenggu;
|
|
|
10302
12488
|
const { buildXiaoliuren } = __mods.xiaoliuren;
|
|
10303
12489
|
const { buildStar } = __mods.star;
|
|
10304
12490
|
const { buildNumerology } = __mods.numerology;
|
|
12491
|
+
const { buildMbti, mbtiPaper } = __mods.mbti;
|
|
10305
12492
|
const { buildConvert } = __mods.convert;
|
|
12493
|
+
const { classicsFor, classicsText } = __mods.classics;
|
|
10306
12494
|
const { buildTrend } = __mods.trend;
|
|
10307
12495
|
const { buildFengshui } = __mods.fengshui;
|
|
10308
12496
|
const { buildName } = __mods.name;
|
|
@@ -10367,6 +12555,9 @@ function baziText(r) {
|
|
|
10367
12555
|
: '';
|
|
10368
12556
|
const dayun = r.dayun.list.slice(0, 8)
|
|
10369
12557
|
.map((d) => `${d.startAge}岁 ${d.ganzhi}(${d.stemTenGod})${d.luck ? `·${d.luck.tier}` : ''}${d.relations && d.relations.length ? `[${d.relations.join('')}]` : ''}`).join(' ');
|
|
12558
|
+
const jiao = r.dayun.jiao && r.dayun.jiao.at
|
|
12559
|
+
? `;交运 ${r.dayun.jiao.at}(${r.dayun.jiao.frame},距${r.dayun.jiao.from.name} ${r.dayun.jiao.spanDays} 天,三日折一年)`
|
|
12560
|
+
: '';
|
|
10370
12561
|
const near = r.jieqi.nearBoundaryMinutes < 20
|
|
10371
12562
|
? `\n⚠ 出生时刻距「节」仅 ${r.jieqi.nearBoundaryMinutes} 分钟,而节气时刻本身有最多约 14 分钟的偏差,月柱与年柱建议人工复核。`
|
|
10372
12563
|
: '';
|
|
@@ -10397,9 +12588,16 @@ function baziText(r) {
|
|
|
10397
12588
|
shenshaLine,
|
|
10398
12589
|
`真太阳时:${r.solarTime.trueSolarText}(${r.input.geo ? r.input.geo.note + ';' : ''}${r.solarTime.note}) 晚子时:${r.input.lateZi ? '23:00 后算次日' : '23:00 后仍算当日'}`,
|
|
10399
12590
|
`节气:上一节 ${r.jieqi.previous.name} ${r.jieqi.previous.time} 下一节 ${r.jieqi.next.name} ${r.jieqi.next.time}`,
|
|
10400
|
-
`大运:${r.dayun.rule}(${r.dayun.direction}),${r.dayun.startAge.years}岁${r.dayun.startAge.months}
|
|
12591
|
+
`大运:${r.dayun.rule}(${r.dayun.direction}),${r.dayun.startAge.years}岁${r.dayun.startAge.months}个月起运${jiao}`,
|
|
10401
12592
|
` ${dayun}`,
|
|
10402
12593
|
`流年:${r.liunian.slice(0, 10).map((l) => `${l.year}${l.ganzhi}(${l.stemTenGod})${l.luck ? `·${l.luck.tier}` : ''}`).join(' ')}`,
|
|
12594
|
+
(() => {
|
|
12595
|
+
const hits = r.liunian.filter((l) => l.suiyun && l.suiyun.signals && l.suiyun.signals.length);
|
|
12596
|
+
if (!hits.length) return '岁运提示:近十年无岁运并临、运年反吟或流年伏吟/反吟(只标干支,不判吉凶)';
|
|
12597
|
+
const label = (s) => `${s.type}${s.type.startsWith('流年') && s.target ? `(${s.target})` : ''}`;
|
|
12598
|
+
return '岁运提示(只标干支变动,不判吉凶):' + hits
|
|
12599
|
+
.map((l) => `${l.year}${l.ganzhi} ${l.suiyun.signals.map(label).join('/')}`).join(';');
|
|
12600
|
+
})(),
|
|
10403
12601
|
'(格局、用神、行运吉凶为扶抑+简化调候的量化提示,非断语。)',
|
|
10404
12602
|
].join('\n') + near;
|
|
10405
12603
|
}
|
|
@@ -10426,6 +12624,28 @@ function ziweiText(r) {
|
|
|
10426
12624
|
: '无明显格局(按内置规则)';
|
|
10427
12625
|
const daxian = (r.daxianList ?? []).slice(0, 8).map((d) =>
|
|
10428
12626
|
` ${d.branch}宫(${d.palace})${d.ages[0]}-${d.ages[1]}岁 ${d.ganzhi} 会${d.mainStars.join('') || '—'} 化 ${d.mutagenHits.map((m) => `${m.star}${m.type}→${m.palace || '未上盘'}`).join('、')}`);
|
|
12627
|
+
const flyLine = (() => {
|
|
12628
|
+
const fc = r.flyChains;
|
|
12629
|
+
if (!fc) return '';
|
|
12630
|
+
const one = (t) => {
|
|
12631
|
+
const ch = fc[t];
|
|
12632
|
+
if (!ch || !ch.steps.length) return '';
|
|
12633
|
+
return `${t}:${ch.path.join('→')}${ch.closed ? '(成环)' : ''}`;
|
|
12634
|
+
};
|
|
12635
|
+
const text = ['禄', '权', '科', '忌'].map(one).filter(Boolean).join(' ');
|
|
12636
|
+
return text ? `【命宫飞星】${text}` : '';
|
|
12637
|
+
})();
|
|
12638
|
+
const flyCompositeLine = (() => {
|
|
12639
|
+
const fc = r.flyComposite;
|
|
12640
|
+
if (!fc || !Array.isArray(fc.sources) || !fc.sources.length) return '';
|
|
12641
|
+
const groups = fc.labels.length ? fc.labels.join(' · ') : '无同宫会聚';
|
|
12642
|
+
const detail = ['禄', '权', '科', '忌'].map((t) => {
|
|
12643
|
+
const list = ((fc.byType && fc.byType[t]) || []).filter((x) => !x.self);
|
|
12644
|
+
const tos = [...new Set(list.map((x) => String(x.to).replace(/宫$/, '')))];
|
|
12645
|
+
return tos.length ? `${t}→${tos.join('/')}` : '';
|
|
12646
|
+
}).filter(Boolean).join(' ');
|
|
12647
|
+
return `【三方四正飞化】${fc.sanfang.join('·')}:${groups}${detail ? ` ${detail}` : ''}`;
|
|
12648
|
+
})();
|
|
10429
12649
|
return [
|
|
10430
12650
|
`【农历】${lunarText}(月首 ${r.lunar.monthStart}) 时支:${r.hourBranch} 年干支:${r.yearGanzhi}`,
|
|
10431
12651
|
`【时刻】${r.solarTime ? `${r.solarTime.civilText} → 真太阳时 ${r.solarTime.trueSolarText}${r.input.geo ? '(' + r.input.geo.note + ')' : ''}` : ''}`,
|
|
@@ -10434,6 +12654,8 @@ function ziweiText(r) {
|
|
|
10434
12654
|
`【大限】${r.daxian.rule},${r.daxian.startAge}岁起 【小限】${r.xiaoxianRule.direction}`,
|
|
10435
12655
|
`【昌曲】文昌${r.changqu.wenchang.branch}(${r.changqu.wenchang.palace}${r.changqu.wenchang.mutagen ? '·化' + r.changqu.wenchang.mutagen : ''}) 文曲${r.changqu.wenqu.branch}(${r.changqu.wenqu.palace}${r.changqu.wenqu.mutagen ? '·化' + r.changqu.wenqu.mutagen : ''})`,
|
|
10436
12656
|
` ${r.changqu.relation} 入命三方:${r.changqu.inSoulSanfang ? '是' : '否'} 吸收面:${r.changqu.absorb.label}(${r.changqu.absorb.reason})`,
|
|
12657
|
+
flyLine,
|
|
12658
|
+
flyCompositeLine,
|
|
10437
12659
|
'十二宫:',
|
|
10438
12660
|
...rows,
|
|
10439
12661
|
'大限(按起运年龄排序,前 8 限,宫干四化落宫):',
|
|
@@ -10441,11 +12663,21 @@ function ziweiText(r) {
|
|
|
10441
12663
|
'流年(前 6 年,完整 12 年在结构化数据里):',
|
|
10442
12664
|
...liunian,
|
|
10443
12665
|
`【格局】${patterns}`,
|
|
10444
|
-
r.patternSummary ? `【结构统计】吉格 ${r.patternSummary.good.length}、忌格 ${r.patternSummary.bad.length};${r.patternSummary.note}` : '',
|
|
12666
|
+
r.patternSummary ? `【结构统计】吉格 ${r.patternSummary.good.length}、中性 ${r.patternSummary.neutral.length}、忌格 ${r.patternSummary.bad.length};${r.patternSummary.note}` : '',
|
|
10445
12667
|
r.lunar.note ? `注:${r.lunar.note}` : '',
|
|
10446
12668
|
].filter(Boolean).join('\n');
|
|
10447
12669
|
}
|
|
10448
12670
|
|
|
12671
|
+
const STATE_ORDER = ['旺', '相', '休', '囚', '死'];
|
|
12672
|
+
function stateLine(r) {
|
|
12673
|
+
const st = r.states;
|
|
12674
|
+
const mo = r.month;
|
|
12675
|
+
if (!st || !mo) return '无月令数据';
|
|
12676
|
+
const fmt = (g) => STATE_ORDER.filter((k) => g && Array.isArray(g[k]) && g[k].length)
|
|
12677
|
+
.map((k) => `${k} ${g[k].join('/')}`).join(' ');
|
|
12678
|
+
return `月令 ${mo.branch}(${mo.element}) 门 ${fmt(st.gate) || '—'} 星 ${fmt(st.star) || '—'} 干 ${fmt(st.stem) || '—'}`;
|
|
12679
|
+
}
|
|
12680
|
+
|
|
10449
12681
|
function qimenText(r) {
|
|
10450
12682
|
const P = r.palaces;
|
|
10451
12683
|
const cell = (x) => `${x.palace}宫 ${x.star || '—'}/${x.gate || '—'}/${x.god || '—'}${x.kong ? ' 空' : ''}${x.ma ? ' 马' : ''}`;
|
|
@@ -10454,6 +12686,8 @@ function qimenText(r) {
|
|
|
10454
12686
|
`【局数】${r.ju} 节气 ${r.jieqi}(${r.jieqiTime})`,
|
|
10455
12687
|
`【值符】${r.zhiFu.star}(${r.zhiFu.gong}宫) 【值使】${r.zhiShi.gate}(${r.zhiShi.gong}宫) 旬首 ${r.xunshou}`,
|
|
10456
12688
|
`【空亡】${r.kongWang.join('') || '—'} 驿马 ${r.ma.zhi || '—'}(${r.ma.gong || '—'}宫)`,
|
|
12689
|
+
`【宫位条件】击刑 ${(r.conditions && r.conditions.jiXing || []).map((x) => `${x.palace}宫${x.stem}`).join('、') || '无'} 入墓 ${(r.conditions && r.conditions.ruMu || []).map((x) => `${x.palace}宫${x.stem}`).join('、') || '无'}`,
|
|
12690
|
+
`【旺衰】${stateLine(r)}`,
|
|
10457
12691
|
`【九宫】${P.map(cell).join(' ')}`,
|
|
10458
12692
|
`※ 晚子时:${r.lateZiHourMode === 'next-day' ? '23:00 后归次日' : '23:00 后仍归当日'}(可用 lateZiHourMode / lateZi 指定)`,
|
|
10459
12693
|
`※ ${r.rules[r.rules.length - 1]}`,
|
|
@@ -10555,6 +12789,36 @@ function liuyaoText(r) {
|
|
|
10555
12789
|
];
|
|
10556
12790
|
if (r.bian) out.push(`动爻:第 ${r.cast.movingPositions.join('、')} 爻`, '变卦(六亲以变卦自身宫论):', fmt(r.bian));
|
|
10557
12791
|
else out.push('六爻安静,无变卦。');
|
|
12792
|
+
const body = (r.body && Array.isArray(r.body.labels)) ? r.body.labels : bodyLabels(r.body);
|
|
12793
|
+
out.push(`卦体:${body.length ? body.join(' · ') : '无六冲、六合、伏吟、反吟'}`);
|
|
12794
|
+
const ug = r.useGod || yongshenOf(r, {});
|
|
12795
|
+
if (ug && ug.liuqin) {
|
|
12796
|
+
const where = ug.found.length
|
|
12797
|
+
? ug.found.map((f) => `${f.position}爻${f.ganzhi}${f.element}${f.kong ? '(空)' : ''}`).join('、')
|
|
12798
|
+
: (ug.fushen.length ? ug.fushen.map((f) => `伏 ${f.position}爻${f.ganzhi}${f.element}(${f.relation || '飞伏关系未知'})`).join('、') : '不上卦');
|
|
12799
|
+
out.push(`用神:${ug.byShi ? '世爻' : ug.liuqin}(${ug.ask})→ ${where}${ug.side ? `(${ug.side})` : ''}`);
|
|
12800
|
+
const head = ug.byShi ? '用神 世爻' : `用神 ${ug.liuqin}`;
|
|
12801
|
+
const extra = ug.labels.filter((x) => x !== head && !x.startsWith(head));
|
|
12802
|
+
if (extra.length) out.push(`用神联动:${extra.join(' · ')}`);
|
|
12803
|
+
const strength = r.useGodStrength;
|
|
12804
|
+
if (strength && strength.labels.length) {
|
|
12805
|
+
const m = strength.month && strength.month.branch ? `月建 ${strength.month.branch}(${strength.month.element}) ` : '';
|
|
12806
|
+
out.push(`用神旺衰:${m}${strength.labels.join(' · ')}`);
|
|
12807
|
+
}
|
|
12808
|
+
} else {
|
|
12809
|
+
out.push('用神:未取(未指明所问之事;用「询问方向」指定后即按六亲取用)');
|
|
12810
|
+
}
|
|
12811
|
+
const hexSt = r.hexStrength;
|
|
12812
|
+
if (hexSt && Array.isArray(hexSt.labels) && hexSt.labels.length) {
|
|
12813
|
+
const m = hexSt.month && hexSt.month.branch
|
|
12814
|
+
? `月建 ${hexSt.month.branch}(${hexSt.month.element}) `
|
|
12815
|
+
: '无月建(未给起卦时间) ';
|
|
12816
|
+
out.push(`全卦旺衰:${m}${hexSt.labels.join(' · ')}`);
|
|
12817
|
+
}
|
|
12818
|
+
const jt = r.jinTuiPower;
|
|
12819
|
+
if (jt && Array.isArray(jt.lines) && jt.lines.length) {
|
|
12820
|
+
out.push(`进退力重:${jt.lines.map((l) => `${l.position}爻${l.from}→${l.to}${l.type}·${l.verdict}`).join(' · ')}`);
|
|
12821
|
+
}
|
|
10558
12822
|
return out.filter(Boolean).join('\n');
|
|
10559
12823
|
}
|
|
10560
12824
|
|
|
@@ -10564,6 +12828,11 @@ function jsonSafe(value) {
|
|
|
10564
12828
|
|
|
10565
12829
|
function compute(args = {}) {
|
|
10566
12830
|
const r = jsonSafe(computeRaw(args));
|
|
12831
|
+
if (r && r.system === 'bazi') {
|
|
12832
|
+
r.classics = classicsFor(r);
|
|
12833
|
+
const ct = classicsText(r.classics);
|
|
12834
|
+
if (ct) r.summary = `${r.summary}\n【古籍】\n${ct}`;
|
|
12835
|
+
}
|
|
10567
12836
|
if (r && r.precision && r.precision.level === 'approx' && r.summary) {
|
|
10568
12837
|
r.summary = `⚠ ${r.precision.note}\n${r.summary}`;
|
|
10569
12838
|
}
|
|
@@ -10829,6 +13098,25 @@ function computeRaw(args = {}) {
|
|
|
10829
13098
|
} catch (e) {
|
|
10830
13099
|
throw fail('E_LINES', e && e.message ? e.message : e);
|
|
10831
13100
|
}
|
|
13101
|
+
const ug = yongshenOf(result, { direction: args.direction, gender: args.gender });
|
|
13102
|
+
if (ug.liuqin) result.useGod = ug;
|
|
13103
|
+
let monthBranch = null;
|
|
13104
|
+
if (stamp) {
|
|
13105
|
+
try {
|
|
13106
|
+
const snap = buildSnapshot({ year: stamp.year, month: stamp.month, day: stamp.day, hour: stamp.hour, minute: stamp.minute });
|
|
13107
|
+
monthBranch = (snap.monthGanZhi || '')[1] || null;
|
|
13108
|
+
} catch {
|
|
13109
|
+
monthBranch = null;
|
|
13110
|
+
}
|
|
13111
|
+
}
|
|
13112
|
+
const hexStrength = hexagramStrength(result, { monthBranch, dayBranch: result.dayGanZhi.branch });
|
|
13113
|
+
if (hexStrength) result.hexStrength = hexStrength;
|
|
13114
|
+
const jtPower = jinTuiPower(result, { monthBranch, dayBranch: result.dayGanZhi.branch });
|
|
13115
|
+
if (jtPower) result.jinTuiPower = jtPower;
|
|
13116
|
+
if (ug.liuqin) {
|
|
13117
|
+
const strength = yongshenStrength(result, ug, { monthBranch, dayBranch: result.dayGanZhi.branch });
|
|
13118
|
+
if (strength) result.useGodStrength = strength;
|
|
13119
|
+
}
|
|
10832
13120
|
if (args.seed !== undefined && args.seed !== null && args.seed !== '') result.seed = Number(args.seed);
|
|
10833
13121
|
return { ...result, ...(asOf ? { asOf } : {}), summary: liuyaoText(result) };
|
|
10834
13122
|
}
|
|
@@ -10902,6 +13190,14 @@ function computeRaw(args = {}) {
|
|
|
10902
13190
|
const result = buildNumerology({ year: dt.year, month: dt.month, day: dt.day });
|
|
10903
13191
|
return { ...result, summary: numerologyText(result) };
|
|
10904
13192
|
}
|
|
13193
|
+
if (system === 'mbti') {
|
|
13194
|
+
if (args.answers === undefined || args.answers === null) {
|
|
13195
|
+
const paper = mbtiPaper();
|
|
13196
|
+
return { ...paper, summary: mbtiPaperText(paper) };
|
|
13197
|
+
}
|
|
13198
|
+
const result = buildMbti({ answers: args.answers });
|
|
13199
|
+
return { ...result, summary: mbtiText(result) };
|
|
13200
|
+
}
|
|
10905
13201
|
if (system === 'trend') {
|
|
10906
13202
|
const dt = parseDateTime(args.datetime);
|
|
10907
13203
|
const result = buildTrend({
|
|
@@ -10971,9 +13267,9 @@ function computeRaw(args = {}) {
|
|
|
10971
13267
|
return { ...result, summary: nameText(result) };
|
|
10972
13268
|
}
|
|
10973
13269
|
if (!system) {
|
|
10974
|
-
throw fail('E_INPUT', '缺少 system,可选:bazi(四柱八字)、ziwei(紫微斗数)、liuyao(六爻)、meihua(梅花易数)、daliuren(大六壬)、qimen(奇门遁甲)、hepan(合盘)、tarot(塔罗)、almanac(黄历)、zeri(择日)、chenggu(称骨)、xiaoliuren(小六壬)、star(星座)、numerology(生命数字)、trend(人生 K 线)、fengshui(风水)、name(起名)、convert(公农历互转)。');
|
|
13270
|
+
throw fail('E_INPUT', '缺少 system,可选:bazi(四柱八字)、ziwei(紫微斗数)、liuyao(六爻)、meihua(梅花易数)、daliuren(大六壬)、qimen(奇门遁甲)、hepan(合盘)、tarot(塔罗)、almanac(黄历)、zeri(择日)、chenggu(称骨)、xiaoliuren(小六壬)、star(星座)、numerology(生命数字)、mbti(十六型人格问卷)、trend(人生 K 线)、fengshui(风水)、name(起名)、convert(公农历互转)。');
|
|
10975
13271
|
}
|
|
10976
|
-
throw fail('E_SYSTEM', `未知体系「${system}」,可选:bazi(四柱八字)、ziwei(紫微斗数)、liuyao(六爻)、meihua(梅花易数)、daliuren(大六壬)、qimen(奇门遁甲)、hepan(合盘)、tarot(塔罗)、almanac(黄历)、zeri(择日)、chenggu(称骨)、xiaoliuren(小六壬)、star(星座)、numerology(生命数字)、trend(人生 K 线)、fengshui(风水)、name(起名)、convert(公农历互转)。`);
|
|
13272
|
+
throw fail('E_SYSTEM', `未知体系「${system}」,可选:bazi(四柱八字)、ziwei(紫微斗数)、liuyao(六爻)、meihua(梅花易数)、daliuren(大六壬)、qimen(奇门遁甲)、hepan(合盘)、tarot(塔罗)、almanac(黄历)、zeri(择日)、chenggu(称骨)、xiaoliuren(小六壬)、star(星座)、numerology(生命数字)、mbti(十六型人格问卷)、trend(人生 K 线)、fengshui(风水)、name(起名)、convert(公农历互转)。`);
|
|
10977
13273
|
}
|
|
10978
13274
|
|
|
10979
13275
|
function almanacText(r) {
|
|
@@ -11072,6 +13368,41 @@ function numerologyText(r) {
|
|
|
11072
13368
|
].join('\n');
|
|
11073
13369
|
}
|
|
11074
13370
|
|
|
13371
|
+
function mbtiText(r) {
|
|
13372
|
+
const dims = r.dims.map((d) => {
|
|
13373
|
+
const side = d.picked === d.left ? d.leftSay : d.rightSay;
|
|
13374
|
+
const pct = Math.round(d.pct * 100);
|
|
13375
|
+
return `${d.left}/${d.right} 取 ${d.picked}(${d.strength} ${pct}%,净分 ${d.sum}) ${side}`;
|
|
13376
|
+
});
|
|
13377
|
+
const p = r.profile;
|
|
13378
|
+
const stack = Array.isArray(p.stack) && p.stack.length
|
|
13379
|
+
? p.stack.map((f, i) => `${i === 0 ? '主导 ' : ''}${f.code}`).join(' → ') + `\n ${p.stack.map((f) => `${f.code}:${f.say}`).join('\n ')}`
|
|
13380
|
+
: '';
|
|
13381
|
+
return [
|
|
13382
|
+
`【十六型人格】${r.type}(${p.title})· ${p.keywords} 已答 ${r.answered}/${r.total} 题`,
|
|
13383
|
+
`一句:${p.oneLine}`,
|
|
13384
|
+
'【四维】',
|
|
13385
|
+
...dims,
|
|
13386
|
+
`【优势】${p.strengths.join(';')}`,
|
|
13387
|
+
`【留意】${p.blindspots.join(';')}`,
|
|
13388
|
+
`【课题】${p.growth}`,
|
|
13389
|
+
`【认知功能】${stack}`,
|
|
13390
|
+
`【工作】${p.work}`,
|
|
13391
|
+
`【关系】${p.love}`,
|
|
13392
|
+
`【学习】${p.study}`,
|
|
13393
|
+
`注:${r.note}`,
|
|
13394
|
+
].join('\n');
|
|
13395
|
+
}
|
|
13396
|
+
|
|
13397
|
+
function mbtiPaperText(paper) {
|
|
13398
|
+
return [
|
|
13399
|
+
`【十六型人格问卷】${paper.total} 题,每题按 1(完全不像我)到 5(很像我)打分`,
|
|
13400
|
+
...paper.questions.map((q) => `${q.no}. ${q.text}`),
|
|
13401
|
+
`请把 ${paper.total} 个分数按顺序交给 answers(如 [4,2,5,3,…]);可以跳过某些题(填 null),至少答 12 题。`,
|
|
13402
|
+
`注:${paper.note}`,
|
|
13403
|
+
].join('\n');
|
|
13404
|
+
}
|
|
13405
|
+
|
|
11075
13406
|
function trendText(r) {
|
|
11076
13407
|
const s = r.meta.strength;
|
|
11077
13408
|
const dm = r.meta.dayMaster;
|
|
@@ -11168,11 +13499,12 @@ function renderText(result) {
|
|
|
11168
13499
|
return parts.filter(Boolean).join('\n\n');
|
|
11169
13500
|
}
|
|
11170
13501
|
|
|
11171
|
-
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 };
|
|
13502
|
+
return { interpret, DIRECTIONS, DIRECTION_DEFAULT, BRIGHTNESS, flowOf, geocodeAddress, resolveAddress, buildBazi, buildLiuyao, tossLines, followup, askPrompt, pastSignals, verifyFit, rectifyBirth, crossCheck, crossText, buildAlmanac, buildZeri, buildChenggu, buildXiaoliuren, buildStar, buildNumerology, buildConvert, buildTrend, buildFengshui, buildName, parseDateTime, compute, interpretText, renderText };
|
|
11172
13503
|
})();
|
|
11173
13504
|
|
|
11174
13505
|
const Engine = __mods.index;
|
|
11175
13506
|
window.Engine = Engine;
|
|
13507
|
+
window.__MP_VER = '0.38.2';
|
|
11176
13508
|
(function () {
|
|
11177
13509
|
const NEED_ASK = { liuyao: true, meihua: true, daliuren: true, tarot: true };
|
|
11178
13510
|
const needAsk = (kind) => !!NEED_ASK[kind];
|
|
@@ -11203,25 +13535,28 @@ return { interpret, DIRECTIONS, DIRECTION_DEFAULT, BRIGHTNESS, flowOf, geocodeAd
|
|
|
11203
13535
|
|
|
11204
13536
|
(function () {
|
|
11205
13537
|
const CSS = `
|
|
11206
|
-
.pp,.mp-it{--ink:#1b1b1b;--ink2:#3f3a33;--muted:#6f6a60;--label:#8a8378;--faint:#a9a296;
|
|
13538
|
+
.pp,.mp-it,.mp-al,.mp-cg,.mp-cl,.mp-cli,.mp-kline,.mp-mb,.mp-mb-paper,.mp-nm,.mp-quick{--ink:#1b1b1b;--ink2:#3f3a33;--muted:#6f6a60;--label:#8a8378;--faint:#a9a296;
|
|
11207
13539
|
--line:#c8c1b2;--dimline:#b9b2a4;--hair:#e9e2d3;
|
|
11208
13540
|
--bg:#f6f1e6;--card:#fffdf8;--band:#fbf7ee;--hover:#f3ede1;--hover2:#ece5d6;
|
|
11209
13541
|
--tri:#f3e8cd;--soul:#fae4dc;--sel:#fceee7;--link:#f9ece0;
|
|
11210
13542
|
--red:#b3261e;--red-rgb:179,38,30;--lu:#1f6f3f;--lu-rgb:31,111,63;
|
|
11211
13543
|
--quan:#8a5a00;--quan-rgb:138,90,0;--ke:#1f4e79;--ke-rgb:31,78,121;--ji:#b3261e;
|
|
11212
13544
|
--br-good:#4c7a5c;--br-bad:#9c5b56;--on-accent:#fff;--wx-metal:#8a6b1f;
|
|
11213
|
-
--tg-bi:#4a6f8a;--tg-shi:#4c7a5c;--tg-cai:#8a6b1f;--tg-guan:#9c5b56;--tg-yin:#6d5f83
|
|
13545
|
+
--tg-bi:#4a6f8a;--tg-shi:#4c7a5c;--tg-cai:#8a6b1f;--tg-guan:#9c5b56;--tg-yin:#6d5f83;
|
|
13546
|
+
--ink3:#8a8378;--fx:"Kaiti SC",KaiTi,"STKaiti","Songti SC",serif;--sans:system-ui,-apple-system,"Microsoft YaHei",sans-serif;--kai:"Kaiti SC",KaiTi,"STKaiti",serif;
|
|
13547
|
+
--shadow:0 1px 2px rgba(35,28,18,.05),0 18px 40px -30px rgba(35,28,18,.42)}
|
|
11214
13548
|
.pp{border:1px solid var(--line);background:var(--bg);color:var(--ink);font-family:"Songti SC","SimSun","Microsoft YaHei",serif;font-size:12.5px;line-height:1.55;
|
|
11215
|
-
container-type:inline-size}
|
|
13549
|
+
border-radius:12px;overflow:hidden;box-shadow:var(--shadow);container-type:inline-size}
|
|
11216
13550
|
@media screen and (prefers-color-scheme:dark){
|
|
11217
|
-
.pp,.mp-it{--ink:#eae5d9;--ink2:#d5cfc2;--muted:#aca598;--label:#a49c8e;--faint:#928b7e;
|
|
13551
|
+
.pp,.mp-it,.mp-al,.mp-cg,.mp-cl,.mp-cli,.mp-kline,.mp-mb,.mp-mb-paper,.mp-nm,.mp-quick{--ink:#eae5d9;--ink2:#d5cfc2;--muted:#aca598;--label:#a49c8e;--faint:#928b7e;
|
|
11218
13552
|
--line:#514a3e;--dimline:#5f5849;--hair:#2f2b23;
|
|
11219
13553
|
--bg:#12110c;--card:#211f18;--band:#282419;--hover:#2e2a1f;--hover2:#383322;
|
|
11220
13554
|
--tri:#332913;--soul:#3a231c;--sel:#43271f;--link:#33241c;
|
|
11221
13555
|
--red:#f08569;--red-rgb:240,133,105;--lu:#74c795;--lu-rgb:116,199,149;
|
|
11222
13556
|
--quan:#e2a95c;--quan-rgb:226,169,92;--ke:#86bcea;--ke-rgb:134,188,234;--ji:#f08569;
|
|
11223
13557
|
--br-good:#79c79a;--br-bad:#e09a8c;--on-accent:#14130f;--wx-metal:#dcb273;
|
|
11224
|
-
--tg-bi:#93b7cf;--tg-shi:#8fbb9d;--tg-cai:#d3ae62;--tg-guan:#d98d84;--tg-yin:#b4a4d0
|
|
13558
|
+
--tg-bi:#93b7cf;--tg-shi:#8fbb9d;--tg-cai:#d3ae62;--tg-guan:#d98d84;--tg-yin:#b4a4d0;
|
|
13559
|
+
--ink3:#8b8478;--shadow:0 1px 2px rgba(0,0,0,.5),0 18px 40px -30px rgba(0,0,0,.9)}
|
|
11225
13560
|
}
|
|
11226
13561
|
.pp *{box-sizing:border-box}
|
|
11227
13562
|
.pp-grid{display:grid;grid-template-columns:repeat(4,1fr);grid-template-rows:repeat(4,minmax(150px,auto));gap:0;border:1px solid var(--line)}
|
|
@@ -11311,6 +13646,7 @@ return { interpret, DIRECTIONS, DIRECTION_DEFAULT, BRIGHTNESS, flowOf, geocodeAd
|
|
|
11311
13646
|
|
|
11312
13647
|
.pp-cell{cursor:pointer;transition:background .14s ease,box-shadow .14s ease;outline:none}
|
|
11313
13648
|
.pp-cell:hover{background:var(--hover)}
|
|
13649
|
+
.pp-cell:focus-visible{box-shadow:inset 0 0 0 2px var(--red)}
|
|
11314
13650
|
.pp-cell.pp-sel{background:var(--sel);box-shadow:inset 0 0 0 2px rgba(var(--red-rgb),.5)}
|
|
11315
13651
|
.pp-cell.pp-link{background:var(--link);box-shadow:inset 0 0 0 1.5px rgba(var(--red-rgb),.22)}
|
|
11316
13652
|
.pp-detail{display:none;border-top:1px solid var(--line);background:var(--card);padding:11px 14px 13px;font-family:system-ui,sans-serif}
|
|
@@ -11366,7 +13702,7 @@ return { interpret, DIRECTIONS, DIRECTION_DEFAULT, BRIGHTNESS, flowOf, geocodeAd
|
|
|
11366
13702
|
.mp-trig{display:inline-block;width:14px;height:10px;vertical-align:-1px;margin-right:4px;color:currentColor}
|
|
11367
13703
|
|
|
11368
13704
|
.mp-hy-wrap{display:flex;gap:22px;flex-wrap:wrap;align-items:flex-start}
|
|
11369
|
-
.mp-hy-box{border:1px solid var(--line);background:var(--card);padding:12px 16px 14px;min-width:250px}
|
|
13705
|
+
.mp-hy-box{border:1px solid var(--line);border-radius:10px;background:var(--card);padding:12px 16px 14px;min-width:250px}
|
|
11370
13706
|
.mp-hy-h{display:flex;align-items:baseline;gap:8px;margin-bottom:10px;font-family:system-ui,sans-serif}
|
|
11371
13707
|
.mp-hy-h b{color:var(--red);font-size:14px}
|
|
11372
13708
|
.mp-hy-h span{color:var(--muted);font-size:12px}
|
|
@@ -11385,7 +13721,7 @@ return { interpret, DIRECTIONS, DIRECTION_DEFAULT, BRIGHTNESS, flowOf, geocodeAd
|
|
|
11385
13721
|
.mp-mh{padding:16px}
|
|
11386
13722
|
.mp-mh-head{font-size:13px;color:var(--muted);margin-bottom:12px}
|
|
11387
13723
|
.mp-mh-main{display:flex;gap:18px;flex-wrap:wrap;align-items:flex-start}
|
|
11388
|
-
.mp-hexbox{border:1px solid var(--line);background:var(--card);padding:12px 15px 13px}
|
|
13724
|
+
.mp-hexbox{border:1px solid var(--line);border-radius:10px;background:var(--card);padding:12px 15px 13px}
|
|
11389
13725
|
.mp-hexbox.hb-mini{min-width:118px}
|
|
11390
13726
|
.mp-hexbox .hb-h{display:flex;justify-content:space-between;gap:10px;font-size:12px;letter-spacing:.14em;color:var(--muted);font-family:system-ui,sans-serif;margin-bottom:5px}
|
|
11391
13727
|
.mp-hexbox .hb-n{font-size:17px;font-weight:700;color:var(--red);margin-bottom:8px;letter-spacing:.04em}
|
|
@@ -11555,7 +13891,7 @@ return { interpret, DIRECTIONS, DIRECTION_DEFAULT, BRIGHTNESS, flowOf, geocodeAd
|
|
|
11555
13891
|
.mp-tt{padding:16px}
|
|
11556
13892
|
.mp-tt-head{font-size:12.5px;color:var(--muted);margin-bottom:12px;letter-spacing:.04em}
|
|
11557
13893
|
.mp-tt-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(172px,1fr));gap:10px}
|
|
11558
|
-
.mp-tt-card{border:1px solid var(--line);background:var(--card);padding:13px 14px;display:flex;flex-direction:column;gap:7px;min-height:168px}
|
|
13894
|
+
.mp-tt-card{border:1px solid var(--line);border-radius:10px;background:var(--card);padding:13px 14px;display:flex;flex-direction:column;gap:7px;min-height:168px}
|
|
11559
13895
|
.mp-tt-card.tt-rev{background:var(--band);border-style:dashed}
|
|
11560
13896
|
.mp-tt-pos{font-size:12px;color:var(--muted);letter-spacing:.14em}
|
|
11561
13897
|
.mp-tt-name{font-size:19px;font-weight:700;color:var(--red);letter-spacing:.04em}
|
|
@@ -11575,11 +13911,12 @@ return { interpret, DIRECTIONS, DIRECTION_DEFAULT, BRIGHTNESS, flowOf, geocodeAd
|
|
|
11575
13911
|
.mp-tt-ta{width:100%;border:1px solid var(--line);background:var(--card);color:var(--ink);padding:8px;font-size:13px;font-family:inherit;line-height:1.7;resize:vertical;outline:none}
|
|
11576
13912
|
.mp-tt-ta:focus{border-color:var(--red)}
|
|
11577
13913
|
|
|
11578
|
-
.mp-it{margin-top:14px;border:1px solid var(--line);background:var(--bg);color:var(--ink);
|
|
13914
|
+
.mp-it{margin-top:14px;border:1px solid var(--line);background:var(--bg);color:var(--ink);border-radius:12px;overflow:hidden;box-shadow:var(--shadow);
|
|
11579
13915
|
font-family:"Songti SC","SimSun","Microsoft YaHei",serif;font-size:13px;line-height:1.75}
|
|
11580
13916
|
.mp-it *{box-sizing:border-box}
|
|
11581
13917
|
.mp-it-head{display:flex;align-items:center;gap:9px;flex-wrap:wrap;width:100%;padding:12px 16px;border:none;border-bottom:1px solid var(--line);background:var(--card);color:inherit;font:inherit;font-family:inherit;text-align:left;cursor:pointer;-webkit-appearance:none;appearance:none}
|
|
11582
13918
|
.mp-it-head:hover{background:var(--band)}
|
|
13919
|
+
.mp-it-head:focus-visible{outline:2px solid var(--red);outline-offset:-3px}
|
|
11583
13920
|
.mp-it-arrow{flex:none;font-size:12px;line-height:1;color:var(--red);transition:transform .16s ease}
|
|
11584
13921
|
.mp-it.folded .mp-it-arrow{transform:rotate(-90deg)}
|
|
11585
13922
|
.mp-it.folded .mp-it-wrap{display:none}
|
|
@@ -11654,7 +13991,7 @@ return { interpret, DIRECTIONS, DIRECTION_DEFAULT, BRIGHTNESS, flowOf, geocodeAd
|
|
|
11654
13991
|
.mp-tables{border-top:1px solid var(--line);padding:12px 16px 4px;background:var(--card)}
|
|
11655
13992
|
.mp-table-wrap{margin-bottom:12px}
|
|
11656
13993
|
.mp-table-h{font-size:12px;font-weight:700;letter-spacing:.1em;color:var(--lu);margin-bottom:5px;font-family:system-ui,sans-serif}
|
|
11657
|
-
.mp-table-scroll{overflow-x:auto;border:1px solid var(--line);border-radius:
|
|
13994
|
+
.mp-table-scroll{overflow-x:auto;border:1px solid var(--line);border-radius:8px}
|
|
11658
13995
|
.mp-table{width:100%;border-collapse:collapse;font-size:12px;line-height:1.6;color:var(--ink2);font-family:system-ui,sans-serif}
|
|
11659
13996
|
.mp-table th,.mp-table td{padding:5px 9px;text-align:left;vertical-align:top;border-bottom:1px solid var(--line);white-space:nowrap}
|
|
11660
13997
|
.mp-table th{background:var(--band);color:var(--label);font-weight:600;font-size:11px;letter-spacing:.06em}
|
|
@@ -11720,6 +14057,18 @@ return { interpret, DIRECTIONS, DIRECTION_DEFAULT, BRIGHTNESS, flowOf, geocodeAd
|
|
|
11720
14057
|
.mp-qt-y b.first{color:var(--ji);border-bottom:2px solid var(--ji);padding-bottom:1px}
|
|
11721
14058
|
.mp-qt-q{margin-top:6px;font-size:12.5px;line-height:1.8;color:var(--ink2);font-family:var(--fx)}
|
|
11722
14059
|
.mp-qt-q span{display:block;font-size:11px;color:var(--ink3);font-family:var(--sans);margin-top:2px}
|
|
14060
|
+
.mp-cl{margin-top:12px;padding:10px 12px 8px;border-left:2px solid var(--quan);border-radius:0 8px 8px 0;
|
|
14061
|
+
background:color-mix(in srgb,var(--band) 72%,transparent)}
|
|
14062
|
+
.mp-cl-h{display:flex;gap:8px;align-items:baseline;font-size:12.5px;margin-bottom:7px}
|
|
14063
|
+
.mp-cl-h b{color:var(--ink);letter-spacing:.06em}
|
|
14064
|
+
.mp-cl-h span{color:var(--ink3);font-size:11.5px}
|
|
14065
|
+
.mp-cl-e{padding:8px 0;border-top:1px dashed var(--hair)}
|
|
14066
|
+
.mp-cl-e:first-of-type{border-top:0;padding-top:0}
|
|
14067
|
+
.mp-cl-t b{font-family:var(--fx);font-size:13px;color:var(--lu);font-weight:600;letter-spacing:.03em}
|
|
14068
|
+
.mp-cl-q{font-family:var(--fx);font-size:14px;line-height:2;color:var(--ink);margin-top:3px;letter-spacing:.02em;
|
|
14069
|
+
padding-left:1.05em;text-indent:-1.05em}
|
|
14070
|
+
.mp-cl-p{font-size:12px;line-height:1.9;color:var(--ink2);margin-top:3px}
|
|
14071
|
+
@media print{.mp-cl{break-inside:avoid}}
|
|
11723
14072
|
@media print{.mp-cli{break-inside:avoid}}
|
|
11724
14073
|
.mp-nm{margin:12px 16px;border:1px solid var(--line);border-radius:8px;background:var(--card);padding:12px 14px;font-family:system-ui,sans-serif}
|
|
11725
14074
|
.mp-nm-h{display:flex;align-items:baseline;gap:10px;flex-wrap:wrap;border-bottom:1px solid var(--hair);padding-bottom:8px;margin-bottom:10px}
|
|
@@ -11748,6 +14097,49 @@ return { interpret, DIRECTIONS, DIRECTION_DEFAULT, BRIGHTNESS, flowOf, geocodeAd
|
|
|
11748
14097
|
.mp-nm-c em{font-style:normal;font-size:11.5px;line-height:1.7;color:var(--muted);font-family:var(--sans)}
|
|
11749
14098
|
@media print{.mp-nm{break-inside:avoid}}
|
|
11750
14099
|
.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)}
|
|
14100
|
+
.mp-mb{margin:12px 16px;border:1px solid var(--line);border-radius:12px;background:var(--card);box-shadow:var(--shadow);overflow:hidden;font-family:var(--sans)}
|
|
14101
|
+
.mp-mb-h{display:flex;flex-direction:row;align-items:center;gap:14px;flex-wrap:wrap;padding:15px 18px 14px;
|
|
14102
|
+
background:linear-gradient(135deg,var(--sel),var(--band) 64%,var(--card));border-bottom:1px solid var(--hair)}
|
|
14103
|
+
.mp-mb-code{font-family:var(--fx);font-size:32px;font-weight:700;line-height:1;letter-spacing:.12em;color:var(--ink)}
|
|
14104
|
+
.mp-mb-meta{display:flex;flex-direction:column;gap:3px;min-width:0}
|
|
14105
|
+
.mp-mb-meta b{font-size:14.5px;font-weight:600;color:var(--ink);letter-spacing:.04em}
|
|
14106
|
+
.mp-mb-meta i{font-style:normal;font-size:12px;line-height:1.5;color:var(--muted)}
|
|
14107
|
+
.mp-mb-count{margin-left:auto;padding:3px 10px;border:1px solid var(--line);border-radius:999px;background:var(--card);color:var(--muted);font-size:11.5px;white-space:nowrap}
|
|
14108
|
+
.mp-mb-body{padding:14px 18px 16px}
|
|
14109
|
+
.mp-mb-dims{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:10px}
|
|
14110
|
+
.mp-mb-dim{border:1px solid var(--hair);border-radius:10px;background:var(--band);padding:9px 11px 10px}
|
|
14111
|
+
.mp-mb-dh{display:flex;align-items:baseline;gap:6px;font-size:11.5px;color:var(--muted)}
|
|
14112
|
+
.mp-mb-dh b{font-family:var(--fx);font-size:17px;font-weight:600;line-height:1.1;letter-spacing:.08em;color:var(--faint)}
|
|
14113
|
+
.mp-mb-dh b.on{color:var(--ink)}
|
|
14114
|
+
.mp-mb-dh em{font-style:normal;margin:0 auto;font-size:11.5px;letter-spacing:.06em}
|
|
14115
|
+
.mp-mb-bar{position:relative;height:7px;border-radius:4px;background:var(--hair);margin:7px 0 6px;overflow:hidden}
|
|
14116
|
+
.mp-mb-bar::after{content:"";position:absolute;left:50%;top:-1px;bottom:-1px;width:1px;background:color-mix(in srgb,var(--line) 70%,transparent)}
|
|
14117
|
+
.mp-mb-bar em{position:absolute;top:0;bottom:0;background:linear-gradient(90deg,var(--quan),color-mix(in srgb,var(--quan) 55%,var(--card)));border-radius:4px}
|
|
14118
|
+
.mp-mb-bar.l em{left:0}
|
|
14119
|
+
.mp-mb-bar.r em{right:0;background:linear-gradient(270deg,var(--quan),color-mix(in srgb,var(--quan) 55%,var(--card)))}
|
|
14120
|
+
.mp-mb-df{font-size:11.5px;color:var(--ink2);font-variant-numeric:tabular-nums}
|
|
14121
|
+
.mp-mb-ds{margin-top:2px;font-size:11.5px;line-height:1.7;color:var(--muted)}
|
|
14122
|
+
.mp-mb-sec{margin-top:11px;font-size:12.5px;line-height:1.85;color:var(--ink2)}
|
|
14123
|
+
.mp-mb-sec em{display:inline-block;margin-right:7px;padding:0 7px;border:1px solid var(--hair);border-radius:5px;background:var(--band);color:var(--muted);font-size:11px;font-style:normal;letter-spacing:.08em}
|
|
14124
|
+
.mp-mb-two{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:10px;margin-top:11px}
|
|
14125
|
+
.mp-mb-two>div{border:1px solid var(--hair);border-left:3px solid var(--br-good);border-radius:8px;background:var(--card);padding:8px 10px;font-size:12.5px;line-height:1.8;color:var(--ink2)}
|
|
14126
|
+
.mp-mb-two>div+div{border-left-color:var(--br-bad)}
|
|
14127
|
+
.mp-mb-two b{display:block;margin-bottom:2px;font-size:11.5px;font-weight:600;letter-spacing:.08em;color:var(--br-good)}
|
|
14128
|
+
.mp-mb-two>div+div b{color:var(--br-bad)}
|
|
14129
|
+
.mp-mb-fn{display:flex;flex-wrap:wrap;gap:6px;margin-top:7px}
|
|
14130
|
+
.mp-mb-fn span{font-size:11.5px;border:1px solid var(--line);border-radius:999px;background:var(--card);padding:2px 9px;color:var(--ink2)}
|
|
14131
|
+
.mp-mb-fn span.lead{border-color:var(--quan);background:color-mix(in srgb,var(--quan) 9%,var(--card));color:var(--quan);font-weight:600}
|
|
14132
|
+
.mp-mb-fn span b{font-weight:600;margin-right:4px}
|
|
14133
|
+
.mp-mb-note{margin:12px 18px 14px;padding-top:10px;font-size:11px;line-height:1.7;color:var(--muted);border-top:1px solid var(--hair)}
|
|
14134
|
+
.mp-mb-paper{margin:12px 16px;border:1px solid var(--line);border-radius:12px;background:var(--card);box-shadow:var(--shadow);overflow:hidden;font-family:var(--sans)}
|
|
14135
|
+
.mp-mb-paper ol{counter-reset:q;display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:4px 20px;
|
|
14136
|
+
margin:0;padding:12px 18px 14px;list-style:none;font-size:12.5px;line-height:1.7;color:var(--ink2)}
|
|
14137
|
+
.mp-mb-paper li{counter-increment:q;position:relative;padding:0 0 6px 26px;border-bottom:1px dashed var(--hair)}
|
|
14138
|
+
.mp-mb-paper li::before{content:counter(q);position:absolute;left:0;top:1px;display:flex;align-items:center;justify-content:center;
|
|
14139
|
+
width:19px;height:19px;border:1px solid var(--hair);border-radius:50%;background:var(--band);color:var(--muted);font-size:10.5px;font-variant-numeric:tabular-nums}
|
|
14140
|
+
.mp-mb-paper .mp-mb-note{margin:0 18px 14px}
|
|
14141
|
+
@media (max-width:640px){.mp-mb-dims,.mp-mb-two,.mp-mb-paper ol{grid-template-columns:1fr}.mp-mb-code{font-size:26px}.mp-mb-body{padding:12px 14px 14px}.mp-mb-h{padding:13px 14px 12px}}
|
|
14142
|
+
@media print{.mp-mb{break-inside:avoid}}
|
|
11751
14143
|
.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}
|
|
11752
14144
|
.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}
|
|
11753
14145
|
.mp-al-h b{font-size:18px;color:var(--ink);font-weight:700;font-variant-numeric:tabular-nums}
|
|
@@ -12130,6 +14522,25 @@ return { interpret, DIRECTIONS, DIRECTION_DEFAULT, BRIGHTNESS, flowOf, geocodeAd
|
|
|
12130
14522
|
? `<div class="pp-chips">${r.daxianList.slice(0, 8).map((d) => `<span class="pp-chip" title="${esc(`${d.ganzhi} 宫干四化:` + d.mutagenHits.map((m) => `${m.star}化${m.type}→${m.palace || '未上盘'}`).join('、'))}">${d.branch} ${d.ages[0]}-${d.ages[1]}</span>`).join('')}</div>` : '';
|
|
12131
14523
|
const lnHit = ln && ln.mutagenHits && ln.mutagenHits.length
|
|
12132
14524
|
? `<div class="pp-chips">${ln.mutagenHits.map((m) => `<span class="pp-chip ${m.type === '忌' ? 'warn' : m.type === '禄' ? 'ok' : ''}">${m.star}化${m.type}→${m.palace || '未上盘'}</span>`).join('')}</div>` : '';
|
|
14525
|
+
const flyHTML = r.flyChains ? (() => {
|
|
14526
|
+
const chips = ['禄', '权', '科', '忌'].map((t) => {
|
|
14527
|
+
const ch = r.flyChains[t];
|
|
14528
|
+
if (!ch || !ch.steps.length) return '';
|
|
14529
|
+
const path = ch.path.map((p) => String(p).replace(/宫$/, '')).join('→');
|
|
14530
|
+
const tip = ch.steps.map((s) => `${s.from}(${s.fromStem})化${t}${s.star}→${s.to}`).join(';');
|
|
14531
|
+
const cls = t === '忌' ? 'warn' : t === '禄' ? 'ok' : '';
|
|
14532
|
+
return `<span class="pp-chip ${cls}" title="${esc(tip)}">飞${t} ${esc(path)}${ch.closed ? '↺' : ''}</span>`;
|
|
14533
|
+
}).join('');
|
|
14534
|
+
return chips ? `<div class="pp-chips">${chips}</div>` : '';
|
|
14535
|
+
})() : '';
|
|
14536
|
+
const flyCompositeHTML = r.flyComposite && Array.isArray(r.flyComposite.labels) && r.flyComposite.labels.length
|
|
14537
|
+
? `<div class="pp-chips">${r.flyComposite.labels.map((l) => {
|
|
14538
|
+
const cls = /忌/.test(l) ? 'warn' : /自化/.test(l) ? '' : 'ok';
|
|
14539
|
+
const palaceOf = (x) => String(x).replace(/^.*?会/, '').replace(/^禄忌同宫/, '').replace(/自化$/, '');
|
|
14540
|
+
const hit = (r.flyComposite.targets || []).find((t) => t.palace === palaceOf(l));
|
|
14541
|
+
const tip = hit ? hit.incoming.map((x) => `${x.from}化${x.type}${x.star}`).join('、') : r.flyComposite.note;
|
|
14542
|
+
return `<span class="pp-chip ${cls}" title="${esc(tip)}">三方四正 ${esc(l)}</span>`;
|
|
14543
|
+
}).join('')}</div>` : '';
|
|
12133
14544
|
|
|
12134
14545
|
const fl = r.flow;
|
|
12135
14546
|
const flowHTML = fl ? (() => {
|
|
@@ -12147,7 +14558,6 @@ return { interpret, DIRECTIONS, DIRECTION_DEFAULT, BRIGHTNESS, flowOf, geocodeAd
|
|
|
12147
14558
|
${row(`流时 ${BR[fl.hour.hourIndex]}时`, fl.hour)}
|
|
12148
14559
|
</div>`;
|
|
12149
14560
|
})() : '';
|
|
12150
|
-
|
|
12151
14561
|
pp._zw = r;
|
|
12152
14562
|
return `<div class="pp">
|
|
12153
14563
|
<input type="radio" name="ppm" id="ppm-ben" class="pp-r" checked>
|
|
@@ -12160,7 +14570,7 @@ return { interpret, DIRECTIONS, DIRECTION_DEFAULT, BRIGHTNESS, flowOf, geocodeAd
|
|
|
12160
14570
|
${body('ben', soulIdx, 'ben')}
|
|
12161
14571
|
${body('da', dxIdx, 'da')}
|
|
12162
14572
|
${body('ln', lnIdx, 'ln')}
|
|
12163
|
-
</div>${flowHTML}${chips}${pats}${dxs}${lnHit}`;
|
|
14573
|
+
</div>${flowHTML}${chips}${flyHTML}${flyCompositeHTML}${pats}${dxs}${lnHit}`;
|
|
12164
14574
|
};
|
|
12165
14575
|
|
|
12166
14576
|
function starLine(list) {
|
|
@@ -12319,9 +14729,52 @@ return { interpret, DIRECTIONS, DIRECTION_DEFAULT, BRIGHTNESS, flowOf, geocodeAd
|
|
|
12319
14729
|
? box(`变卦 ${r.bian.name}`, `${r.bian.palace} · ${r.bian.palaceElement}`, r.bian, r.bian.lines)
|
|
12320
14730
|
: `<div class="mp-hy-box"><div class="mp-hy-h"><b>六爻安静</b><span>无动爻,不取变卦</span></div>
|
|
12321
14731
|
<div class="pp-dim" style="font-size:12px;line-height:1.9">断卦以本卦卦辞与世应生克为主。</div></div>`;
|
|
14732
|
+
const bodyLabels = (r.body && Array.isArray(r.body.labels)) ? r.body.labels : [];
|
|
14733
|
+
const bodyRow = bodyLabels.length
|
|
14734
|
+
? `<div class="pp-chips">${bodyLabels.map((l) => {
|
|
14735
|
+
const cls = /伏吟/.test(l) ? 'warn' : /反吟/.test(l) ? 'warn' : /化退神/.test(l) ? 'warn' : /六冲|散/.test(l) ? '' : 'ok';
|
|
14736
|
+
return `<span class="pp-chip ${cls}">${esc(l)}</span>`;
|
|
14737
|
+
}).join('')}</div>`
|
|
14738
|
+
: `<div class="pp-chips"><span class="pp-chip">卦体无六冲、六合、伏吟、反吟</span></div>`;
|
|
14739
|
+
const ug = r.useGod && r.useGod.liuqin ? r.useGod : null;
|
|
14740
|
+
const useRow = ug
|
|
14741
|
+
? `<div class="pp-chips">${ug.labels.map((l) => {
|
|
14742
|
+
const cls = /空亡|退神|受克|泄气|不上卦/.test(l) ? 'warn'
|
|
14743
|
+
: /持世|化进|六合|得飞神生/.test(l) ? 'ok' : '';
|
|
14744
|
+
return `<span class="pp-chip ${cls}">${esc(l)}</span>`;
|
|
14745
|
+
}).join('')}</div>`
|
|
14746
|
+
: `<div class="pp-chips"><span class="pp-chip">用神未取(未指明所问之事)</span></div>`;
|
|
14747
|
+
const st = r.useGodStrength && Array.isArray(r.useGodStrength.labels) ? r.useGodStrength : null;
|
|
14748
|
+
const strengthRow = st && st.labels.length
|
|
14749
|
+
? `<div class="pp-chips">${st.labels.map((l) => {
|
|
14750
|
+
const cls = /死|囚|月破|受日辰克|泄|耗/.test(l) ? 'warn'
|
|
14751
|
+
: /旺|相|得日辰生|比和/.test(l) ? 'ok' : '';
|
|
14752
|
+
return `<span class="pp-chip ${cls}">${esc(l)}</span>`;
|
|
14753
|
+
}).join('')}</div>`
|
|
14754
|
+
: '';
|
|
14755
|
+
const jp = r.jinTuiPower && Array.isArray(r.jinTuiPower.labels) ? r.jinTuiPower : null;
|
|
14756
|
+
const jinRow = jp && jp.labels.length
|
|
14757
|
+
? `<div class="pp-chips">${jp.labels.map((l) => {
|
|
14758
|
+
const cls = /后劲足|退得缓/.test(l) ? 'ok' : /有限|进得虚|退得实|月破|未定/.test(l) ? 'warn' : '';
|
|
14759
|
+
return `<span class="pp-chip ${cls}">${esc(l)}</span>`;
|
|
14760
|
+
}).join('')}</div>`
|
|
14761
|
+
: '';
|
|
14762
|
+
const hs = r.hexStrength && Array.isArray(r.hexStrength.labels) ? r.hexStrength : null;
|
|
14763
|
+
const hexRow = hs && hs.labels.length
|
|
14764
|
+
? `<div class="pp-chips">${hs.labels.map((l) => {
|
|
14765
|
+
const cls = /死|囚|月破|冲空/.test(l) ? 'warn'
|
|
14766
|
+
: /旺|相/.test(l) ? 'ok' : '';
|
|
14767
|
+
return `<span class="pp-chip ${cls}">${esc(l)}</span>`;
|
|
14768
|
+
}).join('')}</div>`
|
|
14769
|
+
: '';
|
|
12322
14770
|
return `<div class="pp" style="padding:14px">
|
|
12323
14771
|
<div class="mp-mh-head">起卦 ${r.cast.notation.join('、')}(自下而上) 日辰 ${r.dayGanZhi.name}</div>
|
|
12324
14772
|
<div class="mp-hy-wrap">${ben}${bian}</div>
|
|
14773
|
+
${bodyRow}
|
|
14774
|
+
${useRow}
|
|
14775
|
+
${strengthRow}
|
|
14776
|
+
${jinRow}
|
|
14777
|
+
${hexRow}
|
|
12325
14778
|
</div>`;
|
|
12326
14779
|
};
|
|
12327
14780
|
|
|
@@ -12487,6 +14940,12 @@ return { interpret, DIRECTIONS, DIRECTION_DEFAULT, BRIGHTNESS, flowOf, geocodeAd
|
|
|
12487
14940
|
pp.qimenFactsHTML = function (r) {
|
|
12488
14941
|
if (!r || !r.palaces) return '';
|
|
12489
14942
|
const row = (k, v) => `<div class="relation__row"><dt>${esc(k)}</dt><dd>${esc(v)}</dd></div>`;
|
|
14943
|
+
const stateCell = (g) => {
|
|
14944
|
+
if (!g) return '—';
|
|
14945
|
+
const parts = ['旺', '相', '休', '囚', '死'].filter((k) => Array.isArray(g[k]) && g[k].length)
|
|
14946
|
+
.map((k) => `${k} ${g[k].join('、')}`);
|
|
14947
|
+
return parts.join(';') || '—';
|
|
14948
|
+
};
|
|
12490
14949
|
const rows = [
|
|
12491
14950
|
['局数', `${r.ju}${r.yuan ? `(${r.yuan})` : ''}`],
|
|
12492
14951
|
['节气', `${r.jieqi || '—'}${r.jieqiTime ? `(${r.jieqiTime})` : ''}`],
|
|
@@ -12498,6 +14957,24 @@ return { interpret, DIRECTIONS, DIRECTION_DEFAULT, BRIGHTNESS, flowOf, geocodeAd
|
|
|
12498
14957
|
['驿马', r.ma && r.ma.zhi ? `${r.ma.zhi}${r.ma.gong ? `(${r.ma.gong}宫)` : ''}` : '—'],
|
|
12499
14958
|
['换局规则', r.juMethodNote || r.juMethod || '—'],
|
|
12500
14959
|
['晚子时', r.lateZiHourMode === 'next-day' ? '23:00 后归次日' : '23:00 后仍归当日'],
|
|
14960
|
+
['击刑', (r.conditions && r.conditions.jiXing && r.conditions.jiXing.length)
|
|
14961
|
+
? r.conditions.jiXing.map((x) => `${x.palace}宫${x.stem}`).join('、') : '本盘无'],
|
|
14962
|
+
['入墓', (r.conditions && r.conditions.ruMu && r.conditions.ruMu.length)
|
|
14963
|
+
? r.conditions.ruMu.map((x) => `${x.palace}宫${x.stem}`).join('、') : '本盘无'],
|
|
14964
|
+
['月令', r.month && r.month.branch ? `${r.month.branch}(${r.month.element})` : '—'],
|
|
14965
|
+
['门旺衰', stateCell(r.states && r.states.gate)],
|
|
14966
|
+
['星旺衰', stateCell(r.states && r.states.star)],
|
|
14967
|
+
['干旺衰', stateCell(r.states && r.states.stem)],
|
|
14968
|
+
['干宫生克', (() => {
|
|
14969
|
+
const order = ['干克宫', '宫克干', '干生宫', '宫生干', '比和'];
|
|
14970
|
+
const g = {};
|
|
14971
|
+
for (const p of r.palaces || []) {
|
|
14972
|
+
const rel = p.stemRelation || null;
|
|
14973
|
+
if (!rel || rel.type === 'unknown' || !p.tianPan) continue;
|
|
14974
|
+
(g[rel.type] = g[rel.type] || []).push(p.tianPan);
|
|
14975
|
+
}
|
|
14976
|
+
return order.filter((k) => g[k]).map((k) => k + ' ' + g[k].join('、')).join(';') || '—';
|
|
14977
|
+
})()],
|
|
12501
14978
|
];
|
|
12502
14979
|
return `<dl class="relation mp-qm-facts" aria-label="奇门盘面事实">${rows.map(([k, v]) => row(k, v)).join('')}</dl>`;
|
|
12503
14980
|
};
|
|
@@ -12521,6 +14998,7 @@ return { interpret, DIRECTIONS, DIRECTION_DEFAULT, BRIGHTNESS, flowOf, geocodeAd
|
|
|
12521
14998
|
<div class="pp-qm-mid"><span class="tp">${p.tianPan || ''}</span><span class="star">${p.star || ''}</span></div>
|
|
12522
14999
|
<div class="pp-qm-mid"><span class="dp">${p.diPan || ''}</span><span class="gate">${p.gate || ''}</span></div>
|
|
12523
15000
|
<div class="pp-qm-bot"><span>${p.anGan || ''}</span><span class="no">${g}</span></div>
|
|
15001
|
+
<div class="pp-qm-bot"><span class="dim">${(p.stemRelation && p.stemRelation.type !== 'unknown') ? p.stemRelation.type : ''}</span><span class="dim">${p.stemState || ''}</span></div>
|
|
12524
15002
|
</div>`;
|
|
12525
15003
|
};
|
|
12526
15004
|
return `<div class="pp mp-qm">
|
|
@@ -12657,7 +15135,7 @@ return { interpret, DIRECTIONS, DIRECTION_DEFAULT, BRIGHTNESS, flowOf, geocodeAd
|
|
|
12657
15135
|
const tip = `<div class="cv-tip">曲线只呈现引擎已给出的行运评分(${VMIN} ~ ${VMAX}),不预测具体事件;档位与依据见下方「大运 / 流年」各节。悬停看逐年详情。</div>`;
|
|
12658
15136
|
|
|
12659
15137
|
return `<div class="mp-curve">
|
|
12660
|
-
<div class="mp-curve-h"><b>人生运势曲线</b><span>${a0}–${a1} 岁 ${r.dayun.rule},${startAge}
|
|
15138
|
+
<div class="mp-curve-h"><b>人生运势曲线</b><span>${a0}–${a1} 岁 ${r.dayun.rule},${startAge} 岁起运${(r.dayun.jiao && r.dayun.jiao.at) ? `,交运 ${r.dayun.jiao.at}` : ''}</span></div>
|
|
12661
15139
|
<svg viewBox="0 0 ${W} ${H}" role="img" aria-label="人生运势曲线:${a0} 到 ${a1} 岁的大运与流年评分走势">
|
|
12662
15140
|
${bands}${axes}${dyFill}${dyLine}${lnLine}${dots}${ticks.join('')}${yLabels}${mark}${markLo}
|
|
12663
15141
|
</svg>
|
|
@@ -12981,12 +15459,17 @@ return { interpret, DIRECTIONS, DIRECTION_DEFAULT, BRIGHTNESS, flowOf, geocodeAd
|
|
|
12981
15459
|
|
|
12982
15460
|
const dy = r.dayun.list.map((d) => {
|
|
12983
15461
|
const lk = d.luck || null;
|
|
12984
|
-
return `<span class="pp-chip ${lk ? tierCls(lk.tier) : ''}" title="${esc(lk ? `${lk.tier} ${lk.score}|${(lk.reasons || []).join(';')}` : '')}">${d.startAge} ${d.ganzhi}${(d.relations && d.relations.length) ? ` <i class="pp-drel">${d.relations.join('')}</i>` : ''}${lk ? ` ${lk.tier}` : ''}</span>`;
|
|
15462
|
+
return `<span class="pp-chip ${lk ? tierCls(lk.tier) : ''}" title="${esc(`${d.fromDate ? `${d.fromDate} 交运;` : ''}${lk ? `${lk.tier} ${lk.score}|${(lk.reasons || []).join(';')}` : ''}`)}">${d.startAge} ${d.ganzhi}${(d.relations && d.relations.length) ? ` <i class="pp-drel">${d.relations.join('')}</i>` : ''}${lk ? ` ${lk.tier}` : ''}</span>`;
|
|
12985
15463
|
}).join('');
|
|
12986
15464
|
const ln = (r.liunian && r.liunian.length) ? `<div class="pp-chips">${r.liunian.slice(0, 8).map((l) => {
|
|
12987
15465
|
const lk = l.luck || null;
|
|
12988
|
-
|
|
15466
|
+
const sy = (l.suiyun && Array.isArray(l.suiyun.signals)) ? l.suiyun.signals : [];
|
|
15467
|
+
const syTip = sy.length ? `|${sy.map((x) => x.detail).join(';')}` : '';
|
|
15468
|
+
return `<span class="pp-chip ${lk ? tierCls(lk.tier) : ''}" title="${esc(lk ? `${lk.tier} ${lk.score}|${(lk.reasons || []).join(';')}${syTip}` : syTip.replace(/^|/, ''))}">${l.year} ${l.ganzhi}${lk ? ` ${lk.tier}` : ''}</span>`;
|
|
12989
15469
|
}).join('')}</div>` : '';
|
|
15470
|
+
const sy = (r.liunian || []).filter((l) => l.suiyun && Array.isArray(l.suiyun.signals) && l.suiyun.signals.length);
|
|
15471
|
+
const syRow = sy.length ? `<div class="pp-tl pp-dim">岁运提示(只标干支变动,不判吉凶)</div><div class="pp-chips">${sy.map((l) =>
|
|
15472
|
+
`<span class="pp-chip" title="${esc(`${l.suiyun.signals.map((x) => x.detail).join(';')}|${l.suiyun.note || ''}`)}">${l.year} ${esc(l.suiyun.signals.map((x) => `${x.type}${x.type.startsWith('流年') && x.target ? `·${x.target}` : ''}`).join('/'))}</span>`).join('')}</div>` : '';
|
|
12990
15473
|
const str = r.strength ? `<div class="pp-str">日主强弱:<b>${r.strength.level}</b>${r.strength.score} <span class="pp-dim">${r.strength.detail}</span></div>` : '';
|
|
12991
15474
|
const ssGroups = (r.shensha && r.shensha.groups) || [];
|
|
12992
15475
|
const ssx = ssGroups.length ? `
|
|
@@ -13003,16 +15486,24 @@ return { interpret, DIRECTIONS, DIRECTION_DEFAULT, BRIGHTNESS, flowOf, geocodeAd
|
|
|
13003
15486
|
${sect('格局', gj)}
|
|
13004
15487
|
${sect('用神', ys)}
|
|
13005
15488
|
${cliCard}
|
|
15489
|
+
${(Array.isArray(r.classics) && r.classics.length) ? `<section class="mp-cl" aria-label="古籍原文">
|
|
15490
|
+
<div class="mp-cl-h"><b>古籍原文</b><span>照录通行本,释义为白话自撰</span></div>
|
|
15491
|
+
${r.classics.map((e) => `<div class="mp-cl-e">
|
|
15492
|
+
<div class="mp-cl-t"><b>${esc(({ ziping: '子平真诠', ditian: '滴天髓', sanming: '三命通会' }[e.book] || e.book) + '·' + e.chapter)}</b></div>
|
|
15493
|
+
<div class="mp-cl-q">「${esc(e.quote)}」</div>
|
|
15494
|
+
<div class="mp-cl-p">${esc(e.plain)}</div>
|
|
15495
|
+
</div>`).join('')}
|
|
15496
|
+
</section>` : ''}
|
|
13006
15497
|
${sect('五行与十神', `<div class="pp-chips">${wx}</div>${gods}`)}
|
|
13007
15498
|
${sect('大运', `${pp.curveHTML(r)}<div class="pp-chips">${dy}</div>`)}
|
|
13008
|
-
${ln ? sect('流年', ln) : ''}
|
|
15499
|
+
${ln ? sect('流年', ln + syRow) : ''}
|
|
13009
15500
|
${r.palaces ? sect('胎元与命身宫', `<div class="pp-chips">
|
|
13010
15501
|
<span class="pp-chip" title="${r.palaces.taiyuan.note}">胎元 ${r.palaces.taiyuan.ganzhi}</span>
|
|
13011
15502
|
<span class="pp-chip" title="${r.palaces.minggong.note}">命宫 ${r.palaces.minggong.ganzhi}</span>
|
|
13012
15503
|
<span class="pp-chip" title="${r.palaces.shengong.note}">身宫 ${r.palaces.shengong.ganzhi}</span>
|
|
13013
15504
|
</div>`) : ''}
|
|
13014
15505
|
${ssx}
|
|
13015
|
-
<div style="margin-top:8px;font-size:12px;color:var(--muted)">上一节 ${r.jieqi.previous.name} ${r.jieqi.previous.time} 下一节 ${r.jieqi.next.name} ${r.jieqi.next.time} ${r.dayun.rule},${r.dayun.startAge.years}
|
|
15506
|
+
<div style="margin-top:8px;font-size:12px;color:var(--muted)">上一节 ${r.jieqi.previous.name} ${r.jieqi.previous.time} 下一节 ${r.jieqi.next.name} ${r.jieqi.next.time} ${r.dayun.rule},${r.dayun.startAge.years}岁起运${(r.dayun.jiao && r.dayun.jiao.at) ? `(交运 ${r.dayun.jiao.at},${r.dayun.jiao.frame})` : ''}</div>
|
|
13016
15507
|
</div>`;
|
|
13017
15508
|
};
|
|
13018
15509
|
|
|
@@ -13137,11 +15628,62 @@ return { interpret, DIRECTIONS, DIRECTION_DEFAULT, BRIGHTNESS, flowOf, geocodeAd
|
|
|
13137
15628
|
</section>`;
|
|
13138
15629
|
};
|
|
13139
15630
|
|
|
15631
|
+
pp.mbtiHTML = function (r) {
|
|
15632
|
+
if (!r) return '';
|
|
15633
|
+
if (r.needAnswers && Array.isArray(r.questions)) {
|
|
15634
|
+
const items = r.questions.map((q) => `<li>${esc(q.text)}</li>`).join('');
|
|
15635
|
+
return `<section class="mp-mb-paper" aria-label="十六型人格问卷">
|
|
15636
|
+
<div class="mp-mb-h">
|
|
15637
|
+
<span class="mp-mb-meta"><b>十六型人格问卷</b><i>${r.total} 题 · 每题 1 完全不像 / 5 很像我</i></span>
|
|
15638
|
+
<span class="mp-mb-count">填完分数再看结果</span>
|
|
15639
|
+
</div>
|
|
15640
|
+
<ol>${items}</ol>
|
|
15641
|
+
<div class="mp-mb-note">${esc(r.note || '')}</div>
|
|
15642
|
+
</section>`;
|
|
15643
|
+
}
|
|
15644
|
+
const dims = (r.dims || []).map((d) => {
|
|
15645
|
+
const pct = Math.round((d.pct || 0) * 100);
|
|
15646
|
+
const leftOn = d.picked === d.left;
|
|
15647
|
+
const width = Math.max(2, pct);
|
|
15648
|
+
const say = leftOn ? d.leftSay : d.rightSay;
|
|
15649
|
+
return `<div class="mp-mb-dim">
|
|
15650
|
+
<div class="mp-mb-dh"><b class="${leftOn ? 'on' : ''}">${esc(d.left)}</b><em>${esc(d.name)}</em><b class="${leftOn ? '' : 'on'}">${esc(d.right)}</b></div>
|
|
15651
|
+
<div class="mp-mb-bar ${leftOn ? 'l' : 'r'}"><em style="width:${width}%"></em></div>
|
|
15652
|
+
<div class="mp-mb-df">取 ${esc(d.picked)} · ${esc(d.strength)} ${pct}%</div>
|
|
15653
|
+
<div class="mp-mb-ds">${esc(say)}</div>
|
|
15654
|
+
</div>`;
|
|
15655
|
+
}).join('');
|
|
15656
|
+
const p = r.profile || {};
|
|
15657
|
+
const stack = (p.stack || []).map((f, i) => `<span class="${i === 0 ? 'lead' : ''}"><b>${esc(f.code)}</b>${esc(f.say)}</span>`).join('');
|
|
15658
|
+
return `<section class="mp-mb" aria-label="十六型人格结果">
|
|
15659
|
+
<div class="mp-mb-h">
|
|
15660
|
+
<span class="mp-mb-code">${esc(r.type || '')}</span>
|
|
15661
|
+
<span class="mp-mb-meta"><b>${esc(p.title || '')}</b><i>${esc(p.keywords || '')}</i></span>
|
|
15662
|
+
<span class="mp-mb-count">已答 ${r.answered || 0}/${r.total || 0} 题</span>
|
|
15663
|
+
</div>
|
|
15664
|
+
<div class="mp-mb-body">
|
|
15665
|
+
<div class="mp-mb-dims">${dims}</div>
|
|
15666
|
+
<div class="mp-mb-sec"><em>一句</em>${esc(p.oneLine || '')}</div>
|
|
15667
|
+
<div class="mp-mb-two">
|
|
15668
|
+
<div><b>优势</b>${(p.strengths || []).map((s) => esc(s)).join(';')}</div>
|
|
15669
|
+
<div><b>留意</b>${(p.blindspots || []).map((s) => esc(s)).join(';')}</div>
|
|
15670
|
+
</div>
|
|
15671
|
+
${stack ? `<div class="mp-mb-sec"><em>认知功能</em>主导 ${esc((p.stack[0] || {}).code || '')} → 依次展开</div><div class="mp-mb-fn">${stack}</div>` : ''}
|
|
15672
|
+
<div class="mp-mb-sec"><em>工作</em>${esc(p.work || '')}</div>
|
|
15673
|
+
<div class="mp-mb-sec"><em>关系</em>${esc(p.love || '')}</div>
|
|
15674
|
+
<div class="mp-mb-sec"><em>学习</em>${esc(p.study || '')}</div>
|
|
15675
|
+
<div class="mp-mb-sec"><em>课题</em>${esc(p.growth || '')}</div>
|
|
15676
|
+
</div>
|
|
15677
|
+
<div class="mp-mb-note">${esc(r.note || '')}</div>
|
|
15678
|
+
</section>`;
|
|
15679
|
+
};
|
|
15680
|
+
|
|
13140
15681
|
pp.quickHTML = function (r) {
|
|
13141
15682
|
if (!r) return '';
|
|
13142
15683
|
const LABEL = {
|
|
13143
15684
|
almanac: '黄历', zeri: '择日', chenggu: '称骨', xiaoliuren: '小六壬',
|
|
13144
15685
|
star: '星座', numerology: '生命数字', trend: '人生 K 线', fengshui: '风水', name: '起名', convert: '公农历转换',
|
|
15686
|
+
mbti: '十六型人格',
|
|
13145
15687
|
};
|
|
13146
15688
|
const title = LABEL[r.system] || '速查';
|
|
13147
15689
|
const text = r.summary || '';
|
|
@@ -13289,7 +15831,8 @@ const PP = window.__PP;
|
|
|
13289
15831
|
const CSS = `
|
|
13290
15832
|
.mp-wrap{height:100%;overflow:auto;padding:20px 24px 40px;color:var(--dsw-alias-label-primary);font-size:14px}
|
|
13291
15833
|
.mp-wrap>*{max-width:940px;margin-left:auto;margin-right:auto}
|
|
13292
|
-
.mp-panel{background:var(--dsw-alias-bg-layer-2);border:1px solid var(--dsw-alias-border-l1);border-radius:
|
|
15834
|
+
.mp-panel{background:linear-gradient(180deg,var(--dsw-alias-bg-layer-2),color-mix(in srgb,var(--dsw-alias-bg-layer-2) 88%,var(--dsw-alias-bg-layer-1)));border:1px solid var(--dsw-alias-border-l1);border-radius:16px;padding:18px 20px 16px;margin-bottom:16px;
|
|
15835
|
+
box-shadow:0 1px 2px color-mix(in srgb,var(--dsw-alias-label-primary) 5%,transparent),0 16px 34px -30px color-mix(in srgb,var(--dsw-alias-label-primary) 45%,transparent)}
|
|
13293
15836
|
.mp-row{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:12px 14px;align-items:end}
|
|
13294
15837
|
.mp-lbl{display:block;height:18px;line-height:18px;font-size:12.5px;color:var(--dsw-alias-label-secondary);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
|
|
13295
15838
|
.mp-checks{display:flex;gap:20px;flex-wrap:wrap;margin-top:13px;font-size:12.5px;color:var(--dsw-alias-label-secondary)}
|
|
@@ -13297,17 +15840,50 @@ const CSS = `
|
|
|
13297
15840
|
.mp-askblock{margin-top:14px;display:flex;flex-direction:column;gap:5px}
|
|
13298
15841
|
.mp-actions{display:flex;justify-content:flex-end;gap:8px;margin-top:14px}
|
|
13299
15842
|
.mp-tabs{display:inline-flex;gap:4px;margin-bottom:14px;flex-wrap:wrap;padding:4px;background:var(--dsw-alias-bg-layer-2);border:1px solid var(--dsw-alias-border-l1);border-radius:11px;width:100%;max-width:940px}
|
|
13300
|
-
.mp-tab{padding:7px 15px;border-radius:
|
|
13301
|
-
.mp-tab:hover{background:var(--dsw-alias-bg-layer-
|
|
13302
|
-
.mp-tab.on{background:var(--dsw-alias-brand-primary);color:#fff}
|
|
15843
|
+
.mp-tab{padding:7px 15px;border-radius:9px;border:none;background:transparent;color:var(--dsw-alias-label-secondary);cursor:pointer;font-size:13.5px;transition:background .14s,color .14s,box-shadow .14s}
|
|
15844
|
+
.mp-tab:hover{background:var(--dsw-alias-bg-layer-1);color:var(--dsw-alias-label-primary)}
|
|
15845
|
+
.mp-tab.on{background:var(--dsw-alias-brand-primary);color:#fff;box-shadow:0 8px 18px -12px var(--dsw-alias-brand-primary)}
|
|
13303
15846
|
.mp-field{display:flex;flex-direction:column;gap:5px;font-size:13px;color:var(--dsw-alias-label-secondary);min-width:0}
|
|
13304
|
-
.mp-input{background:var(--dsw-alias-bg-layer-1);border:1px solid var(--dsw-alias-border-l1);color:var(--dsw-alias-label-primary);border-radius:
|
|
13305
|
-
|
|
13306
|
-
.mp-
|
|
13307
|
-
.mp-
|
|
15847
|
+
.mp-input{background:var(--dsw-alias-bg-layer-1);border:1px solid var(--dsw-alias-border-l1);color:var(--dsw-alias-label-primary);border-radius:9px;padding:7px 11px;font-size:14px;outline:none;width:100%;min-width:0;height:36px;
|
|
15848
|
+
transition:border-color .14s,box-shadow .14s,background .14s}
|
|
15849
|
+
.mp-input:hover{border-color:color-mix(in srgb,var(--dsw-alias-border-l1) 45%,var(--dsw-alias-brand-primary))}
|
|
15850
|
+
.mp-input:focus{border-color:var(--dsw-alias-brand-primary);box-shadow:0 0 0 3px color-mix(in srgb,var(--dsw-alias-brand-primary) 18%,transparent)}
|
|
15851
|
+
.mp-textarea{background:var(--dsw-alias-bg-layer-1);border:1px solid var(--dsw-alias-border-l1);color:var(--dsw-alias-label-primary);border-radius:9px;padding:8px 11px;font-size:14px;outline:none;width:100%;min-width:0;resize:vertical;line-height:1.5;font-family:inherit;
|
|
15852
|
+
transition:border-color .14s,box-shadow .14s}
|
|
15853
|
+
.mp-textarea:hover{border-color:color-mix(in srgb,var(--dsw-alias-border-l1) 45%,var(--dsw-alias-brand-primary))}
|
|
15854
|
+
.mp-textarea:focus{border-color:var(--dsw-alias-brand-primary);box-shadow:0 0 0 3px color-mix(in srgb,var(--dsw-alias-brand-primary) 18%,transparent)}
|
|
13308
15855
|
.mp-textarea.invalid{border-color:var(--dsw-alias-state-error-primary)}
|
|
13309
|
-
.mp-
|
|
13310
|
-
.mp-
|
|
15856
|
+
.mp-quiz-wrap{grid-column:1 / -1;display:flex;flex-direction:column;gap:6px}
|
|
15857
|
+
.mp-quiz-top{display:flex;align-items:center;gap:10px;flex-wrap:wrap}
|
|
15858
|
+
.mp-quiz-bar{flex:1 1 160px;min-width:110px;height:6px;border:1px solid var(--dsw-alias-border-l1);border-radius:999px;background:var(--dsw-alias-bg-layer-1);overflow:hidden}
|
|
15859
|
+
.mp-quiz-bar i{display:block;height:100%;border-radius:999px;background:var(--dsw-alias-brand-primary);transition:width .18s ease}
|
|
15860
|
+
.mp-quiz-count{font-size:12px;color:var(--dsw-alias-label-secondary);font-variant-numeric:tabular-nums;white-space:nowrap}
|
|
15861
|
+
.mp-quiz-list{display:flex;flex-direction:column;gap:8px;margin-top:8px}
|
|
15862
|
+
.mp-quiz-q{padding:10px 12px;border:1px solid var(--dsw-alias-border-l1);border-radius:10px;background:var(--dsw-alias-bg-layer-1)}
|
|
15863
|
+
.mp-quiz-qt{display:flex;gap:8px;align-items:baseline;font-size:13px;line-height:1.6;color:var(--dsw-alias-label-primary)}
|
|
15864
|
+
.mp-quiz-qt b{flex:none;padding-top:1px;font:600 11px/1.4 ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;letter-spacing:.04em;color:var(--dsw-alias-brand-primary)}
|
|
15865
|
+
.mp-quiz-opts{display:grid;grid-template-columns:repeat(5,minmax(0,1fr));gap:6px;margin-top:8px}
|
|
15866
|
+
.mp-quiz-o{position:relative;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:2px;padding:6px 4px;border:1px solid var(--dsw-alias-border-l1);border-radius:8px;background:var(--dsw-alias-bg-layer-2);color:var(--dsw-alias-label-secondary);cursor:pointer;text-align:center;
|
|
15867
|
+
transition:border-color .14s,background .14s,color .14s}
|
|
15868
|
+
.mp-quiz-o input{position:absolute;inset:0;margin:0;opacity:0;cursor:pointer}
|
|
15869
|
+
.mp-quiz-o b{font-size:13px;font-weight:600;color:var(--dsw-alias-label-primary);font-variant-numeric:tabular-nums}
|
|
15870
|
+
.mp-quiz-o span{font-size:11px;line-height:1.3}
|
|
15871
|
+
.mp-quiz-o:hover{border-color:var(--dsw-alias-brand-primary)}
|
|
15872
|
+
.mp-quiz-o.on{border-color:transparent;background:var(--dsw-alias-brand-primary)}
|
|
15873
|
+
.mp-quiz-o.on b,.mp-quiz-o.on span{color:#fff}
|
|
15874
|
+
.mp-quiz-o:focus-within{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:2px}
|
|
15875
|
+
.mp-quiz-nav{display:flex;align-items:center;gap:8px;margin-top:10px;flex-wrap:wrap}
|
|
15876
|
+
.mp-quiz-btn{padding:6px 14px;border-radius:8px;border:1px solid var(--dsw-alias-border-l1);background:transparent;color:var(--dsw-alias-label-primary);font-family:inherit;font-size:12.5px;cursor:pointer;min-height:32px}
|
|
15877
|
+
.mp-quiz-btn:hover:not(:disabled){border-color:var(--dsw-alias-brand-primary)}
|
|
15878
|
+
.mp-quiz-btn:disabled{opacity:.42;cursor:not-allowed}
|
|
15879
|
+
.mp-quiz-btn.primary{border-color:transparent;background:var(--dsw-alias-brand-primary);color:#fff;font-weight:600}
|
|
15880
|
+
.mp-quiz-hint{margin-left:auto;font-size:12px;color:var(--dsw-alias-label-secondary);line-height:1.6}
|
|
15881
|
+
.mp-btn{padding:8px 22px;border-radius:9px;border:none;background:var(--dsw-alias-brand-primary);color:#fff;cursor:pointer;font-size:14px;font-weight:600;min-width:132px;
|
|
15882
|
+
box-shadow:0 10px 20px -14px var(--dsw-alias-brand-primary);transition:transform .14s,filter .14s,box-shadow .14s}
|
|
15883
|
+
.mp-btn:hover{filter:brightness(1.06);transform:translateY(-1px)}
|
|
15884
|
+
.mp-btn:active{transform:none;filter:brightness(.98)}
|
|
15885
|
+
.mp-btn.ghost{background:transparent;border:1px solid var(--dsw-alias-border-l1);color:var(--dsw-alias-label-secondary);box-shadow:none}
|
|
15886
|
+
.mp-btn.ghost:hover{background:var(--dsw-alias-bg-layer-2);color:var(--dsw-alias-label-primary);filter:none}
|
|
13311
15887
|
.mp-seg{display:flex;width:100%;border:1px solid var(--dsw-alias-border-l1);border-radius:8px;overflow:hidden;height:36px}
|
|
13312
15888
|
.mp-seg button{flex:1;padding:0 8px;background:transparent;border:none;color:var(--dsw-alias-label-secondary);font-size:13px;cursor:pointer}
|
|
13313
15889
|
.mp-seg button.on{background:var(--dsw-alias-brand-primary);color:#fff}
|
|
@@ -13333,7 +15909,8 @@ const CSS = `
|
|
|
13333
15909
|
.mp-hist-item b{font-weight:600}
|
|
13334
15910
|
.mp-hist-item span{color:var(--dsw-alias-label-secondary)}
|
|
13335
15911
|
.mp-hist-item i{font-style:normal;color:var(--dsw-alias-label-secondary);opacity:.7;font-size:11px}.mp-hint{font-size:12.5px;color:var(--dsw-alias-label-secondary);line-height:1.7;margin:0 0 14px;padding-left:2px}
|
|
13336
|
-
.mp-card{margin-top:18px;padding:16px 18px;border-radius:
|
|
15912
|
+
.mp-card{margin-top:18px;padding:16px 18px;border-radius:16px;background:var(--dsw-alias-bg-layer-1);border:1px solid var(--dsw-alias-border-l1);
|
|
15913
|
+
box-shadow:0 1px 2px color-mix(in srgb,var(--dsw-alias-label-primary) 5%,transparent),0 18px 40px -32px color-mix(in srgb,var(--dsw-alias-label-primary) 42%,transparent)}
|
|
13337
15914
|
.mp-flat{margin-top:16px;padding:0;border:none;background:transparent;border-radius:0}
|
|
13338
15915
|
.mp-dim{color:var(--dsw-alias-label-secondary)}
|
|
13339
15916
|
.mp-err{margin-top:16px;padding:9px 14px;border-radius:8px;border-left:3px solid var(--dsw-alias-state-error-primary);background:color-mix(in srgb,var(--dsw-alias-state-error-primary) 8%,transparent);color:var(--dsw-alias-state-error-primary);font-size:13px}
|
|
@@ -13371,6 +15948,11 @@ const CSS = `
|
|
|
13371
15948
|
.mp-tab{padding:9px 4px;font-size:13.5px;text-align:center}
|
|
13372
15949
|
.mp-input,.mp-textarea{padding:10px 12px;font-size:16px;min-height:44px;height:auto}
|
|
13373
15950
|
.mp-textarea{min-height:76px}
|
|
15951
|
+
.mp-quiz-q{padding:9px 10px}
|
|
15952
|
+
.mp-quiz-o{padding:8px 3px;min-height:50px}
|
|
15953
|
+
.mp-quiz-o span{font-size:10px}
|
|
15954
|
+
.mp-quiz-btn{flex:1 1 auto;min-height:44px}
|
|
15955
|
+
.mp-quiz-hint{flex-basis:100%;margin-left:0}
|
|
13374
15956
|
.mp-actions{margin-top:12px}
|
|
13375
15957
|
.mp-btn{width:100%;padding:12px;font-size:15px;min-height:46px;min-width:0}
|
|
13376
15958
|
.mp-hint,.mp-auto,.mp-cast{font-size:12.5px}
|
|
@@ -13384,10 +15966,81 @@ const CSS = `
|
|
|
13384
15966
|
.mp-wrap{padding:12px 10px 32px}
|
|
13385
15967
|
.mp-tab{font-size:13px;padding:8px 2px}
|
|
13386
15968
|
}
|
|
15969
|
+
:where(.mp-btn,.mp-tab,.mp-chip,.mp-hist-item,.mp-hist-clear,.mp-qmopt,.seg button):focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:2px}
|
|
15970
|
+
@media (prefers-reduced-motion:reduce){
|
|
15971
|
+
*,*::before,*::after{transition-duration:.001ms!important;animation-duration:.001ms!important}
|
|
15972
|
+
}
|
|
13387
15973
|
`;
|
|
13388
15974
|
|
|
13389
15975
|
const { useState, useEffect } = React;
|
|
13390
15976
|
|
|
15977
|
+
const MBTI_PER_PAGE = 4;
|
|
15978
|
+
const MBTI_MIN = 12;
|
|
15979
|
+
let MBTI_INFO = null;
|
|
15980
|
+
function mbtiInfo() {
|
|
15981
|
+
if (MBTI_INFO) return MBTI_INFO;
|
|
15982
|
+
let p = null;
|
|
15983
|
+
try { p = Engine.compute({ system: 'mbti' }); } catch (e) { p = null; }
|
|
15984
|
+
const questions = (p && p.questions) || [];
|
|
15985
|
+
MBTI_INFO = { total: (p && p.total) || questions.length, questions, scale: (p && p.scale) || {} };
|
|
15986
|
+
return MBTI_INFO;
|
|
15987
|
+
}
|
|
15988
|
+
|
|
15989
|
+
function MbtiQuiz(props) {
|
|
15990
|
+
const { answers, page, onPick, onPage, onSubmit, onClear } = props;
|
|
15991
|
+
const info = mbtiInfo();
|
|
15992
|
+
const pages = Math.max(1, Math.ceil(info.total / MBTI_PER_PAGE));
|
|
15993
|
+
const start = page * MBTI_PER_PAGE;
|
|
15994
|
+
const slice = info.questions.slice(start, start + MBTI_PER_PAGE);
|
|
15995
|
+
const answered = answers.filter((v) => v != null).length;
|
|
15996
|
+
const pct = info.total ? Math.round((answered / info.total) * 100) : 0;
|
|
15997
|
+
const last = page >= pages - 1;
|
|
15998
|
+
const ready = answered >= MBTI_MIN;
|
|
15999
|
+
return h('div', { className: 'mp-quiz' },
|
|
16000
|
+
h('div', { className: 'mp-quiz-top' },
|
|
16001
|
+
h('div', { className: 'mp-quiz-bar', 'aria-hidden': 'true' }, h('i', { style: { width: pct + '%' } })),
|
|
16002
|
+
h('span', { className: 'mp-quiz-count' }, `第 ${page + 1} / ${pages} 页 · 已答 ${answered} / ${info.total}`)),
|
|
16003
|
+
h('div', { className: 'mp-quiz-list' }, slice.map((q, k) => {
|
|
16004
|
+
const i = start + k;
|
|
16005
|
+
return h('div', { key: q.id || i, className: 'mp-quiz-q' },
|
|
16006
|
+
h('div', { className: 'mp-quiz-qt' }, h('b', null, String(i + 1).padStart(2, '0')), h('span', null, q.text)),
|
|
16007
|
+
h('div', { className: 'mp-quiz-opts', role: 'radiogroup', 'aria-label': `第 ${i + 1} 题` },
|
|
16008
|
+
[1, 2, 3, 4, 5].map((n) => h('label', { key: n, className: 'mp-quiz-o' + (answers[i] === n ? ' on' : '') },
|
|
16009
|
+
h('input', {
|
|
16010
|
+
type: 'radio', name: `mpmbq${i}`, value: String(n), checked: answers[i] === n,
|
|
16011
|
+
onChange: () => onPick(i, n),
|
|
16012
|
+
}),
|
|
16013
|
+
h('b', null, String(n)),
|
|
16014
|
+
h('span', null, info.scale[n] || '')))));
|
|
16015
|
+
})),
|
|
16016
|
+
h('div', { className: 'mp-quiz-nav' },
|
|
16017
|
+
h('button', { className: 'mp-quiz-btn', disabled: page <= 0, onClick: () => onPage(-1) }, '上一页'),
|
|
16018
|
+
last ? null : h('button', { className: 'mp-quiz-btn', onClick: () => onPage(1) }, '下一页'),
|
|
16019
|
+
h('button', { className: 'mp-quiz-btn primary', disabled: !ready, onClick: onSubmit }, '看结果'),
|
|
16020
|
+
h('button', { className: 'mp-quiz-btn', onClick: onClear }, '清空'),
|
|
16021
|
+
h('span', { className: 'mp-quiz-hint' }, ready
|
|
16022
|
+
? `已够 ${MBTI_MIN} 题,可以看结果;答完 ${info.total} 题会更准。`
|
|
16023
|
+
: `答满 ${MBTI_MIN} 题可先看结果(还差 ${MBTI_MIN - answered} 题)。`)),
|
|
16024
|
+
);
|
|
16025
|
+
}
|
|
16026
|
+
|
|
16027
|
+
class PanelGuard extends (React.Component || Object) {
|
|
16028
|
+
constructor(props) { super(props); this.state = { err: null }; }
|
|
16029
|
+
static getDerivedStateFromError(err) { return { err }; }
|
|
16030
|
+
componentDidCatch(err, info) { console.error('[metaphysics] 面板渲染异常', err, info); }
|
|
16031
|
+
render() {
|
|
16032
|
+
if (!this.state.err) return this.props.children;
|
|
16033
|
+
const e = this.state.err;
|
|
16034
|
+
const stack = String((e && e.stack) || '').split('\n').slice(0, 14).join('\n');
|
|
16035
|
+
return h('div', { className: 'mp-wrap' }, h('div', { className: 'mp-panel' },
|
|
16036
|
+
h('div', { className: 'mp-lbl' }, '命理面板渲染出错——把下面这段发给我'),
|
|
16037
|
+
h('pre', { style: { whiteSpace: 'pre-wrap', fontSize: 12, lineHeight: 1.5, maxHeight: 320, overflow: 'auto', margin: '8px 0' } },
|
|
16038
|
+
String((e && e.message) || e) + '\n\n' + stack),
|
|
16039
|
+
h('div', { className: 'mp-lbl' }, '环境:__PP ' + (typeof PP) + ' · Engine ' + (typeof window.Engine) + ' · React ' + (typeof React) + ' · 版本 ' + (typeof PP === 'object' && PP && (window.__MP_VER || '?'))),
|
|
16040
|
+
));
|
|
16041
|
+
}
|
|
16042
|
+
}
|
|
16043
|
+
|
|
13391
16044
|
function PanelIcon(props) {
|
|
13392
16045
|
const size = props && props.size ? props.size : 20;
|
|
13393
16046
|
const active = props && props.active;
|
|
@@ -13418,6 +16071,7 @@ const TABS = [
|
|
|
13418
16071
|
{ k: 'xiaoliuren', label: '小六壬', timeLabel: '起课时刻', hint: '小六壬用农历月/日/时掐指,也可用三个随机数起课。' },
|
|
13419
16072
|
{ k: 'star', label: '星座', timeLabel: '', hint: '星座按公历日期给出太阳星座与当日基调;同日同星座结果固定。' },
|
|
13420
16073
|
{ k: 'numerology', label: '生命数字', timeLabel: '', hint: '生命数字按公历生日归约出生命路径数、生日数与态度数。' },
|
|
16074
|
+
{ k: 'mbti', label: '人格', timeLabel: '', hint: '十六型人格是 24 道自我报告题的 MBTI 风格测算:4 题一页,按 1–5 打分,答满 12 题即可看结果;只作自我参照,不是官方量表。' },
|
|
13421
16075
|
{ k: 'trend', label: '人生K线', timeLabel: '出生时刻', hint: '人生 K 线按大运与流年十神给逐年运势分,画成走势图。' },
|
|
13422
16076
|
{ k: 'fengshui', label: '风水', timeLabel: '', hint: '风水看八宅命卦、大游年四吉四凶与流年九宫飞星;也可按坐向看门主灶倾向。' },
|
|
13423
16077
|
{ k: 'name', label: '起名', timeLabel: '', hint: '起名按八字喜用匹配字库五行,可评估现有名字或生成候选名。' },
|
|
@@ -13437,6 +16091,7 @@ const TIME_KIND = {
|
|
|
13437
16091
|
almanac: 'date', zeri: 'date', star: 'date', numerology: 'date', convert: 'date',
|
|
13438
16092
|
chenggu: 'birth', trend: 'birth', fengshui: 'birth', name: 'birth',
|
|
13439
16093
|
xiaoliuren: 'cast',
|
|
16094
|
+
mbti: 'none',
|
|
13440
16095
|
};
|
|
13441
16096
|
const SAMPLE = { date: '1990-05-12', time: '14:30' };
|
|
13442
16097
|
const kindOf = (t) => TIME_KIND[t] || 'none';
|
|
@@ -13444,6 +16099,85 @@ const kindOf = (t) => TIME_KIND[t] || 'none';
|
|
|
13444
16099
|
const Core = window.__MPCore || {};
|
|
13445
16100
|
const needAsk = Core.needAsk || ((t) => false);
|
|
13446
16101
|
|
|
16102
|
+
const COMPOSER = { ref: null, seats: [], keys: '', injectType: '', spec: '', errs: [], regs: 0, mounted: 0 };
|
|
16103
|
+
const LAST = { r: null, q: '' };
|
|
16104
|
+
|
|
16105
|
+
function bridgeDiagText() {
|
|
16106
|
+
const bits = [];
|
|
16107
|
+
bits.push('inputActions ' + (COMPOSER.ref ? '已拿到' : '未拿到'));
|
|
16108
|
+
bits.push('渲染 ' + COMPOSER.mounted + ' 次');
|
|
16109
|
+
bits.push('注册 ' + COMPOSER.regs + ' 次');
|
|
16110
|
+
bits.push('inject ' + (COMPOSER.injectType || '?'));
|
|
16111
|
+
bits.push('槽位 ' + (COMPOSER.spec || '?'));
|
|
16112
|
+
if (COMPOSER.errs.length) bits.push('错误:' + COMPOSER.errs.join(' / '));
|
|
16113
|
+
return '桥自检:' + bits.join(';');
|
|
16114
|
+
}
|
|
16115
|
+
|
|
16116
|
+
function noteRegError(e) {
|
|
16117
|
+
if (COMPOSER.errs.length >= 3) return;
|
|
16118
|
+
const s = e && e.message ? String(e.message) : String(e);
|
|
16119
|
+
COMPOSER.errs.push(s.slice(0, 90));
|
|
16120
|
+
}
|
|
16121
|
+
function bridgeActions(props) {
|
|
16122
|
+
if (!props) return null;
|
|
16123
|
+
const a = props.inputActions;
|
|
16124
|
+
if (a && typeof a.setDraft === 'function' && typeof a.submit === 'function') return a;
|
|
16125
|
+
const b = props.actions && props.actions.input;
|
|
16126
|
+
if (b && typeof b.setDraft === 'function' && typeof b.submit === 'function') return b;
|
|
16127
|
+
return null;
|
|
16128
|
+
}
|
|
16129
|
+
|
|
16130
|
+
function useBridge(props, name) {
|
|
16131
|
+
const actions = bridgeActions(props);
|
|
16132
|
+
useEffect(() => {
|
|
16133
|
+
if (COMPOSER.seats.indexOf(name) < 0) COMPOSER.seats.push(name);
|
|
16134
|
+
COMPOSER.keys = props ? Object.keys(props).join(',') : '';
|
|
16135
|
+
if (actions) {
|
|
16136
|
+
COMPOSER.ref = actions;
|
|
16137
|
+
try { window.__MPComposer = actions; } catch (e) { /* 非浏览器环境忽略 */ }
|
|
16138
|
+
}
|
|
16139
|
+
return () => { if (COMPOSER.ref === actions) COMPOSER.ref = null; };
|
|
16140
|
+
}, [actions, name]);
|
|
16141
|
+
return actions;
|
|
16142
|
+
}
|
|
16143
|
+
|
|
16144
|
+
function askTextForLast() {
|
|
16145
|
+
const r = LAST.r;
|
|
16146
|
+
if (!r) return '';
|
|
16147
|
+
try {
|
|
16148
|
+
const p = Engine.askPrompt ? Engine.askPrompt(r, { question: LAST.q }) : null;
|
|
16149
|
+
return (p && p.text) || String(r.summary || '');
|
|
16150
|
+
} catch (e) { return String(r.summary || ''); }
|
|
16151
|
+
}
|
|
16152
|
+
|
|
16153
|
+
function ComposerBridge(props) {
|
|
16154
|
+
COMPOSER.mounted += 1;
|
|
16155
|
+
const actions = useBridge(props, 'input.right');
|
|
16156
|
+
if (!actions) {
|
|
16157
|
+
return h('span', { className: 'mp-chip warn', title: '命理:已占住输入框槽位,但没拿到 inputActions;把这句话告诉作者' }, '命理·未就绪');
|
|
16158
|
+
}
|
|
16159
|
+
return h('button', {
|
|
16160
|
+
type: 'button', className: 'mp-chip ok',
|
|
16161
|
+
title: LAST.r ? '把上一张盘的摘要和问题发进对话窗' : '先在侧栏「命理」里排一张盘',
|
|
16162
|
+
onClick: () => { const t = askTextForLast(); if (t) sendToComposer(t); },
|
|
16163
|
+
}, '命理·问');
|
|
16164
|
+
}
|
|
16165
|
+
|
|
16166
|
+
function ComposerProbe(props) {
|
|
16167
|
+
COMPOSER.mounted += 1;
|
|
16168
|
+
useBridge(props, 'composer.dock');
|
|
16169
|
+
return null;
|
|
16170
|
+
}
|
|
16171
|
+
|
|
16172
|
+
function sendToComposer(text) {
|
|
16173
|
+
let ia = COMPOSER.ref;
|
|
16174
|
+
if (!ia) { try { ia = window.__MPComposer || null; } catch (e) { ia = null; } }
|
|
16175
|
+
if (!ia || typeof ia.setDraft !== 'function' || typeof ia.submit !== 'function') return false;
|
|
16176
|
+
ia.setDraft(text);
|
|
16177
|
+
ia.submit();
|
|
16178
|
+
return true;
|
|
16179
|
+
}
|
|
16180
|
+
|
|
13447
16181
|
function App() {
|
|
13448
16182
|
const [tab, setTab] = useState('ziwei');
|
|
13449
16183
|
const [date, setDate] = useState('1990-05-12');
|
|
@@ -13461,6 +16195,7 @@ function App() {
|
|
|
13461
16195
|
const [qLateZi, setQLateZi] = useState('same-day');
|
|
13462
16196
|
const [crossOn, setCrossOn] = useState(false);
|
|
13463
16197
|
const [askText, setAskText] = useState('');
|
|
16198
|
+
const [chatNote, setChatNote] = useState('');
|
|
13464
16199
|
const [fx, setFx] = useState(null);
|
|
13465
16200
|
const [pastMarks, setPastMarks] = useState({});
|
|
13466
16201
|
const [fit, setFit] = useState(null);
|
|
@@ -13474,6 +16209,8 @@ function App() {
|
|
|
13474
16209
|
const [leapMonth, setLeapMonth] = useState(false);
|
|
13475
16210
|
const [xlrMode, setXlrMode] = useState('time');
|
|
13476
16211
|
const [num1, setNum1] = useState(''); const [num2, setNum2] = useState(''); const [num3, setNum3] = useState('');
|
|
16212
|
+
const [mbAns, setMbAns] = useState(() => new Array(mbtiInfo().total).fill(null));
|
|
16213
|
+
const [mbPage, setMbPage] = useState(0);
|
|
13477
16214
|
const [toAge, setToAge] = useState('60');
|
|
13478
16215
|
const [fsMode, setFsMode] = useState('natal');
|
|
13479
16216
|
const [sitting, setSitting] = useState('子');
|
|
@@ -13485,6 +16222,9 @@ function App() {
|
|
|
13485
16222
|
const [onlineGeo, setOnlineGeo] = useState(false);
|
|
13486
16223
|
const [lines, setLines] = useState('');
|
|
13487
16224
|
const [result, setResult] = useState(null);
|
|
16225
|
+
useEffect(() => {
|
|
16226
|
+
if (result && result.r) { LAST.r = result.r; LAST.q = askText.trim(); }
|
|
16227
|
+
}, [result, askText]);
|
|
13488
16228
|
const [hist, setHist] = useState(() => loadHistory());
|
|
13489
16229
|
const [replayArgs, setReplayArgs] = useState(null);
|
|
13490
16230
|
const [error, setError] = useState('');
|
|
@@ -13506,7 +16246,7 @@ function App() {
|
|
|
13506
16246
|
|| tab === 'chenggu' || tab === 'trend' || tab === 'fengshui' || tab === 'name';
|
|
13507
16247
|
const timeKind = kindOf(tab);
|
|
13508
16248
|
const usesTimeInput = !(tab === 'meihua' && mhMode === 'number');
|
|
13509
|
-
const showDate = tab !== 'tarot' && usesTimeInput;
|
|
16249
|
+
const showDate = tab !== 'tarot' && tab !== 'mbti' && usesTimeInput;
|
|
13510
16250
|
const showTime = showDate && timeKind !== 'date';
|
|
13511
16251
|
const showDT = showTime;
|
|
13512
16252
|
|
|
@@ -13516,6 +16256,7 @@ function App() {
|
|
|
13516
16256
|
const dt = override ? override : { date, time };
|
|
13517
16257
|
const genderV = over && over.gender ? over.gender : gender;
|
|
13518
16258
|
const addressV = over && typeof over.address === 'string' ? over.address : address;
|
|
16259
|
+
setNotice(''); // 上一次的提示(如「先答满 12 题」)不该跟着新结果一起留下
|
|
13519
16260
|
try {
|
|
13520
16261
|
const datetime = `${dt.date}T${dt.time}`;
|
|
13521
16262
|
const args = { system: k };
|
|
@@ -13560,6 +16301,12 @@ function App() {
|
|
|
13560
16301
|
args.hour = Number.isFinite(hh) ? hh : 12;
|
|
13561
16302
|
}
|
|
13562
16303
|
}
|
|
16304
|
+
if (k === 'mbti') {
|
|
16305
|
+
delete args.datetime;
|
|
16306
|
+
const nums = mbAns.slice();
|
|
16307
|
+
while (nums.length && nums[nums.length - 1] == null) nums.pop();
|
|
16308
|
+
if (nums.length) args.answers = nums;
|
|
16309
|
+
}
|
|
13563
16310
|
if (k === 'trend') { args.gender = genderV; args.toAge = Number(toAge) || 60; args.trueSolar = trueSolar; args.lateZi = lateZi; }
|
|
13564
16311
|
if (k === 'fengshui') {
|
|
13565
16312
|
args.action = fsMode;
|
|
@@ -13658,7 +16405,7 @@ function App() {
|
|
|
13658
16405
|
setResult({ kind: k, r, it, at: dt, timed, trend });
|
|
13659
16406
|
setFx(null); setFit(null); setPastMarks({}); setRectRes(null);
|
|
13660
16407
|
setError(''); setCopied('');
|
|
13661
|
-
if (k !== 'tarot') {
|
|
16408
|
+
if (k !== 'tarot' && k !== 'mbti') {
|
|
13662
16409
|
const entry = {
|
|
13663
16410
|
kind: k, date, time, gender, address,
|
|
13664
16411
|
lines: k === 'liuyao' ? lines : '',
|
|
@@ -13684,6 +16431,12 @@ function App() {
|
|
|
13684
16431
|
const k = kindOf(next);
|
|
13685
16432
|
setTab(next);
|
|
13686
16433
|
setError('');
|
|
16434
|
+
if (next === 'mbti') {
|
|
16435
|
+
setNotice('');
|
|
16436
|
+
if (mbAns.filter((v) => v != null).length >= MBTI_MIN) run(next);
|
|
16437
|
+
else setResult(null);
|
|
16438
|
+
return;
|
|
16439
|
+
}
|
|
13687
16440
|
if (k === 'none') { run(next); return; } // 塔罗不看时间,直接抽牌(与 web-ui 一致)
|
|
13688
16441
|
const v = manual[k] || (k === 'cast' ? nowParts() : { date: SAMPLE.date, time: SAMPLE.time });
|
|
13689
16442
|
setDate(v.date);
|
|
@@ -13709,6 +16462,15 @@ function App() {
|
|
|
13709
16462
|
};
|
|
13710
16463
|
|
|
13711
16464
|
const go = () => {
|
|
16465
|
+
if (tab === 'mbti') {
|
|
16466
|
+
const n = mbAns.filter((v) => v != null).length;
|
|
16467
|
+
if (n < MBTI_MIN) {
|
|
16468
|
+
setNotice(`先答满 ${MBTI_MIN} 题再看结果(现答 ${n} 题,还差 ${MBTI_MIN - n} 题)。`);
|
|
16469
|
+
return;
|
|
16470
|
+
}
|
|
16471
|
+
run(tab);
|
|
16472
|
+
return;
|
|
16473
|
+
}
|
|
13712
16474
|
if (timeKind !== 'none' && !manual[timeKind]) {
|
|
13713
16475
|
const t = nowParts();
|
|
13714
16476
|
setDate(t.date);
|
|
@@ -13781,6 +16543,21 @@ function App() {
|
|
|
13781
16543
|
} catch (e) { setFx({ question: askText.trim(), ok: false, answer: '追问失败:' + (e && e.message ? e.message : e), evidence: [], confidence: '弱' }); }
|
|
13782
16544
|
};
|
|
13783
16545
|
|
|
16546
|
+
const askInChat = () => {
|
|
16547
|
+
if (!result || !result.r) return;
|
|
16548
|
+
try {
|
|
16549
|
+
const p = Engine.askPrompt ? Engine.askPrompt(result.r, { question: askText.trim() }) : null;
|
|
16550
|
+
const text = p && p.text ? p.text : String(result.r.summary || '');
|
|
16551
|
+
if (sendToComposer(text)) { setChatNote('已发到对话窗,往下看回复。'); return; }
|
|
16552
|
+
const diag = '(' + bridgeDiagText() + ')';
|
|
16553
|
+
if (navigator.clipboard && navigator.clipboard.writeText) {
|
|
16554
|
+
navigator.clipboard.writeText(text).then(
|
|
16555
|
+
() => setChatNote('对话输入框还没就绪' + diag + ',已复制提问;粘进对话窗回车即可。'),
|
|
16556
|
+
() => setChatNote('对话输入框还没就绪' + diag + ',复制也没成功;先点「复制文字结果」再贴。'));
|
|
16557
|
+
} else { setChatNote('对话输入框还没就绪' + diag + ';先点「复制文字结果」再贴进对话窗。'); }
|
|
16558
|
+
} catch (e) { setChatNote('发到对话窗失败:' + (e && e.message ? e.message : e)); }
|
|
16559
|
+
};
|
|
16560
|
+
|
|
13784
16561
|
const downloadReport = () => {
|
|
13785
16562
|
if (!result || !result.r) return;
|
|
13786
16563
|
try {
|
|
@@ -14004,6 +16781,27 @@ function App() {
|
|
|
14004
16781
|
className: 'mp-input', type: 'number', min: 1, max: 99, value: num3,
|
|
14005
16782
|
onChange: (e) => setNum3(e.target.value),
|
|
14006
16783
|
})) : null,
|
|
16784
|
+
tab === 'mbti' ? h('div', { className: 'mp-quiz-wrap' },
|
|
16785
|
+
h('div', { className: 'mp-lbl' }, '十六型人格问卷 · 4 题一页,按 1(完全不像)到 5(很像我)打分'),
|
|
16786
|
+
h(MbtiQuiz, {
|
|
16787
|
+
answers: mbAns,
|
|
16788
|
+
page: mbPage,
|
|
16789
|
+
onPick: (i, n) => setMbAns((prev) => {
|
|
16790
|
+
const next = prev.slice();
|
|
16791
|
+
next[i] = n;
|
|
16792
|
+
return next;
|
|
16793
|
+
}),
|
|
16794
|
+
onPage: (d) => setMbPage((p) => Math.max(0, Math.min(
|
|
16795
|
+
p + d,
|
|
16796
|
+
Math.max(0, Math.ceil(mbtiInfo().total / MBTI_PER_PAGE) - 1),
|
|
16797
|
+
))),
|
|
16798
|
+
onSubmit: go,
|
|
16799
|
+
onClear: () => {
|
|
16800
|
+
setMbAns(new Array(mbtiInfo().total).fill(null));
|
|
16801
|
+
setMbPage(0);
|
|
16802
|
+
setResult(null);
|
|
16803
|
+
},
|
|
16804
|
+
})) : null,
|
|
14007
16805
|
tab === 'trend' ? field('算到几岁', h('input', {
|
|
14008
16806
|
className: 'mp-input', type: 'number', min: 10, max: 100, value: toAge,
|
|
14009
16807
|
onChange: (e) => setToAge(e.target.value),
|
|
@@ -14052,7 +16850,7 @@ function App() {
|
|
|
14052
16850
|
onChange: (e) => { setQuestion(e.target.value); setAskInvalid(false); },
|
|
14053
16851
|
onBlur: (e) => refreshInterpret(undefined, e.target.value),
|
|
14054
16852
|
})) : null,
|
|
14055
|
-
h('div', { key: 'actions', className: 'mp-actions' },
|
|
16853
|
+
tab === 'mbti' ? null : h('div', { key: 'actions', className: 'mp-actions' },
|
|
14056
16854
|
h('button', {
|
|
14057
16855
|
className: 'mp-btn ghost', style: { fontSize: 12, padding: '5px 12px', marginRight: 8 },
|
|
14058
16856
|
onClick: openSample, title: '用固定示例盘看完整报告(不改动你已填的数据)',
|
|
@@ -14084,9 +16882,13 @@ function App() {
|
|
|
14084
16882
|
notice ? h('div', { key: 'ntc', className: 'mp-note', role: 'status' }, notice) : null,
|
|
14085
16883
|
|
|
14086
16884
|
(!result && !error) ? h('div', { key: 'empty', className: 'mp-empty' },
|
|
14087
|
-
h('b', null, tab === 'ziwei'
|
|
14088
|
-
: tab === 'tarot' ? '写下想问的事,点「抽牌」'
|
|
14089
|
-
|
|
16885
|
+
h('b', null, tab === 'ziwei' || tab === 'bazi' ? '填好出生信息,点「排盘」'
|
|
16886
|
+
: tab === 'tarot' ? '写下想问的事,点「抽牌」'
|
|
16887
|
+
: tab === 'mbti' ? '按 1–5 给题目打分,答满 12 题就能看结果'
|
|
16888
|
+
: '写下所问之事,点「起卦」'),
|
|
16889
|
+
tab === 'ziwei' || tab === 'bazi' ? '出生日期、时刻与性别即可;出生地只影响真太阳时。'
|
|
16890
|
+
: tab === 'mbti' ? '4 题一页,答案只在本地参与计算,不会上传。'
|
|
16891
|
+
: '起卦时刻已自动取当下,也可以手动改。') : null,
|
|
14090
16892
|
|
|
14091
16893
|
result ? h('div', {
|
|
14092
16894
|
key: 'card',
|
|
@@ -14109,6 +16911,7 @@ function App() {
|
|
|
14109
16911
|
: result.kind === 'almanac' ? PP.almanacHTML(result.r)
|
|
14110
16912
|
: result.kind === 'trend' ? PP.trendHTML(result.r)
|
|
14111
16913
|
: result.kind === 'name' ? PP.nameHTML(result.r)
|
|
16914
|
+
: result.kind === 'mbti' ? PP.mbtiHTML(result.r)
|
|
14112
16915
|
: PP.quickHTML(result.r),
|
|
14113
16916
|
result.it,
|
|
14114
16917
|
{ folded: defaultFolded() },
|
|
@@ -14128,14 +16931,20 @@ function App() {
|
|
|
14128
16931
|
onClick: downloadCard, title: '生成 PNG 摘要卡(一页读懂 + 首张表),适合直接分享',
|
|
14129
16932
|
}, '存为摘要长图')) : null,
|
|
14130
16933
|
|
|
14131
|
-
result ? h('div', { key: 'ask', className: 'mp-askbox' },
|
|
16934
|
+
result ? h('div', { key: 'ask', className: 'mp-askbox', style: { flexWrap: 'wrap' } },
|
|
14132
16935
|
h('input', {
|
|
14133
16936
|
className: 'mp-input', value: askText, maxLength: 120,
|
|
14134
16937
|
placeholder: '追问:如 2027 年事业怎么样(回车提交)',
|
|
14135
16938
|
onChange: (e) => setAskText(e.target.value),
|
|
14136
16939
|
onKeyDown: (e) => { if (e.key === 'Enter') doAsk(); },
|
|
14137
16940
|
}),
|
|
14138
|
-
h('button', { className: 'mp-btn ghost', style: { fontSize: 12, padding: '5px 12px' }, onClick: doAsk }, '追问')
|
|
16941
|
+
h('button', { className: 'mp-btn ghost', style: { fontSize: 12, padding: '5px 12px' }, onClick: doAsk }, '追问'),
|
|
16942
|
+
h('button', {
|
|
16943
|
+
className: 'mp-btn ghost', style: { fontSize: 12, padding: '5px 12px', marginLeft: 8 },
|
|
16944
|
+
onClick: askInChat, title: '把这张盘的摘要和你的问题一起发进 DSH 对话窗,由对话里的模型接着答',
|
|
16945
|
+
}, '问进对话'),
|
|
16946
|
+
(COMPOSER.ref ? null : h('div', { key: 'bridgediag', className: 'mp-note', style: { marginTop: 6, fontSize: 11, flexBasis: '100%' } }, bridgeDiagText())),
|
|
16947
|
+
chatNote ? h('div', { key: 'chatnote', className: 'mp-note', style: { marginTop: 6, fontSize: 12, flexBasis: '100%' } }, chatNote) : null) : null,
|
|
14139
16948
|
|
|
14140
16949
|
fx ? h('div', { key: 'fx', className: 'mp-fx', dangerouslySetInnerHTML: { __html: PP.followupHTML(fx) } }) : null,
|
|
14141
16950
|
|
|
@@ -14219,6 +17028,25 @@ function safeApply(ctx) {
|
|
|
14219
17028
|
return;
|
|
14220
17029
|
}
|
|
14221
17030
|
|
|
17031
|
+
try {
|
|
17032
|
+
COMPOSER.injectType = typeof slots.inject;
|
|
17033
|
+
const sp = typeof slots.spec === 'function' ? slots.spec('conversation.input.right') : null;
|
|
17034
|
+
COMPOSER.spec = sp ? sp.kind + '/' + sp.scope : '未声明';
|
|
17035
|
+
} catch (e) {
|
|
17036
|
+
COMPOSER.spec = '取声明失败';
|
|
17037
|
+
noteRegError(e);
|
|
17038
|
+
}
|
|
17039
|
+
const tryReg = (options, component) => {
|
|
17040
|
+
try {
|
|
17041
|
+
const d = slots.register(options, component);
|
|
17042
|
+
COMPOSER.regs += 1;
|
|
17043
|
+
return d;
|
|
17044
|
+
} catch (e) {
|
|
17045
|
+
noteRegError(e);
|
|
17046
|
+
return null;
|
|
17047
|
+
}
|
|
17048
|
+
};
|
|
17049
|
+
|
|
14222
17050
|
const waitFor = (key, install) => {
|
|
14223
17051
|
try {
|
|
14224
17052
|
if (typeof slots.inject === 'function') {
|
|
@@ -14232,12 +17060,59 @@ function safeApply(ctx) {
|
|
|
14232
17060
|
}
|
|
14233
17061
|
};
|
|
14234
17062
|
|
|
14235
|
-
waitFor('sidebar.panellist', () =>
|
|
14236
|
-
{ name: 'sidebar.panellist', id: 'metaphysics', order: 20, label: () => '命理' },
|
|
17063
|
+
waitFor('sidebar.panellist', () => tryReg(
|
|
17064
|
+
{ name: 'sidebar.panellist', id: 'metaphysics', order: 20, label: () => '命理 v' + (window.__MP_VER || '') },
|
|
14237
17065
|
PanelIcon,
|
|
14238
17066
|
));
|
|
14239
17067
|
|
|
14240
|
-
waitFor('main', () =>
|
|
17068
|
+
waitFor('main', () => tryReg({ name: 'main', key: 'metaphysics' }, (p) => h(PanelGuard, null, h(App, p))));
|
|
17069
|
+
|
|
17070
|
+
const sessionSeat = (key, install) => {
|
|
17071
|
+
const run = () => {
|
|
17072
|
+
try { slots.inject(key, install); }
|
|
17073
|
+
catch (e) {
|
|
17074
|
+
console.error('[metaphysics] 槽位注册失败:' + key, e);
|
|
17075
|
+
try { install(); } catch (e2) { console.error('[metaphysics] 直接注册也失败:' + key, e2); }
|
|
17076
|
+
}
|
|
17077
|
+
};
|
|
17078
|
+
try {
|
|
17079
|
+
if (typeof ctx.effect === 'function') ctx.effect(run, 'metaphysics: ' + key);
|
|
17080
|
+
else run();
|
|
17081
|
+
} catch (e) {
|
|
17082
|
+
console.error('[metaphysics] effect 包裹失败:' + key, e);
|
|
17083
|
+
run();
|
|
17084
|
+
}
|
|
17085
|
+
};
|
|
17086
|
+
|
|
17087
|
+
sessionSeat('conversation.input.right', () => tryReg(
|
|
17088
|
+
{ name: 'conversation.input.right', id: 'metaphysics-ask', order: 40 },
|
|
17089
|
+
ComposerBridge,
|
|
17090
|
+
));
|
|
17091
|
+
|
|
17092
|
+
sessionSeat('conversation.composer.dock', () => tryReg(
|
|
17093
|
+
{ name: 'conversation.composer.dock', id: 'metaphysics-dock', order: 60 },
|
|
17094
|
+
ComposerProbe,
|
|
17095
|
+
));
|
|
17096
|
+
|
|
17097
|
+
let seatTries = 0;
|
|
17098
|
+
const trySeatNow = () => {
|
|
17099
|
+
if (COMPOSER.ref) return;
|
|
17100
|
+
seatTries += 1;
|
|
17101
|
+
const tag = '-' + seatTries;
|
|
17102
|
+
tryReg({ name: 'conversation.input.right', id: 'metaphysics-ask' + tag, order: 40 }, ComposerBridge);
|
|
17103
|
+
tryReg({ name: 'conversation.composer.dock', id: 'metaphysics-dock' + tag, order: 60 }, ComposerProbe);
|
|
17104
|
+
};
|
|
17105
|
+
let seatTriesLeft = 20;
|
|
17106
|
+
const seatRetry = () => {
|
|
17107
|
+
if (COMPOSER.ref || seatTriesLeft <= 0) return;
|
|
17108
|
+
seatTriesLeft -= 1;
|
|
17109
|
+
trySeatNow();
|
|
17110
|
+
setTimeout(seatRetry, 700);
|
|
17111
|
+
};
|
|
17112
|
+
try { setTimeout(seatRetry, 700); } catch (e) { /* 无计时器环境 */ }
|
|
17113
|
+
try {
|
|
17114
|
+
document.addEventListener('pointerdown', () => trySeatNow(), { once: true, capture: true });
|
|
17115
|
+
} catch (e) { /* 非 DOM 环境 */ }
|
|
14241
17116
|
}
|
|
14242
17117
|
|
|
14243
17118
|
return {
|