update:原生确认框替换为自定义弹窗

This commit is contained in:
xiaozhu
2026-09-01 17:23:31 +08:00
parent 149e85cf10
commit 026cd085c6
15 changed files with 452 additions and 83 deletions
@@ -28,6 +28,8 @@ import {
type ScheduleNode,
} from "~/services/api";
import { SchedulePendingConfirmDialog, type SchedulePendingConfirm } from "./SchedulePendingConfirm";
import { ScheduleRenameDialog } from "./ScheduleRenameDialog";
import { useApi, useAuth } from "~/context/AuthContext";
import {
formFieldClass,
@@ -236,6 +238,8 @@ export default function SchedulePage({
const setRuns = useSchedulesStore((s) => s.setRuns);
const setRunsLoading = useSchedulesStore((s) => s.setRunsLoading);
const canvasRef = useRef<HTMLDivElement | null>(null);
const [pendingConfirm, setPendingConfirm] =
useState<SchedulePendingConfirm | null>(null);
const selectedNode = schedule?.nodes.find(
(item) => item.node_id === selectedNodeId,
@@ -366,6 +370,30 @@ export default function SchedulePage({
[],
);
const requestRemoveNode = async (node: ScheduleNode) => {
const result = await useSchedulesStore.getState().removeNode(node);
if (result === "needs_history_confirm") {
setPendingConfirm({ kind: "node-history", node });
}
};
const handleConfirm = async () => {
if (!pendingConfirm) return;
const target = pendingConfirm;
setPendingConfirm(null);
if (target.kind === "schedule") {
await useSchedulesStore.getState().removeSchedule(target.schedule);
} else if (target.kind === "artifact") {
await useSchedulesStore.getState().removeArtifact(target.artifact);
} else if (target.kind === "node") {
await requestRemoveNode(target.node);
} else {
await useSchedulesStore
.getState()
.removeNode(target.node, { deleteExecutionHistory: true });
}
};
return (
<section className="relative flex min-h-0 flex-1 flex-col gap-[10px] overflow-hidden p-[10px]">
<header className="flex min-h-[56px] items-center justify-between rounded-[7px] border border-line bg-white px-[14px] shadow-md">
@@ -416,7 +444,9 @@ export default function SchedulePage({
variant="destructive"
size="sm"
disabled={!schedule || Boolean(busy)}
onClick={() => useSchedulesStore.getState().removeSchedule(schedule ?? undefined)}
onClick={() => {
if (schedule) setPendingConfirm({ kind: "schedule", schedule });
}}
>
</Button>
@@ -662,7 +692,8 @@ export default function SchedulePage({
busy={Boolean(busy)}
onChange={setNodeForm}
onSave={() => useSchedulesStore.getState().saveNode(selectedNode)}
onDelete={() => useSchedulesStore.getState().removeNode(selectedNode)}
onDelete={() =>
setPendingConfirm({ kind: "node", node: selectedNode })}
/>
) : (
<ScheduleInspector
@@ -722,7 +753,8 @@ export default function SchedulePage({
type="button"
variant="ghost"
role="menuitem"
onClick={() => useSchedulesStore.getState().renameSchedule(contextMenu.schedule)}
onClick={() =>
useSchedulesStore.getState().openRenameDialog(contextMenu.schedule)}
>
<Settings size={14} />
@@ -732,21 +764,47 @@ export default function SchedulePage({
type="button"
variant="destructive"
role="menuitem"
onClick={() => useSchedulesStore.getState().removeSchedule(contextMenu.schedule)}
onClick={() => {
useSchedulesStore.getState().setContextMenu(null);
setPendingConfirm({
kind: "schedule",
schedule: contextMenu.schedule,
});
}}
>
<X size={14} />
</Button>
</>
)}
{contextMenu.kind === "artifact" && null}
{contextMenu.kind === "artifact" && (
<Button
className="w-full justify-start gap-[9px] rounded-[5px] p-[9px_10px] text-[12px] text-[#c23b3b] hover:bg-[#fff0f0]"
type="button"
variant="destructive"
role="menuitem"
onClick={() => {
useSchedulesStore.getState().setContextMenu(null);
setPendingConfirm({
kind: "artifact",
artifact: contextMenu.artifact,
});
}}
>
<X size={14} />
</Button>
)}
{contextMenu.kind === "node" && (
<Button
className="w-full justify-start gap-[9px] rounded-[5px] p-[9px_10px] text-[12px] text-[#c23b3b] hover:bg-[#fff0f0]"
type="button"
variant="destructive"
role="menuitem"
onClick={() => useSchedulesStore.getState().removeNode(contextMenu.node)}
onClick={() => {
useSchedulesStore.getState().setContextMenu(null);
setPendingConfirm({ kind: "node", node: contextMenu.node });
}}
>
<X size={14} />
@@ -816,6 +874,16 @@ export default function SchedulePage({
</form>
</AppFormDialog>
<ScheduleRenameDialog />
<SchedulePendingConfirmDialog
pending={pendingConfirm}
onOpenChange={(open) => {
if (!open) setPendingConfirm(null);
}}
onConfirm={() => void handleConfirm()}
/>
{busy && (
<div
className="absolute bottom-[22px] right-[22px] z-[20] flex min-h-[38px] items-center gap-2 rounded-[7px] border border-[#c9dcee] bg-white px-[13px] text-[11px] text-[#4e657d] shadow-lg"