8.3 KiB
8.3 KiB
架构文档(Architecture)
最后更新:2026-08-03
1. 项目概述
万年历(Lunar Calendar App):中国农历/黄历应用,提供农历转换、黄历宜忌、八字排盘、每日运势、梅花易数、称骨算命、节气等命理功能,移动端优先,支持 PWA 离线安装。
2. 技术栈
| 层 | 技术 |
|---|---|
| Monorepo | pnpm workspaces(packages/*) |
| 核心引擎 | TypeScript + tyme4ts ^1.5.1(历法/干支计算) |
| 构建 | tsup(core)、Vite 6 + tsc(web) |
| UI | React 19、React Router v7、Zustand 5、TailwindCSS v4(CSS-first)、Framer Motion、lucide-react |
| PWA | vite-plugin-pwa 0.21(Workbox,已启用) |
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.ts(tyme4ts → 纯对象)
│ └── 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 / bookmarks(Zustand)
├── 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 核心原则
- tyme4ts 对象永不进入 React:所有历法对象在
@lunar/core内转换为普通 JS 对象(DayInfo、AlmanacInfo、BaziFullResult等),React 层只消费纯数据。 - @lunar/core 零 UI 依赖:仅依赖 tyme4ts,可在任意 JS 运行时运行(web / Node / RN / 小程序)。
- 移动端优先:手机优先布局,桌面端自适应。
- 暗色模式:CSS 自定义属性 +
.darkclass,跟随系统偏好 + 手动切换。
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 |
仅构建 core(tsup,ESM+CJS) |
pnpm --filter @lunar/web build |
仅构建 web(tsc -b && vite build) |
pnpm preview |
预览构建产物 |
pnpm test |
core 单元测试(vitest,50 例) |
pnpm lint |
ESLint(flat config + typescript-eslint) |
pnpm clean |
清理 dist |
10. 已知架构问题(详见 BUGS.md)
- 梅花易数互卦为简化实现(上下卦互换,非真·互卦 2-4/3-5 爻法)
- 每日运势当日八字固定取午时;称骨极端总重仍取"最近值"
- 若干死代码(未使用的 hooks / 组件 / store action,见 BUGS.md 清单)