lu-lowcode-package-form 0.11.80 → 0.11.81
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/index.cjs.js +391 -343
- package/dist/index.es.js +50256 -42721
- package/dist/style.css +7 -1
- package/package.json +2 -2
- package/src/App copy 5.jsx +1027 -0
- package/src/App.jsx +491 -570
- package/src/components/editor/index.jsx +2 -1
- package/src/components/editor/quill2.jsx +88 -0
- package/src/components/field/select/search-select.jsx +1 -1
- package/src/components/form-container/index.jsx +70 -16
@@ -1,4 +1,5 @@
|
|
1
1
|
export {default as EditorQuill} from './quill'
|
2
2
|
export { default as EditorWang } from './wang'
|
3
3
|
export { default as EditorWang2 } from './wang2'
|
4
|
-
export { default as EditorWang3 } from './wang-demo'
|
4
|
+
export { default as EditorWang3 } from './wang-demo'
|
5
|
+
export { default as EditorQuill2 } from './quill2'
|
@@ -0,0 +1,88 @@
|
|
1
|
+
import React, { useEffect, useRef } from 'react';
|
2
|
+
import Quill from 'quill';
|
3
|
+
import 'quill/dist/quill.snow.css'; // 引入 Quill 的主题样式
|
4
|
+
|
5
|
+
// 定义工具栏选项,可以根据需要自定义
|
6
|
+
const toolbarOptions = [
|
7
|
+
[{ 'header': [1, 2, 3, 4, 5, 6, false] }],
|
8
|
+
['bold', 'italic', 'underline', 'strike'], // 粗体、斜体、下划线、删除线
|
9
|
+
[{ 'list': 'ordered'}, { 'list': 'bullet' }], // 有序列表、无序列表
|
10
|
+
[{ 'script': 'sub'}, { 'script': 'super' }], // 上标、下标
|
11
|
+
[{ 'indent': '-1'}, { 'indent': '+1' }], // 缩进
|
12
|
+
[{ 'direction': 'rtl' }], // 文字方向
|
13
|
+
[{ 'size': ['small', false, 'large', 'huge'] }], // 字号
|
14
|
+
[{ 'color': [] }, { 'background': [] }], // 字体颜色、背景颜色
|
15
|
+
[{ 'font': [] }], // 字体
|
16
|
+
[{ 'align': [] }], // 对齐方式
|
17
|
+
['clean'], // 清除格式
|
18
|
+
['link', 'image', 'video'] // 链接、图片、视频
|
19
|
+
];
|
20
|
+
|
21
|
+
const QuillEditor = ({ value, onChange, placeholder = '请输入内容...', height = '300px' }) => {
|
22
|
+
const editorContainerRef = useRef(null); // Ref 指向编辑器的容器 div
|
23
|
+
const quillInstance = useRef(null);
|
24
|
+
|
25
|
+
useEffect(() => {
|
26
|
+
let quillEditorDiv; // Quill 实际初始化的 div
|
27
|
+
if (editorContainerRef.current && !quillInstance.current) {
|
28
|
+
// 创建一个 div 给 Quill 初始化,这样 Snow 主题的工具栏会和它关联
|
29
|
+
// Snow 主题通常会将工具栏放在编辑器 div 的前面
|
30
|
+
quillEditorDiv = document.createElement('div');
|
31
|
+
editorContainerRef.current.appendChild(quillEditorDiv);
|
32
|
+
|
33
|
+
quillInstance.current = new Quill(quillEditorDiv, {
|
34
|
+
modules: {
|
35
|
+
toolbar: toolbarOptions // 直接使用定义的工具栏选项
|
36
|
+
},
|
37
|
+
theme: 'snow',
|
38
|
+
placeholder: placeholder,
|
39
|
+
});
|
40
|
+
|
41
|
+
// 设置初始内容
|
42
|
+
if (value) {
|
43
|
+
quillInstance.current.clipboard.dangerouslyPasteHTML(value);
|
44
|
+
}
|
45
|
+
|
46
|
+
// 监听内容变化
|
47
|
+
quillInstance.current.on('text-change', (delta, oldDelta, source) => {
|
48
|
+
if (source === 'user') {
|
49
|
+
const html = quillInstance.current.root.innerHTML;
|
50
|
+
onChange?.(html);
|
51
|
+
}
|
52
|
+
});
|
53
|
+
}
|
54
|
+
|
55
|
+
return () => {
|
56
|
+
if (quillInstance.current) {
|
57
|
+
quillInstance.current.off('text-change');
|
58
|
+
quillInstance.current = null;
|
59
|
+
}
|
60
|
+
// 清理 editorContainerRef 内部所有由 Quill 创建的 DOM
|
61
|
+
if (editorContainerRef.current) {
|
62
|
+
editorContainerRef.current.innerHTML = '';
|
63
|
+
}
|
64
|
+
};
|
65
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
66
|
+
}, []); // 依赖项为空,确保只在挂载和卸载时运行
|
67
|
+
|
68
|
+
// 当外部传入的 value 变化时,更新编辑器内容
|
69
|
+
useEffect(() => {
|
70
|
+
if (quillInstance.current && value !== undefined) {
|
71
|
+
const currentEditorHTML = quillInstance.current.root.innerHTML;
|
72
|
+
if (value !== currentEditorHTML) {
|
73
|
+
const selection = quillInstance.current.getSelection();
|
74
|
+
quillInstance.current.clipboard.dangerouslyPasteHTML(value);
|
75
|
+
if (selection) {
|
76
|
+
// 尝试恢复光标位置,如果直接粘贴HTML导致光标丢失
|
77
|
+
quillInstance.current.setSelection(selection.index, selection.length);
|
78
|
+
}
|
79
|
+
}
|
80
|
+
}
|
81
|
+
}, [value]);
|
82
|
+
|
83
|
+
// editorContainerRef 的高度由 height prop 控制
|
84
|
+
// Quill 的 Snow 主题会自动在其内部管理编辑器区域和工具栏的布局
|
85
|
+
return <div ref={editorContainerRef} style={{ height: height }} />;
|
86
|
+
};
|
87
|
+
|
88
|
+
export default QuillEditor;
|
@@ -181,7 +181,7 @@ const SearchSelect = forwardRef(({ addWrapper = true, form, fieldName, fieldsVal
|
|
181
181
|
}
|
182
182
|
if (nOptions.length > 0 && !isEqual(nOptions, list) && !list.some(item => item.value == value?.value)) {
|
183
183
|
console.log(`[${props?.label}]handleOptions onChange(undefined)`)
|
184
|
-
// 如果选项发生变化,并且选项中没有当前已经选择的数据,则清空当前已经选择的数据
|
184
|
+
// 如果选项发生变化,并且选项中没有当前已经选择的数据,则清空当前已经选择的数据(场景举例:出库时已选了库位A,此时如果变更出库仓库,新的仓库已经没有了库位A,则需要清空当前已经选择的库位,否则可能会造成操作错误)
|
185
185
|
typeof onChange === 'function' && onChange(undefined)
|
186
186
|
}
|
187
187
|
}
|
@@ -709,6 +709,7 @@ const FormContainer = forwardRef(({ cols = 1, children, mode = "view" }, ref) =>
|
|
709
709
|
|
710
710
|
|
711
711
|
const changedFieldsState = React.useRef({});
|
712
|
+
const changedValuesState = React.useRef({});
|
712
713
|
const timeoutRef = React.useRef(null);
|
713
714
|
|
714
715
|
// 注意:初始化 setFieldsValue 的时候,如果没有更新lastFormValues,或者请求过慢,没有连上500毫秒的防抖,可能会造成数据加载异常(字段变化,填充的连锁反应,造成数据更新成非setFieldsValue的数据)
|
@@ -771,24 +772,77 @@ const FormContainer = forwardRef(({ cols = 1, children, mode = "view" }, ref) =>
|
|
771
772
|
}, []);
|
772
773
|
|
773
774
|
const handleFieldsChange = React.useCallback((changedFields) => {
|
774
|
-
console.log("handleFieldsChange", changedFields)
|
775
|
-
|
776
|
-
|
777
|
-
// const fieldKey = field.name.filter(item => typeof item == "string").join(".")
|
778
|
-
changedFieldsState.current[field.name] = field;
|
779
|
-
|
780
|
-
|
781
|
-
}
|
782
|
-
})
|
783
|
-
console.log("handleFieldsChange", changedFieldsState.current)
|
784
|
-
debounceHandleFieldsChange();
|
785
|
-
|
775
|
+
console.log("handleFieldsChange (disabled, using handleValuesChange instead)", JSON.stringify(changedFields))
|
776
|
+
// 已禁用,改为使用 handleValuesChange 来处理字段变更
|
777
|
+
// 这样可以避免重复处理和多余的触发
|
786
778
|
}, []);
|
787
|
-
|
788
|
-
|
789
|
-
|
790
|
-
|
779
|
+
const handleValuesChange = React.useCallback((changedValues, allValues) => {
|
780
|
+
console.log("handleValuesChange changedValues", JSON.stringify(changedValues))
|
781
|
+
console.log("handleValuesChange allValues", JSON.stringify(allValues))
|
782
|
+
|
783
|
+
// 将 changedValues 转换为类似 handleFieldsChange 的格式
|
784
|
+
const convertToFieldsFormat = (values, parentPath = []) => {
|
785
|
+
const fieldsArray = [];
|
786
|
+
|
787
|
+
for (let fieldName in values) {
|
788
|
+
const fieldValue = values[fieldName];
|
789
|
+
const currentPath = [...parentPath, fieldName];
|
790
|
+
|
791
|
+
// 处理数组类型(如table字段)
|
792
|
+
if (Array.isArray(fieldValue)) {
|
793
|
+
fieldValue.forEach((item, index) => {
|
794
|
+
if (typeof item === 'object' && item !== null) {
|
795
|
+
// 递归处理数组中的对象
|
796
|
+
const subFields = convertToFieldsFormat(item, [...currentPath, index]);
|
797
|
+
fieldsArray.push(...subFields);
|
798
|
+
} else {
|
799
|
+
// 数组中的基本类型值
|
800
|
+
fieldsArray.push({
|
801
|
+
touched: true,
|
802
|
+
validating: false,
|
803
|
+
errors: [],
|
804
|
+
warnings: [],
|
805
|
+
name: [...currentPath, index],
|
806
|
+
validated: false,
|
807
|
+
value: item
|
808
|
+
});
|
809
|
+
}
|
810
|
+
});
|
811
|
+
} else {
|
812
|
+
// 对于非数组类型(包括对象和基本类型),都作为完整的字段值处理
|
813
|
+
// 这样可以正确处理像 {label: "选项2", value: "2"} 这样的对象值
|
814
|
+
fieldsArray.push({
|
815
|
+
touched: true,
|
816
|
+
validating: false,
|
817
|
+
errors: [],
|
818
|
+
warnings: [],
|
819
|
+
name: currentPath,
|
820
|
+
validated: false,
|
821
|
+
value: fieldValue
|
822
|
+
});
|
823
|
+
}
|
824
|
+
}
|
825
|
+
|
826
|
+
return fieldsArray;
|
827
|
+
};
|
828
|
+
|
829
|
+
// 转换为类似 handleFieldsChange 的格式
|
830
|
+
const convertedFields = convertToFieldsFormat(changedValues);
|
831
|
+
console.log("handleValuesChange converted to fields format", JSON.stringify(convertedFields));
|
832
|
+
|
833
|
+
// 使用转换后的数据,复用原有的处理逻辑
|
834
|
+
if (convertedFields.length > 0) {
|
835
|
+
convertedFields.forEach(field => {
|
836
|
+
if (field.name && field.name.length > 0) {
|
837
|
+
changedFieldsState.current[field.name] = field;
|
838
|
+
}
|
839
|
+
});
|
840
|
+
|
841
|
+
console.log("handleValuesChange changedFieldsState", changedFieldsState.current);
|
842
|
+
debounceHandleFieldsChange();
|
843
|
+
}
|
791
844
|
}, []);
|
845
|
+
|
792
846
|
const getTableWithIds = (ids) => {
|
793
847
|
let withAllIds = []
|
794
848
|
ids.forEach(id => {
|