品优购项目记录:day06

36 篇文章 0 订阅
19 篇文章 1 订阅

今日目标:

        (1)完成选择商品分类

        (2)完成品牌选择功能

        (3)完成扩展属性录入

        (4)完成规格选择功能

        (5)完成SKU商品信息功能

        (6)完成是否启用规格

 

目录

1、商品录入[2]

1.1 商品分类选择

1.2 品牌选择

1.3 扩展属性录入

1.4 规格选择

1.5 SKU商品信息(重点理解逻辑)


 

1、商品录入[2]

 

 

1.1 商品分类选择

(1)复制 ItemCat相关控制层类,itemCatService.js 到 shop-web中

 

(2)在goodsController.js 中引入 itemCatService,并在页面引入itemCatService.js文件

 

(3)编写goodsController.js,新增方法

    // 展示一级下拉列表
    $scope.selectItemCat1List = function () {
        itemCatService.findByParentId(0).success(
            function (rtn) {
                $scope.itemCat1List = rtn;
            }
        );
    }
    
    // 关联展示二级下拉列表
    $scope.$watch('entity.goods.category1Id',function (newValue,oldValue) {
        // alert(newValue);
        itemCatService.findByParentId(newValue).success(
            function (rtn) {
                $scope.itemCat2List = rtn;
            }
        );
    });

    // 关联展示三级下拉列表
    $scope.$watch('entity.goods.category2Id',function (newValue,oldValue) {
        // alert(newValue);
        itemCatService.findByParentId(newValue).success(
            function (rtn) {
                $scope.itemCat3List = rtn;
            }
        );
    });

    // 关联展示模板id
    $scope.$watch('entity.goods.category3Id',function (newValue,oldValue) {
        // alert(newValue);
        itemCatService.findOne(newValue).success(
            function (rtn) {
                $scope.entity.goods.typeTemplateId = rtn.typeId;
            }
        );
    });

 

 

 

 

(4)为下拉框绑定变量,使用ng-options指令加载数据

 

(5)为模板ID绑定变量

 

(6)效果

 

 

 

 

1.2 品牌选择

 

(1)将typeTemplate控制层,以及typeTemplateService.js复制到shop-web下

 

(2)在goodsController.js 中引入 typeTemplateService,并在页面引入typeTemplateService.js文件

 

(3)编写goodsController.js,新增方法

    // 关联加载品牌下拉列表
    $scope.$watch('entity.goods.typeTemplateId',function (newValue,oldValue) {
        // alert(newValue);
        typeTemplateService.findOne(newValue).success(
            function (rtn) {
                $scope.typeTemplate = rtn;
                // 将字符串转换为json对象
                $scope.typeTemplate.brandIds = JSON.parse($scope.typeTemplate.brandIds);
            }
        );
    });

 

(4)品牌下拉框绑定变量

 

(5)效果:

 

 

1.3 扩展属性录入

(1)改造goodsController.js的监控typeTemplateId的方法

 

(2)页面绑定变量

 

 

 

1.4 规格选择

(1)后端:服务层接口,TypeTemplateService(sellergoods-interface)

	/**
	 * 获取规格列表
	 *
	 * @param id 模板id
	 * @return java.util.List<java.util.Map>
	 */
	List<Map> findSpecList(Long id);

 

(2)后端:服务层实现,TypeTemplateServiceImpl(sellergoods-service)

    @Override
    public List<Map> findSpecList(Long id) {
        // 根据模板id查询模板
        TbTypeTemplate typeTemplate = typeTemplateMapper.selectByPrimaryKey(id);
        // 将SpecIds转换为集合
        List<Map> list = JSON.parseArray(typeTemplate.getSpecIds(), Map.class);
        // 遍历集合
        for (Map m : list) {
            // 查询对应ID的规格选项列表
            TbSpecificationOptionExample example = new TbSpecificationOptionExample();
            example.createCriteria().andSpecIdEqualTo(new Long(String.valueOf(m.get("id"))));
            List<TbSpecificationOption> options = specificationOptionMapper.selectByExample(example);

            // 将options 放入map中
            m.put("options", options);
        }

        return list;
    }

 

(3)后端:控制层,TypeTemplateController(shop-web)

    @RequestMapping("/findSpecList")
    public List<Map> findSpecList(Long id) {
        return typeTemplateService.findSpecList(id);
    }

 

(4)前端:编写typeTemplateService.js,新增方法

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

 

(5)前端:修改goodsController.js

 

(6)前端:编写baseController.js,新增方法

	// 在list集合中查询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;
    }

 

(7)前端:编写goodsController.js

    // 更新specificationItems集合
    $scope.updateSpecAttribute = function ($event, name, value) {
        var object = $scope.searchObjectByKey($scope.entity.goodsDesc.specificationItems, 'attributeName', name);
        // 判断是否存在该key的值
        if (object == null) {//不存在
            // 新增
            $scope.entity.goodsDesc.specificationItems.push({"attributeName": name, "attributeValue": [value]})
        } else {// 存在
            if ($event.target.checked) {//勾选
                // 追加
                object.attributeValue.push(value);
            } else {// 取消勾选
                if(object.attributeValue.length > 1) {
                    object.attributeValue.splice(object.attributeValue.indexOf(value),1);
                } else {
                    var index = $scope.entity.goodsDesc.specificationItems.indexOf(object);
                    $scope.entity.goodsDesc.specificationItems.splice(index,1);
                }
            }

        }
    }

注意初始化specificationItems:

 

 

 

(8)前端:页面绑定变量,展示规格列表

 

 

 

1.5 SKU商品信息(重点理解逻辑)

(1)前端:编写goodsController.js

    // 构建SKU商品列表
    $scope.createItemList = function () {
        // 初始化SKU商品列表
        $scope.entity.itemList = [{spec: {}, price: 0, num: 9999, status: '0', isDefault: '0'}];
        var specificationItems = $scope.entity.goodsDesc.specificationItems;

        for (var i = 0; i < specificationItems.length; i++) {
            // 用新生成的列表,覆盖久的列表
            $scope.entity.itemList = addColumn($scope.entity.itemList,specificationItems[i].attributeName,specificationItems[i].attributeValue);
        }
    }

    /**
     * 生成SKU列表的方法
     *
     * @param list          原集合
     * @param columnName    新生成列的列名
     * @param columnValues  新生成列的值列表
     * @return SKU列表
     */
    addColumn = function (list, columnName, columnValues) {
        var SKUList = [];
        for (var i = 0; i< list.length; i++) {
            // 取出当前集合中的行
            var oldRow = list[i];
            for (var j = 0; j < columnValues.length; j++) {
                // 对当前行对象进行深克隆
                var newRow = JSON.parse(JSON.stringify(oldRow));
                // 将值,追加到新增行
                newRow.spec[columnName] = columnValues[j];
                // 将新的行对象,添加到要SKU列表中
                SKUList.push(newRow);
            }
        }
        return SKUList;
    }

 

(2)前端:复选框绑定单击事件

 

(3)前端:绑定变量

 

(4)效果:

 

(5)是否启用规格

 

(6)后端:服务层实现,修改add方法

    /**
     * 增加
     */
    @Override
    public void add(Goods goods) {
        /***************************
         * 保存商品基本信息到goods表 *
         **************************/
        // 补全商品基本信息
        TbGoods tbGoods = goods.getGoods();
        tbGoods.setAuditStatus(TbGoods.STATUS_CREATE);
        // 保存商品基本信息
        goodsMapper.insert(tbGoods);


        /*******************************
         * 保存商品扩展信息到goodsdesc表 *
         *******************************/
        // 补全商品扩展信息数据
        TbGoodsDesc tbGoodsDesc = goods.getGoodsDesc();
        tbGoodsDesc.setGoodsId(tbGoods.getId());
        // 保存商品扩展信息
        goodsDescMapper.insert(tbGoodsDesc);


        /*******************************
         *   保存SKU商品信息到 item表    *
         *******************************/
        saveItemList(goods, tbGoods, tbGoodsDesc);


    }

    /**
     * 保存SKU商品信息
     *
     * @param goods       组合商品对象
     * @param tbGoods     商品基本信息对象
     * @param tbGoodsDesc 商品扩展信息对象
     */
    private void saveItemList(Goods goods, TbGoods tbGoods, TbGoodsDesc tbGoodsDesc) {
        // 判断是否启用规格
        if (tbGoods.getIsEnableSpec().equals(TbGoods.ISENABLESPEC_YES)) {// 启用规格
            // 遍历itemList,补全数据并保存
            for (TbItem item : goods.getItemList()) {
                // 设置标题
                item.setTitle(builderTitle(tbGoods, item).toString());
                // 补全其他数据
                setValues(tbGoods, tbGoodsDesc, item);

                // 保存SKU商品信息
                itemMapper.insert(item);
            }
        } else {// 未启用规格
            TbItem item = new TbItem();
            // 设置标题,直接为商品名称
            item.setTitle(tbGoods.getGoodsName());
            // 补全其他数据
            setValues(tbGoods, tbGoodsDesc, item);

            // 保存SKU商品信息
            itemMapper.insert(item);
        }

    }

    /**
     * 补全item数据
     *
     * @param tbGoods     当前保存的商品
     * @param tbGoodsDesc 商品的扩展信息
     * @param item        SKU商品对象
     */
    private void setValues(TbGoods tbGoods, TbGoodsDesc tbGoodsDesc, TbItem item) {
        // 设置商品分类ID
        item.setCategoryid(tbGoods.getCategory3Id());
        // 设置创建日期和更新日期
        item.setCreateTime(new Date());
        item.setUpdateTime(new Date());
        // 设置商品ID
        item.setGoodsId(tbGoods.getId());
        // 设置商家ID
        item.setSeller(tbGoods.getSellerId());
        // 设置商品分类名称
        TbItemCat itemCat = itemCatMapper.selectByPrimaryKey(tbGoods.getCategory3Id());
        item.setCategory(itemCat.getName());
        // 设置品牌名称
        TbBrand brand = brandMapper.selectByPrimaryKey(tbGoods.getBrandId());
        item.setBrand(brand.getName());
        // 设置商家名称(店铺名)
        TbSeller seller = sellerMapper.selectByPrimaryKey(tbGoods.getSellerId());
        item.setSeller(seller.getNickName());
        // 设置图片
        List<Map> mapList = JSON.parseArray(tbGoodsDesc.getItemImages(), Map.class);
        if (mapList.size() > 0) {
            item.setImage(String.valueOf(mapList.get(0).get("url")));
        }
    }


    /**
     * 构造SKU商品信息的标题
     *
     * @param tbGoods 当前保存的商品
     * @param item    SKU商品对象
     * @return java.lang.StringBuilder
     */
    private StringBuilder builderTitle(TbGoods tbGoods, TbItem item) {
        // 使用tbGoods和规格选项构造SKU名称
        StringBuilder stringBuilder = new StringBuilder(tbGoods.getGoodsName());
        Map<String, Object> spec = JSON.parseObject(item.getSpec());
        for (String key : spec.keySet()) {
            stringBuilder.append(spec.get(key));
        }
        return stringBuilder;
    }

注意:其中保存SKU商品信息列表时,逻辑较多,所以我对代码进行了提取到单独的方法,若是后期逻辑有变动,修改起来更加的方便。

 

 

 

 

 

1.2. 结构化一下 1.3. 图形化一下 1.3.1. 运营商后台 1.3.2. 商家后台 1.3.3. 网页前台 参考京东 2. 技术选型 前端:angularJS + Bootstrap 后台:SSM( springmvc+spring+mybatis) 数据库:mysql,使用mycat读写分离 开发模式:SOA 服务中间件:dubbox,需要和zookeeper配合使用 注册中心:zookeeper 消息中间件:Activemq,使用spring-jms 负载均衡:nginx 搜索:solr集群(solrCloud),配合zookeeper搭建, 使用spring-data-solor 缓存:redis集群,使用spring-data-redis 图片存储:fastDFS集群 网页静态化:freemarker 单点登录:cas 权限管理:SpringSecurity, 跨域:cros 支付:微信扫描 短信验证:阿里大于 密码加密:BCrypt 富文本:KindEditor 事务:声明式事务 任务调度:spring task 所有的技术,都可能涉及到为什么用?怎么用?用的过程中有什么问题? 3. 框架搭建 3.1. 前端 理解baseControler.js、base.js、base_pagination.js,以及每一个xxxController.js里面都公共的做了些什么。 baseControler.js 分页配置 列表刷新 处理checkBox勾选 xxxControler.js 自动生成增删改查 base_pagination.js 带分页 base.js 不带分页 3.2. dao 使用了mybatis逆向工程 4. 模块开发 逐个模块开发就好 4.1. 学会评估模块难不难 一个模块难不难从几方面考虑。 涉及几张表? 1,2张表的操作还是没有什么难度的。 涉及哪些功能? 增删改查,批量删除。 前端展示? 分页列表、树形、面包屑、三级联动、内容格式化。 4.2. 举几个简单模块的例子 4.2.1. 品牌管理 单表 分页、新增、删除、修改 4.2.2. 规格管理 2张表 分页、新增、删除、修改、显示优化(显示列表内容的一部分) 4.2.3. 模板管理 2张表 分页、新增、删除、修改、显示优化(显示列表内容的一部分) 4.2.4. 分类管理 单表 4.2.5. 商家审核 单表 4.3. 举一个复杂模块 4.3.1. 商品新增 需要插入3张表,tb_goods、tb_goods_desc、tb_item 前端:三级联动、富文本、图片上传、动态生成内容 4.3.2. 商品修改 需要从3张表获取数据,然后进行回显。 4.4. 典型模块设计 4.4.1. 管理后台 商品新增、商品修改 4.4.2. 前台页面 搜索模块实现 购物车模块实现 支付模块实现 秒杀模块实现 5. 开发过程中问题&优化 1.1. 登录 单点登录怎么实现 session怎么共享 1.2. 缓存 哪些场景需要用到redis redis存储格式的选择 怎么提高redis缓存利用率 缓存如何同步 1.3. 图片上传 图片怎么存储 图片怎么上传 1.4. 搜索 ​ 怎么实现 数据量大、 并发量高的搜索 怎么分词 1.5. 消息通知 ​ 哪些情况用到activeMq 1.6. 优化 seo怎么优化 怎么加快访问速度 1.7. 秒杀 ​ 怎么处理高并发 ​ 秒杀过程中怎么控制库存
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值