1
This commit is contained in:
parent
b7d77c8033
commit
dbbabdcca4
@ -1,4 +1,4 @@
|
|||||||
import React, {useEffect, useState} from 'react';
|
import React, {useEffect, useState, useCallback} from 'react';
|
||||||
import {Modal, Form, Select, message, Switch, InputNumber} from 'antd';
|
import {Modal, Form, Select, message, Switch, InputNumber} from 'antd';
|
||||||
import type {DeploymentConfig, DeployConfigTemplate} from '../types';
|
import type {DeploymentConfig, DeployConfigTemplate} from '../types';
|
||||||
import {createDeploymentConfig, updateDeploymentConfig, getDeployConfigTemplates} from '../service';
|
import {createDeploymentConfig, updateDeploymentConfig, getDeployConfigTemplates} from '../service';
|
||||||
@ -8,11 +8,12 @@ import {BetaSchemaForm} from '@ant-design/pro-form';
|
|||||||
import {convertJsonSchemaToColumns} from '@/utils/jsonSchemaUtils';
|
import {convertJsonSchemaToColumns} from '@/utils/jsonSchemaUtils';
|
||||||
import './styles.less';
|
import './styles.less';
|
||||||
import {Editor} from '@/components/Editor';
|
import {Editor} from '@/components/Editor';
|
||||||
|
import type {JsonNode} from '@/types/common';
|
||||||
|
|
||||||
const {Option} = Select;
|
const {Option} = Select;
|
||||||
|
|
||||||
interface DeploymentConfigModalProps {
|
interface DeploymentConfigModalProps {
|
||||||
visible: boolean;
|
open: boolean;
|
||||||
onCancel: () => void;
|
onCancel: () => void;
|
||||||
onSuccess: () => void;
|
onSuccess: () => void;
|
||||||
initialValues?: DeploymentConfig;
|
initialValues?: DeploymentConfig;
|
||||||
@ -20,7 +21,7 @@ interface DeploymentConfigModalProps {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const DeploymentConfigModal: React.FC<DeploymentConfigModalProps> = ({
|
const DeploymentConfigModal: React.FC<DeploymentConfigModalProps> = ({
|
||||||
visible,
|
open,
|
||||||
onCancel,
|
onCancel,
|
||||||
onSuccess,
|
onSuccess,
|
||||||
initialValues,
|
initialValues,
|
||||||
@ -31,39 +32,40 @@ const DeploymentConfigModal: React.FC<DeploymentConfigModalProps> = ({
|
|||||||
const [templates, setTemplates] = useState<DeployConfigTemplate[]>([]);
|
const [templates, setTemplates] = useState<DeployConfigTemplate[]>([]);
|
||||||
const [selectedTemplate, setSelectedTemplate] = useState<DeployConfigTemplate>();
|
const [selectedTemplate, setSelectedTemplate] = useState<DeployConfigTemplate>();
|
||||||
const [buildVariables, setBuildVariables] = useState<Record<string, any>>({});
|
const [buildVariables, setBuildVariables] = useState<Record<string, any>>({});
|
||||||
|
const [loading, setLoading] = useState(false);
|
||||||
const isEdit = !!initialValues?.id;
|
const isEdit = !!initialValues?.id;
|
||||||
|
|
||||||
// 获取应用列表
|
// 获取应用列表
|
||||||
const fetchApplications = async () => {
|
const fetchApplications = useCallback(async () => {
|
||||||
try {
|
try {
|
||||||
const data = await getApplicationList();
|
const data = await getApplicationList();
|
||||||
setApplications(data);
|
setApplications(data);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
message.error('获取应用列表失败');
|
message.error('获取应用列表失败');
|
||||||
}
|
}
|
||||||
};
|
}, []);
|
||||||
|
|
||||||
// 获取配置模板
|
// 获取配置模板
|
||||||
const fetchTemplates = async () => {
|
const fetchTemplates = useCallback(async () => {
|
||||||
try {
|
try {
|
||||||
const data = await getDeployConfigTemplates();
|
const data = await getDeployConfigTemplates();
|
||||||
setTemplates(data);
|
setTemplates(data);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
message.error('获取配置模板失败');
|
message.error('获取配置模板失败');
|
||||||
}
|
}
|
||||||
};
|
}, []);
|
||||||
|
|
||||||
// 在模态框显示时获取数据
|
// 在模态框显示时获取数据
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (visible) {
|
if (open) {
|
||||||
fetchApplications();
|
fetchApplications();
|
||||||
fetchTemplates();
|
fetchTemplates();
|
||||||
}
|
}
|
||||||
}, [visible]);
|
}, [open, fetchApplications, fetchTemplates]);
|
||||||
|
|
||||||
// 初始化表单数据
|
// 初始化表单数据
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!visible) return;
|
if (!open) return;
|
||||||
|
|
||||||
if (initialValues) {
|
if (initialValues) {
|
||||||
form.setFieldsValue(initialValues);
|
form.setFieldsValue(initialValues);
|
||||||
@ -82,9 +84,9 @@ const DeploymentConfigModal: React.FC<DeploymentConfigModalProps> = ({
|
|||||||
setSelectedTemplate(undefined);
|
setSelectedTemplate(undefined);
|
||||||
setBuildVariables({});
|
setBuildVariables({});
|
||||||
}
|
}
|
||||||
}, [visible, initialValues, envId, form, templates]);
|
}, [open, initialValues, envId, form, templates]);
|
||||||
|
|
||||||
const handleAppChange = (appId: number) => {
|
const handleAppChange = useCallback((appId: number) => {
|
||||||
const app = applications.find(a => a.id === appId);
|
const app = applications.find(a => a.id === appId);
|
||||||
if (app) {
|
if (app) {
|
||||||
const template = templates.find(t => t.languageType === app.language);
|
const template = templates.find(t => t.languageType === app.language);
|
||||||
@ -94,10 +96,11 @@ const DeploymentConfigModal: React.FC<DeploymentConfigModalProps> = ({
|
|||||||
form.setFieldValue('templateCode', template.code);
|
form.setFieldValue('templateCode', template.code);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
}, [applications, templates, form]);
|
||||||
|
|
||||||
const handleSubmit = async () => {
|
const handleSubmit = async () => {
|
||||||
try {
|
try {
|
||||||
|
setLoading(true);
|
||||||
const values = await form.validateFields();
|
const values = await form.validateFields();
|
||||||
const submitData = {
|
const submitData = {
|
||||||
...values,
|
...values,
|
||||||
@ -116,13 +119,19 @@ const DeploymentConfigModal: React.FC<DeploymentConfigModalProps> = ({
|
|||||||
form.resetFields();
|
form.resetFields();
|
||||||
onSuccess();
|
onSuccess();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
message.error(`${isEdit ? '更新' : '创建'}失败`);
|
if (error instanceof Error) {
|
||||||
|
message.error(`${isEdit ? '更新' : '创建'}失败: ${error.message}`);
|
||||||
|
} else {
|
||||||
|
message.error(`${isEdit ? '更新' : '创建'}失败`);
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
setLoading(false);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// 渲染表单项
|
// 渲染表单项
|
||||||
const renderFormItems = () => {
|
const renderFormItems = () => {
|
||||||
if (!selectedTemplate?.buildVariablesSchema) return null;
|
if (!selectedTemplate?.buildVariablesSchema?.properties) return null;
|
||||||
|
|
||||||
const { properties } = selectedTemplate.buildVariablesSchema;
|
const { properties } = selectedTemplate.buildVariablesSchema;
|
||||||
|
|
||||||
@ -142,10 +151,10 @@ const DeploymentConfigModal: React.FC<DeploymentConfigModalProps> = ({
|
|||||||
defaultLanguage={property.editorConfig.language || 'shell'}
|
defaultLanguage={property.editorConfig.language || 'shell'}
|
||||||
theme={property.editorConfig.theme || 'vs-dark'}
|
theme={property.editorConfig.theme || 'vs-dark'}
|
||||||
value={buildVariables[key] || property.default || ''}
|
value={buildVariables[key] || property.default || ''}
|
||||||
onChange={(value) => setBuildVariables({
|
onChange={(value: string) => setBuildVariables(prev => ({
|
||||||
...buildVariables,
|
...prev,
|
||||||
[key]: value || ''
|
[key]: value || ''
|
||||||
})}
|
}))}
|
||||||
options={{
|
options={{
|
||||||
minimap: { enabled: property.editorConfig.minimap ?? false },
|
minimap: { enabled: property.editorConfig.minimap ?? false },
|
||||||
fontSize: property.editorConfig.fontSize || 14,
|
fontSize: property.editorConfig.fontSize || 14,
|
||||||
@ -186,15 +195,15 @@ const DeploymentConfigModal: React.FC<DeploymentConfigModalProps> = ({
|
|||||||
columns={convertJsonSchemaToColumns({
|
columns={convertJsonSchemaToColumns({
|
||||||
type: 'object',
|
type: 'object',
|
||||||
properties: Object.fromEntries(
|
properties: Object.fromEntries(
|
||||||
Object.entries(properties).filter(([_, prop]) => !prop.editorConfig)
|
Object.entries(properties || {}).filter(([_, prop]) => !prop.editorConfig)
|
||||||
),
|
),
|
||||||
required: selectedTemplate.buildVariablesSchema.required || []
|
required: selectedTemplate.buildVariablesSchema.required || []
|
||||||
})}
|
})}
|
||||||
initialValues={buildVariables}
|
initialValues={buildVariables}
|
||||||
onValuesChange={(_, values) => setBuildVariables({
|
onValuesChange={(_, values) => setBuildVariables(prev => ({
|
||||||
...buildVariables,
|
...prev,
|
||||||
...values
|
...values
|
||||||
})}
|
}))}
|
||||||
/>
|
/>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
@ -203,7 +212,7 @@ const DeploymentConfigModal: React.FC<DeploymentConfigModalProps> = ({
|
|||||||
return (
|
return (
|
||||||
<Modal
|
<Modal
|
||||||
title={`${isEdit ? '编辑' : '新建'}部署配置`}
|
title={`${isEdit ? '编辑' : '新建'}部署配置`}
|
||||||
open={visible}
|
open={open}
|
||||||
onCancel={() => {
|
onCancel={() => {
|
||||||
form.resetFields();
|
form.resetFields();
|
||||||
onCancel();
|
onCancel();
|
||||||
@ -212,6 +221,8 @@ const DeploymentConfigModal: React.FC<DeploymentConfigModalProps> = ({
|
|||||||
width={800}
|
width={800}
|
||||||
className="deployment-config-modal"
|
className="deployment-config-modal"
|
||||||
maskClosable={false}
|
maskClosable={false}
|
||||||
|
confirmLoading={loading}
|
||||||
|
destroyOnClose
|
||||||
>
|
>
|
||||||
<Form
|
<Form
|
||||||
form={form}
|
form={form}
|
||||||
@ -251,6 +262,7 @@ const DeploymentConfigModal: React.FC<DeploymentConfigModalProps> = ({
|
|||||||
name="enabled"
|
name="enabled"
|
||||||
label="状态"
|
label="状态"
|
||||||
valuePropName="checked"
|
valuePropName="checked"
|
||||||
|
tooltip="是否启用该配置"
|
||||||
>
|
>
|
||||||
<Switch checkedChildren="启用" unCheckedChildren="禁用" />
|
<Switch checkedChildren="启用" unCheckedChildren="禁用" />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
@ -258,15 +270,9 @@ const DeploymentConfigModal: React.FC<DeploymentConfigModalProps> = ({
|
|||||||
<Form.Item
|
<Form.Item
|
||||||
name="sort"
|
name="sort"
|
||||||
label="排序"
|
label="排序"
|
||||||
required
|
|
||||||
tooltip="数字越小越靠前"
|
tooltip="数字越小越靠前"
|
||||||
>
|
>
|
||||||
<InputNumber
|
<InputNumber min={0} style={{ width: '100%' }} />
|
||||||
min={0}
|
|
||||||
max={999}
|
|
||||||
style={{ width: '100%' }}
|
|
||||||
placeholder="请输入排序号"
|
|
||||||
/>
|
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
</Form>
|
</Form>
|
||||||
</Modal>
|
</Modal>
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
import React, {useState, useEffect} from 'react';
|
import React, {useState, useEffect} from 'react';
|
||||||
import {PageContainer} from '@ant-design/pro-layout';
|
import {PageContainer} from '@ant-design/pro-layout';
|
||||||
import {Button, message, Popconfirm, Select} from 'antd';
|
import {Button, message, Popconfirm, Select, Space} from 'antd';
|
||||||
import {PlusOutlined, EditOutlined, DeleteOutlined} from '@ant-design/icons';
|
import {PlusOutlined, EditOutlined, DeleteOutlined} from '@ant-design/icons';
|
||||||
import {getDeploymentConfigPage, deleteDeploymentConfig} from './service';
|
import {getDeploymentConfigPage, deleteDeploymentConfig} from './service';
|
||||||
import {getEnvironmentList} from '../../Environment/List/service';
|
import {getEnvironmentList} from '../../Environment/List/service';
|
||||||
@ -65,12 +65,15 @@ const DeploymentConfigList: React.FC = () => {
|
|||||||
actionRef.current?.reload();
|
actionRef.current?.reload();
|
||||||
};
|
};
|
||||||
|
|
||||||
const renderResourceInfo = (resources?: { cpu?: string; memory?: string }) => {
|
const handleModalClose = () => {
|
||||||
if (!resources?.cpu && !resources?.memory) return '-';
|
setModalVisible(false);
|
||||||
const items = [];
|
setCurrentConfig(undefined);
|
||||||
if (resources.cpu) items.push(`CPU: ${resources.cpu}`);
|
};
|
||||||
if (resources.memory) items.push(`内存: ${resources.memory}`);
|
|
||||||
return items.join(' / ');
|
const handleSuccess = () => {
|
||||||
|
setModalVisible(false);
|
||||||
|
setCurrentConfig(undefined);
|
||||||
|
actionRef.current?.reload();
|
||||||
};
|
};
|
||||||
|
|
||||||
const columns: ProColumns<DeploymentConfig>[] = [
|
const columns: ProColumns<DeploymentConfig>[] = [
|
||||||
@ -105,74 +108,49 @@ const DeploymentConfigList: React.FC = () => {
|
|||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
|
||||||
title: '部署配置',
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
title: '副本数',
|
|
||||||
dataIndex: ['deployConfig', 'replicas'],
|
|
||||||
width: 100,
|
|
||||||
align: 'center',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: '容器端口',
|
|
||||||
dataIndex: ['deployConfig', 'containerPort'],
|
|
||||||
width: 100,
|
|
||||||
align: 'center',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
title: '状态',
|
title: '状态',
|
||||||
dataIndex: 'enabled',
|
dataIndex: 'enabled',
|
||||||
width: 100,
|
width: 100,
|
||||||
align: 'center',
|
|
||||||
valueEnum: {
|
valueEnum: {
|
||||||
true: {text: '启用', status: 'Success'},
|
true: {text: '启用', status: 'Success'},
|
||||||
false: {text: '禁用', status: 'Default'},
|
false: {text: '禁用', status: 'Default'},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
|
||||||
title: '排序',
|
|
||||||
dataIndex: 'sort',
|
|
||||||
width: 80,
|
|
||||||
align: 'center',
|
|
||||||
sorter: true,
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
title: '操作',
|
title: '操作',
|
||||||
width: 180,
|
width: 180,
|
||||||
key: 'action',
|
key: 'action',
|
||||||
valueType: 'option',
|
valueType: 'option',
|
||||||
fixed: 'right',
|
fixed: 'right',
|
||||||
align: 'center',
|
render: (_, record) => [
|
||||||
render: (_, record) => {
|
<Button
|
||||||
const buttons = [
|
key="edit"
|
||||||
|
type="link"
|
||||||
|
onClick={() => handleEdit(record)}
|
||||||
|
>
|
||||||
|
<Space>
|
||||||
|
<EditOutlined />
|
||||||
|
编辑
|
||||||
|
</Space>
|
||||||
|
</Button>,
|
||||||
|
<Popconfirm
|
||||||
|
key="delete"
|
||||||
|
title="确定要删除该部署配置吗?"
|
||||||
|
description="删除后将无法恢复,请谨慎操作"
|
||||||
|
onConfirm={() => handleDelete(record.id)}
|
||||||
|
>
|
||||||
<Button
|
<Button
|
||||||
key="edit"
|
|
||||||
type="link"
|
type="link"
|
||||||
size="small"
|
danger
|
||||||
onClick={() => handleEdit(record)}
|
|
||||||
>
|
>
|
||||||
<EditOutlined/> 编辑
|
<Space>
|
||||||
</Button>,
|
<DeleteOutlined />
|
||||||
<Popconfirm
|
删除
|
||||||
key="delete"
|
</Space>
|
||||||
title="确定要删除该部署配置吗?"
|
</Button>
|
||||||
description="删除后将无法恢复,请谨慎操作"
|
</Popconfirm>
|
||||||
onConfirm={() => handleDelete(record.id)}
|
],
|
||||||
>
|
|
||||||
<Button
|
|
||||||
type="link"
|
|
||||||
size="small"
|
|
||||||
danger
|
|
||||||
>
|
|
||||||
<DeleteOutlined/> 删除
|
|
||||||
</Button>
|
|
||||||
</Popconfirm>
|
|
||||||
];
|
|
||||||
return <div style={{display: 'flex', gap: '8px', justifyContent: 'center'}}>{buttons}</div>;
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
@ -202,6 +180,31 @@ const DeploymentConfigList: React.FC = () => {
|
|||||||
actionRef={actionRef}
|
actionRef={actionRef}
|
||||||
scroll={{x: 'max-content'}}
|
scroll={{x: 'max-content'}}
|
||||||
cardBordered
|
cardBordered
|
||||||
|
rowKey="id"
|
||||||
|
search={false}
|
||||||
|
options={{
|
||||||
|
setting: false,
|
||||||
|
density: false,
|
||||||
|
fullScreen: false,
|
||||||
|
reload: false,
|
||||||
|
}}
|
||||||
|
toolbar={{
|
||||||
|
actions: [
|
||||||
|
<Button
|
||||||
|
key="add"
|
||||||
|
type="primary"
|
||||||
|
onClick={handleAdd}
|
||||||
|
icon={<PlusOutlined/>}
|
||||||
|
disabled={!selectedEnvId}
|
||||||
|
>
|
||||||
|
新建部署配置
|
||||||
|
</Button>
|
||||||
|
],
|
||||||
|
}}
|
||||||
|
pagination={{
|
||||||
|
pageSize: 10,
|
||||||
|
showQuickJumper: true,
|
||||||
|
}}
|
||||||
request={async (params) => {
|
request={async (params) => {
|
||||||
if (!selectedEnvId) {
|
if (!selectedEnvId) {
|
||||||
return {
|
return {
|
||||||
@ -223,39 +226,13 @@ const DeploymentConfigList: React.FC = () => {
|
|||||||
total: data.totalElements || 0,
|
total: data.totalElements || 0,
|
||||||
};
|
};
|
||||||
}}
|
}}
|
||||||
rowKey="id"
|
|
||||||
search={false}
|
|
||||||
options={{
|
|
||||||
setting: {
|
|
||||||
listsHeight: 400,
|
|
||||||
},
|
|
||||||
}}
|
|
||||||
pagination={{
|
|
||||||
pageSize: 10,
|
|
||||||
showQuickJumper: true,
|
|
||||||
}}
|
|
||||||
dateFormatter="string"
|
|
||||||
toolBarRender={() => [
|
|
||||||
<Button
|
|
||||||
key="add"
|
|
||||||
type="primary"
|
|
||||||
onClick={handleAdd}
|
|
||||||
icon={<PlusOutlined/>}
|
|
||||||
disabled={!selectedEnvId}
|
|
||||||
>
|
|
||||||
新建部署配置
|
|
||||||
</Button>,
|
|
||||||
]}
|
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{selectedEnvId && (
|
{modalVisible && selectedEnvId && (
|
||||||
<DeploymentConfigModal
|
<DeploymentConfigModal
|
||||||
visible={modalVisible}
|
open={modalVisible}
|
||||||
onCancel={() => setModalVisible(false)}
|
onCancel={handleModalClose}
|
||||||
onSuccess={() => {
|
onSuccess={handleSuccess}
|
||||||
setModalVisible(false);
|
|
||||||
actionRef.current?.reload();
|
|
||||||
}}
|
|
||||||
initialValues={currentConfig}
|
initialValues={currentConfig}
|
||||||
envId={selectedEnvId}
|
envId={selectedEnvId}
|
||||||
/>
|
/>
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user