2026-06-11 17:11:04 +08:00

175 lines
4.8 KiB
JavaScript

import { useCallback, useMemo, useState } from "react";
import { createPopup, deletePopup, listPopups, updatePopup } from "@/features/app-config/api";
import { useAppConfigAbilities } from "@/features/app-config/permissions.js";
import { appPopupSchema } from "@/features/app-config/schema";
import { parseForm } from "@/shared/forms/validation";
import { useAdminQuery } from "@/shared/hooks/useAdminQuery.js";
import { useConfirm } from "@/shared/ui/ConfirmProvider.jsx";
import { useToast } from "@/shared/ui/ToastProvider.jsx";
const emptyData = { items: [], total: 0 };
const emptyForm = () => ({
code: "",
displayPeriodDays: "0",
endsAtMs: "",
imageUrl: "",
jumpType: "h5",
jumpUrl: "",
name: "",
sortOrder: "0",
startsAtMs: "",
status: "active",
});
export function usePopupConfigPage() {
const abilities = useAppConfigAbilities();
const confirm = useConfirm();
const { showToast } = useToast();
const [keyword, setKeyword] = useState("");
const [status, setStatus] = useState("");
const [activeAction, setActiveAction] = useState("");
const [editingItem, setEditingItem] = useState(null);
const [form, setFormState] = useState(emptyForm);
const [loadingAction, setLoadingAction] = useState("");
const filters = useMemo(
() => ({
keyword,
status,
}),
[keyword, status],
);
const queryFn = useCallback(() => listPopups(filters), [filters]);
const {
data = emptyData,
error,
loading,
reload,
} = useAdminQuery(queryFn, {
errorMessage: "加载弹窗配置失败",
initialData: emptyData,
queryKey: ["app-config", "popups", filters],
});
const setForm = (patch) => {
setFormState((current) => ({ ...current, ...patch }));
};
const openCreate = () => {
setEditingItem(null);
setFormState(emptyForm());
setActiveAction("create");
};
const openEdit = (item) => {
setEditingItem(item);
setFormState(formFromPopup(item));
setActiveAction("edit");
};
const closeDialog = () => {
setActiveAction("");
setEditingItem(null);
setFormState(emptyForm());
};
const resetFilters = () => {
setKeyword("");
setStatus("");
};
const submitPopup = async (event) => {
event.preventDefault();
const payload = parseForm(appPopupSchema, normalizeForm(form));
const action = editingItem ? "edit" : "create";
setLoadingAction(action);
try {
if (editingItem) {
await updatePopup(editingItem.id, payload);
showToast("弹窗配置已更新", "success");
} else {
await createPopup(payload);
showToast("弹窗配置已新增", "success");
}
closeDialog();
await reload();
} catch (err) {
showToast(err.message || "操作失败", "error");
} finally {
setLoadingAction("");
}
};
const removePopup = async (item) => {
const ok = await confirm({
confirmText: "删除",
message: item.name || item.jumpUrl || `弹窗配置 ${item.id}`,
title: "删除弹窗配置",
tone: "danger",
});
if (!ok) {
return;
}
setLoadingAction(`delete:${item.id}`);
try {
await deletePopup(item.id);
await reload();
showToast("弹窗配置已删除", "success");
} catch (err) {
showToast(err.message || "删除失败", "error");
} finally {
setLoadingAction("");
}
};
return {
abilities,
activeAction,
closeDialog,
data,
editingItem,
error,
form,
keyword,
loading,
loadingAction,
openCreate,
openEdit,
reload,
removePopup,
resetFilters,
setForm,
setKeyword,
setStatus,
status,
submitPopup,
};
}
function normalizeForm(form) {
return {
...form,
displayPeriodDays: form.displayPeriodDays || 0,
endsAtMs: form.endsAtMs || 0,
imageUrl: form.imageUrl || "",
sortOrder: form.sortOrder || 0,
startsAtMs: form.startsAtMs || 0,
};
}
function formFromPopup(item) {
return {
code: item.code || "",
displayPeriodDays: String(item.displayPeriodDays ?? 0),
endsAtMs: item.endsAtMs || "",
imageUrl: item.imageUrl || "",
jumpType: item.jumpType || "h5",
jumpUrl: item.jumpUrl || "",
name: item.name || "",
sortOrder: String(item.sortOrder || 0),
startsAtMs: item.startsAtMs || "",
status: item.status || "active",
};
}