/** * 设备工具函数 * 用于设备数据处理、日期计算、预警判断等 */ /** * 计算两个日期之间的天数差 * @param {string|Date} date1 - 日期1 * @param {string|Date} date2 - 日期2 * @returns {number} 天数差 */ function getDaysDiff(date1, date2) { const d1 = new Date(date1); const d2 = new Date(date2); const diffTime = d2 - d1; return Math.ceil(diffTime / (1000 * 60 * 60 * 24)); } /** * 计算设备距离检验到期的天数 * @param {string} nextInspectionDate - 下次检验日期 * @returns {number} 剩余天数(负数表示已到期) */ function getDaysLeft(nextInspectionDate) { const today = new Date(); const nextDate = new Date(nextInspectionDate); return getDaysDiff(today, nextDate); } /** * 根据剩余天数判断设备状态 * @param {number} daysLeft - 剩余天数 * @param {number} warningDays - 预警天数阈值(默认30天) * @returns {Object} 状态信息 */ function getDeviceStatus(daysLeft, warningDays = 30) { let status = 'normal'; let statusText = '正常'; let statusTheme = 'success'; let isWarning = false; if (daysLeft < 0) { status = 'expired'; statusText = '已到期'; statusTheme = 'danger'; isWarning = true; } else if (daysLeft <= warningDays) { status = 'warning'; statusText = '预警'; statusTheme = 'warning'; isWarning = true; } return { status, statusText, statusTheme, isWarning }; } /** * 根据剩余天数获取预警等级 * @param {number} daysLeft - 剩余天数 * @returns {Object} 预警等级信息 */ function getWarningLevel(daysLeft) { if (daysLeft < 0) { return { level: 'expired', levelText: '已到期', tagTheme: 'danger' }; } else if (daysLeft <= 7) { return { level: 'urgent', levelText: '紧急', tagTheme: 'danger' }; } else if (daysLeft <= 15) { return { level: 'warning', levelText: '预警', tagTheme: 'warning' }; } else if (daysLeft <= 30) { return { level: 'notice', levelText: '提醒', tagTheme: 'warning' }; } return { level: 'normal', levelText: '正常', tagTheme: 'success' }; } /** * 处理设备数据,添加计算字段 * @param {Object} device - 设备原始数据 * @returns {Object} 处理后的设备数据 */ function processDeviceData(device) { const daysLeft = getDaysLeft(device.nextInspectionDate); const statusInfo = getDeviceStatus(daysLeft); const warningInfo = getWarningLevel(daysLeft); return { ...device, daysLeft, ...statusInfo, ...warningInfo }; } /** * 批量处理设备数据 * @param {Array} devices - 设备数组 * @returns {Array} 处理后的设备数组 */ function processDeviceList(devices) { return devices.map(device => processDeviceData(device)); } /** * 根据检验周期计算下次检验日期 * @param {string} lastInspectionDate - 上次检验日期 * @param {number} inspectionCycle - 检验周期(月) * @returns {string} 下次检验日期(YYYY-MM-DD) */ function calculateNextInspectionDate(lastInspectionDate, inspectionCycle) { const lastDate = new Date(lastInspectionDate); const nextDate = new Date(lastDate); nextDate.setMonth(nextDate.getMonth() + parseInt(inspectionCycle)); const year = nextDate.getFullYear(); const month = String(nextDate.getMonth() + 1).padStart(2, '0'); const day = String(nextDate.getDate()).padStart(2, '0'); return `${year}-${month}-${day}`; } /** * 格式化日期 * @param {string|Date} date - 日期 * @param {string} format - 格式(默认:YYYY-MM-DD) * @returns {string} 格式化后的日期 */ function formatDate(date, format = 'YYYY-MM-DD') { const d = new Date(date); const year = d.getFullYear(); const month = String(d.getMonth() + 1).padStart(2, '0'); const day = String(d.getDate()).padStart(2, '0'); const hour = String(d.getHours()).padStart(2, '0'); const minute = String(d.getMinutes()).padStart(2, '0'); const second = String(d.getSeconds()).padStart(2, '0'); return format .replace('YYYY', year) .replace('MM', month) .replace('DD', day) .replace('HH', hour) .replace('mm', minute) .replace('ss', second); } /** * 获取相对时间描述 * @param {string|Date} date - 日期 * @returns {string} 相对时间描述(如:2分钟前、1小时前) */ function getRelativeTime(date) { const now = new Date(); const past = new Date(date); const diffSeconds = Math.floor((now - past) / 1000); if (diffSeconds < 60) { return '刚刚'; } else if (diffSeconds < 3600) { return `${Math.floor(diffSeconds / 60)}分钟前`; } else if (diffSeconds < 86400) { return `${Math.floor(diffSeconds / 3600)}小时前`; } else if (diffSeconds < 2592000) { return `${Math.floor(diffSeconds / 86400)}天前`; } else if (diffSeconds < 31536000) { return `${Math.floor(diffSeconds / 2592000)}个月前`; } else { return `${Math.floor(diffSeconds / 31536000)}年前`; } } /** * 筛选设备列表 * @param {Array} devices - 设备数组 * @param {Object} filters - 筛选条件 * @returns {Array} 筛选后的设备数组 */ function filterDevices(devices, filters = {}) { let result = [...devices]; // 按状态筛选 if (filters.status && filters.status !== 'all') { result = result.filter(device => device.status === filters.status); } // 按设备类型筛选 if (filters.deviceType && filters.deviceType !== '全部') { result = result.filter(device => device.deviceType === filters.deviceType); } // 按使用单位筛选 if (filters.useUnit && filters.useUnit !== '全部') { result = result.filter(device => device.useUnit === filters.useUnit); } // 按关键词搜索 if (filters.keyword) { const keyword = filters.keyword.toLowerCase(); result = result.filter(device => device.deviceName.toLowerCase().includes(keyword) || device.deviceCode.toLowerCase().includes(keyword) || (device.specification && device.specification.toLowerCase().includes(keyword)) ); } return result; } /** * 统计设备数据 * @param {Array} devices - 设备数组 * @returns {Object} 统计结果 */ function getDeviceStatistics(devices) { const total = devices.length; const normal = devices.filter(d => d.status === 'normal').length; const warning = devices.filter(d => d.status === 'warning').length; const expired = devices.filter(d => d.status === 'expired').length; // 按类型统计 const typeStats = {}; devices.forEach(device => { const type = device.deviceType; if (!typeStats[type]) { typeStats[type] = 0; } typeStats[type]++; }); // 按单位统计 const unitStats = {}; devices.forEach(device => { const unit = device.useUnit; if (!unitStats[unit]) { unitStats[unit] = 0; } unitStats[unit]++; }); return { total, normal, warning, expired, warningRate: total > 0 ? ((warning + expired) / total * 100).toFixed(1) : 0, typeStats, unitStats }; } module.exports = { getDaysDiff, getDaysLeft, getDeviceStatus, getWarningLevel, processDeviceData, processDeviceList, calculateNextInspectionDate, formatDate, getRelativeTime, filterDevices, getDeviceStatistics };