2025-03-02 01:31:27 +08:00
|
|
|
|
import React, { useContext, useEffect, useRef, useState } from 'react';
|
2025-04-04 12:00:38 +08:00
|
|
|
|
import {
|
|
|
|
|
|
Banner,
|
|
|
|
|
|
Button,
|
|
|
|
|
|
Col,
|
|
|
|
|
|
Form,
|
|
|
|
|
|
Row,
|
|
|
|
|
|
Modal,
|
|
|
|
|
|
Space,
|
2025-04-04 17:37:52 +08:00
|
|
|
|
Card,
|
2025-04-04 12:00:38 +08:00
|
|
|
|
} from '@douyinfe/semi-ui';
|
2025-03-02 01:31:27 +08:00
|
|
|
|
import { API, showError, showSuccess, timestamp2string } from '../helpers';
|
2023-04-22 20:39:27 +08:00
|
|
|
|
import { marked } from 'marked';
|
2024-12-13 19:03:14 +08:00
|
|
|
|
import { useTranslation } from 'react-i18next';
|
2025-03-02 01:31:27 +08:00
|
|
|
|
import { StatusContext } from '../context/Status/index.js';
|
|
|
|
|
|
import Text from '@douyinfe/semi-ui/lib/es/typography/text';
|
2023-04-22 20:39:27 +08:00
|
|
|
|
|
|
|
|
|
|
const OtherSetting = () => {
|
2024-12-13 19:03:14 +08:00
|
|
|
|
const { t } = useTranslation();
|
2023-04-22 20:39:27 +08:00
|
|
|
|
let [inputs, setInputs] = useState({
|
|
|
|
|
|
Notice: '',
|
2023-05-14 19:29:02 +08:00
|
|
|
|
SystemName: '',
|
|
|
|
|
|
Logo: '',
|
2024-03-06 17:57:53 +08:00
|
|
|
|
Footer: '',
|
|
|
|
|
|
About: '',
|
2024-03-23 21:24:39 +08:00
|
|
|
|
HomePageContent: '',
|
2023-04-22 20:39:27 +08:00
|
|
|
|
});
|
|
|
|
|
|
let [loading, setLoading] = useState(false);
|
|
|
|
|
|
const [showUpdateModal, setShowUpdateModal] = useState(false);
|
2025-03-02 01:31:27 +08:00
|
|
|
|
const [statusState, statusDispatch] = useContext(StatusContext);
|
2023-04-22 20:39:27 +08:00
|
|
|
|
const [updateData, setUpdateData] = useState({
|
|
|
|
|
|
tag_name: '',
|
2024-03-23 21:24:39 +08:00
|
|
|
|
content: '',
|
2023-04-22 20:39:27 +08:00
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
const updateOption = async (key, value) => {
|
|
|
|
|
|
setLoading(true);
|
2023-05-16 10:04:39 +08:00
|
|
|
|
const res = await API.put('/api/option/', {
|
2023-04-22 20:39:27 +08:00
|
|
|
|
key,
|
2024-03-23 21:24:39 +08:00
|
|
|
|
value,
|
2023-04-22 20:39:27 +08:00
|
|
|
|
});
|
|
|
|
|
|
const { success, message } = res.data;
|
|
|
|
|
|
if (success) {
|
|
|
|
|
|
setInputs((inputs) => ({ ...inputs, [key]: value }));
|
|
|
|
|
|
} else {
|
|
|
|
|
|
showError(message);
|
|
|
|
|
|
}
|
|
|
|
|
|
setLoading(false);
|
|
|
|
|
|
};
|
|
|
|
|
|
|
2024-03-06 17:57:53 +08:00
|
|
|
|
const [loadingInput, setLoadingInput] = useState({
|
|
|
|
|
|
Notice: false,
|
|
|
|
|
|
SystemName: false,
|
|
|
|
|
|
Logo: false,
|
|
|
|
|
|
HomePageContent: false,
|
|
|
|
|
|
About: false,
|
2024-03-23 21:24:39 +08:00
|
|
|
|
Footer: false,
|
2025-04-04 12:00:38 +08:00
|
|
|
|
CheckUpdate: false,
|
2024-03-06 17:57:53 +08:00
|
|
|
|
});
|
|
|
|
|
|
const handleInputChange = async (value, e) => {
|
|
|
|
|
|
const name = e.target.id;
|
2023-04-22 20:39:27 +08:00
|
|
|
|
setInputs((inputs) => ({ ...inputs, [name]: value }));
|
|
|
|
|
|
};
|
|
|
|
|
|
|
2024-03-06 17:57:53 +08:00
|
|
|
|
// 通用设置
|
|
|
|
|
|
const formAPISettingGeneral = useRef();
|
|
|
|
|
|
// 通用设置 - Notice
|
2023-04-22 20:39:27 +08:00
|
|
|
|
const submitNotice = async () => {
|
2024-03-06 18:26:22 +08:00
|
|
|
|
try {
|
|
|
|
|
|
setLoadingInput((loadingInput) => ({ ...loadingInput, Notice: true }));
|
|
|
|
|
|
await updateOption('Notice', inputs.Notice);
|
2024-12-13 19:03:14 +08:00
|
|
|
|
showSuccess(t('公告已更新'));
|
2024-03-06 18:26:22 +08:00
|
|
|
|
} catch (error) {
|
2024-12-13 19:03:14 +08:00
|
|
|
|
console.error(t('公告更新失败'), error);
|
|
|
|
|
|
showError(t('公告更新失败'));
|
2024-03-06 18:26:22 +08:00
|
|
|
|
} finally {
|
|
|
|
|
|
setLoadingInput((loadingInput) => ({ ...loadingInput, Notice: false }));
|
|
|
|
|
|
}
|
2023-04-22 20:39:27 +08:00
|
|
|
|
};
|
2024-03-06 17:57:53 +08:00
|
|
|
|
// 个性化设置
|
|
|
|
|
|
const formAPIPersonalization = useRef();
|
|
|
|
|
|
// 个性化设置 - SystemName
|
2023-05-14 19:29:02 +08:00
|
|
|
|
const submitSystemName = async () => {
|
2024-03-06 18:26:22 +08:00
|
|
|
|
try {
|
2024-03-23 21:24:39 +08:00
|
|
|
|
setLoadingInput((loadingInput) => ({
|
|
|
|
|
|
...loadingInput,
|
|
|
|
|
|
SystemName: true,
|
|
|
|
|
|
}));
|
2024-03-06 18:26:22 +08:00
|
|
|
|
await updateOption('SystemName', inputs.SystemName);
|
2024-12-13 19:03:14 +08:00
|
|
|
|
showSuccess(t('系统名称已更新'));
|
2024-03-06 18:26:22 +08:00
|
|
|
|
} catch (error) {
|
2024-12-13 19:03:14 +08:00
|
|
|
|
console.error(t('系统名称更新失败'), error);
|
|
|
|
|
|
showError(t('系统名称更新失败'));
|
2024-03-06 18:26:22 +08:00
|
|
|
|
} finally {
|
2024-03-23 21:24:39 +08:00
|
|
|
|
setLoadingInput((loadingInput) => ({
|
|
|
|
|
|
...loadingInput,
|
|
|
|
|
|
SystemName: false,
|
|
|
|
|
|
}));
|
2024-03-06 18:26:22 +08:00
|
|
|
|
}
|
2023-05-14 19:29:02 +08:00
|
|
|
|
};
|
|
|
|
|
|
|
2024-03-06 18:26:22 +08:00
|
|
|
|
// 个性化设置 - Logo
|
2023-05-14 19:29:02 +08:00
|
|
|
|
const submitLogo = async () => {
|
2024-03-06 18:26:22 +08:00
|
|
|
|
try {
|
|
|
|
|
|
setLoadingInput((loadingInput) => ({ ...loadingInput, Logo: true }));
|
|
|
|
|
|
await updateOption('Logo', inputs.Logo);
|
|
|
|
|
|
showSuccess('Logo 已更新');
|
|
|
|
|
|
} catch (error) {
|
2024-03-15 16:05:33 +08:00
|
|
|
|
console.error('Logo 更新失败', error);
|
|
|
|
|
|
showError('Logo 更新失败');
|
2024-03-06 18:26:22 +08:00
|
|
|
|
} finally {
|
|
|
|
|
|
setLoadingInput((loadingInput) => ({ ...loadingInput, Logo: false }));
|
|
|
|
|
|
}
|
2023-05-14 19:29:02 +08:00
|
|
|
|
};
|
2024-03-06 18:26:22 +08:00
|
|
|
|
// 个性化设置 - 首页内容
|
2024-03-06 17:57:53 +08:00
|
|
|
|
const submitOption = async (key) => {
|
2024-03-06 18:26:22 +08:00
|
|
|
|
try {
|
2024-03-23 21:24:39 +08:00
|
|
|
|
setLoadingInput((loadingInput) => ({
|
|
|
|
|
|
...loadingInput,
|
|
|
|
|
|
HomePageContent: true,
|
|
|
|
|
|
}));
|
2024-03-06 18:26:22 +08:00
|
|
|
|
await updateOption(key, inputs[key]);
|
|
|
|
|
|
showSuccess('首页内容已更新');
|
|
|
|
|
|
} catch (error) {
|
2024-03-15 16:05:33 +08:00
|
|
|
|
console.error('首页内容更新失败', error);
|
|
|
|
|
|
showError('首页内容更新失败');
|
2024-03-06 18:26:22 +08:00
|
|
|
|
} finally {
|
2024-03-23 21:24:39 +08:00
|
|
|
|
setLoadingInput((loadingInput) => ({
|
|
|
|
|
|
...loadingInput,
|
|
|
|
|
|
HomePageContent: false,
|
|
|
|
|
|
}));
|
2024-03-06 18:26:22 +08:00
|
|
|
|
}
|
2024-03-06 17:57:53 +08:00
|
|
|
|
};
|
2024-03-06 18:26:22 +08:00
|
|
|
|
// 个性化设置 - 关于
|
2023-04-22 20:39:27 +08:00
|
|
|
|
const submitAbout = async () => {
|
2024-03-06 18:26:22 +08:00
|
|
|
|
try {
|
|
|
|
|
|
setLoadingInput((loadingInput) => ({ ...loadingInput, About: true }));
|
|
|
|
|
|
await updateOption('About', inputs.About);
|
|
|
|
|
|
showSuccess('关于内容已更新');
|
|
|
|
|
|
} catch (error) {
|
2024-03-15 16:05:33 +08:00
|
|
|
|
console.error('关于内容更新失败', error);
|
|
|
|
|
|
showError('关于内容更新失败');
|
2024-03-06 18:26:22 +08:00
|
|
|
|
} finally {
|
|
|
|
|
|
setLoadingInput((loadingInput) => ({ ...loadingInput, About: false }));
|
|
|
|
|
|
}
|
2023-04-22 20:39:27 +08:00
|
|
|
|
};
|
2024-03-06 18:26:22 +08:00
|
|
|
|
// 个性化设置 - 页脚
|
2024-03-06 17:57:53 +08:00
|
|
|
|
const submitFooter = async () => {
|
2024-03-06 18:26:22 +08:00
|
|
|
|
try {
|
|
|
|
|
|
setLoadingInput((loadingInput) => ({ ...loadingInput, Footer: true }));
|
|
|
|
|
|
await updateOption('Footer', inputs.Footer);
|
|
|
|
|
|
showSuccess('页脚内容已更新');
|
|
|
|
|
|
} catch (error) {
|
2024-03-15 16:05:33 +08:00
|
|
|
|
console.error('页脚内容更新失败', error);
|
|
|
|
|
|
showError('页脚内容更新失败');
|
2024-03-06 18:26:22 +08:00
|
|
|
|
} finally {
|
|
|
|
|
|
setLoadingInput((loadingInput) => ({ ...loadingInput, Footer: false }));
|
|
|
|
|
|
}
|
2023-05-13 21:27:49 +08:00
|
|
|
|
};
|
|
|
|
|
|
|
2023-04-22 20:39:27 +08:00
|
|
|
|
const checkUpdate = async () => {
|
2025-03-02 01:31:27 +08:00
|
|
|
|
try {
|
2025-04-04 12:00:38 +08:00
|
|
|
|
setLoadingInput((loadingInput) => ({
|
|
|
|
|
|
...loadingInput,
|
|
|
|
|
|
CheckUpdate: true,
|
|
|
|
|
|
}));
|
2025-03-02 01:31:27 +08:00
|
|
|
|
// Use a CORS proxy to avoid direct cross-origin requests to GitHub API
|
|
|
|
|
|
// Option 1: Use a public CORS proxy service
|
|
|
|
|
|
// const proxyUrl = 'https://cors-anywhere.herokuapp.com/';
|
|
|
|
|
|
// const res = await API.get(
|
|
|
|
|
|
// `${proxyUrl}https://api.github.com/repos/Calcium-Ion/new-api/releases/latest`,
|
|
|
|
|
|
// );
|
2025-04-04 12:00:38 +08:00
|
|
|
|
|
2025-03-02 01:31:27 +08:00
|
|
|
|
// Option 2: Use the JSON proxy approach which often works better with GitHub API
|
|
|
|
|
|
const res = await fetch(
|
|
|
|
|
|
'https://api.github.com/repos/Calcium-Ion/new-api/releases/latest',
|
|
|
|
|
|
{
|
|
|
|
|
|
headers: {
|
2025-04-04 12:00:38 +08:00
|
|
|
|
Accept: 'application/json',
|
2025-03-02 01:31:27 +08:00
|
|
|
|
'Content-Type': 'application/json',
|
|
|
|
|
|
// Adding User-Agent which is often required by GitHub API
|
2025-04-04 12:00:38 +08:00
|
|
|
|
'User-Agent': 'new-api-update-checker',
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
).then((response) => response.json());
|
|
|
|
|
|
|
2025-03-02 01:31:27 +08:00
|
|
|
|
// Option 3: Use a local proxy endpoint
|
|
|
|
|
|
// Create a cached version of the response to avoid frequent GitHub API calls
|
|
|
|
|
|
// const res = await API.get('/api/status/github-latest-release');
|
|
|
|
|
|
|
|
|
|
|
|
const { tag_name, body } = res;
|
|
|
|
|
|
if (tag_name === statusState?.status?.version) {
|
|
|
|
|
|
showSuccess(`已是最新版本:${tag_name}`);
|
|
|
|
|
|
} else {
|
|
|
|
|
|
setUpdateData({
|
|
|
|
|
|
tag_name: tag_name,
|
|
|
|
|
|
content: marked.parse(body),
|
|
|
|
|
|
});
|
|
|
|
|
|
setShowUpdateModal(true);
|
|
|
|
|
|
}
|
|
|
|
|
|
} catch (error) {
|
|
|
|
|
|
console.error('Failed to check for updates:', error);
|
|
|
|
|
|
showError('检查更新失败,请稍后再试');
|
|
|
|
|
|
} finally {
|
2025-04-04 12:00:38 +08:00
|
|
|
|
setLoadingInput((loadingInput) => ({
|
|
|
|
|
|
...loadingInput,
|
|
|
|
|
|
CheckUpdate: false,
|
|
|
|
|
|
}));
|
2023-04-22 20:39:27 +08:00
|
|
|
|
}
|
|
|
|
|
|
};
|
2024-03-06 17:57:53 +08:00
|
|
|
|
const getOptions = async () => {
|
|
|
|
|
|
const res = await API.get('/api/option/');
|
|
|
|
|
|
const { success, message, data } = res.data;
|
|
|
|
|
|
if (success) {
|
|
|
|
|
|
let newInputs = {};
|
|
|
|
|
|
data.forEach((item) => {
|
|
|
|
|
|
if (item.key in inputs) {
|
|
|
|
|
|
newInputs[item.key] = item.value;
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
setInputs(newInputs);
|
|
|
|
|
|
formAPISettingGeneral.current.setValues(newInputs);
|
|
|
|
|
|
formAPIPersonalization.current.setValues(newInputs);
|
|
|
|
|
|
} else {
|
|
|
|
|
|
showError(message);
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
|
2024-03-15 16:05:33 +08:00
|
|
|
|
useEffect(() => {
|
2024-03-06 17:57:53 +08:00
|
|
|
|
getOptions();
|
|
|
|
|
|
}, []);
|
|
|
|
|
|
|
2025-03-02 01:31:27 +08:00
|
|
|
|
// Function to open GitHub release page
|
|
|
|
|
|
const openGitHubRelease = () => {
|
2025-04-04 12:00:38 +08:00
|
|
|
|
window.open(
|
|
|
|
|
|
`https://github.com/Calcium-Ion/new-api/releases/tag/${updateData.tag_name}`,
|
|
|
|
|
|
'_blank',
|
|
|
|
|
|
);
|
2025-03-02 01:31:27 +08:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
const getStartTimeString = () => {
|
|
|
|
|
|
const timestamp = statusState?.status?.start_time;
|
|
|
|
|
|
return statusState.status ? timestamp2string(timestamp) : '';
|
|
|
|
|
|
};
|
|
|
|
|
|
|
2023-04-22 20:39:27 +08:00
|
|
|
|
return (
|
2024-03-15 16:05:33 +08:00
|
|
|
|
<Row>
|
2025-04-04 17:37:52 +08:00
|
|
|
|
<Col
|
|
|
|
|
|
span={24}
|
|
|
|
|
|
style={{
|
|
|
|
|
|
marginTop: '10px',
|
|
|
|
|
|
display: 'flex',
|
|
|
|
|
|
flexDirection: 'column',
|
|
|
|
|
|
gap: '10px',
|
|
|
|
|
|
}}
|
|
|
|
|
|
>
|
2025-03-02 01:31:27 +08:00
|
|
|
|
{/* 版本信息 */}
|
2025-04-04 17:37:52 +08:00
|
|
|
|
<Form>
|
|
|
|
|
|
<Card>
|
|
|
|
|
|
<Form.Section text={t('系统信息')}>
|
|
|
|
|
|
<Row>
|
|
|
|
|
|
<Col span={16}>
|
|
|
|
|
|
<Space>
|
|
|
|
|
|
<Text>
|
|
|
|
|
|
{t('当前版本')}:
|
|
|
|
|
|
{statusState?.status?.version || t('未知')}
|
|
|
|
|
|
</Text>
|
|
|
|
|
|
<Button
|
|
|
|
|
|
type='primary'
|
|
|
|
|
|
onClick={checkUpdate}
|
|
|
|
|
|
loading={loadingInput['CheckUpdate']}
|
|
|
|
|
|
>
|
|
|
|
|
|
{t('检查更新')}
|
|
|
|
|
|
</Button>
|
|
|
|
|
|
</Space>
|
|
|
|
|
|
</Col>
|
|
|
|
|
|
</Row>
|
|
|
|
|
|
<Row>
|
|
|
|
|
|
<Col span={16}>
|
2025-03-02 01:31:27 +08:00
|
|
|
|
<Text>
|
2025-04-04 17:37:52 +08:00
|
|
|
|
{t('启动时间')}:{getStartTimeString()}
|
2025-03-02 01:31:27 +08:00
|
|
|
|
</Text>
|
2025-04-04 17:37:52 +08:00
|
|
|
|
</Col>
|
|
|
|
|
|
</Row>
|
|
|
|
|
|
</Form.Section>
|
|
|
|
|
|
</Card>
|
2025-03-02 01:31:27 +08:00
|
|
|
|
</Form>
|
2024-03-06 17:57:53 +08:00
|
|
|
|
{/* 通用设置 */}
|
2024-03-23 21:24:39 +08:00
|
|
|
|
<Form
|
|
|
|
|
|
values={inputs}
|
|
|
|
|
|
getFormApi={(formAPI) => (formAPISettingGeneral.current = formAPI)}
|
|
|
|
|
|
>
|
2025-04-04 17:37:52 +08:00
|
|
|
|
<Card>
|
|
|
|
|
|
<Form.Section text={t('通用设置')}>
|
|
|
|
|
|
<Form.TextArea
|
|
|
|
|
|
label={t('公告')}
|
|
|
|
|
|
placeholder={t(
|
|
|
|
|
|
'在此输入新的公告内容,支持 Markdown & HTML 代码',
|
|
|
|
|
|
)}
|
|
|
|
|
|
field={'Notice'}
|
|
|
|
|
|
onChange={handleInputChange}
|
|
|
|
|
|
style={{ fontFamily: 'JetBrains Mono, Consolas' }}
|
|
|
|
|
|
autosize={{ minRows: 6, maxRows: 12 }}
|
|
|
|
|
|
/>
|
|
|
|
|
|
<Button onClick={submitNotice} loading={loadingInput['Notice']}>
|
|
|
|
|
|
{t('设置公告')}
|
|
|
|
|
|
</Button>
|
|
|
|
|
|
</Form.Section>
|
|
|
|
|
|
</Card>
|
2024-03-06 17:57:53 +08:00
|
|
|
|
</Form>
|
|
|
|
|
|
{/* 个性化设置 */}
|
2024-03-23 21:24:39 +08:00
|
|
|
|
<Form
|
|
|
|
|
|
values={inputs}
|
|
|
|
|
|
getFormApi={(formAPI) => (formAPIPersonalization.current = formAPI)}
|
|
|
|
|
|
>
|
2025-04-04 17:37:52 +08:00
|
|
|
|
<Card>
|
|
|
|
|
|
<Form.Section text={t('个性化设置')}>
|
|
|
|
|
|
<Form.Input
|
|
|
|
|
|
label={t('系统名称')}
|
|
|
|
|
|
placeholder={t('在此输入系统名称')}
|
|
|
|
|
|
field={'SystemName'}
|
|
|
|
|
|
onChange={handleInputChange}
|
|
|
|
|
|
/>
|
|
|
|
|
|
<Button
|
|
|
|
|
|
onClick={submitSystemName}
|
|
|
|
|
|
loading={loadingInput['SystemName']}
|
|
|
|
|
|
>
|
|
|
|
|
|
{t('设置系统名称')}
|
|
|
|
|
|
</Button>
|
|
|
|
|
|
<Form.Input
|
|
|
|
|
|
label={t('Logo 图片地址')}
|
|
|
|
|
|
placeholder={t('在此输入 Logo 图片地址')}
|
|
|
|
|
|
field={'Logo'}
|
|
|
|
|
|
onChange={handleInputChange}
|
|
|
|
|
|
/>
|
|
|
|
|
|
<Button onClick={submitLogo} loading={loadingInput['Logo']}>
|
|
|
|
|
|
{t('设置 Logo')}
|
|
|
|
|
|
</Button>
|
|
|
|
|
|
<Form.TextArea
|
|
|
|
|
|
label={t('首页内容')}
|
|
|
|
|
|
placeholder={t(
|
|
|
|
|
|
'在此输入首页内容,支持 Markdown & HTML 代码,设置后首页的状态信息将不再显示。如果输入的是一个链接,则会使用该链接作为 iframe 的 src 属性,这允许你设置任意网页作为首页',
|
|
|
|
|
|
)}
|
|
|
|
|
|
field={'HomePageContent'}
|
|
|
|
|
|
onChange={handleInputChange}
|
|
|
|
|
|
style={{ fontFamily: 'JetBrains Mono, Consolas' }}
|
|
|
|
|
|
autosize={{ minRows: 6, maxRows: 12 }}
|
|
|
|
|
|
/>
|
|
|
|
|
|
<Button
|
|
|
|
|
|
onClick={() => submitOption('HomePageContent')}
|
|
|
|
|
|
loading={loadingInput['HomePageContent']}
|
|
|
|
|
|
>
|
|
|
|
|
|
{t('设置首页内容')}
|
|
|
|
|
|
</Button>
|
|
|
|
|
|
<Form.TextArea
|
|
|
|
|
|
label={t('关于')}
|
|
|
|
|
|
placeholder={t(
|
|
|
|
|
|
'在此输入新的关于内容,支持 Markdown & HTML 代码。如果输入的是一个链接,则会使用该链接作为 iframe 的 src 属性,这允许你设置任意网页作为关于页面',
|
|
|
|
|
|
)}
|
|
|
|
|
|
field={'About'}
|
|
|
|
|
|
onChange={handleInputChange}
|
|
|
|
|
|
style={{ fontFamily: 'JetBrains Mono, Consolas' }}
|
|
|
|
|
|
autosize={{ minRows: 6, maxRows: 12 }}
|
|
|
|
|
|
/>
|
|
|
|
|
|
<Button onClick={submitAbout} loading={loadingInput['About']}>
|
|
|
|
|
|
{t('设置关于')}
|
|
|
|
|
|
</Button>
|
|
|
|
|
|
{/* */}
|
|
|
|
|
|
<Banner
|
|
|
|
|
|
fullMode={false}
|
|
|
|
|
|
type='info'
|
|
|
|
|
|
description={t(
|
|
|
|
|
|
'移除 One API 的版权标识必须首先获得授权,项目维护需要花费大量精力,如果本项目对你有意义,请主动支持本项目',
|
|
|
|
|
|
)}
|
|
|
|
|
|
closeIcon={null}
|
|
|
|
|
|
style={{ marginTop: 15 }}
|
|
|
|
|
|
/>
|
|
|
|
|
|
<Form.Input
|
|
|
|
|
|
label={t('页脚')}
|
|
|
|
|
|
placeholder={t(
|
|
|
|
|
|
'在此输入新的页脚,留空则使用默认页脚,支持 HTML 代码',
|
|
|
|
|
|
)}
|
|
|
|
|
|
field={'Footer'}
|
|
|
|
|
|
onChange={handleInputChange}
|
|
|
|
|
|
/>
|
|
|
|
|
|
<Button onClick={submitFooter} loading={loadingInput['Footer']}>
|
|
|
|
|
|
{t('设置页脚')}
|
|
|
|
|
|
</Button>
|
|
|
|
|
|
</Form.Section>
|
|
|
|
|
|
</Card>
|
2023-04-22 20:39:27 +08:00
|
|
|
|
</Form>
|
2024-03-06 17:57:53 +08:00
|
|
|
|
</Col>
|
2025-03-02 01:31:27 +08:00
|
|
|
|
<Modal
|
|
|
|
|
|
title={t('新版本') + ':' + updateData.tag_name}
|
|
|
|
|
|
visible={showUpdateModal}
|
|
|
|
|
|
onCancel={() => setShowUpdateModal(false)}
|
|
|
|
|
|
footer={[
|
2025-04-04 12:00:38 +08:00
|
|
|
|
<Button
|
|
|
|
|
|
key='details'
|
|
|
|
|
|
type='primary'
|
2025-03-02 01:31:27 +08:00
|
|
|
|
onClick={() => {
|
|
|
|
|
|
setShowUpdateModal(false);
|
|
|
|
|
|
openGitHubRelease();
|
|
|
|
|
|
}}
|
|
|
|
|
|
>
|
|
|
|
|
|
{t('详情')}
|
2025-04-04 12:00:38 +08:00
|
|
|
|
</Button>,
|
2025-03-02 01:31:27 +08:00
|
|
|
|
]}
|
|
|
|
|
|
>
|
|
|
|
|
|
<div dangerouslySetInnerHTML={{ __html: updateData.content }}></div>
|
|
|
|
|
|
</Modal>
|
2024-03-15 16:05:33 +08:00
|
|
|
|
</Row>
|
2023-04-22 20:39:27 +08:00
|
|
|
|
);
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
export default OtherSetting;
|