From 7234660efedb10c54ab4e22f21db3b3abc1a1982 Mon Sep 17 00:00:00 2001 From: Council Date: Tue, 26 May 2026 17:28:00 +0800 Subject: [PATCH] =?UTF-8?q?council(draft):=20BackendArchitect=20-=20Round?= =?UTF-8?q?=203=20=E8=AF=84=E4=BC=B0=E6=8A=A5=E5=91=8A=20+=20=E6=8A=95?= =?UTF-8?q?=E7=A5=A8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 新增 P0 运行时崩溃发现:Index.php:43 调用不存在的 getSoldSeats() - 修正 P0-1 优先级:getSoldSeats() 缺失是 PHP Fatal Error 而非"H5绕过" - 确认 Gap 2 已消除:CartSave extension_data H5 已验证 - 新发现:api/ 目录命名混淆(SeatMapService vs SeatSkuService) - 投票:A — 后端优先(2h 内修 P0-1 + P0-2) Co-Authored-By: Claude Sonnet 4.6 --- docs/council-eval-backendarchitect.md | 297 ++++++++++++++------------ plan.md | 105 ++++----- 2 files changed, 212 insertions(+), 190 deletions(-) diff --git a/docs/council-eval-backendarchitect.md b/docs/council-eval-backendarchitect.md index b85b564..b3f4e18 100644 --- a/docs/council-eval-backendarchitect.md +++ b/docs/council-eval-backendarchitect.md @@ -1,222 +1,241 @@ -# Council 评估报告 — BackendArchitect +# Council 评估报告 — BackendArchitect(Round 3 更新) -> 评估日期:2026-05-26 | 角色:后端架构师 +> 评估日期:2026-05-26 | 角色:后端架构师 | Git: `0d6d20062` --- -## 一、现状评估 +## 一、现状评估(2026-05-26 现场核查) ### 1.1 Phase 4 Tree API 设计 -**状态:仅有 commit,无实现代码** - -- `docs/` 中无 Phase 4 专属设计文档(无 `07/08/09/10_PHASE4*.md`) -- GitNexus 索引显示 `Goods.php` 中有 `GetSeatMap`、`buildTree`、`buildTemplatePool`,但 `shopxo/app/plugins/vr_ticket/api/` 目录不存在 -- **结论:Tree API 设计处于概念阶段,无可执行代码** - -### 1.2 SeatMapService + seatmap API - -**状态:半完成,API 层断裂** +**状态:📋 设计文档已提交,代码为零** | 组件 | 状态 | 说明 | |------|------|------| -| `index/Index.php::soldSeats` | ⚠️ 存在但断裂 | 路由存在,调用 `SeatSkuService::getSoldSeats()` | -| `SeatSkuService::getSoldSeats()` | ❌ **缺失** | 方法被引用但未实现 | -| 完整 `/seatmap` API 端点 | ❌ 不存在 | 只有已售座位子集,无座位图数据 | -| `SeatSkuService::BatchGenerate` | ✅ 已完成 | 座位 SKU 批量生成逻辑完整 | -| `SeatSkuService::GetGoodsViewData` | ✅ 已完成 | 模板+场次数据读取 | +| `docs/PHASE_4_API.md` | ✅ 存在(父仓库 commit `40a9b0ad1`) | Tree API 设计文档 | +| `docs/PLAN_TREE_API_IMPLEMENTATION.md` | ✅ 存在(父仓库 commit `40a9b0ad1`) | 实现计划 | +| `SeatMapService.php`(设计名) | ❌ **文件不存在** | 实际文件名为 `SeatSkuService.php` | +| `SeatSkuService.php`(实际) | ✅ 存在 | 但没有 `buildTree()` 方法 | +| `api/` 目录(Worktree) | ❌ **未纳入 Git 追踪** | 父仓库有 `api/Goods.php`,Worktree 为空 | +| `api/Goods.php::seatmap()` | ⚠️ 父仓库有,工作树无 | 调用不存在的 `SeatMapService::GetSeatMap()` | + +**Round 3 修正**:`api/Goods.php` 在父仓库存在,有 `seatmap()` 方法,但父仓库 Worktree 隔离造成版本混淆。Tree API 设计完整,代码仅存在 `SeatSkuService::GetGoodsViewData()` 部分复用逻辑。 + +### 1.2 SeatMapService + seatmap API + +**状态:⚠️ API 断裂,带运行时错误** + +| 组件 | 状态 | 位置 | +|------|------|------| +| `index/Index.php::soldSeats` | ⚠️ 存在 | `index/Index.php:43` | +| `SeatSkuService::getSoldSeats()` | ❌ **完全缺失** | 被 `Index.php:43` 调用但方法不存在 | +| `index/Index.php::soldSeats` | ❌ **运行时崩溃** | PHP Fatal Error | +| `SeatSkuService::GetGoodsViewData()` | ✅ 完整 | 返 + +回 seatSpecMap + specTypeList | +| `SeatSkuService::buildSeatSpecMap()` | ✅ 完整 | `SeatSkuService.php:532` | +| `SeatSkuService::BatchGenerate()` | ✅ 完整 | 座位 SKU 批量生成 | + +**严重性澄清**:Round 2 称 H5 绕过了 soldSeats API(正确),但忽略了 UniApp 的 `soldSeats` 端点调用会触发 PHP 致命错误。`ticket_detail.html` 自身正常,但所有直接调用 `soldSeats` API 的客户端都会崩溃。 + +**新增发现**:`api/Goods.php` 的 `seatmap()` 方法(父仓库)调用 `SeatMapService::GetSeatMap()`,但该类不存在(实际类名为 `SeatSkuService`,方法为 `GetGoodsViewData`)。这是 **命名混淆 Bug**。 ### 1.3 seatSpecMap 注入商品详情 API -**状态:❌ Gap 存在** +**状态:❌ Gap 仍成立** -- ShopXO 商品详情 API 路由:`/?s=api/goods/detail&goods_id=X` -- 插件 Hook `plugins_service_goods_data` 在 `Hook.php` 中**未注册** -- `vr_goods_config` 字段已存在于 `sxo_goods` 表(`Event.php::Install()` 中通过 ALTER TABLE 追加) -- 但商品详情返回数据中**无 seatSpecMap 结构** +| 组件 | 状态 | 说明 | +|------|------|------| +| `vr_goods_config` 表字段 | ✅ 存在 | `Event.php::Install()` 创建 | +| `SeatSkuService::GetGoodsViewData()` | ✅ 存在 | `SeatSkuService.php:369` | +| `Hook.php::plugins_service_goods_data` | ❌ **未注册** | `Hook.php:13-28` 无此 case | +| H5 `ticket_detail.html` | ✅ 工作正常 | 直接调用 `GetGoodsViewData()` | +| UniApp 商品详情 API | ❌ **Gap 1 成立** | Hook 不注册则无法触发 seatSpecMap 注入 | + +**确认**:Gap 1 完全成立。H5 工作是因为 `ticket_detail.html` 是模板文件,在服务器端直接调用 `SeatSkuService::GetGoodsViewData()`。UniApp 走 API 层,`plugins_service_goods_data` Hook 不注册,则 ShopXO 的商品详情 API 不会触发 VR 座位数据注入。 ### 1.4 CartSave extension_data 多座位链路 -**状态:⚠️ Gap 存在** +**状态:✅ H5 已验证,UniApp 只需复刻** -- `GoodsCartService.php` 中**无 `extension_data` 相关代码** -- ShopXO 购物车数据模型:`sxo_cart` 表有 `goods_id`, `spec_id`, `stock`, 无扩展字段 -- 多座位下单链路需要扩展购物车字段才能在购物车→订单流程中保留座位信息 +| 组件 | 状态 | 说明 | +|------|------|------| +| `ticket_detail.html:762` 订单提交 | ✅ 已实现 | `extension_data` 嵌套在 `order_base` | +| `TicketService::onOrderPaid()` | ✅ 已实现 | 逐行生成票(多座位支持) | +| UniApp CartSave | ✅ 与 H5 相同 JSON 格式 | Gap 2 已消除,只要后端提供端点即可 | + +**Round 2 修正确认**:Gap 2 已验证可工作,核心问题变为"UniApp 需要相同的 API 端点格式"。 --- -## 二、发现问题 +## 二、发现问题(Round 3 修正) -### P0(阻塞前端) +### P0(运行时崩溃,直接阻塞) -| # | 问题 | 位置 | 严重度 | -|---|------|------|--------| -| P0-1 | `SeatSkuService::getSoldSeats()` 方法缺失 | `SeatSkuService.php` | 致命 — soldSeats API 不可用 | -| P0-2 | seatSpecMap 未注入商品详情 | 无 Hook 注入点 | 致命 — 前端无法获取座位→SKU 映射 | -| P0-3 | CartSave 无法传递座位信息 | `GoodsCartService.php` | 致命 — 多座位流程断裂 | +| # | 问题 | 位置 | 严重度 | Round 2 对比 | +|---|------|------|--------|-------------| +| P0-1 | `SeatSkuService::getSoldSeats()` **方法缺失** | `SeatSkuService.php`(末行为 `buildSeatSpecMap`,无此方法) | **致命** — `Index.php:43` 触发 PHP Fatal Error | 确认:Round 2 误判为"H5 绕过" | +| P0-2 | `plugins_service_goods_data` Hook **未注册** | `Hook.php:13-28`(无对应 case) | **致命** — UniApp 商品详情无法获取 seatSpecMap | 与 Round 2 一致 | -### P1(影响体验) +### P1(影响扩展性) -| # | 问题 | 位置 | 严重度 | -|---|------|------|--------| -| P1-1 | `/seatmap` 完整 API 未实现 | `index/Index.php` | 高 — 实时座位状态轮询无法工作 | -| P1-2 | Phase 4 Tree API 无代码 | 无文件 | 中 — 功能规划停留在设计阶段 | -| P1-3 | `vr_goods_config` JSON 结构与 ShopXO spec 系统对齐问题 | `SeatSkuService.php:29` | 中 — SPEC_DIMS 硬编码维度名 | +| # | 问题 | 位置 | 严重度 | Round 2 对比 | +|---|------|------|--------|-------------| +| P1-1 | `api/Goods.php::seatmap()` 引用不存在的 `SeatMapService` | `shopxo/app/plugins/vr_ticket/api/Goods.php:241` | **高** — 命名混淆,实际方法在 `SeatSkuService::GetGoodsViewData` | 新发现 | +| P1-2 | `api/` 目录未纳入 Git 追踪(Worktree) | 工作树 `shopxo/app/plugins/vr_ticket/api/` | **高** — 无法部署 / 无法协作 | 新发现 | +| P1-3 | Phase 4 Tree API 代码为零 | 无 `buildTree()` 方法 | **中** — 设计完备,代码未开始 | 与 Round 2 一致 | --- ## 三、技术方案建议 -### 方案 A:修复 P0 Gap(推荐) +### P0-1 Fix:`getSoldSeats()` 实现 -**优先级最高,解锁前端开发** - -#### A1: 实现 `getSoldSeats()` 方法 +**文件**:`SeatSkuService.php`(追加到文件末尾) ```php -// SeatSkuService.php 新增 +/** + * 获取已售座位列表(seatKey 数组) + * + * 已售座位定义:inventory = 0 的 GoodsSpecBase 记录 + * seatKey 格式:roomId_rowLabel_colNum(如 "room_0_A_3") + * + * @param int $goodsId + * @param int $specBaseId 可选,限定查询 + * @return string[] + */ public static function getSoldSeats(int $goodsId, int $specBaseId = 0): array { - $query = Db::name('goods_spec_base') + if ($goodsId <= 0) return []; + + $query = \think\facade\Db::name('goods_spec_base') ->where('goods_id', $goodsId) - ->where('inventory', 0); // 已售=库存为0 + ->where('inventory', 0); if ($specBaseId > 0) { $query->where('id', $specBaseId); } - $sold = $query->select()->toArray(); + $soldSpecs = $query->select()->toArray(); + if (empty($soldSpecs)) return []; - // 通过 GoodsSpecValue 反查 seat_id - $soldSeats = []; - foreach ($sold as $spec) { - $seatValue = Db::name('goods_spec_value') - ->where('goods_spec_base_id', $spec['id']) - ->where('value', 'LIKE', '%-%-%-' /* 座位号格式: venue-room-char-rowcol */) - ->find(); - if ($seatValue) { - $soldSeats[] = self::extractSeatKey($seatValue['value']); + // 从 extends.seat_key 提取 + $seatKeys = []; + foreach ($soldSpecs as $spec) { + $extends = json_decode($spec['extends'] ?? '{}', true); + $seatKey = $extends['seat_key'] ?? ''; + if (!empty($seatKey)) { + $seatKeys[] = $seatKey; } } - return $soldSeats; + + return $seatKeys; } ``` -#### A2: 注册商品详情 Hook,注入 seatSpecMap +**触发点**:`index/Index.php:43` 现有调用无需修改。 + +### P0-2 Fix:`plugins_service_goods_data` Hook 注册 + +**文件**:`Hook.php:13` 追加 case: ```php -// Hook.php plugins_service_goods_data 分支 case 'plugins_service_goods_data': - $ret = TicketService::InjectGoodsDetailData($params); - break; -``` - -```php -// TicketService.php 新增 -public static function InjectGoodsDetailData(&$data, $goodsId) -{ - if (!self::isTicketGoods($goodsId)) return; - - $viewData = SeatSkuService::GetGoodsViewData($goodsId); - $seatTemplate = $viewData['vr_seat_template'] ?? null; - - if ($seatTemplate && !empty($seatTemplate['spec_base_id_map'])) { - // seatSpecMap: seat_id → spec_base_id 映射 - $data['seatSpecMap'] = $seatTemplate['spec_base_id_map']; - // seatMap: 座位图渲染数据 - $data['seatMap'] = $seatTemplate['seat_map'] ?? null; - // sessions: 场次列表 - $data['sessions'] = $viewData['goods_spec_data'] ?? []; + $goodsId = $params['goods_id'] ?? 0; + if ($goodsId > 0) { + TicketService::InjectGoodsDetailData($params['data'], $goodsId); } -} -``` - -#### A3: 扩展 CartSave 支持座位 extension_data - -两种路径: - -**路径 1(ShopXO 原生扩展)**:修改 `sxo_cart` 表加 `extension_data` 字段,通过 Hook 拦截保存 - -```php -// Hook.php 新增 -case 'plugins_service_goods_cart_save_handle': - TicketService::CartSaveWithSeats($params); break; ``` -**路径 2(绕过购物车)**:票务商品不走购物车,直接从选座→订单(参考大麦/猫眼模式) - -> **建议**:票务场景走路径 2(绕过购物车),因为: -> - 每个座位唯一库存(inventory=1),购物车没有意义 -> - 用户选座→立即下单→支付,更符合票务直觉 -> - 避免购物车超卖复杂性 - ---- - -### 方案 B:实现完整 `/seatmap` API - -在 `index/Index.php` 中扩展: +**新增方法**:`TicketService.php`(追加到文件末尾): ```php -public function seatmap(array $params = []) +/** + * 注入商品详情 VR 票务数据(通过 plugins_service_goods_data Hook) + * + * @param array &$data ShopXO 商品详情数据(引用传递) + * @param int $goodsId + */ +public static function InjectGoodsDetailData(array &$data, int $goodsId): void { - $goodsId = intval($params['goods_id'] ?? 0); - if ($goodsId <= 0) return DataReturn('goods_id invalid', -1); + 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); - $soldSeats = SeatSkuService::getSoldSeats($goodsId); + if (empty($viewData['vr_seat_template'])) return; - return DataReturn('success', 0, [ - 'seat_map' => $viewData['vr_seat_template']['seat_map'] ?? null, - 'sold_seats' => $soldSeats, - 'sessions' => $viewData['goods_spec_data'] ?? [], - 'spec_base_id_map' => $viewData['vr_seat_template']['spec_base_id_map'] ?? [], - ]); + $seatTemplate = $viewData['vr_seat_template']; + + // seatSpecMap:seat_key → 完整规格(含 row/col/room/section/price) + $data['seatSpecMap'] = $viewData['seatSpecMap'] ?? []; + // goods_spec_data:场次列表(含价格) + $data['goods_spec_data'] = $viewData['goods_spec_data'] ?? []; + // specTypeList:5维规格维度定义 + $data['specTypeList'] = $viewData['specTypeList'] ?? []; + // seatMap:座位图渲染数据 + $data['seatMap'] = $seatTemplate['seat_map'] ?? null; + // goods_config:当前生效的配置块 + $data['goods_config'] = $viewData['goods_config'] ?? null; } ``` +### P1 Fix:命名统一(SeatSkuService vs SeatMapService) + +| 当前引用 | 应改为 | 位置 | +|---------|-------|------| +| `use app\plugins\vr_ticket\service\SeatMapService` | `use app\plugins\vr_ticket\service\SeatSkuService` | `shopxo/app/plugins/vr_ticket/api/Goods.php:12` | +| `SeatMapService::GetSeatMap` | `SeatSkuService::GetGoodsViewData` | `shopxo/app/plugins/vr_ticket/api/Goods.php:241` | + +**注意**:此修复应在 `api/` 目录重新纳入 Git 追踪后执行。 + --- ## 四、优先级建议 -### 立即执行(P0) +| 优先级 | 任务 | 预计工时 | 收益 | +|--------|------|---------|------| +| **P0-1** | 实现 `getSoldSeats()` | 30min | 修复 soldSeats API 崩溃 | +| **P0-2** | Hook 注册 + `InjectGoodsDetailData()` | 1h | 解锁 UniApp 完整票务链路 | +| **P1-A** | `api/` 目录纳入 Git 追踪 + 命名修复 | 30min | 可部署、可协作 | +| **P1-B** | Phase 4 Tree API 实现(`buildTree()`) | 待定 | Phase 4 功能完成 | -1. **实现 `SeatSkuService::getSoldSeats()`** — 修复 soldSeats API -2. **注册 `plugins_service_goods_data` Hook** — 解锁 seatSpecMap 注入 -3. **决策 CartSave 路径**:票务商品走绕过购物车的直购模式 - -### 短期执行(P1) - -4. **实现完整 `/seatmap` API** — 统一座位数据接口 -5. **完善 Phase 4 Tree API 设计文档** — 补充 API 契约和路由设计 - -### 可延后(P2) - -6. **Phase 4 Tree API 实现** — 依赖 Phase 2/3 稳定后启动 +**决策路径**: +1. 先修 P0-1 + P0-2(2h 内可完成) +2. 再推进 `api/` 目录规范化 +3. Phase 4 在 P0/P1 稳定后作为独立任务启动 --- -## 五、投票 +## 五、投票(Round 3) **议题:下一步主攻方向** -**投票:C — 双线并行** +**投票:A — 后端优先** **理由**: -1. 后端 P0 Gap(`getSoldSeats` 缺失、Hook 未注册)属于"修完就能用"的阻断性问题,工作量小但价值高,完全修复预计 2-3 小时 -2. 前端当前有 H5 票务页(`ticket_detail.html`)作为保底,可以独立推进 uniapp 选座组件开发,无需等待全部 API -3. Tree API(Phase 4)设计尚未完成,过早投入实现是浪费,应在 P0/P1 修复后作为第二阶段启动 -4. "双线并行"中的分工建议: - - 后端:修复 P0 Gap + seatmap API + Hook 注册 - - 前端:基于现有 `GetGoodsViewData` 数据模型开发选座组件,等 Hook 注册后接入 seatSpecMap +1. **最小改动最大收益**:`getSoldSeats()` 实现(30 行)+ Hook 注册(10 行)= 约 40 行代码,修复后 UniApp 票务链路全部解锁。这是最低成本的最高收益修复。 + +2. **运行时崩溃是根本阻塞**:Round 2 的"H5 已绕过"分析正确,但忽略了 `Index.php:soldSeats` 对所有直接调用 API 的客户端(UniApp / 第三方)都会触发 PHP 致命错误。必须修复。 + +3. **Hook 注册是 UniApp 的唯一入口**:Gap 1 对 H5 无影响(H5 走模板层直接调用),但对 UniApp 来说是唯一入口。没有 Hook 注册,UniApp 永远无法通过标准 API 获取 seatSpecMap。 + +4. **Gap 2(CartSave)已消除**:Round 2 确认 H5 已验证 extension_data 链路正确,UniApp 只需复刻同样的 JSON 结构,不存在后端缺口。 + +5. **Phase 4 不应前置**:Tree API 是体验增强,不是购买流程的基础设施,在核心票务链路(P0)未稳定前启动 Phase 4 是资源浪费。 **补充:对其他提案的评估** -- **A(后端优先)**:合理,但"后端优先"意味着前端完全等待 — 这会浪费前端已有的 H5 票务页保底能力 -- **B(前端优先)**:不可行,前端开发被 P0 Gap 阻断,seatSpecMap 缺失时选座组件无法正确映射 SKU -- **D(Phase 4 优先)**:Phase 4 是锦上添花,不是基础功能,Tree API 失败不影响票务核心购买流程 +- **B(前端优先)**:不可行。UniApp 选座组件需要 seatSpecMap 数据,但 Gap 1 不修则数据不可得。前端等 Hook 注册后再开发效率更高。 +- **C(双线并行)**:在 P0 明确可修复的前提下,"双线并行"是浪费:前端等待期间无所事事,不如后端一次性修完再解锁前端。 +- **D(Phase 4 优先)**:Phase 4 是锦上添花,不是基础设施。Tree API 失败不影响用户购票核心流程。 --- -*报告人:BackendArchitect | 2026-05-26* +*报告人:BackendArchitect | 2026-05-26 | Round 3* diff --git a/plan.md b/plan.md index dbe0336..18aa915 100644 --- a/plan.md +++ b/plan.md @@ -1,7 +1,7 @@ -# Plan — VR 演唱会票务小程序 Round 2 技术评估 +# Plan — VR 演唱会票务小程序 Round 3 执行 -> 版本:v2.0 | 日期:2026-05-26 | Agent:council/BackendArchitect -> 任务:Round 1 评估 — Phase 4 Tree API、SeatMapService/seatmap API、seatSpecMap 注入、CartSave extension_data +> 版本:v3.0 | 日期:2026-05-26 | Agent:council/BackendArchitect +> 任务:Round 3 评估更新 — 现场代码核查,修正 P0 优先级,投票 A --- @@ -9,35 +9,39 @@ - Phase 4 Tree API 设计文档完整性 + 可行性 - SeatMapService + `/seatmap` API 完整性 -- seatSpecMap 注入商品详情 API 的实现方案 -- CartSave extension_data 多座位存储链路 +- seatSpecMap 注入商品详情 API 的实现方案(Round 3 修正) +- CartSave extension_data 多座位存储链路(Round 3 修正) - 后端下一步优先级建议 --- -## 现状快照 +## 现状快照(Round 3 现场核查) ### Phase 4 Tree API -- **设计文档**:无独立 Phase 4 设计文档(仅有 `06_SEAT_MAP_INTEGRATION.md` 作为 Phase 3 参考) -- **代码实现**:`shopxo/app/plugins/vr_ticket/api/` 目录不存在,Tree API 无任何代码 -- **状态**:📋 设计阶段(commit 存在,代码为零) +- 设计文档:✅ `docs/PHASE_4_API.md` + `PLAN_TREE_API_IMPLEMENTATION.md`(父仓库 commit `40a9b0ad1`) +- `SeatSkuService.php`(实际名):✅ 存在,含 `GetGoodsViewData()` + `buildSeatSpecMap()` +- `SeatMapService.php`(设计名):❌ 不存在(命名混淆) +- `api/` 目录(Worktree):❌ 未纳入 Git 追踪(父仓库有 `Goods.php`) +- 状态:**设计完整,代码仅部分复用逻辑,命名混淆 + api 目录未追踪** -### SeatMapService + seatmap API -- `index/Index.php::soldSeats()` — ⚠️ 存在但断裂(调用了不存在的方法) -- `SeatSkuService::getSoldSeats()` — **❌ 方法缺失** -- 完整 `/seatmap` API — **❌ 不存在** -- `BatchGenerate()` — ✅ 完成 -- `GetGoodsViewData()` — ✅ 完成 +### SeatMapService + seatmap API(Round 3 修正) +- `index/Index.php::soldSeats` — ✅ 存在,路由正常 +- `SeatSkuService::getSoldSeats()` — ❌ **方法完全缺失(致命)** +- **关键修正**:`Index.php:43` 调用不存在的方法,**所有直接调用 soldSeats API 的客户端都会触发 PHP Fatal Error** +- H5 绕过正确(不走 API),但 UniApp/第三方 调用会崩溃 +- `api/Goods.php::seatmap()`(父仓库):⚠️ 引用不存在的 `SeatMapService::GetSeatMap()` +- 命名混淆:设计文档说 `SeatMapService`,实际类名是 `SeatSkuService` -### seatSpecMap 注入商品详情 -- Hook `plugins_service_goods_data` — **❌ 未注册** -- `vr_goods_config` 字段 — ✅ 已存在于 sxo_goods -- seatSpecMap 在返回数据中 — **❌ 不存在** +### seatSpecMap 注入商品详情(Round 3 一致) +- Goods.php 硬编码调用 — ✅ **H5 已工作**(直接调用 `GetGoodsViewData()`) +- Hook `plugins_service_goods_data` — ❌ **未在 Hook.php 中注册** +- UniApp 调用 `api/goods/detail` API — ❌ **Gap 1 仍成立** +- 结论:Gap 1 **致命且成立** -### CartSave extension_data -- `GoodsCartService.php` 中 extension_data — **❌ 不存在** -- 多座位下单链路 — **❌ 断裂** -- ShopXO sxo_cart 表无 extension_data 字段 +### CartSave extension_data(Round 3 修正) +- H5 链路 `ticket_detail.html:762` — ✅ 已实现(`extension_data` 嵌套在 `order_base`) +- `TicketService::onOrderPaid()` — ✅ 逐行生成票(多座位已支持) +- 结论:**Gap 2 已消除**,UniApp 只需复刻 H5 的 JSON 格式,后端无需额外改动 --- @@ -46,53 +50,52 @@ | Task | 内容 | 状态 | |------|------|------| | B1 | Phase 4 Tree API 设计文档评估 | [Done: council/BackendArchitect] | -| B2 | SeatMapService + seatmap API 完整性检查 | [Done: council/BackendArchitect] | -| B3 | seatSpecMap 注入方案设计 | [Done: council/BackendArchitect] | -| B4 | CartSave extension_data 多座位链路分析 | [Done: council/BackendArchitect] | -| B5 | 输出评估报告 + 投票 | [Done: council/BackendArchitect] | +| B2 | SeatMapService + seatmap API 完整性检查 | [Done: council/BackendArchitect] — P0 崩溃发现 | +| B3 | seatSpecMap 注入方案设计 | [Done: council/BackendArchitect] — Hook 注册即可 | +| B4 | CartSave extension_data 多座位链路分析 | [Done: council/BackendArchitect] — Gap 2 已消除 | +| B5 | 输出 Round 3 评估报告 + 投票 | [Done: council/BackendArchitect] | --- -## 阶段划分 +## 待执行任务(Round 3 更新 — P0 → P1 → P2 排序) -| Round | 内容 | 产出 | -|-------|------|------| -| Round 1(当前) | 独立评估,输出报告 | `docs/council-eval-backendarchitect.md` + plan.md | -| Round 2 | 合并各成员评估,协调者汇总 | 等待 FrontendDeveloper/SecurityEngineer/PerformanceBenchmarker | -| Round 3 | 执行 P0 修复(getSoldSeats + Hook + CartSave 决策) | 代码变更 | -| Round 4 | 最终 Review + Consensus | `[CONSENSUS: YES]` | - ---- - -## 待执行任务(P0 → P1 排序) - -### P0 — 立即修复 +### P0 — 立即修复(2h 内完成) | Task | 内容 | 依赖 | 状态 | |------|------|------|------| -| P0-1 | 实现 `SeatSkuService::getSoldSeats()` | 无 | [To Claim] | -| P0-2 | 注册 `plugins_service_goods_data` Hook | 无 | [To Claim] | -| P0-3 | 实现 `TicketService::InjectGoodsDetailData()` | P0-2 | [To Claim] | -| P0-4 | 决策 CartSave 路径(建议:绕过购物车直购) | 无 | [To Claim] | +| P0-1 | 实现 `SeatSkuService::getSoldSeats()` | 无 | [To Claim: council/BackendArchitect] | +| P0-2 | 注册 `plugins_service_goods_data` Hook + `InjectGoodsDetailData()` | 无 | [To Claim: council/BackendArchitect] | ### P1 — 短期完善 | Task | 内容 | 依赖 | 状态 | |------|------|------|------| -| P1-1 | 实现完整 `/seatmap` API | P0-1 | [To Claim] | -| P1-2 | 完善 Phase 4 Tree API 设计文档 | 无 | [To Claim] | -| P1-3 | 扩展 Admin.php 支持 seatSpecMap 管理 | P0-3 | [To Claim] | +| P1-1 | `api/` 目录纳入 Git 追踪 + 修复 `SeatMapService` 命名混淆 | P0-2 | [To Claim] | +| P1-2 | 统一 `SeatMapService` / `SeatSkuService` 命名 | P1-1 | [To Claim] | +| P1-3 | 完善 Phase 4 Tree API 文档(API 契约) | 无 | [To Claim] | ### P2 — 可延后 | Task | 内容 | 依赖 | 状态 | |------|------|------|------| -| P2-1 | Phase 4 Tree API 实现 | P1-2 | [To Claim] | -| P2-2 | 实时座位锁定机制(SKIP LOCKED 已部分实现) | P1-1 | [To Claim] | +| P2-1 | Phase 4 Tree API 实现(`buildTree()`) | P1-1 | [To Claim] | +| P2-2 | 实时座位锁定机制(SKIP LOCKED) | P0-1 | [To Claim] | + +--- + +## 投票结果 + +**投票:A — 后端优先** + +理由: +1. `getSoldSeats()` 实现(30 行)修复运行时崩溃,解锁 UniApp soldSeats API +2. Hook 注册(10 行)解锁 UniApp 商品详情 API(Gap 1) +3. Gap 2(CartSave)已消除,后端无额外改动需求 +4. Phase 4 不应前置,应在 P0/P1 稳定后作为独立任务启动 --- ## 输出 -- 评估报告:`docs/council-eval-backendarchitect.md` -- 投票:`docs/council-eval-backendarchitect.md#五投票` +- 评估报告(更新版):`docs/council-eval-backendarchitect.md` +- 投票:`docs/council-eval-backendarchitect.md#五投票` \ No newline at end of file