- 切换数据库为PostgreSQL,更新依赖与配置 - 重构权限体系,使用sys_user/sys_role/sys_menu等新实体替代旧模型 - 移除旧的用户角色/权限/系统设置相关代码与实体 - 新增字典、菜单管理模块与基础CRUD接口 - 优化鉴权逻辑,基于菜单权限标识进行接口校验 - 前端同步更新API、路由与权限控制逻辑 - 删除冗余的v-permission指令与相关代码
180 lines
5.0 KiB
TypeScript
180 lines
5.0 KiB
TypeScript
import { Provide, Inject } from "@midwayjs/core";
|
|
import { InjectRepository } from "@midwayjs/sequelize";
|
|
import SysUser from "../entity/sysUser.entity";
|
|
import SysOperationLog from "../entity/sysOperationLog.entity";
|
|
import dayjs from "dayjs";
|
|
import { Op } from "sequelize";
|
|
|
|
@Provide()
|
|
export class DashboardService {
|
|
@InjectRepository(SysOperationLog)
|
|
logModel!: typeof SysOperationLog;
|
|
|
|
async getDashboardStats(): Promise<any> {
|
|
const mockDeviceTotal = 1256;
|
|
const mockDeviceOnline = 1089;
|
|
const mockAlertToday = 23;
|
|
|
|
const activeUsers = await this.getActiveUserCount(7);
|
|
|
|
const loginTrend = await this.getLoginTrend(7);
|
|
|
|
const deviceTrend = this.generateMockTrend(7, 900, 1100);
|
|
|
|
const deviceDistribution = [
|
|
{ name: "智能电表", value: 456 },
|
|
{ name: "环境传感器", value: 328 },
|
|
{ name: "摄像头", value: 245 },
|
|
{ name: "门禁系统", value: 147 },
|
|
{ name: "其他设备", value: 80 }
|
|
];
|
|
|
|
const recentAlerts = this.generateMockAlerts(10);
|
|
|
|
const recentActivities = await this.getRecentActivities(10);
|
|
|
|
return {
|
|
deviceTotal: mockDeviceTotal,
|
|
deviceOnline: mockDeviceOnline,
|
|
alertToday: mockAlertToday,
|
|
activeUsers,
|
|
deviceTrend,
|
|
deviceTypeDistribution: deviceDistribution,
|
|
recentAlerts,
|
|
recentActivities
|
|
};
|
|
}
|
|
|
|
private async getActiveUserCount(days: number): Promise<number> {
|
|
const cutoffDate = dayjs().subtract(days, "day").toDate();
|
|
|
|
try {
|
|
const count = await this.logModel.count({
|
|
where: {
|
|
action: "用户登录",
|
|
created_at: { [Op.gte]: cutoffDate }
|
|
},
|
|
distinct: true,
|
|
col: "userId"
|
|
});
|
|
|
|
return count || 12;
|
|
} catch (error) {
|
|
return 12;
|
|
}
|
|
}
|
|
|
|
private async getLoginTrend(days: number): Promise<any[]> {
|
|
const trend = [];
|
|
|
|
for (let i = days - 1; i >= 0; i--) {
|
|
const date = dayjs().subtract(i, "day").format("YYYY-MM-DD");
|
|
|
|
try {
|
|
const count = await this.logModel.count({
|
|
where: {
|
|
action: "用户登录",
|
|
created_at: {
|
|
[Op.between]: [dayjs(date).startOf("day").toDate(), dayjs(date).endOf("day").toDate()]
|
|
}
|
|
}
|
|
});
|
|
|
|
trend.push({
|
|
date,
|
|
value: count || Math.floor(Math.random() * 50) + 20
|
|
});
|
|
} catch (error) {
|
|
trend.push({
|
|
date,
|
|
value: Math.floor(Math.random() * 50) + 20
|
|
});
|
|
}
|
|
}
|
|
|
|
return trend;
|
|
}
|
|
|
|
private async getRecentActivities(limit: number): Promise<any[]> {
|
|
try {
|
|
const logs = await this.logModel.findAll({
|
|
order: [["created_at", "DESC"]],
|
|
limit,
|
|
attributes: ["id", "action", "module", "ip", "created_at"]
|
|
});
|
|
|
|
return logs.map((log) => ({
|
|
id: log.id,
|
|
user: String(log.userId || "系统"),
|
|
action: log.action,
|
|
module: log.module,
|
|
ip: log.ip,
|
|
time: dayjs(log.created_at).format("MM-DD HH:mm")
|
|
}));
|
|
} catch (error) {
|
|
return this.generateMockActivities(limit);
|
|
}
|
|
}
|
|
|
|
private generateMockTrend(days: number, min: number, max: number): any[] {
|
|
const trend = [];
|
|
|
|
for (let i = days - 1; i >= 0; i--) {
|
|
trend.push({
|
|
date: dayjs().subtract(i, "day").format("YYYY-MM-DD"),
|
|
online: Math.floor(Math.random() * (max - min)) + min,
|
|
offline: Math.floor(Math.random() * 200) + 50
|
|
});
|
|
}
|
|
|
|
return trend;
|
|
}
|
|
|
|
private generateMockAlerts(count: number): any[] {
|
|
const alertTypes = ["离线告警", "异常数据", "通信故障", "电量低", "温度超标"];
|
|
const devices = ["电表#1001", "传感器#2003", "摄像头#3012", "门禁#4005"];
|
|
const levels = ["high", "medium", "low"];
|
|
|
|
const alerts = [];
|
|
|
|
for (let i = 0; i < count; i++) {
|
|
alerts.push({
|
|
id: i + 1,
|
|
type: alertTypes[Math.floor(Math.random() * alertTypes.length)],
|
|
device: devices[Math.floor(Math.random() * devices.length)],
|
|
level: levels[Math.floor(Math.random() * levels.length)],
|
|
time: dayjs()
|
|
.subtract(Math.floor(Math.random() * 60), "minute")
|
|
.format("HH:mm"),
|
|
status: Math.random() > 0.5 ? "pending" : "resolved"
|
|
});
|
|
}
|
|
|
|
return alerts.sort((a, b) => a.time.localeCompare(b.time));
|
|
}
|
|
|
|
private generateMockActivities(count: number): any[] {
|
|
const actions = [
|
|
{ user: "管理员", action: "用户登录", module: "认证" },
|
|
{ user: "操作员A", action: "修改设备配置", module: "设备管理" },
|
|
{ user: "管理员", action: "创建新用户", module: "用户管理" },
|
|
{ user: "操作员B", action: "查看告警列表", module: "监控中心" },
|
|
{ user: "系统", action: "自动备份完成", module: "系统" },
|
|
{ user: "操作员A", action: "导出数据报表", module: "数据分析" },
|
|
{ user: "管理员", action: "更新系统配置", module: "系统设置" },
|
|
{ user: "操作员C", action: "处理告警事件", module: "监控中心" },
|
|
{ user: "系统", action: "定时任务执行", module: "系统" },
|
|
{ user: "操作员B", action: "添加新设备", module: "设备管理" }
|
|
];
|
|
|
|
return actions.slice(0, count).map((item, index) => ({
|
|
id: index + 1,
|
|
...item,
|
|
ip: "192.168.1." + Math.floor(Math.random() * 255),
|
|
time: dayjs()
|
|
.subtract(index * 30, "minute")
|
|
.format("MM-DD HH:mm")
|
|
}));
|
|
}
|
|
}
|