|
@@ -0,0 +1,364 @@
|
|
|
|
|
+# Story 13.12: 数据统计页测试与功能修复
|
|
|
|
|
+
|
|
|
|
|
+Status: ready-for-dev
|
|
|
|
|
+
|
|
|
|
|
+## 元数据
|
|
|
|
|
+- Epic: Epic 13 - 跨端数据同步测试
|
|
|
|
|
+- 状态: ready-for-dev
|
|
|
|
|
+- 优先级: P1
|
|
|
|
|
+- 故事点: 8
|
|
|
|
|
+
|
|
|
|
|
+## 用户故事
|
|
|
|
|
+
|
|
|
|
|
+作为企业管理员,我在企业小程序的数据统计页能查看各种统计数据,包括在职人数、平均薪资、在职率、新增人数等,并且可以通过年份和月份筛选器查看不同时期的统计数据。统计数据应该从后台 API 动态获取,而非硬编码。
|
|
|
|
|
+
|
|
|
|
|
+## 验收标准
|
|
|
|
|
+
|
|
|
|
|
+### AC 1: 数据统计页可访问性和 UI 验证
|
|
|
|
|
+**Given** 用户已登录企业小程序
|
|
|
|
|
+**When** 用户点击底部导航的"数据"tab
|
|
|
|
|
+**Then** 应能成功导航到数据统计页
|
|
|
|
|
+**And** 页面应显示筛选器区域(年份选择器、月份选择器)
|
|
|
|
|
+**And** 页面应显示 4 个统计卡片(在职人数、平均薪资、在职率、新增人数)
|
|
|
|
|
+**And** 页面应显示 6 个统计图表(残疾类型分布、性别分布、年龄分布、户籍省份分布、在职状态统计、薪资分布)
|
|
|
|
|
+
|
|
|
|
|
+### AC 2: 筛选器功能验证(修复后)
|
|
|
|
|
+**Given** 用户在数据统计页
|
|
|
|
|
+**When** 用户选择年份(如 2026)
|
|
|
|
|
+**And** 用户选择月份(如 1月)
|
|
|
|
|
+**Then** 页面应重新获取该年月的统计数据
|
|
|
|
|
+**And** 统计卡片应显示更新后的数据
|
|
|
|
|
+**And** 统计图表应显示更新后的数据
|
|
|
|
|
+
|
|
|
|
|
+### AC 3: 统计卡片数据验证(修复后)
|
|
|
|
|
+**Given** 用户在数据统计页
|
|
|
|
|
+**When** 页面加载完成
|
|
|
|
|
+**Then** 统计卡片应显示从 API 获取的真实数据
|
|
|
|
|
+**And** "在职人数"应显示当前在职人员总数
|
|
|
|
|
+**And** "平均薪资"应显示所有在职人员的平均薪资
|
|
|
|
|
+**And** "在职率"应显示在职人数占总人数的百分比
|
|
|
|
|
+**And** "新增人数"应显示本月新增的人员数
|
|
|
|
|
+**And** 每个统计卡片应显示与上月对比的数据
|
|
|
|
|
+
|
|
|
|
|
+### AC 4: 统计图表数据验证(修复后)
|
|
|
|
|
+**Given** 用户在数据统计页
|
|
|
|
|
+**When** 页面加载完成
|
|
|
|
|
+**Then** "残疾类型分布"图表应显示各类残疾的人数分布
|
|
|
|
|
+**And** "性别分布"图表应显示男女人数分布
|
|
|
|
|
+**And** "年龄分布"图表应显示各年龄段人数分布
|
|
|
|
|
+**And** "户籍省份分布"图表应显示各省份人数分布
|
|
|
|
|
+**And** "在职状态统计"图表应显示各种工作状态的人数分布
|
|
|
|
|
+**And** "薪资分布"图表应显示各薪资区间的人数分布
|
|
|
|
|
+
|
|
|
|
|
+### AC 5: API 支持年月查询参数(修复)
|
|
|
|
|
+**Given** 数据统计 API 端点已实现
|
|
|
|
|
+**When** 前端请求统计数据时传递 year 和 month 参数
|
|
|
|
|
+**Then** API 应返回该年月的统计数据
|
|
|
|
|
+**And** 如果未传递参数,应返回当前年月的统计数据
|
|
|
|
|
+
|
|
|
|
|
+## 任务
|
|
|
|
|
+
|
|
|
|
|
+### 任务 0: Bug 修复 - 统计卡片数据硬编码问题
|
|
|
|
|
+- [ ] 修改 `yongren-statistics-ui` 包中的统计卡片组件
|
|
|
|
|
+- [ ] 将硬编码的数据改为从 API 获取
|
|
|
|
|
+- [ ] 确保 API 调用正确处理响应数据
|
|
|
|
|
+
|
|
|
|
|
+### 任务 1: Bug 修复 - API 支持年月查询参数
|
|
|
|
|
+- [ ] 修改 `statistics-module` 中的 API 路由
|
|
|
|
|
+- [ ] 为所有统计 API 端点添加 year 和 month 查询参数支持
|
|
|
|
|
+ - `/api/statistics/employment-count`
|
|
|
|
|
+ - `/api/statistics/average-salary`
|
|
|
|
|
+ - `/api/statistics/employment-rate`
|
|
|
|
|
+ - `/api/statistics/new-count`
|
|
|
|
|
+ - `/api/statistics/disability-type-distribution`
|
|
|
|
|
+ - `/api/statistics/gender-distribution`
|
|
|
|
|
+- [ ] 更新 API schema 以支持可选的 year 和 month 参数
|
|
|
|
|
+- [ ] 如果未传递参数,默认使用当前年月
|
|
|
|
|
+
|
|
|
|
|
+### 任务 2: Bug 修复 - 筛选器连接到数据刷新逻辑
|
|
|
|
|
+- [ ] 修改筛选器组件,监听年份和月份的变化
|
|
|
|
|
+- [ ] 当筛选器值变化时,触发数据重新获取
|
|
|
|
|
+- [ ] 传递选中的年月参数到 API 请求
|
|
|
|
|
+- [ ] 显示加载状态,直到数据返回
|
|
|
|
|
+
|
|
|
|
|
+### 任务 3: 准备 Page Object
|
|
|
|
|
+- [ ] 在 `enterprise-mini.page.ts` 中添加数据统计页相关方法:
|
|
|
|
|
+ - `navigateToStatisticsPage()`
|
|
|
|
|
+ - `selectYear(year: number)`
|
|
|
|
|
+ - `selectMonth(month: number)`
|
|
|
|
|
+ - `getStatisticsCards()`
|
|
|
|
|
+ - `expectStatisticsCardData(cardName: string, expected: any)`
|
|
|
|
|
+ - `getStatisticsCharts()`
|
|
|
|
|
+ - `expectChartData(chartName: string, expected: any)`
|
|
|
|
|
+
|
|
|
|
|
+### 任务 4: 创建 E2E 测试文件
|
|
|
|
|
+- [ ] 创建 `web/tests/e2e/specs/cross-platform/statistics-page-validation.spec.ts`
|
|
|
|
|
+
|
|
|
|
|
+### 任务 5: 实现测试用例 - AC1 可访问性和 UI 验证
|
|
|
|
|
+- [ ] 测试:验证数据统计页可以正常访问
|
|
|
|
|
+- [ ] 测试:验证筛选器 UI 元素存在
|
|
|
|
|
+- [ ] 测试:验证 4 个统计卡片显示
|
|
|
|
|
+- [ ] 测试:验证 6 个统计图表显示
|
|
|
|
|
+
|
|
|
|
|
+### 任务 6: 实现测试用例 - AC2 筛选器功能验证(修复后)
|
|
|
|
|
+- [ ] 测试:选择年份后数据更新
|
|
|
|
|
+- [ ] 测试:选择月份后数据更新
|
|
|
|
|
+- [ ] 测试:筛选器变化后显示加载状态
|
|
|
|
|
+
|
|
|
|
|
+### 任务 7: 实现测试用例 - AC3 统计卡片数据验证(修复后)
|
|
|
|
|
+- [ ] 测试:验证在职人数数据正确性
|
|
|
|
|
+- [ ] 测试:验证平均薪资数据正确性
|
|
|
|
|
+- [ ] 测试:验证在职率数据正确性
|
|
|
|
|
+- [ ] 测试:验证新增人数数据正确性
|
|
|
|
|
+- [ ] 测试:验证月度对比数据显示
|
|
|
|
|
+
|
|
|
|
|
+### 任务 8: 实现测试用例 - AC4 统计图表数据验证(修复后)
|
|
|
|
|
+- [ ] 测试:验证残疾类型分布图表数据
|
|
|
|
|
+- [ ] 测试:验证性别分布图表数据
|
|
|
|
|
+- [ ] 测试:验证年龄分布图表数据
|
|
|
|
|
+- [ ] 测试:验证户籍省份分布图表数据
|
|
|
|
|
+- [ ] 测试:验证在职状态统计图表数据
|
|
|
|
|
+- [ ] 测试:验证薪资分布图表数据
|
|
|
|
|
+
|
|
|
|
|
+### 任务 9: 实现测试用例 - AC5 API 年月参数验证
|
|
|
|
|
+- [ ] 测试:验证 API 不传参数时返回当前年月数据
|
|
|
|
|
+- [ ] 测试:验证 API 传递年月参数时返回对应数据
|
|
|
|
|
+- [ ] 测试:验证边界情况(无效年月参数)
|
|
|
|
|
+
|
|
|
|
|
+### 任务 10: 集成测试与稳定性验证
|
|
|
|
|
+- [ ] 测试:完整的数据统计页用户流程
|
|
|
|
|
+- [ ] 测试:快速切换年月的边界情况
|
|
|
|
|
+- [ ] 测试:无数据时的显示状态
|
|
|
|
|
+- [ ] 稳定性验证:连续运行 10 次,100% 通过
|
|
|
|
|
+
|
|
|
|
|
+## Dev Notes
|
|
|
|
|
+
|
|
|
|
|
+### Epic 13 背景和依赖
|
|
|
|
|
+
|
|
|
|
|
+**Epic 13: 跨端数据同步测试 (Epic E)**
|
|
|
|
|
+
|
|
|
|
|
+- **目标**: 验证后台操作后小程序端的数据同步,覆盖完整的业务流程
|
|
|
|
|
+- **业务分组**: Epic E(跨端数据同步测试)
|
|
|
|
|
+- **背景**: 真实用户旅程跨越管理后台和小程序,需要验证数据同步的正确性和时效性
|
|
|
|
|
+- **依赖**:
|
|
|
|
|
+ - Epic 10: ✅ 已完成(订单管理 E2E 测试)
|
|
|
|
|
+ - Epic 12: 🔄 进行中(小程序登录测试)
|
|
|
|
|
+
|
|
|
|
|
+### 数据统计页 URL
|
|
|
|
|
+
|
|
|
|
|
+`/mini/#/mini/pages/yongren/statistics/index`
|
|
|
|
|
+
|
|
|
|
|
+### 数据统计页字段清单
|
|
|
|
|
+
|
|
|
|
|
+#### 筛选功能
|
|
|
|
|
+- 年份选择器:2022-2026
|
|
|
|
|
+- 月份选择器:1-12月
|
|
|
|
|
+
|
|
|
|
|
+#### 统计卡片(4个)
|
|
|
|
|
+- 在职人数:count_employed,带月度对比
|
|
|
|
|
+- 平均薪资:avg_salary,带月度对比
|
|
|
|
|
+- 在职率:employment_rate,带月度对比
|
|
|
|
|
+- 新增人数:count_new_month,带月度对比
|
|
|
|
|
+
|
|
|
|
|
+#### 统计图表(6个)
|
|
|
|
|
+- 残疾类型分布:disabilityType(柱状图)
|
|
|
|
|
+- 性别分布:gender(柱状图)
|
|
|
|
|
+- 年龄分布:age(饼图)
|
|
|
|
|
+- 户籍省份分布:province(条形图)
|
|
|
|
|
+- 在职状态统计:employmentStatus(环形图)
|
|
|
|
|
+- 薪资分布:salary(条形图)
|
|
|
|
|
+
|
|
|
|
|
+### 相关文件
|
|
|
|
|
+- 页面源码: `mini/src/pages/yongren/statistics/index.tsx`
|
|
|
|
|
+- 统计UI包: `mini-ui-packages/yongren-statistics-ui/`
|
|
|
|
|
+- API 路由: `allin-packages/statistics-module/src/routes/statistics.routes.ts`
|
|
|
|
|
+- API Schema: `allin-packages/statistics-module/src/schemas/statistics.schema.ts`
|
|
|
|
|
+
|
|
|
|
|
+### 已知问题
|
|
|
|
|
+
|
|
|
|
|
+1. **统计卡片数据硬编码**
|
|
|
|
|
+ - 当前状态:数据是硬编码在组件中
|
|
|
|
|
+ - 影响:显示的数据不是真实的统计数据
|
|
|
|
|
+ - 修复方案:调用 API 获取真实数据
|
|
|
|
|
+
|
|
|
|
|
+2. **API 不支持年月查询参数**
|
|
|
|
|
+ - 当前状态:API 端点不接受 year 和 month 参数
|
|
|
|
|
+ - 影响:无法按年月筛选统计数据
|
|
|
|
|
+ - 修复方案:为所有统计 API 添加 year 和 month 查询参数支持
|
|
|
|
|
+
|
|
|
|
|
+3. **筛选器未连接到数据刷新逻辑**
|
|
|
|
|
+ - 当前状态:切换年份和月份不会触发数据刷新
|
|
|
|
|
+ - 影响:筛选器功能无效
|
|
|
|
|
+ - 修复方案:监听筛选器变化并触发数据重新获取
|
|
|
|
|
+
|
|
|
|
|
+### 测试开发流程(Playwright MCP 持续验证)
|
|
|
|
|
+
|
|
|
|
|
+本 Story 采用 **Playwright MCP 持续验证**的测试开发流程:
|
|
|
|
|
+
|
|
|
|
|
+1. **即时验证**: 在开发过程中立即使用 Playwright MCP 验证,不等到专门的 E2E Story
|
|
|
|
|
+2. **持续反馈**: 每完成一个功能模块立即验证,快速发现问题
|
|
|
|
|
+3. **减少返工**: 早期发现问题可以减少后期返工成本
|
|
|
|
|
+
|
|
|
|
|
+**任务流程**:
|
|
|
|
|
+```
|
|
|
|
|
+任务 0-2 (Bug 修复) → 任务 3 (Page Object) → 任务 4-9 (E2E 测试) → 任务 10 (稳定性验证)
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+### Page Object 设计
|
|
|
|
|
+
|
|
|
|
|
+**EnterpriseMiniPage 扩展方法**:
|
|
|
|
|
+```typescript
|
|
|
|
|
+// 导航到数据统计页
|
|
|
|
|
+async navigateToStatisticsPage(): Promise<void>
|
|
|
|
|
+
|
|
|
|
|
+// 筛选器操作
|
|
|
|
|
+async selectYear(year: number): Promise<void>
|
|
|
|
|
+async selectMonth(month: number): Promise<void>
|
|
|
|
|
+
|
|
|
|
|
+// 获取统计卡片数据
|
|
|
|
|
+async getStatisticsCards(): Promise<StatisticsCardData[]>
|
|
|
|
|
+async expectStatisticsCardData(cardName: string, expected: any): Promise<void>
|
|
|
|
|
+
|
|
|
|
|
+// 获取统计图表数据
|
|
|
|
|
+async getStatisticsCharts(): Promise<StatisticsChartData[]>
|
|
|
|
|
+async expectChartData(chartName: string, expected: any): Promise<void>
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+### E2E 测试用例设计
|
|
|
|
|
+
|
|
|
|
|
+**AC1: 可访问性和 UI 验证**
|
|
|
|
|
+```typescript
|
|
|
|
|
+test('应该能够访问数据统计页', async ({ enterpriseMiniPage }) => {
|
|
|
|
|
+ await enterpriseMiniPage.navigateToStatisticsPage();
|
|
|
|
|
+ await expect(enterpriseMiniPage.page).toHaveURL(/\/statistics/);
|
|
|
|
|
+});
|
|
|
|
|
+
|
|
|
|
|
+test('应该显示所有统计卡片和图表', async ({ enterpriseMiniPage }) => {
|
|
|
|
|
+ await enterpriseMiniPage.navigateToStatisticsPage();
|
|
|
|
|
+ // 验证 4 个统计卡片
|
|
|
|
|
+ await expect(enterpriseMiniPage.page.getByTestId('card-count-employed')).toBeVisible();
|
|
|
|
|
+ await expect(enterpriseMiniPage.page.getByTestId('card-avg-salary')).toBeVisible();
|
|
|
|
|
+ await expect(enterpriseMiniPage.page.getByTestId('card-employment-rate')).toBeVisible();
|
|
|
|
|
+ await expect(enterpriseMiniPage.page.getByTestId('card-count-new-month')).toBeVisible();
|
|
|
|
|
+ // 验证 6 个统计图表
|
|
|
|
|
+ await expect(enterpriseMiniPage.page.getByTestId('chart-disability-type')).toBeVisible();
|
|
|
|
|
+ await expect(enterpriseMiniPage.page.getByTestId('chart-gender')).toBeVisible();
|
|
|
|
|
+ await expect(enterpriseMiniPage.page.getByTestId('chart-age')).toBeVisible();
|
|
|
|
|
+ await expect(enterpriseMiniPage.page.getByTestId('chart-province')).toBeVisible();
|
|
|
|
|
+ await expect(enterpriseMiniPage.page.getByTestId('chart-employment-status')).toBeVisible();
|
|
|
|
|
+ await expect(enterpriseMiniPage.page.getByTestId('chart-salary')).toBeVisible();
|
|
|
|
|
+});
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+**AC2: 筛选器功能验证**
|
|
|
|
|
+```typescript
|
|
|
|
|
+test('选择年份后应更新统计数据', async ({ enterpriseMiniPage }) => {
|
|
|
|
|
+ await enterpriseMiniPage.navigateToStatisticsPage();
|
|
|
|
|
+ await enterpriseMiniPage.selectYear(2025);
|
|
|
|
|
+ // 验证数据已更新
|
|
|
|
|
+ const cards = await enterpriseMiniPage.getStatisticsCards();
|
|
|
|
|
+ expect(cards).toHaveLength(4);
|
|
|
|
|
+});
|
|
|
|
|
+
|
|
|
|
|
+test('选择月份后应更新统计数据', async ({ enterpriseMiniPage }) => {
|
|
|
|
|
+ await enterpriseMiniPage.navigateToStatisticsPage();
|
|
|
|
|
+ await enterpriseMiniPage.selectMonth(12);
|
|
|
|
|
+ // 验证数据已更新
|
|
|
|
|
+ const cards = await enterpriseMiniPage.getStatisticsCards();
|
|
|
|
|
+ expect(cards).toHaveLength(4);
|
|
|
|
|
+});
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+### API 修复方案
|
|
|
|
|
+
|
|
|
|
|
+**添加年月查询参数支持**:
|
|
|
|
|
+```typescript
|
|
|
|
|
+// 更新 API Schema
|
|
|
|
|
+export const statisticsQuerySchema = z.object({
|
|
|
|
|
+ year: z.coerce.number().min(2020).max(2030).optional(),
|
|
|
|
|
+ month: z.coerce.number().min(1).max(12).optional(),
|
|
|
|
|
+});
|
|
|
|
|
+
|
|
|
|
|
+// 更新路由处理器
|
|
|
|
|
+app.get('/api/statistics/employment-count', async (c) => {
|
|
|
|
|
+ const { year, month } = c.req.query();
|
|
|
|
|
+ // 如果未传递参数,使用当前年月
|
|
|
|
|
+ const queryYear = year || new Date().getFullYear();
|
|
|
|
|
+ const queryMonth = month || new Date().getMonth() + 1;
|
|
|
|
|
+ // ... 查询逻辑
|
|
|
|
|
+});
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+### 前端修复方案
|
|
|
|
|
+
|
|
|
|
|
+**连接筛选器到数据刷新**:
|
|
|
|
|
+```typescript
|
|
|
|
|
+// 监听筛选器变化
|
|
|
|
|
+useEffect(() => {
|
|
|
|
|
+ if (selectedYear && selectedMonth) {
|
|
|
|
|
+ fetchStatisticsData(selectedYear, selectedMonth);
|
|
|
|
|
+ }
|
|
|
|
|
+}, [selectedYear, selectedMonth]);
|
|
|
|
|
+
|
|
|
|
|
+// 获取统计数据
|
|
|
|
|
+const fetchStatisticsData = async (year: number, month: number) => {
|
|
|
|
|
+ setLoading(true);
|
|
|
|
|
+ try {
|
|
|
|
|
+ const data = await api.getStatistics({ year, month });
|
|
|
|
|
+ setStatisticsData(data);
|
|
|
|
|
+ } catch (error) {
|
|
|
|
|
+ console.error('获取统计数据失败:', error);
|
|
|
|
|
+ } finally {
|
|
|
|
|
+ setLoading(false);
|
|
|
|
|
+ }
|
|
|
|
|
+};
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+### 参考文档
|
|
|
|
|
+
|
|
|
|
|
+**架构文档**:
|
|
|
|
|
+- `_bmad-output/planning-artifacts/epics.md#Epic 13`
|
|
|
|
|
+- `_bmad-output/project-context.md`
|
|
|
|
|
+- `docs/standards/e2e-radix-testing.md`
|
|
|
|
|
+
|
|
|
|
|
+**相关 Story 文档**:
|
|
|
|
|
+- `13-1-order-create-sync.md` (跨端测试模式参考)
|
|
|
|
|
+- `12-4-enterprise-mini-page-object.md` (企业小程序 Page Object)
|
|
|
|
|
+- `12-5-enterprise-mini-login.md` (企业小程序登录测试)
|
|
|
|
|
+
|
|
|
|
|
+## Dev Agent Record
|
|
|
|
|
+
|
|
|
|
|
+### Agent Model Used
|
|
|
|
|
+
|
|
|
|
|
+_Created by user request_
|
|
|
|
|
+
|
|
|
|
|
+### Debug Log References
|
|
|
|
|
+
|
|
|
|
|
+_Implementation phase - no debug yet_
|
|
|
|
|
+
|
|
|
|
|
+### Completion Notes List
|
|
|
|
|
+
|
|
|
|
|
+_Story 13.12 ready for development_
|
|
|
|
|
+
|
|
|
|
|
+### File List
|
|
|
|
|
+
|
|
|
|
|
+**新建的文件**:
|
|
|
|
|
+- `_bmad-output/implementation-artifacts/13-12-statistics-page-validation.md` - Story 文档
|
|
|
|
|
+
|
|
|
|
|
+**待创建的文件**:
|
|
|
|
|
+- `web/tests/e2e/specs/cross-platform/statistics-page-validation.spec.ts` - E2E 测试文件
|
|
|
|
|
+
|
|
|
|
|
+**待修改的文件**:
|
|
|
|
|
+- `mini/src/pages/yongren/statistics/index.tsx` - 数据统计页面
|
|
|
|
|
+- `mini-ui-packages/yongren-statistics-ui/` - 统计 UI 组件
|
|
|
|
|
+- `allin-packages/statistics-module/src/routes/statistics.routes.ts` - API 路由
|
|
|
|
|
+- `allin-packages/statistics-module/src/schemas/statistics.schema.ts` - API Schema
|
|
|
|
|
+- `web/tests/e2e/pages/mini/enterprise-mini.page.ts` - Page Object 扩展
|
|
|
|
|
+
|
|
|
|
|
+## Change Log
|
|
|
|
|
+
|
|
|
|
|
+- 2026-01-14: Story 13.12 创建完成
|
|
|
|
|
+ - 数据统计页测试与功能修复需求
|
|
|
|
|
+ - 5 个验收标准(AC)
|
|
|
|
|
+ - 11 个任务(包含 3 个 Bug 修复任务)
|
|
|
|
|
+ - 状态:ready-for-dev
|