yinshaojie пре 9 месеци
родитељ
комит
49499b033b
67 измењених фајлова са 0 додато и 2798 уклоњено
  1. 0
    69
      RuoYi-Vue/ruoyi-novel/pom.xml
  2. 0
    16
      RuoYi-Vue/ruoyi-novel/src/main/java/com/ruoyi/novel/config/MybatisPlusConfig.java
  3. 0
    36
      RuoYi-Vue/ruoyi-novel/src/main/java/com/ruoyi/novel/config/PhpDataSyncTask.java
  4. 0
    61
      RuoYi-Vue/ruoyi-novel/src/main/java/com/ruoyi/novel/config/ScheduledTasks.java
  5. 0
    21
      RuoYi-Vue/ruoyi-novel/src/main/java/com/ruoyi/novel/config/TableSupport.java
  6. 0
    4
      RuoYi-Vue/ruoyi-novel/src/main/java/com/ruoyi/novel/config/ThreadPoolConfig.java
  7. 0
    37
      RuoYi-Vue/ruoyi-novel/src/main/java/com/ruoyi/novel/controller/ChapterController.java
  8. 0
    90
      RuoYi-Vue/ruoyi-novel/src/main/java/com/ruoyi/novel/controller/NovelAdController.java
  9. 0
    92
      RuoYi-Vue/ruoyi-novel/src/main/java/com/ruoyi/novel/controller/NovelController.java
  10. 0
    30
      RuoYi-Vue/ruoyi-novel/src/main/java/com/ruoyi/novel/controller/NovelFinanceController.java
  11. 0
    54
      RuoYi-Vue/ruoyi-novel/src/main/java/com/ruoyi/novel/controller/NovelVoteController.java
  12. 0
    28
      RuoYi-Vue/ruoyi-novel/src/main/java/com/ruoyi/novel/controller/ReadingHistoryController.java
  13. 0
    27
      RuoYi-Vue/ruoyi-novel/src/main/java/com/ruoyi/novel/domain/AdCountRequest.java
  14. 0
    40
      RuoYi-Vue/ruoyi-novel/src/main/java/com/ruoyi/novel/domain/AdLog.java
  15. 0
    26
      RuoYi-Vue/ruoyi-novel/src/main/java/com/ruoyi/novel/domain/AdPlatformConfig.java
  16. 0
    15
      RuoYi-Vue/ruoyi-novel/src/main/java/com/ruoyi/novel/domain/ChapterDTO.java
  17. 0
    39
      RuoYi-Vue/ruoyi-novel/src/main/java/com/ruoyi/novel/domain/Novel.java
  18. 0
    25
      RuoYi-Vue/ruoyi-novel/src/main/java/com/ruoyi/novel/domain/NovelChapter.java
  19. 0
    14
      RuoYi-Vue/ruoyi-novel/src/main/java/com/ruoyi/novel/domain/NovelContent.java
  20. 0
    27
      RuoYi-Vue/ruoyi-novel/src/main/java/com/ruoyi/novel/domain/ReadingRecord.java
  21. 0
    30
      RuoYi-Vue/ruoyi-novel/src/main/java/com/ruoyi/novel/domain/RoyaltyReport.java
  22. 0
    26
      RuoYi-Vue/ruoyi-novel/src/main/java/com/ruoyi/novel/domain/RoyaltySummary.java
  23. 0
    26
      RuoYi-Vue/ruoyi-novel/src/main/java/com/ruoyi/novel/domain/StoryOption.java
  24. 0
    26
      RuoYi-Vue/ruoyi-novel/src/main/java/com/ruoyi/novel/domain/VoteRecord.java
  25. 0
    18
      RuoYi-Vue/ruoyi-novel/src/main/java/com/ruoyi/novel/domain/VoteRequest.java
  26. 0
    45
      RuoYi-Vue/ruoyi-novel/src/main/java/com/ruoyi/novel/exception/GlobalExceptionHandler.java
  27. 0
    20
      RuoYi-Vue/ruoyi-novel/src/main/java/com/ruoyi/novel/mapper/AdLogMapper.java
  28. 0
    8
      RuoYi-Vue/ruoyi-novel/src/main/java/com/ruoyi/novel/mapper/AdPlatformConfigMapper.java
  29. 0
    26
      RuoYi-Vue/ruoyi-novel/src/main/java/com/ruoyi/novel/mapper/NovelChapterMapper.java
  30. 0
    14
      RuoYi-Vue/ruoyi-novel/src/main/java/com/ruoyi/novel/mapper/NovelContentMapper.java
  31. 0
    32
      RuoYi-Vue/ruoyi-novel/src/main/java/com/ruoyi/novel/mapper/NovelMapper.java
  32. 0
    34
      RuoYi-Vue/ruoyi-novel/src/main/java/com/ruoyi/novel/mapper/ReadingHistoryMapper.java
  33. 0
    33
      RuoYi-Vue/ruoyi-novel/src/main/java/com/ruoyi/novel/mapper/RoyaltySummaryMapper.java
  34. 0
    40
      RuoYi-Vue/ruoyi-novel/src/main/java/com/ruoyi/novel/mapper/StoryOptionMapper.java
  35. 0
    46
      RuoYi-Vue/ruoyi-novel/src/main/java/com/ruoyi/novel/mapper/VoteRecordMapper.java
  36. 0
    10
      RuoYi-Vue/ruoyi-novel/src/main/java/com/ruoyi/novel/service/AdConfigService.java
  37. 0
    9
      RuoYi-Vue/ruoyi-novel/src/main/java/com/ruoyi/novel/service/AdLogService.java
  38. 0
    15
      RuoYi-Vue/ruoyi-novel/src/main/java/com/ruoyi/novel/service/AdService.java
  39. 0
    10
      RuoYi-Vue/ruoyi-novel/src/main/java/com/ruoyi/novel/service/AdSyncService.java
  40. 0
    13
      RuoYi-Vue/ruoyi-novel/src/main/java/com/ruoyi/novel/service/ChapterService.java
  41. 0
    22
      RuoYi-Vue/ruoyi-novel/src/main/java/com/ruoyi/novel/service/IAdService.java
  42. 0
    13
      RuoYi-Vue/ruoyi-novel/src/main/java/com/ruoyi/novel/service/IFinanceService.java
  43. 0
    16
      RuoYi-Vue/ruoyi-novel/src/main/java/com/ruoyi/novel/service/IVoteService.java
  44. 0
    13
      RuoYi-Vue/ruoyi-novel/src/main/java/com/ruoyi/novel/service/NovelSearchService.java
  45. 0
    16
      RuoYi-Vue/ruoyi-novel/src/main/java/com/ruoyi/novel/service/NovelService.java
  46. 0
    9
      RuoYi-Vue/ruoyi-novel/src/main/java/com/ruoyi/novel/service/ReadingHistoryService.java
  47. 0
    29
      RuoYi-Vue/ruoyi-novel/src/main/java/com/ruoyi/novel/service/VoteService.java
  48. 0
    69
      RuoYi-Vue/ruoyi-novel/src/main/java/com/ruoyi/novel/service/impl/AdConfigServiceImpl.java
  49. 0
    88
      RuoYi-Vue/ruoyi-novel/src/main/java/com/ruoyi/novel/service/impl/AdLogServiceImpl.java
  50. 0
    131
      RuoYi-Vue/ruoyi-novel/src/main/java/com/ruoyi/novel/service/impl/AdServiceImpl.java
  51. 0
    82
      RuoYi-Vue/ruoyi-novel/src/main/java/com/ruoyi/novel/service/impl/AdSyncServiceImpl.java
  52. 0
    73
      RuoYi-Vue/ruoyi-novel/src/main/java/com/ruoyi/novel/service/impl/ChapterServiceImpl.java
  53. 0
    212
      RuoYi-Vue/ruoyi-novel/src/main/java/com/ruoyi/novel/service/impl/FinanceServiceImpl.java
  54. 0
    103
      RuoYi-Vue/ruoyi-novel/src/main/java/com/ruoyi/novel/service/impl/NovelSearchServiceImpl.java
  55. 0
    53
      RuoYi-Vue/ruoyi-novel/src/main/java/com/ruoyi/novel/service/impl/NovelServiceImpl.java
  56. 0
    60
      RuoYi-Vue/ruoyi-novel/src/main/java/com/ruoyi/novel/service/impl/ReadingHistoryServiceImpl.java
  57. 0
    231
      RuoYi-Vue/ruoyi-novel/src/main/java/com/ruoyi/novel/service/impl/VoteServiceImpl.java
  58. 0
    89
      RuoYi-Vue/ruoyi-novel/src/main/java/com/ruoyi/novel/utils/AdPlatformClient.java
  59. 0
    8
      RuoYi-Vue/ruoyi-novel/src/main/java/com/ruoyi/novel/utils/Constants.java
  60. 0
    72
      RuoYi-Vue/ruoyi-novel/src/main/java/com/ruoyi/novel/utils/JwtUtil.java
  61. 0
    15
      RuoYi-Vue/ruoyi-novel/src/main/java/com/ruoyi/novel/utils/NovelUtils.java
  62. 0
    22
      RuoYi-Vue/ruoyi-novel/src/main/java/com/ruoyi/novel/vip/VipAccessAspect.java
  63. 0
    26
      RuoYi-Vue/ruoyi-novel/src/main/resources/application.yml
  64. 0
    27
      RuoYi-Vue/ruoyi-novel/src/main/resources/mapper/novel/AdLogMapper.xml
  65. 0
    17
      RuoYi-Vue/ruoyi-novel/src/main/resources/mapper/novel/RoyaltySummaryMapper.xml
  66. 0
    26
      RuoYi-Vue/ruoyi-novel/src/main/resources/mapper/novel/VoteRecordMapper.xml
  67. 0
    44
      RuoYi-Vue/ruoyi-system/src/main/java/com/ruoyi/novel/exception/GlobalExceptionHandler.java

+ 0
- 69
RuoYi-Vue/ruoyi-novel/pom.xml Прегледај датотеку

@@ -1,69 +0,0 @@
1
-<?xml version="1.0" encoding="UTF-8"?>
2
-<project xmlns="http://maven.apache.org/POM/4.0.0"
3
-         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
5
-    <modelVersion>4.0.0</modelVersion>
6
-    <parent>
7
-        <groupId>com.ruoyi</groupId>
8
-        <artifactId>ruoyi</artifactId>
9
-        <version>3.9.0</version>
10
-    </parent>
11
-
12
-    <artifactId>ruoyi-novel</artifactId>
13
-
14
-    <properties>
15
-        <maven.compiler.source>17</maven.compiler.source>
16
-        <maven.compiler.target>17</maven.compiler.target>
17
-        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
18
-    </properties>
19
-    <dependencies>
20
-        <dependency>
21
-            <groupId>org.mybatis</groupId>
22
-            <artifactId>mybatis</artifactId>
23
-            <version>3.5.3</version>
24
-            <scope>compile</scope>
25
-        </dependency>
26
-        <dependency>
27
-            <groupId>org.projectlombok</groupId>
28
-            <artifactId>lombok</artifactId>
29
-        </dependency>
30
-        <dependency>
31
-            <groupId>org.springframework</groupId>
32
-            <artifactId>spring-context</artifactId>
33
-        </dependency>
34
-        <dependency>
35
-            <groupId>org.springframework</groupId>
36
-            <artifactId>spring-web</artifactId>
37
-        </dependency>
38
-        <dependency>
39
-            <groupId>com.ruoyi</groupId>
40
-            <artifactId>ruoyi-common</artifactId>
41
-        </dependency>
42
-        <!-- Elasticsearch -->
43
-        <dependency>
44
-            <groupId>org.springframework.boot</groupId>
45
-            <artifactId>spring-boot-starter-data-elasticsearch</artifactId>
46
-        </dependency>
47
-        <!-- MyBatis-Plus 核心依赖 -->
48
-        <dependency>
49
-            <groupId>com.baomidou</groupId>
50
-            <artifactId>mybatis-plus-boot-starter</artifactId>
51
-            <version>3.4.1</version> <!-- 2023年稳定版,兼容Spring Boot 2.7.x -->
52
-        </dependency>
53
-        <!-- 长文本处理 -->
54
-
55
-        <!-- 注解处理器(避免IDE报错) -->
56
-        <dependency>
57
-            <groupId>com.baomidou</groupId>
58
-            <artifactId>mybatis-plus-annotation</artifactId>
59
-            <version>3.4.1</version>
60
-        </dependency>
61
-
62
-        <dependency>
63
-            <groupId>com.google.guava</groupId>
64
-            <artifactId>guava</artifactId>
65
-            <version>33.4.0-jre</version> <!-- 使用较新版本 -->
66
-        </dependency>
67
-    </dependencies>
68
-
69
-</project>

+ 0
- 16
RuoYi-Vue/ruoyi-novel/src/main/java/com/ruoyi/novel/config/MybatisPlusConfig.java Прегледај датотеку

@@ -1,16 +0,0 @@
1
-package com.ruoyi.novel.config;
2
-
3
-import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor;
4
-import org.mybatis.spring.annotation.MapperScan;
5
-import org.springframework.context.annotation.Bean;
6
-import org.springframework.context.annotation.Configuration;
7
-
8
-@Configuration
9
-@MapperScan("com.ruoyi.novel.mapper")
10
-public class MybatisPlusConfig {
11
-
12
-    @Bean
13
-    public PaginationInterceptor paginationInterceptor() {
14
-        return new PaginationInterceptor();
15
-    }
16
-}

+ 0
- 36
RuoYi-Vue/ruoyi-novel/src/main/java/com/ruoyi/novel/config/PhpDataSyncTask.java Прегледај датотеку

@@ -1,36 +0,0 @@
1
-package com.ruoyi.novel.config;
2
-
3
-import com.ruoyi.novel.domain.RoyaltySummary;
4
-import com.ruoyi.novel.mapper.RoyaltySummaryMapper;
5
-import org.springframework.beans.factory.annotation.Value;
6
-import org.springframework.beans.factory.annotation.Autowired;
7
-import org.springframework.scheduling.annotation.Scheduled;
8
-import org.springframework.stereotype.Component;
9
-import org.springframework.web.client.RestTemplate;
10
-
11
-import java.util.Arrays;
12
-
13
-// 定时同步PHP数据任务
14
-@Component
15
-public class PhpDataSyncTask {
16
-
17
-    @Autowired
18
-    private RoyaltySummaryMapper royaltySummaryMapper;
19
-
20
-    @Value("${php.data.url}")
21
-    private String phpDataUrl;
22
-
23
-    // 每天凌晨2点执行
24
-    @Scheduled(cron = "0 0 2 * * ?")
25
-    public void syncRoyaltyData() {
26
-        RestTemplate restTemplate = new RestTemplate();
27
-        RoyaltySummary[] summaries = restTemplate.getForObject(
28
-                phpDataUrl + "/royalty/summary",
29
-                RoyaltySummary[].class
30
-        );
31
-
32
-        if (summaries != null) {
33
-            Arrays.stream(summaries).forEach(royaltySummaryMapper::insertOrUpdate);
34
-        }
35
-    }
36
-}

+ 0
- 61
RuoYi-Vue/ruoyi-novel/src/main/java/com/ruoyi/novel/config/ScheduledTasks.java Прегледај датотеку

@@ -1,61 +0,0 @@
1
-package com.ruoyi.novel.config;
2
-
3
-import com.ruoyi.novel.service.IAdService;
4
-import com.ruoyi.novel.service.IFinanceService;
5
-import com.ruoyi.novel.service.IVoteService;
6
-import org.slf4j.Logger;
7
-import org.slf4j.LoggerFactory;
8
-import org.springframework.beans.factory.annotation.Autowired;
9
-import org.springframework.context.annotation.Configuration;
10
-import org.springframework.scheduling.annotation.EnableScheduling;
11
-import org.springframework.scheduling.annotation.Scheduled;
12
-
13
-
14
-// ScheduledTasks.java
15
-@Configuration
16
-@EnableScheduling
17
-public class ScheduledTasks {
18
-    private static final Logger log = LoggerFactory.getLogger(ScheduledTasks.class);
19
-    @Autowired
20
-    private IAdService adService;
21
-
22
-    @Autowired
23
-    private IVoteService voteService;
24
-
25
-    @Autowired
26
-    private IFinanceService financeService;
27
-
28
-    /**
29
-     * 每5分钟重试失败的广告同步
30
-     */
31
-    @Scheduled(fixedRate = 300000)
32
-    public void retryAdSync() {
33
-        adService.retryFailedSyncs();
34
-    }
35
-
36
-    /**
37
-     * 每10分钟重试失败的PHP通知
38
-     */
39
-    @Scheduled(cron = "0 */10 * * * ?")
40
-    public void retryVoteNotify() {
41
-        voteService.retryFailedNotifications();
42
-    }
43
-
44
-    /**
45
-     * 每天凌晨2点同步分账数据
46
-     */
47
-    @Scheduled(cron = "0 0 2 * * ?")
48
-    public void syncRoyaltyData() {
49
-        financeService.syncRoyaltyData();
50
-    }
51
-
52
-    /**
53
-     * 每小时刷新投票计数器
54
-     */
55
-    @Scheduled(cron = "0 0 * * * ?")
56
-    public void resetVoteCounters() {
57
-        // 实际应基于每日重置
58
-        log.info("Resetting vote counters...");
59
-        // 计数器重置逻辑
60
-    }
61
-}

+ 0
- 21
RuoYi-Vue/ruoyi-novel/src/main/java/com/ruoyi/novel/config/TableSupport.java Прегледај датотеку

@@ -1,21 +0,0 @@
1
-package com.ruoyi.novel.config;
2
-
3
-import com.ruoyi.common.core.page.PageDomain;
4
-import com.ruoyi.common.utils.ServletUtils;
5
-import com.ruoyi.novel.utils.Constants;
6
-
7
-public class TableSupport {
8
-
9
-    public static PageDomain buildPageRequest() {
10
-        return getPageDomain();
11
-    }
12
-
13
-    public static PageDomain getPageDomain() {
14
-        PageDomain pageDomain = new PageDomain();
15
-        pageDomain.setPageNum(ServletUtils.getParameterToInt(Constants.PAGE_NUM));
16
-        pageDomain.setPageSize(ServletUtils.getParameterToInt(Constants.PAGE_SIZE));
17
-        pageDomain.setOrderByColumn(ServletUtils.getParameter(Constants.ORDER_BY_COLUMN));
18
-        pageDomain.setIsAsc(ServletUtils.getParameter(Constants.IS_ASC));
19
-        return pageDomain;
20
-    }
21
-}

+ 0
- 4
RuoYi-Vue/ruoyi-novel/src/main/java/com/ruoyi/novel/config/ThreadPoolConfig.java Прегледај датотеку

@@ -1,4 +0,0 @@
1
-package com.ruoyi.novel.config;
2
-
3
-public class ThreadPoolConfig {
4
-}

+ 0
- 37
RuoYi-Vue/ruoyi-novel/src/main/java/com/ruoyi/novel/controller/ChapterController.java Прегледај датотеку

@@ -1,37 +0,0 @@
1
-package com.ruoyi.novel.controller;
2
-
3
-import com.ruoyi.common.core.domain.AjaxResult;
4
-import com.ruoyi.novel.domain.ChapterDTO;
5
-import com.ruoyi.novel.domain.NovelChapter;
6
-import com.ruoyi.novel.service.ChapterService;
7
-import org.springframework.beans.factory.annotation.Autowired;
8
-import org.springframework.web.bind.annotation.*;
9
-
10
-import java.util.List;
11
-
12
-// ChapterController.java
13
-@RestController
14
-@RequestMapping("/chapter")
15
-public class ChapterController {
16
-
17
-    @Autowired
18
-    private ChapterService chapterService;
19
-    @GetMapping("/list/{novelId}")
20
-    public AjaxResult listChapters(@PathVariable Long novelId) {
21
-        List<NovelChapter> chapters = chapterService.selectChapterListByNovelId(novelId);
22
-        return AjaxResult.success(chapters);
23
-    }
24
-    @GetMapping("/{novelId}")
25
-    public AjaxResult getChapters(@PathVariable Long novelId) {
26
-        List<NovelChapter> chapters = chapterService.selectChapterListByNovelId(novelId);
27
-        return AjaxResult.success(chapters);
28
-    }
29
-
30
-    @PostMapping("/save")
31
-    public AjaxResult saveChapter(@RequestBody ChapterDTO dto) {
32
-        return toAjax(chapterService.saveChapter(dto.getChapter(), dto.getContent()));
33
-    }
34
-    private AjaxResult toAjax(int result) {
35
-        return result > 0 ? AjaxResult.success() : AjaxResult.error();
36
-    }
37
-}

+ 0
- 90
RuoYi-Vue/ruoyi-novel/src/main/java/com/ruoyi/novel/controller/NovelAdController.java Прегледај датотеку

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

+ 0
- 92
RuoYi-Vue/ruoyi-novel/src/main/java/com/ruoyi/novel/controller/NovelController.java Прегледај датотеку

@@ -1,92 +0,0 @@
1
-package com.ruoyi.novel.controller;
2
-
3
-import com.github.pagehelper.PageHelper;
4
-import com.github.pagehelper.PageInfo;
5
-import com.ruoyi.common.constant.HttpStatus;
6
-import com.ruoyi.common.core.domain.AjaxResult;
7
-import com.ruoyi.common.core.page.PageDomain;
8
-import com.ruoyi.common.core.page.TableDataInfo;
9
-import com.ruoyi.common.core.page.TableSupport;
10
-import com.ruoyi.novel.domain.Novel;
11
-import com.ruoyi.novel.mapper.NovelMapper;
12
-import com.ruoyi.novel.service.NovelSearchService;
13
-import com.ruoyi.novel.service.NovelService;
14
-import org.springframework.beans.factory.annotation.Autowired;
15
-import org.springframework.web.bind.annotation.*;
16
-
17
-import java.util.List;
18
-
19
-// NovelController.java
20
-@RestController
21
-@RequestMapping("/novel")
22
-public class NovelController {
23
-
24
-    @Autowired
25
-    private NovelService novelService;
26
-    @Autowired
27
-    private NovelSearchService searchService;
28
-    @Autowired
29
-    private NovelMapper novelMapper;
30
-    @GetMapping("/list")
31
-    public TableDataInfo list(Novel novel) {
32
-        startPage();
33
-        List<Novel> list = novelService.selectNovelList(novel);
34
-        return getDataTable(list);
35
-    }
36
-
37
-    @PostMapping
38
-    public AjaxResult add(@RequestBody Novel novel) {
39
-        return toAjax(novelService.insertNovel(novel));
40
-    }
41
-    @DeleteMapping("/{ids}")
42
-    public AjaxResult remove(@PathVariable Long[] ids) {
43
-        return toAjax(novelService.deleteNovelByIds(ids));
44
-    }
45
-
46
-    private AjaxResult toAjax(int rows) {
47
-        return rows > 0 ? AjaxResult.success() : AjaxResult.error();
48
-    }
49
-    // 若依框架的分页方法
50
-    protected void startPage() {
51
-        PageDomain pageDomain = TableSupport.buildPageRequest();
52
-        Integer pageNum = pageDomain.getPageNum();
53
-        Integer pageSize = pageDomain.getPageSize();
54
-        PageHelper.startPage(pageNum, pageSize);
55
-    }
56
-
57
-    // 若依框架的表格数据封装
58
-    protected TableDataInfo getDataTable(List<?> list) {
59
-        TableDataInfo rspData = new TableDataInfo();
60
-        rspData.setCode(HttpStatus.SUCCESS);
61
-        rspData.setRows(list);
62
-        rspData.setTotal(new PageInfo(list).getTotal());
63
-        return rspData;
64
-    }
65
-    // 其他接口...
66
-    @GetMapping("/search")
67
-    public AjaxResult searchNovels(@RequestParam String keyword) {
68
-        List<Novel> novels = searchService.searchNovels(keyword);
69
-        return AjaxResult.success(novels);
70
-    }
71
-
72
-    @PostMapping
73
-    public AjaxResult addNovel(@RequestBody Novel novel) {
74
-        novelMapper.insert(novel);
75
-        searchService.indexNovel(novel); // 创建索引
76
-        return AjaxResult.success();
77
-    }
78
-
79
-    @PutMapping
80
-    public AjaxResult updateNovel(@RequestBody Novel novel) {
81
-        novelMapper.updateById(novel);
82
-        searchService.updateNovelIndex(novel); // 更新索引
83
-        return AjaxResult.success();
84
-    }
85
-
86
-    @DeleteMapping("/{id}")
87
-    public AjaxResult deleteNovel(@PathVariable Long id) {
88
-        novelMapper.deleteById(id);
89
-        searchService.deleteNovelIndex(id); // 删除索引
90
-        return AjaxResult.success();
91
-    }
92
-}

+ 0
- 30
RuoYi-Vue/ruoyi-novel/src/main/java/com/ruoyi/novel/controller/NovelFinanceController.java Прегледај датотеку

@@ -1,30 +0,0 @@
1
-package com.ruoyi.novel.controller;
2
-
3
-import com.ruoyi.common.core.domain.AjaxResult;
4
-import com.ruoyi.novel.domain.RoyaltyReport;
5
-import com.ruoyi.novel.service.IFinanceService;
6
-import org.springframework.beans.factory.annotation.Autowired;
7
-import org.springframework.format.annotation.DateTimeFormat;
8
-import org.springframework.web.bind.annotation.GetMapping;
9
-import org.springframework.web.bind.annotation.RequestMapping;
10
-import org.springframework.web.bind.annotation.RequestParam;
11
-import org.springframework.web.bind.annotation.RestController;
12
-
13
-//# 分账结算接口
14
-// NovelFinanceController.java
15
-@RestController
16
-@RequestMapping("/finance")
17
-public class NovelFinanceController {
18
-
19
-    @Autowired
20
-    private IFinanceService financeService;
21
-
22
-    @GetMapping("/royalty")
23
-    public AjaxResult getRoyalty(
24
-            @RequestParam Long authorId,
25
-            @RequestParam @DateTimeFormat(pattern="yyyy-MM") String month) {
26
-
27
-        RoyaltyReport report = financeService.calculateRoyalty(authorId, month);
28
-        return AjaxResult.success(report);
29
-    }
30
-}

+ 0
- 54
RuoYi-Vue/ruoyi-novel/src/main/java/com/ruoyi/novel/controller/NovelVoteController.java Прегледај датотеку

@@ -1,54 +0,0 @@
1
-package com.ruoyi.novel.controller;
2
-
3
-import com.google.common.util.concurrent.RateLimiter;
4
-import com.ruoyi.common.core.domain.AjaxResult;
5
-import com.ruoyi.novel.domain.VoteRequest;
6
-import com.ruoyi.novel.service.IVoteService;
7
-import org.springframework.beans.factory.annotation.Autowired;
8
-import org.springframework.web.bind.annotation.PostMapping;
9
-import org.springframework.web.bind.annotation.RequestBody;
10
-import org.springframework.web.bind.annotation.RequestMapping;
11
-import org.springframework.web.bind.annotation.RestController;
12
-
13
-import java.util.concurrent.ConcurrentHashMap;
14
-
15
-//# 剧情投票接口
16
-// NovelVoteController.java
17
-@RestController
18
-@RequestMapping("/story/vote")
19
-public class NovelVoteController {
20
-
21
-    @Autowired
22
-    private IVoteService voteService;
23
-
24
-    // 使用Guava RateLimiter限制投票频率
25
-    private static final ConcurrentHashMap<Long, RateLimiter> userRateLimiters = new ConcurrentHashMap<>();
26
-    private static final int MAX_VOTES_PER_DAY = 3;
27
-
28
-    @PostMapping("/next")
29
-    public AjaxResult voteForStoryBranch(@RequestBody VoteRequest request) {
30
-        // 1. 频率限制检查
31
-        RateLimiter rateLimiter = userRateLimiters.computeIfAbsent(
32
-                request.getUserId(),
33
-                k -> RateLimiter.create(MAX_VOTES_PER_DAY)
34
-        );
35
-        // 1. 检查用户投票频率
36
-//        if (!voteService.canUserVote(request.getUserId())) {
37
-//            return AjaxResult.error("投票过于频繁,请稍后再试");
38
-//        }
39
-        if (!rateLimiter.tryAcquire()) {
40
-            return AjaxResult.error("投票过于频繁,请稍后再试");
41
-        }
42
-
43
-        // 2. 调用DeepSeek API生成剧情
44
-        String generatedContent = voteService.generateStoryContent(
45
-                request.getStoryId(),
46
-                request.getOptionId()
47
-        );
48
-
49
-        // 3. 异步通知PHP系统
50
-        voteService.notifyPhpSystem(request, generatedContent);
51
-
52
-        return AjaxResult.success("Vote processed", generatedContent);
53
-    }
54
-}

+ 0
- 28
RuoYi-Vue/ruoyi-novel/src/main/java/com/ruoyi/novel/controller/ReadingHistoryController.java Прегледај датотеку

@@ -1,28 +0,0 @@
1
-package com.ruoyi.novel.controller;
2
-
3
-import com.ruoyi.common.core.domain.AjaxResult;
4
-import com.ruoyi.novel.domain.ReadingRecord;
5
-import com.ruoyi.novel.service.ReadingHistoryService;
6
-import org.springframework.beans.factory.annotation.Autowired;
7
-import org.springframework.web.bind.annotation.*;
8
-
9
-@RestController
10
-@RequestMapping("/history")
11
-public class ReadingHistoryController {
12
-    @Autowired
13
-    private ReadingHistoryService historyService;
14
-    @PostMapping("/record")
15
-    public AjaxResult recordReading(@RequestBody ReadingRecord record) {
16
-        // 记录用户阅读位置
17
-        historyService.recordReading(record);
18
-        return AjaxResult.success("阅读记录已保存");
19
-    }
20
-
21
-    @GetMapping("/last/{userId}/{novelId}")
22
-    public AjaxResult getLastPosition(
23
-            @PathVariable Long userId,
24
-            @PathVariable Long novelId) {
25
-        ReadingRecord record = historyService.getLastPosition(userId, novelId);
26
-        return AjaxResult.success(record);
27
-    }
28
-}

+ 0
- 27
RuoYi-Vue/ruoyi-novel/src/main/java/com/ruoyi/novel/domain/AdCountRequest.java Прегледај датотеку

@@ -1,27 +0,0 @@
1
-package com.ruoyi.novel.domain;
2
-
3
-import lombok.Data;
4
-
5
-import javax.validation.constraints.NotBlank;
6
-import javax.validation.constraints.NotNull;
7
-
8
-// AdCountRequest.java
9
-@Data
10
-public class AdCountRequest {
11
-    @NotNull(message = "用户ID不能为空")
12
-    private Long userId;
13
-
14
-    @NotNull(message = "章节ID不能为空")
15
-    private Long chapterId;
16
-
17
-    @NotBlank(message = "广告平台不能为空")
18
-    private String adPlatform;
19
-
20
-    @NotBlank(message = "设备ID不能为空")
21
-    private String deviceId;
22
-
23
-    public String source;
24
-
25
-    public String adType;
26
-
27
-}

+ 0
- 40
RuoYi-Vue/ruoyi-novel/src/main/java/com/ruoyi/novel/domain/AdLog.java Прегледај датотеку

@@ -1,40 +0,0 @@
1
-package com.ruoyi.novel.domain;
2
-
3
-import com.baomidou.mybatisplus.annotation.*;
4
-import lombok.Data;
5
-
6
-import javax.validation.constraints.NotBlank;
7
-import javax.validation.constraints.NotNull;
8
-import javax.validation.constraints.Size;
9
-import java.util.Date;
10
-
11
-// AdLog.java
12
-@Data
13
-@TableName("novel_ad_log")
14
-public class AdLog {
15
-    @TableId(type = IdType.AUTO)
16
-    private Long id;
17
-
18
-    @NotNull(message = "用户ID不能为空")
19
-    private Long userId;
20
-
21
-    @NotNull(message = "章节ID不能为空")
22
-    private Long chapterId;
23
-
24
-    @NotBlank(message = "广告平台不能为空")
25
-    @Size(max = 50, message = "广告平台标识过长")
26
-    private String adPlatform;
27
-
28
-    @TableField(fill = FieldFill.INSERT)
29
-    private Date viewTime;
30
-
31
-    private String deviceInfo;
32
-
33
-    // 状态字段:0-未同步 1-已同步
34
-    private Integer syncStatus;
35
-
36
-    // 确保有默认构造方法
37
-    public AdLog() {}
38
-
39
-    public String deviceId;
40
-}

+ 0
- 26
RuoYi-Vue/ruoyi-novel/src/main/java/com/ruoyi/novel/domain/AdPlatformConfig.java Прегледај датотеку

@@ -1,26 +0,0 @@
1
-package com.ruoyi.novel.domain;
2
-
3
-import com.baomidou.mybatisplus.annotation.TableId;
4
-import com.baomidou.mybatisplus.annotation.TableName;
5
-import lombok.Data;
6
-
7
-@Data
8
-@TableName("novel_ad_config")
9
-public class AdPlatformConfig {
10
-    @TableId
11
-    private String platformCode;
12
-
13
-    private String platformName;
14
-    private String apiUrl;
15
-    private String authToken;
16
-    private String paramsTemplate;
17
-
18
-    // 添加带参数的构造方法
19
-    public AdPlatformConfig(String code, String name, String url, String token, String params) {
20
-        this.platformCode = code;
21
-        this.platformName = name;
22
-        this.apiUrl = url;
23
-        this.authToken = token;
24
-        this.paramsTemplate = params;
25
-    }
26
-}

+ 0
- 15
RuoYi-Vue/ruoyi-novel/src/main/java/com/ruoyi/novel/domain/ChapterDTO.java Прегледај датотеку

@@ -1,15 +0,0 @@
1
-package com.ruoyi.novel.domain;
2
-
3
-import lombok.Data;
4
-
5
-import javax.validation.constraints.NotBlank;
6
-import javax.validation.constraints.NotNull;
7
-
8
-@Data
9
-public class ChapterDTO {
10
-    @NotNull(message = "章节不能为空")
11
-    private NovelChapter chapter;
12
-
13
-    @NotBlank(message = "内容不能为空")
14
-    private String content;
15
-}

+ 0
- 39
RuoYi-Vue/ruoyi-novel/src/main/java/com/ruoyi/novel/domain/Novel.java Прегледај датотеку

@@ -1,39 +0,0 @@
1
-package com.ruoyi.novel.domain;
2
-
3
-import com.baomidou.mybatisplus.annotation.IdType;
4
-import com.baomidou.mybatisplus.annotation.TableId;
5
-import com.baomidou.mybatisplus.annotation.TableName;
6
-import lombok.Data;
7
-import org.springframework.data.annotation.Id;
8
-import org.springframework.data.elasticsearch.annotations.Document;
9
-import org.springframework.data.elasticsearch.annotations.Field;
10
-import org.springframework.data.elasticsearch.annotations.FieldType;
11
-
12
-import java.util.Date;
13
-
14
-// Novel.java
15
-@Data
16
-@TableName("novel")
17
-@Document(indexName = "novels")
18
-public class Novel {
19
-    @Id
20
-    @TableId(type = IdType.AUTO)
21
-    private Long id;
22
-    @Field(type = FieldType.Text, analyzer = "ik_max_word")
23
-    private String title;
24
-    @Field(type = FieldType.Keyword)
25
-    private String author;
26
-    private String coverImg;
27
-    @Field(type = FieldType.Long)
28
-    private Long categoryId;
29
-    @Field(type = FieldType.Keyword)
30
-    private String status;// 连载/完本
31
-    @Field(type = FieldType.Text, analyzer = "ik_smart")
32
-    private String description;
33
-    private Long wordCount;
34
-    @Field(type = FieldType.Long)
35
-    private Long readCount;
36
-    @Field(type = FieldType.Date)
37
-    private Date createTime;
38
-    private Date updateTime;
39
-}

+ 0
- 25
RuoYi-Vue/ruoyi-novel/src/main/java/com/ruoyi/novel/domain/NovelChapter.java Прегледај датотеку

@@ -1,25 +0,0 @@
1
-package com.ruoyi.novel.domain;
2
-
3
-import com.baomidou.mybatisplus.annotation.IdType;
4
-import com.baomidou.mybatisplus.annotation.TableId;
5
-import com.baomidou.mybatisplus.annotation.TableName;
6
-import lombok.Data;
7
-
8
-import java.util.Date;
9
-
10
-// NovelChapter.java
11
-@Data
12
-@TableName("novel_chapter")
13
-public class NovelChapter {
14
-    @TableId(type = IdType.AUTO)
15
-    private Long id;
16
-    private Long novelId;
17
-    private String chapterTitle;
18
-    private Integer chapterOrder;
19
-    private Date publishTime;
20
-    private String isVip;
21
-
22
-    public Date createTime;
23
-
24
-    public Date updateTime;
25
-}

+ 0
- 14
RuoYi-Vue/ruoyi-novel/src/main/java/com/ruoyi/novel/domain/NovelContent.java Прегледај датотеку

@@ -1,14 +0,0 @@
1
-package com.ruoyi.novel.domain;
2
-
3
-import com.baomidou.mybatisplus.annotation.TableId;
4
-import com.baomidou.mybatisplus.annotation.TableName;
5
-import lombok.Data;
6
-
7
-// NovelContent.java
8
-@Data
9
-@TableName("novel_content")
10
-public class NovelContent {
11
-    @TableId
12
-    private Long chapterId;
13
-    private String content;
14
-}

+ 0
- 27
RuoYi-Vue/ruoyi-novel/src/main/java/com/ruoyi/novel/domain/ReadingRecord.java Прегледај датотеку

@@ -1,27 +0,0 @@
1
-package com.ruoyi.novel.domain;
2
-
3
-import com.baomidou.mybatisplus.annotation.IdType;
4
-import com.baomidou.mybatisplus.annotation.TableId;
5
-import com.baomidou.mybatisplus.annotation.TableName;
6
-import lombok.Data;
7
-
8
-import javax.validation.constraints.NotNull;
9
-import java.util.Date;
10
-
11
-@Data
12
-@TableName("reading_history")
13
-public class ReadingRecord {
14
-    @TableId(type = IdType.AUTO)
15
-    private Long id;
16
-    @NotNull(message = "用户ID不能为空")
17
-    private Long userId;
18
-
19
-    @NotNull(message = "章节ID不能为空")
20
-    private Long chapterId;
21
-
22
-    @NotNull(message = "小说ID不能为空")
23
-    private Long novelId;
24
-    private Integer progress;
25
-    private Long position;
26
-    private Date lastReadTime;
27
-}

+ 0
- 30
RuoYi-Vue/ruoyi-novel/src/main/java/com/ruoyi/novel/domain/RoyaltyReport.java Прегледај датотеку

@@ -1,30 +0,0 @@
1
-package com.ruoyi.novel.domain;
2
-
3
-import lombok.Data;
4
-
5
-import java.math.BigDecimal;
6
-
7
-// RoyaltyReport.java
8
-@Data
9
-public class RoyaltyReport {
10
-    private Long authorId;
11
-    private String authorName;
12
-    private String month;
13
-    private BigDecimal totalReads;
14
-    private BigDecimal royaltyRate;
15
-    private BigDecimal handlingFeeRate;
16
-    private BigDecimal handlingFee;
17
-    private BigDecimal netAmount;
18
-    private String currency = "CNY";
19
-
20
-    // 计算逻辑
21
-    public void calculate(BigDecimal reads, BigDecimal rate, BigDecimal feeRate) {
22
-        this.totalReads = reads;
23
-        this.royaltyRate = rate;
24
-        this.handlingFeeRate = feeRate;
25
-
26
-        BigDecimal rawAmount = reads.multiply(rate);
27
-        this.handlingFee = rawAmount.multiply(feeRate);
28
-        this.netAmount = rawAmount.subtract(handlingFee);
29
-    }
30
-}

+ 0
- 26
RuoYi-Vue/ruoyi-novel/src/main/java/com/ruoyi/novel/domain/RoyaltySummary.java Прегледај датотеку

@@ -1,26 +0,0 @@
1
-package com.ruoyi.novel.domain;
2
-
3
-import com.baomidou.mybatisplus.annotation.TableId;
4
-import com.baomidou.mybatisplus.annotation.TableName;
5
-import lombok.Data;
6
-
7
-import java.math.BigDecimal;
8
-import java.util.Date;
9
-
10
-// RoyaltySummary.java
11
-// RoyaltySummary.java
12
-@Data
13
-@TableName("novel_royalty_summary")
14
-public class RoyaltySummary {
15
-    @TableId
16
-    private Long authorId;
17
-
18
-    @TableId
19
-    private String month; // yyyy-MM格式
20
-
21
-    private BigDecimal totalReads;
22
-    private Date lastSyncTime;
23
-
24
-    public RoyaltySummary(long l, String s, BigDecimal bigDecimal) {
25
-    }
26
-}

+ 0
- 26
RuoYi-Vue/ruoyi-novel/src/main/java/com/ruoyi/novel/domain/StoryOption.java Прегледај датотеку

@@ -1,26 +0,0 @@
1
-package com.ruoyi.novel.domain;
2
-
3
-import com.baomidou.mybatisplus.annotation.IdType;
4
-import com.baomidou.mybatisplus.annotation.TableId;
5
-import com.baomidou.mybatisplus.annotation.TableName;
6
-import lombok.Data;
7
-
8
-import javax.validation.constraints.NotBlank;
9
-import javax.validation.constraints.NotNull;
10
-
11
-// StoryOption.java
12
-@Data
13
-//@TableName("novel_story_option")
14
-@TableName("story_option")
15
-public class StoryOption {
16
-    @TableId(type = IdType.AUTO)
17
-    private Long id;
18
-
19
-    @NotNull(message = "故事ID不能为空")
20
-    private Long storyId;
21
-
22
-    @NotBlank(message = "选项内容不能为空")
23
-    private String optionText;
24
-
25
-    private Integer voteCount;
26
-}

+ 0
- 26
RuoYi-Vue/ruoyi-novel/src/main/java/com/ruoyi/novel/domain/VoteRecord.java Прегледај датотеку

@@ -1,26 +0,0 @@
1
-package com.ruoyi.novel.domain;
2
-
3
-import com.baomidou.mybatisplus.annotation.*;
4
-import lombok.Data;
5
-
6
-import java.util.Date;
7
-
8
-// VoteRecord.java
9
-// VoteRecord.java
10
-@Data
11
-@TableName("novel_vote_log")
12
-public class VoteRecord {
13
-    @TableId(type = IdType.AUTO)
14
-    private Long id;
15
-
16
-    private Long userId;
17
-    private Long storyId;
18
-    private Long optionId;
19
-
20
-    @TableField(fill = FieldFill.INSERT)
21
-    private Date voteTime;
22
-
23
-    private String generatedContent;
24
-
25
-    private Integer notifyStatus; // 0-未通知 1-已通知
26
-}

+ 0
- 18
RuoYi-Vue/ruoyi-novel/src/main/java/com/ruoyi/novel/domain/VoteRequest.java Прегледај датотеку

@@ -1,18 +0,0 @@
1
-package com.ruoyi.novel.domain;
2
-
3
-import lombok.Data;
4
-
5
-import javax.validation.constraints.NotNull;
6
-
7
-// VoteRequest.java
8
-@Data
9
-public class VoteRequest {
10
-    @NotNull(message = "用户ID不能为空")
11
-    private Long userId;
12
-
13
-    @NotNull(message = "故事ID不能为空")
14
-    private Long storyId;
15
-
16
-    @NotNull(message = "选项ID不能为空")
17
-    private Long optionId;
18
-}

+ 0
- 45
RuoYi-Vue/ruoyi-novel/src/main/java/com/ruoyi/novel/exception/GlobalExceptionHandler.java Прегледај датотеку

@@ -1,45 +0,0 @@
1
-package com.ruoyi.novel.exception;
2
-
3
-import com.ruoyi.common.core.domain.AjaxResult;
4
-import com.ruoyi.common.exception.ServiceException;
5
-import com.ruoyi.novel.service.impl.ReadingHistoryServiceImpl;
6
-import org.slf4j.Logger;
7
-import org.slf4j.LoggerFactory;
8
-import org.springframework.web.bind.MethodArgumentNotValidException;
9
-import org.springframework.web.bind.annotation.ExceptionHandler;
10
-import org.springframework.web.bind.annotation.RestControllerAdvice;
11
-
12
-
13
-// 新增全局异常处理器
14
-@RestControllerAdvice
15
-public class GlobalExceptionHandler {
16
-
17
-    private static final Logger logger = LoggerFactory.getLogger(GlobalExceptionHandler.class);
18
-
19
-    /**
20
-     * 业务异常处理
21
-     */
22
-    @ExceptionHandler(ServiceException.class)
23
-    public AjaxResult handleServiceException(ServiceException e) {
24
-        logger.error(e.getMessage(), e);
25
-        return AjaxResult.error(e.getMessage());
26
-    }
27
-
28
-    /**
29
-     * 参数校验异常
30
-     */
31
-    @ExceptionHandler(MethodArgumentNotValidException.class)
32
-    public AjaxResult handleMethodArgumentNotValidException(MethodArgumentNotValidException e) {
33
-        String message = e.getBindingResult().getFieldError().getDefaultMessage();
34
-        return AjaxResult.error(message);
35
-    }
36
-
37
-    /**
38
-     * 系统异常
39
-     */
40
-    @ExceptionHandler(Exception.class)
41
-    public AjaxResult handleException(Exception e) {
42
-        logger.error(e.getMessage(), e);
43
-        return AjaxResult.error("系统繁忙,请稍后再试");
44
-    }
45
-}

+ 0
- 20
RuoYi-Vue/ruoyi-novel/src/main/java/com/ruoyi/novel/mapper/AdLogMapper.java Прегледај датотеку

@@ -1,20 +0,0 @@
1
-package com.ruoyi.novel.mapper;
2
-
3
-import com.baomidou.mybatisplus.core.mapper.BaseMapper;
4
-import com.ruoyi.novel.domain.AdLog;
5
-import org.apache.ibatis.annotations.Mapper;
6
-import org.apache.ibatis.annotations.Param;
7
-import org.apache.ibatis.annotations.Select;
8
-
9
-import java.util.List;
10
-
11
-// AdLogMapper.java
12
-@Mapper
13
-public interface AdLogMapper extends BaseMapper<AdLog> {
14
-
15
-    @Select("SELECT COUNT(*) FROM novel_ad_log WHERE user_id = #{userId} AND chapter_id = #{chapterId}")
16
-    int countByUserAndChapter(@Param("userId") Long userId, @Param("chapterId") Long chapterId);
17
-
18
-    @Select("SELECT * FROM novel_ad_log WHERE sync_status = 0 ORDER BY view_time ASC LIMIT 100")
19
-    List<AdLog> selectUnsyncedLogs();
20
-}

+ 0
- 8
RuoYi-Vue/ruoyi-novel/src/main/java/com/ruoyi/novel/mapper/AdPlatformConfigMapper.java Прегледај датотеку

@@ -1,8 +0,0 @@
1
-package com.ruoyi.novel.mapper;
2
-
3
-import com.baomidou.mybatisplus.core.mapper.BaseMapper;
4
-import com.ruoyi.novel.domain.AdPlatformConfig;
5
-
6
-public interface AdPlatformConfigMapper extends BaseMapper<AdPlatformConfig> {
7
-    // 继承BaseMapper即拥有selectList/insert等方法
8
-}

+ 0
- 26
RuoYi-Vue/ruoyi-novel/src/main/java/com/ruoyi/novel/mapper/NovelChapterMapper.java Прегледај датотеку

@@ -1,26 +0,0 @@
1
-package com.ruoyi.novel.mapper;
2
-
3
-import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
4
-import com.ruoyi.novel.domain.NovelChapter;
5
-import org.apache.ibatis.annotations.Mapper;
6
-
7
-import java.util.List;
8
-
9
-// NovelChapterMapper.java
10
-@Mapper
11
-public interface NovelChapterMapper {
12
-    List<NovelChapter> selectChapterListByNovelId(Long novelId);
13
-    NovelChapter selectChapterById(Long chapterId);
14
-    int insertChapter(NovelChapter chapter);
15
-    int updateChapter(NovelChapter chapter);
16
-
17
-    List<NovelChapter> selectList(QueryWrapper<NovelChapter> orderByAsc);
18
-
19
-    void insert(NovelChapter chapter);
20
-
21
-    void updateById(NovelChapter chapter);
22
-
23
-    NovelChapter selectById(Long chapterId);
24
-
25
-    int deleteBatchIds(List<Long> asList);
26
-}

+ 0
- 14
RuoYi-Vue/ruoyi-novel/src/main/java/com/ruoyi/novel/mapper/NovelContentMapper.java Прегледај датотеку

@@ -1,14 +0,0 @@
1
-package com.ruoyi.novel.mapper;
2
-
3
-import com.baomidou.mybatisplus.core.mapper.BaseMapper;
4
-import com.ruoyi.novel.domain.NovelContent;
5
-import org.apache.ibatis.annotations.Mapper;
6
-import org.apache.ibatis.annotations.Param;
7
-import org.apache.ibatis.annotations.Update;
8
-
9
-@Mapper
10
-public interface NovelContentMapper extends BaseMapper<NovelContent> {
11
-    // 特殊方法可在此定义
12
-    @Update("UPDATE novel_content SET content = #{content} WHERE chapter_id = #{chapterId}")
13
-    int updateContent(@Param("chapterId") Long chapterId, @Param("content") String content);
14
-}

+ 0
- 32
RuoYi-Vue/ruoyi-novel/src/main/java/com/ruoyi/novel/mapper/NovelMapper.java Прегледај датотеку

@@ -1,32 +0,0 @@
1
-package com.ruoyi.novel.mapper;
2
-
3
-import com.baomidou.mybatisplus.core.mapper.BaseMapper;
4
-import com.ruoyi.novel.domain.Novel;
5
-import org.apache.ibatis.annotations.Param;
6
-import org.apache.ibatis.annotations.Select;
7
-import org.apache.ibatis.annotations.Update;
8
-
9
-import java.util.List;
10
-
11
-// NovelMapper.java
12
-public interface NovelMapper extends BaseMapper<Novel> {
13
-    List<Novel> selectNovelList(Novel novel);
14
-    Novel selectNovelById(Long id);
15
-    int insertNovel(Novel novel);
16
-    int updateNovel(Novel novel);
17
-    int deleteNovelByIds(Long[] ids);
18
-
19
-    // 以下方法已由MyBatis-Plus实现,无需额外代码
20
-    // int updateById(Novel novel);
21
-    // int deleteBatchIds(@Param("ids") List<Long> ids);
22
-    // Novel selectById(Long id);
23
-
24
-    // 自定义方法:根据分类ID查询小说
25
-    @Select("SELECT * FROM novel WHERE category_id = #{categoryId}")
26
-    List<Novel> selectByCategoryId(Long categoryId);
27
-
28
-    // 自定义方法:更新阅读量
29
-    @Update("UPDATE novel SET read_count = read_count + #{increment} WHERE id = #{id}")
30
-    int incrementReadCount(@Param("id") Long id, @Param("increment") Long increment);
31
-}
32
-

+ 0
- 34
RuoYi-Vue/ruoyi-novel/src/main/java/com/ruoyi/novel/mapper/ReadingHistoryMapper.java Прегледај датотеку

@@ -1,34 +0,0 @@
1
-package com.ruoyi.novel.mapper;
2
-
3
-import com.baomidou.mybatisplus.core.mapper.BaseMapper;
4
-import com.ruoyi.novel.domain.ReadingRecord;
5
-import org.apache.ibatis.annotations.Mapper;
6
-import org.apache.ibatis.annotations.Param;
7
-import org.apache.ibatis.annotations.Select;
8
-import org.apache.ibatis.annotations.Update;
9
-
10
-// ReadingHistoryMapper.java
11
-@Mapper
12
-public interface ReadingHistoryMapper extends BaseMapper<ReadingRecord> {
13
-
14
-    // 根据用户和章节查询记录
15
-    @Select("SELECT * FROM reading_history " +
16
-            "WHERE user_id = #{userId} AND chapter_id = #{chapterId}")
17
-    ReadingRecord selectByUserAndChapter(@Param("userId") Long userId,
18
-                                         @Param("chapterId") Long chapterId);
19
-
20
-    // 获取用户最后阅读位置
21
-    @Select("SELECT * FROM reading_history " +
22
-            "WHERE user_id = #{userId} AND novel_id = #{novelId} " +
23
-            "ORDER BY last_read_time DESC LIMIT 1")
24
-    ReadingRecord selectLastPosition(@Param("userId") Long userId,
25
-                                     @Param("novelId") Long novelId);
26
-
27
-    // 更新阅读进度
28
-    @Update("UPDATE reading_history SET " +
29
-            "progress = #{progress}, " +
30
-            "position = #{position}, " +
31
-            "last_read_time = NOW() " +
32
-            "WHERE id = #{id}")
33
-    int updateReadingProgress(ReadingRecord record);
34
-}

+ 0
- 33
RuoYi-Vue/ruoyi-novel/src/main/java/com/ruoyi/novel/mapper/RoyaltySummaryMapper.java Прегледај датотеку

@@ -1,33 +0,0 @@
1
-package com.ruoyi.novel.mapper;
2
-
3
-import com.baomidou.mybatisplus.core.mapper.BaseMapper;
4
-import com.ruoyi.novel.domain.RoyaltySummary;
5
-import org.apache.ibatis.annotations.*;
6
-
7
-// RoyaltySummaryMapper.java
8
-@Mapper
9
-public interface RoyaltySummaryMapper extends BaseMapper<RoyaltySummary> {
10
-
11
-    @Select("SELECT * FROM novel_royalty_summary " +
12
-            "WHERE author_id = #{authorId} AND month = #{month}")
13
-    RoyaltySummary selectByAuthorAndMonth(
14
-            @Param("authorId") Long authorId,
15
-            @Param("month") String month
16
-    );
17
-
18
-    @Update("INSERT INTO novel_royalty_summary (author_id, month, total_reads, last_sync_time) " +
19
-            "VALUES (#{authorId}, #{month}, #{totalReads}, NOW()) " +
20
-            "ON DUPLICATE KEY UPDATE total_reads = #{totalReads}, last_sync_time = NOW()")
21
-    int upsertSummary(RoyaltySummary summary);
22
-
23
-
24
-    // 添加 insertOrUpdate 方法
25
-    @Insert("<script>" +
26
-            "INSERT INTO novel_royalty_summary (author_id, month, total_reads, last_sync_time) " +
27
-            "VALUES (#{authorId}, #{month}, #{totalReads}, NOW()) " +
28
-            "ON DUPLICATE KEY UPDATE " +
29
-            "total_reads = VALUES(total_reads), " +
30
-            "last_sync_time = NOW()" +
31
-            "</script>")
32
-    int insertOrUpdate(RoyaltySummary summary);
33
-}

+ 0
- 40
RuoYi-Vue/ruoyi-novel/src/main/java/com/ruoyi/novel/mapper/StoryOptionMapper.java Прегледај датотеку

@@ -1,40 +0,0 @@
1
-package com.ruoyi.novel.mapper;
2
-
3
-import com.baomidou.mybatisplus.core.mapper.BaseMapper;
4
-import com.ruoyi.novel.domain.StoryOption;
5
-import org.apache.ibatis.annotations.Mapper;
6
-import org.apache.ibatis.annotations.Param;
7
-import org.apache.ibatis.annotations.Select;
8
-import org.apache.ibatis.annotations.Update;
9
-
10
-import java.util.List;
11
-
12
-// StoryOptionMapper.java
13
-@Mapper
14
-public interface StoryOptionMapper extends BaseMapper<StoryOption> {
15
-
16
-    // 增加选项投票数
17
-    @Update("UPDATE story_option SET vote_count = vote_count + 1 WHERE id = #{optionId}")
18
-    int incrementVoteCount(@Param("optionId") Long optionId);
19
-
20
-    // 根据章节ID获取选项
21
-    @Select("SELECT * FROM story_option WHERE chapter_id = #{chapterId} ORDER BY sort_order")
22
-    List<StoryOption> selectByChapterId(Long chapterId);
23
-
24
-    // 批量更新选项投票数
25
-    @Update("<script>" +
26
-            "UPDATE story_option SET vote_count = CASE id " +
27
-            "<foreach collection='options' item='opt'>" +
28
-            "WHEN #{opt.id} THEN #{opt.voteCount} " +
29
-            "</foreach>" +
30
-            "END WHERE id IN " +
31
-            "<foreach collection='options' item='opt' open='(' separator=',' close=')'>" +
32
-            "#{opt.id}" +
33
-            "</foreach>" +
34
-            "</script>")
35
-    int batchUpdateVoteCount(@Param("options") List<StoryOption> options);
36
-
37
-    @Update("UPDATE story_option SET vote_count = vote_count + 1 WHERE id = #{optionId}")
38
-    int incrementOptionVote(@Param("optionId") Long optionId);
39
-
40
-}

+ 0
- 46
RuoYi-Vue/ruoyi-novel/src/main/java/com/ruoyi/novel/mapper/VoteRecordMapper.java Прегледај датотеку

@@ -1,46 +0,0 @@
1
-package com.ruoyi.novel.mapper;
2
-
3
-import com.baomidou.mybatisplus.core.mapper.BaseMapper;
4
-import com.ruoyi.novel.domain.VoteRecord;
5
-import lombok.Data;
6
-import org.apache.ibatis.annotations.*;
7
-
8
-import java.util.List;
9
-
10
-// VoteRecordMapper.java
11
-@Mapper
12
-public interface VoteRecordMapper extends BaseMapper<VoteRecord> {
13
-
14
-    @Select("SELECT COUNT(*) FROM novel_vote_log " +
15
-            "WHERE user_id = #{userId} AND story_id = #{storyId}")
16
-    int countUserVotesForStory(@Param("userId") Long userId, @Param("storyId") Long storyId);
17
-
18
-    @Update("UPDATE novel_vote_log SET notify_status = #{status} WHERE id = #{id}")
19
-    int updateNotifyStatus(@Param("id") Long id, @Param("status") Integer status);
20
-
21
-    @Select("SELECT * FROM novel_vote_log WHERE notify_status = 0 ORDER BY vote_time ASC LIMIT 50")
22
-    List<VoteRecord> selectUnnotifiedRecords();
23
-
24
-
25
-    // 插入投票记录(带生成内容)
26
-    @Insert("INSERT INTO vote_record (user_id, story_id, option_id, vote_time, generated_content) " +
27
-            "VALUES (#{userId}, #{storyId}, #{optionId}, NOW(), #{generatedContent})")
28
-    @Options(useGeneratedKeys = true, keyProperty = "id")
29
-    int insertVoteRecord(VoteRecord record);
30
-
31
-    // 获取用户投票记录
32
-    @Select("SELECT * FROM vote_record WHERE user_id = #{userId} ORDER BY vote_time DESC")
33
-    List<VoteRecord> selectByUserId(Long userId);
34
-
35
-    // 获取故事投票统计
36
-    @Select("SELECT option_id, COUNT(*) AS vote_count FROM vote_record " +
37
-            "WHERE story_id = #{storyId} GROUP BY option_id")
38
-    List<VoteStats> getVoteStatsByStory(Long storyId);
39
-
40
-    // 投票统计DTO
41
-    @Data
42
-    class VoteStats {
43
-        private Long optionId;
44
-        private Integer voteCount;
45
-    }
46
-}

+ 0
- 10
RuoYi-Vue/ruoyi-novel/src/main/java/com/ruoyi/novel/service/AdConfigService.java Прегледај датотеку

@@ -1,10 +0,0 @@
1
-package com.ruoyi.novel.service;
2
-
3
-import com.ruoyi.novel.domain.AdPlatformConfig;
4
-
5
-public interface AdConfigService {
6
-
7
-    void refreshConfigCache();
8
-
9
-    AdPlatformConfig getConfig(String adPlatform);
10
-}

+ 0
- 9
RuoYi-Vue/ruoyi-novel/src/main/java/com/ruoyi/novel/service/AdLogService.java Прегледај датотеку

@@ -1,9 +0,0 @@
1
-package com.ruoyi.novel.service;
2
-
3
-import com.ruoyi.novel.domain.AdLog;
4
-import org.springframework.transaction.annotation.Transactional;
5
-
6
-public interface AdLogService {
7
-    @Transactional
8
-    void logAdView(AdLog adLog);
9
-}

+ 0
- 15
RuoYi-Vue/ruoyi-novel/src/main/java/com/ruoyi/novel/service/AdService.java Прегледај датотеку

@@ -1,15 +0,0 @@
1
-package com.ruoyi.novel.service;
2
-
3
-import com.ruoyi.novel.domain.AdCountRequest;
4
-import com.ruoyi.novel.domain.AdLog;
5
-import org.springframework.stereotype.Service;
6
-
7
-import java.util.List;
8
-@Service
9
-// AdService.java
10
-public interface AdService {
11
-    void logAdView(AdCountRequest request);
12
-    List<AdLog> getAdLogsByUser(Long userId);
13
-
14
-    void logAdView(String userId, Long chapterId, String adType, String source);
15
-}

+ 0
- 10
RuoYi-Vue/ruoyi-novel/src/main/java/com/ruoyi/novel/service/AdSyncService.java Прегледај датотеку

@@ -1,10 +0,0 @@
1
-package com.ruoyi.novel.service;
2
-
3
-import com.ruoyi.novel.domain.AdLog;
4
-import com.ruoyi.novel.domain.AdPlatformConfig;
5
-
6
-public interface AdSyncService {
7
-    void syncToTencent(AdLog adLog, AdPlatformConfig config);
8
-
9
-    void syncToPangle(AdLog adLog, AdPlatformConfig config);
10
-}

+ 0
- 13
RuoYi-Vue/ruoyi-novel/src/main/java/com/ruoyi/novel/service/ChapterService.java Прегледај датотеку

@@ -1,13 +0,0 @@
1
-package com.ruoyi.novel.service;
2
-
3
-import com.ruoyi.novel.domain.NovelChapter;
4
-
5
-import java.util.List;
6
-
7
-// ChapterService.java
8
-public interface ChapterService {
9
-    List<NovelChapter> selectChapterListByNovelId(Long novelId);
10
-    int saveChapter(NovelChapter chapter, String content);
11
-    NovelChapter getChapterById(Long chapterId);
12
-    int deleteChapters(Long[] ids);
13
-}

+ 0
- 22
RuoYi-Vue/ruoyi-novel/src/main/java/com/ruoyi/novel/service/IAdService.java Прегледај датотеку

@@ -1,22 +0,0 @@
1
-package com.ruoyi.novel.service;
2
-
3
-import com.ruoyi.novel.domain.AdCountRequest;
4
-import com.ruoyi.novel.domain.AdLog;
5
-import com.ruoyi.novel.domain.AdPlatformConfig;
6
-import org.springframework.stereotype.Service;
7
-
8
-import java.util.List;
9
-import java.util.Map;
10
-
11
-@Service
12
-public interface IAdService {
13
-    void logAdView(AdLog adLog);
14
-
15
-    void logAdView(AdCountRequest request);
16
-
17
-    List<AdLog> getAdLogsByUser(Long userId);
18
-
19
-    void syncWithAdPlatform(AdLog adLog);
20
-    void retryFailedSyncs();
21
-    Map<String, AdPlatformConfig> loadAdConfigs();
22
-}

+ 0
- 13
RuoYi-Vue/ruoyi-novel/src/main/java/com/ruoyi/novel/service/IFinanceService.java Прегледај датотеку

@@ -1,13 +0,0 @@
1
-package com.ruoyi.novel.service;
2
-
3
-import com.ruoyi.novel.domain.RoyaltyReport;
4
-
5
-import java.math.BigDecimal;
6
-
7
-// IFinanceService.java
8
-public interface IFinanceService {
9
-    RoyaltyReport calculateRoyalty(Long authorId, String month);
10
-    void syncRoyaltyData();
11
-    BigDecimal getRoyaltyRate(Long authorId);
12
-    BigDecimal getHandlingFeeRate();
13
-}

+ 0
- 16
RuoYi-Vue/ruoyi-novel/src/main/java/com/ruoyi/novel/service/IVoteService.java Прегледај датотеку

@@ -1,16 +0,0 @@
1
-package com.ruoyi.novel.service;
2
-
3
-import com.ruoyi.novel.domain.VoteRecord;
4
-import com.ruoyi.novel.domain.VoteRequest;
5
-
6
-// IVoteService.java
7
-public interface IVoteService {
8
-    String processVote(VoteRequest request);
9
-    void generateStoryContent(VoteRecord record);
10
-    void notifyPhpSystem(VoteRecord record);
11
-    void retryFailedNotifications();
12
-
13
-    void notifyPhpSystem(VoteRequest request, String generatedContent);
14
-
15
-    String generateStoryContent(Long storyId, Long optionId);
16
-}

+ 0
- 13
RuoYi-Vue/ruoyi-novel/src/main/java/com/ruoyi/novel/service/NovelSearchService.java Прегледај датотеку

@@ -1,13 +0,0 @@
1
-package com.ruoyi.novel.service;
2
-
3
-import com.ruoyi.novel.domain.Novel;
4
-
5
-import java.util.List;
6
-
7
-// NovelSearchService.java
8
-public interface NovelSearchService {
9
-    List<Novel> searchNovels(String keyword);
10
-    void indexNovel(Novel novel);
11
-    void updateNovelIndex(Novel novel);
12
-    void deleteNovelIndex(Long id);
13
-}

+ 0
- 16
RuoYi-Vue/ruoyi-novel/src/main/java/com/ruoyi/novel/service/NovelService.java Прегледај датотеку

@@ -1,16 +0,0 @@
1
-package com.ruoyi.novel.service;
2
-
3
-import com.ruoyi.novel.domain.Novel;
4
-import org.springframework.transaction.annotation.Transactional;
5
-
6
-import java.util.List;
7
-
8
-public interface NovelService {
9
-    List<Novel> selectNovelList(Novel novel);
10
-
11
-    @Transactional
12
-    int insertNovel(Novel novel);
13
-    int updateNovel(Novel novel);
14
-    int deleteNovelByIds(Long[] ids);
15
-    Novel selectNovelById(Long id);
16
-}

+ 0
- 9
RuoYi-Vue/ruoyi-novel/src/main/java/com/ruoyi/novel/service/ReadingHistoryService.java Прегледај датотеку

@@ -1,9 +0,0 @@
1
-package com.ruoyi.novel.service;
2
-
3
-import com.ruoyi.novel.domain.ReadingRecord;
4
-
5
-// ReadingHistoryService.java
6
-public interface ReadingHistoryService {
7
-    void recordReading(ReadingRecord record);
8
-    ReadingRecord getLastPosition(Long userId, Long novelId);
9
-}

+ 0
- 29
RuoYi-Vue/ruoyi-novel/src/main/java/com/ruoyi/novel/service/VoteService.java Прегледај датотеку

@@ -1,29 +0,0 @@
1
-package com.ruoyi.novel.service;
2
-
3
-import com.ruoyi.novel.domain.VoteRecord;
4
-import com.ruoyi.novel.domain.VoteRequest;
5
-import org.springframework.scheduling.annotation.Async;
6
-import org.springframework.scheduling.annotation.Scheduled;
7
-
8
-// VoteService.java
9
-public interface VoteService {
10
-    String processVote(VoteRequest request);
11
-
12
-    String generateStoryContent(Long storyId, Long optionId);
13
-
14
-    @Async("voteTaskExecutor")
15
-    void generateStoryContent(VoteRecord record);
16
-
17
-    void notifyPhpSystem(VoteRequest request, String content);
18
-
19
-    // 添加方法实现
20
-    void incrementOptionVote(Long optionId);
21
-
22
-    boolean canUserVote(Long userId);
23
-
24
-    @Async("voteTaskExecutor")
25
-    void notifyPhpSystem(VoteRecord record);
26
-
27
-    @Scheduled(cron = "0 */10 * * * ?") // 每10分钟执行一次
28
-    void retryFailedNotifications();
29
-}

+ 0
- 69
RuoYi-Vue/ruoyi-novel/src/main/java/com/ruoyi/novel/service/impl/AdConfigServiceImpl.java Прегледај датотеку

@@ -1,69 +0,0 @@
1
-package com.ruoyi.novel.service.impl;
2
-
3
-import com.ruoyi.novel.domain.AdPlatformConfig;
4
-import com.ruoyi.novel.mapper.AdPlatformConfigMapper;
5
-import com.ruoyi.novel.service.AdConfigService;
6
-import org.springframework.beans.factory.annotation.Autowired;
7
-import org.springframework.stereotype.Service;
8
-
9
-import javax.annotation.PostConstruct;
10
-import java.util.HashMap;
11
-import java.util.Map;
12
-import java.util.function.Function;
13
-import java.util.stream.Collectors;
14
-
15
-// AdConfigServiceImpl.java
16
-@Service
17
-public class AdConfigServiceImpl implements AdConfigService {
18
-
19
-    @Autowired
20
-    private AdPlatformConfigMapper configMapper;
21
-
22
-    private Map<String, AdPlatformConfig> adConfigCache;
23
-    private final Object lock = new Object();
24
-
25
-    @PostConstruct
26
-    public void init() {
27
-        refreshConfigCache();
28
-    }
29
-
30
-    @Override
31
-    public void refreshConfigCache() {
32
-        synchronized (lock) {
33
-            adConfigCache = configMapper.selectList(null).stream()
34
-                    .collect(Collectors.toMap(AdPlatformConfig::getPlatformCode, Function.identity()));
35
-
36
-            // 如果数据库为空,初始化默认配置
37
-            if (adConfigCache.isEmpty()) {
38
-                initDefaultConfigs();
39
-            }
40
-        }
41
-    }
42
-
43
-    private void initDefaultConfigs() {
44
-        adConfigCache = new HashMap<>();
45
-        adConfigCache.put("tencent", new AdPlatformConfig(
46
-                "tencent", "腾讯广告",
47
-                "https://ad.tencent.com/track",
48
-                "default_tencent_token",
49
-                "{\"user_id\":\"${userId}\",\"content_id\":\"${chapterId}\"}"
50
-        ));
51
-        adConfigCache.put("pangle", new AdPlatformConfig(
52
-                "pangle", "穿山甲",
53
-                "https://ad.pangle.com/api/v1/event",
54
-                "default_pangle_token",
55
-                "{\"user\":\"${userId}\",\"content_id\":\"${chapterId}\"}"
56
-        ));
57
-
58
-        // 保存默认配置到数据库
59
-        adConfigCache.values().forEach(configMapper::insert);
60
-    }
61
-
62
-    @Override
63
-    public AdPlatformConfig getConfig(String platformCode) {
64
-        if (adConfigCache == null) {
65
-            refreshConfigCache();
66
-        }
67
-        return adConfigCache.get(platformCode);
68
-    }
69
-}

+ 0
- 88
RuoYi-Vue/ruoyi-novel/src/main/java/com/ruoyi/novel/service/impl/AdLogServiceImpl.java Прегледај датотеку

@@ -1,88 +0,0 @@
1
-package com.ruoyi.novel.service.impl;
2
-
3
-import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
4
-import com.ruoyi.common.exception.ServiceException;
5
-import com.ruoyi.novel.domain.AdLog;
6
-import com.ruoyi.novel.domain.AdPlatformConfig;
7
-import com.ruoyi.novel.mapper.AdLogMapper;
8
-import com.ruoyi.novel.service.AdConfigService;
9
-import com.ruoyi.novel.service.AdLogService;
10
-import com.ruoyi.novel.service.AdSyncService;
11
-import lombok.extern.slf4j.Slf4j;
12
-import org.slf4j.Logger;
13
-import org.slf4j.LoggerFactory;
14
-import org.springframework.beans.factory.annotation.Autowired;
15
-import org.springframework.scheduling.annotation.Async;
16
-import org.springframework.scheduling.annotation.Scheduled;
17
-import org.springframework.stereotype.Service;
18
-import org.springframework.transaction.annotation.Transactional;
19
-
20
-import java.util.List;
21
-
22
-// AdLogServiceImpl.java
23
-@Service
24
-@Slf4j
25
-public class AdLogServiceImpl implements AdLogService {
26
-    private static final Logger logger = LoggerFactory.getLogger(AdLogServiceImpl.class);
27
-
28
-    @Autowired
29
-    private AdLogMapper adLogMapper;
30
-
31
-    @Autowired
32
-    private AdConfigService adConfigService;
33
-
34
-    @Autowired
35
-    private AdSyncService adSyncService;
36
-
37
-    @Override
38
-    @Transactional
39
-    public void logAdView(AdLog adLog) {
40
-        // 1. 保存到数据库
41
-        adLog.setSyncStatus(0); // 0=未同步
42
-        adLogMapper.insert(adLog);
43
-
44
-        // 2. 异步同步到广告平台
45
-        syncAdLogAsync(adLog);
46
-    }
47
-
48
-    @Async
49
-    public void syncAdLogAsync(AdLog adLog) {
50
-        try {
51
-            AdPlatformConfig config = adConfigService.getConfig(adLog.getAdPlatform());
52
-            if (config == null) {
53
-                throw new ServiceException("广告平台配置不存在: " + adLog.getAdPlatform());
54
-            }
55
-
56
-            // 根据平台选择同步方式
57
-            switch (adLog.getAdPlatform()) {
58
-                case "tencent":
59
-                    adSyncService.syncToTencent(adLog, config);
60
-                    break;
61
-                case "pangle":
62
-                    adSyncService.syncToPangle(adLog, config);
63
-                    break;
64
-                default:
65
-                    throw new ServiceException("不支持的广告平台: " + adLog.getAdPlatform());
66
-            }
67
-
68
-            // 更新同步状态
69
-            adLog.setSyncStatus(1); // 1=同步成功
70
-        } catch (Exception e) {
71
-            log.error("广告同步失败: {}", e.getMessage());
72
-            adLog.setSyncStatus(2); // 2=同步失败
73
-        }
74
-        adLogMapper.updateById(adLog);
75
-    }
76
-
77
-    @Scheduled(fixedRate = 300000) // 每5分钟执行一次
78
-    public void retryFailedSyncs() {
79
-        List<AdLog> failedLogs = adLogMapper.selectList(
80
-                new QueryWrapper<AdLog>().eq("sync_status", 2)
81
-        );
82
-
83
-        failedLogs.forEach(log -> {
84
-            logger.info("重试广告同步: ID={}, 平台={}", log.getId(), log.getAdPlatform());
85
-            syncAdLogAsync(log);
86
-        });
87
-    }
88
-}

+ 0
- 131
RuoYi-Vue/ruoyi-novel/src/main/java/com/ruoyi/novel/service/impl/AdServiceImpl.java Прегледај датотеку

@@ -1,131 +0,0 @@
1
-package com.ruoyi.novel.service.impl;
2
-
3
-import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
4
-import com.ruoyi.novel.domain.AdCountRequest;
5
-import com.ruoyi.novel.domain.AdLog;
6
-import com.ruoyi.novel.domain.AdPlatformConfig;
7
-import com.ruoyi.novel.mapper.AdLogMapper;
8
-import com.ruoyi.novel.service.IAdService;
9
-import com.ruoyi.novel.utils.AdPlatformClient;
10
-import org.slf4j.Logger;
11
-import org.slf4j.LoggerFactory;
12
-import org.springframework.beans.factory.annotation.Autowired;
13
-import org.springframework.scheduling.annotation.Async;
14
-import org.springframework.scheduling.annotation.Scheduled;
15
-import org.springframework.stereotype.Service;
16
-import org.springframework.transaction.annotation.Transactional;
17
-
18
-import java.util.Date;
19
-import java.util.HashMap;
20
-import java.util.List;
21
-import java.util.Map;
22
-
23
-@Service
24
-public class AdServiceImpl implements IAdService {
25
-    private static final Logger logger = LoggerFactory.getLogger(AdServiceImpl.class);
26
-    @Autowired
27
-    private AdLogMapper adLogMapper;
28
-
29
-    @Autowired
30
-    private AdPlatformClient adPlatformClient;
31
-
32
-    private Map<String, AdPlatformConfig> adConfigCache;
33
-    private final Object lock = new Object();
34
-    @Override
35
-    @Transactional
36
-    public void logAdView(AdLog adLog) {
37
-        // 防止重复记录
38
-        int count = adLogMapper.countByUserAndChapter(adLog.getUserId(), adLog.getChapterId());
39
-        if (count > 0) {
40
-            logger.warn("Duplicate ad log: user={}, chapter={}", adLog.getUserId(), adLog.getChapterId());
41
-            return;
42
-        }
43
-
44
-        adLog.setSyncStatus(0); // 未同步状态
45
-        adLogMapper.insert(adLog);
46
-    }
47
-
48
-//    @Override
49
-//    @Async("adTaskExecutor")
50
-//    public void syncWithAdPlatform(AdLog adLog) {
51
-//        try {
52
-//            adPlatformClient.syncAdPlatform(adLog);
53
-//            adLog.setSyncStatus(1); // 同步成功
54
-//        } catch (Exception e) {
55
-//            logger.error("Ad sync failed: {}", e.getMessage());
56
-//            adLog.setSyncStatus(2); // 同步失败
57
-//        }
58
-//        adLogMapper.updateById(adLog);
59
-//    }
60
-
61
-    @Override
62
-    @Scheduled(fixedRateString = "${scheduled.ad-retry-interval:300000}") // 默认5分钟重试
63
-    public void retryFailedSyncs() {
64
-        List<AdLog> failedLogs = adLogMapper.selectList(
65
-                new QueryWrapper<AdLog>().eq("sync_status", 2) // 2=同步失败状态
66
-        );
67
-        failedLogs.forEach(adLog -> {
68
-            try {
69
-                syncWithAdPlatform(adLog);  // 调用同步方法
70
-                adLog.setSyncStatus(1);      // 更新为成功状态
71
-                adLogMapper.updateById(adLog);
72
-            } catch (Exception e) {
73
-                logger.error("广告同步重试失败: ID={}", adLog.getId(), e);
74
-            }
75
-        });
76
-    }
77
-
78
-    @Override
79
-    public Map<String, AdPlatformConfig> loadAdConfigs() {
80
-        if (adConfigCache == null) {
81
-            synchronized (lock) {
82
-                if (adConfigCache == null) {
83
-                    // 实际应从数据库加载
84
-                    adConfigCache = new HashMap<>();
85
-                    adConfigCache.put("tencent", new AdPlatformConfig(
86
-                            "tencent", "腾讯广告",
87
-                            "https://ad.tencent.com/track",
88
-                            "token_123",
89
-                            "{\"user_id\":\"${userId}\",\"chapter_id\":\"${chapterId}\"}"
90
-                    ));
91
-                    // 其他平台配置...
92
-                }
93
-            }
94
-        }
95
-        return adConfigCache;
96
-    }
97
-    @Override
98
-    public void logAdView(AdCountRequest request) {
99
-        AdLog log = new AdLog();
100
-        log.setUserId(request.getUserId());
101
-        log.setChapterId(request.getChapterId());
102
-        log.setAdPlatform(request.getAdPlatform());
103
-        log.setDeviceId(request.getDeviceId());
104
-        log.setViewTime(new Date());
105
-        log.setSyncStatus(0); // 未同步
106
-
107
-        adLogMapper.insert(log);
108
-    }
109
-    @Override
110
-    public List<AdLog> getAdLogsByUser(Long userId) {
111
-        return adLogMapper.selectList(
112
-                new QueryWrapper<AdLog>().eq("user_id", userId)
113
-        );
114
-    }
115
-    @Override
116
-    public void syncWithAdPlatform(AdLog adLog) {
117
-        // 根据平台选择不同实现
118
-        switch (adLog.getAdPlatform()) {
119
-            case "tencent":
120
-                adPlatformClient.syncTencent(adLog);
121
-                adLog.setSyncStatus(1); // 同步成功
122
-                break;
123
-            case "pangle":
124
-                adPlatformClient.syncPangle(adLog);
125
-                adLog.setSyncStatus(1); // 同步成功
126
-                break;
127
-            default:
128
-                logger.warn("Unknown ad platform: {}", adLog.getAdPlatform());
129
-        }
130
-    }
131
-}

+ 0
- 82
RuoYi-Vue/ruoyi-novel/src/main/java/com/ruoyi/novel/service/impl/AdSyncServiceImpl.java Прегледај датотеку

@@ -1,82 +0,0 @@
1
-package com.ruoyi.novel.service.impl;
2
-
3
-import com.ruoyi.common.exception.ServiceException;
4
-import com.ruoyi.novel.domain.AdLog;
5
-import com.ruoyi.novel.domain.AdPlatformConfig;
6
-import com.ruoyi.novel.service.AdSyncService;
7
-import lombok.extern.slf4j.Slf4j;
8
-import org.springframework.beans.factory.annotation.Autowired;
9
-import org.springframework.http.*;
10
-import org.springframework.stereotype.Service;
11
-import org.springframework.web.client.RestTemplate;
12
-import org.springframework.web.util.UriComponentsBuilder;
13
-
14
-// AdSyncServiceImpl.java
15
-@Service
16
-@Slf4j
17
-public class AdSyncServiceImpl implements AdSyncService {
18
-
19
-    @Autowired
20
-    private RestTemplate restTemplate;
21
-
22
-    @Override
23
-    public void syncToTencent(AdLog adLog, AdPlatformConfig config) {
24
-        // 1. 构建请求参数
25
-        String payload = buildTencentPayload(adLog, config);
26
-
27
-        // 2. 创建请求头
28
-        HttpHeaders headers = new HttpHeaders();
29
-        headers.setContentType(MediaType.APPLICATION_JSON);
30
-        headers.setBearerAuth(config.getAuthToken());
31
-
32
-        // 3. 发送请求
33
-        HttpEntity<String> entity = new HttpEntity<>(payload, headers);
34
-        ResponseEntity<String> response = restTemplate.postForEntity(
35
-                config.getApiUrl(), entity, String.class);
36
-
37
-        // 4. 处理响应
38
-        if (response.getStatusCode() != HttpStatus.OK) {
39
-            throw new ServiceException("腾讯广告同步失败: " + response.getBody());
40
-        }
41
-        log.info("腾讯广告同步成功: chapter={}, user={}", adLog.getChapterId(), adLog.getUserId());
42
-    }
43
-
44
-    private String buildTencentPayload(AdLog adLog, AdPlatformConfig config) {
45
-        // 使用模板生成请求体
46
-        return config.getParamsTemplate()
47
-                .replace("${userId}", adLog.getUserId().toString())
48
-                .replace("${chapterId}", adLog.getChapterId().toString())
49
-                .replace("${timestamp}", String.valueOf(System.currentTimeMillis()));
50
-    }
51
-
52
-    @Override
53
-    public void syncToPangle(AdLog adLog, AdPlatformConfig config) {
54
-        // 1. 构建请求URL
55
-        String url = buildPangleUrl(adLog, config);
56
-
57
-        // 2. 创建请求头
58
-        HttpHeaders headers = new HttpHeaders();
59
-        headers.setBearerAuth(config.getAuthToken());
60
-
61
-        // 3. 发送请求
62
-        HttpEntity<?> entity = new HttpEntity<>(headers);
63
-        ResponseEntity<String> response = restTemplate.exchange(
64
-                url, HttpMethod.GET, entity, String.class);
65
-
66
-        // 4. 处理响应
67
-        if (response.getStatusCode() != HttpStatus.OK) {
68
-            throw new ServiceException("穿山甲同步失败: " + response.getBody());
69
-        }
70
-        log.info("穿山甲同步成功: chapter={}, user={}", adLog.getChapterId(), adLog.getUserId());
71
-    }
72
-
73
-    private String buildPangleUrl(AdLog adLog, AdPlatformConfig config) {
74
-        // 构建带参数的URL
75
-        return UriComponentsBuilder.fromHttpUrl(config.getApiUrl())
76
-                .queryParam("user", adLog.getUserId())
77
-                .queryParam("content_id", adLog.getChapterId())
78
-                .queryParam("event", "ad_view")
79
-                .queryParam("ts", System.currentTimeMillis())
80
-                .toUriString();
81
-    }
82
-}

+ 0
- 73
RuoYi-Vue/ruoyi-novel/src/main/java/com/ruoyi/novel/service/impl/ChapterServiceImpl.java Прегледај датотеку

@@ -1,73 +0,0 @@
1
-package com.ruoyi.novel.service.impl;
2
-
3
-import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
4
-import com.ruoyi.novel.domain.NovelChapter;
5
-import com.ruoyi.novel.domain.NovelContent;
6
-import com.ruoyi.novel.mapper.NovelChapterMapper;
7
-import com.ruoyi.novel.mapper.NovelContentMapper;
8
-import com.ruoyi.novel.service.ChapterService;
9
-import org.springframework.beans.factory.annotation.Autowired;
10
-import org.springframework.stereotype.Service;
11
-import org.springframework.transaction.annotation.Transactional;
12
-
13
-import java.util.Arrays;
14
-import java.util.Date;
15
-import java.util.List;
16
-
17
-// ChapterServiceImpl.java
18
-@Service
19
-public class ChapterServiceImpl implements ChapterService {
20
-
21
-    @Autowired
22
-    private NovelChapterMapper chapterMapper;
23
-
24
-    @Autowired
25
-    private NovelContentMapper contentMapper;
26
-
27
-    @Override
28
-    public List<NovelChapter> selectChapterListByNovelId(Long novelId) {
29
-        return chapterMapper.selectList(
30
-                new QueryWrapper<NovelChapter>()
31
-                        .eq("novel_id", novelId)
32
-                        .orderByAsc("chapter_order")
33
-        );
34
-    }
35
-
36
-    @Override
37
-    @Transactional
38
-    public int saveChapter(NovelChapter chapter, String content) {
39
-        if (chapter.getId() == null) {
40
-            // 新增章节
41
-            chapter.setCreateTime(new Date());
42
-            chapterMapper.insert(chapter);
43
-
44
-            NovelContent novelContent = new NovelContent();
45
-            novelContent.setChapterId(chapter.getId());
46
-            novelContent.setContent(content);
47
-            return contentMapper.insert(novelContent);
48
-        } else {
49
-            // 更新章节
50
-            chapter.setUpdateTime(new Date());
51
-            chapterMapper.updateById(chapter);
52
-
53
-            NovelContent novelContent = new NovelContent();
54
-            novelContent.setChapterId(chapter.getId());
55
-            novelContent.setContent(content);
56
-            return contentMapper.updateById(novelContent);
57
-        }
58
-    }
59
-
60
-    @Override
61
-    public NovelChapter getChapterById(Long chapterId) {
62
-        return chapterMapper.selectById(chapterId);
63
-    }
64
-
65
-    @Override
66
-    @Transactional
67
-    public int deleteChapters(Long[] ids) {
68
-        // 删除章节内容
69
-        contentMapper.deleteBatchIds(Arrays.asList(ids));
70
-        // 删除章节
71
-        return chapterMapper.deleteBatchIds(Arrays.asList(ids));
72
-    }
73
-}

+ 0
- 212
RuoYi-Vue/ruoyi-novel/src/main/java/com/ruoyi/novel/service/impl/FinanceServiceImpl.java Прегледај датотеку

@@ -1,212 +0,0 @@
1
-package com.ruoyi.novel.service.impl;
2
-
3
-import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
4
-import com.ruoyi.common.exception.ServiceException;
5
-import com.ruoyi.novel.domain.AdLog;
6
-import com.ruoyi.novel.domain.RoyaltyReport;
7
-import com.ruoyi.novel.domain.RoyaltySummary;
8
-import com.ruoyi.novel.mapper.AdLogMapper;
9
-import com.ruoyi.novel.mapper.RoyaltySummaryMapper;
10
-import com.ruoyi.novel.service.IAdService;
11
-import com.ruoyi.novel.service.IFinanceService;
12
-
13
-import org.slf4j.Logger;
14
-import org.slf4j.LoggerFactory;
15
-import org.springframework.beans.factory.annotation.Autowired;
16
-import org.springframework.beans.factory.annotation.Value;
17
-import org.springframework.http.*;
18
-import org.springframework.scheduling.annotation.Scheduled;
19
-import org.springframework.stereotype.Service;
20
-import org.springframework.web.client.RestTemplate;
21
-
22
-import java.math.BigDecimal;
23
-import java.util.ArrayList;
24
-import java.util.Arrays;
25
-import java.util.List;
26
-
27
-// FinanceServiceImpl.java
28
-@Service
29
-public class FinanceServiceImpl implements IFinanceService {
30
-    private static final Logger logger = LoggerFactory.getLogger(FinanceServiceImpl.class);
31
-    @Autowired
32
-    private RoyaltySummaryMapper royaltySummaryMapper;
33
-    @Value("${royalty.base.rate:0.15}")
34
-    private BigDecimal baseRoyaltyRate;
35
-
36
-    @Value("${handling.fee.rate:0.05}")
37
-    private BigDecimal handlingFeeRate;
38
-    @Value("${royalty.rate}")
39
-    private BigDecimal royaltyRate;
40
-    // 添加配置项注入
41
-    @Value("${php.data.url}")
42
-    private String phpDataUrl;
43
-
44
-    @Autowired
45
-    private AdLogMapper adLogMapper; // 确保已注入
46
-
47
-    @Autowired
48
-    private IAdService adService; // 确保已注入
49
-
50
-    //@Value("${handling.fee.rate}")
51
-    //private BigDecimal handlingFeeRate;
52
-
53
-    @Override
54
-    public RoyaltyReport calculateRoyalty(Long authorId, String month) {
55
-        // 1. 从PHP系统拉取数据(补充缺失的调用)
56
-//        RoyaltySummary summary = phpApiClient.getAuthorRoyaltySummary(authorId, month);
57
-//        // 2. 计算分成金额(补充业务逻辑)
58
-//        BigDecimal royaltyRate = getRoyaltyRate(authorId);
59
-//        BigDecimal grossAmount = summary.getTotalReads().multiply(royaltyRate);
60
-//        BigDecimal handlingFee = grossAmount.multiply(handlingFeeRate);
61
-//        BigDecimal netAmount = grossAmount.subtract(handlingFee);
62
-//        // 3. 构建报表对象
63
-//        return new RoyaltyReport(authorId, month, summary.getTotalReads(),
64
-//                royaltyRate, handlingFeeRate, handlingFee, netAmount);
65
-        // 1. 从PHP主库获取基础数据(假设已通过定时任务同步)
66
-        RoyaltySummary summary = royaltySummaryMapper.selectByAuthorAndMonth(authorId, month);
67
-
68
-//        if (summary == null) {
69
-//            throw new ServiceException("No data found for author: " + authorId + " in " + month);
70
-//        }
71
-        if (summary == null) {
72
-            throw new ServiceException("未找到分账数据: author=" + authorId + ", month=" + month);
73
-        }
74
-        // 2. 计算实际分成比例(可根据作者等级调整)
75
-        BigDecimal actualRate = getRoyaltyRate(authorId);
76
-        // 3. 构建报表
77
-        RoyaltyReport report = new RoyaltyReport();
78
-        report.setAuthorId(authorId);
79
-        report.setMonth(month);
80
-        report.calculate(summary.getTotalReads(), actualRate, handlingFeeRate);
81
-
82
-        return report;
83
-
84
-        // 2. 计算分账金额
85
-//        BigDecimal rawAmount = summary.getTotalReads().multiply(royaltyRate);
86
-//        BigDecimal handlingFee = rawAmount.multiply(handlingFeeRate);
87
-//        BigDecimal netAmount = rawAmount.subtract(handlingFee);
88
-//
89
-//        // 3. 构建报表
90
-//        return new RoyaltyReport(
91
-//                authorId,
92
-//                month,
93
-//                summary.getTotalReads(),
94
-//                royaltyRate,
95
-//                handlingFeeRate,
96
-//                handlingFee,
97
-//                netAmount
98
-//        );
99
-    }
100
-
101
-    @Override
102
-    @Scheduled(cron = "0 0 2 * * ?") // 每天凌晨2点执行
103
-    public void syncRoyaltyData() {
104
-        logger.info("开始同步分账数据...");
105
-        try {
106
-            // 1. 从PHP主库获取数据
107
-            List<RoyaltySummary> summaries = fetchFromPhpSystem();
108
-
109
-            // 2. 更新到本地数据库
110
-            summaries.forEach(summary -> {
111
-                royaltySummaryMapper.upsertSummary(summary);
112
-            });
113
-
114
-            logger.info("同步完成: {}条记录", summaries.size());
115
-        } catch (Exception e) {
116
-            logger.error("分账数据同步失败: {}", e.getMessage());
117
-        }
118
-    }
119
-
120
-//    private List<RoyaltySummary> fetchFromPhpSystem() {
121
-//        // 实现从PHP系统获取数据的逻辑
122
-//        // 返回模拟数据
123
-//        List<RoyaltySummary> list = new ArrayList<>();
124
-//        list.add(new RoyaltySummary(1001L, "2023-10", new BigDecimal("15000.00")));
125
-//        list.add(new RoyaltySummary(1002L, "2023-10", new BigDecimal("8500.00")));
126
-//        return list;
127
-//    }
128
-
129
-    // 在FinanceServiceImpl中补充完整数据同步
130
-    private List<RoyaltySummary> fetchFromPhpSystem() {
131
-        try {
132
-            // 使用RestTemplate从PHP系统获取数据
133
-            RestTemplate restTemplate = new RestTemplate();
134
-
135
-            // 设置认证头
136
-            HttpHeaders headers = new HttpHeaders();
137
-            headers.setBasicAuth("api_user", "api_password");
138
-
139
-            // 构建请求
140
-            HttpEntity<String> entity = new HttpEntity<>(headers);
141
-            ResponseEntity<RoyaltySummary[]> response = restTemplate.exchange(
142
-                    phpDataUrl + "/royalty/summary",
143
-                    HttpMethod.GET,
144
-                    entity,
145
-                    RoyaltySummary[].class
146
-            );
147
-
148
-            if (response.getStatusCode() == HttpStatus.OK && response.getBody() != null) {
149
-                return Arrays.asList(response.getBody());
150
-            }
151
-            throw new ServiceException("PHP系统返回错误状态码: " + response.getStatusCode());
152
-        } catch (Exception e) {
153
-            logger.error("从PHP系统获取分账数据失败: {}", e.getMessage());
154
-            throw new ServiceException("数据同步服务暂时不可用", e);
155
-        }
156
-    }
157
-
158
-    // 定时任务重试机制
159
-    @Scheduled(fixedDelayString = "${scheduled.ad-retry-interval}")
160
-    public void retryFailedAdSync() {
161
-        try {
162
-            List<AdLog> failedLogs = adLogMapper.selectList(
163
-                    new QueryWrapper<AdLog>().eq("sync_status", 2) // 2=失败
164
-            );
165
-
166
-            for (AdLog log : failedLogs) {
167
-                logger.info("重试广告同步: ID={}, 平台={}", log.getId(), log.getAdPlatform());
168
-                adService.syncWithAdPlatform(log);
169
-            }
170
-        } catch (Exception e) {
171
-            logger.error("广告同步重试任务失败: {}", e.getMessage());
172
-        }
173
-    }
174
-    @Override
175
-    public BigDecimal getRoyaltyRate(Long authorId) {
176
-        // 实际应根据作者等级计算
177
-        // 这里返回基础比例
178
-        return baseRoyaltyRate;
179
-    }
180
-
181
-    @Override
182
-    public BigDecimal getHandlingFeeRate() {
183
-        return handlingFeeRate;
184
-    }
185
-
186
-
187
-//    @Override
188
-//    public RoyaltyReport calculateRoyalty(Long authorId, String month) {
189
-//        // 1. 从PHP系统拉取数据(补充缺失的调用)
190
-//        RoyaltySummary summary = phpApiClient.getAuthorRoyaltySummary(authorId, month);
191
-//
192
-//        // 2. 计算分成金额(补充业务逻辑)
193
-//        BigDecimal royaltyRate = getRoyaltyRate(authorId);
194
-//        BigDecimal grossAmount = summary.getTotalReads().multiply(royaltyRate);
195
-//        BigDecimal handlingFee = grossAmount.multiply(handlingFeeRate);
196
-//        BigDecimal netAmount = grossAmount.subtract(handlingFee);
197
-//
198
-//        // 3. 构建报表对象
199
-//        return new RoyaltyReport(authorId, month, summary.getTotalReads(),
200
-//                royaltyRate, handlingFeeRate, handlingFee, netAmount);
201
-//    }
202
-//
203
-//    // 补充缺失的辅助方法
204
-//    private BigDecimal getRoyaltyRate(Long authorId) {
205
-//        Author author = authorService.getById(authorId);
206
-//        BigDecimal rate = baseRoyaltyRate;
207
-//        if (author.isVip()) {
208
-//            rate = rate.add(vipBonusRate); // VIP作者加成
209
-//        }
210
-//        return rate.min(new BigDecimal("0.35")); // 上限35%:cite[4]
211
-//    }
212
-}

+ 0
- 103
RuoYi-Vue/ruoyi-novel/src/main/java/com/ruoyi/novel/service/impl/NovelSearchServiceImpl.java Прегледај датотеку

@@ -1,103 +0,0 @@
1
-package com.ruoyi.novel.service.impl;
2
-
3
-import com.ruoyi.novel.domain.Novel;
4
-import com.ruoyi.novel.mapper.NovelMapper;
5
-import com.ruoyi.novel.service.NovelSearchService;
6
-import org.elasticsearch.index.query.QueryBuilders;
7
-import org.slf4j.Logger;
8
-import org.slf4j.LoggerFactory;
9
-import org.springframework.beans.factory.annotation.Autowired;
10
-import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
11
-import org.springframework.data.elasticsearch.core.IndexOperations;
12
-import org.springframework.data.elasticsearch.core.SearchHit;
13
-import org.springframework.data.elasticsearch.core.SearchHits;
14
-import org.springframework.data.elasticsearch.core.document.Document;
15
-import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates;
16
-import org.springframework.data.elasticsearch.core.query.*;
17
-import org.springframework.scheduling.annotation.Scheduled;
18
-import org.springframework.stereotype.Service;
19
-
20
-import javax.annotation.PostConstruct;
21
-import java.util.HashMap;
22
-import java.util.List;
23
-import java.util.Map;
24
-import java.util.stream.Collectors;
25
-
26
-// NovelSearchService.java
27
-@Service
28
-public class NovelSearchServiceImpl implements NovelSearchService {
29
-    private static final Logger logger = LoggerFactory.getLogger(NovelSearchServiceImpl.class);
30
-
31
-    @Autowired
32
-    private ElasticsearchRestTemplate elasticTemplate;
33
-    @Autowired
34
-    private NovelMapper novelMapper;
35
-
36
-    private static final String INDEX_NAME = "novels";
37
-
38
-    @PostConstruct
39
-    public void createIndexIfNotExists() {
40
-        IndexOperations indexOps = elasticTemplate.indexOps(IndexCoordinates.of(INDEX_NAME));
41
-        if (!indexOps.exists()) {
42
-            // 创建索引
43
-            indexOps.create();
44
-
45
-            // 创建映射
46
-            Document mapping = indexOps.createMapping(Novel.class);
47
-            indexOps.putMapping(mapping);
48
-        }
49
-//        if (!elasticTemplate.indexExists(INDEX_NAME)) {
50
-//            elasticTemplate.createIndex(INDEX_NAME);
51
-//            elasticTemplate.putMapping(Novel.class);
52
-//        }
53
-    }
54
-    public List<Novel> searchNovels(String keyword) {
55
-        // 构建查询条件
56
-        NativeSearchQuery query = new NativeSearchQueryBuilder()
57
-                .withQuery(QueryBuilders.multiMatchQuery(keyword, "title", "author", "description"))
58
-                .build();
59
-        // 执行搜索
60
-        SearchHits<Novel> hits = elasticTemplate.search(query, Novel.class);
61
-        return hits.stream()
62
-                .map(SearchHit::getContent)
63
-                .collect(Collectors.toList());
64
-
65
-        //return elasticTemplate.search(query, Novel.class).getContent();
66
-    }
67
-
68
-    @Override
69
-    public void indexNovel(Novel novel) {
70
-        IndexQuery indexQuery = new IndexQueryBuilder()
71
-                .withId(novel.getId().toString())
72
-                .withObject(novel)
73
-                .build();
74
-        elasticTemplate.index(indexQuery, IndexCoordinates.of(INDEX_NAME));
75
-    }
76
-    @Override
77
-    public void updateNovelIndex(Novel novel) {
78
-        UpdateQuery updateQuery = UpdateQuery.builder(novel.getId().toString())
79
-                .withDocument(Document.from(convertNovelToMap(novel)))
80
-                .build();
81
-        elasticTemplate.update(updateQuery, IndexCoordinates.of(INDEX_NAME));
82
-    }
83
-    private Map<String, Object> convertNovelToMap(Novel novel) {
84
-        Map<String, Object> map = new HashMap<>();
85
-        map.put("title", novel.getTitle());
86
-        map.put("author", novel.getAuthor());
87
-        map.put("description", novel.getDescription());
88
-        map.put("categoryId", novel.getCategoryId());
89
-        map.put("status", novel.getStatus());
90
-        return map;
91
-    }
92
-    @Override
93
-    public void deleteNovelIndex(Long id) {
94
-        elasticTemplate.delete(id.toString(), IndexCoordinates.of(INDEX_NAME));
95
-    }
96
-    // 定时同步数据库数据到ES
97
-    @Scheduled(fixedRate = 3600000) // 每小时同步一次
98
-    public void syncDataToEs() {
99
-        List<Novel> novels = novelMapper.selectList(null);
100
-        novels.forEach(this::indexNovel);
101
-        logger.info("同步 {} 条小说数据到ES", novels.size());
102
-    }
103
-}

+ 0
- 53
RuoYi-Vue/ruoyi-novel/src/main/java/com/ruoyi/novel/service/impl/NovelServiceImpl.java Прегледај датотеку

@@ -1,53 +0,0 @@
1
-package com.ruoyi.novel.service.impl;
2
-
3
-import com.ruoyi.novel.domain.Novel;
4
-import com.ruoyi.novel.mapper.NovelMapper;
5
-import com.ruoyi.novel.service.NovelService;
6
-import org.slf4j.Logger;
7
-import org.slf4j.LoggerFactory;
8
-import org.springframework.beans.factory.annotation.Autowired;
9
-import org.springframework.stereotype.Service;
10
-import org.springframework.transaction.annotation.Transactional;
11
-
12
-import java.util.Arrays;
13
-import java.util.Date;
14
-import java.util.List;
15
-
16
-// NovelServiceImpl.java
17
-@Service
18
-public class NovelServiceImpl implements NovelService {
19
-    private static final Logger logger = LoggerFactory.getLogger(NovelServiceImpl.class);
20
-
21
-    @Autowired
22
-    private NovelMapper novelMapper;
23
-
24
-    @Override
25
-    public List<Novel> selectNovelList(Novel novel) {
26
-        return novelMapper.selectNovelList(novel);
27
-    }
28
-
29
-    @Override
30
-    @Transactional
31
-    public int insertNovel(Novel novel) {
32
-        novel.setCreateTime(new Date());
33
-        return novelMapper.insertNovel(novel);
34
-    }
35
-
36
-    @Override
37
-    public int updateNovel(Novel novel) {
38
-        novel.setUpdateTime(new Date());
39
-        return novelMapper.updateById(novel);
40
-    }
41
-
42
-    @Override
43
-    public int deleteNovelByIds(Long[] ids) {
44
-        return novelMapper.deleteBatchIds(Arrays.asList(ids));
45
-    }
46
-
47
-    @Override
48
-    public Novel selectNovelById(Long id) {
49
-        return novelMapper.selectById(id);
50
-    }
51
-
52
-    // 其他CRUD方法...
53
-}

+ 0
- 60
RuoYi-Vue/ruoyi-novel/src/main/java/com/ruoyi/novel/service/impl/ReadingHistoryServiceImpl.java Прегледај датотеку

@@ -1,60 +0,0 @@
1
-package com.ruoyi.novel.service.impl;
2
-
3
-import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
4
-import com.ruoyi.novel.domain.ReadingRecord;
5
-import com.ruoyi.novel.mapper.ReadingHistoryMapper;
6
-import com.ruoyi.novel.service.ReadingHistoryService;
7
-import org.slf4j.Logger;
8
-import org.slf4j.LoggerFactory;
9
-import org.springframework.beans.factory.annotation.Autowired;
10
-import org.springframework.stereotype.Service;
11
-import org.springframework.transaction.annotation.Transactional;
12
-
13
-import java.util.Date;
14
-
15
-// ReadingHistoryServiceImpl.java
16
-@Service
17
-public class ReadingHistoryServiceImpl implements ReadingHistoryService {
18
-    private static final Logger logger = LoggerFactory.getLogger(ReadingHistoryServiceImpl.class);
19
-
20
-    @Autowired
21
-    private ReadingHistoryMapper historyMapper;
22
-
23
-    @Override
24
-    @Transactional
25
-    public void recordReading(ReadingRecord record) {
26
-        record.setLastReadTime(new Date());
27
-
28
-        // 检查是否已存在记录
29
-        ReadingRecord existing = historyMapper.selectOne(
30
-                new QueryWrapper<ReadingRecord>()
31
-                        .eq("user_id", record.getUserId())
32
-                        .eq("chapter_id", record.getChapterId())
33
-        );
34
-
35
-        if (existing != null) {
36
-            // 更新现有记录
37
-            existing.setProgress(record.getProgress());
38
-            existing.setPosition(record.getPosition());
39
-            existing.setLastReadTime(record.getLastReadTime());
40
-            historyMapper.updateById(existing);
41
-        } else {
42
-            // 插入新记录
43
-            historyMapper.insert(record);
44
-        }
45
-    }
46
-
47
-
48
-
49
-
50
-    @Override
51
-    public ReadingRecord getLastPosition(Long userId, Long novelId) {
52
-        return historyMapper.selectOne(
53
-                new QueryWrapper<ReadingRecord>()
54
-                        .eq("user_id", userId)
55
-                        .eq("novel_id", novelId)
56
-                        .orderByDesc("last_read_time")
57
-                        .last("LIMIT 1")
58
-        );
59
-    }
60
-}

+ 0
- 231
RuoYi-Vue/ruoyi-novel/src/main/java/com/ruoyi/novel/service/impl/VoteServiceImpl.java Прегледај датотеку

@@ -1,231 +0,0 @@
1
-package com.ruoyi.novel.service.impl;
2
-
3
-import com.google.common.util.concurrent.RateLimiter;
4
-import com.ruoyi.common.exception.ServiceException;
5
-import com.ruoyi.novel.domain.VoteRecord;
6
-import com.ruoyi.novel.domain.VoteRequest;
7
-import com.ruoyi.novel.mapper.StoryOptionMapper;
8
-import com.ruoyi.novel.mapper.VoteRecordMapper;
9
-import com.ruoyi.novel.service.VoteService;
10
-import org.slf4j.Logger;
11
-import org.slf4j.LoggerFactory;
12
-import org.springframework.beans.factory.annotation.Autowired;
13
-import org.springframework.beans.factory.annotation.Value;
14
-import org.springframework.http.*;
15
-import org.springframework.scheduling.annotation.Async;
16
-import org.springframework.scheduling.annotation.Scheduled;
17
-import org.springframework.stereotype.Service;
18
-import org.springframework.web.client.RestClientException;
19
-import org.springframework.web.client.RestTemplate;
20
-
21
-import java.util.Date;
22
-import java.util.HashMap;
23
-import java.util.List;
24
-import java.util.Map;
25
-import java.util.concurrent.ConcurrentHashMap;
26
-import java.util.concurrent.atomic.AtomicInteger;
27
-
28
-// VoteServiceImpl.java
29
-@Service
30
-public class VoteServiceImpl implements VoteService {
31
-    private static final Logger logger = LoggerFactory.getLogger(VoteServiceImpl.class);
32
-
33
-    @Autowired
34
-    private VoteRecordMapper voteRecordMapper;
35
-    @Autowired
36
-    private StoryOptionMapper storyOptionMapper;
37
-    @Value("${deepseek.api.key}")
38
-    private String deepSeekApiKey;
39
-    @Value("${deepseek.api.url}")
40
-    private String deepSeekApiUrl; // 添加配置项注入
41
-    @Value("${php.notify.url}")
42
-    private String phpNotifyUrl;
43
-    @Autowired
44
-    private RestTemplate restTemplate; // 确保已注入
45
-
46
-    // 使用Guava RateLimiter实现限流
47
-    private static final ConcurrentHashMap<Long, RateLimiter> userRateLimiters = new ConcurrentHashMap<>();
48
-
49
-    // 用户投票限流器 <userId, 计数器>
50
-    private final Map<Long, AtomicInteger> userVoteCounters = new ConcurrentHashMap<>();
51
-    private static final int DAILY_VOTE_LIMIT = 3;
52
-
53
-    // 添加方法实现
54
-    @Override
55
-    public void incrementOptionVote(Long optionId) {
56
-        storyOptionMapper.incrementVoteCount(optionId);
57
-    }
58
-    @Override
59
-    public boolean canUserVote(Long userId) {
60
-        RateLimiter rateLimiter = userRateLimiters.computeIfAbsent(
61
-                userId, k -> RateLimiter.create(3.0) // 每秒3次
62
-        );
63
-        return rateLimiter.tryAcquire();
64
-    }
65
-
66
-    @Override
67
-    public String generateStoryContent(Long storyId, Long optionId) {
68
-        // 实际应调用AI服务
69
-        return "生成的故事内容...";
70
-    }
71
-    @Override
72
-    public String processVote(VoteRequest request) {
73
-        // 1. 检查当日投票次数
74
-        AtomicInteger counter = userVoteCounters.computeIfAbsent(
75
-                request.getUserId(),
76
-                k -> new AtomicInteger(0)
77
-        );
78
-
79
-        if (counter.get() >= DAILY_VOTE_LIMIT) {
80
-            throw new ServiceException("今日投票次数已达上限");
81
-        }
82
-
83
-        // 2. 记录投票
84
-        VoteRecord record = new VoteRecord();
85
-        record.setUserId(request.getUserId());
86
-        record.setStoryId(request.getStoryId());
87
-        record.setOptionId(request.getOptionId());
88
-        record.setNotifyStatus(0); // 未通知状态
89
-        voteRecordMapper.insert(record);
90
-
91
-        // 3. 更新选项计数
92
-        storyOptionMapper.incrementOptionVote(request.getOptionId());
93
-
94
-        // 4. 异步生成内容
95
-        this.generateStoryContent(record);
96
-
97
-        counter.incrementAndGet();
98
-        return "投票成功,剧情生成中...";
99
-    }
100
-    @Override
101
-    @Async("voteTaskExecutor")
102
-    public void generateStoryContent(VoteRecord record) {
103
-        try {
104
-            String content = callDeepSeekApi(record);
105
-            record.setGeneratedContent(content);
106
-            voteRecordMapper.updateById(record);
107
-
108
-            // 通知PHP系统
109
-            this.notifyPhpSystem(record);
110
-        } catch (Exception e) {
111
-            logger.error("AI生成失败: {}", e.getMessage());
112
-        }
113
-    }
114
-    // 在VoteServiceImpl中补充完整API调用
115
-    private String callDeepSeekApi(VoteRecord record) {
116
-        try {
117
-            // 构建请求体
118
-            Map<String, Object> requestBody = new HashMap<>();
119
-            requestBody.put("story_id", record.getStoryId());
120
-            requestBody.put("option_id", record.getOptionId());
121
-            requestBody.put("user_id", record.getUserId());
122
-
123
-            // 设置请求头
124
-            HttpHeaders headers = new HttpHeaders();
125
-            headers.setContentType(MediaType.APPLICATION_JSON);
126
-            headers.setBearerAuth(deepSeekApiKey);
127
-
128
-            // 发送请求
129
-            HttpEntity<Map<String, Object>> entity = new HttpEntity<>(requestBody, headers);
130
-            ResponseEntity<Map> response = restTemplate.exchange(
131
-                    deepSeekApiUrl, HttpMethod.POST, entity, Map.class);
132
-
133
-            // 解析响应
134
-            if (response.getStatusCode() == HttpStatus.OK && response.getBody() != null) {
135
-                Map<String, Object> body = response.getBody();
136
-                if (body.containsKey("data") && ((Map)body.get("data")).containsKey("content")) {
137
-                    return (String) ((Map)body.get("data")).get("content");
138
-                }
139
-            }
140
-            throw new ServiceException("DeepSeek API响应格式错误");
141
-        } catch (RestClientException e) {
142
-            logger.error("DeepSeek API调用失败: {}", e.getMessage());
143
-            throw new ServiceException("AI服务暂时不可用", e);
144
-        }
145
-    }
146
-
147
-//    @Async
148
-//    @Override
149
-//    public void generateStoryContent(Long storyId, Long optionId) {
150
-//        // 调用DeepSeek API
151
-//        DeepSeekRequest request = new DeepSeekRequest(storyId, optionId);
152
-//        String apiUrl = "https://api.deepseek.com/v1/story/generate";
153
-//
154
-//        RestTemplate restTemplate = new RestTemplate();
155
-//        HttpHeaders headers = new HttpHeaders();
156
-//        headers.setBearerAuth(deepSeekApiKey);
157
-//
158
-//        HttpEntity<DeepSeekRequest> entity = new HttpEntity<>(request, headers);
159
-//        ResponseEntity<String> response = restTemplate.exchange(
160
-//                apiUrl, HttpMethod.POST, entity, String.class);
161
-//
162
-//        if (response.getStatusCode() == HttpStatus.OK) {
163
-//            return parseGeneratedContent(response.getBody());
164
-//        }
165
-//        throw new ServiceException("Failed to generate story content");
166
-//    }
167
-
168
-
169
-    @Async
170
-    @Override
171
-    public void notifyPhpSystem(VoteRequest request, String content) {
172
-        // 组装通知数据
173
-        Map<String, Object> payload = new HashMap<>();
174
-        payload.put("userId", request.getUserId());
175
-        payload.put("storyId", request.getStoryId());
176
-        payload.put("optionId", request.getOptionId());
177
-        payload.put("content", content);
178
-
179
-        // 发送异步通知
180
-        RestTemplate restTemplate = new RestTemplate();
181
-        restTemplate.postForObject(phpNotifyUrl, payload, String.class);
182
-
183
-        // 记录投票日志
184
-        VoteRecord record = new VoteRecord();
185
-        record.setUserId(request.getUserId());
186
-        record.setStoryId(request.getStoryId());
187
-        record.setOptionId(request.getOptionId());
188
-        record.setVoteTime(new Date());
189
-        record.setGeneratedContent(content);
190
-        voteRecordMapper.insertVoteRecord(record);
191
-    }
192
-
193
-
194
-    @Override
195
-    @Async("voteTaskExecutor")
196
-    public void notifyPhpSystem(VoteRecord record) {
197
-        try {
198
-            // 构建通知数据
199
-            Map<String, Object> payload = new HashMap<>();
200
-            payload.put("userId", record.getUserId());
201
-            payload.put("storyId", record.getStoryId());
202
-            payload.put("optionId", record.getOptionId());
203
-            payload.put("content", record.getGeneratedContent());
204
-
205
-            // 发送HTTP请求
206
-            RestTemplate restTemplate = new RestTemplate();
207
-            ResponseEntity<String> response = restTemplate.postForEntity(
208
-                    phpNotifyUrl, payload, String.class);
209
-
210
-            if (response.getStatusCode() == HttpStatus.OK) {
211
-                record.setNotifyStatus(1); // 通知成功
212
-            } else {
213
-                record.setNotifyStatus(2); // 通知失败
214
-            }
215
-        } catch (Exception e) {
216
-            logger.error("通知PHP系统失败: {}", e.getMessage());
217
-            record.setNotifyStatus(2);
218
-        }
219
-        voteRecordMapper.updateById(record);
220
-    }
221
-
222
-    @Override
223
-    @Scheduled(cron = "0 */10 * * * ?") // 每10分钟执行一次
224
-    public void retryFailedNotifications() {
225
-        List<VoteRecord> failedRecords = voteRecordMapper.selectUnnotifiedRecords();
226
-        failedRecords.forEach(record -> {
227
-            logger.info("重试通知PHP系统: voteId={}", record.getId());
228
-            this.notifyPhpSystem(record);
229
-        });
230
-    }
231
-}

+ 0
- 89
RuoYi-Vue/ruoyi-novel/src/main/java/com/ruoyi/novel/utils/AdPlatformClient.java Прегледај датотеку

@@ -1,89 +0,0 @@
1
-package com.ruoyi.novel.utils;
2
-
3
-import com.ruoyi.common.exception.ServiceException;
4
-import com.ruoyi.novel.domain.AdLog;
5
-import com.ruoyi.novel.domain.AdPlatformConfig;
6
-import com.ruoyi.novel.service.IAdService;
7
-import lombok.Value;
8
-import org.springframework.beans.factory.annotation.Autowired;
9
-import org.springframework.http.HttpEntity;
10
-import org.springframework.http.ResponseEntity;
11
-import org.springframework.stereotype.Component;
12
-import org.springframework.web.client.RestTemplate;
13
-
14
-import java.net.http.HttpHeaders;
15
-import java.util.Map;
16
-
17
-// AdPlatformClient.java
18
-@Component
19
-public class AdPlatformClient {
20
-    @Autowired
21
-    private IAdService adService;
22
-
23
-    @Autowired
24
-    private RestTemplate restTemplate;
25
-    @Value("${ad.tencent.url}")
26
-    private String tencentUrl;
27
-
28
-    @Value("${ad.pangle.url}")
29
-    private String pangleUrl;
30
-    public void syncAdPlatform(AdLog adLog) {
31
-        Map<String, AdPlatformConfig> configs = adService.loadAdConfigs();
32
-        AdPlatformConfig config = configs.get(adLog.getAdPlatform());
33
-
34
-        if (config == null) {
35
-            throw new ServiceException("广告平台配置不存在: " + adLog.getAdPlatform());
36
-        }
37
-
38
-        // 构建请求参数
39
-        String payload = buildPayload(adLog, config.getParamsTemplate());
40
-
41
-        // 设置请求头
42
-        HttpHeaders headers = new HttpHeaders();
43
-        headers.setContentType(MediaType.APPLICATION_JSON);
44
-        headers.setBearerAuth(config.getAuthToken());
45
-
46
-        // 发送请求
47
-        HttpEntity<String> entity = new HttpEntity<>(payload, headers);
48
-        ResponseEntity<String> response = restTemplate.exchange(
49
-                config.getApiUrl(), HttpMethod.POST, entity, String.class);
50
-
51
-        // 处理响应
52
-        if (!response.getStatusCode().is2xxSuccessful()) {
53
-            throw new ServiceException("广告平台同步失败: " + response.getBody());
54
-        }
55
-
56
-        log.info("广告同步成功: logId={}, platform={}", adLog.getId(), adLog.getAdPlatform());
57
-    }
58
-    private String buildPayload(AdLog adLog, String template) {
59
-        // 使用占位符替换实际值
60
-        return template
61
-                .replace("${userId}", adLog.getUserId().toString())
62
-                .replace("${chapterId}", adLog.getChapterId().toString())
63
-                .replace("${timestamp}", String.valueOf(System.currentTimeMillis()));
64
-    }
65
-    public void syncTencent(AdLog adLog) {
66
-        Map<String, String> params = new HashMap<>();
67
-        params.put("user_id", adLog.getUserId().toString());
68
-        params.put("chapter_id", adLog.getChapterId().toString());
69
-        params.put("event_time", String.valueOf(adLog.getViewTime().getTime()));
70
-
71
-        RestTemplate restTemplate = new RestTemplate();
72
-        restTemplate.postForObject(tencentUrl, params, String.class);
73
-    }
74
-
75
-    public void syncPangle(AdLog adLog) {
76
-        // 穿山甲平台需要不同的参数格式
77
-        JSONObject payload = new JSONObject();
78
-        payload.put("user", adLog.getUserId());
79
-        payload.put("content_id", adLog.getChapterId());
80
-        payload.put("timestamp", System.currentTimeMillis());
81
-
82
-        RestTemplate restTemplate = new RestTemplate();
83
-        HttpHeaders headers = new HttpHeaders();
84
-        headers.setContentType(MediaType.APPLICATION_JSON);
85
-
86
-        HttpEntity<String> entity = new HttpEntity<>(payload.toString(), headers);
87
-        restTemplate.postForObject(pangleUrl, entity, String.class);
88
-    }
89
-}

+ 0
- 8
RuoYi-Vue/ruoyi-novel/src/main/java/com/ruoyi/novel/utils/Constants.java Прегледај датотеку

@@ -1,8 +0,0 @@
1
-package com.ruoyi.novel.utils;
2
-
3
-public class Constants {
4
-    public static final String PAGE_NUM = "pageNum";
5
-    public static final String PAGE_SIZE = "pageSize";
6
-    public static final String ORDER_BY_COLUMN = "orderByColumn";
7
-    public static final String IS_ASC = "isAsc";
8
-}

+ 0
- 72
RuoYi-Vue/ruoyi-novel/src/main/java/com/ruoyi/novel/utils/JwtUtil.java Прегледај датотеку

@@ -1,72 +0,0 @@
1
-package com.ruoyi.novel.utils;
2
-
3
-import io.jsonwebtoken.Claims;
4
-import io.jsonwebtoken.Jwts;
5
-import io.jsonwebtoken.SignatureAlgorithm;
6
-import org.springframework.beans.factory.annotation.Value;
7
-
8
-
9
-import java.nio.charset.StandardCharsets;
10
-import java.util.Date;
11
-
12
-// JwtUtil.java
13
-public class JwtUtil {
14
-    private static String SECRET = "your_jwt_secret_key";
15
-    @Value("${jwt.secret}")
16
-    public void setSecret(String secret) {
17
-        SECRET = secret;
18
-    }
19
-
20
-    private static final long EXPIRE = 86400; // 24小时
21
-    public static String generateToken(Long userId) {
22
-        Date now = new Date();
23
-        Date expire = new Date(now.getTime() + EXPIRE * 1000);
24
-
25
-        return Jwts.builder()
26
-                .setHeaderParam("typ", "JWT")
27
-                .setSubject(userId.toString())
28
-                .setIssuedAt(now)
29
-                .setExpiration(expire)
30
-                .signWith(SignatureAlgorithm.HS512, SECRET)
31
-                .compact();
32
-    }
33
-
34
-    public static boolean verifyToken(String token, Long userId) {
35
-        try {
36
-            Claims claims = Jwts.parser()
37
-                    .setSigningKey(SECRET)
38
-                    .parseClaimsJws(token)
39
-                    .getBody();
40
-
41
-            String subject = claims.getSubject();
42
-            return userId.toString().equals(subject);
43
-        } catch (Exception e) {
44
-            return false;
45
-        }
46
-    }
47
-
48
-    public static Long getUserIdFromToken(String token) {
49
-        Claims claims = Jwts.parser()
50
-                .setSigningKey(SECRET)
51
-                .parseClaimsJws(token)
52
-                .getBody();
53
-        return Long.parseLong(claims.getSubject());
54
-    }
55
-
56
-    // 补充Token解析方法
57
-    public static Claims parseToken(String token) {
58
-        return Jwts.parser()
59
-                .setSigningKey(SECRET.getBytes(StandardCharsets.UTF_8))
60
-                .parseClaimsJws(token)
61
-                .getBody();
62
-    }
63
-
64
-    // 补充缺失的Token生成方法
65
-//    public static String generateToken(Long userId) {
66
-//        return Jwts.builder()
67
-//                .setSubject(userId.toString())
68
-//                .setExpiration(new Date(System.currentTimeMillis() + 86400 * 1000))
69
-//                .signWith(SignatureAlgorithm.HS512, SECRET)
70
-//                .compact();
71
-//    }
72
-}

+ 0
- 15
RuoYi-Vue/ruoyi-novel/src/main/java/com/ruoyi/novel/utils/NovelUtils.java Прегледај датотеку

@@ -1,15 +0,0 @@
1
-package com.ruoyi.novel.utils;
2
-
3
-// NovelUtils.java
4
-public class NovelUtils {
5
-
6
-    // 敏感词过滤
7
-    public static String filterSensitiveWords(String content) {
8
-        // 实现敏感词过滤逻辑
9
-    }
10
-
11
-    // 自动生成章节序号
12
-    public static Integer generateChapterOrder(Long novelId) {
13
-        // 查询最新章节序号+1
14
-    }
15
-}

+ 0
- 22
RuoYi-Vue/ruoyi-novel/src/main/java/com/ruoyi/novel/vip/VipAccessAspect.java Прегледај датотеку

@@ -1,22 +0,0 @@
1
-package com.ruoyi.novel.vip;
2
-
3
-import com.ruoyi.common.exception.ServiceException;
4
-import com.ruoyi.common.utils.SecurityUtils;
5
-import org.aspectj.lang.JoinPoint;
6
-import org.aspectj.lang.annotation.Aspect;
7
-import org.aspectj.lang.annotation.Before;
8
-import org.springframework.stereotype.Component;
9
-
10
-// VipAccessAspect.java
11
-@Aspect
12
-@Component
13
-public class VipAccessAspect {
14
-
15
-    @Before("@annotation(vipAccess)")
16
-    public void checkVipAccess(JoinPoint joinPoint, VipAccess vipAccess) {
17
-        // 校验用户VIP状态
18
-        if(!userService.isVip(SecurityUtils.getUserId())) {
19
-            throw new ServiceException("请开通VIP后阅读此章节");
20
-        }
21
-    }
22
-}

+ 0
- 26
RuoYi-Vue/ruoyi-novel/src/main/resources/application.yml Прегледај датотеку

@@ -1,26 +0,0 @@
1
-## 广告平台配置
2
-#ad:
3
-#  tencent:
4
-#    url: https://ad.tencent.com/track
5
-#  pangle:
6
-#    url: https://ad.pangle.com/api/v1/event
7
-#
8
-## DeepSeek API配置
9
-#deepseek:
10
-#  api:
11
-#    key: your_deepseek_api_key
12
-#    url: https://api.deepseek.com/v1/story/generate
13
-#
14
-## PHP系统配置
15
-#php:
16
-#  notify:
17
-#    url: http://php-system.com/api/vote/notify
18
-#  data:
19
-#    url: http://php-system.com/api/data
20
-#
21
-## 分账规则
22
-#royalty:
23
-#  rate: 0.15   # 15%分成比例
24
-#handling:
25
-#  fee:
26
-#    rate: 0.05  # 5%提现手续费

+ 0
- 27
RuoYi-Vue/ruoyi-novel/src/main/resources/mapper/novel/AdLogMapper.xml Прегледај датотеку

@@ -1,27 +0,0 @@
1
-<!-- AdLogMapper.xml -->
2
-<mapper namespace="com.ruoyi.novel.mapper.AdLogMapper">
3
-
4
-    <resultMap id="AdLogResult" type="AdLog">
5
-        <id property="id" column="id" />
6
-        <result property="userId" column="user_id" />
7
-        <result property="chapterId" column="chapter_id" />
8
-        <result property="adPlatform" column="ad_platform" />
9
-        <result property="viewTime" column="view_time" />
10
-        <result property="deviceInfo" column="device_info" />
11
-        <result property="syncStatus" column="sync_status" />
12
-    </resultMap>
13
-
14
-    <sql id="selectAdLogVo">
15
-        SELECT id, user_id, chapter_id, ad_platform, view_time, device_info, sync_status
16
-        FROM novel_ad_log
17
-    </sql>
18
-
19
-    <update id="updateSyncStatus">
20
-        UPDATE novel_ad_log
21
-        SET sync_status = #{status}
22
-        WHERE id IN
23
-        <foreach item="id" collection="ids" open="(" separator="," close=")">
24
-            #{id}
25
-        </foreach>
26
-    </update>
27
-</mapper>

+ 0
- 17
RuoYi-Vue/ruoyi-novel/src/main/resources/mapper/novel/RoyaltySummaryMapper.xml Прегледај датотеку

@@ -1,17 +0,0 @@
1
-<!-- RoyaltySummaryMapper.xml -->
2
-<mapper namespace="com.ruoyi.novel.mapper.RoyaltySummaryMapper">
3
-
4
-    <resultMap id="RoyaltySummaryResult" type="RoyaltySummary">
5
-        <id property="authorId" column="author_id" />
6
-        <id property="month" column="month" />
7
-        <result property="totalReads" column="total_reads" />
8
-        <result property="lastSyncTime" column="last_sync_time" />
9
-    </resultMap>
10
-
11
-    <select id="selectMonthlySummary" resultMap="RoyaltySummaryResult">
12
-        SELECT author_id, month, SUM(total_reads) AS total_reads
13
-        FROM novel_royalty_detail
14
-        WHERE month = #{month}
15
-        GROUP BY author_id
16
-    </select>
17
-</mapper>

+ 0
- 26
RuoYi-Vue/ruoyi-novel/src/main/resources/mapper/novel/VoteRecordMapper.xml Прегледај датотеку

@@ -1,26 +0,0 @@
1
-<!-- VoteRecordMapper.xml -->
2
-<mapper namespace="com.ruoyi.novel.mapper.VoteRecordMapper">
3
-
4
-    <resultMap id="VoteRecordResult" type="VoteRecord">
5
-        <id property="id" column="id" />
6
-        <result property="userId" column="user_id" />
7
-        <result property="storyId" column="story_id" />
8
-        <result property="optionId" column="option_id" />
9
-        <result property="voteTime" column="vote_time" />
10
-        <result property="generatedContent" column="generated_content"
11
-                typeHandler="com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler"/>
12
-        <result property="notifyStatus" column="notify_status" />
13
-    </resultMap>
14
-
15
-    <update id="incrementOptionVote">
16
-        UPDATE novel_story_option
17
-        SET vote_count = vote_count + 1
18
-        WHERE id = #{optionId}
19
-    </update>
20
-
21
-    <update id="updateNotifyStatus">
22
-        UPDATE novel_vote_log
23
-        SET notify_status = #{status}
24
-        WHERE id = #{id}
25
-    </update>
26
-</mapper>

+ 0
- 44
RuoYi-Vue/ruoyi-system/src/main/java/com/ruoyi/novel/exception/GlobalExceptionHandler.java Прегледај датотеку

@@ -1,44 +0,0 @@
1
-package com.ruoyi.novel.exception;
2
-
3
-import com.ruoyi.common.core.domain.AjaxResult;
4
-import com.ruoyi.common.exception.ServiceException;
5
-import org.slf4j.Logger;
6
-import org.slf4j.LoggerFactory;
7
-import org.springframework.web.bind.MethodArgumentNotValidException;
8
-import org.springframework.web.bind.annotation.ExceptionHandler;
9
-import org.springframework.web.bind.annotation.RestControllerAdvice;
10
-
11
-
12
-// 新增全局异常处理器
13
-@RestControllerAdvice
14
-public class GlobalExceptionHandler {
15
-
16
-    private static final Logger logger = LoggerFactory.getLogger(GlobalExceptionHandler.class);
17
-
18
-    /**
19
-     * 业务异常处理
20
-     */
21
-    @ExceptionHandler(ServiceException.class)
22
-    public AjaxResult handleServiceException(ServiceException e) {
23
-        logger.error(e.getMessage(), e);
24
-        return AjaxResult.error(e.getMessage());
25
-    }
26
-
27
-    /**
28
-     * 参数校验异常
29
-     */
30
-    @ExceptionHandler(MethodArgumentNotValidException.class)
31
-    public AjaxResult handleMethodArgumentNotValidException(MethodArgumentNotValidException e) {
32
-        String message = e.getBindingResult().getFieldError().getDefaultMessage();
33
-        return AjaxResult.error(message);
34
-    }
35
-
36
-    /**
37
-     * 系统异常
38
-     */
39
-    @ExceptionHandler(Exception.class)
40
-    public AjaxResult handleException(Exception e) {
41
-        logger.error(e.getMessage(), e);
42
-        return AjaxResult.error("系统繁忙,请稍后再试");
43
-    }
44
-}

Loading…
Откажи
Сачувај