This commit is contained in:
Your Name
2026-04-17 16:17:19 +08:00
parent 0e096947fc
commit bd6bcb240f
17 changed files with 863 additions and 23 deletions

View File

@@ -24,8 +24,8 @@
<span class="status-pill" :class="runtime.apiOnline ? 'online' : 'offline'">
API {{ runtime.apiOnline ? "在线" : "离线" }}
</span>
<span class="status-pill" :class="runtime.localWorkerOnline ? 'online' : 'offline'">
本机 Worker {{ runtime.localWorkerOnline ? "在线" : "离线" }}
<span class="status-pill" :class="runtime.localWorkerExpected ? (runtime.localWorkerOnline ? 'online' : 'offline') : 'neutral'">
本机 Worker {{ runtime.localWorkerExpected ? (runtime.localWorkerOnline ? "在线" : "离线") : "不承载" }}
</span>
<span class="status-pill" :class="runtime.effectiveWorkerNodes > 0 ? 'online' : 'offline'">
有效执行节点 {{ runtime.effectiveWorkerNodes }}
@@ -57,6 +57,7 @@ const authStore = useAuthStore();
const runtime = ref({
apiOnline: false,
localWorkerOnline: false,
localWorkerExpected: true,
effectiveWorkerNodes: 0,
workerMode: "windows-local"
});
@@ -85,6 +86,7 @@ const loadRuntimeSummary = async () => {
runtime.value = {
apiOnline: Boolean(response.data?.api?.pid),
localWorkerOnline: Boolean(response.data?.worker?.running),
localWorkerExpected: Boolean(response.data?.worker?.expected_on_this_node ?? true),
effectiveWorkerNodes: Number(summary.online_worker_nodes || 0),
workerMode: response.data?.worker?.mode || "windows-local"
};
@@ -92,6 +94,7 @@ const loadRuntimeSummary = async () => {
runtime.value = {
apiOnline: false,
localWorkerOnline: false,
localWorkerExpected: true,
effectiveWorkerNodes: 0,
workerMode: "unknown"
};

View File

@@ -80,12 +80,20 @@ const loadOverview = async (showError = true) => {
loading.value = true;
try {
const { data } = await dashboardApi.overview();
const localWorkerValue =
data.local_worker_status === "not-applicable"
? "不承载"
: data.local_worker_status || data.worker_status;
const localWorkerNote =
data.local_worker_status === "not-applicable"
? `当前节点 ${data.node_region || "-"} / ${data.node_role || "-"},默认不承载本机 Worker`
: "当前节点本机 Worker 运行状态";
stats.value = [
{ label: "总域名", value: String(data.domains_total), note: "数据库域名总量" },
{ label: "待检测", value: String(data.pending_total), note: "当前待处理域名" },
{ label: "黑名单", value: String(data.blacklist_total), note: "命中风险域名" },
{ label: "API", value: data.api_status, note: "当前 API 运行状态" },
{ label: "本机 Worker", value: data.local_worker_status || data.worker_status, note: "当前节点本机 Worker 运行状态" },
{ label: "本机 Worker", value: localWorkerValue, note: localWorkerNote },
{
label: "有效执行节点",
value: `${data.cluster_worker_status || "offline"} / ${data.cluster_online_worker_nodes || 0}`,

View File

@@ -24,7 +24,9 @@
<div class="summary-card">
<div class="summary-title">本机 Worker</div>
<div class="summary-value">{{ runtime.worker?.service_name || "-" }}</div>
<el-tag :type="runtime.worker?.running ? 'success' : 'danger'">{{ runtime.worker?.running ? "本机在线" : "本机离线" }}</el-tag>
<el-tag :type="localWorkerTagType">
{{ localWorkerSummaryText }}
</el-tag>
</div>
<div class="summary-card">
<div class="summary-title">运行模式</div>
@@ -118,8 +120,8 @@
<span class="status-chip" :class="runtime.api?.pid ? 'ok' : 'neutral'">
API {{ runtime.api?.pid ? "运行中" : "未知" }}
</span>
<span class="status-chip" :class="runtime.worker?.running ? 'ok' : 'danger'">
本机 Worker {{ runtime.worker?.running ? "在线" : "离线" }}
<span class="status-chip" :class="localWorkerChipClass">
本机 Worker {{ localWorkerStripText }}
</span>
<span class="status-chip" :class="(runtime.cluster?.summary?.online_worker_nodes || 0) > 0 ? 'ok' : 'danger'">
有效执行节点 {{ runtime.cluster?.summary?.online_worker_nodes || 0 }}
@@ -151,10 +153,10 @@
<el-descriptions-item label="API PID">{{ runtime.api?.pid || "-" }}</el-descriptions-item>
<el-descriptions-item label="API 地址">{{ runtime.api?.health_url || "-" }}</el-descriptions-item>
<el-descriptions-item label="Worker 服务">{{ runtime.worker?.service_name || "-" }}</el-descriptions-item>
<el-descriptions-item label="Worker 在线">{{ runtime.worker?.running ? "是" : "否" }}</el-descriptions-item>
<el-descriptions-item label="Worker 在线">{{ localWorkerBooleanText }}</el-descriptions-item>
<el-descriptions-item label="运行模式">{{ runtime.worker?.mode || "-" }}</el-descriptions-item>
<el-descriptions-item label="进程数">{{ runtime.worker?.process_count ?? "-" }}</el-descriptions-item>
<el-descriptions-item label="运行消息">{{ runtime.worker?.message || "-" }}</el-descriptions-item>
<el-descriptions-item label="运行消息">{{ localWorkerMessage }}</el-descriptions-item>
<el-descriptions-item label="Sync Agent 服务">{{ runtime.sync_agent?.service_name || "-" }}</el-descriptions-item>
<el-descriptions-item label="Sync Agent 在线">{{ runtime.sync_agent?.running ? "是" : "否" }}</el-descriptions-item>
<el-descriptions-item label="Sync Agent 启动时间">{{ runtime.sync_agent?.latest_start_time || "-" }}</el-descriptions-item>
@@ -166,8 +168,21 @@
<div class="action-panel">
<h3>运行时动作</h3>
<div class="action-buttons">
<el-button type="primary" :loading="actionLoading === 'start_worker'" @click="invokeAction('start_worker')">启动 Worker</el-button>
<el-button :loading="actionLoading === 'stop_worker'" @click="invokeAction('stop_worker')">停止 Worker</el-button>
<el-button
v-if="runtime.worker?.expected_on_this_node"
type="primary"
:loading="actionLoading === 'start_worker'"
@click="invokeAction('start_worker')"
>
启动 Worker
</el-button>
<el-button
v-if="runtime.worker?.expected_on_this_node"
:loading="actionLoading === 'stop_worker'"
@click="invokeAction('stop_worker')"
>
停止 Worker
</el-button>
<el-button type="warning" plain :loading="actionLoading === 'restart_api'" @click="invokeAction('restart_api')">重启 API</el-button>
<el-button
v-if="runtime.sync_agent?.expected_on_this_node"
@@ -201,7 +216,15 @@
show-icon
type="info"
style="margin-top: 12px"
:title="`当前本机 Worker${runtime.worker?.running ? '运行中' : '未运行'};有效执行节点:${runtime.cluster?.summary?.online_worker_nodes || 0};独立 Worker${runtime.cluster?.summary?.dedicated_online_worker_nodes || 0};当前 API 状态:${runtime.api?.pid ? '运行中' : '未知'}Sync Agent${runtime.sync_agent?.running ? '运行中' : '未运行'}。`"
:title="`当前本机 Worker${localWorkerActionText};有效执行节点:${runtime.cluster?.summary?.online_worker_nodes || 0};独立 Worker${runtime.cluster?.summary?.dedicated_online_worker_nodes || 0};当前 API 状态:${runtime.api?.pid ? '运行中' : '未知'}Sync Agent${runtime.sync_agent?.running ? '运行中' : runtime.sync_agent?.expected_on_this_node ? '未运行' : '当前节点不承载'}。`"
/>
<el-alert
v-if="!runtime.worker?.expected_on_this_node"
:closable="false"
show-icon
type="info"
style="margin-top: 12px"
:title="`当前节点身份为 ${runtime.node?.region || '-'} / ${runtime.node?.role || '-'},按当前部署角色默认不承载本机 Worker检测执行应由大陆 controller / worker 节点承担。`"
/>
<el-alert
v-if="!runtime.sync_agent?.expected_on_this_node"
@@ -800,6 +823,45 @@ const proxyDiagnosisText = () => {
return runtime.detect?.proxy_runtime_detail || "当前暂无代理运行说明";
};
const localWorkerExpected = computed(() => Boolean(runtime.worker?.expected_on_this_node ?? true));
const localWorkerSummaryText = computed(() => {
if (!localWorkerExpected.value) return "当前节点不承载";
return runtime.worker?.running ? "本机在线" : "本机离线";
});
const localWorkerStripText = computed(() => {
if (!localWorkerExpected.value) return "不承载";
return runtime.worker?.running ? "在线" : "离线";
});
const localWorkerBooleanText = computed(() => {
if (!localWorkerExpected.value) return "当前节点不承载";
return runtime.worker?.running ? "是" : "否";
});
const localWorkerMessage = computed(() => {
if (!localWorkerExpected.value) {
return `当前节点 ${runtime.node?.region || "-"} / ${runtime.node?.role || "-"},默认不承载本机 Worker`;
}
return runtime.worker?.message || "-";
});
const localWorkerActionText = computed(() => {
if (!localWorkerExpected.value) return "当前节点不承载";
return runtime.worker?.running ? "运行中" : "未运行";
});
const localWorkerTagType = computed(() => {
if (!localWorkerExpected.value) return "info";
return runtime.worker?.running ? "success" : "danger";
});
const localWorkerChipClass = computed(() => {
if (!localWorkerExpected.value) return "neutral";
return runtime.worker?.running ? "ok" : "danger";
});
const clusterIssueCount = computed(() => {
const summary = runtime.cluster?.summary || {};
return Number(summary.status_counts?.stale || 0) + Number(summary.status_counts?.offline || 0);