From 94506bee994e9b686c7447cb7784a3938d766a2d Mon Sep 17 00:00:00 2001 From: t0ng7u Date: Wed, 6 Aug 2025 03:29:45 +0800 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20feat(models):=20Revamp=20EditModelM?= =?UTF-8?q?odal=20UI=20and=20UX?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This commit significantly refactors the `EditModelModal` component to streamline the user interface and enhance usability, aligning it with the interaction patterns found elsewhere in the application. - **Consolidated Layout:** Merged the "Vendor Information" and "Feature Configuration" sections into a single "Basic Information" card. This simplifies the form, reduces clutter, and makes all settings accessible in one view. - **Improved Prefill Groups:** Replaced the separate `Select` dropdowns for tag and endpoint groups with a more intuitive button-based system within the `extraText` of the `TagInput` components. - **Additive Button Logic:** The prefill group buttons now operate in an additive mode. Users can click multiple group buttons to incrementally add tags or endpoints, with duplicates being automatically handled. - **Clear Functionality:** Added "Clear" buttons for both tags and endpoints, allowing users to easily reset the fields. - **Code Cleanup:** Removed the unused `endpointOptions` constant and unnecessary icon imports (`Building`, `Settings`) to keep the codebase clean. --- .../channels/modals/EditChannelModal.jsx | 40 ++--- .../table/channels/modals/ModelTestModal.jsx | 2 +- .../components/table/models/ModelsActions.jsx | 47 +++++- .../components/SelectionNotification.jsx | 44 +++++- web/src/components/table/models/index.jsx | 2 + .../table/models/modals/EditModelModal.jsx | 149 ++++++++---------- .../models/modals/MissingModelsModal.jsx | 2 +- web/src/hooks/models/useModelsData.js | 1 + 8 files changed, 171 insertions(+), 116 deletions(-) diff --git a/web/src/components/table/channels/modals/EditChannelModal.jsx b/web/src/components/table/channels/modals/EditChannelModal.jsx index c13aca13..259553d0 100644 --- a/web/src/components/table/channels/modals/EditChannelModal.jsx +++ b/web/src/components/table/channels/modals/EditChannelModal.jsx @@ -1174,27 +1174,27 @@ const EditChannelModal = (props) => { )} - {isEdit && isMultiKeyChannel && ( - setKeyMode(value)} - extraText={ - - {keyMode === 'replace' - ? t('覆盖模式:将完全替换现有的所有密钥') - : t('追加模式:将新密钥添加到现有密钥列表末尾') - } - + {isEdit && isMultiKeyChannel && ( + setKeyMode(value)} + extraText={ + + {keyMode === 'replace' + ? t('覆盖模式:将完全替换现有的所有密钥') + : t('追加模式:将新密钥添加到现有密钥列表末尾') } - /> + + } + /> )} {batch && multiToSingle && ( <> diff --git a/web/src/components/table/channels/modals/ModelTestModal.jsx b/web/src/components/table/channels/modals/ModelTestModal.jsx index 1d159473..7e845a04 100644 --- a/web/src/components/table/channels/modals/ModelTestModal.jsx +++ b/web/src/components/table/channels/modals/ModelTestModal.jsx @@ -175,7 +175,7 @@ const ModelTestModal = ({ {currentTestChannel.name} {t('渠道的模型测试')} - + {t('共')} {currentTestChannel.models.split(',').length} {t('个模型')} diff --git a/web/src/components/table/models/ModelsActions.jsx b/web/src/components/table/models/ModelsActions.jsx index 9eacab69..b10d0500 100644 --- a/web/src/components/table/models/ModelsActions.jsx +++ b/web/src/components/table/models/ModelsActions.jsx @@ -20,13 +20,15 @@ For commercial licensing, please contact support@quantumnous.com import React, { useState } from 'react'; import MissingModelsModal from './modals/MissingModelsModal.jsx'; import PrefillGroupManagement from './modals/PrefillGroupManagement.jsx'; -import { Button, Space, Modal } from '@douyinfe/semi-ui'; +import EditPrefillGroupModal from './modals/EditPrefillGroupModal.jsx'; +import { Button, Modal } from '@douyinfe/semi-ui'; +import { showSuccess, showError, copy } from '../../../helpers'; import CompactModeToggle from '../../common/ui/CompactModeToggle'; -import { showError } from '../../../helpers'; import SelectionNotification from './components/SelectionNotification.jsx'; const ModelsActions = ({ selectedKeys, + setSelectedKeys, setEditingModel, setShowEdit, batchDeleteModels, @@ -38,13 +40,11 @@ const ModelsActions = ({ const [showDeleteModal, setShowDeleteModal] = useState(false); const [showMissingModal, setShowMissingModal] = useState(false); const [showGroupManagement, setShowGroupManagement] = useState(false); + const [showAddPrefill, setShowAddPrefill] = useState(false); + const [prefillInit, setPrefillInit] = useState({ id: undefined }); // Handle delete selected models with confirmation const handleDeleteSelectedModels = () => { - if (selectedKeys.length === 0) { - showError(t('请至少选择一个模型!')); - return; - } setShowDeleteModal(true); }; @@ -54,6 +54,30 @@ const ModelsActions = ({ setShowDeleteModal(false); }; + // Handle clear selection + const handleClearSelected = () => { + setSelectedKeys([]); + }; + + // Handle add selected models to prefill group + const handleCopyNames = async () => { + const text = selectedKeys.map(m => m.model_name).join(','); + if (!text) return; + const ok = await copy(text); + if (ok) { + showSuccess(t('已复制模型名称')); + } else { + showError(t('复制失败')); + } + }; + + const handleAddToPrefill = () => { + // Prepare initial data + const items = selectedKeys.map((m) => m.model_name); + setPrefillInit({ id: undefined, type: 'model', items }); + setShowAddPrefill(true); + }; + return ( <>
@@ -71,7 +95,6 @@ const ModelsActions = ({ {t('添加模型')} - + + ); @@ -51,7 +81,7 @@ const SelectionNotification = ({ selectedKeys = [], t, onDelete }) => { // 使用相同 id 更新通知(若已存在则就地更新,不存在则创建) Notification.info({ id: NOTICE_ID, - title: t('批量操作'), + title: titleNode, content, duration: 0, // 不自动关闭 position: 'bottom', @@ -61,7 +91,7 @@ const SelectionNotification = ({ selectedKeys = [], t, onDelete }) => { // 取消全部勾选时关闭通知 Notification.close(NOTICE_ID); } - }, [selectedKeys, t, onDelete]); + }, [selectedKeys, t, onDelete, onAddPrefill, onClear, onCopy]); // 卸载时确保关闭通知 useEffect(() => { diff --git a/web/src/components/table/models/index.jsx b/web/src/components/table/models/index.jsx index 4732e83d..93d63470 100644 --- a/web/src/components/table/models/index.jsx +++ b/web/src/components/table/models/index.jsx @@ -42,6 +42,7 @@ const ModelsPage = () => { // Actions state selectedKeys, + setSelectedKeys, setEditingModel, setShowEdit, batchDeleteModels, @@ -100,6 +101,7 @@ const ModelsPage = () => {
{ const { t } = useTranslation(); const [loading, setLoading] = useState(false); @@ -332,23 +322,6 @@ const EditModelModal = (props) => { showClear /> - - ({ label: g.name, value: g.id }))} - showClear - onChange={(value) => { - const g = tagGroups.find(item => item.id === value); - if (g && formApiRef.current) { - formApiRef.current.setValue('tags', g.items || []); - } - }} - style={{ width: '100%' }} - /> - - { formApiRef.current.setValue('tags', normalized); }} style={{ width: '100%' }} + extraText={( + + {tagGroups.map(group => ( + + ))} + + + )} /> - - - - {/* 供应商信息 */} - -
- - - -
- {t('供应商信息')} -
{t('设置模型的供应商相关信息')}
-
-
- { style={{ width: '100%' }} /> - -
- - {/* 功能配置 */} - -
- - - -
- {t('功能配置')} -
{t('设置模型的功能和状态')}
-
-
- - ({ label: g.name, value: g.id }))} - showClear - style={{ width: '100%' }} - onChange={(value) => { - const g = endpointGroups.find(item => item.id === value); - if (g && formApiRef.current) { - formApiRef.current.setValue('endpoints', g.items || []); - } - }} - /> - - - - + {endpointGroups.map(group => ( + + ))} + + + )} /> diff --git a/web/src/components/table/models/modals/MissingModelsModal.jsx b/web/src/components/table/models/modals/MissingModelsModal.jsx index 41ff9d13..f181b112 100644 --- a/web/src/components/table/models/modals/MissingModelsModal.jsx +++ b/web/src/components/table/models/modals/MissingModelsModal.jsx @@ -111,7 +111,7 @@ const MissingModelsModal = ({ {t('未配置的模型列表')} - + {t('共')} {missingModels.length} {t('个未配置模型')}
diff --git a/web/src/hooks/models/useModelsData.js b/web/src/hooks/models/useModelsData.js index 0195858d..b41bdfc2 100644 --- a/web/src/hooks/models/useModelsData.js +++ b/web/src/hooks/models/useModelsData.js @@ -328,6 +328,7 @@ export const useModelsData = () => { selectedKeys, rowSelection, handleRow, + setSelectedKeys, // Modal state showEdit,