feat(frontend): 新增设备型号版本分布统计与展示模块
- 后端新增接口,按型号统计全量设备版本分布,空版本计入“未知版本” - 前端API添加获取设备版本分布的请求方法 - 首页新增各型号版本占比的饼图展示,支持展开查看完整版本列表 - 饼图支持高亮显示前10大版本,其他版本合并显示 - 设备版本数据加载失败时提供重试功能 - 优化客服反馈状态下拉选项类型定义及默认值 - 组件重构饼图模块,增强易用性和可访问性
This commit is contained in:
@@ -268,4 +268,46 @@ router.get('/api/dashboard/active-daily', async (req: Request, res: Response) =>
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* GET /api/dashboard/device-versions
|
||||
* 按型号统计全量设备的版本分布,空版本计入“未知版本”
|
||||
*/
|
||||
router.get('/api/dashboard/device-versions', async (_req: Request, res: Response) => {
|
||||
try {
|
||||
const version = sql<string>`COALESCE(NULLIF(TRIM(${userDevices.ver}), ''), '未知版本')`;
|
||||
const rows = await db
|
||||
.select({
|
||||
model: userDevices.model,
|
||||
ver: version.as('version'),
|
||||
count: sql<number>`COUNT(*)`.mapWith(Number).as('count'),
|
||||
})
|
||||
.from(userDevices)
|
||||
.groupBy(userDevices.model, version)
|
||||
.orderBy(userDevices.model, desc(sql`COUNT(*)`), version);
|
||||
|
||||
const modelMap = new Map<string, {
|
||||
model: string;
|
||||
total: number;
|
||||
versions: Array<{ ver: string; count: number }>;
|
||||
}>();
|
||||
|
||||
for (const row of rows) {
|
||||
let stats = modelMap.get(row.model);
|
||||
if (!stats) {
|
||||
stats = { model: row.model, total: 0, versions: [] };
|
||||
modelMap.set(row.model, stats);
|
||||
}
|
||||
const count = Number(row.count);
|
||||
stats.total += count;
|
||||
stats.versions.push({ ver: row.ver, count });
|
||||
}
|
||||
|
||||
res.json(ApiResponse.success({ items: [...modelMap.values()] }));
|
||||
} catch (e: unknown) {
|
||||
const msg = e instanceof Error ? e.message : String(e);
|
||||
logger.error(`获取设备版本分布失败:${msg}`);
|
||||
res.json(ApiResponse.error(`获取设备版本分布失败:${msg}`));
|
||||
}
|
||||
});
|
||||
|
||||
export default router;
|
||||
|
||||
Reference in New Issue
Block a user