Fix official news retries, date boundaries and collection status
Development CI / check-and-build (push) Successful in 3m2s
GitHub Git mirror / mirror (push) Successful in 6s
Development CI / deploy-development (push) Successful in 2m31s

Bound document retries across realtime and history lanes, preserve safe completed reads on failed rounds, and retain unresolved gaps. Honor the longest access-block cooldown and measure retries from the actual failure time.

Filter dated official listings at the collection boundary, handle empty Federal Register days, and distinguish active rounds from waiting or failed processes in the console. Add captured-response regressions and isolated checkpoint validation.
This commit is contained in:
eezd committed 2026-11-05 11:22:46 +08:00
1 parent 80665905e5
commit 39675fe46b
11 files changed
+577 -39

No files matched your search

@@ -7,6 +7,7 @@ import { useSessionScope } from "@@/composables/useSessionScope"
import { formatTime } from "@@/utils/text"
import { CircleCheck, RefreshRight } from "@element-plus/icons-vue"
import dayjs from "dayjs"
import { sourceStatus } from "../sourceStatus"
/** logs 只用来发现「本轮完成」以刷新最新入库;alert 为连续失败达到告警阈值 */
const props = defineProps<{
@@ -87,22 +88,7 @@ async function cancelHistory() {
emit("changed")
}
const statusTag = computed(() => {
if (props.source.configuration_error)
return { type: "warning", text: props.source.configuration_error } as const
const process = props.source.process
if (props.restarting || process?.state === "restarting")
return { type: "warning", text: "重启中" } as const
if (!process)
return { type: "danger", text: "管理进程未运行" } as const
if (process.state === "stopped")
return { type: "danger", text: "子进程未运行" } as const
if (!props.source.enabled)
return { type: "info", text: "已停用" } as const
if (props.source.paused_until && new Date(props.source.paused_until) > new Date())
return { type: "warning", text: "失败退避中" } as const
return { type: "success", text: "运行中" } as const
})
const statusTag = computed(() => sourceStatus(props.source, props.restarting))
onMounted(loadLatest)
</script>
@@ -163,6 +149,9 @@ onMounted(loadLatest)
<div v-if="source.collection_stats?.attachment_gaps" class="text-xs text-amber-600">
附件待核验文档 {{ source.collection_stats.attachment_gaps }};待重试 {{ source.collection_stats.attachment_retry_pending }};重试已耗尽 {{ source.collection_stats.attachment_retry_exhausted }},请核对原文
</div>
<div v-if="source.collection_stats?.document_gaps" class="text-xs text-amber-600">
正文待核验 {{ source.collection_stats.document_gaps }};待重试 {{ source.collection_stats.document_retry_pending }};重试已耗尽 {{ source.collection_stats.document_retry_exhausted }},请核对来源日志
</div>
<div v-if="source.collection_stats?.discovered" class="text-xs text-slate-500">
本轮发现 {{ source.collection_stats.discovered }};筛除 {{ source.collection_stats.excluded ?? 0 }};不完整包 {{ source.collection_stats.partial ?? 0 }}
</div>
+5 -4
View File
@@ -1,5 +1,5 @@
<script lang="ts" setup>
import type { SourcesInfo } from "@@/apis/crawler/type"
import type { SourceInfo, SourcesInfo } from "@@/apis/crawler/type"
import { createRssApi, listSourcesApi, restartCrawlerApi } from "@@/apis/crawler"
import { useSessionScope } from "@@/composables/useSessionScope"
import { formatTime } from "@@/utils/text"
@@ -8,6 +8,7 @@ import { logRequestError } from "@/http/axios"
import CalendarSourcePanel from "./components/CalendarSourcePanel.vue"
import SourcePanel from "./components/SourcePanel.vue"
import { useCrawlerLogs } from "./composables/useCrawlerLogs"
import { sourceStatus } from "./sourceStatus"
const rssVisible = ref(false)
const rssSaving = ref(false)
@@ -178,10 +179,10 @@ onMounted(async () => {
{{ regions[row.region_code as keyof typeof regions] ?? row.region_code }}
</template>
</el-table-column>
<el-table-column label="状态" width="110">
<el-table-column label="状态" min-width="130">
<template #default="{ row }">
<el-tag size="small" :type="row.enabled && row.process?.state === 'running' ? 'success' : 'info'">
{{ !row.enabled ? '已停用' : row.process?.state === 'running' ? '运行中' : '未运行' }}
<el-tag size="small" :type="sourceStatus(row as SourceInfo, restarting.has(row.code)).type">
{{ sourceStatus(row as SourceInfo, restarting.has(row.code)).text }}
</el-tag>
</template>
</el-table-column>
+21
View File
@@ -0,0 +1,21 @@
import type { SourceInfo } from "@@/apis/crawler/type"
export function sourceStatus(source: SourceInfo, restarting = false, now = Date.now()) {
if (source.configuration_error)
return { type: "warning", text: source.configuration_error } as const
if (!source.enabled)
return { type: "info", text: "已停用" } as const
if (restarting || source.process?.state === "restarting")
return { type: "warning", text: "重启中" } as const
if (!source.process || source.process.state === "stopped")
return { type: "danger", text: "采集进程未运行" } as const
if (source.paused_until && new Date(source.paused_until).getTime() > now)
return { type: "warning", text: "失败退避中" } as const
if (source.collection_stats?.round_running)
return { type: "primary", text: "采集中" } as const
if (source.consecutive_failures)
return { type: "danger", text: "失败待重试" } as const
if (source.collection_stats?.document_gaps)
return { type: "warning", text: "存在文档缺口" } as const
return { type: "info", text: "等待调度" } as const
}