editor.md编辑器,图片跨域上传,前后端分离

发布于:2025-02-21 ⋅ 阅读:(29) ⋅ 点赞:(0)

解决思路:

不修改原来的editormd文件

通过猴子补丁(monkey patch)的方式,替换editormd内部的上传方法。例如,找到image-dialog.js中处理上传的函数,保存原函数的引用,然后用自定义函数替换

    // 初始化编辑器
    function initEditor() {
        // 保存原始图片上传处理函数
        const originalImageUpload = editormd.prototype.executePlugin;

        // 猴子补丁方式覆盖图片上传处理
        editormd.prototype.executePlugin = function(pluginName, options) {
            if (pluginName === "imageDialog") {
                this.imageUploader = function() {
                    const file = this.files[0];
                    const loading = layer.msg('上传中...', {icon: 16, shade: 0.01});

                    // 创建与现有上传组件一致的FormData
                    const formData = new FormData();
                    formData.append('editormd-image-file', file); // 保持参数名称与现有系统一致
                    formData.append('filetype', 0); // 添加系统要求的参数

                    // 使用原始XMLHttpRequest发送保持请求结构
                    const xhr = new XMLHttpRequest();
                    xhr.open('POST', API.getApiUrl('index/upload'));
                    xhr.setRequestHeader('Authorization', 'Bearer ' + API.getToken());
                    
                    xhr.upload.onprogress = function(e) {
                        if (e.lengthComputable) {
                            const percent = (e.loaded / e.total * 100).toFixed(2) + '%';
                            layer.msg('上传进度: ' + percent, {icon: 16, shade: 0.01});
                        }
                    };

                    xhr.onload = function() {
                        layer.close(loading);
                        try {
                            const res = JSON.parse(xhr.responseText);
                            if (res.success === 1) {
                                // 使用编辑器API插入图片
                                const cursor = this.getCursor();
                                this.replaceSelection(`![](${res.url})`, cursor);
                                layer.msg('上传成功', {icon: 1});
                            } else {
                                layer.msg(res.msg || '上传失败', {icon: 2});
                            }
                        } catch(e) {
                            console.error('解析响应失败:', e);
                            layer.msg('上传失败', {icon: 2});
                        }
                    }.bind(taskEditor); // 绑定编辑器实例上下文

                    xhr.onerror = function() {
                        layer.close(loading);
                        console.error('上传失败:', xhr.statusText);
                        layer.msg('网络错误', {icon: 2});
                    };

                    xhr.send(formData);
                };

                // 保持与Editor.md一致的DOM操作
                const fakeInput = document.createElement('input');
                fakeInput.type = 'file';
                fakeInput.name = 'editormd-image-file';
                fakeInput.accept = "image/*";
                fakeInput.onchange = this.imageUploader.bind(fakeInput);
                fakeInput.click();
                
                return false;
            }
            return originalImageUpload.apply(this, arguments);
        };

        // 继续原有编辑器初始化逻辑
        const editorContainer = $('#taskDescription');
        if (editorContainer.is(':visible')) {
            const isMobile = window.innerWidth <= 768;
            console.log('0000',CONFIG.API.getBaseUrl());
            taskEditor = editormd("taskDescription", {
                width: "100%",
                height: isMobile ? 400 : 500,
                path : "../editormd/lib/",
                toolbarIcons : function() {
                    return window.editormdConfig ? 
                        window.editormdConfig.toolbarIcons : 
                        [
                            "undo", "redo", "|",
                            "bold", "del", "italic", "quote", "ucwords", "uppercase", "lowercase", "|",
                            "h1", "h2", "h3", "h4", "h5", "h6", "|",
                            "list-ul", "list-ol", "hr", "|",
                            "link", "image", "code", "preformatted-text", "code-block", "table", "|",
                            "watch", "preview", "fullscreen", "|",
                            "help"
                        ];
                },
                placeholder: "请详细描述任务需求...",
                saveHTMLToTextarea : true,
                imageUpload : false,
                imageFormats : ["jpg", "jpeg", "gif", "png", "bmp", "webp"],
                imageUploadURL : CONFIG.API.getBaseUrl() + "/index/upload?filetype=0",
                crossDomainUpload: true, // 禁用跨域上传
                tex  : true,
                flowChart : true,
                sequenceDiagram : true,
                emoji : true,
                watch: !isMobile, // 移动端关闭实时预览
                onload : function() {
                    console.log('编辑器加载完成');
                }
            });
        } else {
            setTimeout(initEditor, 500); // 延迟检查
        }
    }

解决办法就是:猴子补丁方式覆盖图片上传处理

        // 猴子补丁方式覆盖图片上传处理
        editormd.prototype.executePlugin = function(pluginName, options) {
            if (pluginName === "imageDialog") {
                this.imageUploader = function() {
                    const file = this.files[0];
                    const loading = layer.msg('上传中...', {icon: 16, shade: 0.01});

                    // 创建与现有上传组件一致的FormData
                    const formData = new FormData();
                    formData.append('editormd-image-file', file); // 保持参数名称与现有系统一致
                    formData.append('filetype', 0); // 添加系统要求的参数

                    // 使用原始XMLHttpRequest发送保持请求结构
                    const xhr = new XMLHttpRequest();
                    xhr.open('POST', API.getApiUrl('index/upload'));
                    xhr.setRequestHeader('Authorization', 'Bearer ' + API.getToken());
                    
                    xhr.upload.onprogress = function(e) {
                        if (e.lengthComputable) {
                            const percent = (e.loaded / e.total * 100).toFixed(2) + '%';
                            layer.msg('上传进度: ' + percent, {icon: 16, shade: 0.01});
                        }
                    };

                    xhr.onload = function() {
                        layer.close(loading);
                        try {
                            const res = JSON.parse(xhr.responseText);
                            if (res.success === 1) {
                                // 使用编辑器API插入图片
                                const cursor = this.getCursor();
                                this.replaceSelection(`![](${res.url})`, cursor);
                                layer.msg('上传成功', {icon: 1});
                            } else {
                                layer.msg(res.msg || '上传失败', {icon: 2});
                            }
                        } catch(e) {
                            console.error('解析响应失败:', e);
                            layer.msg('上传失败', {icon: 2});
                        }
                    }.bind(taskEditor); // 绑定编辑器实例上下文

                    xhr.onerror = function() {
                        layer.close(loading);
                        console.error('上传失败:', xhr.statusText);
                        layer.msg('网络错误', {icon: 2});
                    };

                    xhr.send(formData);
                };

                // 保持与Editor.md一致的DOM操作
                const fakeInput = document.createElement('input');
                fakeInput.type = 'file';
                fakeInput.name = 'editormd-image-file';
                fakeInput.accept = "image/*";
                fakeInput.onchange = this.imageUploader.bind(fakeInput);
                fakeInput.click();
                
                return false;
            }
            return originalImageUpload.apply(this, arguments);
        };


网站公告

今日签到

点亮在社区的每一天
去签到