Fix server file refresh pending state
This commit is contained in:
@@ -590,12 +590,15 @@ function ServerFilesSection({ instance, session, operations }: ServerFilesSectio
|
||||
}
|
||||
}, [instance.id]);
|
||||
|
||||
const loadList = useCallback(async () => {
|
||||
const loadList = useCallback(async (options: { silent?: boolean } = {}) => {
|
||||
if (!directoryKey) return;
|
||||
setList({ status: "loading" });
|
||||
if (!options.silent) setList({ status: "loading" });
|
||||
try {
|
||||
const response = await platformApiClient.listServerFiles(instance.id, { directoryKey, path: relativePath || undefined, query: searchQuery || undefined, recursive });
|
||||
setList({ status: "ready", data: response });
|
||||
if (options.silent && response.state === "ready") setPanelResult({ status: "succeeded", label: `目录已更新:${response.entries.length} 项` });
|
||||
if (options.silent && response.state === "pending") setPanelResult({ status: "pending", label: serverFileListPendingLabel(response) });
|
||||
if (options.silent && response.state === "failed") setPanelResult({ status: "failed", label: response.reason ?? "目录刷新失败" });
|
||||
} catch (error) {
|
||||
setList({ status: "error", reason: error instanceof Error ? error.message : "文件列表加载失败" });
|
||||
}
|
||||
@@ -613,7 +616,7 @@ function ServerFilesSection({ instance, session, operations }: ServerFilesSectio
|
||||
const response = await platformApiClient.refreshServerFiles(instance.id, { directoryKey, path: relativePath || undefined, query: searchQuery || undefined, recursive, idempotencyKey: serverFileIdempotency("list", instance.id, directoryKey) });
|
||||
setList({ status: "ready", data: response });
|
||||
if (operationId) operations.succeed(operationId, `目录刷新任务 ${response.job?.id ?? "已派发"}`, response.job);
|
||||
setPanelResult({ status: "pending", label: response.reason ?? "目录刷新任务已派发,稍后可再次刷新查看实时结果。" });
|
||||
setPanelResult({ status: serverFileListResultStatus(response), label: serverFileListResultLabel(response) });
|
||||
} catch (error) {
|
||||
const reason = error instanceof Error ? error.message : "目录刷新失败";
|
||||
if (operationId) operations.fail(operationId, reason, operationId);
|
||||
@@ -633,7 +636,7 @@ function ServerFilesSection({ instance, session, operations }: ServerFilesSectio
|
||||
|
||||
useEffect(() => {
|
||||
if (workspace.status !== "ready" || !directoryKey || list.status !== "ready" || list.data.state !== "pending") return;
|
||||
const timer = window.setInterval(() => void loadList(), 2000);
|
||||
const timer = window.setInterval(() => void loadList({ silent: true }), 2000);
|
||||
return () => window.clearInterval(timer);
|
||||
}, [directoryKey, list, loadList, workspace.status]);
|
||||
|
||||
@@ -794,7 +797,7 @@ function ServerFilesSection({ instance, session, operations }: ServerFilesSectio
|
||||
<table className="resource-table server-file-table">
|
||||
<thead><tr><th>文件名称</th><th>大小</th><th>修改时间</th><th>备注</th><th>操作</th></tr></thead>
|
||||
<tbody>
|
||||
{entries.length === 0 && <tr><td colSpan={5}><span className="provider-id">{list.data.state === "pending" ? "正在读取当前目录,Run 返回后会自动更新。" : "当前目录暂无文件。"}</span></td></tr>}
|
||||
{entries.length === 0 && <tr><td colSpan={5}><span className="provider-id">{serverFileListEmptyLabel(list.data)}</span></td></tr>}
|
||||
{entries.map((entry) => (
|
||||
<tr key={serverFileEntryRowKey(entry)} className={entry.kind === "directory" ? "server-file-directory-row" : undefined}>
|
||||
<td>
|
||||
@@ -851,6 +854,52 @@ function serverFileEntryRowKey(entry: ServerFileEntryResponse): string {
|
||||
return `${entry.kind}:${entry.directoryKey}:${entry.relativePath ?? ""}:${entry.logicalKey ?? ""}:${entry.name}`;
|
||||
}
|
||||
|
||||
function serverFileListResultStatus(response: ServerFileListResponse): "pending" | "succeeded" | "failed" {
|
||||
if (response.state === "ready") return "succeeded";
|
||||
if (response.state === "failed") return "failed";
|
||||
return "pending";
|
||||
}
|
||||
|
||||
function serverFileListResultLabel(response: ServerFileListResponse): string {
|
||||
if (response.state === "ready") return `目录已更新:${response.entries.length} 项`;
|
||||
if (response.state === "failed") return response.reason ?? "目录刷新失败";
|
||||
return serverFileListPendingLabel(response);
|
||||
}
|
||||
|
||||
function serverFileListEmptyLabel(response: ServerFileListResponse): string {
|
||||
if (response.state === "pending") return serverFileListPendingLabel(response);
|
||||
if (response.state === "failed") return response.reason ?? "目录刷新失败";
|
||||
return "当前目录暂无文件。";
|
||||
}
|
||||
|
||||
function serverFileListPendingLabel(response: ServerFileListResponse): string {
|
||||
const job = response.job;
|
||||
if (!job) return response.reason ?? "正在读取当前目录,Run 返回后会自动更新。";
|
||||
const progress = job.progress?.message?.trim();
|
||||
const attempt = job.attempt > 0 ? ` · 第 ${job.attempt} 次尝试` : "";
|
||||
const nextAttempt = job.state === "retrying" && job.nextAttemptAt ? ` · 下次 ${formatDateTime(job.nextAttemptAt)}` : "";
|
||||
return `文件刷新任务 ${serverFileJobStateLabel(job.state)}${attempt}${nextAttempt}${progress ? ` · ${progress}` : ""}`;
|
||||
}
|
||||
|
||||
function serverFileJobStateLabel(state: JobResponse["state"]): string {
|
||||
switch (state) {
|
||||
case "queued":
|
||||
return "已排队,等待 Run 领取";
|
||||
case "accepted":
|
||||
return "Run 已领取,等待确认";
|
||||
case "running":
|
||||
return "运行中";
|
||||
case "retrying":
|
||||
return "等待重试";
|
||||
case "succeeded":
|
||||
return "已完成";
|
||||
case "cancelled":
|
||||
return "已取消";
|
||||
default:
|
||||
return "已失败";
|
||||
}
|
||||
}
|
||||
|
||||
function serverFileIdempotency(prefix: string, serverId: string, key: string): string {
|
||||
return `web-file-${prefix}-${serverId}-${String(key).replace(/[^a-zA-Z0-9_.-]+/g, "-").slice(0, 40)}-${Date.now()}`;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user