实现敏感词检测后,失败发生邮箱

This commit is contained in:
2025-11-22 14:03:40 +08:00
parent c2cac51762
commit f3a9926caf
35 changed files with 1233 additions and 43916 deletions

View File

@@ -18,7 +18,6 @@ import org.xyzh.common.utils.IDUtils;
import org.xyzh.news.mapper.BannerMapper;
import org.xyzh.api.news.banner.BannerService;
import org.xyzh.api.system.permission.ResourcePermissionService;
import org.xyzh.common.dto.user.TbSysUser;
import org.xyzh.common.vo.UserDeptRoleVO;
import org.xyzh.common.core.enums.ResourceType;
import org.xyzh.system.utils.LoginUtil;

View File

@@ -281,14 +281,17 @@ public class NCResourceServiceImpl implements ResourceService {
TbResource resource = resourceVO.getResource();
if(resource.getStatus()==1 && !resource.getIsAudited()){
// 进行审核
ResultDomain<Boolean> pass =auditService.auditText(resource.getContent());
if(pass.isSuccess() && pass.getData()){
ResultDomain<String> pass =auditService.auditText(resource.getTitle() + " "+resource.getContent());
if(pass.isSuccess()){
resource.setIsAudited(true);
}else {
auditService.sendAuditResultMessage(resource.getCreator(), "文章"+resource.getTitle(), pass.getDataList());
resource.setStatus(4);
}
}
// 插入数据库
int result = resourceMapper.insertResource(resourceVO.getResource());
int result = resourceMapper.insertResource(resource);
// 插入资源标签
if (resourceVO.getTags() != null && resourceVO.getTags().size() > 0) {
List<TbResourceTag> resourceTagList = new ArrayList<>();
@@ -360,10 +363,37 @@ public class NCResourceServiceImpl implements ResourceService {
return resultDomain;
}
resource.setIsAudited(existing.getIsAudited());
if(!existing.getContent().equals(resource.getContent())){
// 检查内容是否发生变化,如果变化则需要重新审核
boolean contentChanged = !existing.getContent().equals(resource.getContent());
boolean titleChanged = !existing.getTitle().equals(resource.getTitle());
// 如果内容或标题发生变化,需要重新审核
if (contentChanged || titleChanged) {
resource.setIsAudited(false);
// 如果当前状态是已发布(1),且要发布状态(1),需要先设置为审核中(3)再进行审核
if (resource.getStatus() != null && resource.getStatus() == 1) {
// 先设置为审核中状态
resource.setStatus(3);
// 进行敏感词审核
ResultDomain<String> auditResult = auditService.auditText(resource.getTitle() +" "+resource.getContent());
if (auditResult.isSuccess()) {
// 审核通过,设置为已发布
resource.setStatus(1);
resource.setIsAudited(true);
} else {
// 审核失败,设置为敏感词未通过
resource.setStatus(4);
resource.setIsAudited(false);
auditService.sendAuditResultMessage(existing.getCreator(), "文章:"+resource.getTitle(), auditResult.getDataList());
}
}
} else {
// 内容未变化,保持原有审核状态
resource.setIsAudited(existing.getIsAudited());
}
Date now = new Date();
// tag先删后增
TbResourceTag resourceTag = new TbResourceTag();
@@ -376,6 +406,7 @@ public class NCResourceServiceImpl implements ResourceService {
resourceTagMapper.deleteByResourceId(resource.getResourceID());
resourceTagMapper.batchInsertResourceTags(Arrays.asList(resourceTag));
// 更新时间
resource.setUpdateTime(now);
@@ -388,7 +419,15 @@ public class NCResourceServiceImpl implements ResourceService {
ResourceVO updatedResourceVO = new ResourceVO();
updatedResourceVO.setResource(updated);
updatedResourceVO.setTags(resourceVO.getTags());
resultDomain.success("更新资源成功", updatedResourceVO);
// 根据审核结果返回不同消息
if (updated.getStatus() == 4) {
resultDomain.success("更新成功,但内容包含敏感词,请修改后重新发布", updatedResourceVO);
} else if (updated.getStatus() == 3) {
resultDomain.success("更新成功,正在审核中", updatedResourceVO);
} else {
resultDomain.success("更新资源成功", updatedResourceVO);
}
return resultDomain;
} else {
resultDomain.fail("更新资源失败");
@@ -457,22 +496,29 @@ public class NCResourceServiceImpl implements ResourceService {
resultDomain.fail("资源不存在");
return resultDomain;
}
if (status == 1 && !resource.getIsAudited()) {
ResultDomain<Boolean> pass = auditService.auditText(resource.getContent());
if (pass.isSuccess() && pass.getData()) {
// 更新状态
resource.setStatus(status);
if (status == 1) { // 发布状态下更新都有重新审核
// 审核中状态变更
TbResource resourceStautsChange = new TbResource();
resourceStautsChange.setResourceID(resourceID);
resourceStautsChange.setStatus(3);
resourceMapper.updateResource(resourceStautsChange);
ResultDomain<String> pass = auditService.auditText(resource.getTitle()+" "+resource.getContent());
if (pass.isSuccess()) {
resource.setIsAudited(true);
} else {
// 审核失败,标记状态为3(审核失败)
resource.setStatus(3);
// 审核失败,标记状态为4(审核失败)
resource.setStatus(4);
resource.setUpdateTime(new Date());
resourceMapper.updateResource(resource);
auditService.sendAuditResultMessage(resource.getCreator(), "文章"+resource.getTitle(), pass.getDataList());
resultDomain.fail("审核失败");
return resultDomain;
}
}
// 更新状态
resource.setStatus(status);
resource.setUpdateTime(new Date());
int result = resourceMapper.updateResource(resource);
@@ -512,15 +558,15 @@ public class NCResourceServiceImpl implements ResourceService {
}
if (!resource.getIsAudited()) {
ResultDomain<Boolean> pass = auditService.auditText(resource.getContent());
if (pass.isSuccess() && pass.getData()) {
ResultDomain<String> pass = auditService.auditText(resource.getTitle()+" "+resource.getContent());
if (pass.isSuccess()) {
resource.setIsAudited(true);
} else {
// 审核失败标记状态为3审核失败
resource.setStatus(3);
resource.setUpdateTime(new Date());
resourceMapper.updateResource(resource);
auditService.sendAuditResultMessage(resource.getCreator(), "文章"+resource.getTitle(), pass.getDataList());
resultDomain.fail("审核失败");
return resultDomain;
}

View File

@@ -1,8 +1,18 @@
package org.xyzh.news.service.impl;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import org.xyzh.api.news.resource.ResourceAuditService;
import org.xyzh.common.core.domain.ResultDomain;
import org.xyzh.common.dto.user.TbSysUser;
import org.xyzh.common.utils.EmailUtils;
import org.xyzh.api.sensitive.SensitiveService;
import org.xyzh.api.system.user.UserService;
/**
* @description 资源审核服务实现类
@@ -11,24 +21,185 @@ import org.xyzh.common.core.domain.ResultDomain;
@Service
public class ResourceAuditServiceImpl implements ResourceAuditService {
private static final Logger logger = LoggerFactory.getLogger(ResourceAuditServiceImpl.class);
@Autowired
private SensitiveService sensitiveService;
@Autowired
private UserService userService;
@Autowired
private EmailUtils emailUtils;
@Override
public ResultDomain<Boolean> auditText(String text) {
ResultDomain<Boolean> result = new ResultDomain<Boolean>();
public ResultDomain<String> auditText(String text) {
ResultDomain<String> result = new ResultDomain<>();
ResultDomain<String> sensitiveRet = sensitiveService.judgeSensitive(text);
// TODO: 文本审核逻辑(敏感词、违规词等规则校验)
// 示例:直接通过
result.success("审核通过", Boolean.TRUE);
if (sensitiveRet.isSuccess()) {
result.success("审核通过", "");
} else {
result.fail("审核失败", sensitiveRet.getDataList());
}
return result;
}
@Override
public ResultDomain<Boolean> auditByFileId(String fileId) {
ResultDomain<Boolean> result = new ResultDomain<Boolean>();
public ResultDomain<String> auditByFileId(String fileId) {
ResultDomain<String> result = new ResultDomain<>();
// TODO:
// 1. 根据 tb_sys_file.id 查询文件信息
// 2. 读取文件内容,提取文本
// 3. 调用 auditText(text) 进行审核
// 4. 审核通过后,更新对应业务记录(tb_resource / tb_data_collection_item / tb_course_node) 的 is_audited = 1
result.success("审核通过", Boolean.TRUE);
String text = "";
ResultDomain<String> sensitiveRet = sensitiveService.judgeSensitive(text);
if (sensitiveRet.isSuccess()) {
result.success("审核通过", "");
} else {
result.fail("审核失败", sensitiveRet.getDataList());
}
return result;
}
@Override
public ResultDomain<Boolean> sendAuditResultMessage(String receiver, String target, List<String> sensitiveWords) {
ResultDomain<Boolean> result = new ResultDomain<>();
try {
// 参数验证
if (!StringUtils.hasText(receiver)) {
logger.warn("发送审核结果邮件失败接收者ID为空");
result.fail("接收者ID不能为空");
return result;
}
if (!StringUtils.hasText(target)) {
logger.warn("发送审核结果邮件失败:目标内容名称为空");
result.fail("目标内容名称不能为空");
return result;
}
// 获取用户信息
ResultDomain<TbSysUser> userDomain = userService.getUserById(receiver);
if (!userDomain.isSuccess() || userDomain.getData() == null) {
logger.warn("发送审核结果邮件失败用户不存在用户ID: {}", receiver);
result.fail("用户不存在");
return result;
}
TbSysUser user = userDomain.getData();
if (!StringUtils.hasText(user.getEmail())) {
logger.warn("发送审核结果邮件失败用户邮箱为空用户ID: {}", receiver);
result.fail("用户邮箱为空");
return result;
}
// 构建邮件内容
String emailBody = buildEmailBody(target, sensitiveWords);
String subject = "【校园新闻平台】审核结果通知";
// 发送HTML邮件
boolean sent = emailUtils.sendHtmlEmail(user.getEmail(), subject, emailBody);
if (sent) {
logger.info("审核结果邮件发送成功用户ID: {}, 邮箱: {}, 内容: {}", receiver, user.getEmail(), target);
result.success("发送消息成功", true);
} else {
logger.error("审核结果邮件发送失败用户ID: {}, 邮箱: {}, 内容: {}", receiver, user.getEmail(), target);
result.fail("邮件发送失败");
}
} catch (Exception e) {
logger.error("发送审核结果邮件异常用户ID: {}, 内容: {}, 错误: {}", receiver, target, e.getMessage(), e);
result.fail("发送消息失败:" + e.getMessage());
}
return result;
}
/**
* @description 构建审核失败邮件内容
* @param target 文章、课程名称
* @param sensitiveWords 敏感词列表
* @return 邮件正文内容
* @author yslg
* @since 2025-11-22
*/
private String buildEmailBody(String target, List<String> sensitiveWords) {
StringBuilder emailBody = new StringBuilder();
String currentTime = new java.text.SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new java.util.Date());
// 构建HTML格式的邮件内容
emailBody.append("<!DOCTYPE html>");
emailBody.append("<html><head><meta charset='UTF-8'>");
emailBody.append("<style>");
emailBody.append("body { font-family: Arial, sans-serif; line-height: 1.6; color: #333; }");
emailBody.append(".container { max-width: 600px; margin: 0 auto; padding: 20px; }");
emailBody.append(".header { background-color: #f8f9fa; padding: 20px; border-radius: 8px; margin-bottom: 20px; }");
emailBody.append(".content { background-color: #fff; padding: 20px; border: 1px solid #dee2e6; border-radius: 8px; }");
emailBody.append(".alert { background-color: #f8d7da; color: #721c24; padding: 15px; border-radius: 4px; margin: 15px 0; }");
emailBody.append(".sensitive-words { background-color: #fff3cd; padding: 15px; border-radius: 4px; margin: 15px 0; }");
emailBody.append(".steps { background-color: #d1ecf1; padding: 15px; border-radius: 4px; margin: 15px 0; }");
emailBody.append(".footer { text-align: center; margin-top: 20px; color: #6c757d; font-size: 12px; }");
emailBody.append("ul { padding-left: 20px; }");
emailBody.append("li { margin: 5px 0; }");
emailBody.append("</style></head><body>");
emailBody.append("<div class='container'>");
// 头部
emailBody.append("<div class='header'>");
emailBody.append("<h2 style='margin: 0; color: #495057;'>📧 校园新闻平台 - 审核结果通知</h2>");
emailBody.append("</div>");
// 主要内容
emailBody.append("<div class='content'>");
emailBody.append("<p>尊敬的用户,您好!</p>");
emailBody.append("<div class='alert'>");
emailBody.append("<strong>⚠️ 审核未通过</strong><br>");
emailBody.append("您提交的内容「<strong>").append(target).append("</strong>」审核未通过。");
emailBody.append("</div>");
emailBody.append("<p><strong>审核失败原因:</strong>内容包含敏感词汇</p>");
// 敏感词列表
if (sensitiveWords != null && !sensitiveWords.isEmpty()) {
emailBody.append("<div class='sensitive-words'>");
emailBody.append("<strong>🔍 检测到的敏感词汇:</strong>");
emailBody.append("<ul>");
for (String word : sensitiveWords) {
emailBody.append("<li><code style='background-color: #f8f9fa; padding: 2px 4px; border-radius: 3px;'>")
.append(word).append("</code></li>");
}
emailBody.append("</ul>");
emailBody.append("</div>");
}
// 处理步骤
emailBody.append("<div class='steps'>");
emailBody.append("<strong>📋 请您按照以下步骤处理:</strong>");
emailBody.append("<ol>");
emailBody.append("<li>检查并修改上述敏感词汇</li>");
emailBody.append("<li>确保内容符合平台发布规范</li>");
emailBody.append("<li>重新提交内容进行审核</li>");
emailBody.append("</ol>");
emailBody.append("</div>");
emailBody.append("<p>如有疑问,请联系平台管理员。</p>");
emailBody.append("</div>");
// 页脚
emailBody.append("<div class='footer'>");
emailBody.append("<p>此邮件为系统自动发送,请勿回复。</p>");
emailBody.append("<p>校园新闻平台 | 发送时间:").append(currentTime).append("</p>");
emailBody.append("</div>");
emailBody.append("</div></body></html>");
return emailBody.toString();
}
}