feat: 合规红线(提交审核接入敏感词检查 + 内容审核抽象 + 合规声明)

This commit is contained in:
Zhou Weidong committed 2026-10-17 03:03:51 +08:00
1 parent 9d92fa2a73
commit abea0a6c39
5 files changed
+112

No files matched your search

@@ -0,0 +1,27 @@
// Author: fruit.com.cn
package com.fruitshorts.framework.compliance;
/**
* 平台合规声明(法律红线,不可删除或修改)。
*
* <p>本软件「水果短剧(FruitShorts)」为正规短剧平台,仅用于承载、分发符合法律法规
* 与公序良俗的短剧内容。平台严禁且不提供任何用于上传、传播、存储色情、淫秽、露骨或
* 违法犯罪内容的功能。任何运营方利用本软件从事违法犯罪行为的,其法律责任由运营方独立
* 承担,与开发者无任何法律关系。
*/
public final class ComplianceNotice {
private ComplianceNotice() {
}
/** 平台定位与合法用途声明。 */
public static final String PLATFORM_STATEMENT =
"水果短剧(FruitShorts)为正规短剧平台,仅用于合法合规的短剧内容运营,"
+ "严禁用于任何违法犯罪活动或色情、淫秽、露骨内容的传播。";
/** 内容合规红线:用户生成内容发布前必须通过敏感词自动检查。 */
public static final String CONTENT_RED_LINE =
"所有用户生成内容必须通过敏感词自动检查(BLOCK 级直接拦截),"
+ "命中待审词必须进入人工审核,禁止任何违规内容上线。";
}
@@ -0,0 +1,31 @@
// Author: fruit.com.cn
package com.fruitshorts.framework.compliance;
/**
* 图片/视频内容审核抽象(露骨内容、违规画面检测)。
* 第一阶段默认未接入第三方,接入时新增实现类即可,业务侧不感知。
*/
public interface ContentModerationService {
/** 审核结论:通过 / 拦截 / 转人工。 */
enum Verdict {
PASS, BLOCK, REVIEW
}
/**
* 审核图片。
*
* @param imageUrl 图片地址
* @return 审核结论
*/
Verdict checkImage(String imageUrl);
/**
* 审核视频(实现方负责抽帧)。
*
* @param videoUrl 视频地址
* @return 审核结论
*/
Verdict checkVideo(String videoUrl);
}
@@ -0,0 +1,20 @@
// Author: fruit.com.cn
package com.fruitshorts.framework.compliance;
/**
* 默认内容审核实现:未配置第三方审核服务时一律放行,交由运营方人工审核兜底。
* 接入第三方(如阿里云内容安全 / Google Cloud Vision SafeSearch)后新增实现类并替换装配。
*/
public class DisabledContentModeration implements ContentModerationService {
@Override
public Verdict checkImage(String imageUrl) {
return Verdict.PASS;
}
@Override
public Verdict checkVideo(String videoUrl) {
return Verdict.PASS;
}
}
+5
View File
@@ -39,5 +39,10 @@
<groupId>com.fruitshorts</groupId>
<artifactId>fruitshorts-module-system</artifactId>
</dependency>
<!-- 提交审核前做敏感词自动检查(词库在互动域),拦截违规标题/描述 -->
<dependency>
<groupId>com.fruitshorts</groupId>
<artifactId>fruitshorts-module-interaction</artifactId>
</dependency>
</dependencies>
</project>
@@ -12,6 +12,9 @@ import com.fruitshorts.content.dal.entity.Drama;
import com.fruitshorts.content.enums.ContentStatus;
import com.fruitshorts.content.service.DramaService;
import com.fruitshorts.content.service.EpisodeService;
import com.fruitshorts.content.vo.EpisodeRespVO;
import com.fruitshorts.interaction.service.SensitiveWordCheck;
import com.fruitshorts.interaction.service.SensitiveWordService;
import com.fruitshorts.creator.dal.entity.ContentSubmission;
import com.fruitshorts.creator.dal.entity.Creator;
import com.fruitshorts.creator.dal.mapper.ContentSubmissionMapper;
@@ -52,6 +55,7 @@ public class ContentSubmissionService {
private final ContentSubmissionMapper submissionMapper;
private final DramaService dramaService;
private final EpisodeService episodeService;
private final SensitiveWordService sensitiveWordService;
public PageResult<ContentSubmission> page(SubmissionQueryReqVO req) {
Page<ContentSubmission> page = new Page<>(req.getSafePageIndex(), req.getSafePageSize());
@@ -90,6 +94,7 @@ public class ContentSubmissionService {
if (!Objects.equals(drama.getCreatorId(), creator.getId())) {
throw new ServiceException(ErrorCode.FORBIDDEN, "无权访问该作品");
}
checkContentSensitive(drama);
if (!Set.of(TYPE_CREATE, TYPE_UPDATE, TYPE_PUBLISH, TYPE_OFFLINE).contains(type)) {
throw new ServiceException(ErrorCode.BAD_REQUEST, "未知的提交类型: " + type);
}
@@ -166,6 +171,30 @@ public class ContentSubmissionService {
return submission;
}
/**
* 提交审核前的敏感词自动检查:命中禁止词(BLOCK)直接拦截,命中待审词(REVIEW)仍放行交由人工复核。
* 覆盖标题、副标题、简介、标签与全部分集标题。
*/
private void checkContentSensitive(Drama drama) {
checkText(drama.getTitle(), "标题");
checkText(drama.getSubtitle(), "副标题");
checkText(drama.getSynopsis(), "简介");
checkText(drama.getTags(), "标签");
for (EpisodeRespVO ep : episodeService.listByDrama(drama.getId(), null)) {
checkText(ep.getTitle(), "分集标题");
}
}
private void checkText(String text, String field) {
if (!StringUtils.hasText(text)) {
return;
}
SensitiveWordCheck check = sensitiveWordService.check(text);
if (check.blocked()) {
throw new ServiceException(ErrorCode.OPERATION_NOT_ALLOWED, field + check.reason());
}
}
/**
* 创作者撤回自己的提交(撤回重提)。
* 只有还没出结果的提交能撤回;撤回后短剧退回草稿,创作者可以继续改。