Browse Source

添加商品分类导入功能

zhh 3 years ago
parent
commit
0dcb94f415

+ 47 - 0
kmall-admin/src/main/java/com/kmall/admin/controller/CategoryController.java

@@ -1,5 +1,6 @@
 package com.kmall.admin.controller;
 
+import com.kmall.admin.dto.CategoryDto;
 import com.kmall.admin.dto.CopyCategoryDto;
 import com.kmall.admin.dto.StoreDto;
 import com.kmall.admin.dto.StoreIdDto;
@@ -262,4 +263,50 @@ public class CategoryController {
         return R.ok("刷新成功!");
     }
 
+    /**
+     * 导入excel
+     *
+     * @param file
+     * @return
+     */
+    @RequestMapping("/upload")
+    public R upload(@RequestParam("file") MultipartFile file) {
+        List<CategoryDto> categoryDtoList = new ArrayList<>();
+        // 读取 excel 数据
+        try {
+            CategoryDto categoryDto = new CategoryDto();
+            Map<String, Object> beans = new HashMap<>();
+            beans.put("categoryDto", categoryDto);
+            beans.put("categoryDtoList", categoryDtoList);
+            if (file.isEmpty()) {
+                return R.error("文件不能为空!");
+            }
+            excelUtil.readExcel(JxlsXmlTemplateName.CATEGORY_DTO_LIST, beans, file.getInputStream());
+        } catch (XLSDataReadException e) {
+            logger.error("商品类型读取excel失败:" + e.getMessage());
+            return R.error("导入失败!请在单元格输入正确的数据格式");
+        } catch (Exception e) {
+            logger.error("商品类型读取excel失败:" + e.getMessage());
+            return R.error("读取excel数据失败!");
+        }
+        // 新增数据
+        try {
+            if (categoryDtoList == null || categoryDtoList.size() == 0) {
+                return R.error("读取excel失败!单元格内容不能为空!");
+            }
+
+            categoryService.uploadExcel(categoryDtoList);
+        } catch (ServiceException e) {
+            logger.error("商品类型数据格式校验失败:" + e.getMessage());
+            return R.error(e.getMessage());
+        } catch (RRException e) {
+            logger.error("商品类型添加数据失败:" + e.getMsg());
+            return R.error(e.getMsg());
+        } catch (Exception e) {
+            logger.error("商品类型添加数据失败:" + e.getMessage());
+            return R.error("数据保存数据库失败!");
+        }
+        return R.ok("导入成功!");
+    }
+
 }

+ 17 - 0
kmall-admin/src/main/java/com/kmall/admin/dao/CategoryDao.java

@@ -1,5 +1,6 @@
 package com.kmall.admin.dao;
 
+import com.kmall.admin.dto.CategoryDto;
 import com.kmall.admin.dto.Mall2RulesDto;
 import com.kmall.admin.entity.CategoryEntity;
 import com.kmall.admin.entity.vip.Mall2DetilEntity;
@@ -31,6 +32,22 @@ public interface CategoryDao extends BaseDao<CategoryEntity> {
 
     void updateObjectCategory(List<Mall2RulesDto> pointsRulesList);
 
+    /**
+     * 根据父id查询子对象
+     *
+     * @author zhuhh
+     * @param parentId
+     * @return
+     */
     List<CategoryEntity> queryListByParentId(List<Integer> parentId);
 
+    /**
+     * 根据名称和级别查询是否存在对象
+     *
+     * @param name
+     * @param level
+     * @return
+     */
+    CategoryDto queryExistByNameAndLevel(@Param("name") String name, @Param("level") String level);
+
 }

+ 338 - 0
kmall-admin/src/main/java/com/kmall/admin/dto/CategoryDto.java

@@ -0,0 +1,338 @@
+package com.kmall.admin.dto;
+
+import com.kmall.manager.entity.Tree;
+
+/**
+ * category导入excel实体
+ *
+ * 表名 mall_category
+ *
+ * @author zhuhh
+ * @email
+ * @date 2021-12-8 15:02:08
+ */
+public class CategoryDto extends Tree<CategoryDto> {
+
+    //主键
+    private Integer id;
+    //分类名称
+    private String name;
+    //关键字
+    private String keywords;
+    //描述
+    private String frontDesc;
+    //父节点
+    private Integer parentId;
+    //父分类名称
+    private String parentName;
+    //排序
+    private Integer sortOrder;
+    //首页展示
+    private Integer showIndex;
+    //显示
+    private Integer isShow;
+    //banner图片
+    private String bannerUrl;
+    //icon链接
+    private String iconUrl;
+    //图片
+    private String imgUrl;
+    //手机banner
+    private String wapBannerUrl;
+    //级别
+    private String level;
+    //类型
+    private Integer type;
+    //
+    private String frontName;
+
+    //翻译用字段
+    private String show;
+
+    private Integer storeId;
+
+    private String merchSn;
+
+    private String storeName;
+    private String merchName;
+
+    private String share;
+
+    //积分生成规则id
+    private Long pointsRulesId;
+
+    public String getStoreName() {
+        return storeName;
+    }
+
+    public void setStoreName(String storeName) {
+        this.storeName = storeName;
+    }
+
+    public String getMerchName() {
+        return merchName;
+    }
+
+    public void setMerchName(String merchName) {
+        this.merchName = merchName;
+    }
+
+    public Integer getStoreId() {
+        return storeId;
+    }
+
+    public void setStoreId(Integer storeId) {
+        this.storeId = storeId;
+    }
+
+    public String getMerchSn() {
+        return merchSn;
+    }
+
+    public void setMerchSn(String merchSn) {
+        this.merchSn = merchSn;
+    }
+
+    public String getShow() {
+        return show;
+    }
+
+    public void setShow(String show) {
+        this.show = show;
+    }
+
+    /**
+     * 设置:主键
+     */
+    public void setId(Integer id) {
+        this.id = id;
+    }
+
+    /**
+     * 获取:主键
+     */
+    public Integer getId() {
+        return id;
+    }
+
+    /**
+     * 设置:分类名称
+     */
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    /**
+     * 获取:分类名称
+     */
+    public String getName() {
+        return name;
+    }
+
+    /**
+     * 设置:关键字
+     */
+    public void setKeywords(String keywords) {
+        this.keywords = keywords;
+    }
+
+    /**
+     * 获取:关键字
+     */
+    public String getKeywords() {
+        return keywords;
+    }
+
+    /**
+     * 设置:描述
+     */
+    public void setFrontDesc(String frontDesc) {
+        this.frontDesc = frontDesc;
+    }
+
+    /**
+     * 获取:描述
+     */
+    public String getFrontDesc() {
+        return frontDesc;
+    }
+
+    /**
+     * 设置:父节点
+     */
+    public void setParentId(Integer parentId) {
+        this.parentId = parentId;
+    }
+
+    /**
+     * 获取:父节点
+     */
+    public Integer getParentId() {
+        return parentId;
+    }
+
+    /**
+     * 设置:排序
+     */
+    public void setSortOrder(Integer sortOrder) {
+        this.sortOrder = sortOrder;
+    }
+
+    /**
+     * 获取:排序
+     */
+    public Integer getSortOrder() {
+        return sortOrder;
+    }
+
+    /**
+     * 设置:首页展示
+     */
+    public void setShowIndex(Integer showIndex) {
+        this.showIndex = showIndex;
+    }
+
+    /**
+     * 获取:首页展示
+     */
+    public Integer getShowIndex() {
+        return showIndex;
+    }
+
+    /**
+     * 设置:显示
+     */
+    public void setIsShow(Integer isShow) {
+        this.isShow = isShow;
+    }
+
+    /**
+     * 获取:显示
+     */
+    public Integer getIsShow() {
+        return isShow;
+    }
+
+    /**
+     * 设置:banner图片
+     */
+    public void setBannerUrl(String bannerUrl) {
+        this.bannerUrl = bannerUrl;
+    }
+
+    /**
+     * 获取:banner图片
+     */
+    public String getBannerUrl() {
+        return bannerUrl;
+    }
+
+    /**
+     * 设置:icon链接
+     */
+    public void setIconUrl(String iconUrl) {
+        this.iconUrl = iconUrl;
+    }
+
+    /**
+     * 获取:icon链接
+     */
+    public String getIconUrl() {
+        return iconUrl;
+    }
+
+    /**
+     * 设置:图片
+     */
+    public void setImgUrl(String imgUrl) {
+        this.imgUrl = imgUrl;
+    }
+
+    /**
+     * 获取:图片
+     */
+    public String getImgUrl() {
+        return imgUrl;
+    }
+
+    /**
+     * 设置:手机banner
+     */
+    public void setWapBannerUrl(String wapBannerUrl) {
+        this.wapBannerUrl = wapBannerUrl;
+    }
+
+    /**
+     * 获取:手机banner
+     */
+    public String getWapBannerUrl() {
+        return wapBannerUrl;
+    }
+
+    /**
+     * 设置:级别
+     */
+    public void setLevel(String level) {
+        this.level = level;
+    }
+
+    /**
+     * 获取:级别
+     */
+    public String getLevel() {
+        return level;
+    }
+
+    /**
+     * 设置:类型
+     */
+    public void setType(Integer type) {
+        this.type = type;
+    }
+
+    /**
+     * 获取:类型
+     */
+    public Integer getType() {
+        return type;
+    }
+
+    /**
+     * 设置:
+     */
+    public void setFrontName(String frontName) {
+        this.frontName = frontName;
+    }
+
+    /**
+     * 获取:
+     */
+    public String getFrontName() {
+        return frontName;
+    }
+
+    public String getShare() {
+        return share;
+    }
+
+    public void setShare(String share) {
+        this.share = share;
+    }
+
+    public Long getPointsRulesId() {
+        return pointsRulesId;
+    }
+
+    public void setPointsRulesId(Long pointsRulesId) {
+        this.pointsRulesId = pointsRulesId;
+    }
+
+    public String getParentName() {
+        return parentName;
+    }
+
+    public void setParentName(String parentName) {
+        this.parentName = parentName;
+    }
+
+}

+ 10 - 0
kmall-admin/src/main/java/com/kmall/admin/service/CategoryService.java

@@ -1,6 +1,7 @@
 package com.kmall.admin.service;
 
 import com.kmall.admin.dto.CateStoreDto;
+import com.kmall.admin.dto.CategoryDto;
 import com.kmall.admin.dto.CopyCategoryDto;
 import com.kmall.admin.entity.CategoryEntity;
 
@@ -87,4 +88,13 @@ public interface CategoryService {
      */
     List<CategoryEntity> queryListByParentId(List<Integer> parentId);
 
+
+    /**
+     * 导入excel
+     *
+     * @author zhuhh
+     * @param categoryDtoList
+     */
+    void uploadExcel(List<CategoryDto> categoryDtoList);
+
 }

+ 100 - 4
kmall-admin/src/main/java/com/kmall/admin/service/impl/CategoryServiceImpl.java

@@ -6,17 +6,19 @@ import com.kmall.admin.dao.GoodsDao;
 import com.kmall.admin.dao.ProductStoreRelaDao;
 import com.kmall.admin.dao.StoreDao;
 import com.kmall.admin.dto.CateStoreDto;
+import com.kmall.admin.dto.CategoryDto;
 import com.kmall.admin.dto.CopyCategoryDto;
 import com.kmall.admin.entity.*;
 import com.kmall.admin.service.CategoryService;
+import com.kmall.admin.utils.ValidateUtils;
 import com.kmall.common.constant.Dict;
-import com.kmall.common.utils.MapBeanUtil;
-import com.kmall.common.utils.R;
-import com.kmall.common.utils.RRException;
-import com.kmall.common.utils.ValidatorUtil;
+import com.kmall.common.utils.*;
+import com.kmall.manager.manager.express.sf.ServiceException;
 import com.kmall.manager.manager.redis.JedisUtil;
+import org.apache.commons.lang3.StringUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
 
 import java.util.ArrayList;
 import java.util.HashMap;
@@ -305,5 +307,99 @@ public class CategoryServiceImpl implements CategoryService {
         return categoryDao.queryListByParentId(parentId);
     }
 
+    @Override
+    @Transactional
+    public void uploadExcel(List<CategoryDto> categoryDtoList) {
+        int parentId = 0;
+
+        for (CategoryDto categoryDto : categoryDtoList) {
+            // 分类名称
+            String name = categoryDto.getName();
+            // 关键字
+            String keywords = categoryDto.getKeywords();
+            // 描述
+            String frontDesc = categoryDto.getFrontDesc();
+            // 排序
+            Integer sortOrder = categoryDto.getSortOrder();
+            // 是否显示
+            Integer isShow = categoryDto.getIsShow();
+            // 级别
+            String level = categoryDto.getLevel();
+            // 父节点
+            String parentName = categoryDto.getParentName();
+            // 类型
+            Integer type = categoryDto.getType();
+
+            // 校验
+            if (!ValidateUtils.validateSpecialAllowChinese(name)) {
+                throw new ServiceException("请输入正确的分类名称,有问题的分类名称:" + name);
+            }
+            if (StringUtils.isNotBlank(keywords)) {
+                if (!ValidateUtils.validateSpecialAllowChinese(keywords)) {
+                    throw new ServiceException("请输入正确的关键字,有问题的关键字:" + keywords);
+                }
+            }
+            if (!ValidateUtils.validateSpecialAllowChinese(frontDesc)) {
+                throw new ServiceException("请输入正确的描述,有问题的描述:" + frontDesc);
+            }
+            if (sortOrder == null || sortOrder < 0) {
+                throw new ServiceException("请输入正确的排序,有问题的排序:" + sortOrder);
+            }
+            if (isShow < 0 || isShow > 1) {
+                throw new ServiceException("请填写正确的是否显示,有问题的是否显示:" + isShow);
+            }
+            if (!(Dict.Level.item_L1.getItem()).equals(level) && !(Dict.Level.item_L2.getItem()).equals(level)) {
+                throw new ServiceException("请填写正确的级别,有问题的级别:" + level);
+            }
+            if (StringUtils.isNotBlank(parentName)) {
+                if (!ValidateUtils.validateSpecialAllowChinese(parentName)) {
+                    throw new ServiceException("请输入正确的上级分类名称,有问题的上级分类名称:" + parentName);
+                }
+            }
+
+            // 判断分类是否已存在
+            CategoryDto isExist = categoryDao.queryExistByNameAndLevel(name, level);
+            if (isExist != null) {
+                throw new RRException("该级别下的分类名称已存在,已存在的分类名称:" + name);
+            }
+            // 判断上级分类是否已存在
+            if (StringUtils.isNotBlank(parentName)) {
+                // 查询数据库判断有没有
+                CategoryDto isParentExist = categoryDao.queryExistByNameAndLevel(parentName, Dict.Level.item_L1.getItem());
+                if (isParentExist == null) {
+                    // 再去判断excel表是否有对应的上级分类
+                    boolean flag = true;
+                    for (CategoryDto temp : categoryDtoList) {
+                        if (temp.getName().equals(parentName) && Dict.Level.item_L1.getItem().equals(temp.getLevel())) {
+                            flag = false;
+                            break;
+                        }
+                    }
+
+                    if (flag) {
+                        throw new RRException("不存在的父分类名称:" + parentName);
+                    }
+                }
+                // 如果excel表分类的父分类在数据库中,则获取父分类
+                parentId = isParentExist.getId();
+            }
+
+            CategoryEntity categoryEntity = new CategoryEntity();
+            BeanUtils.copyProperties(categoryDto, categoryEntity);
+            // 父分类的添加
+            if (Dict.Level.item_L1.getItem().equals(level)) {
+                categoryEntity.setParentId(0);
+
+                parentId = categoryDao.save(categoryEntity);
+            } else if (Dict.Level.item_L2.getItem().equals(level)) {
+                // 子分类的添加
+                categoryEntity.setParentId(parentId);
+
+                categoryDao.save(categoryEntity);
+            }
+        }
+
+    }
+
 
 }

+ 24 - 0
kmall-admin/src/main/resources/XmlTemplate/CategoryDtoList.xml

@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<workbook>
+    <worksheet name="Sheet1">
+        <section startRow="0" endRow="1"/>
+        <loop startRow="1" endRow="1" items="categoryDtoList" var="categoryDto"
+              varType="com.kmall.admin.dto.CategoryDto">
+            <section startRow="1" endRow="1">
+                <mapping row="1" col="0">categoryDto.name</mapping>
+                <mapping row="1" col="1">categoryDto.keywords</mapping>
+                <mapping row="1" col="2">categoryDto.frontDesc</mapping>
+                <mapping row="1" col="3">categoryDto.sortOrder</mapping>
+                <mapping row="1" col="4">categoryDto.isShow</mapping>
+                <mapping row="1" col="5">categoryDto.level</mapping>
+                <mapping row="1" col="6">categoryDto.parentName</mapping>
+                <mapping row="1" col="7">categoryDto.type</mapping>
+            </section>
+            <loopbreakcondition>
+                <rowcheck offset="0">
+                    <cellcheck offset="0">end</cellcheck>
+                </rowcheck>
+            </loopbreakcondition>
+        </loop>
+    </worksheet>
+</workbook>

+ 8 - 0
kmall-admin/src/main/resources/mybatis/mapper/CategoryDao.xml

@@ -326,4 +326,12 @@
 		</foreach>
 	</select>
 
+	<select id="queryExistByNameAndLevel" resultType="com.kmall.admin.dto.CategoryDto">
+		select
+		 id
+		from mall_category
+		where `name` = #{name} and `level` = #{level}
+		limit 1
+	</select>
+
 </mapper>

+ 11 - 1
kmall-admin/src/main/webapp/WEB-INF/page/shop/category.html

@@ -23,6 +23,16 @@
                 <i-button @click="reloadSearch"><i class="fa fa-refresh"></i>&nbsp;重置</i-button>
             </div>
             <div class="buttons-group">
+                <a @click="importTemplate">导入模板下载</a>&nbsp;&nbsp;&nbsp;&nbsp;
+                <i-col style="display: inline-grid;">
+                    <Upload :show-upload-list="false" :on-success="uploadExcelSuccess" :on-format-error="uploadExcelFormatError"
+                            :format="['xls','xlsx']"
+                            :on-progress="uploadExcelProgress"
+                            action="../category/upload">
+                        <i-button type="ghost" icon="ios-cloud-upload-outline">导入</i-button>
+                    </Upload>
+                </i-col>
+
                 <!--<i-button type="ghost" @click="reload"><i class="fa fa-refresh"></i>&nbsp;刷新</i-button>-->
                 <i-button type="primary" @click="refreshCache"><i class="fa fa-cloud-download"></i>&nbsp;刷新缓存</i-button>
                 #if($shiro.hasPermission("category:save"))
@@ -46,7 +56,7 @@
                 <span>当前第 {{ page.currPage }} 页,共 {{ page.totalPage }} 页</span>
             </div>
             <div style="margin: 25px 0;" align="right" class="col-lg-3 col-md-3 col-xs-3 col-sm-3">
-                <span>共 {{ page.totalCount }} 条</span>
+                <span>每页 20 条,共 {{ page.totalCount }} 条</span>
             </div>
         </div>
     </div>

+ 44 - 0
kmall-admin/src/main/webapp/js/shop/category.js

@@ -386,7 +386,51 @@ var vm = new Vue({
         eyeImageWapBannerUrl: function () {
             var url = vm.category.wapBannerUrl;
             eyeImage(url);
+        },
+        // 下载导入的模板方法
+        importTemplate: function (){
+            const msg = this.$Message.loading({
+                content: 'Loading...',
+                duration: 0
+            });
+            window.location.href='../statics/file/category_yyyy_mm_dd_v1.0.0.xls';
+            setTimeout(msg, 1000);
+        },
+        // 上传方法开始 ----
+        uploadExcelSuccess: function (data) {
+            if (data.code == 0) {
+                alert('导入成功', function (index) {
+                    $("#jqGrid").trigger("reloadGrid");
+                    vm.page = {
+                        currPage: 1,
+                        totalPage: 1,   // 数值不影响,主要是设置参数
+                        totalCount: 1   // 数值不影响,主要是设置参数
+                    }
+                    vm.reload();
+                });
+            } else {
+                alert(data.msg);
+            }
+            setTimeout(exportMsg, 100);
+        },
+        uploadExcelError: function () {
+            alert('上传出现异常,请重试!');
+            setTimeout(exportMsg, 100);
+        },
+        uploadExcelProgress: function (event, file, fileList) {
+            exportMsg = this.$Message.loading({
+                content: 'Loading...',
+                duration: 0
+            });
+        },
+        uploadExcelFormatError: function (file) {
+            this.$Notice.warning({
+                title: '文件格式不正确',
+                desc: '文件 ' + file.name + ' 格式不正确,请上传 xls 或 xlsx 格式的文件。'
+            });
+            setTimeout(exportMsg, 100);
         }
+        // 上传方法结束----
     },
     mounted() {
         $.get("../store/queryAll", function (r) {

BIN
kmall-admin/src/main/webapp/statics/file/category_yyyy_mm_dd_v1.0.0.xls


+ 3 - 0
kmall-common/src/main/java/com/kmall/common/constant/JxlsXmlTemplateName.java

@@ -79,4 +79,7 @@ public class JxlsXmlTemplateName {
     // 计量单位代码导入
     public static final String SYS_CUS_UNIT_CODE_DTO_List = "/XmlTemplate/SysCusUnitCodeDtoList.xml";
 
+    // 商品类型导入
+    public static final String CATEGORY_DTO_LIST = "/XmlTemplate/CategoryDtoList.xml";
+
 }