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

8.3 KiB
Raw Blame History

架构文档(Architecture

最后更新:2026-08-03

1. 项目概述

万年历(Lunar Calendar App):中国农历/黄历应用,提供农历转换、黄历宜忌、八字排盘、每日运势、梅花易数、称骨算命、节气等命理功能,移动端优先,支持 PWA 离线安装。

2. 技术栈

技术
Monorepo pnpm workspacespackages/*
核心引擎 TypeScript + 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 对象(DayInfoAlmanacInfoBaziFullResult 等),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 一览

类型

DayInfoAlmanacInfoHourAlmanacPillarInfoHideStemInfoEightCharInfoDecadeFortuneInfoFortuneInfoChildLimitInfoBaziFullResultPillarRelationshipDailyFortuneResultBirthParamsBranchRelationshipElementProfileTrigramInfoHexagramInfoPlumBlossomResultBoneWeightResult

函数

函数 说明
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 视图日期 / 选中日期 / 周起始 weekStartclearSelection 当前未被使用
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-pwaautoUpdate 模式 + Workbox 预缓存 + google-fonts 运行时缓存
  • 构建产物:manifest.webmanifestsw.jsregisterSW.js
  • manifest 已与 index.html 对齐(lang: zh-CNtheme_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 清单)