【背景】
最近公司的问题汇总平台差不多接近尾声,回顾前段时间领导任命做的报表真是别有一番成长波折;在这之前以为问题汇总平台就差不多完结了,结果原来压轴的在后面呢,报表的设计涵盖了本平台80%的核心内容,既然这么重要就更得放上十足的精神干了O(∩_∩)O~
【简介】
报表的实现使用的是ECharts:百度开源的纯 Javascript 图表库
使用方法:百度搜素ECharts,进入它的官网,有对应的文档以及实例,直接选择自己相应的实例,粘贴到你的代码中,按照它需要的数据结构将数据传递过去,就会出现你想要的优美报表。
【规划】
做程序猿不可能当一辈子代码搬运工,基于这样的思想指导,面对领导安排的活儿,我们并没有将自己局限到最终实现报表的层次,而是深入业务,融入公司需求,站到各种角色的角度来考虑报表的设计、报表将要反应的问题、呈现的趋势,对于战略决策者能够提供一个怎样的数据支撑。
使用何种工具进行报表的实现也属于我们考虑的范畴,如何才能够做到高效、优质的开发是我们方向,给客户呈现出制作人员的核心思考以及达到的实际高价值是我们的终极目标。
有了这样的整体思路下面就是我们的部分实现效果图O(∩_∩)O~
【效果】
【实例】
一、html代码
<span style="font-family:KaiTi_GB2312;font-size:18px;">- <!--整体div--> <div id="zhengti" style="width:900px;margin: 0 auto;margin-bottom: 10px;margin-top: 40px;"> <!--图形div visible="false"--> <div id="main" style="width:800px;height:450px; float:left; display:inline; margin-bottom:30px;"></div> <br /> <!--列表div--> <div id="editor-grid" style=" border-top:none; width:800px;height:300px;"></div> </div> -</span>
二、js代码
<span style="font-family:KaiTi_GB2312;font-size:18px;">- //页面刷新的方法加载 $(document).ready(function () { //获取隐藏控件中的值 var rejctphenomenontypename = ""; //准备数据 var json; $.ajax({ url: '../ashx/chartashx/reject_belongs_system_charts.ashx?cmd=cmd&rejctphenomenontypename=' + rejctphenomenontypename, type: 'post', dataType: 'json', async: false, success: function (data) { json = data; }, error: function (data) { alert("加载失败,请联系管理员!"); } }); loadcharts(json); loadList(json); document.title = "问题汇总"; }); //展示图标function function loadcharts(json) { //图表展示 var myChart1 = echarts.init(document.getElementById('main')); option = { //图表标题 title: { text: "子系统不合格品问题统计", //正标题 x: "center", //标题水平方向位置 //正标题样式 textStyle: { fontSize: 20 }, //副标题样式 subtextStyle: { fontSize: 12, color: "red" } }, tooltip: { trigger: 'axis', axisPointer: { // 坐标轴指示器,坐标轴触发有效 type: 'shadow' // 默认为直线,可选为:'line' | 'shadow' } }, //工具箱配置 toolbox: { show: true, feature: { mark: { show: true }, // 辅助线标志,上图icon左数1/2/3,分别是启用,删除上一条,删除全部 dataView: { show: true, readOnly: false },// 数据视图,上图icon左数8,打开数据视图 magicType: { show: true, type: ['line', 'bar', 'stack', 'tiled'] },// 图表类型切换,当前仅支持直角系下的折线图、柱状图转换,上图icon左数6/7,分别是切换折线图,切换柱形图 restore: { show: true }, // 还原,复位原始图表,上图icon左数9,还原 saveAsImage: { show: true } // 保存为图片,上图icon左数10,保存 } }, //图例内容以及位置 legend: { //加载图例内容,这里json.a是对应的数组元素 data: json.tuli, y: "bottom" }, grid: { left: '0%', right: '0%', bottom: '20%', containLabel: true }, //x轴的数据 xAxis: [ { axisLabel: { rotate: 60, interval: 0 }, type: 'category', //加载x轴的数据,这里 //data: ['部门1', '部门2', '部门3', '部门4'], data: json.xzhou, name: "部门" } ], //y轴的数据 yAxis: [ { type: 'value', name: "数值" } ], //图中的数据,这里是通过匹配的来的! series: json.tushuju }; //将配置好的图加载到div中 myChart1.setOption(option); //单击穿透 myChart1.on('click', function (param) { var rejectbelongssystemname = param.name; //window.open("reject_phenomenon_type_charts.aspx?rejectbelongssystemname=" + rejectbelongssystemname); window.open("reject_phenomenon_type_charts1.aspx?rejectbelongssystemname=" + rejectbelongssystemname, 'newwindow', 'height=672,width=1182,top=100,left=100,toolbar=no,menubar=no,scrollbars=no,resizable=no, location=no,status=no') }); } //加载列表function function loadList(json) { var columns = [json.listbiaotou]; //gridData属性 InitGrid = { //nowrap: true, //autoRowHeight: true, striped: true, singleSelect: true, // url: Init.url + '&cmd=list', //data: [{ "Id": 1, "region": "8号线", "SR": 100, "ST": 80 }, { "Id": 2, "region": " 北京亦庄线", "SR": 40, "ST": 80 }, { "Id": 3, "region": " 重庆3号线", "SR": 30, "ST": 80 }, { "Id": 4, "region": " 成都3号线", "SR": 10, "ST": 80 }, { "Id": 5, "region": " 大连线", "SR": 10, "ST": 80 }], data: json.listshuju, fitColumns: true, idField: 'Id', pagination: true, rownumbers: true, pageSize: 10, pageList: [5, 10, 15, 20, 50, 80, 200], //toolbar: toolbar, columns: columns, // fit: true, //border: true } //创建数据表格 dataGrid = $("#editor-grid").datagrid(InitGrid); } -</span>
三、一般处理程序代码
<span style="font-family:KaiTi_GB2312;font-size:18px;">- #region 3、子系统不合格品问题统计-马康-2016年9月28日17:16:23 /// <summary> /// 3、子系统不合格品问题统计-马康-2016年9月28日17:16:23 /// </summary> /// <returns></returns> private string queryList(string rejctphenomenontypename) { //实例化BLL层 ProblemSpotBLL problemspotbll = new ProblemSpotBLL(); //查询数据 DataSet projectProblemList = problemspotbll.queryrejectbelongssystemList(rejctphenomenontypename); DataTable tables2 = new DataTable(); tables2.Columns.Add("producttype", typeof(String)); DataRow row = tables2.NewRow(); row["producttype"] = "不合格品"; tables2.Rows.Add(row); projectProblemList.Tables.Add(tables2); StringBuilder sb = new StringBuilder(); String resultStr = ""; if (projectProblemList.Tables.Count > 0) { //总括号 sb.Append("{"); #region 1、图例项对象数组 //第一个图例项对象数组 sb.Append("\"tuli\":["); for (int i = 0; i < projectProblemList.Tables[2].Rows.Count; i++) { sb.Append("\"" + projectProblemList.Tables[2].Rows[i][0] + "\","); } sb.Remove(sb.Length - 1, 1); sb.Append("],"); #endregion #region 2、x轴中的项目 //第一个图例项对象数组 sb.Append("\"xzhou\":["); for (int i = 0; i < projectProblemList.Tables[1].Rows.Count; i++) { sb.Append("\"" + projectProblemList.Tables[1].Rows[i][0] + "\","); } sb.Remove(sb.Length - 1, 1); sb.Append("],"); #endregion #region 3、图中的数据 //第一个图例项对象数组 sb.Append("\"tushuju\":["); //最外层循环,循环项目 for (int i = 0; i < projectProblemList.Tables[2].Rows.Count; i++) { sb.Append("{"); sb.Append("\"name\":\"" + projectProblemList.Tables[2].Rows[i][0] + "\","); sb.Append("\"type\":\"bar\","); sb.Append("\"data\":["); //定义一个临时数组,来存储下面要获得的数据 int[] arraylist = new int[projectProblemList.Tables[1].Rows.Count]; //根据项目匹配总数据中的值 for (int j = 0; j < projectProblemList.Tables[0].Rows.Count; j++) { //如果有相等的值,则进入循环部门(这里肯定会至少有一个项目名称与之匹配,因为项目名称是根据这个datatable去重筛选出来的) string adsf = projectProblemList.Tables[0].Rows[j][1].ToString(); string asdfasdf = projectProblemList.Tables[2].Rows[i][0].ToString(); if (projectProblemList.Tables[0].Rows[j][1].ToString() == projectProblemList.Tables[2].Rows[i][0].ToString()) { //通过循环产品,向数组中加入内容 for (int k = 0; k < projectProblemList.Tables[1].Rows.Count; k++) { if (projectProblemList.Tables[1].Rows[k][0].ToString() == projectProblemList.Tables[0].Rows[j][0].ToString()) { arraylist[k] = (int)projectProblemList.Tables[0].Rows[j][2]; } } } } //循环将数组拼接到字符串中 for (int k = 0; k < arraylist.Length; k++) { sb.Append("\"" + arraylist[k] + "\","); } sb.Remove(sb.Length - 1, 1); sb.Append("]"); sb.Append("},"); } sb.Remove(sb.Length - 1, 1); sb.Append("],"); #endregion #region 4、列表中的表头 double kuandu = (800 - 30) / (projectProblemList.Tables[1].Rows.Count + 1) - 3; //第一个图例项对象数组 sb.Append("\"listbiaotou\":["); sb.Append("{"); sb.Append("\"field\":\"id\","); sb.Append("\"hidden\":\"true\""); sb.Append("},"); sb.Append("{"); sb.Append("\"field\":\"region\","); sb.Append("\"title\":\"项目\","); sb.Append("\"align\":\"center\","); sb.Append("\"width\":\"" + kuandu + "\""); sb.Append("},"); for (int i = 0; i < projectProblemList.Tables[1].Rows.Count; i++) { sb.Append("{"); sb.Append("\"field\":\"" + projectProblemList.Tables[1].Rows[i][0] + "\","); sb.Append("\"title\":\"" + projectProblemList.Tables[1].Rows[i][0] + "\","); sb.Append("\"align\":\"center\","); sb.Append("\"width\":\"" + kuandu + "\""); sb.Append("},"); } sb.Remove(sb.Length - 1, 1); sb.Append("],"); #endregion #region 5、列表中的数据 //第一个图例项对象数组 sb.Append("\"listshuju\":["); //最外层循环,循环项目 for (int i = 0; i < projectProblemList.Tables[2].Rows.Count; i++) { sb.Append("{"); sb.Append("\"id\":\"" + i + "\","); sb.Append("\"region\":\"" + projectProblemList.Tables[2].Rows[i][0] + "\","); //定义一个临时数组,来存储下面要获得的数据 int[] arraylist = new int[projectProblemList.Tables[1].Rows.Count]; //根据项目匹配总数据中的值 for (int j = 0; j < projectProblemList.Tables[0].Rows.Count; j++) { //如果有相等的值,则进入循环部门(这里肯定会至少有一个项目名称与之匹配,因为项目名称是根据这个datatable去重筛选出来的) string adsf = projectProblemList.Tables[0].Rows[j][1].ToString(); string asdfasdf = projectProblemList.Tables[2].Rows[i][0].ToString(); if (projectProblemList.Tables[0].Rows[j][1].ToString() == projectProblemList.Tables[2].Rows[i][0].ToString()) { //通过循环部门,向数组中加入内容 for (int k = 0; k < projectProblemList.Tables[1].Rows.Count; k++) { if (projectProblemList.Tables[1].Rows[k][0].ToString() == projectProblemList.Tables[0].Rows[j][0].ToString()) { arraylist[k] = (int)projectProblemList.Tables[0].Rows[j][2]; } } } } //循环将数组拼接到字符串中 for (int k = 0; k < projectProblemList.Tables[1].Rows.Count; k++) { sb.Append("\"" + projectProblemList.Tables[1].Rows[k][0] + "\":\"" + arraylist[k] + "\","); } sb.Remove(sb.Length - 1, 1); sb.Append("},"); } sb.Remove(sb.Length - 1, 1); sb.Append("]"); #endregion //最后的括号! sb.Append("}"); resultStr = sb.ToString(); } return resultStr; } #endregion -</span>
四、BLL层代码
<span style="font-family:KaiTi_GB2312;font-size:18px;">- #region 最终报表3、子系统不合格品问题统计-马康-2016年9月28日17:16:23 /// <summary> /// 最终报表3、子系统不合格品问题统计-马康-2016年9月28日17:16:23 /// </summary> /// <returns></returns> public DataSet queryrejectbelongssystemList(string rejctphenomenontypename) { return dal.GetrejectbelongssystemList(rejctphenomenontypename); } #endregion -</span>
五、DAL层代码
<span style="font-family:KaiTi_GB2312;font-size:18px;">- #region 最终报表3、子系统不合格品问题统计-马康-2016年9月28日17:16:23 /// <summary> /// 3、子系统不合格品问题统计-马康-2016年9月28日17:16:23 /// </summary> /// <returns></returns> public DataSet GetrejectbelongssystemList(string rejctphenomenontypename) { StringBuilder builder = new StringBuilder(); if (rejctphenomenontypename =="") { //总数据 builder.Append(" SELECT sELECT3,replace(IsActive,'1','不合格品'),COUNT(sELECT3) num FROM Pts_Problems WHERE ProjectID IN (197, 29) AND ProblemStateID NOT IN (1870, 250) AND Select3 IN ('VOBC子系统','DCS子系统','ATS子系统','MSS子系统','CI子系统','ZC/DSU子系统') GROUP BY sELECT3,IsActive "); //所属系统个数 builder.Append(" SELECT DISTINCT(sELECT3) FROM Pts_Problems WHERE ProjectID IN (197, 29) AND ProblemStateID NOT IN (1870, 250) AND Select3 IN ('VOBC子系统','DCS子系统','ATS子系统','MSS子系统','CI子系统','ZC/DSU子系统') GROUP BY sELECT3 "); } else { //总数据 builder.Append(" SELECT sELECT3,replace(IsActive,'1','不合格品'),COUNT(sELECT3) num FROM Pts_Problems WHERE ProjectID IN (197, 29) AND ProblemStateID NOT IN (1870, 250) and MultiSelect1 = '" + rejctphenomenontypename + ";' AND Select3 IN ('VOBC子系统','DCS子系统','ATS子系统','MSS子系统','CI子系统','ZC/DSU子系统') GROUP BY sELECT3,IsActive "); //所属系统个数 builder.Append(" SELECT DISTINCT(sELECT3) FROM Pts_Problems WHERE ProjectID IN (197, 29) AND ProblemStateID NOT IN (1870, 250) AND Select3 IN ('VOBC子系统','DCS子系统','ATS子系统','MSS子系统','CI子系统','ZC/DSU子系统') GROUP BY sELECT3 "); } return SqlHelper.ExecuteDataset(sqlConnstring, CommandType.Text, builder.ToString()); } -</span>
【总结】
ECharts只用了简单常用的几个图标样式以及其中常用的属性,如需有其它方面的需求,可以查阅ECharts对应的文档教程。
因为需要好多报表考虑到开发效率以及后面的维护,所以小编经过思考,将其中的数据部分分为了三大块内容:
1、图例 2、X周内容 3、图例和x周对应的数据内容
这样一来,就可以在套用整个一条线所有的内容,只按照数据返回的形式重新写一些DAL层就可以了。
【感受】
环境不同,所能够达到的层次与对自己磨练的层面也不同,无论如何,将能够磨练自己的机会抓住,努力放大,争取在物欲横流的现实社会中不断的提升自己,不断增加自己的加速度。
每一份经历都伴随着不同程度的成长,它都将是我们最深刻、最美好的回忆,它也终将是我们在未来驰骋沙场的武器,所以少年需奋起,少年需进取O(∩_∩)O~