Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

wangEditor5.1.23版本,使用自定义上传多次上传报错 #5959

Open
longsiping opened this issue Sep 23, 2024 · 1 comment
Open

wangEditor5.1.23版本,使用自定义上传多次上传报错 #5959

longsiping opened this issue Sep 23, 2024 · 1 comment

Comments

@longsiping
Copy link

bug 描述

使用wangEditor5.1.23版本,customUpload自定义上传功能,调用insertFn方法插入富文本内时,只上传一张图片没啥问题,上传完成后,再继续上传一张,就提示子节点无法找到;[Unhandled Rejection (Error): Cannot find a descendant at path [0,4] in node: {"children"](global.js:1 Uncaught (in promise) Error: Cannot find a descendant at path [1] in node: {"children":[{"type":"paragraph","children":[{"text":"1231"}]}],"operations":[],"selection":{"anchor":{"path":[1,0],"offset":0},"focus":{"path":[1,0],"offset":0}},"marks":null,"id":"wangEditor-10","isDestroyed":false,"isFullScreen":false,"history":{"undos":[[{"type":"split_node","path":[0,0],"position":4,"properties":{}},{"type":"split_node","path":[0],"position":1,"properties":{"type":"paragraph"}}],[{"type":"remove_text","path":[0,0],"offset":0,"text":"1231"},{"type":"remove_node","path":[0],"node":{"type":"paragraph","children":[{"text":""}]}},{"type":"remove_node","path":[0],"node":{"type":"paragraph","children":[{"text":""}]}},{"type":"insert_node","path":[0],"node":{"type":"paragraph","children":[{"text":"1231"}]}},{"type":"set_selection","properties":{"anchor":{"path":[0,0],"offset":4},"focus":{"path":[0,0],"offset":4}},"newProperties":{"anchor":{"path":[1,0],"offset":0},"focus":{"path":[1,0],"offset":0}}}]],"redos":[]}})

代码

## 你预期的样子是?

*请输入内容……*

## 系统和浏览器及版本号

- 操作系统
- 浏览器和版本

## wangEditor 版本
5.1.23
*请输入内容……*

## demo 能否复现该 bug 

/不能

- 中文 demo https://www.wangeditor.com/demo/
- English demo https://www.wangeditor.com/demo/?lang=en

## 在线 demo

*请尽量提供在线 demo (推荐以下网站),帮助我们最低成本复现 bug*

- https://codesandbox.io/
- https://codepen.io/
- https://stackblitz.com/

## 最小成本的复现步骤

(请告诉我们,如何最快的复现该 bug)

- 步骤一
- 步骤二
- 步骤三
@longsiping
Copy link
Author

import React, { memo, useState, useEffect, useCallback } from "react";
import { Editor, Toolbar } from '@wangeditor/editor-for-react';
import { IDomEditor, IEditorConfig, IToolbarConfig, DomEditor } from '@wangeditor/editor';
import '@wangeditor/editor/dist/css/style.css';
import { message, Spin } from '@alipay/bigfish/antd';
import { uploadFile } from "@/services/upload_file";

type InsertFnType = (url: string, alt: string, href: string) => void

interface getFileUrlType {
id: number;
orderId: number;
filePosition: string;
moduleType: string;
fileType: string;
fileName: string;
fileSize: string;
gmtCreate: string;
gmtModified: string;
url: string;
};

interface MonoContext {
html: string;
setHtml: (html: string) => void;
flag?: boolean;
width?: number;
height?: number;
onChange?: (value: string) => void;
maxLength: number;
isUploadImage?: boolean;
orderId?: string;
filePosition?: string;
moduleType?: string;
getWork?: () => void;
setCurrentImage?: (value: any) => void;
};

export default memo((props: MonoContext) => {

const { html, setHtml, flag, width = 480, height = 400, onChange, isUploadImage = false, orderId, filePosition, moduleType, getWork, setCurrentImage } = props;

const [loading, setLoading] = useState<boolean>(false);
const [editor, setEditor] = useState<IDomEditor | null>(null);

//工具栏配置
const toolbarConfig: Partial<IToolbarConfig> = {
    //排除掉哪些功能
    // excludeKeys: [
    //     'group-video',
    //     'group-image',
    //     "sup",
    //     "sub",
    //     "fullScreen",
    //     "insertTable",
    //     "fontFamily",
    //     'undo',
    //     'redo'

    // ],
    //重新配置某些功能
    toolbarKeys: [
        "headerSelect",
        "fontSize",
        "bold",
        "italic",
        "underline",
        "through",
        "color",
        "bgColor",
        // "lineHeight",
        {
            key: "group-more-style",
            title: '更多',
            menuKeys: [
                "divider",
                "codeBlock",
                "bulletedList",
                "numberedList",
                // "todo",
                // "code",
                "insertLink",
                'blockquote',
                isUploadImage ? "uploadImage" : '',
                "insertTable",
                "fullScreen"
            ],
            iconSvg: `<svg viewBox="0 0 1024 1024"><path d="M204.8 505.6m-76.8 0a76.8 76.8 0 1 0 153.6 0 76.8 76.8 0 1 0-153.6 0Z"></path><path d="M505.6 505.6m-76.8 0a76.8 76.8 0 1 0 153.6 0 76.8 76.8 0 1 0-153.6 0Z"></path><path d="M806.4 505.6m-76.8 0a76.8 76.8 0 1 0 153.6 0 76.8 76.8 0 1 0-153.6 0Z"></path></svg>`
        }

    ]
    // modalAppendToBody:true

};

//编辑器配置
const editorConfig: Partial<IEditorConfig> = {
    placeholder: '请输入内容...',
    readOnly: flag, //是否只读
    MENU_CONF: {
        'fontSize': {
            fontSizeList: [
                { name: '初号', value: '56px' },
                { name: '小初', value: '48px' },
                { name: '一号', value: '34px' },
                { name: '小一', value: '32px' },
                { name: '二号', value: '29px' },
                { name: '小二', value: '24px' },
                { name: '三号', value: '21px' },
                { name: '小三', value: '20px' },
                { name: '四号', value: '18px' },
                { name: '小四', value: '16px' },
                { name: '五号', value: '14px' },
                { name: '小五', value: '12px' },
            ]
        },
        // 'fontFamily': {
        //     fontFamilyList: [
        //         {
        //             name: '黑体', value: '黑体'
        //         },
        //         {
        //             name: '楷体', value: '楷体'
        //         },
        //         {
        //             name: '仿宋', value: '仿宋'
        //         },
        //         {
        //             name: '宋体', value: '宋体'
        //         }
        //     ]
        // },
        // 'lineHeight': {
        //     lineHeightList: ['1', '1.5', '2', '2.5']
        // },
        //上传图片的拦截
        'uploadImage': isUploadImage ? {
            fieldName: 'file',
            allowedFileTypes: ['image/*'],
            //server: '/api/v1/napa/web/transformWorkOrder/uploadFile',
            maxNumberOfFiles: 2,
            // meta: {
            //     orderId,
            //     filePosition,
            //     moduleType
            // },
            // headers: {
            //     accept: 'application/json'
            // },
            //自定义上传逻辑,
            customUpload: async (file: File, insertFn: InsertFnType) => {
                const formData = new FormData();
                formData.append('file', file);
                formData.append('orderId', orderId);
                formData.append('filePosition', filePosition);
                formData.append('moduleType', moduleType);
                const res: any = await uploadFile(formData, {}).catch((err) => {
                    message.error('上传失败');
                }).finally(() => setLoading(false));
                if (res.success) {
                    message.success('上传成功');
                    if (typeof getWork === 'function') {
                        const data: any = await getWork();
                        const filerFile = data?.bkBankFileUploadInfoModels?.filter((item: getFileUrlType) => item.filePosition == filePosition) ?? [];
                        if (filerFile?.length > 0) {
                            const url = filerFile[filerFile.length - 1].url;
                            const poster = filerFile[filerFile.length - 1].url;
                            const alt = filerFile[filerFile.length - 1].fileName;
                            insertFn(url, alt,poster);
                        }
                    };

                };


            },
            //上传前拦截
            onBeforeUpload: (file: File) => {
                let flag = true;
                for (let key in file) {
                    flag = file[key].type.includes('image');
                };
                if (flag) {
                    return file
                } else {
                    return false;
                }
            }
        } : {},
        //上传视频的拦截
        'uploadVideo': {
            onInsertedVideo(videoNode) {
                return message.error('识别错误')
            }
        },
        'codeSelectLang': {
            codeLangs: [
                { text: 'CSS', value: 'css' },
                { text: 'HTML', value: 'html' },
                { text: 'XML', value: 'xml' },
                { text: 'JSON', value: 'json' },
                { test: 'JavaScript', value: 'javascript' },
                { text: 'JAVA', value: 'java' },
            ]
        }
    },
    //告警配置
    customAlert: (s, t) => {
        switch (t) {
            case 'success':
                message.success(s)
                break
            case 'info':
                message.info(s)
                break
            case 'warning':
                message.warning(s)
                break
            case 'error':
                message.error(s)
                break
            default:
                message.info(s)
                break
        }
    },
    //粘贴配置
    customPaste: (editor: IDomEditor, event: any) => {
        const html = event.clipboardData.getData('text/html');
        const text = event.clipboardData.getData('text/plain');
        const rtf = event.clipboardData.getData('text/rtf');

        if (!html && !text) {
            message.error('无法识别复制内容')
            return false;
        };
        return true
    }
};








useEffect(() => {
    //富文本实例
    //@ts-ignore
    const toolbar = DomEditor.getToolbar(editor);
    // console.log(toolbar?.getConfig().toolbarKeys, '默认配置');
    // console.log(editor?.getAllMenuKeys(), '查询编辑器注册的所有菜单key');
    return () => {
        if (editor == null) return;
        editor.destroy()
        setEditor(null)
    }
}, [editor]);


return <>
    <div style={{ border: '1px solid #ccc', zIndex: 100, width: width }}>
        <Toolbar
            editor={editor}

            defaultConfig={toolbarConfig}
            mode="default"
            style={{ borderBottom: '1px solid #ccc' }}
        />
        <Spin spinning={loading}>
            <Editor

                defaultConfig={editorConfig}
                value={html}

                onCreated={setEditor}

                onChange={editor => {
                    const text = editor.getText();
                    const html = editor.getHtml();
                    const isEmpty = editor.isEmpty();
                    if (typeof setCurrentImage === 'function') {
                        setCurrentImage(editor?.getElemsByType('image'));
                    };

                    setHtml(isEmpty ? '' : html);
                    if (onChange && typeof onChange === 'function') {
                        onChange(isEmpty ? '' : html);
                    }
                    // setContentFlag(editor.isEmpty());
                }}


                mode="default"
                style={{ height: height }}
            />
        </Spin>

    </div>
</>

});

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant