export const nextStepMap = { ylTeamLeader: { name: '养护组长分配', btnText: '分配', operateTypePass: 110, operateTypeNoPass: 210, //养护组长退回:210 backShow: true, renewShow: false }, ylWorker: { name: '养护员待实施', btnText: '实施', operateTypePass: 120, operateTypeNoPass: 220, backShow: true, renewShow: false }, ylTeamLeaderConfirm: { name: '养护组长验收', btnText: '验收', operateTypePass: 130, //养护组长验收通过: 130 operateTypeNoPass: 230, // 养护组长验收不通过:230 backShow: false, renewShow: false }, ylInspector: { name: '巡查员验收', // btnText: '验收', ysShow:true, operateTypePass: 140, //巡查员验收通过: 140 operateTypeNoPass: 240, // 巡查员验收不通过:240 backShow: false, renewShow: false }, ylInspectorStart: { name: '发起人确认', btnText: '结束工单', operateTypePass: 200, //巡查员结束工单:200 operateTypeNoPass: 240, // 巡查员验收不通过:240 operateTypeRenew: 100, //巡查员重新发起:100 backShow: false, renewShow: true }, regionManager: { name: '大区经理分配', btnText: '分配', operateTypePass: 80, // 大区经理分配:80 operateTypeNoPass: 90, // 大区经理退回:90 backShow: true, renewShow: false }, shRegionManager: { name: '督察员单子大区经理分配', btnText: '分配', operateTypePass: 60, // 大区经理分配:60 operateTypeNoPass: 70, // 大区经理退回:70 backShow: true, renewShow: false }, aiRegionManager: { name: 'ai单子大区经理分配', btnText: '分配', operateTypePass: 40, // 大区经理分配:40 operateTypeNoPass: 50, // 大区经理退回:50 backShow: true, renewShow: false }, ylAiInspectorStart: { name: 'AI工单派发人员', ysShow:false, btnText: '', operateTypePass: 40, // 大区经理分配:40 operateTypeNoPass: 50, // 大区经理退回:50 backShow: false, renewShow: false }, } export const buzStatusMap = { '000': '发起', "210": '退回', "110": '分配', "200": '结束工单', "100": '重新发起', "220": '退回', "120": '实施', "130": '验收通过', "230": '验收不通过', "140": '验收通过', "240": '验收不通过', '90': '退回', '80': '分配', '70': '退回', '60': '分配', '50':'退回', '40':'分配', } /** * 计算两个时间的时间差,返回格式化字符串(天/小时/分钟/秒,按需显示,无无效单位) * @param {string | Date | number} startTime - 开始时间(时间字符串/Date对象/10位/13位时间戳) * @param {string | Date | number} endTime - 结束时间(时间字符串/Date对象/10位/13位时间戳) * @returns {string} - 格式化时间差字符串(如:3天5小时2分钟30秒、3小时2分钟30秒、2分钟30秒、30秒) */ export const calculateFormatTimeDiff = (startTime, endTime) => { // 辅助函数:将任意合法时间格式转换为13位毫秒级时间戳 const to13BitTimestamp = (time) => { let timestamp = 0; // 情况1:数字类型(时间戳) if (typeof time === 'number') { const timeStr = time.toString(); if (timeStr.length === 10) { timestamp = time * 1000; // 10位秒级转13位毫秒级 } else if (timeStr.length === 13) { timestamp = time; // 13位毫秒级直接使用 } else { console.error('非法时间戳:仅支持10位/13位数字', time); return 0; } return timestamp; } // 情况2:Date对象 if (time instanceof Date) { timestamp = time.getTime(); if (isNaN(timestamp)) { console.error('无效的Date对象', time); return 0; } return timestamp; } // 情况3:字符串类型 if (typeof time === 'string') { const timeStr = time.trim().replace(/\//g, '-'); // 统一分隔符,兼容YYYY/MM/DD const date = new Date(timeStr); timestamp = date.getTime(); if (isNaN(timestamp)) { console.error('无效的时间字符串', time); return 0; } return timestamp; } // 非法类型 console.error('不支持的时间类型:仅支持string/Date/number', time); return 0; }; // 1. 统一转换为13位时间戳 const startTimestamp = to13BitTimestamp(startTime); const endTimestamp = to13BitTimestamp(endTime); // 2. 校验时间戳有效性 if (startTimestamp === 0 || endTimestamp === 0) { return '0秒'; } // 3. 计算总毫秒差(取绝对值,确保时间差为正数,不影响单位计算) const totalMsDiff = Math.abs(endTimestamp - startTimestamp); // 4. 定义时间单位换算(毫秒) const oneDayMs = 24 * 60 * 60 * 1000; const oneHourMs = 60 * 60 * 1000; const oneMinuteMs = 60 * 1000; const oneSecondMs = 1000; // 5. 计算各单位的差值(向下取整,获取整数单位) const days = Math.floor(totalMsDiff / oneDayMs); const remainingMsAfterDay = totalMsDiff % oneDayMs; // 扣除天数后剩余的毫秒数 const hours = Math.floor(remainingMsAfterDay / oneHourMs); const remainingMsAfterHour = remainingMsAfterDay % oneHourMs; // 扣除小时后剩余的毫秒数 const minutes = Math.floor(remainingMsAfterHour / oneMinuteMs); const remainingMsAfterMinute = remainingMsAfterHour % oneMinuteMs; // 扣除分钟后剩余的毫秒数 const seconds = Math.floor(remainingMsAfterMinute / oneSecondMs); // 6. 组装格式化字符串(按需添加单位,无无效单位) const timeParts = []; if (days > 0) { timeParts.push(`${days}天`); } if (hours > 0 || (days > 0 && hours === 0)) { timeParts.push(`${hours}小时`); } if (minutes > 0 || (timeParts.length > 0 && minutes === 0)) { timeParts.push(`${minutes}分钟`); } timeParts.push(`${seconds}秒`); // 7. 过滤掉可能存在的「0单位」 const validTimeParts = timeParts.filter(part => { const num = parseInt(part); return num > 0 || (timeParts.length === 1 && num === 0); }); // 8. 拼接并返回结果 return validTimeParts.join(''); }; /** * 将日期数组 [年, 月, 日] 转为标准日期字符串(兼容 iOS/Android) * @param {Array} dateArr 日期数组,如 [2025, 12, 20] * @returns {String} 标准日期字符串,如 '2025-12-20' */ export const convertArrToDateStr = (dateArr) => { // 边界判断:非数组/长度不足3,返回空 if (!Array.isArray(dateArr) || dateArr.length < 3) { return dateArr; } // 解构年、月、日,补零处理(确保格式统一,如 12月→12,2月→02) const [year, month, day] = dateArr; const formatMonth = month.toString().padStart(2, '0'); const formatDay = day.toString().padStart(2, '0'); // 拼接为标准字符串 return `${year}-${formatMonth}-${formatDay}`; } /** * 角色编码 转 中文名称 公共方法 * @param {Array} roles 角色编码数组 如:["team_leader_yl", "team_leader_wy"] | ["team_leader_yl"] * @returns {string} 拼接后的中文角色字符串 如:"管理员,子公司管理员" | "管理员" */ export const translateRoles = (roles = []) => { // 角色编码与中文名称映射表 const roleMap = { 'super_admin': '超级管理员', 'common': '普通角色', 'admin': '管理员', 'zgs_leader': '子公司管理员', 'regional_manager': '大区经理', 'patrol_leader': '巡查组长', 'dispatcher': '业务调度员', 'patrol_global': '全域巡查员', 'yl_inspector': '园林巡查员', 'team_leader_yl': '园林养护组长', 'wy_inspector': '物业巡查员', 'yl_worker': '园林养护员', 'wy_worker': '物业养护员', 'Inspector_global': '全域督察员', 'AI_dispatcher': 'AI工单派发人员', }; // 过滤有效角色 + 翻译 + 中文逗号拼接 return roles .filter(role => role && roleMap[role]) .map(role => roleMap[role]) .join(','); }