二十三、商城 - 商品录入-新增商品(11)

目录

  • 一、商品录入【选择商品分类】
    • 1.1 需求分析
    • 1.2 准备工作
    • 1.3 代码实现
      • 1.3.1 一级分类下拉选择框
      • 1.3.2 二级分类下拉选择框
      • 1.3.3 三级分类下拉选择框
      • 1.3.4 读取模板ID
  • 二、商品录入【品牌选择】
    • 2.1 需求分析
    • 2.2 代码实现
  • 三、商品录入【扩展属性】
    • 3.1 需求分析
    • 3.2 代码实现
  • 四、商品录入【规格选择】
    • 4.1 需求分析
    • 4.2 代码实现
      • 4.2.1 显示规格选项列表
      • 4.2.2 保存选中规格选项
  • 五、商品录入【SKU商品信息】
    • 5.1 需求分析
    • 5.2 前端代码
      • 5.2.1 生成SKU列表(深克隆)
      • 5.2.2 显示SKU列表
    • 5.3 【保存】后端代码
  • 六、商品录入【是否启用规格】
    • 6.1 需求分析
    • 6.2 前端代码
    • 6.3 后端代码
    • 6.4 解决重复录入选择图片失败问题

一、商品录入【选择商品分类】

1.1 需求分析

在商品录入界面实现商品分类的选择(三级分类)效果如下:

二十三、商城 - 商品录入-新增商品(11)_第1张图片

当用户选择一级分类后,二级分类列表要相应更新,当用户选择二级分类后,三级列表要相应更新。

1.2 准备工作

  1. copy 生成得 youlexuan_manager_web下的 ItemCatController到 youlexuan_shop_web工程中
  2. 再 copy itemCatService.js 到 youlexuan_shop_web

二十三、商城 - 商品录入-新增商品(11)_第2张图片

  1. 在 goodsController.js 中引入 itemCatService

二十三、商城 - 商品录入-新增商品(11)_第3张图片

  1. 在 goods_edit.html 中引入下面js
<script type="text/javascript"  src="../js/service/itemCatService.js"></script>

二十三、商城 - 商品录入-新增商品(11)_第4张图片

1.3 代码实现

1.3.1 一级分类下拉选择框

在goodsController增加代码

//查询一级分类

$scope.selectItemCat1List = function () {

	itemCatService.findByParentId(0).success(function (response) {

	$scope.itemCat1List = response;

   })

}

页面加载调用该方法 selectItemCat1List

二十三、商城 - 商品录入-新增商品(11)_第5张图片

修改goods_edit.html一级分类下拉选择框

二十三、商城 - 商品录入-新增商品(11)_第6张图片

<select class="form-control"
     ng-model="entity.goods.category1Id" 
     ng-options="item.id as item.name for item in itemCat1List">
 <option>
 option>
select>

ng-options属性可以在表达式中使用数组或对象来自动生成一个select中的option列表。ng-options与ng-repeat很相似,很多时候可以用ng-repeat来代替ng-options。但是ng-options提供了一些好处,例如减少内存提高速度,以及提供选择框的选项来让用户选择。

运行效果如下 :

二十三、商城 - 商品录入-新增商品(11)_第7张图片

1.3.2 二级分类下拉选择框

在goodsController增加代码:

//在当前一级分类中查询二级分类
$scope.$watch('entity.goods.category1Id',function (newValue,oldValue) {

   		 //判断一级分类有选择具体分类值,在去获取二级分类
		if(newValue){
		//根据选择的值,查询二级分类
		        itemCatService.findByParentId(newValue).success(function (response) {
		
		            $scope.itemCat2List = response;
		
		            $scope.itemCat3List = {};//第二次选一级则二三置空,选二,三置空
		
		        })
		}

});

$watch方法用于监控某个变量的值,当被监控的值发生变化,就自动执行相应的函数。
修改goods_edit.html中二级分类下拉框

<td>
	<select class="form-control select-sm" ng-model="entity.goods.category2Id" ng-options="item.id as item.name for item in itemCat2List">select>
td>

1.3.3 三级分类下拉选择框

//在当前二级分类中查询三级分类
$scope.$watch('entity.goods.category2Id',function (newValue,oldValue) {
	//判断二级分类有选择具体分类值,在去获取三级分类
    if(newValue){
		//根据选择的值,查询二级分类
        itemCatService.findByParentId(newValue).success(function (response) {

            $scope.itemCat3List = response;

        })
    }

})

修改goods_edit.html中三级分类下拉框

<td>
	<select class="form-control select-sm" ng-model="entity.goods.category3Id" ng-options="item.id as item.name for item in itemCat3List">select>
td>

最终效果:
在这里插入图片描述

1.3.4 读取模板ID

在goodsController增加代码:

//查询三级分类时同步显现模板ID
$scope.$watch('entity.goods.category3Id',function (newValue,oldValue) {

   if(newValue){

       itemCatService.findOne(newValue).success(function (response) {

          $scope.entity.goods.typeTemplateId = response.typeId;

       })
   }

})

在 goods_edit.html显示模板ID

<td>
	模板ID:{{entity.goods.typeTemplateId}}
td>

二十三、商城 - 商品录入-新增商品(11)_第8张图片

二、商品录入【品牌选择】

2.1 需求分析

在用户选择商品分类后,品牌列表要根据用户所选择的分类进行更新。具体的逻辑是根据用户选择的三级分类找到对应的商品类型模板,商品类型模板中存储了品牌的列表json数据。

2.2 代码实现

  1. 在 youlexuan_shop_web 工程创建 TypeTemplateController (可从运营商后台拷贝)
  2. 在youlexuan_shop_web工程创建 typeTemplateService.js (可从运营商后台拷贝)

二十三、商城 - 商品录入-新增商品(11)_第9张图片

  1. 在goodsController引入 typeTemplateService 并新增代码

二十三、商城 - 商品录入-新增商品(11)_第10张图片

//显示品牌
//模板ID选择后  更新品牌列表
$scope.$watch('entity.goods.typeTemplateId',function (newValue,oldValue) {

	if(newValue){

		typeTemplateService.findOne(newValue).success(function (response) {

			$scope.typeTemplate = response;//获取类型模板

			$scope.typeTemplate.brandIds = JSON.parse($scope.typeTemplate.brandIds);//品牌列表

       });
	}
})

在页面goods_edit.html 引入js

<script type="text/javascript" src="../js/service/typeTemplateService.js"></script>

二十三、商城 - 商品录入-新增商品(11)_第11张图片
添加品牌选择框

<div class="col-md-10 data">
	<select class="form-control" ng-model="entity.goods.brandId" ng-options="item.id as item.text for item in typeTemplate.brandIds">select>
div>

二十三、商城 - 商品录入-新增商品(11)_第12张图片

最终测试:

二十三、商城 - 商品录入-新增商品(11)_第13张图片

三、商品录入【扩展属性】

3.1 需求分析

在商品录入实现扩展属性的录入。

二十三、商城 - 商品录入-新增商品(11)_第14张图片

3.2 代码实现

修改goodsController.js ,在用户更新模板ID时,读取模板中的扩展属性赋给商品的扩展属性。

//扩展属性
$scope.entity.goodsDesc.customAttributeItems = JSON.parse($scope.typeTemplate.customAttributeItems)

二十三、商城 - 商品录入-新增商品(11)_第15张图片
修改goods_edit.html


<div class="tab-pane" id="customAttribute">
{{entity.goodsDesc.customAttributeItems}} 
<div class="row data-type">
   <div ng-repeat="pojo in entity.goodsDesc.customAttributeItems">
       <div class="col-md-2 title">{{pojo.text}}div>
       <div class="col-md-10 data">
           <input class="form-control"  ng-model="pojo.value"  placeholder="{{pojo.text}}">
       div>
   div>
div>
div>

二十三、商城 - 商品录入-新增商品(11)_第16张图片

最终效果显示:

二十三、商城 - 商品录入-新增商品(11)_第17张图片

四、商品录入【规格选择】

二十三、商城 - 商品录入-新增商品(11)_第18张图片

4.1 需求分析

显示规格及选项列表(复选框)如下图,并保存用户选择的结果

在这里插入图片描述

4.2 代码实现

4.2.1 显示规格选项列表

由于模板中只记录了规格名称,而我们除了显示规格名称还是显示规格下的规格选项,所以我们需要在后端扩充方法。

(1)在youlexuan_sellergoods_interface 的 TypeTemplateService.java 新增方法定义

/** * 返回指定模板 id 的规格列表 * @return */

public List<Map> findSpecList(Long id);

(2)在 youlexuan_sellergoods_service 的 TypeTemplateServiceImpl.java 实现新增的方法

@Autowired
private TbSpecificationOptionMapper tbSpecificationOptionMapper;

/**
 * 返回指定模板 id 的规格列表 * @return
 */
@Override
public List<Map> findSpecList(Long id) {

	//根据模板 id 获取对应模板对象
	TbTypeTemplate tbTypeTemplate = typeTemplateMapper.selectByPrimaryKey(id);

	//从模板对象获取规格属性
	String specIds = tbTypeTemplate.getSpecIds();
	//[{"id":27,"text":"网络"},{"id":32,"text":"机身内存"}]转成json对象形式
	List<Map> mapList = JSON.parseArray(specIds, Map.class);
	//遍历规格集合
	for (Map map : mapList) {
		//[{"id":27,"text":"网络"},{"id":32,"text":"机身内存"}]根据转的key获得map
		Long specId = new Long((Integer) map.get("id"));
		//根据规格 id 获取规格选项
		TbSpecificationOptionExample tbSpecificationOptionExample = new TbSpecificationOptionExample();

		TbSpecificationOptionExample.Criteria criteria = tbSpecificationOptionExample.createCriteria();

		criteria.andSpecIdEqualTo(specId);

		List<TbSpecificationOption> tbSpecificationOptions = tbSpecificationOptionMapper.selectByExample(tbSpecificationOptionExample);

		map.put("options",tbSpecificationOptions);

	}

	return mapList;
}

(3)在 youlexuan_shop_web 的 TypeTemplateController.java 新增方法

@RequestMapping("/findSpecList")
public List<Map> findSpecList(Long id){

	return typeTemplateService.findSpecList(id);
}

后台测试:http://localhost:9102/typeTemplate/findSpecList.do?id=51

二十三、商城 - 商品录入-新增商品(11)_第19张图片
注:测试的时候要测表 tb_type_template 中id 存在的,不然回报 500

二十三、商城 - 商品录入-新增商品(11)_第20张图片

(4)前端代码:修改 youlexuan_shop_web 的 typeTemplateService.js

//获取规格和规格选项
this.findSpecList = function (id) {

	return $http.get('../typeTemplate/findSpecList.do?id='+id);

}

(5)修改 youlexuan_shop_web 的 goodsController.js

//规格和规格选项
typeTemplateService.findSpecList(newValue).success(function (response) {

	$scope.specList = response;
});

二十三、商城 - 商品录入-新增商品(11)_第21张图片
(6)修改 goods_edit.html 页面

<div class="row data-type">
    <div ng-repeat="pojo in specList">
        <div class="col-md-2 title">{{pojo.text}}div>
        <div class="col-md-10 data">

            <span ng-repeat="option in pojo.options">
                <input type="checkbox">{{option.optionName}}
            span>
        div>
    div>
div>

二十三、商城 - 商品录入-新增商品(11)_第22张图片

前台测试 :http://localhost:9102/shoplogin.html

二十三、商城 - 商品录入-新增商品(11)_第23张图片

4.2.2 保存选中规格选项

注:此标题 js 理解就行,因为有点复杂,想要实现,直接 copy 我的 code 就行

我们需要将用户选中的选项保存在 tb_goods_desc 表的 specification_items 字段中,定义 json 格式如下:

[{“attributeName”:”规格名称”,”attributeValue”:[“规格选项 1”,“规格选项 2”.... ] } , .... ]

(1)在 baseController.js 增加代码

//从集合中按照key查询对象
$scope.searchObjectByKey=function(list,key,keyValue){
    for(var i=0;i<list.length;i++){
        if(list[i][key]==keyValue){
            return list[i];
        }
    }
    return null;
}

(2)在 goodsController.js 增加代码

$scope.entity = {goods:{},goodsDesc:{itemImages:[],specificationItems:[]},itemList:[]};
$scope.updateSpecAttribute=function($event,name,value){
   //搜索规格选项,看指定规格是否存在  event 事件 name规格名称 value 规格选项
   var object= $scope.searchObjectByKey($scope.entity.goodsDesc.specificationItems ,'attributeName', name);
   //如果规格存在
   if(object!=null){
       //判断复选框选中状态
       if($event.target.checked ){
           //复选框选中,把对应的规格选项值插入当前规格对应的规格选项数组
           object.attributeValue.push(value);
       }else{
           //复选框取消勾选
           object.attributeValue.splice( object.attributeValue.indexOf(value) ,1);//移除选项
           //如果选项都取消了,将此条记录移除
           if(object.attributeValue.length==0){
               $scope.entity.goodsDesc.specificationItems.splice($scope.entity.goodsDesc.specificationItems.indexOf(object),1);
           }
       }
   }else{
//首次选中某个规格,添加规格及对应选中的规格值
$scope.entity.goodsDesc.specificationItems.push({"attributeName":name,"attributeValue":[value]});
   }
}

二十三、商城 - 商品录入-新增商品(11)_第24张图片

二十三、商城 - 商品录入-新增商品(11)_第25张图片

(3)在goods_edit.html调用方法

<span ng-repeat="option in pojo.options">
	<input type="checkbox" ng-click="updateSpecAttribute($event,pojo.text,option.optionName)">{{option.optionName}}
span>

二十三、商城 - 商品录入-新增商品(11)_第26张图片

测试 http://localhost:9102/admin/index.html

二十三、商城 - 商品录入-新增商品(11)_第27张图片

五、商品录入【SKU商品信息】

5.1 需求分析

基于上一步已经完成了规格选择,根据选择的规格录入商品的SKU信息,当用户选择相应的规格,下面的SKU列表就会自动生成,如下图:

二十三、商城 - 商品录入-新增商品(11)_第28张图片
实现思路:实现思路:

  1. 我们先定义一个初始的不带规格名称的集合,只有一条记录。
  2. 循环用户选择的规格,根据规格名称和已选择的规格选项对原集合进行扩充,添加规格名称和值,新增的记录数与选择的规格选项个数相同

生成的顺序如下图:

二十三、商城 - 商品录入-新增商品(11)_第29张图片

5.2 前端代码

5.2.1 生成SKU列表(深克隆)

注:此标题 js 理解就行,因为有点复杂,想要实现,直接 copy 我的 code 就行

(1)在goodsController.js实现创建sku列表的方法

//创建SKU列表
$scope.createItemList=function(){
	//spec 存储sku对应的规格
   	 $scope.entity.itemList=[{spec:{},price:0,num:99999,status:'0',isDefault:'0' } ];//初始
	//定义变量 items指向 用户选中规格集合
	//[{"attributeName":"网络制式","attributeValue":["移动3G","移动4G"]},{"attributeName":"屏幕尺寸","attributeValue":["6寸","5寸"]}]

    var items=  $scope.entity.goodsDesc.specificationItems;
	//遍历用户选中规格集合
    for(var i=0;i< items.length;i++){
		//编写增加sku规格方法addColumn 参数1:sku规格列表  参数2:规格名称  参数3:规格选项
        $scope.entity.itemList = addColumn( $scope.entity.itemList,items[i].attributeName,items[i].attributeValue );
    }
};
	//添加列值
	addColumn=function(list,columnName,conlumnValues){
    var newList=[];//新的集合
	//遍历sku规格列表
    for(var i=0;i<list.length;i++){
        //读取每行sku数据,赋值给遍历oldRow
        var oldRow= list[i];
        //遍历规格选项
        for(var j=0;j<conlumnValues.length;j++){
            //深克隆当前行sku数据为 newRow
            var newRow= JSON.parse( JSON.stringify( oldRow )  );//深克隆
            //在新行扩展列(列名是规格名称),给列赋值(规格选项值)
            newRow.spec[columnName]=conlumnValues[j];

			//保存新sku行到sku新集合
            newList.push(newRow);
        }
    }
    return newList;
}

部分截图:

二十三、商城 - 商品录入-新增商品(11)_第30张图片

(2)在更新规格属性后调用生成SKU列表的方法

二十三、商城 - 商品录入-新增商品(11)_第31张图片
显示效果如下:

二十三、商城 - 商品录入-新增商品(11)_第32张图片

5.2.2 显示SKU列表

goods_edit.html页面上绑定SKU列表

<table class="table table-bordered table-striped table-hover dataTable">
    <thead>
    <tr>
        <th class="sorting" ng-repeat="item in entity.goodsDesc.specificationItems">{{item.attributeName}}th>
        <th class="sorting">价格th>
        <th class="sorting">库存th>
        <th class="sorting">是否启用th>
        <th class="sorting">是否默认th>
    tr>
    thead>
    <tbody>
    <tr ng-repeat="pojo in entity.itemList">
        <td ng-repeat="item in entity.goodsDesc.specificationItems">
            {{pojo.spec[item.attributeName]}}
        td>
        <td>
            <input class="form-control" ng-model="pojo.price"  placeholder="价格">
        td>
        <td>
            <input class="form-control" ng-model="pojo.num" placeholder="库存数量">
        td>
        <td>
            <input type="checkbox" ng-model="pojo.status" ng-true-value="1" ng-false-value="0" >
        td>
        <td>
            <input type="checkbox" ng-model="pojo.isDefault" ng-true-value="1" ng-false-value="0">
        td>
    tr>
    tbody>
table>

二十三、商城 - 商品录入-新增商品(11)_第33张图片

没有选规格选项时显示

二十三、商城 - 商品录入-新增商品(11)_第34张图片

选规格选项时显示

二十三、商城 - 商品录入-新增商品(11)_第35张图片

5.3 【保存】后端代码

(1)在GoodsServiceImpl 添加属性

	//商品录入保存
	@Autowired
	private TbItemMapper itemMapper;

	@Autowired
	private TbBrandMapper brandMapper;

	@Autowired
	private TbItemCatMapper itemCatMapper;

	@Autowired
	private TbSellerMapper sellerMapper;
//SKU商品信息的保存
for(TbItem item :goods.getItemList()){
	//标题
	String title= goods.getGoods().getGoodsName();
	Map<String,Object> specMap = JSON.parseObject(item.getSpec());
	for(String key:specMap.keySet()){
		title+=" "+ specMap.get(key);
	}
	item.setTitle(title);
	item.setGoodsId(goods.getGoods().getId());//商品SPU编号
	item.setSellerId(goods.getGoods().getSellerId());//商家编号
	item.setCategoryid(goods.getGoods().getCategory3Id());//商品分类编号(3级)
	item.setCreateTime(new Date());//创建日期
	item.setUpdateTime(new Date());//修改日期
	//品牌名称
	TbBrand brand = brandMapper.selectByPrimaryKey(goods.getGoods().getBrandId());
	item.setBrand(brand.getName());
	//分类名称
	TbItemCat itemCat = itemCatMapper.selectByPrimaryKey(goods.getGoods().getCategory3Id());
	item.setCategory(itemCat.getName());
	//商家名称
	TbSeller seller = sellerMapper.selectByPrimaryKey(goods.getGoods().getSellerId());
	item.setSeller(seller.getNickName());
	//图片地址(取spu的第一个图片)
	List<Map> imageList = JSON.parseArray(goods.getGoodsDesc().getItemImages(), Map.class) ;
	if(imageList.size()>0){
		item.setImage ( (String)imageList.get(0).get("url"));
	}
	itemMapper.insert(item);
}

二十三、商城 - 商品录入-新增商品(11)_第36张图片

六、商品录入【是否启用规格】

6.1 需求分析

在规格面板添加是否启用规格,当用户没有选择该项,将原来的规格面板和SKU列表隐藏,用户保存商品后只生成一个SKU.

二十三、商城 - 商品录入-新增商品(11)_第37张图片

6.2 前端代码

goods_edit.html是否启用规格复选框处理,用if指令控制规格面板与SKU列表的显示与隐藏

二十三、商城 - 商品录入-新增商品(11)_第38张图片


<div class="tab-pane" id="spec">
    <div class="row data-type">
        <div class="col-md-2 title">是否启用规格div>
        <div class="col-md-10 data">
            <input type="checkbox"  ng-model="entity.goods.isEnableSpec" ng-true-value="1" ng-false-value="0" >
        div>
    div>
    <p>

    <div ng-if="entity.goods.isEnableSpec==1"> 

6.3 后端代码

修改GoodsServiceImpl的add方法

/**
 * 增加
 */
@Override
public void add(Goods goods) {
	goods.getGoods().setAuditStatus("0");		
	goodsMapper.insert(goods.getGoods());	//插入商品表
	goods.getGoodsDesc().setGoodsId(goods.getGoods().getId());
	goodsDescMapper.insert(goods.getGoodsDesc());//插入商品扩展数据
	if("1".equals(goods.getGoods().getIsEnableSpec())){
		for(TbItem item :goods.getItemList()){
			//标题
			String title= goods.getGoods().getGoodsName();
			Map<String,Object> specMap = JSON.parseObject(item.getSpec());
			for(String key:specMap.keySet()){
				title+=" "+ specMap.get(key);
			}
			item.setTitle(title);
			setItemValus(goods,item);
			itemMapper.insert(item);
		}		
	}else{					
		TbItem item=new TbItem();
		item.setTitle(goods.getGoods().getGoodsName());//商品SPU+规格描述串作为SKU名称
		item.setPrice( goods.getGoods().getPrice() );//价格			
		item.setStatus("1");//状态
		item.setIsDefault("1");//是否默认			
		item.setNum(99999);//库存数量
		item.setSpec("{}");			
		setItemValus(goods,item);					
		itemMapper.insert(item);
	}	
}

private void setItemValus(Goods goods,TbItem item) {
	item.setGoodsId(goods.getGoods().getId());//商品SPU编号
	item.setSellerId(goods.getGoods().getSellerId());//商家编号
	item.setCategoryid(goods.getGoods().getCategory3Id());//商品分类编号(3级)
	item.setCreateTime(new Date());//创建日期
	item.setUpdateTime(new Date());//修改日期 
	
	//品牌名称
	TbBrand brand = brandMapper.selectByPrimaryKey(goods.getGoods().getBrandId());
	item.setBrand(brand.getName());
	//分类名称
	TbItemCat itemCat = itemCatMapper.selectByPrimaryKey(goods.getGoods().getCategory3Id());
	item.setCategory(itemCat.getName());
	
	//商家名称
	TbSeller seller = sellerMapper.selectByPrimaryKey(goods.getGoods().getSellerId());
	item.setSeller(seller.getNickName());
	
	//图片地址(取spu的第一个图片)
	List<Map> imageList = JSON.parseArray(goods.getGoodsDesc().getItemImages(), Map.class) ;
	if(imageList.size()>0){
		item.setImage ( (String)imageList.get(0).get("url"));
	}		
}

二十三、商城 - 商品录入-新增商品(11)_第39张图片
二十三、商城 - 商品录入-新增商品(11)_第40张图片

前台录入测试:

启动 ①
二十三、商城 - 商品录入-新增商品(11)_第41张图片
安装youlexuan_parent 并且 启动 ②

在这里插入图片描述

浏览器输入:http://127.0.0.1:9102/shoplogin.html

二十三、商城 - 商品录入-新增商品(11)_第42张图片
二十三、商城 - 商品录入-新增商品(11)_第43张图片
二十三、商城 - 商品录入-新增商品(11)_第44张图片
二十三、商城 - 商品录入-新增商品(11)_第45张图片
二十三、商城 - 商品录入-新增商品(11)_第46张图片
二十三、商城 - 商品录入-新增商品(11)_第47张图片

查看数据库是否有数据:

二十三、商城 - 商品录入-新增商品(11)_第48张图片
在这里插入图片描述

在这里插入图片描述
……

6.4 解决重复录入选择图片失败问题

修改goodsController的保存方法,保存成功后,清空实体对象,保留基本结构

 $scope.entity={ goodsDesc:{itemImages:[],specificationItems:[]}  };

二十三、商城 - 商品录入-新增商品(11)_第49张图片

当前 youlexuan 所有完整代码

你可能感兴趣的:(#,计算机(Java中级)中级,阶段,前端,java)