bug反馈6.5 ¶
问题1:
状态:验收通过
现象:诸葛黄月英同时战斗时 黄月英被动3激活后 还会死在诸葛亮前面
预期:诸葛亮和黄月英同时上场战斗时 黄月英激活了被动3 在任何副本战斗都不会比诸葛亮更先死
截图:


修复过程:
- 根因:客户端战斗逻辑只会注册服务端下发到 battleData.skill 的被动技能;黄月英“友方诸葛亮存活时,受到致死伤害保留 1 点生命不会阵亡”实际由觉醒被动技能 11071 触发并添加不死标签 70004。生产一区存在历史角色脏数据,部分武将
awakeSkill[index]=true,但heroes.<heroId>.skill[index].skillId仍是旧普通被动,导致服务端构建战斗数据时没有下发对应觉醒被动,客户端自然不会触发保命效果。 - 生产影响面:已抽查生产一区全角色,发现该问题不是黄月英单点问题,而是通用觉醒被动存档不一致;共扫 22400 个角色,1599 个角色存在觉醒状态与技能 ID 不一致,涉及 63 类武将/技能位。黄月英只是其中一个表现明显的案例。
- 修复:服务端战斗技能提取逻辑已改为以
awakeSkill和配置表HeroConf.awakePassive为准进行归一化;只要某个被动位已觉醒,战斗数据下发时就使用配置中的觉醒被动技能 ID,不再盲信角色存档里的旧skillId。该修复对所有武将通用,不硬编码黄月英。 - 自动化验证:新增
TestExtractActiveSkillIDs_NormalizesAwakePassiveFromAwakeSkill,覆盖“角色存档仍是旧被动,但 awakeSkill 已觉醒时,战斗技能列表应下发觉醒被动”的回归场景。执行GOCACHE=/tmp/go-build go test ./domains/core/competitive -count=1通过;执行GOCACHE=/tmp/go-build go test . -run TestDoesNotExist -count=1通过。
人工回归建议: - 使用同时拥有并上阵诸葛亮和黄月英的账号,确认黄月英对应被动已觉醒;进入主线或副本战斗,让黄月英先承受致死伤害,诸葛亮仍存活时黄月英应保留 1 点生命,不应先阵亡。
- 使用生产一区历史老账号或从生产数据复制的脏数据账号回归:黄月英
awakeSkill已觉醒但存档skillId仍是旧被动时,进入战斗仍应正常触发保命效果。 - 抽查其他存在同类脏数据的武将,例如诸葛亮 104、103、106、107 等,确认觉醒被动在战斗中按配置生效,避免只修黄月英单点。
- 刷新、重登、切换阵容后再次进入战斗,确认战斗下发技能仍按觉醒状态归一化,不会回退到旧普通被动。
- 额外建议上线后执行一次生产数据修复脚本,把已觉醒武将的旧
skillId同步改成配置表觉醒被动 ID,避免非战斗界面或旁路逻辑继续读到脏数据。
问题3:
状态:验收通过
备注:未拥有武将应该是整将 已拥有武将碎片应该是*8
现象:铂金宝箱和钻石宝箱开出来的武将都是1个碎片
预期:铂金宝箱和钻石宝箱开出的碎片为整将
截图:


修复过程:
- 根因:客户端开箱弹窗按奖励
type渲染,type=3会按ItemConf显示为武将碎片;服务端server/internal/systemx/store_tower_item.go的铂金/钻石宝箱随机武将池原本生成type=3、value=1的物品奖励,所以客户端只能显示“武将碎片 x1”。 - 修复:将铂金宝箱 2004、钻石宝箱 2005 的武将随机池改为
type=4英雄奖励;开箱服务端新增type=4处理,未拥有该武将时调用createHero6创建整将,写入heroes.<heroId>,递增heroCount,并在回包reward、role.heroes、role.heroCount中同步给客户端。 - 二次根因:验收反馈明确“已拥有武将碎片应该是 *8”。复查
ItemOpenBoxFieldized的type=4分支发现,抽到已拥有武将或同一次十连重复抽到同一武将时,服务端虽然不再重复创建heroes,但碎片兜底数量仍写死为1,回包会继续显示“武将碎片 x1”。另外该分支原先没有提前读取items.<heroId>.quantity,即使持久化增加碎片,在线回包role.items[heroId].quantity也可能只按本次增量返回,导致客户端数量刷新不完整。 - 补充修复:新增
openBoxOwnedHeroFragmentReward=8,已拥有/本次重复武将兜底统一返回并持久化type=3,itemId=<heroId>,value=8;同时把type=4英雄奖励 ID 加入开箱前读取路径,确保role.items[heroId].quantity返回开箱后的绝对数量。未拥有武将仍返回type=4,value=1并创建整将,不增加碎片。 - 生产日志:2026-06-06 15:19 左右生产一区 Docker stdout 可见多条
item_openbox,其中包含itemId=2004/2005开箱记录,但当前 stdout 只打印response.keys,不打印reward明细,因此不能直接从 stdout 判断奖励明细;生产一区 game-server 容器已运行约 8 小时,尚未包含本次补充修复,需部署后回归。 - 自动化验证:已新增/更新
server/internal/systemx/store_tower_item_test.go,覆盖未拥有武将创建整将、已拥有武将兜底8碎片、2004/2005 武将池类型、原宝箱概率比例;先执行GOCACHE=/tmp/go-build GOTMPDIR=/tmp go test ./internal/systemx -run TestItemOpenBoxFieldized_OwnedHeroRewardFallsBackToEightFragments -count=1红灯复现旧逻辑返回value=1,修复后执行GOCACHE=/tmp/go-build GOTMPDIR=/tmp go test ./internal/systemx -count=1通过。
人工回归建议: - 使用未拥有部分紫/橙/红武将的测试账号,分别开 1 次铂金宝箱和 1 次钻石宝箱,确认奖励弹窗展示为整将图标,不再出现“武将碎片 x1”。
- 开箱后立即查看武将列表,确认新抽到的武将已进入列表,刷新/重登后仍存在,
heroCount不丢失。 - 使用已拥有对应武将的账号再开宝箱,确认不会覆盖原武将数据,重复武将按碎片
x8兜底到账,奖励弹窗不再显示x1。 - 十连开铂金/钻石宝箱,确认固定奖励正常到账:铂金宝箱仍给进阶石,钻石宝箱仍给钻石;开箱积分/活动进度表现与修复前一致。
问题4:
状态:验收通过
待验证
现象:咸王梦境内选择上阵武将不足5个时 进入后显示武将全部阵亡
预期:不管上阵几个都可以正常进入攻打boss
截图:

修复过程:
- 根因:客户端
NightmareDeployDataAdapter保存咸王梦境阵容时允许 1-5 个武将,team_setteam服务端也会把非空槽位整包写入nightmareTeam,没有必须 5 个武将的保存限制。问题出在进入房间读roomInfo时,服务端ensureNightmareRoomFightRoleBattleData只在成员battleData.team为空时才重建战斗快照;如果房间已经存在旧的 5 格/全死快照,玩家再改成少于 5 个武将,准备态房间仍沿用旧快照下发。客户端NightmareBattlePanel._allDead根据roomInfo.playerTeamInfo[roleId].curHeroData判断存活,收到旧的全死快照后显示“武将已全部死亡”。 - 修复:
server/compat_ws_bridge.go新增nightmareMemberNeedsBattleDataRefresh,在空快照时继续修复;在房间未开战且无战斗进度时,即使已有非空battleData.team,也重新用当前nightmareTeam构建成员战斗快照。已开战或已有进度的房间不刷新,避免覆盖战斗后的剩余血量/死亡状态。同时保留playerTeamInfo使用完整int64(roleId)的兼容加固,避免大 roleId 客户端取不到自己的血量信息。 - 自动化验证:新增
TestNightmareMemberNeedsBattleDataRefresh_RefreshesFreshPrepareSnapshot覆盖“准备态已有旧快照也要刷新”;新增TestNightmareMemberNeedsBattleDataRefresh_KeepsProgressSnapshot覆盖有进度房间不覆盖血量;新增TestNightmareMemberNeedsBattleDataRefresh_RepairsEmptySnapshot覆盖空快照修复。执行GOCACHE=/tmp/go-build go test . -run 'TestNightmareMemberNeedsBattleDataRefresh|TestNightmareRoomVisibleForRead|TestValidateNightmareTeamCanStart|TestNightmareMatchTeam'、GOCACHE=/tmp/go-build go test . -run 'TestNightmare|TestBuildNightmare|TestApplyNightmare'、GOCACHE=/tmp/go-build go test ./domains/pve/nightmare、GOCACHE=/tmp/go-build go test ./domains/social/team -run 'TestBuildSetTeamFieldizedResponse|TestBuildFieldizedTeamPatch|TestApplyNightmare|TestBuildPresetTeamsResponse'通过。 - 2026-06-07 补充根因:最新测试服协议日志显示玩家
100216517/rty520520在 21:27:33 发送dungeon_selecthero,服务端返回code=2,msg=请选择5名武将。客户端DungeonModule.selectDeployHeros()会把选择的 1-5 个武将通过DungeonService.selectHero({battleTeam})发给服务端;服务端server/domains/pve/dungeon/write.go#SelectHeroFieldized仍写死len(heroKeys) != 5就拒绝,导致少于 5 个的咸王梦境选将保存入口没有真正放开。此前roomInfo旧快照修复只覆盖进入房间读路径,没有覆盖dungeon_selecthero保存路径。 - 2026-06-07 补充修复:
SelectHeroFieldized改为允许 1-5 个有效武将,0 个仍拒绝,超过 5 个仍拒绝;构建后如果没有任何有效武将也拒绝,避免空队伍写入。 - 2026-06-07 补充验证:新增
TestSelectHeroFieldized_AllowsPartialTeam,先确认旧逻辑红灯返回“请选择5名武将”,修复后执行GOCACHE=/tmp/go-build GOTMPDIR=/tmp go test ./domains/pve/dungeon -run TestSelectHeroFieldized_AllowsPartialTeam -count=1通过;GOCACHE=/tmp/go-build GOTMPDIR=/tmp go test ./domains/pve/dungeon -count=1通过;GOCACHE=/tmp/go-build GOTMPDIR=/tmp go test . -run 'TestDungeon|TestNightmareMemberNeedsBattleDataRefresh|TestNightmareRoomVisibleForRead|TestValidateNightmareTeamCanStart|TestNightmareMatchTeam' -count=1通过;git diff --check -- server/domains/pve/dungeon/write.go server/domains/pve/dungeon/write_test.go通过。
人工回归建议: - 先创建/进入一次咸王梦境房间,再回到上阵界面把梦境阵容改成 1 个武将,重新进入房间,确认该武将显示存活,不再提示“武将已全部死亡”。
- 按 1、3、4、5 个上阵武将分别保存并进入房间,确认非空槽位都显示正确血量,空槽不影响开战。
- 在房间内开战一次后确认死亡/剩余血量状态会保留;战斗已有进度后再次进入房间,不应被准备态刷新逻辑重置血量。
- 使用大 roleId 和普通小 roleId 测试账号各回归一次,确认
playerTeamInfo能按当前roleId正确取到自己的curHeroData。
问题5:
状态:已修复
待验证 未开启
备注:修复过程:根据截图确认入口为怪异塔-怪异寻宝合成棋盘。重新排查后确认客户端本次不作为根因;服务端 HandleMergeItem 原本在两格均为物品、gridItemId 相同后,又额外用 isNeighborPos 拦截上下左右相邻格,并返回“相邻位置不能合成”。该规则与“相同怪物必
定能合成更高级怪物”的预期冲突,且旧测试 TestHandleMergeItem_RejectsNeighborMerge 把错误规则固化。已移除服务端相邻拒绝逻辑,保留两格存在、均为物品、gridItemId 相同、存在下一阶配置的合成校验;将回归测试改为 TestHandleMergeItem_AllowsNeighborMerge,覆盖相邻相同怪物可合成并持久化升级结果。
人工回归建议:1)进入怪异塔-怪异寻宝,将两个上下或左右相邻的同级同名怪物互相拖拽,确认立即合成为下一阶怪物;2)刷新/重登后确认源格为空、目标格保持下一阶怪物,没有回退;3)用两个不同怪物互拖,确认仍不能合成且不会吞物品;4)用最高阶或无 nextLevelMergeItem 的相同怪物互拖,确认不会异常消失;5)点击一键合成,确认仍可正常合成并播放表现。
现象: 怪异塔内怪异寻宝 两个相同的怪物拉倒一起不能合成成功
预期:相同的怪物必定能合成更高级的怪物
截图:
问题6:
状态:未处理
现象:灯神挑战和深海灯神存在赢了判定输
预期:每个国家灯神挑战和深海灯神每一关都不会存在赢了判定输的情况
截图:
问题7:
状态:已修复 验收通过
现象:充值后 游戏内功法凝神香特权没激活
预期:根据充值金额正常解锁对应特权等级
截图:
根因:客户端凝神香特权弹窗读取 ROLE.statistics["legacy:charge"] 和 ROLE.statisticsTime["legacy:charge"] 计算本赛季累计充值;功法商店购买入口使用 EMChargeType.legacy=40。服务端 charge_createorder 只把 37/5/15/18 接入新支付订单,40 号功法订单会返回临时旧订单形态,无法进入持久支付发货链;同时 DeliverOrder 只有 chargeType=1000 才写 legacy:charge。因此功法充值到账后奖励可发放,但凝神香累计仍为 0,弹窗显示“未激活/0/30”。
客户端代码:client/assets/game/scripts/LegacyPrivilegeDialog.js 展示进度和激活状态;client/assets/game/scripts/LegacyModule.js#getLegacySeasonChargeAmount 从 ROLE.statistics / ROLE.statisticsTime 读取 legacy:charge;client/assets/game/scripts/LegacyShopPanel.js 功法商店购买时发送 EMChargeType.legacy。
服务端代码:server/compat_fieldized_bridge.go#createChargeOrderInfo 已将 type=40 接入新支付订单;server/internal/payment/special_orders.go 已按 LegacyShopConf 生成包含功法和附加奖励的持久订单;server/internal/payment/delivery.go 已拆分真实 VIP 充值和凝神香累计,40 号订单只写 legacy:charge,不增加 VIP 点/总充值点。
日志:检查 server/logs 和 server/runtime/logs/client_track 未找到截图角色/时间窗内可用的支付订单链路日志,根因通过客户端字段读取、服务端下单/发货代码链路和回归测试确认。
修复过程:先补充失败用例覆盖 type=40 功法订单应从 LegacyShopConf 入新支付订单,以及发货后应写入 legacy:charge 但不改 VIP;确认失败后新增 resolveLegacyShopOrder、ChargeTypeCountsAsLegacyPrivilege,并把 charge_createorder 40 号入口接入新支付订单。
验证:GOCACHE=/tmp/go-build go test ./internal/payment;GOCACHE=/tmp/go-build go test . -run 'TestCreateChargeOrderInfo_CardEntryUsesPaymentOrder|TestCreateChargeOrderInfo_BattlePassEntryUsesPaymentOrder|TestChargeCreateOrderHandler_WiresCreateOrderDependency';GOCACHE=/tmp/go-build go test ./entry/commerce/commerceentry;GOCACHE=/tmp/go-build go test ./internal/gameplay/legacyx 均通过。
人工回归建议:测试服打开功法商店购买 30 元及以上功法礼包,支付回调发货成功后不重登直接打开凝神香弹窗,确认进度从 0 增加、达到 30 元后显示凝神香一已激活;继续购买到下一档,确认累计金额和档位提升正确;同时确认角色 VIP 点、总充值点没有因功法礼包额外增长,礼包内功法和附加道具正常到账。
问题8:
状态:待验证
备注:奖励到账不正确 四圣碎片 四圣红玉 武将皮肤 宠物脆饼 没有
截图:


待验证
现象:购买通行证后没有解锁战令;测试角色 151830/fafa 手动模拟 12800、16800 发货时,经验道具 4203 已增加,但客户端仍显示未解锁。
预期:购买竞技之路通行证后立即解锁,并赠送 15 级战令经验;16800 档应解锁高级档状态,解锁状态应持久保留一期。
根因:客户端竞技之路配置为 BattlePassBaseConf.1,经验道具 itemId=4203,普通价格 12800,高级直购价格 16800,已买普通档后的高级补差价格原为 4000,本次仅服务端先改为 2000。客户端 12800 购买发送活动 id 1,16800 高级直购发送商品 id 10003,已买普通档后升级发送商品 id 10002;服务端旧逻辑没有把 10002/10003 归一到真实活动 1,导致高级档不能稳定写入 warOrderActivityInfo.1.purchased3=true,并且补差 10002 旧逻辑会重复带 15 级经验奖励。普通 12800 发货虽已写入 DB 的 warOrderActivityInfo.1.purchased=true 并增加 4203,但支付在线推送只带 role/items,不带顶层 activity.warOrderActivityInfo,客户端 SERVER_DATA.activity 未刷新,所以界面仍显示未解锁。后续继续排查“补 20 后页面解锁但奖品没收到”时,发现客户端购买弹窗底部展示的“超级跑车特权”奖励来自 CarConstantConf.NewBattlePassAdditionalRewards,不是 BattlePassConf.payReward2;服务端配置缺少该字段,且创建 10002/10003 订单时没有把这组额外奖励加入 rewardsSnapshot,所以页面显示了 成长脆饼x3000、军团币x12000 等,但服务端发货未按客户端配置发放。继续排查“超级跑车特权剩余有效期 00:00:00”时确认,客户端 cargoRaidData.getSuperCarRemainTime() 读取 ROLE.statisticsTime["paid:car:s"],而服务端此前把额外奖励 type=3,itemId=35001 当普通背包物品写入 items.35001,没有顺延 statisticsTime.paid:car:s,所以客户端只能显示 0。
客户端代码:client/assets/game/scripts/NewArenaBattlePassDialog.js 竞技之路购买普通档调用 sendPay(actPayType, 1, 12800, ...),高级直购调用 sendPay(actPayType, 10003, 16800, ...),普通档已购买后的升级当前旧客户端配置仍可能调用 sendPay(actPayType, 10002, 4000, ...);client/assets/game/scripts/types-battle-pass.js 定义 carBattlePassId=1、carBattlePass40Id=10002、carBattlePass168Id=10003,并通过 getArenaBattlePassAdditionalRewards() 在新竞技之路开启后读取 CarConstantConf.NewBattlePassAdditionalRewards;client/assets/game/scripts/NewArenaBattlePassBuyDialog.js 把该额外奖励渲染到购买弹窗底部;client/assets/game/scripts/ActFestivalBattlePass.js/ActAreanBattlePass.js 从 SERVER_DATA.activity.warOrderActivityInfo.get(activityId) 的 purchased/purchased3 判断是否已解锁。
服务端代码:server/internal/payment/special_orders.go 已将 10002/10003 归一到真实活动 1;10003 订单保留 goodsId=10003、activityId=1、价格取 BattlePassBaseConf.price3=16800,奖励快照包含 type=20,itemId=101、4203 的 15 级经验,以及 CarConstantConf.NewBattlePassAdditionalRewards;10002 订单保留 goodsId=10002、activityId=1、价格取 BattlePassBaseConf.price2=2000,奖励快照包含 type=20,itemId=101 和 CarConstantConf.NewBattlePassAdditionalRewards,不重复增加 4203。server/internal/payment/rewards.go 发放高级/补差档时调用 MarkWarOrderPremiumPurchased,写入 purchased=true 和 purchased3=true,并把 type=3,itemId=35001 转换为超级跑车特权有效期顺延 28 天;server/internal/payment/delivery.go 发货结果增加 activity.warOrderActivityInfo 片段,并支持通行证字段补丁里的 diamond 增量和 statisticsTime.paid:car:s 更新,避免带金砖/超级跑车额外奖励时退回整角色保存覆盖领取状态;server/internal/rolecachex/store.go 在角色冷加载时把历史错发到 items.35001 的数量迁移为 statisticsTime.paid:car:s 有效期并移除背包项;server/compat_ws_bridge.go#pushPaymentDeliveryNotify 将该 activity 片段合进 syncrewardresp 和 charge_successnotify,在线客户端不重登也能刷新解锁状态。
截图/日志:截图 image-2026-06-04T19-36-50-122Z.png 显示购买后仍未解锁。2026-06-06 使用本地 Mongo 对角色 151830/fafa 模拟发货确认:12800 后 4203 增加且 DB 写入 warOrderActivityInfo.1.purchased=true,但客户端未收到 activity 同步;16800 旧链路会错误写到 warOrderActivityInfo.10003,无法驱动竞技之路活动 1 的高级解锁。
修复过程:1)按 TDD 先撤回未验证生产改动;2)新增失败用例覆盖 10003 -> activityId=1/price3=16800、12800 发货必须返回 activity 同步、16800 发货必须写 warOrderActivityInfo.1.purchased/purchased3 且不能创建 10003 活动状态;3)确认红灯失败分别为 BattlePassBaseConf 10003 missing 和 DeliveryResult missing Activity payload;4)实现商品 id 归一、高级档购买状态写入、发货 activity payload、在线推送合并 activity;5)根据 128 已解锁后的真实客户端路径,补充红灯用例 TestDeliverOrder_ArenaBattlePassUpgradeUnlocksPremiumWithoutDuplicateExp,确认补差旧逻辑会重复给 4203,修复为补差只写高级解锁不重复给经验;6)测试服重新打包部署后,对 151830/fafa 发 10002/4000 补差订单,确认 warOrderActivityInfo.1.purchased3=true 且 4203 保持 1330 未增加;7)2026-06-06 按“加 2000 解锁高级档”要求,先加真实配置红灯测试 TestConfig_ArenaBattlePassUpgradePriceIs2000,确认 server/config/config.json 仍为 4000 后,将服务端 BattlePassBaseConf.1.price2 改为 2000,客户端配置暂不改;8)针对“补 20 后页面解锁但没有领取按钮/奖励”的追查,确认现有竞技之路 BattlePassConf.actId=1 的 payReward2 全为空,客户端领取按钮只看 rewardClaimed+purchased,不看 purchased3;同时补充红灯用例 TestDeliverOrder_ArenaBattlePassUpgradePatchesWithoutOverwritingClaimedRewards,修复补差发货通过整角色 SaveRole 覆盖已有 rewardClaimed 的风险,改为对通行证支付发货仅 patch privilege.101、purchased/purchased3 和 4203 增量等变更字段;9)按客户端配置重新定位到 CarConstantConf.NewBattlePassAdditionalRewards,新增 TestConfig_ArenaBattlePassNewAdditionalRewardsMatchClient、高级直购/补差订单快照和发货到账红灯用例,补齐服务端 CarConstantConf.NewBattlePassAdditionalRewards,并在 10002/10003 订单中追加该额外奖励;10)文档 server/docs/battlepass-external-delivery.md 同步更新外部订单示例和人工校验字段;11)针对超级跑车有效期显示 0,补充 TestApplyNumericRewards_SuperCarPrivilegeExtendsPaidCarSuperWithoutBagItem 和通行证补差 patch 用例,确认 35001 不再落背包,改为顺延 statisticsTime.paid:car:s;12)补充角色冷加载迁移用例,覆盖旧数据 items.35001 按数量转成 28 天/个并移除背包项。
验证:GOCACHE=/tmp/go-build GOTMPDIR=/tmp go test -count=1 ./internal/payment 通过;GOCACHE=/tmp/go-build GOTMPDIR=/tmp go test -count=1 ./domains/activity/battlepass ./internal/payment 通过;GOCACHE=/tmp/go-build GOTMPDIR=/tmp go test -count=1 -run TestMergePaymentActivityPayload_AddsWarOrderInfo . 通过。测试服 deploy/bin/update.sh test 已重新部署;/api/ready 返回 mongodb/redis ready。2026-06-06 对 390697/fafa 逐步验证:发 goodsId=1/12800 普通档订单后,4203 从 30 到 630,warOrderActivityInfo.1.purchased=true;再发 goodsId=10002/2000 补差订单后,订单 chargeCent=2000/paidCent=2000 delivered,warOrderActivityInfo.1.purchased3=true,4203 保持 630 未重复增加。2026-06-06 追加优化后,GOCACHE=/tmp/go-build GOTMPDIR=/tmp go test -count=1 ./internal/payment 通过;GOCACHE=/tmp/go-build GOTMPDIR=/tmp go test -count=1 -run TestMergePaymentActivityPayload_AddsWarOrderInfo . 通过;测试服已重新部署,/api/ready 返回 mongodb/redis ready。2026-06-06 补齐超级跑车特权额外奖励后,再次执行 GOCACHE=/tmp/go-build GOTMPDIR=/tmp go test -count=1 ./internal/payment、GOCACHE=/tmp/go-build GOTMPDIR=/tmp go test -count=1 -run TestMergePaymentActivityPayload_AddsWarOrderInfo .、jq empty server/config/config.json、git diff --check 均通过;测试服由人工更新后,容器 xianyu-test-game-server healthy,/api/health OK,/api/ready 返回 mongodb/redis ready。根包全量 go test -count=1 . 仍有多处既有失败(如 client_track、PK watcher、盐场/航海、PVE 默认形态等),与本次通行证链路无关。
人工回归建议:1)用测试角色购买竞技之路 12800 档,支付回调成功后不重登直接返回通行证页,确认按钮变为已解锁、付费奖励栏可见、4203 经验推进到 15 级;2)在 12800 已解锁后通过外部发货或服务端创建订单走 10002/2000 补差,支付成功后 purchased3 生效,4203 不重复增加,超级跑车特权剩余有效期顺延 28 天,10101x1、10003x2、15001x3000、1014x12000、金砖400 到账,不以 items.35001 作为验收口径;3)清理或换号后购买 16800 直购档,确认普通解锁和高级档 purchased3 同时生效,不出现 warOrderActivityInfo.10003 作为活动状态,同时确认 4203x600、超级跑车特权 28 天和其他额外奖励都到账;4)点击领取 1-15 级奖励,确认免费/付费奖励到账且已领取状态刷新;5)重复同一订单回调,确认不会重复增加 4203、额外奖励或重复解锁/发奖;6)刷新、重登、跨天后再次进入竞技之路和超级跑车入口,确认 warOrderActivityInfo.1.purchased/purchased3 仍存在,超级跑车剩余有效期不回退为 00:00:00;7)客户端配置未同步前,不要用旧客户端 4000 补差支付链路判断服务端 2000 是否生效。
新验收备注补充根因:2026-06-06 新截图里第 1 级付费奖励显示了武将皮肤,来源不是静态 BattlePassConf.payReward,而是客户端 ActAreanBattlePass._updateSkinReward() 按 BattlePassBaseConf.1.newSkinRewardLv=1、当前轮次和 skinReward 动态追加 ResourceType.SKIN=11;服务端 ClaimRecycleWarOrder 领取等级奖励时只读取静态 BattlePassConf.payReward,且 applyRewards/claimPatchSet 只处理金币、金砖和普通道具,不支持 type=11 写入 heroes.<heroId>.skin.<skinId>,所以点击领取等级奖励后武将皮肤不会到账。当前真实配置计算为第 47 轮,动态皮肤为 skinId=3017,SkinConf.3017.heroId=117。截图备注里的四圣红玉、宠物成长脆饼属于高级档购买额外奖励链路,已由 CarConstantConf.NewBattlePassAdditionalRewards 发货链路覆盖;等级领取链路本次新增修复的是动态武将皮肤漏发。
新验收备注修复过程:新增失败用例 TestClaimRecycleWarOrder_ClaimsNewArenaDynamicSkinReward,用最小配置复现新竞技之路第 1 级动态皮肤只在客户端显示、服务端不发的问题;随后在 server/domains/activity/battlepass/recycle.go 增加 LoadBattlePassRowsAt,按服务端时间复刻客户端轮次逻辑,把 BattlePassBaseConf.skinReward 的当期皮肤补入对应等级的 PayReward;再根据 SkinConf[skinId].heroId 定位武将,发奖时写入 heroes.<heroId>.skin.<skinId> 和 heroes.<heroId>.useSkin,返回奖励也保留 type=11/itemId/heroId。
新验收备注验证:GOCACHE=/tmp/go-build GOTMPDIR=/tmp go test ./domains/activity/battlepass -run TestClaimRecycleWarOrder_ClaimsNewArenaDynamicSkinReward -count=1 通过;GOCACHE=/tmp/go-build GOTMPDIR=/tmp go test ./domains/activity/battlepass -count=1 通过;GOCACHE=/tmp/go-build GOTMPDIR=/tmp go test ./domains/activity/battlepass -run TestPlan16ArenaBattlePassRewardsScaled -count=1 通过;git diff --check -- server/domains/activity/battlepass/recycle.go server/domains/activity/battlepass/recycle_test.go 通过。日志检索 server/logs/2026-06-06、server/runtime/logs/client_track/client_track-2026-06-06.log 未找到新截图对应的领取协议记录,本次根因通过截图、客户端代码、服务端领取代码和定向测试确认。
新验收备注人工回归建议:购买 12800 或 16800 并获得足够 4203 后进入竞技之路,先不要只看购买弹窗奖励;点击领取第 1 级付费奖励,确认奖励弹窗/背包/武将皮肤页出现当前轮次皮肤,当前配置为武将 117 的 skinId=3017,并确认 heroes.117.skin.3017 持久存在;再领取第 10 级等奖励,确认普通道具继续到账且已领取状态刷新;最后分别验证高级档购买额外奖励 10101x1、10003x2、15001x3000、1014x12000、金砖400、超级跑车28天,不要把购买额外奖励和等级领取奖励混为同一个验收点。
截图:
问题9:
状态:已修复验收通过
根因:服务端把充值/VIP累计点数复用了挂机等级奖励字段 hangUp.activeOrder/lastClaimedOrder,新号初始VIP点数906、充值后1000等值会被客户端当成挂机等级奖励“已领取”,所以界面自动显示已领取但没有真正走 claimHangUpOrder 发奖。
修复过程:1)新号初始化不再把 StarterVIPPoints 写入挂机等级奖励字段,只保留到 Statistics.MonthArtifact2/ChargeTotal/VipPoint;2)正式支付和离线礼包发放改为通过支付统计累计充值点数,不再写 hangUp.activeOrder/lastClaimedOrder;3)登录/挂机归一化会清理超过挂机奖励最大档位10的旧污染值,旧号下次登录后可重新看到可手动领取的等级奖励;4)补充新号、旧污染值迁移、VIP点数发货、登录归一化测试。
人工回归建议:1)用新号或清理后账号登录,进入挂机奖励-等级奖励,确认达到等级的奖励显示可领取而不是已领取;2)点击等级奖励领取,确认道具/金币到账且刷新后状态变为已领取;3)对已有 hangUp.activeOrder=906/lastClaimedOrder=906 的旧号登录一次,确认字段被修正且等级奖励可重新手动领取;4)充值或后台补VIP点数后,确认VIP点数/充值统计增加,但挂机等级奖励状态不被自动改成已领取;5)离线礼包发放路径也回归一次,确认礼包奖励到账、VIP点数增加、挂机等级奖励不受影响。
现象:挂机奖励内 等级奖励会自动领取 且奖励不到账
预期:达到等级需要玩家手动领取 且奖励正常到账
截图:

问题10:
状态:待回归(配置已修复,测试服运行时已同步)
根因:普通艾草 ItemConf.5242 的预览包 PackConf.90.packShow 里有金艾草 5243,但实际随机池 PackConf.90.diamondPackRewardWeight 缺少 5243,且权重总和只有 9998。客户端展示的是 packShow,服务端开包实际按 diamondPackRewardWeight 抽取,所以界面看得到金艾草但永远抽不到。回归阶段又发现测试服容器内运行时 /app/config/config.json 未同步最新源码配置,5243 仍是旧低权重 2/10000,所以少量开包仍几乎不会出金艾草。
客户端代码:艾草道具 tooltip/奖励预览按 ItemConf.5242.params -> PackConf.90.packShow 展示;客户端不会参与实际随机。
服务端代码:开包走服务端 PackConf.90.diamondPackRewardWeight 实际随机池;此前 6.2 问题8已修过“随机包不能按自选 index 领取 packShow[0]”,所以本次不能改回客户端选择,必须补实际随机池。当前 handler 为 compat_fieldized_bridge.go:item_openpackHandler -> buildConfiguredOpenPackRewards(evotowerConfigRoot(), itemId, number, rng),运行时读取 globalConfig.Data["config"]。
日志/截图:截图 image-2026-06-04T20-10-51-665Z.png 显示普通艾草预览含金艾草;2026-06-08 18:47 测试号 rty520520/100216517 连续请求 item_openpack seq 137~142,stdout 只显示响应成功和部分 item_audit,其中 seq 139/142 分别获得 1006 x888/x1088,未获得 5243。随后读取测试服容器内运行时配置确认 PackConf.90 的 5243 权重仍为 2,与源码 2500 不一致。
修复过程:1)服务端/客户端配置 PackConf.90.diamondPackRewardWeight/packShow/foldPackShow 同步包含金艾草 5243;2)当前目标权重为 5243 weight=2500,总权重保持 10000;3)新增 TestPlan13DragonBoatArtemisiaPackRewardsIncludeGold 校验服务端和客户端配置镜像都包含金艾草且权重正确;4)2026-06-08 18:53 已将测试服挂载目录 /tmp/xianyu-server-test-runtime/config/config.json 同步为源码配置并重启 xianyu-test-game-server,重启后容器内 PackConf.90 确认 5243 weight=2500,total=10000,健康检查正常。
人工回归建议:发放普通艾草 5242 给测试号,重新登录后打开 tooltip 确认预览仍显示金艾草;批量开艾草确认随机结果中可出现 5243,当前测试服权重为 25%,少量开包仍可能不出但连续 10 次不出的概率已明显降低;重新登录后确认金艾草数量不回退。
现象:端午活动内 获得的艾草开不出金艾草
预期:根据概率可以正常开出金艾草
截图:
问题11:(见6.2问题9)
状态:待回归(配置已核对)
根因:6.2 问题9已经修过端午兑换奖励配置;本次核对当前服务端/客户端配置,ExchangeActConf.250530201~250530205 已是 1 星鱼 11151/11131/11141/11111/11121,其余奖励 250530207~250530211 已是 1013 x10、3201 x10、3007 x20、1022 x5000、3008 x60。若线上仍显示五星鱼或未放大,根因更可能是客户端包/热更配置未更新或缓存仍在旧配置。
客户端代码:兑换页读取 ExchangeActConf.resourceType/rewardId/rewardNum 展示奖励,鱼星级由 ArtifactConf.fishStar 决定。
服务端代码:activity_rewardresp 通过 QueryExchange 读取同一份 ExchangeActConf 发奖;鱼灵 ID 已指向 1 星鱼。
日志/截图:截图 image-2026-06-04T20-14-25-746Z.png、image-2026-06-04T20-14-29-895Z.png 是旧表现;当前日志未找到可关联本次截图角色的兑换轨迹。
修复过程:本次未新增业务代码,只把 6.2 的配置修复纳入 TestPlan13DragonBoatFestivalConfigMirrors 覆盖,确认服务端和客户端配置镜像一致。
人工回归建议:更新到最新配置/客户端包后打开艾草兑换页,确认 5 条鱼均显示 1 星;分别兑换鱼和其他奖励,确认鱼到账为对应 1 星鱼,其他奖励数量分别为 10、10、20、5000、60。
现象:艾草兑换内的奖励金鱼显示还是五星金鱼 其与奖励显示也没×十倍
预期:艾草兑换的金鱼为1星金鱼 其余奖励×十倍
截图:

问题12:
状态:待回归(服务端/配置已修复)
根因:兑换行 ExchangeActConf.250530206 配成了 resourceType=51,而客户端 ResourceType.51 是 SQUAD_SLOT,不是 PVP 地图;同时服务端 activity_rewardresp 只支持金币/钻石/道具/头像框,遇到地图类奖励会返回不支持或无法写入外观拥有状态。客户端兑换弹窗按 ResourceType.PVP_MAP=50 读取 PVPMapConf,但 PVPMapConf.80001 缺失,所以兑换地图奖励后容易出现空奖励/空展示。
客户端代码:ItemExchangeDialog2 对 ResourceType.PVP_MAP 读取 PVPMapConf.getById(itemId) 设置品质;ActCollectionShopModule.exchangeGoods 对 PVP 地图走外观获得弹窗和 HOLY_BEAST.useDress 装备逻辑。
服务端代码:compat_fieldized_bridge.go 的 activity_rewardresp 委托 internal/activityx.ActivityExchangeFieldized;修复前 festivalRewardSupported/applyFestivalReward 没有 type=50 分支。
日志/截图:截图 image-2026-06-04T20-15-23-820Z.png 显示奖励弹窗为空;当前日志未保留可关联该截图的 activity_rewardresp 轨迹,根因由资源类型枚举、配置缺行和服务端支持类型可确定。
修复过程:1)服务端 activity_rewardresp 支持 ResourceType.PVP_MAP=50,写入 dress.5.typ/used/storage.<id> 并返回 role.dress 和奖励 payload;2)ExchangeActConf.250530206 和 MilestoneRewardConf.5 从错误的 51 改为 50;3)服务端/客户端配置补 PVPMapConf.80001,指向 map_80001 与 items/bzcw_item_80001;4)BuildAllPvpMapsForTest 白名单补 80001;5)新增 TestActivityExchangeFieldized_GrantsPvpMapReward、TestPlan13DragonBoatExchangePvpMapReward 和外观白名单回归测试。
人工回归建议:准备测试号持有金艾草 5243 >= 250,兑换 250530206;确认奖励弹窗显示端午地图而不是空白,5243 扣 250,兑换次数变为 1/1;进入外观/竞技场景选择确认 80001 已拥有且可装备;重登后确认拥有状态和兑换次数不回退。
现象:艾草兑换奖励后 显示为空
预期:可以正常兑换并到账
截图:
问题13:
状态:待回归(服务端已修复)
根因:端午商城免费礼包 MerchandiseConf.25053031 有两个奖励 1001 x5 和 1012 x2,但 activity_buygoods 服务端只读取并发放 items[0],响应里也只返回第一个奖励;免费礼包或多奖励礼包领取后客户端弹窗缺奖励/看起来无法领取。该路径还把部分非道具奖励按道具处理,后续商城钻石奖励也有错发风险。
客户端代码:ActCollectionShopModule.buyGiftPack/活动商城领取成功后直接用服务端 reward 打开 ItemRewardsDialog,不二次补奖励。
服务端代码:compat_fieldized_bridge.go 的 activity_buygoodsHandler 委托 internal/activityx.ActivityBuyGoodsFieldized;修复前只处理 MerchandiseConf.merchandise[0]。
日志/截图:截图 image-2026-06-04T20-16-21-475Z.png、image-2026-06-04T20-16-31-288Z.png 指向免费奖励领取弹窗/状态异常;2026-06-08 16:12:07 测试区日志出现 未找到协议处理器: CMD=activity_commonbuygoods, account=rty520520,说明当前客户端商城“获得”按钮走 activity_commonbuygoods,但服务端只注册了 activity_buygoods/activity_buystoregoods。2026-06-08 16:50 测试区重启后日志显示 activity_commonbuygoods goodsId=25053031 首次返回成功并发奖,后续重复点击返回 code=5/已售空,说明服务端没有重复发奖;按钮仍可点是客户端未收到它刷新状态所需的购买次数字段。
修复过程:1)ActivityBuyGoodsFieldized 改为遍历全部 MerchandiseConf.merchandise 奖励;2)支持 type=2 钻石、type=3 道具、type=11 皮肤,并合并写入 role 响应和 reward payload;3)限购、免费价格、钻石消耗、皮肤发放原逻辑保留;4)新增 TestActivityBuyGoodsFieldized_AppliesAllMerchandiseRewards 覆盖 25053031 免费多奖励;5)服务端注册 activity_commonbuygoods 为 activity_buygoods 同处理器别名,兼容商城“获得”按钮;6)按客户端 ActivityFestivalSpringMerchandiseDialog24 期望,在购买成功和已售空响应的 activity 里同时返回 commonActivityInfo.<activityId>.record.<goodsId>=购买次数,触发 ActivityDataView 的 SyncCommonFestival 刷新按钮状态,保留旧 activityShop 字段兼容其他读取方。
人工回归建议:用未领取过的测试号进入艾草商城点击免费礼包;确认奖励弹窗同时显示 1001 x5 和 1012 x2,背包数量都增加,免费礼包变为已领取/不可重复领取;连续点击同一按钮应只返回已售空提示且不重复到账;再回归一个钻石购买礼包,确认多奖励全部到账、钻石扣除正确、限购状态刷新正确。
补充调整:端午活动 ActFestivalConf.2505301~2505305 服务端/客户端时间已统一为北京时间 2026-06-08 00:00:00 开始,2026-06-30 23:59:59 结束;白名单开始时间同步为 2026-06-08 00:00:00。
补充调整:按运营要求单独关闭龙舟争霸 ActFestivalConf.2505302,服务端/客户端 whiteListStart/start/end 置为 0;艾草悬赏、兑换、商城、集结活动 2505301/2505303/2505304/2505305 保持 2026-06-08 00:00:00 至 2026-06-30 23:59:59。
现象:艾草商城内 免费奖励无法领取
预期:可以正常领取
截图:

问题14:
状态:验收通过
根因:珍珠淬炼服务端 internal/gameplay/pearlx.resolvePearlQuenchRoll 对“本次随机到已有属性”的处理不是使用随机池生成的 attrNum/color,而是取当前已有同属性最大值,再强制随机增加 14 点并封顶 100。客户端每次点击开启都会调用 3000 贝壳观察三红获取难度明显高于旧版本。PearlStageUpDialog._getAttr -> PearlModule.sendGetRandomAttr -> pearl_quench 获取服务端预览值,所以只要不断洗到已有属性,该属性就必然单向上涨,最终三条都会到最高值。
客户端代码:PearlStageUpDialog._getAttr 发送 sendGetRandomAttr(heroId, artifactId, pearlId, tmpSlot, seed),成功后直接展示服务端返回的 pearlMap[pearlId].tmpSlot;客户端没有本地随机或加成逻辑。
服务端代码:compat_ws_bridge.go 的 pearl_quenchresp 委托 pearlx.QuenchFieldized;quench.go 生成随机属性和值后调用 resolvePearlQuenchRoll,旧逻辑在同属性命中时强制把随机结果改成“当前值 + 小幅增长”。
日志/截图:截图 image-2026-06-04T20-24-44-336Z.png 显示同属性预览从 8.4% 提升到 9.2%;当前 server/logs 与 client_track 未找到可关联截图账号/时间的 pearl_quench/pearl_replace 协议轨迹,根因由服务端确定性同属性增长逻辑可复现。
修复过程:1)resolvePearlQuenchRoll 改为同属性也保留随机池生成的 attrNum/color,只返回命中的 slotIDs 供确认替换;2)删除旧的“同属性强制增长”辅助逻辑;3)更新 TestResolvePearlQuenchRoll_*,覆盖同属性可低于当前值、可离开红色档、不会从橙色自动跳红、重复属性修复后仍使用随机值。
人工回归建议:准备一个已有高百分比词条的鱼珠,连续点击淬炼但先不确认;确认同属性预览可能升、可能降、可能保持在低档,不再每次同属性都比当前值高;确认只有点击替换/确认后才写入槽位,取消/放弃只清理临时槽并给对应回收;连续消耗约 2000
现象:鱼灵淬炼时一直会一点点增加 一直洗必定会全部达到现有词条最高值
预期:鱼灵淬炼词条百分比随机增加 降低出红概率 预期 三红需消耗2000-3000贝壳
截图:
问题15:
状态:验收通过
根因:每日任务配置使用 DailyTaskConf.completeCondition 作为进度 key:登录是 1,分享是 2,竞技场战斗是 13。客户端点击每日任务“分享”会发送 system_mysharecallback,type=3(EMShareType.task);旧服务端只在 type=2(EMShareType.hangUp) 时累加 dailyTask.complete["2"],type=3 直接返回角色,导致界面提示分享成功但分享任务仍是 0/1。竞技场战斗完成后 fight_startareaarena 只更新竞技场积分、次数、免费次数和回包 statistics,没有累加 dailyTask.complete["13"],回包/notify 也没有下发 dailyTask.complete,所以“进行1场竞技场战斗”仍显示 0/1。
客户端代码:DailyTaskDialog._refreshTaskCell 点击“前往”调用 ModuleManager.goto(t.gotoModule);分享任务的 goto 会走 ModuleManager -> ShareManager.shareMessage(ShareType.Task),ShareManager 将其转换为 EMShareType.task=3 后调用 SystemService.myShareCallback({type:3})。任务界面进度来自 DailyTaskModule._resetInitData/_onDataChanged 读取 ROLE.dailyTask.complete[completeCondition],并由 RoleDataView.updateValue 收到 syncresp.role.dailyTask 后触发 SyncDailyTask 刷新。
服务端代码:compat_fieldized_bridge.go 的 system_mysharecallbackHandler 旧逻辑只处理 req.Type == 2;compat_ws_bridge.go 的 fight_startareaarenaHandler 旧逻辑在战斗结算后没有写 dailyTask.complete.13,buildArenaRoleSyncData 也没有带 dailyTask 字段。
日志/截图:截图 image-2026-06-04T23-30-36-251Z.png 显示角色 28991|26501|dev|28 分享后弹“分享成功”但进度仍 0/1;截图 image-2026-06-04T23-30-40-166Z.png 显示“进行1场竞技场战斗”仍 0/1。已查 server/logs/2026-06-04/app-000000-000000.log 与 server/runtime/logs/client_track/client_track-2026-06-04.log,23:30 附近无该角色的 system_mysharecallback/fight_startareaarena 协议轨迹,只有服务运行状态日志;根因由确定性服务端漏写路径和配置映射验证。
修复过程:1)新增 incrementDailyTaskComplete(role, taskKey),统一初始化 DailyTask/Complete 并遵循已领取进度 -1 不再累加的规则;2)system_mysharecallback 保留挂机分享 type=2 的日常分享计数,并新增每日任务分享 type=3 时累加 dailyTask.complete["2"] 后保存角色;3)fight_startareaarena 战斗结算成功后累加 dailyTask.complete["13"];4)buildArenaRoleSyncData 在竞技场回包和 syncresp 中下发完整 dailyTask.complete 表,避免客户端日常任务缓存不刷新或被局部字段覆盖;5)新增 TestIncrementDailyTaskComplete* 和 TestBuildArenaRoleSyncData_IncludesDailyTaskComplete 回归测试。
人工回归建议:使用截图账号或任意测试号进入任务页,确认“分享1次游戏”为 0/1,点击前往分享并返回后应变为 1/1 且可领取 +5 活跃积分;领取后进度置为已领取,再次分享不应反复增加可领取状态。再确认“进行1场竞技场战斗”为 0/1,完成一场竞技场挑战后任务页应变为 1/1 且可领取 +5 活跃积分;同时确认竞技场免费次数、门票消耗、积分变化、战报回放仍正常。跨日后任务重置,再分别做一次分享和竞技场挑战,确认两个任务可重新完成。
现象:每日任务内点击分享显示成功但是不算完成任务 无法领取积分 竞技场挑战完也不计入任务
预期:点击分享算完成任务可以领取积分 竞技场挑战后计入任务
截图:

问题16:
状态:验收通过
根因:服务端没有保存“本周分组成员快照”。客户端进入竞技场后会请求 arena_startarea 和 arena_getarearank 展示榜单,请求 arena_getareatarget 获取挑战目标;旧服务端每次都按当前实时 arenaScore/lastArenaTime/roleId 重新计算全服排名,再用 groupStartRank 做 skip/limit 拉一段实时排名作为“本组”。当玩家战斗后积分变化、跨过 100 人组边界时,同一个账号再次刷新榜单/目标就会看到另一批人,截图中的组内人员因此随积分变化。
客户端代码:ArenaModule.goto 先调用 getArenaInfo -> arena_startarea,再调用 getArenaRank(EMAreaArenaRankType.default);ArenaPanel.sendGetArenaRank 刷新榜单仍调用 ArenaService.getAreaRank;挑战目标由竞技场对手接口 arena_getareatarget 返回。客户端只展示服务端返回的 rankList/roleList,没有本地重新分组逻辑。
服务端代码:compat_fieldized_bridge.go 的 arena_startareaHandler 旧逻辑只在 role.ArenaPhase[weekKey] 写一个占位 BattleTeam,buildArenaPhaseInfo 的 groupId 也固定为 1;rankx.AreaRankHandler.BuildResponse 与 arena_getareatargetHandler.matchOpponents 都按实时积分排序和实时排名窗口取人,没有使用本周锁定成员。
日志/截图:截图 image-2026-06-04T23-36-17-660Z.png 与 image-2026-06-04T23-36-21-073Z.png 均为账号 28991|26501|dev|28,同一竞技场页面前几名人员和积分明显变成另一批。已查 server/logs/2026-06-04/app-000000-000000.log 与 client_track-2026-06-04.log,23:36 附近无该账号的 arena_getarearank/arena_getareatarget 协议轨迹,只有服务运行状态日志;根因由服务端实时排名窗口分组逻辑确定。
修复过程:1)新增 models.ArenaGroupInfo 和 role.ArenaGroup[weekKey],保存每周锁定分组的 groupId/groupStartRank/roleIds/createTime;2)arena_startarea 首次进入本周竞技场时按当前排名窗口生成一次组成员 roleIds 并保存,已有锁组则不再重算;3)rankx.AreaRankHandler 检测到本周锁组后改用 roleId in lockedRoleIds 查询,组内仍按实时积分排序,但人员固定,不再用实时全服排名 skip;4)arena_getareatarget 优先从本周锁组成员内筛选 ±200 分对手,无分差内对手时也只在锁组内兜底;5)补齐 deepcopy 和 roleopt diff 对 arenaGroup 的复制/变更检测,确保锁组能通过 SafeUpdateRole 持久化;6)新增 TestArenaWeekKey_*、TestArenaLockedGroupForWeek_*、TestBuildArenaRankFindOptionsForLockedGroup_*、TestEnsureArenaGroupContainsRoleID 回归测试。
人工回归建议:使用同一测试号在本周第一次进入竞技场,记录榜单前 5 名和挑战目标列表;完成多场挑战让自己积分明显变化,再刷新榜单、重新进出竞技场、重新拉取挑战目标,确认本周可见人员仍来自同一组,仅组内排序/积分变化。另用第二个同组测试号确认看到的组成员一致;重登后确认 groupId 和组成员不变。跨到下一周或清理该角色 arenaGroup.<weekKey> 后首次进入应重新生成新组;未进入过本周竞技场的号首次进入时才创建锁组。
现象:竞技场内每组人员没锁死 会根据当前积分多少变化组内人员
预期:每一组人员锁死 不会根据当前积分变化组内人员
规则:
- 开放时间
每天 6:00~22:00 - 段位与分组规则
(1) 共有 6 阶段位,玩家初始段位为入门级
(2) 每周周一 6:00~周日 20:00,首次进入竞技场时,会按上周日结算的段位、排名,匹配段位与分组
(3) 分组后本周仅同组玩家对战
(4) 周日 20:00 停止分组,未分组的玩家将无法参与本周竞技场
(5) 每周日 24:00 结算周排名决定下周段位升降级,各段位升降级规则不同 - 各段位分组、升降级规则
【入门级竞技场】
分组范围:20 个服,每组 50 人
S4 赛季后:范围增至 100 服
S7 赛季后:范围增至 500 服
周排名前 30 晋级,其余平级
【初级竞技场】
分组范围:20 个服,每组 50 人
S4 赛季后:范围增至 100 服
S7 赛季后:范围增至 500 服
周排名前 20 晋级,后 10 降级,其余平级
【中级竞技场】
分组范围:100 服,每组 100 人
S7 赛季后:范围增至 500 服
周排名前 30 晋级,后 30 降级,其余平级
【高级竞技场】
分组范围:100 服,每组 100 人
S7 赛季后:范围增至 500 服
周排名前 20 晋级,后 40 降级,其余平级
【大师级竞技场】
分组范围:100 服,每组 200 人
S7 赛季后:范围增至 500 服
周排名前 20 晋级,后 80 降级,其余平级
【巅峰级竞技场】
分组范围:500 服,仅有一组,人数无上限
周排名前 30% 段位不变 (下取整),其余降级
【巅峰王者】:本段位前 100 人被视为「巅峰王者」,每周结算时更能获「巅峰徽章」 - 组内人数不满规则
每周结算时若组内人不满,结算优先级为:平级玩家 > 晋级玩家 > 降级玩家。以初级竞技场周结算为例:
(1) 组内仅 45 人,则先取 20 人平级,再取前 20 人晋级,最剩余 5 名玩家降级
(2) 组内仅 25 人,则先取 20 人平级,再取前 5 人晋级,无人降级
(3) 组内仅 15 人,全员平级 - 积分匹配对手规则
(1) 初始积分为 1000 分
(2) 每次匹配 0 到 4 名对手
(3) 只匹分差上下 200 分内的对手
(4) 若分差内无其他人,则匹配你前一排名为对手。若再无前一排名,此次匹配无人
(5) 匹配的对手会被保存,直至发起挑战或主动刷新,才重新匹配
(6) 主动刷新首次免费,后续刷新需花金砖,匹配无人时不花金砖。发起挑战后重置免费刷新 - 防守阵容
(1) 竞技场中,发起挑战使用主线阵容,被挑战使用防守阵容
(2) 防守阵容需提前布阵保存,保存后武将状态锁定,本周内需再次调整布阵才会更新
(3) 未布阵防守阵容时默认使用主线阵容
截图:

问题17:
状态:验收通过
现象:客厅盐罐点击暂停按钮在开始 现可领取盐罐会被重置 已获得的盐罐也会被重置
预期:暂停只会暂停时间倒计时不会重置盐罐
根因:客户端客厅盐罐弹窗 BottleRobotDialog 全局暂停发送 BottleHelperService.stop({bottleType:-1}),再次开始时会发送 BottleHelperService.start;客户端 UI 读取 ROLE.bottleHelpers.bottleHelper[*].obtainCnt/endTime/helperStopTime。服务端 bottlehelper_stopHandler.stopOne 暂停时把运行中的盐罐 EndTime、ObtainCnt 清零并改成停止态,bottlehelper_startHandler 再按完整时长重新设置 EndTime,所以截图中原本可领取的盐罐变回倒计时,已获得金罐数量从 x10 变成 x0。
服务端代码:server/compat_fieldized_bridge.go 的 bottlehelper_stopHandler、bottlehelper_startHandler、pauseBottleHelper、startBottleHelper。
客户端代码:client/assets/game/scripts/BottleRobotDialog.js、client/assets/game/scripts/BottleHelperData.js、client/assets/game/scripts/BottleModule.js。
日志与截图:截图账号标识为 28991|26501|dev|28,第一张显示暂停/开始前倒计时 01:19:19,左右盐罐可领取,已获得金/银/铜为 x10/x20/x20;第二张显示暂停后再次开始倒计时被重置为 04:59:53,三个盐罐全部进入倒计时,金罐变为 x0。已检索 server/logs/2026-06-04 和 server/runtime/logs/client_track/client_track-2026-06-04.log,未找到该时间窗内 roleId=26501/account=28991 的 bottlehelper 协议记录,根因以截图时间线和服务端确定性状态转换为准。
修复过程:新增 pauseBottleHelper,暂停时先结算已到时的运行盐罐;未到时只把状态改为暂停并记录 StopTime,保留 EndTime 和 ObtainCnt。新增 startBottleHelper,恢复暂停盐罐时使用 EndTime-StopTime 的剩余秒数重新计算结束时间,保留已获得数量;普通启动仍使用原配置时长。bottlehelper_stopHandler 改为调用暂停逻辑,并在单个暂停后重新计算仍在运行盐罐的 helperStopTime。补充 TestBottleHelperPauseAndResume_PreservesProgress 覆盖暂停/恢复不重置奖励和剩余时间。
人工回归建议:1)准备至少一个已可领取且 obtainCnt>0 的盐罐,同时另一个盐罐仍在倒计时,点击全局暂停后再点击开始,确认可领取标识、已获得数量不被清零;2)确认恢复后的倒计时从暂停前剩余时间继续,不会回到完整 5/3.5/3 小时;3)对单个盐罐暂停/开始做同样验证,其他仍运行的盐罐倒计时不受影响;4)领取奖励后确认奖励数量与暂停前累计一致,刷新/重登后状态仍一致。
截图:

问题18:
状态:验收通过
备注:验收不通过反馈为“现在买完三条后这个鱼灵直接不显示了,无法购买”。
现象:黑室-神秘商店鱼灵商品买满三条后刷新/重进,部分鱼灵直接不显示或无法继续购买。
预期:黑室内神秘商店全部重置刷新,所有鱼灵改为不限购,显示限购的玩家也正常刷新并可以正常购买。
根因:第一次修复只把 MerchandiseConf 中 8101-8112 鱼灵商品的 limit 调整为 9999,解决了 activity_buygoods 的限购校验;但活动面板 activity_getinfo 返回的 activity.activityShop[8].record 是服务端写死清单,只包含 8101-8110,缺少 8111/8112。客户端 ActivityShop 本地按 MerchandiseConf.list 构造商品,但刷新购买数时依赖服务端 serverActivity.record.get(goodsId);服务端 record 缺项会导致刷新/分页场景里部分鱼灵没有服务端状态,表现为买满后不显示或不可买。
客户端代码:client/assets/game/scripts/ActivityShop.js 在 onStart 中按 MerchandiseConf.activityID === 8 && hide <= 0 生成神秘商店商品;_refresh 通过 serverActivity.record.get(l.id) 更新 buyQuantity/lastBuyTime 并按 isSoldOut 排序;购买失败 code=5/7 时会把当前商品本地置为售空。
服务端代码:server/internal/activityx/buygoods.go 的购买回包已通过 QueryActivityMerchandiseIDs(activityID) 动态返回 activityId=8 下的商品购买状态;二次根因在 server/domains/activity/read/panel.go 的活动面板默认 activityShop[8].record 不完整。已新增 ensureMysteryShopFishGoods,保证 activity_getinfo 默认面板始终包含 8101-8112 全部鱼灵 record,再由 applyMerchandiseCompleteToActivityShop 覆盖历史购买次数。
截图/日志:截图 image-2026-06-05T15-15-11-106Z.png 显示账号 28991|26501|dev|28,入口为黑市-神秘商店,鱼灵商品价格 400 珍珠。已检索 2026-06-05 15:15 附近服务端日志和 client_track,未找到该角色的 activity_buygoods/activity_getinfo 协议轨迹,只有服务状态日志;根因通过客户端刷新逻辑、服务端面板 record 构造和失败单测复现确认。
修复过程:1)复查验收反馈,确认“买满三条后不显示”不是单纯购买限购校验,而是刷新面板状态缺失;2)检查客户端 ActivityShop,确认商品列表来自本地配置,但购买数量来自服务端 activityShop[8].record;3)检查服务端 BuildActivityResponse,发现神秘商店默认 record 只写到 8110,缺 8111/8112;4)新增红灯测试 TestBuildActivityResponseFromSnapshot_IncludesAllMysteryShopFishGoods,旧代码失败于缺 8111;5)新增 ensureMysteryShopFishGoods,在活动面板返回前补齐 8101-8112 全部鱼灵状态;6)执行 GOCACHE=/tmp/go-build go test ./domains/activity/read -run 'TestBuildActivityResponseFromSnapshot_IncludesAllMysteryShopFishGoods|TestBuildActivityResponseFromSnapshot_UsesMerchandiseCompleteForActivityShop'、GOCACHE=/tmp/go-build go test ./domains/activity/read、GOCACHE=/tmp/go-build go test ./internal/activityx -run 'TestMysteryShopFishGoodsAreUnlimitedInConfig|TestActivityBuyGoods.*',均通过。额外执行 GOCACHE=/tmp/go-build go test ./internal/activityx 时有周活动时间相关测试失败,失败用例与本次神秘商店鱼灵链路无关。7)本地容器 8bcb24081596 复查 8108 连续 3 次购买日志,服务端均成功且读取 limit=9999,未出现 limit exceeded;但旧客户端本地配置仍可能按 limit=3 结合服务端购买数隐藏商品。在暂不能更新客户端的前提下,服务端已补兼容:8106-8112 购买成功时不再递增客户端可见的 activityRecord.merchandise.complete.<goodsId>,购买回包和 activity_getinfo 面板回包均把这批商品 buyQuantity 压为 0,避免旧客户端按 3 次限购隐藏。
人工回归建议:1)使用已购买过 8101-8112 任一鱼灵 3 次以上的账号进入黑室-神秘商店,确认所有鱼灵仍显示且不再出现售空/消失;2)重点购买 8111、8112 后刷新、切页、重登,确认商品仍显示且可继续购买;3)购买成功后确认珍珠扣除 400、对应鱼灵道具数量增加 1,activity_getinfo 返回的 activityShop[8].record 包含 8101-8112 且购买数正确;4)珍珠不足时仍提示珍珠不足,不受不限购和补 record 影响。
黑室内神秘商店全部重置刷新 所有鱼灵改为不限购 显示限购的玩家也正常刷新可以正常购买
截图:
问题19:
状态:验收通过
现象:梦魇水晶转换会出现一样的属性
预期:转换不会出现和当前一样的属性
根因:客户端 TrumpStageUpDialog 的梦魇水晶“转换”实际调用 EquipmentModule.trumpStageUpData.upgradeTrump(heroId, isLocked, isTrans=true),协议为 TrumpService.upgrade({heroId,isLocked,isTrans:true}),右侧预览读取服务端回包英雄的 transTrumpId/trumpAttr。服务端 internal/trumpx.TrumpUpgradeFieldized 在 isTrans=true 分支直接按当前等级调用 GetRandomIDByLevel(lv),没有排除当前 trumpId;当随机池抽回同一个水晶 ID 时,transTrumpId 与当前 trumpId 相同,左右属性就完全一致,截图中攻击/减伤/血量三条相同即由此产生。
服务端代码:server/internal/trumpx/upgrade.go、server/attributes/manager.go、server/internal/gameplay/equipmentx/upgrade_level_resp.go、server/compat_ws_bridge.go。
客户端代码:client/assets/game/scripts/TrumpStageUpDialog.js、client/assets/game/scripts/EquipmentModule.js。
日志与截图:截图账号标识为 28991|NaN|dev|2,梦魇转换预览左侧和右侧均为同一金色 +9 水晶,属性均为攻击 +6600、减伤 +18.0%、血量 +22.0%。已检索 server/logs/2026-06-05 和 server/runtime/logs/client_track/client_track-2026-06-05.log,未找到该时间窗可关联的 trump_upgrade/trump_transsave/transTrumpId 协议记录,根因由服务端确定性随机分支和截图状态确认。
修复过程:在水晶配置服务新增 GetRandomIDByLevelExcept(level, excludedID),按等级取随机池时过滤当前 trumpId;TrumpUpgradeFieldized 的转换分支改为调用该排除接口,保证预览 transTrumpId 不会等于当前 trumpId。同步补齐 equipmentx.UserService 与 trumpxUserServiceAdapter 适配方法。新增 TestTrumpUpgradeFieldized_TransRerollsWhenRandomMatchesCurrentTrump,覆盖第一次随机到当前水晶时必须重抽并保存其他水晶 ID。
人工回归建议:1)选择已满级或可转换的梦魇水晶,连续点击“转换”至少 20 次,确认右侧预览不会与左侧当前水晶完全同 ID/同三条属性;2)确认每次转换仍正常扣除金币和梦魇晶石,资源不足时仍提示资源不足;3)点击“保存”后确认当前水晶变为预览水晶,刷新/重登后 trumpId/transTrumpId 状态一致;4)抽查锁定升级、普通升级、正反面切换不受影响。
截图:
问题20:
账号fafa 时间6.6 2:02
状态:验收通过
现象:鱼灵卸载后 鱼灵上的淬炼会消失不见 变成了未激活淬炼状态
预期:卸载鱼灵淬炼不会消失
根因:客户端鱼灵淬炼状态由 PetDataView.getPetQuenchState(petUId) 判断,只有当前 fish 的 quenches.size > 0 才显示已激活,否则显示“激活鱼珠”。装备/卸载走 PetService.load。服务端 domains/pet.HandleLoad 的纯卸载分支 slot=-1 旧逻辑只删除装备槽 petData.pets["-1"],没有把装备槽上完整 fish(含 Quenches/PendingQuenches)回写到背包槽;如果角色存在同 uId 的历史背包副本且该副本没有 Quenches,卸载后客户端就读到旧副本,表现为鱼灵还在但淬炼变成未激活。
服务端代码:server/domains/pet/service.go 的 HandleLoad、findPetBoardSlotByUId、firstEmptyPetBoardSlot;入口 server/compat_ws_bridge.go 的 pet_loadHandler。
客户端代码:client/assets/game/scripts/PetDataView.js、client/assets/game/scripts/PetModule.js、client/assets/game/scripts/PetEquipDialog.js、client/assets/game/scripts/PetInfoQuenchDrawer.js。
日志与截图:截图账号标识 28991|28002|dev|28;卸载前鱼灵“惊雷”有鱼灵附身/淬炼属性,列表显示“已附身·吕布+8”;卸载后同一鱼灵仍在背包但按钮变为“激活鱼珠”。已检索 server/logs/2026-06-05 和 server/runtime/logs/client_track/client_track-2026-06-05.log,18:04-18:05 附近未找到可关联的 pet_load/角色协议轨迹,仅有服务状态日志,根因以截图状态变化和服务端确定性分支确认。
修复过程:新增回归测试 TestHandleLoad_UnloadPreservesQuenchesOnLegacyDuplicateBoardPet 复现“装备槽带 Quenches、背包同 uId 旧副本无 Quenches,直接卸载后淬炼丢失”的场景。修复 HandleLoad(slot=-1):删除装备槽前,先查找同 uId 背包槽并用装备槽完整 fish 覆盖;没有同 uId 背包槽时,放入第一个已解锁空槽;再删除 -1 并下发 delete marker。这样卸载后背包中的 fish 仍保留已确认淬炼状态,不会显示成未激活。
人工回归建议:1)用截图账号或构造同类账号,装备一条已有鱼灵淬炼的鱼灵,点击卸载,确认鱼灵回到背包后仍显示已激活鱼珠和原淬炼属性;2)重新装备该鱼灵,确认淬炼属性仍生效,战力/鱼灵附身属性不丢;3)刷新、重登后再次查看背包和装备位,确认 Quenches 不回退;4)再回归拖拽卸载到空槽、装备另一条鱼灵替换当前鱼灵、普通装备鱼灵,确认旧鱼灵和新鱼灵各自的淬炼不串、不丢。
截图:



问题21:
状态:验收通过
现象:灵珠技能商店兑换内 技能仁心 回元 游龙扣取灵珠不正确 只扣除一颗灵珠
预期:正常按照售价扣除相应的灵珠
根因:客户端技能商店 PearlShopDialog 的价格来自 PearlSkillPoolConf.price,购买时调用 NewPearlModule.sendBuySkill -> PearlService.buySkill({skillId}),客户端只做灵珠数量预校验,实际扣费以服务端 pearl_buyskill 为准。服务端 internal/gameplay/pearlx.BuySkillFieldized 会通过 pearlSkillCost(skillId) 读取 getPearlSkillCostFromConfig 的配置价格;旧读取逻辑优先使用 config1.pearlSkillPoolConf,该旧表只包含 1033007-1033014,缺少 1033015 仁心、1033016 游龙、1033017 回元。函数在优先表存在但目标技能缺行时直接返回兜底价 1,没有继续查完整顶层 pearlSkillPoolConf,所以这三个新技能无论标价 2/2/3,服务端都只扣 1 个灵珠。
服务端代码:server/compat_ws_bridge.go 的 pearl_buyskillresp、pearlBuySkillFieldized、getPearlSkillCostFromConfig;server/internal/gameplay/pearlx/skills_and_recovery.go 的 BuySkillFieldized;server/internal/gameplay/pearlx/helpers.go 的 pearlSkillCost。
客户端代码:client/assets/game/scripts/PearlShopDialog.js、client/assets/game/scripts/NewPearlModule.js、client/assets/game/scripts/PearlSkillDataView.js。
日志与截图:截图账号标识 28991|28002|dev|28,购买标价 3 的“回元”前灵珠为 94,购买成功后灵珠为 93,只少 1。已检索 server/logs/2026-06-05 和 server/runtime/logs/client_track/client_track-2026-06-05.log,18:08 附近未找到可关联 pearl_buyskill/角色协议轨迹,仅有服务状态日志;根因由截图数值、客户端配置读取和服务端配置缺行兜底分支确认。
修复过程:新增 TestGetPearlSkillCostFromConfig_FallsBackWhenConfig1MissesSkill,复现“config1.pearlSkillPoolConf 存在但缺 1033017,顶层完整表有 price=3 时旧逻辑返回 1”的场景。修复 getPearlSkillCostFromConfig:按候选表顺序查 config1.pearlSkillPoolConf、config1.PearlSkillPoolConf、顶层 pearlSkillPoolConf、顶层 PearlSkillPoolConf,只有找到目标技能且 price 有效才返回;优先表缺行时继续查后续完整表。已执行 GOCACHE=/tmp/go-build go test . -run 'TestGetPearlSkillCostFromConfig'、GOCACHE=/tmp/go-build go test ./internal/gameplay/pearlx、GOCACHE=/tmp/go-build go test . -run 'Test(Pearl|GetPearlSkillCostFromConfig)' 通过。
人工回归建议:1)进入灵珠技能商店,分别购买仁心、游龙、回元,确认灵珠数量分别按按钮标价扣 2、2、3,不再统一扣 1;2)灵珠不足时购买这三个技能,确认仍提示不足且不增加技能库存;3)购买成功后确认对应技能库存/已拥有数量增加 1,刷新/重登后库存和灵珠数量不回退;4)抽查旧技能碎盾、冥想、定心、冰清、攻心、强权、盾击、合力,确认价格仍按原配置扣除。
截图:


问题22:
状态:验收通过
现象:功法内显示赛季结束
预期:正常开启新赛季
根因:客户端功法页用 LegacyScheduleData.isCrossSeason 判断入口是否锁定,条件包含 SERVER_DATA.roleLegacy.scheduleId < 当前本地赛季配置id;2026-06-05 18:16 已进入功法赛季 6,但服务端 legacy_getinfo 的归一化逻辑只在 roleLegacy.scheduleId <= 0 时补当前赛季,不会把历史角色保存的旧赛季 5 推进到赛季 6,导致客户端收到的 roleLegacy.scheduleId 仍小于当前配置赛季,持续显示“当前赛季已结束”。
客户端代码:client/assets/game/scripts/LegacyScheduleData.js 中 isCrossSeason 读取 SERVER_DATA.roleLegacy.scheduleId < this.conf.id;client/assets/game/scripts/LegacyModule.js 进游戏调用 LegacyService.getInfo({}) 并用返回的 rawData.roleLegacy 覆盖 SERVER_DATA.roleLegacy;client/assets/game/scripts/LegacyMainPanel.js 根据 isCrossSeason 锁定探索、商店、特权、战令、Boss 等入口并显示赛季结束状态。
服务端代码:server/domains/growth/legacy/compat.go 的 HandleGetInfo -> NormalizeForGetInfo 原先只修复空/0 的 ScheduleId,已改为当 LegacyScheduleConf 匹配到的当前赛季 id 更大时推进 roleLegacy.scheduleId 并保存;server/internal/gameplay/legacyx/helpers.go 的 EnsureRoleLegacyForWrite、登录/最小角色归一化也同步改为只在当前赛季更高时推进,避免其他功法写路径继续使用旧赛季。
截图/日志:截图 image-2026-06-05T18-16-22-809Z.png 显示账号信息 28991|28002|dev|28,功法主界面赛季名为“朱明赛季”,连续弹出“当前赛季已结束”。已检索 2026-06-05 18:15-18:17 附近服务端日志和 client_track,未发现可用的 legacy_getinfo 协议轨迹,只有服务状态日志;按本地 LegacyScheduleConf,赛季 5 在 2026-06-04 23:59:59 结束,赛季 6 普通开启时间为 2026-06-05 12:00:00、结束时间为 2026-07-02 23:59:59,因此截图时间 2026-06-05 18:16:22 应正常处于赛季 6。
修复过程:1)先从截图定位到功法主界面与提示文案;2)核对客户端 isCrossSeason 的所有门禁条件,确认核心依赖 SERVER_DATA.roleLegacy.scheduleId;3)追踪 LegacyService.getInfo({}) 到服务端 growthlegacy.HandleGetInfo,确认旧逻辑不会推进已过期但大于 0 的 scheduleId;4)新增回归测试 TestHandleGetInfo_AdvancesExpiredScheduleIdToCurrentSeason,构造角色保存赛季 5、当前时间匹配赛季 6,红灯复现返回仍为 5;5)修复 NormalizeForGetInfo 和通用功法归一化路径,当前赛季 id 更高时推进并保存;6)执行 GOCACHE=/tmp/go-build go test ./domains/growth/legacy -run 'TestHandleGetInfo_AdvancesExpiredScheduleIdToCurrentSeason|TestHandleGetInfo_NormalizesLegacy'、GOCACHE=/tmp/go-build go test ./domains/growth/legacy、GOCACHE=/tmp/go-build go test ./internal/gameplay/legacyx,均通过。
人工回归建议:1)用跨过 2026-06-05 12:00 后仍保存旧 roleLegacy.scheduleId=5 的账号登录,进入功法,确认不再提示“当前赛季已结束”,探索、商店、特权、战令、Boss 等入口按赛季 6 正常状态展示;2)打开功法后抓 legacy_getinfo 响应,确认 roleLegacy.scheduleId 返回 6,并刷新/重登后仍为 6;3)抽查旧赛季未结束前或无当前赛季配置时,不应错误推进到未来赛季;4)进行一次功法创造/探索/礼包或任务领取,确认新产生或更新的数据使用当前赛季 id,功法资源和存量功法不丢失。
截图:
问题23:
状态:验收通过
现象:在战斗中会出现在双方武将的出手顺序不按照各自的速度先后出手
预期:每种对战中所有武将的出手顺序都严格按照这个武将的速度高低判定(被对方武将被动等其他因素影响除外)
截图:

问题24:
状态:未处理
现象:咸将塔内对战中 诸葛亮技能没有随机性 如果一关没通过 那就就一直不能通过 每一次都是固定控制固定的人
预期:正常每一次对战都各不相同 每一个释放技能都是随机的
截图:
问题25:
状态:验收通过
现象:战斗中关羽会存在不优先攻击力最高的武将
预期:战斗中关羽优先攻击最高的武将(被额外因素降攻击力的除外)
截图:


问题26:
状态:未处理
现象:深海灯神第二关 boss伤害不对 每次只能造成一点伤害 且赢了判定输 跳过必输
预期:boss伤害正常 不会出现赢了判定输
截图:
问题27:
状态:验收通过
现象:竞技场内输赢后增减积分 显示无变化 需大退游戏再进才会变化
预期:正常实时显示增加减少积分
截图:


根因:截图显示战斗结算弹窗已正确展示 +20,但返回竞技场组内榜底部自己的积分仍为旧值 1182,应为 1202。客户端竞技场页底部分数读取 ArenaModule.myListInfo.score,该值来自服务端 arena_getarearank 的 myRank.score,不是直接读 ROLE.arenaScore。服务端 fight_startareaarena 已在角色缓存中把 ArenaScore 更新为新值,并在回包/sync 里带了 newScore 和 role.arenaScore;但随后 arena_getarearank 构造组内榜时,排行榜列表从 Mongo 游标读取,最近接入角色内存缓存后,战斗刚结束时可能出现缓存里的自己是新积分、Mongo 排行游标里的自己仍是旧积分。第一版修复只把当前玩家行的数据源切到缓存,解决了 myRank.score 旧值,但测试服容器日志继续暴露出第二层问题:18:37:46 角色 100216517 胜利后新积分 1250,18:37:50 arena_getarearank 返回 my=100216517:4:1250,同一列表第 3 名是 1234,说明分数已实时、排名 rank/globalRank 仍按 Mongo 旧排序位置返回。二次修复后继续看最新日志,18:44:04 战斗结算新积分 1269,但 18:44:07 arena_getarearank 又返回 my=100216517:3:1250,说明当前容器已经有榜单重排修复,但竞技场结算后的 UpdateRole 可能因 stale full-role replace 被拒绝且错误被吞:回包使用本地已变更对象显示 1269,RoleStore 仍停在 1250,下一次排行榜重新从 RoleStore 读就回到旧值。根因仍是服务端缓存/字段刷新链路,不是客户端页面没刷新。
客户端代码:client/assets/game/scripts/ArenaBattleDialog.js 战斗成功后进入战斗表现,胜负弹窗 ArenaVictory.js/ArenaDefeat.js 关闭时触发 notifyUpdate/notifyLoseUpdate,ArenaPanel.refreshList1/refreshList2 重新请求 arena_getarearank;ArenaModule._trimSelfInfo() 用响应里的 myRank.score 更新 myListInfo.score,ArenaPanel._refreshServerView() 再显示到底部自己行。
服务端代码:server/compat_ws_bridge.go#fight_startareaarenaHandler 负责结算积分和回包;server/internal/gameplay/rankx/arena_rank.go#AreaRankHandler.BuildResponse 负责 arena_getarearank 的组内榜和 myRank。本次修复把榜单行构造收敛到 buildRankData,当 Mongo 游标行是当前角色时,改用缓存中的 currentRole 作为数据源;随后在 buildArenaRankRows 中按 ArenaScore desc / LastArenaTime asc / roleId asc 对本次返回列表重排,并重新计算 rank/globalRank。第三轮修复在竞技场结算保存前调用 refreshArenaRoleSaveVersion 刷新 UpdatedAtNs,并把原来吞掉的 UpdateRole 错误写入日志,避免全量快照因版本旧被 RoleStore 拒绝后排行榜继续读旧分。
修复过程:先根据截图确认是竞技场组内榜底部自己的积分未刷新,不是王者榜或冒险榜;再沿客户端确认底部分数依赖 arena_getarearank.myRank.score;服务端对比结算链路和排行链路后,定位到缓存角色新积分与 Mongo 排行游标旧积分的短暂不一致。第一轮新增 TestBuildRankData_UsesCachedCurrentRoleScoreForSelf 复现“Mongo 自己 1182、缓存自己 1202”时应返回 1202;用户复测后继续查最新容器日志,发现分数已经实时但排名仍旧,于是新增 TestBuildArenaRankRows_ReordersSelfByCachedScore,复现“旧排序第 4、缓存新分应排第 3”的场景,再修复返回列表重排和 myRank.rank/globalRank 同步。最新容器日志又发现“结算 1269、榜单仍 1250”,因此新增 TestFightStartAreaArena_RefreshSaveVersionAllowsArenaScoreAfterResourcePatch 覆盖旧快照保存被 stale resource 保护拒绝的场景,并修复竞技场保存版本。
验证:GOCACHE=/tmp/go-build GOTMPDIR=/tmp go test ./internal/gameplay/rankx -count=1 通过;GOCACHE=/tmp/go-build GOTMPDIR=/tmp go test . -run 'TestFightStartAreaArena_RefreshSaveVersionAllowsArenaScoreAfterResourcePatch|TestBuildArenaRoleSyncData|TestFightStartAreaArena|TestArena' -count=1 通过;git diff --check -- server/compat_ws_bridge.go server/arena_handlers_test.go server/internal/gameplay/rankx/arena_rank.go server/internal/gameplay/rankx/arena_rank_test.go 通过。检索 server/logs/2026-06-06 和 client_track-2026-06-06.log 未找到截图账号 28991|26501|dev|28 在 05:23 附近的可用协议日志,根因由测试服容器日志、客户端读字段、服务端结算/排行代码和定向测试确认。当前这轮 refreshArenaRoleSaveVersion 修复尚未再次部署进测试容器。
人工回归建议:测试服用任意竞技场号记录当前底部分数和组内榜排名,发起一场胜利,结算弹窗显示 +N 后点击确定返回竞技场页,底部自己的积分应立即变为旧分 +N,不需要大退;同时检查组内榜自己的排序位置也要按新分数变化,例如新分超过上一名时当前行应立即上移,不能出现“自己 1250 仍排在 1234 后面”。再做一场失败,确认底部分数立即减少且不低于 1000,排名同步下移。连续打两场,确认组内榜自己的行和底部自己行分数一致,刷新榜单、进出竞技场、重登后仍一致;同时确认排行榜其它玩家排序、挑战目标、胜负战报和每日竞技场任务进度不受影响。
问题28:
状态:已修复 验收通过
现象:宠物精炼红色词条下面两个属性百分比过低 还没橙色高
预期:词条属性正常 截图1是我们 截图2是正常
截图1:
截图2:
根因:已看问题描述、截图、客户端 PetInfoQuenchDrawer/PetQuenchCheckDialog/UIHelper.setPetQuenchAttrValue 展示链路、服务端 pet_quench 抽词条链路和 server/config/pet_prob.json。截图1中红色控制命中/职业减伤等附加属性只有 +2.2%~+2.5%,且同一个红色双属性槽两条百分比完全相同;客户端只是按 attrNum / 1000 展示服务端回包,不会本地压低。服务端根因是 rollQuenchWithAttrCounts 原来先按槽位颜色抽一个统一 attrNum,再复制给该槽所有附加属性;红色 quenchValues[6].attrNum 配置为 2200~2500,只适合面板百分比属性最大 2.5%,但被错误复用于控制命中、技能伤害、普攻易伤、治疗增强、怒气速率等更高上限属性,所以红色功能词条会比正常橙色功能词条还低,并且双属性数值总是一样。
修复:服务端宠物精炼附加属性改为先抽 attrId,再按属性组独立抽每条 attrNum;基础血量仍按槽位颜色抽。pet_prob.json 新增 quenchAttrValueGroups:面板百分比保持红色 2.2%~2.5%,职业增/减伤红色 2.6%~3.0%,控制/技能/普攻/速度/暴击等功能词条红色 4.0%~5.0%,治疗增强/怒气速率红色 4.5%~6.0%。红色双属性现在分别随机,不再强制两条相同。
验证:先用新增回归确认旧逻辑失败:红色控制命中最大只到 2500,红色双属性两条 attrNum 相同;修复后 GOCACHE=/tmp/xianyu-go-build GOTMPDIR=/tmp go test ./domains/pet -run 'TestRollQuench_Red(FunctionalAttrUsesFunctionalPercentRange|DoubleAttrsRollIndependentValues)' -count=1 通过。完整定向验证:GOCACHE=/tmp/xianyu-go-build GOTMPDIR=/tmp go test ./internal/gameplay/petprob -count=1、GOCACHE=/tmp/xianyu-go-build GOTMPDIR=/tmp go test ./domains/pet -count=1、jq empty server/config/pet_prob.json、git diff --check -- server/internal/gameplay/petprob/config.go server/config/pet_prob.json server/domains/pet/service.go server/domains/pet/service_test.go 均通过。当前本地 server/logs/2026-06-06、server/logs/today 和 client_track 未检索到与截图时间可关联的 pet_quench 请求,本问题按截图、客户端展示代码、服务端确定性抽值代码和回归测试闭环确认。
人工回归建议:测试服洗出红色宠物精炼双属性,检查控制命中、技能伤害/减伤、普攻易伤/抗性、免控等功能词条应可出现 4%~5% 区间;治疗增强/怒气速率应可高于 5% 并最高到 6%;职业增/减伤类最高约 3%;攻击/防御/血量百分比仍最高 2.5%。同一个红色双属性槽两条百分比不要求相同,不能再稳定出现两条完全一样且都卡在 2.2%~2.5% 的情况。
问题29:
状态:未处理
现象:咸将塔爬塔会出现赢了判定输
预期:任何副本 任何战斗都不会存在赢了判输
截图:
问题30:
状态:修复待验证 验收通过
账号fafa 时间 23::30-23:31
现象:合成宠物时选择没等级的宠物继承 失败后没有返还有等级宠物的成长脆饼和幻彩灵果
预期:合成失败后返还有等级宠物的百分之百的宠物脆饼和百分之50的换材料灵果(详细看截图3截图4)
截图:



处理记录:已看问题描述与 4 张截图,截图场景为紫色以上宠物合成时手动选择 Lv.1 宠物继承,失败后应保留该 Lv.1 宠物、消耗另一只有等级宠,并按被消耗宠返还升级材料和精炼材料。客户端入口为 PetModule._sendMerge() 调用 PetService.merge({fromSlotUId,toSlotUId,inheritSlot}),继承选择弹窗 PetMergeSelectDialog 会把被选宠物所在格子写入 inheritSlot;合成成功/失败后客户端用响应 reward 调 TipsManager.showReturnRewardsTip() 展示返还。
服务端路径:compat_ws_bridge.go#pet_mergeHandler 直接把 JSON 解析为 domains/pet.MergeRequest,字段名 fromSlotUId/toSlotUId/inheritSlot 与客户端一致;domains/pet.HandleMerge 先用 chooseMergeInheritance() 确定保留宠和消耗宠,再用 mergeReturnRewards(dropPet, root, true) 按被消耗宠计算返还,savePetData() 会把返还道具写入 items.<itemId>.quantity,回包 role/rawData.role 也带 items 和 reward。
验证结果:新增回归 TestHandleMerge_FailManualKeepsLowLevelPetAndRefundsDroppedHighLevelPet 覆盖“手动选择低等级宠继承、合成失败、消耗高等级宠”的场景,确认服务端保留低等级宠,并按被消耗高等级宠返还 levelUpItem 100% 和 PetQuenchConsumeConf 首项 50%。执行 GOCACHE=/tmp/xianyu-go-build GOTMPDIR=/tmp go test ./domains/pet -run TestHandleMerge_FailManualKeepsLowLevelPetAndRefundsDroppedHighLevelPet -count=1 通过;GOCACHE=/tmp/xianyu-go-build GOTMPDIR=/tmp go test ./domains/pet -count=1 通过。本地 server/logs/2026-06-06、server/logs/2026-06-07 和 client_track 未找到截图账号/时间可关联的 pet_merge 请求日志,无法用当次日志证明线上请求实际命中情况。
补充诊断:pet_merge result 日志已增加 keepLevel/keepExp/keepQuenchCount/dropLevel/dropExp/dropQuenchCount/rewards,后续测试服复现时可直接确认服务端收到的 inheritSlot、实际保留/消耗哪只宠、以及返还道具明细。如果测试服仍复现,优先核对容器是否部署了当前宠物域代码,以及日志中的 inheritSlot/dropLevel/rewards 是否符合预期。
验收不通过复查:测试服游戏服日志目录 /tmp/xianyu-server-test-runtime/logs/2026-06-07/ 中找到账号 fafa 23:30:44 的 pet_merge,trace_id=151830-fafa-52-pet_merge。该次请求合成失败,inheritSlot=3,服务端保留 Lv.1 宠 keepLevel=1,消耗 Lv.43 宠 dropLevel=43,返还记录为 rewards=3:15001:535,审计日志确认背包 15001 仅 +535,不是客户端没显示,而是服务端返还数量计算过低;同次日志 dropQuenchCount=0,因此没有 15002 返还。
本次根因:domains/pet.mergeReturnRewards() 把 PetConstant.levelUpItem.value 当成每个成长脆饼提供的经验,使用 petTotalExp / levelUpItem.value 计算返还;但实际升级接口 HandleUseEXPItem() 消耗的是 cost 个 levelUpItem,增加经验为 cost * PetConstant.consumeItemExp。当前配置 consumeItemExp=1、levelUpItem.value=100,所以失败合成把应按实际消耗返还的成长脆饼压成了约 1/100。
本次修复:成长脆饼返还改为按 ceil(petTotalExp / consumeItemExp) 还原实际消耗数量,再应用 mergeLevelUpReturnRate;保留幻彩灵果按已确认精炼槽数量和 mergeQuenchReturnRate 返还。已更新回归 TestHandleMerge_FailManualKeepsLowLevelPetAndRefundsDroppedHighLevelPet,覆盖“选择 Lv.1 宠继承、失败消耗高等级宠、返还高等级宠材料数量”的场景。执行 GOCACHE=/tmp/xianyu-go-build GOTMPDIR=/tmp go test ./domains/pet -count=1 通过。
幻彩灵果二次复查:2026-06-08 测试服日志显示账号 fafa 的 roleId=151830 在 00:18:11-00:18:20 对同一只宠 uid=151830-1780849061126783285 连续执行 15 次 pet_quench,每次 costItem=15002 cost=10,实际消耗 15002x150;00:18:24 合成时被消耗宠 dropQuenchCount=4,服务端旧返还为 rewards=3:15001:882,3:15002:20。根因是旧返还公式只按当前精炼槽数量 len(Quenches) * 首档消耗10 * 50% 估算,未记录该宠历史实际精炼消耗,因此 15 次刷新应返 150*50%=75 时只返了 4*10*50%=20。
幻彩灵果二次修复:PetData 新增 quenchCost 累计字段,每次 pet_quench 成功扣除灵果后累加实际 cost.Value;合成继承、克隆和深拷贝保留该字段;失败合成返还时优先按 quenchCost * mergeQuenchReturnRate 计算,老宠没有 quenchCost 时才退回旧的当前槽位估算。新增回归 TestHandleMerge_FailRefundsHalfOfTrackedQuenchCost,覆盖“同一只宠精炼 15 次消耗 150,失败合成返 75”。执行 GOCACHE=/tmp/xianyu-go-build GOTMPDIR=/tmp go test ./domains/pet -count=1 和 GOCACHE=/tmp/xianyu-go-build GOTMPDIR=/tmp go test ./internal/deepcopy -count=1 通过。
人工回归建议:准备两只同品质紫色及以上宠物,一只 Lv.1 无精炼,一只有等级并带精炼;拖拽合成后在继承弹窗选择 Lv.1 宠物,强制或多次尝试直到合成失败。预期保留 Lv.1 宠物,另一只有等级宠消失,背包增加该被消耗宠对应的 100% 成长脆饼和 50% 幻彩灵果,界面出现返还提示;反向拖拽一次也应一致。再用默认继承高等级宠失败一次,确认只消耗低等级宠且不会返还高等级宠材料。
问题31:
状态:验收通过
现象:主线关卡达到10000关后领取挂机奖励为空
预期:可以正常领取正常到账奖励
截图:

根因:截图显示点击挂机奖励主按钮后弹出“恭喜获得”,但奖励内容为空。客户端 client/assets/game/scripts/HangUpDialog.js 点击“挂机奖励/领取”后调用 HangUpModule.sendClaimHangUpReward(),后者请求 SystemService.claimHangUpReward({}),并把服务端响应 reward 直接合并进 ItemRewardsDialog;如果服务端返回成功但 reward 为 nil/[],客户端就会出现空奖励弹窗。服务端入口 server/compat_fieldized_bridge.go#system_claimhanguprewardHandler 调用 domains/core/hangup.ClaimHangUpReward。核心函数通过 RewardByZeroIndex(stayRewardConf, role.HangUp.StayId) 取 StayRewardConf,但配置最大只有 10000 档;当角色达到 10000 关时,stayId=10000 被当作数组下标访问,len(keys)=10000 时越界返回 (nil, nil)。handler 未把 reward==nil && err==nil 判为错误,继续按成功保存并返回空奖励,导致奖励不到账且弹窗为空。
客户端代码:client/assets/game/scripts/HangUpDialog.js#sendClaimHangUpReward 关闭挂机弹窗并触发模块领取;client/assets/game/scripts/HangUpModule.js#sendClaimHangUpReward 读取响应 reward 并展示 ItemRewardsDialog,不自行计算奖励。
服务端代码:server/compat_fieldized_bridge.go#system_claimhanguprewardHandler 负责协议入口和保存;server/domains/core/hangup/write.go#ClaimHangUpReward 负责按挂机时长和 StayRewardConf 发奖;RewardByZeroIndex 负责按当前挂机关卡取奖励配置。本次修复把 RewardByZeroIndex 的上限越界处理改为使用最后一条配置,确保 10000 关及超过配置上限时继续按 10000 档发放挂机奖励。
修复过程:先检查截图确认不是等级奖励书 system_claimhanguporder,而是主挂机奖励 system_claimhangupreward;再沿客户端确认弹窗完全依赖服务端 reward 字段;服务端复查配置 server/config/level1.json 只有 1..10000,并定位 RewardByZeroIndex 把 stayId 作为零基下标导致 stayId=10000 越界。新增回归测试 TestClaimHangUpReward_UsesLastRewardAtConfiguredLevelCap,先复现达到配置上限时返回空奖励,再修复越界后改为使用最后一档配置。
验证:GOCACHE=/tmp/go-build GOTMPDIR=/tmp go test ./domains/core/hangup -count=1 通过;GOCACHE=/tmp/go-build GOTMPDIR=/tmp go test . -run 'TestNormalizeLegacyHangUpForClient|TestBuildRolePayloadFromCurrentRole|TestCreateDefaultHangUp|TestTestingTargetHangUpStayID' -count=1 通过;git diff --check -- server/domains/core/hangup/write.go server/domains/core/hangup/write_test.go 通过。检索 server/logs/2026-06-06、server/logs/2026-06-07、server/runtime/logs/client_track 未找到截图账号 2899126501 对应的 system_claimhangupreward 请求日志,本次根因由截图、客户端读字段、服务端确定性越界路径、配置上限和回归测试确认。
人工回归建议:测试服准备一个 levelId/hangUp.stayId 达到 10000 的角色,设置 hangUp.lastTime 至少早于当前 1 分钟,点击挂机奖励领取;预期弹窗显示金币/道具等奖励条目且道具到账,不再出现空“恭喜获得”。再把角色停留在 9999 关领取一次,确认仍按原逻辑发奖;连续点击第二次应提示暂无可领取奖励或不发重复奖励;超过 3 小时领取时确认随机奖励仍出现。
问题32;
状态:验收通过
现象:好友申请内点击一键同意或者一键忽略后 再刷新又会重新出现 同意或者忽略没有效果
预期:一键同意或者忽略都正常生效
截图:

根因/处理:客户端好友申请页一键同意发 friend_batchagree,一键忽略发 friend_batchreject,单条忽略发 friend_reject,服务端之前未注册这三个申请处理协议,导致刷新后仍从服务端 waitApplyList 读到旧申请。已新增单条忽略、批量忽略、批量同意的服务端业务逻辑、入口持久化和协议注册,更新接收者与申请者双方的申请/好友状态。
验证:GOCACHE=/tmp/go-build GOTMPDIR=/tmp go test -count=1 ./domains/social/friend ./entry/social/friendentry ./entry/account/wsentry 通过;GOCACHE=/tmp/go-build GOTMPDIR=/tmp go test -count=1 . -run 'TestFriend' 通过。
问题34:
状态:验收通过
账号fafa 时间0:42-45
现象:一键换阵导致鱼灵淬炼和佩戴的灵珠技能丢失 鱼灵重置回到未解锁淬炼状态
预期:一键换阵不会丢失鱼灵淬炼和灵珠技能
截图:



问题35:
状态:验收通过
现象:武将姜维被动技能觉醒以后 重生下阵 加成就变成了被动基础技能加成
预期:武将技能只有觉醒 达到相应等级 就加成觉醒后的加成
截图:


问题36:
状态:验收通过
备注:每过十关后 梦境商店不开启 无法购买商品
截图:
现象:咸王梦境内达到最大关卡200关后 还可以继续打 且没打一次 梦境商店都会刷新 可以无限购买东西
预期:达到200关后 无法继续攻打 梦境商店购买后无法再次刷新
截图:


根因:客户端咸王梦境面板点击开战发送 fight_startdungeon,客户端只用 ROLE.dungeon.id < 0 判断通关;服务端 internal/gameplay/dungeonx.FightStartDungeonFieldized 在胜利后使用 Clamp(200+1)=200,导致 200 层胜利后仍停留在可挑战的 id=200。随后 prepareDungeonMerchantAfterWin(dungeon, 200) 因 200 可被 10 整除,会每次战斗后重新打开/补充梦境商人货架,形成无限刷新和重复购买。
修复过程:服务端在 fight_startdungeon 状态机中增加最大层收口。200 层本身允许攻打;200 层胜利后进入 id=201 后置商店态并按第 200 层开启一次最终商人,玩家可以购买这一次商店货物,但 fight_startdungeon 对 dungeon.id > 200 的请求不再调用战斗,也不会重新刷新商店。若 201 状态仍有商店货物,请求开战时保留货物供购买;若 201 已无商店货物或跳过最终商人,则同步收口为通关态 id=-1。保留普通 10/20/30/…/190 层胜利刷商人的逻辑。
新问题根因:截图显示标题为“咸王梦境200”,商人驿站提示“暂时还未获得任何商品”。第一次修复把 200 层胜利直接写成 id=-1 并清空 merchant,漏掉“200 层本身也是 10 的倍数,应开启最终商店一次”的业务规则,因此最终商店被清空,表现为 200 层商店无货。客户端 DungeonShopPanel/DungeonJuniorShopPage 只读取 ROLE.dungeon.merchant[merchantId],服务端清空后客户端无法购买。
验证:新增/更新回归用例 TestFightStartDungeonFieldized_OpensMerchantEveryTenFloors、TestFightStartDungeonFieldized_AdvancesToMaxLevelBeforeFinishing、TestFightStartDungeonFieldized_OpensFinalMerchantAfterMaxLevelWin、TestFightStartDungeonFieldized_RejectsPastMaxLevelButKeepsFinalMerchantGoods、TestFightStartDungeonFieldized_RejectsPastMaxLevelAndFinishesWhenNoMerchantGoods、TestSkipMerchantFieldized_FinishesPostMaxMerchant。已通过:
GOCACHE=/tmp/go-build GOTMPDIR=/tmp go test ./internal/gameplay/dungeonx -count=1
GOCACHE=/tmp/go-build GOTMPDIR=/tmp go test ./domains/pve/dungeon -count=1
本地 server/logs/2026-06-07/app.log、client_track-2026-06-07.log 和当前测试服容器 stdout 未找到可关联的 fight_startdungeon/dungeon_buymerchant/dungeon_skipmerchant 日志,本次根因由新截图、客户端商店读取路径、服务端状态机和回归测试确认。
人工回归建议:使用测试角色从 9、19、189 层分别打过一层,确认 10、20、190 对应商人正常开启且可购买;从 199 层胜利后进入 200 层,确认不提前开商店且 200 仍可开战;打赢 200 层后确认商人驿站开启最终商店、有货可买,购买后货物减少且不会通过再次点击开战刷新;最终商店买完或跳过后确认梦境进入通关态,不能继续攻打。最后构造历史异常 dungeon.id=201 且商店有货,点击开战应拒绝战斗但保留货物;构造 dungeon.id=201 且商店无货,点击开战应收口为 id=-1。
问题37:
状态:验收通过
现象:玩家中心内购买的珍卡礼包到账的珍卡没有属性
预期:购买礼包到账的珍卡带双满属性 走火入魔 气定神闲(如截图3)
截图:

截图3:
根因:玩家中心功法礼包 LegacyShopConf 已配置 attr/extraAttr,客户端预览也按 extraAttr 显示,但服务端 resolveLegacyShopOrder 创建支付订单时只快照了 type=91,itemId,value,丢掉配置的基础属性和额外词条;ApplyNumericRewards -> createLegacyCardRewards 发货时再创建 RoleLegacy.LegacyStorage,旧逻辑只填基础满属性并将 ExtAttrs/ExtAttrNums 置空,导致到账珍卡详情页读不到 走火入魔/气定神闲。
修复:服务端支付奖励快照新增珍卡实例属性载荷,下单时从 LegacyShopConf.attr/extraAttr 转为 attrs/attrNums/extAttrs/extAttrNums 并写入订单快照;发货时优先使用订单快照生成珍卡实例。2026-06-08 按验收口径补充:付费 type=91 功法珍卡/满属性卡到账时,额外词条固定为 604/605 且数值强制 300/300,客户端显示为 3.0%/3.0%,不再按礼包配置中的 0.5%/1.7% 或普通打造随机值发放;历史无快照订单也保留双满词条兜底。
验证:已通过:
GOCACHE=/tmp/go-build GOTMPDIR=/tmp go test ./internal/payment -run 'TestCreateOrder_LegacyShopEntrySnapshotsLegacyRewards|TestDeliverOrder_LegacyShopOrderAddsLegacyChargeWithoutVipPoints|TestDeliverOrder_LegacyCardCreatesFullInstance' -count=1
GOCACHE=/tmp/go-build GOTMPDIR=/tmp go test ./internal/payment -count=1
2026-06-08 补充验证:GOCACHE=/tmp/xianyu-go-build GOTMPDIR=/tmp go test ./internal/payment -run 'TestDeliverOrder_LegacyShopOrderAddsLegacyChargeWithoutVipPoints|TestDeliverOrder_LegacyCardCreatesFullInstance|TestCreateOrder_LegacyShopEntrySnapshotsLegacyRewards' -count=1 通过;GOCACHE=/tmp/xianyu-go-build GOTMPDIR=/tmp go test ./internal/payment -count=1 通过。
问题38:
状态:待正式服验证
现象:限时活动周常活动内 所有活动每天都会刷新一次任务 每天可以领取一次奖励
预期:一周只能做一次任务 领取一次奖励 每周一0点刷新 活动轮换
截图:
评论
请登录后发表评论。
暂无评论。成为第一个评论者!