refactor: useSchedulesStore.ts
This commit is contained in:
@@ -0,0 +1,78 @@
|
||||
// Dialog slice: create-schedule dialog state + cron preview.
|
||||
// Pure setters + small mutations that read/write only dialog-owned fields.
|
||||
|
||||
import type { CronPreview } from "../../../services/api";
|
||||
import type { StateCreator } from "zustand";
|
||||
|
||||
import { handleError, notify, requireApi } from "./helpers";
|
||||
import type { SchedulesStore } from "./useSchedulesStore";
|
||||
|
||||
// ---- State ----
|
||||
|
||||
export type DialogSliceState = {
|
||||
createDialogOpen: boolean;
|
||||
newScheduleName: string;
|
||||
cronResult: CronPreview | null;
|
||||
};
|
||||
|
||||
// ---- Actions ----
|
||||
|
||||
export type DialogSliceActions = {
|
||||
// pure setters
|
||||
setCreateDialogOpen: (open: boolean) => void;
|
||||
setNewScheduleName: (name: string) => void;
|
||||
setCronResult: (result: CronPreview | null) => void;
|
||||
|
||||
// mutations
|
||||
openCreateDialog: () => void;
|
||||
runCronPreview: () => Promise<void>;
|
||||
};
|
||||
|
||||
// `SchedulesStore` is the combined state+actions of all slices, so `get()`
|
||||
// returns a fully typed snapshot — no `any` propagation.
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
export const createDialogSlice: StateCreator<SchedulesStore, [], [], DialogSliceState & DialogSliceActions> = (set, get) => ({
|
||||
// ---- initial state ----
|
||||
createDialogOpen: false,
|
||||
newScheduleName: "",
|
||||
cronResult: null,
|
||||
|
||||
// ---- pure setters ----
|
||||
|
||||
setCreateDialogOpen: (open) => set({ createDialogOpen: open }),
|
||||
setNewScheduleName: (name) => set({ newScheduleName: name }),
|
||||
setCronResult: (result) => set({ cronResult: result }),
|
||||
|
||||
// ---- mutations ----
|
||||
|
||||
openCreateDialog: () => {
|
||||
if (get().busy) return;
|
||||
set((s: any) => ({
|
||||
contextMenu: null,
|
||||
newScheduleName: `新建调度 ${s.schedules.length + 1}`,
|
||||
createDialogOpen: true,
|
||||
}));
|
||||
},
|
||||
|
||||
runCronPreview: async () => {
|
||||
const api = requireApi();
|
||||
const { scheduleForm } = get();
|
||||
if (scheduleForm.triggerType !== "cron") return;
|
||||
if (get().busy) return;
|
||||
set({ busy: "cron-preview" });
|
||||
try {
|
||||
const result = await api.previewCron({
|
||||
cron_expression: scheduleForm.cronExpression.trim(),
|
||||
timezone: scheduleForm.timezone.trim(),
|
||||
count: 5,
|
||||
});
|
||||
set({ cronResult: result });
|
||||
notify({ tone: "success", message: "Cron 表达式校验通过" });
|
||||
} catch (error) {
|
||||
set({ cronResult: null });
|
||||
await handleError(get, error, "Cron 预览失败");
|
||||
} finally {
|
||||
set({ busy: null });
|
||||
}
|
||||
},
|
||||
});
|
||||
Reference in New Issue
Block a user