今日目标:
1.完成商品录入之SKU列表生成
2.运营商的对商品的审核
3.商家对商品的管理
一、商品录入之SKU列表生成
前端js中,json格式的对象,最适合组装动态变化的数据。
tb_item表中spec字段,记录商品特有的规格数据。
spec:{"机身内存":"16G","网络":"联通3G"}
js数组的组装技巧
克隆 分为两种:浅克隆和深克隆
要基于js克隆方式,实现spec对象组装。
浅克隆 var a={name:"zhangsan"} var b=a; 声明变量,重新赋予已经存在的变量。
深克隆 var a='{name:"zhangsan"}' var b={name:"zhangsan"} 深克隆:对象的内容完成相同,但是对象地址值引用不同
深克隆实现方式:
将原有对象,先转化为json格式字符串 '{name:"zhangsan"}' JSON.stringify();
再将json格式字符串转为json对象 {name:"zhangsan"} JSON.parse();
注意我们组装数据要动态显示,所以我们要json数据进行封装
分析:如何实现这种效果,首先我们上次规格选项的点击的基础上,在添加已给方法,createItemList ()这个方法主要是组装我们需要的数据,通过深克隆,实现数据的收集类似于这种:
specList:[{"attributeName":"网络","attributeValue":["移动3G"]},{"attributeName":"机身内存","attributeValue":["16G"]}]
前台代码实现:
//基于数组中对象的值 获取该对象返回
//[{"attributeName":"网络","attributeValue":["移动3G","移动4G"]}]
//list是传入的列表数组 key是attributeName 是根据传入值决定的 value 是对应的值,比如网络
$scope.getObjectByKey = function (list,key,value) {
for (var i=0;i<list.length;i++){
//存在对象时
if (list[i][key]==value){
return list[i];
}
}
//不存在则返回空值
return null;
}
//创建item列表
$scope.createItemList=function () {
//初始化item对象
$scope.entity.itemList=[{spec:{},price:0,num:99999,status:"1",isDefault:"0"}];
//勾选规格结果集
//specList:[{"attributeName":"网络","attributeValue":["移动3G"]},{"attributeName":"机身内存","attributeValue":["16G"]}]
var specList =$scope.entity.tbGoodsDesc.specificationItems;
//如果规格选项全部取消
if(specList.length==0){
$scope.entity.itemList=[];
}
for(var i=0;i<specList.length;i++){
//动态为列表中对象的spec属性赋值方法,动态生成sku列表 行列方法
$scope.entity.itemList=addColumn($scope.entity.itemList,specList[i].attributeName,specList[i].attributeValue);
}
}
addColumn=function (itemList,specName,specOptions) {
var newList=[];
//动态组装itemList列表中的spec对象数据 参考数据示例:{"机身内存":"16G","网络":"联通3G"}
for(var i=0;i<itemList.length;i++){
//获取litmList列表对象
//{spec:{},price:0,num:99999,status:1,isDefault:0}
var item = itemList[i];
//遍历勾选的规格选项数组
for(var j=0;j<specOptions.length;j++){
//基于深克隆实现构建item对象操作
var newItem = JSON.parse(JSON.stringify(item));
newItem.spec[specName]=specOptions[j];
newList.push(newItem);
}
}
return newList;
}
保存的后台实现:
我们上次已经实现了goods表,goodsDesc表,然后我们这次完成组装tb_item表
//组装tb_item表
List<TbItem> items = goods.getItems();
for (TbItem item : items) {
/*后台组装
`title` varchar(100) NOT NULL COMMENT '商品标题', // 商品名称(SPU名称)+ 商品规格选项名称 中间以空格隔开
`image` varchar(2000) DEFAULT NULL COMMENT '商品图片', // 从 tb_goods_desc item_images中获取第一张
`categoryId` bigint(10) NOT NULL COMMENT '所属类目,叶子类目', //三级分类id
`create_time` datetime NOT NULL COMMENT '创建时间',
`update_time` datetime NOT NULL COMMENT '更新时间',
`goods_id` bigint(20) DEFAULT NULL,
`seller_id` varchar(30) DEFAULT NULL,
//以下字段作用:
`category` varchar(200) DEFAULT NULL, //三级分类名称
`brand` varchar(100) DEFAULT NULL,//品牌名称
`seller` varchar(200) DEFAULT NULL,//商家店铺名称*/
String title = tbGoods.getGoodsName();
//{"机身内存":"16G","网络":"联通3G"}
String spec = item.getSpec();
Map<String,String> specMap = JSON.parseObject(spec,Map.class);
for (String s : specMap.keySet()) {
title+=" "+specMap.get(s);
}
item.setTitle(title);
//image数据组装
String itemImages = tbGoodsDesc.getItemImages();
List<Map> imageList = JSON.parseArray(itemImages,Map.class);
//image数据组装
//[{"color":"红色","url":"http://192.168.25.133/group1/M00/00/01/wKgZhVmHINKADo__AAjlKdWCzvg874.jpg"},
// {"color":"黑色","url":"http://192.168.25.133/group1/M00/00/01/wKgZhVmHINyAQAXHAAgawLS1G5Y136.jpg"}]
if (imageList!=null&&imageList.size()>0){
String image = (String) imageList.get(0).get("url");
item.setImage(image);
}
//三级分类id
item.setCategoryid(tbGoods.getCategory1Id());
//时间设置
item.setCreateTime(new Date());
item.setUpdateTime(new Date());
//goods_id
item.setGoodsId(tbGoods.getId());
// selller_id
item.setSellerId(tbGoods.getSellerId());
//三级分类名称
//注入三个mappper
TbItemCat tbItemCat = itemCatMapper.selectByPrimaryKey(tbGoods.getCategory3Id());
item.setCategory(tbItemCat.getName());
TbBrand tbBrand = brandMapper.selectByPrimaryKey(tbGoods.getBrandId());
item.setBrand(tbBrand.getName());
TbSeller tbSeller = sellerMapper.selectByPrimaryKey(tbGoods.getSellerId());
item.setSeller(tbSeller.getNickName());
itemMapper.insert(item);
}
3.完成规格的启用
主要适用一个新的angularjs表达式来体现
is_enable_spec=0 不启用规格
is_enable_spec=1 启用规格
业务:库存业务。商品销售不受库存影响。可以稍微延迟发货时间,商家赶紧去补货即可。
注意,后台代码:不开启规格,那么页面的数据无法提交,我们就要后台自己组装数据,通过if判断是否启用规格,我们将公共的能提交的代码封装起来
代码:
} else {
//为不启用规格
TbItem item = new TbItem();
item.setTitle(tbGoods.getGoodsName());
setItemValue(tbGoods, tbGoodsDesc, item);
/*为启用规格时,组装页面需要提交的数据
`spec` varchar(200) DEFAULT NULL,
`price` decimal(20,2) NOT NULL COMMENT '商品价格,单位为:元',
`num` int(10) NOT NULL COMMENT '库存数量',
`status` varchar(1) NOT NULL COMMENT '商品状态,1-正常,2-下架,3-删除',
`is_default` varchar(1) DEFAULT NULL,*/
item.setSpec("{}");
item.setPrice(tbGoods.getPrice());
item.setNum(9999);
item.setStatus("1");
item.setIsDefault("1");
itemMapper.insert(item);
}
}
//抽取item工具的方法
private void setItemValue(TbGoods tbGoods, TbGoodsDesc tbGoodsDesc, TbItem item) {
//image数据组装
String itemImages = tbGoodsDesc.getItemImages();
List<Map> imageList = JSON.parseArray(itemImages, Map.class);
//image数据组装
//[{"color":"红色","url":"http://192.168.25.133/group1/M00/00/01/wKgZhVmHINKADo__AAjlKdWCzvg874.jpg"},
// {"color":"黑色","url":"http://192.168.25.133/group1/M00/00/01/wKgZhVmHINyAQAXHAAgawLS1G5Y136.jpg"}]
if (imageList != null && imageList.size() > 0) {
String image = (String) imageList.get(0).get("url");
item.setImage(image);
}
//三级分类id
item.setCategoryid(tbGoods.getCategory1Id());
//时间设置
item.setCreateTime(new Date());
item.setUpdateTime(new Date());
//goods_id
item.setGoodsId(tbGoods.getId());
// selller_id
item.setSellerId(tbGoods.getSellerId());
//三级分类名称
//注入三个mappper
TbItemCat tbItemCat = itemCatMapper.selectByPrimaryKey(tbGoods.getCategory3Id());
item.setCategory(tbItemCat.getName());
TbBrand tbBrand = brandMapper.selectByPrimaryKey(tbGoods.getBrandId());
item.setBrand(tbBrand.getName());
TbSeller tbSeller = sellerMapper.selectByPrimaryKey(tbGoods.getSellerId());
item.setSeller(tbSeller.getNickName());
}
效果:
二、运营商的对商品的审核
1.运营商的列表展示
思路:和商家一样,包括字段也是一样的,所以直接复制就行
2.列表的批量审核
后台实现:
//批量审核
@Override
public void deleteStatus(Long[] ids, String status) {
for (Long id : ids) {
TbGoods tbGoods = goodsMapper.selectByPrimaryKey(id);
tbGoods.setAuditStatus(status);
goodsMapper.updateByPrimaryKey(tbGoods);
}
}
前台实现:
service层
//批量审核
this.updateStatus=function(ids,status){
return $http.get('../goods/updateStatus.do?ids='+ids+"&status="+status);
}
controller层
//批量审核
$scope.updateStatus=function(status){
//获取选中的复选框
goodsService.updateStatus( $scope.selectIds ,status).success(
function(response){
if(response.success){
$scope.reloadList();//刷新列表
$scope.selectIds=[];//注意清空
}
}
);
}
3.批量删除功能的实现
思路:和上面的实现思路也是一样的,在service中也是先查,在设置,后跟新,因为删除的是逻辑的删除,所以我们执行更新就行
逻辑删除
更新is_delete字段,默认为null时,未删除商品,删除时,需要将is_delete设置为1
效果:
三、商家对商品的管理
1.完成商品的展示
思路:修改search方法,通过条件查询,商家的id查询,注意修改 条件查询的值为等值查询而不是模糊查询
2.修改商品审核状态
0 未审核 1 已审核 2 审核未通过 3 关闭
['未审核','已审核','审核未通过','关闭']
//定义商品状态的数组
$scope.status=['未审核','已审核','审核未通过','关闭'];
<span>
{{status[pojo.auditStatus]}}
</span>
3.
商家后台查询未审核商品列表
商品列表中展示分类名称实现方式:
1、后台组装数据,根据分类id查询分类名称,返回前台展示页面。 缺点:性能较差
2、将商品分类列表数据一次性加载到页面。将分类id作为分类列表索引值,将分类名称作为该索引位置的内容。 缺点:消耗浏览器存储空间
1 2
时间和空间 成本。
代码:
//定义查询所有分类的方法
//注意初始化分类列表
$scope.itemCatList=[];
$scope.selectItemList=function () {
itemCatService.findAll().success(function (response) {
/* ["","手机","电脑" ...]*/
//定义记录分类列表的数据
for(var i = 0;i<response.length;i++){
//分类对象
$scope.itemCatList[response[i].id]=response[i].name;
}
})
}
页面展示:
<td>{{itemCatList[pojo.category1Id]}}</td>
<td>{{itemCatList[pojo.category2Id]}}</td>
<td>{{itemCatList[pojo.category3Id]}}</td>
注意:在页面刚加载的时候就进行初始化ng-init="selectItemList()
4.商品的上下架
思路:也是跟新一个字段id_marketable 0 为下架 1为上架
is_marketable=1 上架
is_marketable=0 下架
注意:审核通过的商品才能上下架
后台代码:
/**
* 批量上下架
* @param ids
* @return
*/
@RequestMapping("/updateIsMarketable")
public Result updateIsMarketable(Long [] ids,String isMarketable){
try {
goodsService.updateIsMarketable(ids,isMarketable);
return new Result(true, "上下架成功");
}
catch (RuntimeException e) {
e.printStackTrace();
return new Result(false,e.getMessage());
}catch (Exception e){
return new Result(false, "上下架失败");
}
}
service层
@Override
public void updateIsMarketable(Long[] ids, String isMarketable) {
for (Long id : ids) {
TbGoods tbGoods = goodsMapper.selectByPrimaryKey(id);
//只有审核通过的才能上下架
if ("1".equals(tbGoods.getAuditStatus())){
tbGoods.setIsMarketable(isMarketable);
goodsMapper.updateByPrimaryKey(tbGoods);
}else{
throw new RuntimeException("只有审核通过的才能上下架");
}
}
}
前台代码:
controller层
//定义商品的上下架
$scope.isMarketable=['下架','上架'];
//批量上下架
$scope.updateIsMarketable=function(isMarketable){
//获取选中的复选框
goodsService.updateIsMarketable( $scope.selectIds,isMarketable ).success(
function(response){
if(response.success){
$scope.reloadList();//刷新列表
$scope.selectIds=[];//清空记录id的数组
}else{
alert(response.message);
}
}
);
}
service层
//批量上下架
this.updateIsMarketable=function(ids,isMarketable){
return $http.get('../goods/updateIsMarketable.do?ids='+ids+"&isMarketable="+isMarketable);
}
效果:
四、常见错误
1.变量初始化问题
这个就是定义了方法,而没有初始化变量
//注意初始化分类列表
$scope.itemCatList=[];
五、总结
js对象数据组装技巧:
克隆
要基于js克隆方式,实现spec对象组装。
浅克隆 var a={name:"zhangsan"} var b=a; 声明变量,重新赋予已经存在的变量。
深克隆 var a='{name:"zhangsan"}' var b={name:"zhangsan"} 深克隆:对象的内容完成相同,但是对象地址值引用不同
深克隆实现方式:
将原有对象,先转化为json格式字符串 '{name:"zhangsan"}' JSON.stringify();
再将json格式字符串转为json对象 {name:"zhangsan"} JSON.parse();
item中status=1时,代表 启用, status=0时,代表未启用
item中isDefault=1时,代表 是默认商品, isDefault=0时,代表非默认商品
angularjs的指令
ng-true-value="1" ng-false-value="0"