From 7ec4e16eb608201b6c2bed8d74242a5a717d6f6f Mon Sep 17 00:00:00 2001 From: mediabot-pt <295750538+mediabot-pt@users.noreply.github.com> Date: Mon, 6 Jul 2026 22:35:38 +0800 Subject: [PATCH] feat: add fixed-order rule summary text at bottom of visual editor Sort order: EXEMPT \u2192 TASK \u2192 HD \u2192 KILL \u2192 RATIO \u2192 DRATIO \u2192 TRAFFIC Each rule shown as natural language sentence with applicable condition TASK shows only enabled requirements Regardless of card drag order, summary always displays in fixed sequence --- web/src/views/RiskRules.vue | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/web/src/views/RiskRules.vue b/web/src/views/RiskRules.vue index 551ba10..cc0110c 100644 --- a/web/src/views/RiskRules.vue +++ b/web/src/views/RiskRules.vue @@ -178,6 +178,14 @@ + + +
+
规则摘要
+
+ {{ i + 1 }}. {{ ruleText(r) }} +
+
@@ -367,6 +375,35 @@ const editSiteName = computed(() => { const site = (sites.value||[]).find(s => s.siteType === editType.value) return site ? (site.names||[]).join('/') || site.siteId || editType.value : editType.value }) + +const typeOrder = ['EXEMPT', 'TASK', 'HD', 'KILL', 'RATIO', 'DRATIO', 'TRAFFIC'] +const sortedRules = computed(() => { + return [...parsed.value].sort((a, b) => { + const ai = typeOrder.indexOf(a.type), bi = typeOrder.indexOf(b.type) + return (ai === -1 ? 99 : ai) - (bi === -1 ? 99 : bi) + }) +}) + +const ruleText = (r) => { + const appText = r.applicable ? `(${applicableOptions.find(x=>x.value===r.applicable)?.label||r.applicable})` : '' + if (r.type === 'EXEMPT') { + return `等级豁免:永久保留 ≥ ${rankDisplay(r.permRank)}、封存豁免 ≥ ${rankDisplay(r.sealExemptRank)} → 保号` + } + if (r.type === 'TASK') { + const reqs = (r.requirements||[]).filter(x => x.enabled).map(x => `${x.label} ≥ ${x.threshold}${x.unit}`).join('、') + return `新人考核:${r.threshold||30}天内,${reqs} → 封号/删除账号${appText}` + } + const metric = metricLabel(r.metric) + const cond = condLabel(r.condition) + const val = `${metric}${cond}${r.threshold}${r.unit||''}` + if (r.type === 'DRATIO') { + return `动态分享率:下载量 ≥ ${r.threshold}GB 时分享率 ≥ ${r.minRatio} → 封号(缓刑7天)${appText}` + } + if (r.type === 'RATIO') { + return `分享率:${val} → 封号(缓刑7天)${appText}` + } + return `${typeLabel(r.type)}:${val} → 封号/删除账号${appText}` +} const merged = computed(() => (Array.isArray(sites.value)?sites.value:[]).map(s => ({ siteId: s.siteId, names: s.names, siteType: s.siteType, ruleCount: rulesMap.value[s.siteType]?.ruleCount || 0, version: rulesMap.value[s.siteType]?.version || null,