|
|
@@ -24,7 +24,7 @@ Ready
|
|
|
- [ ] 实现页面标题和筛选条件区域
|
|
|
- [ ] 添加图表加载状态和错误提示
|
|
|
- [ ] 任务2:实现残疾类型分布图表(AC:2)
|
|
|
- - [ ] 集成数据统计API(史诗012提供)
|
|
|
+ - [ ] 集成数据统计API(@d8d/allin-statistics-module提供)
|
|
|
- [ ] 实现饼图或环形图展示残疾类型分布
|
|
|
- [ ] 添加图例和百分比显示
|
|
|
- [ ] 支持图表点击交互(查看详情)
|
|
|
@@ -71,19 +71,144 @@ Ready
|
|
|
- 011.004(订单管理):统计可能涉及订单数据,Navbar集成和页面结构规范
|
|
|
|
|
|
### API规范
|
|
|
-**数据统计API**(史诗012提供):
|
|
|
-- 残疾类型统计接口
|
|
|
-- 性别年龄统计接口
|
|
|
-- 地域分布统计接口
|
|
|
-- 时间趋势统计接口
|
|
|
+**数据统计API**(statistics模块):
|
|
|
+- **实现状态**:后端`@d8d/allin-statistics-module`已实现6个分布统计API,均为企业专用版本。前端`@d8d/yongren-statistics-ui`包目前只有占位符API客户端,需要按照故事实现完整的API客户端集成。
|
|
|
+- **架构说明**:按照史诗011的mini-ui-packages架构,API客户端在各UI包内创建。数据统计API客户端应在`@d8d/yongren-statistics-ui`包内创建,而非在`mini/src/api.ts`中统一注册。
|
|
|
+- **后端路由类型**:从`@d8d/allin-statistics-module`导入`statisticsRoutes`类型定义
|
|
|
+- **路径前缀**:`/api/v1/yongren/statistics`(企业专用版本,通过`enterpriseAuthMiddleware`中间件保护)
|
|
|
+- **主要接口**(6个分布统计接口,均为企业专用版本):
|
|
|
+ - `GET /disability-type-distribution` - 残疾类型分布统计接口
|
|
|
+ - 查询参数:`companyId?`(企业ID,可选。如未提供,从认证用户的token中获取)
|
|
|
+ - `GET /gender-distribution` - 性别分布统计接口
|
|
|
+ - 查询参数:`companyId?`(企业ID,可选)
|
|
|
+ - `GET /age-distribution` - 年龄分布统计接口
|
|
|
+ - 查询参数:`companyId?`(企业ID,可选)
|
|
|
+ - `GET /household-distribution` - 户籍分布统计接口
|
|
|
+ - 查询参数:`companyId?`(企业ID,可选)
|
|
|
+ - `GET /job-status-distribution` - 在职状态分布统计接口
|
|
|
+ - 查询参数:`companyId?`(企业ID,可选)
|
|
|
+ - `GET /salary-distribution` - 薪资分布统计接口
|
|
|
+ - 查询参数:`companyId?`(企业ID,可选)
|
|
|
+- **安全要求**:所有API通过`enterpriseAuthMiddleware`中间件保护,自动验证企业用户权限,确保数据安全隔离。
|
|
|
|
|
|
-**企业统计API**(史诗012提供):
|
|
|
-- 企业维度数据统计接口
|
|
|
-- 实时数据更新接口
|
|
|
+**企业专用数据统计API客户端创建**:
|
|
|
+- **实现状态**:`@d8d/yongren-statistics-ui`包目前只有占位符API客户端,需要按照本故事实现完整的API客户端。
|
|
|
+- **架构模式**:参考`@d8d/yongren-order-management-ui`包的企业专用API客户端实现模式,在UI包内创建RPC客户端。
|
|
|
+- **客户端创建示例**:
|
|
|
+ ```typescript
|
|
|
+ // 文件:mini-ui-packages/yongren-statistics-ui/src/api/enterpriseStatisticsClient.ts
|
|
|
+ import type { statisticsRoutes } from '@d8d/allin-statistics-module';
|
|
|
+ import { rpcClient } from '@d8d/mini-shared-ui-components/utils/rpc/rpc-client';
|
|
|
+
|
|
|
+ // 注意:企业专用数据统计API通过enterpriseAuthMiddleware中间件保护,确保仅限企业用户访问
|
|
|
+ // **重要安全要求**:企业专用API自动验证JWT token中的`companyId`字段,确保数据隔离安全
|
|
|
+ // 路径前缀 /api/v1/yongren/statistics 在路由层配置
|
|
|
+ export const enterpriseStatisticsClient = rpcClient<typeof statisticsRoutes>('/api/v1/yongren/statistics');
|
|
|
+ ```
|
|
|
+- **路径前缀**:`/api/v1/yongren/statistics`(企业专用版本)
|
|
|
+- **主要接口**(6个分布统计接口,与后端实现保持一致):
|
|
|
+ - `GET /disability-type-distribution` - 残疾类型分布统计接口
|
|
|
+ - `GET /gender-distribution` - 性别分布统计接口
|
|
|
+ - `GET /age-distribution` - 年龄分布统计接口
|
|
|
+ - `GET /household-distribution` - 户籍分布统计接口
|
|
|
+ - `GET /job-status-distribution` - 在职状态分布统计接口
|
|
|
+ - `GET /salary-distribution` - 薪资分布统计接口
|
|
|
+- **使用示例**:
|
|
|
+ ```typescript
|
|
|
+ // 在数据统计UI包内使用
|
|
|
+ import { enterpriseStatisticsClient } from '../api/enterpriseStatisticsClient'
|
|
|
+
|
|
|
+ // 获取残疾类型分布统计
|
|
|
+ const disabilityStats = await enterpriseStatisticsClient['disability-type-distribution'].$get({
|
|
|
+ query: {
|
|
|
+ companyId: 1 // 可选,如未提供则从认证用户token中获取
|
|
|
+ }
|
|
|
+ })
|
|
|
+
|
|
|
+ // 获取性别分布统计
|
|
|
+ const genderStats = await enterpriseStatisticsClient['gender-distribution'].$get({
|
|
|
+ query: {
|
|
|
+ companyId: 1
|
|
|
+ }
|
|
|
+ })
|
|
|
+
|
|
|
+ // 获取年龄分布统计
|
|
|
+ const ageStats = await enterpriseStatisticsClient['age-distribution'].$get()
|
|
|
+
|
|
|
+ // 获取户籍分布统计
|
|
|
+ const householdStats = await enterpriseStatisticsClient['household-distribution'].$get()
|
|
|
+
|
|
|
+ // 获取在职状态分布统计
|
|
|
+ const jobStatusStats = await enterpriseStatisticsClient['job-status-distribution'].$get()
|
|
|
+
|
|
|
+ // 获取薪资分布统计
|
|
|
+ const salaryStats = await enterpriseStatisticsClient['salary-distribution'].$get()
|
|
|
+ ```
|
|
|
+
|
|
|
+**RPC类型推断实现**
|
|
|
+参考 `mini-ui-packages/yongren-order-management-ui/src/api/types.ts` 的实现模式,使用Hono的类型推导工具 `InferResponseType` 和 `InferRequestType` 从API客户端自动推导请求和响应类型,避免手动定义重复的自定义类型。
|
|
|
+
|
|
|
+**实现示例**:
|
|
|
+```typescript
|
|
|
+// 文件:mini-ui-packages/yongren-statistics-ui/src/api/types.ts
|
|
|
+import type { InferResponseType, InferRequestType } from 'hono/client';
|
|
|
+import { enterpriseStatisticsClient } from './enterpriseStatisticsClient';
|
|
|
+
|
|
|
+// 使用Hono类型推导 - 注意正确的属性访问语法
|
|
|
+export type DisabilityTypeDistributionResponse = InferResponseType<typeof enterpriseStatisticsClient['disability-type-distribution']['$get'], 200>;
|
|
|
+export type GenderDistributionResponse = InferResponseType<typeof enterpriseStatisticsClient['gender-distribution']['$get'], 200>;
|
|
|
+export type AgeDistributionResponse = InferResponseType<typeof enterpriseStatisticsClient['age-distribution']['$get'], 200>;
|
|
|
+export type HouseholdDistributionResponse = InferResponseType<typeof enterpriseStatisticsClient['household-distribution']['$get'], 200>;
|
|
|
+export type JobStatusDistributionResponse = InferResponseType<typeof enterpriseStatisticsClient['job-status-distribution']['$get'], 200>;
|
|
|
+export type SalaryDistributionResponse = InferResponseType<typeof enterpriseStatisticsClient['salary-distribution']['$get'], 200>;
|
|
|
+
|
|
|
+// 查询参数类型推导
|
|
|
+export type DisabilityTypeDistributionParams = InferRequestType<typeof enterpriseStatisticsClient['disability-type-distribution']['$get']>['query'];
|
|
|
+export type GenderDistributionParams = InferRequestType<typeof enterpriseStatisticsClient['gender-distribution']['$get']>['query'];
|
|
|
+export type AgeDistributionParams = InferRequestType<typeof enterpriseStatisticsClient['age-distribution']['$get']>['query'];
|
|
|
+export type HouseholdDistributionParams = InferRequestType<typeof enterpriseStatisticsClient['household-distribution']['$get']>['query'];
|
|
|
+export type JobStatusDistributionParams = InferRequestType<typeof enterpriseStatisticsClient['job-status-distribution']['$get']>['query'];
|
|
|
+export type SalaryDistributionParams = InferRequestType<typeof enterpriseStatisticsClient['salary-distribution']['$get']>['query'];
|
|
|
+```
|
|
|
+
|
|
|
+**优势**:
|
|
|
+- 类型安全:自动与后端路由类型保持同步,确保编译时类型检查
|
|
|
+- 减少重复:避免手动定义重复的类型定义,消除代码冗余
|
|
|
+- 维护性:后端路由变更时,前端类型自动更新,减少维护成本
|
|
|
+- 一致性:确保请求/响应类型与API契约完全匹配
|
|
|
+- 消除不必要的类型断言:无需使用`as any`或`as DisabilityTypeDistributionResponse`等手动断言,TypeScript可自动推断API响应类型
|
|
|
+- 简化组件代码:组件中直接导入推导的类型,代码更简洁清晰
|
|
|
+
|
|
|
+**组件中使用示例**:
|
|
|
+```typescript
|
|
|
+import type { DisabilityTypeDistributionResponse, GenderDistributionResponse } from '../../api'
|
|
|
+
|
|
|
+// API响应自动推断类型,无需手动断言
|
|
|
+const response = await enterpriseStatisticsClient['disability-type-distribution'].$get({ query: { companyId: 1 } })
|
|
|
+const data = await response.json() // TypeScript自动推断为DisabilityTypeDistributionResponse类型
|
|
|
+
|
|
|
+// 统计数据使用具体类型
|
|
|
+const transformedStats = (data.stats || []).map((item: DisabilityTypeDistributionResponse['stats'][0]) => {
|
|
|
+ // 类型安全的转换逻辑
|
|
|
+ return {
|
|
|
+ key: item.key,
|
|
|
+ value: item.value,
|
|
|
+ percentage: item.percentage
|
|
|
+ }
|
|
|
+})
|
|
|
+
|
|
|
+// 性别分布数据示例
|
|
|
+const genderResponse = await enterpriseStatisticsClient['gender-distribution'].$get()
|
|
|
+const genderData = await genderResponse.json() // TypeScript自动推断为GenderDistributionResponse类型
|
|
|
+```
|
|
|
|
|
|
**技术集成**:
|
|
|
-- 使用故事011.001集成的RPC客户端
|
|
|
-- API路径前缀:`api/v1/yongren`
|
|
|
+- **RPC客户端工具**:使用`@d8d/mini-shared-ui-components/utils/rpc/rpc-client`提供的RPC客户端工具,在UI包内创建企业专用API客户端
|
|
|
+- **企业专用API路径前缀**:`/api/v1/yongren/statistics`(数据统计模块专用前缀)
|
|
|
+- **架构模式**:按照史诗011的mini-ui-packages架构,每个UI包负责创建和管理自己的API客户端,实现模块化集成。数据统计API客户端在`@d8d/yongren-statistics-ui`包内创建
|
|
|
+- **类型安全**:从`@d8d/allin-statistics-module`导入`statisticsRoutes`路由类型定义,确保类型安全
|
|
|
+- **数据安全**:所有API通过`enterpriseAuthMiddleware`中间件保护,自动验证企业用户权限,仅返回当前企业关联数据
|
|
|
+- **认证集成**:所有API调用自动携带企业用户token(通过企业认证框架管理),自动从token中提取`companyId`进行数据过滤
|
|
|
|
|
|
### 组件规范
|
|
|
**数据统计页设计规范**:
|
|
|
@@ -224,6 +349,7 @@ Ready
|
|
|
| 2025-12-17 | 1.0 | 初始创建(数据统计故事) | Bob(Scrum Master) |
|
|
|
| 2025-12-20 | 1.1 | 更新Navbar集成规范,添加页面层级结构,反映mini-ui-packages架构 | Claude Code |
|
|
|
| 2025-12-22 | 1.2 | 更新故事状态为Ready,依赖故事011.001-011.004已完成 | Claude Code |
|
|
|
+| 2025-12-22 | 1.3 | 根据实际API实现修正API规范,移除虚构API描述,更新为6个实际分布统计接口 | Claude Code |
|
|
|
## 开发代理记录
|
|
|
*此部分由开发代理在实施过程中填充*
|
|
|
|
|
|
@@ -235,5 +361,16 @@ Ready
|
|
|
- 更新测试要求,添加页面结构测试场景
|
|
|
- 统一所有用人小程序页面的Navbar集成标准
|
|
|
|
|
|
+**文档更新记录 (2025-12-22)**:
|
|
|
+- 根据实际API实现验证和修正API规范部分
|
|
|
+- 移除虚构的通用版本和企业专用扩展API描述
|
|
|
+- 更新为实际存在的6个分布统计接口:残疾类型分布、性别分布、年龄分布、户籍分布、在职状态分布、薪资分布
|
|
|
+- 修正接口路径名称(添加-distribution后缀)
|
|
|
+- 修正查询参数(仅支持companyId,无时间范围参数)
|
|
|
+- 更新API客户端创建示例,反映mini-ui-packages架构
|
|
|
+- 更新RPC类型推断实现示例,使用实际接口名称
|
|
|
+- 更新组件中使用示例,使用正确的接口和类型
|
|
|
+- 更新技术集成描述,反映实际实现状态
|
|
|
+
|
|
|
## QA结果
|
|
|
*来自QA代理对已完成故事实施的QA审查结果*
|