# 会议出勤（Meeting Attendance）E2E 测试报告

- 测试日期：2026-01-28
- 测试类型：E2E（全页面 + 关键操作）
- 执行器：AI Agent + Playwright MCP
- 浏览器：Chromium（Playwright MCP）
- 环境：本地开发环境
- 前端基址：http://localhost:3000
- 后端基址：http://localhost:3001/api/v1
- 等待策略：domcontentloaded + 条件等待
- 鉴权策略：storageState
- storageState：`testing/reports/meeting-attendance-2026-01-28-e2e/storage-state.json`
- 截图目录：`testing/reports/meeting-attendance-2026-01-28-e2e/`

## 测试范围
- 页面：Dashboard、Meetings、Meeting Detail、QR、Check-in（系统/访客）、Series、Templates、Reports、Audit Logs、Users、Teams（meetings/reports/config）、Settings
- 操作：会议创建/删除、模板创建/删除/基于模板创建会议、系列二维码下载（ZIP/Word）、签到成功/失败、审计日志查看、用户页跳转组织架构

## 环境与数据准备
- 登录账号：`itadmin@ff.com`（Administrator）
- 新建会议：
  - `cmkxm5upr000vjxegdap6mqph`（E2E Full Regression 2026-01-28 A，含出勤）
  - `cmkxmc2xd000yjxeglxjuu30n`（E2E Guest Checkin 2026-01-28 B，访客成功）
  - `cmkxmelsg0012jxeg26xhamiy`（E2E Guest NonMember 2026-01-28 C，访客失败）
  - `cmkxmxgz30016jxegqtt094x6`（E2E Hard Delete 2026-01-28，已硬删）
  - `cmkxn3i070018jxegcknucdgx`（E2E Template Meeting，模板创建会议）
- 软删会议：`cmkxjklq90003jxeg7y7rmojx`（含出勤记录，删除后变为 Cancelled）
- 系列：`E2E Series 2026-01-28`（3 实例）
- 模板：`E2E Template 2026-01-28`（保留）；`E2E Template 2026-01-28 B`（创建后删除）

## 用例明细

### E2E-28-01：Dashboard 可访问并加载
- 优先级：P0
- 前置条件：已登录
- 步骤：打开 `/meetingattendance/dashboard`
- 断言：欢迎标题与统计卡片可见
- 关联 API：页面统计（未在 07-api.md 单独列出）
- 结果：通过
- 证据截图：`testing/reports/meeting-attendance-2026-01-28-e2e/E2E-28-R27-dashboard-page.png`

### E2E-28-02：会议列表（Scheduled）二维码入口可见
- 优先级：P0
- 前置条件：存在会议二维码
- 步骤：打开 `/meetingattendance/meetings`
- 断言：会议卡片出现 `QR Codes` 按钮
- 关联 API：[001]
- 结果：通过
- 证据截图：`testing/reports/meeting-attendance-2026-01-28-e2e/E2E-28-R08-meetings-list-qr-visible.png`

### E2E-28-03：历史会议列表二维码入口可见
- 优先级：P0
- 前置条件：存在已完成会议
- 步骤：切换到 `Completed` 筛选
- 断言：会议卡片出现 `QR Codes` 按钮
- 关联 API：[001]
- 结果：通过
- 证据截图：`testing/reports/meeting-attendance-2026-01-28-e2e/E2E-28-R18-completed-list-qr-visible.png`

### E2E-28-04：历史会议二维码页可展示
- 优先级：P0
- 前置条件：存在已完成会议
- 步骤：进入某历史会议二维码页
- 断言：线上/线下二维码图片可见
- 关联 API：[003]
- 结果：通过
- 证据截图：`testing/reports/meeting-attendance-2026-01-28-e2e/E2E-28-R17-completed-list-qr-visible.png`

### E2E-28-04A：最早历史会议二维码可展示（抽检）
- 优先级：P1
- 前置条件：存在较早历史会议（起始时间 2025-10-29）
- 步骤：打开 `/meetingattendance/meetings/cmhca5gel06pby6pnd325f1b2/qr`
- 断言：线上/线下二维码图片可见
- 关联 API：[003]
- 结果：通过
- 证据截图：`testing/reports/meeting-attendance-2026-01-28-e2e/E2E-29-historical-qr-oldest.png`

### E2E-28-05：创建会议（用于硬删验证）
- 优先级：P1
- 前置条件：管理员登录
- 步骤：在 `/meetingattendance/meetings/create` 创建会议
- 断言：进入会议详情页且信息显示正确
- 关联 API：[002], [003]
- 结果：通过
- 证据截图：`testing/reports/meeting-attendance-2026-01-28-e2e/E2E-28-R24-meeting-create-for-hard-delete.png`

### E2E-28-06：会议硬删成功（无出勤）
- 优先级：P1
- 前置条件：会议 `cmkxmxgz30016jxegqtt094x6` 无出勤
- 步骤：会议详情点击 `Delete Meeting` 并确认
- 断言：提示删除成功，返回列表
- 关联 API：[005]
- 结果：通过
- 证据截图：`testing/reports/meeting-attendance-2026-01-28-e2e/E2E-28-R25-meeting-hard-delete-success.png`

### E2E-28-07：会议软删（有出勤）
- 优先级：P1
- 前置条件：会议 `cmkxjklq90003jxeg7y7rmojx` 有出勤
- 步骤：会议详情点击 `Delete Meeting` 并确认
- 断言：状态变为 `Cancelled`
- 关联 API：[005]
- 结果：通过
- 证据截图：`testing/reports/meeting-attendance-2026-01-28-e2e/E2E-28-R26-meeting-soft-delete-cancelled.png`

### E2E-28-08：系列会议页可访问
- 优先级：P1
- 前置条件：存在系列数据
- 步骤：打开 `/meetingattendance/series`
- 断言：系列卡片与实例列表可见
- 关联 API：[017]
- 结果：通过
- 证据截图：`testing/reports/meeting-attendance-2026-01-28-e2e/E2E-28-R28-series-page.png`

### E2E-28-09：系列二维码 ZIP 下载成功
- 优先级：P2
- 前置条件：系列 `E2E Series 2026-01-28` 存在
- 步骤：点击 ZIP 下载并确认
- 断言：出现 `QR codes downloaded` 提示
- 关联 API：前端导出（未在 07-api.md 单独列出）
- 结果：通过
- 证据截图：`testing/reports/meeting-attendance-2026-01-28-e2e/E2E-28-R29-series-download-zip-success.png`

### E2E-28-10：系列二维码 Word 下载成功
- 优先级：P2
- 前置条件：系列 `E2E Series 2026-01-28` 存在
- 步骤：点击 Word 下载并确认
- 断言：出现 `Word document generated` 提示
- 关联 API：前端导出（未在 07-api.md 单独列出）
- 结果：通过
- 证据截图：`testing/reports/meeting-attendance-2026-01-28-e2e/E2E-28-R30-series-download-word-success.png`

### E2E-28-11：模板页可访问
- 优先级：P2
- 前置条件：存在模板
- 步骤：打开 `/meetingattendance/templates`
- 断言：模板卡片可见
- 关联 API：[030]
- 结果：通过
- 证据截图：`testing/reports/meeting-attendance-2026-01-28-e2e/E2E-28-R31-templates-page.png`

### E2E-28-12：模板创建成功
- 优先级：P2
- 前置条件：管理员登录
- 步骤：创建模板 `E2E Template 2026-01-28 B`
- 断言：提示 `Template created successfully`
- 关联 API：[030]
- 结果：通过
- 证据截图：`testing/reports/meeting-attendance-2026-01-28-e2e/E2E-28-R37-template-create-success.png`

### E2E-28-13：基于模板创建会议
- 优先级：P2
- 前置条件：模板存在
- 步骤：点击 `Create Meeting` 输入时间
- 断言：进入会议详情页
- 关联 API：[002], [033]
- 结果：通过
- 证据截图：`testing/reports/meeting-attendance-2026-01-28-e2e/E2E-28-R32-template-create-meeting.png`

### E2E-28-14：模板删除成功
- 优先级：P2
- 前置条件：模板 `E2E Template 2026-01-28 B` 存在
- 步骤：删除模板并确认
- 断言：模板卡片移除
- 关联 API：[032]
- 结果：通过
- 证据截图：`testing/reports/meeting-attendance-2026-01-28-e2e/E2E-28-R38-template-delete-success.png`

### E2E-28-15：报表页可访问
- 优先级：P1
- 前置条件：存在会议数据
- 步骤：打开 `/meetingattendance/reports`
- 断言：单场/系列报表入口可见
- 关联 API：[045], [046]
- 结果：通过
- 证据截图：`testing/reports/meeting-attendance-2026-01-28-e2e/E2E-28-R33-reports-page.png`

### E2E-28-16：审计日志页可访问
- 优先级：P2
- 前置条件：存在审计日志
- 步骤：打开 `/meetingattendance/audit-logs`
- 断言：统计卡片与日志列表可见
- 关联 API：[047], [048]
- 结果：通过
- 证据截图：`testing/reports/meeting-attendance-2026-01-28-e2e/E2E-28-R34-audit-logs-page.png`

### E2E-28-16A：审计日志筛选（资源类型 + 日期区间）
- 优先级：P1
- 前置条件：存在 2026-01-27~2026-01-28 的会议类审计日志
- 步骤：打开 `/meetingattendance/audit-logs` → 展开 Filters → 设置 `Resource Type = MEETING`、`Start Date = 2026-01-27`、`End Date = 2026-01-28`
- 断言：统计卡片数量与日志列表均显示非 0（本次为 7 条）
- 关联 API：[047], [048]
- 结果：通过
- 证据截图：`testing/reports/meeting-attendance-2026-01-28-e2e/E2E-29-audit-filter-success.png`

### E2E-28-16B：审计日志-出勤状态变更记录可见
- 优先级：P1
- 前置条件：存在出勤状态更新审计日志
- 步骤：打开 `/meetingattendance/audit-logs` → 展开 Filters → 设置 `Action Type = ATTENDANCE_UPDATE`、`Resource Type = ATTENDANCE`
- 断言：列表出现 `Update Attendance` 且变更详情包含 `Absent → Online` 等出勤状态变更
- 关联 API：[047], [048]
- 结果：通过
- 证据截图：`testing/reports/meeting-attendance-2026-01-28-e2e/E2E-29-audit-attendance-update.png`

### E2E-28-16C：触发出勤状态变更并验证审计日志
- 优先级：P1
- 前置条件：会议 `cmhc9sct8017zy6pny1dgzwqq` 存在出勤人员
- 步骤：
  1. 打开 `/meetingattendance/meetings/cmhc9sct8017zy6pny1dgzwqq`
  2. 将 `Aaron Ma (aaron.ma@ff.com)` 出勤状态从 `Online` 改为 `Absent`，再改回 `Online`
  3. 打开 `/meetingattendance/audit-logs` 查看最新记录
- 断言：审计日志出现 `ATTENDANCE UPDATE`，详情包含 `Absent → Online` 且会议为 `FX EC Meeting - Session 14 (01/29/2026)`
- 关联 API：[010], [047], [048]
- 结果：通过
- 证据截图：`testing/reports/meeting-attendance-2026-01-28-e2e/E2E-29-audit-attendance-update-live.png`

### E2E-28-21：访客签到成功（名单内）
- 优先级：P0
- 前置条件：会议 `cmkxrd4vg000cjxvqwexkd5qg` 已添加 `Aaron Ma (aaron.ma@ff.com)`，且处于可签到时间窗
- 步骤：打开 `/meetingattendance/checkin/guest?meeting=cmkxrd4vg000cjxvqwexkd5qg&type=online` → 输入姓名/邮箱 → 提交
- 断言：出现 `Check-in Successful` 成功页
- 关联 API：[014]
- 结果：通过
- 证据截图：`testing/reports/meeting-attendance-2026-01-28-e2e/E2E-29-guest-checkin-success.png`

### E2E-28-22：访客签到设备限制（同设备仅一次）
- 优先级：P1
- 前置条件：同一设备已在会议 `cmkxrd4vg000cjxvqwexkd5qg` 完成一次签到
- 步骤：再次打开访客签到页并提交
- 断言：提示 `This device has already checked in for this meeting.`
- 关联 API：[014]
- 结果：通过
- 证据截图：`testing/reports/meeting-attendance-2026-01-28-e2e/E2E-29-guest-device-limit.png`

### E2E-28-23：访客不在名单禁止签到
- 优先级：P0
- 前置条件：会议 `cmkxr62b90007jxvq1erhecre` 有名单，但访客不在名单内且处于可签到时间窗
- 步骤：打开 `/meetingattendance/checkin/guest?meeting=cmkxr62b90007jxvq1erhecre&type=online` → 输入非名单用户信息 → 提交
- 断言：提示 `Not in attendee list`
- 关联 API：[014]
- 结果：通过
- 证据截图：`testing/reports/meeting-attendance-2026-01-28-e2e/E2E-29-guest-not-in-list.png`

### E2E-28-24：签到过早拦截
- 优先级：P0
- 前置条件：会议 `cmkxrd4vg000cjxvqwexkd5qg` 开始时间为 02:00，当前时间早于可签到窗口（提前 15 分钟）
- 步骤：打开 `/meetingattendance/checkin/guest?meeting=cmkxrd4vg000cjxvqwexkd5qg&type=online`
- 断言：提示 `Check-in not yet available`，提交按钮不可用
- 关联 API：[014]
- 结果：通过
- 证据截图：`testing/reports/meeting-attendance-2026-01-28-e2e/E2E-29-early-checkin-blocked.png`

### E2E-28-25：系列会议改期（更新开始时间与时长）
- 优先级：P1
- 前置条件：系列 `E2E Series 2026-01-28` 存在且包含 3 个实例
- 步骤：在 `/meetingattendance/series` 选择该系列 → 更新开始时间为 `10:30`、时长 `45`
- 断言：提示 `Updated 3 meeting(s)`，实例时间更新为 10:30
- 关联 API：[021]
- 结果：通过
- 证据截图：`testing/reports/meeting-attendance-2026-01-28-e2e/E2E-29-series-reschedule-success.png`

### E2E-28-26：单场会议报表生成
- 优先级：P1
- 前置条件：会议 `E2E Full Regression 2026-01-28 A` 存在出勤数据
- 步骤：打开 `/meetingattendance/reports` → 选择该会议
- 断言：统计卡片与出勤分布图表加载，列表展示 1 行数据
- 关联 API：[046]
- 结果：通过
- 证据截图：`testing/reports/meeting-attendance-2026-01-28-e2e/E2E-29-report-single-meeting.png`

### E2E-28-27：系列报表生成
- 优先级：P1
- 前置条件：系列 `E2E Series 2026-01-28` 存在
- 步骤：打开 `/meetingattendance/reports` → 切换 `Series Report` → 选择该系列
- 断言：统计卡片与排名表格加载（总会议数=3）
- 关联 API：[045]
- 结果：通过
- 证据截图：`testing/reports/meeting-attendance-2026-01-28-e2e/E2E-29-report-series.png`

### E2E-28-28：会议删除审计日志记录
- 优先级：P2
- 前置条件：新建会议 `E2E Audit Delete 2026-01-28`（无出勤）
- 步骤：删除会议 → 打开 `/meetingattendance/audit-logs`
- 断言：顶部出现 `Delete Meeting` 日志，资源为 MEETING
- 关联 API：[005], [047], [048]
- 结果：通过
- 证据截图：`testing/reports/meeting-attendance-2026-01-28-e2e/E2E-29-audit-meeting-delete.png`

### E2E-28-17：用户管理页可访问
- 优先级：P2
- 前置条件：用户数据已同步
- 步骤：打开 `/meetingattendance/users`
- 断言：用户列表与过滤器可见
- 关联 API：[034]
- 结果：通过
- 证据截图：`testing/reports/meeting-attendance-2026-01-28-e2e/E2E-28-R35-users-page.png`

### E2E-28-18：用户页跳转组织架构成功
- 优先级：P2
- 前置条件：存在组织架构模块
- 步骤：点击 `Go to Organization Members`
- 断言：打开 `/organization/members`
- 关联 API：平台组织架构模块
- 结果：通过
- 证据截图：`testing/reports/meeting-attendance-2026-01-28-e2e/E2E-28-R36-organization-members-redirect.png`

### E2E-28-19：Teams 会议列表可访问
- 优先级：P2
- 前置条件：Teams 页面可用
- 步骤：打开 `/meetingattendance/teams/meetings`
- 断言：会议列表与 `QR Codes` 按钮可见
- 关联 API：Teams 页面（未在 07-api.md 单独列出）
- 结果：通过
- 证据截图：`testing/reports/meeting-attendance-2026-01-28-e2e/E2E-28-R19-teams-meetings-page.png`

### E2E-28-20：Teams 会议二维码按钮可用
- 优先级：P2
- 前置条件：Teams 会议列表存在
- 步骤：点击 `QR Codes`
- 断言：打开二维码页面并显示二维码卡片
- 结果：通过
- 证据截图：`testing/reports/meeting-attendance-2026-01-28-e2e/teams-qr-opened.png`

### E2E-28-21：Teams 报表页可访问
- 优先级：P2
- 前置条件：存在统计数据
- 步骤：打开 `/meetingattendance/teams/reports`
- 断言：统计卡片与图表容器可见
- 关联 API：[044]
- 结果：通过
- 证据截图：`testing/reports/meeting-attendance-2026-01-28-e2e/E2E-28-R21-teams-reports-page.png`

### E2E-28-22：Teams 配置页可访问
- 优先级：P3
- 前置条件：Teams 页面可用
- 步骤：打开 `/meetingattendance/teams/config`
- 断言：配置说明与保存按钮可见
- 关联 API：Teams 页面（未在 07-api.md 单独列出）
- 结果：通过
- 证据截图：`testing/reports/meeting-attendance-2026-01-28-e2e/E2E-28-R22-teams-config-page.png`

### E2E-28-23：修改密码页可访问
- 优先级：P3
- 前置条件：已登录
- 步骤：打开 `/meetingattendance/settings/change-password`
- 断言：表单字段与按钮可见
- 关联 API：页面级表单
- 结果：通过
- 证据截图：`testing/reports/meeting-attendance-2026-01-28-e2e/E2E-28-R23-settings-change-password-page.png`

### E2E-28-24：系统签到成功
- 优先级：P0
- 前置条件：会议 `cmkxm5upr000vjxegdap6mqph` 存在参会人
- 步骤：打开 `/meetingattendance/checkin?meeting=cmkxm5upr000vjxegdap6mqph&type=online`
- 断言：出现 `Check-in Successful`
- 关联 API：[013]
- 结果：通过
- 证据截图：`testing/reports/meeting-attendance-2026-01-28-e2e/E2E-28-R05-system-checkin-success.png`

### E2E-28-25：访客签到成功（名单内）
- 优先级：P0
- 前置条件：会议 `cmkxmc2xd000yjxeglxjuu30n` 已添加参会人
- 步骤：打开 `/meetingattendance/checkin/guest?meeting=cmkxmc2xd000yjxeglxjuu30n&type=online`
- 断言：出现 `Check-in Successful`
- 关联 API：[014]
- 结果：通过
- 证据截图：`testing/reports/meeting-attendance-2026-01-28-e2e/E2E-28-R06-guest-checkin-success.png`

### E2E-28-26：访客非名单签到失败
- 优先级：P0
- 前置条件：会议 `cmkxmelsg0012jxeg26xhamiy` 未包含该访客
- 步骤：访客签到提交非名单邮箱
- 断言：提示 `Not in attendee list`
- 关联 API：[014]
- 结果：通过
- 证据截图：`testing/reports/meeting-attendance-2026-01-28-e2e/E2E-28-R07-guest-checkin-fail-not-in-list.png`

### E2E-28-A1：创建会议（审计日志验证数据准备）
- 优先级：P1
- 前置条件：IT Administrator 已登录
- 步骤：创建会议 `E2E Audit Log Meeting 2026-01-28`
- 断言：会议详情页可见，标题正确
- 关联 API：[001]
- 结果：通过
- 证据截图：`testing/reports/meeting-attendance-2026-01-28-e2e/E2E-28-A1-create-meeting-success.png`

### E2E-28-A2：编辑会议（审计日志验证数据准备）
- 优先级：P1
- 前置条件：会议已创建
- 步骤：编辑描述为 `...updated`
- 断言：详情页展示更新后的描述
- 关联 API：[002]
- 结果：通过
- 证据截图：`testing/reports/meeting-attendance-2026-01-28-e2e/E2E-28-A2-edit-meeting-success.png`

### E2E-28-A3：添加参会人（审计日志验证数据准备）
- 优先级：P1
- 前置条件：会议已创建
- 步骤：添加 `itadmin@ff.com` 为参会人
- 断言：参会人数从 0 变为 1
- 关联 API：[006]
- 结果：通过
- 证据截图：`testing/reports/meeting-attendance-2026-01-28-e2e/E2E-28-A3-add-attendee-success.png`

### E2E-28-A4：系统签到成功（审计日志验证数据准备）
- 优先级：P1
- 前置条件：会议时间调整为当前可签到时段
- 步骤：打开 `/meetingattendance/checkin?meeting=cmkxo5t4y001ajxegzwvch5z9&type=online`
- 断言：出现 `Check-in Successful`
- 关联 API：[013]
- 结果：通过
- 证据截图：`testing/reports/meeting-attendance-2026-01-28-e2e/E2E-28-A4-system-checkin-success.png`

### E2E-28-A5：删除会议（有出勤 → 软删除）
- 优先级：P1
- 前置条件：会议已产生签到记录
- 步骤：点击 `Delete Meeting` 并确认
- 断言：提示无法硬删，会议状态变为 `Cancelled`
- 关联 API：[004]
- 结果：通过
- 证据截图：`testing/reports/meeting-attendance-2026-01-28-e2e/E2E-28-A5-delete-meeting-soft.png`

### E2E-28-A6：审计日志写入验证（复测）
- 优先级：P1
- 前置条件：已完成 A1-A5
- 步骤：审计日志页过滤 `Resource Type = MEETING`（不限制日期）
- 断言：出现本次会议的创建/编辑/取消日志
- 关联 API：[045]
- 结果：通过（审计日志已写入）
- 证据截图：`testing/reports/meeting-attendance-2026-01-28-e2e/E2E-28-V2-20-audit-logs-filter-meeting.png`

## 复测与补测（V2）

### 环境与数据准备（V2）
- 登录账号：`itadmin@ff.com`（Administrator）
- 新建会议：
  - `cmkxpfi4v0000jxyys6in4yh5`（E2E Audit Log Meeting V2 2026-01-28，更新描述后软删除）
  - `cmkxpy3uh000ijxyye21p06sz`（E2E System Checkin V2 2026-01-27 23:40，系统签到成功）
  - `cmkxq3pw3000njxyymu2prdwd`（E2E Guest Checkin V2 2026-01-27 23:50，访客签到成功）
  - `cmkxq8h4z000tjxyyd1qj9d62`（E2E Guest NonMember V2 2026-01-27 23:55，访客失败）
- 模板创建/删除：`E2E Template V2 2026-01-28`
- 基于模板创建会议：`cmkxpm1dx000djxyymktykajm`

### V2-01：Dashboard 可访问并加载
- 优先级：P0
- 前置条件：已登录
- 步骤：打开 `/meetingattendance/dashboard`
- 断言：欢迎标题与统计卡片可见
- 结果：通过
- 证据截图：`testing/reports/meeting-attendance-2026-01-28-e2e/E2E-28-V2-01-dashboard.png`

### V2-02：会议列表（Scheduled）二维码入口可见
- 优先级：P0
- 前置条件：存在会议二维码
- 步骤：打开 `/meetingattendance/meetings`
- 断言：会议卡片出现 `QR Codes` 按钮
- 结果：通过
- 证据截图：`testing/reports/meeting-attendance-2026-01-28-e2e/E2E-28-V2-02-meetings-list.png`

### V2-03：历史会议二维码入口可见
- 优先级：P0
- 前置条件：存在已完成会议
- 步骤：切换到 `Completed` 筛选
- 断言：会议卡片出现 `QR Codes` 按钮
- 结果：通过
- 证据截图：`testing/reports/meeting-attendance-2026-01-28-e2e/E2E-28-V2-03-meetings-completed.png`

### V2-04：历史会议二维码页可展示
- 优先级：P0
- 前置条件：存在已完成会议
- 步骤：进入二维码页
- 断言：线上/线下二维码图片可见
- 结果：通过
- 证据截图：`testing/reports/meeting-attendance-2026-01-28-e2e/E2E-28-V2-04-meeting-qr-page.png`

### V2-05：创建会议（审计日志用）
- 优先级：P1
- 前置条件：管理员登录
- 步骤：创建会议 `E2E Audit Log Meeting V2 2026-01-28`
- 断言：进入会议详情页且标题正确
- 结果：通过
- 证据截图：`testing/reports/meeting-attendance-2026-01-28-e2e/E2E-28-V2-05-meeting-created.png`

### V2-06：编辑会议成功
- 优先级：P1
- 前置条件：会议已创建
- 步骤：编辑描述并保存
- 断言：详情页展示更新后的描述
- 结果：通过
- 证据截图：`testing/reports/meeting-attendance-2026-01-28-e2e/E2E-28-V2-06-meeting-updated.png`

### V2-07：添加参会人成功
- 优先级：P1
- 前置条件：会议已创建
- 步骤：添加 `itadmin@ff.com`
- 断言：参会人数从 0 变为 1
- 结果：通过
- 证据截图：`testing/reports/meeting-attendance-2026-01-28-e2e/E2E-28-V2-07-add-attendee.png`

### V2-08：会议软删（有参会）
- 优先级：P1
- 前置条件：会议存在参会人
- 步骤：点击 `Delete Meeting` 并确认
- 断言：状态变为 `Cancelled`
- 结果：通过
- 证据截图：`testing/reports/meeting-attendance-2026-01-28-e2e/E2E-28-V2-08-meeting-cancelled.png`

### V2-09：系列会议页可访问
- 优先级：P1
- 前置条件：存在系列数据
- 步骤：打开 `/meetingattendance/series`
- 断言：系列卡片与实例列表可见
- 结果：通过
- 证据截图：`testing/reports/meeting-attendance-2026-01-28-e2e/E2E-28-V2-09-series-page.png`

### V2-10：系列二维码 ZIP 下载成功
- 优先级：P2
- 前置条件：系列存在
- 步骤：下载 ZIP 并确认
- 断言：出现 `QR codes downloaded` 提示
- 结果：通过
- 证据截图：`testing/reports/meeting-attendance-2026-01-28-e2e/E2E-28-V2-10-series-zip-success.png`

### V2-11：系列二维码 Word 下载成功
- 优先级：P2
- 前置条件：系列存在
- 步骤：下载 Word 并确认
- 断言：出现 `Word document generated` 提示
- 结果：通过
- 证据截图：`testing/reports/meeting-attendance-2026-01-28-e2e/E2E-28-V2-11-series-word-success.png`

### V2-12：模板页可访问
- 优先级：P2
- 前置条件：存在模板
- 步骤：打开 `/meetingattendance/templates`
- 断言：模板卡片可见
- 结果：通过
- 证据截图：`testing/reports/meeting-attendance-2026-01-28-e2e/E2E-28-V2-12-templates-page.png`

### V2-13：模板创建成功
- 优先级：P2
- 前置条件：管理员登录
- 步骤：创建模板 `E2E Template V2 2026-01-28`
- 断言：提示 `Template created successfully`
- 结果：通过
- 证据截图：`testing/reports/meeting-attendance-2026-01-28-e2e/E2E-28-V2-13-template-create-success.png`

### V2-14：基于模板创建会议
- 优先级：P2
- 前置条件：模板存在
- 步骤：点击 `Create Meeting` 输入时间
- 断言：进入会议详情页
- 结果：通过
- 证据截图：`testing/reports/meeting-attendance-2026-01-28-e2e/E2E-28-V2-14-template-create-meeting.png`

### V2-15：模板删除成功
- 优先级：P2
- 前置条件：模板存在
- 步骤：删除模板并确认
- 断言：模板卡片移除
- 结果：通过
- 证据截图：`testing/reports/meeting-attendance-2026-01-28-e2e/E2E-28-V2-15-template-delete-success.png`

### V2-16：报表页可访问
- 优先级：P1
- 前置条件：存在会议数据
- 步骤：打开 `/meetingattendance/reports`
- 断言：报表入口可见
- 结果：通过
- 证据截图：`testing/reports/meeting-attendance-2026-01-28-e2e/E2E-28-V2-16-reports-page.png`

### V2-17：用户管理页可访问
- 优先级：P2
- 前置条件：用户数据已同步
- 步骤：打开 `/meetingattendance/users`
- 断言：用户列表与过滤器可见
- 结果：通过
- 证据截图：`testing/reports/meeting-attendance-2026-01-28-e2e/E2E-28-V2-17-users-page.png`

### V2-18：用户页跳转组织架构成功
- 优先级：P2
- 前置条件：组织架构模块可用
- 步骤：点击 `Go to Organization Members`
- 断言：打开 `/organization/members`
- 结果：通过
- 证据截图：`testing/reports/meeting-attendance-2026-01-28-e2e/E2E-28-V2-18-organization-members-redirect.png`

### V2-19：审计日志页可访问并显示最新日志
- 优先级：P2
- 前置条件：已产生审计日志
- 步骤：打开 `/meetingattendance/audit-logs`
- 断言：日志列表出现最新 MEETING/TEMPLATE 操作
- 结果：通过
- 证据截图：`testing/reports/meeting-attendance-2026-01-28-e2e/E2E-28-V2-19-audit-logs-page.png`

### V2-20：审计日志过滤（Resource = MEETING）
- 优先级：P1
- 前置条件：存在会议操作日志
- 步骤：筛选 `Resource Type = MEETING`
- 断言：显示 MEETING CREATE/UPDATE/CANCEL 记录
- 结果：通过
- 证据截图：`testing/reports/meeting-attendance-2026-01-28-e2e/E2E-28-V2-20-audit-logs-filter-meeting.png`

### V2-21：Teams 会议列表可访问
- 优先级：P2
- 前置条件：Teams 页面可用
- 步骤：打开 `/meetingattendance/teams/meetings`
- 断言：会议列表与 `QR Codes` 按钮可见
- 结果：通过
- 证据截图：`testing/reports/meeting-attendance-2026-01-28-e2e/E2E-28-V2-21-teams-meetings-page.png`

### V2-22：Teams 会议二维码按钮可用
- 优先级：P2
- 前置条件：Teams 会议列表存在
- 步骤：点击 `QR Codes`
- 断言：打开二维码页面并显示二维码卡片
- 结果：通过
- 证据截图：`testing/reports/meeting-attendance-2026-01-28-e2e/E2E-28-V2-22-teams-qr-opened.png`

### V2-23：Teams 报表页可访问
- 优先级：P2
- 前置条件：存在统计数据
- 步骤：打开 `/meetingattendance/teams/reports`
- 断言：统计卡片与图表容器可见
- 结果：通过
- 证据截图：`testing/reports/meeting-attendance-2026-01-28-e2e/E2E-28-V2-23-teams-reports-page.png`

### V2-24：Teams 配置页可访问
- 优先级：P3
- 前置条件：Teams 页面可用
- 步骤：打开 `/meetingattendance/teams/config`
- 断言：配置说明与保存按钮可见
- 结果：通过
- 证据截图：`testing/reports/meeting-attendance-2026-01-28-e2e/E2E-28-V2-24-teams-config-page.png`

### V2-25：修改密码页可访问
- 优先级：P3
- 前置条件：已登录
- 步骤：打开 `/meetingattendance/settings/change-password`
- 断言：表单字段与按钮可见
- 结果：通过
- 证据截图：`testing/reports/meeting-attendance-2026-01-28-e2e/E2E-28-V2-25-settings-change-password.png`

### V2-26：系统签到成功
- 优先级：P0
- 前置条件：会议 `cmkxpy3uh000ijxyye21p06sz` 已添加参会人
- 步骤：打开 `/meetingattendance/checkin?meeting=cmkxpy3uh000ijxyye21p06sz&type=online`
- 断言：出现 `Check-in Successful`
- 结果：通过
- 证据截图：`testing/reports/meeting-attendance-2026-01-28-e2e/E2E-28-V2-26-system-checkin-success.png`

### V2-27：访客签到成功（名单内）
- 优先级：P0
- 前置条件：会议 `cmkxq3pw3000njxyymu2prdwd` 已添加参会人
- 步骤：访客输入 `itadmin@ff.com` 并提交
- 断言：出现 `Check-in Successful`
- 结果：通过
- 证据截图：`testing/reports/meeting-attendance-2026-01-28-e2e/E2E-28-V2-27-guest-checkin-success.png`

### V2-28：访客非名单签到失败
- 优先级：P0
- 前置条件：会议 `cmkxq8h4z000tjxyyd1qj9d62` 无参会人
- 步骤：访客输入 `nonmember@ff.com` 并提交
- 断言：提示 `Not in attendee list`
- 结果：通过
- 证据截图：`testing/reports/meeting-attendance-2026-01-28-e2e/E2E-28-V2-28-guest-checkin-fail-not-in-list.png`

### V2-29：非 MeetingManager 访问会议出勤被拒绝
- 优先级：P1
- 前置条件：本地用户 `e2e_employee2`（无角色）
- 步骤：登录后访问 `/meetingattendance/meetings`
- 断言：出现 `Permission Denied`
- 结果：通过
- 证据截图：`testing/reports/meeting-attendance-2026-01-28-e2e/E2E-29-permission-denied-meetings.png`

### V2-30：非 MeetingManager 访问报表页被拒绝
- 优先级：P1
- 前置条件：本地用户 `e2e_employee2`（无角色）
- 步骤：登录后访问 `/meetingattendance/reports`
- 断言：出现 `Permission Denied`
- 结果：通过
- 证据截图：`testing/reports/meeting-attendance-2026-01-28-e2e/E2E-29-permission-denied-reports.png`

### V2-31：非 MeetingManager 访问模板页被拒绝
- 优先级：P1
- 前置条件：本地用户 `e2e_employee2`（无角色）
- 步骤：登录后访问 `/meetingattendance/templates`
- 断言：出现 `Permission Denied`
- 结果：通过
- 证据截图：`testing/reports/meeting-attendance-2026-01-28-e2e/E2E-29-permission-denied-templates.png`

### V2-32：历史会议二维码可显示
- 优先级：P2
- 前置条件：历史会议 `cmhc9sct8017zy6pny1dgzwqq` 存在
- 步骤：打开 `/meetingattendance/meetings/cmhc9sct8017zy6pny1dgzwqq/qr`
- 断言：线上/线下二维码均可见
- 结果：通过
- 证据截图：`testing/reports/meeting-attendance-2026-01-28-e2e/E2E-29-historical-qr-present.png`

### V2-33：历史会议二维码可显示（抽检 2/3）
- 优先级：P2
- 前置条件：历史会议 `cmhc9scuz019xy6pn17ztsmpb` 存在
- 步骤：打开 `/meetingattendance/meetings/cmhc9scuz019xy6pn17ztsmpb/qr`
- 断言：线上/线下二维码均可见
- 结果：通过
- 证据截图：`testing/reports/meeting-attendance-2026-01-28-e2e/E2E-29-historical-qr-present-2.png`

### V2-34：历史会议二维码可显示（抽检 3/3）
- 优先级：P2
- 前置条件：历史会议 `cmhlac604002hy60swgnuj8xh` 存在
- 步骤：打开 `/meetingattendance/meetings/cmhlac604002hy60swgnuj8xh/qr`
- 断言：线上/线下二维码均可见
- 结果：通过
- 证据截图：`testing/reports/meeting-attendance-2026-01-28-e2e/E2E-29-historical-qr-present-3.png`

## 执行信息
- 执行时间：2026-01-28（本机）
- 执行方式：Playwright MCP 手工操作
- storageState：已使用（`storage-state.json`）
- 新增测试账号：`e2e.employee2@ff.com` / `Admin@2024`（仅本机）
- 二维码全量回写：执行 `npx dotenv -e .env -- env NODE_PATH=$(pwd)/node_modules ts-node --transpile-only --project tsconfig.json -r tsconfig-paths/register ../scripts/backend/data/regenerate-meeting-attendance-qrcodes.ts`，更新 246 条会议

## 失败与阻断
- 未发现阻断问题
- 观察：审计日志筛选日期区间问题已修复并复测通过（见 E2E-28-16A）
- 观察：历史会议二维码为空问题本次未复现（见 V2-32）
- 观察：会议列表第 1-3 页（各 10 条）均存在 `QR Codes` 按钮，未复现“缺失二维码操作按钮”问题

## 覆盖度说明
- 覆盖页面：仪表盘、会议列表/详情、二维码、系统签到、访客签到、报表、系列、模板、用户、审计日志、Teams（meetings/reports/config）、设置-改密码
- 覆盖流程：会议创建/删除、模板创建/删除/基于模板创建会议、系列二维码下载、签到成功/失败、组织架构跳转
- 未覆盖列表：用户/角色管理后台变更

## 契约一致性
- 关键路径与 `09-test-scenarios.md` 一致，未发现与 `07-api.md` 明确冲突。

## 待执行与说明
- 二维码“全量重生成并回写”已执行，已补 3 条历史会议二维码抽检用例（V2-32~V2-34）。

## 结论
- 当前 E2E 覆盖的会议出勤模块核心路径均通过，未发现阻断问题。
- 建议完成二维码回写后再做一次历史会议二维码抽检以闭环。

## 资产引用
- 截图目录：`testing/reports/meeting-attendance-2026-01-28-e2e/`
