feat(themes): 添加可编辑的站点外观和皮肤主题(#408)
This commit is contained in:
@@ -84,7 +84,7 @@ const adminNavigation: Array<{ label: string; items: AdminNavigationItem[] }> =
|
||||
{
|
||||
label: "系统配置",
|
||||
items: [
|
||||
{ path: "/admin/settings/appearance", label: "外观管理", description: "品牌、Logo 与登录影片", icon: <Palette className="size-4" /> },
|
||||
{ path: "/admin/settings/appearance", label: "站点及外观", description: "品牌、SEO、备案与皮肤", icon: <Palette className="size-4" /> },
|
||||
{ path: "/admin/settings/features", label: "功能开放", description: "工作台、插件与模型能力", icon: <ToggleLeft className="size-4" /> },
|
||||
{ path: "/admin/settings/drawing-engine", label: "绘图工具", description: "画布绘图节点默认引擎", icon: <Paintbrush className="size-4" /> },
|
||||
{ path: "/admin/settings/runtime-policy", label: "资源与策略", description: "配额、并发、频控与超时", icon: <Settings2 className="size-4" /> },
|
||||
@@ -127,7 +127,7 @@ export function AdminShell() {
|
||||
};
|
||||
|
||||
return (
|
||||
<ConfigProvider theme={getAdminAntThemeConfig(dark)}>
|
||||
<ConfigProvider theme={getAdminAntThemeConfig(dark, appearance.activeSkin)}>
|
||||
<main className="admin-shell app-user-workspace flex h-full min-h-0 overflow-hidden text-foreground">
|
||||
<aside className={cn("app-workspace-sidebar admin-sidebar hidden shrink-0 flex-col overflow-hidden lg:flex", collapsed && "is-collapsed")}>
|
||||
<div className="admin-sidebar-identity shrink-0">
|
||||
|
||||
@@ -5,12 +5,14 @@ import { useBlocker } from "react-router";
|
||||
|
||||
import { cn } from "@/lib/utils";
|
||||
import { getAdminEmailSetting, updateAdminEmailSetting, type EmailSetting } from "@/services/api/wallet";
|
||||
import { useAppearanceStore } from "@/stores/use-appearance-store";
|
||||
import { AdminStatusBadge, configuredSecretText, SettingsSectionCard } from "./admin-ui";
|
||||
|
||||
type EmailFormValues = Pick<EmailSetting, "enabled" | "host" | "port" | "username" | "password" | "encryption" | "fromEmail" | "fromName">;
|
||||
|
||||
export default function EmailSettingsPanel() {
|
||||
const { message, modal } = App.useApp();
|
||||
const brandName = useAppearanceStore((state) => state.appearance.brandName);
|
||||
const [setting, setSetting] = useState<EmailSetting | null>(null);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [refreshing, setRefreshing] = useState(false);
|
||||
@@ -394,9 +396,9 @@ export default function EmailSettingsPanel() {
|
||||
validator: (_, value: string | undefined) => (!draftEnabled || !value || !/[\r\n]/.test(value) ? Promise.resolve() : Promise.reject(new Error("发件人名称不能包含换行"))),
|
||||
},
|
||||
]}
|
||||
extra="留空时服务端使用“影策”。"
|
||||
extra={`留空时自动使用当前站点名称“${brandName}”;之后修改站点名称会同步更新。`}
|
||||
>
|
||||
<Input placeholder="影策" />
|
||||
<Input placeholder={brandName} />
|
||||
</Form.Item>
|
||||
</div>
|
||||
</div>
|
||||
@@ -429,7 +431,7 @@ function toEmailFormValues(setting: EmailSetting): EmailFormValues {
|
||||
password: "",
|
||||
encryption: setting.encryption,
|
||||
fromEmail: setting.fromEmail,
|
||||
fromName: setting.fromName,
|
||||
fromName: setting.fromNameInherited ? "" : setting.fromName,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -442,7 +444,7 @@ function normalizeEmailFormValues(values: Partial<EmailFormValues>): EmailFormVa
|
||||
password: values.password?.trim() || "",
|
||||
encryption: values.encryption === "tls" || values.encryption === "none" ? values.encryption : "starttls",
|
||||
fromEmail: values.fromEmail?.trim().toLowerCase() || "",
|
||||
fromName: values.fromName?.trim() || "影策",
|
||||
fromName: values.fromName?.trim() || "",
|
||||
};
|
||||
}
|
||||
|
||||
@@ -482,6 +484,7 @@ function isEmailSetting(value: unknown): value is EmailSetting {
|
||||
["starttls", "tls", "none"].includes(setting.encryption || "") &&
|
||||
typeof setting.fromEmail === "string" &&
|
||||
typeof setting.fromName === "string" &&
|
||||
typeof setting.fromNameInherited === "boolean" &&
|
||||
typeof setting.hasPassword === "boolean"
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user