1
This commit is contained in:
parent
fe6de5720a
commit
f8a9243ecd
@ -73,15 +73,21 @@ const DeploymentConfigModal: React.FC<DeploymentConfigModalProps> = ({
|
|||||||
if (!open) return;
|
if (!open) return;
|
||||||
|
|
||||||
if (initialValues) {
|
if (initialValues) {
|
||||||
|
// 设置基础字段
|
||||||
form.setFieldsValue({
|
form.setFieldsValue({
|
||||||
applicationId: initialValues.applicationId,
|
applicationId: initialValues.applicationId,
|
||||||
enabled: initialValues.enabled
|
enabled: initialValues.enabled,
|
||||||
|
...initialValues.buildVariables // 设置所有构建变量到表单中
|
||||||
});
|
});
|
||||||
|
|
||||||
const template = templates.find(t => t.buildType === initialValues.buildType && t.languageType === initialValues.languageType);
|
const template = templates.find(t => t.buildType === initialValues.buildType && t.languageType === initialValues.languageType);
|
||||||
if (template) {
|
if (template) {
|
||||||
setSelectedTemplate(template);
|
setSelectedTemplate(template);
|
||||||
setBuildVariables(initialValues.buildVariables || {});
|
// 只保存编辑器字段的值到 buildVariables
|
||||||
|
const editorValues = Object.entries(initialValues.buildVariables || {})
|
||||||
|
.filter(([key]) => template.buildVariablesSchema?.properties?.[key]?.editorConfig)
|
||||||
|
.reduce((acc, [key, value]) => ({...acc, [key]: value}), {});
|
||||||
|
setBuildVariables(editorValues);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
form.resetFields();
|
form.resetFields();
|
||||||
@ -100,17 +106,30 @@ const DeploymentConfigModal: React.FC<DeploymentConfigModalProps> = ({
|
|||||||
if (template) {
|
if (template) {
|
||||||
setSelectedTemplate(template);
|
setSelectedTemplate(template);
|
||||||
setBuildVariables({});
|
setBuildVariables({});
|
||||||
|
// 重置除了 applicationId 和 enabled 之外的所有字段
|
||||||
|
const currentValues = form.getFieldsValue();
|
||||||
|
form.setFieldsValue({
|
||||||
|
applicationId: currentValues.applicationId,
|
||||||
|
enabled: currentValues.enabled
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, [applications, templates]);
|
}, [applications, templates, form]);
|
||||||
|
|
||||||
|
const handleFormValuesChange = (changedValues: Record<string, any>) => {
|
||||||
|
setBuildVariables(prev => ({
|
||||||
|
...prev,
|
||||||
|
...changedValues
|
||||||
|
}));
|
||||||
|
};
|
||||||
|
|
||||||
const handleSubmit = async () => {
|
const handleSubmit = async () => {
|
||||||
try {
|
try {
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
const values = await form.validateFields();
|
const formValues = await form.validateFields();
|
||||||
|
|
||||||
// 获取选中的应用信息
|
// 获取选中的应用信息
|
||||||
const selectedApp = applications.find(app => app.id === values.applicationId);
|
const selectedApp = applications.find(app => app.id === formValues.applicationId);
|
||||||
if (!selectedApp) {
|
if (!selectedApp) {
|
||||||
throw new Error('请选择应用');
|
throw new Error('请选择应用');
|
||||||
}
|
}
|
||||||
@ -121,14 +140,20 @@ const DeploymentConfigModal: React.FC<DeploymentConfigModalProps> = ({
|
|||||||
throw new Error('未找到匹配配置模板');
|
throw new Error('未找到匹配配置模板');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 从 formValues 中提取构建变量(排除 applicationId 和 enabled)
|
||||||
|
const { applicationId, enabled, ...formBuildVariables } = formValues;
|
||||||
|
|
||||||
// 构建提交数据
|
// 构建提交数据
|
||||||
const submitData: CreateDeploymentConfigRequest = {
|
const submitData: CreateDeploymentConfigRequest = {
|
||||||
environmentId: envId,
|
environmentId: envId,
|
||||||
applicationId: values.applicationId,
|
applicationId,
|
||||||
buildType: template.buildType,
|
buildType: template.buildType,
|
||||||
languageType: selectedApp.language,
|
languageType: selectedApp.language,
|
||||||
buildVariables,
|
buildVariables: {
|
||||||
enabled: values.enabled
|
...formBuildVariables, // 表单中的值
|
||||||
|
...buildVariables // 编辑器中的值
|
||||||
|
} as Record<string, any>, // 使用类型断言确保类型兼容
|
||||||
|
enabled
|
||||||
};
|
};
|
||||||
|
|
||||||
if (isEdit) {
|
if (isEdit) {
|
||||||
@ -217,34 +242,57 @@ const DeploymentConfigModal: React.FC<DeploymentConfigModalProps> = ({
|
|||||||
{/* 动态构建配置 */}
|
{/* 动态构建配置 */}
|
||||||
{selectedTemplate?.buildVariablesSchema?.properties && (
|
{selectedTemplate?.buildVariablesSchema?.properties && (
|
||||||
<>
|
<>
|
||||||
{/* 按照原始顺序渲染所有字段 */}
|
{/* 使用 BetaSchemaForm 渲染普通字段 */}
|
||||||
{Object.entries(selectedTemplate.buildVariablesSchema.properties).map(([key, property]) => {
|
<BetaSchemaForm
|
||||||
// 如果是编辑器字段
|
layoutType="Embed"
|
||||||
if (property.editorConfig) {
|
columns={convertJsonSchemaToColumns({
|
||||||
|
type: 'object',
|
||||||
|
properties: Object.fromEntries(
|
||||||
|
Object.entries(selectedTemplate.buildVariablesSchema.properties)
|
||||||
|
.filter(([_, prop]) => !prop.editorConfig)
|
||||||
|
.map(([key, prop]) => [key, {
|
||||||
|
...prop,
|
||||||
|
type: prop.type || 'string' // 确保有 type 字段
|
||||||
|
}])
|
||||||
|
),
|
||||||
|
required: selectedTemplate.buildVariablesSchema.required || []
|
||||||
|
})}
|
||||||
|
initialValues={buildVariables}
|
||||||
|
onValuesChange={(_, values) => {
|
||||||
|
setBuildVariables(prev => ({
|
||||||
|
...prev,
|
||||||
|
...values
|
||||||
|
}));
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
|
||||||
|
{/* 渲染编辑器字段 */}
|
||||||
|
{Object.entries(selectedTemplate.buildVariablesSchema.properties)
|
||||||
|
.filter(([_, prop]) => prop.editorConfig)
|
||||||
|
.map(([key, property]) => {
|
||||||
const isFullscreen = fullscreenEditor?.key === key;
|
const isFullscreen = fullscreenEditor?.key === key;
|
||||||
const editorConfig = property.editorConfig;
|
|
||||||
|
|
||||||
const editor = (
|
const editor = (
|
||||||
<Editor
|
<Editor
|
||||||
height={isFullscreen ? "calc(100vh - 55px)" : "300px"}
|
height={isFullscreen ? "calc(100vh - 55px)" : "300px"}
|
||||||
defaultLanguage={editorConfig.language || 'shell'}
|
defaultLanguage={property.editorConfig.language || 'shell'}
|
||||||
theme={editorConfig.theme || 'vs-dark'}
|
theme={property.editorConfig.theme || 'vs-dark'}
|
||||||
value={buildVariables[key] || property.default || ''}
|
value={buildVariables[key] || property.default || ''}
|
||||||
onChange={(value) => handleEditorChange(key, value)}
|
onChange={(value) => handleEditorChange(key, value)}
|
||||||
options={{
|
options={{
|
||||||
minimap: { enabled: isFullscreen ? true : (editorConfig.minimap ?? false) },
|
minimap: { enabled: isFullscreen ? true : (property.editorConfig.minimap ?? false) },
|
||||||
fontSize: editorConfig.fontSize || 14,
|
fontSize: property.editorConfig.fontSize || 14,
|
||||||
lineNumbers: editorConfig.lineNumbers ? 'on' : 'off',
|
lineNumbers: property.editorConfig.lineNumbers ? 'on' : 'off',
|
||||||
wordWrap: editorConfig.wordWrap ? 'on' : 'off',
|
wordWrap: property.editorConfig.wordWrap ? 'on' : 'off',
|
||||||
tabSize: editorConfig.tabSize || 2,
|
tabSize: property.editorConfig.tabSize || 2,
|
||||||
scrollBeyondLastLine: false,
|
scrollBeyondLastLine: false,
|
||||||
automaticLayout: true,
|
automaticLayout: true,
|
||||||
folding: editorConfig.folding ?? true,
|
folding: property.editorConfig.folding ?? true,
|
||||||
autoClosingBrackets: 'always',
|
autoClosingBrackets: 'always',
|
||||||
autoClosingQuotes: 'always',
|
autoClosingQuotes: 'always',
|
||||||
formatOnPaste: true,
|
formatOnPaste: true,
|
||||||
formatOnType: true,
|
formatOnType: true,
|
||||||
suggestOnTriggerCharacters: editorConfig.autoComplete ?? true,
|
suggestOnTriggerCharacters: property.editorConfig.autoComplete ?? true,
|
||||||
renderWhitespace: 'boundary',
|
renderWhitespace: 'boundary',
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
@ -298,48 +346,7 @@ const DeploymentConfigModal: React.FC<DeploymentConfigModalProps> = ({
|
|||||||
{editor}
|
{editor}
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
);
|
);
|
||||||
}
|
})}
|
||||||
|
|
||||||
// 如果是普通字段,使用 BetaSchemaForm
|
|
||||||
return (
|
|
||||||
<BetaSchemaForm
|
|
||||||
key={key}
|
|
||||||
layoutType="Embed"
|
|
||||||
columns={convertJsonSchemaToColumns({
|
|
||||||
type: 'object',
|
|
||||||
properties: {
|
|
||||||
[key]: {
|
|
||||||
type: property.type || 'string',
|
|
||||||
title: property.title,
|
|
||||||
description: property.description,
|
|
||||||
default: property.default,
|
|
||||||
enum: property.enum,
|
|
||||||
enumNames: property.enumNames,
|
|
||||||
format: property.format,
|
|
||||||
minimum: property.minimum,
|
|
||||||
maximum: property.maximum,
|
|
||||||
minLength: property.minLength,
|
|
||||||
maxLength: property.maxLength,
|
|
||||||
pattern: property.pattern,
|
|
||||||
items: property.items && {
|
|
||||||
type: property.items.type || 'string',
|
|
||||||
enum: property.items.enum,
|
|
||||||
enumNames: property.items.enumNames
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
required: selectedTemplate.buildVariablesSchema.required?.includes(key) ? [key] : []
|
|
||||||
})}
|
|
||||||
initialValues={{
|
|
||||||
[key]: buildVariables[key]
|
|
||||||
}}
|
|
||||||
onValuesChange={(_, values) => setBuildVariables(prev => ({
|
|
||||||
...prev,
|
|
||||||
...values
|
|
||||||
}))}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
|||||||
@ -20,7 +20,7 @@ const CodePreviewModal: React.FC<{
|
|||||||
language?: string;
|
language?: string;
|
||||||
}> = ({open, onCancel, code, language = 'shell'}) => {
|
}> = ({open, onCancel, code, language = 'shell'}) => {
|
||||||
const [isFullscreen, setIsFullscreen] = useState(false);
|
const [isFullscreen, setIsFullscreen] = useState(false);
|
||||||
|
|
||||||
// 当模态<E6A8A1><E68081>打开或关闭时重置全屏状态
|
// 当模态<E6A8A1><E68081>打开或关闭时重置全屏状态
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setIsFullscreen(false);
|
setIsFullscreen(false);
|
||||||
@ -33,7 +33,7 @@ const CodePreviewModal: React.FC<{
|
|||||||
代码预览
|
代码预览
|
||||||
<Button
|
<Button
|
||||||
type="text"
|
type="text"
|
||||||
icon={<FullscreenOutlined />}
|
icon={<FullscreenOutlined/>}
|
||||||
onClick={() => setIsFullscreen(!isFullscreen)}
|
onClick={() => setIsFullscreen(!isFullscreen)}
|
||||||
/>
|
/>
|
||||||
</Space>
|
</Space>
|
||||||
@ -51,17 +51,17 @@ const CodePreviewModal: React.FC<{
|
|||||||
} : undefined}
|
} : undefined}
|
||||||
wrapClassName={isFullscreen ? 'fullscreen-modal' : undefined}
|
wrapClassName={isFullscreen ? 'fullscreen-modal' : undefined}
|
||||||
styles={{
|
styles={{
|
||||||
body: { padding: 0 }
|
body: {padding: 0}
|
||||||
}}
|
}}
|
||||||
destroyOnClose
|
destroyOnClose
|
||||||
>
|
>
|
||||||
<Editor
|
<Editor
|
||||||
height={isFullscreen ? "calc(100vh - 55px)" : "500px"}
|
height={isFullscreen ? "calc(100vh - 100px)" : "500px"}
|
||||||
defaultLanguage={language}
|
defaultLanguage={language}
|
||||||
value={code}
|
value={code}
|
||||||
options={{
|
options={{
|
||||||
readOnly: true,
|
readOnly: true,
|
||||||
minimap: { enabled: true },
|
minimap: {enabled: true},
|
||||||
scrollBeyondLastLine: false,
|
scrollBeyondLastLine: false,
|
||||||
automaticLayout: true,
|
automaticLayout: true,
|
||||||
contextmenu: true,
|
contextmenu: true,
|
||||||
@ -78,7 +78,7 @@ const DeploymentConfigList: React.FC = () => {
|
|||||||
const [currentConfig, setCurrentConfig] = useState<DeploymentConfig>();
|
const [currentConfig, setCurrentConfig] = useState<DeploymentConfig>();
|
||||||
const [templates, setTemplates] = useState<DeployConfigTemplate[]>([]);
|
const [templates, setTemplates] = useState<DeployConfigTemplate[]>([]);
|
||||||
const [codePreviewVisible, setCodePreviewVisible] = useState(false);
|
const [codePreviewVisible, setCodePreviewVisible] = useState(false);
|
||||||
const [previewCode, setPreviewCode] = useState<{code: string; language?: string}>({code: ''});
|
const [previewCode, setPreviewCode] = useState<{ code: string; language?: string }>({code: ''});
|
||||||
const actionRef = React.useRef<ActionType>();
|
const actionRef = React.useRef<ActionType>();
|
||||||
|
|
||||||
// 获取环境列表
|
// 获取环境列表
|
||||||
@ -158,7 +158,7 @@ const DeploymentConfigList: React.FC = () => {
|
|||||||
// 根据模板获取构建配置的子列
|
// 根据模板获取构建配置的子列
|
||||||
const getBuildConfigColumns = () => {
|
const getBuildConfigColumns = () => {
|
||||||
const buildConfigColumns: ProColumns<DeploymentConfig>[] = [];
|
const buildConfigColumns: ProColumns<DeploymentConfig>[] = [];
|
||||||
|
|
||||||
// 获取所有可能的字段和它们的标题
|
// 获取所有可能的字段和它们的标题
|
||||||
const fieldInfo = new Map<string, { title: string }>();
|
const fieldInfo = new Map<string, { title: string }>();
|
||||||
templates.forEach(template => {
|
templates.forEach(template => {
|
||||||
@ -182,11 +182,11 @@ const DeploymentConfigList: React.FC = () => {
|
|||||||
ellipsis: true,
|
ellipsis: true,
|
||||||
render: (_, record) => {
|
render: (_, record) => {
|
||||||
// 找到对应的模板
|
// 找到对应的模板
|
||||||
const template = templates.find(t =>
|
const template = templates.find(t =>
|
||||||
t.buildType === record.buildType &&
|
t.buildType === record.buildType &&
|
||||||
t.languageType === record.languageType
|
t.languageType === record.languageType
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!template?.buildVariablesSchema?.properties?.[field]) {
|
if (!template?.buildVariablesSchema?.properties?.[field]) {
|
||||||
return '-';
|
return '-';
|
||||||
}
|
}
|
||||||
@ -201,9 +201,9 @@ const DeploymentConfigList: React.FC = () => {
|
|||||||
return (
|
return (
|
||||||
<Space>
|
<Space>
|
||||||
<Tooltip title="点击查看完整内容">
|
<Tooltip title="点击查看完整内容">
|
||||||
<Button
|
<Button
|
||||||
type="link"
|
type="link"
|
||||||
icon={<EyeOutlined />}
|
icon={<EyeOutlined/>}
|
||||||
onClick={() => handleCodePreview(
|
onClick={() => handleCodePreview(
|
||||||
value,
|
value,
|
||||||
fieldProperties.editorConfig?.language
|
fieldProperties.editorConfig?.language
|
||||||
@ -234,13 +234,6 @@ const DeploymentConfigList: React.FC = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const columns: ProColumns<DeploymentConfig>[] = [
|
const columns: ProColumns<DeploymentConfig>[] = [
|
||||||
{
|
|
||||||
title: '应用名称',
|
|
||||||
dataIndex: ['application', 'appName'],
|
|
||||||
width: 150,
|
|
||||||
ellipsis: true,
|
|
||||||
fixed: 'left',
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
title: '应用编码',
|
title: '应用编码',
|
||||||
dataIndex: ['application', 'appCode'],
|
dataIndex: ['application', 'appCode'],
|
||||||
@ -248,6 +241,13 @@ const DeploymentConfigList: React.FC = () => {
|
|||||||
copyable: true,
|
copyable: true,
|
||||||
ellipsis: true,
|
ellipsis: true,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
title: '应用名称',
|
||||||
|
dataIndex: ['application', 'appName'],
|
||||||
|
width: 150,
|
||||||
|
ellipsis: true,
|
||||||
|
fixed: 'left',
|
||||||
|
},
|
||||||
{
|
{
|
||||||
title: '构建配置',
|
title: '构建配置',
|
||||||
children: getBuildConfigColumns()
|
children: getBuildConfigColumns()
|
||||||
@ -274,7 +274,7 @@ const DeploymentConfigList: React.FC = () => {
|
|||||||
onClick={() => handleEdit(record)}
|
onClick={() => handleEdit(record)}
|
||||||
>
|
>
|
||||||
<Space>
|
<Space>
|
||||||
<EditOutlined />
|
<EditOutlined/>
|
||||||
编辑
|
编辑
|
||||||
</Space>
|
</Space>
|
||||||
</Button>,
|
</Button>,
|
||||||
@ -289,7 +289,7 @@ const DeploymentConfigList: React.FC = () => {
|
|||||||
danger
|
danger
|
||||||
>
|
>
|
||||||
<Space>
|
<Space>
|
||||||
<DeleteOutlined />
|
<DeleteOutlined/>
|
||||||
删除
|
删除
|
||||||
</Space>
|
</Space>
|
||||||
</Button>
|
</Button>
|
||||||
@ -301,7 +301,7 @@ const DeploymentConfigList: React.FC = () => {
|
|||||||
return (
|
return (
|
||||||
<PageContainer
|
<PageContainer
|
||||||
header={{
|
header={{
|
||||||
title: '部署配置',
|
title: '部署配置管理',
|
||||||
extra: [
|
extra: [
|
||||||
<Select
|
<Select
|
||||||
key="env-select"
|
key="env-select"
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
import React, {useState} from 'react';
|
import React, {useState} from 'react';
|
||||||
import {PageContainer} from '@ant-design/pro-layout';
|
import {PageContainer} from '@ant-design/pro-layout';
|
||||||
import {Button, Space, Popconfirm, Tag, App} from 'antd';
|
import {Button, Space, Popconfirm, Tag, App, Select} from 'antd';
|
||||||
import {PlusOutlined, EditOutlined, DeleteOutlined} from '@ant-design/icons';
|
import {PlusOutlined, EditOutlined, DeleteOutlined} from '@ant-design/icons';
|
||||||
import {getEnvironmentPage, deleteEnvironment} from './service';
|
import {getEnvironmentPage, deleteEnvironment} from './service';
|
||||||
import type {Environment, EnvironmentQueryParams} from './types';
|
import type {Environment, EnvironmentQueryParams} from './types';
|
||||||
@ -166,7 +166,11 @@ const EnvironmentList: React.FC = () => {
|
|||||||
];
|
];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<PageContainer>
|
<PageContainer
|
||||||
|
header={{
|
||||||
|
title: '环境管理'
|
||||||
|
}}
|
||||||
|
>
|
||||||
<ProTable<Environment>
|
<ProTable<Environment>
|
||||||
columns={columns}
|
columns={columns}
|
||||||
actionRef={actionRef}
|
actionRef={actionRef}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user