lu-lowcode-package-form 0.7.4 → 0.7.13

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.
package/dist/style.css CHANGED
@@ -1 +1 @@
1
- *,:before,:after{box-sizing:border-box;border-width:0;border-style:solid;border-color:#e5e7eb}:before,:after{--tw-content: ""}html,:host{line-height:1.5;-webkit-text-size-adjust:100%;-moz-tab-size:4;tab-size:4;font-family:ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji",Segoe UI Symbol,"Noto Color Emoji";font-feature-settings:normal;font-variation-settings:normal;-webkit-tap-highlight-color:transparent}body{margin:0;line-height:inherit}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-feature-settings:normal;font-variation-settings:normal;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}button,input,optgroup,select,textarea{font-family:inherit;font-feature-settings:inherit;font-variation-settings:inherit;font-size:100%;font-weight:inherit;line-height:inherit;letter-spacing:inherit;color:inherit;margin:0;padding:0}button,select{text-transform:none}button,input:where([type=button]),input:where([type=reset]),input:where([type=submit]){-webkit-appearance:button;background-color:transparent;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:baseline}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dl,dd,h1,h2,h3,h4,h5,h6,hr,figure,p,pre{margin:0}fieldset{margin:0;padding:0}legend{padding:0}ol,ul,menu{list-style:none;margin:0;padding:0}dialog{padding:0}textarea{resize:vertical}input::placeholder,textarea::placeholder{opacity:1;color:#9ca3af}button,[role=button]{cursor:pointer}:disabled{cursor:default}img,svg,video,canvas,audio,iframe,embed,object{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}[hidden]{display:none}*,:before,:after{--tw-border-spacing-x: 0;--tw-border-spacing-y: 0;--tw-translate-x: 0;--tw-translate-y: 0;--tw-rotate: 0;--tw-skew-x: 0;--tw-skew-y: 0;--tw-scale-x: 1;--tw-scale-y: 1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness: proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width: 0px;--tw-ring-offset-color: #fff;--tw-ring-color: rgb(59 130 246 / .5);--tw-ring-offset-shadow: 0 0 #0000;--tw-ring-shadow: 0 0 #0000;--tw-shadow: 0 0 #0000;--tw-shadow-colored: 0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }::backdrop{--tw-border-spacing-x: 0;--tw-border-spacing-y: 0;--tw-translate-x: 0;--tw-translate-y: 0;--tw-rotate: 0;--tw-skew-x: 0;--tw-skew-y: 0;--tw-scale-x: 1;--tw-scale-y: 1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness: proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width: 0px;--tw-ring-offset-color: #fff;--tw-ring-color: rgb(59 130 246 / .5);--tw-ring-offset-shadow: 0 0 #0000;--tw-ring-shadow: 0 0 #0000;--tw-shadow: 0 0 #0000;--tw-shadow-colored: 0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }.relative{position:relative}.ml-2{margin-left:.5rem}.ml-4{margin-left:1rem}.mr-2{margin-right:.5rem}.box-border{box-sizing:border-box}.flex{display:flex}.h-8{height:2rem}.h-full{height:100%}.min-h-5{min-height:1.25rem}.w-\[960px\]{width:960px}.w-full{width:100%}.flex-col{flex-direction:column}.items-center{align-items:center}.items-stretch{align-items:stretch}.justify-between{justify-content:space-between}.overflow-auto{overflow:auto}.rounded{border-radius:.25rem}.bg-slate-100{--tw-bg-opacity: 1;background-color:rgb(241 245 249 / var(--tw-bg-opacity))}.p-6{padding:1.5rem}.pb-10{padding-bottom:2.5rem}.text-sm{font-size:.875rem;line-height:1.25rem}.text-xs{font-size:.75rem;line-height:1rem}.text-\[\#1890ff\]{--tw-text-opacity: 1;color:rgb(24 144 255 / var(--tw-text-opacity))}.text-gray-200{--tw-text-opacity: 1;color:rgb(229 231 235 / var(--tw-text-opacity))}.text-gray-500{--tw-text-opacity: 1;color:rgb(107 114 128 / var(--tw-text-opacity))}.filter{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.hover\:text-\[\#1890ff\]:hover{--tw-text-opacity: 1;color:rgb(24 144 255 / var(--tw-text-opacity))}.hover\:text-red-500:hover{--tw-text-opacity: 1;color:rgb(239 68 68 / var(--tw-text-opacity))}
1
+ *,:before,:after{box-sizing:border-box;border-width:0;border-style:solid;border-color:#e5e7eb}:before,:after{--tw-content: ""}html,:host{line-height:1.5;-webkit-text-size-adjust:100%;-moz-tab-size:4;tab-size:4;font-family:ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji",Segoe UI Symbol,"Noto Color Emoji";font-feature-settings:normal;font-variation-settings:normal;-webkit-tap-highlight-color:transparent}body{margin:0;line-height:inherit}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-feature-settings:normal;font-variation-settings:normal;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}button,input,optgroup,select,textarea{font-family:inherit;font-feature-settings:inherit;font-variation-settings:inherit;font-size:100%;font-weight:inherit;line-height:inherit;letter-spacing:inherit;color:inherit;margin:0;padding:0}button,select{text-transform:none}button,input:where([type=button]),input:where([type=reset]),input:where([type=submit]){-webkit-appearance:button;background-color:transparent;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:baseline}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dl,dd,h1,h2,h3,h4,h5,h6,hr,figure,p,pre{margin:0}fieldset{margin:0;padding:0}legend{padding:0}ol,ul,menu{list-style:none;margin:0;padding:0}dialog{padding:0}textarea{resize:vertical}input::placeholder,textarea::placeholder{opacity:1;color:#9ca3af}button,[role=button]{cursor:pointer}:disabled{cursor:default}img,svg,video,canvas,audio,iframe,embed,object{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}[hidden]{display:none}*,:before,:after{--tw-border-spacing-x: 0;--tw-border-spacing-y: 0;--tw-translate-x: 0;--tw-translate-y: 0;--tw-rotate: 0;--tw-skew-x: 0;--tw-skew-y: 0;--tw-scale-x: 1;--tw-scale-y: 1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness: proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width: 0px;--tw-ring-offset-color: #fff;--tw-ring-color: rgb(59 130 246 / .5);--tw-ring-offset-shadow: 0 0 #0000;--tw-ring-shadow: 0 0 #0000;--tw-shadow: 0 0 #0000;--tw-shadow-colored: 0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }::backdrop{--tw-border-spacing-x: 0;--tw-border-spacing-y: 0;--tw-translate-x: 0;--tw-translate-y: 0;--tw-rotate: 0;--tw-skew-x: 0;--tw-skew-y: 0;--tw-scale-x: 1;--tw-scale-y: 1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness: proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width: 0px;--tw-ring-offset-color: #fff;--tw-ring-color: rgb(59 130 246 / .5);--tw-ring-offset-shadow: 0 0 #0000;--tw-ring-shadow: 0 0 #0000;--tw-shadow: 0 0 #0000;--tw-shadow-colored: 0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }.relative{position:relative}.mb-5{margin-bottom:1.25rem}.ml-2{margin-left:.5rem}.ml-4{margin-left:1rem}.mr-2{margin-right:.5rem}.box-border{box-sizing:border-box}.flex{display:flex}.h-11{height:2.75rem}.h-8{height:2rem}.h-full{height:100%}.min-h-5{min-height:1.25rem}.w-\[960px\]{width:960px}.w-full{width:100%}.flex-col{flex-direction:column}.items-center{align-items:center}.items-stretch{align-items:stretch}.justify-between{justify-content:space-between}.overflow-auto{overflow:auto}.rounded{border-radius:.25rem}.border-b{border-bottom-width:1px}.bg-slate-100{--tw-bg-opacity: 1;background-color:rgb(241 245 249 / var(--tw-bg-opacity))}.p-6{padding:1.5rem}.pb-10{padding-bottom:2.5rem}.text-lg{font-size:1.125rem;line-height:1.75rem}.text-sm{font-size:.875rem;line-height:1.25rem}.text-xs{font-size:.75rem;line-height:1rem}.font-medium{font-weight:500}.text-\[\#1890ff\]{--tw-text-opacity: 1;color:rgb(24 144 255 / var(--tw-text-opacity))}.text-gray-200{--tw-text-opacity: 1;color:rgb(229 231 235 / var(--tw-text-opacity))}.text-gray-500{--tw-text-opacity: 1;color:rgb(107 114 128 / var(--tw-text-opacity))}.filter{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.hover\:text-\[\#1890ff\]:hover{--tw-text-opacity: 1;color:rgb(24 144 255 / var(--tw-text-opacity))}.hover\:text-red-500:hover{--tw-text-opacity: 1;color:rgb(239 68 68 / var(--tw-text-opacity))}
package/package.json CHANGED
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "lu-lowcode-package-form",
3
- "version": "0.7.4",
3
+ "version": "0.7.13",
4
4
  "dependencies": {
5
- "@ant-design/icons": "^5.3.7",
5
+ "@ant-design/icons": "^4.8.1",
6
6
  "@testing-library/jest-dom": "^5.17.0",
7
7
  "@testing-library/react": "^13.4.0",
8
8
  "@testing-library/user-event": "^13.5.0",
9
- "antd": "^5.18.0",
9
+ "antd": "^5.13.2",
10
10
  "web-vitals": "^2.1.4"
11
11
  },
12
12
  "main": "dist/index.cjs.js",
package/src/App.jsx CHANGED
@@ -1,6 +1,7 @@
1
- import { FormContainer, Field,FormContainerWrapper } from './components';
1
+ import { FormContainer, Field,FormContainerWrapper , Layout } from './components';
2
2
  import './App.css';
3
3
  import { Button } from 'antd';
4
+ import React from 'react';
4
5
 
5
6
  const treeData = [
6
7
  {
@@ -19,19 +20,47 @@ const treeData = [
19
20
  ];
20
21
 
21
22
  function App() {
23
+ const formRef = React.createRef();
24
+ const [cols, setCols] = React.useState(1);
25
+
26
+ const getFormFields = () => {
27
+ console.log("formRef?.current",formRef)
28
+ const formData = formRef?.current?.formRef?.getFieldsValue();
29
+ console.log("formData",formData);
30
+ }
31
+ const setFormFields = () => {
32
+ formRef?.current?.formRef?.setFieldsValue({
33
+ remark11:"{\"label\": \"解决方案部1112\", \"value\": 11}",
34
+ remark12:"[{\"label\": \"水电费\", \"value\": 2}]",
35
+ })
36
+ }
37
+ const handleCols = () => {
38
+ setCols(cols + 1)
39
+ }
22
40
  return (
23
41
 
24
42
  <div className="App flex flex-col items-center">
25
43
  <div className='w-[960px] rounded bg-slate-100 flex flex-col items-center pb-10'>
26
- <FormContainerWrapper cols={1} className="" >
44
+ <FormContainerWrapper cols={cols} className="" ref={formRef} >
27
45
  <Field.Input label="分组名" __id="title" />
28
46
  <Field.TreeSelect label="分组名" __id="title11"></Field.TreeSelect>
29
47
  <Field.CodeMachine label="角色编号" prompt="" __id="code" />
30
48
  <Field.Input label="角色名称" __id="name" />
49
+ <Layout.FormRow _componentName="Layout.FormRow" layout={'1,1,1'}>
50
+ <Field.Input label="角色名称布局" __id="name1" />
51
+ <Field.Input label="角色名称布局2" __id="name2" />
52
+ <Field.Input label="角色名称布局3" __id="name3" />
53
+ </Layout.FormRow>
31
54
  <Field.CheckboxTree label="角色权限" __id="permissions" addRoot={false} treeData={treeData} />
32
- <Field.TextArea label="备注" __id="remark" />
55
+ <Layout.FormGroupTitle _componentName="Layout.FormGroupTitle" title={"关联信息"}/>
56
+ <Field.WithSingleSelect label="测试关联单选" options={[{ label: '选项1', value: '1' }, { label: '选项2', value: '2' }]} __id="remark11" />
57
+ <Field.WithMultipleSelect label="测试关联多选" options={[{ label: '选项1', value: '1' }, { label: '选项2', value: '2' }]} __id="remark12" />
58
+ <Layout.FormRow _componentName="Layout.FormRow"> <Field.TextArea label="备注" __id="remark" /></Layout.FormRow>
59
+
33
60
  </FormContainerWrapper>
34
- <Button type="primary">Button</Button>
61
+ <Button type="primary" onClick={getFormFields}>GetValues</Button>
62
+ <Button type="primary" onClick={setFormFields}>SetValues</Button>
63
+ <Button type="primary" onClick={handleCols}>UpdateCol</Button>
35
64
  </div>
36
65
 
37
66
  </div>
@@ -1,2 +1,4 @@
1
1
  export { default as TreeSelect } from './tree-select.jsx';
2
- export { default as Select } from './select.jsx';
2
+ export { Select, WithSingleSelect,WithMultipleSelect } from './select.jsx';
3
+
4
+
@@ -1,9 +1,9 @@
1
- import { Select as OriginalSelect } from "antd";
1
+ import { Select as OriginalSelect } from "antd";
2
2
 
3
- import {BaseWrapper } from "../base"
4
- import React,{useEffect,useState} from 'react';
3
+ import { BaseWrapper } from "../base"
4
+ import React, { useEffect, useState } from 'react';
5
5
 
6
- const Select = ({ request, option_label = "label", option_value="id", disabledValue, callError, options , ...props }) => {
6
+ const Select = ({ request, option_label = "label", option_value = "id", disabledValue, callError, options, ...props }) => {
7
7
  // const [firstLoad, setFirstLoad] = React.useState(false)
8
8
  const [nOptions, setNOptions] = React.useState([])
9
9
  useEffect(() => {
@@ -24,16 +24,75 @@ const Select = ({ request, option_label = "label", option_value="id", disabledVa
24
24
 
25
25
  if (options && options.length > 0) {
26
26
  setNOptions(options)
27
- }
27
+ }
28
+
28
29
 
29
-
30
30
  // setFirstLoad(true)
31
31
  }
32
- return (
33
- <BaseWrapper {...props}>
34
- <OriginalSelect {...props} options={nOptions} />
35
- </BaseWrapper>
36
- )
32
+ return (
33
+ <BaseWrapper {...props}>
34
+ <OriginalSelect {...props} options={nOptions} style={{ width: '100%' }} />
35
+ </BaseWrapper>
36
+ )
37
+ }
38
+
39
+ /**
40
+ * 关联单选组件
41
+ * @param {*}
42
+ * @returns
43
+ */
44
+ const WithSingleSelect = ({ onChange, value, ...props }) => {
45
+ const [nValue, setNValue] = React.useState("")
46
+
47
+ React.useEffect(() => {
48
+ if(value) {
49
+ try {
50
+ value = JSON.parse(value)
51
+ setNValue(value.label)
52
+ } catch (error) {
53
+
54
+ }
55
+ }
56
+ }, [value])
57
+
58
+
59
+ const onWithSelectChange = (_value, _option) => {
60
+ onChange && typeof onChange == "function" && onChange(JSON.stringify(_option))
61
+ setNValue(_option.label)
62
+ }
63
+ return (
64
+ <Select {...props} onChange={onWithSelectChange} value={nValue} mode="single" />
65
+ )
66
+ }
67
+
68
+ /**
69
+ * 关联多选组件
70
+ * @param {*}
71
+ * @returns
72
+ */
73
+ const WithMultipleSelect = ({ onChange, value, ...props }) => {
74
+ const [nValue, setNValue] = React.useState([])
75
+
76
+
77
+ React.useEffect(() => {
78
+ if (value) {
79
+ try {
80
+ value = JSON.parse(value)
81
+ if (Array.isArray(value)) setNValue(value)
82
+ } catch (error) {
83
+
84
+ }
85
+ }
86
+ }, [value])
87
+
88
+ const onWithSelectChange = (_value, _option) => {
89
+ onChange && typeof onChange == "function" && onChange(JSON.stringify(_option))
90
+ const selectLabels = _option.map(item => item.label);
91
+ setNValue(_option)
92
+ }
93
+ return (
94
+ <Select {...props} onChange={onWithSelectChange} value={nValue} mode="multiple" />
95
+ )
37
96
  }
38
97
 
39
- export default Select ;
98
+ export { WithSingleSelect, WithMultipleSelect, Select };
@@ -1,208 +1,180 @@
1
1
  import React, { forwardRef, useEffect } from "react";
2
-
3
2
  import { Form, Row, Col } from "antd";
4
3
 
5
- function debounce(func, wait) {
6
- let timeout;
7
- return function (...args) {
8
- clearTimeout(timeout);
9
- timeout = setTimeout(() => func.apply(this, args), wait);
10
- }
11
- }
12
- function groupArray(array, groupLength) {
13
- console.log("groupArray array", array.length)
14
- const newArray = [];
15
- let tmpArray = [];
16
-
17
- const fillReactElement = (groupLength, array) => {
18
- const diff = groupLength - array.length;
19
- array.push(...new Array(diff).fill(React.createElement('div')));
4
+ import {debounce } from 'lodash';
5
+
6
+
7
+ function batchElements(elements, groupSize) {
8
+ const groupedElements = [];
9
+ let tempArray = [];
10
+
11
+ const fillWithReactElement = (size, array) => {
12
+ const missingElementsCount = size - array.length;
13
+ array.push(...new Array(missingElementsCount).fill(React.createElement('div')));
20
14
  };
21
15
 
22
- for (const currNode of array) {
23
- const { cols = 1 } = currNode?.props || {};
24
- tmpArray.push(currNode);
25
-
26
- if (tmpArray.length === groupLength) {
27
- newArray.push(tmpArray);
28
- tmpArray = [];
29
- } else if (tmpArray.length > groupLength) {
30
- fillReactElement(groupLength, tmpArray);
31
- newArray.push(tmpArray);
32
- tmpArray = [currNode];
16
+ for (const element of elements) {
17
+ const { _componentName } = element?.props || {};
18
+
19
+ if (_componentName && _componentName.startsWith('Layout')) {
20
+ if (tempArray.length > 0) {
21
+ fillWithReactElement(groupSize, tempArray);
22
+ groupedElements.push(tempArray);
23
+ tempArray = [];
24
+ }
25
+ groupedElements.push([element]);
26
+ } else {
27
+ tempArray.push(element);
28
+ if (tempArray.length === groupSize) {
29
+ groupedElements.push(tempArray);
30
+ tempArray = [];
31
+ }
33
32
  }
34
33
  }
35
34
 
36
- if (tmpArray.length > 0) {
37
- fillReactElement(groupLength, tmpArray);
38
- newArray.push(tmpArray);
35
+ if (tempArray.length > 0) {
36
+ fillWithReactElement(groupSize, tempArray);
37
+ groupedElements.push(tempArray);
39
38
  }
40
39
 
41
- return newArray;
40
+ return groupedElements;
42
41
  }
43
42
 
44
43
 
45
- const FormContainer = forwardRef(({ cols, children }, ref) => {
46
- cols = cols ? cols : 1
44
+ const FormContainer = forwardRef(({ cols = 1, children }, ref) => {
47
45
  const [form] = Form.useForm();
48
46
  const [formContent, setFormContent] = React.useState(null);
49
- const withMap = React.useRef(null);
50
- React.useImperativeHandle(ref, () => {
51
- return {
52
- formRef: form,
53
- initFieldsShow: initFieldsShow,
54
- }
55
- }, [])
47
+ const dependencyMap = React.useRef(null);
56
48
 
57
- useEffect(() => {
58
- }, [form])
49
+ React.useImperativeHandle(ref, () => ({
50
+ formRef: form,
51
+ initializeFieldVisibility,
52
+ }), []);
59
53
 
60
54
  useEffect(() => {
61
- initWithMap()
62
- setFormContent(getChildren())
63
- }, [])
64
-
65
-
66
- const initWithMap = () => {
67
- withMap.current = new Map();
68
- let childrenArray = React.Children.toArray(children);
69
- for (let i = 0; i < childrenArray.length; i++) {
70
- const { componentId, __id, _componentName, ...props } = childrenArray[i].props;
71
- const name = componentId || __id;
72
- withMap.current.set(name, {
73
- children: childrenArray.filter((item) => {
74
- return item.props.__withId == name || item.props.__withIds?.includes(name)
75
- }),
76
- show: true
55
+ initializeDependencyMap();
56
+ setFormContent(renderChildren());
57
+ }, [children, cols]);
58
+
59
+ const initializeDependencyMap = () => {
60
+ dependencyMap.current = new Map();
61
+ const childrenArray = React.Children.toArray(children);
62
+
63
+ childrenArray.forEach(child => {
64
+ const { componentId, __id, ...props } = child.props;
65
+ const identifier = componentId || __id;
66
+ dependencyMap.current.set(identifier, {
67
+ children: childrenArray.filter(item => item.props.__withId === identifier || item.props.__withIds?.includes(identifier)),
68
+ show: true,
77
69
  });
78
- }
79
-
80
- initFieldsShow();
70
+ });
81
71
 
82
- }
72
+ initializeFieldVisibility();
73
+ };
83
74
 
84
75
  // 初始化字段的显示状态
85
- const initFieldsShow = (reloadFields = false) => {
86
- const fieldsValues = form.getFieldsValue();
87
- withMap.current.keys().forEach(function (key) {
88
- computeNeedShow(key, fieldsValues)
89
- });
76
+ const initializeFieldVisibility = (reloadFields = false) => {
77
+ const fieldValues = form.getFieldsValue();
78
+ for (let key of dependencyMap.current.keys()) {
79
+ updateFieldVisibility(key, fieldValues);
80
+ }
90
81
 
91
- if (reloadFields) setFormContent(getChildren())
92
- }
82
+ if (reloadFields) setFormContent(renderChildren());
83
+ };
93
84
 
94
85
  // 计算是否显示
95
- const computeNeedShow = (name, fieldsValues) => {
86
+ const updateFieldVisibility = (identifier, fieldValues) => {
96
87
  let needRefresh = false;
97
- if (withMap.current.has(name)) {
98
- let withChildrens = withMap.current.get(name).children
99
- withChildrens.forEach((item) => {
100
- if (item.props.__withFunc && typeof item.props.__withFunc === 'function') {
101
- let childrenShow = item.props.__withFunc(fieldsValues);
102
- const name = item.props.componentId || item.props.__id;
103
- if (withMap.current.has(name)) {
104
- let childrenItem = withMap.current.get(name)
105
- if (childrenItem.show != childrenShow) {
106
- childrenItem.show = childrenShow
107
- withMap.current.set(name, childrenItem)
88
+ if (dependencyMap.current.has(identifier)) {
89
+ const dependentChildren = dependencyMap.current.get(identifier).children;
90
+ dependentChildren.forEach(child => {
91
+ if (child.props.__withFunc && typeof child.props.__withFunc === 'function') {
92
+ const childShouldBeVisible = child.props.__withFunc(fieldValues);
93
+ const childIdentifier = child.props.componentId || child.props.__id;
94
+ if (dependencyMap.current.has(childIdentifier)) {
95
+ const childData = dependencyMap.current.get(childIdentifier);
96
+ if (childData.show !== childShouldBeVisible) {
97
+ childData.show = childShouldBeVisible;
98
+ dependencyMap.current.set(childIdentifier, childData);
108
99
  needRefresh = true;
109
100
  }
110
101
  }
111
102
  }
112
- })
103
+ });
113
104
  }
114
- return needRefresh
115
- }
105
+ return needRefresh;
106
+ };
116
107
 
117
108
  const handleFieldsChange = debounce((changedFields, allFields) => {
118
- // 获得所有字段值
119
- const fieldsValues = form.getFieldsValue();
109
+ const fieldValues = form.getFieldsValue();
120
110
  let needRefresh = false;
121
- for (let index = 0; index < changedFields.length; index++) {
122
- const element = changedFields[index];
123
- if (element.name && element.name.length > 0)
124
- needRefresh = computeNeedShow(element.name[0], fieldsValues)
125
- }
111
+ changedFields.forEach(field => {
112
+ if (field.name && field.name.length > 0) {
113
+ needRefresh = updateFieldVisibility(field.name[0], fieldValues);
114
+ }
115
+ });
116
+
126
117
  if (needRefresh) {
127
- setFormContent(getChildren())
118
+ setFormContent(renderChildren());
128
119
  }
129
- }, 100); // 字段变化时会调用三次此函数,使用 100 毫秒的防抖时间
130
-
131
- const getChildren = () => {
132
- let childrenArray = React.Children.toArray(children);
133
- const newArray = groupArray(childrenArray.filter((item) => {
134
- const name = item.props.componentId || item.props.__id
135
- return withMap.current.has(name) && withMap.current.get(name).show
136
- }), cols);
137
- console.log("newArray", newArray)
138
- const result = newArray.map((childs) => {
139
- return (
140
- <Row
141
- key={childs?.[0]?.key}
142
- gutter={[24, 24]}
143
- >
144
- {childs.map((child) => {
145
- const { componentId, __id, _componentName, onChange, ...props } = child.props;
146
- const name = componentId || __id;
147
- const componentName = _componentName;
148
-
149
-
150
- // 占整行内容
151
- if (['FieldLayout', 'FieldSubTable'].includes(componentName)) {
152
- // console.log('q=>child', child);
153
- return (
154
- <Col key={name} span={24} style={{ marginBottom: 0 }} >
120
+ }, 100);
121
+
122
+ const renderChildren = () => {
123
+ const childrenArray = React.Children.toArray(children);
124
+ const groupedChildren = batchElements(
125
+ childrenArray.filter(child => {
126
+ const identifier = child.props.componentId || child.props.__id;
127
+ return dependencyMap.current.has(identifier) && dependencyMap.current.get(identifier).show;
128
+ }),
129
+ cols
130
+ );
131
+
132
+ return groupedChildren.map((group,index) => (
133
+ <Row key={`row-${index}`} gutter={[24, 24]}>
134
+ {group.map((child, index) => {
135
+ const { componentId, __id, _componentName, ...props } = child.props;
136
+ const identifier = componentId || __id;
137
+ const isLayoutComponent = _componentName && _componentName.startsWith('Layout');
138
+
139
+ return (
140
+ <Col key={identifier || `col-${index}`} span={isLayoutComponent ? 24 : 24 / group.length} style={{ marginBottom: 0 }}>
141
+ {isLayoutComponent ? (
142
+ child
143
+ ) : (
144
+ <Form.Item
145
+ style={{ marginBottom: 0 }}
146
+ label=""
147
+ name={identifier}
148
+ rules={[{ required: props.isRequired, message: `${props.title}不能为空!` }]}
149
+ >
155
150
  {child}
156
- </Col>
157
- );
158
- }
159
- // console.log('child', child)
160
- return (
161
- <Col key={name} span={24 / childs.length} >
162
- {name && (
163
- <Form.Item
164
- style={{ marginBottom: 0 }}
165
- label=""
166
- name={name}
167
- rules={[{ required: props.isRequired, message: `${props.title}不能为空!` }]}
168
- >
169
-
170
- {child}
171
- </Form.Item>
172
- )}
173
- </Col>
174
- );
175
- })}
176
- </Row>
177
- );
178
- });
179
-
180
- console.log("result", newArray)
181
- return result;
151
+ </Form.Item>
152
+ )}
153
+ </Col>
154
+ );
155
+ })}
156
+ </Row>
157
+ ));
182
158
  };
159
+
183
160
  return (
184
161
  <Form form={form} className="form-container p-6 w-full h-full box-border overflow-auto" onFieldsChange={handleFieldsChange}>
185
162
  {formContent}
186
163
  </Form>
187
- )
164
+ );
188
165
  });
189
166
 
190
-
191
- /**
192
- * 简单包装,不做任何处理
193
- * 部分组件ref比较特殊,包一层会解决这个问题
194
- */
195
- export function withWrap(Comp) {
196
- return forwardRef((props, ref) => {
197
- return <Comp {...props} ref={ref} forwardedRef={ref} />;
198
- });
167
+ export function withWrap(Component) {
168
+ return forwardRef((props, ref) => <Component {...props} ref={ref} forwardedRef={ref} />);
199
169
  }
200
170
 
201
- const FormContainerClass = (props) => {
202
- const { forwardedRef, ...otherProps } = props;
203
- return <FormContainer {...otherProps} ref={forwardedRef} />
171
+ export class FormContainerClass extends React.PureComponent{
172
+ render() {
173
+ const { forwardedRef, ...otherProps } = this.props;
174
+ return <FormContainer {...otherProps} ref={forwardedRef} />
175
+ }
204
176
  }
177
+ const FormContainerWrapper = withWrap(({ forwardedRef, ...props }) => <FormContainer {...props} ref={forwardedRef} />);
205
178
 
206
- const FormContainerWrapper = withWrap(FormContainerClass);
207
-
208
- export { FormContainer, FormContainerWrapper }
179
+ export { LayoutFormRow, LayoutFormGroupTitle } from './layout';
180
+ export { FormContainer, FormContainerWrapper };
@@ -0,0 +1,6 @@
1
+ const FormGroupTitle = ({ title }) => {
2
+ return (title? <div className="h-11 border-b flex items-center text-lg font-medium mb-5 ">{title}</div>: null )
3
+ };
4
+
5
+ export default FormGroupTitle;
6
+
@@ -0,0 +1,48 @@
1
+ import React, { useMemo } from 'react';
2
+ import { Form, Row, Col } from 'antd';
3
+
4
+ const LayoutFormRow = ({ children, layout }) => {
5
+ layout = layout || '1';
6
+ const getColSpan = (layoutStr) => {
7
+ const layoutArray = layoutStr.split(',').map(Number);
8
+ const totalCols = 24;
9
+ return layoutArray.map(num => (num / layoutArray.reduce((a, b) => a + b)) * totalCols);
10
+ };
11
+
12
+ const colSpans = useMemo(() => getColSpan(layout), [layout]);
13
+
14
+ console.log("colSpans", colSpans)
15
+
16
+ const formItems = useMemo(() => {
17
+ return React.Children.toArray(children).map((child, index) => {
18
+ const props = child.props;
19
+ const name = props?.componentId || props?.__id;
20
+
21
+ if (name) {
22
+ return (
23
+ colSpans?.[index] && <Col span={colSpans[index]} key={index}>
24
+ <Form.Item
25
+ style={{ marginBottom: 0 }}
26
+ label=""
27
+ key={`${name}-form-item`}
28
+ name={name}
29
+ rules={[{ required: props.isRequired, message: `${props.title}不能为空!` }]}
30
+ >
31
+ {child}
32
+ </Form.Item>
33
+ </Col>
34
+ );
35
+ } else {
36
+ return (
37
+ colSpans?.[index] && <Col span={colSpans[index]} key={index}>
38
+ {child}
39
+ </Col>
40
+ );
41
+ }
42
+ });
43
+ }, [children, colSpans]);
44
+
45
+ return <Row gutter={24}>{formItems}</Row>;
46
+ };
47
+
48
+ export default LayoutFormRow;
@@ -0,0 +1,2 @@
1
+ export { default as LayoutFormRow } from './form-row';
2
+ export { default as LayoutFormGroupTitle } from './form-group-title';
@@ -1,8 +1,8 @@
1
1
  import { Input, TextArea, Password, Search ,CodeMachine} from './field/input/index.jsx'
2
2
  import '../App.css';
3
- import { TreeSelect, Select } from './field/select/index.jsx'
3
+ import { TreeSelect, Select, WithSingleSelect,WithMultipleSelect } from './field/select/index.jsx'
4
4
  import Custom from './field/custom/index.jsx'
5
- import { FormContainer, FormContainerWrapper } from './form-container/index.jsx'
5
+ import { FormContainer, FormContainerWrapper,LayoutFormRow,LayoutFormGroupTitle } from './form-container/index.jsx'
6
6
  import { Checkbox ,CheckboxTree } from './field/checkbox/index.jsx'
7
7
  import { default as RadioGrop } from './field/radio/index.jsx'
8
8
  const Field = {
@@ -12,11 +12,16 @@ const Field = {
12
12
  Search,
13
13
  TreeSelect,
14
14
  Select,
15
+ WithSingleSelect,
16
+ WithMultipleSelect,
15
17
  CodeMachine,
16
18
  Checkbox,
17
19
  CheckboxTree,
18
20
  RadioGrop,
19
21
  Custom,
20
22
  }
21
-
22
- export { FormContainer, Field ,FormContainerWrapper }
23
+ const Layout = {
24
+ FormRow: LayoutFormRow,
25
+ FormGroupTitle: LayoutFormGroupTitle
26
+ }
27
+ export { FormContainer, Field ,FormContainerWrapper,Layout }