最近进入一个go开发项目组,我一个java开发的第一个任务就是研究ueditor组件的使用,嗨,来来回回花了5天多吧,特意写下这篇文章,记住在ueditor中踩过的坑。
1.不晓得前端下的ueditor是哪个版本,就是和百度上面的主流不一样,搞的我想弄死他。打开ueditor的富文本编辑器,点击图片也好视频也好,就是报上面后台配置错误,最后我在ueditor.config.js中加入的多图片上传和视频上传的配置。
//为编辑器实例添加一个路径,这个不能被注释
UEDITOR_HOME_URL: URL,
// 服务器统一请求接口路径
serverUrl: gHost + 'ybufweb/uploadfile',
/* 上传视频配置 */
videoActionName: gHost + 'ybufweb/uploadfile', /* 执行上传视频的action名称 */
videoFieldName: "file_data", /* 提交的视频表单名称 */
videoPathFormat: "root/images/{yyyy}{mm}{dd}/{time}{rand:6}/", /* 上传保存路径,可以自定义保存路径和文件名格式 */
videoUrlPrefix: "", /* 视频访问路径前缀 */
videoMaxSize: 100000000, /* 上传大小限制,单位B,默认100MB */
videoAllowFiles: [".mp4", ".webm", ".mp3", ".wav", ".ogg"], /* 上传视频格式显示 */
/* 上传图片配置项 */
imageActionName: gHost + 'ybufweb/uploadfile', /* 执行上传图片的action名称 */
imageFieldName: "file_data", /* 提交的图片表单名称 */
imageMaxSiz: 1000000, /* 上传大小限制,单位B */
imageAllowFiles: [".png", ".jpg", ".jpeg", ".gif", ".bmp"], /* 上传图片格式显示 */
imageCompressEnable: true, /* 是否压缩图片,默认是true */
imageCompressBorder: 1600, /* 图片压缩最长边限制 */
imageInsertAlign: "none", /* 插入的图片浮动方式 */
imageUrlPrefix: "", /* 图片访问路径前缀 */
imagePathFormat: "root/images/{yyyy}{mm}{dd}/{time}{rand:6}/", /* 上传保存路径,可以自定义保存路径和文件名格式 */
2.ueditor中的多图片上传
找了半天才晓得,多图片上传的页面就在image包中,自己去组件中找一下就可以找到。然后呢,我在image.html中把不需要的标签页全部隐藏掉,就留下本地多图片上传。
好吧,这样ueditor组件就会往我指定在ueditor.config.js中的serverUrl属性。结果一看后台,需要传一个自定义的参数,这是早就定义好了的公共方法不能修改,怎么办。百度了一下。在使用组件的article-management-save.js页面中
var ue = UE.getEditor(‘editor’);初始化组件时后,
ue.ready(function () {
ue.execCommand('serverparam', {
'filetype': 'upload_file',
});
ue.queryCommandValue('serverparam');
});
意思就是名字为filetype=‘upload_file’的参数通过get传到后台。结果我后台是post接收的。查看方法,确实是有get传递filetype参数,那么在后台怎么获得呢
if poststr == "" {
strs := r.Form["filetype"]
if len(strs) > 0 {
poststr = strs[0]
}
}
意思就是在post中找不到filetype的值,我就去找get的。
然后呢,就是后台返回的json。妈卖批,后台因为是公共的方法,改不了,怎么办呢。改源代码吧。垃圾ueditor。
uploader.on('uploadSuccess', function (file, ret) {
var $file = $('#' + file.id);
try {
var responseText = (ret._raw || ret),
json = utils.str2json(responseText);
//这里是上传之后的回执事件,进行json加工处理
json = changeDataToJson(json);
if (json.state == 'SUCCESS') {
// _this.imageList.push(json);
_this.imageList[$file.index()] = json;
$file.append('');
} else {
$file.find('.error').text(json.state).show();
}
} catch (e) {
$file.find('.error').text(lang.errorServerUpload).show();
}
});
image.js在uploader.on(‘uploadSuccess’, function (file, ret) {方法中就是对于后台返回json的处理。不符合ueditor的格式。那么我就把他转为符合的格式呗。
在下面我定义了方法changeDataToJson()
/** 自己写的方法,把返回的json拼成需要的格式 **/
function changeDataToJson(json) {
var object = {
"original": '', "size": '',
"state": '', "title": '', "type": '',
"msg": '', "url": ''
};
var _json = json;
if (_json.msg == 'OK') {
object.state = 'SUCCESS';
} else {
object.state = 'ERROR';
}
object.url = _json.results;
return object;
}
下面就是重点了。在ueditor中找了半天,就是没有找到多图片上传的张数的限制。这个是什么鬼情况。产品说限制50张,不干到时候又给提bug。
首先在article-management-save.页面的js中定义了
var fileCount= 0;//计算该页面中img标签的个数
//监听ueditor中内容改变事件
ue.addListener("contentChange",function(){
fileCount=$(ue.getContent()).find("img").length;
// console.log('内容改变:'+ue.getContent());
//动态修改视频、音频上传的参数
recompose();
});
这样我监听ueditor的文本改变事件,去计算已经有了多少个图片。然后在image.js中通过top.window.document.getElementById(“layui-layer-iframe1”).contentWindow.fileCount获取到article-management-save.js中得到的img图片个数,再加上在image.js上面定义的fileCount(这次上传的图片个数),俩着相加就是图片总数了。
$upload.on('click', function () {
//获取父级页面得到的图片总数,fileCount为该次上传的图片数量
var sum = top.window.document.getElementById("layui-layer-iframe1").contentWindow.fileCount + fileCount;
console.log(sum);
if (sum > 50) {
msgalter("图片总数为" + sum + "张,超过50张,限制上传!");
return;
}
if ($(this).hasClass('disabled')) {
return false;
}
if (state === 'ready') {
uploader.upload();
} else if (state === 'paused') {
uploader.upload();
} else if (state === 'uploading') {
uploader.stop();
}
});
$upload.on(‘click’, function () {方法就是你点击开始上传时按钮触发的世界。
本来以为这样就行了,结果发现表情也是图片,我擦,还需要统计表情的总数,在emotion文件夹的emotion.js中找到function InsertSmiley( url, evt ) {方法
如果,超过50个就不能点击
function InsertSmiley( url, evt ) {
//console.log("...C..");
var sum = top.window.document.getElementById("layui-layer-iframe1").contentWindow.fileCount;
if(sum >= 50){
msgalter("图片总数为" + sum + "张,超过50张,限制上传!");
return;
}
var obj = {
src:editor.options.emotionLocalization ? editor.options.UEDITOR_HOME_URL + "dialogs/emotion/" + url : url
};
obj._src = obj.src;
editor.execCommand( 'insertimage', obj );
if ( !evt.ctrlKey ) {
dialog.popup.hide();
}
}
顺便说一下,怎么把表情的http图片改为https,就是在emotion.js中
emotion.SmileyPath = editor.options.emotionLocalization === true ? 'images/' : "https://img.baidu.com/hi/";
就是把http改为了HTTPS,然后在emotion.html页面中加入
ok,图片告一段落
3.视频、音频上传
其他的问题,百度应该就可以解决,懒的说。我是视频和音频在一起上传的。所以基本是在video包中。然后呢,上传之后的json回执和图片上传一样的需要处理。
uploader.on('uploadSuccess', function (file, ret) {
// console.log(file, ret);
var $file = $('#' + file.id);
try {
var responseText = (ret._raw || ret),
json = utils.str2json(responseText);
//这里是上传之后的回执事件,进行json加工处理
json = changeDataToJson(json);
// console.log(json,"...");
if (json.state == 'SUCCESS') {
uploadVideoList.push({
'url': json.url,
'type': json.type,
'original':json.original
});
$file.append('');
} else {
$file.find('.error').text(json.state).show();
}
} catch (e) {
$file.find('.error').text(lang.errorServerUpload).show();
}
});
/** 自己写的方法,把返回的json拼成需要的格式 **/
function changeDataToJson(json){
var object = {"original":'',"size":'',
"state":'',"title":'',"type":'',
"msg":'',"url":''};
var _json = json;
if(_json.msg == 'OK'){
object.state = 'SUCCESS';
}else{
object.state = 'ERROR';
}
object.url = _json.results;
return object;
}
接下来问题来了,需求就是一个视频一个音频,
第一步就是在视频上传中一次只能上传一个,找了半天在点击上传时控制最好,
$upload.on('click', function (file) {
//限制视频、音频上传,一次只能上传一个
if (fileCount > 1) {
msgalter("一次只能上传一个!");
return;
}
// console.log("...5...",file);
//在这里判断在objectAudio中有值(说明是音频),需要重新校验音频的大小为10M
// console.log(objectAudio,file)
if(objectAudio !=undefined && objectAudio != '' && objectAudio !=null){
// console.log(objectAudio.size);
//设置音频的大小为10M
if(objectAudio.size > 10000000){
msgalter("音频超过10M,请重新上传!");
return;
}
}
if ($(this).hasClass('disabled')) {
return false;
}
if (state === 'ready') {
uploader.upload();
} else if (state === 'paused') {
uploader.upload();
} else if (state === 'uploading') {
uploader.stop();
}
});
//限制视频、音频上传,一次只能上传一个
if (fileCount > 1) {
msgalter(“一次只能上传一个!”);
return;
}
就可以控制单上传了
第二步 怎么去保证只能上传一个视频一个音频呢
ueditor.config.js页面中我写的
videoAllowFiles: [".mp4", “.webm”, “.mp3”, “.wav”, “.ogg”], /* 上传视频格式显示 */ 中包含了视频音频。所以第一次是可以上传视频或者音频的,假如我现在上传了一个视频,如果我把videoAllowFiles的值改为[".mp3", “.wav”, “.ogg”],那么以后就只能上传音频了,上传完音频后就把videoAllowFiles数组的值清空,什么都不能上传。
首先在article-management-save.js中定义方法
//动态修改视频、音频的参数
function recompose(){
//监听如果有视频
var video =$(ue.getContent()).find("video").length;
var audio = $(ue.getContent()).find("audio").length;
// console.log('内容改变:'+video+"...."+audio,"..."+window.UEDITOR_CONFIG.videoAllowFiles);
if(video>0 && audio==0){//监听如果有视频
//需要去更改ueditor.config.js中videoAllowFiles的值为audioDeploy,只能上传音频,和音频的大小为10M
window.UEDITOR_CONFIG.videoAllowFiles.splice(0,5);//清除全部的数组内容
window.UEDITOR_CONFIG.videoAllowFiles.push(".mp3", ".wav", ".ogg");//重新添加
// window.UEDITOR_CONFIG.videoMaxSize = 1000000;
// console.log( window.UEDITOR_CONFIG.videoAllowFiles);
// ue = UE.getEditor('editor');
}else if(video == 0 && audio>0){
window.UEDITOR_CONFIG.videoAllowFiles.splice(0,5);//清除全部的数组内容
window.UEDITOR_CONFIG.videoAllowFiles.push(".mp4", ".webm");//重新添加
// window.UEDITOR_CONFIG.videoMaxSize = 100000000;
// console.log( window.UEDITOR_CONFIG.videoAllowFiles);
// ue = UE.getEditor('editor');
}else if(video > 0 && audio>0){
window.UEDITOR_CONFIG.videoAllowFiles.splice(0,5);//清除全部的数组内容
// ue = UE.getEditor('editor');
}else if(video == 0 && audio == 0){
window.UEDITOR_CONFIG.videoAllowFiles.splice(0,5);//清除全部的数组内容
window.UEDITOR_CONFIG.videoAllowFiles.push(".mp4", ".webm", ".mp3", ".wav", ".ogg");//重新添加
}
}
在以前的方法中加入
//监听ueditor中内容改变事件
ue.addListener("contentChange",function(){
fileCount=$(ue.getContent()).find("img").length;
// console.log('内容改变:'+ue.getContent());
//动态修改视频、音频上传的参数
recompose();
});
为什么这么写,因为数组有一个特别奇怪的地方。如果,数组ABC,在数组A中定义好内容,然后B=A,C=B,那么如果我给数组A重新赋值,A=D,那么请问C=A(老A),还是C=D。哈哈,可以去试一试。
如果
window.UEDITOR_CONFIG.videoAllowFiles=[".mp3", “.wav”, “.ogg”];
虽然输出window.UEDITOR_CONFIG.videoAllowFiles的值确实变化了,但是在ueditor中并不是直接用的videoAllowFiles属性,而是,XXXX=videoAllowFiles,然后YYYY=XXX,天知道转了多少层,所以没有效果。但是我直接操作该数组。
window.UEDITOR_CONFIG.videoAllowFiles.splice(0,5);//清除全部的数组内容
window.UEDITOR_CONFIG.videoAllowFiles.push(".mp3", “.wav”, “.ogg”);//重新添加
这样就没有问题。一定要记得 这一点。
以上实现了一次只能上传一个和保证了视频和音频只有一个的问题。但是问题来了,我视频最大为100M,音频最大为10M。
在video.js中,最后的getQueueCount: function () {方法中
getQueueCount: function () {
var file, i, status, readyFile = 0, files = this.uploader.getFiles();
for (i = 0; file = files[i++]; ) {
status = file.getStatus();
if (status == 'queued' || status == 'uploading' || status == 'progress') readyFile++;
}
// console.log(file,"...7...",files);
//在这里判断,files中的第一个值(因为是单上传),ext是".mp3", ".wav", ".ogg",说明是音频
//把值给到定义的变量objectAudio中,再到823方法中去判断就可以限制音频的上传大小了
var fileAudio = files[0];
objectAudioList = files;
if(files.length>0){//循环集合,如果值为ext是".mp3", ".wav", ".ogg",说明是音频
if(fileAudio.ext == 'mp3' || fileAudio.ext == 'wav' || fileAudio.ext == 'z'){
objectAudio = fileAudio;
}
}
return readyFile;
},
当然了在最上面定义俩参数
var objectAudio;//用来存储音频file对象
var objectAudioList;//用来存储file数组
因为是单上传,所以我在这里获取到files数组,取到第一个,再去判断如果是音频,就给objectAudio值。最后在$upload.on(‘click’, function (file) {中
这样就可以判断是音频时,点击上传按钮时进行重新校验。但是,如果那个手欠的一次选择多个,然后因为提示是只能单上传,一个个删除时,没有进去getQueueCount: function () {方法了,这个时候进去的是删除方法uploader.on(‘fileDequeued’, function (file) {
uploader.on('fileDequeued', function (file) {
fileCount--;
fileSize -= file.size;
// console.log(file,fileSize,files);
removeFile(file);
//删除在objectAudioList数组中的file对象
// console.log($.inArray(file,objectAudioList));
objectAudioList.splice($.inArray(file,objectAudioList),1);
if(objectAudioList.length>0){
//反正取第一个(单视频、音频上传)
if(objectAudioList[0].ext == 'mp3' || objectAudioList[0].ext == 'wav' || objectAudioList[0].ext == 'z'){
objectAudio = objectAudioList[0];
}
}else{//如果没有长度了,就把objectAudio为空,其实加不加无所谓,反正不会上传
objectAudio = null;
}
// console.log("...1...",file,objectAudioList);
updateTotalProgress();
// getQueueCount();
});
稍微解释一下。objectAudioList的值在getQueueCount: function () {中定义了
通过
$.inArray(file,objectAudioList)
可以获得,要删除的file在数组中的下标,然后根据下标删除掉该元素咯
objectAudioList.splice($.inArray(file,objectAudioList),1);
接下来,富文本中对于字数的限制只有提示,超过了之后还是可以输入,这样明显不合适,解决思路如下:
找到代码如下:
if (count > max) {//解决超过字数,只提示,还可以输入的问题
// countDom.innerHTML = errMsg;
// editor.fireEvent("wordcountoverflow");
msgalter('文章内容限5000字以内');
var content = editor.getContentTxt();
editor.setContent(content.substring(0,max));
editor.focus(true);
}
下一个bug 在有的人电脑上谷歌浏览器居然会出现ueditor无法滚动到底部工具栏浮动bug,解决方法
再这里是创建刚才div 的js ,这里加上编辑器的高就可以,量了一下大概79px,jia将上面代码替换为
placeHolder.style.height = toolbarBox.offsetHeight+120.75+ 'px';
这样 又解决了一个bug,基本上 视频音频上传就没有什么问题了。