From 4608dbd5cfb2c79af462e68257448903ec52300d Mon Sep 17 00:00:00 2001 From: zhouzhibo Date: Thu, 15 Oct 2026 21:56:45 +0800 Subject: [PATCH] feat: refine profile and home UI with dynamic fortune rules --- .gitignore | 2 +- config/index.ts | 10 +- docs/five-elements-rules.md | 39 ++ docs/home-rules.md | 51 ++ docs/zodiac-rules.md | 51 ++ package.json | 5 + pnpm-lock.yaml | 8 + scripts/fiveElements.test.cjs | 84 +++ scripts/frontendPreview.test.cjs | 51 ++ scripts/homeOverview.test.cjs | 110 ++++ scripts/render-home-icons.cjs | 27 + scripts/render-zodiac-icons.cjs | 33 + scripts/zodiac.test.cjs | 64 ++ scripts/zodiacWeekly.test.cjs | 98 +++ src/app.config.ts | 2 +- src/assets/home/bamboo.png | Bin 0 -> 13386 bytes src/assets/home/coin.png | Bin 0 -> 18047 bytes src/assets/home/fan.png | Bin 0 -> 13162 bytes src/assets/home/gourd.png | Bin 0 -> 8985 bytes src/assets/home/heart.png | Bin 0 -> 6957 bytes src/assets/home/horse.png | Bin 0 -> 8712 bytes src/assets/home/scroll.png | Bin 0 -> 11835 bytes src/assets/home/spirit.png | Bin 0 -> 12727 bytes src/assets/home/vase.png | Bin 0 -> 9426 bytes src/assets/home/water.png | Bin 0 -> 9258 bytes src/assets/zodiac/dog.png | Bin 0 -> 10886 bytes src/assets/zodiac/dragon.png | Bin 0 -> 11233 bytes src/assets/zodiac/goat.png | Bin 0 -> 11356 bytes src/assets/zodiac/horse.png | Bin 0 -> 9780 bytes src/assets/zodiac/monkey.png | Bin 0 -> 10601 bytes src/assets/zodiac/ox.png | Bin 0 -> 10123 bytes src/assets/zodiac/pig.png | Bin 0 -> 8904 bytes src/assets/zodiac/rabbit.png | Bin 0 -> 9163 bytes src/assets/zodiac/rat.png | Bin 0 -> 9365 bytes src/assets/zodiac/rooster.png | Bin 0 -> 9046 bytes src/assets/zodiac/snake.png | Bin 0 -> 8839 bytes src/assets/zodiac/tiger.png | Bin 0 -> 9451 bytes src/components/AppTabBar.scss | 40 ++ src/components/AppTabBar.tsx | 27 + src/components/RadarChart.scss | 108 +--- src/components/RadarChart.tsx | 75 +-- src/components/ZodiacMascot.scss | 3 + src/components/ZodiacMascot.tsx | 26 + src/index.html | 13 + src/pages/agreement/index.scss | 161 ++++- src/pages/agreement/index.tsx | 42 +- src/pages/home/index.scss | 699 +++------------------- src/pages/home/index.tsx | 409 ++++--------- src/pages/my/index.scss | 958 +++++++++++++++++++++++++++++- src/pages/my/index.tsx | 278 ++++++--- src/pages/profile-edit/index.scss | 427 ++++++++++--- src/pages/profile-edit/index.tsx | 364 ++++++++++-- src/services/frontendPreview.ts | 21 + src/services/request.ts | 37 ++ src/types/assets.d.ts | 5 + src/utils/fiveElements.ts | 196 ++++-- src/utils/homeOverview.ts | 140 +++++ src/utils/zodiac.ts | 18 + src/utils/zodiacWeekly.ts | 89 +++ 59 files changed, 3424 insertions(+), 1347 deletions(-) create mode 100644 docs/five-elements-rules.md create mode 100644 docs/home-rules.md create mode 100644 docs/zodiac-rules.md create mode 100644 scripts/fiveElements.test.cjs create mode 100644 scripts/frontendPreview.test.cjs create mode 100644 scripts/homeOverview.test.cjs create mode 100644 scripts/render-home-icons.cjs create mode 100644 scripts/render-zodiac-icons.cjs create mode 100644 scripts/zodiac.test.cjs create mode 100644 scripts/zodiacWeekly.test.cjs create mode 100644 src/assets/home/bamboo.png create mode 100644 src/assets/home/coin.png create mode 100644 src/assets/home/fan.png create mode 100644 src/assets/home/gourd.png create mode 100644 src/assets/home/heart.png create mode 100644 src/assets/home/horse.png create mode 100644 src/assets/home/scroll.png create mode 100644 src/assets/home/spirit.png create mode 100644 src/assets/home/vase.png create mode 100644 src/assets/home/water.png create mode 100644 src/assets/zodiac/dog.png create mode 100644 src/assets/zodiac/dragon.png create mode 100644 src/assets/zodiac/goat.png create mode 100644 src/assets/zodiac/horse.png create mode 100644 src/assets/zodiac/monkey.png create mode 100644 src/assets/zodiac/ox.png create mode 100644 src/assets/zodiac/pig.png create mode 100644 src/assets/zodiac/rabbit.png create mode 100644 src/assets/zodiac/rat.png create mode 100644 src/assets/zodiac/rooster.png create mode 100644 src/assets/zodiac/snake.png create mode 100644 src/assets/zodiac/tiger.png create mode 100644 src/components/AppTabBar.scss create mode 100644 src/components/AppTabBar.tsx create mode 100644 src/components/ZodiacMascot.scss create mode 100644 src/components/ZodiacMascot.tsx create mode 100644 src/index.html create mode 100644 src/services/frontendPreview.ts create mode 100644 src/utils/homeOverview.ts create mode 100644 src/utils/zodiac.ts create mode 100644 src/utils/zodiacWeekly.ts diff --git a/.gitignore b/.gitignore index fb263b6..09be9e0 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,5 @@ node_modules/ dist/ +dist-h5/ .swc/ .DS_Store - diff --git a/config/index.ts b/config/index.ts index 0db465e..2fd244b 100644 --- a/config/index.ts +++ b/config/index.ts @@ -10,7 +10,7 @@ export default defineConfig(async () => ({ 828: 1.81 / 2 }, sourceRoot: 'src', - outputRoot: 'dist', + outputRoot: process.env.TARO_ENV === 'h5' ? 'dist-h5' : 'dist', plugins: ['@tarojs/plugin-framework-react'], defineConstants: {}, copy: { @@ -19,6 +19,14 @@ export default defineConfig(async () => ({ }, framework: 'react', compiler: 'webpack5', + h5: { + postcss: { + pxtransform: { + enable: true, + config: { baseFontSize: 20, minRootSize: 16, maxRootSize: 40 } + } + } + }, mini: { postcss: { pxtransform: { diff --git a/docs/five-elements-rules.md b/docs/five-elements-rules.md new file mode 100644 index 0000000..335ea92 --- /dev/null +++ b/docs/five-elements-rules.md @@ -0,0 +1,39 @@ +# 前端五行报告:普通扶抑简化参考算法 v1 + +用户确认采用可解释的普通扶抑综合评分。本规则为本产品的确定性参考算法,不是统一命理标准或专业断命依据;只作传统文化娱乐参考。 + +## 输入与排盘 + +- 只使用保存后的公历生日、出生时辰,不使用接口返回的 `elementReport`。 +- 使用锁定版本的 `lunar-typescript` 生成四柱和地支藏干;年/月柱沿用库的节气划分。 +- 输入按北京时间处理,不转换浏览器时区,不作真太阳时校正。 +- 只有时辰时,使用该时辰起始小时(子时23点,丑时1点等);库 `setSect(2)` 约定日柱零点换日。由于缺少具体分钟,节气交界的时辰无法精确划分;不声称处理了分钟级边界。 +- 日期支持1900至2100年;非法日期、缺失/非法时辰返回空状态,不伪造默认五行或日主。 + +## 组成比例 + +四个天干各10份,年/日/时支各10份,月支18份。地支分到其藏干:一藏干100%,两藏干70%/30%,三藏干60%/30%/10%,顺序使用历法库藏干顺序。这些份数为产品约定。用最大余数法转换为整数百分比,保证五项之和为100%。 + +## 三项评分 + +1. 得令(40%):以月支主五行作为季节,辰戌丑未简化为土。日主与季节同类为旺100分,季节生日主为相80分,日主生季节为休50分,日主克季节为囚30分,季节克日主为死15分。旺、相标为月令支持。 +2. 得地(30%):四支藏干中与日主同五行的份额相加,达到两个完整根计100分,其余按比例计分并封顶100分。有任何同类藏干即标为有根;“有根”不等于“根气充分”。 +3. 得势(30%):排除日干本身,计算其他天干和所有地支藏干中印星(生日主)与比劫(同日主)的加权份额占比。月支仍取18份,其他支10份,其他天干10份,占比即评分。达到50%标为生扶力量占优。 + +总分 = 得令×0.4 + 得地×0.3 + 得势×0.3,四舍五入到整数。该启发式中月令也参与藏干和得势,是刻意强调季节的产品约定,并非三份独立统计样本。 + +## 扶抑喜忌 + +- 小于45分:偏弱。喜生扶,列印星、比劫;忌项为食伤、财、官杀。 +- 大于55分:偏强。喜泄耗制衡,列食伤、财、官杀;忌项为印星、比劫。 +- 45到55分(含边界):相对平衡,不强行指定喜用/忌用;页面提示保持协调。 + +此处“喜用”是扶抑方向集合,不进一步判断唯一用神或精确优先级。不包含从格、专旺、化气、合冲刑害、调候、藏干司令天数等;不能把本算法表述为完整八字喜用神体系。 + +## 更新与验收 + +`useDidShow` 重新读取 `GET /api/user/profile` 的个人资料;生日或时辰改变后,`useMemo` 重新计算整份报告。昵称、头像、性别、地点不参与本版计算。加载失败显示重试入口,不退回假资料。保存使用原来的 `PUT /api/user/profile`,无需新增报告接口。 + +执行 `npm run test:elements`,覆盖强弱反转、藏干根气、无效日期、百分比守恒、时辰变化、节气月份切换和子时换日。构建验证仍需 `tsc --noEmit`、H5与小程序构建。 + +开发者工具验收:我的→我的元素,检查五项比例、强弱、得令/得地/得势说明;返回修改生日或时辰并保存,再次进入元素页检查四柱和报告。测试平衡命例时,喜忌应显示“暂无明显偏向/偏忌”。 diff --git a/docs/home-rules.md b/docs/home-rules.md new file mode 100644 index 0000000..4a8d2ff --- /dev/null +++ b/docs/home-rules.md @@ -0,0 +1,51 @@ +# 首页动态生成与验收(开发维护说明) + +用户确认:纯前端简化参考规则;页面不公开公式、权重、计算依据;维度卡片仅展示列表,不做详情交互。因此下面内容仅为维护文档,不渲染进首页。 + +## 数据与更新 + +只请求 `GET /api/user/profile` 获取生日、时辰、头像,不读取旧 `/api/home/overview` 的报告,也不使用异常时的固定42分示例。沿用 `calculateFiveElements` 的扶抑规则,以及按春节换年的生肖和合冲关系。需要有效生日、时辰,缺失时显示完善资料入口;网络失败显示重试。H5显式 `?preview=1` 由现有预览适配器提供示例个人资料,不请求后端。 + +北京时间日期作为基准,昨日/今日/明日分别偏移−1/0/+1。每份报告独立生成整套公历、星期、农历、摘要、指数、吉色吉数、吉向吉时和八个维度。页面显示时重读个人资料;北京时间零点刷新相对日期。生日、时辰、日期任一输入变化后重新计算,相同输入结果稳定,不调用随机数。 + +## 评分约定 + +本产品的简化娱乐规则,不代表统一命理标准。分值仅用于界面参考,不解释为健康、财富或事件发生的概率。 + +- 日主喜忌由已经确认的普通扶抑算法产生。 +- 某元素在喜用集合:基础权重 + round(max(0,20−个人该元素百分比)/5)。在忌用集合:−基础权重 − round(max(0,个人该元素百分比−20)/5)。相对平衡时不加减。即先判断扶抑方向,再小幅调节份额,不把“缺少”直接等同于“喜用”。 +- 当日公共基分=50 + 日干五行喜忌项(基础权重10) + 出生生肖年支对当日日支的关系分×5。关系分沿用六合+2、三合同组+1、六冲−2、相害−1、其余0。 +- 各维度再加该维度五行的喜忌项(基础权重8),以及日干五行对维度五行的同类/生助+6、相克−6、其余0。 +- 黄历宜忌读取所选日期的历法库数据,匹配该维度活动关键词。命中忌为−10,否则命中宜为+10,否则0;同项冲突优先忌。不把黄历活动误写成事件必然发生。 +- 维度分限制15到90;≥50显示宜,<50显示忌。展示文案按宜/忌选择对应普通生活建议,再用日干奇偶选择文案变体;不是固定的一套八维文案,也不以随机数伪装计算。 +- 八个维度等权平均并四舍五入为综合指数。≥80大吉、≥65小吉、≥50平日、≥35小逆、其余谨慎。 +- 维度关联:情感/社交=火,健康/事业=木,生活=土,财富=金,学业/出行=水。活动词见 `definitions`,属于产品简化映射。 + +普通建议仅涉及日常沟通、整理、作息、预算核对、任务安排和路线准备,不生成诊疗、投资或事故预测。摘要由当日状态和最高/最低分维度形成;同分时使用均衡描述。 + +## 吉色、吉数、吉向、吉时 + +- 有利五行取扶抑报告喜用集合;相对平衡时只在颜色/数字展示中取两个较低占比元素作装饰参考,不重新定义喜用。结合所选日干的生助关系排序,取两项。 +- 色盘映射:木为绿、火为粉橘、土为杏麦、金为白金、水为蓝;按日干奇偶选色调。 +- 数字映射采用产品约定的河图数:木3/8、火2/7、土5/0、金4/9、水1/6,按日支奇偶选对应数字。 +- 吉向读取所选当日 `getDayPositionXiDesc()`,作为传统喜神方位参考;指南针图标跟随方向旋转。 +- 吉时只在当日 `getTimes()` 的“吉”片段中选择,以时干喜忌项(基础权重2)和出生年支对时支关系排序,取两个不重复时支。用历法库具体起止片段显示:早子时00–01,夜子时23–24,不把跨日片段混作同一天。若无时段,显示暂无参考时段。 + +## 图标、列表、排序和导航 + +八维图标、水滴和灵境头像为原创矢量源转换的256像素透明PNG,源码在 `scripts/render-home-icons.cjs`。统一由共享 `AppTabBar` 提供首页与我的导航;H5关闭Taro重复系统tabBar,微信端保留原tab配置并使用 `switchTab`。 + +`src/index.html` 交给Taro的HTML插件生成预览入口与正确的脚本文件名,不再手写分块编号。模板注入rem响应式脚本,H5使用baseFontSize20、minRootSize16、maxRootSize40;修复以前缺少脚本导致宽屏/窄屏缩放不一致的问题。 + +维度按本机顺序展示,不默认按宜忌重排。排序页用上下按钮调整,完成后写入 `home.dimension-order.v1`;损坏或旧存储通过去重/过滤/补齐修复为八维。页面没有不可点击的伪详情箭头,也没有评分依据展开入口。 + +## 验收 + +1. 开发者工具打开首页;检查水滴头像、三个日期、真实农历、紫色指数卡、四块参考信息、八维图标与卡片、底部灵境头像。 +2. 依次切换昨日/今日/明日,日期与状态、整份报告同步变化;不同字段允许在某些日期相同,不人为强制每项变化。 +3. 修改生日或时辰保存后回首页,报告按新资料重新计算;昵称/头像不参与评分。 +4. 点击排序,用上下按钮调整后完成,退出重进仍保留八维顺序;首尾按钮不可越界。 +5. 列表无详情点击交互;页面不显示评分公式、干支依据、权重或测试工具,只保留简短娱乐参考标注。 +6. 切换窄屏、常规屏、长屏检查文本、卡片和安全区;从首页切我的,导航样式一致,H5不重复渲染原生tabBar。 + +自动验证:`npm run test:home`。验证真实日期/农历、三日切换、评分一致性、同输入稳定、生日时辰变化、吉时来源和边界、排序修复及图标资产。 diff --git a/docs/zodiac-rules.md b/docs/zodiac-rules.md new file mode 100644 index 0000000..038efff --- /dev/null +++ b/docs/zodiac-rules.md @@ -0,0 +1,51 @@ +# 我的生肖 + +按用户确认,以春节(农历正月初一)换生肖,使用公历生日经 `lunar-typescript` 转为农历,读取 `getYearShengXiao()`。不使用公历年份模12,也不使用以立春为界的八字年柱。 + +`src/utils/zodiac.ts` 只接收生日,返回十二生肖名称或空值。缺失或无效生日不默认展示兔子。支持1900至2100年,和当前元素报告的生日范围一致。 + +“我的生肖”入口与弹窗共用同一个 `zodiac` 结果及 `ZodiacMascot` 组件。十二张图标为本地256×256透明PNG,矢量源保存在 `scripts/render-zodiac-icons.cjs`。通过 `sharp` 可重新生成,运行时无需依赖 `sharp`。 + +页面返回时通过现有 `GET /api/user/profile` 获取最新生日,生日变化后重新计算生肖。保存生日沿用 `PUT /api/user/profile`,不新增生肖接口。图标、弹窗标题和“属X”名称随结果一起变化;隐藏生日开关不影响计算。 + +## 验收 + +1. 在开发者工具使用测试账号,进入“我的”,点击“我的生肖”,入口及弹窗应显示同一种动物,弹窗有对应“属X”名称。 +2. 修改测试账号生日为2024-02-09并保存,返回应显示兔;改为2024-02-10并保存,返回应显示龙。 +3. 2024-02-05在立春之后但春节之前,仍应为兔;避免把“我的元素”的节气年柱与日常生肖混用。 +4. 对缺失或非法生日,入口显示“待完善”,弹窗提示完善生日并提供编辑入口。 +5. 点击遮罩或“知道了”关闭弹窗,进入资料编辑与生肖按钮保持独立。 + +自动验证:`npm run test:zodiac`,覆盖春节前后、十二生肖周期、非法生日、资料改变和图标资产完整性。H5和微信小程序均需构建通过。 + +## 动态生肖周运:合冲简化规则 v1 + +用户已确认采用纯前端合冲关系计算,并要求公开权重与判断依据。输入为保存后的生日和北京时间当前日期。生日先按春节换年得到生肖,再对应子丑寅卯辰巳午未申酉戌亥的出生年支。按北京时间本周一至周日,用历法库计算七天日支;不是按公历日期模12伪造日支。 + +每天按以下互斥关系计一次分: + +| 关系 | 分数 | 对应关系 | +| --- | --- | --- | +| 六合 | +2 | 子丑、寅亥、卯戌、辰酉、巳申、午未 | +| 三合同组 | +1 | 申子辰、亥卯未、寅午戌、巳酉丑,同组且不同支 | +| 六冲 | −2 | 子午、丑未、寅申、卯酉、辰戌、巳亥 | +| 相害 | −1 | 子未、丑午、寅巳、卯辰、申亥、酉戌 | +| 平常 | 0 | 其余关系,包括相同地支 | + +六合与六冲表复用历法库 `LunarUtil.HE_ZHI_6` / `LunarUtil.CHONG`。三合同组只是出生年支与日支两支间的助力关系,不声称完整三合成局。不纳入刑、破或八字整体。权重与以下阈值是本产品的简化娱乐参考规则,不是统一命理标准。 + +七天分数求和:≥2为“顺势”,≤−2为“谨慎”,−1至1为“平稳”。正分日列为助力日,负分日列为留意日。摘要由本周实际天数、周状态及其对应建议组成;同一生肖同周稳定,不随机。不同生肖/周次可能同为“平稳”,不保证每次切换都换一个状态。 + +弹窗展示周一/周日的完整公历日期、状态、摘要、助力/留意日期,可展开权重、周总分与七天日支/关系/分数。明确标注“仅作传统文化娱乐参考”。普通建议限于沟通、协调、确认安排,不生成健康或投资预测。 + +页面显示、弹窗打开时检查北京时间日期;弹窗保持打开时在北京时间零点刷新,跨周后重新计算。没有后端报告接口,没有持久化周运结果。无效生日不给出周运;无效设备日期显示日期检查提示。 + +### 周运验收 + +1. “我的”→“我的生肖”,确认显示本周周一至周日区间、生肖、动态摘要和日期。 +2. 展开“判断依据”,逐日分数合计应等于周总分;总分对应状态应与上述阈值一致。 +3. 修改生日跨生肖,检查图标、名称、七天关系和摘要一起更新;同生肖的不同生日在同周允许结果相同。 +4. 按北京时间周日/周一检查周区间,跨年周应保留完整年份。不要用UTC日期替代北京时间日期。 +5. 小屏下滚动查看详细依据,“知道了”按钮始终可用;遮罩仍可关闭弹窗。 + +测试:`npm run test:zodiac-weekly`,覆盖所有地支关系及对称性、北京时间零点、同周稳定、跨年/跨周、十二生肖结果差异、分数复算、非法输入。 diff --git a/package.json b/package.json index 28bdb91..bafe9a8 100644 --- a/package.json +++ b/package.json @@ -3,6 +3,10 @@ "version": "0.0.1", "private": true, "scripts": { + "test:elements": "node --test scripts/fiveElements.test.cjs", + "test:zodiac": "node --test scripts/zodiac.test.cjs", + "test:zodiac-weekly": "node --test scripts/zodiacWeekly.test.cjs", + "test:home": "node --test scripts/homeOverview.test.cjs", "dev:weapp": "taro build --type weapp --watch", "build:weapp": "taro build --type weapp" }, @@ -16,6 +20,7 @@ "@tarojs/runtime": "3.6.35", "@tarojs/shared": "3.6.35", "@tarojs/taro": "3.6.35", + "china-area-data": "^5.0.1", "lunar-typescript": "^1.8.6", "react": "18.2.0", "react-dom": "18.2.0" diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index e7576bd..6481282 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -35,6 +35,9 @@ importers: '@tarojs/taro': specifier: 3.6.35 version: 3.6.35(@tarojs/helper@3.6.35(supports-color@8.1.1))(@tarojs/runtime@3.6.35(@tarojs/shared@3.6.35))(@types/react@18.3.31)(postcss@8.5.26) + china-area-data: + specifier: ^5.0.1 + version: 5.0.1 lunar-typescript: specifier: ^1.8.6 version: 1.8.6 @@ -2083,6 +2086,9 @@ packages: charenc@0.0.2: resolution: {integrity: sha512-yrLQ/yVUFXkzg7EDQsPieE/53+0RlaWTs+wBrvW36cyilJ2SaDWfl4Yj7MtLTXleV9uEKefbAGUPv2/iWSooRA==} + china-area-data@5.0.1: + resolution: {integrity: sha512-BQDPpiv5Nn+018ekcJK2oSD9PAD+E1bvXB0wgabc//dFVS/KvRqCgg0QOEUt3vBkx9XzB5a9BmkJCEZDBxVjVw==} + chokidar@3.6.0: resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==} engines: {node: '>= 8.10.0'} @@ -8818,6 +8824,8 @@ snapshots: charenc@0.0.2: {} + china-area-data@5.0.1: {} + chokidar@3.6.0: dependencies: anymatch: 3.1.3 diff --git a/scripts/fiveElements.test.cjs b/scripts/fiveElements.test.cjs new file mode 100644 index 0000000..cadec41 --- /dev/null +++ b/scripts/fiveElements.test.cjs @@ -0,0 +1,84 @@ +const test = require('node:test') +const assert = require('node:assert/strict') +const fs = require('node:fs') +const path = require('node:path') +const Module = require('node:module') +const ts = require('typescript') +const filename = path.resolve(__dirname, '../src/utils/fiveElements.ts') +const compiled = ts.transpileModule(fs.readFileSync(filename, 'utf8'), { + compilerOptions: { module: ts.ModuleKind.CommonJS, target: ts.ScriptTarget.ES2017 } +}).outputText +const loaded = new Module(filename, module) +loaded.filename = filename +loaded.paths = Module._nodeModulePaths(path.dirname(filename)) +loaded._compile(compiled, filename) +const { analyzePillars, calculateFiveElements } = loaded.exports + +test('同一日主在强弱不同的四柱下,扶抑方向应反转', () => { + const strong = analyzePillars(['甲寅', '乙卯', '甲寅', '乙卯']) + const weak = analyzePillars(['丙午', '丁巳', '甲申', '戊戌']) + assert.equal(strong.dayMaster, weak.dayMaster) + assert.equal(strong.strength, '偏强') + assert.equal(weak.strength, '偏弱') + assert.equal(strong.favorable, '火土金') + assert.equal(weak.favorable, '水木') + assert.equal(strong.analysis.season.supported, true) + assert.equal(weak.analysis.roots.supported, false) +}) + +test('地支藏干中的同类根必须计入,得势不包含日干自身', () => { + const report = analyzePillars(['丙午', '丁巳', '甲辰', '戊戌']) + assert.equal(report.analysis.roots.supported, true) // 辰藏乙,不能只看辰土。 + assert.ok(report.analysis.roots.score > 0) + const noSupport = analyzePillars(['丙午', '丁巳', '甲申', '戊戌']) + assert.ok(noSupport.analysis.support.score < 20) +}) + +test('有效日期和时辰改变后重新排盘,不受昵称或后端报告影响', () => { + const first = calculateFiveElements('1998-06-18', '辰时') + assert.deepEqual(first.pillars, ['戊寅', '戊午', '丙申', '壬辰']) + const changedDate = calculateFiveElements('1998-12-18', '辰时') + const changedHour = calculateFiveElements('1998-06-18', '戌时') + assert.notDeepEqual(first.scores, changedDate.scores) + assert.notDeepEqual(first.pillars, changedHour.pillars) + assert.notDeepEqual(first.scores, changedHour.scores) + assert.deepEqual(first, calculateFiveElements('1998-06-18', '7')) +}) + +test('百分比总和为100,强弱有界,喜忌互斥,平衡不强行指定喜忌', () => { + let balanced = false + for (let month = 1; month <= 12; month++) { + for (const hour of ['子时', '辰时', '午时', '酉时']) { + const report = calculateFiveElements(`2000-${String(month).padStart(2, '0')}-15`, hour) + assert.equal(report.scores.reduce((sum, score) => sum + score.value, 0), 100) + assert.ok(report.scores.every((score) => Number.isInteger(score.value) && score.value >= 0 && score.value <= 100)) + assert.ok(report.strengthScore >= 0 && report.strengthScore <= 100) + assert.ok(![...report.favorable].some((element) => report.unfavorable.includes(element))) + if (report.strength === '相对平衡') { + balanced = true + assert.equal(report.favorable, '') + assert.equal(report.unfavorable, '') + } + } + } + assert.equal(balanced, true) +}) + +test('不把无效生日、缺失时辰或越界时辰转换成虚构报告', () => { + for (const [date, hour] of [ + ['', '辰时'], ['2025-02-29', '辰时'], ['2024-02-30', '辰时'], + ['2024-13-01', '辰时'], ['2000-01-01', ''], ['2000-01-01', '24'], + ['2000-01-01', '-1'], ['2000-01-01', '辰时xxx'] + ]) assert.equal(calculateFiveElements(date, hour), null) + assert.ok(calculateFiveElements('2024-02-29', '子时')) + assert.throws(() => analyzePillars(['甲子', '无效', '甲子', '甲子'])) +}) + +test('节气前后切换月柱;子时换日采用历法库第二流派', () => { + const before = calculateFiveElements('2024-02-03', '午时') + const after = calculateFiveElements('2024-02-05', '午时') + assert.notEqual(before.pillars[1], after.pillars[1]) + const early = calculateFiveElements('2024-06-18', '0') + const late = calculateFiveElements('2024-06-18', '23') + assert.equal(early.dayMaster, late.dayMaster) +}) diff --git a/scripts/frontendPreview.test.cjs b/scripts/frontendPreview.test.cjs new file mode 100644 index 0000000..dc9e910 --- /dev/null +++ b/scripts/frontendPreview.test.cjs @@ -0,0 +1,51 @@ +const test = require('node:test') +const assert = require('node:assert/strict') +const fs = require('node:fs') +const path = require('node:path') +const vm = require('node:vm') +const ts = require('typescript') + +function loadApi(env, search) { + let requests = 0 + let uploads = 0 + const taro = { default: { + getStorageSync: () => '', + request: async () => { requests++; return { data: { code: 0, data: { id: 9 } } } }, + uploadFile: async () => { uploads++; return { data: JSON.stringify({ code: 0, data: { id: 9 } }) } } + } } + const cache = {} + function load(name) { + if (cache[name]) return cache[name] + const source = fs.readFileSync(path.resolve(__dirname, `../src/services/${name}.ts`), 'utf8') + const code = ts.transpileModule(source, { compilerOptions: { module: ts.ModuleKind.CommonJS, target: ts.ScriptTarget.ES2017 } }).outputText + const exports = {} + cache[name] = exports + vm.runInNewContext(code, { + exports, process: { env: { TARO_ENV: env } }, window: { location: { search } }, URLSearchParams, + require: (id) => id === '@tarojs/taro' ? taro : load('frontendPreview') + }) + return exports + } + return { api: load('request').api, counts: () => ({ requests, uploads }) } +} + +test('显式H5预览使用示例资料,阻止后端读取、保存和上传', async () => { + const { api, counts } = loadApi('h5', '?preview=1') + const profile = await api.profile() + assert.equal(profile.id, 0) + assert.equal(profile.birthday, '1998-06-18') + await assert.rejects(api.updateProfile({ nickname: 'Changed' }), /纯前端预览/) + await assert.rejects(api.uploadAvatar('local.png'), /纯前端预览/) + await assert.rejects(api.agreement('privacy'), /纯前端预览/) + assert.deepEqual(counts(), { requests: 0, uploads: 0 }) + profile.nickname = 'Mutated' + assert.equal((await api.profile()).nickname, 'You') +}) + +test('普通H5和微信端不使用预览资料', async () => { + for (const [env, search] of [['h5', ''], ['h5', '?preview=0'], ['weapp', '?preview=1']]) { + const { api, counts } = loadApi(env, search) + assert.equal((await api.profile()).id, 9) + assert.deepEqual(counts(), { requests: 1, uploads: 0 }) + } +}) diff --git a/scripts/homeOverview.test.cjs b/scripts/homeOverview.test.cjs new file mode 100644 index 0000000..547aeef --- /dev/null +++ b/scripts/homeOverview.test.cjs @@ -0,0 +1,110 @@ +const test = require('node:test') +const assert = require('node:assert/strict') +const fs = require('node:fs') +const path = require('node:path') +const Module = require('node:module') +const ts = require('typescript') +const { Solar } = require('lunar-typescript') +const cache = {} +function load(name) { + if (cache[name]) return cache[name].exports + const filename = path.resolve(__dirname, `../src/utils/${name}.ts`) + const loaded = new Module(filename, module) + cache[name] = loaded + loaded.filename = filename + loaded.paths = Module._nodeModulePaths(path.dirname(filename)) + const original = loaded.require.bind(loaded) + loaded.require = (id) => id.startsWith('./') ? load(id.slice(2)) : original(id) + loaded._compile(ts.transpileModule(fs.readFileSync(filename, 'utf8'), { compilerOptions: { module: ts.ModuleKind.CommonJS, target: ts.ScriptTarget.ES2017 } }).outputText, filename) + return loaded.exports +} +const { generateHomeOverview: generate, normalizeDimensionOrder, HOME_DIMENSION_IDS } = load('homeOverview') +const profile = { birthday: '1998-06-18', birthHour: '辰时' } + +test('昨日今日明日整体切换,公历星期农历均来自实际所选日期', () => { + const reports = [-1, 0, 1].map((offset) => generate(profile, '2026-10-15', offset)) + assert.deepEqual(reports.map((item) => item.activeDay), ['昨日', '今日', '明日']) + assert.deepEqual(reports.map((item) => item.date), ['2026-10-14', '2026-10-15', '2026-10-16']) + reports.forEach((report) => { + const [y, m, d] = report.date.split('-').map(Number) + const solar = Solar.fromYmd(y, m, d) + const lunar = solar.getLunar() + assert.equal(report.weekName, `星期${'日一二三四五六'[solar.getWeek()]}`) + assert.equal(report.lunarDate, `农历${lunar.getYearInGanZhi()}年 ${lunar.getMonthInChinese()}月${lunar.getDayInChinese()}`) + assert.equal(report.luckyDirection, lunar.getDayPositionXiDesc()) + assert.equal(report.days.find((day) => day.label === report.activeDay).status, report.status) + }) + assert.notDeepEqual(reports[0].dimensions, reports[1].dimensions) + assert.notDeepEqual(reports[1].dimensions, reports[2].dimensions) +}) + +test('八维评分有界,宜忌与评分一致,综合指数可复算', () => { + for (let day = 1; day <= 31; day++) { + const report = generate(profile, `2026-10-${String(day).padStart(2, '0')}`) + assert.equal(report.dimensions.length, 8) + assert.equal(new Set(report.dimensions.map((item) => item.id)).size, 8) + report.dimensions.forEach((item) => { + assert.ok(item.score >= 15 && item.score <= 90) + assert.equal(item.suitable, item.score >= 50) + assert.ok(item.headline && item.detail) + }) + assert.equal(report.overallIndex, Math.round(report.dimensions.reduce((sum, item) => sum + item.score, 0) / 8)) + assert.equal(report.status, report.overallIndex >= 80 ? '大吉' : report.overallIndex >= 65 ? '小吉' : report.overallIndex >= 50 ? '平日' : report.overallIndex >= 35 ? '小逆' : '谨慎') + assert.equal(report.luckyColors.length, 2) + assert.equal(new Set(report.luckyNumbers).size, 2) + } +}) + +test('吉时仅取所选当日的吉时片段,不越过日期边界且时支不重复', () => { + for (let day = 1; day <= 31; day++) { + const report = generate(profile, `2026-10-${String(day).padStart(2, '0')}`) + const times = Solar.fromYmd(2026, 10, day).getLunar().getTimes() + assert.ok(report.luckyHours.length > 0 && report.luckyHours.length <= 2) + assert.equal(new Set(report.luckyHours.map((hour) => hour.branch)).size, report.luckyHours.length) + report.luckyHours.forEach(({ branch, time }) => { + const [start, end] = time.split('–') + const match = times.find((hour) => hour.getZhi() === branch && hour.getMinHm() === start) + assert.ok(match) + assert.equal(match.getTianShenLuck(), '吉') + assert.ok(end <= '24:00') + assert.ok(start < end) + }) + } +}) + +test('日期、生日、时辰影响报告;相同输入稳定且不读取后端报告', () => { + const first = generate(profile, '2026-10-15') + assert.deepEqual(first, generate({ ...profile, elementReport: { invalid: true } }, '2026-10-15')) + assert.notDeepEqual(first, generate({ birthday: '1999-11-06', birthHour: '辰时' }, '2026-10-15')) + let changedHour = false + for (const hour of ['子时', '卯时', '午时', '戌时']) { + if (JSON.stringify(generate({ ...profile, birthHour: hour }, '2026-10-15')) !== JSON.stringify(first)) changedHour = true + } + assert.equal(changedHour, true) +}) + +test('跨月、跨年与非法日期安全处理,不回退为固定42分报告', () => { + assert.equal(generate(profile, '2026-01-01', -1).date, '2025-12-31') + assert.equal(generate(profile, '2026-12-31', 1).date, '2027-01-01') + assert.equal(generate(profile, '2024-03-01', -1).date, '2024-02-29') + for (const date of ['', '2026-02-30', '2026-13-01']) assert.equal(generate(profile, date), null) + assert.equal(generate({ birthday: '', birthHour: '' }, '2026-10-15'), null) + assert.equal(generate(profile, '2026-10-15', 2), null) +}) + +test('排序兼容缺失、重复、旧字段和损坏存储,保留八个维度', () => { + assert.deepEqual(normalizeDimensionOrder(null), HOME_DIMENSION_IDS) + assert.deepEqual(normalizeDimensionOrder('bad'), HOME_DIMENSION_IDS) + const order = normalizeDimensionOrder(['travel', 'travel', 'removed', 'wealth', null]) + assert.deepEqual(order.slice(0, 2), ['travel', 'wealth']) + assert.equal(order.length, 8) + assert.equal(new Set(order).size, 8) +}) + +test('首页八个维度、头像与天宫图标资产存在', () => { + for (const icon of ['heart', 'gourd', 'vase', 'coin', 'fan', 'scroll', 'bamboo', 'horse', 'water', 'spirit']) { + const data = fs.readFileSync(path.resolve(__dirname, `../src/assets/home/${icon}.png`)) + assert.equal(data.subarray(1, 4).toString(), 'PNG') + assert.equal(data.readUInt32BE(16), 256) + } +}) diff --git a/scripts/render-home-icons.cjs b/scripts/render-home-icons.cjs new file mode 100644 index 0000000..afa563e --- /dev/null +++ b/scripts/render-home-icons.cjs @@ -0,0 +1,27 @@ +// Original vector sources; generate portable PNG assets with sharp. +const sharp = require(process.argv[2] || 'sharp') +const fs = require('node:fs') +const path = require('node:path') +const output = path.resolve(__dirname, '../src/assets/home') +const art = { + heart: ``, + gourd: ``, + vase: ``, + coin: ``, + fan: ``, + scroll: ``, + bamboo: ``, + horse: ``, + water: ``, + spirit: `` +} +const gradients = `` +async function main() { + fs.mkdirSync(output, { recursive: true }) + for (const [name, content] of Object.entries(art)) { + const svg = `${gradients}${content}` + await sharp(Buffer.from(svg)).png().toFile(path.join(output, `${name}.png`)) + } + console.log(`Rendered ${Object.keys(art).length} home icons`) +} +main().catch((error) => { console.error(error); process.exitCode = 1 }) diff --git a/scripts/render-zodiac-icons.cjs b/scripts/render-zodiac-icons.cjs new file mode 100644 index 0000000..4bb729b --- /dev/null +++ b/scripts/render-zodiac-icons.cjs @@ -0,0 +1,33 @@ +// Vector source for the twelve original zodiac mascots. PNG output works in both H5 and WeChat. +// Run with a locally installed sharp, or pass its module path as the first argument. +const path = require('node:path') +const fs = require('node:fs') +const sharp = require(process.argv[2] || 'sharp') +const output = path.resolve(__dirname, '../src/assets/zodiac') +const face = (fill, extra = '') => `${extra}` +const eyes = `` +const smile = `` +const art = { + rat: `${face('#e8e1f4')}${eyes}${smile}`, + ox: `${face('#efd6b0')}${eyes}`, + tiger: `${face('#ffd17d')}${eyes}${smile}`, + rabbit: `${face('#fff4d8')}${eyes}${smile}`, + dragon: `${face('#a1e2c3')}${eyes}`, + snake: ``, + horse: `${face('#dfb18b')}${eyes}`, + goat: `${face('#f7e6d0')}${eyes}${smile}`, + monkey: `${face('#bd9373')}${eyes}${smile}`, + rooster: `${face('#fff1ce')}${eyes}`, + dog: `${face('#eed1a9')}${eyes}${smile}`, + pig: `${face('#ffd3dc')}${eyes}` +} + +async function main() { + fs.mkdirSync(output, { recursive: true }) + for (const [name, content] of Object.entries(art)) { + const svg = `${content}` + await sharp(Buffer.from(svg)).png().toFile(path.join(output, `${name}.png`)) + } + console.log(`Rendered ${Object.keys(art).length} zodiac icons`) +} +main().catch((error) => { console.error(error); process.exitCode = 1 }) diff --git a/scripts/zodiac.test.cjs b/scripts/zodiac.test.cjs new file mode 100644 index 0000000..3ae21e0 --- /dev/null +++ b/scripts/zodiac.test.cjs @@ -0,0 +1,64 @@ +const test = require('node:test') +const assert = require('node:assert/strict') +const fs = require('node:fs') +const path = require('node:path') +const Module = require('node:module') +const crypto = require('node:crypto') +const ts = require('typescript') +const filename = path.resolve(__dirname, '../src/utils/zodiac.ts') +const loaded = new Module(filename, module) +loaded.filename = filename +loaded.paths = Module._nodeModulePaths(path.dirname(filename)) +loaded._compile(ts.transpileModule(fs.readFileSync(filename, 'utf8'), { + compilerOptions: { module: ts.ModuleKind.CommonJS, target: ts.ScriptTarget.ES2017 } +}).outputText, filename) +const { calculateZodiac, zodiacNames } = loaded.exports + +test('春节前一天与正月初一换生肖,不按1月1日或立春换年', () => { + for (const [before, after, previous, next] of [ + ['2023-01-21', '2023-01-22', '虎', '兔'], + ['2024-02-09', '2024-02-10', '兔', '龙'], + ['2025-01-28', '2025-01-29', '龙', '蛇'], + ['2026-02-16', '2026-02-17', '蛇', '马'] + ]) { + assert.equal(calculateZodiac(before), previous) + assert.equal(calculateZodiac(after), next) + } + assert.equal(calculateZodiac('2024-01-01'), '兔') + assert.equal(calculateZodiac('2024-02-05'), '兔') // 立春后,春节前仍属兔。 +}) + +test('十二生肖全部覆盖,年份跨越周期仍正确', () => { + zodiacNames.forEach((name, index) => { + assert.equal(calculateZodiac(`${2008 + index}-06-15`), name) + assert.equal(calculateZodiac(`${2020 + index}-06-15`), name) + }) +}) + +test('无效或缺失生日不默认显示某种生肖,闰年有效日期可计算', () => { + for (const birthday of ['', '2025-02-29', '2024-02-30', '2024-00-10', '2024-13-01', '2024-01-00', '2024-1-1', '1899-12-31', '2101-01-01']) { + assert.equal(calculateZodiac(birthday), null) + } + assert.equal(calculateZodiac('2024-02-29'), '龙') +}) + +test('修改生日跨春节后返回不同生肖,重复计算稳定', () => { + const first = calculateZodiac('1999-02-15') + const changed = calculateZodiac('1999-02-16') + assert.equal(first, '虎') + assert.equal(changed, '兔') + assert.equal(calculateZodiac('1999-02-15'), first) +}) + +test('十二个图标均为独立的256像素透明PNG,非重复占位图', () => { + const files = ['rat', 'ox', 'tiger', 'rabbit', 'dragon', 'snake', 'horse', 'goat', 'monkey', 'rooster', 'dog', 'pig'] + const hashes = files.map((name) => { + const data = fs.readFileSync(path.resolve(__dirname, `../src/assets/zodiac/${name}.png`)) + assert.equal(data.subarray(1, 4).toString(), 'PNG') + assert.equal(data.readUInt32BE(16), 256) + assert.equal(data.readUInt32BE(20), 256) + assert.equal(data[25], 6) // RGBA,保留透明背景。 + return crypto.createHash('sha256').update(data).digest('hex') + }) + assert.equal(new Set(hashes).size, 12) +}) diff --git a/scripts/zodiacWeekly.test.cjs b/scripts/zodiacWeekly.test.cjs new file mode 100644 index 0000000..fd1b7bd --- /dev/null +++ b/scripts/zodiacWeekly.test.cjs @@ -0,0 +1,98 @@ +const test = require('node:test') +const assert = require('node:assert/strict') +const fs = require('node:fs') +const path = require('node:path') +const Module = require('node:module') +const ts = require('typescript') +const { Solar } = require('lunar-typescript') +const cache = {} +function load(name) { + if (cache[name]) return cache[name].exports + const filename = path.resolve(__dirname, `../src/utils/${name}.ts`) + const loaded = new Module(filename, module) + cache[name] = loaded + loaded.filename = filename + loaded.paths = Module._nodeModulePaths(path.dirname(filename)) + const originalRequire = loaded.require.bind(loaded) + loaded.require = (id) => id === './zodiac' ? load('zodiac') : originalRequire(id) + loaded._compile(ts.transpileModule(fs.readFileSync(filename, 'utf8'), { + compilerOptions: { module: ts.ModuleKind.CommonJS, target: ts.ScriptTarget.ES2017 } + }).outputText, filename) + return loaded.exports +} +const { getBeijingDate, getZodiacRelation, calculateWeeklyZodiacFortune: weekly } = load('zodiacWeekly') + +test('合冲表对称,12生肖均覆盖1六合、2三合、1六冲、1相害', () => { + const branches = [...'子丑寅卯辰巳午未申酉戌亥'] + for (const first of branches) { + const counts = {} + for (const second of branches) { + const relation = getZodiacRelation(first, second) + assert.equal(relation, getZodiacRelation(second, first)) + counts[relation] = (counts[relation] || 0) + 1 + } + assert.deepEqual(counts, { 平常: 7, 六合: 1, 三合: 2, 六冲: 1, 相害: 1 }) + assert.equal(getZodiacRelation(first, first), '平常') + } + assert.equal(getZodiacRelation('子', '丑'), '六合') + assert.equal(getZodiacRelation('寅', '午'), '三合') + assert.equal(getZodiacRelation('子', '午'), '六冲') + assert.equal(getZodiacRelation('子', '未'), '相害') + assert.throws(() => getZodiacRelation('鼠', '子')) +}) + +test('北京时间零点边界、周一到周日及跨年周正确', () => { + assert.equal(getBeijingDate(new Date('2026-10-18T15:59:59Z')), '2026-10-18') + assert.equal(getBeijingDate(new Date('2026-10-18T16:00:00Z')), '2026-10-19') + assert.equal(getBeijingDate(new Date('invalid')), '') + const monday = weekly('1998-06-18', '2026-10-12') + const sunday = weekly('1998-06-18', '2026-10-18') + assert.deepEqual(monday, sunday) + assert.equal(monday.weekStart, '2026-10-12') + assert.equal(monday.weekEnd, '2026-10-18') + assert.equal(weekly('1998-06-18', '2026-10-19').weekStart, '2026-10-19') + const newYear = weekly('1998-06-18', '2027-01-01') + assert.equal(newYear.weekStart, '2026-12-28') + assert.equal(newYear.weekEnd, '2027-01-03') +}) + +test('逐日分值与周状态可复算,日期不遗漏、不重复,状态有差异', () => { + const statuses = new Set() + const date = '2026-10-15' + for (let year = 2008; year < 2020; year++) { + const report = weekly(`${year}-06-15`, date) + assert.equal(report.days.length, 7) + assert.equal(new Set(report.days.map((day) => day.date)).size, 7) + const weights = { 六合: 2, 三合: 1, 六冲: -2, 相害: -1, 平常: 0 } + report.days.forEach((day) => { + const [y, m, d] = day.date.split('-').map(Number) + assert.equal(day.branch, Solar.fromYmd(y, m, d).getLunar().getDayZhi()) + assert.equal(day.relation, getZodiacRelation(report.branch, day.branch)) + assert.equal(day.score, weights[day.relation]) + }) + assert.equal(report.score, report.days.reduce((sum, day) => sum + day.score, 0)) + assert.equal(report.status, report.score >= 2 ? '顺势' : report.score <= -2 ? '谨慎' : '平稳') + assert.ok(report.supportiveDays.every((day) => day.score > 0)) + assert.ok(report.cautiousDays.every((day) => day.score < 0)) + statuses.add(report.status) + } + assert.deepEqual([...statuses].sort(), ['平稳', '谨慎', '顺势'].sort()) +}) + +test('生日、周次驱动结果,同生肖同周稳定,跨周明细改变', () => { + const first = weekly('1998-06-18', '2026-10-15') + assert.deepEqual(first, weekly('1998-06-18', '2026-10-15')) + assert.deepEqual(first, weekly('2010-06-18', '2026-10-15')) + assert.notDeepEqual(first.days, weekly('1999-06-18', '2026-10-15').days) + assert.notDeepEqual(first.days, weekly('1998-06-18', '2026-10-22').days) + assert.equal(weekly('2024-02-09', '2026-10-15').zodiac, '兔') + assert.equal(weekly('2024-02-10', '2026-10-15').zodiac, '龙') +}) + +test('非法生日与非法参考日期不给出虚构周运', () => { + assert.equal(weekly('', '2026-10-15'), null) + assert.equal(weekly('2025-02-29', '2026-10-15'), null) + for (const date of ['', 'invalid', '2026-02-30', '2026-13-01', '2026-00-01', '2026-10-00']) { + assert.equal(weekly('1998-06-18', date), null) + } +}) diff --git a/src/app.config.ts b/src/app.config.ts index 0cac7d6..77d7672 100644 --- a/src/app.config.ts +++ b/src/app.config.ts @@ -15,7 +15,7 @@ export default defineAppConfig({ navigationStyle: 'custom', backgroundColor: '#fffdf7' }, - tabBar: { + tabBar: process.env.TARO_ENV === 'h5' ? undefined : { custom: true, color: '#cfcfcf', selectedColor: '#9a6d0f', diff --git a/src/assets/home/bamboo.png b/src/assets/home/bamboo.png new file mode 100644 index 0000000000000000000000000000000000000000..5a75ebc7960264ae16b8ed492f1724c6f5f1a938 GIT binary patch literal 13386 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 literal 0 HcmV?d00001 diff --git a/src/assets/home/coin.png b/src/assets/home/coin.png new file mode 100644 index 0000000000000000000000000000000000000000..5b64562e7f4f8018179a0fb39e59f968fd8c0400 GIT binary patch literal 18047 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 literal 0 HcmV?d00001 diff --git a/src/assets/home/gourd.png b/src/assets/home/gourd.png new file mode 100644 index 0000000000000000000000000000000000000000..140064a6cb44fce0793e817358ecb682bcbe968c GIT binary patch literal 8985 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 H?lJ!ddM5pY literal 0 HcmV?d00001 diff --git a/src/assets/home/heart.png b/src/assets/home/heart.png new file mode 100644 index 0000000000000000000000000000000000000000..4b69d5aeffdd4b9bd4ba9a5adee6befa7b7d08a1 GIT binary patch literal 6957 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 literal 0 HcmV?d00001 diff --git a/src/assets/home/horse.png b/src/assets/home/horse.png new file mode 100644 index 0000000000000000000000000000000000000000..1e96769f4c83ed070b1401b25c2b48b01e506bd4 GIT binary patch literal 8712 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 literal 0 HcmV?d00001 diff --git a/src/assets/home/spirit.png b/src/assets/home/spirit.png new file mode 100644 index 0000000000000000000000000000000000000000..d6944d9647e84fb0ff3378580edb930ee3b850ee GIT binary patch literal 12727 zcmYkjbyQT}7dL!oV1{l9>F!bxlpGZ4R2nJy(j`de(A^SBjR=B*Fi1)aLy43i-9w2W z-8H~7{@(Sj=ecX$b?+Z{pR?oa&)IvQedG0XRLO`Li2(p0Q&&@d1^^)3D+nNj;vO%& z%I$FvqE~9BuK|FB=HCqh-sLj@06UcE#YKAU*QKaT*7k$9O9O?L0yZ4CQ?YQ?5A)^>f9$_Bj%TQMhwZ4&Grl&PLhrG zCEo(=19$)KZeEpt-u)}nEGUE-2%c$Q4Ktm{%*ry%ItwyAxrq~#y!URiZ}1FtdyBcf z-Mj7m{)S(_SUH}WN8|s#sEGmlFGrTO5qa$-Z$hXEuSgJ+l?EOSSo9*!5ba1(-+I4x>>d26v%GdVnKbL)Dle&ey+PPG5>*Iu=9pBka$vJY&K z0&H{36n8?yzRj=K07TWeah8$Yc+>{4Zxd2(^}?qAgy*sWWR^mgK?3?2rXZF@@S6qV z@yiBn(YnD1HCD?VMv&cDXJ6JMJ?ZP* zbIFX>#oaA+FKj%xa*CYR4oS~^UI&^^$R1OVr;tOI;#H~;PMOh>$uE`@Ph2j}I#yN& zsB6#VkY&&OpCAaSKRt}<>B*U>{vD>8H;DPDO-KH~D|#JqT_FbtjsBoLR$}{AN~vah zKTK=jcl&6rWk8Tt_btDk6i+CgP+~msk0~Pd?ZIW4hrq77@FYtr2f?*DF)q4{T{ICN8(FX1Pht}1a|z*lzGvo z79^2lMSkg#n(vr-k@z!J#kc}yECi#ILOg1t)4RJ?HXe{WqPOK6M8->*KHSDSR*vG247s^J;72AyN3w`F zYPUikR7ZC(kp6slD+2i2Rs4z;?f7V*HpS!!u1A3Z7X5&o*}t-Nec0>dzShmWeN9^N zDJE;TjFh&7psABT6s0=lmFiqMVI@yMu97kepP9-j2cO~nczL((Q!!h#_+svhYkbEw z%;z7dXELxEV#!SroHqFCUo3BL8ciTdPXwIqzDCIfdS&fo>yv}DEdQow9 z{e#7k5#7%?@|)Ok>^e*7=u#$^N85CP${1WZAGJQ%95(6_vv(aAG*t?q#Bh{}*+Sc| zLM1;SH?2Sq!zI z7XP12uIomY6Q3Sr8UxJQG)XJ=!{>m-7ZBwElerCAnmxNMrSK0H%y7Y|OJ7z~_O7bU zprsir^iLT}K310B{+z#3`)Tk72*hLH@%`p5eIN2yjlE?c)xGV{>`;}T;a{arXz41p zXu#ab%5J#QS`7HpJ2$#QF+v(qv%W)yFn5|Tfa^&uz4LFzK7T46aVK;00644MGVL!8 z$hwR3?6IGzIiJ^e_o0Exsb$2U6ZAN9w-~K5-R;`kgi-UdYm<`B+r9o;FU@EwJ z@@#qX)qgOC+jWbzB2f(+VL%L=CF22JDWn^!82kqvez7X_l--+5^!tul5qH6QJl*k` zYy)*|&KI8A$^~Z~c)K5ncK?6Q#eS@h`tXNquiRzsPX6=;)|rh-#7YR1oqMwpvs=9u zfOlHO|Koe$%Z+L8qaYp>iIOKMPs!in!FRIHDR@Nbm{k?N^|J%_*o|vI)H{p)Pr~h! zf2r<^>}EZB{I<%eS34xY~WkC zF|FCu7<^4Sv>|0Jy}0L69Kc(;&ykX%z2y5I`!Vpx@83F*k;iVsrs6qceZ1Bco4c=F z)P3j=l|r}C zwClX=9xhV{g-M`$wbKmB zpt5muoj49Bi7!|1VoU-ydtMop%CZe&o<6vN(7a`%R-G*5hWH&d8q_2&Ye0_E{ATRo_N=y{1n?s!#uNIq(>9G15a`V^lAxS z{0W^}AZC52{cuWGRQQm+MlAARe{+PZ<2>u2u$T3e`6H@VMH_B*cI-o7VVf0^MA#Ml z#R`HRlZ~zFG>V|IPZg-~{f5MMZzP40%>3r*5r11&_N*#1#oM!oAYvTw-(9%DEHT-B z;D*f=-y*sN^SwemZjmy?+A*Q%`%_yiJ(3c;B)1ZUlQny*(8G`h`ccTC^v`~g+&ewD+(_%gNIKCfH(eAC}>%6yijq3a-?3i z$h|KKR2X5-P+YO}M~9ICogo6kBljpCJszY;Cd&lS)nK~|L|#cIHx3~%X7CP;r2xdY zb9s=ki;CZrRh9qwQq{o{v3Piuf@gX=H3AA30*qg9HF-Joy#GuAILlMne`vDkX76~< zUJu}9p$)Kwa9Ly5GE_|13MI;xu@vQ*(awl~qUEWR_U2w;oQJ2y3H5wkriVs-IQU^U zY9nTFl>fdmr(vYU>W72oElNMS?|!eVov2qa$ulQE9BwpzFal?4$f`tGI9lO;wjBs= z46<=~PYd624@uiX*f@hO&B9}K4zHFy-37n;HGW07*^4Vbm zIRo?b;rsTs8y+gtGOR_tUj<>61jVilek>trR5ms)pi9AURh`J_rz}Jbsoz^4dUy+f zY*z76nX-S_{5n$WjZ*hE&R|XdcoCoPN=LEO+_(!Tg1fP>aqY1zU9wkvavCBqE5BEJ z-~0z+@>Gmj=LzwJ48>SeC)hd zD$lz-tmfnkHyDj0alY&we&|OtvUgU;%8+S_hM(aJoRK-pN4OW7xPSs-vI?}Am?}R^ z%8^f|*0Uv+*eX)hq@0jC2R<4r%nV%1SF^@jU62$w-ufSekU2DQtKzEDnd7I+tPOsD+j#>hSbJu^yJ_xh&9mv(f;URv% zmuLHiQSEE=W89)qp9K3WDaz6p(IYcL#Lx?KiaJ{uIf=a4<_sLi*qQm?Thrr`p%C$S z`3JrKQ6aXU$Gesga&=}@K{h%g`TScxt+m3p|HGeO$VaY8SEXA{H;}dam~A=ZmxDGQ zQ46Q<4Jt_SMp~;rN4WBS8oJ}FY{FO%xG(*;(%lN5+4cunOe%i&c3O4xf+%LiJpk}j zB6_|6A4~VaXzN?~Uqg4iluZP21ly!dHqhi8FN-_(CG_awg&I>cio9E?^4HHSh6y4j zfLFsJ4S8_X8+2Ls*=d<8M_&%9ET`}nGhq1sa#Sl2@>8G1(fihqWR>^a>a02>at5KZ zH2fDUKgGKp6fR`66}I90*~OI11kc*-@3m?~Pc>jKej{a&e%quHRccDI1noMo^7IFh z;r-BnYy`3-dC{0yG!i+RNr7qR#WtTr7!L z)(1l2x9mC~N?#dI2qjLS*?K_7ahM=kF;U0C-cap^8$UdeB*Y_{E zI%om97o}|}$?ylj4UQqg&Yy7{?d~@^hqEHHaY#uQkj(y)`t;}1BZCn)Df7uziWytJ z(4@&l`b~l^BjQ1$h_)A78qMjqIP8JLxH`UCvM@9ZTj?p^rONgdfzzywX2eE&Q2nA< z=4m+9SI0nDY`k7kbkxVl{M@IhiOGqa0HPR(=;(dRG(*82$+hc>pQvm;O@SZ6Hw8)4 zeDY_;c-scMr)1+XB;}-xs-t8#hL0zKC?+C0Ji=NyT6?uwn)cimP z34X zZA|Iv$`wx=A0u>RlhaipfMe1p27VpM|F_#AMhd&E=(7GG+_cdk|A>Xf;o6nU7)<6nP=Kx2u)$=04sxYb@ZV$#y8 z5{@#stKqU2|DDYGt?1AfaKYeF2>c3k2H8y&H_pwxOGF2PV(o*8;bvB}|FhW^No%ol z((VkZZjah^yG597Gw)u;;?rP0lP=_QpL^S-_^J`nJt^mR0Gk|Tlon2x^5Id8%f|(# zZk>l`C)j=+TkMPr3y1hA zs_q**Y6Q%*1o>5IWxpp_+CqP3Q`{ z*-LQ~f=?7NueRryuEcW7A06X&2H?e~;*&s5;~DP2Ps%sw<7GH2BeB%Y=T2pN@194y z9X5uyOOuvRJPD2|Z-k#*ama!EKFge@Tfc7wwmLQ}!iXvoLetB+I+2j6A7()ml{=5- zN`cAK{DEMYnB?Zx0wE)_mIJqm9t7Q=-V9CDx$U{nNqY73*E0DAzh8zuK97uLplXO#YUj|#JQbMyMc-<@qxa>w* zWm^uoyr5P8Y>&SFxdfNTj%oD=01EldK(tN~^@V^djK-1=`yLOMQ#jR*ng#vZsjK_h z9M*1f-B;Vn6SQuDjhig|reC|9^lxxFd?isR=$;}sHXKKhnR6bYwg)%H@h-`CG{X}L zE^!d86M{fe@s9`=g2O1!Zf^<0tc$oh{l~2YM+cO!Qj@-ZQ`c8Lv%9Z9XkHF2c4JP# z;;ig}+__eir{4f#^kw`$!KnnNF!&<&*KCUtN!!-Vbwt(V{UTIi=5ZxnlXpL#EnWmX-8%FYx*d#gRf-_k zmE{~1mX1{jp^rIsTTy6Q?Y;;v@`ddU^k|g z4gU4?TIl#MO=5Z<=KFg0%8%yrO196^OU#yB@AwMY2fJ@rBWdB}9&|TIJW+fb8_ka| zus9Tx(km2@+pwd)tD)h7Y|Ne5a5BYD3$7^C9l({mzxi76#>e zZlop#Kd;<@R6bBn#b*M1x2z$sX{&@VJr9Q5jAxUJjnwGS+l#BzSikE%MRFC>0q6lF zy|CW80cI3Mfxk)Csj$_Bhuo#ULCB+}eC&4cve#d-vTT47&%q>`9byDH!sIhssAKLkc2?6>bu809$ zOD*R}ufh|Ov$oT6cq4SfdGj^R(tgGG5+T^31?VEXLhqpM4k#EqFH^-gLyR}vPKQbN z;}ogYB@b%VE;aZX-chsS5w>is5~A%(o&z7=pft}<3u=}N?k-W?l8JDY=<*>PV%S5O z&XbA*#>k|0R6)Y=VIw-Yz1>4rM9c7z1fJYV`?De7;CJ1rJ-v5|h=r6GT;%)_xH3LW zk77%#qJG#hEI8@#Xb|n&ZDlk%;IX4kuvxHl4PJW&Kop5#=i+*NDi^Lr$MQjgr0i?l zp$(O7Gb%IT2|vfCiXYXHb@qqefjvKuY(Q&<#%3LZGMz$TqalKE3)t)Wljj< zLLYGDuWYaEW`m3lXkqWDdC0(rIn%+`Z}kDW6X~@QHklO)mQ8iX6&jEWJxU|o3U5`-V z#CAZ>=E);@u-S;BXVx7#;r@Tc?yU&XE7o=o^KWVsT|e5 z9KI`K$;DvXgYYK`DZr#{G3zU#gstkzHVurrM&Q^cB(9BZABkIIm+u+2JjjM;EKB!d zWD$*2&>=TOnNXZ9=4cf(FVKB?<#TIzsRKFY_C3%RTgj2(5a;o4!L6M?%5wP=%m~2X z(%nB!@xMQTwK?@-C+HZ&!E#iHN`D8t+(`}(JuaBJZ=726F45{RR)nJwf2Nl}2w1=_ zjMKu2H$DYowK6Ozw6IbPr^IPqlDXs_8m2;hZaaoBUDK;%e>Kc+$c8`=NZY^7d$pq` z=(FIYe&gPK+a1k=4vnL1b{i;ch@29!_ESWT>^TEoO_H(QzOCl`NzsRjFQ|kqOD$9YG};319evXZ#{=Ou=v7J9{)U^srxx~cio_)t zwb*mFl5A@3$J3%N=u2T?(jF z+2dNkMJzT^QP3esy|QgNy59b4@)II+66Me;fL}I$9Ix;13X>sA)vf{_fqU2+yf8Nd zZzq{81}5#M%cj)}R>iI`T?1HZwq(=cxzoc}S6s}-tg>X@7MW4!+6Wi28!eV$V^_5& zfss#Y(_J<8VT2Ith0LTAhtYoi{V%e7{lh2MTs9rhj|2sbQKgVcX!J}<7pt@$meEh(v@x9qTg#& zrj-(}m%jd~U6x4Hz`Qp+3FHknO5c>_9-Ap*-aKeyrSjOBYE6Hkkru+;1XkP70aR}7 zxNg`X@Q10{Lz+Y-X(;m+B%$u@Nu)e2y!_Zg3<4iE%Qv}0JtC1n_R#OPR(`4m7iQw8 zEyj0?5Qry&$s&JSnH&I|JY3wr{^m|7y~_I=^cJ zlCS21F#4t~`{w9>4s}Ub1vZ_vU-!gXUmqq&KDw$;)Wp6Glovy3E^i0BPA|jlf4k%c>+DAb0VOO1j*(?}JREIIO&xr!{_ab>Pe`P% z2O)@3l?~#yLjzD@d*kih(@$dCQ9Y~AN7ELQqa9vj?-KOr34VL*xblIgDA238I(Ds6 z9T6QPH;I~#UmFc|gIMn*DTkVakhdAzPge9{qAPv~4UWdMZFKU`@NZex=*~+Bb}=@^3G2#?(-=?=?K2y zRZY~(JGdPta9_WZK5(0|(nQ@9eKr3e1c$al3FkBpl@8qD1|???r>YCz?&PJs&O8|p zA+Wi8n}`ezxXU;|8(M;n3kmrK?n%^~pJ2OFzj!L{J_ivhb13C$V-n(Xu*T5)T?9&F zq0ieNQn=70>J?#tXXUTQ|45zhX)8YH!1IrMqw#OWi{GBvc^)LQs*RsCl5Np>Nq+?| zX~2<*ea?bcp)k&pRJC9}=hr+BeTOqqQZHYi9m6*Johvt6O5*mqFMI4B`m643!>AvI z4rl7MphS}sJ?=oh-86t7GLhhb6)|ZcAcuTY;zw|t#_TwAk0k9lMn$Z+=0(=*?3pIc z6=E06@?chI#7r#fM4;R06 z8FvUfBpqAg0F!r+rFFE{^`W2+#xISYsn2x~7y#CfHeT=YP{61l5$;q6` z6GSMwD+8MCw^xbVQ%u0TsOqR+SVh_5MZQ|`I8{2puE0jef>}1^p=o`bX#+yII%R}{ z0>Rp#@J3nH>wT-#;hEdL!~3_j=YIQp-=7BWUgnH4LObo#YHI|5D*W=3dV^M=T{S$k z1T%t0!$(W)*uV7fI@m|p2Gjj0#`gc=!!+P_|rGBpz|&^q|Z7}Lg?Su zJR5qG$OcW0zOSX|14;?C^;p{T#-YP^v8{0R+AA|Ru{)aR)lQpL76Go^%G3FMy7+}mBZRj=6wwILr}p-enFzfZ^wvNmxz~N|??DA7YRShI8cXx7x;*T7lMStQ1*;LrhH+AuZ zyu*w|p^#XI>)O|!sIB}2!w*c&iSD$d3y_G9{?&9a!E3s!43bvz?6MN5(G9b04p z-TTJ%q`TIm7Aj7tJuY#!WW(TrELt?ICfK%$lexAy*sI_s6ErD_rUQ!&=AOD5l>I zKj#XQT}%AnTGb>xs9m7v?-Tk9w<*Qn2bebt8Lc?iAv(RQd(`9q7O4r+8=N8G4(Zij zTFLM(@q4-Y=`{+MeSN1{jfmT;W+1Q?=Txtj^$dNVh>brv+k)h;g7!1IX#r#K_@z;^ zSga~2mL9%)J7c=sjro3FSqEzC???>qYu_Q-E=ud14N_8+=gL0jV|nP)Hg+QRarcr7 zRY?3VDBGWuj0~Ss1*vkRutC!JHw#$N=lOL#GWDxdkA>iWe+g|uj*IyL{cgpX1ibur zn|c64tIo`&Ic(|U_?>^#&*puNsdd3KBZga=QEOtyq|vFs*R(~h5PB7&x<0YU`ZGCj zzSSL_;00WYlCixv#gtm6feWs@k3v4R^Rq%e`!1($5`+JO<1o+yA@!nKieh|0)oL}n zowmOR0@;@dyf=N>1mbN_6;wwN3AM-JG6-)mv-yAc`P`{pc#kX25@;wzA=#6T=O)=m zBGTX)CRgPe>{5q(Ay=XpWC@_b|VKSVk7w!^A}W1;W+V=%=kCt6UGi&ey3` zH})wi42!XGTpVOjFTT{a0wK53TW(a0z|gBY!lBrwbaOq@b}Sp-RNk#q1?-!ReMJLv z|7Fbo!*Rn@i$s-Bbw=0elQS~Jlvz$VH7_bV2KLyEkPH3Vz0qvn$|# z&jZH3gsZH>Yq8lF;;!U0{Da{^aGN~_Jdjbpr@HbtU5MGV<`mBZBQgnp;cP*W^7dE; zdL=4yw1swC;o4^+;k>;QxMX{u(3z8i4U`IIHTFtAf$D7o-cFz9gb39FT?rpMOl^;v z#DfDjjW^U^?p!Ulx&+_}J!rujxrny5>>!fftl{_pZokpak(P}c)>r#b@0Y~Yo=Ghi z3)oF52NSxoj-GLn`x2Om;uV+@teUa@=y}Ti=g*G$e2W2MGUZ_1N_Q_?nAcOp2FsF6qj^L@{yKYEO}T4|1MNl+?Ttg9R(vmgGp>~yzk$BI_SW(Z=WQh?98(Tv zPx=8>xY7)4NX-ejo1S`nhYOtfTf zwnY;ZY$GfL2C6Baan6H9-)LZxKh~$_9lz-+q~uP*o|Y8lB-^ROq;J*63074>eHOu4 zD4Ok+D{cihj_aFH@{M)26gz#m$*u0VYFEWuK|~oiP+v{gT&=#ok*WLgz{CgwghKd* z5-$ClUfnkdq8%B?t}i2B`o+`sNx}WF)(1GBs1YX7JH4k*3~)6FhLnx^DXHrgRE0e; z_$C%{T~=d5Np+1khpu=h=%Bc=*#a*q!-Za2VeL}Bsbq-=CcHPlql48}eD3^s4Abp= zS&;N`FM_&gg@3;_ZF13Vz$!|nHPAH|-}~sgxId~UbxF-|qfaY1UR{?(t*!p7q2r}F zuG2Gx>;q7b64~X4@$lX_W>~7MjM26%Czglc+8@`aks2L;83Vx#H;xTt=1%>CNkk$U{zC<=7E8!X#yWZJe^-ECqKTefhJo2!4u%)7u6i$~VG1K9pczk9~TiBM9ohsX#)Ug76-EPVl+^4t3;qqN%O)8e7RE zK3x>Qp7#c~Z8VQW&xkTj{;oe2453drH<=TwY|Zgq68$BYX|z29p43@RjG~VlVPY^^ zp*Z-4BEcH5QTde>`EFMfsZ0M-m8ywNHdCZWnWRjB9|FdM1Lxyd*U{~n?|3{R*1`$1TPK! z;3}v%;Ej{gPTv5}Q!)Fq6)zW>zw=^SGnOmI7P>1Q8!KahgSjsA}KNa}62_z$1kahCOz z%}rN;L)AYL+LhC6R1lgK#OYK0SYL72am7UZBH!(EIp|3L!#0!`;zR_r0_8q=`#q<5 z3iGh1ILY6~wNKW$oZ2P)9V={7rM)QmM96>joPF>|6z7Qc)g;GvA_LfPY+m(%0U8fa z?6iC~^j^dhnsDU1eQiqRyNN)ZB`iE)XJZL&GCtEU)1PiLKR&KAN z9VWhN1P(xr%B7a3l=p&o$U$)W6+=z^g_za37j!0Ovi2i`a+~*P6I5A4X{9xHe?j)7&?wC9^wX6~}rDsvq_inZNu{G`2aYWE#hhS!ycn}zm@ z&dp(!Y}NwJ8`qWGC2;o}1-%B&U}gNTDcPUwM)~|J&-|bS0@x7 ztSMt%d=Hqkl=?l;39y+j#b=)~@FBnrNO8(e-lClHOnN%{ggYUaixbzD9sX6|X^Flu zuPdEq|Ixa!_2~U+YlZ=Ya2|jB5=z-1nosxv+Bv!H zK_UIgty($aJr9F;-Kk(TyQfQg`|tG%Fe}d?(Z)V6Vlv0@lwIermRWC06Vb)=w7Qy_ zr$dJ3fP+^siy`9psP(o`a9;nuq+!hXEGVkrIZtol?sYaxPvb6twb|5hCN(J(_JRrC zHU`8WgKo5pO8;9Y zKgh-|XrxCfed`NG=+VtQ&yC;3@RH(|@0CNXd4MzzR(gVm>HqzM;eY=$WYh@%xFx6- W8kI#CPjLgdOZ};ia@Aw&i2nmA){>F{ literal 0 HcmV?d00001 diff --git a/src/assets/home/vase.png b/src/assets/home/vase.png new file mode 100644 index 0000000000000000000000000000000000000000..07ffbcbe0d2fcd0df259ba41aff6bbf2b1a0b00a GIT binary patch literal 9426 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 d}lP45lyMGB@NI|96%z@8Cd-ijm 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

%n`e{GZs~?a=e!3*}^AeRt4$(t_i!DwsoL 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 literal 0 HcmV?d00001 diff --git a/src/assets/zodiac/horse.png b/src/assets/zodiac/horse.png new file mode 100644 index 0000000000000000000000000000000000000000..18a486aac07e099f2c78ee4187fee5b4ca0ad7a8 GIT binary patch literal 9780 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 a=;ijyPQV(xS=2T#fVwhBsZzlz^nU^R;+m)c literal 0 HcmV?d00001 diff --git a/src/assets/zodiac/monkey.png b/src/assets/zodiac/monkey.png new file mode 100644 index 0000000000000000000000000000000000000000..d4e98f0dde2f653d36eefae8f49207cf52d3a7f3 GIT binary patch literal 10601 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 DeL5#& literal 0 HcmV?d00001 diff --git a/src/assets/zodiac/pig.png b/src/assets/zodiac/pig.png new file mode 100644 index 0000000000000000000000000000000000000000..711e81d63f9d1f3838347dc00c5c7d5a0c4341ff GIT binary patch literal 8904 zcmcI~byQrt=zQGV0tioB96JGv*f{{g?p>`XL=~4VD~@Ck%BzO!2WHr&j>U z$S_5DSzX-QPXd-a&^)23xRuw*GIR?~k(FdZ4uDibCDN8gDA-@? zWC?Nk-}O1@=&XI|Xujz9)P{2q2vw}+hdxOmZpisLdJ-NUUJ`PEfrI8bUW%~Jhe;}C zN?pjQuPr8iY-`5Cs3k84&hT}xEDaYm4EYNBd#m-fV>oqaE|Wf6~ot4c_ysB(*37-`W{A?n~Zqb-jH>VF%U>+2(A02!AiVjgU8 z^kmANliSC;@M|N@&7~1Si4#Lft*Yab70IdC)2V5hf%69krq`VDlN zFhncWaAQwfAwhL^o=@YF)AZ;cf7EPbW1-uunHZC=niH6Vo16RYIrS@oEcbHX_hEoD z#^i6d`xhI+6CM??Ys*GLihBq{b=U-+%bx(fuzNq1Wt zaW1>vAzpH0O3f@9Rjjn>yC+-CL>p**pA5u)cbPTPFw~rU2s|>JHsDQS99k0rK+e8c z-^jTBbQRN&ing;fTE>9Hje>WX7M}v=W`4^EGR=Llx&O_%TPTk<_RzdCLRr_*FYMUK zzIR*9^j-|m6CrW^?v-l%f{q_$C6>qvA$g+h0_Wbe4-_ou`0MNt4zyq~)o@YrCg0CZ{u6%?cc)z$IUl(ZcNapmfjJ6) zbMm%74vdVsUi z40?4G;ekXLTZvE^!I0R-YuZUvv()o#_YBIo>55jmHiM6|k6#3VTx*U=<_suIiY|`j zhLiY=t~}qkah$m{$@E#Ao3&>$i~JlV-fAJ}X+#{}UN0YxECpNhY=^=u6l%;c%E8RG zo*x})@2gD5|1>|&&J9q|%xeBkv(bUW<|8Ab(fDmWH?lMuGmFY0E{j3Lyz*gjFa20~ zk*YBk$BfA7ehmW~Sr$fcj^h4io~J4Re&IOJ-)Qi-=R2RjCb}wSX7CiM@||7PYR=P2 zDDI`&gKqEt%nJ^U;9)|m zAUV#lMUO$U2Q@ztvw7?e>{W@g^!>YEixs~WD<3|(Dt09wo5oMp%d}YP)2~J;0F+0U z0yi2#86^N7Xk?myRKv_-n{_!~TfQLd(^m40;{vCRR+EZmRt*^2d0LiblA=ycC+jka zgU!64?M^r)Un0wN)QR8r`lj{ z)lgLsq^&v->=HF>Wjdnyd!{#WY8sPzz4pL}J*Xz9*c37@_0voz zcMY5xrJ*2nd``z7;6;A}zXDz@@Ijt;F4600fAVb9oWtZ*#98qRfWhRKe4zg+YHVgburM zG*##Whh4dfOs<2+^PTZ|qJ0CA7@f0~>|3Hj(gZyFZMN<*;g>s`6XGl=fp9nvhU&`QNyty=Dv&qy-gx?>^Z+cWg#eCsY`bH_QHOuL?h{Eg8av0qV>X7n}#Rjn9k|Nk&W(qm486t zl&)Qd=;MzD)lbVT#D6V+*`- z{zQ_IOZ7aY(G|y+!Hy9Gv`e$O*A9cOwR5&UD5?-N&;TmT=@lalcoCS>OI}xkR<+Xj zsG+Q)?<_E_mnLS$+xY~?+pja(;Bd#B)53gqQQGXB$VZG$1epHt@akM-#2xx22CMf||aw%;uh_d@=jJYiuCDCm$H9PyN+WizZ zxXv4T^5!9wQNU@Tmea{U*$x_nHu$Ec*fenqO^us>bbZy8F*0?mNK!1 z+0^wFsvt-(dGKInYhJ9tvB&$HKK?nqUyliDOpQJctMbAdgqG{Q6eeDtZ3EJ--Y^gn z7<>T6^`Q?EMiKf;s8lw>xTVlsV$3j22y}2KwJx0&CD5FQ9yK5v$MQr?*LA_B;(Iei zVgXWw~{v7qQKf@gEe3~Rz4$D)@jJUnb zNM&$P!!FsE>hHyvU#xUNx#(}=L{8`~U@|9!oP8nzAnQ|g-UXr0S*L#IxEi-`toB-@ znk{m!IHbWe4rc+C;{wym%MBO$w*wAon*19U%IwI-Z z0WJiiChG_MPXze3B{@ZtZv~+UrV5rI;Wn2UKsA!}?e zg4%x>u0#gXKiX3ilx(Zx&tY}X*G64Xq7NHZp+gP{m|Z{jO=1(Mb+B$kYSwk~&?J9o zuncv!3zh&jd|rN*Z2MjlN*66u0Dwk zm^4=FW-+GR`at0zskn!{S)*D7^_}S^Vz=94uWV^T`;u}j{fyPSTBbdJjSqLCoqWGP zY8Ym3Lg_7!Sd%ksvvikqsgbnF-|KQZD~`z0*6U4`4T1qS5$&#^t?s&N#eq_k)A z762oEx{5DR?010(__euLXqK!e5xu5N7pqKYgq6DU`+dx2g3A0?T0KR-O z)y42YJEsj!lkj_s+2&igVf13D>BYip&Hyn^=9i+Nxmi3fuopf{^D05o0HN7M28_7g zX_X6|H!L$?a$4unQB*79N!<@zg?oD2w5ultk{|KHV{~#2=2&{cC%T}C9ir_DfpcTUl8mkJy}qQ~~RKxKO{?*myWVt?5qhm7D#iXEe0B)xWge{jQQ;9U0$DlDED;O&>||507?8OdrvCEn z3IsDA1TYNEQ6#jGHx%?Nw-54fk0**(b@!{G&}EzbDidrKTG`c~7jdbJP64zpV=Xv# za1HXCCH3J3>#Te6Wo7{KE_}iSKC&nG(W0f0Jy?qz42-n17;n_hyXO&Io_8?z$x)tq z5YHDuhwn6}!})G2MA#wEfpogsf91VI{s7Yc(gew|B*3>bwkw1K7gmIBFJB-}8?syK zJ32a=zkpygNca|0L)AjXK+!KC5t+WI@YwjTC4#jh56wy`f6$0{+g*y~@Fu(x|6l03 z{rXy5kQDgN7)LtcM=p!!SIc3}{nUS9Yv&hRmk76jM|oD>k7QOK^5-ba;RI3S7csgA zsr(sDv$I3*R*LiT0l;XIbna-=WJ(S?WI!Wmn>iRVb;_e(<*xZ~$RN>ok(R@|hK>J0 zx;W7X0k|4nc0J4}g9UVbbb3xlabO=cJ?h)MnchJM2=zx2F$0cd)>)63(AudK0jvJK zkW~frV4f&IJ9b=h`&Ud7V-Q*}F^5nH11_jZ8l8ke%Z`lMM;HTF+C#lg>4y4$047By z?cs|FlFXZD_G0$AK>rU4MZggjna@SKL(D}qU={y=LXZ6`bQdoL?1JxtUm$Vb=G~(o zHD~a}!~$wKNw0VRvhhIz4W`9yN$z!dKXc)I-+>`}Uk$&+TiJhId3W_NTbQmYUP1=$C_eLMV`r(`e=~mt`ri!mu2=f1{Z|!8GMc;HAE{FYz@pS61 z&f6W(LEHI8JrZT|S>1ogF1krwyN&J`hy<9L;0gJ395FwME2bU7^W|;)={( zr8;7g!fH=NGi*d>QqXPz`Hsiee9cv$KOqOoH=vCJ{?McmF7~F5OIc)IUum6n6LLG|=66Uy3EbZBS z-P+&0+WEHnQm-=(Oe~Z2{k?Xs8+xFhJ9Vqs*@B#6W6MqP^QRNDo%UoWtewl;Y*lcp zLS~&|GT9@OkP3(CRVC91NzAd$)iQQyy1C8x{xJe5;USi#?9DQZkcrx2?^)WUIq6t1 zeB)GnTP0A90UAo~e+x*WzEZ19*nC2EE@%|JXFtE%2qjfB;o zqvm4cPb4tY`-U~vnwM!#G-A0kYuyjZU(DHdZR0CQ4OVYZmf92~eZjWP3b>lw;57O2 z@hn~huFWL~qbAfhoSkX4RcL~@!@&<*&$qv4YaM)BU#e~2eC7~qJ=8Rx%-Y_Io6!G) zZB^O6G~8LeW-Y(8&+Kb8z2mVfXh++f@UZ`8PXE3HrpX{?YDHKBZ}Hh8-w$ycGl_%1 zxC69YDc|YU)f%0gNNc8gPHF3w5Yf>`0wZ?>veKICViu1i433ont)yqWus&B~nK>-abU`@rO4V{(XcFriNnr$*Ja- z93&wX82D*)U6-mq@zAz3U@SddVo6uqB9=klV5LEumH4bV6+%zoIKo}%_4>$wrU2p_FAgMYYDi`H~eU0Vwv1KO;o?qpUS$QkY6YjbM}IGp3E zmo~Yd#G0PD9}mBw zkLPme_oAAuJ|+hYqSd5i{1jPUb-rEctE-DnM(S zzMlg}!I+4?5enDL#Lt_MC;P$2>V#4iL%A`ZR2lYMtGsB%MCt>bh73$_ZdLACIfOGu z(h3Ta>T+?W9$(Rwtu!b#;3|Cdx4OrApTX|HdWcJA2NBJO^>HpMDY&H)1lUv+$w%!c z8lCyTh77ukr{wRa?fK_4lSMjiC^;9}BqfhMrUhu6BE79b`LWQp98TV}dG+$ydw-vL z^Jd#_(Q?eyD;IsaNI-0+DW$_0uUcjXQ9pf=YK7%pIp!rkf{zO*zQ~ z89`T|zVd5favzj!3VJv>zxDw?A8HC^KJkoiyh@_k zRiYO05PMg11Jty|gf^B_JDD*JAXjDiyYO8O(nxeaBx)b-bm(<=-OK?|0CeJ3Ci+`$ zJ>&+mOOm}aw+i4FsSY=m8X@X1yOpFJ5gTx+S@Ub}}!wHe{c%Euc7= z{z|v&r;@a2qtdmMaEv#DnX9-r^Q@W-=7^SS5&7vxVScv>4KG=r&jwg*`}FyD^A@Ip z%MvmqW0B0C4w1^H0`}2d3nFQ?Kw|{bWG*pYWgz%QKD`%Gji}Y($SfsQRCgB?E+yS+ z8yj+f-)-l6ObJAvykzny_FZQ_O!L)g5_SJX8`iG*&BAQf1ByDr6s!j#nWnk6l z`2Q@PUyFGCMYknS$_ZN&Kx_FuQkmgHVjq;rJ)G(CEx%lvkpT^kro>#S^CV4L2xAqF zdDUTarcTtstS5WZJDt%ng;9<$eKuoifxX;}TQWIP!{}KTH4F|E=|S8mjHOx=Ob1c1bGx<uiH;hArbfb zdFmb$2mW9kVJ)vM^RbYew@Vt1dFyLvEY?y*xD?z(WisF4r62L|Js-Nu23A`Y2Ny}F)(&t2;aysh;;+8)`Bnwt!e2X8|t5@l{ z@YX>Fbp-4a?$8YhduMNgrnYA{55&o*aUmmH(6m7UeH)Ve4Cc>H03Y4=t?5gdKHqH_)ubP`9F zC&9tgJ;*)i?;V?wR?1yjQS1Js)(Ix8^Xsl_h^=(>3d6}I7n)hyDH;_d`bi;OaC~gu z_pC$=db?6#tBhW#rA){lK$z1^nz7l>w#*0{6({e;YoE^SX(vO6)3$E1r5t@XkCSD#lYo~QK)bkNvO60JB`4>cAHRc6RjW&%c+zBa2fbu) z--EB*wM^bU=vz%+L@Nz0ylZoVI$EhAM)1bx72Z`(Bz&Fn4GO&72RrJfM^o)@dh0H+ z2|~?WQ*ft;5H~0QudRpjXpMljTkDmlhDDKicBhdKk0^_+`pSR_aqsLN*O^;p zt)WL5|BB`5pqeaFddclbn7NY?Da}7XTln_3bafZGb3K5%+425$D${NDw_-573&1TB zV<?t@B}Yoo$N>-)!bfaN56{cb2ob)(S6;DV|b-)?emfr;TuL#X(pC&q1m~i zxka1DH~tCL!(37j^w~=>D?>Q~o{CzvQSM-*Zk8loQJiZb67L=b-PWk4nCnx;&rKqVm9@<{YbAqmk~p%* zCPti7%APH>iE?tzl&GazZtB%MG63?DBPkQOJG1JKA_q(Ol_SR*T03^CUa*X_TGLiV z&nnw)#2w-B&w2l_O@8wuG4Oh_{;KI>Ji)ujJ%(@j479q&p(Hh`y`5p0n?uO4Ffp;G zr^8b)nDzvw&Kx>Sf(X1?;LOLc+i`t%fnZ5)Ih7gjM!7T<7dT**{3=aUhaiiN`@)$z zoe|Iw5Whx7-M4Bi^E1{9NqmoOO-OV?)br&lX`G~_8%I4GqRH)o^0W^EB7C)Qd}crO zB^yTzY9!7(!dKP+0J`1Zy8vgO1i)T{n~*DSdv{RE-%9kye11dCwR1lwv!r>BWPZ^+ zHpE;uuP3uUud6`|&?6_K`(eFtw^kdGIIcY#MU1{@gv3b^u?shxZ{WLBVa;>7J`_Io zK8KEUso$l+l#wjJuxdU){92Z>)UftXk?)siW9dr3){XGN+W-*6`r_3jxO znWyMxkvqbM(DuQ#wN7mH^Na6e2c8gETqWK`+80TRpzB!8f zl@;X=*+QU|I{-v5+bt`wBLKD=*WOm9!@i|_sG`J?feeTMO z?~lQ5ZywIT+4Sm z=Zmm?^h1+ef+S^2sF3jXOgFvJbJ!=88o>)M`lGGJd)h0U(2xIb?r9K|b$FxcF{crK SU4df%MX3ZG=Nx8-@2lN<`_HTQYOD5E-MW2m_vt>}ef#t|zh6h_YO9dnV!QH8gMNvqJEttrgFct8*+W&D|k71`_CQQuu#;|X4@Pn6dGF7d`<#4+L$yXGy8n5zJb zIiC&wAe>_V_bZ=NNl7Un+tCC$1}R9+sXif3a$*~WKnp6k^GM~(T#>pPJ3m`>DrH+o zgeSUCiBA?g2m|6>e)TLm?l){+fb6v`AZJXs-k4dvQm}d!EcMi&pjH-QKG@fH(YWd3 z$)waiFZxq-k$u!C?y?xX^7ACrsRqe+@mnrUFEMV9>tpvvMsU*-+b*A`c=<|I?B=`g z1ZD&MM_go-IXo;L}L4X`$ z5>IadP9k{GO$kjVIi)wVO0AYT3M~(!QFdNF!LwJkC?A(u1xqHWTCAr%&ns2uK|}GS zJBgvt)wFj4)$Q2tGCn3oNm+y=AAX21U`;0zdDQj_x*g&`vhu^OQBW>To zbOPV&6yRlxT+3;;c8UHU^D);c&nt8Ht9OD}?a8T!T+$4)Cc=KItsGhLF3em(_l_OW zPy*@f$5ZPr>?8<`M)_Ifn#(>97vin|h8<05lU`TMmdRit<@Q#-q%LIa_)LcK^bVLQ z=}A26Poo}nqm)+1?V-Lb=Y>9uPr^yxz-JV*W%4Rt^yX81O8vvlnt-BGSXd^i`{b9P z68dG4p<#m)3G4a0N6$Si4ciLo!Rb~;9{U4-wlwaY#rtZv#?1F^wOj5w!u!adMOJW2 zZGuExjV=7KFACV(MW*O%J@%eRNzB};m$fnhX5~0;5;Q%HSwo`_wS-zZFi4p)oqUen z#!Warr96$MThbgAN!0nb6J$95DbwcincwBWHnUS&Wv^{ZaJvk}Dac#JMbu=yd{S~h zjr785|KT`rJXEWGy-&IwgRO(H0%GK}-o_Ovw@!b>G#b+;STb$){@Q9TvifZN{r)#1 z-{2e@+VEaAX*P?_1&xxZxVh;9X#Fh?m;Cb}=)tqZE*(~5resSd7`BnJvm5|v*bW2A zNzq?&N`)#d@tVrW+;4pbsh%!lY7d+bar5fHqyCTs)>jNR+aIj@K#XXIT~tZ0BB!JC z`tN08pYNMK4Snd$%LgO7}#r(q}@~`9yU1myFq{yukBjU!NLy z%$C4#fAU$ERTjrsvM}ArK`w=pq7~57ZoL{72B4IwHXLG@G;k9wJ-cGRdpY>!`RKM0 zBn3-b{>DBxs)~o|`L*!8-mTg)TcxEJk3D1$<+j@}4{Lg+-Aau;(b7PEl}Y2&B(L*& zpCAnJj^6_Wlging)WzA>kx!bj)7o`WLfcxTu!jq%n+P|L)%8kCk>2;Za*%7}8dwj3 zNa{B8n@YZAm+!|sXy;FRTol2!!~DqQem7y0XVruC!kO=)Wn6WrrzSBT_+P2{_Lwn} z0uETkg&ifD$PXk*>&6JHK#eCtBC;I!($c2cs=~4$x4Nb*DTkCqRV=SABjksVok}m+ z=AW#7Ra(k{D=(zmU1{l8IuYU%{X8ar!<}o7>}XovZ%nrs&_J3D?7(K2^kNSg%okoR z{$WptomZ%Pv{|8~qIwme(cdtv<;dcSqCt>Zi4)upf3{Iq39@Y(vAkf<&Pux99-(mi zrfF@Kch`wcdJoO#b8Tor&puXE%a_7+8H&rauc%9rGX9<)*nm|;LZWhrfWW>-#83pS zR5gXmg+q|~fS!s@-Z!0xEBL`yJ}tc74g=&~WR12r(#$ef3%jCxU}{8>e5&S+Bnl!j zq0SrHfWF)w$3N0pbB(*mDzRN_db z`P#p5S6B~k>d}l`o7uC6X_c+7yG_5Pu=tq_xVZ2}zlg0D-F|}HP}~&~Fdu^zM62Pk z+($Yc2hb$t!9r>puo1f_aQi$EANV-5hZ?NPsjNM5!cKDBUPzQjXVo!377_AU5sS__ z`T^37?YPb|GO+xRh!b9@=_MZ|#8S`i_&KhST%ozRHg=#FB;P^PfeIXn8a;@K6K>D# zD3e%EPYKfv^NTZJjwLzYL0zCqw$I(9klxi!x`flaIDL$3@4HmMAdNA*Wn`sj?)`QPoQ@#PJgr=^a=g!~gE zfy{ARJoD6Ukh58Jj&$0VgT-REeO=#ykvW~T0*~Xh)}$Yx*h=WtgZX!>EJ`OjP*)+q zcb@>?@^WSUU{U@Q4o3X%;2EPf0+jecW679Fgth0dO|GjE(!C>%wM+!fUcmbbgJ{VFoAgD*_IM!h=YV&zrt59p!J8U7}C5 zj#m$Uy5O;l8<2XEP6&(OR3J-=uH9^P>wnTmTYZ_u)iyNw_4KT5nKG1QoVd>W1p*mJ zs$J|pW?e4MIMZLNth_Ou`3%TKXRPx|Sm;=Q@#G#h#!mIeZ z#yC+zP~b4*X0%BMS6zM3dHj zVkLa3?yo%&^I*G}YK^>&Vr2tc{%O5v??_svMSrs|cAp6?jUWGOa?15V&`X&nt{fTz zXP2ptGc8*#jQ3lg$4y$0vd`Ksua?F7zJAdDe*U-LIY;1NydTqh%n^V0sLWN_g5MIoH@4 z1=$h1ok#b=lbEamr+TaRO2hDhlt~8xr6>@oiELOg%n<9{<>U0IS;pb zC;J(ONF^Z zx?msk%;AB~>H+Hys~=a^2FhTbq}1NuRnpnpuP^b-3`}?kGZ=h;VkkvM}FI)Y*5KBy75}*(N zVupU5x5BP~zfc}C4}$KYt7}8E*ZI4S^CgbkpSRl0%Su<7F|En17_wtxV}2SvsVn0b z_9IYL7Nk-_8X3!Yk&L8n56NIv9t5EfBVR7YCGRXIm)0MY(-iJLsdUqJn7`w0*P(*^ z9ig)}nK{H#e9)EfaW~$?>U5%D)N5_MVL5(E!8Gdq(nQztEfu)_-O_>3r`Cs_9mrAJ z)tbBMw5gc6M(ecqe2tuD>HZ=9QT~FdP{s>&x>onU2BTr0dklF8EwY~y`!DF}Jw7Ez zpX2k(P9`$)#Gx!Rmh9X=Fb7vwO!aFhw{#JC>eA3HGP|B~>(``TGBu_;`6to5=U`HSIQ@& zph!^?WMR<~?LsdZL{}GsT~n2$*2j4D>@zIuPye!Ebbk6mRjCqdR~8a4-;AGuZ*gn? zF1zx+W2toYq2EGgAk$1qs+AJS{0G<^Fxk=$mX)MRtHa{JU9v0*nk<{^5{=2~jGFGb zUd*!*7OsogFQFI1Ge9IjY-w*zVa?jW27Iv?Y-HuY{Apt%)M&sA z)I?KmTJKuc@H6g!W~Y7+1}Kf;rSRb@c(@8?vUwPP-%LnDFLT!9hf2$=G&pC3 z_&nmO^x0&xPC=ZD_NFORx-L(x%w@Swbfa@UEku%(@HIrl7_l9w@mSvE{e!o2O&&!N zvh{p^L(c?J5s%kg56?e|oW?T0G#A`wIMen*WQA51J2P?_mq-q;xJSFkl}pYCnFTQh zCwB_DxXJYB_7UA<+ss72hNT-P?kC!iL_t+Ol~k zEhz?$t>hC(5g&JQK6{b8r;XhHOvgG*-#0wh_aQ4siV6=vrNqDx@PN9vJ2WAbt6u~G zWHw)vOhyiEI7>(p-lJ`y{8=v~5bVobEL}7x!kfZ-8BlV73$<~{q>}@d zWqG@XczujRWV-N`1NLWMfs(t5JNZ%wC#sW*YoKr0?`qt&dryLh$@~ZP2L8VIz}P1! z1&|XMM2j*s8V(Qt%CCZ`f5}IzQBGMzkx@I6mQvC$PaMdJV)4`_5NdXGj3NF}0k# z3T4tu0)y;K0qhn|G4m&?)Y*;j(!N&4K6y}J&mB+*c3d~9??F4+dZN{_AT)|;xt}Om zW)5tQZ|MP?8pjhpsHDPcQ#4A7*;-B+eZT_Bs;8!Ma-n_2+^!NUL%b@^Yd!fgUuw@f zih(wr62VLBL}ci4mX`YfG?LPqnJ6PDuhSLaP}!5{p10Ot|wbKIJ4Q9;zzo_00U!ln*5iPqh)rTSnWTmcqT)WM%tF-I7``n4By`U&vSP*y_g zd>G;}sSc_wDO-L(czu}`xN7$H!10gLJKMW~Au5!z&81~U}^EOBu3)(i% zIkwA#vSUaHLoD( zs`x1AO}b~&+>b*`R(VnxMUyPVfimEm5%qL6?BjQ)Y@52ca-&$wB70l$JuXqE%Igu7 zU8YLTZn!9v1rOzthb`G}fIx@nM^qZ=U%m6){hckUNHYIoxMt`&2R0WB(u?izf9SA1 ztR_g@cBm;Y32Ov4emT+rW$U1Xq1i>bNU<7?Mk<`-o2^6s^m?Fr0J@QY#kV1Ndd!jh?^W+{b-BEq=~7^;@*3%m6su&sn~;wD5)&9`1frf9^}0V!e1_f zzT~M^?MfDGuYLAUNRB`ls0J^I8z*8_q+SeJYL&UOgM|`(HHCG@O6R@}l!70T{_WI7 zYnApExc`BN61j#^;zD6ARe(A<9;)LGV&EE46rd6!^KVw~#85p0QQPg;UzI4ivEY)a zny?8CI+lKBX)#wzW*g9XTrkxJuR5S!Ao<_V-`%S z+hfl&OI@yw(GTv?I&D>45L9( zl<<-uC|e~b;+|nrqx&zRwcwD3J|a_Eox5(pDRQ&~;S*o%|CDdQOkZhSG=kESHPXi z*-BGTM?&_gFb4TH=P+BfaQ|Z*;4;*drme*>%&Sr)^@pWhmAQE2nF+c*oqvg(9e7Gw z&l$+fW1~d&k#MHL;maXFJNdta7J*XCM4gGb<|FuGX1)Kaq6P4qv5}+*znq=;Z(q#> z12)9iR%_t@Rn%VV3y+(_hZ>I3iGDsHT+|KdmZ;Cr9mj)8)#^XXy(q{2p3K+{gQy;JM$Sc~@<;rJt zb!XwiPz_n>#`{mc*L`5y>_W)Ru*%}avKpAf|9_K@$f^UVTL{FA8tzL3%@+No6foQ+ zvQMdG^N+#90^{BYm*@T0FolPrb2-)%=-VTGQP(9|rrsdR}dRc+wFycrueWggCt}xT7fT6_{C!=Tedn`pA0l=loc>Y{Zfbe&qDGtE?@DOl<<7fQ z*}b@3oyLo06)@x01YF6NBSQd(^ewJ6$cH7Uj+tcRs2w+Z>JO7+s`GGa+2${sAhuC# z(##iP8i2hT;;UTZKbs0hP6sJ2==*D$P)MqL1GUOd#9M!&ezmdp0=sV{Ekco_lh`;h3)zL{5I@^|cui_b!gfkWTMi zYBMwo?Dp9fNEI1**RN1Jn=Gw?sh;VRDY!W0LSt`GRdRsg{nKZkE8vu6U{9~f*)b9^ z0tBqvZYIG~x%qd5g&5;|ypd3=tdy*}rV02-kE(#n11GP^mwI?9T&74iZMP(Mx}%+n ztT}cw--y~X8bUOob28@YqYi7uft8O@3Oj}zlZRZxtYTLMJtng;v1Wsc(>S(+E?b)XNge8-72KAmAOZ0HvY8t#RiOf{YKiiIQp05n=kfgDD!WgoT zYL4CcYDex->qf9c)B9QSbdAxC551)J@uo?fS00&$eF%3a#ZeXTuemnA(Fz*{q)$vd zR@4cyBt2v`%Yo;E&DHp4nWc9}`r>#cecrTu$5wJn;e6U4PSU}0D z_V7(3&qhv^_tfycclD$iQTcddqyip8v~z z;!%#j;726S11qYRatqrUDSs;mo(rjwoLo<8 zUJ$n@b1vd&(d&1a{OJs~FZ9acVNLf`^!Wi^H1z%{K-K~wn40>Xvsc;sUOcFTE^Ke>|T5h{S(Q|uOSvo(8wiqKrH$sHCQx|Y7vz7)Q z&{kDqp5D!C!g={pWxt6G=nS|JI{rycTi2Hd0iZK{l>>aY=p-~rNtKfbrrMVL@;@h)kO#N(#dd$KEMBM{Sru*C z?aXev$ept}+?ufom_bebQGLLK;flfG8h6#$l-hM#S#Uhq>)p|7f4^WP)=`zUv!Cfj zw}tXLg;4+9Q|n(%DH0i-ZH4ye#RcM>Q>6Dk&qeVzn;(^^pCosHja~10crU5}1vhMfY!?Mfxs}A>HOl z$4T-jpDR~d?#7TuN7HOQhCyq&nBB<-jb44qem|d}Q&hZT7r3Klfz&oa8<&u(vZ~5W z!u{2D(lR5D_bgu_w|$37(9O&8=ZITHn~V62V$l-;jlCtL@~K!nH2&J+(vqLqWFkvr zud^bLHREjBG%`%Qbho?V`I=lRtjWE&|7EF+Pd>|A!mNVg%`X+zaw!v}FI8?161>pN zcifa4`*96sK#5qVM-}dm5>4zAO;T!5PI+y$AF2B{zK%BG1g9SiU)t#SMoY0_;$xtb zf&j!Jj*o0ZB~s=wuvR@?r$kCtaaoAE1UJlgk-E@qzbu|t@f28aT+w=r|5e-ka}Uvx zw1G57mb^!s{vA6886g8`V@~z7S8#SU`A%9Nj*lNm)?(`NtW4|D*);8P`Ec^>8EQ>* zt=_Xd!~Qqv9L=0*Zm<2hCgfWJC3KP<@V1isCS;$Z=-gw>^pwdpm6ZOqYQqvNM+#l# z*0dt6ef@b*T&%V(#c1m^JfP8~puvfDz?kDd_oPFUa|*xY3c1N#$C0`<(bf8R2!)xx zG`qzs3Ypy%*biOKQDKC!o96o$j9O*6(Iyb3c3$aNWu}-a&FKQpFZD#fMVD}hK99W( z6o=^+!Z+{%_9#W#={$2Iw5Ec-_Nmya&J9(X2)Hi};LW}ksG}f*Fcjd94$LuptPp{S z+ZXi;dH0@>)?HJ8nF8sv7fRiP53r1k8#Z<@cm+2Td30tn%e>C!rO}B{>UP}r-HUDf z*x*jfqF$K|96D80R)~I$nu5Kcbg?U&)ui65Wm!jRM10GrP{VDR*_aZn)>7761Pj0% zJ;s5vJ?rN5ITJ(l4XGGGc@r7Ify<^N!6WSCx;^aM&B>bo`9<}n6H9cEqbriVH#m1w Ootl!iVuieA@P7dL@|vOm literal 0 HcmV?d00001 diff --git a/src/assets/zodiac/rat.png b/src/assets/zodiac/rat.png new file mode 100644 index 0000000000000000000000000000000000000000..af26694e89c29981caeef4a35374cbdfbd8cb3f6 GIT binary patch literal 9365 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 OfQE{;a^*8{#D4%GJ{WBP literal 0 HcmV?d00001 diff --git a/src/assets/zodiac/rooster.png b/src/assets/zodiac/rooster.png new file mode 100644 index 0000000000000000000000000000000000000000..172b57c90e8bcf68be90d4a74e243775c4023ec1 GIT binary patch literal 9046 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 n;eBY@WkdJ>rk-cT?N2a view { position: absolute; left: 12px; bottom: 0; width: 9px; height: 14px; border-radius: 5px 5px 0 0; background: #fff; } +.app-person-symbol { width: 52px; height: 48px; position: relative; flex: none; } +.app-person-head { position: absolute; left: 50%; top: 1px; width: 19px; height: 19px; border-radius: 50%; background: currentColor; transform: translateX(-50%); } +.app-person-body { position: absolute; left: 4px; bottom: 0; width: 44px; height: 24px; border-radius: 23px 23px 7px 7px; background: currentColor; } +// 共用48px图标占位,放大图标只向上延伸,不挤压或裁切下方文字。 +.app-realm-symbol { position: relative; width: 116px; height: 48px; flex: none; } +.app-spirit-frame { position: absolute; left: 0; bottom: 0; width: 116px; height: 116px; padding: 9px; border: 2px solid #fff; box-sizing: border-box; border-radius: 50%; background: linear-gradient(145deg,#fff,#edf3ff); box-shadow: 0 7px 20px rgba(137,110,160,.12); } +.app-spirit-image { display: block; width: 100%; height: 100%; border-radius: 50%; } diff --git a/src/components/AppTabBar.tsx b/src/components/AppTabBar.tsx new file mode 100644 index 0000000..02126df --- /dev/null +++ b/src/components/AppTabBar.tsx @@ -0,0 +1,27 @@ +import Taro from '@tarojs/taro' +import { Button, Image, Text, View } from '@tarojs/components' +import spirit from '../assets/home/spirit.png' +import './AppTabBar.scss' + +export function AppTabBar({ active }: { active: 'home' | 'my' }) { + const navigate = (page: 'home' | 'my') => { + if (page === active) return + const url = `/pages/${page}/index` + if (process.env.TARO_ENV === 'weapp') Taro.switchTab({ url }) + else Taro.redirectTo({ url }) + } + return + + + + +} diff --git a/src/components/RadarChart.scss b/src/components/RadarChart.scss index 70111c2..39cc802 100644 --- a/src/components/RadarChart.scss +++ b/src/components/RadarChart.scss @@ -1,81 +1,31 @@ -.radar { - position: relative; - width: 520px; - height: 470px; - margin: 22px auto 42px; -} - -.radar-web, -.radar-fill { +.radar { position: relative; width: 100%; height: 490px; margin: 0 auto; } +.radar-plot { position: absolute; width: 66%; height: 360px; left: 17%; top: 75px; } +.radar-ring, .radar-ring-inner, .radar-fill { position: absolute; - left: 110px; - top: 58px; - width: 300px; - height: 300px; - clip-path: polygon(50% 0, 98% 36%, 80% 98%, 20% 98%, 2% 36%); -} - -.radar-web { - border: 2px solid rgba(255, 219, 117, 0.5); - background: rgba(255, 237, 184, 0.18); -} - -.web-1 { - transform: scale(1); -} - -.web-2 { - transform: scale(0.68); -} - -.web-3 { - transform: scale(0.36); -} - -.radar-fill { - background: #13cce9; - opacity: 0.95; -} - -.radar-label { - position: absolute; - display: flex; - flex-direction: column; - align-items: center; - font-weight: 700; -} - -.radar-name { - font-size: 34px; -} - -.radar-value { - margin-top: 8px; - font-size: 22px; -} - -.radar-label-0 { - left: 50%; - top: 0; - transform: translateX(-50%); -} - -.radar-label-1 { - right: 0; - top: 150px; -} - -.radar-label-2 { - right: 50px; - bottom: 12px; -} - -.radar-label-3 { - left: 48px; - bottom: 12px; -} - -.radar-label-4 { - left: 0; - top: 150px; + inset: 0; + clip-path: polygon(50% 4%, 93.75% 35.79%, 77.04% 87.21%, 22.96% 87.21%, 6.25% 35.79%); } +.radar-ring { background: #decac6; } +.radar-ring-inner { inset: 2px; background: #fff2e9; } +.radar-ring:nth-child(even) .radar-ring-inner { background: #fff9f1; } +.radar-axis { position: absolute; left: 50%; top: 50%; width: 46%; border-top: 2px dashed rgba(171,151,151,.35); transform-origin: left center; } +.radar-fill { background: rgba(255,143,201,.72); } +.radar-dot { position: absolute; width: 9px; height: 9px; border: 2px solid rgba(255,255,255,.5); border-radius: 50%; transform: translate(-50%,-50%); } +.radar-label { position: absolute; display: flex; flex-direction: column; align-items: center; gap: 6px; font-weight: 700; } +.radar-name-row { display: flex; align-items: center; gap: 6px; } +.radar-name { font-size: 32px; line-height: 40px; } +.radar-value { min-width: 64px; height: 28px; padding: 0 8px; box-sizing: border-box; border-radius: 20px; color: #fff; font-size: 21px; font-weight: 500; line-height: 28px; text-align: center; } +.radar-label-0 { left: 50%; top: 0; transform: translateX(-50%); } +.radar-label-1 { right: 2%; top: 177px; } +.radar-label-2 { right: 20%; bottom: 0; } +.radar-label-3 { left: 20%; bottom: 0; } +.radar-label-4 { left: 2%; top: 177px; } +.element-mark { position: relative; width: 28px; height: 30px; border-radius: 11px 13px 10px 12px; background: currentColor; box-shadow: inset 5px 5px 8px rgba(255,255,255,.35); } +.mark-1 { border-radius: 8px 8px 16px 16px; height: 23px; } +.mark-2 { border-radius: 70% 35% 65% 40%; transform: rotate(25deg); } +.mark-3 { border-radius: 90% 12% 75% 30%; } +.mark-4 { border-radius: 70% 15% 60% 45%; transform: rotate(-12deg); } +.mark-eye { position: absolute; top: 12px; width: 3px; height: 4px; border-radius: 50%; background: rgba(49,44,65,.65); } +.mark-eye.left { left: 8px; } +.mark-eye.right { right: 8px; } +.mark-smile { position: absolute; left: 11px; top: 17px; width: 6px; height: 3px; border-bottom: 2px solid rgba(49,44,65,.55); border-radius: 50%; } diff --git a/src/components/RadarChart.tsx b/src/components/RadarChart.tsx index 84ae494..ed3c760 100644 --- a/src/components/RadarChart.tsx +++ b/src/components/RadarChart.tsx @@ -2,45 +2,52 @@ import { View, Text } from '@tarojs/components' import { ElementScore } from '../services/request' import './RadarChart.scss' -type Props = { - scores: ElementScore[] -} - -const positions = [ - { left: 50, top: 3 }, - { left: 86, top: 35 }, - { left: 72, top: 84 }, - { left: 28, top: 84 }, - { left: 14, top: 35 } -] - -const elementMarks: Record = { - 土: '●', 金: '✦', 水: '●', 木: '●', 火: '●' -} +type Props = { scores: ElementScore[] } +const order = ['土', '金', '水', '木', '火'] +const colors = ['#b87338', '#dca823', '#42b7e4', '#55b56a', '#ef6777'] +const points = order.map((_, index) => { + const angle = (-90 + index * 72) * Math.PI / 180 + return { x: 50 + Math.cos(angle) * 46, y: 50 + Math.sin(angle) * 46 } +}) export function RadarChart({ scores }: Props) { - const polygon = scores.map((score, index) => { - const point = positions[index] - const scale = Math.max(score.value, 4) / 100 - const x = 50 + (point.left - 50) * scale - const y = 50 + (point.top - 50) * scale - return `${x}% ${y}%` - }).join(', ') + const values = order.map((name, index) => ({ + name, + value: Math.max(0, Math.min(100, scores.find((score) => score.name === name)?.value || 0)), + color: colors[index] + })) + const maximum = Math.max(50, ...values.map((score) => score.value)) + const dataPoints = values.map((score, index) => ({ + x: 50 + (points[index].x - 50) * score.value / maximum, + y: 50 + (points[index].y - 50) * score.value / maximum + })) + const polygon = dataPoints.map(({ x, y }) => `${x}% ${y}%`).join(', ') return ( - - - - - {scores.map((score, index) => ( - - {elementMarks[score.name]} {score.name} - {score.value}% + + {[1, 0.8, 0.6, 0.4, 0.2].map((scale) => ( + + + + ))} + {points.map((_, index) => ( + + ))} + + {dataPoints.map((point, index) => ( + + ))} + + {values.map((score, index) => ( + + + + + + {score.name} + + {score.value}% ))} diff --git a/src/components/ZodiacMascot.scss b/src/components/ZodiacMascot.scss new file mode 100644 index 0000000..1124486 --- /dev/null +++ b/src/components/ZodiacMascot.scss @@ -0,0 +1,3 @@ +.zodiac-mascot { display: block; width: 86px; height: 86px; flex: none; } +.zodiac-mascot-empty { color: #8d7d9c; font-size: 22px; line-height: 1.4; } +.zodiac-large .zodiac-mascot { width: 148px; height: 148px; } diff --git a/src/components/ZodiacMascot.tsx b/src/components/ZodiacMascot.tsx new file mode 100644 index 0000000..52bdac8 --- /dev/null +++ b/src/components/ZodiacMascot.tsx @@ -0,0 +1,26 @@ +import { Image, Text } from '@tarojs/components' +import type { ZodiacName } from '../utils/zodiac' +import rat from '../assets/zodiac/rat.png' +import ox from '../assets/zodiac/ox.png' +import tiger from '../assets/zodiac/tiger.png' +import rabbit from '../assets/zodiac/rabbit.png' +import dragon from '../assets/zodiac/dragon.png' +import snake from '../assets/zodiac/snake.png' +import horse from '../assets/zodiac/horse.png' +import goat from '../assets/zodiac/goat.png' +import monkey from '../assets/zodiac/monkey.png' +import rooster from '../assets/zodiac/rooster.png' +import dog from '../assets/zodiac/dog.png' +import pig from '../assets/zodiac/pig.png' +import './ZodiacMascot.scss' + +const icons: Record = { + 鼠: rat, 牛: ox, 虎: tiger, 兔: rabbit, 龙: dragon, 蛇: snake, + 马: horse, 羊: goat, 猴: monkey, 鸡: rooster, 狗: dog, 猪: pig +} + +export function ZodiacMascot({ zodiac }: { zodiac: ZodiacName | null }) { + return zodiac + ? + : 待完善 +} diff --git a/src/index.html b/src/index.html new file mode 100644 index 0000000..076c420 --- /dev/null +++ b/src/index.html @@ -0,0 +1,13 @@ + + + + + + + Hera 前端预览 + + + +

+ + diff --git a/src/pages/agreement/index.scss b/src/pages/agreement/index.scss index b35a822..4f582bb 100644 --- a/src/pages/agreement/index.scss +++ b/src/pages/agreement/index.scss @@ -1,51 +1,154 @@ .agreement-page { - color: #222; - padding-left: 30px; - padding-right: 30px; + width: 100%; + max-width: 750px; + min-height: 100vh; + margin: 0 auto; + padding: calc(132px + env(safe-area-inset-top)) 32px calc(36px + env(safe-area-inset-bottom)); + box-sizing: border-box; + color: #28243a; + background: + radial-gradient(circle at 16% 5%, rgba(180, 155, 255, 0.62), transparent 31%), + linear-gradient(180deg, #c8b7ff 0%, #e8e2ff 34%, #f0f5ff 70%, #edf5ff 100%); + overflow: hidden; } -.tabs { - margin-top: 210px; - display: flex; - justify-content: space-around; +.agreement-page .nav { + left: 50%; + right: auto; + width: 100%; + max-width: 750px; + height: calc(106px + env(safe-area-inset-top)); + padding-bottom: 20px; + transform: translateX(-50%); } -.tab { +.agreement-page .nav-title { + color: #27213f; + font-size: 38px; + font-weight: 800; +} + +.agreement-page .back { + color: #30294b; +} + +.agreement-tabs { position: relative; - color: #8f640d; - font-size: 34px; - font-weight: 700; - padding-bottom: 18px; + z-index: 1; + width: 100%; + height: 84px; + padding: 6px; + border: 2px solid rgba(255, 255, 255, 0.68); + border-radius: 46px; + background: rgba(255, 255, 255, 0.48); + box-shadow: 0 10px 28px rgba(95, 76, 139, 0.08); + display: flex; + box-sizing: border-box; + overflow: hidden; } -.current::after { - content: ''; +.tab-indicator { position: absolute; - left: 32px; - right: 32px; - bottom: 0; - height: 8px; - border-radius: 4px; - background: #8f640d; + left: 6px; + top: 6px; + width: calc(50% - 6px); + height: 68px; + border-radius: 38px; + background: linear-gradient(135deg, #7862dc 0%, #9279ed 100%); + box-shadow: 0 8px 18px rgba(102, 78, 193, 0.24); + transition: transform 220ms cubic-bezier(0.22, 0.72, 0.22, 1); } -.article { - height: calc(100vh - 350px); - margin-top: 42px; +.agreement-tabs.privacy-active .tab-indicator { + transform: translateX(100%); +} + +.agreement-tab { + position: relative; + z-index: 2; + width: 50%; + height: 68px; + flex: none; + color: #59516f; + font-size: 30px; + font-weight: 700; + line-height: 68px; + text-align: center; + transition: color 180ms ease; +} + +.agreement-tab + .agreement-tab { + margin-top: 0; +} + +.agreement-tab.current { + color: #fff; +} + +.agreement-article { + height: calc(100vh - 252px - env(safe-area-inset-top) - env(safe-area-inset-bottom)); + margin-top: 28px; + border: 2px solid rgba(255, 255, 255, 0.72); + border-radius: 28px; + background: rgba(255, 255, 255, 0.82); + box-shadow: 0 16px 38px rgba(85, 72, 119, 0.08); + box-sizing: border-box; + overflow: hidden; +} + +.article-inner { + min-height: 100%; + padding: 38px 34px 56px; + box-sizing: border-box; + animation: article-enter 230ms cubic-bezier(0.22, 0.72, 0.22, 1); } .article-title { display: block; - color: #252525; + margin-bottom: 30px; + color: #28213f; font-size: 40px; font-weight: 800; - margin-bottom: 26px; + line-height: 1.35; + text-align: center; } .paragraph { display: block; - color: #2f2f2f; - font-size: 30px; - line-height: 1.95; - margin-bottom: 28px; + margin-bottom: 26px; + color: #4c465c; + font-size: 28px; + line-height: 1.9; + text-align: justify; +} + +.paragraph:last-child { + margin-bottom: 0; +} + +@keyframes article-enter { + from { + opacity: 0; + transform: translateY(10px); + } + + to { + opacity: 1; + transform: translateY(0); + } +} + +@media screen and (max-height: 700px) { + .agreement-page { + padding-top: calc(112px + env(safe-area-inset-top)); + } + + .agreement-article { + height: calc(100vh - 222px - env(safe-area-inset-top) - env(safe-area-inset-bottom)); + margin-top: 22px; + } + + .article-inner { + padding-top: 30px; + } } diff --git a/src/pages/agreement/index.tsx b/src/pages/agreement/index.tsx index 56e593b..9fcb362 100644 --- a/src/pages/agreement/index.tsx +++ b/src/pages/agreement/index.tsx @@ -4,30 +4,46 @@ import { NavBar } from '../../components/NavBar' import { api } from '../../services/request' import './index.scss' +type AgreementType = 'user' | 'privacy' + const sampleUser = '为使用小程序软件服务(以下简称“本服务”),您应当阅读并遵守《小程序软件注册协议》以及专项规则等。请您务必审慎阅读、充分理解各条款内容,特别是免除或限制责任的相应条款。' const samplePrivacy = '欢迎使用那吉。本隐私政策旨在向您说明我们收集、使用、存储、披露个人信息的方式、范围及您享有的相关权利,确保您在充分知情的前提下自愿使用本应用。' export default function AgreementPage() { - const [active, setActive] = useState<'user' | 'privacy'>('user') - const [body, setBody] = useState(sampleUser) + const [active, setActive] = useState('user') + const [content, setContent] = useState>({ + user: sampleUser, + privacy: samplePrivacy + }) useEffect(() => { - api.agreement(active).then((res) => setBody(res.body)).catch(() => setBody(active === 'user' ? sampleUser : samplePrivacy)) + let cancelled = false + api.agreement(active) + .then((res) => { + if (!cancelled) setContent((current) => ({ ...current, [active]: res.body })) + }) + .catch(() => undefined) + return () => { + cancelled = true + } }, [active]) return ( - + - - - + + + + - - {active === 'user' ? '用户协议' : '一、引言'} - {body} - 一、协议的范围{'\n'}1.1 本协议是您与那吉之间关于使用那吉软件服务所订立的协议。所有规则均为本协议不可分割的一部分,与协议正文具有同等法律效力。 - 二、适用范围{'\n'}本政策适用于您通过本应用进行的所有操作及我们因此收集的个人信息,涵盖注册、登录、使用功能、参与互动等场景。 - 三、个人信息的收集与使用{'\n'}我们遵循合法、正当、必要原则,仅收集为实现服务功能所必需的信息。 + + + {active === 'user' ? '用户协议' : '隐私政策'} + {content[active]} + 一、协议的范围{'\n'}1.1 本协议是您与那吉之间关于使用那吉软件服务所订立的协议。所有规则均为本协议不可分割的一部分,与协议正文具有同等法律效力。 + 二、适用范围{'\n'}本政策适用于您通过本应用进行的所有操作及我们因此收集的个人信息,涵盖注册、登录、使用功能、参与互动等场景。 + 三、个人信息的收集与使用{'\n'}我们遵循合法、正当、必要原则,仅收集为实现服务功能所必需的信息。 + ) diff --git a/src/pages/home/index.scss b/src/pages/home/index.scss index 6b8289f..3b9ad1f 100644 --- a/src/pages/home/index.scss +++ b/src/pages/home/index.scss @@ -1,602 +1,99 @@ .home-page { - min-height: 100vh; - padding: calc(216px + env(safe-area-inset-top)) 30px calc(178px + env(safe-area-inset-bottom)); - box-sizing: border-box; - color: #29243a; - background: - linear-gradient(180deg, rgba(154, 124, 255, 0.92) 0%, rgba(220, 201, 255, 0.76) 27%, rgba(253, 241, 255, 0.9) 52%, #eef6ff 100%); - overflow-x: hidden; -} - -.day-switch { - display: flex; - align-items: center; - gap: 52px; -} - -.avatar-orb { - width: 132px; - height: 132px; - flex: none; - border-radius: 70px; - background: #fffef0; - display: flex; - align-items: center; - justify-content: center; - box-shadow: 0 12px 26px rgba(119, 102, 154, 0.12); -} - -.water-face { - width: 82px; - height: 96px; - border-radius: 50% 50% 52% 52%; - background: linear-gradient(180deg, #9ff5ff 0%, #39c6ea 100%); - color: #3274c8; - font-size: 42px; - line-height: 78px; - text-align: center; -} - -.day-tabs { - flex: 1; - display: grid; - grid-template-columns: repeat(3, 1fr); - align-items: center; -} - -.day-tab { - min-width: 0; - text-align: center; - color: rgba(42, 34, 62, 0.58); - position: relative; -} - -.day-tab + .day-tab::before { - content: ''; - position: absolute; - left: -2px; - top: 20px; - width: 2px; - height: 12px; - background: rgba(42, 34, 62, 0.4); -} - -.day-label, -.day-status { - display: block; -} - -.day-label { - font-size: 36px; - line-height: 1.2; -} - -.day-status { - width: 112px; - height: 48px; - margin: 12px auto 0; - border-radius: 26px; - font-size: 28px; - line-height: 48px; -} - -.day-tab.active { - color: #29243a; - font-weight: 900; -} - -.day-tab.active .day-label { - font-size: 46px; -} - -.day-tab.active .day-status { - background: #7956f4; - color: #fff; - box-shadow: 0 8px 18px rgba(105, 71, 220, 0.26); -} - -.date-row { - margin-top: 52px; - color: #4f485f; - font-size: 28px; - display: flex; - align-items: center; - justify-content: space-between; -} - -.month-day { - font-size: 34px; - font-weight: 900; -} - -.summary-card { - min-height: 202px; - margin-top: 38px; - border-radius: 18px; - background: linear-gradient(105deg, #7139f3 0%, #8344ff 54%, #d35af3 100%); - color: #fff; - padding: 42px 34px; - box-sizing: border-box; - display: flex; - align-items: center; - justify-content: space-between; - overflow: hidden; - position: relative; -} - -.summary-card::after { - content: ''; - position: absolute; - right: -22px; - top: -36px; - width: 236px; - height: 236px; - border-radius: 50%; - background: radial-gradient(circle, rgba(131, 226, 255, 0.95) 0%, rgba(61, 121, 250, 0.72) 50%, rgba(255, 255, 255, 0) 70%); - filter: blur(1px); -} - -.summary-copy { - width: 420px; - font-size: 34px; - line-height: 1.75; - font-weight: 800; - position: relative; - z-index: 1; -} - -.index-orb { - width: 178px; - height: 178px; - border-radius: 96px; - background: radial-gradient(circle at 45% 36%, #e8ffff 0%, #86dfff 42%, #5a71ff 100%); - color: #fff; - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - box-shadow: 0 0 0 12px rgba(255, 255, 255, 0.22); - position: relative; - z-index: 1; -} - -.index-number { - font-size: 72px; - line-height: 0.95; - font-weight: 900; -} - -.index-orb text:last-child { - margin-top: 10px; - font-size: 24px; -} - -.lucky-grid-home { - margin-top: 24px; - display: grid; - grid-template-columns: 1.35fr 0.75fr; - gap: 22px; -} - -.lucky-box { - min-height: 90px; - border-radius: 18px; - padding: 0 28px; - background: rgba(255, 255, 255, 0.52); - display: flex; - align-items: center; - box-sizing: border-box; - gap: 18px; -} - -.colors-box { - background: rgba(246, 233, 255, 0.72); -} - -.number-box { - background: rgba(234, 225, 255, 0.72); -} - -.direction-box { - background: rgba(255, 241, 198, 0.82); -} - -.hour-box { - background: rgba(196, 235, 255, 0.82); -} - -.lucky-label { - flex: none; - color: #29243a; - font-size: 30px; - font-weight: 900; -} - -.color-chip, -.hour-chip { - display: flex; - align-items: center; - gap: 10px; - color: #423a52; - font-size: 28px; - white-space: nowrap; -} - -.swatch { - width: 48px; - height: 48px; - border-radius: 12px; -} - -.number-slots { - display: flex; - gap: 12px; -} - -.number-slots text { - width: 48px; - height: 58px; - border-radius: 10px; - background: linear-gradient(180deg, #8f75ff, #7454ef); - color: #fff; - font-size: 48px; - line-height: 58px; - text-align: center; - font-weight: 900; - box-shadow: inset 0 -12px 0 rgba(255, 255, 255, 0.18); -} - -.compass-icon { - width: 42px; - height: 42px; - border-radius: 50%; - background: #fff; - color: #ff9f27; - font-size: 30px; - line-height: 42px; - text-align: center; -} - -.hour-chip text:first-child { - width: 42px; - height: 42px; - border-radius: 22px; - background: #5bb8df; - color: #fff; - text-align: center; - line-height: 42px; - font-weight: 900; -} - -.dimension-head { - margin-top: 46px; - display: flex; - align-items: center; - justify-content: space-between; -} - -.dimension-head > text { - color: #29243a; - font-size: 42px; - font-weight: 900; -} - -.dimension-head button { - color: #6d6578; - font-size: 28px; -} - -.dimension-list { - margin-top: 28px; - display: flex; - flex-direction: column; - gap: 22px; -} - -.dimension-card { - min-height: 204px; - border-radius: 18px; - background: rgba(255, 255, 255, 0.84); - padding: 26px 60px 28px 34px; - box-sizing: border-box; - display: flex; - align-items: flex-start; - position: relative; - box-shadow: 0 8px 22px rgba(90, 79, 116, 0.06); -} - -.dimension-card.suitable { - background: rgba(255, 255, 255, 0.86); -} - -.dimension-card.avoid { - background: linear-gradient(180deg, rgba(255, 249, 236, 0.9) 0%, rgba(255, 255, 255, 0.86) 48%); -} - -.dimension-icon { - width: 62px; - height: 62px; - flex: none; - margin-right: 20px; - border-radius: 18px; - position: relative; -} - -.icon-heart { - background: radial-gradient(circle at 32% 32%, #ffd2df, #ff79a3 68%, #fff 70%); - transform: rotate(-10deg); -} - -.icon-gourd { - background: radial-gradient(circle at 50% 28%, #ffc65c 0 28%, transparent 29%), radial-gradient(circle at 50% 65%, #f0a222 0 48%, transparent 49%); -} - -.icon-vase { - background: radial-gradient(circle at 50% 18%, #d5fff0 0 24%, transparent 25%), linear-gradient(180deg, #7df0c9, #2ccda0); - border-radius: 30px 30px 16px 16px; -} - -.icon-coin { - border-radius: 50%; - background: radial-gradient(circle, #fff8bb 0 33%, #f1b82d 34% 100%); -} - -.icon-fan { - border-radius: 50% 50% 12px 12px; - background: conic-gradient(from 235deg, #c29cff, #fff, #8e63ef, #c29cff); -} - -.icon-scroll { - border-radius: 12px; - background: repeating-linear-gradient(90deg, #ffe8aa 0 10px, #f5c868 11px 16px); -} - -.icon-bamboo { - background: linear-gradient(135deg, transparent 20%, #30d3b9 21% 38%, transparent 39% 50%, #25bfa8 51% 68%, transparent 69%); -} - -.icon-horse { - border-radius: 50% 28px 50% 30px; - background: linear-gradient(135deg, #dbe9ff, #6b94f8); -} - -.dimension-copy { - flex: 1; - min-width: 0; -} - -.dimension-title-row { - display: flex; - align-items: center; - gap: 20px; -} - -.dimension-title { - color: #29243a; - font-size: 34px; - font-weight: 900; - white-space: nowrap; -} - -.dimension-headline { - min-width: 0; - color: #5d5667; - font-size: 28px; - line-height: 1.3; - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; -} - -.dimension-detail { - display: block; - margin-top: 30px; - color: #666071; - font-size: 28px; - line-height: 1.7; -} - -.dimension-tag { - position: absolute; - right: 34px; - top: 30px; - width: 48px; - height: 48px; - border-radius: 50%; - color: #fff; - font-size: 28px; - line-height: 48px; - text-align: center; - font-weight: 900; -} - -.dimension-tag.suitable { - background: #4bc660; -} - -.dimension-tag.avoid { - background: #f45b72; -} - -.dimension-arrow { - position: absolute; - right: 34px; - bottom: 30px; - color: #3f394a; - font-size: 52px; - line-height: 1; -} - -.home-tabbar { - position: fixed; - left: 0; - right: 0; - bottom: 0; - z-index: 12; - height: calc(158px + env(safe-area-inset-bottom)); - padding-bottom: env(safe-area-inset-bottom); - border-radius: 26px 26px 0 0; - background: rgba(255, 255, 255, 0.96); - box-shadow: 0 -10px 32px rgba(85, 79, 110, 0.1); - display: flex; - align-items: center; - justify-content: space-around; - box-sizing: border-box; -} - -.home-tabbar-item, -.home-realm-tab { - width: 150px; - height: 132px; - color: #29243a; - font-size: 28px; - font-weight: 900; - line-height: 1.1; - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - gap: 12px; -} - -.home-tabbar-item.active { - color: #ff9b2a; -} - -.home-tab-icon { - width: 42px; - height: 36px; - border-radius: 0 0 18px 18px; - background: currentColor; - position: relative; -} - -.home-tab-icon::before { - content: ''; - position: absolute; - left: 5px; - top: -22px; - width: 32px; - height: 32px; - border-radius: 18px 18px 10px 10px; - background: currentColor; -} - -.home-mine-icon { - width: 48px; - height: 32px; - border-radius: 24px 24px 14px 14px; - background: currentColor; - position: relative; -} - -.home-mine-icon::before { - content: ''; - position: absolute; - left: 13px; - top: -26px; - width: 22px; - height: 22px; - border-radius: 50%; - background: currentColor; -} - -.home-realm-tab { - margin-top: -78px; -} - -.home-realm-avatar { - width: 112px; - height: 112px; - border-radius: 60px; - border: 12px solid #f0f7ff; - box-shadow: 0 10px 24px rgba(121, 129, 164, 0.16); -} - -.sort-page { - padding-top: calc(188px + env(safe-area-inset-top)); -} - -.sort-back { - position: fixed; - left: 30px; - top: calc(48px + env(safe-area-inset-top)); - z-index: 3; - width: 58px; - height: 58px; - color: #2d2549; - font-size: 72px; - line-height: 44px; -} - -.sort-title { - position: fixed; - left: 0; - right: 0; - top: calc(116px + env(safe-area-inset-top)); - z-index: 2; - color: #29243a; - font-size: 42px; - line-height: 1; - font-weight: 900; - text-align: center; -} - -.sort-hint-row { - display: flex; - align-items: center; - color: #6e6678; - font-size: 28px; -} - -.sort-handle-symbol { - margin: 0 16px; - color: #6e6678; - font-size: 42px; -} - -.sort-done { - margin-left: auto; - color: #29243a; - font-size: 30px; - font-weight: 900; -} - -.sort-list { - margin-top: 62px; - display: flex; - flex-direction: column; - gap: 12px; -} - -.sort-item { - height: 112px; - border-radius: 18px; - background: rgba(255, 255, 255, 0.7); - padding: 0 34px 0 38px; - box-sizing: border-box; - display: flex; - align-items: center; - justify-content: space-between; - color: #29243a; - font-size: 32px; - font-weight: 800; -} - -.sort-controls { - display: flex; - align-items: center; - gap: 14px; - color: #77717f; - font-size: 38px; -} - -.sort-controls button { - width: 44px; - height: 44px; - border-radius: 22px; - background: rgba(121, 86, 244, 0.1); - color: #6d57da; - font-size: 28px; - line-height: 44px; -} + position: relative; width: 100%; max-width: 750px; min-height: 100vh; margin: 0 auto; + padding: calc(182px + env(safe-area-inset-top)) 30px calc(210px + env(safe-area-inset-bottom)); + box-sizing: border-box; color: #2c263a; overflow-x: hidden; + background: linear-gradient(180deg,#9d81fb 0,#c6acfb 300px,#eddaff 660px,#f7edff 1120px,#f6f2ff 100%); +} +.home-preview-note { position: absolute; top: calc(110px + env(safe-area-inset-top)); left: 0; right: 0; color: rgba(60,41,104,.65); font-size: 22px; line-height: 1.5; text-align: center; } +.home-day-switch { display: flex; align-items: center; gap: 38px; padding: 0 16px; } +.home-avatar-orb { flex: none; width: 108px; height: 108px; border: 3px solid rgba(255,255,255,.75); border-radius: 50%; box-sizing: border-box; background: #fffef0; display: flex; align-items: center; justify-content: center; box-shadow: 0 10px 20px rgba(115,78,168,.1); overflow: hidden; } +.home-water-image { width: 86px; height: 86px; } +.home-avatar-image { width: 100%; height: 100%; border-radius: 50%; } +.home-day-tabs { display: flex; flex: 1; min-width: 0; align-items: center; } +.home-page .home-day-tab { flex: 1; min-width: 0; height: 108px; margin: 0; padding: 0; position: relative; display: flex; flex-direction: column; align-items: center; color: #6f568f; background: transparent; border: 0; font-weight: 500; } +.home-page .home-day-tab + .home-day-tab { margin-top: 0; } +.home-day-tab + .home-day-tab::before { content: ''; position: absolute; left: 0; top: 23px; width: 2px; height: 9px; border-radius: 2px; background: rgba(79,52,112,.3); } +.home-day-label { display: block; height: 58px; font-size: 35px; line-height: 58px; white-space: nowrap; } +.home-day-status { min-width: 96px; height: 40px; padding: 0 8px; box-sizing: border-box; margin-top: 6px; border-radius: 24px; font-size: 25px; line-height: 40px; color: #a17bb8; white-space: nowrap; } +.home-day-tab.active .home-day-label { color: #2e2340; font-size: 43px; font-weight: 800; } +.home-day-tab.active .home-day-status { color: #fff; background: linear-gradient(135deg,#9864fa,#8150ee); box-shadow: 0 5px 12px rgba(124,71,216,.13); font-weight: 700; } +.home-date-row { display: flex; flex-wrap: wrap; justify-content: space-between; align-items: baseline; gap: 8px 20px; margin: 38px 10px 28px; color: #5e486f; font-size: 25px; line-height: 1.5; } +.home-solar-date { display: flex; align-items: baseline; white-space: nowrap; } +.home-date-number { font-size: 38px; font-weight: 800; line-height: 1.1; } +.home-lunar-date { font-size: 24px; } +.home-summary-card { position: relative; min-height: 200px; padding: 28px; border-radius: 24px; display: flex; align-items: center; justify-content: space-between; gap: 18px; box-sizing: border-box; color: #fff; background: linear-gradient(115deg,#7841f6 0,#8749fc 50%,#c773ef 100%); box-shadow: 0 12px 24px rgba(139,81,211,.1); overflow: hidden; } +.home-summary-card::after { content: ''; position: absolute; right: -40px; top: -90px; width: 330px; height: 330px; border: 2px solid rgba(255,255,255,.15); border-radius: 50%; } +.home-summary-copy { position: relative; z-index: 1; flex: 1; min-width: 0; font-size: 28px; font-weight: 600; line-height: 1.8; letter-spacing: 1px; } +.home-index-halo { position: relative; z-index: 1; width: 174px; height: 174px; padding: 9px; border: 2px solid rgba(240,208,255,.4); border-radius: 50%; box-sizing: border-box; background: rgba(230,195,255,.16); box-shadow: 0 0 16px rgba(255,218,251,.3); flex: none; } +.home-index-orb { width: 100%; height: 100%; border-radius: 50%; display: flex; flex-direction: column; align-items: center; justify-content: center; background: radial-gradient(circle at 36% 25%,#b8f3ff 0,#77b7ec 28%,#547be3 61%,#96b6fc 87%,#d9d7ff 100%); box-shadow: inset 0 3px 9px rgba(255,255,255,.8),inset 0 -8px 16px rgba(64,81,187,.2); } +.home-index-number { font-size: 76px; font-weight: 800; line-height: 1; letter-spacing: -3px; } +.home-index-label { margin-top: 8px; font-size: 22px; line-height: 1.3; } +.home-summary-stars { position: absolute; inset: 0; pointer-events: none; } +.home-summary-stars > view { position: absolute; width: 6px; height: 6px; border-radius: 50%; background: rgba(255,240,255,.7); } +.home-summary-stars > view:nth-child(1) { top: 25px; left: 42px; } +.home-summary-stars > view:nth-child(2) { top: 35px; right: 15px; width: 4px; height: 4px; } +.home-summary-stars > view:nth-child(3) { bottom: 27px; right: 29px; width: 3px; height: 3px; } +.home-lucky-row { display: flex; gap: 20px; margin-top: 20px; } +.home-lucky-box { min-width: 0; min-height: 90px; padding: 18px 20px; box-sizing: border-box; border: 1px solid rgba(255,255,255,.3); border-radius: 22px; display: flex; align-items: center; gap: 16px; } +.home-colors-box { flex: 1.8; background: rgba(231,211,250,.68); } +.home-numbers-box { flex: 1; background: rgba(220,208,252,.72); } +.home-direction-box { flex: 1; background: linear-gradient(110deg,#ffe6bd,#fff0df); } +.home-hours-box { flex: 1.8; background: linear-gradient(110deg,#c2e7fa,#dfedff); } +.home-lucky-label { flex: none; font-size: 27px; font-weight: 800; white-space: nowrap; } +.home-color-list { display: flex; gap: 16px; min-width: 0; flex: 1; flex-wrap: wrap; } +.home-color-chip { display: flex; align-items: center; gap: 8px; white-space: nowrap; font-size: 25px; } +.home-swatch { width: 42px; height: 42px; flex: none; border-radius: 12px; border: 1px solid rgba(120,100,150,.06); box-sizing: border-box; } +.home-number-slots { display: flex; gap: 10px; } +.home-number-slot { position: relative; width: 43px; height: 52px; border-radius: 8px; color: #fff; background: linear-gradient(180deg,#9279ee 49%,#a18af1 50%); text-align: center; } +.home-number-slot > text { position: relative; z-index: 1; font-size: 43px; font-weight: 700; line-height: 52px; } +.home-number-slot::after { content: ''; position: absolute; top: 50%; left: 0; right: 0; height: 1px; background: rgba(92,65,152,.26); } +.home-compass { flex: none; width: 42px; height: 42px; border: 5px solid #f8d787; border-radius: 50%; background: #fff9eb; box-sizing: border-box; position: relative; } +.home-compass-needle { position: absolute; inset: 0; } +.home-compass-needle::before { content: ''; position: absolute; left: 10px; top: 3px; border-left: 5px solid transparent; border-right: 5px solid transparent; border-bottom: 14px solid #ee9b82; } +.home-compass-needle::after { content: ''; position: absolute; left: 10px; bottom: 3px; border-left: 5px solid transparent; border-right: 5px solid transparent; border-top: 14px solid #7eafdd; } +.home-direction-value { font-size: 25px; white-space: nowrap; } +.home-hours-list { display: flex; gap: 12px; flex-wrap: wrap; min-width: 0; } +.home-hour-chip { display: flex; align-items: center; gap: 5px; color: #39495c; font-size: 23px; white-space: nowrap; } +.home-hour-branch { width: 34px; height: 34px; border-radius: 50%; color: #fff; background: #72b8df; line-height: 34px; text-align: center; font-weight: 700; } +.home-no-hour { font-size: 22px; color: #7385a1; } +.home-dimension-head { display: flex; align-items: center; justify-content: space-between; margin-top: 42px; } +.home-dimension-head > text { flex: none; white-space: nowrap; font-size: 37px; font-weight: 800; letter-spacing: -1px; } +.home-dimension-head > button { width: auto; flex: none; margin: 0; display: flex; align-items: center; gap: 9px; color: #85738f; font-size: 25px; padding: 14px 0 14px 20px; } +.home-sort-symbol { width: 21px; height: 23px; position: relative; } +.home-sort-symbol > view { position: absolute; top: 3px; width: 3px; height: 16px; border-radius: 2px; background: currentColor; } +.home-sort-symbol > view:first-child { left: 5px; } +.home-sort-symbol > view:last-child { right: 5px; } +.home-sort-symbol > view:first-child::after { content: ''; position: absolute; top: 0; left: -3px; width: 6px; height: 6px; border-left: 2px solid currentColor; border-top: 2px solid currentColor; transform: rotate(45deg); } +.home-sort-symbol > view:last-child::after { content: ''; position: absolute; bottom: 0; left: -3px; width: 6px; height: 6px; border-right: 2px solid currentColor; border-bottom: 2px solid currentColor; transform: rotate(45deg); } +.home-dimension-list { display: flex; flex-direction: column; gap: 18px; margin-top: 26px; } +.home-dimension-card { min-height: 206px; padding: 20px 26px 28px; border: 2px solid rgba(255,255,255,.9); border-radius: 26px; box-sizing: border-box; background: linear-gradient(180deg,#fff8ec,#fff 65%); box-shadow: 0 7px 18px rgba(115,83,149,.025); } +.home-dimension-card.dimension-emotion { background: linear-gradient(180deg,#fff0f7,#fff 65%); } +.home-dimension-card.dimension-life { background: linear-gradient(180deg,#f3fff0,#fff 65%); } +.home-dimension-card.dimension-social { background: linear-gradient(180deg,#f6efff,#fff 65%); } +.home-dimension-card.dimension-career { background: linear-gradient(180deg,#effff9,#fff 65%); } +.home-dimension-card.dimension-travel { background: linear-gradient(180deg,#f0f7ff,#fff 65%); } +.home-dimension-title-row { display: flex; align-items: center; gap: 11px; min-width: 0; } +.home-dimension-icon { display: block; width: 56px; height: 56px; flex: none; } +.home-dimension-title { font-size: 33px; font-weight: 800; white-space: nowrap; } +.home-dimension-headline { min-width: 0; flex: 1; margin-left: 4px; font-size: 26px; line-height: 1.45; color: #665b6c; } +.home-dimension-tag { flex: none; width: 43px; height: 43px; border-radius: 50%; color: #fff; font-size: 25px; font-weight: 700; line-height: 43px; text-align: center; } +.home-dimension-tag.suitable { background: #6ac87d; } +.home-dimension-tag.avoid { background: #f17d8f; } +.home-dimension-detail { display: block; margin: 24px 1px 0; color: #77707d; font-size: 27px; line-height: 1.85; } +.home-entertainment-note { display: block; margin: 28px 12px 0; color: #b0a1bd; font-size: 21px; line-height: 1.7; text-align: center; } +.home-empty { display: flex; flex-direction: column; align-items: center; gap: 28px; padding: 90px 20px; color: #7d6593; font-size: 28px; line-height: 1.8; text-align: center; } +.home-empty-image { width: 120px; height: 120px; } +.home-empty button { padding: 22px 40px; border-radius: 40px; color: #fff; background: #9977e9; font-size: 28px; } +.home-sort-page { padding-top: calc(130px + env(safe-area-inset-top)); } +.home-sort-nav { display: flex; align-items: center; justify-content: space-between; gap: 20px; } +.home-sort-nav > text { flex: 1; text-align: center; white-space: nowrap; font-size: 36px; font-weight: 800; } +.home-sort-nav > button { width: auto; flex: none; min-width: 70px; margin: 0; font-size: 29px; color: #6e4e9c; line-height: 60px; } +.home-sort-nav > button:first-child { font-size: 64px; text-align: left; } +.home-sort-hint { display: block; margin: 24px 0; color: #8e7c9e; font-size: 25px; line-height: 1.8; } +.home-sort-list { display: flex; flex-direction: column; gap: 12px; } +.home-sort-item { min-height: 96px; display: flex; align-items: center; gap: 20px; padding: 18px 24px; border-radius: 22px; box-sizing: border-box; background: rgba(255,255,255,.75); font-size: 28px; color: #5c466d; } +.home-sort-icon { width: 48px; height: 48px; } +.home-sort-controls { display: flex; gap: 16px; margin-left: auto; } +.home-sort-controls > button { width: 46px; height: 46px; border-radius: 50%; font-size: 27px; color: #9174cc; background: rgba(175,144,223,.12); line-height: 46px; } +.home-sort-controls > button[disabled] { opacity: .3; } +@media screen and (max-height: 700px) { .home-page { padding-top: calc(148px + env(safe-area-inset-top)); } .home-preview-note { top: calc(98px + env(safe-area-inset-top)); } .home-sort-page { padding-top: calc(110px + env(safe-area-inset-top)); } } diff --git a/src/pages/home/index.tsx b/src/pages/home/index.tsx index cf5fa7e..0b8e45f 100644 --- a/src/pages/home/index.tsx +++ b/src/pages/home/index.tsx @@ -1,306 +1,147 @@ -import { useEffect, useMemo, useState } from 'react' -import Taro from '@tarojs/taro' +import { useEffect, useMemo, useRef, useState } from 'react' +import Taro, { useDidShow } from '@tarojs/taro' import { Button, Image, Text, View } from '@tarojs/components' -import avatarAsset from '../../assets/fortune/avatar.jpg' -import { api, DimensionItem, HomeOverview } from '../../services/request' +import { AppTabBar } from '../../components/AppTabBar' +import { api, resolveAssetUrl, UserProfile } from '../../services/request' +import { isFrontendPreview } from '../../services/frontendPreview' +import { generateHomeOverview, HOME_DIMENSION_IDS, normalizeDimensionOrder } from '../../utils/homeOverview' +import { getBeijingDate } from '../../utils/zodiacWeekly' +import water from '../../assets/home/water.png' +import heart from '../../assets/home/heart.png' +import gourd from '../../assets/home/gourd.png' +import vase from '../../assets/home/vase.png' +import coin from '../../assets/home/coin.png' +import fan from '../../assets/home/fan.png' +import scroll from '../../assets/home/scroll.png' +import bamboo from '../../assets/home/bamboo.png' +import horse from '../../assets/home/horse.png' import './index.scss' -type PageMode = 'home' | 'sort' - -const weekNames = ['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六'] - -const pad = (value: number) => `${value}`.padStart(2, '0') - -const formatDate = (date: Date) => `${date.getFullYear()}-${pad(date.getMonth() + 1)}-${pad(date.getDate())}` - -const createDate = (offset: number) => { - const date = new Date() - date.setDate(date.getDate() + offset) - return date -} - -const createMockHome = (): HomeOverview => { - const yesterday = createDate(-1) - const today = createDate(0) - const tomorrow = createDate(1) - - return { - activeDay: '今日', - days: [ - { - label: '昨日', - date: formatDate(yesterday), - weekName: weekNames[yesterday.getDay()], - lunarDate: '农历丙午年 九月初二', - status: '小逆' - }, - { - label: '今日', - date: formatDate(today), - weekName: weekNames[today.getDay()], - lunarDate: '农历丙午年 九月初三', - status: '小逆' - }, - { - label: '明日', - date: formatDate(tomorrow), - weekName: weekNames[tomorrow.getDay()], - lunarDate: '农历丙午年 九月初四', - status: '平日' - } - ], - summary: '小逆之日,少言多思,养精蓄锐为上。', - overallIndex: 42, - luckyColors: [ - { name: '绿茶色', value: '#a7ad2a' }, - { name: '瀑布蓝', value: '#50c3cf' } - ], - luckyNumbers: ['6', '8'], - luckyDirection: '东北', - luckyHours: [ - { branch: '子', time: '23-01点' }, - { branch: '申', time: '15-17点' } - ], - dimensions: [ - { - id: 'emotion', - title: '情感', - icon: 'heart', - headline: '默契收集,心流时刻', - detail: '适合捕捉和TA的默契瞬间,让这些小细节成为关系里的锚点。', - suitable: true - }, - { - id: 'health', - title: '健康', - icon: 'gourd', - headline: '润肺养身,舒缓秋燥', - detail: '秋日干燥适合润肺养身,舒缓身体的秋燥不适感。', - suitable: true - }, - { - id: 'life', - title: '生活', - icon: 'vase', - headline: '收纳旧物,沉淀回忆', - detail: '秋日里适合收纳旧物,在整理中沉淀那些温暖的小回忆。', - suitable: true - }, - { - id: 'wealth', - title: '财富', - icon: 'coin', - headline: '勿乱囤货,按需消费', - detail: '财富能量忌盲目囤积,适合避开非必要的批量采购,保持理性消费。', - suitable: false - }, - { - id: 'social', - title: '社交', - icon: 'fan', - headline: '勿涉纷争,保持中立', - detail: '易卷入人际是非,适合远离矛盾,保持中立姿态。', - suitable: false - }, - { - id: 'study', - title: '学业', - icon: 'scroll', - headline: '基础松散,学业忌跳级', - detail: '底层知识不牢,别急于学习进阶内容。', - suitable: false - }, - { - id: 'career', - title: '事业', - icon: 'bamboo', - headline: '敷衍了事,别凑活', - detail: '今日易因松散出错,适合认真对待每一项小任务,别敷衍。', - suitable: false - }, - { - id: 'travel', - title: '出行', - icon: 'horse', - headline: '勿负重行,轻装简从', - detail: '今日出行负重易生疲惫,建议轻装出门,避免带过多不必要的物品。', - suitable: false - } - ] - } -} - -const iconClass = (icon: string) => `dimension-icon icon-${icon}` +const icons: Record = { heart, gourd, vase, coin, fan, scroll, bamboo, horse } +const ORDER_KEY = 'home.dimension-order.v1' +const directionAngles: Record = { 正北: 0, 东北: 45, 正东: 90, 东南: 135, 正南: 180, 西南: 225, 正西: 270, 西北: 315 } export default function HomePage() { - const [overview, setOverview] = useState(createMockHome) - const [mode, setMode] = useState('home') - const [orderedIds, setOrderedIds] = useState([]) + const [profile, setProfile] = useState(null) + const [loading, setLoading] = useState(true) + const [loadFailed, setLoadFailed] = useState(false) + const [mode, setMode] = useState<'home' | 'sort'>('home') + const [today, setToday] = useState(() => getBeijingDate()) + const [dayOffset, setDayOffset] = useState<-1 | 0 | 1>(0) + const [orderedIds, setOrderedIds] = useState(HOME_DIMENSION_IDS) + const [avatarFailed, setAvatarFailed] = useState(false) + const requestSequence = useRef(0) + + const refreshProfile = () => { + setToday(getBeijingDate()) + setLoading(true) + setLoadFailed(false) + const sequence = ++requestSequence.current + api.profile().then((data) => { + if (sequence !== requestSequence.current) return + setProfile(data) + setAvatarFailed(false) + }).catch(() => { + if (sequence !== requestSequence.current) return + setProfile(null) + setLoadFailed(true) + }).finally(() => { + if (sequence === requestSequence.current) setLoading(false) + }) + try { setOrderedIds(normalizeDimensionOrder(Taro.getStorageSync(ORDER_KEY))) } catch { setOrderedIds([...HOME_DIMENSION_IDS]) } + } + useDidShow(refreshProfile) useEffect(() => { - api.homeOverview() - .then((data) => { - setOverview(data) - setOrderedIds(data.dimensions.map((item) => item.id)) - }) - .catch(() => { - const mock = createMockHome() - setOverview(mock) - setOrderedIds(mock.dimensions.map((item) => item.id)) - }) + let timer: ReturnType + const refreshDate = () => { + const now = new Date() + setToday(getBeijingDate(now)) + timer = setTimeout(refreshDate, 86400000 - ((now.getTime() + 28800000) % 86400000) + 100) + } + refreshDate() + return () => { clearTimeout(timer); requestSequence.current++ } }, []) - const activeDay = overview.days.find((day) => day.label === overview.activeDay) || overview.days[1] + const overview = useMemo(() => profile ? generateHomeOverview(profile, today, dayOffset) : null, [profile?.birthday, profile?.birthHour, today, dayOffset]) const orderedDimensions = useMemo(() => { - const byId = overview.dimensions.reduce>((result, item) => { - result[item.id] = item - return result - }, {}) - return orderedIds.map((id) => byId[id]).filter(Boolean) - }, [orderedIds, overview.dimensions]) + if (!overview) return [] + return orderedIds.map((id) => overview.dimensions.find((item) => item.id === id)).filter(Boolean) + }, [overview, orderedIds]) const moveDimension = (index: number, direction: -1 | 1) => { const target = index + direction if (target < 0 || target >= orderedIds.length) return const next = [...orderedIds] - const current = next[index] - next[index] = next[target] - next[target] = current + ;[next[index], next[target]] = [next[target], next[index]] setOrderedIds(next) } - - const go = (url: string) => Taro.redirectTo({ url }) - - const renderTabbar = () => ( - - - - 首页 - - - - - ) - - if (mode === 'sort') { - return ( - - - 排序 - - 按住右侧 - ☰ - 上下拖动排序 - - - - {orderedDimensions.map((item, index) => ( - - {item.title} - - - - ☰ - - - ))} - - {renderTabbar()} - - ) + const finishSorting = () => { + try { Taro.setStorageSync(ORDER_KEY, orderedIds); setMode('home') } + catch { Taro.showToast({ title: '排序保存失败,请重试', icon: 'none' }) } } - return ( - - - - ⌣ - - - {overview.days.map((day) => ( - - {day.label} - {day.status} - - ))} - + if (loading || !overview) { + return + + + {loading ? '正在准备你的每日参考…' : loadFailed ? '个人资料加载失败,请重试' : '请先完善有效的出生日期和时辰'} + {!loading && } - - - {Number(activeDay.date.slice(5, 7))}月{Number(activeDay.date.slice(8, 10))}日 {activeDay.weekName} - {activeDay.lunarDate} - - - - {overview.summary} - - {overview.overallIndex} - 综合指数 - - - - - - 吉色 - {overview.luckyColors.map((color) => ( - - - {color.name} - - ))} - - - 吉数 - - {overview.luckyNumbers.map((number) => {number})} - - - - 吉向 - ⌖ - {overview.luckyDirection} - - - 吉时 - {overview.luckyHours.map((hour) => ( - - {hour.branch} - {hour.time} - - ))} - - - - - 维度解析 - - - - - {orderedDimensions.map((item) => ( - - - - - {item.title} - {item.headline} - - {item.detail} - - - {item.suitable ? '宜' : '忌'} - - › - - ))} - - {renderTabbar()} + - ) + } + + if (mode === 'sort') { + return + + 维度排序 + + 点击上下箭头调整显示顺序,完成后保存在本机。 + {orderedDimensions.map((item, index) => + {item.title} + + + + + )} + + + } + + const activeDay = overview.days[dayOffset + 1] + return + {isFrontendPreview() && 前端预览 · 示例资料 · 不保存个人资料} + + setAvatarFailed(true)} /> + {overview.days.map((day, index) => )} + + + {Number(activeDay.date.slice(5, 7))}月{Number(activeDay.date.slice(8, 10))}日 {activeDay.weekName}{activeDay.lunarDate} + + + + {overview.summary} + {overview.overallIndex}综合指数 + + + + 吉色{overview.luckyColors.map((color) => {color.name})} + 吉数{overview.luckyNumbers.map((number) => {number})} + + + 吉向{overview.luckyDirection} + 吉时{overview.luckyHours.length ? overview.luckyHours.map((hour) => {hour.branch}{hour.time.replace(/:00/g, '')}) : 暂无参考时段} + + + 维度解析 + {orderedDimensions.map((item) => + {item.title}{item.headline}{item.suitable ? '宜' : '忌'} + {item.detail} + )} + 每日简化参考 · 仅作传统文化娱乐参考,不作为现实决策依据 + + } diff --git a/src/pages/my/index.scss b/src/pages/my/index.scss index 2c55a39..4aa919a 100644 --- a/src/pages/my/index.scss +++ b/src/pages/my/index.scss @@ -9,10 +9,22 @@ overflow-x: hidden; } +.frontend-preview-note { + position: absolute; + top: calc(100px + env(safe-area-inset-top)); + left: 0; + right: 0; + color: rgba(69, 49, 109, 0.65); + font-size: 22px; + line-height: 32px; + text-align: center; +} + .profile-area { display: flex; align-items: center; min-height: 140px; + cursor: pointer; } .profile-avatar-button { @@ -25,6 +37,13 @@ align-items: center; justify-content: center; box-shadow: 0 12px 26px rgba(119, 102, 154, 0.12); + overflow: hidden; +} + +.profile-avatar-image { + width: 100%; + height: 100%; + border-radius: 50%; } .water-avatar, @@ -436,22 +455,60 @@ display: flex; align-items: center; justify-content: center; - padding: 0 84px; + padding: 36px 60px; box-sizing: border-box; } .zodiac-modal { width: 100%; - min-height: 620px; + max-width: 650px; + min-height: 0; + height: calc(100vh - 150px - env(safe-area-inset-top) - env(safe-area-inset-bottom)); border-radius: 34px; background: linear-gradient(180deg, #fbf7ff 0%, #f7f2ff 100%); box-shadow: 0 28px 0 -14px rgba(193, 127, 255, 0.52), 26px 30px 0 -18px rgba(114, 160, 255, 0.46); display: flex; flex-direction: column; align-items: center; - padding: 80px 52px 54px; + padding: 80px 32px 28px; box-sizing: border-box; position: relative; + max-height: calc(100vh - 150px - env(safe-area-inset-top) - env(safe-area-inset-bottom)); + overflow: hidden; +} + +.zodiac-scroll { width: 100%; height: 0; min-height: 0; flex: 1; margin-top: 18px; } +.zodiac-body { display: flex; flex-direction: column; align-items: center; padding: 0 10px 8px; box-sizing: border-box; } +.zodiac-body > * { flex-shrink: 0; } +.zodiac-body .zodiac-large { margin-top: 16px; } +.zodiac-title { flex: none; } +.zodiac-week-range { margin-top: 18px; font-size: 23px; color: #8c7b9f; text-align: center; } +.zodiac-status.positive { background: #d4efdd; color: #358259; } +.zodiac-status.neutral { background: #ece3fa; color: #806399; } +.zodiac-status.cautious { background: #ffe4d6; color: #b97a4e; } +.zodiac-date-guide { width: 100%; margin-top: 24px; padding: 22px; border: 2px solid rgba(255,255,255,.8); border-radius: 20px; background: rgba(255,255,255,.65); box-sizing: border-box; font-size: 24px; line-height: 1.8; color: #72647e; } +.zodiac-date-guide > view { display: flex; align-items: flex-start; gap: 16px; } +.zodiac-date-guide > view + view { margin-top: 16px; } +.guide-label { flex: none; font-weight: 700; } +.guide-label.supportive { color: #56a476; } +.guide-label.cautious { color: #c58a62; } +.zodiac-rules-toggle { width: 100%; margin: 22px 0 0; color: #9574bb; font-size: 24px; line-height: 44px; } +.zodiac-rules { width: 100%; padding: 22px; box-sizing: border-box; border-radius: 20px; background: rgba(237,228,249,.65); } +.zodiac-rule-copy { display: block; color: #93849f; font-size: 22px; line-height: 1.8; } +.zodiac-rule-copy + .zodiac-rule-copy { margin-top: 12px; } +.zodiac-day { display: flex; align-items: center; justify-content: space-between; gap: 8px; padding: 14px 0; border-bottom: 1px solid rgba(199,182,217,.4); font-size: 23px; line-height: 1.5; color: #928599; } +.zodiac-day.supportive { color: #53916d; } +.zodiac-day.cautious { color: #bb815f; } +.zodiac-week-note { margin-top: 20px; color: #a297ad; font-size: 21px; line-height: 1.7; text-align: center; } +.zodiac-modal .zodiac-confirm { flex: none; margin-top: 24px; } + +.zodiac-modal .lucky-flower { + top: 18px; + left: 50%; + width: 48px; + height: 48px; + font-size: 24px; + transform: translateX(-50%); } .lucky-flower { @@ -476,6 +533,10 @@ font-weight: 900; } +.zodiac-animal-name { margin-top: 22px; font-size: 34px; font-weight: 800; color: #4f3d70; } +.zodiac-calendar-note { margin-top: 10px; color: #9b8bad; font-size: 23px; line-height: 1.5; text-align: center; } +.zodiac-edit { margin-top: 24px; color: #8465c9; font-size: 28px; line-height: 1.5; } + .zodiac-large { margin-top: 46px; color: #5b4539; @@ -519,7 +580,11 @@ } .element-detail { - padding-top: calc(104px + env(safe-area-inset-top)); + width: 100%; + max-width: 750px; + margin: 0 auto; + padding: calc(130px + env(safe-area-inset-top)) 30px calc(220px + env(safe-area-inset-bottom)); + background: linear-gradient(180deg, #b4a1fc 0%, #e2d4fc 28%, #eee8ff 51%, #edf5ff 100%); } .element-back { @@ -535,32 +600,32 @@ } .element-radar { - margin-top: 52px; + margin: 0 0 44px; } .element-radar .radar { - margin-bottom: 40px; + margin-bottom: 0; } .element-radar .radar-fill { - background: #ff8fc9; - opacity: 0.72; + background: rgba(255, 143, 201, 0.72); } .element-card { - margin-top: 26px; - border-radius: 18px; - padding: 30px 28px 36px; - background: rgba(255, 255, 255, 0.72); + margin-top: 20px; + border-radius: 26px; + padding: 24px 22px 34px; + border: 2px solid rgba(255,255,255,0.45); + background: linear-gradient(145deg, rgba(255,248,241,0.78), rgba(255,255,255,0.58)); box-sizing: border-box; } .favorable-card { - background: rgba(242, 255, 248, 0.8); + background: linear-gradient(160deg, rgba(231,255,242,0.85), rgba(255,255,255,0.58)); } .avoid-card { - background: rgba(255, 247, 249, 0.78); + background: linear-gradient(160deg, rgba(255,234,241,0.8), rgba(255,255,255,0.58)); } .element-title-row { @@ -620,6 +685,24 @@ font-weight: 900; } +.strength-summary { + display: flex; + flex-direction: column; + gap: 12px; + margin-top: 26px; + padding: 20px; + border-radius: 18px; + color: #65528e; + background: rgba(232, 220, 255, 0.45); + font-size: 26px; + line-height: 1.6; +} +.pillars-summary { font-size: 23px; color: #7b708e; } +.strength-factors { display: flex; flex-direction: column; gap: 14px; margin-top: 24px; color: #71677f; font-size: 25px; line-height: 1.7; } +.element-method-note { display: block; margin: 28px 10px 0; color: #81778e; font-size: 22px; line-height: 1.7; } +.element-empty { display: flex; flex-direction: column; gap: 30px; padding: 100px 30px; color: #65528e; font-size: 28px; line-height: 1.8; text-align: center; } +.element-empty button { padding: 22px; border-radius: 40px; color: #fff; background: #9279ed; font-size: 28px; } + .green-text { color: #49bb68; font-weight: 900; @@ -629,3 +712,850 @@ color: #ef5b80; font-weight: 900; } + +/* “我的”首页视觉重构:所有图标均由稳定的 CSS 图形组成,避免依赖字体字形。 */ +.my-home { + width: 100%; + max-width: 750px; + margin: 0 auto; + padding: calc(182px + env(safe-area-inset-top)) 30px calc(196px + env(safe-area-inset-bottom)); + background: + radial-gradient(circle at 75% 8%, rgba(226, 204, 255, 0.76), transparent 31%), + linear-gradient(180deg, #9e83f5 0%, #cbbaf7 23%, #e8e9f9 43%, #edf4ff 63%, #eaf3ff 100%); +} + +.my-home .profile-area { + min-height: 146px; + padding: 0 8px; +} + +.my-home .profile-avatar-button { + width: 136px; + height: 136px; + border: 4px solid rgba(255, 255, 255, 0.78); + background: rgba(255, 255, 235, 0.98); + box-shadow: 0 14px 34px rgba(92, 69, 147, 0.14); + box-sizing: border-box; +} + +.water-mascot { + position: relative; + width: 84px; + height: 100px; + flex: none; +} + +.water-mascot::before { + content: ''; + position: absolute; + left: 7px; + top: 18px; + width: 70px; + height: 70px; + border-radius: 70% 43% 66% 44%; + background: linear-gradient(145deg, #a9f8ff 4%, #53d8f2 54%, #28bce7 100%); + box-shadow: + inset 10px 10px 18px rgba(255, 255, 255, 0.36), + 0 8px 14px rgba(43, 171, 218, 0.18); + transform: rotate(45deg); +} + +.water-highlight { + position: absolute; + z-index: 1; + left: 22px; + top: 28px; + width: 15px; + height: 24px; + border-radius: 50%; + background: rgba(255, 255, 255, 0.32); + transform: rotate(24deg); +} + +.water-eye { + position: absolute; + z-index: 2; + top: 61px; + width: 7px; + height: 10px; + border-radius: 50%; + background: #3464c7; +} + +.water-eye.left { left: 30px; } +.water-eye.right { right: 29px; } + +.water-smile { + position: absolute; + z-index: 2; + left: 34px; + top: 70px; + width: 18px; + height: 10px; + border: 3px solid #3464c7; + border-top: 0; + border-radius: 0 0 16px 16px; + box-sizing: border-box; +} + +.water-mascot.compact { + transform: scale(0.78); +} + +.my-home .profile-info { + margin-left: 30px; +} + +.my-home .profile-name { + max-width: 306px; + color: #242035; + font-size: 42px; + font-weight: 800; + letter-spacing: -1px; +} + +.my-home .gender-chip { + width: 42px; + height: 42px; + background: linear-gradient(145deg, #71d6ff, #3cbcf3); + font-size: 29px; + box-shadow: 0 5px 10px rgba(61, 183, 235, 0.22); +} + +.my-home .birthday-row { + margin-top: 20px; + gap: 11px; + color: #625a78; + font-size: 27px; + font-weight: 500; +} + +.birthday-value { + width: 178px; + flex: none; + font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace; + font-size: 27px; + font-variant-numeric: tabular-nums; + line-height: 32px; + letter-spacing: 1px; + white-space: nowrap; + text-align: left; +} + +.birthday-icon { + position: relative; + width: 30px; + height: 27px; + flex: none; +} + +.cake-candle { + position: absolute; + top: 6px; + width: 2px; + height: 7px; + border-radius: 2px; + background: currentColor; +} + +.cake-candle.left { left: 7px; } +.cake-candle.middle { left: 14px; } +.cake-candle.right { left: 21px; } + +.cake-candle::before { + content: ''; + position: absolute; + top: -5px; + left: -0.5px; + width: 3px; + height: 4px; + border-radius: 70% 30% 65% 35%; + background: currentColor; +} + +.cake-body { + position: absolute; + left: 2px; + bottom: 2px; + width: 26px; + height: 13px; + border: 2px solid currentColor; + border-radius: 3px 3px 2px 2px; + box-sizing: border-box; +} + +.cake-icing { + position: absolute; + top: 1px; + left: 0; + right: 0; + height: 3px; + border-bottom: 2px solid currentColor; + border-radius: 0 0 50% 50%; +} + +.cake-plate { + position: absolute; + left: 0; + bottom: 0; + width: 30px; + height: 2px; + border-radius: 2px; + background: currentColor; +} + +.birthday-visibility { + width: 46px; + height: 40px; + flex: none; + margin: -10px -8px -10px -3px; + border-radius: 22px; + display: flex; + align-items: center; + justify-content: center; + cursor: pointer; +} + +.birthday-visibility:active { + background: rgba(105, 88, 148, 0.1); +} + +.my-home .eye-line { + position: relative; + width: 34px; + height: 18px; + flex: none; + border: 0; + border-bottom: 4px solid #7b6845; + border-radius: 0 0 50% 50%; + transform: translateY(-3px); +} + +.birthday-visibility.open .eye-line { + height: 22px; + border: 3px solid #7b6845; + border-radius: 50%; + transform: none; + box-sizing: border-box; +} + +.eye-pupil { + position: absolute; + left: 50%; + top: 50%; + width: 8px; + height: 8px; + border-radius: 50%; + background: #7b6845; + transform: translate(-50%, -50%); +} + +.eye-lash { + position: absolute; + bottom: -7px; + width: 3px; + height: 8px; + border-radius: 3px; + background: #7b6845; +} + +.eye-lash.left { left: 2px; transform: rotate(35deg); } +.eye-lash.right { right: 2px; transform: rotate(-35deg); } + +.my-home .profile-arrow { + width: 42px; + color: rgba(48, 40, 72, 0.38); + font-size: 50px; + font-weight: 300; + text-align: right; +} + +.my-home .quick-card { + min-height: 194px; + margin-top: 48px; + padding: 25px 40px; + gap: 56px; + border: 2px solid rgba(255, 255, 255, 0.48); + border-radius: 28px; + background: rgba(255, 255, 255, 0.72); + box-shadow: 0 18px 44px rgba(92, 72, 134, 0.08); + backdrop-filter: blur(16px); +} + +.my-home .quick-entry { + width: 142px; + height: 142px; + flex: none; + color: #29243a; + font-size: 29px; + font-weight: 500; + gap: 14px; + line-height: 1; + justify-content: flex-start; + box-sizing: border-box; +} + +.my-home .quick-entry + .quick-entry { + margin-top: 0 !important; +} + +.my-home .quick-entry > text { + width: 100%; + height: 34px; + line-height: 34px; + text-align: center; +} + +.quick-icon { + position: relative; + width: 94px; + height: 94px; + border-radius: 50%; + background: linear-gradient(145deg, #f2ebff, #e8ddff); + box-shadow: + inset 0 2px 0 rgba(255, 255, 255, 0.68), + 0 9px 20px rgba(121, 91, 172, 0.13); + display: flex; + align-items: center; + justify-content: center; + box-sizing: border-box; +} + +.my-home .zodiac-icon, +.my-home .element-icon { + width: 94px; + height: 94px; + color: inherit; + font-size: inherit; + line-height: inherit; + background: linear-gradient(145deg, #f2ebff, #e8ddff); +} + +.my-home .element-icon .water-mascot.compact { + transform: translateY(-4px) scale(0.78); +} + +.rabbit-mascot { + position: relative; + width: 62px; + height: 76px; +} + +.rabbit-ear { + position: absolute; + z-index: 1; + top: 0; + width: 20px; + height: 43px; + border: 3px solid #70513d; + border-radius: 50% 50% 42% 42%; + background: #fff8d8; + box-sizing: border-box; +} + +.rabbit-ear.left { left: 9px; transform: rotate(-5deg); } +.rabbit-ear.right { right: 9px; transform: rotate(5deg); } + +.rabbit-ear view { + position: absolute; + left: 50%; + top: 8px; + width: 7px; + height: 24px; + border-radius: 50%; + background: #ffbdc8; + transform: translateX(-50%); +} + +.rabbit-head { + position: absolute; + z-index: 2; + left: 3px; + bottom: 1px; + width: 56px; + height: 49px; + border: 3px solid #70513d; + border-radius: 46% 46% 42% 42%; + background: #fff8d8; + box-sizing: border-box; + box-shadow: inset 0 -5px 0 rgba(255, 225, 176, 0.42); +} + +.rabbit-eye { + position: absolute; + top: 22px; + width: 4px; + height: 5px; + border-radius: 50%; + background: #5d4337; +} + +.rabbit-eye.left { left: 15px; } +.rabbit-eye.right { right: 15px; } + +.rabbit-nose { + position: absolute; + left: 50%; + top: 28px; + width: 6px; + height: 5px; + border-radius: 50% 50% 70% 70%; + background: #f28ca6; + transform: translateX(-50%); +} + +.my-home .palace-section { + margin-top: 38px; + padding: 0 2px; +} + +.my-home .section-title-row { + gap: 11px; +} + +.my-home .section-title { + color: #252034; + font-size: 40px; + font-weight: 800; + letter-spacing: -1px; +} + +.my-home .collection-text { + color: #393347; + font-size: 27px; +} + +.my-home .collection-text text { + color: #e84a7d; +} + +.my-home .palace-placeholder { + width: 222px; + height: 300px; + margin-top: 25px; + padding: 16px 15px 18px; + border: 2px solid rgba(255, 218, 108, 0.72); + border-radius: 21px; + background: + radial-gradient(circle at 75% 18%, rgba(255, 251, 210, 0.9), transparent 34%), + linear-gradient(155deg, #ffd670 0%, #ffe49b 54%, #fff0b3 100%); + box-shadow: 0 15px 28px rgba(198, 151, 53, 0.18); +} + +.my-home .palace-copy { + width: 26px; + color: #7a4c16; + font-size: 23px; + line-height: 1.18; +} + +.my-home .palace-coin { + width: 160px; + height: 160px; + margin-top: -49px; + filter: saturate(1.04) contrast(1.02); +} + +.my-home .palace-name { + margin-top: 5px; + color: #72440e; + font-size: 28px; + font-weight: 800; +} + +.my-home .settings-card { + margin-top: 38px; + padding: 0 31px; + border: 2px solid rgba(255, 255, 255, 0.65); + border-radius: 28px; + background: rgba(255, 255, 255, 0.88); + box-shadow: 0 16px 36px rgba(85, 76, 111, 0.08); + backdrop-filter: blur(16px); +} + +.my-home .settings-row { + min-height: 108px; + gap: 25px; + color: #29243a; + font-size: 31px; + font-weight: 500; + border-bottom-color: rgba(215, 219, 232, 0.72); +} + +.my-home .menu-icon { + width: 48px; + height: 48px; + color: #332d4d; +} + +.my-home .headset-icon { + border: 0; + border-radius: 0; +} + +.my-home .headset-icon::before, +.my-home .headset-icon::after { + content: none; +} + +.headset-band { + position: absolute; + left: 5px; + top: 4px; + width: 38px; + height: 34px; + border: 4px solid currentColor; + border-bottom: 0; + border-radius: 24px 24px 0 0; + box-sizing: border-box; +} + +.headset-ear { + position: absolute; + top: 24px; + width: 9px; + height: 17px; + border: 4px solid currentColor; + border-radius: 8px; + box-sizing: border-box; + background: #fff; +} + +.headset-ear.left { left: 2px; } +.headset-ear.right { right: 2px; } + +.headset-mic { + position: absolute; + right: 8px; + bottom: 3px; + width: 14px; + height: 9px; + border-bottom: 4px solid currentColor; + border-radius: 0 0 10px 10px; + transform: rotate(-12deg); +} + +.my-home .star-icon { + border: 0; + border-radius: 0; + line-height: 1; +} + +.star-core { + position: absolute; + inset: 8px; + border: 4px solid currentColor; + border-radius: 12px; + transform: rotate(45deg); + box-sizing: border-box; +} + +.star-plus { + position: absolute; + z-index: 2; + left: 50%; + top: 50%; + width: 18px; + height: 4px; + border-radius: 4px; + background: currentColor; + transform: translate(-50%, -50%); +} + +.star-plus.vertical { + transform: translate(-50%, -50%) rotate(90deg); +} + +.my-home .agreement-icon { + border: 4px solid currentColor; + border-radius: 9px; +} + +.my-home .agreement-icon::before, +.my-home .agreement-icon::after { + content: none; +} + +.agreement-line { + position: absolute; + left: 9px; + height: 3px; + border-radius: 3px; + background: currentColor; +} + +.agreement-line.first { top: 13px; width: 24px; } +.agreement-line.second { top: 24px; width: 18px; } + +.agreement-check { + position: absolute; + right: -9px; + bottom: -9px; + width: 22px; + height: 22px; + border: 4px solid currentColor; + border-radius: 50%; + background: #fff; + box-sizing: border-box; +} + +.agreement-check::after { + content: ''; + position: absolute; + left: 5px; + top: 3px; + width: 6px; + height: 3px; + border-left: 3px solid currentColor; + border-bottom: 3px solid currentColor; + transform: rotate(-45deg); +} + +.my-home .row-arrow { + color: rgba(42, 36, 60, 0.4); + font-size: 48px; +} + +.my-page .my-tabbar { + left: 50%; + right: auto; + width: 100%; + max-width: 750px; + height: calc(158px + env(safe-area-inset-bottom)); + border: 2px solid rgba(255, 255, 255, 0.7); + border-bottom: 0; + border-radius: 30px 30px 0 0; + background: rgba(255, 255, 255, 0.96); + box-shadow: 0 -13px 34px rgba(74, 70, 102, 0.1); + transform: translateX(-50%); + backdrop-filter: blur(18px); +} + +.my-page .my-tabbar-item, +.my-page .realm-tab { + width: 150px; + height: 132px; + gap: 10px; + color: #2d2940; + font-size: 27px; + font-weight: 700; +} + +.my-page .my-tabbar-item.active { + color: #ff9a29; +} + +.my-page .home-tab-icon { + position: relative; + width: 48px; + height: 46px; + border-radius: 0; + background: transparent; +} + +.my-page .home-tab-icon::before { + content: none; +} + +.home-roof { + position: absolute; + left: 8px; + top: 2px; + width: 30px; + height: 30px; + border: 7px solid currentColor; + border-right: 0; + border-bottom: 0; + border-radius: 5px; + box-sizing: border-box; + transform: rotate(45deg); +} + +.home-body { + position: absolute; + left: 8px; + bottom: 1px; + width: 32px; + height: 27px; + border-radius: 3px 3px 7px 7px; + background: currentColor; +} + +.home-door { + position: absolute; + left: 12px; + bottom: 0; + width: 9px; + height: 14px; + border-radius: 5px 5px 0 0; + background: #fff; +} + +.my-page .mine-tab-icon { + position: relative; + width: 52px; + height: 48px; + border-radius: 0; + background: transparent; +} + +.my-page .mine-tab-icon::before { + content: none; +} + +.mine-head { + position: absolute; + left: 50%; + top: 1px; + width: 19px; + height: 19px; + border-radius: 50%; + background: currentColor; + transform: translateX(-50%); +} + +.mine-body { + position: absolute; + left: 4px; + bottom: 0; + width: 44px; + height: 24px; + border-radius: 23px 23px 7px 7px; + background: currentColor; +} + +.my-page .realm-tab { + margin-top: -76px; +} + +.realm-avatar-wrap { + width: 118px; + height: 118px; + padding: 9px; + border-radius: 50%; + background: linear-gradient(145deg, #fff, #e8f2ff); + box-shadow: 0 10px 26px rgba(104, 114, 157, 0.18); + box-sizing: border-box; +} + +.my-page .realm-avatar { + width: 100%; + height: 100%; + border: 0; + border-radius: 50%; + box-shadow: none; +} + +.realm-spirit { + position: relative; + width: 100%; + height: 100%; + overflow: hidden; + border-radius: 50%; + background: + radial-gradient(circle at 28% 30%, rgba(255, 255, 255, 0.96) 0 12%, transparent 13%), + linear-gradient(145deg, #fffaff 0%, #ffe9f5 52%, #e9efff 100%); +} + +.spirit-ear { + position: absolute; + z-index: 1; + top: 12px; + width: 34px; + height: 40px; + border-radius: 88% 18% 55% 44%; + background: linear-gradient(145deg, #fff 16%, #f6bddb 86%); + box-shadow: 0 3px 8px rgba(219, 124, 172, 0.18); +} + +.spirit-ear.left { left: 12px; transform: rotate(-24deg); } +.spirit-ear.right { right: 12px; transform: scaleX(-1) rotate(-24deg); } + +.spirit-ear view { + position: absolute; + left: 11px; + top: 7px; + width: 11px; + height: 23px; + border-radius: 80% 30% 60% 40%; + background: rgba(242, 113, 168, 0.54); +} + +.spirit-face { + position: absolute; + z-index: 2; + left: 12px; + right: 12px; + bottom: 9px; + height: 67px; + border-radius: 48% 48% 45% 45%; + background: + radial-gradient(circle at 50% 16%, rgba(255, 255, 255, 0.9), transparent 42%), + linear-gradient(180deg, #fffafd, #fce9f5); + box-shadow: inset 0 -7px 12px rgba(226, 190, 225, 0.24); +} + +.spirit-eye { + position: absolute; + top: 32px; + width: 18px; + height: 9px; + border-bottom: 4px solid #9f5c95; + border-radius: 0 0 50% 50%; + box-sizing: border-box; +} + +.spirit-eye.left { left: 10px; transform: rotate(8deg); } +.spirit-eye.right { right: 10px; transform: rotate(-8deg); } + +.spirit-nose { + position: absolute; + left: 50%; + top: 39px; + width: 8px; + height: 8px; + border-radius: 60% 60% 55% 55%; + background: #ee75a7; + transform: translateX(-50%) rotate(45deg); +} + +.spirit-cheek { + position: absolute; + top: 45px; + width: 14px; + height: 7px; + border-radius: 50%; + background: rgba(248, 134, 178, 0.3); +} + +.spirit-cheek.left { left: 6px; } +.spirit-cheek.right { right: 6px; } + +.zodiac-large { + width: 174px; + height: 174px; + flex: none; + margin-top: 32px; + border-radius: 50%; + background: linear-gradient(145deg, #f5edff, #e7dcff); + box-shadow: inset 0 2px 0 rgba(255, 255, 255, 0.72), 0 14px 26px rgba(121, 91, 172, 0.14); + display: flex; + align-items: center; + justify-content: center; +} + + +@media screen and (max-height: 720px) { + .my-home { + padding-top: calc(142px + env(safe-area-inset-top)); + } + + .my-home .quick-card { + margin-top: 34px; + } + + .my-home .palace-section, + .my-home .settings-card { + margin-top: 30px; + } +} diff --git a/src/pages/my/index.tsx b/src/pages/my/index.tsx index 96dfffe..ddc15e9 100644 --- a/src/pages/my/index.tsx +++ b/src/pages/my/index.tsx @@ -1,50 +1,23 @@ import { useEffect, useMemo, useState } from 'react' -import Taro from '@tarojs/taro' -import { Button, Image, Text, View } from '@tarojs/components' +import Taro, { useDidShow } from '@tarojs/taro' +import { Button, Image, ScrollView, Text, View } from '@tarojs/components' import { RadarChart } from '../../components/RadarChart' -import { api, UserProfile } from '../../services/request' -import avatarAsset from '../../assets/fortune/avatar.jpg' +import { AppTabBar } from '../../components/AppTabBar' +import { ZodiacMascot } from '../../components/ZodiacMascot' +import { api, resolveAssetUrl, UserProfile } from '../../services/request' import coinAsset from '../../assets/fortune/coin.jpg' import { calculateFiveElements } from '../../utils/fiveElements' +import { calculateZodiac } from '../../utils/zodiac' +import { calculateWeeklyZodiacFortune, getBeijingDate, ZODIAC_WEEKLY_RULES } from '../../utils/zodiacWeekly' +import { isFrontendPreview } from '../../services/frontendPreview' import './index.scss' type PageMode = 'home' | 'element' -const mockProfile: UserProfile = { - id: 1, - nickname: 'You', - gender: '男', - birthday: '1998-06-18', - birthHour: '辰时', - province: '河南省', - city: '洛阳市', - district: '老城区', - points: 120, - remainingEdits: 5, - elementReport: { - scores: [ - { name: '土', color: '#b46a18', value: 42 }, - { name: '金', color: '#d59a05', value: 22 }, - { name: '水', color: '#35bfe8', value: 8 }, - { name: '木', color: '#36b85b', value: 22 }, - { name: '火', color: '#ed3c43', value: 7 } - ], - favorable: '金水', - unfavorable: '木火土', - dayMaster: '壬' - } -} - -const formatMaskedBirthday = (birthday: string) => { +const formatBirthday = (birthday: string, visible: boolean) => { const [year, month, day] = birthday.split('-') if (!year || !month || !day) return '****_**_**' - return '****_**_**' -} - -const formatBirthday = (birthday: string) => { - const [year, month, day] = birthday.split('-') - if (!year || !month || !day) return '****_**_**' - return `${year}_${month}_${day}` + return visible ? `${year}_${month}_${day}` : '****_**_**' } const genderSymbol = (gender: string) => (gender === '女' ? '♀' : '♂') @@ -63,22 +36,68 @@ const traitText = (elements: string) => elements .filter(Boolean) .join('、') +const WaterMascot = ({ compact = false }: { compact?: boolean }) => ( + + + + + + +) + export default function MyPage() { - const [profile, setProfile] = useState(mockProfile) + const [profile, setProfile] = useState(null) + const [profileError, setProfileError] = useState(false) const [mode, setMode] = useState('home') const [zodiacOpen, setZodiacOpen] = useState(false) + const [zodiacRulesOpen, setZodiacRulesOpen] = useState(false) + const [beijingDate, setBeijingDate] = useState(() => getBeijingDate()) const [birthdayVisible, setBirthdayVisible] = useState(false) + const previewNote = isFrontendPreview() + ? 前端预览 · 示例资料 · 不保存修改 + : null - const elementReport = useMemo( - () => calculateFiveElements(profile.birthday, profile.birthHour), - [profile.birthday, profile.birthHour] + const zodiac = useMemo(() => calculateZodiac(profile?.birthday || ''), [profile?.birthday]) + const weeklyFortune = useMemo( + () => calculateWeeklyZodiacFortune(profile?.birthday || '', beijingDate), + [profile?.birthday, beijingDate] ) useEffect(() => { + if (!zodiacOpen) return + let timer: ReturnType + const refreshDate = () => { + const now = new Date() + setBeijingDate(getBeijingDate(now)) + const untilMidnight = 86400000 - ((now.getTime() + 28800000) % 86400000) + timer = setTimeout(refreshDate, untilMidnight + 100) + } + refreshDate() + return () => clearTimeout(timer) + }, [zodiacOpen]) + + const openZodiac = () => { + setBeijingDate(getBeijingDate()) + setZodiacRulesOpen(false) + setZodiacOpen(true) + } + + const elementReport = useMemo( + () => profile ? calculateFiveElements(profile.birthday, profile.birthHour) : null, + [profile?.birthday, profile?.birthHour] + ) + + const refreshProfile = () => { + setBeijingDate(getBeijingDate()) + setProfileError(false) api.profile() .then(setProfile) - .catch(() => setProfile(mockProfile)) - }, []) + .catch(() => { + setProfileError(true) + setProfile(null) + }) + } + useDidShow(refreshProfile) const go = (url: string) => Taro.navigateTo({ url }) @@ -87,25 +106,21 @@ export default function MyPage() { Taro.showToast({ title: '企业微信入口待配置', icon: 'none' }) } - const renderTabs = () => ( - - - - - - 我的 - - - ) + const renderTabs = () => - const renderElement = () => ( + const renderElement = () => !elementReport ? ( + {previewNote} + + + 请先完善有效的出生日期和时辰,再查看元素报告。 + + + {renderTabs()} + + ) : ( + + {previewNote} @@ -118,63 +133,111 @@ export default function MyPage() { 日主,即出生日期中的天干,其五行属性直接代表自身能量基础。 - 你适应力强,擅长在变化中寻找机会与路径。 + 你的日主为{elementReport.dayMaster}{elementReport.masterElement},对应的五行特质是{traitText(elementReport.masterElement)}。 + + 日主{elementReport.strength} · 综合评分 {elementReport.strengthScore}/100 + 四柱:{elementReport.pillars.join(' · ')} + + + 得令:{elementReport.analysis.season.description} + 得地:{elementReport.analysis.roots.description} + 得势:{elementReport.analysis.support.description} + 喜用 - {elementReport.favorable} + {elementReport.favorable || '暂无明显偏向'} 喜用,即更容易让事情进展顺、做得稳、发挥得好的行为方式。 + {'\n'}根据得令、得地、得势综合判断,作为平衡日主强弱的五行参考。 - 你更容易发挥{traitText(elementReport.favorable)}的优势,遇事能找到适合自己的节奏。 + {elementReport.strength === '相对平衡' + ? '当前日主相对平衡,不预设需要补充的五行,宜保持协调。' + : `日主${elementReport.strength},以${elementReport.strength === '偏弱' ? '生扶' : '泄耗制衡'}为参考方向。可关注${traitText(elementReport.favorable)}。`} 忌用 - {elementReport.unfavorable} + {elementReport.unfavorable || '暂无明显偏忌'} 忌用,即容易让你更累、更乱,或做了很多却效果不好的行为方式。 - 当{traitText(elementReport.unfavorable)}的能量偏旺时,适合放慢节奏,避免陷入无谓消耗。 + {elementReport.unfavorable + ? `日主${elementReport.strength}时,${elementReport.unfavorable}不宜继续偏增。可留意${traitText(elementReport.unfavorable)}失衡带来的消耗。` + : '当前不划分固定偏忌,避免单一五行过度偏增。'} + 普通扶抑简化参考算法 v1,仅作传统文化娱乐参考;不含从格、化气、合冲刑害及调候等特殊判断。按北京时间公历、节气月柱与零点换日计算;时辰以起始小时代表,不作真太阳时校正。 {renderTabs()} ) + if (!profile) { + return + {profileError ? '个人资料加载失败,请重试' : '个人资料加载中…'} + {profileError && } + {renderTabs()} + } + if (mode === 'element') { return renderElement() } return ( - - + {previewNote} + go('/pages/profile-edit/index')}> + + {profile.avatarUrl + ? + : } + {profile.nickname} {genderSymbol(profile.gender)} - + + + + + + + + + {formatBirthday(profile.birthday, birthdayVisible)} + { + event.stopPropagation() + setBirthdayVisible((visible) => !visible) + }} + > + + {birthdayVisible + ? + : ( + <> + + + + )} + + + - + › - @@ -193,17 +256,30 @@ export default function MyPage() { @@ -215,10 +291,42 @@ export default function MyPage() { setZodiacOpen(false)}> event.stopPropagation()}> 运 - 生肖周运 - ⌇ - 平稳 - 本周运势平稳,生活节奏舒缓,安心度日,享受静谧时光。 + {zodiac ? `${zodiac} · 生肖周运` : '我的生肖'} + + + + {weeklyFortune ? ( + <> + 属{zodiac} + 按农历出生年 · 春节换年 + {weeklyFortune.weekStart} — {weeklyFortune.weekEnd} + {weeklyFortune.status} + {weeklyFortune.summary} + + 助力日{weeklyFortune.supportiveDays.map((item) => `${item.label} ${item.weekday}`).join('、') || '本周无明显合助日'} + 留意日{weeklyFortune.cautiousDays.map((item) => `${item.label} ${item.weekday}`).join('、') || '本周无六冲、相害日'} + + + {zodiacRulesOpen && + {ZODIAC_WEEKLY_RULES} + 本周合计:{weeklyFortune.score > 0 ? '+' : ''}{weeklyFortune.score}。逐日与出生年支“{weeklyFortune.branch}”比较: + {weeklyFortune.days.map((item) => 0 ? 'supportive' : item.score < 0 ? 'cautious' : ''}`}> + {item.label} {item.weekday} + {item.branch}日 · {item.relation === '三合' ? '三合同组' : item.relation} + {item.score > 0 ? '+' : ''}{item.score} + )} + 三合仅取同组两支的助力关系,不代表三合成局;不纳入刑、破或完整八字。 + } + 按北京时间周一至周日计算 · 合冲简化规则 v1{ '\n' }仅作传统文化娱乐参考,不作为现实决策依据 + + ) : ( + <> + {zodiac ? '周运日期无法计算,请检查设备日期后重新打开。' : '请先完善有效的出生日期,再查看你的生肖。'} + {!zodiac && } + + )} + + diff --git a/src/pages/profile-edit/index.scss b/src/pages/profile-edit/index.scss index 444ac8e..3abfd03 100644 --- a/src/pages/profile-edit/index.scss +++ b/src/pages/profile-edit/index.scss @@ -1,113 +1,364 @@ .edit-page { + min-height: 100vh; + box-sizing: border-box; + color: #211c3a; + background: + radial-gradient(circle at 14% 12%, rgba(179, 154, 255, 0.72), transparent 34%), + linear-gradient(180deg, #c2afff 0%, #e4d8ff 36%, #edf4ff 70%, #edf5ff 100%); + overflow-x: hidden; +} + +.edit-page .nav { + height: calc(112px + env(safe-area-inset-top)); + padding: 0 32px 24px; + align-items: flex-end; +} + +.edit-page .nav-title { + color: #211c3a; + font-size: 40px; + font-weight: 800; +} + +.edit-page .back { + left: 34px; + bottom: 18px; + color: #292244; + font-size: 60px; +} + +.profile-loading { + padding-top: calc(280px + env(safe-area-inset-top)); + text-align: center; + color: rgba(33, 28, 58, 0.58); + font-size: 28px; +} + +.edit-content { + width: 100%; + max-width: 750px; + min-height: 100vh; + margin: 0 auto; + padding: calc(164px + env(safe-area-inset-top)) 64px calc(78px + env(safe-area-inset-bottom)); + box-sizing: border-box; display: flex; flex-direction: column; align-items: center; - padding-top: 210px; } -.edit-avatar { - width: 150px; - height: 150px; - border-radius: 88px; - background: #fbffd7; - color: #17c9ea; - font-size: 60px; +.avatar-button { + width: 280px; + height: 280px; + flex: none; + border-radius: 50%; + background: rgba(255, 255, 237, 0.94); + display: flex; + align-items: center; + justify-content: center; + position: relative; + overflow: visible; + box-shadow: 0 4px 12px rgba(102, 83, 151, 0.08); +} + +.avatar-image { + width: 100%; + height: 100%; + border-radius: 50%; +} + +.water-mascot { + width: 142px; + height: 178px; + position: relative; + border-radius: 70% 70% 56% 56% / 82% 82% 42% 42%; + background: linear-gradient(180deg, #a0f6ff 0%, #47d2ef 54%, #1fb7e4 100%); + box-shadow: inset 16px 10px 30px rgba(255, 255, 255, 0.28); +} + +.mascot-eye { + position: absolute; + top: 100px; + width: 10px; + height: 14px; + border-radius: 50%; + background: #3275ef; +} + +.mascot-eye.left { left: 48px; } +.mascot-eye.right { right: 48px; } + +.mascot-smile { + position: absolute; + left: 56px; + top: 116px; + width: 34px; + height: 22px; + border: 7px solid #3275ef; + border-top: 0; + border-radius: 0 0 28px 28px; + box-sizing: border-box; +} + +.avatar-add { + position: absolute; + right: 4px; + bottom: 4px; + width: 66px; + height: 66px; + border-radius: 50%; + background: linear-gradient(145deg, #ffb13b 0%, #ff8c1f 100%); + border: 5px solid rgba(255, 255, 255, 0.9); + box-sizing: border-box; + box-shadow: 0 7px 16px rgba(188, 100, 19, 0.24); +} + +.plus-line { + position: absolute; + left: 50%; + top: 50%; + width: 30px; + height: 6px; + border-radius: 6px; + background: #fff; + transform: translate(-50%, -50%); +} + +.plus-line.vertical { + transform: translate(-50%, -50%) rotate(90deg); +} + +.form-card { + width: 100%; + min-height: 94px; + border: 3px solid rgba(255, 255, 255, 0.72); + border-radius: 50px; + background: rgba(255, 255, 255, 0.68); + box-sizing: border-box; + display: flex; + align-items: center; + color: #28204e; +} + +.nickname-card { + margin-top: 58px; + padding: 0 30px; +} + +.field-label { + flex: none; + font-size: 30px; + font-weight: 800; +} + +.nickname-input { + height: 90px; + flex: 1; + min-width: 0; + margin-left: 36px; + color: #28204e; + font-size: 31px; + display: flex; + align-items: center; +} + +.nickname-input input { + height: 100%; + padding: 0; + line-height: 90px; + box-sizing: border-box; +} + +.nickname-count { + flex: none; + color: #746c9c; + font-size: 28px; +} + +.gender-row { + width: 100%; + margin: 34px 0; + display: flex; + justify-content: space-between; + gap: 76px; +} + +.gender-option { + height: 94px; + flex: 1; + border: 3px solid rgba(255, 255, 255, 0.7); + border-radius: 50px; + background: rgba(255, 255, 255, 0.66); + color: #332463; + font-size: 31px; + font-weight: 700; + display: flex; + align-items: center; + justify-content: center; + gap: 22px; +} + +.gender-option.active { + color: #fff; + background: linear-gradient(90deg, #65c8f9 0%, #51b8ef 100%); +} + +.gender-option + .gender-option { + margin-top: 0; +} + +.gender-symbol { + font-size: 52px; + font-weight: 500; + line-height: 1; +} + +.picker-card { + margin-bottom: 34px; + padding: 0 28px 0 31px; +} + +.form-picker { + width: 100%; + display: block; +} + +.field-value { + flex: 1; + min-width: 0; + margin-left: 36px; + font-size: 29px; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} + +.field-value.location { + font-size: 27px; +} + +.field-value.placeholder { + color: #8e88aa; +} + +.chevron { + flex: none; + margin-left: 14px; + font-size: 56px; + font-weight: 300; + line-height: 1; +} + +.save-button { + width: 456px; + height: 96px; + margin-top: 36px; + border-radius: 52px; + color: #fff; + background: #ff9828; + font-size: 34px; + font-weight: 800; + display: flex; + align-items: center; + justify-content: center; + box-shadow: 0 10px 20px rgba(222, 128, 32, 0.14); +} + +.save-button[disabled] { + opacity: 0.68; +} + +.edit-note { + margin-top: 28px; + color: #666275; + font-size: 27px; +} + +.edit-note text { + color: #f13d57; +} + +.avatar-mask { + position: fixed; + z-index: 30; + inset: 0; + background: rgba(21, 17, 39, 0.62); +} + +.avatar-sheet { + position: absolute; + left: 0; + right: 0; + bottom: 0; + padding-bottom: env(safe-area-inset-bottom); + border-radius: 28px 28px 0 0; + overflow: hidden; + background: #fff; +} + +.avatar-action { + width: 100%; + height: 118px; + border-bottom: 1px solid #eeeef2; + border-radius: 0; + color: #202020; + background: #fff; + font-size: 33px; display: flex; align-items: center; justify-content: center; position: relative; } -.edit-avatar text { - position: absolute; - right: -34px; - bottom: 34px; - font-size: 28px; - font-weight: 700; -} - -.name-pill { - width: 420px; - height: 76px; - margin-top: 56px; - border-radius: 40px; - background: #fff7de; - display: flex; - align-items: center; - padding: 0 30px; - gap: 20px; - box-sizing: border-box; - color: #8f640d; - font-size: 38px; -} - -.name-pill input { - flex: 1; - text-align: center; - color: #8f640d; -} - -.gender-row { - margin-top: 58px; - display: flex; - gap: 86px; -} - -.gender { - color: #8f640d; - font-size: 34px; - display: flex; +.wechat-avatar-action { + height: 154px; + flex-direction: column; gap: 12px; - align-items: center; } -.section-title { - margin-top: 58px; - font-size: 34px; - font-weight: 700; - color: #8f640d; +.wechat-avatar-preview { + width: 44px; + height: 44px; + border-radius: 6px; } -.date-row, -.region-row { - margin-top: 34px; - display: flex; - gap: 18px; +.sheet-gap { + height: 16px; + background: #f5f5f7; } -.date-part { - width: 150px; - display: flex; - align-items: center; - justify-content: center; - font-size: 32px; +.cancel-action { + height: 126px; + border-bottom: 0; } -.hour { - width: 360px; - margin-top: 30px; - display: flex; - align-items: center; - justify-content: center; - font-size: 32px; -} +@media screen and (max-height: 700px) { + .edit-content { + padding-top: calc(140px + env(safe-area-inset-top)); + } -.region-row .input-pill { - width: 176px; - display: flex; - align-items: center; - justify-content: center; - font-size: 26px; - padding: 0 12px; -} + .avatar-button { + width: 220px; + height: 220px; + } -.start-button { - width: 500px; - margin-top: 110px; -} + .water-mascot { + transform: scale(0.82); + } -.edit-note { - margin-top: 28px; - color: #4b2d1a; - font-size: 28px; + .nickname-card { + margin-top: 38px; + } + + .gender-row, + .picker-card { + margin-bottom: 24px; + } + + .gender-row { + margin-top: 24px; + } + + .save-button { + margin-top: 18px; + } } diff --git a/src/pages/profile-edit/index.tsx b/src/pages/profile-edit/index.tsx index 524c6eb..6291f19 100644 --- a/src/pages/profile-edit/index.tsx +++ b/src/pages/profile-edit/index.tsx @@ -1,74 +1,332 @@ import { useEffect, useState } from 'react' import Taro from '@tarojs/taro' -import { Button, Input, Picker, Text, View } from '@tarojs/components' +import { Button, Image, Input, Picker, Text, View } from '@tarojs/components' +import areaData from 'china-area-data' import { NavBar } from '../../components/NavBar' -import { api, UserProfile } from '../../services/request' +import { api, resolveAssetUrl, UserProfile } from '../../services/request' import './index.scss' -const hours = ['子时', '丑时', '寅时', '卯时', '辰时', '巳时', '午时', '未时', '申时', '酉时', '戌时', '亥时'] -const regions = [['河南省', '北京市', '上海市'], ['洛阳市', '郑州市', '北京市'], ['老城区', '涧西区', '西工区']] +const hours = [ + { name: '子时', range: '23:00-01:00' }, + { name: '丑时', range: '01:00-03:00' }, + { name: '寅时', range: '03:00-05:00' }, + { name: '卯时', range: '05:00-07:00' }, + { name: '辰时', range: '07:00-09:00' }, + { name: '巳时', range: '09:00-11:00' }, + { name: '午时', range: '11:00-13:00' }, + { name: '未时', range: '13:00-15:00' }, + { name: '申时', range: '15:00-17:00' }, + { name: '酉时', range: '17:00-19:00' }, + { name: '戌时', range: '19:00-21:00' }, + { name: '亥时', range: '21:00-23:00' } +] + +type EditableProfile = Pick +type RegionEntry = [string, string] + +const emptyForm: EditableProfile = { + nickname: '', + gender: '', + birthday: '', + birthHour: '', + province: '', + city: '', + district: '' +} + +const previewProfile: UserProfile = { + id: 0, + nickname: 'You', + gender: '男', + birthday: '1999-11-06', + birthHour: '戌时', + province: '河南省', + city: '洛阳市', + district: '洛龙区', + points: 0, + remainingEdits: 5, + elementReport: { scores: [], favorable: '', unfavorable: '', dayMaster: '' } +} + +const toEditableProfile = (data: UserProfile): EditableProfile => ({ + nickname: data.nickname, + gender: data.gender, + birthday: data.birthday, + birthHour: data.birthHour, + province: data.province, + city: data.city, + district: data.district +}) + +const regionEntries = (parentCode: string): RegionEntry[] => Object.entries(areaData[parentCode] || {}) + +const findCodeByName = (entries: RegionEntry[], name: string) => entries.find(([, label]) => label === name)?.[0] + +const findRegionCodes = (profile: Pick): string[] => { + const provinces = regionEntries('86') + const provinceCode = findCodeByName(provinces, profile.province) || provinces[0]?.[0] || '' + const cities = regionEntries(provinceCode) + const cityCode = findCodeByName(cities, profile.city) + || (profile.city === profile.province && cities.length === 1 ? cities[0]?.[0] : '') + || cities[0]?.[0] + || '' + const districts = regionEntries(cityCode) + const districtCode = findCodeByName(districts, profile.district) || districts[0]?.[0] || '' + return [provinceCode, cityCode, districtCode] +} + +const errorMessage = (error: unknown, fallback: string) => error instanceof Error ? error.message : fallback export default function ProfileEditPage() { - const [form, setForm] = useState>({}) + const [profile, setProfile] = useState(null) + const [form, setForm] = useState(emptyForm) + const [avatarPreview, setAvatarPreview] = useState('') + const [pendingAvatar, setPendingAvatar] = useState('') + const [regionCodes, setRegionCodes] = useState(findRegionCodes(previewProfile)) + const [avatarSheetOpen, setAvatarSheetOpen] = useState(false) + const [loading, setLoading] = useState(true) + const [saving, setSaving] = useState(false) useEffect(() => { - api.profile().then(setForm) + api.profile() + .then((data) => { + setProfile(data) + setForm(toEditableProfile(data)) + setRegionCodes(findRegionCodes(data)) + setAvatarPreview(resolveAssetUrl(data.avatarUrl)) + }) + .catch((error) => { + if (process.env.TARO_ENV === 'h5') { + setProfile(previewProfile) + setForm(toEditableProfile(previewProfile)) + setRegionCodes(findRegionCodes(previewProfile)) + return + } + Taro.showToast({ title: errorMessage(error, '个人信息加载失败'), icon: 'none' }) + }) + .finally(() => setLoading(false)) }, []) + const useAvatar = (filePath: string) => { + if (!filePath) return + setAvatarPreview(filePath) + setPendingAvatar(filePath) + setAvatarSheetOpen(false) + } + + const chooseFrom = async (sourceType: 'album' | 'camera') => { + try { + const result = await Taro.chooseMedia({ + count: 1, + mediaType: ['image'], + sourceType: [sourceType], + sizeType: ['compressed'] + }) + useAvatar(result.tempFiles[0]?.tempFilePath || '') + } catch (error) { + const message = errorMessage(error, '') + if (message && !message.toLowerCase().includes('cancel')) { + Taro.showToast({ title: '头像选择失败', icon: 'none' }) + } + } + } + + const handleWechatAvatar = (event: { detail: { avatarUrl: string } }) => { + useAvatar(event.detail.avatarUrl) + } + const save = async () => { - await api.updateProfile(form) - Taro.showToast({ title: '已开启吉运', icon: 'none' }) - Taro.navigateBack() + const nickname = form.nickname.trim() + if (!nickname) { + Taro.showToast({ title: '请输入昵称', icon: 'none' }) + return + } + if (!form.gender || !form.birthday || !form.birthHour || !form.province || !form.city || !form.district) { + Taro.showToast({ title: '请完整填写个人信息', icon: 'none' }) + return + } + setSaving(true) + try { + await api.updateProfile({ ...form, nickname }) + if (pendingAvatar) { + await api.uploadAvatar(pendingAvatar) + } + Taro.showToast({ title: '修改成功', icon: 'success' }) + setTimeout(() => Taro.navigateBack(), 500) + } catch (error) { + Taro.showToast({ title: errorMessage(error, '保存失败,请重试'), icon: 'none' }) + } finally { + setSaving(false) + } + } + + const birthHour = hours.find((item) => item.name === form.birthHour) || hours[0] + const dateParts = form.birthday ? form.birthday.split('-') : ['', '', ''] + const today = new Date().toISOString().slice(0, 10) + const provinceEntries = regionEntries('86') + const provinceCode = regionCodes[0] || provinceEntries[0]?.[0] || '' + const cityEntries = regionEntries(provinceCode) + const cityCode = regionCodes[1] || cityEntries[0]?.[0] || '' + const districtEntries = regionEntries(cityCode) + const districtCode = regionCodes[2] || districtEntries[0]?.[0] || '' + const regionPickerValue = [ + Math.max(0, provinceEntries.findIndex(([code]) => code === provinceCode)), + Math.max(0, cityEntries.findIndex(([code]) => code === cityCode)), + Math.max(0, districtEntries.findIndex(([code]) => code === districtCode)) + ] + + const changeRegionColumn = (column: number, value: number) => { + if (column === 0) { + const nextProvinceCode = provinceEntries[value]?.[0] || provinceEntries[0]?.[0] || '' + const nextCities = regionEntries(nextProvinceCode) + const nextCityCode = nextCities[0]?.[0] || '' + const nextDistrictCode = regionEntries(nextCityCode)[0]?.[0] || '' + setRegionCodes([nextProvinceCode, nextCityCode, nextDistrictCode]) + return + } + if (column === 1) { + const nextCityCode = cityEntries[value]?.[0] || cityEntries[0]?.[0] || '' + setRegionCodes([provinceCode, nextCityCode, regionEntries(nextCityCode)[0]?.[0] || '']) + return + } + setRegionCodes([provinceCode, cityCode, districtEntries[value]?.[0] || districtEntries[0]?.[0] || '']) + } + + const confirmRegion = (values: number[]) => { + const selectedProvince = provinceEntries[values[0]] || provinceEntries[0] + const selectedCities = regionEntries(selectedProvince?.[0] || '') + const selectedCity = selectedCities[values[1]] || selectedCities[0] + const selectedDistricts = regionEntries(selectedCity?.[0] || '') + const selectedDistrict = selectedDistricts[values[2]] || selectedDistricts[0] + if (!selectedProvince || !selectedCity || !selectedDistrict) return + const cityName = selectedCity[1] === '市辖区' ? selectedProvince[1] : selectedCity[1] + setRegionCodes([selectedProvince[0], selectedCity[0], selectedDistrict[0]]) + setForm({ + ...form, + province: selectedProvince[1], + city: cityName, + district: selectedDistrict[1] + }) } return ( - - - 💧水 - - setForm({ ...form, nickname: String(e.detail.value) })} /> - ✎ - - - {['男', '女'].map((gender) => ( - - ))} - - 选择你的出生日期(公历) - setForm({ ...form, birthday: String(e.detail.value) })}> - - {(form.birthday || '2008-12-28').split('-').map((part, idx) => ( - {part} - ))} + + + 昵称 + setForm({ ...form, nickname: String(event.detail.value) })} + /> + {form.nickname.length}/20 + + + + {[ + { value: '男', symbol: '♂' }, + { value: '女', symbol: '♀' } + ].map((item) => ( + + ))} + + + setForm({ ...form, birthday: String(event.detail.value) })}> + + 出生日期 + + {form.birthday ? `${dateParts[0]} 年 ${dateParts[1]} 月 ${dateParts[2]} 日` : '请选择'} + + › + + + + `${item.name}(${item.range})`)} + value={Math.max(0, hours.findIndex((item) => item.name === form.birthHour))} + onChange={(event) => setForm({ ...form, birthHour: hours[Number(event.detail.value)].name })} + > + + 出生时辰 + + {form.birthHour ? `${birthHour.name}(${birthHour.range})` : '请选择'} + + › + + + + name), + cityEntries.map(([, name]) => name === '市辖区' ? form.province || '市辖区' : name), + districtEntries.map(([, name]) => name) + ]} + value={regionPickerValue} + onColumnChange={(event) => changeRegionColumn(Number(event.detail.column), Number(event.detail.value))} + onCancel={() => setRegionCodes(findRegionCodes(form))} + onChange={(event) => confirmRegion(event.detail.value as number[])} + > + + 出生地点 + + {form.province ? `${form.province} - ${form.city} - ${form.district}` : '请选择'} + + › + + + + + 半年内只能修改{profile?.remainingEdits ?? 0}次哦 - - setForm({ ...form, birthHour: hours[Number(e.detail.value)] })}> - {form.birthHour || '寅时'} 时 - - 选择你的出生地 - { - const values = e.detail.value as number[] - setForm({ ...form, province: regions[0][values[0]], city: regions[1][values[1]], district: regions[2][values[2]] }) - }} - > - - {form.province || '河南省'} ▼ - {form.city || '洛阳市'} ▼ - {form.district || '老城区'} ▼ + )} + + {avatarSheetOpen && ( + setAvatarSheetOpen(false)}> + event.stopPropagation()}> + + + + + + - - - 半年内只能修改五次哦 + )} ) } diff --git a/src/services/frontendPreview.ts b/src/services/frontendPreview.ts new file mode 100644 index 0000000..a6670eb --- /dev/null +++ b/src/services/frontendPreview.ts @@ -0,0 +1,21 @@ +import type { UserProfile } from './request' + +export function isFrontendPreview(): boolean { + return process.env.TARO_ENV === 'h5' + && typeof window !== 'undefined' + && new URLSearchParams(window.location.search).get('preview') === '1' +} + +export const frontendPreviewProfile: UserProfile = { + id: 0, + nickname: 'You', + gender: '男', + birthday: '1998-06-18', + birthHour: '辰时', + province: '河南省', + city: '洛阳市', + district: '洛龙区', + points: 0, + remainingEdits: 5, + elementReport: { scores: [], favorable: '', unfavorable: '', dayMaster: '' } +} diff --git a/src/services/request.ts b/src/services/request.ts index d248a20..0dd7e72 100644 --- a/src/services/request.ts +++ b/src/services/request.ts @@ -1,4 +1,5 @@ import Taro from '@tarojs/taro' +import { frontendPreviewProfile, isFrontendPreview } from './frontendPreview' const BASE_URL = 'http://localhost:8080' @@ -11,6 +12,12 @@ type ApiResult = { type RequestOptions = Omit export async function request(url: string, options: RequestOptions = {}): Promise { + if (isFrontendPreview()) { + if (url === '/api/user/profile' && (!options.method || options.method === 'GET')) { + return { ...frontendPreviewProfile, elementReport: { ...frontendPreviewProfile.elementReport, scores: [] } } as T + } + throw new Error('纯前端预览暂不请求后端或保存修改') + } const token = Taro.getStorageSync('token') const headers = { 'content-type': 'application/json', @@ -28,6 +35,34 @@ export async function request(url: string, options: RequestOptions = {}): Pro return res.data.data } +export function resolveAssetUrl(url?: string) { + if (!url) return '' + return /^https?:\/\//.test(url) || url.startsWith('wxfile://') || url.startsWith('http://tmp/') + ? url + : `${BASE_URL}${url.startsWith('/') ? url : `/${url}`}` +} + +async function uploadAvatar(filePath: string): Promise { + if (isFrontendPreview()) throw new Error('纯前端预览暂不上传头像或保存修改') + const token = Taro.getStorageSync('token') + const response = await Taro.uploadFile({ + url: `${BASE_URL}/api/user/avatar`, + filePath, + name: 'file', + header: token ? { Authorization: `Bearer ${token}` } : {} + }) + let result: ApiResult + try { + result = JSON.parse(response.data) as ApiResult + } catch (error) { + throw new Error('头像上传失败') + } + if (result.code !== 0) { + throw new Error(result.message || '头像上传失败') + } + return result.data +} + export const api = { wxLogin: (code: string) => request<{ sessionKey: string; phoneBound: boolean }>('/api/auth/wx-login', { method: 'POST', @@ -46,6 +81,7 @@ export const api = { method: 'PUT', data }), + uploadAvatar, exchangeStatus: () => request<{ points: number; available: boolean; message: string }>('/api/points/exchange-status'), agreement: (type: string) => request<{ title: string; body: string }>(`/api/content/agreement/${type}`), follow: () => request>('/api/content/follow'), @@ -66,6 +102,7 @@ export type ElementScore = { export type UserProfile = { id: number + avatarUrl?: string nickname: string phone?: string gender: string diff --git a/src/types/assets.d.ts b/src/types/assets.d.ts index 89d74bf..9a46ffa 100644 --- a/src/types/assets.d.ts +++ b/src/types/assets.d.ts @@ -7,3 +7,8 @@ declare module '*.png' { const src: string export default src } + +declare module 'china-area-data' { + const data: Record> + export default data +} diff --git a/src/utils/fiveElements.ts b/src/utils/fiveElements.ts index aee6487..a6f6413 100644 --- a/src/utils/fiveElements.ts +++ b/src/utils/fiveElements.ts @@ -1,90 +1,158 @@ -import { Solar } from 'lunar-typescript' -import { ElementScore } from '../services/request' - -type ElementName = '木' | '火' | '土' | '金' | '水' +import { LunarUtil, Solar } from 'lunar-typescript' +import type { ElementScore } from '../services/request' +export type ElementName = '木' | '火' | '土' | '金' | '水' +export type Pillars = [string, string, string, string] export type FiveElementReport = { scores: ElementScore[] favorable: string unfavorable: string dayMaster: string + masterElement: ElementName + pillars: Pillars + strength: '偏弱' | '相对平衡' | '偏强' + strengthScore: number + analysis: { + season: { supported: boolean; score: number; description: string } + roots: { supported: boolean; score: number; description: string } + support: { supported: boolean; score: number; description: string } + } } -const stemElements: Record = { +const stems: Record = { 甲: '木', 乙: '木', 丙: '火', 丁: '火', 戊: '土', 己: '土', 庚: '金', 辛: '金', 壬: '水', 癸: '水' } - const branchElements: Record = { 子: '水', 丑: '土', 寅: '木', 卯: '木', 辰: '土', 巳: '火', 午: '火', 未: '土', 申: '金', 酉: '金', 戌: '土', 亥: '水' } - -const elementMeta: Record = { - 木: { color: '#36b85b' }, - 火: { color: '#ef5a58' }, - 土: { color: '#b46a18' }, - 金: { color: '#d59a05' }, - 水: { color: '#35bfe8' } +const colors: Record = { + 木: '#36b85b', 火: '#ef5a58', 土: '#b46a18', 金: '#d59a05', 水: '#35bfe8' } - const scoreOrder: ElementName[] = ['土', '金', '水', '木', '火'] -const generationOrder: ElementName[] = ['木', '火', '土', '金', '水'] +const cycle: ElementName[] = ['木', '火', '土', '金', '水'] +const emptyWeights = (): Record => ({ 木: 0, 火: 0, 土: 0, 金: 0, 水: 0 }) -const hourFromBirthHour = (birthHour: string) => { - const numericHour = Number.parseInt(birthHour, 10) - if (Number.isFinite(numericHour)) return Math.max(0, Math.min(23, numericHour)) - - const branchHours: Record = { - 子: 23, 丑: 1, 寅: 3, 卯: 5, 辰: 7, 巳: 9, - 午: 11, 未: 13, 申: 15, 酉: 17, 戌: 19, 亥: 21 - } - return branchHours[birthHour.slice(0, 1)] ?? 12 +// 本项目普通扶抑规则 v1,权重为产品约定,不代表各命理流派的统一标准。 +// 月令:旺/相/休/囚/死分别取 100/80/50/30/15 分,辰戌丑未按土月简化。 +const seasonScore = (element: ElementName, season: ElementName) => { + const relation = (cycle.indexOf(element) - cycle.indexOf(season) + 5) % 5 + return [100, 80, 15, 30, 50][relation] } -export function calculateFiveElements(birthday: string, birthHour: string): FiveElementReport { - const date = new Date(`${birthday}T00:00:00`) - if (Number.isNaN(date.getTime())) { - return { - scores: scoreOrder.map((name) => ({ name, color: elementMeta[name].color, value: 20 })), - favorable: '金水', - unfavorable: '木火土', - dayMaster: '壬' - } +const hiddenStems = (branch: string): Array<{ stem: string; share: number }> => { + const hidden = LunarUtil.ZHI_HIDE_GAN[branch] || [] + const shares = hidden.length === 1 ? [1] : hidden.length === 2 ? [0.7, 0.3] : [0.6, 0.3, 0.1] + return hidden.map((stem, index) => ({ stem, share: shares[index] })) +} + +// 最大余数法保证展示百分比之和为 100,零值仍保持为零。 +const toScores = (weights: Record): ElementScore[] => { + const total = Object.values(weights).reduce((sum, value) => sum + value, 0) + const entries = scoreOrder.map((name) => { + const exact = weights[name] / total * 100 + return { name, value: Math.floor(exact), remainder: exact - Math.floor(exact) } + }) + const remaining = 100 - entries.reduce((sum, item) => sum + item.value, 0) + const ranked = [...entries].sort((a, b) => b.remainder - a.remainder) + for (let index = 0; index < remaining; index++) ranked[index].value++ + return entries.map(({ name, value }) => ({ name, value, color: colors[name] })) +} + +export function analyzePillars(pillars: Pillars): FiveElementReport { + if (pillars.some((pillar) => pillar.length !== 2 || !stems[pillar[0]] || !branchElements[pillar[1]])) { + throw new Error('四柱数据不完整') } + const dayMaster = pillars[2][0] + const masterElement = stems[dayMaster] + const masterIndex = cycle.indexOf(masterElement) + const resource = cycle[(masterIndex + 4) % 5] + const season = branchElements[pillars[1][1]] + const weights = emptyWeights() + const surrounding = emptyWeights() + let rootPower = 0 + const rootBranches: string[] = [] - const solar = Solar.fromYmdHms( - date.getFullYear(), - date.getMonth() + 1, - date.getDate(), - hourFromBirthHour(birthHour), - 0, - 0 - ) - const eightChar = solar.getLunar().getEightChar() - const pillars = [eightChar.getYear(), eightChar.getMonth(), eightChar.getDay(), eightChar.getTime()] - const weights: Record = { 木: 0, 火: 0, 土: 0, 金: 0, 水: 0 } - - pillars.forEach((pillar) => { - const [stem, branch] = pillar - if (stemElements[stem]) weights[stemElements[stem]] += 2 - if (branchElements[branch]) weights[branchElements[branch]] += 1 + pillars.forEach((pillar, index) => { + const stemElement = stems[pillar[0]] + weights[stemElement] += 10 + // 得势不把日干自身计入生扶比例,避免自己支持自己的循环判断。 + if (index !== 2) surrounding[stemElement] += 10 + const branchWeight = index === 1 ? 18 : 10 + const hidden = hiddenStems(pillar[1]) + const roots = hidden.filter(({ stem }) => stems[stem] === masterElement) + if (roots.length) rootBranches.push(pillar[1]) + rootPower += roots.reduce((sum, { share }) => sum + share, 0) + hidden.forEach(({ stem, share }) => { + weights[stems[stem]] += branchWeight * share + surrounding[stems[stem]] += branchWeight * share + }) }) - const total = Object.values(weights).reduce((sum, value) => sum + value, 0) - const scores = scoreOrder.map((name) => ({ - name, - color: elementMeta[name].color, - value: Math.round((weights[name] / total) * 100) - })) - const dayMaster = eightChar.getDay().slice(0, 1) - const masterElement = stemElements[dayMaster] || '水' - const masterIndex = generationOrder.indexOf(masterElement) - const resourceElement = generationOrder[(masterIndex + generationOrder.length - 1) % generationOrder.length] - const unfavorable = generationOrder.filter((element) => element !== resourceElement && element !== masterElement).join('') + const seasonValue = seasonScore(masterElement, season) + // 两个完整同类根视为根气充分;藏干按 1、7:3 或 6:3:1 分配根气。 + const rootValue = Math.min(100, rootPower / 2 * 100) + const surroundingTotal = Object.values(surrounding).reduce((sum, value) => sum + value, 0) + const supportValue = (surrounding[masterElement] + surrounding[resource]) / surroundingTotal * 100 + const strengthScore = Math.round(seasonValue * 0.4 + rootValue * 0.3 + supportValue * 0.3) + const strength = strengthScore < 45 ? '偏弱' : strengthScore > 55 ? '偏强' : '相对平衡' + const favorable = strength === '偏弱' + ? `${resource}${masterElement}` + : strength === '偏强' + ? [cycle[(masterIndex + 1) % 5], cycle[(masterIndex + 2) % 5], cycle[(masterIndex + 3) % 5]].join('') + : '' + const unfavorable = strength === '相对平衡' ? '' : cycle.filter((element) => !favorable.includes(element)).join('') return { - scores, - favorable: `${resourceElement}${masterElement}`, - unfavorable, - dayMaster + scores: toScores(weights), favorable, unfavorable, dayMaster, masterElement, pillars, + strength, strengthScore, + analysis: { + season: { + supported: seasonValue >= 80, + score: seasonValue, + description: `${pillars[1][1]}月按${season}气判断,${masterElement}${seasonValue >= 80 ? '得到月令支持' : '月令支持较少'}。` + }, + roots: { + supported: rootPower > 0, + score: Math.round(rootValue), + description: rootBranches.length + ? `四支中${rootBranches.join('、')}的藏干有${masterElement}根,根气评分${Math.round(rootValue)}。` + : `四支藏干未见${masterElement}同类根。` + }, + support: { + supported: supportValue >= 50, + score: Math.round(supportValue), + description: `除日干外,${resource}与${masterElement}的生扶力量占${Math.round(supportValue)}%。` + } + } + } +} + +const hourFromBirthHour = (birthHour: string): number | null => { + const branchHours: Record = { + 子: 23, 丑: 1, 寅: 3, 卯: 5, 辰: 7, 巳: 9, 午: 11, 未: 13, 申: 15, 酉: 17, 戌: 19, 亥: 21 + } + if (Object.prototype.hasOwnProperty.call(branchHours, birthHour)) return branchHours[birthHour] + if (/^[子丑寅卯辰巳午未申酉戌亥]时$/.test(birthHour)) return branchHours[birthHour[0]] + if (/^\d{1,2}$/.test(birthHour)) { + const hour = Number(birthHour) + return hour <= 23 ? hour : null + } + return null +} + +export function calculateFiveElements(birthday: string, birthHour: string): FiveElementReport | null { + if (!/^\d{4}-\d{2}-\d{2}$/.test(birthday || '')) return null + const [year, month, day] = birthday.split('-').map(Number) + const hour = hourFromBirthHour(birthHour || '') + if (hour === null || year < 1900 || year > 2100 || month < 1 || month > 12 || day < 1) return null + const daysInMonth = new Date(Date.UTC(year, month, 0)).getUTCDate() + if (day > daysInMonth) return null + try { + // 直接使用公历字段,避免浏览器时区/日期字符串解析影响结果。 + const eightChar = Solar.fromYmdHms(year, month, day, hour, 0, 0).getLunar().getEightChar() + eightChar.setSect(2) // 沿用历法库默认:子初不换日,日柱按零点换日。 + return analyzePillars([eightChar.getYear(), eightChar.getMonth(), eightChar.getDay(), eightChar.getTime()]) + } catch { + return null } } diff --git a/src/utils/homeOverview.ts b/src/utils/homeOverview.ts new file mode 100644 index 0000000..a23bb0f --- /dev/null +++ b/src/utils/homeOverview.ts @@ -0,0 +1,140 @@ +import { Solar } from 'lunar-typescript' +import type { DimensionItem, HomeOverview, UserProfile } from '../services/request' +import { calculateFiveElements, ElementName, FiveElementReport } from './fiveElements' +import { calculateZodiac, zodiacNames } from './zodiac' +import { getZodiacRelation } from './zodiacWeekly' + +type DimensionId = 'emotion' | 'health' | 'life' | 'wealth' | 'social' | 'study' | 'career' | 'travel' +type DimensionDefinition = { id: DimensionId; title: string; icon: string; element: ElementName; activities: string[]; positive: [string, string][]; cautious: [string, string][] } +export type GeneratedDimension = DimensionItem & { score: number } +export type GeneratedHomeOverview = Omit & { dimensions: GeneratedDimension[] } +const cycle: ElementName[] = ['木', '火', '土', '金', '水'] +const stems: Record = { 甲: '木', 乙: '木', 丙: '火', 丁: '火', 戊: '土', 己: '土', 庚: '金', 辛: '金', 壬: '水', 癸: '水' } +const branches = [...'子丑寅卯辰巳午未申酉戌亥'] +const relationPoints = { 六合: 2, 三合: 1, 六冲: -2, 相害: -1, 平常: 0 } +const definitions: DimensionDefinition[] = [ + { id: 'emotion', title: '情感', icon: 'heart', element: '火', activities: ['嫁娶', '订盟', '纳采'], + positive: [['默契收集,认真倾听', '留一点时间给在意的人,认真听完对方的话,也表达自己的感受。'], ['温柔表达,分享日常', '从一件小事聊起,让轻松的分享成为彼此理解的机会。']], + cautious: [['放慢表达,少些猜测', '遇到分歧先确认对方的意思,避免用猜测代替沟通。'], ['留出空间,不急回应', '不必急着为关系下结论,先整理感受,再选择合适的表达方式。']] }, + { id: 'health', title: '健康', icon: 'gourd', element: '木', activities: ['沐浴', '解除'], + positive: [['留白休息,照顾节奏', '给日程留出休息空隙,选择让自己感到舒适的活动。'], ['规律作息,轻松生活', '合理安排工作与休息,用平常心照顾自己的日常节奏。']], + cautious: [['减少透支,适度休息', '行程尽量安排宽松一些,避免为了赶进度不断压缩休息。'], ['放下紧绷,量力而行', '适当减少不必要的忙碌,不用勉强自己完成所有安排。']] }, + { id: 'life', title: '生活', icon: 'vase', element: '土', activities: ['入宅', '移徙', '安床', '扫舍', '修造'], + positive: [['整理日常,留住从容', '从一处小空间开始整理,为生活腾出一点轻松与秩序。'], ['收纳旧物,珍惜日常', '梳理身边物品,留下真正需要和喜欢的部分,不必一次完成。']], + cautious: [['少些堆叠,做好取舍', '先处理手头的小事,避免同时开启太多整理或采购计划。'], ['简化安排,稳住节奏', '把复杂的家务拆成小步骤,逐项完成比匆忙赶工更从容。']] }, + { id: 'wealth', title: '财富', icon: 'coin', element: '金', activities: ['交易', '纳财', '开市', '立券'], + positive: [['梳理预算,按需安排', '核对日常收支和购物清单,让消费围绕实际需求展开。'], ['清点账目,有序消费', '整理订阅与账单,关注自己真正会使用的物品和服务。']], + cautious: [['勿乱囤货,按需消费', '面对促销先看清需求与总价,给非必要购买留一点考虑时间。'], ['核对清单,避免冲动', '先确认已有物品和预算,再决定是否添置,不急于跟随热度。']] }, + { id: 'social', title: '社交', icon: 'fan', element: '火', activities: ['会亲友', '宴会', '订盟'], + positive: [['友好交流,真诚回应', '把注意力放在真诚的交流上,适时表达感谢与关心。'], ['主动问候,轻松相聚', '选择让双方都舒适的话题和时间,为相处保留自然的空间。']], + cautious: [['勿涉纷争,尊重边界', '不必急着评判他人的是非,先确认事实,保持清楚的边界。'], ['少些争辩,多些理解', '意见不同时可以暂缓讨论,不让一时的情绪替自己作答。']] }, + { id: 'study', title: '学业', icon: 'scroll', element: '水', activities: ['入学', '习艺'], + positive: [['专注积累,温故知新', '挑选一个清晰的小目标,结合复习和练习检验理解。'], ['循序探索,整理笔记', '把新知识与已有内容连起来,留下自己的问题与总结。']], + cautious: [['回到基础,不急跳级', '遇到难点先检查基础概念,不用靠加快进度掩盖疑问。'], ['减少分心,逐项练习', '收起暂时无关的信息,把注意力留给眼前的一项学习任务。']] }, + { id: 'career', title: '事业', icon: 'bamboo', element: '木', activities: ['赴任', '开市', '立券'], + positive: [['清晰协作,稳步推进', '先对齐目标和分工,再推进关键任务,为沟通留足时间。'], ['认真落实,积累进展', '聚焦一项可以交付的小成果,让行动形成清晰的进度。']], + cautious: [['认真核对,避免敷衍', '提交前检查要求和细节,遇到不明确的地方及时确认。'], ['收拢任务,先稳后快', '把任务按轻重缓急排好,避免为了同时推进而忽略细节。']] }, + { id: 'travel', title: '出行', icon: 'horse', element: '水', activities: ['出行', '移徙'], + positive: [['轻装安排,从容出发', '提前整理路线和随身物品,为换乘与休息留出余地。'], ['规划路线,享受沿途', '出发前确认时间与目的地,选择适合自己节奏的行程。']], + cautious: [['勿负重行,检查安排', '精简随身物品,出发前再次确认路线、时间和必要证件。'], ['留足余量,不必赶路', '为临时调整留出时间,行程有变化时先重新确认安排。']] } +] +export const HOME_DIMENSION_IDS = definitions.map((item) => item.id) + +export function normalizeDimensionOrder(value: unknown): string[] { + const saved = Array.isArray(value) ? value.filter((id): id is DimensionId => HOME_DIMENSION_IDS.includes(id)) : [] + return [...new Set([...saved, ...HOME_DIMENSION_IDS])] +} + +const palette: Record = { + 木: { colors: [{ name: '青竹绿', value: '#9fbb81' }, { name: '绿茶色', value: '#a7ad42' }], numbers: ['3', '8'] }, + 火: { colors: [{ name: '珊瑚粉', value: '#ef9ca1' }, { name: '暖橘色', value: '#edaf73' }], numbers: ['2', '7'] }, + 土: { colors: [{ name: '暖杏色', value: '#eac58e' }, { name: '麦芽色', value: '#d6b887' }], numbers: ['5', '0'] }, + 金: { colors: [{ name: '月白色', value: '#f4eede' }, { name: '浅金色', value: '#e8d5a7' }], numbers: ['4', '9'] }, + 水: { colors: [{ name: '瀑布蓝', value: '#58bfce' }, { name: '雾霭蓝', value: '#8eb4d6' }], numbers: ['1', '6'] } +} + +function elementSupport(source: ElementName, target: ElementName): number { + const delta = (cycle.indexOf(target) - cycle.indexOf(source) + 5) % 5 + return delta === 0 || delta === 1 ? 6 : delta === 2 ? -6 : 0 +} +const preference = (report: FiveElementReport, element: ElementName, weight: number) => { + const share = report.scores.find((score) => score.name === element)?.value || 0 + // 先由扶抑确定方向,再在该方向内按个人五行份额小幅调整;不是缺什么就补什么。 + if (report.favorable.includes(element)) return weight + Math.round(Math.max(0, 20 - share) / 5) + if (report.unfavorable.includes(element)) return -weight - Math.round(Math.max(0, share - 20) / 5) + return 0 +} +const clamp = (value: number) => Math.min(90, Math.max(15, value)) +const statusFor = (score: number) => score >= 80 ? '大吉' : score >= 65 ? '小吉' : score >= 50 ? '平日' : score >= 35 ? '小逆' : '谨慎' +const formatHourEnd = (end: string) => { + const [hour, minute] = end.split(':').map(Number) + const total = hour * 60 + minute + 1 + return `${String(Math.floor(total / 60)).padStart(2, '0')}:${String(total % 60).padStart(2, '0')}` +} + +function calculateDay(solar: Solar, report: FiveElementReport, birthBranch: string) { + const lunar = solar.getLunar() + const dayElement = stems[lunar.getDayGan()] + const relation = getZodiacRelation(birthBranch, lunar.getDayZhi()) + const commonScore = 50 + preference(report, dayElement, 10) + relationPoints[relation] * 5 + const yi = lunar.getDayYi() + const ji = lunar.getDayJi() + const dimensions: GeneratedDimension[] = definitions.map((definition) => { + const discouraged = definition.activities.some((activity) => ji.includes(activity)) + const encouraged = definition.activities.some((activity) => yi.includes(activity)) + const calendarPoints = discouraged ? -10 : encouraged ? 10 : 0 + const score = clamp(commonScore + preference(report, definition.element, 8) + elementSupport(dayElement, definition.element) + calendarPoints) + const suitable = score >= 50 + const variants = suitable ? definition.positive : definition.cautious + const [headline, detail] = variants[lunar.getDayGanIndex() % variants.length] + return { id: definition.id, title: definition.title, icon: definition.icon, headline, detail, suitable, score } + }) + const overallIndex = Math.round(dimensions.reduce((sum, item) => sum + item.score, 0) / dimensions.length) + const ranked = [...dimensions].sort((a, b) => b.score - a.score) + const status = statusFor(overallIndex) + const summary = ranked[0].score === ranked[ranked.length - 1].score + ? `${status}之日,节奏相对均衡,按计划推进,也给自己留出余地。` + : `${status}之日,可关注${ranked[0].title}安排,${ranked[ranked.length - 1].title}方面多留意细节。` + + const preferred = report.favorable + ? [...report.favorable] as ElementName[] + : [...report.scores].sort((a, b) => a.value - b.value).slice(0, 2).map((score) => score.name as ElementName) + const luckyElements = [...preferred].sort((a, b) => elementSupport(dayElement, b) - elementSupport(dayElement, a)).slice(0, 2) + const alternate = lunar.getDayGanIndex() % 2 + const luckyColors = luckyElements.map((element) => palette[element].colors[alternate]) + const luckyNumbers = luckyElements.map((element) => palette[element].numbers[lunar.getDayZhiIndex() % 2]) + const hours = lunar.getTimes() + .map((hour, index) => ({ hour, index, score: preference(report, stems[hour.getGan()], 2) + relationPoints[getZodiacRelation(birthBranch, hour.getZhi())] })) + .filter(({ hour }) => hour.getTianShenLuck() === '吉') + .sort((a, b) => b.score - a.score || a.index - b.index) + const seen = new Set() + const luckyHours = hours.filter(({ hour }) => { + if (seen.has(hour.getZhi())) return false + seen.add(hour.getZhi()) + return true + }).slice(0, 2).map(({ hour }) => ({ branch: hour.getZhi(), time: `${hour.getMinHm()}–${formatHourEnd(hour.getMaxHm())}` })) + return { + date: solar.toYmd(), weekName: `星期${'日一二三四五六'[solar.getWeek()]}`, + lunarDate: `农历${lunar.getYearInGanZhi()}年 ${lunar.getMonthInChinese()}月${lunar.getDayInChinese()}`, + status, summary, overallIndex, luckyColors, luckyNumbers, luckyDirection: lunar.getDayPositionXiDesc(), luckyHours, dimensions + } +} + +export function generateHomeOverview(profile: Pick, today: string, offset: -1 | 0 | 1 = 0): GeneratedHomeOverview | null { + const report = calculateFiveElements(profile.birthday, profile.birthHour) + const zodiac = calculateZodiac(profile.birthday) + if (!report || !zodiac || !/^\d{4}-\d{2}-\d{2}$/.test(today)) return null + const [year, month, day] = today.split('-').map(Number) + if (year < 1900 || year > 2100 || month < 1 || month > 12 || day < 1 || day > new Date(Date.UTC(year, month, 0)).getUTCDate()) return null + if (![-1, 0, 1].includes(offset)) return null + try { + const base = Solar.fromYmd(year, month, day) + const birthBranch = branches[zodiacNames.indexOf(zodiac)] + const reports = [-1, 0, 1].map((index) => calculateDay(base.next(index), report, birthBranch)) + const labels = ['昨日', '今日', '明日'] as const + const selected = reports[offset + 1] + return { ...selected, activeDay: labels[offset + 1], days: reports.map((item, index) => ({ label: labels[index], date: item.date, weekName: item.weekName, lunarDate: item.lunarDate, status: item.status })) } + } catch { + return null + } +} diff --git a/src/utils/zodiac.ts b/src/utils/zodiac.ts new file mode 100644 index 0000000..c8f69bd --- /dev/null +++ b/src/utils/zodiac.ts @@ -0,0 +1,18 @@ +import { Solar } from 'lunar-typescript' + +export const zodiacNames = ['鼠', '牛', '虎', '兔', '龙', '蛇', '马', '羊', '猴', '鸡', '狗', '猪'] as const +export type ZodiacName = typeof zodiacNames[number] + +// 日常生肖按农历正月初一换年,不能使用公历年份或立春年柱代替。 +export function calculateZodiac(birthday: string): ZodiacName | null { + if (!/^\d{4}-\d{2}-\d{2}$/.test(birthday || '')) return null + const [year, month, day] = birthday.split('-').map(Number) + if (year < 1900 || year > 2100 || month < 1 || month > 12 || day < 1) return null + if (day > new Date(Date.UTC(year, month, 0)).getUTCDate()) return null + try { + const zodiac = Solar.fromYmd(year, month, day).getLunar().getYearShengXiao() + return zodiacNames.includes(zodiac as ZodiacName) ? zodiac as ZodiacName : null + } catch { + return null + } +} diff --git a/src/utils/zodiacWeekly.ts b/src/utils/zodiacWeekly.ts new file mode 100644 index 0000000..295435c --- /dev/null +++ b/src/utils/zodiacWeekly.ts @@ -0,0 +1,89 @@ +import { LunarUtil, Solar } from 'lunar-typescript' +import { calculateZodiac, zodiacNames, ZodiacName } from './zodiac' + +export type ZodiacRelation = '六合' | '三合' | '六冲' | '相害' | '平常' +export type ZodiacWeeklyDay = { + date: string + label: string + weekday: string + branch: string + relation: ZodiacRelation + score: number +} +export type ZodiacWeeklyReport = { + zodiac: ZodiacName + branch: string + weekStart: string + weekEnd: string + score: number + status: '顺势' | '平稳' | '谨慎' + tone: 'positive' | 'neutral' | 'cautious' + summary: string + days: ZodiacWeeklyDay[] + supportiveDays: ZodiacWeeklyDay[] + cautiousDays: ZodiacWeeklyDay[] +} + +export const ZODIAC_WEEKLY_RULES = '六合 +2,三合同组 +1,六冲 −2,相害 −1,其余 0;七日合计 ≥2 为顺势,≤−2 为谨慎,其余为平稳。' +const BEIJING_OFFSET = 8 * 60 * 60 * 1000 +const branches = LunarUtil.ZHI.slice(1) +const threeHarmonyGroups = ['申子辰', '亥卯未', '寅午戌', '巳酉丑'] +const harmPairs = ['子未', '丑午', '寅巳', '卯辰', '申亥', '酉戌'] +const relationScores: Record = { 六合: 2, 三合: 1, 六冲: -2, 相害: -1, 平常: 0 } +const weekdays = ['周一', '周二', '周三', '周四', '周五', '周六', '周日'] + +// 用UTC字段读取UTC+8日期,不依赖设备时区,也不依赖浏览器Intl能力。 +export function getBeijingDate(now = new Date()): string { + if (!Number.isFinite(now.getTime())) return '' + return new Date(now.getTime() + BEIJING_OFFSET).toISOString().slice(0, 10) +} + +export function getZodiacRelation(birthBranch: string, dayBranch: string): ZodiacRelation { + const index = branches.indexOf(birthBranch) + if (index < 0 || !branches.includes(dayBranch)) throw new Error('无效的地支') + if (LunarUtil.HE_ZHI_6[index] === dayBranch) return '六合' + if (LunarUtil.CHONG[index] === dayBranch) return '六冲' + if (harmPairs.some((pair) => pair.includes(birthBranch) && pair.includes(dayBranch)) && birthBranch !== dayBranch) return '相害' + // 只表示同组三合的助力关系,两个地支不等于完整三合成局。 + if (birthBranch !== dayBranch && threeHarmonyGroups.some((group) => group.includes(birthBranch) && group.includes(dayBranch))) return '三合' + return '平常' +} + +export function calculateWeeklyZodiacFortune(birthday: string, beijingDate = getBeijingDate()): ZodiacWeeklyReport | null { + const zodiac = calculateZodiac(birthday) + if (!zodiac || !/^\d{4}-\d{2}-\d{2}$/.test(beijingDate)) return null + const [year, month, day] = beijingDate.split('-').map(Number) + if (year < 1900 || year > 2100 || month < 1 || month > 12 || day < 1 || day > new Date(Date.UTC(year, month, 0)).getUTCDate()) return null + try { + const current = Solar.fromYmd(year, month, day) + const monday = current.next(-((current.getWeek() + 6) % 7)) + const branch = branches[zodiacNames.indexOf(zodiac)] + const days = weekdays.map((weekday, index): ZodiacWeeklyDay => { + const solar = monday.next(index) + const dayBranch = solar.getLunar().getDayZhi() + const relation = getZodiacRelation(branch, dayBranch) + return { + date: solar.toYmd(), + label: `${solar.getMonth()}/${solar.getDay()}`, + weekday, branch: dayBranch, relation, score: relationScores[relation] + } + }) + const score = days.reduce((sum, item) => sum + item.score, 0) + const supportiveDays = days.filter((item) => item.score > 0) + const cautiousDays = days.filter((item) => item.score < 0) + const status = score >= 2 ? '顺势' : score <= -2 ? '谨慎' : '平稳' + const recommendation = score >= 2 + ? '助力关系相对较多,可优先在助力日安排沟通与协作;遇到留意日仍宜放慢节奏。' + : score <= -2 + ? '需要留意的关系相对较多,宜提前确认安排、耐心沟通;助力日可用于协调与收尾。' + : '合冲影响整体接近平衡,宜按计划推进,在助力日多做协调,在留意日注意细节。' + return { + zodiac, branch, weekStart: days[0].date, weekEnd: days[6].date, score, status, + tone: score >= 2 ? 'positive' : score <= -2 ? 'cautious' : 'neutral', + summary: `本周有${supportiveDays.length}个助力日、${cautiousDays.length}个留意日。${recommendation}`, + days, supportiveDays, cautiousDays + } + } catch { + return null + } +}