diff --git a/web/src/views/RiskRules.vue b/web/src/views/RiskRules.vue
index b45d99a..0299feb 100644
--- a/web/src/views/RiskRules.vue
+++ b/web/src/views/RiskRules.vue
@@ -76,6 +76,7 @@
考核周期 {{ rule.threshold }}天
下载量 ≥ {{ rule.threshold }}GB 时分享率 ≥ {{ rule.minRatio }}
+ 永久保留 ≥ {{ rule.permRank || '—' }} / 封存豁免 ≥ {{ rule.sealExemptRank || '—' }}
{{ metricLabel(rule.metric) }} {{ condLabel(rule.condition) }} {{ rule.threshold }}{{ rule.unit || '' }}
- →
- 封号/删除账号
+ →
+ {{ rule.type==='EXEMPT' ? '保号' : '封号/删除账号' }}
+
+
+
+ 永久保留等级
+
+ 该等级及以上用户永久保留,不受任何清理规则影响
+
+
+ 封存豁免等级
+
+ 该等级及以上用户封存后不会被删除
+
+
+
@@ -163,7 +179,7 @@
-
规则体系:等级豁免 → 账号存活 → 流量监控 → H&R 惩罚 → 分享率检查
+
规则体系:等级豁免 → 账号存活 → 新人考核 → 流量监控 → H&R 惩罚 → 分享率
满足豁免条件的用户不受任何规则影响。系统会自动根据风险百分比触发告警(riskPct > 80%)。
@@ -174,7 +190,7 @@
{{ p.name }}
- 封号
+ {{ p.type==='EXEMPT' ? '保号' : '封号' }}
{{ presetDesc(p) }}
@@ -200,6 +216,7 @@ const typeOptions = [
{ value: 'RATIO', label: '分享率' },
{ value: 'TASK', label: '新人考核' },
{ value: 'DRATIO', label: '动态分享率' },
+ { value: 'EXEMPT', label: '等级豁免' },
]
const condOptions = [
{ value: 'GT', label: '大于' },
@@ -257,6 +274,9 @@ const onTypeChange = (rule) => {
rule.threshold = rule.threshold || 100
rule.minRatio = rule.minRatio || 1.0
rule.unit = 'GB'
+ } else if (rule.type === 'EXEMPT') {
+ rule.permRank = rule.permRank || ''
+ rule.sealExemptRank = rule.sealExemptRank || ''
} else {
const d = typeDefaults[rule.type]
if (d) { rule.metric = d.metric; rule.condition = d.condition; rule.unit = d.unit }
@@ -281,6 +301,8 @@ const presets = [
{ name:'新人考核', type:'TASK', threshold:30, unit:'天', description:'新注册用户需在考核周期内完成各项要求' },
// 动态分享率
{ name:'动态分享率', type:'DRATIO', threshold:100, minRatio:1.0, unit:'GB', description:'下载量达到阈值时分享率不低于要求值' },
+ // 等级豁免
+ { name:'等级豁免', type:'EXEMPT', permRank:'Elite User', sealExemptRank:'Power User', description:'达到等级的账号可豁免清理' },
]
const presetCategories = [
@@ -290,11 +312,13 @@ const presetCategories = [
{ title:'H&R 惩罚', items: presets.filter(p => p.type === 'HD') },
{ title:'新人考核', items: presets.filter(p => p.type === 'TASK') },
{ title:'分享率', items: presets.filter(p => p.type === 'DRATIO') },
+ { title:'等级豁免', items: presets.filter(p => p.type === 'EXEMPT') },
]
const presetDesc = (p) => {
if (p.type === 'TASK') return `考核周期 ${p.threshold||30} 天,需满足上传/下载/魔力值/做种积分/做种时间要求`
if (p.type === 'DRATIO') return `下载量 ≥ ${p.threshold||100}GB 时分享率 ≥ ${p.minRatio||1.0}`
+ if (p.type === 'EXEMPT') return `永久保留 ≥ ${p.permRank||'—'} / 封存豁免 ≥ ${p.sealExemptRank||'—'}`
const condLabel = condOptions.find(c => c.value === p.condition)?.label || p.condition
const appLabel = applicableOptions.find(a => a.value === p.applicable)?.label || ''
return `${metricOptions.find(m=>m.value===p.metric)?.label||p.metric} ${condLabel} ${p.threshold}${p.unit||''}${appLabel?' ('+appLabel+')':''}`