From 84187eedc46964f6cf34d14804af4f0e6fcacfcd Mon Sep 17 00:00:00 2001 From: jialin Date: Tue, 11 Nov 2025 15:46:35 +0800 Subject: [PATCH] fix: access control, voices options --- src/atoms/models.ts | 2 + src/components/seal-form/config/components.ts | 5 +- src/locales/en-US/models.ts | 3 +- src/locales/ja-JP/models.ts | 6 +- src/locales/ru-RU/models.ts | 6 +- src/locales/zh-CN/models.ts | 3 +- src/pages/backends/config/index.ts | 15 ++- src/pages/llmodels/apis/index.ts | 2 +- src/pages/llmodels/catalog.tsx | 14 +- .../components/access-control-modal/form.tsx | 122 ++++++++++++++++-- .../components/access-control-modal/index.tsx | 2 +- src/pages/llmodels/components/table-list.tsx | 15 ++- src/pages/llmodels/style/catalog-item.less | 2 + .../playground/components/dynamic-params.tsx | 3 +- .../playground/components/ground-tts.tsx | 22 ++-- src/pages/playground/config/params-config.ts | 4 +- src/pages/playground/config/types.ts | 8 +- src/pages/resources/config/gpu-driver.ts | 12 +- src/pages/resources/config/index.ts | 9 -- 19 files changed, 196 insertions(+), 59 deletions(-) diff --git a/src/atoms/models.ts b/src/atoms/models.ts index ad55504b..c5242c8b 100644 --- a/src/atoms/models.ts +++ b/src/atoms/models.ts @@ -4,6 +4,8 @@ import { atom, getDefaultStore } from 'jotai'; // models expand keys: create, update , delete, export const modelsExpandKeysAtom = atom([]); +export const modelsSessionAtom = atom>({}); + export const requestIdAtom = atom(0); export const setRquestId = () => { diff --git a/src/components/seal-form/config/components.ts b/src/components/seal-form/config/components.ts index 29702b67..59d4d3f6 100644 --- a/src/components/seal-form/config/components.ts +++ b/src/components/seal-form/config/components.ts @@ -1,4 +1,5 @@ import { Checkbox } from 'antd'; +import AutoComplete from '../auto-complete'; import SealInput from '../seal-input'; import SealSelect from '../seal-select'; import Slider from '../seal-slider'; @@ -12,6 +13,7 @@ const components: { Input: typeof SealInput.Input; Checkbox: typeof Checkbox; Switch: typeof Switch; + AutoComplete: typeof AutoComplete; } = { InputNumber: SealInput.Number, Select: SealSelect, @@ -19,7 +21,8 @@ const components: { TextArea: SealInput.TextArea, Input: SealInput.Input, Checkbox: Checkbox, - Switch: Switch + Switch: Switch, + AutoComplete: AutoComplete }; export default components; diff --git a/src/locales/en-US/models.ts b/src/locales/en-US/models.ts index 128a94d1..bddaa6f3 100644 --- a/src/locales/en-US/models.ts +++ b/src/locales/en-US/models.ts @@ -247,5 +247,6 @@ export default { 'models.form.gpuPerReplica.tips': 'Enter a custom number', 'models.form.generic_proxy': 'Enable Generic Proxy', 'models.form.generic_proxy.tips': 'Enable Generic Proxy', - 'models.form.generic_proxy.button': 'Generic Proxy' + 'models.form.generic_proxy.button': 'Generic Proxy', + 'models.accessControlModal.includeusers': 'Include Users' }; diff --git a/src/locales/ja-JP/models.ts b/src/locales/ja-JP/models.ts index 73003c0e..aab4e9a3 100644 --- a/src/locales/ja-JP/models.ts +++ b/src/locales/ja-JP/models.ts @@ -247,7 +247,8 @@ export default { 'models.form.gpuPerReplica.tips': 'Enter a custom number', 'models.form.generic_proxy': 'Enable Generic Proxy', 'models.form.generic_proxy.tips': 'Enable Generic Proxy', - 'models.form.generic_proxy.button': 'Generic Proxy' + 'models.form.generic_proxy.button': 'Generic Proxy', + 'models.accessControlModal.includeusers': 'Include Users' }; // ========== To-Do: Translate Keys (Remove After Translation) ========== @@ -322,6 +323,7 @@ export default { // 52. 'models.form.gpuPerReplica.tips': 'Enter a custom number', // 53. 'models.form.generic_proxy': 'Enable Generic Proxy', // 54. 'models.form.generic_proxy.tips': 'Enable Generic Proxy', -// 55. 'models.form.generic_proxy.button': 'Generic Proxy' +// 55. 'models.form.generic_proxy.button': 'Generic Proxy', +// 56. 'models.accessControlModal.includeusers': 'Include Users' // ========== End of To-Do List ========== diff --git a/src/locales/ru-RU/models.ts b/src/locales/ru-RU/models.ts index 97759936..10b8eb50 100644 --- a/src/locales/ru-RU/models.ts +++ b/src/locales/ru-RU/models.ts @@ -248,7 +248,8 @@ export default { 'models.form.gpuPerReplica.tips': 'Enter a custom number', 'models.form.generic_proxy': 'Enable Generic Proxy', 'models.form.generic_proxy.tips': 'Enable Generic Proxy', - 'models.form.generic_proxy.button': 'Generic Proxy' + 'models.form.generic_proxy.button': 'Generic Proxy', + 'models.accessControlModal.includeusers': 'Include Users' }; // ========== To-Do: Translate Keys (Remove After Translation) ========== @@ -256,5 +257,6 @@ export default { // 2. 'models.form.gpuPerReplica.tips': 'Enter a custom number', // 3. 'models.form.generic_proxy': 'Enable Generic Proxy', // 4. 'models.form.generic_proxy.tips': 'Enable Generic Proxy', -// 5. 'models.form.generic_proxy.button': 'Generic Proxy' +// 5. 'models.form.generic_proxy.button': 'Generic Proxy', +// 6. 'models.accessControlModal.includeusers': 'Include Users', // ========== End of To-Do List ========== diff --git a/src/locales/zh-CN/models.ts b/src/locales/zh-CN/models.ts index fc175c0a..b6dd7832 100644 --- a/src/locales/zh-CN/models.ts +++ b/src/locales/zh-CN/models.ts @@ -234,5 +234,6 @@ export default { 'models.form.gpuPerReplica.tips': '输入自定义数值', 'models.form.generic_proxy': '启用通用代理', 'models.form.generic_proxy.tips': '启用通用代理', - 'models.form.generic_proxy.button': '通用代理' + 'models.form.generic_proxy.button': '通用代理', + 'models.accessControlModal.includeusers': '显示用户' }; diff --git a/src/pages/backends/config/index.ts b/src/pages/backends/config/index.ts index ef09f8c8..f166dd6a 100644 --- a/src/pages/backends/config/index.ts +++ b/src/pages/backends/config/index.ts @@ -86,7 +86,8 @@ export const gpuColorMap: Record = { dtk: 'magenta', musa: 'cyan', corex: 'purple', - maca: 'geekblue' + maca: 'geekblue', + neuware: 'gold' }; export const getGpuColor = (gpuType: string) => { @@ -146,10 +147,22 @@ export const frameworks = [ label: 'DTK', value: 'dtk' }, + { + label: 'MACA', + value: 'maca' + }, { label: 'CoreX', value: 'corex' }, + { + label: 'MUSA', + value: 'musa' + }, + { + label: 'Neuware', + value: 'neuware' + }, { label: 'CPU', value: 'cpu' diff --git a/src/pages/llmodels/apis/index.ts b/src/pages/llmodels/apis/index.ts index 02336cd9..d3e486af 100644 --- a/src/pages/llmodels/apis/index.ts +++ b/src/pages/llmodels/apis/index.ts @@ -372,7 +372,7 @@ export async function queryCatalogItemSpec( params: { id: number }, options?: any ) { - return await request>( + return request>( `/model-sets/${params.id}/specs`, { method: 'GET', diff --git a/src/pages/llmodels/catalog.tsx b/src/pages/llmodels/catalog.tsx index b9468392..53370058 100644 --- a/src/pages/llmodels/catalog.tsx +++ b/src/pages/llmodels/catalog.tsx @@ -1,4 +1,4 @@ -import { modelsExpandKeysAtom } from '@/atoms/models'; +import { modelsExpandKeysAtom, modelsSessionAtom } from '@/atoms/models'; import IconFont from '@/components/icon-font'; import { FilterBar } from '@/components/page-tools'; import { PageAction } from '@/config'; @@ -14,7 +14,7 @@ import _ from 'lodash'; import React, { useCallback, useEffect, useState } from 'react'; import NoResult from '../_components/no-result'; import PageBox from '../_components/page-box'; -import { createModel, queryCatalogList } from './apis'; +import { createModel, queryCatalogItemSpec, queryCatalogList } from './apis'; import CatalogList from './components/catalog-list'; import DelopyBuiltInModal from './components/deploy-builtin-modal'; import { modelCategories, modelSourceMap } from './config'; @@ -50,6 +50,7 @@ const Catalog: React.FC = () => { source: modelSourceMap.huggingface_value }); const [modelsExpandKeys, setModelsExpandKeys] = useAtom(modelsExpandKeysAtom); + const [, setModelsSession] = useAtom(modelsSessionAtom); const cacheData = React.useRef([]); const categoryOptions = [ @@ -184,7 +185,14 @@ const Catalog: React.FC = () => { }); }); - const handleDeployFromOtherHubs = () => { + const handleDeployFromOtherHubs = async () => { + try { + const id = dataSource.dataList?.[0]?.id; + const res: any = await queryCatalogItemSpec({ id }); + setModelsSession({ + source: res?.items?.[0]?.source + }); + } catch (error) {} navigate('/models/deployments'); }; diff --git a/src/pages/llmodels/components/access-control-modal/form.tsx b/src/pages/llmodels/components/access-control-modal/form.tsx index 7907dd4d..93e7a8da 100644 --- a/src/pages/llmodels/components/access-control-modal/form.tsx +++ b/src/pages/llmodels/components/access-control-modal/form.tsx @@ -1,9 +1,16 @@ import AlertBlockInfo from '@/components/alert-info/block'; import TransferInner from '@/pages/_components/transfer'; import { queryUsersList } from '@/pages/users/apis'; +import { DownOutlined } from '@ant-design/icons'; import { useIntl } from '@umijs/max'; -import { Empty, Form, Radio } from 'antd'; -import { forwardRef, useEffect, useImperativeHandle, useState } from 'react'; +import { Checkbox, Dropdown, DropdownProps, Empty, Form, Radio } from 'antd'; +import { + forwardRef, + useEffect, + useImperativeHandle, + useMemo, + useState +} from 'react'; import styled from 'styled-components'; import { queryModelAccessUserList } from '../../apis'; import { AccessControlFormData, ListItem } from '../../config/types'; @@ -29,20 +36,42 @@ const AccessControlForm = forwardRef((props: AccessControlFormProps, ref) => { const accessPolicy = Form.useWatch('access_policy', form); const [targetKeys, setTargetKeys] = useState([]); const [totalPages, setTotalPages] = useState(0); - const [userList, setUserList] = useState<{ title: string; key: number }[]>( - [] - ); + const [userList, setUserList] = useState< + { title: string; key: number; is_admin: boolean; is_active: boolean }[] + >([]); + const [open, setOpen] = useState(false); + const [filterInUsers, setFilterInUsers] = useState>(new Set()); const [queryParams, setQueryParams] = useState({ page: -1 }); + const dataList = useMemo(() => { + if (filterInUsers.size === 0) { + return userList.filter((user) => { + return !user.is_admin && user.is_active; + }); + } + return userList.filter((user) => { + const isAdmin = user.is_admin; + const isActive = user.is_active; + if (!filterInUsers.has('admin') && isAdmin) { + return false; + } + if (!filterInUsers.has('inactive') && !isActive) { + return false; + } + return true; + }); + }, [userList, filterInUsers]); + const getUserList = async (query: Global.SearchParams) => { try { const res = await queryUsersList(query); const options = res.items.map((item) => ({ title: item.username, key: item.id, - is_admin: item.is_admin + is_admin: item.is_admin as boolean, + is_active: item.is_active as boolean })); setTotalPages(res.pagination.totalPage); setUserList(options); @@ -65,6 +94,30 @@ const AccessControlForm = forwardRef((props: AccessControlFormProps, ref) => { console.log('search:', dir, value); }; + const handleCheck = (e: any, type: string) => { + const newSet = new Set(filterInUsers); + if (e.target.checked) { + newSet.add(type); + } else { + newSet.delete(type); + } + setFilterInUsers(newSet); + }; + + const handleOpenChange: DropdownProps['onOpenChange'] = (nextOpen, info) => { + if (info.source === 'trigger' || nextOpen) { + setOpen(nextOpen); + } + }; + + const handleFilterChange = (e: any) => { + if (e.target.checked) { + setFilterInUsers(new Set(['admin', 'inactive'])); + } else { + setFilterInUsers(new Set()); + } + }; + useImperativeHandle(ref, () => ({ submit: () => { form.submit(); @@ -97,6 +150,51 @@ const AccessControlForm = forwardRef((props: AccessControlFormProps, ref) => { getUserList(queryParams); }, [currentData?.id]); + const renderFilterDropdown = () => { + return ( + handleCheck(e, 'admin')} + > + {intl.formatMessage({ id: 'models.table.admin' })} + + ), + key: '0' + }, + { + label: ( + handleCheck(e, 'inactive')} + > + {intl.formatMessage({ id: 'users.status.deactivate' })} + + ), + key: '1' + } + ] + }} + > + + + {intl.formatMessage({ + id: 'models.accessControlModal.includeusers' + })} + + + + + ); + }; + return (
{ name="users"> { {item.title} - {item.is_admin - ? `[${intl.formatMessage({ id: 'models.table.admin' })}]` - : ''} + {!item.is_active + ? `[${intl.formatMessage({ id: 'users.status.inactive' })}]` + : item.is_admin + ? `[${intl.formatMessage({ id: 'models.table.admin' })}]` + : ''} )} diff --git a/src/pages/llmodels/components/access-control-modal/index.tsx b/src/pages/llmodels/components/access-control-modal/index.tsx index 6a867ed9..4fa5bf5f 100644 --- a/src/pages/llmodels/components/access-control-modal/index.tsx +++ b/src/pages/llmodels/components/access-control-modal/index.tsx @@ -9,7 +9,7 @@ import AccessControlForm from './form'; const AccessControlModal: React.FC< Global.ScrollerModalProps -> = ({ open, title, currentData, action, onOk, onCancel }) => { +> = ({ open, title, currentData, action, onCancel }) => { const intl = useIntl(); const form = useRef(null); diff --git a/src/pages/llmodels/components/table-list.tsx b/src/pages/llmodels/components/table-list.tsx index 41a186be..7b138c80 100644 --- a/src/pages/llmodels/components/table-list.tsx +++ b/src/pages/llmodels/components/table-list.tsx @@ -1,4 +1,4 @@ -import { modelsExpandKeysAtom } from '@/atoms/models'; +import { modelsExpandKeysAtom, modelsSessionAtom } from '@/atoms/models'; import DeleteModal from '@/components/delete-modal'; import DropDownActions from '@/components/drop-down-actions'; import DropdownButtons from '@/components/drop-down-buttons'; @@ -137,6 +137,7 @@ const Models: React.FC = ({ isGGUF: false }); const [expandAtom, setExpandAtom] = useAtom(modelsExpandKeysAtom); + const [modelsSession, setModelsSession] = useAtom(modelsSessionAtom); const intl = useIntl(); const navigate = useNavigate(); const rowSelection = useTableRowSelection(); @@ -591,7 +592,16 @@ const Models: React.FC = ({ }); }; - const handleSubmitAccessControl = (data: any) => {}; + useEffect(() => { + if (modelsSession.source && loadend) { + handleClickDropdown({ + key: modelsSession.source + }); + } + return () => { + setModelsSession({}); + }; + }, [loadend]); return ( <> @@ -774,7 +784,6 @@ const Models: React.FC = ({ > = forwardRef( } ); -export default memo(ParamsSettings); +export default ParamsSettings; diff --git a/src/pages/playground/components/ground-tts.tsx b/src/pages/playground/components/ground-tts.tsx index d66f4a82..d7be4615 100644 --- a/src/pages/playground/components/ground-tts.tsx +++ b/src/pages/playground/components/ground-tts.tsx @@ -1,6 +1,7 @@ import { setRouteCache } from '@/atoms/route-cache'; import AlertInfo from '@/components/alert-info'; import IconFont from '@/components/icon-font'; +import AutoComplete from '@/components/seal-form/auto-complete'; import SealSelect from '@/components/seal-form/seal-select'; import SpeechContent from '@/components/speech-content'; import routeCachekey from '@/config/route-cachekey'; @@ -274,17 +275,20 @@ const GroundTTS: React.FC = forwardRef((props, ref) => { const renderExtra = useMemo(() => { return paramsConfig.map((item: ParamsSchema) => { + const comProps = { + ...item.attrs, + options: item.name === 'voice' ? voiceList : item.options, + label: item.label.isLocalized + ? intl.formatMessage({ id: item.label.text }) + : item.label.text + }; return ( - + {item.type === 'AutoComplete' ? ( + + ) : ( + + )} ); }); diff --git a/src/pages/playground/config/params-config.ts b/src/pages/playground/config/params-config.ts index e8880700..f6d1cbb3 100644 --- a/src/pages/playground/config/params-config.ts +++ b/src/pages/playground/config/params-config.ts @@ -32,7 +32,7 @@ export const imageSizeOptions: { export const TTSParamsConfig: ParamsSchema[] = [ { - type: 'Select', + type: 'AutoComplete', name: 'voice', options: [], label: { @@ -41,7 +41,7 @@ export const TTSParamsConfig: ParamsSchema[] = [ }, rules: [ { - required: true, + required: false, message: 'Voice is required' } ] diff --git a/src/pages/playground/config/types.ts b/src/pages/playground/config/types.ts index bc86b594..cdefb482 100644 --- a/src/pages/playground/config/types.ts +++ b/src/pages/playground/config/types.ts @@ -38,13 +38,13 @@ export interface MessageItem { type SchemaType = | 'Input' | 'InputNumber' - | 'Textarea' + | 'TextArea' | 'Select' | 'Slider' - | 'TextArea' - | 'Checkbox' | 'Textarea' - | 'Switch'; + | 'Checkbox' + | 'Switch' + | 'AutoComplete'; export interface ParamsSchema { type: SchemaType; diff --git a/src/pages/resources/config/gpu-driver.ts b/src/pages/resources/config/gpu-driver.ts index 4e2195df..54185e1c 100644 --- a/src/pages/resources/config/gpu-driver.ts +++ b/src/pages/resources/config/gpu-driver.ts @@ -1,12 +1,12 @@ export const GPUDriverMap = { NVIDIA: 'cuda', AMD: 'rocm', - ASCEND: 'npu', - HYGON: 'dcu', + ASCEND: 'cann', + HYGON: 'dtk', MOORE_THREADS: 'musa', ILUVATAR: 'corex', - CAMBRICON: 'cambricon', - METAX: 'metax' + CAMBRICON: 'neuware', + METAX: 'maca' }; const ManufacturerMap = { @@ -45,7 +45,7 @@ export const GPUsConfigs: Record< [GPUDriverMap.HYGON]: { label: ManufacturerMap[GPUDriverMap.HYGON], value: GPUDriverMap.HYGON, - runtime: 'dcu', // TODO: confirm runtime name + runtime: '', // TODO: confirm runtime name driver: 'hy-smi' }, [GPUDriverMap.MOORE_THREADS]: { @@ -57,7 +57,7 @@ export const GPUsConfigs: Record< [GPUDriverMap.ILUVATAR]: { label: ManufacturerMap[GPUDriverMap.ILUVATAR], value: GPUDriverMap.ILUVATAR, - runtime: 'corex', // TODO: confirm runtime name + runtime: '', // TODO: confirm runtime name driver: 'ixsmi' }, [GPUDriverMap.CAMBRICON]: { diff --git a/src/pages/resources/config/index.ts b/src/pages/resources/config/index.ts index 4c5520a0..e635047a 100644 --- a/src/pages/resources/config/index.ts +++ b/src/pages/resources/config/index.ts @@ -68,15 +68,6 @@ export const addWorkerGuide: Record = { } }; -export const containerInstallOptions = [ - { label: 'NVIDIA CUDA', value: 'cuda' }, - { label: 'AMD ROCm', value: 'rocm' }, - { label: 'Ascend CANN', value: 'npu' }, - { label: 'Hygon DTK', value: 'dcu' }, - { label: 'Moore Threads MUSA', value: 'musa' }, - { label: 'Iluvatar Corex', value: 'corex' } -]; - export const ModelfileStateMap = { Error: 'error', Downloading: 'downloading',