From b4c4929dbb4c1e96c6b203a93e543f942e1b69ac Mon Sep 17 00:00:00 2001 From: kkfluous Date: Tue, 14 Apr 2026 22:44:01 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E9=83=A8=E9=97=A8/=E4=B8=9A=E5=8A=A1?= =?UTF-8?q?=E8=B4=9F=E8=B4=A3=E4=BA=BA=E5=88=97=E8=A1=A8=E8=A1=A5=E9=BD=90?= =?UTF-8?q?=E6=97=A0=E8=BD=A6=E8=BE=86=E4=B8=9A=E5=8A=A1=E5=91=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit /dept-stats 在按车辆聚合后,查询 tab_user 把业务部门内所有在职用户补进 managers 列表,无车辆显示为 0 辆。跳过公务车部门。 Co-Authored-By: Claude Opus 4.6 (1M context) --- src/server/routes/vehicles.ts | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/src/server/routes/vehicles.ts b/src/server/routes/vehicles.ts index 56d8ca5..1572a35 100644 --- a/src/server/routes/vehicles.ts +++ b/src/server/routes/vehicles.ts @@ -690,6 +690,28 @@ app.get('/dept-stats', async (c) => { mgrMap.get(mgr)!.push(v); } + // 补齐:业务部门内所有在职用户,即使当前无车辆也需显示 + const deptNames = Array.from(deptMap.keys()).filter((d) => d !== '公务车'); + if (deptNames.length > 0) { + const placeholders = deptNames.map(() => '?').join(','); + const [userRows] = await pool.query( + `SELECT u.user_name, dep.dep_name + FROM tab_user u + LEFT JOIN tab_department dep ON dep.id = u.dep_id AND dep.is_deleted = 0 + WHERE u.is_deleted = 0 + AND dep.dep_name IN (${placeholders})`, + deptNames, + ); + for (const r of userRows as any[]) { + const dept = r.dep_name as string | null; + const mgr = r.user_name as string | null; + if (!dept || !mgr) continue; + const mgrMap = deptMap.get(dept); + if (!mgrMap) continue; + if (!mgrMap.has(mgr)) mgrMap.set(mgr, []); + } + } + // Compute attendance & avg mileage from realtime data const getMileageStats = (vList: Vehicle[]) => { const todayActive = vList.filter((v) => (todayMileageMap.get(v.plateNumber) || 0) > 0).length;