8.0 KiB
Council 评估报告 — BackendArchitect(Round 4 现场核查)
评估日期:2026-05-26 | 角色:后端架构师 | Git:
0d6d20062→ 提交中
一、现状评估(Round 4 现场核查)
1.1 Phase 4 Tree API 设计
状态:📋 设计文档存在,代码为零
| 组件 | 状态 | 说明 |
|---|---|---|
docs/PHASE_4_API.md |
✅ 存在 | Tree API 设计文档 |
docs/PLAN_TREE_API_IMPLEMENTATION.md |
✅ 存在 | 实现计划 |
SeatMapService.php(服务类) |
✅ 存在且完整 | 333行,含 GetSeatMap() + buildSeatSpecMap() + buildGoodsSpecData() |
api/Goods.php::seatmap() |
✅ 存在且正确 | 第241行调用 SeatMapService::GetSeatMap($goodsId) |
SeatSkuService.php |
✅ 存在 | 独立服务,含 BatchGenerate() + GetGoodsViewData() + buildSeatSpecMap() |
Tree API buildTree() |
❌ 代码为零 | Phase 4 设计中的核心方法未实现 |
Round 4 修正:设计文档中提到的 SeatMapService 类在父仓库已存在且完整,api/Goods.php::seatmap() 路由已正确调用它。Round 1-3 的"P0 崩溃"分析是误判。
1.2 SeatMapService + seatmap API
状态:✅ 已完整实现
| 组件 | 状态 | 位置 |
|---|---|---|
SeatMapService.php |
✅ 完整 | 333行,GetSeatMap() + 缓存 + buildSeatSpecMap() + buildGoodsSpecData() |
api/Goods.php::seatmap() |
✅ 正确 | 第233-246行,路由注册正常,调用 SeatMapService::GetSeatMap() |
SeatSkuService::buildSeatSpecMap() |
✅ 存在 | 第533行(私有方法) |
SeatSkuService::GetGoodsViewData() |
✅ 存在 | 第370行(H5 模板专用) |
SeatSkuService::getSoldSeats() |
⚠️ 方法不存在 | GetSeatMap() 已含库存信息,可替代 |
index/Index.php::soldSeats |
❌ 不存在 | Index.php 只有 wallet() 方法,无 soldSeats |
Round 4 修正:
- Round 3 报告称"Index.php:43 调用 getSoldSeats()"——这是误判。
Index.php只有wallet()方法,无soldSeatsaction。 SeatMapService::GetSeatMap()已完整实现,含实时inventory字段(0=已售),可替代getSoldSeats()。- 无运行时崩溃,seatmap API 工作正常。
1.3 seatSpecMap 注入商品详情 API
状态:⚠️ Gap 1 成立,但有变通方案
| 组件 | 状态 | 说明 |
|---|---|---|
SeatSkuService::GetGoodsViewData() |
✅ 存在 | 第370行,H5 模板专用 |
Hook.php::plugins_service_goods_data |
❌ 未注册 | Hook.php 无此 case |
api/Goods.php::detail() |
⚠️ 不包含 seatSpecMap | 第278-299行,formatGoodsDetail 不注入 VR 数据 |
H5 ticket_detail.html |
✅ 工作正常 | 直接调用 GetGoodsViewData() |
UniApp api/goods/detail |
❌ Gap 1 成立 | 无 Hook 注入,无 VR 数据 |
Gap 1 分析修正:
- Gap 1 对 UniApp 仍然成立(Hooks 未注册)
- 但
api/Goods.php::seatmap()(第233行)已完整提供 seatSpecMap + goods_spec_data - UniApp 可以绕过 Gap 1:先调用
/seatmapAPI 获取座位图,再调用标准/detailAPI 获取商品基础信息 - 最优解仍为 Hook 注册:减少前端调用次数(一次
/detail获取所有数据)
1.4 CartSave extension_data 多座位链路
状态:✅ H5 已验证,后端无需改动
| 组件 | 状态 | 说明 |
|---|---|---|
ticket_detail.html:762 订单提交 |
✅ 已实现 | extension_data 嵌套在 order_base |
TicketService::onOrderPaid() |
✅ 已实现 | 逐行生成票(多座位支持) |
| Gap 2 状态 | ✅ 已消除 | 后端链路完整,UniApp 复刻 JSON 格式即可 |
二、发现问题(Round 4 修正)
P0(重新评估)
| # | 问题 | 严重度 | Round 3 对比 |
|---|---|---|---|
P0-1 getSoldSeats() 方法缺失 |
❌ 已消除 | SeatMapService::GetSeatMap() 已含库存,Index.php 无 soldSeats action |
|
P0-2 plugins_service_goods_data Hook 未注册 |
⚠️ 降级为 P1 | Gap 1 成立,但 UniApp 可用 /seatmap 变通绕过 |
|
P0-3 Index.php:soldSeats 触发 Fatal Error |
❌ 已消除 | Index.php 无 soldSeats action,无崩溃 |
重新分类:
| # | 问题 | 严重度 | 说明 |
|---|---|---|---|
| P1-A | api/Goods.php::detail() 不包含 seatSpecMap |
高 | UniApp /detail API 缺少 VR 数据注入 |
| P1-B | plugins_service_goods_data Hook 未注册 |
中 | UniApp detail API 最佳入口缺失 |
| P2-A | Phase 4 Tree API buildTree() 未实现 |
中 | 设计完整,代码为零 |
| P2-B | api/Goods.php::seatmap() 命名不一致 |
低 | seatmap vs seatMap(大小写) |
三、技术方案建议
方案 A(推荐):Hook 注册(最小改动)
文件:Hook.php 追加 case:
case 'plugins_service_goods_data':
$goodsId = $params['goods_id'] ?? 0;
if ($goodsId > 0) {
TicketService::InjectGoodsDetailData($params['data'], $goodsId);
}
break;
新增方法:TicketService.php:
public static function InjectGoodsDetailData(array &$data, int $goodsId): void
{
if ($goodsId <= 0) return;
$vrConfig = \think\facade\Db::name('goods')
->where('id', $goodsId)
->value('vr_goods_config');
if (empty($vrConfig)) return;
$viewData = SeatSkuService::GetGoodsViewData($goodsId);
if (empty($viewData['seatSpecMap'])) return;
$data['seatSpecMap'] = $viewData['seatSpecMap'];
$data['goods_spec_data'] = $viewData['goods_spec_data'];
$data['specTypeList'] = $viewData['specTypeList'] ?? [];
$data['seatMap'] = $viewData['vr_seat_template']['seat_map'] ?? null;
$data['goods_config'] = $viewData['goods_config'] ?? null;
}
代码量:约 30 行。效果:UniApp 调用 ShopXO 标准 /goods/detail API 时自动获得 VR 数据。
方案 B(备选):UniApp 变通绕过(无需后端改动)
UniApp 端可在调用商品详情后,再调用 /seatmap API 补充 VR 数据。
- 优点:无需后端改动,立即可用
- 缺点:前端多一次 API 调用(可接受)
方案 C:Phase 4 完整实现(独立任务)
buildTree() 实现 + Tree VR 体验,作为 Phase 4 独立里程碑。
四、优先级建议
| 优先级 | 任务 | 预计工时 | 收益 |
|---|---|---|---|
| P1-A | Hook 注册 + InjectGoodsDetailData() |
30min | 解锁 UniApp 完整票务链路 |
| P1-B | api/Goods.php::detail() 命名规范化 |
10min | API 契约一致性 |
| P2 | Phase 4 Tree API 实现 | 待定 | Tree VR 体验 |
| P3 | Phase 4 完整 Tree 体验 | 待定 | VR 差异化功能 |
五、投票(Round 4)
议题:下一步主攻方向
投票:A — 后端优先
理由:
-
Hook 注册是最低成本最高收益:约 30 行代码,一次性解决 UniApp 商品详情 API 的 VR 数据注入问题。无需前端变通,减少 API 调用次数。
-
Round 4 重新评估确认:后端 seatmap API 已完整实现(P0-1/P0-3 误判已消除),核心剩余问题是 Hook 注入这一处。
-
Gap 2 已消除:后端票务链路(CartSave → onOrderPaid → 票生成)已完整,多座位支持已验证。
-
UniApp 可用方案 B 变通立即推进:即使 Hook 暂未注册,UniApp 仍可通过"先 /seatmap 后 /detail"的方式绕过 Gap 1 立即启动开发。
-
Phase 4 不应前置:Tree API 是体验增强,在核心票务链路(P1)稳定前启动 Phase 4 资源浪费。
补充:对其他提案的评估
- B(前端优先):可接受——UniApp 确实可以先用方案 B 变通绕过 Gap 1 立即开发。但变通方案不如 Hook 注册简洁。
- C(双线并行):可接受,但需明确分工。后端修 Hook,前端用方案 B 变通同时推进。
- D(Phase 4 优先):不建议。Phase 4 是锦上添花,不是票务购买的基础设施。
报告人:BackendArchitect | 2026-05-26 | Round 4