diff --git a/examples/approval-process-designer-react/src/App.tsx b/examples/approval-process-designer-react/src/App.tsx
index 3b8d08b..5498e7a 100644
--- a/examples/approval-process-designer-react/src/App.tsx
+++ b/examples/approval-process-designer-react/src/App.tsx
@@ -1,47 +1,51 @@
import React from 'react';
import './App.css';
import {
- ApprovalProcessDesigner,
+ ApprovalProcessDesigner, GlobalStore,
IProcessNode,
ProcessWidget, StudioPanel
} from "@trionesdev/approval-process-designer-react";
-import {ApprovalActivity, ConditionActivity, RouteActivity, StartActivity,CcActivity} from "./activities";
+import {ApprovalActivity, ConditionActivity, RouteActivity, StartActivity, CcActivity} from "./activities";
+import {Watermark} from "antd";
+import * as Icons from "./activities/Icons"
function App() {
-
+ const handleOnChange = (value: any) => {
+ console.log("[processNode]", value)
+ }
const processNode: IProcessNode = {
type: 'START',
componentName: 'StartActivity',
- title: '开始',
- nextNode:{
+ title: '发起人',
+ nextNode: {
type: 'APPROVAL',
componentName: 'ApprovalActivity',
title: '审批',
- nextNode:{
- type:'ROUTE',
- componentName:'RouteActivity',
- title:'路由',
- nextNode:{
+ nextNode: {
+ type: 'ROUTE',
+ componentName: 'RouteActivity',
+ title: '路由',
+ nextNode: {
type: 'CC',
componentName: 'CcActivity',
title: '抄送人',
},
- children:[
+ children: [
{
- type:'CONDITION',
- componentName:'ConditionActivity',
- title:'条件1',
- nextNode:{
+ type: 'CONDITION',
+ componentName: 'ConditionActivity',
+ title: '条件1',
+ nextNode: {
type: 'APPROVAL',
componentName: 'ApprovalActivity',
title: '审批人',
}
},
{
- type:'CONDITION',
- componentName:'ConditionActivity',
- props:{
- defaultCondition:true,
+ type: 'CONDITION',
+ componentName: 'ConditionActivity',
+ props: {
+ defaultCondition: true,
}
}
]
@@ -49,14 +53,23 @@ function App() {
}
}
+ GlobalStore.registerIcons(Icons);
return (
- <>
-
-
-
-
-
- >
+
);
}
diff --git a/examples/approval-process-designer-react/src/activities/ApprovalActivity.tsx b/examples/approval-process-designer-react/src/activities/ApprovalActivity.tsx
index 2028962..a889b2d 100644
--- a/examples/approval-process-designer-react/src/activities/ApprovalActivity.tsx
+++ b/examples/approval-process-designer-react/src/activities/ApprovalActivity.tsx
@@ -8,6 +8,7 @@ import createResource = DesignerCore.createResource;
export const ApprovalActivity : ActivityFC = TdApprovalActivity
ApprovalActivity.Resource = createResource({
+ icon:'ApprovalActivityIcon',
type: 'APPROVAL',
componentName:'ApprovalActivity',
title:'审批人',
diff --git a/examples/approval-process-designer-react/src/activities/CcActivity.tsx b/examples/approval-process-designer-react/src/activities/CcActivity.tsx
index e73794c..9a0791e 100644
--- a/examples/approval-process-designer-react/src/activities/CcActivity.tsx
+++ b/examples/approval-process-designer-react/src/activities/CcActivity.tsx
@@ -5,7 +5,7 @@ export const CcActivity: ActivityFC = TdCcActivity
CcActivity.Resource = createResource({
type: 'CC',
- icon: '',
+ icon: 'CcActivityIcon',
componentName: 'CcActivity',
title: '抄送人',
addable: true
diff --git a/examples/approval-process-designer-react/src/activities/ConditionActivity.tsx b/examples/approval-process-designer-react/src/activities/ConditionActivity.tsx
index 72571c7..d3a1386 100644
--- a/examples/approval-process-designer-react/src/activities/ConditionActivity.tsx
+++ b/examples/approval-process-designer-react/src/activities/ConditionActivity.tsx
@@ -9,7 +9,5 @@ import createResource = DesignerCore.createResource;
export const ConditionActivity: ActivityFC = TdConditionActivity
ConditionActivity.Resource = createResource({
type: 'CONDITION',
- icon: '',
- componentName: 'ConditionActivity',
- title:'条件'
+ componentName: 'ConditionActivity'
})
\ No newline at end of file
diff --git a/examples/approval-process-designer-react/src/activities/Icons.tsx b/examples/approval-process-designer-react/src/activities/Icons.tsx
new file mode 100644
index 0000000..8899306
--- /dev/null
+++ b/examples/approval-process-designer-react/src/activities/Icons.tsx
@@ -0,0 +1,43 @@
+export const ApprovalActivityIcon = (
+
+)
+export const RouteActivityIcon = (
+
+)
+
+export const CcActivityIcon = (
+
+)
\ No newline at end of file
diff --git a/examples/approval-process-designer-react/src/activities/RouteActivity.tsx b/examples/approval-process-designer-react/src/activities/RouteActivity.tsx
index d21db09..2c0645b 100644
--- a/examples/approval-process-designer-react/src/activities/RouteActivity.tsx
+++ b/examples/approval-process-designer-react/src/activities/RouteActivity.tsx
@@ -4,6 +4,7 @@ import createResource = DesignerCore.createResource;
export const RouteActivity: ActivityFC = TdRouteActivity
RouteActivity.Resource = createResource({
+ icon: 'RouteActivityIcon',
type: 'ROUTE',
componentName: 'RouteActivity',
title: '条件分支',
diff --git a/packages/approval-process-designer-react/src/activity/Activity.tsx b/packages/approval-process-designer-react/src/activity/Activity.tsx
index 33b50e2..08125a2 100644
--- a/packages/approval-process-designer-react/src/activity/Activity.tsx
+++ b/packages/approval-process-designer-react/src/activity/Activity.tsx
@@ -5,6 +5,7 @@ import {ProcessNode} from "../model";
import {CloseIcon, RightIcon} from "../Icons";
import {AddActivityBox} from "./AddActivityBox";
import {IconWidget} from "../widget/IconWidget";
+import {observer} from "@formily/react";
const ActivityStyled = styled('div')({
boxSizing: 'border-box',
@@ -109,22 +110,34 @@ export type ActivityProps = {
closeable?: boolean
onClick?: () => void
}
-export const Activity: FC = ({
- children,
- processNode,
- titleStyle,
- titleEditable,
- onChange,
- closeable,
- onClick,
- }) => {
+export const Activity: FC = observer(({
+ children,
+ processNode,
+ titleStyle,
+ titleEditable,
+ onChange,
+ closeable,
+ onClick,
+ }) => {
const inputRef = createRef()
const [editing, setEditing] = useState(false)
+
+ const handleSave = (value: any) => {
+ processNode.title = value
+ setEditing(false)
+ }
+
const handleInputBlur = (e: any) => {
if (onChange) {
onChange(e.target.value)
}
- setEditing(false)
+ handleSave(e.target.value)
+ }
+
+ const handleKeyDown = (e: any) => {
+ if (e.keyCode == 13) {
+ handleSave(e.target.value)
+ }
}
const handleRemove = () => {
@@ -143,7 +156,8 @@ export const Activity: FC = ({
-}
\ No newline at end of file
+})
\ No newline at end of file
diff --git a/packages/approval-process-designer-react/src/activity/CondiitionActivity.tsx b/packages/approval-process-designer-react/src/activity/CondiitionActivity.tsx
index a4dd514..64c45b9 100644
--- a/packages/approval-process-designer-react/src/activity/CondiitionActivity.tsx
+++ b/packages/approval-process-designer-react/src/activity/CondiitionActivity.tsx
@@ -194,7 +194,7 @@ export const ConditionActivity: FC = ({
defaultValue={processNode?.title || `条件${(index || 0) + 1}`}
onBlur={handleInputBlur}/> : <>
setEditing(true)}>{processNode?.title}
+ onClick={() => setEditing(true)}>{processNode?.title || `条件${(index || 0) + 1}`}
优先级{(index || 0) + 1}
diff --git a/packages/approval-process-designer-react/src/activity/RouteActivity.tsx b/packages/approval-process-designer-react/src/activity/RouteActivity.tsx
index cdf5cc0..48e0efa 100644
--- a/packages/approval-process-designer-react/src/activity/RouteActivity.tsx
+++ b/packages/approval-process-designer-react/src/activity/RouteActivity.tsx
@@ -53,7 +53,7 @@ export const RouteActivity: FC = ({children, processNode, ne
}
return <>
-
+
{children}
diff --git a/packages/approval-process-designer-react/src/container/ApprovalProcessDesigner.tsx b/packages/approval-process-designer-react/src/container/ApprovalProcessDesigner.tsx
index 62eaf3b..5debdb6 100644
--- a/packages/approval-process-designer-react/src/container/ApprovalProcessDesigner.tsx
+++ b/packages/approval-process-designer-react/src/container/ApprovalProcessDesigner.tsx
@@ -7,21 +7,25 @@ type ApprovalProcessDesignerProps = {
children?: React.ReactNode;
engine?: ApprovalProcessEngine
value?: any
+ onChange?: (value: any) => void
}
export const ApprovalProcessDesigner: FC = ({
children,
engine,
- value
+ value,
+ onChange
}) => {
let scopeEngine = engine;
if (!scopeEngine) {
scopeEngine = new ApprovalProcessEngine();
}
+ scopeEngine?.setOnchange(onChange)
+
useEffect(() => {
if (value) {
- scopeEngine.processNode.from(value)
+ scopeEngine.process.from(value)
}
}, [value])
diff --git a/packages/approval-process-designer-react/src/context.tsx b/packages/approval-process-designer-react/src/context.tsx
index 9ced82d..d7af28b 100644
--- a/packages/approval-process-designer-react/src/context.tsx
+++ b/packages/approval-process-designer-react/src/context.tsx
@@ -1,7 +1,10 @@
import {createContext} from "react";
import {ApprovalProcessEngine} from "./model/ApprovalProcessEngine";
import {IActivities} from "./types";
+import {ProcessNode} from "./model";
export const ApprovalProcessContext = createContext(null)
-export const ActivitiesContext = createContext(null)
\ No newline at end of file
+export const ActivitiesContext = createContext(null)
+
+export const ProcessNodeContext = createContext(null)
\ No newline at end of file
diff --git a/packages/approval-process-designer-react/src/hooks/index.tsx b/packages/approval-process-designer-react/src/hooks/index.tsx
index fab19a0..02ad761 100644
--- a/packages/approval-process-designer-react/src/hooks/index.tsx
+++ b/packages/approval-process-designer-react/src/hooks/index.tsx
@@ -1,2 +1,4 @@
export * from "./useProcessEngine"
-export * from "./useActivities"
\ No newline at end of file
+export * from "./useActivities"
+export * from "./useProcess"
+export * from "./useProcessNode"
\ No newline at end of file
diff --git a/packages/approval-process-designer-react/src/hooks/useProcess.tsx b/packages/approval-process-designer-react/src/hooks/useProcess.tsx
new file mode 100644
index 0000000..218038a
--- /dev/null
+++ b/packages/approval-process-designer-react/src/hooks/useProcess.tsx
@@ -0,0 +1,5 @@
+import {useProcessEngine} from "./useProcessEngine";
+
+export const useProcess = () => {
+ return useProcessEngine().process
+}
\ No newline at end of file
diff --git a/packages/approval-process-designer-react/src/hooks/useProcessNode.tsx b/packages/approval-process-designer-react/src/hooks/useProcessNode.tsx
index 3eeba09..f688dc2 100644
--- a/packages/approval-process-designer-react/src/hooks/useProcessNode.tsx
+++ b/packages/approval-process-designer-react/src/hooks/useProcessNode.tsx
@@ -1,5 +1,6 @@
-import {useProcessEngine} from "./useProcessEngine";
+import {useContext} from "react";
+import {ProcessNodeContext} from "../context";
export const useProcessNode = () => {
- return useProcessEngine().processNode
+ return useContext(ProcessNodeContext)
}
\ No newline at end of file
diff --git a/packages/approval-process-designer-react/src/index.ts b/packages/approval-process-designer-react/src/index.ts
index eedbe0d..e48baf9 100644
--- a/packages/approval-process-designer-react/src/index.ts
+++ b/packages/approval-process-designer-react/src/index.ts
@@ -4,4 +4,5 @@ export * from "./activity"
export * from "./widget"
export * from "./panel"
export * from "./types"
-export * from "./util"
\ No newline at end of file
+export * from "./util"
+export * from "./store"
\ No newline at end of file
diff --git a/packages/approval-process-designer-react/src/model/ApprovalProcessEngine.ts b/packages/approval-process-designer-react/src/model/ApprovalProcessEngine.ts
index 89f0af8..a3b5d57 100644
--- a/packages/approval-process-designer-react/src/model/ApprovalProcessEngine.ts
+++ b/packages/approval-process-designer-react/src/model/ApprovalProcessEngine.ts
@@ -1,16 +1,20 @@
import {ProcessNode} from "./ProcessNode";
-import {action, define, observable} from "@formily/reactive";
+import {define, observable} from "@formily/reactive";
import {GlobalStore} from "../store";
+import {DesignerCore} from "../util";
+import _ from "lodash";
interface IApprovalProcessEngine {
}
export class ApprovalProcessEngine {
- processNode: ProcessNode;
+ process: ProcessNode;
+ onChange?: (value: any) => void
constructor(engine?: IApprovalProcessEngine) {
- this.processNode = new ProcessNode({
+ this.process = new ProcessNode({
+ engine: this,
type: 'START',
componentName: 'StartActivity',
title: '开始'
@@ -20,11 +24,19 @@ export class ApprovalProcessEngine {
makeObservable() {
define(this, {
- processNode: observable,
+ process: observable,
addableActivityResources: observable.computed
})
}
+ handleChange = _.debounce((msg: any)=>{
+ this.onChange?.(DesignerCore.transformToSchema(this.process))
+ },100)
+
+ setOnchange(fn: (value: any) => void) {
+ this.onChange = fn
+ }
+
get addableActivityResources() {
return GlobalStore.getAddableActivityResources()
}
diff --git a/packages/approval-process-designer-react/src/model/ProcessNode.ts b/packages/approval-process-designer-react/src/model/ProcessNode.ts
index b42bcc7..3248b63 100644
--- a/packages/approval-process-designer-react/src/model/ProcessNode.ts
+++ b/packages/approval-process-designer-react/src/model/ProcessNode.ts
@@ -1,11 +1,14 @@
-import {define, observable} from "@formily/reactive";
+import {autorun, define, observable, observe, reaction} from "@formily/reactive";
import randomstring from "randomstring"
import _ from "lodash";
import {GlobalStore} from "../store";
+import {ApprovalProcessEngine} from "./ApprovalProcessEngine";
export type ProcessNodeType = 'START' | 'ROUTE' | 'CONDITION' | 'APPROVAL' | 'CC' | 'END'
export interface IProcessNode {
+ engine?: ApprovalProcessEngine
+ isSourceNode?: boolean
id?: string
type: ProcessNodeType
componentName?: string
@@ -19,6 +22,8 @@ export interface IProcessNode {
const ProcessNodes = new Map()
export class ProcessNode {
+ engine: ApprovalProcessEngine
+ isSourceNode: boolean
id: string
type: ProcessNodeType
componentName: string
@@ -30,6 +35,8 @@ export class ProcessNode {
props: any
constructor(node: IProcessNode, parentNode?: ProcessNode) {
+ this.engine = node.engine
+ this.isSourceNode = node.isSourceNode
this.id = node.id || `Activity_${randomstring.generate({
length: 10,
charset: 'alphabetic'
@@ -42,6 +49,7 @@ export class ProcessNode {
this.title = node.title
this.description = node.description
this.props = node.props
+ this.engine = parentNode?.engine
ProcessNodes.set(this.id, this)
if (node) {
@@ -52,10 +60,28 @@ export class ProcessNode {
makeObservable() {
define(this, {
+ prevNodeId: observable.ref,
+ title: observable.ref,
+ description: observable.ref,
nextNode: observable.ref,
children: observable.shallow,
props: observable
})
+
+ reaction(() => {
+ return this.prevNodeId + this.title + this.description + this.nextNode?.id + this.children.length
+ }, () => {
+ if (!this.isSourceNode) {
+ this.engine.handleChange(`${this.id} something changed`)
+ }
+ })
+
+ observe(this.props, (change) => {
+ if (!this.isSourceNode) {
+ this.engine.handleChange(`${this.id} props changed`)
+ }
+ })
+
}
setNextNode(node: ProcessNode) {
@@ -85,7 +111,14 @@ export class ProcessNode {
ProcessNodes.set(node.id, this)
this.id = node.id
}
+ this.type = node.type
+ this.componentName = node.componentName || node.type
+ this.title = node.title
+ this.description = node.description
this.props = node.props ?? {}
+ if (node.engine) {
+ this.engine = node.engine
+ }
if (node.nextNode) {
this.nextNode = new ProcessNode(node.nextNode, this)
diff --git a/packages/approval-process-designer-react/src/util.ts b/packages/approval-process-designer-react/src/util.ts
index 6c6d381..32b6096 100644
--- a/packages/approval-process-designer-react/src/util.ts
+++ b/packages/approval-process-designer-react/src/util.ts
@@ -6,6 +6,7 @@ export namespace DesignerCore {
export function createResource(resource: IResourceCreator): IResource {
return _.assign(resource, {
node: new ProcessNode({
+ isSourceNode: true,
type: resource.type,
componentName: resource.componentName,
title: resource.title,
@@ -14,4 +15,24 @@ export namespace DesignerCore {
})
})
}
+
+ export function transformToSchema(processNode: ProcessNode) {
+ function toSchema(processNode: ProcessNode) {
+ if (!processNode) {
+ return null
+ }
+ return {
+ id: processNode.id,
+ type: processNode.type,
+ componentName: processNode.componentName,
+ title: processNode.title,
+ description: processNode.description,
+ props: processNode.props,
+ nextNode: toSchema(processNode.nextNode),
+ children: processNode.children?.map(toSchema) || []
+ }
+ }
+
+ return toSchema(processNode)
+ }
}
\ No newline at end of file
diff --git a/packages/approval-process-designer-react/src/widget/ActivityWidget.tsx b/packages/approval-process-designer-react/src/widget/ActivityWidget.tsx
index 7ca9c6d..c8ddeef 100644
--- a/packages/approval-process-designer-react/src/widget/ActivityWidget.tsx
+++ b/packages/approval-process-designer-react/src/widget/ActivityWidget.tsx
@@ -4,6 +4,7 @@ import {observer} from "@formily/react";
import {useActivities} from "../hooks";
import {ActivityFC} from "../types";
import _ from "lodash"
+import {ProcessNodeContext} from "../context";
type ActivityWidgetProps = {
processNode: ProcessNode;
@@ -43,5 +44,5 @@ export const ActivityWidget: FC = observer(({
}
}
- return <>{handleRender()}>
+ return {handleRender()}
})
\ No newline at end of file
diff --git a/packages/approval-process-designer-react/src/widget/AddActivityItemWidget.tsx b/packages/approval-process-designer-react/src/widget/AddActivityItemWidget.tsx
index 2566441..9a0dd99 100644
--- a/packages/approval-process-designer-react/src/widget/AddActivityItemWidget.tsx
+++ b/packages/approval-process-designer-react/src/widget/AddActivityItemWidget.tsx
@@ -17,10 +17,14 @@ const ActivityCardWidgetStyled = styled('div')({
padding: '10px',
boxSizing: 'border-box',
background: 'rgba(17, 31, 44, 0.02)',
+ gap: '8px',
[`&:hover`]: {
background: '#FFFFFF',
border: '1px solid #ecedef',
boxShadow: '0 2px 8px 0 rgba(17, 31, 44, 0.08)'
+ },
+ '.activity-icon': {
+ fontSize: '28px'
}
})
@@ -41,7 +45,7 @@ export const AddActivityItemWidget: FC = ({
processNode.setNextNode(activity?.node.clone(processNode))
}
return
-
+
{resource?.title}
}
\ No newline at end of file
diff --git a/packages/approval-process-designer-react/src/widget/ProcessWidget.tsx b/packages/approval-process-designer-react/src/widget/ProcessWidget.tsx
index 84e368d..b51bd61 100644
--- a/packages/approval-process-designer-react/src/widget/ProcessWidget.tsx
+++ b/packages/approval-process-designer-react/src/widget/ProcessWidget.tsx
@@ -1,7 +1,7 @@
import {IActivities} from "../types";
import React, {FC, useEffect} from "react";
import {ActivityWidget} from "./ActivityWidget";
-import {useProcessNode} from "../hooks/useProcessNode";
+import {useProcess} from "../hooks/useProcess";
import {ActivitiesContext} from "../context";
import {EndActivity} from "../activity";
import styled from "@emotion/styled";
@@ -20,7 +20,7 @@ type ProcessWidgetProps = {
export const ProcessWidget: FC = ({
activities
}) => {
- const processNode = useProcessNode()
+ const processNode = useProcess()
GlobalStore.registerActivityResources(activities)