|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
import React, { useState } from 'react'; |
|
|
import MissingModelsModal from './modals/MissingModelsModal'; |
|
|
import PrefillGroupManagement from './modals/PrefillGroupManagement'; |
|
|
import EditPrefillGroupModal from './modals/EditPrefillGroupModal'; |
|
|
import { Button, Modal, Popover, RadioGroup, Radio } from '@douyinfe/semi-ui'; |
|
|
import { showSuccess, showError, copy } from '../../../helpers'; |
|
|
import CompactModeToggle from '../../common/ui/CompactModeToggle'; |
|
|
import SelectionNotification from './components/SelectionNotification'; |
|
|
import UpstreamConflictModal from './modals/UpstreamConflictModal'; |
|
|
import SyncWizardModal from './modals/SyncWizardModal'; |
|
|
|
|
|
const ModelsActions = ({ |
|
|
selectedKeys, |
|
|
setSelectedKeys, |
|
|
setEditingModel, |
|
|
setShowEdit, |
|
|
batchDeleteModels, |
|
|
syncing, |
|
|
previewing, |
|
|
syncUpstream, |
|
|
previewUpstreamDiff, |
|
|
applyUpstreamOverwrite, |
|
|
compactMode, |
|
|
setCompactMode, |
|
|
t, |
|
|
}) => { |
|
|
|
|
|
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 }); |
|
|
const [showConflict, setShowConflict] = useState(false); |
|
|
const [conflicts, setConflicts] = useState([]); |
|
|
const [showSyncModal, setShowSyncModal] = useState(false); |
|
|
const [syncLocale, setSyncLocale] = useState('zh'); |
|
|
|
|
|
const handleSyncUpstream = async (locale) => { |
|
|
|
|
|
const data = await previewUpstreamDiff?.({ locale }); |
|
|
const conflictItems = data?.conflicts || []; |
|
|
if (conflictItems.length > 0) { |
|
|
setConflicts(conflictItems); |
|
|
setShowConflict(true); |
|
|
return; |
|
|
} |
|
|
|
|
|
await syncUpstream?.({ locale }); |
|
|
}; |
|
|
|
|
|
|
|
|
const handleDeleteSelectedModels = () => { |
|
|
setShowDeleteModal(true); |
|
|
}; |
|
|
|
|
|
|
|
|
const handleConfirmDelete = () => { |
|
|
batchDeleteModels(); |
|
|
setShowDeleteModal(false); |
|
|
}; |
|
|
|
|
|
|
|
|
const handleClearSelected = () => { |
|
|
setSelectedKeys([]); |
|
|
}; |
|
|
|
|
|
|
|
|
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 = () => { |
|
|
|
|
|
const items = selectedKeys.map((m) => m.model_name); |
|
|
setPrefillInit({ id: undefined, type: 'model', items }); |
|
|
setShowAddPrefill(true); |
|
|
}; |
|
|
|
|
|
return ( |
|
|
<> |
|
|
<div className='flex flex-wrap gap-2 w-full md:w-auto order-2 md:order-1'> |
|
|
<Button |
|
|
type='primary' |
|
|
className='flex-1 md:flex-initial' |
|
|
onClick={() => { |
|
|
setEditingModel({ |
|
|
id: undefined, |
|
|
}); |
|
|
setShowEdit(true); |
|
|
}} |
|
|
size='small' |
|
|
> |
|
|
{t('添加模型')} |
|
|
</Button> |
|
|
|
|
|
<Button |
|
|
type='secondary' |
|
|
className='flex-1 md:flex-initial' |
|
|
size='small' |
|
|
onClick={() => setShowMissingModal(true)} |
|
|
> |
|
|
{t('未配置模型')} |
|
|
</Button> |
|
|
|
|
|
<Popover |
|
|
position='bottom' |
|
|
trigger='hover' |
|
|
content={ |
|
|
<div className='p-2 max-w-[360px]'> |
|
|
<div className='text-[var(--semi-color-text-2)] text-sm'> |
|
|
{t( |
|
|
'模型社区需要大家的共同维护,如发现数据有误或想贡献新的模型数据,请访问:', |
|
|
)} |
|
|
</div> |
|
|
<a |
|
|
href='https://github.com/basellm/llm-metadata' |
|
|
target='_blank' |
|
|
rel='noreferrer' |
|
|
className='text-blue-600 underline' |
|
|
> |
|
|
https://github.com/basellm/llm-metadata |
|
|
</a> |
|
|
</div> |
|
|
} |
|
|
> |
|
|
<Button |
|
|
type='secondary' |
|
|
className='flex-1 md:flex-initial' |
|
|
size='small' |
|
|
loading={syncing || previewing} |
|
|
onClick={() => { |
|
|
setSyncLocale('zh'); |
|
|
setShowSyncModal(true); |
|
|
}} |
|
|
> |
|
|
{t('同步')} |
|
|
</Button> |
|
|
</Popover> |
|
|
|
|
|
<Button |
|
|
type='secondary' |
|
|
className='flex-1 md:flex-initial' |
|
|
size='small' |
|
|
onClick={() => setShowGroupManagement(true)} |
|
|
> |
|
|
{t('预填组管理')} |
|
|
</Button> |
|
|
|
|
|
<CompactModeToggle |
|
|
compactMode={compactMode} |
|
|
setCompactMode={setCompactMode} |
|
|
t={t} |
|
|
/> |
|
|
</div> |
|
|
|
|
|
<SelectionNotification |
|
|
selectedKeys={selectedKeys} |
|
|
t={t} |
|
|
onDelete={handleDeleteSelectedModels} |
|
|
onAddPrefill={handleAddToPrefill} |
|
|
onClear={handleClearSelected} |
|
|
onCopy={handleCopyNames} |
|
|
/> |
|
|
|
|
|
<Modal |
|
|
title={t('批量删除模型')} |
|
|
visible={showDeleteModal} |
|
|
onCancel={() => setShowDeleteModal(false)} |
|
|
onOk={handleConfirmDelete} |
|
|
type='warning' |
|
|
> |
|
|
<div> |
|
|
{t('确定要删除所选的 {{count}} 个模型吗?', { |
|
|
count: selectedKeys.length, |
|
|
})} |
|
|
</div> |
|
|
</Modal> |
|
|
|
|
|
<SyncWizardModal |
|
|
visible={showSyncModal} |
|
|
onClose={() => setShowSyncModal(false)} |
|
|
loading={syncing || previewing} |
|
|
t={t} |
|
|
onConfirm={async ({ option, locale }) => { |
|
|
setSyncLocale(locale); |
|
|
if (option === 'official') { |
|
|
await handleSyncUpstream(locale); |
|
|
} |
|
|
setShowSyncModal(false); |
|
|
}} |
|
|
/> |
|
|
|
|
|
<MissingModelsModal |
|
|
visible={showMissingModal} |
|
|
onClose={() => setShowMissingModal(false)} |
|
|
onConfigureModel={(name) => { |
|
|
setEditingModel({ id: undefined, model_name: name }); |
|
|
setShowEdit(true); |
|
|
setShowMissingModal(false); |
|
|
}} |
|
|
t={t} |
|
|
/> |
|
|
|
|
|
<PrefillGroupManagement |
|
|
visible={showGroupManagement} |
|
|
onClose={() => setShowGroupManagement(false)} |
|
|
/> |
|
|
|
|
|
<EditPrefillGroupModal |
|
|
visible={showAddPrefill} |
|
|
onClose={() => setShowAddPrefill(false)} |
|
|
editingGroup={prefillInit} |
|
|
onSuccess={() => setShowAddPrefill(false)} |
|
|
/> |
|
|
|
|
|
<UpstreamConflictModal |
|
|
visible={showConflict} |
|
|
onClose={() => setShowConflict(false)} |
|
|
conflicts={conflicts} |
|
|
onSubmit={async (payload) => { |
|
|
return await applyUpstreamOverwrite?.({ |
|
|
overwrite: payload, |
|
|
locale: syncLocale, |
|
|
}); |
|
|
}} |
|
|
t={t} |
|
|
loading={syncing} |
|
|
/> |
|
|
</> |
|
|
); |
|
|
}; |
|
|
|
|
|
export default ModelsActions; |
|
|
|