最近公司开发的EMIS系统有个模块需要按excel格式写,原先有个estartable插件,我们经理写的,在原来的模块上面很好用,由于我水平有限,我在短期内不能清晰的修改或扩展它,最近掌握了angularJS,突发奇想,自己写了这套,没有写的太高深,但效果很满意哦。,废话、又是废话一堆,那么咱们上截图看看啥样的效果吧:
理想的样子、也是最终的效果
基于angularJS 强大的数据绑定实现的实时计算功能
异常受我喜爱的各大优势
有点脑残了,光把优势写在图片上了,忘记拷贝到这里了。…..
简单罗列使用优势:
外观:
1、简单、美丽、看着就舒服…..醉了
操作:
1、新增一行,方便快捷,缺点:暂时不能在指定位置插入一行,需要优化功能
2、删除按钮:每行最前方有删除按钮,根据本行索引自动删除,同时也会传入本行id,会触发到数据库同步删除数据
3、保存:一行一个对象,存在json数据,逐行存储方式,避免服务器压力
4、强大的自动计算:可根据需要指定某些单元格的计算结果显示在某个单元格内,目前适用于本行内,不适用于异行操作
5、强大的编辑功能:随时随地,点谁编辑谁,即编即存,这全基于angular的双向数据绑定功能,不多解释。
6、自动显示序号功能,无需写代码,自己会展示。
…..
时间原因,不多解析;先上一部分代码看看喽
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" ng-app="birdApp">
<head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /><title></title><script src="../../../../../../js/jquery-1.10.2.min.js"></script><script src="../../../../../../js/jquery.query.js"></script><link href="../../../../../../js/bootstrap-3.2.0/css/bootstrap.css" rel="stylesheet" /><script src="../../../../../../js/angular/angular.js"></script><link href="css/edit.css" rel="stylesheet" />
</head>
<body ng-controller="birdCtrl"><div class="panel"><span class="btn btn-success" ng-click="save()">保存填写</span><button type="button" class="btn btn-danger" ng-click="addRow()">新增一行</button><small>单元格提示:<span style="background: #CBCBCB">灰色区域</span>为禁填,白色区域为选填内容,直接点击白色区域即可编辑</small></div><table><thead><tr><th rowspan="3" width="23">操作</th><th colspan="20" style="background-color: white"> 填报人:<input type="text" ng-model="username" /> 联系方式: <input type="text" ng-model="tel" /> </th><th colspan="2" style="background-color: #CC99FF ;">{{getData(-1)}}鸟巢处理情况</th><th colspan="6" style="background-color: #99CCFF">{{getData(0)}}鸟巢位置统计分析</th><th colspan="3" style="background-color: #CCFFCC">{{getData(1)}}登乘巡视计划</th></tr><tr><th rowspan="2" style="width:20px;">序号</th><th rowspan="2" style="width:60px;">线别</th><th rowspan="2" style="width:60px;">区段</th><th rowspan="2" style="width:60px;">段/车间/工区</th><th rowspan="2" style="width:50px;">登乘人员(或巡视人员)</th><th rowspan="2" style="width:50px;">登乘车次(或巡视时间)</th><th rowspan="2" style="background-color: #CCFFFF;width:80px;">{{getData(0)}}当日登乘发现鸟巢处所</th><th colspan="3" style="width:100px;">当日发现鸟巢数量</th><th rowspan="2" style="background-color: #CCFFFF;width:30px;">本周累计发现鸟巢数量</th><th colspan="3" style="width:40px;">本周已处理鸟巢数量</th><th rowspan="2" style="background-color: #CCFFFF;width:30px">本月累计发现鸟巢数量</th><th colspan="3">本月已处理鸟巢数量</th><th rowspan="2" style="width:30px;">目前遗留问题数量</th><th rowspan="2">目前遗留问题处所</th><th rowspan="2" style="background-color: #CC99FF;width:30px;">处理鸟巢数量</th><th rowspan="2" style="background-color: #CC99FF">鸟巢处理处所 </th><th rowspan="2" style="background-color: #99CCFF;width:20px;">补偿装置</th><th rowspan="2" style="background-color: #99CCFF; width: 20px; ">隔离开关底座</th><th rowspan="2" style="background-color: #99CCFF; width: 20px; ">腕臂底座</th><th rowspan="2" style="background-color: #99CCFF; width: 20px; ">硬横梁</th><th rowspan="2" style="background-color: #99CCFF; width: 20px; ">跳线肩架</th><th rowspan="2" style="background-color: #99CCFF; width: 20px; ">其它</th><th rowspan="2" style="background-color: #CCFFCC; width: 60px; ">段/车间/工区</th><th rowspan="2" style="background-color: #CCFFCC; width: 60px; ">登乘人员(巡视人员)</th><th rowspan="2" style="background-color: #CCFFCC; width: 60px; ">登乘车次(或巡视时间)</th></tr><tr><th style="width:35px;">合计</th><th style="width:30px;">需临时要点处理</th><th style="width:30px;">需纳入天窗处理</th><th style="width:35px;">合计</th><th style="width:30px;">临时要点处理</th><th style="width:30px;">纳入天窗计划</th><th style="width:35px;">合计</th><th style="width:30px;">临时要点处理</th><th style="width:30px;">纳入天窗计划</th></tr></thead><tbody><tr ng-repeat="item in todo.items "><td><button class="deletes" title="删除" ng-click='deleteRow({{$index}},item.id)'>x</button></td><td>{{$index+1}}</td><td><select ng-model="item.RAILWAYID"><option value="idlong">陇海线</option><option value="idjing">京广线</option><option value="idlx">龙线</option><option value="idfeiguang">飞光线</option><option value="idsanjing">三经线</option></select></td><td><select ng-model="item.SECTIONID"><option value="idlong">陇海线</option><option value="idjing">京广线</option><option value="idlx">龙线</option><option value="idfeiguang">飞光线</option><option value="idsanjing">三经线</option></select></td><td><input type="text" ng-model="item.JGNAME" /></td><td><input type="text" ng-model="item.CARPERSON" /></td><td><input type="text" ng-model="item.CARTIMES" /></td><td><input type="text" ng-model="item.LOCATION" /></td><td>{{(item.TODAYTEMP*1)+(1*item.TODAYADD)}}</td><td><input type="text" ng-model="item.TODAYTEMP" /></td><td><input type="text" ng-model="item.TODAYADD" /></td><td style="background-color: #CBCBCB">{{item.weekTotal}}</td><td style="background-color: #CBCBCB">{{item.weekCount}}</td><td style="background-color: #CBCBCB">{{item.weekDeul}}</td><td style="background-color: #CBCBCB">{{item.weekNaru}}</td><td style="background-color: #CBCBCB">{{item.monthTotal}}</td><td style="background-color: #CBCBCB">{{item.monthCount}}</td><td style="background-color: #CBCBCB">{{item.monthDeul}}</td><td style="background-color: #CBCBCB">{{item.monthNaru}}</td><td><input type="text" ng-model="item.yiliu" /></td><td><input type="text" ng-model="item.yiliuchusuo" /></td><td style="background-color: #CBCBCB">{{item.LEAVECOUNT}}</td><td style="background-color: #CBCBCB">{{item.LEAVELOCATION}}</td><td><input ng-model="item.TOTAL1" /></td><td><input ng-model="item.TOTAL2" /></td><td><input ng-model="item.TOTAL3" /></td><td><input ng-model="item.TOTAL4" /></td><td><input ng-model="item.TOTAL5" /></td><td><input ng-model="item.TOTAL6" /></td><td><input ng-model="item.PLANJGNAME" /></td><td><input ng-model="item.PLANCARPERSON" /></td><td><input ng-model="item.PLANCARTIMES" /></td></tr></tbody></table>{{todo.tips}}<div style="position:absolute;bottom:5px;left:10px;"><button type="button" class="btn btn-danger" onclick="top.closewin()">关闭</button><button type="button" class="btn btn-danger" ng-click="length()">显示数据</button></div><script type="text/javascript">//获取必要信息var today = $.query.get('time');var planid = $.query.get('id');//绑定一个存在的应用模型var birdApp = angular.module('birdApp', []);//绑定控制器birdApp.controller("birdCtrl", function ($scope, $http) {//总信息存储对象$scope.todo = {items: [],data: today.length > 6 ? today : '2016-01-01',tips: '正在加载数据...'};//首次加载数据|Bug:不能立即展示数据,需要手动点击显示|原因很难查$scope.load = function () {$.get('/Bureau/1power/catenary/specialplan/yearplan/bird_special/ashx/edit.ashx?r=' + Math.random(),{ act: 'list', planid: planid, createtime: today },function (ret) {if (ret.flag) {if (ret.datas.length > 0) {for (var i = 0; i < ret.datas.length; i++) {$scope.todo.items.push(ret.datas[i]);}$scope.username = ret.username;$scope.tel = ret.tel;$scope.todo.tips = '加载完毕';}}else {$scope.todo.tips = '暂无数据,请新增一行进行填写';}});};$scope.load();//得到日期$scope.getData = function (tag) {var temp = $scope.todo.data.split('-');if (temp.length != 3) {return $scope.todo.data;}var year = temp[0];var month = temp[1];var day = temp[2];switch (tag) {case 0://当天break;case 1://下一天if (day == DayNumOfMonth(year, month)) {month = Number(month) + 1;month = (month == 13) ? 1 : month;day = 1;}elseday = Number(day) + 1;break;case -1://上一天if (day == 1) {month = Number(month) - 1;year = (month == 0) ? Number(year) - 1 : year;month = (month == 0) ? 12 : month;day = DayNumOfMonth(year, month);}elseday = Number(day) - 1;break;}return month + "月" + day + "日";}//添加一行$scope.addRow = function () {var o = {"id": newguid(), "no": "", "RAILWAYID": "", "SECTIONID": '', "JGNAME": "","CARPERSON": "", "CARTIMES": "", "LOCATION": "无","dayCount": 0, "TODAYTEMP": 0, "TODAYADD": 0,"weekTotal": "", "weekCount": "", "weekDeul": "", "weekNaru": "","monthTotal": "", "monthCount": "", "monthDeul": "", "monthNaru": "","LEAVECOUNT": "", "LEAVELOCATION": "","TOTAL1": "", "TOTAL2": "", "TOTAL3": "", "TOTAL4": "", "TOTAL5": "", "TOTAL6": "","PLANJGNAME": "", "PLANCARPERSON": "", "PLANCARTIMES": "", "planid": planid, "CREATETIME": today};$scope.todo.items.push(o);}//保存$scope.save = function () {var flag = 0;for (var i = 0; i < $scope.todo.items.length; i++) {$.get('/Bureau/1power/catenary/specialplan/yearplan/bird_special/ashx/edit.ashx?r=' + Math.random(),{ act: 'save', data: $scope.todo.items[i], username: $scope.username, tel: $scope.tel },function (data) {if (data.flag) { flag++; }else { alert('第' + i + '条,保存失败,' + data.msg); }if (flag >= $scope.todo.items.length) { alert('保存成功'); }});}}//删除当前行$scope.deleteRow = function (index, rowid) {var tempArray = $scope.todo.items;$.get('/Bureau/1power/catenary/specialplan/yearplan/bird_special/ashx/edit.ashx?r=' + Math.random(),{ act: 'deleteRow', id: rowid },function (data) {alert('删除成功');});tempArray.splice(index, 1);if (tempArray.length > 0) {$scope.todo.items = tempArray;}else {$scope.todo.items = [];}}//长度测试$scope.length = function () {//alert($scope.username);}});//GUIDfunction newguid() {return ('xxxxxxxxxxxx4xxxyxxxxxxxxxxxxxxx').replace(/[xy]/g, function (c) { var r = Math.random() * 16 | 0, v = c == 'x' ? r : r & 0x3 | 0x8; return v.toString(16); });}//某月的天数function DayNumOfMonth(Year, Month) {return ((new Date(Year, Month, 0).getDate()));}</script>
</body></html>
css
table {font-size: 0.7em;}table th {background-color: #c0c0c0;}table th, td {text-align: center;border: 1px solid gray;}table td input, table td textarea {width: 100%;height: 100%;border: none;background-color: none;}table td input:hover {background-color: #EDEDED;}table th input{border:none;}.deletes {border-radius: 5px;border: 1px solid #ff6a00;}.deletes:hover {border: 2px solid #ff0000;background-color: #f00;color: white;}
服务器端:
<%@ WebHandler Language="C#" Class="edit" %>using System;
using System.Web;
using Newtonsoft.Json;
using System.Web.SessionState;
using System.Text;
using System.Data;public class edit : IHttpHandler, IRequiresSessionState
{xxx.Model.WJX_SPECIALPLAN_BIRD model = new xxx.Model.WJX_SPECIALPLAN_BIRD();xxx.BLL.WJX_SPECIALPLAN_BIRD bll = new xxx.BLL.WJX_SPECIALPLAN_BIRD();PageBase p = new PageBase();public void ProcessRequest(HttpContext context){string act = context.Request.Params["act"];switch (act){case "save":SaveOrUpdate(context);break;case "list":GetTodayList(context);break;case "deleteRow":DeleteRow(context);break;default:break;}}/// <summary>/// 逐条保存填写或更新填写/// </summary>/// <param name="context"></param>private void SaveOrUpdate(HttpContext context){string temp = "{\"flag\":";context.Response.ContentType = "text/json";try{//获取数据model.ID = context.Request.Params["data[id]"];model.JGID = p.of_GetUser().ORGANIZATIONGID2;model.RAILWAYID = context.Request.Params["data[RAILWAYID]"];model.SECTIONID = context.Request.Params["data[SECTIONID]"];model.JGNAME = context.Request.Params["data[JGNAME]"];model.CARPERSON = context.Request.Params["data[CARPERSON]"];model.CARTIMES = context.Request.Params["data[CARTIMES]"];model.LOCATION = context.Request.Params["data[LOCATION]"];model.TODAYTEMP = p.ext_int(context.Request.Params["data[TODAYTEMP]"]);model.TODAYADD = p.ext_int(context.Request.Params["data[TODAYADD]"]);model.LEAVECOUNT = context.Request.Params["data[LEAVECOUNT]"];model.LEAVELOCATION = context.Request.Params["data[LEAVELOCATION]"];model.TOTAL1 = context.Request.Params["data[TOTAL1]"];model.TOTAL2 = context.Request.Params["data[TOTAL2]"];model.TOTAL3 = context.Request.Params["data[TOTAL3]"];model.TOTAL4 = context.Request.Params["data[TOTAL4]"];model.TOTAL5 = context.Request.Params["data[TOTAL5]"];model.TOTAL6 = context.Request.Params["data[TOTAL6]"];model.PLANJGNAME = context.Request.Params["data[PLANJGNAME]"];model.PLANCARPERSON = context.Request.Params["data[PLANCARPERSON]"];model.PLANCARTIMES = context.Request.Params["data[PLANCARTIMES]"];model.CREATETIME = p.ext_date(context.Request.Params["data[CREATETIME]"]);model.PLANID = context.Request.Params["data[planid]"];model.USERNAME = context.Request.Params["username"];model.TEL = context.Request.Params["tel"];Maticsoft.DBUtility.DbHelperOra.connectionString = p.getconfig("DB1");//调用其他数据库//判断是否存在if (bll.Exists(model.ID))//更新{Maticsoft.DBUtility.DbHelperOra.connectionString = p.getconfig("DB1");//调用其他数据库bll.Update(model);}else//添加{bll.Add(model);}temp += "true}";}catch (Exception ex){context.Response.Write(temp + "false,\"msg\":\"" + ex.Message + "\"}");context.Response.End();}context.Response.Write(temp);context.Response.End();}/// <summary>/// 得到当天的填写记录/// </summary>/// <param name="context"></param>private void GetTodayList(HttpContext context){string planid = context.Request.Params["planid"];//XX-IDDateTime createtime = Convert.ToDateTime(p.ext_date(context.Request.Params["createtime"]));//想得到哪日数据string jgid =XXX;//当前XXstring datatime = createtime.Year + "/" + createtime.Month + "/" + createtime.Day;DataSet ds = bll.GetList(" 1=1 and planid='" + planid + "' and jgid='" + jgid +"' and createtime = to_date('" + datatime + "','yyyy-mm-dd') ");StringBuilder row = new StringBuilder();if (ds.Tables[0].Rows.Count > 0)row.Append("{\"flag\":true,\"datas\":[");elserow.Append("{\"flag\":false,\"datas\":[");foreach (DataRow rows in ds.Tables[0].Rows){row.Append("{\"id\":\"" + rows["id"] + "\",");row.Append("\"no\":\"\",");row.Append("\"RAILWAYID\":\"" + rows["RAILWAYID"] + "\",");row.Append("\"SECTIONID\":\"" + rows["SECTIONID"] + "\",");row.Append("\"JGNAME\":\"" + rows["JGNAME"] + "\",");row.Append("\"CARPERSON\":\"" + rows["CARPERSON"] + "\",");row.Append("\"CARTIMES\":\"" + rows["CARTIMES"] + "\",");row.Append("\"LOCATION\":\"" + rows["LOCATION"] + "\",");int dayCount = p.ext_int(rows["TODAYTEMP"]) + p.ext_int(rows["TODAYADD"]);row.Append("\"dayCount\":\"" + dayCount + "\",");row.Append("\"TODAYTEMP\":" + rows["TODAYTEMP"] + ",");row.Append("\"TODAYADD\":" + rows["TODAYADD"] + ",");row.Append("\"weekTotal\":\"\",");row.Append("\"weekCount\":\"\",");row.Append("\"weekDeul\":\"\",");row.Append("\"weekNaru\":\"\",");row.Append("\"monthTotal\":\"\",");row.Append("\"monthCount\":\"\",");row.Append("\"monthDeul\":\"\",");row.Append("\"monthNaru\":\"\",");row.Append("\"LEAVECOUNT\":\"" + rows["leaveCount"] + "\",");row.Append("\"LEAVELOCATION\":\"" + rows["leaveLocation"] + "\",");row.Append("\"TOTAL1\":\"" + rows["TOTAL1"] + "\",");row.Append("\"TOTAL2\":\"" + rows["TOTAL2"] + "\",");row.Append("\"TOTAL3\":\"" + rows["TOTAL3"] + "\",");row.Append("\"TOTAL4\":\"" + rows["TOTAL4"] + "\",");row.Append("\"TOTAL5\":\"" + rows["TOTAL5"] + "\",");row.Append("\"TOTAL6\":\"" + rows["TOTAL6"] + "\",");row.Append("\"PLANJGNAME\":\"" + rows["PLANJGNAME"] + "\",");row.Append("\"PLANCARPERSON\":\"" + rows["PLANCARPERSON"] + "\",");row.Append("\"PLANCARTIMES\":\"" + rows["PLANCARTIMES"] + "\",");row.Append("\"planid\":\"" + rows["planid"] + "\",");row.Append("\"CREATETIME\":\"" + rows["CREATETIME"] + "\"},");}if (ds.Tables[0].Rows.Count > 0){context.Response.Write(row.ToString().Substring(0, row.ToString().Length - 1) + "],\"username\":\"" + ds.Tables[0].Rows[0]["username"] + "\",\"tel\":\"" +ds.Tables[0].Rows[0]["tel"] + "\"}");context.Response.ContentType = "text/json";context.Response.End();}else{context.Response.Write(row.ToString() + "]}");context.Response.ContentType = "text/json";context.Response.End();}}/// <summary>/// 删除一行数据/// </summary>/// <param name="context"></param>private void DeleteRow(HttpContext context){string rowid = context.Request.Params["id"];if (bll.Exists(rowid)){bll.Delete(rowid);}}public bool IsReusable{get{return false;}}}
后来新增了很多功能,比如合计