Status: review
作为企业管理员, 我在企业小程序的数据统计页查看"在职状态分布"图时, 我希望看到基于订单人员实际工作状态的准确分布, 以便了解企业真实的在职/待入职/离职人员构成。
当前问题: getJobStatusDistribution 方法使用 disabled_person.jobStatus 字段(数字类型:0=未在职,1=已在职)进行统计,这是一个二元状态的旧字段,无法反映实际的工作状态多样性。
根本原因: 该方法展示的是旧字段 jobStatus 的分布,而不是实际使用的 order_person.work_status 枚举字段('working', 'pending', 'departed' 等)。
影响:
work_status 字段不一致技术细节:
disabled_person.jobStatus: 数字类型,0 或 1,二元状态order_person.work_status: 字符串枚举,包括 'working', 'pending', 'departed' 等work_status 来管理人员的各种工作状态Given 企业小程序数据统计页
When 查看在职状态分布图
Then 应显示基于 order_person.work_status 的分布
And 包括 'working', 'pending', 'departed' 等所有状态
Given 在职状态分布图 When 显示各状态 Then 应显示友好的中文名称(如"在职"、"待入职"、"已离职"等) And 不显示原始的枚举值
Given 在职状态分布图 When 查看分布总数 Then 总数应与首页仪表板在职人数一致 And 各状态人数之和应等于总人数
Given 前端调用 /statistics/job-status-distribution API
When 获取数据
Then 返回的数据结构应保持不变
And 只改变状态的内容和数量
Given 修改完成后 When 运行数据统计页 E2E 测试 Then 在职状态分布相关测试应该通过
getJobStatusDistribution 方法的当前实现work_status 枚举的所有可能值disabledPersonRepository 改为 orderPersonRepositoryop.workStatus 进行分组统计getJobStatusDistribution 的正确性allin-packages/statistics-module/src/services/statistics.service.tsgetJobStatusDistribution() (行 258-301)allin-packages/mini-enterprise-module/src/pages/statistics.tsx (可能需要调整)// 当前实现(使用旧字段)
async getJobStatusDistribution(companyId: number): Promise<{
companyId: number;
stats: StatItem[];
total: number;
}> {
const personIds = await this.getCompanyDisabledPersonIds(companyId);
if (personIds.length === 0) {
return {
companyId,
stats: [],
total: 0
};
}
const query = this.disabledPersonRepository
.createQueryBuilder('dp')
.select('dp.jobStatus', 'key')
.addSelect('COUNT(dp.id)', 'value')
.where('dp.id IN (:...personIds)', { personIds })
.andWhere('dp.jobStatus IS NOT NULL')
.groupBy('dp.jobStatus');
const rawStats = await query.getRawMany();
const total = rawStats.reduce((sum, item) => sum + parseInt(item.value), 0);
// jobStatus映射:0-未在职,1-已在职
const jobStatusMap: Record<number, string> = {
0: '未在职',
1: '已在职'
};
const stats = rawStats.map(item => ({
key: jobStatusMap[item.key] || `未知(${item.key})`,
value: parseInt(item.value),
percentage: total > 0 ? (parseInt(item.value) / total) * 100 : 0
}));
return {
companyId,
stats,
total
};
}
// 修复后的实现(使用 work_status 枚举)
async getJobStatusDistribution(companyId: number): Promise<{
companyId: number;
stats: StatItem[];
total: number;
}> {
// 直接从 orderPerson 表统计,基于 workStatus 分组
const query = this.orderPersonRepository
.createQueryBuilder('op')
.innerJoin('op.order', 'order')
.select('op.workStatus', 'key')
.addSelect('COUNT(DISTINCT op.personId)', 'value') // 使用 DISTINCT 避免重复计数
.where('order.companyId = :companyId', { companyId })
.andWhere('op.workStatus IS NOT NULL')
.groupBy('op.workStatus');
const rawStats = await query.getRawMany();
const total = rawStats.reduce((sum, item) => sum + parseInt(item.value), 0);
// workStatus 枚举映射到中文
const workStatusMap: Record<string, string> = {
'working': '在职',
'pending': '待入职',
'departed': '已离职',
// 根据实际枚举值补充其他状态
};
const stats = rawStats.map(item => ({
key: workStatusMap[item.key] || item.key, // 未知状态显示原始值
value: parseInt(item.value),
percentage: total > 0 ? (parseInt(item.value) / total) * 100 : 0
}));
return {
companyId,
stats,
total
};
}
需要确认 WorkStatus 枚举的完整定义,通常包括:
enum WorkStatus {
WORKING = 'working', // 在职
PENDING = 'pending', // 待入职
DEPARTED = 'departed', // 已离职
// 可能有其他状态
}
查询重构:
disabledPersonRepository 改为 orderPersonRepositoryop.workStatus 分组,无需先获取 personIdsCOUNT(DISTINCT op.personId) 避免同一人员多订单重复计数状态映射:
WorkStatus 枚举的所有可能值数据一致性:
workStatus 字段前端兼容:
单元测试:
集成测试:
E2E 测试:
allin-packages/statistics-module/src/services/statistics.service.ts - 统计服务实现allin-packages/order-module/entities/order-person.entity.ts - OrderPerson 实体(WorkStatus 枚举定义)allin-packages/mini-enterprise-module/src/pages/statistics.tsx - 前端统计页面Claude (d8d-model)
N/A
主要修改文件:
allin-packages/statistics-module/src/services/statistics.service.ts (修改 getJobStatusDistribution 方法,添加 WorkStatusLabels 导入)allin-packages/statistics-module/tests/integration/statistics.integration.test.ts (更新集成测试,添加 Channel 实体和新的测试用例)