# 金字塔开发与联调说明 日期:2026-09-28。前后端代码已落地本地,未部署、未发布活动、未发生真实支付。 ## 已实现 - 2026-10-10:金字塔接入公共 `remote/manifest.json` 与 SHA-256 ZIP 缓存,构建及上传步骤见[活动分包说明](activity-bundles.md)。本地需完整重新构建并上传资源后联调。 - `assets/pyramid/prefab/Pyramid.prefab`:独立 Cocos 2.4 活动包,按效果图组合标题、阶梯、奖励格子、箭头、道具数量、倒计时和购买/抽奖/免费领取按钮。 - `PyramidPanel.ts` 与 `PyramidDigits.ts`:配置驱动奖励布局、宝箱气泡详情、抽奖高亮、领取勾选、过期及支付未决状态。仅宝箱点击后展示其内部奖励,普通奖励和顶部大奖不弹出道具详情。气泡按效果图使用圆角底图和向下尖角,锚定对应宝箱上方;点击外部关闭。所有数值均以图片数字拼接;缺少字符会报告并停止显示,不回退到 Label。 - `assets/Script/PyramidView.ts`:首页入口直接复用 `JiaZai.startUI2` 的 `pyramid.png`,不叠加文字;活动弹窗与既有首页队列接入,登录及在线补发恢复;活动不存在或完成后隐藏入口。 - `assets/Script/module/Config/PyramidService.ts`:接口、持久化请求 ID、支付轮询、账号切换隔离、跨期授权恢复、库存保存收据与发奖确认。 2026-10-12 补发查询与黄金矿工对齐:进入/返回首页、切回前台,以及本地检测到活动开始/结束边界时,查询 `/pyramid/api action:settlement_read`。并发查询共享任务,已返回但尚未展示的清单按 noticeId 合并保留。接口返回 `status: settling` 表示定时任务尚未准备完清单;请求失败或仍在结算时,仅重试补发查询,间隔为 2、3、5、7、10、15、25、30、50 秒。返回 `ready` 后停止重试,包括没有奖励的情况;持续停留首页不做常规接口轮询。下一次首页/前台触发会重新检查。查询在首页弹窗队列及输入遮挡中执行,仅展示待领取清单;点击领取成功后才同步服务端绝对库存。 补发查询 `settlement_read` 只返回清单,不入账、不标记已读、不同步库存。点击领取后调用 `settlement_claim`(periodId、noticeId),成功后同步服务端绝对库存、关闭清单,再用战令的 `publicUI/prefab/RewardWindow` 展示本期奖励,体力使用小时/分钟格式。领取失败保留弹窗供重试,重复领取通过后端发奖凭据防止重复入账。关闭弹窗不请求领取、不播放奖励动画,服务端清单仍未领取,下次首页/前台检查可再次展示。奖励动画结束后移除本地清单并继续队列;动画仅展示。前后端及金字塔分包须同步更新。 - 独立后端 `C:/Users/NK/Desktop/workspace/server/laf-cloud/functions/pyramid`:期次配置、单笔未决支付、不放回加权抽奖、六层领取、到期结算、幂等发奖和测试。下单在既有两个微信签名接口中路由;共享 `pay_test` 通过 `activityType:pyramid` 区分。 ## 测试配置与待补内容 测试排期为北京时间 **2026-09-28 00:00 至 2026-09-29 00:00**。前五层均 `pay_test`,草稿暂按 **100 分/次**。用户“价格1元1”的原文在实际发布前需要最终核对。后端草稿文件为 `config/2026-09-28-test.draft.json`。 各层正式奖励、数量、目标格子和权重未提供;草稿留空且不能通过发布校验。浏览器隔离预览和单元测试的奖励仅是样例,不写入活动数据库。第六层是否有固定奖也须由配置确定。 | 素材 | 当前处理 | | --- | --- | | 普通数字零至九、价格数字零至九 | 原目录两套共二十张全部齐全,原样导入;哈希测试核对原图 | | 背景、阶梯、标题、按钮、箭头、四种宝箱 | 原样导入到 `assets/pyramid/art` | | 效果图顶部独立蛋糕大奖 | 原目录未找到,暂用提供的第四种宝箱占位,需补独立透明图 | | 关闭、金币、锤子、冻结、魔法棒、无限体力、已领取勾、分钟单位 | 复用项目现有 `seven_day_gift` / `jungle_treasure` 图片,来源见素材清单 | | 小数点数字字形 | 原目录未找到;当前整数元使用图片数字加原有“元”图。未来非整元价格显示图片数字组成的分值加文字单位“分”,不以 Label 显示数字;若要求元小数样式需补小数点 | 完整源图映射:`tools/pyramid-art-manifest.json`。`tools/generate-pyramid-assets.cjs` 可从原素材目录重建元数据和预制体,**会覆盖预制体编辑结果**;日常调 UI 直接在 Creator 中编辑预制体。 ## 验证结果 | 检查 | 结果与范围 | | --- | --- | | 新增后端测试 | 24 项通过:并发下单/抽奖、权重及多目标、签名校验、幂等、支付截止、到期补发、保存收据、关单恢复 | | 新增客户端测试 | 8 项通过:丢失响应恢复、支付取消保持锁、切换账号、图片数字及预制体引用 | | 既有黄金矿工及支付路由回归 | 111 项通过;使用测试桩,需提供既有回调转发 URL 环境变量 | | 前端 TypeScript 对比 | HEAD 基线 18 个既有错误,当前同样 18 个,无新增;完整根目录检查另受旧 `server/drawHead.ts` 语法错误影响 | | 实际 Cocos 引擎隔离预览 | 已加载实际预制体、源码组件及原图;验证购买转抽奖、终点全部领取及过期显示。服务层为本地模拟,不等于真实支付联调 | | Creator 完整构建 | 本机命令行构建长时间停在资源库初始化,已停止本次启动的构建进程;未取得完整构建成功结果 | 运行:`node --test tools/test-pyramid-client.cjs`;`node tools/check-pyramid-types.cjs`;`node tools/preview-pyramid.cjs`。预览仅监听 `127.0.0.1:8766`,依赖本机 Creator 2.4.15 引擎及项目已有 `build/wechatgame/assets/internal`。预览不连接业务服务器、不真实付款。 ## 尚需环境验收 真实 Mongo/Laf 与微信真机支付尚未联调。当前轮询依靠服务端已验签回调和持久化状态恢复;仓库无已验证的该渠道主动查单/关单能力,因此无回调会保持未决,不会因客户端取消或超时放行。管理员只能在渠道已明确不可逆关单后记录关单凭据。详见后端 README。 发奖已经通过同一次用户文档更新保存库存和收据,并接入首页串行队列;旧游戏库存接口仍可能发送绝对值覆盖,真机验收需要检查其他自动保存流程,不应只以隔离预览作为上线依据。 发布前补齐运营配置、顶部蛋糕图(或确认宝箱占位)、价格确认,并完成 Creator 构建、Mongo/Laf、支付成功/取消/延迟/断网恢复验收。活动默认保持未发布。 ## 云函数名额优化 金字塔从十三个云函数合并为两个:`pyramid/api`(唯一 HTTP 入口)与 `pyramid/jobs`(内部定时任务)。客户端通过 POST `pyramid/api` 的 action 指定 info、query、draw、claim、delivery_list、delivery_save、delivery_confirm;保存步骤改用 phase,避免占用 action。管理员 action:admin 单独验证 adminToken。现有支付签名和回调通过 api 的导出函数复用同一实现。2026-10-10 起,公共 `activityConfig/list` 仅提供入口日程,移除 pyramid、pyramidError、pyramidErrorMessage;完整个人状态由 `action:info` 返回,错误使用标准 errorCode 和中文 msg。前后端须配套更新。 本次验证:后端二十四项、客户端八项、既有回归一百一十一项通过。尚未更新或删除测试环境的云函数;按后端 README 的迁移顺序更新 api、支付函数、jobs 和客户端,再移除旧的十一个云函数,才能释放远端名额。数据集合和历史记录无需变更。 # 2026-09-29:v3 奖励与分档 独立后端已补入两份 v3 文档的四档 80 格目录、自动分档及反馈、免费首抽、登顶自动建立补齐授权;配置草稿默认关闭,尚未上线。完整接入合同见独立后端 `laf-cloud/functions/pyramid/V3-OFFERS.md`。付费用户必须提供可信净支付/退款/SKU 版本事实,旧 RFM 不直接作为报价证据。 本客户端新增全部楼层价格展示、实际渲染后的价格曝光事件及画像暂不可用提示。`tools/preview-pyramid.cjs` 在相邻后端有 v3 目录时自动读取,也可用 `PYRAMID_CATALOG_PATH` 指定;URL 的 `?tier=1` 至 `?tier=4` 仅控制本地隔离预览,不写服务端或提供生产切档。既有真机支付/库存验收边界不变。 ## 临时免费抽奖测试(上线前删除) `PyramidPanel.ts` 的 `PYRAMID_ANIMATION_DEBUG` 当前设为 `false`,预览、开发版、体验版和网页版均走正式服务端流程。需要单独验证动画时才临时启用;正式抽奖结果始终由后端决定。 测试状态集中在 `PyramidAnimationDebug.ts`,深拷贝进入面板时的活动快照,在本次面板会话中保留进度,关闭重开、切换账号或期次后重新开始复制。每次免费按剩余格子权重抽取,标记已获得并排除,命中 up 后上楼;概率弹窗读取同一份本地状态。第六层手动领取剩余奖励及终点奖励,完成后不可重复领取。测试不创建订单、不调用抽奖/发奖接口、不修改真实库存,展示仍复用战令领奖效果。 上线前必须删除测试代码,而非仅把标识改为 false: 1. 删除 `PYRAMID_ANIMATION_DEBUG`、`animationDebug()`、`actionDebug()`、`debugSession` 字段以及 `PyramidAnimationDebug` 导入和 `.ts/.meta` 文件。 2. `action()` 直接调用 `actionLive()`,`state()` 直接返回 `Service.data()`;恢复初始化的价格曝光和待发奖励处理、恢复 `recoverDelivery()` 正式处理,移除渲染中的测试有效期分支。 3. 删除 `tools/test-pyramid-animation-debug.cjs` 及隔离预览中的调试模块和会话引用;检查 `rg "PYRAMID_ANIMATION_DEBUG|PyramidAnimationDebug|actionDebug|animationDebug|debugSession" assets` 无匹配。 4. 重新执行类型检查、`tools/test-pyramid-client.cjs`,并完成真机支付成功、取消、恢复、抽奖上楼及领奖验收。 `SummitGlow` 是预制体内位于 `SummitPrize` 后方的独立光效节点,由面板以每秒 60 度持续旋转;它属于正式表现,不随测试代码一起删除。