From 3ad3b9a39ec48d57fdadbd98840cacfa86e5d2b3 Mon Sep 17 00:00:00 2001 From: sunflower2014 Date: Thu, 31 Jul 2025 15:32:14 +0800 Subject: [PATCH] =?UTF-8?q?1.=E6=93=8D=E4=BD=9C=E6=97=A5=E5=BF=97=E5=A2=9E?= =?UTF-8?q?=E5=8A=A0=E5=88=A0=E9=99=A4=E3=80=81=E6=81=A2=E5=A4=8D=EF=BC=8C?= =?UTF-8?q?=E5=8F=91=E5=B8=83=E7=AD=89=E6=93=8D=E4=BD=9C=202.=E8=B5=84?= =?UTF-8?q?=E8=AE=AF=E7=B2=BE=E9=80=89=E5=88=97=E8=A1=A8=E8=BF=94=E5=9B=9E?= =?UTF-8?q?=E6=9C=80=E5=90=8E=E9=80=81=E5=AE=A1=E8=80=85=E5=A7=93=E5=90=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- admin/pom.xml | 7 ----- .../reference/admin/AdminApplication.java | 2 +- .../admin/aspect/UserOperationLogAspect.java | 14 ++++++++- .../admin/controller/NewsController.java | 8 +++-- .../admin/job/NewsDeduplicationJob.java | 11 +++++-- .../reference/core/mapper/NewsMapper.java | 12 ++++---- .../core/mapper/UserOperationLogMapper.java | 13 ++++++++ .../core/model/dto/news/SaveNewsDTO.java | 11 +++++-- .../reference/core/model/vo/news/NewsVO.java | 10 +++++++ .../reference/core/service/NewsService.java | 30 +++++++++++++++---- 10 files changed, 91 insertions(+), 27 deletions(-) diff --git a/admin/pom.xml b/admin/pom.xml index c77f4c9..fbcc4cf 100644 --- a/admin/pom.xml +++ b/admin/pom.xml @@ -55,13 +55,6 @@ pdfbox 3.0.5 - - - com.itextpdf - itext7-core - 9.2.0 - pom - diff --git a/admin/src/main/java/com/jinrui/reference/admin/AdminApplication.java b/admin/src/main/java/com/jinrui/reference/admin/AdminApplication.java index 4a1b77c..5c8603e 100644 --- a/admin/src/main/java/com/jinrui/reference/admin/AdminApplication.java +++ b/admin/src/main/java/com/jinrui/reference/admin/AdminApplication.java @@ -14,7 +14,7 @@ import org.springframework.scheduling.annotation.EnableScheduling; "com.jinrui.reference.admin.mapper", "com.jinrui.reference.core.mapper"}) @EnableScheduling -@EnableAspectJAutoProxy +@EnableAspectJAutoProxy(proxyTargetClass = true) public class AdminApplication { public static void main(String[] args) { diff --git a/admin/src/main/java/com/jinrui/reference/admin/aspect/UserOperationLogAspect.java b/admin/src/main/java/com/jinrui/reference/admin/aspect/UserOperationLogAspect.java index f33fd90..e5b9dda 100644 --- a/admin/src/main/java/com/jinrui/reference/admin/aspect/UserOperationLogAspect.java +++ b/admin/src/main/java/com/jinrui/reference/admin/aspect/UserOperationLogAspect.java @@ -16,7 +16,10 @@ import org.springframework.stereotype.Component; import com.jinrui.reference.admin.annotation.OperationInfo; import com.jinrui.reference.admin.model.dto.news.PublishNewsDTO; +import com.jinrui.reference.admin.model.entity.AdminUser; +import com.jinrui.reference.admin.service.AdminJwtService; import com.jinrui.reference.admin.service.UserOperationLogService; +import com.jinrui.reference.core.model.dto.news.SaveNewsDTO; import com.jinrui.reference.core.model.vo.ResultObject; @Component @@ -50,7 +53,16 @@ public class UserOperationLogAspect { } } if ("news".equals(type)) { - userOperationLogService.logUserOperation(type, behavior, (String)args[0], ((PublishNewsDTO)args[1]).getId()); + if (args[1] instanceof PublishNewsDTO) { + userOperationLogService.logUserOperation(type, behavior, (String)args[0], ((PublishNewsDTO)args[1]).getId()); + } else if (args[1] instanceof SaveNewsDTO) { + String token = (String)args[0]; + AdminUser adminUser = AdminJwtService.parseToken(token); + behavior = (adminUser.isReviewer() ? "发布": "送审"); + userOperationLogService.logUserOperation(type, behavior, token, ((SaveNewsDTO)args[1]).getId()); + } else { + userOperationLogService.logUserOperation(type, behavior, (String)args[0], (Long)args[1]); + } } diff --git a/admin/src/main/java/com/jinrui/reference/admin/controller/NewsController.java b/admin/src/main/java/com/jinrui/reference/admin/controller/NewsController.java index 2028e10..8280dcd 100644 --- a/admin/src/main/java/com/jinrui/reference/admin/controller/NewsController.java +++ b/admin/src/main/java/com/jinrui/reference/admin/controller/NewsController.java @@ -83,7 +83,7 @@ public class NewsController { if (!isSuccessed) { return ResultObject.failed("该资讯正在审核中,请勿重复操作!"); } - log.info("path: /news/publish, method: POST, request user id: {}, news id: {}", adminUserId, id); + log.info("path: /news/submit, method: POST, request user id: {}, news id: {}", adminUserId, id); return newsService.submit(id, adminUserId); } catch (Exception e) { log.error("解析登陆Token出错!", e); @@ -94,6 +94,7 @@ public class NewsController { } @PostMapping("/revoke") + @OperationInfo(behavior = "撤销", type = "news") public ResultObject revoke(@RequestHeader("auth-token") String token, @RequestBody PublishNewsDTO publishNewsDTO) { if (!StringUtils.hasText(token)) { @@ -121,7 +122,7 @@ public class NewsController { if (!isSuccessed) { return ResultObject.failed("该资讯正在审核中,请勿重复操作!"); } - log.info("path: /news/publish, method: POST, request user id: {}, news id: {}", adminUserId, id); + log.info("path: /news/revoke, method: POST, request user id: {}, news id: {}", adminUserId, id); return newsService.revoke(id, adminUserId, adminUser.isReviewer()); } catch (Exception e) { log.error("解析登陆Token出错!", e); @@ -197,6 +198,7 @@ public class NewsController { } @DeleteMapping + @OperationInfo(behavior = "删除", type = "news") public ResultObject deleteNews(@RequestHeader("auth-token") String token, @RequestParam("id") Long id) { if (!StringUtils.hasText(token)) { @@ -230,6 +232,7 @@ public class NewsController { } @PostMapping("/{id}/recover") + @OperationInfo(behavior = "恢复", type = "news") public ResultObject recoverNews(@RequestHeader("auth-token") String token, @PathVariable( name = "id", required = true) Long id) { if (!StringUtils.hasText(token)) { @@ -258,6 +261,7 @@ public class NewsController { } @PostMapping("/create/publish") + @OperationInfo(behavior = "发布", type = "news") public ResultObject createPublish(@RequestHeader("auth-token") String token, @RequestBody SaveNewsDTO saveNewsDTO) { if (!StringUtils.hasText(token)) { diff --git a/admin/src/main/java/com/jinrui/reference/admin/job/NewsDeduplicationJob.java b/admin/src/main/java/com/jinrui/reference/admin/job/NewsDeduplicationJob.java index a86fe71..f9eba18 100644 --- a/admin/src/main/java/com/jinrui/reference/admin/job/NewsDeduplicationJob.java +++ b/admin/src/main/java/com/jinrui/reference/admin/job/NewsDeduplicationJob.java @@ -1,6 +1,7 @@ package com.jinrui.reference.admin.job; import java.util.List; +import java.util.Objects; import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; @@ -22,18 +23,22 @@ public class NewsDeduplicationJob { private NewsMapper newsMapper; -// @Scheduled(fixedDelay=15, initialDelay=0, timeUnit = TimeUnit.MINUTES) + @Scheduled(fixedDelay=15, initialDelay=0, timeUnit = TimeUnit.MINUTES) public void cleanDuplicatedData() { List clusterIds = newsMapper.getDuplicatedCluster(); for (String clusterId: clusterIds) { List duplicatedNews = newsMapper.getDuplicatedNews(clusterId); List toBeDeletedNews = duplicatedNews.stream().filter(e -> e.getDeleted() && e.getEditorId() == null).collect(Collectors.toList()); + List modifedNews = duplicatedNews.stream().filter(e -> e.getDeleted() && !Objects.equals(e.getStatus(), 1)).collect(Collectors.toList()); if (duplicatedNews.size() > toBeDeletedNews.size()) { newsService.backupDuplicatedNews(toBeDeletedNews, clusterId); newsService.deletDuplicatedNews(toBeDeletedNews); } + if (duplicatedNews.size() > modifedNews.size()) { + for(News news: modifedNews) { + newsMapper.recoverNews(news.getId(), news.getEditorId()); + } + } } } - - } diff --git a/core/src/main/java/com/jinrui/reference/core/mapper/NewsMapper.java b/core/src/main/java/com/jinrui/reference/core/mapper/NewsMapper.java index 9b22f58..098f078 100644 --- a/core/src/main/java/com/jinrui/reference/core/mapper/NewsMapper.java +++ b/core/src/main/java/com/jinrui/reference/core/mapper/NewsMapper.java @@ -251,7 +251,7 @@ public interface NewsMapper { @Select("SELECT cluster_id FROM news WHERE newsinfo_id IS NOT NULL AND cluster_id IS NOT NULL GROUP BY cluster_id HAVING COUNT(*) > 1") List getDuplicatedCluster(); - @Select("select id, draft_id as draftId, newsinfo_id as newsinfoId, is_delete as deleted, editor_id as editorId from news where cluster_id = #{clusterId} and newsinfo_id IS NOT NULL") + @Select("select id, draft_id as draftId, newsinfo_id as newsinfoId, is_delete as deleted, editor_id as editorId, status from news where cluster_id = #{clusterId} and newsinfo_id IS NOT NULL") List getDuplicatedNews(@Param("clusterId") String clusterId); @Delete("delete from news where id = #{id}") @@ -294,16 +294,16 @@ public interface NewsMapper { "news_tags.source_impact," + "news_tags.China_factor," + "news_tags.public_opinion_score" + - "from news " + + " from news " + " left join news_tags on news.newsinfo_id = news_tags.newsinfo_id " + "" + - " news.status = 2 and news.is_delete = 0 and news.publish_time >= adddate(date(now()), -2) " + + " news.status in (1, 2, 3) and news.is_delete = 0 and news.publish_time >= adddate(date(now()), -2) " + "" + - "and news.id > #{last}" + + " and news.id > #{last}" + "" + "" + - "order by id desc " + - "limit ${limit}" + + " order by id asc " + + " limit ${limit}" + "") List queryNewsByApi(@Param("last") Long last, @Param("limit") int limit); } diff --git a/core/src/main/java/com/jinrui/reference/core/mapper/UserOperationLogMapper.java b/core/src/main/java/com/jinrui/reference/core/mapper/UserOperationLogMapper.java index ecec0a0..01e031f 100644 --- a/core/src/main/java/com/jinrui/reference/core/mapper/UserOperationLogMapper.java +++ b/core/src/main/java/com/jinrui/reference/core/mapper/UserOperationLogMapper.java @@ -32,4 +32,17 @@ public interface UserOperationLogMapper { @Select("select count(*) from user_operation_log where data_id = #{dataId} and type = #{type}") int queryTotal(@Param("dataId") Long dataId, @Param("type") String type); + + @Results({ + @Result(column = "id", property = "id", id = true), + @Result(column = "data_id", property = "dataId"), + @Result(column = "user_id", property = "userId"), + @Result(column = "username", property = "username"), + @Result(column = "user_type", property = "userType"), + @Result(column = "type", property = "type"), + @Result(column = "behavior", property = "behavior"), + @Result(column = "create_time", property = "createTime", javaType = Date.class, jdbcType = JdbcType.TIMESTAMP), + }) + @Select("select * from user_operation_log where data_id = #{dataId} and type = #{type} and behavior = #{behavior} order by create_time desc limit 1") + UserOperationLog selectLastOperation(@Param("dataId") Long dataId, @Param("type") String type, @Param("behavior") String behavior); } diff --git a/core/src/main/java/com/jinrui/reference/core/model/dto/news/SaveNewsDTO.java b/core/src/main/java/com/jinrui/reference/core/model/dto/news/SaveNewsDTO.java index e999471..3c4bfd4 100644 --- a/core/src/main/java/com/jinrui/reference/core/model/dto/news/SaveNewsDTO.java +++ b/core/src/main/java/com/jinrui/reference/core/model/dto/news/SaveNewsDTO.java @@ -7,6 +7,7 @@ import org.springframework.util.CollectionUtils; import org.springframework.util.ObjectUtils; import com.jinrui.reference.core.model.entity.NewsInfo; +import com.jinrui.reference.core.model.entity.NewsTags; import com.jinrui.reference.core.model.vo.news.NewsDetailVO; @SuppressWarnings("unused") @@ -139,13 +140,19 @@ public class SaveNewsDTO { public NewsInfo toNewsInfo() { NewsInfo newsInfo = new NewsInfo(); - newsInfo.setTitle(this.getTitle()); +// newsInfo.setTitle(this.getTitle()); newsInfo.setSummary(this.getSummary()); newsInfo.setStatus(this.getStatus()); - newsInfo.setContent(this.getContent()); +// newsInfo.setContent(this.getContent()); newsInfo.setCreateTime(new Date()); newsInfo.setUpdateTime(newsInfo.getCreateTime()); newsInfo.setInputDate(newsInfo.getCreateTime()); + + NewsTags newsTags = new NewsTags(); + newsTags.setTitle(this.getTitle()); + newsTags.setRewriteContent(this.getContent()); + + newsInfo.setNewsTags(newsTags); return newsInfo; } diff --git a/core/src/main/java/com/jinrui/reference/core/model/vo/news/NewsVO.java b/core/src/main/java/com/jinrui/reference/core/model/vo/news/NewsVO.java index 02a0cb6..5dcc8a4 100644 --- a/core/src/main/java/com/jinrui/reference/core/model/vo/news/NewsVO.java +++ b/core/src/main/java/com/jinrui/reference/core/model/vo/news/NewsVO.java @@ -54,6 +54,8 @@ public class NewsVO { private Double score; + private String submitter; + public Boolean getDeleted() { return deleted; } @@ -145,4 +147,12 @@ public class NewsVO { public void setRating(Byte rating) { this.rating = rating; } + + public String getSubmitter() { + return submitter; + } + + public void setSubmitter(String submitter) { + this.submitter = submitter; + } } diff --git a/core/src/main/java/com/jinrui/reference/core/service/NewsService.java b/core/src/main/java/com/jinrui/reference/core/service/NewsService.java index 61ab262..b3d2bbf 100644 --- a/core/src/main/java/com/jinrui/reference/core/service/NewsService.java +++ b/core/src/main/java/com/jinrui/reference/core/service/NewsService.java @@ -115,6 +115,9 @@ public class NewsService { log.warn("找不到ID为{}的新闻!", id); return ResultObject.failed("找不到ID为" + id + "的新闻!"); } + if (news.getDeleted()) { + return ResultObject.failed("该资讯正在审核中,请勿重复操作!"); + } Integer oldStatus = news.getStatus(); if (oldStatus == 1) { return ResultObject.failed("资讯已被撤稿,请刷新列表页面!"); @@ -476,9 +479,11 @@ public class NewsService { return ResultObject.failed(500, "服务器错误,请联系系统管理员!"); } - // 同步更新对应的全量资讯逻辑 + // 发布时同步更新对应的全量资讯逻辑 try { - syncUpdateNewsInfo(saveNewsDTO); + if (newStatus == 2) { + syncUpdateNewsInfo(saveNewsDTO); + } } catch(IOException e) { log.error("同步更新对应的全量资讯出错!", e); return ResultObject.failed(500, "服务器错误,请联系系统管理员!"); @@ -545,6 +550,10 @@ public class NewsService { if (status == 2) { return ResultObject.failed("请先手动下架新闻然后进行删除!"); } + + if (status == 3) { + return ResultObject.failed("该资讯正在审核中,请勿重复操作"); + } try { int count = newsMapper.deleteNews(newsId, editorId); @@ -898,6 +907,9 @@ public class NewsService { newsMap.put(newsVO.getId(), newsVO); } resultList.add(newsVO); + if (isReviewer) { + newsVO.setSubmitter(this.getNewsLastSubmitter(news.getId())); + } } List columns = columnMapper.queryAll(); @@ -937,6 +949,14 @@ public class NewsService { return pageObject; } + private String getNewsLastSubmitter(Long newsId) { + UserOperationLog userOperationLog = userOperationLogMapper.selectLastOperation(newsId, "news", "送审"); + if (userOperationLog == null) { + return null; + } + return userOperationLog.getUsername(); + } + public ResultObject getScore(Long id) { News news = newsMapper.getById(id); String newsinfoId = news.getNewsinfoId(); @@ -1087,7 +1107,7 @@ public class NewsService { return ResultObject.failed("找不到ID为" + id + "的新闻!"); } Integer oldStatus = news.getStatus(); - if (oldStatus != 1) { + if (oldStatus != 1||news.getDeleted()) { return ResultObject.failed("该资讯正在审核中,请勿重复操作"); } @@ -1103,14 +1123,14 @@ public class NewsService { } Integer oldStatus = news.getStatus(); if (isReviewer) { - if (oldStatus != 2) { + if (oldStatus != 2||news.getDeleted()) { return ResultObject.failed("该资讯正在审核中,请勿重复操作"); } newsMapper.changeFrom(id, oldStatus, 3, editorId); return ResultObject.success(); } - if (oldStatus != 3) { + if (oldStatus != 3||news.getDeleted()) { return ResultObject.failed("该资讯正在审核中,请勿重复操作"); }