fix(vr_ticket): template_snapshot 重建逻辑重写 + 幽灵配置过滤
=== 问题 1: template_snapshot.rooms 为空 ===
根因:前端 outputBase64 根本不包含 template_snapshot,导致:
- template_snapshot 永远是空的
- 无论 v1/v3 格式,rooms 信息都丢失
修复(AdminGoodsSaveHandle.php):
- 条件从「template_snapshot 为空才读 DB」改为「selected_rooms 有值就永远从 DB 重建」
- 读 DB 时同时做 v1→v3 迁移(sections+map → rooms 数组)
- ID 匹配支持前端标准化的 "room_0" 格式和 DB 原始 "0" 格式双向兼容
- PHP 7.x 兼容(strpos 而非 str_starts_with)
=== 问题 2: 幽灵配置(软删除场馆仍出现在表单)===
根因:AdminGoodsSave.php 查询模板时用 where('status', 1),软删除模板不加载,
但 configs.value 里还保留着旧配置 → 场馆 checkbox 选中但无法操作。
修复(AdminGoodsSave.php):
- 加载时用 Set 过滤掉 status=0 模板的配置
- 幽灵配置在编辑表单加载时直接排除,不出现在 UI
council/ProductManager
parent
ca7bee5494
commit
da001797ab
|
|
@ -194,7 +194,13 @@ class AdminGoodsSave
|
||||||
|
|
||||||
// 还原已保存的配置并清洗历史脏数据
|
// 还原已保存的配置并清洗历史脏数据
|
||||||
if (AppData.vrGoodsConfig && Array.isArray(AppData.vrGoodsConfig)) {
|
if (AppData.vrGoodsConfig && Array.isArray(AppData.vrGoodsConfig)) {
|
||||||
configs.value = AppData.vrGoodsConfig.map(c => {
|
// 构建有效模板 ID 集合(只含 status=1 的模板)
|
||||||
|
const validTemplateIds = new Set((AppData.templates || []).map(t => t.id));
|
||||||
|
|
||||||
|
configs.value = AppData.vrGoodsConfig
|
||||||
|
// 过滤掉软删除模板的配置(幽灵配置)
|
||||||
|
.filter(c => validTemplateIds.has(c.template_id))
|
||||||
|
.map(c => {
|
||||||
// 确保 sessions 结构正确
|
// 确保 sessions 结构正确
|
||||||
if (!c.sessions || c.sessions.length === 0) {
|
if (!c.sessions || c.sessions.length === 0) {
|
||||||
c.sessions = defaultSessions();
|
c.sessions = defaultSessions();
|
||||||
|
|
|
||||||
|
|
@ -67,46 +67,59 @@ class AdminGoodsSaveHandle
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is_array($configs) && !empty($configs)) {
|
if (is_array($configs) && !empty($configs)) {
|
||||||
// 0) 填充 template_snapshot(前端没传、或 rooms 为空时兜底从 vr_seat_templates 读)
|
// 0) 重建 template_snapshot — 前端不发送 template_snapshot,
|
||||||
|
// 当 template_snapshot 为空、或 selected_rooms 有值时,从 DB 重建
|
||||||
foreach ($configs as $i => &$config) {
|
foreach ($configs as $i => &$config) {
|
||||||
if (empty($config['template_snapshot']) || empty($config['template_snapshot']['rooms'])) {
|
$templateId = intval($config['template_id'] ?? 0);
|
||||||
$templateId = intval($config['template_id'] ?? 0);
|
$selectedRooms = $config['selected_rooms'] ?? [];
|
||||||
if ($templateId > 0) {
|
|
||||||
$template = Db::name('vr_seat_templates')->find($templateId);
|
|
||||||
if (empty($template)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
$seatMap = json_decode($template['seat_map'] ?? '{}', true);
|
|
||||||
$allRooms = $seatMap['rooms'] ?? [];
|
|
||||||
|
|
||||||
// ── v1→v3 兼容迁移 ──
|
// 条件:snapshot 为空,或者前端有 selected_rooms
|
||||||
// v1 旧格式没有 rooms 嵌套,只有 sections+map 扁平结构
|
if ($templateId > 0 && (!empty($selectedRooms) || empty($config['template_snapshot']) || empty($config['template_snapshot']['rooms']))) {
|
||||||
if (empty($allRooms) && !empty($seatMap['sections'])) {
|
$template = Db::name('vr_seat_templates')->find($templateId);
|
||||||
$v1Sections = $seatMap['sections'] ?? [];
|
if (empty($template)) {
|
||||||
$v1Map = $seatMap['map'] ?? [];
|
continue;
|
||||||
$v1Seats = $seatMap['seats'] ?? [];
|
|
||||||
$v1RoomId = $config['selected_rooms'][0] ?? 'room_1';
|
|
||||||
$allRooms = [[
|
|
||||||
'id' => $v1RoomId,
|
|
||||||
'name' => $seatMap['venue']['name'] ?? '主馆',
|
|
||||||
'sections' => $v1Sections,
|
|
||||||
'map' => $v1Map,
|
|
||||||
'seats' => $v1Seats,
|
|
||||||
]];
|
|
||||||
}
|
|
||||||
|
|
||||||
// 按 selected_rooms 过滤,只存用户选中的房间
|
|
||||||
$selectedRoomIds = array_column(
|
|
||||||
array_filter($allRooms, function ($r) use ($config) {
|
|
||||||
return isset($r['id']) && in_array($r['id'], $config['selected_rooms'] ?? []);
|
|
||||||
}), null
|
|
||||||
);
|
|
||||||
|
|
||||||
$config['template_snapshot'] = [
|
|
||||||
'venue' => $seatMap['venue'] ?? [],
|
|
||||||
'rooms' => $selectedRoomIds,
|
|
||||||
];
|
|
||||||
}
|
}
|
||||||
|
$seatMap = json_decode($template['seat_map'] ?? '{}', true);
|
||||||
|
$allRooms = $seatMap['rooms'] ?? [];
|
||||||
|
|
||||||
|
// ── v1→v3 兼容迁移 ──
|
||||||
|
// v1 旧格式没有 rooms 嵌套,只有 sections+map 扁平结构
|
||||||
|
if (empty($allRooms) && !empty($seatMap['sections'])) {
|
||||||
|
$v1Sections = $seatMap['sections'] ?? [];
|
||||||
|
$v1Map = $seatMap['map'] ?? [];
|
||||||
|
$v1Seats = $seatMap['seats'] ?? [];
|
||||||
|
$v1RoomId = $selectedRooms[0] ?? 'room_1';
|
||||||
|
$allRooms = [[
|
||||||
|
'id' => $v1RoomId,
|
||||||
|
'name' => $seatMap['venue']['name'] ?? '主馆',
|
||||||
|
'sections' => $v1Sections,
|
||||||
|
'map' => $v1Map,
|
||||||
|
'seats' => $v1Seats,
|
||||||
|
]];
|
||||||
|
}
|
||||||
|
|
||||||
|
// 按 selected_rooms 过滤(支持前端标准化的 "room_0" 格式双向兼容)
|
||||||
|
$selectedRoomIds = array_column(
|
||||||
|
array_filter($allRooms, function ($r) use ($selectedRooms) {
|
||||||
|
$rid = $r['id'] ?? '';
|
||||||
|
if (in_array($rid, $selectedRooms)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// 尝试加/减 "room_" 前缀匹配(PHP 7.x 兼容)
|
||||||
|
if (strpos($rid, 'room_') === 0 && in_array(substr($rid, 5), $selectedRooms)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (in_array('room_' . $rid, $selectedRooms)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}), null
|
||||||
|
);
|
||||||
|
|
||||||
|
$config['template_snapshot'] = [
|
||||||
|
'venue' => $seatMap['venue'] ?? [],
|
||||||
|
'rooms' => $selectedRoomIds,
|
||||||
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
unset($config); // 解除引用,避免后续误改
|
unset($config); // 解除引用,避免后续误改
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue