Skip to content

Commit aa10a54

Browse files
authored
WIP: [feat/sql-languages][taier-ui] add custom parameters (#1138)
### 简介 控制台新增自定义参数 ### 🔗 相关 Issue feat [#1137](#1137)
1 parent 0bd48ec commit aa10a54

4 files changed

Lines changed: 259 additions & 3 deletions

File tree

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
.dtc-custom-parameter {
2+
&__item {
3+
margin-bottom: 24px;
4+
}
5+
6+
&__gap {
7+
margin-left: 2px;
8+
margin-right: 6px;
9+
}
10+
11+
&__add {
12+
color: #3f87ff;
13+
cursor: pointer;
14+
}
15+
16+
&__delete {
17+
margin-left: 8px;
18+
color: #3f87ff;
19+
font-size: 0;
20+
cursor: pointer;
21+
}
22+
23+
&__exist {
24+
font-size: 12px;
25+
color: #ff4d4f;
26+
}
27+
}
Lines changed: 191 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,191 @@
1+
import React, { useEffect, useState } from 'react';
2+
import { DeleteOutlined, PlusSquareOutlined } from '@ant-design/icons';
3+
import { Col, Input, Row, Space } from 'antd';
4+
5+
import './index.scss';
6+
7+
interface IComponentType {
8+
/**
9+
* 自定义组件类型
10+
*/
11+
type: string;
12+
/**
13+
* 组件
14+
*/
15+
Component: React.ComponentClass<any, any> | React.FC<any>;
16+
}
17+
18+
interface ICustomItem extends IComponentType {
19+
/**
20+
* 自定义参数名
21+
*/
22+
label: string;
23+
/**
24+
* 自定义参数值
25+
*/
26+
value: string;
27+
/**
28+
* 自定义参数是否合法
29+
*/
30+
status: boolean;
31+
}
32+
33+
export type ICustomValue = Omit<ICustomItem, 'Component'>;
34+
35+
interface ICustomParameterProps {
36+
/**
37+
* 自定义参数名-value对应的key名
38+
*/
39+
labelKey?: string;
40+
/**
41+
* 自定义参数值-value对应的key名
42+
*/
43+
valueKey?: string;
44+
/**
45+
* 已存在的keys
46+
*/
47+
existingKeys: string[];
48+
/**
49+
* 自定义参数列表
50+
*/
51+
value?: Record<string, string>[];
52+
/**
53+
* 自定义参数改变触发函数
54+
* @param value
55+
* @returns
56+
*/
57+
onChange?: (value: ICustomValue[]) => void;
58+
}
59+
60+
const DEFAULT_FORM_ITEM: IComponentType = {
61+
type: 'INPUT',
62+
Component: Input,
63+
};
64+
65+
export default function CustomParameter({
66+
labelKey = 'label',
67+
valueKey = 'value',
68+
existingKeys,
69+
value,
70+
onChange,
71+
}: ICustomParameterProps) {
72+
const [customParamRows, setCustomParamRows] = useState<ICustomItem[]>([]);
73+
74+
const handleCustomParameterAdd = () => {
75+
const customItem: ICustomItem = {
76+
type: DEFAULT_FORM_ITEM.type,
77+
Component: DEFAULT_FORM_ITEM.Component,
78+
label: '',
79+
value: '',
80+
status: false,
81+
};
82+
83+
setCustomParamRows([...customParamRows, customItem]);
84+
};
85+
86+
const handleCustomParameterDelete = (index: number) => {
87+
const paramRows = customParamRows.filter((_, i) => i !== index);
88+
setCustomParamRows(paramRows);
89+
onChange?.(
90+
paramRows?.map((item) => ({
91+
label: item.label,
92+
value: item.value,
93+
type: item.type,
94+
status: item.status,
95+
}))
96+
);
97+
};
98+
99+
const handleIsSame = (item: ICustomItem) =>
100+
existingKeys.includes(item.label) || customParamRows.filter((cIt) => cIt.label === item.label).length > 1;
101+
102+
console.log(existingKeys);
103+
104+
useEffect(() => {
105+
setCustomParamRows(
106+
value?.map((item) => {
107+
return {
108+
type: item.type || DEFAULT_FORM_ITEM.type,
109+
label: item[labelKey],
110+
value: item[valueKey],
111+
Component: DEFAULT_FORM_ITEM.Component,
112+
status: false,
113+
};
114+
}) || []
115+
);
116+
}, []);
117+
118+
return (
119+
<div className="dtc-custom-parameter">
120+
{customParamRows.map((item, index) => (
121+
<Row className="dtc-custom-parameter__item" align={'middle'} key={index}>
122+
<Col span={8}>
123+
<Input
124+
value={item.label}
125+
style={{
126+
width: 'calc(100% - 18px)',
127+
}}
128+
status={!item.label ? 'error' : ''}
129+
onChange={(e: any) => {
130+
const params = customParamRows.map((item, i) => {
131+
if (i === index) item.label = e.target.value;
132+
return item;
133+
});
134+
setCustomParamRows(params);
135+
onChange?.(
136+
params?.map((item) => ({
137+
label: item.label,
138+
value: item.value,
139+
type: item.type,
140+
status: Boolean(item.label && item.value && !handleIsSame(item)),
141+
}))
142+
);
143+
}}
144+
/>
145+
<span className="dtc-custom-parameter__gap">:</span>
146+
</Col>
147+
<Col span={12}>
148+
<item.Component
149+
value={item.value}
150+
status={!item.value ? 'error' : ''}
151+
onChange={(e: any) => {
152+
const params = customParamRows.map((item, i) => {
153+
if (i === index) item.value = e.target.value;
154+
return item;
155+
});
156+
setCustomParamRows(params);
157+
onChange?.(
158+
params?.map((item) => ({
159+
label: item.label,
160+
value: item.value,
161+
type: item.type,
162+
status: Boolean(item.label && item.value && !handleIsSame(item)),
163+
}))
164+
);
165+
}}
166+
/>
167+
</Col>
168+
<Col span={4}>
169+
<div className="dtc-custom-parameter__delete">
170+
<Space>
171+
<DeleteOutlined
172+
style={{ fontSize: 18 }}
173+
onClick={() => handleCustomParameterDelete(index)}
174+
/>
175+
{handleIsSame(item) ? (
176+
<span className="dtc-custom-parameter__exist">已存在</span>
177+
) : null}
178+
</Space>
179+
</div>
180+
</Col>
181+
</Row>
182+
))}
183+
<Col span={16} offset={8}>
184+
<Space className="dtc-custom-parameter__add" onClick={handleCustomParameterAdd}>
185+
<PlusSquareOutlined />
186+
<span>{'添加自定义参数'}</span>
187+
</Space>
188+
</Col>
189+
</div>
190+
);
191+
}

taier-ui/src/pages/console/cluster/detail/detail.tsx

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ import {
2929
import type { RcFile } from 'antd/lib/upload';
3030

3131
import api from '@/api';
32+
import CustomParameter, { ICustomValue } from '@/components/customParameter';
3233
import { COMPONENT_TYPE_VALUE } from '@/constant';
3334
import context from '@/context/cluster';
3435
import type { IComponentProps } from '.';
@@ -38,6 +39,7 @@ const { Sider, Content } = Layout;
3839
const { Panel } = Collapse;
3940

4041
interface IDetailProps {
42+
form: any;
4143
templateData: ILayoutData[];
4244
currentTreeNode?: IComponentProps;
4345
loading?: boolean;
@@ -80,11 +82,12 @@ export interface ITemplateData {
8082
/**
8183
* XML 表示该值作为 config 渲染
8284
*/
83-
type: 'INPUT' | 'RADIO_LINKAGE' | 'CHECKBOX' | 'XML' | 'GROUP';
85+
type: 'INPUT' | 'RADIO_LINKAGE' | 'CHECKBOX' | 'XML' | 'GROUP' | 'CUSTOM';
8486
value: string;
8587
}
8688

8789
export default function Detail({
90+
form,
8891
loading,
8992
currentTreeNode,
9093
templateData = [],
@@ -371,6 +374,23 @@ export default function Detail({
371374
);
372375
}
373376
)}
377+
<Form.Item
378+
name={[template.groupName, 'customParameters'].join('$')}
379+
noStyle
380+
rules={[
381+
{
382+
validator(_, value: ICustomValue[]) {
383+
return value.every((item) => item.status)
384+
? Promise.resolve()
385+
: Promise.reject('自定义字段名重复');
386+
},
387+
},
388+
]}
389+
>
390+
<CustomParameter
391+
existingKeys={Object.keys(form.getFieldValue(template.groupName) || {})}
392+
/>
393+
</Form.Item>
374394
</Panel>
375395
</Collapse>
376396
);

taier-ui/src/pages/console/cluster/detail/index.tsx

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -400,8 +400,24 @@ export default function ClusterDetail() {
400400

401401
// 上传配置文件所解析出来的配置项会放在 config 字段中,不存在于 values 里
402402
const xmlConfig = form.getFieldValue('config');
403-
404-
const componentConfig = xmlConfig ? JSON.stringify(xmlConfig) : JSON.stringify(restValues);
403+
let componentConfig: string;
404+
const customParameters: Record<string, any> = {};
405+
if (xmlConfig) {
406+
componentConfig = JSON.stringify(xmlConfig);
407+
} else {
408+
const deploymode = restValues.deploymode;
409+
deploymode?.forEach((item: string) => {
410+
const key = [item, 'customParameters'].join('$');
411+
customParameters[item] = restValues[key];
412+
restValues[key]?.forEach((it: any) => {
413+
restValues[item][it.key] = it.value;
414+
});
415+
return {};
416+
});
417+
console.log(customParameters);
418+
console.log(restValues);
419+
componentConfig = JSON.stringify(restValues);
420+
}
405421

406422
try {
407423
setDetailLoading(true);
@@ -416,6 +432,7 @@ export default function ClusterDetail() {
416432
principals,
417433
versionName: Array.isArray(versionName) ? versionName[versionName.length - 1] : versionName,
418434
componentConfig,
435+
customParameters,
419436
deployType: currentComponent.deployType,
420437
clusterId: currentComponent.clusterId,
421438
componentCode: currentComponent.componentTypeCode,
@@ -632,6 +649,7 @@ export default function ClusterDetail() {
632649
<Content className="h-full">
633650
{selectedKey ? (
634651
<Detail
652+
form={form}
635653
loading={detailLoading}
636654
templateData={templateData}
637655
currentTreeNode={currentTreeNode}

0 commit comments

Comments
 (0)