最近因为需要用到了Echarts这个插件,下面是自己的一点使用心得
效果图:
直接上代码:
js:
<%@ page import="org.apache.commons.lang3.RandomStringUtils" %> <%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8" %> <%@include file="../common/base.jsp" %> <spring:message code="ui.normal" var="normal"/> <spring:message code="ui.frozen" var="frozen"/> <spring:message code="ui.notify" var="notify"/> <spring:message code="ui.details" var="details"/> <spring:message code="ui.pay" var="pay"/> <% request.setAttribute("id0", RandomStringUtils.randomAlphabetic(8)); %> <script src="//cdn.bootcss.com/echarts/3.6.2/echarts.min.js"></script> <style> th { background-color: #d3d3d3; } </style> <div class="box"> <!-- /.box-header --> <div class="row"> <div class="col-md-10"> <div class="form-group"> <label>Mode:</label> <input type="radio" name="mode" value="0" checked>Currency <input type="radio" name="mode" value="1">Merchant <input type="radio" name="mode" value="2">Channel </div> </div> </div> <div class="row"> <div class="col-md-2"> <div class="form-group"> <label>Currency:</label> <lp:currency currencyId="currencyCode" currencyName="currencyCode" currencyClass="form-control"/> </div> </div> <div class="col-md-3"> <div class="form-group"> <label>Create Time:</label> <div class="input-group input-medium date-picker input-daterange"> <div class="input-group-addon"> <i class="fa fa-calendar"></i> </div> <input name="startDate" id="startDate" class="form-control" style="font-size: 13px;" type="text"/> <span class="input-group-addon">~</span> <input name="endDate" id="endDate" class="form-control" style="font-size: 13px;" type="text"/> </div> </div> </div> <div class="col-md-2" id="merchantQueryLabel" style="display: none"> <div class="form-group"> <label>Merchant:</label> <input type="text" name="userId" id="userId" class="form-control"> </div> </div> <div class="col-md-2" id="channelCodeQueryLabel" style="display: none"> <div class="form-group"> <label>Payment Channel:</label> <select class="form-control" name="channelCode"> <option value="">All</option> <c:forEach items="${channel}" var="channel"> <option value="${channel.orgCode}">${channel.orgCode}</option> </c:forEach> </select> </div> </div> <div class="col-md-1"> <div class="form-group"> <label> </label> <button type="button" class="form-control btn btn-info" name="search">${ ui_search }</button> </div> </div> <div class="col-md-1"> <div class="form-group"> <label> </label> <button type="button" class="form-control btn btn-info" name="export">${ ui_export }</button> </div> </div> </div> <div class="box-body"> <div id="main" style="width: 100%;height: 300px;"></div> </div> <%--<script type="script-data" class="script-data">--%> <script type="text/javascript"> /** * 查询请求 */ $("button[name='search']").on({ click: function () { loadTable(); getCurrencyCodeList(); paymentRateDate(); } }); var results = {}; var colors = ['#000000', '#FF0000', '#44CEF6', '#A88462', '#00E500', '#FA8C35', '#789262', '#801DAE', '#6E511E', '#FF461F']; var lineStyle = function () { return { normal: { color: 0 } }; }; /** * 获取折线图的图例数据(根据选择的条件不同为币种或商户) */ function getCurrencyCodeList() { var mode = $("input[name='mode']:checked").val(); $.ajax({ type: "post", url: "paymentrate/getCurrencyCodeList", dataType: "json", data: { 'currencyCode': $("select[name='currencyCode']").val(), 'startDate': $("input[name='startDate']").val(), 'mode': $("input[name='mode']:checked").val(), 'endDate': $("input[name='endDate']").val(), 'userId': $("#userId").val() }, success: function (result) { if (result) { results.legends = []; /** * 获取图例数据放入Echarts参数legends中 */ for (var i = 0; i < result.length; i++) { if (mode === '1') { results.legends.push(result[i].userId); } else { results.legends.push(result[i].currencyCode); } initChart(results); } } } } ); } function paymentRateDate() { $.ajax({ type: "post", url: "paymentrate/paymentRateLine", dataType: "json", data: { 'currencyCode': $("select[name='currencyCode']").val(), 'startDate': $("input[name='startDate']").val(), 'mode': $("input[name='mode']:checked").val(), 'endDate': $("input[name='endDate']").val(), 'userId': $("#userId").val() }, success: function (result) { if (result) { //获取X轴的时间数据 results.xAxis = result.xAxis; var seriesData = []; $.each(result.seriesList, function (i, series) { $.each(series, function (j, item) { var p = colors[j]; var ls = lineStyle(); ls.normal.color = p; item.lineStyle = ls; seriesData.push(item); }) }); results.series = seriesData; initChart(results); } } }); } var formatter = function (params) { var title = results.xAxis[params[0].dataIndex]; var res = title + '<br/>'; for (var i = 0; i < params.length; i++) { var source = results.series[params[i].seriesIndex].source; res += '<span style="display:inline-block;margin-right:5px;border-radius:10px;width:9px;height:9px;background-color:' + colors[i] + ';"></span>' + source + ' : ' + params[i].data + '<br/>'; } return res; }; var myChart = null; function initChart(data) { if (!myChart) { myChart = echarts.init(document.getElementById('main')); } var firstLegend = data.legends[0]; var option = { toolbox: { feature: { saveAsImage: { title: 'Save' } } }, legend: { show: true, data: data.legends, selected: {}, selectedMode: 'single' }, tooltip: { trigger: 'axis', axisPointer: { type: 'cross', label: { backgroundColor: '#6a7985' } }, formatter: formatter }, xAxis: { data: data.xAxis }, yAxis: { scale: true }, grid: { left: '3%', right: '4%', bottom: '3%', containLabel: true }, series: data.series }; option.legend.selected[firstLegend] = true; for (var i = 1; i < data.legends.length; i++) { option.legend.selected[data.legends[i]] = false; } myChart.setOption(option, true); } /** * 加载收银台订单表格 */ function loadTable() { $('#totalRate').text(""); var timestamp = (new Date()).valueOf(); var dataUrl = "paymentrate/queryByPage?timestamp=" + timestamp; if (table == null) { table = $('#${id0}').DataTable({ ajax: { url: dataUrl, type: 'POST', data: function (param) { param.currencyCode = $("select[name='currencyCode']").val(); param.startDate = $("input[name='startDate']").val(); param.endDate = $("input[name='endDate']").val(); param.mode = $("input[name='mode']:checked").val(); param.channelCode = $("select[name='channelCode']").val(); param.userId = $("#userId").val(); }, dataSrc: function (result) { return result.data; } }, columns: columns, paging: true, pagingType: "simple_numbers", lengthChange: true, searching: false, ordering: false, info: true, autoWidth: true, scrollX: true, scrollCollapse: true, processing: true, serverSide: true, retrieve: true }).on('draw', function () { var sumRateUrl = "paymentrate/countpayrate"; $.ajax({ url: sumRateUrl, type: 'POST', data: { currencyCode: $("select[name='currencyCode']").val(), startDate: $("input[name='startDate']").val(), endDate: $("input[name='endDate']").val(), mode: $("input[name='mode']:checked").val(), userId: $("#userId").val() }, dataType: 'json', success: function (data) { if (data.payRates != null) { $('#totalRate').text(data.payRates); } if (data.amountRates != null) { $('#totalAmountRate').text(data.amountRates); } } }); }); } else { table.ajax.reload(null, true); } } /** * 导出CSV格式请求 */ $("button[name='export']").on({ click: function () { var url = "paymentrate/export?startDate=" + $("input[name='startDate']").val() + "&endDate=" + $("input[name='endDate']").val() + "&mode=" + $("input[name='mode']:checked").val() + "&userId=" + $("#userId").val() + "¤cyCode=" + $("select[name='currencyCode']").val(); window.open(url); } }); }); </script>
java:
@ResponseBody @RequestMapping("/getCurrencyCodeList") public String getCurrencyCodeList(Model model, PaymentRateForm form) { List<PaymentRateDO> paymentRateDOList; //根据条件查询不同的视图 if (StringUtils.equals(form.getMode(), "1")) { paymentRateDOList = paymentRateDAO.queryMerchantList(form.getStartDate(), form.getEndDate(), form.getCurrencyCode(), form.getUserId()); } else { paymentRateDOList = paymentRateDAO.queryCurrencyCodeList(form.getStartDate(), form.getEndDate(), form.getCurrencyCode()); } return JSON.toJSONString(paymentRateDOList); } @ResponseBody @RequestMapping("/paymentRateLine") public String paymentRateList(Model model, PaymentRateForm form) { try { List<PaymentRateDO> paymentRateDOList = new ArrayList<>(); if (StringUtils.equals(form.getMode(), "0") || StringUtils.equals(form.getMode(), "2")) { paymentRateDOList = paymentRateDAO.queryPaymentRate(form.getStartDate(), form.getEndDate(), form.getCurrencyCode()); } if (StringUtils.equals(form.getMode(), "1")) { paymentRateDOList = paymentRateDAO.queryMerchantPaymentRate(form.getStartDate(), form.getEndDate(), form.getCurrencyCode(), form.getUserId()); } ArrayList<String> stringArrayList = new ArrayList<>(); //获取x轴数据的数量,过滤重复数据 for (PaymentRateDO paymentRateDO : paymentRateDOList) { if (!stringArrayList.contains(paymentRateDO.getCollectDate())) { stringArrayList.add(paymentRateDO.getCollectDate()); } } String[] xAxis = new String[stringArrayList.size()]; int i = 0; //构建三层树形结构 <userId/currency,<currency,<date,paymentRate>>> Map<String, Map<String, Map<String, String>>> parentDict = new HashMap<>(); ArrayList<String> arrayList = new ArrayList<>(); //往x轴数组中填充数据 for (PaymentRateDO paymentRateDO : paymentRateDOList) { if (!arrayList.contains(paymentRateDO.getCollectDate())) { arrayList.add(paymentRateDO.getCollectDate()); xAxis[i++] = paymentRateDO.getCollectDate(); } Map<String, Map<String, String>> dict = new HashMap<>(); //查询条件为币种和商户 if (StringUtils.equals(form.getMode(), "1")) { dict = parentDict.get(paymentRateDO.getUserId()); if (dict == null) { dict = new HashMap<>(); parentDict.put(paymentRateDO.getUserId(), dict); } } //查询条件为币种,因暂时无法获取渠道的支付数据,故查询条件不考虑渠道 if (StringUtils.equals(form.getMode(), "0") || StringUtils.equals(form.getMode(), "2")) { dict = parentDict.get(paymentRateDO.getCurrencyCode()); if (dict == null) { dict = new HashMap<>(); parentDict.put(paymentRateDO.getCurrencyCode(), dict); } } Map<String, String> subDist = dict.get(paymentRateDO.getCurrencyCode()); if (subDist == null) { subDist = new HashMap<>(); dict.put(paymentRateDO.getCurrencyCode(), subDist); } //保留小数点后两位,得到百分比 String paymentRate = String.format("%.2f", (paymentRateDO.getOrderSuccessNum().doubleValue() / paymentRateDO.getOrderCreateNum().doubleValue()) * 100); subDist.put(paymentRateDO.getCollectDate(), paymentRate); } Map<String, List<Series>> dateResult = turnToEchartsFormat(parentDict, xAxis); Map<String, Object> resultMap = new HashMap<>(); resultMap.put("xAxis", xAxis); resultMap.put("seriesList", dateResult); //如果resultMap中有值 return JSON.toJSONString(resultMap); } catch (Exception e) { log.error("query payment rate error", e); return null; } } //按照echarts需要的格式填入相应的数据 private Map<String, List<Series>> turnToEchartsFormat(Map<String, Map<String, Map<String, String>>> parentDict, String[] xAxis) { Map<String, List<Series>> dataResult = new HashMap<>(); for (Map.Entry<String, Map<String, Map<String, String>>> entry1 : parentDict.entrySet()) { Map<String, Map<String, String>> currencyMap = entry1.getValue(); List<Series> seriesList = new ArrayList<>(); dataResult.put(entry1.getKey(), seriesList); for (Map.Entry<String, Map<String, String>> entry2 : currencyMap.entrySet()) { Map<String, String> dateMap = entry2.getValue(); String[] data = new String[xAxis.length]; int i = 0; Series series = Series.build(entry1.getKey(), entry2.getKey()); //如果数据为空,则设为0 for (String str : xAxis) { String s = dateMap.get(str); data[i++] = s == null ? "0.00" : s; } series.setData(data); seriesList.add(series); } } return dataResult; } @ResponseBody @RequestMapping("/export") public String export(HttpServletResponse response, PaymentRateForm form) { try { WhereCriteria whereCriteria = buildWhereCriteria(form); Pagination page = new Pagination(); List<PaymentRateDO> paymentRateDOS = new ArrayList<>(); String mode = form.getMode(); String sTitle = ""; if (StringUtil.equals(mode, "0")) { paymentRateDOS = paymentRateDAO.findPaymentRatePage(whereCriteria); } if (StringUtil.equals(mode, "1")) { paymentRateDOS = paymentRateDAO.findMerchantPaymentRatePage(whereCriteria); sTitle = "MerchantId,"; } if (StringUtil.equals(mode, "2")) { paymentRateDOS = paymentRateDAO.findChannelPaymentRatePage(whereCriteria); sTitle = "ChannelCode,"; } sTitle += "Date,Currency,CreateNum,CreateAmount,SuccessNum,SuccessAmount,PayRate,AmountRate"; StringBuilder body = new StringBuilder(sTitle); body.append("\r\n"); NumberFormat numberFormat = NumberFormat.getInstance(); // 设置精确到小数点后2位 numberFormat.setMaximumFractionDigits(2); if (paymentRateDOS != null && !paymentRateDOS.isEmpty()) { for (PaymentRateDO paymentRateDO : paymentRateDOS) { if (StringUtil.equals(mode, "1")) { body.append("\t" + paymentRateDO.getUserId()).append(","); } if (StringUtil.equals(mode, "2")) { body.append(paymentRateDO.getChannelCode()).append(","); } body.append(paymentRateDO.getCollectDate()).append(","); body.append(paymentRateDO.getCurrencyCode()).append(","); body.append(paymentRateDO.getOrderCreateNum()).append(","); Money createAmount = new Money(); createAmount.setCent(paymentRateDO.getOrderCreateAmount()); body.append(createAmount.toString()).append(","); body.append(paymentRateDO.getOrderSuccessNum()).append(","); Money successAmount = new Money(); successAmount.setCent(paymentRateDO.getOrderSuccessAmount()); body.append(successAmount.toString()).append(","); if (paymentRateDO.getOrderSuccessNum() == 0 || paymentRateDO.getOrderCreateNum() == 0) { body.append(0).append(","); } else { String result = numberFormat .format((float) paymentRateDO.getOrderSuccessNum() / (float) paymentRateDO.getOrderCreateNum() * 100) + "%"; body.append(result).append(","); } if (paymentRateDO.getOrderSuccessAmount() == 0 || paymentRateDO.getOrderCreateAmount() == 0) { body.append(0).append(","); } else { String result = numberFormat .format((float) paymentRateDO.getOrderSuccessAmount() / (float) paymentRateDO.getOrderCreateAmount() * 100) + "%"; body.append(result).append(","); } body.append("\r\n"); } } //写入resp ExportUtil.responseSetProperties(response); ExportUtil.doExport(body.toString(), response); return null; } catch (Exception e) { log.error("export pending pay order error", e); return null; } }
工作中肯定会遇到很多从没有用过的插件,那么这个时候怎么快速的去熟悉这个插件并且获得基本的使用功能就尤为重要了。
个人有一点小心得,先访问插件的官网,尽量使用中文版的(易于阅读),或者使用谷歌页面翻译成中文,当然如果英语很厉害的就另说了。
根据自己的需求去查看官方实例,要带着目的去看,不能盲目的一头扎进去,插件的功能强大的话,整体看下来其实收获不了什么。带着需求去的话,你看了某一个实例正是你想要的那种结果,你就会继续去看js是怎么写的,以及其中每个参数有什么意义,需要一些什么数据就可以显示出那样的效果。
到了这里,你就可以开始考虑你的代码实现了,传什么数据给js,以及怎么去获取这些数据。
如果碰到一些问题,第一谷歌,去看看别人有没有碰到,基本你碰到的问题,别人也会碰到,毕竟使用的人多了,坑基本都被人家踩过了。
第二官方文档,谷歌解决不了,你就回归本质,到文档中去看看,是哪个参数引起的问题,还是哪些功能有问题,或者显示有问题。兴许就是你少加了个参数或者ture啊false啊 什么的,效果会截然不同。
第三,去加一些插件的QQ群,里面都是一些正在使用或者使用过的人,向里边的人取取经,会有意外的收获。
详细的代码已经上传到资源(包括js和后台代码,数据库视图,功能为根据多个条件来显示折线图,以及datatable表格):http://download.csdn.net/download/wj18570504421/10169716
总结到最后,还是觉得要培养自己解决问题的能力,使用过程中,肯定会碰到很多BUG,但是怎么去排查出来并且解决它,那个思维过程很重要!