From c9889a4aabf37c993665b7006e063492a696b86e Mon Sep 17 00:00:00 2001 From: mediabot-pt <295750538+mediabot-pt@users.noreply.github.com> Date: Mon, 6 Jul 2026 21:52:48 +0800 Subject: [PATCH] refactor: simplify rule card UI - hide metric/condition/unit - Replace editable name/metric/condition/unit with plain text in card header - Card header shows: [type] [metric label] [condition label] [threshold][unit] \u2192 \u5c01\u53f7 - Type change auto-updates metric/condition/unit via typeDefaults mapping - Card body only shows: threshold, applicable, description - Fix edit title to show site name instead of raw siteType - Remove unused styles and functions --- web/src/views/RiskRules.vue | 72 ++++++++++++++++++++----------------- 1 file changed, 40 insertions(+), 32 deletions(-) diff --git a/web/src/views/RiskRules.vue b/web/src/views/RiskRules.vue index fdad20b..61d2131 100644 --- a/web/src/views/RiskRules.vue +++ b/web/src/views/RiskRules.vue @@ -31,7 +31,7 @@
-

编辑: {{ editType }}

+

编辑: {{ editSiteName }}

{{ parsed.length }} 条规则
@@ -86,12 +86,12 @@
- - + - - + {{ metricLabel(rule.metric) }} {{ condLabel(rule.condition) }} {{ rule.threshold }}{{ rule.unit || '' }} + → + 封号
#{{ idx + 1 }} @@ -105,34 +105,24 @@
+ +
+ 阈值 + + {{ rule.unit || '' }} +
+
适用条件 - {{ applicableHint(rule.applicable) }}
- +
- 触发条件 - 当 - - - - - - - - - → - 封号 -
- - -
- 规则说明 + 说明
@@ -207,9 +197,21 @@ const metricOptions = [ ] const typeLabel = (t) => typeOptions.find(x => x.value === t)?.label || t -const applicableHint = (a) => { - const m = { '!sealed':'未封存用户', 'sealed':'已封存用户', 'zero_traffic':'上传/下载均为 0', 'new_account_30d':'从未完成种子且无流量增量' } - return a ? `— ${m[a] || ''}` : '' + +const typeDefaults = { + KILL: { metric:'days_since_last_login', condition:'GT', unit:'天' }, + TRAFFIC: { metric:'days_since_last_traffic', condition:'GT', unit:'天' }, + LOGIN: { metric:'days_since_last_login', condition:'GT', unit:'天' }, + HD: { metric:'hnr_count', condition:'GTE', unit:'次' }, + RATIO: { metric:'ratio', condition:'LT', unit:'' }, +} +const metricLabel = (m) => metricOptions.find(x => x.value === m)?.label || m || '' +const condLabel = (c) => condOptions.find(x => x.value === c)?.label || c || '' + +const onTypeChange = (rule) => { + const d = typeDefaults[rule.type] + if (d) { rule.metric = d.metric; rule.condition = d.condition; rule.unit = d.unit } + sync() } // ============ 预设规则模板 ============ @@ -255,6 +257,11 @@ const parsed = computed({ set(v) { editorJson.value = JSON.stringify(v, null, 2) } }) +const editSiteName = computed(() => { + if (!editType.value) return '' + const site = (sites.value||[]).find(s => s.siteType === editType.value) + return site ? (site.names||[]).join('/') || site.siteId || editType.value : editType.value +}) 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, @@ -289,8 +296,9 @@ const editRule = async (row) => { const sync = () => { editorJson.value = JSON.stringify(parsed.value, null, 2) } const addRule = () => { + const d = typeDefaults['KILL'] parsed.value = [...parsed.value, { - type:'KILL', name:'', metric:'days_since_last_login', threshold:0, unit:'天', condition:'GT', + type:'KILL', metric:d.metric, threshold:0, unit:d.unit, condition:d.condition, applicable:null, description:'', _fold:false }] } @@ -361,11 +369,11 @@ onMounted(fetchAll) .drag-handle:active { cursor: grabbing; } .rule-index { font-size: 11px; color: #c0c4cc; font-weight: 500; min-width: 24px; text-align: right; } -.card-body { padding: 4px 12px 10px 34px; display: flex; flex-direction: column; gap: 6px; } +.card-body { padding: 6px 12px 10px 12px; display: flex; flex-direction: column; gap: 6px; } +.rule-fixed-text { font-size: 13px; color: #303133; } .field-row { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; font-size: 13px; } .field-label { font-weight: 500; color: #606266; font-size: 12px; min-width: 56px; } -.field-hint { color: #909399; font-size: 11px; } -.condition-text { color: #909399; font-size: 12px; } -.then-arrow { color: #f56c6c; font-size: 16px; font-weight: 700; margin: 0 2px; } +.field-hint { color: #909399; font-size: 12px; } +.then-arrow { color: #f56c6c; font-size: 14px; font-weight: 700; margin: 0 2px; }