规格管理
后台代码
- 1、创建一个规格与规格选项的实体类
public class Specification implements Serializable{
private static final long serialVersionUID = 1L;
private TbSpecification specification;
private List<TbSpecificationOption> specificationOptionList;
public TbSpecification getSpecification() {
return specification;
}
public void setSpecification(TbSpecification specification) {
this.specification = specification;
}
public List<TbSpecificationOption> getSpecificationOptionList() {
return specificationOptionList;
}
public void setSpecificationOptionList(
List<TbSpecificationOption> specificationOptionList) {
this.specificationOptionList = specificationOptionList;
}
public Specification() {
super();
// TODO Auto-generated constructor stub
}
public Specification(TbSpecification specification,
List<TbSpecificationOption> specificationOptionList) {
super();
this.specification = specification;
this.specificationOptionList = specificationOptionList;
}
- 2、规格增加service层
@Override
public void add(Specification specification) {
// 获取规格对象
specificationMapper.insert(specification.getSpecification());
// 判断若数组不为空并且长度大于0就向规格选项表中插入数据
for (TbSpecificationOption tbSpecificationOption : specification.getSpecificationOptionList()) {
// 向规格选项对象插入规格对象id
tbSpecificationOption.setSpecId(specification.getSpecification().getId());
// 插入数据
specificationOptionMapper.insert(tbSpecificationOption);
}
}
-在执行service规格增加时,需要在xml中加入一段语句
< selectKey resultType=“java.lang.Long” order=“AFTER” keyProperty=“id” >
SELECT LAST_INSERT_ID() AS id
< /selectKey>
-
由于规格和规格选项表是一个主外键关系,此段语句加入到规格插入语句中的最前面,用于获取最后一次插入的id值
-
3、规格修改
public void update(Specification specification) {
// 获取规格对象
specificationMapper.updateByPrimaryKey(specification.getSpecification());
// 新增Example对象
TbSpecificationOptionExample example = new TbSpecificationOptionExample();
// 获取离线qbc对象
com.pinyougou.pojo.TbSpecificationOptionExample.Criteria createCriteria = example
.createCriteria();
createCriteria.andSpecIdEqualTo(specification.getSpecification().getId());
// 根据qbc删除
specificationOptionMapper.deleteByExample(example);
// specificationMapper.updateByPrimaryKey(specification);
// 循环插入数据
for (TbSpecificationOption tbSpecificationOption : specification
.getSpecificationOptionList()) {
// 向规格选项对象插入规格对象id
tbSpecificationOption.setSpecId(specification.getSpecification().getId());
// 插入数据
specificationOptionMapper.insert(tbSpecificationOption);
}
}
- 在此修改语句中,是先删除规格选项与此规格相关联的所有数据,再插入数据;
- 4、根据id获取实体
public Specification findOne(Long id) {
TbSpecification tbSpecification = specificationMapper
.selectByPrimaryKey(id);
// 新增Example对象
TbSpecificationOptionExample example = new TbSpecificationOptionExample();
// 获取离线qbc对象
com.pinyougou.pojo.TbSpecificationOptionExample.Criteria createCriteria = example
.createCriteria();
createCriteria.andSpecIdEqualTo(tbSpecification.getId());
// 通过离线查询查询出规格对应的规格选项对象
List<TbSpecificationOption> tbSpecificationOption = specificationOptionMapper
.selectByExample(example);
return new Specification(tbSpecification, tbSpecificationOption);
}
- 5、批量删除
public void delete(Long[] ids) {
//通过规格选项对象获取离线查询对象
for (Long id : ids) {
TbSpecificationOptionExample example = new TbSpecificationOptionExample();
//创建离线查询对象
com.pinyougou.pojo.TbSpecificationOptionExample.Criteria createCriteria = example.createCriteria();
createCriteria.andSpecIdEqualTo(id);
//执行删除
specificationOptionMapper.deleteByExample(example);
specificationMapper.deleteByPrimaryKey(id);
}
}
规格选项前台
- 新建按钮绑定一个单击事件,即:
ng-click="entity={specificationOptionList:[]}"
- 添加行:
$scope.specificationOptionAdd = function(){
$scope.entity.specificationOptionList.push({});
}
- 删除行:
$scope.specificationOptionDel = function(index){
$scope.entity.specificationOptionList.splice(index,1);
}
- 循环新增/编辑窗口,通过ng-repeat指令进行循环,代码展示如下:
< tr ng-repeat="pojo in entity.specificationOptionList">
<td>
<input class="form-control" placeholder="规格选项" ng-model="pojo.optionName">
</td>
<td>
<input class="form-control" placeholder="排序" ng-model="pojo.orders">
</td>
<td>
<button type="button" class="btn btn-default" title="删除" ng-click="specificationOptionDel($index)"><i class="fa fa-trash-o"></i> 删除</button>
</td>
</tr>
- 保存/更新二合一方法:
$scope.save=function(){
var serviceObject;//服务层对象
if($scope.entity.specification.id!=null){//如果有ID
serviceObject=specificationService.update( $scope.entity ); //修改
}else{
serviceObject=specificationService.add( $scope.entity );//增加
}
serviceObject.success(
function(response){
if(response.success){
//重新查询
$scope.reloadList();//重新加载
}else{
alert(response.message);
}
}
);
}
模板列表
引入select2标签
<link rel="stylesheet" href="../plugins/select2/select2.css" />
<link rel="stylesheet" href="../plugins/select2/select2-bootstrap.css" />
<script src="../plugins/select2/select2.min.js" type="text/javascript"></script >
< script type="text/javascript" src="../js/angular-select2.js">< /script>
- 最后一个js标签需要使用app指令,必须放在baseController下方
- 前端品牌实例
<input select2 select2-model="entity.brandIds" config="brandIdsList" multiple placeholder="选择品牌(可多选)" class="form-control" type="text"/>
/*select2 表示应用的select2插件,select2-model是绑定在哪个变量上,config是数据来源,multiple代表多选,没有multiple代表单选
前端controller实例:*/
$scope.brandIdsList={data:[]};
$scope.queryBrandList = function(){
brandService.queryBrandList().success(
function(response){
$scope.brandIdsList={data:response};
}
);/*brandService是调用的service方法*/
}
/*引用其他service类时,需要在html中加入service对应的js,并在controller中要获取service名称,以便调用*/
/*后台品牌列表获取时获取的是一个map集合的List集合,即List<Map>*/
- 新增/编辑时品牌、规格获取
/*前端controller的变化*/
$scope.findOne=function(id){
typeTemplateService.findOne(id).success(
function(response){
$scope.entity= response;
$scope.entity.brandIds = JSON.parse($scope.entity.brandIds);
$scope.entity.specIds = JSON.parse($scope.entity.specIds);
$scope.entity.customAttributeItems = JSON.parse($scope.entity.customAttributeItems);
}
);
}/*通过内置的JSON转换,将json数据转换为字符串*/
前端模板展示优化
- 由于json格式化是通用的,所有模板都能使用到的,所以写入到baseController中
$scope.jsonToString = function(jsonString,key){
//将jsonString转换为字符串
var json = JSON.parse(jsonString);
var value = "";
for(var i = 0;i< json.length;i++){
//得到每一个属性
//如果是最后一个值,不需要添加逗号
if(i == json.length - 1){
value += json[i][key];
}else{
value += json[i][key]+"," ;
}
}
return value;
}
- 前端html该如何引用呢?
<tr ng-repeat="entity in list">
<td><input type="checkbox" ng-click="updateSelection($event,entity.id)"></td>
<td>{{entity.id}}</td>
<td>{{entity.name}}</td>
<td>{{jsonToString(entity.brandIds,'text')}}</td>
<td>{{jsonToString(entity.specIds,'text')}}</td>
<td>{{jsonToString(entity.customAttributeItems,'text')}}</td>
<td class="text-center">
<button type="button" class="btn bg-olive btn-xs" data-toggle="modal" data-target="#editModal" ng-click="findOne(entity.id)">修改</button>
</td>
</tr>
分层、继承
小伙伴们有疑问了,分层和继承,不是后端的么?错了,angularjs同样可以分层和继承
- 我们来看看以前的代码
<script type="text/javascript" >
var app = angular.module('pinyougou',['pagination']);
app.controller('typeTemplateController' ,function($scope,$http)
//读取列表数据绑定到表单中
$http.get('../typeTemplate/findAll.do').findAll=function(){
typeTemplateService.findAll().success(
function(response){
$scope.list=response;
}
);
}
}
< /script>
- 与html代码糅杂在一起的代码是不方便后期维护/管理的,这时分层来了
-- 首先定义一个支持分页的js文件,并在页面上引用
var app = angular.module('pinyougou',['pagination']);
-- 定义一个页面文件对应的service,和后台交互的服务层
app.service('typeTemplateService',function($http){
//读取列表数据绑定到表单中
this.findAll=function(){
return $http.get('../typeTemplate/findAll.do');
}
}
-- 定义一个页面文件对应的controller
app.controller('typeTemplateController' ,function($scope,typeTemplateService){
//读取列表数据绑定到表单中
$scope.findAll=function(){
typeTemplateService.findAll().success(
function(response){
$scope.list=response;
}
);
}
}
- 继承
app.controller('typeTemplateController' ,function($scope,$controller,typeTemplateService){
$controller('baseController',{$scope:$scope});//继承
//读取列表数据绑定到表单中
$scope.findAll=function(){
typeTemplateService.findAll().success(
function(response){
$scope.list=response;
}
);
}
}
- 继承其实是一种伪继承,就是将父类controller的内容加入到本controller当中,继承必须引用内置的$controller对象