(一)大概
背景:
需求就是设计一个自定义报表功能,当需要新报表时,能够快速的构建。
经过初步的构思,有至少三种方式可以实现:
-
构建demo代码,一个报表对应编写一套代码,不过可以将重复代码提取,尽可能的缩减代码,每套代码只保留个性化功能点;
-
一键生成代码,设计一套代码生成程序,以后需要报表时,一键生成配套代码,然后将代码拷贝到对应程序即可;
-
报表维护页面,添加报表数据源等基本信息,保存后自动在报表模块生成报表链接及对应数据。
因为当前项目报表预期会比较简单,能展示,能搜索,能导出即可,再一个希望后期能比较省事,有个看似高大上的东西,所以,最终选择了方式3。
思路设计:
- 要实现动态生成报表,那就得共用一套代码,不然还需要修改发布等等(当然目前好像也可以,但不是很了解);
- 共用一套代码就需要区分各个不同的报表,而且还调用同一个接口
2.1这个后端可以通过rest风格带参数来区分不同的报表,这个参数可以用这条信息的id来区分,这个id最好是无规律的(比如java的uuid,再一个可以是添加时间加一个随机数方式),不要用id自增(太容易被人试出别的报表链接),最终选择java的uuid方式。
2,2后端数据解决了,就剩前端,前端要能根据后端传递的不同数据,解析出不同的字段,然后根据这些字段动态的构建报表,这个应该也没问题,无非是页面加载时解析后台传过来的数据,然后渲染上。
内容步骤
根据思路,大体可以分成这么几部分:
- 设计通用后端接口;
- 设计通用前端接口;
- 增加管理页面相关前后端;
- 添加报表模块;
- 整合文档及程序包等。
此外,由于这个项目设计到多数据源,还有考虑这点。
基本大概就是这些,下一步简单描述下实现…
(二)大体实现
一、通用后端:
摘取几处主要的代码
- controller设计
@Autowired
private ICommonReportsService iCommonReportsService;
@RequestMapping("list/{id}")
public String list(@PathVariable(value = "id") String id,ModelMap mmap) {
System.out.println("获取到的id为:" + id);
List<Map<String, Object>> list = iCommonReportsService.list(id);
String reportName = iCommonReportsService.getReportName(id);
mmap.put("list", list);
mmap.put("reportName", reportName);
return "report/common";
}
- service设计
@Autowired
private JdbcTemplate jdbcTemplate;
@Autowired
private CommonReportsService commonReportsService;
public List<Map<String, Object>> list(String id) {
String sql = getSql(id);
String type = getDBType(id);
if(type==null || "".equals(type) || "M".equalsIgnoreCase(type)) {
return listOfM(id,sql);
}else {
return commonReportsService.listOfS(id,sql);
}
}
- 其他设计
二、通用前端
项目中使用的前端页面是thymeleaf+bootstrap
关键代码如下:
$(function() {
var list = [[${list}]];
var dynamicHeader = [];
/* dynamicHeader.push({
field: "state",
check: true
}); */
dynamicHeader.push({
checkbox: true
});
for (var i = 0; i<(Object.keys(list[0])).length; i++) {
var property = (Object.keys(list[0]))[i];
//console.log(property);
dynamicHeader.push({
"title": property,
"field": property,
//显示是否显示隐藏
switchable: true,
//是否开启排序
sortable: true
});
}
$('#bootstrap-table').bootstrapTable('destroy').bootstrapTable({
data: list,
//Bstable工具导航条
toolbar: '#toolbar',
//浏览器缓存,默认为true,设置为false避免页面刷新调用浏览器缓存
cache: false,
//是否显示行间隔色
striped: true,
//分页方式:client客户端分页,server服务端分页
sidePagination: "client",
//排序方式
sortOrder: "desc",
//每页记录行数
pageSize: 25,
//初始化加载第一页
pageNumber: 1,
//可供选择的每页行数
pageList: "[25, 50, 100, All]",
//是否显示切换按钮
showToggle: true,
//是否显示所有的列
showColumns: true,
//是否显示导出按钮
showExport: true,
//导出数据类型(
exportDataType: "basic",
//是否显示分页
pagination: true,
//是否启用全匹配搜索,否则为模糊搜索
strictSearch: false,
//开启搜索
search: true,
//自定义所生成的动态表头放入,结合上述data数据,实现表格数据内容的构建
columns: dynamicHeader
});
});
代码参考:
如何实现BootStrapTable的动态表格
(后面计划也会转载过来)