فهرست منبع

Merge pull request #2582 from seefs001/fix/tips

fix: add tips for model management and channel testing
Seefs 2 ماه پیش
والد
کامیت
9e61338a6f

+ 9 - 3
web/src/components/auth/LoginForm.jsx

@@ -59,6 +59,11 @@ import { SiDiscord }from 'react-icons/si';
 const LoginForm = () => {
   let navigate = useNavigate();
   const { t } = useTranslation();
+  const githubButtonTextKeyByState = {
+    idle: '使用 GitHub 继续',
+    redirecting: '正在跳转 GitHub...',
+    timeout: '请求超时,请刷新页面后重新发起 GitHub 登录',
+  };
   const [inputs, setInputs] = useState({
     username: '',
     password: '',
@@ -90,9 +95,10 @@ const LoginForm = () => {
   const [agreedToTerms, setAgreedToTerms] = useState(false);
   const [hasUserAgreement, setHasUserAgreement] = useState(false);
   const [hasPrivacyPolicy, setHasPrivacyPolicy] = useState(false);
-  const [githubButtonText, setGithubButtonText] = useState('使用 GitHub 继续');
+  const [githubButtonState, setGithubButtonState] = useState('idle');
   const [githubButtonDisabled, setGithubButtonDisabled] = useState(false);
   const githubTimeoutRef = useRef(null);
+  const githubButtonText = t(githubButtonTextKeyByState[githubButtonState]);
 
   const logo = getLogo();
   const systemName = getSystemName();
@@ -284,13 +290,13 @@ const LoginForm = () => {
     }
     setGithubLoading(true);
     setGithubButtonDisabled(true);
-    setGithubButtonText(t('正在跳转 GitHub...'));
+    setGithubButtonState('redirecting');
     if (githubTimeoutRef.current) {
       clearTimeout(githubTimeoutRef.current);
     }
     githubTimeoutRef.current = setTimeout(() => {
       setGithubLoading(false);
-      setGithubButtonText(t('请求超时,请刷新页面后重新发起 GitHub 登录'));
+      setGithubButtonState('timeout');
       setGithubButtonDisabled(true);
     }, 20000);
     try {

+ 9 - 3
web/src/components/auth/RegisterForm.jsx

@@ -57,6 +57,11 @@ import { SiDiscord } from 'react-icons/si';
 const RegisterForm = () => {
   let navigate = useNavigate();
   const { t } = useTranslation();
+  const githubButtonTextKeyByState = {
+    idle: '使用 GitHub 继续',
+    redirecting: '正在跳转 GitHub...',
+    timeout: '请求超时,请刷新页面后重新发起 GitHub 登录',
+  };
   const [inputs, setInputs] = useState({
     username: '',
     password: '',
@@ -88,9 +93,10 @@ const RegisterForm = () => {
   const [agreedToTerms, setAgreedToTerms] = useState(false);
   const [hasUserAgreement, setHasUserAgreement] = useState(false);
   const [hasPrivacyPolicy, setHasPrivacyPolicy] = useState(false);
-  const [githubButtonText, setGithubButtonText] = useState('使用 GitHub 继续');
+  const [githubButtonState, setGithubButtonState] = useState('idle');
   const [githubButtonDisabled, setGithubButtonDisabled] = useState(false);
   const githubTimeoutRef = useRef(null);
+  const githubButtonText = t(githubButtonTextKeyByState[githubButtonState]);
 
   const logo = getLogo();
   const systemName = getSystemName();
@@ -251,13 +257,13 @@ const RegisterForm = () => {
     }
     setGithubLoading(true);
     setGithubButtonDisabled(true);
-    setGithubButtonText(t('正在跳转 GitHub...'));
+    setGithubButtonState('redirecting');
     if (githubTimeoutRef.current) {
       clearTimeout(githubTimeoutRef.current);
     }
     githubTimeoutRef.current = setTimeout(() => {
       setGithubLoading(false);
-      setGithubButtonText(t('请求超时,请刷新页面后重新发起 GitHub 登录'));
+      setGithubButtonState('timeout');
       setGithubButtonDisabled(true);
     }, 20000);
     try {

+ 5 - 0
web/src/components/table/channels/modals/ModelTestModal.jsx

@@ -265,6 +265,11 @@ const ModelTestModal = ({
               placeholder={t('选择端点类型')}
             />
           </div>
+          <Typography.Text type='tertiary' size='small' className='block mb-2'>
+            {t(
+              '说明:本页测试为非流式请求;若渠道仅支持流式返回,可能出现测试失败,请以实际使用为准。',
+            )}
+          </Typography.Text>
 
           {/* 搜索与操作按钮 */}
           <div className='flex items-center justify-end gap-2 w-full mb-2'>

+ 64 - 1
web/src/components/table/models/index.jsx

@@ -17,7 +17,9 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
 For commercial licensing, please contact support@quantumnous.com
 */
 
-import React from 'react';
+import React, { useState } from 'react';
+import { Banner, Button, Modal } from '@douyinfe/semi-ui';
+import { IconAlertTriangle, IconClose } from '@douyinfe/semi-icons';
 import CardPro from '../../common/ui/CardPro';
 import ModelsTable from './ModelsTable';
 import ModelsActions from './ModelsActions';
@@ -29,6 +31,9 @@ import { useModelsData } from '../../../hooks/models/useModelsData';
 import { useIsMobile } from '../../../hooks/common/useIsMobile';
 import { createCardProPagination } from '../../../helpers/utils';
 
+const MARKETPLACE_DISPLAY_NOTICE_STORAGE_KEY =
+  'models_marketplace_display_notice_dismissed';
+
 const ModelsPage = () => {
   const modelsData = useModelsData();
   const isMobile = useIsMobile();
@@ -71,6 +76,37 @@ const ModelsPage = () => {
     t,
   } = modelsData;
 
+  const [showMarketplaceDisplayNotice, setShowMarketplaceDisplayNotice] =
+    useState(() => {
+      try {
+        return (
+          localStorage.getItem(MARKETPLACE_DISPLAY_NOTICE_STORAGE_KEY) !== '1'
+        );
+      } catch (_) {
+        return true;
+      }
+    });
+
+  const confirmCloseMarketplaceDisplayNotice = () => {
+    Modal.confirm({
+      title: t('确认关闭提示'),
+      content: t(
+        '关闭后将不再显示此提示(仅对当前浏览器生效)。确定要关闭吗?',
+      ),
+      okText: t('关闭提示'),
+      cancelText: t('取消'),
+      okButtonProps: {
+        type: 'danger',
+      },
+      onOk: () => {
+        try {
+          localStorage.setItem(MARKETPLACE_DISPLAY_NOTICE_STORAGE_KEY, '1');
+        } catch (_) {}
+        setShowMarketplaceDisplayNotice(false);
+      },
+    });
+  };
+
   return (
     <>
       <EditModelModal
@@ -94,6 +130,33 @@ const ModelsPage = () => {
         }}
       />
 
+      {showMarketplaceDisplayNotice ? (
+        <div style={{ position: 'relative', marginBottom: 12 }}>
+          <Banner
+            type='warning'
+            closeIcon={null}
+            icon={
+              <IconAlertTriangle
+                size='large'
+                style={{ color: 'var(--semi-color-warning)' }}
+              />
+            }
+            description={t(
+              '提示:此处配置仅用于控制「模型广场」对用户的展示效果,不会影响模型的实际调用与路由。若需配置真实调用行为,请前往「渠道管理」进行设置。',
+            )}
+            style={{ marginBottom: 0 }}
+          />
+          <Button
+            theme='borderless'
+            size='small'
+            type='tertiary'
+            icon={<IconClose aria-hidden={true} />}
+            onClick={confirmCloseMarketplaceDisplayNotice}
+            style={{ position: 'absolute', top: 8, right: 8 }}
+            aria-label={t('关闭')}
+          />
+        </div>
+      ) : null}
       <CardPro
         type='type3'
         tabsArea={<ModelsTabs {...modelsData} />}

+ 18 - 2
web/src/components/table/models/modals/EditModelModal.jsx

@@ -31,9 +31,10 @@ import {
   Avatar,
   Col,
   Row,
+  Tooltip,
 } from '@douyinfe/semi-ui';
 import { Save, X, FileText } from 'lucide-react';
-import { IconLink } from '@douyinfe/semi-icons';
+import { IconInfoCircle, IconLink } from '@douyinfe/semi-icons';
 import { API, showError, showSuccess } from '../../../../helpers';
 import { useTranslation } from 'react-i18next';
 import { useIsMobile } from '../../../../hooks/common/useIsMobile';
@@ -447,7 +448,22 @@ const EditModelModal = (props) => {
                   <Col span={24}>
                     <JSONEditor
                       field='endpoints'
-                      label={t('端点映射')}
+                      label={
+                        <span className='inline-flex items-center gap-2'>
+                          <span>{t('端点映射')}</span>
+                          <Tooltip
+                            position='top'
+                            content={t(
+                              '提示:端点映射仅用于模型广场展示,不会影响模型真实调用。如需配置真实调用,请前往「渠道管理」。',
+                            )}
+                          >
+                            <IconInfoCircle
+                              size='small'
+                              className='text-gray-400 cursor-help'
+                            />
+                          </Tooltip>
+                        </span>
+                      }
                       placeholder={
                         '{\n  "openai": {"path": "/v1/chat/completions", "method": "POST"}\n}'
                       }

+ 7 - 1
web/src/i18n/locales/en.json

@@ -2582,6 +2582,12 @@
     "签到奖励的最小额度": "Minimum quota for check-in rewards",
     "签到最大额度": "Maximum check-in quota",
     "签到奖励的最大额度": "Maximum quota for check-in rewards",
-    "保存签到设置": "Save check-in settings"
+    "保存签到设置": "Save check-in settings",
+    "提示:此处配置仅用于控制「模型广场」对用户的展示效果,不会影响模型的实际调用与路由。若需配置真实调用行为,请前往「渠道管理」进行设置。": "Notice: This configuration only affects how models are displayed in the Model Marketplace and does not impact actual model invocation or routing. To configure real invocation behavior, please go to Channel Management.",
+    "确认关闭提示": "Confirm close",
+    "关闭后将不再显示此提示(仅对当前浏览器生效)。确定要关闭吗?": "After closing, this notice will no longer be shown (only for this browser). Are you sure you want to close it?",
+    "关闭提示": "Close notice",
+    "说明:本页测试为非流式请求;若渠道仅支持流式返回,可能出现测试失败,请以实际使用为准。": "Note: Tests on this page use non-streaming requests. If a channel only supports streaming responses, tests may fail. Please rely on actual usage.",
+    "提示:端点映射仅用于模型广场展示,不会影响模型真实调用。如需配置真实调用,请前往「渠道管理」。": "Notice: Endpoint mapping is for Model Marketplace display only and does not affect real model invocation. To configure real invocation, please go to Channel Management."
   }
 }

+ 7 - 1
web/src/i18n/locales/fr.json

@@ -2593,6 +2593,12 @@
     "签到奖励的最小额度": "Quota minimum pour les récompenses d'enregistrement",
     "签到最大额度": "Quota maximum d'enregistrement",
     "签到奖励的最大额度": "Quota maximum pour les récompenses d'enregistrement",
-    "保存签到设置": "Enregistrer les paramètres d'enregistrement"
+    "保存签到设置": "Enregistrer les paramètres d'enregistrement",
+    "提示:此处配置仅用于控制「模型广场」对用户的展示效果,不会影响模型的实际调用与路由。若需配置真实调用行为,请前往「渠道管理」进行设置。": "Remarque : cette configuration n'affecte que l'affichage des modèles dans la place de marché des modèles et n'a aucun impact sur l'invocation ou le routage réels. Pour configurer le comportement réel des appels, veuillez aller dans « Gestion des canaux ».",
+    "确认关闭提示": "Confirmer la fermeture",
+    "关闭后将不再显示此提示(仅对当前浏览器生效)。确定要关闭吗?": "Après fermeture, cet avertissement ne sera plus affiché (uniquement pour ce navigateur). Voulez-vous vraiment le fermer ?",
+    "关闭提示": "Fermer l’avertissement",
+    "说明:本页测试为非流式请求;若渠道仅支持流式返回,可能出现测试失败,请以实际使用为准。": "Remarque : les tests sur cette page utilisent des requêtes non-streaming. Si un canal ne prend en charge que les réponses en streaming, les tests peuvent échouer. Veuillez vous référer à l’usage réel.",
+    "提示:端点映射仅用于模型广场展示,不会影响模型真实调用。如需配置真实调用,请前往「渠道管理」。": "Remarque : la correspondance des endpoints sert uniquement à l’affichage dans la place de marché des modèles et n’affecte pas l’invocation réelle. Pour configurer l’invocation réelle, veuillez aller dans « Gestion des canaux »."
   }
 }

+ 7 - 2
web/src/i18n/locales/ja.json

@@ -2556,7 +2556,6 @@
     "默认补全倍率": "デフォルト補完倍率",
     "每日签到": "毎日のチェックイン",
     "今日已签到,累计签到": "本日チェックイン済み、累計チェックイン",
-    "天": "日",
     "每日签到可获得随机额度奖励": "毎日のチェックインでランダムなクォータ報酬を獲得できます",
     "今日已签到": "本日チェックイン済み",
     "立即签到": "今すぐチェックイン",
@@ -2577,6 +2576,12 @@
     "签到奖励的最小额度": "チェックイン報酬の最小クォータ",
     "签到最大额度": "チェックイン最大クォータ",
     "签到奖励的最大额度": "チェックイン報酬の最大クォータ",
-    "保存签到设置": "チェックイン設定を保存"
+    "保存签到设置": "チェックイン設定を保存",
+    "提示:此处配置仅用于控制「模型广场」对用户的展示效果,不会影响模型的实际调用与路由。若需配置真实调用行为,请前往「渠道管理」进行设置。": "注意: ここでの設定は「モデル広場」での表示にのみ影響し、実際の呼び出しやルーティングには影響しません。実際の呼び出しを設定する場合は、「チャネル管理」で設定してください。",
+    "确认关闭提示": "閉じる確認",
+    "关闭后将不再显示此提示(仅对当前浏览器生效)。确定要关闭吗?": "閉じると、このお知らせは今後表示されません(このブラウザのみ)。閉じてもよろしいですか?",
+    "关闭提示": "お知らせを閉じる",
+    "说明:本页测试为非流式请求;若渠道仅支持流式返回,可能出现测试失败,请以实际使用为准。": "注意: このページのテストは非ストリーミングリクエストです。チャネルがストリーミング応答のみ対応の場合、テストが失敗することがあります。実際の利用結果を優先してください。",
+    "提示:端点映射仅用于模型广场展示,不会影响模型真实调用。如需配置真实调用,请前往「渠道管理」。": "注意: エンドポイントマッピングは「モデル広場」での表示専用で、実際の呼び出しには影響しません。実際の呼び出し設定は「チャネル管理」で行ってください。"
   }
 }

+ 7 - 2
web/src/i18n/locales/ru.json

@@ -2586,7 +2586,6 @@
     "默认补全倍率": "Default completion ratio",
     "每日签到": "Ежедневная регистрация",
     "今日已签到,累计签到": "Зарегистрирован сегодня, всего регистраций",
-    "天": "дней",
     "每日签到可获得随机额度奖励": "Ежедневная регистрация награждает случайной квотой",
     "今日已签到": "Зарегистрирован сегодня",
     "立即签到": "Зарегистрироваться сейчас",
@@ -2607,6 +2606,12 @@
     "签到奖励的最小额度": "Минимальная квота для наград за регистрацию",
     "签到最大额度": "Максимальная квота регистрации",
     "签到奖励的最大额度": "Максимальная квота для наград за регистрацию",
-    "保存签到设置": "Сохранить настройки регистрации"
+    "保存签到设置": "Сохранить настройки регистрации",
+    "提示:此处配置仅用于控制「模型广场」对用户的展示效果,不会影响模型的实际调用与路由。若需配置真实调用行为,请前往「渠道管理」进行设置。": "Примечание: эта настройка влияет только на отображение моделей в «Маркетплейсе моделей» и не влияет на фактический вызов или маршрутизацию. Чтобы настроить реальное поведение вызовов, перейдите в «Управление каналами».",
+    "确认关闭提示": "Подтвердить закрытие",
+    "关闭后将不再显示此提示(仅对当前浏览器生效)。确定要关闭吗?": "После закрытия это уведомление больше не будет показываться (только в этом браузере). Закрыть?",
+    "关闭提示": "Закрыть уведомление",
+    "说明:本页测试为非流式请求;若渠道仅支持流式返回,可能出现测试失败,请以实际使用为准。": "Примечание: тесты на этой странице используют нестриминговые запросы. Если канал поддерживает только стриминговые ответы, тест может завершиться неудачей. Ориентируйтесь на реальное использование.",
+    "提示:端点映射仅用于模型广场展示,不会影响模型真实调用。如需配置真实调用,请前往「渠道管理」。": "Примечание: сопоставление endpoint'ов используется только для отображения в «Маркетплейсе моделей» и не влияет на реальный вызов. Чтобы настроить реальное поведение вызовов, перейдите в «Управление каналами»."
   }
 }

+ 7 - 3
web/src/i18n/locales/vi.json

@@ -1547,7 +1547,6 @@
     "此项可选,用于覆盖请求头参数": "Tùy chọn, được sử dụng để ghi đè tham số tiêu đề yêu cầu.",
     "此项可选,用于通过自定义API地址来进行 API 调用,末尾不要带/v1和/": "Tùy chọn cho các cuộc gọi API thông qua địa chỉ API tùy chỉnh, không thêm /v1 và / ở cuối",
     "每容器GPU数": "GPUs per Container",
-    "每日签到": "Đăng nhập hàng ngày",
     "每日签到获得": "Nhận được từ đăng nhập hàng ngày",
     "每隔多少分钟测试一次所有通道": "Bao nhiêu phút kiểm tra tất cả các kênh một lần",
     "比率": "Tỷ lệ",
@@ -3137,7 +3136,6 @@
     "默认补全倍率": "Tỷ lệ hoàn thành mặc định",
     "每日签到": "Đăng nhập hàng ngày",
     "今日已签到,累计签到": "Đã đăng nhập hôm nay, tổng số lần đăng nhập",
-    "天": "ngày",
     "每日签到可获得随机额度奖励": "Đăng nhập hàng ngày để nhận phần thưởng hạn mức ngẫu nhiên",
     "今日已签到": "Đã đăng nhập hôm nay",
     "立即签到": "Đăng nhập ngay",
@@ -3158,6 +3156,12 @@
     "签到奖励的最小额度": "Hạn mức tối thiểu cho phần thưởng đăng nhập",
     "签到最大额度": "Hạn mức đăng nhập tối đa",
     "签到奖励的最大额度": "Hạn mức tối đa cho phần thưởng đăng nhập",
-    "保存签到设置": "Lưu cài đặt đăng nhập"
+    "保存签到设置": "Lưu cài đặt đăng nhập",
+    "提示:此处配置仅用于控制「模型广场」对用户的展示效果,不会影响模型的实际调用与路由。若需配置真实调用行为,请前往「渠道管理」进行设置。": "Lưu ý: Cấu hình tại đây chỉ ảnh hưởng đến cách hiển thị trong \"Chợ mô hình\" và không ảnh hưởng đến việc gọi hoặc định tuyến thực tế. Nếu cần cấu hình hành vi gọi thực tế, vui lòng thiết lập trong \"Quản lý kênh\".",
+    "确认关闭提示": "Xác nhận đóng",
+    "关闭后将不再显示此提示(仅对当前浏览器生效)。确定要关闭吗?": "Sau khi đóng, thông báo này sẽ không còn hiển thị nữa (chỉ với trình duyệt này). Bạn có chắc muốn đóng không?",
+    "关闭提示": "Đóng thông báo",
+    "说明:本页测试为非流式请求;若渠道仅支持流式返回,可能出现测试失败,请以实际使用为准。": "Lưu ý: Bài kiểm tra trên trang này sử dụng yêu cầu không streaming. Nếu kênh chỉ hỗ trợ phản hồi streaming, bài kiểm tra có thể thất bại. Vui lòng dựa vào sử dụng thực tế.",
+    "提示:端点映射仅用于模型广场展示,不会影响模型真实调用。如需配置真实调用,请前往「渠道管理」。": "Lưu ý: Ánh xạ endpoint chỉ dùng để hiển thị trong \"Chợ mô hình\" và không ảnh hưởng đến việc gọi thực tế. Để cấu hình gọi thực tế, vui lòng vào \"Quản lý kênh\"."
   }
 }

+ 7 - 1
web/src/i18n/locales/zh.json

@@ -2568,6 +2568,12 @@
     "签到奖励的最小额度": "签到奖励的最小额度",
     "签到最大额度": "签到最大额度",
     "签到奖励的最大额度": "签到奖励的最大额度",
-    "保存签到设置": "保存签到设置"
+    "保存签到设置": "保存签到设置",
+    "提示:此处配置仅用于控制「模型广场」对用户的展示效果,不会影响模型的实际调用与路由。若需配置真实调用行为,请前往「渠道管理」进行设置。": "提示:此处配置仅用于控制「模型广场」对用户的展示效果,不会影响模型的实际调用与路由。若需配置真实调用行为,请前往「渠道管理」进行设置。",
+    "确认关闭提示": "确认关闭提示",
+    "关闭后将不再显示此提示(仅对当前浏览器生效)。确定要关闭吗?": "关闭后将不再显示此提示(仅对当前浏览器生效)。确定要关闭吗?",
+    "关闭提示": "关闭提示",
+    "说明:本页测试为非流式请求;若渠道仅支持流式返回,可能出现测试失败,请以实际使用为准。": "说明:本页测试为非流式请求;若渠道仅支持流式返回,可能出现测试失败,请以实际使用为准。",
+    "提示:端点映射仅用于模型广场展示,不会影响模型真实调用。如需配置真实调用,请前往「渠道管理」。": "提示:端点映射仅用于模型广场展示,不会影响模型真实调用。如需配置真实调用,请前往「渠道管理」。"
   }
 }