diff --git a/src/api/userContainer.ts b/src/api/userContainer.ts index d184d31..553f9bf 100644 --- a/src/api/userContainer.ts +++ b/src/api/userContainer.ts @@ -21,4 +21,9 @@ export function stopContainer(deployEnvId) { // 根据组件实例ID获取容器数据 export function getContainer(deployEnvId) { return axios.get(`${urlPrefix}/userContainer/${deployEnvId}/get`); +} + +// 获取容器限制配置 +export function getContainerLimit(deployEnvId) { + return axios.get(`${urlPrefix}/userContainer/${deployEnvId}/limits`); } \ No newline at end of file diff --git a/src/pages/componentDevelopment/componentEnv/containerModal.tsx b/src/pages/componentDevelopment/componentEnv/containerModal.tsx index bda1ea6..a51cedb 100644 --- a/src/pages/componentDevelopment/componentEnv/containerModal.tsx +++ b/src/pages/componentDevelopment/componentEnv/containerModal.tsx @@ -1,7 +1,19 @@ -import React, { useEffect, useState } from 'react' ; -import { Modal, Form, Select, Grid, Slider, Switch, Input, InputNumber, Message } from '@arco-design/web-react'; +import React, { useEffect, useState, useMemo } from 'react'; +import { + Modal, + Form, + Select, + Grid, + Slider, + Switch, + Input, + InputNumber, + Message, + Button, + Spin +} from '@arco-design/web-react'; import EditableTable from '@/components/EditableTable'; -import { containerRegister } from '@/api/userContainer'; +import { containerRegister, getContainerLimit } from '@/api/userContainer'; import { getNetworkMode } from '@/api/componentDeploy'; const FormItem = Form.Item; @@ -124,6 +136,12 @@ const ContainerModal = ({ addItem, visible, envType, setVisible, onSuccess }) => const [currentNetworkCard, setCurrentNetworkCard] = useState(''); // 当前选择的网卡 const [currentIp, setCurrentIp] = useState(''); // 当前输入的IP + const [containerConfig, setContainerConfig] = useState<{ + maxCpuCores: number, + maxMemoryMiB: number + }>({ maxCpuCores: 4, maxMemoryMiB: 4096 }); // 容器配置数据 + const [configLoaded, setConfigLoaded] = useState(false); // 容器配置是否已加载 + const [configLoading, setConfigLoading] = useState(false); // 容器配置加载中 // 处理取消 const handleCancel = () => { @@ -135,6 +153,8 @@ const ContainerModal = ({ addItem, visible, envType, setVisible, onSuccess }) => setSelectedNetworkType([]); setCurrentNetworkCard(''); setCurrentIp(''); + setConfigLoaded(false); + setConfigLoading(false); setVisible(false); }; @@ -168,7 +188,7 @@ const ContainerModal = ({ addItem, visible, envType, setVisible, onSuccess }) => volumes: directoryMountData, // 目录挂载 devices: deviceMountData, // 设备挂载 // 下面是暂时写死的数据, - 'restartPolicy': 'always', + 'restartPolicy': 'always' }; const res: any = await containerRegister(submitData); @@ -189,6 +209,51 @@ const ContainerModal = ({ addItem, visible, envType, setVisible, onSuccess }) => } }; + const getContainerConfig = async () => { + setConfigLoading(true); + try { + const res: any = await getContainerLimit(addItem.id); + if (res.code === 200) { + setContainerConfig(res.data); + setConfigLoaded(true); + // 设置表单默认值 + form.setFieldsValue({ + cpuCount: 1, + memory: 2048, + useGpu: false + }); + } + } finally { + setConfigLoading(false); + } + }; + + // 动态生成CPU核数的marks + const cpuMarks = useMemo(() => { + const max = containerConfig.maxCpuCores; + const marks: Record = {}; + marks[1] = '1核'; + if (max > 1) marks[max] = `${max}核`; + // 中间值不显示文字 + for (let i = 2; i < max; i++) { + marks[i] = ''; + } + return marks; + }, [containerConfig.maxCpuCores]); + + // 动态生成内存的marks (按2的幂次方: 1, 2, 4, 8, 16GB) + const memoryMarks = useMemo(() => { + const max = containerConfig.maxMemoryMiB; + const marks: Record = {}; + for (let gb = 2; gb <= 128; gb *= 2) { + const mb = gb * 1024; + if (mb <= max) { + marks[mb] = `${gb}GB`; + } + } + return marks; + }, [containerConfig.maxMemoryMiB]); + useEffect(() => { if (envType.length > 0) setEnvTypeOptions(envType); }, [envType]); @@ -196,12 +261,7 @@ const ContainerModal = ({ addItem, visible, envType, setVisible, onSuccess }) => useEffect(() => { if (visible) { - // 设置表单默认值 - form.setFieldsValue({ - cpuCount: 1, - memory: 2048, - useGpu: false - }); + // 不再自动加载,等用户点击按钮 } else { // 关闭时重置表单和数据 @@ -213,6 +273,8 @@ const ContainerModal = ({ addItem, visible, envType, setVisible, onSuccess }) => setSelectedNetworkType([]); setCurrentNetworkCard(''); setCurrentIp(''); + setConfigLoaded(false); + setConfigLoading(false); } }, [visible]); @@ -228,195 +290,209 @@ const ContainerModal = ({ addItem, visible, envType, setVisible, onSuccess }) => style={{ width: '80%' }} >
- <> - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + )} + + {/* 以下配置默认展示 */} + + + + + + + + + { - setCurrentIp(value); - form.setFieldValue('ip', value); - }} - onBlur={(e) => { - const value = e.target.value; - if (value) { - // IP地址正则表达式 - const ipRegex = /^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/; - if (!ipRegex.test(value)) { - Message.warning('请输入有效的IP地址'); - } + {networkTypeList.map((option, index) => ( + + ))} + + + + + + { + setCurrentIp(value); + form.setFieldValue('ip', value); + }} + onBlur={(e) => { + const value = e.target.value; + if (value) { + // IP地址正则表达式 + const ipRegex = /^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/; + if (!ipRegex.test(value)) { + Message.warning('请输入有效的IP地址'); } - }} - /> -
所属子网: {selectedNetworkType.length > 0 ? selectedNetworkType[0]?.subnet : '-'}
-
-
-
- - setPortMappingData(newData)} - showAddButton={true} - addButtonText="添加行" - showDeleteButton={true} - deleteButtonText="删除" - tableProps={{ - pagination: { pageSize: 5 }, - scroll: { y: 400 } - }} - /> - - - setDirectoryMountData(newData)} - showAddButton={true} - addButtonText="添加行" - showDeleteButton={true} - deleteButtonText="删除" - tableProps={{ - pagination: { pageSize: 5 }, - scroll: { y: 400 } - }} - /> - - - setDeviceMountData(newData)} - showAddButton={true} - addButtonText="添加行" - showDeleteButton={true} - deleteButtonText="删除" - tableProps={{ - pagination: { pageSize: 5 }, - scroll: { y: 400 } - }} - /> - - + } + }} + /> +
所属子网: {selectedNetworkType.length > 0 ? selectedNetworkType[0]?.subnet : '-'}
+ + + + + setPortMappingData(newData)} + showAddButton={true} + addButtonText="添加行" + showDeleteButton={true} + deleteButtonText="删除" + tableProps={{ + pagination: { pageSize: 5 }, + scroll: { y: 400 } + }} + /> + + + setDirectoryMountData(newData)} + showAddButton={true} + addButtonText="添加行" + showDeleteButton={true} + deleteButtonText="删除" + tableProps={{ + pagination: { pageSize: 5 }, + scroll: { y: 400 } + }} + /> + + + setDeviceMountData(newData)} + showAddButton={true} + addButtonText="添加行" + showDeleteButton={true} + deleteButtonText="删除" + tableProps={{ + pagination: { pageSize: 5 }, + scroll: { y: 400 } + }} + /> +