//js部分
//捕获离开当前页面或刷新当前页面的事件 window.onbeforeunload = function (e) { //var e = window.event || e; //e.returnValue = ("确定离开当前页面吗?"); validateAndSave(); } //handsometable相关 var container = document.getElementById('handsontable'); var dataObject = initData(); var dataCopy = JSON.parse(JSON.stringify(dataObject)); /** * 获取初始化数据 */ function initData() { var resData; //获取数据源 $.ajax({ async: false, url: "/YTSYCGB/GetHandsometableInitData", data: { oaid: $("#param_xmid").val() }, success: function (data) { resData = data; } }); if (resData == undefined || resData == null) { return []; } return JSON.parse(resData); } //用来保存修改过但还未被保存的行索引 var changeLines = new Set(); var hot = new Handsontable(container, { //调用handsometable的绑定数据的方式是: hot.getData() data: dataCopy, //定义数据源为空时,handsometable的数据格式 dataSchema: { TID: null, BGMC: null, BGLX: null, XMMC: null, XMID: null, ZKBH: null, ZKQYBH: null, YTMC: null, YYBH: null, SYBH: null, KLMD: null, HG: null, ZR: null, BH: null, HSL: null, XSL: null, BHXSL: null, KXL: null, BHKYQDDZ: null, BHKYQDPJ: null, TRKYQDDZ: null, TRKYQDPJ: null, RHXS: null, BXMLDZ: null, BXMLPJ: null, TXMLDZ: null, TXMLPJ: null, BSB: null, KLQDDZ: null, KLQDPJ: null, TJFTG: null, TJFC: null, ZXRCFTG: null, ZXRCFNJLC: null, XGXS: null, NMCJ: null, BZ: null, GROUPID: null }, colWidths: 100, //列宽 rowHeights: 33, //行高 //通过定义width和height来决定容器的宽和高,当内容超出时,便会显示滚动条 height: 650, '100%', //通过设置fixedRowsTop来决定滚动时,锁定的行;通过设置fixedColumnsLeft来决定滚动时,锁定的列 fixedColumnsLeft: 9, //设置列名 colHeaders: ['操作', '报告名称', '报告类型', '项目名称', '项目编号', '钻孔编号', '钻孔取样编号', '岩土名称', '岩样编号', '实验编号', '颗粒密度', '烘干', '自然', '饱和', '含水率', '吸水率', '饱和吸水率', '孔隙率', '饱和抗压强度单值', '饱和抗压强度平均', '天然抗压强度单值', '天然抗压强度平均', '软化系数', '变形模量单值', '变形模量平均', '弹性模量单值', '弹性模量平均', '泊松比', '抗拉强度单值', '抗拉强度平均', '图解法tg', '图解法C', '最小二乘法tg', '最小二乘法内聚力C', '相关系数', '内摩擦角', '备注', '报告分组编号'], //单独设置列宽 colWidths: [47, 47, 47, 47, 47, 47, 47, 60, 80, 60, 60, 47, 47, 47, 47, 47, 74, 50, 114, 74, 114, 74, 74, 94, 74, 94, 74, 50, 94, 74, 74, 74, 94, 124, 74, 74, 200, 74], //设置显示行索引 rowHeaders: true, //不允许拖拽填充 //fillHandle: false, //许可秘钥 licenseKey: 'non-commercial-and-evaluation', //留出一行空白,用作新增 //minSpareRows: 1, //隐藏的列索引 例:columns:[0,1,2],隐藏0,1,2三列 //如果需要显示隐藏列的位置标识,可以在hiddenColumns中加上 indicators: true hiddenColumns: { columns: [0,1,2,3,4,5,6,19,21,24,26,29,37] }, //className用作定义表格的对齐方式,多个值用空格隔开 //水平方向上的值: htLeft, htCenter, htRight, htJustify //垂直方向上的值: htTop, htMiddle, htBottom className: "htCenter htMiddle", //定义列和数据源的映射关系和一些其它属性 columns: [ { data: 'TID' }, { data: 'BGMC' }, { data: 'BGLX' }, { data: 'XMMC' }, { data: 'XMID' }, { data: 'ZKBH' }, { data: 'ZKQYBH' }, { data: 'YTMC', readOnly: true }, { data: 'YYBH', readOnly: true }, { data: 'SYBH', type: 'numeric' }, { data: 'KLMD', type: 'numeric' }, { data: 'HG', type: 'numeric' }, { data: 'ZR', type: 'numeric' }, { data: 'BH', type: 'numeric' }, { data: 'HSL', type: 'numeric' }, { data: 'XSL', type: 'numeric' }, { data: 'BHXSL', type: 'numeric' }, { data: 'KXL', type: 'numeric' }, { data: 'BHKYQDDZ', type: 'numeric' }, { data: 'BHKYQDPJ', type: 'numeric' }, { data: 'TRKYQDDZ', type: 'numeric' }, { data: 'TRKYQDPJ', type: 'numeric' }, { data: 'RHXS', type: 'numeric' }, { data: 'BXMLDZ', type: 'numeric' }, { data: 'BXMLPJ', type: 'numeric' }, { data: 'TXMLDZ', type: 'numeric' }, { data: 'TXMLPJ', type: 'numeric' }, { data: 'BSB', type: 'numeric' }, { data: 'KLQDDZ', type: 'numeric' }, { data: 'KLQDPJ', type: 'numeric' }, { data: 'TJFTG', type: 'numeric' }, { data: 'TJFC', type: 'numeric' }, { data: 'ZXRCFTG', type: 'numeric' }, { data: 'ZXRCFNJLC', type: 'numeric' }, { data: 'XGXS', type: 'numeric' }, { data: 'NMCJ', type: 'numeric' }, { data: 'BZ' }, { data: 'GROUPID' } ] ////当table数据发生改变的相应事件,handsometable的afterChange在多个单元格同时发生改变时,只能监听到第一个单元格的变化。为了解决这个问题,我写了getChangeLines()来代替它的作用 //afterChange: function (change, source) { // //change[0]是一个数组,第一个值是行索引/行名,第二个值是列索引/列名,第三个值是修改前的值,第四个值是修改后的值 // //source的值目前知道:loadData(加载数据);edit(新增或编辑) // if (source === 'loadData') { // return; // } // if (change[0][2] == change[0][3]) { // //未改变值 // return; // } // changeLines.add(change[0][0]); // //console.log("修改了ID为:" + dataCopy[change[0][0]].TID + "的数据,值由" + change[0][2] + "修改为:" + change[0][3]); //} }); //保存已经改变的数据 function saveChangeData(datas) { //重置changeLines changeLines.clear(); //保存 $.ajax({ url: "/YTSYCGB/SaveHandsometableData", type:'post', data: { modelsStr: JSON.stringify(datas) }, success: function () { toastr.info("系统已自动保存!"); dataObject = JSON.parse(JSON.stringify(dataCopy)); }, error: function () { toastr.error("自动保存失败!"); } }); } /** * 验证有效性并保存 */ function validateAndSave() { getChangeLines(); if (changeLines.size == 0) { //数据没有发生任何更 return; } var datas = []; var rowIndexs = [];//待保存的行索引,用作验证数据是否有效 changeLines.forEach(item => { //将修改过的数据添加到数组 datas.push(dataCopy[item]); rowIndexs.push(item); }); hot.validateRows(rowIndexs, (valid) => { if (valid) { saveChangeData(datas); } else { toastr.error("存在无效数据,无法自动保存!"); } }); } /** * 获取改变行的索引 */ function getChangeLines() { for (var i = 0; i < dataCopy.length; i++) { try { Object.keys(dataCopy[i]).forEach(key => { if (dataObject[i][key] != dataCopy[i][key]) { changeLines.add(i); foreach.break = new Error("StopIteration");//利用异常跳出forEach循环 } }); } catch (e) { } } } //每过5s自动保存一次 setInterval(function () { validateAndSave(); }, 5000);
2、Html部分
<div> <div id="handsontable"></div> <div>