Commit eb2ab085c591d96e76e2b92d5208908841c0c93d

Authored by 李婷
1 parent 07e3d34c

feat(选择表单): 组件重构

1 -import { DownOutlined } from '@ant-design/icons';  
2 -import {  
3 - Input,  
4 - Menu,  
5 - // message,  
6 - Modal,  
7 - Popover,  
8 - Radio,  
9 - Select,  
10 - // TreeSelect,  
11 - Typography,  
12 -} from 'antd';  
13 -import { cloneDeep } from 'lodash-es'; 1 +
14 import React, { useEffect, useMemo, useState } from 'react'; 2 import React, { useEffect, useMemo, useState } from 'react';
15 import { 3 import {
16 getAggreList, 4 getAggreList,
@@ -18,7 +6,12 @@ import { @@ -18,7 +6,12 @@ import {
18 getDatasetListByAppid, 6 getDatasetListByAppid,
19 getFunList, 7 getFunList,
20 } from './service'; 8 } from './service';
21 -// import { FRWidgetProps } from '@/packages/qx-form-generator/src'; 9 +import {
  10 + Modal,
  11 + Radio,
  12 + Select,
  13 + Typography,
  14 +} from 'antd';
22 import type { ModalProps } from 'antd'; 15 import type { ModalProps } from 'antd';
23 import {QxBaseIcon} from '@qx/common'; 16 import {QxBaseIcon} from '@qx/common';
24 17
@@ -60,6 +53,198 @@ type QxAppSelectProps = { @@ -60,6 +53,198 @@ type QxAppSelectProps = {
60 nodeFrom?: 'flow_query_single'; 53 nodeFrom?: 'flow_query_single';
61 request: any; 54 request: any;
62 }; 55 };
  56 +/* 表单组件 */
  57 +const RelItemOption: React.FC<any> = (riProps) => {
  58 + // const [visible, setVisible] = useState<boolean>(false);
  59 + const [list, setList] = useState<any>(riProps.list);
  60 + const [item, setItem] = useState<any>();
  61 + useEffect(() => {
  62 + if (riProps.item) {
  63 + setItem(riProps.item);
  64 + }
  65 +
  66 + if (riProps.list) {
  67 + setList(riProps.list);
  68 + }
  69 + }, [riProps]);
  70 +
  71 + // const filter = (word: string) => {
  72 + // if (list) {
  73 + // const _data = cloneDeep(list);
  74 + // _data.forEach((it: Item) => {
  75 + // it.deleted = !(it.name.indexOf(word) > -1);
  76 + // });
  77 + //
  78 + // setList(_data);
  79 + // }
  80 + // };
  81 +
  82 + // const handleChange = (_keyword: string) => {
  83 + // filter(_keyword.trim());
  84 + // };
  85 +
  86 + // const handleVisibleChange = (_visible: boolean) => {
  87 + // setVisible(_visible);
  88 + // };
  89 +
  90 + // const menus = () => {
  91 + // return (
  92 + // <div className={'qx-search-menus__wrap'}>
  93 + // <Input
  94 + // className={'qx-selector-sub-search'}
  95 + // placeholder={'输入名称,回车搜索'}
  96 + // allowClear
  97 + // prefix={<QxBaseIcon type={'icon-app-search-line'} />}
  98 + // onChange={(e) => {
  99 + // handleChange(e.target.value);
  100 + // }}
  101 + // />
  102 + // <div>
  103 + // <Menu mode={'inline'} selectedKeys={riProps?.item?.code}>
  104 + // {list && list.length > 0 ? (
  105 + // <>
  106 + // {list.map((it: any) => {
  107 + // return !it.deleted ? (
  108 + // <Menu.Item
  109 + // style={{ width: '100%' }}
  110 + // onClick={() => {
  111 + // riProps.onChange(it);
  112 + // setVisible(false);
  113 + // }}
  114 + // key={it.code}
  115 + // >
  116 + // {it.name}
  117 + // </Menu.Item>
  118 + // ) : null;
  119 + // })}
  120 + // </>
  121 + // ) : null}
  122 + // </Menu>
  123 + // </div>
  124 + // </div>
  125 + // );
  126 + // };
  127 +
  128 + //搜索
  129 + const filterOption = (input: string, option: any) =>
  130 + (option?.name ?? '').toLowerCase().includes(input.toLowerCase());
  131 +
  132 + return (
  133 + <>
  134 + <Title level={5} style={{ margin: '16px 0 8px' }}>
  135 + {riProps.title}
  136 + </Title>
  137 + <div style={{ width: '100%'}}>
  138 + <Select
  139 + showSearch
  140 + style={{ width: '100%', height: '36px' }}
  141 + placeholder={riProps.placeholder || '请选择数据源'}
  142 + options={list}
  143 + value={item?.code}
  144 + onChange={(val)=>{
  145 + const _list = list.filter((el: any) => el.code === val);
  146 + if(_list?.length) {
  147 + riProps.onChange(_list[0])
  148 + }
  149 + }}
  150 + dropdownStyle={{ maxHeight: 400, overflow: 'auto' }}
  151 + getPopupContainer={() => document.body}
  152 + filterOption={filterOption}
  153 + fieldNames={{
  154 + label: 'name',
  155 + value: 'code'
  156 + }}
  157 + />
  158 + {/*<Popover*/}
  159 + {/* content={menus}*/}
  160 + {/* open={visible}*/}
  161 + {/* trigger={'click'}*/}
  162 + {/* onOpenChange={handleVisibleChange}*/}
  163 + {/* placement="bottomLeft"*/}
  164 + {/* overlayClassName={'qx-fg-select-overlay'}*/}
  165 + {/* getPopupContainer={(triggerNode) => triggerNode}*/}
  166 + {/*>*/}
  167 + {/* <div*/}
  168 + {/* className={`ant-input qx-fr-input--fake select-source`}*/}
  169 + {/* >*/}
  170 + {/* <div>*/}
  171 + {/* {item?.name ? (*/}
  172 + {/* item.name*/}
  173 + {/* ) : (*/}
  174 + {/* <Text type="secondary">{riProps.placeholder}</Text>*/}
  175 + {/* )}*/}
  176 + {/* </div>*/}
  177 + {/* <DownOutlined />*/}
  178 + {/* </div>*/}
  179 + {/*</Popover>*/}
  180 + </div>
  181 + </>
  182 + );
  183 +};
  184 +/* 聚合表组件 */
  185 +const AggreOption: React.FC<any> = (_props: any) => {
  186 + return (
  187 + <>
  188 + <Title level={5} style={{ margin: '16px 0 8px' }}>
  189 + {_props.title}
  190 + </Title>
  191 + <Select
  192 + allowClear
  193 + style={{ width: '100%', height: '36px' }}
  194 + placeholder={_props.placeholder || '请选择数据源'}
  195 + options={_props.aggreList}
  196 + value={_props.aggreValue}
  197 + onChange={_props.onChange}
  198 + dropdownStyle={{ maxHeight: 400, overflow: 'auto' }}
  199 + getPopupContainer={() => document.body}
  200 + />
  201 + </>
  202 + );
  203 +};
  204 +
  205 +/**
  206 + * 表单类型选择
  207 + */
  208 +const TableTypeNode: React.FC<any> = (_typeProps: any) => {
  209 + const {showTableTypeTab, flag} = _typeProps
  210 + return (
  211 + <>
  212 + {showTableTypeTab && (
  213 + <Radio.Group
  214 + onChange={(e: any) => _typeProps.radioChange(e, _typeProps.appData)}
  215 + value={_typeProps.radioType}
  216 + defaultValue={_typeProps.defaultRadioType}
  217 + optionType="button"
  218 + style={{
  219 + width: '100%',
  220 + textAlign: 'center',
  221 + display: flag === 'join' ? '' : 'none',
  222 + height: '36px',
  223 + }}
  224 + >
  225 + <Radio.Button
  226 + value="single"
  227 + style={{
  228 + width: '50%',
  229 + height: '36px',
  230 + }}
  231 + >
  232 + 表单
  233 + </Radio.Button>
  234 + <Radio.Button
  235 + value="join"
  236 + style={{
  237 + width: '50%',
  238 + height: '36px',
  239 + }}
  240 + >
  241 + 聚合表
  242 + </Radio.Button>
  243 + </Radio.Group>
  244 + )}
  245 + </>
  246 + );
  247 +};
63 248
64 export const QxAppSelector: React.FC<QxAppSelectProps> = ({ 249 export const QxAppSelector: React.FC<QxAppSelectProps> = ({
65 showTableTypeTab = true, 250 showTableTypeTab = true,
@@ -231,178 +416,6 @@ export const QxAppSelector: React.FC<QxAppSelectProps> = ({ @@ -231,178 +416,6 @@ export const QxAppSelector: React.FC<QxAppSelectProps> = ({
231 return formList; 416 return formList;
232 }, [appItem?.extract, formList, props.nodeFrom]); 417 }, [appItem?.extract, formList, props.nodeFrom]);
233 418
234 - /* 表单组件 */  
235 - const RelItemOption: React.FC<any> = (riProps) => {  
236 - const [visible, setVisible] = useState<boolean>(false);  
237 - const [list, setList] = useState<any>(riProps.list);  
238 - const [item, setItem] = useState<any>();  
239 - useEffect(() => {  
240 - if (riProps.item) {  
241 - setItem(riProps.item);  
242 - }  
243 -  
244 - if (riProps.list) {  
245 - setList(riProps.list);  
246 - }  
247 - }, [riProps]);  
248 -  
249 - const filter = (word: string) => {  
250 - if (list) {  
251 - const _data = cloneDeep(list);  
252 - _data.forEach((it: Item) => {  
253 - it.deleted = !(it.name.indexOf(word) > -1);  
254 - });  
255 -  
256 - setList(_data);  
257 - }  
258 - };  
259 -  
260 - const handleChange = (_keyword: string) => {  
261 - filter(_keyword.trim());  
262 - };  
263 -  
264 - const handleVisibleChange = (_visible: boolean) => {  
265 - setVisible(_visible);  
266 - };  
267 -  
268 - const menus = () => {  
269 - return (  
270 - <div className={'qx-search-menus__wrap'}>  
271 - <Input  
272 - className={'qx-selector-sub-search'}  
273 - placeholder={'输入名称,回车搜索'}  
274 - allowClear  
275 - prefix={<QxBaseIcon type={'icon-app-search-line'} />}  
276 - onChange={(e) => {  
277 - handleChange(e.target.value);  
278 - }}  
279 - />  
280 - <div>  
281 - <Menu mode={'inline'} selectedKeys={riProps?.item?.code}>  
282 - {list && list.length > 0 ? (  
283 - <>  
284 - {list.map((it: any) => {  
285 - return !it.deleted ? (  
286 - <Menu.Item  
287 - style={{ width: '100%' }}  
288 - onClick={() => {  
289 - riProps.onChange(it);  
290 - setVisible(false);  
291 - }}  
292 - key={it.code}  
293 - >  
294 - {it.name}  
295 - </Menu.Item>  
296 - ) : null;  
297 - })}  
298 - </>  
299 - ) : null}  
300 - </Menu>  
301 - </div>  
302 - </div>  
303 - );  
304 - };  
305 -  
306 - return (  
307 - <>  
308 - <Title level={5} style={{ margin: '20px 0 6px' }}>  
309 - {riProps.title}  
310 - </Title>  
311 - <div style={{ width: '100%', marginBottom: '20px' }}>  
312 - <Popover  
313 - content={menus}  
314 - open={visible}  
315 - trigger={'click'}  
316 - onOpenChange={handleVisibleChange}  
317 - placement="bottomLeft"  
318 - overlayClassName={'qx-fg-select-overlay'}  
319 - getPopupContainer={(triggerNode) => triggerNode}  
320 - >  
321 - <div  
322 - className={`ant-input qx-fr-input--fake select-source css-dev-only-do-not-override-nnuwmp`}  
323 - style={{  
324 - height: '36px',  
325 - }}  
326 - >  
327 - <div>  
328 - {item?.name ? (  
329 - item.name  
330 - ) : (  
331 - <Text type="secondary">{riProps.placeholder}</Text>  
332 - )}  
333 - </div>  
334 - <DownOutlined />  
335 - </div>  
336 - {/*<Input/>*/}  
337 - </Popover>  
338 - </div>  
339 - </>  
340 - );  
341 - };  
342 - /* 聚合表组件 */  
343 - const AggreOption: React.FC<any> = (_props: any) => {  
344 - return (  
345 - <>  
346 - <Title level={5} style={{ margin: '20px 0 6px' }}>  
347 - {_props.title}  
348 - </Title>  
349 - <Select  
350 - allowClear  
351 - style={{ width: '100%', height: '36px' }}  
352 - placeholder={_props.placeholder || '请选择数据源'}  
353 - options={_props.aggreList}  
354 - value={_props.aggreValue}  
355 - onChange={_props.onChange}  
356 - dropdownStyle={{ maxHeight: 400, overflow: 'auto' }}  
357 - getPopupContainer={(triggerNode) => triggerNode}  
358 - />  
359 - </>  
360 - );  
361 - };  
362 -  
363 - /**  
364 - * 表单类型选择  
365 - */  
366 - const TableTypeNode: React.FC<any> = (_typeProps: any) => {  
367 - return (  
368 - <>  
369 - {showTableTypeTab && (  
370 - <Radio.Group  
371 - onChange={(e: any) => _typeProps.radioChange(e, _typeProps.appData)}  
372 - value={_typeProps.radioType}  
373 - defaultValue={_typeProps.defaultRadioType}  
374 - optionType="button"  
375 - style={{  
376 - width: '100%',  
377 - textAlign: 'center',  
378 - display: props.flag === 'join' ? '' : 'none',  
379 - height: '36px',  
380 - }}  
381 - >  
382 - <Radio.Button  
383 - value="single"  
384 - style={{  
385 - width: '50%',  
386 - height: '36px',  
387 - }}  
388 - >  
389 - 表单  
390 - </Radio.Button>  
391 - <Radio.Button  
392 - value="join"  
393 - style={{  
394 - width: '50%',  
395 - height: '36px',  
396 - }}  
397 - >  
398 - 聚合表  
399 - </Radio.Button>  
400 - </Radio.Group>  
401 - )}  
402 - </>  
403 - );  
404 - };  
405 -  
406 return ( 419 return (
407 <> 420 <>
408 <Modal 421 <Modal
@@ -461,7 +474,7 @@ export const QxAppSelector: React.FC<QxAppSelectProps> = ({ @@ -461,7 +474,7 @@ export const QxAppSelector: React.FC<QxAppSelectProps> = ({
461 placeholder={'请选择应用'} 474 placeholder={'请选择应用'}
462 /> 475 />
463 <> 476 <>
464 - <Title level={5} style={{ margin: '20px 0 6px' }}> 477 + <Title level={5} style={{ margin: '20px 0 8px' }}>
465 数据类型 478 数据类型
466 </Title> 479 </Title>
467 <TableTypeNode 480 <TableTypeNode
@@ -469,6 +482,8 @@ export const QxAppSelector: React.FC<QxAppSelectProps> = ({ @@ -469,6 +482,8 @@ export const QxAppSelector: React.FC<QxAppSelectProps> = ({
469 defaultRadioType={defaultTableType} 482 defaultRadioType={defaultTableType}
470 appData={appItem} 483 appData={appItem}
471 radioChange={radioChange} 484 radioChange={radioChange}
  485 + showTableTypeTab={showTableTypeTab}
  486 + flag={props.flag}
472 /> 487 />
473 </> 488 </>
474 {tableType === 'single' ? ( 489 {tableType === 'single' ? (
@@ -506,6 +521,8 @@ export const QxAppSelector: React.FC<QxAppSelectProps> = ({ @@ -506,6 +521,8 @@ export const QxAppSelector: React.FC<QxAppSelectProps> = ({
506 defaultRadioType={defaultTableType} 521 defaultRadioType={defaultTableType}
507 appData={appItem} 522 appData={appItem}
508 radioChange={radioChange} 523 radioChange={radioChange}
  524 + showTableTypeTab={showTableTypeTab}
  525 + flag={props.flag}
509 /> 526 />
510 {tableType === 'single' ? ( 527 {tableType === 'single' ? (
511 <div style={{ margin: '20px auto' }}> 528 <div style={{ margin: '20px auto' }}>
@@ -546,8 +563,8 @@ export const QxAppSelector: React.FC<QxAppSelectProps> = ({ @@ -546,8 +563,8 @@ export const QxAppSelector: React.FC<QxAppSelectProps> = ({
546 ); 563 );
547 }; 564 };
548 565
549 -type Item = {  
550 - name: string;  
551 - code?: string;  
552 - deleted?: boolean;  
553 -}; 566 +// type Item = {
  567 +// name: string;
  568 +// code?: string;
  569 +// deleted?: boolean;
  570 +// };
@@ -12,24 +12,36 @@ @@ -12,24 +12,36 @@
12 display: none; 12 display: none;
13 } 13 }
14 14
15 - .ant-input.select-source {  
16 - display: flex;  
17 - flex-direction: row;  
18 - align-items: center;  
19 - justify-content: space-between;  
20 - min-height: 32px;  
21 - position: unset;  
22 - transition: all .3s;  
23 -  
24 - .ant-tag {  
25 - margin: 1px;  
26 - }  
27 -  
28 - > .anticon {  
29 - padding: 0 6px;  
30 - color: @N5;  
31 - font-size: 12px;  
32 - }  
33 - } 15 + //.ant-input.select-source {
  16 + // display: flex;
  17 + // flex-direction: row;
  18 + // align-items: center;
  19 + // justify-content: space-between;
  20 + // min-height: 32px;
  21 + // transition: all .3s;
  22 + // box-sizing: border-box;
  23 + // margin: 0;
  24 + // list-style: none;
  25 + // width: 100%;
  26 + // padding: 4px 11px;
  27 + // font-size: 14px;
  28 + // background-color: #fff;
  29 + // border: 1px solid #d9d9d9;
  30 + // border-radius: 4px;
  31 + //
  32 + // &:hover {
  33 + // border-color: @B8;
  34 + // }
  35 + //
  36 + // .ant-tag {
  37 + // margin: 1px;
  38 + // }
  39 + //
  40 + // > .anticon {
  41 + // padding: 0 6px;
  42 + // color: @N5;
  43 + // font-size: 12px;
  44 + // }
  45 + //}
34 } 46 }
35 47