mirror of
https://github.com/songquanpeng/one-api.git
synced 2025-11-06 00:33:43 +08:00
feat: i18n support
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
import React, { useContext, useEffect, useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { Button, Divider, Form, Header, Image, Message, Modal } from 'semantic-ui-react';
|
||||
import { Link, useNavigate } from 'react-router-dom';
|
||||
import { API, copy, showError, showInfo, showNotice, showSuccess } from '../helpers';
|
||||
@@ -7,6 +8,7 @@ import { UserContext } from '../context/User';
|
||||
import { onGitHubOAuthClicked, onLarkOAuthClicked } from './utils';
|
||||
|
||||
const PersonalSetting = () => {
|
||||
const { t } = useTranslation();
|
||||
const [userState, userDispatch] = useContext(UserContext);
|
||||
let navigate = useNavigate();
|
||||
|
||||
@@ -169,18 +171,24 @@ const PersonalSetting = () => {
|
||||
|
||||
return (
|
||||
<div style={{ lineHeight: '40px' }}>
|
||||
<Header as='h3'>通用设置</Header>
|
||||
<Header as='h3'>{t('setting.personal.general.title')}</Header>
|
||||
<Message>
|
||||
注意,此处生成的令牌用于系统管理,而非用于请求 OpenAI 相关的服务,请知悉。
|
||||
{t('setting.personal.general.system_token_notice')}
|
||||
</Message>
|
||||
<Button as={Link} to={`/user/edit/`}>
|
||||
更新个人信息
|
||||
{t('setting.personal.general.buttons.update_profile')}
|
||||
</Button>
|
||||
<Button onClick={generateAccessToken}>
|
||||
{t('setting.personal.general.buttons.generate_token')}
|
||||
</Button>
|
||||
<Button onClick={getAffLink}>
|
||||
{t('setting.personal.general.buttons.copy_invite')}
|
||||
</Button>
|
||||
<Button onClick={generateAccessToken}>生成系统访问令牌</Button>
|
||||
<Button onClick={getAffLink}>复制邀请链接</Button>
|
||||
<Button onClick={() => {
|
||||
setShowAccountDeleteModal(true);
|
||||
}}>删除个人账户</Button>
|
||||
}}>
|
||||
{t('setting.personal.general.buttons.delete_account')}
|
||||
</Button>
|
||||
|
||||
{systemToken && (
|
||||
<Form.Input
|
||||
@@ -201,18 +209,12 @@ const PersonalSetting = () => {
|
||||
/>
|
||||
)}
|
||||
<Divider />
|
||||
<Header as='h3'>账号绑定</Header>
|
||||
{
|
||||
status.wechat_login && (
|
||||
<Button
|
||||
onClick={() => {
|
||||
setShowWeChatBindModal(true);
|
||||
}}
|
||||
>
|
||||
绑定微信账号
|
||||
</Button>
|
||||
)
|
||||
}
|
||||
<Header as='h3'>{t('setting.personal.binding.title')}</Header>
|
||||
{status.wechat_login && (
|
||||
<Button onClick={() => setShowWeChatBindModal(true)}>
|
||||
{t('setting.personal.binding.buttons.bind_wechat')}
|
||||
</Button>
|
||||
)}
|
||||
<Modal
|
||||
onClose={() => setShowWeChatBindModal(false)}
|
||||
onOpen={() => setShowWeChatBindModal(true)}
|
||||
@@ -223,41 +225,35 @@ const PersonalSetting = () => {
|
||||
<Modal.Description>
|
||||
<Image src={status.wechat_qrcode} fluid />
|
||||
<div style={{ textAlign: 'center' }}>
|
||||
<p>
|
||||
微信扫码关注公众号,输入「验证码」获取验证码(三分钟内有效)
|
||||
</p>
|
||||
<p>{t('setting.personal.binding.wechat.description')}</p>
|
||||
</div>
|
||||
<Form size='large'>
|
||||
<Form.Input
|
||||
fluid
|
||||
placeholder='验证码'
|
||||
placeholder={t('setting.personal.binding.wechat.verification_code')}
|
||||
name='wechat_verification_code'
|
||||
value={inputs.wechat_verification_code}
|
||||
onChange={handleInputChange}
|
||||
/>
|
||||
<Button color='' fluid size='large' onClick={bindWeChat}>
|
||||
绑定
|
||||
{t('setting.personal.binding.wechat.bind')}
|
||||
</Button>
|
||||
</Form>
|
||||
</Modal.Description>
|
||||
</Modal.Content>
|
||||
</Modal>
|
||||
{
|
||||
status.github_oauth && (
|
||||
<Button onClick={()=>{onGitHubOAuthClicked(status.github_client_id)}}>绑定 GitHub 账号</Button>
|
||||
)
|
||||
}
|
||||
{
|
||||
status.lark_client_id && (
|
||||
<Button onClick={()=>{onLarkOAuthClicked(status.lark_client_id)}}>绑定飞书账号</Button>
|
||||
)
|
||||
}
|
||||
<Button
|
||||
onClick={() => {
|
||||
setShowEmailBindModal(true);
|
||||
}}
|
||||
>
|
||||
绑定邮箱地址
|
||||
{status.github_oauth && (
|
||||
<Button onClick={() => onGitHubOAuthClicked(status.github_client_id)}>
|
||||
{t('setting.personal.binding.buttons.bind_github')}
|
||||
</Button>
|
||||
)}
|
||||
{status.lark_client_id && (
|
||||
<Button onClick={() => onLarkOAuthClicked(status.lark_client_id)}>
|
||||
{t('setting.personal.binding.buttons.bind_lark')}
|
||||
</Button>
|
||||
)}
|
||||
<Button onClick={() => setShowEmailBindModal(true)}>
|
||||
{t('setting.personal.binding.buttons.bind_email')}
|
||||
</Button>
|
||||
<Modal
|
||||
onClose={() => setShowEmailBindModal(false)}
|
||||
@@ -266,57 +262,57 @@ const PersonalSetting = () => {
|
||||
size={'tiny'}
|
||||
style={{ maxWidth: '450px' }}
|
||||
>
|
||||
<Modal.Header>绑定邮箱地址</Modal.Header>
|
||||
<Modal.Header>{t('setting.personal.binding.email.title')}</Modal.Header>
|
||||
<Modal.Content>
|
||||
<Modal.Description>
|
||||
<Form size='large'>
|
||||
<Form.Input
|
||||
fluid
|
||||
placeholder='输入邮箱地址'
|
||||
placeholder={t('setting.personal.binding.email.email_placeholder')}
|
||||
onChange={handleInputChange}
|
||||
name='email'
|
||||
type='email'
|
||||
action={
|
||||
<Button onClick={sendVerificationCode} disabled={disableButton || loading}>
|
||||
{disableButton ? `重新发送(${countdown})` : '获取验证码'}
|
||||
{disableButton
|
||||
? t('setting.personal.binding.email.get_code_retry', { countdown })
|
||||
: t('setting.personal.binding.email.get_code')}
|
||||
</Button>
|
||||
}
|
||||
/>
|
||||
<Form.Input
|
||||
fluid
|
||||
placeholder='验证码'
|
||||
placeholder={t('setting.personal.binding.email.code_placeholder')}
|
||||
name='email_verification_code'
|
||||
value={inputs.email_verification_code}
|
||||
onChange={handleInputChange}
|
||||
/>
|
||||
{turnstileEnabled ? (
|
||||
{turnstileEnabled && (
|
||||
<Turnstile
|
||||
sitekey={turnstileSiteKey}
|
||||
onVerify={(token) => {
|
||||
setTurnstileToken(token);
|
||||
}}
|
||||
/>
|
||||
) : (
|
||||
<></>
|
||||
)}
|
||||
<div style={{ display: 'flex', justifyContent: 'space-between', marginTop: '1rem' }}>
|
||||
<Button
|
||||
color=''
|
||||
fluid
|
||||
size='large'
|
||||
onClick={bindEmail}
|
||||
loading={loading}
|
||||
>
|
||||
确认绑定
|
||||
</Button>
|
||||
<div style={{ width: '1rem' }}></div>
|
||||
<Button
|
||||
fluid
|
||||
size='large'
|
||||
onClick={() => setShowEmailBindModal(false)}
|
||||
>
|
||||
取消
|
||||
</Button>
|
||||
<Button
|
||||
color=''
|
||||
fluid
|
||||
size='large'
|
||||
onClick={bindEmail}
|
||||
loading={loading}
|
||||
>
|
||||
{t('setting.personal.binding.email.bind')}
|
||||
</Button>
|
||||
<div style={{ width: '1rem' }}></div>
|
||||
<Button
|
||||
fluid
|
||||
size='large'
|
||||
onClick={() => setShowEmailBindModal(false)}
|
||||
>
|
||||
{t('setting.personal.binding.email.cancel')}
|
||||
</Button>
|
||||
</div>
|
||||
</Form>
|
||||
</Modal.Description>
|
||||
@@ -329,27 +325,27 @@ const PersonalSetting = () => {
|
||||
size={'tiny'}
|
||||
style={{ maxWidth: '450px' }}
|
||||
>
|
||||
<Modal.Header>危险操作</Modal.Header>
|
||||
<Modal.Header>{t('setting.personal.delete_account.title')}</Modal.Header>
|
||||
<Modal.Content>
|
||||
<Message>您正在删除自己的帐户,将清空所有数据且不可恢复</Message>
|
||||
<Message>{t('setting.personal.delete_account.warning')}</Message>
|
||||
<Modal.Description>
|
||||
<Form size='large'>
|
||||
<Form.Input
|
||||
fluid
|
||||
placeholder={`输入你的账户名 ${userState?.user?.username} 以确认删除`}
|
||||
placeholder={t('setting.personal.delete_account.confirm_placeholder', {
|
||||
username: userState?.user?.username
|
||||
})}
|
||||
name='self_account_deletion_confirmation'
|
||||
value={inputs.self_account_deletion_confirmation}
|
||||
onChange={handleInputChange}
|
||||
/>
|
||||
{turnstileEnabled ? (
|
||||
{turnstileEnabled && (
|
||||
<Turnstile
|
||||
sitekey={turnstileSiteKey}
|
||||
onVerify={(token) => {
|
||||
setTurnstileToken(token);
|
||||
}}
|
||||
/>
|
||||
) : (
|
||||
<></>
|
||||
)}
|
||||
<div style={{ display: 'flex', justifyContent: 'space-between', marginTop: '1rem' }}>
|
||||
<Button
|
||||
@@ -359,7 +355,7 @@ const PersonalSetting = () => {
|
||||
onClick={deleteAccount}
|
||||
loading={loading}
|
||||
>
|
||||
确认删除
|
||||
{t('setting.personal.delete_account.buttons.confirm')}
|
||||
</Button>
|
||||
<div style={{ width: '1rem' }}></div>
|
||||
<Button
|
||||
@@ -367,7 +363,7 @@ const PersonalSetting = () => {
|
||||
size='large'
|
||||
onClick={() => setShowAccountDeleteModal(false)}
|
||||
>
|
||||
取消
|
||||
{t('setting.personal.delete_account.buttons.cancel')}
|
||||
</Button>
|
||||
</div>
|
||||
</Form>
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { Button, Divider, Form, Grid, Header, Modal, Message } from 'semantic-ui-react';
|
||||
import { API, removeTrailingSlash, showError } from '../helpers';
|
||||
|
||||
const SystemSetting = () => {
|
||||
const { t } = useTranslation();
|
||||
let [inputs, setInputs] = useState({
|
||||
PasswordLoginEnabled: '',
|
||||
PasswordRegisterEnabled: '',
|
||||
@@ -260,42 +262,43 @@ const SystemSetting = () => {
|
||||
<Grid columns={1}>
|
||||
<Grid.Column>
|
||||
<Form loading={loading}>
|
||||
<Header as='h3'>通用设置</Header>
|
||||
<Header as='h3'>{t('setting.system.general.title')}</Header>
|
||||
<Form.Group widths='equal'>
|
||||
<Form.Input
|
||||
label='服务器地址'
|
||||
placeholder='例如:https://yourdomain.com'
|
||||
label={t('setting.system.general.server_address')}
|
||||
placeholder={t('setting.system.general.server_address_placeholder')}
|
||||
value={inputs.ServerAddress}
|
||||
name='ServerAddress'
|
||||
onChange={handleInputChange}
|
||||
/>
|
||||
</Form.Group>
|
||||
<Form.Button onClick={submitServerAddress}>
|
||||
更新服务器地址
|
||||
{t('setting.system.general.buttons.update')}
|
||||
</Form.Button>
|
||||
<Divider />
|
||||
<Header as='h3'>配置登录注册</Header>
|
||||
<Header as='h3'>{t('setting.system.login.title')}</Header>
|
||||
<Form.Group inline>
|
||||
<Form.Checkbox
|
||||
checked={inputs.PasswordLoginEnabled === 'true'}
|
||||
label='允许通过密码进行登录'
|
||||
label={t('setting.system.login.password_login')}
|
||||
name='PasswordLoginEnabled'
|
||||
onChange={handleInputChange}
|
||||
/>
|
||||
{
|
||||
showPasswordWarningModal &&
|
||||
{showPasswordWarningModal && (
|
||||
<Modal
|
||||
open={showPasswordWarningModal}
|
||||
onClose={() => setShowPasswordWarningModal(false)}
|
||||
size={'tiny'}
|
||||
style={{ maxWidth: '450px' }}
|
||||
>
|
||||
<Modal.Header>警告</Modal.Header>
|
||||
<Modal.Header>{t('setting.system.password_login.warning.title')}</Modal.Header>
|
||||
<Modal.Content>
|
||||
<p>取消密码登录将导致所有未绑定其他登录方式的用户(包括管理员)无法通过密码登录,确认取消?</p>
|
||||
<p>{t('setting.system.password_login.warning.content')}</p>
|
||||
</Modal.Content>
|
||||
<Modal.Actions>
|
||||
<Button onClick={() => setShowPasswordWarningModal(false)}>取消</Button>
|
||||
<Button onClick={() => setShowPasswordWarningModal(false)}>
|
||||
{t('setting.system.password_login.warning.buttons.cancel')}
|
||||
</Button>
|
||||
<Button
|
||||
color='yellow'
|
||||
onClick={async () => {
|
||||
@@ -303,32 +306,32 @@ const SystemSetting = () => {
|
||||
await updateOption('PasswordLoginEnabled', 'false');
|
||||
}}
|
||||
>
|
||||
确定
|
||||
{t('setting.system.password_login.warning.buttons.confirm')}
|
||||
</Button>
|
||||
</Modal.Actions>
|
||||
</Modal>
|
||||
}
|
||||
)}
|
||||
<Form.Checkbox
|
||||
checked={inputs.PasswordRegisterEnabled === 'true'}
|
||||
label='允许通过密码进行注册'
|
||||
label={t('setting.system.login.password_register')}
|
||||
name='PasswordRegisterEnabled'
|
||||
onChange={handleInputChange}
|
||||
/>
|
||||
<Form.Checkbox
|
||||
checked={inputs.EmailVerificationEnabled === 'true'}
|
||||
label='通过密码注册时需要进行邮箱验证'
|
||||
label={t('setting.system.login.email_verification')}
|
||||
name='EmailVerificationEnabled'
|
||||
onChange={handleInputChange}
|
||||
/>
|
||||
<Form.Checkbox
|
||||
checked={inputs.GitHubOAuthEnabled === 'true'}
|
||||
label='允许通过 GitHub 账户登录 & 注册'
|
||||
label={t('setting.system.login.github_oauth')}
|
||||
name='GitHubOAuthEnabled'
|
||||
onChange={handleInputChange}
|
||||
/>
|
||||
<Form.Checkbox
|
||||
checked={inputs.WeChatAuthEnabled === 'true'}
|
||||
label='允许通过微信登录 & 注册'
|
||||
label={t('setting.system.login.wechat_login')}
|
||||
name='WeChatAuthEnabled'
|
||||
onChange={handleInputChange}
|
||||
/>
|
||||
@@ -336,304 +339,283 @@ const SystemSetting = () => {
|
||||
<Form.Group inline>
|
||||
<Form.Checkbox
|
||||
checked={inputs.RegisterEnabled === 'true'}
|
||||
label='允许新用户注册(此项为否时,新用户将无法以任何方式进行注册)'
|
||||
label={t('setting.system.login.registration')}
|
||||
name='RegisterEnabled'
|
||||
onChange={handleInputChange}
|
||||
/>
|
||||
<Form.Checkbox
|
||||
checked={inputs.TurnstileCheckEnabled === 'true'}
|
||||
label='启用 Turnstile 用户校验'
|
||||
label={t('setting.system.login.turnstile')}
|
||||
name='TurnstileCheckEnabled'
|
||||
onChange={handleInputChange}
|
||||
/>
|
||||
</Form.Group>
|
||||
<Divider />
|
||||
<Header as='h3'>
|
||||
配置邮箱域名白名单
|
||||
<Header.Subheader>用以防止恶意用户利用临时邮箱批量注册</Header.Subheader>
|
||||
</Header>
|
||||
<Form.Group widths={3}>
|
||||
<Header as='h3'>{t('setting.system.email_restriction.title')}</Header>
|
||||
<Message>{t('setting.system.email_restriction.subtitle')}</Message>
|
||||
<Form.Group inline>
|
||||
<Form.Checkbox
|
||||
label='启用邮箱域名白名单'
|
||||
checked={inputs.EmailDomainRestrictionEnabled === 'true'}
|
||||
label={t('setting.system.email_restriction.enable')}
|
||||
name='EmailDomainRestrictionEnabled'
|
||||
onChange={handleInputChange}
|
||||
checked={inputs.EmailDomainRestrictionEnabled === 'true'}
|
||||
/>
|
||||
</Form.Group>
|
||||
<Form.Group widths={2}>
|
||||
<Form.Dropdown
|
||||
label='允许的邮箱域名'
|
||||
placeholder='允许的邮箱域名'
|
||||
name='EmailDomainWhitelist'
|
||||
required
|
||||
fluid
|
||||
multiple
|
||||
selection
|
||||
onChange={handleInputChange}
|
||||
value={inputs.EmailDomainWhitelist}
|
||||
autoComplete='new-password'
|
||||
options={EmailDomainWhitelist}
|
||||
/>
|
||||
<Form.Group widths={3}>
|
||||
<Form.Input
|
||||
label='添加新的允许的邮箱域名'
|
||||
action={
|
||||
<Button type='button' onClick={() => {
|
||||
submitNewRestrictedDomain();
|
||||
}}>填入</Button>
|
||||
}
|
||||
onKeyDown={(e) => {
|
||||
if (e.key === 'Enter') {
|
||||
submitNewRestrictedDomain();
|
||||
}
|
||||
}}
|
||||
autoComplete='new-password'
|
||||
placeholder='输入新的允许的邮箱域名'
|
||||
label={t('setting.system.email_restriction.add_domain')}
|
||||
placeholder={t('setting.system.email_restriction.add_domain_placeholder')}
|
||||
value={restrictedDomainInput}
|
||||
onChange={(e, { value }) => {
|
||||
setRestrictedDomainInput(value);
|
||||
}}
|
||||
action={
|
||||
<Button onClick={() => {
|
||||
if (restrictedDomainInput === '') return;
|
||||
setEmailDomainWhitelist([...EmailDomainWhitelist, {
|
||||
key: restrictedDomainInput,
|
||||
text: restrictedDomainInput,
|
||||
value: restrictedDomainInput
|
||||
}]);
|
||||
setRestrictedDomainInput('');
|
||||
}}>
|
||||
{t('setting.system.email_restriction.buttons.fill')}
|
||||
</Button>
|
||||
}
|
||||
/>
|
||||
</Form.Group>
|
||||
<Form.Button onClick={submitEmailDomainWhitelist}>保存邮箱域名白名单设置</Form.Button>
|
||||
<Form.Dropdown
|
||||
label={t('setting.system.email_restriction.allowed_domains')}
|
||||
placeholder={t('setting.system.email_restriction.allowed_domains')}
|
||||
fluid
|
||||
multiple
|
||||
search
|
||||
selection
|
||||
allowAdditions
|
||||
value={EmailDomainWhitelist.map(item => item.value)}
|
||||
options={EmailDomainWhitelist}
|
||||
onAddItem={(e, { value }) => {
|
||||
setEmailDomainWhitelist([...EmailDomainWhitelist, {
|
||||
key: value,
|
||||
text: value,
|
||||
value: value
|
||||
}]);
|
||||
}}
|
||||
onChange={(e, { value }) => {
|
||||
let newEmailDomainWhitelist = [];
|
||||
value.forEach((item) => {
|
||||
newEmailDomainWhitelist.push({
|
||||
key: item,
|
||||
text: item,
|
||||
value: item
|
||||
});
|
||||
});
|
||||
setEmailDomainWhitelist(newEmailDomainWhitelist);
|
||||
}}
|
||||
/>
|
||||
<Form.Button onClick={submitEmailDomainWhitelist}>
|
||||
{t('setting.system.email_restriction.buttons.save')}
|
||||
</Form.Button>
|
||||
|
||||
<Divider />
|
||||
<Header as='h3'>
|
||||
配置 SMTP
|
||||
<Header.Subheader>用以支持系统的邮件发送</Header.Subheader>
|
||||
</Header>
|
||||
<Header as='h3'>{t('setting.system.smtp.title')}</Header>
|
||||
<Message>{t('setting.system.smtp.subtitle')}</Message>
|
||||
<Form.Group widths={3}>
|
||||
<Form.Input
|
||||
label='SMTP 服务器地址'
|
||||
label={t('setting.system.smtp.server')}
|
||||
placeholder={t('setting.system.smtp.server_placeholder')}
|
||||
name='SMTPServer'
|
||||
onChange={handleInputChange}
|
||||
autoComplete='new-password'
|
||||
value={inputs.SMTPServer}
|
||||
placeholder='例如:smtp.qq.com'
|
||||
/>
|
||||
<Form.Input
|
||||
label='SMTP 端口'
|
||||
label={t('setting.system.smtp.port')}
|
||||
placeholder={t('setting.system.smtp.port_placeholder')}
|
||||
name='SMTPPort'
|
||||
onChange={handleInputChange}
|
||||
autoComplete='new-password'
|
||||
value={inputs.SMTPPort}
|
||||
placeholder='默认: 587'
|
||||
/>
|
||||
<Form.Input
|
||||
label='SMTP 账户'
|
||||
label={t('setting.system.smtp.account')}
|
||||
placeholder={t('setting.system.smtp.account_placeholder')}
|
||||
name='SMTPAccount'
|
||||
onChange={handleInputChange}
|
||||
autoComplete='new-password'
|
||||
value={inputs.SMTPAccount}
|
||||
placeholder='通常是邮箱地址'
|
||||
/>
|
||||
</Form.Group>
|
||||
<Form.Group widths={3}>
|
||||
<Form.Input
|
||||
label='SMTP 发送者邮箱'
|
||||
label={t('setting.system.smtp.from')}
|
||||
placeholder={t('setting.system.smtp.from_placeholder')}
|
||||
name='SMTPFrom'
|
||||
onChange={handleInputChange}
|
||||
autoComplete='new-password'
|
||||
value={inputs.SMTPFrom}
|
||||
placeholder='通常和邮箱地址保持一致'
|
||||
/>
|
||||
<Form.Input
|
||||
label='SMTP 访问凭证'
|
||||
label={t('setting.system.smtp.token')}
|
||||
placeholder={t('setting.system.smtp.token_placeholder')}
|
||||
name='SMTPToken'
|
||||
onChange={handleInputChange}
|
||||
type='password'
|
||||
autoComplete='new-password'
|
||||
checked={inputs.RegisterEnabled === 'true'}
|
||||
placeholder='敏感信息不会发送到前端显示'
|
||||
value={inputs.SMTPToken}
|
||||
/>
|
||||
</Form.Group>
|
||||
<Form.Button onClick={submitSMTP}>保存 SMTP 设置</Form.Button>
|
||||
<Form.Button onClick={submitSMTP}>
|
||||
{t('setting.system.smtp.buttons.save')}
|
||||
</Form.Button>
|
||||
|
||||
<Divider />
|
||||
<Header as='h3'>
|
||||
配置 GitHub OAuth App
|
||||
<Header.Subheader>
|
||||
用以支持通过 GitHub 进行登录注册,
|
||||
<a href='https://github.com/settings/developers' target='_blank'>
|
||||
点击此处
|
||||
</a>
|
||||
管理你的 GitHub OAuth App
|
||||
</Header.Subheader>
|
||||
</Header>
|
||||
<Header as='h3'>{t('setting.system.github.title')}</Header>
|
||||
<Message>
|
||||
Homepage URL 填 <code>{inputs.ServerAddress}</code>
|
||||
,Authorization callback URL 填{' '}
|
||||
<code>{`${inputs.ServerAddress}/oauth/github`}</code>
|
||||
{t('setting.system.github.subtitle')}
|
||||
<a href='https://github.com/settings/developers' target='_blank'>
|
||||
{t('setting.system.github.manage_link')}
|
||||
</a>
|
||||
{t('setting.system.github.manage_text')}
|
||||
</Message>
|
||||
<Message>
|
||||
{t('setting.system.github.url_notice', {
|
||||
server_url: originInputs.ServerAddress,
|
||||
callback_url: `${originInputs.ServerAddress}/oauth/github`
|
||||
})}
|
||||
</Message>
|
||||
<Form.Group widths={3}>
|
||||
<Form.Input
|
||||
label='GitHub Client ID'
|
||||
label={t('setting.system.github.client_id')}
|
||||
placeholder={t('setting.system.github.client_id_placeholder')}
|
||||
name='GitHubClientId'
|
||||
onChange={handleInputChange}
|
||||
autoComplete='new-password'
|
||||
value={inputs.GitHubClientId}
|
||||
placeholder='输入你注册的 GitHub OAuth APP 的 ID'
|
||||
/>
|
||||
<Form.Input
|
||||
label='GitHub Client Secret'
|
||||
label={t('setting.system.github.client_secret')}
|
||||
placeholder={t('setting.system.github.client_secret_placeholder')}
|
||||
name='GitHubClientSecret'
|
||||
onChange={handleInputChange}
|
||||
type='password'
|
||||
autoComplete='new-password'
|
||||
value={inputs.GitHubClientSecret}
|
||||
placeholder='敏感信息不会发送到前端显示'
|
||||
/>
|
||||
</Form.Group>
|
||||
<Form.Button onClick={submitGitHubOAuth}>
|
||||
保存 GitHub OAuth 设置
|
||||
{t('setting.system.github.buttons.save')}
|
||||
</Form.Button>
|
||||
|
||||
<Divider />
|
||||
<Header as='h3'>
|
||||
配置飞书授权登录
|
||||
{t('setting.system.lark.title')}
|
||||
<Header.Subheader>
|
||||
用以支持通过飞书进行登录注册,
|
||||
{t('setting.system.lark.subtitle')}
|
||||
<a href='https://open.feishu.cn/app' target='_blank'>
|
||||
点击此处
|
||||
{t('setting.system.lark.manage_link')}
|
||||
</a>
|
||||
管理你的飞书应用
|
||||
{t('setting.system.lark.manage_text')}
|
||||
</Header.Subheader>
|
||||
</Header>
|
||||
<Message>
|
||||
主页链接填 <code>{inputs.ServerAddress}</code>
|
||||
,重定向 URL 填{' '}
|
||||
<code>{`${inputs.ServerAddress}/oauth/lark`}</code>
|
||||
{t('setting.system.lark.url_notice', {
|
||||
server_url: inputs.ServerAddress,
|
||||
callback_url: `${inputs.ServerAddress}/oauth/lark`
|
||||
})}
|
||||
</Message>
|
||||
<Form.Group widths={3}>
|
||||
<Form.Input
|
||||
label='App ID'
|
||||
label={t('setting.system.lark.client_id')}
|
||||
name='LarkClientId'
|
||||
onChange={handleInputChange}
|
||||
autoComplete='new-password'
|
||||
value={inputs.LarkClientId}
|
||||
placeholder='输入 App ID'
|
||||
placeholder={t('setting.system.lark.client_id_placeholder')}
|
||||
/>
|
||||
<Form.Input
|
||||
label='App Secret'
|
||||
label={t('setting.system.lark.client_secret')}
|
||||
name='LarkClientSecret'
|
||||
onChange={handleInputChange}
|
||||
type='password'
|
||||
autoComplete='new-password'
|
||||
value={inputs.LarkClientSecret}
|
||||
placeholder='敏感信息不会发送到前端显示'
|
||||
placeholder={t('setting.system.lark.client_secret_placeholder')}
|
||||
/>
|
||||
</Form.Group>
|
||||
<Form.Button onClick={submitLarkOAuth}>
|
||||
保存飞书 OAuth 设置
|
||||
{t('setting.system.lark.buttons.save')}
|
||||
</Form.Button>
|
||||
|
||||
<Divider />
|
||||
<Header as='h3'>
|
||||
配置 WeChat Server
|
||||
{t('setting.system.wechat.title')}
|
||||
<Header.Subheader>
|
||||
用以支持通过微信进行登录注册,
|
||||
{t('setting.system.wechat.subtitle')}
|
||||
<a
|
||||
href='https://github.com/songquanpeng/wechat-server'
|
||||
target='_blank'
|
||||
>
|
||||
点击此处
|
||||
{t('setting.system.wechat.learn_more')}
|
||||
</a>
|
||||
了解 WeChat Server
|
||||
</Header.Subheader>
|
||||
</Header>
|
||||
<Form.Group widths={3}>
|
||||
<Form.Input
|
||||
label='WeChat Server 服务器地址'
|
||||
label={t('setting.system.wechat.server_address')}
|
||||
name='WeChatServerAddress'
|
||||
placeholder='例如:https://yourdomain.com'
|
||||
onChange={handleInputChange}
|
||||
autoComplete='new-password'
|
||||
value={inputs.WeChatServerAddress}
|
||||
placeholder={t('setting.system.wechat.server_address_placeholder')}
|
||||
/>
|
||||
<Form.Input
|
||||
label='WeChat Server 访问凭证'
|
||||
label={t('setting.system.wechat.token')}
|
||||
name='WeChatServerToken'
|
||||
type='password'
|
||||
onChange={handleInputChange}
|
||||
type='password'
|
||||
autoComplete='new-password'
|
||||
value={inputs.WeChatServerToken}
|
||||
placeholder='敏感信息不会发送到前端显示'
|
||||
placeholder={t('setting.system.wechat.token_placeholder')}
|
||||
/>
|
||||
<Form.Input
|
||||
label='微信公众号二维码图片链接'
|
||||
label={t('setting.system.wechat.qrcode')}
|
||||
name='WeChatAccountQRCodeImageURL'
|
||||
onChange={handleInputChange}
|
||||
autoComplete='new-password'
|
||||
value={inputs.WeChatAccountQRCodeImageURL}
|
||||
placeholder='输入一个图片链接'
|
||||
placeholder={t('setting.system.wechat.qrcode_placeholder')}
|
||||
/>
|
||||
</Form.Group>
|
||||
<Form.Button onClick={submitWeChat}>
|
||||
保存 WeChat Server 设置
|
||||
{t('setting.system.wechat.buttons.save')}
|
||||
</Form.Button>
|
||||
|
||||
<Divider />
|
||||
<Header as='h3'>
|
||||
配置 Message Pusher
|
||||
{t('setting.system.turnstile.title')}
|
||||
<Header.Subheader>
|
||||
用以推送报警信息,
|
||||
<a
|
||||
href='https://github.com/songquanpeng/message-pusher'
|
||||
target='_blank'
|
||||
>
|
||||
点击此处
|
||||
</a>
|
||||
了解 Message Pusher
|
||||
</Header.Subheader>
|
||||
</Header>
|
||||
<Form.Group widths={3}>
|
||||
<Form.Input
|
||||
label='Message Pusher 推送地址'
|
||||
name='MessagePusherAddress'
|
||||
placeholder='例如:https://msgpusher.com/push/your_username'
|
||||
onChange={handleInputChange}
|
||||
autoComplete='new-password'
|
||||
value={inputs.MessagePusherAddress}
|
||||
/>
|
||||
<Form.Input
|
||||
label='Message Pusher 访问凭证'
|
||||
name='MessagePusherToken'
|
||||
type='password'
|
||||
onChange={handleInputChange}
|
||||
autoComplete='new-password'
|
||||
value={inputs.MessagePusherToken}
|
||||
placeholder='敏感信息不会发送到前端显示'
|
||||
/>
|
||||
</Form.Group>
|
||||
<Form.Button onClick={submitMessagePusher}>
|
||||
保存 Message Pusher 设置
|
||||
</Form.Button>
|
||||
<Divider />
|
||||
<Header as='h3'>
|
||||
配置 Turnstile
|
||||
<Header.Subheader>
|
||||
用以支持用户校验,
|
||||
{t('setting.system.turnstile.subtitle')}
|
||||
<a href='https://dash.cloudflare.com/' target='_blank'>
|
||||
点击此处
|
||||
{t('setting.system.turnstile.manage_link')}
|
||||
</a>
|
||||
管理你的 Turnstile Sites,推荐选择 Invisible Widget Type
|
||||
{t('setting.system.turnstile.manage_text')}
|
||||
</Header.Subheader>
|
||||
</Header>
|
||||
<Form.Group widths={3}>
|
||||
<Form.Input
|
||||
label='Turnstile Site Key'
|
||||
label={t('setting.system.turnstile.site_key')}
|
||||
name='TurnstileSiteKey'
|
||||
onChange={handleInputChange}
|
||||
autoComplete='new-password'
|
||||
value={inputs.TurnstileSiteKey}
|
||||
placeholder='输入你注册的 Turnstile Site Key'
|
||||
placeholder={t('setting.system.turnstile.site_key_placeholder')}
|
||||
/>
|
||||
<Form.Input
|
||||
label='Turnstile Secret Key'
|
||||
label={t('setting.system.turnstile.secret_key')}
|
||||
name='TurnstileSecretKey'
|
||||
onChange={handleInputChange}
|
||||
type='password'
|
||||
autoComplete='new-password'
|
||||
value={inputs.TurnstileSecretKey}
|
||||
placeholder='敏感信息不会发送到前端显示'
|
||||
placeholder={t('setting.system.turnstile.secret_key_placeholder')}
|
||||
/>
|
||||
</Form.Group>
|
||||
<Form.Button onClick={submitTurnstile}>
|
||||
保存 Turnstile 设置
|
||||
{t('setting.system.turnstile.buttons.save')}
|
||||
</Form.Button>
|
||||
</Form>
|
||||
</Grid.Column>
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import React from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { Card, Tab } from 'semantic-ui-react';
|
||||
import SystemSetting from '../../components/SystemSetting';
|
||||
import { isRoot } from '../../helpers';
|
||||
@@ -7,9 +8,11 @@ import PersonalSetting from '../../components/PersonalSetting';
|
||||
import OperationSetting from '../../components/OperationSetting';
|
||||
|
||||
const Setting = () => {
|
||||
const { t } = useTranslation();
|
||||
|
||||
let panes = [
|
||||
{
|
||||
menuItem: '个人设置',
|
||||
menuItem: t('setting.tabs.personal'),
|
||||
render: () => (
|
||||
<Tab.Pane attached={false}>
|
||||
<PersonalSetting />
|
||||
@@ -20,7 +23,7 @@ const Setting = () => {
|
||||
|
||||
if (isRoot()) {
|
||||
panes.push({
|
||||
menuItem: '运营设置',
|
||||
menuItem: t('setting.tabs.operation'),
|
||||
render: () => (
|
||||
<Tab.Pane attached={false}>
|
||||
<OperationSetting />
|
||||
@@ -28,7 +31,7 @@ const Setting = () => {
|
||||
),
|
||||
});
|
||||
panes.push({
|
||||
menuItem: '系统设置',
|
||||
menuItem: t('setting.tabs.system'),
|
||||
render: () => (
|
||||
<Tab.Pane attached={false}>
|
||||
<SystemSetting />
|
||||
@@ -36,7 +39,7 @@ const Setting = () => {
|
||||
),
|
||||
});
|
||||
panes.push({
|
||||
menuItem: '其他设置',
|
||||
menuItem: t('setting.tabs.other'),
|
||||
render: () => (
|
||||
<Tab.Pane attached={false}>
|
||||
<OtherSetting />
|
||||
@@ -49,12 +52,12 @@ const Setting = () => {
|
||||
<div className='dashboard-container'>
|
||||
<Card fluid className='chart-card'>
|
||||
<Card.Content>
|
||||
<Card.Header className='header'>系统设置</Card.Header>
|
||||
<Card.Header className='header'>{t('setting.title')}</Card.Header>
|
||||
<Tab
|
||||
menu={{
|
||||
secondary: true,
|
||||
pointing: true,
|
||||
className: 'settings-tab', // 添加自定义类名以便样式化
|
||||
className: 'settings-tab',
|
||||
}}
|
||||
panes={panes}
|
||||
/>
|
||||
|
||||
Reference in New Issue
Block a user