WEB前端bootstrap结合SSM框架
效果图:
step:
1. 后端接受请求跳转到html页面:html页面中相同的部分可以单独定义出来
eg:主html中定义head和div的th:replace="":第一个tag表示文件名,第二个tag表示fragment。div部分略
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org"
lang="en">
<head th:replace="common/tag::tag"/>
<meta charset="utf-8">
<body>
<!-- 页面顶部¨ -->
<div th:replace="common/head::head"/>
2. 对于表格部分只要定义个id即可,对于表格的操作(初始化,增删改)都定义到js中
<table id="rds_customer" class="table"></table>
<script src="/tpl/rds_customer/rds_customer_list.js"></script>
3 .表格的初始化:
var properties = {
//ajax url 和类型
tableAjax : {
url : '/rds_customer/findRdsCustomerList',
type : "GET",
},
//table的html id
tableId : 'rds_customer',//表的id
uniqueId : 'id',//表的主键
//table的列
tableColumn : [ {
checkbox : true,
align : 'center'
}, {
field : 'id',
title : '客户ID'
}, {
field : 'name',
title : '客户名'
}, {
field : 'hobbies',
title : '客户爱好'
}, {
field : 'gender',
title : '客户性别'
}, ]
};
$(function() {
//初始化Table
var oTable = new TableInit(properties);
oTable.Init();
});
4.查询-分页查询:
- 前端在js中定义pagination:true或者默认不写。后端用page,rows接收即可。
@RequestMapping("/findRdsCustomerList")
@ResponseBody()
public DataGridResult findCustomerList(
//defaultValue定义了每页默认显示5条记录
@RequestParam(required = false, defaultValue = "1", value = "page") Integer page,
@RequestParam(required = false, defaultValue = "5",value ="rows" ) Integer rows, ){
return customerService.findCustomerList(page, rows);
}
- 在Controlle层或者Impl层写分页代码:
PageHelper.startPage(page,rows);
//中间省略了模糊查询的条件部分,后续
List<RdsCustomer> customerList = rdsCustomerMapper.selectByExample(example);
//查询的结果进行分页布置
PageInfo<RdsCustomer> pageInfo = new PageInfo<RdsCustomer>(customerList);
//封装成返回类型的结果
DataGridResult result = new DataGridResult();
//设置需要的参数
result.setTotal(pageInfo.getTotal());
result.setRows(customerList);
//返回结果
return result;
}
- 将表格数据和分页信息封装成DataGridResult()直接返回到html页面,bootstrapTable会直接将数据和分页信息填充到表格中
- ps1:springboot中使用分页插件直接导入pagehelper和autoconfigurer即可
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper-spring-boot-autoconfigure</artifactId>
<version>1.2.5</version>
</dependency>
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper</artifactId>
<version>5.1.4</version>
</dependency>
- myBatis中使用分页插件则需要引入分页插件,然后在配置文件手动配置
<!-- 配置分页插件 -->
<plugins>
<plugin interceptor="com.github.pagehelper.PageInterceptor">
<!-- 设置数据库类型 Oracle,Mysql,MariaDB,SQLite,Hsqldb,PostgreSQL六种数据库-->
</plugin>
</plugins>
<!--加载mybatis的全局配置文件 -->
<property name="configLocation" value="classpath:mybatis/config/SqlMapConfig.xml" />
- ps2:引入不同版本pagehelper页码形式也会有所不同
5.查询-模糊查询
- 模糊查询先进入到html绘制模糊查询域,利用bootstrap即可绘制。注:form表单id必须与bootstrap中的queryParam中的选择器id保持一致,这样才能提交后端
oTableInit.queryParams = function (params) {
var param = {};
$('#searchForm').find('[name]').each(function () {
var value = $(this).val();
if (value != '') {
param[$(this).attr('name')] = value;
}
});
- 查询按钮添加search()方法,当传入参数refreshOptions时,等于对表格重新初始化了,就会将queryParam中参数传递过去,并且刷新后的页码显示为第1页
function search() {
$("#rds_customer").bootstrapTable('refreshOptions',{pageNumber:1});
}
- 后端在原来基础上用RdsCustomer类接收
@RequestMapping("/findRdsCustomerList")
@ResponseBody()
public DataGridResult findCustomerList(
@RequestParam(required = true, defaultValue = "1", value = "page") Integer page,
@RequestParam(required = true, defaultValue = "3",value ="rows" ) Integer rows, RdsCustomer rdsCostumer){
return customerService.findCustomerList(page, rows,rdsCostumer);
}
- Impl类在分页查询的基础上增加example即可
public class CustomerSerivceImpl implements CustomerService {
Logger logger = LoggerFactory.getLogger(CustomerSerivceImpl.class);
@Autowired
private RdsCustomerMapper rdsCustomerMapper;
@Override
public DataGridResult findCustomerList(Integer page, Integer rows, RdsCustomer rdsCostumer) {
PageHelper.startPage(page,rows);
//组织好example
RdsCustomerExample example = new RdsCustomerExample();
//创建好条件标椎模板
RdsCustomerExample.Criteria criteria = example.createCriteria();
//查询条件:id要和文本框中一模一样
if (StringUtil.isNotEmpty(rdsCostumer.getId())){
criteria.andIdEqualTo(Integer.parseInt(rdsCostumer.getId()));
}
//查询条件:姓名和文本框类似
if (StringUtil.isNotEmpty(rdsCostumer.getName())){
criteria.andNameLike("%"+ rdsCostumer.getName() + "%");
}
//按照id进行排序
example.setOrderByClause("id");
//example模板准备好后进行查询
List<RdsCustomer> customerList = rdsCustomerMapper.selectByExample(example);
//查询的结果进行分页布置
PageInfo<RdsCustomer> pageInfo = new PageInfo<RdsCustomer>(customerList);
//封装成返回类型的结果
DataGridResult result = new DataGridResult();
//设置需要的参数
result.setTotal(pageInfo.getTotal());
result.setRows(customerList);
//返回结果
return result;
}
6.新增:
- 点击新增按钮弹出框:
模态框中写的地址就是请求的地址 - 新增界面要显示下一个新增进来的人的id:
Controller层:
@RequestMapping("/toAddRdsCustomerById")
public String toAddCustomerPage(Model model){
Long id = customerService.getNextId();
model.addAttribute("id",id);
return "rds_customer/rds_customer_add";
}
Impl层:
@Override
public Long getNextId() {
RdsCustomerExample example = new RdsCustomerExample();
example.setOrderByClause("id desc");
List<RdsCustomer> resultList = rdsCustomerMapper.selectByExample(example);
//查询条件是按照id进行降序排序,然后获取到第一个集合的id,加1获取到的就是下一个新增的id
return resultList.size()==0?10000:Long.parseLong(resultList.get(0).getId())+1;
}
- 填好新增信息后保存到数据库:保存触发addRdsCustomer()方法,bootatrap先进行正则校验,然后Ajax传数据并响应“增加用户成功”
function addRdsCustomer() {
$('#addForm').data('bootstrapValidator').validate();
if (!($('#addForm').data('bootstrapValidator').isValid())) {
return;
}
$.mask_element('#addForm','数据保存中...');
$.ajax({
url : '/rds_customer/addRdsCustomer',
data : $("#addForm").serialize(),
success : function(result) {
//请求成功时
toastr.success('增加用户成功!');
$(".close").click();
search();
}
})
}
- 后端用一个封装好的类ReturnResult()接收
@RequestMapping("/addRdsCustomer")
@ResponseBody
public ReturnResult addRdsCustomer(RdsCustomer rdsCustomer){
return ReturnResult.success(customerService.addCustomer(rdsCustomer));
}
- ReturnResult中代码
public class ReturnResult {
//成功
public static final int SUCCESS_CODE = 0;
//失败
public static final int ERROR_CODE = 1;
//参数验证失败
public static final int PARA_VALID_CODE = 12022;
//自定义异常代码
public static final int CUS_EX_CODE = 12023;
//错误的请求
public static final int BAD_REQUEST = 400;
//未经授权
public static final int UNAUTHORIZED = 401;
//没有权限
public static final int FORBIDDEN = 403;
//没有找到
public static final int NOT_FOUND = 404;
//内部服务器错误
public static final int INTERNAL_SERVER_ERROR = 500;
private int code;
/**
* 响应中的数据
*/
private Object data;
/**
* 响应中的消息
*/
private String msg;
public boolean isSuccess() {
return SUCCESS_CODE==code;
}
public ReturnResult() {
}
public ReturnResult(int code, Object data, String msg) {
super();
this.code = code;
this.data = data;
this.msg = msg;
}
public int getCode() {
return code;
}
public void setCode(int code) {
this.code = code;
}
public Object getData() {
return data;
}
public void setData(Object data) {
this.data = data;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
public static ReturnResult byCode(int code) {
return new ReturnResult(code, "", null);
}
public static ReturnResult byCodeMsg(int code, String msg) {
return new ReturnResult(code, null ,msg);
}
public static ReturnResult success() {
return new ReturnResult(SUCCESS_CODE, null, null);
}
public static ReturnResult success(Object data) {
return new ReturnResult(SUCCESS_CODE, data, null);
}
public static ReturnResult error(String msg) {
return new ReturnResult(ERROR_CODE, null, msg);
}
public static ReturnResult error(Object data, String msg) {
return new ReturnResult(ERROR_CODE, data, msg);
}
}
function toAddCustomerById(){
Dialog.modal({url:"/rds_customer/toAddRdsCustomerById"})
}
7.修改
- 点击修改按钮触发 toUpdateRdsCustomerById()方法
- var rows = $("#rds_customer").bootstrapTable(“getSelections”)
获取到的rows是二维数组rows[i][‘j’],i表示选中记录的index,j是字段名 - 将选中的那一条记录的id传到后端 后续操作和新增类似,略。
function toUpdateRdsCustomerById(){
var rows = $("#rds_customer").bootstrapTable("getSelections");
if (rows.length == 0){
toastr.warning("请选择一条记录");
return;
}else if (rows.length > 1) {
toastr.warning("只能选择一条记录");
return;
}
Dialog.modal({url:"/rds_customer/toUpdatePage?id="+rows[0]['id']});
}
8.删除
- 点击删除按钮跳转到deleteRdsCustomerByIds
- 获取到被选中的所有记录,将记录中的所有id封装成对象ids,将ids传到后端
//获取表中所有被选中的记录:是数组
var rows = $("#rds_customer").bootstrapTable("getSelections");
//规定至少选择一条
if (rows.length < 1){
toastr.warning("请至少选择一条记录");
return;
}
//获取到选择的那些记录的ids:对象
var ids = {};
for (var i = 0 ; i < rows.length ; i++){
ids[i] = rows[i]['id'];
}
- 利用Ajax传到后端 并得到响应
//将ids对象传到后端
Dialog.confirm({
message:"确认要删除数据吗?"
}).on(function (e) {
if (!e){
return;
}
$.ajax({
type:"POST",
url:"/rds_customer/deleteRdsCustomerByIds",
data:{
ids:ids//传到后端的是ids对象
},
dataType:'json',
success : function (data) {
if (data.code == "0"){
toastr.warning("删除客户成功");
search();
}else {
toastr.warning("删除顾客失败");
}
}
});
});
- 后端IController层进行接收Impl进行删除操作
@Override
public int deleteCustomerByIds(RdsCustomer rdsCustomer) {
RdsCustomerExample example = new RdsCustomerExample();
example.createCriteria().andIdIn(rdsCustomer.getIds());
return rdsCustomerMapper.deleteByExample(example);
}
- 所有增删改默认返回的都是SUCCESS_CODE,返回到前端,前端利用Ajax收到响应显示结果在界面上“XX用户成功!”。
8.在每一行加上操作按钮
- 实现:在表格进行初始化时给按钮添加事件
var properties = {
//tableAjax url 数据接收类型 数据传输类型
tableAjax: {
url: "/fee/fee_data_list",
dataType: "json",
type: "GET"
},
tableId: 'datalist',
//画table
tableColumn : [{
field: "id",
title: "id"
},{
field: "name",
title: "资费名称"
},{
field: "baseDuration",
title: "基本时长"
},{
field: "baseCost",
title: "基本费用"
},{
field: "unitCost",
title: "单位费用"
},{
field: "status",
title: "状态",
formatter: function (value, row, index) {
return changeStatusFormat(value);
}
},{
field: "descr",
title: "描述"
},{
field: "creatime",
title: "创建时间",
formatter: function (value, row, index) {
return changeDateFormat(value);}
},{
field: "startime",
title: "开通时间",
formatter: function (value, row, index) {
return changeDateFormat(value);}
},{
field:'operate',
title:'操作',
formatter:'operateFormatter'
}]
};
$(function() {
//初始化Table
var oTable = new TableInit(properties);
oTable.Init();
});
function operateFormatter(vlaue , row , index){
if (row.status == "2"){
return [
''
].join('');
} else if (row.status == "1"){
return [
'<input type="button" class="btn_pause" onclick="changeStatus( '+ row.id +','+row.status+ ')" value="暂停">' +
'<input type="button" class="btn_modify" onclick="modifyStatus(' + row.id +','+row.status+ ')" value="修改">' +
'<input type="button" class="btn_delete" onclick="deleteStatus('+ row.id +','+row.status+ ')" value="删除">'
].join('');
}else{
return [
'<input type="button" class="btn_start" onclick="changeStatus('+ row.id +','+row.status+')" value="开通">' +
'<input type="button" class="btn_modify" onclick="modifyStatus(' + row.id +','+row.status+ ')" value="修改">' +
'<input type="button" class="btn_delete" onclick="deleteStatus(' + row.id +','+row.status+ ')" value="删除">'
].join('');
}
}
- 实现:开通、暂停、删除按钮的功能 (开通、暂停时:表格数据发生改变同时按钮样式发生改变;删除时表格数据发生改变同时三个按钮消失)。开通、暂停公用一个方法:
function changeStatus(id,status){
//将状态改为"1"class样式改为"btn_pause"开通后可以暂停
$.ajax({
type: "POST",
url: "/fee/fee_start_status",
datatype: "JSON",
data: "id="+id+"&status="+status,
success: function (data) {
if (data == "1"){
if (status == "0"){
toastr.warning("已暂停!");
search();
}else{
toastr.warning("已开通!");
search();
}
}else{
toastr.warning("开通失败!");
}
}
});
}
function deleteStatus(id , status) {
//将所有状态删除
$.ajax({
url: "/fee/fee_delete_status",
type: "POST",
datatype: "JSON",
data: "id="+id+"&status="+status,
success: function (data) {
if (data == "1"){
toastr.warning("删除成功!");
search();
return;
}
toastr.warning("删除失败!");
}
});
}
9.bootstrap-table中的子父表
- 在初始化表格的时候加上属性 detailView:true,表明显示子父表,加上此属性后表格最前列就会有“+”符号,然后在最后加上方法onExpandRow。如下:
detailView: true, //是否显示父子表
onLoadError :function(){
var $errorMsg = $('<td colspan="12"><div class="m-error"><b class="error-icon"> </b> <span class="error-text"><b class="text1">很抱歉,系统加载异常......</b><b class="text2"></b></span> </div></td>') ;
$(".no-records-found").empty().append($errorMsg);
},
onExpandRow: function (index, row, $detail) {
oTableInit.InitSubTable(index,row, $detail);
}
-
初始化子表(实现InitSubTable方法)
index:当前行的行索引 row:父表当前行的Json数据 $detail:当前行创建的td对象
//父子表的实现
oTableInit.InitSubTable = function (index, row, $detail) {
var parentid = row.id;//将当前行的id传给属性parentid
var cur_table = $detail.html('<table></table>').find('table');//创建子表cur_table
$(cur_table).bootstrapTable({//初始化子表
url: '/fee/fee_detail?id='+parentid,
method: 'get',
queryParams: { strParentID: parentid },
ajaxOptions: { strParentID: parentid },
pagination: false,
columns: [{
field: "id",
title: "id"
},{
field: "name",
title: "资费名称"
},{
field: "baseDuration",
title: "基本时长",
},{
field: "baseCost",
title: "基本费用",
},{
field: "unitCost",
title: "单位费用"
},{
field: "status",
title: "状态",
},{
field: "creatime",
title: "创建时间",
formatter: function (value, row, index) {
return changeDateFormat(value);}
},{
field: "startime",
title: "开通时间",
formatter: function (value, row, index) {
return changeDateFormat(value);}
},{
field: "descr",
title: "描述"
} ],
});
};
显示客户使用时长并进行排行(不使用表格的升降序符号)
- 点击“客户使用时长”按钮以及第一次进入该页面时都是按照id进行排序
- 点击“时长排行榜”便是时长最高的前三名客户
前端代码:
<div class="tabs">
<ul onclick="changeTab(event,this);">
<li><a id="sumDuration" onclick="byDuration(1,2)" class="tab_on" title="每位客户每月的累计时长">客户使用时长</a></li>
<li><a id="durationRank" onclick="byDuration(1,2,3)" class="tab_out" title="每台服务器上累计时长最高的前三名客户">时长排行榜</a></li>
</ul>
</div>
js中定义byDuration方法:这是为什么点击不同按钮会有不同表格的原因。刷新表格的属性:refreshOptions,
刷新的同时绑定属性:pageNumber,sortName,sortOrder
//时长排行榜
function byDuration(e) {
//模拟方法的重载
if (arguments.length == 2) {
$("#datalist").bootstrapTable('refreshOptions',{pageNumber:1,sortName: "id",sortOrder: "asc"});
}else if (arguments.length == 3) {
$("#datalist").bootstrapTable('refreshOptions',{pageNumber:1,sortName: "sum_duration",sortOrder: "desc"});
}
}
后端controller中代码:这是为什么第一进入该页面时显示使用时长的界面的原因。
@GetMapping("/report/report_data_list")
@ResponseBody
public DataGridResult reportList(@RequestParam(defaultValue = "1" , value = "page" , required = true) Integer page,
@RequestParam(defaultValue = "5" , value = "rows" , required = true) Integer rows,
@RequestParam(defaultValue = "asc" , required = true , value = "order") String order ,
@RequestParam(defaultValue = "id" , required = true , value = "orderName") String orderName){
return reportService.findAllReport(page , rows, order , orderName);
}
后端service中代码:主要是先进行降序排序,然后取出前三条记录。这是为什么能取出使用时长最长的三名用户的原因
public DataGridResult findAllReport(Integer page , Integer rows , String order ,String orderName) {
List<RdsReport> result = new ArrayList<>();
List<RdsReport> rdsReportListByDuration = null;
PageInfo<RdsReport> pageInfo = null;
DataGridResult dataGridResult = new DataGridResult();
PageHelper.startPage(page , rows);
RdsReportExample example = new RdsReportExample();
example.createCriteria().andIdIsNotNull();
if (orderName.equals("sum_duration")){
example.setOrderByClause(orderName + " " + order);
rdsReportListByDuration = rdsReportMapper.selectByExample(example);
result.add(0,rdsReportListByDuration.get(0));
result.add(1,rdsReportListByDuration.get(1));
result.add(2,rdsReportListByDuration.get(2));
pageInfo = new PageInfo<>(result);
dataGridResult.setRows(result);
}else{
example.setOrderByClause(orderName + " " + order);
rdsReportListByDuration = rdsReportMapper.selectByExample(example);
pageInfo = new PageInfo<>(rdsReportListByDuration);
dataGridResult.setRows(rdsReportListByDuration);
}
dataGridResult.setTotal(pageInfo.getTotal());
return dataGridResult;
}