@coding-flow/flow-design 0.1.2 → 0.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -49,6 +49,25 @@ const AdviceStrategy = ()=>{
49
49
  })
50
50
  })
51
51
  })
52
+ }),
53
+ /*#__PURE__*/ jsx(Form.Item, {
54
+ label: /*#__PURE__*/ jsx(FieldTip, {
55
+ label: "隐藏审批意见",
56
+ description: "开启后,审批时不展示审批意见输入框,仅弹框确认。"
57
+ }),
58
+ name: [
59
+ "AdviceStrategy",
60
+ "adviceHidden"
61
+ ],
62
+ children: /*#__PURE__*/ jsx(Field, {
63
+ name: "AdviceStrategy.adviceHidden",
64
+ render: ({ field: { value, onChange } })=>/*#__PURE__*/ jsx(Fragment, {
65
+ children: /*#__PURE__*/ jsx(Switch, {
66
+ value: value,
67
+ onChange: onChange
68
+ })
69
+ })
70
+ })
52
71
  })
53
72
  ]
54
73
  });
@@ -7,8 +7,7 @@ const StartNodeRegistry = {
7
7
  selectable: false,
8
8
  copyDisable: true,
9
9
  expandable: false,
10
- addDisable: true,
11
- editTitleDisable: true
10
+ addDisable: true
12
11
  },
13
12
  info: {
14
13
  icon: 'START',
@@ -1,6 +1,8 @@
1
1
  import { jsx, jsxs } from "react/jsx-runtime";
2
2
  import react from "react";
3
+ import { InputNumber } from "antd";
3
4
  import { CardForm, Panel } from "@coding-flow/flow-pc-ui";
5
+ import { FieldTip } from "../../field-tip/index.js";
4
6
  import { InterferePanel } from "../panels/workflow/interfere.js";
5
7
  import { UrgePanel } from "../panels/workflow/urge.js";
6
8
  import { useDesignContext } from "../hooks/use-design-context.js";
@@ -12,22 +14,37 @@ const TabSetting = ()=>{
12
14
  const workflowStrategyManager = new WorkflowStrategyManager();
13
15
  const resetFieldsValue = ()=>{
14
16
  const formData = workflowStrategyManager.toRender(state.workflow.strategies);
15
- form.setFieldsValue(formData);
17
+ form.setFieldsValue({
18
+ ...formData,
19
+ maxNestDepth: state.workflow.maxNestDepth ?? 10
20
+ });
16
21
  };
17
22
  react.useEffect(()=>{
18
23
  resetFieldsValue();
19
24
  }, [
20
- state.workflow.strategies
25
+ state.workflow.strategies,
26
+ state.workflow.maxNestDepth
21
27
  ]);
22
28
  react.useEffect(()=>{
23
29
  form.resetFields();
24
30
  resetFieldsValue();
25
31
  formActionContext.addAction({
26
- save: ()=>workflowStrategyManager.toData(form.getFieldsValue()),
32
+ save: ()=>{
33
+ const formValues = form.getFieldsValue();
34
+ const strategyData = workflowStrategyManager.toData(formValues);
35
+ return {
36
+ ...strategyData || {},
37
+ maxNestDepth: formValues.maxNestDepth
38
+ };
39
+ },
27
40
  key: ()=>'setting',
28
41
  validate: ()=>new Promise((resolve, reject)=>{
29
42
  form.validateFields().then((values)=>{
30
- resolve(workflowStrategyManager.toData(values));
43
+ const strategyData = workflowStrategyManager.toData(values);
44
+ resolve({
45
+ ...strategyData || {},
46
+ maxNestDepth: values.maxNestDepth
47
+ });
31
48
  }).catch(reject);
32
49
  })
33
50
  });
@@ -42,6 +59,26 @@ const TabSetting = ()=>{
42
59
  }),
43
60
  /*#__PURE__*/ jsx(UrgePanel, {
44
61
  form: form
62
+ }),
63
+ /*#__PURE__*/ jsx(CardForm, {
64
+ form: form,
65
+ title: "循环防护配置",
66
+ children: /*#__PURE__*/ jsx(CardForm.Item, {
67
+ name: [
68
+ "maxNestDepth"
69
+ ],
70
+ label: /*#__PURE__*/ jsx(FieldTip, {
71
+ label: "最大嵌套深度",
72
+ description: "子流程嵌套层数上限(默认 10)。运行期创建子流程时沿父链统计嵌套层数,超过该值将拒绝创建,用于兜底防护子流程创建自身/祖先流程等循环配置导致的无限递归。"
73
+ }),
74
+ children: /*#__PURE__*/ jsx(InputNumber, {
75
+ min: 1,
76
+ max: 100,
77
+ style: {
78
+ width: '100%'
79
+ }
80
+ })
81
+ })
45
82
  })
46
83
  ]
47
84
  });
@@ -16,6 +16,7 @@ export interface Workflow {
16
16
  operatorCreateScript: string;
17
17
  strategies?: any[];
18
18
  nodes?: FlowNode[];
19
+ maxNestDepth?: number;
19
20
  }
20
21
  export interface FlowNode {
21
22
  id: string;
@@ -2,7 +2,7 @@ import { Fragment, jsx } from "react/jsx-runtime";
2
2
  import react from "react";
3
3
  import { FormDataList } from "./components/list.js";
4
4
  import { Provider } from "react-redux";
5
- import { formDataStore } from "./store.js";
5
+ import { createFormDataStore } from "./store.js";
6
6
  import { FormDataContext } from "./context/index.js";
7
7
  import { createFormDataContext, useFormDataContext } from "./hooks/use-form-data-context.js";
8
8
  const FormDataContent = (props)=>{
@@ -28,12 +28,16 @@ const FormDataContextContent = (props)=>{
28
28
  })
29
29
  });
30
30
  };
31
- const FormDataReduxContent = (props)=>/*#__PURE__*/ jsx(Provider, {
32
- store: formDataStore,
31
+ const FormDataReduxContent = (props)=>{
32
+ const storeRef = react.useRef(void 0);
33
+ if (!storeRef.current) storeRef.current = createFormDataStore();
34
+ return /*#__PURE__*/ jsx(Provider, {
35
+ store: storeRef.current,
33
36
  children: /*#__PURE__*/ jsx(FormDataContextContent, {
34
37
  ...props
35
38
  })
36
39
  });
40
+ };
37
41
  const FormDataView = (props)=>{
38
42
  const form = props.form;
39
43
  if (form) return /*#__PURE__*/ jsx(FormDataReduxContent, {
@@ -5,11 +5,17 @@ export type FormDataStoreAction = {
5
5
  };
6
6
  export declare const formDataSlice: import("@reduxjs/toolkit").Slice<FormDataState, FormDataStoreAction, "formData", "formData", {}>;
7
7
  export declare const updateState: import("@reduxjs/toolkit").ActionCreatorWithPayload<Partial<FormDataState> | ((prev: FormDataState) => Partial<FormDataState>), "formData/updateState">;
8
- export declare const formDataStore: import("@reduxjs/toolkit").EnhancedStore<{
8
+ /**
9
+ * 按实例创建表单数据 store。
10
+ * 每个 FormDataView 使用独立的 store,避免多个子流程配置项共享模块级单例 store
11
+ * 导致表单数据互相覆盖、输入时被刷新。
12
+ */
13
+ export declare const createFormDataStore: () => import("@reduxjs/toolkit").EnhancedStore<{
9
14
  formData: FormDataState;
10
15
  }, import("redux").UnknownAction, import("@reduxjs/toolkit").Tuple<[import("redux").StoreEnhancer<{
11
16
  dispatch: import("redux-thunk").ThunkDispatch<{
12
17
  formData: FormDataState;
13
18
  }, undefined, import("redux").UnknownAction>;
14
19
  }>, import("redux").StoreEnhancer]>>;
15
- export type FormDataReduxState = ReturnType<typeof formDataStore.getState>;
20
+ export type FormDataStore = ReturnType<typeof createFormDataStore>;
21
+ export type FormDataReduxState = ReturnType<FormDataStore['getState']>;
@@ -13,9 +13,9 @@ const formDataSlice = createSlice({
13
13
  }
14
14
  });
15
15
  const { updateState } = formDataSlice.actions;
16
- const formDataStore = configureStore({
17
- reducer: {
18
- formData: formDataSlice.reducer
19
- }
20
- });
21
- export { formDataSlice, formDataStore, updateState };
16
+ const createFormDataStore = ()=>configureStore({
17
+ reducer: {
18
+ formData: formDataSlice.reducer
19
+ }
20
+ });
21
+ export { createFormDataStore, formDataSlice, updateState };
@@ -102,7 +102,7 @@ const SubProcessView = (props)=>{
102
102
  const [form] = Form.useForm();
103
103
  const subProcessPresenter = useSubProcessPresenter(props);
104
104
  react.useEffect(()=>{
105
- if (props.value) {
105
+ if (subProcessPresenter.isExternalChange(props.value)) {
106
106
  const data = subProcessPresenter.parserScript(props.value);
107
107
  form.resetFields();
108
108
  form.setFieldsValue({
@@ -1,7 +1,20 @@
1
1
  import { SubProcessFormValues, SubProcessViewProps } from "../typings";
2
2
  export declare class SubProcessPresenter {
3
3
  private readonly props;
4
+ /**
5
+ * 自身最后一次生成的脚本。
6
+ * 用于区分"自身编辑触发的脚本变更"与"外部脚本变更",
7
+ * 避免编辑回填表单后再次重置表单,导致输入时表单自动刷新。
8
+ */
9
+ private lastEmittedScript?;
4
10
  constructor(props: SubProcessViewProps);
11
+ /**
12
+ * 判断脚本变更是否来自外部(非自身编辑产生)。
13
+ * 仅外部变更才需要将脚本解析结果回填到表单。
14
+ *
15
+ * @param value 当前脚本内容
16
+ */
17
+ isExternalChange(value: string | undefined): boolean;
5
18
  parserScript(value: string): SubProcessFormValues;
6
19
  updateScript(values: SubProcessFormValues): void;
7
20
  private toFormData;
@@ -1,9 +1,14 @@
1
1
  import { GroovyScriptConvertorUtil } from "@coding-flow/flow-core";
2
2
  class SubProcessPresenter {
3
3
  props;
4
+ lastEmittedScript;
4
5
  constructor(props){
5
6
  this.props = props;
6
7
  }
8
+ isExternalChange(value) {
9
+ if (!value) return false;
10
+ return value !== this.lastEmittedScript;
11
+ }
7
12
  parserScript(value) {
8
13
  const meta = GroovyScriptConvertorUtil.getScriptMeta(value);
9
14
  if (!meta) return {
@@ -25,7 +30,9 @@ class SubProcessPresenter {
25
30
  };
26
31
  }
27
32
  updateScript(values) {
28
- this.props.onChange(this.toScript(values));
33
+ const script = this.toScript(values);
34
+ this.lastEmittedScript = script;
35
+ this.props.onChange(script);
29
36
  }
30
37
  toFormData(config) {
31
38
  if (config.formData) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@coding-flow/flow-design",
3
- "version": "0.1.2",
3
+ "version": "0.1.3",
4
4
  "description": "flow-engine design components ",
5
5
  "type": "module",
6
6
  "sideEffects": [
@@ -54,16 +54,16 @@
54
54
  "nanoid": "^5.1.6",
55
55
  "react-redux": "^9.2.0",
56
56
  "styled-components": "^5.3.11",
57
- "@coding-flow/flow-core": "0.1.2",
58
- "@coding-flow/flow-icons": "0.1.2",
59
- "@coding-flow/flow-pc-ui": "0.1.2",
60
- "@coding-flow/flow-types": "0.1.2"
57
+ "@coding-flow/flow-core": "0.1.3",
58
+ "@coding-flow/flow-icons": "0.1.3",
59
+ "@coding-flow/flow-pc-ui": "0.1.3",
60
+ "@coding-flow/flow-types": "0.1.3"
61
61
  },
62
62
  "devDependencies": {
63
63
  "@types/lodash-es": "^4.17.12",
64
64
  "@types/styled-components": "^5.1.36",
65
- "@coding-flow/flow-core": "0.1.2",
66
- "@coding-flow/flow-types": "0.1.2"
65
+ "@coding-flow/flow-core": "0.1.3",
66
+ "@coding-flow/flow-types": "0.1.3"
67
67
  },
68
68
  "scripts": {
69
69
  "build": "rslib build",