diff --git a/taier-ui/src/components/customParameter/index.scss b/taier-ui/src/components/customParameter/index.scss new file mode 100644 index 0000000000..a664b61ca3 --- /dev/null +++ b/taier-ui/src/components/customParameter/index.scss @@ -0,0 +1,27 @@ +.dtc-custom-parameter { + &__item { + margin-bottom: 24px; + } + + &__gap { + margin-left: 2px; + margin-right: 6px; + } + + &__add { + color: #3f87ff; + cursor: pointer; + } + + &__delete { + margin-left: 8px; + color: #3f87ff; + font-size: 0; + cursor: pointer; + } + + &__exist { + font-size: 12px; + color: #ff4d4f; + } +} diff --git a/taier-ui/src/components/customParameter/index.tsx b/taier-ui/src/components/customParameter/index.tsx new file mode 100644 index 0000000000..aa960fdd47 --- /dev/null +++ b/taier-ui/src/components/customParameter/index.tsx @@ -0,0 +1,191 @@ +import React, { useEffect, useState } from 'react'; +import { DeleteOutlined, PlusSquareOutlined } from '@ant-design/icons'; +import { Col, Input, Row, Space } from 'antd'; + +import './index.scss'; + +interface IComponentType { + /** + * 自定义组件类型 + */ + type: string; + /** + * 组件 + */ + Component: React.ComponentClass | React.FC; +} + +interface ICustomItem extends IComponentType { + /** + * 自定义参数名 + */ + label: string; + /** + * 自定义参数值 + */ + value: string; + /** + * 自定义参数是否合法 + */ + status: boolean; +} + +export type ICustomValue = Omit; + +interface ICustomParameterProps { + /** + * 自定义参数名-value对应的key名 + */ + labelKey?: string; + /** + * 自定义参数值-value对应的key名 + */ + valueKey?: string; + /** + * 已存在的keys + */ + existingKeys: string[]; + /** + * 自定义参数列表 + */ + value?: Record[]; + /** + * 自定义参数改变触发函数 + * @param value + * @returns + */ + onChange?: (value: ICustomValue[]) => void; +} + +const DEFAULT_FORM_ITEM: IComponentType = { + type: 'INPUT', + Component: Input, +}; + +export default function CustomParameter({ + labelKey = 'label', + valueKey = 'value', + existingKeys, + value, + onChange, +}: ICustomParameterProps) { + const [customParamRows, setCustomParamRows] = useState([]); + + const handleCustomParameterAdd = () => { + const customItem: ICustomItem = { + type: DEFAULT_FORM_ITEM.type, + Component: DEFAULT_FORM_ITEM.Component, + label: '', + value: '', + status: false, + }; + + setCustomParamRows([...customParamRows, customItem]); + }; + + const handleCustomParameterDelete = (index: number) => { + const paramRows = customParamRows.filter((_, i) => i !== index); + setCustomParamRows(paramRows); + onChange?.( + paramRows?.map((item) => ({ + label: item.label, + value: item.value, + type: item.type, + status: item.status, + })) + ); + }; + + const handleIsSame = (item: ICustomItem) => + existingKeys.includes(item.label) || customParamRows.filter((cIt) => cIt.label === item.label).length > 1; + + console.log(existingKeys); + + useEffect(() => { + setCustomParamRows( + value?.map((item) => { + return { + type: item.type || DEFAULT_FORM_ITEM.type, + label: item[labelKey], + value: item[valueKey], + Component: DEFAULT_FORM_ITEM.Component, + status: false, + }; + }) || [] + ); + }, []); + + return ( +
+ {customParamRows.map((item, index) => ( + + + { + const params = customParamRows.map((item, i) => { + if (i === index) item.label = e.target.value; + return item; + }); + setCustomParamRows(params); + onChange?.( + params?.map((item) => ({ + label: item.label, + value: item.value, + type: item.type, + status: Boolean(item.label && item.value && !handleIsSame(item)), + })) + ); + }} + /> + : + + + { + const params = customParamRows.map((item, i) => { + if (i === index) item.value = e.target.value; + return item; + }); + setCustomParamRows(params); + onChange?.( + params?.map((item) => ({ + label: item.label, + value: item.value, + type: item.type, + status: Boolean(item.label && item.value && !handleIsSame(item)), + })) + ); + }} + /> + + +
+ + handleCustomParameterDelete(index)} + /> + {handleIsSame(item) ? ( + 已存在 + ) : null} + +
+ +
+ ))} + + + + {'添加自定义参数'} + + +
+ ); +} diff --git a/taier-ui/src/pages/console/cluster/detail/detail.tsx b/taier-ui/src/pages/console/cluster/detail/detail.tsx index c9bfd2ce71..0c782a5a72 100644 --- a/taier-ui/src/pages/console/cluster/detail/detail.tsx +++ b/taier-ui/src/pages/console/cluster/detail/detail.tsx @@ -29,6 +29,7 @@ import { import type { RcFile } from 'antd/lib/upload'; import api from '@/api'; +import CustomParameter, { ICustomValue } from '@/components/customParameter'; import { COMPONENT_TYPE_VALUE } from '@/constant'; import context from '@/context/cluster'; import type { IComponentProps } from '.'; @@ -38,6 +39,7 @@ const { Sider, Content } = Layout; const { Panel } = Collapse; interface IDetailProps { + form: any; templateData: ILayoutData[]; currentTreeNode?: IComponentProps; loading?: boolean; @@ -80,11 +82,12 @@ export interface ITemplateData { /** * XML 表示该值作为 config 渲染 */ - type: 'INPUT' | 'RADIO_LINKAGE' | 'CHECKBOX' | 'XML' | 'GROUP'; + type: 'INPUT' | 'RADIO_LINKAGE' | 'CHECKBOX' | 'XML' | 'GROUP' | 'CUSTOM'; value: string; } export default function Detail({ + form, loading, currentTreeNode, templateData = [], @@ -371,6 +374,23 @@ export default function Detail({ ); } )} + item.status) + ? Promise.resolve() + : Promise.reject('自定义字段名重复'); + }, + }, + ]} + > + + ); diff --git a/taier-ui/src/pages/console/cluster/detail/index.tsx b/taier-ui/src/pages/console/cluster/detail/index.tsx index 74bd6d3486..d9f7510c68 100644 --- a/taier-ui/src/pages/console/cluster/detail/index.tsx +++ b/taier-ui/src/pages/console/cluster/detail/index.tsx @@ -400,8 +400,24 @@ export default function ClusterDetail() { // 上传配置文件所解析出来的配置项会放在 config 字段中,不存在于 values 里 const xmlConfig = form.getFieldValue('config'); - - const componentConfig = xmlConfig ? JSON.stringify(xmlConfig) : JSON.stringify(restValues); + let componentConfig: string; + const customParameters: Record = {}; + if (xmlConfig) { + componentConfig = JSON.stringify(xmlConfig); + } else { + const deploymode = restValues.deploymode; + deploymode?.forEach((item: string) => { + const key = [item, 'customParameters'].join('$'); + customParameters[item] = restValues[key]; + restValues[key]?.forEach((it: any) => { + restValues[item][it.key] = it.value; + }); + return {}; + }); + console.log(customParameters); + console.log(restValues); + componentConfig = JSON.stringify(restValues); + } try { setDetailLoading(true); @@ -416,6 +432,7 @@ export default function ClusterDetail() { principals, versionName: Array.isArray(versionName) ? versionName[versionName.length - 1] : versionName, componentConfig, + customParameters, deployType: currentComponent.deployType, clusterId: currentComponent.clusterId, componentCode: currentComponent.componentTypeCode, @@ -630,6 +647,7 @@ export default function ClusterDetail() { {selectedKey ? (