jqGrid 4.15.3日期列filterToolbar精确匹配失效问题排查
eq精确匹配原始/Date(xxx)/格式无效的问题 这个问题的核心原因是:jqGrid的filterToolbar在执行eq精确匹配时,默认是和单元格的显示值(也就是经过formatter: "date"处理后的d.m.Y格式字符串)进行比较,而不是原始的/Date(xxx)/格式值。而ge操作正常是因为sorttype: "date"让jqGrid自动将原始日期转换成日期对象进行大小比较,不受字符串格式影响。
下面提供两种实用的解决方案:
方案一:自动转换输入的原始日期格式为显示格式
这种方法最直接,通过监听搜索框的输入事件,把用户输入的/Date(xxx)/格式自动转换成对应的dd.mm.yy格式(和你的datepicker格式一致),这样eq匹配就会和显示值对应上。
修改你的列模型中的searchoptions,添加dataEvents:
{ "search" : "true", "label" : "DateCreated", "name": "DateCreated", "width" : 140, "sorttype": "date", "formatter" : "date", "formatoptions" : { "newformat" : "d.m.Y" }, "searchoptions" : { "clearSearch" : "false", "sopt": ["eq","ge"], "dataInit" : "(function(el) { $(el).datepicker( { firstDay: 1, dateFormat: 'dd.mm.yy' } ); }) ", "dataEvents": [ { type: 'change keyup', fn: function(e) { const input = $(this); const val = input.val().trim(); // 匹配/Date(数字)/格式 const dateMatch = val.match(/^\/Date\((\d+)\)\/$/); if (dateMatch) { const timestamp = parseInt(dateMatch[1], 10); // 转换成datepicker的格式:dd.mm.yy const formattedDate = $.datepicker.formatDate('dd.mm.yy', new Date(timestamp)); input.val(formattedDate); } } } ] } }
这样用户输入/Date(1515401700270)/时,输入框会自动转换成对应的日期字符串(比如08.01.2018,根据时间戳计算),eq匹配就能正常找到对应的行了。
方案二:让eq匹配基于原始日期值
如果你希望直接用原始的/Date(xxx)/格式进行匹配,而不转换输入格式,可以通过自定义搜索逻辑实现。设置searchoptions的custom: true,并编写customSearch函数来处理eq的比较逻辑:
{ "search" : "true", "label" : "DateCreated", "name": "DateCreated", "width" : 140, "sorttype": function(cellValue) { // 自定义sorttype,返回日期对象用于排序和比较 const ms = cellValue.replace(/\/Date\((\d+)\)\//, "$1"); return new Date(parseInt(ms, 10)); }, "formatter" : "date", "formatoptions" : { "newformat" : "d.m.Y" }, "searchoptions" : { "clearSearch" : "false", "sopt": ["eq","ge"], "dataInit" : "(function(el) { $(el).datepicker( { firstDay: 1, dateFormat: 'dd.mm.yy' } ); }) ", "custom": true, "customSearch": function(options) { const oper = options.oper; const searchVal = options.searchValue.trim(); const cellVal = options.cellvalue; if (oper === "eq") { // 处理两种输入格式:原始/Date(xxx)/ 或 显示格式dd.mm.yy const dateMatch = searchVal.match(/^\/Date\((\d+)\)\/$/); if (dateMatch) { // 输入的是原始格式,直接和单元格原始值比较 return searchVal === cellVal; } else { // 输入的是显示格式,转换成原始格式后比较 const searchDate = $.datepicker.parseDate('dd.mm.yy', searchVal); const searchRaw = `/Date(${searchDate.getTime()})/`; return searchRaw === cellVal; } } else if (oper === "ge") { // 保持ge的日期大小比较逻辑 const cellDate = new Date(parseInt(cellVal.replace(/\/Date\((\d+)\)\//, "$1"), 10)); const searchDate = $.datepicker.parseDate('dd.mm.yy', searchVal); return cellDate >= searchDate; } return false; } } }
这个方案会同时支持两种格式的eq搜索:不管用户输入原始的/Date(xxx)/还是格式化后的日期字符串,都能正确匹配到对应的行。
关于srcFormat的补充说明
你提到的srcFormat确实和日期解析有关,但因为你的原始日期是/Date(xxx)/这种微软特定格式,jqGrid默认的srcFormat选项无法直接解析它,所以需要我们通过自定义函数(比如sorttype、formatter或者搜索逻辑)来处理这种格式的转换。
内容的提问来源于stack exchange,提问作者theChampion

