fix(workbench): hold refresh feedback
This commit is contained in:
@@ -10,7 +10,7 @@ import {
|
|||||||
XCircle
|
XCircle
|
||||||
} from "lucide-react";
|
} from "lucide-react";
|
||||||
import { AnimatePresence, motion } from "motion/react";
|
import { AnimatePresence, motion } from "motion/react";
|
||||||
import { useCallback, useEffect, useMemo, useState } from "react";
|
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
||||||
import { MAP_TOOL_PANEL_SURFACE_CLASS_NAME, showMapNotice } from "@/features/map/core";
|
import { MAP_TOOL_PANEL_SURFACE_CLASS_NAME, showMapNotice } from "@/features/map/core";
|
||||||
import { isGeneratedScheduledConditionSessionId } from "../data/scheduled-conditions";
|
import { isGeneratedScheduledConditionSessionId } from "../data/scheduled-conditions";
|
||||||
import type {
|
import type {
|
||||||
@@ -62,6 +62,7 @@ const CONDITION_CONTENT_SURFACE_CLASS_NAME =
|
|||||||
"surface-reading rounded-xl border border-slate-200/70";
|
"surface-reading rounded-xl border border-slate-200/70";
|
||||||
const CONDITION_CONTROL_SURFACE_CLASS_NAME =
|
const CONDITION_CONTROL_SURFACE_CLASS_NAME =
|
||||||
"surface-control rounded-xl border border-slate-200/70";
|
"surface-control rounded-xl border border-slate-200/70";
|
||||||
|
const MINIMUM_REFRESH_FEEDBACK_MS = 3_000;
|
||||||
|
|
||||||
export type ScheduledConditionFeedPresentation =
|
export type ScheduledConditionFeedPresentation =
|
||||||
| "desktop-dock"
|
| "desktop-dock"
|
||||||
@@ -156,6 +157,7 @@ export function ScheduledConditionFeed({
|
|||||||
const [scheduleSubmitting, setScheduleSubmitting] = useState(false);
|
const [scheduleSubmitting, setScheduleSubmitting] = useState(false);
|
||||||
const [scheduleError, setScheduleError] = useState<string | null>(null);
|
const [scheduleError, setScheduleError] = useState<string | null>(null);
|
||||||
const [refreshing, setRefreshing] = useState(false);
|
const [refreshing, setRefreshing] = useState(false);
|
||||||
|
const refreshingRef = useRef(false);
|
||||||
const mobileSheet = presentation === "mobile-sheet";
|
const mobileSheet = presentation === "mobile-sheet";
|
||||||
const desktopDock = presentation === "desktop-dock";
|
const desktopDock = presentation === "desktop-dock";
|
||||||
const compactPresentation = mobileSheet || desktopDock;
|
const compactPresentation = mobileSheet || desktopDock;
|
||||||
@@ -335,19 +337,32 @@ export function ScheduledConditionFeed({
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function handleRefresh() {
|
async function handleRefresh() {
|
||||||
if (!onRefresh || refreshing) return;
|
if (!onRefresh || refreshingRef.current) return;
|
||||||
|
refreshingRef.current = true;
|
||||||
setRefreshing(true);
|
setRefreshing(true);
|
||||||
|
const startedAt = Date.now();
|
||||||
|
let refreshError: unknown = null;
|
||||||
try {
|
try {
|
||||||
await onRefresh();
|
await onRefresh();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
refreshError = error;
|
||||||
|
} finally {
|
||||||
|
const remainingFeedbackMs = MINIMUM_REFRESH_FEEDBACK_MS - (Date.now() - startedAt);
|
||||||
|
if (remainingFeedbackMs > 0) {
|
||||||
|
await new Promise((resolve) => window.setTimeout(resolve, remainingFeedbackMs));
|
||||||
|
}
|
||||||
|
refreshingRef.current = false;
|
||||||
|
setRefreshing(false);
|
||||||
|
}
|
||||||
|
if (refreshError) {
|
||||||
showMapNotice({
|
showMapNotice({
|
||||||
id: "scheduled-condition-refresh",
|
id: "scheduled-condition-refresh",
|
||||||
tone: "error",
|
tone: "error",
|
||||||
title: "工况任务刷新失败",
|
title: "工况任务刷新失败",
|
||||||
message: error instanceof Error ? error.message : "暂时无法重新获取工况任务。"
|
message: refreshError instanceof Error
|
||||||
|
? refreshError.message
|
||||||
|
: "暂时无法重新获取工况任务。"
|
||||||
});
|
});
|
||||||
} finally {
|
|
||||||
setRefreshing(false);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -271,8 +271,16 @@ test("审批动作展示中文参数和证据,viewer 不可审批,冲突后
|
|||||||
await expect(conditionPanel.getByRole("button", { name: /预约任务/ })).toContainText("后端");
|
await expect(conditionPanel.getByRole("button", { name: /预约任务/ })).toContainText("后端");
|
||||||
const conditionRefreshButton = conditionPanel.getByRole("button", { name: "刷新工况任务" });
|
const conditionRefreshButton = conditionPanel.getByRole("button", { name: "刷新工况任务" });
|
||||||
await expect(conditionRefreshButton).toBeVisible();
|
await expect(conditionRefreshButton).toBeVisible();
|
||||||
|
const refreshStartedAt = Date.now();
|
||||||
await conditionRefreshButton.click();
|
await conditionRefreshButton.click();
|
||||||
await expect.poll(() => snapshotRequests).toBe(2);
|
await expect.poll(() => snapshotRequests).toBe(2);
|
||||||
|
const refreshingButton = conditionPanel.getByRole("button", { name: "正在刷新工况任务" });
|
||||||
|
await expect(refreshingButton).toBeDisabled();
|
||||||
|
await refreshingButton.evaluate((button: HTMLButtonElement) => button.click());
|
||||||
|
await page.waitForTimeout(500);
|
||||||
|
expect(snapshotRequests).toBe(2);
|
||||||
|
await expect(conditionRefreshButton).toBeEnabled({ timeout: 4_000 });
|
||||||
|
expect(Date.now() - refreshStartedAt).toBeGreaterThanOrEqual(2_900);
|
||||||
await conditionPanel.getByRole("button", { name: "配置定时流程" }).click();
|
await conditionPanel.getByRole("button", { name: "配置定时流程" }).click();
|
||||||
await conditionPanel.getByLabel("定时流程名称").fill("夜间阀门巡检");
|
await conditionPanel.getByLabel("定时流程名称").fill("夜间阀门巡检");
|
||||||
await conditionPanel.getByLabel("任务说明").fill("每十五分钟检查预约维修涉及的边界阀门。");
|
await conditionPanel.getByLabel("任务说明").fill("每十五分钟检查预约维修涉及的边界阀门。");
|
||||||
|
|||||||
Reference in New Issue
Block a user