最近公司要做一套台账系统。有一下几个需求:
1、表头复杂。表头不固定,且多行。
2、经常格式变化,且台账不止一种。
3、录入操作要方便。
4、录入的数据能够对比检索。
贴几张图大家看一下,相信不少人碰见过:
说明:灰色部分为表头,下面是填写的数据。
前端效果
通过几天的分析,得出以下结论:
1、台账能够灵活配置。不能做死。
2、填写要方便,最好能够类似于在线EXCEL,能够插入,删除,合并,复制粘贴等
3、且能够读取及放入数据库。方便后期统计分析。
3、填写时能够预留空行,并且能够初始化一些常量,还能够单元格合并。(例如图:每次预留2行;第一列上下合并,第二列初始化为开始|结束)。
经过半个月的努力,经过界面设计、数据库设计、开发等,也算稍有成就。
好吧,闲话少说,直接贴最终效果图
在线EXCEL选取
在线EXCEL网上成熟的案例不少。综合各种原因我决定选用jquery.handsontable
1、
handsontable是基于jquery的一个轻量级表格插件,无需安装其他环境。浏览器兼容性比较好,简单易学,因此在线EXCEL原型就选用它了。
贴一下handsontable官方实力图片:
可以看出handsontable是一个非常轻量级的jquery插件。支持插入、删除、复制等操作。
操作如片:
想了解更多可以访问
前端代码说明
当然如果只做在线EXCEL,handsontable完全够用。但是为了符合台账的需要。需要扩充及更改几个地方:
1、多行表头
2、加载数据
3、单元格合并
4、预留空行及空行初始值
5、其他(汉化等)
1、多行表头
我们知道一个表格标签定义如下:
<table border="1"><thead><tr><th>1</th><th>1</th><th>1</th><th>1</th><th>1</th><th>1</th></tr></thead><tbody><tr><td id="Td1">1</td><td id="Td2">2</td><td id="Td9">2</td><td id="Td10">2</td><td id="Td11">2</td><td id="Td12">2</td></tr></tbody></table>
多行表头也就是要在<thead>标签中插入多行<tr></tr>,然后左右合并、上下合并一些单元格,合并的操作就需要colspan,rowspan属性
首先要定义一个能够向handsontable绘制多表头的函数:
container.handsontable("setMcolHeaders", colHeaders);//设置表头
其中colHeaders就是我们要传入的表头对象。colHeaders是绘制表头的重要参数,由于本系统的特殊性,我把多行表头竖着放,实际上就是一个树。
这样既可以应用已有的jquery.ztree插件来配置表头,而且又能满足多表头的需要。
当然在配置的时候对应每个节点还需要其他一些参数,例如是否上下合并、初始值、排序号、宽度等
生成的colHeaders对象如下:
//配置表头colHeaders = [{ id: ‘id1’, name: ‘表头1’, depth: 0, leafs: 2, children: [{ id: ‘id11’, name: ‘表头11’, depth: 1, leafs: 0, leafnum: ‘001’, ismerger: 1 }, { id: ‘id12’, name: ‘表头12’, depth: 1, leafs: 0, leafnum: ‘002’, ismerger: 0 }] },{ id: ‘id2’, name: ‘表头2’, depth: 0, leafs: 2, children: [{ id: ‘id21’, name: ‘表头21’, depth: 1, leafs: 0, leafnum: ‘003’, ismerger: 0 }, { id: ‘id22’, name: ‘表头22’, depth: 1, leafs: 0, leafnum: ‘004’, ismerger: 0 }] },{ id: ‘id3’, name: ‘项’, depth: 0, leafs: 0, value: ‘检测|检修’, leafnum: ‘005’, ismerger: 0 },{id: ‘id4’, name: ‘表头4’, depth: 0, leafs: 3, children: [{ id: ‘id41’, name: ‘表头41’, depth: 1, leafs: 2, children: [{ id: ‘id411’, name: ‘表头411’, depth: 2, leafs: 0, leafnum: ‘006’, ismerger: 0 }, { id: ‘id412’, name: ‘表头412’, depth: 2, leafs: 0, leafnum: ‘007’, ismerger: 0 }] },{ id: ‘id42’, name: ‘表头42’, depth: 1, leafs: 0, value: ‘标准’, leafnum: ‘008’, ismerger: 0 }]}];
colHeaders.children即为当前节点下的子节点对象。container.handsontable("setMcolHeaders", colHeaders);函数的作用就是把colHeaders树对象转换成table行对象,不是太难,这里不再贴出代码。
2、加载数据源
对于加载数据源.handsontable提供了几种数据格式,及加载方式。
数据源格式可以是array、object、function几种。这里为了方面与数据库操作对接,采用object对象数据源。
object实例代码:
var nestedObjects = [ {id: 1, name: {first: "Ted", last: "Right"}, address: ""}, {id: 2, name: {first: "Frank", last: "Honest"}, address: ""}, {id: 3, name: {first: "Joan", last: "Well"}, address: ""}];var $container = $("#example4");$container.handsontable({ data: nestedObjects, startRows: 5, startCols: 4, colHeaders: true, columns: [{data: "id"},{data: "name.first"},{data: "name.last"},{data: "address"} ], minSpareRows: 1});
为了能够实现数据源的值与表单头列对应。我们必须要设置handsontab的lecolumns对象。从第一步表单头的配置可以看出,其实数据源对应的就是表单头的最后一行树叶。
即数据源的格式如下{表头11:3,表头12:Ted,表头21:b,表头22:地址…}
既然知道了数据源与多行表头的关系。那么第一步就是要确定多行表头的最后一行树叶对象。这样才能确定handsontab的地图属性:lecolumns。
先定义树叶对象:
var leafHeaders = [];//树叶集合var leafWidths = [];//树叶宽度集合
具体怎么获取,可以放到第一步的container.handsontable("setMcolHeaders", colHeaders);里面。
踮起脚尖,我们就能离幸福更近点吗?