|
|
import React, { useState, useEffect } from 'react';
|
|
|
import { Modal, Button, Input, Message, Tooltip } from '@arco-design/web-react';
|
|
|
import { IconQuestionCircle, IconCopy, IconDelete, IconPlus } from '@arco-design/web-react/icon';
|
|
|
import styles from './style/envConfigModal.module.less';
|
|
|
import { getComponentEnvConfig, saveComponentEnvConfig } from '@/api/componentInstance';
|
|
|
|
|
|
interface EnvConfigModalProps {
|
|
|
language: string;
|
|
|
visible: boolean;
|
|
|
instanceId: string;
|
|
|
onCancel: () => void;
|
|
|
onSuccess?: () => void;
|
|
|
}
|
|
|
|
|
|
interface ConfigItem {
|
|
|
name: string;
|
|
|
key: string;
|
|
|
value: string;
|
|
|
desc: string;
|
|
|
unmodifiable?: boolean;
|
|
|
isCustom?: boolean; // 标记是否为用户自定义添加的
|
|
|
}
|
|
|
|
|
|
const EnvConfigModal: React.FC<EnvConfigModalProps> = ({
|
|
|
language,
|
|
|
visible,
|
|
|
instanceId,
|
|
|
onCancel,
|
|
|
onSuccess
|
|
|
}) => {
|
|
|
const [loading, setLoading] = useState(false);
|
|
|
const [saveLoading, setSaveLoading] = useState(false);
|
|
|
const [configData, setConfigData] = useState<any>(null);
|
|
|
const [configList, setConfigList] = useState<ConfigItem[]>([]);
|
|
|
|
|
|
useEffect(() => {
|
|
|
if (visible && instanceId) {
|
|
|
fetchEnvConfig();
|
|
|
}
|
|
|
}, [visible, instanceId]);
|
|
|
|
|
|
const fetchEnvConfig = async () => {
|
|
|
try {
|
|
|
setLoading(true);
|
|
|
const res: any = await getComponentEnvConfig(instanceId);
|
|
|
if (res.code === 200) {
|
|
|
setConfigData(res.data);
|
|
|
setConfigList(res.data.config || []);
|
|
|
}
|
|
|
else {
|
|
|
Message.error(res.msg || '获取环境配置失败');
|
|
|
}
|
|
|
} catch (error) {
|
|
|
console.error('获取环境配置失败:', error);
|
|
|
Message.error('获取环境配置失败');
|
|
|
} finally {
|
|
|
setLoading(false);
|
|
|
}
|
|
|
};
|
|
|
|
|
|
const handleConfigChange = (index: number, field: keyof ConfigItem, value: string) => {
|
|
|
const newConfigList: any = [...configList];
|
|
|
newConfigList[index][field] = value;
|
|
|
setConfigList(newConfigList);
|
|
|
};
|
|
|
|
|
|
// 添加新配置行
|
|
|
const handleAddConfig = () => {
|
|
|
const newConfig: ConfigItem = {
|
|
|
name: '',
|
|
|
key: '',
|
|
|
value: '',
|
|
|
desc: '',
|
|
|
isCustom: true
|
|
|
};
|
|
|
setConfigList([...configList, newConfig]);
|
|
|
};
|
|
|
|
|
|
// 删除配置行
|
|
|
const handleDeleteConfig = (index: number) => {
|
|
|
const newConfigList = configList.filter((_, i) => i !== index);
|
|
|
setConfigList(newConfigList);
|
|
|
};
|
|
|
|
|
|
const handleCopyCommand = () => {
|
|
|
navigator.clipboard.writeText(configData.javaCommand);
|
|
|
Message.success('复制成功');
|
|
|
};
|
|
|
|
|
|
const handleSave = async () => {
|
|
|
try {
|
|
|
setSaveLoading(true);
|
|
|
const params = {
|
|
|
...configData,
|
|
|
config: configList
|
|
|
};
|
|
|
const res: any = await saveComponentEnvConfig(instanceId, params);
|
|
|
if (res.code === 200) {
|
|
|
Message.success('保存成功');
|
|
|
onSuccess?.();
|
|
|
onCancel();
|
|
|
}
|
|
|
else {
|
|
|
Message.error(res.msg || '保存失败');
|
|
|
}
|
|
|
} catch (error) {
|
|
|
console.error('保存失败:', error);
|
|
|
Message.error('保存失败');
|
|
|
} finally {
|
|
|
setSaveLoading(false);
|
|
|
}
|
|
|
};
|
|
|
|
|
|
return (
|
|
|
<Modal
|
|
|
title="环境配置"
|
|
|
visible={visible}
|
|
|
onCancel={onCancel}
|
|
|
style={{ width: 1000 }}
|
|
|
footer={
|
|
|
<div style={{ display: 'flex', justifyContent: 'flex-end', gap: 12 }}>
|
|
|
<Button onClick={onCancel}>取消</Button>
|
|
|
<Button type="primary" onClick={handleSave} loading={saveLoading}>
|
|
|
保存配置
|
|
|
</Button>
|
|
|
</div>
|
|
|
}
|
|
|
>
|
|
|
<div className={styles['env-config-modal']}>
|
|
|
{loading ? (
|
|
|
<div className={styles['loading-state']}>
|
|
|
<div className={styles['loading-spinner']}></div>
|
|
|
<p>正在加载配置信息...</p>
|
|
|
</div>
|
|
|
) : (
|
|
|
<>
|
|
|
{/* 命令展示 */}
|
|
|
{configData?.javaCommand && (
|
|
|
<div className={styles['command-section']}>
|
|
|
<div className={styles['command-header']}>
|
|
|
<Button
|
|
|
type="text"
|
|
|
size="mini"
|
|
|
icon={<IconCopy />}
|
|
|
onClick={handleCopyCommand}
|
|
|
>
|
|
|
复制命令
|
|
|
</Button>
|
|
|
</div>
|
|
|
<div className={styles['command-content']}>
|
|
|
{language.includes('Python') ? configData.pythonCommand : configData.javaCommand}
|
|
|
</div>
|
|
|
<div className={styles['command-hint']}>
|
|
|
本地点击"复制命令"按钮可以复制上方命令
|
|
|
</div>
|
|
|
</div>
|
|
|
)}
|
|
|
|
|
|
{/* 配置表格 */}
|
|
|
<div className={styles['config-table']}>
|
|
|
<div className={styles['table-header']}>
|
|
|
<div className={styles['col-index']}>#</div>
|
|
|
<div className={styles['col-name']}>
|
|
|
<span className={styles['required']}>*</span>
|
|
|
启动名称
|
|
|
</div>
|
|
|
<div className={styles['col-key']}>
|
|
|
<span className={styles['required']}>*</span>
|
|
|
参数名(key)
|
|
|
</div>
|
|
|
<div className={styles['col-value']}>配置值</div>
|
|
|
<div className={styles['col-desc']}>描述说明</div>
|
|
|
<div className={styles['col-action']}>操作</div>
|
|
|
</div>
|
|
|
|
|
|
<div className={styles['table-body']}>
|
|
|
{configList.map((item, index) => (
|
|
|
<div key={index} className={styles['table-row']}>
|
|
|
<div className={styles['col-index']}>{index + 1}</div>
|
|
|
<div className={styles['col-name']}>
|
|
|
<Input
|
|
|
value={item.name}
|
|
|
onChange={(value) => handleConfigChange(index, 'name', value)}
|
|
|
placeholder="请输入启动名称"
|
|
|
size="small"
|
|
|
/>
|
|
|
</div>
|
|
|
<div className={styles['col-key']}>
|
|
|
<Input
|
|
|
value={item.key}
|
|
|
onChange={(value) => handleConfigChange(index, 'key', value)}
|
|
|
placeholder="请输入参数名"
|
|
|
size="small"
|
|
|
/>
|
|
|
</div>
|
|
|
<div className={styles['col-value']}>
|
|
|
<Input
|
|
|
value={item.value}
|
|
|
onChange={(value) => handleConfigChange(index, 'value', value)}
|
|
|
placeholder="请输入配置值"
|
|
|
size="small"
|
|
|
/>
|
|
|
</div>
|
|
|
<div className={styles['col-desc']}>
|
|
|
<Input
|
|
|
value={item.desc}
|
|
|
onChange={(value) => handleConfigChange(index, 'desc', value)}
|
|
|
placeholder="请输入描述说明"
|
|
|
size="small"
|
|
|
/>
|
|
|
</div>
|
|
|
<div className={styles['col-action']}>
|
|
|
{item.isCustom && (
|
|
|
<Button
|
|
|
type="text"
|
|
|
status="danger"
|
|
|
icon={<IconDelete />}
|
|
|
onClick={() => handleDeleteConfig(index)}
|
|
|
size="small"
|
|
|
>
|
|
|
删除
|
|
|
</Button>
|
|
|
)}
|
|
|
</div>
|
|
|
</div>
|
|
|
))}
|
|
|
</div>
|
|
|
|
|
|
{/* 添加新配置按钮 */}
|
|
|
<div className={styles['add-config-btn']}>
|
|
|
<Button
|
|
|
type="dashed"
|
|
|
icon={<IconPlus />}
|
|
|
onClick={handleAddConfig}
|
|
|
long
|
|
|
>
|
|
|
添加配置项
|
|
|
</Button>
|
|
|
</div>
|
|
|
</div>
|
|
|
</>
|
|
|
)}
|
|
|
</div>
|
|
|
</Modal>
|
|
|
);
|
|
|
};
|
|
|
|
|
|
export default EnvConfigModal;
|