hyapp-admin-platform/src/features/app-config/hooks/useSplashScreenConfigPage.js
2026-07-13 15:23:55 +08:00

218 lines
6.5 KiB
JavaScript

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",
};
}