├── typings.d.ts ├── .fatherrc.ts ├── .prettierignore ├── src ├── Flow │ ├── context │ │ └── OperatorContext.js │ ├── components │ │ ├── End.js │ │ ├── TitleElement.js │ │ ├── Render.js │ │ ├── Node.js │ │ ├── Start.js │ │ ├── MyDrawer.js │ │ ├── Wrap.js │ │ ├── Add.js │ │ ├── Approver.js │ │ ├── Notifier.js │ │ ├── SetApprover.js │ │ ├── ZoomLayout.js │ │ ├── Constants.js │ │ ├── AddOptionList.js │ │ ├── SetCondition.js │ │ └── Condition.js │ ├── index.md │ ├── init.json │ ├── index.jsx │ └── index.less ├── index.ts ├── UserList │ ├── index.md │ └── index.jsx └── ConditionList │ ├── index.md │ ├── util.js │ └── index.jsx ├── .prettierrc ├── .editorconfig ├── README.md ├── .gitignore ├── .umirc.ts ├── tsconfig.json └── package.json /typings.d.ts: -------------------------------------------------------------------------------- 1 | declare module '*.css'; 2 | declare module '*.less'; 3 | -------------------------------------------------------------------------------- /.fatherrc.ts: -------------------------------------------------------------------------------- 1 | export default { 2 | esm: 'rollup', 3 | cjs: 'rollup', 4 | }; 5 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | **/*.svg 2 | **/*.ejs 3 | **/*.html 4 | package.json 5 | .umi 6 | .umi-production 7 | .umi-test 8 | -------------------------------------------------------------------------------- /src/Flow/context/OperatorContext.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | 3 | const Context = React.createContext(null) 4 | export default Context; -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | export { default as Flow } from './Flow'; 2 | export { default as UserList } from './UserList'; 3 | export { default as ConditionList } from './ConditionList'; -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "singleQuote": true, 3 | "trailingComma": "all", 4 | "printWidth": 80, 5 | "overrides": [ 6 | { 7 | "files": ".prettierrc", 8 | "options": { "parser": "json" } 9 | } 10 | ] 11 | } 12 | -------------------------------------------------------------------------------- /src/UserList/index.md: -------------------------------------------------------------------------------- 1 | Demo: 2 | 3 | ```tsx 4 | import React from 'react'; 5 | import { UserList } from 'raycloud-apaas-flow'; 6 | 7 | export default () => ; 8 | ``` 9 | 10 | More skills for writing demo: https://d.umijs.org/guide/basic#write-component-demo 11 | -------------------------------------------------------------------------------- /src/Flow/components/End.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | function EndNode(){ 4 | return (
5 |
6 |
流程结束
7 |
) 8 | } 9 | 10 | export default EndNode -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # http://editorconfig.org 2 | root = true 3 | 4 | [*] 5 | indent_style = space 6 | indent_size = 2 7 | end_of_line = lf 8 | charset = utf-8 9 | trim_trailing_whitespace = true 10 | insert_final_newline = true 11 | 12 | [*.md] 13 | trim_trailing_whitespace = false 14 | 15 | [Makefile] 16 | indent_style = tab 17 | -------------------------------------------------------------------------------- /src/UserList/index.jsx: -------------------------------------------------------------------------------- 1 | import React, { forwardRef, useImperativeHandle, useState } from 'react'; 2 | 3 | const UserList = forwardRef((props, ref) => { 4 | useImperativeHandle(ref, () => ({ 5 | 6 | })); 7 | return ( 8 |
9 |
UserList
10 |
11 | ) 12 | }) 13 | 14 | export default UserList -------------------------------------------------------------------------------- /src/Flow/components/TitleElement.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import { CloseCircleOutlined } from '@ant-design/icons'; 3 | function TitleElement(props) { 4 | return (
5 | {props.nodeName} 6 | 7 |
) 8 | } 9 | export default TitleElement -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # raycloud-apaas-flow 2 | 3 | ## Getting Started 4 | 5 | Install dependencies, 6 | 7 | ```bash 8 | $ npm i 9 | ``` 10 | 11 | Start the dev server, 12 | 13 | ```bash 14 | $ npm start 15 | ``` 16 | 17 | Build documentation, 18 | 19 | ```bash 20 | $ npm run docs:build 21 | ``` 22 | 23 | Build library via `father-build`, 24 | 25 | ```bash 26 | $ npm run build 27 | ``` 28 | -------------------------------------------------------------------------------- /src/Flow/components/Render.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import MatchNode from './Node' 3 | 4 | function Render({ config, pRef }) { 5 | return ( 6 | 7 | 8 | {config.childNode && } 9 | 10 | ) 11 | } 12 | 13 | export default Render -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /npm-debug.log* 6 | /yarn-error.log 7 | /yarn.lock 8 | /package-lock.json 9 | 10 | # production 11 | /dist 12 | /docs-dist 13 | 14 | # misc 15 | .DS_Store 16 | 17 | # umi 18 | .umi 19 | .umi-production 20 | .umi-test 21 | .env.local 22 | 23 | # ide 24 | /.vscode 25 | /.idea 26 | -------------------------------------------------------------------------------- /.umirc.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'dumi'; 2 | 3 | export default defineConfig({ 4 | title: 'raycloud-apaas-flow', 5 | favicon: 'https://user-images.githubusercontent.com/9554297/83762004-a0761b00-a6a9-11ea-83b4-9c8ff721d4b8.png', 6 | logo: 'https://user-images.githubusercontent.com/9554297/83762004-a0761b00-a6a9-11ea-83b4-9c8ff721d4b8.png', 7 | outputPath: 'docs-dist', 8 | // more config: https://d.umijs.org/config 9 | }); 10 | -------------------------------------------------------------------------------- /src/Flow/components/Node.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | 3 | import StartNode from './Start' 4 | import ApproverNode from './Approver' 5 | import NotifierNode from './Notifier' 6 | import ConditionNode from './Condition' 7 | 8 | const NodeMaps = { 9 | 0: StartNode, 10 | 1: ApproverNode, 11 | 2: NotifierNode, 12 | 4: ConditionNode 13 | } 14 | 15 | function MatchNode({config, pRef}) { 16 | const Node = NodeMaps[config.type] || null 17 | return Node && 18 | } 19 | 20 | export default MatchNode -------------------------------------------------------------------------------- /src/Flow/index.md: -------------------------------------------------------------------------------- 1 | Demo: 2 | 3 | ```tsx 4 | import React from 'react'; 5 | import { Flow } from 'raycloud-apaas-flow'; 6 | 7 | const config = {}; // 流程配置 8 | const formItems = [{ 9 | label: 'String', 10 | value: 'input_123456', 11 | type: 'string' 12 | }, { 13 | label: 'Array', 14 | value: 'checkbox_123456', 15 | type: 'array' 16 | }, { 17 | label: 'Object', 18 | value: 'checkbox2_123456', 19 | type: 'object' 20 | }, { 21 | label: 'Boolean', 22 | value: 'boolean_123456', 23 | type: 'boolean' 24 | }]; // 工单列表字段 25 | 26 | export default () => ; 27 | ``` 28 | -------------------------------------------------------------------------------- /src/Flow/components/Start.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import NodeWrap from './Wrap'; 3 | 4 | const getOwner = (userList = []) => { 5 | return userList.map(user => user.name).join('、') 6 | } 7 | function StartNode(props) { 8 | return ( 9 | {props.nodeName}} 13 | > 14 |
0 && getOwner(props.nodeUserList)}>{props.nodeUserList?.length > 0 && getOwner(props.nodeUserList) }
15 | {/* */} 16 |
17 | ); 18 | } 19 | export default StartNode; 20 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "esnext", 4 | "module": "esnext", 5 | "moduleResolution": "node", 6 | "importHelpers": true, 7 | "jsx": "react", 8 | "esModuleInterop": true, 9 | "sourceMap": true, 10 | "baseUrl": "./", 11 | "strict": true, 12 | "paths": { 13 | "@/*": ["src/*"], 14 | "@@/*": ["src/.umi/*"] 15 | }, 16 | "allowSyntheticDefaultImports": true 17 | }, 18 | "exclude": [ 19 | "node_modules", 20 | "lib", 21 | "es", 22 | "dist", 23 | "typings", 24 | "**/__test__", 25 | "test", 26 | "docs", 27 | "tests" 28 | ] 29 | } 30 | -------------------------------------------------------------------------------- /src/ConditionList/index.md: -------------------------------------------------------------------------------- 1 | Demo: 2 | 3 | ```tsx 4 | import React from 'react'; 5 | import { ConditionList } from 'raycloud-apaas-flow'; 6 | 7 | const formItems = [{ 8 | label: 'String', 9 | value: 'input_123456', 10 | type: 'string' 11 | }, { 12 | label: 'Array', 13 | value: 'checkbox_123456', 14 | type: 'array' 15 | }, { 16 | label: 'Object', 17 | value: 'checkbox2_123456', 18 | type: 'object' 19 | }, { 20 | label: 'Boolean', 21 | value: 'boolean_123456', 22 | type: 'boolean' 23 | }]; 24 | export default () => ; 25 | ``` 26 | 27 | More skills for writing demo: https://d.umijs.org/guide/basic#write-component-demo 28 | -------------------------------------------------------------------------------- /src/Flow/components/MyDrawer.js: -------------------------------------------------------------------------------- 1 | import React, { useState, forwardRef, useImperativeHandle } from 'react'; 2 | import { Drawer } from 'antd'; 3 | 4 | const ApproverDrawer = forwardRef(({ children, title, ...other }, ref) => { 5 | const [visible, setVisible] = useState(false); 6 | const onClose = () => { 7 | setVisible(false); 8 | }; 9 | useImperativeHandle(ref, () => ({ 10 | openModal: () => setVisible(true), 11 | closeModal: onClose, 12 | })); 13 | return ( 14 | 21 | {children} 22 | 23 | ) 24 | }) 25 | 26 | export default ApproverDrawer; 27 | -------------------------------------------------------------------------------- /src/Flow/components/Wrap.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import {NodeTypes} from './Constants' 3 | import AddNode from './Add' 4 | function NodeWrap(props) { 5 | return ( 6 |
7 |
8 |
9 |
10 | {props.title} 11 |
12 |
13 | {props.children} 14 |
15 |
16 | 17 |
18 | 19 |
20 | ) 21 | } 22 | export default NodeWrap -------------------------------------------------------------------------------- /src/Flow/components/Add.js: -------------------------------------------------------------------------------- 1 | import React, { useContext } from 'react'; 2 | import { PlusCircleFilled } from '@ant-design/icons'; 3 | import { Popover } from 'antd'; 4 | import AddNodeList from './AddOptionList'; 5 | import WFC from '../context/OperatorContext'; 6 | import 'antd/dist/antd.css'; 7 | 8 | function AddNode(props) { 9 | const { onAddNode } = useContext(WFC); 10 | function onOptionClick(type) { 11 | onAddNode(type, props.pRef, props.objRef); 12 | } 13 | return ( 14 |
15 |
16 | } trigger="hover"> 17 | 18 | 19 |
20 |
21 | ); 22 | } 23 | 24 | export default AddNode; 25 | -------------------------------------------------------------------------------- /src/Flow/components/Approver.js: -------------------------------------------------------------------------------- 1 | import React, { useContext } from 'react'; 2 | import { RightOutlined } from '@ant-design/icons'; 3 | import NodeWrap from './Wrap' 4 | import TitleElement from './TitleElement' 5 | import WFC from '../context/OperatorContext' 6 | function ApproverNode(props) { 7 | const { onDeleteNode, onSelectNode, handleOpenApproverDrawer } = useContext(WFC) 8 | const delNode = (e) => { 9 | e.stopPropagation(); 10 | onDeleteNode(props.pRef, props.objRef) 11 | } 12 | 13 | function onContentClick() { 14 | onSelectNode(props.pRef, props.objRef) 15 | handleOpenApproverDrawer(); 16 | } 17 | // TODO: 这里读取props数据 18 | let TitleEl = 19 | return ( 20 |
21 | {props.owner ? props.owner :'请选择审核人'} 22 |
23 | 24 |
) 25 | } 26 | export default ApproverNode -------------------------------------------------------------------------------- /src/Flow/components/Notifier.js: -------------------------------------------------------------------------------- 1 | import React, { useContext } from 'react' 2 | import { RightOutlined } from '@ant-design/icons'; 3 | import NodeWrap from './Wrap' 4 | import TitleElement from './TitleElement' 5 | import WFC from '../context/OperatorContext'; 6 | 7 | function NotifierNode(props) { 8 | const {onDeleteNode, onSelectNode} = useContext(WFC) 9 | function delNode() { 10 | onDeleteNode(props.pRef, props.objRef) 11 | } 12 | function onChange(val) { 13 | props.pRef.childNode.nodeName = val 14 | } 15 | 16 | function onContentClick() { 17 | onSelectNode(props.pRef, props.objRef) 18 | props.onContentClick && props.onContentClick() 19 | } 20 | 21 | let TitleEl = 22 | return ( 23 |
24 | {props.owner ? props.owner : '请选择抄送人'} 25 |
26 | 27 | {/* */} 28 |
) 29 | } 30 | export default NotifierNode -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "name": "raycloud-apaas-flow", 4 | "version": "1.0.0", 5 | "scripts": { 6 | "start": "dumi dev", 7 | "docs:build": "dumi build", 8 | "docs:deploy": "gh-pages -d docs-dist", 9 | "build": "father-build", 10 | "deploy": "npm run docs:build && npm run docs:deploy", 11 | "release": "npm run build && npm publish", 12 | "prettier": "prettier --write \"**/*.{js,jsx,tsx,ts,less,md,json}\"", 13 | "test": "umi-test", 14 | "test:coverage": "umi-test --coverage" 15 | }, 16 | "main": "dist/index.js", 17 | "module": "dist/index.esm.js", 18 | "typings": "dist/index.d.ts", 19 | "gitHooks": { 20 | "pre-commit": "lint-staged" 21 | }, 22 | "lint-staged": { 23 | "*.{js,jsx,less,md,json}": [ 24 | "prettier --write" 25 | ], 26 | "*.ts?(x)": [ 27 | "prettier --parser=typescript --write" 28 | ] 29 | }, 30 | "dependencies": { 31 | "@ant-design/icons": "^4.6.4", 32 | "antd": "^4.16.13", 33 | "lodash": "^4.17.21", 34 | "react": "^16.12.0" 35 | }, 36 | "devDependencies": { 37 | "@umijs/test": "^3.0.5", 38 | "dumi": "^1.0.16", 39 | "father-build": "^1.17.2", 40 | "gh-pages": "^3.0.0", 41 | "lint-staged": "^10.0.7", 42 | "prettier": "^2.2.1", 43 | "yorkie": "^2.0.0" 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/Flow/components/SetApprover.js: -------------------------------------------------------------------------------- 1 | import React, { useContext } from 'react'; 2 | import { Form, Input, Select, Button, Modal } from 'antd'; 3 | import WFC from '../context/OperatorContext'; 4 | 5 | const SetApprover = () => { 6 | const { currentNode, updateNode } = useContext(WFC); 7 | const handleChange = ({ key, value }) => { 8 | currentNode[key] = value; 9 | updateNode(); 10 | } 11 | return ( 12 | <> 13 | 14 | handleChange({ key: 'nodeName', value: e.target.value })} 18 | /> 19 | 20 | 21 | 22 | 23 | 24 | handleChange({ key: 'nodeName', value: e.target.value })} 38 | /> 39 | 40 | 41 | 42 | 43 | 48 | 72 | 73 | )} 74 | 75 | 76 | 81 | 82 | 83 | 84 | {/* */} 85 | 86 | ))} 87 | 88 | )} 89 | 90 | 91 | 92 | 93 | 94 | ); 95 | }); 96 | 97 | export default ConditionList; -------------------------------------------------------------------------------- /src/Flow/index.jsx: -------------------------------------------------------------------------------- 1 | import React, { 2 | forwardRef, 3 | useImperativeHandle, 4 | useState, 5 | useRef, 6 | } from 'react'; 7 | import { isEmpty } from 'lodash'; 8 | import initConfig from './init.json'; 9 | import OpContext from './context/OperatorContext'; 10 | import ZoomLayout from './components/ZoomLayout'; 11 | import Render from './components/Render'; 12 | import EndNode from './components/End'; 13 | import MyDrawer from './components/MyDrawer'; 14 | import SetApprover from './components/SetApprover'; 15 | import SetCondition from './components/SetCondition'; 16 | import { OptionTypes, NodeTemplates, NodeTypes } from './components/Constants'; 17 | import './index.less'; 18 | 19 | const Flow = forwardRef((props, ref) => { 20 | const [config, setConfig] = useState( 21 | isEmpty(props.config) ? initConfig : props.config, 22 | ); 23 | const [currentNode, setCurrentNode] = useState({}); 24 | const approverRef = useRef(null); 25 | const conditionRef = useRef(null); 26 | useImperativeHandle(ref, () => ({})); 27 | const updateNode = () => { 28 | setConfig({ ...config }); 29 | }; 30 | 31 | const onAddNode = (type, pRef, objRef) => { 32 | const o = objRef.childNode; 33 | if (type === OptionTypes.APPROVER) { 34 | objRef.childNode = { 35 | ...NodeTemplates[OptionTypes.APPROVER], 36 | childNode: o, 37 | }; 38 | } 39 | if (type === OptionTypes.NOTIFIER) { 40 | objRef.childNode = { 41 | ...NodeTemplates[OptionTypes.NOTIFIER], 42 | childNode: o, 43 | }; 44 | } 45 | if (type === OptionTypes.CONDITION) { 46 | objRef.childNode = { 47 | ...NodeTemplates[OptionTypes.CONDITION], 48 | conditionNodes: [ 49 | { 50 | ...NodeTemplates[OptionTypes.BRANCH], 51 | nodeName: '条件1', 52 | childNode: o, 53 | }, 54 | { ...NodeTemplates[OptionTypes.BRANCH], nodeName: '条件2' }, 55 | ], 56 | }; 57 | } 58 | if (type === OptionTypes.BRANCH) { 59 | objRef.conditionNodes.push({ ...NodeTemplates[NodeTypes.BRANCH] }); 60 | } 61 | updateNode(); 62 | }; 63 | const onDeleteNode = (pRef, objRef, type, index) => { 64 | if (window.confirm('是否删除节点?')) { 65 | if (type === NodeTypes.BRANCH) { 66 | console.log([...objRef.conditionNodes], index); 67 | objRef.conditionNodes.splice(index, 1); 68 | console.log(objRef.conditionNodes); 69 | } else { 70 | const newObj = objRef.childNode; 71 | pRef.childNode = newObj; 72 | } 73 | updateNode(); 74 | } 75 | }; 76 | 77 | // 获取节点 78 | const onSelectNode = (pRef, objRef) => { 79 | setCurrentNode(objRef) 80 | }; 81 | 82 | // 打开审批人Drawer 83 | const handleOpenApproverDrawer = () => approverRef.current.openModal(); 84 | const handleCloseApproverDrawer = () => approverRef.current.closeModal(); 85 | const handleOpenConditionDrawer = () => conditionRef.current.openModal(); 86 | const handleCloseConditionDrawer = () => conditionRef.current.closeModal(); 87 | 88 | return ( 89 | 103 |
104 | 105 | 106 | 107 | 108 |
109 | 115 | 116 | 117 | 123 | 124 | 125 |
126 | ); 127 | }); 128 | 129 | export default Flow; 130 | -------------------------------------------------------------------------------- /src/Flow/index.less: -------------------------------------------------------------------------------- 1 | .node-wrap-box { 2 | display: -webkit-inline-box; 3 | display: -ms-inline-flexbox; 4 | display: inline-flex; 5 | -webkit-box-orient: vertical; 6 | -webkit-box-direction: normal; 7 | -ms-flex-direction: column; 8 | flex-direction: column; 9 | position: relative; 10 | width: 220px; 11 | min-height: 72px; 12 | -ms-flex-negative: 0; 13 | flex-shrink: 0; 14 | background: #fff; 15 | border-radius: 4px; 16 | cursor: pointer 17 | } 18 | 19 | .node-wrap-box:after { 20 | pointer-events: none; 21 | content: ""; 22 | position: absolute; 23 | top: 0; 24 | bottom: 0; 25 | left: 0; 26 | right: 0; 27 | z-index: 2; 28 | border-radius: 4px; 29 | border: 1px solid transparent; 30 | transition: all .1s cubic-bezier(.645, .045, .355, 1); 31 | box-shadow: 0 2px 5px 0 rgba(0, 0, 0, .1) 32 | } 33 | 34 | .node-wrap-box.active:after, 35 | .node-wrap-box:active:after, 36 | .node-wrap-box:hover:after { 37 | border: 1px solid #3296fa; 38 | box-shadow: 0 0 6px 0 rgba(50, 150, 250, .3) 39 | } 40 | 41 | .node-wrap-box.active .close, 42 | .node-wrap-box:active .close, 43 | .node-wrap-box:hover .close { 44 | display: block 45 | } 46 | 47 | .node-wrap-box.error:after { 48 | border: 1px solid #f25643; 49 | box-shadow: 0 2px 5px 0 rgba(0, 0, 0, .1) 50 | } 51 | 52 | .node-wrap-box .title { 53 | position: relative; 54 | display: flex; 55 | align-items: center; 56 | padding-left: 16px; 57 | padding-right: 8px; 58 | // width: 100%; 59 | height: 24px; 60 | line-height: 24px; 61 | font-size: 12px; 62 | color: #fff; 63 | text-align: left; 64 | background: #576a95; 65 | border-radius: 4px 4px 0 0; 66 | .title-element { 67 | width: 100%; 68 | display: flex; 69 | flex-direction: row; 70 | align-items: center; 71 | justify-content: space-between; 72 | } 73 | } 74 | 75 | .node-wrap-box .title .iconfont { 76 | font-size: 12px; 77 | margin-right: 5px 78 | } 79 | 80 | .node-wrap-box .placeholder { 81 | color: #bfbfbf 82 | } 83 | 84 | .node-wrap-box .close { 85 | display: none; 86 | position: absolute; 87 | right: 10px; 88 | top: 50%; 89 | transform: translateY(-50%); 90 | width: 20px; 91 | height: 20px; 92 | font-size: 14px; 93 | color: #fff; 94 | border-radius: 50%; 95 | text-align: center; 96 | line-height: 20px 97 | } 98 | 99 | .node-wrap-box .content { 100 | position: relative; 101 | font-size: 14px; 102 | padding: 16px; 103 | padding-right: 12px; 104 | display: flex; 105 | flex-direction: row; 106 | justify-content: space-between; 107 | align-items: center; 108 | } 109 | 110 | .node-wrap-box .content .text { 111 | overflow: hidden; 112 | text-overflow: ellipsis; 113 | display: -webkit-box; 114 | -webkit-line-clamp: 3; 115 | -webkit-box-orient: vertical 116 | } 117 | 118 | .node-wrap-box .content .arrow { 119 | position: absolute; 120 | right: 10px; 121 | top: 50%; 122 | transform: translateY(-50%); 123 | width: 20px; 124 | height: 14px; 125 | font-size: 14px; 126 | color: #979797 127 | } 128 | 129 | .start-node.node-wrap-box .content .text { 130 | display: block; 131 | white-space: nowrap 132 | } 133 | 134 | .node-wrapper-box-new { 135 | padding: 12px 10px 136 | } 137 | 138 | .node-wrapper-box-new .actions { 139 | margin-top: 11px; 140 | text-align: right 141 | } 142 | 143 | .node-wrapper-box-new .ant-btn { 144 | margin-left: 8px 145 | } 146 | 147 | .node-wrap-box:before { 148 | content: ""; 149 | position: absolute; 150 | top: -12px; 151 | left: 50%; 152 | -webkit-transform: translateX(-50%); 153 | transform: translateX(-50%); 154 | width: 0; 155 | height: 4px; 156 | border-style: solid; 157 | border-width: 8px 6px 4px; 158 | border-color: #cacaca transparent transparent; 159 | background: #f5f5f7 160 | } 161 | 162 | .node-wrap-box.start-node:before { 163 | content: none 164 | } 165 | 166 | .add-node-popover { 167 | min-height: 160px 168 | } 169 | 170 | .add-node-popover-header { 171 | position: relative; 172 | margin-bottom: 15px 173 | } 174 | 175 | .add-node-popover-close { 176 | cursor: pointer; 177 | position: absolute; 178 | top: 5px; 179 | right: 5px; 180 | color: rgba(0, 0, 0, .25) 181 | } 182 | 183 | .add-node-popover-body { 184 | display: flex; 185 | .wrap-container { 186 | display: flex; 187 | flex-direction: column; 188 | .wrap { 189 | width: 64px; 190 | height: 64px; 191 | border-radius: 32px; 192 | border: 1px solid #e2e2e2; 193 | display: flex; 194 | align-items: center; 195 | justify-content: center; 196 | margin-left: 8px; 197 | } 198 | .text { 199 | padding-top: 8px; 200 | text-align: center; 201 | } 202 | } 203 | } 204 | 205 | .add-node-popover-item { 206 | margin-right: 10px; 207 | cursor: pointer; 208 | text-align: center; 209 | flex: 1; 210 | color: #191f25!important 211 | } 212 | 213 | .add-node-popover-item .item-wrapper { 214 | user-select: none; 215 | display: inline-block; 216 | width: 80px; 217 | height: 80px; 218 | margin-bottom: 5px; 219 | background: #fff; 220 | border: 1px solid #e2e2e2; 221 | border-radius: 50%; 222 | transition: all .3s cubic-bezier(.645, .045, .355, 1) 223 | } 224 | 225 | .add-node-popover-item .iconfont { 226 | font-size: 35px; 227 | line-height: 80px 228 | } 229 | 230 | .add-node-popover-item.approver .item-wrapper { 231 | color: #ff943e 232 | } 233 | 234 | .add-node-popover-item.notifier .item-wrapper { 235 | color: #3296fa 236 | } 237 | 238 | .add-node-popover-item.condition .item-wrapper { 239 | color: #15bc83 240 | } 241 | 242 | .add-node-popover-item.auto .item-wrapper { 243 | color: #1059fb 244 | } 245 | 246 | .add-node-popover-item:hover .item-wrapper { 247 | background: #3296fa; 248 | box-shadow: 0 10px 20px 0 rgba(50, 150, 250, .4) 249 | } 250 | 251 | .add-node-popover-item:hover .iconfont { 252 | color: #fff 253 | } 254 | 255 | .add-node-popover-item:active .item-wrapper { 256 | box-shadow: none; 257 | background: #eaeaea 258 | } 259 | 260 | .add-node-popover-item:active .iconfont { 261 | color: inherit 262 | } 263 | 264 | 265 | .top-left-cover-line { 266 | left: -1px 267 | } 268 | 269 | .top-left-cover-line, 270 | .top-right-cover-line { 271 | position: absolute; 272 | height: 3px; 273 | width: 50%; 274 | background-color: #f5f5f7; 275 | top: -2px 276 | } 277 | 278 | .top-right-cover-line { 279 | right: -1px 280 | } 281 | 282 | .bottom-left-cover-line { 283 | left: -1px 284 | } 285 | 286 | .bottom-left-cover-line, 287 | .bottom-right-cover-line { 288 | position: absolute; 289 | height: 3px; 290 | width: 50%; 291 | background-color: #f5f5f7; 292 | bottom: -2px 293 | } 294 | 295 | .bottom-right-cover-line { 296 | right: -1px 297 | } 298 | 299 | .panel-row { 300 | position: relative; 301 | margin-bottom: 10px 302 | } 303 | 304 | .dingflow-design { 305 | width: 100%; 306 | background-color: #f5f5f7; 307 | overflow: auto; 308 | position: absolute; 309 | bottom: 0; 310 | left: 0; 311 | right: 0; 312 | top: 0; 313 | z-index: 1; 314 | } 315 | 316 | .dingflow-design .box-scale { 317 | transform: scale(1); 318 | display: inline-block; 319 | position: relative; 320 | width: 100%; 321 | padding: 54.5px 0; 322 | -webkit-box-align: start; 323 | -ms-flex-align: start; 324 | align-items: flex-start; 325 | -webkit-box-pack: center; 326 | -ms-flex-pack: center; 327 | justify-content: center; 328 | -ms-flex-wrap: wrap; 329 | flex-wrap: wrap; 330 | min-width: -webkit-min-content; 331 | min-width: -moz-min-content; 332 | min-width: min-content; 333 | background-color: #f5f5f7; 334 | -webkit-transform-origin: 0 0 0; 335 | transform-origin: 0 0 0 336 | } 337 | 338 | .dingflow-design .ie-polyfill-container { 339 | display: -ms-grid; 340 | -ms-grid-columns: min-content 341 | } 342 | 343 | .dingflow-design .add-node-btn-box { 344 | width: 240px; 345 | display: -webkit-inline-box; 346 | display: -ms-inline-flexbox; 347 | display: inline-flex; 348 | -ms-flex-negative: 0; 349 | flex-shrink: 0; 350 | -webkit-box-flex: 1; 351 | -ms-flex-positive: 1; 352 | position: relative 353 | } 354 | 355 | .dingflow-design .add-node-btn-box:before { 356 | content: ""; 357 | position: absolute; 358 | top: 0; 359 | left: 0; 360 | right: 0; 361 | bottom: 0; 362 | z-index: -1; 363 | margin: auto; 364 | width: 2px; 365 | height: 100%; 366 | background-color: #cacaca 367 | } 368 | 369 | .dingflow-design .node-wrap { 370 | flex-direction: column; 371 | -webkit-box-pack: start; 372 | -ms-flex-pack: start; 373 | justify-content: flex-start; 374 | -webkit-box-align: center; 375 | -ms-flex-align: center; 376 | align-items: center; 377 | -ms-flex-wrap: wrap; 378 | flex-wrap: wrap; 379 | -webkit-box-flex: 1; 380 | -ms-flex-positive: 1; 381 | // padding: 0 50px; 382 | position: relative 383 | } 384 | 385 | .dingflow-design .branch-wrap, 386 | .dingflow-design .node-wrap { 387 | display: inline-flex; 388 | width: 100% 389 | } 390 | 391 | .dingflow-design .branch-box-wrap { 392 | display: flex; 393 | -webkit-box-orient: vertical; 394 | -webkit-box-direction: normal; 395 | -ms-flex-direction: column; 396 | flex-direction: column; 397 | -ms-flex-wrap: wrap; 398 | flex-wrap: wrap; 399 | -webkit-box-align: center; 400 | -ms-flex-align: center; 401 | align-items: center; 402 | min-height: 270px; 403 | width: 100%; 404 | -ms-flex-negative: 0; 405 | flex-shrink: 0 406 | } 407 | 408 | .dingflow-design .branch-box { 409 | display: flex; 410 | overflow: visible; 411 | min-height: 180px; 412 | height: auto; 413 | border-bottom: 2px solid #ccc; 414 | border-top: 2px solid #ccc; 415 | position: relative; 416 | margin-top: 15px 417 | } 418 | 419 | .dingflow-design .branch-box .col-box { 420 | background: #f5f5f7 421 | } 422 | 423 | .dingflow-design .branch-box .col-box:before { 424 | content: ""; 425 | position: absolute; 426 | top: 0; 427 | left: 0; 428 | right: 0; 429 | bottom: 0; 430 | z-index: 0; 431 | margin: auto; 432 | width: 2px; 433 | height: 100%; 434 | background-color: #cacaca 435 | } 436 | 437 | .dingflow-design .add-branch { 438 | border: none; 439 | outline: none; 440 | user-select: none; 441 | justify-content: center; 442 | font-size: 12px; 443 | padding: 0 10px; 444 | height: 30px; 445 | line-height: 30px; 446 | border-radius: 15px; 447 | color: #3296fa; 448 | background: #fff; 449 | box-shadow: 0 2px 4px 0 rgba(0, 0, 0, .1); 450 | position: absolute; 451 | top: -16px; 452 | left: 50%; 453 | transform: translateX(-50%); 454 | transform-origin: center center; 455 | cursor: pointer; 456 | z-index: 1; 457 | display: inline-flex; 458 | align-items: center; 459 | -webkit-transition: all .3s cubic-bezier(.645, .045, .355, 1); 460 | transition: all .3s cubic-bezier(.645, .045, .355, 1) 461 | } 462 | 463 | .dingflow-design .add-branch:hover { 464 | transform: translateX(-50%) scale(1.1); 465 | box-shadow: 0 8px 16px 0 rgba(0, 0, 0, .1) 466 | } 467 | 468 | .dingflow-design .add-branch:active { 469 | transform: translateX(-50%); 470 | box-shadow: none 471 | } 472 | 473 | .dingflow-design .col-box { 474 | display: inline-flex; 475 | -webkit-box-orient: vertical; 476 | -webkit-box-direction: normal; 477 | flex-direction: column; 478 | -webkit-box-align: center; 479 | align-items: center; 480 | position: relative 481 | } 482 | 483 | .dingflow-design .condition-node { 484 | min-height: 220px 485 | } 486 | 487 | .dingflow-design .condition-node, 488 | .dingflow-design .condition-node-box { 489 | display: inline-flex; 490 | -webkit-box-orient: vertical; 491 | -webkit-box-direction: normal; 492 | flex-direction: column; 493 | -webkit-box-flex: 1 494 | } 495 | 496 | .dingflow-design .condition-node-box { 497 | padding-top: 30px; 498 | padding-right: 50px; 499 | padding-left: 50px; 500 | -webkit-box-pack: center; 501 | justify-content: center; 502 | -webkit-box-align: center; 503 | align-items: center; 504 | flex-grow: 1; 505 | position: relative 506 | } 507 | 508 | .dingflow-design .condition-node-box:before { 509 | content: ""; 510 | position: absolute; 511 | top: 0; 512 | left: 0; 513 | right: 0; 514 | bottom: 0; 515 | margin: auto; 516 | width: 2px; 517 | height: 100%; 518 | background-color: #cacaca 519 | } 520 | 521 | .dingflow-design .auto-judge { 522 | position: relative; 523 | width: 220px; 524 | min-height: 72px; 525 | background: #fff; 526 | border-radius: 4px; 527 | padding: 12px 8px 0 16px; 528 | cursor: pointer 529 | } 530 | 531 | .dingflow-design .auto-judge:after { 532 | pointer-events: none; 533 | content: ""; 534 | position: absolute; 535 | top: 0; 536 | bottom: 0; 537 | left: 0; 538 | right: 0; 539 | z-index: 2; 540 | border-radius: 4px; 541 | border: 1px solid transparent; 542 | transition: all .1s cubic-bezier(.645, .045, .355, 1); 543 | box-shadow: 0 2px 5px 0 rgba(0, 0, 0, .1) 544 | } 545 | 546 | .dingflow-design .auto-judge.active:after, 547 | .dingflow-design .auto-judge:active:after, 548 | .dingflow-design .auto-judge:hover:after { 549 | border: 1px solid #3296fa; 550 | box-shadow: 0 0 6px 0 rgba(50, 150, 250, .3) 551 | } 552 | 553 | .dingflow-design .auto-judge.active .close, 554 | .dingflow-design .auto-judge:active .close, 555 | .dingflow-design .auto-judge:hover .close { 556 | display: block 557 | } 558 | 559 | .dingflow-design .auto-judge.error:after { 560 | border: 1px solid #f25643; 561 | box-shadow: 0 2px 5px 0 rgba(0, 0, 0, .1) 562 | } 563 | 564 | .dingflow-design .auto-judge .title-wrapper { 565 | position: relative; 566 | font-size: 12px; 567 | color: #15bc83; 568 | text-align: left; 569 | line-height: 16px; 570 | display: flex; 571 | flex-direction: row; 572 | justify-content: space-between; 573 | align-items: center; 574 | } 575 | 576 | .dingflow-design .auto-judge .title-wrapper .editable-title { 577 | display: inline-block; 578 | max-width: 120px; 579 | overflow: hidden; 580 | white-space: nowrap; 581 | text-overflow: ellipsis 582 | } 583 | 584 | .dingflow-design .auto-judge .title-wrapper .priority-title { 585 | display: inline-block; 586 | float: right; 587 | margin-right: 10px; 588 | color: rgba(25, 31, 37, .56) 589 | } 590 | 591 | .dingflow-design .auto-judge .title-wrapper .priority-button { 592 | display: inline-block; 593 | height: 28px; 594 | float: right; 595 | margin-right: 10px; 596 | border: 1px solid rgba(0, 0, 0, .15); 597 | border-radius: 4px; 598 | color: rgba(0, 0, 0, .65) 599 | } 600 | 601 | .dingflow-design .auto-judge .title-wrapper .priority-button div { 602 | display: inline-block 603 | } 604 | 605 | .dingflow-design .auto-judge .title-wrapper .priority-button .priority-content { 606 | padding: 0 8px; 607 | font-size: 12px; 608 | line-height: 28px; 609 | border-left: 1px solid rgba(0, 0, 0, .15); 610 | border-right: 1px solid rgba(0, 0, 0, .15) 611 | } 612 | 613 | .dingflow-design .auto-judge .placeholder { 614 | color: #bfbfbf 615 | } 616 | 617 | .dingflow-design .auto-judge .close { 618 | display: none; 619 | position: absolute; 620 | right: -10px; 621 | top: -10px; 622 | width: 20px; 623 | height: 20px; 624 | font-size: 14px; 625 | color: rgba(0, 0, 0, .25); 626 | border-radius: 50%; 627 | text-align: center; 628 | line-height: 20px; 629 | z-index: 2 630 | } 631 | 632 | .dingflow-design .auto-judge .content { 633 | font-size: 14px; 634 | color: #191f25; 635 | text-align: left; 636 | margin-top: 6px; 637 | overflow: hidden; 638 | text-overflow: ellipsis; 639 | display: -webkit-box; 640 | -webkit-line-clamp: 3; 641 | -webkit-box-orient: vertical; 642 | padding-right: 12px; 643 | display: flex; 644 | flex-direction: row; 645 | justify-content: space-between; 646 | align-items: center; 647 | } 648 | 649 | .dingflow-design .auto-judge .sort-left, 650 | .dingflow-design .auto-judge .sort-right { 651 | position: absolute; 652 | top: 0; 653 | bottom: 0; 654 | display: none; 655 | z-index: 1 656 | } 657 | 658 | .dingflow-design .auto-judge .sort-left { 659 | left: 0; 660 | border-right: 1px solid #f6f6f6 661 | } 662 | 663 | .dingflow-design .auto-judge .sort-right { 664 | right: 0; 665 | border-left: 1px solid #f6f6f6 666 | } 667 | 668 | .dingflow-design .auto-judge:hover .sort-left, 669 | .dingflow-design .auto-judge:hover .sort-right { 670 | display: flex; 671 | align-items: center 672 | } 673 | 674 | .dingflow-design .auto-judge .sort-left:hover, 675 | .dingflow-design .auto-judge .sort-right:hover { 676 | background: #efefef 677 | } 678 | 679 | .dingflow-design .add-node-btn { 680 | user-select: none; 681 | width: 240px; 682 | padding: 20px 0 32px; 683 | display: flex; 684 | -webkit-box-pack: center; 685 | justify-content: center; 686 | flex-shrink: 0; 687 | -webkit-box-flex: 1; 688 | flex-grow: 1 689 | } 690 | 691 | .dingflow-design .add-node-btn .btn { 692 | outline: none; 693 | box-shadow: 0 2px 4px 0 rgba(0, 0, 0, .1); 694 | width: 30px; 695 | height: 30px; 696 | background: #3296fa; 697 | border-radius: 50%; 698 | position: relative; 699 | border: none; 700 | line-height: 30px; 701 | -webkit-transition: all .3s cubic-bezier(.645, .045, .355, 1); 702 | transition: all .3s cubic-bezier(.645, .045, .355, 1) 703 | } 704 | 705 | .dingflow-design .add-node-btn .btn .iconfont { 706 | color: #fff; 707 | font-size: 16px 708 | } 709 | 710 | .dingflow-design .add-node-btn .btn:hover { 711 | transform: scale(1.3); 712 | box-shadow: 0 13px 27px 0 rgba(0, 0, 0, .1) 713 | } 714 | 715 | .dingflow-design .add-node-btn .btn:active { 716 | transform: none; 717 | background: #1e83e9; 718 | box-shadow: 0 2px 4px 0 rgba(0, 0, 0, .1) 719 | } 720 | 721 | .dingflow-design .end-node { 722 | border-radius: 50%; 723 | font-size: 14px; 724 | color: rgba(25, 31, 37, .4); 725 | text-align: left 726 | } 727 | 728 | .dingflow-design .end-node .end-node-circle { 729 | width: 10px; 730 | height: 10px; 731 | margin: auto; 732 | border-radius: 50%; 733 | background: #dbdcdc 734 | } 735 | 736 | .dingflow-design .end-node .end-node-text { 737 | margin-top: 5px; 738 | text-align: center 739 | } 740 | 741 | 742 | .zoom { 743 | display: flex; 744 | position: fixed; 745 | -webkit-box-align: center; 746 | -ms-flex-align: center; 747 | align-items: center; 748 | -webkit-box-pack: justify; 749 | -ms-flex-pack: justify; 750 | justify-content: space-between; 751 | height: 40px; 752 | width: 125px; 753 | right: 40px; 754 | margin-top: 30px; 755 | z-index: 10 756 | } 757 | 758 | .zoom .zoom-in, 759 | .zoom .zoom-out { 760 | width: 30px; 761 | height: 30px; 762 | background: #fff; 763 | color: #c1c1cd; 764 | cursor: pointer; 765 | background-size: 100%; 766 | background-repeat: no-repeat 767 | } 768 | 769 | .zoom .zoom-out { 770 | background-image: url(https://gw.alicdn.com/tfs/TB1s0qhBHGYBuNjy0FoXXciBFXa-90-90.png) 771 | } 772 | 773 | .zoom .zoom-out.disabled { 774 | opacity: .5 775 | } 776 | 777 | .zoom .zoom-in { 778 | background-image: url(https://gw.alicdn.com/tfs/TB1UIgJBTtYBeNjy1XdXXXXyVXa-90-90.png) 779 | } 780 | 781 | .zoom .zoom-in.disabled { 782 | opacity: .5 783 | } 784 | 785 | .add-icon { 786 | transition: all .3s cubic-bezier(.645, .045, .355, 1) 787 | } 788 | .add-icon:hover { 789 | transform: scale(1.2); 790 | } 791 | --------------------------------------------------------------------------------