Files
lunar-mini/web/docs/ARCHITECTURE.md
T

163 lines
8.3 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 架构文档(Architecture
> 最后更新:2026-08-03
## 1. 项目概述
万年历(Lunar Calendar App):中国农历/黄历应用,提供农历转换、黄历宜忌、八字排盘、每日运势、梅花易数、称骨算命、节气等命理功能,移动端优先,支持 PWA 离线安装。
## 2. 技术栈
| 层 | 技术 |
|---|---|
| Monorepo | pnpm workspaces`packages/*` |
| 核心引擎 | TypeScript + [tyme4ts](https://github.com/6tail/tyme4ts) ^1.5.1(历法/干支计算) |
| 构建 | tsupcore)、Vite 6 + tscweb |
| UI | React 19、React Router v7、Zustand 5、TailwindCSS v4CSS-first)、Framer Motion、lucide-react |
| PWA | vite-plugin-pwa 0.21Workbox,已启用) |
## 3. 目录结构
```
lunar/
├── docs/ # 项目文档(本目录,含 RETROSPECT 会话回顾)
├── AGENTS.md # 开发代理指引
├── package.json # workspace 聚合脚本
├── pnpm-workspace.yaml # 工作区定义
├── tsconfig.base.json # 共享 TS 配置
└── packages/
├── core/ # @lunar/core —— 纯 TS 计算引擎,零 UI 依赖
│ ├── tsup.config.ts
│ └── src/
│ ├── index.ts # 公共 API 出口(barrel
│ ├── types/ # calendar.ts / bazi.ts / almanac.ts / fortune.ts
│ ├── transformers/ # day.ts / bazi.ts / almanac.ts / yearMonths.tstyme4ts → 纯对象)
│ └── calculators/ # dailyMatch / relationship / elementStrength / plumBlossom / boneWeight / buddhistDates / shensha / fortuneLuck
└── web/ # @lunar/web —— React 应用
├── vite.config.ts # Vite + Tailwind v4 + PWA
├── index.html
└── src/
├── App.tsx # 路由 + 懒加载 + 页面过渡 + ErrorBoundary
├── main.tsx
├── styles/globals.css # 设计令牌(亮/暗主题)
├── lib/utils.ts # cn、日期格式化等工具
├── stores/ # calendar / user / settings / ui / bookmarksZustand
├── hooks/ # useCalendar / useDayDetail / useBazi / useDailyFortune
├── components/
│ ├── calendar/ # CalendarGrid / CalendarCell / MonthYearPicker / WeekDayBar
│ ├── layout/ # AppShell / Header / BottomNav
│ ├── ui/ # Badge / Button / Card / AnimatedPanel / ErrorBoundary / Skeleton
│ ├── day-detail/ bazi/ daily-fortune/(页面内联实现,目录内暂无独立组件)
└── pages/ # 8 个页面(见路由表)
```
## 4. 分层设计
```
┌───────────────────────────────┐
│ @lunar/web (React 页面层) │
│ pages → hooks → stores │
├───────────────────────────────┤
│ @lunar/core (纯计算引擎) │
│ index.ts │
│ ├─ transformers tyme4ts → │
│ │ 纯 JS 对象 │
│ ├─ calculators 业务算法 │
│ └─ types 类型定义 │
├───────────────────────────────┤
│ tyme4ts (历法计算源) │
└───────────────────────────────┘
```
### 4.1 核心原则
1. **tyme4ts 对象永不进入 React**:所有历法对象在 `@lunar/core` 内转换为普通 JS 对象(`DayInfo``AlmanacInfo``BaziFullResult` 等),React 层只消费纯数据。
2. **@lunar/core 零 UI 依赖**:仅依赖 tyme4ts,可在任意 JS 运行时运行(web / Node / RN / 小程序)。
3. **移动端优先**:手机优先布局,桌面端自适应。
4. **暗色模式**CSS 自定义属性 + `.dark` class,跟随系统偏好 + 手动切换。
### 4.2 数据流示例
```
SolarDay (tyme4ts)
→ solarDayToDayInfo() # DayInfo
→ solarDayToAlmanacInfo() # AlmanacInfo(含 12 时辰)
→ birthInfoToBazi() # BaziFullResult(四柱/十神/大运…)
→ calculateDailyFortune() # DailyFortuneResult(每日运势)
```
## 5. @lunar/core API 一览
### 类型
`DayInfo``AlmanacInfo``HourAlmanac``PillarInfo``HideStemInfo``EightCharInfo``DecadeFortuneInfo``FortuneInfo``ChildLimitInfo``BaziFullResult``PillarRelationship``DailyFortuneResult``BirthParams``BranchRelationship``ElementProfile``TrigramInfo``HexagramInfo``PlumBlossomResult``BoneWeightResult`
### 函数
| 函数 | 说明 |
|---|---|
| `solarDayToDayInfo(solarDay)` | SolarDay → DayInfo(含季节/节气进度/儒略日/佛历/伊斯兰历/佛教节日) |
| `getDayInfo(y, m, d)` / `getTodayInfo()` | 获取某日/今日信息 |
| `getMonthCalendar(y, m, weekStart?)` | 月历二维数组(周 × 天),可指定周起始 |
| `solarDayToAlmanacInfo(solarDay)` | SolarDay → AlmanacInfo |
| `getAlmanacInfo(y, m, d)` | 获取黄历信息(宜忌/值神/冲煞/时辰) |
| `birthInfoToBazi(params)` | 出生信息 → 完整八字排盘(`ziSect` 流派参数:晚子时换日) |
| `getYearMonths(year)` | 按节气月返回某年 12 个流月 |
| `getBranchRelationship(a, b)` | 地支六合/三合/六冲/六害/相刑 |
| `getTenStarRelationship(s, o)` / `checkStemCombine` / `checkStemOpposite` | 干支关系判断 |
| `calculateDailyFortune(userBazi, date)` | 用户八字 × 日期 → 每日运势评分 |
| `analyzeElementBalance(bazi)` | 五行力量分析 |
| `calculatePlumBlossom(y, m, d, h?)` | 梅花易数起卦 |
| `calculateBoneWeight(...)` | 袁天罡称骨算命 |
| `getBuddhistFestival(lunarMonth, lunarDay)` | 农历佛教节日 |
| `analyzeShensha(bazi)` | 22 个常见神煞 |
| `analyzeFortuneGanzhi(ganzhi, dayStem, dayBranch)` | 大运/流年/流月/流日 vs 日主生克冲合 |
## 6. 前端状态管理(Zustand
| Store | 持久化 Key | 职责 | 备注 |
|---|---|---|---|
| `calendar` | — | 视图日期 / 选中日期 / 周起始 | `weekStart``clearSelection` 当前未被使用 |
| `user` | `lunar-user-profiles` | 出生档案(最多 3 个)、active 档案、八字结果 | |
| `settings` | `lunar-settings` | 主题、周起始、显示开关、八字来源 | `showLunar` 等 4 个字段未被消费 |
| `ui` | — | 侧栏 / 移动端 / 底部面板 | 多数 action 未被消费 |
| `bookmarks` | `lunar-bookmarks` | 日期收藏(标记在日历格上) | `getByDate`/`getByLunarDate` 未使用 |
## 7. 路由(React Router v7,全部懒加载)
| 路径 | 页面 | 底部导航 |
|---|---|---|
| `/` | HomePage(今日概览) | ✔ |
| `/calendar` | CalendarPage(月/周视图) | ✔ |
| `/calendar/:date` | DayDetailPage(日详情) | — |
| `/bazi` | BaziPage(八字排盘) | ✔ |
| `/daily-fortune` | DailyFortunePage(每日运势) | ✔ |
| `/settings` | SettingsPage(设置) | ✔ |
| `/divination` | DivinationPage(梅花易数 + 称骨) | 首页快捷入口 |
| `/solar-terms` | SolarTermsPage(节气) | 首页快捷入口 |
| `*` | 重定向 `/` | — |
## 8. PWA(已启用)
- `vite-plugin-pwa`autoUpdate 模式 + Workbox 预缓存 + google-fonts 运行时缓存
- 构建产物:`manifest.webmanifest``sw.js``registerSW.js`
- manifest 已与 index.html 对齐(`lang: zh-CN``theme_color: #FFFBF5`
## 9. 构建与命令
| 命令 | 说明 |
|---|---|
| `pnpm dev` | 启动 web dev(端口 4258 |
| `pnpm build` | 构建 core → web |
| `pnpm --filter @lunar/core build` | 仅构建 coretsupESM+CJS |
| `pnpm --filter @lunar/web build` | 仅构建 webtsc -b && vite build |
| `pnpm preview` | 预览构建产物 |
| `pnpm test` | core 单元测试(vitest50 例) |
| `pnpm lint` | ESLintflat config + typescript-eslint |
| `pnpm clean` | 清理 dist |
## 10. 已知架构问题(详见 BUGS.md)
- 梅花易数互卦为简化实现(上下卦互换,非真·互卦 2-4/3-5 爻法)
- 每日运势当日八字固定取午时;称骨极端总重仍取"最近值"
- 若干死代码(未使用的 hooks / 组件 / store action,见 BUGS.md 清单)