记录一下最近使用Ueditor富文本编辑器时遇到的问题
用户在编辑富文本内容时,比如上传了10张图片保存,下一次编辑时去掉了其中3张图片,那么数据库中当前文档与文档上传的文件的对应关系应该如何更新呢?
我采用的做法是,每次重新获取富文本中的文件,然后清除文档与文件的关系后,按当前文档中获取来的文件列表重新添加关系
不采用正则表达式这种效率低的方式
在上传文件时将文件内容做md5运算生成唯一key,然后将需要记录的文件内容都存储到数据库中的表中
我采用md5运算方法逻辑是,如果文件大于2MB就取文件头1MB和后1MB,做md5运算生成文件唯一标识,小于2MB就直接md5
不要问我为什么用头1MB和后1MB运算生成的MD5值作做唯一标识,用就完了
UEditor 工具栏配置
var ueToolbars = [
[
'undo', //撤销
'redo', //重做
'bold', //加粗
'indent', //首行缩进
'italic', //斜体
'fontsize', //字号
'simpleupload', //单图上传
'insertvideo', //视频
'justifyleft', //居左对齐
'justifyright', //居右对齐
'justifycenter', //居中对齐
'justifyjustify', //两端对齐
'attachment', //附件
]
]
需要修改ueditor.all.js源码,在回显与保存文档时给相应标签增加两个属性
1、t_crc="7d90bcfc87c1e8a918b38f35a6186f53",文件唯一标识ID,文件内容MD5值
2、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