Showing
30 changed files
with
403 additions
and
392 deletions
@@ -7,14 +7,16 @@ const cwd = process.cwd(); | @@ -7,14 +7,16 @@ const cwd = process.cwd(); | ||
7 | 7 | ||
8 | module.exports = { | 8 | module.exports = { |
9 | output: { | 9 | output: { |
10 | - filename: 'index.js', | 10 | + filename: 'qx-[name]-[contenthash].bundle.js', |
11 | libraryTarget: 'umd', | 11 | libraryTarget: 'umd', |
12 | + clean: true, | ||
12 | }, | 13 | }, |
13 | entry: path.resolve(cwd, './src/index.tsx'), | 14 | entry: path.resolve(cwd, './src/index.tsx'), |
14 | module: { | 15 | module: { |
15 | rules: [ | 16 | rules: [ |
16 | { | 17 | { |
17 | test: /\.(js|jsx)$/, | 18 | test: /\.(js|jsx)$/, |
19 | + exclude: /node_modules/, | ||
18 | use: { | 20 | use: { |
19 | loader: 'babel-loader', | 21 | loader: 'babel-loader', |
20 | options: { | 22 | options: { |
@@ -29,14 +31,23 @@ module.exports = { | @@ -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 | use: { | 35 | use: { |
34 | loader: 'file-loader', | 36 | loader: 'file-loader', |
35 | }, | 37 | }, |
36 | }, | 38 | }, |
37 | { | 39 | { |
38 | test: /\.less$/i, | 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 | test: /\.svg$/, | 53 | test: /\.svg$/, |
@@ -24,6 +24,7 @@ | @@ -24,6 +24,7 @@ | ||
24 | "license": "ISC", | 24 | "license": "ISC", |
25 | "dependencies": { | 25 | "dependencies": { |
26 | "@ant-design/icons": "^5.2.5", | 26 | "@ant-design/icons": "^5.2.5", |
27 | + "@qx/common": "0.2.31-alpha.5", | ||
27 | "@qx/flow": "1.0.0-alpha.10", | 28 | "@qx/flow": "1.0.0-alpha.10", |
28 | "@qx/icon-btn": "^0.0.13", | 29 | "@qx/icon-btn": "^0.0.13", |
29 | "@qx/ui": "0.0.3-beta.1", | 30 | "@qx/ui": "0.0.3-beta.1", |
src/components/dynamic-component/index.tsx
deleted
100644 → 0
@@ -26,6 +26,7 @@ const FlowVersion: React.FC<FlowVersionProps> = (props) => { | @@ -26,6 +26,7 @@ const FlowVersion: React.FC<FlowVersionProps> = (props) => { | ||
26 | return ( | 26 | return ( |
27 | <> | 27 | <> |
28 | {versionText || | 28 | {versionText || |
29 | + // @ts-ignore | ||
29 | (statusEnums || FlowStatusEnums)[status || 'UNPUBLISHED'] ? ( | 30 | (statusEnums || FlowStatusEnums)[status || 'UNPUBLISHED'] ? ( |
30 | <div | 31 | <div |
31 | className={cls( | 32 | className={cls( |
@@ -51,6 +52,7 @@ const FlowVersion: React.FC<FlowVersionProps> = (props) => { | @@ -51,6 +52,7 @@ const FlowVersion: React.FC<FlowVersionProps> = (props) => { | ||
51 | > | 52 | > |
52 | {!!versionText ? <span>V {versionText}</span> : null} | 53 | {!!versionText ? <span>V {versionText}</span> : null} |
53 | {!!status ? ( | 54 | {!!status ? ( |
55 | + // @ts-ignore | ||
54 | <span>{(statusEnums || FlowStatusEnums)[status]}</span> | 56 | <span>{(statusEnums || FlowStatusEnums)[status]}</span> |
55 | ) : null} | 57 | ) : null} |
56 | </div> | 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,6 +62,7 @@ const NameDescriptionSetting: React.FC<NameDescriptionSettingProps> = ( | ||
62 | if (_.isEmpty(values)) { | 62 | if (_.isEmpty(values)) { |
63 | form.resetFields(); | 63 | form.resetFields(); |
64 | } else { | 64 | } else { |
65 | + // @ts-ignore | ||
65 | form.setValues(values); | 66 | form.setValues(values); |
66 | } | 67 | } |
67 | }, 100); | 68 | }, 100); |
@@ -114,6 +115,7 @@ const NameDescriptionSetting: React.FC<NameDescriptionSettingProps> = ( | @@ -114,6 +115,7 @@ const NameDescriptionSetting: React.FC<NameDescriptionSettingProps> = ( | ||
114 | form={form} | 115 | form={form} |
115 | schema={FORM_SCHEMA} | 116 | schema={FORM_SCHEMA} |
116 | onMount={() => {}} | 117 | onMount={() => {}} |
118 | + // @ts-ignore | ||
117 | onFinish={onFinish} | 119 | onFinish={onFinish} |
118 | watch={{}} | 120 | watch={{}} |
119 | /> | 121 | /> |
@@ -2,12 +2,13 @@ import React, { memo, useContext, useEffect, useState } from 'react'; | @@ -2,12 +2,13 @@ import React, { memo, useContext, useEffect, useState } from 'react'; | ||
2 | import { BuilderContext } from '@qx/flow'; | 2 | import { BuilderContext } from '@qx/flow'; |
3 | import { Drawer, Spin, Tabs } from 'antd'; | 3 | import { Drawer, Spin, Tabs } from 'antd'; |
4 | import NodeList, { NodeItemsProps } from './components/node-list'; | 4 | import NodeList, { NodeItemsProps } from './components/node-list'; |
5 | -import { useLocation, useSearchParams } from 'react-router-dom'; | 5 | +import { useSearchParams } from '@/hooks'; |
6 | import { getListGroupNode } from '@/services'; | 6 | import { getListGroupNode } from '@/services'; |
7 | import { QxIcon } from '@/components'; | 7 | import { QxIcon } from '@/components'; |
8 | import { ReactSortable } from 'react-sortablejs'; | 8 | import { ReactSortable } from 'react-sortablejs'; |
9 | import { cloneDeep } from 'lodash-es'; | 9 | import { cloneDeep } from 'lodash-es'; |
10 | import { v4 as uuid } from 'uuid'; | 10 | import { v4 as uuid } from 'uuid'; |
11 | +// @ts-ignore | ||
11 | import type { INodePanelProps } from '@qx/flow'; | 12 | import type { INodePanelProps } from '@qx/flow'; |
12 | import Empty from './img/empty.png'; | 13 | import Empty from './img/empty.png'; |
13 | 14 | ||
@@ -31,10 +32,10 @@ const panelTabs = [ | @@ -31,10 +32,10 @@ const panelTabs = [ | ||
31 | ]; | 32 | ]; |
32 | 33 | ||
33 | const NodePanel: React.FC<NodePanelProps> = (props) => { | 34 | const NodePanel: React.FC<NodePanelProps> = (props) => { |
34 | - const { visible, onClose } = props; | ||
35 | // @ts-ignore | 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 | const { registerNodes } = useContext(BuilderContext); | 39 | const { registerNodes } = useContext(BuilderContext); |
39 | const [loading, setLoading] = useState(false); | 40 | const [loading, setLoading] = useState(false); |
40 | const [activeKey, setActiveKey] = useState('SYSTEM'); | 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,7 +17,7 @@ import { Start, End } from './nodes'; | ||
17 | import { NodeTypes, ProcessItemProps, FlowStatusEnums } from '@/interface'; | 17 | import { NodeTypes, ProcessItemProps, FlowStatusEnums } from '@/interface'; |
18 | import { handleWindowOpen } from '@qx/utils'; | 18 | import { handleWindowOpen } from '@qx/utils'; |
19 | // import { history } from '@@/core/history'; | 19 | // import { history } from '@@/core/history'; |
20 | -import { useLocation, useSearchParams } from 'react-router-dom'; | 20 | +import { useLocation } from 'react-router-dom'; |
21 | import { useTitle } from 'ahooks'; | 21 | import { useTitle } from 'ahooks'; |
22 | // 头部相关 | 22 | // 头部相关 |
23 | import { | 23 | import { |
@@ -31,6 +31,7 @@ import cls from 'classnames'; | @@ -31,6 +31,7 @@ import cls from 'classnames'; | ||
31 | import styles from '@/components/header/index.module.less'; | 31 | import styles from '@/components/header/index.module.less'; |
32 | import { getIcon } from '@/utils'; | 32 | import { getIcon } from '@/utils'; |
33 | import { QxIcon } from '@/components'; | 33 | import { QxIcon } from '@/components'; |
34 | +import { useSearchParams } from '@/hooks'; | ||
34 | import { | 35 | import { |
35 | getProcessDetailsById, | 36 | getProcessDetailsById, |
36 | publishProcessById, | 37 | publishProcessById, |
@@ -71,8 +72,7 @@ const systemNodes: IRegisterNode[] = [ | @@ -71,8 +72,7 @@ const systemNodes: IRegisterNode[] = [ | ||
71 | export default () => { | 72 | export default () => { |
72 | const [nodes, setNodes] = useState<INode[]>([]); | 73 | const [nodes, setNodes] = useState<INode[]>([]); |
73 | const [remoteNodes, setRemoteNodes] = useState<IRegisterRemoteNode[]>([]); | 74 | const [remoteNodes, setRemoteNodes] = useState<IRegisterRemoteNode[]>([]); |
74 | - // @ts-ignore | ||
75 | - const [searchParams] = useSearchParams(); | 75 | + const [query, setQuery] = useSearchParams<any>(); |
76 | const [showEditTitle, setShowEditTitle] = useState(false); | 76 | const [showEditTitle, setShowEditTitle] = useState(false); |
77 | const { | 77 | const { |
78 | appId, // 应用id | 78 | appId, // 应用id |
@@ -80,13 +80,7 @@ export default () => { | @@ -80,13 +80,7 @@ export default () => { | ||
80 | returnUrl, // 来自页面跳转返回可跳转 | 80 | returnUrl, // 来自页面跳转返回可跳转 |
81 | processId, // 流程Id preview | 81 | processId, // 流程Id preview |
82 | type, // 流程类型 edit 编辑 preview 预览 | 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 | const [processDetails, setProcessDetails] = useState<ProcessItemProps>({ | 85 | const [processDetails, setProcessDetails] = useState<ProcessItemProps>({ |
92 | id: '', | 86 | id: '', |
@@ -116,6 +110,7 @@ export default () => { | @@ -116,6 +110,7 @@ export default () => { | ||
116 | .catch((err: { msg?: string }) => { | 110 | .catch((err: { msg?: string }) => { |
117 | message.warning(err?.msg || '流程详情数据请求失败', 5); | 111 | message.warning(err?.msg || '流程详情数据请求失败', 5); |
118 | setProcessDetails( | 112 | setProcessDetails( |
113 | + // @ts-ignore | ||
119 | _data || { | 114 | _data || { |
120 | id: _id, | 115 | id: _id, |
121 | name: '未命名流程', | 116 | name: '未命名流程', |
@@ -198,7 +193,7 @@ export default () => { | @@ -198,7 +193,7 @@ export default () => { | ||
198 | // 发布流程 | 193 | // 发布流程 |
199 | // TODO 要先校验是否保存 才能发布 | 194 | // TODO 要先校验是否保存 才能发布 |
200 | publishProcessById(processDetails.id || '') | 195 | publishProcessById(processDetails.id || '') |
201 | - .then((res) => { | 196 | + .then((res: any) => { |
202 | console.log('res ====', res); | 197 | console.log('res ====', res); |
203 | }) | 198 | }) |
204 | .catch((err: { msg?: string }) => { | 199 | .catch((err: { msg?: string }) => { |
@@ -237,11 +232,8 @@ export default () => { | @@ -237,11 +232,8 @@ export default () => { | ||
237 | remark: data.remark, | 232 | remark: data.remark, |
238 | }); | 233 | }); |
239 | if (!processDetails?.id) { | 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,6 +381,7 @@ export default () => { | ||
389 | useEffect(() => { | 381 | useEffect(() => { |
390 | let _data: ProcessItemProps = {}; | 382 | let _data: ProcessItemProps = {}; |
391 | _data.name = '未命名流程'; | 383 | _data.name = '未命名流程'; |
384 | + // @ts-ignore | ||
392 | _data.appId = appId; | 385 | _data.appId = appId; |
393 | if (!!funCode) { | 386 | if (!!funCode) { |
394 | _data.funCode = funCode; | 387 | _data.funCode = funCode; |
@@ -416,6 +409,7 @@ export default () => { | @@ -416,6 +409,7 @@ export default () => { | ||
416 | defaultTools: INode[], | 409 | defaultTools: INode[], |
417 | actions: any, | 410 | actions: any, |
418 | ) => { | 411 | ) => { |
412 | + console.log('nodes', nodes); | ||
419 | const { copyNodeAndChildren } = actions; | 413 | const { copyNodeAndChildren } = actions; |
420 | switch (node.type) { | 414 | switch (node.type) { |
421 | case 'condition': | 415 | case 'condition': |
@@ -452,6 +446,7 @@ export default () => { | @@ -452,6 +446,7 @@ export default () => { | ||
452 | registerNodes={systemNodes} | 446 | registerNodes={systemNodes} |
453 | historyTool | 447 | historyTool |
454 | zoomTool | 448 | zoomTool |
449 | + // @ts-ignore | ||
455 | expandAllTool | 450 | expandAllTool |
456 | DrawerComponent={Drawer} | 451 | DrawerComponent={Drawer} |
457 | PopoverComponent={Popover} | 452 | PopoverComponent={Popover} |
@@ -463,6 +458,7 @@ export default () => { | @@ -463,6 +458,7 @@ export default () => { | ||
463 | registerRemoteNodes={remoteNodes} | 458 | registerRemoteNodes={remoteNodes} |
464 | ConfigDrawerContainer={ConfigDrawer} | 459 | ConfigDrawerContainer={ConfigDrawer} |
465 | NodePanel={NodesPanel} | 460 | NodePanel={NodesPanel} |
461 | + // @ts-ignore | ||
466 | getNodeTool={getNodeTool} | 462 | getNodeTool={getNodeTool} |
467 | /> | 463 | /> |
468 | <NameDescriptionSetting cRef={formModalRef} handleClick={handleClick} /> | 464 | <NameDescriptionSetting cRef={formModalRef} handleClick={handleClick} /> |
1 | import React, { useContext, memo, useImperativeHandle } from 'react'; | 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 | import styles from './index.less'; | 5 | import styles from './index.less'; |
6 | import type { IConfigComponent } from '@qx/flow'; | 6 | import type { IConfigComponent } from '@qx/flow'; |
7 | 7 | ||
8 | const StartConfigComponent = React.forwardRef<any, StartConfigComponentProps>( | 8 | const StartConfigComponent = React.forwardRef<any, StartConfigComponentProps>( |
9 | (props, ref) => { | 9 | (props, ref) => { |
10 | - const form = useForm(); | 10 | + // const form = useForm(); |
11 | 11 | ||
12 | const handleValuesChange = (values: any) => { | 12 | const handleValuesChange = (values: any) => { |
13 | props?.onChange(values); | 13 | props?.onChange(values); |
14 | }; | 14 | }; |
15 | 15 | ||
16 | useImperativeHandle(ref, () => ({ | 16 | useImperativeHandle(ref, () => ({ |
17 | - validateFields: form.validateFields, | 17 | + // validateFields: form.validateFields, |
18 | })); | 18 | })); |
19 | 19 | ||
20 | return ( | 20 | return ( |
21 | <div className={styles['qx-flow-single-records-config']}> | 21 | <div className={styles['qx-flow-single-records-config']}> |
22 | - <QxFormRender | 22 | + {/* <QxFormRender |
23 | form={form} | 23 | form={form} |
24 | schema={conditionSetting} | 24 | schema={conditionSetting} |
25 | widgets={{}} | 25 | widgets={{}} |
26 | watch={{}} | 26 | watch={{}} |
27 | onValuesChange={handleValuesChange} | 27 | onValuesChange={handleValuesChange} |
28 | - /> | 28 | + /> */} |
29 | </div> | 29 | </div> |
30 | ); | 30 | ); |
31 | }, | 31 | }, |
1 | import React, { useContext, memo } from 'react'; | 1 | import React, { useContext, memo } from 'react'; |
2 | -import { useForm } from '@qx/form-render'; | 2 | +// import { useForm } from '@qx/form-render'; |
3 | import { useDrawer } from '@qx/flow'; | 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 | import styles from './index.less'; | 7 | import styles from './index.less'; |
8 | import type { IConfigComponent } from '@qx/flow'; | 8 | import type { IConfigComponent } from '@qx/flow'; |
9 | 9 | ||
10 | const EndConfigComponent: React.FC<EndConfigComponentProps> = (props) => { | 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 | interface EndConfigComponentProps extends IConfigComponent {} | 16 | interface EndConfigComponentProps extends IConfigComponent {} |
1 | import React, { memo } from 'react'; | 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 | import type { IDisplayComponent, INode } from '@qx/flow'; | 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 | const DisplayComponent: React.FC<DisplayComponentProps> = (props) => { | 21 | const DisplayComponent: React.FC<DisplayComponentProps> = (props) => { |
7 | const { node, nodes } = props; | 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 | return ( | 31 | return ( |
10 | <div className="qx-flow-default-node"> | 32 | <div className="qx-flow-default-node"> |
11 | <div className="qx-flow-default-node__header"> | 33 | <div className="qx-flow-default-node__header"> |
@@ -16,13 +38,38 @@ const DisplayComponent: React.FC<DisplayComponentProps> = (props) => { | @@ -16,13 +38,38 @@ const DisplayComponent: React.FC<DisplayComponentProps> = (props) => { | ||
16 | <span className="qx-flow-default-node__title--name">{node.name}</span> | 38 | <span className="qx-flow-default-node__title--name">{node.name}</span> |
17 | </span> | 39 | </span> |
18 | </div> | 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 | </div> | 73 | </div> |
27 | ); | 74 | ); |
28 | }; | 75 | }; |
1 | export { default as Start } from './start'; | 1 | export { default as Start } from './start'; |
2 | export { default as End } from './end'; | 2 | export { default as End } from './end'; |
3 | // export { default as Condition } from './condition'; | 3 | // export { default as Condition } from './condition'; |
4 | -export { default as Loop } from './loop'; |
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 | import type { IConfigComponent } from '@qx/flow'; | 5 | import type { IConfigComponent } from '@qx/flow'; |
12 | import { QxParameterSetting } from '@qx/common'; | 6 | import { QxParameterSetting } from '@qx/common'; |
13 | import { QxIcon } from '@/components'; | 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 | interface PropagationSettingProps { | 59 | interface PropagationSettingProps { |
18 | value: string; | 60 | value: string; |
19 | onChange: (val: string) => void; | 61 | onChange: (val: string) => void; |
@@ -63,29 +105,24 @@ const StartConfigComponent: React.FC<StartConfigComponentProps> = | @@ -63,29 +105,24 @@ const StartConfigComponent: React.FC<StartConfigComponentProps> = | ||
63 | })); | 105 | })); |
64 | 106 | ||
65 | const [values, setValues] = useState<{ | 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 | useEffect(() => { | 113 | useEffect(() => { |
78 | - if (_.isEmpty(props?.node?.data)) { | 114 | + if (isEmpty(props?.node?.data)) { |
79 | return; | 115 | return; |
80 | } | 116 | } |
81 | - if (_.isEqual(props?.node?.data, values)) { | 117 | + if (isEqual(props?.node?.data, values)) { |
82 | return; | 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 | const onCheckedChange = (e: CheckboxChangeEvent) => { | 124 | const onCheckedChange = (e: CheckboxChangeEvent) => { |
88 | - const _cloneVal = _.cloneDeep(values); | 125 | + const _cloneVal = !!values ? cloneDeep(values) : {}; |
89 | setValues({ | 126 | setValues({ |
90 | ..._cloneVal, | 127 | ..._cloneVal, |
91 | enablePropagation: e.target.checked, | 128 | enablePropagation: e.target.checked, |
@@ -93,11 +130,11 @@ const StartConfigComponent: React.FC<StartConfigComponentProps> = | @@ -93,11 +130,11 @@ const StartConfigComponent: React.FC<StartConfigComponentProps> = | ||
93 | }; | 130 | }; |
94 | 131 | ||
95 | useEffect(() => { | 132 | useEffect(() => { |
96 | - if (_.isEqual(props?.node?.data, values)) { | 133 | + if (!values || isEqual(props?.node?.data, values)) { |
97 | return; | 134 | return; |
98 | } | 135 | } |
99 | props.onChange(values); | 136 | props.onChange(values); |
100 | - }, [values]); | 137 | + }, [JSON.stringify(values)]); |
101 | 138 | ||
102 | return ( | 139 | return ( |
103 | <Form | 140 | <Form |
@@ -109,37 +146,55 @@ const StartConfigComponent: React.FC<StartConfigComponentProps> = | @@ -109,37 +146,55 @@ const StartConfigComponent: React.FC<StartConfigComponentProps> = | ||
109 | isolation: 'REPEATABLE_READ', | 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 | <h3 className={'qx-flow-form__label-title'}>入参设置</h3> | 155 | <h3 className={'qx-flow-form__label-title'}>入参设置</h3> |
114 | <p className={'qx-flow-form__label-tips'}> | 156 | <p className={'qx-flow-form__label-tips'}> |
115 | 参数可以被后面的所有数据流节点使用 | 157 | 参数可以被后面的所有数据流节点使用 |
116 | </p> | 158 | </p> |
117 | <QxParameterSetting | 159 | <QxParameterSetting |
118 | - value={values.params} | 160 | + // @ts-ignore |
161 | + value={values?.params || []} | ||
119 | onChange={(_v: any) => { | 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 | </Form.Item> | 170 | </Form.Item> |
124 | - <Form.Item name="enablePropagation"> | 171 | + <Form.Item |
172 | + style={{ | ||
173 | + marginBottom: '16px', | ||
174 | + }} | ||
175 | + name="enablePropagation" | ||
176 | + > | ||
125 | <h3 className={'qx-flow-form__label-title'}>事务控制</h3> | 177 | <h3 className={'qx-flow-form__label-title'}>事务控制</h3> |
126 | <Checkbox | 178 | <Checkbox |
127 | - checked={values.enablePropagation} | 179 | + checked={values?.enablePropagation} |
128 | onChange={onCheckedChange} | 180 | onChange={onCheckedChange} |
129 | > | 181 | > |
130 | 设置事务的传播行为和隔离级别 | 182 | 设置事务的传播行为和隔离级别 |
131 | </Checkbox> | 183 | </Checkbox> |
132 | </Form.Item> | 184 | </Form.Item> |
133 | <Form.Item | 185 | <Form.Item |
134 | - hidden={!values.enablePropagation} | 186 | + hidden={!values?.enablePropagation} |
135 | label="事务传播行为" | 187 | label="事务传播行为" |
136 | name="propagation" | 188 | name="propagation" |
189 | + style={{ | ||
190 | + marginBottom: '16px', | ||
191 | + }} | ||
137 | > | 192 | > |
138 | <PropagationSetting | 193 | <PropagationSetting |
139 | optionsList={propagationList} | 194 | optionsList={propagationList} |
140 | - value={'REQUIRED'} | 195 | + value={values?.propagation || 'REQUIRED'} |
141 | onChange={(_v: string) => { | 196 | onChange={(_v: string) => { |
142 | - const _cloneVal = _.cloneDeep(values); | 197 | + const _cloneVal = cloneDeep(values); |
143 | setValues({ | 198 | setValues({ |
144 | ..._cloneVal, | 199 | ..._cloneVal, |
145 | propagation: _v, | 200 | propagation: _v, |
@@ -148,15 +203,15 @@ const StartConfigComponent: React.FC<StartConfigComponentProps> = | @@ -148,15 +203,15 @@ const StartConfigComponent: React.FC<StartConfigComponentProps> = | ||
148 | /> | 203 | /> |
149 | </Form.Item> | 204 | </Form.Item> |
150 | <Form.Item | 205 | <Form.Item |
151 | - hidden={!values.enablePropagation} | 206 | + hidden={!values?.enablePropagation} |
152 | label="事务隔离级别" | 207 | label="事务隔离级别" |
153 | name="isolation" | 208 | name="isolation" |
154 | > | 209 | > |
155 | <PropagationSetting | 210 | <PropagationSetting |
156 | optionsList={isolationList} | 211 | optionsList={isolationList} |
157 | - value={'REPEATABLE_READ'} | 212 | + value={values?.isolation || 'REPEATABLE_READ'} |
158 | onChange={(_v: string) => { | 213 | onChange={(_v: string) => { |
159 | - const _cloneVal = _.cloneDeep(values); | 214 | + const _cloneVal = cloneDeep(values); |
160 | setValues({ | 215 | setValues({ |
161 | ..._cloneVal, | 216 | ..._cloneVal, |
162 | isolation: _v, | 217 | isolation: _v, |
1 | import React, { memo } from 'react'; | 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 | import type { IDisplayComponent, INode } from '@qx/flow'; | 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 | const DisplayComponent: React.FC<DisplayComponentProps> = (props) => { | 21 | const DisplayComponent: React.FC<DisplayComponentProps> = (props) => { |
7 | const { node, nodes } = props; | 22 | const { node, nodes } = props; |
@@ -11,6 +26,8 @@ const DisplayComponent: React.FC<DisplayComponentProps> = (props) => { | @@ -11,6 +26,8 @@ const DisplayComponent: React.FC<DisplayComponentProps> = (props) => { | ||
11 | props.onChange?.([...nodes]); | 26 | props.onChange?.([...nodes]); |
12 | }; | 27 | }; |
13 | 28 | ||
29 | + const { clickNode } = useAction(); | ||
30 | + | ||
14 | return ( | 31 | return ( |
15 | <div className="qx-flow-default-node"> | 32 | <div className="qx-flow-default-node"> |
16 | <div className="qx-flow-default-node__header"> | 33 | <div className="qx-flow-default-node__header"> |
@@ -21,13 +38,38 @@ const DisplayComponent: React.FC<DisplayComponentProps> = (props) => { | @@ -21,13 +38,38 @@ const DisplayComponent: React.FC<DisplayComponentProps> = (props) => { | ||
21 | <span className="qx-flow-default-node__title--name">{node.name}</span> | 38 | <span className="qx-flow-default-node__title--name">{node.name}</span> |
22 | </span> | 39 | </span> |
23 | </div> | 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 | </div> | 73 | </div> |
32 | ); | 74 | ); |
33 | }; | 75 | }; |
@@ -9,8 +9,9 @@ import { QxIcon } from '@/components'; | @@ -9,8 +9,9 @@ import { QxIcon } from '@/components'; | ||
9 | import { isEmpty } from 'lodash-es'; | 9 | import { isEmpty } from 'lodash-es'; |
10 | import { handleWindowOpen } from '@qx/utils'; | 10 | import { handleWindowOpen } from '@qx/utils'; |
11 | // import {} from '@/src/services/data-flow'; | 11 | // import {} from '@/src/services/data-flow'; |
12 | -import { getIcon, useFlowTableScrollY } from '@/utils'; | 12 | +import { getIcon } from '@/utils'; |
13 | import { useDebounceEffect } from 'ahooks'; | 13 | import { useDebounceEffect } from 'ahooks'; |
14 | +import { useFlowTableScrollY } from '@/hooks'; | ||
14 | 15 | ||
15 | const { Text } = Typography; | 16 | const { Text } = Typography; |
16 | 17 |
@@ -16,7 +16,8 @@ import { useDebounceEffect, useDebounceFn } from 'ahooks'; | @@ -16,7 +16,8 @@ import { useDebounceEffect, useDebounceFn } from 'ahooks'; | ||
16 | import { isEmpty, cloneDeep } from 'lodash-es'; | 16 | import { isEmpty, cloneDeep } from 'lodash-es'; |
17 | 17 | ||
18 | import { FlowSettingProps } from '@/page/view/constant'; | 18 | import { FlowSettingProps } from '@/page/view/constant'; |
19 | -import { getIcon, useFlowTableScrollY } from '@/utils'; | 19 | +import { getIcon } from '@/utils'; |
20 | +import { useFlowTableScrollY } from '@/hooks'; | ||
20 | import actions from '@/utils/actions'; | 21 | import actions from '@/utils/actions'; |
21 | 22 | ||
22 | import { copyProcessById, deleteProcessById, getListProcess } from '@/services'; | 23 | import { copyProcessById, deleteProcessById, getListProcess } from '@/services'; |
1 | import React from 'react'; | 1 | import React from 'react'; |
2 | // import { history } from '@@/core/history'; | 2 | // import { history } from '@@/core/history'; |
3 | -import { useSearchParams } from 'react-router-dom'; | 3 | +import { useSearchParams } from '@/hooks'; |
4 | import { useTitle } from 'ahooks'; | 4 | import { useTitle } from 'ahooks'; |
5 | // @ts-ignore; | 5 | // @ts-ignore; |
6 | import { handleWindowOpen } from '@qx/utils'; | 6 | import { handleWindowOpen } from '@qx/utils'; |
@@ -13,16 +13,12 @@ import styles from '@/page/view/index.module.less'; | @@ -13,16 +13,12 @@ import styles from '@/page/view/index.module.less'; | ||
13 | const prefix = 'qx-data-flow'; | 13 | const prefix = 'qx-data-flow'; |
14 | 14 | ||
15 | const DataFlowView: React.FC = ({}) => { | 15 | const DataFlowView: React.FC = ({}) => { |
16 | - const [searchParams] = useSearchParams(); | 16 | + const [query] = useSearchParams<any>(); |
17 | const { | 17 | const { |
18 | appId, // 应用id | 18 | appId, // 应用id |
19 | funCode, // 表单id | 19 | funCode, // 表单id |
20 | returnUrl, // 来自页面跳转返回可跳转 | 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 | if (!!appId && !funCode) { | 24 | if (!!appId && !funCode) { |
@@ -44,94 +44,3 @@ export const getIcon = (icon: string, type?: string) => { | @@ -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,14 +11,13 @@ import { | ||
11 | Avatar, | 11 | Avatar, |
12 | } from 'antd'; | 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 | import { useTitle } from 'ahooks'; | 15 | import { useTitle } from 'ahooks'; |
17 | import { QxIcon } from '@/components'; | 16 | import { QxIcon } from '@/components'; |
18 | import { handleWindowOpen } from '@qx/utils'; | 17 | import { handleWindowOpen } from '@qx/utils'; |
19 | import { FlowHeader, FlowVersion } from '@/components'; | 18 | import { FlowHeader, FlowVersion } from '@/components'; |
20 | 19 | ||
21 | -import { useFlowTableScrollY } from '@/utils'; | 20 | +import { useFlowTableScrollY } from '@/hooks'; |
22 | import actions from '@/utils/actions'; | 21 | import actions from '@/utils/actions'; |
23 | 22 | ||
24 | import { isEmpty, cloneDeep } from 'lodash-es'; | 23 | import { isEmpty, cloneDeep } from 'lodash-es'; |
@@ -33,17 +32,12 @@ import { FlowVersionStatusEnums } from '@/interface'; | @@ -33,17 +32,12 @@ import { FlowVersionStatusEnums } from '@/interface'; | ||
33 | const prefix = 'qx-flow-setting'; | 32 | const prefix = 'qx-flow-setting'; |
34 | 33 | ||
35 | const DataFlowVersion: React.FC = ({}) => { | 34 | const DataFlowVersion: React.FC = ({}) => { |
36 | - // @ts-ignore | ||
37 | - const [searchParams] = useSearchParams(); | 35 | + const [query] = useSearchParams<any>(); |
38 | const { | 36 | const { |
39 | processId, // 流程ID | 37 | processId, // 流程ID |
40 | name, // 流程名称 | 38 | name, // 流程名称 |
41 | returnUrl, // 来自页面跳转返回可跳转 | 39 | returnUrl, // 来自页面跳转返回可跳转 |
42 | - } = { | ||
43 | - processId: searchParams.get('processId'), | ||
44 | - name: searchParams.get('name'), | ||
45 | - returnUrl: searchParams.get('returnUrl'), | ||
46 | - }; | 40 | + } = query; |
47 | const [pageData, setPageData] = useState<any[]>([]); | 41 | const [pageData, setPageData] = useState<any[]>([]); |
48 | const [tableLoading, setTableLoading] = useState<boolean>(true); // 表格loading | 42 | const [tableLoading, setTableLoading] = useState<boolean>(true); // 表格loading |
49 | // 表格是否添加scroll 属性 | 43 | // 表格是否添加scroll 属性 |
src/public/imgs/default_cover.png
0 → 100644
4.11 KB
1 | import { createHashRouter, RouterProvider } from 'react-router-dom'; | 1 | import { createHashRouter, RouterProvider } from 'react-router-dom'; |
2 | import Root from '../page/root'; | 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 | export default () => ( | 5 | export default () => ( |
9 | <RouterProvider | 6 | <RouterProvider |
@@ -14,19 +11,27 @@ export default () => ( | @@ -14,19 +11,27 @@ export default () => ( | ||
14 | children: [ | 11 | children: [ |
15 | { | 12 | { |
16 | path: '/about', | 13 | path: '/about', |
17 | - element: <About />, | 14 | + element: lazyComponent( |
15 | + () => import(/*qx-dataflow-about*/ '@/page/about'), | ||
16 | + ), | ||
18 | }, | 17 | }, |
19 | { | 18 | { |
20 | path: '/designer', | 19 | path: '/designer', |
21 | - element: <Designer />, | 20 | + element: lazyComponent( |
21 | + () => import(/*qx-dataflow-designer*/ '@/page/designer'), | ||
22 | + ), | ||
22 | }, | 23 | }, |
23 | { | 24 | { |
24 | path: '/list', | 25 | path: '/list', |
25 | - element: <List />, | 26 | + element: lazyComponent( |
27 | + () => import(/*qx-dataflow-list*/ '@/page/view/list'), | ||
28 | + ), | ||
26 | }, | 29 | }, |
27 | { | 30 | { |
28 | path: '/version', | 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,6 +4,7 @@ import request from '@/request'; | ||
4 | const qxSdk = new QxSdk(); | 4 | const qxSdk = new QxSdk(); |
5 | 5 | ||
6 | qxSdk.registerSdk({ | 6 | qxSdk.registerSdk({ |
7 | + // @ts-ignore | ||
7 | getFormFields(appCode: string, funCode: string, viewCode: string) { | 8 | getFormFields(appCode: string, funCode: string, viewCode: string) { |
8 | return request.get( | 9 | return request.get( |
9 | `/qx-apaas-lowcode/app/${appCode}/form/${funCode}/field/option/${viewCode}?withRel=true`, | 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 | import { QxIcon } from '@/components'; | 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 | const defaultIcon: Record<string, string> = { | 6 | const defaultIcon: Record<string, string> = { |
9 | form: 'icon-app-file-fill', | 7 | form: 'icon-app-file-fill', |
@@ -44,94 +42,3 @@ export const getIcon = (icon: string, type?: string) => { | @@ -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 | -}; |