// 全局任务超时服务
|
import http from '../api/http';
|
|
// 任务超时服务类
|
class TaskTimeoutService {
|
constructor() {
|
this.taskStatusMap = {}; // 存储任务状态开始时间
|
this.taskTimeoutMinutes = 10; // 任务超时时间,单位为分钟,调整为10分钟便于测试
|
this.checkTaskStatusTimer = null;
|
this.apiTaskData = []; // 存储通过API获取的任务数据
|
this.apiRefreshTimer = null; // API数据刷新定时器
|
this.apiRefreshInterval = 10000; // API数据刷新间隔,调整为10秒便于测试
|
}
|
|
// 初始化任务超时服务
|
init(app) {
|
// 设置定时器,每10秒检查一次,调整为便于测试的频率
|
this.checkTaskStatusTimer = setInterval(() => {
|
this.checkTaskStatus();
|
}, 10000);
|
|
// 设置API数据刷新定时器,每10秒刷新一次任务数据
|
this.apiRefreshTimer = setInterval(() => {
|
this.refreshTaskDataFromApi();
|
}, this.apiRefreshInterval);
|
|
// 初始刷新一次任务数据
|
this.refreshTaskDataFromApi();
|
|
// 保存定时器引用,方便后续清理
|
if (app && app.config) {
|
app.config.globalProperties.$global.taskTimeoutTimer = this.checkTaskStatusTimer;
|
app.config.globalProperties.$global.taskTimeoutApiTimer = this.apiRefreshTimer;
|
}
|
|
// 方便手动测试,将check方法挂载到window对象
|
window.testTaskTimeout = () => {
|
this.checkTaskStatus();
|
};
|
}
|
|
// 从API刷新任务数据
|
async refreshTaskDataFromApi() {
|
try {
|
// 构建查询参数,获取所有任务,不限制状态,在后续处理中过滤
|
const requestData = {
|
Page: 1,
|
Rows: 9999,
|
Filter: [],
|
Wheres: '',
|
Sort: 'CreateDate',
|
Order: 'desc'
|
};
|
|
// 调用API获取任务数据
|
const apiData = await http.post('/api/Task/GetPageData', requestData);
|
|
if (apiData && apiData.rows) {
|
this.apiTaskData = apiData.rows;
|
} else {
|
this.apiTaskData = [];
|
}
|
} catch (error) {
|
console.error('从API获取任务数据失败:', error);
|
this.apiTaskData = [];
|
}
|
}
|
|
// 检查任务状态
|
checkTaskStatus() {
|
// 直接使用从API获取的数据
|
const allTaskData = this.apiTaskData || [];
|
|
// 去重,确保每个任务只处理一次
|
const uniqueTaskData = [];
|
const taskNumSet = new Set();
|
|
allTaskData.forEach(task => {
|
if (task && task.taskNum && !taskNumSet.has(task.taskNum)) {
|
uniqueTaskData.push(task);
|
taskNumSet.add(task.taskNum);
|
}
|
});
|
|
if (uniqueTaskData.length === 0) {
|
return;
|
}
|
|
const now = new Date();
|
|
// 获取全局对象
|
const globalObj = window.$global || {};
|
|
// 处理消息删除逻辑,重置对应任务的定时器
|
const deletedMessages = [...(globalObj.messageDeleted || [])];
|
|
if (deletedMessages.length > 0) {
|
// 清空已处理的删除消息列表,避免重复处理
|
globalObj.messageDeleted = [];
|
|
// 遍历被删除的消息ID,重置对应任务的定时器
|
deletedMessages.forEach(deletedId => {
|
// 不需要从messageList中查找,因为消息已经被删除
|
// 直接处理任务状态重置
|
// 这里不做任何操作,因为消息删除是用户主动行为
|
// 我们只需要清空messageDeleted数组即可
|
});
|
}
|
|
// 获取当前所有任务号和状态
|
const currentTaskStatuses = {};
|
uniqueTaskData.forEach(task => {
|
currentTaskStatuses[task.taskNum] = task.taskStatus;
|
});
|
|
// 检查任务状态
|
uniqueTaskData.forEach(task => {
|
if (task.taskStatus === 210) {
|
// 堆垛机执行中状态
|
if (!this.taskStatusMap[task.taskNum]) {
|
this.taskStatusMap[task.taskNum] = now;
|
} else {
|
// 计算持续时间(分钟)
|
const duration = (now - this.taskStatusMap[task.taskNum]) / 60000;
|
if (duration >= this.taskTimeoutMinutes) {
|
this.sendTaskWarningMessage(task, duration);
|
delete this.taskStatusMap[task.taskNum];
|
}
|
}
|
} else {
|
// 任务状态已改变,清除记录
|
delete this.taskStatusMap[task.taskNum];
|
}
|
});
|
|
// 清除已解决的任务超时消息
|
this.clearResolvedTaskMessages(currentTaskStatuses);
|
}
|
|
// 清除已解决的任务超时消息
|
clearResolvedTaskMessages(currentTaskStatuses) {
|
// 获取全局对象
|
const globalObj = window.$global || {};
|
|
// 获取全局消息列表
|
const globalMessageList = [...(globalObj.messageList || [])];
|
|
// 找出需要清除的任务超时消息
|
const taskTimeoutMessages = globalMessageList.filter(msg => msg.businessType === 'task_timeout');
|
|
// 遍历所有任务超时消息
|
taskTimeoutMessages.forEach(msg => {
|
const taskNum = msg.taskNum;
|
// 检查条件:
|
// 1. 任务不在当前任务列表中(已完成或被移除)
|
// 2. 任务在当前任务列表中,但状态已不再是堆垛机执行中
|
if (taskNum && (!currentTaskStatuses[taskNum] || currentTaskStatuses[taskNum] !== 210)) {
|
// 任务已完成或状态已改变,清除该消息
|
// 但要确保只在消息仍然存在时才删除
|
if (globalObj.messageList && Array.isArray(globalObj.messageList)) {
|
const index = globalObj.messageList.findIndex(m => m.id === msg.id);
|
if (index !== -1) {
|
globalObj.messageList.splice(index, 1);
|
}
|
}
|
}
|
});
|
}
|
|
|
|
// 发送任务警告消息
|
sendTaskWarningMessage(task, duration) {
|
// 创建唯一的消息ID
|
const messageId = Date.now() + Math.random().toString(36).substr(2, 9);
|
|
// 创建警告消息
|
const warningMessage = {
|
id: messageId,
|
title: '任务异常警告',
|
message: `任务号 ${task.taskNum} 已在堆垛机执行中状态超过${Math.round(duration)}分钟,请及时处理!`,
|
type: 'warning',
|
businessType: 'task_timeout',
|
taskNum: task.taskNum,
|
createTime: new Date().toLocaleString()
|
};
|
|
// 获取全局对象
|
const globalObj = window.$global || {};
|
|
// 检查是否已经存在相同的任务超时警告
|
const globalMessageList = globalObj.messageList || [];
|
|
const hasExistingWarning = globalMessageList.some(msg =>
|
msg.businessType === 'task_timeout' && msg.taskNum === task.taskNum
|
);
|
|
if (hasExistingWarning) return;
|
|
// 发送消息到全局消息列表
|
try {
|
if (globalObj.messageList) {
|
globalObj.messageList.push(warningMessage);
|
}
|
} catch (error) {
|
// 出错时使用浏览器原生alert作为最终备选
|
try {
|
alert(`任务异常警告: 任务号 ${task.taskNum} 已在堆垛机执行中状态超过${Math.round(duration)}分钟,请及时处理!`);
|
} catch (e) {
|
// 忽略所有错误
|
}
|
}
|
}
|
|
// 手动检查任务状态(用于外部调用)
|
manualCheckTaskStatus() {
|
this.checkTaskStatus();
|
}
|
|
// 设置任务超时时间
|
setTaskTimeoutMinutes(minutes) {
|
if (typeof minutes === 'number' && minutes > 0) {
|
this.taskTimeoutMinutes = minutes;
|
}
|
}
|
|
// 获取当前任务超时时间
|
getTaskTimeoutMinutes() {
|
return this.taskTimeoutMinutes;
|
}
|
|
// 清理资源
|
cleanup() {
|
if (this.checkTaskStatusTimer) {
|
clearInterval(this.checkTaskStatusTimer);
|
this.checkTaskStatusTimer = null;
|
}
|
|
if (this.apiRefreshTimer) {
|
clearInterval(this.apiRefreshTimer);
|
this.apiRefreshTimer = null;
|
}
|
|
this.taskStatusMap = {};
|
this.apiTaskData = [];
|
delete window.testTaskTimeout;
|
}
|
}
|
|
// 创建单例实例
|
const taskTimeoutService = new TaskTimeoutService();
|
|
export default taskTimeoutService;
|