0]; } // ────────────────────────────────────────────────────── // 时机 2:plugins_service_goods_save_thing_end(事务内,goods 已落表) // 关键:此时 GoodsSpecificationsInsert + GoodsSaveBaseUpdate // 已经执行完毕(它们处理的是表单原生规格数据)。 // // 对于票务商品,我们需要: // a) 删除原生流程产生的所有 spec 数据(表单垃圾) // b) 用 BatchGenerate 重新生成 VR 座位级 SKU // c) 回写 GoodsSpecType.value(让后台正确展示) // d) 重新计算 goods 表的 price/inventory // ────────────────────────────────────────────────────── if ($hookName === 'plugins_service_goods_save_thing_end') { $data = $params['data'] ?? []; $goodsId = $params['goods_id'] ?? 0; if ($goodsId > 0 && ($data['item_type'] ?? '') === 'ticket') { $rawConfig = $data['vr_goods_config'] ?? ''; if (!empty($rawConfig)) { $configs = json_decode($rawConfig, true); if (is_array($configs) && !empty($configs)) { // 0) 填充 template_snapshot(前端没传时兜底从 vr_seat_templates 读) foreach ($configs as $i => &$config) { if (empty($config['template_snapshot'])) { $templateId = intval($config['template_id'] ?? 0); if ($templateId > 0) { $template = Db::name('vr_seat_templates')->find($templateId); $seatMap = json_decode($template['seat_map'] ?? '{}', true); $allRooms = $seatMap['rooms'] ?? []; // 按 selected_rooms 过滤,只存用户选中的房间 $selectedRoomIds = array_column( array_filter($allRooms, function ($r) use ($config) { return in_array($r['id'], $config['selected_rooms'] ?? []); }), null ); $config['template_snapshot'] = [ 'venue' => $seatMap['venue'] ?? [], 'rooms' => $selectedRoomIds, ]; } } } unset($config); // 解除引用,避免后续误改 // 将填充后的完整 config 写回 goods 表 Db::name('Goods')->where('id', $goodsId)->update([ 'vr_goods_config' => json_encode($configs, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), ]); // a) 清空原生规格数据 —— 避免列偏移 Db::name('GoodsSpecType')->where('goods_id', $goodsId)->delete(); Db::name('GoodsSpecBase')->where('goods_id', $goodsId)->delete(); Db::name('GoodsSpecValue')->where('goods_id', $goodsId)->delete(); // b) 逐模板生成 VR SKU(ensureAndFillVrSpecTypes 在内部调用,type.value 同步写入) foreach ($configs as $config) { $templateId = intval($config['template_id'] ?? 0); $selectedRooms = $config['selected_rooms'] ?? []; $selectedSections = $config['selected_sections'] ?? []; $sessions = $config['sessions'] ?? []; if ($templateId > 0) { $res = SeatSkuService::BatchGenerate( $goodsId, $templateId, $selectedRooms, $selectedSections, $sessions ); if ($res['code'] !== 0) { return $res; } } } // c) 重新计算 goods.price / goods.inventory SeatSkuService::refreshGoodsBase($goodsId); } } } return ['code' => 0]; } return ['code' => 0]; } }