feat: 祈福小助手万年历小程序第一期

This commit is contained in:
gouki
2026-08-06 08:47:09 +00:00
commit a3e6aa9c01
136 changed files with 16597 additions and 0 deletions
+162
View File
@@ -0,0 +1,162 @@
# 架构文档(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 清单)
+64
View File
@@ -0,0 +1,64 @@
# BUG 记录(Known Issues
> 最后更新:2026-08-02
> 严重度:🔴 高(影响功能/构建) · 🟠 中 · 🟡 低
> 状态:⬜ 待修复 · 🔧 修复中 · ✅ 已修复
## 0. 已修复汇总(2026-08-02
- BUG-01 core CJS 导出 · BUG-02 周起始设置 · BUG-05 lint · BUG-07 版本号 · BUG-08 死分支
- BUG-03 PWA manifest 与 index.html 对齐(lang=zh-CN、theme_color 统一)
- BUG-09 日历页"回到今天"按钮永不显示(条件恒为 false)
- BUG-10 日详情页时辰列表重复 React key(早子/晚子均为"子",改用 ganzhi 作 key
- TECH-03 更正:梅花卦库实测 **64/64 完整**(原 review 报告"缺 8 卦"不属实),已添加测试锁定
- TECH-06 以 `solarAdjusted` 类型安全字段替代 `(as any)._solarAdjusted`
- TECH-04 称骨数据表整体修正(年表主流版本 + 日表初五 + 歌诀 21~72 补全)
- TECH-05 占卜页称骨年索引改用出生年干支
- 新增单元测试 50 个(vitest)与 ESLint 配置
- 功能深化:八字流派/出生地全国化/海外时区/太阳时开关、神煞、大运流年流月流日交互、历法信息、佛教节日(见 CHANGELOG)
## 1. 已知 BUG
| ID | 严重度 | 状态 | 位置 | 描述 |
|---|---|---|---|---|
| BUG-01 | 🟠 | ✅ | `packages/core` | ~~exports.require 指向不存在的 dist/index.cjs~~ → tsup 改为 `format: ['esm','cjs']``dist/index.cjs` 已生成并通过 `require()` 验证 |
| BUG-02 | 🟠 | ✅ | `useCalendar` / `CalendarGrid` / `WeekDayBar` / `CalendarPage` | ~~周一开始设置无效~~`settings.weekStartDay` 已贯通至 `getMonthCalendar(weekStart)` 与表头渲染 |
| BUG-03 | 🟡 | ✅ | `vite.config.ts` / `index.html` | ~~PWA manifest lang=en、theme_color 不一致~~ → manifest 增加 `lang: zh-CN``theme_color` 统一为 `#FFFBF5`,与 index.html 一致 |
| BUG-04 | 🟡 | ⬜ | `HomePage`InfoCard | `highlight` prop 传为布尔值,但渲染时当作 `border-primary/30` 样式类处理,语义不符(需确认意图) |
| BUG-05 | 🟡 | ✅ | 根 `package.json` | ~~pnpm lint 失败~~ → 已配置 ESLint 9 flat config + typescript-eslint,两个包均通过 |
| BUG-06 | 🟡 | ⬜ | `pnpm-workspace.yaml` | `allowBuilds` 不是 pnpm 标准字段(应为 `onlyBuiltDependencies`),疑似无效配置 |
| BUG-07 | 🟡 | ✅ | `SettingsPage` 关于区 | ~~版本号 v0.2~~ → 与 package.json 统一为 v0.1.0 |
| BUG-08 | 🟡 | ✅ | `transformers/day.ts` | ~~getMonthCalendar 死分支~~ → 已移除 if/else 相同调用 |
| BUG-09 | 🟡 | ✅ | `CalendarPage.tsx` | ~~"回到今天"按钮永不显示~~ → 条件误用 `todaySummary.di.isToday`(恒为 true),改为基于 `viewDate` 判断是否正在查看今天;已在浏览器实测 |
| BUG-10 | 🟡 | ✅ | `DayDetailPage.tsx` | ~~时辰列表重复 React key~~`getHours()` 返回 13 个时辰(早子 00:00 / 晚子 23:00 均为地支"子"),原用 `h.branch` 作 key 冲突,改为唯一的 `h.ganzhi`;已在浏览器实测无警告 |
## 2. 算法近似 / 技术债
> 非紧急,但应在后续迭代中改善。
| ID | 位置 | 说明 |
|---|---|---|
| TECH-01 | `calculators/dailyMatch.ts` | 当日八字固定取午时(`getHours()[6]`),无法体现时辰差异 |
| TECH-02 | `calculators/plumBlossom.ts` | 互卦为简化实现(上下卦互换),非真·互卦(2-4/3-5 爻法) |
| TECH-03 | `calculators/plumBlossom.ts` | ✅ 已核实:数据集 64/64 完整,`plumBlossom.test.ts` 含完整性校验用例 |
| TECH-04 | `calculators/boneWeight.ts` | ✅ 已修复:歌诀补全 2两1钱~7两2钱(原缺 5两8钱/5两9钱/6两1钱/6两3钱/6两5钱/6两7钱/6两9钱/7两1钱,此前这些总重会错误地取"最近值");年表已按主流版本整体修正(原混用两套网络变体错约 40 处),日表修正初五重量 |
| TECH-05 | `DivinationPage` | ✅ 已修复:称骨年索引改用出生年干支(`ec.yearPillar.ganzhi`),不再用日干支近似 |
| TECH-06 | `types/bazi.ts` | ✅ 已修复:`BaziFullResult` 新增 `solarAdjusted?: boolean`,替代 `(as any)` 补丁 |
| TECH-07 | `calculators/elementStrength.ts` | 五行推断按天干名字映射而非复用 tyme4ts 元素定义(可接受但存在重复逻辑) |
| TECH-08 | `lib/utils.ts` | `getChineseDayName` / `getChineseMonthName` 未使用 |
## 3. 死代码清单
| 位置 | 内容 | 建议 |
|---|---|---|
| `hooks/useDayDetail.ts` | 从未被 import | 删除或接入 DayDetailPage |
| `hooks/useBazi.ts` | 从未被 import(本轮仅修复了其 lint 错误) | 删除或接入 BaziPage |
| `components/ui/AnimatedPanel.tsx` | 从未使用 | 删除或接入日详情弹层 |
| `components/ui/Card.tsx` `CardHeader` | 未使用 | 删除导出 |
| `components/ui/Skeleton.tsx` `CalendarSkeleton`/`BaziSkeleton` | 未使用 | 删除 |
| `stores/ui.ts` | `toggleSideNav`/`closeSideNav`/`setActiveTab`/`openDayDetail`/`closeDayDetail``activeTab`/`showDayDetail` 未被消费 | 精简或接入 |
| `stores/settings.ts` | `showLunar`/`showSolarTerm`/`showHoliday`/`eightCharProvider` 及对应 toggle 未被读取 | 接入设置页或删除 |
| `stores/calendar.ts` | `weekStart`/`setWeekStart`/`clearSelection` 未使用(周起始现直接读 settings store | 删除 |
| `stores/bookmarks.ts` | `getByDate`/`getByLunarDate` 未使用 | 配合农历收藏规划 |
| `lib/utils.ts` | `getChineseDayName`/`getChineseMonthName` | 删除 |
| web 依赖 | `tailwind-variants` 从未 import | 移除依赖 |
+80
View File
@@ -0,0 +1,80 @@
# 变更日志(Changelog
> 格式参考 [Keep a Changelog](https://keepachangelog.com/zh-CN/)。版本号遵循 SemVer。
## [Unreleased]
### 文档
- 新增 `docs/` 文档体系:架构(ARCHITECTURE)、需求(REQUIREMENTS)、进度(PROGRESS)、BUGBUGS)、变更日志(CHANGELOG
- 更新 `AGENTS.md` / `CLAUDE.md`:补全新页面/Store/API、修正 PWA 状态、指向文档目录
### 功能
- **八字流派切换**`birthInfoToBazi` 新增 `ziSect` 参数,设置页新增"八字流派"选项(晚子时算次日 23点换日 / 晚子时算当日 0点换日),BaziPage 排盘实时生效;浏览器实测两种流派排出不同日柱/时柱
- **出生时间选择器**:BaziPage 出生时间改为 时/分 下拉选择器(替代不对称的 −/+ 步进),时辰格可点击快速设置时辰
- **出生地全国化 + 海外时区**:出生地列出全国 34 个省级城市(含省会经度真太阳时校正),新增"海外"模式按时区(UTC-12~+14,含半小时时区)将当地出生时间换算为北京时间(UTC+8)排盘;换算与真太阳时校正均按日期运算处理,支持跨日回退(浏览器实测:UTC-5 23:30 → 次日北京 12:30;乌鲁木齐 00:30 真太阳 → 前日 22:20
- **真太阳时校正开关**:设置页新增"真太阳时校正"开关(默认开启);关闭后中国出生按北京时间直接排盘,海外时区换算不受影响(浏览器实测:关闭时乌鲁木齐 00:30 排日柱己酉,开启时排戊申)
- **宜忌完整显示**:引擎本就返回完整黄历宜忌(如 8/3 共 22 条宜),此前首页 `slice(0,6)` 截断导致显得比别的黄历站少;已放开并标注总数
- **历法信息增强**:DayInfo 新增季节、所处节气/第几天/距下节气天数、儒略日、佛历年(公历+543)、伊斯兰历日期(tyme4ts 原生支持 Hijri),日详情页新增"历法信息"卡片
- **佛教节日**:tyme4ts 无佛教日期支持,新增 `getBuddhistFestival`(农历 21 个重大佛教节日表),日详情页显示 🪷 徽章
- **八字神煞**:新增 `analyzeShensha`(22 个常见神煞:天乙/天厨/文昌贵人、禄神、羊刃、金舆、天德/月德贵人、桃花、驿马、华盖、劫煞、亡神、将星、红鸾、天喜、孤辰、寡宿、天罗、地网、魁罡、阴差阳错),八字页新增"神煞"卡片;查法采用主流排盘工具版本(神煞版本差异已在文档注明)
- **大运/流年生克冲合**:新增 `analyzeFortuneGanzhi`(任意干支 vs 日主:十神、五行生克 生我/我生/克我/我克/比和、天干合冲、地支六合三合冲害刑、吉凶分级);八字页"起运·大运"改为全量 10 个大运并附生克冲合,新增"流年(小运)"10 条卡片
- **今日流年·流月·流日**:八字页新增卡片,用今日年/月/日干支 vs 日主展示生克冲合
- **大运·流年·流月·流日交互下钻**:core 新增 `getYearMonths(year)`(按节气月返回 12 个流月);八字页改为交互浏览器——点选大运 → 流年(按年度切换)→ 流月 12 chips → 该月每日流日列表(带吉凶点与十神),点击日期跳转日详情页;默认定位到当前年份/月份
### 修复
- **称骨算命数据表整体修正**:年份表改为主流通行版本(原混用两套网络变体错约 40 处);日表修正初五(1两6钱);歌诀补全 2两1钱~7两2钱全部 52 条(原缺 5两8钱~7两1钱共 8 条,此前这些总重错误取"最近值")
- **占卜页称骨年索引**:改用出生年干支(`ec.yearPillar.ganzhi`),不再用日干支近似
- **BUG-01**core 包改为同时输出 ESM + CJS`exports.require` 指向的 `dist/index.cjs` 现在真实存在并通过 `require()` 验证
- **BUG-02**:周起始设置生效 —— `settings.weekStartDay` 贯通 `useCalendar``getMonthCalendar(weekStart)``WeekDayBar` 表头渲染
- **BUG-03**PWA manifest 对齐 —— `lang: zh-CN``theme_color` 统一为 `#FFFBF5`(与 index.html 一致)
- **BUG-05**:配置 ESLint 9 flat config + typescript-eslint`pnpm lint` 通过(修复 24 处代码问题)
- **BUG-07**:设置页版本号统一为 0.1.0
- **BUG-08**:移除 `getMonthCalendar` 中的死分支
- **BUG-09**:日历页"回到今天"浮动按钮恢复正常 —— 原条件 `todaySummary.di.isToday` 恒为 true 导致按钮永不显示,改为基于 `viewDate` 判断(浏览器实测:非本月可见、点击返回本月)
- **BUG-10**:日详情页时辰列表重复 key 修复 —— 早子/晚子地支均为"子",key 改用唯一的干支(`h.ganzhi`
- **TECH-06**`BaziFullResult` 新增 `solarAdjusted?: boolean` 字段,替代 `(as any)._solarAdjusted` 非类型安全补丁
### 工程
-@lunar/core 引入 vitest 单元测试(7 个测试文件 / 29 个用例),覆盖历法转换、八字排盘、每日运势、梅花易数(含 64 卦完整性校验)、称骨、干支关系、五行分析
- 根与子包新增 `test` / `lint` 脚本;根 package.json 标记 `"type": "module"`
- 核实梅花卦库为 64/64 完整(此前 review 报告"缺 8 卦"不属实),并以测试固化
### 已知问题(见 docs/BUGS.md
- 梅花易数互卦仍为简化实现(上下卦互换)
- 每日运势当日八字固定取午时;称骨年索引用日干支近似
- PWA manifest `lang`/`theme_color` 不一致;死代码待清理
## [0.1.0] - 2026-06-07
首个可用版本(monorepo 初始化于 2026-06-06)。
### 新增 — @lunar/core
- 历法转换:`getDayInfo` / `getTodayInfo` / `getMonthCalendar` / `solarDayToDayInfo`
- 黄历:`getAlmanacInfo` / `solarDayToAlmanacInfo`(含 12 时辰逐时黄历)
- 八字:`birthInfoToBazi`(四柱、十神、藏干、十二长生、胎元胎息、命宫身宫、空亡、起运、10 大运、10 流年)
- 干支关系:`getBranchRelationship` / `getTenStarRelationship` / `checkStemCombine` / `checkStemOpposite`
- 五行分析:`analyzeElementBalance`
- 每日运势:`calculateDailyFortune`(四柱打分、宜忌、幸运色/数/方位、分项得分)
- 占卜:`calculatePlumBlossom`(梅花易数,56/64 卦)、`calculateBoneWeight`(袁天罡称骨)
### 新增 — @lunar/web
- 路由与骨架:8 页面懒加载、页面过渡动画、ErrorBoundary、Suspense 骨架屏
- 首页:今日概览、宜忌、运势预览、快捷入口
- 日历:月/周视图、年/月切换、收藏星标、运势点、滑动切月、日详情页(四柱/黄历/12 时辰/收藏)
- 八字排盘页:档案管理(最多 3 个,localStorage 持久化)、排盘全览、称骨
- 每日运势页:日期导航、评分与建议
- 占卜页:梅花易数今日卦象、称骨
- 节气页:全年 24 节气
- 设置页:主题切换(亮/暗/跟随系统)、周起始、阴阳历转换、今日干支
- 状态管理:Zustand 5 个 storecalendar / user / settings / ui / bookmarks
- PWAvite-plugin-pwa 集成(autoUpdate + Workbox 预缓存)
- 设计系统:Tailwind v4 设计令牌(亮/暗主题)、Badge / Button / Card / Skeleton
### 已知问题(见 docs/BUGS.md
- core 包 require 导出指向不存在的 `dist/index.cjs`
- 周起始设置未生效
- 梅花易数互卦简化、卦库缺 8 卦;称骨年索引用日干支近似
- 无自动化测试、无 lint
+49
View File
@@ -0,0 +1,49 @@
# 开发进度(Progress
> 最后更新:2026-08-03
## 1. 里程碑
| 里程碑 | 时间 | 内容 | 状态 |
|---|---|---|---|
| M0 项目初始化 | 2026-06-06 | monorepo 脚手架、tsconfig、workspace、核心类型定义 | ✅ |
| M1 核心引擎 | 2026-06-06 ~ 06-07 | transformersday/almanac/bazi)、calculatorsrelationship/elementStrength | ✅ |
| M2 高级算法 | 2026-06-07 | dailyMatch(每日运势)、plumBlossom(梅花)、boneWeight(称骨) | ✅ |
| M3 前端页面 | 2026-06-07 | 8 个页面、5 个 store、路由、布局、组件库 | ✅ |
| M4 构建与 PWA | 2026-06-07 | Vite 构建、tsup、PWA 集成(Workbox 缓存) | ✅ |
| M5 文档化 | 2026-08-02 | 架构/需求/进度/BUG/CHANGELOG 文档建立 | ✅ |
| M6 质量加固 | 2026-08-02 | 单元测试(vitest)、ESLint、CJS 导出修复、周起始修复、版本号 | ✅ |
| M7 功能深化 | 2026-08-02 ~ 08-03 | 称骨数据修正、八字流派/出生地/太阳时开关、神煞、大运流年流月流日交互、历法信息、佛教节日 | ✅ |
| M8 收尾 | 2026-08-03 | README、文档整理、源码打包(node_modules 清理) | ✅ |
> 注:主体功能于 2026-06-06 ~ 06-07 完成;2026-08-02 ~ 08-03 进行质量加固与功能深化。
## 2. 当前状态
- **可运行**`pnpm dev` 可启动,`pnpm build` 可产出 coreESM+CJS+ web 产物(含 PWA)。
- **质量**:50 个单元测试通过(vitest)、`pnpm lint` 通过(ESLint flat config + typescript-eslint)。
- 剩余 BUG 与技术债见 BUGS.md。
## 3. 待办清单(Backlog
按优先级排序:
| 优先级 | 事项 | 类型 | 关联 | 状态 |
|---|---|---|---|---|
| P0 | 修复 core 包 `require` 导出指向不存在的 `dist/index.cjs` | BUG | BUG-01 | ✅ |
| P1 | 周起始设置生效 | 功能 | BUG-02 | ✅ |
| P1 | 为 core 算法补充单元测试 | 工程 | N5 | ✅ 50 例 |
| P2 | 六十四卦数据补全 | 算法 | C10 | ✅ 已核实 64/64 完整,测试锁定 |
| P2 | 互卦算法实现真·互卦(2-4/3-5 爻) | 算法 | C10 | ⬜ |
| P2 | 清理死代码(useDayDetail/useBazi、AnimatedPanel、CardHeader、未用 store action 等) | 工程 | — | ⬜ |
| P3 | PWA manifest 修复 | BUG | BUG-03 | ✅ |
| P3 | 农历周期收藏 UI | 功能 | M2 | ⬜ |
| P3 | 收藏列表页 | 功能 | M3 | ⬜ |
| P4 | 配置 lint 并修复 `pnpm lint` | 工程 | N6 | ✅ |
| P4 | 显示开关字段真正消费(showLunar 等) | 功能 | T6 | ⬜ |
| P4 | 版本号统一(0.1.0 | BUG | BUG-07 | ✅ |
| P4 | 称骨数据表整体修正(年表/日表/歌诀) | 算法 | C11 | ✅ |
| P4 | 占卜页称骨年索引用出生年干支 | 算法 | TECH-05 | ✅ |
| P5 | 每日运势当日八字取午时 → 改为可选时辰 | 算法 | C9 | ⬜ |
| P5 | 称骨极端总重仍取"最近值" → 提示超出范围 | 算法 | TECH-04 | ⬜ |
| P5 | README 编写 | 工程 | M8 | ✅ |
+142
View File
@@ -0,0 +1,142 @@
# 需求文档(Requirements & 功能清单)
> 最后更新:2026-08-02
> 状态说明:✅ 已完成 · 🟡 部分完成 / 有已知问题 · ⬜ 规划中
## 1. 需求总览
| 模块 | 状态 | 说明 |
|---|---|---|
| 历法核心引擎(@lunar/core) | ✅ | 农历/干支/黄历/八字/运势算法 |
| 万年历(首页 + 日历 + 日详情) | ✅ | 功能齐全(周起始设置已修复) |
| 八字排盘 | 🟡 | 功能齐全,含一个非类型安全补丁 |
| 每日运势 | ✅ | 依赖用户档案 |
| 占卜工具(梅花易数 / 称骨) | 🟡 | 算法为简化实现(见备注) |
| 节气 | ✅ | 24 节气列表 |
| 用户档案 + 设置 | 🟡 | 部分设置字段未生效 |
| 收藏 | 🟡 | 仅支持公历单日收藏 |
| PWA | ✅ | 已构建,manifest 有瑕疵 |
## 2. 功能点清单
### 2.1 历法核心(@lunar/core
| # | 功能点 | 描述 | 状态 |
|---|---|---|---|
| C1 | 日期转换 | tyme4ts → DayInfo(公历/农历/干支/星座/生肖/节日/假日/月相) | ✅ |
| C2 | 月历生成 | `getMonthCalendar` 周×天网格,含相邻月补位 | ✅ |
| C3 | 黄历信息 | 宜忌、值神(日/时)、十二/廿八/九/六曜星、彭祖百忌、胎神、冲煞、纳音、三合/六合 | ✅ |
| C4 | 时辰黄历 | 12 时辰逐时黄历(buildHourlyAlmanac | ✅ |
| C5 | 八字排盘 | 四柱、十神、藏干、十二长生、胎元/胎息、命宫/身宫、空亡、起运 | ✅ |
| C6 | 大运/流年 | 10 大运 + 10 流年 | ✅ |
| C7 | 干支关系 | 六合/三合/六冲/六害/相刑/三合局/天干合冲 | ✅ |
| C8 | 五行分析 | 五行力量统计(藏干 0.5 权重)、旺衰、平衡度 | ✅ |
| C9 | 每日运势 | 四柱逐柱 vs 当日干支打分(日 40%/月 25%/年 20%/时 15%),输出评分、宜忌、幸运色/数/方位、分项(感情/事业/财运/健康) | 🟡 当日八字固定取午时 |
| C10 | 梅花易数 | 时间起卦、变卦、互卦(简化)、体用关系、64 卦辞 | 🟡 互卦简化为上下互换(卦库 64/64 完整,已有测试) |
| C11 | 称骨算命 | 年/月/日/时称骨表 + 52 首解诗(2两1钱~7两2钱完整) | ✅ 数据表已按主流版本修正,歌诀补全(极端值仍取最近) |
| C12 | 历法信息 | 季节、所处节气/第几天/距下节气、儒略日、佛历年、伊斯兰历(Hijri) | ✅ |
| C13 | 佛教节日 | 农历 21 个重大佛教节日(`getBuddhistFestival`) | ✅ 日详情页 🪷 徽章展示 |
| C14 | 八字神煞 | 22 个常见神煞(`analyzeShensha` | ✅ 八字页"神煞"卡片 |
| C15 | 大运/流年 vs 日主生克冲合 | 十神、五行生克、天干合冲、地支关系、吉凶(`analyzeFortuneGanzhi` | ✅ |
| C16 | 流年·流月·流日分析 | 任意日期年/月/日干支 vs 日主(`getYearMonths` 按节气月) | ✅ 八字页交互浏览器 |
### 2.2 首页 HomePage`/`
| # | 功能点 | 状态 |
|---|---|---|
| H1 | 今日概览:日期、农历、干支、宜忌摘要 | ✅ |
| H2 | 运势预览(需档案) | ✅ |
| H3 | 快捷导航(占卜、节气) | ✅ |
| H4 | 值神/彭祖/胎神展示 | ✅ |
### 2.3 日历 CalendarPage`/calendar`
| # | 功能点 | 状态 |
|---|---|---|
| K1 | 月视图/周视图切换 | ✅ |
| K2 | 年/月切换(MonthYearPicker | ✅ |
| K3 | 格子显示:节日/节气缩写、农历、周末/今日高亮、收藏星标、运势点 | ✅ |
| K4 | 点击日期 → 日详情页 | ✅ |
| K5 | 手势滑动切换月份 | ✅ |
| K6 | 周起始(周一/周日)设置生效 | ✅ 已修复(BUG-02) |
| K7 | 非本月时显示"回到今天"浮动按钮,点击返回当月 | ✅ 已修复(BUG-09) |
### 2.4 日详情 DayDetailPage`/calendar/:date`
| # | 功能点 | 状态 |
|---|---|---|
| D1 | 四柱、纳音、值星展示 | ✅ |
| D2 | 冲合害煞、宜忌列表 | ✅ |
| D3 | 值神、彭祖百忌、胎神 | ✅ |
| D4 | 12 时辰逐时黄历 | ✅ |
| D5 | 收藏按钮 | ✅ 仅公历收藏 |
### 2.5 八字 BaziPage`/bazi`
| # | 功能点 | 状态 |
|---|---|---|
| B1 | 出生档案管理(最多 3 个,持久化) | ✅ |
| B2 | 排盘:四柱 + 十神 + 藏干 | ✅ |
| B3 | 五行力量 / 十二长生展示 | ✅ |
| B4 | 起运 / 大运 / 流年 | ✅ |
| B5 | 称骨集成 | ✅ 使用出生年干支(占卜页已同步修正) |
| B6 | 日柱类型安全 | ✅ `solarAdjusted` 字段替代 `(as any)` 补丁 |
| B7 | 八字流派切换(晚子时换日 23点 / 0点换日) | ✅ 设置页可切换,排盘实时生效 |
| B8 | 出生地:全国 34 省级城市真太阳时校正 | ✅ 含跨日处理,受"真太阳时校正"开关控制 |
| B9 | 出生地:海外时区 → 北京时间(UTC+8)换算排盘 | ✅ 含跨日处理 |
| B10 | 神煞展示(22 个常见神煞,吉/凶/中性分组) | ✅ |
| B11 | 大运全量 10 条 + 流年(小运)10 条,均附生克冲合 | ✅ |
| B12 | 大运→流年→流月→流日交互下钻(按年度切换) | ✅ 点选日期跳转日详情 |
### 2.6 每日运势 DailyFortunePage`/daily-fortune`
| # | 功能点 | 状态 |
|---|---|---|
| F1 | 日期导航查看任意日运势 | ✅ |
| F2 | 无档案时引导创建 | ✅ |
| F3 | 评分等级、宜忌、幸运信息、分项得分 | ✅ |
### 2.7 占卜 DivinationPage`/divination`
| # | 功能点 | 状态 |
|---|---|---|
| P1 | 今日梅花易数卦象 + 体用分析 | 🟡 算法简化 |
| P2 | 称骨算命输入与结果 | 🟡 年索引用日干支近似 |
### 2.8 节气 SolarTermsPage`/solar-terms`
| # | 功能点 | 状态 |
|---|---|---|
| S1 | 全年 24 节气列表 | ✅ |
### 2.9 设置 SettingsPage`/settings`
| # | 功能点 | 状态 |
|---|---|---|
| T1 | 档案管理入口 | ✅ |
| T2 | 农历日期查询(阴阳历转换) | ✅ |
| T3 | 今日天干地支/纳音 | ✅ |
| T4 | 主题切换(亮/暗/跟随系统) | ✅ |
| T5 | 周起始设置 | ✅ 已修复(BUG-02) |
| T6 | 显示开关(农历/节气/假日)、八字来源 | 🟡 字段已持久化但未消费 |
| T7 | 关于:版本号 | ✅ 已统一为 0.1.0BUG-07 |
| T8 | 真太阳时校正开关(默认开启) | ✅ 关闭后按北京时间排盘 |
### 2.10 收藏 Bookmarks
| # | 功能点 | 状态 |
|---|---|---|
| M1 | 收藏/取消收藏日期,日历格星标 | ✅ |
| M2 | 农历周期收藏(每年/月循环) | ⬜ 字段已预留,UI 未提供 |
| M3 | 收藏列表页 | ⬜ 规划中 |
### 2.11 非功能需求
| # | 需求 | 状态 |
|---|---|---|
| N1 | PWA 可安装、离线可用 | ✅ 已构建 |
| N2 | 移动端优先响应式 | ✅ |
| N3 | 暗色模式(跟随系统) | ✅ |
| N4 | 页面懒加载 + 骨架屏 + 错误边界 | ✅ |
| N5 | 自动化测试 | ✅ 2026-08-02 引入 vitest29 个用例(历法/八字/运势/梅花/称骨/干支) |
| N6 | Lint / 代码规范 | ✅ 2026-08-02 配置 ESLint 9 flat config + typescript-eslint`pnpm lint` 通过 |
+74
View File
@@ -0,0 +1,74 @@
# 开发回顾记录(Retrospect
> 会话日期:2026-08-02 ~ 2026-08-03
> 用途:记录本次会话"做了什么 / 没做什么 / 有疑问的事项",便于事后回顾与决策。
## 一、本次完成的工作
### 1. 文档体系(docs/
- 新建 `docs/`ARCHITECTURE / REQUIREMENTS / PROGRESS / BUGS / CHANGELOG,另加根 README.md
- 修正 AGENTS.md / CLAUDE.md 的过时信息(PWA 状态、页面/Store/API 补全),并持续同步
### 2. BUG 修复(BUGS.md 均已标记 ✅)
| ID | 内容 |
|---|---|
| BUG-01 | core 包 CJS 导出:tsup 增加 cjs 产物,`require()` 实测可用 |
| BUG-02 | 周起始设置生效:settings → useCalendar → getMonthCalendar(weekStart) → WeekDayBar |
| BUG-03 | PWA manifest 对齐(lang=zh-CN、theme_color=#FFFBF5 |
| BUG-05 | 配置 ESLint 9 flat config + typescript-eslint`pnpm lint` 通过(修复 24 处) |
| BUG-07 | 版本号统一 v0.1.0 |
| BUG-08 | getMonthCalendar 死分支移除 |
| BUG-09 | "回到今天"按钮条件恒 false,改为基于 viewDate 判断 |
| BUG-10 | 日详情时辰列表重复 React key(早子/晚子均"子"),改用 ganzhi 作 key |
| TECH-06 | `(as any)._solarAdjusted``BaziFullResult.solarAdjusted` 类型化 |
### 3. 功能深化
- **八字流派切换**`birthInfoToBazi` 新增 `ziSect`(晚子时算次日/当日),设置页开关
- **出生时间选择器**:时/分下拉 + 时辰格可点
- **出生地全国化 + 海外时区**:34 省级城市(真太阳时校正)+ 海外 UTC-12~+14 换算北京时间,均支持跨日
- **真太阳时校正开关**(设置页,默认开启)
- **宜忌完整显示**:根因是首页 `slice(0,6)`,引擎本有 22 条宜
- **历法信息增强**:DayInfo 新增 季节/所处节气/第几天/距下节气/儒略日/佛历年/伊斯兰历(tyme4ts 原生 Hijri
- **佛教节日**:新增 `getBuddhistFestival`(农历 21 个节日),日详情 🪷 徽章
- **八字神煞**:新增 `analyzeShensha`(22 个常见神煞),八字页"神煞"卡
- **大运/流年生克冲合**:新增 `analyzeFortuneGanzhi`(十神/五行生克/合冲害刑/吉凶)
- **大运→流年→流月→流日交互下钻**:新增 `getYearMonths`(节气月);八字页交互浏览器,流日可跳日详情
### 4. 质量
- 单元测试 29 → **50 个**(vitest),覆盖历法/八字/运势/梅花/称骨/干支/五行/神煞/流月/流年
- 浏览器 E2E 验证(headless Chrome + CDP 脚本,无新增依赖):周起始、回到今天、流派、出生地、太阳时开关、宜忌、历法信息、神煞、大运流年交互 全部实测通过
### 5. 工程清理
- 整理全部文档;删除 node_modules / dist / tsbuildinfo;源码 241M → 764K;打包 164K/tmp/lunar-source-20260803.tar.gz
## 二、未完成 / 待办(详见 PROGRESS.md Backlog
| 事项 | 说明 |
|---|---|
| 互卦真算法 | 梅花易数互卦仍为上下卦互换简化(2-4/3-5 爻法未实现) |
| 死代码清理 | useDayDetail/useBazi hooks、AnimatedPanel、CardHeader、CalendarSkeleton/BaziSkeleton、ui store 未用 action、settings 显示开关字段、calendar store weekStart、bookmarks getByDate、utils 未用函数、tailwind-variants 依赖 |
| 显示开关字段 | settings.showLunar/showSolarTerm/showHoliday/eightCharProvider 已持久化但未消费(其中 eightCharProvider 已被 ziHourSect 替换) |
| 农历周期收藏 | bookmarks 的 isLunar 字段已预留,UI 未提供;收藏列表页未做 |
| 午时假设 | calculateDailyFortune 当日八字固定取午时(TECH-01) |
| 称骨极端值 | 超出 2两1钱~7两2钱范围的总重仍取"最近值"TECH-04 残余) |
| 紫微斗数 | 未做(大工程,用户同意先做神煞) |
| web 端自动化测试 | 仅 core 有单测;web 无测试框架 |
| git | 项目未初始化 git 仓库,无版本管理与回滚能力 |
## 三、有疑问 / 待确认事项
1. **称骨年表存在两套网络变体**:本实现采用主流版本(算准网/网易/sunfinelife 三家一致:丙子16钱、戊子15钱等),但另一套变体(丙子19钱、戊子12钱等)也在流通。若用户希望换另一套,改 `boneWeight.ts``YEAR_WEIGHTS` 即可。
2. **天厨贵人查法有版本差异**:本实现采用主流版(甲巳、乙午、丙巳、丁午、戊申、己酉、庚亥、辛子、壬寅、癸卯);传统版(丙寅、丁酉、戊申、己未、庚亥、辛戌、壬卯、癸子)也有出处。代码注释已注明。
3. **tyme4ts 十神方向语义**:实测 `A.getTenStar(B)` 返回"B 以 A 为日主"的十神。`dailyMatch.ts` 中的用法方向(userPillar vs dayPillar 同位置比较)语义上存疑,但**未改动**(避免影响每日运势结果);新写的 `fortuneLuck` 已按正确方向实现。需确认 dailyMatch 是否也要调整。
4. **佛历年**:按公历 + 543(泰国惯例);bmcx 示例 2570 对应的是其他年份。
5. **佛教节日表**:21 个为通行版本,个别日期(如腊月廿九华严菩萨圣诞)在不同资料有出入。
6. **默认出生地变化**:默认从"120°E 不校正"改为"北京 116.4°E-14 分钟真太阳校正)",临界时辰的结果会变。太阳时校正开关默认开启——用户接受度未知,如需要可默认关闭。
7. **BUG-04HomePage InfoCard highlight**`highlight` 传布尔但被当作样式类 `border-primary/30` 处理,语义不清,需确认意图(是要"高亮边框"还是别的)。
8. **起运前年份 UX**:大运流年浏览器中,出生当年(起运前)不在任何大运区间,自动落到第一柱大运(如 2026 年出生 → 从 2028 起显示)。是否要显示"起运前"年份待定。
9. **pnpm-workspace.yaml `allowBuilds`**:非 pnpm 标准字段(应为 onlyBuiltDependencies),疑似无效但无害,未改。
10. **打包清理**:已删除 node_modules/dist,开发前需 `pnpm install`
## 四、验证方式备忘
- E2E 通过 headless ChromePlaywright 缓存目录的 chromium headless shell+ CDP 协议 Node 脚本驱动,未引入 Playwright npm 依赖;脚本存于 `/tmp/lunar-*.mjs`(会话临时文件,未入库)。
- 所有功能均以"单测 + 浏览器实测"双重验证;仅 UI 纯样式类改动(如时间选择器)以 tsc 构建验证为主。