diff --git a/web/src/views/RiskRules.vue b/web/src/views/RiskRules.vue index 74cdf89..859e612 100644 --- a/web/src/views/RiskRules.vue +++ b/web/src/views/RiskRules.vue @@ -6,30 +6,36 @@ 刷新 - - + + + + + + - + - + - -
+
- 编辑: {{ editType }} + 编辑: {{ editSiteId }} ({{ editSiteType }}) + 修改会影响所有 {{ editSiteType }} 类型的站点 表格 JSON @@ -55,7 +61,7 @@
保存 - 取消 + 取消
@@ -66,8 +72,8 @@ import api from '../api' const loading = ref(false), saving = ref(false) -const siteTypes = ref([]), rulesData = ref([]) -const editType = ref(''), editorMode = ref('table'), editorJson = ref('') +const sites = ref([]), rulesMap = ref({}) +const editSiteId = ref(''), editSiteType = ref(''), editorMode = ref('table'), editorJson = ref('') const editingRules = ref([]) const fmt = (t) => t ? (t.substring(0,19)||'').replace('T',' ') : '-' @@ -78,44 +84,42 @@ watch(editorMode, (m) => { }) const merged = computed(() => { - const map = {} - const rules = Array.isArray(rulesData.value) ? rulesData.value : [] - for (const r of rules) { - const cnt = (() => { try { return JSON.parse(r.rulesJson||'[]').length } catch { return 0 } })() - map[r.siteType] = { siteType: r.siteType, version: r.version, ruleCount: cnt, updatedAt: r.updatedAt, rulesJson: r.rulesJson } - } - for (const t of siteTypes.value) { - if (!map[t]) map[t] = { siteType: t, version: null, ruleCount: 0, updatedAt: null, rulesJson: null } - } - return Object.values(map) + return (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, + updatedAt: rulesMap.value[s.siteType]?.updatedAt || null, + rulesJson: rulesMap.value[s.siteType]?.rulesJson || null, + })) }) const fetchAll = async () => { loading.value = true try { - // 站点类型 = 默认四种 + 实际站点数据中提取的去重 - const defaults = ['nexusphp','mtorrent','gazelle','unit3d'] - try { - const sr = await api.raw.get('/admin/sites') - const siteList = Array.isArray(sr?.data) ? sr.data : Array.isArray(sr) ? sr : [] - const dbTypes = siteList.map(s => s.siteType).filter(Boolean) - siteTypes.value = [...new Set([...defaults, ...dbTypes])] - } catch { - siteTypes.value = defaults + const [sr, rr] = await Promise.allSettled([ + api.raw.get('/admin/sites'), + api.raw.get('/admin/risk-rules'), + ]) + sites.value = sr.status==='fulfilled' ? (Array.isArray(sr.value?.data)?sr.value.data:sr.value||[]) : [] + const rulesData = rr.status==='fulfilled' ? (Array.isArray(rr.value?.data)?rr.value.data:rr.value||[]) : [] + const map = {} + for (const r of rulesData) { + const cnt = (() => { try { return JSON.parse(r.rulesJson||'[]').length } catch { return 0 } })() + map[r.siteType] = { ruleCount: cnt, version: r.version, updatedAt: r.updatedAt, rulesJson: r.rulesJson } } - - const rr = await api.raw.get('/admin/risk-rules').catch(() => ({})) - rulesData.value = Array.isArray(rr?.data) ? rr.data : Array.isArray(rr) ? rr : [] - } catch { ElMessage.error('加载失败') } - finally { loading.value = false } + rulesMap.value = map + } finally { loading.value = false } } -const toggleEdit = (row) => { - if (editType.value === row.siteType) { editType.value = ''; return } - editType.value = row.siteType +const startEdit = (row) => { + if (editSiteId.value === row.siteId) { editSiteId.value = ''; return } + editSiteId.value = row.siteId + editSiteType.value = row.siteType editorMode.value = 'table' try { editingRules.value = JSON.parse(JSON.stringify(JSON.parse(row.rulesJson||'[]'))) } - catch { editingRules.value = [{type:'KILL',name:'',metric:'',threshold:0,unit:'DAY',condition:'GT',level:'CRITICAL'}] } + catch { editingRules.value = [] } if (editingRules.value.length===0) editingRules.value.push({type:'KILL',name:'',metric:'',threshold:0,unit:'DAY',condition:'GT',level:'CRITICAL'}) } @@ -123,14 +127,11 @@ const saveRules = async () => { saving.value = true try { const rules = editorMode.value==='json' ? JSON.parse(editorJson.value) : editingRules.value - await api.raw.post('/risk-rules/'+editType.value, { rules }) - ElMessage.success('已保存'); editType.value = ''; fetchAll() + await api.raw.post('/risk-rules/'+editSiteType.value, { rules }) + ElMessage.success('已保存'); editSiteId.value = ''; fetchAll() } catch { ElMessage.error('保存失败') } finally { saving.value = false } } onMounted(fetchAll) - - -