feat(api): 新增节点墙检测自动托管与显隐
新增定时墙检测命令与节点托管字段,自动为开启托管的父 节点创建检测任务,并在 blocked 时自动隐藏节点、normal 时仅恢复由墙检测自动隐藏的节点 更新自动上线服务以尊重 blocked 与自动隐藏状态,避免疑 似被墙节点被重新发布;同时补齐管理端墙检测托管开关、 刷新入口、批量设置与相关测试和知识库同步
This commit is contained in:
@@ -35,6 +35,7 @@ import NodeEditorDialog from './NodeEditorDialog.vue'
|
||||
import NodeSortDialog from './NodeSortDialog.vue'
|
||||
import {
|
||||
buildNodeTypeOptions,
|
||||
countAutoGfwCheckNodes,
|
||||
countAutoOnlineNodes,
|
||||
countOnlineNodes,
|
||||
countVisibleNodes,
|
||||
@@ -77,6 +78,7 @@ const selectedNodeIds = ref<number[]>([])
|
||||
const syncingSelection = ref(false)
|
||||
const switchingIds = ref<number[]>([])
|
||||
const autoSwitchingIds = ref<number[]>([])
|
||||
const gfwSwitchingIds = ref<number[]>([])
|
||||
const workingIds = ref<number[]>([])
|
||||
const editorVisible = ref(false)
|
||||
const editorMode = ref<NodeDialogMode>('create')
|
||||
@@ -119,6 +121,7 @@ const summaryCards = computed(() => [
|
||||
{ label: '在线节点', value: String(countOnlineNodes(nodes.value)) },
|
||||
{ label: '显示中', value: String(countVisibleNodes(nodes.value)) },
|
||||
{ label: '自动上线', value: String(countAutoOnlineNodes(nodes.value)) },
|
||||
{ label: '自动墙检', value: String(countAutoGfwCheckNodes(nodes.value)) },
|
||||
{ label: '已勾选', value: String(selectedNodes.value.length) },
|
||||
])
|
||||
|
||||
@@ -166,6 +169,10 @@ function isAutoSwitching(id: number): boolean {
|
||||
return autoSwitchingIds.value.includes(id)
|
||||
}
|
||||
|
||||
function isGfwSwitching(id: number): boolean {
|
||||
return gfwSwitchingIds.value.includes(id)
|
||||
}
|
||||
|
||||
function isWorking(id: number): boolean {
|
||||
return workingIds.value.includes(id)
|
||||
}
|
||||
@@ -293,6 +300,7 @@ async function handleBatchSubmit(payload: NodeBatchEditPayload) {
|
||||
rate: payload.rate,
|
||||
group_ids: payload.group_ids,
|
||||
auto_online: payload.auto_online,
|
||||
gfw_check_enabled: payload.gfw_check_enabled,
|
||||
}
|
||||
|
||||
try {
|
||||
@@ -453,6 +461,29 @@ async function handleToggleAutoOnline(node: AdminNodeItem, nextValue: boolean) {
|
||||
}
|
||||
}
|
||||
|
||||
async function handleToggleGfwCheck(node: AdminNodeItem, nextValue: boolean) {
|
||||
const previous = node.gfw_check_enabled !== false
|
||||
if (previous === nextValue) {
|
||||
return
|
||||
}
|
||||
|
||||
node.gfw_check_enabled = nextValue
|
||||
markPending(gfwSwitchingIds, node.id, true)
|
||||
|
||||
try {
|
||||
await updateNode({
|
||||
id: node.id,
|
||||
gfw_check_enabled: nextValue,
|
||||
})
|
||||
ElMessage.success(nextValue ? '已开启墙检测托管' : '已关闭墙检测托管')
|
||||
} catch (error) {
|
||||
node.gfw_check_enabled = previous
|
||||
ElMessage.error(error instanceof Error ? error.message : '墙检测托管状态更新失败')
|
||||
} finally {
|
||||
markPending(gfwSwitchingIds, node.id, false)
|
||||
}
|
||||
}
|
||||
|
||||
async function handlePinTop(node: AdminNodeItem) {
|
||||
const orderedNodes = sortNodesByOrder(nodes.value)
|
||||
if (orderedNodes[0]?.id === node.id) {
|
||||
@@ -652,6 +683,13 @@ watch(
|
||||
<ElIcon><Connection /></ElIcon>
|
||||
检测墙状态
|
||||
</ElButton>
|
||||
<ElButton
|
||||
:loading="loading"
|
||||
@click="loadNodeBoard"
|
||||
>
|
||||
<ElIcon><RefreshRight /></ElIcon>
|
||||
刷新数据
|
||||
</ElButton>
|
||||
<ElButton
|
||||
type="danger"
|
||||
plain
|
||||
@@ -720,13 +758,30 @@ watch(
|
||||
<ElSwitch
|
||||
:model-value="Boolean(row.show)"
|
||||
:loading="isSwitching(row.id)"
|
||||
:disabled="Boolean(row.auto_online)"
|
||||
:disabled="Boolean(row.auto_online) || (Boolean(row.gfw_auto_hidden) && row.gfw_check_enabled !== false)"
|
||||
@change="(value) => handleToggleShow(row, Boolean(value))"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
</ElTableColumn>
|
||||
|
||||
<ElTableColumn label="墙检测" width="118">
|
||||
<template #default="{ row }">
|
||||
<ElTooltip
|
||||
:content="row.parent_id ? '子节点不单独检测;此开关只控制是否随父节点自动隐藏或恢复。' : '关闭后不参与自动墙检测和墙状态自动显隐。'"
|
||||
placement="top"
|
||||
>
|
||||
<div class="switch-shell switch-shell--gfw">
|
||||
<ElSwitch
|
||||
:model-value="row.gfw_check_enabled !== false"
|
||||
:loading="isGfwSwitching(row.id)"
|
||||
@change="(value) => handleToggleGfwCheck(row, Boolean(value))"
|
||||
/>
|
||||
</div>
|
||||
</ElTooltip>
|
||||
</template>
|
||||
</ElTableColumn>
|
||||
|
||||
<ElTableColumn label="自动上线" width="118">
|
||||
<template #default="{ row }">
|
||||
<div class="switch-shell switch-shell--auto">
|
||||
@@ -759,6 +814,24 @@ watch(
|
||||
>
|
||||
自动上线
|
||||
</ElTag>
|
||||
<ElTag
|
||||
v-if="row.gfw_check_enabled !== false"
|
||||
round
|
||||
effect="plain"
|
||||
type="primary"
|
||||
class="auto-online-tag"
|
||||
>
|
||||
墙检测
|
||||
</ElTag>
|
||||
<ElTag
|
||||
v-if="row.gfw_auto_hidden"
|
||||
round
|
||||
effect="plain"
|
||||
type="danger"
|
||||
class="auto-online-tag"
|
||||
>
|
||||
自动隐藏
|
||||
</ElTag>
|
||||
<ElTooltip :content="getNodeGfwTooltip(row)" placement="top">
|
||||
<ElTag
|
||||
round
|
||||
@@ -1048,6 +1121,10 @@ watch(
|
||||
--el-switch-on-color: #0071e3;
|
||||
}
|
||||
|
||||
.switch-shell--gfw :deep(.el-switch) {
|
||||
--el-switch-on-color: #34c759;
|
||||
}
|
||||
|
||||
.node-cell,
|
||||
.stack-cell,
|
||||
.online-cell {
|
||||
|
||||
Reference in New Issue
Block a user