vr-shopxo-plugin/docs/DEVELOPMENT_LOG.md

13 KiB
Raw Blame History

VR 票务插件开发日志

vr-shopxo-plugin 项目全量记录 仓库:http://xmhome.ow-my.com:3000/sileya-ai/vr-shopxo-plugin 最后更新2026-04-15


一、项目背景与决策

1.1 需求来源2026-04-13

大头受朋友委托,为其合作伙伴调研轻量级商城小程序解决方案。

核心需求:

  • 订单:外卖配送 / 包邮 / 自提
  • 会员:充值、积分、优惠券
  • 约束:无程序员/无前端/无后端,要求直接可用,后期能用 AI 改动,架构清晰,部署简单

调研结论4 个方案对比):

项目 Stars 功能 部署 会员体系 AI友好 综合
ShopXO 8.5k 9/10
Bagisto 14k 5/10
Saleor 22.4k 5/10
Medusa 23k+ 4/10

ShopXO 断层第一,原因:功能完整 + 虚拟主机可部署 + 有 uni-app 前端配套 + MIT 协议可商用。

票务插件定位: 票务 = ShopXO 商品类型扩展。item_type = 'ticket' 时走插件逻辑处理座位图/场次/QR票。

1.2 技术栈决策

技术选型 说明
商城底座 ShopXO v6.8.0 ThinkPHP 8虚拟主机可部署
前端 uni-app 微信小程序 + H5
票务插件 PHP 原生 插件机制 + Hook 系统
票务详情页 独立 HTML 模板 完全独立 UI绕过 ShopXO 主题限制
数据库 MySQL与 ShopXO 共用) 表前缀 vrt_
QR 票 AES 加密 防伪造
核销 扫码枪 + RLS B 端小程序扫码核销

核心原则(已固化):

怎么快怎么来,怎么方便怎么来,少改动少复杂度,完全允许改 ShopXO 核心代码(自己部署)。


二、技术调研2026-04-13 白天)

2.1 ShopXO 插件机制调研

调研文件:

  • docs/07_SHOPXO_PLUGIN_MECHANISM.md — 插件开发机制完整手册
  • docs/08_SHOPXO_REQUIREMENTS_MAPPING.md — 票务需求 → ShopXO 机制对照矩阵
  • docs/09_SHOPXO_HOOKS_REFERENCE.md — 100+ 钩子清单

插件核心机制:

  1. config.json — 插件元数据(名称/版本/依赖/菜单/权限/静态资源)
  2. BaseService — 插件业务服务基类GetDb / 参数校验 / 日志)
  3. EventListener.php — 生命周期钩子Install/Uninstall/Upgrade/Index
  4. URL 路由 — 后台控制器 plugins_admin 前缀,前台 plugins 前缀
  5. 视图 — admin/view/default/plugins_admin/ + view/default/plugins/ 目录

关键发现(票务用途):

钩子 用途
plugins_service_order_pay_success_handle_end 支付成功 → 生成 QR 票
plugins_view_goods_detail_base_sku_top 商品详情页顶部(选座 UI
plugins_view_user_various_inside_top 用户中心(票夹)
plugins_service_goods_delete_end 商品删除 → 清理票务数据
plugins_admin_goods_info_init_end 后台商品编辑 → 加载票务字段

2.2 票务详情页方案抉择

方案 AURL 劫持 放弃

  • 缺点:无法继承商品详情页基础样式,改动 ShopXO 核心代码量大

方案 BCSS 隐藏标准 SKU 放弃

  • 缺点Hook 链过长,不可控

方案 C插件模板替换 不可行

  • 调研结论MyView() 源码确认 ShopXO 插件系统是纯钩子系统config.json 无权覆盖 Goods 控制器模板路径goods/detail.html 写死在控制器里

方案 D最终Goods.php 1 行判断

  • 在 app/index/controller/Goods.php 的 return MyView(); 前插入判断
  • item_type == 'ticket' → 加载插件模板路径 + 预查询座位模板数据
  • 改动量1 行条件判断 + ~10 行数据注入
  • 实测验证:浏览器访问商品详情页,座位图渲染正常

三、ShopXO 环境配置2026-04-15 凌晨)

3.1 Docker 环境

服务 端口 说明
shopxo-web :10000 Nginx 前端
shopxo-mysql :10001 MySQL 8.0
shopxo-php :9000 PHP-FPM

3.2 关键配置

  • 后台入口adminwatekc.php非标准 admin.php
  • 表前缀vrt_非标准 sxo_
  • 数据库凭证root=shopxo_root_2024 / user=shopxo_user / pass=shopxo_pass_2024
  • 源码路径:~/.openclaw/workspace/council-research/shopxo-eval/.worktrees/shopxo-evaluator/shopxo-src/
  • is_develop在 config/shopxo.php 第 41 行改为 true

3.3 后台权限修复

admin 用户role_id=1默认缺少插件权限。手动写入 38 条权限到 vrt_role_power

  • 应用管理链路340 / 341 及子权限 342-591

3.4 模板目录冲突

ThinkPHP 路由用 plugins_admin下划线格式但实际目录为 pluginsadmin无下划线。通过创建符号链接解决。


四、Phase 0插件骨架2026-04-15 04:36 起)

4.1 完成内容

数据库建表(手动 SQL

-- 座位模板 CREATE TABLE vrt_vr_seat_templates ( id INT PRIMARY KEY AUTO_INCREMENT, name VARCHAR(100) NOT NULL COMMENT '模板名称', category_id INT DEFAULT 0 COMMENT '绑定分类ID', spec_base JSON COMMENT '座位规格基数据', qr_data VARCHAR(64) NOT NULL COMMENT 'QR数据前缀', is_enable TINYINT DEFAULT 1, created_at DATETIME DEFAULT CURRENT_TIMESTAMP );

-- 电子票 CREATE TABLE vrt_vr_tickets ( id INT PRIMARY KEY AUTO_INCREMENT, order_id INT NOT NULL, order_no VARCHAR(64), goods_id INT NOT NULL, user_id INT NOT NULL, qr_code TEXT NOT NULL COMMENT 'AES加密QR数据', status ENUM('pending','active','used','cancelled') DEFAULT 'pending', qr_data VARCHAR(128), seat_label VARCHAR(32), verified_at DATETIME, created_at DATETIME DEFAULT CURRENT_TIMESTAMP );

-- 核销员 CREATE TABLE vrt_vr_verifiers ( id INT PRIMARY KEY AUTO_INCREMENT, user_id INT NOT NULL, name VARCHAR(50), status TINYINT DEFAULT 1, created_at DATETIME DEFAULT CURRENT_TIMESTAMP );

-- 核销记录 CREATE TABLE vrt_vr_verifications ( id INT PRIMARY KEY AUTO_INCREMENT, ticket_id INT NOT NULL, verifier_id INT NOT NULL, verified_at DATETIME DEFAULT CURRENT_TIMESTAMP, location VARCHAR(200) );

插件文件结构:

app/plugins/vr_ticket/ ├── plugin.json # 插件配置3个子菜单 ├── EventListener.php # 生命周期Install建表/Uninstall/Upgrade ├── service/ │ ├── BaseService.php # 工具AES/QrData/UUID/日志) │ ├── TicketService.php # onOrderPaid/verifyTicket/getUserTickets │ └── SeatTemplateService.php ├── admin/ │ ├── controller/ │ │ ├── SeatTemplate.php # 座位模板 CRUD │ │ ├── Ticket.php # 电子票列表+详情+导出 │ │ ├── Verifier.php # 核销员管理 │ │ └── Verification.php # 核销记录 │ └── view/default/ # Layui 列表页 └── view/goods/ └── ticket_detail.html # 前端票务详情页独立UI

测试数据:

  • 商品 ID 112VR演唱会电子票 2024item_type=ticket
  • 分类 ID 911VR演唱会
  • 座位模板 ID 1Bird Nest - Zone A绑定 category_id=911
  • 3排座位A排AAAAAA红色VIP区/ B排BBBBBB蓝色看台区/ C排CCCCCC绿色普通区

五、Phase 1Goods.php 改法 + 前端验证2026-04-15 白天)

5.1 修改内容

文件app/index/controller/Goods.php 位置detail() 方法return MyView(); 前约第 137-139 行

代码改动:

// --- VR 票务处理 start --- $goods = $result['data']['goods']; if (!empty($goods['item_type']) && $goods['item_type'] === 'ticket') { // 加载座位模板 $spec_base = Db::table('vr_seat_templates') ->where('category_id', $goods['category_id']) ->where('is_enable', 1) ->find(); $goods['vr_seat_template'] = $spec_base; // 加载 goods_spec_data座位动态价格 $goods_spec_data = empty($goods['spec_base']) ? [] : json_decode($goods['spec_base'], true); $goods['vr_spec_data'] = $goods_spec_data; // 使用票务专用模板 $this->set_title($goods['title'].' - VR电子票'); return MyView('public/../../../plugins/vr_ticket/view/goods/ticket_detail', [ 'common' => $common, 'header' => $header, 'goods' => $goods, ]); } // --- VR 票务处理 end ---

5.2 前端票务详情页渲染结果

URLhttp://localhost:10000/?s=index/goods/index/id/1商品1改为 item_type=ticket 测试)

渲染效果:

  • 舞台(舞 台)
  • 座位图三行A排AAAAAA红色VIP区/ B排BBBBBB蓝色看台区/ C排CCCCCC绿色普通区
  • 图例VIP区 / 看台 / 普通)
  • 选座 UI已选座位计数 + 合计价格)
  • 场次选择
  • 观演人表单(姓名+手机号)

六、Council 审议记录2026-04-14

6.1 Architect Round 1已合并

评审结论Q2+Q4

  • Q2spec 座位共用 vs 独立 → 确认方案
  • Q4spec 复用粒度 → 确认粒度

6.2 PM Round 2已合并

  • 解决 plan.md 合并冲突

6.3 待 Council 审议的遗留问题

问题 状态 说明
Q2spec座位共用vs独立 已解决 见 ARCHITECTURE.md
Q3观演人存储位置 待 Council 尚未最终确认
Q4spec复用粒度 已解决 见 ARCHITECTURE.md

七、关键决策固化

决策 结论 备注
改 ShopXO 核心可以吗 可以,自己部署 原则已写入 README
票务详情页方案 Goods.php 1行判断 → ticket_detail.html 已验证
spec = 场次 确认 无需 vr_sessions 表
座位模板绑定分类 确认 Q1 已解决
item_type 字段 ticket / normal 触发票务逻辑开关
座位图渲染 HTML Table + CSS Grid 不依赖第三方库
QR 安全 AES_Encrypt 防伪造
AI 介入程度 90%+ 模板/Hook/PHP/Vue 均为标准技术

八、当前状态快照2026-04-15 09:00 CST

8.1 Git Commit 历史

7508bed docs: 追加 vr-shopxo-plugin Phase 0/1 状态记录 0f5a82d feat(Phase 1): ShopXO Goods.php 修改(实际验证通过) 34f7045 feat(Phase 0): vr_ticket plugin skeleton complete d5edb76 docs: add guiding principle + Goods.php modification guide 1c6d32b docs: add ShopXO hooks reference (v6.8.0) - extracted from source e7b7bf9 docs: add plugin mechanism + requirements mapping docs 536ef9e docs: add 项目启动报告 REPORT-KICKOFF.md (issue #5) 8c6878e council(draft): Architect - 合并 Round 1 架构评审结论 9eae259 council(draft): Architect - Round 1 架构评审结论 (Q2+Q4)

8.2 Phase 完成度

Phase 状态 说明
Phase 0骨架 完成 14个文件4张表插件已注册
Phase 1前端票务详情页 完成 Goods.php验证通过座位图渲染正常
Phase 2后台管理页面 待开始 场次管理/座位管理/票务订单列表
Phase 3支付回调 + 发票 待开始 钩子联调 + QR 票生成
Phase 4B端扫码核销 待开始 核销员管理 + 扫码 API

8.3 关键文件路径

ShopXO 容器: 源码:~/.openclaw/workspace/council-research/shopxo-eval/.worktrees/shopxo-evaluator/shopxo-src/ 插件shopxo-src/app/plugins/vr_ticket/ Goods.phpshopxo-src/app/index/controller/Goods.php

vr-shopxo-plugin 仓库: 插件代码app/plugins/vr_ticket/ ShopXO 修改shopxo-modifications/app/index/controller/Goods.php 文档docs/


九、下一步计划

Phase 2后台管理页面

  1. 座位模板管理admin/controller/SeatTemplate.php

    • Layui 列表页(已生成 view
    • 创建/编辑/删除操作
  2. 电子票管理admin/controller/Ticket.php

    • 票列表(支持按订单号/手机号搜索)
    • 票详情(显示 QR 码)
    • 导出功能
  3. 核销员管理admin/controller/Verifier.php

    • 增删改查
  4. 核销记录admin/controller/Verification.php

    • 核销历史列表

Phase 3支付回调 + QR 票生成

  1. 实现 TicketService::onOrderPaid() → 支付成功时生成票
  2. Hookplugins_service_order_pay_success_handle_end
  3. AES 加密 QR 数据
  4. ShopXO 站内通知或 Realtime 推送

Phase 4B 端扫码核销

  1. 核销 APIB 端小程序调用)

    • POST /api/ticket/verify扫码枪调用
    • RLS 策略profiles.role = 'staff' 可核销
  2. 核销员注册

    • 后台添加核销员(手机号)
    • 绑定 user_id

十、已知问题与待验证项

问题 优先级 状态
后台插件菜单无权限 P1 admin 已有 340/341vr_ticket 控制器权限未单独分配
观演人存储位置Q3 P2 待 Council 审议
spec_base JSON 结构最终版 P2 已确认 Q4 方案,待落地
支付回调联调 P2 等待 Phase 2 后台完成后测试
核销 API RLS P2 待实现