mirror of
https://github.com/Rain-kl/OpenFlare.git
synced 2026-10-01 14:46:36 +08:00
重构获取公共参数
This commit is contained in:
@@ -36,6 +36,11 @@ function persistRedirectTarget(searchParams: ReturnType<typeof useSearchParams>)
|
||||
}
|
||||
}
|
||||
|
||||
function configBool(value: string | undefined, fallback: boolean) {
|
||||
if (value === undefined) return fallback
|
||||
return value === "true"
|
||||
}
|
||||
|
||||
export function LoginForm() {
|
||||
const router = useRouter()
|
||||
const searchParams = useSearchParams()
|
||||
@@ -80,7 +85,7 @@ export function LoginForm() {
|
||||
const authSourcesQuery = useQuery({
|
||||
queryKey: ["auth-sources"],
|
||||
queryFn: () => services.auth.getAuthSources(),
|
||||
enabled: publicConfigQuery.data?.oidc_login_enabled ?? true,
|
||||
enabled: configBool(publicConfigQuery.data?.oidc_login_enabled, true),
|
||||
})
|
||||
|
||||
const redirectTarget = useMemo(
|
||||
@@ -88,8 +93,8 @@ export function LoginForm() {
|
||||
[searchParams],
|
||||
)
|
||||
|
||||
const capEnabled = publicConfigQuery.data?.cap_login_enabled ?? false
|
||||
const capAutoSolve = publicConfigQuery.data?.cap_auto_solve ?? true
|
||||
const capEnabled = configBool(publicConfigQuery.data?.cap_login_enabled, false)
|
||||
const capAutoSolve = configBool(publicConfigQuery.data?.cap_auto_solve, true)
|
||||
|
||||
const loginMutation = useMutation({
|
||||
mutationFn: (req: LoginRequest) => {
|
||||
@@ -201,7 +206,6 @@ export function LoginForm() {
|
||||
|
||||
const handleRegister = () => {
|
||||
setErrorMessage("")
|
||||
const emailRegisterEnabled = publicConfigQuery.data?.email_register_verification_enabled ?? false
|
||||
if (emailRegisterEnabled) {
|
||||
if (!email.trim() || !code.trim()) {
|
||||
toast.error("邮箱和验证码不能为空")
|
||||
@@ -241,10 +245,11 @@ export function LoginForm() {
|
||||
}
|
||||
|
||||
const registrationEnabled =
|
||||
(publicConfigQuery.data?.registration_enabled ?? true) &&
|
||||
(publicConfigQuery.data?.password_register_enabled ?? true)
|
||||
configBool(publicConfigQuery.data?.registration_enabled, true) &&
|
||||
configBool(publicConfigQuery.data?.password_register_enabled, true)
|
||||
|
||||
const passwordLoginEnabled = publicConfigQuery.data?.password_login_enabled ?? true
|
||||
const passwordLoginEnabled = configBool(publicConfigQuery.data?.password_login_enabled, true)
|
||||
const emailRegisterEnabled = configBool(publicConfigQuery.data?.email_register_verification_enabled, false)
|
||||
|
||||
const authSources = authSourcesQuery.data ?? []
|
||||
|
||||
@@ -379,10 +384,10 @@ export function LoginForm() {
|
||||
<Input
|
||||
value={email}
|
||||
onChange={(e) => setEmail(e.target.value)}
|
||||
placeholder={publicConfigQuery.data?.email_register_verification_enabled ? "电子邮箱" : "电子邮箱(可选)"}
|
||||
placeholder={emailRegisterEnabled ? "电子邮箱" : "电子邮箱(可选)"}
|
||||
autoComplete="email"
|
||||
/>
|
||||
{publicConfigQuery.data?.email_register_verification_enabled && (
|
||||
{emailRegisterEnabled && (
|
||||
<div className="flex gap-2">
|
||||
<Input
|
||||
value={code}
|
||||
|
||||
@@ -124,6 +124,16 @@ function SystemConfigDetailPanel({
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="px-3 py-2 flex items-center justify-between border-b border-dashed last:border-b-0">
|
||||
<label className="text-xs font-medium text-muted-foreground">公共可见</label>
|
||||
<Switch
|
||||
checked={(editData.visibility ?? config?.visibility ?? 0) === 1}
|
||||
onCheckedChange={(checked) => {
|
||||
onEditDataChange('visibility', checked ? 1 : 0)
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="px-3 py-2 flex items-center justify-between border-b border-dashed last:border-b-0">
|
||||
<label className="text-xs font-medium text-muted-foreground">配置类型</label>
|
||||
<span className={`text-[11px] px-1.5 py-0.5 rounded font-medium ${
|
||||
@@ -173,6 +183,7 @@ export function SystemConfigs() {
|
||||
|
||||
const getInitialEditData = (config: SystemConfig) => ({
|
||||
value: config.value,
|
||||
visibility: config.visibility,
|
||||
description: config.description
|
||||
})
|
||||
|
||||
@@ -181,6 +192,7 @@ export function SystemConfigs() {
|
||||
|
||||
await updateSystemConfig(config.key, {
|
||||
value: editData.value ?? config.value,
|
||||
visibility: editData.visibility ?? config.visibility,
|
||||
description: editData.description ?? config.description
|
||||
})
|
||||
}
|
||||
@@ -208,6 +220,7 @@ export function SystemConfigs() {
|
||||
columns={[
|
||||
{ header: "配置键", cell: (item) => <span className="font-mono font-medium">{item.key}</span>, width: "200px" },
|
||||
{ header: "配置值", cell: (item) => <span className="truncate max-w-[120px] inline-block" title={item.value}>{item.value}</span>, width: "120px" },
|
||||
{ header: "公共可见", cell: (item) => <span>{item.visibility === 1 ? "可见" : "不可见"}</span>, width: "80px" },
|
||||
{ header: "描述", cell: (item) => <span className="truncate max-w-[200px] inline-block text-muted-foreground" title={item.description}>{item.description}</span>, width: "200px" },
|
||||
]}
|
||||
renderDetail={({ selected, hovered, editData, onEditDataChange, onSave, saving }) => (
|
||||
|
||||
@@ -234,17 +234,17 @@ export const apiSections: PolicySection[] = [
|
||||
<div className="space-y-4 text-sm leading-relaxed">
|
||||
<h3 id="4-1-public-config" className="text-base md:text-lg font-semibold text-foreground mt-4 mb-2">4.1 公共系统配置</h3>
|
||||
<p><strong>接口:</strong>GET <code className="bg-muted px-1.5 py-0.5 rounded text-xs font-mono">/api/v1/config/public</code></p>
|
||||
<p><strong>说明:</strong>无感获取当前系统的公开业务设置(如注册是否开启、密码登录是否开启)。供前端页面动态渲染使用。</p>
|
||||
<p><strong>说明:</strong>无感获取当前系统配置表中公共可见的键值集合。供前端页面动态渲染使用。</p>
|
||||
<p className="mt-2">返回数据结构样例:</p>
|
||||
<CodeBlock
|
||||
code={`{
|
||||
"error_msg": "",
|
||||
"data": {
|
||||
"site_name": "Wavelet",
|
||||
"registration_enabled": true,
|
||||
"password_login_enabled": true,
|
||||
"password_register_enabled": true,
|
||||
"oidc_login_enabled": true
|
||||
"registration_enabled": "true",
|
||||
"password_login_enabled": "true",
|
||||
"password_register_enabled": "true",
|
||||
"oidc_login_enabled": "true"
|
||||
}
|
||||
}`}
|
||||
language="json"
|
||||
|
||||
@@ -6,7 +6,7 @@ export function RobotsMeta() {
|
||||
const { config } = usePublicConfig()
|
||||
|
||||
// Default to noindex, nofollow if config is loading or if it's explicitly disabled
|
||||
const enabled = config?.search_engine_indexing_enabled === true
|
||||
const enabled = config?.search_engine_indexing_enabled === "true"
|
||||
|
||||
return (
|
||||
<meta
|
||||
|
||||
@@ -84,6 +84,23 @@ const data = {
|
||||
],
|
||||
}
|
||||
|
||||
function parseMenuDisplayConfig(raw: string | undefined): Record<string, boolean> {
|
||||
if (!raw) return {}
|
||||
try {
|
||||
const parsed: unknown = JSON.parse(raw)
|
||||
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) return {}
|
||||
|
||||
return Object.entries(parsed).reduce<Record<string, boolean>>((result, [key, value]) => {
|
||||
if (typeof value === "boolean") {
|
||||
result[key] = value
|
||||
}
|
||||
return result
|
||||
}, {})
|
||||
} catch {
|
||||
return {}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 应用侧边栏组件
|
||||
* 显示应用侧边栏
|
||||
@@ -145,17 +162,17 @@ export function AppSidebar({ ...props }: React.ComponentProps<typeof Sidebar>) {
|
||||
}
|
||||
|
||||
const navMainFiltered = React.useMemo(() => {
|
||||
const displayConfig = config?.menu_display_config || {}
|
||||
const displayConfig = parseMenuDisplayConfig(config?.menu_display_config)
|
||||
return data.navMain.filter((item) => displayConfig[item.url] !== false)
|
||||
}, [config])
|
||||
|
||||
const adminFiltered = React.useMemo(() => {
|
||||
const displayConfig = config?.menu_display_config || {}
|
||||
const displayConfig = parseMenuDisplayConfig(config?.menu_display_config)
|
||||
return data.admin.filter((item) => displayConfig[item.url] !== false)
|
||||
}, [config])
|
||||
|
||||
const documentFiltered = React.useMemo(() => {
|
||||
const displayConfig = config?.menu_display_config || {}
|
||||
const displayConfig = parseMenuDisplayConfig(config?.menu_display_config)
|
||||
return data.document.filter((item) => displayConfig[item.url] !== false)
|
||||
}, [config])
|
||||
|
||||
|
||||
Reference in New Issue
Block a user