记录一下最近使用Ueditor富文本编辑器时遇到的问题javascript
用户在编辑富文本内容时,好比上传了10张图片保存,下一次编辑时去掉了其中3张图片,那么数据库中当前文档与文档上传的文件的对应关系应该如何更新呢?html
我采用的作法是,每次从新获取富文本中的文件,而后清除文档与文件的关系后,按当前文档中获取来的文件列表从新添加关系java
不采用正则表达式这种效率低的方式node
在上传文件时将文件内容作md5运算生成惟一key,而后将须要记录的文件内容都存储到数据库中的表中正则表达式
我采用md5运算方法逻辑是,若是文件大于2MB就取文件头1MB和后1MB,作md5运算生成文件惟一标识,小于2MB就直接md5数据库
不要问我为何用头1MB和后1MB运算生成的MD5值做作惟一标识,用就完了json
UEditor 工具栏配置 app
var ueToolbars = [ [ 'undo', //撤销 'redo', //重作 'bold', //加粗 'indent', //首行缩进 'italic', //斜体 'fontsize', //字号 'simpleupload', //单图上传 'insertvideo', //视频 'justifyleft', //居左对齐 'justifyright', //居右对齐 'justifycenter', //居中对齐 'justifyjustify', //两端对齐 'attachment', //附件 ] ]
须要修改ueditor.all.js源码,在回显与保存文档时给相应标签增长两个属性dom
一、t_crc="7d90bcfc87c1e8a918b38f35a6186f53",文件惟一标识ID,文件内容MD5值编辑器
二、t_tag="cxUeditorUploadFile",在标签中打入标记,以后保存时使用原生js方式获取带有标记的全部标签,这样就获取到了文件惟一标识crc字段
如上传的图最终保存为 :
<!-- 图片 --> <img src="/preview/20190429/20190429182137525982_98488150.jpg" title="191322z2g2mmnoloqzcqnq.jpg" _src="/preview/20190429/20190429182137525982_98488150.jpg" alt="191322z2g2mmnoloqzcqnq.jpg" t_crc="7d90bcfc87c1e8a918b38f35a6186f53" t_tag="cxUeditorUploadImage">
须要注意的是,UEditor中的标签属性有名单验证,须要修改ueditor.config.js中的白名单whitList,增长t_crc,t_tag,不然UEditor会过滤掉咱们自定义的属性
由于不清楚如何自定义controller的返回字段,看了官网也没找到如何能自定义返回字段,没有办法只能将其中一个字段改成json字符串,然修改ueditor源码解析改字符串,是否是很low,我也不想这样写实在是没办法
{ "original": "xy.png", "state": "SUCCESS", "title": "xy.png", "url": "{\"crc\":\"fe760006af17c5bfe2d68ad17f5fe8f6\",\"url\":\"/preview/20190430/20190430105610120347_98488150.png\"}" }
注意源码中的ueditor.all.js源码中7966行的filterInputRule方法,执行editor.setContent方法和执行'inserthtml'命令后,会运行该过滤函数,咱们直接加入return;不然咱们本身加的标签他会过滤掉
/** * 执行注册的过滤规则 * @method filterInputRule * @param { UE.uNode } root 要过滤的uNode节点 * @remind 执行editor.setContent方法和执行'inserthtml'命令后,会运行该过滤函数 * @example * ```javascript * editor.filterInputRule(editor.body); * ``` * @see UE.Editor:addInputRule */ filterInputRule: function (root) { // kdy修改 return ; for (var i = 0, ci; ci = this.inputRules[i++];) { ci.call(this, root) } },
ueditor.all.js源码中9969行的过滤器defaultfilter也直接加入return;
UE.plugins['defaultfilter'] = function () { return; // kdy修改 ......省略 }
ueditor.all.js源码中17648行,修改video标签加入咱们自定义属性t_crc,t_tag
/** * 建立插入视频字符窜 * @param url 视频地址 * @param width 视频宽度 * @param height 视频高度 * @param align 视频对齐 * @param toEmbed 是否以flash代替显示 * @param addParagraph 是否须要添加P 标签 * // kdy修改 */ function creatInsertStr(url,width,height,id,align,classname,type,node){ let urlJSON = undefined; try { urlJSON = JSON.parse(url); } catch (error) { if (node != undefined) { urlJSON = { "url": node.getAttr("_url"), "crc": node.getAttr("t_crc") }; } } let crc = urlJSON.crc; if(node != undefined){ crc = node.getAttr("t_crc"); } url = urlJSON.url; url = utils.unhtmlForUrl(url); align = utils.unhtml(align); classname = utils.unhtml(classname); width = parseInt(width, 10) || 0; height = parseInt(height, 10) || 0; //修改了这里 var str; switch (type){ case 'image': str = '<img t_tag="cxUeditorUploadFile" t_crc="'+crc+'" ' + (id ? 'id="' + id+'"' : '') + ' width="'+ width +'" height="' + height + '" _url="'+url+'" class="' + classname.replace(/\bvideo-js\b/, '') + '"' + ' src="' + me.options.UEDITOR_HOME_URL+'themes/default/images/spacer.gif" style="background:url('+me.options.UEDITOR_HOME_URL+'themes/default/images/videologo.gif) no-repeat center center; border:1px solid gray;'+(align ? 'float:' + align + ';': '')+'" />' break; case 'embed': str = '<embed type="application/x-shockwave-flash" class="' + classname + '" pluginspage="http://www.macromedia.com/go/getflashplayer"' + ' src="' + utils.html(url) + '" width="' + width + '" height="' + height + '"' + (align ? ' style="float:' + align + '"': '') + ' wmode="transparent" play="true" loop="false" menu="false" allowscriptaccess="never" allowfullscreen="true" >'; break; case 'video': var ext = url.substr(url.lastIndexOf('.') + 1); if(ext == 'ogv') ext = 'ogg'; str = '<video t_tag="cxUeditorUploadFile" t_crc="'+crc+'" ' + (id ? ' id="' + id + '"' : '') + ' class="' + classname + ' video-js" ' + (align ? ' style="float:' + align + '"': '') + ' controls preload="none" width="' + width + '" height="' + height + '" src="' + url + '" data-setup="{}">' + '<source src="' + url + '" type="video/' + ext + '" /></video>'; break; } return str; }
ueditor.all.js源码中17780行,视频上传后的回调函数加入t_crc 和 t_tag
me.commands["insertvideo"] = { execCommand: function (cmd, videoObjs, type){ videoObjs = utils.isArray(videoObjs)?videoObjs:[videoObjs]; var html = [],id = 'tmpVedio', cl; for(var i=0,vi,len = videoObjs.length;i<len;i++){ vi = videoObjs[i]; cl = (type == 'upload' ? 'edui-upload-video video-js vjs-default-skin':'edui-faked-video'); html.push(creatInsertStr( vi.url, vi.width || 420, vi.height || 280, id + i, null, cl, 'image')); } me.execCommand("inserthtml",html.join(""),true); var rng = this.selection.getRange(); for(var i= 0,len=videoObjs.length;i<len;i++){ var img = this.document.getElementById('tmpVedio'+i); domUtils.removeAttributes(img,'id'); rng.selectNode(img).select(); me.execCommand('imagefloat',videoObjs[i].align) } }, queryCommandState : function(){ var img = me.selection.getRange().getClosedNode(), flag = img && (img.className == "edui-faked-video" || img.className.indexOf("edui-upload-video")!=-1); return flag ? 1 : 0; } };
ueditor.all.js源码中24536行,修改image标签图片上传成功后的回调函数,这个方法会在富文本编辑框中加入咱们上传的图片,一样加入t_crc 和 t_tag
function callback(){ try{ var link, json, loader, body = (iframe.contentDocument || iframe.contentWindow.document).body, result = body.innerText || body.textContent || ''; json = (new Function("return " + result))(); // 修改这里 let urlJSON = JSON.parse(json.url); let t_url = urlJSON.url; let t_crc = urlJSON.crc; json.url = t_url; link = me.options.imageUrlPrefix + json.url; if(json.state == 'SUCCESS' && json.url) { loader = me.document.getElementById(loadingId); loader.setAttribute('src', link); loader.setAttribute('_src', link); loader.setAttribute('title', json.title || ''); loader.setAttribute('alt', json.original || ''); loader.setAttribute('style','max-width:650px'); loader.setAttribute('t_crc', t_crc || ''); loader.setAttribute('t_tag','cxUeditorUploadFile'); loader.removeAttribute('id'); domUtils.removeClasses(loader, 'loadingclass'); } else { showErrorLoader && showErrorLoader(json.state); } }catch(er){ showErrorLoader && showErrorLoader(me.getLang('simpleupload.loadError')); } form.reset(); domUtils.un(iframe, 'load', callback); }
ueditor.all.js源码中24812行,上传附件后的回调函数,一样加入t_crc 和 t_tag
return { commands:{ 'insertfile': { execCommand: function (command, filelist){ filelist = utils.isArray(filelist) ? filelist : [filelist]; var i, item, icon, title, html = '', URL = me.getOpt('UEDITOR_HOME_URL'), iconDir = URL + (URL.substr(URL.length - 1) == '/' ? '':'/') + 'dialogs/attachment/fileTypeImages/'; for (i = 0; i < filelist.length; i++) { item = filelist[i]; // 修改这里 let urlJSON = JSON.parse(item.url); let t_url = urlJSON.url; let t_crc = urlJSON.crc; item.url = t_url; icon = iconDir + getFileIcon(item.url); title = item.title || item.url.substr(item.url.lastIndexOf('/') + 1); html += '<p style="line-height: 16px;">' + '<img style="vertical-align: middle; margin-right: 2px;" src="'+ icon + '" _src="' + icon + '" />' + '<a t_crc="'+ t_crc +'" t_tag="cxUeditorUploadFile" style="font-size:12px; color:#0066cc;" href="' + item.url +'" title="' + title + '">' + title + '</a>' + '</p>'; } me.execCommand('insertHtml', html); // me.fireEvent('afterUpfile', filelist); } } } }
完成
连接:https://pan.baidu.com/s/1JZ0qbz7Fu0EL1H5quA98Jg 提取码:raer