From a3ceae4a8669b9c7a25d392601809addae2e14c2 Mon Sep 17 00:00:00 2001 From: "1808837298@qq.com" <1808837298@qq.com> Date: Sun, 2 Mar 2025 01:31:27 +0800 Subject: [PATCH] feat: Enhance update checking and system information display - Add version and startup time display in OtherSetting component - Implement robust GitHub release update checking mechanism - Add error handling for update check process - Update Modal component for displaying update information - Add new translations for version and system information --- web/src/components/OtherSetting.js | 140 ++++++++++++++++++++--------- web/src/i18n/locales/en.json | 17 +++- 2 files changed, 115 insertions(+), 42 deletions(-) diff --git a/web/src/components/OtherSetting.js b/web/src/components/OtherSetting.js index dad79fd1..e3295fb1 100644 --- a/web/src/components/OtherSetting.js +++ b/web/src/components/OtherSetting.js @@ -1,8 +1,10 @@ -import React, { useEffect, useRef, useState } from 'react'; -import { Banner, Button, Col, Form, Row } from '@douyinfe/semi-ui'; -import { API, showError, showSuccess } from '../helpers'; +import React, { useContext, useEffect, useRef, useState } from 'react'; +import { Banner, Button, Col, Form, Row, Modal, Space } from '@douyinfe/semi-ui'; +import { API, showError, showSuccess, timestamp2string } from '../helpers'; import { marked } from 'marked'; import { useTranslation } from 'react-i18next'; +import { StatusContext } from '../context/Status/index.js'; +import Text from '@douyinfe/semi-ui/lib/es/typography/text'; const OtherSetting = () => { const { t } = useTranslation(); @@ -16,6 +18,7 @@ const OtherSetting = () => { }); let [loading, setLoading] = useState(false); const [showUpdateModal, setShowUpdateModal] = useState(false); + const [statusState, statusDispatch] = useContext(StatusContext); const [updateData, setUpdateData] = useState({ tag_name: '', content: '', @@ -43,6 +46,7 @@ const OtherSetting = () => { HomePageContent: false, About: false, Footer: false, + CheckUpdate: false }); const handleInputChange = async (value, e) => { const name = e.target.id; @@ -145,23 +149,48 @@ const OtherSetting = () => { } }; - const openGitHubRelease = () => { - window.location = 'https://github.com/songquanpeng/one-api/releases/latest'; - }; - const checkUpdate = async () => { - const res = await API.get( - 'https://api.github.com/repos/songquanpeng/one-api/releases/latest', - ); - const { tag_name, body } = res.data; - if (tag_name === process.env.REACT_APP_VERSION) { - showSuccess(`已是最新版本:${tag_name}`); - } else { - setUpdateData({ - tag_name: tag_name, - content: marked.parse(body), - }); - setShowUpdateModal(true); + try { + setLoadingInput((loadingInput) => ({ ...loadingInput, CheckUpdate: true })); + // 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`, + // ); + + // 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: { + 'Accept': 'application/json', + 'Content-Type': 'application/json', + // Adding User-Agent which is often required by GitHub API + 'User-Agent': 'new-api-update-checker' + } + } + ).then(response => response.json()); + + // 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 { + setLoadingInput((loadingInput) => ({ ...loadingInput, CheckUpdate: false })); } }; const getOptions = async () => { @@ -186,9 +215,41 @@ const OtherSetting = () => { getOptions(); }, []); + // Function to open GitHub release page + const openGitHubRelease = () => { + window.open(`https://github.com/Calcium-Ion/new-api/releases/tag/${updateData.tag_name}`, '_blank'); + }; + + const getStartTimeString = () => { + const timestamp = statusState?.status?.start_time; + return statusState.status ? timestamp2string(timestamp) : ''; + }; + return ( + {/* 版本信息 */} +
+ + + + + + {t('当前版本')}:{statusState?.status?.version || t('未知')} + + + + + + + + {t('启动时间')}:{getStartTimeString()} + + + +
{/* 通用设置 */}
{
- {/* setShowUpdateModal(false)}*/} - {/* onOpen={() => setShowUpdateModal(true)}*/} - {/* open={showUpdateModal}*/} - {/*>*/} - {/* 新版本:{updateData.tag_name}*/} - {/* */} - {/* */} - {/*
*/} - {/*
*/} - {/*
*/} - {/* */} - {/* */} - {/* {*/} - {/* setShowUpdateModal(false);*/} - {/* openGitHubRelease();*/} - {/* }}*/} - {/* />*/} - {/* */} - {/**/} + setShowUpdateModal(false)} + footer={[ + + ]} + > +
+
); }; diff --git a/web/src/i18n/locales/en.json b/web/src/i18n/locales/en.json index 750f762f..3c7d368c 100644 --- a/web/src/i18n/locales/en.json +++ b/web/src/i18n/locales/en.json @@ -1320,5 +1320,20 @@ "模型倍率和补全倍率同时设置": "Both model ratio and completion ratio are set", "自用模式": "Self-use mode", "开启后不限制:必须设置模型倍率": "After enabling, no limit: must set model ratio", - "演示站点模式": "Demo site mode" + "演示站点模式": "Demo site mode", + "当前版本": "Current version", + "Gemini设置": "Gemini settings", + "Gemini安全设置": "Gemini safety settings", + "default为默认设置,可单独设置每个分类的安全等级": "\"default\" is the default setting, and each category can be set separately", + "Gemini版本设置": "Gemini version settings", + "default为默认设置,可单独设置每个模型的版本": "\"default\" is the default setting, and each model can be set separately", + "Claude设置": "Claude settings", + "Claude请求头覆盖": "Claude request header override", + "示例": "Example", + "缺省 MaxTokens": "Default MaxTokens", + "启用Claude思考适配(-thinking后缀)": "Enable Claude thinking adaptation (-thinking suffix)", + "Claude思考适配 BudgetTokens = MaxTokens * BudgetTokens 百分比": "Claude thinking adaptation BudgetTokens = MaxTokens * BudgetTokens percentage", + "思考适配 BudgetTokens 百分比": "Thinking adaptation BudgetTokens percentage", + "0.1-1之间的小数": "Decimal between 0.1 and 1", + "模型相关设置": "Model related settings" }