From 7fd2b4370406bd10d51d602f431865bd72fe1838 Mon Sep 17 00:00:00 2001 From: jialin Date: Wed, 4 Feb 2026 14:57:53 +0800 Subject: [PATCH] fix: refresh enable backend state --- src/atoms/backend.ts | 3 ++ src/hooks/use-table-fetch.ts | 1 + src/locales/en-US/backends.ts | 2 +- src/locales/en-US/clusters.ts | 2 +- src/locales/en-US/users.ts | 2 +- src/locales/ja-JP/backends.ts | 2 +- src/locales/ja-JP/clusters.ts | 4 +- src/locales/ja-JP/users.ts | 4 +- src/locales/ru-RU/backends.ts | 4 +- src/locales/ru-RU/clusters.ts | 2 +- src/locales/zh-CN/clusters.ts | 4 +- src/locales/zh-CN/models.ts | 2 +- .../community/add-community-modal.tsx | 16 +++++- .../backends/community/commnity-backends.tsx | 53 ++++++++++++++----- 14 files changed, 74 insertions(+), 27 deletions(-) create mode 100644 src/atoms/backend.ts diff --git a/src/atoms/backend.ts b/src/atoms/backend.ts new file mode 100644 index 00000000..f222d521 --- /dev/null +++ b/src/atoms/backend.ts @@ -0,0 +1,3 @@ +import { atom } from 'jotai'; + +export const enabledBackendsAtom = atom(null); diff --git a/src/hooks/use-table-fetch.ts b/src/hooks/use-table-fetch.ts index 3cbc74ba..c46902df 100644 --- a/src/hooks/use-table-fetch.ts +++ b/src/hooks/use-table-fetch.ts @@ -430,6 +430,7 @@ export default function useTableFetch( extraStatus, TABLE_SORT_DIRECTIONS, debounceFetchData, + setDataSource, setQueryParams, handleDelete, handleDeleteBatch, diff --git a/src/locales/en-US/backends.ts b/src/locales/en-US/backends.ts index 3feda808..64ed1a04 100644 --- a/src/locales/en-US/backends.ts +++ b/src/locales/en-US/backends.ts @@ -44,5 +44,5 @@ export default { 'backend.filter.source': 'Filter by source', 'backend.add.custom': 'Custom', 'backend.add.community': 'Community Backends', - 'backend.community.title': 'Community Backends Marketplace' + 'backend.community.title': 'Community Backend Marketplace' }; diff --git a/src/locales/en-US/clusters.ts b/src/locales/en-US/clusters.ts index c585f421..e5660196 100644 --- a/src/locales/en-US/clusters.ts +++ b/src/locales/en-US/clusters.ts @@ -113,7 +113,7 @@ export default { 'clusters.table.ip.internal': 'Internal', 'clusters.table.ip.external': 'External', 'clusters.form.serverUrl.tips': - 'Specify an externally accessible GPUStack service URL if the worker cannot access GPUStack directly.', + 'Specify an externally accessible GPUStack service URL if the worker cannot access GPUStack Server directly.', 'clusters.form.setDefault': 'Set as Default', 'clusters.form.setDefault.tips': 'Default for deployment.', 'clusters.addworker.noClusters': 'No available Docker clusters found', diff --git a/src/locales/en-US/users.ts b/src/locales/en-US/users.ts index 8b64f9bf..d18098c4 100644 --- a/src/locales/en-US/users.ts +++ b/src/locales/en-US/users.ts @@ -39,5 +39,5 @@ export default { 'users.status.deactivate': 'Deactivate Account', 'users.status.inactiveAccount': 'Inactive Account', 'users.login.getInitialPassword': - 'Run the following command on your server to retrieve the initial admin password.' + 'Run the following command on your GPUStack Server to retrieve the initial admin password.' }; diff --git a/src/locales/ja-JP/backends.ts b/src/locales/ja-JP/backends.ts index 3feda808..64ed1a04 100644 --- a/src/locales/ja-JP/backends.ts +++ b/src/locales/ja-JP/backends.ts @@ -44,5 +44,5 @@ export default { 'backend.filter.source': 'Filter by source', 'backend.add.custom': 'Custom', 'backend.add.community': 'Community Backends', - 'backend.community.title': 'Community Backends Marketplace' + 'backend.community.title': 'Community Backend Marketplace' }; diff --git a/src/locales/ja-JP/clusters.ts b/src/locales/ja-JP/clusters.ts index f4a64699..922a707f 100644 --- a/src/locales/ja-JP/clusters.ts +++ b/src/locales/ja-JP/clusters.ts @@ -113,7 +113,7 @@ export default { 'clusters.table.ip.internal': 'Internal', 'clusters.table.ip.external': 'External', 'clusters.form.serverUrl.tips': - 'Specify an externally accessible GPUStack service URL if the worker cannot access GPUStack directly.', + 'Specify an externally accessible GPUStack service URL if the worker cannot access GPUStack Server directly.', 'clusters.form.setDefault': 'Set as Default', 'clusters.form.setDefault.tips': 'Default for deployment.', 'clusters.addworker.noClusters': 'No available Docker clusters found', @@ -217,7 +217,7 @@ export default { // 78. 'clusters.addworker.dataVolume.tips': 'Specify a data storage path for GPUStack.', // 79. 'clusters.table.ip.internal': 'Internal', // 80. 'clusters.table.ip.external': 'External', -// 81. 'clusters.form.serverUrl.tips': 'Specify an externally accessible GPUStack service URL if the worker cannot access GPUStack directly.', +// 81. 'clusters.form.serverUrl.tips': 'Specify an externally accessible GPUStack service URL if the worker cannot access GPUStack Server directly.', // 82. 'clusters.addworker.externalIP.tips': 'Specify an external IP if the worker is in a VPC or private network.', // 83. 'clusters.form.setDefault': 'Set as Default', // 84. 'clusters.form.setDefault.tips': 'Default for deployment', diff --git a/src/locales/ja-JP/users.ts b/src/locales/ja-JP/users.ts index a28b77e7..090ce1a0 100644 --- a/src/locales/ja-JP/users.ts +++ b/src/locales/ja-JP/users.ts @@ -40,7 +40,7 @@ export default { 'users.status.deactivate': 'Deactivate Account', 'users.status.inactiveAccount': 'Inactive Account', 'users.login.getInitialPassword': - 'Run the following command on your server to retrieve the initial admin password.' + 'Run the following command on your GPUStack Server to retrieve the initial admin password.' }; // ========== To-Do: Translate Keys (Remove After Translation) ========== @@ -48,5 +48,5 @@ export default { // 2. 'users.status.activate': 'Activate Account', // 3. 'users.status.deactivate': 'Deactivate Account', // 4. 'users.status.inactiveAccount': 'Inactive Account', -// 5. 'users.login.getInitialPassword': 'Run the following command on your server to retrieve the initial admin password.' +// 5. 'users.login.getInitialPassword': 'Run the following command on your GPUStack Server to retrieve the initial admin password.' // ========== End of To-Do List ========== diff --git a/src/locales/ru-RU/backends.ts b/src/locales/ru-RU/backends.ts index 9e9dfc9b..3bcabf40 100644 --- a/src/locales/ru-RU/backends.ts +++ b/src/locales/ru-RU/backends.ts @@ -44,7 +44,7 @@ export default { 'backend.filter.source': 'Filter by source', 'backend.add.custom': 'Custom', 'backend.add.community': 'Community Backends', - 'backend.community.title': 'Community Backends Marketplace' + 'backend.community.title': 'Community Backend Marketplace' }; // ========== To-Do: Translate Keys (Remove After Translation) ========== @@ -53,5 +53,5 @@ export default { // 3. 'backend.filter.source': 'Filter by source', // 4. 'backend.add.custom': 'Custom', // 5. 'backend.add.community': 'Community Backends', -// 6. 'backend.community.title': 'Community Backends Marketplace' +// 6. 'backend.community.title': 'Community Backend Marketplace' // ========== End of To-Do List ========== diff --git a/src/locales/ru-RU/clusters.ts b/src/locales/ru-RU/clusters.ts index b841564a..364f2ade 100644 --- a/src/locales/ru-RU/clusters.ts +++ b/src/locales/ru-RU/clusters.ts @@ -113,7 +113,7 @@ export default { 'clusters.table.ip.internal': 'Внутренний', 'clusters.table.ip.external': 'Внешний', 'clusters.form.serverUrl.tips': - 'Если рабочий узел не может напрямую получить доступ к GPUStack, укажите внешний URL службы GPUStack.', + 'Если рабочий узел не может напрямую получить доступ к GPUStack Server, укажите внешний URL службы GPUStack Server.', 'clusters.form.setDefault': 'Установить по умолчанию', 'clusters.form.setDefault.tips': 'Использовать по умолчанию для развертывания.', diff --git a/src/locales/zh-CN/clusters.ts b/src/locales/zh-CN/clusters.ts index cc9fda88..2349947a 100644 --- a/src/locales/zh-CN/clusters.ts +++ b/src/locales/zh-CN/clusters.ts @@ -102,7 +102,7 @@ export default { '已将 {count} 个新节点添加到集群中。', 'clusters.addworker.message.success_multiple': '已将 {count} 个新节点添加到集群中。', - 'clusters.create.serverUrl': 'GPUStack 服务地址', + 'clusters.create.serverUrl': 'GPUStack Server 节点地址', 'clusters.create.workerConfig': '节点配置', 'clusters.addworker.containerName': '节点容器名称', 'clusters.addworker.containerName.tips': '为节点容器指定一个名称。', @@ -111,7 +111,7 @@ export default { 'clusters.table.ip.internal': '内', 'clusters.table.ip.external': '外', 'clusters.form.serverUrl.tips': - '如果节点无法直接访问 GPUStack,则指定一个可访问的外部 GPUStack 服务地址。', + '如果节点无法直接访问 GPUStack Server,则指定一个可访问的外部 GPUStack Server 地址。', 'clusters.form.setDefault': '设为默认', 'clusters.form.setDefault.tips': '部署时的默认集群。', 'clusters.addworker.noClusters': '无可用的 Docker 集群', diff --git a/src/locales/zh-CN/models.ts b/src/locales/zh-CN/models.ts index a9d67e84..da5683c0 100644 --- a/src/locales/zh-CN/models.ts +++ b/src/locales/zh-CN/models.ts @@ -258,7 +258,7 @@ export default { 'models.form.backendVersions.tips': `如需使用更多版本,请前往{link}页面并编辑对应的后端以添加版本。`, 'models.catalog.nogpus.tips': '所选集群中没有兼容该模型的 GPU。', 'models.form.modelfile.notfound': - '你指定的模型文件路径在 GPUStack 服务器上不存在。建议在 GPUStack 服务器和 GPUStack 节点上使用相同的模型文件路径,这有助于 GPUStack 做出更优的调度与决策。', + '你指定的模型文件路径在 GPUStack Server 节点上不存在。建议在 GPUStack Server 节点和 GPUStack 节点上使用相同的模型文件路径,这有助于 GPUStack 做出更优的调度与决策。', 'models.form.readyWorkers': '节点就绪', 'models.form.maxContextLength': '最大上下文长度', 'models.form.backend.helperText': '该社区后端暂未启用,部署后将自动启用', diff --git a/src/pages/backends/community/add-community-modal.tsx b/src/pages/backends/community/add-community-modal.tsx index 61b5a051..0aefd752 100644 --- a/src/pages/backends/community/add-community-modal.tsx +++ b/src/pages/backends/community/add-community-modal.tsx @@ -1,8 +1,10 @@ +import { enabledBackendsAtom } from '@/atoms/backend'; import GSDrawer from '@/components/scroller-modal/gs-drawer'; import ColumnWrapper from '@/pages/_components/column-wrapper'; import Separator from '@/pages/llmodels/components/separator'; import { useIntl } from '@umijs/max'; -import React from 'react'; +import { useAtom } from 'jotai'; +import React, { useEffect } from 'react'; import styled from 'styled-components'; import { ListItem } from '../config/types'; import useEnableBackend from '../services/use-enable-backend'; @@ -23,6 +25,7 @@ const AddCommunityModal: React.FC<{ const intl = useIntl(); const { handleEnableBackend } = useEnableBackend(); const [currentData, setCurrentData] = React.useState(null); + const [, setEnabledBackendAtom] = useAtom(enabledBackendsAtom); const handleOnEnable = async (checked: boolean, data: ListItem) => { await handleEnableBackend({ @@ -32,12 +35,23 @@ const AddCommunityModal: React.FC<{ enabled: checked } }); + setEnabledBackendAtom({ + ...data, + enabled: checked + }); onRefresh?.(); }; const handleOnClick = (data: ListItem) => { setCurrentData(data); }; + + useEffect(() => { + if (!open) { + setEnabledBackendAtom(null); + } + }, [open]); + return ( void; }> = ({ onEnable, onClick }) => { const intl = useIntl(); + const [enabledBackendAtom] = useAtom(enabledBackendsAtom); const [currentData, setCurrentData] = React.useState(null); - const { dataSource, loadMore, queryParams, handleSearch, handleNameChange } = - useTableFetch({ - fetchAPI: queryBackendsList, - API: INFERENCE_BACKEND_API, - watch: false, - isInfiniteScroll: true, - contentForDelete: 'backends.title', - defaultQueryParams: { - perPage: 24, - community: 1 - } - }); + const { + dataSource, + loadMore, + queryParams, + handleSearch, + setDataSource, + handleNameChange + } = useTableFetch({ + fetchAPI: queryBackendsList, + API: INFERENCE_BACKEND_API, + watch: false, + isInfiniteScroll: true, + contentForDelete: 'backends.title', + defaultQueryParams: { + perPage: 24, + community: 1 + } + }); + + useEffect(() => { + if (enabledBackendAtom) { + setDataSource((prev) => { + const newDataList = prev.dataList.map((item) => { + if (item.id === enabledBackendAtom.id) { + return { + ...item, + enabled: enabledBackendAtom.enabled + }; + } + return item; + }); + return { + ...prev, + dataList: newDataList + }; + }); + } + }, [enabledBackendAtom]); const handleOnClickItem = (data: ListItem) => { onClick(data);