✨ feat(models): Revamp EditModelModal UI and UX
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.
This commit is contained in:
@@ -1174,27 +1174,27 @@ const EditChannelModal = (props) => {
|
|||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{isEdit && isMultiKeyChannel && (
|
{isEdit && isMultiKeyChannel && (
|
||||||
<Form.Select
|
<Form.Select
|
||||||
field='key_mode'
|
field='key_mode'
|
||||||
label={t('密钥更新模式')}
|
label={t('密钥更新模式')}
|
||||||
placeholder={t('请选择密钥更新模式')}
|
placeholder={t('请选择密钥更新模式')}
|
||||||
optionList={[
|
optionList={[
|
||||||
{ label: t('追加到现有密钥'), value: 'append' },
|
{ label: t('追加到现有密钥'), value: 'append' },
|
||||||
{ label: t('覆盖现有密钥'), value: 'replace' },
|
{ label: t('覆盖现有密钥'), value: 'replace' },
|
||||||
]}
|
]}
|
||||||
style={{ width: '100%' }}
|
style={{ width: '100%' }}
|
||||||
value={keyMode}
|
value={keyMode}
|
||||||
onChange={(value) => setKeyMode(value)}
|
onChange={(value) => setKeyMode(value)}
|
||||||
extraText={
|
extraText={
|
||||||
<Text type="tertiary" size="small">
|
<Text type="tertiary" size="small">
|
||||||
{keyMode === 'replace'
|
{keyMode === 'replace'
|
||||||
? t('覆盖模式:将完全替换现有的所有密钥')
|
? t('覆盖模式:将完全替换现有的所有密钥')
|
||||||
: t('追加模式:将新密钥添加到现有密钥列表末尾')
|
: t('追加模式:将新密钥添加到现有密钥列表末尾')
|
||||||
}
|
|
||||||
</Text>
|
|
||||||
}
|
}
|
||||||
/>
|
</Text>
|
||||||
|
}
|
||||||
|
/>
|
||||||
)}
|
)}
|
||||||
{batch && multiToSingle && (
|
{batch && multiToSingle && (
|
||||||
<>
|
<>
|
||||||
|
|||||||
@@ -175,7 +175,7 @@ const ModelTestModal = ({
|
|||||||
<Typography.Text strong className="!text-[var(--semi-color-text-0)] !text-base">
|
<Typography.Text strong className="!text-[var(--semi-color-text-0)] !text-base">
|
||||||
{currentTestChannel.name} {t('渠道的模型测试')}
|
{currentTestChannel.name} {t('渠道的模型测试')}
|
||||||
</Typography.Text>
|
</Typography.Text>
|
||||||
<Typography.Text type="tertiary" className="!text-xs flex items-center">
|
<Typography.Text type="tertiary" size="small">
|
||||||
{t('共')} {currentTestChannel.models.split(',').length} {t('个模型')}
|
{t('共')} {currentTestChannel.models.split(',').length} {t('个模型')}
|
||||||
</Typography.Text>
|
</Typography.Text>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -20,13 +20,15 @@ For commercial licensing, please contact support@quantumnous.com
|
|||||||
import React, { useState } from 'react';
|
import React, { useState } from 'react';
|
||||||
import MissingModelsModal from './modals/MissingModelsModal.jsx';
|
import MissingModelsModal from './modals/MissingModelsModal.jsx';
|
||||||
import PrefillGroupManagement from './modals/PrefillGroupManagement.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 CompactModeToggle from '../../common/ui/CompactModeToggle';
|
||||||
import { showError } from '../../../helpers';
|
|
||||||
import SelectionNotification from './components/SelectionNotification.jsx';
|
import SelectionNotification from './components/SelectionNotification.jsx';
|
||||||
|
|
||||||
const ModelsActions = ({
|
const ModelsActions = ({
|
||||||
selectedKeys,
|
selectedKeys,
|
||||||
|
setSelectedKeys,
|
||||||
setEditingModel,
|
setEditingModel,
|
||||||
setShowEdit,
|
setShowEdit,
|
||||||
batchDeleteModels,
|
batchDeleteModels,
|
||||||
@@ -38,13 +40,11 @@ const ModelsActions = ({
|
|||||||
const [showDeleteModal, setShowDeleteModal] = useState(false);
|
const [showDeleteModal, setShowDeleteModal] = useState(false);
|
||||||
const [showMissingModal, setShowMissingModal] = useState(false);
|
const [showMissingModal, setShowMissingModal] = useState(false);
|
||||||
const [showGroupManagement, setShowGroupManagement] = useState(false);
|
const [showGroupManagement, setShowGroupManagement] = useState(false);
|
||||||
|
const [showAddPrefill, setShowAddPrefill] = useState(false);
|
||||||
|
const [prefillInit, setPrefillInit] = useState({ id: undefined });
|
||||||
|
|
||||||
// Handle delete selected models with confirmation
|
// Handle delete selected models with confirmation
|
||||||
const handleDeleteSelectedModels = () => {
|
const handleDeleteSelectedModels = () => {
|
||||||
if (selectedKeys.length === 0) {
|
|
||||||
showError(t('请至少选择一个模型!'));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
setShowDeleteModal(true);
|
setShowDeleteModal(true);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -54,6 +54,30 @@ const ModelsActions = ({
|
|||||||
setShowDeleteModal(false);
|
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 (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className="flex flex-wrap gap-2 w-full md:w-auto order-2 md:order-1">
|
<div className="flex flex-wrap gap-2 w-full md:w-auto order-2 md:order-1">
|
||||||
@@ -71,7 +95,6 @@ const ModelsActions = ({
|
|||||||
{t('添加模型')}
|
{t('添加模型')}
|
||||||
</Button>
|
</Button>
|
||||||
|
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
type="secondary"
|
type="secondary"
|
||||||
className="flex-1 md:flex-initial"
|
className="flex-1 md:flex-initial"
|
||||||
@@ -101,6 +124,9 @@ const ModelsActions = ({
|
|||||||
selectedKeys={selectedKeys}
|
selectedKeys={selectedKeys}
|
||||||
t={t}
|
t={t}
|
||||||
onDelete={handleDeleteSelectedModels}
|
onDelete={handleDeleteSelectedModels}
|
||||||
|
onAddPrefill={handleAddToPrefill}
|
||||||
|
onClear={handleClearSelected}
|
||||||
|
onCopy={handleCopyNames}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Modal
|
<Modal
|
||||||
@@ -130,6 +156,13 @@ const ModelsActions = ({
|
|||||||
visible={showGroupManagement}
|
visible={showGroupManagement}
|
||||||
onClose={() => setShowGroupManagement(false)}
|
onClose={() => setShowGroupManagement(false)}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
<EditPrefillGroupModal
|
||||||
|
visible={showAddPrefill}
|
||||||
|
onClose={() => setShowAddPrefill(false)}
|
||||||
|
editingGroup={prefillInit}
|
||||||
|
onSuccess={() => setShowAddPrefill(false)}
|
||||||
|
/>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ For commercial licensing, please contact support@quantumnous.com
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import React, { useEffect } from 'react';
|
import React, { useEffect } from 'react';
|
||||||
import { Notification, Button, Space } from '@douyinfe/semi-ui';
|
import { Notification, Button, Space, Typography } from '@douyinfe/semi-ui';
|
||||||
|
|
||||||
// 固定通知 ID,保持同一个实例即可避免闪烁
|
// 固定通知 ID,保持同一个实例即可避免闪烁
|
||||||
const NOTICE_ID = 'models-batch-actions';
|
const NOTICE_ID = 'models-batch-actions';
|
||||||
@@ -28,22 +28,52 @@ const NOTICE_ID = 'models-batch-actions';
|
|||||||
* 1. 当 selectedKeys.length > 0 时,使用固定 id 创建/更新通知
|
* 1. 当 selectedKeys.length > 0 时,使用固定 id 创建/更新通知
|
||||||
* 2. 当 selectedKeys 清空时关闭通知
|
* 2. 当 selectedKeys 清空时关闭通知
|
||||||
*/
|
*/
|
||||||
const SelectionNotification = ({ selectedKeys = [], t, onDelete }) => {
|
const SelectionNotification = ({ selectedKeys = [], t, onDelete, onAddPrefill, onClear, onCopy }) => {
|
||||||
// 根据选中数量决定显示/隐藏或更新通知
|
// 根据选中数量决定显示/隐藏或更新通知
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const selectedCount = selectedKeys.length;
|
const selectedCount = selectedKeys.length;
|
||||||
|
|
||||||
if (selectedCount > 0) {
|
if (selectedCount > 0) {
|
||||||
|
const titleNode = (
|
||||||
|
<Space wrap>
|
||||||
|
<span>{t('批量操作')}</span>
|
||||||
|
<Typography.Text type="tertiary" size="small">{t('已选择 {{count}} 个模型', { count: selectedCount })}</Typography.Text>
|
||||||
|
</Space>
|
||||||
|
);
|
||||||
|
|
||||||
const content = (
|
const content = (
|
||||||
<Space>
|
<Space wrap>
|
||||||
<span>{t('已选择 {{count}} 个模型', { count: selectedCount })}</span>
|
<Button
|
||||||
|
size="small"
|
||||||
|
type="secondary"
|
||||||
|
theme="solid"
|
||||||
|
onClick={onClear}
|
||||||
|
>
|
||||||
|
{t('取消全选')}
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
size="small"
|
||||||
|
type="primary"
|
||||||
|
theme="solid"
|
||||||
|
onClick={onAddPrefill}
|
||||||
|
>
|
||||||
|
{t('加入预填组')}
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
size="small"
|
||||||
|
type="tertiary"
|
||||||
|
theme="solid"
|
||||||
|
onClick={onCopy}
|
||||||
|
>
|
||||||
|
{t('复制名称')}
|
||||||
|
</Button>
|
||||||
<Button
|
<Button
|
||||||
size="small"
|
size="small"
|
||||||
type="danger"
|
type="danger"
|
||||||
theme="solid"
|
theme="solid"
|
||||||
onClick={onDelete}
|
onClick={onDelete}
|
||||||
>
|
>
|
||||||
{t('删除所选模型')}
|
{t('删除所选')}
|
||||||
</Button>
|
</Button>
|
||||||
</Space>
|
</Space>
|
||||||
);
|
);
|
||||||
@@ -51,7 +81,7 @@ const SelectionNotification = ({ selectedKeys = [], t, onDelete }) => {
|
|||||||
// 使用相同 id 更新通知(若已存在则就地更新,不存在则创建)
|
// 使用相同 id 更新通知(若已存在则就地更新,不存在则创建)
|
||||||
Notification.info({
|
Notification.info({
|
||||||
id: NOTICE_ID,
|
id: NOTICE_ID,
|
||||||
title: t('批量操作'),
|
title: titleNode,
|
||||||
content,
|
content,
|
||||||
duration: 0, // 不自动关闭
|
duration: 0, // 不自动关闭
|
||||||
position: 'bottom',
|
position: 'bottom',
|
||||||
@@ -61,7 +91,7 @@ const SelectionNotification = ({ selectedKeys = [], t, onDelete }) => {
|
|||||||
// 取消全部勾选时关闭通知
|
// 取消全部勾选时关闭通知
|
||||||
Notification.close(NOTICE_ID);
|
Notification.close(NOTICE_ID);
|
||||||
}
|
}
|
||||||
}, [selectedKeys, t, onDelete]);
|
}, [selectedKeys, t, onDelete, onAddPrefill, onClear, onCopy]);
|
||||||
|
|
||||||
// 卸载时确保关闭通知
|
// 卸载时确保关闭通知
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|||||||
@@ -42,6 +42,7 @@ const ModelsPage = () => {
|
|||||||
|
|
||||||
// Actions state
|
// Actions state
|
||||||
selectedKeys,
|
selectedKeys,
|
||||||
|
setSelectedKeys,
|
||||||
setEditingModel,
|
setEditingModel,
|
||||||
setShowEdit,
|
setShowEdit,
|
||||||
batchDeleteModels,
|
batchDeleteModels,
|
||||||
@@ -100,6 +101,7 @@ const ModelsPage = () => {
|
|||||||
<div className="flex flex-col md:flex-row justify-between items-center gap-2 w-full">
|
<div className="flex flex-col md:flex-row justify-between items-center gap-2 w-full">
|
||||||
<ModelsActions
|
<ModelsActions
|
||||||
selectedKeys={selectedKeys}
|
selectedKeys={selectedKeys}
|
||||||
|
setSelectedKeys={setSelectedKeys}
|
||||||
setEditingModel={setEditingModel}
|
setEditingModel={setEditingModel}
|
||||||
setShowEdit={setShowEdit}
|
setShowEdit={setShowEdit}
|
||||||
batchDeleteModels={batchDeleteModels}
|
batchDeleteModels={batchDeleteModels}
|
||||||
|
|||||||
@@ -35,13 +35,13 @@ import {
|
|||||||
Save,
|
Save,
|
||||||
X,
|
X,
|
||||||
FileText,
|
FileText,
|
||||||
Building,
|
|
||||||
Settings,
|
|
||||||
} from 'lucide-react';
|
} from 'lucide-react';
|
||||||
import { API, showError, showSuccess } from '../../../../helpers';
|
import { API, showError, showSuccess } from '../../../../helpers';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { useIsMobile } from '../../../../hooks/common/useIsMobile';
|
import { useIsMobile } from '../../../../hooks/common/useIsMobile';
|
||||||
|
|
||||||
|
const { Text, Title } = Typography;
|
||||||
|
|
||||||
const nameRuleOptions = [
|
const nameRuleOptions = [
|
||||||
{ label: '精确名称匹配', value: 0 },
|
{ label: '精确名称匹配', value: 0 },
|
||||||
{ label: '前缀名称匹配', value: 1 },
|
{ label: '前缀名称匹配', value: 1 },
|
||||||
@@ -49,16 +49,6 @@ const nameRuleOptions = [
|
|||||||
{ label: '后缀名称匹配', value: 3 },
|
{ label: '后缀名称匹配', value: 3 },
|
||||||
];
|
];
|
||||||
|
|
||||||
const endpointOptions = [
|
|
||||||
{ label: 'OpenAI', value: 'openai' },
|
|
||||||
{ label: 'Anthropic', value: 'anthropic' },
|
|
||||||
{ label: 'Gemini', value: 'gemini' },
|
|
||||||
{ label: 'Image Generation', value: 'image-generation' },
|
|
||||||
{ label: 'Jina Rerank', value: 'jina-rerank' },
|
|
||||||
];
|
|
||||||
|
|
||||||
const { Text, Title } = Typography;
|
|
||||||
|
|
||||||
const EditModelModal = (props) => {
|
const EditModelModal = (props) => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const [loading, setLoading] = useState(false);
|
const [loading, setLoading] = useState(false);
|
||||||
@@ -332,23 +322,6 @@ const EditModelModal = (props) => {
|
|||||||
showClear
|
showClear
|
||||||
/>
|
/>
|
||||||
</Col>
|
</Col>
|
||||||
<Col span={24}>
|
|
||||||
<Form.Select
|
|
||||||
field='tag_group'
|
|
||||||
label={t('标签组')}
|
|
||||||
placeholder={t('选择标签组后将自动填充标签')}
|
|
||||||
optionList={tagGroups.map(g => ({ 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%' }}
|
|
||||||
/>
|
|
||||||
</Col>
|
|
||||||
|
|
||||||
<Col span={24}>
|
<Col span={24}>
|
||||||
<Form.TagInput
|
<Form.TagInput
|
||||||
field='tags'
|
field='tags'
|
||||||
@@ -366,23 +339,40 @@ const EditModelModal = (props) => {
|
|||||||
formApiRef.current.setValue('tags', normalized);
|
formApiRef.current.setValue('tags', normalized);
|
||||||
}}
|
}}
|
||||||
style={{ width: '100%' }}
|
style={{ width: '100%' }}
|
||||||
|
extraText={(
|
||||||
|
<Space wrap>
|
||||||
|
{tagGroups.map(group => (
|
||||||
|
<Button
|
||||||
|
key={group.id}
|
||||||
|
size='small'
|
||||||
|
type='primary'
|
||||||
|
onClick={() => {
|
||||||
|
if (formApiRef.current) {
|
||||||
|
const currentTags = formApiRef.current.getValue('tags') || [];
|
||||||
|
const newTags = [...currentTags, ...(group.items || [])];
|
||||||
|
const uniqueTags = [...new Set(newTags)];
|
||||||
|
formApiRef.current.setValue('tags', uniqueTags);
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{group.name}
|
||||||
|
</Button>
|
||||||
|
))}
|
||||||
|
<Button
|
||||||
|
size='small'
|
||||||
|
type='warning'
|
||||||
|
onClick={() => {
|
||||||
|
if (formApiRef.current) {
|
||||||
|
formApiRef.current.setValue('tags', []);
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{t('清除标签')}
|
||||||
|
</Button>
|
||||||
|
</Space>
|
||||||
|
)}
|
||||||
/>
|
/>
|
||||||
</Col>
|
</Col>
|
||||||
</Row>
|
|
||||||
</Card>
|
|
||||||
|
|
||||||
{/* 供应商信息 */}
|
|
||||||
<Card className='!rounded-2xl shadow-sm border-0'>
|
|
||||||
<div className='flex items-center mb-2'>
|
|
||||||
<Avatar size='small' color='blue' className='mr-2 shadow-md'>
|
|
||||||
<Building size={16} />
|
|
||||||
</Avatar>
|
|
||||||
<div>
|
|
||||||
<Text className='text-lg font-medium'>{t('供应商信息')}</Text>
|
|
||||||
<div className='text-xs text-gray-600'>{t('设置模型的供应商相关信息')}</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<Row gutter={12}>
|
|
||||||
<Col span={24}>
|
<Col span={24}>
|
||||||
<Form.Select
|
<Form.Select
|
||||||
field='vendor_id'
|
field='vendor_id'
|
||||||
@@ -400,47 +390,46 @@ const EditModelModal = (props) => {
|
|||||||
style={{ width: '100%' }}
|
style={{ width: '100%' }}
|
||||||
/>
|
/>
|
||||||
</Col>
|
</Col>
|
||||||
</Row>
|
|
||||||
</Card>
|
|
||||||
|
|
||||||
{/* 功能配置 */}
|
|
||||||
<Card className='!rounded-2xl shadow-sm border-0'>
|
|
||||||
<div className='flex items-center mb-2'>
|
|
||||||
<Avatar size='small' color='purple' className='mr-2 shadow-md'>
|
|
||||||
<Settings size={16} />
|
|
||||||
</Avatar>
|
|
||||||
<div>
|
|
||||||
<Text className='text-lg font-medium'>{t('功能配置')}</Text>
|
|
||||||
<div className='text-xs text-gray-600'>{t('设置模型的功能和状态')}</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<Row gutter={12}>
|
|
||||||
<Col span={24}>
|
<Col span={24}>
|
||||||
<Form.Select
|
<Form.TagInput
|
||||||
field='endpoint_group'
|
|
||||||
label={t('端点组')}
|
|
||||||
placeholder={t('选择端点组后将自动填充端点')}
|
|
||||||
optionList={endpointGroups.map(g => ({ 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 || []);
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</Col>
|
|
||||||
|
|
||||||
<Col span={24}>
|
|
||||||
<Form.Select
|
|
||||||
field='endpoints'
|
field='endpoints'
|
||||||
label={t('支持端点')}
|
label={t('支持端点')}
|
||||||
placeholder={t('选择模型支持的端点类型')}
|
placeholder={t('输入端点名称,按回车添加')}
|
||||||
optionList={endpointOptions}
|
addOnBlur
|
||||||
multiple
|
|
||||||
showClear
|
showClear
|
||||||
style={{ width: '100%' }}
|
style={{ width: '100%' }}
|
||||||
|
extraText={(
|
||||||
|
<Space wrap>
|
||||||
|
{endpointGroups.map(group => (
|
||||||
|
<Button
|
||||||
|
key={group.id}
|
||||||
|
size='small'
|
||||||
|
type='primary'
|
||||||
|
onClick={() => {
|
||||||
|
if (formApiRef.current) {
|
||||||
|
const currentEndpoints = formApiRef.current.getValue('endpoints') || [];
|
||||||
|
const newEndpoints = [...currentEndpoints, ...(group.items || [])];
|
||||||
|
const uniqueEndpoints = [...new Set(newEndpoints)];
|
||||||
|
formApiRef.current.setValue('endpoints', uniqueEndpoints);
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{group.name}
|
||||||
|
</Button>
|
||||||
|
))}
|
||||||
|
<Button
|
||||||
|
size='small'
|
||||||
|
type='warning'
|
||||||
|
onClick={() => {
|
||||||
|
if (formApiRef.current) {
|
||||||
|
formApiRef.current.setValue('endpoints', []);
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{t('清除端点')}
|
||||||
|
</Button>
|
||||||
|
</Space>
|
||||||
|
)}
|
||||||
/>
|
/>
|
||||||
</Col>
|
</Col>
|
||||||
<Col span={24}>
|
<Col span={24}>
|
||||||
|
|||||||
@@ -111,7 +111,7 @@ const MissingModelsModal = ({
|
|||||||
<Typography.Text strong className="!text-[var(--semi-color-text-0)] !text-base">
|
<Typography.Text strong className="!text-[var(--semi-color-text-0)] !text-base">
|
||||||
{t('未配置的模型列表')}
|
{t('未配置的模型列表')}
|
||||||
</Typography.Text>
|
</Typography.Text>
|
||||||
<Typography.Text type="tertiary" className="!text-xs flex items-center">
|
<Typography.Text type="tertiary" size="small">
|
||||||
{t('共')} {missingModels.length} {t('个未配置模型')}
|
{t('共')} {missingModels.length} {t('个未配置模型')}
|
||||||
</Typography.Text>
|
</Typography.Text>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -328,6 +328,7 @@ export const useModelsData = () => {
|
|||||||
selectedKeys,
|
selectedKeys,
|
||||||
rowSelection,
|
rowSelection,
|
||||||
handleRow,
|
handleRow,
|
||||||
|
setSelectedKeys,
|
||||||
|
|
||||||
// Modal state
|
// Modal state
|
||||||
showEdit,
|
showEdit,
|
||||||
|
|||||||
Reference in New Issue
Block a user