O2O-业务功能-养修服务单项
养修服务单项
1>养修服务单项查询列表
前端:
-
需要使用的boostrap插件
<div class="col-sm-12 select-table table-striped"> <table id="bootstrap-table"></table> </div>
-
配合js将分页数据展示出来
$(function() { var options = { url: prefix + "/query", createUrl: prefix + "/addPage", updateUrl: prefix + "/editPage?id={id}", removeUrl: prefix + "/remove", exportUrl: prefix + "/export", modalName: "服务项", columns: [{ checkbox: true }, { field: 'id', title: '服务项id', visible: false }, { field: 'name', title: '服务项名称', sortable: true }, { field: 'originalPrice', title: '服务项原价', sortable: true }, { field: 'discountPrice', title: '服务项折扣价', sortable: true }, { field: 'carPackage', title: '是否套餐', sortable: true, formatter: function(value, row, index) { return $.table.selectDictLabel(carPackageDatas, value); } }, { field: 'info', title: '备注信息', sortable: true, formatter: function(value, row, index) { return $.table.tooltip(value, 10, "open"); } }, { field: 'createTime', title: '创建时间', sortable: true }, { field: 'serviceCatalog', title: '服务分类', align: 'center', formatter: function(value, row, index) { return $.table.selectDictLabel(serviceCatalogDatas, value); } }, { field: 'auditStatus', title: '审核状态', align: 'center', formatter: function(value, row, index) { return $.table.selectDictLabel(auditStatusDatas, value); } }, { field: 'saleStatus', title: '上架状态', align: 'center', formatter: function(value, row, index) { return $.table.selectDictLabel(saleStatusDatas, value); } }, }] }; $.table.init(options); });
后端:
-
前端发送页面请求http://localhost/business/serviceItem/listPage,
//页面------------------------------------------------------------ //列表 @RequiresPermissions("system:serviceItem:view") @RequestMapping("/listPage") public String listPage(){ return prefix + "list"; }
-
这个请求会直接去加载list.html界面,界面中再次发送请求,请求页面数据http://localhost/business/serviceItem/listPage,
-
后端程序去数据库查询分页数据,TablePageInfo返回一个自己封装好的页面数据类
//数据----------------------------------------------------------- //列表 @RequiresPermissions("system:serviceItem:list") @RequestMapping("/query") @ResponseBody public TablePageInfo<ServiceItem> query(ServiceItemQuery qo){ return serviceItemService.query(qo); } --------------------------------------------------- /** * 分页对象 * @param <T> */ @Setter @Getter public class TablePageInfo<T>{ private int code; //返回值状态码:为0是表示成功 private String msg; //返回值信息 private long total; //分页总条数 private List<T> rows = new ArrayList<>(); //当前页面显示数据 public TablePageInfo(List<T> list){ PageInfo<T> pageInfo = new PageInfo<>(list); this.total = pageInfo.getTotal(); this.rows = pageInfo.getList(); //成功 this.code = StateType.SUCCESS.getValue(); } } -------------------------------------------------------- //service层的实现类 //需要注意的 //qo中存放前端传过来的分页和过滤数据 @Override public TablePageInfo< ServiceItem > query(ServiceItemQuery qo) { PageHelper.startPage(qo.getPageNum(), qo.getPageSize()); return new TablePageInfo<ServiceItem>(serviceItemMapper.selectForList(qo)); } -------------------------------------------------------- //实体类 import com.fasterxml.jackson.annotation.JsonFormat; import lombok.Getter; import lombok.Setter; import org.springframework.format.annotation.DateTimeFormat; import java.math.BigDecimal; import java.util.Date; @Setter @Getter public class ServiceItem { private static final long serialVersionUID = 1L; public static final Integer CARPACKAGE_NO = 0;//不是套餐 public static final Integer CARPACKAGE_YES = 1;//是套餐 public static final Integer AUDITSTATUS_INIT = 0;//初始化 public static final Integer AUDITSTATUS_AUDITING = 1;//审核中 public static final Integer AUDITSTATUS_APPROVED = 2;//审核通过 public static final Integer AUDITSTATUS_REPLY = 3;//重新调整 public static final Integer AUDITSTATUS_NO_REQUIRED = 4;//无需审核 public static final Integer SALESTATUS_OFF = 0;//下架 public static final Integer SALESTATUS_ON = 1;//上架 private Long id; private String name; //服务项名称 private BigDecimal originalPrice; //服务项原价 private BigDecimal discountPrice; //服务项折扣价 private Integer carPackage; //是否套餐【是/否】 private String info; //备注信息 @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone ="GMT+8") @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm") private Date createTime; //创建时间 private Integer serviceCatalog; //服务分类【维修/保养/其他】 private Integer auditStatus = AUDITSTATUS_NO_REQUIRED; //审核状态【初始化/审核中/审核通过/审核拒绝/无需审核】 private Integer saleStatus = SALESTATUS_OFF; //上架状态【已上架/未上架】 }
2>养修服务单项添加
前端:
-
需要将另一实现添加任务的页面,作为模态框似的弹出来
-
弹出框中需要将套餐否:复选框和**服务分类:下拉框****的数据从数据字典中查询出来
-
点击添加按钮时:/business/serviceItem/addPage
-
点击确定时执行添加程序
-
弹框,使用的若依绞手架底层封装的一个弹窗api,作用就是将写好的add.html页面作为一个弹框展现出来,命名必须按照ruyi的规范来否则无法完成页面的跳转
<a class="btn btn-success" onclick="$.operate.add()" <i class="fa fa-plus"></i> 新增 </a>
//ruyi底层 add: function(id) { table.set(); $.modal.open("添加" + table.options.modalName, $.operate.addUrl(id)); }, // 添加访问地址 addUrl: function(id) { var url = $.common.isEmpty(id) ? table.options.createUrl.replace("{id}", "") : table.options.createUrl.replace("{id}", id); //添加操作时id是为空的这样会直接返回/business/serviceItem/addPage这个地址,发送到后端 return url; },
-
-
跳转到添加服务项的弹框后的add.html
- 展示是一个form表单
<div class="wrapper wrapper-content animated fadeInRight ibox-content"> <form class="form-horizontal m" id="form-serviceItem-add"> <div class="form-group"> <label class="col-sm-3 control-label is-required">服务项名称:</label> <div class="col-sm-8"> <input class="form-control" type="text" name="name" id="serviceItemName" required> </div> </div> <div class="form-group"> <label class="col-sm-3 control-label is-required">服务项原价:</label> <div class="col-sm-8"> <input class="form-control" type="text" name="originalPrice" id="originalPrice" required> </div> </div> <div class="form-group"> <label class="col-sm-3 control-label is-required">服务项折扣价:</label> <div class="col-sm-8"> <input class="form-control" type="text" name="discountPrice" id="discountPrice" required> </div> </div> <div class="form-group"> <label class="col-sm-3 control-label">套餐否:</label> <div class="col-sm-8"> <div class="radio-box" th:each="dict : ${@dict.getType('si_car_package')}"> <input type="radio" th:id="${dict.id}" name="carPackage" th:value="${dict.value}" th:checked="${dict.isDefault}"> <label th:for="${dict.id}" th:text="${dict.label}"></label> </div> </div> </div> <div class="form-group"> <label class="col-sm-3 control-label">服务分类:</label> <div class="col-sm-8"> <select name="serviceCatalog" class="form-control m-b" th:with="type=${@dict.getType('si_service_catalog')}"> <option th:each="dict : ${type}" th:text="${dict.label}" th:value="${dict.value}"></option> </select> </div> </div> <div class="form-group"> <label class="col-sm-3 control-label">备注:</label> <div class="col-sm-8"> <textarea id="info" name="info" class="form-control"></textarea> </div> </div> </form> </div>
<script type="text/javascript"> var prefix = ctx + "/business/serviceItem"; function submitHandler() { if ($.validate.form()) { //使用的ruyi的save 函数 $.operate.save(prefix + "/add", $('#form-serviceItem-add').serialize()); } } </script> ------------------------------------- // save的底层实现 就是发送一个ajax使用的api data=$('#form-serviceItem-add').serialize() 提交form表单中的data数据 save: function(url, data, callback) { var config = { url: url, type: "post", dataType: "json", data: data, beforeSend: function () { $.modal.loading("正在处理中,请稍后..."); $.modal.disable(); }, success: function(result) { if (typeof callback == "function") { callback(result); } $.operate.successCallback(result); } }; $.ajax(config) },
后端:
-
进行控制跳转到add.html页面
@RequestMapping("/addPage") public String addPage(){ return prefix + "add"; }
-
看到添加页面用户进行服务项的添加
-
添加完毕后点击确定按钮这时会将添加信息按照对应的name值一一提交到后端封装到serviceItem中
-
添加时需要注意,提交过来的额值中并没有创建时间和服务项的状态,需要通过他是否是套餐来是否需要审核
-
如果是套餐那么难么就设置套餐的审核状态为初始化状态
-
防止恶意添加数据,尽管默认状态是下架的但是反正逻辑是只要是新添加的都属于下架状态
//C层: //新增 @RequestMapping("/add") @ResponseBody public AjaxResult addSave(ServiceItem serviceItem){ serviceItemService.save(serviceItem); return AjaxResult.success(); } ----------------------------------------- //service层 /** * 创建的时间是页面没有提交的,这时业务层需要实现 * 审核状态和上架状态也是没有提交的 * 审核装是可以通过是否是套餐来判断是否需要经过审核流程 * 上架状态默认是未上架的,但是为了防止而已访问修改需要加一层保护 * @param serviceItem */ @Override public void save(ServiceItem serviceItem) { //防止恶意添加数据 serviceItem.setSaleStatus(ServiceItem.SALESTATUS_OFF); serviceItem.setCreateTime(new Date()); //如果是套餐那么审核状态就是初始化 if (ServiceItem.CARPACKAGE_YES.equals(serviceItem.getCarPackage())) { serviceItem.setAuditStatus(ServiceItem.AUDITSTATUS_INIT); }else { //非套餐就是不需要审核 serviceItem.setAuditStatus(ServiceItem.AUDITSTATUS_NO_REQUIRED); } serviceItemMapper.insert(serviceItem); }
3>养修服务单项编辑
前端:
-
前端编辑按钮的**“disable”**逻辑
-
上架和审核中的状态下编辑按钮不亮表无法操作
{ title: '操作', align: 'center', formatter: function(value, row, index) { var disUpdate; var actions = []; //如果是上架和审核中是不允许修改的 if (row.saleStatus==1 || row.auditStatus==1){ disUpdate="disabled" } actions.push('<a class="btn btn-success btn-xs '+disUpdate+'" href="javascript:void(0)" ' + 'οnclick="$.operate.edit(\'' + row.id + '\')"><i class="fa fa-edit"></i>编辑</a> '); //是否是套餐 return actions.join(''); }
-
需要准备一个edit.html页面作为弹窗页面 ,向后端发送一个id查询serviceItem
<div class="wrapper wrapper-content animated fadeInRight ibox-content"> <form class="form-horizontal m" id="form-serviceItem-edit"> <input class="form-control" type="hidden" name="id" id="id" th:value="${serviceItem.id}" required> <div class="form-group"> <label class="col-sm-3 control-label is-required">服务项名称:</label> <div class="col-sm-8"> <input class="form-control" type="text" name="name" id="serviceItemName"th:value="${serviceItem.name}" required> </div> </div> <div class="form-group"> <label class="col-sm-3 control-label is-required">服务项原价:</label> <div class="col-sm-8"> <input class="form-control" type="text" th:value="${serviceItem.originalPrice}" name="originalPrice" id="originalPrice" required> </div> </div> <div class="form-group"> <label class="col-sm-3 control-label is-required">服务项折扣价:</label> <div class="col-sm-8"> <input class="form-control" type="text"th:value="${serviceItem.discountPrice}" name="discountPrice" id="discountPrice" required> </div> </div> <div class="form-group"> <label class="col-sm-3 control-label">服务分类:</label> <div class="col-sm-8"> <select name="serviceCatalog" class="form-control m-b" th:field="${serviceItem.serviceCatalog}" th:with="type=${@dict.getType('si_service_catalog')}"> <option th:each="dict : ${type}" th:text="${dict.label}" th:value= "${dict.value}" ></option> </select> </div> </div> <div class="form-group"> <label class="col-sm-3 control-label">备注:</label> <div class="col-sm-8"> <textarea id="info" name="info" th:text="${serviceItem.info}" th:value="${serviceItem.info}" class="form-control"></textarea> </div> </div> </form> </div>
-
点击确定按钮时提交修改页面
<script type="text/javascript"> var prefix = ctx + "/business/serviceItem"; function submitHandler() { if ($.validate.form()) { $.operate.save(prefix + "/edit", $('#form-serviceItem-edit').serialize()); } } </script>
-
后端:
-
查询出Id 对应的 serviceItem,存入作用域中,跳转到edit.html页面
@RequestMapping("/editPage") public String editPage(Long id, Model model){ model.addAttribute("serviceItem", serviceItemService.get(id)); return prefix + "edit"; }
-
前端页面点击确定修改按钮提交过来数据
- 首先需要根据id从数据库中查出数据库中数据,为安全起见,先查询在修改,最后提交修改对象是从数据库中查询出来的对象
- 需要注意的是要判断其状态是否为上架中或者是审核中的状态如果是那么就报异常
- 再判断是否是套餐,是套餐就将器审核状态设置为初始化状态
- 把不需要修改的字段在sql中删除掉
- 不需要修改的,套餐否 日期,上架状态
@RequestMapping("/edit") @ResponseBody public AjaxResult edit(ServiceItem serviceItem){ serviceItemService.update(serviceItem); return AjaxResult.success(); } -------------------------------------------------------- /** * 1首先需要根据id从数据库中查出数据库中数据 * 2判断业务是否处于审核中或者是上架状态如果是抛出异常,非法操作 * 3再判断是否是套餐,是套餐那并且本来状态是审核通过那么要设置成初始化 * 4把不需要修改的字段在sql中删除掉 * 不需要修改的,套餐否 日期,上架状态 * @param serviceItem */ @Override public void update(ServiceItem serviceItem) { ServiceItem dbServiceItem = serviceItemMapper.selectByPrimaryKey(serviceItem.getId()); if (ServiceItem.SALESTATUS_ON.equals(dbServiceItem.getSaleStatus())|| ServiceItem.AUDITSTATUS_AUDITING.equals(dbServiceItem.getAuditStatus())) { throw new RuntimeException("非法操作"); } if (ServiceItem.CARPACKAGE_YES.equals(dbServiceItem.getCarPackage())&& ServiceItem.AUDITSTATUS_APPROVED.equals(dbServiceItem.getAuditStatus())){ dbServiceItem.setAuditStatus(ServiceItem.AUDITSTATUS_INIT); } dbServiceItem.setName(serviceItem.getName()); dbServiceItem.setOriginalPrice(serviceItem.getOriginalPrice()); dbServiceItem.setDiscountPrice(serviceItem.getDiscountPrice()); dbServiceItem.setServiceCatalog(serviceItem.getServiceCatalog()); dbServiceItem.setInfo(serviceItem.getInfo()); serviceItemMapper.updateByPrimaryKey(dbServiceItem); }
4>养修服务单项上架/下架
前端:
-
只有审核通过和下架状态下让上架按钮显示
{ title: '操作', align: 'center', formatter: function(value, row, index) { var disSale; var actions = []; //是否是套餐 if (row.saleStatus==0){ //只有在审核通过和在下架状态下才能让上架的按钮有作用 if (row.auditStatus!==2 && row.carPackage==1){ disSale="disabled"; } actions.push('<a class="btn btn-info btn-xs '+disSale+'" href="javascript:void(0)"' + ' onclick="saleOn(\'' + row.id + '\')"><i class="fa fa-shopping-bag"></i>上架</a>'); }else{ actions.push('<a class="btn btn-danger btn-xs ' + saleOffFlag + '" href="javascript:void(0)"' + ' onclick="saleOff(\'' + row.id + '\')"><i class="fa fa-remove"></i>下架</a>'); } return actions.join(''); }
-
给后端传递一个id,让后端判断其是否具备上架的或则下架的条件
function saleOn(id) { $.modal.confirm("确定要上架",function () { $.operate.get(prefix+"/saleOn?id="+id) }) } function saleOff(id) { $.modal.confirm("确定要下架",function () { $.operate.get(prefix+"/saleOff?id="+id) }) }
后端:
-
上架逻辑
-
判断需要上架的服务项是否是套餐并且再判断是否是审核通过的,
-
不是套餐可以直接上架
-
不满足条件抛出异常
-
可以上架成功修改上架状态
@Override public void saleOn(Long id) { //如果是套餐而必须是审核通过的才能进行上架,剩下的也就是没什么限制 ServiceItem serviceItem = serviceItemMapper.selectByPrimaryKey(id); if (ServiceItem.CARPACKAGE_YES.equals(serviceItem.getCarPackage()) && !ServiceItem.AUDITSTATUS_APPROVED.equals(serviceItem.getAuditStatus()) ) { throw new RuntimeException("非法操作"); } serviceItemMapper.updateSaleStatus(id,ServiceItem.SALESTATUS_ON); }
-
-
下架逻辑
-
只要是上架状态就下架
-
只修改可以为下架状态即可
@Override public void saleOff(Long id) { serviceItemMapper.changeSaleStatus(id,ServiceItem.SALESTATUS_OFF); }
-
前端list.html的整体代码
<!DOCTYPE html>
<html lang="zh" xmlns:th="http://www.thymeleaf.org" xmlns:shiro="http://www.pollix.at/thymeleaf/shiro">
<head>
<th:block th:include="common/include :: header('服务项列表')" />
</head>
<body class="gray-bg">
<div class="container-div">
<div class="row">
<div class="col-sm-12 search-collapse">
<form id="customer-form">
<div class="select-list">
<ul>
<li>
服务项名称:<input type="text" name="name"/>
</li>
<li>
套餐否
<select name="carPackage" th:with="type=${@dict.getType('si_car_package')}">
<option value="">所有</option>
<option th:each="dict : ${type}" th:text="${dict.label}" th:value="${dict.value}"></option>
</select>
服务分类
<select name="serviceCatalog" th:with="type=${@dict.getType('si_service_catalog')}">
<option value="">所有</option>
<option th:each="dict : ${type}" th:text="${dict.label}" th:value="${dict.value}"></option>
</select>
审核状态
<select name="auditStatus" th:with="type=${@dict.getType('si_audit_status')}">
<option value="">所有</option>
<option th:each="dict : ${type}" th:text="${dict.label}" th:value="${dict.value}"></option>
</select>
上架状态
<select name="saleStatus" th:with="type=${@dict.getType('si_sale_status')}">
<option value="">所有</option>
<option th:each="dict : ${type}" th:text="${dict.label}" th:value="${dict.value}"></option>
</select>
</li>
<li>
<a class="btn btn-primary btn-rounded btn-sm" onclick="$.table.search()"><i class="fa fa-search"></i> 搜索</a>
<a class="btn btn-warning btn-rounded btn-sm" onclick="$.form.reset()"><i class="fa fa-refresh"></i> 重置</a>
</li>
</ul>
</div>
</form>
</div>
<div class="btn-group-sm" id="toolbar" role="group">
<a class="btn btn-success" onclick="$.operate.add()"
shiro:hasPermission="business:serviceItem:add">
<i class="fa fa-plus"></i> 新增
</a>
<a class="btn btn-primary disabled" id="startAudit" onclick="startAudit()"
shiro:hasPermission="business:serviceItem:audit">
<i class="fa fa-edit"></i> 发起审核
</a>
</div>
<div class="col-sm-12 select-table table-striped">
<table id="bootstrap-table"></table>
</div>
</div>
</div>
<th:block th:include="common/include :: footer" />
<script th:inline="javascript">
var editFlag = [[${@permission.hasPermi('business:serviceItem:edit')}]];
var saleOnFlag = [[${@permission.hasPermi('business:serviceItem:saleOn')}]];
var saleOffFlag = [[${@permission.hasPermi('business:serviceItem:saleOff')}]];
var auditStatusDatas = [[${@dict.getType('si_audit_status')}]];
var serviceCatalogDatas = [[${@dict.getType('si_service_catalog')}]];
var carPackageDatas = [[${@dict.getType('si_car_package')}]];
var saleStatusDatas = [[${@dict.getType('si_sale_status')}]];
var prefix = ctx + "/business/serviceItem";
$(function() {
var options = {
url: prefix + "/query",
createUrl: prefix + "/addPage",
updateUrl: prefix + "/editPage?id={id}",
removeUrl: prefix + "/remove",
exportUrl: prefix + "/export",
modalName: "服务项",
columns: [{
checkbox: true
},
{
field: 'id',
title: '服务项id',
visible: false
},
{
field: 'name',
title: '服务项名称',
sortable: true
},
{
field: 'originalPrice',
title: '服务项原价',
sortable: true
},
{
field: 'discountPrice',
title: '服务项折扣价',
sortable: true
},
{
field: 'carPackage',
title: '是否套餐',
sortable: true,
formatter: function(value, row, index) {
return $.table.selectDictLabel(carPackageDatas, value);
}
},
{
field: 'info',
title: '备注信息',
sortable: true,
formatter: function(value, row, index) {
return $.table.tooltip(value, 10, "open");
}
},
{
field: 'createTime',
title: '创建时间',
sortable: true
},
{
field: 'serviceCatalog',
title: '服务分类',
align: 'center',
formatter: function(value, row, index) {
return $.table.selectDictLabel(serviceCatalogDatas, value);
}
},
{
field: 'auditStatus',
title: '审核状态',
align: 'center',
formatter: function(value, row, index) {
return $.table.selectDictLabel(auditStatusDatas, value);
}
},
{
field: 'saleStatus',
title: '上架状态',
align: 'center',
formatter: function(value, row, index) {
return $.table.selectDictLabel(saleStatusDatas, value);
}
},
{
title: '操作',
align: 'center',
formatter: function(value, row, index) {
var disUpdate;
var disSale;
var actions = [];
//如果是上架和审核中是不允许修改的
if (row.saleStatus==1 || row.auditStatus==1){
disUpdate="disabled"
}
actions.push('<a class="btn btn-success btn-xs '+disUpdate+'" href="javascript:void(0)" ' +
'οnclick="$.operate.edit(\'' + row.id + '\')"><i class="fa fa-edit"></i>编辑</a> ');
//是否是套餐
if (row.saleStatus==0){
//只有在审核通过和在下架状态下才能让上架的按钮有作用
if (row.auditStatus!==2 && row.carPackage==1){
disSale="disabled";
}
actions.push('<a class="btn btn-info btn-xs '+disSale+'" href="javascript:void(0)"' +
' οnclick="saleOn(\'' + row.id + '\')"><i class="fa fa-shopping-bag"></i>上架</a>');
}else{
actions.push('<a class="btn btn-danger btn-xs ' + saleOffFlag + '" href="javascript:void(0)"' +
' οnclick="saleOff(\'' + row.id + '\')"><i class="fa fa-remove"></i>下架</a>');
}
return actions.join('');
}
}]
};
$.table.init(options);
});
$("#bootstrap-table").on("check.bs.table uncheck.bs.table check-all.bs.table uncheck-all.bs.table load-success.bs.table",function () {
//得到的是一个数组
var rows = $('#bootstrap-table').bootstrapTable('getSelections');
//没有或者一个以上的流程不能发起审核
var row = rows[0];
if (row) {
if(rows.length>1||row.length==0 ){
console.log(1);
$("#startAudit").addClass("disabled");
return;
}
//不是套餐不能发起审核
if (row.carPackage==0){
$("#startAudit").addClass("disabled");
return;
}
//审核中或者审核通过不需要发起审核
if (row.auditStatus == 1 || row.auditStatus == 2) {
$("#startAudit").addClass("disabled");
return;
}
$("#startAudit").removeClass("disabled");
}
});
function startAudit(){
//获取选中行的数据,是一个数组
var rows = $('#bootstrap-table').bootstrapTable('getSelections');
var row = rows[0];
$.modal.open("发起审核", prefix + "/startAuditPage?id="+row.id);
}
function saleOn(id) {
$.modal.confirm("确定要上架",function () {
$.operate.get(prefix+"/saleOn?id="+id)
})
}
function saleOff(id) {
$.modal.confirm("确定要下架",function () {
$.operate.get(prefix+"/saleOff?id="+id)
})
}
</script>
</body>
</html>