JavaScript格式化avg_runtime字符串并实现Material UI DataGrid正确排序
问题描述
初始问题
在将字符串格式化为可用于Material UI DataGrid的有效可排序类型时遇到问题,涉及字段为avg_runtime。API返回数据包含两种格式的运行时长字符串:
- 无天数格式:
0:05:12.026100 - 带天数格式:
9 days, 17:30:02.813297
后端已新增avg_runtime_seconds字段,返回以秒为单位的十进制数值,但前端在DataGrid中排序时,带天数的字符串出现排序异常(如9 days, 17:30:02.813297与11 days, 2:43:52.300138排序顺序错误)。尝试使用new Date(${x.avg_runtime}).toDateString()转换时,返回Invalid Date。
API返回示例:
{ "data": [ { "id": "01", "avg_runtime": "0:05:12.026100", "avg_runtime_seconds": 312.0261, "file_name": "myFile1" }, { "id": "02", "avg_runtime": "0:10:03.936321", "avg_runtime_seconds": 603.936321, "file_name": "myFile2" } ] }
当前前端API调用的格式化逻辑:
async function getData() { await axios .get(`https://myapi.com/${ runmode }/products`, { headers: { 'Content-Type': 'application/json' } }) .then((response) =>{ var this_data = response.data.data; setData( this_data.map((x) => { return { id: parseInt(`${x.product_id}`), file_name: `${x.file_name}`, avg_runtime: `${x.avg_runtime}`, avg_runtime_seconds: `${x.last_rundate}` } }) ); setValidationList( this_data.map((x) => x.product_id) ) setLoadingData(false); }); }
更新后问题
按照建议使用Value Getter后,即使avg_runtime_seconds为6位小数的数值,排序时仍未按整体数值比较,而是按字符位置排序(如9天17小时对应的秒数与2小时对应的秒数排序异常)。
解决方案
1. 修复前端数据类型错误
当前代码中存在明显笔误:avg_runtime_seconds被错误赋值为${x.last_rundate},且用模板字符串转为了字符串类型,这是导致按字符排序的核心原因。修正如下:
setData( this_data.map((x) => { return { id: parseInt(x.product_id), file_name: x.file_name, avg_runtime: x.avg_runtime, // 确保avg_runtime_seconds为数值类型,而非字符串 avg_runtime_seconds: Number(x.avg_runtime_seconds) }; }) );
2. 配置DataGrid列的排序规则
在DataGrid的列定义中,指定avg_runtime列使用avg_runtime_seconds数值字段进行排序,同时保留原字符串的显示格式:
const columns = [ // 其他列配置 { field: 'avg_runtime', headerName: '平均运行时间', // 显示原始时长字符串 valueGetter: (params) => params.row.avg_runtime, // 强制使用数值字段进行排序 sortAccessor: (params) => params.row.avg_runtime_seconds, // 可选:自定义格式化显示(统一格式) valueFormatter: (params) => { return formatSecondsToDuration(params.row.avg_runtime_seconds); } }, // 可选:显示秒数字段,设置为数值类型确保排序正确 { field: 'avg_runtime_seconds', headerName: '运行时长(秒)', type: 'number' } ];
3. 自定义时长解析/格式化工具函数(可选)
如果后端未返回avg_runtime_seconds,可以自行解析avg_runtime字符串为总秒数:
// 将时长字符串转为总秒数 function parseDurationToSeconds(durationStr) { let totalSeconds = 0; // 处理带天数的格式 const dayMatch = durationStr.match(/(\d+) days,/); if (dayMatch) { totalSeconds += parseInt(dayMatch[1]) * 24 * 3600; // 提取时间部分并拆分 const [hours, minutes, seconds] = durationStr.split(', ')[1].split(':'); totalSeconds += parseInt(hours) * 3600 + parseInt(minutes) * 60 + parseFloat(seconds); } else { // 处理无天数的HH:MM:SS.sss格式 const [hours, minutes, seconds] = durationStr.split(':'); totalSeconds += parseInt(hours) * 3600 + parseInt(minutes) * 60 + parseFloat(seconds); } return totalSeconds; } // 将总秒数转回易读的时长格式 function formatSecondsToDuration(totalSeconds) { const days = Math.floor(totalSeconds / (24 * 3600)); const remainingSeconds = totalSeconds % (24 * 3600); const hours = Math.floor(remainingSeconds / 3600); const minutes = Math.floor((remainingSeconds % 3600) / 60); const seconds = remainingSeconds % 60; let durationStr = ''; if (days > 0) { durationStr += `${days} days, `; } durationStr += `${hours.toString().padStart(2, '0')}:${minutes.toString().padStart(2, '0')}:${seconds.toFixed(6)}`; return durationStr; }
内容的提问来源于stack exchange,提问作者gwydion93
相关产品推荐
相关产品推荐

