Files
nj/app/lib/data/services/sensitive_words.dart
iven 988ee7335a
Some checks failed
Main Merge / backend (push) Has been cancelled
Main Merge / frontend (push) Has been cancelled
feat(app): 内容安全词库 + 过滤服务 + 分享前检查 — 28 个测试全覆盖
新增文件:
- sensitive_words.dart — 8 分类 ~200 条敏感词 + 谐音/形近/数字变体映射
- content_filter_service.dart — 精确匹配 + 变体匹配 + 文本预处理(去零宽/空格/符号)
- content_filter_service_test.dart — 28 个测试(8分类精确/安全内容/预处理/变体/边界/词库完整性)

修改:
- share_bottom_sheet.dart — 分享到班级前调用 ContentFilterService,
  有敏感词时弹出警告对话框(返回修改/仍然分享),新增 contentText 参数
2026-06-03 19:40:13 +08:00

142 lines
4.1 KiB
Dart
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// 敏感词库 — 本地静态词库常量,面向小学生场景
//
// 分类:暴力、色情、欺凌、毒品、赌博、政治、诈骗、粗口
// 每个分类包含基础词 + 谐音/形近/数字变体
// 词库为 const 编译期常量,零运行时开销
//
// 注意:本词库仅为 Phase 1 基础覆盖Phase 2 将接入服务端 AI + 可更新词库。
/// 敏感词分类
enum SensitiveCategory {
violence('暴力'),
sexual('色情'),
bullying('欺凌'),
drugs('毒品'),
gambling('赌博'),
politics('政治敏感'),
fraud('诈骗'),
profanity('粗口');
const SensitiveCategory(this.label);
final String label;
}
/// ============================================================
/// 各分类敏感词
/// ============================================================
/// 暴力类
const _violenceWords = [
// 直接暴力
'杀人', '砍人', '捅人', '打死', '打死你', '弄死', '弄死你',
'揍你', '揍死', '打死他', '砍死', '捅死',
'杀了他', '打死他', '砍了他', '捅了他',
'去死', '你去死', '怎么不去死',
'割腕', '割脖子', '跳楼', '上吊',
// 武器
'炸弹', '手枪', '步枪', '子弹', '刀杀',
// 自残/伤害暗示
'自杀', '自残', '不想活',
];
/// 色情类
const _sexualWords = [
'色情', '裸体', '裸照', '黄色', '黄片',
'做爱', '性行为', '性交', '强奸', '强暴',
'猥亵', '性骚扰', '偷拍',
'发情', '骚货', '贱人',
];
/// 欺凌类
const _bullyingWords = [
'废物', '垃圾', '蠢货', '白痴', '弱智',
'傻子', '笨蛋', '猪头', '丑八怪',
'滚开', '滚蛋', '闭嘴', '别烦我',
'讨厌鬼', '没人要', '没朋友',
'不和你玩', '不要和你玩',
'大家不要理', '孤立',
'偷东西', '小偷',
];
/// 毒品类
const _drugsWords = [
'毒品', '吸毒', '贩毒', '大麻', '海洛因',
'冰毒', '摇头丸', '可卡因', '吗啡',
'鸦片', 'K粉', '安非他命',
'上瘾', '毒瘾',
];
/// 赌博类
const _gamblingWords = [
'赌博', '赌钱', '下注', '押注', '赌场',
'买彩票', '时时彩', '六合彩',
'百家乐', '老虎机', '扑克赌',
'赌债', '借钱赌',
];
/// 政治敏感类
const _politicsWords = [
'反动', '颠覆', '分裂', '暴动', '造反',
'推翻', '政变', '游行示威',
];
/// 诈骗类
const _fraudWords = [
'诈骗', '骗钱', '骗密码', '骗账号',
'中奖了', '恭喜中奖', '免费领取',
'点击链接领奖', '转账给我',
'刷单', '兼职刷单', '高薪兼职',
'传销', '拉人头',
];
/// 粗口类
const _profanityWords = [
'操你', '妈的', '他妈', '去你的', '狗屎',
'', '', '放屁', '扯淡', '王八蛋',
'混蛋', '', '我去', '卧槽',
'我靠', '我擦',
];
/// 全量词库:分类 → 词列表
const Map<SensitiveCategory, List<String>> kSensitiveWords = {
SensitiveCategory.violence: _violenceWords,
SensitiveCategory.sexual: _sexualWords,
SensitiveCategory.bullying: _bullyingWords,
SensitiveCategory.drugs: _drugsWords,
SensitiveCategory.gambling: _gamblingWords,
SensitiveCategory.politics: _politicsWords,
SensitiveCategory.fraud: _fraudWords,
SensitiveCategory.profanity: _profanityWords,
};
/// ============================================================
/// 谐音/形近/数字变体映射
/// ============================================================
/// 原词 → 变体列表
///
/// 变体检测在预处理后的文本上运行,可以捕获常见的绕过手法:
/// - 数字谐音: "死" → "4"
/// - 形近替换: "傻" → "纱"
/// - 拼音缩写: "牛逼" → "nb"
const Map<String, List<String>> kHomophoneVariants = {
// 暴力相关
'': ['4', '', '', ''],
'': ['', '', ''],
'': ['砍人'],
'': ['捅人'],
// 欺凌相关
'': ['', '', ''],
'': [], // 无实际变体
'': [''],
'废物': ['费物', '废无'],
'垃圾': ['拉吉', '垃 圾'],
// 粗口相关
'': ['', '', ''],
'卧槽': ['我槽', '我草', 'wc', 'WC', 'Wc'],
'我靠': ['我 k', '我K'],
// 欺凌
'': [''],
'': [''],
};