vr-shopxo-plugin/docs/council-research-output.md

264 lines
14 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

# ShopXO 酷炫前端模板实现方案调研报告
> 调研日期2026-04-20
> 状态:**Round 3 收敛版本**
> 参与FrontendDev (Q1/Q4)、BackendArchitect (Q2)、ProductManager (Q3)、FirstPrinciples (Q4 集成)
---
## Q2 结论:单订单多 SKU 支持
### 核心答案
**ShopXO 订单模型技术上支持同一商品多规格(多 SKU出现在同一订单中**,但现有 vr_ticket 模板的 `submit()` 只传单行,完整多座位下单需要做两件事:① 让前端传多行 `goods_data`,② 阻止 `OrderSplitService` 按 warehouse 拆单。
### 证据来源
| 文件 | 关键代码 | 说明 |
|------|---------|------|
| `BuyService.php:86` | `foreach($params['goods_data'] as $v)` | 循环处理每个商品项,每项独立 spec_base_id |
| `BuyService.php:423-435` | `extension_data` JSON 序列化 | 每行 item 支持挂载座位/观演人扩展数据 |
| `BuyService.php:101` | `md5(goods_id + spec implode)` | 内部用 goods_id+spec 组合生成唯一行 ID |
| `OrderSplitService.php:52-53` | `GoodsWarehouseAggregate()` | **拆单触发点**:按仓库分组,多 SKU 同一仓库则合并 |
| `OrderSplitService.php:289-310` | 按 spec MD5 找 spec_base_id | spec_base_id 已可不同(座位级 SKU |
| `ticket_detail.html:413-436` | `goodsParamsList.map()` | Plan A 代码已写好,但 URL 只传第一行bug |
### 最小可行方案Multi-Seat Now
**改动点仅 3 处,全在 ticket_detail.html不碰 ShopXO 核心:**
```
ticket_detail.html submit() 函数
BEFORE: location.href = checkoutUrl + '&goods_params=' + encodeURIComponent(goodsParams)
AFTER: goodsParamsList 整体 base64 编码,拆分成多条 goods_data 逐条 POST 到 CartSave
然后跳转到合并支付流程ShopXO 购物车天然支持多商品同单)
```
**为什么走购物车路线更稳:**
- `BuyCart``BuyTypeGoodsList` → 直接调用 `BuyGoods`,完美支持多 `goods_data`
- 不需要hook `OrderSplitService`,购物车结算路径不触发按仓库拆单(只按商品拆)
- 核销逻辑不受影响:支付成功后 `plugins_service_order_pay_success_handle_end` 钩子正常触发
### 理想方案Multi-Seat Proper
在插件中挂载 `plugins_service_buy_group_goods_handle` 钩子,拦截 `OrderSplitService`,将同一 goods_id + 不同 spec_base_id 的多行合并进同一个 order_base
```
plugins_service_buy_group_goods_handle:
- 按 goods_id 聚合,而非按 warehouse_id
- 每个 goods_id 只生成一条 order_basegoods_items 内嵌多个 spec_base_id 不同的行
- extension_data 按座位索引扁平化存储
```
**ShopXO 官方立场**:这是非标准用法,建议走购物车路线。
### 最大风险点
1. **OrderSplitService 按仓库拆单** — 如果场次商品和周边商品挂在不同仓库,多座位票务订单会被拆成多个子单。用户会收到多笔支付通知,体验割裂。→ **最小方案走购物车绕过此风险**。
2. **座位级 SKU 未在 ShopXO 后台创建** — `specBaseIdMap` 依赖数据库中已存在的 `sxo_goods_spec_base` 记录。如果模板生成的 seatKey如 "A_1")没有对应的 spec_base_id`submit()` 会降级到 Zone 级别 SKU同一 zone 全部座位共享一个 spec失去座位粒度。→ **需要后台管理员先为每个座位创建规格**。
### 优先级与依赖
- **Q2 是 Q4 的前提** — Q4 的"多座位选座流程"依赖 Q2 的多 SKU 订单能力。
- Q2 本身不依赖 Q1可以独立推进。
- Q3 和 Q4 无依赖,但 Q3 生成的代码需适配 Q4 选型H5 vs uni-app
---
## Q1 结论ShopXO 自定义模板最佳实践
### 核心答案
**票务详情页不走 DIY 设计器,直接修改 `ticket_detail.html` 的 PHP+原生 JS**uni-app 端 fork `shopxo-uniapp` 改写 `goods-detail.vue`,无需经过 ShopXO 模板中间层。
### 证据来源
| 文件/文档 | 结论 |
|----------|------|
| `docs/02_FRONTEND_CUSTOMIZATION.md` | DIY 设计器只支持静态 HTML 区块嵌入无法参数化uni-app 完全独立于 ShopXO 模板 |
| `docs/12_UNIAPP_FRONTEND_RESEARCH.md` | shopxo-uniapp 是独立 Vue 项目,通过 API 对接 ShopXOCSS 在 H5/小程序完全一致WebView 同源) |
| `docs/14_TEMPLATE_RENDER_INVESTIGATION.md` | ShopXO view/goods/ 模板使用原生 PHP + 原生 JSsession/buy 等控制器直接 render |
| `ticket_detail.html` | 当前已实现:场次选择 + 座位图渲染 + 观演人表单 + 购买栏 |
### 最小可行方案
**H5 端**:在现有 `ticket_detail.html` 基础上增强,引入:
- 座位类型图例(已完成)
- 已售座位 AJAX 实时标记(待实现 `loadSoldSeats()`
- 座位缩放/拖拽交互(原生 JS<200 行)
- 动态场次切换时重置已选座位(已写但未调用)
**技术栈**`原生 HTML + 内联 CSS + 内联 JS`,无框架依赖,ShopXO 模板系统直接渲染,无需构建。
### 理想方案
**uni-app 端**
1. Fork `shopxo-uniapp` `vr-shopxo-uniapp`
2. 重写 `pages/goods-detail/goods-detail.vue`,接入 vr_ticket API
3. 新建 `pages/ticket-seat/ticket-seat.vue`(选座主流程)
4. 新建 `pages/ticket-wallet/ticket-wallet.vue`(票夹)
5. H5 本地预览 = 小程序编译效果,CSS 完全一致
**关键约束(uni-app 开发规范)**
- `rpx` 不用 `vw/vh`
- `<view>` 不用 `<div>`
- 避免 `calc()` 混用单位
- `position: fixed` 吸顶在 H5 正常,小程序需 shopxo-uniapp 已有方案
### 最大风险点
1. **shopxo-uniapp fork 同步成本** 官方 shopxo-uniapp 更新后需要手动同步,未来维护成本高。→ 建议在 fork 分支上做票务专属页面,官方页面保持独立升级路径。
2. **ShopXO 版本 vs shopxo-diy 版本匹配** shopxo-diy v1.4.2 ShopXO v6.8.0,如果使用 DIY 设计器管理非票务页面,版本必须严格匹配。
### 优先级与依赖
- Q1 Q4 的技术基础,Q1 的结论直接支撑 Q4 的技术选型决策。
- Q3 依赖 Q1 的约束条件输出。
---
## Q3 结论:第三方无代码构建服务提示词策略
### 核心答案
**用"模板 + 示例 + 约束"三层结构撰写 Prompt**ShopXO 模板的特殊性(模块化 PHP 标签、ShopXO 资源路径 API)在 Prompt 中明确声明,生成代码后只需做两件事后处理:① 替换静态资源路径为 `ModuleInclude()` 调用,② 注入座位图数据结构(从 PHP 模板变量传入)。
### Prompt 三层结构
```
【第一层:角色定义】
你是一个 ShopXO v6.8.0 模板开发者,擅长编写票务商品详情页。
【第二层:约束清单】
- HTML 结构:使用 <?php echo ModuleInclude('public/header'); ?> 包裹页面头
- 样式:全部内联 <style>CSS 类名前缀 vr- 避免冲突
- JS 数据注入const app = <?php echo json_encode($php_var); ?>
- 资源路径:静态资源用 <?php echo ModuleInclude('images/foo.png'); ?>
- 不使用Vue/React CDN、外部 CDNShopXO 必须离线可用)
【第三层:具体需求】
[座位图 UI 规格rpx 规范、颜色、尺寸 + 交互事件定义]
[ShopXO 数据契约goods_spec_data、vr_seat_template、extension_data]
```
### 生成代码后处理步骤
1. **路径替换**:全局搜索 `src="/static/` `<?php echo ModuleInclude('static/') ?>`
2. **变量注入点**:在 `<script>` 顶部注入 `var seatMap = <?php echo json_encode($vr_seat_template['seat_map']); ?>`
3. **事件绑定**`onclick` 属性需改为 `onclick="vrTicketApp.toggleSeat(this)"` 格式(原生 JS
4. **样式隔离**:检查是否覆盖 `.goods-detail-*` ShopXO 全局类名,如有则加 `.vr-ticket-page` 限定符
### 最大风险点
1. **无代码服务生成的 UI 过于复杂** 座位图等高交互组件无法用无代码工具精确生成,强行生成会导致大量调试工作。→ **无代码服务适合静态展示区块(票务商品介绍、艺人信息图),座位图选座交互必须手写**。
2. **ShopXO 离线可用约束** ShopXO 运行在企业内部/私有化部署场景,所有资源必须本地化,无代码服务默认 CDN 引用必须全部替换。
---
## Q4 结论uni-app 兼容性技术栈选型
### 核心答案
**推荐方案:一套 shopxo-uniapp fork + 条件编译**,票务页面走独立路由(H5/小程序双端),商城标准页面复用 shopxo-uniapp 原生实现。
### 技术选型对比
| 维度 | 原生 HTML 模板 | uni-app fork shopxo-uniapp | Flutter / React Native |
|------|---------------|---------------------------|----------------------|
| H5 本地预览 | 直接浏览器打开 | HBuilderX H5 运行 | 需真机调试 |
| 微信小程序 | 不支持 | 一键编译 | 需分别开发 |
| ShopXO API 对接 | 需手动 HTTP | shopxo-uniapp 已封装 | 需手动 HTTP |
| 学习成本 | | 中(需熟悉 Vue | |
| 座位图等复杂交互 | 原生 JS 手写 | Vue 组件手写 | 手写 |
| 开发速度 | 快(单文件) | | |
**最终推荐**`fork shopxo-uniapp`,用 Vue 3 + SCSS,票务页面自研,其他页面复用。
### 票务页面与商城标准页面共存方案
```
vr-shopxo-uniapp/
├── pages/index/index.vue ← 改写:底部 Tab 新增「票务」Tab
├── pages/goods-detail/ ← 改写:票务商品跳 ticket-seat 页面
├── pages/ticket-seat/ ← 新建:选座 + 购票主流程Vue 组件)
├── pages/ticket-wallet/ ← 新建:票夹(我的票)
├── pages/ticket-verify/ ← 新建B 端核销
├── App.vue ← request_url 指向目标商城
└── pages.json ← 路由配置
```
**H5/小程序一致性**uni-app H5 和小程序都基于 WebViewCSS 渲染一致。关键:用 `rpx`,用 `<view>`,避免浏览器私有前缀。
### 最大风险点
1. **shopxo-uniapp 官方更新同步** 100+ forks,官方更新需手动 cherry-pick vr fork。建议将票务专属页面与商城原生页面放在不同目录,改动隔离,升级时只同步商城页面。
2. **ShopXO 版本与 shopxo-uniapp 版本匹配** shopxo-uniapp API 契约随 ShopXO 后端版本变化,vr_ticket 插件如使用 shopxo-uniapp,请确认 ShopXO 版本(当前 v6.8.0),使用对应的 shopxo-uniapp 版本。
### 优先级与依赖
- **Q4 依赖 Q2(多座位选座)和 Q1H5 模板基础)**
- Q4 本身是最终落地执行层,前三个 Q 的结论在 Q4 中整合实现
---
## 优先级矩阵
| 优先级 | 任务 | 负责 Agent | 前置条件 |
|--------|------|-----------|---------|
| P0 | Q2 SKU 走购物车路线打通多座位下单 | BackendArchitect | |
| P1 | Q4 uni-app fork 建立项目骨架 | FrontendDev | Q1 结论 |
| P2 | Q4 ticket-seat.vue 选座核心组件 | FrontendDev | P0 完成 |
| P3 | Q1 ticket_detail.html 增强 已售座位实时标记 | FrontendDev | |
| P4 | Q3 提示词策略落地 无代码服务辅助静态区块 | ProductManager | Q1 结论 |
| P5 | Q2 理想方案 插件 hook 拦截 OrderSplitService | BackendArchitect | P0 验证 |
---
## 最小可行方案 vs 理想方案对比
| 维度 | 最小可行方案 | 理想方案 |
|------|------------|---------|
| 多座位下单 | 购物车路线(不碰 OrderSplitService | 插件 hook 拦截,实现原生多 SKU 单订单 |
| 前端 H5 | 增强 ticket_detail.html< 3 处改动) | 迁移到 uni-app H5 |
| 前端小程序 | shopxo-uniapp fork,票务页面 Vue 自研 | 完整迁移,小程序体验与 H5 一致 |
| 座位图 | 原生 JS< 200 | Vue 组件,含缩放/拖拽/动画 |
| 观演人表单 | HTML + JS,支持动态增减 | Vue 组件化,数据校验 |
| 核销 B | 复用现有后台核销页面 | 新建小程序核销页面(扫码 + API |
| 交付周期 | 1 天(可上线 demo | 2-3 周(完整票务流程) |
---
## 最大技术风险点汇总
| 风险 | 严重程度 | 缓解措施 |
|------|---------|---------|
| OrderSplitService 拆单导致多座位订单被拆 | | 最小方案走购物车绕过;理想方案用插件 hook 拦截 |
| 座位级 SKU 未在后台创建 | | 后台管理界面增加「批量生成座位规格」功能 |
| shopxo-uniapp fork 同步成本 | | 票务页面与商城页面目录隔离,改动隔离升级 |
| 无代码服务无法生成高交互组件 | 低(已有认知) | 座位图等核心交互手写,静态区块用无代码辅助 |
| ShopXO 版本不匹配 shopxo-diy | 低(不走 DIY | 不使用 DIY 设计器 |
---
## 关键文件清单
| 文件 | 用途 |
|------|------|
| `shopxo/app/service/BuyService.php` | 订单创建入口,多 SKU 关键代码 |
| `shopxo/app/service/OrderSplitService.php` | 拆单逻辑,多座位订单被拆的风险点 |
| `shopxo/app/plugins/vr_ticket/view/goods/ticket_detail.html` | 当前票务详情页模板,Q2 SKU Plan A 代码已在此 |
| `docs/12_UNIAPP_FRONTEND_RESEARCH.md` | uni-app 调研存档,Q1/Q4 依赖此文档 |
| `docs/02_FRONTEND_CUSTOMIZATION.md` | ShopXO DIY 设计器局限性证明 |
| `docs/14_TEMPLATE_RENDER_INVESTIGATION.md` | 模板渲染机制调查 |
| `docs/09_SHOPXO_HOOKS_REFERENCE.md` | 插件钩子清单,Q2 理想方案所需 hook 在此 |
---
## 结论
1. **多座位下单可行**:走购物车路线,1 天内可上线多座位下单 Demo
2. **uni-app 是最终目标**fork shopxo-uniapp 票务页面自研,商城页面复用,H5 预览 = 小程序编译效果。
3. **无代码服务辅助有限**:适合静态展示区块,座位图等核心交互必须手写。
4. **Immediate Action**BackendArchitect 提交 Q2 Plan A(购物车路线),FrontendDev 启动 shopxo-uniapp fork 项目骨架。