Bläddra i källkod

商品分类维护

JeromeSoar 3 år sedan
förälder
incheckning
d3edaec2b1

+ 3 - 3
sql/mall.sql

@@ -26,10 +26,10 @@ CREATE TABLE `product_category`
     `id`          bigint        NOT NULL AUTO_INCREMENT COMMENT '分类编号',
     `pid`         bigint        NOT NULL COMMENT '父分类编号',
     `name`        varchar(255)  NOT NULL COMMENT '分类名称',
-    `icon`        varchar(100)           DEFAULT '#' COMMENT '分类图标',
+    `icon`        varchar(100)  NOT NULL DEFAULT '#' COMMENT '分类图标',
     `banner_url`  varchar(255)  NOT NULL COMMENT '分类图片',
-    `sort`        int           NOT NULL DEFAULT '0' COMMENT '分类排序',
-    `description` varchar(1024) NOT NULL COMMENT '分类描述',
+    `sort`        int                    DEFAULT '0' COMMENT '分类排序',
+    `description` varchar(1024)          DEFAULT NULL COMMENT '分类描述',
     `status`      tinyint       NOT NULL COMMENT '开启状态',
     `creator`     varchar(64)            DEFAULT '' COMMENT '创建者',
     `create_time` datetime      NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',

+ 27 - 21
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/category/CategoryController.java

@@ -1,30 +1,29 @@
 package cn.iocoder.yudao.module.product.controller.admin.category;
 
-import org.springframework.web.bind.annotation.*;
-import javax.annotation.Resource;
-import org.springframework.validation.annotation.Validated;
-import org.springframework.security.access.prepost.PreAuthorize;
-import io.swagger.annotations.*;
-
-import javax.validation.constraints.*;
-import javax.validation.*;
-import javax.servlet.http.*;
-import java.util.*;
-import java.io.IOException;
-
-import cn.iocoder.yudao.framework.common.pojo.PageResult;
 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
-import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
-
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
 import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
-
 import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog;
-import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.*;
-
 import cn.iocoder.yudao.module.product.controller.admin.category.vo.*;
-import cn.iocoder.yudao.module.product.dal.dataobject.category.CategoryDO;
 import cn.iocoder.yudao.module.product.convert.category.CategoryConvert;
+import cn.iocoder.yudao.module.product.dal.dataobject.category.CategoryDO;
 import cn.iocoder.yudao.module.product.service.category.CategoryService;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiImplicitParam;
+import io.swagger.annotations.ApiOperation;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+import javax.annotation.Resource;
+import javax.servlet.http.HttpServletResponse;
+import javax.validation.Valid;
+import java.io.IOException;
+import java.util.Collection;
+import java.util.List;
+
+import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
+import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT;
 
 @Api(tags = "管理后台 - 商品分类")
 @RestController
@@ -68,15 +67,22 @@ public class CategoryController {
         return success(CategoryConvert.INSTANCE.convert(category));
     }
 
-    @GetMapping("/list")
+    @GetMapping("/listByIds")
     @ApiOperation("获得商品分类列表")
-    @ApiImplicitParam(name = "ids", value = "编号列表", required = true, example = "1024,2048", dataTypeClass = List.class)
     @PreAuthorize("@ss.hasPermission('product:category:query')")
     public CommonResult<List<CategoryRespVO>> getCategoryList(@RequestParam("ids") Collection<Long> ids) {
         List<CategoryDO> list = categoryService.getCategoryList(ids);
         return success(CategoryConvert.INSTANCE.convertList(list));
     }
 
+    @GetMapping("/listByQuery")
+    @ApiOperation("获得商品分类列表")
+    @PreAuthorize("@ss.hasPermission('product:category:query')")
+    public CommonResult<List<CategoryRespVO>> listByQuery() {
+        List<CategoryDO> list = categoryService.listByQuery();
+        return success(CategoryConvert.INSTANCE.convertList(list));
+    }
+
     @GetMapping("/page")
     @ApiOperation("获得商品分类分页")
     @PreAuthorize("@ss.hasPermission('product:category:query')")

+ 8 - 8
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/category/vo/CategoryBaseVO.java

@@ -1,9 +1,10 @@
 package cn.iocoder.yudao.module.product.controller.admin.category.vo;
 
-import lombok.*;
-import java.util.*;
-import io.swagger.annotations.*;
-import javax.validation.constraints.*;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.NotNull;
 
 /**
 * 商品分类 Base VO,提供给添加、修改、详细的子 VO 使用
@@ -17,22 +18,21 @@ public class CategoryBaseVO {
     private Long pid;
 
     @ApiModelProperty(value = "分类名称", required = true, example = "办公文具")
-    @NotNull(message = "分类名称不能为空")
+    @NotBlank(message = "分类名称不能为空")
     private String name;
 
     @ApiModelProperty(value = "分类图标")
+    @NotBlank(message = "分类图标不能为空")
     private String icon;
 
     @ApiModelProperty(value = "分类图片", required = true)
-    @NotNull(message = "分类图片不能为空")
+    @NotBlank(message = "分类图片不能为空")
     private String bannerUrl;
 
     @ApiModelProperty(value = "分类排序", required = true, example = "1")
-    @NotNull(message = "分类排序不能为空")
     private Integer sort;
 
     @ApiModelProperty(value = "分类描述", required = true, example = "描述")
-    @NotNull(message = "分类描述不能为空")
     private String description;
 
     @ApiModelProperty(value = "开启状态", required = true, example = "0")

+ 15 - 4
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/category/CategoryService.java

@@ -1,10 +1,15 @@
 package cn.iocoder.yudao.module.product.service.category;
 
-import java.util.*;
-import javax.validation.*;
-import cn.iocoder.yudao.module.product.controller.admin.category.vo.*;
-import cn.iocoder.yudao.module.product.dal.dataobject.category.CategoryDO;
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.module.product.controller.admin.category.vo.CategoryCreateReqVO;
+import cn.iocoder.yudao.module.product.controller.admin.category.vo.CategoryExportReqVO;
+import cn.iocoder.yudao.module.product.controller.admin.category.vo.CategoryPageReqVO;
+import cn.iocoder.yudao.module.product.controller.admin.category.vo.CategoryUpdateReqVO;
+import cn.iocoder.yudao.module.product.dal.dataobject.category.CategoryDO;
+
+import javax.validation.Valid;
+import java.util.Collection;
+import java.util.List;
 
 /**
  * 商品分类 Service 接口
@@ -67,4 +72,10 @@ public interface CategoryService {
      */
     List<CategoryDO> getCategoryList(CategoryExportReqVO exportReqVO);
 
+    /**
+     * 获得商品分类列表
+     *
+     * @return 商品分类列表
+     */
+    List<CategoryDO> listByQuery();
 }

+ 17 - 9
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/category/CategoryServiceImpl.java

@@ -1,19 +1,22 @@
 package cn.iocoder.yudao.module.product.service.category;
 
-import org.springframework.stereotype.Service;
-import javax.annotation.Resource;
-import org.springframework.validation.annotation.Validated;
-
-import java.util.*;
-import cn.iocoder.yudao.module.product.controller.admin.category.vo.*;
-import cn.iocoder.yudao.module.product.dal.dataobject.category.CategoryDO;
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
-
+import cn.iocoder.yudao.module.product.controller.admin.category.vo.CategoryCreateReqVO;
+import cn.iocoder.yudao.module.product.controller.admin.category.vo.CategoryExportReqVO;
+import cn.iocoder.yudao.module.product.controller.admin.category.vo.CategoryPageReqVO;
+import cn.iocoder.yudao.module.product.controller.admin.category.vo.CategoryUpdateReqVO;
 import cn.iocoder.yudao.module.product.convert.category.CategoryConvert;
+import cn.iocoder.yudao.module.product.dal.dataobject.category.CategoryDO;
 import cn.iocoder.yudao.module.product.dal.mysql.category.CategoryMapper;
+import org.springframework.stereotype.Service;
+import org.springframework.validation.annotation.Validated;
+
+import javax.annotation.Resource;
+import java.util.Collection;
+import java.util.List;
 
 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
-import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.*;
+import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.CATEGORY_NOT_EXISTS;
 
 /**
  * 商品分类 Service 实现类
@@ -79,4 +82,9 @@ public class CategoryServiceImpl implements CategoryService {
         return categoryMapper.selectList(exportReqVO);
     }
 
+    @Override
+    public List<CategoryDO> listByQuery() {
+        return categoryMapper.selectList();
+    }
+
 }

+ 9 - 0
yudao-ui-admin/src/api/mall/product/category.js

@@ -34,6 +34,15 @@ export function getCategory(id) {
   })
 }
 
+// 获得商品分类
+export function listCategory(query) {
+  return request({
+    url: '/product/category/listByQuery',
+    method: 'get',
+    params: query
+  })
+}
+
 // 获得商品分类分页
 export function getCategoryPage(query) {
   return request({

+ 58 - 13
yudao-ui-admin/src/views/mall/product/category/index.vue

@@ -40,13 +40,18 @@
 
     <!-- 列表 -->
     <el-table v-loading="loading" :data="list">
-      <el-table-column label="分类编号" align="center" prop="id"/>
-      <el-table-column label="父分类编号" align="center" prop="pid"/>
       <el-table-column label="分类名称" align="center" prop="name"/>
-      <el-table-column label="分类图标" align="center" prop="icon"/>
-      <el-table-column label="分类图片" align="center" prop="bannerUrl"/>
+      <el-table-column label="分类图标" align="center" prop="icon">
+        <template slot-scope="scope">
+          <svg-icon :icon-class="scope.row.icon" />
+        </template>
+      </el-table-column>
+      <el-table-column label="分类图片" align="center" prop="bannerUrl">
+        <template slot-scope="scope">
+          <img v-if="scope.row.bannerUrl" :src="scope.row.bannerUrl" alt="分类图片"/>
+        </template>
+      </el-table-column>
       <el-table-column label="分类排序" align="center" prop="sort"/>
-      <el-table-column label="分类描述" align="center" prop="description"/>
       <el-table-column label="开启状态" align="center" prop="status">
         <template slot-scope="scope">
           <dict-tag :type="DICT_TYPE.COMMON_STATUS" :value="scope.row.status"/>
@@ -75,20 +80,28 @@
     <!-- 对话框(添加 / 修改) -->
     <el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
       <el-form ref="form" :model="form" :rules="rules" label-width="80px">
-        <el-form-item label="父分类编号" prop="pid">
-          <el-input v-model="form.pid" placeholder="请输入父分类编号"/>
+        <el-form-item label="上级分类" prop="pid">
+          <Treeselect v-model="form.pid" :options="parentCategoryOptions" :normalizer="normalizer" :show-count="true"
+                      placeholder="上级分类"/>
         </el-form-item>
         <el-form-item label="分类名称" prop="name">
           <el-input v-model="form.name" placeholder="请输入分类名称"/>
         </el-form-item>
         <el-form-item label="分类图标" prop="icon">
-          <el-input v-model="form.icon" placeholder="请输入分类图标"/>
+          <el-popover placement="bottom-start" width="460" trigger="click" @show="$refs['iconSelect'].reset()">
+            <IconSelect ref="iconSelect" @selected="iconSelected"/>
+            <el-input slot="reference" v-model="form.icon" placeholder="点击选择分类图标" readonly>
+              <svg-icon v-if="form.icon" slot="prefix" :icon-class="form.icon" class="el-input__icon"
+                        style="height: 32px;width: 16px;"/>
+              <i v-else slot="prefix" class="el-icon-search el-input__icon"/>
+            </el-input>
+          </el-popover>
         </el-form-item>
         <el-form-item label="分类图片" prop="bannerUrl">
           <el-input v-model="form.bannerUrl" placeholder="请输入分类图片"/>
         </el-form-item>
         <el-form-item label="分类排序" prop="sort">
-          <el-input v-model="form.sort" placeholder="请输入分类排序"/>
+          <el-input-number v-model="form.sort" controls-position="right" :min="0" />
         </el-form-item>
         <el-form-item label="分类描述">
           <editor v-model="form.description" :min-height="192"/>
@@ -116,14 +129,19 @@ import {
   exportCategoryExcel,
   getCategory,
   getCategoryPage,
+  listCategory,
   updateCategory
 } from "@/api/mall/product/category";
 import Editor from '@/components/Editor';
+import Treeselect from "@riophae/vue-treeselect";
+import "@riophae/vue-treeselect/dist/vue-treeselect.css";
+import IconSelect from "@/components/IconSelect";
+import ImageUpload from '@/components/ImageUpload';
 
 export default {
   name: "Category",
   components: {
-    Editor,
+    Editor, Treeselect, IconSelect, ImageUpload
   },
   data() {
     return {
@@ -137,6 +155,8 @@ export default {
       total: 0,
       // 商品分类列表
       list: [],
+      // 商品分类树选项
+      parentCategoryOptions: [],
       // 弹出层标题
       title: "",
       // 是否显示弹出层
@@ -153,11 +173,10 @@ export default {
       form: {},
       // 表单校验
       rules: {
-        pid: [{required: true, message: "父分类编号不能为空", trigger: "blur"}],
+        pid: [{required: true, message: "请选择上级分类", trigger: "blur"}],
         name: [{required: true, message: "分类名称不能为空", trigger: "blur"}],
+        icon: [{required: true, message: "分类图标不能为空", trigger: "blur"}],
         bannerUrl: [{required: true, message: "分类图片不能为空", trigger: "blur"}],
-        sort: [{required: true, message: "分类排序不能为空", trigger: "blur"}],
-        description: [{required: true, message: "分类描述不能为空", trigger: "blur"}],
         status: [{required: true, message: "开启状态不能为空", trigger: "blur"}],
       }
     };
@@ -179,6 +198,30 @@ export default {
         this.loading = false;
       });
     },
+    // 选择图标
+    iconSelected(name) {
+      this.form.icon = name;
+    },
+    /** 转换菜单数据结构 */
+    normalizer(node) {
+      if (node.children && !node.children.length) {
+        delete node.children;
+      }
+      return {
+        id: node.id,
+        label: node.name,
+        children: node.children
+      };
+    },
+    /** 查询分类下拉树结构 */
+    getTreeselect() {
+      listCategory().then(response => {
+        this.parentCategoryOptions = [];
+        const menu = {id: 0, name: '主分类', children: []};
+        menu.children = this.handleTree(response.data, "id", "pid");
+        this.parentCategoryOptions.push(menu);
+      });
+    },
     /** 取消按钮 */
     cancel() {
       this.open = false;
@@ -212,12 +255,14 @@ export default {
     /** 新增按钮操作 */
     handleAdd() {
       this.reset();
+      this.getTreeselect();
       this.open = true;
       this.title = "添加商品分类";
     },
     /** 修改按钮操作 */
     handleUpdate(row) {
       this.reset();
+      this.getTreeselect();
       const id = row.id;
       getCategory(id).then(response => {
         this.form = response.data;