一、前端框架分层开发
1、将前端angularjs框架分为controller和service层
controller文件夹中放置所有的自定义的controller模块的的js文件,controller模块是angularjs提供的同页面进行交互的模块,service中放置所有与后台进行交互的模块内容
2、各个js文件中的内容
(1)、base.js
/* 该文件是基本自定义模块文件,不需要引入任何的模块*/ var app = angular.module("pinyougou", []);
(2)、base_pagination.js
/* 该文件是引入了分页功能的自定义模块文件*/ var app = angular.module("pinyougou", ['pagination']);
(3)、brandService.js
/* service 模块是angularjs提供的用于和后台进行交互的模块,该文件中只放用于和后台做交互的内容 */ app.service("brandService", function($http){ //定义按条件查询品牌的方法 this.search = function(page, pageSize, searchEntity){ //需要传递到后台的参数是当前页、每页显示条数、条件实体 return $http.post("../brand/search.do?page=" + page + "&pageSize=" + pageSize, searchEntity); } //定义分页查询的方法 this.findByPage = function(page, pageSize){ return $http.get("../brand/findByPage.do?page=" + page + "&pageSize=" + pageSize); } //查询所有 this.findAll = function(){ return $http.get("../brand/findAll.do"); } //添加品牌 this.save = function(entity){ return $http.post("../brand/saveBrand.do", entity); } //更新品牌 this.update = function(entity){ return $http.post("../brand/updateBrand.do", entity); } //根据id查询brand this.toEdit = function(id){ return $http.get("../brand/findById.do?id=" + id); } //定义删除的方法 this.del = function(selectIds){ return $http.post("../brand/del.do?ids=" + selectIds); } });
(4)、brandController.js
/*controller 模块用于进行和页面进行交互, controller中function的第二个参数可以写与后台交互的service模块的名称*/ app.controller("brandController", function($scope, brandService){ //使用分页插件 $scope.paginationConf = { currentPage:1, totalItems:10, itemsPerPage:10, perPageOptions:[10, 20, 30, 40, 50], onChange:function(){ $scope.reloadList(); } }; //初始化查询实体类 $scope.searchEntity = {}; //定义reloadList重新加载列表的方法 $scope.reloadList = function(){ var page = $scope.paginationConf.currentPage; var pageSize = $scope.paginationConf.itemsPerPage; $scope.search(page, pageSize, $scope.searchEntity); } //定义按条件查询品牌的方法 $scope.search = function(page, pageSize, searchEntity){ //需要传递到后台的参数是当前页、每页显示条数、条件实体 brandService.search(page, pageSize, searchEntity).success(function(data){ $scope.list = data.rows; $scope.paginationConf.totalItems = data.total; }); } //定义分页查询的方法 $scope.findByPage = function(page, pageSize){ brandService.findByPage(page, pageSize).success(function(data){ $scope.list = data.rows; $scope.paginationConf.totalItems = data.total; }); } //查询所有 $scope.findAll = function(){ brandService.findAll().success(function(data){ $scope.list = data; }); } //添加品牌 $scope.save = function(){ //定义返回结果集 var returnObj; if($scope.entity.id != null){ returnObj = brandService.update($scope.entity); }else{ returnObj = brandService.save($scope.entity); } returnObj.success(function(data){ if(data.success){ $scope.reloadList(); }else{ alert(data.message); } }); } //根据id查询brand $scope.toEdit = function(id){ brandService.toEdit(id).success(function(data){ $scope.entity = data; }); } //定义选中的id数组 $scope.selectIds = []; $scope.updateSelectIds = function($event, id){ if($event.target.checked){ $scope.selectIds.push(id); }else{ var index = $scope.selectIds.indexOf(id); $scope.selectIds.splice(index, 1); } } //定义删除的方法 $scope.del = function(){ if($scope.selectIds.length == 0){ return; }else{ if(window.confirm("是否删除选中的id")){ brandService.del($scope.selectIds).success(function(data){ if(data.success){ $scope.reloadList(); }else{ alert(data.message); } }); } } } });
(5)、brand.html
<!-- 引入抽取之后的自定义angularjs文件 --> <script type="text/javascript" src="../js/base_pagination.js"></script> <script type="text/javascript" src="../js/service/brandService.js"></script> <script type="text/javascript" src="../js/controller/brandController.js"></script>
二、控制器的继承
1、继承有什么用
自定义的控制器中可以放入一些通用的方法及属性,如分页以及复选框选中事件,在其他控制器中继承即可使用
2、改造brandController.js
将brandController.js中的分页以及复选框事件抽取到baseController.js中,在brandController.js中继承baseController.js
3、baseController.js
app.controller("baseController",function($scope){ //使用分页插件 $scope.paginationConf = { currentPage:1, totalItems:10, itemsPerPage:10, perPageOptions:[10, 20, 30, 40, 50], onChange:function(){ $scope.reloadList(); } }; //初始化查询实体类 $scope.searchEntity = {}; //定义选中的id数组 $scope.selectIds = []; //定义选中复选框事件 $scope.updateSelectIds = function($event, id){ if($event.target.checked){ $scope.selectIds.push(id); }else{ var index = $scope.selectIds.indexOf(id); $scope.selectIds.splice(index, 1); } } });
4、brandController.js中引入baseController.js
5、brand.html中引入baseController.js
三、规格管理
1、规格管理分析
规格管理分为规格以及规格项,在展示规格过程中需要绑定规格下的规格项,在保存和修改规格的时候,要关联修改规格项,因此,需要一个组合实体类来存放用于修改和保存规格时接收参数的实体类,实体类如下:
package com.groupentity; import java.io.Serializable; import java.util.List; import com.pinyougou.pojo.TbSpecification; import com.pinyougou.pojo.TbSpecificationOption; /** * 该实体类用于操作规格时接收数据用的包装类 接收规格数据的格式是:{tbSpecification:{specName:xxx,id:xxx}, * [{规格项},{规格项},{规格项}]} * * @author wingz * */ public class Specification implements Serializable { private TbSpecification tbSpecification; // 规格 private List<TbSpecificationOption> specificationOptionList; // 规格项集合 public TbSpecification getTbSpecification() { return tbSpecification; } public void setTbSpecification(TbSpecification tbSpecification) { this.tbSpecification = tbSpecification; } public List<TbSpecificationOption> getSpecificationOptionList() { return specificationOptionList; } public void setSpecificationOptionList(List<TbSpecificationOption> specificationOptionList) { this.specificationOptionList = specificationOptionList; } }
2、规格分页展示功能
(1)、html页面改造
(2)、specificationService.js
/* service 模块是angularjs提供的用于和后台进行交互的模块,该文件中只放用于和后台做交互的内容 */ app.service("specificationService", function($http){ //定义按条件查询品牌的方法 this.search = function(page, pageSize, searchEntity){ //需要传递到后台的参数是当前页、每页显示条数、条件实体 return $http.post("../specification/search.do?page=" + page + "&pageSize=" + pageSize, searchEntity); } });
(3)、specificationController.js
/*controller 模块用于进行和页面进行交互, controller中function的第二个参数可以写与后台交互的service模块的名称*/ app.controller("specificationController", function($scope, $controller, specificationService){ //继承baseController,目的是让specificationController和baseController共用一个$scope对象 $controller("baseController", {$scope:$scope}); //定义reloadList重新加载列表的方法 $scope.reloadList = function(){ var page = $scope.paginationConf.currentPage; var pageSize = $scope.paginationConf.itemsPerPage; $scope.search(page, pageSize, $scope.searchEntity); //$scope.findByPage(page, pageSize); } //定义按条件查询品牌的方法 $scope.search = function(page, pageSize, searchEntity){ //需要传递到后台的参数是当前页、每页显示条数、条件实体 specificationService.search(page, pageSize, searchEntity).success(function(data){ $scope.list = data.rows; $scope.paginationConf.totalItems = data.total; }); } });
(4)、TbSpecificationController.java
package com.pinyougou.manager.controller; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import com.alibaba.dubbo.config.annotation.Reference; import com.groupentity.Specification; import com.pinyougou.pojo.TbBrand; import com.pinyougou.pojo.TbSpecification; import com.pinyougou.sellergoods.service.SpecificationService; import com.resultentity.PageResult; import com.resultentity.ResultMessage; @RestController @RequestMapping("/specification") public class SpecificationController { @Reference private SpecificationService service; /** * 按条件查询品牌数据 * @param page * @param pageSize * @param TbBrand * @return */ @RequestMapping("search") public PageResult search(Integer page, Integer pageSize, @RequestBody TbSpecification entity) { PageResult rest = service.findPageByExample(page, pageSize, entity); return rest; } }
(5)、TbSepcificationServiceImpl.java
package com.pinyougou.sellergoods.service.impl; import org.springframework.beans.factory.annotation.Autowired; import com.alibaba.dubbo.common.utils.StringUtils; import com.alibaba.dubbo.config.annotation.Service; import com.github.pagehelper.Page; import com.github.pagehelper.PageHelper; import com.groupentity.Specification; import com.pinyougou.mapper.TbSpecificationMapper; import com.pinyougou.pojo.TbSpecification; import com.pinyougou.pojo.TbSpecificationExample; import com.pinyougou.pojo.TbSpecificationExample.Criteria; import com.pinyougou.sellergoods.service.SpecificationService; import com.resultentity.PageResult; @Service public class SpecificationServiceImpl implements SpecificationService { @Autowired private TbSpecificationMapper mapper; /** * 按条件分页查询 */ public PageResult findPageByExample(Integer pageNum, Integer pageSize, TbSpecification searchEntity) { PageHelper.startPage(pageNum, pageSize); TbSpecificationExample example = new TbSpecificationExample(); Criteria criteria = example.createCriteria(); if (StringUtils.isNotEmpty(searchEntity.getSpecName())) { criteria.andSpecNameLike("%" + searchEntity.getSpecName() + "%"); } if (searchEntity.getId() != null) { criteria.andIdEqualTo(searchEntity.getId()); } Page page = (Page) mapper.selectByExample(example); return new PageResult(page.getTotal(), page.getResult()); } }
3、新增规格
(1)、html页面处理
(2)、specificationController.js
//定义保存和修改时的组合类对象,tbSpecification:规格, specificationOptionList:规格项集合 $scope.entity = {tbSpecification:{}, specificationOptionList:[]}; //定义在新建页面添加规格项按钮时触发的添加规格项的方法,动态添加一个可以输入内容的空行 $scope.addSpecificationOption = function(){ $scope.entity.specificationOptionList.push({}); } //定义新建页面添加规格项时点击删除按钮执行的方,动态删除一行数据 $scope.delSpecificationOption = function(index){ $scope.entity.specificationOptionList.splice(index, 1); } //定义添加规格的方法 $scope.saveSpecification = function(){ //定义返回结果集 var returnObj; if($scope.entity.tbSpecification.id != null){ returnObj = specificationService.update($scope.entity); }else{ returnObj = specificationService.save($scope.entity); } returnObj.success(function(data){ if(data.success){ $scope.reloadList(); }else{ alert(data.message); } }); }
(3)、specificationService.js
//添加规格 this.save = function(entity){ return $http.post("../specification/saveSpecification.do", entity); } //更新规格 this.update = function(entity){ return $http.post("../specification/updateSpecification.do", entity); }
(4)、SpecificationController.java
/** * 保存规格 * @param entity 规格和规格项的组合类 * @return */ @RequestMapping("saveSpecification") public ResultMessage saveBrand(@RequestBody Specification entity) { ResultMessage rest = null; try { service.save(entity); rest = new ResultMessage(true, "保存成功"); } catch (Exception e) { rest = new ResultMessage(false, "保存失败"); e.printStackTrace(); } return rest; }
(5)、SpecificationServiceImpl.java
/** * */ public void save(Specification specification) { //参数为规格和规格项集合的组合类,需要将规格和规格项取出单独执行保存方法 TbSpecification tbSpecification = specification.getTbSpecification(); //保存规格时需要将保存后的id返回,即需要改造mapper映射文件 mapper.insert(tbSpecification); //保存规格项 List<TbSpecificationOption> list = specification.getSpecificationOptionList(); for (TbSpecificationOption option : list) { option.setSpecId(tbSpecification.getId()); optionMapper.insert(option); } }
4、跳转到规格修改操作
(1)、html页面改造
(2)、specificationController.js
//根据id查询specification $scope.toEdit = function(id){ specificationService.toEdit(id).success(function(data){ $scope.entity = data; }); }
(3)、specificationService.js
//根据id查询specification this.toEdit = function(id){ return $http.get("../specification/findById.do?id=" + id); }
(4)、SpecificationController.java
/** * 根据规格id查询规格和规格项集合,用于修改规格 * @param id * @return */ @RequestMapping("findById") public Specification findById(Long id) { Specification rest = service.findById(id); return rest; } /** * 修改规格数据 * @param entity * @return */ @RequestMapping("updateSpecification") public ResultMessage updateBrand(@RequestBody Specification entity) { ResultMessage rest = null; try { service.update(entity); rest = new ResultMessage(true, "修改成功"); } catch (Exception e) { rest = new ResultMessage(false, "修改失败"); e.printStackTrace(); } return rest; }
(5)、SpecificationServiceImpl.java
/** * 根据规格id查询规格和规格项的集合 */ public Specification findById(Long id) { Specification spec = new Specification(); // 根据id查询规格对象 TbSpecification tbSpecification = mapper.selectByPrimaryKey(id); spec.setTbSpecification(tbSpecification); // 根据规格id查询规格项集合 TbSpecificationOptionExample example = new TbSpecificationOptionExample(); example.createCriteria().andSpecIdEqualTo(id); List<TbSpecificationOption> list = optionMapper.selectByExample(example); spec.setSpecificationOptionList(list); return spec; } /** * 更新操作 */ public void update(Specification specification) { //修改规格 mapper.updateByPrimaryKey(specification.getTbSpecification()); //修改规格项,需要先将原有的规格项删除,在将本次请求传递的数据添加到数据库中 TbSpecificationOptionExample example = new TbSpecificationOptionExample(); example.createCriteria().andSpecIdEqualTo(specification.getTbSpecification().getId()); optionMapper.deleteByExample(example); //获取请求中的规格项集合 List<TbSpecificationOption> optionList = specification.getSpecificationOptionList(); for (TbSpecificationOption option : optionList) { option.setSpecId(specification.getTbSpecification().getId()); optionMapper.insert(option); } }
7、规格删除操作
(1)、html页面
(2)、specificationController.js
//定义删除的方法 $scope.del = function(){ if($scope.selectIds.length == 0){ return; }else{ if(window.confirm("是否删除选中的id")){ specificationService.del($scope.selectIds).success(function(data){ if(data.success){ $scope.reloadList(); }else{ alert(data.message); } }); } } }
(3)、specificationService.js
//定义删除的方法 this.del = function(selectIds){ return $http.post("../specification/del.do?ids=" + selectIds); }
(4)、SpecificationController.java
/** * 批量删除规格 * @param ids * @return */ @RequestMapping("del") public ResultMessage deleteBrand(Long[] ids) { ResultMessage rest = null; try { service.delete(ids); rest = new ResultMessage(true, "删除成功"); } catch (Exception e) { rest = new ResultMessage(false, "删除失败"); e.printStackTrace(); } return rest; }
(5)、SpecificationServiceImpl.java
/** * 删除规格以及规格项 */ public void delete(Long[] ids) { //根据id删除对应的规格 for (Long id : ids) { mapper.deleteByPrimaryKey(id); //删除规格的同时,删除规格下的所有规格项 TbSpecificationOptionExample example = new TbSpecificationOptionExample(); example.createCriteria().andSpecIdEqualTo(id); optionMapper.deleteByExample(example); } }
四、模板管理
1、实现模版类型的分页显示
(1)、typeTemplateController.js
/*controller 模块用于进行和页面进行交互, controller中function的第二个参数可以写与后台交互的service模块的名称*/ app.controller("typeTemplateController", function($scope, $controller, typeTemplateService){ //继承baseController,目的是让typeTemplateController和baseController共用一个$scope对象 $controller("baseController", {$scope:$scope}); //定义reloadList重新加载列表的方法 $scope.reloadList = function(){ var page = $scope.paginationConf.currentPage; var pageSize = $scope.paginationConf.itemsPerPage; //$scope.search(page, pageSize, $scope.searchEntity); $scope.findByPage(page, pageSize); } //定义分页查询的方法 $scope.findByPage = function(page, pageSize){ typeTemplateService.findByPage(page, pageSize).success(function(data){ $scope.list = data.rows; $scope.paginationConf.totalItems = data.total; }); } });
(2)、typeTemplateService.js
/* service 模块是angularjs提供的用于和后台进行交互的模块,该文件中只放用于和后台做交互的内容 */ app.service("typeTemplateService", function($http){ //定义分页查询的方法 this.findByPage = function(page, pageSize){ return $http.get("../typeTemplate/findByPage.do?page=" + page + "&pageSize=" + pageSize); } });
(3)、type_template.html
(4)、TypeTemplateController.java
package com.pinyougou.manager.controller; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import com.alibaba.dubbo.config.annotation.Reference; import com.pinyougou.pojo.TbTypeTemplate; import com.pinyougou.sellergoods.service.TypeTemplateService; import com.resultentity.PageResult; import com.resultentity.ResultMessage; @RestController @RequestMapping("/typeTemplate") public class TypeTemplateController { @Reference private TypeTemplateService service; /** * 分页显示所有类型模版 * @param page * @param pageSize * @return */ @RequestMapping("findByPage") public PageResult findByPage(Integer page, Integer pageSize) { PageResult rest = service.findByPage(page, pageSize); return rest; } }
(5)、TypeTemplateServiceImpl.java
package com.pinyougou.sellergoods.service.impl; import java.util.List; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.transaction.annotation.Transactional; import com.alibaba.dubbo.config.annotation.Service; import com.github.pagehelper.Page; import com.github.pagehelper.PageHelper; import com.pinyougou.mapper.TbTypeTemplateMapper; import com.pinyougou.pojo.TbTypeTemplate; import com.pinyougou.sellergoods.service.TypeTemplateService; import com.resultentity.PageResult; @Service @Transactional public class TypeTemplateServiceImpl implements TypeTemplateService { @Autowired private TbTypeTemplateMapper mapper; /** * 分页查询的方法 */ public PageResult findByPage(Integer pageNum, Integer pageSize) { PageHelper.startPage(pageNum, pageSize); Page page = (Page) mapper.selectByExample(null); return new PageResult(page.getTotal(), page.getResult()); } }
2、使用select2插件实现新增页面中的下拉列表选中功能,以及添加删除属性按钮功能
(1)、认识select2插件需要的json数据格式
数据格式:{data : [ {id : xxx; text : xxx}, {id : xxx; text : xxx}, {id : xxx; text : xxx}, {id : xxx; text : xxx} ] }
(2)、改造html页面
(3)、typeTemplateController.js
(4)、brandService.js
//定义用于模版页面中select2插件的品牌下拉表的显示所有品牌的方法 this.findBrandList = function(){ return $http.get("../brand/findBrandList.do"); }
(5)、TbBrandController.java
/** * 查询使用select2插件需要的品牌列表的数据 * {data:[{id:xxx, text:xxx}, {id:xxx, text:xxx}]} * @return */ @RequestMapping("findBrandList") public Map<String, List<Map<String, String>>> findBrandList(){ Map map = service.findByList(); return map; }
(6)、TbBrandServiceImpl.java
/** * 查询所有品牌列表,按需要的格式返回数据 */ public Map findByList() { // 定义json大map, key为data,value为查询出来的每一个品牌的列表对象集合 Map<String, List<Map>> map = new HashMap<String, List<Map>>(); // 查询List集合 List<Map> list = mapper.findByList(); //将查询出的结果封装到大map中 map.put("data", list); return map; }
(7)、TbBrandMapperMapp.java和TbBrandMapper.xml
<!-- 定义返回结果是Map的查询所有品牌的方法 --> <select id="findByList" resultType="map"> select id, name as text from tb_brand </select>
(8)、SpecificationController.java
/** * 定义查询所有规格,并返回指定列表数据的方法 * @return */ @RequestMapping("findSpecList") public Map findSpecList() { Map map = service.findSpecList(); return map; }
(9)、SpecificationServiceImpl.java
/** * 查询数据,返回Select2插件需要的数据 * {data: [{id: xxx, text: xxx}]} */ public Map findSpecList() { Map<String, List<Map>> map = new HashMap<>(); List<Map> list = mapper.findSpecList(); map.put("data", list); return map; }
(10)、TbSpecificationMapper.java和TbSpecificationMapper.xml
<!-- 自定义返回结果为map的查询所有规格的方法 --> <select id="findSpecList" resultType="map"> select id, spec_name as text from tb_specification </select>
(11)、页面测试效果
3、实现新增和修改模版类型功能
(1)、改造html页面
(2)、typeTemplateController.js
//添加或者修改模版 $scope.saveTypeTemplate = function(){ //定义返回结果集 var returnObj; if($scope.entity.id != null){ returnObj = typeTemplateService.update($scope.entity); }else{ returnObj = typeTemplateService.save($scope.entity); } returnObj.success(function(data){ if(data.success){ $scope.reloadList(); }else{ alert(data.message); } }); } //根据id查询typeTemplate $scope.toEdit = function(id){ typeTemplateService.toEdit(id).success(function(data){ //获取到tpyeTemplate对象,其中的品牌列表和规格列表以及属性列表都是字符串,需要转换为数组 var brandIds = data.brandIds; var specIds = data.specIds; var customAttributeItems = data.customAttributeItems; //字符串转换数组 data.brandIds = JSON.parse(brandIds); data.specIds = JSON.parse(specIds); data.customAttributeItems = JSON.parse(customAttributeItems); $scope.entity = data; }); }
(3)、typeTemplateService.js
//添加品牌 this.save = function(entity){ return $http.post("../typeTemplate/saveTypeTemplate.do", entity); } //更新品牌 this.update = function(entity){ return $http.post("../typeTemplate/updateTypeTemplate.do", entity); } //根据id查询typeTemplate this.toEdit = function(id){ return $http.get("../typeTemplate/findById.do?id=" + id); }
(4)、TypeTemplateController.java
/** * 保存模版 * @param entity 模版类 * @return */ @RequestMapping("saveTypeTemplate") public ResultMessage saveBrand(@RequestBody TbTypeTemplate entity) { ResultMessage rest = null; try { service.save(entity); rest = new ResultMessage(true, "保存成功"); } catch (Exception e) { rest = new ResultMessage(false, "保存失败"); e.printStackTrace(); } return rest; } /** * 根据模版id查询模版用于修改模版 * @param id * @return */ @RequestMapping("findById") public TbTypeTemplate findById(Long id) { TbTypeTemplate rest = service.findById(id); return rest; } /** * 修改模版数据 * @param entity * @return */ @RequestMapping("updateTypeTemplate") public ResultMessage updateBrand(@RequestBody TbTypeTemplate entity) { ResultMessage rest = null; try { service.update(entity); rest = new ResultMessage(true, "修改成功"); } catch (Exception e) { rest = new ResultMessage(false, "修改失败"); e.printStackTrace(); } return rest; }
(5)、TypeTemplateServiceImpl.java
/** * 新增 */ public void save(TbTypeTemplate typeTemplate) { mapper.insert(typeTemplate); } /** * 修改 */ public void update(TbTypeTemplate typeTemplate) { mapper.updateByPrimaryKey(typeTemplate); } /** * 根据id查询 */ public TbTypeTemplate findById(Long id) { return mapper.selectByPrimaryKey(id); }
4、优化模版列表数据的展示
(1)、html页面改造
(2)、typeTemplateController.js
//定义将json数组转换为字符串的方法 $scope.jsonToString = function(jsonArray){ //方法获取的是字符串,先转成数组 array = JSON.parse(jsonArray); //遍历json数组,取出每一个元素中的text属性的值,拼接成字符串返回 var str = ""; for (var i = 0; i < array.length; i++) { if(i == array.length - 1){ str += array[i].text; }else{ str += array[i].text + ", "; } } return str; }