diff --git a/pom.xml b/pom.xml index 0ba239d5d..e3c5072ab 100644 --- a/pom.xml +++ b/pom.xml @@ -18,7 +18,7 @@ yudao-module-system yudao-module-infra yudao-module-pay - yudao-module-market + yudao-module-mall ${project.artifactId} diff --git a/sql/mall.sql b/sql/mall.sql new file mode 100644 index 000000000..825d43e36 --- /dev/null +++ b/sql/mall.sql @@ -0,0 +1,55 @@ +/* + Navicat Premium Data Transfer + + Source Server : 127.0.0.1 + Source Server Type : MySQL + Source Server Version : 80026 + Source Host : localhost:3306 + Source Schema : ruoyi-vue-pro + + Target Server Type : MySQL + Target Server Version : 80026 + File Encoding : 65001 + + Date: 05/02/2022 00:50:30 +*/ +SET +FOREIGN_KEY_CHECKS = 0; +SET NAMES utf8mb4; + +-- ---------------------------- +-- Table structure for product_category +-- ---------------------------- +DROP TABLE IF EXISTS `product_category`; +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) NOT NULL DEFAULT '#' COMMENT '分类图标', + `banner_url` varchar(255) 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 '创建时间', + `updater` varchar(64) DEFAULT '' COMMENT '更新者', + `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', + `tenant_id` bigint NOT NULL DEFAULT '0' COMMENT '租户编号', + PRIMARY KEY (`id`) USING BTREE +) ENGINE=InnoDB COMMENT='商品分类'; + +-- TODO 父级菜单的 id 处理 +INSERT INTO `system_menu` (`id`, `name`, `permission`, `menu_type`, `sort`, `parent_id`, `path`, `icon`, `component`, `status`) VALUES (2000, '商城', '', 1, 1, 0, '/mall', 'merchant', NULL, 0); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `menu_type`, `sort`, `parent_id`, `path`, `icon`, `component`, `status`) VALUES (2001, '商品管理', '', 1, 1, 2000, 'product', 'dict', NULL, 0); +-- 菜单 SQL +INSERT INTO `system_menu`(`name`, `permission`, `menu_type`, `sort`, `parent_id`, `path`, `icon`, `component`, `status`) VALUES ('商品分类管理', '', 2, 0, 2001, 'category', '', 'mall/product/category/index', 0); +-- 按钮父菜单ID +SELECT @parentId := LAST_INSERT_ID(); +-- 按钮 SQL +INSERT INTO `system_menu`(`name`, `permission`, `menu_type`, `sort`, `parent_id`, `path`, `icon`, `component`, `status`) VALUES ('商品分类查询', 'product:category:query', 3, 1, @parentId, '', '', '', 0); +INSERT INTO `system_menu`(`name`, `permission`, `menu_type`, `sort`, `parent_id`, `path`, `icon`, `component`, `status`) VALUES ('商品分类创建', 'product:category:create', 3, 2, @parentId, '', '', '', 0); +INSERT INTO `system_menu`(`name`, `permission`, `menu_type`, `sort`, `parent_id`, `path`, `icon`, `component`, `status`) VALUES ('商品分类更新', 'product:category:update', 3, 3, @parentId, '', '', '', 0); +INSERT INTO `system_menu`(`name`, `permission`, `menu_type`, `sort`, `parent_id`, `path`, `icon`, `component`, `status`) VALUES ('商品分类删除', 'product:category:delete', 3, 4, @parentId, '', '', '', 0); +INSERT INTO `system_menu`(`name`, `permission`, `menu_type`, `sort`, `parent_id`, `path`, `icon`, `component`, `status`) VALUES ('商品分类导出', 'product:category:export', 3, 5, @parentId, '', '', '', 0); diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/FileController.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/FileController.java index e3d810dec..f53b45ac8 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/FileController.java +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/FileController.java @@ -1,5 +1,6 @@ package cn.iocoder.yudao.module.infra.controller.admin.file; +import cn.hutool.core.date.DateUtil; import cn.hutool.core.io.IoUtil; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageResult; @@ -23,6 +24,7 @@ import org.springframework.web.multipart.MultipartFile; import javax.annotation.Resource; import javax.servlet.http.HttpServletResponse; import javax.validation.Valid; +import java.util.Date; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; @@ -47,6 +49,17 @@ public class FileController { return success(fileService.createFile(path, IoUtil.readBytes(file.getInputStream()))); } + @PostMapping("/simple-upload") + @ApiOperation("简单上传文件") + @ApiImplicitParams({ + @ApiImplicitParam(name = "file", value = "文件附件", required = true, dataTypeClass = MultipartFile.class), + }) + public CommonResult uploadFile(@RequestParam("file") MultipartFile file) throws Exception { + String path = DateUtil.format(new Date(), "yyyy/MM/dd/") + file.getOriginalFilename(); + String file1 = fileService.createFile(path, IoUtil.readBytes(file.getInputStream())); + return success(file1); + } + @DeleteMapping("/delete") @ApiOperation("删除文件") @ApiImplicitParam(name = "id", value = "编号", required = true, dataTypeClass = Long.class) diff --git a/yudao-module-mall/pom.xml b/yudao-module-mall/pom.xml index 448986c6e..866874852 100644 --- a/yudao-module-mall/pom.xml +++ b/yudao-module-mall/pom.xml @@ -9,7 +9,7 @@ 4.0.0 - yudao-module-market + yudao-module-mall pom ${project.artifactId} @@ -21,6 +21,8 @@ yudao-module-market-api yudao-module-market-biz + yudao-module-product-api + yudao-module-product-biz diff --git a/yudao-module-mall/yudao-module-market-api/pom.xml b/yudao-module-mall/yudao-module-market-api/pom.xml index c83179632..fef3428fc 100644 --- a/yudao-module-mall/yudao-module-market-api/pom.xml +++ b/yudao-module-mall/yudao-module-market-api/pom.xml @@ -3,8 +3,8 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> - yudao-module-market cn.iocoder.boot + yudao-module-mall ${revision} 4.0.0 diff --git a/yudao-module-mall/yudao-module-market-biz/pom.xml b/yudao-module-mall/yudao-module-market-biz/pom.xml index 0e3a0490e..e7fa33e9d 100644 --- a/yudao-module-mall/yudao-module-market-biz/pom.xml +++ b/yudao-module-mall/yudao-module-market-biz/pom.xml @@ -3,8 +3,8 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> - yudao-module-market cn.iocoder.boot + yudao-module-mall ${revision} 4.0.0 diff --git a/yudao-module-mall/yudao-module-product-api/pom.xml b/yudao-module-mall/yudao-module-product-api/pom.xml new file mode 100644 index 000000000..7eb38008a --- /dev/null +++ b/yudao-module-mall/yudao-module-product-api/pom.xml @@ -0,0 +1,27 @@ + + + 4.0.0 + + cn.iocoder.boot + yudao-module-mall + ${revision} + + + yudao-module-product-api + jar + + ${project.artifactId} + + product 模块 API,暴露给其它模块调用 + + + + + cn.iocoder.boot + yudao-common + + + + \ No newline at end of file diff --git a/yudao-module-mall/yudao-module-product-api/src/main/cn/iocoder/yudao/module/product/api/package-info.java b/yudao-module-mall/yudao-module-product-api/src/main/cn/iocoder/yudao/module/product/api/package-info.java new file mode 100644 index 000000000..b19092853 --- /dev/null +++ b/yudao-module-mall/yudao-module-product-api/src/main/cn/iocoder/yudao/module/product/api/package-info.java @@ -0,0 +1,4 @@ +/** + * 占位 + */ +package cn.iocoder.yudao.module.product.api; \ No newline at end of file diff --git a/yudao-module-mall/yudao-module-product-api/src/main/cn/iocoder/yudao/module/product/enums/ErrorCodeConstants.java b/yudao-module-mall/yudao-module-product-api/src/main/cn/iocoder/yudao/module/product/enums/ErrorCodeConstants.java new file mode 100644 index 000000000..b8c671fc5 --- /dev/null +++ b/yudao-module-mall/yudao-module-product-api/src/main/cn/iocoder/yudao/module/product/enums/ErrorCodeConstants.java @@ -0,0 +1,14 @@ +package cn.iocoder.yudao.module.product.enums; + +import cn.iocoder.yudao.framework.common.exception.ErrorCode; + +/** + * product 错误码枚举类 + *

+ * product 系统,使用 1-008-000-000 段 + */ +public interface ErrorCodeConstants { + + // ========== 商品分类相关 1008001000============ + ErrorCode CATEGORY_NOT_EXISTS = new ErrorCode(1008001000, "商品分类不存在"); +} diff --git a/yudao-module-mall/yudao-module-product-biz/pom.xml b/yudao-module-mall/yudao-module-product-biz/pom.xml new file mode 100644 index 000000000..a06f8937c --- /dev/null +++ b/yudao-module-mall/yudao-module-product-biz/pom.xml @@ -0,0 +1,67 @@ + + + 4.0.0 + + cn.iocoder.boot + yudao-module-mall + ${revision} + + + yudao-module-product-biz + jar + + ${project.artifactId} + + product 模块,主要实现商品相关功能 + 例如:品牌、商品分类、spu、sku等功能。 + + + + + + cn.iocoder.boot + yudao-module-product-api + ${revision} + + + + + cn.iocoder.boot + yudao-spring-boot-starter-biz-operatelog + + + cn.iocoder.boot + yudao-spring-boot-starter-biz-weixin + + + cn.iocoder.boot + yudao-spring-boot-starter-biz-tenant + + + + + cn.iocoder.boot + yudao-spring-boot-starter-web + + + cn.iocoder.boot + yudao-spring-boot-starter-excel + + + + + cn.iocoder.boot + yudao-spring-boot-starter-mybatis + + + + + cn.iocoder.boot + yudao-spring-boot-starter-test + + + + + \ No newline at end of file diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/category/CategoryController.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/category/CategoryController.java new file mode 100644 index 000000000..9e5614a87 --- /dev/null +++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/category/CategoryController.java @@ -0,0 +1,108 @@ +package cn.iocoder.yudao.module.product.controller.admin.category; + +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +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 cn.iocoder.yudao.module.product.controller.admin.category.vo.*; +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.Comparator; +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 +@RequestMapping("/product/category") +@Validated +public class CategoryController { + + @Resource + private CategoryService categoryService; + + @PostMapping("/create") + @ApiOperation("创建商品分类") + @PreAuthorize("@ss.hasPermission('product:category:create')") + public CommonResult createCategory(@Valid @RequestBody CategoryCreateReqVO createReqVO) { + return success(categoryService.createCategory(createReqVO)); + } + + @PutMapping("/update") + @ApiOperation("更新商品分类") + @PreAuthorize("@ss.hasPermission('product:category:update')") + public CommonResult updateCategory(@Valid @RequestBody CategoryUpdateReqVO updateReqVO) { + categoryService.updateCategory(updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @ApiOperation("删除商品分类") + @ApiImplicitParam(name = "id", value = "编号", required = true, dataTypeClass = Long.class) + @PreAuthorize("@ss.hasPermission('product:category:delete')") + public CommonResult deleteCategory(@RequestParam("id") Long id) { + categoryService.deleteCategory(id); + return success(true); + } + + @GetMapping("/get") + @ApiOperation("获得商品分类") + @ApiImplicitParam(name = "id", value = "编号", required = true, example = "1024", dataTypeClass = Long.class) + @PreAuthorize("@ss.hasPermission('product:category:query')") + public CommonResult getCategory(@RequestParam("id") Long id) { + CategoryDO category = categoryService.getCategory(id); + return success(CategoryConvert.INSTANCE.convert(category)); + } + + @GetMapping("/listByIds") + @ApiOperation("获得商品分类列表") + @PreAuthorize("@ss.hasPermission('product:category:query')") + public CommonResult> getCategoryList(@RequestParam("ids") Collection ids) { + List list = categoryService.getCategoryList(ids); + return success(CategoryConvert.INSTANCE.convertList(list)); + } + + @GetMapping("/listByQuery") + @ApiOperation("获得商品分类列表") + @PreAuthorize("@ss.hasPermission('product:category:query')") + public CommonResult> listByQuery(@Valid CategoryTreeListReqVO treeListReqVO) { + List list = categoryService.getCategoryTreeList(treeListReqVO); + list.sort(Comparator.comparing(CategoryDO::getSort)); + return success(CategoryConvert.INSTANCE.convertList(list)); + } + + @GetMapping("/page") + @ApiOperation("获得商品分类分页") + @PreAuthorize("@ss.hasPermission('product:category:query')") + public CommonResult> getCategoryPage(@Valid CategoryPageReqVO pageVO) { + PageResult pageResult = categoryService.getCategoryPage(pageVO); + return success(CategoryConvert.INSTANCE.convertPage(pageResult)); + } + + @GetMapping("/export-excel") + @ApiOperation("导出商品分类 Excel") + @PreAuthorize("@ss.hasPermission('product:category:export')") + @OperateLog(type = EXPORT) + public void exportCategoryExcel(@Valid CategoryExportReqVO exportReqVO, + HttpServletResponse response) throws IOException { + List list = categoryService.getCategoryList(exportReqVO); + // 导出 Excel + List datas = CategoryConvert.INSTANCE.convertList02(list); + ExcelUtils.write(response, "商品分类.xls", "数据", CategoryExcelVO.class, datas); + } + +} diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/category/vo/CategoryBaseVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/category/vo/CategoryBaseVO.java new file mode 100644 index 000000000..d4c2ebb8b --- /dev/null +++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/category/vo/CategoryBaseVO.java @@ -0,0 +1,42 @@ +package cn.iocoder.yudao.module.product.controller.admin.category.vo; + +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; + +/** +* 商品分类 Base VO,提供给添加、修改、详细的子 VO 使用 +* 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成 +*/ +@Data +public class CategoryBaseVO { + + @ApiModelProperty(value = "父分类编号", required = true, example = "1") + @NotNull(message = "父分类编号不能为空") + private Long pid; + + @ApiModelProperty(value = "分类名称", required = true, example = "办公文具") + @NotBlank(message = "分类名称不能为空") + private String name; + + @ApiModelProperty(value = "分类图标") + @NotBlank(message = "分类图标不能为空") + private String icon; + + @ApiModelProperty(value = "分类图片", required = true) + @NotBlank(message = "分类图片不能为空") + private String bannerUrl; + + @ApiModelProperty(value = "分类排序", required = true, example = "1") + private Integer sort; + + @ApiModelProperty(value = "分类描述", required = true, example = "描述") + private String description; + + @ApiModelProperty(value = "开启状态", required = true, example = "0") + @NotNull(message = "开启状态不能为空") + private Integer status; + +} diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/category/vo/CategoryCreateReqVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/category/vo/CategoryCreateReqVO.java new file mode 100644 index 000000000..ce583f08b --- /dev/null +++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/category/vo/CategoryCreateReqVO.java @@ -0,0 +1,14 @@ +package cn.iocoder.yudao.module.product.controller.admin.category.vo; + +import lombok.*; +import java.util.*; +import io.swagger.annotations.*; +import javax.validation.constraints.*; + +@ApiModel("管理后台 - 商品分类创建 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class CategoryCreateReqVO extends CategoryBaseVO { + +} diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/category/vo/CategoryExcelVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/category/vo/CategoryExcelVO.java new file mode 100644 index 000000000..ae754e42d --- /dev/null +++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/category/vo/CategoryExcelVO.java @@ -0,0 +1,48 @@ +package cn.iocoder.yudao.module.product.controller.admin.category.vo; + +import lombok.*; +import java.util.*; +import io.swagger.annotations.*; + +import com.alibaba.excel.annotation.ExcelProperty; +import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; +import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; + + +/** + * 商品分类 Excel VO + * + * @author 芋道源码 + */ +@Data +public class CategoryExcelVO { + + @ExcelProperty("分类编号") + private Long id; + + @ExcelProperty("父分类编号") + private Long pid; + + @ExcelProperty("分类名称") + private String name; + + @ExcelProperty("分类图标") + private String icon; + + @ExcelProperty("分类图片") + private String bannerUrl; + + @ExcelProperty("分类排序") + private Integer sort; + + @ExcelProperty("分类描述") + private String description; + + @ExcelProperty(value = "开启状态", converter = DictConvert.class) + @DictFormat("common_status") // TODO 代码优化:建议设置到对应的 XXXDictTypeConstants 枚举类中 + private Integer status; + + @ExcelProperty("创建时间") + private Date createTime; + +} diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/category/vo/CategoryExportReqVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/category/vo/CategoryExportReqVO.java new file mode 100644 index 000000000..c1e23b3ed --- /dev/null +++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/category/vo/CategoryExportReqVO.java @@ -0,0 +1,30 @@ +package cn.iocoder.yudao.module.product.controller.admin.category.vo; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import org.springframework.format.annotation.DateTimeFormat; + +import java.util.Date; + +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; + +@ApiModel(value = "管理后台 - 商品分类 Excel 导出 Request VO", description = "参数和 CategoryPageReqVO 是一致的") +@Data +public class CategoryExportReqVO { + + @ApiModelProperty(value = "分类名称", example = "办公文具") + private String name; + + @ApiModelProperty(value = "开启状态", example = "0") + private Integer status; + + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + @ApiModelProperty(value = "开始创建时间") + private Date beginCreateTime; + + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + @ApiModelProperty(value = "结束创建时间") + private Date endCreateTime; + +} diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/category/vo/CategoryPageReqVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/category/vo/CategoryPageReqVO.java new file mode 100644 index 000000000..d824b8bd8 --- /dev/null +++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/category/vo/CategoryPageReqVO.java @@ -0,0 +1,35 @@ +package cn.iocoder.yudao.module.product.controller.admin.category.vo; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; +import org.springframework.format.annotation.DateTimeFormat; + +import java.util.Date; + +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; + +@ApiModel("管理后台 - 商品分类分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class CategoryPageReqVO extends PageParam { + + @ApiModelProperty(value = "分类名称", example = "办公文具") + private String name; + + @ApiModelProperty(value = "开启状态", example = "0") + private Integer status; + + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + @ApiModelProperty(value = "开始创建时间") + private Date beginCreateTime; + + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + @ApiModelProperty(value = "结束创建时间") + private Date endCreateTime; + +} diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/category/vo/CategoryRespVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/category/vo/CategoryRespVO.java new file mode 100644 index 000000000..e7d0b2238 --- /dev/null +++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/category/vo/CategoryRespVO.java @@ -0,0 +1,19 @@ +package cn.iocoder.yudao.module.product.controller.admin.category.vo; + +import lombok.*; +import java.util.*; +import io.swagger.annotations.*; + +@ApiModel("管理后台 - 商品分类 Response VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class CategoryRespVO extends CategoryBaseVO { + + @ApiModelProperty(value = "分类编号", required = true, example = "2") + private Long id; + + @ApiModelProperty(value = "创建时间", required = true) + private Date createTime; + +} diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/category/vo/CategoryTreeListReqVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/category/vo/CategoryTreeListReqVO.java new file mode 100644 index 000000000..12256efd3 --- /dev/null +++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/category/vo/CategoryTreeListReqVO.java @@ -0,0 +1,29 @@ +package cn.iocoder.yudao.module.product.controller.admin.category.vo; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import org.springframework.format.annotation.DateTimeFormat; + +import java.util.Date; + +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; + +@Data +@ApiModel(value = "管理后台 - 商品分类列表查询 Request VO", description = "参数和 CategoryPageReqVO 是一致的") +public class CategoryTreeListReqVO extends CategoryExportReqVO { + + @ApiModelProperty(value = "分类名称", example = "办公文具") + private String name; + + @ApiModelProperty(value = "开启状态", example = "0") + private Integer status; + + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + @ApiModelProperty(value = "开始创建时间") + private Date beginCreateTime; + + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + @ApiModelProperty(value = "结束创建时间") + private Date endCreateTime; +} diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/category/vo/CategoryUpdateReqVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/category/vo/CategoryUpdateReqVO.java new file mode 100644 index 000000000..13ee83c1e --- /dev/null +++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/category/vo/CategoryUpdateReqVO.java @@ -0,0 +1,18 @@ +package cn.iocoder.yudao.module.product.controller.admin.category.vo; + +import lombok.*; +import java.util.*; +import io.swagger.annotations.*; +import javax.validation.constraints.*; + +@ApiModel("管理后台 - 商品分类更新 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class CategoryUpdateReqVO extends CategoryBaseVO { + + @ApiModelProperty(value = "分类编号", required = true, example = "2") + @NotNull(message = "分类编号不能为空") + private Long id; + +} diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/convert/category/CategoryConvert.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/convert/category/CategoryConvert.java new file mode 100644 index 000000000..2b2cfe99c --- /dev/null +++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/convert/category/CategoryConvert.java @@ -0,0 +1,34 @@ +package cn.iocoder.yudao.module.product.convert.category; + +import java.util.*; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; + +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; +import cn.iocoder.yudao.module.product.controller.admin.category.vo.*; +import cn.iocoder.yudao.module.product.dal.dataobject.category.CategoryDO; + +/** + * 商品分类 Convert + * + * @author 芋道源码 + */ +@Mapper +public interface CategoryConvert { + + CategoryConvert INSTANCE = Mappers.getMapper(CategoryConvert.class); + + CategoryDO convert(CategoryCreateReqVO bean); + + CategoryDO convert(CategoryUpdateReqVO bean); + + CategoryRespVO convert(CategoryDO bean); + + List convertList(List list); + + PageResult convertPage(PageResult page); + + List convertList02(List list); + +} diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/category/CategoryDO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/category/CategoryDO.java new file mode 100644 index 000000000..bbebfc11c --- /dev/null +++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/category/CategoryDO.java @@ -0,0 +1,58 @@ +package cn.iocoder.yudao.module.product.dal.dataobject.category; + +import lombok.*; +import java.util.*; +import com.baomidou.mybatisplus.annotation.*; +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; + +/** + * 商品分类 DO + * + * @author 芋道源码 + */ +@TableName("product_category") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class CategoryDO extends BaseDO { + + /** + * 分类编号 + */ + @TableId + private Long id; + /** + * 父分类编号 + */ + private Long pid; + /** + * 分类名称 + */ + private String name; + /** + * 分类图标 + */ + private String icon; + /** + * 分类图片 + */ + private String bannerUrl; + /** + * 分类排序 + */ + private Integer sort; + /** + * 分类描述 + */ + private String description; + /** + * 开启状态 + * + * 枚举 {@link TODO common_status 对应的类} + */ + private Integer status; + +} diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/category/CategoryMapper.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/category/CategoryMapper.java new file mode 100644 index 000000000..109f1ff54 --- /dev/null +++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/category/CategoryMapper.java @@ -0,0 +1,37 @@ +package cn.iocoder.yudao.module.product.dal.mysql.category; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +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.dal.dataobject.category.CategoryDO; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +/** + * 商品分类 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface CategoryMapper extends BaseMapperX { + + default PageResult selectPage(CategoryPageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .likeIfPresent(CategoryDO::getName, reqVO.getName()) + .eqIfPresent(CategoryDO::getStatus, reqVO.getStatus()) + .betweenIfPresent(CategoryDO::getCreateTime, reqVO.getBeginCreateTime(), reqVO.getEndCreateTime()) + .orderByDesc(CategoryDO::getId)); + } + + default List selectList(CategoryExportReqVO reqVO) { + return selectList(new LambdaQueryWrapperX() + .likeIfPresent(CategoryDO::getName, reqVO.getName()) + .eqIfPresent(CategoryDO::getStatus, reqVO.getStatus()) + .betweenIfPresent(CategoryDO::getCreateTime, reqVO.getBeginCreateTime(), reqVO.getEndCreateTime()) + .orderByDesc(CategoryDO::getId)); + } + +} diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/package-info.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/package-info.java new file mode 100644 index 000000000..4e80cc2bc --- /dev/null +++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/package-info.java @@ -0,0 +1,7 @@ +/** + * TODO + * + * @author JeromeSoar + * @since 2022-04-24 + */ +package cn.iocoder.yudao.module.product; \ No newline at end of file diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/category/CategoryService.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/category/CategoryService.java new file mode 100644 index 000000000..b29b3418f --- /dev/null +++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/category/CategoryService.java @@ -0,0 +1,79 @@ +package cn.iocoder.yudao.module.product.service.category; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.product.controller.admin.category.vo.*; +import cn.iocoder.yudao.module.product.dal.dataobject.category.CategoryDO; + +import javax.validation.Valid; +import java.util.Collection; +import java.util.List; + +/** + * 商品分类 Service 接口 + * + * @author 芋道源码 + */ +public interface CategoryService { + + /** + * 创建商品分类 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createCategory(@Valid CategoryCreateReqVO createReqVO); + + /** + * 更新商品分类 + * + * @param updateReqVO 更新信息 + */ + void updateCategory(@Valid CategoryUpdateReqVO updateReqVO); + + /** + * 删除商品分类 + * + * @param id 编号 + */ + void deleteCategory(Long id); + + /** + * 获得商品分类 + * + * @param id 编号 + * @return 商品分类 + */ + CategoryDO getCategory(Long id); + + /** + * 获得商品分类列表 + * + * @param ids 编号 + * @return 商品分类列表 + */ + List getCategoryList(Collection ids); + + /** + * 获得商品分类分页 + * + * @param pageReqVO 分页查询 + * @return 商品分类分页 + */ + PageResult getCategoryPage(CategoryPageReqVO pageReqVO); + + /** + * 获得商品分类列表, 用于 Excel 导出 + * + * @param exportReqVO 查询条件 + * @return 商品分类列表 + */ + List getCategoryList(CategoryExportReqVO exportReqVO); + + /** + * 获得商品分类列表 + * + * @param treeListReqVO 查询条件 + * @return 商品分类列表 + */ + List getCategoryTreeList(CategoryTreeListReqVO treeListReqVO); +} diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/category/CategoryServiceImpl.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/category/CategoryServiceImpl.java new file mode 100644 index 000000000..b84ac5b9a --- /dev/null +++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/category/CategoryServiceImpl.java @@ -0,0 +1,87 @@ +package cn.iocoder.yudao.module.product.service.category; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.product.controller.admin.category.vo.*; +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.CATEGORY_NOT_EXISTS; + +/** + * 商品分类 Service 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +public class CategoryServiceImpl implements CategoryService { + + @Resource + private CategoryMapper categoryMapper; + + @Override + public Long createCategory(CategoryCreateReqVO createReqVO) { + // 插入 + CategoryDO category = CategoryConvert.INSTANCE.convert(createReqVO); + categoryMapper.insert(category); + // 返回 + return category.getId(); + } + + @Override + public void updateCategory(CategoryUpdateReqVO updateReqVO) { + // 校验存在 + this.validateCategoryExists(updateReqVO.getId()); + // 更新 + CategoryDO updateObj = CategoryConvert.INSTANCE.convert(updateReqVO); + categoryMapper.updateById(updateObj); + } + + @Override + public void deleteCategory(Long id) { + // 校验存在 + this.validateCategoryExists(id); + // 删除 + categoryMapper.deleteById(id); + } + + private void validateCategoryExists(Long id) { + if (categoryMapper.selectById(id) == null) { + throw exception(CATEGORY_NOT_EXISTS); + } + } + + @Override + public CategoryDO getCategory(Long id) { + return categoryMapper.selectById(id); + } + + @Override + public List getCategoryList(Collection ids) { + return categoryMapper.selectBatchIds(ids); + } + + @Override + public PageResult getCategoryPage(CategoryPageReqVO pageReqVO) { + return categoryMapper.selectPage(pageReqVO); + } + + @Override + public List getCategoryList(CategoryExportReqVO exportReqVO) { + return categoryMapper.selectList(exportReqVO); + } + + @Override + public List getCategoryTreeList(CategoryTreeListReqVO treeListReqVO) { + return categoryMapper.selectList(treeListReqVO); + } + +} diff --git a/yudao-module-mall/yudao-module-product-biz/src/test/java/cn/iocoder/yudao/module/product/service/category/CategoryServiceImplTest.java b/yudao-module-mall/yudao-module-product-biz/src/test/java/cn/iocoder/yudao/module/product/service/category/CategoryServiceImplTest.java new file mode 100644 index 000000000..c0ef7e572 --- /dev/null +++ b/yudao-module-mall/yudao-module-product-biz/src/test/java/cn/iocoder/yudao/module/product/service/category/CategoryServiceImplTest.java @@ -0,0 +1,194 @@ +package cn.iocoder.yudao.module.product.service.category; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; +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 cn.iocoder.yudao.module.product.dal.mysql.category.CategoryMapper; +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; +import org.springframework.context.annotation.Import; + +import javax.annotation.Resource; +import java.util.List; + +import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId; +import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals; +import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException; +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomLongId; +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo; +import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.CATEGORY_NOT_EXISTS; +import static org.junit.jupiter.api.Assertions.*; + +/** + * {@link CategoryServiceImpl} 的单元测试类 + * + * @author 芋道源码 + */ +@Import(CategoryServiceImpl.class) +public class CategoryServiceImplTest extends BaseDbUnitTest { + + @Resource + private CategoryServiceImpl categoryService; + + @Resource + private CategoryMapper categoryMapper; + + @Test + public void testCreateCategory_success() { + // 准备参数 + CategoryCreateReqVO reqVO = randomPojo(CategoryCreateReqVO.class); + + // 调用 + Long categoryId = categoryService.createCategory(reqVO); + // 断言 + assertNotNull(categoryId); + // 校验记录的属性是否正确 + CategoryDO category = categoryMapper.selectById(categoryId); + assertPojoEquals(reqVO, category); + } + + @Test + public void testUpdateCategory_success() { + // mock 数据 + CategoryDO dbCategory = randomPojo(CategoryDO.class); + categoryMapper.insert(dbCategory);// @Sql: 先插入出一条存在的数据 + // 准备参数 + CategoryUpdateReqVO reqVO = randomPojo(CategoryUpdateReqVO.class, o -> { + o.setId(dbCategory.getId()); // 设置更新的 ID + }); + + // 调用 + categoryService.updateCategory(reqVO); + // 校验是否更新正确 + CategoryDO category = categoryMapper.selectById(reqVO.getId()); // 获取最新的 + assertPojoEquals(reqVO, category); + } + + @Test + public void testUpdateCategory_notExists() { + // 准备参数 + CategoryUpdateReqVO reqVO = randomPojo(CategoryUpdateReqVO.class); + + // 调用, 并断言异常 + assertServiceException(() -> categoryService.updateCategory(reqVO), CATEGORY_NOT_EXISTS); + } + + @Test + public void testDeleteCategory_success() { + // mock 数据 + CategoryDO dbCategory = randomPojo(CategoryDO.class); + categoryMapper.insert(dbCategory);// @Sql: 先插入出一条存在的数据 + // 准备参数 + Long id = dbCategory.getId(); + + // 调用 + categoryService.deleteCategory(id); + // 校验数据不存在了 + assertNull(categoryMapper.selectById(id)); + } + + @Test + public void testDeleteCategory_notExists() { + // 准备参数 + Long id = randomLongId(); + + // 调用, 并断言异常 + assertServiceException(() -> categoryService.deleteCategory(id), CATEGORY_NOT_EXISTS); + } + + @Test + @Disabled // TODO 请修改 null 为需要的值,然后删除 @Disabled 注解 + public void testGetCategoryPage() { + // mock 数据 + CategoryDO dbCategory = randomPojo(CategoryDO.class, o -> { // 等会查询到 + o.setPid(null); + o.setName(null); + o.setIcon(null); + o.setBannerUrl(null); + o.setSort(null); + o.setDescription(null); + o.setStatus(null); + o.setCreateTime(null); + }); + categoryMapper.insert(dbCategory); + // 测试 pid 不匹配 + categoryMapper.insert(cloneIgnoreId(dbCategory, o -> o.setPid(null))); + // 测试 name 不匹配 + categoryMapper.insert(cloneIgnoreId(dbCategory, o -> o.setName(null))); + // 测试 icon 不匹配 + categoryMapper.insert(cloneIgnoreId(dbCategory, o -> o.setIcon(null))); + // 测试 bannerUrl 不匹配 + categoryMapper.insert(cloneIgnoreId(dbCategory, o -> o.setBannerUrl(null))); + // 测试 sort 不匹配 + categoryMapper.insert(cloneIgnoreId(dbCategory, o -> o.setSort(null))); + // 测试 description 不匹配 + categoryMapper.insert(cloneIgnoreId(dbCategory, o -> o.setDescription(null))); + // 测试 status 不匹配 + categoryMapper.insert(cloneIgnoreId(dbCategory, o -> o.setStatus(null))); + // 测试 createTime 不匹配 + categoryMapper.insert(cloneIgnoreId(dbCategory, o -> o.setCreateTime(null))); + // 准备参数 + CategoryPageReqVO reqVO = new CategoryPageReqVO(); + reqVO.setName(null); + reqVO.setStatus(null); + reqVO.setBeginCreateTime(null); + reqVO.setEndCreateTime(null); + + // 调用 + PageResult pageResult = categoryService.getCategoryPage(reqVO); + // 断言 + assertEquals(1, pageResult.getTotal()); + assertEquals(1, pageResult.getList().size()); + assertPojoEquals(dbCategory, pageResult.getList().get(0)); + } + + @Test + @Disabled // TODO 请修改 null 为需要的值,然后删除 @Disabled 注解 + public void testGetCategoryList() { + // mock 数据 + CategoryDO dbCategory = randomPojo(CategoryDO.class, o -> { // 等会查询到 + o.setPid(null); + o.setName(null); + o.setIcon(null); + o.setBannerUrl(null); + o.setSort(null); + o.setDescription(null); + o.setStatus(null); + o.setCreateTime(null); + }); + categoryMapper.insert(dbCategory); + // 测试 pid 不匹配 + categoryMapper.insert(cloneIgnoreId(dbCategory, o -> o.setPid(null))); + // 测试 name 不匹配 + categoryMapper.insert(cloneIgnoreId(dbCategory, o -> o.setName(null))); + // 测试 icon 不匹配 + categoryMapper.insert(cloneIgnoreId(dbCategory, o -> o.setIcon(null))); + // 测试 bannerUrl 不匹配 + categoryMapper.insert(cloneIgnoreId(dbCategory, o -> o.setBannerUrl(null))); + // 测试 sort 不匹配 + categoryMapper.insert(cloneIgnoreId(dbCategory, o -> o.setSort(null))); + // 测试 description 不匹配 + categoryMapper.insert(cloneIgnoreId(dbCategory, o -> o.setDescription(null))); + // 测试 status 不匹配 + categoryMapper.insert(cloneIgnoreId(dbCategory, o -> o.setStatus(null))); + // 测试 createTime 不匹配 + categoryMapper.insert(cloneIgnoreId(dbCategory, o -> o.setCreateTime(null))); + // 准备参数 + CategoryExportReqVO reqVO = new CategoryExportReqVO(); + reqVO.setName(null); + reqVO.setStatus(null); + reqVO.setBeginCreateTime(null); + reqVO.setEndCreateTime(null); + + // 调用 + List list = categoryService.getCategoryList(reqVO); + // 断言 + assertEquals(1, list.size()); + assertPojoEquals(dbCategory, list.get(0)); + } + +} diff --git a/yudao-module-mall/yudao-module-product-biz/src/test/resources/sql/clean.sql b/yudao-module-mall/yudao-module-product-biz/src/test/resources/sql/clean.sql new file mode 100644 index 000000000..7c66b9074 --- /dev/null +++ b/yudao-module-mall/yudao-module-product-biz/src/test/resources/sql/clean.sql @@ -0,0 +1 @@ +DELETE FROM "product_category"; \ No newline at end of file diff --git a/yudao-module-mall/yudao-module-product-biz/src/test/resources/sql/create_tables.sql b/yudao-module-mall/yudao-module-product-biz/src/test/resources/sql/create_tables.sql new file mode 100644 index 000000000..6400c8f0b --- /dev/null +++ b/yudao-module-mall/yudao-module-product-biz/src/test/resources/sql/create_tables.sql @@ -0,0 +1,17 @@ +CREATE TABLE IF NOT EXISTS "product_category" ( + "id" bigint(20) NOT NULL GENERATED BY DEFAULT AS IDENTITY, + "pid" bigint(20) NOT NULL, + "name" varchar(255) NOT NULL, + "icon" varchar(100), + "banner_url" varchar(255) NOT NULL, + "sort" int(11) NOT NULL, + "description" varchar(1024) NOT NULL, + "status" tinyint(4) NOT NULL, + "creator" varchar(64) DEFAULT '', + "create_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updater" varchar(64) DEFAULT '', + "update_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + "deleted" bit NOT NULL DEFAULT FALSE, + "tenant_id" bigint(20) NOT NULL, + PRIMARY KEY ("id") +) COMMENT '商品分类'; \ No newline at end of file diff --git a/yudao-server/pom.xml b/yudao-server/pom.xml index 73eba6068..b7eed1e50 100644 --- a/yudao-server/pom.xml +++ b/yudao-server/pom.xml @@ -47,16 +47,21 @@ yudao-module-market-biz ${revision} + + cn.iocoder.boot + yudao-module-product-biz + ${revision} + cn.iocoder.boot yudao-module-bpm-biz-flowable ${revision} - - - - + + + + diff --git a/yudao-ui-admin/src/api/mall/product/category.js b/yudao-ui-admin/src/api/mall/product/category.js new file mode 100644 index 000000000..bd825034d --- /dev/null +++ b/yudao-ui-admin/src/api/mall/product/category.js @@ -0,0 +1,63 @@ +import request from '@/utils/request' + +// 创建商品分类 +export function createCategory(data) { + return request({ + url: '/product/category/create', + method: 'post', + data: data + }) +} + +// 更新商品分类 +export function updateCategory(data) { + return request({ + url: '/product/category/update', + method: 'put', + data: data + }) +} + +// 删除商品分类 +export function deleteCategory(id) { + return request({ + url: '/product/category/delete?id=' + id, + method: 'delete' + }) +} + +// 获得商品分类 +export function getCategory(id) { + return request({ + url: '/product/category/get?id=' + id, + method: 'get' + }) +} + +// 获得商品分类 +export function listCategory(query) { + return request({ + url: '/product/category/listByQuery', + method: 'get', + params: query + }) +} + +// 获得商品分类分页 +export function getCategoryPage(query) { + return request({ + url: '/product/category/page', + method: 'get', + params: query + }) +} + +// 导出商品分类 Excel +export function exportCategoryExcel(query) { + return request({ + url: '/product/category/export-excel', + method: 'get', + params: query, + responseType: 'blob' + }) +} diff --git a/yudao-ui-admin/src/components/ImageUpload/index.vue b/yudao-ui-admin/src/components/ImageUpload/index.vue index 170c1bd08..b736b7240 100644 --- a/yudao-ui-admin/src/components/ImageUpload/index.vue +++ b/yudao-ui-admin/src/components/ImageUpload/index.vue @@ -77,7 +77,7 @@ export default { dialogVisible: false, hideUpload: false, baseUrl: process.env.VUE_APP_BASE_API, - uploadImgUrl: process.env.VUE_APP_BASE_API + "/common/upload", // 上传的图片服务器地址 + uploadImgUrl: process.env.VUE_APP_BASE_API + "/admin-api/infra/file/simple-upload", // 上传的图片服务器地址 headers: { Authorization: "Bearer " + getToken(), }, @@ -127,7 +127,7 @@ export default { }, // 上传成功回调 handleUploadSuccess(res) { - this.uploadList.push({ name: res.fileName, url: res.fileName }); + this.uploadList.push({ name: res.data, url: res.data }); if (this.uploadList.length === this.number) { this.fileList = this.fileList.concat(this.uploadList); this.uploadList = []; diff --git a/yudao-ui-admin/src/views/mall/product/category/index.vue b/yudao-ui-admin/src/views/mall/product/category/index.vue new file mode 100644 index 000000000..751ad9c52 --- /dev/null +++ b/yudao-ui-admin/src/views/mall/product/category/index.vue @@ -0,0 +1,330 @@ + + +