import { useCallback, useEffect, useMemo, useState } from "react"; import { useAppScope } from "@/app/app-scope/AppScopeProvider.jsx"; import { createSplashScreen, deleteSplashScreen, listSplashScreens, updateSplashScreen, } from "@/features/app-config/api"; import { useAppConfigAbilities } from "@/features/app-config/permissions.js"; import { appSplashScreenSchema } from "@/features/app-config/schema"; import { useCountryOptions } from "@/features/host-org/hooks/useCountryOptions.js"; import { parseForm } from "@/shared/forms/validation"; import { useAdminQuery } from "@/shared/hooks/useAdminQuery.js"; import { useRegionOptions } from "@/shared/hooks/useRegionOptions.js"; import { useConfirm } from "@/shared/ui/ConfirmProvider.jsx"; import { useToast } from "@/shared/ui/ToastProvider.jsx"; const emptyData = { items: [], total: 0 }; const emptyForm = () => ({ countryCode: "", coverUrl: "", description: "", displayDurationMs: "3000", endsAtMs: "", param: "", platform: "android", regionId: "", sortOrder: "0", splashType: "h5", startsAtMs: "", status: "active", }); export function useSplashScreenConfigPage() { const { appCode } = useAppScope(); const abilities = useAppConfigAbilities(); const confirm = useConfirm(); const { showToast } = useToast(); const { countryOptions, loadingCountries } = useCountryOptions(); const { loadingRegions, regionOptions } = useRegionOptions(); const [keyword, setKeyword] = useState(""); const [status, setStatus] = useState(""); const [platform, setPlatform] = useState(""); const [regionId, setRegionId] = useState(""); const [countryCode, setCountryCode] = useState(""); const [activeAction, setActiveAction] = useState(""); const [editingItem, setEditingItem] = useState(null); const [form, setFormState] = useState(emptyForm); const [loadingAction, setLoadingAction] = useState(""); const filters = useMemo( () => ({ countryCode, keyword, platform, regionId, status, }), [countryCode, keyword, platform, regionId, status], ); const queryFn = useCallback(() => listSplashScreens(appCode, filters), [appCode, filters]); const { data = emptyData, error, loading, reload, } = useAdminQuery(queryFn, { enabled: Boolean(appCode), errorMessage: "加载开屏配置失败", initialData: emptyData, queryKey: ["app-config", "splash-screens", appCode, filters], }); useEffect(() => { // 开屏配置按 App 独立;切换时关闭旧表单,避免旧图片和投放条件被带到新 App。 setActiveAction(""); setEditingItem(null); setFormState(emptyForm()); }, [appCode]); const setForm = (patch) => { setFormState((current) => ({ ...current, ...patch })); }; const openCreate = () => { setEditingItem(null); setFormState(emptyForm()); setActiveAction("create"); }; const openEdit = (item) => { setEditingItem(item); setFormState(formFromSplashScreen(item)); setActiveAction("edit"); }; const closeDialog = () => { setActiveAction(""); setEditingItem(null); setFormState(emptyForm()); }; const resetFilters = () => { setKeyword(""); setStatus(""); setPlatform(""); setRegionId(""); setCountryCode(""); }; const submitSplashScreen = async (event) => { event.preventDefault(); const payload = parseForm(appSplashScreenSchema, normalizeForm(form)); const action = editingItem ? "edit" : "create"; setLoadingAction(action); try { if (editingItem) { await updateSplashScreen(appCode, editingItem.id, payload); showToast("开屏配置已更新", "success"); } else { await createSplashScreen(appCode, payload); showToast("开屏配置已新增", "success"); } closeDialog(); await reload(); } catch (err) { showToast(err.message || "操作失败", "error"); } finally { setLoadingAction(""); } }; const removeSplashScreen = async (item) => { const ok = await confirm({ confirmText: "删除", message: item.description || item.param || `开屏配置 ${item.id}`, title: "删除开屏配置", tone: "danger", }); if (!ok) { return; } setLoadingAction(`delete:${item.id}`); try { await deleteSplashScreen(appCode, item.id); await reload(); showToast("开屏配置已删除", "success"); } catch (err) { showToast(err.message || "删除失败", "error"); } finally { setLoadingAction(""); } }; return { abilities, activeAction, closeDialog, countryCode, countryOptions, data, editingItem, error, form, keyword, loading, loadingAction, loadingCountries, loadingRegions, openCreate, openEdit, platform, regionId, regionOptions, reload, removeSplashScreen, resetFilters, setCountryCode, setForm, setKeyword, setPlatform, setRegionId, setStatus, status, submitSplashScreen, }; } function normalizeForm(form) { return { ...form, countryCode: form.countryCode || "", displayDurationMs: form.displayDurationMs || 3000, endsAtMs: form.endsAtMs || 0, regionId: form.regionId || 0, sortOrder: form.sortOrder || 0, startsAtMs: form.startsAtMs || 0, }; } function formFromSplashScreen(item) { return { countryCode: item.countryCode || "", coverUrl: item.coverUrl || "", description: item.description || "", displayDurationMs: String(item.displayDurationMs || 3000), endsAtMs: item.endsAtMs || "", param: item.param || "", platform: item.platform || "android", regionId: item.regionId ? String(item.regionId) : "", sortOrder: String(item.sortOrder || 0), splashType: item.splashType || "h5", startsAtMs: item.startsAtMs || "", status: item.status || "active", }; }