Przeglądaj źródła

商户查看统计图

Yangzw 7 miesięcy temu
rodzic
commit
8ab63e2da7
25 zmienionych plików z 1876 dodań i 0 usunięć
  1. 82 0
      feifan-module-mall/feifan-module-product-biz/src/main/java/cn/newfeifan/mall/module/product/controller/admin/skuapply/vo/SkuApplyPageReqVO.java
  2. 102 0
      feifan-module-mall/feifan-module-product-biz/src/main/java/cn/newfeifan/mall/module/product/controller/admin/skuapply/vo/SkuApplyRespVO.java
  3. 95 0
      feifan-module-mall/feifan-module-product-biz/src/main/java/cn/newfeifan/mall/module/product/controller/admin/skuapply/vo/SkuApplySaveReqVO.java
  4. 113 0
      feifan-module-mall/feifan-module-product-biz/src/main/java/cn/newfeifan/mall/module/product/controller/admin/spuapply/SpuApplyController.java
  5. 131 0
      feifan-module-mall/feifan-module-product-biz/src/main/java/cn/newfeifan/mall/module/product/controller/admin/spuapply/vo/SpuApplyPageReqVO.java
  6. 171 0
      feifan-module-mall/feifan-module-product-biz/src/main/java/cn/newfeifan/mall/module/product/controller/admin/spuapply/vo/SpuApplyRespVO.java
  7. 119 0
      feifan-module-mall/feifan-module-product-biz/src/main/java/cn/newfeifan/mall/module/product/controller/admin/spuapply/vo/SpuApplySaveReqVO.java
  8. 33 0
      feifan-module-mall/feifan-module-product-biz/src/main/java/cn/newfeifan/mall/module/product/controller/admin/spuapplylog/vo/SpuApplyLogPageReqVO.java
  9. 37 0
      feifan-module-mall/feifan-module-product-biz/src/main/java/cn/newfeifan/mall/module/product/controller/admin/spuapplylog/vo/SpuApplyLogRespVO.java
  10. 28 0
      feifan-module-mall/feifan-module-product-biz/src/main/java/cn/newfeifan/mall/module/product/controller/admin/spuapplylog/vo/SpuApplyLogSaveReqVO.java
  11. 109 0
      feifan-module-mall/feifan-module-product-biz/src/main/java/cn/newfeifan/mall/module/product/dal/dataobject/skuapply/SkuApplyDO.java
  12. 176 0
      feifan-module-mall/feifan-module-product-biz/src/main/java/cn/newfeifan/mall/module/product/dal/dataobject/spuapply/SpuApplyDO.java
  13. 44 0
      feifan-module-mall/feifan-module-product-biz/src/main/java/cn/newfeifan/mall/module/product/dal/dataobject/spuapplylog/SpuApplyLogDO.java
  14. 49 0
      feifan-module-mall/feifan-module-product-biz/src/main/java/cn/newfeifan/mall/module/product/dal/mysql/skuapply/SkuApplyMapper.java
  15. 64 0
      feifan-module-mall/feifan-module-product-biz/src/main/java/cn/newfeifan/mall/module/product/dal/mysql/spuapply/SpuApplyMapper.java
  16. 29 0
      feifan-module-mall/feifan-module-product-biz/src/main/java/cn/newfeifan/mall/module/product/dal/mysql/spuapplylog/SpuApplyLogMapper.java
  17. 61 0
      feifan-module-mall/feifan-module-product-biz/src/main/java/cn/newfeifan/mall/module/product/service/skuapply/SkuApplyService.java
  18. 74 0
      feifan-module-mall/feifan-module-product-biz/src/main/java/cn/newfeifan/mall/module/product/service/skuapply/SkuApplyServiceImpl.java
  19. 60 0
      feifan-module-mall/feifan-module-product-biz/src/main/java/cn/newfeifan/mall/module/product/service/spuapply/SpuApplyService.java
  20. 140 0
      feifan-module-mall/feifan-module-product-biz/src/main/java/cn/newfeifan/mall/module/product/service/spuapply/SpuApplyServiceImpl.java
  21. 53 0
      feifan-module-mall/feifan-module-product-biz/src/main/java/cn/newfeifan/mall/module/product/service/spuapplylog/SpuApplyLogService.java
  22. 70 0
      feifan-module-mall/feifan-module-product-biz/src/main/java/cn/newfeifan/mall/module/product/service/spuapplylog/SpuApplyLogServiceImpl.java
  23. 12 0
      feifan-module-mall/feifan-module-product-biz/src/main/resources/mapper/skuapply/SkuApplyMapper.xml
  24. 12 0
      feifan-module-mall/feifan-module-product-biz/src/main/resources/mapper/spuapply/SpuApplyMapper.xml
  25. 12 0
      feifan-module-mall/feifan-module-product-biz/src/main/resources/mapper/spuapplylog/SpuApplyLogMapper.xml

+ 82 - 0
feifan-module-mall/feifan-module-product-biz/src/main/java/cn/newfeifan/mall/module/product/controller/admin/skuapply/vo/SkuApplyPageReqVO.java

@@ -0,0 +1,82 @@
+package cn.newfeifan.mall.module.product.controller.admin.skuapply.vo;
+
+import lombok.*;
+import io.swagger.v3.oas.annotations.media.Schema;
+import cn.newfeifan.mall.framework.common.pojo.PageParam;
+import java.math.BigDecimal;
+import org.springframework.format.annotation.DateTimeFormat;
+import java.time.LocalDateTime;
+
+import static cn.newfeifan.mall.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
+
+@Schema(description = "管理后台 - 商品sku申请分页 Request VO")
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ToString(callSuper = true)
+public class SkuApplyPageReqVO extends PageParam {
+
+    @Schema(description = "spu编号", example = "9866")
+    private Long spuApplyId;
+
+    @Schema(description = "属性数组,JSON 格式 [{propertId: , valueId: }, {propertId: , valueId: }]")
+    private String properties;
+
+    @Schema(description = "商品价格,单位:分", example = "24705")
+    private Integer price;
+
+    @Schema(description = "推广费, 单位: 分")
+    private Integer promotionFee;
+
+    @Schema(description = "备注")
+    private String mark;
+
+    @Schema(description = "市场价,单位:分", example = "24117")
+    private Integer marketPrice;
+
+    @Schema(description = "成本价,单位: 分", example = "21015")
+    private Integer costPrice;
+
+    @Schema(description = "SKU 的条形码")
+    private String barCode;
+
+    @Schema(description = "图片地址", example = "https://www.zhongxing.cn")
+    private String picUrl;
+
+    @Schema(description = "库存")
+    private Integer stock;
+
+    @Schema(description = "商品重量,单位:kg 千克")
+    private Double weight;
+
+    @Schema(description = "商品体积,单位:m^3 平米")
+    private Double volume;
+
+    @Schema(description = "一级分销的佣金,单位:分", example = "7462")
+    private Integer firstBrokeragePrice;
+
+    @Schema(description = "二级分销的佣金,单位:分", example = "32532")
+    private Integer secondBrokeragePrice;
+
+    @Schema(description = "商品销量", example = "7812")
+    private Integer salesCount;
+
+    @Schema(description = "创建时间")
+    @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+    private LocalDateTime[] createTime;
+
+    @Schema(description = "店铺id", example = "25567")
+    private Long shopId;
+
+    @Schema(description = "商户id", example = "9994")
+    private Long merchantId;
+
+    @Schema(description = "高精度价格", example = "15815")
+    private BigDecimal highPrecisionPrice;
+
+    @Schema(description = "结算价,单位: 分", example = "21066")
+    private Integer settlementPrice;
+
+    @Schema(description = "高精度结算价", example = "1872")
+    private BigDecimal highPrecisionSettlementPrice;
+
+}

+ 102 - 0
feifan-module-mall/feifan-module-product-biz/src/main/java/cn/newfeifan/mall/module/product/controller/admin/skuapply/vo/SkuApplyRespVO.java

@@ -0,0 +1,102 @@
+package cn.newfeifan.mall.module.product.controller.admin.skuapply.vo;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.*;
+import java.math.BigDecimal;
+import java.time.LocalDateTime;
+import com.alibaba.excel.annotation.*;
+
+@Schema(description = "管理后台 - 商品sku申请 Response VO")
+@Data
+@ExcelIgnoreUnannotated
+public class SkuApplyRespVO {
+
+    @Schema(description = "主键", requiredMode = Schema.RequiredMode.REQUIRED, example = "8231")
+    @ExcelProperty("主键")
+    private Long id;
+
+    @Schema(description = "spu编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "9866")
+    @ExcelProperty("spu编号")
+    private Long spuApplyId;
+
+    @Schema(description = "属性数组,JSON 格式 [{propertId: , valueId: }, {propertId: , valueId: }]")
+    @ExcelProperty("属性数组,JSON 格式 [{propertId: , valueId: }, {propertId: , valueId: }]")
+    private String properties;
+
+    @Schema(description = "商品价格,单位:分", example = "24705")
+    @ExcelProperty("商品价格,单位:分")
+    private Integer price;
+
+    @Schema(description = "推广费, 单位: 分")
+    @ExcelProperty("推广费, 单位: 分")
+    private Integer promotionFee;
+
+    @Schema(description = "备注")
+    @ExcelProperty("备注")
+    private String mark;
+
+    @Schema(description = "市场价,单位:分", example = "24117")
+    @ExcelProperty("市场价,单位:分")
+    private Integer marketPrice;
+
+    @Schema(description = "成本价,单位: 分", example = "21015")
+    @ExcelProperty("成本价,单位: 分")
+    private Integer costPrice;
+
+    @Schema(description = "SKU 的条形码")
+    @ExcelProperty("SKU 的条形码")
+    private String barCode;
+
+    @Schema(description = "图片地址", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.zhongxing.cn")
+    @ExcelProperty("图片地址")
+    private String picUrl;
+
+    @Schema(description = "库存")
+    @ExcelProperty("库存")
+    private Integer stock;
+
+    @Schema(description = "商品重量,单位:kg 千克")
+    @ExcelProperty("商品重量,单位:kg 千克")
+    private Double weight;
+
+    @Schema(description = "商品体积,单位:m^3 平米")
+    @ExcelProperty("商品体积,单位:m^3 平米")
+    private Double volume;
+
+    @Schema(description = "一级分销的佣金,单位:分", example = "7462")
+    @ExcelProperty("一级分销的佣金,单位:分")
+    private Integer firstBrokeragePrice;
+
+    @Schema(description = "二级分销的佣金,单位:分", example = "32532")
+    @ExcelProperty("二级分销的佣金,单位:分")
+    private Integer secondBrokeragePrice;
+
+    @Schema(description = "商品销量", example = "7812")
+    @ExcelProperty("商品销量")
+    private Integer salesCount;
+
+    @Schema(description = "创建时间")
+    @ExcelProperty("创建时间")
+    private LocalDateTime createTime;
+
+    @Schema(description = "店铺id", example = "25567")
+    @ExcelProperty("店铺id")
+    private Long shopId;
+
+    @Schema(description = "商户id", example = "9994")
+    @ExcelProperty("商户id")
+    private Long merchantId;
+
+    @Schema(description = "高精度价格", example = "15815")
+    @ExcelProperty("高精度价格")
+    private BigDecimal highPrecisionPrice;
+
+    @Schema(description = "结算价,单位: 分", example = "21066")
+    @ExcelProperty("结算价,单位: 分")
+    private Integer settlementPrice;
+
+    @Schema(description = "高精度结算价", example = "1872")
+    @ExcelProperty("高精度结算价")
+    private BigDecimal highPrecisionSettlementPrice;
+
+}

+ 95 - 0
feifan-module-mall/feifan-module-product-biz/src/main/java/cn/newfeifan/mall/module/product/controller/admin/skuapply/vo/SkuApplySaveReqVO.java

@@ -0,0 +1,95 @@
+package cn.newfeifan.mall.module.product.controller.admin.skuapply.vo;
+
+import cn.newfeifan.mall.module.product.controller.admin.spu.vo.ProductSkuSaveReqVO;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.*;
+import java.util.*;
+import javax.validation.constraints.*;
+import java.math.BigDecimal;
+
+@Schema(description = "管理后台 - 商品sku申请新增/修改 Request VO")
+@Data
+public class SkuApplySaveReqVO {
+
+    @Schema(description = "商品 SKU 名字", requiredMode = Schema.RequiredMode.REQUIRED, example = "清凉小短袖")
+    @NotEmpty(message = "商品 SKU 名字不能为空")
+    private String name;
+
+    @Schema(description = "销售价格,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "1999")
+    private Integer price;
+
+    @Schema(description = "市场价", example = "2999")
+    private Integer marketPrice;
+
+    @Schema(description = "成本价", example = "19")
+    private Integer costPrice;
+
+    @Schema(description = "条形码", example = "15156165456")
+    private String barCode;
+
+    @Schema(description = "图片地址", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.zhongxing.cn/xx.png")
+    @NotNull(message = "图片地址不能为空")
+    private String picUrl;
+
+    @Schema(description = "库存", requiredMode = Schema.RequiredMode.REQUIRED, example = "200")
+    @NotNull(message = "库存不能为空")
+    private Integer stock;
+
+    @Schema(description = "商品重量,单位:kg 千克", example = "1.2")
+    private Double weight;
+
+    @Schema(description = "商品体积,单位:m^3 平米", example = "2.5")
+    private Double volume;
+
+    @Schema(description = "一级分销的佣金,单位:分", example = "199")
+    private Integer firstBrokeragePrice;
+
+    @Schema(description = "二级分销的佣金,单位:分", example = "19")
+    private Integer secondBrokeragePrice;
+
+
+    @Schema(description = "推广费, 单位: 分")
+    private Integer promotionFee;
+
+    @Schema(description = "备注")
+    private String mark;
+
+    @Schema(description = "属性数组")
+    private List<ProductSkuSaveReqVO.Property> properties;
+
+    @Schema(description = "商品属性")
+    @Data
+    @NoArgsConstructor
+    @AllArgsConstructor
+    public static class Property {
+
+        @Schema(description = "属性编号", example = "10")
+        private Long propertyId;
+
+        @Schema(description = "属性名字", example = "颜色")
+        private String propertyName;
+
+        @Schema(description = "属性值编号", example = "10")
+        private Long valueId;
+
+        @Schema(description = "属性值名字", example = "红色")
+        private String valueName;
+
+    }
+
+    @Schema(description = "店铺id", example = "20588")
+    private Long shopId;
+
+    @Schema(description = "商户id", example = "8240")
+    private Long merchantId;
+
+    @Schema(description = "高精度价格", example = "9255")
+    private BigDecimal highPrecisionPrice;
+
+    @Schema(description = "结算价,单位: 分", example = "19500")
+    private Integer settlementPrice;
+
+    @Schema(description = "高精度结算价", example = "19997")
+    private BigDecimal highPrecisionSettlementPrice;
+
+}

+ 113 - 0
feifan-module-mall/feifan-module-product-biz/src/main/java/cn/newfeifan/mall/module/product/controller/admin/spuapply/SpuApplyController.java

@@ -0,0 +1,113 @@
+package cn.newfeifan.mall.module.product.controller.admin.spuapply;
+
+import cn.newfeifan.mall.module.product.convert.spuapply.SpuApplyConvert;
+import cn.newfeifan.mall.module.product.dal.dataobject.skuapply.SkuApplyDO;
+import cn.newfeifan.mall.module.product.dal.mysql.spuapply.SpuApplyMapper;
+import cn.newfeifan.mall.module.product.service.skuapply.SkuApplyService;
+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.v3.oas.annotations.tags.Tag;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.Operation;
+
+import javax.validation.*;
+import javax.servlet.http.*;
+import java.util.*;
+import java.io.IOException;
+
+import cn.newfeifan.mall.framework.common.pojo.PageParam;
+import cn.newfeifan.mall.framework.common.pojo.PageResult;
+import cn.newfeifan.mall.framework.common.pojo.CommonResult;
+import cn.newfeifan.mall.framework.common.util.object.BeanUtils;
+import static cn.newfeifan.mall.framework.common.pojo.CommonResult.success;
+
+import cn.newfeifan.mall.framework.excel.core.util.ExcelUtils;
+
+import cn.newfeifan.mall.framework.operatelog.core.annotations.OperateLog;
+import static cn.newfeifan.mall.framework.operatelog.core.enums.OperateTypeEnum.*;
+
+import cn.newfeifan.mall.module.product.controller.admin.spuapply.vo.*;
+import cn.newfeifan.mall.module.product.dal.dataobject.spuapply.SpuApplyDO;
+import cn.newfeifan.mall.module.product.service.spuapply.SpuApplyService;
+
+@Tag(name = "管理后台 - 商品spu申请")
+@RestController
+@RequestMapping("/product/spu-apply")
+@Validated
+public class SpuApplyController {
+
+    @Resource
+    private SpuApplyService spuApplyService;
+    @Resource
+    private SpuApplyMapper spuApplyMapper;
+    @Resource
+    private SkuApplyService skuApplyService;
+
+    @PostMapping("/create")
+    @Operation(summary = "创建商品spu申请")
+    @PreAuthorize("@ss.hasPermission('product:spu-apply:create')")
+    public CommonResult<Long> createSpuApply(@Valid @RequestBody SpuApplySaveReqVO createReqVO) {
+        return success(spuApplyService.createSpuApply(createReqVO));
+    }
+
+    @PutMapping("/update")
+    @Operation(summary = "更新商品spu申请")
+    @PreAuthorize("@ss.hasPermission('product:spu-apply:update')")
+    public CommonResult<Boolean> updateSpuApply(@Valid @RequestBody SpuApplySaveReqVO updateReqVO) {
+        spuApplyService.updateSpuApply(updateReqVO);
+        return success(true);
+    }
+
+    @DeleteMapping("/delete")
+    @Operation(summary = "删除商品spu申请")
+    @Parameter(name = "id", description = "编号", required = true)
+    @PreAuthorize("@ss.hasPermission('product:spu-apply:delete')")
+    public CommonResult<Boolean> deleteSpuApply(@RequestParam("id") Long id) {
+        spuApplyService.deleteSpuApply(id);
+        return success(true);
+    }
+
+    @GetMapping("/get-detail")
+    @Operation(summary = "获得商品 spu 申请 明细")
+    @Parameter(name = "id", description = "编号", required = true, example = "1024")
+    @PreAuthorize("@ss.hasPermission('product:spu-apply:query')")
+    public CommonResult<SpuApplyRespVO> getSpuApply(@RequestParam("id") Long id) {
+        // 获得商品 SPU 申请
+        SpuApplyDO spu = spuApplyService.getSpu(id);
+        if (spu == null) {
+            return success(null);
+        }
+        // 查询商品 SKU
+        List<SkuApplyDO> skus = skuApplyService.getSkuListBySpuId(spu.getId());
+
+        String shopName = spuApplyMapper.selectShopNameById(spu.getShopId());
+        CommonResult<SpuApplyRespVO> success = success(SpuApplyConvert.INSTANCE.convert(spu, skus));
+        success.getData().setShopName(shopName);
+
+        return success;
+    }
+
+    @GetMapping("/page")
+    @Operation(summary = "获得商品spu申请分页")
+    @PreAuthorize("@ss.hasPermission('product:spu-apply:query')")
+    public CommonResult<PageResult<SpuApplyRespVO>> getSpuApplyPage(@Valid SpuApplyPageReqVO pageReqVO) {
+        PageResult<SpuApplyDO> pageResult = spuApplyService.getSpuApplyPage(pageReqVO);
+        return success(BeanUtils.toBean(pageResult, SpuApplyRespVO.class));
+    }
+
+    @GetMapping("/export-excel")
+    @Operation(summary = "导出商品spu申请 Excel")
+    @PreAuthorize("@ss.hasPermission('product:spu-apply:export')")
+    @OperateLog(type = EXPORT)
+    public void exportSpuApplyExcel(@Valid SpuApplyPageReqVO pageReqVO,
+              HttpServletResponse response) throws IOException {
+        pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
+        List<SpuApplyDO> list = spuApplyService.getSpuApplyPage(pageReqVO).getList();
+        // 导出 Excel
+        ExcelUtils.write(response, "商品spu申请.xls", "数据", SpuApplyRespVO.class,
+                        BeanUtils.toBean(list, SpuApplyRespVO.class));
+    }
+
+}

+ 131 - 0
feifan-module-mall/feifan-module-product-biz/src/main/java/cn/newfeifan/mall/module/product/controller/admin/spuapply/vo/SpuApplyPageReqVO.java

@@ -0,0 +1,131 @@
+package cn.newfeifan.mall.module.product.controller.admin.spuapply.vo;
+
+import lombok.*;
+import io.swagger.v3.oas.annotations.media.Schema;
+import cn.newfeifan.mall.framework.common.pojo.PageParam;
+import java.math.BigDecimal;
+import org.springframework.format.annotation.DateTimeFormat;
+import java.time.LocalDateTime;
+
+import static cn.newfeifan.mall.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
+
+@Schema(description = "管理后台 - 商品spu申请分页 Request VO")
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ToString(callSuper = true)
+public class SpuApplyPageReqVO extends PageParam {
+
+    @Schema(description = "商品名称", example = "非繁人")
+    private String name;
+
+    @Schema(description = "关键字")
+    private String keyword;
+
+    @Schema(description = "商品简介")
+    private String introduction;
+
+    @Schema(description = "商品详情", example = "你猜")
+    private String description;
+
+    @Schema(description = "产地")
+    private String producerArea;
+
+    @Schema(description = "商品类别", example = "2")
+    private Integer spuType;
+
+    @Schema(description = "商品分类编号", example = "1734")
+    private Long categoryId;
+
+    @Schema(description = "商品品牌编号", example = "4607")
+    private Integer brandId;
+
+    @Schema(description = "商品封面图", example = "https://www.zhongxing.cn")
+    private String picUrl;
+
+    @Schema(description = "商品轮播图地址数组,以逗号分隔最多上传15张")
+    private String sliderPicUrls;
+
+    @Schema(description = "排序字段")
+    private Integer sort;
+
+    @Schema(description = "商品状态: 0 上架(开启) 1 下架(禁用)-1 回收", example = "1")
+    private Integer status;
+
+    @Schema(description = "规格类型:0 单规格 1 多规格", example = "2")
+    private Boolean specType;
+
+    @Schema(description = "商品价格,单位使用:分", example = "2808")
+    private Integer price;
+
+    @Schema(description = "市场价,单位使用:分", example = "7922")
+    private Integer marketPrice;
+
+    @Schema(description = "成本价,单位: 分", example = "17622")
+    private Integer costPrice;
+
+    @Schema(description = "库存")
+    private Integer stock;
+
+    @Schema(description = "配送方式数组")
+    private String deliveryTypes;
+
+    @Schema(description = "物流配置模板编号", example = "3169")
+    private Long deliveryTemplateId;
+
+    @Schema(description = "赠送积分")
+    private Integer giveIntegral;
+
+    @Schema(description = "分销类型", example = "1")
+    private Boolean subCommissionType;
+
+    @Schema(description = "商品销量", example = "231")
+    private Integer salesCount;
+
+    @Schema(description = "虚拟销量", example = "24880")
+    private Integer virtualSalesCount;
+
+    @Schema(description = "商品点击量", example = "18493")
+    private Integer browseCount;
+
+    @Schema(description = "创建时间")
+    @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+    private LocalDateTime[] createTime;
+
+    @Schema(description = "店铺id", example = "19626")
+    private Long shopId;
+
+    @Schema(description = "商户id", example = "14569")
+    private Long merchantId;
+
+    @Schema(description = "是否隐藏。隐藏:1,不隐藏:0")
+    private Boolean hidden;
+
+    @Schema(description = "推广费, 单位: 分,值为sku中最大的推广费")
+    private Integer promotionFee;
+
+    @Schema(description = "商品支付类别(1 rmb 2积分)", example = "1")
+    private Integer spuPayType;
+
+    @Schema(description = "高精度")
+    private Boolean highPrecision;
+
+    @Schema(description = "高精度价格", example = "23692")
+    private BigDecimal highPrecisionPrice;
+
+    @Schema(description = "申请用户id", example = "22602")
+    private Long applyMemberUserId;
+
+    @Schema(description = "审核系统用户id", example = "22820")
+    private Long checkSystemUserId;
+
+    @Schema(description = "审核时间")
+    @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+    private LocalDateTime[] checkTime;
+
+    @Schema(description = "审核意见")
+    private String checkComment;
+
+    @Schema(description = "审核状态:默认0表示未审核,1审核通过,2审核不通过", example = "1")
+    private Integer checkStatus;
+
+}

+ 171 - 0
feifan-module-mall/feifan-module-product-biz/src/main/java/cn/newfeifan/mall/module/product/controller/admin/spuapply/vo/SpuApplyRespVO.java

@@ -0,0 +1,171 @@
+package cn.newfeifan.mall.module.product.controller.admin.spuapply.vo;
+
+import cn.newfeifan.mall.framework.excel.core.annotations.DictFormat;
+import cn.newfeifan.mall.framework.excel.core.convert.DictConvert;
+import cn.newfeifan.mall.framework.excel.core.convert.MoneyConvert;
+import cn.newfeifan.mall.module.product.controller.admin.spu.vo.ProductSkuRespVO;
+import cn.newfeifan.mall.module.product.enums.DictTypeConstants;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.*;
+import java.util.*;
+import java.math.BigDecimal;
+import java.time.LocalDateTime;
+import com.alibaba.excel.annotation.*;
+
+@Schema(description = "管理后台 - 商品spu申请 Response VO")
+@Data
+@ExcelIgnoreUnannotated
+public class SpuApplyRespVO {
+
+    @Schema(description = "商品 SPU 编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "111")
+    @ExcelProperty("商品编号")
+    private Long id;
+
+    @Schema(description = "商品名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "清凉小短袖")
+    @ExcelProperty("商品名称")
+    private String name;
+
+    @Schema(description = "关键字", requiredMode = Schema.RequiredMode.REQUIRED, example = "清凉丝滑不出汗")
+    @ExcelProperty("关键字")
+    private String keyword;
+
+    @Schema(description = "商品简介", requiredMode = Schema.RequiredMode.REQUIRED, example = "清凉小短袖简介")
+    @ExcelProperty("商品简介")
+    private String introduction;
+
+    @Schema(description = "商品详情", requiredMode = Schema.RequiredMode.REQUIRED, example = "清凉小短袖详情")
+    @ExcelProperty("商品详情")
+    private String description;
+
+    @Schema(description = "商品分类编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
+    @ExcelProperty("商品分类编号")
+    private Long categoryId;
+
+    @Schema(description = "商品品牌编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
+    @ExcelProperty("商品品牌编号")
+    private Long brandId;
+
+    @Schema(description = "商品封面图", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.zhongxing.cn/xx.png")
+    @ExcelProperty("商品封面图")
+    private String picUrl;
+
+    @Schema(description = "商品轮播图", requiredMode = Schema.RequiredMode.REQUIRED, example = "[https://www.zhongxing.cn/xx.png, https://www.zhongxing.cn/xxx.png]")
+    private List<String> sliderPicUrls;
+
+    @Schema(description = "排序字段", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
+    @ExcelProperty("排序字段")
+    private Integer sort;
+
+    @Schema(description = "商品状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
+    @ExcelProperty(value = "商品状态", converter = DictConvert.class)
+    @DictFormat(DictTypeConstants.PRODUCT_SPU_STATUS)
+    private Integer status;
+
+    @Schema(description = "商品创建时间", requiredMode = Schema.RequiredMode.REQUIRED, example = "2023-05-24 00:00:00")
+    @ExcelProperty("创建时间")
+    private LocalDateTime createTime;
+
+    // ========== SKU 相关字段 =========
+
+    @Schema(description = "规格类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "true")
+    @ExcelProperty("规格类型")
+    private Boolean specType;
+
+    @Schema(description = "商品价格", requiredMode = Schema.RequiredMode.REQUIRED, example = "1999")
+    @ExcelProperty(value = "商品价格", converter = MoneyConvert.class)
+    private Integer price;
+
+    @Schema(description = "市场价,单位使用:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "199")
+    @ExcelProperty(value = "市场价", converter = MoneyConvert.class)
+    private Integer marketPrice;
+
+    @Schema(description = "成本价,单位使用:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "19")
+    @ExcelProperty(value = "成本价", converter = MoneyConvert.class)
+    private Integer costPrice;
+
+    @Schema(description = "商品库存", requiredMode = Schema.RequiredMode.REQUIRED, example = "10000")
+    @ExcelProperty("库存")
+    private Integer stock;
+
+    @Schema(description = "SKU 数组")
+    private List<ProductSkuRespVO> skus;
+
+    // ========== 物流相关字段 =========
+
+    @Schema(description = "配送方式数组", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
+    private List<Integer> deliveryTypes;
+
+    @Schema(description = "物流配置模板编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "111")
+    @ExcelProperty("物流配置模板编号")
+    private Long deliveryTemplateId;
+
+    // ========== 营销相关字段 =========
+
+    @Schema(description = "赠送积分", requiredMode = Schema.RequiredMode.REQUIRED, example = "111")
+    @ExcelProperty("赠送积分")
+    private Integer giveIntegral;
+
+    @Schema(description = "分销类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "true")
+    @ExcelProperty("分销类型")
+    private Boolean subCommissionType;
+
+    // ========== 统计相关字段 =========
+
+    @Schema(description = "商品销量", requiredMode = Schema.RequiredMode.REQUIRED, example = "2000")
+    @ExcelProperty("商品销量")
+    private Integer salesCount;
+
+    @Schema(description = "虚拟销量", example = "66")
+    @ExcelProperty("虚拟销量")
+    private Integer virtualSalesCount;
+
+    @Schema(description = "浏览量", requiredMode = Schema.RequiredMode.REQUIRED, example = "888")
+    @ExcelProperty("商品点击量")
+    private Integer browseCount;
+
+    @Schema(description = "产地")
+    private String producerArea;
+
+    @Schema(description = "商品类别", example = "1")
+    private Integer spuType;
+
+    @Schema(description = "店铺id", example = "20588")
+    private Long shopId;
+
+    @Schema(description = "店铺名称", example = "中星温暖")
+    private String shopName;
+
+    @Schema(description = "商户id", example = "8240")
+    private Long merchantId;
+    @Schema(description = "商品支付类别")
+    private Integer spuPayType;
+
+    @Schema(description = "高精度", requiredMode = Schema.RequiredMode.REQUIRED)
+    @ExcelProperty("高精度")
+    private Boolean highPrecision;
+
+    @Schema(description = "高精度价格", example = "9255")
+    @ExcelProperty("高精度价格")
+    private BigDecimal highPrecisionPrice;
+
+    @Schema(description = "申请用户id", example = "22602")
+    @ExcelProperty("申请用户id")
+    private Long applyMemberUserId;
+
+    @Schema(description = "审核系统用户id", example = "22820")
+    @ExcelProperty("审核系统用户id")
+    private Long checkSystemUserId;
+
+    @Schema(description = "审核时间")
+    @ExcelProperty("审核时间")
+    private LocalDateTime checkTime;
+
+    @Schema(description = "审核意见")
+    @ExcelProperty("审核意见")
+    private String checkComment;
+
+    @Schema(description = "审核状态:默认0表示未审核,1审核通过,2审核不通过", example = "1")
+    @ExcelProperty("审核状态:默认0表示未审核,1审核通过,2审核不通过")
+    private Integer checkStatus;
+
+}

+ 119 - 0
feifan-module-mall/feifan-module-product-biz/src/main/java/cn/newfeifan/mall/module/product/controller/admin/spuapply/vo/SpuApplySaveReqVO.java

@@ -0,0 +1,119 @@
+package cn.newfeifan.mall.module.product.controller.admin.spuapply.vo;
+
+import cn.newfeifan.mall.module.product.controller.admin.skuapply.vo.SkuApplySaveReqVO;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.*;
+import java.util.*;
+import javax.validation.Valid;
+import javax.validation.constraints.*;
+import java.math.BigDecimal;
+
+@Schema(description = "管理后台 - 商品spu申请新增/修改 Request VO")
+@Data
+public class SpuApplySaveReqVO {
+
+    @Schema(description = "商品编号", example = "1")
+    private Long id;
+
+    @Schema(description = "商品名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "清凉小短袖")
+    @NotEmpty(message = "商品名称不能为空")
+    private String name;
+
+    @Schema(description = "关键字", requiredMode = Schema.RequiredMode.REQUIRED, example = "清凉丝滑不出汗")
+    @NotEmpty(message = "商品关键字不能为空")
+    private String keyword;
+
+    @Schema(description = "商品简介", requiredMode = Schema.RequiredMode.REQUIRED, example = "清凉小短袖简介")
+    @NotEmpty(message = "商品简介不能为空")
+    private String introduction;
+
+    @Schema(description = "商品详情", requiredMode = Schema.RequiredMode.REQUIRED, example = "清凉小短袖详情")
+    @NotEmpty(message = "商品详情不能为空")
+    private String description;
+
+    @Schema(description = "商品分类编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
+    @NotNull(message = "商品分类不能为空")
+    private Long categoryId;
+
+    @Schema(description = "商品品牌编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
+    private Long brandId;
+
+    @Schema(description = "商品封面图", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.zhongxing.cn/xx.png")
+    @NotEmpty(message = "商品封面图不能为空")
+    private String picUrl;
+
+    @Schema(description = "商品轮播图", requiredMode = Schema.RequiredMode.REQUIRED,
+            example = "[https://www.zhongxing.cn/xx.png, https://www.zhongxing.cn/xxx.png]")
+    private List<String> sliderPicUrls;
+
+    @Schema(description = "排序字段", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
+    @NotNull(message = "商品排序字段不能为空")
+    private Integer sort;
+
+    // ========== SKU 相关字段 =========
+
+    @Schema(description = "规格类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "true")
+    @NotNull(message = "商品规格类型不能为空")
+    private Boolean specType;
+
+    // ========== 物流相关字段 =========
+
+    @Schema(description = "配送方式数组", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
+    @NotEmpty(message = "配送方式不能为空")
+    private List<Integer> deliveryTypes;
+
+    @Schema(description = "物流配置模板编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "111")
+    private Long deliveryTemplateId;
+
+    // ========== 营销相关字段 =========
+
+    @Schema(description = "赠送积分", requiredMode = Schema.RequiredMode.REQUIRED, example = "111")
+    @NotNull(message = "商品赠送积分不能为空")
+    private Integer giveIntegral;
+
+    @Schema(description = "分销类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "true")
+    @NotNull(message = "商品分销类型不能为空")
+    private Boolean subCommissionType;
+
+    // ========== 统计相关字段 =========
+
+    @Schema(description = "虚拟销量", example = "66")
+    private Integer virtualSalesCount;
+
+    @Schema(description = "商品销量", requiredMode = Schema.RequiredMode.REQUIRED, example = "1999")
+    private Integer salesCount;
+
+    @Schema(description = "浏览量", requiredMode = Schema.RequiredMode.REQUIRED, example = "1999")
+    private Integer browseCount;
+
+    // ========== SKU 相关字段 =========
+
+    @Schema(description = "SKU 数组")
+    @Valid
+    private List<SkuApplySaveReqVO> skus;
+
+    @Schema(description = "产地")
+    private String producerArea;
+
+    @Schema(description = "商品类别", example = "1")
+    private Integer spuType;
+
+    @Schema(description = "店铺id", example = "20588")
+    private Long shopId;
+
+
+    @Schema(description = "商户id", example = "8240")
+    private Long merchantId;
+
+    @Schema(description = "商品支付类别", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
+    @NotNull(message = "商品支付类别不能为空")
+    private Integer spuPayType;
+
+    @Schema(description = "高精度价格", example = "9255")
+    private BigDecimal highPrecisionPrice;
+
+    @Schema(description = "高精度", requiredMode = Schema.RequiredMode.REQUIRED)
+    @NotNull(message = "高精度不能为空")
+    private Boolean highPrecision;
+
+}

+ 33 - 0
feifan-module-mall/feifan-module-product-biz/src/main/java/cn/newfeifan/mall/module/product/controller/admin/spuapplylog/vo/SpuApplyLogPageReqVO.java

@@ -0,0 +1,33 @@
+package cn.newfeifan.mall.module.product.controller.admin.spuapplylog.vo;
+
+import lombok.*;
+import io.swagger.v3.oas.annotations.media.Schema;
+import cn.newfeifan.mall.framework.common.pojo.PageParam;
+import org.springframework.format.annotation.DateTimeFormat;
+import java.time.LocalDateTime;
+
+import static cn.newfeifan.mall.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
+
+@Schema(description = "管理后台 - 商品审核记录分页 Request VO")
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ToString(callSuper = true)
+public class SpuApplyLogPageReqVO extends PageParam {
+
+    @Schema(description = "申请状态  0:申请中 1:通过 2:未通过", example = "1")
+    private Integer status;
+
+    @Schema(description = "商品申请id", example = "1516")
+    private Long productSpuApplyId;
+
+    @Schema(description = "审核系统用户id", example = "28003")
+    private Long checkSystemUserId;
+
+    @Schema(description = "审核意见")
+    private String checkComment;
+
+    @Schema(description = "创建时间")
+    @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+    private LocalDateTime[] createTime;
+
+}

+ 37 - 0
feifan-module-mall/feifan-module-product-biz/src/main/java/cn/newfeifan/mall/module/product/controller/admin/spuapplylog/vo/SpuApplyLogRespVO.java

@@ -0,0 +1,37 @@
+package cn.newfeifan.mall.module.product.controller.admin.spuapplylog.vo;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.*;
+import java.time.LocalDateTime;
+import com.alibaba.excel.annotation.*;
+
+@Schema(description = "管理后台 - 商品审核记录 Response VO")
+@Data
+@ExcelIgnoreUnannotated
+public class SpuApplyLogRespVO {
+
+    @Schema(description = "spu审核记录id", requiredMode = Schema.RequiredMode.REQUIRED, example = "3825")
+    @ExcelProperty("spu审核记录id")
+    private Long id;
+
+    @Schema(description = "申请状态  0:申请中 1:通过 2:未通过", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
+    @ExcelProperty("申请状态  0:申请中 1:通过 2:未通过")
+    private Integer status;
+
+    @Schema(description = "商品申请id", requiredMode = Schema.RequiredMode.REQUIRED, example = "1516")
+    @ExcelProperty("商品申请id")
+    private Long productSpuApplyId;
+
+    @Schema(description = "审核系统用户id", example = "28003")
+    @ExcelProperty("审核系统用户id")
+    private Long checkSystemUserId;
+
+    @Schema(description = "审核意见")
+    @ExcelProperty("审核意见")
+    private String checkComment;
+
+    @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
+    @ExcelProperty("创建时间")
+    private LocalDateTime createTime;
+
+}

+ 28 - 0
feifan-module-mall/feifan-module-product-biz/src/main/java/cn/newfeifan/mall/module/product/controller/admin/spuapplylog/vo/SpuApplyLogSaveReqVO.java

@@ -0,0 +1,28 @@
+package cn.newfeifan.mall.module.product.controller.admin.spuapplylog.vo;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.*;
+import javax.validation.constraints.*;
+
+@Schema(description = "管理后台 - 商品审核记录新增/修改 Request VO")
+@Data
+public class SpuApplyLogSaveReqVO {
+
+    @Schema(description = "spu审核记录id", requiredMode = Schema.RequiredMode.REQUIRED, example = "3825")
+    private Long id;
+
+    @Schema(description = "申请状态  0:申请中 1:通过 2:未通过", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
+    @NotNull(message = "申请状态  0:申请中 1:通过 2:未通过不能为空")
+    private Integer status;
+
+    @Schema(description = "商品申请id", requiredMode = Schema.RequiredMode.REQUIRED, example = "1516")
+    @NotNull(message = "商品申请id不能为空")
+    private Long productSpuApplyId;
+
+    @Schema(description = "审核系统用户id", example = "28003")
+    private Long checkSystemUserId;
+
+    @Schema(description = "审核意见")
+    private String checkComment;
+
+}

+ 109 - 0
feifan-module-mall/feifan-module-product-biz/src/main/java/cn/newfeifan/mall/module/product/dal/dataobject/skuapply/SkuApplyDO.java

@@ -0,0 +1,109 @@
+package cn.newfeifan.mall.module.product.dal.dataobject.skuapply;
+
+import lombok.*;
+import java.math.BigDecimal;
+import com.baomidou.mybatisplus.annotation.*;
+import cn.newfeifan.mall.framework.mybatis.core.dataobject.BaseDO;
+
+/**
+ * 商品sku申请 DO
+ *
+ * @author 非繁人
+ */
+@TableName("product_sku_apply")
+@KeySequence("product_sku_apply_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ToString(callSuper = true)
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class SkuApplyDO extends BaseDO {
+
+    /**
+     * 主键
+     */
+    @TableId
+    private Long id;
+    /**
+     * spu编号
+     */
+    private Long spuApplyId;
+    /**
+     * 属性数组,JSON 格式 [{propertId: , valueId: }, {propertId: , valueId: }]
+     */
+    private String properties;
+    /**
+     * 商品价格,单位:分
+     */
+    private Integer price;
+    /**
+     * 推广费, 单位: 分
+     */
+    private Integer promotionFee;
+    /**
+     * 备注
+     */
+    private String mark;
+    /**
+     * 市场价,单位:分
+     */
+    private Integer marketPrice;
+    /**
+     * 成本价,单位: 分
+     */
+    private Integer costPrice;
+    /**
+     * SKU 的条形码
+     */
+    private String barCode;
+    /**
+     * 图片地址
+     */
+    private String picUrl;
+    /**
+     * 库存
+     */
+    private Integer stock;
+    /**
+     * 商品重量,单位:kg 千克
+     */
+    private Double weight;
+    /**
+     * 商品体积,单位:m^3 平米
+     */
+    private Double volume;
+    /**
+     * 一级分销的佣金,单位:分
+     */
+    private Integer firstBrokeragePrice;
+    /**
+     * 二级分销的佣金,单位:分
+     */
+    private Integer secondBrokeragePrice;
+    /**
+     * 商品销量
+     */
+    private Integer salesCount;
+    /**
+     * 店铺id
+     */
+    private Long shopId;
+    /**
+     * 商户id
+     */
+    private Long merchantId;
+    /**
+     * 高精度价格
+     */
+    private BigDecimal highPrecisionPrice;
+    /**
+     * 结算价,单位: 分
+     */
+    private Integer settlementPrice;
+    /**
+     * 高精度结算价
+     */
+    private BigDecimal highPrecisionSettlementPrice;
+
+}

+ 176 - 0
feifan-module-mall/feifan-module-product-biz/src/main/java/cn/newfeifan/mall/module/product/dal/dataobject/spuapply/SpuApplyDO.java

@@ -0,0 +1,176 @@
+package cn.newfeifan.mall.module.product.dal.dataobject.spuapply;
+
+import lombok.*;
+import java.time.LocalDateTime;
+import java.math.BigDecimal;
+import com.baomidou.mybatisplus.annotation.*;
+import cn.newfeifan.mall.framework.mybatis.core.dataobject.BaseDO;
+
+/**
+ * 商品spu申请 DO
+ *
+ * @author 非繁人
+ */
+@TableName("product_spu_apply")
+@KeySequence("product_spu_apply_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ToString(callSuper = true)
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class SpuApplyDO extends BaseDO {
+
+    /**
+     * 商品 SPU 编号,自增
+     */
+    @TableId
+    private Long id;
+    /**
+     * 商品名称
+     */
+    private String name;
+    /**
+     * 关键字
+     */
+    private String keyword;
+    /**
+     * 商品简介
+     */
+    private String introduction;
+    /**
+     * 商品详情
+     */
+    private String description;
+    /**
+     * 产地
+     */
+    private String producerArea;
+    /**
+     * 商品类别
+     */
+    private Integer spuType;
+    /**
+     * 商品分类编号
+     */
+    private Long categoryId;
+    /**
+     * 商品品牌编号
+     */
+    private Integer brandId;
+    /**
+     * 商品封面图
+     */
+    private String picUrl;
+    /**
+     * 商品轮播图地址
+ 数组,以逗号分隔
+ 最多上传15张
+     */
+    private String sliderPicUrls;
+    /**
+     * 排序字段
+     */
+    private Integer sort;
+    /**
+     * 商品状态: 0 上架(开启) 1 下架(禁用)-1 回收
+     */
+    private Integer status;
+    /**
+     * 规格类型:0 单规格 1 多规格
+     */
+    private Boolean specType;
+    /**
+     * 商品价格,单位使用:分
+     */
+    private Integer price;
+    /**
+     * 市场价,单位使用:分
+     */
+    private Integer marketPrice;
+    /**
+     * 成本价,单位: 分
+     */
+    private Integer costPrice;
+    /**
+     * 库存
+     */
+    private Integer stock;
+    /**
+     * 配送方式数组
+     */
+    private String deliveryTypes;
+    /**
+     * 物流配置模板编号
+     */
+    private Long deliveryTemplateId;
+    /**
+     * 赠送积分
+     */
+    private Integer giveIntegral;
+    /**
+     * 分销类型
+     */
+    private Boolean subCommissionType;
+    /**
+     * 商品销量
+     */
+    private Integer salesCount;
+    /**
+     * 虚拟销量
+     */
+    private Integer virtualSalesCount;
+    /**
+     * 商品点击量
+     */
+    private Integer browseCount;
+    /**
+     * 店铺id
+     */
+    private Long shopId;
+    /**
+     * 商户id
+     */
+    private Long merchantId;
+    /**
+     * 是否隐藏。隐藏:1,不隐藏:0
+     */
+    private Boolean hidden;
+    /**
+     * 推广费, 单位: 分,值为sku中最大的推广费
+     */
+    private Integer promotionFee;
+    /**
+     * 商品支付类别(1 rmb 2积分)
+     */
+    private Integer spuPayType;
+    /**
+     * 高精度
+     */
+    private Boolean highPrecision;
+    /**
+     * 高精度价格
+     */
+    private BigDecimal highPrecisionPrice;
+    /**
+     * 申请用户id
+     */
+    private Long applyMemberUserId;
+    /**
+     * 审核系统用户id
+     */
+    private Long checkSystemUserId;
+    /**
+     * 审核时间
+     */
+    private LocalDateTime checkTime;
+    /**
+     * 审核意见
+     */
+    private String checkComment;
+    /**
+     * 审核状态:默认0表示未审核,1审核通过,2审核不通过
+     */
+    private Integer checkStatus;
+
+}

+ 44 - 0
feifan-module-mall/feifan-module-product-biz/src/main/java/cn/newfeifan/mall/module/product/dal/dataobject/spuapplylog/SpuApplyLogDO.java

@@ -0,0 +1,44 @@
+package cn.newfeifan.mall.module.product.dal.dataobject.spuapplylog;
+
+import lombok.*;
+import com.baomidou.mybatisplus.annotation.*;
+import cn.newfeifan.mall.framework.mybatis.core.dataobject.BaseDO;
+
+/**
+ * 商品审核记录 DO
+ *
+ * @author 非繁人
+ */
+@TableName("product_spu_apply_log")
+@KeySequence("product_spu_apply_log_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ToString(callSuper = true)
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class SpuApplyLogDO extends BaseDO {
+
+    /**
+     * spu审核记录id
+     */
+    @TableId
+    private Long id;
+    /**
+     * 申请状态  0:申请中 1:通过 2:未通过
+     */
+    private Integer status;
+    /**
+     * 商品申请id
+     */
+    private Long productSpuApplyId;
+    /**
+     * 审核系统用户id
+     */
+    private Long checkSystemUserId;
+    /**
+     * 审核意见
+     */
+    private String checkComment;
+
+}

+ 49 - 0
feifan-module-mall/feifan-module-product-biz/src/main/java/cn/newfeifan/mall/module/product/dal/mysql/skuapply/SkuApplyMapper.java

@@ -0,0 +1,49 @@
+package cn.newfeifan.mall.module.product.dal.mysql.skuapply;
+
+import java.util.*;
+
+import cn.newfeifan.mall.framework.common.pojo.PageResult;
+import cn.newfeifan.mall.framework.mybatis.core.query.LambdaQueryWrapperX;
+import cn.newfeifan.mall.framework.mybatis.core.mapper.BaseMapperX;
+import cn.newfeifan.mall.module.product.dal.dataobject.skuapply.SkuApplyDO;
+import org.apache.ibatis.annotations.Mapper;
+import cn.newfeifan.mall.module.product.controller.admin.skuapply.vo.*;
+
+/**
+ * 商品sku申请 Mapper
+ *
+ * @author 非繁人
+ */
+@Mapper
+public interface SkuApplyMapper extends BaseMapperX<SkuApplyDO> {
+
+    default PageResult<SkuApplyDO> selectPage(SkuApplyPageReqVO reqVO) {
+        return selectPage(reqVO, new LambdaQueryWrapperX<SkuApplyDO>()
+                .eqIfPresent(SkuApplyDO::getSpuApplyId, reqVO.getSpuApplyId())
+                .eqIfPresent(SkuApplyDO::getProperties, reqVO.getProperties())
+                .eqIfPresent(SkuApplyDO::getPrice, reqVO.getPrice())
+                .eqIfPresent(SkuApplyDO::getPromotionFee, reqVO.getPromotionFee())
+                .eqIfPresent(SkuApplyDO::getMark, reqVO.getMark())
+                .eqIfPresent(SkuApplyDO::getMarketPrice, reqVO.getMarketPrice())
+                .eqIfPresent(SkuApplyDO::getCostPrice, reqVO.getCostPrice())
+                .eqIfPresent(SkuApplyDO::getBarCode, reqVO.getBarCode())
+                .eqIfPresent(SkuApplyDO::getPicUrl, reqVO.getPicUrl())
+                .eqIfPresent(SkuApplyDO::getStock, reqVO.getStock())
+                .eqIfPresent(SkuApplyDO::getWeight, reqVO.getWeight())
+                .eqIfPresent(SkuApplyDO::getVolume, reqVO.getVolume())
+                .eqIfPresent(SkuApplyDO::getFirstBrokeragePrice, reqVO.getFirstBrokeragePrice())
+                .eqIfPresent(SkuApplyDO::getSecondBrokeragePrice, reqVO.getSecondBrokeragePrice())
+                .eqIfPresent(SkuApplyDO::getSalesCount, reqVO.getSalesCount())
+                .betweenIfPresent(SkuApplyDO::getCreateTime, reqVO.getCreateTime())
+                .eqIfPresent(SkuApplyDO::getShopId, reqVO.getShopId())
+                .eqIfPresent(SkuApplyDO::getMerchantId, reqVO.getMerchantId())
+                .eqIfPresent(SkuApplyDO::getHighPrecisionPrice, reqVO.getHighPrecisionPrice())
+                .eqIfPresent(SkuApplyDO::getSettlementPrice, reqVO.getSettlementPrice())
+                .eqIfPresent(SkuApplyDO::getHighPrecisionSettlementPrice, reqVO.getHighPrecisionSettlementPrice())
+                .orderByDesc(SkuApplyDO::getId));
+    }
+
+    default List<SkuApplyDO> selectListBySpuId(Long spuApplyId){
+        return selectList(SkuApplyDO::getSpuApplyId, spuApplyId);
+    }
+}

+ 64 - 0
feifan-module-mall/feifan-module-product-biz/src/main/java/cn/newfeifan/mall/module/product/dal/mysql/spuapply/SpuApplyMapper.java

@@ -0,0 +1,64 @@
+package cn.newfeifan.mall.module.product.dal.mysql.spuapply;
+
+
+import cn.newfeifan.mall.framework.common.pojo.PageResult;
+import cn.newfeifan.mall.framework.mybatis.core.query.LambdaQueryWrapperX;
+import cn.newfeifan.mall.framework.mybatis.core.mapper.BaseMapperX;
+import cn.newfeifan.mall.module.product.dal.dataobject.spuapply.SpuApplyDO;
+import org.apache.ibatis.annotations.Mapper;
+import cn.newfeifan.mall.module.product.controller.admin.spuapply.vo.*;
+import org.apache.ibatis.annotations.Select;
+
+/**
+ * 商品spu申请 Mapper
+ *
+ * @author 非繁人
+ */
+@Mapper
+public interface SpuApplyMapper extends BaseMapperX<SpuApplyDO> {
+
+    default PageResult<SpuApplyDO> selectPage(SpuApplyPageReqVO reqVO) {
+        return selectPage(reqVO, new LambdaQueryWrapperX<SpuApplyDO>()
+                .likeIfPresent(SpuApplyDO::getName, reqVO.getName())
+                .eqIfPresent(SpuApplyDO::getKeyword, reqVO.getKeyword())
+                .eqIfPresent(SpuApplyDO::getIntroduction, reqVO.getIntroduction())
+                .eqIfPresent(SpuApplyDO::getDescription, reqVO.getDescription())
+                .eqIfPresent(SpuApplyDO::getProducerArea, reqVO.getProducerArea())
+                .eqIfPresent(SpuApplyDO::getSpuType, reqVO.getSpuType())
+                .eqIfPresent(SpuApplyDO::getCategoryId, reqVO.getCategoryId())
+                .eqIfPresent(SpuApplyDO::getBrandId, reqVO.getBrandId())
+                .eqIfPresent(SpuApplyDO::getPicUrl, reqVO.getPicUrl())
+                .eqIfPresent(SpuApplyDO::getSliderPicUrls, reqVO.getSliderPicUrls())
+                .eqIfPresent(SpuApplyDO::getSort, reqVO.getSort())
+                .eqIfPresent(SpuApplyDO::getStatus, reqVO.getStatus())
+                .eqIfPresent(SpuApplyDO::getSpecType, reqVO.getSpecType())
+                .eqIfPresent(SpuApplyDO::getPrice, reqVO.getPrice())
+                .eqIfPresent(SpuApplyDO::getMarketPrice, reqVO.getMarketPrice())
+                .eqIfPresent(SpuApplyDO::getCostPrice, reqVO.getCostPrice())
+                .eqIfPresent(SpuApplyDO::getStock, reqVO.getStock())
+                .eqIfPresent(SpuApplyDO::getDeliveryTypes, reqVO.getDeliveryTypes())
+                .eqIfPresent(SpuApplyDO::getDeliveryTemplateId, reqVO.getDeliveryTemplateId())
+                .eqIfPresent(SpuApplyDO::getGiveIntegral, reqVO.getGiveIntegral())
+                .eqIfPresent(SpuApplyDO::getSubCommissionType, reqVO.getSubCommissionType())
+                .eqIfPresent(SpuApplyDO::getSalesCount, reqVO.getSalesCount())
+                .eqIfPresent(SpuApplyDO::getVirtualSalesCount, reqVO.getVirtualSalesCount())
+                .eqIfPresent(SpuApplyDO::getBrowseCount, reqVO.getBrowseCount())
+                .betweenIfPresent(SpuApplyDO::getCreateTime, reqVO.getCreateTime())
+                .eqIfPresent(SpuApplyDO::getShopId, reqVO.getShopId())
+                .eqIfPresent(SpuApplyDO::getMerchantId, reqVO.getMerchantId())
+                .eqIfPresent(SpuApplyDO::getHidden, reqVO.getHidden())
+                .eqIfPresent(SpuApplyDO::getPromotionFee, reqVO.getPromotionFee())
+                .eqIfPresent(SpuApplyDO::getSpuPayType, reqVO.getSpuPayType())
+                .eqIfPresent(SpuApplyDO::getHighPrecision, reqVO.getHighPrecision())
+                .eqIfPresent(SpuApplyDO::getHighPrecisionPrice, reqVO.getHighPrecisionPrice())
+                .eqIfPresent(SpuApplyDO::getApplyMemberUserId, reqVO.getApplyMemberUserId())
+                .eqIfPresent(SpuApplyDO::getCheckSystemUserId, reqVO.getCheckSystemUserId())
+                .betweenIfPresent(SpuApplyDO::getCheckTime, reqVO.getCheckTime())
+                .eqIfPresent(SpuApplyDO::getCheckComment, reqVO.getCheckComment())
+                .eqIfPresent(SpuApplyDO::getCheckStatus, reqVO.getCheckStatus())
+                .orderByDesc(SpuApplyDO::getId));
+    }
+
+    @Select("select name from sale_shop where id=#{id}")
+    String selectShopNameById(Long id);
+}

+ 29 - 0
feifan-module-mall/feifan-module-product-biz/src/main/java/cn/newfeifan/mall/module/product/dal/mysql/spuapplylog/SpuApplyLogMapper.java

@@ -0,0 +1,29 @@
+package cn.newfeifan.mall.module.product.dal.mysql.spuapplylog;
+
+
+import cn.newfeifan.mall.framework.common.pojo.PageResult;
+import cn.newfeifan.mall.framework.mybatis.core.query.LambdaQueryWrapperX;
+import cn.newfeifan.mall.framework.mybatis.core.mapper.BaseMapperX;
+import cn.newfeifan.mall.module.product.dal.dataobject.spuapplylog.SpuApplyLogDO;
+import org.apache.ibatis.annotations.Mapper;
+import cn.newfeifan.mall.module.product.controller.admin.spuapplylog.vo.*;
+
+/**
+ * 商品审核记录 Mapper
+ *
+ * @author 非繁人
+ */
+@Mapper
+public interface SpuApplyLogMapper extends BaseMapperX<SpuApplyLogDO> {
+
+    default PageResult<SpuApplyLogDO> selectPage(SpuApplyLogPageReqVO reqVO) {
+        return selectPage(reqVO, new LambdaQueryWrapperX<SpuApplyLogDO>()
+                .eqIfPresent(SpuApplyLogDO::getStatus, reqVO.getStatus())
+                .eqIfPresent(SpuApplyLogDO::getProductSpuApplyId, reqVO.getProductSpuApplyId())
+                .eqIfPresent(SpuApplyLogDO::getCheckSystemUserId, reqVO.getCheckSystemUserId())
+                .eqIfPresent(SpuApplyLogDO::getCheckComment, reqVO.getCheckComment())
+                .betweenIfPresent(SpuApplyLogDO::getCreateTime, reqVO.getCreateTime())
+                .orderByDesc(SpuApplyLogDO::getId));
+    }
+
+}

+ 61 - 0
feifan-module-mall/feifan-module-product-biz/src/main/java/cn/newfeifan/mall/module/product/service/skuapply/SkuApplyService.java

@@ -0,0 +1,61 @@
+package cn.newfeifan.mall.module.product.service.skuapply;
+
+import java.util.*;
+import javax.validation.*;
+import cn.newfeifan.mall.module.product.controller.admin.skuapply.vo.*;
+import cn.newfeifan.mall.module.product.dal.dataobject.skuapply.SkuApplyDO;
+import cn.newfeifan.mall.framework.common.pojo.PageResult;
+
+/**
+ * 商品sku申请 Service 接口
+ *
+ * @author 非繁人
+ */
+public interface SkuApplyService {
+
+    /**
+     * 创建商品sku申请
+     *
+     * @param createReqVO 创建信息
+     * @return 编号
+     */
+    Long createSkuApply(@Valid SkuApplySaveReqVO createReqVO);
+
+    /**
+     * 删除商品sku申请
+     *
+     * @param id 编号
+     */
+    void deleteSkuApply(Long id);
+
+    /**
+     * 获得商品sku申请
+     *
+     * @param id 编号
+     * @return 商品sku申请
+     */
+    SkuApplyDO getSkuApply(Long id);
+
+    /**
+     * 获得商品sku申请分页
+     *
+     * @param pageReqVO 分页查询
+     * @return 商品sku申请分页
+     */
+    PageResult<SkuApplyDO> getSkuApplyPage(SkuApplyPageReqVO pageReqVO);
+    /**
+     * 批量创建 SKU
+     *
+     * @param spuId 商品 SPU 编号
+     * @param list  SKU 对象集合
+     */
+    void createSkuList(Long spuId, List<SkuApplySaveReqVO> list);
+
+    /**
+     * 获得商品 SKU 申请 集合
+     *
+     * @param spuApplyId spu 申请 编号
+     * @return 商品sku 申请 集合
+     */
+    List<SkuApplyDO> getSkuListBySpuId(Long spuApplyId);
+}

+ 74 - 0
feifan-module-mall/feifan-module-product-biz/src/main/java/cn/newfeifan/mall/module/product/service/skuapply/SkuApplyServiceImpl.java

@@ -0,0 +1,74 @@
+package cn.newfeifan.mall.module.product.service.skuapply;
+
+import org.springframework.stereotype.Service;
+import javax.annotation.Resource;
+import org.springframework.validation.annotation.Validated;
+
+import java.util.*;
+import cn.newfeifan.mall.module.product.controller.admin.skuapply.vo.*;
+import cn.newfeifan.mall.module.product.dal.dataobject.skuapply.SkuApplyDO;
+import cn.newfeifan.mall.framework.common.pojo.PageResult;
+import cn.newfeifan.mall.framework.common.util.object.BeanUtils;
+
+import cn.newfeifan.mall.module.product.dal.mysql.skuapply.SkuApplyMapper;
+
+import static cn.newfeifan.mall.framework.common.exception.util.ServiceExceptionUtil.exception;
+import static cn.newfeifan.mall.module.product.enums.ErrorCodeConstants.*;
+
+/**
+ * 商品sku申请 Service 实现类
+ *
+ * @author 非繁人
+ */
+@Service
+@Validated
+public class SkuApplyServiceImpl implements SkuApplyService {
+
+    @Resource
+    private SkuApplyMapper skuApplyMapper;
+
+    @Override
+    public Long createSkuApply(SkuApplySaveReqVO createReqVO) {
+        // 插入
+        SkuApplyDO skuApply = BeanUtils.toBean(createReqVO, SkuApplyDO.class);
+        skuApplyMapper.insert(skuApply);
+        // 返回
+        return skuApply.getId();
+    }
+
+    @Override
+    public void deleteSkuApply(Long id) {
+        // 校验存在
+        validateSkuApplyExists(id);
+        // 删除
+        skuApplyMapper.deleteById(id);
+    }
+
+    private void validateSkuApplyExists(Long id) {
+        if (skuApplyMapper.selectById(id) == null) {
+            throw exception(SKU_APPLY_NOT_EXISTS);
+        }
+    }
+
+    @Override
+    public SkuApplyDO getSkuApply(Long id) {
+        return skuApplyMapper.selectById(id);
+    }
+
+    @Override
+    public PageResult<SkuApplyDO> getSkuApplyPage(SkuApplyPageReqVO pageReqVO) {
+        return skuApplyMapper.selectPage(pageReqVO);
+    }
+
+    @Override
+    public void createSkuList(Long spuId, List<SkuApplySaveReqVO> skuCreateReqList) {
+        List<SkuApplyDO> skus = BeanUtils.toBean(skuCreateReqList, SkuApplyDO.class, sku -> sku.setSpuApplyId(spuId));
+        skuApplyMapper.insertBatch(skus);
+    }
+
+    @Override
+    public List<SkuApplyDO> getSkuListBySpuId(Long spuApplyId) {
+        return skuApplyMapper.selectListBySpuId(spuApplyId);
+    }
+
+}

+ 60 - 0
feifan-module-mall/feifan-module-product-biz/src/main/java/cn/newfeifan/mall/module/product/service/spuapply/SpuApplyService.java

@@ -0,0 +1,60 @@
+package cn.newfeifan.mall.module.product.service.spuapply;
+
+import javax.validation.*;
+import cn.newfeifan.mall.module.product.controller.admin.spuapply.vo.*;
+import cn.newfeifan.mall.module.product.dal.dataobject.spuapply.SpuApplyDO;
+import cn.newfeifan.mall.framework.common.pojo.PageResult;
+
+/**
+ * 商品spu申请 Service 接口
+ *
+ * @author 非繁人
+ */
+public interface SpuApplyService {
+
+    /**
+     * 创建商品spu申请
+     *
+     * @param createReqVO 创建信息
+     * @return 编号
+     */
+    Long createSpuApply(@Valid SpuApplySaveReqVO createReqVO);
+
+    /**
+     * 更新商品spu申请
+     *
+     * @param updateReqVO 更新信息
+     */
+    void updateSpuApply(@Valid SpuApplySaveReqVO updateReqVO);
+
+    /**
+     * 删除商品spu申请
+     *
+     * @param id 编号
+     */
+    void deleteSpuApply(Long id);
+
+    /**
+     * 获得商品spu申请
+     *
+     * @param id 编号
+     * @return 商品spu申请
+     */
+    SpuApplyDO getSpuApply(Long id);
+
+    /**
+     * 获得商品spu申请分页
+     *
+     * @param pageReqVO 分页查询
+     * @return 商品spu申请分页
+     */
+    PageResult<SpuApplyDO> getSpuApplyPage(SpuApplyPageReqVO pageReqVO);
+
+    /**
+     * 获得商品 SPU 申请
+     *
+     * @param id 编号
+     * @return 商品 SPU 申请
+     */
+    SpuApplyDO getSpu(Long id);
+}

+ 140 - 0
feifan-module-mall/feifan-module-product-biz/src/main/java/cn/newfeifan/mall/module/product/service/spuapply/SpuApplyServiceImpl.java

@@ -0,0 +1,140 @@
+package cn.newfeifan.mall.module.product.service.spuapply;
+
+import cn.newfeifan.mall.module.product.controller.admin.skuapply.vo.SkuApplySaveReqVO;
+import cn.newfeifan.mall.module.product.controller.admin.spu.vo.ProductSkuSaveReqVO;
+import cn.newfeifan.mall.module.product.enums.spu.ProductSpuStatusEnum;
+import cn.newfeifan.mall.module.product.service.sku.ProductSkuService;
+import cn.newfeifan.mall.module.product.service.skuapply.SkuApplyService;
+import cn.newfeifan.mall.module.system.controller.admin.user.vo.user.UserShopDetailsVO;
+import cn.newfeifan.mall.module.system.service.user.AdminUserService;
+import org.springframework.context.annotation.Lazy;
+import org.springframework.stereotype.Service;
+
+import javax.annotation.Resource;
+
+import org.springframework.validation.annotation.Validated;
+
+import java.util.*;
+
+import cn.newfeifan.mall.module.product.controller.admin.spuapply.vo.*;
+import cn.newfeifan.mall.module.product.dal.dataobject.spuapply.SpuApplyDO;
+import cn.newfeifan.mall.framework.common.pojo.PageResult;
+import cn.newfeifan.mall.framework.common.util.object.BeanUtils;
+
+import cn.newfeifan.mall.module.product.dal.mysql.spuapply.SpuApplyMapper;
+
+import static cn.newfeifan.mall.framework.common.exception.util.ServiceExceptionUtil.exception;
+import static cn.newfeifan.mall.framework.common.util.collection.CollectionUtils.getMinValue;
+import static cn.newfeifan.mall.framework.common.util.collection.CollectionUtils.getSumValue;
+import static cn.newfeifan.mall.module.product.enums.ErrorCodeConstants.*;
+
+/**
+ * 商品spu申请 Service 实现类
+ *
+ * @author 非繁人
+ */
+@Service
+@Validated
+public class SpuApplyServiceImpl implements SpuApplyService {
+
+    @Resource
+    private SpuApplyMapper spuApplyMapper;
+    @Resource
+    private SkuApplyService skuApplyService;
+    @Resource
+    @Lazy // 循环依赖,避免报错
+    private ProductSkuService productSkuService;
+    @Resource
+    private AdminUserService adminUserService;
+
+    @Override
+    public Long createSpuApply(SpuApplySaveReqVO createReqVO) {
+        // 校验 SKU
+        List<SkuApplySaveReqVO> skuSaveReqList = createReqVO.getSkus();
+        productSkuService.validateSkuList(BeanUtils.toBean(skuSaveReqList, ProductSkuSaveReqVO.class), createReqVO.getSpecType(), createReqVO.getHighPrecision());
+
+        SpuApplyDO spuApply = BeanUtils.toBean(createReqVO, SpuApplyDO.class);
+        // 初始化 SPU 中 SKU 相关属性
+        initSpuFromSkus(spuApply, skuSaveReqList);
+        // 插入 SPU
+        spuApplyMapper.insert(spuApply);
+        // 插入 SKU
+        skuApplyService.createSkuList(spuApply.getId(), skuSaveReqList);
+        // 返回
+        return spuApply.getId();
+    }
+
+    /**
+     * 基于 SKU 的信息,初始化 SPU 的信息
+     * 主要是计数相关的字段,例如说市场价、最大最小价、库存等等
+     *
+     * @param spu  商品 SPU
+     * @param skus 商品 SKU 数组
+     */
+    private void initSpuFromSkus(SpuApplyDO spu, List<SkuApplySaveReqVO> skus) {
+        //是否是高精度商品
+        if (!spu.getHighPrecision()) {
+            // sku 单价最低的商品的价格
+            spu.setPrice(getMinValue(skus, SkuApplySaveReqVO::getPrice));
+            // sku 单价最低的商品的市场价格
+            spu.setMarketPrice(getMinValue(skus, SkuApplySaveReqVO::getMarketPrice));
+            // sku 单价最低的商品的成本价格
+            spu.setCostPrice(getMinValue(skus, SkuApplySaveReqVO::getCostPrice));
+        } else {
+            // sku 单价最低的商品的价格
+            spu.setHighPrecisionPrice(getMinValue(skus, SkuApplySaveReqVO::getHighPrecisionPrice));
+        }
+
+        // skus 库存总数
+        spu.setStock(getSumValue(skus, SkuApplySaveReqVO::getStock, Integer::sum));
+        // 若是 spu 已有状态则不处理
+        if (spu.getStatus() == null) {
+            spu.setStatus(ProductSpuStatusEnum.ENABLE.getStatus()); // 默认状态为上架
+            spu.setSalesCount(0); // 默认商品销量
+            spu.setBrowseCount(0); // 默认商品浏览量
+        }
+    }
+
+    @Override
+    public void updateSpuApply(SpuApplySaveReqVO updateReqVO) {
+        // 校验存在
+        validateSpuApplyExists(updateReqVO.getId());
+        // 更新
+        SpuApplyDO updateObj = BeanUtils.toBean(updateReqVO, SpuApplyDO.class);
+        spuApplyMapper.updateById(updateObj);
+    }
+
+    @Override
+    public void deleteSpuApply(Long id) {
+        // 校验存在
+        validateSpuApplyExists(id);
+        // 删除
+        spuApplyMapper.deleteById(id);
+    }
+
+    private void validateSpuApplyExists(Long id) {
+        if (spuApplyMapper.selectById(id) == null) {
+            throw exception(SPU_APPLY_NOT_EXISTS);
+        }
+    }
+
+    @Override
+    public SpuApplyDO getSpuApply(Long id) {
+        return spuApplyMapper.selectById(id);
+    }
+
+    @Override
+    public PageResult<SpuApplyDO> getSpuApplyPage(SpuApplyPageReqVO pageReqVO) {
+
+        UserShopDetailsVO userShopDetails = adminUserService.getUserShopDetails();
+        pageReqVO.setShopId(userShopDetails.getShopId());
+        pageReqVO.setMerchantId(userShopDetails.getMerId());
+        return spuApplyMapper.selectPage(pageReqVO);
+    }
+
+    @Override
+    public SpuApplyDO getSpu(Long id) {
+        return spuApplyMapper.selectById(id);
+    }
+
+}

+ 53 - 0
feifan-module-mall/feifan-module-product-biz/src/main/java/cn/newfeifan/mall/module/product/service/spuapplylog/SpuApplyLogService.java

@@ -0,0 +1,53 @@
+package cn.newfeifan.mall.module.product.service.spuapplylog;
+
+import javax.validation.*;
+import cn.newfeifan.mall.module.product.controller.admin.spuapplylog.vo.*;
+import cn.newfeifan.mall.module.product.dal.dataobject.spuapplylog.SpuApplyLogDO;
+import cn.newfeifan.mall.framework.common.pojo.PageResult;
+
+/**
+ * 商品审核记录 Service 接口
+ *
+ * @author 非繁人
+ */
+public interface SpuApplyLogService {
+
+    /**
+     * 创建商品审核记录
+     *
+     * @param createReqVO 创建信息
+     * @return 编号
+     */
+    Long createSpuApplyLog(@Valid SpuApplyLogSaveReqVO createReqVO);
+
+    /**
+     * 更新商品审核记录
+     *
+     * @param updateReqVO 更新信息
+     */
+    void updateSpuApplyLog(@Valid SpuApplyLogSaveReqVO updateReqVO);
+
+    /**
+     * 删除商品审核记录
+     *
+     * @param id 编号
+     */
+    void deleteSpuApplyLog(Long id);
+
+    /**
+     * 获得商品审核记录
+     *
+     * @param id 编号
+     * @return 商品审核记录
+     */
+    SpuApplyLogDO getSpuApplyLog(Long id);
+
+    /**
+     * 获得商品审核记录分页
+     *
+     * @param pageReqVO 分页查询
+     * @return 商品审核记录分页
+     */
+    PageResult<SpuApplyLogDO> getSpuApplyLogPage(SpuApplyLogPageReqVO pageReqVO);
+
+}

+ 70 - 0
feifan-module-mall/feifan-module-product-biz/src/main/java/cn/newfeifan/mall/module/product/service/spuapplylog/SpuApplyLogServiceImpl.java

@@ -0,0 +1,70 @@
+package cn.newfeifan.mall.module.product.service.spuapplylog;
+
+import org.springframework.stereotype.Service;
+import javax.annotation.Resource;
+import org.springframework.validation.annotation.Validated;
+import cn.newfeifan.mall.module.product.controller.admin.spuapplylog.vo.*;
+import cn.newfeifan.mall.module.product.dal.dataobject.spuapplylog.SpuApplyLogDO;
+import cn.newfeifan.mall.framework.common.pojo.PageResult;
+import cn.newfeifan.mall.framework.common.util.object.BeanUtils;
+
+import cn.newfeifan.mall.module.product.dal.mysql.spuapplylog.SpuApplyLogMapper;
+
+import static cn.newfeifan.mall.framework.common.exception.util.ServiceExceptionUtil.exception;
+import static cn.newfeifan.mall.module.product.enums.ErrorCodeConstants.*;
+
+/**
+ * 商品审核记录 Service 实现类
+ *
+ * @author 非繁人
+ */
+@Service
+@Validated
+public class SpuApplyLogServiceImpl implements SpuApplyLogService {
+
+    @Resource
+    private SpuApplyLogMapper spuApplyLogMapper;
+
+    @Override
+    public Long createSpuApplyLog(SpuApplyLogSaveReqVO createReqVO) {
+        // 插入
+        SpuApplyLogDO spuApplyLog = BeanUtils.toBean(createReqVO, SpuApplyLogDO.class);
+        spuApplyLogMapper.insert(spuApplyLog);
+        // 返回
+        return spuApplyLog.getId();
+    }
+
+    @Override
+    public void updateSpuApplyLog(SpuApplyLogSaveReqVO updateReqVO) {
+        // 校验存在
+        validateSpuApplyLogExists(updateReqVO.getId());
+        // 更新
+        SpuApplyLogDO updateObj = BeanUtils.toBean(updateReqVO, SpuApplyLogDO.class);
+        spuApplyLogMapper.updateById(updateObj);
+    }
+
+    @Override
+    public void deleteSpuApplyLog(Long id) {
+        // 校验存在
+        validateSpuApplyLogExists(id);
+        // 删除
+        spuApplyLogMapper.deleteById(id);
+    }
+
+    private void validateSpuApplyLogExists(Long id) {
+        if (spuApplyLogMapper.selectById(id) == null) {
+            throw exception(SPU_APPLY_LOG_NOT_EXISTS);
+        }
+    }
+
+    @Override
+    public SpuApplyLogDO getSpuApplyLog(Long id) {
+        return spuApplyLogMapper.selectById(id);
+    }
+
+    @Override
+    public PageResult<SpuApplyLogDO> getSpuApplyLogPage(SpuApplyLogPageReqVO pageReqVO) {
+        return spuApplyLogMapper.selectPage(pageReqVO);
+    }
+
+}

+ 12 - 0
feifan-module-mall/feifan-module-product-biz/src/main/resources/mapper/skuapply/SkuApplyMapper.xml

@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="cn.newfeifan.mall.module.product.dal.mysql.skuapply.SkuApplyMapper">
+
+    <!--
+        一般情况下,尽可能使用 Mapper 进行 CRUD 增删改查即可。
+        无法满足的场景,例如说多表关联查询,才使用 XML 编写 SQL。
+        代码生成器暂时只生成 Mapper XML 文件本身,更多推荐 MybatisX 快速开发插件来生成查询。
+        文档可见:https://www.zhongxing.cn/MyBatis/x-plugins/
+     -->
+
+</mapper>

+ 12 - 0
feifan-module-mall/feifan-module-product-biz/src/main/resources/mapper/spuapply/SpuApplyMapper.xml

@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="cn.newfeifan.mall.module.product.dal.mysql.spuapply.SpuApplyMapper">
+
+    <!--
+        一般情况下,尽可能使用 Mapper 进行 CRUD 增删改查即可。
+        无法满足的场景,例如说多表关联查询,才使用 XML 编写 SQL。
+        代码生成器暂时只生成 Mapper XML 文件本身,更多推荐 MybatisX 快速开发插件来生成查询。
+        文档可见:https://www.zhongxing.cn/MyBatis/x-plugins/
+     -->
+
+</mapper>

+ 12 - 0
feifan-module-mall/feifan-module-product-biz/src/main/resources/mapper/spuapplylog/SpuApplyLogMapper.xml

@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="cn.newfeifan.mall.module.product.dal.mysql.spuapplylog.SpuApplyLogMapper">
+
+    <!--
+        一般情况下,尽可能使用 Mapper 进行 CRUD 增删改查即可。
+        无法满足的场景,例如说多表关联查询,才使用 XML 编写 SQL。
+        代码生成器暂时只生成 Mapper XML 文件本身,更多推荐 MybatisX 快速开发插件来生成查询。
+        文档可见:https://www.zhongxing.cn/MyBatis/x-plugins/
+     -->
+
+</mapper>