/** * H5版本的字段格式化工具函数 * 基于小程序版本改造,适配H5环境 */ /** * 获取字典翻译 - H5版本 * @param {string} cbName - 字典名称 * @param {string|number} value - 值 * @param {string} cacheKey - 缓存键 * @param {Map} dictCache - 字典缓存 * @param {Function} updateCallback - 更新回调函数 */ const getDictTranslation = async (cbName, value, cacheKey, dictCache, updateCallback) => { try { console.log(`🔍 获取字典翻译 [${cbName}:${value}]`); // 使用 loadObjpOpt 接口调用字典 const result = await request.post( '/service?ssServ=loadObjpOpt&objectpickerdropdown1=1', { objectpickerparam: JSON.stringify({ input: "false", codebook: cbName }), objectpickertype: 2, // 2表示获取要回显的一项 objectpickervalue: value // 需回显的值 }, { loading: false, formData: true } ); console.log(`字典翻译 [${cbName}:${value}] API返回:`, result); // 处理返回数据格式:{"result":{"622182":"会议室A"}} let translatedValue = value; // 默认返回原值 if (result && result.data && result.data.result) { // 从result对象中根据value查找对应的翻译 translatedValue = result.data.result[value] || value; console.log(`字典翻译结果: ${value} -> ${translatedValue}`); } dictCache.set(cacheKey, translatedValue); // 触发页面更新 if (updateCallback) { updateCallback(); } } catch (error) { console.error(`字典翻译失败 [${cbName}:${value}]:`, error); dictCache.set(cacheKey, value); } }; /** * 格式化字段值(处理字典翻译、日期格式等)- H5版本 * @param {Object} fieldObj - 字段对象 {field, value} * @param {Map} dictCache - 字典缓存 * @param {Function} getDictTranslationFn - 字典翻译函数 * @returns {string} 格式化后的值 */ const formatFieldValue = (fieldObj, dictCache, getDictTranslationFn) => { if (!fieldObj || !fieldObj.field || fieldObj.value === undefined) { return ''; } const { field, value } = fieldObj; // 空值处理 if (value === null || value === undefined || value === '') { return ''; } // 如果字段有字典配置,进行字典翻译 if (field.cbName) { const cacheKey = `${field.cbName}_${value}`; // 先从缓存中查找 if (dictCache.has(cacheKey)) { return dictCache.get(cacheKey); } // 缓存中没有,异步获取翻译 if (getDictTranslationFn) { getDictTranslationFn(field.cbName, value, cacheKey, dictCache); } // 返回原值作为临时显示 return value; } // 时间格式化(优先检查fmt字段) if (field.fmt) { return h5FormatDate(value, field.fmt); } // 日期格式化(兼容旧逻辑) if (field.type === 'date' || field.name.toLowerCase().includes('date') || field.name.toLowerCase().includes('time')) { return h5FormatDate(value); } // 数字格式化 if (field.type === 'number' && typeof value === 'number') { return value.toLocaleString(); } // 布尔值格式化 if (field.type === 'boolean' || typeof value === 'boolean') { return value ? '是' : '否'; } // 默认返回字符串 return String(value); }; /** * 解析特殊日期格式:Jul 4, 2025, 6:00:00 AM * @param {string} dateStr - 日期字符串 * @returns {object|null} 解析后的日期对象或null */ const parseSpecialDateFormat = (dateStr) => { try { // 匹配格式:Jul 4, 2025, 6:00:00 AM const regex = /^(\w{3})\s+(\d{1,2}),\s+(\d{4}),\s+(\d{1,2}):(\d{2}):(\d{2})\s+(AM|PM)$/; const match = dateStr.match(regex); if (!match) return null; const [, monthStr, day, year, hour, minute, second, ampm] = match; // 月份映射 const months = { 'Jan': 0, 'Feb': 1, 'Mar': 2, 'Apr': 3, 'May': 4, 'Jun': 5, 'Jul': 6, 'Aug': 7, 'Sep': 8, 'Oct': 9, 'Nov': 10, 'Dec': 11 }; const month = months[monthStr]; if (month === undefined) return null; // 处理12小时制 let hour24 = parseInt(hour); if (ampm === 'PM' && hour24 !== 12) { hour24 += 12; } else if (ampm === 'AM' && hour24 === 12) { hour24 = 0; } return { year: parseInt(year), month: month, day: parseInt(day), hour: hour24, minute: parseInt(minute), second: parseInt(second) }; } catch (error) { console.warn('解析特殊日期格式失败:', dateStr, error); return null; } }; /** * 格式化日期对象 * @param {object} dateObj - 日期对象 {year, month, day, hour, minute, second} * @param {string} format - 格式字符串 * @returns {string} 格式化后的字符串 */ const formatDateObject = (dateObj, format) => { const { year, month, day, hour, minute, second } = dateObj; return format .replace(/YYYY/g, year) .replace(/yyyy/g, year) .replace(/MM/g, String(month + 1).padStart(2, '0')) .replace(/DD/g, String(day).padStart(2, '0')) .replace(/dd/g, String(day).padStart(2, '0')) .replace(/HH/g, String(hour).padStart(2, '0')) .replace(/hh/g, String(hour).padStart(2, '0')) .replace(/mm/g, String(minute).padStart(2, '0')) .replace(/ss/g, String(second).padStart(2, '0')); }; /** * 增强的日期格式化函数 - H5版本 * @param {string|Date} date - 日期,支持多种格式如 "Jul 4, 2025, 6:00:00 AM" * @param {string} format - 格式,如 'YYYY-MM-DD HH:mm:ss' * @returns {string} 格式化后的日期 */ const h5FormatDate = (date, format = 'YYYY-MM-DD HH:mm:ss') => { if (!date) return ''; try { console.log(`🔧 h5FormatDate 开始处理:`, date, '目标格式:', format); // 手动解析特殊格式:Jul 4, 2025, 6:00:00 AM const parseResult = parseSpecialDateFormat(date); if (parseResult) { console.log(`🔧 手动解析成功:`, parseResult); const result = formatDateObject(parseResult, format); console.log(`✅ 手动格式化结果:`, result); return result; } // 使用 Day.js 解析日期(更强大的日期解析能力) if (typeof window !== 'undefined' && window.dayjs) { const dayObj = window.dayjs(date); console.log(`🔧 使用 Day.js 解析:`, dayObj.isValid(), dayObj.toString()); if (dayObj.isValid()) { const result = dayObj.format(format); console.log(`✅ Day.js 格式化结果:`, result); return result; } } // 降级到原生 Date(如果 Day.js 未加载) console.log(`🔧 Day.js 未加载,使用原生 Date`); const d = new Date(date); console.log(`🔧 解析后的日期对象:`, d, '是否有效:', !isNaN(d.getTime())); // 检查日期是否有效 if (isNaN(d.getTime())) { console.warn('❌ 无效日期格式:', date); return date; // 无效日期返回原值 } const year = d.getFullYear(); const month = String(d.getMonth() + 1).padStart(2, '0'); const day = String(d.getDate()).padStart(2, '0'); const hours = String(d.getHours()).padStart(2, '0'); const minutes = String(d.getMinutes()).padStart(2, '0'); const seconds = String(d.getSeconds()).padStart(2, '0'); // 支持多种格式模式 let result = format .replace(/YYYY/g, year) .replace(/yyyy/g, year) .replace(/MM/g, month) .replace(/DD/g, day) .replace(/dd/g, day) .replace(/HH/g, hours) .replace(/hh/g, hours) .replace(/mm/g, minutes) .replace(/ss/g, seconds); console.log(`日期格式化: ${date} -> ${result} (格式: ${format})`); return result; } catch (error) { console.error('日期格式化异常:', date, format, error); return date; // 异常时返回原值 } }; /** * 异步格式化字段值 - 支持字典转换 * @param {object} fieldData - 字段数据 {field, value} * @param {Map} dictCache - 字典缓存 * @returns {Promise} 格式化后的值 */ const formatFieldValueAsync = async (fieldData, dictCache) => { if (!fieldData || !fieldData.field) { return fieldData?.value || ''; } const { field, value } = fieldData; // 空值处理 if (value === null || value === undefined || value === '') { return ''; } // 优先处理时间格式化(如果字段有fmt属性) if (field.fmt) { try { console.log(`🕐 格式化时间字段 [${field.name}]:`, value, '格式:', field.fmt); console.log(`🔧 调用 h5FormatDate 前...`); const formattedTime = h5FormatDate(value, field.fmt); console.log(`🔧 调用 h5FormatDate 后,结果:`, formattedTime); console.log(`✅ 时间格式化结果:`, formattedTime); return formattedTime; } catch (error) { console.error('❌ 时间格式化失败:', field.name, value, error); // 格式化失败,返回原值 return value; } } // 如果字段有字典配置,进行字典转换 if (field.cbName) { const cacheKey = `${field.cbName}_${value}`; // 先从缓存中查找 if (dictCache && dictCache.has(cacheKey)) { return dictCache.get(cacheKey); } // 缓存中没有,异步获取翻译 try { const result = await request.post( `/service?ssServ=loadObjpOpt&objectpickerdropdown1=1`, { objectpickerparam: JSON.stringify({ input: "false", codebook: field.cbName }), objectpickertype: 2, objectpickervalue: value }, { loading: false, formData: true } ); if (result && result.data && result.data.result && result.data.result[value]) { const translatedValue = result.data.result[value]; // 缓存结果 if (dictCache) { dictCache.set(cacheKey, translatedValue); } return translatedValue; } } catch (error) { console.warn('字典转换失败:', field.cbName, value, error); } // 转换失败,返回原值 return value; } // 日期格式化 if (field.type === 3 && field.fmt) { return h5FormatDate(value, field.fmt); } // 数字格式化 if (field.type === 2 && typeof value === 'number') { return value.toLocaleString(); } // 默认返回字符串 return value.toString(); }; /** * 获取字典所有选项 - 用于下拉菜单 * @param {string} cbName - 字典名称 * @param {Map} dictCache - 字典缓存 * @returns {Promise} 选项列表 [{n: '显示名', v: '值'}] */ const getDictOptions = async (cbName, dictCache) => { const cacheKey = `options_${cbName}`; // 检查缓存 if (dictCache && dictCache.has(cacheKey)) { return dictCache.get(cacheKey); } try { console.log(`🔍 获取字典选项 [${cbName}]`); const result = await request.post( `/service?ssServ=loadObjpOpt&objectpickerdropdown1=1`, { objectpickerparam: JSON.stringify({ input: "false", codebook: cbName }), objectpickertype: 1, objectpickersearchAll: 1 }, { loading: false, formData: true } ); console.log(`字典选项 [${cbName}] API返回:`, result); if (result && result.data && result.data.result) { const options = Object.entries(result.data.result).map(([value, label]) => ({ n: label, v: value })); // 缓存结果 if (dictCache) { dictCache.set(cacheKey, options); } return options; } return []; } catch (error) { console.error(`❌ 获取字典选项失败 [${cbName}]:`, error); return []; } }; /** * 格式化对象列表数据 - 处理API返回的objectList * @param {Array} objectList - 原始对象列表 * @param {Map} dictCache - 字典缓存 * @returns {Promise} 格式化后的列表 */ const formatObjectList = async (objectList, dictCache) => { if (!Array.isArray(objectList)) return []; const formattedList = []; for (const item of objectList) { const formattedItem = { ...item }; // 格式化 first 字段 if (item.first) { formattedItem.firstDisplay = await formatFieldValueAsync(item.first, dictCache); } // 格式化 second 字段 if (item.second) { formattedItem.secondDisplay = await formatFieldValueAsync(item.second, dictCache); } // 格式化 third 字段组 if (item.third && Array.isArray(item.third)) { formattedItem.thirdDisplay = []; for (const group of item.third) { const formattedGroup = []; for (const fieldData of group) { const displayValue = await formatFieldValueAsync(fieldData, dictCache); formattedGroup.push({ ...fieldData, displayValue }); } formattedItem.thirdDisplay.push(formattedGroup); } } formattedList.push(formattedItem); } return formattedList; }; // 导出到全局 window.H5FieldFormatter = { getDictTranslation, formatFieldValue, formatFieldValueAsync, formatDate: h5FormatDate, getDictOptions, formatObjectList }; // 兼容性:也导出为全局函数 window.getDictTranslation = getDictTranslation; window.formatFieldValue = formatFieldValue; window.formatFieldValueAsync = formatFieldValueAsync; window.getDictOptions = getDictOptions; window.formatObjectList = formatObjectList; console.log('✅ H5字段格式化工具加载完成');