品优购_day06
1. 商品分类
在商品录入界面实现商品分类的选择(三级分类)效果如下:
当用户选择一级分类后,二级分类列表要相应更新,当用户选择二级分类后,三级列表要相应更新。
1.1 一级分类
重点:ng-options
goods_edit页面初始化时加载selectItemCat1List()方法,查询一级分类,及parentId为0。
修改goods_edit.html一级分类下拉选择框:
<select class="form-control" ng-model="entity.goods.category1Id" ng-options="item.id as item.name for item in itemCat1List"></select>
entity.goods.category1Id是要提交的实体的属性名称。
ng-options属性可以在表达式中使用数组或对象来自动生成一个select中的option列表。ng-options与ng-repeat很相似,很多时候可以用ng-repeat来代替ng-options。但是ng-options提供了一些好处,例如减少内存提高速度,以及提供选择框的选项来让用户选择。
item.id为值,即select的value;item.name是下拉选择框的文本,即select的label(标签)。
id和name取决于数据库中怎么写的:
1.2 二级分类
重点:$watch
//查询二级分类
$scope.$watch('entity.goods.category1Id',function(newValue,oldValue){
//根据选择的一级分类id查询二级分类
itemCatService.findAll(newValue).success(
function(response){
$scope.itemCat2List=response;
}
);
});
oldvalue即entity.goods.category1Id变化前的值,newvalue即变化后的值。$watch方法用于监控某个变量的值,当被监控的值发生变化,就自动执行相应的函数,
(三级分类略)
2. 商品录入:品牌选择
重点:将json字符串转换为json对象,从json对象中取数据较方便
选择三级分类后,模板id也确定了,根据模板id查询品牌列表,形成品牌下拉框。
$scope.$watch('entity.goods.typeTemplateId',function(newValue,oldValue){
typeTemplateService.findOne(newValue).success(
function(response){
$scope.typeTemplate=response;
$scope.typeTemplate.brandIds=JSON.parse($scope.typeTemplate.brandIds);//品牌下拉框的显示
//将json字符串转换为json对象,从json对象中取数据较方便,方便品牌选择框循环品牌数据
//[{"id":27,"text":"网络"},{"id":32,"text":"机身内存"}]
}
}
)
添加品牌选择框:
<select class="form-control" ng-model="entity.goods.brandId" ng-options="item.id as item.text for item in typeTemplate.brandIds"></select>
3. 商品录入:扩展属性
选择三级分类后,模板id也确定了,根据模板id查询扩展属性,获取扩展属性名称。
$scope.$watch('entity.goods.typeTemplateId',function(newValue,oldValue){
typeTemplateService.findOne(newValue).success(
function(response){
$scope.typeTemplate=response;
$scope.typeTemplate.brandIds=JSON.parse($scope.typeTemplate.brandIds); $scope.entity.goodsDesc.customAttributeItems=JSON.parse($scope.typeTemplate.customAttributeItems);//扩展属性
}
}
)
4. 商品录入:规格选择
4.1 需求分析
显示规格及选项列表(复选框)如下图,并保存用户选择的结果
4.2 查询规格选项列表
TypeTemplateServiceImpl.java,根据模板id查询规格具体选项
public List<Map> selectSpecList(Long id) {
//1.根据模板id查询出模板
TbTypeTemplate typeTemplate=typeTemplateMapper.selectByPrimaryKey(id);
//2.获取规格id
String specIds=typeTemplate.getSpecIds();
/*
* typeTemplate.getSpecIds()获取到的数据为String类型,如下:
* [{"id":27,"text":"网络"},{"id":32,"text":"机身内存"}],
* 需要转换成List<Map>以便获取id
*/
List<Map> list=JSON.parseArray(specIds, Map.class);
//3.遍历list集合,获取规格选项
for(Map map:list) {
//获取规格id(转为Long,规格选项的id为Long型)
Long specId=new Long((Integer)map.get("id"));
//根据规格id查询规格选项
TbSpecificationOptionExample example=new TbSpecificationOptionExample();
com.pinyougou.pojo.TbSpecificationOptionExample.Criteria c=example.createCriteria();
c.andSpecIdEqualTo(specId);
List<TbSpecificationOption> options=specificationOptionMapper.selectByExample(example);
map.put("specList", options);
}
return list;
}
4.3 保存勾选的规格选项
重点:查找集合中的某一对象,规格选项保存时的几种情况
goods_edit.html页面,每次勾选或者取消勾选规格选项时,执行更新规格属性方法。
<span ng-repeat="option in spec.specList">
<input type="checkbox" ng- click="updateSpecItems($event,spec.text,option.optionName)">{{option.optionName}} </span>
将用户选中的规格选项保存在tb_goods_desc表的specification_items字段中,格式如下:
[{"attributeName":"网络","attributeValue":["移动3G","移动4G"]},{"attributeName":"机身内存","attributeValue":["16G","32G"]}]
保存思路:
例如,勾选了""移动3G",判断entity.specificationItems中是否存在attributeName为"网络""的对象,如果存在,如{"attributeName":"网络","attributeValue":"移动4G"},则在该对象的attributeValue里添加“移动3G”,变为{"attributeName":"网络","attributeValue":["移动3G","移动4G"]};如果不存在,则在entity.specificationItems中新建一个对象:{"attributeName":"网络","attributeValue":"移动3G"}。
当取消勾选了""移动3G",判断entity.specificationItems中是否存在attributeName为"网络""的对象,如果存在,如{"attributeName":"网络","attributeValue":["移动3G","移动4G"]},则在该对象的attributeValue里移除掉“移动3G”,变为{"attributeName":"网络","attributeValue":"移动4G"};如果存在且当移除"移动3G"后,"网络"对应attributeValue为空,则将{"attributeName":"网络","attributeValue":}整条记录移除。
- goodsController.js
- 定义规格选项属性
$scope.entity={goods:{},goodsDesc:{itemImages:[],specificationItems:[]}};
-
根据attributeName在entity.specificationItems中查找对象
如查询attributeName为"网络"的对象,则参数为($scope.entity.goodsDesc.specificationItems, "attributeName", "网络")
$scope.searchObjByKey=function(list,key,keyValue){
for(var i=0;i<list.length;i++){
if(list[i][key]==keyValue){
return list[i];
}
}
return null;
}
- 保存规格选项
//更新选择的规格选项
$scope.updateSpecItems=function($event,name,value){
//获取key名为"attributeName",key值为name的对象
var obj=$scope.searchObjByKey($scope.entity.goodsDesc.specificationItems,'attributeName',name);
if(obj!=null){
//如果已存在key名为"attributeName",key值为name的对象,则在后面添加数据即可
if($event.target.checked){
//勾选
obj.attributeValue.push(value);
}else{
//取消勾选
obj.attributeValue.splice(obj.attributeValue.indexOf(value),1);
//如果该attributeName对应的attributeValue都被取消了,则将此条记录移除
if(obj.attributeValue.length==0){
$scope.entity.goodsDesc.specificationItems.splice($scope.entity.goodsDesc.specificationItems.indexOf(obj),1);
}
}
}else{
//如果不存在,则新建一条 $scope.entity.goodsDesc.specificationItems.push({"attributeName":name,"attributeValue":[value]});
}
}
5.商品录入:sku商品信息
重点:勾选规格选项后,生成sku列表
基于上一步完成的规格选择,根据选择的规格录入商品的SKU信息,当用户选择相应的规格,下面的SKU列表就会自动生成,如下图:
实现思路:
(1)先定义一个初始的不带规格名称只有价格和库存的集合,只有一条记录;
(2)循环用户选择的规格,根据规格名称和已选择的规格选项对原集合进行扩充,添加规格名称和值,新增的记录数与选择的几类规格选项值个数的乘积相同。
生成的顺序如下图:
- goodsController.js
//创建SKU列表
$scope.createSKUlist=function(){
$scope.entity.itemList=[{spec:{},price:0,num:99999,status:'0',isDefault:'0'}];
//初始化SKU列表:规格属性名及值为空
var list=$scope.entity.goodsDesc.specificationItems;//便于以后调用,用户勾选的规格
for(var i=0;i<list.length;i++){
$scope.entity.itemList=addColumn($scope.entity.itemList,list[i].attributeName,list[i].attributeValue);
}
}
//添加列值,返回新的集合。如果方法不在页面调用的话,则不需要加$scope
addColumn=function(oldList,columnName,columnValues){
var newList=[];
for(var i=0;i<oldList.length;i++){
var oldRow=oldList[i];
for(var j=0;j<columnValues.length;j++){
var newRow=JSON.parse(JSON.stringify(oldRow));//深克隆,复制数据,二者互不影响
newRow.spec[columnName]=columnValues[j];
newList.push(newRow);
}
}
return newList;
}
6. 商品录入:是否启用规格
需求:在规格面板添加是否启用规格,当用户没有选择该项,将原来的规格面板和SKU列表隐藏,用户保存商品后只生成一个SKU。
- goodsController.js
//判断规格选项是否勾选
$scope.checkAttributeValue=function(specName,optionName){
var obj=$scope.searchObjByKey($scope.entity.goodsDesc.specificationItems,'attributeName',specName);
if(obj==null){
//如果规格名称为都不存在,则无须再判断规格选项是否勾选
return false;
}else{
if(obj.attributeValue.indexOf(optionName)>=0){
return true;
}else{
return false;
}
}
}
//$scope.searchObjByKey见4.3里的searchObjByKey方法