电商项目日总结(第七天)

商品新增之商品图片和规格的新增

1.完成了上传图片文件到FastDFS服务器上

准备工作:将老师给的带有FastDFS的Linux镜像安装到了虚拟机上

在pyg_parent父模块下建立一个子模块pyg_common(工具类模块),在这个模块中新建一个util目录,写一个文件上传的工具类到上面:

因为在商家页面添加商品时需要上传图片,所以在pyg_shop_web的pom文件中添加pyg_common的依赖,在springmvc.xml中配置多媒体解析器,并在resources目录下的config的目录下拷贝fdfs_client.conf配置文件,并在application.properties文件下添加相应内容

代码部分:

创建一个UploadController.java

@RestController
public class UploadController {
    //获取文件服务器地址
    @Value("${FILE_SERVER_URL}")
    private String file_url;

    @RequestMapping("/upload")
    public Result upload(MultipartFile multipartFile) {
        //1.取文件扩展名
        String originalFilename = multipartFile.getOriginalFilename();
        System.out.println("============================");
        System.out.println("originalFilename:"+originalFilename);
        String extName = originalFilename.substring(originalFilename.lastIndexOf(".") + 1);
        System.out.println("exName:"+extName);
        //2.创建FastDFS客户端(用我们的工具类)
        FastDFSClient fastDFSClient = null;
        try {
            fastDFSClient = new FastDFSClient("classpath:config/fdfs_client.conf");
            //3.客户端上传图片后,将获取的路径拼接全路径后
            String path = fastDFSClient.uploadFile(multipartFile.getBytes(), extName);
            System.out.println("path:"+path);
            String url = file_url + path;
            //4.进行Result返回,success的时候返回图片路径给页面
            return new Result(true,url);
        } catch (Exception e) {
            e.printStackTrace();
            return new Result(false,"文件上传失败");
        }
    }
}

创建一个uploadService.js文件

app.service('uploadService',function ($http) {
    this.uploadFile = function() {
        var formData = new FormData(); //上传文件的数据模型
        formData.append("multipartFile", file.files[0]); //文件上传框的id必须是和append的第一个参数一致
        return $http({
            method : 'post',
            url : "../upload.do",
            data : formData,
            headers : {'Content-Type' : undefined}, //上传文件必须是这个类型,默认text/plain
            transformRequest : angular.identity  //对整个表单进行二进制序列化
        });
    }
})

goodsController.js中,别忘了参数部分引入uploadService

$scope.entity_image = {};
    //跨服务器上传图片
    $scope.uploadFile = function () {
        uploadService.uploadFile().success(
            function (response) {
                if (response.success) {
                    //数据库中的数据
                    //[{"color":"黄色","url":"http://192.168.25.133/group1/M00/00/00/wKgZhVrAnfuABpS9AABtBwqnSTg963.jpg"},
                    // {"color":"金黄色","url":"http://192.168.25.133/group1/M00/00/00/wKgZhVrFXJWAZ7DUAACQQzLtwW0606.jpg"}]
                    $scope.entity_image.url = response.message;
                } else {
                    alert(response.message);
                }
            }
        )
    }

    //将图片保存到entity.tbGoodsDesc这个对象的itemImages的属性中去,前提是把这个对象初始化(在上面)
    $scope.addImage = function () {
        $scope.entity.tbGoodsDesc.itemImages.push($scope.entity_image)
    }

    //将图片从entity.tbGoodsDesc这个对象的itemImages的属性中删除出去
    $scope.deleImage = function ($index) {
        $scope.entity.tbGoodsDesc.itemImages.splice($index, 1);
    }

goods_edit.html页面部分,绑定上图goodsController.js中对应的方法

这样点击上传按钮,先去找tracker,然后tracker会告诉你哪个storage服务器空闲,可以存放文件,然后你再去访问对应的storage,并上传图片,文件就会上传到图片服务器上(fastdfs跨服务器上传文件成功后会返回一个id,当你在去访问这个图片的时候就拿着id去找,把id给tracker让他去找在storage里具体哪个服务器里)

2.实现了商品对应模板的所有规格和规格选项的展示

goodsController.js的监听模板id变化的$watch方法中调用typeTemplateService中的findSpecList方法

//根据模板id的变化去模板表里找对应的所有品牌(type_template表里所有的brandIds)
    $scope.$watch('entity.tbGoods.typeTemplateId', function (newValue, oldValue) {
        typeTemplateService.findOne(newValue).success(
            function (response) {
                $scope.brandList = JSON.parse(response.brandIds);
                //根据模板id的变化去模板表里找对应的所有扩展属性(type_template表里所有的customAttributeItems)
                $scope.entity.tbGoodsDesc.customAttributeItems = JSON.parse(response.customAttributeItems)
            }
        )

        //根据模板id的变化去规格表里去找对应的所有规格和规格对应的所有选项
        typeTemplateService.findSpecList(newValue).success(
            function (response) {
                //将返回来的所有规格和规格对应的所有选项构成的list集合
                $scope.specList = response;
            }
        )

        //别忘了初始化entity这个对象中的tbItemList这个集合属性(最后页面上就多显示了除了规格选项后面的部分,价格,库存,是否启用,是否默认这四个)
        $scope.entity.tbItemList = [];
    })

typeTemplateService.js中:

//查找模板中所有的规格findSpecList
	this.findSpecList=function (id) {
		return $http.get('../typeTemplate/findSpecList.do?id='+id);
    }

TypeTemplateController.java(略)

TyepTemplateSerivceImpl.java中:

//查找模板id对应下的所有规格和规格对应的所有规格选项(因要要根据模板id查对应所有规格,所以,就在模板的
	//实现接口下写逻辑
	@Override
	public List<Map> findSpecList(Long id) {
		TbTypeTemplate tbTypeTemplate = typeTemplateMapper.selectByPrimaryKey(id);
		//把每一个规格封装成了map类型,所有的规格构成了list集合
		List<Map> maps = JSON.parseArray(tbTypeTemplate.getSpecIds(), Map.class);
		//遍历每一个规格,并获得规格下面所有的规格选项
		for (Map map : maps) {
			TbSpecificationOptionExample example = new TbSpecificationOptionExample();

			example.createCriteria().andSpecIdEqualTo(new Long((Integer)map.get("id")));//这里类型转换容易出现错误
			List<TbSpecificationOption> options = specificationOptionMapper.selectByExample(example);
			map.put("options",options);
		}
		return maps;
	}

goods_edit.html页面:

<!--遍历每一个规格-->
		                                <div ng-repeat="specification in specList">
			                                <div class="col-md-2 title">{{specification.text}}</div>
					                        <div class="col-md-10 data">
					                               <!--遍历每一个规格选项-->
					                            <span ng-repeat="option in specification.options">
					                            	<input ng-click="updateSpecAttribute($event,specification.text,option.optionName);createItemList()"  type="checkbox" >{{option.optionName}}
					                            </span>

					                        </div>
		                                </div>

3.实现了点击规格选项页面下方能动态的显示SKU商品的列表(全是前端部分的逻辑,不涉及后端)

goods_edit.html页面:给规格选项绑定点击事件

<!--遍历每一个规格-->
		                                <div ng-repeat="specification in specList">
			                                <div class="col-md-2 title">{{specification.text}}</div>
					                        <div class="col-md-10 data">
					                               <!--遍历每一个规格选项-->
					                            <span ng-repeat="option in specification.options">
					                            	<input ng-click="updateSpecAttribute($event,specification.text,option.optionName);createItemList()"  type="checkbox" >{{option.optionName}}
					                            </span>

					                        </div>
		                                </div>

goodsController.js中:

//以下两个方法实现点击规格选项能添加到$scope.entity.tbGoodsDesc.specificationItems这个集合中去/
    //提供一个方法,判断集合中是否存在key的方法
    searchObjectByKey = function (list, key, value) {
        //报错length is not defind 原因是找不到list对象,而list对象就是$scope.entity.tbGoodsDesc.specificationItems,因为没有给他初始化
        for (var i = 0; i < list.length; i++) {
            if (list[i][key] == value) {
                return list[i]
            }
        }
        return null;
    }
    //增加对当前规格集合增加内容的方法,需要判断是新增还是追加
    $scope.updateSpecAttribute = function ($event, name, value) {
        //先查询当前的集合中是否已经有当前的name了
        var object = searchObjectByKey($scope.entity.tbGoodsDesc.specificationItems, 'attributeName', name)
        if (object != null) {
            //如果点击的规格选项被勾选,那么就进行追加
            if ($event.target.checked) {
                object.attributeValue.push(value);
            } else {//如果点击为取消勾选
                object.attributeValue.splice(object.attributeValue.indexOf(value), 1);//移出规格选项
                //如果把该规格的规格选项都移出了,规格选项长度为0的化,那么将词条记录移除
                if (object.attributeValue.length == 0) {
                    $scope.entity.tbGoodsDesc.specificationItems.splice(
                        $scope.entity.tbGoodsDesc.specificationItems.indexOf(object), 1)
                }
            }
        } else {
            $scope.entity.tbGoodsDesc.specificationItems.push({
                "attributeName": name,
                "attributeValue": [value]
            });
        }
    }
//以下两个方法实现sku列表的显示/
    //初始化Goods类中的List<TbItem>集合
    $scope.entity.tbItemList = [{spec: {}, price: 0, num: 99999, status: '0', isDefault: '0'}];
    //循环$scope.entity.goodsDesc.specificationItems的内容,attributeName和attributeValue
    //再通过addColumn = function(list, columnName, conlumnValues)深克隆每一行 {"spec":{"网络":"移动3G"}的内容
    $scope.createItemList = function () {
        $scope.entity.tbItemList = [{spec: {}, price: 0, num: 99999, status: '0', isDefault: '0'}];// 初始
        var items = $scope.entity.tbGoodsDesc.specificationItems;
        for (var i = 0; i < items.length; i++) {
            $scope.entity.tbItemList = addColumn($scope.entity.tbItemList,
                items[i].attributeName, items[i].attributeValue);
        }
    }
    // 添加列值:参数1是创建的itemList集合,参数2是规格名称,参数3是规格值的集合
    addColumn = function (list, columnName, conlumnValues) {
        var newList = [];// 新的集合
        for (var i = 0; i < list.length; i++) {
            var oldRow = list[i];  //获取出当前行的内容 {spec:{},price:'0.01',num:'99999',status:'0',isDefault:'0'}
            for (var j = 0; j < conlumnValues.length; j++) {//循环attributeValue数组的内容
                var newRow = JSON.parse(JSON.stringify(oldRow));// 深克隆,根据attributeValue的数量
                newRow.spec[columnName] = conlumnValues[j];//{spec:{"网络制式":"移动4G"},price:'0.01',num:'99999',status:'0',isDefault:'0'}
                newList.push(newRow);
            }
        }
        return newList;
    }

goods_edit.html页面:SKU商品列表的动态展示

 <table class="table table-bordered table-striped table-hover dataTable">
    <thead>
        <tr>
            <!--三层循环之第一层-->
		    <th ng-repeat="spec in entity.tbGoodsDesc.specificationItems" class="sorting">{{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.tbItemList">
          <!--三层循环之第三层-->
            <td ng-repeat="specification in entity.tbGoodsDesc.specificationItems">
            	{{item.spec[specification.attributeName]}}
            </td>
            <td>
           		<input ng-model="item.price" class="form-control"  placeholder="价格">
            </td>
            <td>
            	<input ng-model="item.num" class="form-control" placeholder="库存数量">
            </td>
            <td>
             	<input ng-model="item.status" ng-true-value="1" ng-false-value="0" type="checkbox" >
            </td>
            <td>
                <input ng-model="item.isDefault" ng-true-value="1" ng-false-value="0" type="checkbox" >
            </td>
      </tr>
	  
    </tbody>
</table>

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值