/* Copyright (C) 2025 QuantumNous This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see . For commercial licensing, please contact support@quantumnous.com */ import React, { useEffect, useState, useContext } from 'react'; import { Button, Card, Col, Form, Row, Switch, Typography, } from '@douyinfe/semi-ui'; import { API, showError, showSuccess } from '../../../helpers'; import { useTranslation } from 'react-i18next'; import { StatusContext } from '../../../context/Status'; const { Text } = Typography; export default function SettingsHeaderNavModules(props) { const { t } = useTranslation(); const [loading, setLoading] = useState(false); const [statusState, statusDispatch] = useContext(StatusContext); // 顶栏模块管理状态 const [headerNavModules, setHeaderNavModules] = useState({ home: { enabled: true, blurPricing: false, showCostPrice: false, }, pricing: { enabled: true, requireAuth: false, blurPricing: false, }, console: true, benchmark: true, docs: true, }); const [showThemeToggle, setShowThemeToggle] = useState(true); const [showLanguageSelector, setShowLanguageSelector] = useState(true); // 处理顶栏模块配置变更 function handleHeaderNavModuleChange(moduleKey) { return (checked) => { const newModules = { ...headerNavModules }; if (moduleKey === 'pricing' || moduleKey === 'home') { newModules[moduleKey] = { ...newModules[moduleKey], enabled: checked, }; } else { newModules[moduleKey] = checked; } setHeaderNavModules(newModules); }; } // 处理模型广场权限控制变更 function handlePricingAuthChange(checked) { const newModules = { ...headerNavModules }; newModules.pricing = { ...newModules.pricing, requireAuth: checked, }; setHeaderNavModules(newModules); } // 处理首页成本价展示开关变更(即时保存) function handleShowCostPriceChange(checked) { const newModules = { ...headerNavModules }; newModules.home = { ...newModules.home, showCostPrice: checked, }; setHeaderNavModules(newModules); (async () => { try { const res = await API.put('/api/option/', { key: 'HeaderNavModules', value: JSON.stringify(newModules), }); const { success, message } = res.data; if (success) { showSuccess(t('保存成功')); statusDispatch({ type: 'set', payload: { ...statusState.status, HeaderNavModules: JSON.stringify(newModules), }, }); if (props.refresh) { await props.refresh(); } } else { showError(message); newModules.home = { ...newModules.home, showCostPrice: !checked, }; setHeaderNavModules(newModules); } } catch { showError(t('保存失败,请重试')); newModules.home = { ...newModules.home, showCostPrice: !checked, }; setHeaderNavModules(newModules); } })(); } // 处理主题切换开关变更(即时保存) async function handleShowThemeToggleChange(checked) { setShowThemeToggle(checked); const key = 'HeaderShowThemeToggle'; const value = String(checked); try { const res = await API.put('/api/option/', { key, value }); if (res.data.success) { showSuccess(t('保存成功')); statusDispatch({ type: 'set', payload: { ...statusState.status, [key]: value }, }); } else { showError(res.data.message); setShowThemeToggle(!checked); } } catch { showError(t('保存失败,请重试')); setShowThemeToggle(!checked); } } // 处理语言选择器开关变更(即时保存) async function handleShowLanguageSelectorChange(checked) { setShowLanguageSelector(checked); const key = 'HeaderShowLanguageSelector'; const value = String(checked); try { const res = await API.put('/api/option/', { key, value }); if (res.data.success) { showSuccess(t('保存成功')); statusDispatch({ type: 'set', payload: { ...statusState.status, [key]: value }, }); } else { showError(res.data.message); setShowLanguageSelector(!checked); } } catch { showError(t('保存失败,请重试')); setShowLanguageSelector(!checked); } } // 处理模糊价格开关变更(即时保存) function handleBlurPricingChange(moduleKey) { return async (checked) => { const newModules = { ...headerNavModules }; newModules[moduleKey] = { ...newModules[moduleKey], blurPricing: checked, }; setHeaderNavModules(newModules); try { const res = await API.put('/api/option/', { key: 'HeaderNavModules', value: JSON.stringify(newModules), }); const { success, message } = res.data; if (success) { showSuccess(t('保存成功')); statusDispatch({ type: 'set', payload: { ...statusState.status, HeaderNavModules: JSON.stringify(newModules), }, }); if (props.refresh) { await props.refresh(); } } else { showError(message); newModules[moduleKey] = { ...newModules[moduleKey], blurPricing: !checked }; setHeaderNavModules(newModules); } } catch { showError(t('保存失败,请重试')); newModules[moduleKey] = { ...newModules[moduleKey], blurPricing: !checked }; setHeaderNavModules(newModules); } }; } // 重置顶栏模块为默认配置 function resetHeaderNavModules() { const defaultModules = { home: { enabled: true, blurPricing: false, showCostPrice: false, }, pricing: { enabled: true, requireAuth: false, blurPricing: false, }, console: true, benchmark: true, docs: true, }; setHeaderNavModules(defaultModules); showSuccess(t('已重置为默认配置')); } // 保存配置 async function onSubmit() { setLoading(true); try { const res = await API.put('/api/option/', { key: 'HeaderNavModules', value: JSON.stringify(headerNavModules), }); const { success, message } = res.data; if (success) { showSuccess(t('保存成功')); // 立即更新StatusContext中的状态 statusDispatch({ type: 'set', payload: { ...statusState.status, HeaderNavModules: JSON.stringify(headerNavModules), }, }); // 刷新父组件状态 if (props.refresh) { await props.refresh(); } } else { showError(message); } } catch (error) { showError(t('保存失败,请重试')); } finally { setLoading(false); } } useEffect(() => { // 从 props.options 中获取主题切换和语言选择器设置 if (props.options) { const themeVal = props.options.HeaderShowThemeToggle; if (themeVal !== undefined && themeVal !== null) { setShowThemeToggle(themeVal === 'true' || themeVal === true); } const langVal = props.options.HeaderShowLanguageSelector; if (langVal !== undefined && langVal !== null) { setShowLanguageSelector(langVal === 'true' || langVal === true); } } // 从 props.options 中获取配置 if (props.options && props.options.HeaderNavModules) { try { const modules = JSON.parse(props.options.HeaderNavModules); // 处理向后兼容性:如果home是boolean,转换为对象格式 if (typeof modules.home === 'boolean') { modules.home = { enabled: modules.home, blurPricing: false, showCostPrice: false, }; } // 处理向后兼容性:如果pricing是boolean,转换为对象格式 if (typeof modules.pricing === 'boolean') { modules.pricing = { enabled: modules.pricing, requireAuth: false, blurPricing: false, }; } // 确保 blurPricing 字段存在 if (typeof modules.home === 'object' && modules.home.blurPricing === undefined) { modules.home.blurPricing = false; } if (typeof modules.home === 'object' && modules.home.showCostPrice === undefined) { modules.home.showCostPrice = false; } if (typeof modules.pricing === 'object' && modules.pricing.blurPricing === undefined) { modules.pricing.blurPricing = false; } setHeaderNavModules(modules); } catch (error) { // 使用默认配置 const defaultModules = { home: { enabled: true, blurPricing: false, showCostPrice: false, }, pricing: { enabled: true, requireAuth: false, blurPricing: false, }, console: true, benchmark: true, docs: true, }; setHeaderNavModules(defaultModules); } } }, [props.options]); // 获取模块是否启用 function getModuleEnabled(moduleKey) { const val = headerNavModules[moduleKey]; if (typeof val === 'object' && val !== null) { return val.enabled; } return !!val; } // 模块配置数据 const moduleConfigs = [ { key: 'home', title: t('首页'), description: t('用户主页,展示系统信息'), hasBlurPricing: true, hasCostPrice: true, }, { key: 'pricing', title: t('模型'), description: t('模型定价,需要登录访问'), hasSubConfig: true, hasBlurPricing: true, }, { key: 'console', title: t('控制台'), description: t('用户控制面板,管理账户'), }, { key: 'benchmark', title: t('评测'), description: t('AI 模型评测与排行'), }, { key: 'docs', title: t('文档'), description: t('系统文档和帮助信息'), }, ]; return ( {moduleConfigs.map((module) => (
{module.title}
{module.description}
{/* 为模型广场添加权限控制子开关 */} {module.key === 'pricing' && getModuleEnabled(module.key) && (
{t('需要登录访问')}
{t('开启后未登录用户无法访问模型广场')}
)} {/* 未登录模糊价格子开关 */} {module.hasBlurPricing && getModuleEnabled(module.key) && (
{t('未登录模糊价格')}
{t('开启后未登录用户看到的价格和供应商信息将模糊处理')}
)} {/* 首页成本价展示子开关 */} {module.hasCostPrice && getModuleEnabled(module.key) && (
{t('成本价')}
{t( '开启后,供应商、代理商、管理员与超级管理员在首页模型详情侧栏「我的令牌」下方可查看各通道成本价', )}
)}
))} {/* 主题切换开关 */}
{t('主题切换')}
{t('顶栏显示主题切换按钮,允许用户切换亮色/暗色模式')}
{/* 语言选择器开关 */}
{t('语言选择器')}
{t('顶栏显示语言选择器,允许用户切换界面语言')}
); }