Files
autoAiWorkSys/api/controller_admin/device_monitor.js
张成 699c1d4f55 1
2025-12-18 18:18:43 +08:00

355 lines
11 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* 设备监控管理API - 后台管理
* 提供设备状态监控和管理功能
*/
const Framework = require("../../framework/node-core-framework.js");
module.exports = {
/**
* @swagger
* /admin_api/device/list:
* post:
* summary: 获取设备列表
* description: 分页获取所有设备列表(管理后台)
* tags: [后台-设备管理]
* requestBody:
* required: true
* content:
* application/json:
* schema:
* type: object
* properties:
* page:
* type: integer
* description: 页码
* pageSize:
* type: integer
* description: 每页数量
* isOnline:
* type: boolean
* description: 是否在线(可选)
* healthStatus:
* type: string
* description: 健康状态(可选)
* responses:
* 200:
* description: 获取成功
*/
/**
* @swagger
* /admin_api/device/detail:
* post:
* summary: 获取设备详情
* description: 根据设备SN码获取设备详细信息
* tags: [后台-设备管理]
* requestBody:
* required: true
* content:
* application/json:
* schema:
* type: object
* required:
* - deviceSn
* properties:
* deviceSn:
* type: string
* description: 设备SN码
* responses:
* 200:
* description: 获取成功
*/
'POST /device/detail': async (ctx) => {
const models = Framework.getModels();
const { pla_account } = models;
const body = ctx.getBody();
const { deviceSn } = body;
if (!deviceSn) {
return ctx.fail('设备SN码不能为空');
}
// 从 pla_account 获取账号信息(包含 is_online 和 is_logged_in)
const account = await pla_account.findOne({
where: { sn_code: deviceSn }
});
if (!account) {
return ctx.fail('设备不存在');
}
const accountData = account.toJSON();
// 组合返回数据(直接从数据库读取 is_online 和 is_logged_in)
const deviceData = {
sn_code: accountData.sn_code,
device_id: accountData.device_id,
deviceName: accountData.name || accountData.sn_code,
platform: accountData.platform_type,
isOnline: accountData.is_online === 1,
is_online: accountData.is_online === 1,
is_logged_in: accountData.is_logged_in === 1,
isRunning: false, // 不再维护运行状态
lastHeartbeatTime: null, // 不再从内存读取
accountName: accountData.name,
platform_type: accountData.platform_type,
is_enabled: accountData.is_enabled
};
return ctx.success(deviceData);
},
'POST /device/list': async (ctx) => {
const models = Framework.getModels();
const { pla_account, op } = models;
const deviceManager = require('../middleware/schedule/deviceManager');
const body = ctx.getBody();
const { isOnline, healthStatus, platform, searchText} = ctx.getBody();
// 获取分页参数
const { limit, offset } = ctx.getPageSize();
// 从 pla_account 查询账号
const where = { is_delete: 0 };
if (platform) where.platform_type = platform;
// 支持搜索设备名称或SN码
if (searchText) {
where[op.or] = [
{ name: { [op.like]: `%${searchText}%` } },
{ sn_code: { [op.like]: `%${searchText}%` } }
];
}
const result = await pla_account.findAndCountAll({
where,
limit,
offset,
order: [['id', 'DESC']]
});
// 获取设备在线状态
const deviceStatus = deviceManager.getAllDevicesStatus();
// 组合数据并过滤在线状态
let list = result.rows.map(account => {
const accountData = account.toJSON();
const status = deviceStatus[accountData.sn_code] || { isOnline: false };
return {
sn_code: accountData.sn_code,
device_id: accountData.device_id,
deviceName: accountData.name || accountData.sn_code,
platform: accountData.platform_type,
isOnline: status.isOnline || false,
isRunning: false,
lastHeartbeatTime: status.lastHeartbeat ? new Date(status.lastHeartbeat) : null,
accountName: accountData.name,
platform_type: accountData.platform_type,
is_enabled: accountData.is_enabled
};
});
// 如果指定了在线状态筛选
if (isOnline !== undefined) {
list = list.filter(item => item.isOnline === isOnline);
}
return ctx.success({
total: list.length,
list: list.slice(0, limit)
});
},
/**
* @swagger
* /admin_api/device/overview:
* get:
* summary: 获取设备概览
* description: 获取所有设备的统计概览
* tags: [后台-设备管理]
* responses:
* 200:
* description: 获取成功
*/
'GET /device/overview': async (ctx) => {
const models = Framework.getModels();
const { pla_account } = models;
const deviceManager = require('../middleware/schedule/deviceManager');
// 从 pla_account 获取账号总数
const totalDevices = await pla_account.count({ where: { is_delete: 0 } });
// 从 deviceManager 获取在线设备统计
const deviceStatus = deviceManager.getAllDevicesStatus();
const onlineDevices = Object.values(deviceStatus).filter(d => d.isOnline).length;
const runningDevices = 0; // 不再维护运行状态
const healthyDevices = onlineDevices; // 简化处理,在线即健康
const warningDevices = 0;
const errorDevices = 0;
// 获取最近离线的设备(从内存状态中获取)
const offlineDevicesList = Object.entries(deviceStatus)
.filter(([sn_code, status]) => !status.isOnline)
.map(([sn_code, status]) => ({
sn_code,
deviceName: sn_code,
lastOfflineTime: status.lastHeartbeat ? new Date(status.lastHeartbeat) : null,
lastError: ''
}))
.sort((a, b) => (b.lastOfflineTime?.getTime() || 0) - (a.lastOfflineTime?.getTime() || 0))
.slice(0, 5);
return ctx.success({
totalDevices,
onlineDevices,
offlineDevices: totalDevices - onlineDevices,
runningDevices,
idleDevices: onlineDevices - runningDevices,
healthyDevices,
warningDevices,
errorDevices,
onlineRate: totalDevices > 0 ? ((onlineDevices / totalDevices) * 100).toFixed(2) : 0,
healthyRate: totalDevices > 0 ? ((healthyDevices / totalDevices) * 100).toFixed(2) : 0,
averageHealthScore: '100.00', // 简化处理
recentOffline: offlineDevicesList
});
},
/**
* @swagger
* /admin_api/device/update-config:
* post:
* summary: 更新设备配置
* description: 更新指定设备的配置信息,保存到 pla_account 表的 deliver_config 字段
* tags: [后台-设备管理]
* requestBody:
* required: true
* content:
* application/json:
* schema:
* type: object
* required:
* - sn_code
* - deliver_config
* properties:
* sn_code:
* type: string
* description: 设备SN码
* deliver_config:
* type: object
* description: 投递配置数据
* responses:
* 200:
* description: 更新成功
*/
'POST /device/update-config': async (ctx) => {
const models = Framework.getModels();
const body = ctx.getBody();
const { sn_code, deliver_config } = body;
if (!sn_code) {
return ctx.fail('设备SN码不能为空');
}
if (!deliver_config) {
return ctx.fail('配置数据不能为空');
}
// 从 pla_account 获取账号
const { pla_account } = models;
const account = await pla_account.findOne({ where: { sn_code } });
if (!account) {
return ctx.fail('设备不存在');
}
// 更新 pla_account 表的 deliver_config 字段
await pla_account.update(
{
deliver_config: deliver_config,
auto_deliver: deliver_config.auto_delivery ? 1 : 0
},
{ where: { id: account.id } }
);
return ctx.success({ message: '设备配置更新成功' });
},
/**
* @swagger
* /admin_api/device/reset-error:
* post:
* summary: 重置设备错误
* description: 清除设备的错误信息和计数
* tags: [后台-设备管理]
* requestBody:
* required: true
* content:
* application/json:
* schema:
* type: object
* required:
* - sn_code
* properties:
* sn_code:
* type: string
* description: 设备SN码
* responses:
* 200:
* description: 重置成功
*/
'POST /device/reset-error': async (ctx) => {
// device_status 表已移除,此功能暂时禁用
// 如果需要重置错误,可以在 account_config 表中添加错误信息字段
return ctx.success({ message: '设备错误重置功能已禁用device_status 表已移除)' });
},
/**
* @swagger
* /admin_api/device/delete:
* post:
* summary: 删除设备
* description: 删除指定的设备记录
* tags: [后台-设备管理]
* requestBody:
* required: true
* content:
* application/json:
* schema:
* type: object
* required:
* - sn_code
* properties:
* sn_code:
* type: string
* description: 设备SN码
* responses:
* 200:
* description: 删除成功
*/
'POST /device/delete': async (ctx) => {
// device_status 表已移除,删除设备功能改为删除账号
// 如果需要删除设备,应该删除对应的 pla_account 记录
const models = Framework.getModels();
const { pla_account } = models;
const body = ctx.getBody();
const { sn_code } = body;
if (!sn_code) {
return ctx.fail('设备SN码不能为空');
}
// 软删除账号(设置 is_delete = 1
const result = await pla_account.update(
{ is_delete: 1 },
{ where: { sn_code } }
);
if (result[0] === 0) {
return ctx.fail('设备不存在');
}
return ctx.success({ message: '设备删除成功' });
}
};