guanwei 1.1.1

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.
Files changed (157) hide show
  1. package/LICENSE +21 -0
  2. package/README.en.md +202 -0
  3. package/README.md +247 -0
  4. package/dist/assets/index-CsOD5rSo.js +102 -0
  5. package/dist/assets/index-CsOD5rSo.js.map +1 -0
  6. package/dist/assets/index-DQx62TUr.css +1 -0
  7. package/dist/favicon.svg +12 -0
  8. package/dist/index.html +15 -0
  9. package/eslint.config.js +28 -0
  10. package/index.html +25 -0
  11. package/package.json +96 -0
  12. package/postcss.config.js +10 -0
  13. package/public/favicon.svg +12 -0
  14. package/scripts/guanwei +245 -0
  15. package/scripts/install.sh +79 -0
  16. package/scripts/release.sh +42 -0
  17. package/scripts/setup.bat +36 -0
  18. package/scripts/setup.sh +123 -0
  19. package/server/src/data/db.json +12059 -0
  20. package/server/src/data/guanwei.db +0 -0
  21. package/server/src/data/lifeContext.ts +423 -0
  22. package/server/src/data/spreads.ts +255 -0
  23. package/server/src/data/tarotCards.ts +2353 -0
  24. package/server/src/index.ts +71 -0
  25. package/server/src/routes/ai.ts +376 -0
  26. package/server/src/routes/divine.ts +140 -0
  27. package/server/src/routes/hour.ts +40 -0
  28. package/server/src/routes/tarot.ts +129 -0
  29. package/server/src/routes/users.ts +140 -0
  30. package/server/src/services/chartBrief.ts +131 -0
  31. package/server/src/services/divineStore.ts +188 -0
  32. package/server/src/services/hourInference.ts +150 -0
  33. package/server/src/services/llmProvider.ts +181 -0
  34. package/server/src/services/promptBuilder.ts +327 -0
  35. package/server/src/services/relativesCheck.ts +139 -0
  36. package/server/src/services/sixRelatives.ts +70 -0
  37. package/server/src/services/skills.ts +116 -0
  38. package/server/src/types/index.ts +104 -0
  39. package/server/src/utils/semanticAnalyzer.ts +555 -0
  40. package/server/src/utils/tarotEngine.ts +849 -0
  41. package/server/tsconfig.json +18 -0
  42. package/shared/core/data/classics.ts +276 -0
  43. package/shared/core/data/courses.ts +211 -0
  44. package/shared/core/data/duanyu.ts +148 -0
  45. package/shared/core/data/ganzhi.ts +53 -0
  46. package/shared/core/data/gua64.ts +93 -0
  47. package/shared/core/data/liuren.ts +18 -0
  48. package/shared/core/data/liuyao.ts +73 -0
  49. package/shared/core/data/qimen.ts +27 -0
  50. package/shared/core/data/region-full.ts +3 -0
  51. package/shared/core/data/region.ts +310 -0
  52. package/shared/core/data/tarotSpreads.ts +78 -0
  53. package/shared/core/data/xiaoliuren.ts +18 -0
  54. package/shared/core/data/ziwei.ts +97 -0
  55. package/shared/core/data/zodiac.ts +20 -0
  56. package/shared/core/engine/astrology.ts +169 -0
  57. package/shared/core/engine/bazi.ts +306 -0
  58. package/shared/core/engine/calendar.ts +127 -0
  59. package/shared/core/engine/daily.ts +133 -0
  60. package/shared/core/engine/liuren.ts +86 -0
  61. package/shared/core/engine/liuyao.ts +93 -0
  62. package/shared/core/engine/meihua.ts +87 -0
  63. package/shared/core/engine/qimen.ts +78 -0
  64. package/shared/core/engine/questionFit.ts +94 -0
  65. package/shared/core/engine/tarot.ts +69 -0
  66. package/shared/core/engine/trueSolarTime.ts +86 -0
  67. package/shared/core/engine/xiaoliuren.ts +19 -0
  68. package/shared/core/engine/ziwei.ts +217 -0
  69. package/shared/core/engine/ziweiInterpret.ts +161 -0
  70. package/shared/core/types.ts +206 -0
  71. package/src/App.tsx +69 -0
  72. package/src/arts/registry.ts +31 -0
  73. package/src/assets/react.svg +1 -0
  74. package/src/components/Backdrop.tsx +27 -0
  75. package/src/components/BambooArt.tsx +41 -0
  76. package/src/components/CalendarInput.tsx +131 -0
  77. package/src/components/DateInput.tsx +103 -0
  78. package/src/components/Disclaimer.tsx +12 -0
  79. package/src/components/Empty.tsx +8 -0
  80. package/src/components/ErrorBoundary.tsx +38 -0
  81. package/src/components/HomeSideAnchor.tsx +62 -0
  82. package/src/components/InkVein.tsx +10 -0
  83. package/src/components/LifeEventsInput.tsx +47 -0
  84. package/src/components/LocationPicker.tsx +117 -0
  85. package/src/components/Motes.tsx +65 -0
  86. package/src/components/Navigation.tsx +80 -0
  87. package/src/components/ProfileForm.tsx +40 -0
  88. package/src/components/ProfilePicker.tsx +40 -0
  89. package/src/components/QuestionFields.tsx +47 -0
  90. package/src/components/ReportView.tsx +211 -0
  91. package/src/components/ResultCard.tsx +40 -0
  92. package/src/components/SealButton.tsx +18 -0
  93. package/src/components/SiteFooter.tsx +17 -0
  94. package/src/components/SiteNav.tsx +103 -0
  95. package/src/components/SongDialog.tsx +64 -0
  96. package/src/components/SongSearchSelect.tsx +81 -0
  97. package/src/components/SongSelect.tsx +61 -0
  98. package/src/components/StarField.tsx +119 -0
  99. package/src/components/TarotCard.tsx +129 -0
  100. package/src/components/TimeShichenInput.tsx +29 -0
  101. package/src/components/arts/AstrologyArt.tsx +141 -0
  102. package/src/components/arts/BaziArt.tsx +269 -0
  103. package/src/components/arts/LiurenArt.tsx +87 -0
  104. package/src/components/arts/LiuyaoArt.tsx +111 -0
  105. package/src/components/arts/MeihuaArt.tsx +105 -0
  106. package/src/components/arts/QimenArt.tsx +86 -0
  107. package/src/components/arts/TarotArt.tsx +110 -0
  108. package/src/components/arts/XiaoliurenArt.tsx +93 -0
  109. package/src/components/arts/ZiweiArt.tsx +296 -0
  110. package/src/data/arts.ts +84 -0
  111. package/src/data/lifeContext.ts +423 -0
  112. package/src/data/sample-report.json +146 -0
  113. package/src/data/shichen.ts +21 -0
  114. package/src/data/spreads.ts +255 -0
  115. package/src/data/tarotCards.ts +2353 -0
  116. package/src/hooks/useAIInterpret.ts +76 -0
  117. package/src/hooks/useDivine.ts +39 -0
  118. package/src/hooks/useTheme.ts +29 -0
  119. package/src/index.css +190 -0
  120. package/src/lib/utils.ts +6 -0
  121. package/src/main.tsx +12 -0
  122. package/src/pages/AboutPage.tsx +25 -0
  123. package/src/pages/AcademyPage.tsx +128 -0
  124. package/src/pages/AstrologyPage.tsx +33 -0
  125. package/src/pages/AuthPage.tsx +263 -0
  126. package/src/pages/BaZiPage.tsx +33 -0
  127. package/src/pages/ClassicsPage.tsx +120 -0
  128. package/src/pages/DemoPage.tsx +161 -0
  129. package/src/pages/HistoryPage.tsx +133 -0
  130. package/src/pages/Home.tsx +179 -0
  131. package/src/pages/HomePage.tsx +174 -0
  132. package/src/pages/ModulePage.tsx +320 -0
  133. package/src/pages/SpreadEditor.tsx +230 -0
  134. package/src/pages/SpreadEditorPage.tsx +105 -0
  135. package/src/pages/SpreadLibrary.tsx +199 -0
  136. package/src/pages/SpreadLibraryPage.tsx +17 -0
  137. package/src/pages/TarotPage.tsx +738 -0
  138. package/src/pages/ZiWeiPage.tsx +33 -0
  139. package/src/services/api.ts +342 -0
  140. package/src/stores/useDivinationStore.ts +22 -0
  141. package/src/styles/song.css +1066 -0
  142. package/src/styles/tokens.css +60 -0
  143. package/src/types/index.ts +104 -0
  144. package/src/utils/astrologyCalc.ts +61 -0
  145. package/src/utils/comboEngine.ts +134 -0
  146. package/src/utils/dst.ts +24 -0
  147. package/src/utils/panTone.ts +206 -0
  148. package/src/utils/recordStore.ts +60 -0
  149. package/src/utils/semanticAnalyzer.ts +555 -0
  150. package/src/utils/spreadStorage.ts +32 -0
  151. package/src/utils/storage.ts +27 -0
  152. package/src/utils/tarotEngine.ts +849 -0
  153. package/src/utils/userStore.ts +234 -0
  154. package/src/vite-env.d.ts +1 -0
  155. package/tailwind.config.js +52 -0
  156. package/tsconfig.json +40 -0
  157. package/vite.config.ts +34 -0
@@ -0,0 +1,169 @@
1
+ // 星盘:回归黄道(Tropical Zodiac)· VSOP87 精确星历(astronomy-engine)
2
+ // 行星黄经按 of-date 春分点(回归黄道),上升/中天按标准天文公式精确计算
3
+ import * as astroNS from 'astronomy-engine';
4
+ import { mod } from '../data/ganzhi';
5
+ import type { AstrologyResult } from '../types';
6
+
7
+ // 兼容 tsx(CJS interop) 与 vite(ESM) 的导入方式
8
+ const Astro: any = (astroNS as any).default ?? astroNS;
9
+
10
+ const DEG = Math.PI / 180;
11
+ const RAD = 180 / Math.PI;
12
+
13
+ // ─── 星座与古典占星表(补齐层)───
14
+ const SIGNS = ['白羊', '金牛', '双子', '巨蟹', '狮子', '处女', '天秤', '天蝎', '射手', '摩羯', '水瓶', '双鱼'];
15
+ // 古典守护星(不含三王星)
16
+ const SIGN_RULER: Record<string, string> = {
17
+ 白羊: '火星', 金牛: '金星', 双子: '水星', 巨蟹: '月亮', 狮子: '太阳', 处女: '水星',
18
+ 天秤: '金星', 天蝎: '火星', 射手: '木星', 摩羯: '土星', 水瓶: '土星', 双鱼: '木星',
19
+ };
20
+ // 古典庙旺表(庙/旺/陷/弱)
21
+ const DIGNITY: Record<string, { miao: string; wang: string }> = {
22
+ 太阳: { miao: '狮子', wang: '白羊' }, 月亮: { miao: '巨蟹', wang: '金牛' },
23
+ 水星: { miao: '双子', wang: '处女' }, 金星: { miao: '金牛', wang: '双鱼' },
24
+ 火星: { miao: '白羊', wang: '摩羯' }, 木星: { miao: '射手', wang: '巨蟹' },
25
+ 土星: { miao: '摩羯', wang: '天秤' },
26
+ };
27
+ const signOf = (lng: number) => SIGNS[Math.floor(mod(lng, 360) / 30)];
28
+ const degreeIn = (lng: number) => mod(lng, 30);
29
+ // 行星在星座中的守护/庙旺判定:宫主星(行星是否守护该星座)与庙旺
30
+ function dignityOf(planet: string, sign: string): AstroDignity {
31
+ const d = DIGNITY[planet];
32
+ if (!d) return { status: '', note: '' };
33
+ if (d.miao === sign) return { status: '庙', note: planet + '入' + sign + '为庙(本垣),力量最显' };
34
+ if (d.wang === sign) return { status: '旺', note: planet + '入' + sign + '为旺(擢升),助力显著' };
35
+ if (d.miao === SIGNS[(SIGNS.indexOf(sign) + 6) % 12]) return { status: '陷', note: planet + '入' + sign + '为陷(失势),力量受抑' };
36
+ if (d.wang === SIGNS[(SIGNS.indexOf(sign) + 6) % 12]) return { status: '弱', note: planet + '入' + sign + '为弱(失位),助力有限' };
37
+ return { status: '', note: '' };
38
+ }
39
+ interface AstroDignity { status: '庙' | '旺' | '陷' | '弱' | ''; note: string }
40
+
41
+ // 黄赤交角(of date,IAU 简式)
42
+ function obliquity(jd: number): number {
43
+ const T = (jd - 2451545.0) / 36525;
44
+ return (23.4392911 - 0.0130042 * T - 1.64e-7 * T * T + 5.04e-7 * T * T * T) * DEG;
45
+ }
46
+
47
+ // 儒略日
48
+ function julianDay(y: number, m: number, d: number, hour: number, min: number): number {
49
+ // 输入为北京时间(UTC+8)→ 转为 UTC 时刻
50
+ const utc = Date.UTC(y, m - 1, d, hour, min) - 8 * 3600 * 1000;
51
+ return utc / 86400000 + 2440587.5;
52
+ }
53
+
54
+ export function daysSince(y: number, m: number, d: number): number {
55
+ return Math.floor(julianDay(y, m, d, 0, 0) - 2451545);
56
+ }
57
+
58
+ export function astrologyCalc(
59
+ y: number, m: number, d: number,
60
+ hour: number, min: number,
61
+ lng?: number,
62
+ lat?: number,
63
+ ): AstrologyResult {
64
+ const jd = julianDay(y, m, d, hour, min);
65
+ const date = new Date((jd - 2440587.5) * 86400000);
66
+
67
+ // 行星精确黄经(回归黄道 ofdate)
68
+ const BODIES: [string, string, string, string][] = [
69
+ ['太阳', '☉', 'Sun', '#C8872E'],
70
+ ['月亮', '☽', 'Moon', '#8C9BA8'],
71
+ ['水星', '☿', 'Mercury', '#7A8A9A'],
72
+ ['金星', '♀', 'Venus', '#A5767E'],
73
+ ['火星', '♂', 'Mars', '#B0563A'],
74
+ ['木星', '♃', 'Jupiter', '#9C7A4A'],
75
+ ['土星', '♄', 'Saturn', '#6E7566'],
76
+ ];
77
+ const planets: [string, string, number, string][] = [];
78
+ for (const [cn, sym, en, color] of BODIES) {
79
+ try {
80
+ const eq = Astro.GeoVector(Astro.Body[en], date, true);
81
+ const ecl = Astro.Ecliptic(eq, true); // ofdate=true → 回归黄道
82
+ planets.push([cn, sym, mod(ecl.elon, 360), color]);
83
+ } catch {
84
+ planets.push([cn, sym, 0, color]);
85
+ }
86
+ }
87
+ const sun = planets[0][2];
88
+ const moon = planets[1][2];
89
+
90
+ // 恒星时:GAST(格林尼治视恒星时,小时)→ 本地恒星时
91
+ const gast = Astro.SiderealTime(date);
92
+ const lstHours = mod(gast + (lng !== undefined ? lng / 15 : 8), 24);
93
+ const RAMC = lstHours * 15;
94
+
95
+ // 黄赤交角
96
+ const eps = obliquity(jd);
97
+ // 纬度:出生地纬度(关键!上升点对纬度高度敏感)
98
+ const phi = (lat ?? 39.9) * DEG;
99
+
100
+ // 上升点黄经(推导自地平方程 cos(RAMC-α) = -tanφ·tanδ):
101
+ // tanλ = -cos(RAMC) / (sin(RAMC)·cosε + tanφ·sinε)
102
+ // atan2 给出两个解之一(西方交点),+180° 取东方交点(上升点)
103
+ const asc = mod(
104
+ Math.atan2(
105
+ -Math.cos(RAMC * DEG),
106
+ Math.sin(RAMC * DEG) * Math.cos(eps) + Math.tan(phi) * Math.sin(eps),
107
+ ) * RAD + 180,
108
+ 360,
109
+ );
110
+ // 中天黄经:MC = atan2( sin(RAMC), cos(RAMC)·cos(ε) )
111
+ const mc = mod(Math.atan2(Math.sin(RAMC * DEG), Math.cos(RAMC * DEG) * Math.cos(eps)) * RAD, 360);
112
+
113
+ // 相位(黄经差,容差 8°)
114
+ const aspects: [string, string, string, string][] = [];
115
+ for (let i = 0; i < planets.length; i++) {
116
+ for (let j = i + 1; j < planets.length; j++) {
117
+ const diff = mod(planets[i][2] - planets[j][2], 360);
118
+ const a = Math.min(diff, 360 - diff);
119
+ const orb = 8;
120
+ if (a < orb) aspects.push([planets[i][0], planets[j][0], '合', '凝聚之象']);
121
+ else if (Math.abs(a - 60) < orb) aspects.push([planets[i][0], planets[j][0], '六合', '和谐之象']);
122
+ else if (Math.abs(a - 90) < orb) aspects.push([planets[i][0], planets[j][0], '刑', '紧张之象']);
123
+ else if (Math.abs(a - 120) < orb) aspects.push([planets[i][0], planets[j][0], '拱', '顺遂之象']);
124
+ else if (Math.abs(a - 180) < orb) aspects.push([planets[i][0], planets[j][0], '冲', '对峙之象']);
125
+ }
126
+ }
127
+ // ─── 补齐层:整宫制十二宫 + 行星详情 + 逆行 + 庙旺 ───
128
+ const houseSystem = 'whole-sign' as const;
129
+ // 整宫制:1 宫头 = 上升点黄经,每宫 30°
130
+ const houses = SIGNS.map((_, i) => {
131
+ const cusp = mod(asc + i * 30, 360);
132
+ const sign = signOf(cusp);
133
+ return { num: i + 1, cusp, sign, ruler: SIGN_RULER[sign], rulerLng: 0 };
134
+ });
135
+ // 行星详情
136
+ const planetDetails = planets.map(([cn, sym, lng, color]) => {
137
+ // 逆行检测:与 1 天前黄经比较(太阳/月亮除外)
138
+ let retrograde = false;
139
+ if (cn !== '太阳' && cn !== '月亮') {
140
+ const prev = new Date(date.getTime() - 86400000);
141
+ try {
142
+ const eq0 = Astro.GeoVector(Astro.Body[(BODIES.find(b => b[0] === cn) as any)[2]], prev, true);
143
+ const ecl0 = Astro.Ecliptic(eq0, true);
144
+ const prevLng = mod(ecl0.elon, 360);
145
+ const d1 = mod(lng - prevLng, 360);
146
+ retrograde = d1 < 0.5 && d1 > 0 ? false : (mod(prevLng - lng, 360) < 0.5 && mod(prevLng - lng, 360) > 0) ? true : mod(lng - prevLng, 360) > 180;
147
+ } catch { /* 忽略 */ }
148
+ }
149
+ const sign = signOf(lng);
150
+ const house = Math.floor(mod(lng - asc, 360) / 30) + 1;
151
+ return {
152
+ cn, sym, color,
153
+ lng, sign, degree: degreeIn(lng),
154
+ house,
155
+ retrograde,
156
+ dignity: dignityOf(cn, sign),
157
+ };
158
+ });
159
+ // 宫主星黄经(供展示:守护星所在位置)
160
+ houses.forEach(h => {
161
+ const ruler = planetDetails.find(p => p.cn === h.ruler);
162
+ h.rulerLng = ruler ? ruler.lng : -1;
163
+ });
164
+ const ascSign = signOf(asc);
165
+ const sunSign = signOf(sun);
166
+ const moonSign = signOf(moon);
167
+
168
+ return { planets, asc, sun, moon, lstHours, aspects, mc, epsilon: eps / DEG, houseSystem, houses, planetDetails, ascSign, sunSign, moonSign };
169
+ }
@@ -0,0 +1,306 @@
1
+ // 四柱八字:真太阳时校正 + 精确节气定年柱月柱 + 十神强弱
2
+ // 补齐层(2026-08-20):地支藏干十神 / 旺衰拆解 / 用神喜忌 / 大运流年 / 神煞 / 胎元命宫身宫
3
+ import { GAN, ZHI, WUXING, NAYIN, mod, jiaziIndex } from '../data/ganzhi';
4
+ import { daysSince, monthBranchOf, getJieQiTableExact } from './calendar';
5
+ import { trueSolarTime, shiftedDate } from './trueSolarTime';
6
+ import type { BaziInput, BaziResult } from '../types';
7
+
8
+ const MONTH_NAMES: Record<number, string> = { 0: '寅月', 1: '卯月', 2: '辰月', 3: '巳月', 4: '午月', 5: '未月', 6: '申月', 7: '酉月', 8: '戌月', 9: '亥月', 10: '子月', 11: '丑月' };
9
+
10
+ // ─── 地支藏干(本气/中气/余气)───
11
+ const CANGGAN: Record<string, { gan: string; qi: '本气' | '中气' | '余气' }[]> = {
12
+ 子: [{ gan: '癸', qi: '本气' }],
13
+ 丑: [{ gan: '己', qi: '本气' }, { gan: '癸', qi: '中气' }, { gan: '辛', qi: '余气' }],
14
+ 寅: [{ gan: '甲', qi: '本气' }, { gan: '丙', qi: '中气' }, { gan: '戊', qi: '余气' }],
15
+ 卯: [{ gan: '乙', qi: '本气' }],
16
+ 辰: [{ gan: '戊', qi: '本气' }, { gan: '乙', qi: '中气' }, { gan: '癸', qi: '余气' }],
17
+ 巳: [{ gan: '丙', qi: '本气' }, { gan: '庚', qi: '中气' }, { gan: '戊', qi: '余气' }],
18
+ 午: [{ gan: '丁', qi: '本气' }, { gan: '己', qi: '中气' }],
19
+ 未: [{ gan: '己', qi: '本气' }, { gan: '丁', qi: '中气' }, { gan: '乙', qi: '余气' }],
20
+ 申: [{ gan: '庚', qi: '本气' }, { gan: '壬', qi: '中气' }, { gan: '戊', qi: '余气' }],
21
+ 酉: [{ gan: '辛', qi: '本气' }],
22
+ 戌: [{ gan: '戊', qi: '本气' }, { gan: '辛', qi: '中气' }, { gan: '丁', qi: '余气' }],
23
+ 亥: [{ gan: '壬', qi: '本气' }, { gan: '甲', qi: '中气' }],
24
+ };
25
+
26
+ // ─── 神煞表(日干起)───
27
+ const GUI_REN: Record<string, string[]> = { 甲: ['丑', '未'], 戊: ['丑', '未'], 庚: ['丑', '未'], 乙: ['子', '申'], 己: ['子', '申'], 丙: ['亥', '酉'], 丁: ['亥', '酉'], 壬: ['卯', '巳'], 癸: ['卯', '巳'], 辛: ['午', '寅'] };
28
+ const WEN_CHANG: Record<string, string> = { 甲: '巳', 乙: '午', 丙: '申', 丁: '酉', 戊: '申', 己: '酉', 庚: '亥', 辛: '子', 壬: '寅', 癸: '卯' };
29
+ const LU_SHEN: Record<string, string> = { 甲: '寅', 乙: '卯', 丙: '巳', 丁: '午', 戊: '巳', 己: '午', 庚: '申', 辛: '酉', 壬: '亥', 癸: '子' };
30
+ const YANG_REN: Record<string, string> = { 甲: '卯', 乙: '寅', 丙: '午', 丁: '巳', 戊: '午', 己: '巳', 庚: '酉', 辛: '申', 壬: '子', 癸: '亥' };
31
+ // 三合局(年支/日支)→ 驿马/桃花/华盖/将星
32
+ const SANHE: Record<string, { ma: string; tao: string; gai: string; jiang: string }> = {
33
+ 申: { ma: '寅', tao: '酉', gai: '辰', jiang: '子' }, 子: { ma: '寅', tao: '酉', gai: '辰', jiang: '子' }, 辰: { ma: '寅', tao: '酉', gai: '辰', jiang: '子' },
34
+ 寅: { ma: '申', tao: '卯', gai: '戌', jiang: '午' }, 午: { ma: '申', tao: '卯', gai: '戌', jiang: '午' }, 戌: { ma: '申', tao: '卯', gai: '戌', jiang: '午' },
35
+ 巳: { ma: '亥', tao: '午', gai: '丑', jiang: '酉' }, 酉: { ma: '亥', tao: '午', gai: '丑', jiang: '酉' }, 丑: { ma: '亥', tao: '午', gai: '丑', jiang: '酉' },
36
+ 亥: { ma: '巳', tao: '子', gai: '未', jiang: '卯' }, 卯: { ma: '巳', tao: '子', gai: '未', jiang: '卯' }, 未: { ma: '巳', tao: '子', gai: '未', jiang: '卯' },
37
+ };
38
+
39
+ // 十二「节」(大运起运顺逆数此)
40
+ const JIE_NAMES = ['小寒', '立春', '惊蛰', '清明', '立夏', '芒种', '小暑', '立秋', '白露', '寒露', '立冬', '大雪'];
41
+
42
+ const WX_ORDER = ['木', '火', '土', '金', '水'];
43
+
44
+ export function baziCalc(input: BaziInput): BaziResult {
45
+ let { y, m, d, hourIndex } = input;
46
+ const gender = input.gender;
47
+ // 时辰未知:hourIndex < 0(或缺失)→ 不排时柱,年月日三柱照排,大运/起运不受影响
48
+ const hourUnknown = hourIndex === undefined || hourIndex === null || hourIndex < 0;
49
+
50
+ // 1. 真太阳时校正(出生地点 → 经度;仅时辰已知时做;优先用输入精确时刻,缺省用时辰中点)
51
+ let correctedHourIndex = hourUnknown ? -1 : hourIndex;
52
+ let trueSolar;
53
+ if (!hourUnknown && input.location) {
54
+ const [th, tm] = input.time ? input.time.split(':').map(Number) : [(hourIndex * 2) % 24, 30];
55
+ trueSolar = trueSolarTime(y, m, d, th, tm, input.location.lng);
56
+ correctedHourIndex = trueSolar.hourIndex;
57
+ if (trueSolar.dateOffset !== 0) {
58
+ [y, m, d] = shiftedDate(y, m, d, trueSolar.dateOffset);
59
+ }
60
+ }
61
+ const hour = hourUnknown ? 12 : (correctedHourIndex * 2) % 24;
62
+ const min = 0;
63
+
64
+ // 2. 年柱(立春为界)
65
+ const t = new Date(y, m - 1, d, hour, min).getTime();
66
+ let lichunBest = -Infinity;
67
+ let lichunYear = y - 1;
68
+ for (const yy of [y - 1, y, y + 1]) {
69
+ for (const jq of getJieQiTableExact(yy)) {
70
+ if (jq.name === '立春') {
71
+ const tt = jq.time.getTime();
72
+ if (tt <= t && tt > lichunBest) { lichunBest = tt; lichunYear = yy; }
73
+ }
74
+ }
75
+ }
76
+ const yearGZ = ganzhiYear(lichunYear);
77
+
78
+ // 3. 月柱(精确节气定月支 + 五虎遁)
79
+ const mb = monthBranchOf(y, m, d, hour, min);
80
+ const ygIdx = GAN.indexOf(yearGZ[0] as any);
81
+ const mgIdx = mod((ygIdx % 5) * 2 + 2 + mb, 10);
82
+ const monthGZ = GAN[mgIdx] + ZHI[mod(2 + mb, 12)];
83
+
84
+ // 4. 日柱
85
+ const dIdx = mod(daysSince(y, m, d) + 55, 60);
86
+ const dayGZ = GAN[dIdx % 10] + ZHI[dIdx % 12];
87
+ const dayGan = dayGZ[0];
88
+ const dayGanWx = WUXING[dayGan];
89
+
90
+ // 5. 时柱(五鼠遁;时辰未知则不排)
91
+ let hourGZ = '未知';
92
+ if (!hourUnknown) {
93
+ const dgIdx = GAN.indexOf(dayGan as any);
94
+ const hgIdx = mod((dgIdx % 5) * 2 + correctedHourIndex, 10);
95
+ hourGZ = GAN[hgIdx] + ZHI[correctedHourIndex];
96
+ }
97
+
98
+ // 6. 基础五行统计 + 天干十神(保留原口径;时辰未知时仅三柱)
99
+ const wxCount: Record<string, number> = { 木: 0, 火: 0, 土: 0, 金: 0, 水: 0 };
100
+ const gzList = hourUnknown ? [yearGZ, monthGZ, dayGZ] : [yearGZ, monthGZ, dayGZ, hourGZ];
101
+ gzList.forEach(gz => { wxCount[WUXING[gz[0]]]++; wxCount[WUXING[gz[1]]]++; });
102
+ const shishenList = gzList.map(gz => ({ gan: gz[0], name: shishen(dayGan, gz[0]) }));
103
+ if (hourUnknown) shishenList.push({ gan: '□', name: '未知' });
104
+ const nayin = NAYIN[Math.floor(jiaziIndex(y) / 2) % 30];
105
+ const support = wxCount[dayGanWx] + wxCount[WX_ORDER[(WX_ORDER.indexOf(dayGanWx) + 4) % 5]];
106
+ const drain = gzList.length * 2 - support;
107
+ const strength = support > drain ? '身强' : (support < drain ? '身弱' : '中和');
108
+
109
+ // ─── 7. 地支藏干 + 藏干十神 + 加权五行 ───
110
+ const canggan = gzList.map(gz => ({
111
+ zhi: gz[1],
112
+ gans: (CANGGAN[gz[1]] || []).map(c => ({
113
+ gan: c.gan, wx: WUXING[c.gan], qi: c.qi, shishen: shishen(dayGan, c.gan),
114
+ })),
115
+ }));
116
+ if (hourUnknown) canggan.push({ zhi: '?', gans: [] });
117
+ const wxWeighted: Record<string, number> = { 木: 0, 火: 0, 土: 0, 金: 0, 水: 0 };
118
+ gzList.forEach(gz => { wxWeighted[WUXING[gz[0]]] += 1; });
119
+ canggan.forEach(cg => cg.gans.forEach(c => { wxWeighted[c.wx] += c.qi === '本气' ? 2 : 1; }));
120
+
121
+ // ─── 8. 旺衰拆解(得令/得地/得势)───
122
+ const dayWxIdx = WX_ORDER.indexOf(dayGanWx);
123
+ const monthWx = WUXING[monthGZ[1]];
124
+ const mIdx = WX_ORDER.indexOf(monthWx);
125
+ // 月令生克:同=3 生我=2 我生=1 我克/克我=0.5
126
+ const rel = mod(mIdx - dayWxIdx, 5);
127
+ const ling = rel === 0 ? 3 : rel === 4 ? 2 : rel === 1 ? 1 : 0.5;
128
+ let gen = 0;
129
+ const genDetails: string[] = [];
130
+ gzList.forEach(gz => {
131
+ const cgs = CANGGAN[gz[1]] || [];
132
+ const ben = cgs.find(c => c.qi === '本气');
133
+ const zhong = cgs.find(c => c.qi !== '本气' && WUXING[c.gan] === dayGanWx);
134
+ if (ben && WUXING[ben.gan] === dayGanWx) { gen += 2; genDetails.push(gz[1] + '本气' + ben.gan + '通根'); }
135
+ else if (zhong) { gen += 1; genDetails.push(gz[1] + '藏' + zhong.gan + '微根'); }
136
+ });
137
+ let shi = 0;
138
+ [yearGZ[0], monthGZ[0], dayGZ[0]].forEach(gan => {
139
+ const gw = WUXING[gan];
140
+ if (gw === dayGanWx) shi += 1;
141
+ else if (mod(WX_ORDER.indexOf(gw) - dayWxIdx, 5) === 4) shi += 1; // 生我
142
+ });
143
+ const score = ling + gen + shi;
144
+ const reasons: string[] = [];
145
+ reasons.push((ling >= 3 ? '月令得令(' + monthGZ[1] + '月' + monthWx + ')' : ling >= 2 ? '月令生扶' : '月令失令(' + monthGZ[1] + '月' + monthWx + ')') + ' +' + ling);
146
+ if (genDetails.length) reasons.push('地支通根:' + genDetails.join('、') + ' +' + gen);
147
+ else reasons.push('地支无根 +' + gen);
148
+ reasons.push((shi > 0 ? '天干得势(比劫印星 ' + shi + ' 位)' : '天干无助') + ' +' + shi);
149
+ const finalStrength: BaziResult['strength'] = score >= 7 ? '身强' : score <= 4 ? '身弱' : '中和';
150
+
151
+ // ─── 9. 用神/喜忌(扶抑 + 季节调候)───
152
+ const XI_Q: Record<string, string[]> = { 身强: ['官杀', '食伤', '财'], 身弱: ['印', '比劫'], 中和: ['食伤', '财', '印'] };
153
+ const JI_Q: Record<string, string[]> = { 身强: ['印', '比劫'], 身弱: ['财', '官杀', '食伤'], 中和: ['比劫', '官杀'] };
154
+ const xi = XI_Q[finalStrength] || [];
155
+ const ji = JI_Q[finalStrength] || [];
156
+ // 调候:按季节(月支)
157
+ const season = ['寅', '卯', '辰', '巳', '午', '未', '申', '酉', '戌', '亥', '子', '丑'].indexOf(monthGZ[1]);
158
+ let tiaohou = '';
159
+ if (season >= 9 || season <= 0) tiaohou = '冬月寒凝,宜火调候(丙丁)';
160
+ else if (season >= 3 && season <= 5) tiaohou = '夏月炎燥,宜水调候(壬癸)';
161
+ else if (season >= 0 && season <= 2) tiaohou = '春月木旺,宜火泄秀或金制衡';
162
+ else tiaohou = '秋月金旺,宜火炼金或水泄秀';
163
+ // 主用神五行:身强取克泄(官杀=克我、食伤=我生、财=我克);身弱取生扶(印=生我、比劫=同我)
164
+ const useWx = finalStrength === '身强'
165
+ ? (WX_ORDER[(dayWxIdx + 2) % 5]) // 我克=财(或取食伤,简化取财)
166
+ : (WX_ORDER[(dayWxIdx + 4) % 5]); // 生我=印
167
+ const yongshen = {
168
+ wx: useWx, shishen: finalStrength === '身强' ? '财星' : '印星',
169
+ xi, ji, tiaohou,
170
+ reason: '日主' + finalStrength + '(旺衰分 ' + score + ':' + reasons.join(';') + ')。' + (finalStrength === '身强' ? '身强宜克泄耗,取' + useWx + '(财星)为用,喜财官食伤,忌印比生扶。' : '身弱宜生扶,取' + useWx + '(印星)为用,喜印比帮身,忌财官食伤。') + tiaohou + '。',
171
+ };
172
+
173
+ // ─── 10. 大运(起运 + 序列)───
174
+ const ganYang = GAN.indexOf(yearGZ[0] as any) % 2 === 0;
175
+ const forward = (gender === '男' && ganYang) || (gender === '女' && !ganYang);
176
+ // 找最近「节」:顺排找下一个,逆排找上一个
177
+ const jieTimes: { name: string; time: number }[] = [];
178
+ for (const yy of [y - 1, y, y + 1]) {
179
+ for (const jq of getJieQiTableExact(yy)) {
180
+ if (JIE_NAMES.includes(jq.name)) jieTimes.push({ name: jq.name, time: jq.time.getTime() });
181
+ }
182
+ }
183
+ jieTimes.sort((a, b) => a.time - b.time);
184
+ let diffDays = 0, jieName = '';
185
+ if (forward) {
186
+ const next = jieTimes.find(j => j.time > t);
187
+ if (next) { diffDays = (next.time - t) / 86400000; jieName = next.name; }
188
+ } else {
189
+ const prev = [...jieTimes].reverse().find(j => j.time < t);
190
+ if (prev) { diffDays = (t - prev.time) / 86400000; jieName = prev.name; }
191
+ }
192
+ const qiYunYears = Math.max(0, Math.floor(diffDays / 3));
193
+ const qiYunMonths = Math.max(0, Math.floor((diffDays - qiYunYears * 3) * 4));
194
+ const startAge = qiYunYears + 1; // 虚岁起运
195
+ const mgIdx2 = GAN.indexOf(monthGZ[0] as any);
196
+ const mzIdx2 = ZHI.indexOf(monthGZ[1] as any);
197
+ const dayun: BaziResult['dayun'] = [];
198
+ const birthYear = y;
199
+ for (let i = 0; i < 8; i++) {
200
+ const step = forward ? i : -i;
201
+ const g = GAN[mod(mgIdx2 + step, 10)];
202
+ const z = ZHI[mod(mzIdx2 + step, 12)];
203
+ dayun.push({
204
+ gz: g + z,
205
+ ganShishen: shishen(dayGan, g),
206
+ zhiShishen: (CANGGAN[z] || []).map(c => c.gan + shishen(dayGan, c.gan)).join('、'),
207
+ startAge: startAge + i * 10,
208
+ startYear: birthYear + startAge + i * 10 - 1,
209
+ endYear: birthYear + startAge + i * 10 + 9 - 1,
210
+ forward,
211
+ });
212
+ }
213
+
214
+ // ─── 11. 流年(当前年)───
215
+ const nowYear = new Date().getFullYear();
216
+ const liuIdx = jiaziIndex(nowYear);
217
+ const liuGZ = GAN[liuIdx % 10] + ZHI[liuIdx % 12];
218
+ const liunian = {
219
+ year: nowYear,
220
+ gz: liuGZ,
221
+ ganShishen: shishen(dayGan, liuGZ[0]),
222
+ zhiShishen: (CANGGAN[liuGZ[1]] || []).map(c => c.gan + shishen(dayGan, c.gan)).join('、'),
223
+ };
224
+
225
+ // ─── 12. 神煞(日干 + 年支/日支三合)───
226
+ const shensha: BaziResult['shensha'] = [];
227
+ const zhis = gzList.map(gz => gz[1]);
228
+ const zhiSet = new Set(zhis);
229
+ (GUI_REN[dayGan] || []).forEach(z => { if (zhiSet.has(z)) shensha.push({ name: '天乙贵人', zhi: z, type: '吉' }); });
230
+ const wc = WEN_CHANG[dayGan];
231
+ if (wc && zhiSet.has(wc)) shensha.push({ name: '文昌贵人', zhi: wc, type: '吉' });
232
+ const lu = LU_SHEN[dayGan];
233
+ if (lu && zhiSet.has(lu)) shensha.push({ name: '禄神', zhi: lu, type: '吉' });
234
+ const yr = YANG_REN[dayGan];
235
+ if (yr && zhiSet.has(yr)) shensha.push({ name: '羊刃', zhi: yr, type: '凶' });
236
+ const sanheKey = SANHE[yearGZ[1]] || SANHE[dayGZ[1]];
237
+ if (sanheKey) {
238
+ if (zhiSet.has(sanheKey.ma)) shensha.push({ name: '驿马', zhi: sanheKey.ma, type: '平' });
239
+ if (zhiSet.has(sanheKey.tao)) shensha.push({ name: '桃花(咸池)', zhi: sanheKey.tao, type: '平' });
240
+ if (zhiSet.has(sanheKey.gai)) shensha.push({ name: '华盖', zhi: sanheKey.gai, type: '平' });
241
+ if (zhiSet.has(sanheKey.jiang)) shensha.push({ name: '将星', zhi: sanheKey.jiang, type: '平' });
242
+ }
243
+
244
+ // ─── 12.5 月令取格(八格:月支本气十神定格局,透干者加力)───
245
+ const monthBenQi = (CANGGAN[monthGZ[1]] || [])[0]; // 月支本气
246
+ const monthBenQiShishen = monthBenQi ? shishen(dayGan, monthBenQi.gan) : '比肩';
247
+ const benQiIndex = gzList.findIndex(gz => gz[0] === monthBenQi?.gan); // 本气是否透干
248
+ const benQiTou = benQiIndex >= 0;
249
+ const gejuName = ['比肩', '劫财'].includes(monthBenQiShishen)
250
+ ? (monthBenQiShishen === '比肩' ? '建禄格(月令比肩,不作八格,以身强论)' : '羊刃格(月令劫财,旺极须制)')
251
+ : monthBenQiShishen + '格';
252
+ const geju = {
253
+ name: gejuName,
254
+ gan: monthBenQi?.gan || '',
255
+ shishen: monthBenQiShishen,
256
+ basis: '月支' + monthGZ[1] + '本气' + (monthBenQi?.gan || '') + '(' + monthBenQiShishen + ')' + (benQiTou ? ',透干于' + ['年干', '月干', '日干', '时干'][benQiIndex] + ',格气有力' : ',未透干,格气内藏') + ';' + tiaohou,
257
+ };
258
+ // ─── 13. 胎元 / 命宫 / 身宫 ───
259
+ const taiyuan = GAN[mod(mgIdx2 + 1, 10)] + ZHI[mod(mzIdx2 + 3, 12)];
260
+ const minggong = hourUnknown ? '未知' : ZHI[mod(2 + mod((mb) - correctedHourIndex, 12), 12)];
261
+ const shengong = hourUnknown ? '未知' : ZHI[mod(2 + mod((mb) + correctedHourIndex, 12), 12)];
262
+
263
+ return {
264
+ yearGZ, monthGZ, dayGZ, hourGZ,
265
+ dayGan, dayGanWx,
266
+ wxCount,
267
+ shishen: shishenList,
268
+ strength: finalStrength, support, drain,
269
+ nayin,
270
+ correctedHourIndex,
271
+ trueSolar,
272
+ canggan,
273
+ wxWeighted,
274
+ strengthDetail: { score, ling, gen, shi, reasons },
275
+ yongshen,
276
+ dayun,
277
+ qiYun: { startAge, startMonth: qiYunMonths, detail: (forward ? '顺行' : '逆行') + ',' + (jieName ? '距' + jieName : '') + (diffDays > 0 ? ' ' + diffDays.toFixed(1) + ' 天(3 天为 1 岁)' : '') + ',约 ' + startAge + ' 岁起运' },
278
+ liunian,
279
+ shensha,
280
+ taiyuan,
281
+ minggong,
282
+ shengong,
283
+ geju,
284
+ };
285
+ }
286
+
287
+ export function ganzhiYear(year: number): string {
288
+ const i = jiaziIndex(year);
289
+ return GAN[i % 10] + ZHI[i % 12];
290
+ }
291
+
292
+ export function shishen(dayGan: string, gan: string): string {
293
+ if (gan === dayGan) return '比肩';
294
+ const dWx = WUXING[dayGan], gWx = WUXING[gan];
295
+ const dYin = GAN.indexOf(dayGan as any) % 2 === 0;
296
+ const gYin = GAN.indexOf(gan as any) % 2 === 0;
297
+ const same = dYin === gYin;
298
+ if (gWx === dWx) return same ? '比肩' : '劫财';
299
+ const wxOrder = ['木', '火', '土', '金', '水'];
300
+ const dI = wxOrder.indexOf(dWx), gI = wxOrder.indexOf(gWx);
301
+ const rel = mod(gI - dI, 5);
302
+ const map: Record<number, string> = { 1: same ? '食神' : '伤官', 2: same ? '偏财' : '正财', 3: same ? '七杀' : '正官', 4: same ? '偏印' : '正印' };
303
+ return map[rel] || '比肩';
304
+ }
305
+
306
+ export { MONTH_NAMES };
@@ -0,0 +1,127 @@
1
+ // 历法模块:儒略日 / 节气(精确,基于 lunar-typescript)/ 农历黄历
2
+ import { Solar } from 'lunar-typescript';
3
+ import { JIEQI_APPROX } from '../data/qimen';
4
+
5
+ /* ---------- 儒略日 ---------- */
6
+ export function jd(y: number, m: number, d: number): number {
7
+ let yy = y, mm = m;
8
+ if (mm <= 2) { yy--; mm += 12; }
9
+ const A = Math.floor(yy / 100);
10
+ return Math.floor(365.25 * (yy + 4716)) + Math.floor(30.6001 * (mm + 1)) + d + 2 - A + Math.floor(A / 4) - 1524.5;
11
+ }
12
+
13
+ export function daysSince(y: number, m: number, d: number): number {
14
+ return Math.floor(jd(y, m, d) - 2451545);
15
+ }
16
+
17
+ /* ---------- 节气 ---------- */
18
+ // 近似表取法(奇门定遁 / 展示用):
19
+ export function getJieqiApproxName(y: number, m: number, d: number): string {
20
+ const v = m * 100 + d;
21
+ let name = '大雪';
22
+ for (let i = JIEQI_APPROX.length - 1; i >= 0; i--) {
23
+ const [, jm, jd2] = JIEQI_APPROX[i];
24
+ if (v >= jm * 100 + jd2) { name = JIEQI_APPROX[i][0]; break; }
25
+ }
26
+ return name;
27
+ }
28
+
29
+ // 精确节气时刻表(某年全年 24 节气)
30
+ export interface JieQiTime { name: string; time: Date }
31
+ export function getJieQiTableExact(year: number): JieQiTime[] {
32
+ const solar = Solar.fromYmdHms(year, 6, 1, 12, 0, 0);
33
+ const table = solar.getLunar().getJieQiTable();
34
+ const out: JieQiTime[] = [];
35
+ for (const key of Object.keys(table)) {
36
+ const s = table[key];
37
+ out.push({ name: key, time: new Date(s.getYear(), s.getMonth() - 1, s.getDay(), s.getHour(), s.getMinute(), s.getSecond()) });
38
+ }
39
+ return out;
40
+ }
41
+
42
+ // 当天是否为某节气(精确)
43
+ export function getJieQiNameExact(y: number, m: number, d: number): string | null {
44
+ const solar = Solar.fromYmdHms(y, m, d, 12, 0, 0);
45
+ return solar.getLunar().getJieQi() || null;
46
+ }
47
+
48
+ // 当前所处节气(精确:取该时刻之前最近的节气,24 节气皆可)
49
+ export function currentJieqiNameExact(y: number, m: number, d: number): string {
50
+ const t = new Date(y, m - 1, d, 12, 0, 0).getTime();
51
+ let best: { name: string; time: number } | null = null;
52
+ for (const yy of [y - 1, y, y + 1]) {
53
+ for (const jq of getJieQiTableExact(yy)) {
54
+ const tt = jq.time.getTime();
55
+ if (tt <= t && (!best || tt > best.time)) best = { name: jq.name, time: tt };
56
+ }
57
+ }
58
+ return best ? best.name : '大雪';
59
+ }
60
+
61
+ // 十二「节」(定月支用)与月支映射(0=寅 … 11=丑,与参考项目一致)
62
+ export const JIE_BRANCH: Record<string, number> = {
63
+ 小寒: 11, 立春: 0, 惊蛰: 1, 清明: 2, 立夏: 3, 芒种: 4,
64
+ 小暑: 5, 立秋: 6, 白露: 7, 寒露: 8, 立冬: 9, 大雪: 10,
65
+ };
66
+
67
+ // 判断给定时刻位于哪个「节」之后 → 返回月支(0=寅 正月起)
68
+ export function monthBranchOf(y: number, m: number, d: number, hour: number, min = 0): number {
69
+ const t = new Date(y, m - 1, d, hour, min).getTime();
70
+ // 收集 y-1/y/y+1 三年的节时刻,取 t 之前最近的
71
+ let best: { name: string; time: number } | null = null;
72
+ for (const yy of [y - 1, y, y + 1]) {
73
+ for (const jq of getJieQiTableExact(yy)) {
74
+ if (JIE_BRANCH[jq.name] === undefined) continue; // 只取十二节
75
+ const tt = jq.time.getTime();
76
+ if (tt <= t && (!best || tt > best.time)) best = { name: jq.name, time: tt };
77
+ }
78
+ }
79
+ return best ? JIE_BRANCH[best.name] : 0;
80
+ }
81
+
82
+ // 判断给定时刻是否已过某「节」(精确,年柱用立春)
83
+ export function isAfterJie(y: number, m: number, d: number, hour: number, min: number, jieName: string): boolean {
84
+ const t = new Date(y, m - 1, d, hour, min).getTime();
85
+ for (const yy of [y - 1, y, y + 1]) {
86
+ for (const jq of getJieQiTableExact(yy)) {
87
+ if (jq.name === jieName && jq.time.getTime() <= t) return true;
88
+ }
89
+ }
90
+ return false;
91
+ }
92
+
93
+ /* ---------- 农历 / 黄历(万年历,供 almanac 模块与首页) ---------- */
94
+ export interface AlmanacDay {
95
+ lunarText: string; // 二〇二四年腊月廿六
96
+ ganzhiYear: string;
97
+ ganzhiMonth: string;
98
+ ganzhiDay: string;
99
+ shengxiao: string;
100
+ xingZuo: string;
101
+ jieQi: string | null; // 当天节气名
102
+ yi: string[];
103
+ ji: string[];
104
+ pengZu: string;
105
+ chong: string;
106
+ sha: string;
107
+ }
108
+
109
+ export function almanacOf(y: number, m: number, d: number): AlmanacDay {
110
+ const solar = Solar.fromYmdHms(y, m, d, 12, 0, 0);
111
+ const l = solar.getLunar();
112
+ const ec = l.getEightChar();
113
+ return {
114
+ lunarText: l.toString(),
115
+ ganzhiYear: ec.getYear(),
116
+ ganzhiMonth: ec.getMonth(),
117
+ ganzhiDay: ec.getDay(),
118
+ shengxiao: l.getYearShengXiao(),
119
+ xingZuo: solar.getXingZuo(),
120
+ jieQi: l.getJieQi() || null,
121
+ yi: l.getDayYi(),
122
+ ji: l.getDayJi(),
123
+ pengZu: l.getPengZuGan() + ' ' + l.getPengZuZhi(),
124
+ chong: l.getDayChongDesc(),
125
+ sha: l.getDaySha(),
126
+ };
127
+ }