From 1cc75aa9a2e9583cfe42161b0e28f6bb5085ec5e Mon Sep 17 00:00:00 2001 From: fengsilin Date: Thu, 23 Apr 2026 15:35:36 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=9C=8D=E5=8A=A1=E6=9D=A1=E6=AC=BE?= =?UTF-8?q?=E5=92=8C=E4=BD=BF=E7=94=A8=E6=94=BF=E7=AD=96=E9=A1=B5=E9=9D=A2?= =?UTF-8?q?=EF=BC=8C=E6=94=AF=E6=8C=81=E5=90=8E=E5=8F=B0=20Markdown=20?= =?UTF-8?q?=E9=85=8D=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 复用现有 LegalSettings 模式,新增 TermsOfService 和 UsagePolicy 字段, 添加 /terms 和 /usage-policy 前端页面及 API 端点。 Co-Authored-By: Claude Opus 4.7 --- controller/misc.go | 20 +++++ router/api-router.go | 2 + setting/system_setting/legal.go | 12 ++- web/src/App.jsx | 18 +++++ web/src/components/settings/OtherSetting.jsx | 79 ++++++++++++++++++++ web/src/pages/Terms/index.jsx | 18 +++++ web/src/pages/UsagePolicy/index.jsx | 18 +++++ 7 files changed, 163 insertions(+), 4 deletions(-) create mode 100644 web/src/pages/Terms/index.jsx create mode 100644 web/src/pages/UsagePolicy/index.jsx diff --git a/controller/misc.go b/controller/misc.go index b24a74a..e0c61bc 100644 --- a/controller/misc.go +++ b/controller/misc.go @@ -115,6 +115,8 @@ func GetStatus(c *gin.Context) { "setup": constant.Setup, "user_agreement_enabled": legalSetting.UserAgreement != "", "privacy_policy_enabled": legalSetting.PrivacyPolicy != "", + "terms_enabled": legalSetting.TermsOfService != "", + "usage_policy_enabled": legalSetting.UsagePolicy != "", "checkin_enabled": operation_setting.GetCheckinSetting().Enabled, "_qn": "new-api", } @@ -206,6 +208,24 @@ func GetPrivacyPolicy(c *gin.Context) { return } +func GetTermsOfService(c *gin.Context) { + c.JSON(http.StatusOK, gin.H{ + "success": true, + "message": "", + "data": system_setting.GetLegalSettings().TermsOfService, + }) + return +} + +func GetUsagePolicy(c *gin.Context) { + c.JSON(http.StatusOK, gin.H{ + "success": true, + "message": "", + "data": system_setting.GetLegalSettings().UsagePolicy, + }) + return +} + func GetMidjourney(c *gin.Context) { common.OptionMapRWMutex.RLock() defer common.OptionMapRWMutex.RUnlock() diff --git a/router/api-router.go b/router/api-router.go index 0bab2e1..119630a 100644 --- a/router/api-router.go +++ b/router/api-router.go @@ -26,6 +26,8 @@ func SetApiRouter(router *gin.Engine) { apiRouter.GET("/notice", controller.GetNotice) apiRouter.GET("/user-agreement", controller.GetUserAgreement) apiRouter.GET("/privacy-policy", controller.GetPrivacyPolicy) + apiRouter.GET("/terms", controller.GetTermsOfService) + apiRouter.GET("/usage-policy", controller.GetUsagePolicy) apiRouter.GET("/about", controller.GetAbout) //apiRouter.GET("/midjourney", controller.GetMidjourney) apiRouter.GET("/home_page_content", controller.GetHomePageContent) diff --git a/setting/system_setting/legal.go b/setting/system_setting/legal.go index cc84d40..7bf08a5 100644 --- a/setting/system_setting/legal.go +++ b/setting/system_setting/legal.go @@ -3,13 +3,17 @@ package system_setting import "github.com/QuantumNous/new-api/setting/config" type LegalSettings struct { - UserAgreement string `json:"user_agreement"` - PrivacyPolicy string `json:"privacy_policy"` + UserAgreement string `json:"user_agreement"` + PrivacyPolicy string `json:"privacy_policy"` + TermsOfService string `json:"terms_of_service"` + UsagePolicy string `json:"usage_policy"` } var defaultLegalSettings = LegalSettings{ - UserAgreement: "", - PrivacyPolicy: "", + UserAgreement: "", + PrivacyPolicy: "", + TermsOfService: "", + UsagePolicy: "", } func init() { diff --git a/web/src/App.jsx b/web/src/App.jsx index a5d1ebc..d0498af 100644 --- a/web/src/App.jsx +++ b/web/src/App.jsx @@ -55,6 +55,8 @@ const Dashboard = lazy(() => import('./pages/Dashboard')); const About = lazy(() => import('./pages/About')); const UserAgreement = lazy(() => import('./pages/UserAgreement')); const PrivacyPolicy = lazy(() => import('./pages/PrivacyPolicy')); +const Terms = lazy(() => import('./pages/Terms')); +const UsagePolicy = lazy(() => import('./pages/UsagePolicy')); function DynamicOAuth2Callback() { const { provider } = useParams(); @@ -358,6 +360,22 @@ function App() { } /> + } key={location.pathname}> + + + } + /> + } key={location.pathname}> + + + } + /> { const { t } = useTranslation(); @@ -43,6 +45,8 @@ const OtherSetting = () => { Notice: '', [LEGAL_USER_AGREEMENT_KEY]: '', [LEGAL_PRIVACY_POLICY_KEY]: '', + [LEGAL_TERMS_KEY]: '', + [LEGAL_USAGE_POLICY_KEY]: '', SystemName: '', Logo: '', Footer: '', @@ -76,6 +80,8 @@ const OtherSetting = () => { Notice: false, [LEGAL_USER_AGREEMENT_KEY]: false, [LEGAL_PRIVACY_POLICY_KEY]: false, + [LEGAL_TERMS_KEY]: false, + [LEGAL_USAGE_POLICY_KEY]: false, SystemName: false, Logo: false, HomePageContent: false, @@ -147,6 +153,47 @@ const OtherSetting = () => { })); } }; + // 通用设置 - TermsOfService + const submitTermsOfService = async () => { + try { + setLoadingInput((loadingInput) => ({ + ...loadingInput, + [LEGAL_TERMS_KEY]: true, + })); + await updateOption(LEGAL_TERMS_KEY, inputs[LEGAL_TERMS_KEY]); + showSuccess(t('服务条款已更新')); + } catch (error) { + console.error(t('服务条款更新失败'), error); + showError(t('服务条款更新失败')); + } finally { + setLoadingInput((loadingInput) => ({ + ...loadingInput, + [LEGAL_TERMS_KEY]: false, + })); + } + }; + // 通用设置 - UsagePolicy + const submitUsagePolicy = async () => { + try { + setLoadingInput((loadingInput) => ({ + ...loadingInput, + [LEGAL_USAGE_POLICY_KEY]: true, + })); + await updateOption( + LEGAL_USAGE_POLICY_KEY, + inputs[LEGAL_USAGE_POLICY_KEY], + ); + showSuccess(t('使用政策已更新')); + } catch (error) { + console.error(t('使用政策更新失败'), error); + showError(t('使用政策更新失败')); + } finally { + setLoadingInput((loadingInput) => ({ + ...loadingInput, + [LEGAL_USAGE_POLICY_KEY]: false, + })); + } + }; // 个性化设置 const formAPIPersonalization = useRef(); // 个性化设置 - SystemName @@ -413,6 +460,38 @@ const OtherSetting = () => { > {t('设置隐私政策')} + + + + diff --git a/web/src/pages/Terms/index.jsx b/web/src/pages/Terms/index.jsx new file mode 100644 index 0000000..7065a9d --- /dev/null +++ b/web/src/pages/Terms/index.jsx @@ -0,0 +1,18 @@ +import React from 'react'; +import { useTranslation } from 'react-i18next'; +import DocumentRenderer from '../../components/common/DocumentRenderer'; + +const Terms = () => { + const { t } = useTranslation(); + + return ( + + ); +}; + +export default Terms; diff --git a/web/src/pages/UsagePolicy/index.jsx b/web/src/pages/UsagePolicy/index.jsx new file mode 100644 index 0000000..241b25a --- /dev/null +++ b/web/src/pages/UsagePolicy/index.jsx @@ -0,0 +1,18 @@ +import React from 'react'; +import { useTranslation } from 'react-i18next'; +import DocumentRenderer from '../../components/common/DocumentRenderer'; + +const UsagePolicy = () => { + const { t } = useTranslation(); + + return ( + + ); +}; + +export default UsagePolicy;