refactor: extract components

This commit is contained in:
tao.chen
2026-08-07 17:38:28 +08:00
parent 873a464629
commit e2615be2e8
4 changed files with 529 additions and 112 deletions
@@ -262,8 +262,7 @@ export default function SchedulePage({
const [runsLoading, setRunsLoading] = useState(false);
const canvasRef = useRef<HTMLDivElement | null>(null);
const dragRef = useRef<DragState | null>(null);
const positionDraftsRef = useRef<Record<string, NodePositionDraft>>({});
const [positionDraftCount, setPositionDraftCount] = useState(0);
const positionDraftCount = useSchedulesStore((state) => state.positionDraftCount);
const api = useApi();
const selectedNode = schedule?.nodes.find(
@@ -299,12 +298,8 @@ export default function SchedulePage({
window.removeEventListener("scroll", close, true);
window.removeEventListener("keydown", onKeyDown);
};
}, [contextMenu]);
}, [contextMenu]);
const clearPositionDrafts = (): void => {
positionDraftsRef.current = {};
setPositionDraftCount(0);
};
const openContextMenu = (
event: ReactMouseEvent<HTMLElement | SVGElement>,
@@ -321,16 +316,16 @@ export default function SchedulePage({
} as ScheduleContextMenu);
};
const applyPositionDrafts = (serverSchedule: Schedule): Schedule => {
const drafts = positionDraftsRef.current;
if (Object.keys(drafts).length === 0) return serverSchedule;
return {
...serverSchedule,
nodes: serverSchedule.nodes.map((node) => {
const draft = drafts[node.node_id];
return draft ? { ...node, ...draft } : node;
}),
};
const applyPositionDrafts = (serverSchedule: Schedule): Schedule => {
const drafts = useSchedulesStore.getState().getPositionDrafts();
if (drafts.size === 0) return serverSchedule;
return {
...serverSchedule,
nodes: serverSchedule.nodes.map((node) => {
const draft = drafts.get(node.node_id);
return draft ? { ...node, ...draft } : node;
}),
};
};
const refreshRuns = async (
@@ -484,17 +479,12 @@ export default function SchedulePage({
if (busy) return null;
setBusy(label);
try {
const serverUpdated = await action();
const validNodeIds = new Set(
serverUpdated.nodes.map((node) => node.node_id),
);
positionDraftsRef.current = Object.fromEntries(
Object.entries(positionDraftsRef.current).filter(([nodeId]) => (
validNodeIds.has(nodeId)
)),
);
setPositionDraftCount(Object.keys(positionDraftsRef.current).length);
const updated = applyPositionDrafts(serverUpdated);
const serverUpdated = await action();
const validNodeIds = new Set(
serverUpdated.nodes.map((node) => node.node_id),
);
useSchedulesStore.getState().prunePositionDrafts(validNodeIds);
const updated = applyPositionDrafts(serverUpdated);
setSchedule(updated);
setSchedules((current) => {
const summary = { ...updated, nodes: [], edges: [] };
@@ -518,9 +508,9 @@ export default function SchedulePage({
const chooseSchedule = async (scheduleId: string): Promise<void> => {
if (scheduleId === schedule?.schedule_id || busy) return;
setBusy("load-schedule");
clearPositionDrafts();
setSelectedNodeId(null);
setBusy("load-schedule");
useSchedulesStore.getState().clearAllPositionDrafts();
setSelectedNodeId(null);
setSelectedEdgeId(null);
setLinkSourceId(null);
setCronResult(null);
@@ -554,10 +544,10 @@ export default function SchedulePage({
timezone: "Asia/Shanghai",
enabled: false,
});
setSchedules((current) => [created, ...current]);
setSchedule(created);
clearPositionDrafts();
setSelectedNodeId(null);
setSchedules((current) => [created, ...current]);
setSchedule(created);
useSchedulesStore.getState().clearAllPositionDrafts();
setSelectedNodeId(null);
setCreateDialogOpen(false);
setNewScheduleName("");
onNotify({ tone: "success", message: "调度方案已创建" });
@@ -583,10 +573,10 @@ export default function SchedulePage({
(item) => item.schedule_id !== selectedSchedule.schedule_id,
);
setSchedules(remaining);
if (schedule?.schedule_id === selectedSchedule.schedule_id) {
setSchedule(null);
clearPositionDrafts();
setSelectedNodeId(null);
if (schedule?.schedule_id === selectedSchedule.schedule_id) {
setSchedule(null);
useSchedulesStore.getState().clearAllPositionDrafts();
setSelectedNodeId(null);
setSelectedEdgeId(null);
if (remaining[0]) {
setSchedule(await api.getSchedule(remaining[0].schedule_id));
@@ -665,12 +655,11 @@ export default function SchedulePage({
return;
}
setBusy("save-schedule");
let updated = useSchedulesStore.getState().schedule ?? schedule;
try {
for (const [nodeId, position] of Object.entries(
positionDraftsRef.current,
)) {
updated = await api.updateScheduleNode(updated.schedule_id, nodeId, {
let updated = useSchedulesStore.getState().schedule ?? schedule;
try {
const drafts = useSchedulesStore.getState().getPositionDrafts();
for (const [nodeId, position] of drafts.entries()) {
updated = await api.updateScheduleNode(updated.schedule_id, nodeId, {
workflow_version: updated.workflow_version,
position_x: position.position_x,
position_y: position.position_y,
@@ -686,11 +675,11 @@ export default function SchedulePage({
: null,
timezone: scheduleForm.timezone.trim(),
enabled: scheduleForm.enabled,
max_concurrency: maxConcurrency,
failure_policy: scheduleForm.failurePolicy,
});
clearPositionDrafts();
setSchedule(updated);
max_concurrency: maxConcurrency,
failure_policy: scheduleForm.failurePolicy,
});
useSchedulesStore.getState().clearAllPositionDrafts();
setSchedule(updated);
setSchedules((current) => current.map((item) => (
item.schedule_id === updated.schedule_id
? { ...updated, nodes: [], edges: [] }
@@ -871,16 +860,12 @@ export default function SchedulePage({
const current = useSchedulesStore.getState().schedule;
const node = current?.nodes.find((item) => item.node_id === drag.nodeId);
if (!current || !node) return;
const position = {
position_x: Math.round(node.position_x),
position_y: Math.round(node.position_y),
};
positionDraftsRef.current = {
...positionDraftsRef.current,
[node.node_id]: position,
};
setPositionDraftCount(Object.keys(positionDraftsRef.current).length);
setSchedule((value) => {
const position = {
position_x: Math.round(node.position_x),
position_y: Math.round(node.position_y),
};
useSchedulesStore.getState().setPositionDraft(node.node_id, position);
setSchedule((value) => {
if (!value) return value;
return {
...value,