feat(线缆管理): 新增向导式接线创建功能
- 新增四步向导流程,简化接线创建过程 - 添加线缆标签、颜色、安装信息等新字段 - 实现端口可视化面板和冲突检测功能 - 新增耗材日志设备关联字段 - 添加耗材导入后台任务管理 - 更新线缆管理文档和使用指南
This commit is contained in:
@@ -0,0 +1,174 @@
|
||||
const { EventEmitter } = require('events');
|
||||
const path = require('path');
|
||||
const fs = require('fs');
|
||||
|
||||
class ImportJobManager extends EventEmitter {
|
||||
constructor() {
|
||||
super();
|
||||
this.jobs = new Map();
|
||||
this.JOB_STATUS = {
|
||||
PENDING: 'pending',
|
||||
PROCESSING: 'processing',
|
||||
COMPLETED: 'completed',
|
||||
FAILED: 'failed',
|
||||
CANCELLED: 'cancelled',
|
||||
};
|
||||
}
|
||||
|
||||
createJob(jobId, type, totalItems) {
|
||||
const job = {
|
||||
jobId,
|
||||
type,
|
||||
status: this.JOB_STATUS.PENDING,
|
||||
totalItems,
|
||||
processedItems: 0,
|
||||
successCount: 0,
|
||||
failedCount: 0,
|
||||
skippedCount: 0,
|
||||
updatedCount: 0,
|
||||
startTime: null,
|
||||
endTime: null,
|
||||
error: null,
|
||||
canCancel: true,
|
||||
result: null,
|
||||
createdAt: new Date(),
|
||||
};
|
||||
this.jobs.set(jobId, job);
|
||||
return job;
|
||||
}
|
||||
|
||||
getJob(jobId) {
|
||||
return this.jobs.get(jobId);
|
||||
}
|
||||
|
||||
updateJob(jobId, updates) {
|
||||
const job = this.jobs.get(jobId);
|
||||
if (!job) return null;
|
||||
|
||||
Object.assign(job, updates);
|
||||
this.emit('jobUpdate', job);
|
||||
return job;
|
||||
}
|
||||
|
||||
startJob(jobId) {
|
||||
const job = this.jobs.get(jobId);
|
||||
if (!job) return null;
|
||||
|
||||
job.status = this.JOB_STATUS.PROCESSING;
|
||||
job.startTime = new Date();
|
||||
this.emit('jobStart', job);
|
||||
return job;
|
||||
}
|
||||
|
||||
incrementProgress(jobId, success = 0, failed = 0, skipped = 0, updated = 0) {
|
||||
const job = this.jobs.get(jobId);
|
||||
if (!job) return null;
|
||||
|
||||
job.processedItems += success + failed + skipped + updated;
|
||||
job.successCount += success;
|
||||
job.failedCount += failed;
|
||||
job.skippedCount += skipped;
|
||||
job.updatedCount += updated;
|
||||
this.emit('jobProgress', job);
|
||||
return job;
|
||||
}
|
||||
|
||||
completeJob(jobId, result = null) {
|
||||
const job = this.jobs.get(jobId);
|
||||
if (!job) return null;
|
||||
|
||||
job.status = this.JOB_STATUS.COMPLETED;
|
||||
job.endTime = new Date();
|
||||
job.canCancel = false;
|
||||
job.result = result;
|
||||
this.emit('jobComplete', job);
|
||||
return job;
|
||||
}
|
||||
|
||||
failJob(jobId, error) {
|
||||
const job = this.jobs.get(jobId);
|
||||
if (!job) return null;
|
||||
|
||||
job.status = this.JOB_STATUS.FAILED;
|
||||
job.endTime = new Date();
|
||||
job.canCancel = false;
|
||||
job.error = error;
|
||||
this.emit('jobFailed', job);
|
||||
return job;
|
||||
}
|
||||
|
||||
cancelJob(jobId) {
|
||||
const job = this.jobs.get(jobId);
|
||||
if (!job || !job.canCancel) return null;
|
||||
|
||||
job.status = this.JOB_STATUS.CANCELLED;
|
||||
job.endTime = new Date();
|
||||
job.canCancel = false;
|
||||
this.emit('jobCancelled', job);
|
||||
return job;
|
||||
}
|
||||
|
||||
getJobProgress(jobId) {
|
||||
const job = this.jobs.get(jobId);
|
||||
if (!job) return null;
|
||||
|
||||
const progress = {
|
||||
jobId: job.jobId,
|
||||
status: job.status,
|
||||
totalItems: job.totalItems,
|
||||
processedItems: job.processedItems,
|
||||
progressPercent:
|
||||
job.totalItems > 0 ? Math.round((job.processedItems / job.totalItems) * 100) : 0,
|
||||
successCount: job.successCount,
|
||||
failedCount: job.failedCount,
|
||||
skippedCount: job.skippedCount,
|
||||
updatedCount: job.updatedCount,
|
||||
canCancel: job.canCancel,
|
||||
error: job.error,
|
||||
startTime: job.startTime,
|
||||
endTime: job.endTime,
|
||||
elapsedTime: job.startTime
|
||||
? Date.now() - new Date(job.startTime).getTime()
|
||||
: null,
|
||||
};
|
||||
|
||||
return progress;
|
||||
}
|
||||
|
||||
listJobs() {
|
||||
return Array.from(this.jobs.values()).map(job => ({
|
||||
jobId: job.jobId,
|
||||
type: job.type,
|
||||
status: job.status,
|
||||
totalItems: job.totalItems,
|
||||
processedItems: job.processedItems,
|
||||
progressPercent:
|
||||
job.totalItems > 0 ? Math.round((job.processedItems / job.totalItems) * 100) : 0,
|
||||
canCancel: job.canCancel,
|
||||
startTime: job.startTime,
|
||||
endTime: job.endTime,
|
||||
createdAt: job.createdAt,
|
||||
}));
|
||||
}
|
||||
|
||||
cleanupOldJobs(maxAgeMs = 24 * 60 * 60 * 1000) {
|
||||
const now = Date.now();
|
||||
for (const [jobId, job] of this.jobs.entries()) {
|
||||
const jobEndTime = job.endTime || job.createdAt;
|
||||
if (now - new Date(jobEndTime).getTime() > maxAgeMs) {
|
||||
this.jobs.delete(jobId);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const importJobManager = new ImportJobManager();
|
||||
|
||||
setInterval(() => {
|
||||
importJobManager.cleanupOldJobs();
|
||||
}, 60 * 60 * 1000);
|
||||
|
||||
module.exports = {
|
||||
importJobManager,
|
||||
ImportJobManager,
|
||||
};
|
||||
Reference in New Issue
Block a user