![](https://i-blog.csdnimg.cn/blog_migrate/860ff3b62751226bb4e1bcc5d66bdf15.png)
需求分析:商家添加商品,如上图样式,如商家添加手机这个商品,我们先查询到手机这个属性的规格选项,及规格 ,当商家选择一个规格和一个规格选项时,我们为其添加一行组成商品数据 SKU ,(规格和规格选项的关系就是,每个规格下面都对应下面所有的规格选项,一行商品数据就是一个商品)
实现步骤:
1.先通过模板ID查询规格,再通过规格ID查询到规格选项,并在页面显示,成选择框样式。
1.通过$watch监控entity.goods.typeTemplateId模板id的变化 调用模板的方法通过模板id查询规格,及规格选项
$scope.$watch(
'entity.goods.typeTemplateId'
,
function
(newValue, oldValue) {
typeTemplateService
.findSpecOptionListByTypeId(newValue).success(
function
(data) {
$scope.specList = data;
});
});
2.在serviceimpl中
//注入规格选项mapper接口代理对象
@Autowired
private TbSpecificationOptionMapper specificationOptionMapper;
/**
* 需求: 查询模版中存储关键规格属性对应规格选项
* 请求: findSpecOptionListByTypeId
* 参数:模版id
* 返回值: List<Map>
*/
public List<Map> findSpecOptionListByTypeId(Long typeId) {
// 根据模版id查询规格属性值
TbTypeTemplate typeTemplate = typeTemplateMapper.selectByPrimaryKey(typeId);
// 从模版中获取规格属性值
String specIds = typeTemplate.getSpecIds();
// [{"id":27,"text":"网络"},{"id":32,"text":"机身内存"}]
// 把规格属性转换为json对象
List<Map> specList = JSON.parseArray(specIds, Map.class);
// 循环规格属性值,根据规格属性id查询规格选项
for (Map map : specList) {
//从规格属性中获取规格id
Integer specId = (Integer)map.get("id");
//创建example对象
TbSpecificationOptionExample example = new TbSpecificationOptionExample();
//创建criteria对象,设置查询参数
com.pyg.pojo.TbSpecificationOptionExample.Criteria createCriteria = example.createCriteria();
//设置外键规格id查询规格选项
createCriteria.andSpecIdEqualTo(specId.longValue());
//查询规格选项值(根据外键查询)
List<TbSpecificationOption> specOptionList = specificationOptionMapper.selectByExample(example);
// 根据数据库里的[{"id":27,"text":"网络","options":[{}{}]},{"id":32,"text":"机身内存","options":[{}{}]}]
//把规格选项封装到map中,存到模板里的规格中
map.put("options", specOptionList);
}
return specList;
}
3.页面显示
<div class="row data-type">
<
div
ng-repeat
=
"spec in specList"
>
<
div
class
=
"col-md-2 title"
>
{{spec.text}}
</
div
>
<
div
class
=
"col-md-10 data"
>
<
span
ng-repeat
=
"option in spec.options"
>//遍历模板里面的规格里存放的规格选项
<
input
type
=
"checkbox"
ng-click
=
"updateSpecAttribute($event,spec.text,option.optionName);createSkuItemList()"
>
{{option.optionName}}
</
span
>
</
div
>
</
div
>
</
div
>
2.更具数据库查看规格选项和规格属性在数据库保存的样式,我们是如下样式,及把规格和规格选项的数据以json保存,attributeName代表规格名,attributeValue代表该规格的规格属性(这是一个数组类型),以对象的方式放在json数组中
[{"attributeName":"网络制式","attributeValue":["移动3G","移动4G"]},{"attributeName":"屏幕尺寸","attributeValue":["6寸","5.5寸"]}]
3.实现,当商家选择一个规格和一个规格选项时,我们为其添加一行组成商品数据 SKU ,(规格和规格选项的关系就是,每个规格下面都对应下面所有的规格选项,一行商品数据就是一个商品)
也就是说使用两个遍历方法,先遍历一个规格,在这个规格中再遍历规格选项,然后深克隆数据添加一行数据
// 定义选中规格属性事件
$scope.updateSpecAttribute = function($event, text, name) {
// 获取实体中规格选项值
// [{"attributeName":"网络","attributeValue":["移动3G"]}]
var specList = $scope.entity.goodsDesc.specificationItems;
// 循环规格选项值
for (var i = 0; i < specList.length; i++) {
// 判断选择的是那个属性
if (specList[i].attributeName == text) {
// 判断是否选中事件
if ($event.target.checked) {
// [{"attributeName":"网络","attributeValue":["移动3G","联通4G"]}]
// 把规格选项推送到规格选项数据结构中
specList[i].attributeValue.push(name);
} else {
// [{"attributeName":"网络","attributeValue":["移动3G"]}]
// 取消事件
specList[i].attributeValue.splice(
specList[i].attributeValue.indexOf(name), 1);
}
return;
}
}
// 如果商品描述中规格属性没值,把选择中值推送到集合中
// 第一次点击规格属性选项值
// [{"attributeName":"网络","attributeValue":["移动3G"]}]
specList.push({
attributeName : text,
attributeValue : [ name ]
});
};
完成单个商品的组合,,
// 定义函数,封装规格选项组合成商品最小销售单元
$scope.createSkuItemList = function() {
// 初始化规格数据组合
$scope.entity.itemList = [ {
spec : {}, //规格属性
price : 999999, //默认库存
stockCount : 0,//默认价格
status : '0',//默认商品状态
idDefault : '0'//默认是否选用
} ];
// 获取选中规格属性值
// [{"attributeName":"网络","attributeValue":["电信2G","联通2G"]},{"attributeName":"机身内存","attributeValue":["16G","64G"]}]
var specList = $scope.entity.goodsDesc.specificationItems;
// 循环规格属性值,组合sku最小销售单元商品数据
for (var i = 0; i < specList.length; i++) {
// 第一次循环:$scope.entity.itemList =
// [{spec:{"网络":"电信2G"},price:999999,stockCount:0,status:'0',idDefault:'0'},{spec:{"网络":"联通2G"},price:999999,stockCount:0,status:'0',idDefault:'0'}]
// 添加一列 调用添加一行方法
$scope.entity.itemList = addColumn($scope.entity.itemList,
specList[i].attributeName, specList[i].attributeValue);
}
};
==================================================================================================
//实现添加一行的数据 方法
addColumn = function(list, name, columnValues) {
//定义一个空数组
var newList = [];
// 第一次循环数据:[{spec:{},price:999999,stockCount:0,status:'0',idDefault:'0'}];
// 第二次循环数据:[{spec:{"网络":"电信2G"},price:999999,stockCount:0,status:'0',idDefault:'0'},{spec:{"网络":"联通2G"},price:999999,stockCount:0,status:'0',idDefault:'0'}]
// 循环list集合数据 2
for (var i = 0; i < list.length; i++) {
// 第一次循环第一个对象:{spec:{},price:999999,stockCount:0,status:'0',idDefault:'0'}
// 第二次循环第一个对象:{spec:{"网络":"电信2G"},price:999999,stockCount:0,status:'0',idDefault:'0'}
// 获取一个旧的对象
var oldRow = list[i];
// 第一次循环:columnValues:["电信2G","联通2G"]
// 第二次循环:columnValues:["16G","64G"]
// 第二个循环
for (var j = 0; j < columnValues.length; j++) {
// 第一次克隆:{spec:{},price:999999,stockCount:0,status:'0',idDefault:'0'}
// 第二次克隆:
// {spec:{"网络":"电信2G"},price:999999,stockCount:0,status:'0',idDefault:'0'}
// 深克隆操作,新创建一行数据
var newRow = JSON.parse(JSON.stringify(oldRow));
// {spec:{"网络":"电信2G",:"机身内存":"4G"},price:999999,stockCount:0,status:'0',idDefault:'0'}
newRow.spec[name] = columnValues[j];
// j:循环第一次:{spec:{"网络":"电信2G"},price:999999,stockCount:0,status:'0',idDefault:'0'}
// j:循环第二次:{spec:{"网络":"联通2G"},price:999999,stockCount:0,status:'0',idDefault:'0'}
// 推送集合 将新创建的一行数据,推送到上面定义的空数组中,并返回到上面的单击事件方法中
newList.push(newRow);
}
}
// [{spec:{"网络":"电信2G"},price:999999,stockCount:0,status:'0',idDefault:'0'},{spec:{"网络":"联通2G"},price:999999,stockCount:0,status:'0',idDefault:'0'}]
return newList;
};
页面显示
<
div
class
=
"row data-type"
>
<
table
class
=
"table table-bordered table-striped table-hover dataTable"
>
<
thead
>
<
tr
>
<!--回显规格及规格选项 -->
<
th
class
=
"sorting"
ng-repeat
=
"spec in entity.goodsDesc.specificationItems"
>
{{spec.attributeName}}
</
th
>
<
th
class
=
"sorting"
>
价格
</
th
>
<
th
class
=
"sorting"
>
库存
</
th
>
<
th
class
=
"sorting"
>
是否启用
</
th
>
<
th
class
=
"sorting"
>
是否默认
</
th
>
</
tr
>
</
thead
>
<
tbody
>
<
tr
ng-repeat="item in entity.itemList"
>
<!-- 遍历单个商品的数据,并通过过个属性回显 -->
<
td
ng-repeat="specName in entity.goodsDesc.specificationItems"
>
{{item.spec[specName.attributeName]}}
</
td
>
<
td
><
input
class
=
"form-control"
ng-model
=
"item.price"
placeholder
=
"价格"
>
</
td
>
<
td
><
input
class
=
"form-control"
ng-model
=
"item.stockCount"
placeholder
=
"库存数量"
>
</
td
>
<
td
><
input
type
=
"checkbox"
ng-model
=
"item.status"
></
td
>
<
td
><
input
type
=
"checkbox"
ng-model
=
"item.isDefault"
ng-true-value
=
"1"
ng-false-value
=
"0"
></
td
>
</
tr
>
</
tbody
>
</
table
>
</
div
>