442 lines
17 KiB
Markdown
442 lines
17 KiB
Markdown
# VR票务详情页面 UniApp 移植规划文档
|
||
|
||
> 创建时间:2026-05-13
|
||
> 状态:**Phase 3 导航优化完成(防闪烁/缓存预检查)**
|
||
|
||
---
|
||
|
||
## 📌 背景与目标
|
||
|
||
### 背景
|
||
- 后端 VR Ticket 插件 (`vr_ticket`) 已实现票务商品详情页模板 `ticket_detail.html`
|
||
- 前端参考项目 [show-start](file:///Users/bigemon/WorkSpace/vr-shopxo-uniapp/references/show-start/src/App.vue) 提供了高质量的 UI 设计
|
||
- 需要将参考项目的 UI 移植到 UniApp 环境中,并整合票务商品的4维选择逻辑
|
||
|
||
### 用户需求
|
||
1. **保持 show-start 的 popup 交互模式** 作为购票弹窗基础
|
||
2. **点击"立即购票"按钮** 后弹出购票弹窗
|
||
3. 弹窗内容包含:场次选择、场馆/演播室/分区选择、"选座"按钮
|
||
4. **选座功能**:独立的全屏遮罩座位选择器,选完后返回已选座位 tags
|
||
|
||
---
|
||
|
||
## 📋 数据结构规范(Phase 2 核心)
|
||
|
||
### VR 票务扩展字段
|
||
从后端 API 返回的商品扩展数据中,票务商品会包含以下关键字段:
|
||
|
||
```typescript
|
||
interface VRTicketGoods {
|
||
id: number;
|
||
title: string;
|
||
images: string[];
|
||
is_vr_ticket: 1; // 票务商品标识
|
||
|
||
// VR 票务扩展数据(来自 vr_config 或 extension_data)
|
||
vr_config?: {
|
||
// 场次规格列表(从 goods_spec_data 解析)
|
||
spec_list?: Array<{
|
||
spec_name: string; // 场次名称,如 "2026-06-01 14:00"
|
||
price: number; // 价格
|
||
inventory: number; // 库存
|
||
}>;
|
||
|
||
// 座位规格映射(从 seat_spec_map 解析)
|
||
seat_spec_map?: Record<string, {
|
||
spec: Array<{ type: string; value: string }>; // 4维规格
|
||
price: number;
|
||
inventory: number;
|
||
section: { name: string; color: string };
|
||
}>;
|
||
|
||
// 座位模板(座位图数据)
|
||
seat_template?: {
|
||
venue: { name: string; address: string; location: { lng: string; lat: string } };
|
||
rooms: Array<{
|
||
id: string;
|
||
name: string;
|
||
map: string[]; // 座位矩阵,如 ["AAAAA", "AAB__AA"]
|
||
sections: Array<{ char: string; name: string; price: number; color: string }>;
|
||
}>;
|
||
};
|
||
};
|
||
}
|
||
```
|
||
|
||
### 4维规格体系
|
||
票务商品的选座流程采用 **4维规格级联选择**:
|
||
|
||
| 维度 | 字段名 | 说明 | 示例 |
|
||
|------|--------|------|------|
|
||
| 1 | `$vr-场次` | 演出场次/时间 | "2026-06-01 14:00" |
|
||
| 2 | `$vr-场馆` | 演出场馆 | "北京凯迪拉克中心" |
|
||
| 3 | `$vr-演播室` | 室内演出厅 | "主要展厅" |
|
||
| 4 | `$vr-分区` | 座位分区 | "VIP区"、"普通区" |
|
||
|
||
**选择级联逻辑**:选择场次 → 筛选可用场馆 → 选择场馆 → 筛选可用演播室 → 选择演播室 → 筛选可用分区 → 选择分区 → 加载座位图
|
||
|
||
---
|
||
|
||
## 📐 UI/UX 设计概览
|
||
|
||
### 页面结构
|
||
```
|
||
┌─────────────────────────────────────┐
|
||
│ Header Banner (海报 + 标题 + 收藏) │
|
||
├─────────────────────────────────────┤
|
||
│ Location Card (最近场馆) │
|
||
├─────────────────────────────────────┤
|
||
│ Service Tags (服务说明) │
|
||
├─────────────────────────────────────┤
|
||
│ 演出详情 Section │
|
||
├─────────────────────────────────────┤
|
||
│ 购票须知 Section │
|
||
├─────────────────────────────────────┤
|
||
│ 观演须知 Section │
|
||
├─────────────────────────────────────┤
|
||
│ Bottom Bar (客服 + 立即购票) │ ← Fixed 底部
|
||
└─────────────────────────────────────┘
|
||
```
|
||
|
||
### 购票弹窗 Popup 交互(核心功能区)
|
||
```
|
||
┌─────────────────────────────────────┐
|
||
│ [场次选择 - 横向卡片滚动] │ ← vr-session-grid
|
||
├─────────────────────────────────────┤
|
||
│ [选择场馆] │ ← vr-booking-block
|
||
├─────────────────────────────────────┤
|
||
│ [选择演播室] → [选择分区] │ ← 级联选择
|
||
├─────────────────────────────────────┤
|
||
│ [选座] 按钮 ← 打开座位选择器 │
|
||
│ │
|
||
│ 未选座时:尚未选择 [立刻选座] │
|
||
│ 已选座时: │
|
||
│ ┌─────┐ ┌─────┐ ┌─────┐ │
|
||
│ │ A1 │ │ A2 │ │ A3 │ │ ← 已选座位 tags
|
||
│ └─────┘ └─────┘ └─────┘ │
|
||
│ 【重新选座】 │
|
||
├─────────────────────────────────────┤
|
||
│ 合计: ¥888 [确认购票] │ ← 底部购买栏
|
||
└─────────────────────────────────────┘
|
||
```
|
||
|
||
### 座位选择器(全屏遮罩)
|
||
```
|
||
┌─────────────────────────────────────┐
|
||
│ ← 返回 选择座位 [已完成 3 座] │
|
||
├─────────────────────────────────────┤
|
||
│ 🎵 舞 台 │ ← 舞台指示
|
||
├─────────────────────────────────────┤
|
||
│ A ■ ■ ■ ■ ■ │ ← 座位行(A排)
|
||
│ B ■ ■ ■ ■ ■ ■ ■ │ ← 可用座位:■ 点击选中
|
||
│ C ■ _ _ ■ ■ ■ │ ← 过道:_
|
||
│ D ■ ■ ■ ■ ■ │ ← 已售:灰色
|
||
├─────────────────────────────────────┤
|
||
│ 图例: [VIP] [普通] [已售] │
|
||
└─────────────────────────────────────┘
|
||
```
|
||
|
||
### 座位状态定义
|
||
- **可用座位**:可点击选择,带分区颜色
|
||
- **已选座位**:高亮边框,数字标识
|
||
- **已售座位**:灰色,不可点击
|
||
- **过道/空位**:占位符,不渲染
|
||
|
||
---
|
||
|
||
## 🔄 阶段进展记录
|
||
|
||
### Phase 1: 基础 UI 移植 ✅ 已完成
|
||
- [x] 在 `pages.json` 中注册新页面路由
|
||
- [x] 创建 `pages/goods-vr-ticket/` 目录
|
||
- [x] 搬运 `App.vue` 内容到 `goods-vr-ticket.vue`
|
||
- [x] 适配 UniApp 语法(scrollable、navigation 等)
|
||
- [x] 替换内联 SVG → iconfont 组件(兼容<E585BC><E5AEB9>信小程序)
|
||
- [x] 添加 popup 容器左右留白(padding: 16px)
|
||
- [x] 修复 popup-content 溢出问题(overflow-x, word-break)
|
||
|
||
### Phase 2: 购票弹窗与4维选择(开发中)
|
||
- [x] 购票弹窗基础结构(当前 popupType='buy')
|
||
- [ ] 接入商品 API 数据(vr_config 解析)
|
||
- [ ] 场次选择器实现(横向滚动卡片)
|
||
- [ ] 场馆选择器实现
|
||
- [ ] 演播室/分区级联选择
|
||
- [ ] 座位选择器组件开发
|
||
- [ ] 已选座位 UI 展示
|
||
- [ ] 底部总价计算
|
||
|
||
### Phase 3: 完整购票流程(待开发)
|
||
- [ ] 观演人信息表单(每座必填)
|
||
- [ ] 订单提交 API 集成
|
||
- [ ] 跳转支付流程
|
||
|
||
### Phase 4: 优化与测试
|
||
- [ ] 滚动穿透处理(catchtouchmove)
|
||
- [ ] 真机/小程序测试
|
||
- [ ] 性能优化
|
||
|
||
---
|
||
|
||
## 📝 待办事项
|
||
|
||
### ✅ 已完成
|
||
- [x] 在 `pages.json` 中注册新页面路由
|
||
- [x] 创建 `pages/goods-vr-ticket/` 目录
|
||
- [x] 搬运 `App.vue` 内容到 `goods-vr-ticket.vue`
|
||
- [x] 适配 UniApp 语法(scrollable、navigation 等)
|
||
- [x] 替换内联 SVG → iconfont 组件(兼容微信小程序)
|
||
- [x] 添加 popup 容器左右留白(padding: 16px)
|
||
- [x] 修复 popup-content 溢出问题(overflow-x, word-break)
|
||
- [x] 购票弹窗基础框架(popupType='buy' 判断)
|
||
|
||
### ⏳ 后续待办
|
||
- [x] 在 `goods-detail.vue` 中添加跳转判断逻辑
|
||
- [ ] 解析商品数据中的 vr_config 等扩展字段
|
||
- [ ] 实现场次选择器(横向滚动卡片)
|
||
- [ ] 实现场馆选择器(场次筛选后可用)
|
||
- [ ] 实现演播室→分区级联选择
|
||
- [ ] 实现选座按钮与座位选择器(全屏遮罩)
|
||
- [ ] 实现已选座位 tags 展示
|
||
- [ ] 实现重新选座功能
|
||
- [ ] 连接后端 BuyService API 获取动态票务数据
|
||
- [ ] 实现底部购买栏联动(已选座数、总价)
|
||
- [ ] 添加 popup 滚动事件处理(:catchtouchmove)
|
||
- [ ] 观演人信息表单(姓名/手机/身份证)
|
||
- [ ] 订单提交入口
|
||
- [ ] 测试页面在真机/小程序环境运行
|
||
|
||
---
|
||
|
||
## 🔌 API 接口规范
|
||
|
||
### 商品详情接口(扩展字段)
|
||
请求商品详情时,后端返回 `vr_config` 扩展数据:
|
||
|
||
```javascript
|
||
// GET /api/goods/detail?id=xxx
|
||
{
|
||
"code": 0,
|
||
"data": {
|
||
"id": 100,
|
||
"title": "王一浩「To U」巡演北京收官站",
|
||
"images": "[\"xxx.jpg\"]",
|
||
"is_vr_ticket": 1,
|
||
// VR 票务扩展
|
||
"vr_config": {
|
||
"goods_spec_data": [
|
||
{ "spec_name": "2026-06-01 14:00", "price": 580, "inventory": 100 },
|
||
{ "spec_name": "2026-06-01 20:00", "price": 680, "inventory": 50 }
|
||
],
|
||
"seat_spec_map": {
|
||
"room_001_A_1": {
|
||
"spec": [
|
||
{ "type": "$vr-场次", "value": "2026-06-01 14:00" },
|
||
{ "type": "$vr-场馆", "value": "北京凯迪拉克中心" },
|
||
{ "type": "$vr-演播室", "value": "主要展厅" },
|
||
{ "type": "$vr-分区", "value": "VIP区" }
|
||
],
|
||
"price": 580,
|
||
"inventory": 1,
|
||
"section": { "name": "VIP区", "color": "#ff4d4f" }
|
||
}
|
||
},
|
||
"vr_seat_template": {
|
||
"venue": { "name": "北京凯迪拉克中心", "address": "...", "location": { "lng": "116.4", "lat": "39.9" } },
|
||
"rooms": [...]
|
||
}
|
||
}
|
||
}
|
||
}
|
||
```
|
||
|
||
### 订单提交接口
|
||
```javascript
|
||
// POST /api/buy/add
|
||
{
|
||
"goods_data": [
|
||
{
|
||
"goods_id": 100,
|
||
"spec": [...], // 4维规格数组
|
||
"stock": 1,
|
||
"order_base": {
|
||
"extension_data": {
|
||
"attendee": {
|
||
"real_name": "张三",
|
||
"phone": "13800138000",
|
||
"id_card": "110101199001011234"
|
||
}
|
||
}
|
||
}
|
||
}
|
||
],
|
||
"buy_type": "goods",
|
||
"address_id": "0",
|
||
"site_model": "2"
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 🛠️ 技术实现要点
|
||
|
||
### 1. 4维规格筛选逻辑
|
||
参考 `ticket_detail.html` 中的 `filterSeats` 方法:
|
||
|
||
```javascript
|
||
// 根据当前选择的4维过滤可用座位
|
||
filterSeats: function() {
|
||
var matchSession = this.currentSession != null;
|
||
var matchVenue = this.currentVenue != null;
|
||
var matchRoom = this.currentRoom != null;
|
||
var matchSection = this.currentSection != null;
|
||
|
||
// 遍历所有座位,检查是否满足当前选择条件
|
||
for (var i = 0; i < seatInfo.spec.length; i++) {
|
||
if (seatInfo.spec[i].type === '$vr-场次' && seatInfo.spec[i].value === this.currentSession) {
|
||
matchSession = true;
|
||
}
|
||
// ... 同理其他维度
|
||
}
|
||
}
|
||
```
|
||
|
||
### 2. 座位状态管理
|
||
- `selectedSeats[]`:已选座位数组
|
||
- `soldSeats{}`:已售座位映射
|
||
- 切换场次时清空已选座位
|
||
|
||
### 3. 级联选择
|
||
- 选择「场次」后 → 重置「场馆/演播室/分区」,重新计算可选场馆
|
||
- 选择「场馆」后 → 筛选出<E98089><E587BA>场馆下的演播室
|
||
- 选择「演播室」后 → 筛选出该演播室下的分区,显示分区选择器
|
||
|
||
### 4. 座位渲染
|
||
座位图使用字符矩阵渲染:
|
||
- `A`/`B`/...:座位字符
|
||
- `_`:过道/空位
|
||
|
||
---
|
||
|
||
## 📦 文件结构
|
||
|
||
```
|
||
pages/goods-vr-ticket/
|
||
├── goods-vr-ticket.vue # 主页面(已移植 Phase 1)
|
||
├── goods-vr-ticket.css # 独立样式(可选)
|
||
└── components/
|
||
├── vr-session-select/ # 场次选择器组件
|
||
├── vr-venue-select/ # 场馆选择器组件
|
||
├── vr-seat-selector/ # 座位选择器(全屏遮罩)
|
||
└── vr-attendee-form/ # 观演人表单
|
||
```
|
||
|
||
---
|
||
|
||
## 🔗 相关参考
|
||
|
||
| 文件 | 说明 |
|
||
|------|------|
|
||
| [references/show-start/src/App.vue](file:///Users/bigemon/WorkSpace/vr-shopxo-uniapp/references/show-start/src/App.vue) | 源 UI 参考(Vue 2) |
|
||
| [pages/goods-detail/goods-detail.vue](file:///Users/bigemon/WorkSpace/vr-shopxo-uniapp/pages/goods-detail/goods-detail.vue) | 商品详情页(跳转入口) |
|
||
| [vr_ticket/ticket_detail.html](file:///Users/bigemon/WorkSpace/vr-shopxo-plugin/shopxo/app/plugins/vr_ticket/view/goods/ticket_detail.html) | 后端票务模板参考(4维选择+座位图) |
|
||
| [pages.json](file:///Users/bigemon/WorkSpace/vr-shopxo-uniapp/pages.json) | 页面路由配置 |
|
||
|
||
---
|
||
|
||
## 🎯 关键文件
|
||
|
||
| 文件 | 状态 | 说明 |
|
||
|------|------|------|
|
||
| pages/goods-vr-ticket/goods-vr-ticket.vue | ✅ 已移植 | 主页面(Phase 1 完成) |
|
||
| pages/goods-detail/goods-detail.vue | ⏳ 待修改 | 添加 is_vr_ticket 跳转判断 |
|
||
| components/iconfont/iconfont.vue | ✅ 已加固 | iconfont 组件 |
|
||
|
||
---
|
||
|
||
> ⚠️ **注意**:当前 Phase 2 正在开发中,核心为 4维规格选择器 + 座位选择器。Phase 3 将实现观演人表单和订单提交。座时:尚未选择 [立刻选座] │
|
||
│ 已选座时: │
|
||
│ [A区-2排-3号] [A区-2排-4号] │
|
||
│ 【重新选座】 │
|
||
├─────────────────────────────────────┤
|
||
│ [确认购票] │
|
||
└─────────────────────────────────────┘
|
||
|
||
点击[选座] → 打开座位选择器(全屏遮罩)
|
||
```
|
||
|
||
---
|
||
|
||
## 🗂️ 文件结构(Phase 1 完成后)
|
||
|
||
```
|
||
pages/goods-vr-ticket/
|
||
├── goods-vr-ticket.vue # 主页面(移植自 App.vue)
|
||
└── goods-vr-ticket.css # 独立样式文件(可选)
|
||
```
|
||
|
||
---
|
||
|
||
## 📝 待办事项
|
||
|
||
### ✅ 已完成
|
||
- [x] 在 `pages.json` 中注册新页面路由
|
||
- [x] 创建 `pages/goods-vr-ticket/` 目录
|
||
- [x] 搬运 `App.vue` 内容到 `goods-vr-ticket.vue`
|
||
- [x] 适配 UniApp 语法(scrollable、navigation 等)
|
||
- [x] 替换内联 SVG → iconfont 组件(兼容微信小程序)
|
||
- [x] 添加 popup 容器左右留白(padding: 16px)
|
||
- [x] 修复 popup-content 溢出问题(overflow-x, word-break)
|
||
|
||
### ⏳ 后续待办
|
||
- [ ] 在 `goods-detail.vue` 中添加跳转判断逻辑
|
||
- [ ] 对 商品数据里的vr_config 等数据进行解析,
|
||
- [ ] 实现购票弹窗 Popup 交互,移植老的4 维规格选择到新的购票弹窗 Popup 中。
|
||
- [ ] 实现购票弹窗内的选座逻辑
|
||
- [ ] 连接后端 BuyService API(动态票务数据)
|
||
- [ ] 优化 popup 滚动事件处理(:catchtouchmove)
|
||
- [ ] 测试页面在真机/小程序环境运行
|
||
|
||
---
|
||
|
||
## 🔄 阶段进展记录
|
||
|
||
### 2026-05-13 样式迁移完成
|
||
- ✅ 移除 inline SVG,改用 iconfont 组件
|
||
- ✅ map-icon 容器添加边框
|
||
- ✅ venue-popup-info 添加地址图标(icon-location)
|
||
- ✅ popup-container 添加 padding: 0 16px
|
||
- ✅ popup-content 修复溢出(word-break, box-sizing)
|
||
|
||
### 2026-05-14 导航优化完成
|
||
- ✅ goods-detail.vue 添加白色遮罩(初始覆盖,200ms后渐变消失)
|
||
- ✅ 添加缓存预检查(快速判断VR票务,无需等待API)
|
||
- ✅ goods-vr-ticket.vue 加载遮罩 + pageShow 显示控制
|
||
- ✅ 修复返回导航:智能判断页面栈,无历史则跳转首页
|
||
- ✅ goods-detail 使用 redirectTo 替代 navigateTo,避免循环
|
||
|
||
### 关键文件
|
||
| 文件 | 状态 |
|
||
|------|------|
|
||
| pages/goods-vr-ticket/goods-vr-ticket.vue | ✅ 已移植 |
|
||
| pages/goods-vr-ticket/goods-vr-ticket.css | ✅ 已移植 |
|
||
| pages/goods-vr-ticket/components/ticket-header/index.vue | ✅ 已移植 |
|
||
| pages/goods-vr-ticket/components/venue-card/index.vue | ✅ 已移植 |
|
||
| pages/goods-vr-ticket/components/ticket-popup/index.vue | ✅ 已移植 |
|
||
| components/iconfont/iconfont.vue | ✅ 已加固尺寸 |
|
||
| pages/goods-detail/goods-detail.vue | ✅ 已加固导航 |
|
||
|
||
---
|
||
|
||
## 🔗 相关参考
|
||
|
||
| 文件 | 说明 |
|
||
|------|------|
|
||
| [references/show-start/src/App.vue](file:///Users/bigemon/WorkSpace/vr-shopxo-uniapp/references/show-start/src/App.vue) | 源 UI 参考(Vue 2) |
|
||
| [pages/goods-detail/goods-detail.vue](file:///Users/bigemon/WorkSpace/vr-shopxo-uniapp/pages/goods-detail/goods-detail.vue) | 商品详情页(跳转入口) |
|
||
| [vr_ticket/ticket_detail.html](file:///Users/bigemon/WorkSpace/vr-shopxo-plugin/shopxo/app/plugins/vr_ticket/view/goods/ticket_detail.html) | 后端票务模板参考 |
|
||
| [pages.json](file:///Users/bigemon/WorkSpace/vr-shopxo-uniapp/pages.json) | 页面路由配置 |
|
||
|
||
---
|
||
|
||
> ⚠️ **注意**:当前为 Phase 1 规划,仅实现初步移植和测试环境搭建。后续 Phase 2-4 将逐步实现座位选择器、4维规格选择、完整购票流程等高级功能。
|