前言:
单一的批量图片上传按钮,禁用tinymce编辑器,但是还可以操作图片编辑;
多元化格式的富文本编辑要求;
采用tinymce实现。
附:
tinymce中文手册网站:
http://tinymce.ax-z.cn/download-all.php
tinymce下载地址:
社区版: http://download.tiny.cloud/tinymce/community/tinymce_5.10.0.zip
开发版:http://download.tiny.cloud/tinymce/community/tinymce_5.10.0_dev.zip
auxipimage批量图片插件下载地址:
百度风盘链接:链接: https://pan.baidu.com/s/1w4RE_an7Xi8KLLAVm6kf4A 提取码: ivjj
参考项目代码:
https://gitee.com/tonyjoba_deen/ssm_-shiro_-tiny-mce/tree/feature
效果
核心代码:(引入了网上大佬们无私奉献的tinymce批量上传图片插件,感谢,注意插件的plugin.js或者plugin.min.js里面的base路径需要根据实际的项目目录更改。另外,我这里时集成了EasyUi,通过dialog弹框的形式使用富文本编辑器,部分的css样式不能加载,只能采用skin_url的形式。如果有更好的操作,欢迎评论发言)。
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ include file="../../page/common/head.jsp" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
<style lang="scss">
/* 在el-dialog中使用tinymce z-index被遮挡 */
.tox-editor-container{
z-index: 9999 !important;
}
.tox-tinymce-aux {
z-index: 9999 !important;
}
/*隐藏文本输入框*/
.tox-sidebar-wrap{
}
</style>
<script src="${ctx}/tinymce/tinymce.min.js"></script>
<script src="${ctx}/tinymce/themes/silver/theme.min.js"></script>
<script src="${ctx}/tinymce/models/dom/model.min.js"></script>
<script src="${ctx}/tinymce/icons/default/icons.min.js"></script>
<script src="${ctx}/tinymce/plugins/image/plugin.min.js"></script>
<script src="${ctx}/tinymce/plugins/axupimgs/plugin.min.js"></script>
<script src="${ctx}/tinymce/plugins/quickbars/plugin.min.js"></script>
<script src="${ctx}/tinymce/langs/zh-Hans.js"></script>
<script type="text/javascript">
/*获取每个tinyEditor的输入值,tinymce.get('my-tinymce-editor').getContent()*/
tinymce.init(
{
selector: '#myfeel',
skin: 'oxide-dark',
language:'zh-Hans',
/*inline:true,
toolbar_persist:true,*/
placeholder:"再次输入感受内容!",
skin_url:'${ctx}/tinymce/skins/ui/oxide-dark',
content_css:
'${ctx}/tinymce/skins/content/default/content.min.css',
statusbar:true,/*隐藏状态栏,就是下方的tinmce的官网链接行*/
promotion: false,/*去除upgrade标识*/
branding:false,/*去掉广告标tiny*/
plugins: "image axupimgs",
toolbar: "undo redo newdocument bold italic underline strikethrough subscript superscript | removeformat | selectall cut copy paste | image axupimgs",
images_upload_handler: (blobInfo, progress) => new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest();
xhr.withCredentials = false;
xhr.open('POST', 'uploadFile');
xhr.upload.onprogress = (e) => {
progress(e.loaded / e.total * 100);
};
xhr.onload = () => {
if (xhr.status === 403) {
reject({ message: 'HTTP Error: ' + xhr.status, remove: true });
return;
}
if (xhr.status < 200 || xhr.status >= 300) {
reject('HTTP Error: ' + xhr.status);
return;
}
const json = JSON.parse(xhr.responseText);
if (!json || typeof json.location != 'string') {
reject('Invalid JSON: ' + xhr.responseText);
return;
}
resolve(json.location);
};
xhr.onerror = () => {
reject('Image upload failed due to a XHR Transport error. Code: ' + xhr.status);
};
const formData = new FormData();
formData.append('file', blobInfo.blob(), blobInfo.filename());
xhr.send(formData);
})
});
</script>
<script>
tinymce.init(
{
selector: '#mytinydemo',
language:'zh-Hans',
height:200,
placeholder:"点击上方按钮上传图片,上传成功后点击保存至此处!",
skin_url:'${ctx}/tinymce/skins/ui/oxide',
content_css:
'${ctx}/tinymce/skins/content/default/content.min.css',
// ...其他TinyMCE配置
plugins: "image axupimgs",
toolbar: "axupimgs",
menubar:false, /*隐藏菜单栏*/
statusbar:true,/*隐藏状态栏,就是下方的tinmce的官网链接行*/
promotion: false,/*去除upgrade标识*/
branding:false,/*去掉广告标tiny*/
//images_upload_url: 'uploadFile',//指定一个接受上传文件的后端处理程序地址
//如果返回的地址是相对路径,还有一个参数images_upload_base_path,可以给相对路径指定它所相对的基本路径
// images_upload_base_path: '/demo',
images_upload_handler: function (blobInfo, succFun, failFun) {
var xhr, formData;
var file = blobInfo.blob();//转化为易于理解的file对象
xhr = new XMLHttpRequest();
xhr.withCredentials = false;
xhr.open('POST', 'uploadFile');
xhr.onload = function() {
//上传完成回调
var json;
if (xhr.status != 200) {
failFun('HTTP Error: ' + xhr.status);
return;
}
json = JSON.parse(xhr.responseText);
if (!json || typeof json.location != 'string') {
failFun('Invalid JSON: ' + xhr.responseText);
return;
}
succFun(json.location);
};
formData = new FormData();
formData.append('file', file, file.name );//此处与源文档不一样
xhr.send(formData);
},
// 添加`keydown`和`keydown`事件,实现编辑器的禁用
setup: function (ed) {
var tempVal = "";
/*禁用编辑按钮,实现只负责文件图片的处理*/
ed.on('keydown', function (e) {
if(e.key=='Backspace' || e.key=="Delete"){
}else{
e.preventDefault();
return false;
}
});
ed.on('keyup', function (e) {
if(e.key=='backspace'){
}else{
e.preventDefault();
return false;
}
});
ed.on('copy',function(e){
return false;
});
ed.on('cut',function(e){
return false;
});
ed.on('paste',function(e){
return false;
});
ed.on('compositionstart',function(e){
tempVal = tinymce.get('mytinydemo').getContent();
});
ed.on('compositionend',function(e){
tinymce.get('mytinydemo').setContent(tempVal);
});
},
file_picker_callback: function(callback, value, meta) {
//文件上传,注意插件是link
//文件分类
var filetype='.pdf, .txt, .zip, .rar, .7z, .doc, .docx, .xls, .xlsx, .ppt, .pptx, .mp3, .mp4';
//后端接收上传文件的地址
var upurl='uploadFile';
//为不同插件指定文件类型及后端地址
switch(meta.filetype){
case 'image':
filetype='.jpg, .jpeg, .png, .gif';
upurl='upimg.php';
break;
case 'media':
filetype='.mp3, .mp4';
upurl='upfile.php';
break;
case 'file':
default:
}
//模拟出一个input用于添加本地文件
var input = document.createElement('input');
input.setAttribute('type', 'file');
input.setAttribute('accept', filetype);
input.click();
input.onchange = function() {
var file = this.files[0];
var xhr, formData;
console.log(file.name);
xhr = new XMLHttpRequest();
xhr.withCredentials = false;
xhr.open('POST', upurl);
xhr.onload = function() {
var json;
if (xhr.status != 200) {
failure('HTTP Error: ' + xhr.status);
return;
}
json = JSON.parse(xhr.responseText);
if (!json || typeof json.location != 'string') {
failure('Invalid JSON: ' + xhr.responseText);
return;
}
callback(json.location);
};
formData = new FormData();
formData.append('file', file, file.name );
xhr.send(formData);
}
}
});
$("#feel_edit_submit").click(function(){
$('#feel_edit_form').form('submit', {
url:"user/submitUserInfo123123123223123",
onSubmit: function(){
$.messager.progress(); // 显示进度条
var isValid = $(this).form('validate');
if (!isValid){
$.messager.progress('close'); // 如果表单是无效的则隐藏进度条
}
return isValid; // 返回false终止表单提交
},
success:function(data){
$.messager.progress('close'); // 如果提交成功则隐藏进度条
if(data==1){
$.messager.show({
title:'系统消息',
msg:'修改成功',
timeout:3000,
showType:'slide'
});
//弹出框关闭
$("#role_dialog").dialog("close");
$('#role_table').datagrid('reload');
}else{
$.messager.alert("系统信息","修改失败,请重新修改");
}
}
});
})
</script>
</head>
<body>
<div style="padding:10px;">
论坛管理 >> 文章管理
<hr/>
<form action="" method="post" id="feel_edit_form">
<input type="hidden" name="id"/>
<table width="800px">
<tr>
<td>标题:</td>
<td><input type="text" name="title"/> </td>
</tr>
<tr>
<td>图片:</td>
<td>
<div id="mytinydemo" ></div>
</td>
</tr>
<tr>
<td>正文:</td>
<td><textarea id="myfeel" type="text" name="remark"/> </td>
</tr>
<tr>
<td colspan="2">
<a id="feel_edit_submit" href="#" class="easyui-linkbutton"
data-options="iconCls:'icon-search'">发布</a>
</td>
</tr>
</table>
</form>
</div>
</body>
</html>