Showing
30 changed files
with
403 additions
and
392 deletions
... | ... | @@ -7,14 +7,16 @@ const cwd = process.cwd(); |
7 | 7 | |
8 | 8 | module.exports = { |
9 | 9 | output: { |
10 | - filename: 'index.js', | |
10 | + filename: 'qx-[name]-[contenthash].bundle.js', | |
11 | 11 | libraryTarget: 'umd', |
12 | + clean: true, | |
12 | 13 | }, |
13 | 14 | entry: path.resolve(cwd, './src/index.tsx'), |
14 | 15 | module: { |
15 | 16 | rules: [ |
16 | 17 | { |
17 | 18 | test: /\.(js|jsx)$/, |
19 | + exclude: /node_modules/, | |
18 | 20 | use: { |
19 | 21 | loader: 'babel-loader', |
20 | 22 | options: { |
... | ... | @@ -29,14 +31,23 @@ module.exports = { |
29 | 31 | }, |
30 | 32 | }, |
31 | 33 | { |
32 | - test: /\.(ttf|eot|woff(2)?)(\?[a-z0-9=&.]+)?$/, | |
34 | + test: /\.(png|jpeg|jpg|ttf|eot|woff(2)?)(\?[a-z0-9=&.]+)?$/, | |
33 | 35 | use: { |
34 | 36 | loader: 'file-loader', |
35 | 37 | }, |
36 | 38 | }, |
37 | 39 | { |
38 | 40 | test: /\.less$/i, |
39 | - use: ['style-loader', 'css-loader', 'less-loader'], | |
41 | + use: [ | |
42 | + 'style-loader', | |
43 | + 'css-loader', | |
44 | + { | |
45 | + loader: 'less-loader', | |
46 | + options: { | |
47 | + additionalData: `@import '@qx/ui/dist/src/style/variable.less';`, | |
48 | + }, | |
49 | + }, | |
50 | + ], | |
40 | 51 | }, |
41 | 52 | { |
42 | 53 | test: /\.svg$/, | ... | ... |
src/components/dynamic-component/index.tsx
deleted
100644 → 0
... | ... | @@ -26,6 +26,7 @@ const FlowVersion: React.FC<FlowVersionProps> = (props) => { |
26 | 26 | return ( |
27 | 27 | <> |
28 | 28 | {versionText || |
29 | + // @ts-ignore | |
29 | 30 | (statusEnums || FlowStatusEnums)[status || 'UNPUBLISHED'] ? ( |
30 | 31 | <div |
31 | 32 | className={cls( |
... | ... | @@ -51,6 +52,7 @@ const FlowVersion: React.FC<FlowVersionProps> = (props) => { |
51 | 52 | > |
52 | 53 | {!!versionText ? <span>V {versionText}</span> : null} |
53 | 54 | {!!status ? ( |
55 | + // @ts-ignore | |
54 | 56 | <span>{(statusEnums || FlowStatusEnums)[status]}</span> |
55 | 57 | ) : null} |
56 | 58 | </div> | ... | ... |
src/components/lazy-component/index.tsx
0 → 100644
1 | +import React, { Suspense } from 'react'; | |
2 | +import { Skeleton } from 'antd'; | |
3 | + | |
4 | +const lazyComponent = (importComp: () => any) => { | |
5 | + const Comp = React.lazy(importComp); | |
6 | + return ( | |
7 | + <Suspense fallback={<Skeleton.Input />}> | |
8 | + <Comp></Comp> | |
9 | + </Suspense> | |
10 | + ); | |
11 | +}; | |
12 | + | |
13 | +export default lazyComponent; | ... | ... |
... | ... | @@ -62,6 +62,7 @@ const NameDescriptionSetting: React.FC<NameDescriptionSettingProps> = ( |
62 | 62 | if (_.isEmpty(values)) { |
63 | 63 | form.resetFields(); |
64 | 64 | } else { |
65 | + // @ts-ignore | |
65 | 66 | form.setValues(values); |
66 | 67 | } |
67 | 68 | }, 100); |
... | ... | @@ -114,6 +115,7 @@ const NameDescriptionSetting: React.FC<NameDescriptionSettingProps> = ( |
114 | 115 | form={form} |
115 | 116 | schema={FORM_SCHEMA} |
116 | 117 | onMount={() => {}} |
118 | + // @ts-ignore | |
117 | 119 | onFinish={onFinish} |
118 | 120 | watch={{}} |
119 | 121 | /> | ... | ... |
... | ... | @@ -2,12 +2,13 @@ import React, { memo, useContext, useEffect, useState } from 'react'; |
2 | 2 | import { BuilderContext } from '@qx/flow'; |
3 | 3 | import { Drawer, Spin, Tabs } from 'antd'; |
4 | 4 | import NodeList, { NodeItemsProps } from './components/node-list'; |
5 | -import { useLocation, useSearchParams } from 'react-router-dom'; | |
5 | +import { useSearchParams } from '@/hooks'; | |
6 | 6 | import { getListGroupNode } from '@/services'; |
7 | 7 | import { QxIcon } from '@/components'; |
8 | 8 | import { ReactSortable } from 'react-sortablejs'; |
9 | 9 | import { cloneDeep } from 'lodash-es'; |
10 | 10 | import { v4 as uuid } from 'uuid'; |
11 | +// @ts-ignore | |
11 | 12 | import type { INodePanelProps } from '@qx/flow'; |
12 | 13 | import Empty from './img/empty.png'; |
13 | 14 | |
... | ... | @@ -31,10 +32,10 @@ const panelTabs = [ |
31 | 32 | ]; |
32 | 33 | |
33 | 34 | const NodePanel: React.FC<NodePanelProps> = (props) => { |
34 | - const { visible, onClose } = props; | |
35 | 35 | // @ts-ignore |
36 | - const [searchParams] = useSearchParams(); | |
37 | - const appId = searchParams.get('appId'); | |
36 | + const { visible, onClose } = props; | |
37 | + const [query] = useSearchParams<any>(); | |
38 | + const appId = query?.appId; | |
38 | 39 | const { registerNodes } = useContext(BuilderContext); |
39 | 40 | const [loading, setLoading] = useState(false); |
40 | 41 | const [activeKey, setActiveKey] = useState('SYSTEM'); | ... | ... |
src/hooks/useFlowTableScrollY.ts
0 → 100644
1 | +import React, { useEffect, useMemo, useRef, useState } from 'react'; | |
2 | + | |
3 | +// 表格 Scroll 高度计算 | |
4 | +export const useFlowTableScrollY = ( | |
5 | + deps: { | |
6 | + columns: any[]; | |
7 | + size?: 'small' | 'middle' | 'default'; | |
8 | + tableBoxClassName?: string; | |
9 | + classNames?: string[]; // 表格DOM内嵌元素 列名 添加在此, | |
10 | + hasPagination?: boolean; | |
11 | + listProps?: any; | |
12 | + } = { | |
13 | + size: 'small', | |
14 | + tableBoxClassName: '', | |
15 | + classNames: [], | |
16 | + hasPagination: false, | |
17 | + columns: [], | |
18 | + listProps: {}, | |
19 | + }, | |
20 | +) => { | |
21 | + const itemHeaderHeight = | |
22 | + (deps?.size === 'middle' ? 48 : deps?.size === 'default' ? 56 : 40) + 1; | |
23 | + const TABLE_VIEW_LIST = deps?.tableBoxClassName || 'qx-data-flow-table'; | |
24 | + let tableHeader = itemHeaderHeight; | |
25 | + const tableViewListDefaultHeight = 400; | |
26 | + const defaultPagePadding = 0; | |
27 | + | |
28 | + const $ = (selectors: string) => | |
29 | + document.querySelector<HTMLElement>(selectors); | |
30 | + | |
31 | + const defaultScrollY = useMemo( | |
32 | + () => document.body.clientHeight, | |
33 | + [tableHeader], | |
34 | + ); | |
35 | + | |
36 | + const [scrollY, setScrollY] = useState<number>(defaultScrollY ?? 200); | |
37 | + | |
38 | + // @ts-ignore | |
39 | + const timer = useRef<NodeJS.Timer>(); | |
40 | + | |
41 | + const getScrollY = () => { | |
42 | + const tableViewList = $(`.${TABLE_VIEW_LIST}`); | |
43 | + | |
44 | + const tableViewListClientHeight = | |
45 | + tableViewList?.clientHeight || tableViewListDefaultHeight; | |
46 | + // 分页大小 目前已经固定 所以直接用56px | |
47 | + const antPaginationHeight = deps?.hasPagination ? 56 : 0; | |
48 | + | |
49 | + const _domHeightByClassName = (deps?.classNames || []).map( | |
50 | + (_v: string) => $(`.${_v}`)?.clientHeight ?? 0, | |
51 | + ); | |
52 | + let result = | |
53 | + tableViewListClientHeight - | |
54 | + tableHeader - | |
55 | + defaultPagePadding - | |
56 | + antPaginationHeight; | |
57 | + if (!!_domHeightByClassName?.length) { | |
58 | + result = result - eval(_domHeightByClassName.join('+')); | |
59 | + } | |
60 | + | |
61 | + if (tableViewList) { | |
62 | + tableViewList.style.overflowY = result < 200 ? 'auto' : 'hidden'; | |
63 | + } | |
64 | + | |
65 | + setScrollY(result < 100 ? 100 : result); | |
66 | + }; | |
67 | + | |
68 | + const observer = () => { | |
69 | + window.addEventListener('resize', getScrollY); | |
70 | + }; | |
71 | + | |
72 | + const removeObserver = () => { | |
73 | + if (timer.current) window.clearTimeout(timer.current); | |
74 | + window.removeEventListener('resize', getScrollY); | |
75 | + }; | |
76 | + | |
77 | + useEffect(() => { | |
78 | + observer(); | |
79 | + return () => { | |
80 | + removeObserver(); | |
81 | + }; | |
82 | + }, [tableHeader]); | |
83 | + | |
84 | + useEffect(() => { | |
85 | + if (deps) { | |
86 | + timer.current = setTimeout(() => { | |
87 | + getScrollY(); | |
88 | + }, 100); | |
89 | + } | |
90 | + }, [JSON.stringify(deps)]); | |
91 | + | |
92 | + return [scrollY, getScrollY]; | |
93 | +}; | ... | ... |
src/hooks/useSearchParams.ts
0 → 100644
1 | +import { useMemo } from 'react'; | |
2 | +import { useSearchParams as useRouterDOMSearchParams } from 'react-router-dom'; | |
3 | + | |
4 | +export const useSearchParams = <T = Record<string, any>>() => { | |
5 | + const [searchParams, setQuery] = useRouterDOMSearchParams(); | |
6 | + | |
7 | + const query = useMemo<T>(() => { | |
8 | + const params = {} as T; | |
9 | + searchParams.forEach((value, key) => { | |
10 | + (params as Record<string, any>)[key] = value; | |
11 | + }); | |
12 | + return params; | |
13 | + }, []); | |
14 | + | |
15 | + return [query, setQuery]; | |
16 | +}; | ... | ... |
... | ... | @@ -17,7 +17,7 @@ import { Start, End } from './nodes'; |
17 | 17 | import { NodeTypes, ProcessItemProps, FlowStatusEnums } from '@/interface'; |
18 | 18 | import { handleWindowOpen } from '@qx/utils'; |
19 | 19 | // import { history } from '@@/core/history'; |
20 | -import { useLocation, useSearchParams } from 'react-router-dom'; | |
20 | +import { useLocation } from 'react-router-dom'; | |
21 | 21 | import { useTitle } from 'ahooks'; |
22 | 22 | // 头部相关 |
23 | 23 | import { |
... | ... | @@ -31,6 +31,7 @@ import cls from 'classnames'; |
31 | 31 | import styles from '@/components/header/index.module.less'; |
32 | 32 | import { getIcon } from '@/utils'; |
33 | 33 | import { QxIcon } from '@/components'; |
34 | +import { useSearchParams } from '@/hooks'; | |
34 | 35 | import { |
35 | 36 | getProcessDetailsById, |
36 | 37 | publishProcessById, |
... | ... | @@ -71,8 +72,7 @@ const systemNodes: IRegisterNode[] = [ |
71 | 72 | export default () => { |
72 | 73 | const [nodes, setNodes] = useState<INode[]>([]); |
73 | 74 | const [remoteNodes, setRemoteNodes] = useState<IRegisterRemoteNode[]>([]); |
74 | - // @ts-ignore | |
75 | - const [searchParams] = useSearchParams(); | |
75 | + const [query, setQuery] = useSearchParams<any>(); | |
76 | 76 | const [showEditTitle, setShowEditTitle] = useState(false); |
77 | 77 | const { |
78 | 78 | appId, // 应用id |
... | ... | @@ -80,13 +80,7 @@ export default () => { |
80 | 80 | returnUrl, // 来自页面跳转返回可跳转 |
81 | 81 | processId, // 流程Id preview |
82 | 82 | type, // 流程类型 edit 编辑 preview 预览 |
83 | - } = { | |
84 | - appId: searchParams.get('appId'), | |
85 | - funCode: searchParams.get('funCode'), | |
86 | - returnUrl: searchParams.get('returnUrl'), | |
87 | - processId: searchParams.get('processId'), | |
88 | - type: searchParams.get('type'), | |
89 | - }; | |
83 | + } = query; | |
90 | 84 | |
91 | 85 | const [processDetails, setProcessDetails] = useState<ProcessItemProps>({ |
92 | 86 | id: '', |
... | ... | @@ -116,6 +110,7 @@ export default () => { |
116 | 110 | .catch((err: { msg?: string }) => { |
117 | 111 | message.warning(err?.msg || '流程详情数据请求失败', 5); |
118 | 112 | setProcessDetails( |
113 | + // @ts-ignore | |
119 | 114 | _data || { |
120 | 115 | id: _id, |
121 | 116 | name: '未命名流程', |
... | ... | @@ -198,7 +193,7 @@ export default () => { |
198 | 193 | // 发布流程 |
199 | 194 | // TODO 要先校验是否保存 才能发布 |
200 | 195 | publishProcessById(processDetails.id || '') |
201 | - .then((res) => { | |
196 | + .then((res: any) => { | |
202 | 197 | console.log('res ====', res); |
203 | 198 | }) |
204 | 199 | .catch((err: { msg?: string }) => { |
... | ... | @@ -237,11 +232,8 @@ export default () => { |
237 | 232 | remark: data.remark, |
238 | 233 | }); |
239 | 234 | if (!processDetails?.id) { |
240 | - history.replace({ | |
241 | - query: { | |
242 | - ...query, | |
243 | - processId: res, | |
244 | - }, | |
235 | + setQuery({ | |
236 | + processId: res, | |
245 | 237 | }); |
246 | 238 | } |
247 | 239 | } |
... | ... | @@ -389,6 +381,7 @@ export default () => { |
389 | 381 | useEffect(() => { |
390 | 382 | let _data: ProcessItemProps = {}; |
391 | 383 | _data.name = '未命名流程'; |
384 | + // @ts-ignore | |
392 | 385 | _data.appId = appId; |
393 | 386 | if (!!funCode) { |
394 | 387 | _data.funCode = funCode; |
... | ... | @@ -416,6 +409,7 @@ export default () => { |
416 | 409 | defaultTools: INode[], |
417 | 410 | actions: any, |
418 | 411 | ) => { |
412 | + console.log('nodes', nodes); | |
419 | 413 | const { copyNodeAndChildren } = actions; |
420 | 414 | switch (node.type) { |
421 | 415 | case 'condition': |
... | ... | @@ -452,6 +446,7 @@ export default () => { |
452 | 446 | registerNodes={systemNodes} |
453 | 447 | historyTool |
454 | 448 | zoomTool |
449 | + // @ts-ignore | |
455 | 450 | expandAllTool |
456 | 451 | DrawerComponent={Drawer} |
457 | 452 | PopoverComponent={Popover} |
... | ... | @@ -463,6 +458,7 @@ export default () => { |
463 | 458 | registerRemoteNodes={remoteNodes} |
464 | 459 | ConfigDrawerContainer={ConfigDrawer} |
465 | 460 | NodePanel={NodesPanel} |
461 | + // @ts-ignore | |
466 | 462 | getNodeTool={getNodeTool} |
467 | 463 | /> |
468 | 464 | <NameDescriptionSetting cRef={formModalRef} handleClick={handleClick} /> | ... | ... |
1 | 1 | import React, { useContext, memo, useImperativeHandle } from 'react'; |
2 | -import { useForm } from '@qx/form-render'; | |
3 | -import QxFormRender from '@/packages/qx-form-generator/src/form-render'; | |
4 | -import { conditionSetting } from '../../setting-configs'; | |
2 | +// import { useForm } from '@qx/form-render'; | |
3 | +// import QxFormRender from '@/packages/qx-form-generator/src/form-render'; | |
4 | +// import { conditionSetting } from '../../setting-configs'; | |
5 | 5 | import styles from './index.less'; |
6 | 6 | import type { IConfigComponent } from '@qx/flow'; |
7 | 7 | |
8 | 8 | const StartConfigComponent = React.forwardRef<any, StartConfigComponentProps>( |
9 | 9 | (props, ref) => { |
10 | - const form = useForm(); | |
10 | + // const form = useForm(); | |
11 | 11 | |
12 | 12 | const handleValuesChange = (values: any) => { |
13 | 13 | props?.onChange(values); |
14 | 14 | }; |
15 | 15 | |
16 | 16 | useImperativeHandle(ref, () => ({ |
17 | - validateFields: form.validateFields, | |
17 | + // validateFields: form.validateFields, | |
18 | 18 | })); |
19 | 19 | |
20 | 20 | return ( |
21 | 21 | <div className={styles['qx-flow-single-records-config']}> |
22 | - <QxFormRender | |
22 | + {/* <QxFormRender | |
23 | 23 | form={form} |
24 | 24 | schema={conditionSetting} |
25 | 25 | widgets={{}} |
26 | 26 | watch={{}} |
27 | 27 | onValuesChange={handleValuesChange} |
28 | - /> | |
28 | + /> */} | |
29 | 29 | </div> |
30 | 30 | ); |
31 | 31 | }, | ... | ... |
1 | 1 | import React, { useContext, memo } from 'react'; |
2 | -import { useForm } from '@qx/form-render'; | |
2 | +// import { useForm } from '@qx/form-render'; | |
3 | 3 | import { useDrawer } from '@qx/flow'; |
4 | -import { ConfigComponentFooter } from '../../components'; | |
5 | -import QxFormRender from '@/packages/qx-form-generator/src/form-render'; | |
6 | -import { startSetting } from '../../setting-configs'; | |
4 | +// import { ConfigComponentFooter } from '../../components'; | |
5 | +// import QxFormRender from '@/packages/qx-form-generator/src/form-render'; | |
6 | +// import { startSetting } from '../../setting-configs'; | |
7 | 7 | import styles from './index.less'; |
8 | 8 | import type { IConfigComponent } from '@qx/flow'; |
9 | 9 | |
10 | 10 | const EndConfigComponent: React.FC<EndConfigComponentProps> = (props) => { |
11 | - const form = useForm(); | |
12 | - const { closeDrawer: cancel, saveDrawer: save } = useDrawer(); | |
11 | + // const form = useForm(); | |
13 | 12 | |
14 | - const onSave = async () => { | |
15 | - try { | |
16 | - await form.submit(); | |
17 | - const values = form.getValues(); | |
18 | - console.log('values', values); | |
19 | - save(values); | |
20 | - } catch (error) { | |
21 | - console.log(error); | |
22 | - } | |
23 | - }; | |
24 | - | |
25 | - return ( | |
26 | - <div className={styles['qx-flow-single-records-config']}> | |
27 | - <QxFormRender form={form} schema={startSetting} widgets={{}} watch={{}} /> | |
28 | - <ConfigComponentFooter onSave={onSave} onCancel={cancel} /> | |
29 | - </div> | |
30 | - ); | |
13 | + return <div className={styles['qx-flow-single-records-config']}></div>; | |
31 | 14 | }; |
32 | 15 | |
33 | 16 | interface EndConfigComponentProps extends IConfigComponent {} | ... | ... |
1 | 1 | import React, { memo } from 'react'; |
2 | -// import { ReactComponent as Icon } from "../../public/icons/outlined.svg"; | |
2 | +import { Button, Typography } from 'antd'; | |
3 | +import { useAction } from '@qx/flow'; | |
4 | +const { Text } = Typography; | |
3 | 5 | import type { IDisplayComponent, INode } from '@qx/flow'; |
4 | -import './index.less'; | |
6 | + | |
7 | +const paramsEnums: Record<string, string> = { | |
8 | + STRING: '文本', | |
9 | + NUMBER: '数字', | |
10 | + TIME: '日期', | |
11 | + BOOL: '布尔', | |
12 | + OBJECT: '对象', | |
13 | + ARRAY: '数组', | |
14 | + ANNEX: '附件', | |
15 | + PIC: '图片', | |
16 | + FORM: '表单', | |
17 | + USER: '人员', | |
18 | + ORG: '部门', | |
19 | +}; | |
5 | 20 | |
6 | 21 | const DisplayComponent: React.FC<DisplayComponentProps> = (props) => { |
7 | 22 | const { node, nodes } = props; |
8 | 23 | |
24 | + const handleChangeName = (newValue: string) => { | |
25 | + node.name = newValue; | |
26 | + props.onChange?.([...nodes]); | |
27 | + }; | |
28 | + | |
29 | + const { clickNode } = useAction(); | |
30 | + | |
9 | 31 | return ( |
10 | 32 | <div className="qx-flow-default-node"> |
11 | 33 | <div className="qx-flow-default-node__header"> |
... | ... | @@ -16,13 +38,38 @@ const DisplayComponent: React.FC<DisplayComponentProps> = (props) => { |
16 | 38 | <span className="qx-flow-default-node__title--name">{node.name}</span> |
17 | 39 | </span> |
18 | 40 | </div> |
19 | - <div className="qx-flow-default-node__content"> | |
20 | - {!node.data ? ( | |
21 | - <span className="qx-flow-start-node__button">设置入参</span> | |
22 | - ) : ( | |
23 | - <span>节点配置内容</span> | |
24 | - )} | |
25 | - </div> | |
41 | + {!!node?.data?.params?.length ? ( | |
42 | + <> | |
43 | + <div className="qx-flow-default-node__content"> | |
44 | + {props?.node?.data?.params.map((_v: any) => { | |
45 | + return ( | |
46 | + <Text | |
47 | + style={{ | |
48 | + width: '100%', | |
49 | + lineHeight: '22px', | |
50 | + }} | |
51 | + ellipsis={{ | |
52 | + tooltip: `${paramsEnums?.[_v.type || '']} ${ | |
53 | + _v.title || '未命名' | |
54 | + }`, | |
55 | + }} | |
56 | + > | |
57 | + {paramsEnums?.[_v.type || '']} {_v.title || '未命名'} | |
58 | + </Text> | |
59 | + ); | |
60 | + })} | |
61 | + </div> | |
62 | + </> | |
63 | + ) : ( | |
64 | + <Button | |
65 | + style={{ marginTop: 8 }} | |
66 | + type="link" | |
67 | + size="small" | |
68 | + // onClick={() => clickNode()} | |
69 | + > | |
70 | + 设置入参 | |
71 | + </Button> | |
72 | + )} | |
26 | 73 | </div> |
27 | 74 | ); |
28 | 75 | }; | ... | ... |
src/page/designer/nodes/loop/configComponent.tsx
deleted
100644 → 0
1 | -import React, { useContext, memo } from 'react'; | |
2 | -import { useForm } from '@qx/form-render'; | |
3 | -import { useDrawer } from '@qx/flow'; | |
4 | -import { ConfigComponentFooter } from '../../components'; | |
5 | -import QxFormRender from '@/packages/qx-form-generator/src/form-render'; | |
6 | -import { loopSetting } from '../../setting-configs'; | |
7 | -import styles from './index.less'; | |
8 | -import type { IConfigComponent } from '@qx/flow'; | |
9 | - | |
10 | -const LoopConfigComponent: React.FC<LoopConfigComponentProps> = (props) => { | |
11 | - const form = useForm(); | |
12 | - const { closeDrawer: cancel, saveDrawer: save } = useDrawer(); | |
13 | - | |
14 | - const onSave = async () => { | |
15 | - try { | |
16 | - await form.submit(); | |
17 | - const values = form.getValues(); | |
18 | - console.log('values', values); | |
19 | - save(values); | |
20 | - } catch (error) { | |
21 | - console.log(error); | |
22 | - } | |
23 | - }; | |
24 | - | |
25 | - return ( | |
26 | - <div className={styles['qx-flow-single-records-config']}> | |
27 | - <QxFormRender form={form} schema={LoopSetting} widgets={{}} watch={{}} /> | |
28 | - <ConfigComponentFooter onSave={onSave} onCancel={cancel} /> | |
29 | - </div> | |
30 | - ); | |
31 | -}; | |
32 | - | |
33 | -interface LoopConfigComponentProps extends IConfigComponent {} | |
34 | - | |
35 | -export default memo(LoopConfigComponent); |
src/page/designer/nodes/loop/displayComponent.tsx
deleted
100644 → 0
1 | -import React, { memo, useContext } from 'react'; | |
2 | -import { useAction } from '@qx/flow'; | |
3 | -import type { IDisplayComponent } from '@qx/flow'; | |
4 | - | |
5 | -const ConditionDisplayComponent: React.FC<ConditionDisplayComponentProps> = ( | |
6 | - props, | |
7 | -) => { | |
8 | - return <>条件节点内容</>; | |
9 | -}; | |
10 | - | |
11 | -interface ConditionDisplayComponentProps extends IDisplayComponent {} | |
12 | - | |
13 | -export default memo(ConditionDisplayComponent); |
src/page/designer/nodes/loop/index.less
deleted
100644 → 0
src/page/designer/nodes/loop/index.tsx
deleted
100644 → 0
1 | -import React, { | |
2 | - useContext, | |
3 | - memo, | |
4 | - useState, | |
5 | - useEffect, | |
6 | - useImperativeHandle, | |
7 | -} from 'react'; | |
8 | -import { Checkbox, Form, Input, Radio, Space, Tooltip } from 'antd'; | |
9 | -import type { CheckboxChangeEvent, RadioChangeEvent } from 'antd/es/checkbox'; | |
10 | - | |
1 | +import React, { memo, useState, useEffect, useImperativeHandle } from 'react'; | |
2 | +import { Checkbox, Form, Radio, Space, Tooltip } from 'antd'; | |
3 | +import type { RadioChangeEvent } from 'antd'; | |
4 | +import type { CheckboxChangeEvent } from 'antd/es/checkbox'; | |
11 | 5 | import type { IConfigComponent } from '@qx/flow'; |
12 | 6 | import { QxParameterSetting } from '@qx/common'; |
13 | 7 | import { QxIcon } from '@/components'; |
14 | -import _ from 'lodash'; | |
8 | +import { isEmpty, isEqual, cloneDeep } from 'lodash-es'; | |
9 | + | |
10 | +const propagationList: { | |
11 | + value: string; | |
12 | + label: string; | |
13 | + tips: string; | |
14 | +}[] = [ | |
15 | + { | |
16 | + value: 'REQUIRED', | |
17 | + label: '需要事务', | |
18 | + tips: '如果当前存在事务,则加入该事务;如果不存在事务,则创建一个新的事务', | |
19 | + }, | |
20 | + { | |
21 | + value: 'SUPPORTS', | |
22 | + label: '支持当前事务', | |
23 | + tips: '如果当前存在事务,则加入该事务;如果不存在事务,则直接执行', | |
24 | + }, | |
25 | + { | |
26 | + value: 'REQUIRES_NEW', | |
27 | + label: '新建事务', | |
28 | + tips: '不管当前是否存在事务,必定创建一个新事务,如果当前存在事务这个事务会被挂起。新事务在层级上与之前的事务是平级的,两者互不干扰', | |
29 | + }, | |
30 | +]; | |
31 | + | |
32 | +const isolationList: { | |
33 | + value: string; | |
34 | + label: string; | |
35 | + tips: string; | |
36 | +}[] = [ | |
37 | + { | |
38 | + value: 'READ_UNCOMMITTED', | |
39 | + label: '读未提交', | |
40 | + tips: '可以读到其它事务未提交的数据', | |
41 | + }, | |
42 | + { | |
43 | + value: 'READ_COMMITTED', | |
44 | + label: '已提交读取', | |
45 | + tips: '可以读到其它事务已提交的数据', | |
46 | + }, | |
47 | + { | |
48 | + value: 'REPEATABLE_READ', | |
49 | + label: '可重复读取', | |
50 | + tips: '不会读到其它事务已提交的数据', | |
51 | + }, | |
52 | + { | |
53 | + value: 'SERIALIZABLE', | |
54 | + label: '可串行化的', | |
55 | + tips: '串行化读', | |
56 | + }, | |
57 | +]; | |
15 | 58 | |
16 | -import { isolationList, propagationList } from '../../setting-configs/start'; | |
17 | 59 | interface PropagationSettingProps { |
18 | 60 | value: string; |
19 | 61 | onChange: (val: string) => void; |
... | ... | @@ -63,29 +105,24 @@ const StartConfigComponent: React.FC<StartConfigComponentProps> = |
63 | 105 | })); |
64 | 106 | |
65 | 107 | const [values, setValues] = useState<{ |
66 | - params: any[]; | |
67 | - enablePropagation: boolean; | |
68 | - propagation: string; | |
69 | - isolation: string; | |
70 | - }>({ | |
71 | - params: [], | |
72 | - enablePropagation: false, | |
73 | - propagation: 'REQUIRED', | |
74 | - isolation: 'REPEATABLE_READ', | |
75 | - }); | |
76 | - | |
108 | + params?: any[]; | |
109 | + enablePropagation?: boolean; | |
110 | + propagation?: string; | |
111 | + isolation?: string; | |
112 | + }>(); | |
77 | 113 | useEffect(() => { |
78 | - if (_.isEmpty(props?.node?.data)) { | |
114 | + if (isEmpty(props?.node?.data)) { | |
79 | 115 | return; |
80 | 116 | } |
81 | - if (_.isEqual(props?.node?.data, values)) { | |
117 | + if (isEqual(props?.node?.data, values)) { | |
82 | 118 | return; |
83 | 119 | } |
84 | - setValues(props?.node?.data); | |
85 | - }, [props?.node?.data]); | |
120 | + setValues({ ...props?.node?.data }); | |
121 | + form.setFieldsValue({ ...props?.node?.data }); | |
122 | + }, [JSON.stringify(props?.node?.data)]); | |
86 | 123 | |
87 | 124 | const onCheckedChange = (e: CheckboxChangeEvent) => { |
88 | - const _cloneVal = _.cloneDeep(values); | |
125 | + const _cloneVal = !!values ? cloneDeep(values) : {}; | |
89 | 126 | setValues({ |
90 | 127 | ..._cloneVal, |
91 | 128 | enablePropagation: e.target.checked, |
... | ... | @@ -93,11 +130,11 @@ const StartConfigComponent: React.FC<StartConfigComponentProps> = |
93 | 130 | }; |
94 | 131 | |
95 | 132 | useEffect(() => { |
96 | - if (_.isEqual(props?.node?.data, values)) { | |
133 | + if (!values || isEqual(props?.node?.data, values)) { | |
97 | 134 | return; |
98 | 135 | } |
99 | 136 | props.onChange(values); |
100 | - }, [values]); | |
137 | + }, [JSON.stringify(values)]); | |
101 | 138 | |
102 | 139 | return ( |
103 | 140 | <Form |
... | ... | @@ -109,37 +146,55 @@ const StartConfigComponent: React.FC<StartConfigComponentProps> = |
109 | 146 | isolation: 'REPEATABLE_READ', |
110 | 147 | }} |
111 | 148 | > |
112 | - <Form.Item name="params"> | |
149 | + <Form.Item | |
150 | + style={{ | |
151 | + marginBottom: '24px', | |
152 | + }} | |
153 | + name="params" | |
154 | + > | |
113 | 155 | <h3 className={'qx-flow-form__label-title'}>入参设置</h3> |
114 | 156 | <p className={'qx-flow-form__label-tips'}> |
115 | 157 | 参数可以被后面的所有数据流节点使用 |
116 | 158 | </p> |
117 | 159 | <QxParameterSetting |
118 | - value={values.params} | |
160 | + // @ts-ignore | |
161 | + value={values?.params || []} | |
119 | 162 | onChange={(_v: any) => { |
120 | - console.log('参数 === ', _v); | |
163 | + const _cloneVal = cloneDeep(values); | |
164 | + setValues({ | |
165 | + ..._cloneVal, | |
166 | + params: _v, | |
167 | + }); | |
121 | 168 | }} |
122 | 169 | /> |
123 | 170 | </Form.Item> |
124 | - <Form.Item name="enablePropagation"> | |
171 | + <Form.Item | |
172 | + style={{ | |
173 | + marginBottom: '16px', | |
174 | + }} | |
175 | + name="enablePropagation" | |
176 | + > | |
125 | 177 | <h3 className={'qx-flow-form__label-title'}>事务控制</h3> |
126 | 178 | <Checkbox |
127 | - checked={values.enablePropagation} | |
179 | + checked={values?.enablePropagation} | |
128 | 180 | onChange={onCheckedChange} |
129 | 181 | > |
130 | 182 | 设置事务的传播行为和隔离级别 |
131 | 183 | </Checkbox> |
132 | 184 | </Form.Item> |
133 | 185 | <Form.Item |
134 | - hidden={!values.enablePropagation} | |
186 | + hidden={!values?.enablePropagation} | |
135 | 187 | label="事务传播行为" |
136 | 188 | name="propagation" |
189 | + style={{ | |
190 | + marginBottom: '16px', | |
191 | + }} | |
137 | 192 | > |
138 | 193 | <PropagationSetting |
139 | 194 | optionsList={propagationList} |
140 | - value={'REQUIRED'} | |
195 | + value={values?.propagation || 'REQUIRED'} | |
141 | 196 | onChange={(_v: string) => { |
142 | - const _cloneVal = _.cloneDeep(values); | |
197 | + const _cloneVal = cloneDeep(values); | |
143 | 198 | setValues({ |
144 | 199 | ..._cloneVal, |
145 | 200 | propagation: _v, |
... | ... | @@ -148,15 +203,15 @@ const StartConfigComponent: React.FC<StartConfigComponentProps> = |
148 | 203 | /> |
149 | 204 | </Form.Item> |
150 | 205 | <Form.Item |
151 | - hidden={!values.enablePropagation} | |
206 | + hidden={!values?.enablePropagation} | |
152 | 207 | label="事务隔离级别" |
153 | 208 | name="isolation" |
154 | 209 | > |
155 | 210 | <PropagationSetting |
156 | 211 | optionsList={isolationList} |
157 | - value={'REPEATABLE_READ'} | |
212 | + value={values?.isolation || 'REPEATABLE_READ'} | |
158 | 213 | onChange={(_v: string) => { |
159 | - const _cloneVal = _.cloneDeep(values); | |
214 | + const _cloneVal = cloneDeep(values); | |
160 | 215 | setValues({ |
161 | 216 | ..._cloneVal, |
162 | 217 | isolation: _v, | ... | ... |
1 | 1 | import React, { memo } from 'react'; |
2 | -// import { ReactComponent as Icon } from '../../public/icons/outlined.svg'; | |
2 | +import { Button, Typography } from 'antd'; | |
3 | +import { useAction } from '@qx/flow'; | |
4 | +const { Text } = Typography; | |
3 | 5 | import type { IDisplayComponent, INode } from '@qx/flow'; |
4 | -// import './index.less'; | |
6 | + | |
7 | +const paramsEnums: Record<string, string> = { | |
8 | + STRING: '文本', | |
9 | + NUMBER: '数字', | |
10 | + TIME: '日期', | |
11 | + BOOL: '布尔', | |
12 | + OBJECT: '对象', | |
13 | + ARRAY: '数组', | |
14 | + ANNEX: '附件', | |
15 | + PIC: '图片', | |
16 | + FORM: '表单', | |
17 | + USER: '人员', | |
18 | + ORG: '部门', | |
19 | +}; | |
5 | 20 | |
6 | 21 | const DisplayComponent: React.FC<DisplayComponentProps> = (props) => { |
7 | 22 | const { node, nodes } = props; |
... | ... | @@ -11,6 +26,8 @@ const DisplayComponent: React.FC<DisplayComponentProps> = (props) => { |
11 | 26 | props.onChange?.([...nodes]); |
12 | 27 | }; |
13 | 28 | |
29 | + const { clickNode } = useAction(); | |
30 | + | |
14 | 31 | return ( |
15 | 32 | <div className="qx-flow-default-node"> |
16 | 33 | <div className="qx-flow-default-node__header"> |
... | ... | @@ -21,13 +38,38 @@ const DisplayComponent: React.FC<DisplayComponentProps> = (props) => { |
21 | 38 | <span className="qx-flow-default-node__title--name">{node.name}</span> |
22 | 39 | </span> |
23 | 40 | </div> |
24 | - <div className="qx-flow-default-node__content"> | |
25 | - {!node.data ? ( | |
26 | - <span className="qx-flow-end-node__button">设置入参</span> | |
27 | - ) : ( | |
28 | - <span>节点配置内容</span> | |
29 | - )} | |
30 | - </div> | |
41 | + {!!node?.data?.params?.length ? ( | |
42 | + <> | |
43 | + <div className="qx-flow-default-node__content"> | |
44 | + {props?.node?.data?.params.map((_v: any) => { | |
45 | + return ( | |
46 | + <Text | |
47 | + style={{ | |
48 | + width: '100%', | |
49 | + lineHeight: '22px', | |
50 | + }} | |
51 | + ellipsis={{ | |
52 | + tooltip: `${paramsEnums?.[_v.type || '']} ${ | |
53 | + _v.title || '未命名' | |
54 | + }`, | |
55 | + }} | |
56 | + > | |
57 | + {paramsEnums?.[_v.type || '']} {_v.title || '未命名'} | |
58 | + </Text> | |
59 | + ); | |
60 | + })} | |
61 | + </div> | |
62 | + </> | |
63 | + ) : ( | |
64 | + <Button | |
65 | + style={{ marginTop: 8 }} | |
66 | + type="link" | |
67 | + size="small" | |
68 | + // onClick={() => clickNode()} | |
69 | + > | |
70 | + 设置入参 | |
71 | + </Button> | |
72 | + )} | |
31 | 73 | </div> |
32 | 74 | ); |
33 | 75 | }; | ... | ... |
... | ... | @@ -9,8 +9,9 @@ import { QxIcon } from '@/components'; |
9 | 9 | import { isEmpty } from 'lodash-es'; |
10 | 10 | import { handleWindowOpen } from '@qx/utils'; |
11 | 11 | // import {} from '@/src/services/data-flow'; |
12 | -import { getIcon, useFlowTableScrollY } from '@/utils'; | |
12 | +import { getIcon } from '@/utils'; | |
13 | 13 | import { useDebounceEffect } from 'ahooks'; |
14 | +import { useFlowTableScrollY } from '@/hooks'; | |
14 | 15 | |
15 | 16 | const { Text } = Typography; |
16 | 17 | ... | ... |
... | ... | @@ -16,7 +16,8 @@ import { useDebounceEffect, useDebounceFn } from 'ahooks'; |
16 | 16 | import { isEmpty, cloneDeep } from 'lodash-es'; |
17 | 17 | |
18 | 18 | import { FlowSettingProps } from '@/page/view/constant'; |
19 | -import { getIcon, useFlowTableScrollY } from '@/utils'; | |
19 | +import { getIcon } from '@/utils'; | |
20 | +import { useFlowTableScrollY } from '@/hooks'; | |
20 | 21 | import actions from '@/utils/actions'; |
21 | 22 | |
22 | 23 | import { copyProcessById, deleteProcessById, getListProcess } from '@/services'; | ... | ... |
1 | 1 | import React from 'react'; |
2 | 2 | // import { history } from '@@/core/history'; |
3 | -import { useSearchParams } from 'react-router-dom'; | |
3 | +import { useSearchParams } from '@/hooks'; | |
4 | 4 | import { useTitle } from 'ahooks'; |
5 | 5 | // @ts-ignore; |
6 | 6 | import { handleWindowOpen } from '@qx/utils'; |
... | ... | @@ -13,16 +13,12 @@ import styles from '@/page/view/index.module.less'; |
13 | 13 | const prefix = 'qx-data-flow'; |
14 | 14 | |
15 | 15 | const DataFlowView: React.FC = ({}) => { |
16 | - const [searchParams] = useSearchParams(); | |
16 | + const [query] = useSearchParams<any>(); | |
17 | 17 | const { |
18 | 18 | appId, // 应用id |
19 | 19 | funCode, // 表单id |
20 | 20 | returnUrl, // 来自页面跳转返回可跳转 |
21 | - } = { | |
22 | - appId: searchParams.get('appId'), | |
23 | - funCode: searchParams.get('funCode'), | |
24 | - returnUrl: searchParams.get('returnUrl'), | |
25 | - }; | |
21 | + } = query; | |
26 | 22 | |
27 | 23 | // 添加标题 |
28 | 24 | if (!!appId && !funCode) { | ... | ... |
... | ... | @@ -44,94 +44,3 @@ export const getIcon = (icon: string, type?: string) => { |
44 | 44 | ); |
45 | 45 | } |
46 | 46 | }; |
47 | - | |
48 | -// 表格 Scroll 高度计算 | |
49 | -export const useFlowTableScrollY = ( | |
50 | - deps: { | |
51 | - columns: any[]; | |
52 | - size?: 'small' | 'middle' | 'default'; | |
53 | - tableBoxClassName?: string; | |
54 | - classNames?: string[]; // 表格DOM内嵌元素 列名 添加在此, | |
55 | - hasPagination?: boolean; | |
56 | - listProps?: any; | |
57 | - } = { | |
58 | - size: 'small', | |
59 | - tableBoxClassName: '', | |
60 | - classNames: [], | |
61 | - hasPagination: false, | |
62 | - columns: [], | |
63 | - listProps: {}, | |
64 | - }, | |
65 | -) => { | |
66 | - const itemHeaderHeight = | |
67 | - (deps?.size === 'middle' ? 48 : deps?.size === 'default' ? 56 : 40) + 1; | |
68 | - const TABLE_VIEW_LIST = deps?.tableBoxClassName || 'qx-data-flow-table'; | |
69 | - let tableHeader = itemHeaderHeight; | |
70 | - const tableViewListDefaultHeight = 400; | |
71 | - const defaultPagePadding = 0; | |
72 | - | |
73 | - const $ = (selectors: string) => | |
74 | - document.querySelector<HTMLElement>(selectors); | |
75 | - | |
76 | - const defaultScrollY = useMemo( | |
77 | - () => document.body.clientHeight, | |
78 | - [tableHeader], | |
79 | - ); | |
80 | - | |
81 | - const [scrollY, setScrollY] = useState<number>(defaultScrollY ?? 200); | |
82 | - | |
83 | - const timer = useRef<NodeJS.Timer>(); | |
84 | - | |
85 | - const getScrollY = () => { | |
86 | - const tableViewList = $(`.${TABLE_VIEW_LIST}`); | |
87 | - | |
88 | - const tableViewListClientHeight = | |
89 | - tableViewList?.clientHeight || tableViewListDefaultHeight; | |
90 | - // 分页大小 目前已经固定 所以直接用56px | |
91 | - const antPaginationHeight = deps?.hasPagination ? 56 : 0; | |
92 | - | |
93 | - const _domHeightByClassName = (deps?.classNames || []).map( | |
94 | - (_v: string) => $(`.${_v}`)?.clientHeight ?? 0, | |
95 | - ); | |
96 | - let result = | |
97 | - tableViewListClientHeight - | |
98 | - tableHeader - | |
99 | - defaultPagePadding - | |
100 | - antPaginationHeight; | |
101 | - if (!!_domHeightByClassName?.length) { | |
102 | - result = result - eval(_domHeightByClassName.join('+')); | |
103 | - } | |
104 | - | |
105 | - if (tableViewList) { | |
106 | - tableViewList.style.overflowY = result < 200 ? 'auto' : 'hidden'; | |
107 | - } | |
108 | - | |
109 | - setScrollY(result < 100 ? 100 : result); | |
110 | - }; | |
111 | - | |
112 | - const observer = () => { | |
113 | - window.addEventListener('resize', getScrollY); | |
114 | - }; | |
115 | - | |
116 | - const removeObserver = () => { | |
117 | - if (timer.current) window.clearTimeout(timer.current); | |
118 | - window.removeEventListener('resize', getScrollY); | |
119 | - }; | |
120 | - | |
121 | - useEffect(() => { | |
122 | - observer(); | |
123 | - return () => { | |
124 | - removeObserver(); | |
125 | - }; | |
126 | - }, [tableHeader]); | |
127 | - | |
128 | - useEffect(() => { | |
129 | - if (deps) { | |
130 | - timer.current = setTimeout(() => { | |
131 | - getScrollY(); | |
132 | - }, 100); | |
133 | - } | |
134 | - }, [JSON.stringify(deps)]); | |
135 | - | |
136 | - return [scrollY, getScrollY]; | |
137 | -}; | ... | ... |
... | ... | @@ -11,14 +11,13 @@ import { |
11 | 11 | Avatar, |
12 | 12 | } from 'antd'; |
13 | 13 | |
14 | -import { SettingOutlined } from '@ant-design/icons/lib'; | |
15 | -import { useSearchParams } from 'react-router-dom'; | |
14 | +import { useSearchParams } from '@/hooks'; | |
16 | 15 | import { useTitle } from 'ahooks'; |
17 | 16 | import { QxIcon } from '@/components'; |
18 | 17 | import { handleWindowOpen } from '@qx/utils'; |
19 | 18 | import { FlowHeader, FlowVersion } from '@/components'; |
20 | 19 | |
21 | -import { useFlowTableScrollY } from '@/utils'; | |
20 | +import { useFlowTableScrollY } from '@/hooks'; | |
22 | 21 | import actions from '@/utils/actions'; |
23 | 22 | |
24 | 23 | import { isEmpty, cloneDeep } from 'lodash-es'; |
... | ... | @@ -33,17 +32,12 @@ import { FlowVersionStatusEnums } from '@/interface'; |
33 | 32 | const prefix = 'qx-flow-setting'; |
34 | 33 | |
35 | 34 | const DataFlowVersion: React.FC = ({}) => { |
36 | - // @ts-ignore | |
37 | - const [searchParams] = useSearchParams(); | |
35 | + const [query] = useSearchParams<any>(); | |
38 | 36 | const { |
39 | 37 | processId, // 流程ID |
40 | 38 | name, // 流程名称 |
41 | 39 | returnUrl, // 来自页面跳转返回可跳转 |
42 | - } = { | |
43 | - processId: searchParams.get('processId'), | |
44 | - name: searchParams.get('name'), | |
45 | - returnUrl: searchParams.get('returnUrl'), | |
46 | - }; | |
40 | + } = query; | |
47 | 41 | const [pageData, setPageData] = useState<any[]>([]); |
48 | 42 | const [tableLoading, setTableLoading] = useState<boolean>(true); // 表格loading |
49 | 43 | // 表格是否添加scroll 属性 | ... | ... |
src/public/imgs/default_cover.png
0 → 100644
4.11 KB
1 | 1 | import { createHashRouter, RouterProvider } from 'react-router-dom'; |
2 | 2 | import Root from '../page/root'; |
3 | -import About from '../page/about'; | |
4 | -import Designer from '../page/designer'; | |
5 | -import List from '../page/view/list'; | |
6 | -import Version from '../page/view/version'; | |
3 | +import lazyComponent from '@/components/lazy-component'; | |
7 | 4 | |
8 | 5 | export default () => ( |
9 | 6 | <RouterProvider |
... | ... | @@ -14,19 +11,27 @@ export default () => ( |
14 | 11 | children: [ |
15 | 12 | { |
16 | 13 | path: '/about', |
17 | - element: <About />, | |
14 | + element: lazyComponent( | |
15 | + () => import(/*qx-dataflow-about*/ '@/page/about'), | |
16 | + ), | |
18 | 17 | }, |
19 | 18 | { |
20 | 19 | path: '/designer', |
21 | - element: <Designer />, | |
20 | + element: lazyComponent( | |
21 | + () => import(/*qx-dataflow-designer*/ '@/page/designer'), | |
22 | + ), | |
22 | 23 | }, |
23 | 24 | { |
24 | 25 | path: '/list', |
25 | - element: <List />, | |
26 | + element: lazyComponent( | |
27 | + () => import(/*qx-dataflow-list*/ '@/page/view/list'), | |
28 | + ), | |
26 | 29 | }, |
27 | 30 | { |
28 | 31 | path: '/version', |
29 | - element: <Version />, | |
32 | + element: lazyComponent( | |
33 | + () => import(/*qx-dataflow-version*/ '@/page/view/version'), | |
34 | + ), | |
30 | 35 | }, |
31 | 36 | ], |
32 | 37 | }, | ... | ... |
... | ... | @@ -4,6 +4,7 @@ import request from '@/request'; |
4 | 4 | const qxSdk = new QxSdk(); |
5 | 5 | |
6 | 6 | qxSdk.registerSdk({ |
7 | + // @ts-ignore | |
7 | 8 | getFormFields(appCode: string, funCode: string, viewCode: string) { |
8 | 9 | return request.get( |
9 | 10 | `/qx-apaas-lowcode/app/${appCode}/form/${funCode}/field/option/${viewCode}?withRel=true`, | ... | ... |
1 | -import React, { useEffect, useMemo, useRef, useState } from 'react'; | |
2 | - | |
3 | -import { Button, Image, message, Modal, Tooltip, Upload } from 'antd'; | |
1 | +import { Image, Skeleton } from 'antd'; | |
4 | 2 | import { QxIcon } from '@/components'; |
5 | 3 | |
6 | -import defaultImg from '@/components/default/default_cover.png'; | |
4 | +import defaultImg from '@/public/imgs/default_cover.png'; | |
7 | 5 | |
8 | 6 | const defaultIcon: Record<string, string> = { |
9 | 7 | form: 'icon-app-file-fill', |
... | ... | @@ -44,94 +42,3 @@ export const getIcon = (icon: string, type?: string) => { |
44 | 42 | ); |
45 | 43 | } |
46 | 44 | }; |
47 | - | |
48 | -// 表格 Scroll 高度计算 | |
49 | -export const useFlowTableScrollY = ( | |
50 | - deps: { | |
51 | - columns: any[]; | |
52 | - size?: 'small' | 'middle' | 'default'; | |
53 | - tableBoxClassName?: string; | |
54 | - classNames?: string[]; // 表格DOM内嵌元素 列名 添加在此, | |
55 | - hasPagination?: boolean; | |
56 | - listProps?: any; | |
57 | - } = { | |
58 | - size: 'small', | |
59 | - tableBoxClassName: '', | |
60 | - classNames: [], | |
61 | - hasPagination: false, | |
62 | - columns: [], | |
63 | - listProps: {}, | |
64 | - }, | |
65 | -) => { | |
66 | - const itemHeaderHeight = | |
67 | - (deps?.size === 'middle' ? 48 : deps?.size === 'default' ? 56 : 40) + 1; | |
68 | - const TABLE_VIEW_LIST = deps?.tableBoxClassName || 'qx-data-flow-table'; | |
69 | - let tableHeader = itemHeaderHeight; | |
70 | - const tableViewListDefaultHeight = 400; | |
71 | - const defaultPagePadding = 0; | |
72 | - | |
73 | - const $ = (selectors: string) => | |
74 | - document.querySelector<HTMLElement>(selectors); | |
75 | - | |
76 | - const defaultScrollY = useMemo( | |
77 | - () => document.body.clientHeight, | |
78 | - [tableHeader], | |
79 | - ); | |
80 | - | |
81 | - const [scrollY, setScrollY] = useState<number>(defaultScrollY ?? 200); | |
82 | - | |
83 | - const timer = useRef<NodeJS.Timer>(); | |
84 | - | |
85 | - const getScrollY = () => { | |
86 | - const tableViewList = $(`.${TABLE_VIEW_LIST}`); | |
87 | - | |
88 | - const tableViewListClientHeight = | |
89 | - tableViewList?.clientHeight || tableViewListDefaultHeight; | |
90 | - // 分页大小 目前已经固定 所以直接用56px | |
91 | - const antPaginationHeight = deps?.hasPagination ? 56 : 0; | |
92 | - | |
93 | - const _domHeightByClassName = (deps?.classNames || []).map( | |
94 | - (_v: string) => $(`.${_v}`)?.clientHeight ?? 0, | |
95 | - ); | |
96 | - let result = | |
97 | - tableViewListClientHeight - | |
98 | - tableHeader - | |
99 | - defaultPagePadding - | |
100 | - antPaginationHeight; | |
101 | - if (!!_domHeightByClassName?.length) { | |
102 | - result = result - eval(_domHeightByClassName.join('+')); | |
103 | - } | |
104 | - | |
105 | - if (tableViewList) { | |
106 | - tableViewList.style.overflowY = result < 200 ? 'auto' : 'hidden'; | |
107 | - } | |
108 | - | |
109 | - setScrollY(result < 100 ? 100 : result); | |
110 | - }; | |
111 | - | |
112 | - const observer = () => { | |
113 | - window.addEventListener('resize', getScrollY); | |
114 | - }; | |
115 | - | |
116 | - const removeObserver = () => { | |
117 | - if (timer.current) window.clearTimeout(timer.current); | |
118 | - window.removeEventListener('resize', getScrollY); | |
119 | - }; | |
120 | - | |
121 | - useEffect(() => { | |
122 | - observer(); | |
123 | - return () => { | |
124 | - removeObserver(); | |
125 | - }; | |
126 | - }, [tableHeader]); | |
127 | - | |
128 | - useEffect(() => { | |
129 | - if (deps) { | |
130 | - timer.current = setTimeout(() => { | |
131 | - getScrollY(); | |
132 | - }, 100); | |
133 | - } | |
134 | - }, [JSON.stringify(deps)]); | |
135 | - | |
136 | - return [scrollY, getScrollY]; | |
137 | -}; | ... | ... |