From aeeef895de861dd3c4e5916ce6926381d8df9927 Mon Sep 17 00:00:00 2001 From: JetSprow Date: Wed, 29 Apr 2026 16:44:24 +1000 Subject: [PATCH] style: collapse subscription risk settings --- src/actions/admin/settings.ts | 36 ++- .../(admin)/admin/settings/settings-form.tsx | 289 ++++++++++-------- 2 files changed, 181 insertions(+), 144 deletions(-) diff --git a/src/actions/admin/settings.ts b/src/actions/admin/settings.ts index 950beb6..174f20c 100644 --- a/src/actions/admin/settings.ts +++ b/src/actions/admin/settings.ts @@ -87,9 +87,16 @@ async function assertSmtpTestRateLimit(userId: string) { } } +function optionalBoolean(value: string | undefined, fallback: boolean) { + return value == null ? fallback : value === "true"; +} + function buildSettingsUpdate(parsed: z.infer, current: Awaited>) { - const smtpEnabled = parsed.smtpEnabled === "true"; - const emailVerificationRequired = parsed.emailVerificationRequired === "true"; + const smtpEnabled = optionalBoolean(parsed.smtpEnabled, current.smtpEnabled); + const emailVerificationRequired = optionalBoolean( + parsed.emailVerificationRequired, + current.emailVerificationRequired, + ); const smtpPassword = parsed.smtpPassword?.trim() ? encrypt(parsed.smtpPassword.trim()) : current.smtpPassword; @@ -102,17 +109,26 @@ function buildSettingsUpdate(parsed: z.infer, current: Aw supportOpenTicketLimit: parsed.supportOpenTicketLimit ?? current.supportOpenTicketLimit, maintenanceNotice: parsed.maintenanceNotice || null, siteNotice: parsed.siteNotice || null, - allowRegistration: parsed.allowRegistration === "true", + allowRegistration: optionalBoolean(parsed.allowRegistration, current.allowRegistration), emailVerificationRequired, - requireInviteCode: parsed.requireInviteCode === "true", - autoReminderDispatchEnabled: parsed.autoReminderDispatchEnabled === "true", + requireInviteCode: optionalBoolean(parsed.requireInviteCode, current.requireInviteCode), + autoReminderDispatchEnabled: optionalBoolean( + parsed.autoReminderDispatchEnabled, + current.autoReminderDispatchEnabled, + ), reminderDispatchIntervalMinutes: parsed.reminderDispatchIntervalMinutes ?? current.reminderDispatchIntervalMinutes, - trafficSyncEnabled: parsed.trafficSyncEnabled === "true", + trafficSyncEnabled: optionalBoolean(parsed.trafficSyncEnabled, current.trafficSyncEnabled), trafficSyncIntervalSeconds: parsed.trafficSyncIntervalSeconds ?? current.trafficSyncIntervalSeconds, - subscriptionRiskEnabled: parsed.subscriptionRiskEnabled === "true", - subscriptionRiskAutoSuspend: parsed.subscriptionRiskAutoSuspend === "true", + subscriptionRiskEnabled: optionalBoolean( + parsed.subscriptionRiskEnabled, + current.subscriptionRiskEnabled, + ), + subscriptionRiskAutoSuspend: optionalBoolean( + parsed.subscriptionRiskAutoSuspend, + current.subscriptionRiskAutoSuspend, + ), subscriptionRiskWindowHours: parsed.subscriptionRiskWindowHours ?? current.subscriptionRiskWindowHours, subscriptionRiskCityWarning: @@ -131,7 +147,7 @@ function buildSettingsUpdate(parsed: z.infer, current: Aw parsed.subscriptionRiskIpLimitPerHour ?? current.subscriptionRiskIpLimitPerHour, subscriptionRiskTokenLimitPerHour: parsed.subscriptionRiskTokenLimitPerHour ?? current.subscriptionRiskTokenLimitPerHour, - inviteRewardEnabled: parsed.inviteRewardEnabled === "true", + inviteRewardEnabled: optionalBoolean(parsed.inviteRewardEnabled, current.inviteRewardEnabled), inviteRewardRate: parsed.inviteRewardRate ?? Number(current.inviteRewardRate), inviteRewardCouponId: parsed.inviteRewardCouponId || null, turnstileSiteKey: parsed.turnstileSiteKey || null, @@ -139,7 +155,7 @@ function buildSettingsUpdate(parsed: z.infer, current: Aw smtpEnabled, smtpHost: parsed.smtpHost || null, smtpPort: parsed.smtpPort ?? current.smtpPort, - smtpSecure: parsed.smtpSecure === "true", + smtpSecure: optionalBoolean(parsed.smtpSecure, current.smtpSecure), smtpUser: parsed.smtpUser || null, smtpPassword, smtpFromName: parsed.smtpFromName || null, diff --git a/src/app/(admin)/admin/settings/settings-form.tsx b/src/app/(admin)/admin/settings/settings-form.tsx index 5e09142..e904eb5 100644 --- a/src/app/(admin)/admin/settings/settings-form.tsx +++ b/src/app/(admin)/admin/settings/settings-form.tsx @@ -2,7 +2,7 @@ import { useState, type FormEvent } from "react"; import { useRouter } from "next/navigation"; -import { Bell, Clock3, Gift, LifeBuoy, Mail, Send, Settings2, ShieldAlert, ShieldCheck } from "lucide-react"; +import { Bell, ChevronDown, Clock3, Gift, LifeBuoy, Mail, Send, Settings2, ShieldAlert, ShieldCheck } from "lucide-react"; import { Button, buttonVariants } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; import { Label } from "@/components/ui/label"; @@ -63,6 +63,7 @@ export function SettingsForm({ config, coupons }: { config: AppConfig; coupons: const router = useRouter(); const [saving, setSaving] = useState(false); const [testingEmail, setTestingEmail] = useState(false); + const [riskSettingsOpen, setRiskSettingsOpen] = useState(false); async function handleSubmit(event: FormEvent) { event.preventDefault(); @@ -235,140 +236,160 @@ export function SettingsForm({ config, coupons }: { config: AppConfig; coupons:
-
- 订阅访问风控 -
-

- 控制订阅接口限流、跨地区访问告警和自动暂停。关闭总控后仍会保留访问日志,但不会限流、告警或自动暂停。 -

-
-
- - + + + {riskSettingsOpen && ( +
+
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+

+ 默认值对应原规则:24 小时内 4 城市警告、5 城市暂停;2 省/地区警告、3 省/地区暂停;2 国家警告、3 国家暂停;IP 180 次/小时,订阅 60 次/小时。 +

-
- - -
-
- - -
-
- - -
-
- - -
-
- - -
-
- - -
-
- - -
-
- - -
-
- - -
-
- - -
-
-

- 默认值对应原规则:24 小时内 4 城市警告、5 城市暂停;2 省/地区警告、3 省/地区暂停;2 国家警告、3 国家暂停;IP 180 次/小时,订阅 60 次/小时。 -

+ )}