最稳妥解法是直接修改table.exportFile函数,通过为≥15位纯数字字段末尾添加制表符 ,欺骗Excel将其识别为文本,避免科学计数法丢失精度。
直接改 table.exportfile 函数是最稳妥的解法,不依赖后端、不增加请求、导出即保真。其他“前端拼接 csv 字符串”或“用 sheetjs 重写导出”的方案,要么绕过 layui 原生逻辑埋坑,要么引入额外体积和兼容性问题。
为什么导出后长数字变 1.23E+17?
这不是 Layui 的 bug,是 Excel 的默认行为:当单元格内容看起来像纯数字且长度 ≥15 位时(如身份证号、订单号、银行卡号),Excel 会自动转为双精度浮点数并显示为科学计数法——此时原始字符已丢失,无法还原。
关键点在于:Layui 导出本质是生成 CSV 或简易 XLS 字符串,它不控制 Excel 打开时的列格式。所以必须在数据写入前「欺骗」Excel:让其认为该字段是文本而非数值。
- Excel 识别文本的常见方式有三种:
'12345678901234567890(单引号前置)、"12345678901234567890"(双引号包裹)、12345678901234567890(末尾加制表符) - Layui 原生导出用的是逗号分隔 + 双引号包裹,但没对长数字做特殊处理,所以 Excel 直接按数值解析
- IE 下走
navigator.msSaveBlob,非 IE 走data:URL,两种路径都要覆盖
修改 table.js 中的 exportFile 函数
找到 layui/lay/modules/table.js,搜索 exportFile = function(通常在第 2 个匹配项),将其整个函数体替换为以下逻辑(仅核心改动处加注释):
table.exportFile = function (e, t, i) {
t = t || table.clearCacheKey(table.cache[e]);
i = i || "csv";
var a = table.config[e] || {},
l = { csv: "text/csv", xls: "application/vnd.ms-excel" }[i],
n = document.createElement("a"),
type = i,
meta = l,
title = a.title;
// ? 关键:遍历每行数据,对疑似长数字字段追加
layui.each(t, function (ks, vs) {
var inner = {};
layui.each(vs, function (k, v) {
// 判断是否为「纯数字且长度 ≥15」,也可用 /^d{15,}$/
if (typeof v === 'string' && /^d+$/.test(v) && v.length >= 15) {
vs[k] = v + ' '; // 强制 Excel 当作文本
}
inner[k] = vs[k];
});
t[ks] = inner;
});
if (device.ie) {
// IE 分支:手动拼 CSV 字符串,同样需对长数字加 (已有逻辑)
var i = [], a = [];
layui.each(t, function (t, l) {
var n = [];
layui.each(table.clearCacheKey(l), function (e, t) {
if (typeof t === 'string' && /^d+$/.test(t) && t.length >= 15) {
n.push('"' + t + ' "'); // 注意:这里加 后再包双引号
} else {
n.push('"' + (t || "") + '"');
}
});
a.push(n.join(","));
});
// ...后续 msSaveBlob 逻辑保持不变
} else {
// 非 IE:走 data: URL,encodeURIComponent 前确保长数字已带
return n.href = "data:" + l + ";charset=utf-8,ufeff" + encodeURIComponent(function () {
var i = [], a = [];
layui.each(t, function (t, l) {
var n = [];
layui.each(table.clearCacheKey(l), function (e, t) {
if (typeof t === 'string' && /^d+$/.test(t) && t.length >= 15) {
n.push('"' + t + ' "');
} else {
n.push('"' + (t || "") + '"');
}
});
a.push(n.join(","));
});
return i.join(",") + "
" + a.join("
");
}());
}
};
注意:不要直接复制网上残缺的片段,上面代码已补全 IE 和非 IE 分支中对长数字的统一处理逻辑,且避免了 vs[k] = vs[k] + ' ' 在非字符串类型上出错的问题。
如果不能改源码,用 templet 或导出前预处理数据
适用于只改局部、无权限动 table.js 的场景。原理是导出前把目标字段值显式转成带 的字符串:
- 若导出的是当前表格实例(
table.exportFile('id')),可在列定义中加templet:
{ field: 'orderNo', title: '订单号', templet: '<div>{{ d.orderNo + "\t" }}</div>' }
- 若导出的是自定义数据(
table.exportFile(headers, data, opts)),导出前先映射处理:
var exportData = data.map(item => ({ ...item, orderNo: item.orderNo + ' ' })); table.exportFile(['订单号', '姓名'], exportData, {type: 'xls'});
⚠️ 这种方式缺点明显:导出列头和数据结构需手动对齐;如果字段含 HTML 标签或换行符, 可能被忽略;且不适用于 IE 下的 Blob 导出路径。
真正容易被忽略的是:即使加了 ,Excel 有时仍会自动去除首尾空白并重新解析。最保险的做法是在服务端导出时用真正的 Excel 库(如 Apache POI / ExcelJS)写入 TEXT 类型单元格——但如果你必须用 Layui 前端导出,那就老老实实改 table.js,别信“加单引号就行”这种半吊子方案,它在 CSV 场景下经常失效。


















