# Plan: 幽灵 Spec 问题修复 > 日期:2026-04-20 | Issue: #15 + #16 | 状态:待实施 --- ## 问题概览 | Issue | 问题 | 优先级 | 根因文件 | |--------|------|--------|---------| | #15 | save_thing_end 脏数据写回 | P1 | AdminGoodsSaveHandle.php | | #16 | GetGoodsViewData 单模板模式 | P1 | SeatSkuService.php | --- ## Issue #15 — save_thing_end 脏数据写回 ### 根因 `AdminGoodsSaveHandle.php` 第 60-65 行:DB 值优先(`$goodsRow['vr_goods_config']`),前端过滤后的值(`$data['vr_goods_config']`)只是 fallback。脏 config 块(含已删除场馆的 template_id)被写回 DB,幽灵 spec 累积。 ### 修复计划 #### 步骤 1:调换读取优先级(主要修复) **文件**:`shopxo/app/plugins/vr_ticket/hook/AdminGoodsSaveHandle.php` **行号**:第 60-65 行 ```php // 修改前 $rawConfig = is_array($goodsRow) ? ($goodsRow['vr_goods_config'] ?? '') : ''; if (empty($rawConfig)) { $rawConfig = $data['vr_goods_config'] ?? ''; } // 修改后(主要修复) // 前端已过滤无效 template_id,优先使用 data。若无前端数据再 fallback 到 DB if (!empty($data['vr_goods_config'])) { $rawConfig = $data['vr_goods_config']; } else { $rawConfig = is_array($goodsRow) ? ($goodsRow['vr_goods_config'] ?? '') : ''; } ``` **验证**: - 提交后 `git diff` 确认读取顺序调换 - `git status` 确认只有 AdminGoodsSaveHandle.php 被修改 #### 步骤 2:无效 config 块移除(防御层) **文件**:同上 **行号**:第 88-89 行 ```diff if (empty($template)) { - continue; + unset($configs[$i]); // 移除无效 config 块 + continue; } ``` **行号**:第 145 行(`unset($config);` 之后) ```php $configs = array_values($configs); // 重排数组索引 ``` **验证**: - grep 确认 `unset($configs[$i])` 在第 89 行附近 - grep 确认 `array_values` 在 `unset($config)` 之后 #### 步骤 3:写回前判空(防御层) **行号**:第 148 行之前 ```diff + if (!empty($configs)) { Db::name('Goods')->where('id', $goodsId)->update([ 'vr_goods_config' => json_encode($configs, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), ]); + } ``` --- ## Issue #16 — GetGoodsViewData 单模板模式 ### 根因 `SeatSkuService.php` 第 368 行:只取 `$vrGoodsConfig[0]`(第一个配置块)。多模板商品时其余配置块被完全忽略;写回时只写 `[$config]` 单元素,可能覆盖其他有效配置块。 ### 修复计划 #### 步骤 1:过滤有效配置块 **文件**:`shopxo/app/plugins/vr_ticket/service/SeatSkuService.php` **行号**:第 365-373 行(在 `$config = $vrGoodsConfig[0];` 之前) ```php // 过滤有效配置块 $validConfigs = []; foreach ($vrGoodsConfig as $cfg) { $tid = intval($cfg['template_id'] ?? 0); if ($tid <= 0) continue; $tpl = Db::name(self::table('seat_templates'))->where('id', $tid)->find(); if (!empty($tpl)) { $validConfigs[] = $cfg; } } if (empty($validConfigs)) { return ['vr_seat_template' => null, 'goods_spec_data' => [], 'goods_config' => null]; } $config = $validConfigs[0]; // 取第一个有效配置块用于前端展示 ``` #### 步骤 2:修改写回逻辑 **行号**:第 386-388 行(原写回 `[$config]`) ```diff - Db::name('Goods')->where('id', $goodsId)->update([ - 'vr_goods_config' => json_encode([$config], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), - ]); + Db::name('Goods')->where('id', $goodsId)->update([ + 'vr_goods_config' => json_encode($validConfigs, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), + ]); ``` **验证**: - grep 确认 `validConfigs` 被用于写回 - grep 确认不再有 `[$config]` 写回模式 --- ## 实施顺序 ``` 1. Issue #15(AdminGoodsSaveHandle.php)— 三步修改 2. Issue #16(SeatSkuService.php)— 两步修改 3. 验证:grep + git diff 确认修改正确 4. commit + push ``` --- ## 禁止事项 - 不改其他文件(尤其是 Admin.php) - 不改 Hook.php 或其他无关文件 - commit 前执行 `git status` 确认只有目标文件