Просмотр исходного кода

Merge branch 'refs/heads/xiaolu' into master

肖路 1 месяц назад
Родитель
Сommit
6d192f758f
63 измененных файлов с 3078 добавлено и 106 удалено
  1. 1 0
      ruoyi-auth/src/main/java/org/dromara/auth/controller/TokenController.java
  2. 2 0
      ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/core/page/TableDataInfo.java
  3. 1 1
      ruoyi-common/ruoyi-common-satoken/src/main/resources/common-satoken.yml
  4. 0 27
      ruoyi-gateway/src/main/java/org/dromara/gateway/filter/GlobalCorsConfig.java
  5. 106 0
      ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/controller/ClientSiteController.java
  6. 106 0
      ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/controller/ClientSiteProductController.java
  7. 106 0
      ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/controller/ClientSiteSettingController.java
  8. 106 0
      ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/controller/ProcurementProgramCollectController.java
  9. 2 0
      ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/controller/ProcurementTopicsController.java
  10. 2 6
      ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/controller/pc/IndexProductController.java
  11. 54 12
      ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/controller/pc/MyProductController.java
  12. 134 0
      ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/domain/ClientSite.java
  13. 97 0
      ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/domain/ClientSiteProduct.java
  14. 130 0
      ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/domain/ClientSiteSetting.java
  15. 51 0
      ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/domain/ProcurementProgramCollect.java
  16. 10 0
      ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/domain/ProductDecorationFloorLink.java
  17. 3 0
      ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/domain/ProductIndustrialFloorLink.java
  18. 143 0
      ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/domain/bo/ClientSiteBo.java
  19. 96 0
      ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/domain/bo/ClientSiteProductBo.java
  20. 142 0
      ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/domain/bo/ClientSiteSettingBo.java
  21. 5 1
      ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/domain/bo/PcProductBo.java
  22. 5 0
      ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/domain/bo/ProcurementProgramBo.java
  23. 53 0
      ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/domain/bo/ProcurementProgramCollectBo.java
  24. 7 0
      ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/domain/bo/ProductBaseBo.java
  25. 5 0
      ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/domain/bo/ProductBrandBo.java
  26. 10 0
      ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/domain/bo/ProductDecorationFloorLinkBo.java
  27. 2 0
      ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/domain/bo/ProductIndustrialFloorLinkBo.java
  28. 7 0
      ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/domain/bo/ProductProgramBo.java
  29. 117 0
      ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/domain/vo/ClientSiteProductVo.java
  30. 163 0
      ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/domain/vo/ClientSiteSettingVo.java
  31. 161 0
      ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/domain/vo/ClientSiteVo.java
  32. 5 0
      ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/domain/vo/PcProductVo.java
  33. 62 0
      ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/domain/vo/ProcurementProgramCollectVo.java
  34. 6 0
      ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/domain/vo/ProductBaseVo.java
  35. 7 1
      ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/domain/vo/ProductBrowsingHistoryVo.java
  36. 10 1
      ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/domain/vo/ProductDecorationFloorLinkVo.java
  37. 3 0
      ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/domain/vo/ProductIndustrialFloorLinkVo.java
  38. 5 2
      ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/domain/vo/ProductProgramVo.java
  39. 12 0
      ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/domain/vo/ServiceCaseVo.java
  40. 15 0
      ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/mapper/ClientSiteMapper.java
  41. 15 0
      ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/mapper/ClientSiteProductMapper.java
  42. 15 0
      ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/mapper/ClientSiteSettingMapper.java
  43. 15 0
      ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/mapper/ProcurementProgramCollectMapper.java
  44. 70 0
      ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/service/IClientSiteProductService.java
  45. 70 0
      ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/service/IClientSiteService.java
  46. 70 0
      ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/service/IClientSiteSettingService.java
  47. 70 0
      ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/service/IProcurementProgramCollectService.java
  48. 7 1
      ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/service/IProductBaseService.java
  49. 2 0
      ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/service/IProductShoppingCartService.java
  50. 144 0
      ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/service/impl/ClientSiteProductServiceImpl.java
  51. 151 0
      ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/service/impl/ClientSiteServiceImpl.java
  52. 150 0
      ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/service/impl/ClientSiteSettingServiceImpl.java
  53. 136 0
      ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/service/impl/ProcurementProgramCollectServiceImpl.java
  54. 135 47
      ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/service/impl/ProductBaseServiceImpl.java
  55. 3 0
      ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/service/impl/ProductBrandServiceImpl.java
  56. 40 2
      ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/service/impl/ProductProgramServiceImpl.java
  57. 7 0
      ruoyi-modules/ruoyi-product/src/main/resources/mapper/product/ClientSiteMapper.xml
  58. 7 0
      ruoyi-modules/ruoyi-product/src/main/resources/mapper/product/ClientSiteProductMapper.xml
  59. 7 0
      ruoyi-modules/ruoyi-product/src/main/resources/mapper/product/ClientSiteSettingMapper.xml
  60. 7 0
      ruoyi-modules/ruoyi-product/src/main/resources/mapper/product/ProcurementProgramCollectMapper.xml
  61. 1 0
      ruoyi-modules/ruoyi-product/src/main/resources/mapper/product/ProductIndustrialFloorLinkMapper.xml
  62. 3 4
      ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/pc/IndexSystemController.java
  63. 1 1
      ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/pc/IndustrySystemController.java

+ 1 - 0
ruoyi-auth/src/main/java/org/dromara/auth/controller/TokenController.java

@@ -4,6 +4,7 @@ import cn.dev33.satoken.exception.NotLoginException;
 import cn.hutool.core.codec.Base64;
 import cn.hutool.core.collection.CollUtil;
 import cn.hutool.core.util.ObjectUtil;
+import cn.hutool.http.HttpUtil;
 import jakarta.servlet.http.HttpServletRequest;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;

+ 2 - 0
ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/core/page/TableDataInfo.java

@@ -8,6 +8,7 @@ import lombok.NoArgsConstructor;
 
 import java.io.Serial;
 import java.io.Serializable;
+import java.util.ArrayList;
 import java.util.List;
 
 /**
@@ -84,6 +85,7 @@ public class TableDataInfo<T> implements Serializable {
         TableDataInfo<T> rspData = new TableDataInfo<>();
         rspData.setCode(HttpStatus.HTTP_OK);
         rspData.setMsg("查询成功");
+        rspData.setRows(new ArrayList<>());
         return rspData;
     }
 

+ 1 - 1
ruoyi-common/ruoyi-common-satoken/src/main/resources/common-satoken.yml

@@ -8,7 +8,7 @@ sa-token:
   # 允许从 header 读取 token
   is-read-header: true
   # 关闭 cookie 鉴权 从根源杜绝 csrf 漏洞风险
-  is-read-cookie: false
+  is-read-cookie: true
   # token前缀
   token-prefix: "Bearer"
   cookie:

+ 0 - 27
ruoyi-gateway/src/main/java/org/dromara/gateway/filter/GlobalCorsConfig.java

@@ -1,27 +0,0 @@
-package org.dromara.gateway.filter;
-
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-import org.springframework.web.cors.CorsConfiguration;
-import org.springframework.web.cors.reactive.CorsWebFilter;
-import org.springframework.web.cors.reactive.UrlBasedCorsConfigurationSource;
-
-@Configuration
-public class GlobalCorsConfig {
-
-    @Bean
-    public CorsWebFilter corsWebFilter() {
-        CorsConfiguration config = new CorsConfiguration();
-        config.setAllowCredentials(true); // 【关键】
-
-        // 添加允许的源 (生产环境建议动态获取或配置列表)
-        config.addAllowedOriginPattern("https://*.xiaoluwebsite.xyz");
-        config.addAllowedHeader("*");
-        config.addAllowedMethod("*");
-
-        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
-        source.registerCorsConfiguration("/**", config);
-
-        return new CorsWebFilter(source);
-    }
-}

+ 106 - 0
ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/controller/ClientSiteController.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.ClientSiteVo;
+import org.dromara.product.domain.bo.ClientSiteBo;
+import org.dromara.product.service.IClientSiteService;
+import org.dromara.common.mybatis.core.page.TableDataInfo;
+
+/**
+ * 客户站点配置
+ * 前端访问路由地址为:/product/site
+ *
+ * @author LionLi
+ * @date 2026-03-04
+ */
+@Validated
+@RequiredArgsConstructor
+@RestController
+@RequestMapping("/site")
+public class ClientSiteController extends BaseController {
+
+    private final IClientSiteService clientSiteService;
+
+    /**
+     * 查询客户站点配置列表
+     */
+    //@SaCheckPermission("product:site:list")
+    @GetMapping("/list")
+    public TableDataInfo<ClientSiteVo> list(ClientSiteBo bo, PageQuery pageQuery) {
+        return clientSiteService.queryPageList(bo, pageQuery);
+    }
+
+    /**
+     * 导出客户站点配置列表
+     */
+    //@SaCheckPermission("product:site:export")
+    @Log(title = "客户站点配置", businessType = BusinessType.EXPORT)
+    @PostMapping("/export")
+    public void export(ClientSiteBo bo, HttpServletResponse response) {
+        List<ClientSiteVo> list = clientSiteService.queryList(bo);
+        ExcelUtil.exportExcel(list, "客户站点配置", ClientSiteVo.class, response);
+    }
+
+    /**
+     * 获取客户站点配置详细信息
+     *
+     * @param id 主键
+     */
+    //@SaCheckPermission("product:site:query")
+    @GetMapping("/{id}")
+    public R<ClientSiteVo> getInfo(@NotNull(message = "主键不能为空")
+                                     @PathVariable("id") Long id) {
+        return R.ok(clientSiteService.queryById(id));
+    }
+
+    /**
+     * 新增客户站点配置
+     */
+    //@SaCheckPermission("product:site:add")
+    @Log(title = "客户站点配置", businessType = BusinessType.INSERT)
+    @RepeatSubmit()
+    @PostMapping()
+    public R<Void> add(@Validated(AddGroup.class) @RequestBody ClientSiteBo bo) {
+        return toAjax(clientSiteService.insertByBo(bo));
+    }
+
+    /**
+     * 修改客户站点配置
+     */
+    //@SaCheckPermission("product:site:edit")
+    @Log(title = "客户站点配置", businessType = BusinessType.UPDATE)
+    @RepeatSubmit()
+    @PutMapping()
+    public R<Void> edit(@Validated(EditGroup.class) @RequestBody ClientSiteBo bo) {
+        return toAjax(clientSiteService.updateByBo(bo));
+    }
+
+    /**
+     * 删除客户站点配置
+     *
+     * @param ids 主键串
+     */
+    //@SaCheckPermission("product:site:remove")
+    @Log(title = "客户站点配置", businessType = BusinessType.DELETE)
+    @DeleteMapping("/{ids}")
+    public R<Void> remove(@NotEmpty(message = "主键不能为空")
+                          @PathVariable("ids") Long[] ids) {
+        return toAjax(clientSiteService.deleteWithValidByIds(List.of(ids), true));
+    }
+}

+ 106 - 0
ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/controller/ClientSiteProductController.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.ClientSiteProductVo;
+import org.dromara.product.domain.bo.ClientSiteProductBo;
+import org.dromara.product.service.IClientSiteProductService;
+import org.dromara.common.mybatis.core.page.TableDataInfo;
+
+/**
+ * 客户站点产品配置
+ * 前端访问路由地址为:/product/siteProduct
+ *
+ * @author LionLi
+ * @date 2026-03-04
+ */
+@Validated
+@RequiredArgsConstructor
+@RestController
+@RequestMapping("/siteProduct")
+public class ClientSiteProductController extends BaseController {
+
+    private final IClientSiteProductService clientSiteProductService;
+
+    /**
+     * 查询客户站点产品配置列表
+     */
+    //@SaCheckPermission("product:siteProduct:list")
+    @GetMapping("/list")
+    public TableDataInfo<ClientSiteProductVo> list(ClientSiteProductBo bo, PageQuery pageQuery) {
+        return clientSiteProductService.queryPageList(bo, pageQuery);
+    }
+
+    /**
+     * 导出客户站点产品配置列表
+     */
+    //@SaCheckPermission("product:siteProduct:export")
+    @Log(title = "客户站点产品配置", businessType = BusinessType.EXPORT)
+    @PostMapping("/export")
+    public void export(ClientSiteProductBo bo, HttpServletResponse response) {
+        List<ClientSiteProductVo> list = clientSiteProductService.queryList(bo);
+        ExcelUtil.exportExcel(list, "客户站点产品配置", ClientSiteProductVo.class, response);
+    }
+
+    /**
+     * 获取客户站点产品配置详细信息
+     *
+     * @param id 主键
+     */
+    //@SaCheckPermission("product:siteProduct:query")
+    @GetMapping("/{id}")
+    public R<ClientSiteProductVo> getInfo(@NotNull(message = "主键不能为空")
+                                     @PathVariable("id") Long id) {
+        return R.ok(clientSiteProductService.queryById(id));
+    }
+
+    /**
+     * 新增客户站点产品配置
+     */
+    //@SaCheckPermission("product:siteProduct:add")
+    @Log(title = "客户站点产品配置", businessType = BusinessType.INSERT)
+    @RepeatSubmit()
+    @PostMapping()
+    public R<Void> add(@Validated(AddGroup.class) @RequestBody ClientSiteProductBo bo) {
+        return toAjax(clientSiteProductService.insertByBo(bo));
+    }
+
+    /**
+     * 修改客户站点产品配置
+     */
+    //@SaCheckPermission("product:siteProduct:edit")
+    @Log(title = "客户站点产品配置", businessType = BusinessType.UPDATE)
+    @RepeatSubmit()
+    @PutMapping()
+    public R<Void> edit(@Validated(EditGroup.class) @RequestBody ClientSiteProductBo bo) {
+        return toAjax(clientSiteProductService.updateByBo(bo));
+    }
+
+    /**
+     * 删除客户站点产品配置
+     *
+     * @param ids 主键串
+     */
+    //@SaCheckPermission("product:siteProduct:remove")
+    @Log(title = "客户站点产品配置", businessType = BusinessType.DELETE)
+    @DeleteMapping("/{ids}")
+    public R<Void> remove(@NotEmpty(message = "主键不能为空")
+                          @PathVariable("ids") Long[] ids) {
+        return toAjax(clientSiteProductService.deleteWithValidByIds(List.of(ids), true));
+    }
+}

+ 106 - 0
ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/controller/ClientSiteSettingController.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.ClientSiteSettingVo;
+import org.dromara.product.domain.bo.ClientSiteSettingBo;
+import org.dromara.product.service.IClientSiteSettingService;
+import org.dromara.common.mybatis.core.page.TableDataInfo;
+
+/**
+ * 客户站点设置
+ * 前端访问路由地址为:/product/siteSetting
+ *
+ * @author LionLi
+ * @date 2026-03-04
+ */
+@Validated
+@RequiredArgsConstructor
+@RestController
+@RequestMapping("/siteSetting")
+public class ClientSiteSettingController extends BaseController {
+
+    private final IClientSiteSettingService clientSiteSettingService;
+
+    /**
+     * 查询客户站点设置列表
+     */
+    //@SaCheckPermission("product:siteSetting:list")
+    @GetMapping("/list")
+    public TableDataInfo<ClientSiteSettingVo> list(ClientSiteSettingBo bo, PageQuery pageQuery) {
+        return clientSiteSettingService.queryPageList(bo, pageQuery);
+    }
+
+    /**
+     * 导出客户站点设置列表
+     */
+    //@SaCheckPermission("product:siteSetting:export")
+    @Log(title = "客户站点设置", businessType = BusinessType.EXPORT)
+    @PostMapping("/export")
+    public void export(ClientSiteSettingBo bo, HttpServletResponse response) {
+        List<ClientSiteSettingVo> list = clientSiteSettingService.queryList(bo);
+        ExcelUtil.exportExcel(list, "客户站点设置", ClientSiteSettingVo.class, response);
+    }
+
+    /**
+     * 获取客户站点设置详细信息
+     *
+     * @param id 主键
+     */
+    //@SaCheckPermission("product:siteSetting:query")
+    @GetMapping("/{id}")
+    public R<ClientSiteSettingVo> getInfo(@NotNull(message = "主键不能为空")
+                                     @PathVariable("id") Long id) {
+        return R.ok(clientSiteSettingService.queryById(id));
+    }
+
+    /**
+     * 新增客户站点设置
+     */
+    //@SaCheckPermission("product:siteSetting:add")
+    @Log(title = "客户站点设置", businessType = BusinessType.INSERT)
+    @RepeatSubmit()
+    @PostMapping()
+    public R<Void> add(@Validated(AddGroup.class) @RequestBody ClientSiteSettingBo bo) {
+        return toAjax(clientSiteSettingService.insertByBo(bo));
+    }
+
+    /**
+     * 修改客户站点设置
+     */
+    //@SaCheckPermission("product:siteSetting:edit")
+    @Log(title = "客户站点设置", businessType = BusinessType.UPDATE)
+    @RepeatSubmit()
+    @PutMapping()
+    public R<Void> edit(@Validated(EditGroup.class) @RequestBody ClientSiteSettingBo bo) {
+        return toAjax(clientSiteSettingService.updateByBo(bo));
+    }
+
+    /**
+     * 删除客户站点设置
+     *
+     * @param ids 主键串
+     */
+    //@SaCheckPermission("product:siteSetting:remove")
+    @Log(title = "客户站点设置", businessType = BusinessType.DELETE)
+    @DeleteMapping("/{ids}")
+    public R<Void> remove(@NotEmpty(message = "主键不能为空")
+                          @PathVariable("ids") Long[] ids) {
+        return toAjax(clientSiteSettingService.deleteWithValidByIds(List.of(ids), true));
+    }
+}

+ 106 - 0
ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/controller/ProcurementProgramCollectController.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.ProcurementProgramCollectVo;
+import org.dromara.product.domain.bo.ProcurementProgramCollectBo;
+import org.dromara.product.service.IProcurementProgramCollectService;
+import org.dromara.common.mybatis.core.page.TableDataInfo;
+
+/**
+ * 客户收藏方案列
+ * 前端访问路由地址为:/product/programCollect
+ *
+ * @author LionLi
+ * @date 2026-03-03
+ */
+@Validated
+@RequiredArgsConstructor
+@RestController
+@RequestMapping("/programCollect")
+public class ProcurementProgramCollectController extends BaseController {
+
+    private final IProcurementProgramCollectService procurementProgramCollectService;
+
+    /**
+     * 查询客户收藏方案列列表
+     */
+    //@SaCheckPermission("product:programCollect:list")
+    @GetMapping("/list")
+    public TableDataInfo<ProcurementProgramCollectVo> list(ProcurementProgramCollectBo bo, PageQuery pageQuery) {
+        return procurementProgramCollectService.queryPageList(bo, pageQuery);
+    }
+
+    /**
+     * 导出客户收藏方案列列表
+     */
+    //@SaCheckPermission("product:programCollect:export")
+    @Log(title = "客户收藏方案列", businessType = BusinessType.EXPORT)
+    @PostMapping("/export")
+    public void export(ProcurementProgramCollectBo bo, HttpServletResponse response) {
+        List<ProcurementProgramCollectVo> list = procurementProgramCollectService.queryList(bo);
+        ExcelUtil.exportExcel(list, "客户收藏方案列", ProcurementProgramCollectVo.class, response);
+    }
+
+    /**
+     * 获取客户收藏方案列详细信息
+     *
+     * @param id 主键
+     */
+    //@SaCheckPermission("product:programCollect:query")
+    @GetMapping("/{id}")
+    public R<ProcurementProgramCollectVo> getInfo(@NotNull(message = "主键不能为空")
+                                     @PathVariable("id") Long id) {
+        return R.ok(procurementProgramCollectService.queryById(id));
+    }
+
+    /**
+     * 新增客户收藏方案列
+     */
+    //@SaCheckPermission("product:programCollect:add")
+    @Log(title = "客户收藏方案列", businessType = BusinessType.INSERT)
+    @RepeatSubmit()
+    @PostMapping()
+    public R<Void> add(@Validated(AddGroup.class) @RequestBody ProcurementProgramCollectBo bo) {
+        return toAjax(procurementProgramCollectService.insertByBo(bo));
+    }
+
+    /**
+     * 修改客户收藏方案列
+     */
+    //@SaCheckPermission("product:programCollect:edit")
+    @Log(title = "客户收藏方案列", businessType = BusinessType.UPDATE)
+    @RepeatSubmit()
+    @PutMapping()
+    public R<Void> edit(@Validated(EditGroup.class) @RequestBody ProcurementProgramCollectBo bo) {
+        return toAjax(procurementProgramCollectService.updateByBo(bo));
+    }
+
+    /**
+     * 删除客户收藏方案列
+     *
+     * @param ids 主键串
+     */
+    //@SaCheckPermission("product:programCollect:remove")
+    @Log(title = "客户收藏方案列", businessType = BusinessType.DELETE)
+    @DeleteMapping("/{ids}")
+    public R<Void> remove(@NotEmpty(message = "主键不能为空")
+                          @PathVariable("ids") Long[] ids) {
+        return toAjax(procurementProgramCollectService.deleteWithValidByIds(List.of(ids), true));
+    }
+}

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

@@ -2,6 +2,7 @@ package org.dromara.product.controller;
 
 import java.util.List;
 
+import cn.hutool.core.date.DateUtil;
 import lombok.RequiredArgsConstructor;
 import jakarta.servlet.http.HttpServletResponse;
 import jakarta.validation.constraints.*;
@@ -77,6 +78,7 @@ public class ProcurementTopicsController extends BaseController {
     @RepeatSubmit()
     @PostMapping()
     public R<Void> add(@Validated(AddGroup.class) @RequestBody ProcurementTopicsBo bo) {
+        bo.setReleaseTime(DateUtil.date());
         return toAjax(procurementTopicsService.insertByBo(bo));
     }
 

+ 2 - 6
ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/controller/pc/IndexProductController.java

@@ -10,10 +10,7 @@ import org.dromara.product.domain.bo.*;
 import org.dromara.product.domain.vo.*;
 import org.dromara.product.service.*;
 import org.springframework.validation.annotation.Validated;
-import org.springframework.web.bind.annotation.GetMapping;
-import org.springframework.web.bind.annotation.PathVariable;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.bind.annotation.*;
 
 import java.util.List;
 
@@ -102,8 +99,7 @@ public class IndexProductController {
      * 查询产品分类树
      * */
     @GetMapping("getProductCategoryTree")
-    public R<List<Tree<Long>>> getProductCategoryTree() {
-        ProductCategoryBo bo = new ProductCategoryBo();
+    public R<List<Tree<Long>>> getProductCategoryTree(ProductCategoryBo bo) {
         bo.setDataSource("youyi");
         return R.ok(productCategoryService.selectCategoryTreeList(bo));
     }

+ 54 - 12
ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/controller/pc/MyProductController.java

@@ -7,11 +7,13 @@ 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.common.satoken.utils.LoginHelper;
+import org.dromara.product.domain.ProductBrowsingHistory;
 import org.dromara.product.domain.ProductCollect;
 import org.dromara.product.domain.ProductFavorites;
 import org.dromara.product.domain.ProductShoppingCart;
 import org.dromara.product.domain.bo.*;
 import org.dromara.product.domain.vo.PcProductVo;
+import org.dromara.product.domain.vo.ProcurementProgramVo;
 import org.dromara.product.domain.vo.ProductFavoritesVo;
 import org.dromara.product.service.*;
 import org.springframework.validation.annotation.Validated;
@@ -19,6 +21,8 @@ import org.springframework.web.bind.annotation.*;
 
 import java.util.Arrays;
 import java.util.List;
+import java.util.Map;
+import java.util.Objects;
 
 /**
  * 我的商品相关接口
@@ -41,6 +45,10 @@ public class MyProductController {
     private final IProductFavoritesService productFavoritesService;
     //购物车
     private final IProductShoppingCartService productShoppingCartService;
+    //采购方案
+    private final IProcurementProgramService procurementProgramService;
+    //采购方案收藏
+    private final IProcurementProgramCollectService procurementProgramCollectService;
 
 
     /**
@@ -49,6 +57,9 @@ public class MyProductController {
     @PostMapping("/addProductBrowsingHistory/{productId}")
     public R addProductBrowsingHistory(@PathVariable Long productId) {
         ProductBrowsingHistoryBo productBrowsingHistoryBo = new ProductBrowsingHistoryBo();
+        productBrowsingHistoryBo.setProductId(productId);
+        productBrowsingHistoryBo.setUserId(LoginHelper.getUserId());
+        productBrowsingHistoryBo.setCustomerId(LoginHelper.getLoginUser().getCustomerId());
         productBrowsingHistoryService.insertByBo(productBrowsingHistoryBo);
         return R.ok();
     }
@@ -58,16 +69,19 @@ public class MyProductController {
     * */
     @DeleteMapping("/deleteProductBrowsingHistory/{ids}")
     public R deleteProductBrowsingHistory(@PathVariable Long[] ids) {
-        productBrowsingHistoryService.deleteWithValidByIds(Arrays.asList(ids), false);
+        productBrowsingHistoryService.remove(Wrappers.lambdaQuery(ProductBrowsingHistory.class)
+            .in(ProductBrowsingHistory::getProductId, ids)
+            .eq(ProductBrowsingHistory::getUserId, LoginHelper.getUserId())
+        );
         return R.ok();
     }
 
     /**
     * 浏览记录的商品
     * */
-    @GetMapping("/getProductBrowsingHistoryPage")
-    public TableDataInfo<PcProductVo> getProductBrowsingHistoryPage(PageQuery pageQuery) {
-        return productBaseService.getProductBrowsingHistoryPage(LoginHelper.getUserId(),pageQuery);
+    @GetMapping("/getProductBrowsingHistory")
+    public R<Map<String,List<PcProductVo>>> getProductBrowsingHistory() {
+        return R.ok(productBaseService.getProductBrowsingHistory(LoginHelper.getUserId()));
     }
 
     /**
@@ -76,6 +90,7 @@ public class MyProductController {
     @PostMapping("/addProductFavorites")
     public R addProductFavorites(@RequestBody ProductFavoritesBo bo) {
         bo.setUserId(LoginHelper.getUserId());
+        bo.setCustomerId(LoginHelper.getLoginUser().getCustomerId());
         productFavoritesService.insertByBo(bo);
         return R.ok();
     }
@@ -114,6 +129,7 @@ public class MyProductController {
             if(one == null){
                 one = new ProductFavorites();
                 one.setUserId(LoginHelper.getUserId());
+                one.setCustomerId(LoginHelper.getLoginUser().getCustomerId());
                 one.setTitle("默认收藏夹");
                 one.setIsDefault("0");
                 productFavoritesService.save(one);
@@ -121,7 +137,7 @@ public class MyProductController {
             bo.setFavoritesId(one.getId());
         }
         bo.setUserId(LoginHelper.getUserId());
-
+        bo.setCustomerId(LoginHelper.getLoginUser().getCustomerId());
         productCollectService.insertByBo(bo);
         return R.ok();
     }
@@ -198,6 +214,16 @@ public class MyProductController {
     public TableDataInfo<PcProductVo> getProductShoppingCartPage(String id, PageQuery pageQuery) {
         return productBaseService.getProductShoppingCartPage(id,LoginHelper.getUserId(),pageQuery);
     }
+
+    /**
+    * 获取购物车商品未失效的商品数量
+    * */
+    @GetMapping("/getProductShoppingCartCount")
+    public R getProductShoppingCartCount() {
+        return R.ok(productBaseService.getProductShoppingCartCount(LoginHelper.getUserId(), 0));
+    }
+
+
     /**
     * 协议供货商品列表
     * */
@@ -207,12 +233,28 @@ public class MyProductController {
         return productBaseService.getProtocolProductsPage(bo,pageQuery);
     }
 
-
-
-
-
-
-
-
+    /**
+    * 获取采购方案
+    * */
+    @GetMapping("/getProcurementProgramProductPage")
+    public TableDataInfo<ProcurementProgramVo> getProcurementProgramProductPage(ProcurementProgramBo bo, PageQuery pageQuery) {
+        if(Objects.equals(bo.getType(), "1")){
+            return procurementProgramService.queryPageList(bo,pageQuery);
+        }else if(Objects.equals(bo.getType(), "2")){
+            return TableDataInfo.build();
+        }else {
+            return TableDataInfo.build();
+        }
+    }
+    /**
+    * 收藏采购方案
+    * */
+    @PostMapping("/addProcurementProgramCollect")
+    public R addProcurementProgramCollect(@RequestBody ProcurementProgramCollectBo bo) {
+        bo.setUserId(LoginHelper.getUserId());
+        bo.setCustomerId(LoginHelper.getLoginUser().getCustomerId());
+        procurementProgramCollectService.insertByBo(bo);
+        return R.ok();
+    }
 
 }

+ 134 - 0
ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/domain/ClientSite.java

@@ -0,0 +1,134 @@
+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.util.Date;
+import com.fasterxml.jackson.annotation.JsonFormat;
+
+import java.io.Serial;
+
+/**
+ * 客户站点配置对象 client_site
+ *
+ * @author LionLi
+ * @date 2026-03-04
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+@TableName("client_site")
+public class ClientSite extends TenantEntity {
+
+    @Serial
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 主键ID,自增
+     */
+    @TableId(value = "id")
+    private Long id;
+
+    /**
+     * 站点名称
+     */
+    private String siteName;
+
+    /**
+     * 站点域名
+     */
+    private String siteDomain;
+
+    /**
+     * 客户id
+     */
+    private Long clientId;
+
+    /**
+     * 客户编号
+     */
+    private String clientNo;
+
+    /**
+     * 客户名称
+     */
+    private String clientName;
+
+    /**
+     * 站点Logo路径或URL
+     */
+    private String siteLogo;
+
+    /**
+     * 登录页背景图路径或URL
+     */
+    private String loginImg;
+
+    /**
+     * 是否显示(例如:1-显示,0-隐藏)
+     */
+    private Long isShow;
+
+    /**
+     * 站点启用开始时间
+     */
+    private Date startTime;
+
+    /**
+     * 站点启用结束时间
+     */
+    private Date endTime;
+
+    /**
+     * 站点标题(HTML title)
+     */
+    private String siteTitle;
+
+    /**
+     * 站点描述(SEO description)
+     */
+    private String siteDescribe;
+
+    /**
+     * 站点关键词(SEO keywords)
+     */
+    private String siteKeywords;
+
+    /**
+     * 背景颜色(如 #FFFFFF 或 CSS 颜色值)
+     */
+    private String backgroundColor;
+
+    /**
+     * 是否为主站(例如:1-是,0-否)
+     */
+    private Long isMainsite;
+
+    /**
+     * 副标题
+     */
+    private String subTitle;
+
+    /**
+     * 备注
+     */
+    private String remark;
+
+    /**
+     * 协议文件路径
+     */
+    private String protocolfile;
+
+    /**
+     * 状态(0正常 1停用)
+     */
+    private String status;
+
+    /**
+     * 删除标志(0代表存在 2代表删除)
+     */
+    @TableLogic
+    private String delFlag;
+
+
+}

+ 97 - 0
ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/domain/ClientSiteProduct.java

@@ -0,0 +1,97 @@
+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;
+
+/**
+ * 客户站点产品配置对象 client_site_product
+ *
+ * @author LionLi
+ * @date 2026-03-04
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+@TableName("client_site_product")
+public class ClientSiteProduct extends TenantEntity {
+
+    @Serial
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 主键ID,自增
+     */
+    @TableId(value = "id")
+    private Long id;
+
+    /**
+     * 客户编号
+     */
+    private String clientNo;
+
+    /**
+     * 客户id
+     */
+    private Long clientId;
+
+    /**
+     * 产品编号
+     */
+    private String productNo;
+
+    /**
+     * 产品id
+     */
+    private Long productId;
+
+    /**
+     * 是否在中心展示(例如:1-是,0-否)
+     */
+    private Long centerView;
+
+    /**
+     * 展示方案1可见性(1-可见,0-不可见)
+     */
+    private Long zsfa1View;
+
+    /**
+     * 展示方案2可见性(1-可见,0-不可见)
+     */
+    private Long zsfa2View;
+
+    /**
+     * 展示方案3可见性(1-可见,0-不可见)
+     */
+    private Long zsfa3View;
+
+    /**
+     * 展示方案4可见性(1-可见,0-不可见)
+     */
+    private Long zsfa4View;
+
+    /**
+     * 协议价格(字符串形式,可能含格式或货币符号)
+     */
+    private String agreementprice;
+
+    /**
+     * 状态(0正常 1停用)
+     */
+    private String status;
+
+    /**
+     * 删除标志(0代表存在 2代表删除)
+     */
+    @TableLogic
+    private String delFlag;
+
+    /**
+     * 备注
+     */
+    private String remark;
+
+
+}

+ 130 - 0
ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/domain/ClientSiteSetting.java

@@ -0,0 +1,130 @@
+package org.dromara.product.domain;
+
+import org.dromara.common.mybatis.core.domain.BaseEntity;
+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;
+
+/**
+ * 客户站点设置对象 client_site_setting
+ *
+ * @author LionLi
+ * @date 2026-03-04
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+@TableName("client_site_setting")
+public class ClientSiteSetting extends BaseEntity {
+
+    @Serial
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 主键ID,自增
+     */
+    @TableId(value = "id")
+    private Long id;
+
+    /**
+     * 客户编号
+     */
+    private String clientNo;
+
+    /**
+     * 客户编号
+     */
+    private Long clientId;
+
+    /**
+     * 设置类型
+     */
+    private String settingType;
+
+    /**
+     * 广告类型
+     */
+    private String advertisType;
+
+    /**
+     * 商品id
+     */
+    private Long productId;
+
+    /**
+     * 产品编号
+     */
+    private String productNo;
+
+    /**
+     * 产品名称
+     */
+    private String productName;
+
+    /**
+     * 导航名称
+     */
+    private String navigationName;
+
+    /**
+     * URL链接
+     */
+    private String url;
+
+    /**
+     * 排序值
+     */
+    private Long sort;
+
+    /**
+     * 是否启用(例如:1-是,0-否)
+     */
+    private Long isEnable;
+
+    /**
+     * 备注
+     */
+    private String remark;
+
+    /**
+     * 广告图片(存储图片路径或Base64编码字符串)
+     */
+    private String advertiseImage;
+
+    /**
+     * 开始时间
+     */
+    private Date startTime;
+
+    /**
+     * 结束时间
+     */
+    private Date endTime;
+
+    /**
+     * 公告编号
+     */
+    private String announcementNo;
+
+    /**
+     * 公告内容
+     */
+    private String announcementContent;
+
+    /**
+     * 创建时间
+     */
+    private Date created;
+
+    /**
+     * 最后修改时间
+     */
+    private Date modify;
+
+
+}

+ 51 - 0
ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/domain/ProcurementProgramCollect.java

@@ -0,0 +1,51 @@
+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_collect
+ *
+ * @author LionLi
+ * @date 2026-03-03
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+@TableName("procurement_program_collect")
+public class ProcurementProgramCollect extends TenantEntity {
+
+    @Serial
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 
+     */
+    @TableId(value = "id")
+    private Long id;
+
+    /**
+     * 方案id
+     */
+    private Long programId;
+
+    /**
+     * 用户id
+     */
+    private Long userId;
+
+    /**
+     * 客户id
+     */
+    private Long customerId;
+
+    /**
+     * 备注
+     */
+    private String remark;
+
+
+}

+ 10 - 0
ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/domain/ProductDecorationFloorLink.java

@@ -37,6 +37,16 @@ public class ProductDecorationFloorLink extends TenantEntity {
      */
     private String productNo;
 
+    /**
+     * 楼层Id
+     */
+    private Long floorId;
+
+    /**
+     * 商品ID
+     */
+    private Long productId;
+
     /**
      * 商品折扣
      */

+ 3 - 0
ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/domain/ProductIndustrialFloorLink.java

@@ -52,6 +52,9 @@ public class ProductIndustrialFloorLink extends TenantEntity {
      */
     private String brandNo;
 
+
+    private Long brandId;
+
     /**
      * 排序
      */

+ 143 - 0
ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/domain/bo/ClientSiteBo.java

@@ -0,0 +1,143 @@
+package org.dromara.product.domain.bo;
+
+import org.dromara.product.domain.ClientSite;
+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 java.util.Date;
+import com.fasterxml.jackson.annotation.JsonFormat;
+
+/**
+ * 客户站点配置业务对象 client_site
+ *
+ * @author LionLi
+ * @date 2026-03-04
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+@AutoMapper(target = ClientSite.class, reverseConvertGenerate = false)
+public class ClientSiteBo extends BaseEntity {
+
+    /**
+     * 主键ID,自增
+     */
+    private Long id;
+
+    /**
+     * 站点名称
+     */
+    //@NotBlank(message = "站点名称不能为空", groups = { AddGroup.class, EditGroup.class })
+    private String siteName;
+
+    /**
+     * 站点域名
+     */
+    //@NotBlank(message = "站点域名不能为空", groups = { AddGroup.class, EditGroup.class })
+    private String siteDomain;
+
+    /**
+     * 客户id
+     */
+    //@NotNull(message = "客户id不能为空", groups = { AddGroup.class, EditGroup.class })
+    private Long clientId;
+
+    /**
+     * 客户编号
+     */
+    //@NotBlank(message = "客户编号不能为空", groups = { AddGroup.class, EditGroup.class })
+    private String clientNo;
+
+    /**
+     * 客户名称
+     */
+    //@NotBlank(message = "客户名称不能为空", groups = { AddGroup.class, EditGroup.class })
+    private String clientName;
+
+    /**
+     * 站点Logo路径或URL
+     */
+    //@NotBlank(message = "站点Logo路径或URL不能为空", groups = { AddGroup.class, EditGroup.class })
+    private String siteLogo;
+
+    /**
+     * 登录页背景图路径或URL
+     */
+    //@NotBlank(message = "登录页背景图路径或URL不能为空", groups = { AddGroup.class, EditGroup.class })
+    private String loginImg;
+
+    /**
+     * 是否显示(例如:1-显示,0-隐藏)
+     */
+    private Long isShow;
+
+    /**
+     * 站点启用开始时间
+     */
+    //@NotNull(message = "站点启用开始时间不能为空", groups = { AddGroup.class, EditGroup.class })
+    private Date startTime;
+
+    /**
+     * 站点启用结束时间
+     */
+    //@NotNull(message = "站点启用结束时间不能为空", groups = { AddGroup.class, EditGroup.class })
+    private Date endTime;
+
+    /**
+     * 站点标题(HTML title)
+     */
+    //@NotBlank(message = "站点标题(HTML title)不能为空", groups = { AddGroup.class, EditGroup.class })
+    private String siteTitle;
+
+    /**
+     * 站点描述(SEO description)
+     */
+    //@NotBlank(message = "站点描述(SEO description)不能为空", groups = { AddGroup.class, EditGroup.class })
+    private String siteDescribe;
+
+    /**
+     * 站点关键词(SEO keywords)
+     */
+    //@NotBlank(message = "站点关键词(SEO keywords)不能为空", groups = { AddGroup.class, EditGroup.class })
+    private String siteKeywords;
+
+    /**
+     * 背景颜色(如 #FFFFFF 或 CSS 颜色值)
+     */
+    //@NotBlank(message = "背景颜色(如 #FFFFFF 或 CSS 颜色值)不能为空", groups = { AddGroup.class, EditGroup.class })
+    private String backgroundColor;
+
+    /**
+     * 是否为主站(例如:1-是,0-否)
+     */
+    private Long isMainsite;
+
+    /**
+     * 副标题
+     */
+    //@NotBlank(message = "副标题不能为空", groups = { AddGroup.class, EditGroup.class })
+    private String subTitle;
+
+    /**
+     * 备注
+     */
+    //@NotBlank(message = "备注不能为空", groups = { AddGroup.class, EditGroup.class })
+    private String remark;
+
+    /**
+     * 协议文件路径
+     */
+    //@NotBlank(message = "协议文件路径不能为空", groups = { AddGroup.class, EditGroup.class })
+    private String protocolfile;
+
+    /**
+     * 状态(0正常 1停用)
+     */
+    //@NotBlank(message = "状态(0正常 1停用)不能为空", groups = { AddGroup.class, EditGroup.class })
+    private String status;
+
+
+}

+ 96 - 0
ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/domain/bo/ClientSiteProductBo.java

@@ -0,0 +1,96 @@
+package org.dromara.product.domain.bo;
+
+import org.dromara.product.domain.ClientSiteProduct;
+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.*;
+
+/**
+ * 客户站点产品配置业务对象 client_site_product
+ *
+ * @author LionLi
+ * @date 2026-03-04
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+@AutoMapper(target = ClientSiteProduct.class, reverseConvertGenerate = false)
+public class ClientSiteProductBo extends BaseEntity {
+
+    /**
+     * 主键ID,自增
+     */
+    private Long id;
+
+    /**
+     * 客户编号
+     */
+    //@NotBlank(message = "客户编号不能为空", groups = { AddGroup.class, EditGroup.class })
+    private String clientNo;
+
+    /**
+     * 客户id
+     */
+    //@NotNull(message = "客户id不能为空", groups = { AddGroup.class, EditGroup.class })
+    private Long clientId;
+
+    /**
+     * 产品编号
+     */
+    //@NotBlank(message = "产品编号不能为空", groups = { AddGroup.class, EditGroup.class })
+    private String productNo;
+
+    /**
+     * 产品id
+     */
+    //@NotNull(message = "产品id不能为空", groups = { AddGroup.class, EditGroup.class })
+    private Long productId;
+
+    /**
+     * 是否在中心展示(例如:1-是,0-否)
+     */
+    private Long centerView;
+
+    /**
+     * 展示方案1可见性(1-可见,0-不可见)
+     */
+    private Long zsfa1View;
+
+    /**
+     * 展示方案2可见性(1-可见,0-不可见)
+     */
+    private Long zsfa2View;
+
+    /**
+     * 展示方案3可见性(1-可见,0-不可见)
+     */
+    private Long zsfa3View;
+
+    /**
+     * 展示方案4可见性(1-可见,0-不可见)
+     */
+    private Long zsfa4View;
+
+    /**
+     * 协议价格(字符串形式,可能含格式或货币符号)
+     */
+    //@NotBlank(message = "协议价格(字符串形式,可能含格式或货币符号)不能为空", groups = { AddGroup.class, EditGroup.class })
+    private String agreementprice;
+
+    /**
+     * 状态(0正常 1停用)
+     */
+    //@NotBlank(message = "状态(0正常 1停用)不能为空", groups = { AddGroup.class, EditGroup.class })
+    private String status;
+
+    /**
+     * 备注
+     */
+    //@NotBlank(message = "备注不能为空", groups = { AddGroup.class, EditGroup.class })
+    private String remark;
+
+
+}

+ 142 - 0
ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/domain/bo/ClientSiteSettingBo.java

@@ -0,0 +1,142 @@
+package org.dromara.product.domain.bo;
+
+import org.dromara.product.domain.ClientSiteSetting;
+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;
+
+/**
+ * 客户站点设置业务对象 client_site_setting
+ *
+ * @author LionLi
+ * @date 2026-03-04
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+@AutoMapper(target = ClientSiteSetting.class, reverseConvertGenerate = false)
+public class ClientSiteSettingBo extends BaseEntity {
+
+    /**
+     * 主键ID,自增
+     */
+    private Long id;
+
+    /**
+     * 客户编号
+     */
+    //@NotBlank(message = "客户编号不能为空", groups = { AddGroup.class, EditGroup.class })
+    private String clientNo;
+
+    /**
+     * 客户编号
+     */
+    //@NotNull(message = "客户编号不能为空", groups = { AddGroup.class, EditGroup.class })
+    private Long clientId;
+
+    /**
+     * 设置类型
+     */
+    //@NotBlank(message = "设置类型不能为空", groups = { AddGroup.class, EditGroup.class })
+    private String settingType;
+
+    /**
+     * 广告类型
+     */
+    //@NotBlank(message = "广告类型不能为空", groups = { AddGroup.class, EditGroup.class })
+    private String advertisType;
+
+    /**
+     * 商品id
+     */
+    //@NotNull(message = "商品id不能为空", groups = { AddGroup.class, EditGroup.class })
+    private Long productId;
+
+    /**
+     * 产品编号
+     */
+    //@NotBlank(message = "产品编号不能为空", groups = { AddGroup.class, EditGroup.class })
+    private String productNo;
+
+    /**
+     * 产品名称
+     */
+    //@NotBlank(message = "产品名称不能为空", groups = { AddGroup.class, EditGroup.class })
+    private String productName;
+
+    /**
+     * 导航名称
+     */
+    //@NotBlank(message = "导航名称不能为空", groups = { AddGroup.class, EditGroup.class })
+    private String navigationName;
+
+    /**
+     * URL链接
+     */
+    //@NotBlank(message = "URL链接不能为空", groups = { AddGroup.class, EditGroup.class })
+    private String url;
+
+    /**
+     * 排序值
+     */
+    private Long sort;
+
+    /**
+     * 是否启用(例如:1-是,0-否)
+     */
+    private Long isEnable;
+
+    /**
+     * 备注
+     */
+    //@NotBlank(message = "备注不能为空", groups = { AddGroup.class, EditGroup.class })
+    private String remark;
+
+    /**
+     * 广告图片(存储图片路径或Base64编码字符串)
+     */
+    //@NotBlank(message = "广告图片(存储图片路径或Base64编码字符串)不能为空", groups = { AddGroup.class, EditGroup.class })
+    private String advertiseImage;
+
+    /**
+     * 开始时间
+     */
+    private Date startTime;
+
+    /**
+     * 结束时间
+     */
+    private Date endTime;
+
+    /**
+     * 公告编号
+     */
+    //@NotBlank(message = "公告编号不能为空", groups = { AddGroup.class, EditGroup.class })
+    private String announcementNo;
+
+    /**
+     * 公告内容
+     */
+    //@NotBlank(message = "公告内容不能为空", groups = { AddGroup.class, EditGroup.class })
+    private String announcementContent;
+
+    /**
+     * 创建时间
+     */
+    private Date created;
+
+    /**
+     * 最后修改时间
+     */
+    //@NotNull(message = "最后修改时间不能为空", groups = { AddGroup.class, EditGroup.class })
+    private Date modify;
+
+
+}

+ 5 - 1
ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/domain/bo/PcProductBo.java

@@ -19,6 +19,10 @@ public class PcProductBo {
     * */
     private String productNo;
     /**
+    * 商品名称
+    * */
+    private String itemName;
+    /**
     * 客户id
     * */
     private Long customerId;
@@ -33,7 +37,7 @@ public class PcProductBo {
     /**
     * 中级分类id
     * */
-    private Long middleCategoryId;
+    private Long mediumCategoryId;
     /**
     * 底层分类id
     * */

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

@@ -131,5 +131,10 @@ public class ProcurementProgramBo extends BaseEntity {
     //@NotBlank(message = "备注不能为空", groups = { AddGroup.class, EditGroup.class })
     private String remark;
 
+    /**
+     * 类型 1采购方案 2专属采购方案 3收藏的采购方案
+     */
+    private String type;
+
 
 }

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

@@ -0,0 +1,53 @@
+package org.dromara.product.domain.bo;
+
+import org.dromara.product.domain.ProcurementProgramCollect;
+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_collect
+ *
+ * @author LionLi
+ * @date 2026-03-03
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+@AutoMapper(target = ProcurementProgramCollect.class, reverseConvertGenerate = false)
+public class ProcurementProgramCollectBo extends BaseEntity {
+
+    /**
+     * 
+     */
+    private Long id;
+
+    /**
+     * 方案id
+     */
+    //@NotNull(message = "方案id不能为空", groups = { AddGroup.class, EditGroup.class })
+    private Long programId;
+
+    /**
+     * 用户id
+     */
+    //@NotNull(message = "用户id不能为空", groups = { AddGroup.class, EditGroup.class })
+    private Long userId;
+
+    /**
+     * 客户id
+     */
+    //@NotNull(message = "客户id不能为空", groups = { AddGroup.class, EditGroup.class })
+    private Long customerId;
+
+    /**
+     * 备注
+     */
+    //@NotBlank(message = "备注不能为空", groups = { AddGroup.class, EditGroup.class })
+    private String remark;
+
+
+}

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

@@ -1,5 +1,6 @@
 package org.dromara.product.domain.bo;
 
+import cn.idev.excel.annotation.ExcelProperty;
 import org.dromara.product.domain.ProductBase;
 import org.dromara.common.mybatis.core.domain.BaseEntity;
 import org.dromara.common.core.validate.AddGroup;
@@ -342,4 +343,10 @@ public class ProductBaseBo extends BaseEntity {
     * */
     private String shelfComments;
 
+    /**
+     * 商品多图
+     * */
+    private String imageUrl;
+
+
 }

+ 5 - 0
ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/domain/bo/ProductBrandBo.java

@@ -29,6 +29,11 @@ public class ProductBrandBo extends BaseEntity {
      */
     private Long id;
 
+    /**
+     * 平台编号
+     */
+    private String ids;
+
     /**
      * 品牌编号(唯一标识)
      */

+ 10 - 0
ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/domain/bo/ProductDecorationFloorLinkBo.java

@@ -36,6 +36,16 @@ public class ProductDecorationFloorLinkBo extends BaseEntity {
 //    @NotBlank(message = "商品编号不能为空", groups = { AddGroup.class, EditGroup.class })
     private String productNo;
 
+    /**
+     * 楼层Id
+     */
+    private Long floorId;
+
+    /**
+     * 商品ID
+     */
+    private Long productId;
+
     /**
      * 商品折扣
      */

+ 2 - 0
ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/domain/bo/ProductIndustrialFloorLinkBo.java

@@ -47,6 +47,8 @@ public class ProductIndustrialFloorLinkBo extends BaseEntity {
 //    @NotBlank(message = "商品编号不能为空", groups = { AddGroup.class, EditGroup.class })
     private String productNo;
 
+    private Long brandId;
+
     /**
      * 品牌编号
      */

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

@@ -11,6 +11,8 @@ import jakarta.validation.constraints.*;
 import org.dromara.common.translation.annotation.Translation;
 import org.dromara.common.translation.constant.TransConstant;
 
+import java.util.List;
+
 /**
  * 产品解决方案/项目方案业务对象 product_program
  *
@@ -91,5 +93,10 @@ public class ProductProgramBo extends BaseEntity {
     //@NotBlank(message = "备注不能为空", groups = { AddGroup.class, EditGroup.class })
     private String remark;
 
+    /**
+    * 多个产品id
+    * */
+    private List<Long> productIds;
+
 
 }

+ 117 - 0
ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/domain/vo/ClientSiteProductVo.java

@@ -0,0 +1,117 @@
+package org.dromara.product.domain.vo;
+
+import org.dromara.product.domain.ClientSiteProduct;
+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;
+
+
+
+/**
+ * 客户站点产品配置视图对象 client_site_product
+ *
+ * @author LionLi
+ * @date 2026-03-04
+ */
+@Data
+@ExcelIgnoreUnannotated
+@AutoMapper(target = ClientSiteProduct.class)
+public class ClientSiteProductVo implements Serializable {
+
+    @Serial
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 主键ID,自增
+     */
+    @ExcelProperty(value = "主键ID,自增")
+    private Long id;
+
+    /**
+     * 客户编号
+     */
+    @ExcelProperty(value = "客户编号")
+    private String clientNo;
+
+    /**
+     * 客户id
+     */
+    @ExcelProperty(value = "客户id")
+    private Long clientId;
+
+    /**
+     * 产品编号
+     */
+    @ExcelProperty(value = "产品编号")
+    private String productNo;
+
+    /**
+     * 产品id
+     */
+    @ExcelProperty(value = "产品id")
+    private Long productId;
+
+    /**
+     * 是否在中心展示(例如:1-是,0-否)
+     */
+    @ExcelProperty(value = "是否在中心展示", converter = ExcelDictConvert.class)
+    @ExcelDictFormat(readConverterExp = "例=如:1-是,0-否")
+    private Long centerView;
+
+    /**
+     * 展示方案1可见性(1-可见,0-不可见)
+     */
+    @ExcelProperty(value = "展示方案1可见性", converter = ExcelDictConvert.class)
+    @ExcelDictFormat(readConverterExp = "1=-可见,0-不可见")
+    private Long zsfa1View;
+
+    /**
+     * 展示方案2可见性(1-可见,0-不可见)
+     */
+    @ExcelProperty(value = "展示方案2可见性", converter = ExcelDictConvert.class)
+    @ExcelDictFormat(readConverterExp = "1=-可见,0-不可见")
+    private Long zsfa2View;
+
+    /**
+     * 展示方案3可见性(1-可见,0-不可见)
+     */
+    @ExcelProperty(value = "展示方案3可见性", converter = ExcelDictConvert.class)
+    @ExcelDictFormat(readConverterExp = "1=-可见,0-不可见")
+    private Long zsfa3View;
+
+    /**
+     * 展示方案4可见性(1-可见,0-不可见)
+     */
+    @ExcelProperty(value = "展示方案4可见性", converter = ExcelDictConvert.class)
+    @ExcelDictFormat(readConverterExp = "1=-可见,0-不可见")
+    private Long zsfa4View;
+
+    /**
+     * 协议价格(字符串形式,可能含格式或货币符号)
+     */
+    @ExcelProperty(value = "协议价格", converter = ExcelDictConvert.class)
+    @ExcelDictFormat(readConverterExp = "字=符串形式,可能含格式或货币符号")
+    private String agreementprice;
+
+    /**
+     * 状态(0正常 1停用)
+     */
+    @ExcelProperty(value = "状态", converter = ExcelDictConvert.class)
+    @ExcelDictFormat(readConverterExp = "0=正常,1=停用")
+    private String status;
+
+    /**
+     * 备注
+     */
+    @ExcelProperty(value = "备注")
+    private String remark;
+
+
+}

+ 163 - 0
ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/domain/vo/ClientSiteSettingVo.java

@@ -0,0 +1,163 @@
+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.ClientSiteSetting;
+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;
+
+
+
+/**
+ * 客户站点设置视图对象 client_site_setting
+ *
+ * @author LionLi
+ * @date 2026-03-04
+ */
+@Data
+@ExcelIgnoreUnannotated
+@AutoMapper(target = ClientSiteSetting.class)
+public class ClientSiteSettingVo implements Serializable {
+
+    @Serial
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 主键ID,自增
+     */
+    @ExcelProperty(value = "主键ID,自增")
+    private Long id;
+
+    /**
+     * 客户编号
+     */
+    @ExcelProperty(value = "客户编号")
+    private String clientNo;
+
+    /**
+     * 客户编号
+     */
+    @ExcelProperty(value = "客户编号")
+    private Long clientId;
+
+    /**
+     * 设置类型
+     */
+    @ExcelProperty(value = "设置类型")
+    private String settingType;
+
+    /**
+     * 广告类型
+     */
+    @ExcelProperty(value = "广告类型")
+    private String advertisType;
+
+    /**
+     * 商品id
+     */
+    @ExcelProperty(value = "商品id")
+    private Long productId;
+
+    /**
+     * 产品编号
+     */
+    @ExcelProperty(value = "产品编号")
+    private String productNo;
+
+    /**
+     * 产品名称
+     */
+    @ExcelProperty(value = "产品名称")
+    private String productName;
+
+    /**
+     * 导航名称
+     */
+    @ExcelProperty(value = "导航名称")
+    private String navigationName;
+
+    /**
+     * URL链接
+     */
+    @ExcelProperty(value = "URL链接")
+    private String url;
+
+    /**
+     * 排序值
+     */
+    @ExcelProperty(value = "排序值")
+    private Long sort;
+
+    /**
+     * 是否启用(例如:1-是,0-否)
+     */
+    @ExcelProperty(value = "是否启用", converter = ExcelDictConvert.class)
+    @ExcelDictFormat(readConverterExp = "例=如:1-是,0-否")
+    private Long isEnable;
+
+    /**
+     * 备注
+     */
+    @ExcelProperty(value = "备注")
+    private String remark;
+
+    /**
+     * 广告图片(存储图片路径或Base64编码字符串)
+     */
+    @ExcelProperty(value = "广告图片", converter = ExcelDictConvert.class)
+    @ExcelDictFormat(readConverterExp = "存=储图片路径或Base64编码字符串")
+    private String advertiseImage;
+
+    /**
+     * 广告图片(存储图片路径或Base64编码字符串)Url
+     */
+    @Translation(type = TransConstant.OSS_ID_TO_URL, mapper = "advertiseImage")
+    private String advertiseImageUrl;
+    /**
+     * 开始时间
+     */
+    @ExcelProperty(value = "开始时间")
+    private Date startTime;
+
+    /**
+     * 结束时间
+     */
+    @ExcelProperty(value = "结束时间")
+    private Date endTime;
+
+    /**
+     * 公告编号
+     */
+    @ExcelProperty(value = "公告编号")
+    private String announcementNo;
+
+    /**
+     * 公告内容
+     */
+    @ExcelProperty(value = "公告内容")
+    private String announcementContent;
+
+    /**
+     * 创建时间
+     */
+    @ExcelProperty(value = "创建时间")
+    private Date created;
+
+    /**
+     * 最后修改时间
+     */
+    @ExcelProperty(value = "最后修改时间")
+    private Date modify;
+
+
+}

+ 161 - 0
ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/domain/vo/ClientSiteVo.java

@@ -0,0 +1,161 @@
+package org.dromara.product.domain.vo;
+
+import java.util.Date;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import org.dromara.product.domain.ClientSite;
+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;
+
+
+
+/**
+ * 客户站点配置视图对象 client_site
+ *
+ * @author LionLi
+ * @date 2026-03-04
+ */
+@Data
+@ExcelIgnoreUnannotated
+@AutoMapper(target = ClientSite.class)
+public class ClientSiteVo implements Serializable {
+
+    @Serial
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 主键ID,自增
+     */
+    @ExcelProperty(value = "主键ID,自增")
+    private Long id;
+
+    /**
+     * 站点名称
+     */
+    @ExcelProperty(value = "站点名称")
+    private String siteName;
+
+    /**
+     * 站点域名
+     */
+    @ExcelProperty(value = "站点域名")
+    private String siteDomain;
+
+    /**
+     * 客户id
+     */
+    @ExcelProperty(value = "客户id")
+    private Long clientId;
+
+    /**
+     * 客户编号
+     */
+    @ExcelProperty(value = "客户编号")
+    private String clientNo;
+
+    /**
+     * 客户名称
+     */
+    @ExcelProperty(value = "客户名称")
+    private String clientName;
+
+    /**
+     * 站点Logo路径或URL
+     */
+    @ExcelProperty(value = "站点Logo路径或URL")
+    private String siteLogo;
+
+    /**
+     * 登录页背景图路径或URL
+     */
+    @ExcelProperty(value = "登录页背景图路径或URL")
+    private String loginImg;
+
+    /**
+     * 是否显示(例如:1-显示,0-隐藏)
+     */
+    @ExcelProperty(value = "是否显示", converter = ExcelDictConvert.class)
+    @ExcelDictFormat(readConverterExp = "例=如:1-显示,0-隐藏")
+    private Long isShow;
+
+    /**
+     * 站点启用开始时间
+     */
+    @ExcelProperty(value = "站点启用开始时间")
+    private Date startTime;
+
+    /**
+     * 站点启用结束时间
+     */
+    @ExcelProperty(value = "站点启用结束时间")
+    private Date endTime;
+
+    /**
+     * 站点标题(HTML title)
+     */
+    @ExcelProperty(value = "站点标题", converter = ExcelDictConvert.class)
+    @ExcelDictFormat(readConverterExp = "H=TML,t=itle")
+    private String siteTitle;
+
+    /**
+     * 站点描述(SEO description)
+     */
+    @ExcelProperty(value = "站点描述", converter = ExcelDictConvert.class)
+    @ExcelDictFormat(readConverterExp = "S=EO,d=escription")
+    private String siteDescribe;
+
+    /**
+     * 站点关键词(SEO keywords)
+     */
+    @ExcelProperty(value = "站点关键词", converter = ExcelDictConvert.class)
+    @ExcelDictFormat(readConverterExp = "S=EO,k=eywords")
+    private String siteKeywords;
+
+    /**
+     * 背景颜色(如 #FFFFFF 或 CSS 颜色值)
+     */
+    @ExcelProperty(value = "背景颜色", converter = ExcelDictConvert.class)
+    @ExcelDictFormat(readConverterExp = "如=,#=FFFFFF,或=,C=SS,颜=色值")
+    private String backgroundColor;
+
+    /**
+     * 是否为主站(例如:1-是,0-否)
+     */
+    @ExcelProperty(value = "是否为主站", converter = ExcelDictConvert.class)
+    @ExcelDictFormat(readConverterExp = "例=如:1-是,0-否")
+    private Long isMainsite;
+
+    /**
+     * 副标题
+     */
+    @ExcelProperty(value = "副标题")
+    private String subTitle;
+
+    /**
+     * 备注
+     */
+    @ExcelProperty(value = "备注")
+    private String remark;
+
+    /**
+     * 协议文件路径
+     */
+    @ExcelProperty(value = "协议文件路径")
+    private String protocolfile;
+
+    /**
+     * 状态(0正常 1停用)
+     */
+    @ExcelProperty(value = "状态", converter = ExcelDictConvert.class)
+    @ExcelDictFormat(readConverterExp = "0=正常,1=停用")
+    private String status;
+
+
+}

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

@@ -79,4 +79,9 @@ public class PcProductVo {
     * */
     private Long shoppingCartId;
 
+    /**
+    * 创建时间
+    * */
+    private String createTime;
+
 }

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

@@ -0,0 +1,62 @@
+package org.dromara.product.domain.vo;
+
+import org.dromara.product.domain.ProcurementProgramCollect;
+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_collect
+ *
+ * @author LionLi
+ * @date 2026-03-03
+ */
+@Data
+@ExcelIgnoreUnannotated
+@AutoMapper(target = ProcurementProgramCollect.class)
+public class ProcurementProgramCollectVo implements Serializable {
+
+    @Serial
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 
+     */
+    @ExcelProperty(value = "")
+    private Long id;
+
+    /**
+     * 方案id
+     */
+    @ExcelProperty(value = "方案id")
+    private Long programId;
+
+    /**
+     * 用户id
+     */
+    @ExcelProperty(value = "用户id")
+    private Long userId;
+
+    /**
+     * 客户id
+     */
+    @ExcelProperty(value = "客户id")
+    private Long customerId;
+
+    /**
+     * 备注
+     */
+    @ExcelProperty(value = "备注")
+    private String remark;
+
+
+}

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

@@ -376,6 +376,12 @@ public class ProductBaseVo implements Serializable {
     @ExcelProperty(value = "采购人员")
     private String purchasingPersonnel;
 
+    /**
+    * 商品多图
+    * */
+    @ExcelProperty(value = "商品多图")
+    private String imageUrl;
+
     /**
      * 商品详情 - 电脑端
      */

+ 7 - 1
ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/domain/vo/ProductBrowsingHistoryVo.java

@@ -29,7 +29,7 @@ public class ProductBrowsingHistoryVo implements Serializable {
     private static final long serialVersionUID = 1L;
 
     /**
-     * 
+     *
      */
     @ExcelProperty(value = "")
     private Long id;
@@ -58,5 +58,11 @@ public class ProductBrowsingHistoryVo implements Serializable {
     @ExcelProperty(value = "备注")
     private String remark;
 
+    /**
+    * 创建时间
+    * */
+    @ExcelProperty(value = "创建时间")
+    private Date createTime;
+
 
 }

+ 10 - 1
ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/domain/vo/ProductDecorationFloorLinkVo.java

@@ -43,9 +43,18 @@ public class ProductDecorationFloorLinkVo implements Serializable {
     /**
      * 商品编号
      */
-    @ExcelProperty(value = "商品编号")
     private String productNo;
 
+    /**
+     * 楼层Id
+     */
+    private Long floorId;
+
+    /**
+     * 商品ID
+     */
+    private Long productId;
+
     /**
      * 商品折扣
      */

+ 3 - 0
ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/domain/vo/ProductIndustrialFloorLinkVo.java

@@ -80,6 +80,9 @@ public class ProductIndustrialFloorLinkVo implements Serializable {
     @ExcelProperty(value = "品牌编号")
     private String brandNo;
 
+
+    private Long brandId;
+
     /**
      * 排序
      */

+ 5 - 2
ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/domain/vo/ProductProgramVo.java

@@ -13,7 +13,7 @@ import lombok.Data;
 import java.io.Serial;
 import java.io.Serializable;
 import java.util.Date;
-
+import java.util.List;
 
 
 /**
@@ -118,5 +118,8 @@ public class ProductProgramVo implements Serializable {
     @ExcelProperty(value = "备注")
     private String remark;
 
-
+    /**
+     * 多个产品id
+     * */
+    private List<Long> productIds;
 }

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

@@ -59,6 +59,12 @@ public class ServiceCaseVo implements Serializable {
     @ExcelProperty(value = "项目类型")
     private String projectType;
 
+    /**
+    * 项目类型名称
+    * */
+    private String projectTypeName;
+
+
     /**
      * 上传方案
      */
@@ -105,4 +111,10 @@ public class ServiceCaseVo implements Serializable {
     @ExcelProperty(value = "备注")
     private String remark;
 
+    /*
+    * 创建时间
+    * */
+    @ExcelProperty(value = "创建时间")
+    private String createTime;
+
 }

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

@@ -0,0 +1,15 @@
+package org.dromara.product.mapper;
+
+import org.dromara.product.domain.ClientSite;
+import org.dromara.product.domain.vo.ClientSiteVo;
+import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
+
+/**
+ * 客户站点配置Mapper接口
+ *
+ * @author LionLi
+ * @date 2026-03-04
+ */
+public interface ClientSiteMapper extends BaseMapperPlus<ClientSite, ClientSiteVo> {
+
+}

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

@@ -0,0 +1,15 @@
+package org.dromara.product.mapper;
+
+import org.dromara.product.domain.ClientSiteProduct;
+import org.dromara.product.domain.vo.ClientSiteProductVo;
+import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
+
+/**
+ * 客户站点产品配置Mapper接口
+ *
+ * @author LionLi
+ * @date 2026-03-04
+ */
+public interface ClientSiteProductMapper extends BaseMapperPlus<ClientSiteProduct, ClientSiteProductVo> {
+
+}

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

@@ -0,0 +1,15 @@
+package org.dromara.product.mapper;
+
+import org.dromara.product.domain.ClientSiteSetting;
+import org.dromara.product.domain.vo.ClientSiteSettingVo;
+import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
+
+/**
+ * 客户站点设置Mapper接口
+ *
+ * @author LionLi
+ * @date 2026-03-04
+ */
+public interface ClientSiteSettingMapper extends BaseMapperPlus<ClientSiteSetting, ClientSiteSettingVo> {
+
+}

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

@@ -0,0 +1,15 @@
+package org.dromara.product.mapper;
+
+import org.dromara.product.domain.ProcurementProgramCollect;
+import org.dromara.product.domain.vo.ProcurementProgramCollectVo;
+import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
+
+/**
+ * 客户收藏方案列Mapper接口
+ *
+ * @author LionLi
+ * @date 2026-03-03
+ */
+public interface ProcurementProgramCollectMapper extends BaseMapperPlus<ProcurementProgramCollect, ProcurementProgramCollectVo> {
+
+}

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

@@ -0,0 +1,70 @@
+package org.dromara.product.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import org.dromara.product.domain.ClientSiteProduct;
+import org.dromara.product.domain.vo.ClientSiteProductVo;
+import org.dromara.product.domain.bo.ClientSiteProductBo;
+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-03-04
+ */
+public interface IClientSiteProductService extends IService<ClientSiteProduct>{
+
+    /**
+     * 查询客户站点产品配置
+     *
+     * @param id 主键
+     * @return 客户站点产品配置
+     */
+    ClientSiteProductVo queryById(Long id);
+
+    /**
+     * 分页查询客户站点产品配置列表
+     *
+     * @param bo        查询条件
+     * @param pageQuery 分页参数
+     * @return 客户站点产品配置分页列表
+     */
+    TableDataInfo<ClientSiteProductVo> queryPageList(ClientSiteProductBo bo, PageQuery pageQuery);
+
+    /**
+     * 查询符合条件的客户站点产品配置列表
+     *
+     * @param bo 查询条件
+     * @return 客户站点产品配置列表
+     */
+    List<ClientSiteProductVo> queryList(ClientSiteProductBo bo);
+
+    /**
+     * 新增客户站点产品配置
+     *
+     * @param bo 客户站点产品配置
+     * @return 是否新增成功
+     */
+    Boolean insertByBo(ClientSiteProductBo bo);
+
+    /**
+     * 修改客户站点产品配置
+     *
+     * @param bo 客户站点产品配置
+     * @return 是否修改成功
+     */
+    Boolean updateByBo(ClientSiteProductBo 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/IClientSiteService.java

@@ -0,0 +1,70 @@
+package org.dromara.product.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import org.dromara.product.domain.ClientSite;
+import org.dromara.product.domain.vo.ClientSiteVo;
+import org.dromara.product.domain.bo.ClientSiteBo;
+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-03-04
+ */
+public interface IClientSiteService extends IService<ClientSite>{
+
+    /**
+     * 查询客户站点配置
+     *
+     * @param id 主键
+     * @return 客户站点配置
+     */
+    ClientSiteVo queryById(Long id);
+
+    /**
+     * 分页查询客户站点配置列表
+     *
+     * @param bo        查询条件
+     * @param pageQuery 分页参数
+     * @return 客户站点配置分页列表
+     */
+    TableDataInfo<ClientSiteVo> queryPageList(ClientSiteBo bo, PageQuery pageQuery);
+
+    /**
+     * 查询符合条件的客户站点配置列表
+     *
+     * @param bo 查询条件
+     * @return 客户站点配置列表
+     */
+    List<ClientSiteVo> queryList(ClientSiteBo bo);
+
+    /**
+     * 新增客户站点配置
+     *
+     * @param bo 客户站点配置
+     * @return 是否新增成功
+     */
+    Boolean insertByBo(ClientSiteBo bo);
+
+    /**
+     * 修改客户站点配置
+     *
+     * @param bo 客户站点配置
+     * @return 是否修改成功
+     */
+    Boolean updateByBo(ClientSiteBo 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/IClientSiteSettingService.java

@@ -0,0 +1,70 @@
+package org.dromara.product.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import org.dromara.product.domain.ClientSiteSetting;
+import org.dromara.product.domain.vo.ClientSiteSettingVo;
+import org.dromara.product.domain.bo.ClientSiteSettingBo;
+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-03-04
+ */
+public interface IClientSiteSettingService extends IService<ClientSiteSetting>{
+
+    /**
+     * 查询客户站点设置
+     *
+     * @param id 主键
+     * @return 客户站点设置
+     */
+    ClientSiteSettingVo queryById(Long id);
+
+    /**
+     * 分页查询客户站点设置列表
+     *
+     * @param bo        查询条件
+     * @param pageQuery 分页参数
+     * @return 客户站点设置分页列表
+     */
+    TableDataInfo<ClientSiteSettingVo> queryPageList(ClientSiteSettingBo bo, PageQuery pageQuery);
+
+    /**
+     * 查询符合条件的客户站点设置列表
+     *
+     * @param bo 查询条件
+     * @return 客户站点设置列表
+     */
+    List<ClientSiteSettingVo> queryList(ClientSiteSettingBo bo);
+
+    /**
+     * 新增客户站点设置
+     *
+     * @param bo 客户站点设置
+     * @return 是否新增成功
+     */
+    Boolean insertByBo(ClientSiteSettingBo bo);
+
+    /**
+     * 修改客户站点设置
+     *
+     * @param bo 客户站点设置
+     * @return 是否修改成功
+     */
+    Boolean updateByBo(ClientSiteSettingBo 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/IProcurementProgramCollectService.java

@@ -0,0 +1,70 @@
+package org.dromara.product.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import org.dromara.product.domain.ProcurementProgramCollect;
+import org.dromara.product.domain.vo.ProcurementProgramCollectVo;
+import org.dromara.product.domain.bo.ProcurementProgramCollectBo;
+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-03-03
+ */
+public interface IProcurementProgramCollectService extends IService<ProcurementProgramCollect>{
+
+    /**
+     * 查询客户收藏方案列
+     *
+     * @param id 主键
+     * @return 客户收藏方案列
+     */
+    ProcurementProgramCollectVo queryById(Long id);
+
+    /**
+     * 分页查询客户收藏方案列列表
+     *
+     * @param bo        查询条件
+     * @param pageQuery 分页参数
+     * @return 客户收藏方案列分页列表
+     */
+    TableDataInfo<ProcurementProgramCollectVo> queryPageList(ProcurementProgramCollectBo bo, PageQuery pageQuery);
+
+    /**
+     * 查询符合条件的客户收藏方案列列表
+     *
+     * @param bo 查询条件
+     * @return 客户收藏方案列列表
+     */
+    List<ProcurementProgramCollectVo> queryList(ProcurementProgramCollectBo bo);
+
+    /**
+     * 新增客户收藏方案列
+     *
+     * @param bo 客户收藏方案列
+     * @return 是否新增成功
+     */
+    Boolean insertByBo(ProcurementProgramCollectBo bo);
+
+    /**
+     * 修改客户收藏方案列
+     *
+     * @param bo 客户收藏方案列
+     * @return 是否修改成功
+     */
+    Boolean updateByBo(ProcurementProgramCollectBo bo);
+
+    /**
+     * 校验并批量删除客户收藏方案列信息
+     *
+     * @param ids     待删除的主键集合
+     * @param isValid 是否进行有效性校验
+     * @return 是否删除成功
+     */
+    Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
+}

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

@@ -9,6 +9,7 @@ import org.dromara.common.mybatis.core.page.PageQuery;
 
 import java.util.Collection;
 import java.util.List;
+import java.util.Map;
 
 /**
  * 产品基础信息Service接口
@@ -158,7 +159,7 @@ public interface IProductBaseService extends IService<ProductBase>{
     /**
     * PC端商品浏览记录
     * */
-    TableDataInfo<PcProductVo> getProductBrowsingHistoryPage(Long userId,PageQuery pageQuery);
+    Map<String,List<PcProductVo>> getProductBrowsingHistory(Long userId);
 
     /**
     * PC端商品收藏夹
@@ -175,6 +176,11 @@ public interface IProductBaseService extends IService<ProductBase>{
     * */
     TableDataInfo<PcProductVo> getProductShoppingCartPage(String id,Long userId, PageQuery pageQuery);
 
+    /**
+    * PC端商品购物车数量
+    * */
+    Long getProductShoppingCartCount(Long userId,Integer isShow);
+
     /**
     * PC端轮播图商品列表
     * */

+ 2 - 0
ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/service/IProductShoppingCartService.java

@@ -67,4 +67,6 @@ public interface IProductShoppingCartService extends IService<ProductShoppingCar
      * @return 是否删除成功
      */
     Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
+
+
 }

+ 144 - 0
ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/service/impl/ClientSiteProductServiceImpl.java

@@ -0,0 +1,144 @@
+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.ClientSiteProductBo;
+import org.dromara.product.domain.vo.ClientSiteProductVo;
+import org.dromara.product.domain.ClientSiteProduct;
+import org.dromara.product.mapper.ClientSiteProductMapper;
+import org.dromara.product.service.IClientSiteProductService;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Collection;
+
+/**
+ * 客户站点产品配置Service业务层处理
+ *
+ * @author LionLi
+ * @date 2026-03-04
+ */
+@Slf4j
+@RequiredArgsConstructor
+@Service
+public class ClientSiteProductServiceImpl  extends ServiceImpl<ClientSiteProductMapper, ClientSiteProduct> implements IClientSiteProductService {
+
+    private final ClientSiteProductMapper baseMapper;
+
+    /**
+     * 查询客户站点产品配置
+     *
+     * @param id 主键
+     * @return 客户站点产品配置
+     */
+    @Override
+    public ClientSiteProductVo queryById(Long id){
+        return baseMapper.selectVoById(id);
+    }
+
+    /**
+     * 分页查询客户站点产品配置列表
+     *
+     * @param bo        查询条件
+     * @param pageQuery 分页参数
+     * @return 客户站点产品配置分页列表
+     */
+    @Override
+    public TableDataInfo<ClientSiteProductVo> queryPageList(ClientSiteProductBo bo, PageQuery pageQuery) {
+        LambdaQueryWrapper<ClientSiteProduct> lqw = buildQueryWrapper(bo);
+        Page<ClientSiteProductVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
+        return TableDataInfo.build(result);
+    }
+
+    /**
+     * 查询符合条件的客户站点产品配置列表
+     *
+     * @param bo 查询条件
+     * @return 客户站点产品配置列表
+     */
+    @Override
+    public List<ClientSiteProductVo> queryList(ClientSiteProductBo bo) {
+        LambdaQueryWrapper<ClientSiteProduct> lqw = buildQueryWrapper(bo);
+        return baseMapper.selectVoList(lqw);
+    }
+
+    private LambdaQueryWrapper<ClientSiteProduct> buildQueryWrapper(ClientSiteProductBo bo) {
+        Map<String, Object> params = bo.getParams();
+        LambdaQueryWrapper<ClientSiteProduct> lqw = Wrappers.lambdaQuery();
+        lqw.orderByAsc(ClientSiteProduct::getId);
+        lqw.eq(StringUtils.isNotBlank(bo.getClientNo()), ClientSiteProduct::getClientNo, bo.getClientNo());
+        lqw.eq(bo.getClientId() != null, ClientSiteProduct::getClientId, bo.getClientId());
+        lqw.eq(StringUtils.isNotBlank(bo.getProductNo()), ClientSiteProduct::getProductNo, bo.getProductNo());
+        lqw.eq(bo.getProductId() != null, ClientSiteProduct::getProductId, bo.getProductId());
+        lqw.eq(bo.getCenterView() != null, ClientSiteProduct::getCenterView, bo.getCenterView());
+        lqw.eq(bo.getZsfa1View() != null, ClientSiteProduct::getZsfa1View, bo.getZsfa1View());
+        lqw.eq(bo.getZsfa2View() != null, ClientSiteProduct::getZsfa2View, bo.getZsfa2View());
+        lqw.eq(bo.getZsfa3View() != null, ClientSiteProduct::getZsfa3View, bo.getZsfa3View());
+        lqw.eq(bo.getZsfa4View() != null, ClientSiteProduct::getZsfa4View, bo.getZsfa4View());
+        lqw.eq(StringUtils.isNotBlank(bo.getAgreementprice()), ClientSiteProduct::getAgreementprice, bo.getAgreementprice());
+        lqw.eq(StringUtils.isNotBlank(bo.getStatus()), ClientSiteProduct::getStatus, bo.getStatus());
+        lqw.eq(StringUtils.isNotBlank(bo.getPlatformCode()), ClientSiteProduct::getPlatformCode, bo.getPlatformCode());
+        return lqw;
+    }
+
+    /**
+     * 新增客户站点产品配置
+     *
+     * @param bo 客户站点产品配置
+     * @return 是否新增成功
+     */
+    @Override
+    public Boolean insertByBo(ClientSiteProductBo bo) {
+        ClientSiteProduct add = MapstructUtils.convert(bo, ClientSiteProduct.class);
+        validEntityBeforeSave(add);
+        boolean flag = baseMapper.insert(add) > 0;
+        if (flag) {
+            bo.setId(add.getId());
+        }
+        return flag;
+    }
+
+    /**
+     * 修改客户站点产品配置
+     *
+     * @param bo 客户站点产品配置
+     * @return 是否修改成功
+     */
+    @Override
+    public Boolean updateByBo(ClientSiteProductBo bo) {
+        ClientSiteProduct update = MapstructUtils.convert(bo, ClientSiteProduct.class);
+        validEntityBeforeSave(update);
+        return baseMapper.updateById(update) > 0;
+    }
+
+    /**
+     * 保存前的数据校验
+     */
+    private void validEntityBeforeSave(ClientSiteProduct entity){
+        //TODO 做一些数据校验,如唯一约束
+    }
+
+    /**
+     * 校验并批量删除客户站点产品配置信息
+     *
+     * @param ids     待删除的主键集合
+     * @param isValid 是否进行有效性校验
+     * @return 是否删除成功
+     */
+    @Override
+    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
+        if(isValid){
+            //TODO 做一些业务上的校验,判断是否需要校验
+        }
+        return baseMapper.deleteByIds(ids) > 0;
+    }
+}

+ 151 - 0
ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/service/impl/ClientSiteServiceImpl.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.ClientSiteBo;
+import org.dromara.product.domain.vo.ClientSiteVo;
+import org.dromara.product.domain.ClientSite;
+import org.dromara.product.mapper.ClientSiteMapper;
+import org.dromara.product.service.IClientSiteService;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Collection;
+
+/**
+ * 客户站点配置Service业务层处理
+ *
+ * @author LionLi
+ * @date 2026-03-04
+ */
+@Slf4j
+@RequiredArgsConstructor
+@Service
+public class ClientSiteServiceImpl  extends ServiceImpl<ClientSiteMapper, ClientSite> implements IClientSiteService {
+
+    private final ClientSiteMapper baseMapper;
+
+    /**
+     * 查询客户站点配置
+     *
+     * @param id 主键
+     * @return 客户站点配置
+     */
+    @Override
+    public ClientSiteVo queryById(Long id){
+        return baseMapper.selectVoById(id);
+    }
+
+    /**
+     * 分页查询客户站点配置列表
+     *
+     * @param bo        查询条件
+     * @param pageQuery 分页参数
+     * @return 客户站点配置分页列表
+     */
+    @Override
+    public TableDataInfo<ClientSiteVo> queryPageList(ClientSiteBo bo, PageQuery pageQuery) {
+        LambdaQueryWrapper<ClientSite> lqw = buildQueryWrapper(bo);
+        Page<ClientSiteVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
+        return TableDataInfo.build(result);
+    }
+
+    /**
+     * 查询符合条件的客户站点配置列表
+     *
+     * @param bo 查询条件
+     * @return 客户站点配置列表
+     */
+    @Override
+    public List<ClientSiteVo> queryList(ClientSiteBo bo) {
+        LambdaQueryWrapper<ClientSite> lqw = buildQueryWrapper(bo);
+        return baseMapper.selectVoList(lqw);
+    }
+
+    private LambdaQueryWrapper<ClientSite> buildQueryWrapper(ClientSiteBo bo) {
+        Map<String, Object> params = bo.getParams();
+        LambdaQueryWrapper<ClientSite> lqw = Wrappers.lambdaQuery();
+        lqw.orderByAsc(ClientSite::getId);
+        lqw.like(StringUtils.isNotBlank(bo.getSiteName()), ClientSite::getSiteName, bo.getSiteName());
+        lqw.eq(StringUtils.isNotBlank(bo.getSiteDomain()), ClientSite::getSiteDomain, bo.getSiteDomain());
+        lqw.eq(bo.getClientId() != null, ClientSite::getClientId, bo.getClientId());
+        lqw.eq(StringUtils.isNotBlank(bo.getClientNo()), ClientSite::getClientNo, bo.getClientNo());
+        lqw.like(StringUtils.isNotBlank(bo.getClientName()), ClientSite::getClientName, bo.getClientName());
+        lqw.eq(StringUtils.isNotBlank(bo.getSiteLogo()), ClientSite::getSiteLogo, bo.getSiteLogo());
+        lqw.eq(StringUtils.isNotBlank(bo.getLoginImg()), ClientSite::getLoginImg, bo.getLoginImg());
+        lqw.eq(bo.getIsShow() != null, ClientSite::getIsShow, bo.getIsShow());
+        lqw.eq(bo.getStartTime() != null, ClientSite::getStartTime, bo.getStartTime());
+        lqw.eq(bo.getEndTime() != null, ClientSite::getEndTime, bo.getEndTime());
+        lqw.eq(StringUtils.isNotBlank(bo.getSiteTitle()), ClientSite::getSiteTitle, bo.getSiteTitle());
+        lqw.eq(StringUtils.isNotBlank(bo.getSiteDescribe()), ClientSite::getSiteDescribe, bo.getSiteDescribe());
+        lqw.eq(StringUtils.isNotBlank(bo.getSiteKeywords()), ClientSite::getSiteKeywords, bo.getSiteKeywords());
+        lqw.eq(StringUtils.isNotBlank(bo.getBackgroundColor()), ClientSite::getBackgroundColor, bo.getBackgroundColor());
+        lqw.eq(bo.getIsMainsite() != null, ClientSite::getIsMainsite, bo.getIsMainsite());
+        lqw.eq(StringUtils.isNotBlank(bo.getSubTitle()), ClientSite::getSubTitle, bo.getSubTitle());
+        lqw.eq(StringUtils.isNotBlank(bo.getProtocolfile()), ClientSite::getProtocolfile, bo.getProtocolfile());
+        lqw.eq(StringUtils.isNotBlank(bo.getStatus()), ClientSite::getStatus, bo.getStatus());
+        lqw.eq(StringUtils.isNotBlank(bo.getPlatformCode()), ClientSite::getPlatformCode, bo.getPlatformCode());
+        return lqw;
+    }
+
+    /**
+     * 新增客户站点配置
+     *
+     * @param bo 客户站点配置
+     * @return 是否新增成功
+     */
+    @Override
+    public Boolean insertByBo(ClientSiteBo bo) {
+        ClientSite add = MapstructUtils.convert(bo, ClientSite.class);
+        validEntityBeforeSave(add);
+        boolean flag = baseMapper.insert(add) > 0;
+        if (flag) {
+            bo.setId(add.getId());
+        }
+        return flag;
+    }
+
+    /**
+     * 修改客户站点配置
+     *
+     * @param bo 客户站点配置
+     * @return 是否修改成功
+     */
+    @Override
+    public Boolean updateByBo(ClientSiteBo bo) {
+        ClientSite update = MapstructUtils.convert(bo, ClientSite.class);
+        validEntityBeforeSave(update);
+        return baseMapper.updateById(update) > 0;
+    }
+
+    /**
+     * 保存前的数据校验
+     */
+    private void validEntityBeforeSave(ClientSite entity){
+        //TODO 做一些数据校验,如唯一约束
+    }
+
+    /**
+     * 校验并批量删除客户站点配置信息
+     *
+     * @param ids     待删除的主键集合
+     * @param isValid 是否进行有效性校验
+     * @return 是否删除成功
+     */
+    @Override
+    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
+        if(isValid){
+            //TODO 做一些业务上的校验,判断是否需要校验
+        }
+        return baseMapper.deleteByIds(ids) > 0;
+    }
+}

+ 150 - 0
ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/service/impl/ClientSiteSettingServiceImpl.java

@@ -0,0 +1,150 @@
+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.ClientSiteSettingBo;
+import org.dromara.product.domain.vo.ClientSiteSettingVo;
+import org.dromara.product.domain.ClientSiteSetting;
+import org.dromara.product.mapper.ClientSiteSettingMapper;
+import org.dromara.product.service.IClientSiteSettingService;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Collection;
+
+/**
+ * 客户站点设置Service业务层处理
+ *
+ * @author LionLi
+ * @date 2026-03-04
+ */
+@Slf4j
+@RequiredArgsConstructor
+@Service
+public class ClientSiteSettingServiceImpl  extends ServiceImpl<ClientSiteSettingMapper, ClientSiteSetting> implements IClientSiteSettingService {
+
+    private final ClientSiteSettingMapper baseMapper;
+
+    /**
+     * 查询客户站点设置
+     *
+     * @param id 主键
+     * @return 客户站点设置
+     */
+    @Override
+    public ClientSiteSettingVo queryById(Long id){
+        return baseMapper.selectVoById(id);
+    }
+
+    /**
+     * 分页查询客户站点设置列表
+     *
+     * @param bo        查询条件
+     * @param pageQuery 分页参数
+     * @return 客户站点设置分页列表
+     */
+    @Override
+    public TableDataInfo<ClientSiteSettingVo> queryPageList(ClientSiteSettingBo bo, PageQuery pageQuery) {
+        LambdaQueryWrapper<ClientSiteSetting> lqw = buildQueryWrapper(bo);
+        Page<ClientSiteSettingVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
+        return TableDataInfo.build(result);
+    }
+
+    /**
+     * 查询符合条件的客户站点设置列表
+     *
+     * @param bo 查询条件
+     * @return 客户站点设置列表
+     */
+    @Override
+    public List<ClientSiteSettingVo> queryList(ClientSiteSettingBo bo) {
+        LambdaQueryWrapper<ClientSiteSetting> lqw = buildQueryWrapper(bo);
+        return baseMapper.selectVoList(lqw);
+    }
+
+    private LambdaQueryWrapper<ClientSiteSetting> buildQueryWrapper(ClientSiteSettingBo bo) {
+        Map<String, Object> params = bo.getParams();
+        LambdaQueryWrapper<ClientSiteSetting> lqw = Wrappers.lambdaQuery();
+        lqw.orderByAsc(ClientSiteSetting::getId);
+        lqw.eq(StringUtils.isNotBlank(bo.getClientNo()), ClientSiteSetting::getClientNo, bo.getClientNo());
+        lqw.eq(bo.getClientId() != null, ClientSiteSetting::getClientId, bo.getClientId());
+        lqw.eq(StringUtils.isNotBlank(bo.getSettingType()), ClientSiteSetting::getSettingType, bo.getSettingType());
+        lqw.eq(StringUtils.isNotBlank(bo.getAdvertisType()), ClientSiteSetting::getAdvertisType, bo.getAdvertisType());
+        lqw.eq(bo.getProductId() != null, ClientSiteSetting::getProductId, bo.getProductId());
+        lqw.eq(StringUtils.isNotBlank(bo.getProductNo()), ClientSiteSetting::getProductNo, bo.getProductNo());
+        lqw.like(StringUtils.isNotBlank(bo.getProductName()), ClientSiteSetting::getProductName, bo.getProductName());
+        lqw.like(StringUtils.isNotBlank(bo.getNavigationName()), ClientSiteSetting::getNavigationName, bo.getNavigationName());
+        lqw.eq(StringUtils.isNotBlank(bo.getUrl()), ClientSiteSetting::getUrl, bo.getUrl());
+        lqw.eq(bo.getSort() != null, ClientSiteSetting::getSort, bo.getSort());
+        lqw.eq(bo.getIsEnable() != null, ClientSiteSetting::getIsEnable, bo.getIsEnable());
+        lqw.eq(StringUtils.isNotBlank(bo.getAdvertiseImage()), ClientSiteSetting::getAdvertiseImage, bo.getAdvertiseImage());
+        lqw.eq(bo.getStartTime() != null, ClientSiteSetting::getStartTime, bo.getStartTime());
+        lqw.eq(bo.getEndTime() != null, ClientSiteSetting::getEndTime, bo.getEndTime());
+        lqw.eq(StringUtils.isNotBlank(bo.getAnnouncementNo()), ClientSiteSetting::getAnnouncementNo, bo.getAnnouncementNo());
+        lqw.eq(StringUtils.isNotBlank(bo.getAnnouncementContent()), ClientSiteSetting::getAnnouncementContent, bo.getAnnouncementContent());
+        lqw.eq(bo.getCreated() != null, ClientSiteSetting::getCreated, bo.getCreated());
+        lqw.eq(bo.getModify() != null, ClientSiteSetting::getModify, bo.getModify());
+        return lqw;
+    }
+
+    /**
+     * 新增客户站点设置
+     *
+     * @param bo 客户站点设置
+     * @return 是否新增成功
+     */
+    @Override
+    public Boolean insertByBo(ClientSiteSettingBo bo) {
+        ClientSiteSetting add = MapstructUtils.convert(bo, ClientSiteSetting.class);
+        validEntityBeforeSave(add);
+        boolean flag = baseMapper.insert(add) > 0;
+        if (flag) {
+            bo.setId(add.getId());
+        }
+        return flag;
+    }
+
+    /**
+     * 修改客户站点设置
+     *
+     * @param bo 客户站点设置
+     * @return 是否修改成功
+     */
+    @Override
+    public Boolean updateByBo(ClientSiteSettingBo bo) {
+        ClientSiteSetting update = MapstructUtils.convert(bo, ClientSiteSetting.class);
+        validEntityBeforeSave(update);
+        return baseMapper.updateById(update) > 0;
+    }
+
+    /**
+     * 保存前的数据校验
+     */
+    private void validEntityBeforeSave(ClientSiteSetting entity){
+        //TODO 做一些数据校验,如唯一约束
+    }
+
+    /**
+     * 校验并批量删除客户站点设置信息
+     *
+     * @param ids     待删除的主键集合
+     * @param isValid 是否进行有效性校验
+     * @return 是否删除成功
+     */
+    @Override
+    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
+        if(isValid){
+            //TODO 做一些业务上的校验,判断是否需要校验
+        }
+        return baseMapper.deleteByIds(ids) > 0;
+    }
+}

+ 136 - 0
ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/service/impl/ProcurementProgramCollectServiceImpl.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.ProcurementProgramCollectBo;
+import org.dromara.product.domain.vo.ProcurementProgramCollectVo;
+import org.dromara.product.domain.ProcurementProgramCollect;
+import org.dromara.product.mapper.ProcurementProgramCollectMapper;
+import org.dromara.product.service.IProcurementProgramCollectService;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Collection;
+
+/**
+ * 客户收藏方案列Service业务层处理
+ *
+ * @author LionLi
+ * @date 2026-03-03
+ */
+@Slf4j
+@RequiredArgsConstructor
+@Service
+public class ProcurementProgramCollectServiceImpl  extends ServiceImpl<ProcurementProgramCollectMapper, ProcurementProgramCollect> implements IProcurementProgramCollectService {
+
+    private final ProcurementProgramCollectMapper baseMapper;
+
+    /**
+     * 查询客户收藏方案列
+     *
+     * @param id 主键
+     * @return 客户收藏方案列
+     */
+    @Override
+    public ProcurementProgramCollectVo queryById(Long id){
+        return baseMapper.selectVoById(id);
+    }
+
+    /**
+     * 分页查询客户收藏方案列列表
+     *
+     * @param bo        查询条件
+     * @param pageQuery 分页参数
+     * @return 客户收藏方案列分页列表
+     */
+    @Override
+    public TableDataInfo<ProcurementProgramCollectVo> queryPageList(ProcurementProgramCollectBo bo, PageQuery pageQuery) {
+        LambdaQueryWrapper<ProcurementProgramCollect> lqw = buildQueryWrapper(bo);
+        Page<ProcurementProgramCollectVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
+        return TableDataInfo.build(result);
+    }
+
+    /**
+     * 查询符合条件的客户收藏方案列列表
+     *
+     * @param bo 查询条件
+     * @return 客户收藏方案列列表
+     */
+    @Override
+    public List<ProcurementProgramCollectVo> queryList(ProcurementProgramCollectBo bo) {
+        LambdaQueryWrapper<ProcurementProgramCollect> lqw = buildQueryWrapper(bo);
+        return baseMapper.selectVoList(lqw);
+    }
+
+    private LambdaQueryWrapper<ProcurementProgramCollect> buildQueryWrapper(ProcurementProgramCollectBo bo) {
+        Map<String, Object> params = bo.getParams();
+        LambdaQueryWrapper<ProcurementProgramCollect> lqw = Wrappers.lambdaQuery();
+        lqw.orderByAsc(ProcurementProgramCollect::getId);
+        lqw.eq(bo.getProgramId() != null, ProcurementProgramCollect::getProgramId, bo.getProgramId());
+        lqw.eq(bo.getUserId() != null, ProcurementProgramCollect::getUserId, bo.getUserId());
+        lqw.eq(bo.getCustomerId() != null, ProcurementProgramCollect::getCustomerId, bo.getCustomerId());
+        lqw.eq(StringUtils.isNotBlank(bo.getPlatformCode()), ProcurementProgramCollect::getPlatformCode, bo.getPlatformCode());
+        return lqw;
+    }
+
+    /**
+     * 新增客户收藏方案列
+     *
+     * @param bo 客户收藏方案列
+     * @return 是否新增成功
+     */
+    @Override
+    public Boolean insertByBo(ProcurementProgramCollectBo bo) {
+        ProcurementProgramCollect add = MapstructUtils.convert(bo, ProcurementProgramCollect.class);
+        validEntityBeforeSave(add);
+        boolean flag = baseMapper.insert(add) > 0;
+        if (flag) {
+            bo.setId(add.getId());
+        }
+        return flag;
+    }
+
+    /**
+     * 修改客户收藏方案列
+     *
+     * @param bo 客户收藏方案列
+     * @return 是否修改成功
+     */
+    @Override
+    public Boolean updateByBo(ProcurementProgramCollectBo bo) {
+        ProcurementProgramCollect update = MapstructUtils.convert(bo, ProcurementProgramCollect.class);
+        validEntityBeforeSave(update);
+        return baseMapper.updateById(update) > 0;
+    }
+
+    /**
+     * 保存前的数据校验
+     */
+    private void validEntityBeforeSave(ProcurementProgramCollect entity){
+        //TODO 做一些数据校验,如唯一约束
+    }
+
+    /**
+     * 校验并批量删除客户收藏方案列信息
+     *
+     * @param ids     待删除的主键集合
+     * @param isValid 是否进行有效性校验
+     * @return 是否删除成功
+     */
+    @Override
+    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
+        if(isValid){
+            //TODO 做一些业务上的校验,判断是否需要校验
+        }
+        return baseMapper.deleteByIds(ids) > 0;
+    }
+}

+ 135 - 47
ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/service/impl/ProductBaseServiceImpl.java

@@ -2,6 +2,7 @@ package org.dromara.product.service.impl;
 
 import cn.hutool.core.bean.BeanUtil;
 import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.date.DateUtil;
 import cn.hutool.core.util.ObjectUtil;
 import co.elastic.clients.elasticsearch._types.FieldValue;
 import co.elastic.clients.elasticsearch._types.aggregations.Aggregate;
@@ -113,6 +114,8 @@ public class ProductBaseServiceImpl extends ServiceImpl<ProductBaseMapper, Produ
     private final ProductRecommendLinkMapper productRecommendLinkMapper;
     //平台装修楼层商品
     private final ProductDecorationFloorLinkMapper decorationFloorLinkMapper;
+    //工业装修楼层
+    private final ProductIndustrialFloorLinkMapper industrialFloorLinkMapper;
     //协议商品
     private final ProtocolProductsMapper protocolProductsMapper;
 
@@ -345,6 +348,7 @@ public class ProductBaseServiceImpl extends ServiceImpl<ProductBaseMapper, Produ
         photosWrapper.eq(ProductPhotos::getProductId, id);
         ProductPhotos productPhotos = photosMapper.selectOne(photosWrapper);
         if(ObjectUtil.isNotEmpty(productPhotos)){
+            vo.setImageUrl(productPhotos.getImageUrl());
             vo.setPcDetail(productPhotos.getProductDetailsPc());
             vo.setMobileDetail(productPhotos.getProductDetailsApp());
         }
@@ -449,7 +453,7 @@ public class ProductBaseServiceImpl extends ServiceImpl<ProductBaseMapper, Produ
         log.info("执行数据库降级查询...");
 
         LambdaQueryWrapper<ProductBase> lqw = buildQueryWrapper(bo);
-//        Page<ProductBaseVo> page = baseMapper.selectVoPage(pageQuery.build(), lqw);
+        Page<ProductBaseVo> page = baseMapper.selectVoPage(pageQuery.build(), lqw);
 
 //        log.info("数据库查询完成,总记录数: {}", page.getTotal());
         return TableDataInfo.build();
@@ -467,8 +471,9 @@ public class ProductBaseServiceImpl extends ServiceImpl<ProductBaseMapper, Produ
         return baseMapper.selectVoList(lqw);
     }
     private LambdaEsQueryWrapper<ProductBaseVo> buildEsQueryWrapper(ProductBaseBo bo) {
-        return new LambdaEsQueryWrapper<ProductBaseVo>()
+        LambdaEsQueryWrapper<ProductBaseVo> productBaseVoLambdaEsQueryWrapper = new LambdaEsQueryWrapper<ProductBaseVo>()
             .eq(ObjectUtil.isNotEmpty(bo.getProductNo()), ProductBaseVo::getProductNo, bo.getProductNo())
+
             .like(ObjectUtil.isNotEmpty(bo.getItemName()), ProductBaseVo::getItemName, bo.getItemName())
             .eq(bo.getBrandId() != null, ProductBaseVo::getBrandId, bo.getBrandId())
             .eq(bo.getTopCategoryId() != null, ProductBaseVo::getTopCategoryId, bo.getTopCategoryId())
@@ -479,8 +484,13 @@ 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)
-            ;
+            .orderByDesc(ProductBaseVo::getId);
+        if (ObjectUtil.isNotEmpty(bo.getIds())){
+            productBaseVoLambdaEsQueryWrapper.in(ProductBaseVo::getId, bo.getIds().split(","));
+        }
+
+
+        return productBaseVoLambdaEsQueryWrapper;
     }
 
     /**
@@ -499,8 +509,8 @@ public class ProductBaseServiceImpl extends ServiceImpl<ProductBaseMapper, Produ
         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.getMediumCategoryId())) {
+            wrapper.eq(ProductBaseVo::getMediumCategoryId, bo.getMediumCategoryId());
         }
         if (ObjectUtil.isNotEmpty(bo.getBottomCategoryId())) {
             wrapper.eq(ProductBaseVo::getBottomCategoryId, bo.getBottomCategoryId());
@@ -701,7 +711,7 @@ public class ProductBaseServiceImpl extends ServiceImpl<ProductBaseMapper, Produ
 
             // 1. 更新产品基础信息
             ProductBase productBase = MapstructUtils.convert(bo, ProductBase.class);
-            validEntityBeforeSave(productBase);
+//            validEntityBeforeSave(productBase);
 
             boolean flag = baseMapper.updateById(productBase) > 0;
             if (!flag) {
@@ -1354,7 +1364,8 @@ public class ProductBaseServiceImpl extends ServiceImpl<ProductBaseMapper, Produ
             try {
                 LambdaEsQueryWrapper<ProductBaseVo> esQueryWrapper = new LambdaEsQueryWrapper<ProductBaseVo>()
                     .in(ProductBaseVo::getId, productIds)
-                    .eq(ProductBaseVo::getProductStatus, 1);
+//                    .eq(ProductBaseVo::getProductStatus, 1)
+                    ;
 
                 // 检查ES索引是否存在
                 if (!esMapper.existsIndex("productbasevo")) {
@@ -1398,7 +1409,8 @@ public class ProductBaseServiceImpl extends ServiceImpl<ProductBaseMapper, Produ
             try {
                 LambdaEsQueryWrapper<ProductBaseVo> esQueryWrapper = new LambdaEsQueryWrapper<ProductBaseVo>()
                     .in(ProductBaseVo::getProductNo, productNos)
-                    .eq(ProductBaseVo::getProductStatus, 1);
+//                    .eq(ProductBaseVo::getProductStatus, 1)
+                    ;
 
                 // 检查ES索引是否存在
                 if (!esMapper.existsIndex("productbasevo")) {
@@ -1449,7 +1461,7 @@ public class ProductBaseServiceImpl extends ServiceImpl<ProductBaseMapper, Produ
         lqw.like(StringUtils.isNotBlank(bo.getProductNo()), "b.product_no", bo.getProductNo());
         lqw.eq(ObjectUtil.isNotEmpty(bo.getBrandId()), "b.brand_id", bo.getBrandId());
         lqw.eq(ObjectUtil.isNotEmpty(bo.getTopCategoryId()), "b.top_category_id", bo.getTopCategoryId());
-        lqw.eq(ObjectUtil.isNotEmpty(bo.getMiddleCategoryId()), "b.middle_category_id", bo.getMiddleCategoryId());
+        lqw.eq(ObjectUtil.isNotEmpty(bo.getMediumCategoryId()), "b.medium_category_id", bo.getMediumCategoryId());
         lqw.eq(ObjectUtil.isNotEmpty(bo.getBottomCategoryId()), "b.bottom_category_id", bo.getBottomCategoryId());
         lqw.eq(ObjectUtil.isNotEmpty(bo.getIsCustomize()), "e.is_customize", bo.getIsCustomize());
         if(bo.getPriceRange() != null){
@@ -1489,7 +1501,10 @@ public class ProductBaseServiceImpl extends ServiceImpl<ProductBaseMapper, Produ
             if (ObjectUtil.isNotEmpty(bo.getSearchKeyword())) {
                 esQueryWrapper.and(wrapper -> wrapper
                     .like(ProductBaseVo::getItemName, bo.getSearchKeyword())
-                    .or().like(ProductBaseVo::getBrandName, bo.getSearchKeyword())
+                    .or()
+                    .like(ProductBaseVo::getBrandName, bo.getSearchKeyword())
+                    .or()
+                    .like(ProductBaseVo::getProductNo, bo.getProductNo())
                 );
             }
 
@@ -1511,6 +1526,21 @@ public class ProductBaseServiceImpl extends ServiceImpl<ProductBaseMapper, Produ
                 }
             }
 
+            if(bo.getSortField() != null && bo.getSortOrder() != null){
+                String[] sortFields = bo.getSortField().split(",");
+                String[] sortOrders = bo.getSortOrder().split(",");
+                for (int i = 0; i < sortFields.length; i++) {
+                    switch (sortFields[i]) {
+                        case "1":
+                            esQueryWrapper.orderBy( true, sortOrders[i].equals("Asc"),ProductBaseVo::getId);
+                        case "2":
+                            esQueryWrapper.orderBy( true, sortOrders[i].equals("Asc"),ProductBaseVo::getTotalInventory);
+                        case "3":
+                            esQueryWrapper.orderBy( true, sortOrders[i].equals("Asc"),ProductBaseVo::getMarketPrice);
+                    }
+                }
+            }
+
             // 检查ES索引是否存在
             if (!esMapper.existsIndex("productbasevo")) {
                 log.warn("ES索引 [productbasevo] 不存在,降级到数据库查询");
@@ -1539,32 +1569,27 @@ public class ProductBaseServiceImpl extends ServiceImpl<ProductBaseMapper, Produ
      * @param userId
      */
     @Override
-    public TableDataInfo<PcProductVo> getProductBrowsingHistoryPage(Long userId, PageQuery pageQuery) {
+    public Map<String,List<PcProductVo>> getProductBrowsingHistory(Long userId) {
         List<ProductBrowsingHistoryVo> productBrowsingHistoryVos = productBrowsingHistoryMapper.selectVoList(Wrappers.lambdaQuery(ProductBrowsingHistory.class)
             .eq(ProductBrowsingHistory::getUserId, userId)
         );
         if (CollUtil.isNotEmpty(productBrowsingHistoryVos)) {
-            List<Long> productIds = productBrowsingHistoryVos.stream().map(ProductBrowsingHistoryVo::getProductId).toList();
-            //获取商品浏览记录
-            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)) {
+            //将浏览记录通过创建时间的日分组
+            Map<String, List<ProductBrowsingHistoryVo>> collect =
+                productBrowsingHistoryVos.stream()
+                    .collect(Collectors.groupingBy(productBrowsingHistoryVo -> DateUtil.format(productBrowsingHistoryVo.getCreateTime(), "yyyy-MM-dd")));
+            //遍历构建PC端商品浏览记录
+            return collect.entrySet().stream().map(entry -> {
+                List<Long> productIds = entry.getValue().stream().map(ProductBrowsingHistoryVo::getProductId).distinct().toList();
+                QueryWrapper<ProductBase> lqw = Wrappers.query(ProductBase.class);
+                lqw.in("b.id", productIds);
+                List<ProductBaseVo> productBaseVos = baseMapper.selectAllList(lqw);
                 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 Map.entry(entry.getKey(), pcProductVos);
+            }).collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
         }
 
-        return TableDataInfo.build();
+        return Map.of();
     }
 
     /**
@@ -1577,7 +1602,7 @@ public class ProductBaseServiceImpl extends ServiceImpl<ProductBaseMapper, Produ
     public TableDataInfo<PcProductVo> getFavoritesProductPage(Long favoritesId, Long userId, PageQuery pageQuery) {
         //获取收藏夹商品id
         List<ProductCollectVo> productFavoritesLinkVos = productCollectMapper.selectVoList(Wrappers.lambdaQuery(ProductCollect.class)
-            .eq(ProductCollect::getFavoritesId, favoritesId)
+            .eq(ObjectUtil.isNotEmpty(favoritesId),ProductCollect::getFavoritesId, favoritesId)
             .eq(ProductCollect::getUserId, userId)
         );
         if (CollUtil.isNotEmpty(productFavoritesLinkVos)) {
@@ -1585,7 +1610,7 @@ public class ProductBaseServiceImpl extends ServiceImpl<ProductBaseMapper, Produ
             //获取收藏夹商品
             QueryWrapper<ProductBase> lqw = Wrappers.query(ProductBase.class);
             lqw.in("b.id", productIds);
-            lqw.eq("b.product_status", 1);
+//            lqw.eq("b.product_status", 1);
             int limit = pageQuery.getPageSize() + 1;
             lqw.last("limit "+ limit );
             List<ProductBaseVo> productBaseVos = baseMapper.selectAllList(lqw);
@@ -1670,6 +1695,30 @@ public class ProductBaseServiceImpl extends ServiceImpl<ProductBaseMapper, Produ
         return TableDataInfo.build();
     }
 
+    /**
+     * PC端商品购物车数量
+     *
+     * @param userId
+     * @param isShow
+     */
+    @Override
+    public Long getProductShoppingCartCount(Long userId, Integer isShow) {
+        if (ObjectUtil.isNotNull(userId)) {
+            List<ProductShoppingCartVo> productShoppingCartVos = productShoppingCartMapper.selectVoList(Wrappers.lambdaQuery(ProductShoppingCart.class)
+                .eq(ProductShoppingCart::getUserId, userId)
+            );
+            if (CollUtil.isEmpty(productShoppingCartVos)){
+                return 0L;
+            }
+            Long count = baseMapper.selectCount(Wrappers.lambdaQuery(ProductBase.class)
+                .in(ProductBase::getId, productShoppingCartVos.stream().map(ProductShoppingCartVo::getProductId).toList())
+                .eq(ProductBase::getProductStatus, 1)
+            );
+            return count;
+        }
+        return 0L;
+    }
+
     /**
      * PC端轮播图商品列表
      */
@@ -1701,13 +1750,13 @@ public class ProductBaseServiceImpl extends ServiceImpl<ProductBaseMapper, Produ
     public List<PcProductVo> getRecommendedCategoryProductList(Long categoryId) {
         List<ProductCategoryRecommendedLinkVo> productCategoryRecommendedLinkVos = productCategoryRecommendedLinkMapper.selectVoList(
                 Wrappers.lambdaQuery(ProductCategoryRecommendedLink.class)
-                    .eq(ProductCategoryRecommendedLink::getCategoryId, categoryId)
+                    .eq(ObjectUtil.isNotEmpty(categoryId),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);
+//                lqw.eq("b.product_status", 1);
                 List<ProductBaseVo> productBaseVos = baseMapper.selectAllList(lqw);
                 if (CollUtil.isNotEmpty(productBaseVos)) {
                     return BeanUtil.copyToList(productBaseVos, PcProductVo.class);
@@ -1723,15 +1772,15 @@ public class ProductBaseServiceImpl extends ServiceImpl<ProductBaseMapper, Produ
      */
     @Override
     public List<PcProductVo> getIndustrialFloorProductList(Long floorId) {
-        List<ProductDecorationFloorLinkVo> productDecorationFloorLinkVos = decorationFloorLinkMapper.selectVoList(
-                Wrappers.lambdaQuery(ProductDecorationFloorLink.class)
-                    .eq(ProductDecorationFloorLink::getFloorNo, floorId)
+        List<ProductIndustrialFloorLinkVo> productIndustrialFloorLinkVos = industrialFloorLinkMapper.selectVoList(
+                Wrappers.lambdaQuery(ProductIndustrialFloorLink.class)
+                    .eq(ProductIndustrialFloorLink::getFloorId, floorId)
             );
-        if (CollUtil.isNotEmpty(productDecorationFloorLinkVos)) {
-            List<String> productNos = productDecorationFloorLinkVos.stream().map(ProductDecorationFloorLinkVo::getProductNo).toList();
+        if (CollUtil.isNotEmpty(productIndustrialFloorLinkVos)) {
+            List<Long> productIds = productIndustrialFloorLinkVos.stream().map(ProductIndustrialFloorLinkVo::getProductId).toList();
             QueryWrapper<ProductBase> lqw = Wrappers.query(ProductBase.class);
-            lqw.in("b.product_no", productNos);
-            lqw.eq("b.product_status", 1);
+            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);
@@ -1783,7 +1832,8 @@ public class ProductBaseServiceImpl extends ServiceImpl<ProductBaseMapper, Produ
                 try {
                     LambdaEsQueryWrapper<ProductBaseVo> esQueryWrapper = new LambdaEsQueryWrapper<ProductBaseVo>()
                         .in(ProductBaseVo::getId, productIds)
-                        .eq(ProductBaseVo::getProductStatus, 1);
+//                        .eq(ProductBaseVo::getProductStatus, 1)
+                        ;
 
                     // 检查ES索引是否存在
                     if (!esMapper.existsIndex("productbasevo")) {
@@ -1870,10 +1920,48 @@ public class ProductBaseServiceImpl extends ServiceImpl<ProductBaseMapper, Produ
             .le(ObjectUtil.isNotEmpty(bo.getMaxPrice()), ProtocolProducts::getAgreementPrice, bo.getMaxPrice())
         );
         if (CollUtil.isNotEmpty(protocolProductsVos)) {
-            LambdaEsQueryWrapper<ProductBaseVo> wrapper = new LambdaEsQueryWrapper<ProductBaseVo>();
+            LambdaEsQueryWrapper<ProductBaseVo> esQueryWrapper = 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());
+            esQueryWrapper.in(ProductBaseVo::getId, protocolProductsVos.stream().map(ProtocolProductsVo::getProductId).toList());
+            // 添加额外的查询条件
+            esQueryWrapper.like(ObjectUtil.isNotEmpty(bo.getItemName()),ProductBaseVo::getItemName,bo.getItemName());
+            esQueryWrapper.eq(ObjectUtil.isNotEmpty(bo.getProductNo()),ProductBaseVo::getProductNo,bo.getProductNo());
+            esQueryWrapper.eq(ObjectUtil.isNotEmpty(bo.getTopCategoryId()),ProductBaseVo::getTopCategoryId,bo.getTopCategoryId());
+            esQueryWrapper.eq(ObjectUtil.isNotEmpty(bo.getMediumCategoryId()),ProductBaseVo::getMediumCategoryId,bo.getMediumCategoryId());
+            esQueryWrapper.eq(ObjectUtil.isNotEmpty(bo.getBottomCategoryId()),ProductBaseVo::getBottomCategoryId,bo.getBottomCategoryId());
+            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;
+                }
+            }
+
+            if(bo.getSortField() != null && bo.getSortOrder() != null){
+                String[] sortFields = bo.getSortField().split(",");
+                String[] sortOrders = bo.getSortOrder().split(",");
+                for (int i = 0; i < sortFields.length; i++) {
+                    switch (sortFields[i]) {
+                        case "1":
+                            esQueryWrapper.orderBy( true, sortOrders[i].equals("Asc"),ProductBaseVo::getId);
+                        case "2":
+                            esQueryWrapper.orderBy( true, sortOrders[i].equals("Asc"),ProductBaseVo::getTotalInventory);
+                        case "3":
+                            esQueryWrapper.orderBy( true, sortOrders[i].equals("Asc"),ProductBaseVo::getMarketPrice);
+                    }
+                }
+            }
+            EsPageInfo<ProductBaseVo> esPageInfo = esMapper.pageQuery(esQueryWrapper, pageQuery.getPageNum(), pageQuery.getPageSize());
             List<PcProductVo> pcProductVos = BeanUtil.copyToList(esPageInfo.getList(), PcProductVo.class);
             TableDataInfo<PcProductVo> build = TableDataInfo.build(pcProductVos);
             build.getRows().forEach(pcProductVo -> {
@@ -1903,8 +1991,8 @@ public class ProductBaseServiceImpl extends ServiceImpl<ProductBaseMapper, Produ
             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.getMediumCategoryId())) {
+                wrapper.eq(ProductBaseVo::getMediumCategoryId, bo.getMediumCategoryId());
             }
             if (ObjectUtil.isNotEmpty(bo.getBottomCategoryId())) {
                 wrapper.eq(ProductBaseVo::getBottomCategoryId, bo.getBottomCategoryId());

+ 3 - 0
ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/service/impl/ProductBrandServiceImpl.java

@@ -100,6 +100,9 @@ public class ProductBrandServiceImpl  extends ServiceImpl<ProductBrandMapper, Pr
     @Override
     public TableDataInfo<ProductBrandVo> queryPageList(ProductBrandBo bo, PageQuery pageQuery) {
         LambdaQueryWrapper<ProductBrand> lqw = buildQueryWrapper(bo);
+        if(ObjectUtil.isNotEmpty( bo.getIds())){
+            lqw.in(ProductBrand::getId, bo.getIds().split(","));
+        }
         Page<ProductBrandVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
         return TableDataInfo.build(result);
     }

+ 40 - 2
ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/service/impl/ProductProgramServiceImpl.java

@@ -1,5 +1,6 @@
 package org.dromara.product.service.impl;
 
+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;
@@ -10,6 +11,8 @@ 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.ProductProgramLink;
+import org.dromara.product.mapper.ProductProgramLinkMapper;
 import org.springframework.stereotype.Service;
 import org.dromara.product.domain.bo.ProductProgramBo;
 import org.dromara.product.domain.vo.ProductProgramVo;
@@ -34,6 +37,8 @@ public class ProductProgramServiceImpl  extends ServiceImpl<ProductProgramMapper
 
     private final ProductProgramMapper baseMapper;
 
+    private final ProductProgramLinkMapper productProgramLinkMapper;
+
     /**
      * 查询产品解决方案/项目方案
      *
@@ -42,7 +47,14 @@ public class ProductProgramServiceImpl  extends ServiceImpl<ProductProgramMapper
      */
     @Override
     public ProductProgramVo queryById(Long id){
-        return baseMapper.selectVoById(id);
+        ProductProgramVo productProgramVo = baseMapper.selectVoById(id);
+        if (ObjectUtil.isNotNull(productProgramVo)) {
+            List<ProductProgramLink> productProgramLinks = productProgramLinkMapper.selectList(Wrappers.lambdaQuery(ProductProgramLink.class)
+                .eq(ProductProgramLink::getProgramId, id)
+            );
+            productProgramVo.setProductIds(productProgramLinks.stream().map(ProductProgramLink::getProductId).toList());
+        }
+        return productProgramVo;
     }
 
     /**
@@ -101,6 +113,9 @@ public class ProductProgramServiceImpl  extends ServiceImpl<ProductProgramMapper
         ProductProgram add = MapstructUtils.convert(bo, ProductProgram.class);
         validEntityBeforeSave(add);
         boolean flag = baseMapper.insert(add) > 0;
+        if (flag) {
+            insertProductProgramLink(bo.getProductIds(), add.getId());
+        }
         if (flag) {
             bo.setId(add.getId());
         }
@@ -117,9 +132,32 @@ public class ProductProgramServiceImpl  extends ServiceImpl<ProductProgramMapper
     public Boolean updateByBo(ProductProgramBo bo) {
         ProductProgram update = MapstructUtils.convert(bo, ProductProgram.class);
         validEntityBeforeSave(update);
-        return baseMapper.updateById(update) > 0;
+        boolean b = baseMapper.updateById(update) > 0;
+        if (b) {
+            insertProductProgramLink(bo.getProductIds(), bo.getId());
+        }
+        return b;
+    }
+
+    /**
+     * 批量新增产品关联
+     */
+    private void insertProductProgramLink(List<Long> productIds, Long programId){
+        productProgramLinkMapper.delete(Wrappers.lambdaQuery(ProductProgramLink.class)
+            .eq(ProductProgramLink::getProgramId, programId)
+        );
+        if(ObjectUtil.isNotEmpty(productIds)){
+            for (Long productId : productIds) {
+                ProductProgramLink productProgramLink = new ProductProgramLink();
+                productProgramLink.setProductId(productId);
+                productProgramLink.setProgramId(programId);
+                productProgramLinkMapper.insert(productProgramLink);
+            }
+        }
     }
 
+
+
     /**
      * 保存前的数据校验
      */

+ 7 - 0
ruoyi-modules/ruoyi-product/src/main/resources/mapper/product/ClientSiteMapper.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.ClientSiteMapper">
+
+</mapper>

+ 7 - 0
ruoyi-modules/ruoyi-product/src/main/resources/mapper/product/ClientSiteProductMapper.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.ClientSiteProductMapper">
+
+</mapper>

+ 7 - 0
ruoyi-modules/ruoyi-product/src/main/resources/mapper/product/ClientSiteSettingMapper.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.ClientSiteSettingMapper">
+
+</mapper>

+ 7 - 0
ruoyi-modules/ruoyi-product/src/main/resources/mapper/product/ProcurementProgramCollectMapper.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.ProcurementProgramCollectMapper">
+
+</mapper>

+ 1 - 0
ruoyi-modules/ruoyi-product/src/main/resources/mapper/product/ProductIndustrialFloorLinkMapper.xml

@@ -13,6 +13,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             l.product_id,
             l.product_no,
             l.brand_no,
+            l.brand_id,
             l.sort,
             l.status,
             l.remark,

+ 3 - 4
ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/pc/IndexSystemController.java

@@ -11,10 +11,7 @@ import org.dromara.system.domain.bo.SysAnnouncementBo;
 import org.dromara.system.domain.vo.SysAnnouncementVo;
 import org.dromara.system.service.*;
 import org.springframework.validation.annotation.Validated;
-import org.springframework.web.bind.annotation.GetMapping;
-import org.springframework.web.bind.annotation.PathVariable;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.bind.annotation.*;
 
 import java.util.List;
 
@@ -24,6 +21,7 @@ import java.util.List;
  * @date 2026/1/29 下午3:31
  */
 @Validated
+
 @RequiredArgsConstructor
 @RestController
 @RequestMapping("/indexSystem")
@@ -223,6 +221,7 @@ public class IndexSystemController {
     public R<List<SysFloorAdvertise>> getClassificationFloorDetail(@PathVariable Long floorNo) {
         List<SysFloorAdvertise> list = sysFloorAdvertiseService.list(Wrappers.lambdaQuery(SysFloorAdvertise.class)
             .eq(SysFloorAdvertise::getFloorNo, floorNo)
+            .orderByAsc(SysFloorAdvertise::getSort)
         );
         return R.ok(list);
     }

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

@@ -66,7 +66,7 @@ public class IndustrySystemController {
     public R<List<SysAdContent>> getBusinessLabelList() {
         List<SysAdContent> list = sysAdContentService.list(Wrappers.<SysAdContent>lambdaQuery(SysAdContent.class)
             .eq(SysAdContent::getAdType, "industrial_tag")
-            .eq(SysAdContent::getStatus, 1)
+//            .eq(SysAdContent::getStatus, 1)
         );
         return R.ok(list);
     }