From 55c6624407e8ae9d8ba9dd4c65d4c1d3b0ffaed0 Mon Sep 17 00:00:00 2001
From: wangrong <wangrong@shsening.com>
Date: 星期一, 12 十月 2026 00:03:54 +0800
Subject: [PATCH] 首页图表做下尊
---
src/modules/report/controller/admin/screen.ts | 10 +++++
src/modules/base/middleware/authority.ts | 5 +-
src/modules/report/service/screen.ts | 97 ++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 110 insertions(+), 2 deletions(-)
diff --git a/src/modules/base/middleware/authority.ts b/src/modules/base/middleware/authority.ts
index 6f1e934..5f9b021 100644
--- a/src/modules/base/middleware/authority.ts
+++ b/src/modules/base/middleware/authority.ts
@@ -101,8 +101,9 @@
new RegExp(`^${adminUrl}?.*/comm/`).test(url) ||
// 瀛楀吀鎺ュ彛
url == '/admin/dict/info/data' ||
- // 椹鹃┒鑸遍椤垫眹鎬伙細鑿滃崟銆岄椤点�嶆病鏈夋寜閽潈闄愶紝鏈櫥璁� report:screen:query 鏃堕潪瓒呯浼� 403
- url == '/admin/report/screen/query'
+ // 椹鹃┒鑸遍椤碉細鑿滃崟銆岄椤点�嶆病鏈夋寜閽潈闄愶紝鏈櫥璁� report:screen:* 鏃堕潪瓒呯浼� 403
+ url == '/admin/report/screen/query' ||
+ url == '/admin/report/screen/drill'
) {
await next();
return;
diff --git a/src/modules/report/controller/admin/screen.ts b/src/modules/report/controller/admin/screen.ts
index c862300..47fa398 100644
--- a/src/modules/report/controller/admin/screen.ts
+++ b/src/modules/report/controller/admin/screen.ts
@@ -14,4 +14,14 @@
async query(@Body('range') range: string) {
return this.ok(await this.reportScreenService.query(range));
}
+
+ @Post('/drill', { summary: '鍒嗙被涓嬮捇閮ㄩ棬/绔欑偣' })
+ async drill(
+ @Body('range') range: string,
+ @Body('code') code: string,
+ @Body('metric') metric: string,
+ @Body('departmentId') departmentId?: number
+ ) {
+ return this.ok(await this.reportScreenService.drill(range, code, metric, departmentId));
+ }
}
diff --git a/src/modules/report/service/screen.ts b/src/modules/report/service/screen.ts
index ac1c6d2..31b7b45 100644
--- a/src/modules/report/service/screen.ts
+++ b/src/modules/report/service/screen.ts
@@ -17,6 +17,7 @@
import { UserInfoEntity } from '../../user/entity/info';
import { PushVehicleGpsEntity } from '../../push/entity/vehiclegps';
import { BaseSysParamEntity } from '../../base/entity/sys/param';
+import { BaseSysDepartmentEntity } from '../../base/entity/sys/department';
const WASTE_COLORS: Record<string, string> = {
SW62: '#16a34a',
@@ -278,6 +279,102 @@
};
}
+ /**
+ * 鍒嗙被涓嬮捇锛氫笉浼� departmentId 鎸夐儴闂ㄦ眹鎬昏绫绘寚鏍囷紱浼犲叆鍒欎笅閽昏閮ㄩ棬涓嬪悇绔欑偣銆�
+ * metric: weight | value | count | carbon
+ */
+ async drill(range: string, code: string, metric: string, departmentId?: number) {
+ const dates = this.getRange(range || 'month');
+ const rawCode = String(code || '').toUpperCase();
+ const field = this.resolveDrillField(rawCode, metric);
+ const names = await this.wasteNames();
+ const categoryName = names.get(rawCode) || this.defaultWasteName(rawCode);
+ const deptId =
+ departmentId == null || departmentId === ('' as any)
+ ? undefined
+ : Number(departmentId);
+ const level = Number.isFinite(deptId as number) ? 'site' : 'department';
+
+ if (!field) {
+ return {
+ level,
+ code: rawCode,
+ categoryName,
+ departmentId: Number.isFinite(deptId as number) ? deptId : null,
+ departmentName: null,
+ items: [],
+ };
+ }
+
+ const expr = `SUM(IFNULL(a.${field},0))`;
+ const qb = this.dailySite.createQueryBuilder('a');
+
+ let departmentName: string | null = null;
+ if (level === 'site') {
+ qb.select('a.siteId', 'id')
+ .addSelect('a.siteName', 'name')
+ .addSelect(expr, 'metricValue')
+ .where('a.date BETWEEN :start AND :end', { start: dates.start, end: dates.end })
+ .andWhere('a.departmentId = :deptId', { deptId })
+ .groupBy('a.siteId')
+ .addGroupBy('a.siteName');
+ const dept = await this.dailySite.manager
+ .createQueryBuilder(BaseSysDepartmentEntity, 'd')
+ .select('d.name', 'name')
+ .where('d.id = :id', { id: deptId })
+ .getRawOne();
+ departmentName = dept?.name || `閮ㄩ棬${deptId}`;
+ } else {
+ qb.select('a.departmentId', 'id')
+ .addSelect(`IFNULL(d.name, CONCAT('閮ㄩ棬', a.departmentId))`, 'name')
+ .addSelect(expr, 'metricValue')
+ .leftJoin(BaseSysDepartmentEntity, 'd', 'd.id = a.departmentId')
+ .where('a.date BETWEEN :start AND :end', { start: dates.start, end: dates.end })
+ .groupBy('a.departmentId')
+ .addGroupBy('d.name');
+ }
+
+ this.applyDept(qb, 'a');
+ const rows = await qb.getRawMany();
+ const absCarbon = metric === 'carbon';
+ const decimals = metric === 'value' || metric === 'count' ? 0 : 1;
+ const items = rows
+ .map(r => {
+ const raw = n(r.metricValue);
+ const value = round(absCarbon ? Math.abs(raw) : raw, decimals);
+ return {
+ id: n(r.id),
+ name: String(r.name || (level === 'site' ? `绔欑偣${r.id}` : `閮ㄩ棬${r.id}`)),
+ value,
+ };
+ })
+ .filter(e => e.value !== 0)
+ .sort((a, b) => b.value - a.value);
+
+ const total = items.reduce((s, e) => s + e.value, 0);
+ return {
+ level,
+ code: rawCode,
+ categoryName,
+ departmentId: Number.isFinite(deptId as number) ? deptId : null,
+ departmentName,
+ items: items.map(e => ({
+ ...e,
+ percent: total ? round((e.value / total) * 100, 1) : 0,
+ })),
+ };
+ }
+
+ private resolveDrillField(code: string, metric: string): string | null {
+ const f = WASTE_FIELDS.find(e => e.code === code);
+ if (!f) return null;
+ if (metric === 'weight') return f.weight;
+ if (metric === 'carbon') return f.carbon;
+ if (metric === 'count') return f.time;
+ if (metric === 'value') return f.sales || null;
+ return null;
+ }
+
private deptIds(): number[] | null {
const admin = this.ctx.admin;
if (!admin || admin.username === 'admin') return null;
--
Gitblit v1.9.1