| @@ -116,6 +116,8 @@ func GetStatus(c *gin.Context) { | |||||
| "setup": constant.Setup, | "setup": constant.Setup, | ||||
| "user_agreement_enabled": legalSetting.UserAgreement != "", | "user_agreement_enabled": legalSetting.UserAgreement != "", | ||||
| "privacy_policy_enabled": legalSetting.PrivacyPolicy != "", | "privacy_policy_enabled": legalSetting.PrivacyPolicy != "", | ||||
| "terms_enabled": legalSetting.TermsOfService != "", | |||||
| "usage_policy_enabled": legalSetting.UsagePolicy != "", | |||||
| "checkin_enabled": operation_setting.GetCheckinSetting().Enabled, | "checkin_enabled": operation_setting.GetCheckinSetting().Enabled, | ||||
| "_qn": "new-api", | "_qn": "new-api", | ||||
| } | } | ||||
| @@ -207,6 +209,24 @@ func GetPrivacyPolicy(c *gin.Context) { | |||||
| return | 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) { | func GetMidjourney(c *gin.Context) { | ||||
| common.OptionMapRWMutex.RLock() | common.OptionMapRWMutex.RLock() | ||||
| defer common.OptionMapRWMutex.RUnlock() | defer common.OptionMapRWMutex.RUnlock() | ||||
| @@ -26,6 +26,8 @@ func SetApiRouter(router *gin.Engine) { | |||||
| apiRouter.GET("/notice", controller.GetNotice) | apiRouter.GET("/notice", controller.GetNotice) | ||||
| apiRouter.GET("/user-agreement", controller.GetUserAgreement) | apiRouter.GET("/user-agreement", controller.GetUserAgreement) | ||||
| apiRouter.GET("/privacy-policy", controller.GetPrivacyPolicy) | apiRouter.GET("/privacy-policy", controller.GetPrivacyPolicy) | ||||
| apiRouter.GET("/terms", controller.GetTermsOfService) | |||||
| apiRouter.GET("/usage-policy", controller.GetUsagePolicy) | |||||
| apiRouter.GET("/about", controller.GetAbout) | apiRouter.GET("/about", controller.GetAbout) | ||||
| //apiRouter.GET("/midjourney", controller.GetMidjourney) | //apiRouter.GET("/midjourney", controller.GetMidjourney) | ||||
| apiRouter.GET("/home_page_content", controller.GetHomePageContent) | apiRouter.GET("/home_page_content", controller.GetHomePageContent) | ||||
| @@ -3,13 +3,17 @@ package system_setting | |||||
| import "github.com/QuantumNous/new-api/setting/config" | import "github.com/QuantumNous/new-api/setting/config" | ||||
| type LegalSettings struct { | 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{ | var defaultLegalSettings = LegalSettings{ | ||||
| UserAgreement: "", | |||||
| PrivacyPolicy: "", | |||||
| UserAgreement: "", | |||||
| PrivacyPolicy: "", | |||||
| TermsOfService: "", | |||||
| UsagePolicy: "", | |||||
| } | } | ||||
| func init() { | func init() { | ||||
| @@ -55,6 +55,8 @@ const Dashboard = lazy(() => import('./pages/Dashboard')); | |||||
| const About = lazy(() => import('./pages/About')); | const About = lazy(() => import('./pages/About')); | ||||
| const UserAgreement = lazy(() => import('./pages/UserAgreement')); | const UserAgreement = lazy(() => import('./pages/UserAgreement')); | ||||
| const PrivacyPolicy = lazy(() => import('./pages/PrivacyPolicy')); | const PrivacyPolicy = lazy(() => import('./pages/PrivacyPolicy')); | ||||
| const Terms = lazy(() => import('./pages/Terms')); | |||||
| const UsagePolicy = lazy(() => import('./pages/UsagePolicy')); | |||||
| function DynamicOAuth2Callback() { | function DynamicOAuth2Callback() { | ||||
| const { provider } = useParams(); | const { provider } = useParams(); | ||||
| @@ -358,6 +360,22 @@ function App() { | |||||
| </Suspense> | </Suspense> | ||||
| } | } | ||||
| /> | /> | ||||
| <Route | |||||
| path='/terms' | |||||
| element={ | |||||
| <Suspense fallback={<Loading></Loading>} key={location.pathname}> | |||||
| <Terms /> | |||||
| </Suspense> | |||||
| } | |||||
| /> | |||||
| <Route | |||||
| path='/usage-policy' | |||||
| element={ | |||||
| <Suspense fallback={<Loading></Loading>} key={location.pathname}> | |||||
| <UsagePolicy /> | |||||
| </Suspense> | |||||
| } | |||||
| /> | |||||
| <Route | <Route | ||||
| path='/console/chat/:id?' | path='/console/chat/:id?' | ||||
| element={ | element={ | ||||
| @@ -36,6 +36,8 @@ import Text from '@douyinfe/semi-ui/lib/es/typography/text'; | |||||
| const LEGAL_USER_AGREEMENT_KEY = 'legal.user_agreement'; | const LEGAL_USER_AGREEMENT_KEY = 'legal.user_agreement'; | ||||
| const LEGAL_PRIVACY_POLICY_KEY = 'legal.privacy_policy'; | const LEGAL_PRIVACY_POLICY_KEY = 'legal.privacy_policy'; | ||||
| const LEGAL_TERMS_KEY = 'legal.terms_of_service'; | |||||
| const LEGAL_USAGE_POLICY_KEY = 'legal.usage_policy'; | |||||
| const OtherSetting = () => { | const OtherSetting = () => { | ||||
| const { t } = useTranslation(); | const { t } = useTranslation(); | ||||
| @@ -43,6 +45,8 @@ const OtherSetting = () => { | |||||
| Notice: '', | Notice: '', | ||||
| [LEGAL_USER_AGREEMENT_KEY]: '', | [LEGAL_USER_AGREEMENT_KEY]: '', | ||||
| [LEGAL_PRIVACY_POLICY_KEY]: '', | [LEGAL_PRIVACY_POLICY_KEY]: '', | ||||
| [LEGAL_TERMS_KEY]: '', | |||||
| [LEGAL_USAGE_POLICY_KEY]: '', | |||||
| SystemName: '', | SystemName: '', | ||||
| Logo: '', | Logo: '', | ||||
| Footer: '', | Footer: '', | ||||
| @@ -76,6 +80,8 @@ const OtherSetting = () => { | |||||
| Notice: false, | Notice: false, | ||||
| [LEGAL_USER_AGREEMENT_KEY]: false, | [LEGAL_USER_AGREEMENT_KEY]: false, | ||||
| [LEGAL_PRIVACY_POLICY_KEY]: false, | [LEGAL_PRIVACY_POLICY_KEY]: false, | ||||
| [LEGAL_TERMS_KEY]: false, | |||||
| [LEGAL_USAGE_POLICY_KEY]: false, | |||||
| SystemName: false, | SystemName: false, | ||||
| Logo: false, | Logo: false, | ||||
| HomePageContent: 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(); | const formAPIPersonalization = useRef(); | ||||
| // 个性化设置 - SystemName | // 个性化设置 - SystemName | ||||
| @@ -413,6 +460,38 @@ const OtherSetting = () => { | |||||
| > | > | ||||
| {t('设置隐私政策')} | {t('设置隐私政策')} | ||||
| </Button> | </Button> | ||||
| <Form.TextArea | |||||
| label={t('服务条款')} | |||||
| placeholder={t( | |||||
| '在此输入服务条款内容,支持 Markdown & HTML 代码', | |||||
| )} | |||||
| field={LEGAL_TERMS_KEY} | |||||
| onChange={handleInputChange} | |||||
| style={{ fontFamily: 'JetBrains Mono, Consolas' }} | |||||
| autosize={{ minRows: 6, maxRows: 12 }} | |||||
| /> | |||||
| <Button | |||||
| onClick={submitTermsOfService} | |||||
| loading={loadingInput[LEGAL_TERMS_KEY]} | |||||
| > | |||||
| {t('设置服务条款')} | |||||
| </Button> | |||||
| <Form.TextArea | |||||
| label={t('使用政策')} | |||||
| placeholder={t( | |||||
| '在此输入使用政策内容,支持 Markdown & HTML 代码', | |||||
| )} | |||||
| field={LEGAL_USAGE_POLICY_KEY} | |||||
| onChange={handleInputChange} | |||||
| style={{ fontFamily: 'JetBrains Mono, Consolas' }} | |||||
| autosize={{ minRows: 6, maxRows: 12 }} | |||||
| /> | |||||
| <Button | |||||
| onClick={submitUsagePolicy} | |||||
| loading={loadingInput[LEGAL_USAGE_POLICY_KEY]} | |||||
| > | |||||
| {t('设置使用政策')} | |||||
| </Button> | |||||
| </Form.Section> | </Form.Section> | ||||
| </Card> | </Card> | ||||
| </Form> | </Form> | ||||
| @@ -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 ( | |||||
| <DocumentRenderer | |||||
| apiEndpoint='/api/terms' | |||||
| title={t('服务条款')} | |||||
| cacheKey='terms_of_service' | |||||
| emptyMessage={t('加载服务条款内容失败...')} | |||||
| /> | |||||
| ); | |||||
| }; | |||||
| export default Terms; | |||||
| @@ -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 ( | |||||
| <DocumentRenderer | |||||
| apiEndpoint='/api/usage-policy' | |||||
| title={t('使用政策')} | |||||
| cacheKey='usage_policy' | |||||
| emptyMessage={t('加载使用政策内容失败...')} | |||||
| /> | |||||
| ); | |||||
| }; | |||||
| export default UsagePolicy; | |||||