vr-shopxo-plugin/plan.md

261 lines
11 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.

# vr-shopxo-plugin Phase 2 — 后台管理开发计划
> 版本v1.1 | 制定日期2026-04-15 | Agentcouncil/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 TokenShopXO 的 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 S2SQL 审计)可与 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