# 架构对齐文档 — 用户需求 vs 文档现状

> PM Agent 输出 | 2026-04-14
> 状态：草稿，待确认

---

## 一、用户需求摘要

以下需求从对话记录中提取，已确认：

| # | 需求 | 来源 |
|---|---|---|
| U1 | **spec = 场次**：规格（spec）直接作为场次，不需要独立的 vr_sessions 表 | "规格（spec）就是场次" |
| U2 | **每个商品 = 一个场馆的演唱会**：用户在一个商品内完成选座购买全流程 | "每一个商品就是一个物理意义上的电影院或者演出地址" |
| U3 | **场次作为分类值**：场次加载为 ShopXO 的分类（category）值，后台通过分类名关联 | "场次这个东西我们直接加载成一个分类值就好了" |
| U4 | **座位模板 → 绑定分类 → 商品关联**：后台创建座位模板 → 绑定特定分类 → 创建商品时关联 | "后端管理页：创建座位模板 → 绑定特定的分类信息 → 创建商品时关联" |
| U5 | **前端判断 item_type 替换模板**：商品详情页加载时判断传入值，如果是 VR 票则替换为专用前端 | "前端商品详情页加载时，判断传入的值，得出这是不是VR演唱会票，如果是就替换成专用前端" |
| U6 | **购买走 ShopXO 原生流程**：最终提交购买按钮走 ShopXO 原生订单流程，不另建独立下单 | "最终提交购买按钮时走 ShopXO 原生订单流程" |
| U7 | **核销端独立页面**：核销是单独的页面，不在购票流程内 | "核销端是另外的独立页面" |
| U8 | **扩展字段注入模式**：插件新增数据表 → 绑定 spec_value（全局可复用）→ 写入 goods.extension_data → 前端按数据渲染自定义 UI。这是通用模式，可套用到票务/实物/套票等所有自定义类型商品 | 通用扩展方法论确认 |

### Q4（新增待确认问题）
> ShopXO spec_value 是「全局可复用」还是「商品级私有」？
> - 全局复用：插件初始化时自动检测/创建 spec，商家直接选
> - 商品级私有：每个商品的 spec_value 独立，插件需要引导用户正确填写
> 影响：插件初始化策略 + 绑定方案

**Q4 的两个选项：**
- Option A：全局可复用（推荐，插件可以一键初始化）
- Option B：商品级私有（需要引导流程）

---

## 二、冲突点列表

### 冲突 1：vr_sessions 独立表 vs spec = 场次

| 维度 | 文档现状 | 用户想法 |
|---|---|---|
| 场次存储 | `vr_sessions` 独立表，存日期/时间/价格覆盖/库存 | ShopXO spec 系统即为场次载体，每个 spec 选项 = 一个场次 |
| 座位布局 | `sxo_goods.venue_data` 存完整 venue + sessions[] + spec_base_id_map | 座位模板（seat_map）绑定分类，通过分类关联到商品 |
| 多场次复用 | vr_sessions 共用 venue.seat_map，多场次同一座位图 | 每个商品 = 单一商品内嵌多个 spec（场次选项） |

**分析**：
- 用户明确说"规格（spec）就是场次"，意味着不需要独立的 vr_sessions 表
- 多个场次 = 商品的多个 spec 选项（如"2026-06-01 19:30"、"2026-06-02 14:00"）
- 座位图/座位布局是商品属性，通过分类绑定关联

**建议方案**：
> 废弃 `vr_sessions` 独立表，改为：
> - 商品的每个 spec 选项 = 一个场次（spec_value = 日期时间）
> - `sxo_goods.venue_data` 仅存座位图配置（seat_map），不存 sessions[]
> - 座位图与分类绑定，商品通过分类继承座位图配置

---

### 冲突 2：venue_data 存完整配置 vs 座位模板绑定分类

| 维度 | 文档现状 | 用户想法 |
|---|---|---|
| 座位配置存储 | `sxo_goods.venue_data` 存完整 venue + seat_map + sessions[] + spec_base_id_map | 座位模板单独管理，绑定到分类，商品通过分类关联 |
| 绑定机制 | 每个商品直接存完整配置 | 商品关联分类 → 分类关联座位模板 → 座位模板提供 seat_map |

**分析**：
- 用户强调"创建座位模板 → 绑定特定的分类信息 → 创建商品时关联"
- 这是解耦思路：座位模板可复用，多个商品（同一场馆不同演出）共用同一模板
- 分类在这里是"座位模板 ID"的载体

**建议方案**：
> 保留座位模板表 `vr_seat_templates`：
> - 存储 seat_map JSON（座位图布局）
> - 绑定到一个特定分类（如 category_id = 场馆分类 ID）
> - 商品创建时选择该分类 → 自动继承 seat_map → 商品的 spec 展示座位选择

---

### 冲突 3：item_type 字段写入机制

| 维度 | 文档现状 | 用户想法 |
|---|---|---|
| item_type 来源 | 文档提到 Goods.php 修改来识别 ticket 类型 | 前端商品详情页加载时判断"传入的值"，识别 VR 票类型 |
| 谁来写 item_type | 未明确（后台手动设置？插件自动？） | 用户认为商品数据中有某个值可以用来判断类型 |

**分析**：
- 用户说"判断传入的值" → 说明商品数据里有某个字段可区分票务商品
- 这个字段可能是：`item_type`、`goods_type`、或者自定义的 `venue_data` 是否存在
- 最简单方案：商品有 `venue_data` 就认为是票务商品，不需要额外字段

**建议方案**：
> `item_type` 不作为独立字段，用 `sxo_goods.venue_data IS NOT NULL` 作为票务商品标识：
> - 创建商品时勾选"票务商品"或选择座位模板 → 插件写入 `venue_data`
> - 前端判断 `$goods.venue_data` 是否有值 → 有值则加载票务专用前端
> - 无需修改 ShopXO 核心或新增字段

---

### 冲突 4：Goods.php 修改 vs 纯 Hook 方案

| 维度 | 文档现状 | 用户想法 |
|---|---|---|
| 模板替换方式 | 文档记录了 Goods.php Index() 加判断的方案（MIT 允许范围内最小改动） | 用户说"前端商品详情页加载时，判断传入的值，得出这是不是VR演唱会票，如果是就替换成专用前端" |
| 是否改核心文件 | 文档认为改 1 行可接受，保留为备案 | 用户想法中没有提到需要改核心 PHP 文件 |

**分析**：
- 用户的前端判断逻辑可以完全在 Hook + Vue 前端实现
- 不需要修改 Goods.php

**建议方案**：
> 废弃 Goods.php 修改方案，完全用 Hook：
> - `plugins_view_goods_detail_base_sku_top` 注入票务选座 UI（覆盖原有规格选择区）
> - 前端 Vue 判断 `goods.venue_data` 是否有值 → 决定是否跳转到票务页面
> - 保留 Goods.php 方案作为备案（如 Hook 注入不够时）

---

### 冲突 5：vr_venues 场馆表是否还需要？

| 维度 | 文档现状 | 用户想法 |
|---|---|---|
| 场馆概念 | `vr_venues` 表存场馆名称/地址/座位图，多 session 共用一个 venue | 用户说"每一个商品就是一个物理意义上的电影院或者演出地址" |
| 粒度 | venue 是复用层，session 是时间层 | 商品 = 场馆 + 演出，座位模板是绑定到分类的 |

**分析**：
- 用户思路里"商品 = 场馆的一个演出"，不需要跨商品的 venue 复用
- 座位模板（seat_map）是绑定分类的，不是绑定 venue 的
- `vr_venues` 表在用户思路里没有明确位置

**建议方案**：
> 废弃 `vr_venues` 表，改用 `vr_seat_templates`（座位模板）表：
> - 模板存储 seat_map JSON + 分类绑定
> - 商品通过分类关联模板
> - 不需要独立的场馆表（场馆名称可存商品信息里）

---

## 三、确认方案（无争议部分）

以下结论可以直接落地：

### 3.1 spec = 场次（已确认）

每个 ShopXO spec 选项 = 一个演出场次（如"2026-06-01 晚场"、"2026-06-02 下午场"）。

- 不需要 `vr_sessions` 表
- 商品的多个 spec 值 = 多个场次
- spec_base_id_map 绑定 seat_id → spec_base_id → 购买流程

### 3.2 座位模板绑定分类（已确认）

座位模板 `vr_seat_templates` 表：
```sql
CREATE TABLE vr_seat_templates (
  id           BIGINT PRIMARY KEY AUTO_INCREMENT,
  name         VARCHAR(180) NOT NULL COMMENT '模板名称（如：鸟巢-A区）',
  category_id  BIGINT UNSIGNED NOT NULL COMMENT '绑定的分类ID',
  seat_map     LONGTEXT NOT NULL COMMENT '座位地图JSON',
  status       TINYINT UNSIGNED DEFAULT 1,
  add_time     INT UNSIGNED DEFAULT 0,
  upd_time     INT UNSIGNED DEFAULT 0,
  UNIQUE KEY category_id (category_id)
);
```

绑定流程：
1. 后台创建座位模板 → 选择绑定分类（如"VR演唱会-A区"）
2. 创建商品 → 选择该分类
3. 插件自动将模板 seat_map 写入商品 `venue_data`

### 3.3 venue_data 精简为仅座位配置

`sxo_goods.venue_data` JSON 结构简化：
```json
{
  "seat_map": { /* 座位图配置 */ },
  "spec_base_id_map": { /* seat_id → spec_base_id */ }
}
```

sessions 信息不再存在 venue_data 里，由 ShopXO spec 系统提供。

### 3.4 item_type 判断用 venue_data 非空

- 不新增 `item_type` 字段
- 判断逻辑：`!empty($goods['venue_data'])` → 票务商品
- 前端 Vue 同理：`goods.venue_data` 是否有值

### 3.5 完全通过 Hook 实现，不改 Goods.php

- `plugins_view_goods_detail_base_sku_top` 注入票务选座 UI
- 保留 Goods.php 修改方案为备案（如 Hook 注入范围不够时启用）

### 3.6 核销端独立页面

- B 端核销页：`pages/plugins/vr-ticket-verify/check/check.vue`（Fork 自 realstore/check.vue）
- 不在购票主流程内

---

## 四、待确认问题（需要 Council 判断）

以下问题无法从对话记录中确认解决方案，打上 `pending-council` 标签：

### Q1: 座位模板与分类的绑定粒度

**背景**：用户说"绑定特定的分类信息"，但一个演出可能有多个座位区（A区/B区/C区），每个区是不同的座位图。

**选项**：
- A：每个分类 = 一个座位区（多个分类绑定同一个演出）
- B：一个分类 = 一个完整场馆（座位图内分区）
- C：一个商品可以绑定多个座位模板

**待验证**：用户的"分类"是指 ShopXO 商品分类，还是自定义的"场馆座位分类"？需要明确。

### Q2: spec_base_id_map 的生成时机

**背景**：spec = 场次时，座位选择是跨 spec（场次）的，还是每个 spec（场次）有独立的座位？

**选项**：
- A：每个 spec（场次）有独立的座位配置（不同日期同一座位区）
- B：所有 spec 共用同一座位配置（日期不同，座位相同）

**待验证**：用户说"只要用户想要买某一个场馆的演唱会，他就在这一个商品里面操作就行" → 倾向于 B（同一座位图，日期不同）。

### Q4: spec_value 复用粒度 — 全局还是商品级？

**背景**：用户在确认通用扩展方法论时提出，spec_value 的复用粒度直接影响插件初始化策略。

**选项**：
- Option A：全局可复用（推荐，插件可以一键初始化）— 插件初始化时自动检测/创建 spec_value，商家创建商品时直接选
- Option B：商品级私有（需要引导流程）— 每个商品的 spec_value 独立，插件需要引导用户正确填写

**影响**：插件初始化策略 + 绑定方案。

---

### Q3: 观演人信息的存储位置

**背景**：用户说"走 ShopXO 原生订单流程"，但票务需要观演人信息。

**选项**：
- A：观演人信息存 `sxo_order.extension_data`（ShopXO 扩展字段）
- B：观演人信息存 `vr_tickets` 表
- C：观演人信息作为 spec 选项的一部分

**待验证**：ShopXO 原生订单的 extension_data 是否足够存观演人信息？是否有更优雅的方式？

---

## 五、ARCHITECTURE.md 更新计划

根据以上对齐结论，ARCHITECTURE.md 需要做以下更新：

1. **删除 vr_sessions 表**，改为 spec = 场次
2. **删除 vr_venues 表**，改为 vr_seat_templates 表（座位模板绑定分类）
3. **简化 venue_data JSON 结构**，只保留 seat_map + spec_base_id_map
4. **明确 item_type 判断机制**：venue_data 非空
5. **删除 Goods.php 修改方案**，改为纯 Hook 方案
6. **更新购票流程**，反映 spec = 场次的设计
7. **更新目录结构**，反映 vr_seat_templates 替代 vr_venues/vr_sessions
