# vr-shopxo-plugin Phase 2 — 后台管理开发计划 > 版本:v1.1 | 制定日期:2026-04-15 | Agent:council/FrontendDev + council/SecurityEngineer 合并 ## 概述 Phase 2 目标:完成后台管理页面开发,涵盖座位模板管理、电子票管理、核销员管理、核销记录查询,以及 Admin 控制器鉴权修复。 --- ## 阶段划分 | 阶段 | 内容 | 负责 | |------|------|------| | Draft | 资料收集、研究方向确认 | 所有成员 | | Review | 代码实现审查、安全评审 | SecurityEngineer + Council | | Finalize | 合并到 main、文档整理 | 所有成员 | --- ## Agent 任务分配 | Agent | 主要任务 | |-------|---------| | BackendArchitect | API 设计、权限模型、数据库查询 | | SecurityEngineer | Admin 鉴权、注入/XSS、审计、IDOR | | FrontendDev | UI 框架选型、ShopXO admin 风格适配 | --- ## 任务清单 ### 座位模板管理 - [x] 座位模板列表页(seat_template/list.html)— 已完成 - [x] 座位模板新增/编辑页(seat_template/save.html)— 已完成 - [ ] 座位图可视化编辑器集成 - [x] 分类绑定功能 — 已完成 ### 电子票管理 - [x] 电子票列表页(ticket/list.html)— 已完成 - [x] 票详情页(ticket/detail.html)— 已完成 - [x] 批量导出功能(CSV/Excel)— 已完成 - [x] 票状态筛选(未核销/已核销/已退款)— 已完成 ### 核销员管理 - [x] 核销员列表页(verifier/list.html)— 已完成 - [x] 核销员新增/编辑/删除(verifier/save.html)— 已完成 - [ ] 核销员绑定店铺/场次 ### 核销记录 - [x] 核销记录列表页(verification/list.html)— 已完成 - [x] 多条件查询(时间/核销员/场次)— 已完成 - [ ] 核销统计看板 ### Admin 鉴权(P1 安全) - [x] 所有 Admin 控制器继承 Base controller — 已完成(Base extends Common) - [ ] 鉴权中间件验证 — `[Claimed: council/SecurityEngineer]` - [ ] 敏感操作日志审计 — `[Pending]` ### 安全任务 - [ ] **Task S1** — 审查 ShopXO 后台鉴权机制,确认 Phase 2 Base 控制器鉴权覆盖完整性 `[Pending]` - [ ] **Task S2** — SQL 注入风险审计,覆盖所有 Phase 2 数据查询 `[Pending]` - [ ] **Task S3** — XSS / CSRF 防护检查 `[Pending]` - [ ] **Task S4** — 敏感操作审计日志设计 `[Pending]` - [ ] **Task S5** — IDOR / 水平越权测试用例编写 `[Pending]` --- ## Research Direction List(合并版) ### 安全研究方向(SecurityEngineer) #### R1: Admin 控制器鉴权风险 **背景**:Council 安全审议发现 P1 问题 —— Admin 控制器缺少统一鉴权机制,Phase 2 所有后台页面均受影响。 Key Questions: - [ ] ShopXO 后台 admin 控制器统一鉴权入口在哪里?`AdminBaseController` 或中间件? - [ ] Phase 2 新增的 Base 控制器(`app/common.php` 的 Base 类)是否已正确调用鉴权? - [ ] 各子控制器(SeatTemplate / Ticket / Verifier)是否有遗漏的 public 方法暴露未授权访问? - [ ] 鉴权失败后的跳转逻辑是否正确?是否存在认证绕过风险? - [ ] 后台操作是否需要二次验证(如删除、核销等敏感操作)? **优先级**:P0 #### R2: SQL 注入风险评估 **背景**:电子票导出、核销记录查询等涉及复杂 SQL,必须防范注入。 Key Questions: - [ ] ShopXO 原生查询构造器(Db::table / Db::name)的参数绑定机制是否覆盖所有输入点? - [ ] 日期范围查询、模糊搜索等动态构造场景是否存在拼接风险? - [ ] IN() 子句的数组参数是否经过安全处理? - [ ] 关联查询(join)中是否有注入向量? - [ ] 是否有 ORM 之外的原始 SQL 执行需要审查? **优先级**:P1 #### R3: XSS / CSRF 风险 **背景**:后台管理页面输出到管理端,但仍需防范存储型 XSS 和 CSRF。 Key Questions: - [ ] 后台页面渲染时是否统一使用 htmlspecialchars 或框架转义? - [ ] 富文本编辑(如座位模板名称备注)是否存在存储型 XSS? - [ ] POST 请求是否均携带 CSRF Token?ShopXO 的 CSRF 保护机制是什么? - [ ] JSON API 响应是否可能携带恶意脚本? - [ ] 删除/核销等关键操作是否有 CSRF Token 保护? **优先级**:P1 #### R4: 敏感操作审计日志 **背景**:核销操作、票务导出等属于高敏感操作,必须可追溯。 Key Questions: - [ ] 是否需要新建 `vr_audit_log` 表记录关键操作? - [ ] 核销记录是否需要记录操作人 IP、UA、设备指纹? - [ ] 导出操作是否需要记录?谁、何时、导出内容摘要? - [ ] 审计日志是否需要防篡改设计(如 hash chain 或 append-only 表)? - [ ] ShopXO 是否有现有审计日志机制可以复用? **优先级**:P2 #### R5: 水平越权风险(IDOR) **背景**:核销员管理、电子票详情等场景存在横向越权风险。 Key Questions: - [ ] 核销员详情/编辑接口是否校验当前用户所属机构/场馆? - [ ] 电子票详情接口是否校验持票人身份? - [ ] 核销记录查询是否仅返回当前核销员/机构的记录? - [ ] 删除/编辑操作是否有归属校验(owner check)? - [ ] 是否有测试用例覆盖常见的 IDOR 攻击向量? **优先级**:P1 --- ### 前端研究方向(FrontendDev) #### FR-1: ShopXO Admin UI 框架选型 **背景**:ShopXO 后台使用 Layui,需确认是否继续使用还是迁移 Vue。 Key Questions: - ShopXO 官方后台(v6.8.0)使用的是什么 UI 版本? - Layui 是否支持 Vue 3?如果不支持,混用 Vue + Layui 是否会导致冲突? - 票务插件是否应保持与 ShopXO 原生风格一致,还是可以独立升级? - 是否有 ShopXO 插件使用 Vue 3 的先例? #### FR-2: 现有 ShopXO Admin 页面风格适配 **背景**:保持与 ShopXO 原生后台风格一致可降低学习成本。 Key Questions: - ShopXO 后台使用的是什么设计系统(颜色/字体/间距规范)? - 表格组件(数据列表)用的是 Layui table 还是自建? - 分页、筛选、搜索的通用组件封装在哪里? - 弹窗/表单布局的规范是什么? #### FR-3: 座位图编辑器集成方案 **背景**:座位模板需要可视化编辑,复杂度高。 Key Questions: - 是否有开源的 Vue 座位图编辑器可以集成? - Canvas vs SVG vs CSS Grid,哪个方案最适合票务座位图? - 座位图编辑后如何序列化存储到 seat_map JSON? - 编辑器是否需要支持拖拽、分区着色、座位类型标注? #### FR-4: 数据导出方案(CSV/Excel) **背景**:电子票列表需要支持批量导出。 Key Questions: - ShopXO 后台是否有现成的导出组件? - 大量数据(10000+ 条)导出的处理策略是什么(流式导出 vs 后台队列)? - 是否需要支持 Excel 格式(.xlsx)还是只需 CSV? - 导出字段如何与 vr_tickets 表字段对应? #### FR-5: 响应式与权限控制 **背景**:后台页面需要同时支持不同屏幕和权限级别。 Key Questions: - ShopXO 后台的权限体系是如何设计的(RBAC?按钮级?字段级?)? - 票务管理员是否需要独立的角色?与 ShopXO 管理员如何隔离? - 后台页面是否需要支持移动端(PAD 核销场景)? - 操作日志记录哪些字段(用户/时间/操作/IP/变更前后)? --- ## 依赖关系 - FR-1、FR-2 优先完成,决定技术栈选型 - FR-3 依赖 FR-1 的选型结论 - FR-4 可在 Phase 3 后端 API 确定后并行进行 - FR-5 与 SecurityEngineer 协同,需要等 BackendArchitect 输出权限模型 - Task S1(鉴权审查)需在 BackendArchitect 完成 API 设计初稿后进行交叉评审 - Task S2(SQL 审计)可与 BackendArchitect 的数据库设计并行 - Task S4(审计日志)依赖最终的数据模型设计 --- ## Round 2 执行发现(BackendArchitect) ### 关键阻塞问题 | # | 问题 | 严重度 | 影响范围 | |---|------|--------|---------| | 1 | plugin Base 控制器只做登录检查,未做权限检查 | **P0** | 所有插件后台页面 | | 2 | `Verifier.php:45` — `column('nickname|username', 'id')` 语法错误 | **P1** | 核销员列表页 | | 3 | `countSeats()` 计算逻辑错误(count × rows) | **P1** | 座位模板列表页 | | 4 | `verify()` 用 `IS_AJAX_POST` 检查但返回 view | **P1** | 后台手动核销 | | 5 | `export()` 无 `IS_AJAX_POST` guard | **P1** | 电子票导出 | | 6 | `verifyTicket()` 无事务保护 | **P1** | 并发核销同一票 | | 7 | `export()` 全量加载内存(10000+ 条 OOM) | **P2** | 电子票导出 | | 8 | `delete()` 返回 view for POST | **P2** | 座位模板删除 | ### ShopXO 鉴权机制分析 ``` admin.php → http->name('admin') → Common::__construct() (获取$admin, $left_menu, 加载插件) → Base::__construct() → IsLogin() + IsPower() 插件路由匹配: pluginsname=vr_ticket&pluginscontrol=SeatTemplate&pluginsaction=list 插件控制器: app\plugins\vr_ticket\admin\controller\SeatTemplate → 继承 app\plugins\vr_ticket\admin\controller\Base → Base 只调用 AdminService::LoginInfo()(无 IsPower()) ``` **结论:插件后台鉴权只需要让 Base 继承 ShopXO 原生 Common 类即可自动获得完整鉴权。** ### 已认领任务 - [x] **Task B1** — 座位模板管理 CRUD — `[Done: council/BackendArchitect]` - [x] **Task B2** — 电子票列表/详情/导出 — `[Done: council/BackendArchitect]` - [x] **Task B3** — 核销员管理(增删改查)— `[Done: council/BackendArchitect]` - [x] **Task B4** — 核销记录查询 — `[Done: council/BackendArchitect]` - [x] **Task B5** — Base 控制器鉴权修复 — `[Done: council/BackendArchitect]` --- ## Round 3 执行结果(BackendArchitect) ### 本轮完成内容 | # | 文件 | 操作 | 说明 | |---|------|------|------| | 1 | `admin/view/verifier/list.html` | 新建 | 核销员列表页(Layui table + 搜索栏 + 编辑/禁用按钮) | | 2 | `admin/view/verifier/save.html` | 新建 | 核销员新增/编辑页(用户选择 + 名称 + 状态) | | 3 | `admin/view/ticket/detail.html` | 新建 | 票详情页(基本信息 + QR码 + 手动核销表单) | | 4 | `admin/controller/Verifier.php` | 修复 | `column(CONCAT(...))` 语法错误 → 改为先 select 再 PHP 拼接 | | 5 | `admin/controller/Ticket.php` | 修复 | `detail()` 补充 `verifiers` 变量传给 detail.html | ### 遗留 P0/P1 阻塞(需 SecurityEngineer 处理) | # | 问题 | 严重度 | 备注 | |---|------|--------|------| | S1 | Admin 控制器鉴权覆盖完整性 | P0 | `[Pending: council/SecurityEngineer]` | | S2 | SQL 注入风险审计 | P1 | `[Pending: council/SecurityEngineer]` | | S3 | XSS / CSRF 防护检查 | P1 | `[Pending: council/SecurityEngineer]` | | S5 | IDOR 越权测试 | P1 | `[Pending: council/SecurityEngineer]` | --- ## 共识投票 [CONSENSUS: NO] — 等待 SecurityEngineer 完成 Task S1~S5 后可结束 Phase 2