refactor(publish): collapse pending_review/unknown task states into failed

Treat ambiguous terminal states as failures end-to-end: server
normalizes unknown desktop task completions and views to failed, drops
the pending_review aggregate branch, and remaps pending_review to
failed in publish record conversion. admin-web removes the
pending_review status option from article list filters, pushes
pending_review through the failed tone, and folds lingering
publishing/pending entries under the publishing bucket. desktop-client
relabels unknown as 发送失败 in PublishManagement/TasksView, rewrites
the scaffold adapter result to a proper failed error envelope, and
sanitises legacy scaffold-only error messages to a user-friendly note.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-20 11:44:47 +08:00
parent 4014eff427
commit dc68ad044c
11 changed files with 62 additions and 45 deletions
@@ -19,7 +19,7 @@ interface PublishPlatformEntry {
status: PublishRecordStatus;
}
type PublishRecordStatus = "success" | "failed" | "publishing" | "pending_review";
type PublishRecordStatus = "success" | "failed" | "publishing";
interface PublishPlatformSection {
key: PublishRecordStatus;
@@ -104,7 +104,7 @@ const failedEntries = computed(() =>
);
const pendingEntries = computed(() =>
platformEntries.value.filter((entry) => entry.status === "publishing" || entry.status === "pending_review"),
platformEntries.value.filter((entry) => entry.status === "publishing"),
);
const displayStatus = computed(() => {
@@ -121,7 +121,7 @@ const displayStatus = computed(() => {
}
if (pendingEntries.value.length > 0) {
return "pending_review";
return "publishing";
}
if (props.status === "partial_success") {
@@ -136,6 +136,10 @@ const displayStatus = computed(() => {
return "failed";
}
if (props.status === "pending_review") {
return "failed";
}
return props.status ?? null;
});
@@ -149,8 +153,6 @@ const statusTone = computed(() => {
return "failed";
case "publishing":
return "processing";
case "pending_review":
return "warning";
default:
return "default";
}
@@ -178,13 +180,9 @@ const popoverSections = computed<PublishPlatformSection[]>(() => {
}
if (pendingEntries.value.length > 0) {
const pendingStatus = pendingEntries.value.some((entry) => entry.status === "publishing")
? "publishing"
: "pending_review";
sections.push({
key: pendingStatus,
label: `${getPublishStatusMeta(pendingStatus).label}`,
key: "publishing",
label: `${getPublishStatusMeta("publishing").label}`,
tone: "pending",
entries: pendingEntries.value,
});
@@ -208,7 +206,7 @@ function normalizePublishRecordStatus(status?: string | null): PublishRecordStat
case "queued":
return "publishing";
case "pending_review":
return "pending_review";
return "failed";
case "failed":
case "publish_failed":
default:
@@ -77,7 +77,6 @@ const publishStatusOptions = computed(() => [
{ label: getPublishStatusMeta("success").label, value: "success" },
{ label: getPublishStatusMeta("partial_success").label, value: "partial_success" },
{ label: getPublishStatusMeta("failed").label, value: "failed" },
{ label: getPublishStatusMeta("pending_review").label, value: "pending_review" },
]);
const articleParams = computed<ArticleListParams>(() => {