"use client"; import { ExternalLink, LogIn, MessageSquare, MessagesSquare, ShieldCheck, ShieldOff, Timer } from "lucide-react"; import { useState } from "react"; import { AdminSettingsGroup, AdminSettingsRow, AdminStepper, AdminSwitch, } from "@/components/admin"; import ConfirmDialog from "@/components/ConfirmDialog"; import useUnsavedGuard from "@/hooks/useUnsavedGuard"; import { apiUpdateSiteSettings, type PublicSettings } from "@/lib/api"; import { toast } from "@/lib/toast"; import OperationsPanel from "./OperationsPanel"; function InstantNote({ saving }: { saving?: boolean }) { return {saving ? "正在保存…" : "修改后立即生效"}; } /** 内容互动开关 + 访问安全模块 */ export default function AccessSettings({ initial }: { initial: PublicSettings }) { const [allowComments, setAllowComments] = useState(initial.allow_comments !== false); const [commentsRequireLogin, setCommentsRequireLogin] = useState( initial.comments_require_login === true, ); const [allowMessages, setAllowMessages] = useState(initial.allow_messages !== false); const [postLinkNewTab, setPostLinkNewTab] = useState(initial.post_link_new_tab !== false); const [trustOn, setTrustOn] = useState(initial.trust_reviewed_publish !== false); const [withoutReviewOn, setWithoutReviewOn] = useState(initial.publish_without_review === true); const [cooldown, setCooldown] = useState(initial.post_cooldown_hours); const [savedCooldown, setSavedCooldown] = useState(initial.post_cooldown_hours); const [togglingComments, setTogglingComments] = useState(false); const [togglingCommentsLogin, setTogglingCommentsLogin] = useState(false); const [togglingMessages, setTogglingMessages] = useState(false); const [togglingLink, setTogglingLink] = useState(false); const [togglingTrust, setTogglingTrust] = useState(false); const [togglingWithoutReview, setTogglingWithoutReview] = useState(false); const [savingCooldown, setSavingCooldown] = useState(false); const [moduleDirty, setModuleDirty] = useState(false); const leave = useUnsavedGuard(moduleDirty); const toggleComments = async () => { if (togglingComments) return; const next = !allowComments; setTogglingComments(true); try { const res = await apiUpdateSiteSettings({ allow_comments: next }); setAllowComments(res.allow_comments); toast(res.allow_comments ? "已开放评论" : "已关闭评论", "ok"); } catch (e) { toast(e instanceof Error ? e.message : "保存失败"); } finally { setTogglingComments(false); } }; const toggleCommentsRequireLogin = async () => { if (togglingCommentsLogin || !allowComments) return; const next = !commentsRequireLogin; setTogglingCommentsLogin(true); try { const res = await apiUpdateSiteSettings({ comments_require_login: next }); setCommentsRequireLogin(res.comments_require_login === true); toast(res.comments_require_login ? "评论仅登录用户可见" : "游客也可查看评论", "ok"); } catch (e) { toast(e instanceof Error ? e.message : "保存失败"); } finally { setTogglingCommentsLogin(false); } }; const toggleMessages = async () => { if (togglingMessages) return; const next = !allowMessages; setTogglingMessages(true); try { const res = await apiUpdateSiteSettings({ allow_messages: next }); setAllowMessages(res.allow_messages); toast(res.allow_messages ? "已开放消息" : "已关闭消息", "ok"); } catch (e) { toast(e instanceof Error ? e.message : "保存失败"); } finally { setTogglingMessages(false); } }; const togglePostLinkNewTab = async () => { if (togglingLink) return; const next = !postLinkNewTab; setTogglingLink(true); try { const res = await apiUpdateSiteSettings({ post_link_new_tab: next }); setPostLinkNewTab(res.post_link_new_tab !== false); toast( res.post_link_new_tab !== false ? "帖子与评论外链将在新标签打开" : "帖子与评论外链将在当前页打开", "ok", ); } catch (e) { toast(e instanceof Error ? e.message : "保存失败"); } finally { setTogglingLink(false); } }; const toggleWithoutReview = async () => { if (togglingWithoutReview) return; setTogglingWithoutReview(true); try { const res = await apiUpdateSiteSettings({ publish_without_review: !withoutReviewOn }); setWithoutReviewOn(res.publish_without_review === true); toast( res.publish_without_review ? "已开启全站免审(发帖与评论直接公开,无需过审记录)" : "已关闭全站免审(将按过审免审规则决定是否待审)", "ok", ); } catch (e) { toast(e instanceof Error ? e.message : "保存失败"); } finally { setTogglingWithoutReview(false); } }; const toggleTrust = async () => { if (togglingTrust) return; setTogglingTrust(true); try { const res = await apiUpdateSiteSettings({ trust_reviewed_publish: !trustOn }); setTrustOn(res.trust_reviewed_publish); toast( res.trust_reviewed_publish ? "已开启过审免审(帖子与评论)" : "已关闭过审免审(帖子与评论将按规则待审)", "ok", ); } catch (e) { toast(e instanceof Error ? e.message : "保存失败"); } finally { setTogglingTrust(false); } }; const saveCooldown = async () => { if (savingCooldown) return; const n = Math.max(0, Math.min(168, Math.round(Number(cooldown)) || 0)); setSavingCooldown(true); try { const res = await apiUpdateSiteSettings({ post_cooldown_hours: n }); setCooldown(res.post_cooldown_hours); setSavedCooldown(res.post_cooldown_hours); toast( res.post_cooldown_hours === 0 ? "已关闭新用户发帖冷静期" : `新用户发帖冷静期已设为 ${res.post_cooldown_hours} 小时(评论与聊天不受限)`, "ok", ); } catch (e) { toast(e instanceof Error ? e.message : "保存失败"); } finally { setSavingCooldown(false); } }; return (