feat(web): simplify subscription and manual download flows and sync UHD styles

This commit is contained in:
root committed 2026-10-13 14:37:03 +08:00
1 parent 27c0f27434
commit c3c4456913
33 files changed
+1083 -633

No files matched your search

+25 -8
View File
@@ -1,4 +1,4 @@
import { useQuery } from "@tanstack/react-query";
import { useQuery, useQueryClient } from "@tanstack/react-query";
import {
type AcquisitionPlan,
cursorPage,
@@ -10,9 +10,12 @@ import {
type TaskKind,
type TaskStatus,
} from "@umt/contracts";
import { recordPath, taskPath } from "~/components/console/record-sheet.tsx";
import { consolePath } from "~/components/console/nav.ts";
import { recordPath, subjectLink, taskPath } from "~/components/console/record-sheet.tsx";
import { DECISION_STATUS } from "~/components/library/labels.ts";
import { organizationActionLabel, organizationLabel } from "~/lib/labels.ts";
import { humanizeReason, reasonLine } from "~/lib/reasons.ts";
import { useSse } from "~/lib/sse.ts";
import { PAUSE_REASON_LABEL, PLAN_STATUS_LABEL } from "./downloads.ts";
import { apiParsed } from "./parse.ts";
@@ -60,6 +63,14 @@ export function useSourceRelease(id: string | null | undefined) {
/** 与该下载有关的待处理事项(subject = 下载任务或计划),含 Agent 调查 run */
export function useSubjectDecisions(subjectIds: string[]) {
const ids = subjectIds.filter(Boolean);
const qc = useQueryClient();
useSse(
["decision.created", "decision.updated"],
() => {
void qc.invalidateQueries({ queryKey: ["decisions", "subjects", ids] });
},
ids.length > 0,
);
return useQuery({
queryKey: ["decisions", "subjects", ids],
enabled: ids.length > 0,
@@ -256,23 +267,29 @@ export function buildTimeline(input: {
});
}
for (const d of decisions) {
const state = DECISION_STATUS[d.status];
const needsUser = d.status === "open" || d.status === "awaiting_user";
const recovery = d.evidence.autoRecover as { suggestion?: unknown } | undefined;
const suggestion =
d.status === "awaiting_user" && typeof recovery?.suggestion === "string" ? recovery.suggestion : null;
ev.push({
key: `dec-${d.id}`,
stage: "agent",
at: d.createdAt,
title: `需要处理:${d.title}`,
detail: d.summary,
tone: d.severity === "critical" ? "destructive" : "warning",
href: "/console/inbox",
title: `${state.label}:${d.title}`,
detail: suggestion ?? d.summary,
tone: needsUser && d.severity === "critical" ? "destructive" : state.tone,
href: subjectLink(d) ?? (d.agentRunId ? consolePath("agent", d.agentRunId) : consolePath("agent")),
ongoing: d.status === "investigating",
});
if (d.agentRunId)
ev.push({
key: `agent-${d.id}`,
stage: "agent",
at: d.updatedAt,
title: "智能体已介入调查",
title: "智能体调查记录",
tone: "neutral",
href: `/console/agent/${d.agentRunId}`,
href: consolePath("agent", d.agentRunId),
});
}
for (const t of tasks) {