fzzj 9 miesięcy temu
rodzic
commit
b4e3c8ef00

+ 93
- 0
RuoYi-App/components/AdSystem.vue Wyświetl plik

@@ -0,0 +1,93 @@
1
+<script>
2
+export default {
3
+  data() {
4
+    return {
5
+      // 多平台广告配置
6
+      adConfig: {
7
+        h5: {
8
+          adpid: 'AYDZ_H5_MAIN',
9
+          widescreen: 'AYDZ_H5_WIDE'
10
+        },
11
+        wechat: {
12
+          unitId: 'WECHAT_AD_UNIT_ID'
13
+        },
14
+        douyin: {
15
+          codeId: 'DOUYIN_AD_CODE_ID'
16
+        }
17
+      }
18
+    }
19
+  },
20
+  computed: {
21
+    currentAdConfig() {
22
+      // #ifdef H5
23
+      return this.adConfig.h5
24
+      // #endif
25
+      // #ifdef MP-WEIXIN
26
+      return this.adConfig.wechat
27
+      // #endif
28
+      // #ifdef MP-TOUTIAO
29
+      return this.adConfig.douyin
30
+      // #endif
31
+      return {}
32
+    }
33
+  },
34
+  methods: {
35
+    showAd(adType) {
36
+      // #ifdef H5
37
+      if(adType === 'feed') {
38
+        this.showH5FeedAd()
39
+      } else {
40
+        this.showH5RewardAd()
41
+      }
42
+      // #endif
43
+      
44
+      // #ifdef MP-WEIXIN
45
+      if(adType === 'feed') {
46
+        this.showWechatBannerAd()
47
+      } else {
48
+        this.showWechatRewardAd()
49
+      }
50
+      // #endif
51
+      
52
+      // #ifdef MP-TOUTIAO
53
+      if(adType === 'feed') {
54
+        this.showDouyinBannerAd()
55
+      } else {
56
+        this.showDouyinRewardAd()
57
+      }
58
+      // #endif
59
+    },
60
+    showH5FeedAd() {
61
+      // 获取DCloud广告实例
62
+      const ad = plus.ad.createAd({
63
+        adpid: this.currentAdConfig.adpid,
64
+        adType: 'feed'
65
+      })
66
+      ad.show()
67
+      
68
+      // 广告事件监听
69
+      ad.onLoad(() => console.log('H5广告加载成功'))
70
+      ad.onClose(res => {
71
+        if(res && res.isEnded) {
72
+          this.$emit('ad-completed')
73
+        }
74
+      })
75
+    }
76
+  }
77
+}
78
+</script>
79
+
80
+<template>
81
+  <!-- H5广告组件 -->
82
+  <view v-if="platform === 'h5'">
83
+    <ad 
84
+      v-if="showAd"
85
+      :adpid="currentAdConfig.adpid"
86
+      :adpid-widescreen="currentAdConfig.widescreen"
87
+      @close="onAdClose"
88
+    ></ad>
89
+  </view>
90
+</template>
91
+
92
+<style>
93
+</style>

+ 72
- 1
RuoYi-Vue/ruoyi-novel/src/main/java/com/ruoyi/novel/controller/NovelAdController.java Wyświetl plik

@@ -1,4 +1,75 @@
1 1
 package com.ruoyi.novel.controller;
2 2
 //# 广告计数接口
3
+
4
+import org.springframework.beans.factory.annotation.Autowired;
5
+
6
+@RestController
7
+@RequestMapping("/ad")
3 8
 public class NovelAdController {
4
-}
9
+
10
+    private final AdService adService;
11
+    private final RedisTemplate<String, String> redisTemplate;
12
+
13
+    @Autowired
14
+    public NovelAdController(AdService adService, RedisTemplate<String, String> redisTemplate) {
15
+        this.adService = adService;
16
+        this.redisTemplate = redisTemplate;
17
+    }
18
+
19
+    @PostMapping("/count")
20
+    public ResponseEntity<?> countAdView(
21
+            @RequestBody AdCountRequest request,
22
+            @RequestHeader(value = "X-PHP-Session", required = false) String phpSessionId
23
+    ) {
24
+        // 验证请求来源
25
+        if (!isValidSource(request.getSource())) {
26
+            return ResponseEntity.status(HttpStatus.FORBIDDEN).body("Invalid source");
27
+        }
28
+
29
+        // 会话同步处理
30
+        String userId = resolveUserId(request, phpSessionId);
31
+
32
+        // 防重处理 (5分钟内同一章节只计数一次)
33
+        String redisKey = String.format("ad:%s:%s:%s",
34
+                request.getSource(), userId, request.getChapterId());
35
+
36
+        if (redisTemplate.hasKey(redisKey)) {
37
+            return ResponseEntity.ok("Already counted");
38
+        }
39
+
40
+        // 记录广告
41
+        adService.logAdView(
42
+                userId,
43
+                request.getChapterId(),
44
+                request.getAdType(),
45
+                request.getSource()
46
+        );
47
+
48
+        // 设置Redis锁
49
+        redisTemplate.opsForValue().set(redisKey, "1", Duration.ofMinutes(5));
50
+
51
+        return ResponseEntity.ok("Ad counted");
52
+    }
53
+
54
+    private String resolveUserId(AdCountRequest request, String phpSessionId) {
55
+        // 优先使用PHP会话
56
+        if (phpSessionId != null) {
57
+            String sessionKey = "session:" + phpSessionId;
58
+            String userId = redisTemplate.opsForValue().get(sessionKey + ":user_id");
59
+            if (userId != null) return userId;
60
+        }
61
+
62
+        // 其次使用请求中的用户ID
63
+        if (request.getUserId() != null) {
64
+            return request.getUserId();
65
+        }
66
+
67
+        // 最后使用设备ID
68
+        return request.getDeviceId();
69
+    }
70
+
71
+    private boolean isValidSource(String source) {
72
+        List<String> validSources = Arrays.asList("h5", "wechat", "douyin", "app");
73
+        return validSources.contains(source);
74
+    }
75
+}

Ładowanie…
Anuluj
Zapisz