vr-shopxo-plugin/docs/PHASE_B_2026-04-25_PLAN.md

188 lines
6.8 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.

# Phase BB端核销开发计划
> 创建时间2026-04-25 10:26 CST
> 创建人:西莉雅
> 状态:✅ Council 执行完成2026-04-25 10:39 CST
> Commit: `feat/phase-b-verification` 分支3个 subagent 并行完成)
---
## 一、背景
C端票夹 + 出票链路已完成Phase 4.1-4.3)。
下一步B端核销管理后台 + 安全修复。
**已知安全债务Issue #7**
- M-01verifyTicket TOCTOU → ✅ 已修复FOR UPDATE + 事务)
- M-02手动核销无鉴权 → 🔴 B端开发前必须修复
- M-03ALTER TABLE 条件永不成立 → 🟢 快速修复2行
- M-04loadSoldSeats 未实现 → ✅ 已实现
- M-05verifier_id 客户端伪造 → 🔴 B端开发前必须修复
- M-06Admin 控制器无权限校验 → 🔴 B端安全基线
- M-07QR 明文暴露 ticket_code → 🟢 低风险,可后置
- M-08issueTicket 二次写入 → ✅ 已修复
---
## 二、分阶段计划
### Phase B0 — 安全基线 ✅ 完成
> B0-1 + B0-2 + B0-3 由 subagent B0-SecurityFix 完成commit: `f3d102e7a`
**目标**:修复 M-06、M-02、M-05、M-03建立 B端安全防线。
#### B0-1Admin.php 权限校验M-06
在 Admin.php 所有操作方法TicketVerify/TicketList/TicketExport/VerifierSave/VerifierDelete 等)开头加:
```php
public function TicketVerify()
{
// M-06: 强制管理员登录校验
if (empty(session('admin_id'))) {
return DataReturn('无权限访问,请先登录后台', -1);
}
// ...原有逻辑
}
```
#### B0-2verifier_id 改为 session 来源M-05
**现状**`TicketVerify` 接收客户端传入的 `$verifier_id`,攻击者可伪造任意身份。
**修复**:改为从 session 获取当前 admin 对应的 ShopXO 用户ID`vr_verifiers` 表获取 verifier_id。
```php
// 错误(可伪造):
$verifier_id = input('verifier_id', 0, 'intval');
// 正确(从 session 获取):
$admin_user_id = session('admin_user_info.id'); // ShopXO 后台登录用户ID
$verifier = \think\facade\Db::name('vr_verifiers')
->where('user_id', $admin_user_id)
->where('status', 1)
->find();
if (empty($verifier)) {
return DataReturn('你不是核销员,无权核销', -1);
}
$verifier_id = $verifier['id'];
```
#### B0-3ALTER TABLE bug 修复M-03
EventListener.php 中 `empty($result)` 对 PDOStatement 永远返回 falseALTER TABLE 永不执行。
**文件**`shopxo/app/plugins/vr_ticket/Event.php`(或 EventListener.php
**修复**:改用 `count($result) === 0``empty($result->fetchAll())`
---
### Phase B1 — 核心 B端核销页 ✅ 完成
> B1-1 + B1-2 + B1-3 由 subagent B1-CorePages 完成commit: `d8c45fbb8`
**目标**:建一个可用的扫码核销页面,优先满足现场核销需求。
#### B1-1admin/view/ticket/verify.html扫码核销主页面
**功能**
- 扫码按钮HTML5 MediaDevices API兼容 PC 摄像头)
- 手动输入短码/票码文本框
- 调用 `PluginsAdminUrl('vr_ticket', 'admin', 'TicketVerify')` API
- 展示核销结果(座位号、观演人姓名、商品名)
- 统计栏:今日核销数 / 待核销数 / 已核销总数
**注意**:需要先在 Hook.php 的 `AdminSidebarInit` 注册菜单项 `ticketVerify`
#### B1-2admin/view/ticket/list.html电子票列表
- 搜索:订单号/票码/观演人姓名/手机号
- 状态筛选:全部/未核销/已核销/已退款
- 商品筛选
- 每行显示:票码、观演人、座位信息、商品名、状态、时间
- 操作:查看详情
#### B1-3admin/view/ticket/detail.html票详情
- 显示票完整信息(座位/观演人/QR码/发放时间)
- 显示核销记录(如已核销)
---
### Phase B2 — 辅助管理页 ✅ 完成
> B2-1 + B2-2 + B2-3 由 subagent B2-SupportPages 完成commit: `a104f16f0`
#### B2-1核销员管理
- `admin/view/verifier/list.html`:核销员列表(关联 ShopXO 用户)
- `admin/view/verifier/save.html`:添加/编辑核销员(选择 ShopXO 用户作为关联)
#### B2-2核销记录
- `admin/view/verification/list.html`:核销历史记录,支持按核销员/日期筛选
#### B2-3座位模板管理
- `admin/view/seat_template/list.html`:座位模板列表
- `admin/view/seat_template/save.html`:座位模板编辑(参考现有的 view/venue/save.html 风格)
---
## 三、实施顺序
```
B0-1 → B0-2 → B0-3 (安全基线,并行)
B1-1 → B1-2 → B1-3 (核心核销,并行或串行)
B2-1 → B2-2 → B2-3 (辅助管理,并行)
```
---
## 四、技术约束(来自 EXPERIENCES.md
1. **视图路径**`MyView('../../../plugins/vr_ticket/admin/view/ticket/list', [...])`
2. **public_host**:控制器必须显式传递 `public_host` 给模板
3. **header/footer**:所有 admin 页面必须有 `{{:ModuleInclude('public/header')}}``{{:ModuleInclude('public/footer')}}`
4. **Vue 3 textarea**:禁止 `<textarea>[[ value ]]</textarea>`,用隐藏 input
5. **CDN**:禁止 unpkg/jsdelivr`cdn.staticfile.net` 或 ShopXO 自带文件
6. **双目录陷阱**:修改 `app/plugins/vr_ticket/static/` 后必须同步到 `public/plugins/vr_ticket/static/`
7. **AmazeUI 类名**:列表页用 `am-table am-table-striped am-table-hover am-text-middle`
8. **PHP 注释**:确保所有 `/* ... */` 闭合,避免语法错误
---
## 五、验收标准
- [x] M-06无 session('admin_id') 无法调用任何 Admin.php 接口
- [x] M-05核销记录中的 verifier_id 来自 session不可伪造
- [x] M-03ALTER TABLE bug 已修复
- [ ] B1-1PC 摄像头扫码可成功核销,显示票信息(待实际测试)
- [ ] B1-1手动输入短码可成功核销待实际测试
- [ ] B1-2电子票列表正常展示支持搜索和状态筛选待实际测试
- [ ] B1-3票详情页正常展示待实际测试
- [ ] B2-1可添加/禁用核销员(待实际测试)
- [ ] B2-2核销记录正常展示待实际测试
- [ ] 所有页面 header/footer 完整,无无限加载问题(待实际测试)
---
## 六、待确认 & 待测试
1. **ShopXO 后台 session key**:需确认 `session('admin_user_info.id')` 是正确的 ShopXO 后台登录用户 ID key。
2. **Hook.php 菜单注册**`ticket/verify.html` 已注册扫码核销菜单项,需在 ShopXO 后台确认菜单显示。
3. **TicketStats API**`verify.html` 引用了 `PluginsAdminUrl('vr_ticket', 'admin', 'TicketStats')` 获取统计数据,该方法尚未在 Admin.php 中实现,需补充。
4. **QR 码展示**`detail.html` 需确认 QR 码图片 URL 路径(`TicketService::getQrCodeUrl` 是否可被 admin 模板调用)。
## 七、Commit 记录
```
f3d102e7a feat(B0): M-06/M-05/M-03 security fixes
d8c45fbb8 feat(B1): ticket/verify + list + detail admin views
a104f16f0 feat(B2): verifier + verification + seat_template admin views
```