Kaynağa Gözat

Merge branch 'refs/heads/xiaolu' into master

肖路 2 ay önce
ebeveyn
işleme
f634a3aecb
65 değiştirilmiş dosya ile 4600 ekleme ve 160 silme
  1. 50 0
      ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/controller/pc/CustomerIndexController.java
  2. 106 0
      ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/controller/ProcurementGroupController.java
  3. 106 0
      ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/controller/ProcurementProgramController.java
  4. 115 0
      ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/controller/ProcurementProgramProductController.java
  5. 106 0
      ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/controller/ProcurementTopicsController.java
  6. 106 0
      ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/controller/ProductSpecialLinkController.java
  7. 69 2
      ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/controller/pc/BenefitsProductController.java
  8. 163 11
      ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/controller/pc/IndexProductController.java
  9. 11 6
      ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/controller/pc/IndustryProductController.java
  10. 22 8
      ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/controller/pc/MyProductController.java
  11. 69 0
      ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/domain/ProcurementGroup.java
  12. 136 0
      ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/domain/ProcurementProgram.java
  13. 62 0
      ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/domain/ProcurementProgramProduct.java
  14. 156 0
      ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/domain/ProcurementTopics.java
  15. 7 0
      ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/domain/ProductGiftCategoryLink.java
  16. 57 0
      ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/domain/ProductSpecialLink.java
  17. 12 0
      ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/domain/bo/PcProductBo.java
  18. 67 0
      ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/domain/bo/ProcurementGroupBo.java
  19. 135 0
      ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/domain/bo/ProcurementProgramBo.java
  20. 57 0
      ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/domain/bo/ProcurementProgramProductBo.java
  21. 159 0
      ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/domain/bo/ProcurementTopicsBo.java
  22. 53 0
      ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/domain/bo/ProductSpecialLinkBo.java
  23. 5 0
      ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/domain/vo/PcProductVo.java
  24. 82 0
      ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/domain/vo/ProcurementGroupVo.java
  25. 70 0
      ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/domain/vo/ProcurementProgramProductVo.java
  26. 165 0
      ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/domain/vo/ProcurementProgramVo.java
  27. 190 0
      ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/domain/vo/ProcurementTopicsVo.java
  28. 5 0
      ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/domain/vo/ProductBaseVo.java
  29. 63 0
      ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/domain/vo/ProductSpecialLinkVo.java
  30. 4 0
      ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/domain/vo/ServiceCaseVo.java
  31. 15 0
      ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/mapper/ProcurementGroupMapper.java
  32. 15 0
      ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/mapper/ProcurementProgramMapper.java
  33. 15 0
      ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/mapper/ProcurementProgramProductMapper.java
  34. 15 0
      ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/mapper/ProcurementTopicsMapper.java
  35. 15 0
      ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/mapper/ProductSpecialLinkMapper.java
  36. 70 0
      ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/service/IProcurementGroupService.java
  37. 80 0
      ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/service/IProcurementProgramProductService.java
  38. 70 0
      ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/service/IProcurementProgramService.java
  39. 70 0
      ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/service/IProcurementTopicsService.java
  40. 46 7
      ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/service/IProductBaseService.java
  41. 15 0
      ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/service/IProductBrandService.java
  42. 9 0
      ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/service/IProductCategoryService.java
  43. 70 0
      ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/service/IProductSpecialLinkService.java
  44. 138 0
      ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/service/impl/ProcurementGroupServiceImpl.java
  45. 178 0
      ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/service/impl/ProcurementProgramProductServiceImpl.java
  46. 151 0
      ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/service/impl/ProcurementProgramServiceImpl.java
  47. 155 0
      ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/service/impl/ProcurementTopicsServiceImpl.java
  48. 580 80
      ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/service/impl/ProductBaseServiceImpl.java
  49. 88 11
      ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/service/impl/ProductBrandServiceImpl.java
  50. 47 2
      ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/service/impl/ProductCategoryServiceImpl.java
  51. 136 0
      ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/service/impl/ProductSpecialLinkServiceImpl.java
  52. 47 10
      ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/service/impl/ProtocolProductsServiceImpl.java
  53. 7 0
      ruoyi-modules/ruoyi-product/src/main/resources/mapper/product/ProcurementGroupMapper.xml
  54. 7 0
      ruoyi-modules/ruoyi-product/src/main/resources/mapper/product/ProcurementProgramMapper.xml
  55. 7 0
      ruoyi-modules/ruoyi-product/src/main/resources/mapper/product/ProcurementProgramProductMapper.xml
  56. 7 0
      ruoyi-modules/ruoyi-product/src/main/resources/mapper/product/ProcurementTopicsMapper.xml
  57. 2 1
      ruoyi-modules/ruoyi-product/src/main/resources/mapper/product/ProductBaseMapper.xml
  58. 7 0
      ruoyi-modules/ruoyi-product/src/main/resources/mapper/product/ProductSpecialLinkMapper.xml
  59. 7 0
      ruoyi-modules/ruoyi-product/src/main/resources/mapper/product/ProtocolInfoMapper.xml
  60. 7 0
      ruoyi-modules/ruoyi-product/src/main/resources/mapper/product/ProtocolProductsMapper.xml
  61. 9 9
      ruoyi-modules/ruoyi-resource/src/main/java/org/dromara/resource/controller/FileCategoryController.java
  62. 12 12
      ruoyi-modules/ruoyi-resource/src/main/java/org/dromara/resource/controller/FileInfoController.java
  63. 39 0
      ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/pc/BenefitsSystemController.java
  64. 55 0
      ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/pc/IndexSystemController.java
  65. 1 1
      ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/pc/IndustrySystemController.java

+ 50 - 0
ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/controller/pc/CustomerIndexController.java

@@ -0,0 +1,50 @@
+package org.dromara.customer.controller.pc;
+
+import lombok.RequiredArgsConstructor;
+import org.dromara.common.core.domain.R;
+import org.dromara.customer.domain.bo.CustomerTagBo;
+import org.dromara.customer.domain.bo.IndustryCategoryBo;
+import org.dromara.customer.domain.vo.CustomerTagVo;
+import org.dromara.customer.domain.vo.IndustryCategoryVo;
+import org.dromara.customer.service.ICustomerTagService;
+import org.dromara.customer.service.IIndustryCategoryService;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.util.List;
+
+/**
+ * 首页
+ * @author
+ * @date 2026/1/29 上午10:15
+ */
+@Validated
+@RequiredArgsConstructor
+@RestController
+@RequestMapping("/indexCustomer")
+public class CustomerIndexController {
+
+    //客户行业
+    private final IIndustryCategoryService industryCategoryService;
+    //推荐标签
+    private final ICustomerTagService customerTagService;
+
+
+
+    /**
+    * 客户行业
+    * */
+    @GetMapping("/getCustomerIndustry")
+    public R<List<IndustryCategoryVo>> getCustomerIndustry() {
+        return R.ok(industryCategoryService.queryList(new IndustryCategoryBo()));
+    }
+    /**
+    * 推荐标签
+    * */
+    @GetMapping("/getCustomerTag")
+    public R<List<CustomerTagVo>> getCustomerTag() {
+        return R.ok(customerTagService.queryList(new CustomerTagBo()));
+    }
+}

+ 106 - 0
ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/controller/ProcurementGroupController.java

@@ -0,0 +1,106 @@
+package org.dromara.product.controller;
+
+import java.util.List;
+
+import lombok.RequiredArgsConstructor;
+import jakarta.servlet.http.HttpServletResponse;
+import jakarta.validation.constraints.*;
+import cn.dev33.satoken.annotation.SaCheckPermission;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.validation.annotation.Validated;
+import org.dromara.common.idempotent.annotation.RepeatSubmit;
+import org.dromara.common.log.annotation.Log;
+import org.dromara.common.web.core.BaseController;
+import org.dromara.common.mybatis.core.page.PageQuery;
+import org.dromara.common.core.domain.R;
+import org.dromara.common.core.validate.AddGroup;
+import org.dromara.common.core.validate.EditGroup;
+import org.dromara.common.log.enums.BusinessType;
+import org.dromara.common.excel.utils.ExcelUtil;
+import org.dromara.product.domain.vo.ProcurementGroupVo;
+import org.dromara.product.domain.bo.ProcurementGroupBo;
+import org.dromara.product.service.IProcurementGroupService;
+import org.dromara.common.mybatis.core.page.TableDataInfo;
+
+/**
+ * 采购组信息
+ * 前端访问路由地址为:/product/group
+ *
+ * @author LionLi
+ * @date 2026-02-06
+ */
+@Validated
+@RequiredArgsConstructor
+@RestController
+@RequestMapping("/group")
+public class ProcurementGroupController extends BaseController {
+
+    private final IProcurementGroupService procurementGroupService;
+
+    /**
+     * 查询采购组信息列表
+     */
+    //@SaCheckPermission("product:group:list")
+    @GetMapping("/list")
+    public TableDataInfo<ProcurementGroupVo> list(ProcurementGroupBo bo, PageQuery pageQuery) {
+        return procurementGroupService.queryPageList(bo, pageQuery);
+    }
+
+    /**
+     * 导出采购组信息列表
+     */
+    //@SaCheckPermission("product:group:export")
+    @Log(title = "采购组信息", businessType = BusinessType.EXPORT)
+    @PostMapping("/export")
+    public void export(ProcurementGroupBo bo, HttpServletResponse response) {
+        List<ProcurementGroupVo> list = procurementGroupService.queryList(bo);
+        ExcelUtil.exportExcel(list, "采购组信息", ProcurementGroupVo.class, response);
+    }
+
+    /**
+     * 获取采购组信息详细信息
+     *
+     * @param id 主键
+     */
+    //@SaCheckPermission("product:group:query")
+    @GetMapping("/{id}")
+    public R<ProcurementGroupVo> getInfo(@NotNull(message = "主键不能为空")
+                                     @PathVariable("id") Long id) {
+        return R.ok(procurementGroupService.queryById(id));
+    }
+
+    /**
+     * 新增采购组信息
+     */
+    //@SaCheckPermission("product:group:add")
+    @Log(title = "采购组信息", businessType = BusinessType.INSERT)
+    @RepeatSubmit()
+    @PostMapping()
+    public R<Void> add(@Validated(AddGroup.class) @RequestBody ProcurementGroupBo bo) {
+        return toAjax(procurementGroupService.insertByBo(bo));
+    }
+
+    /**
+     * 修改采购组信息
+     */
+    //@SaCheckPermission("product:group:edit")
+    @Log(title = "采购组信息", businessType = BusinessType.UPDATE)
+    @RepeatSubmit()
+    @PutMapping()
+    public R<Void> edit(@Validated(EditGroup.class) @RequestBody ProcurementGroupBo bo) {
+        return toAjax(procurementGroupService.updateByBo(bo));
+    }
+
+    /**
+     * 删除采购组信息
+     *
+     * @param ids 主键串
+     */
+    //@SaCheckPermission("product:group:remove")
+    @Log(title = "采购组信息", businessType = BusinessType.DELETE)
+    @DeleteMapping("/{ids}")
+    public R<Void> remove(@NotEmpty(message = "主键不能为空")
+                          @PathVariable("ids") Long[] ids) {
+        return toAjax(procurementGroupService.deleteWithValidByIds(List.of(ids), true));
+    }
+}

+ 106 - 0
ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/controller/ProcurementProgramController.java

@@ -0,0 +1,106 @@
+package org.dromara.product.controller;
+
+import java.util.List;
+
+import lombok.RequiredArgsConstructor;
+import jakarta.servlet.http.HttpServletResponse;
+import jakarta.validation.constraints.*;
+import cn.dev33.satoken.annotation.SaCheckPermission;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.validation.annotation.Validated;
+import org.dromara.common.idempotent.annotation.RepeatSubmit;
+import org.dromara.common.log.annotation.Log;
+import org.dromara.common.web.core.BaseController;
+import org.dromara.common.mybatis.core.page.PageQuery;
+import org.dromara.common.core.domain.R;
+import org.dromara.common.core.validate.AddGroup;
+import org.dromara.common.core.validate.EditGroup;
+import org.dromara.common.log.enums.BusinessType;
+import org.dromara.common.excel.utils.ExcelUtil;
+import org.dromara.product.domain.vo.ProcurementProgramVo;
+import org.dromara.product.domain.bo.ProcurementProgramBo;
+import org.dromara.product.service.IProcurementProgramService;
+import org.dromara.common.mybatis.core.page.TableDataInfo;
+
+/**
+ * 采购项目
+ * 前端访问路由地址为:/product/program
+ *
+ * @author LionLi
+ * @date 2026-02-06
+ */
+@Validated
+@RequiredArgsConstructor
+@RestController
+@RequestMapping("/procurementProgram")
+public class ProcurementProgramController extends BaseController {
+
+    private final IProcurementProgramService procurementProgramService;
+
+    /**
+     * 查询采购项目列表
+     */
+    //@SaCheckPermission("product:program:list")
+    @GetMapping("/list")
+    public TableDataInfo<ProcurementProgramVo> list(ProcurementProgramBo bo, PageQuery pageQuery) {
+        return procurementProgramService.queryPageList(bo, pageQuery);
+    }
+
+    /**
+     * 导出采购项目列表
+     */
+    //@SaCheckPermission("product:program:export")
+    @Log(title = "采购项目", businessType = BusinessType.EXPORT)
+    @PostMapping("/export")
+    public void export(ProcurementProgramBo bo, HttpServletResponse response) {
+        List<ProcurementProgramVo> list = procurementProgramService.queryList(bo);
+        ExcelUtil.exportExcel(list, "采购项目", ProcurementProgramVo.class, response);
+    }
+
+    /**
+     * 获取采购项目详细信息
+     *
+     * @param id 主键
+     */
+    //@SaCheckPermission("product:program:query")
+    @GetMapping("/{id}")
+    public R<ProcurementProgramVo> getInfo(@NotNull(message = "主键不能为空")
+                                     @PathVariable("id") Long id) {
+        return R.ok(procurementProgramService.queryById(id));
+    }
+
+    /**
+     * 新增采购项目
+     */
+    //@SaCheckPermission("product:program:add")
+    @Log(title = "采购项目", businessType = BusinessType.INSERT)
+    @RepeatSubmit()
+    @PostMapping()
+    public R<Void> add(@Validated(AddGroup.class) @RequestBody ProcurementProgramBo bo) {
+        return toAjax(procurementProgramService.insertByBo(bo));
+    }
+
+    /**
+     * 修改采购项目
+     */
+    //@SaCheckPermission("product:program:edit")
+    @Log(title = "采购项目", businessType = BusinessType.UPDATE)
+    @RepeatSubmit()
+    @PutMapping()
+    public R<Void> edit(@Validated(EditGroup.class) @RequestBody ProcurementProgramBo bo) {
+        return toAjax(procurementProgramService.updateByBo(bo));
+    }
+
+    /**
+     * 删除采购项目
+     *
+     * @param ids 主键串
+     */
+    //@SaCheckPermission("product:program:remove")
+    @Log(title = "采购项目", businessType = BusinessType.DELETE)
+    @DeleteMapping("/{ids}")
+    public R<Void> remove(@NotEmpty(message = "主键不能为空")
+                          @PathVariable("ids") Long[] ids) {
+        return toAjax(procurementProgramService.deleteWithValidByIds(List.of(ids), true));
+    }
+}

+ 115 - 0
ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/controller/ProcurementProgramProductController.java

@@ -0,0 +1,115 @@
+package org.dromara.product.controller;
+
+import java.util.List;
+
+import lombok.RequiredArgsConstructor;
+import jakarta.servlet.http.HttpServletResponse;
+import jakarta.validation.constraints.*;
+import cn.dev33.satoken.annotation.SaCheckPermission;
+import org.dromara.product.domain.vo.ProductBaseVo;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.validation.annotation.Validated;
+import org.dromara.common.idempotent.annotation.RepeatSubmit;
+import org.dromara.common.log.annotation.Log;
+import org.dromara.common.web.core.BaseController;
+import org.dromara.common.mybatis.core.page.PageQuery;
+import org.dromara.common.core.domain.R;
+import org.dromara.common.core.validate.AddGroup;
+import org.dromara.common.core.validate.EditGroup;
+import org.dromara.common.log.enums.BusinessType;
+import org.dromara.common.excel.utils.ExcelUtil;
+import org.dromara.product.domain.vo.ProcurementProgramProductVo;
+import org.dromara.product.domain.bo.ProcurementProgramProductBo;
+import org.dromara.product.service.IProcurementProgramProductService;
+import org.dromara.common.mybatis.core.page.TableDataInfo;
+
+/**
+ * 采购项目产品关联
+ * 前端访问路由地址为:/product/programProduct
+ *
+ * @author LionLi
+ * @date 2026-02-06
+ */
+@Validated
+@RequiredArgsConstructor
+@RestController
+@RequestMapping("/programProduct")
+public class ProcurementProgramProductController extends BaseController {
+
+    private final IProcurementProgramProductService procurementProgramProductService;
+
+    /**
+     * 查询采购项目产品关联列表
+     */
+    //@SaCheckPermission("product:programProduct:list")
+    @GetMapping("/list")
+    public TableDataInfo<ProcurementProgramProductVo> list(ProcurementProgramProductBo bo, PageQuery pageQuery) {
+        return procurementProgramProductService.queryPageList(bo, pageQuery);
+    }
+
+    /**
+     * 导出采购项目产品关联列表
+     */
+    //@SaCheckPermission("product:programProduct:export")
+    @Log(title = "采购项目产品关联", businessType = BusinessType.EXPORT)
+    @PostMapping("/export")
+    public void export(ProcurementProgramProductBo bo, HttpServletResponse response) {
+        List<ProcurementProgramProductVo> list = procurementProgramProductService.queryList(bo);
+        ExcelUtil.exportExcel(list, "采购项目产品关联", ProcurementProgramProductVo.class, response);
+    }
+
+    /**
+     * 获取采购项目产品关联详细信息
+     *
+     * @param id 主键
+     */
+    //@SaCheckPermission("product:programProduct:query")
+    @GetMapping("/{id}")
+    public R<ProcurementProgramProductVo> getInfo(@NotNull(message = "主键不能为空")
+                                     @PathVariable("id") Long id) {
+        return R.ok(procurementProgramProductService.queryById(id));
+    }
+
+    /**
+     * 新增采购项目产品关联
+     */
+    //@SaCheckPermission("product:programProduct:add")
+    @Log(title = "采购项目产品关联", businessType = BusinessType.INSERT)
+    @RepeatSubmit()
+    @PostMapping()
+    public R<Void> add(@Validated(AddGroup.class) @RequestBody ProcurementProgramProductBo bo) {
+        return toAjax(procurementProgramProductService.insertByBo(bo));
+    }
+
+    /**
+     * 修改采购项目产品关联
+     */
+    //@SaCheckPermission("product:programProduct:edit")
+    @Log(title = "采购项目产品关联", businessType = BusinessType.UPDATE)
+    @RepeatSubmit()
+    @PutMapping()
+    public R<Void> edit(@Validated(EditGroup.class) @RequestBody ProcurementProgramProductBo bo) {
+        return toAjax(procurementProgramProductService.updateByBo(bo));
+    }
+
+    /**
+     * 删除采购项目产品关联
+     *
+     * @param ids 主键串
+     */
+    //@SaCheckPermission("product:programProduct:remove")
+    @Log(title = "采购项目产品关联", businessType = BusinessType.DELETE)
+    @DeleteMapping("/{ids}")
+    public R<Void> remove(@NotEmpty(message = "主键不能为空")
+                          @PathVariable("ids") Long[] ids) {
+        return toAjax(procurementProgramProductService.deleteWithValidByIds(List.of(ids), true));
+    }
+
+    /**
+    * 获取采购方案分组关联的商品列表
+    * */
+    @GetMapping("/groupProductPage")
+    public TableDataInfo<ProductBaseVo> groupProductPage(Long groupId, PageQuery pageQuery) {
+        return procurementProgramProductService.groupProductPage(groupId, pageQuery);
+    }
+}

+ 106 - 0
ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/controller/ProcurementTopicsController.java

@@ -0,0 +1,106 @@
+package org.dromara.product.controller;
+
+import java.util.List;
+
+import lombok.RequiredArgsConstructor;
+import jakarta.servlet.http.HttpServletResponse;
+import jakarta.validation.constraints.*;
+import cn.dev33.satoken.annotation.SaCheckPermission;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.validation.annotation.Validated;
+import org.dromara.common.idempotent.annotation.RepeatSubmit;
+import org.dromara.common.log.annotation.Log;
+import org.dromara.common.web.core.BaseController;
+import org.dromara.common.mybatis.core.page.PageQuery;
+import org.dromara.common.core.domain.R;
+import org.dromara.common.core.validate.AddGroup;
+import org.dromara.common.core.validate.EditGroup;
+import org.dromara.common.log.enums.BusinessType;
+import org.dromara.common.excel.utils.ExcelUtil;
+import org.dromara.product.domain.vo.ProcurementTopicsVo;
+import org.dromara.product.domain.bo.ProcurementTopicsBo;
+import org.dromara.product.service.IProcurementTopicsService;
+import org.dromara.common.mybatis.core.page.TableDataInfo;
+
+/**
+ * 采购主题
+ * 前端访问路由地址为:/product/topics
+ *
+ * @author LionLi
+ * @date 2026-02-06
+ */
+@Validated
+@RequiredArgsConstructor
+@RestController
+@RequestMapping("/topics")
+public class ProcurementTopicsController extends BaseController {
+
+    private final IProcurementTopicsService procurementTopicsService;
+
+    /**
+     * 查询采购主题列表
+     */
+    //@SaCheckPermission("product:topics:list")
+    @GetMapping("/list")
+    public TableDataInfo<ProcurementTopicsVo> list(ProcurementTopicsBo bo, PageQuery pageQuery) {
+        return procurementTopicsService.queryPageList(bo, pageQuery);
+    }
+
+    /**
+     * 导出采购主题列表
+     */
+    //@SaCheckPermission("product:topics:export")
+    @Log(title = "采购主题", businessType = BusinessType.EXPORT)
+    @PostMapping("/export")
+    public void export(ProcurementTopicsBo bo, HttpServletResponse response) {
+        List<ProcurementTopicsVo> list = procurementTopicsService.queryList(bo);
+        ExcelUtil.exportExcel(list, "采购主题", ProcurementTopicsVo.class, response);
+    }
+
+    /**
+     * 获取采购主题详细信息
+     *
+     * @param id 主键
+     */
+    //@SaCheckPermission("product:topics:query")
+    @GetMapping("/{id}")
+    public R<ProcurementTopicsVo> getInfo(@NotNull(message = "主键不能为空")
+                                     @PathVariable("id") Long id) {
+        return R.ok(procurementTopicsService.queryById(id));
+    }
+
+    /**
+     * 新增采购主题
+     */
+    //@SaCheckPermission("product:topics:add")
+    @Log(title = "采购主题", businessType = BusinessType.INSERT)
+    @RepeatSubmit()
+    @PostMapping()
+    public R<Void> add(@Validated(AddGroup.class) @RequestBody ProcurementTopicsBo bo) {
+        return toAjax(procurementTopicsService.insertByBo(bo));
+    }
+
+    /**
+     * 修改采购主题
+     */
+    //@SaCheckPermission("product:topics:edit")
+    @Log(title = "采购主题", businessType = BusinessType.UPDATE)
+    @RepeatSubmit()
+    @PutMapping()
+    public R<Void> edit(@Validated(EditGroup.class) @RequestBody ProcurementTopicsBo bo) {
+        return toAjax(procurementTopicsService.updateByBo(bo));
+    }
+
+    /**
+     * 删除采购主题
+     *
+     * @param ids 主键串
+     */
+    //@SaCheckPermission("product:topics:remove")
+    @Log(title = "采购主题", businessType = BusinessType.DELETE)
+    @DeleteMapping("/{ids}")
+    public R<Void> remove(@NotEmpty(message = "主键不能为空")
+                          @PathVariable("ids") Long[] ids) {
+        return toAjax(procurementTopicsService.deleteWithValidByIds(List.of(ids), true));
+    }
+}

+ 106 - 0
ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/controller/ProductSpecialLinkController.java

@@ -0,0 +1,106 @@
+package org.dromara.product.controller;
+
+import java.util.List;
+
+import lombok.RequiredArgsConstructor;
+import jakarta.servlet.http.HttpServletResponse;
+import jakarta.validation.constraints.*;
+import cn.dev33.satoken.annotation.SaCheckPermission;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.validation.annotation.Validated;
+import org.dromara.common.idempotent.annotation.RepeatSubmit;
+import org.dromara.common.log.annotation.Log;
+import org.dromara.common.web.core.BaseController;
+import org.dromara.common.mybatis.core.page.PageQuery;
+import org.dromara.common.core.domain.R;
+import org.dromara.common.core.validate.AddGroup;
+import org.dromara.common.core.validate.EditGroup;
+import org.dromara.common.log.enums.BusinessType;
+import org.dromara.common.excel.utils.ExcelUtil;
+import org.dromara.product.domain.vo.ProductSpecialLinkVo;
+import org.dromara.product.domain.bo.ProductSpecialLinkBo;
+import org.dromara.product.service.IProductSpecialLinkService;
+import org.dromara.common.mybatis.core.page.TableDataInfo;
+
+/**
+ * 特价商品
+ * 前端访问路由地址为:/product/specialLink
+ *
+ * @author LionLi
+ * @date 2026-02-10
+ */
+@Validated
+@RequiredArgsConstructor
+@RestController
+@RequestMapping("/specialLink")
+public class ProductSpecialLinkController extends BaseController {
+
+    private final IProductSpecialLinkService productSpecialLinkService;
+
+    /**
+     * 查询特价商品列表
+     */
+    //@SaCheckPermission("product:specialLink:list")
+    @GetMapping("/list")
+    public TableDataInfo<ProductSpecialLinkVo> list(ProductSpecialLinkBo bo, PageQuery pageQuery) {
+        return productSpecialLinkService.queryPageList(bo, pageQuery);
+    }
+
+    /**
+     * 导出特价商品列表
+     */
+    //@SaCheckPermission("product:specialLink:export")
+    @Log(title = "特价商品", businessType = BusinessType.EXPORT)
+    @PostMapping("/export")
+    public void export(ProductSpecialLinkBo bo, HttpServletResponse response) {
+        List<ProductSpecialLinkVo> list = productSpecialLinkService.queryList(bo);
+        ExcelUtil.exportExcel(list, "特价商品", ProductSpecialLinkVo.class, response);
+    }
+
+    /**
+     * 获取特价商品详细信息
+     *
+     * @param id 主键
+     */
+    //@SaCheckPermission("product:specialLink:query")
+    @GetMapping("/{id}")
+    public R<ProductSpecialLinkVo> getInfo(@NotNull(message = "主键不能为空")
+                                     @PathVariable("id") Long id) {
+        return R.ok(productSpecialLinkService.queryById(id));
+    }
+
+    /**
+     * 新增特价商品
+     */
+    //@SaCheckPermission("product:specialLink:add")
+    @Log(title = "特价商品", businessType = BusinessType.INSERT)
+    @RepeatSubmit()
+    @PostMapping()
+    public R<Void> add(@Validated(AddGroup.class) @RequestBody ProductSpecialLinkBo bo) {
+        return toAjax(productSpecialLinkService.insertByBo(bo));
+    }
+
+    /**
+     * 修改特价商品
+     */
+    //@SaCheckPermission("product:specialLink:edit")
+    @Log(title = "特价商品", businessType = BusinessType.UPDATE)
+    @RepeatSubmit()
+    @PutMapping()
+    public R<Void> edit(@Validated(EditGroup.class) @RequestBody ProductSpecialLinkBo bo) {
+        return toAjax(productSpecialLinkService.updateByBo(bo));
+    }
+
+    /**
+     * 删除特价商品
+     *
+     * @param ids 主键串
+     */
+    //@SaCheckPermission("product:specialLink:remove")
+    @Log(title = "特价商品", businessType = BusinessType.DELETE)
+    @DeleteMapping("/{ids}")
+    public R<Void> remove(@NotEmpty(message = "主键不能为空")
+                          @PathVariable("ids") Long[] ids) {
+        return toAjax(productSpecialLinkService.deleteWithValidByIds(List.of(ids), true));
+    }
+}

+ 69 - 2
ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/controller/pc/BenefitsProductController.java

@@ -1,9 +1,15 @@
 package org.dromara.product.controller.pc;
 
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import lombok.RequiredArgsConstructor;
 import org.dromara.common.core.domain.R;
+import org.dromara.common.mybatis.core.page.PageQuery;
+import org.dromara.common.mybatis.core.page.TableDataInfo;
+import org.dromara.product.domain.ProductGiftFloor;
+import org.dromara.product.domain.bo.PcProductBo;
 import org.dromara.product.domain.bo.ProductGiftCategoryBo;
-import org.dromara.product.domain.vo.ProductGiftCategoryVo;
+import org.dromara.product.domain.bo.ProductGiftNoticeBo;
+import org.dromara.product.domain.vo.*;
 import org.dromara.product.service.*;
 import org.springframework.validation.annotation.Validated;
 import org.springframework.web.bind.annotation.GetMapping;
@@ -14,7 +20,7 @@ import java.util.List;
 
 /**
  *
- * 工业商城
+ * 福利商城
  * @author
  * @date 2026/2/6 上午11:31
  */
@@ -60,4 +66,65 @@ public class BenefitsProductController {
     public R<List<ProductGiftCategoryVo>> getGiftCategoryList() {
         return R.ok(productGiftCategoryService.queryList(new ProductGiftCategoryBo()));
     }
+
+    /**
+     * 获取福利分类下的商品(福利装修-分类管理)
+     * */
+    @GetMapping("getGiftCategoryLinkPage")
+    public TableDataInfo<PcProductVo> getGiftCategoryLinkPage(PcProductBo bo, PageQuery pageQuery) {
+
+        return productBaseService.getGiftCategoryLinkPage(bo,pageQuery);
+    }
+
+    /**
+    * 获取楼层广告列表(福利装修-楼层广告)
+    * */
+    @GetMapping("getAdvertisementGiftFloorList")
+    public R<List<ProductGiftFloor>> getGiftFloorList() {
+        List<ProductGiftFloor> list = productGiftFloorService.list(Wrappers.lambdaQuery(ProductGiftFloor.class)
+            .eq(ProductGiftFloor::getType, 1)
+        );
+        return R.ok(list);
+    }
+    /**
+     * 热门定制(福利装修-热门定制)
+     */
+    @GetMapping("getHotCustomGiftFloorList")
+    public R<List<ProductGiftFloor>> getHotCustomGiftFloorList() {
+        List<ProductGiftFloor> list = productGiftFloorService.list(Wrappers.lambdaQuery(ProductGiftFloor.class)
+            .eq(ProductGiftFloor::getType, 2)
+        );
+        return R.ok(list);
+    }
+    /**
+     * 为你推荐(福利装修-为你推荐)
+     */
+    @GetMapping("getRecommendGiftFloorList")
+    public R<List<ProductGiftFloor>> getRecommendGiftFloorList() {
+        List<ProductGiftFloor> list = productGiftFloorService.list(Wrappers.lambdaQuery(ProductGiftFloor.class)
+            .eq(ProductGiftFloor::getType, 3)
+        );
+        return R.ok(list);
+    }
+    /**
+    * 获取楼层广告下的商品(福利装修-楼层广告)(福利装修-热门定制)(福利装修-为你推荐)
+    * */
+    @GetMapping("getGiftFloorLinkProductList")
+    public R<List<PcProductVo>> getGiftFloorLinkProductList(Long floorId) {
+        List<PcProductVo> list =  productBaseService.getGiftFloorLinkProductList(floorId);
+        return R.ok(list);
+    }
+
+    /**
+     * 公告管理(福利装修-公告管理)
+     */
+    @GetMapping("getNoticeList")
+    public R<List<ProductGiftNoticeVo>> getNoticeList() {
+        ProductGiftNoticeBo productGiftNoticeBo = new ProductGiftNoticeBo();
+        List<ProductGiftNoticeVo> list = productGiftNoticeService.queryList(productGiftNoticeBo);
+        return R.ok(list);
+    }
+
+
+
 }

+ 163 - 11
ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/controller/pc/IndexProductController.java

@@ -1,13 +1,12 @@
 package org.dromara.product.controller.pc;
 
 import cn.hutool.core.lang.tree.Tree;
+import cn.hutool.http.HttpUtil;
 import lombok.RequiredArgsConstructor;
 import org.dromara.common.core.domain.R;
 import org.dromara.common.mybatis.core.page.PageQuery;
 import org.dromara.common.mybatis.core.page.TableDataInfo;
-import org.dromara.product.domain.bo.PcProductBo;
-import org.dromara.product.domain.bo.ProductBrandBo;
-import org.dromara.product.domain.bo.ProductCategoryBo;
+import org.dromara.product.domain.bo.*;
 import org.dromara.product.domain.vo.*;
 import org.dromara.product.service.*;
 import org.springframework.validation.annotation.Validated;
@@ -56,7 +55,30 @@ public class IndexProductController {
     private final IProductDecorationFloorLinkService productDecorationFloorLinkService;
     //项目案例
     private final IServiceCaseService serviceCaseService;
-    //收藏
+    //采购方案
+    private final IProcurementProgramService procurementProgramService;
+    //采购方案下的分组
+    private final IProcurementGroupService procurementGroupService;
+    //采购指南
+    private final IProcurementTopicsService procurementTopicsService;
+    //特价商品
+    private final IProductSpecialLinkService productSpecialLinkService;
+
+    public static void main(String[] args) {
+        String string = HttpUtil.get("http://127.0.0.1:8080/product/indexProduct/getEsProductList");
+        System.out.println(string);
+    }
+    /**
+    * 获取es商品
+    * */
+    @GetMapping("getEsProductList")
+    public TableDataInfo<ProductBaseVo> getEsProductList() {
+        ProductBaseBo productBaseBo = new ProductBaseBo();
+
+        TableDataInfo<ProductBaseVo> productBaseVoTableDataInfo = productBaseService.queryPageList(productBaseBo, new PageQuery());
+
+        return productBaseVoTableDataInfo;
+    }
 
     /**
     * 商品列表接口
@@ -86,6 +108,14 @@ public class IndexProductController {
         return R.ok(productCategoryService.selectCategoryTreeList(bo));
     }
 
+    /**
+    * 查看分类列表
+    * */
+    @GetMapping("getProductCategoryList")
+    public R<List<ProductCategoryVo>> getProductCategoryList(ProductCategoryBo bo) {
+        return R.ok(productCategoryService.queryList(bo));
+    }
+
     /**
     * 查询行家精选商品列表(平台装修-特价管理)
     * */
@@ -146,14 +176,136 @@ public class IndexProductController {
         return productBaseService.getCategoryRecommendProductPage(categoryId, pageQuery);
     }
 
-//    /**
-//    * 查询协议供货的商品信息
-//    * */
-//    @GetMapping("/getAgreementSupplyProductList")
-//    public TableDataInfo<PcProductVo> getAgreementSupplyProductList(PageQuery pageQuery) {
-//        return productBaseService.getAgreementSupplyProductList(pageQuery);
-//    }
+    /**
+    * 采购方案列表
+    * */
+    @GetMapping("/getProcurementProgramList")
+    public TableDataInfo<ProcurementProgramVo> getProcurementProgramList(ProcurementProgramBo bo, PageQuery pageQuery) {
+        bo.setIsShow(1L);
+        return procurementProgramService.queryPageList(bo,pageQuery);
+    }
+
+    /**
+    * 采购方案详情
+    * */
+    @GetMapping("/getProcurementProgramDetail/{programId}")
+    public R<ProcurementProgramVo> getProcurementProgramDetail(@PathVariable Long programId) {
+        return R.ok(procurementProgramService.queryById(programId));
+    }
+
+    /**
+    * 获取采购方案下的分组
+    * */
+    @GetMapping("/getProcurementProgramGroupList/{programId}")
+    public R<List<ProcurementGroupVo>> getProcurementProgramGroupList(@PathVariable Long programId) {
+        ProcurementGroupBo bo = new ProcurementGroupBo();
+        bo.setProgramId(programId);
+        return R.ok(procurementGroupService.queryList(bo));
+    }
+    /**
+    * 获取采购方案分组下的商品
+    * */
+    @GetMapping("/getProcurementProgramGroupProductList")
+    public TableDataInfo<PcProductVo> getProcurementProgramGroupProductList(Long groupId,PageQuery pageQuery) {
+        return productBaseService.getProcurementProgramGroupProductList(groupId,pageQuery);
+    }
+
+
+    /**
+    * 采购指南列表
+    * */
+    @GetMapping("/getPurchaseGuideList")
+    public TableDataInfo<ProcurementTopicsVo> getPurchaseGuideList(ProcurementTopicsBo bo, PageQuery pageQuery) {
+        bo.setIsShow(1L);
+        return procurementTopicsService.queryPageList(bo,pageQuery);
+    }
+
+    /**
+    * 采购指南详情
+    * */
+    @GetMapping("/getPurchaseGuideDetail/{guideId}")
+    public R<ProcurementTopicsVo> getPurchaseGuideDetail(@PathVariable Long guideId) {
+        return R.ok(procurementTopicsService.queryById(guideId));
+    }
+    /**
+    * 项目案例列表
+    * */
+    @GetMapping("/getProjectCaseAllList")
+    public TableDataInfo<ServiceCaseVo> getProjectCaseAllList(ServiceCaseBo bo, PageQuery pageQuery) {
+        bo.setIsShow("1");
+        return serviceCaseService.queryPageList(bo,pageQuery);
+    }
+    /**
+    * 项目案例详情
+    * */
+    @GetMapping("/getProjectCaseDetail/{caseId}")
+    public R<ServiceCaseVo> getProjectCaseDetail(@PathVariable Long caseId) {
+        return R.ok(serviceCaseService.queryById(caseId));
+    }
+
+    /**
+    * 查询场景采购信息列表
+    * */
+    @GetMapping("/getProductProgramPage")
+    public TableDataInfo<ProductProgramVo> getProductProgramPage(ProductProgramBo bo, PageQuery pageQuery) {
+        bo.setIsShow("1");
+        return productProgramService.queryPageList(bo,pageQuery);
+    }
+
+    /**
+    * 查询场景采购详情
+    * */
+    @GetMapping("/getProductProgramDetail/{programId}")
+    public R<ProductProgramVo> getProductProgramDetail(@PathVariable Long programId) {
+        return R.ok(productProgramService.queryById(programId));
+    }
 
+    /**
+    * 获取场景采购下的商品
+    * */
+    @GetMapping("/getProductProgramProductList/{programId}")
+    public R<List<PcProductVo>> getProductProgramProductList(@PathVariable Long programId) {
+        return R.ok(productBaseService.getProductProgramProductList(programId));
+    }
+
+    /**
+    * 通过分类去查询品牌
+    * */
+    @GetMapping("/getBrandByCategoryList")
+    public TableDataInfo<ProductBrandVo> getBrandByCategoryList(Long categoryId,String name,String initial,PageQuery pageQuery) {
+
+        return productBrandService.getBrandByCategoryList(categoryId,name,initial,pageQuery);
+    }
+
+    /**
+    * 品牌详情
+    * */
+    @GetMapping("/getBrandDetail/{brandId}")
+    public R<ProductBrandVo> getBrandDetail(@PathVariable Long brandId) {
+        return R.ok(productBrandService.queryById(brandId));
+    }
+
+    /**
+    * 特价商品分类
+    * */
+    @GetMapping("/getSpecialCategoryList")
+    public R<List<ProductCategoryVo>> getSpecialCategoryList() {
+        return R.ok(productCategoryService.getSpecialCategoryList());
+    }
+    /**
+    * 特价商品品牌
+    * */
+    @GetMapping("/getSpecialBrandList")
+    public R<List<ProductBrandVo>> getSpecialBrandList() {
+        return R.ok(productBrandService.getSpecialBrandList());
+    }
+    /**
+    * 特价商品
+    * */
+    @GetMapping("/getSpecialProductList")
+    public TableDataInfo<PcProductVo> getSpecialProductList(PcProductBo bo, PageQuery pageQuery) {
+        return productBaseService.getSpecialProductList(bo,pageQuery);
+    }
 
 
 

+ 11 - 6
ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/controller/pc/IndustryProductController.java

@@ -76,22 +76,23 @@ public class IndustryProductController {
     * */
     @GetMapping("getCarouselDisplayProductList")
     public R<List<PcProductVo>> getCarouselDisplayProductList() {
-        return R.ok(productBaseService.getCarouselDisplayProductList());
+        Long recommendId = 2001108545239650371L;
+        return R.ok(productBaseService.getCarouselDisplayProductList(recommendId));
     }
 
-    /*
+    /**
     * 获取工业名牌楼层(工业装修-品牌楼层)
     * */
     @GetMapping("getIndustrialFloor")
     public R<List<ProductIndustrialFloorVo>> getIndustrialFloor() {
         return R.ok(productIndustrialFloorService.queryList(new ProductIndustrialFloorBo()));
     }
-    /*
+    /**
     * 获取工业名牌楼层商品(工业装修-品牌楼层商品)
     * */
-    @GetMapping("getIndustrialFloorProduct")
-    public R<List<PcProductVo>> getIndustrialFloorProduct(Long floorId) {
-        return R.ok(productBaseService.getIndustrialFloorProduct(floorId));
+    @GetMapping("getIndustrialFloorProductList")
+    public R<List<PcProductVo>> getIndustrialFloorProductList(Long floorId) {
+        return R.ok(productBaseService.getIndustrialFloorProductList(floorId));
     }
 
     /**
@@ -113,6 +114,10 @@ public class IndustryProductController {
     /**
     * 获取推荐的分类商品(工业装修-分类推荐商品列表)
     * */
+    @GetMapping("getRecommendedCategoryProductList")
+    public R<List<PcProductVo>> getRecommendedCategoryProductList(Long categoryId) {
+        return R.ok(productBaseService.getRecommendedCategoryProductList(categoryId));
+    }
 
 
 

+ 22 - 8
ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/controller/pc/MyProductController.java

@@ -10,10 +10,7 @@ import org.dromara.common.satoken.utils.LoginHelper;
 import org.dromara.product.domain.ProductCollect;
 import org.dromara.product.domain.ProductFavorites;
 import org.dromara.product.domain.ProductShoppingCart;
-import org.dromara.product.domain.bo.ProductBrowsingHistoryBo;
-import org.dromara.product.domain.bo.ProductCollectBo;
-import org.dromara.product.domain.bo.ProductFavoritesBo;
-import org.dromara.product.domain.bo.ProductShoppingCartBo;
+import org.dromara.product.domain.bo.*;
 import org.dromara.product.domain.vo.PcProductVo;
 import org.dromara.product.domain.vo.ProductFavoritesVo;
 import org.dromara.product.service.*;
@@ -56,6 +53,15 @@ public class MyProductController {
         return R.ok();
     }
 
+    /**
+    * 删除浏览记录
+    * */
+    @DeleteMapping("/deleteProductBrowsingHistory/{ids}")
+    public R deleteProductBrowsingHistory(@PathVariable Long[] ids) {
+        productBrowsingHistoryService.deleteWithValidByIds(Arrays.asList(ids), false);
+        return R.ok();
+    }
+
     /**
     * 浏览记录的商品
     * */
@@ -134,11 +140,11 @@ public class MyProductController {
     }
 
     /**
-    * 收藏夹商品
+    * 收藏夹商品列表
     * */
-    @GetMapping("/getProductFavoritesPage/{favoritesId}")
-    public TableDataInfo<PcProductVo> getProductFavoritesPage(@PathVariable Long favoritesId,PageQuery pageQuery) {
-        return productBaseService.getProductFavoritesPage(favoritesId, LoginHelper.getUserId(),pageQuery);
+    @GetMapping("/getFavoritesProductPage")
+    public TableDataInfo<PcProductVo> getFavoritesProductPage(Long favoritesId,PageQuery pageQuery) {
+        return productBaseService.getFavoritesProductPage(favoritesId, LoginHelper.getUserId(),pageQuery);
     }
 
     /**
@@ -192,6 +198,14 @@ public class MyProductController {
     public TableDataInfo<PcProductVo> getProductShoppingCartPage(String id, PageQuery pageQuery) {
         return productBaseService.getProductShoppingCartPage(id,LoginHelper.getUserId(),pageQuery);
     }
+    /**
+    * 协议供货商品列表
+    * */
+    @GetMapping("/getAgreementSupplyProductPage")
+    public TableDataInfo<PcProductVo> getProtocolProductsPage(PcProductBo bo, PageQuery pageQuery) {
+        bo.setCustomerId(LoginHelper.getLoginUser().getCustomerId());
+        return productBaseService.getProtocolProductsPage(bo,pageQuery);
+    }
 
 
 

+ 69 - 0
ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/domain/ProcurementGroup.java

@@ -0,0 +1,69 @@
+package org.dromara.product.domain;
+
+import org.dromara.common.tenant.core.TenantEntity;
+import com.baomidou.mybatisplus.annotation.*;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import org.dromara.common.translation.annotation.Translation;
+import org.dromara.common.translation.constant.TransConstant;
+
+import java.io.Serial;
+
+/**
+ * 采购组信息对象 procurement_group
+ *
+ * @author LionLi
+ * @date 2026-02-06
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+@TableName("procurement_group")
+public class ProcurementGroup extends TenantEntity {
+
+    @Serial
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 主键ID,自增
+     */
+    @TableId(value = "id")
+    private Long id;
+
+    /**
+     * 项目id
+     */
+    private Long programId;
+
+    /**
+     * 封面图片路径或URL
+     */
+    private String coverImage;
+
+    /**
+     * 标题
+     */
+    private String title;
+
+    /**
+     * 副标题
+     */
+    private String subtitle;
+
+    /**
+     * 状态(0正常 1停用)
+     */
+    private String status;
+
+    /**
+     * 删除标志(0代表存在 2代表删除)
+     */
+    @TableLogic
+    private String delFlag;
+
+    /**
+     * 备注
+     */
+    private String remark;
+
+
+}

+ 136 - 0
ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/domain/ProcurementProgram.java

@@ -0,0 +1,136 @@
+package org.dromara.product.domain;
+
+import org.dromara.common.tenant.core.TenantEntity;
+import com.baomidou.mybatisplus.annotation.*;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import org.dromara.common.translation.annotation.Translation;
+import java.util.Date;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import org.dromara.common.translation.constant.TransConstant;
+
+import java.io.Serial;
+
+/**
+ * 采购项目对象 procurement_program
+ *
+ * @author LionLi
+ * @date 2026-02-06
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+@TableName("procurement_program")
+public class ProcurementProgram extends TenantEntity {
+
+    @Serial
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 主键ID,自增
+     */
+    @TableId(value = "id")
+    private Long id;
+
+    /**
+     * 项目编号
+     */
+    private String programNo;
+
+    /**
+     * 推文标题
+     */
+    private String tweetsTitle;
+
+    /**
+     * 副标题
+     */
+    private String subtitle;
+
+    /**
+     * 描述
+     */
+    private String programDescribe;
+
+    /**
+     * 推文分类
+     */
+    private String tweetsCategory;
+
+    /**
+     * 是否显示(例如:1-显示,0-不显示)
+     */
+    private Long isShow;
+
+    /**
+     * 封面图片路径或URL
+     */
+    private String coverImage;
+
+    /**
+     * 图片列表
+     */
+    private String imageList;
+
+    /**
+     * 点击次数
+     */
+    private Long clicks;
+
+    /**
+     * 收藏次数
+     */
+    private Long collects;
+
+    /**
+     * 价格
+     */
+    private String price;
+
+    /**
+     * 适配编号
+     */
+    private String adaptNo;
+
+    /**
+     * 标签
+     */
+    private String lable;
+
+    /**
+     * 上传方案
+     */
+    private String uploadScheme;
+
+    /**
+     * 适配行业
+     */
+    private String adaptIndustry;
+
+    /**
+     * 无效时间
+     */
+    private Date invalidTime;
+
+    /**
+     * 文件名
+     */
+    private String filename;
+
+    /**
+     * 状态(0正常 1停用)
+     */
+    private String status;
+
+    /**
+     * 删除标志(0代表存在 2代表删除)
+     */
+    @TableLogic
+    private String delFlag;
+
+    /**
+     * 备注
+     */
+    private String remark;
+
+
+}

+ 62 - 0
ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/domain/ProcurementProgramProduct.java

@@ -0,0 +1,62 @@
+package org.dromara.product.domain;
+
+import org.dromara.common.tenant.core.TenantEntity;
+import com.baomidou.mybatisplus.annotation.*;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import java.io.Serial;
+
+/**
+ * 采购项目产品关联对象 procurement_program_product
+ *
+ * @author LionLi
+ * @date 2026-02-06
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+@TableName("procurement_program_product")
+public class ProcurementProgramProduct extends TenantEntity {
+
+    @Serial
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 主键ID,自增
+     */
+    @TableId(value = "id")
+    private Long id;
+
+    /**
+     * 组号
+     */
+    private Long groupId;
+
+    /**
+     * 产品编号
+     */
+    private Long productId;
+
+    /**
+     * 是否为主产品(例如:1-是,0-否)
+     */
+    private Long isMain;
+
+    /**
+     * 状态(0正常 1停用)
+     */
+    private String status;
+
+    /**
+     * 删除标志(0代表存在 2代表删除)
+     */
+    @TableLogic
+    private String delFlag;
+
+    /**
+     * 备注
+     */
+    private String remark;
+
+
+}

+ 156 - 0
ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/domain/ProcurementTopics.java

@@ -0,0 +1,156 @@
+package org.dromara.product.domain;
+
+import org.dromara.common.tenant.core.TenantEntity;
+import com.baomidou.mybatisplus.annotation.*;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import org.dromara.common.translation.annotation.Translation;
+import java.util.Date;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import org.dromara.common.translation.constant.TransConstant;
+
+import java.io.Serial;
+
+/**
+ * 采购主题对象 procurement_topics
+ *
+ * @author LionLi
+ * @date 2026-02-06
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+@TableName("procurement_topics")
+public class ProcurementTopics extends TenantEntity {
+
+    @Serial
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 主键ID,自增
+     */
+    @TableId(value = "id")
+    private Long id;
+
+    /**
+     * 采购主题编号
+     */
+    private Long procurementTopicsId;
+
+    /**
+     * 标题
+     */
+    private String title;
+
+    /**
+     * 推文类型
+     */
+    private String tweetType;
+
+    /**
+     * 推文类别
+     */
+    private String tweetCategory;
+
+    /**
+     * 是否显示(例如:1-显示,0-不显示)
+     */
+    private Long isShow;
+
+    /**
+     * 发布时间
+     */
+    private Date releaseTime;
+
+    /**
+     * 专属客户
+     */
+    private String exclusiveClient;
+
+    /**
+     * 内容
+     */
+    private String content;
+
+    /**
+     * 封面图片路径或URL
+     */
+    private String coverImage;
+
+    /**
+     * 副标题
+     */
+    private String subtitle;
+
+    /**
+     * 点赞数
+     */
+    private Long praise;
+
+    /**
+     * 发布状态(例如:0-草稿,1-已发布)
+     */
+    private Long releaseStatus;
+
+    /**
+     * 适配编号
+     */
+    private String adaptNo;
+
+    /**
+     * 价格
+     */
+    private String price;
+
+    /**
+     * 标签
+     */
+    private String lable;
+
+    /**
+     * 产品数量
+     */
+    private Long productCount;
+
+    /**
+     * 是否首页展示(例如:1-是,0-否)
+     */
+    private Long isHome;
+
+    /**
+     * 上传方案
+     */
+    private String uploadScheme;
+
+    /**
+     * 是否相关(例如:1-是,0-否)
+     */
+    private Long isRelevant;
+
+    /**
+     * 适配行业
+     */
+    private String adaptIndustry;
+
+    /**
+     * 描述
+     */
+    private String topicsDescribe;
+
+    /**
+     * 状态(0正常 1停用)
+     */
+    private String status;
+
+    /**
+     * 删除标志(0代表存在 2代表删除)
+     */
+    @TableLogic
+    private String delFlag;
+
+    /**
+     * 备注
+     */
+    private String remark;
+
+
+}

+ 7 - 0
ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/domain/ProductGiftCategoryLink.java

@@ -34,6 +34,11 @@ public class ProductGiftCategoryLink extends TenantEntity {
      */
     private String categoryNo;
 
+    /**
+    * 分类id
+    * */
+    private Long categoryId;
+
     /**
      * 分类名称
      */
@@ -54,6 +59,8 @@ public class ProductGiftCategoryLink extends TenantEntity {
      */
     private String productNo;
 
+
+
     /**
      * 商品ID
      */

+ 57 - 0
ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/domain/ProductSpecialLink.java

@@ -0,0 +1,57 @@
+package org.dromara.product.domain;
+
+import org.dromara.common.tenant.core.TenantEntity;
+import com.baomidou.mybatisplus.annotation.*;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import java.io.Serial;
+
+/**
+ * 特价商品对象 product_special_link
+ *
+ * @author LionLi
+ * @date 2026-02-10
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+@TableName("product_special_link")
+public class ProductSpecialLink extends TenantEntity {
+
+    @Serial
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 
+     */
+    @TableId(value = "id")
+    private Long id;
+
+    /**
+     * 商品id
+     */
+    private Long productId;
+
+    /**
+     * 特殊价格
+     */
+    private Long specialPrice;
+
+    /**
+     * 状态(0正常 1停用)
+     */
+    private String status;
+
+    /**
+     * 删除标志(0代表存在 2代表删除)
+     */
+    @TableLogic
+    private String delFlag;
+
+    /**
+     * 备注
+     */
+    private String remark;
+
+
+}

+ 12 - 0
ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/domain/bo/PcProductBo.java

@@ -15,6 +15,10 @@ public class PcProductBo {
      * */
     private String searchKeyword;
     /**
+    * 客户id
+    * */
+    private Long customerId;
+    /**
     * 品牌id
     * */
     private Long brandId;
@@ -35,6 +39,14 @@ public class PcProductBo {
     * */
     private String priceRange;
     /**
+    * 最低价格
+    * */
+    private String minPrice;
+    /**
+    * 最高价格
+    * */
+    private String maxPrice;
+    /**
     * 是否可定制 0:不可定制 1:可定制
     * */
     private String isCustomize;

+ 67 - 0
ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/domain/bo/ProcurementGroupBo.java

@@ -0,0 +1,67 @@
+package org.dromara.product.domain.bo;
+
+import org.dromara.product.domain.ProcurementGroup;
+import org.dromara.common.mybatis.core.domain.BaseEntity;
+import org.dromara.common.core.validate.AddGroup;
+import org.dromara.common.core.validate.EditGroup;
+import io.github.linpeilie.annotations.AutoMapper;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import jakarta.validation.constraints.*;
+import org.dromara.common.translation.annotation.Translation;
+import org.dromara.common.translation.constant.TransConstant;
+
+/**
+ * 采购组信息业务对象 procurement_group
+ *
+ * @author LionLi
+ * @date 2026-02-06
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+@AutoMapper(target = ProcurementGroup.class, reverseConvertGenerate = false)
+public class ProcurementGroupBo extends BaseEntity {
+
+    /**
+     * 主键ID,自增
+     */
+    private Long id;
+
+    /**
+     * 项目id
+     */
+    //@NotNull(message = "项目id不能为空", groups = { AddGroup.class, EditGroup.class })
+    private Long programId;
+
+    /**
+     * 封面图片路径或URL
+     */
+    //@NotBlank(message = "封面图片路径或URL不能为空", groups = { AddGroup.class, EditGroup.class })
+    private String coverImage;
+
+    /**
+     * 标题
+     */
+    //@NotBlank(message = "标题不能为空", groups = { AddGroup.class, EditGroup.class })
+    private String title;
+
+    /**
+     * 副标题
+     */
+    //@NotBlank(message = "副标题不能为空", groups = { AddGroup.class, EditGroup.class })
+    private String subtitle;
+
+    /**
+     * 状态(0正常 1停用)
+     */
+    //@NotBlank(message = "状态(0正常 1停用)不能为空", groups = { AddGroup.class, EditGroup.class })
+    private String status;
+
+    /**
+     * 备注
+     */
+    //@NotBlank(message = "备注不能为空", groups = { AddGroup.class, EditGroup.class })
+    private String remark;
+
+
+}

+ 135 - 0
ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/domain/bo/ProcurementProgramBo.java

@@ -0,0 +1,135 @@
+package org.dromara.product.domain.bo;
+
+import org.dromara.product.domain.ProcurementProgram;
+import org.dromara.common.mybatis.core.domain.BaseEntity;
+import org.dromara.common.core.validate.AddGroup;
+import org.dromara.common.core.validate.EditGroup;
+import io.github.linpeilie.annotations.AutoMapper;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import jakarta.validation.constraints.*;
+import org.dromara.common.translation.annotation.Translation;
+import java.util.Date;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import org.dromara.common.translation.constant.TransConstant;
+
+/**
+ * 采购项目业务对象 procurement_program
+ *
+ * @author LionLi
+ * @date 2026-02-06
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+@AutoMapper(target = ProcurementProgram.class, reverseConvertGenerate = false)
+public class ProcurementProgramBo extends BaseEntity {
+
+    /**
+     * 主键ID,自增
+     */
+    private Long id;
+
+    /**
+     * 项目编号
+     */
+    private String programNo;
+
+    /**
+     * 推文标题
+     */
+    private String tweetsTitle;
+
+    /**
+     * 副标题
+     */
+    private String subtitle;
+
+    /**
+     * 描述
+     */
+    private String programDescribe;
+
+    /**
+     * 推文分类
+     */
+    private String tweetsCategory;
+
+    /**
+     * 是否显示(例如:1-显示,0-不显示)
+     */
+    private Long isShow;
+
+    /**
+     * 封面图片路径或URL
+     */
+    private String coverImage;
+
+    /**
+     * 图片列表
+     */
+    private String imageList;
+
+    /**
+     * 点击次数
+     */
+    private Long clicks;
+
+    /**
+     * 收藏次数
+     */
+    private Long collects;
+
+    /**
+     * 价格
+     */
+    //@NotBlank(message = "价格不能为空", groups = { AddGroup.class, EditGroup.class })
+    private String price;
+
+    /**
+     * 适配编号
+     */
+    private String adaptNo;
+
+    /**
+     * 标签
+     */
+    private String lable;
+
+    /**
+     * 上传方案
+     */
+    //@NotBlank(message = "上传方案不能为空", groups = { AddGroup.class, EditGroup.class })
+    private String uploadScheme;
+
+    /**
+     * 适配行业
+     */
+    //@NotBlank(message = "适配行业不能为空", groups = { AddGroup.class, EditGroup.class })
+    private String adaptIndustry;
+
+    /**
+     * 无效时间
+     */
+    //@NotNull(message = "无效时间不能为空", groups = { AddGroup.class, EditGroup.class })
+    private Date invalidTime;
+
+    /**
+     * 文件名
+     */
+    //@NotBlank(message = "文件名不能为空", groups = { AddGroup.class, EditGroup.class })
+    private String filename;
+
+    /**
+     * 状态(0正常 1停用)
+     */
+    //@NotBlank(message = "状态(0正常 1停用)不能为空", groups = { AddGroup.class, EditGroup.class })
+    private String status;
+
+    /**
+     * 备注
+     */
+    //@NotBlank(message = "备注不能为空", groups = { AddGroup.class, EditGroup.class })
+    private String remark;
+
+
+}

+ 57 - 0
ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/domain/bo/ProcurementProgramProductBo.java

@@ -0,0 +1,57 @@
+package org.dromara.product.domain.bo;
+
+import org.dromara.product.domain.ProcurementProgramProduct;
+import org.dromara.common.mybatis.core.domain.BaseEntity;
+import org.dromara.common.core.validate.AddGroup;
+import org.dromara.common.core.validate.EditGroup;
+import io.github.linpeilie.annotations.AutoMapper;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import jakarta.validation.constraints.*;
+
+/**
+ * 采购项目产品关联业务对象 procurement_program_product
+ *
+ * @author LionLi
+ * @date 2026-02-06
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+@AutoMapper(target = ProcurementProgramProduct.class, reverseConvertGenerate = false)
+public class ProcurementProgramProductBo extends BaseEntity {
+
+    /**
+     * 主键ID,自增
+     */
+    private Long id;
+
+    /**
+     * 组号
+     */
+    private Long groupId;
+
+    /**
+     * 产品编号
+     */
+    //@NotNull(message = "产品编号不能为空", groups = { AddGroup.class, EditGroup.class })
+    private Long productId;
+
+    /**
+     * 是否为主产品(例如:1-是,0-否)
+     */
+    private Long isMain;
+
+    /**
+     * 状态(0正常 1停用)
+     */
+    //@NotBlank(message = "状态(0正常 1停用)不能为空", groups = { AddGroup.class, EditGroup.class })
+    private String status;
+
+    /**
+     * 备注
+     */
+    //@NotBlank(message = "备注不能为空", groups = { AddGroup.class, EditGroup.class })
+    private String remark;
+
+
+}

+ 159 - 0
ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/domain/bo/ProcurementTopicsBo.java

@@ -0,0 +1,159 @@
+package org.dromara.product.domain.bo;
+
+import org.dromara.product.domain.ProcurementTopics;
+import org.dromara.common.mybatis.core.domain.BaseEntity;
+import org.dromara.common.core.validate.AddGroup;
+import org.dromara.common.core.validate.EditGroup;
+import io.github.linpeilie.annotations.AutoMapper;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import jakarta.validation.constraints.*;
+import org.dromara.common.translation.annotation.Translation;
+import java.util.Date;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import org.dromara.common.translation.constant.TransConstant;
+
+/**
+ * 采购主题业务对象 procurement_topics
+ *
+ * @author LionLi
+ * @date 2026-02-06
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+@AutoMapper(target = ProcurementTopics.class, reverseConvertGenerate = false)
+public class ProcurementTopicsBo extends BaseEntity {
+
+    /**
+     * 主键ID,自增
+     */
+    private Long id;
+
+    /**
+     * 采购主题编号
+     */
+    //@NotNull(message = "采购主题编号不能为空", groups = { AddGroup.class, EditGroup.class })
+    private Long procurementTopicsId;
+
+    /**
+     * 标题
+     */
+    //@NotBlank(message = "标题不能为空", groups = { AddGroup.class, EditGroup.class })
+    private String title;
+
+    /**
+     * 推文类型
+     */
+    //@NotBlank(message = "推文类型不能为空", groups = { AddGroup.class, EditGroup.class })
+    private String tweetType;
+
+    /**
+     * 推文类别
+     */
+    //@NotBlank(message = "推文类别不能为空", groups = { AddGroup.class, EditGroup.class })
+    private String tweetCategory;
+
+    /**
+     * 是否显示(例如:1-显示,0-不显示)
+     */
+    private Long isShow;
+
+    /**
+     * 发布时间
+     */
+    private Date releaseTime;
+
+    /**
+     * 专属客户
+     */
+    //@NotBlank(message = "专属客户不能为空", groups = { AddGroup.class, EditGroup.class })
+    private String exclusiveClient;
+
+    /**
+     * 内容
+     */
+    private String content;
+
+    /**
+     * 封面图片路径或URL
+     */
+    private String coverImage;
+
+    /**
+     * 副标题
+     */
+    private String subtitle;
+
+    /**
+     * 点赞数
+     */
+    private Long praise;
+
+    /**
+     * 发布状态(例如:0-草稿,1-已发布)
+     */
+    private Long releaseStatus;
+
+    /**
+     * 适配编号
+     */
+    private String adaptNo;
+
+    /**
+     * 价格
+     */
+    //@NotBlank(message = "价格不能为空", groups = { AddGroup.class, EditGroup.class })
+    private String price;
+
+    /**
+     * 标签
+     */
+    private String lable;
+
+    /**
+     * 产品数量
+     */
+    private Long productCount;
+
+    /**
+     * 是否首页展示(例如:1-是,0-否)
+     */
+    private Long isHome;
+
+    /**
+     * 上传方案
+     */
+    //@NotBlank(message = "上传方案不能为空", groups = { AddGroup.class, EditGroup.class })
+    private String uploadScheme;
+
+    /**
+     * 是否相关(例如:1-是,0-否)
+     */
+    private Long isRelevant;
+
+    /**
+     * 适配行业
+     */
+    //@NotBlank(message = "适配行业不能为空", groups = { AddGroup.class, EditGroup.class })
+    private String adaptIndustry;
+
+    /**
+     * 描述
+     */
+    //@NotBlank(message = "描述不能为空", groups = { AddGroup.class, EditGroup.class })
+    private String topicsDescribe;
+
+    /**
+     * 状态(0正常 1停用)
+     */
+    //@NotBlank(message = "状态(0正常 1停用)不能为空", groups = { AddGroup.class, EditGroup.class })
+    private String status;
+
+    /**
+     * 备注
+     */
+    //@NotBlank(message = "备注不能为空", groups = { AddGroup.class, EditGroup.class })
+    private String remark;
+
+
+}

+ 53 - 0
ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/domain/bo/ProductSpecialLinkBo.java

@@ -0,0 +1,53 @@
+package org.dromara.product.domain.bo;
+
+import org.dromara.product.domain.ProductSpecialLink;
+import org.dromara.common.mybatis.core.domain.BaseEntity;
+import org.dromara.common.core.validate.AddGroup;
+import org.dromara.common.core.validate.EditGroup;
+import io.github.linpeilie.annotations.AutoMapper;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import jakarta.validation.constraints.*;
+
+/**
+ * 特价商品业务对象 product_special_link
+ *
+ * @author LionLi
+ * @date 2026-02-10
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+@AutoMapper(target = ProductSpecialLink.class, reverseConvertGenerate = false)
+public class ProductSpecialLinkBo extends BaseEntity {
+
+    /**
+     * 
+     */
+    private Long id;
+
+    /**
+     * 商品id
+     */
+    //@NotNull(message = "商品id不能为空", groups = { AddGroup.class, EditGroup.class })
+    private Long productId;
+
+    /**
+     * 特殊价格
+     */
+    //@NotNull(message = "特殊价格不能为空", groups = { AddGroup.class, EditGroup.class })
+    private Long specialPrice;
+
+    /**
+     * 状态(0正常 1停用)
+     */
+    //@NotBlank(message = "状态(0正常 1停用)不能为空", groups = { AddGroup.class, EditGroup.class })
+    private String status;
+
+    /**
+     * 备注
+     */
+    //@NotBlank(message = "备注不能为空", groups = { AddGroup.class, EditGroup.class })
+    private String remark;
+
+
+}

+ 5 - 0
ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/domain/vo/PcProductVo.java

@@ -50,6 +50,11 @@ public class PcProductVo {
      */
     private BigDecimal minSellingPrice;
 
+    /**
+     * 协议价格
+     * */
+    private BigDecimal agreementPrice;
+
     /**
      * 最低起订量
      */

+ 82 - 0
ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/domain/vo/ProcurementGroupVo.java

@@ -0,0 +1,82 @@
+package org.dromara.product.domain.vo;
+
+import org.dromara.common.translation.annotation.Translation;
+import org.dromara.common.translation.constant.TransConstant;
+import org.dromara.product.domain.ProcurementGroup;
+import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
+import cn.idev.excel.annotation.ExcelProperty;
+import org.dromara.common.excel.annotation.ExcelDictFormat;
+import org.dromara.common.excel.convert.ExcelDictConvert;
+import io.github.linpeilie.annotations.AutoMapper;
+import lombok.Data;
+
+import java.io.Serial;
+import java.io.Serializable;
+import java.util.Date;
+
+
+
+/**
+ * 采购组信息视图对象 procurement_group
+ *
+ * @author LionLi
+ * @date 2026-02-06
+ */
+@Data
+@ExcelIgnoreUnannotated
+@AutoMapper(target = ProcurementGroup.class)
+public class ProcurementGroupVo implements Serializable {
+
+    @Serial
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 主键ID,自增
+     */
+    @ExcelProperty(value = "主键ID,自增")
+    private Long id;
+
+    /**
+     * 项目id
+     */
+    @ExcelProperty(value = "项目id")
+    private Long programId;
+
+    /**
+     * 封面图片路径或URL
+     */
+    @ExcelProperty(value = "封面图片路径或URL")
+    private String coverImage;
+
+    /**
+     * 封面图片路径或URLUrl
+     */
+    @Translation(type = TransConstant.OSS_ID_TO_URL, mapper = "coverImage")
+    private String coverImageUrl;
+    /**
+     * 标题
+     */
+    @ExcelProperty(value = "标题")
+    private String title;
+
+    /**
+     * 副标题
+     */
+    @ExcelProperty(value = "副标题")
+    private String subtitle;
+
+    /**
+     * 状态(0正常 1停用)
+     */
+    @ExcelProperty(value = "状态", converter = ExcelDictConvert.class)
+    @ExcelDictFormat(readConverterExp = "0=正常,1=停用")
+    private String status;
+
+    /**
+     * 备注
+     */
+    @ExcelProperty(value = "备注")
+    private String remark;
+
+
+}

+ 70 - 0
ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/domain/vo/ProcurementProgramProductVo.java

@@ -0,0 +1,70 @@
+package org.dromara.product.domain.vo;
+
+import org.dromara.product.domain.ProcurementProgramProduct;
+import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
+import cn.idev.excel.annotation.ExcelProperty;
+import org.dromara.common.excel.annotation.ExcelDictFormat;
+import org.dromara.common.excel.convert.ExcelDictConvert;
+import io.github.linpeilie.annotations.AutoMapper;
+import lombok.Data;
+
+import java.io.Serial;
+import java.io.Serializable;
+import java.util.Date;
+
+
+
+/**
+ * 采购项目产品关联视图对象 procurement_program_product
+ *
+ * @author LionLi
+ * @date 2026-02-06
+ */
+@Data
+@ExcelIgnoreUnannotated
+@AutoMapper(target = ProcurementProgramProduct.class)
+public class ProcurementProgramProductVo implements Serializable {
+
+    @Serial
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 主键ID,自增
+     */
+    @ExcelProperty(value = "主键ID,自增")
+    private Long id;
+
+    /**
+     * 组号
+     */
+    @ExcelProperty(value = "组号")
+    private Long groupId;
+
+    /**
+     * 产品编号
+     */
+    @ExcelProperty(value = "产品编号")
+    private Long productId;
+
+    /**
+     * 是否为主产品(例如:1-是,0-否)
+     */
+    @ExcelProperty(value = "是否为主产品", converter = ExcelDictConvert.class)
+    @ExcelDictFormat(readConverterExp = "例=如:1-是,0-否")
+    private Long isMain;
+
+    /**
+     * 状态(0正常 1停用)
+     */
+    @ExcelProperty(value = "状态", converter = ExcelDictConvert.class)
+    @ExcelDictFormat(readConverterExp = "0=正常,1=停用")
+    private String status;
+
+    /**
+     * 备注
+     */
+    @ExcelProperty(value = "备注")
+    private String remark;
+
+
+}

+ 165 - 0
ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/domain/vo/ProcurementProgramVo.java

@@ -0,0 +1,165 @@
+package org.dromara.product.domain.vo;
+
+import org.dromara.common.translation.annotation.Translation;
+import java.util.Date;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import org.dromara.common.translation.constant.TransConstant;
+import org.dromara.product.domain.ProcurementProgram;
+import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
+import cn.idev.excel.annotation.ExcelProperty;
+import org.dromara.common.excel.annotation.ExcelDictFormat;
+import org.dromara.common.excel.convert.ExcelDictConvert;
+import io.github.linpeilie.annotations.AutoMapper;
+import lombok.Data;
+
+import java.io.Serial;
+import java.io.Serializable;
+import java.util.Date;
+
+
+
+/**
+ * 采购项目视图对象 procurement_program
+ *
+ * @author LionLi
+ * @date 2026-02-06
+ */
+@Data
+@ExcelIgnoreUnannotated
+@AutoMapper(target = ProcurementProgram.class)
+public class ProcurementProgramVo implements Serializable {
+
+    @Serial
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 主键ID,自增
+     */
+    @ExcelProperty(value = "主键ID,自增")
+    private Long id;
+
+    /**
+     * 项目编号
+     */
+    @ExcelProperty(value = "项目编号")
+    private String programNo;
+
+    /**
+     * 推文标题
+     */
+    @ExcelProperty(value = "推文标题")
+    private String tweetsTitle;
+
+    /**
+     * 副标题
+     */
+    @ExcelProperty(value = "副标题")
+    private String subtitle;
+
+    /**
+     * 描述
+     */
+    @ExcelProperty(value = "描述")
+    private String programDescribe;
+
+    /**
+     * 推文分类
+     */
+    @ExcelProperty(value = "推文分类")
+    private String tweetsCategory;
+
+    /**
+     * 是否显示(例如:1-显示,0-不显示)
+     */
+    @ExcelProperty(value = "是否显示", converter = ExcelDictConvert.class)
+    @ExcelDictFormat(readConverterExp = "例=如:1-显示,0-不显示")
+    private Long isShow;
+
+    /**
+     * 封面图片路径或URL
+     */
+    @ExcelProperty(value = "封面图片路径或URL")
+    private String coverImage;
+
+    /**
+     * 封面图片路径或URLUrl
+     */
+    @Translation(type = TransConstant.OSS_ID_TO_URL, mapper = "coverImage")
+    private String coverImageUrl;
+    /**
+     * 图片列表
+     */
+    @ExcelProperty(value = "图片列表")
+    private String imageList;
+
+    /**
+     * 点击次数
+     */
+    @ExcelProperty(value = "点击次数")
+    private Long clicks;
+
+    /**
+     * 收藏次数
+     */
+    @ExcelProperty(value = "收藏次数")
+    private Long collects;
+
+    /**
+     * 价格
+     */
+    @ExcelProperty(value = "价格")
+    private String price;
+
+    /**
+     * 适配编号
+     */
+    @ExcelProperty(value = "适配编号")
+    private String adaptNo;
+
+    /**
+     * 标签
+     */
+    @ExcelProperty(value = "标签")
+    private String lable;
+
+    /**
+     * 上传方案
+     */
+    @ExcelProperty(value = "上传方案")
+    private String uploadScheme;
+
+    /**
+     * 适配行业
+     */
+    @ExcelProperty(value = "适配行业")
+    private String adaptIndustry;
+
+    /**
+     * 无效时间
+     */
+    @ExcelProperty(value = "无效时间")
+    private Date invalidTime;
+
+    /**
+     * 文件名
+     */
+    @ExcelProperty(value = "文件名")
+    private String filename;
+
+    /**
+     * 状态(0正常 1停用)
+     */
+    @ExcelProperty(value = "状态", converter = ExcelDictConvert.class)
+    @ExcelDictFormat(readConverterExp = "0=正常,1=停用")
+    private String status;
+
+    /**
+     * 备注
+     */
+    @ExcelProperty(value = "备注")
+    private String remark;
+
+    private Date createTime;
+
+
+}

+ 190 - 0
ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/domain/vo/ProcurementTopicsVo.java

@@ -0,0 +1,190 @@
+package org.dromara.product.domain.vo;
+
+import org.dromara.common.translation.annotation.Translation;
+import java.util.Date;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import org.dromara.common.translation.constant.TransConstant;
+import org.dromara.product.domain.ProcurementTopics;
+import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
+import cn.idev.excel.annotation.ExcelProperty;
+import org.dromara.common.excel.annotation.ExcelDictFormat;
+import org.dromara.common.excel.convert.ExcelDictConvert;
+import io.github.linpeilie.annotations.AutoMapper;
+import lombok.Data;
+
+import java.io.Serial;
+import java.io.Serializable;
+import java.util.Date;
+
+
+
+/**
+ * 采购主题视图对象 procurement_topics
+ *
+ * @author LionLi
+ * @date 2026-02-06
+ */
+@Data
+@ExcelIgnoreUnannotated
+@AutoMapper(target = ProcurementTopics.class)
+public class ProcurementTopicsVo implements Serializable {
+
+    @Serial
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 主键ID,自增
+     */
+    @ExcelProperty(value = "主键ID,自增")
+    private Long id;
+
+    /**
+     * 采购主题编号
+     */
+    @ExcelProperty(value = "采购主题编号")
+    private Long procurementTopicsId;
+
+    /**
+     * 标题
+     */
+    @ExcelProperty(value = "标题")
+    private String title;
+
+    /**
+     * 推文类型
+     */
+    @ExcelProperty(value = "推文类型")
+    private String tweetType;
+
+    /**
+     * 推文类别
+     */
+    @ExcelProperty(value = "推文类别")
+    private String tweetCategory;
+
+    /**
+     * 是否显示(例如:1-显示,0-不显示)
+     */
+    @ExcelProperty(value = "是否显示", converter = ExcelDictConvert.class)
+    @ExcelDictFormat(readConverterExp = "例=如:1-显示,0-不显示")
+    private Long isShow;
+
+    /**
+     * 发布时间
+     */
+    @ExcelProperty(value = "发布时间")
+    private Date releaseTime;
+
+    /**
+     * 专属客户
+     */
+    @ExcelProperty(value = "专属客户")
+    private String exclusiveClient;
+
+    /**
+     * 内容
+     */
+    @ExcelProperty(value = "内容")
+    private String content;
+
+    /**
+     * 封面图片路径或URL
+     */
+    @ExcelProperty(value = "封面图片路径或URL")
+    private String coverImage;
+
+    /**
+     * 封面图片路径或URLUrl
+     */
+    @Translation(type = TransConstant.OSS_ID_TO_URL, mapper = "coverImage")
+    private String coverImageUrl;
+    /**
+     * 副标题
+     */
+    @ExcelProperty(value = "副标题")
+    private String subtitle;
+
+    /**
+     * 点赞数
+     */
+    @ExcelProperty(value = "点赞数")
+    private Long praise;
+
+    /**
+     * 发布状态(例如:0-草稿,1-已发布)
+     */
+    @ExcelProperty(value = "发布状态", converter = ExcelDictConvert.class)
+    @ExcelDictFormat(readConverterExp = "例=如:0-草稿,1-已发布")
+    private Long releaseStatus;
+
+    /**
+     * 适配编号
+     */
+    @ExcelProperty(value = "适配编号")
+    private String adaptNo;
+
+    /**
+     * 价格
+     */
+    @ExcelProperty(value = "价格")
+    private String price;
+
+    /**
+     * 标签
+     */
+    @ExcelProperty(value = "标签")
+    private String lable;
+
+    /**
+     * 产品数量
+     */
+    @ExcelProperty(value = "产品数量")
+    private Long productCount;
+
+    /**
+     * 是否首页展示(例如:1-是,0-否)
+     */
+    @ExcelProperty(value = "是否首页展示", converter = ExcelDictConvert.class)
+    @ExcelDictFormat(readConverterExp = "例=如:1-是,0-否")
+    private Long isHome;
+
+    /**
+     * 上传方案
+     */
+    @ExcelProperty(value = "上传方案")
+    private String uploadScheme;
+
+    /**
+     * 是否相关(例如:1-是,0-否)
+     */
+    @ExcelProperty(value = "是否相关", converter = ExcelDictConvert.class)
+    @ExcelDictFormat(readConverterExp = "例=如:1-是,0-否")
+    private Long isRelevant;
+
+    /**
+     * 适配行业
+     */
+    @ExcelProperty(value = "适配行业")
+    private String adaptIndustry;
+
+    /**
+     * 描述
+     */
+    @ExcelProperty(value = "描述")
+    private String topicsDescribe;
+
+    /**
+     * 状态(0正常 1停用)
+     */
+    @ExcelProperty(value = "状态", converter = ExcelDictConvert.class)
+    @ExcelDictFormat(readConverterExp = "0=正常,1=停用")
+    private String status;
+
+    /**
+     * 备注
+     */
+    @ExcelProperty(value = "备注")
+    private String remark;
+
+
+}

+ 5 - 0
ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/domain/vo/ProductBaseVo.java

@@ -406,6 +406,11 @@ public class ProductBaseVo implements Serializable {
     @ExcelProperty(value = "最低起订量")
     private Long minOrderQuantity;
 
+    /**
+     * 是否可定制 0:不可定制 1:可定制
+     * */
+    private Long isCustomize;
+
     /**
      * 总库存
      * */

+ 63 - 0
ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/domain/vo/ProductSpecialLinkVo.java

@@ -0,0 +1,63 @@
+package org.dromara.product.domain.vo;
+
+import org.dromara.product.domain.ProductSpecialLink;
+import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
+import cn.idev.excel.annotation.ExcelProperty;
+import org.dromara.common.excel.annotation.ExcelDictFormat;
+import org.dromara.common.excel.convert.ExcelDictConvert;
+import io.github.linpeilie.annotations.AutoMapper;
+import lombok.Data;
+
+import java.io.Serial;
+import java.io.Serializable;
+import java.util.Date;
+
+
+
+/**
+ * 特价商品视图对象 product_special_link
+ *
+ * @author LionLi
+ * @date 2026-02-10
+ */
+@Data
+@ExcelIgnoreUnannotated
+@AutoMapper(target = ProductSpecialLink.class)
+public class ProductSpecialLinkVo implements Serializable {
+
+    @Serial
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 
+     */
+    @ExcelProperty(value = "")
+    private Long id;
+
+    /**
+     * 商品id
+     */
+    @ExcelProperty(value = "商品id")
+    private Long productId;
+
+    /**
+     * 特殊价格
+     */
+    @ExcelProperty(value = "特殊价格")
+    private Long specialPrice;
+
+    /**
+     * 状态(0正常 1停用)
+     */
+    @ExcelProperty(value = "状态", converter = ExcelDictConvert.class)
+    @ExcelDictFormat(readConverterExp = "0=正常,1=停用")
+    private String status;
+
+    /**
+     * 备注
+     */
+    @ExcelProperty(value = "备注")
+    private String remark;
+
+
+}

+ 4 - 0
ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/domain/vo/ServiceCaseVo.java

@@ -95,6 +95,10 @@ public class ServiceCaseVo implements Serializable {
     @ExcelProperty(value = "平台标识")
     private String platformCode;
 
+
+    @ExcelProperty(value = "项目详情")
+    private String projectDetails;
+
     /**
      * 备注
      */

+ 15 - 0
ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/mapper/ProcurementGroupMapper.java

@@ -0,0 +1,15 @@
+package org.dromara.product.mapper;
+
+import org.dromara.product.domain.ProcurementGroup;
+import org.dromara.product.domain.vo.ProcurementGroupVo;
+import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
+
+/**
+ * 采购组信息Mapper接口
+ *
+ * @author LionLi
+ * @date 2026-02-06
+ */
+public interface ProcurementGroupMapper extends BaseMapperPlus<ProcurementGroup, ProcurementGroupVo> {
+
+}

+ 15 - 0
ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/mapper/ProcurementProgramMapper.java

@@ -0,0 +1,15 @@
+package org.dromara.product.mapper;
+
+import org.dromara.product.domain.ProcurementProgram;
+import org.dromara.product.domain.vo.ProcurementProgramVo;
+import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
+
+/**
+ * 采购项目Mapper接口
+ *
+ * @author LionLi
+ * @date 2026-02-06
+ */
+public interface ProcurementProgramMapper extends BaseMapperPlus<ProcurementProgram, ProcurementProgramVo> {
+
+}

+ 15 - 0
ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/mapper/ProcurementProgramProductMapper.java

@@ -0,0 +1,15 @@
+package org.dromara.product.mapper;
+
+import org.dromara.product.domain.ProcurementProgramProduct;
+import org.dromara.product.domain.vo.ProcurementProgramProductVo;
+import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
+
+/**
+ * 采购项目产品关联Mapper接口
+ *
+ * @author LionLi
+ * @date 2026-02-06
+ */
+public interface ProcurementProgramProductMapper extends BaseMapperPlus<ProcurementProgramProduct, ProcurementProgramProductVo> {
+
+}

+ 15 - 0
ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/mapper/ProcurementTopicsMapper.java

@@ -0,0 +1,15 @@
+package org.dromara.product.mapper;
+
+import org.dromara.product.domain.ProcurementTopics;
+import org.dromara.product.domain.vo.ProcurementTopicsVo;
+import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
+
+/**
+ * 采购主题Mapper接口
+ *
+ * @author LionLi
+ * @date 2026-02-06
+ */
+public interface ProcurementTopicsMapper extends BaseMapperPlus<ProcurementTopics, ProcurementTopicsVo> {
+
+}

+ 15 - 0
ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/mapper/ProductSpecialLinkMapper.java

@@ -0,0 +1,15 @@
+package org.dromara.product.mapper;
+
+import org.dromara.product.domain.ProductSpecialLink;
+import org.dromara.product.domain.vo.ProductSpecialLinkVo;
+import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
+
+/**
+ * 特价商品Mapper接口
+ *
+ * @author LionLi
+ * @date 2026-02-10
+ */
+public interface ProductSpecialLinkMapper extends BaseMapperPlus<ProductSpecialLink, ProductSpecialLinkVo> {
+
+}

+ 70 - 0
ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/service/IProcurementGroupService.java

@@ -0,0 +1,70 @@
+package org.dromara.product.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import org.dromara.product.domain.ProcurementGroup;
+import org.dromara.product.domain.vo.ProcurementGroupVo;
+import org.dromara.product.domain.bo.ProcurementGroupBo;
+import org.dromara.common.mybatis.core.page.TableDataInfo;
+import org.dromara.common.mybatis.core.page.PageQuery;
+
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * 采购组信息Service接口
+ *
+ * @author LionLi
+ * @date 2026-02-06
+ */
+public interface IProcurementGroupService extends IService<ProcurementGroup>{
+
+    /**
+     * 查询采购组信息
+     *
+     * @param id 主键
+     * @return 采购组信息
+     */
+    ProcurementGroupVo queryById(Long id);
+
+    /**
+     * 分页查询采购组信息列表
+     *
+     * @param bo        查询条件
+     * @param pageQuery 分页参数
+     * @return 采购组信息分页列表
+     */
+    TableDataInfo<ProcurementGroupVo> queryPageList(ProcurementGroupBo bo, PageQuery pageQuery);
+
+    /**
+     * 查询符合条件的采购组信息列表
+     *
+     * @param bo 查询条件
+     * @return 采购组信息列表
+     */
+    List<ProcurementGroupVo> queryList(ProcurementGroupBo bo);
+
+    /**
+     * 新增采购组信息
+     *
+     * @param bo 采购组信息
+     * @return 是否新增成功
+     */
+    Boolean insertByBo(ProcurementGroupBo bo);
+
+    /**
+     * 修改采购组信息
+     *
+     * @param bo 采购组信息
+     * @return 是否修改成功
+     */
+    Boolean updateByBo(ProcurementGroupBo bo);
+
+    /**
+     * 校验并批量删除采购组信息信息
+     *
+     * @param ids     待删除的主键集合
+     * @param isValid 是否进行有效性校验
+     * @return 是否删除成功
+     */
+    Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
+}

+ 80 - 0
ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/service/IProcurementProgramProductService.java

@@ -0,0 +1,80 @@
+package org.dromara.product.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import org.dromara.product.domain.ProcurementProgramProduct;
+import org.dromara.product.domain.vo.ProcurementProgramProductVo;
+import org.dromara.product.domain.bo.ProcurementProgramProductBo;
+import org.dromara.common.mybatis.core.page.TableDataInfo;
+import org.dromara.common.mybatis.core.page.PageQuery;
+import org.dromara.product.domain.vo.ProductBaseVo;
+
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * 采购项目产品关联Service接口
+ *
+ * @author LionLi
+ * @date 2026-02-06
+ */
+public interface IProcurementProgramProductService extends IService<ProcurementProgramProduct>{
+
+    /**
+     * 查询采购项目产品关联
+     *
+     * @param id 主键
+     * @return 采购项目产品关联
+     */
+    ProcurementProgramProductVo queryById(Long id);
+
+    /**
+     * 分页查询采购项目产品关联列表
+     *
+     * @param bo        查询条件
+     * @param pageQuery 分页参数
+     * @return 采购项目产品关联分页列表
+     */
+    TableDataInfo<ProcurementProgramProductVo> queryPageList(ProcurementProgramProductBo bo, PageQuery pageQuery);
+
+    /**
+     * 查询符合条件的采购项目产品关联列表
+     *
+     * @param bo 查询条件
+     * @return 采购项目产品关联列表
+     */
+    List<ProcurementProgramProductVo> queryList(ProcurementProgramProductBo bo);
+
+    /**
+     * 新增采购项目产品关联
+     *
+     * @param bo 采购项目产品关联
+     * @return 是否新增成功
+     */
+    Boolean insertByBo(ProcurementProgramProductBo bo);
+
+    /**
+     * 修改采购项目产品关联
+     *
+     * @param bo 采购项目产品关联
+     * @return 是否修改成功
+     */
+    Boolean updateByBo(ProcurementProgramProductBo bo);
+
+    /**
+     * 校验并批量删除采购项目产品关联信息
+     *
+     * @param ids     待删除的主键集合
+     * @param isValid 是否进行有效性校验
+     * @return 是否删除成功
+     */
+    Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
+
+    /**
+     * 获取分组下的产品列表
+     *
+     * @param groupId 分组id
+     * @param pageQuery 分页参数
+     * @return 产品列表
+     */
+    TableDataInfo<ProductBaseVo> groupProductPage(Long groupId, PageQuery pageQuery);
+}

+ 70 - 0
ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/service/IProcurementProgramService.java

@@ -0,0 +1,70 @@
+package org.dromara.product.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import org.dromara.product.domain.ProcurementProgram;
+import org.dromara.product.domain.vo.ProcurementProgramVo;
+import org.dromara.product.domain.bo.ProcurementProgramBo;
+import org.dromara.common.mybatis.core.page.TableDataInfo;
+import org.dromara.common.mybatis.core.page.PageQuery;
+
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * 采购项目Service接口
+ *
+ * @author LionLi
+ * @date 2026-02-06
+ */
+public interface IProcurementProgramService extends IService<ProcurementProgram>{
+
+    /**
+     * 查询采购项目
+     *
+     * @param id 主键
+     * @return 采购项目
+     */
+    ProcurementProgramVo queryById(Long id);
+
+    /**
+     * 分页查询采购项目列表
+     *
+     * @param bo        查询条件
+     * @param pageQuery 分页参数
+     * @return 采购项目分页列表
+     */
+    TableDataInfo<ProcurementProgramVo> queryPageList(ProcurementProgramBo bo, PageQuery pageQuery);
+
+    /**
+     * 查询符合条件的采购项目列表
+     *
+     * @param bo 查询条件
+     * @return 采购项目列表
+     */
+    List<ProcurementProgramVo> queryList(ProcurementProgramBo bo);
+
+    /**
+     * 新增采购项目
+     *
+     * @param bo 采购项目
+     * @return 是否新增成功
+     */
+    Boolean insertByBo(ProcurementProgramBo bo);
+
+    /**
+     * 修改采购项目
+     *
+     * @param bo 采购项目
+     * @return 是否修改成功
+     */
+    Boolean updateByBo(ProcurementProgramBo bo);
+
+    /**
+     * 校验并批量删除采购项目信息
+     *
+     * @param ids     待删除的主键集合
+     * @param isValid 是否进行有效性校验
+     * @return 是否删除成功
+     */
+    Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
+}

+ 70 - 0
ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/service/IProcurementTopicsService.java

@@ -0,0 +1,70 @@
+package org.dromara.product.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import org.dromara.product.domain.ProcurementTopics;
+import org.dromara.product.domain.vo.ProcurementTopicsVo;
+import org.dromara.product.domain.bo.ProcurementTopicsBo;
+import org.dromara.common.mybatis.core.page.TableDataInfo;
+import org.dromara.common.mybatis.core.page.PageQuery;
+
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * 采购主题Service接口
+ *
+ * @author LionLi
+ * @date 2026-02-06
+ */
+public interface IProcurementTopicsService extends IService<ProcurementTopics>{
+
+    /**
+     * 查询采购主题
+     *
+     * @param id 主键
+     * @return 采购主题
+     */
+    ProcurementTopicsVo queryById(Long id);
+
+    /**
+     * 分页查询采购主题列表
+     *
+     * @param bo        查询条件
+     * @param pageQuery 分页参数
+     * @return 采购主题分页列表
+     */
+    TableDataInfo<ProcurementTopicsVo> queryPageList(ProcurementTopicsBo bo, PageQuery pageQuery);
+
+    /**
+     * 查询符合条件的采购主题列表
+     *
+     * @param bo 查询条件
+     * @return 采购主题列表
+     */
+    List<ProcurementTopicsVo> queryList(ProcurementTopicsBo bo);
+
+    /**
+     * 新增采购主题
+     *
+     * @param bo 采购主题
+     * @return 是否新增成功
+     */
+    Boolean insertByBo(ProcurementTopicsBo bo);
+
+    /**
+     * 修改采购主题
+     *
+     * @param bo 采购主题
+     * @return 是否修改成功
+     */
+    Boolean updateByBo(ProcurementTopicsBo bo);
+
+    /**
+     * 校验并批量删除采购主题信息
+     *
+     * @param ids     待删除的主键集合
+     * @param isValid 是否进行有效性校验
+     * @return 是否删除成功
+     */
+    Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
+}

+ 46 - 7
ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/service/IProductBaseService.java

@@ -2,11 +2,8 @@ package org.dromara.product.service;
 
 import com.baomidou.mybatisplus.extension.service.IService;
 import org.dromara.product.domain.ProductBase;
-import org.dromara.product.domain.bo.PcProductBo;
-import org.dromara.product.domain.bo.ProductCategoryBo;
+import org.dromara.product.domain.bo.*;
 import org.dromara.product.domain.vo.*;
-import org.dromara.product.domain.bo.ProductBaseBo;
-import org.dromara.product.domain.bo.SiteProductBo;
 import org.dromara.common.mybatis.core.page.TableDataInfo;
 import org.dromara.common.mybatis.core.page.PageQuery;
 
@@ -21,6 +18,12 @@ import java.util.List;
  */
 public interface IProductBaseService extends IService<ProductBase>{
 
+
+    /**
+    * 获取es商品
+    * */
+    List<ProductBaseVo> getEsProductList();
+
     /**
      * 查询产品基础信息
      *
@@ -160,7 +163,7 @@ public interface IProductBaseService extends IService<ProductBase>{
     /**
     * PC端商品收藏夹
     * */
-    TableDataInfo<PcProductVo> getProductFavoritesPage(Long favoritesId, Long userId,PageQuery pageQuery);
+    TableDataInfo<PcProductVo> getFavoritesProductPage(Long favoritesId, Long userId,PageQuery pageQuery);
 
     /**
     * PC端分类推荐商品
@@ -175,10 +178,46 @@ public interface IProductBaseService extends IService<ProductBase>{
     /**
     * PC端轮播图商品列表
     * */
-    List<PcProductVo> getCarouselDisplayProductList();
+    List<PcProductVo> getCarouselDisplayProductList(Long recommendId);
+
+    /**
+     * PC端推荐分类推荐商品列表
+     * */
+    List<PcProductVo> getRecommendedCategoryProductList(Long categoryId);
 
     /**
     * PC端工业品牌楼层商品列表
     * */
-    List<PcProductVo> getIndustrialFloorProduct(Long floorId);
+    List<PcProductVo> getIndustrialFloorProductList(Long floorId);
+
+    /**
+    * PC端福利分类下的商品列表
+     * */
+    TableDataInfo<PcProductVo> getGiftCategoryLinkPage(PcProductBo bo, PageQuery pageQuery);
+
+    /**
+    * PC端福利楼层商品列表
+     * */
+    List<PcProductVo> getGiftFloorLinkProductList(Long floorId);
+
+
+    /**
+    * PC端采购方案组商品列表
+     * */
+    TableDataInfo<PcProductVo> getProcurementProgramGroupProductList(Long groupId,PageQuery pageQuery);
+
+    /**
+    * PC端场景采购下的商品
+     * */
+    List<PcProductVo> getProductProgramProductList(Long programId);
+
+    /**
+    * PC端协议商品列表
+     * */
+    TableDataInfo<PcProductVo> getProtocolProductsPage(PcProductBo bo, PageQuery pageQuery);
+
+    /**
+    * PC端特价商品列表
+     * */
+    TableDataInfo<PcProductVo> getSpecialProductList(PcProductBo bo, PageQuery pageQuery);
 }

+ 15 - 0
ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/service/IProductBrandService.java

@@ -91,4 +91,19 @@ public interface IProductBrandService extends IService<ProductBrand>{
      * @return
      */
     List<ProductBrandVo> getIndustrialFloorBrand(Long floorId);
+
+    /**
+     * 获取品牌列表
+     *
+     * @param categoryId
+     * @return
+     */
+    TableDataInfo<ProductBrandVo> getBrandByCategoryList(Long categoryId,String name,String initial,PageQuery pageQuery);
+
+    /**
+     * 获取特价品牌列表
+     *
+     * @return
+     */
+    List<ProductBrandVo> getSpecialBrandList();
 }

+ 9 - 0
ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/service/IProductCategoryService.java

@@ -4,6 +4,7 @@ import cn.hutool.core.lang.tree.Tree;
 import com.baomidou.mybatisplus.extension.service.IService;
 import org.dromara.product.domain.ProductCategory;
 import org.dromara.product.domain.vo.PcProductVo;
+import org.dromara.product.domain.vo.ProductBrandVo;
 import org.dromara.product.domain.vo.ProductCategoryVo;
 import org.dromara.product.domain.bo.ProductCategoryBo;
 import org.dromara.common.mybatis.core.page.TableDataInfo;
@@ -109,4 +110,12 @@ public interface IProductCategoryService extends IService<ProductCategory>{
      * @return 商品列表
      */
     List<ProductCategoryVo> getProductCategoryList(Long categoryId);
+
+    /**
+     * 获取特价分类列表
+     *
+     * @return 专题分类列表
+     */
+    List<ProductCategoryVo> getSpecialCategoryList();
+
 }

+ 70 - 0
ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/service/IProductSpecialLinkService.java

@@ -0,0 +1,70 @@
+package org.dromara.product.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import org.dromara.product.domain.ProductSpecialLink;
+import org.dromara.product.domain.vo.ProductSpecialLinkVo;
+import org.dromara.product.domain.bo.ProductSpecialLinkBo;
+import org.dromara.common.mybatis.core.page.TableDataInfo;
+import org.dromara.common.mybatis.core.page.PageQuery;
+
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * 特价商品Service接口
+ *
+ * @author LionLi
+ * @date 2026-02-10
+ */
+public interface IProductSpecialLinkService extends IService<ProductSpecialLink>{
+
+    /**
+     * 查询特价商品
+     *
+     * @param id 主键
+     * @return 特价商品
+     */
+    ProductSpecialLinkVo queryById(Long id);
+
+    /**
+     * 分页查询特价商品列表
+     *
+     * @param bo        查询条件
+     * @param pageQuery 分页参数
+     * @return 特价商品分页列表
+     */
+    TableDataInfo<ProductSpecialLinkVo> queryPageList(ProductSpecialLinkBo bo, PageQuery pageQuery);
+
+    /**
+     * 查询符合条件的特价商品列表
+     *
+     * @param bo 查询条件
+     * @return 特价商品列表
+     */
+    List<ProductSpecialLinkVo> queryList(ProductSpecialLinkBo bo);
+
+    /**
+     * 新增特价商品
+     *
+     * @param bo 特价商品
+     * @return 是否新增成功
+     */
+    Boolean insertByBo(ProductSpecialLinkBo bo);
+
+    /**
+     * 修改特价商品
+     *
+     * @param bo 特价商品
+     * @return 是否修改成功
+     */
+    Boolean updateByBo(ProductSpecialLinkBo bo);
+
+    /**
+     * 校验并批量删除特价商品信息
+     *
+     * @param ids     待删除的主键集合
+     * @param isValid 是否进行有效性校验
+     * @return 是否删除成功
+     */
+    Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
+}

+ 138 - 0
ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/service/impl/ProcurementGroupServiceImpl.java

@@ -0,0 +1,138 @@
+package org.dromara.product.service.impl;
+
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import org.dromara.common.core.utils.MapstructUtils;
+import org.dromara.common.core.utils.StringUtils;
+import org.dromara.common.mybatis.core.page.TableDataInfo;
+import org.dromara.common.mybatis.core.page.PageQuery;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Service;
+import org.dromara.product.domain.bo.ProcurementGroupBo;
+import org.dromara.product.domain.vo.ProcurementGroupVo;
+import org.dromara.product.domain.ProcurementGroup;
+import org.dromara.product.mapper.ProcurementGroupMapper;
+import org.dromara.product.service.IProcurementGroupService;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Collection;
+
+/**
+ * 采购组信息Service业务层处理
+ *
+ * @author LionLi
+ * @date 2026-02-06
+ */
+@Slf4j
+@RequiredArgsConstructor
+@Service
+public class ProcurementGroupServiceImpl  extends ServiceImpl<ProcurementGroupMapper, ProcurementGroup> implements IProcurementGroupService {
+
+    private final ProcurementGroupMapper baseMapper;
+
+    /**
+     * 查询采购组信息
+     *
+     * @param id 主键
+     * @return 采购组信息
+     */
+    @Override
+    public ProcurementGroupVo queryById(Long id){
+        return baseMapper.selectVoById(id);
+    }
+
+    /**
+     * 分页查询采购组信息列表
+     *
+     * @param bo        查询条件
+     * @param pageQuery 分页参数
+     * @return 采购组信息分页列表
+     */
+    @Override
+    public TableDataInfo<ProcurementGroupVo> queryPageList(ProcurementGroupBo bo, PageQuery pageQuery) {
+        LambdaQueryWrapper<ProcurementGroup> lqw = buildQueryWrapper(bo);
+        Page<ProcurementGroupVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
+        return TableDataInfo.build(result);
+    }
+
+    /**
+     * 查询符合条件的采购组信息列表
+     *
+     * @param bo 查询条件
+     * @return 采购组信息列表
+     */
+    @Override
+    public List<ProcurementGroupVo> queryList(ProcurementGroupBo bo) {
+        LambdaQueryWrapper<ProcurementGroup> lqw = buildQueryWrapper(bo);
+        return baseMapper.selectVoList(lqw);
+    }
+
+    private LambdaQueryWrapper<ProcurementGroup> buildQueryWrapper(ProcurementGroupBo bo) {
+        Map<String, Object> params = bo.getParams();
+        LambdaQueryWrapper<ProcurementGroup> lqw = Wrappers.lambdaQuery();
+        lqw.orderByAsc(ProcurementGroup::getId);
+        lqw.eq(bo.getProgramId() != null, ProcurementGroup::getProgramId, bo.getProgramId());
+        lqw.eq(StringUtils.isNotBlank(bo.getCoverImage()), ProcurementGroup::getCoverImage, bo.getCoverImage());
+        lqw.eq(StringUtils.isNotBlank(bo.getTitle()), ProcurementGroup::getTitle, bo.getTitle());
+        lqw.eq(StringUtils.isNotBlank(bo.getSubtitle()), ProcurementGroup::getSubtitle, bo.getSubtitle());
+        lqw.eq(StringUtils.isNotBlank(bo.getStatus()), ProcurementGroup::getStatus, bo.getStatus());
+        lqw.eq(StringUtils.isNotBlank(bo.getPlatformCode()), ProcurementGroup::getPlatformCode, bo.getPlatformCode());
+        return lqw;
+    }
+
+    /**
+     * 新增采购组信息
+     *
+     * @param bo 采购组信息
+     * @return 是否新增成功
+     */
+    @Override
+    public Boolean insertByBo(ProcurementGroupBo bo) {
+        ProcurementGroup add = MapstructUtils.convert(bo, ProcurementGroup.class);
+        validEntityBeforeSave(add);
+        boolean flag = baseMapper.insert(add) > 0;
+        if (flag) {
+            bo.setId(add.getId());
+        }
+        return flag;
+    }
+
+    /**
+     * 修改采购组信息
+     *
+     * @param bo 采购组信息
+     * @return 是否修改成功
+     */
+    @Override
+    public Boolean updateByBo(ProcurementGroupBo bo) {
+        ProcurementGroup update = MapstructUtils.convert(bo, ProcurementGroup.class);
+        validEntityBeforeSave(update);
+        return baseMapper.updateById(update) > 0;
+    }
+
+    /**
+     * 保存前的数据校验
+     */
+    private void validEntityBeforeSave(ProcurementGroup entity){
+        //TODO 做一些数据校验,如唯一约束
+    }
+
+    /**
+     * 校验并批量删除采购组信息信息
+     *
+     * @param ids     待删除的主键集合
+     * @param isValid 是否进行有效性校验
+     * @return 是否删除成功
+     */
+    @Override
+    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
+        if(isValid){
+            //TODO 做一些业务上的校验,判断是否需要校验
+        }
+        return baseMapper.deleteByIds(ids) > 0;
+    }
+}

+ 178 - 0
ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/service/impl/ProcurementProgramProductServiceImpl.java

@@ -0,0 +1,178 @@
+package org.dromara.product.service.impl;
+
+import cn.hutool.core.bean.BeanUtil;
+import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.util.ObjectUtil;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import org.dromara.common.core.utils.MapstructUtils;
+import org.dromara.common.core.utils.StringUtils;
+import org.dromara.common.mybatis.core.page.TableDataInfo;
+import org.dromara.common.mybatis.core.page.PageQuery;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.dromara.product.domain.ProductBase;
+import org.dromara.product.domain.ProductShoppingCart;
+import org.dromara.product.domain.vo.PcProductVo;
+import org.dromara.product.domain.vo.ProductBaseVo;
+import org.dromara.product.esmapper.ProductEsMapper;
+import org.dromara.product.mapper.ProductBaseMapper;
+import org.dromara.easyes.core.conditions.select.LambdaEsQueryWrapper;
+import org.springframework.stereotype.Service;
+import org.dromara.product.domain.bo.ProcurementProgramProductBo;
+import org.dromara.product.domain.vo.ProcurementProgramProductVo;
+import org.dromara.product.domain.ProcurementProgramProduct;
+import org.dromara.product.mapper.ProcurementProgramProductMapper;
+import org.dromara.product.service.IProcurementProgramProductService;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.Collection;
+
+/**
+ * 采购项目产品关联Service业务层处理
+ *
+ * @author LionLi
+ * @date 2026-02-06
+ */
+@Slf4j
+@RequiredArgsConstructor
+@Service
+public class ProcurementProgramProductServiceImpl  extends ServiceImpl<ProcurementProgramProductMapper, ProcurementProgramProduct> implements IProcurementProgramProductService {
+
+    private final ProcurementProgramProductMapper baseMapper;
+    private final ProductBaseMapper productBaseMapper;
+    private final ProductEsMapper productEsMapper;
+
+    /**
+     * 查询采购项目产品关联
+     *
+     * @param id 主键
+     * @return 采购项目产品关联
+     */
+    @Override
+    public ProcurementProgramProductVo queryById(Long id){
+        return baseMapper.selectVoById(id);
+    }
+
+    /**
+     * 分页查询采购项目产品关联列表
+     *
+     * @param bo        查询条件
+     * @param pageQuery 分页参数
+     * @return 采购项目产品关联分页列表
+     */
+    @Override
+    public TableDataInfo<ProcurementProgramProductVo> queryPageList(ProcurementProgramProductBo bo, PageQuery pageQuery) {
+        LambdaQueryWrapper<ProcurementProgramProduct> lqw = buildQueryWrapper(bo);
+        Page<ProcurementProgramProductVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
+        return TableDataInfo.build(result);
+    }
+
+    /**
+     * 查询符合条件的采购项目产品关联列表
+     *
+     * @param bo 查询条件
+     * @return 采购项目产品关联列表
+     */
+    @Override
+    public List<ProcurementProgramProductVo> queryList(ProcurementProgramProductBo bo) {
+        LambdaQueryWrapper<ProcurementProgramProduct> lqw = buildQueryWrapper(bo);
+        return baseMapper.selectVoList(lqw);
+    }
+
+    private LambdaQueryWrapper<ProcurementProgramProduct> buildQueryWrapper(ProcurementProgramProductBo bo) {
+        Map<String, Object> params = bo.getParams();
+        LambdaQueryWrapper<ProcurementProgramProduct> lqw = Wrappers.lambdaQuery();
+        lqw.orderByAsc(ProcurementProgramProduct::getId);
+        lqw.eq(bo.getGroupId() != null, ProcurementProgramProduct::getGroupId, bo.getGroupId());
+        lqw.eq(bo.getProductId() != null, ProcurementProgramProduct::getProductId, bo.getProductId());
+        lqw.eq(bo.getIsMain() != null, ProcurementProgramProduct::getIsMain, bo.getIsMain());
+        lqw.eq(StringUtils.isNotBlank(bo.getStatus()), ProcurementProgramProduct::getStatus, bo.getStatus());
+        lqw.eq(StringUtils.isNotBlank(bo.getPlatformCode()), ProcurementProgramProduct::getPlatformCode, bo.getPlatformCode());
+        return lqw;
+    }
+
+    /**
+     * 新增采购项目产品关联
+     *
+     * @param bo 采购项目产品关联
+     * @return 是否新增成功
+     */
+    @Override
+    public Boolean insertByBo(ProcurementProgramProductBo bo) {
+        ProcurementProgramProduct add = MapstructUtils.convert(bo, ProcurementProgramProduct.class);
+        validEntityBeforeSave(add);
+        boolean flag = baseMapper.insert(add) > 0;
+        if (flag) {
+            bo.setId(add.getId());
+        }
+        return flag;
+    }
+
+    /**
+     * 修改采购项目产品关联
+     *
+     * @param bo 采购项目产品关联
+     * @return 是否修改成功
+     */
+    @Override
+    public Boolean updateByBo(ProcurementProgramProductBo bo) {
+        ProcurementProgramProduct update = MapstructUtils.convert(bo, ProcurementProgramProduct.class);
+        validEntityBeforeSave(update);
+        return baseMapper.updateById(update) > 0;
+    }
+
+    /**
+     * 保存前的数据校验
+     */
+    private void validEntityBeforeSave(ProcurementProgramProduct entity){
+        //TODO 做一些数据校验,如唯一约束
+    }
+
+    /**
+     * 校验并批量删除采购项目产品关联信息
+     *
+     * @param ids     待删除的主键集合
+     * @param isValid 是否进行有效性校验
+     * @return 是否删除成功
+     */
+    @Override
+    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
+        if(isValid){
+            //TODO 做一些业务上的校验,判断是否需要校验
+        }
+        return baseMapper.deleteByIds(ids) > 0;
+    }
+
+    /**
+     * 获取分组下的产品列表
+     *
+     * @param groupId   分组id
+     * @param pageQuery 分页参数
+     * @return 产品列表
+     */
+    @Override
+    public TableDataInfo<ProductBaseVo> groupProductPage(Long groupId, PageQuery pageQuery) {
+        //先查询分组下的产品
+        LambdaQueryWrapper<ProcurementProgramProduct> lqw = Wrappers.lambdaQuery(ProcurementProgramProduct.class);
+        lqw.eq(ProcurementProgramProduct::getGroupId, groupId);
+        Page<ProcurementProgramProduct> procurementProgramProductPage = baseMapper.selectPage(pageQuery.build(), lqw);
+        if (CollUtil.isNotEmpty(procurementProgramProductPage.getRecords())) {
+            List<ProductBaseVo> productVos = new ArrayList<>();
+            for (ProcurementProgramProduct productShoppingCart : procurementProgramProductPage.getRecords()) {
+                List<ProductBaseVo> productBaseVos = productBaseMapper.selectAllList(Wrappers.query(ProductBase.class)
+                    .eq("b.id", productShoppingCart.getProductId())
+                );
+                productVos.addAll(productBaseVos);
+            }
+            TableDataInfo<ProductBaseVo> build = TableDataInfo.build(productVos);
+            build.setTotal(procurementProgramProductPage.getTotal());
+            return build;
+        }
+        return TableDataInfo.build();
+    }
+}

+ 151 - 0
ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/service/impl/ProcurementProgramServiceImpl.java

@@ -0,0 +1,151 @@
+package org.dromara.product.service.impl;
+
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import org.dromara.common.core.utils.MapstructUtils;
+import org.dromara.common.core.utils.StringUtils;
+import org.dromara.common.mybatis.core.page.TableDataInfo;
+import org.dromara.common.mybatis.core.page.PageQuery;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Service;
+import org.dromara.product.domain.bo.ProcurementProgramBo;
+import org.dromara.product.domain.vo.ProcurementProgramVo;
+import org.dromara.product.domain.ProcurementProgram;
+import org.dromara.product.mapper.ProcurementProgramMapper;
+import org.dromara.product.service.IProcurementProgramService;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Collection;
+
+/**
+ * 采购项目Service业务层处理
+ *
+ * @author LionLi
+ * @date 2026-02-06
+ */
+@Slf4j
+@RequiredArgsConstructor
+@Service
+public class ProcurementProgramServiceImpl  extends ServiceImpl<ProcurementProgramMapper, ProcurementProgram> implements IProcurementProgramService {
+
+    private final ProcurementProgramMapper baseMapper;
+
+    /**
+     * 查询采购项目
+     *
+     * @param id 主键
+     * @return 采购项目
+     */
+    @Override
+    public ProcurementProgramVo queryById(Long id){
+        return baseMapper.selectVoById(id);
+    }
+
+    /**
+     * 分页查询采购项目列表
+     *
+     * @param bo        查询条件
+     * @param pageQuery 分页参数
+     * @return 采购项目分页列表
+     */
+    @Override
+    public TableDataInfo<ProcurementProgramVo> queryPageList(ProcurementProgramBo bo, PageQuery pageQuery) {
+        LambdaQueryWrapper<ProcurementProgram> lqw = buildQueryWrapper(bo);
+        Page<ProcurementProgramVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
+        return TableDataInfo.build(result);
+    }
+
+    /**
+     * 查询符合条件的采购项目列表
+     *
+     * @param bo 查询条件
+     * @return 采购项目列表
+     */
+    @Override
+    public List<ProcurementProgramVo> queryList(ProcurementProgramBo bo) {
+        LambdaQueryWrapper<ProcurementProgram> lqw = buildQueryWrapper(bo);
+        return baseMapper.selectVoList(lqw);
+    }
+
+    private LambdaQueryWrapper<ProcurementProgram> buildQueryWrapper(ProcurementProgramBo bo) {
+        Map<String, Object> params = bo.getParams();
+        LambdaQueryWrapper<ProcurementProgram> lqw = Wrappers.lambdaQuery();
+        lqw.orderByAsc(ProcurementProgram::getId);
+        lqw.eq(StringUtils.isNotBlank(bo.getProgramNo()), ProcurementProgram::getProgramNo, bo.getProgramNo());
+        lqw.eq(StringUtils.isNotBlank(bo.getTweetsTitle()), ProcurementProgram::getTweetsTitle, bo.getTweetsTitle());
+        lqw.eq(StringUtils.isNotBlank(bo.getSubtitle()), ProcurementProgram::getSubtitle, bo.getSubtitle());
+        lqw.eq(StringUtils.isNotBlank(bo.getProgramDescribe()), ProcurementProgram::getProgramDescribe, bo.getProgramDescribe());
+        lqw.eq(StringUtils.isNotBlank(bo.getTweetsCategory()), ProcurementProgram::getTweetsCategory, bo.getTweetsCategory());
+        lqw.eq(bo.getIsShow() != null, ProcurementProgram::getIsShow, bo.getIsShow());
+        lqw.eq(StringUtils.isNotBlank(bo.getCoverImage()), ProcurementProgram::getCoverImage, bo.getCoverImage());
+        lqw.eq(StringUtils.isNotBlank(bo.getImageList()), ProcurementProgram::getImageList, bo.getImageList());
+        lqw.eq(bo.getClicks() != null, ProcurementProgram::getClicks, bo.getClicks());
+        lqw.eq(bo.getCollects() != null, ProcurementProgram::getCollects, bo.getCollects());
+        lqw.eq(StringUtils.isNotBlank(bo.getPrice()), ProcurementProgram::getPrice, bo.getPrice());
+        lqw.eq(StringUtils.isNotBlank(bo.getAdaptNo()), ProcurementProgram::getAdaptNo, bo.getAdaptNo());
+        lqw.eq(StringUtils.isNotBlank(bo.getLable()), ProcurementProgram::getLable, bo.getLable());
+        lqw.eq(StringUtils.isNotBlank(bo.getUploadScheme()), ProcurementProgram::getUploadScheme, bo.getUploadScheme());
+        lqw.eq(StringUtils.isNotBlank(bo.getAdaptIndustry()), ProcurementProgram::getAdaptIndustry, bo.getAdaptIndustry());
+        lqw.eq(bo.getInvalidTime() != null, ProcurementProgram::getInvalidTime, bo.getInvalidTime());
+        lqw.like(StringUtils.isNotBlank(bo.getFilename()), ProcurementProgram::getFilename, bo.getFilename());
+        lqw.eq(StringUtils.isNotBlank(bo.getStatus()), ProcurementProgram::getStatus, bo.getStatus());
+        lqw.eq(StringUtils.isNotBlank(bo.getPlatformCode()), ProcurementProgram::getPlatformCode, bo.getPlatformCode());
+        return lqw;
+    }
+
+    /**
+     * 新增采购项目
+     *
+     * @param bo 采购项目
+     * @return 是否新增成功
+     */
+    @Override
+    public Boolean insertByBo(ProcurementProgramBo bo) {
+        ProcurementProgram add = MapstructUtils.convert(bo, ProcurementProgram.class);
+        validEntityBeforeSave(add);
+        boolean flag = baseMapper.insert(add) > 0;
+        if (flag) {
+            bo.setId(add.getId());
+        }
+        return flag;
+    }
+
+    /**
+     * 修改采购项目
+     *
+     * @param bo 采购项目
+     * @return 是否修改成功
+     */
+    @Override
+    public Boolean updateByBo(ProcurementProgramBo bo) {
+        ProcurementProgram update = MapstructUtils.convert(bo, ProcurementProgram.class);
+        validEntityBeforeSave(update);
+        return baseMapper.updateById(update) > 0;
+    }
+
+    /**
+     * 保存前的数据校验
+     */
+    private void validEntityBeforeSave(ProcurementProgram entity){
+        //TODO 做一些数据校验,如唯一约束
+    }
+
+    /**
+     * 校验并批量删除采购项目信息
+     *
+     * @param ids     待删除的主键集合
+     * @param isValid 是否进行有效性校验
+     * @return 是否删除成功
+     */
+    @Override
+    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
+        if(isValid){
+            //TODO 做一些业务上的校验,判断是否需要校验
+        }
+        return baseMapper.deleteByIds(ids) > 0;
+    }
+}

+ 155 - 0
ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/service/impl/ProcurementTopicsServiceImpl.java

@@ -0,0 +1,155 @@
+package org.dromara.product.service.impl;
+
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import org.dromara.common.core.utils.MapstructUtils;
+import org.dromara.common.core.utils.StringUtils;
+import org.dromara.common.mybatis.core.page.TableDataInfo;
+import org.dromara.common.mybatis.core.page.PageQuery;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Service;
+import org.dromara.product.domain.bo.ProcurementTopicsBo;
+import org.dromara.product.domain.vo.ProcurementTopicsVo;
+import org.dromara.product.domain.ProcurementTopics;
+import org.dromara.product.mapper.ProcurementTopicsMapper;
+import org.dromara.product.service.IProcurementTopicsService;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Collection;
+
+/**
+ * 采购主题Service业务层处理
+ *
+ * @author LionLi
+ * @date 2026-02-06
+ */
+@Slf4j
+@RequiredArgsConstructor
+@Service
+public class ProcurementTopicsServiceImpl  extends ServiceImpl<ProcurementTopicsMapper, ProcurementTopics> implements IProcurementTopicsService {
+
+    private final ProcurementTopicsMapper baseMapper;
+
+    /**
+     * 查询采购主题
+     *
+     * @param id 主键
+     * @return 采购主题
+     */
+    @Override
+    public ProcurementTopicsVo queryById(Long id){
+        return baseMapper.selectVoById(id);
+    }
+
+    /**
+     * 分页查询采购主题列表
+     *
+     * @param bo        查询条件
+     * @param pageQuery 分页参数
+     * @return 采购主题分页列表
+     */
+    @Override
+    public TableDataInfo<ProcurementTopicsVo> queryPageList(ProcurementTopicsBo bo, PageQuery pageQuery) {
+        LambdaQueryWrapper<ProcurementTopics> lqw = buildQueryWrapper(bo);
+        Page<ProcurementTopicsVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
+        return TableDataInfo.build(result);
+    }
+
+    /**
+     * 查询符合条件的采购主题列表
+     *
+     * @param bo 查询条件
+     * @return 采购主题列表
+     */
+    @Override
+    public List<ProcurementTopicsVo> queryList(ProcurementTopicsBo bo) {
+        LambdaQueryWrapper<ProcurementTopics> lqw = buildQueryWrapper(bo);
+        return baseMapper.selectVoList(lqw);
+    }
+
+    private LambdaQueryWrapper<ProcurementTopics> buildQueryWrapper(ProcurementTopicsBo bo) {
+        Map<String, Object> params = bo.getParams();
+        LambdaQueryWrapper<ProcurementTopics> lqw = Wrappers.lambdaQuery();
+        lqw.orderByAsc(ProcurementTopics::getId);
+        lqw.eq(bo.getProcurementTopicsId() != null, ProcurementTopics::getProcurementTopicsId, bo.getProcurementTopicsId());
+        lqw.eq(StringUtils.isNotBlank(bo.getTitle()), ProcurementTopics::getTitle, bo.getTitle());
+        lqw.eq(StringUtils.isNotBlank(bo.getTweetType()), ProcurementTopics::getTweetType, bo.getTweetType());
+        lqw.eq(StringUtils.isNotBlank(bo.getTweetCategory()), ProcurementTopics::getTweetCategory, bo.getTweetCategory());
+        lqw.eq(bo.getIsShow() != null, ProcurementTopics::getIsShow, bo.getIsShow());
+        lqw.eq(bo.getReleaseTime() != null, ProcurementTopics::getReleaseTime, bo.getReleaseTime());
+        lqw.eq(StringUtils.isNotBlank(bo.getExclusiveClient()), ProcurementTopics::getExclusiveClient, bo.getExclusiveClient());
+        lqw.eq(StringUtils.isNotBlank(bo.getContent()), ProcurementTopics::getContent, bo.getContent());
+        lqw.eq(StringUtils.isNotBlank(bo.getCoverImage()), ProcurementTopics::getCoverImage, bo.getCoverImage());
+        lqw.eq(StringUtils.isNotBlank(bo.getSubtitle()), ProcurementTopics::getSubtitle, bo.getSubtitle());
+        lqw.eq(bo.getPraise() != null, ProcurementTopics::getPraise, bo.getPraise());
+        lqw.eq(bo.getReleaseStatus() != null, ProcurementTopics::getReleaseStatus, bo.getReleaseStatus());
+        lqw.eq(StringUtils.isNotBlank(bo.getAdaptNo()), ProcurementTopics::getAdaptNo, bo.getAdaptNo());
+        lqw.eq(StringUtils.isNotBlank(bo.getPrice()), ProcurementTopics::getPrice, bo.getPrice());
+        lqw.eq(StringUtils.isNotBlank(bo.getLable()), ProcurementTopics::getLable, bo.getLable());
+        lqw.eq(bo.getProductCount() != null, ProcurementTopics::getProductCount, bo.getProductCount());
+        lqw.eq(bo.getIsHome() != null, ProcurementTopics::getIsHome, bo.getIsHome());
+        lqw.eq(StringUtils.isNotBlank(bo.getUploadScheme()), ProcurementTopics::getUploadScheme, bo.getUploadScheme());
+        lqw.eq(bo.getIsRelevant() != null, ProcurementTopics::getIsRelevant, bo.getIsRelevant());
+        lqw.eq(StringUtils.isNotBlank(bo.getAdaptIndustry()), ProcurementTopics::getAdaptIndustry, bo.getAdaptIndustry());
+        lqw.eq(StringUtils.isNotBlank(bo.getTopicsDescribe()), ProcurementTopics::getTopicsDescribe, bo.getTopicsDescribe());
+        lqw.eq(StringUtils.isNotBlank(bo.getStatus()), ProcurementTopics::getStatus, bo.getStatus());
+        lqw.eq(StringUtils.isNotBlank(bo.getPlatformCode()), ProcurementTopics::getPlatformCode, bo.getPlatformCode());
+        return lqw;
+    }
+
+    /**
+     * 新增采购主题
+     *
+     * @param bo 采购主题
+     * @return 是否新增成功
+     */
+    @Override
+    public Boolean insertByBo(ProcurementTopicsBo bo) {
+        ProcurementTopics add = MapstructUtils.convert(bo, ProcurementTopics.class);
+        validEntityBeforeSave(add);
+        boolean flag = baseMapper.insert(add) > 0;
+        if (flag) {
+            bo.setId(add.getId());
+        }
+        return flag;
+    }
+
+    /**
+     * 修改采购主题
+     *
+     * @param bo 采购主题
+     * @return 是否修改成功
+     */
+    @Override
+    public Boolean updateByBo(ProcurementTopicsBo bo) {
+        ProcurementTopics update = MapstructUtils.convert(bo, ProcurementTopics.class);
+        validEntityBeforeSave(update);
+        return baseMapper.updateById(update) > 0;
+    }
+
+    /**
+     * 保存前的数据校验
+     */
+    private void validEntityBeforeSave(ProcurementTopics entity){
+        //TODO 做一些数据校验,如唯一约束
+    }
+
+    /**
+     * 校验并批量删除采购主题信息
+     *
+     * @param ids     待删除的主键集合
+     * @param isValid 是否进行有效性校验
+     * @return 是否删除成功
+     */
+    @Override
+    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
+        if(isValid){
+            //TODO 做一些业务上的校验,判断是否需要校验
+        }
+        return baseMapper.deleteByIds(ids) > 0;
+    }
+}

+ 580 - 80
ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/service/impl/ProductBaseServiceImpl.java

@@ -4,6 +4,11 @@ import cn.hutool.core.bean.BeanUtil;
 import cn.hutool.core.collection.CollUtil;
 import cn.hutool.core.util.ObjectUtil;
 import co.elastic.clients.elasticsearch._types.FieldValue;
+import co.elastic.clients.elasticsearch._types.aggregations.Aggregate;
+import co.elastic.clients.elasticsearch._types.aggregations.Buckets;
+import co.elastic.clients.elasticsearch._types.aggregations.LongTermsAggregate;
+import co.elastic.clients.elasticsearch._types.aggregations.LongTermsBucket;
+import co.elastic.clients.elasticsearch.core.SearchResponse;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
@@ -24,8 +29,7 @@ import org.dromara.easyes.core.conditions.select.LambdaEsQueryWrapper;
 import org.dromara.external.api.service.RemoteExternalProductService;
 import org.dromara.product.api.domain.ProductVo;
 import org.dromara.product.domain.*;
-import org.dromara.product.domain.bo.PcProductBo;
-import org.dromara.product.domain.bo.ProductCategoryBo;
+import org.dromara.product.domain.bo.*;
 import org.dromara.product.domain.vo.*;
 import org.dromara.product.esmapper.ProductEsMapper;
 import org.dromara.product.mapper.*;
@@ -34,8 +38,6 @@ import org.springframework.boot.ApplicationArguments;
 import org.springframework.boot.ApplicationRunner;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
-import org.dromara.product.domain.bo.ProductBaseBo;
-import org.dromara.product.domain.bo.SiteProductBo;
 import org.dromara.product.domain.ProductBase;
 import org.dromara.product.domain.ProductExtend;
 import org.dromara.product.domain.ProductClassification;
@@ -111,6 +113,8 @@ public class ProductBaseServiceImpl extends ServiceImpl<ProductBaseMapper, Produ
     private final ProductRecommendLinkMapper productRecommendLinkMapper;
     //平台装修楼层商品
     private final ProductDecorationFloorLinkMapper decorationFloorLinkMapper;
+    //协议商品
+    private final ProtocolProductsMapper protocolProductsMapper;
 
     private final ProductPhotosMapper photosMapper;
 
@@ -122,11 +126,25 @@ public class ProductBaseServiceImpl extends ServiceImpl<ProductBaseMapper, Produ
 
     private final ProductShoppingCartMapper productShoppingCartMapper;
 
+    private final ProductGiftCategoryLinkMapper productGiftCategoryLinkMapper;
+
+    private final ProductGiftFloorLinkMapper productGiftFloorLinkMapper;
+
+    private final ProcurementProgramProductMapper procurementProgramProductMapper;
+
+    private final ProductProgramLinkMapper productProgramLinkMapper;
+
+    private final ProductGiftCategoryMapper productGiftCategoryMapper;
+
+    private final ProductSpecialLinkMapper productSpecialLinkMapper;
+
+
     private final ProductEsMapper esMapper;
 
     @DubboReference
     private RemoteExternalProductService externalProductService;
 
+
     /**
      * Callback used to run the bean.
      * 优化说明:针对200万级别数据,采用分批流式处理,避免OOM
@@ -150,9 +168,9 @@ public class ProductBaseServiceImpl extends ServiceImpl<ProductBaseMapper, Produ
         if (totalInEs < totalInDb) {
             log.info("ES 数据不完整,开始同步...");
 
-            // 优化:使用分页流式处理,每次只加载1000条到内存
+            // 使用LIMIT分页查询,避免一次性加载所有数据
             int pageSize = 1000;
-            int pageNum = 1;
+            long offset = 0;
             long totalSynced = 0;
 
             // 使用线程池处理批量插入
@@ -161,24 +179,23 @@ public class ProductBaseServiceImpl extends ServiceImpl<ProductBaseMapper, Produ
 
             try {
                 while (true) {
-                    // 分页查询,避免一次性加载所有数据
-                    Page<ProductBase> page = new Page<>(pageNum, pageSize);
-                    Page<ProductBaseVo> resultPage = baseMapper.selectVoPage(page, Wrappers.emptyWrapper());
-
-                    if (resultPage.getRecords().isEmpty()) {
+                    // 使用LIMIT OFFSET进行分页查询
+                    QueryWrapper<ProductBase> queryWrapper = Wrappers.query();
+                    queryWrapper.last("LIMIT " + pageSize + " OFFSET " + offset);
+                    List<ProductBaseVo> currentBatch = baseMapper.selectAllList(queryWrapper);
+                    if (CollUtil.isEmpty(currentBatch)) {
                         break;
                     }
 
-                    List<ProductBaseVo> currentBatch = resultPage.getRecords();
-
                     // 异步插入ES
-                    int finalPageNum = pageNum;
+                    long finalOffset = offset;
+                    int batchNumber = (int) (offset / pageSize) + 1;
                     CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
                         try {
                             esMapper.insertBatch(currentBatch);
-                            log.info("成功同步第 {} 页,共 {} 条记录", finalPageNum, currentBatch.size());
+                            log.info("成功同步第 {} 批(OFFSET: {}),共 {} 条记录", batchNumber, finalOffset, currentBatch.size());
                         } catch (Exception e) {
-                            log.error("同步第 {} 页数据失败: {}", finalPageNum, e.getMessage(), e);
+                            log.error("同步第 {} 批数据失败: {}", batchNumber, e.getMessage(), e);
                             throw new RuntimeException(e);
                         }
                     }, executorService);
@@ -189,12 +206,12 @@ public class ProductBaseServiceImpl extends ServiceImpl<ProductBaseMapper, Produ
                     totalSynced += currentBatch.size();
                     log.info("已同步进度: {}/{}", totalSynced, totalInDb);
 
-                    // 如果是最后一页,退出循环
-                    if (resultPage.getRecords().size() < pageSize || !resultPage.hasNext()) {
+                    // 如果当前批次数据少于pageSize,说明是最后一批
+                    if (currentBatch.size() < pageSize) {
                         break;
                     }
 
-                    pageNum++;
+                    offset += pageSize;
 
                     // 添加短暂延迟,避免对数据库和ES造成过大压力
                     Thread.sleep(100);
@@ -335,6 +352,60 @@ public class ProductBaseServiceImpl extends ServiceImpl<ProductBaseMapper, Produ
         return vo;
     }
 
+    /**
+     * 获取es商品
+     */
+    @Override
+    public List<ProductBaseVo> getEsProductList() {
+        return List.of();
+    }
+
+    //    /**
+//     * 分页查询产品基础信息列表
+//     *
+//     * @param bo        查询条件
+//     * @param pageQuery 分页参数
+//     * @return 产品基础信息分页列表
+//     */
+//    @Override
+//    public TableDataInfo<ProductBaseVo> queryPageList(ProductBaseBo bo, PageQuery pageQuery) {
+//        QueryWrapper<ProductBase> lqw = Wrappers.query();
+//        if(ObjectUtil.isNotEmpty(bo.getIds())){
+//            lqw.in( "b.id", bo.getIds().split(","));
+//        }
+//        lqw.ge(ObjectUtil.isNotEmpty(pageQuery.getFirstSeenId()) && pageQuery.getWay() == 0,"b.id", pageQuery.getFirstSeenId());
+//        lqw.gt(ObjectUtil.isNotEmpty(pageQuery.getLastSeenId()) && pageQuery.getWay() == 1,"b.id", pageQuery.getLastSeenId());
+//        lqw.eq(ObjectUtil.isNotEmpty(bo.getBottomCategoryId()),"b.bottom_category_id", bo.getBottomCategoryId());
+//        lqw.eq(ObjectUtil.isNotEmpty(bo.getProductStatus()), "b.product_status", bo.getProductStatus());
+//        lqw.eq(ObjectUtil.isNotEmpty(bo.getProductReviewStatus()),"b.product_review_status", bo.getProductReviewStatus());
+//        lqw.eq(ObjectUtil.isNotEmpty(bo.getDataSource()),"b.data_source", bo.getDataSource());
+//        lqw.eq(ObjectUtil.isNotEmpty(bo.getIsSelf()),"b.is_self", bo.getIsSelf());
+//        lqw.eq(ObjectUtil.isNotEmpty(bo.getProductNo()),"b.product_no", bo.getProductNo());
+//        lqw.like(ObjectUtil.isNotEmpty(bo.getBrandName()),"br.brand_name", bo.getBrandName());
+//        // 支持分类名称模糊搜索(匹配三级分类中的任意一个)
+//        if (ObjectUtil.isNotEmpty(bo.getCategoryName())) {
+//            lqw.and(wrapper -> wrapper
+//                .like("tc.category_name", bo.getCategoryName())
+//                .or().like("mc.category_name", bo.getCategoryName())
+//                .or().like("bc.category_name", bo.getCategoryName())
+//            );
+//        }
+//        lqw.orderByAsc("b.id");
+//        int limit = pageQuery.getPageSize() + 1;
+//        lqw.last("limit "+ limit );
+//        List<ProductBaseVo> result = baseMapper.selectAllList(lqw);
+////        result.forEach(vo -> {
+////
+////        });
+//        int size = result.size();
+//        if (size > pageQuery.getPageSize()) {
+//            result.remove(result.size() - 1);
+//        }
+//        TableDataInfo<ProductBaseVo> tableDataInfo = TableDataInfo.build(result);
+//        tableDataInfo.setTotal( size);
+//        return tableDataInfo;
+//    }
+
     /**
      * 分页查询产品基础信息列表
      *
@@ -344,41 +415,44 @@ public class ProductBaseServiceImpl extends ServiceImpl<ProductBaseMapper, Produ
      */
     @Override
     public TableDataInfo<ProductBaseVo> queryPageList(ProductBaseBo bo, PageQuery pageQuery) {
-        QueryWrapper<ProductBase> lqw = Wrappers.query();
-        if(ObjectUtil.isNotEmpty(bo.getIds())){
-            lqw.in( "b.id", bo.getIds().split(","));
-        }
-        lqw.ge(ObjectUtil.isNotEmpty(pageQuery.getFirstSeenId()) && pageQuery.getWay() == 0,"b.id", pageQuery.getFirstSeenId());
-        lqw.gt(ObjectUtil.isNotEmpty(pageQuery.getLastSeenId()) && pageQuery.getWay() == 1,"b.id", pageQuery.getLastSeenId());
-        lqw.eq(ObjectUtil.isNotEmpty(bo.getBottomCategoryId()),"b.bottom_category_id", bo.getBottomCategoryId());
-        lqw.eq(ObjectUtil.isNotEmpty(bo.getProductStatus()), "b.product_status", bo.getProductStatus());
-        lqw.eq(ObjectUtil.isNotEmpty(bo.getProductReviewStatus()),"b.product_review_status", bo.getProductReviewStatus());
-        lqw.eq(ObjectUtil.isNotEmpty(bo.getDataSource()),"b.data_source", bo.getDataSource());
-        lqw.eq(ObjectUtil.isNotEmpty(bo.getIsSelf()),"b.is_self", bo.getIsSelf());
-        lqw.eq(ObjectUtil.isNotEmpty(bo.getProductNo()),"b.product_no", bo.getProductNo());
-        lqw.like(ObjectUtil.isNotEmpty(bo.getBrandName()),"br.brand_name", bo.getBrandName());
-        // 支持分类名称模糊搜索(匹配三级分类中的任意一个)
-        if (ObjectUtil.isNotEmpty(bo.getCategoryName())) {
-            lqw.and(wrapper -> wrapper
-                .like("tc.category_name", bo.getCategoryName())
-                .or().like("mc.category_name", bo.getCategoryName())
-                .or().like("bc.category_name", bo.getCategoryName())
-            );
+        try {
+            LambdaEsQueryWrapper<ProductBaseVo> productBaseVoLambdaEsQueryWrapper = buildEsQueryWrapper(bo);
+
+            // 检查ES索引是否存在,不存在则降级到数据库查询
+            if (!esMapper.existsIndex("productbasevo")) {
+                log.warn("ES索引 [productbasevo] 不存在,降级到数据库查询");
+                return fallbackToDatabaseQuery(bo, pageQuery);
+            }
+
+            EsPageInfo<ProductBaseVo> esPageInfo = esMapper.pageQuery(productBaseVoLambdaEsQueryWrapper, pageQuery.getPageNum(), pageQuery.getPageSize());
+            log.info("ES查询成功,总页数: {}, 总记录数: {}", esPageInfo.getPages(), esPageInfo.getTotal());
+
+            TableDataInfo<ProductBaseVo> tableDataInfo = TableDataInfo.build();
+            tableDataInfo.setRows(esPageInfo.getList());
+            tableDataInfo.setTotal(esPageInfo.getTotal());
+            return tableDataInfo;
+
+        } catch (Exception e) {
+            log.error("ES查询异常,降级到数据库查询: {}", e.getMessage(), e);
+            return fallbackToDatabaseQuery(bo, pageQuery);
         }
-        lqw.orderByAsc("b.id");
-        int limit = pageQuery.getPageSize() + 1;
-        lqw.last("limit "+ limit );
-        List<ProductBaseVo> result = baseMapper.selectAllList(lqw);
-//        result.forEach(vo -> {
-//
-//        });
-        int size = result.size();
-        if (size > pageQuery.getPageSize()) {
-            result.remove(result.size() - 1);
-        }
-        TableDataInfo<ProductBaseVo> tableDataInfo = TableDataInfo.build(result);
-        tableDataInfo.setTotal( size);
-        return tableDataInfo;
+    }
+
+    /**
+     * 降级到数据库查询(当ES查询失败时使用)
+     *
+     * @param bo        查询条件
+     * @param pageQuery 分页参数
+     * @return 数据库查询结果
+     */
+    private TableDataInfo<ProductBaseVo> fallbackToDatabaseQuery(ProductBaseBo bo, PageQuery pageQuery) {
+        log.info("执行数据库降级查询...");
+
+        LambdaQueryWrapper<ProductBase> lqw = buildQueryWrapper(bo);
+//        Page<ProductBaseVo> page = baseMapper.selectVoPage(pageQuery.build(), lqw);
+
+//        log.info("数据库查询完成,总记录数: {}", page.getTotal());
+        return TableDataInfo.build();
     }
 
     /**
@@ -405,9 +479,121 @@ public class ProductBaseServiceImpl extends ServiceImpl<ProductBaseMapper, Produ
             .eq(ObjectUtil.isNotEmpty(bo.getIsSelf()), ProductBaseVo::getIsSelf, bo.getIsSelf())
             .eq(ObjectUtil.isNotEmpty(bo.getProductReviewStatus()), ProductBaseVo::getProductReviewStatus, bo.getProductReviewStatus())
             .eq(ObjectUtil.isNotEmpty(bo.getDataSource()), ProductBaseVo::getDataSource, bo.getDataSource())
+            .orderByDesc(ProductBaseVo::getId)
             ;
     }
 
+    /**
+     * 构建PC端ES查询条件
+     */
+    private LambdaEsQueryWrapper<ProductBaseVo> buildEsQueryWrapperForPc(PcProductBo bo) {
+        LambdaEsQueryWrapper<ProductBaseVo> wrapper = new LambdaEsQueryWrapper<ProductBaseVo>()
+            .eq(ProductBaseVo::getProductStatus, 1);
+
+        if (ObjectUtil.isNotEmpty(bo.getBrandId())) {
+            wrapper.eq(ProductBaseVo::getBrandId, bo.getBrandId());
+        }
+        if (ObjectUtil.isNotEmpty(bo.getTopCategoryId())) {
+            wrapper.eq(ProductBaseVo::getTopCategoryId, bo.getTopCategoryId());
+        }
+        if (ObjectUtil.isNotEmpty(bo.getMiddleCategoryId())) {
+            wrapper.eq(ProductBaseVo::getMediumCategoryId, bo.getMiddleCategoryId());
+        }
+        if (ObjectUtil.isNotEmpty(bo.getBottomCategoryId())) {
+            wrapper.eq(ProductBaseVo::getBottomCategoryId, bo.getBottomCategoryId());
+        }
+        if (ObjectUtil.isNotEmpty(bo.getIsCustomize())) {
+            wrapper.eq(ProductBaseVo::getIsCustomize, bo.getIsCustomize());
+        }
+
+        return wrapper;
+    }
+
+    /**
+     * PC端商品列表降级查询
+     */
+    private TableDataInfo<PcProductVo> fallbackPcProductQuery(PcProductBo bo, PageQuery pageQuery, QueryWrapper<ProductBase> lqw) {
+        int limit = pageQuery.getPageSize() + 1;
+        lqw.last("limit "+ limit );
+        List<ProductBaseVo> productBaseVos = baseMapper.selectAllList(lqw);
+        if (CollUtil.isNotEmpty(productBaseVos)) {
+            List<PcProductVo> pcProductVos = BeanUtil.copyToList(productBaseVos, PcProductVo.class);
+            int size = productBaseVos.size();
+            if (size > pageQuery.getPageSize()) {
+                pcProductVos.remove(pcProductVos.size() - 1);
+            }
+            TableDataInfo<PcProductVo> tableDataInfo = TableDataInfo.build(pcProductVos);
+            tableDataInfo.setTotal(size);
+            return tableDataInfo;
+        }
+        return TableDataInfo.build();
+    }
+
+    /**
+     * 商品浏览记录降级查询
+     */
+    private TableDataInfo<PcProductVo> fallbackBrowsingHistoryQuery(List<Long> productIds, PageQuery pageQuery) {
+        QueryWrapper<ProductBase> lqw = Wrappers.query(ProductBase.class);
+        lqw.in("b.id", productIds);
+        lqw.eq("b.product_status", 1);
+        int limit = pageQuery.getPageSize() + 1;
+        lqw.last("limit "+ limit );
+        List<ProductBaseVo> productBaseVos = baseMapper.selectAllList(lqw);
+        if (CollUtil.isNotEmpty(productBaseVos)) {
+            List<PcProductVo> pcProductVos = BeanUtil.copyToList(productBaseVos, PcProductVo.class);
+            int size = pcProductVos.size();
+            if (size > pageQuery.getPageSize()) {
+                pcProductVos.remove(pcProductVos.size() - 1);
+            }
+            TableDataInfo<PcProductVo> tableDataInfo = TableDataInfo.build(pcProductVos);
+            tableDataInfo.setTotal(size);
+            return tableDataInfo;
+        }
+        return TableDataInfo.build();
+    }
+
+    /**
+     * 商品收藏夹降级查询
+     */
+    private TableDataInfo<PcProductVo> fallbackFavoritesQuery(List<Long> productIds, PageQuery pageQuery) {
+        QueryWrapper<ProductBase> lqw = Wrappers.query(ProductBase.class);
+        lqw.in("b.id", productIds);
+        lqw.eq("b.product_status", 1);
+        int limit = pageQuery.getPageSize() + 1;
+        lqw.last("limit "+ limit );
+        List<ProductBaseVo> productBaseVos = baseMapper.selectAllList(lqw);
+        if (CollUtil.isNotEmpty(productBaseVos)) {
+            List<PcProductVo> pcProductVos = BeanUtil.copyToList(productBaseVos, PcProductVo.class);
+            int size = pcProductVos.size();
+            if (size > pageQuery.getPageSize()) {
+                pcProductVos.remove(pcProductVos.size() - 1);
+            }
+            TableDataInfo<PcProductVo> tableDataInfo = TableDataInfo.build(pcProductVos);
+            tableDataInfo.setTotal(size);
+            return tableDataInfo;
+        }
+        return TableDataInfo.build();
+    }
+
+    /**
+     * 分类推荐商品降级查询
+     */
+    private TableDataInfo<PcProductVo> fallbackCategoryRecommendQuery(List<Long> productIds, PageQuery pageQuery) {
+        QueryWrapper<ProductBase> lqw = Wrappers.query(ProductBase.class);
+        lqw.in("b.id", productIds);
+        lqw.eq("b.product_status", 1);
+        int limit = pageQuery.getPageSize() + 1;
+        lqw.last("limit "+ limit );
+        List<ProductBaseVo> productBaseVos = baseMapper.selectAllList(lqw);
+        if (CollUtil.isNotEmpty(productBaseVos)) {
+            List<PcProductVo> pcProductVos = BeanUtil.copyToList(productBaseVos, PcProductVo.class);
+            TableDataInfo<PcProductVo> tableDataInfo = TableDataInfo.build(pcProductVos);
+            tableDataInfo.setTotal(productBaseVos.size());
+            return tableDataInfo;
+        }
+        return TableDataInfo.build();
+    }
+
     private LambdaQueryWrapper<ProductBase> buildQueryWrapper(ProductBaseBo bo) {
         Map<String, Object> params = bo.getParams();
         LambdaQueryWrapper<ProductBase> lqw = Wrappers.lambdaQuery();
@@ -1161,12 +1347,33 @@ public class ProductBaseServiceImpl extends ServiceImpl<ProductBaseMapper, Produ
             .eq(ProductRecommendLink::getRecommendId, recommendId));
         if (CollUtil.isNotEmpty(productRecommendLinkVos)) {
             List<Long> productIds = productRecommendLinkVos.stream().map(ProductRecommendLinkVo::getProductId).toList();
-            //获取行家精选商品
-            List<ProductBaseVo> productBaseVos = baseMapper.selectAllList(Wrappers.query(ProductBase.class)
-                .in("b.id", productIds));
-            if (CollUtil.isNotEmpty(productBaseVos)) {
-                List<PcProductVo> pcProductVos = BeanUtil.copyToList(productBaseVos, PcProductVo.class);
-                return pcProductVos;
+            //获取行家精选商品 - 使用ES查询
+            try {
+                LambdaEsQueryWrapper<ProductBaseVo> esQueryWrapper = new LambdaEsQueryWrapper<ProductBaseVo>()
+                    .in(ProductBaseVo::getId, productIds)
+                    .eq(ProductBaseVo::getProductStatus, 1);
+
+                // 检查ES索引是否存在
+                if (!esMapper.existsIndex("productbasevo")) {
+                    log.warn("ES索引 [productbasevo] 不存在,降级到数据库查询");
+                    List<ProductBaseVo> productBaseVos = baseMapper.selectAllList(Wrappers.query(ProductBase.class)
+                        .in("b.id", productIds));
+                    if (CollUtil.isNotEmpty(productBaseVos)) {
+                        return BeanUtil.copyToList(productBaseVos, PcProductVo.class);
+                    }
+                } else {
+                    List<ProductBaseVo> productBaseVos = esMapper.selectList(esQueryWrapper);
+                    if (CollUtil.isNotEmpty(productBaseVos)) {
+                        return BeanUtil.copyToList(productBaseVos, PcProductVo.class);
+                    }
+                }
+            } catch (Exception e) {
+                log.error("ES查询行家精选商品失败,降级到数据库查询: {}", e.getMessage(), e);
+                List<ProductBaseVo> productBaseVos = baseMapper.selectAllList(Wrappers.query(ProductBase.class)
+                    .in("b.id", productIds));
+                if (CollUtil.isNotEmpty(productBaseVos)) {
+                    return BeanUtil.copyToList(productBaseVos, PcProductVo.class);
+                }
             }
         }
         return List.of();
@@ -1184,12 +1391,33 @@ public class ProductBaseServiceImpl extends ServiceImpl<ProductBaseMapper, Produ
         );
         if (CollUtil.isNotEmpty(productDecorationFloorLinkVos)) {
             List<String> productNos = productDecorationFloorLinkVos.stream().map(ProductDecorationFloorLinkVo::getProductNo).toList();
-            //获取分类楼层商品
-            List<ProductBaseVo> productBaseVos = baseMapper.selectAllList(Wrappers.query(ProductBase.class)
-                .in("b.product_no", productNos));
-            if (CollUtil.isNotEmpty(productBaseVos)) {
-                List<PcProductVo> pcProductVos = BeanUtil.copyToList(productBaseVos, PcProductVo.class);
-                return pcProductVos;
+            //获取分类楼层商品 - 使用ES查询
+            try {
+                LambdaEsQueryWrapper<ProductBaseVo> esQueryWrapper = new LambdaEsQueryWrapper<ProductBaseVo>()
+                    .in(ProductBaseVo::getProductNo, productNos)
+                    .eq(ProductBaseVo::getProductStatus, 1);
+
+                // 检查ES索引是否存在
+                if (!esMapper.existsIndex("productbasevo")) {
+                    log.warn("ES索引 [productbasevo] 不存在,降级到数据库查询");
+                    List<ProductBaseVo> productBaseVos = baseMapper.selectAllList(Wrappers.query(ProductBase.class)
+                        .in("b.product_no", productNos));
+                    if (CollUtil.isNotEmpty(productBaseVos)) {
+                        return BeanUtil.copyToList(productBaseVos, PcProductVo.class);
+                    }
+                } else {
+                    List<ProductBaseVo> productBaseVos = esMapper.selectList(esQueryWrapper);
+                    if (CollUtil.isNotEmpty(productBaseVos)) {
+                        return BeanUtil.copyToList(productBaseVos, PcProductVo.class);
+                    }
+                }
+            } catch (Exception e) {
+                log.error("ES查询分类楼层商品失败,降级到数据库查询: {}", e.getMessage(), e);
+                List<ProductBaseVo> productBaseVos = baseMapper.selectAllList(Wrappers.query(ProductBase.class)
+                    .in("b.product_no", productNos));
+                if (CollUtil.isNotEmpty(productBaseVos)) {
+                    return BeanUtil.copyToList(productBaseVos, PcProductVo.class);
+                }
             }
         }
         return List.of();
@@ -1248,19 +1476,56 @@ public class ProductBaseServiceImpl extends ServiceImpl<ProductBaseMapper, Produ
             }
         }
         lqw.select("b.id","b.product_image","p.market_price","p.member_price","p.min_selling_price","p.min_order_quantity","b.item_name","u.unit_name");
-        int limit = pageQuery.getPageSize() + 1;
-        lqw.last("limit "+ limit );
-        List<ProductBaseVo> productBaseVos = baseMapper.selectAllList(lqw);
-        if (CollUtil.isNotEmpty(productBaseVos)) {
-            List<PcProductVo> pcProductVos = BeanUtil.copyToList(productBaseVos, PcProductVo.class);
-            int size = productBaseVos.size();
-            if (size > pageQuery.getPageSize()) {
-                pcProductVos.remove(pcProductVos.size() - 1);
+
+        // 使用ES分页查询
+        try {
+            LambdaEsQueryWrapper<ProductBaseVo> esQueryWrapper = buildEsQueryWrapperForPc(bo);
+
+            // 添加额外的查询条件
+            if (ObjectUtil.isNotEmpty(bo.getSearchKeyword())) {
+                esQueryWrapper.and(wrapper -> wrapper
+                    .like(ProductBaseVo::getItemName, bo.getSearchKeyword())
+                    .or().like(ProductBaseVo::getBrandName, bo.getSearchKeyword())
+                );
             }
-            TableDataInfo<ProductBaseVo> tableDataInfo = TableDataInfo.build(productBaseVos);
-            tableDataInfo.setTotal(size);
-            return TableDataInfo.build(pcProductVos);
+
+            if (bo.getPriceRange() != null) {
+                //价格区间 1:1-100 2:100-500 3:500-1000 4:1000以上
+                switch (bo.getPriceRange()) {
+                    case "1":
+                        esQueryWrapper.between(ProductBaseVo::getMarketPrice, 1, 100);
+                        break;
+                    case "2":
+                        esQueryWrapper.between(ProductBaseVo::getMarketPrice, 100, 500);
+                        break;
+                    case "3":
+                        esQueryWrapper.between(ProductBaseVo::getMarketPrice, 500, 1000);
+                        break;
+                    case "4":
+                        esQueryWrapper.ge(ProductBaseVo::getMarketPrice, 1000);
+                        break;
+                }
+            }
+
+            // 检查ES索引是否存在
+            if (!esMapper.existsIndex("productbasevo")) {
+                log.warn("ES索引 [productbasevo] 不存在,降级到数据库查询");
+                return fallbackPcProductQuery(bo, pageQuery, lqw);
+            }
+
+            EsPageInfo<ProductBaseVo> esPageInfo = esMapper.pageQuery(esQueryWrapper, pageQuery.getPageNum(), pageQuery.getPageSize());
+
+            if (CollUtil.isNotEmpty(esPageInfo.getList())) {
+                List<PcProductVo> pcProductVos = BeanUtil.copyToList(esPageInfo.getList(), PcProductVo.class);
+                TableDataInfo<PcProductVo> tableDataInfo = TableDataInfo.build(pcProductVos);
+                tableDataInfo.setTotal(esPageInfo.getTotal());
+                return tableDataInfo;
+            }
+        } catch (Exception e) {
+            log.error("ES查询PC端商品列表失败,降级到数据库查询: {}", e.getMessage(), e);
+            return fallbackPcProductQuery(bo, pageQuery, lqw);
         }
+
         return TableDataInfo.build();
     }
 
@@ -1295,7 +1560,7 @@ public class ProductBaseServiceImpl extends ServiceImpl<ProductBaseMapper, Produ
             }
         }
 
-        return null;
+        return TableDataInfo.build();
     }
 
     /**
@@ -1305,7 +1570,7 @@ public class ProductBaseServiceImpl extends ServiceImpl<ProductBaseMapper, Produ
      * @param userId
      */
     @Override
-    public TableDataInfo<PcProductVo> getProductFavoritesPage(Long favoritesId, Long userId, PageQuery pageQuery) {
+    public TableDataInfo<PcProductVo> getFavoritesProductPage(Long favoritesId, Long userId, PageQuery pageQuery) {
         //获取收藏夹商品id
         List<ProductCollectVo> productFavoritesLinkVos = productCollectMapper.selectVoList(Wrappers.lambdaQuery(ProductCollect.class)
             .eq(ProductCollect::getFavoritesId, favoritesId)
@@ -1405,7 +1670,45 @@ public class ProductBaseServiceImpl extends ServiceImpl<ProductBaseMapper, Produ
      * PC端轮播图商品列表
      */
     @Override
-    public List<PcProductVo> getCarouselDisplayProductList() {
+    public List<PcProductVo> getCarouselDisplayProductList(Long recommendId) {
+        List<ProductRecommendLinkVo> productRecommendLinkVos = productRecommendLinkMapper.selectVoList(
+                Wrappers.lambdaQuery(ProductRecommendLink.class)
+                    .eq(ProductRecommendLink::getRecommendId, recommendId)
+            );
+        if (CollUtil.isNotEmpty(productRecommendLinkVos)) {
+            List<Long> productIds = productRecommendLinkVos.stream().map(ProductRecommendLinkVo::getProductId).toList();
+            QueryWrapper<ProductBase> lqw = Wrappers.query(ProductBase.class);
+            lqw.in("b.id", productIds);
+            lqw.eq("b.product_status", 1);
+            List<ProductBaseVo> productBaseVos = baseMapper.selectAllList(lqw);
+            if (CollUtil.isNotEmpty(productBaseVos)) {
+                return BeanUtil.copyToList(productBaseVos, PcProductVo.class);
+            }
+        }
+        return List.of();
+    }
+
+    /**
+     * PC端推荐分类推荐商品列表
+     *
+     * @param categoryId
+     */
+    @Override
+    public List<PcProductVo> getRecommendedCategoryProductList(Long categoryId) {
+        List<ProductCategoryRecommendedLinkVo> productCategoryRecommendedLinkVos = productCategoryRecommendedLinkMapper.selectVoList(
+                Wrappers.lambdaQuery(ProductCategoryRecommendedLink.class)
+                    .eq(ProductCategoryRecommendedLink::getCategoryId, categoryId)
+            );
+            if (CollUtil.isNotEmpty(productCategoryRecommendedLinkVos)) {
+                List<Long> productIds = productCategoryRecommendedLinkVos.stream().map(ProductCategoryRecommendedLinkVo::getProductId).toList();
+                QueryWrapper<ProductBase> lqw = Wrappers.query(ProductBase.class);
+                lqw.in("b.id", productIds);
+                lqw.eq("b.product_status", 1);
+                List<ProductBaseVo> productBaseVos = baseMapper.selectAllList(lqw);
+                if (CollUtil.isNotEmpty(productBaseVos)) {
+                    return BeanUtil.copyToList(productBaseVos, PcProductVo.class);
+                }
+            }
         return List.of();
     }
 
@@ -1415,8 +1718,205 @@ public class ProductBaseServiceImpl extends ServiceImpl<ProductBaseMapper, Produ
      * @param floorId
      */
     @Override
-    public List<PcProductVo> getIndustrialFloorProduct(Long floorId) {
+    public List<PcProductVo> getIndustrialFloorProductList(Long floorId) {
+        List<ProductDecorationFloorLinkVo> productDecorationFloorLinkVos = decorationFloorLinkMapper.selectVoList(
+                Wrappers.lambdaQuery(ProductDecorationFloorLink.class)
+                    .eq(ProductDecorationFloorLink::getFloorNo, floorId)
+            );
+        if (CollUtil.isNotEmpty(productDecorationFloorLinkVos)) {
+            List<String> productNos = productDecorationFloorLinkVos.stream().map(ProductDecorationFloorLinkVo::getProductNo).toList();
+            QueryWrapper<ProductBase> lqw = Wrappers.query(ProductBase.class);
+            lqw.in("b.product_no", productNos);
+            lqw.eq("b.product_status", 1);
+            List<ProductBaseVo> productBaseVos = baseMapper.selectAllList(lqw);
+            if (CollUtil.isNotEmpty(productBaseVos)) {
+                return BeanUtil.copyToList(productBaseVos, PcProductVo.class);
+            }
+        }
+
+
         return List.of();
     }
+    /**
+     * PC端福利分类下的商品列表
+     * */
+    @Override
+    public TableDataInfo<PcProductVo> getGiftCategoryLinkPage(PcProductBo bo, PageQuery pageQuery) {
+        ProductGiftCategoryVo productGiftCategoryVo = productGiftCategoryMapper.selectVoById(bo.getBottomCategoryId());
+        if (productGiftCategoryVo == null) {
+            return TableDataInfo.build();
+        }
+        List<ProductGiftCategoryLinkVo> productGiftCategoryLinkVos = productGiftCategoryLinkMapper.selectVoList(
+            Wrappers.lambdaQuery(ProductGiftCategoryLink.class)
+                .eq(ProductGiftCategoryLink::getCategoryNo, productGiftCategoryVo.getCategoryNo())
+                .eq(ProductGiftCategoryLink::getIsShow, "1")
+        );
+        LambdaEsQueryWrapper<ProductBaseVo> wrapper = new LambdaEsQueryWrapper<ProductBaseVo>()
+            .eq(ProductBaseVo::getProductStatus, 1);
+        wrapper.in(ProductBaseVo::getId, productGiftCategoryLinkVos.stream().map(ProductGiftCategoryLinkVo::getProductId).toList());
+        EsPageInfo<ProductBaseVo> esPageInfo = esMapper.pageQuery(wrapper, pageQuery.getPageNum(), pageQuery.getPageSize());
+        List<PcProductVo> pcProductVos = BeanUtil.copyToList(esPageInfo.getList(), PcProductVo.class);
+        TableDataInfo<PcProductVo> build = TableDataInfo.build(pcProductVos);
+        build.setTotal(esPageInfo.getTotal());
+        return build;
+    }
+
+    /**
+     * PC端福利楼层商品列表
+     *
+     * @param floorId
+     */
+    @Override
+    public List<PcProductVo> getGiftFloorLinkProductList(Long floorId) {
+        List<ProductGiftFloorLinkVo> productGiftFloorLinkVos = productGiftFloorLinkMapper.selectVoList(
+                Wrappers.lambdaQuery(ProductGiftFloorLink.class)
+                    .eq(ProductGiftFloorLink::getFloorId, floorId)
+            );
+            if (CollUtil.isNotEmpty(productGiftFloorLinkVos)) {
+                List<Long> productIds = productGiftFloorLinkVos.stream().map(ProductGiftFloorLinkVo::getProductId).toList();
+
+                // 使用ES查询
+                try {
+                    LambdaEsQueryWrapper<ProductBaseVo> esQueryWrapper = new LambdaEsQueryWrapper<ProductBaseVo>()
+                        .in(ProductBaseVo::getId, productIds)
+                        .eq(ProductBaseVo::getProductStatus, 1);
+
+                    // 检查ES索引是否存在
+                    if (!esMapper.existsIndex("productbasevo")) {
+                        log.warn("ES索引 [productbasevo] 不存在,降级到数据库查询");
+                        List<ProductBaseVo> productBaseVos = baseMapper.selectAllList(Wrappers.query(ProductBase.class)
+                            .in("b.id", productIds));
+                        if (CollUtil.isNotEmpty(productBaseVos)) {
+                            return BeanUtil.copyToList(productBaseVos, PcProductVo.class);
+                        }
+                    } else {
+                        List<ProductBaseVo> productBaseVos = esMapper.selectList(esQueryWrapper);
+                        if (CollUtil.isNotEmpty(productBaseVos)) {
+                            return BeanUtil.copyToList(productBaseVos, PcProductVo.class);
+                        }
+                    }
+                } catch (Exception e) {
+                    log.error("ES查询福利楼层商品失败,降级到数据库查询: {}", e.getMessage(), e);
+                    List<ProductBaseVo> productBaseVos = baseMapper.selectAllList(Wrappers.query(ProductBase.class)
+                        .in("b.id", productIds));
+                    if (CollUtil.isNotEmpty(productBaseVos)) {
+                        return BeanUtil.copyToList(productBaseVos, PcProductVo.class);
+                    }
+                }
+            }
+        return List.of();
+    }
+
+    /**
+     * PC端采购方案组商品列表
+     *
+     * @param groupId
+     */
+    @Override
+    public TableDataInfo<PcProductVo> getProcurementProgramGroupProductList(Long groupId,PageQuery pageQuery) {
+        List<ProcurementProgramProductVo> productRecommendLinkVos = procurementProgramProductMapper.selectVoList(
+                Wrappers.lambdaQuery(ProcurementProgramProduct.class)
+                    .eq(ProcurementProgramProduct::getGroupId, groupId)
+            );
+        if (CollUtil.isNotEmpty(productRecommendLinkVos)) {
+            LambdaEsQueryWrapper<ProductBaseVo> wrapper = new LambdaEsQueryWrapper<ProductBaseVo>();
+//            wrapper.eq(ProductBaseVo::getProductStatus, 1);
+            wrapper.in(ProductBaseVo::getId, productRecommendLinkVos.stream().map(ProcurementProgramProductVo::getProductId).toList());
+            EsPageInfo<ProductBaseVo> esPageInfo = esMapper.pageQuery(wrapper, pageQuery.getPageNum(), pageQuery.getPageSize());
+            List<PcProductVo> pcProductVos = BeanUtil.copyToList(esPageInfo.getList(), PcProductVo.class);
+            TableDataInfo<PcProductVo> build = TableDataInfo.build(pcProductVos);
+            build.setTotal(esPageInfo.getTotal());
+            return build;
+        }
+        return TableDataInfo.build();
+    }
+
+    /**
+     * PC端场景采购下的商品
+     *
+     * @param programId
+     */
+    @Override
+    public List<PcProductVo> getProductProgramProductList(Long programId) {
+        List<ProductProgramLinkVo> productProgramLinkVos = productProgramLinkMapper.selectVoList(
+            Wrappers.lambdaQuery(ProductProgramLink.class)
+                .eq(ProductProgramLink::getProgramId, programId)
+        );
+        if (CollUtil.isNotEmpty(productProgramLinkVos)) {
+            List<Long> productIds = productProgramLinkVos.stream().map(ProductProgramLinkVo::getProductId).toList();
+            QueryWrapper<ProductBase> lqw = Wrappers.query(ProductBase.class);
+            lqw.in("b.id", productIds);
+            lqw.eq("b.product_status", 1);
+            List<ProductBaseVo> productBaseVos = baseMapper.selectAllList(lqw);
+            if (CollUtil.isNotEmpty(productBaseVos)) {
+                return BeanUtil.copyToList(productBaseVos, PcProductVo.class);
+            }
+        }
+
+        return List.of();
+    }
+    /**
+     * PC端协议商品列表
+     * */
+    @Override
+    public TableDataInfo<PcProductVo> getProtocolProductsPage(PcProductBo bo, PageQuery pageQuery) {
+        List<ProtocolProductsVo> protocolProductsVos = protocolProductsMapper.selectVoList(Wrappers.lambdaQuery(ProtocolProducts.class)
+            .eq(ProtocolProducts::getCustomerId, bo.getCustomerId())
+            .ge(ObjectUtil.isNotEmpty(bo.getMinPrice()), ProtocolProducts::getAgreementPrice, bo.getMinPrice())
+            .le(ObjectUtil.isNotEmpty(bo.getMaxPrice()), ProtocolProducts::getAgreementPrice, bo.getMaxPrice())
+        );
+        if (CollUtil.isNotEmpty(protocolProductsVos)) {
+            LambdaEsQueryWrapper<ProductBaseVo> wrapper = new LambdaEsQueryWrapper<ProductBaseVo>();
+//            wrapper.eq(ProductBaseVo::getProductStatus, 1);
+            wrapper.in(ProductBaseVo::getId, protocolProductsVos.stream().map(ProtocolProductsVo::getProductId).toList());
+            EsPageInfo<ProductBaseVo> esPageInfo = esMapper.pageQuery(wrapper, pageQuery.getPageNum(), pageQuery.getPageSize());
+            List<PcProductVo> pcProductVos = BeanUtil.copyToList(esPageInfo.getList(), PcProductVo.class);
+            TableDataInfo<PcProductVo> build = TableDataInfo.build(pcProductVos);
+            build.getRows().forEach(pcProductVo -> {
+                pcProductVo.setAgreementPrice(protocolProductsVos.stream().filter(o -> o.getProductId().equals(pcProductVo.getId())).findFirst().get().getAgreementPrice());
+            });
+            build.setTotal(esPageInfo.getTotal());
+            return build;
+        }
+        return TableDataInfo.build();
+    }
+
+    /**
+     * PC端特价商品列表
+     *
+     * @param bo
+     * @param pageQuery
+     */
+    @Override
+    public TableDataInfo<PcProductVo> getSpecialProductList(PcProductBo bo, PageQuery pageQuery) {
+        List<ProductSpecialLinkVo> specialProductsVos = productSpecialLinkMapper.selectVoList(Wrappers.lambdaQuery(ProductSpecialLink.class));
+        if (CollUtil.isNotEmpty(specialProductsVos)) {
+            LambdaEsQueryWrapper<ProductBaseVo> wrapper = new LambdaEsQueryWrapper<ProductBaseVo>();
+            //            wrapper.eq(ProductBaseVo::getProductStatus, 1);
+            if (ObjectUtil.isNotEmpty(bo.getBrandId())) {
+                wrapper.eq(ProductBaseVo::getBrandId, bo.getBrandId());
+            }
+            if (ObjectUtil.isNotEmpty(bo.getTopCategoryId())) {
+                wrapper.eq(ProductBaseVo::getTopCategoryId, bo.getTopCategoryId());
+            }
+            if (ObjectUtil.isNotEmpty(bo.getMiddleCategoryId())) {
+                wrapper.eq(ProductBaseVo::getMediumCategoryId, bo.getMiddleCategoryId());
+            }
+            if (ObjectUtil.isNotEmpty(bo.getBottomCategoryId())) {
+                wrapper.eq(ProductBaseVo::getBottomCategoryId, bo.getBottomCategoryId());
+            }
+            if (ObjectUtil.isNotEmpty(bo.getIsCustomize())) {
+                wrapper.eq(ProductBaseVo::getIsCustomize, bo.getIsCustomize());
+            }
+
+            wrapper.in(ProductBaseVo::getId, specialProductsVos.stream().map(ProductSpecialLinkVo::getProductId).toList());
+            EsPageInfo<ProductBaseVo> esPageInfo = esMapper.pageQuery(wrapper, pageQuery.getPageNum(), pageQuery.getPageSize());
+            List<PcProductVo> pcProductVos = BeanUtil.copyToList(esPageInfo.getList(), PcProductVo.class);
+            TableDataInfo<PcProductVo> build = TableDataInfo.build(pcProductVos);
+            build.setTotal(esPageInfo.getTotal());
+            return build;
+        }
+        return TableDataInfo.build();
+    }
 }
 

+ 88 - 11
ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/service/impl/ProductBrandServiceImpl.java

@@ -3,6 +3,10 @@ package org.dromara.product.service.impl;
 import cn.hutool.core.bean.BeanUtil;
 import cn.hutool.core.collection.CollUtil;
 import cn.hutool.core.util.ObjectUtil;
+import co.elastic.clients.elasticsearch._types.aggregations.Aggregate;
+import co.elastic.clients.elasticsearch._types.aggregations.LongTermsAggregate;
+import co.elastic.clients.elasticsearch._types.aggregations.LongTermsBucket;
+import co.elastic.clients.elasticsearch.core.SearchResponse;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import org.dromara.common.core.utils.MapstructUtils;
@@ -15,21 +19,15 @@ import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.dromara.easyes.core.conditions.select.LambdaEsQueryWrapper;
-import org.dromara.product.domain.ProductBase;
-import org.dromara.product.domain.ProductRecommendLink;
-import org.dromara.product.domain.vo.PcProductVo;
-import org.dromara.product.domain.vo.ProductBaseVo;
-import org.dromara.product.domain.vo.ProductRecommendLinkVo;
+import org.dromara.product.domain.*;
+import org.dromara.product.domain.vo.*;
 import org.dromara.product.esmapper.ProductBrandEsMapper;
-import org.dromara.product.mapper.ProductBaseMapper;
-import org.dromara.product.mapper.ProductRecommendLinkMapper;
+import org.dromara.product.esmapper.ProductEsMapper;
+import org.dromara.product.mapper.*;
 import org.dromara.product.service.IProductRecommendLinkService;
 import org.springframework.boot.ApplicationArguments;
 import org.springframework.stereotype.Service;
 import org.dromara.product.domain.bo.ProductBrandBo;
-import org.dromara.product.domain.vo.ProductBrandVo;
-import org.dromara.product.domain.ProductBrand;
-import org.dromara.product.mapper.ProductBrandMapper;
 import org.dromara.product.service.IProductBrandService;
 import org.springframework.boot.ApplicationRunner;
 import org.springframework.stereotype.Component;
@@ -56,8 +54,12 @@ public class ProductBrandServiceImpl  extends ServiceImpl<ProductBrandMapper, Pr
 
     private final ProductRecommendLinkMapper productRecommendLinkMapper;
 
-    private final ProductBaseMapper productBaseMapper;
+    private final ProductSpecialLinkMapper productSpecialLinkMapper;
 
+    private final ProductEsMapper productEsMapper;
+
+
+    private final ProductIndustrialFloorLinkMapper productIndustrialFloorLinkMapper;
     @Override
     public void run(ApplicationArguments args) throws Exception {
         // 检查索引是否存在,不存在则创建
@@ -261,6 +263,81 @@ public class ProductBrandServiceImpl  extends ServiceImpl<ProductBrandMapper, Pr
      */
     @Override
     public List<ProductBrandVo> getIndustrialFloorBrand(Long floorId) {
+        List<ProductIndustrialFloorLinkVo> productIndustrialFloorLinkVos = productIndustrialFloorLinkMapper.selectVoList(Wrappers.lambdaQuery(ProductIndustrialFloorLink.class)
+            .eq(ProductIndustrialFloorLink::getFloorId, floorId));
+        if (CollUtil.isNotEmpty(productIndustrialFloorLinkVos)) {
+            List<String> brandNo = productIndustrialFloorLinkVos.stream().map(ProductIndustrialFloorLinkVo::getBrandNo).toList();
+            List<ProductBrandVo> productBaseVos = baseMapper.selectVoList(Wrappers.lambdaQuery(ProductBrand.class)
+                .in(ProductBrand::getBrandNo, brandNo));
+            return productBaseVos;
+        }
         return List.of();
     }
+
+    /**
+     * 获取品牌列表
+     *
+     * @param categoryId
+     * @return
+     */
+    @Override
+    public TableDataInfo<ProductBrandVo> getBrandByCategoryList(Long categoryId,String name,String initial,PageQuery pageQuery) {
+        SearchResponse<ProductBaseVo> response = productEsMapper.search(new LambdaEsQueryWrapper<ProductBaseVo>()
+            .eq(ObjectUtil.isNotEmpty(categoryId),ProductBaseVo::getTopCategoryId, categoryId)
+            .like(ObjectUtil.isNotEmpty(name),ProductBaseVo::getBrandName, name)
+            .like(ObjectUtil.isNotEmpty(initial),ProductBaseVo::getBrandName, initial)
+            .limit(pageQuery.getPageNum())
+            .size(pageQuery.getPageSize())
+            .groupBy(ProductBaseVo::getBrandId)
+        );
+        // 解析结果
+        Map<String, Aggregate> aggregations = response.aggregations();
+        if (CollUtil.isEmpty(aggregations)) {
+            return null;
+        }
+        LongTermsAggregate aggregate = (LongTermsAggregate) aggregations.get("brandIdTerms")._get();
+        if (ObjectUtil.isEmpty( aggregate)) {
+            return null;
+        }
+        List<LongTermsBucket> buckets = (List<LongTermsBucket>) aggregate.buckets()._get();
+        if (CollUtil.isEmpty(buckets)) {
+            return null;
+        }
+        List<Long> brandIds = buckets.stream().map(LongTermsBucket::key).toList();
+        Page<ProductBrandVo> productBrandVos = baseMapper.selectVoPage(pageQuery.build(),Wrappers.lambdaQuery(ProductBrand.class)
+            .in(ProductBrand::getId, brandIds));
+        return TableDataInfo.build(productBrandVos);
+    }
+
+    /**
+     * 获取特价品牌列表
+     *
+     * @return
+     */
+    @Override
+    public List<ProductBrandVo> getSpecialBrandList() {
+        List<ProductSpecialLinkVo> specialProductsVos = productSpecialLinkMapper.selectVoList(Wrappers.lambdaQuery(ProductSpecialLink.class));
+        SearchResponse<ProductBaseVo> response = productEsMapper.search(new LambdaEsQueryWrapper<ProductBaseVo>()
+            .size(100)
+            .in(ObjectUtil.isNotEmpty(specialProductsVos),ProductBaseVo::getId, specialProductsVos.stream().map(ProductSpecialLinkVo::getProductId).toList())
+            .groupBy(ProductBaseVo::getBrandId)
+        );
+        // 解析结果
+        Map<String, Aggregate> aggregations = response.aggregations();
+        if (CollUtil.isEmpty(aggregations)) {
+            return null;
+        }
+        LongTermsAggregate aggregate = (LongTermsAggregate) aggregations.get("brandIdTerms")._get();
+        if (ObjectUtil.isEmpty( aggregate)) {
+            return null;
+        }
+        List<LongTermsBucket> buckets = (List<LongTermsBucket>) aggregate.buckets()._get();
+        if (CollUtil.isEmpty(buckets)) {
+            return null;
+        }
+        List<Long> brandIds = buckets.stream().map(LongTermsBucket::key).toList();
+        List<ProductBrandVo> productBrandVos = baseMapper.selectVoList(Wrappers.lambdaQuery(ProductBrand.class)
+            .in(ProductBrand::getId, brandIds));
+        return productBrandVos;
+    }
 }

+ 47 - 2
ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/service/impl/ProductCategoryServiceImpl.java

@@ -2,6 +2,11 @@ package org.dromara.product.service.impl;
 
 import cn.hutool.core.collection.CollUtil;
 import cn.hutool.core.lang.tree.Tree;
+import cn.hutool.core.util.ObjectUtil;
+import co.elastic.clients.elasticsearch._types.aggregations.Aggregate;
+import co.elastic.clients.elasticsearch._types.aggregations.LongTermsAggregate;
+import co.elastic.clients.elasticsearch._types.aggregations.LongTermsBucket;
+import co.elastic.clients.elasticsearch.core.SearchResponse;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import org.dromara.common.core.constant.SystemConstants;
 import org.dromara.common.core.utils.MapstructUtils;
@@ -15,11 +20,15 @@ import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.dromara.common.mybatis.helper.DataBaseHelper;
-import org.dromara.product.domain.vo.PcProductVo;
+import org.dromara.easyes.core.conditions.select.LambdaEsQueryWrapper;
+import org.dromara.product.domain.ProductBrand;
+import org.dromara.product.domain.ProductSpecialLink;
+import org.dromara.product.domain.vo.*;
+import org.dromara.product.esmapper.ProductEsMapper;
+import org.dromara.product.mapper.ProductSpecialLinkMapper;
 import org.springframework.cache.annotation.Cacheable;
 import org.springframework.stereotype.Service;
 import org.dromara.product.domain.bo.ProductCategoryBo;
-import org.dromara.product.domain.vo.ProductCategoryVo;
 import org.dromara.product.domain.ProductCategory;
 import org.dromara.product.mapper.ProductCategoryMapper;
 import org.dromara.product.service.IProductCategoryService;
@@ -41,6 +50,10 @@ public class ProductCategoryServiceImpl  extends ServiceImpl<ProductCategoryMapp
 
     private final ProductCategoryMapper baseMapper;
 
+    private final ProductSpecialLinkMapper productSpecialLinkMapper;
+
+    private final ProductEsMapper productEsMapper;
+
     /**
      * 查询产品分类
      *
@@ -265,4 +278,36 @@ public class ProductCategoryServiceImpl  extends ServiceImpl<ProductCategoryMapp
         );
         return productCategoryVos;
     }
+
+    /**
+     * 获取特价分类列表
+     *
+     * @return 专题分类列表
+     */
+    @Override
+    public List<ProductCategoryVo> getSpecialCategoryList() {
+        List<ProductSpecialLinkVo> specialProductsVos = productSpecialLinkMapper.selectVoList(Wrappers.lambdaQuery(ProductSpecialLink.class));
+        SearchResponse<ProductBaseVo> response = productEsMapper.search(new LambdaEsQueryWrapper<ProductBaseVo>()
+            .size(100)
+            .in(ObjectUtil.isNotEmpty(specialProductsVos),ProductBaseVo::getId, specialProductsVos.stream().map(ProductSpecialLinkVo::getProductId).toList())
+            .groupBy(ProductBaseVo::getTopCategoryId)
+        );
+        // 解析结果
+        Map<String, Aggregate> aggregations = response.aggregations();
+        if (CollUtil.isEmpty(aggregations)) {
+            return null;
+        }
+        LongTermsAggregate aggregate = (LongTermsAggregate) aggregations.get("topCategoryIdTerms")._get();
+        if (ObjectUtil.isEmpty( aggregate)) {
+            return null;
+        }
+        List<LongTermsBucket> buckets = (List<LongTermsBucket>) aggregate.buckets()._get();
+        if (CollUtil.isEmpty(buckets)) {
+            return null;
+        }
+        List<Long> categoryIds = buckets.stream().map(LongTermsBucket::key).toList();
+        List<ProductCategoryVo> productBrandVos = baseMapper.selectVoList(Wrappers.lambdaQuery(ProductCategory.class)
+            .in(ProductCategory::getId, categoryIds));
+        return productBrandVos;
+    }
 }

+ 136 - 0
ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/service/impl/ProductSpecialLinkServiceImpl.java

@@ -0,0 +1,136 @@
+package org.dromara.product.service.impl;
+
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import org.dromara.common.core.utils.MapstructUtils;
+import org.dromara.common.core.utils.StringUtils;
+import org.dromara.common.mybatis.core.page.TableDataInfo;
+import org.dromara.common.mybatis.core.page.PageQuery;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Service;
+import org.dromara.product.domain.bo.ProductSpecialLinkBo;
+import org.dromara.product.domain.vo.ProductSpecialLinkVo;
+import org.dromara.product.domain.ProductSpecialLink;
+import org.dromara.product.mapper.ProductSpecialLinkMapper;
+import org.dromara.product.service.IProductSpecialLinkService;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Collection;
+
+/**
+ * 特价商品Service业务层处理
+ *
+ * @author LionLi
+ * @date 2026-02-10
+ */
+@Slf4j
+@RequiredArgsConstructor
+@Service
+public class ProductSpecialLinkServiceImpl  extends ServiceImpl<ProductSpecialLinkMapper, ProductSpecialLink> implements IProductSpecialLinkService {
+
+    private final ProductSpecialLinkMapper baseMapper;
+
+    /**
+     * 查询特价商品
+     *
+     * @param id 主键
+     * @return 特价商品
+     */
+    @Override
+    public ProductSpecialLinkVo queryById(Long id){
+        return baseMapper.selectVoById(id);
+    }
+
+    /**
+     * 分页查询特价商品列表
+     *
+     * @param bo        查询条件
+     * @param pageQuery 分页参数
+     * @return 特价商品分页列表
+     */
+    @Override
+    public TableDataInfo<ProductSpecialLinkVo> queryPageList(ProductSpecialLinkBo bo, PageQuery pageQuery) {
+        LambdaQueryWrapper<ProductSpecialLink> lqw = buildQueryWrapper(bo);
+        Page<ProductSpecialLinkVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
+        return TableDataInfo.build(result);
+    }
+
+    /**
+     * 查询符合条件的特价商品列表
+     *
+     * @param bo 查询条件
+     * @return 特价商品列表
+     */
+    @Override
+    public List<ProductSpecialLinkVo> queryList(ProductSpecialLinkBo bo) {
+        LambdaQueryWrapper<ProductSpecialLink> lqw = buildQueryWrapper(bo);
+        return baseMapper.selectVoList(lqw);
+    }
+
+    private LambdaQueryWrapper<ProductSpecialLink> buildQueryWrapper(ProductSpecialLinkBo bo) {
+        Map<String, Object> params = bo.getParams();
+        LambdaQueryWrapper<ProductSpecialLink> lqw = Wrappers.lambdaQuery();
+        lqw.orderByAsc(ProductSpecialLink::getId);
+        lqw.eq(bo.getProductId() != null, ProductSpecialLink::getProductId, bo.getProductId());
+        lqw.eq(bo.getSpecialPrice() != null, ProductSpecialLink::getSpecialPrice, bo.getSpecialPrice());
+        lqw.eq(StringUtils.isNotBlank(bo.getStatus()), ProductSpecialLink::getStatus, bo.getStatus());
+        lqw.eq(StringUtils.isNotBlank(bo.getPlatformCode()), ProductSpecialLink::getPlatformCode, bo.getPlatformCode());
+        return lqw;
+    }
+
+    /**
+     * 新增特价商品
+     *
+     * @param bo 特价商品
+     * @return 是否新增成功
+     */
+    @Override
+    public Boolean insertByBo(ProductSpecialLinkBo bo) {
+        ProductSpecialLink add = MapstructUtils.convert(bo, ProductSpecialLink.class);
+        validEntityBeforeSave(add);
+        boolean flag = baseMapper.insert(add) > 0;
+        if (flag) {
+            bo.setId(add.getId());
+        }
+        return flag;
+    }
+
+    /**
+     * 修改特价商品
+     *
+     * @param bo 特价商品
+     * @return 是否修改成功
+     */
+    @Override
+    public Boolean updateByBo(ProductSpecialLinkBo bo) {
+        ProductSpecialLink update = MapstructUtils.convert(bo, ProductSpecialLink.class);
+        validEntityBeforeSave(update);
+        return baseMapper.updateById(update) > 0;
+    }
+
+    /**
+     * 保存前的数据校验
+     */
+    private void validEntityBeforeSave(ProductSpecialLink entity){
+        //TODO 做一些数据校验,如唯一约束
+    }
+
+    /**
+     * 校验并批量删除特价商品信息
+     *
+     * @param ids     待删除的主键集合
+     * @param isValid 是否进行有效性校验
+     * @return 是否删除成功
+     */
+    @Override
+    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
+        if(isValid){
+            //TODO 做一些业务上的校验,判断是否需要校验
+        }
+        return baseMapper.deleteByIds(ids) > 0;
+    }
+}

+ 47 - 10
ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/service/impl/ProtocolProductsServiceImpl.java

@@ -15,7 +15,9 @@ import lombok.extern.slf4j.Slf4j;
 import org.dromara.product.domain.ProductBase;
 import org.dromara.product.domain.bo.ProductBaseBo;
 import org.dromara.product.domain.vo.ProductBaseVo;
+import org.dromara.product.esmapper.ProductEsMapper;
 import org.dromara.product.mapper.ProductBaseMapper;
+import org.dromara.easyes.core.conditions.select.LambdaEsQueryWrapper;
 import org.springframework.stereotype.Service;
 import org.dromara.product.domain.bo.ProtocolProductsBo;
 import org.dromara.product.domain.vo.ProtocolProductsVo;
@@ -42,6 +44,8 @@ public class ProtocolProductsServiceImpl  extends ServiceImpl<ProtocolProductsMa
 
     private final ProductBaseMapper productBaseMapper;
 
+    private final ProductEsMapper productEsMapper;
+
     /**
      * 查询协议产品关联
      *
@@ -70,16 +74,49 @@ public class ProtocolProductsServiceImpl  extends ServiceImpl<ProtocolProductsMa
             return TableDataInfo.build();
         }
         List<Long> productIds = protocolProducts.stream().map(ProtocolProducts::getProductId).distinct().toList();
-        QueryWrapper<ProductBase> lqw = Wrappers.query();
-        lqw.in("b.id", productIds);
-        lqw.eq(ObjectUtil.isNotEmpty(bo.getProductName()),"b.item_name", bo.getProductName());
-        lqw.eq(ObjectUtil.isNotEmpty(bo.getBrandId()),"b.brand_id", bo.getBrandId());
-        lqw.eq(ObjectUtil.isNotEmpty(bo.getProductStatus()),"b.product_status", bo.getProductStatus());
-        lqw.orderByAsc("b.id");
-        List<ProductBaseVo> result = productBaseMapper.selectAllList(lqw);
-        TableDataInfo<ProductBaseVo> tableDataInfo = TableDataInfo.build(result);
-        tableDataInfo.setTotal(productIds.size());
-        return tableDataInfo;
+        
+        // 使用ES查询
+        try {
+            LambdaEsQueryWrapper<ProductBaseVo> esQueryWrapper = new LambdaEsQueryWrapper<ProductBaseVo>()
+                .in(ProductBaseVo::getId, productIds)
+                .like(ObjectUtil.isNotEmpty(bo.getProductName()), ProductBaseVo::getItemName, bo.getProductName())
+                .eq(ObjectUtil.isNotEmpty(bo.getBrandId()), ProductBaseVo::getBrandId, bo.getBrandId())
+                .eq(ObjectUtil.isNotEmpty(bo.getProductStatus()), ProductBaseVo::getProductStatus, bo.getProductStatus())
+                .orderByAsc(ProductBaseVo::getId);
+            
+            // 检查ES索引是否存在
+            if (!productEsMapper.existsIndex("productbasevo")) {
+                log.warn("ES索引 [productbasevo] 不存在,降级到数据库查询");
+                QueryWrapper<ProductBase> lqw = Wrappers.query();
+                lqw.in("b.id", productIds);
+                lqw.eq(ObjectUtil.isNotEmpty(bo.getProductName()),"b.item_name", bo.getProductName());
+                lqw.eq(ObjectUtil.isNotEmpty(bo.getBrandId()),"b.brand_id", bo.getBrandId());
+                lqw.eq(ObjectUtil.isNotEmpty(bo.getProductStatus()),"b.product_status", bo.getProductStatus());
+                lqw.orderByAsc("b.id");
+                List<ProductBaseVo> result = productBaseMapper.selectAllList(lqw);
+                TableDataInfo<ProductBaseVo> tableDataInfo = TableDataInfo.build(result);
+                tableDataInfo.setTotal(productIds.size());
+                return tableDataInfo;
+            }
+            
+            List<ProductBaseVo> result = productEsMapper.selectList(esQueryWrapper);
+            TableDataInfo<ProductBaseVo> tableDataInfo = TableDataInfo.build(result);
+            tableDataInfo.setTotal(productIds.size());
+            return tableDataInfo;
+            
+        } catch (Exception e) {
+            log.error("ES查询协议产品失败,降级到数据库查询: {}", e.getMessage(), e);
+            QueryWrapper<ProductBase> lqw = Wrappers.query();
+            lqw.in("b.id", productIds);
+            lqw.eq(ObjectUtil.isNotEmpty(bo.getProductName()),"b.item_name", bo.getProductName());
+            lqw.eq(ObjectUtil.isNotEmpty(bo.getBrandId()),"b.brand_id", bo.getBrandId());
+            lqw.eq(ObjectUtil.isNotEmpty(bo.getProductStatus()),"b.product_status", bo.getProductStatus());
+            lqw.orderByAsc("b.id");
+            List<ProductBaseVo> result = productBaseMapper.selectAllList(lqw);
+            TableDataInfo<ProductBaseVo> tableDataInfo = TableDataInfo.build(result);
+            tableDataInfo.setTotal(productIds.size());
+            return tableDataInfo;
+        }
     }
 
     /**

+ 7 - 0
ruoyi-modules/ruoyi-product/src/main/resources/mapper/product/ProcurementGroupMapper.xml

@@ -0,0 +1,7 @@
+<?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="org.dromara.product.mapper.ProcurementGroupMapper">
+
+</mapper>

+ 7 - 0
ruoyi-modules/ruoyi-product/src/main/resources/mapper/product/ProcurementProgramMapper.xml

@@ -0,0 +1,7 @@
+<?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="org.dromara.product.mapper.ProcurementProgramMapper">
+
+</mapper>

+ 7 - 0
ruoyi-modules/ruoyi-product/src/main/resources/mapper/product/ProcurementProgramProductMapper.xml

@@ -0,0 +1,7 @@
+<?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="org.dromara.product.mapper.ProcurementProgramProductMapper">
+
+</mapper>

+ 7 - 0
ruoyi-modules/ruoyi-product/src/main/resources/mapper/product/ProcurementTopicsMapper.xml

@@ -0,0 +1,7 @@
+<?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="org.dromara.product.mapper.ProcurementTopicsMapper">
+
+</mapper>

+ 2 - 1
ruoyi-modules/ruoyi-product/src/main/resources/mapper/product/ProductBaseMapper.xml

@@ -272,6 +272,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             b.product_status AS productStatus,
             b.data_source AS dataSource,
             b.remark,
+            b.is_customize AS isCustomize,
             -- 扩展表字段
             e.invoice_name AS invoiceName,
             e.invoice_specs AS invoiceSpec,
@@ -316,7 +317,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         LEFT JOIN product_category bc ON b.bottom_category_id = bc.id AND bc.del_flag = '0'
         LEFT JOIN product_unit u ON b.unit_id = u.id AND u.del_flag = '0'
         ${ew.customSqlSegment}
-    </select>
+                b.is_customize AS isCustomize,</select>
 
     <!-- 查询商品状态统计信息(优化版) -->
     <select id="selectProductStatusCount" resultType="org.dromara.product.domain.vo.StatusCountVo">

+ 7 - 0
ruoyi-modules/ruoyi-product/src/main/resources/mapper/product/ProductSpecialLinkMapper.xml

@@ -0,0 +1,7 @@
+<?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="org.dromara.product.mapper.ProductSpecialLinkMapper">
+
+</mapper>

+ 7 - 0
ruoyi-modules/ruoyi-product/src/main/resources/mapper/product/ProtocolInfoMapper.xml

@@ -0,0 +1,7 @@
+<?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="org.dromara.product.mapper.ProtocolInfoMapper">
+
+</mapper>

+ 7 - 0
ruoyi-modules/ruoyi-product/src/main/resources/mapper/product/ProtocolProductsMapper.xml

@@ -0,0 +1,7 @@
+<?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="org.dromara.product.mapper.ProtocolProductsMapper">
+
+</mapper>

+ 9 - 9
ruoyi-modules/ruoyi-resource/src/main/java/org/dromara/resource/controller/FileCategoryController.java

@@ -39,7 +39,7 @@ public class FileCategoryController extends BaseController {
     /**
      * 查询文件分类列表
      */
-    @SaCheckPermission("file:info:list")
+    //@SaCheckPermission("file:info:list")
     @GetMapping("/list")
     public TableDataInfo<FileCategoryVo> list(FileCategoryBo bo, PageQuery pageQuery) {
         return fileCategoryService.queryPageList(bo, pageQuery);
@@ -48,7 +48,7 @@ public class FileCategoryController extends BaseController {
     /**
      * 查询文件分类列表
      */
-    @SaCheckPermission("file:info:list")
+    //@SaCheckPermission("file:info:list")
     @GetMapping("/listAll")
     public R<List<FileCategoryVo>> listAll(FileCategoryBo bo) {
         List<FileCategoryVo> list = fileCategoryService.queryList(bo);
@@ -58,7 +58,7 @@ public class FileCategoryController extends BaseController {
     /**
      * 查询文件分类树结构
      */
-    @SaCheckPermission("file:info:list")
+    //@SaCheckPermission("file:info:list")
     @GetMapping("/tree")
     public R<List<FileCategoryVo>> tree() {
         List<FileCategoryVo> tree = fileCategoryService.queryCategoryTree();
@@ -68,7 +68,7 @@ public class FileCategoryController extends BaseController {
     /**
      * 根据类型查询分类列表
      */
-    @SaCheckPermission("file:info:list")
+    //@SaCheckPermission("file:info:list")
     @GetMapping("/type/{type}")
     public R<List<FileCategoryVo>> listByType(@PathVariable Integer type) {
         List<FileCategoryVo> list = fileCategoryService.queryByType(type);
@@ -78,7 +78,7 @@ public class FileCategoryController extends BaseController {
     /**
      * 导出文件分类列表
      */
-    @SaCheckPermission("file:info:export")
+    //@SaCheckPermission("file:info:export")
     @Log(title = "文件分类", businessType = BusinessType.EXPORT)
     @PostMapping("/export")
     public void export(FileCategoryBo bo, HttpServletResponse response) {
@@ -91,7 +91,7 @@ public class FileCategoryController extends BaseController {
      *
      * @param id 主键
      */
-    @SaCheckPermission("file:info:query")
+    //@SaCheckPermission("file:info:query")
     @GetMapping("/{id}")
     public R<FileCategoryVo> getInfo(@NotNull(message = "主键不能为空")
                                      @PathVariable Long id) {
@@ -101,7 +101,7 @@ public class FileCategoryController extends BaseController {
     /**
      * 新增文件分类
      */
-    @SaCheckPermission("file:info:add")
+    //@SaCheckPermission("file:info:add")
     @Log(title = "文件分类", businessType = BusinessType.INSERT)
     @PostMapping()
     public R<Void> add(@Validated(AddGroup.class) @RequestBody FileCategoryBo bo) {
@@ -111,7 +111,7 @@ public class FileCategoryController extends BaseController {
     /**
      * 修改文件分类
      */
-    @SaCheckPermission("file:info:edit")
+    //@SaCheckPermission("file:info:edit")
     @Log(title = "文件分类", businessType = BusinessType.UPDATE)
     @PutMapping()
     public R<Void> edit(@Validated(EditGroup.class) @RequestBody FileCategoryBo bo) {
@@ -123,7 +123,7 @@ public class FileCategoryController extends BaseController {
      *
      * @param ids 主键串
      */
-    @SaCheckPermission("file:info:remove")
+    //@SaCheckPermission("file:info:remove")
     @Log(title = "文件分类", businessType = BusinessType.DELETE)
     @DeleteMapping("/{ids}")
     public R<Void> remove(@NotEmpty(message = "主键不能为空")

+ 12 - 12
ruoyi-modules/ruoyi-resource/src/main/java/org/dromara/resource/controller/FileInfoController.java

@@ -40,7 +40,7 @@ public class FileInfoController extends BaseController {
     /**
      * 查询文件信息列表
      */
-    @SaCheckPermission("file:info:list")
+    //@SaCheckPermission("file:info:list")
     @GetMapping("/list")
     public TableDataInfo<FileInfoVo> list(FileInfoBo bo, PageQuery pageQuery) {
         // 添加调试日志
@@ -52,7 +52,7 @@ public class FileInfoController extends BaseController {
     /**
      * 查询文件信息列表
      */
-    @SaCheckPermission("file:info:list")
+    //@SaCheckPermission("file:info:list")
     @GetMapping("/listAll")
     public R<List<FileInfoVo>> listAll(FileInfoBo bo) {
         List<FileInfoVo> list = fileInfoService.queryList(bo);
@@ -62,7 +62,7 @@ public class FileInfoController extends BaseController {
     /**
      * 根据分类ID查询文件列表
      */
-    @SaCheckPermission("file:info:list")
+    //@SaCheckPermission("file:info:list")
     @GetMapping("/category/{categoryId}")
     public R<List<FileInfoVo>> listByCategoryId(@PathVariable Long categoryId) {
         List<FileInfoVo> list = fileInfoService.queryByCategoryId(categoryId);
@@ -72,7 +72,7 @@ public class FileInfoController extends BaseController {
     /**
      * 根据文件类型查询文件列表
      */
-    @SaCheckPermission("file:info:list")
+    //@SaCheckPermission("file:info:list")
     @GetMapping("/type/{type}")
     public R<List<FileInfoVo>> listByType(@PathVariable String type) {
         List<FileInfoVo> list = fileInfoService.queryByType(type);
@@ -82,7 +82,7 @@ public class FileInfoController extends BaseController {
     /**
      * 导出文件信息列表
      */
-    @SaCheckPermission("file:info:export")
+    //@SaCheckPermission("file:info:export")
     @Log(title = "文件信息", businessType = BusinessType.EXPORT)
     @PostMapping("/export")
     public void export(FileInfoBo bo, HttpServletResponse response) {
@@ -95,7 +95,7 @@ public class FileInfoController extends BaseController {
      *
      * @param id 主键
      */
-    @SaCheckPermission("file:info:query")
+    //@SaCheckPermission("file:info:query")
     @GetMapping("/{id}")
     public R<FileInfoVo> getInfo(@NotNull(message = "主键不能为空")
                                  @PathVariable Long id) {
@@ -105,7 +105,7 @@ public class FileInfoController extends BaseController {
     /**
      * 新增文件信息
      */
-    @SaCheckPermission("file:info:add")
+    //@SaCheckPermission("file:info:add")
     @Log(title = "文件信息", businessType = BusinessType.INSERT)
     @PostMapping()
     public R<Void> add(@Validated(AddGroup.class) @RequestBody FileInfoBo bo) {
@@ -115,7 +115,7 @@ public class FileInfoController extends BaseController {
     /**
      * 修改文件信息
      */
-    @SaCheckPermission("file:info:edit")
+    //@SaCheckPermission("file:info:edit")
     @Log(title = "文件信息", businessType = BusinessType.UPDATE)
     @PutMapping()
     public R<Void> edit(@Validated(EditGroup.class) @RequestBody FileInfoBo bo) {
@@ -127,7 +127,7 @@ public class FileInfoController extends BaseController {
      *
      * @param ids 主键串
      */
-    @SaCheckPermission("file:info:remove")
+    //@SaCheckPermission("file:info:remove")
     @Log(title = "文件信息", businessType = BusinessType.DELETE)
     @DeleteMapping("/{ids}")
     public R<Void> remove(@NotEmpty(message = "主键不能为空")
@@ -138,7 +138,7 @@ public class FileInfoController extends BaseController {
     /**
      * 更新文件下载次数
      */
-    @SaCheckPermission("file:info:update")
+    //@SaCheckPermission("file:info:update")
     @Log(title = "文件信息", businessType = BusinessType.UPDATE)
     @PutMapping("/download/{id}")
     public R<Void> updateDownloadCount(@NotNull(message = "主键不能为空")
@@ -149,7 +149,7 @@ public class FileInfoController extends BaseController {
     /**
      * 更新文件查看次数
      */
-    @SaCheckPermission("file:info:update")
+    //@SaCheckPermission("file:info:update")
     @Log(title = "文件信息", businessType = BusinessType.UPDATE)
     @PutMapping("/view/{id}")
     public R<Void> updateViewCount(@NotNull(message = "主键不能为空")
@@ -162,7 +162,7 @@ public class FileInfoController extends BaseController {
      *
      * @param id 文件ID
      */
-    @SaCheckPermission("file:info:download")
+    //@SaCheckPermission("file:info:download")
     @GetMapping("/download/{id}")
     public void downloadFile(@NotNull(message = "文件ID不能为空")
                              @PathVariable Long id,

+ 39 - 0
ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/pc/BenefitsSystemController.java

@@ -40,6 +40,7 @@ public class BenefitsSystemController {
     //分类楼层标签
     private final ISysFloorLabelService sysFloorLabelService;
 
+
     /**
      * 轮播广告(福利装修-轮播广告)
      */
@@ -74,4 +75,42 @@ public class BenefitsSystemController {
         );
         return R.ok(list);
     }
+
+    /**
+    * 首页横幅广告(福利装修-首页长图广告-首页横幅广告)
+    * */
+    @GetMapping("/getBannerAdList")
+    public R<List<SysAdContent>> getBannerAdList() {
+        List<SysAdContent> list = sysAdContentService.list(Wrappers.<SysAdContent>lambdaQuery(SysAdContent.class)
+            .eq(SysAdContent::getAdType, "gift_long_ad")
+            .eq(SysAdContent::getStatus, 1)
+        );
+        return R.ok(list);
+    }
+
+    /**
+    * 推荐广告(福利装修-推荐广告)
+    * */
+    @GetMapping("/getRecommendAdList")
+    public R<List<SysAdContent>> getRecommendAdList() {
+        List<SysAdContent> list = sysAdContentService.list(Wrappers.<SysAdContent>lambdaQuery(SysAdContent.class)
+            .eq(SysAdContent::getAdType, "gift_recommend_ad")
+            .eq(SysAdContent::getStatus, 1)
+        );
+        return R.ok(list);
+    }
+
+    /**
+    * 底部广告(福利装修-Banner广告)
+    * */
+    @GetMapping("/getBottomAdList")
+    public R<List<SysAdContent>> getBottomAdList() {
+        List<SysAdContent> list = sysAdContentService.list(Wrappers.<SysAdContent>lambdaQuery(SysAdContent.class)
+            .eq(SysAdContent::getAdType, "gift_bottom_banner")
+            .eq(SysAdContent::getStatus, 1)
+        );
+        return R.ok(list);
+    }
+
+
 }

+ 55 - 0
ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/pc/IndexSystemController.java

@@ -44,6 +44,14 @@ public class IndexSystemController {
     private final ISysFloorAdvertiseService sysFloorAdvertiseService;
     //分类楼层标签
     private final ISysFloorLabelService sysFloorLabelService;
+    //采购分类
+    private final ISysPurchaseCategoryService sysPurchaseCategoryService;
+    //适配场景
+    private final ISysAdaptSceneService sysAdaptSceneService;
+    //价格区间
+    private final ISysPriceRangeService sysPriceRangeService;
+    //项目类型
+    private final ISysProjectTypeService sysProjectTypeService;
 
     /**
     * 轮播广告(平台装修-轮播广告)
@@ -68,6 +76,15 @@ public class IndexSystemController {
         return R.ok(list);
     }
 
+    /**
+    * 咨迅详情
+    * */
+    @GetMapping("/getYouYiZiXunInfo/{id}")
+    public R<SysAnnouncement> getYouYiZiXunInfo(@PathVariable Long id) {
+        SysAnnouncement sysAnnouncement = sysAnnouncementService.getById(id);
+        return R.ok(sysAnnouncement);
+    }
+
     /**
     * 企业会员权益(平台装修-楼层广告-首页图标广告)
     * */
@@ -219,6 +236,44 @@ public class IndexSystemController {
         return R.ok(sysFloorTitle);
     }
 
+    /**
+     * 采购分类列表
+     * */
+    @GetMapping("/getPurchaseCategoryList")
+    public R<List<SysPurchaseCategory>> getPurchaseCategoryList() {
+        List<SysPurchaseCategory> list = sysPurchaseCategoryService.list(Wrappers.<SysPurchaseCategory>lambdaQuery(SysPurchaseCategory.class));
+        return R.ok(list);
+    }
+
+    /**
+     * 适配场景列表
+     * */
+    @GetMapping("/getAdaptSceneList")
+    public R<List<SysAdaptScene>> getAdaptSceneList() {
+        List<SysAdaptScene> list = sysAdaptSceneService.list(Wrappers.<SysAdaptScene>lambdaQuery(SysAdaptScene.class)
+        );
+        return R.ok(list);
+    }
+    /**
+     * 获取价格区间列表
+     * */
+    @GetMapping("/getPriceRangeList")
+    public R<List<SysPriceRange>> getPriceRangeList() {
+        List<SysPriceRange> list = sysPriceRangeService.list(Wrappers.<SysPriceRange>lambdaQuery(SysPriceRange.class)
+        );
+        return R.ok(list);
+    }
+
+    /**
+    * 项目类型
+    * */
+    @GetMapping("/getProjectTypeList")
+    public R<List<SysProjectType>> getProjectTypeList() {
+        List<SysProjectType> list = sysProjectTypeService.list(Wrappers.<SysProjectType>lambdaQuery(SysProjectType.class)
+        );
+        return R.ok(list);
+    }
+
 
 
 

+ 1 - 1
ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/pc/IndustrySystemController.java

@@ -15,7 +15,7 @@ import org.springframework.web.bind.annotation.RestController;
 import java.util.List;
 
 /**
- * 首页
+ * 工业商城
  *
  * @author
  * @date 2026/1/29 下午3:31