SSM项目之商铺系统-商品修改(十六)

我们来进行商品修改方法的实现。

我们呢先看成型图

其实和商铺修改相似,所以需要实现两个功能

第一个通过商品id获取商品初始类型

第二个接受前台输入的数据更新商品

我们两个方法一起说

DAO:

修改商品因为修改的是product额多个属性,所以用product包装

获取商品信息只需要获得商品的id,即可查出。

mapper.xml:


    <!--通过传入的product修改相应的信息-->
    <update id="modifyProduct" >
            UPDATE tb_product
            <set>
                <if test="productName!=null">product_name=#{productName},</if>
                <if test="productDesc!=null">product_desc=#{productDesc},</if>
                <if test="imgAddr!=null">img_addr=#{imgAddr},</if>
                <if test="normalPrice!=null">normal_price=#{normalPrice},</if>
                <if test="promotionPrice!=null">promotion_price=#{promotionPrice},</if>
                <if test="priority!=null">priority=#{priority},</if>
                <if test="lastEditTime!=null">last_edit_time=#{lastEditTime},</if>
                <if test="enableStatus!=null">enable_status=#{enableStatus},</if>
                <if test="productCategory != null and productCategory.productCategoryId != null ">product_category_id=#{productCategory.productCategoryId}</if>
            </set>
          WHERE product_id=#{productId} AND shop_id=#{shop.shopId}
    </update>

Service:

  //通过商品id获得商品信息
    Product getProductById(long productId);
    //修改商品信息
    ProductExecution modifyProduct(Product product,ImageHolder imageHolder, List<ImageHolder> prodImgDetailList) throws ProductOperationException;

修改商品信息的三个参数分别是修改的product,文件缩略图包装类,文件详情图包装类。

ServiceImpl:

    //根据商品id获取商品信息
    @Override
    public Product getProductById(long productId) { return productDao.getProductById(productId);}

我们主要看修改页面的方法:

第一步:判断product和shopid是否为空(注意,这里只能判断这么多,下架商品也是通过修改界面实现的,修改商品上下架状态时只能传入product和shopid如果判断别的会造成无法成功执行操作) 

第二步:判断传入的缩略图是否为空,如果不为空我们判断之前是否有缩略图,如果有删除原有的。然后加入新的图片

通过addProductImg方法将路径存入product的属性中

第三步:判断传入的商品详情图是否为空,如果不为空我们删除原来的存储的图片,之后调用addproductImgList方法将所有图片和传入服务器并将路径写入productImg属性供下面操作

第四步,完成操作后,我们通过获得的所有信息,调用修改的方法,进行修改,并且设置操作状态值并传给前端

  /*
    * 根据前端传入的信息我们进行修改
    * 如果更改了product的里的属性我们就更改那些更改了的属性
    * 如果传入文件缩略图,我们就对原来的照片采取删除操作重新存储,且把地址写入product表中
    * 如果传入商品详情图,我们就把原来的商品详情图全部删除,存入新的并更新Img表
    * */
    @Override
    public ProductExecution modifyProduct(Product product, ImageHolder imageHolder, List<ImageHolder> prodImgDetailList) throws ProductOperationException {
        //先设置属性
        if (product != null && product.getShop()!=null&&product.getShop().getShopId() != null ) {
            product.setLastEditTime(new Date());
            //如果传入的缩略图不为空我们更新缩略图
            if (imageHolder!=null){
                //通过商品id获取商品的信息
                Product tempProduct=productDao.getProductById(product.getProductId());
                if (tempProduct.getImgAddr()!=null){//删除旧的缩略图,因为缩略图不想商品详情图存入单独一个表,所以我们不用再写一个dao
                    ImageUtil.deleteFileOrPath(tempProduct.getImgAddr());
                }
                //添加缩略图
                addProductImg(product,imageHolder);
            }
            //接下来我们完成对商品详情图的处理
            if(prodImgDetailList!=null&&prodImgDetailList.size()>0){//如果也传入了详情图
                //删除表中详情图片
                deleteProductImgs(product.getProductId());//通过商品id删除详情图库中的记录,并且删除相应文件,还有product表中的详情图相应的属性
                addProductImgList(product,prodImgDetailList);//存入新的详情图
            }
            try {
                //更新product
                int effectNum=productDao.modifyProduct(product);
                if (effectNum<=0){
                    throw new ProductOperationException("商品更新失败");//抛出异常
                }
                return  new ProductExecution(ProductStateEnum.SUCCESS,product);
            }catch (Exception e){
                throw  new ProductOperationException("商品更新失败"+e.getMessage());
            }
        }
        else {
            return  new ProductExecution(ProductStateEnum.NULL_PARAMETER);
        }
    }



    private void addProductImg(Product product, ImageHolder imageHolder) {//存入图片的方法
        // 根据shopId获取图片存储的相对路径
        String relativePath = PathUtil.getProductImagePath(product.getProductId(),product.getShop().getShopId());
        // 添加图片到指定的目录
        String relativeAddr = ImageUtil.generateThumnail(imageHolder, relativePath);
        // 将relativeAddr设置给product
        product.setImgAddr(relativeAddr);
    }



    /**
     * 批量添加商品图片
     *
     * @param product
     * @param productImgHolderList
     */
    private void addProductImgList(Product product, List<ImageHolder> productImgHolderList) {
        // 获取图片存储路径,这里直接存到相应店铺的文件夹下
        String desc = PathUtil.getProductDetaisImagePath(product.getProductId(),product.getShop().getShopId());
        List<ProductImg> productImgList = new ArrayList<>();

        // 遍历图片依次去处理,并添加进 productImg 实体类中
        for (ImageHolder productImageHolder : productImgHolderList) {
            String imgAddr = ImageUtil.generateNormalImg(productImageHolder, desc);
            ProductImg productImg = new ProductImg();
            productImg.setImgAddr(imgAddr);
            productImg.setProductId(product.getProductId());
            productImg.setCreateTime(new Date());
            productImgList.add(productImg);
        }

        // 如果确定是有图片需要添加的,就执行批量添加操作
        if (productImgList.size() > 0) {
            try {

                int effectedNum = productImgDao.batchInsertProductImg(productImgList);
                if (effectedNum <= 0) {
                    throw new ProductOperationException("创建商品详情图片失败!");
                }
            } catch (Exception e) {
                throw new ProductOperationException("创建商品详情图片失败," + e.toString());
            }
        }
    }

    private void deleteProductImgs(Long productId) {
        // 获取该商铺下对应的productImg信息
        List<ProductImg> productImgList = productDao.getProductById(productId).getProductImgList();
        // 遍历删除该目录下的全部文件
        for (ProductImg productImg : productImgList) {
            ImageUtil.deleteFileOrPath(productImg.getImgAddr());
        }
        // 删除tb_product_img中该productId对应的记录
        productImgDao.deleteProductImgById(productId);

    }


}

controller:

通过商品id获得商品,没什么要说的

/**
 * 通过商品id获得商品信息
 * 我们不仅要加载商品信息,还要加载当前商铺的商品所有类型,使其显示在下拉框让客户完成选择
 */
    @RequestMapping(value ="/getproductbyid" ,method = RequestMethod.GET)
@ResponseBody
private Map<String,Object> getProductById(@RequestParam long productId){
    Map<String,Object>  modelMap=new HashMap<String, Object>();//返回给前台使用
    if (productId>0){
        Product product=productService.getProductById(productId);//通过商品id获得商品数据
        List<ProductCategory> productCategoryList=productCategoryService.getProductCategoryList(product.getShop().getShopId());//通过商铺id获取商铺所有商品类别
        modelMap.put("product",product);
        modelMap.put("productCategoryList",productCategoryList);
        modelMap.put("success",true);
    }else {
        modelMap.put("success",false);
        modelMap.put("errMsg","empty pageSize or pageIndex or shopId");
    }

    return modelMap;

    }

通过传入的数据更改商品信息

第一步:通过验证码测试,注意可能我们修改的只是上下架,那么要在判断前判断是不是下架如果是,不进行验证码操作

第二步:获取前端传要修改的数据,用mapperObject解析

第三步:判断是否有文件流上传,如果有文件啊流上传我们需要特殊件处理

         ①.将request请求转为文件spring处理文件的requset

        ②.从multipartHttpServletRequest获取文件

       ③将获得的文件封装起来交给下步处理

第四步:和上一步的过程一样处理商品详情图,进行封装

第五步:从session获得当前店铺编号

第六步:传入前几步封装的信息进行更改

 

   /*
    * 我们完成修改product的controller操作
    * */
    @RequestMapping(value ="/modifyproduct" ,method = RequestMethod.POST)
    @ResponseBody
    private  Map<String,Object> modifyProduct(HttpServletRequest request){
        Map<String, Object> modelMap = new HashMap<String, Object>();
        // 是商品编辑时候调用还是上下架操作的时候调用
        // 若为前者则进行验证码判断,后者则跳过验证码判断
        boolean statusChange = HttpServletRequestUtil.getBoolean(request, "statusChange");
        // 验证码检验
        if (!statusChange && !CodeUtil.checkVerifyCode(request)) {
            modelMap.put("success", false);
            modelMap.put("errMsg", "验证码错误!");
            return modelMap;
        }
        Product product = null;
        // 接收前端传递过来的product
        String productStr = null;
        // 商品图片缩略图(输入流和名称的封装类)
        ImageHolder thumbnail = null;

        // 将HttpServletRequest转型为MultipartHttpServletRequest,可以很方便地得到文件名和文件内容
        MultipartHttpServletRequest multipartHttpServletRequest = null;
        // 接收商品缩略图
        CommonsMultipartFile thumbnailFile = null;
        // 接收商品详情图片
        List<ImageHolder> productDetailImgList = new ArrayList<ImageHolder>();

        // 创建一个通用的多部分解析器
        CommonsMultipartResolver commonsMultipartResolver = new CommonsMultipartResolver(request.getSession().getServletContext());

        // Step2: 使用FastJson提供的api,实例化Product 构造调用service层的第一个参数
        ObjectMapper mapper = new ObjectMapper();
        // 获取前端传递过来的product,约定好使用productStr
        try {
            productStr = HttpServletRequestUtil.getString(request, "productStr");
            product = mapper.readValue(productStr, Product.class);
        } catch (Exception e) {
            modelMap.put("success", false);
            modelMap.put("errMsg", e.toString());
            return modelMap;
        }
        // Step3: 商品缩略图 和 商品详情图 构造调用service层的第二个参数和第三个参数
        try {
            // 判断 request 是否有文件上传,即多部分请求
            if (commonsMultipartResolver.isMultipart(request)) {
                // 将request转换成多部分request
                multipartHttpServletRequest = (MultipartHttpServletRequest) request;

                // 得到缩略图的CommonsMultipartFile ,和前端约定好使用thumbnail 传递
                // ,并构建ImageHolder对象
                thumbnailFile = (CommonsMultipartFile) multipartHttpServletRequest.getFile("thumbnail");
                // 转化为ImageHolder,使用service层的参数类型要求
                thumbnail = new ImageHolder(thumbnailFile.getOriginalFilename(), thumbnailFile.getInputStream());

                // 得到 商品详情的列表,和前端约定使用productImg + i 传递 ,并构建ImageHolder对象
                for (int i = 0; i < IMAGEMAXCOUNT; i++) {
                    CommonsMultipartFile productDetailImgFile = (CommonsMultipartFile) multipartHttpServletRequest.getFile("productImg" + i);
                    if (productDetailImgFile != null) {
                        ImageHolder productDetailImg = new ImageHolder( productDetailImgFile.getOriginalFilename(),productDetailImgFile.getInputStream());
                        productDetailImgList.add(productDetailImg);
                    } else {
                        // 如果从请求中获取的到file为空,终止循环
                        break;
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            modelMap.put("success", false);
            modelMap.put("errMsg", e.toString());
            return modelMap;
        }

        // Step4 调用Service层
        if (product != null ) {
            try {
                // 从session中获取shop信息,不依赖前端的传递更加安全
                Shop currentShop = (Shop) request.getSession().getAttribute("currentShop");
                product.setShop(currentShop);
                // 调用addProduct
                ProductExecution pe = productService.modifyProduct(product, thumbnail, productDetailImgList);
                if (pe.getState() == ProductStateEnum.SUCCESS.getState()) {
                    modelMap.put("success", true);
                } else {
                    modelMap.put("success", false);
                    modelMap.put("errMsg", pe.getStateInfo());
                }
            } catch (ProductOperationException e) {
                modelMap.put("success", false);
                modelMap.put("errMsg", e.toString());
                return modelMap;
            }
        } else {
            modelMap.put("success", false);
            modelMap.put("errMsg", "请输入商品信息");
        }
        return modelMap;
    }

VIEW

productoperation.js


 *  因为商品的添加和编辑复用同一个页面,所以需要根据url中的商品Id来判断
 */
$(function(){
    //通过url是否含有productId来判断是添加商品还是编辑
    var productId = getQueryString('productId');
    // 标示符  productId非空则为true即编辑,否则为添加商品
    var isEdit = productId ? true : false ;

    // 商品添加URL 用于提交
    var addProductURL = '/storepro/shopadmin/addproduct';
    // 商品编辑URL 用于提交
    var editProductURL = '/storepro/shopadmin/modifyproduct?productId=' + productId;
    // 获取商品初始化信息的URL  根据页面原型只需要获取productCategory即可,后台调用之前写好的路由方法即可
    var categoryInfoURL = '/storepro/shopadmin/getproductcategorybyshopid';
    // 商品编辑URL 用于从后台加载该product的基本信息,页面展示用
    var productInitURL = '/storepro/shopadmin/getproductbyid?productId=' + productId;

    // 通过标示符,确定调用的方法
    if(isEdit){
        // 为true,则根据productId调用获取product信息的方法
        showEditProductPage(productId);
    }else{
        // 为false,则初始化新增product页面
        showAddProductPage();
    }

    /**
     * 始化新增product页面
     *
     * 根据页面原型和数据模型,需要加载该shop对应的productCategory信息(shop信息从服务端session中获取)
     */
    function showAddProductPage(){
        $.getJSON(categoryInfoURL,
            function(data){
                if(data.success){
                    // 设置product_category
                    var productCategoryList = data.data;
                    var productCategoryTempHtml = '';
                    productCategoryList.map(function(item, index) {
//                          productCategoryTempHtml += '<option data-id="'
//                                  + item.productCategoryId + '">' + item.productCategoryName
//                                  + '</option>';
                        productCategoryTempHtml += '<option data-value="'
                            + item.productCategoryId + '">'
                            + item.productCategoryName + '</option>';
                    });
                    $('#product-category').html(productCategoryTempHtml);
                }else{
                    $.toast(data.errMsg)
                }
            });
    };

    /**
     * 点击控件的最后一个且图片数量小于6个的时候,生成一个选择框
     */
    $('.detail-img-div').on('change', '.detail-img:last-child', function() {
        if ($('.detail-img').length < 6) {
            $('#detail-img').append('<input type="file" class="detail-img">');
        }
    });


    /**
     * 编辑页面调用的function
     */
    function showEditProductPage(productId){
        $.getJSON(
            productInitURL,
            function(data) {
                if (data.success) {
                    var product = data.product;
                    $('#product-name').val(product.productName);
                    $('#product-desc').val(product.productDesc);
                    $('#priority').val(product.priority);
                    $('#normal-price').val(product.normalPrice);
                    $('#promotion-price').val(
                        product.promotionPrice);

                    var optionHtml = '';
                    var optionArr = data.productCategoryList;
                    var optionSelected = product.productCategory.productCategoryId;
                    optionArr.map(function(item, index) {
                        var isSelect = optionSelected === item.productCategoryId ? 'selected'
                            : '';
                        optionHtml += '<option data-value="'
                            + item.productCategoryId
                            + '"'
                            + isSelect
                            + '>'
                            + item.productCategoryName
                            + '</option>';
                    });
                    $('#product-category').html(optionHtml);
                }
            });
    };

    /**
     * 提交按钮的响应时间,分别对商品添加和商品编辑做不同的相应
     */
    $('#submit').click(
        function(){
            // 创建商品Json对象,并从表单对象中获取对应的属性值
            var product = {};

            // 如果是编辑操作,需要传入productId
            if(isEdit){
                product.productId = productId;
            }

            product.productName = $('#product-name').val();
            product.productDesc = $('#product-desc').val();

            // 获取商品的特定目录值
            product.productCategory = {
                productCategoryId : $('#product-category').find('option').not(
                    function() {
                        return !this.selected;
                    }).data('value')
            };

            product.priority = $('#priority').val();
            product.normalPrice = $('#normal-price').val();
            product.promotionPrice = $('#promotion-price').val();

            // 生成表单对象用于接收参数并传递给后台
            var formData = new FormData();

            // 缩略图 (只有一张),获取缩略图的文件流
            var thumbnail = $('#small-img')[0].files[0];
            formData.append('thumbnail',thumbnail);

            // 图片详情
            $('.detail-img').map(
                function(index, item) {
                    // 判断该控件是否已经选择了文件
                    if ($('.detail-img')[index].files.length > 0) {
                        // 将第i个文件流赋值给key为productImgi的表单键值对里
                        formData.append('productImg' + index,
                            $('.detail-img')[index].files[0]);
                    }
                });
            // 将product 转换为json ,添加到forData
            formData.append('productStr', JSON.stringify(product));

            // 获取表单中的验证码
            var verifyCodeActual = $('#j_captcha').val();
            if (!verifyCodeActual) {
                $.toast('请输入验证码!');
                return;
            }
            formData.append("verifyCodeActual", verifyCodeActual);


            // 使用ajax异步提交
            $.ajax({
                url: isEdit?editProductURL:addProductURL,
                type: 'POST' ,
                data : formData,
                contentType : false,
                processData : false,
                cache : false,
                success: function(data){
                    if (data.success) {
                        $.toast('提交成功!');
                        $('#captcha_img').click();
                    } else {
                        $.toast('提交失败!');
                        $('#captcha_img').click();
                    }
                }
            });
        });
});

在前台中已经完成了相应的上下架操作,通过前台传入的数据我们我们后台能进行相应的上下架操作

试验:

我们必须先进入商品商铺管理页面,因为我们需要这里的shopid

 

 

 

 

 

 

 

 

 

通过这样的url访问修改页面

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值