# Agent 执行 Prompt — VR 演唱会票务小程序 Phase 2

## 前提条件（必读）

你正在帮助开发一个 **ShopXO 票务插件（vr_ticket）**。

- 仓库：`http://xmhome.ow-my.com:3000/sileya-ai/vr-shopxo-plugin`
- 本地路径：`/Users/bigemon/WorkSpace/vr-shopxo-plugin`
- ShopXO 容器：localhost:10000（Web）/ localhost:10001（MySQL）/ localhost:9000（PHP-FPM）
- DB 用户：root / shopxo_root_2024，表前缀：`vrt_`

**完整文档路径**：`/Users/bigemon/WorkSpace/vr-shopxo-plugin/docs/FULL_PLAN.md`

> ⚠️ 在做任何事情之前，**必须先读 `FULL_PLAN.md`**，理解完整上下文后再开始。

> 📋 **AntiGravity 已进行会话进度**: `SESSION_REPORT_20260421_PHASE2_FIX.md` - 记录AntiGravity 推进的所有工作。涵盖经验、教训与改动。
---

## 项目背景（一句话）

VR 演唱会票务微信小程序插件。用户选座 → 填观演人 → 微信支付 → 电子票二维码 → 现场扫码核销。

---

## 当前优先级

### P0（阻塞一切）

**Issue 1 修复**：购买提交流程完全失效，有三层叠加问题。

**顺序**：

1. **后端**：修改 `SeatSkuService::GetGoodsViewData()`，新增 `seatSpecMap` 生成逻辑
   - 查询 `GoodsSpecBase` + `GoodsSpecValue` + `GoodsSpecBase.extends.seat_key`
   - 输出 `seatSpecMap[seatKey] = {spec_base_id, price, inventory, spec: [...]}`
   - 完整逻辑见 `FULL_PLAN.md` 第 4.3 节

2. **后端**：修改 `Goods.php`，在 `MyViewAssign` 中加入 `seatSpecMap`

3. **前端**：修改 `ticket_detail.html`，用 `seatSpecMap` 替代当前错误的 `specBaseIdMap`

4. **前端**：修复 `submit()` 函数
   - 改 GET → POST 隐藏表单（**不是** `location.href`）
   - spec 必须是**完整的 4 维数组**：`[{type:'$vr-场馆',value:'...'},{type:'$vr-分区',value:'...'},{type:'$vr-座位号',value:'...'},{type:'$vr-场次',value:'...'}]`
   - **不是** `{type:'$vr-座位号', value: seatKey}` — 这是错的
   - spec 从 `seatSpecMap[seatKey].spec` 读取，**不要自己构造**
   - `extension_data` 必须嵌套在 `order_base` 内，**不是平铺在第一层**
   - 直接 `JSON.stringify`，**不需要 base64**

### P1

5. **前端**：`ticket_detail.html` 新增场次/场馆/分区选择器 UI + `filterSeatMap()` 联动过滤
6. **前端**：缩放时舞台跟随（zoom wrapper 方案）
7. **前端**：`loadSoldSeats()` ✅ 已实现（seatSpecMap.inventory，无需后端 API）

### P2

8. 商品详情图片展示（确认需求）
9. `GetGoodsViewData()` 多场次返回数组而非 `validConfigs[0]`
10. `onOrderPaid` spec 匹配审计（未来关注，不阻塞）

---

## 绝对禁止事项

- ❌ **不要**用 `location.href` 传递购买参数（ShopXO 只在 POST 时存储数据）
- ❌ **不要**把 spec 格式写成 `{type:'$vr-座位号', value: 'room_001_A_3'}` — 这是错的
- ❌ **不要**把 `extension_data` 平铺在 `goods_data` 第一层 — 必须嵌套在 `order_base` 里
- ❌ **不要**在 submit() 里对 `goods_data` 做 base64 — 直接 `JSON.stringify` 即可
- ❌ **不要**修改 `BuyService.php` 的核心逻辑 — 所有修复都在前端和插件后端做
- ❌ **不要**新建数据库表来存观演人信息 — 用 ShopXO 原生的 `order.extension_data`

---

## 常见错误警告

### spec 数组格式（最高频错误）

```
错误：
spec: [{type:'$vr-座位号', value: 'room_001_A_3'}]

正确（完整4维）：
spec: [
    {type:'$vr-场馆',   value: 'VR 演唱会馆'},
    {type:'$vr-分区',   value: 'VR 演唱会馆-1号演播厅-VIP区'},
    {type:'$vr-座位号', value: 'VR 演唱会馆-1号演播厅-VIP区-A-1排3座'},
    {type:'$vr-场次',   value: '15:00-16:59'}
]
```

### order_base 嵌套（第二高频错误）

```
错误：
{
    goods_id: 118,
    spec: [...],
    extension_data: {...}    ← 平铺！错！
}

正确：
{
    goods_id: 118,
    spec: [...],
    order_base: {            ← 必须嵌套在 order_base 内！
        extension_data: {...}
    }
}
```

### goods_data 编码（第三高频错误）

```
错误：
input.value = btoa(JSON.stringify(goodsDataList))  ← 不需要 base64！

正确：
input.value = JSON.stringify(goodsDataList)  ← 直接 JSON 字符串
```

ShopXO `BuyService::BuyGoods` 第60行判断 `!is_array($_POST['goods_data'])` 才会 decode，直接 POST JSON 字符串即可。

---

## 快速参考

| 我需要知道 | 去哪里找 |
|-----------|---------|
| 完整上下文 + 修复方案 | `FULL_PLAN.md` |
| 原始 goods.vr_goods_config 数据 | `FULL_PLAN.md` 第二章 |
| seatSpecMap 正确结构 | `FULL_PLAN.md` 4.3 节 |
| submit() 正确实现 | `FULL_PLAN.md` 第六章 |
| Buy 链路数据流 | `FULL_PLAN.md` 6.3 节 |
| 关键代码行号索引 | `FULL_PLAN.md` 第八章 |
| spec 选择器设计 | `FULL_PLAN.md` 第五章 |
| 座位图渲染方法 | `FULL_PLAN.md` 5.3 节 |

---

## 工作流程

1. **读** `FULL_PLAN.md` 全文（必读）
2. **确认**你理解了 4 维 spec 结构 + seatSpecMap 映射关系
3. **按优先级顺序**处理 P0 → P1 → P2
4. **每完成一个模块**，在本地测试验证后再继续
5. **commit 前**：`git status` 检查暂存区，不提交 binary（图片/压缩包），不在本仓库 push 到远程

---

## commit 规范

```
feat(Phase2): [模块名] [简短描述]

示例：
feat(Phase2): SeatSkuService GetGoodsViewData 新增 seatSpecMap 生成
feat(Phase2): ticket_detail.html 修复 submit() POST + 4维spec数组
```

**注意**：本仓库是 fork，不直接 push 到 upstream。只 commit 到本地，汇报给大头后由他处理上游合并。
