234 lines
7.0 KiB
JavaScript
234 lines
7.0 KiB
JavaScript
|
|
/**
|
|||
|
|
* 塔罗小程序 - 提问过滤与质量评分模块
|
|||
|
|
* 纯本地规则,不依赖外部 API
|
|||
|
|
*/
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 验证问题并返回过滤结果
|
|||
|
|
* @param {string} question - 用户输入的问题
|
|||
|
|
* @returns {Object} { status: "pass"|"rewrite"|"reject", reason: "", suggestions: [] }
|
|||
|
|
*/
|
|||
|
|
function validateQuestion(question) {
|
|||
|
|
if (!question || question.trim().length === 0) {
|
|||
|
|
return {
|
|||
|
|
status: 'reject',
|
|||
|
|
reason: '请输入您的问题',
|
|||
|
|
suggestions: []
|
|||
|
|
};
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
const q = question.trim();
|
|||
|
|
|
|||
|
|
// ========== 1. 直接拒绝规则 (reject) ==========
|
|||
|
|
|
|||
|
|
// 1.1 联系方式检测
|
|||
|
|
const contactPatterns = [
|
|||
|
|
/微信|wx|weixin|vx/i,
|
|||
|
|
/qq|扣扣|q q/i,
|
|||
|
|
/电话|手机|tel|phone/i,
|
|||
|
|
/tg|telegram|飞机/i,
|
|||
|
|
/\d{5,}/ // 5位以上数字(可能是QQ号、电话等)
|
|||
|
|
];
|
|||
|
|
if (contactPatterns.some(pattern => pattern.test(q))) {
|
|||
|
|
return {
|
|||
|
|
status: 'reject',
|
|||
|
|
reason: '为了保证内容健康与占卜体验,该问题暂不支持占卜。',
|
|||
|
|
suggestions: []
|
|||
|
|
};
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 1.2 广告引流检测
|
|||
|
|
const adPatterns = [
|
|||
|
|
/加我|联系我|找我|私信|咨询我/i,
|
|||
|
|
/推广|代理|兼职|赚钱|刷单/i,
|
|||
|
|
/链接|网址|http|www\./i
|
|||
|
|
];
|
|||
|
|
if (adPatterns.some(pattern => pattern.test(q))) {
|
|||
|
|
return {
|
|||
|
|
status: 'reject',
|
|||
|
|
reason: '为了保证内容健康与占卜体验,该问题暂不支持占卜。',
|
|||
|
|
suggestions: []
|
|||
|
|
};
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 1.3 成人/违法内容检测
|
|||
|
|
const illegalPatterns = [
|
|||
|
|
/黄色|色情|裸|性爱/i,
|
|||
|
|
/毒品|大麻|冰毒/i,
|
|||
|
|
/枪支|炸药|爆炸/i
|
|||
|
|
];
|
|||
|
|
if (illegalPatterns.some(pattern => pattern.test(q))) {
|
|||
|
|
return {
|
|||
|
|
status: 'reject',
|
|||
|
|
reason: '为了保证内容健康与占卜体验,该问题暂不支持占卜。',
|
|||
|
|
suggestions: []
|
|||
|
|
};
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 1.4 专业决策类检测(医疗/法律/金融/赌博)
|
|||
|
|
const professionalPatterns = [
|
|||
|
|
/病|癌|肿瘤|手术|治疗|吃药|诊断/i,
|
|||
|
|
/官司|诉讼|判决|坐牢|犯法/i,
|
|||
|
|
/股票|期货|基金|投资.*收益|炒股/i,
|
|||
|
|
/彩票|赌博|赌|博彩|中奖号码/i
|
|||
|
|
];
|
|||
|
|
if (professionalPatterns.some(pattern => pattern.test(q))) {
|
|||
|
|
return {
|
|||
|
|
status: 'reject',
|
|||
|
|
reason: '为了让占卜更聚焦你自身的成长,建议调整提问方式。塔罗牌无法替代专业咨询。',
|
|||
|
|
suggestions: []
|
|||
|
|
};
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 1.5 危险内容检测
|
|||
|
|
const dangerPatterns = [
|
|||
|
|
/自杀|轻生|结束生命|不想活/i,
|
|||
|
|
/杀人|伤害.*人|报复/i,
|
|||
|
|
/什么时候死|何时去世|死亡时间/i
|
|||
|
|
];
|
|||
|
|
if (dangerPatterns.some(pattern => pattern.test(q))) {
|
|||
|
|
return {
|
|||
|
|
status: 'reject',
|
|||
|
|
reason: '为了保证内容健康与占卜体验,该问题暂不支持占卜。如您正面临困境,建议寻求专业心理咨询帮助。',
|
|||
|
|
suggestions: []
|
|||
|
|
};
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// ========== 2. 建议改写规则 (rewrite) ==========
|
|||
|
|
|
|||
|
|
const rewritePatterns = [
|
|||
|
|
{
|
|||
|
|
// 他/她爱不爱我
|
|||
|
|
pattern: /(他|她|ta|TA|对方|那个人)(爱不爱|喜不喜欢|有没有感觉|在乎)/i,
|
|||
|
|
suggestions: [
|
|||
|
|
'我在这段感情中感受到爱了吗',
|
|||
|
|
'我对这段关系的真实期待是什么',
|
|||
|
|
'我需要怎样的爱才能感到满足'
|
|||
|
|
]
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
// 是否出轨
|
|||
|
|
pattern: /(他|她|ta|TA|对方).*(出轨|劈腿|有别人|背叛)/i,
|
|||
|
|
suggestions: [
|
|||
|
|
'我内心的不安来自哪里',
|
|||
|
|
'我在这段关系中缺失了什么',
|
|||
|
|
'我该如何重建内心的安全感'
|
|||
|
|
]
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
// TA在干嘛
|
|||
|
|
pattern: /(他|她|ta|TA|对方).*(在干嘛|在做什么|在想什么|想法)/i,
|
|||
|
|
suggestions: [
|
|||
|
|
'我为什么会如此在意对方的动态',
|
|||
|
|
'我现在最需要关注的是什么',
|
|||
|
|
'我该如何平复内心的焦虑'
|
|||
|
|
]
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
// 控制类问题
|
|||
|
|
pattern: /(怎么|如何).*(让|使|控制|改变).*(他|她|ta|TA|对方)/i,
|
|||
|
|
suggestions: [
|
|||
|
|
'我可以如何让自己变得更有吸引力',
|
|||
|
|
'我在关系中真正想要的是什么',
|
|||
|
|
'我该如何更好地表达自己的需求'
|
|||
|
|
]
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
// 怎么让他喜欢我
|
|||
|
|
pattern: /(怎么|如何).*(让|使).*(他|她|ta|TA|对方).*(喜欢|爱上|回来)/i,
|
|||
|
|
suggestions: [
|
|||
|
|
'我身上最值得被爱的特质是什么',
|
|||
|
|
'我该如何在关系中保持真实的自己',
|
|||
|
|
'我准备好迎接一段健康的关系了吗'
|
|||
|
|
]
|
|||
|
|
}
|
|||
|
|
];
|
|||
|
|
|
|||
|
|
for (const item of rewritePatterns) {
|
|||
|
|
if (item.pattern.test(q)) {
|
|||
|
|
console.log('匹配到改写规则:', item.pattern);
|
|||
|
|
return {
|
|||
|
|
status: 'rewrite',
|
|||
|
|
reason: '为了让占卜更聚焦你的成长,我们建议这样提问:',
|
|||
|
|
suggestions: item.suggestions
|
|||
|
|
};
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// ========== 3. 通过验证 ==========
|
|||
|
|
console.log('问题通过所有过滤规则');
|
|||
|
|
return {
|
|||
|
|
status: 'pass',
|
|||
|
|
reason: '',
|
|||
|
|
suggestions: []
|
|||
|
|
};
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 评估问题质量
|
|||
|
|
* @param {string} question - 用户输入的问题
|
|||
|
|
* @returns {Object} { score: 0-5, level: "普通"|"良好"|"优秀", icon: "🌱"|"🌿"|"🌳" }
|
|||
|
|
*/
|
|||
|
|
function scoreQuestion(question) {
|
|||
|
|
if (!question || question.trim().length === 0) {
|
|||
|
|
return {
|
|||
|
|
score: 0,
|
|||
|
|
level: '普通',
|
|||
|
|
icon: '🌱'
|
|||
|
|
};
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
const q = question.trim();
|
|||
|
|
let score = 0;
|
|||
|
|
|
|||
|
|
// 规则1: 以"我"为主体 (+2分)
|
|||
|
|
if (/^我|[,。!?\s]我/.test(q)) {
|
|||
|
|
score += 2;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 规则2: 包含情绪或状态词 (+1分)
|
|||
|
|
const emotionWords = /感受|状态|心情|情绪|焦虑|迷茫|困惑|压力|快乐|幸福|痛苦|难过/;
|
|||
|
|
if (emotionWords.test(q)) {
|
|||
|
|
score += 1;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 规则3: 开放式问题 (+1分)
|
|||
|
|
const openQuestions = /如何|怎样|什么|哪些|为什么/;
|
|||
|
|
if (openQuestions.test(q)) {
|
|||
|
|
score += 1;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 规则4: 包含绝对预测词 (-2分)
|
|||
|
|
const absoluteWords = /会不会|能不能|一定会|肯定|必然|到底|结果是/;
|
|||
|
|
if (absoluteWords.test(q)) {
|
|||
|
|
score -= 2;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 确保分数在 0-5 范围内
|
|||
|
|
score = Math.max(0, Math.min(5, score));
|
|||
|
|
|
|||
|
|
// 映射等级
|
|||
|
|
let level, icon;
|
|||
|
|
if (score <= 2) {
|
|||
|
|
level = '普通';
|
|||
|
|
icon = '🌱';
|
|||
|
|
} else if (score <= 4) {
|
|||
|
|
level = '良好';
|
|||
|
|
icon = '🌿';
|
|||
|
|
} else {
|
|||
|
|
level = '优秀';
|
|||
|
|
icon = '🌳';
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return {
|
|||
|
|
score,
|
|||
|
|
level,
|
|||
|
|
icon
|
|||
|
|
};
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
module.exports = {
|
|||
|
|
validateQuestion,
|
|||
|
|
scoreQuestion
|
|||
|
|
};
|