From 38fc4187eafaf1f8c2bf3ddf14030a5271e40b69 Mon Sep 17 00:00:00 2001 From: zhouzhibo Date: Sun, 18 Oct 2026 23:35:28 +0800 Subject: [PATCH] feat: refine login flows and integrate tiangong worship audio --- docs/birthday-calendar-and-avatar.md | 45 +++++ docs/incense-sound.md | 51 +++++ docs/tiangong-login-access.md | 47 +++++ package.json | 1 + scripts/accountIntegration.test.cjs | 29 +++ scripts/avatarEntry.test.cjs | 71 +++++++ scripts/birthdayCalendar.test.cjs | 97 ++++++++++ scripts/incenseRitual.test.cjs | 241 ++++++++++++++++++++++++ scripts/loginPresentation.test.cjs | 86 +++++++++ scripts/navigation.test.cjs | 7 +- scripts/tiangong.test.cjs | 26 +-- scripts/tiangongAccess.test.cjs | 214 +++++++++++++++++++++ scripts/tiangongStore.test.cjs | 91 +++++++++ src/assets/tiangong/incense-yinqing.m4a | Bin 0 -> 183574 bytes src/components/BirthdayPicker.tsx | 38 ++++ src/components/DeityBinding.scss | 6 + src/components/DeityBinding.tsx | 11 +- src/components/LoginGate.tsx | 18 ++ src/components/TiangongLoginGate.scss | 20 ++ src/components/TiangongLoginGate.tsx | 8 + src/components/TiangongPending.scss | 7 + src/components/TiangongPending.tsx | 17 ++ src/components/TiangongUI.scss | 12 ++ src/components/TiangongUI.tsx | 7 +- src/hooks/useIncenseRitual.ts | 65 +++++++ src/hooks/useRequiredLogin.ts | 50 +++++ src/hooks/useTiangongSnapshot.ts | 14 +- src/pages/fortune/index.tsx | 25 ++- src/pages/home/index.tsx | 14 +- src/pages/login/index.scss | 93 ++------- src/pages/login/index.tsx | 26 +-- src/pages/my/index.tsx | 10 +- src/pages/profile-edit/index.scss | 20 +- src/pages/profile-edit/index.tsx | 32 ++-- src/pages/tiangong-detail/index.scss | 7 +- src/pages/tiangong-detail/index.tsx | 77 ++++---- src/services/avatarDemo.ts | 1 + src/services/frontendPreview.ts | 1 + src/services/loginAccess.ts | 44 +++++ src/services/request.ts | 9 + src/services/tabNavigation.ts | 4 +- src/services/tiangong.ts | 38 +++- src/types/assets.d.ts | 5 + src/utils/birthdayCalendar.ts | 67 +++++++ src/utils/incenseRitual.ts | 115 +++++++++++ src/utils/profileEditing.ts | 6 +- src/utils/resourceCache.ts | 1 + src/utils/tiangongMock.ts | 31 ++- src/utils/tiangongStore.ts | 105 +++++++++++ 49 files changed, 1786 insertions(+), 224 deletions(-) create mode 100644 docs/birthday-calendar-and-avatar.md create mode 100644 docs/incense-sound.md create mode 100644 docs/tiangong-login-access.md create mode 100644 scripts/avatarEntry.test.cjs create mode 100644 scripts/birthdayCalendar.test.cjs create mode 100644 scripts/incenseRitual.test.cjs create mode 100644 scripts/loginPresentation.test.cjs create mode 100644 scripts/tiangongAccess.test.cjs create mode 100644 scripts/tiangongStore.test.cjs create mode 100644 src/assets/tiangong/incense-yinqing.m4a create mode 100644 src/components/BirthdayPicker.tsx create mode 100644 src/components/LoginGate.tsx create mode 100644 src/components/TiangongLoginGate.scss create mode 100644 src/components/TiangongLoginGate.tsx create mode 100644 src/components/TiangongPending.scss create mode 100644 src/components/TiangongPending.tsx create mode 100644 src/hooks/useIncenseRitual.ts create mode 100644 src/hooks/useRequiredLogin.ts create mode 100644 src/services/loginAccess.ts create mode 100644 src/utils/birthdayCalendar.ts create mode 100644 src/utils/incenseRitual.ts create mode 100644 src/utils/tiangongStore.ts diff --git a/docs/birthday-calendar-and-avatar.md b/docs/birthday-calendar-and-avatar.md new file mode 100644 index 0000000..ffdfb5c --- /dev/null +++ b/docs/birthday-calendar-and-avatar.md @@ -0,0 +1,45 @@ +# 出生历法与头像入口验收 + +## 实现与数据约定 + +- 编辑个人信息、完善注册资料共用 `BirthdayPicker`,支持阳历与农历、真实闰月、大小月日期联动。范围为阳历 1900-01-01 至北京时间今天,与现有生肖/五行计算的支持范围保持一致。 +- `birthday` 仍为对应阳历 `YYYY-MM-DD`,用于生肖、五行和每日计算;新增 `birthdayCalendar: "solar" | "lunar"` 仅记录输入/显示偏好。切换历法不改变实际生日,保存后重新编辑按接口偏好回显。农历闰月可由阳历日期准确还原,不需再保存第二份农历生日。 +- 生日或偏好变更沿用现有个人资料保存与修改额度规则;不在选择或切换时自动保存、不擅自改动后端生日计算。 +- 首页左上角头像使用主 Tab 导航到“我的”,不再是不可点的展示区域。 +- 微信端直接点击头像即使用 `openType=chooseAvatar`,不再先打开本项目的自定义菜单;回调只预览选中的临时文件,点击保存时仍走后端文件服务,不绕过平台用户确认。H5 不支持该微信能力,仍保留相册/拍照菜单。本次 H5 验收不代表已操作微信原生弹窗。 + +## 接口清单 + +没有新增路径或改变部署基址,复用以下接口: + +- GET `/api/user/profile`:响应新增 `birthdayCalendar`,生日仍为阳历。 +- PUT `/api/user/profile`:请求、响应新增 `birthdayCalendar`;服务端只允许 `solar`、`lunar`。 +- POST `/api/auth/wx-login`、POST `/api/auth/bind-phone`:登录资料中的 `user` 同样返回偏好。 +- POST `/api/user/avatar`:头像保存仍上传至现有文件存储服务,生日选择不影响头像接口。 + +## 部署前置条件 + +后端已补 DTO、实体、联合查询、资料 Mapper 和建表定义。已有目标数据库应先由部署人员执行: + +`/Users/zhouzhibo/file/hongzhen/idea/hera/src/main/resources/db/birthday-calendar-update.sql` + +随后部署/重启新版后端,再更新小程序。脚本只按列是否存在增加 `user_profile.birthday_calendar`,默认 `solar`,不修改生日、不删除数据;没有自动启动时远程迁移。本次未执行远程 MySQL DDL、未部署后端、未提交或推送。 + +## 验收步骤 + +1. 开发者工具重新编译,登录后从首页点击左上角头像:应切换到“我的”;再点头部进入编辑信息。 +2. 点击“农历”:显示同一天的农历及对应阳历,实际生日未变;打开日期选择器可单独选择闰月。 +3. 示例农历 2023 年闰二月初一,应对应阳历 2023-03-22。切换年份到无此闰月的年份时,使用该年的普通二月;切到小月时超出天数自动收敛,不提交无效日期。 +4. 在选择器点取消:实际生日不变。点确定、保存、返回再进入:农历偏好与日期保持;切回阳历保存后同样能回显。 +5. 首次注册完善资料使用同一控件。不能选未来日期;保存后生肖、五行使用换算后的阳历日期。 +6. 微信端直接点头像:应立即出现一次微信官方头像选择器,不先弹自定义菜单;确认后预览、取消不更换当前头像。H5 点击头像仍显示相册/拍照菜单。 + +本地视觉验收可用 `http://127.0.0.1:4173/?avatarDemo=1#/pages/home/index`,其中资料、头像仅为隔离演示,刷新重置;不能据此认定远程保存已生效。 + +## 已验证与边界 + +- 79 项前端测试通过,类型检查、H5/微信构建与 13 个文件的原生 WXSS 检查通过;其中头像入口测试验证微信端直接绑定官方选择器、无自定义菜单,以及 H5 的相册入口保留。 +- 后端 12 项 H2/MockMvc 测试通过,验证资料落库、回显、再次登录、非法历法拒绝、头像不受影响;1 项真实 MySQL 测试未配置专用测试库而跳过,没有写远程库。 +- 浏览器实测首页头像跳转、农历闰月确认、隔离演示保存与再次编辑回显,以及注册场景共用选择器。 +- 截图:`/private/tmp/hera-birthday-lunar-edit.png`。 +- 微信官方选择器的外观、取消/安全审核分支需微信开发者工具与真机验收;H5 不模拟成真实微信授权。 diff --git a/docs/incense-sound.md b/docs/incense-sound.md new file mode 100644 index 0000000..4cd184f --- /dev/null +++ b/docs/incense-sound.md @@ -0,0 +1,51 @@ +# 敬神:音频与真实供奉接口 + +## 本期规则 + +- 不提供功德、爱心、钱包、捐款、充值入口,不累计功德。服务端拒绝 offeringType=4 或任何非空 meritValue。历史列和流水保留,不删数据。 +- 喇叭默认开启,偏好仅保存在本机。关闭立即静音,音频以音量0继续推进;重新开启只恢复当前实际进度的声音,不暂停、不重头、不补播。最初静音上香也从首轮开始推进,音频已经结束则开启不再出声;追加上香延长点亮,不延长音频。 +- 每次上香独立提交。只有服务端返回有效记录 ID 后,次数才+1;请求失败不计数、不播音、不自动重试。网络结果不明时应刷新核对,避免手动重试重复记账。 +- 点亮截止时间为最后一次成功请求对应的点击时间+15秒(不从回包开始重计)。持续点击仅增加次数、延长点亮,不重播;音频自然结束不循环。点亮到期即停止声音、恢复供桌,不回退次数。 +- 页面隐藏/离开销毁音频。返回只恢复剩余点亮,不自动播放。播放错误提示用户,但不撤销已落库记录。 +- 祈愿最多500字;回向任意姓名最多50字+祝愿最多500字。权限、有效绑定由服务端再次验证。成功才清空,失败保留内容。表单提交中防重复,连续上香不节流丢次数。 + +## 已接入接口(JWT,标准 ApiResponse) + +服务前缀 `http://101.43.139.56/hera`。 + +| 接口 | 用途/请求 | +| --- | --- | +| GET `/api/tiangong/items`(新增) | 本人列表:id/name/iconUrl/description、holdingId、active、days、incenseCount。状态与统计来自数据库,无示例持有。 | +| POST `/api/user/virtual-items/offerings`(复用) | `{userVirtualItemId: 本人holdingId, offeringType: 2}` 上香;type=3+`content` 祈愿。返回流水及id。 | +| POST `/api/user/virtual-items/dedications`(新增) | `{userVirtualItemId: 本人holdingId, name, content}` 任意姓名回向。返回流水及id。接收人ID为空,不创建账号、不转移资产。 | + +前端调用:`src/services/tiangong.ts`;状态管理:`src/utils/tiangongStore.ts`。使用服务端持有ID,不猜测数字ID。原型与字典名称精确匹配(财神/武财神、禄星、寿星、文昌星、月老),未配置者禁用,不假装已恭请。账号变更清空缓存,旧响应不能写入新账号。 + +真实 NFC 绑定、解绑、送神不属于本次三项写接口;正式模式不执行本地 Mock 绑定,也不展示示例额度或虚构成功。已有绑定可正常供奉。此前拟定 NFC 契约仍未调用。 + +## 部署边界 + +**前后端代码推送不等于部署:本次未部署远程后端、未操作远程数据库。** + +部署后端前执行 `hera/src/main/resources/db/named-dedication-update.sql`,仅将 `user_virtual_item_transfer.to_user_id` 改为可空,保留数据。`CREATE TABLE IF NOT EXISTS` 不会更新现存表,不能省略。前端构建不能代替后端部署。此前生日偏好迁移也需按对应文档执行。 + +远端无新接口/新表结构时,正式页面提示加载或提交失败,不以 Mock 伪装成功。隔离 H2 测试已验证 Controller→Service→MyBatis→落库,不等同于远端联调。 + +H5演示:`http://127.0.0.1:4173/?avatarDemo=1#/pages/tiangong-detail/index?id=wealth`。仅此显式演示和preview使用内存Mock及明确提示,不上传姓名和祝愿,不代表真实账号。普通地址及微信构建走真实接口。 + +## 开发者工具验收 + +1. 重新编译,后端及SQL部署后,用已绑定神仙的账号登录→天宫→对应详情。无功德入口,上香次数与服务端一致。 +2. 开声→上香:网络出现type=2请求,成功才次数+1、点亮。10秒再点一次,再+1;音频不重播,第二次点击15秒后恢复。 +3. 上香第3秒关闭喇叭,立即无声;第10秒开启,应听到第10秒处剩余音频,不从第3秒接续,次数不变。第15秒音频结束后开启不得再播;第10秒追加上香使供桌仍亮时,也不得重播已结束音频。初始静音上香同样验证。 +4. 祈愿输入内容→确认,type=3成功显示“祈愿已记录”。回向输入任意姓名+祝愿→确认,dedications成功显示“回向已记录”;数据库to_user_id为空,姓名祝愿保留。 +5. 断网或停用绑定:三种提交均不显示成功;上香不增加;表单内容保留。切账号后不能沿用旧持有状态,离开不得继续响。 +6. 真机检查系统静音、音量及来电中断。自动测试验证音量开关、进度推进及结束状态,不能代替听感验收。 + +用户原WAV未改;本地15秒AAC约179KB。使用 createInnerAudioContext 的play/volume/stop/destroy、结束/错误事件及本机存储,不调用真实支付或硬件。 + +## 验证记录 + +- 音频规则调整后103项前端测试通过,类型检查、H5/微信构建、13个原生WXSS编译检查通过。后端沿用上次H2供奉/NFC测试14项、账号回归8项的验证结果,本次未修改后端。 +- 微信产物合计2,022,060 bytes,低于2MiB,后续新增素材需关注余量。 +- 浏览器375×812检查上香计数、开关、回向、祈愿及空值校验通过;无浏览器错误。截图 `/private/tmp/hera-dedication-no-merit.png`。未以浏览器检查替代真机听感和远端联调。 diff --git a/docs/tiangong-login-access.md b/docs/tiangong-login-access.md new file mode 100644 index 0000000..7dccc3b --- /dev/null +++ b/docs/tiangong-login-access.md @@ -0,0 +1,47 @@ +# 天宫登录访问限制 + +## 行为 + +- 真实模式没有登录 token:点击中间天宫入口直接发起微信登录,不切换到神仙内容、不堆叠重复登录。首页、我的与天宫直达路由共用同一套登录提示卡片。 +- 直接打开天宫或敬神/请神详情页:没有权限时只显示登录提示和返回首页入口,不挂载神仙列表、神像场景或业务弹窗。直接进入不强制反复跳转,避免用户按返回键陷入循环。 +- 有 token:同一 token 的资料缓存仍在 30 秒有效期内时直接挂载内容,不先切为 checking,不重复请求资料;没有有效缓存才通过共享资料接口确认。401 清除登录后隐藏内容;网络错误显示重试,不当成登录成功,也不随意删除仍有效的 token。 +- 页面隐藏不再重置可复用的已验证状态;重新显示时检查有效期。隐藏或卸载后的旧异步结果不恢复页面权限,切换账号不能沿用另一个 token 的 allowed 状态。注册未完成、仅取得微信临时会话而尚无登录 token,也不能进入天宫。 +- 必要的异步校验使用天宫轻量场景占位和可用的返回入口,不显示“正在确认登录状态”的整页卡片,不提前挂载神仙资料或业务按钮。 +- 现有 `preview=1` 和 `avatarDemo=1` 仅在 H5 的明确演示环境保留访问,仍沿用隔离 Mock,不创建真实身份、不调用真实天宫写接口;微信端不启用这些查询参数。 +- 登录/注册成功后的落点继续沿用我的/完善资料页,没有增加未约定的返回天宫逻辑。用户随后点击天宫即可进入。 + +## 接口边界 + +不新增 REST 接口。复用已存在且需要 Bearer token 的 GET `/api/user/profile` 校验,基址按部署配置默认使用 `http://101.43.139.56/hera`。本次没有把天宫 Mock 接口改成真实后端,也不以界面守卫代替服务端鉴权。 + +## 验收 + +1. 在微信开发者工具以未登录状态进入首页或我的,点击登录/注册或天宫入口:直接调用微信登录;不能看到任何神仙,连续点击不重复发起登录。 +2. 未登录直达 `pages/fortune/index` 或 `pages/tiangong-detail/index?id=wealth`:只出现登录提示,不能操作恭请、上香、祈愿或其他业务按钮。 +3. 正常完成登录/注册,重新点击天宫:资料校验通过后可进入;首页、我的的导航不受影响。 +4. 登录过期返回 401 后:天宫和详情内容隐藏,重新登录后恢复。断网导致校验失败:显示重新加载和返回首页,不展示旧内容。 +5. H5 普通地址不带演示参数时执行同样拦截;H5 点击登录只提示在微信环境完成,不伪造 code、不再打开“那吉”品牌中间页。明确的演示 URL 保留原型预览。 + +自动测试覆盖导航拦截、重复点击、登录失败重试、无 token 不请求资料、真实会话校验、401、网络错误、隐藏/卸载后的异步失效,以及直达页面不挂载业务内容。 + +## 本次验证 + +- 全量前端测试 83 项通过,TypeScript 检查、H5 构建、微信小程序构建通过;13 个 WXSS 文件通过微信原生编译器检查。 +- 浏览器实测:未登录首页和我的显示相同卡片,H5 登录入口不再跳品牌页;冷启动天宫列表和详情路由仅展示登录提示;独立头像演示模式仍展示隔离 Mock。 +- 小屏视口下检查统一登录提示、操作按钮与底部导航,无遮挡。截图保存在 `/private/tmp/hera-unified-login.png`。 +- 未在浏览器伪造微信登录,也未验证真实微信授权流程;有效会话和过期会话分支由自动测试覆盖。本次未修改后端、未提交或推送代码。 + +## 锁定页与精简登录流程 + +- 未绑定任意神仙时,首页和我的元素报告使用固定高度的锁定首屏,裁切长报告并拦截触摸滚动。绑定弹窗、返回、底部导航仍可操作;绑定后移除限制,恢复报告滚动。 +- 微信入口直接执行 `wx.login` 和 POST `/api/auth/wx-login`。已注册的响应直接沿用原有登录成功落点;未绑定手机号的响应仅把临时会话保留在内存,再进入必要的手机号表单,不放入 URL 或持久存储。 +- 手机号验证仍使用 POST `/api/auth/sms` 与 POST `/api/auth/bind-phone`。品牌名称、“一触即吉”和二次微信登录点击已从正常入口流程移除,不绕过后端注册和手机号验证。 +- 微信开发者工具验收:未绑定时在首页和“我的→我的元素”上下滑动,页面不位移;点击绑定/取消仍有效,绑定一个神仙后可正常滚动。分别从三个入口登录,已注册用户不再看到品牌中间页,新用户才显示手机号与验证码表单。 +- 浏览器已用隔离 Mock 验证解绑→锁定→绑定→恢复滚动;没有操作真实绑定或真实短信。截图:`/private/tmp/hera-locked-home.png`、`/private/tmp/hera-unified-login.png`。 + +## 详情页无登录检查闪屏 + +- 微信开发者工具登录后进入天宫,再点财神详情、返回、再次进入:资料缓存有效时应直接看到详情,不出现登录检查页。 +- 超过资料缓存有效期、冷启动只有 token 时,仍先校验,使用轻量占位;401 应显示登录入口,断网应显示重试,不能展示未验证的内容。 +- 自动测试覆盖有效缓存首帧允许且不发请求、隐藏/返回不闪检查态、缓存过期必须重新验证、切换账号/退出不能复用旧状态、轻量占位不渲染登录检查卡片。 +- 浏览器已验证隔离 Mock 中详情进入和返回,以及真实未登录直达详情仍被拦截;未伪造登录凭证。真实会话缓存/延迟分支通过自动测试验证,仍需微信端实际网络环境验收。截图:`/private/tmp/hera-tiangong-smooth-detail.png`。 diff --git a/package.json b/package.json index fd99d41..21d5fc0 100644 --- a/package.json +++ b/package.json @@ -7,6 +7,7 @@ "test:wxss": "node --test scripts/wxssCompatibility.test.cjs", "test:navigation": "node --test scripts/navigation.test.cjs scripts/frontendPreview.test.cjs", "test:tiangong": "node --test scripts/tiangong.test.cjs", + "test:tiangong-access": "node --test scripts/tiangongAccess.test.cjs scripts/navigation.test.cjs", "test:elements": "node --test scripts/fiveElements.test.cjs scripts/elementIcon.test.cjs", "test:zodiac": "node --test scripts/zodiac.test.cjs", "test:zodiac-weekly": "node --test scripts/zodiacWeekly.test.cjs", diff --git a/scripts/accountIntegration.test.cjs b/scripts/accountIntegration.test.cjs index a16212a..9df2ef2 100644 --- a/scripts/accountIntegration.test.cjs +++ b/scripts/accountIntegration.test.cjs @@ -81,6 +81,35 @@ test('无登录凭证不发送个人资料请求;401清除缓存并同步所 unsubscribe() }) +test('生日阳历日期与农历显示偏好一起保存并从接口回显', async () => { + const ctx = setup() + const original = await ctx.service.api.profile() + const form = { ...ctx.editing.toEditableProfile(original), birthdayCalendar: 'lunar' } + const saved = await ctx.editing.saveProfileEdits(original, form, '', ctx.service.api, () => {}) + const request = ctx.calls.find(call => call.method === 'PUT') + assert.equal(request.data.birthday, original.birthday) + assert.equal(request.data.birthdayCalendar, 'lunar') + assert.equal(saved.profile.birthdayCalendar, 'lunar') + const reloaded = ctx.editing.toEditableProfile(await ctx.service.api.profile(true)) + assert.equal(reloaded.birthdayCalendar, 'lunar') + assert.equal(reloaded.birthday, original.birthday) + const before = ctx.calls.length + const unchanged = await ctx.editing.saveProfileEdits(saved.profile, reloaded, '', ctx.service.api, () => {}) + assert.equal(unchanged.changed, false) + assert.equal(ctx.calls.length, before) +}) + +test('登录校验只复用同token的有效资料,账号切换与退出后立即失效', async () => { + const ctx = setup() + assert.equal(ctx.service.getFreshCachedProfile(), null) + await ctx.service.api.profile() + assert.equal(ctx.service.getFreshCachedProfile().id, fullProfile.id) + ctx.storage.token = 'another-session' + assert.equal(ctx.service.getFreshCachedProfile(), null) + ctx.service.clearLogin() + assert.equal(ctx.service.getFreshCachedProfile(), null) +}) + test('头像经专用COS后端接口上传,Bearer字段正确,禁止H5跨域Cookie', async () => { const ctx = setup() const updates = [] diff --git a/scripts/avatarEntry.test.cjs b/scripts/avatarEntry.test.cjs new file mode 100644 index 0000000..c8342e0 --- /dev/null +++ b/scripts/avatarEntry.test.cjs @@ -0,0 +1,71 @@ +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') +const profile = { nickname: '测试', gender: '男', birthday: '1998-06-18', birthdayCalendar: 'solar', birthHour: '辰时', province: '北京市', city: '北京市', district: '朝阳区', remainingEdits: 5 } + +function render(env, sheet = false) { + const exports = {}, updates = [], media = [] + let index = 0 + const source = fs.readFileSync(path.join(__dirname, '../src/pages/profile-edit/index.tsx'), 'utf8') + vm.runInNewContext(ts.transpileModule(source, { compilerOptions: { module: ts.ModuleKind.CommonJS, + target: ts.ScriptTarget.ES2019, jsx: ts.JsxEmit.ReactJSX } }).outputText, { + exports, process: { env: { TARO_ENV: env } }, require: id => { + if (id === 'react/jsx-runtime') return require(id) + if (id === 'react') return { useEffect: () => {}, useRef: initial => ({ current: initial }), useState: initial => { + const current = index++ + let value = typeof initial === 'function' ? initial() : initial + if (value === null || (value && typeof value === 'object' && 'nickname' in value)) value = profile + if (initial === true) value = false + if (current === 5) value = sheet // avatarSheetOpen + return [value, next => updates.push([current, next])] + } } + if (id === '@tarojs/taro') return { useRouter: () => ({ params: {} }), default: { + chooseMedia: async options => { media.push(options); return { tempFiles: [{ tempFilePath: 'temp:album', size: 10 }] } }, showToast: () => {} + } } + if (id === '@tarojs/components') return { View: 'View', Text: 'Text', Button: 'Button', Input: 'Input', Picker: 'Picker' } + if (id === 'china-area-data') return { default: {} } + if (id.endsWith('/NavBar')) return { NavBar: 'NavBar' } + if (id.endsWith('/UserAvatar')) return { UserAvatar: 'UserAvatar' } + if (id.endsWith('/BirthdayPicker')) return { BirthdayPicker: 'BirthdayPicker' } + if (id.endsWith('/frontendPreview')) return { isFrontendPreview: () => false } + if (id.endsWith('/avatarDemo')) return { isAvatarDemo: () => false } + return {} + } + }) + const collect = node => { + if (!node || typeof node !== 'object') return [] + if (Array.isArray(node)) return node.flatMap(collect) + return [node, ...collect(node.props?.children)] + } + return { nodes: collect(exports.default()), updates, media } +} + +test('微信端头像本身直接绑定官方chooseAvatar,不再弹自定义菜单', () => { + const h = render('weapp', true) + const button = h.nodes.find(node => node.props?.className === 'avatar-button') + assert.equal(button.props.openType, 'chooseAvatar') + assert.equal(button.props.onClick, undefined) + assert.equal(typeof button.props.onChooseAvatar, 'function') + assert.ok(!h.nodes.some(node => node.props?.className === 'avatar-mask')) + button.props.onChooseAvatar({ detail: { avatarUrl: 'temp:wechat-avatar' } }) + assert.equal(h.media.length, 0) + assert.ok(h.updates.some(([, value]) => value === 'temp:wechat-avatar')) + assert.ok(h.updates.some(([index, value]) => index === 5 && value === false)) +}) + +test('H5保留相册拍照菜单,不伪造微信官方头像选择能力', async () => { + const h = render('h5') + const button = h.nodes.find(node => node.props?.className === 'avatar-button') + assert.equal(button.props.openType, undefined) + assert.equal(button.props.onChooseAvatar, undefined) + button.props.onClick() + assert.ok(h.updates.some(([index, value]) => index === 5 && value === true)) + const opened = render('h5', true) + const album = opened.nodes.find(node => node.props?.children === '从相册选择') + await album.props.onClick() + assert.equal(opened.media.length, 1) + assert.equal(opened.media[0].sourceType[0], 'album') +}) diff --git a/scripts/birthdayCalendar.test.cjs b/scripts/birthdayCalendar.test.cjs new file mode 100644 index 0000000..3bd13dd --- /dev/null +++ b/scripts/birthdayCalendar.test.cjs @@ -0,0 +1,97 @@ +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') +const exports_ = {} +vm.runInNewContext(ts.transpileModule(fs.readFileSync(path.join(__dirname, '../src/utils/birthdayCalendar.ts'), 'utf8'), { + compilerOptions: { module: ts.ModuleKind.CommonJS, target: ts.ScriptTarget.ES2019 } +}).outputText, { exports: exports_, require }) +const { solarToLunarBirthday, lunarBirthdayToSolar, lunarBirthdayModel, changeLunarBirthdayColumn, formatLunarBirthday } = exports_ +const max = '2026-10-18' + +test('阳历农历准确往返,闰月单列而不是重复普通月份', () => { + for (const solar of ['1900-01-01', '1998-06-18', '2000-02-05', '2023-03-22', '2024-02-29', max]) { + assert.equal(lunarBirthdayToSolar(solarToLunarBirthday(solar)), solar) + } + const leap = solarToLunarBirthday('2023-03-22') + assert.equal(leap.year, 2023); assert.equal(leap.month, -2); assert.equal(leap.day, 1) + assert.match(formatLunarBirthday('2023-03-22'), /闰二月初一/) + const model = lunarBirthdayModel(leap, max) + assert.ok(model.months.some(month => month.value === 2)) + assert.ok(model.months.some(month => month.value === -2 && month.label === '闰二月')) +}) + +test('小月天数、无闰月年份联动纠正,不生成无效生日', () => { + const original = lunarBirthdayModel({ year: 2023, month: 2, day: 30 }, max) + const leapIndex = original.months.findIndex(month => month.value === -2) + const leap = changeLunarBirthdayColumn(original, 1, leapIndex, max) + assert.equal(leap.month, -2); assert.equal(leap.day, 29) + const leapModel = lunarBirthdayModel(leap, max) + const next = changeLunarBirthdayColumn(leapModel, 0, leapModel.years.indexOf(2024), max) + assert.equal(next.month, 2) + assert.ok(lunarBirthdayToSolar(next)) + assert.equal(lunarBirthdayToSolar({ year: 2023, month: -2, day: 30 }), null) + assert.equal(lunarBirthdayToSolar({ year: 2024, month: -2, day: 1 }), null) +}) + +test('边界年月日只包含1900至今天,农历跨年仍正确', () => { + for (const solar of ['1900-01-01', max]) { + const model = lunarBirthdayModel(solarToLunarBirthday(solar), max) + for (const month of model.months) for (const day of month.days) { + const candidate = lunarBirthdayToSolar({ year: model.selection.year, month: month.value, day }) + assert.ok(candidate >= '1900-01-01' && candidate <= max) + } + } + const current = lunarBirthdayModel({ year: 2026, month: 12, day: 30 }, max) + assert.ok(lunarBirthdayToSolar(current.selection) <= max) + assert.equal(solarToLunarBirthday('2026-02-30'), null) + assert.equal(solarToLunarBirthday('2026-2-1'), null) +}) + +test('同一生日两种输入不改变生肖与日主计算日期', () => { + for (const solar of ['2000-02-04', '2000-02-05', '2023-03-22']) { + const lunar = solarToLunarBirthday(solar) + const input = lunarBirthdayModel(lunar, max) + assert.equal(lunarBirthdayToSolar(input.selection), solar) + } +}) + +test('微信头像选择仅接收系统结果,不会再次调用媒体选择', () => { + const source = fs.readFileSync(path.join(__dirname, '../src/pages/profile-edit/index.tsx'), 'utf8') + assert.equal((source.match(/\? 'chooseAvatar' : undefined/g) || []).length, 1) + const callback = source.match(/const handleWechatAvatar = [\s\S]*?\n }/)[0] + assert.match(callback, /useAvatar\(event.detail.avatarUrl\)/) + assert.doesNotMatch(callback, /chooseMedia|chooseFrom|chooseImage/) + assert.doesNotMatch(source, /微信头像选择|wechat-avatar-action/) +}) + +test('日期控件回显农历偏好,切换历法不修改实际生日或触发保存', () => { + const component = {} + const file = fs.readFileSync(path.join(__dirname, '../src/components/BirthdayPicker.tsx'), 'utf8') + vm.runInNewContext(ts.transpileModule(file, { compilerOptions: { module: ts.ModuleKind.CommonJS, + target: ts.ScriptTarget.ES2019, jsx: ts.JsxEmit.ReactJSX } }).outputText, { exports: component, require: id => { + if (id === 'react') return { useState: initial => [initial(), () => {}], useEffect: () => {}, useMemo: fn => fn() } + if (id.endsWith('/birthdayCalendar')) return exports_ + if (id === '@tarojs/components') return { View: 'View', Text: 'Text', Button: 'Button', Picker: 'Picker' } + return require(id) + } }) + const modes = [], dates = [] + const tree = component.BirthdayPicker({ value: '2023-03-22', calendar: 'lunar', onChange: value => dates.push(value), onCalendarChange: mode => modes.push(mode) }) + const collect = node => { + if (!node || typeof node !== 'object') return [] + if (Array.isArray(node)) return node.flatMap(collect) + return [node, ...collect(node.props?.children)] + } + const nodes = collect(tree) + const lunar = nodes.find(node => node.props?.['aria-label'] === '选择农历') + assert.match(lunar.props.className, /active/) + nodes.find(node => node.props?.['aria-label'] === '选择阳历').props.onClick() + assert.deepEqual(modes, ['solar']); assert.deepEqual(dates, []) + const picker = nodes.find(node => node.type === 'Picker') + assert.equal(picker.props.mode, 'multiSelector') + assert.ok(picker.props.range[1].includes('闰二月')) + picker.props.onCancel() + assert.deepEqual(dates, []) +}) diff --git a/scripts/incenseRitual.test.cjs b/scripts/incenseRitual.test.cjs new file mode 100644 index 0000000..d8cd7c6 --- /dev/null +++ b/scripts/incenseRitual.test.cjs @@ -0,0 +1,241 @@ +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') +const root = path.resolve(__dirname, '..') +function load(file, dependencies = {}, globals = {}) { + const exports = {} + vm.runInNewContext(ts.transpileModule(fs.readFileSync(path.join(root, file), 'utf8'), { + compilerOptions: { module: ts.ModuleKind.CommonJS, target: ts.ScriptTarget.ES2019 } + }).outputText, { exports, require: id => dependencies[id], setTimeout, clearTimeout, ...globals }) + return exports +} +const ritualModule = load('src/utils/incenseRitual.ts') +const { createIncenseRitual, INCENSE_DURATION_MS } = ritualModule +const { createTiangongMock } = load('src/utils/tiangongMock.ts', { './incenseRitual': ritualModule }) + +function harness() { + let time = 0, nextTimer = 0, enabled = true, errors = 0, refreshed = 0, creationFails = false + const timers = new Map(), audios = [] + const mock = createTiangongMock(() => time) + const scheduler = { + now: () => time, + schedule: (callback, delay) => { const id = ++nextTimer; timers.set(id, { callback, at: time + delay }); return id }, + cancel: id => { timers.delete(id) } + } + const create = () => createIncenseRitual({ + ...scheduler, + getDeadline: () => mock.snapshot().deities.wealth.incenseUntil, + recordIncense: () => { mock.incense('wealth') }, + refresh: () => { refreshed++; mock.refreshIncense('wealth') }, + soundEnabled: () => enabled, + createAudio: () => { + if (creationFails) throw new Error('unavailable') + const startedAt = time + const audio = { plays: 0, pauses: 0, stops: 0, destroys: 0, volume: 1, + get currentTime() { return Math.min(15, (time - startedAt) / 1000) }, + play() { this.plays++ }, pause() { this.pauses++ }, stop() { this.stops++ }, destroy() { this.destroys++ }, + onEnded(callback) { this.ended = callback }, onError(callback) { this.error = callback } } + audios.push(audio) + return audio + }, + onAudioError: () => { errors++ } + }) + const ritual = create() + const advance = milliseconds => { + const target = time + milliseconds + while (true) { + const next = [...timers.entries()].filter(([, timer]) => timer.at <= target).sort((a, b) => a[1].at - b[1].at)[0] + if (!next) break + time = next[1].at; timers.delete(next[0]); next[1].callback() + } + time = target + } + return { ritual, create, mock, audios, advance, timers, + mute: value => { enabled = value; if (!value) ritual.mute(); else ritual.resume() }, + creationFails: value => { creationFails = value }, errors: () => errors, refreshed: () => refreshed } +} + +test('首次上香播放一次,15秒后恢复供桌,次数不回退', () => { + const h = harness() + h.ritual.tap() + assert.equal(h.mock.snapshot().deities.wealth.incenseCount, 60) + assert.equal(h.mock.snapshot().deities.wealth.lit, true) + assert.equal(h.audios.length, 1); assert.equal(h.audios[0].plays, 1) + h.advance(INCENSE_DURATION_MS - 1) + assert.equal(h.mock.snapshot().deities.wealth.lit, true) + h.advance(1) + assert.equal(h.mock.snapshot().deities.wealth.lit, false) + assert.equal(h.mock.snapshot().deities.wealth.incenseCount, 60) + assert.equal(h.refreshed(), 1) + assert.equal(h.audios[0].destroys, 1) +}) + +test('重复上香每次+1并按最后点击延长15秒,但音频不重播或续播', () => { + const h = harness() + h.ritual.tap(); h.advance(10000); h.ritual.tap() + assert.equal(h.mock.snapshot().deities.wealth.incenseUntil, 25000) + assert.equal(h.mock.snapshot().deities.wealth.incenseCount, 61) + h.advance(5000) + assert.equal(h.audios[0].destroys, 1) + assert.equal(h.mock.snapshot().deities.wealth.lit, true) + h.advance(5000); h.ritual.tap() + assert.equal(h.audios.length, 1) + h.advance(14999); assert.equal(h.mock.snapshot().deities.wealth.lit, true) + h.advance(1); assert.equal(h.mock.snapshot().deities.wealth.lit, false) + assert.equal(h.mock.snapshot().deities.wealth.incenseCount, 62) + h.ritual.tap(); assert.equal(h.audios.length, 2) +}) + +test('关闭立即静音但进度继续,重新开启接实际进度,不重播不增加次数', () => { + const h = harness() + h.ritual.tap(); h.advance(3000); h.mute(false) + assert.equal(h.audios[0].volume, 0); assert.equal(h.audios[0].pauses, 0); assert.equal(h.audios[0].destroys, 0) + h.advance(2000); h.mute(true) + assert.equal(h.audios[0].volume, 1); assert.equal(h.audios[0].currentTime, 5) + assert.equal(h.audios[0].plays, 1); assert.equal(h.mock.snapshot().deities.wealth.incenseCount, 60) + h.ritual.tap(); assert.equal(h.audios.length, 1) + h.advance(15000); h.ritual.tap(); assert.equal(h.audios.length, 2) +}) + +test('静音上香以音量0推进,轮次内开启按实际进度出声,过期不补播', () => { + const h = harness() + h.mute(false); h.ritual.tap() + assert.equal(h.audios.length, 1); assert.equal(h.audios[0].volume, 0) + assert.equal(h.mock.snapshot().deities.wealth.incenseCount, 60) + h.advance(7000); h.mute(true); h.ritual.tap(); assert.equal(h.audios.length, 1) + assert.equal(h.audios[0].currentTime, 7); assert.equal(h.audios[0].volume, 1) + h.mute(false); h.advance(15000); h.mute(true); assert.equal(h.audios.length, 1) + h.ritual.tap(); assert.equal(h.audios.length, 2) +}) + +test('播放失败不回退计数、不重复播放,也不妨碍15秒状态恢复', () => { + const h = harness() + h.ritual.tap(); h.audios[0].error() + assert.equal(h.errors(), 1); assert.equal(h.audios[0].destroys, 1) + h.audios[0].error(); assert.equal(h.errors(), 1) + h.ritual.tap(); assert.equal(h.audios.length, 1) + h.advance(15000); assert.equal(h.mock.snapshot().deities.wealth.lit, false) + h.creationFails(true); h.ritual.tap(); assert.equal(h.errors(), 2) + assert.equal(h.mock.snapshot().deities.wealth.incenseCount, 62) + h.advance(15000); assert.equal(h.mock.snapshot().deities.wealth.lit, false) +}) + +test('静音期间自然结束,延长点亮也不能让开关重新播放已结束的音频', () => { + const h = harness() + h.ritual.tap(); h.advance(3000); h.mute(false) + h.advance(7000); h.ritual.tap(); h.advance(5000) + assert.equal(h.audios[0].destroys, 1); assert.equal(h.mock.snapshot().deities.wealth.lit, true) + h.mute(false); h.mute(true); assert.equal(h.audios.length, 1) + assert.equal(h.audios[0].plays, 1) + h.advance(10000); h.ritual.tap(); assert.equal(h.audios.length, 2) +}) + +test('异步失败不播音,离开后成功回包也不产生后台声音', async () => { + let resolve, reject, deadline = 0, creations = 0 + const response = () => new Promise((ok, fail) => { resolve = ok; reject = fail }) + const ritual = createIncenseRitual({ now: () => 1000, getDeadline: () => deadline, + recordIncense: response, refresh() {}, soundEnabled: () => true, + createAudio: () => { creations++; throw new Error('不应该创建') }, onAudioError() {} }) + const failed = ritual.tap(); reject(new Error('失败')); await assert.rejects(failed, /失败/) + assert.equal(creations, 0) + const pending = ritual.tap(); ritual.dispose(); deadline = 16000; resolve({ startsRound: true }); await pending + assert.equal(creations, 0) +}) + +test('音频结束回调被延迟时,重新开声仍按15秒截止时间判断,不恢复过期声音', () => { + const h = harness() + h.ritual.tap(); h.advance(10000); h.ritual.tap(); h.mute(false) + h.timers.clear(); h.advance(6000); h.mute(true) + assert.equal(h.mock.snapshot().deities.wealth.lit, true) + assert.equal(h.audios[0].volume, 0); assert.equal(h.audios[0].destroys, 1) + assert.equal(h.audios[0].plays, 1); assert.equal(h.audios.length, 1) + h.ritual.dispose() +}) + +test('音频自然结束不提前熄香,旧回调不会停止下一轮音频', () => { + const h = harness() + h.ritual.tap(); h.advance(12000); h.audios[0].ended() + assert.equal(h.mock.snapshot().deities.wealth.lit, true) + h.advance(3000); h.ritual.tap() + h.audios[0].ended(); h.audios[0].error() + assert.equal(h.audios[1].stops, 0); assert.equal(h.errors(), 0) +}) + +test('离开清理声音和定时器,返回只恢复剩余视觉计时,不自动播放', () => { + const h = harness() + h.ritual.tap(); h.advance(3000); h.ritual.dispose() + assert.equal(h.timers.size, 0); assert.equal(h.audios[0].destroys, 1) + h.advance(2000) + const returning = h.create(); returning.sync() + assert.equal(h.audios.length, 1) + assert.equal(h.mock.snapshot().deities.wealth.lit, true) + h.advance(10000); assert.equal(h.mock.snapshot().deities.wealth.lit, false) + returning.tap(); assert.equal(h.audios.length, 2) + returning.dispose() +}) + +test('后台定时器延迟时按绝对截止时间校正,解绑与重置清除点亮状态', () => { + const h = harness() + h.ritual.tap(); h.ritual.dispose(); h.advance(20000) + assert.equal(h.mock.snapshot().deities.wealth.lit, false) + assert.equal(h.mock.snapshot().deities.wealth.incenseCount, 60) + h.mock.incense('wealth'); h.mock.unbind('wealth') + assert.equal(h.mock.snapshot().deities.wealth.incenseUntil, 0) + h.mock.invite('wealth'); h.mock.incense('wealth'); h.mock.reset() + assert.equal(h.mock.snapshot().deities.wealth.incenseUntil, 0) +}) + +test('无恭请权限时不创建声音或定时器,不允许额外扣款或奖励', () => { + const h = harness() + h.mock.unbind('wealth') + assert.throws(() => h.ritual.tap(), /未恭请/) + assert.equal(h.audios.length, 0); assert.equal(h.timers.size, 0) + assert.equal('balance' in h.mock.snapshot(), false) +}) + +test('喇叭默认开启、开关跨详情记忆,微信音频懒创建且离开销毁', () => { + const storage = {}, audio = [], cleanups = [] + const instantiate = () => { + let state, show, hide, stateIndex = 0 + const mock = createTiangongMock() + const context = load('src/hooks/useIncenseRitual.ts', { + react: { useState: initial => { const index = stateIndex++; const value = typeof initial === 'function' ? initial() : initial; if (!index) state = value; return [value, value => { if (!index) state = value }] }, useRef: initial => ({ current: initial }), useEffect: fn => { cleanups.push(fn()) } }, + '@tarojs/taro': { useDidShow: fn => { show = fn }, useDidHide: fn => { hide = fn }, default: { + getStorageSync: key => storage[key], setStorageSync: (key, value) => { storage[key] = value }, showToast: () => {}, + createInnerAudioContext: () => { const item = { plays: 0, destroys: 0, play() { this.plays++ }, pause() {}, stop() {}, destroy() { this.destroys++ }, onEnded() {}, onError() {} }; audio.push(item); return item } + } }, + '../services/tiangong': { tiangongSession: { ...mock, incense: id => { const startsRound = !mock.snapshot().deities[id].lit; mock.incense(id); return { startsRound } } } }, + '../utils/incenseRitual': ritualModule, + '../assets/tiangong/incense-yinqing.m4a': { default: 'assets/incense-yinqing.m4a' } + }, { process: { env: { TARO_ENV: 'weapp' } } }) + const result = context.useIncenseRitual('wealth') + return { result, show: () => show(), hide: () => hide(), state: () => state } + } + try { + const first = instantiate(); first.show() + assert.equal(first.state(), true); assert.equal(audio.length, 0) + first.result.toggleSound(); assert.equal(first.state(), false) + first.hide() + const second = instantiate(); second.show() + assert.equal(second.state(), false) + second.result.incense(); assert.equal(audio.length, 1); assert.equal(audio[0].volume, 0) + second.result.toggleSound(); assert.equal(second.state(), true) + second.result.incense(); assert.equal(audio.length, 1) + second.hide() + const third = instantiate(); third.show(); third.result.incense(); third.result.incense() + assert.equal(audio.length, 2); assert.equal(audio[1].plays, 1) + assert.equal(audio[1].src, '/assets/incense-yinqing.m4a') + assert.equal(audio[1].autoplay, false); assert.equal(audio[1].loop, false) + third.hide(); assert.equal(audio[1].destroys, 1) + } finally { cleanups.forEach(fn => fn?.()) } +}) + +test('打包音频为用户素材转码的本地M4A,大小低于200KB,原WAV不进入主包', () => { + const bytes = fs.readFileSync(path.join(root, 'src/assets/tiangong/incense-yinqing.m4a')) + assert.ok(bytes.length > 100000 && bytes.length < 200 * 1024) + assert.equal(bytes.subarray(4, 8).toString(), 'ftyp') + assert.equal(fs.existsSync(path.join(root, 'src/assets/tiangong/incense-yinqing.wav')), false) +}) diff --git a/scripts/loginPresentation.test.cjs b/scripts/loginPresentation.test.cjs new file mode 100644 index 0000000..b83b0ed --- /dev/null +++ b/scripts/loginPresentation.test.cjs @@ -0,0 +1,86 @@ +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') +const root = path.resolve(__dirname, '..') +const read = file => fs.readFileSync(path.join(root, file), 'utf8') + +function page(file, { guest = false, bound = false, element = false, routes = [] } = {}) { + const profile = guest ? null : { birthday: '1998-06-18', birthHour: '辰时' } + const factor = { description: '测试' } + const report = { scores: [], dayMaster: '甲', masterElement: '木', strength: '偏弱', strengthScore: 20, + pillars: [], favorable: '水木', unfavorable: '土', analysis: { season: factor, roots: factor, support: factor } } + const day = { label: '今日', date: '2026-10-18' } + const exports = {} + vm.runInNewContext(ts.transpileModule(read(file), { compilerOptions: { + module: ts.ModuleKind.CommonJS, target: ts.ScriptTarget.ES2019, jsx: ts.JsxEmit.ReactJSX + } }).outputText, { exports, require: id => { + if (id === 'react/jsx-runtime') return require(id) + if (id === 'react') return { useEffect: () => {}, useMemo: fn => fn(), useRef: value => ({ current: value }), + useState: value => [element && value === 'home' ? 'element' : typeof value === 'function' ? value() : value, () => {}] } + if (id === '@tarojs/taro') return { useDidShow: () => {} } + if (id === '@tarojs/components') return { View: 'View', Text: 'Text', Button: 'Button', Image: 'Image' } + if (id.endsWith('/LoginGate')) return { LoginGate: 'shared-login-gate' } + if (id.endsWith('/tabNavigation')) return { switchMainTab: (target, active) => routes.push([target, active]) } + if (id.endsWith('/useTiangongSnapshot')) return { useTiangongSnapshot: () => ({}) } + if (id.endsWith('/tiangongMock')) return { hasBoundDeity: () => bound } + if (id.endsWith('/tiangong')) return { deityCatalog: [] } + if (id.endsWith('/frontendPreview')) return { isFrontendPreview: () => false } + if (id.endsWith('/avatarDemo')) return { isAvatarDemo: () => false } + if (id.endsWith('/request')) return { getCachedProfile: () => profile, getToken: () => guest ? '' : 'test' } + if (id.endsWith('/zodiacWeekly')) return { getBeijingDate: () => '2026-10-18', calculateWeeklyZodiacFortune: () => null } + if (id.endsWith('/zodiac')) return { calculateZodiac: () => null } + if (id.endsWith('/fiveElements')) return { calculateFiveElements: () => report } + if (id.endsWith('/homeOverview')) return { HOME_DIMENSION_IDS: [], generateHomeOverview: () => ({ days: [day, day, day], dimensions: [], luckyColors: [], luckyNumbers: [], luckyHours: [] }) } + return {} + } }) + return exports.default() +} + +test('首页和我的未登录入口使用同一登录组件;天宫包装也复用它', () => { + assert.equal(page('src/pages/home/index.tsx', { guest: true }).type, 'shared-login-gate') + assert.equal(page('src/pages/my/index.tsx', { guest: true }).type, 'shared-login-gate') + assert.match(read('src/components/TiangongLoginGate.tsx'), /return { + const routes = [], tree = page('src/pages/home/index.tsx', { routes }) + function find(node) { + if (!node || typeof node !== 'object') return null + if (node.props?.['aria-label'] === '前往我的页面') return node + const children = node.props?.children + return (Array.isArray(children) ? children : [children]).map(find).find(Boolean) + } + const avatar = find(tree) + assert.ok(avatar) + avatar.props.onClick() + assert.deepEqual(routes, [['my', 'home']]) +}) + +test('未绑定首页与元素报告固定首屏;绑定后移除锁定类恢复滚动', () => { + for (const [file, element] of [['src/pages/home/index.tsx', false], ['src/pages/my/index.tsx', true]]) { + const locked = page(file, { bound: false, element }), unlocked = page(file, { bound: true, element }) + assert.match(locked.props.className, /binding-viewport-locked/) + assert.equal(locked.props.catchMove, true) + assert.doesNotMatch(unlocked.props.className, /binding-viewport-locked/) + assert.equal(unlocked.props.catchMove, false) + } + const runner = require.resolve('@tarojs/webpack5-runner') + const sass = require(require.resolve('sass', { paths: [runner] })) + const postcss = require(require.resolve('postcss', { paths: [runner] })) + const css = sass.renderSync({ file: path.join(root, 'src/components/DeityBinding.scss') }).css.toString() + let checked = false + postcss.parse(css).walkRules(rule => { + if (!rule.selector.includes('.home-page.binding-viewport-locked')) return + const declarations = Object.fromEntries(rule.nodes.filter(node => node.type === 'decl').map(node => [node.prop, node.value])) + assert.equal(declarations.position, 'fixed') + assert.equal(declarations.overflow, 'hidden') + assert.equal(declarations.height, '100%') + checked = true + }) + assert.ok(checked) + assert.match(read('src/components/DeityBinding.tsx'), /className='binding-gate' catchMove/) +}) diff --git a/scripts/navigation.test.cjs b/scripts/navigation.test.cjs index f8156a9..5926bca 100644 --- a/scripts/navigation.test.cjs +++ b/scripts/navigation.test.cjs @@ -23,7 +23,7 @@ test('三个主页面均注册为Tab,切换不使用push/redirect', () => { test('连续点击只切换一次,完成或失败后均可继续点击', async () => { const urls = [], notices = [] let complete - const { switchMainTab } = load('src/services/tabNavigation.ts', () => ({ default: { + const { switchMainTab } = load('src/services/tabNavigation.ts', id => id === './loginAccess' ? { hasLoginAccess: () => true } : ({ default: { switchTab: ({ url }) => { urls.push(url); return new Promise(resolve => { complete = resolve }) }, showToast: value => notices.push(value.title) } })) @@ -36,7 +36,7 @@ test('连续点击只切换一次,完成或失败后均可继续点击', async const next = switchMainTab('my', 'fortune') complete(); await next assert.deepEqual(urls, ['/pages/fortune/index', '/pages/my/index']) - const failing = load('src/services/tabNavigation.ts', () => ({ default: { + const failing = load('src/services/tabNavigation.ts', id => id === './loginAccess' ? { hasLoginAccess: () => true } : ({ default: { switchTab: () => Promise.reject(new Error('offline')), showToast: value => notices.push(value.title) } })) await failing.switchMainTab('my') @@ -50,8 +50,10 @@ test('资料缓存合并并发请求,过期保留快照并重取;失败可 const [a,b] = await Promise.all([cache.load('a', loader), cache.load('a', loader)]) assert.equal(a, b); assert.equal(calls, 1) await cache.load('a', loader); assert.equal(calls, 1) + assert.equal(cache.peekFresh('a').nickname, 'A') now = 31 assert.equal(cache.peek('a').nickname, 'A') + assert.equal(cache.peekFresh('a'), undefined) await assert.rejects(cache.load('a', async () => { throw new Error('offline') }), /offline/) await cache.load('a', loader); assert.equal(calls, 2) await cache.load('a', loader, true); assert.equal(calls, 3) @@ -65,6 +67,7 @@ test('保存后的新资料不会被旧请求覆盖,不同账号不共用缓 finish({ nickname: 'Old' }) assert.equal((await old).nickname, 'New') assert.equal(cache.peek('b'), undefined) + assert.equal(cache.peekFresh('b'), undefined) let resolveA const readA = cache.load('a', () => new Promise(resolve => { resolveA = resolve })) await Promise.resolve() diff --git a/scripts/tiangong.test.cjs b/scripts/tiangong.test.cjs index b7285f9..50c1bb1 100644 --- a/scripts/tiangong.test.cjs +++ b/scripts/tiangong.test.cjs @@ -7,6 +7,10 @@ const ts = require('typescript') const root = path.resolve(__dirname, '..') const filename = path.join(root, 'src/utils/tiangongMock.ts') const loaded = new Module(filename, module) +const ritualFilename = path.join(root, 'src/utils/incenseRitual.ts') +const ritual = new Module(ritualFilename, module) +ritual._compile(ts.transpileModule(fs.readFileSync(ritualFilename, 'utf8'), { compilerOptions: { module: ts.ModuleKind.CommonJS, target: ts.ScriptTarget.ES2019 } }).outputText, ritualFilename) +loaded.require = id => id === './incenseRitual' ? ritual.exports : Module.prototype.require.call(loaded, id) loaded._compile(ts.transpileModule(fs.readFileSync(filename, 'utf8'), { compilerOptions: { module: ts.ModuleKind.CommonJS, target: ts.ScriptTarget.ES2019 } }).outputText, filename) const { createTiangongMock, DEITY_IDS, isDeityId, hasBoundDeity } = loaded.exports @@ -15,7 +19,7 @@ test('天宫仅财神初始已恭请,五位神仙独立且状态快照隔离', const first = mock.snapshot() assert.equal(DEITY_IDS.length, 5) assert.deepEqual(DEITY_IDS.filter(id => first.deities[id].unlocked), ['wealth']) - assert.equal(first.balance, 100) + assert.equal('balance' in first, false) first.deities.wealth.incenseCount = 999 assert.equal(mock.snapshot().deities.wealth.incenseCount, 59) assert.equal(isDeityId('not-a-god'), false) @@ -25,8 +29,7 @@ test('上香点亮供桌次数+1,不猜测爱心扣减与功德奖励', () => const state = mock.incense('wealth') assert.equal(state.deities.wealth.incenseCount, 60) assert.equal(state.deities.wealth.lit, true) - assert.equal(state.deities.wealth.merit, 99) - assert.equal(state.balance, 100) + assert.equal('merit' in state.deities.wealth, false) assert.throws(() => mock.incense('fortune'), /未恭请/) }) test('模拟恭请和送神只改变指定神仙,返回列表状态可同步', () => { @@ -38,16 +41,14 @@ test('模拟恭请和送神只改变指定神仙,返回列表状态可同步', assert.equal(mock.snapshot().deities.fortune.unlocked, false) assert.equal(mock.snapshot().deities.fortune.lit, false) assert.equal(mock.snapshot().deities.wealth.unlocked, true) - assert.equal(mock.snapshot().balance, 100) }) -test('档位、非法金额与余额不足可以验证,但不执行任何真实扣款', () => { +test('本期无功德、余额、捐款接口或入口', () => { const mock = createTiangongMock() - assert.equal(mock.offering('wealth', 99).insufficient, false) - assert.equal(mock.offering('wealth', 168).insufficient, true) - assert.equal(mock.snapshot().balance, 100) - for (const value of [0, -1, 1.5, NaN, Infinity]) assert.throws(() => mock.offering('wealth', value), /正整数/) - mock.setDemoBalance(0) - assert.equal(mock.offering('wealth', 9).insufficient, true) + assert.equal(mock.offering, undefined) + assert.equal(mock.setDemoBalance, undefined) + for (const page of ['fortune', 'tiangong-detail']) { + assert.doesNotMatch(fs.readFileSync(path.join(root, `src/pages/${page}/index.tsx`), 'utf8'), /功德|爱心|充值|balance|merit/) + } }) test('祈愿/回向校验空值,不持久化姓名或祝愿;重置还原样例', () => { const mock = createTiangongMock() @@ -59,9 +60,8 @@ test('祈愿/回向校验空值,不持久化姓名或祝愿;重置还原样 mock.invite('fortune') mock.reset() assert.equal(mock.snapshot().deities.fortune.unlocked, false) - assert.equal(mock.snapshot().balance, 100) }) -test('未知神仙不回退为财神,页面只导入Mock;预留契约不被调用', () => { +test('未知神仙不回退为财神,页面通过服务层调用,未接入契约不被调用', () => { const service = fs.readFileSync(path.join(root, 'src/services/tiangong.ts'), 'utf8') assert.ok(!service.includes("id || 'wealth'")) for (const page of ['fortune', 'tiangong-detail']) { diff --git a/scripts/tiangongAccess.test.cjs b/scripts/tiangongAccess.test.cjs new file mode 100644 index 0000000..bcef72b --- /dev/null +++ b/scripts/tiangongAccess.test.cjs @@ -0,0 +1,214 @@ +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') +const root = path.resolve(__dirname, '..') +const flush = () => new Promise(resolve => setImmediate(resolve)) +function load(file, requireImpl, env = 'weapp') { + const exports = {} + const code = ts.transpileModule(fs.readFileSync(path.join(root, file), 'utf8'), { + compilerOptions: { module: ts.ModuleKind.CommonJS, target: ts.ScriptTarget.ES2019, jsx: ts.JsxEmit.ReactJSX } + }).outputText + vm.runInNewContext(code, { exports, require: requireImpl, process: { env: { TARO_ENV: env } } }) + return exports +} + +test('未登录点击天宫不切换Tab,连续点击只打开一次登录页,其他Tab仍可访问', async () => { + const routes = [] + let complete, loggedIn = false + const { switchMainTab } = load('src/services/tabNavigation.ts', id => id === './loginAccess' ? { + hasLoginAccess: () => loggedIn, + openLogin: () => { routes.push('login'); return new Promise(resolve => { complete = resolve }) } + } : { default: { switchTab: async ({ url }) => routes.push(url), showToast: () => {} } }) + const first = switchMainTab('fortune', 'my') + await switchMainTab('fortune', 'my') + assert.deepEqual(routes, ['login']) + complete(); await first + await switchMainTab('home', 'my') + await switchMainTab('my', 'home') + assert.deepEqual(routes, ['login', '/pages/home/index', '/pages/my/index']) + loggedIn = true + await switchMainTab('fortune', 'my') + assert.equal(routes.at(-1), '/pages/fortune/index') +}) + +function entryHarness(env = 'weapp') { + let token = '', preview = false, demo = false, response = { phoneBound: true, token: 'test', user: { id: 1 } }, failure, resolveLogin + const calls = [], routes = [], accepted = [], toasts = [] + const service = load('src/services/loginAccess.ts', id => { + if (id === './request') return { getToken: () => token, api: { wxLogin: async code => { calls.push(code); if (failure) throw new Error('请求失败'); return response } } } + if (id === './account') return { finishAccountLogin: async session => { accepted.push(session) } } + if (id === './frontendPreview') return { isFrontendPreview: () => preview } + if (id === './avatarDemo') return { isAvatarDemo: () => demo } + return { default: { + login: () => new Promise(resolve => { resolveLogin = resolve }), + navigateTo: async ({ url }) => { routes.push(url) }, + showLoading: () => {}, hideLoading: () => {}, showToast: data => toasts.push(data.title) + } } + }, env) + return { service, calls, routes, accepted, toasts, complete: code => resolveLogin({ code }), + token: value => { token = value }, preview: value => { preview = value }, demo: value => { demo = value }, + response: value => { response = value }, fail: value => { failure = value } } +} + +test('入口一次点击直接微信登录、去重;已注册不跳品牌页,失败可重试', async () => { + const h = entryHarness(), { service } = h + assert.equal(service.hasLoginAccess(), false) + h.token('session'); assert.equal(service.hasLoginAccess(), true) + h.token(''); h.preview(true); assert.equal(service.hasLoginAccess(), true) + h.preview(false); h.demo(true); assert.equal(service.hasLoginAccess(), true) + h.demo(false) + const first = service.openLogin(), second = service.openLogin() + assert.equal(first, second) + await flush(); h.complete('wx-test-code'); await first + assert.deepEqual(h.calls, ['wx-test-code']) + assert.equal(h.accepted.length, 1) + assert.equal(h.routes.length, 0) + h.fail(true) + const failed = service.openLogin(); await flush(); h.complete('failed'); await failed + assert.equal(h.toasts.length, 1) + h.fail(false) + const retry = service.openLogin(); await flush(); h.complete('retry'); await retry + assert.equal(h.accepted.length, 2) +}) + +test('新注册仅进入必要的手机号表单,临时会话留内存、不放入URL', async () => { + const h = entryHarness() + h.response({ phoneBound: false, sessionKey: 'temporary-test-session' }) + const attempt = h.service.openLogin(); await flush(); h.complete('new-user'); await attempt + assert.equal(h.service.getRegistrationSession(), 'temporary-test-session') + assert.deepEqual(h.routes, ['/pages/login/index']) + assert.equal(h.accepted.length, 0) + h.service.clearRegistrationSession() + assert.equal(h.service.getRegistrationSession(), '') +}) + +test('H5和演示环境不伪造登录;缺少code或token不接受身份', async () => { + const web = entryHarness('h5') + await web.service.openLogin() + assert.equal(web.routes.length, 0); assert.equal(web.calls.length, 0) + assert.match(web.toasts[0], /微信开发者工具/) + const h = entryHarness() + h.preview(true); await h.service.openLogin(); assert.equal(h.calls.length, 0) + h.preview(false) + const noCode = h.service.openLogin(); await flush(); h.complete(''); await noCode + assert.equal(h.calls.length, 0) + h.response({ phoneBound: true }) + const invalid = h.service.openLogin(); await flush(); h.complete('incomplete'); await invalid + assert.equal(h.accepted.length, 0) +}) + +function authHarness(initialToken = '', sandbox = false, fresh = false) { + let token = initialToken, stateIndex = 0, refIndex = 0, initialized = false, show, hide, listener, cleanup + let freshToken = fresh ? initialToken : '' + const states = [], refs = [] + let requests = 0, complete, fail + const { useRequiredLogin } = load('src/hooks/useRequiredLogin.ts', id => { + if (id === 'react') return { + useState: initial => { const index = stateIndex++; if (!(index in states)) states[index] = typeof initial === 'function' ? initial() : initial; return [states[index], value => { states[index] = value }] }, + useRef: initial => { const index = refIndex++; return refs[index] || (refs[index] = { current: initial }) }, + useEffect: effect => { if (!initialized) { cleanup = effect(); initialized = true } } + } + if (id === '@tarojs/taro') return { useDidShow: callback => { show = callback }, useDidHide: callback => { hide = callback } } + if (id === '../services/frontendPreview') return { isFrontendPreview: () => sandbox } + if (id === '../services/avatarDemo') return { isAvatarDemo: () => false } + return { + getToken: () => token, + getFreshCachedProfile: () => fresh && token === freshToken ? { id: 1 } : null, + subscribeProfile: callback => { listener = callback; return () => { listener = undefined } }, + api: { profile: () => { requests++; return new Promise((resolve, reject) => { complete = resolve; fail = reject }) } } + } + }) + const render = () => { stateIndex = 0; refIndex = 0; return useRequiredLogin() } + render() + return { render, show: () => show(), hide: () => hide(), resolve: () => complete({ id: 1 }), reject: () => fail(new Error('offline')), + emit: value => listener?.(value), setToken: value => { token = value }, setFresh: value => { fresh = value; freshToken = value ? token : '' }, count: () => requests, unmount: () => cleanup() } +} + +test('同账号有效登录缓存直接允许进入,前后台切换不再闪检查页或重复请求', async () => { + const auth = authHarness('session', false, true) + assert.equal(auth.render().status, 'allowed') + auth.show(); assert.equal(auth.render().status, 'allowed'); assert.equal(auth.count(), 0) + auth.hide(); auth.show(); assert.equal(auth.render().status, 'allowed'); assert.equal(auth.count(), 0) + auth.setFresh(false) + auth.show(); assert.equal(auth.render().status, 'checking'); assert.equal(auth.count(), 1) + auth.reject(); await flush(); assert.equal(auth.render().status, 'error') +}) + +test('缓存页面切换账号或退出登录时,不复用旧账号已允许的状态', () => { + const auth = authHarness('first-session', false, true) + assert.equal(auth.render().status, 'allowed') + auth.hide(); auth.setToken('second-session') + assert.equal(auth.render().status, 'checking') + auth.setToken('') + assert.equal(auth.render().status, 'denied') +}) + +test('未登录不发资料请求;已登录必须校验资料才显示内容,401后立即隐藏', async () => { + const guest = authHarness() + guest.show(); assert.equal(guest.render().status, 'denied'); assert.equal(guest.count(), 0) + const auth = authHarness('session') + assert.equal(auth.render().status, 'checking') + auth.show(); assert.equal(auth.render().status, 'checking') + auth.emit({ id: 1 }); auth.resolve(); await flush(); assert.equal(auth.render().status, 'allowed') + auth.setToken(''); auth.emit(null) + assert.equal(auth.render().status, 'denied') + const demo = authHarness('', true) + demo.show(); assert.equal(demo.render().status, 'allowed'); assert.equal(demo.count(), 0) +}) + +test('网络错误保持登录但不显示内容,可重试;失效token不能通过校验', async () => { + const auth = authHarness('session') + auth.show(); auth.reject(); await flush() + assert.equal(auth.render().status, 'error') + auth.render().retry(); assert.equal(auth.render().status, 'checking') + auth.resolve(); await flush(); assert.equal(auth.render().status, 'allowed') + const expired = authHarness('expired') + expired.show(); expired.setToken(''); expired.emit(null); expired.reject(); await flush() + assert.equal(expired.render().status, 'denied') +}) + +test('页面隐藏或卸载后,旧校验结果不会恢复内容权限', async () => { + const hidden = authHarness('session') + hidden.show(); hidden.hide(); hidden.emit({ id: 1 }); hidden.resolve(); await flush() + assert.equal(hidden.render().status, 'checking') + const unmounted = authHarness('session') + unmounted.show(); unmounted.unmount(); unmounted.resolve(); await flush() + assert.equal(unmounted.render().status, 'checking') +}) + +test('直达天宫和详情页先渲染登录守卫,未验证时不挂载神仙列表或详情', () => { + for (const file of ['src/pages/fortune/index.tsx', 'src/pages/tiangong-detail/index.tsx']) { + let status = 'denied', session = false, contentReads = 0 + const page = load(file, id => { + if (id === 'react' || id === 'react/jsx-runtime') return require(id) + if (id.endsWith('/useRequiredLogin')) return { useRequiredLogin: () => ({ status, retry: () => {} }) } + if (id.endsWith('/loginAccess')) return { hasLoginAccess: () => session } + if (id.endsWith('/TiangongLoginGate')) return { TiangongLoginGate: 'login-gate' } + if (id.endsWith('/useTiangongSnapshot')) return { useTiangongSnapshot: () => { contentReads++; return {} } } + if (id.endsWith('/tiangong')) return { getDeity: () => { contentReads++; return {} } } + return {} + }) + for (const next of ['denied', 'checking', 'error', 'allowed']) { + status = next + assert.equal(page.default().type, 'login-gate') + } + assert.equal(contentReads, 0) + session = true; status = 'checking'; assert.equal(page.default().type, 'login-gate') + status = 'allowed'; assert.equal(typeof page.default().type, 'function') + } +}) + +test('必要校验只显示轻量场景占位,不出现整页登录检查提示', () => { + const gate = load('src/components/TiangongLoginGate.tsx', id => { + if (id === 'react/jsx-runtime') return require(id) + if (id === './TiangongPending') return { TiangongPending: 'pending-scene' } + if (id === './LoginGate') return { LoginGate: 'login-gate' } + return {} + }) + assert.equal(gate.TiangongLoginGate({ status: 'checking', retry: () => {} }).type, 'pending-scene') + assert.equal(gate.TiangongLoginGate({ status: 'denied', retry: () => {} }).type, 'login-gate') + assert.equal(gate.TiangongLoginGate({ status: 'error', retry: () => {} }).type, 'login-gate') +}) diff --git a/scripts/tiangongStore.test.cjs b/scripts/tiangongStore.test.cjs new file mode 100644 index 0000000..2d1efa1 --- /dev/null +++ b/scripts/tiangongStore.test.cjs @@ -0,0 +1,91 @@ +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 load(file, deps = {}) { + const exports = {} + vm.runInNewContext(ts.transpileModule(fs.readFileSync(path.join(__dirname, '..', file), 'utf8'), { compilerOptions: { module: ts.ModuleKind.CommonJS, target: ts.ScriptTarget.ES2019 } }).outputText, { exports, require: id => deps[id], setTimeout, clearTimeout }) + return exports +} +const ritual = load('src/utils/incenseRitual.ts') +const mock = load('src/utils/tiangongMock.ts', { './incenseRitual': ritual }) +const { createTiangongStore } = load('src/utils/tiangongStore.ts', { './tiangongMock': mock, './incenseRitual': ritual }) +const defer = () => { let resolve, reject; const promise = new Promise((ok, fail) => { resolve = ok; reject = fail }); return { promise, resolve, reject } } +function harness() { + let key = 'account-a', time = 1000, rows = [{ id: 81, name: '财神', holdingId: 726, active: true, incenseCount: 7, days: 3 }] + let loader = async () => rows, offer = async () => ({ id: 99 }) + const calls = [] + const store = createTiangongStore({ key: () => key, now: () => time, resolve: name => name === '财神' ? 'wealth' : undefined, + load: () => loader(), offer: (...args) => { calls.push(args); return offer(...args) }, dedicate: async (...args) => { calls.push(args); return { id: 100 } } }) + return { store, calls, key: value => { key = value }, time: value => { time = value }, rows: value => { rows = value }, load: value => { loader = value }, offer: value => { offer = value } } +} +test('真实状态不预置财神,按后端持有ID提交,后端确认后才计数', async () => { + const h = harness() + assert.equal(h.store.snapshot().deities.wealth.unlocked, false) + await h.store.refresh() + const response = defer(); h.offer(() => response.promise) + const request = h.store.incense('wealth') + assert.equal(h.store.snapshot().deities.wealth.incenseCount, 7) + assert.equal(h.store.snapshot().deities.wealth.lit, false) + assert.equal(h.calls[0][0], 726); assert.equal(h.calls[0][1], 2) + response.resolve({ id: 10 }); await request + assert.equal(h.store.snapshot().deities.wealth.incenseCount, 8) + assert.equal(h.store.snapshot().deities.wealth.incenseUntil, 16000) +}) +test('失败无计数无自动重试;晚到查询不覆盖已确认上香', async () => { + const h = harness(); await h.store.refresh() + h.offer(async () => { throw new Error('网络失败') }) + await assert.rejects(h.store.incense('wealth'), /网络失败/) + assert.equal(h.calls.length, 1); assert.equal(h.store.snapshot().deities.wealth.incenseCount, 7) + const read = defer(); h.load(() => read.promise) + const refreshing = h.store.refresh(true) + h.offer(async () => ({ id: 1 })); await h.store.incense('wealth') + read.resolve([{ name: '财神', holdingId: 726, active: true, incenseCount: 7 }]); await refreshing + assert.equal(h.store.snapshot().deities.wealth.incenseCount, 8) +}) +test('乱序并发响应逐次累计,不让旧点击缩短最后截止时间', async () => { + const h = harness(); await h.store.refresh() + const a = defer(), b = defer(); let count = 0 + h.offer(() => (++count === 1 ? a : b).promise) + const first = h.store.incense('wealth'); h.time(4000); const second = h.store.incense('wealth') + b.resolve({ id: 2 }); assert.equal((await second).startsRound, true) + a.resolve({ id: 1 }); assert.equal((await first).startsRound, false) + assert.equal(h.store.snapshot().deities.wealth.incenseCount, 9) + assert.equal(h.store.snapshot().deities.wealth.incenseUntil, 19000) + h.time(19001); assert.equal(h.store.snapshot().deities.wealth.lit, false) +}) + +test('写入在途不采纳可能已包含该流水的GET,避免回包后再次加一', async () => { + const h = harness(); await h.store.refresh() + const response = defer(), read = defer() + h.load(() => read.promise) + const refreshing = h.store.refresh(true) + h.offer(() => response.promise); const sending = h.store.incense('wealth') + read.resolve([{ name: '财神', holdingId: 726, active: true, incenseCount: 8 }]); await refreshing + assert.equal(h.store.snapshot().deities.wealth.incenseCount, 7) + await h.store.refresh(true) + response.resolve({ id: 2 }); await sending + assert.equal(h.store.snapshot().deities.wealth.incenseCount, 8) +}) +test('切换账号丢弃旧响应,不以Mock兜底;未绑定不可提交', async () => { + const h = harness(); await h.store.refresh() + const response = defer(); h.offer(() => response.promise) + const sending = h.store.incense('wealth') + h.key('account-b'); assert.equal(h.store.snapshot().deities.wealth.unlocked, false) + response.resolve({ id: 10 }); await assert.rejects(sending, /登录状态/) + h.rows([]); await h.store.refresh() + await assert.rejects(h.store.incense('wealth'), /绑定/) + h.load(async () => { throw new Error('未部署') }); await assert.rejects(h.store.refresh(true), /未部署/) + assert.equal(h.store.snapshot().deities.wealth.unlocked, false) +}) +test('祈愿和任意姓名回向去空白提交,不携带功德或注册收件人ID', async () => { + const h = harness(); await h.store.refresh() + await h.store.wish('wealth', ' 愿顺遂 ') + await h.store.dedicate('wealth', ' 家人 ', ' 平安 ') + assert.deepEqual(h.calls, [[726, 3, '愿顺遂'], [726, '家人', '平安']]) + await assert.rejects(h.store.wish('wealth', ' '), /愿望/) + await assert.rejects(h.store.dedicate('wealth', '', '祝愿'), /回向对象/) + assert.equal(h.calls.length, 2) +}) diff --git a/src/assets/tiangong/incense-yinqing.m4a b/src/assets/tiangong/incense-yinqing.m4a new file mode 100644 index 0000000000000000000000000000000000000000..fa8e0fa7c05aab6b2e6fae68317a8de3b4ff79a8 GIT binary patch literal 183574 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 CXGl~4 literal 0 HcmV?d00001 diff --git a/src/components/BirthdayPicker.tsx b/src/components/BirthdayPicker.tsx new file mode 100644 index 0000000..9106ce9 --- /dev/null +++ b/src/components/BirthdayPicker.tsx @@ -0,0 +1,38 @@ +import { useEffect, useMemo, useState } from 'react' +import { Button, Picker, Text, View } from '@tarojs/components' +import { beijingToday, BirthdayCalendar, changeLunarBirthdayColumn, formatLunarBirthday, lunarBirthdayModel, lunarBirthdayToSolar, MIN_BIRTHDAY, solarToLunarBirthday } from '../utils/birthdayCalendar' + +// Both registration and editing use the same form and this controlled picker. +// The saved birthday is always solar; calendar is a separate persisted preference. +export function BirthdayPicker({ value, calendar, onChange, onCalendarChange }: { + value: string; calendar: BirthdayCalendar; onChange: (solar: string) => void; onCalendarChange: (calendar: BirthdayCalendar) => void +}) { + const today = beijingToday() + const initial = () => solarToLunarBirthday(value) || solarToLunarBirthday(today)! + const [draft, setDraft] = useState(initial) + useEffect(() => { setDraft(initial()) }, [value]) + const model = useMemo(() => lunarBirthdayModel(draft, today), [draft.year, draft.month, draft.day, today]) + const solarLabel = value ? value.replace(/-/g, ' / ') : '' + const lunarLabel = formatLunarBirthday(value) + const field = + 出生日期 + {value ? calendar === 'lunar' ? lunarLabel : solarLabel : '请选择'} + › + + return + + {(['solar', 'lunar'] as const).map(type => )} + + {calendar === 'solar' ? onChange(String(event.detail.value))}>{field} + : setDraft(changeLunarBirthdayColumn(model, Number(event.detail.column), Number(event.detail.value), today))} + onCancel={() => setDraft(initial())} + onChange={event => { + const [y, m, d] = event.detail.value as number[] + const selected = { year: model.years[y], month: model.months[m]?.value, day: model.days[d] } + const solar = lunarBirthdayToSolar(selected) + if (solar && solar >= MIN_BIRTHDAY && solar <= today) onChange(solar) + }}>{field}} + {value && {calendar === 'lunar' ? `对应阳历:${solarLabel}` : `对应农历:${lunarLabel}`}} + +} diff --git a/src/components/DeityBinding.scss b/src/components/DeityBinding.scss index 7f98c36..0d864d0 100644 --- a/src/components/DeityBinding.scss +++ b/src/components/DeityBinding.scss @@ -48,6 +48,12 @@ .binding-gate-content > text { display: block; font-size: 30px; line-height: 1.8; } .binding-gate-actions { display: flex; justify-content: space-between; gap: 28px; margin: 100px 14px 0; } .binding-gate-actions > button { flex: 1; width: auto; padding-left: 14px; padding-right: 14px; white-space: nowrap; } +// A fixed, clipped viewport removes the long blurred report from page scroll. +// Binding dialogs remain separate fixed layers and keep their own interactions. +.home-page.binding-viewport-locked, .my-page.binding-viewport-locked { + position: fixed; inset: 0; width: 100%; height: 100%; min-height: 0; + overflow: hidden; overscroll-behavior: none; +} .binding-lock { position: relative; width: 48px; height: 43px; margin: 0 auto 60px; border-radius: 10px; background: #675088; } .binding-lock::before { content: ''; position: absolute; width: 29px; height: 29px; border: 6px solid #675088; border-bottom: 0; box-sizing: border-box; border-radius: 22px 22px 0 0; left: 9px; top: -23px; } .binding-lock > view { position: absolute; left: 20px; top: 13px; width: 9px; height: 16px; border-radius: 8px; background: #f0dfff; } diff --git a/src/components/DeityBinding.tsx b/src/components/DeityBinding.tsx index 7242314..9274142 100644 --- a/src/components/DeityBinding.tsx +++ b/src/components/DeityBinding.tsx @@ -1,13 +1,13 @@ import { useRef, useState } from 'react' import Taro from '@tarojs/taro' import { Button, Image, Text, View } from '@tarojs/components' -import { deityCatalog, getDeity, tiangongMock } from '../services/tiangong' +import { deityCatalog, getDeity, isTiangongDemo, tiangongMock } from '../services/tiangong' import { DeityId } from '../utils/tiangongMock' import { useTiangongSnapshot } from '../hooks/useTiangongSnapshot' import './DeityBinding.scss' export function BindingGate({ onBind, lock = true }: { onBind: () => void; lock?: boolean }) { - return + return {lock && } 须绑定神仙开启你的守护之旅 @@ -27,6 +27,12 @@ export function DeityCardDialog({ deityId, mode = 'view', onClose }: { deityId: const [confirmUnbind, setConfirmUnbind] = useState(false) const [error, setError] = useState('') const working = useRef(false) + if (!isTiangongDemo()) return + {deity.name} + + {state.unlocked ? `已守护 ${state.days} 天 · 持有记录 ${state.holdingId}` : '请通过 NFC 绑定神仙。此处不模拟建立真实绑定关系。'} + + const perform = (action: () => void) => { if (working.current) return working.current = true @@ -82,6 +88,7 @@ export function DeityCardDialog({ deityId, mode = 'view', onClose }: { deityId: export function DeityBindingFlow({ initialDeity, onClose }: { initialDeity?: DeityId; onClose: () => void }) { const [selected, setSelected] = useState(initialDeity || null) const snapshot = useTiangongSnapshot() + if (!isTiangongDemo()) return 碰一碰,绑定神仙请通过 NFC 绑定神仙,本次不在页面中模拟真实设备绑定。 if (selected) return const available = deityCatalog.filter(item => !snapshot.deities[item.id].unlocked) return diff --git a/src/components/LoginGate.tsx b/src/components/LoginGate.tsx new file mode 100644 index 0000000..cb9c990 --- /dev/null +++ b/src/components/LoginGate.tsx @@ -0,0 +1,18 @@ +import { Button, Text, View } from '@tarojs/components' +import { openLogin } from '../services/loginAccess' +import { MainTab, switchMainTab } from '../services/tabNavigation' +import type { LoginAccessStatus } from '../hooks/useRequiredLogin' +import { AppTabBar } from './AppTabBar' +import './TiangongLoginGate.scss' + +export function LoginGate({ status = 'denied', retry = () => {}, active }: { status?: LoginAccessStatus; retry?: () => void; active?: MainTab }) { + return + + {status === 'checking' ? '正在确认登录状态…' : status === 'error' ? '登录状态暂时无法确认' : '登录后开启守护之旅'} + {status === 'checking' ? '请稍候' : status === 'error' ? '请检查网络后重试。' : '微信登录 / 注册,查看你的专属内容'} + {status !== 'checking' && } + {!active && } + + {active && } + +} diff --git a/src/components/TiangongLoginGate.scss b/src/components/TiangongLoginGate.scss new file mode 100644 index 0000000..096c838 --- /dev/null +++ b/src/components/TiangongLoginGate.scss @@ -0,0 +1,20 @@ +.tiangong-login-gate { + position: fixed; + inset: 0; + overflow: hidden; + overscroll-behavior: none; + box-sizing: border-box; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + padding: calc(40px + env(safe-area-inset-top)) 44px calc(210px + env(safe-area-inset-bottom)); + background: linear-gradient(180deg,#c4b0ff,#e9e1fa 48%,#edf4ff); + color: #4c3b6b; + + .tiangong-login-card { width: 100%; max-width: 600px; box-sizing: border-box; padding: 58px 34px; border-radius: 32px; background: rgba(255,255,255,.78); text-align: center; } + .tiangong-login-title { display: block; font-size: 34px; font-weight: 700; line-height: 1.5; } + .tiangong-login-copy { display: block; margin-top: 18px; color: #8c7c9f; font-size: 25px; line-height: 1.8; } + .tiangong-login-action { width: 100%; margin: 34px 0 0; padding: 24px 12px; border-radius: 48px; color: #fff; font-size: 28px; line-height: 1.4; background: linear-gradient(135deg,#a984ed,#8d6acb); } + .tiangong-login-home { margin-top: 24px; padding: 14px; color: #8c7c9f; font-size: 25px; line-height: 1.5; } +} diff --git a/src/components/TiangongLoginGate.tsx b/src/components/TiangongLoginGate.tsx new file mode 100644 index 0000000..070f733 --- /dev/null +++ b/src/components/TiangongLoginGate.tsx @@ -0,0 +1,8 @@ +import type { LoginAccessStatus } from '../hooks/useRequiredLogin' +import { LoginGate } from './LoginGate' +import { TiangongPending } from './TiangongPending' + +export function TiangongLoginGate({ status, retry, tab = false }: { status: LoginAccessStatus; retry: () => void; tab?: boolean }) { + if (status === 'checking') return + return +} diff --git a/src/components/TiangongPending.scss b/src/components/TiangongPending.scss new file mode 100644 index 0000000..e506b28 --- /dev/null +++ b/src/components/TiangongPending.scss @@ -0,0 +1,7 @@ +.tg-pending { + min-height: 100vh; box-sizing: border-box; background: #faf2d4; color: #314337; + .tg-pending-content { min-height: 68vh; padding: 12vh 42px 42px; box-sizing: border-box; display: flex; flex-direction: column; justify-content: flex-end; align-items: center; gap: 30px; } + .tg-pending-silhouette { width: 48%; height: 32vh; border-radius: 48% 48% 24px 24px; background: rgba(172,160,123,.08); } + .tg-pending-base { width: 90%; height: 14vh; border-radius: 18px; background: rgba(172,160,123,.08); } + &.catalog { background: linear-gradient(180deg,#bda5fa,#edf4ff); padding-bottom: calc(190px + env(safe-area-inset-bottom)); } +} diff --git a/src/components/TiangongPending.tsx b/src/components/TiangongPending.tsx new file mode 100644 index 0000000..90ea046 --- /dev/null +++ b/src/components/TiangongPending.tsx @@ -0,0 +1,17 @@ +import Taro from '@tarojs/taro' +import { View } from '@tarojs/components' +import { AppTabBar } from './AppTabBar' +import { TiangongHeader } from './TiangongUI' +import './TiangongPending.scss' + +// No deity data or business controls mount before authentication is confirmed. +export function TiangongPending({ tab = false }: { tab?: boolean }) { + const back = () => Taro.getCurrentPages().length > 1 ? Taro.navigateBack() : Taro.switchTab({ url: '/pages/fortune/index' }) + return + + } -export function TiangongMockNote() { return Mock 原型演示 · 不扣费、不连接设备 · 刷新重置 } +export function TiangongMockNote() { return isTiangongDemo() ? Mock 原型演示 · 不扣费、不连接设备 · 刷新重置 : null } diff --git a/src/hooks/useIncenseRitual.ts b/src/hooks/useIncenseRitual.ts new file mode 100644 index 0000000..ce0db6f --- /dev/null +++ b/src/hooks/useIncenseRitual.ts @@ -0,0 +1,65 @@ +import { useEffect, useRef, useState } from 'react' +import Taro, { useDidHide, useDidShow } from '@tarojs/taro' +import { tiangongSession } from '../services/tiangong' +import { DeityId } from '../utils/tiangongMock' +import { createIncenseRitual } from '../utils/incenseRitual' +import sound from '../assets/tiangong/incense-yinqing.m4a' + +const SOUND_KEY = 'tiangong.incense-sound.enabled.v1' +function readSoundPreference() { + try { return Taro.getStorageSync(SOUND_KEY) !== false } catch { return true } +} + +export function useIncenseRitual(deityId?: DeityId) { + const [soundEnabled, setSoundEnabled] = useState(readSoundPreference) + const enabled = useRef(soundEnabled) + const mounted = useRef(true) + const [pending, setPending] = useState(0) + const ritual = useRef | null>(null) + const getRitual = () => { + if (!deityId) return null + if (!ritual.current) ritual.current = createIncenseRitual({ + getDeadline: () => tiangongSession.snapshot().deities[deityId].incenseUntil, + recordIncense: () => tiangongSession.incense(deityId), + refresh: () => { tiangongSession.refreshIncense(deityId) }, + soundEnabled: () => enabled.current, + createAudio: () => { + const context = Taro.createInnerAudioContext() + context.autoplay = false + context.loop = false + context.src = process.env.TARO_ENV === 'weapp' && !sound.startsWith('/') ? `/${sound}` : sound + return context + }, + onAudioError: () => { Taro.showToast({ title: '音频暂时无法播放,上香次数已记录', icon: 'none' }) } + }) + return ritual.current + } + const leave = () => { ritual.current?.dispose(); ritual.current = null } + useDidShow(() => { + enabled.current = readSoundPreference() + setSoundEnabled(enabled.current) + getRitual()?.sync() + }) + useDidHide(leave) + useEffect(() => { mounted.current = true; return () => { mounted.current = false; leave() } }, [deityId]) + + return { + soundEnabled, + pending, + toggleSound: () => { + const next = !enabled.current + enabled.current = next + setSoundEnabled(next) + if (!next) ritual.current?.mute() + else ritual.current?.resume() + try { Taro.setStorageSync(SOUND_KEY, next) } + catch { Taro.showToast({ title: '开关本次生效,未能保存到本机', icon: 'none' }) } + }, + incense: async () => { + setPending(value => value + 1) + try { await getRitual()?.tap() } + catch (error) { Taro.showToast({ title: error instanceof Error ? error.message : '上香提交失败,请稍后重试', icon: 'none' }) } + finally { if (mounted.current) setPending(value => Math.max(0, value - 1)) } + } + } +} diff --git a/src/hooks/useRequiredLogin.ts b/src/hooks/useRequiredLogin.ts new file mode 100644 index 0000000..699e9ca --- /dev/null +++ b/src/hooks/useRequiredLogin.ts @@ -0,0 +1,50 @@ +import { useEffect, useRef, useState } from 'react' +import { useDidHide, useDidShow } from '@tarojs/taro' +import { api, getFreshCachedProfile, getToken, subscribeProfile } from '../services/request' +import { isFrontendPreview } from '../services/frontendPreview' +import { isAvatarDemo } from '../services/avatarDemo' + +export type LoginAccessStatus = 'checking' | 'allowed' | 'denied' | 'error' +const sandbox = () => isFrontendPreview() || isAvatarDemo() +const initialStatus = (): LoginAccessStatus => sandbox() ? 'allowed' : !getToken() ? 'denied' : getFreshCachedProfile() ? 'allowed' : 'checking' + +// Presence of a stored token is not proof of a valid login. Confirm through the +// shared authenticated profile cache; 401 clears all page access immediately. +export function useRequiredLogin() { + const [status, setStatus] = useState(initialStatus) + const revision = useRef(0) + const active = useRef(true) + const verifiedToken = useRef(status === 'allowed' ? getToken() : '') + const retry = () => { + const version = ++revision.current + const next = initialStatus() + const token = getToken() + verifiedToken.current = next === 'allowed' ? token : '' + setStatus(next) + if (next !== 'checking') return + api.profile().then(() => { + if (active.current && version === revision.current && token === getToken()) { + verifiedToken.current = token + setStatus('allowed') + } + }).catch(() => { + if (active.current && version === revision.current) setStatus(getToken() ? 'error' : 'denied') + }) + } + useDidShow(() => { active.current = true; retry() }) + useDidHide(() => { active.current = false; revision.current++ }) + useEffect(() => { + active.current = true + const unsubscribe = subscribeProfile(profile => { + if (!active.current || sandbox()) return + revision.current++ + verifiedToken.current = profile && getToken() ? getToken() : '' + setStatus(profile && getToken() ? 'allowed' : 'denied') + }) + return () => { active.current = false; revision.current++; unsubscribe() } + }, []) + // A cached tab may render once before useDidShow: never reuse another token's + // allowed state, even when both accounts have non-empty stored credentials. + const visibleStatus = !sandbox() && status === 'allowed' && verifiedToken.current !== getToken() ? initialStatus() : status + return { status: visibleStatus, retry } +} diff --git a/src/hooks/useTiangongSnapshot.ts b/src/hooks/useTiangongSnapshot.ts index a585133..4d4823b 100644 --- a/src/hooks/useTiangongSnapshot.ts +++ b/src/hooks/useTiangongSnapshot.ts @@ -1,16 +1,20 @@ import { useEffect, useState } from 'react' import { useDidShow } from '@tarojs/taro' -import { tiangongMock } from '../services/tiangong' +import { tiangongSession } from '../services/tiangong' // Cached Tab pages also react immediately when a dialog binds/unbinds a deity. export function useTiangongSnapshot() { - const [snapshot, setSnapshot] = useState(tiangongMock.snapshot) + const [snapshot, setSnapshot] = useState(tiangongSession.snapshot) useEffect(() => { - const refresh = () => setSnapshot(tiangongMock.snapshot()) - const unsubscribe = tiangongMock.subscribe(refresh) + const refresh = () => setSnapshot(tiangongSession.snapshot()) + const unsubscribe = tiangongSession.subscribe(refresh) refresh() + tiangongSession.refresh().catch(() => { /* Snapshot exposes a retryable load error. */ }) return unsubscribe }, []) - useDidShow(() => setSnapshot(tiangongMock.snapshot())) + useDidShow(() => { + setSnapshot(tiangongSession.snapshot()) + tiangongSession.refresh().catch(() => { /* Shared snapshot exposes the error for retry. */ }) + }) return snapshot } diff --git a/src/pages/fortune/index.tsx b/src/pages/fortune/index.tsx index 4ba38ea..1fa3027 100644 --- a/src/pages/fortune/index.tsx +++ b/src/pages/fortune/index.tsx @@ -3,24 +3,35 @@ import Taro from '@tarojs/taro' import { Button, Image, Text, View } from '@tarojs/components' import { AppTabBar } from '../../components/AppTabBar' import { TiangongHeader, TiangongMockNote, TiangongModal } from '../../components/TiangongUI' -import { deityCatalog, tiangongMock } from '../../services/tiangong' +import { deityCatalog, isTiangongDemo, tiangongMock, tiangongSession } from '../../services/tiangong' +import { resolveAssetUrl } from '../../services/request' import { useTiangongSnapshot } from '../../hooks/useTiangongSnapshot' import { DeityId } from '../../utils/tiangongMock' +import { hasLoginAccess } from '../../services/loginAccess' +import { useRequiredLogin } from '../../hooks/useRequiredLogin' +import { TiangongLoginGate } from '../../components/TiangongLoginGate' import './index.scss' export default function FortunePage() { + const auth = useRequiredLogin() + if (auth.status !== 'allowed' || !hasLoginAccess()) return + return +} + +function FortuneContent() { const snapshot = useTiangongSnapshot() const items = deityCatalog.map(item => ({ ...item, ...snapshot.deities[item.id] })) const [selected, setSelected] = useState(null) const [settings, setSettings] = useState(false) - const balance = snapshot.balance const open = (id: DeityId, invite = false) => Taro.navigateTo({ url: `/pages/tiangong-detail/index?id=${id}${invite ? '&mode=invite' : ''}` }) return + {snapshot.loading && !snapshot.ready && 正在加载神仙列表…} + {snapshot.error && {snapshot.error}} {items.map(item => - {selected === item.id && !item.unlocked && @@ -29,11 +40,9 @@ export default function FortunePage() { } )} - + {isTiangongDemo() && } {settings && setSettings(false)} variant='plain'> - Mock 演示设置当前模拟爱心:{balance} - 仅切换演示余额,不是充值。刷新网页或重新启动小程序后恢复初始样例。 - {([0, 100] as const).map(value => )} + Mock 演示设置仅重置本次演示,不修改真实供奉记录。 } diff --git a/src/pages/home/index.tsx b/src/pages/home/index.tsx index 2790ccd..fb14a39 100644 --- a/src/pages/home/index.tsx +++ b/src/pages/home/index.tsx @@ -2,6 +2,8 @@ import { useEffect, useMemo, useRef, useState } from 'react' import Taro, { useDidShow } from '@tarojs/taro' import { Button, Image, Text, View } from '@tarojs/components' import { AppTabBar } from '../../components/AppTabBar' +import { LoginGate } from '../../components/LoginGate' +import { switchMainTab } from '../../services/tabNavigation' import { UserAvatar } from '../../components/UserAvatar' import { BindingGate, DeityBindingFlow } from '../../components/DeityBinding' import { useTiangongSnapshot } from '../../hooks/useTiangongSnapshot' @@ -91,13 +93,15 @@ export default function HomePage() { catch { Taro.showToast({ title: '排序保存失败,请重试', icon: 'none' }) } } + const loggedOut = !isFrontendPreview() && !isAvatarDemo() && !getToken() + if (loggedOut) return + if (loading || !overview) { - const loggedOut = !isFrontendPreview() && !isAvatarDemo() && !getToken() return - {loggedOut ? '登录后开启你的守护之旅' : loading ? '正在准备你的每日参考…' : loadFailed ? '个人资料加载失败,请重试' : '请先完善有效的出生日期和时辰'} - {!loading && } + {loading ? '正在准备你的每日参考…' : loadFailed ? '个人资料加载失败,请重试' : '请先完善有效的出生日期和时辰'} + {!loading && } @@ -121,11 +125,11 @@ export default function HomePage() { } const activeDay = overview.days[dayOffset + 1] - return + return {isFrontendPreview() && 前端预览 · 示例资料 · 不保存个人资料} {isAvatarDemo() && 已登录演示 · 头像仅本地保存 · 刷新重置} - } /> + {overview.days.map((day, index) => )} diff --git a/src/pages/login/index.scss b/src/pages/login/index.scss index 13a0c01..da0cbf8 100644 --- a/src/pages/login/index.scss +++ b/src/pages/login/index.scss @@ -1,80 +1,17 @@ .login-page { - min-height: 100vh; - padding: 170px 56px 80px; - box-sizing: border-box; - display: flex; - flex-direction: column; - align-items: center; -} - -.brand-mark { - width: 180px; - height: 180px; - border-radius: 90px; - background: rgba(255, 255, 255, 0.86); - box-shadow: 0 18px 42px rgba(143, 100, 13, 0.14); - color: #8f640d; - font-size: 54px; - font-weight: 700; - display: flex; - align-items: center; - justify-content: center; -} - -.login-title { - margin-top: 44px; - font-size: 48px; - font-weight: 800; - color: #8f640d; -} - -.login-subtitle { - margin-top: 22px; - font-size: 26px; - color: #9e8b65; -} -.login-platform-note { display: block; margin-top: 24px; font-size: 25px; line-height: 1.8; color: #9e8b65; } -.login-page .login-button[disabled] { opacity: .55; } -.login-page .code-input { min-width: 0; } -.login-page .send-code { flex: none; width: 180px; font-size: 25px; } - -.login-button { - width: 100%; - margin-top: 54px; -} - -.login-form { - width: 100%; - margin-top: 40px; - display: flex; - flex-direction: column; - gap: 22px; -} - -.code-row { - display: flex; - gap: 18px; -} - -.code-input { - flex: 1; -} - -.send-code { - width: 148px; - height: 78px; - border-radius: 40px; - background: #fff; - color: #8f640d; - box-shadow: 0 10px 24px rgba(143, 100, 13, 0.14); - font-size: 28px; - display: flex; - align-items: center; - justify-content: center; -} - -.mock-code { - padding-left: 24px; - font-size: 24px; - color: #b38a32; + min-height: 100vh; padding: calc(80px + env(safe-area-inset-top)) 44px calc(60px + env(safe-area-inset-bottom)); + box-sizing: border-box; display: flex; flex-direction: column; justify-content: center; align-items: center; + background: linear-gradient(180deg,#c4b0ff,#e9e1fa 48%,#edf4ff); color: #4c3b6b; + .login-card { width: 100%; max-width: 600px; padding: 58px 34px; box-sizing: border-box; border-radius: 32px; background: rgba(255,255,255,.78); } + .login-title { display: block; text-align: center; font-size: 34px; line-height: 1.5; font-weight: 700; } + .login-subtitle, .login-platform-note { display: block; margin-top: 18px; color: #8c7c9f; font-size: 25px; line-height: 1.8; text-align: center; } + .login-button { width: 100%; margin-top: 34px; padding: 24px 12px; border-radius: 48px; color: white; font-size: 28px; line-height: 1.4; background: linear-gradient(135deg,#a984ed,#8d6acb); } + .login-button[disabled] { opacity: .55; } + .login-form { display: flex; flex-direction: column; gap: 22px; margin-top: 34px; } + .input-pill { width: 100%; min-width: 0; height: 88px; padding: 0 24px; box-sizing: border-box; font-size: 26px; line-height: 88px; border-radius: 44px; background: white; color: #4c3b6b; } + .code-row { display: flex; align-items: center; gap: 14px; } + .code-input { flex: 1; } + .send-code { flex: none; margin: 0; width: 180px; padding: 20px 8px; font-size: 24px; line-height: 1.5; border-radius: 40px; background: #eee5fc; color: #8d6acb; } + .mock-code { font-size: 23px; line-height: 1.6; color: #8c7c9f; } + .login-retry { margin: 0; font-size: 25px; line-height: 1.6; color: #8c7c9f; background: transparent; } } diff --git a/src/pages/login/index.tsx b/src/pages/login/index.tsx index d6af33f..d4ed157 100644 --- a/src/pages/login/index.tsx +++ b/src/pages/login/index.tsx @@ -4,10 +4,11 @@ import { Button, Input, Text, View } from '@tarojs/components' import { api } from '../../services/request' import { finishAccountLogin } from '../../services/account' import { isFrontendPreview } from '../../services/frontendPreview' +import { beginWechatLogin, clearRegistrationSession, getRegistrationSession } from '../../services/loginAccess' import './index.scss' export default function LoginPage() { - const [sessionKey, setSessionKey] = useState('') + const [sessionKey, setSessionKey] = useState(getRegistrationSession) const [phone, setPhone] = useState('') const [captcha, setCaptcha] = useState('') const [mockCode, setMockCode] = useState('') @@ -27,16 +28,14 @@ export default function LoginPage() { try { await work() } catch (error) { const message = error instanceof Error ? error.message : '操作失败,请检查网络后重试' - if (/会话.*(过期|不存在)/.test(message)) { setSessionKey(''); setCaptcha(''); setMockCode('') } + if (/会话.*(过期|不存在)/.test(message)) { clearRegistrationSession(); setSessionKey(''); setCaptcha(''); setMockCode('') } Taro.showToast({ title: message, icon: 'none' }) } finally { working.current = false; setBusy('') } } const wxLogin = () => run('wx', async () => { if (!supported || isFrontendPreview()) throw new Error('请在微信小程序中登录') setSessionKey(''); setCaptcha(''); setMockCode(''); setCountdown(0) - const login = await Taro.login() - if (!login.code) throw new Error('微信未返回登录凭证,请重试') - const res = await api.wxLogin(login.code) + const res = await beginWechatLogin() if (res.phoneBound) { if (!res.token || !res.user) throw new Error('登录响应不完整,请重试') await finishAccountLogin({ token: res.token, user: res.user }) @@ -62,17 +61,18 @@ export default function LoginPage() { if (!/^1\d{10}$/.test(phone)) throw new Error('请输入正确的11位手机号') if (!/^\d{6}$/.test(captcha)) throw new Error('请输入6位验证码') const res = await api.bindPhone(sessionKey, phone, captcha) + clearRegistrationSession() await finishAccountLogin(res) }) return ( - - 那吉 - 一触即吉 - 微信登录后绑定手机号,开启你的守护之旅 - {!supported && 微信登录 / 注册请在微信开发者工具或微信小程序中完成。H5 不伪造微信凭证;已有会话可继续联调资料和头像接口。} + + + {sessionKey ? '绑定手机号' : '登录后开启守护之旅'} + {sessionKey ? '首次注册需验证手机号,完成后即可继续' : '微信登录 / 注册,查看你的专属内容'} + {!supported && 请在微信开发者工具或微信小程序中完成登录 / 注册。} {isFrontendPreview() && 当前为纯前端预览,不会请求注册接口。} - + {!sessionKey && } {sessionKey && { setPhone(String(e.detail.value)); setCaptcha(''); setMockCode('') }} /> @@ -80,8 +80,10 @@ export default function LoginPage() { {mockCode && 开发验证码:{mockCode}(后端返回,非真实短信)} - + + } + ) } diff --git a/src/pages/my/index.tsx b/src/pages/my/index.tsx index 87b4535..afaf885 100644 --- a/src/pages/my/index.tsx +++ b/src/pages/my/index.tsx @@ -3,6 +3,7 @@ import Taro, { useDidShow } from '@tarojs/taro' import { Button, Image, ScrollView, Text, View } from '@tarojs/components' import { RadarChart } from '../../components/RadarChart' import { AppTabBar } from '../../components/AppTabBar' +import { LoginGate } from '../../components/LoginGate' import { UserAvatar } from '../../components/UserAvatar' import { FiveElementIcon } from '../../components/FiveElementIcon' import { BindingGate, DeityBindingFlow, DeityCardDialog } from '../../components/DeityBinding' @@ -128,7 +129,7 @@ export default function MyPage() { const renderElement = () => !elementReport ? ( - + {previewNote} @@ -139,7 +140,7 @@ export default function MyPage() { {renderBindingDialogs()} ) : ( - + {previewNote} @@ -202,9 +203,10 @@ export default function MyPage() { if (!profile) { const loggedOut = !isFrontendPreview() && !isAvatarDemo() && !getToken() + if (loggedOut) return return - {loggedOut ? '登录后查看个人信息' : profileError ? '个人资料加载失败,请重试' : '个人资料加载中…'} - {loggedOut ? : profileError && } + {profileError ? '个人资料加载失败,请重试' : '个人资料加载中…'} + {profileError && } {renderTabs()} } diff --git a/src/pages/profile-edit/index.scss b/src/pages/profile-edit/index.scss index 89401af..21fb937 100644 --- a/src/pages/profile-edit/index.scss +++ b/src/pages/profile-edit/index.scss @@ -219,6 +219,14 @@ padding: 0 28px 0 31px; } +.birthday-picker { width: 100%; margin-bottom: 34px; } +.birthday-calendar-tabs { display: flex; justify-content: flex-end; gap: 8px; margin-bottom: 14px; } +.birthday-calendar-tab { margin: 0; padding: 10px 24px; border-radius: 28px; background: rgba(255,255,255,.4); color: #847498; font-size: 24px; line-height: 1.4; } +.birthday-calendar-tab.active { color: #fff; background: #a181d7; } +.birthday-card { margin-bottom: 0; } +.birthday-card .field-value { font-size: 26px; margin-left: 20px; } +.birthday-equivalent { display: block; margin: 12px 12px 0; color: #8e82a0; font-size: 22px; line-height: 1.5; } + .form-picker { width: 100%; display: block; @@ -311,18 +319,6 @@ position: relative; } -.wechat-avatar-action { - height: 154px; - flex-direction: column; - gap: 12px; -} - -.wechat-avatar-preview { - width: 44px; - height: 44px; - border-radius: 6px; -} - .sheet-gap { height: 16px; background: #f5f5f7; diff --git a/src/pages/profile-edit/index.tsx b/src/pages/profile-edit/index.tsx index dca41df..e618b3f 100644 --- a/src/pages/profile-edit/index.tsx +++ b/src/pages/profile-edit/index.tsx @@ -1,13 +1,15 @@ import { useEffect, useRef, useState } from 'react' import Taro, { useRouter } from '@tarojs/taro' -import { Button, Image, Input, Picker, Text, View } from '@tarojs/components' +import { Button, Input, Picker, Text, View } from '@tarojs/components' import areaData from 'china-area-data' import { NavBar } from '../../components/NavBar' import { UserAvatar } from '../../components/UserAvatar' +import { BirthdayPicker } from '../../components/BirthdayPicker' import { api, resolveAssetUrl, UserProfile } from '../../services/request' import { isFrontendPreview } from '../../services/frontendPreview' import { isAvatarDemo } from '../../services/avatarDemo' import { EditableProfile, toEditableProfile, saveProfileEdits, validateProfileForm } from '../../utils/profileEditing' +import { openLogin } from '../../services/loginAccess' import './index.scss' const hours = [ @@ -31,6 +33,7 @@ const emptyForm: EditableProfile = { nickname: '', gender: '', birthday: '', + birthdayCalendar: 'solar', birthHour: '', province: '', city: '', @@ -144,8 +147,6 @@ export default function ProfileEditPage() { } const birthHour = hours.find((item) => item.name === form.birthHour) || hours[0] - const dateParts = form.birthday ? form.birthday.split('-') : ['', '', ''] - const today = new Date(Date.now() + 8 * 60 * 60 * 1000).toISOString().slice(0, 10) const provinceEntries = regionEntries('86') const provinceCode = regionCodes[0] || provinceEntries[0]?.[0] || '' const cityEntries = regionEntries(provinceCode) @@ -199,12 +200,15 @@ export default function ProfileEditPage() { 加载中... ) : loadError || !profile ? {loadError || '个人信息加载失败'} - + : ( {isFrontendPreview() && 纯前端预览 · 不保存个人资料或头像} {isAvatarDemo() && 已登录演示 · 选择图片并保存可查看三处头像同步,不上传真实存储;刷新页面重置。} - } diff --git a/src/pages/tiangong-detail/index.scss b/src/pages/tiangong-detail/index.scss index 5b1a207..bc4b246 100644 --- a/src/pages/tiangong-detail/index.scss +++ b/src/pages/tiangong-detail/index.scss @@ -7,7 +7,6 @@ // one stage size and centreline so lighting incense never moves the composition. .tg-altar-frame { position: relative; flex: none; height: 0; padding-top: 43.4%; overflow: hidden; background: #e7d5ae; } .tg-altar { position: absolute; top: -0.3%; left: -3.7%; display: block; width: 106%; height: 100.3%; } -.tg-merit-entry { position: absolute; left: 24px; top: 20px; padding: 10px 24px; margin: 0; color: #786c48; border: 1px solid rgba(157,135,71,.25); border-radius: 25px; background: rgba(255,253,236,.8); font-size: 23px; line-height: 32px; } .tg-incense-count { position: absolute; right: 24px; top: 30px; color: #887942; font-size: 23px; line-height: 32px; } .worship-actions { flex: none; display: flex; justify-content: space-around; align-items: center; padding: 18px 12px calc(24px + env(safe-area-inset-bottom)); background: #faf2d4; } .worship-actions .worship-action { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 3px; width: 68px; height: 108px; padding: 0; margin: 0; border-radius: 34px; font-size: 27px; line-height: 34px; color: #3f5141; background: linear-gradient(110deg,#c3d7c7,#e1eadc); box-shadow: inset 2px 1px 5px rgba(255,255,255,.7),0 3px 8px rgba(107,125,92,.08); } @@ -16,11 +15,7 @@ .tg-panel-statue { flex: none; width: 130px; height: 150px; } .tg-panel-copy { flex: 1; } .tg-panel-heading-line { display: block; font-size: 25px; font-weight: 600; line-height: 1.8; } -.tg-merit-stats { margin-top: 22px; padding: 20px 24px; background: rgba(255,255,255,.25); border-radius: 12px; } -.tg-merit-stat { display: block; font-size: 23px; line-height: 1.8; } -.tg-offering-options { display: grid; grid-template-columns: repeat(2,minmax(0,1fr)); gap: 20px; margin: 30px 0; } -.tg-offering-options .tg-offering-option { margin: 0; padding: 14px; border: 2px solid transparent; border-radius: 16px; color: #47614d; background: #fffdf4; font-size: 30px; line-height: 44px; } -.tg-offering-options .tg-offering-option.chosen { border-color: #567f60; background: #edf4e8; } +.tg-worship-stats { display: flex; flex-wrap: wrap; gap: 20px; margin-top: 22px; padding: 20px 24px; background: rgba(255,255,255,.25); border-radius: 12px; font-size: 23px; line-height: 1.8; } .tg-waiting-dots { font-size: 64px; text-align: center; line-height: 1.8; letter-spacing: 18px; color: #7c9a7f; } .tiangong-detail-page.invitation { height: auto; min-height: 100vh; overflow: visible; } .invitation .tg-sacred-scene { flex: none; height: 730px; } diff --git a/src/pages/tiangong-detail/index.tsx b/src/pages/tiangong-detail/index.tsx index 44ec8c9..59637fd 100644 --- a/src/pages/tiangong-detail/index.tsx +++ b/src/pages/tiangong-detail/index.tsx @@ -1,70 +1,84 @@ -import { useState } from 'react' +import { useRef, useState } from 'react' import Taro, { useRouter } from '@tarojs/taro' import { Button, Image, Input, Text, Textarea, View } from '@tarojs/components' import { TiangongHeader, TiangongModal, TiangongMockNote } from '../../components/TiangongUI' import { DeityBindingFlow } from '../../components/DeityBinding' import { useTiangongSnapshot } from '../../hooks/useTiangongSnapshot' -import { getDeity, tiangongMock } from '../../services/tiangong' +import { getDeity, isTiangongDemo, tiangongMock, tiangongSession } from '../../services/tiangong' +import { TiangongPending } from '../../components/TiangongPending' +import { hasLoginAccess } from '../../services/loginAccess' +import { useRequiredLogin } from '../../hooks/useRequiredLogin' +import { TiangongLoginGate } from '../../components/TiangongLoginGate' +import { useIncenseRitual } from '../../hooks/useIncenseRitual' import clouds from '../../assets/tiangong/proto-clouds.jpg' import altar from '../../assets/tiangong/proto-altar.jpg' import altarLit from '../../assets/tiangong/proto-altar-lit.jpg' import './index.scss' -type Modal = '' | 'wish' | 'dedicate' | 'offering' | 'send-off' | 'stand' | 'waiting' | 'invited' | 'insufficient' | 'result' +type Modal = '' | 'wish' | 'dedicate' | 'send-off' | 'stand' | 'waiting' | 'invited' | 'result' export default function TiangongDetailPage() { + const auth = useRequiredLogin() + if (auth.status !== 'allowed' || !hasLoginAccess()) return + return +} + +function TiangongDetailContent() { const router = useRouter() const deity = getDeity(router.params.id) const snapshot = useTiangongSnapshot() + const ritual = useIncenseRitual(deity?.id) const [bindingCardOpen, setBindingCardOpen] = useState(false) const [modal, setModal] = useState('') const [wish, setWish] = useState('') const [name, setName] = useState('') const [blessing, setBlessing] = useState('') - const [amount, setAmount] = useState('') const [error, setError] = useState('') const [result, setResult] = useState('') const [busy, setBusy] = useState(false) - const close = () => { setModal(''); setError('') } + const working = useRef(false) + const demo = isTiangongDemo() + const close = () => { if (!working.current) { setModal(''); setError('') } } const open = (next: Modal) => { setError(''); setModal(next) } const back = () => { if (Taro.getCurrentPages().length > 1) Taro.navigateBack() else Taro.switchTab({ url: '/pages/fortune/index' }) } if (!deity) return 未找到该神仙,请返回天宫选择。 + if (!snapshot.ready) return snapshot.error ? {snapshot.error} : const state = snapshot.deities[deity.id] + if (!state.available) return 该神仙暂未配置,请返回天宫选择。 const invited = state.unlocked - const perform = (action: () => void) => { - if (busy) return - setBusy(true) - try { action() } catch (cause) { setError(cause instanceof Error ? cause.message : '演示操作失败,请重试') } - finally { setBusy(false) } + const perform = async (action: () => void | Promise) => { + if (working.current) return + working.current = true; setBusy(true); setError('') + try { await action() } catch (cause) { setError(cause instanceof Error ? cause.message : '操作失败,请重试') } + finally { working.current = false; setBusy(false) } } const showResult = (text: string) => { setResult(text); open('result') } - const incense = () => perform(() => { tiangongMock.incense(deity.id); Taro.showToast({ title: '模拟上香,次数 +1', icon: 'none' }) }) - const confirmOffering = () => perform(() => { - const response = tiangongMock.offering(deity.id, Number(amount)) - if (response.insufficient) open('insufficient') - else showResult(`已模拟选择 ${response.amount} 爱心。本次不扣减余额、不增加真实功德。`) - }) const showBindingCard = () => { close(); setBindingCardOpen(true) } - const submitWish = () => perform(() => { tiangongMock.wish(deity.id, wish); setWish(''); showResult('模拟祈愿已完成,内容未上传、未保存。') }) - const submitDedication = () => perform(() => { tiangongMock.dedicate(deity.id, name, blessing); setName(''); setBlessing(''); showResult('模拟回向已完成,姓名和祝愿未上传、未保存。') }) + const submitWish = () => perform(async () => { await tiangongSession.wish(deity.id, wish); setWish(''); showResult(demo ? '模拟祈愿已完成,内容未上传、未保存。' : '祈愿已记录。') }) + const submitDedication = () => perform(async () => { await tiangongSession.dedicate(deity.id, name, blessing); setName(''); setBlessing(''); showResult(demo ? '模拟回向已完成,姓名和祝愿未上传、未保存。' : '回向已记录。') }) const panelHeader = (title: string, subtitle: string) => {title}{subtitle} const dialogActions = (confirm: string, action: () => void, danger = false, disabled = false) => return - + + + + } /> - {invited && <>上香 {state.incenseCount}} + {invited && 上香 {state.incenseCount}{ritual.pending > 0 ? ' · 提交中' : ''}} {invited && } {invited ? {['上香', '祈愿', '回向', '送神', '返回'].map(action => )} : @@ -72,34 +86,27 @@ export default function TiangongDetailPage() { {deity.introduction || '原型未提供这位神仙的独立介绍,待确认后补充。'} {deity.introduction && 原型介绍与“禄星”名称不一致,文案待确认。} {deity.missingStatue && 原型未提供独立详情神像,暂使用同一神仙的列表原图。} - - 仅演示恭请流程,不扣费、不建立真实供奉关系。 + + {demo && 仅演示恭请流程,不扣费、不建立真实供奉关系。} } - {modal && + {modal && {} : close} variant={['stand', 'waiting'].includes(modal) ? 'plain' : ''}> {modal === 'wish' && <> {panelHeader(`向【${deity.ritualName}】祈愿`, '诚心许愿,助您愿望实现!')} 您的愿望