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 2 import React, { useEffect, useMemo, useState } from 'react';
15 3 import {
16 4 getAggreList,
... ... @@ -18,7 +6,12 @@ import {
18 6 getDatasetListByAppid,
19 7 getFunList,
20 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 15 import type { ModalProps } from 'antd';
23 16 import {QxBaseIcon} from '@qx/common';
24 17
... ... @@ -60,6 +53,198 @@ type QxAppSelectProps = {
60 53 nodeFrom?: 'flow_query_single';
61 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 249 export const QxAppSelector: React.FC<QxAppSelectProps> = ({
65 250 showTableTypeTab = true,
... ... @@ -231,178 +416,6 @@ export const QxAppSelector: React.FC<QxAppSelectProps> = ({
231 416 return formList;
232 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 419 return (
407 420 <>
408 421 <Modal
... ... @@ -461,7 +474,7 @@ export const QxAppSelector: React.FC<QxAppSelectProps> = ({
461 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 479 </Title>
467 480 <TableTypeNode
... ... @@ -469,6 +482,8 @@ export const QxAppSelector: React.FC<QxAppSelectProps> = ({
469 482 defaultRadioType={defaultTableType}
470 483 appData={appItem}
471 484 radioChange={radioChange}
  485 + showTableTypeTab={showTableTypeTab}
  486 + flag={props.flag}
472 487 />
473 488 </>
474 489 {tableType === 'single' ? (
... ... @@ -506,6 +521,8 @@ export const QxAppSelector: React.FC<QxAppSelectProps> = ({
506 521 defaultRadioType={defaultTableType}
507 522 appData={appItem}
508 523 radioChange={radioChange}
  524 + showTableTypeTab={showTableTypeTab}
  525 + flag={props.flag}
509 526 />
510 527 {tableType === 'single' ? (
511 528 <div style={{ margin: '20px auto' }}>
... ... @@ -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 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
... ...