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,