Prechádzať zdrojové kódy

开发积分商城的功能

jinshihui 5 dní pred
rodič
commit
3e97d0bd9a
17 zmenil súbory, kde vykonal 290 pridanie a 294 odobranie
  1. 74 0
      nightFragrance-admin/src/main/java/com/ylx/web/controller/massage/ProductCategoryController.java
  2. 46 101
      nightFragrance-admin/src/main/java/com/ylx/web/controller/massage/ProductController.java
  3. 55 0
      nightFragrance-admin/src/main/java/com/ylx/web/controller/massage/ProductSpecController.java
  4. 15 8
      nightFragrance-massage/src/main/java/com/ylx/massage/domain/Product.java
  5. 0 63
      nightFragrance-massage/src/main/java/com/ylx/massage/domain/ProductImage.java
  6. 4 4
      nightFragrance-massage/src/main/java/com/ylx/massage/domain/ProductSku.java
  7. 6 0
      nightFragrance-massage/src/main/java/com/ylx/massage/domain/ProductSpec.java
  8. 6 0
      nightFragrance-massage/src/main/java/com/ylx/massage/domain/ProductSpecValue.java
  9. 23 10
      nightFragrance-massage/src/main/java/com/ylx/massage/domain/dto/ProductCreateDTO.java
  10. 4 6
      nightFragrance-massage/src/main/java/com/ylx/massage/domain/dto/ProductSkuDTO.java
  11. 6 0
      nightFragrance-massage/src/main/java/com/ylx/massage/domain/dto/ProductSpecSetupDTO.java
  12. 14 0
      nightFragrance-massage/src/main/java/com/ylx/massage/domain/vo/ProductDetailsVo.java
  13. 0 14
      nightFragrance-massage/src/main/java/com/ylx/massage/mapper/ProductImageMapper.java
  14. 0 14
      nightFragrance-massage/src/main/java/com/ylx/massage/service/ProductImageService.java
  15. 3 3
      nightFragrance-massage/src/main/java/com/ylx/massage/service/ProductService.java
  16. 0 18
      nightFragrance-massage/src/main/java/com/ylx/massage/service/impl/ProductImageServiceImpl.java
  17. 34 53
      nightFragrance-massage/src/main/java/com/ylx/massage/service/impl/ProductServiceImpl.java

+ 74 - 0
nightFragrance-admin/src/main/java/com/ylx/web/controller/massage/ProductCategoryController.java

@@ -0,0 +1,74 @@
+package com.ylx.web.controller.massage;
+
+import com.ylx.common.annotation.Log;
+import com.ylx.common.core.controller.BaseController;
+import com.ylx.common.core.domain.R;
+import com.ylx.common.enums.BusinessType;
+import com.ylx.massage.domain.ProductCategory;
+import com.ylx.massage.domain.vo.CategoryTreeVO;
+import com.ylx.massage.service.ProductCategoryService;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.web.bind.annotation.*;
+
+import javax.annotation.Resource;
+import java.util.List;
+
+@Slf4j
+@Api(tags = {"商品分类管理"})
+@RestController
+@RequestMapping("product")
+public class ProductCategoryController extends BaseController {
+
+    @Resource
+    private ProductCategoryService productCategoryService;
+
+    /**
+     * 新增商品分类
+     *
+     * @param category 分类实体
+     * @return R 新增结果
+     */
+    @PostMapping("category/create")
+    @ApiOperation("新增商品分类")
+    public R createCategory(@RequestBody ProductCategory category) {
+        return R.ok(productCategoryService.save(category));
+    }
+
+    /**
+     * 修改商品分类
+     *
+     * @param category 分类实体
+     * @return 修改结果
+     */
+    @PostMapping("category/update")
+    @Log(title = "商品分类修改", businessType = BusinessType.UPDATE)
+    @ApiOperation("修改商品分类")
+    public R updateCategory(@RequestBody ProductCategory category) {
+        return R.ok(productCategoryService.updateById(category));
+    }
+
+    /**
+     * 删除商品分类
+     *
+     * @param id 分类ID
+     * @return 删除结果
+     */
+    @PostMapping("category/delete")
+    @ApiOperation("删除商品分类")
+    public R deleteCategory(@RequestParam("id") Long id) {
+        return R.ok(productCategoryService.removeById(id));
+    }
+
+    /**
+     * 查询商品分类树形结构
+     *
+     * @return R<List<CategoryTreeVO>> 分类树形列表
+     */
+    @GetMapping("category/list")
+    @ApiOperation("查询商品分类树形结构")
+    public R<List<CategoryTreeVO>> categoryList() {
+        return R.ok(productCategoryService.getCategoryTree());
+    }
+}

+ 46 - 101
nightFragrance-admin/src/main/java/com/ylx/web/controller/massage/ProductController.java

@@ -1,5 +1,7 @@
 package com.ylx.web.controller.massage;
 
+import cn.hutool.core.bean.BeanUtil;
+import com.alibaba.fastjson2.JSON;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.ylx.common.annotation.Log;
@@ -12,6 +14,7 @@ import com.ylx.massage.domain.ProductCategory;
 import com.ylx.massage.domain.dto.ProductCreateDTO;
 import com.ylx.massage.domain.dto.ProductSpecSetupDTO;
 import com.ylx.massage.domain.vo.CategoryTreeVO;
+import com.ylx.massage.domain.vo.ProductDetailsVo;
 import com.ylx.massage.domain.vo.SpecComboVO;
 import com.ylx.massage.service.ProductCategoryService;
 import com.ylx.massage.service.ProductService;
@@ -45,8 +48,8 @@ public class ProductController extends BaseController {
      * 分页查询商品列表
      *
      * @param page    分页对象
-     * @param product 查询实体
-     * @return 所有数据
+     * @param product 商品实体
+     * @return R<Page<Product>> 所有数据
      */
     @RequestMapping(value = "/list", method = RequestMethod.GET)
     @ApiOperation("PC查询商品管理列表")
@@ -54,22 +57,33 @@ public class ProductController extends BaseController {
         LambdaQueryWrapper<Product> queryWrapper = new LambdaQueryWrapper<>();
         queryWrapper.eq(product.getCategoryId() != null, Product::getCategoryId, product.getCategoryId())
                 .like(StringUtils.isNotBlank(product.getName()), Product::getName, product.getName())
+                .like(StringUtils.isNotBlank(product.getProductNo()), Product::getProductNo, product.getProductNo())
                 .eq(product.getStatus() != null, Product::getStatus, product.getStatus())
-                .eq(product.getHasSpec() != null, Product::getHasSpec, product.getHasSpec())
-                .orderByDesc(Product::getCreatedAt);
+                .orderByDesc(Product::getCreateTime);
         return R.ok(this.productService.page(page, queryWrapper));
     }
 
     /**
-     * 通过主键查询单条数据
+     * 通过主键查询商品详情
      *
      * @param id 主键
-     * @return 单条数据
+     * @return R
      */
     @GetMapping("getById")
-    @ApiOperation("通过主键查询单条数据")
-    public R selectOne(Long id) {
-        return R.ok(this.productService.getById(id));
+    @ApiOperation("通过主键查询商品详情")
+    public R selectOne(@RequestParam Long id) {
+        try {
+            Product productServiceById = this.productService.getById(id);
+            //根据商品id查询商品的规格
+            List<SpecComboVO> specComboVOList = this.productService.getSpecCombinations(productServiceById.getProductNo());
+            ProductDetailsVo productDetailsVo = new ProductDetailsVo();
+            BeanUtil.copyProperties(productServiceById, productDetailsVo);
+            productDetailsVo.setSpecComboVOList(specComboVOList);
+            return R.ok(productDetailsVo);
+        } catch (Exception e) {
+            log.error("商品查询失败", e);
+            return R.fail("商品查询失败:" + e.getMessage());
+        }
     }
 
     /**
@@ -79,12 +93,11 @@ public class ProductController extends BaseController {
      * @return R 新增结果
      */
     @PostMapping("create")
-    @Log(title = "商品管理新增数据", businessType = BusinessType.INSERT)
     @ApiOperation("新增商品")
     public R create(@Valid @RequestBody ProductCreateDTO dto) {
         try {
             Long productId = productService.createProduct(dto);
-            return R.ok(productId, "商品创建成功");
+            return R.ok("商品ID:" + productId, "商品创建成功");
         } catch (Exception e) {
             log.error("商品创建失败", e);
             return R.fail("商品创建失败:" + e.getMessage());
@@ -92,26 +105,30 @@ public class ProductController extends BaseController {
     }
 
     /**
-     * 修改数据
+     * 修改商品
      *
-     * @param product 实体对象
-     * @return 修改结果
+     * @param product 商品实体对象
+     * @return R 修改结果
      */
     @PostMapping("update")
-    @Log(title = "商品管理修改数据", businessType = BusinessType.UPDATE)
-    @ApiOperation("修改数据")
+    @ApiOperation("修改商品")
     public R update(@RequestBody Product product) {
-        return R.ok(this.productService.updateById(product));
+        try {
+            return R.ok(this.productService.updateById(product));
+        } catch (Exception e) {
+            e.printStackTrace();
+            throw new RuntimeException(e);
+        }
     }
 
     /**
-     * 删除数据
+     * 删除商品
      *
      * @param idList 主键结合
-     * @return 删除结果
+     * @return R 删除结果
      */
     @PostMapping("delete")
-    @ApiOperation("删除数据")
+    @ApiOperation("删除商品")
     public R delete(@RequestBody List<Long> idList) {
         return R.ok(this.productService.removeByIds(idList));
     }
@@ -121,95 +138,23 @@ public class ProductController extends BaseController {
      *
      * @param id     商品ID
      * @param status 状态:1上架 0下架
-     * @return 操作结果
+     * @return R 操作结果
      */
     @PostMapping("updateStatus")
-    @Log(title = "商品管理上下架", businessType = BusinessType.UPDATE)
     @ApiOperation("上下架商品")
-    public R updateStatus(@RequestParam("id") Long id, @RequestParam("status") Integer status) {
-        Product product = new Product();
-        product.setId(id);
-        product.setStatus(status);
-        return R.ok(this.productService.updateById(product));
-    }
-
-    /**
-     * 查询商品分类树形结构
-     *
-     * @return R<List<CategoryTreeVO>> 分类树形列表
-     */
-    @GetMapping("category/list")
-    @ApiOperation("查询商品分类树形结构")
-    public R<List<CategoryTreeVO>> categoryList() {
-        return R.ok(productCategoryService.getCategoryTree());
-    }
-
-    /**
-     * 新增商品分类
-     *
-     * @param category 分类实体
-     * @return R 新增结果
-     */
-    @PostMapping("category/create")
-    @ApiOperation("新增商品分类")
-    public R createCategory(@RequestBody ProductCategory category) {
-        return R.ok(productCategoryService.save(category));
-    }
-
-    /**
-     * 修改商品分类
-     *
-     * @param category 分类实体
-     * @return 修改结果
-     */
-    @PostMapping("category/update")
-    @Log(title = "商品分类修改", businessType = BusinessType.UPDATE)
-    @ApiOperation("修改商品分类")
-    public R updateCategory(@RequestBody ProductCategory category) {
-        return R.ok(productCategoryService.updateById(category));
-    }
-
-    /**
-     * 删除商品分类
-     *
-     * @param id 分类ID
-     * @return 删除结果
-     */
-    @PostMapping("category/delete")
-    @ApiOperation("删除商品分类")
-    public R deleteCategory(@RequestParam("id") Long id) {
-        return R.ok(productCategoryService.removeById(id));
-    }
-
-    /**
-     * 新增商品规格
-     *
-     * @param dto 规格设置请求DTO
-     * @return R 操作结果
-     */
-    @PostMapping("spec/setup")
-    @ApiOperation("设置商品规格")
-    public R setupSpec(@Valid @RequestBody ProductSpecSetupDTO dto) {
+    public R updateStatus(@RequestBody Product productDto) {
         try {
-            productService.setupSpec(dto);
-            return R.ok("规格设置成功");
+            log.info("商品上下架请求:{}", JSON.toJSONString(productDto));
+            Product product = new Product();
+            product.setId(productDto.getId());
+            product.setStatus(productDto.getStatus());
+            return R.ok(this.productService.updateById(product));
         } catch (Exception e) {
-            log.error("规格设置失败", e);
-            return R.fail("规格设置失败:" + e.getMessage());
+            log.error("商品上下架失败", e);
+            return R.fail("商品上下架失败:" + e.getMessage());
         }
     }
 
-    /**
-     * 获取商品规格组合(笛卡尔积)
-     *
-     * @param productId 商品ID
-     * @return R<List<SpecComboVO>> 规格组合列表
-     */
-    @GetMapping("spec/combinations")
-    @ApiOperation("获取商品规格组合")
-    public R<List<SpecComboVO>> getSpecCombinations() {
-        return R.ok(productService.getSpecCombinations());
-    }
 
     /**
      * 生成商品编号

+ 55 - 0
nightFragrance-admin/src/main/java/com/ylx/web/controller/massage/ProductSpecController.java

@@ -0,0 +1,55 @@
+package com.ylx.web.controller.massage;
+
+import com.ylx.common.core.controller.BaseController;
+import com.ylx.common.core.domain.R;
+import com.ylx.massage.domain.dto.ProductSpecSetupDTO;
+import com.ylx.massage.domain.vo.SpecComboVO;
+import com.ylx.massage.service.ProductService;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.web.bind.annotation.*;
+
+import javax.annotation.Resource;
+import javax.validation.Valid;
+import java.util.List;
+@Slf4j
+@Api(tags = {"商品规格管理"})
+@RestController
+@RequestMapping("product")
+public class ProductSpecController extends BaseController {
+
+    @Resource
+    private ProductService productService;
+
+
+    /**
+     * 新增商品规格
+     *
+     * @param dto 规格设置请求DTO
+     * @return R 操作结果
+     */
+    @PostMapping("spec/setup")
+    @ApiOperation("新增商品规格")
+    public R setupSpec(@Valid @RequestBody ProductSpecSetupDTO dto) {
+        try {
+            productService.setupSpec(dto);
+            return R.ok("新增规格成功");
+        } catch (Exception e) {
+            log.error("新增规格失败", e);
+            return R.fail("新增规格失败:" + e.getMessage());
+        }
+    }
+
+    /**
+     * 获取商品规格组合(笛卡尔积)
+     *
+     * @param productId 商品ID
+     * @return R<List<SpecComboVO>> 规格组合列表
+     */
+    @GetMapping("spec/combinations")
+    @ApiOperation("获取商品规格组合")
+    public R<List<SpecComboVO>> getSpecCombinations(@RequestParam String productNo) {
+        return R.ok(productService.getSpecCombinations(productNo));
+    }
+}

+ 15 - 8
nightFragrance-massage/src/main/java/com/ylx/massage/domain/Product.java

@@ -7,6 +7,7 @@ import lombok.EqualsAndHashCode;
 import lombok.experimental.Accessors;
 import java.io.Serializable;
 import java.math.BigDecimal;
+import java.time.LocalDate;
 import java.time.LocalDateTime;
 import java.util.List;
 /**
@@ -71,6 +72,12 @@ public class Product implements Serializable {
     @TableField("detail")
     private String detail;
 
+    /**
+     * 付款类型(1:积分 2:金额 3:积分+金额)
+     */
+    @TableField("payment_type")
+    private Integer paymentType;
+
     /**
      * 积分价格
      */
@@ -118,15 +125,15 @@ public class Product implements Serializable {
      * 上架开始时间
      */
     @TableField("sale_start_time")
-    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "Asia/Shanghai")
-    private LocalDateTime saleStartTime;
+    @JsonFormat(pattern = "yyyy-MM-dd", timezone = "Asia/Shanghai")
+    private LocalDate saleStartTime;
 
     /**
      * 上架结束时间
      */
     @TableField("sale_end_time")
-    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "Asia/Shanghai")
-    private LocalDateTime saleEndTime;
+    @JsonFormat(pattern = "yyyy-MM-dd", timezone = "Asia/Shanghai")
+    private LocalDate saleEndTime;
 
     /**
      * 状态:1上架 0下架
@@ -143,16 +150,16 @@ public class Product implements Serializable {
     /**
      * 创建时间
      */
-    @TableField(value = "created_at", fill = FieldFill.INSERT)
+    @TableField(value = "create_time", fill = FieldFill.INSERT)
     @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "Asia/Shanghai")
-    private LocalDateTime createdAt;
+    private LocalDateTime createTime;
 
     /**
      * 更新时间
      */
-    @TableField(value = "updated_at", fill = FieldFill.INSERT_UPDATE)
+    @TableField(value = "update_time", fill = FieldFill.INSERT_UPDATE)
     @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "Asia/Shanghai")
-    private LocalDateTime updatedAt;
+    private LocalDateTime updateTime;
 
     /**
      * 逻辑删除:1已删除 0未删除

+ 0 - 63
nightFragrance-massage/src/main/java/com/ylx/massage/domain/ProductImage.java

@@ -1,63 +0,0 @@
-package com.ylx.massage.domain;
-
-import com.baomidou.mybatisplus.annotation.*;
-import com.fasterxml.jackson.annotation.JsonFormat;
-import lombok.Data;
-import lombok.EqualsAndHashCode;
-import lombok.experimental.Accessors;
-
-import java.io.Serializable;
-import java.time.LocalDateTime;
-
-/**
- * 商品图片表 实体类
- *
- * @author ylx
- * @since 2026-03-26
- */
-@Data
-@EqualsAndHashCode(callSuper = false)
-@Accessors(chain = true)
-@TableName("product_image")
-public class ProductImage implements Serializable {
-
-    private static final long serialVersionUID = 1L;
-
-    /**
-     * 主键
-     */
-    @TableId(value = "id", type = IdType.AUTO)
-    private Long id;
-
-    /**
-     * 商品ID
-     */
-    @TableField("product_id")
-    private Long productId;
-
-    /**
-     * 图片URL
-     */
-    @TableField("url")
-    private String url;
-
-    /**
-     * 类型:1主图 2副图
-     */
-    @TableField("type")
-    private Integer type;
-
-    /**
-     * 排序
-     */
-    @TableField("sort")
-    private Integer sort;
-
-    /**
-     * 创建时间
-     */
-    @TableField(value = "created_at", fill = FieldFill.INSERT)
-    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "Asia/Shanghai")
-    private LocalDateTime createdAt;
-
-}

+ 4 - 4
nightFragrance-massage/src/main/java/com/ylx/massage/domain/ProductSku.java

@@ -99,15 +99,15 @@ public class ProductSku implements Serializable {
     /**
      * 创建时间
      */
-    @TableField(value = "created_at", fill = FieldFill.INSERT)
+    @TableField(value = "create_time", fill = FieldFill.INSERT)
     @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "Asia/Shanghai")
-    private LocalDateTime createdAt;
+    private LocalDateTime createTime;
 
     /**
      * 更新时间
      */
-    @TableField(value = "updated_at", fill = FieldFill.INSERT_UPDATE)
+    @TableField(value = "update_time", fill = FieldFill.INSERT_UPDATE)
     @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "Asia/Shanghai")
-    private LocalDateTime updatedAt;
+    private LocalDateTime updateTime;
 
 }

+ 6 - 0
nightFragrance-massage/src/main/java/com/ylx/massage/domain/ProductSpec.java

@@ -32,6 +32,12 @@ public class ProductSpec implements Serializable {
     @TableField("product_id")
     private Long productId;
 
+    /**
+     * 商品编号
+     */
+    @TableField("product_no")
+    private String productNo;
+
     /**
      * 规格名(颜色/型号/尺码)
      */

+ 6 - 0
nightFragrance-massage/src/main/java/com/ylx/massage/domain/ProductSpecValue.java

@@ -41,6 +41,12 @@ public class ProductSpecValue implements Serializable {
     @TableField("product_id")
     private Long productId;
 
+    /**
+     * 商品编号
+     */
+    @TableField("product_no")
+    private String productNo;
+
     /**
      * 规格值(白色/红色/加粗)
      */

+ 23 - 10
nightFragrance-massage/src/main/java/com/ylx/massage/domain/dto/ProductCreateDTO.java

@@ -1,13 +1,16 @@
 package com.ylx.massage.domain.dto;
 
+import com.fasterxml.jackson.annotation.JsonFormat;
 import io.swagger.annotations.ApiModel;
 import io.swagger.annotations.ApiModelProperty;
 import lombok.Data;
+import org.springframework.format.annotation.DateTimeFormat;
 
 import javax.validation.Valid;
 import javax.validation.constraints.NotBlank;
 import javax.validation.constraints.NotNull;
 import java.math.BigDecimal;
+import java.time.LocalDate;
 import java.time.LocalDateTime;
 import java.util.List;
 
@@ -74,6 +77,12 @@ public class ProductCreateDTO {
     @Valid
     private List<ProductSpecDTO> specList;
 
+    /**
+     * 付款类型(1:积分 2:金额 3:积分+金额)
+     */
+    @ApiModelProperty(value = "付款类型", required = true)
+    private Integer paymentType;
+
     /**
      * SKU列表(规格组合明细)
      */
@@ -82,22 +91,22 @@ public class ProductCreateDTO {
     private List<ProductSkuDTO> skuList;
 
     /**
-     * 积分价格(无规格时使用)
+     * 积分价格
      */
-    @ApiModelProperty("积分价格")
-    private Integer pricePoint;
+    /*@ApiModelProperty("积分价格")
+    private Integer pricePoint;*/
 
     /**
-     * 现金价格(无规格时使用)
+     * 现金价格
      */
-    @ApiModelProperty("现金价格")
-    private BigDecimal priceMoney;
+    /*@ApiModelProperty("现金价格")
+    private BigDecimal priceMoney;*/
 
     /**
      * 库存(无规格时使用)
      */
-    @ApiModelProperty("库存")
-    private Integer stock;
+    /*@ApiModelProperty("库存")
+    private Integer stock;*/
 
     /**
      * 基础运费
@@ -122,11 +131,15 @@ public class ProductCreateDTO {
      * 上架开始时间
      */
     @ApiModelProperty("上架开始时间")
-    private LocalDateTime saleStartTime;
+    @JsonFormat(pattern = "yyyy-MM-dd", timezone = "Asia/Shanghai")
+    @DateTimeFormat(pattern = "yyyy-MM-dd")
+    private LocalDate saleStartTime;
 
     /**
      * 上架结束时间
      */
+    @JsonFormat(pattern = "yyyy-MM-dd", timezone = "Asia/Shanghai")
+    @DateTimeFormat(pattern = "yyyy-MM-dd")
     @ApiModelProperty("上架结束时间")
-    private LocalDateTime saleEndTime;
+    private LocalDate saleEndTime;
 }

+ 4 - 6
nightFragrance-massage/src/main/java/com/ylx/massage/domain/dto/ProductSkuDTO.java

@@ -26,8 +26,8 @@ public class ProductSkuDTO {
     /**
      * 规格值ID组合(如:1_3_5,前端传递规格值的索引组合)
      */
-    @ApiModelProperty(value = "规格值索引组合(如:0_1_2)", required = true)
-    private String specValueIndexCombo;
+    /*@ApiModelProperty(value = "规格值索引组合(如:0_1_2)", required = true)
+    private String specValueIndexCombo;*/
 
     /**
      * SKU图片URL
@@ -38,15 +38,13 @@ public class ProductSkuDTO {
     /**
      * 现金价格
      */
-    @ApiModelProperty(value = "现金价格", required = true)
-    @NotNull(message = "现金价格不能为空")
+    @ApiModelProperty(value = "现金价格", required = false)
     private BigDecimal priceMoney;
 
     /**
      * 积分价格
      */
-    @ApiModelProperty(value = "积分价格", required = true)
-    @NotNull(message = "积分价格不能为空")
+    @ApiModelProperty(value = "积分价格", required = false)
     private Integer pricePoint;
 
     /**

+ 6 - 0
nightFragrance-massage/src/main/java/com/ylx/massage/domain/dto/ProductSpecSetupDTO.java

@@ -1,5 +1,6 @@
 package com.ylx.massage.domain.dto;
 
+import com.baomidou.mybatisplus.annotation.TableField;
 import io.swagger.annotations.ApiModel;
 import io.swagger.annotations.ApiModelProperty;
 import lombok.Data;
@@ -18,6 +19,11 @@ import java.util.List;
 @ApiModel("商品规格设置请求")
 public class ProductSpecSetupDTO {
 
+    /**
+     * 商品编号
+     */
+    private String productNo;
+
     /**
      * 规格列表
      */

+ 14 - 0
nightFragrance-massage/src/main/java/com/ylx/massage/domain/vo/ProductDetailsVo.java

@@ -0,0 +1,14 @@
+package com.ylx.massage.domain.vo;
+
+import com.ylx.massage.domain.Product;
+import lombok.Data;
+
+import java.util.List;
+@Data
+public class ProductDetailsVo extends Product{
+
+    /**
+     * 商品规格组合列表
+     */
+    private List<SpecComboVO> specComboVOList;
+}

+ 0 - 14
nightFragrance-massage/src/main/java/com/ylx/massage/mapper/ProductImageMapper.java

@@ -1,14 +0,0 @@
-package com.ylx.massage.mapper;
-
-import com.baomidou.mybatisplus.core.mapper.BaseMapper;
-import com.ylx.massage.domain.ProductImage;
-
-/**
- * 商品图片表(ProductImage)表数据库访问层
- *
- * @author ylx
- * @since 2026-03-26
- */
-public interface ProductImageMapper extends BaseMapper<ProductImage> {
-
-}

+ 0 - 14
nightFragrance-massage/src/main/java/com/ylx/massage/service/ProductImageService.java

@@ -1,14 +0,0 @@
-package com.ylx.massage.service;
-
-import com.baomidou.mybatisplus.extension.service.IService;
-import com.ylx.massage.domain.ProductImage;
-
-/**
- * 商品图片表(ProductImage)表服务接口
- *
- * @author ylx
- * @since 2026-03-26
- */
-public interface ProductImageService extends IService<ProductImage> {
-
-}

+ 3 - 3
nightFragrance-massage/src/main/java/com/ylx/massage/service/ProductService.java

@@ -34,10 +34,10 @@ public interface ProductService extends IService<Product> {
     /**
      * 获取商品规格组合(笛卡尔积)
      *
-     * @param productId 商品ID
-     * @return 规格组合列表
+     * @param productNo 商品编号
+     * @return List<SpecComboVO> 规格组合列表
      */
-    List<SpecComboVO> getSpecCombinations();
+    List<SpecComboVO> getSpecCombinations(String productNo);
 
     /**
      * 生成商品编号

+ 0 - 18
nightFragrance-massage/src/main/java/com/ylx/massage/service/impl/ProductImageServiceImpl.java

@@ -1,18 +0,0 @@
-package com.ylx.massage.service.impl;
-
-import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
-import com.ylx.massage.domain.ProductImage;
-import com.ylx.massage.mapper.ProductImageMapper;
-import com.ylx.massage.service.ProductImageService;
-import org.springframework.stereotype.Service;
-
-/**
- * 商品图片表(ProductImage)表服务实现类
- *
- * @author ylx
- * @since 2026-03-26
- */
-@Service("productImageService")
-public class ProductImageServiceImpl extends ServiceImpl<ProductImageMapper, ProductImage> implements ProductImageService {
-
-}

+ 34 - 53
nightFragrance-massage/src/main/java/com/ylx/massage/service/impl/ProductServiceImpl.java

@@ -36,9 +36,6 @@ public class ProductServiceImpl extends ServiceImpl<ProductMapper, Product> impl
     @Resource
     private ProductCategoryMapper productCategoryMapper;
 
-    @Resource
-    private ProductImageMapper productImageMapper;
-
     @Resource
     private ProductSpecMapper productSpecMapper;
 
@@ -49,7 +46,10 @@ public class ProductServiceImpl extends ServiceImpl<ProductMapper, Product> impl
     private ProductSkuMapper productSkuMapper;
 
     /**
-     * 新增商品(包含规格、SKU、图片)
+     * 新增商品
+     *
+     * @param dto 新增商品请求DTO
+     * @return Long 商品ID
      */
     @Override
     @Transactional(rollbackFor = Exception.class)
@@ -60,61 +60,52 @@ public class ProductServiceImpl extends ServiceImpl<ProductMapper, Product> impl
             throw new RuntimeException("商品分类不存在");
         }
 
-        // 2. 生成商品编号
-        String productNo = generateProductNo(dto.getCategoryId());
-
-        // 3. 保存商品基本信息
+        // 2. 保存商品基本信息
         Product product = new Product();
-        product.setProductNo(productNo);
+        product.setProductNo(dto.getProductNo());
         product.setCategoryId(dto.getCategoryId());
         product.setName(dto.getName());
         product.setProductMainImage(dto.getProductMainImage());
         product.setProductImage(dto.getProductImage());
         product.setSummary(dto.getSummary());
         product.setDetail(dto.getDetail());
-        product.setPricePoint(dto.getPricePoint());
-        product.setPriceMoney(dto.getPriceMoney());
-        product.setStock(dto.getStock());
         product.setFreight(dto.getFreight());
         product.setDeliveryTime(dto.getDeliveryTime());
         product.setServicePromise(dto.getServicePromise());
         product.setSaleStartTime(dto.getSaleStartTime());
         product.setSaleEndTime(dto.getSaleEndTime());
         //product.setHasSpec(dto.getHasSpec());
+        // 设置付款方式
+        product.setPaymentType(dto.getPaymentType());
         product.setStatus(0); // 默认下架
         product.setSales(0); // 初始销量为0
         product.setDeleted(0); // 未删除
 
         // 计算总库存
         if (!CollectionUtils.isEmpty(dto.getSkuList())) {
-            int totalStock = dto.getSkuList().stream()
-                    .mapToInt(ProductSkuDTO::getStock)
-                    .sum();
+            int totalStock = dto.getSkuList().stream().mapToInt(ProductSkuDTO::getStock).sum();
             product.setStock(totalStock);
         }
 
         this.save(product);
         Long productId = product.getId();
 
-        // 4. 保存商品副图
-        saveProductImages(productId, dto.getProductImage());
-
-        // 5. 如果有规格,保存规格和SKU
+        // 3. 如果有规格,保存规格和SKU
         if (!CollectionUtils.isEmpty(dto.getSpecList())) {
             saveProductSpecsAndSkus(productId, dto);
         }
 
-        log.info("商品创建成功,商品ID:{},商品编号:{}", productId, productNo);
+        log.info("商品创建成功,商品ID:{},商品编号:{}", productId, dto.getProductNo());
         return productId;
     }
 
     /**
-     * 生成商品编号(公开方法,供Controller调用)
+     * 生成商品编号
      * 规则:分类编码 + 当前日期(yyyyMMdd) + 序列号(3位)
      * 示例:AD20260327001
      *
      * @param categoryId 分类ID
-     * @return 生成的商品编号
+     * @return String 生成的商品编号
      */
     @Override
     public String generateProductNo(Long categoryId) {
@@ -129,13 +120,12 @@ public class ProductServiceImpl extends ServiceImpl<ProductMapper, Product> impl
         if (categoryCode == null || categoryCode.trim().isEmpty()) {
             throw new RuntimeException("商品分类编码不存在");
         }
-
         // 3. 生成商品编号
         return generateProductNoByCategoryCode(categoryCode);
     }
 
     /**
-     * 根据分类编码生成商品编号(私有方法)
+     * 根据分类编码生成商品编号
      * 规则:分类编码 + 当前日期(yyyyMMdd) + 序列号(3位)
      *
      * @param categoryCode 分类编码
@@ -167,34 +157,28 @@ public class ProductServiceImpl extends ServiceImpl<ProductMapper, Product> impl
 
     /**
      * 保存商品图片
+     *
+     * @param productId 商品ID
+     * @param imageUrls 图片URL列表
      */
     private void saveProductImages(Long productId, List<String> imageUrls) {
         if (CollectionUtils.isEmpty(imageUrls)) {
             return;
         }
-
-        List<ProductImage> images = new ArrayList<>();
-        for (int i = 0; i < imageUrls.size(); i++) {
-            ProductImage image = new ProductImage();
-            image.setProductId(productId);
-            image.setUrl(imageUrls.get(i));
-            image.setType(2); // 副图
-            image.setSort(i + 1);
-            image.setCreatedAt(LocalDateTime.now());
-            images.add(image);
-        }
-        images.forEach(productImageMapper::insert);
     }
 
     /**
      * 保存商品规格和SKU
+     *
+     * @param productId 商品ID
+     * @param dto 商品创建DTO
      */
     private void saveProductSpecsAndSkus(Long productId, ProductCreateDTO dto) {
         List<ProductSpecDTO> specList = dto.getSpecList();
         List<ProductSkuDTO> skuList = dto.getSkuList();
 
         if (CollectionUtils.isEmpty(specList) || CollectionUtils.isEmpty(skuList)) {
-            throw new RuntimeException("规格商品必须包含规格和SKU信息");
+            throw new RuntimeException("商品必须包含规格和SKU信息");
         }
 
         // 保存规格名和规格值,并记录ID映射
@@ -206,7 +190,6 @@ public class ProductServiceImpl extends ServiceImpl<ProductMapper, Product> impl
             spec.setProductId(productId);
             spec.setSpecName(specDTO.getSpecName());
             spec.setSort(specDTO.getSort() != null ? specDTO.getSort() : specIndex.get() + 1);
-            spec.setCreateTime(LocalDateTime.now());
             productSpecMapper.insert(spec);
             Long specId = spec.getId();
 
@@ -233,16 +216,14 @@ public class ProductServiceImpl extends ServiceImpl<ProductMapper, Product> impl
             sku.setProductId(productId);
             sku.setSkuNo(generateSkuNo(productId));
             sku.setSpecCombo(skuDTO.getSpecCombo());
-            sku.setSpecValueIds(skuDTO.getSpecValueIndexCombo());
             sku.setImage(skuDTO.getImage());
+            //sku.setSpecValueIds(skuDTO.getSpecValueIndexCombo());
             sku.setPriceMoney(skuDTO.getPriceMoney());
             sku.setPricePoint(skuDTO.getPricePoint());
             sku.setOriginPrice(skuDTO.getOriginPrice());
             sku.setStock(skuDTO.getStock());
             sku.setSales(0);
             sku.setStatus(1);
-            sku.setCreatedAt(LocalDateTime.now());
-            sku.setUpdatedAt(LocalDateTime.now());
             productSkuMapper.insert(sku);
         }
     }
@@ -266,7 +247,7 @@ public class ProductServiceImpl extends ServiceImpl<ProductMapper, Product> impl
             for (ProductSpecSetupDTO.SpecItemDTO specItem : dto.getSpecList()) {
                 // 保存规格名
                 ProductSpec spec = new ProductSpec();
-                //spec.setProductId(productId);
+                spec.setProductNo(dto.getProductNo());
                 // 检查规格名是否存在,如果存在,则直接通过,不插入
                 LambdaQueryWrapper<ProductSpec> specWrapper = new LambdaQueryWrapper<>();
                 specWrapper.eq(ProductSpec::getSpecName, specItem.getSpecName());
@@ -276,7 +257,6 @@ public class ProductServiceImpl extends ServiceImpl<ProductMapper, Product> impl
                 }
                 spec.setSpecName(specItem.getSpecName());
                 spec.setSort(specItem.getSort() != null ? specItem.getSort() : specIndex.get() + 1);
-                spec.setCreateTime(LocalDateTime.now());
                 productSpecMapper.insert(spec);
                 Long specId = spec.getId();
 
@@ -286,10 +266,9 @@ public class ProductServiceImpl extends ServiceImpl<ProductMapper, Product> impl
                     for (ProductSpecSetupDTO.SpecValueItemDTO valueItem : specItem.getSpecValues()) {
                         ProductSpecValue specValue = new ProductSpecValue();
                         specValue.setSpecId(specId);
-                        //specValue.setProductId(productId);
+                        specValue.setProductNo(dto.getProductNo());
                         specValue.setSpecValue(valueItem.getSpecValue());
                         specValue.setSort(valueItem.getSort() != null ? valueItem.getSort() : valueIndex.get() + 1);
-                        specValue.setCreateTime(LocalDateTime.now());
                         productSpecValueMapper.insert(specValue);
                         valueIndex.getAndIncrement();
                     }
@@ -301,23 +280,23 @@ public class ProductServiceImpl extends ServiceImpl<ProductMapper, Product> impl
 
     /**
      * 获取商品规格组合(笛卡尔积)
+     * @param productId 商品ID
+     * @return List<SpecComboVO> 规格组合列表
      */
     @Override
-    public List<SpecComboVO> getSpecCombinations() {
-        // 查询商品的所有规格名
+    public List<SpecComboVO> getSpecCombinations(String productNo) {
+        // 根据商品编号查询商品的所有规格名
         LambdaQueryWrapper<ProductSpec> specWrapper = new LambdaQueryWrapper<>();
-        //specWrapper.eq(ProductSpec::getProductId, productId).orderByAsc(ProductSpec::getSort);
-        specWrapper.orderByAsc(ProductSpec::getSort);
+        specWrapper.eq(ProductSpec::getProductNo, productNo).orderByAsc(ProductSpec::getSort);
         List<ProductSpec> specList = productSpecMapper.selectList(specWrapper);
 
         if (CollectionUtils.isEmpty(specList)) {
             return Collections.emptyList();
         }
 
-        // 查询所有规格值,按规格名分组
+        // 查询所有规格值
         LambdaQueryWrapper<ProductSpecValue> valueWrapper = new LambdaQueryWrapper<>();
-        //valueWrapper.eq(ProductSpecValue::getProductId, productId).orderByAsc(ProductSpecValue::getSort);
-        valueWrapper.orderByAsc(ProductSpecValue::getSort);
+        valueWrapper.eq(ProductSpecValue::getProductNo, productNo).orderByAsc(ProductSpecValue::getSort);
         List<ProductSpecValue> allValues = productSpecValueMapper.selectList(valueWrapper);
 
         // 按规格名ID分组
@@ -356,7 +335,6 @@ public class ProductServiceImpl extends ServiceImpl<ProductMapper, Product> impl
 
             /*List<Long> specValueIds = combo.stream().map(SpecComboVO.SpecNameValue::getSpecValueId).collect(Collectors.toList());
             vo.setSpecValueIds(specValueIds);*/
-
             vo.setSpecValueText(String.join(",", specValues));
             vo.setSpecNameValueList(combo);
             result.add(vo);
@@ -366,6 +344,9 @@ public class ProductServiceImpl extends ServiceImpl<ProductMapper, Product> impl
 
     /**
      * 计算笛卡尔积
+     *
+     * @param lists 规格值列表列表
+     * @return List<List<T>> 笛卡尔积结果
      */
     private <T> List<List<T>> cartesianProduct(List<List<T>> lists) {
         if (lists.isEmpty()) {