|
|
|
|
@ -0,0 +1,374 @@
|
|
|
|
|
import React, { useEffect, useState } from 'react' ;
|
|
|
|
|
import { Modal, Form, Select, Grid, Slider, Switch, Input, Message } from '@arco-design/web-react';
|
|
|
|
|
import EditableTable from '@/components/EditableTable';
|
|
|
|
|
import { createInstance, localStart } from '@/api/componentInstance';
|
|
|
|
|
import { getHostList } from '@/api/componentDeployEnv';
|
|
|
|
|
|
|
|
|
|
const FormItem = Form.Item;
|
|
|
|
|
const Option = Select.Option;
|
|
|
|
|
|
|
|
|
|
const runTypes = [
|
|
|
|
|
{
|
|
|
|
|
label: '本地运行',
|
|
|
|
|
value: 'local'
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
label: '线上运行',
|
|
|
|
|
value: 'online'
|
|
|
|
|
}
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
const portColumns = [
|
|
|
|
|
{
|
|
|
|
|
title: '主机端口',
|
|
|
|
|
dataIndex: 'hostPort',
|
|
|
|
|
editable: true
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
title: '容器端口',
|
|
|
|
|
dataIndex: 'containerPort',
|
|
|
|
|
editable: true
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
title: '备注',
|
|
|
|
|
dataIndex: 'remake',
|
|
|
|
|
editable: true
|
|
|
|
|
}
|
|
|
|
|
];
|
|
|
|
|
const directoryColumns = [
|
|
|
|
|
{
|
|
|
|
|
title: '主机路径',
|
|
|
|
|
dataIndex: 'hostPath',
|
|
|
|
|
editable: true
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
title: '容器路径',
|
|
|
|
|
dataIndex: 'containerPath',
|
|
|
|
|
editable: true
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
title: '备注',
|
|
|
|
|
dataIndex: 'remake',
|
|
|
|
|
editable: true
|
|
|
|
|
}
|
|
|
|
|
];
|
|
|
|
|
const deviceColumns = [
|
|
|
|
|
{
|
|
|
|
|
title: '主机路径',
|
|
|
|
|
dataIndex: 'hostPath',
|
|
|
|
|
editable: true
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
title: '容器路径',
|
|
|
|
|
dataIndex: 'containerPath',
|
|
|
|
|
editable: true
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
title: '权限',
|
|
|
|
|
dataIndex: 'permissions',
|
|
|
|
|
editable: true
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
title: '备注',
|
|
|
|
|
dataIndex: 'remake',
|
|
|
|
|
editable: true
|
|
|
|
|
}
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
const ContainerModal = ({ addItem, visible, envType, setVisible, onSuccess }) => {
|
|
|
|
|
const [form] = Form.useForm();
|
|
|
|
|
const [currentRunType, setCurrentRunType] = useState('local');
|
|
|
|
|
const [envTypeOptions, setEnvTypeOptions] = useState([]);
|
|
|
|
|
const [portMappingData, setPortMappingData] = useState([]); // 端口映射数据
|
|
|
|
|
const [directoryMountData, setDirectoryMountData] = useState([]); // 目录挂载数据
|
|
|
|
|
const [deviceMountData, setDeviceMountData] = useState([]); // 设备挂载数据
|
|
|
|
|
const [loading, setLoading] = useState(false);
|
|
|
|
|
const [hostOptions, setHostOptions] = useState([]); // 主机
|
|
|
|
|
|
|
|
|
|
const getHostOptions = async () => {
|
|
|
|
|
const res: any = await getHostList({
|
|
|
|
|
type: 'docker-env',
|
|
|
|
|
componentBaseId: addItem.componentBaseId
|
|
|
|
|
});
|
|
|
|
|
if (res.code === 200) setHostOptions(res.data);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 处理取消
|
|
|
|
|
const handleCancel = () => {
|
|
|
|
|
form.resetFields();
|
|
|
|
|
setCurrentRunType('local');
|
|
|
|
|
setPortMappingData([]);
|
|
|
|
|
setDirectoryMountData([]);
|
|
|
|
|
setDeviceMountData([]);
|
|
|
|
|
setVisible(false);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 处理确认
|
|
|
|
|
const handleOk = async () => {
|
|
|
|
|
try {
|
|
|
|
|
setLoading(true);
|
|
|
|
|
const values = await form.validate();
|
|
|
|
|
|
|
|
|
|
// 组装提交数据
|
|
|
|
|
const submitData = {
|
|
|
|
|
...values,
|
|
|
|
|
portMapping: portMappingData, // 端口映射
|
|
|
|
|
directoryMount: directoryMountData, // 目录挂载
|
|
|
|
|
deviceMount: deviceMountData, // 设备挂载
|
|
|
|
|
componentBaseId: addItem?.componentBaseId
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
console.log('提交数据:', submitData);
|
|
|
|
|
|
|
|
|
|
// TODO: 调用接口提交数据
|
|
|
|
|
// const res = await createContainerConfig(submitData);
|
|
|
|
|
// if (res.code === 200) {
|
|
|
|
|
// Message.success('容器配置成功');
|
|
|
|
|
// handleCancel();
|
|
|
|
|
// onSuccess?.();
|
|
|
|
|
// } else {
|
|
|
|
|
// Message.error('容器配置失败: ' + res.message);
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
} catch (error) {
|
|
|
|
|
console.error('表单校验失败:', error);
|
|
|
|
|
Message.error('请检查表单必填项');
|
|
|
|
|
} finally {
|
|
|
|
|
setLoading(false);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
useEffect(() => {
|
|
|
|
|
if (envType.length > 0) setEnvTypeOptions(envType);
|
|
|
|
|
}, [envType]);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
useEffect(() => {
|
|
|
|
|
if (visible) {
|
|
|
|
|
getHostOptions();
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
// 关闭时重置表单和数据
|
|
|
|
|
form.resetFields();
|
|
|
|
|
setPortMappingData([]);
|
|
|
|
|
setDirectoryMountData([]);
|
|
|
|
|
setDeviceMountData([]);
|
|
|
|
|
}
|
|
|
|
|
}, [visible]);
|
|
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
<Modal
|
|
|
|
|
title="容器配置"
|
|
|
|
|
visible={visible}
|
|
|
|
|
onOk={handleOk}
|
|
|
|
|
onCancel={handleCancel}
|
|
|
|
|
confirmLoading={loading}
|
|
|
|
|
autoFocus={false}
|
|
|
|
|
focusLock={true}
|
|
|
|
|
style={{ width: '80%' }}
|
|
|
|
|
>
|
|
|
|
|
<Form form={form} autoComplete="off" labelCol={{ flex: 'none' }}>
|
|
|
|
|
<>
|
|
|
|
|
<Grid.Row gutter={8}>
|
|
|
|
|
<Grid.Col span={12}>
|
|
|
|
|
<FormItem
|
|
|
|
|
label="部署环境:"
|
|
|
|
|
field="tags"
|
|
|
|
|
rules={[{ required: true, message: '请选择部署环境' }]}
|
|
|
|
|
>
|
|
|
|
|
<Select
|
|
|
|
|
placeholder="请选择部署环境"
|
|
|
|
|
style={{ width: '90%' }}
|
|
|
|
|
>
|
|
|
|
|
{envTypeOptions.map((option, index) => (
|
|
|
|
|
<Option key={option.id} value={option.dictKey}>
|
|
|
|
|
{option.classifyName}
|
|
|
|
|
</Option>
|
|
|
|
|
))}
|
|
|
|
|
</Select>
|
|
|
|
|
</FormItem>
|
|
|
|
|
</Grid.Col>
|
|
|
|
|
<Grid.Col span={12}>
|
|
|
|
|
<FormItem
|
|
|
|
|
label="主机:"
|
|
|
|
|
field="type"
|
|
|
|
|
rules={[{ required: true, message: '请选择主机' }]}
|
|
|
|
|
>
|
|
|
|
|
<Select
|
|
|
|
|
placeholder="请选择主机"
|
|
|
|
|
style={{ width: '90%' }}
|
|
|
|
|
>
|
|
|
|
|
{hostOptions.map((option, index) => (
|
|
|
|
|
<Option key={option.ip} value={option.id}>
|
|
|
|
|
<div style={{ display: 'flex', justifyContent: 'space-between' }}>
|
|
|
|
|
<span>{option.name}</span>
|
|
|
|
|
<span style={{ color: '#999', fontSize: 12 }}>{option.ip}</span>
|
|
|
|
|
</div>
|
|
|
|
|
</Option>
|
|
|
|
|
))}
|
|
|
|
|
</Select>
|
|
|
|
|
</FormItem>
|
|
|
|
|
</Grid.Col>
|
|
|
|
|
</Grid.Row>
|
|
|
|
|
<Grid.Row gutter={8}>
|
|
|
|
|
<Grid.Col span={12}>
|
|
|
|
|
<FormItem
|
|
|
|
|
label="CPU核数:"
|
|
|
|
|
field="cpuCores"
|
|
|
|
|
rules={[{ required: true, message: '请选择CPU核数' }]}
|
|
|
|
|
>
|
|
|
|
|
<Slider
|
|
|
|
|
defaultValue={1}
|
|
|
|
|
min={1}
|
|
|
|
|
max={4}
|
|
|
|
|
step={1}
|
|
|
|
|
showTicks={true}
|
|
|
|
|
marks={{
|
|
|
|
|
1: '1核',
|
|
|
|
|
2: '',
|
|
|
|
|
3: '',
|
|
|
|
|
4: '4核'
|
|
|
|
|
}}
|
|
|
|
|
style={{
|
|
|
|
|
width: '90%',
|
|
|
|
|
whiteSpace: 'nowrap'
|
|
|
|
|
}}
|
|
|
|
|
/>
|
|
|
|
|
</FormItem>
|
|
|
|
|
</Grid.Col>
|
|
|
|
|
<Grid.Col span={12}>
|
|
|
|
|
<FormItem
|
|
|
|
|
label="是否使用GPU:"
|
|
|
|
|
field="useGpu"
|
|
|
|
|
rules={[{ required: true, message: '请选择是否使用GPU' }]}
|
|
|
|
|
>
|
|
|
|
|
<Switch checkedText="ON" uncheckedText="OFF" />
|
|
|
|
|
</FormItem>
|
|
|
|
|
</Grid.Col>
|
|
|
|
|
</Grid.Row>
|
|
|
|
|
<FormItem
|
|
|
|
|
label="最大内存:"
|
|
|
|
|
field="maxMemory"
|
|
|
|
|
rules={[{ required: true, message: '请设置最大内存' }]}
|
|
|
|
|
>
|
|
|
|
|
<Slider
|
|
|
|
|
defaultValue={2048}
|
|
|
|
|
min={64}
|
|
|
|
|
max={4069}
|
|
|
|
|
step={64}
|
|
|
|
|
marks={{
|
|
|
|
|
64: '64MB',
|
|
|
|
|
1024: '1GB',
|
|
|
|
|
2048: '2GB',
|
|
|
|
|
4069: '4GB'
|
|
|
|
|
}}
|
|
|
|
|
showInput={{
|
|
|
|
|
hideControl: false,
|
|
|
|
|
suffix: 'MB',
|
|
|
|
|
style: {
|
|
|
|
|
width: 100
|
|
|
|
|
}
|
|
|
|
|
}}
|
|
|
|
|
style={{ width: '100%' }}
|
|
|
|
|
/>
|
|
|
|
|
</FormItem>
|
|
|
|
|
<Grid.Row gutter={8}>
|
|
|
|
|
<Grid.Col span={8}>
|
|
|
|
|
<FormItem
|
|
|
|
|
label="网络模式:"
|
|
|
|
|
field="networkMode"
|
|
|
|
|
rules={[{ required: true, message: '请选择网络模式' }]}
|
|
|
|
|
>
|
|
|
|
|
<Select
|
|
|
|
|
placeholder="请选择网络模式"
|
|
|
|
|
style={{ width: '90%' }}
|
|
|
|
|
>
|
|
|
|
|
{runTypes.map((option, index) => (
|
|
|
|
|
<Option key={option.value} value={option.value}>
|
|
|
|
|
{option.label}
|
|
|
|
|
</Option>
|
|
|
|
|
))}
|
|
|
|
|
</Select>
|
|
|
|
|
</FormItem>
|
|
|
|
|
</Grid.Col>
|
|
|
|
|
<Grid.Col span={8}>
|
|
|
|
|
<FormItem
|
|
|
|
|
label="网卡:"
|
|
|
|
|
field="networkCard"
|
|
|
|
|
rules={[{ required: true, message: '请选择网卡' }]}
|
|
|
|
|
>
|
|
|
|
|
<Select
|
|
|
|
|
placeholder="请选择网卡"
|
|
|
|
|
style={{ width: '90%' }}
|
|
|
|
|
>
|
|
|
|
|
{runTypes.map((option, index) => (
|
|
|
|
|
<Option key={option.value} value={option.value}>
|
|
|
|
|
{option.label}
|
|
|
|
|
</Option>
|
|
|
|
|
))}
|
|
|
|
|
</Select>
|
|
|
|
|
</FormItem>
|
|
|
|
|
</Grid.Col>
|
|
|
|
|
<Grid.Col span={8}>
|
|
|
|
|
<FormItem
|
|
|
|
|
label="IP:"
|
|
|
|
|
field="ip"
|
|
|
|
|
rules={[{ required: true, message: '请输入IP' }]}
|
|
|
|
|
>
|
|
|
|
|
<Input style={{ width: '90%' }} allowClear placeholder="请输入IP" />
|
|
|
|
|
</FormItem>
|
|
|
|
|
</Grid.Col>
|
|
|
|
|
</Grid.Row>
|
|
|
|
|
<FormItem label="端口映射:">
|
|
|
|
|
<EditableTable
|
|
|
|
|
columns={portColumns}
|
|
|
|
|
data={portMappingData}
|
|
|
|
|
onDataChange={(newData) => setPortMappingData(newData)}
|
|
|
|
|
showAddButton={true}
|
|
|
|
|
addButtonText="添加行"
|
|
|
|
|
showDeleteButton={true}
|
|
|
|
|
deleteButtonText="删除"
|
|
|
|
|
tableProps={{
|
|
|
|
|
pagination: { pageSize: 5 },
|
|
|
|
|
scroll: { y: 400 }
|
|
|
|
|
}}
|
|
|
|
|
/>
|
|
|
|
|
</FormItem>
|
|
|
|
|
<FormItem label="目录挂载:">
|
|
|
|
|
<EditableTable
|
|
|
|
|
columns={directoryColumns}
|
|
|
|
|
data={directoryMountData}
|
|
|
|
|
onDataChange={(newData) => setDirectoryMountData(newData)}
|
|
|
|
|
showAddButton={true}
|
|
|
|
|
addButtonText="添加行"
|
|
|
|
|
showDeleteButton={true}
|
|
|
|
|
deleteButtonText="删除"
|
|
|
|
|
tableProps={{
|
|
|
|
|
pagination: { pageSize: 5 },
|
|
|
|
|
scroll: { y: 400 }
|
|
|
|
|
}}
|
|
|
|
|
/>
|
|
|
|
|
</FormItem>
|
|
|
|
|
<FormItem label="设备挂载:">
|
|
|
|
|
<EditableTable
|
|
|
|
|
columns={deviceColumns}
|
|
|
|
|
data={deviceMountData}
|
|
|
|
|
onDataChange={(newData) => setDeviceMountData(newData)}
|
|
|
|
|
showAddButton={true}
|
|
|
|
|
addButtonText="添加行"
|
|
|
|
|
showDeleteButton={true}
|
|
|
|
|
deleteButtonText="删除"
|
|
|
|
|
tableProps={{
|
|
|
|
|
pagination: { pageSize: 5 },
|
|
|
|
|
scroll: { y: 400 }
|
|
|
|
|
}}
|
|
|
|
|
/>
|
|
|
|
|
</FormItem>
|
|
|
|
|
</>
|
|
|
|
|
</Form>
|
|
|
|
|
|
|
|
|
|
</Modal>
|
|
|
|
|
);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
export default ContainerModal;
|