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 | -}; | ... | ... |