feat: add metadata console and seo ai rule pages
This commit is contained in:
@@ -1,5 +1,60 @@
|
||||
<template>
|
||||
<div class="home card">
|
||||
<el-card shadow="never" class="home-metadata-console">
|
||||
<template #header>
|
||||
<div class="home-metadata-console__header">
|
||||
<div>
|
||||
<div class="home-metadata-console__title">视频缺字段控制台</div>
|
||||
<div class="home-metadata-console__subtitle">后台打开先看这里,工作台、任务池和计划任务状态都汇总到首屏。</div>
|
||||
</div>
|
||||
<div class="home-metadata-console__actions">
|
||||
<el-button :loading="metadataLoading" @click="loadMetadataConsole">刷新状态</el-button>
|
||||
<el-button type="primary" :loading="workbenchRunning" @click="handleRunWorkbench">刷新工作台</el-button>
|
||||
<el-button type="warning" plain :loading="taskPoolRunning" @click="handleRunTaskPool">刷新任务池</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<el-alert
|
||||
:type="metadataAlertType"
|
||||
:closable="false"
|
||||
show-icon
|
||||
:title="metadataAlertTitle"
|
||||
:description="metadataAlertDescription"
|
||||
/>
|
||||
|
||||
<div class="home-metadata-console__stats">
|
||||
<div class="home-metadata-stat">
|
||||
<div class="home-metadata-stat__label">缺字段视频总量</div>
|
||||
<div class="home-metadata-stat__value">{{ metadataSummary.workbench?.videos_with_any_missing_metadata || 0 }}</div>
|
||||
<div class="home-metadata-stat__tip">越大越需要先看工作台,再按批次派给 Codex。</div>
|
||||
</div>
|
||||
<div class="home-metadata-stat">
|
||||
<div class="home-metadata-stat__label">重采优先队列</div>
|
||||
<div class="home-metadata-stat__value">{{ metadataSummary.workbench?.queue_size || 0 }}</div>
|
||||
<div class="home-metadata-stat__tip">这是最适合优先处理的一批,适合先做首轮修复。</div>
|
||||
</div>
|
||||
<div class="home-metadata-stat">
|
||||
<div class="home-metadata-stat__label">任务池批次数</div>
|
||||
<div class="home-metadata-stat__value">{{ metadataSummary.task_pool?.batch_count || 0 }}</div>
|
||||
<div class="home-metadata-stat__tip">批次越清晰,后续技术和 Codex 的协作越顺。</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="home-metadata-console__hint">
|
||||
<strong>当前建议:</strong>{{ metadataSummary.recommended_action || "先刷新状态,再看工作台和任务池。" }}
|
||||
<br />
|
||||
<strong>首条提示:</strong>{{ metadataFirstHint }}
|
||||
</div>
|
||||
|
||||
<div class="home-metadata-console__links">
|
||||
<el-button text type="primary" @click="openMetadataRoute('/video/metadata/missing/task-pool/status')">打开状态总览</el-button>
|
||||
<el-button text type="primary" @click="openMetadataRoute('/video/metadata/missing/task-pool/ops')">打开运维总览</el-button>
|
||||
<el-button text type="primary" @click="openMetadataRoute('/video/metadata/missing/task-pool')">打开任务池</el-button>
|
||||
<el-button text type="primary" @click="openMetadataRoute('/video/metadata/missing/workbench')">打开工作台</el-button>
|
||||
</div>
|
||||
</el-card>
|
||||
|
||||
<div class="home-bootstrap-actions">
|
||||
<el-button type="primary" @click="openBootstrapCenter('overview')">打开 Bootstrap 总控台</el-button>
|
||||
<el-button type="warning" plain @click="openBootstrapCenter({ tab: 'ops', opsFocus: { panel: 'oncall', stage: 'all', clearHostFocus: true, hostConsolePanel: 'oncall' } })">值班待办</el-button>
|
||||
@@ -13,14 +68,25 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts" name="home">
|
||||
import { computed, onMounted, ref } from "vue";
|
||||
import { useRouter } from "vue-router";
|
||||
import { ElMessage } from "element-plus";
|
||||
import BootstrapOpsOverview from "@/views/site/bootstrapOpsOverview.vue";
|
||||
import BootstrapEnvOverview from "@/views/site/bootstrapEnvOverview.vue";
|
||||
import BootstrapAdminCenter from "@/views/site/bootstrapAdminCenter.vue";
|
||||
import { ref } from "vue";
|
||||
import {
|
||||
getMetadataMissingTaskPoolStatus,
|
||||
runMetadataMissingTaskPool,
|
||||
runMetadataMissingWorkbench
|
||||
} from "@/api/modules/video/list";
|
||||
import type { VideoList } from "@/api/interface/video/list";
|
||||
|
||||
const router = useRouter();
|
||||
const bootstrapAdminCenterRef = ref<InstanceType<typeof BootstrapAdminCenter> | null>(null);
|
||||
const metadataLoading = ref(false);
|
||||
const workbenchRunning = ref(false);
|
||||
const taskPoolRunning = ref(false);
|
||||
const metadataSummary = ref<VideoList.MetadataMissingTaskPoolStatusData>({});
|
||||
type BootstrapFocusMode = "all" | "task" | "oncall" | "pipeline" | "import" | "release";
|
||||
type BootstrapFocusPayload = BootstrapFocusMode | BootstrapFocusMode[];
|
||||
type BootstrapComparePreset =
|
||||
@@ -77,6 +143,69 @@ const openBootstrapCenter = (payload: BootstrapAdminOpenPayload = "overview") =>
|
||||
bootstrapAdminCenterRef.value?.openDialog(payload);
|
||||
};
|
||||
|
||||
const loadMetadataConsole = async () => {
|
||||
metadataLoading.value = true;
|
||||
try {
|
||||
const response = await getMetadataMissingTaskPoolStatus();
|
||||
metadataSummary.value = response.data || {};
|
||||
} finally {
|
||||
metadataLoading.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
const handleRunWorkbench = async () => {
|
||||
workbenchRunning.value = true;
|
||||
try {
|
||||
const response = await runMetadataMissingWorkbench();
|
||||
ElMessage.success(response.msg || "工作台刷新已触发");
|
||||
await loadMetadataConsole();
|
||||
} finally {
|
||||
workbenchRunning.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
const handleRunTaskPool = async () => {
|
||||
taskPoolRunning.value = true;
|
||||
try {
|
||||
const response = await runMetadataMissingTaskPool();
|
||||
ElMessage.success(response.msg || "任务池刷新已触发");
|
||||
await loadMetadataConsole();
|
||||
} finally {
|
||||
taskPoolRunning.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
const openMetadataRoute = (path: string) => {
|
||||
router.push(path);
|
||||
};
|
||||
|
||||
const metadataFirstHint = computed(() => metadataSummary.value.operator_hint?.[0] || "当前还没有额外提示,建议先看状态总览。");
|
||||
|
||||
const metadataAlertType = computed(() => {
|
||||
const status = metadataSummary.value.plan_task?.status_label || "missing";
|
||||
if (status === "enabled") return "success";
|
||||
if (status === "disabled") return "warning";
|
||||
if (status === "db_blocked") return "error";
|
||||
return "info";
|
||||
});
|
||||
|
||||
const metadataAlertTitle = computed(() => {
|
||||
const status = metadataSummary.value.plan_task?.status_label || "missing";
|
||||
if (status === "enabled") return "视频缺字段计划任务已启用";
|
||||
if (status === "disabled") return "视频缺字段计划任务已存在但未启用";
|
||||
if (status === "db_blocked") return "当前环境暂时无法读取视频缺字段计划任务";
|
||||
return "视频缺字段计划任务尚未补齐";
|
||||
});
|
||||
|
||||
const metadataAlertDescription = computed(() => {
|
||||
const status = metadataSummary.value.plan_task?.status_label || "missing";
|
||||
const action = metadataSummary.value.recommended_action || "先刷新状态,再决定下一步。";
|
||||
if (status === "enabled") return `当前工作台和任务池已经可持续刷新。${action}`;
|
||||
if (status === "disabled") return `当前后台已经有这条计划任务,但还没有启用。${action}`;
|
||||
if (status === "db_blocked") return `这通常说明当前后台环境没读到完整数据库上下文。${action}`;
|
||||
return `当前还没补齐这条计划任务,建议先补齐再观察。${action}`;
|
||||
});
|
||||
|
||||
const goSitePage = (payload: BootstrapDialogPayload = "all") => {
|
||||
const normalizedFocus = typeof payload === "string" || Array.isArray(payload) ? payload : payload.focusMode ?? "all";
|
||||
const comparePreset = typeof payload === "string" || Array.isArray(payload) ? undefined : payload.comparePreset;
|
||||
@@ -93,6 +222,10 @@ const goSitePage = (payload: BootstrapDialogPayload = "all") => {
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
loadMetadataConsole();
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
|
||||
Reference in New Issue
Block a user