From 17e1a017c9db1a03c52195d0adb6844843169e15 Mon Sep 17 00:00:00 2001
From: YunaiV <>
Date: Sun, 3 Mar 2019 22:54:36 +0800
Subject: [PATCH] =?UTF-8?q?=E5=95=86=E5=93=81=E5=88=86=E7=B1=BB=E9=83=A8?=
 =?UTF-8?q?=E5=88=86=E6=8F=90=E4=BA=A4?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../api/constant/AdminErrorCodeEnum.java      |  2 +-
 product/product-application/pom.xml           | 18 ++++
 .../application/config/MVCConfiguration.java  |  4 +-
 .../AdminsProductCategoryController.java      | 14 +++
 .../users/ProductCategoryController.java      |  8 +-
 .../convert/ProductCategoryConvert.java       |  6 +-
 .../vo/ProductCategorySimpleVO.java           | 40 ++++++++
 .../vo/ProductCategoryTreeNodeVO.java         | 10 ++
 .../application/vo/ProductCategoryVO.java     | 38 +-------
 product/product-service-api/pom.xml           | 13 +++
 .../product/api/ProductCategoryService.java   | 20 ++++
 .../constant/ProductCategoryConstants.java    | 19 ++++
 .../api/constant/ProductErrorCodeEnum.java    | 35 +++++++
 .../api/dto/ProductCategoryAddDTO.java        | 81 ++++++++++++++++
 .../api/dto/ProductCategoryUpdateDTO.java     | 94 +++++++++++++++++++
 .../convert/ProductCategoryConvert.java       |  9 ++
 .../product/dao/ProductCategoryMapper.java    | 10 ++
 .../product/dataobject/ProductCategoryDO.java | 54 ++++-------
 .../service/ProductCategoryServiceImpl.java   | 91 ++++++++++++++++++
 .../main/resources/config/application.yaml    |  4 +-
 .../mapper/ProductCategoryMapper.xml          | 62 +++++++++++-
 .../api/constant/UserErrorCodeEnum.java       |  2 +-
 22 files changed, 547 insertions(+), 87 deletions(-)
 create mode 100644 product/product-application/src/main/java/cn/iocoder/mall/product/application/controller/admins/AdminsProductCategoryController.java
 create mode 100644 product/product-application/src/main/java/cn/iocoder/mall/product/application/vo/ProductCategorySimpleVO.java
 create mode 100644 product/product-application/src/main/java/cn/iocoder/mall/product/application/vo/ProductCategoryTreeNodeVO.java
 create mode 100644 product/product-service-api/src/main/java/cn/iocoder/mall/product/api/constant/ProductCategoryConstants.java
 create mode 100644 product/product-service-api/src/main/java/cn/iocoder/mall/product/api/constant/ProductErrorCodeEnum.java
 create mode 100644 product/product-service-api/src/main/java/cn/iocoder/mall/product/api/dto/ProductCategoryAddDTO.java
 create mode 100644 product/product-service-api/src/main/java/cn/iocoder/mall/product/api/dto/ProductCategoryUpdateDTO.java

diff --git a/admin/admin-service-api/src/main/java/cn/iocoder/mall/admin/api/constant/AdminErrorCodeEnum.java b/admin/admin-service-api/src/main/java/cn/iocoder/mall/admin/api/constant/AdminErrorCodeEnum.java
index 1d8c3d1f..0d5e9e00 100644
--- a/admin/admin-service-api/src/main/java/cn/iocoder/mall/admin/api/constant/AdminErrorCodeEnum.java
+++ b/admin/admin-service-api/src/main/java/cn/iocoder/mall/admin/api/constant/AdminErrorCodeEnum.java
@@ -3,7 +3,7 @@ package cn.iocoder.mall.admin.api.constant;
 /**
  * 错误码枚举类
  *
- * 用户中心,使用 1-002-000-000 段
+ * 管理员系统,使用 1-002-000-000 段
  */
 public enum AdminErrorCodeEnum {
 
diff --git a/product/product-application/pom.xml b/product/product-application/pom.xml
index 685d042d..ba9cd1f7 100644
--- a/product/product-application/pom.xml
+++ b/product/product-application/pom.xml
@@ -32,6 +32,17 @@
             <version>1.0-SNAPSHOT</version>
         </dependency>
 
+        <!--<dependency>-->
+            <!--<groupId>cn.iocoder.mall</groupId>-->
+            <!--<artifactId>user-sdk</artifactId>-->
+            <!--<version>1.0-SNAPSHOT</version>-->
+        <!--</dependency>-->
+        <dependency>
+            <groupId>cn.iocoder.mall</groupId>
+            <artifactId>admin-sdk</artifactId>
+            <version>1.0-SNAPSHOT</version>
+        </dependency>
+
         <dependency>
             <groupId>org.springframework.boot</groupId>
             <artifactId>spring-boot-starter-web</artifactId>
@@ -92,6 +103,13 @@
             <version>2.9.2</version>
         </dependency>
 
+        <dependency>
+            <groupId>javax.servlet</groupId>
+            <artifactId>servlet-api</artifactId>
+            <version>2.5</version>
+            <scope>provided</scope>
+        </dependency>
+
     </dependencies>
 
     <build>
diff --git a/product/product-application/src/main/java/cn/iocoder/mall/product/application/config/MVCConfiguration.java b/product/product-application/src/main/java/cn/iocoder/mall/product/application/config/MVCConfiguration.java
index 20dc7390..4e50c7d4 100644
--- a/product/product-application/src/main/java/cn/iocoder/mall/product/application/config/MVCConfiguration.java
+++ b/product/product-application/src/main/java/cn/iocoder/mall/product/application/config/MVCConfiguration.java
@@ -1,6 +1,8 @@
 package cn.iocoder.mall.product.application.config;
 
+import cn.iocoder.common.framework.config.GlobalExceptionHandler;
 import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Import;
 import org.springframework.web.servlet.config.annotation.EnableWebMvc;
 import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
 import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
@@ -8,7 +10,7 @@ import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
 
 @EnableWebMvc
 @Configuration
-//@Import(value = {GlobalExceptionHandler.class}) // 统一全局返回
+@Import(value = {GlobalExceptionHandler.class}) // 统一全局返回
 public class MVCConfiguration implements WebMvcConfigurer {
 
 //    @Autowired
diff --git a/product/product-application/src/main/java/cn/iocoder/mall/product/application/controller/admins/AdminsProductCategoryController.java b/product/product-application/src/main/java/cn/iocoder/mall/product/application/controller/admins/AdminsProductCategoryController.java
new file mode 100644
index 00000000..c1b3ecf7
--- /dev/null
+++ b/product/product-application/src/main/java/cn/iocoder/mall/product/application/controller/admins/AdminsProductCategoryController.java
@@ -0,0 +1,14 @@
+package cn.iocoder.mall.product.application.controller.admins;
+
+import io.swagger.annotations.Api;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+@RestController
+@RequestMapping("admins/product/category")
+@Api("商品分类")
+public class AdminsProductCategoryController {
+
+    
+
+}
\ No newline at end of file
diff --git a/product/product-application/src/main/java/cn/iocoder/mall/product/application/controller/users/ProductCategoryController.java b/product/product-application/src/main/java/cn/iocoder/mall/product/application/controller/users/ProductCategoryController.java
index f439f743..b7857d24 100644
--- a/product/product-application/src/main/java/cn/iocoder/mall/product/application/controller/users/ProductCategoryController.java
+++ b/product/product-application/src/main/java/cn/iocoder/mall/product/application/controller/users/ProductCategoryController.java
@@ -3,7 +3,7 @@ package cn.iocoder.mall.product.application.controller.users;
 import cn.iocoder.mall.product.api.ProductCategoryService;
 import cn.iocoder.mall.product.api.bo.ProductCategoryBO;
 import cn.iocoder.mall.product.application.convert.ProductCategoryConvert;
-import cn.iocoder.mall.product.application.vo.ProductCategoryVO;
+import cn.iocoder.mall.product.application.vo.ProductCategorySimpleVO;
 import com.alibaba.dubbo.config.annotation.Reference;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiImplicitParam;
@@ -15,8 +15,8 @@ import org.springframework.web.bind.annotation.RestController;
 
 import java.util.List;
 
-@RestController
-@RequestMapping("user/product/category")
+@RestController("productCategoryController_users")
+@RequestMapping("users/product/category")
 @Api("商品分类")
 public class ProductCategoryController {
 
@@ -26,7 +26,7 @@ public class ProductCategoryController {
     @GetMapping
     @ApiOperation("获得指定编号下的子分类的数组")
     @ApiImplicitParam(name = "pid", value = "指定分类编号", required = true, example = "0")
-    public List<ProductCategoryVO> list(@RequestParam("pid") Integer pid) {
+    public List<ProductCategorySimpleVO> list(@RequestParam("pid") Integer pid) {
         List<ProductCategoryBO> result = productCategoryService.getListByPid(pid);
         return ProductCategoryConvert.INSTANCE.convertToVO(result);
     }
diff --git a/product/product-application/src/main/java/cn/iocoder/mall/product/application/convert/ProductCategoryConvert.java b/product/product-application/src/main/java/cn/iocoder/mall/product/application/convert/ProductCategoryConvert.java
index 72a73663..687715db 100644
--- a/product/product-application/src/main/java/cn/iocoder/mall/product/application/convert/ProductCategoryConvert.java
+++ b/product/product-application/src/main/java/cn/iocoder/mall/product/application/convert/ProductCategoryConvert.java
@@ -1,7 +1,7 @@
 package cn.iocoder.mall.product.application.convert;
 
 import cn.iocoder.mall.product.api.bo.ProductCategoryBO;
-import cn.iocoder.mall.product.application.vo.ProductCategoryVO;
+import cn.iocoder.mall.product.application.vo.ProductCategorySimpleVO;
 import org.mapstruct.Mapper;
 import org.mapstruct.Mappings;
 import org.mapstruct.factory.Mappers;
@@ -14,9 +14,9 @@ public interface ProductCategoryConvert {
     ProductCategoryConvert INSTANCE = Mappers.getMapper(ProductCategoryConvert.class);
 
     @Mappings({})
-    ProductCategoryVO convertToVO(ProductCategoryBO category);
+    ProductCategorySimpleVO convertToVO(ProductCategoryBO category);
 
-    List<ProductCategoryVO> convertToVO(List<ProductCategoryBO> categoryList);
+    List<ProductCategorySimpleVO> convertToVO(List<ProductCategoryBO> categoryList);
 
 
 }
diff --git a/product/product-application/src/main/java/cn/iocoder/mall/product/application/vo/ProductCategorySimpleVO.java b/product/product-application/src/main/java/cn/iocoder/mall/product/application/vo/ProductCategorySimpleVO.java
new file mode 100644
index 00000000..49d4cf80
--- /dev/null
+++ b/product/product-application/src/main/java/cn/iocoder/mall/product/application/vo/ProductCategorySimpleVO.java
@@ -0,0 +1,40 @@
+package cn.iocoder.mall.product.application.vo;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+
+@ApiModel("商品分类(简单)")
+public class ProductCategorySimpleVO {
+
+    @ApiModelProperty(value = "分类编号", required = true, example = "1")
+    private Integer id;
+    @ApiModelProperty(value = "分类名", required = true, example = "手机")
+    private String name;
+    @ApiModelProperty(value = "分类图片", notes = "一般情况下,只有根分类才有图片", example = "http://www.iocoder.cn/images/common/wechat_mp_2017_07_31_bak.jpg")
+    private String picUrl;
+
+    public Integer getId() {
+        return id;
+    }
+
+    public void setId(Integer id) {
+        this.id = id;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public String getPicUrl() {
+        return picUrl;
+    }
+
+    public void setPicUrl(String picUrl) {
+        this.picUrl = picUrl;
+    }
+
+}
\ No newline at end of file
diff --git a/product/product-application/src/main/java/cn/iocoder/mall/product/application/vo/ProductCategoryTreeNodeVO.java b/product/product-application/src/main/java/cn/iocoder/mall/product/application/vo/ProductCategoryTreeNodeVO.java
new file mode 100644
index 00000000..532e0401
--- /dev/null
+++ b/product/product-application/src/main/java/cn/iocoder/mall/product/application/vo/ProductCategoryTreeNodeVO.java
@@ -0,0 +1,10 @@
+package cn.iocoder.mall.product.application.vo;
+
+import io.swagger.annotations.ApiModel;
+
+@ApiModel("产品分类树节点 VO")
+public class ProductCategoryTreeNodeVO {
+
+    
+
+}
\ No newline at end of file
diff --git a/product/product-application/src/main/java/cn/iocoder/mall/product/application/vo/ProductCategoryVO.java b/product/product-application/src/main/java/cn/iocoder/mall/product/application/vo/ProductCategoryVO.java
index 910f1bef..5b5c1c70 100644
--- a/product/product-application/src/main/java/cn/iocoder/mall/product/application/vo/ProductCategoryVO.java
+++ b/product/product-application/src/main/java/cn/iocoder/mall/product/application/vo/ProductCategoryVO.java
@@ -1,40 +1,4 @@
 package cn.iocoder.mall.product.application.vo;
 
-import io.swagger.annotations.ApiModel;
-import io.swagger.annotations.ApiModelProperty;
-
-@ApiModel("商品分类")
 public class ProductCategoryVO {
-
-    @ApiModelProperty(value = "分类编号", required = true, example = "1")
-    private Integer id;
-    @ApiModelProperty(value = "分类名", required = true, example = "手机")
-    private String name;
-    @ApiModelProperty(value = "分类图片", notes = "一般情况下,只有根分类才有图片", example = "http://www.iocoder.cn/images/common/wechat_mp_2017_07_31_bak.jpg")
-    private String picUrl;
-
-    public Integer getId() {
-        return id;
-    }
-
-    public void setId(Integer id) {
-        this.id = id;
-    }
-
-    public String getName() {
-        return name;
-    }
-
-    public void setName(String name) {
-        this.name = name;
-    }
-
-    public String getPicUrl() {
-        return picUrl;
-    }
-
-    public void setPicUrl(String picUrl) {
-        this.picUrl = picUrl;
-    }
-
-}
\ No newline at end of file
+}
diff --git a/product/product-service-api/pom.xml b/product/product-service-api/pom.xml
index e85bd9c7..24117697 100644
--- a/product/product-service-api/pom.xml
+++ b/product/product-service-api/pom.xml
@@ -11,4 +11,17 @@
 
     <artifactId>product-service-api</artifactId>
 
+    <dependencies>
+        <dependency>
+            <groupId>cn.iocoder.mall</groupId>
+            <artifactId>common-framework</artifactId>
+            <version>1.0-SNAPSHOT</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.hibernate.validator</groupId>
+            <artifactId>hibernate-validator</artifactId>
+        </dependency>
+    </dependencies>
+
 </project>
\ No newline at end of file
diff --git a/product/product-service-api/src/main/java/cn/iocoder/mall/product/api/ProductCategoryService.java b/product/product-service-api/src/main/java/cn/iocoder/mall/product/api/ProductCategoryService.java
index 90f8e439..55bd1208 100644
--- a/product/product-service-api/src/main/java/cn/iocoder/mall/product/api/ProductCategoryService.java
+++ b/product/product-service-api/src/main/java/cn/iocoder/mall/product/api/ProductCategoryService.java
@@ -1,11 +1,31 @@
 package cn.iocoder.mall.product.api;
 
+import cn.iocoder.common.framework.vo.CommonResult;
 import cn.iocoder.mall.product.api.bo.ProductCategoryBO;
+import cn.iocoder.mall.product.api.dto.ProductCategoryAddDTO;
+import cn.iocoder.mall.product.api.dto.ProductCategoryUpdateDTO;
 
 import java.util.List;
 
 public interface ProductCategoryService {
 
+    /**
+     * @param pid 指定父分类编号
+     * @return 返回指定分类编号的子产品分类们
+     */
     List<ProductCategoryBO> getListByPid(Integer pid);
 
+    /**
+     * @return 返回所有产品分类们
+     */
+    List<ProductCategoryBO> getAll();
+
+    CommonResult<ProductCategoryBO> addProductCategory(Integer adminId, ProductCategoryAddDTO productCategoryAddDTO);
+
+    CommonResult<Boolean> updateProductCategory(Integer adminId, ProductCategoryUpdateDTO productCategoryUpdateDTO);
+
+    CommonResult<Boolean> updateProductCategoryStatus(Integer adminId, Integer productCategoryId, Integer status);
+
+    CommonResult<Boolean> deleteProductCategory(Integer admin, Integer productCategoryId);
+
 }
\ No newline at end of file
diff --git a/product/product-service-api/src/main/java/cn/iocoder/mall/product/api/constant/ProductCategoryConstants.java b/product/product-service-api/src/main/java/cn/iocoder/mall/product/api/constant/ProductCategoryConstants.java
new file mode 100644
index 00000000..1e83e5ad
--- /dev/null
+++ b/product/product-service-api/src/main/java/cn/iocoder/mall/product/api/constant/ProductCategoryConstants.java
@@ -0,0 +1,19 @@
+package cn.iocoder.mall.product.api.constant;
+
+public class ProductCategoryConstants {
+
+    /**
+     * 状态 - 开启
+     */
+    public static final Integer STATUS_ENABLE = 1;
+    /**
+     * 状态 - 关闭
+     */
+    public static final Integer STATUS_DISABLE = 1;
+
+    /**
+     * 父分类编号 - 根节点
+     */
+    public static final Integer PID_ROOT = 0;
+
+}
\ No newline at end of file
diff --git a/product/product-service-api/src/main/java/cn/iocoder/mall/product/api/constant/ProductErrorCodeEnum.java b/product/product-service-api/src/main/java/cn/iocoder/mall/product/api/constant/ProductErrorCodeEnum.java
new file mode 100644
index 00000000..cf84493d
--- /dev/null
+++ b/product/product-service-api/src/main/java/cn/iocoder/mall/product/api/constant/ProductErrorCodeEnum.java
@@ -0,0 +1,35 @@
+package cn.iocoder.mall.product.api.constant;
+
+/**
+ * 错误码枚举类
+ *
+ * 商品系统,使用 1-003-000-000 段
+ */
+public enum ProductErrorCodeEnum {
+
+    // ========== PRODUCT CATEGORY 模块 ==========
+    PRODUCT_CATEGORY_PARENT_NOT_EXISTS(1003001000, "父分类不存在"),
+    PRODUCT_CATEGORY_NOT_EXISTS(1003001001, "商品分类不存在"),
+    PRODUCT_CATEGORY_PARENT_NOT_SELF(1003001002, "不能设置自己为父分类"),
+    PRODUCT_CATEGORY_STATUS_EQUALS(1002002003, "商品分类已经是该状态"),
+    PRODUCT_CATEGORY_DELETE_ONLY_DISABLE(1002002004, "只有关闭的商品分类才可以删除"),
+
+    ;
+
+    private final int code;
+    private final String message;
+
+    ProductErrorCodeEnum(int code, String message) {
+        this.code = code;
+        this.message = message;
+    }
+
+    public int getCode() {
+        return code;
+    }
+
+    public String getMessage() {
+        return message;
+    }
+
+}
\ No newline at end of file
diff --git a/product/product-service-api/src/main/java/cn/iocoder/mall/product/api/dto/ProductCategoryAddDTO.java b/product/product-service-api/src/main/java/cn/iocoder/mall/product/api/dto/ProductCategoryAddDTO.java
new file mode 100644
index 00000000..8c677c7b
--- /dev/null
+++ b/product/product-service-api/src/main/java/cn/iocoder/mall/product/api/dto/ProductCategoryAddDTO.java
@@ -0,0 +1,81 @@
+package cn.iocoder.mall.product.api.dto;
+
+import javax.validation.constraints.NotNull;
+
+/**
+ * 商品分类添加 DTO
+ */
+public class ProductCategoryAddDTO {
+
+    /**
+     * 父分类编号
+     */
+    @NotNull(message = "父分类编号不能为空")
+    private Integer pid;
+    /**
+     * 名称
+     */
+    @NotNull(message = "名称不能为空")
+    private String name;
+    /**
+     * 描述
+     */
+    @NotNull(message = "描述不能为空")
+    private String description;
+    /**
+     * 分类图片
+     */
+    @NotNull(message = "分类图片不能为空")
+    private String picUrl;
+    /**
+     * 排序值
+     */
+    @NotNull(message = "排序值不能为空")
+    private Integer sort;
+
+    public Integer getPid() {
+        return pid;
+    }
+
+    public ProductCategoryAddDTO setPid(Integer pid) {
+        this.pid = pid;
+        return this;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public ProductCategoryAddDTO setName(String name) {
+        this.name = name;
+        return this;
+    }
+
+    public String getDescription() {
+        return description;
+    }
+
+    public ProductCategoryAddDTO setDescription(String description) {
+        this.description = description;
+        return this;
+    }
+
+    public String getPicUrl() {
+        return picUrl;
+    }
+
+    public ProductCategoryAddDTO setPicUrl(String picUrl) {
+        this.picUrl = picUrl;
+        return this;
+    }
+
+    public Integer getSort() {
+        return sort;
+    }
+
+    public ProductCategoryAddDTO setSort(Integer sort) {
+        this.sort = sort;
+        return this;
+    }
+
+}
\ No newline at end of file
diff --git a/product/product-service-api/src/main/java/cn/iocoder/mall/product/api/dto/ProductCategoryUpdateDTO.java b/product/product-service-api/src/main/java/cn/iocoder/mall/product/api/dto/ProductCategoryUpdateDTO.java
new file mode 100644
index 00000000..611b6e13
--- /dev/null
+++ b/product/product-service-api/src/main/java/cn/iocoder/mall/product/api/dto/ProductCategoryUpdateDTO.java
@@ -0,0 +1,94 @@
+package cn.iocoder.mall.product.api.dto;
+
+import javax.validation.constraints.NotNull;
+
+/**
+ * 商品分类更新 DTO
+ */
+public class ProductCategoryUpdateDTO {
+
+    /**
+     * 编号
+     */
+    @NotNull(message = "编号不能为空")
+    private Integer id;
+    /**
+     * 父分类编号
+     */
+    @NotNull(message = "父分类编号不能为空")
+    private Integer pid;
+    /**
+     * 名称
+     */
+    @NotNull(message = "名称不能为空")
+    private String name;
+    /**
+     * 描述
+     */
+    @NotNull(message = "描述不能为空")
+    private String description;
+    /**
+     * 分类图片
+     */
+    @NotNull(message = "分类图片不能为空")
+    private String picUrl;
+    /**
+     * 排序值
+     */
+    @NotNull(message = "排序值不能为空")
+    private Integer sort;
+
+    public Integer getPid() {
+        return pid;
+    }
+
+    public ProductCategoryUpdateDTO setPid(Integer pid) {
+        this.pid = pid;
+        return this;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public ProductCategoryUpdateDTO setName(String name) {
+        this.name = name;
+        return this;
+    }
+
+    public String getDescription() {
+        return description;
+    }
+
+    public ProductCategoryUpdateDTO setDescription(String description) {
+        this.description = description;
+        return this;
+    }
+
+    public String getPicUrl() {
+        return picUrl;
+    }
+
+    public ProductCategoryUpdateDTO setPicUrl(String picUrl) {
+        this.picUrl = picUrl;
+        return this;
+    }
+
+    public Integer getSort() {
+        return sort;
+    }
+
+    public ProductCategoryUpdateDTO setSort(Integer sort) {
+        this.sort = sort;
+        return this;
+    }
+
+    public Integer getId() {
+        return id;
+    }
+
+    public ProductCategoryUpdateDTO setId(Integer id) {
+        this.id = id;
+        return this;
+    }
+}
\ No newline at end of file
diff --git a/product/product-service-impl/src/main/java/cn/iocoder/mall/product/convert/ProductCategoryConvert.java b/product/product-service-impl/src/main/java/cn/iocoder/mall/product/convert/ProductCategoryConvert.java
index 969aa6ab..e43f7660 100644
--- a/product/product-service-impl/src/main/java/cn/iocoder/mall/product/convert/ProductCategoryConvert.java
+++ b/product/product-service-impl/src/main/java/cn/iocoder/mall/product/convert/ProductCategoryConvert.java
@@ -1,6 +1,8 @@
 package cn.iocoder.mall.product.convert;
 
 import cn.iocoder.mall.product.api.bo.ProductCategoryBO;
+import cn.iocoder.mall.product.api.dto.ProductCategoryAddDTO;
+import cn.iocoder.mall.product.api.dto.ProductCategoryUpdateDTO;
 import cn.iocoder.mall.product.dataobject.ProductCategoryDO;
 import org.mapstruct.Mapper;
 import org.mapstruct.Mappings;
@@ -16,6 +18,13 @@ public interface ProductCategoryConvert {
     @Mappings({})
     ProductCategoryBO convertToBO(ProductCategoryDO category);
 
+    @Mappings({})
     List<ProductCategoryBO> convertToBO(List<ProductCategoryDO> categoryList);
 
+    @Mappings({})
+    ProductCategoryDO convert(ProductCategoryAddDTO productCategoryAddDTO);
+
+    @Mappings({})
+    ProductCategoryDO convert(ProductCategoryUpdateDTO productCategoryUpdateDTO);
+
 }
\ No newline at end of file
diff --git a/product/product-service-impl/src/main/java/cn/iocoder/mall/product/dao/ProductCategoryMapper.java b/product/product-service-impl/src/main/java/cn/iocoder/mall/product/dao/ProductCategoryMapper.java
index e1c5a398..1e4dc175 100644
--- a/product/product-service-impl/src/main/java/cn/iocoder/mall/product/dao/ProductCategoryMapper.java
+++ b/product/product-service-impl/src/main/java/cn/iocoder/mall/product/dao/ProductCategoryMapper.java
@@ -12,4 +12,14 @@ public interface ProductCategoryMapper {
     List<ProductCategoryDO> selectListByPidAndStatusOrderBySort(@Param("pid") Integer pid,
                                                                 @Param("status") Integer status);
 
+    List<ProductCategoryDO> selectList();
+
+    ProductCategoryDO selectById(@Param("id") Integer id);
+
+    void insert(ProductCategoryDO productCategoryDO);
+
+    int update(ProductCategoryDO productCategoryDO);
+
+
+
 }
\ No newline at end of file
diff --git a/product/product-service-impl/src/main/java/cn/iocoder/mall/product/dataobject/ProductCategoryDO.java b/product/product-service-impl/src/main/java/cn/iocoder/mall/product/dataobject/ProductCategoryDO.java
index 47690acb..b68542bd 100644
--- a/product/product-service-impl/src/main/java/cn/iocoder/mall/product/dataobject/ProductCategoryDO.java
+++ b/product/product-service-impl/src/main/java/cn/iocoder/mall/product/dataobject/ProductCategoryDO.java
@@ -1,11 +1,11 @@
 package cn.iocoder.mall.product.dataobject;
 
-import java.util.Date;
+import cn.iocoder.common.framework.dataobject.BaseDO;
 
 /**
  * 商品分类
  */
-public class ProductCategoryDO {
+public class ProductCategoryDO extends BaseDO {
 
     public static final Integer STATUS_ENABLE = 1;
 
@@ -35,19 +35,11 @@ public class ProductCategoryDO {
      * 排序值
      */
     private Integer sort;
-    /**
-     * 创建时间
-     */
-    private Date createTime;
-    /**
-     * 最后更新时间
-     */
-    private Date updateTime;
     /**
      * 状态
      *
-     * 1-正常
-     * 2-删除
+     * 1-开启
+     * 2-关闭
      */
     private Integer status;
 
@@ -55,72 +47,62 @@ public class ProductCategoryDO {
         return id;
     }
 
-    public void setId(Integer id) {
+    public ProductCategoryDO setId(Integer id) {
         this.id = id;
+        return this;
     }
 
     public Integer getPid() {
         return pid;
     }
 
-    public void setPid(Integer pid) {
+    public ProductCategoryDO setPid(Integer pid) {
         this.pid = pid;
+        return this;
     }
 
     public String getName() {
         return name;
     }
 
-    public void setName(String name) {
+    public ProductCategoryDO setName(String name) {
         this.name = name;
+        return this;
     }
 
     public String getDescription() {
         return description;
     }
 
-    public void setDescription(String description) {
+    public ProductCategoryDO setDescription(String description) {
         this.description = description;
+        return this;
     }
 
     public String getPicUrl() {
         return picUrl;
     }
 
-    public void setPicUrl(String picUrl) {
+    public ProductCategoryDO setPicUrl(String picUrl) {
         this.picUrl = picUrl;
+        return this;
     }
 
     public Integer getSort() {
         return sort;
     }
 
-    public void setSort(Integer sort) {
+    public ProductCategoryDO setSort(Integer sort) {
         this.sort = sort;
-    }
-
-    public Date getCreateTime() {
-        return createTime;
-    }
-
-    public void setCreateTime(Date createTime) {
-        this.createTime = createTime;
-    }
-
-    public Date getUpdateTime() {
-        return updateTime;
-    }
-
-    public void setUpdateTime(Date updateTime) {
-        this.updateTime = updateTime;
+        return this;
     }
 
     public Integer getStatus() {
         return status;
     }
 
-    public void setStatus(Integer status) {
+    public ProductCategoryDO setStatus(Integer status) {
         this.status = status;
+        return this;
     }
-
 }
\ No newline at end of file
diff --git a/product/product-service-impl/src/main/java/cn/iocoder/mall/product/service/ProductCategoryServiceImpl.java b/product/product-service-impl/src/main/java/cn/iocoder/mall/product/service/ProductCategoryServiceImpl.java
index 8d6367d7..1a0915e7 100644
--- a/product/product-service-impl/src/main/java/cn/iocoder/mall/product/service/ProductCategoryServiceImpl.java
+++ b/product/product-service-impl/src/main/java/cn/iocoder/mall/product/service/ProductCategoryServiceImpl.java
@@ -1,13 +1,21 @@
 package cn.iocoder.mall.product.service;
 
+import cn.iocoder.common.framework.dataobject.BaseDO;
+import cn.iocoder.common.framework.util.ServiceExceptionUtil;
+import cn.iocoder.common.framework.vo.CommonResult;
 import cn.iocoder.mall.product.api.ProductCategoryService;
 import cn.iocoder.mall.product.api.bo.ProductCategoryBO;
+import cn.iocoder.mall.product.api.constant.ProductCategoryConstants;
+import cn.iocoder.mall.product.api.constant.ProductErrorCodeEnum;
+import cn.iocoder.mall.product.api.dto.ProductCategoryAddDTO;
+import cn.iocoder.mall.product.api.dto.ProductCategoryUpdateDTO;
 import cn.iocoder.mall.product.convert.ProductCategoryConvert;
 import cn.iocoder.mall.product.dao.ProductCategoryMapper;
 import cn.iocoder.mall.product.dataobject.ProductCategoryDO;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
+import java.util.Date;
 import java.util.List;
 
 @Service // 实际上不用添加。添加的原因是,必须 Spring 报错提示
@@ -23,4 +31,87 @@ public class ProductCategoryServiceImpl implements ProductCategoryService {
         return ProductCategoryConvert.INSTANCE.convertToBO(categoryList);
     }
 
+    @Override
+    public List<ProductCategoryBO> getAll() {
+        List<ProductCategoryDO> categoryList = productCategoryMapper.selectList();
+        return ProductCategoryConvert.INSTANCE.convertToBO(categoryList);
+    }
+
+    @Override
+    public CommonResult<ProductCategoryBO> addProductCategory(Integer adminId, ProductCategoryAddDTO productCategoryAddDTO) {
+        // 校验父分类是否存在
+        if (ProductCategoryConstants.PID_ROOT.equals(productCategoryAddDTO.getPid())
+            && productCategoryMapper.selectById(productCategoryAddDTO.getPid()) == null) {
+            return ServiceExceptionUtil.error(ProductErrorCodeEnum.PRODUCT_CATEGORY_PARENT_NOT_EXISTS.getCode());
+        }
+        // 保存到数据库
+        ProductCategoryDO productCategory = ProductCategoryConvert.INSTANCE.convert(productCategoryAddDTO)
+                .setStatus(ProductCategoryConstants.STATUS_ENABLE);
+        productCategory.setCreateTime(new Date()).setDeleted(BaseDO.DELETED_NO);
+        productCategoryMapper.insert(productCategory);
+        // TODO 操作日志
+        // 返回成功
+        return CommonResult.success(ProductCategoryConvert.INSTANCE.convertToBO(productCategory));
+    }
+
+    @Override
+    public CommonResult<Boolean> updateProductCategory(Integer adminId, ProductCategoryUpdateDTO productCategoryUpdateDTO) {
+        // 校验分类是否存在
+        if (productCategoryMapper.selectById(productCategoryUpdateDTO.getId()) == null) {
+            return ServiceExceptionUtil.error(ProductErrorCodeEnum.PRODUCT_CATEGORY_NOT_EXISTS.getCode());
+        }
+        // 校验不能设置自己为父分类
+        if (productCategoryUpdateDTO.getId().equals(productCategoryUpdateDTO.getPid())) {
+            return ServiceExceptionUtil.error(ProductErrorCodeEnum.PRODUCT_CATEGORY_PARENT_NOT_SELF.getCode());
+        }
+        // 校验父分类是否存在
+        if (ProductCategoryConstants.PID_ROOT.equals(productCategoryUpdateDTO.getPid())
+                && productCategoryMapper.selectById(productCategoryUpdateDTO.getPid()) == null) {
+            return ServiceExceptionUtil.error(ProductErrorCodeEnum.PRODUCT_CATEGORY_PARENT_NOT_EXISTS.getCode());
+        }
+        // 更新到数据库
+        ProductCategoryDO updateProductCategory = ProductCategoryConvert.INSTANCE.convert(productCategoryUpdateDTO);
+        productCategoryMapper.update(updateProductCategory);
+        // TODO 操作日志
+        return CommonResult.success(true);
+    }
+
+    @Override
+    public CommonResult<Boolean> updateProductCategoryStatus(Integer adminId, Integer productCategoryId, Integer status) {
+        // 校验分类是否存在
+        ProductCategoryDO productCategory = productCategoryMapper.selectById(productCategoryId);
+        if (productCategory == null) {
+            return ServiceExceptionUtil.error(ProductErrorCodeEnum.PRODUCT_CATEGORY_NOT_EXISTS.getCode());
+        }
+        // 如果状态相同,则返回错误
+        if (productCategory.getStatus().equals(status)) {
+            return ServiceExceptionUtil.error(ProductErrorCodeEnum.PRODUCT_CATEGORY_STATUS_EQUALS.getCode());
+        }
+        // 更新商品分类
+        ProductCategoryDO updateProductCategory = new ProductCategoryDO().setStatus(status);
+        productCategoryMapper.update(updateProductCategory);
+        // TODO 操作日志
+        return CommonResult.success(true);
+    }
+
+    @Override
+    public CommonResult<Boolean> deleteProductCategory(Integer admin, Integer productCategoryId) {
+        // 校验分类是否存在
+        ProductCategoryDO productCategory = productCategoryMapper.selectById(productCategoryId);
+        if (productCategory == null) {
+            return ServiceExceptionUtil.error(ProductErrorCodeEnum.PRODUCT_CATEGORY_NOT_EXISTS.getCode());
+        }
+        // 只有禁用的商品分类才可以删除
+        if (ProductCategoryConstants.STATUS_ENABLE.equals(productCategory.getStatus())) {
+            return ServiceExceptionUtil.error(ProductErrorCodeEnum.PRODUCT_CATEGORY_DELETE_ONLY_DISABLE.getCode());
+        }
+        // TODO 芋艿:考虑下,是否需要判断下该分类下是否有商品
+        // 标记删除商品分类
+        ProductCategoryDO updateProductCategory = new ProductCategoryDO();
+        updateProductCategory.setDeleted(BaseDO.DELETED_YES);
+        productCategoryMapper.update(updateProductCategory);
+        // TODO 操作日志
+        return CommonResult.success(true);
+    }
+
 }
\ No newline at end of file
diff --git a/product/product-service-impl/src/main/resources/config/application.yaml b/product/product-service-impl/src/main/resources/config/application.yaml
index 80f856a1..af5940f4 100644
--- a/product/product-service-impl/src/main/resources/config/application.yaml
+++ b/product/product-service-impl/src/main/resources/config/application.yaml
@@ -1,10 +1,10 @@
 spring:
   # datasource
   datasource:
-    url: jdbc:mysql://127.0.0.1:33061/mall_product?useSSL=false
+    url: jdbc:mysql://180.167.213.26:13306/mall_product?useSSL=false&useUnicode=true&characterEncoding=UTF-8
     driver-class-name: com.mysql.jdbc.Driver
     username: root
-    password: 123456
+    password: ${MALL_MYSQL_PASSWORD}
 
 # mybatis
 mybatis:
diff --git a/product/product-service-impl/src/main/resources/mapper/ProductCategoryMapper.xml b/product/product-service-impl/src/main/resources/mapper/ProductCategoryMapper.xml
index 52f26f49..7f8023b5 100644
--- a/product/product-service-impl/src/main/resources/mapper/ProductCategoryMapper.xml
+++ b/product/product-service-impl/src/main/resources/mapper/ProductCategoryMapper.xml
@@ -2,14 +2,72 @@
 <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
 <mapper namespace="cn.iocoder.mall.product.dao.ProductCategoryMapper">
 
+    <sql id="FIELDS">
+        id, pid, name, descrption, pic_url,
+        sort, status, create_time
+    </sql>
+
     <select id="selectListByPidAndStatusOrderBySort" resultType="ProductCategoryDO">
         SELECT
-          id, name, pic_url, sort
+            <include refid="FIELDS" />
         FROM product_category
         WHERE pid = #{pid}
         AND status = #{status}
+        AND deleted = 0
         ORDER BY sort ASC
     </select>
 
+    <select id="selectList" resultType="ProductCategoryDO">
+        SELECT
+          <include refid="FIELDS" />
+        FROM product_category
+        WHERE deleted = 0
+    </select>
+
+    <select id="selectById" parameterType="Integer" resultType="ProductCategoryDO">
+        SELECT
+          <include refid="FIELDS" />
+        FROM product_category
+        WHERE id = #{id}
+        AND deleted = 0
+    </select>
+
+    <insert id="insert" parameterType="ProductCategoryDO" useGeneratedKeys="true" keyColumn="id" keyProperty="id">
+        INSERT INTO product_category (
+          pid, name, description, pic_url, sort,
+          status, create_time, deleted
+        ) VALUES (
+          #{pid}, #{name}, #{description}, #{picUrl}, #{sort},
+          #{status}, #{createTime}, #{deleted}
+        )
+    </insert>
+
+    <update id="update" parameterType="ProductCategoryDO">
+        UPDATE resource
+        <set>
+            <if test="pid != null">
+                pid = #{pid},
+            </if>
+            <if test="name != null">
+                name = #{name},
+            </if>
+            <if test="description != null">
+                description = #{description},
+            </if>
+            <if test="picUrl != null">
+                pic_url = #{picUrl},
+            </if>
+            <if test="sort != null">
+                sort = #{sort},
+            </if>
+            <if test="status != null">
+                status = #{status},
+            </if>
+            <if test="deleted != null">
+                deleted = #{deleted}
+            </if>
+        </set>
+        WHERE id = #{id}
+    </update>
 
-</mapper>
+</mapper>
\ No newline at end of file
diff --git a/user/user-service-api/src/main/java/cn/iocoder/mall/user/service/api/constant/UserErrorCodeEnum.java b/user/user-service-api/src/main/java/cn/iocoder/mall/user/service/api/constant/UserErrorCodeEnum.java
index 281852c6..7577a643 100644
--- a/user/user-service-api/src/main/java/cn/iocoder/mall/user/service/api/constant/UserErrorCodeEnum.java
+++ b/user/user-service-api/src/main/java/cn/iocoder/mall/user/service/api/constant/UserErrorCodeEnum.java
@@ -3,7 +3,7 @@ package cn.iocoder.mall.user.service.api.constant;
 /**
  * 错误码枚举类
  *
- * 用户中心,使用 1-001-000-000 段
+ * 用户系统,使用 1-001-000-000 段
  */
 public enum UserErrorCodeEnum {
 
-- 
2.17.1