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.
@@ -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
- changedFields.filter(field => {
776
- if (field.name && field.name.length > 0) {
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
- const handleValuesChange = React.useCallback((changedValues) => {
789
- console.log("handleValuesChange", changedValues)
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 => {