소스 검색

coding:投流代码提交

zhangqin 3 주 전
부모
커밋
8a83b66ea5
77개의 변경된 파일1237개의 추가작업 그리고 2478개의 파일을 삭제
  1. 0 5
      fs-ad-new-api/src/main/java/com/fs/app/constant/MqTopicConstant.java
  2. 12 3
      fs-ad-new-api/src/main/java/com/fs/app/controller/CallbackController.java
  3. 4 22
      fs-ad-new-api/src/main/java/com/fs/app/controller/LandingPageController.java
  4. 62 0
      fs-ad-new-api/src/main/java/com/fs/app/controller/TestController.java
  5. 10 151
      fs-ad-new-api/src/main/java/com/fs/app/controller/TrackingController.java
  6. 0 6
      fs-ad-new-api/src/main/java/com/fs/app/enums/event/IEventType.java
  7. 0 56
      fs-ad-new-api/src/main/java/com/fs/app/event/ConversionEventListener.java
  8. 0 54
      fs-ad-new-api/src/main/java/com/fs/app/event/ConversionEventPublisher.java
  9. 12 8
      fs-ad-new-api/src/main/java/com/fs/app/facade/CallbackProcessingFacadeService.java
  10. 64 137
      fs-ad-new-api/src/main/java/com/fs/app/facade/CallbackProcessingFacadeServiceImpl.java
  11. 50 41
      fs-ad-new-api/src/main/java/com/fs/app/facade/ConversionServiceImpl.java
  12. 5 6
      fs-ad-new-api/src/main/java/com/fs/app/facade/IConversionService.java
  13. 32 31
      fs-ad-new-api/src/main/java/com/fs/app/integration/adapter/BaiduAdapter.java
  14. 9 9
      fs-ad-new-api/src/main/java/com/fs/app/integration/adapter/IAdvertiserAdapter.java
  15. 70 0
      fs-ad-new-api/src/main/java/com/fs/app/integration/adapter/OPPOAdapter.java
  16. 41 29
      fs-ad-new-api/src/main/java/com/fs/app/integration/adapter/OceanEngineAdapter.java
  17. 67 0
      fs-ad-new-api/src/main/java/com/fs/app/integration/adapter/TencentAdapter.java
  18. 63 0
      fs-ad-new-api/src/main/java/com/fs/app/integration/adapter/VIVOAdapter.java
  19. 3 3
      fs-ad-new-api/src/main/java/com/fs/app/integration/client/AbstractApiClient.java
  20. 1 1
      fs-ad-new-api/src/main/java/com/fs/app/integration/client/IApiClient.java
  21. 7 98
      fs-ad-new-api/src/main/java/com/fs/app/integration/client/advertiser/BaiduApiClient.java
  22. 70 0
      fs-ad-new-api/src/main/java/com/fs/app/integration/client/advertiser/IQIYIApiClient.java
  23. 11 22
      fs-ad-new-api/src/main/java/com/fs/app/integration/client/advertiser/OPPOApiClient.java
  24. 11 27
      fs-ad-new-api/src/main/java/com/fs/app/integration/client/advertiser/OceanEngineApiClient.java
  25. 15 20
      fs-ad-new-api/src/main/java/com/fs/app/integration/client/advertiser/TencentApiClient.java
  26. 86 0
      fs-ad-new-api/src/main/java/com/fs/app/integration/client/advertiser/VIVOApiClient.java
  27. 4 33
      fs-ad-new-api/src/main/java/com/fs/app/integration/factory/AdvertiserHandlerFactory.java
  28. 0 51
      fs-ad-new-api/src/main/java/com/fs/app/integration/strategy/BaiduCallbackStrategy.java
  29. 0 37
      fs-ad-new-api/src/main/java/com/fs/app/integration/strategy/ICallbackStrategy.java
  30. 0 47
      fs-ad-new-api/src/main/java/com/fs/app/integration/strategy/OceanEngineCallbackStrategy.java
  31. 0 46
      fs-ad-new-api/src/main/java/com/fs/app/mq/consumer/ClickMessageConsumer.java
  32. 0 111
      fs-ad-new-api/src/main/java/com/fs/app/mq/consumer/ConversionMessageConsumer.java
  33. 0 111
      fs-ad-new-api/src/main/java/com/fs/app/mq/consumer/ConversionMessageConsumer2.java
  34. 67 0
      fs-ad-new-api/src/main/java/com/fs/app/mq/consumer/ConversionTrackingMessageConsumer.java
  35. 0 26
      fs-ad-new-api/src/main/java/com/fs/app/mq/message/ClickMessage.java
  36. 0 53
      fs-ad-new-api/src/main/java/com/fs/app/mq/message/ConversionMessage.java
  37. 0 19
      fs-ad-new-api/src/main/java/com/fs/app/mq/message/MqMessageDto.java
  38. 0 125
      fs-ad-new-api/src/main/java/com/fs/app/mq/producer/ConversionMessageProducer.java
  39. 1 1
      fs-ad-new-api/src/main/java/com/fs/app/task/ConversionRetryTask.java
  40. 2 2
      fs-ad-new-api/src/main/java/com/fs/app/task/DataSyncTask.java
  41. 24 8
      fs-company/src/main/java/com/fs/company/controller/newAdv/CallbackAccountController.java
  42. 0 94
      fs-company/src/main/java/com/fs/company/controller/newAdv/LeadSourceController.java
  43. 33 0
      fs-service/src/main/java/com/fs/newAdv/constant/ConversionTrackingMessage.java
  44. 27 0
      fs-service/src/main/java/com/fs/newAdv/constant/MqTopicConstant.java
  45. 44 0
      fs-service/src/main/java/com/fs/newAdv/domain/AdvEventType.java
  46. 43 7
      fs-service/src/main/java/com/fs/newAdv/domain/CallbackAccount.java
  47. 0 109
      fs-service/src/main/java/com/fs/newAdv/domain/ClickTrace.java
  48. 57 17
      fs-service/src/main/java/com/fs/newAdv/domain/Lead.java
  49. 0 97
      fs-service/src/main/java/com/fs/newAdv/domain/LeadSource.java
  50. 0 10
      fs-service/src/main/java/com/fs/newAdv/domain/PromotionAccount.java
  51. 0 4
      fs-service/src/main/java/com/fs/newAdv/domain/Site.java
  52. 0 144
      fs-service/src/main/java/com/fs/newAdv/domain/SiteStatisticsMonthly.java
  53. 0 155
      fs-service/src/main/java/com/fs/newAdv/domain/SiteStatisticsWeekly.java
  54. 0 1
      fs-service/src/main/java/com/fs/newAdv/dto/req/LandingIndexReq.java
  55. 11 9
      fs-service/src/main/java/com/fs/newAdv/enums/AdvertiserTypeEnum.java
  56. 1 1
      fs-service/src/main/java/com/fs/newAdv/enums/CallbackStatusEnum.java
  57. 1 1
      fs-service/src/main/java/com/fs/newAdv/enums/ConversionTypeEnum.java
  58. 1 1
      fs-service/src/main/java/com/fs/newAdv/enums/TaskStatusEnum.java
  59. 1 1
      fs-service/src/main/java/com/fs/newAdv/enums/TaskTypeEnum.java
  60. 6 22
      fs-service/src/main/java/com/fs/newAdv/event/ConversionEvent.java
  61. 78 0
      fs-service/src/main/java/com/fs/newAdv/event/ConversionEventListener.java
  62. 48 0
      fs-service/src/main/java/com/fs/newAdv/event/ConversionEventPublisher.java
  63. 3 3
      fs-service/src/main/java/com/fs/newAdv/mapper/AdvEventTypeMapper.java
  64. 0 16
      fs-service/src/main/java/com/fs/newAdv/mapper/ClickTraceMapper.java
  65. 0 17
      fs-service/src/main/java/com/fs/newAdv/mapper/SiteStatisticsMonthlyMapper.java
  66. 0 17
      fs-service/src/main/java/com/fs/newAdv/mapper/SiteStatisticsWeeklyMapper.java
  67. 11 0
      fs-service/src/main/java/com/fs/newAdv/service/IAdvEventTypeService.java
  68. 12 25
      fs-service/src/main/java/com/fs/newAdv/service/ICallbackAccountService.java
  69. 0 36
      fs-service/src/main/java/com/fs/newAdv/service/IClickTraceService.java
  70. 1 0
      fs-service/src/main/java/com/fs/newAdv/service/ILeadService.java
  71. 0 46
      fs-service/src/main/java/com/fs/newAdv/service/ILeadSourceService.java
  72. 17 0
      fs-service/src/main/java/com/fs/newAdv/service/impl/AdvEventTypeServiceImpl.java
  73. 18 70
      fs-service/src/main/java/com/fs/newAdv/service/impl/CallbackAccountServiceImpl.java
  74. 0 74
      fs-service/src/main/java/com/fs/newAdv/service/impl/ClickTraceServiceImpl.java
  75. 8 1
      fs-service/src/main/java/com/fs/newAdv/service/impl/LeadServiceImpl.java
  76. 0 101
      fs-service/src/main/java/com/fs/newAdv/service/impl/LeadSourceServiceImpl.java
  77. 13 0
      fs-service/src/main/java/com/fs/newAdv/vo/ConversionEventVo.java

+ 0 - 5
fs-ad-new-api/src/main/java/com/fs/app/constant/MqTopicConstant.java

@@ -1,5 +0,0 @@
-package com.fs.app.constant;
-
-public class MqTopicConstant {
-    public static final String CONVERSION_TOPIC = "conversion-topic";
-}

+ 12 - 3
fs-ad-new-api/src/main/java/com/fs/app/controller/CallbackController.java

@@ -1,7 +1,6 @@
 package com.fs.app.controller;
 
 import com.fs.app.facade.CallbackProcessingFacadeService;
-import com.fs.app.facade.CallbackProcessingFacadeServiceImpl;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.GetMapping;
@@ -9,6 +8,9 @@ import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RequestParam;
 import org.springframework.web.bind.annotation.RestController;
 
+/**
+ * 广告商回调接口
+ */
 @Slf4j
 @RestController
 @RequestMapping("/callBack")
@@ -18,10 +20,17 @@ public class CallbackController {
     private CallbackProcessingFacadeService facadeService;
 
 
-    @GetMapping("/gdt/getAuthCode")
-    public void gdtGetAuthCode(
+    @GetMapping("/tencent/getAuthCode")
+    public void getTencentAuthCode(
             @RequestParam("authorization_code") Integer code,
             @RequestParam("state") Long state) {
         facadeService.gdtGetAuthCode(code, state);
     }
+/*
+    @GetMapping("/vivo/getAuthCode")
+    public void getVivoAuthCode(
+            @RequestParam("authorization_code") Integer code,
+            @RequestParam("state") Long state) {
+        facadeService.getVivoAuthCode(code, state);
+    }*/
 }

+ 4 - 22
fs-ad-new-api/src/main/java/com/fs/app/controller/LandingPageController.java

@@ -2,11 +2,8 @@ package com.fs.app.controller;
 
 import cn.hutool.core.util.StrUtil;
 import com.fs.app.facade.CallbackProcessingFacadeService;
-import com.fs.app.mq.message.ClickMessage;
-import com.fs.app.mq.producer.ConversionMessageProducer;
 import com.fs.common.result.Result;
 import com.fs.newAdv.dto.req.LandingIndexReq;
-import com.fs.newAdv.dto.req.LeadSubmitRequest;
 import com.fs.newAdv.dto.res.LandingIndexRes;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -28,10 +25,7 @@ import java.util.Map;
 public class LandingPageController {
 
     @Autowired
-    private CallbackProcessingFacadeService callbackFacade;
-
-    @Autowired
-    private ConversionMessageProducer messageProducer;
+    private CallbackProcessingFacadeService facadeService;
 
     /**
      * 落地页访问
@@ -51,23 +45,11 @@ public class LandingPageController {
                 return Result.error(400, "缺少站点ID参数");
             }
         }
-        // 完善线索追踪信息
-        ClickMessage message = new ClickMessage();
-        message.setSiteId(siteId);
-        messageProducer.sendClickMessage(message);
+        // 保存落地页访问记录
+        facadeService.saveLandingIndexTrace(siteId, allParams);
         // 查询落地页模板
-        LandingIndexRes res = callbackFacade.getLandingIndexBySiteId(siteId);
-        return Result.success(res);
+        return Result.success(facadeService.getLandingIndexBySiteId(siteId));
     }
 
-
-    /**
-     * 提交表单/落地按钮点击
-     */
-    @PostMapping("/submit")
-    public Result<String> submitForm(@RequestBody LeadSubmitRequest request) {
-        callbackFacade.submitForm(request);
-        return Result.success();
-    }
 }
 

+ 62 - 0
fs-ad-new-api/src/main/java/com/fs/app/controller/TestController.java

@@ -0,0 +1,62 @@
+package com.fs.app.controller;
+
+import com.fs.newAdv.enums.event.SystemEventTypeEnum;
+import com.fs.newAdv.event.ConversionEventPublisher;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+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;
+
+/**
+ * 广告商监测链接
+ *
+ * @author zhangqin
+ */
+@Slf4j
+@RestController
+@RequestMapping("/test")
+public class TestController {
+
+    @Autowired
+    private ConversionEventPublisher conversionEventPublisher;
+
+    @GetMapping("/test1/{traceId}")
+    public void test1(@PathVariable("traceId") String traceId) {
+        log.info("模拟 当日加群 事件完成");
+        conversionEventPublisher.publishConversionEvent(traceId, SystemEventTypeEnum.GROUP_TODAY);
+    }
+
+    @GetMapping("/test2/{traceId}")
+    public void test2(@PathVariable("traceId") String traceId) {
+        log.info("模拟 当日加微 事件完成");
+        conversionEventPublisher.publishConversionEvent(traceId, SystemEventTypeEnum.WEICHAT_TODAY);
+    }
+
+    @GetMapping("/submit/{traceId}")
+    public void test3(@PathVariable("traceId") String traceId) {
+        log.info("模拟 直播到课加群 事件完成");
+        conversionEventPublisher.publishConversionEvent(traceId, SystemEventTypeEnum.TO_CLASS_AND_GROUP_TODAY);
+    }
+
+    @GetMapping("/test4/{traceId}")
+    public void test4(@PathVariable("traceId") String traceId) {
+        log.info("模拟 直播到课加微 事件完成");
+        conversionEventPublisher.publishConversionEvent(traceId, SystemEventTypeEnum.TO_CLASS_AND_WEICHAT_TODAY);
+    }
+
+    @GetMapping("/test5/{traceId}")
+    public void test5(@PathVariable("traceId") String traceId) {
+        log.info("模拟 商品购买订单 事件完成");
+        conversionEventPublisher.publishConversionEvent(traceId, SystemEventTypeEnum.BUY_ORDER);
+    }
+
+    @GetMapping("/test6/{traceId}")
+    public void test6(@PathVariable("traceId") String traceId) {
+        log.info("模拟当日加群事件完成");
+        conversionEventPublisher.publishConversionEvent(traceId, SystemEventTypeEnum.GROUP_TODAY);
+    }
+
+
+}

+ 10 - 151
fs-ad-new-api/src/main/java/com/fs/app/controller/TrackingController.java

@@ -1,21 +1,15 @@
 package com.fs.app.controller;
 
-import cn.hutool.core.util.StrUtil;
-import com.fs.app.enums.AdvertiserTypeEnum;
 import com.fs.app.facade.CallbackProcessingFacadeService;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.web.bind.annotation.GetMapping;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RequestParam;
-import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.bind.annotation.*;
 
-import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 import java.util.Map;
 
 /**
- * 链化追踪
+ * 广告商监测链接
  *
  * @author zhangqin
  */
@@ -25,165 +19,30 @@ import java.util.Map;
 public class TrackingController {
 
     @Autowired
-    private CallbackProcessingFacadeService callback;
+    private CallbackProcessingFacadeService facadeService;
+
 
     /**
-     * 百度推广监测端点
+     * 监测链接端口
      *
      * @param allParams 所有URL参数
      * @param response  HTTP响应
      */
-    @GetMapping("/baidu")
+    @GetMapping("/click/{advertiserCode}")
     public void trackBaidu(
             @RequestParam Map<String, String> allParams,
+            @PathVariable("advertiserCode") Long advertiserCode,
             HttpServletResponse response) {
-        log.info("【百度】接收监测请求 | params={}", allParams);
+        log.info("接收监测请求 | params={}", allParams);
         try {
-            // 1. 提取百度特有参数
-            String traceId = allParams.get("bd_id");
-            if (StrUtil.isBlank(traceId)) {
-                log.warn("【百度】监测请求缺少点击ID | params={}", allParams);
-                response.setStatus(HttpServletResponse.SC_OK);
-                return;
-            }
             // 2. 保存点击追踪记录
-            callback.saveClickTrace(
-                    AdvertiserTypeEnum.BAIDU,
-                    allParams
-            );
+            facadeService.saveClickTrace(advertiserCode,allParams);
             // 3. 返回 200 OK
             response.setStatus(HttpServletResponse.SC_OK);
         } catch (Exception e) {
-            log.error("【百度】监测请求处理失败 | params={}", allParams, e);
-            response.setStatus(HttpServletResponse.SC_OK);
-        }
-    }
-
-    /**
-     * 巨量引擎监测端点
-     *
-     * @param allParams 所有URL参数
-     * @param request   HTTP请求
-     * @param response  HTTP响应
-     */
-    @GetMapping("/oceanengine")
-    public void trackOceanEngine(
-            @RequestParam Map<String, String> allParams,
-            HttpServletRequest request,
-            HttpServletResponse response) {
-
-        try {
-
-
-        } catch (Exception e) {
-            log.error("【巨量引擎】监测请求处理失败 | params={}", allParams, e);
-            response.setStatus(HttpServletResponse.SC_OK);
-        }
-    }
-
-    /**
-     * 新浪扶翼监测端点
-     * <p>
-     * 监测链接示例:
-     * https://track.yourdomain.com/api/track/sina?click_id={click_id}&site_id=100&campaign_id={campaign_id}
-     * <p>
-     * 新浪宏参数说明:
-     * - {click_id}: 点击ID(必填)
-     * - {campaign_id}: 广告计划ID
-     * - {ad_id}: 广告ID
-     *
-     * @param allParams 所有URL参数
-     * @param request   HTTP请求
-     * @param response  HTTP响应
-     */
-    @GetMapping("/sina")
-    public void trackSina(
-            @RequestParam Map<String, String> allParams,
-            HttpServletRequest request,
-            HttpServletResponse response) {
-
-        try {
-            // 1. 提取新浪参数
-            String clickId = allParams.get("click_id");
-
-            if (StrUtil.isBlank(clickId)) {
-                log.warn("【新浪】监测请求缺少点击ID | params={}", allParams);
-                response.setStatus(HttpServletResponse.SC_OK);
-                return;
-            }
-
-
-            // 4. 返回 200 OK
-            response.setStatus(HttpServletResponse.SC_OK);
-
-        } catch (Exception e) {
-            log.error("【新浪】监测请求处理失败 | params={}", allParams, e);
+            log.error("监测请求处理失败 | params={}", allParams, e);
             response.setStatus(HttpServletResponse.SC_OK);
         }
     }
 
-    /**
-     * 腾讯广点通监测端点
-     * <p>
-     * 监测链接示例:
-     * https://track.yourdomain.com/api/track/gdt?click_id={CLICK_ID}&site_id=100&ad_id={ADGROUPID}
-     * <p>
-     * 广点通宏参数说明:
-     * - {CLICK_ID}: 点击ID(必填)
-     * - {ADGROUPID}: 广告组ID
-     * - {CREATIVEID}: 创意ID
-     * - {CAMPAIGNID}: 推广计划ID
-     *
-     * @param allParams 所有URL参数
-     * @param request   HTTP请求
-     * @param response  HTTP响应
-     */
-    @GetMapping("/gdt")
-    public void trackGdt(
-            @RequestParam Map<String, String> allParams,
-            HttpServletRequest request,
-            HttpServletResponse response) {
-
-        try {
-            // 1. 提取广点通参数(广点通使用大写参数名)
-
-
-            // 4. 返回 200 OK
-            response.setStatus(HttpServletResponse.SC_OK);
-
-        } catch (Exception e) {
-            log.error("【广点通】监测请求处理失败 | params={}", allParams, e);
-            response.setStatus(HttpServletResponse.SC_OK);
-        }
-    }
-
-    /**
-     * 通用监测端点(兼容旧配置)
-     * <p>
-     * 如果广告平台已配置了统一的监测链接,仍可使用此端点
-     * 需要在参数中指定 source 参数
-     * <p>
-     * 示例:
-     * https://track.yourdomain.com/api/track/common?click_id=ABC123&site_id=100&source=baidu
-     *
-     * @param allParams 所有URL参数
-     * @param request   HTTP请求
-     * @param response  HTTP响应
-     */
-    @GetMapping("/common")
-    public void trackCommon(
-            @RequestParam Map<String, String> allParams,
-            HttpServletRequest request,
-            HttpServletResponse response) {
-
-        try {
-
-            // 4. 返回 200 OK
-            response.setStatus(HttpServletResponse.SC_OK);
-
-        } catch (Exception e) {
-            log.error("【通用】监测请求处理失败 | params={}", allParams, e);
-            response.setStatus(HttpServletResponse.SC_OK);
-        }
-    }
 }

+ 0 - 6
fs-ad-new-api/src/main/java/com/fs/app/enums/event/IEventType.java

@@ -1,6 +0,0 @@
-package com.fs.app.enums.event;
-
-public interface IEventType {
-    String getCode();
-    String getDesc();
-}

+ 0 - 56
fs-ad-new-api/src/main/java/com/fs/app/event/ConversionEventListener.java

@@ -1,56 +0,0 @@
-package com.fs.app.event;
-
-import com.fs.app.enums.AdvertiserTypeEnum;
-import com.fs.app.mq.message.ConversionMessage;
-import com.fs.app.mq.producer.ConversionMessageProducer;
-import com.fs.app.enums.ConversionTypeEnum;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.context.event.EventListener;
-import org.springframework.scheduling.annotation.Async;
-import org.springframework.stereotype.Component;
-
-/**
- * 转化事件监听器
- * 监听转化事件并发送到MQ进行异步处理
- *
- * @author zhangqin
- * @date 2025-11-03
- * @updated 2025-11-05 重构为发送MQ消息
- */
-@Slf4j
-@Component
-public class ConversionEventListener {
-
-    @Autowired
-    private ConversionMessageProducer messageProducer;
-
-    /**
-     * 处理转化事件
-     * 将转化事件转换为MQ消息并发送
-     *
-     * @param event 转化事件
-     */
-    @Async("asyncExecutor")
-    @EventListener
-    public void handleConversionEvent(ConversionEvent event) {
-        Long siteId = event.getSiteId();
-        String traceId = event.getTraceId();
-        AdvertiserTypeEnum advertiser = event.getAdvertiser();
-        ConversionTypeEnum eventType = event.getEventType();
-        Double value = event.getValue();
-        Long leadId = event.getLeadId();
-        log.info("接收到转化事件 | siteId={}, traceId={}, advertiser={}, eventType={}",
-                siteId, traceId, advertiser, eventType);
-        // 1. 校验参数
-        // 2. 构建MQ消息
-        ConversionMessage message = new ConversionMessage();
-        message.setSiteId(siteId);
-        message.setAdvertiser(advertiser);
-        message.setEventType(eventType);
-        message.setLeadId(leadId);
-        message.setTraceId(traceId);
-        // 3. 发送到MQ
-        messageProducer.sendConversionMessage(message);
-    }
-}

+ 0 - 54
fs-ad-new-api/src/main/java/com/fs/app/event/ConversionEventPublisher.java

@@ -1,54 +0,0 @@
-package com.fs.app.event;
-
-import com.fs.app.enums.AdvertiserTypeEnum;
-import com.fs.app.enums.ConversionTypeEnum;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.context.ApplicationEventPublisher;
-import org.springframework.stereotype.Component;
-
-/**
- * 转化事件发布器
- *
- * @author zhangqin
- * @date 2025-11-03
- * @updated 2025-11-05 添加clickId和advertiser参数
- */
-@Slf4j
-@Component
-public class ConversionEventPublisher {
-
-    @Autowired
-    private ApplicationEventPublisher applicationEventPublisher;
-
-    /**
-     * 发布转化事件
-     *
-     * @param siteId 站点ID
-     * @param clickId 点击ID(广告平台提供)
-     * @param advertiser 广告商名称(BAIDU, OCEANENGINE, SINA, GDT)
-     * @param eventType 转化事件类型(如:SUBMIT_FORM、REGISTER、PAY)
-     * @param value 转化价值(元)
-     * @param leadId 线索ID(可选)
-     */
-    public void publishConversionEvent(Long siteId, String clickId, AdvertiserTypeEnum advertiser,
-                                       ConversionTypeEnum eventType, Double value, Long leadId) {
-        log.info("发布转化事件 | siteId={}, clickId={}, advertiser={}, eventType={}, value={}",
-                siteId, clickId, advertiser, eventType, value);
-        ConversionEvent event = new ConversionEvent(this, siteId, clickId,
-                                                     advertiser, eventType, value, leadId);
-        applicationEventPublisher.publishEvent(event);
-    }
-
-    /**
-     * 发布转化事件(无价值,无线索ID)
-     *
-     * @param siteId 站点ID
-     * @param clickId 点击ID
-     * @param advertiser 广告商名称
-     * @param eventType 转化事件类型
-     */
-    public void publishConversionEvent(Long siteId, String clickId, AdvertiserTypeEnum advertiser, ConversionTypeEnum eventType) {
-        publishConversionEvent(siteId, clickId, advertiser, eventType, null, null);
-    }
-}

+ 12 - 8
fs-ad-new-api/src/main/java/com/fs/app/facade/CallbackProcessingFacadeService.java

@@ -1,8 +1,5 @@
 package com.fs.app.facade;
 
-import com.fs.app.enums.AdvertiserTypeEnum;
-import com.fs.app.mq.message.ClickMessage;
-import com.fs.newAdv.dto.req.LeadSubmitRequest;
 import com.fs.newAdv.dto.res.LandingIndexRes;
 
 import java.util.Map;
@@ -10,12 +7,17 @@ import java.util.Map;
 public interface CallbackProcessingFacadeService {
 
 
-    void saveClickTrace(AdvertiserTypeEnum trackType, Map<String, String> allParams);
-
-    void updateClickTrace(ClickMessage message);
-
-    void submitForm(LeadSubmitRequest request);
+    /**
+     * 链化追踪点击
+     * @param allParams
+     */
+    void saveClickTrace(Long advertiserCode,Map<String,String> allParams);
 
+    /**
+     * 落地页追踪点击
+     * @param allParams
+     */
+    void saveLandingIndexTrace(Long siteId, Map<String, String> allParams);
     /**
      * 根据站点ID获取落地页信息
      *
@@ -26,4 +28,6 @@ public interface CallbackProcessingFacadeService {
 
     //----------------------code回调---------------------------------
     void gdtGetAuthCode(Integer code, Long state);
+
+
 }

+ 64 - 137
fs-ad-new-api/src/main/java/com/fs/app/facade/CallbackProcessingFacadeServiceImpl.java

@@ -1,156 +1,104 @@
 package com.fs.app.facade;
 
-import cn.hutool.core.util.StrUtil;
+import cn.hutool.core.util.ObjectUtil;
 import cn.hutool.json.JSONUtil;
-import com.fs.app.enums.AdvertiserTypeEnum;
-import com.fs.app.enums.ConversionTypeEnum;
-import com.fs.app.event.ConversionEventPublisher;
+import com.fs.app.integration.adapter.IAdvertiserAdapter;
 import com.fs.app.integration.client.IAccessTokenClient;
 import com.fs.app.integration.client.IApiClient;
 import com.fs.app.integration.factory.AdvertiserHandlerFactory;
-import com.fs.app.mq.message.ClickMessage;
 import com.fs.common.exception.base.BusinessException;
-import com.fs.newAdv.domain.*;
-import com.fs.newAdv.dto.req.LeadSubmitRequest;
+import com.fs.newAdv.domain.LandingPageTemplate;
+import com.fs.newAdv.domain.Lead;
+import com.fs.newAdv.domain.PromotionAccount;
+import com.fs.newAdv.domain.Site;
 import com.fs.newAdv.dto.res.LandingIndexRes;
-import com.fs.newAdv.service.*;
+import com.fs.newAdv.enums.AdvertiserTypeEnum;
+import com.fs.newAdv.service.ILandingPageTemplateService;
+import com.fs.newAdv.service.ILeadService;
+import com.fs.newAdv.service.IPromotionAccountService;
+import com.fs.newAdv.service.ISiteService;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
 import java.time.LocalDateTime;
-import java.util.HashMap;
 import java.util.Map;
 import java.util.Objects;
 
 @Service
 @Slf4j
 public class CallbackProcessingFacadeServiceImpl implements CallbackProcessingFacadeService {
-
     @Autowired
     private AdvertiserHandlerFactory handlerFactory;
-
     @Autowired
     private ILeadService leadService;
     @Autowired
     private ISiteService siteService;
-
-    @Autowired
-    private ConversionEventPublisher conversionEventPublisher;
-
-    @Autowired
-    private IClickTraceService iClickTraceService;
     @Autowired
     private ILandingPageTemplateService landingPageTemplateService;
     @Autowired
     private IPromotionAccountService promotionAccountService;
 
     @Override
-    public void saveClickTrace(AdvertiserTypeEnum trackType, Map<String, String> allParams) {
-        ClickTrace trace = new ClickTrace();
-        // 提取不同平台的参数
-        extractPlatformParams(trace, trackType, allParams);
-        // 保存原始参数
-        trace.setRawParams(JSONUtil.toJsonStr(allParams));
-        // 状态初始化
-        trace.setIsConverted(0);
-        trace.setSource(trackType.getName());
-        // 时间
-        trace.setCreateTime(LocalDateTime.now());
-        trace.setUpdateTime(LocalDateTime.now());
-
-        iClickTraceService.save(trace);
-        log.info("点击追踪记录保存成功:traceId={}", trace.getTraceId());
-    }
-
-    /**
-     * 获取traceId和source平台信息
-     *
-     * @param allParams
-     * @return traceId 线索id
-     */
-    private Map<String, String> getTraceIdByPlatformParams(Long advertiserId, Map<String, String> allParams) {
-        Map<String, String> traceId = new HashMap<>();
-        if (Objects.equals(AdvertiserTypeEnum.getByCode(advertiserId), AdvertiserTypeEnum.BAIDU) && StrUtil.isNotEmpty(allParams.get("bd_vid"))) {
-            traceId.put("traceId", allParams.get("bd_vid"));
-        } else if (Objects.equals(AdvertiserTypeEnum.getByCode(advertiserId), AdvertiserTypeEnum.OCEANENGINE) && StrUtil.isNotEmpty(allParams.get("bd_vid"))) {
-            traceId.put("traceId", allParams.get("bd_vid"));
-        }else if (Objects.equals(AdvertiserTypeEnum.getByCode(advertiserId), AdvertiserTypeEnum.GDT) && StrUtil.isNotEmpty(allParams.get("bd_vid"))) {
-            traceId.put("traceId", allParams.get("bd_vid"));
-        }else if (Objects.equals(AdvertiserTypeEnum.getByCode(advertiserId), AdvertiserTypeEnum.OPPO) && StrUtil.isNotEmpty(allParams.get("pageId"))) {
-            traceId.put("traceId", allParams.get("pageId"));
-        }else if (Objects.equals(AdvertiserTypeEnum.getByCode(advertiserId), AdvertiserTypeEnum.VIVO) && StrUtil.isNotEmpty(allParams.get("bd_vid"))) {
-            traceId.put("traceId", allParams.get("bd_vid"));
-        }else if (Objects.equals(AdvertiserTypeEnum.getByCode(advertiserId), AdvertiserTypeEnum.iQIYI) && StrUtil.isNotEmpty(allParams.get("bd_vid"))) {
-            traceId.put("traceId", allParams.get("bd_vid"));
+    public void saveClickTrace(Long advertiserCode, Map<String, String> allParams) {
+        IAdvertiserAdapter advertiserAdapter = handlerFactory.getAdapter(AdvertiserTypeEnum.getByCode(advertiserCode));
+        Lead lead = advertiserAdapter.adaptCallbackData(allParams);
+        Lead byTraceId = leadService.getByTraceId(lead.getTraceId());
+        if (ObjectUtil.isNotEmpty(byTraceId)) {
+            throw new BusinessException("监测信息已存在: " + lead.getTraceId());
         }
-        return traceId;
-    }
-
-    @Override
-    public void updateClickTrace(ClickMessage clickMessage) {
-        Map<String, String> params = getTraceIdByPlatformParams(null,clickMessage.getAllParams());
-        Site site = siteService.getById(clickMessage.getSiteId());
-        ClickTrace byTraceId = iClickTraceService.getByTraceId(params.get("traceId"));
-        byTraceId.setSiteId(site.getId());
-        byTraceId.setAdvertiserId(site.getAdvertiserId());
-        byTraceId.setAdvertiserName(site.getAdvertiserName());
-        byTraceId.setViewUrl(clickMessage.getViewUrl());
-        siteService.updateById(site);
-    }
-
-    /**
-     * 提取不同平台的参数
-     */
-    private void extractPlatformParams(ClickTrace trace,
-                                       AdvertiserTypeEnum trackType,
-                                       Map<String, String> allParams) {
-        switch (trackType) {
-            case BAIDU:
-                trace.setTraceId(allParams.get("bd_vid"));
-                trace.setClickId(allParams.get("click_id"));
-                trace.setCreativeId(allParams.get("aid"));
-                trace.setCampaignId(allParams.get("pid"));
-                trace.setIp(allParams.get("ip"));
-                break;
-            case OCEANENGINE:
-                break;
+        lead.setStatus(0);
+        lead.setClickTrigger(1);
+        lead.setTraceRawParams(JSONUtil.toJsonStr(allParams));
+        boolean saved = leadService.save(lead);
+        if (!saved) {
+            log.error("线索保存失败:{}", lead);
+            throw new RuntimeException("线索保存失败");
         }
-
     }
 
     @Override
-    public void submitForm(LeadSubmitRequest request) {
-        Site byId = siteService.getById(request.getSiteId());
-        if (byId == null) {
-            throw new BusinessException("站点不存在");
+    public void saveLandingIndexTrace(Long siteId, Map<String, String> allParams) {
+        Site byId = siteService.getById(siteId);
+        Long advertiserId = byId.getAdvertiserId();
+        String traceId = getTraceIdByAdvertiser(Objects.requireNonNull(AdvertiserTypeEnum.getByCode(advertiserId)), allParams);
+        Lead byTraceId = leadService.getByTraceId(traceId);
+        if (ObjectUtil.isEmpty(byTraceId)) {
+            byTraceId = new Lead();
+            byTraceId.setAdvertiserId(advertiserId);
+            byTraceId.setSiteId(siteId);
+            leadService.save(byTraceId);
         }
-        Map<String, String> params = getTraceIdByPlatformParams(byId.getAdvertiserId(), request.getRawParams());
-        String traceId = params.get("traceId");
-        if (StrUtil.isEmpty(traceId)) {
-            throw new BusinessException("缺少traceId");
+        if (!Objects.equals(byTraceId.getSiteId(), siteId)) {
+            log.info("落地页站点信息异常:{}---{}", byTraceId.getSiteId(), siteId);
         }
-        // 2. 构建Lead对象
-        Lead lead = new Lead();
-        lead.setSiteId(request.getSiteId());
-        lead.setViewUrl(request.getViewUrl());
-        lead.setAdvertiserId(byId.getAdvertiserId());
-        lead.setAdvertiserName(byId.getAdvertiserName());
-        lead.setTraceId(traceId);
-        lead.setStatus(0); // 新线索
-
-        // 3. 保存原始参数JSON(优先使用前端传递的完整参数)
-        Map<String, Object> rawParams = new HashMap<>();
-        if (request.getRawParams() != null && !request.getRawParams().isEmpty()) {
-            // 使用前端传递的所有URL参数(包括bd_vid等平台特定参数)
-            rawParams.putAll(request.getRawParams());
+        if (!Objects.equals(byTraceId.getAdvertiserId(), advertiserId)) {
+            log.info("落地页站点信息异常:{}---{}", byTraceId.getAdvertiserId(), advertiserId);
         }
-        lead.setRawParams(JSONUtil.toJsonStr(rawParams));
-
-        // 4. 获取客户端信息
+        byTraceId.setLandingPageRawParams(JSONUtil.toJsonStr(allParams));
+        byTraceId.setLandingPageTrigger(1);
+        byTraceId.setLandingPageTs(LocalDateTime.now());
+        byTraceId.setUpdateTime(LocalDateTime.now());
+        leadService.updateById(byTraceId);
+    }
 
-        // 5. 保存线索并触发转化事件
-        saveLeadAndTriggerConversion(lead);
+    private String getTraceIdByAdvertiser(AdvertiserTypeEnum byCode, Map<String, String> allParams) {
+        switch (byCode) {
+            case OCEANENGINE:
+                return allParams.get("click_id");
+            case TENCENT:
+                return allParams.get("click_id");
+            case OPPO:
+                return allParams.get("traceId");
+            case BAIDU:
+                return allParams.get("bdVid");
+            case VIVO:
+                return allParams.get("requestId");
+            case IQIYI:
+                return allParams.get("traceId");
+            default:
+                return null;
+        }
     }
 
     @Override
@@ -164,40 +112,19 @@ public class CallbackProcessingFacadeServiceImpl implements CallbackProcessingFa
 
     @Override
     public void gdtGetAuthCode(Integer code, Long state) {
-        if (code == null || state == null) {
+   /*     if (code == null || state == null) {
             return;
         }
         PromotionAccount byId = promotionAccountService.getById(state);
         if (byId == null) {
             return;
         }
-        IApiClient apiClient = handlerFactory.getApiClient(AdvertiserTypeEnum.GDT);
+        IApiClient apiClient = handlerFactory.getApiClient(AdvertiserTypeEnum.TENCENT);
         if (apiClient instanceof IAccessTokenClient) {
             IAccessTokenClient tokenClient = (IAccessTokenClient) apiClient;
             Map<String, String> accessToken = tokenClient.getAccessToken(code, byId.getAppId(), byId.getAppSecret(), byId.getCallbackUrl());
             byId.setAccessToken(accessToken.get("access_token"));
             byId.setRefreshToken(accessToken.get("refresh_token"));
-        }
-
+        }*/
     }
-
-    public void saveLeadAndTriggerConversion(Lead lead) {
-        // 1. 保存线索到数据库
-        boolean saved = leadService.save(lead);
-        if (!saved) {
-            log.error("线索保存失败 | phone={}", lead.getPhone());
-            throw new RuntimeException("线索保存失败");
-        }
-        // 2. 如果有点击ID和来源,触发转化事件
-        // 发布转化事件(会自动发送到MQ)
-        conversionEventPublisher.publishConversionEvent(
-                lead.getSiteId(),           // 站点ID
-                lead.getTraceId(),          // 点击ID
-                AdvertiserTypeEnum.getByCode(lead.getAdvertiserId()), // 广告商(BAIDU/OCEANENGINE/SINA/GDT)
-                ConversionTypeEnum.FORM_SUBMIT,              // 事件类型:提交表单
-                null,                       // 转化价值(可选)
-                lead.getId()                // 线索ID
-        );
-    }
-
 }

+ 50 - 41
fs-ad-new-api/src/main/java/com/fs/app/facade/ConversionServiceImpl.java

@@ -1,25 +1,27 @@
 package com.fs.app.facade;
 
+import cn.hutool.core.collection.CollUtil;
 import cn.hutool.json.JSONUtil;
-import com.fs.app.enums.AdvertiserTypeEnum;
-import com.fs.app.enums.ConversionTypeEnum;
+import com.fs.app.integration.adapter.IAdvertiserAdapter;
+import com.fs.newAdv.enums.AdvertiserTypeEnum;
+import com.fs.newAdv.enums.ConversionTypeEnum;
+import com.fs.newAdv.enums.event.SystemEventTypeEnum;
 import com.fs.app.integration.client.IApiClient;
 import com.fs.app.integration.factory.AdvertiserHandlerFactory;
 import com.fs.common.utils.RedisUtil;
 import com.fs.common.utils.SnowflakeUtil;
-import com.fs.newAdv.domain.ConversionLog;
-import com.fs.newAdv.domain.Lead;
-import com.fs.newAdv.domain.PromotionAccount;
-import com.fs.newAdv.domain.Site;
+import com.fs.newAdv.domain.*;
 import com.fs.newAdv.mapper.ConversionLogMapper;
 import com.fs.newAdv.mapper.ConversionTargetMapper;
 import com.fs.newAdv.service.*;
+import com.fs.newAdv.vo.ConversionEventVo;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
 import java.time.LocalDateTime;
 import java.util.HashMap;
+import java.util.List;
 import java.util.Map;
 
 /**
@@ -52,65 +54,72 @@ public class ConversionServiceImpl implements IConversionService {
     @Autowired
     private RedisUtil redisUtil;
 
-    @Autowired
-    private IClickTraceService clickTraceService;
     @Autowired
     private ILeadService leadService;
 
     @Override
-    public boolean reportToAdvertiser(AdvertiserTypeEnum advertiser, Long siteId, ConversionTypeEnum eventType, String traceId, Long leadId, Double value) {
-        log.info("开始回传转化数据:广告商={},站点ID={},点击ID={},事件类型={}",
-                advertiser, siteId, traceId, eventType);
-        // 广告商client
-        IApiClient apiClient = advertiserHandlerFactory.getApiClient(advertiser);
-        // 询站点信息
-        Site site = siteService.getById(siteId);
+    public boolean reportTrackingToAdvertiser(SystemEventTypeEnum systemEventTypeEnum, String traceId) {
+        // 线索信息
+        Lead lead = leadService.getByTraceId(traceId);
+        // 站点信息
+        Site site = siteService.getById(lead.getSiteId());
         if (site == null) {
-            log.error("站点不存在:{}", siteId);
+            log.error("站点不存在:{}", site);
+            return false;
+        }
+        // 查询回传信息
+        CallbackAccount callbackAccount = callbackAccountService.getById(site.getCallbackAccountId());
+        // 回传事件
+        List<ConversionEventVo> conversionEventVo = callbackAccount.getConversionEventVo();
+        if (CollUtil.isEmpty(conversionEventVo)){
+            log.error("回传事件不存在: {}",traceId);
             return false;
         }
 
-        // 查询回传账号
+        Integer advertiserEventType = conversionEventVo.stream()
+                .filter(item -> item.getSystemEventType().equals(systemEventTypeEnum.getCode()))
+                .findFirst()
+                .map(ConversionEventVo::getAdvertiserEventType)
+                .orElse(null);
+
+        if (advertiserEventType == null) {
+            log.error("回传事件未匹配: {}",traceId);
+            return false;
+        }
+
+        // 查询广告商账号
         PromotionAccount promotionAccount = promotionAccountService.getById(site.getPromotionAccountId());
         if (promotionAccount == null) {
             log.error("回传账号不存在:{}", site.getPromotionAccountId());
             return false;
         }
 
-        Lead lead = leadService.getById(leadId);
-        Map<String, Object> params = JSONUtil.toBean(lead.getRawParams(), Map.class);
+        Map<String, Object> params = JSONUtil.toBean(lead.getTraceRawParams(), Map.class);
         // 构建回传参数
         Map<String, Object> conversionData = new HashMap<>();
         // ------------------------------通用参数----------
-        conversionData.put("ownerId", promotionAccount.getAdAccountId());
-        conversionData.put("appId", promotionAccount.getAppId());
-        conversionData.put("appSecret", promotionAccount.getAppSecret());
-        conversionData.put("token", promotionAccount.getAccessToken());
-        conversionData.put("refreshToken", promotionAccount.getRefreshToken());
+        conversionData.put("adAccountId", callbackAccount.getAdAccountId());
+        conversionData.put("appId", callbackAccount.getAppId());
+        conversionData.put("appSecret", callbackAccount.getAppSecret());
+        conversionData.put("accessToken", callbackAccount.getAccessToken());
         conversionData.put("ip", lead.getIp());
-        conversionData.put("value", value);
-        // 链路唯一id
+        conversionData.put("scr_id", callbackAccount.getScrId());
         conversionData.put("traceId", traceId);
-        // 事件
-        conversionData.put("eventType", eventType.getAdvertiserType(advertiser));
+        conversionData.put("eventType", advertiserEventType);
         conversionData.put("timestamp", System.currentTimeMillis() / 1000);
-        // ------------------------------百度参数----------
-        // 百度落地页
-        conversionData.put("logidUrl", lead.getViewUrl());
-
-
-        // ------------------------------oppo参数----------
-        conversionData.put("tid", params.get("tid"));
-        conversionData.put("lbid", params.get("lbid"));
+        // 添加平台适应参数
+        IAdvertiserAdapter adapter = advertiserHandlerFactory.getAdapter(AdvertiserTypeEnum.getByCode(callbackAccount.getAdvertiserId()));
+        adapter.uploadConversionData(conversionData,params);
 
 
-        // 调用百度API回传
+        // 调用API回传
+        IApiClient apiClient = advertiserHandlerFactory.getApiClient(AdvertiserTypeEnum.getByCode(site.getAdvertiserId()));
         boolean b = apiClient.reportConversion(conversionData);
 
         // 保存转化日志(待回传状态)
         ConversionLog conversionLog = saveConversionLog(
-                siteId, site.getAdvertiserId(), site.getAdvertiserName(),
-                eventType, traceId, conversionData, b);
+                site.getId(), site.getAdvertiserId(), site.getAdvertiserName(),
+                systemEventTypeEnum, traceId, conversionData, b);
         return b;
     }
 
@@ -136,7 +145,7 @@ public class ConversionServiceImpl implements IConversionService {
      * 保存转化日志
      */
     private ConversionLog saveConversionLog(Long siteId, Long advertiserId,
-                                            String advertiserName, ConversionTypeEnum eventType,
+                                            String advertiserName, SystemEventTypeEnum eventType,
                                             String clickId,
                                             Map<String, Object> conversionData,
                                             boolean status) {
@@ -146,7 +155,7 @@ public class ConversionServiceImpl implements IConversionService {
         log.setAdvertiserId(advertiserId);
         log.setAdvertiserName(advertiserName);
         log.setConversionType(eventType.getCode());
-        log.setConversionEvent(eventType.getDesc());
+        log.setConversionEvent(eventType.getDescription());
         log.setCallbackParams(JSONUtil.toJsonStr(conversionData));
         log.setCallbackStatus(status ? 1 : 2);
         log.setRetryCount(0);

+ 5 - 6
fs-ad-new-api/src/main/java/com/fs/app/facade/IConversionService.java

@@ -1,7 +1,8 @@
 package com.fs.app.facade;
 
-import com.fs.app.enums.AdvertiserTypeEnum;
-import com.fs.app.enums.ConversionTypeEnum;
+import com.fs.newAdv.enums.AdvertiserTypeEnum;
+import com.fs.newAdv.enums.ConversionTypeEnum;
+import com.fs.newAdv.enums.event.SystemEventTypeEnum;
 
 /**
  * 转化回传服务接口
@@ -12,14 +13,12 @@ import com.fs.app.enums.ConversionTypeEnum;
  */
 public interface IConversionService {
     /**
-     * 回传转化数据到广告商
+     * 链化追踪回传转化数据到广告商
      *
-     * @param siteId 站点ID
      * @param eventType 事件类型
      * @param traceId 点击ID(广告平台提供)
-     * @param value 转化价值
      * @return 是否成功
      */
-    boolean reportToAdvertiser(AdvertiserTypeEnum advertiser,Long siteId, ConversionTypeEnum eventType, String traceId, Long leadId, Double value);
+    boolean reportTrackingToAdvertiser(SystemEventTypeEnum eventType, String traceId);
 }
 

+ 32 - 31
fs-ad-new-api/src/main/java/com/fs/app/integration/adapter/BaiduAdapter.java

@@ -1,12 +1,13 @@
 package com.fs.app.integration.adapter;
 
-import cn.hutool.core.map.MapUtil;
-
-import com.fs.app.enums.AdvertiserTypeEnum;
+import com.fs.newAdv.domain.Lead;
+import com.fs.newAdv.enums.AdvertiserTypeEnum;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.stereotype.Component;
 
-import java.util.HashMap;
+import java.time.Instant;
+import java.time.LocalDateTime;
+import java.time.ZoneId;
 import java.util.Map;
 
 /**
@@ -19,41 +20,41 @@ import java.util.Map;
 @Component
 public class BaiduAdapter implements IAdvertiserAdapter {
 
+    /**
+     * https://dev2.baidu.com/content?sceneType=0&pageId=103228&nodeId=769
+     *
+     * @param rawData 原始数据
+     * @return
+     */
     @Override
-    public Map<String, Object> adaptCallbackData(Map<String, Object> rawData) {
+    public Lead adaptCallbackData(Map<String, String> rawData) {
         log.info("百度数据适配:{}", rawData);
-
-        Map<String, Object> result = new HashMap<>();
-
-        // 百度字段映射
-        result.put("advertiserType", getAdvertiserType());
-        result.put("clickId", MapUtil.getStr(rawData, "clk_id"));
-        result.put("siteId", MapUtil.getLong(rawData, "site_id"));
-        result.put("impressionCount", MapUtil.getLong(rawData, "show"));
-        result.put("clickCount", MapUtil.getLong(rawData, "click"));
-        result.put("cost", MapUtil.getDouble(rawData, "cost"));
-
-        return result;
+        Lead lead = new Lead();
+        lead.setTraceId(rawData.get("bd_vid"));
+        lead.setAdvertiserId(AdvertiserTypeEnum.BAIDU.getCode());
+        lead.setIp(rawData.get("ip"));
+        lead.setIdeaId(rawData.get("aid"));
+        lead.setPlanId(rawData.get("pid"));
+        lead.setUnitId(rawData.get("uid"));
+        lead.setAdAccountId(rawData.get("userid"));
+        try {
+            lead.setClickTs(LocalDateTime.ofInstant(
+                    Instant.ofEpochMilli(Long.parseLong(rawData.get("ts"))),
+                    ZoneId.systemDefault()));
+        } catch (Exception e) {
+            log.error("时间转换异常:", e);
+        }
+        return lead;
     }
 
     @Override
-    public Map<String, Object> adaptApiResponse(Map<String, Object> rawData) {
-        log.info("百度API响应适配:{}", rawData);
-
-        Map<String, Object> result = new HashMap<>();
-
-        // 适配API返回的统计数据
-        result.put("impressionCount", MapUtil.getLong(rawData, "impression"));
-        result.put("clickCount", MapUtil.getLong(rawData, "click"));
-        result.put("cost", MapUtil.getDouble(rawData, "cost"));
-        result.put("avgClickPrice", MapUtil.getDouble(rawData, "acp"));
-
-        return result;
+    public AdvertiserTypeEnum getAdvertiserType() {
+        return AdvertiserTypeEnum.BAIDU;
     }
 
     @Override
-    public AdvertiserTypeEnum getAdvertiserType() {
-        return AdvertiserTypeEnum.BAIDU;
+    public void uploadConversionData(Map<String, Object> conversionData, Map<String, Object> params) {
+        conversionData.put("logidUrl",params.get("logidUrl"));
     }
 }
 

+ 9 - 9
fs-ad-new-api/src/main/java/com/fs/app/integration/adapter/IAdvertiserAdapter.java

@@ -1,6 +1,7 @@
 package com.fs.app.integration.adapter;
 
-import com.fs.app.enums.AdvertiserTypeEnum;
+import com.fs.newAdv.enums.AdvertiserTypeEnum;
+import com.fs.newAdv.domain.Lead;
 
 import java.util.Map;
 
@@ -20,19 +21,18 @@ public interface IAdvertiserAdapter {
      * @param rawData 原始数据
      * @return 统一格式数据
      */
-    Map<String, Object> adaptCallbackData(Map<String, Object> rawData);
+    Lead adaptCallbackData(Map<String,String> rawData);
 
     /**
-     * 适配API响应数据
-     *
-     * @param rawData 原始数据
-     * @return 统一格式数据
+     * 获取广告商类型
      */
-    Map<String, Object> adaptApiResponse(Map<String, Object> rawData);
+    AdvertiserTypeEnum getAdvertiserType();
 
     /**
-     * 获取广告商类型
+     * 适配转化归因参数
+     * @param conversionData
+     * @param params
      */
-    AdvertiserTypeEnum getAdvertiserType();
+    void uploadConversionData(Map<String, Object> conversionData, Map<String, Object> params);
 }
 

+ 70 - 0
fs-ad-new-api/src/main/java/com/fs/app/integration/adapter/OPPOAdapter.java

@@ -0,0 +1,70 @@
+package com.fs.app.integration.adapter;
+
+import cn.hutool.core.util.StrUtil;
+import com.fs.newAdv.domain.Lead;
+import com.fs.newAdv.enums.AdvertiserTypeEnum;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Component;
+
+import java.time.Instant;
+import java.time.LocalDateTime;
+import java.time.ZoneId;
+import java.util.Map;
+
+/**
+ * 百度广告适配器
+ *
+ * @author zhangqin
+ * @date 2025-11-03
+ */
+@Slf4j
+@Component
+public class OPPOAdapter implements IAdvertiserAdapter {
+
+    /**
+     * https://datanexus.qq.com/doc/develop/guider/interface/conversion/ad_track_click
+     *
+     * @param rawData 原始数据
+     * @return
+     */
+    @Override
+    public Lead adaptCallbackData(Map<String, String> rawData) {
+        log.info("腾讯数据适配:{}", rawData);
+        Lead lead = new Lead();
+        lead.setTraceId(rawData.get("request_id"));
+        lead.setAdvertiserId(AdvertiserTypeEnum.TENCENT.getCode());
+        lead.setIp(rawData.get("ip"));
+        if (StrUtil.isNotEmpty(rawData.get("dynamic_creative_id"))){
+            lead.setIdeaId(rawData.get("dynamic_creative_id"));
+        }else {
+            lead.setIdeaId(rawData.get("smart_dynamic_creative_id"));
+        }
+        if (StrUtil.isNotEmpty(rawData.get("project_id"))){
+            lead.setPlanId(rawData.get("project_id"));
+        }else {
+            lead.setPlanId(rawData.get("smart_project_id"));
+        }
+        lead.setAdAccountId(rawData.get("account_id"));
+        try {
+            lead.setClickTs(LocalDateTime.ofInstant(
+                    Instant.ofEpochMilli(Long.parseLong(rawData.get("click_time"))),
+                    ZoneId.systemDefault()));
+        } catch (Exception e) {
+            log.error("时间转换异常:", e);
+        }
+        return lead;
+    }
+
+    @Override
+    public AdvertiserTypeEnum getAdvertiserType() {
+        return AdvertiserTypeEnum.OPPO;
+    }
+
+    @Override
+    public void uploadConversionData(Map<String, Object> conversionData, Map<String, Object> params) {
+        // ------------------------------oppo参数----------
+        conversionData.put("tid", params.get("tid"));
+        conversionData.put("lbid", params.get("lbid"));
+    }
+}
+

+ 41 - 29
fs-ad-new-api/src/main/java/com/fs/app/integration/adapter/OceanEngineAdapter.java

@@ -1,12 +1,14 @@
 package com.fs.app.integration.adapter;
 
-import cn.hutool.core.map.MapUtil;
-
-import com.fs.app.enums.AdvertiserTypeEnum;
+import cn.hutool.core.util.StrUtil;
+import com.fs.newAdv.domain.Lead;
+import com.fs.newAdv.enums.AdvertiserTypeEnum;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.stereotype.Component;
 
-import java.util.HashMap;
+import java.time.Instant;
+import java.time.LocalDateTime;
+import java.time.ZoneId;
 import java.util.Map;
 
 /**
@@ -19,40 +21,50 @@ import java.util.Map;
 @Component
 public class OceanEngineAdapter implements IAdvertiserAdapter {
 
+    /**
+     * https://open.oceanengine.com/labels/7/docs/1696710655781900
+     *
+     * @param rawData
+     * @return
+     */
     @Override
-    public Map<String, Object> adaptCallbackData(Map<String, Object> rawData) {
+    public Lead adaptCallbackData(Map<String, String> rawData) {
         log.info("巨量引擎数据适配:{}", rawData);
+        Lead lead = new Lead();
+        lead.setTraceId(rawData.get("track_id"));
+        lead.setAdvertiserId(AdvertiserTypeEnum.OCEANENGINE.getCode());
+        if (StrUtil.isNotEmpty(rawData.get("cid"))) {
+            lead.setIdeaId(rawData.get("cid"));
+        } else {
+            lead.setIdeaId(rawData.get("promotion_id"));
+        }
 
-        Map<String, Object> result = new HashMap<>();
-
-        // 巨量引擎字段映射
-        result.put("advertiserType", getAdvertiserType());
-        result.put("clickId", MapUtil.getStr(rawData, "clickid"));
-        result.put("siteId", MapUtil.getLong(rawData, "site_id"));
-        result.put("impressionCount", MapUtil.getLong(rawData, "show"));
-        result.put("clickCount", MapUtil.getLong(rawData, "click"));
-        result.put("cost", MapUtil.getDouble(rawData, "cost"));
-
-        return result;
+        if (StrUtil.isNotEmpty(rawData.get("aid"))) {
+            lead.setPlanId(rawData.get("aid"));
+        } else {
+            lead.setIdeaId(rawData.get("project_id"));
+        }
+        lead.setUnitId(rawData.get("campaign_id"));
+        lead.setAdAccountId(rawData.get("userid"));
+        lead.setIp(rawData.get("ip"));
+        try {
+            lead.setClickTs(LocalDateTime.ofInstant(
+                    Instant.ofEpochMilli(Long.parseLong(rawData.get("ts"))),
+                    ZoneId.systemDefault()));
+        } catch (Exception e) {
+            log.error("时间转换异常:", e);
+        }
+        return lead;
     }
 
     @Override
-    public Map<String, Object> adaptApiResponse(Map<String, Object> rawData) {
-        log.info("巨量引擎API响应适配:{}", rawData);
-
-        Map<String, Object> result = new HashMap<>();
-
-        result.put("impressionCount", MapUtil.getLong(rawData, "stat_cost"));
-        result.put("clickCount", MapUtil.getLong(rawData, "click"));
-        result.put("cost", MapUtil.getDouble(rawData, "cost"));
-        result.put("avgClickPrice", MapUtil.getDouble(rawData, "avg_show_cost"));
-
-        return result;
+    public AdvertiserTypeEnum getAdvertiserType() {
+        return AdvertiserTypeEnum.OCEANENGINE;
     }
 
     @Override
-    public AdvertiserTypeEnum getAdvertiserType() {
-        return AdvertiserTypeEnum.OCEANENGINE;
+    public void uploadConversionData(Map<String, Object> conversionData, Map<String, Object> params) {
+
     }
 }
 

+ 67 - 0
fs-ad-new-api/src/main/java/com/fs/app/integration/adapter/TencentAdapter.java

@@ -0,0 +1,67 @@
+package com.fs.app.integration.adapter;
+
+import cn.hutool.core.util.StrUtil;
+import com.fs.newAdv.domain.Lead;
+import com.fs.newAdv.enums.AdvertiserTypeEnum;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Component;
+
+import java.time.Instant;
+import java.time.LocalDateTime;
+import java.time.ZoneId;
+import java.util.Map;
+
+/**
+ * 腾讯广告适配器
+ *
+ * @author zhangqin
+ */
+@Slf4j
+@Component
+public class TencentAdapter implements IAdvertiserAdapter {
+
+    /**
+     * https://datanexus.qq.com/doc/develop/guider/interface/conversion/ad_track_click
+     *
+     * @param rawData 原始数据
+     * @return
+     */
+    @Override
+    public Lead adaptCallbackData(Map<String, String> rawData) {
+        log.info("腾讯数据适配:{}", rawData);
+        Lead lead = new Lead();
+        lead.setTraceId(rawData.get("request_id"));
+        lead.setAdvertiserId(AdvertiserTypeEnum.TENCENT.getCode());
+        lead.setIp(rawData.get("ip"));
+        if (StrUtil.isNotEmpty(rawData.get("dynamic_creative_id"))){
+            lead.setIdeaId(rawData.get("dynamic_creative_id"));
+        }else {
+            lead.setIdeaId(rawData.get("smart_dynamic_creative_id"));
+        }
+        if (StrUtil.isNotEmpty(rawData.get("project_id"))){
+            lead.setPlanId(rawData.get("project_id"));
+        }else {
+            lead.setPlanId(rawData.get("smart_project_id"));
+        }
+        lead.setAdAccountId(rawData.get("account_id"));
+        try {
+            lead.setClickTs(LocalDateTime.ofInstant(
+                    Instant.ofEpochMilli(Long.parseLong(rawData.get("click_time"))),
+                    ZoneId.systemDefault()));
+        } catch (Exception e) {
+            log.error("时间转换异常:", e);
+        }
+        return lead;
+    }
+
+    @Override
+    public AdvertiserTypeEnum getAdvertiserType() {
+        return AdvertiserTypeEnum.TENCENT;
+    }
+
+    @Override
+    public void uploadConversionData(Map<String, Object> conversionData, Map<String, Object> params) {
+        conversionData.put("callBackUrl", params.get("callBackUrl"));
+    }
+}
+

+ 63 - 0
fs-ad-new-api/src/main/java/com/fs/app/integration/adapter/VIVOAdapter.java

@@ -0,0 +1,63 @@
+package com.fs.app.integration.adapter;
+
+import cn.hutool.core.util.StrUtil;
+import com.fs.newAdv.domain.Lead;
+import com.fs.newAdv.enums.AdvertiserTypeEnum;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Component;
+
+import java.time.Instant;
+import java.time.LocalDateTime;
+import java.time.ZoneId;
+import java.util.Map;
+
+/**
+ * 百度广告适配器
+ *
+ * @author zhangqin
+ * @date 2025-11-03
+ */
+@Slf4j
+@Component
+public class VIVOAdapter implements IAdvertiserAdapter {
+
+    /**
+     * https://datanexus.qq.com/doc/develop/guider/interface/conversion/ad_track_click
+     *
+     * @param rawData 原始数据
+     * @return
+     */
+    @Override
+    public Lead adaptCallbackData(Map<String, String> rawData) {
+        log.info("VIVO适配:{}", rawData);
+        Lead lead = new Lead();
+        lead.setTraceId(rawData.get("requestId"));
+        lead.setAdvertiserId(AdvertiserTypeEnum.VIVO.getCode());
+        lead.setIp(rawData.get("ip"));
+        lead.setIdeaId(rawData.get("creativeId"));
+        lead.setPlanId(rawData.get("campaignId"));
+        lead.setUnitId(rawData.get("adId"));
+        lead.setAdAccountId(rawData.get("advertiserId"));
+        try {
+            lead.setClickTs(LocalDateTime.ofInstant(
+                    Instant.ofEpochMilli(Long.parseLong(rawData.get("ts"))),
+                    ZoneId.systemDefault()));
+        } catch (Exception e) {
+            log.error("时间转换异常:", e);
+        }
+        return lead;
+    }
+
+    @Override
+    public AdvertiserTypeEnum getAdvertiserType() {
+        return AdvertiserTypeEnum.VIVO;
+    }
+
+    @Override
+    public void uploadConversionData(Map<String, Object> conversionData, Map<String, Object> params) {
+        // ------------------------------VIVO----------
+        conversionData.put("requestId", params.get("requestId"));
+        conversionData.put("creativeId", params.get("creativeId"));
+    }
+}
+

+ 3 - 3
fs-ad-new-api/src/main/java/com/fs/app/integration/client/AbstractApiClient.java

@@ -4,7 +4,7 @@ import cn.hutool.core.util.ObjectUtil;
 import cn.hutool.core.util.StrUtil;
 import cn.hutool.http.HttpResponse;
 import cn.hutool.json.JSONUtil;
-import com.fs.app.enums.AdvertiserTypeEnum;
+import com.fs.newAdv.enums.AdvertiserTypeEnum;
 import com.fs.newAdv.service.IApiCallLogService;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -21,7 +21,7 @@ public abstract class AbstractApiClient implements IApiClient {
     /**
      * 构建上下文信息 (traceId, userId等)
      */
-    protected abstract String buildConversionParams(Map<String, Object> conversionData);
+    protected abstract Map<String, Object> buildConversionParams(Map<String, Object> conversionData);
 
     /**
      * 统一封装API调用日志和异常处理逻辑
@@ -41,7 +41,7 @@ public abstract class AbstractApiClient implements IApiClient {
         }
         if (StrUtil.isNotEmpty(responseBody)) {
             Integer code = JSONUtil.parseObj(responseBody).getInt("code");
-            if (ObjectUtil.isNotEmpty(code) && code == 0) {
+            if (ObjectUtil.isNotEmpty(code) && (code == 0 || code == 200)) {
                 callStatus = true;
             }
         }

+ 1 - 1
fs-ad-new-api/src/main/java/com/fs/app/integration/client/IApiClient.java

@@ -1,6 +1,6 @@
 package com.fs.app.integration.client;
 
-import com.fs.app.enums.AdvertiserTypeEnum;
+import com.fs.newAdv.enums.AdvertiserTypeEnum;
 
 import java.util.Map;
 

+ 7 - 98
fs-ad-new-api/src/main/java/com/fs/app/integration/client/advertiser/BaiduApiClient.java

@@ -3,7 +3,7 @@ package com.fs.app.integration.client.advertiser;
 import cn.hutool.core.util.StrUtil;
 import cn.hutool.http.HttpRequest;
 import cn.hutool.json.JSONUtil;
-import com.fs.app.enums.AdvertiserTypeEnum;
+import com.fs.newAdv.enums.AdvertiserTypeEnum;
 import com.fs.app.integration.client.AbstractApiClient;
 import com.fs.common.constant.SystemConstant;
 import com.fs.common.exception.ThirdPartyException;
@@ -41,10 +41,12 @@ public class BaiduApiClient extends AbstractApiClient {
     @Override
     public boolean reportConversion(Map<String, Object> conversionData) {
         return executeWithLog(AdvertiserTypeEnum.OCEANENGINE, CONVERSION_API_URL, conversionData, () -> {
+            // 构建请求参数
+            Map<String, Object> stringObjectMap = buildConversionParams(conversionData);
             // 发送HTTP请求
             return HttpRequest.post(CONVERSION_API_URL)
                     .header("Content-Type", "application/json")
-                    .body(buildConversionParams(conversionData))
+                    .body(JSONUtil.toJsonStr(stringObjectMap))
                     .timeout(SystemConstant.API_TIMEOUT)
                     .execute();
         });
@@ -56,11 +58,11 @@ public class BaiduApiClient extends AbstractApiClient {
      * @param conversionData 转化数据
      * @return 请求参数
      */
-    protected String buildConversionParams(Map<String, Object> conversionData) {
+    protected Map<String, Object> buildConversionParams(Map<String, Object> conversionData) {
         Map<String, Object> params = new HashMap<>();
 
         // 必填参数
-        String token = (String) conversionData.get("token");
+        String token = (String) conversionData.get("accessToken");
         if (StrUtil.isBlank(token)) {
             throw new ThirdPartyException("token不能为空");
         }
@@ -95,102 +97,9 @@ public class BaiduApiClient extends AbstractApiClient {
         conversionList.add(conversion);
         params.put("conversionTypes", conversionList);
 
-        return JSONUtil.toJsonStr(params);
+        return params;
     }
 
-    /*  *//**
-     * 获取访问令牌(百度OAuth2.0)
-     *
-     * @param apiKey    API Key
-     * @param secretKey Secret Key
-     * @return 访问令牌
-     *//*
-    public String getAccessToken(String apiKey, String secretKey) {
-        log.info("开始获取百度AccessToken");
-
-        try {
-            String url = TOKEN_API_URL +
-                    "?grant_type=client_credentials" +
-                    "&client_id=" + apiKey +
-                    "&client_secret=" + secretKey;
-
-            String response = HttpRequest.get(url)
-                    .timeout(SystemConstant.API_TIMEOUT)
-                    .execute()
-                    .body();
-
-            JSONObject result = JSONUtil.parseObj(response);
-
-            if (result.containsKey("access_token")) {
-                String accessToken = result.getStr("access_token");
-                log.info("获取百度AccessToken成功");
-                return accessToken;
-            } else {
-                String error = result.getStr("error_description", "未知错误");
-                throw new ThirdPartyException("获取百度AccessToken失败:" + error);
-            }
-
-        } catch (Exception e) {
-            log.error("获取百度AccessToken异常", e);
-            throw new ThirdPartyException("获取AccessToken异常:" + e.getMessage(), e);
-        }
-    }*/
-
-    /*    */
-
-    /**
-     * 查询账户报告数据
-     *
-     * @param accessToken 访问令牌
-     * @param startDate   开始日期(yyyyMMdd)
-     * @param endDate     结束日期(yyyyMMdd)
-     * @return 报告数据
-     *//*
-    public Map<String, Object> getAccountReport(String accessToken, String startDate, String endDate) {
-        log.info("查询百度账户报告:{}到{}", startDate, endDate);
-
-        String apiUrl = "https://api.baidu.com/json/sms/service/KR2Service/getReportId";
-
-        try {
-            Map<String, Object> params = new HashMap<>();
-            params.put("performanceData", new String[]{"impression", "click", "cost"});
-            params.put("startDate", startDate);
-            params.put("endDate", endDate);
-            params.put("levelOfDetails", "account");
-
-            Map<String, Object> header = new HashMap<>();
-            header.put("token", accessToken);
-
-            Map<String, Object> body = new HashMap<>();
-            body.put("header", header);
-            body.put("body", params);
-
-            String response = HttpRequest.post(apiUrl)
-                    .header("Content-Type", "application/json")
-                    .body(JSONUtil.toJsonStr(body))
-                    .timeout(SystemConstant.API_TIMEOUT)
-                    .execute()
-                    .body();
-
-            JSONObject result = JSONUtil.parseObj(response);
-
-            if (result.containsKey("header")) {
-                JSONObject resHeader = result.getJSONObject("header");
-                Integer status = resHeader.getInt("status");
-
-                if (status != null && status == 0) {
-                    return result.getJSONObject("body");
-                }
-            }
-
-            log.error("查询百度报告失败:{}", response);
-            throw new ThirdPartyException("查询百度报告失败");
-
-        } catch (Exception e) {
-            log.error("查询百度账户报告异常", e);
-            throw new ThirdPartyException("查询报告异常:" + e.getMessage(), e);
-        }
-    }*/
     @Override
     public AdvertiserTypeEnum getAdvertiserType() {
         return AdvertiserTypeEnum.BAIDU;

+ 70 - 0
fs-ad-new-api/src/main/java/com/fs/app/integration/client/advertiser/IQIYIApiClient.java

@@ -0,0 +1,70 @@
+package com.fs.app.integration.client.advertiser;
+
+import cn.hutool.http.HttpRequest;
+import com.fs.app.integration.client.AbstractApiClient;
+import com.fs.common.constant.SystemConstant;
+import com.fs.newAdv.enums.AdvertiserTypeEnum;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Component;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * 爱奇艺API客户端
+ *
+ * @author zhangqin
+ * @see <a href="https://iq.feishu.cn/wiki/YbDzwp0K3iy5IOkLHjGcBKcxnBc">爱奇艺 API文档</a>
+ */
+@Slf4j
+@Component
+public class IQIYIApiClient extends AbstractApiClient {
+
+    /**
+     * 爱奇艺 回传API地址
+     */
+    private static final String CONVERSION_API_URL = "http://tc.cupid.iqiyi.com/dsp_lpapi";
+
+    /**
+     * 回传转化数据到爱奇艺
+     *
+     * @param conversionData 转化数据
+     * @return 是否成功
+     */
+    @Override
+    public boolean reportConversion(Map<String, Object> conversionData) {
+        return executeWithLog(AdvertiserTypeEnum.OCEANENGINE, CONVERSION_API_URL, conversionData, () -> {
+            // 构建请求参数
+            Map<String, Object> body = buildConversionParams(conversionData);
+            // 发送HTTP请求
+            return HttpRequest.get(CONVERSION_API_URL)
+                    .form(body)
+                    .timeout(SystemConstant.API_TIMEOUT)
+                    .execute();
+        });
+    }
+
+    /**
+     * 构建转化回传参数
+     *
+     * @param conversionData 转化数据
+     * @return 请求参数
+     */
+    protected Map<String, Object> buildConversionParams(Map<String, Object> conversionData) {
+        Map<String, Object> params = new HashMap<>();
+        // 必填参数
+        params.put("impress_id", conversionData.get("traceId"));
+        params.put("event_type", conversionData.get("eventType"));
+        // 转化价值(可选)
+        if (conversionData.containsKey("value")) {
+            params.put("pmao", conversionData.get("value"));
+        }
+        return params;
+    }
+
+    @Override
+    public AdvertiserTypeEnum getAdvertiserType() {
+        return AdvertiserTypeEnum.IQIYI;
+    }
+}
+

+ 11 - 22
fs-ad-new-api/src/main/java/com/fs/app/integration/client/advertiser/OPPOApiClient.java

@@ -1,26 +1,16 @@
 package com.fs.app.integration.client.advertiser;
 
 import cn.hutool.core.codec.Base64;
-import cn.hutool.crypto.digest.MD5;
 import cn.hutool.http.HttpRequest;
-import cn.hutool.http.HttpResponse;
-import cn.hutool.json.JSONObject;
 import cn.hutool.json.JSONUtil;
-import com.fs.ad.yk.utils.Md5Util;
-import com.fs.app.enums.AdvertiserTypeEnum;
+import com.fs.newAdv.enums.AdvertiserTypeEnum;
 import com.fs.app.integration.client.AbstractApiClient;
-import com.fs.app.integration.client.IAccessTokenClient;
 import com.fs.common.constant.SystemConstant;
-import com.fs.common.utils.SnowflakeUtil;
-import com.fs.newAdv.service.IApiCallLogService;
 import lombok.extern.slf4j.Slf4j;
 import me.chanjar.weixin.common.util.crypto.SHA1;
-import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Component;
 
-import java.util.ArrayList;
 import java.util.HashMap;
-import java.util.List;
 import java.util.Map;
 
 /**
@@ -33,7 +23,7 @@ import java.util.Map;
  */
 @Slf4j
 @Component
-public class OPPOApiClient extends AbstractApiClient  {
+public class OPPOApiClient extends AbstractApiClient {
 
     /**
      * 巨量引擎转化回传API地址
@@ -49,20 +39,20 @@ public class OPPOApiClient extends AbstractApiClient  {
      */
     @Override
     public boolean reportConversion(Map<String, Object> conversionData) {
-        return executeWithLog(AdvertiserTypeEnum.OPPO,CONVERSION_API_URL, conversionData, () -> {
+        return executeWithLog(AdvertiserTypeEnum.OPPO, CONVERSION_API_URL, conversionData, () -> {
             // 构建请求参数
-            String requestBody = buildConversionParams(conversionData);
+            Map<String, Object> requestBody = buildConversionParams(conversionData);
             Long timestamp = (Long) conversionData.get("timestamp");
             String ownerId = (String) conversionData.get("ownerId");
             String appId = (String) conversionData.get("appId");
             String appKey = (String) conversionData.get("appKey");
-            String sign = SHA1.gen(appId+appKey+timestamp);
-            String token = Base64.encode(ownerId+","+appId+","+timestamp+","+sign);
+            String sign = SHA1.gen(appId + appKey + timestamp);
+            String token = Base64.encode(ownerId + "," + appId + "," + timestamp + "," + sign);
             // 发送HTTP请求
             return HttpRequest.post(CONVERSION_API_URL)
                     .header("Content-Type", "application/json")
-                    .header("Authorization","Bearer  "+token)
-                    .body(requestBody)
+                    .header("Authorization", "Bearer  " + token)
+                    .body(JSONUtil.toJsonStr(requestBody))
                     .timeout(SystemConstant.API_TIMEOUT)
                     .execute();
         });
@@ -74,13 +64,13 @@ public class OPPOApiClient extends AbstractApiClient  {
      * @param conversionData 转化数据
      * @return 请求参数
      */
-    protected  String buildConversionParams(Map<String, Object> conversionData) {
+    protected Map<String, Object> buildConversionParams(Map<String, Object> conversionData) {
         Map<String, Object> params = new HashMap<>();
 
         // 落地页Id:投放广告到投放
         params.put("pageId", conversionData.get("traceId"));
         // 广告主id:对应广告主自提供
-        params.put("ownerId", conversionData.get("ownerId"));
+        params.put("adAccountId", conversionData.get("adAccountId"));
         // 用户IP:广告主收集
         // params.put("ip", conversionData.get("ip"));
         params.put("ip", "192.168.1.1");
@@ -90,11 +80,10 @@ public class OPPOApiClient extends AbstractApiClient  {
         params.put("lbid ", conversionData.get("lbid"));
         // 事件
         params.put("transformType ", conversionData.get("eventType"));
-        return JSONUtil.toJsonStr(params);
+        return params;
     }
 
 
-
     @Override
     public AdvertiserTypeEnum getAdvertiserType() {
         return AdvertiserTypeEnum.OPPO;

+ 11 - 27
fs-ad-new-api/src/main/java/com/fs/app/integration/client/advertiser/OceanEngineApiClient.java

@@ -2,17 +2,12 @@ package com.fs.app.integration.client.advertiser;
 
 import cn.hutool.core.util.StrUtil;
 import cn.hutool.http.HttpRequest;
-import cn.hutool.http.HttpResponse;
-import cn.hutool.json.JSONObject;
 import cn.hutool.json.JSONUtil;
-import com.fs.app.enums.AdvertiserTypeEnum;
 import com.fs.app.integration.client.AbstractApiClient;
 import com.fs.common.constant.SystemConstant;
 import com.fs.common.exception.ThirdPartyException;
-import com.fs.common.utils.SnowflakeUtil;
-import com.fs.newAdv.service.IApiCallLogService;
+import com.fs.newAdv.enums.AdvertiserTypeEnum;
 import lombok.extern.slf4j.Slf4j;
-import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Component;
 
 import java.util.HashMap;
@@ -33,7 +28,7 @@ public class OceanEngineApiClient extends AbstractApiClient {
     /**
      * 巨量引擎转化回传API地址
      */
-    private static final String CONVERSION_API_URL = "https://ad.oceanengine.com/open_api/2/conversion/";
+    private static final String CONVERSION_API_URL = "https://ad.oceanengine.com/track/activate";
 
     /**
      * 回传转化数据到巨量引擎
@@ -43,14 +38,12 @@ public class OceanEngineApiClient extends AbstractApiClient {
      */
     @Override
     public boolean reportConversion(Map<String, Object> conversionData) {
-        return executeWithLog(AdvertiserTypeEnum.OCEANENGINE,CONVERSION_API_URL, conversionData, () -> {
+        return executeWithLog(AdvertiserTypeEnum.OCEANENGINE, CONVERSION_API_URL, conversionData, () -> {
             // 构建请求参数
-            String requestBody = buildConversionParams(conversionData);
+            Map<String, Object> requestBody = buildConversionParams(conversionData);
             // 发送HTTP请求
-            return HttpRequest.post(CONVERSION_API_URL)
-                    .header("Access-Token", (String) conversionData.get("token"))
-                    .header("Content-Type", "application/json")
-                    .body(requestBody)
+            return HttpRequest.get(CONVERSION_API_URL)
+                    .form(JSONUtil.toJsonStr(requestBody))
                     .timeout(SystemConstant.API_TIMEOUT)
                     .execute();
         });
@@ -62,23 +55,14 @@ public class OceanEngineApiClient extends AbstractApiClient {
      * @param conversionData 转化数据
      * @return 请求参数
      */
-    protected String buildConversionParams(Map<String, Object> conversionData) {
+    protected Map<String, Object> buildConversionParams(Map<String, Object> conversionData) {
         Map<String, Object> params = new HashMap<>();
 
         // 必填参数
-        params.put("event_type", conversionData.get("eventType")); // 转化类型
-        params.put("context", buildContext(conversionData)); // 上下文信息
-
-        // 可选参数
-        if (conversionData.containsKey("value")) {
-            params.put("value", conversionData.get("value")); // 转化价值
-        }
-
-        if (conversionData.containsKey("description")) {
-            params.put("description", conversionData.get("description")); // 描述
-        }
-
-        return JSONUtil.toJsonStr(params);
+        params.put("event_type", conversionData.get("eventType"));
+        params.put("callback", conversionData.get("traceId"));
+        params.put("conv_time", conversionData.get("timestamp"));
+        return params;
     }
 
     /**

+ 15 - 20
fs-ad-new-api/src/main/java/com/fs/app/integration/client/advertiser/GDTApiClient.java → fs-ad-new-api/src/main/java/com/fs/app/integration/client/advertiser/TencentApiClient.java

@@ -4,7 +4,7 @@ import cn.hutool.http.HttpRequest;
 import cn.hutool.http.HttpResponse;
 import cn.hutool.json.JSONObject;
 import cn.hutool.json.JSONUtil;
-import com.fs.app.enums.AdvertiserTypeEnum;
+import com.fs.newAdv.enums.AdvertiserTypeEnum;
 import com.fs.app.integration.client.AbstractApiClient;
 import com.fs.app.integration.client.IAccessTokenClient;
 import com.fs.common.constant.SystemConstant;
@@ -19,19 +19,15 @@ import java.util.Map;
 
 /**
  * 腾讯广点通API客户端
- * 用于调用巨量引擎的API接口(转化回传等)
  *
  * @author zhangqin
  * @date 2025-11-03
- * @see <a href="https://developers.e.qq.com/v3.0/docs/api/leads_action_type_report/add">巨量引擎API文档</a>
+ * @see <a https://datanexus.qq.com/doc/develop/guider/interface/conversion/trackingcgi_api_miniprogram"></a>
  */
 @Slf4j
 @Component
-public class GDTApiClient extends AbstractApiClient implements IAccessTokenClient {
+public class TencentApiClient extends AbstractApiClient implements IAccessTokenClient {
 
-    /**
-     * 巨量引擎转化回传API地址
-     */
     private static final String CONVERSION_API_URL = "https://api.e.qq.com/user_actions/add";
 
     /**
@@ -42,13 +38,15 @@ public class GDTApiClient extends AbstractApiClient implements IAccessTokenClien
      */
     @Override
     public boolean reportConversion(Map<String, Object> conversionData) {
-        return executeWithLog(AdvertiserTypeEnum.OCEANENGINE,CONVERSION_API_URL, conversionData, () -> {
+        return executeWithLog(AdvertiserTypeEnum.OCEANENGINE, CONVERSION_API_URL, conversionData, () -> {
+            // 构建请求参数
+            Map<String, Object> stringObjectMap = buildConversionParams(conversionData);
             // 发送HTTP请求
             return HttpRequest.post(CONVERSION_API_URL)
-                    .form("access_token", conversionData.get("timestamp"))
+                    .header("access_token", (String) conversionData.get("accessToken"))
                     .form("timestamp", conversionData.get("timestamp"))
                     .form("nonce", SnowflakeUtil.nextIdStr())
-                    .body(buildConversionParams(conversionData))
+                    .body(JSONUtil.toJsonStr(stringObjectMap))
                     .timeout(SystemConstant.API_TIMEOUT)
                     .execute();
         });
@@ -60,33 +58,30 @@ public class GDTApiClient extends AbstractApiClient implements IAccessTokenClien
      * @param conversionData 转化数据
      * @return 请求参数
      */
-    protected String buildConversionParams(Map<String, Object> conversionData) {
+    protected Map<String, Object> buildConversionParams(Map<String, Object> conversionData) {
         Map<String, Object> params = new HashMap<>();
-
-        // 必填参数
-        params.put("account_id", conversionData.get("account_id")); // 转化类型
-        params.put("user_action_set_id", conversionData.get("user_action_set_id")); // 上下文信息
-
+        params.put("account_id", conversionData.get("adAccountId"));
+        params.put("user_action_set_id", conversionData.get("scr_id"));
         List<Map<String, Object>> actionsList = new ArrayList<>();
         Map<String, Object> actions = new HashMap<>();
         params.put("actions", actionsList);
         actionsList.add(actions);
         actions.put("action_type", conversionData.get("eventType"));
         actions.put("action_time", conversionData.get("timestamp"));
-        return JSONUtil.toJsonStr(params);
+        return params;
     }
 
 
     @Override
     public AdvertiserTypeEnum getAdvertiserType() {
-        return AdvertiserTypeEnum.GDT;
+        return AdvertiserTypeEnum.TENCENT;
     }
 
 
     @Override
     public Map<String, String> getAccessToken(Integer code, String appId, String appSecret, String callbackUrl) {
         // 发送HTTP请求
-        HttpResponse response = HttpRequest.post(CONVERSION_API_URL)
+        HttpResponse response = HttpRequest.post("CONVERSION_API_URL")
                 .form("client_id", appId)
                 .form("client_secret", appSecret)
                 .form("grant_type", "authorization_code")
@@ -105,7 +100,7 @@ public class GDTApiClient extends AbstractApiClient implements IAccessTokenClien
     @Override
     public Map<String, String> refreshAccessToken(String appId, String appSecret, String refreshToken) {
         // 发送HTTP请求
-        HttpResponse response = HttpRequest.post(CONVERSION_API_URL)
+        HttpResponse response = HttpRequest.post("CONVERSION_API_URL")
                 .form("client_id", appId)
                 .form("client_secret", appSecret)
                 .form("grant_type", "refresh_token")

+ 86 - 0
fs-ad-new-api/src/main/java/com/fs/app/integration/client/advertiser/VIVOApiClient.java

@@ -0,0 +1,86 @@
+package com.fs.app.integration.client.advertiser;
+
+import cn.hutool.http.HttpRequest;
+import cn.hutool.json.JSONUtil;
+import com.fs.app.integration.client.AbstractApiClient;
+import com.fs.common.constant.SystemConstant;
+import com.fs.common.utils.SnowflakeUtil;
+import com.fs.newAdv.enums.AdvertiserTypeEnum;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Component;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * VIVOAPI客户端
+ *
+ * @author zhangqin
+ * @see <a href="https://open-ad.vivo.com.cn/doc?id=636">VIVO API文档</a>
+ */
+@Slf4j
+@Component
+public class VIVOApiClient extends AbstractApiClient {
+
+    /**
+     * VIVO 回传API地址
+     */
+    private static final String CONVERSION_API_URL = "https://marketing-api.vivo.com.cn/openapi/v1/advertiser/behavior/upload";
+
+    /**
+     * 回传转化数据
+     *
+     * @param conversionData 转化数据
+     * @return 是否成功
+     */
+    @Override
+    public boolean reportConversion(Map<String, Object> conversionData) {
+        String url = CONVERSION_API_URL +
+                "?access_token=" + conversionData.get("accessToken") +
+                "&timestamp=" + conversionData.get("timestamp") +
+                "&nonce=" + SnowflakeUtil.nextId() +
+                "&advertiser_id=" + conversionData.get("advertiserId");
+        return executeWithLog(AdvertiserTypeEnum.VIVO, url, conversionData, () -> {
+            // 构建请求参数
+            Map<String, Object> requestBody = buildConversionParams(conversionData);
+            // 发送HTTP请求
+            return HttpRequest.post(url)
+                    .header("Content-Type", "application/json")
+                    .body(JSONUtil.toJsonStr(requestBody))
+                    .timeout(SystemConstant.API_TIMEOUT)
+                    .execute();
+        });
+    }
+
+    /**
+     * 构建转化回传参数
+     *
+     * @param conversionData 转化数据
+     * @return 请求参数
+     */
+    protected Map<String, Object> buildConversionParams(Map<String, Object> conversionData) {
+        Map<String, Object> params = new HashMap<>();
+        // 事件类型
+        params.put("srcType", "web");
+        // 事件源id
+        params.put("srcId", conversionData.get("srcId"));
+        List<Map<String, Object>> list = new ArrayList<>();
+        Map<String, Object> dataList = new HashMap<>();
+        dataList.put("cvType", conversionData.get("eventType"));
+        dataList.put("cvTime", conversionData.get("timestamp"));
+        dataList.put("requestId", conversionData.get("requestId"));
+        dataList.put("creativeId", conversionData.get("creativeId"));
+        list.add(dataList);
+        params.put("dataList", list);
+        return params;
+    }
+
+
+    @Override
+    public AdvertiserTypeEnum getAdvertiserType() {
+        return AdvertiserTypeEnum.OPPO;
+    }
+}
+

+ 4 - 33
fs-ad-new-api/src/main/java/com/fs/app/integration/factory/AdvertiserHandlerFactory.java

@@ -1,10 +1,9 @@
 package com.fs.app.integration.factory;
 
 
-import com.fs.app.enums.AdvertiserTypeEnum;
+import com.fs.newAdv.enums.AdvertiserTypeEnum;
 import com.fs.app.integration.adapter.IAdvertiserAdapter;
 import com.fs.app.integration.client.IApiClient;
-import com.fs.app.integration.strategy.ICallbackStrategy;
 import com.fs.common.exception.base.BusinessException;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -28,9 +27,6 @@ public class AdvertiserHandlerFactory {
 
     @Autowired
     private List<IAdvertiserAdapter> advertiserAdapters;
-
-    @Autowired
-    private List<ICallbackStrategy> callbackStrategies;
     @Autowired
     private List<IApiClient> apiClients;
 
@@ -38,12 +34,9 @@ public class AdvertiserHandlerFactory {
      * 适配器缓存
      */
     private final Map<AdvertiserTypeEnum, IAdvertiserAdapter> adapterMap = new ConcurrentHashMap<>();
-
     /**
-     * 策略缓存
+     * 客户端
      */
-    private final Map<AdvertiserTypeEnum, ICallbackStrategy> strategyMap = new ConcurrentHashMap<>();
-
     private final Map<AdvertiserTypeEnum, IApiClient> apiClientMap = new ConcurrentHashMap<>();
 
     /**
@@ -55,19 +48,12 @@ public class AdvertiserHandlerFactory {
         for (IAdvertiserAdapter adapter : advertiserAdapters) {
             adapterMap.put(adapter.getAdvertiserType(), adapter);
         }
-
-        // 初始化策略Map
-        for (ICallbackStrategy strategy : callbackStrategies) {
-            strategyMap.put(strategy.getAdvertiserType(), strategy);
-        }
-
         // 初始化策略Map
         for (IApiClient apiClient : apiClients) {
             apiClientMap.put(apiClient.getAdvertiserType(), apiClient);
         }
-
-        log.info("广告商处理器工厂初始化完成,适配器数量:{},策略数量:{}",
-                adapterMap.size(), strategyMap.size());
+        log.info("广告商处理器工厂初始化完成,适配器数量:{},客户端:{}",
+                adapterMap.size(), apiClientMap.size());
     }
 
     /**
@@ -84,21 +70,6 @@ public class AdvertiserHandlerFactory {
         return adapter;
     }
 
-    /**
-     * 获取回调策略
-     *
-     * @param advertiserType 广告商类型
-     * @return 回调策略
-     */
-    public ICallbackStrategy getStrategy(AdvertiserTypeEnum advertiserType) {
-        ICallbackStrategy strategy = strategyMap.get(advertiserType);
-        if (strategy == null) {
-            throw new BusinessException("不支持的广告商类型:" + advertiserType);
-        }
-        return strategy;
-    }
-
-
     /**
      * 获取回调策略
      *

+ 0 - 51
fs-ad-new-api/src/main/java/com/fs/app/integration/strategy/BaiduCallbackStrategy.java

@@ -1,51 +0,0 @@
-package com.fs.app.integration.strategy;
-
-import cn.hutool.core.map.MapUtil;
-
-import com.fs.app.enums.AdvertiserTypeEnum;
-import com.fs.common.utils.SignatureUtil;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.stereotype.Component;
-
-import java.util.Map;
-
-/**
- * 百度回调处理策略
- *
- * @author zhangqin
- * @date 2025-11-03
- */
-@Slf4j
-@Component
-public class BaiduCallbackStrategy implements ICallbackStrategy {
-
-    /**
-     * 百度密钥(实际应从配置或数据库读取)
-     */
-    private static final String BAIDU_SECRET = "baidu_secret_key";
-
-    @Override
-    public void handleCallback(Map<String, Object> callbackData) {
-        log.info("百度回调数据处理:{}", callbackData);
-
-        Long siteId = MapUtil.getLong(callbackData, "siteId");
-        Long impressionCount = MapUtil.getLong(callbackData, "impressionCount");
-        Long clickCount = MapUtil.getLong(callbackData, "clickCount");
-
-        // 更新站点统计数据
-        log.info("更新站点 {} 统计数据:展示数 {},点击数 {}", siteId, impressionCount, clickCount);
-
-        // 具体业务逻辑在Service层实现
-    }
-
-    @Override
-    public boolean verifySign(Map<String, String> params, String sign) {
-        return SignatureUtil.verifySign(params, sign, BAIDU_SECRET);
-    }
-
-    @Override
-    public AdvertiserTypeEnum getAdvertiserType() {
-        return AdvertiserTypeEnum.BAIDU;
-    }
-}
-

+ 0 - 37
fs-ad-new-api/src/main/java/com/fs/app/integration/strategy/ICallbackStrategy.java

@@ -1,37 +0,0 @@
-package com.fs.app.integration.strategy;
-
-import com.fs.app.enums.AdvertiserTypeEnum;
-
-import java.util.Map;
-
-/**
- * 回调处理策略接口(策略模式)
- * 定义不同广告平台的回调处理策略
- *
- * @author zhangqin
- * @date 2025-11-03
- */
-public interface ICallbackStrategy {
-
-    /**
-     * 处理回调数据
-     *
-     * @param callbackData 回调数据
-     */
-    void handleCallback(Map<String, Object> callbackData);
-
-    /**
-     * 验证签名
-     *
-     * @param params 参数
-     * @param sign 签名
-     * @return 是否验证通过
-     */
-    boolean verifySign(Map<String, String> params, String sign);
-
-    /**
-     * 获取广告商类型
-     */
-    AdvertiserTypeEnum getAdvertiserType();
-}
-

+ 0 - 47
fs-ad-new-api/src/main/java/com/fs/app/integration/strategy/OceanEngineCallbackStrategy.java

@@ -1,47 +0,0 @@
-package com.fs.app.integration.strategy;
-
-import cn.hutool.core.map.MapUtil;
-import com.fs.app.enums.AdvertiserTypeEnum;
-import com.fs.common.utils.SignatureUtil;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.stereotype.Component;
-
-import java.util.Map;
-
-/**
- * 巨量引擎回调处理策略
- *
- * @author zhangqin
- * @date 2025-11-03
- */
-@Slf4j
-@Component
-public class OceanEngineCallbackStrategy implements ICallbackStrategy {
-
-    /**
-     * 巨量引擎密钥(实际应从配置或数据库读取)
-     */
-    private static final String OCEAN_ENGINE_SECRET = "oceanengine_secret_key";
-
-    @Override
-    public void handleCallback(Map<String, Object> callbackData) {
-        log.info("巨量引擎回调数据处理:{}", callbackData);
-
-        Long siteId = MapUtil.getLong(callbackData, "siteId");
-        Long impressionCount = MapUtil.getLong(callbackData, "impressionCount");
-        Long clickCount = MapUtil.getLong(callbackData, "clickCount");
-
-        log.info("更新站点 {} 统计数据:展示数 {},点击数 {}", siteId, impressionCount, clickCount);
-    }
-
-    @Override
-    public boolean verifySign(Map<String, String> params, String sign) {
-        return SignatureUtil.verifySign(params, sign, OCEAN_ENGINE_SECRET);
-    }
-
-    @Override
-    public AdvertiserTypeEnum getAdvertiserType() {
-        return AdvertiserTypeEnum.OCEANENGINE;
-    }
-}
-

+ 0 - 46
fs-ad-new-api/src/main/java/com/fs/app/mq/consumer/ClickMessageConsumer.java

@@ -1,46 +0,0 @@
-package com.fs.app.mq.consumer;
-
-import com.fs.app.facade.CallbackProcessingFacadeService;
-import com.fs.app.mq.message.ClickMessage;
-import lombok.extern.slf4j.Slf4j;
-import org.apache.rocketmq.spring.annotation.ConsumeMode;
-import org.apache.rocketmq.spring.annotation.RocketMQMessageListener;
-import org.apache.rocketmq.spring.core.RocketMQListener;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Component;
-
-/**
- * 转化消息消费者
- * 多线程并发消费,支持自动重试
- *
- * @author zhangqin
- * @date 2025-11-05
- */
-@Slf4j
-@Component
-@RocketMQMessageListener(
-        topic = "landing-page-click-topic",
-        consumerGroup = "landing-page-click-topic-consumer-group",
-        // 并发消费模式(多线程并发消费,线程数由RocketMQ自动管理)
-        consumeMode = ConsumeMode.CONCURRENTLY,
-        // 最大重试次数(RocketMQ默认16次)
-        maxReconsumeTimes = 16
-)
-public class ClickMessageConsumer implements RocketMQListener<ClickMessage> {
-
-
-    @Autowired
-    private CallbackProcessingFacadeService facadeService;
-    /**
-     * 消费转化消息
-     *
-     * @param message 转化消息
-     */
-    @Override
-    public void onMessage(ClickMessage message) {
-        facadeService.updateClickTrace(message);
-    }
-
-
-}
-

+ 0 - 111
fs-ad-new-api/src/main/java/com/fs/app/mq/consumer/ConversionMessageConsumer.java

@@ -1,111 +0,0 @@
-package com.fs.app.mq.consumer;
-
-import com.fs.app.constant.MqTopicConstant;
-import com.fs.app.enums.AdvertiserTypeEnum;
-import com.fs.app.enums.ConversionTypeEnum;
-import com.fs.app.facade.IConversionService;
-import com.fs.app.mq.message.ConversionMessage;
-import com.fs.common.annotation.DistributeLock;
-import com.fs.common.utils.RedisUtil;
-import com.fs.newAdv.mapper.ConversionLogMapper;
-import lombok.extern.slf4j.Slf4j;
-import org.apache.rocketmq.spring.annotation.ConsumeMode;
-import org.apache.rocketmq.spring.annotation.RocketMQMessageListener;
-import org.apache.rocketmq.spring.core.RocketMQListener;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Component;
-
-import java.util.concurrent.TimeUnit;
-
-/**
- * 转化消息消费者
- * 多线程并发消费,支持自动重试
- *
- * @author zhangqin
- */
-@Slf4j
-@Component
-@RocketMQMessageListener(
-        topic = MqTopicConstant.CONVERSION_TOPIC,
-        consumerGroup = "conversion-topic-consumer-group",
-        // 并发消费模式(多线程并发消费,线程数由RocketMQ自动管理)
-        consumeMode = ConsumeMode.CONCURRENTLY,
-        // 最大重试次数(RocketMQ默认16次)
-        maxReconsumeTimes = 16
-)
-public class ConversionMessageConsumer implements RocketMQListener<ConversionMessage> {
-
-    @Autowired
-    private IConversionService conversionService;
-
-    @Autowired
-    private RedisUtil redisUtil;
-
-    @Autowired
-    private ConversionLogMapper conversionLogMapper;
-
-    /**
-     * 消费转化消息
-     *
-     * @param message 转化消息
-     */
-    @Override
-    @DistributeLock(scene = "mq", keyExpression = "#message.getMessageId", waitTime = 0, errorMsg = "任务已执行")
-    public void onMessage(ConversionMessage message) {
-        log.info("消费者1开始消费 | message={}", message);
-        try {
-            Thread.sleep(1000L);
-        } catch (InterruptedException e) {
-            throw new RuntimeException(e);
-        }
-        AdvertiserTypeEnum advertiser = message.getAdvertiser();
-        String traceId = message.getTraceId();
-        String messageId = message.getMessageId();
-        Long siteId = message.getSiteId();
-        Long leadId = message.getLeadId();
-        ConversionTypeEnum eventType = message.getEventType();
-
-        log.info("消费者接收到转化消息 | traceId={}, advertiser={}, eventType={}",
-                traceId, advertiser, eventType.getDesc());
-
-        // 1. 幂等性校验(防止重复消费)
-        if (!checkIdempotent(messageId)) {
-            log.warn("消息已处理,跳过 | messageId={}", messageId);
-            return;
-        }
-
-        // 2. 调用广告平台API回传
-        boolean success = conversionService.reportToAdvertiser(advertiser, siteId, eventType,
-                traceId, leadId, null);
-
-        markAsProcessed(messageId);
-        if (success) {
-            log.info("转化回传成功 | traceId={}, eventType={}", traceId, eventType);
-        } else {
-            log.info("转化回传失败 | traceId={}, eventType={}", traceId, eventType);
-        }
-    }
-
-    /**
-     * 幂等性校验(Redis)
-     *
-     * @param messageId 消息ID
-     * @return true=未处理,false=已处理
-     */
-    private boolean checkIdempotent(String messageId) {
-        String key = "conversion:processed:" + messageId;
-        Boolean success = redisUtil.setIfAbsent(key, "1", 7, TimeUnit.DAYS);
-        return Boolean.TRUE.equals(success);
-    }
-
-    /**
-     * 标记消息已处理
-     *
-     * @param messageId 消息ID
-     */
-    private void markAsProcessed(String messageId) {
-        String key = "conversion:processed:" + messageId;
-        redisUtil.set(key, "1", 7, TimeUnit.DAYS);
-    }
-}
-

+ 0 - 111
fs-ad-new-api/src/main/java/com/fs/app/mq/consumer/ConversionMessageConsumer2.java

@@ -1,111 +0,0 @@
-package com.fs.app.mq.consumer;
-
-import com.fs.app.constant.MqTopicConstant;
-import com.fs.app.enums.AdvertiserTypeEnum;
-import com.fs.app.enums.ConversionTypeEnum;
-import com.fs.app.facade.IConversionService;
-import com.fs.app.mq.message.ConversionMessage;
-import com.fs.common.annotation.DistributeLock;
-import com.fs.common.utils.RedisUtil;
-import com.fs.newAdv.mapper.ConversionLogMapper;
-import lombok.extern.slf4j.Slf4j;
-import org.apache.rocketmq.spring.annotation.ConsumeMode;
-import org.apache.rocketmq.spring.annotation.RocketMQMessageListener;
-import org.apache.rocketmq.spring.core.RocketMQListener;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Component;
-
-import java.util.concurrent.TimeUnit;
-
-/**
- * 转化消息消费者
- * 多线程并发消费,支持自动重试
- *
- * @author zhangqin
- */
-@Slf4j
-@Component
-@RocketMQMessageListener(
-        topic = MqTopicConstant.CONVERSION_TOPIC,
-        consumerGroup = "conversion-topic-consumer2-group",
-        // 并发消费模式(多线程并发消费,线程数由RocketMQ自动管理)
-        consumeMode = ConsumeMode.CONCURRENTLY,
-        // 最大重试次数(RocketMQ默认16次)
-        maxReconsumeTimes = 16
-)
-public class ConversionMessageConsumer2 implements RocketMQListener<ConversionMessage> {
-
-    @Autowired
-    private IConversionService conversionService;
-
-    @Autowired
-    private RedisUtil redisUtil;
-
-    @Autowired
-    private ConversionLogMapper conversionLogMapper;
-
-    /**
-     * 消费转化消息
-     *
-     * @param message 转化消息
-     */
-    @Override
-    @DistributeLock(scene = "mq", keyExpression = "#message.getMessageId", waitTime = 0, errorMsg = "任务已执行")
-    public void onMessage(ConversionMessage message) {
-        log.info("消费者2开始消费 | message={}", message);
-        try {
-            Thread.sleep(1000L);
-        } catch (InterruptedException e) {
-            throw new RuntimeException(e);
-        }
-        AdvertiserTypeEnum advertiser = message.getAdvertiser();
-        String traceId = message.getTraceId();
-        String messageId = message.getMessageId();
-        Long siteId = message.getSiteId();
-        Long leadId = message.getLeadId();
-        ConversionTypeEnum eventType = message.getEventType();
-
-        log.info("消费者接收到转化消息 | traceId={}, advertiser={}, eventType={}",
-                traceId, advertiser, eventType.getDesc());
-
-        // 1. 幂等性校验(防止重复消费)
-        if (!checkIdempotent(messageId)) {
-            log.warn("消息已处理,跳过 | messageId={}", messageId);
-            return;
-        }
-
-        // 2. 调用广告平台API回传
-        boolean success = conversionService.reportToAdvertiser(advertiser, siteId, eventType,
-                traceId, leadId, null);
-
-        markAsProcessed(messageId);
-        if (success) {
-            log.info("转化回传成功 | traceId={}, eventType={}", traceId, eventType);
-        } else {
-            log.info("转化回传失败 | traceId={}, eventType={}", traceId, eventType);
-        }
-    }
-
-    /**
-     * 幂等性校验(Redis)
-     *
-     * @param messageId 消息ID
-     * @return true=未处理,false=已处理
-     */
-    private boolean checkIdempotent(String messageId) {
-        String key = "conversion:processed:" + messageId;
-        Boolean success = redisUtil.setIfAbsent(key, "1", 7, TimeUnit.DAYS);
-        return Boolean.TRUE.equals(success);
-    }
-
-    /**
-     * 标记消息已处理
-     *
-     * @param messageId 消息ID
-     */
-    private void markAsProcessed(String messageId) {
-        String key = "conversion:processed:" + messageId;
-        redisUtil.set(key, "1", 7, TimeUnit.DAYS);
-    }
-}
-

+ 67 - 0
fs-ad-new-api/src/main/java/com/fs/app/mq/consumer/ConversionTrackingMessageConsumer.java

@@ -0,0 +1,67 @@
+package com.fs.app.mq.consumer;
+
+import com.fs.newAdv.constant.MqTopicConstant;
+import com.fs.newAdv.enums.event.SystemEventTypeEnum;
+import com.fs.app.facade.IConversionService;
+import com.fs.newAdv.constant.ConversionTrackingMessage;
+import com.fs.common.annotation.DistributeLock;
+import com.fs.common.utils.RedisUtil;
+import com.fs.newAdv.mapper.ConversionLogMapper;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.rocketmq.spring.annotation.ConsumeMode;
+import org.apache.rocketmq.spring.annotation.RocketMQMessageListener;
+import org.apache.rocketmq.spring.core.RocketMQListener;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+/**
+ * 转化追踪
+ *
+ * @author zhangqin
+ */
+@Slf4j
+@Component
+@RocketMQMessageListener(
+        topic = MqTopicConstant.CONVERSION_TRACKING_TOPIC,
+        consumerGroup = MqTopicConstant.CONVERSION_TRACKING_TOPIC_CONSUMER_GROUP,
+        // 并发消费模式(多线程并发消费,线程数由RocketMQ自动管理)
+        consumeMode = ConsumeMode.CONCURRENTLY,
+        // 最大重试次数(RocketMQ默认16次)
+        maxReconsumeTimes = 16
+)
+public class ConversionTrackingMessageConsumer implements RocketMQListener<ConversionTrackingMessage> {
+
+    @Autowired
+    private IConversionService conversionService;
+
+    @Autowired
+    private RedisUtil redisUtil;
+
+    @Autowired
+    private ConversionLogMapper conversionLogMapper;
+
+    /**
+     * 消费转化消息
+     *
+     * @param message 转化消息
+     */
+    @Override
+    @DistributeLock(scene = "mq", keyExpression = "#message.traceId", waitTime = 0, errorMsg = "重复消费")
+    public void onMessage(ConversionTrackingMessage message) {
+        String traceId = message.getTraceId();
+        SystemEventTypeEnum eventType = message.getEventType();
+
+        log.info("转化追踪消息开始消费 | traceId={}, eventType={}",
+                traceId, eventType.getDescription());
+
+        //  调用广告平台API回传
+        boolean success = conversionService.reportTrackingToAdvertiser(eventType, traceId);
+
+        if (success) {
+            log.info("转化回传成功 | traceId={}, eventType={}", traceId, eventType);
+        } else {
+            log.info("转化回传失败 | traceId={}, eventType={}", traceId, eventType);
+        }
+    }
+}
+

+ 0 - 26
fs-ad-new-api/src/main/java/com/fs/app/mq/message/ClickMessage.java

@@ -1,26 +0,0 @@
-package com.fs.app.mq.message;
-
-import lombok.Data;
-
-import java.io.Serializable;
-import java.util.Map;
-
-/**
- * 转化回传消息实体
- *
- * @author zhangqin
- * @date 2025-11-05
- */
-@Data
-public class ClickMessage extends MqMessageDto implements Serializable {
-
-    private static final long serialVersionUID = 1L;
-
-    private Long siteId;
-
-    private String viewUrl;
-
-    private Map<String, String> allParams;
-}
-
-

+ 0 - 53
fs-ad-new-api/src/main/java/com/fs/app/mq/message/ConversionMessage.java

@@ -1,53 +0,0 @@
-package com.fs.app.mq.message;
-
-import com.fs.app.enums.AdvertiserTypeEnum;
-import com.fs.app.enums.ConversionTypeEnum;
-import lombok.Data;
-import lombok.EqualsAndHashCode;
-
-import java.io.Serializable;
-
-/**
- * 转化回传消息实体
- *
- * @author zhangqin
- * @date 2025-11-05
- */
-@EqualsAndHashCode(callSuper = true)
-@Data
-public class ConversionMessage extends MqMessageDto implements Serializable {
-
-    private static final long serialVersionUID = 1L;
-
-    /**
-     * 站点ID
-     */
-    private Long siteId;
-
-    /**
-     * 链路id
-     */
-    private String traceId;
-
-    /**
-     * 广告商名称
-     */
-    private AdvertiserTypeEnum advertiser;
-
-    /**
-     * 事件类型
-     */
-    private ConversionTypeEnum eventType;
-
-    /**
-     * 线索id
-     */
-    private Long leadId;
-
-    /**
-     * 转化价值(可选)
-     */
-    private Double value;
-}
-
-

+ 0 - 19
fs-ad-new-api/src/main/java/com/fs/app/mq/message/MqMessageDto.java

@@ -1,19 +0,0 @@
-package com.fs.app.mq.message;
-
-import lombok.Data;
-
-import java.io.Serializable;
-
-@Data
-public class MqMessageDto implements Serializable {
-    private static final long serialVersionUID = 1L;
-    /**
-     * 消息唯一键
-     */
-    private String messageId;
-
-    /**
-     * 时间戳
-     */
-    private Long timestamp;
-}

+ 0 - 125
fs-ad-new-api/src/main/java/com/fs/app/mq/producer/ConversionMessageProducer.java

@@ -1,125 +0,0 @@
-package com.fs.app.mq.producer;
-
-import cn.hutool.core.util.StrUtil;
-import com.fs.app.constant.MqTopicConstant;
-import com.fs.app.mq.message.ClickMessage;
-import com.fs.app.mq.message.ConversionMessage;
-import lombok.extern.slf4j.Slf4j;
-import org.apache.rocketmq.client.producer.SendCallback;
-import org.apache.rocketmq.client.producer.SendResult;
-import org.apache.rocketmq.spring.core.RocketMQTemplate;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Component;
-
-/**
- * 转化消息生产者
- *
- * @author zhangqin
- * @date 2025-11-05
- */
-@Slf4j
-@Component
-public class ConversionMessageProducer {
-
-    @Autowired
-    private RocketMQTemplate rocketMQTemplate;
-
-
-    /**
-     * 发送转化回传消息(异步)
-     *
-     * @param message 转化消息
-     */
-    public void sendConversionMessage(ConversionMessage message) {
-        // 1. 设置消息ID(用于幂等性校验)
-        if (StrUtil.isBlank(message.getMessageId())) {
-            message.setMessageId(buildMessageId(message));
-        }
-
-        // 2. 设置时间戳
-        if (message.getTimestamp() == null) {
-            message.setTimestamp(System.currentTimeMillis());
-        }
-
-        // 3. 异步发送消息
-        rocketMQTemplate.asyncSend(
-                MqTopicConstant.CONVERSION_TOPIC,
-                message,
-                new SendCallback() {
-                    @Override
-                    public void onSuccess(SendResult sendResult) {
-                        log.info("转化消息发送成功 | traceId={}, eventType={}, msgId={}, queueId={}",
-                                message.getTraceId(),
-                                message.getEventType().getDesc(),
-                                sendResult.getMsgId(),
-                                sendResult.getMessageQueue().getQueueId());
-                    }
-
-                    @Override
-                    public void onException(Throwable e) {
-                        log.error("转化消息发送失败 | clickId={}, eventType={}, error={}",
-                                message.getTraceId(),
-                                message.getEventType(),
-                                e.getMessage(),
-                                e);
-                        // TODO: 记录到数据库,后续补偿
-                    }
-                }
-        );
-    }
-
-
-    /**
-     * 发送点击同步消息(异步)
-     *
-     * @param message 转化消息
-     */
-    public void sendClickMessage(ClickMessage message) {
-        try {
-            // 1. 设置消息ID(用于幂等性校验)
-
-
-            // 2. 设置时间戳
-
-
-            // 3. 异步发送消息
-            rocketMQTemplate.asyncSend(
-                    "event-feedback",
-                    message,
-                    new SendCallback() {
-                        @Override
-                        public void onSuccess(SendResult sendResult) {
-                            log.info("转化消息发送成功");
-                        }
-
-                        @Override
-                        public void onException(Throwable e) {
-                            log.error("转化消息发送失败");
-                            // TODO: 记录到数据库,后续补偿
-                        }
-                    }
-            );
-
-        } catch (Exception e) {
-            log.error("发送转化消息异常", e);
-        }
-    }
-
-
-    /**
-     * 构建消息ID(用于幂等性)
-     * 格式:traceId_timestamp
-     *
-     * @param message 转化消息
-     * @return 消息ID
-     */
-    private String buildMessageId(ConversionMessage message) {
-        return String.format("%s_%d",
-                message.getTraceId(),
-                System.currentTimeMillis());
-    }
-
-
-}
-
-

+ 1 - 1
fs-ad-new-api/src/main/java/com/fs/app/task/ConversionRetryTask.java

@@ -2,7 +2,7 @@ package com.fs.app.task;
 
 
 import cn.hutool.json.JSONUtil;
-import com.fs.app.enums.AdvertiserTypeEnum;
+import com.fs.newAdv.enums.AdvertiserTypeEnum;
 import com.fs.app.integration.client.IApiClient;
 import com.fs.app.integration.factory.AdvertiserHandlerFactory;
 import com.fs.common.annotation.DistributeLock;

+ 2 - 2
fs-ad-new-api/src/main/java/com/fs/app/task/DataSyncTask.java

@@ -1,8 +1,8 @@
 package com.fs.app.task;
 
 import cn.hutool.core.date.DateUtil;
-import com.fs.app.enums.TaskStatusEnum;
-import com.fs.app.enums.TaskTypeEnum;
+import com.fs.newAdv.enums.TaskStatusEnum;
+import com.fs.newAdv.enums.TaskTypeEnum;
 import com.fs.common.utils.SnowflakeUtil;
 import com.fs.newAdv.domain.PromotionAccount;
 import com.fs.newAdv.domain.ScheduleTaskLog;

+ 24 - 8
fs-company/src/main/java/com/fs/company/controller/newAdv/CallbackAccountController.java

@@ -1,16 +1,21 @@
 package com.fs.company.controller.newAdv;
 
+import cn.hutool.core.util.StrUtil;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.fs.common.result.Result;
+import com.fs.newAdv.domain.AdvEventType;
 import com.fs.newAdv.domain.CallbackAccount;
 import com.fs.newAdv.service.ICallbackAccountService;
+import com.fs.newAdv.vo.ConversionEventVo;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.validation.annotation.Validated;
 import org.springframework.web.bind.annotation.*;
 
 import javax.validation.constraints.NotNull;
+import java.util.List;
 
 /**
  * 回传账号管理控制器
@@ -37,7 +42,10 @@ public class CallbackAccountController {
             @RequestParam(required = false) String accountName) {
 
         Page<CallbackAccount> page = new Page<>(current, size);
-        IPage<CallbackAccount> result = callbackAccountService.page(page, accountName);
+        LambdaQueryWrapper<CallbackAccount> wrapper = new LambdaQueryWrapper<>();
+        wrapper.like(StrUtil.isNotBlank(accountName), CallbackAccount::getAccountName, accountName);
+        wrapper.orderByDesc(CallbackAccount::getCreateTime);
+        IPage<CallbackAccount> result = callbackAccountService.page(page, wrapper);
         return Result.success(result);
     }
 
@@ -55,7 +63,7 @@ public class CallbackAccountController {
      */
     @PostMapping
     public Result<Void> create(@RequestBody @Validated CallbackAccount callbackAccount) {
-        boolean success = callbackAccountService.create(callbackAccount);
+        boolean success = callbackAccountService.save(callbackAccount);
         return success ? Result.success() : Result.error("创建失败");
     }
 
@@ -68,7 +76,7 @@ public class CallbackAccountController {
             @RequestBody @Validated CallbackAccount callbackAccount) {
 
         callbackAccount.setId(id);
-        boolean success = callbackAccountService.update(callbackAccount);
+        boolean success = callbackAccountService.updateById(callbackAccount);
         return success ? Result.success() : Result.error("更新失败");
     }
 
@@ -77,17 +85,25 @@ public class CallbackAccountController {
      */
     @DeleteMapping("/{id}")
     public Result<Void> delete(@PathVariable @NotNull(message = "账号ID不能为空") Long id) {
-        boolean success = callbackAccountService.delete(id);
+        boolean success = callbackAccountService.removeById(id);
         return success ? Result.success() : Result.error("删除失败");
     }
 
     /**
-     * 批量删除回传账号
+     * 新增回传事件
      */
-    @DeleteMapping("/batch")
-    public Result<Void> batchDelete(@RequestBody Long[] ids) {
-        boolean success = callbackAccountService.batchDelete(ids);
+    @PostMapping("/saveEventType/{id}")
+    public Result<Void> saveEventType(@RequestBody List<ConversionEventVo> vo, @PathVariable("id") Long id) {
+        boolean success = callbackAccountService.saveEventType(vo, id);
         return success ? Result.success() : Result.error("批量删除失败");
     }
+
+    /**
+     * 查询回传事件
+     */
+    @PostMapping("/queryEventType/{advertiserId}")
+    public Result<List<AdvEventType>> queryEventType(@PathVariable("advertiserId") Long advertiserId) {
+        return Result.success(callbackAccountService.queryEventType(advertiserId));
+    }
 }
 

+ 0 - 94
fs-company/src/main/java/com/fs/company/controller/newAdv/LeadSourceController.java

@@ -1,94 +0,0 @@
-package com.fs.company.controller.newAdv;
-
-import com.baomidou.mybatisplus.core.metadata.IPage;
-import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-import com.fs.common.result.Result;
-import com.fs.newAdv.domain.LeadSource;
-import com.fs.newAdv.service.ILeadSourceService;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.validation.annotation.Validated;
-import org.springframework.web.bind.annotation.*;
-
-import javax.validation.constraints.NotNull;
-
-/**
- * 线索来源管理控制器
- *
- * @author zhangqin
- * @date 2025-11-03
- */
-@Slf4j
-@Validated
-@RestController
-@RequestMapping("/lead-source")
-public class LeadSourceController {
-
-    @Autowired
-    private ILeadSourceService leadSourceService;
-
-    /**
-     * 分页查询线索来源列表
-     */
-    @GetMapping("/page")
-    public Result<IPage<LeadSource>> page(
-            @RequestParam(defaultValue = "1") Long current,
-            @RequestParam(defaultValue = "10") Long size,
-            @RequestParam(required = false) String sourceName,
-            @RequestParam(required = false) Integer distributeType) {
-
-        Page<LeadSource> page = new Page<>(current, size);
-        IPage<LeadSource> result = leadSourceService.page(page, sourceName, distributeType);
-        return Result.success(result);
-    }
-
-    /**
-     * 根据ID查询线索来源详情
-     */
-    @GetMapping("/{id}")
-    public Result<LeadSource> getById(@PathVariable @NotNull(message = "来源ID不能为空") Long id) {
-        LeadSource leadSource = leadSourceService.getById(id);
-        return Result.success(leadSource);
-    }
-
-    /**
-     * 创建线索来源
-     */
-    @PostMapping
-    public Result<Void> create(@RequestBody @Validated LeadSource leadSource) {
-        boolean success = leadSourceService.create(leadSource);
-        return success ? Result.success() : Result.error("创建失败");
-    }
-
-    /**
-     * 更新线索来源
-     */
-    @PutMapping("/{id}")
-    public Result<Void> update(
-            @PathVariable @NotNull(message = "来源ID不能为空") Long id,
-            @RequestBody @Validated LeadSource leadSource) {
-
-        leadSource.setId(id);
-        boolean success = leadSourceService.update(leadSource);
-        return success ? Result.success() : Result.error("更新失败");
-    }
-
-    /**
-     * 删除线索来源
-     */
-    @DeleteMapping("/{id}")
-    public Result<Void> delete(@PathVariable @NotNull(message = "来源ID不能为空") Long id) {
-        boolean success = leadSourceService.delete(id);
-        return success ? Result.success() : Result.error("删除失败");
-    }
-
-    /**
-     * 批量删除线索来源
-     */
-    @DeleteMapping("/batch")
-    public Result<Void> batchDelete(@RequestBody Long[] ids) {
-        boolean success = leadSourceService.batchDelete(ids);
-        return success ? Result.success() : Result.error("批量删除失败");
-    }
-}
-

+ 33 - 0
fs-service/src/main/java/com/fs/newAdv/constant/ConversionTrackingMessage.java

@@ -0,0 +1,33 @@
+package com.fs.newAdv.constant;
+
+import com.fs.newAdv.enums.event.SystemEventTypeEnum;
+import lombok.Data;
+
+import java.io.Serializable;
+
+/**
+ * 链化追踪回传消息实体
+ *
+ * @author zhangqin
+ *
+ * */
+@Data
+public class ConversionTrackingMessage implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+    /**
+     * 链路id
+     */
+    private String traceId;
+
+    /**
+     * 事件类型
+     */
+    private SystemEventTypeEnum eventType;
+    /*
+     * value
+     */
+    private Double value;
+}
+
+

+ 27 - 0
fs-service/src/main/java/com/fs/newAdv/constant/MqTopicConstant.java

@@ -0,0 +1,27 @@
+package com.fs.newAdv.constant;
+
+public class MqTopicConstant {
+    /**
+     * 落地页回传topic
+     */
+    public static final String CONVERSION_TOPIC = "conversion-topic";
+
+    /**
+     * 转化追踪topic
+     */
+    public static final String CONVERSION_TRACKING_TOPIC = "conversion-tracking-topic";
+
+
+
+    //---------------------consumerGroup
+
+    /**
+     * 落地页回传consumer
+     */
+    public static final String CONVERSION_TOPIC_CONSUMER_GROUP = "conversion-topic-consumer-group";
+
+    /**
+     * 转化追踪consumer
+     */
+    public static final String CONVERSION_TRACKING_TOPIC_CONSUMER_GROUP = "conversion-topic-tracking-consumer-group";
+}

+ 44 - 0
fs-service/src/main/java/com/fs/newAdv/domain/AdvEventType.java

@@ -0,0 +1,44 @@
+package com.fs.newAdv.domain;
+
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+
+import java.io.Serializable;
+
+@Data
+@TableName("adv_event_type")
+public class AdvEventType implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    @TableId(value = "id", type = IdType.AUTO)
+    private Long id;
+
+    /**
+     * 事件类型
+     */
+    private String eventType;
+
+    /**
+     * 事件名称
+     */
+    private Integer eventName;
+
+    /**
+     * 广告商id
+     */
+    private Long advertiserId;
+    /**
+     * 广告商名称
+     */
+    private String advertiserName;
+
+    /**
+     * 是否系统内置(1是0否)
+     */
+    private String system;
+
+}

+ 43 - 7
fs-service/src/main/java/com/fs/newAdv/domain/CallbackAccount.java

@@ -1,11 +1,16 @@
 package com.fs.newAdv.domain;
 
+import cn.hutool.core.bean.BeanUtil;
+import cn.hutool.json.JSONUtil;
 import com.baomidou.mybatisplus.annotation.*;
 import com.fasterxml.jackson.annotation.JsonFormat;
+import com.fs.newAdv.vo.ConversionEventVo;
 import lombok.Data;
 
 import java.io.Serializable;
 import java.time.LocalDateTime;
+import java.util.Collections;
+import java.util.List;
 
 /**
  * 回传账号表
@@ -30,21 +35,44 @@ public class CallbackAccount implements Serializable {
      */
     private String accountName;
     /**
-     * ocpcId 回传账号id
+     * 广告商Id
      */
-    private String ocpcId;
+    private Long advertiserId;
+
+    /**
+     * 广告商名称
+     */
+    private String advertiserName;
+    /**
+     * 广告主id
+     */
+    private String adAccountId;
+    /**
+     * 回传token
+     */
+    private String accessToken;
+
     /**
-     * ocpcId 回传账号token
+     * 数据源id
      */
-    private String ocpcToken;
+    private String scrId;
+
     /**
-     * 着陆页URL
+     * 应用程序ID
      */
-    private String landingPageUrl;
+    private String appId;
+
     /**
-     * 转换事件逗号分隔
+     * 应用程序Secret(加密存储)
+     */
+    private String appSecret;
+
+    /**
+     * 转换事件
      */
     private String conversionEvent;
+    @TableField(exist = false)
+    private List<ConversionEventVo> conversionEventVo;
 
     /**
      * 创建时间
@@ -69,5 +97,13 @@ public class CallbackAccount implements Serializable {
      * 更新人
      */
     private String updater;
+
+    public List<ConversionEventVo> getConversionEventVo() {
+        if (this.conversionEvent == null || this.conversionEvent.isEmpty()) {
+            return Collections.emptyList();
+        }
+        // 根据实际的数据格式进行相应的转换处理
+        // 这里假设 conversionEvent 存储的是JSON格式的数组字符串
+        return JSONUtil.toList(JSONUtil.parseArray(this.conversionEvent), ConversionEventVo.class);    }
 }
 

+ 0 - 109
fs-service/src/main/java/com/fs/newAdv/domain/ClickTrace.java

@@ -1,109 +0,0 @@
-package com.fs.newAdv.domain;
-
-import com.baomidou.mybatisplus.annotation.IdType;
-import com.baomidou.mybatisplus.annotation.TableId;
-import com.baomidou.mybatisplus.annotation.TableName;
-import lombok.Data;
-
-import java.io.Serializable;
-import java.time.LocalDateTime;
-
-/**
- * 点击追踪表实体类
- * 用于记录用户通过广告平台访问落地页时携带的参数
- *
- * @author zhangqin
- * @date 2025-11-04
- */
-@Data
-@TableName("adv_click_trace")
-public class ClickTrace implements Serializable {
-
-    private static final long serialVersionUID = 1L;
-
-    /**
-     * 主键ID
-     */
-    @TableId(type = IdType.AUTO)
-    private Long id;
-
-    /**
-     * 追踪ID(第三方唯一标识)
-     */
-    private String traceId;
-
-    /**
-     * 站点ID
-     */
-    private Long siteId;
-
-    /**
-     * 广告商ID
-     */
-    private Long advertiserId;
-
-    /**
-     * 广告商名称
-     */
-    private String advertiserName;
-
-    /**
-     * 点击ID(百度:clk_id/logid,巨量:callback,广点通:gdt_vid)
-     */
-    private String clickId;
-
-    /**
-     * 广告计划ID
-     */
-    private String campaignId;
-
-    /**
-     * 创意ID
-     */
-    private String creativeId;
-
-    /**
-     * 来源平台(baidu/oceanengine/sina/gdt)
-     */
-    private String source;
-
-    /**
-     * 原始参数JSON
-     */
-    private String rawParams;
-
-    /**
-     * 用户ID(注册后关联)
-     */
-    private Long userId;
-
-    /**
-     * IP地址
-     */
-    private String ip;
-
-    /**
-     * 是否回传:0=未回传,1=已回传
-     */
-    private Integer isConverted;
-    /**
-     * 落地页访问地址
-     */
-    private String viewUrl;
-
-    /**
-     * 回传时间
-     */
-    private LocalDateTime conversionTime;
-
-
-    /**
-     * 创建时间
-     */
-    private LocalDateTime createTime;
-
-    /**
-     * 更新时间
-     */
-    private LocalDateTime updateTime;
-}

+ 57 - 17
fs-service/src/main/java/com/fs/newAdv/domain/Lead.java

@@ -25,18 +25,13 @@ public class Lead implements Serializable {
     @TableId(value = "id", type = IdType.AUTO)
     private Long id;
 
-    /**
-     * phone
-     */
-    private String phone;
-
     /**
      * 站点ID
      */
     private Long siteId;
 
     /**
-     * 链路id唯一
+     * 链路id唯一(clickId)
      */
     private String traceId;
 
@@ -44,24 +39,26 @@ public class Lead implements Serializable {
      * 来源平台
      */
     private Long advertiserId;
-    private String advertiserName;
+    // 用户手机号
+    private String phone;
+    // 系统用户id
+    private String systemUserId;
 
     /**
-     * 原始参数JSON
+     * 状态:0未转化,1已转化
      */
-    private String rawParams;
-
-    private String viewUrl;
-
+    private Integer status;
     /**
-     * 状态:0=新线索,1=已联系,2=已转化,3=无效
+     * 是否链化追踪触发 1是0否
      */
-    private Integer status;
-
-
-    private Integer ip;
+    private Integer clickTrigger;
     /**
+     * 是否落地页触发 1是0否
+     */
+    private Integer landingPageTrigger;
+
     /**
+     /**
      * 创建时间
      */
     @TableField(value = "create_time", strategy = FieldStrategy.NOT_NULL)
@@ -74,5 +71,48 @@ public class Lead implements Serializable {
     @TableField(value = "update_time", strategy = FieldStrategy.NOT_NULL)
     @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
     private LocalDateTime updateTime;
+
+
+    //-----------点击事件参数------------
+    /**
+     * 计划id
+     */
+    private String planId;
+    /**
+     * 单元id
+     */
+    private String unitId;
+    /**
+     * 创意ID
+     */
+    private String ideaId;
+    /**
+     * 账户id,广告主id
+     */
+    private String adAccountId;
+
+    private String ip;
+    /**
+     * 点击事件发生时间
+     */
+    private LocalDateTime clickTs;
+
+    /**
+     * 监测链接原始参数JSON
+     */
+    private String traceRawParams;
+
+
+    // -------------落地页参数
+
+    /**
+     * 落地页原始参数JSON
+     */
+    private String  landingPageRawParams;
+
+    /**
+     * 落地页访问时间
+     */
+    private LocalDateTime landingPageTs;
 }
 

+ 0 - 97
fs-service/src/main/java/com/fs/newAdv/domain/LeadSource.java

@@ -1,97 +0,0 @@
-package com.fs.newAdv.domain;
-
-import com.baomidou.mybatisplus.annotation.*;
-import com.fasterxml.jackson.annotation.JsonFormat;
-import lombok.Data;
-
-import java.io.Serializable;
-import java.time.LocalDateTime;
-
-/**
- * 线索来源表
- *
- * @author zhangqin
- * @date 2025-11-03
- */
-@Data
-@TableName("adv_lead_source")
-public class LeadSource implements Serializable {
-
-    private static final long serialVersionUID = 1L;
-
-    /**
-     * 来源ID
-     */
-    @TableId(value = "id", type = IdType.AUTO)
-    private Long id;
-
-    /**
-     * 来源名称
-     */
-    private String sourceName;
-
-    /**
-     * 负责机构
-     */
-    private String responsibleOrg;
-
-    /**
-     * 负责机构ID
-     */
-    private Long responsibleOrgId;
-
-    /**
-     * 负责人
-     */
-    private String responsiblePerson;
-
-    /**
-     * 负责人ID
-     */
-    private Long responsiblePersonId;
-
-    /**
-     * 分配方式(1自动 2手动)
-     */
-    private Integer distributeType;
-
-    /**
-     * 名片创建开始时间
-     */
-    private LocalDateTime cardCreateStartTime;
-
-    /**
-     * 名片创建结束时间
-     */
-    private LocalDateTime cardCreateEndTime;
-
-    /**
-     * 来源选项(1显示 2隐藏)
-     */
-    private Integer sourceOption;
-
-    /**
-     * 创建时间
-     */
-    @TableField(value = "create_time", strategy = FieldStrategy.NOT_NULL)
-    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
-    private LocalDateTime createTime;
-
-    /**
-     * 更新时间
-     */
-    @TableField(value = "update_time", strategy = FieldStrategy.NOT_NULL)
-    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
-    private LocalDateTime updateTime;
-
-    /**
-     * 创建人
-     */
-    private String creator;
-
-    /**
-     * 更新人
-     */
-    private String updater;
-}
-

+ 0 - 10
fs-service/src/main/java/com/fs/newAdv/domain/PromotionAccount.java

@@ -80,16 +80,6 @@ public class PromotionAccount implements Serializable {
      */
     private String adAccountId;
 
-    /**
-     * 应用程序ID
-     */
-    private String appId;
-
-    /**
-     * 应用程序Secret(加密存储)
-     */
-    private String appSecret;
-
     /**
      * 回调地址
      */

+ 0 - 4
fs-service/src/main/java/com/fs/newAdv/domain/Site.java

@@ -130,10 +130,6 @@ public class Site implements Serializable {
      */
     private String callbackAccountName;
 
-    /**
-     * 转化目标ID
-     */
-    private Long conversionTargetId;
     /**
      * 站点URL
      */

+ 0 - 144
fs-service/src/main/java/com/fs/newAdv/domain/SiteStatisticsMonthly.java

@@ -1,144 +0,0 @@
-package com.fs.newAdv.domain;
-
-import com.baomidou.mybatisplus.annotation.*;
-import lombok.Data;
-
-import java.io.Serializable;
-import java.math.BigDecimal;
-import java.time.LocalDateTime;
-
-/**
- * 站点月统计归档表
- *
- * @author zhangqin
- * @date 2025-11-03
- */
-@Data
-@TableName("adv_site_statistics_monthly")
-public class SiteStatisticsMonthly implements Serializable {
-
-    private static final long serialVersionUID = 1L;
-
-    /**
-     * 主键
-     */
-    @TableId(value = "id", type = IdType.AUTO)
-    private Long id;
-
-    /**
-     * 站点ID
-     */
-    private Long siteId;
-
-    /**
-     * 统计月份(如:2025-11)
-     */
-    private String statMonth;
-
-    /**
-     * ROI
-     */
-    private BigDecimal roi;
-
-    /**
-     * 销售额
-     */
-    private BigDecimal salesAmount;
-
-    /**
-     * PV
-     */
-    private Long pv;
-
-    /**
-     * UV
-     */
-    private Long uv;
-
-    /**
-     * 展示数
-     */
-    private Long impressionCount;
-
-    /**
-     * 点击数
-     */
-    private Long clickCount;
-
-    /**
-     * 点击率(%)
-     */
-    private BigDecimal clickRate;
-
-    /**
-     * 平均点击单价
-     */
-    private BigDecimal avgClickPrice;
-
-    /**
-     * 账面花费
-     */
-    private BigDecimal accountCost;
-
-    /**
-     * 实际花费
-     */
-    private BigDecimal actualCost;
-
-    /**
-     * 名片数
-     */
-    private Long cardCount;
-
-    /**
-     * 名片获取率(%)
-     */
-    private BigDecimal cardAcquireRate;
-
-    /**
-     * 名片获取成本
-     */
-    private BigDecimal cardAcquireCost;
-
-    /**
-     * 企微添加人数
-     */
-    private Long wechatAddCount;
-
-    /**
-     * 企微添加率(%)
-     */
-    private BigDecimal wechatAddRate;
-
-    /**
-     * 报名成功名片人数
-     */
-    private Long registerSuccessCount;
-
-    /**
-     * 报名成功加微率(%)
-     */
-    private BigDecimal registerWechatRate;
-
-    /**
-     * 企微添加成本
-     */
-    private BigDecimal wechatAddCost;
-
-    /**
-     * 企微加群人数
-     */
-    private Long wechatGroupCount;
-
-    /**
-     * 企微加群率(%)
-     */
-    private BigDecimal wechatGroupRate;
-
-    /**
-     * 创建时间
-     */
-    @TableField(fill = FieldFill.INSERT)
-    private LocalDateTime createTime;
-}
-

+ 0 - 155
fs-service/src/main/java/com/fs/newAdv/domain/SiteStatisticsWeekly.java

@@ -1,155 +0,0 @@
-package com.fs.newAdv.domain;
-
-import com.baomidou.mybatisplus.annotation.*;
-import lombok.Data;
-
-import java.io.Serializable;
-import java.math.BigDecimal;
-import java.time.LocalDate;
-import java.time.LocalDateTime;
-
-/**
- * 站点周统计归档表
- *
- * @author zhangqin
- * @date 2025-11-03
- */
-@Data
-@TableName("adv_site_statistics_weekly")
-public class SiteStatisticsWeekly implements Serializable {
-
-    private static final long serialVersionUID = 1L;
-
-    /**
-     * 主键
-     */
-    @TableId(value = "id", type = IdType.AUTO)
-    private Long id;
-
-    /**
-     * 站点ID
-     */
-    private Long siteId;
-
-    /**
-     * 统计周(如:2025-W44)
-     */
-    private String statWeek;
-
-    /**
-     * 周开始日期
-     */
-    private LocalDate weekStartDate;
-
-    /**
-     * 周结束日期
-     */
-    private LocalDate weekEndDate;
-
-    /**
-     * ROI
-     */
-    private BigDecimal roi;
-
-    /**
-     * 销售额
-     */
-    private BigDecimal salesAmount;
-
-    /**
-     * PV
-     */
-    private Long pv;
-
-    /**
-     * UV
-     */
-    private Long uv;
-
-    /**
-     * 展示数
-     */
-    private Long impressionCount;
-
-    /**
-     * 点击数
-     */
-    private Long clickCount;
-
-    /**
-     * 点击率(%)
-     */
-    private BigDecimal clickRate;
-
-    /**
-     * 平均点击单价
-     */
-    private BigDecimal avgClickPrice;
-
-    /**
-     * 账面花费
-     */
-    private BigDecimal accountCost;
-
-    /**
-     * 实际花费
-     */
-    private BigDecimal actualCost;
-
-    /**
-     * 名片数
-     */
-    private Long cardCount;
-
-    /**
-     * 名片获取率(%)
-     */
-    private BigDecimal cardAcquireRate;
-
-    /**
-     * 名片获取成本
-     */
-    private BigDecimal cardAcquireCost;
-
-    /**
-     * 企微添加人数
-     */
-    private Long wechatAddCount;
-
-    /**
-     * 企微添加率(%)
-     */
-    private BigDecimal wechatAddRate;
-
-    /**
-     * 报名成功名片人数
-     */
-    private Long registerSuccessCount;
-
-    /**
-     * 报名成功加微率(%)
-     */
-    private BigDecimal registerWechatRate;
-
-    /**
-     * 企微添加成本
-     */
-    private BigDecimal wechatAddCost;
-
-    /**
-     * 企微加群人数
-     */
-    private Long wechatGroupCount;
-
-    /**
-     * 企微加群率(%)
-     */
-    private BigDecimal wechatGroupRate;
-
-    /**
-     * 创建时间
-     */
-    @TableField(fill = FieldFill.INSERT)
-    private LocalDateTime createTime;
-}
-

+ 0 - 1
fs-service/src/main/java/com/fs/newAdv/dto/req/LandingIndexReq.java

@@ -19,5 +19,4 @@ public class LandingIndexReq implements Serializable {
      */
     @NotBlank(message = "落地页地址不能为空")
     private String viewUrl;
-
 }

+ 11 - 9
fs-ad-new-api/src/main/java/com/fs/app/enums/AdvertiserTypeEnum.java → fs-service/src/main/java/com/fs/newAdv/enums/AdvertiserTypeEnum.java

@@ -1,7 +1,9 @@
-package com.fs.app.enums;
+package com.fs.newAdv.enums;
 
 import lombok.Getter;
 
+import java.io.Serializable;
+
 /**
  * 广告商类型枚举
  *
@@ -9,14 +11,14 @@ import lombok.Getter;
  * @date 2025-11-03
  */
 @Getter
-public enum AdvertiserTypeEnum {
-
-    BAIDU(1L, "BAIDU", "百度"),
-    OCEANENGINE(2L, "OCEANENGINE", "巨量引擎"),
-    GDT(3L, "GDT", "广点通"),
-    OPPO(4L, "OPPO", "OPPO"),
-    VIVO(5L, "VIVO", "VIVO"),
-    iQIYI(6L, "iQIYI", "爱奇艺");
+public enum AdvertiserTypeEnum implements Serializable {
+
+    BAIDU(10001L, "BAIDU", "百度"),
+    OCEANENGINE(10002L, "OCEANENGINE", "巨量引擎"),
+    TENCENT(10003L, "GDT", "广点通"),
+    OPPO(10004L, "OPPO", "OPPO"),
+    VIVO(10005L, "VIVO", "VIVO"),
+    IQIYI(10006L, "IQIYI", "爱奇艺");
 
     private final Long code;
     private final String name;

+ 1 - 1
fs-ad-new-api/src/main/java/com/fs/app/enums/CallbackStatusEnum.java → fs-service/src/main/java/com/fs/newAdv/enums/CallbackStatusEnum.java

@@ -1,4 +1,4 @@
-package com.fs.app.enums;
+package com.fs.newAdv.enums;
 
 import lombok.Getter;
 

+ 1 - 1
fs-ad-new-api/src/main/java/com/fs/app/enums/ConversionTypeEnum.java → fs-service/src/main/java/com/fs/newAdv/enums/ConversionTypeEnum.java

@@ -1,4 +1,4 @@
-package com.fs.app.enums;
+package com.fs.newAdv.enums;
 
 import cn.hutool.core.util.ObjectUtil;
 import lombok.Getter;

+ 1 - 1
fs-ad-new-api/src/main/java/com/fs/app/enums/TaskStatusEnum.java → fs-service/src/main/java/com/fs/newAdv/enums/TaskStatusEnum.java

@@ -1,4 +1,4 @@
-package com.fs.app.enums;
+package com.fs.newAdv.enums;
 
 import lombok.Getter;
 

+ 1 - 1
fs-ad-new-api/src/main/java/com/fs/app/enums/TaskTypeEnum.java → fs-service/src/main/java/com/fs/newAdv/enums/TaskTypeEnum.java

@@ -1,4 +1,4 @@
-package com.fs.app.enums;
+package com.fs.newAdv.enums;
 
 import lombok.Getter;
 

+ 6 - 22
fs-ad-new-api/src/main/java/com/fs/app/event/ConversionEvent.java → fs-service/src/main/java/com/fs/newAdv/event/ConversionEvent.java

@@ -1,7 +1,8 @@
-package com.fs.app.event;
+package com.fs.newAdv.event;
 
-import com.fs.app.enums.AdvertiserTypeEnum;
-import com.fs.app.enums.ConversionTypeEnum;
+
+import com.fs.newAdv.enums.ConversionTypeEnum;
+import com.fs.newAdv.enums.event.SystemEventTypeEnum;
 import lombok.Getter;
 import org.springframework.context.ApplicationEvent;
 
@@ -17,45 +18,28 @@ import org.springframework.context.ApplicationEvent;
 @Getter
 public class ConversionEvent extends ApplicationEvent {
 
-    /**
-     * 站点ID
-     */
-    private final Long siteId;
-
     /**
      * 点击ID(广告平台提供)
      */
     private final String traceId;
 
-    /**
-     * 广告商名称(
-     */
-    private final AdvertiserTypeEnum advertiser;
 
     /**
      * 转化事件类型(如:register、form_submit、add_wechat)
      */
-    private final ConversionTypeEnum eventType;
+    private final SystemEventTypeEnum eventType;
 
     /**
      * 转化价值(元)
      */
     private final Double value;
 
-    /**
-     * 线索ID(可选)
-     */
-    private final Long leadId;
 
-    public ConversionEvent(Object source, Long siteId, String traceId,
-                           AdvertiserTypeEnum advertiser, ConversionTypeEnum eventType, Double value, Long leadId) {
+    public ConversionEvent(Object source, String traceId, SystemEventTypeEnum eventType, Double value) {
         super(source);
-        this.siteId = siteId;
         this.traceId = traceId;
-        this.advertiser = advertiser;
         this.eventType = eventType;
         this.value = value;
-        this.leadId = leadId;
     }
 }
 

+ 78 - 0
fs-service/src/main/java/com/fs/newAdv/event/ConversionEventListener.java

@@ -0,0 +1,78 @@
+package com.fs.newAdv.event;
+
+
+import com.fs.newAdv.constant.ConversionTrackingMessage;
+import com.fs.newAdv.constant.MqTopicConstant;
+import com.fs.newAdv.enums.ConversionTypeEnum;
+import com.fs.newAdv.enums.event.SystemEventTypeEnum;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.rocketmq.client.producer.SendCallback;
+import org.apache.rocketmq.client.producer.SendResult;
+import org.apache.rocketmq.spring.core.RocketMQTemplate;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.event.EventListener;
+import org.springframework.scheduling.annotation.Async;
+import org.springframework.stereotype.Component;
+
+/**
+ * 转化事件监听器
+ * 监听转化事件并发送到MQ进行异步处理
+ *
+ * @author zhangqin
+ * @date 2025-11-03
+ * @updated 2025-11-05 重构为发送MQ消息
+ */
+@Slf4j
+@Component
+public class ConversionEventListener {
+
+    @Autowired
+    private RocketMQTemplate rocketMQTemplate;
+
+    /**
+     * 处理转化事件
+     * 将转化事件转换为MQ消息并发送
+     *
+     * @param event 转化事件
+     */
+    @Async("asyncExecutor")
+    @EventListener
+    public void handleConversionEvent(ConversionEvent event) {
+        String traceId = event.getTraceId();
+        SystemEventTypeEnum eventType = event.getEventType();
+        Double value = event.getValue();
+        log.info("接收到转化事件 | traceId={}, eventType={} ,value={}",
+                traceId, eventType, value);
+        // 1. 校验参数
+        // 2. 构建MQ消息
+        ConversionTrackingMessage message = new ConversionTrackingMessage();
+        message.setTraceId(traceId);
+        message.setEventType(eventType);
+        message.setValue(value);
+        // 3. 异步发送消息
+        rocketMQTemplate.asyncSend(
+                MqTopicConstant.CONVERSION_TOPIC,
+                message,
+                new SendCallback() {
+                    @Override
+                    public void onSuccess(SendResult sendResult) {
+                        log.info("转化消息发送成功 | traceId={}, eventType={}, msgId={}, queueId={}",
+                                message.getTraceId(),
+                                message.getEventType().getDescription(),
+                                sendResult.getMsgId(),
+                                sendResult.getMessageQueue().getQueueId());
+                    }
+
+                    @Override
+                    public void onException(Throwable e) {
+                        log.error("转化消息发送失败 | clickId={}, eventType={}, error={}",
+                                message.getTraceId(),
+                                message.getEventType().getDescription(),
+                                e.getMessage(),
+                                e);
+                        // TODO: 记录到数据库,后续补偿
+                    }
+                }
+        );
+    }
+}

+ 48 - 0
fs-service/src/main/java/com/fs/newAdv/event/ConversionEventPublisher.java

@@ -0,0 +1,48 @@
+package com.fs.newAdv.event;
+
+
+import com.fs.newAdv.enums.event.SystemEventTypeEnum;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.ApplicationEventPublisher;
+import org.springframework.stereotype.Component;
+
+/**
+ * 转化事件发布器
+ *
+ * @author zhangqin
+ * @date 2025-11-03
+ * @updated 2025-11-05 添加clickId和advertiser参数
+ */
+@Slf4j
+@Component
+public class ConversionEventPublisher {
+
+    @Autowired
+    private ApplicationEventPublisher applicationEventPublisher;
+
+    /**
+     * 发布转化事件
+     *
+     * @param traceId   点击ID(广告平台提供)
+     * @param eventType 转化事件类型(如:SUBMIT_FORM、REGISTER、PAY)
+     * @param value     转化价值(元)
+     */
+    public void publishConversionEvent(String traceId, SystemEventTypeEnum eventType, Double value) {
+        log.info("发布转化事件 | traceId={}, eventType={}, value={}",
+                traceId, eventType, value);
+        ConversionEvent event = new ConversionEvent(this, traceId, eventType, value);
+        applicationEventPublisher.publishEvent(event);
+    }
+
+    /**
+     * 发布转化事件-无价值
+     *
+     * @param traceId   点击ID(广告平台提供)
+     * @param eventType 转化事件类型(如:SUBMIT_FORM、REGISTER、PAY)
+     */
+    public void publishConversionEvent(String traceId, SystemEventTypeEnum eventType) {
+        this.publishConversionEvent(traceId, eventType,null);
+    }
+
+}

+ 3 - 3
fs-service/src/main/java/com/fs/newAdv/mapper/LeadSourceMapper.java → fs-service/src/main/java/com/fs/newAdv/mapper/AdvEventTypeMapper.java

@@ -1,17 +1,17 @@
 package com.fs.newAdv.mapper;
 
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
-import com.fs.newAdv.domain.LeadSource;
+import com.fs.newAdv.domain.AdvEventType;
 import org.apache.ibatis.annotations.Mapper;
 
 /**
- * 线索来源表 Mapper接口
+ * 广告商表 Mapper接口
  *
  * @author zhangqin
  * @date 2025-11-03
  */
 @Mapper
-public interface LeadSourceMapper extends BaseMapper<LeadSource> {
+public interface AdvEventTypeMapper extends BaseMapper<AdvEventType> {
 
 }
 

+ 0 - 16
fs-service/src/main/java/com/fs/newAdv/mapper/ClickTraceMapper.java

@@ -1,16 +0,0 @@
-package com.fs.newAdv.mapper;
-
-import com.baomidou.mybatisplus.core.mapper.BaseMapper;
-import com.fs.newAdv.domain.ClickTrace;
-import org.apache.ibatis.annotations.Mapper;
-
-/**
- * 点击追踪表Mapper
- *
- * @author zhangqin
- * @date 2025-11-04
- */
-@Mapper
-public interface ClickTraceMapper extends BaseMapper<ClickTrace> {
-
-}

+ 0 - 17
fs-service/src/main/java/com/fs/newAdv/mapper/SiteStatisticsMonthlyMapper.java

@@ -1,17 +0,0 @@
-package com.fs.newAdv.mapper;
-
-import com.baomidou.mybatisplus.core.mapper.BaseMapper;
-import com.fs.newAdv.domain.SiteStatisticsMonthly;
-import org.apache.ibatis.annotations.Mapper;
-
-/**
- * 站点月统计归档表 Mapper接口
- *
- * @author zhangqin
- * @date 2025-11-03
- */
-@Mapper
-public interface SiteStatisticsMonthlyMapper extends BaseMapper<SiteStatisticsMonthly> {
-
-}
-

+ 0 - 17
fs-service/src/main/java/com/fs/newAdv/mapper/SiteStatisticsWeeklyMapper.java

@@ -1,17 +0,0 @@
-package com.fs.newAdv.mapper;
-
-import com.baomidou.mybatisplus.core.mapper.BaseMapper;
-import com.fs.newAdv.domain.SiteStatisticsWeekly;
-import org.apache.ibatis.annotations.Mapper;
-
-/**
- * 站点周统计归档表 Mapper接口
- *
- * @author zhangqin
- * @date 2025-11-03
- */
-@Mapper
-public interface SiteStatisticsWeeklyMapper extends BaseMapper<SiteStatisticsWeekly> {
-
-}
-

+ 11 - 0
fs-service/src/main/java/com/fs/newAdv/service/IAdvEventTypeService.java

@@ -0,0 +1,11 @@
+package com.fs.newAdv.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.fs.newAdv.domain.AdvEventType;
+
+
+
+public interface IAdvEventTypeService extends IService<AdvEventType> {
+
+}
+

+ 12 - 25
fs-service/src/main/java/com/fs/newAdv/service/ICallbackAccountService.java

@@ -2,7 +2,13 @@ package com.fs.newAdv.service;
 
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.fs.newAdv.domain.AdvEventType;
+import com.fs.newAdv.domain.ApiCallLog;
 import com.fs.newAdv.domain.CallbackAccount;
+import com.fs.newAdv.vo.ConversionEventVo;
+
+import java.util.List;
 
 
 /**
@@ -11,36 +17,17 @@ import com.fs.newAdv.domain.CallbackAccount;
  * @author zhangqin
  * @date 2025-11-03
  */
-public interface ICallbackAccountService {
+public interface ICallbackAccountService extends IService<CallbackAccount> {
 
-    /**
-     * 分页查询回传账号列表
-     */
-    IPage<CallbackAccount> page(Page<CallbackAccount> page, String accountName);
 
-    /**
-     * 根据ID查询回传账号
-     */
-    CallbackAccount getById(Long id);
 
     /**
-     * 创建回传账号
+     * 添加回传事件
+     * @param vo
+     * @return
      */
-    boolean create(CallbackAccount callbackAccount);
+    boolean saveEventType(List<ConversionEventVo> vo, Long id);
 
-    /**
-     * 更新回传账号
-     */
-    boolean update(CallbackAccount callbackAccount);
-
-    /**
-     * 删除回传账号
-     */
-    boolean delete(Long id);
-
-    /**
-     * 批量删除回传账号
-     */
-    boolean batchDelete(Long[] ids);
+    List<AdvEventType> queryEventType(Long advertiserId);
 }
 

+ 0 - 36
fs-service/src/main/java/com/fs/newAdv/service/IClickTraceService.java

@@ -1,36 +0,0 @@
-package com.fs.newAdv.service;
-
-
-import com.baomidou.mybatisplus.extension.service.IService;
-import com.fs.newAdv.domain.ClickTrace;
-
-/**
- * 点击追踪服务接口
- *
- * @author zhangqin
- */
-public interface IClickTraceService extends IService<ClickTrace> {
-    /**
-     * 关联用户ID
-     *
-     * @param traceId 追踪ID
-     * @param userId  用户ID
-     */
-    void bindUser(String traceId, Long userId);
-
-    /**
-     * 标记为已转化
-     *
-     * @param traceId 追踪记录ID
-     */
-    void markAsConverted(Long traceId);
-
-    /**
-     * 根据traceId查询
-     *
-     * @param traceId 追踪ID
-     * @return 追踪记录
-     */
-    ClickTrace getByTraceId(String traceId);
-}
-

+ 1 - 0
fs-service/src/main/java/com/fs/newAdv/service/ILeadService.java

@@ -2,6 +2,7 @@ package com.fs.newAdv.service;
 
 import com.baomidou.mybatisplus.extension.service.IService;
 import com.fs.newAdv.domain.Lead;
+import com.fs.newAdv.enums.AdvertiserTypeEnum;
 
 /**
  * 站点管理服务

+ 0 - 46
fs-service/src/main/java/com/fs/newAdv/service/ILeadSourceService.java

@@ -1,46 +0,0 @@
-package com.fs.newAdv.service;
-
-import com.baomidou.mybatisplus.core.metadata.IPage;
-import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-import com.fs.newAdv.domain.LeadSource;
-
-
-/**
- * 线索来源服务接口
- *
- * @author zhangqin
- * @date 2025-11-03
- */
-public interface ILeadSourceService {
-
-    /**
-     * 分页查询线索来源列表
-     */
-    IPage<LeadSource> page(Page<LeadSource> page, String sourceName, Integer distributeType);
-
-    /**
-     * 根据ID查询线索来源
-     */
-    LeadSource getById(Long id);
-
-    /**
-     * 创建线索来源
-     */
-    boolean create(LeadSource leadSource);
-
-    /**
-     * 更新线索来源
-     */
-    boolean update(LeadSource leadSource);
-
-    /**
-     * 删除线索来源
-     */
-    boolean delete(Long id);
-
-    /**
-     * 批量删除线索来源
-     */
-    boolean batchDelete(Long[] ids);
-}
-

+ 17 - 0
fs-service/src/main/java/com/fs/newAdv/service/impl/AdvEventTypeServiceImpl.java

@@ -0,0 +1,17 @@
+package com.fs.newAdv.service.impl;
+
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.fs.newAdv.domain.AdvEventType;
+import com.fs.newAdv.mapper.AdvEventTypeMapper;
+import com.fs.newAdv.service.IAdvEventTypeService;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Service;
+
+
+@Slf4j
+@Service
+public class AdvEventTypeServiceImpl extends ServiceImpl<AdvEventTypeMapper, AdvEventType>
+        implements IAdvEventTypeService {
+
+}
+

+ 18 - 70
fs-service/src/main/java/com/fs/newAdv/service/impl/CallbackAccountServiceImpl.java

@@ -1,19 +1,19 @@
 package com.fs.newAdv.service.impl;
 
-import cn.hutool.core.util.StrUtil;
+import cn.hutool.json.JSONUtil;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
-import com.baomidou.mybatisplus.core.metadata.IPage;
-import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-import com.fs.common.exception.base.BusinessException;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.fs.newAdv.domain.AdvEventType;
 import com.fs.newAdv.domain.CallbackAccount;
 import com.fs.newAdv.mapper.CallbackAccountMapper;
+import com.fs.newAdv.service.IAdvEventTypeService;
 import com.fs.newAdv.service.ICallbackAccountService;
+import com.fs.newAdv.vo.ConversionEventVo;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
-import org.springframework.transaction.annotation.Transactional;
 
-import java.util.Arrays;
+import java.util.List;
 
 /**
  * 回传账号服务实现类
@@ -23,78 +23,26 @@ import java.util.Arrays;
  */
 @Slf4j
 @Service
-public class CallbackAccountServiceImpl implements ICallbackAccountService {
+public class CallbackAccountServiceImpl extends ServiceImpl<CallbackAccountMapper, CallbackAccount> implements ICallbackAccountService {
 
     @Autowired
-    private CallbackAccountMapper callbackAccountMapper;
+    private IAdvEventTypeService iAdvEventTypeService;
 
-    @Override
-    public IPage<CallbackAccount> page(Page<CallbackAccount> page, String accountName) {
-        LambdaQueryWrapper<CallbackAccount> wrapper = new LambdaQueryWrapper<>();
-        wrapper.like(StrUtil.isNotBlank(accountName), CallbackAccount::getAccountName, accountName);
-        wrapper.orderByDesc(CallbackAccount::getCreateTime);
-
-        return callbackAccountMapper.selectPage(page, wrapper);
-    }
-
-    @Override
-    public CallbackAccount getById(Long id) {
-        CallbackAccount callbackAccount = callbackAccountMapper.selectById(id);
-        if (callbackAccount == null) {
-            throw new BusinessException("回传账号不存在");
-        }
-        return callbackAccount;
-    }
-
-    @Override
-    @Transactional(rollbackFor = Exception.class)
-    public boolean create(CallbackAccount callbackAccount) {
-        // 校验账号名称是否重复
-        LambdaQueryWrapper<CallbackAccount> wrapper = new LambdaQueryWrapper<>();
-        wrapper.eq(CallbackAccount::getAccountName, callbackAccount.getAccountName());
-        Integer count = callbackAccountMapper.selectCount(wrapper);
-        if (count > 0) {
-            throw new BusinessException("回传账号名称已存在");
-        }
-
-        return callbackAccountMapper.insert(callbackAccount) > 0;
-    }
-
-    @Override
-    @Transactional(rollbackFor = Exception.class)
-    public boolean update(CallbackAccount callbackAccount) {
-        CallbackAccount existAccount = callbackAccountMapper.selectById(callbackAccount.getId());
-        if (existAccount == null) {
-            throw new BusinessException("回传账号不存在");
-        }
-
-        // 校验名称是否重复
-        LambdaQueryWrapper<CallbackAccount> wrapper = new LambdaQueryWrapper<>();
-        wrapper.eq(CallbackAccount::getAccountName, callbackAccount.getAccountName());
-        wrapper.ne(CallbackAccount::getId, callbackAccount.getId());
-        Integer count = callbackAccountMapper.selectCount(wrapper);
-        if (count > 0) {
-            throw new BusinessException("回传账号名称已存在");
-        }
-
-        return callbackAccountMapper.updateById(callbackAccount) > 0;
-    }
 
     @Override
-    @Transactional(rollbackFor = Exception.class)
-    public boolean delete(Long id) {
-        CallbackAccount callbackAccount = callbackAccountMapper.selectById(id);
-        if (callbackAccount == null) {
-            throw new BusinessException("回传账号不存在");
-        }
-
-        return callbackAccountMapper.deleteById(id) > 0;
+    public boolean saveEventType(List<ConversionEventVo> vo, Long id) {
+        CallbackAccount callbackAccount = new CallbackAccount();
+        callbackAccount.setId(id);
+        callbackAccount.setConversionEvent(JSONUtil.toJsonStr(vo));
+        this.updateById(callbackAccount);
+        return false;
     }
 
     @Override
-    @Transactional(rollbackFor = Exception.class)
-    public boolean batchDelete(Long[] ids) {
-        return callbackAccountMapper.deleteBatchIds(Arrays.asList(ids)) > 0;
+    public List<AdvEventType> queryEventType(Long advertiserId) {
+        return iAdvEventTypeService.list(new LambdaQueryWrapper<AdvEventType>()
+                .eq(AdvEventType::getAdvertiserId, advertiserId)
+                .eq(AdvEventType::getSystem, 0));
     }
 }
 

+ 0 - 74
fs-service/src/main/java/com/fs/newAdv/service/impl/ClickTraceServiceImpl.java

@@ -1,74 +0,0 @@
-package com.fs.newAdv.service.impl;
-
-import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
-import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
-import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
-import com.fs.newAdv.domain.ClickTrace;
-import com.fs.newAdv.mapper.ClickTraceMapper;
-import com.fs.newAdv.mapper.SiteMapper;
-import com.fs.newAdv.service.IClickTraceService;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Service;
-import org.springframework.transaction.annotation.Transactional;
-
-import java.time.LocalDateTime;
-
-/**
- * 点击追踪服务实现类
- *
- * @author zhangqin
- * @date 2025-11-04
- */
-@Slf4j
-@Service
-public class ClickTraceServiceImpl extends ServiceImpl<ClickTraceMapper, ClickTrace> implements IClickTraceService {
-
-    @Autowired
-    private ClickTraceMapper clickTraceMapper;
-
-    @Autowired
-    private SiteMapper siteMapper;
-
-    @Override
-    @Transactional(rollbackFor = Exception.class)
-    public void bindUser(String traceId, Long userId) {
-        log.info("关联用户ID:traceId={},userId={}", traceId, userId);
-
-        LambdaUpdateWrapper<ClickTrace> wrapper = new LambdaUpdateWrapper<>();
-        wrapper.eq(ClickTrace::getTraceId, traceId);
-        wrapper.set(ClickTrace::getUserId, userId);
-        wrapper.set(ClickTrace::getUpdateTime, LocalDateTime.now());
-
-        int count = clickTraceMapper.update(null, wrapper);
-
-        if (count > 0) {
-            log.info("用户ID关联成功");
-        } else {
-            log.warn("未找到对应的追踪记录:traceId={}", traceId);
-        }
-    }
-
-    @Override
-    @Transactional(rollbackFor = Exception.class)
-    public void markAsConverted(Long traceId) {
-        log.info("标记为已转化:traceId={}", traceId);
-
-        LambdaUpdateWrapper<ClickTrace> wrapper = new LambdaUpdateWrapper<>();
-        wrapper.eq(ClickTrace::getId, traceId);
-        wrapper.set(ClickTrace::getIsConverted, 1);
-        wrapper.set(ClickTrace::getConversionTime, LocalDateTime.now());
-        wrapper.set(ClickTrace::getUpdateTime, LocalDateTime.now());
-
-        clickTraceMapper.update(null, wrapper);
-    }
-
-    @Override
-    public ClickTrace getByTraceId(String traceId) {
-        LambdaQueryWrapper<ClickTrace> wrapper = new LambdaQueryWrapper<>();
-        wrapper.eq(ClickTrace::getTraceId, traceId);
-
-        return clickTraceMapper.selectOne(wrapper);
-    }
-}
-

+ 8 - 1
fs-service/src/main/java/com/fs/newAdv/service/impl/LeadServiceImpl.java

@@ -8,6 +8,8 @@ import com.fs.newAdv.service.ILeadService;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.stereotype.Service;
 
+import java.util.List;
+
 /**
  * 域名管理Service实现类
  *
@@ -20,7 +22,12 @@ public class LeadServiceImpl extends ServiceImpl<LeadMapper, Lead> implements IL
 
     @Override
     public Lead getByTraceId(String traceId) {
-        return this.getOne(new LambdaQueryWrapper<Lead>().eq(Lead::getTraceId, traceId));
+        List<Lead> list = this.list(new LambdaQueryWrapper<Lead>()
+                .eq(Lead::getTraceId, traceId));
+        if (list.size() > 1) {
+            log.error("查询投流线索信息不唯一:{}", traceId);
+        }
+        return list.isEmpty() ? null : list.get(0);
     }
 }
 

+ 0 - 101
fs-service/src/main/java/com/fs/newAdv/service/impl/LeadSourceServiceImpl.java

@@ -1,101 +0,0 @@
-package com.fs.newAdv.service.impl;
-
-import cn.hutool.core.util.StrUtil;
-import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
-import com.baomidou.mybatisplus.core.metadata.IPage;
-import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-import com.fs.common.exception.base.BusinessException;
-import com.fs.newAdv.domain.LeadSource;
-import com.fs.newAdv.mapper.LeadSourceMapper;
-import com.fs.newAdv.service.ILeadSourceService;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Service;
-import org.springframework.transaction.annotation.Transactional;
-
-import java.util.Arrays;
-
-/**
- * 线索来源服务实现类
- *
- * @author zhangqin
- * @date 2025-11-03
- */
-@Slf4j
-@Service
-public class LeadSourceServiceImpl implements ILeadSourceService {
-
-    @Autowired
-    private LeadSourceMapper leadSourceMapper;
-
-    @Override
-    public IPage<LeadSource> page(Page<LeadSource> page, String sourceName, Integer distributeType) {
-        LambdaQueryWrapper<LeadSource> wrapper = new LambdaQueryWrapper<>();
-        wrapper.like(StrUtil.isNotBlank(sourceName), LeadSource::getSourceName, sourceName);
-        wrapper.eq(distributeType != null, LeadSource::getDistributeType, distributeType);
-        wrapper.orderByDesc(LeadSource::getCreateTime);
-
-        return leadSourceMapper.selectPage(page, wrapper);
-    }
-
-    @Override
-    public LeadSource getById(Long id) {
-        LeadSource leadSource = leadSourceMapper.selectById(id);
-        if (leadSource == null) {
-            throw new BusinessException("线索来源不存在");
-        }
-        return leadSource;
-    }
-
-    @Override
-    @Transactional(rollbackFor = Exception.class)
-    public boolean create(LeadSource leadSource) {
-        // 校验来源名称是否重复
-        LambdaQueryWrapper<LeadSource> wrapper = new LambdaQueryWrapper<>();
-        wrapper.eq(LeadSource::getSourceName, leadSource.getSourceName());
-        Integer count = leadSourceMapper.selectCount(wrapper);
-        if (count > 0) {
-            throw new BusinessException("线索来源名称已存在");
-        }
-
-        return leadSourceMapper.insert(leadSource) > 0;
-    }
-
-    @Override
-    @Transactional(rollbackFor = Exception.class)
-    public boolean update(LeadSource leadSource) {
-        LeadSource existLeadSource = leadSourceMapper.selectById(leadSource.getId());
-        if (existLeadSource == null) {
-            throw new BusinessException("线索来源不存在");
-        }
-
-        // 校验名称是否重复
-        LambdaQueryWrapper<LeadSource> wrapper = new LambdaQueryWrapper<>();
-        wrapper.eq(LeadSource::getSourceName, leadSource.getSourceName());
-        wrapper.ne(LeadSource::getId, leadSource.getId());
-        Integer count = leadSourceMapper.selectCount(wrapper);
-        if (count > 0) {
-            throw new BusinessException("线索来源名称已存在");
-        }
-
-        return leadSourceMapper.updateById(leadSource) > 0;
-    }
-
-    @Override
-    @Transactional(rollbackFor = Exception.class)
-    public boolean delete(Long id) {
-        LeadSource leadSource = leadSourceMapper.selectById(id);
-        if (leadSource == null) {
-            throw new BusinessException("线索来源不存在");
-        }
-
-        return leadSourceMapper.deleteById(id) > 0;
-    }
-
-    @Override
-    @Transactional(rollbackFor = Exception.class)
-    public boolean batchDelete(Long[] ids) {
-        return leadSourceMapper.deleteBatchIds(Arrays.asList(ids)) > 0;
-    }
-}
-

+ 13 - 0
fs-service/src/main/java/com/fs/newAdv/vo/ConversionEventVo.java

@@ -0,0 +1,13 @@
+package com.fs.newAdv.vo;
+
+import lombok.Data;
+
+@Data
+public class ConversionEventVo {
+    // 系统事件
+    private Integer systemEventType;
+    private String systemEventTypeName;
+    // 广告商事件
+    private Integer advertiserEventType;
+    private String advertiserEventName;
+}