Tinymce 编辑器添加自定义图片管理插件

时间:2022-05-23 04:55:43

在使用Tinymce的过程中需要用到图片上传功能,而提供的上传插件在上传文件后是给了一个连接地址,就想用户需要什么图片,不能用最直观的方式表现出来么!

虽然官网上也有一个文件管理的插件moxiemanager,可奈何他是收费的!https://www.tiny.cloud/docs/plugins/moxiemanager/

然后就打算自己弄一个,其实实现效果起来很简单,就只是做了一个类型相册管理的功能,然后在点击图片的时候,将图片的地址信息插入到编辑器里就行了,由于后台用的是layui

的框架,所以界面也就用了layui来实现,这里我只弄了上传,删除功能,也可自己添加检索等功能,实现效果如下

Tinymce 编辑器添加自定义图片管理插件

1 、添加插件

我们需要在tinymce的 Plugins  目录下新建一个filemanager文件夹,并添加一个名为plugin.min.js ,其中editor传参后再图片管理页面通过

var editor = top.tinymce.activeEditor.windowManager.getParams().editor; 获取编辑器对象,进行图片插入操作

tinymce.PluginManager.add("filemanager", function (editor, url) {
editor.addButton("filemanager", {
title: "图片管理",
icon: 'image',
onclick: function () {
editor.windowManager.open({
title: "图片管理",
url: "/Administrator/Filemanager/Editor",
width: window.innerWidth * 0.9,
height: window.innerHeight * 0.8
}, {
editor: editor // pointer to access editor from cshtml
})
}
})
});

  

2. 相册功能实现

文件夹管理实体类

public class FileManagerDirectoryEntity : BaseEntity
{
/// <summary>
/// 父级Id
/// </summary>
public int ParentId { get; set; } /// <summary>
/// 文件夹名称
/// </summary>
public string Name { get; set; } /// <summary>
/// 路径
/// </summary>
public string FullPath { get; set; } /// <summary>
/// 子文件数量
/// </summary>
public int ChildrenCount { get; set; }
}

  

文件管理实体类

public class FileManagerDirectoryEntity : BaseEntity
{
/// <summary>
/// 父级Id
/// </summary>
public int ParentId { get; set; } /// <summary>
/// 文件夹名称
/// </summary>
public string Name { get; set; } /// <summary>
/// 路径
/// </summary>
public string FullPath { get; set; } /// <summary>
/// 子文件数量
/// </summary>
public int ChildrenCount { get; set; }
}

  

相册功能具体实现controller

public class FileManagerController : Controller
{ #region Core
private readonly IRepository<FileManagerDirectoryEntity> _fileManagerDirectoryRepository;
private readonly IRepository<FileManagerFilesEntity> _fileManagerFilesRepository;
private const string smallImage = "_small"; public FileManagerController(
IRepository<FileManagerDirectoryEntity> fileManagerDirectoryRepository,
IRepository<FileManagerFilesEntity> fileManagerFilesRepository
)
{
this._fileManagerDirectoryRepository = fileManagerDirectoryRepository;
this._fileManagerFilesRepository = fileManagerFilesRepository;
} #endregion /// <summary>
/// 编辑器插件
/// 获取文件数据
/// </summary>
/// <param name="dirId"></param>
/// <returns></returns>
public ActionResult Editor(int dirId = 0) { List<FileManagerFileModel> modelList = new List<FileManagerFileModel>(); //加载该文件夹下的文件夹
var dirList = _fileManagerDirectoryRepository.Table
.Where(x=>x.ParentId==dirId)
.OrderByDescending(x=>x.CreateTime)
.ToList();
foreach(var item in dirList)
{ FileManagerFileModel model = new FileManagerFileModel();
model.Id = item.Id;
model.Name = item.Name;
model.FullPath = item.FullPath;
model.FileType = 2;
model.ChildrenCount = item.ChildrenCount;
modelList.Add(model);
} //加载该文件夹下的图片文件
var fileList = _fileManagerFilesRepository.Table
.Where(x => x.DirectoryId == dirId)
.OrderByDescending(x => x.CreateTime)
.ToList();
foreach (var item in fileList)
{ FileManagerFileModel model = new FileManagerFileModel();
model.Id = item.Id;
model.Name = item.Name;
model.FullPath = item.FullPath;
model.SmallFullPath = item.FullPath + smallImage + item.FileExt;
model.FileType = 1;
modelList.Add(model);
} return View(modelList);
} /// <summary>
/// 创建文件夹
/// </summary>
/// <param name="dirId"></param>
/// <returns></returns>
public ActionResult _AddDirectory(int dirId) {
return View();
} /// <summary>
/// 文件夹信息保存
/// </summary>
/// <param name="dirId"></param>
/// <param name="dirName"></param>
/// <returns></returns>
public ActionResult _AddDirectorySave(int dirId , string dirName) {
var parentDirEntity = _fileManagerDirectoryRepository.GetById(dirId);
if (!string.IsNullOrEmpty(dirName))
{
var parentDirPath = parentDirEntity == null ? "/Content/FileManager/" : parentDirEntity.FullPath;
if(parentDirEntity != null)
{
parentDirEntity.ChildrenCount++;
} FileManagerDirectoryEntity entity = new FileManagerDirectoryEntity();
entity.ParentId = dirId;
entity.Name = dirName;
entity.FullPath = string.Format("{0}/{1}/", parentDirPath, Guid.NewGuid());
if (!Directory.Exists(Server.MapPath(entity.FullPath)))
{
Directory.CreateDirectory(Server.MapPath(entity.FullPath));
} _fileManagerDirectoryRepository.Insert(entity);
_fileManagerDirectoryRepository.SaveChanges();
}
return RedirectToAction("Editor",new { dirId = dirId});
} /// <summary>
/// 上传图片
/// </summary>
/// <param name="dirId"></param>
/// <returns></returns>
public JsonResult UploadImage(int dirId)
{
//路径地址
string fileUrl = "";
var parentDirEntity = _fileManagerDirectoryRepository.GetById(dirId);
var parentDirPath = parentDirEntity == null ? "/Content/FileManager/" : parentDirEntity.FullPath; HttpFileCollectionBase postfile = HttpContext.Request.Files;
if (postfile == null)
{
return Json(new { code = 1, msg = "文件不能为空" });
} var file = postfile[0];
string extName = Path.GetExtension(file.FileName); using (System.Drawing.Image image = System.Drawing.Image.FromStream(file.InputStream))
{ string fileName = Guid.NewGuid().ToString() + extName;
string smallImgName = string.Format("{0}{1}{2}", fileName, smallImage, extName); string route = Server.MapPath(parentDirPath);
fileUrl = Path.Combine(parentDirPath, fileName);
string savePath = Path.Combine(route, fileName);
//缩略图路径
string smallImgPath = Path.Combine(route, smallImgName); //生成缩略图
try
{
ImageResizer.Fit(image, 160, 160, ImageResizeMode.Crop, ImageResizeScale.Down).Save(smallImgPath);
}
catch (Exception)
{
return Json(new { flag = false, msg = "生成缩略图出错!" });
} file.SaveAs(savePath);
} #region 添加数据到素材表
FileManagerFilesEntity entity = new FileManagerFilesEntity();
entity.FileExt = extName;
entity.FullPath = fileUrl;
entity.Name = Path.GetFileNameWithoutExtension(file.FileName);
entity.DirectoryId = dirId;
entity.Size = file.ContentLength; _fileManagerFilesRepository.Insert(entity);
_fileManagerFilesRepository.SaveChanges();
#endregion if (parentDirEntity != null)
{
parentDirEntity.ChildrenCount++;
}
_fileManagerDirectoryRepository.SaveChanges(); return Json(new { code = 0 });
} public class DeleteFilesParams
{
public int Id { get; set; } public int Type { get; set; }
} /// <summary>
/// 删除选中文件夹及图片
/// </summary>
/// <returns></returns>
public JsonResult CheckedFilesDelete(List<DeleteFilesParams> checkeds)
{
var directoryList = _fileManagerDirectoryRepository.Table.ToList();
var fileList = _fileManagerFilesRepository.Table.ToList(); foreach(var item in checkeds)
{
//删除图片
if (item.Type == 1)
{
var fileEntity = fileList.FirstOrDefault(x => x.Id == item.Id);
string path = Server.MapPath(fileEntity.FullPath);
if (System.IO.File.Exists(path))
{
System.IO.File.Delete(path);
} var parentDir = directoryList.Find(x => x.Id == fileEntity.DirectoryId);
if (parentDir != null)
{
parentDir.ChildrenCount--;
} _fileManagerFilesRepository.Delete(fileEntity);
}
else
{
var dirEntity = directoryList.FirstOrDefault(x => x.Id == item.Id);
DeleteChildDirFiles(dirEntity.Id, directoryList, fileList);
string path = Server.MapPath(dirEntity.FullPath);
if (Directory.Exists(path))
{
Directory.Delete(path, true);
} var parentDir = directoryList.Find(x => x.Id == dirEntity.ParentId);
if (parentDir != null)
{
parentDir.ChildrenCount--;
} _fileManagerDirectoryRepository.Delete(dirEntity);
}
}
_fileManagerFilesRepository.SaveChanges();
_fileManagerDirectoryRepository.SaveChanges(); return Json(new { code = 0 });
} public void DeleteChildDirFiles(int pid,List<FileManagerDirectoryEntity> dirList, List<FileManagerFilesEntity> files) {
var dirEntityList = dirList.Where(x => x.ParentId == pid);
var fileEntityList = files.Where(x => x.DirectoryId == pid);
foreach (var item in dirEntityList)
{
DeleteChildDirFiles(item.Id, dirList, files);
_fileManagerDirectoryRepository.Delete(item);
} foreach (var item in fileEntityList)
{
_fileManagerFilesRepository.Delete(item);
}
_fileManagerDirectoryRepository.SaveChanges();
_fileManagerFilesRepository.SaveChanges(); }
}

文件管理页面 Editor.chtml

 

@using Web.Areas.Administrator.Models
@model List<FileManagerFileModel>
@{
Layout = null;
} <!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>文件管理</title>
<link href="/Assets/iconfont/iconfont.css" rel="stylesheet" />
<link href="/Scripts/layui/css/layui.css" rel="stylesheet" />
<style>
body { background: #f6f6f6; }
.toolbar { padding: 10px; background: #fff; }
.toolbar i.iconfont{margin-right:10px;}
.file-list{margin:20px;}
.file-list li { float: left; background:#fff; margin-bottom:20px; margin-right:20px; }
.file-list li .img-wapper { width:160px; }
.file-list li .img-wapper img{width:100%; height:160px;}
.file-list li .file-name { padding: 0 10px; width: 100%; overflow:hidden; line-height: 30px; height:30px; color: #666; font-size: 12px; background: #fafafa; }
.file-list li .file-name .layui-form-checkbox{width:140px !important; overflow:hidden !important; }
.file-list li:hover { box-shadow: 0 0 10px rgba(0,0,0,.1); }
.file-list li:hover .file-name { background: #f5f5f5;}
</style>
</head>
<body>
<div class="toolbar">
<a class="layui-btn layui-btn-small" href="javascript:;" data-toggle="modal" data-title="新建文件夹" data-url="@Url.Action("_AddDirectory",new { dirId = Request["dirId"] == null ? 0 : int.Parse(Request["dirId"])})">
<i class="iconfont icon-directory"></i>
新建文件夹
</a>
<button id="upload-img-btn" type="button" class="layui-btn"><i class="iconfont icon-photo"></i>上传图片</button>
<button id="delete-img-btn" type="button" class="layui-btn layui-btn-danger"><i class="iconfont icon-photo"></i>删除图片</button>
</div>
<div class="layui-form">
<ul class="file-list">
@if (!string.IsNullOrWhiteSpace(Request["dirId"]))
{
<li class="file-item">
<div class="img-wapper">
<a href="javascript:history.back(-1);">
<img src="/Assets/images/default/admin_directory_back.png" alt="返回上级" title="返回上级" />
</a>
</div>
<div class="file-name">
...
</div>
</li>
}
@if (Model.Any())
{
foreach (var item in Model)
{
<li class="file-item">
@if (item.FileType == 1)
{
<div class="img-wapper">
<a href="javascript:;" class="file-img" data-url="@item.FullPath" data-title="@item.Name">
<img src="@item.SmallFullPath" title="@item.Name" />
</a>
</div>
<div class="file-name">
<input type="checkbox" name="file-id" lay-skin="primary" title="@item.Name" data-id="@item.Id" data-type="1">
</div>
}
else
{
<div class="img-wapper">
<a href="@Url.Action("Editor",new { dirId=item.Id})">
@if (item.ChildrenCount > 0)
{
<img src="/Assets/images/default/admin_directory_files.png" title="@item.Name" />
}
else
{
<img src="/Assets/images/default/admin_directory.png" title="@item.Name" />
}
</a>
</div>
<div class="file-name">
<input type="checkbox" name="file-id" lay-skin="primary" title="@item.Name" data-id="@item.Id" data-type="2">
</div>
}
</li>
}
}
</ul>
</div>
<input id="dirId" value="@Request["dirId"]" hidden>
<script src="~/Scripts/jquery-3.2.1.min.js"></script>
<script src="/Scripts/layui/layui.js"></script>
<script>
//获取tinymce编辑器
var editor = top.tinymce.activeEditor.windowManager.getParams().editor; layui.use(['upload'], function () {
var upload = layui.upload;
var dirId = $("#dirId").val() == "" ? 0 : $("#dirId").val();
upload.render({ //允许上传的文件后缀
elem: '#upload-img-btn'
, url: 'UploadImage?dirId=' + dirId
, accept: 'file' //普通文件
, multiple: true
, size: 1024 * 2 //限制文件大小,单位 KB
, exts: 'jpg|jpeg|png|gif' //只允许上传压缩文件
, done: function (res) {
if (res.code == 0) {
window.location.reload();
}
}
}); //删除图片
$("#delete-img-btn").click(function () {
var checkeds = [];
$("input[name='file-id']:checkbox").each(function () {
if (true == $(this).is(':checked')) {
checkeds.push({
id: $(this).data('id'),
type: $(this).data('type')
});
}
});
if (checkeds.length == 0) {
layer.alert('请先选择需要删除的文件!');
}
else {
layer.confirm('删除后将无法恢复,请确认是否要删除所选文件?', {
btn: ['确定删除', '我在想想'] //按钮
}, function () {
$.ajax({
type: 'post',
url: 'CheckedFilesDelete',
data: { checkeds : checkeds },
success: function (result) {
if (result.code == 0) {
window.location.reload();
}
else {
showMsg(result.msg);
}
}
})
}, function () {
});
}
})
}) //添加图片至编辑器
$(".file-img").click(function () {
var url = $(this).data("url"),
title = $(this).data("title"); //添加确认
layer.confirm('是否需要添加此图片?', {
btn: ['确认添加', '我在想想'] //按钮
}, function () {
editor.execCommand('mceInsertContent', false, '<img alt="' + title + '" src="' + url + '"/>');
editor.windowManager.close();
}, function () {});
}) </script>
<script>
//layui基本代码
$(function () {
layui.use(['element', 'form', "layer"], function () {
var element = layui.element; //表单渲染
var form = layui.form;
form.on('submit(formDemo)', function (data) {
layer.msg(JSON.stringify(data.field));
return false;
});
form.render(); //异步加载modal
$(document).on("click", '[data-toggle="modal"]', function (e) {
var $this = $(this),
url = $(this).data('url'),
title = $(this).data("title")
if (url) {
$.ajax({
url: url,
data: { rnd: Math.random() },
//dataType: 'html',
success: function (data) {
//示范一个公告层
layer.open({
type: 1
, title: title //不显示标题栏
, shade: 0.8
, shadeClose: true
, fixed: false
, area: ["900px"]
, offset: '40px'
, id: 'ajax-modal-wapper' //设定一个id,防止重复弹出
, move: false //禁止拖拽
, content: data
});
},
error: function (XMLHttpRequest, textStatus, errorThrown) {
alert('加载出错。' + textStatus + '. ' + XMLHttpRequest.status);
},
complete: function () {
}
});
}
});
});
})
</script>
</body>
</html>

  

新增文件夹页面 _AddDirectory.chtml

@{
Layout = null;
} <div class="modal-content" style="padding-top:20px;">
<form class="layui-form" action="_AddDirectorySave" method="post" enctype="multipart/form-data">
<input name="dirId" value="@Request["dirId"]" hidden>
<div class="layui-form-item">
<label class="layui-form-label" for="dirName">文件夹名称</label>
<div class="layui-input-block">
<input class="layui-input" id="dirName" lay-verify="required" name="dirName" placeholder="请输入文件夹名称" type="text" value="">
</div>
</div>
<div class="layui-form-item">
<div class="layui-input-block">
<button class="layui-btn" lay-submit lay-filter="account-form" type="submit">保存信息</button>
</div>
</div>
</form>
</div>

  

3. 将选中图片插入编辑器

在图片列表的页面中,我们只需要在点击图片的事件中调用Tinymce编辑器的插入方法即可,以下为插入图片的代码

<script>
//获取tinymce编辑器
var editor = top.tinymce.activeEditor.windowManager.getParams().editor; layui.use(['upload'], function () {
var upload = layui.upload;
var dirId = $("#dirId").val() == "" ? 0 : $("#dirId").val();
upload.render({ //允许上传的文件后缀
elem: '#upload-img-btn'
, url: 'UploadImage?dirId=' + dirId
, accept: 'file' //普通文件
, multiple: true
, size: 1024 * 2 //限制文件大小,单位 KB
, exts: 'jpg|jpeg|png|gif' //只允许上传压缩文件
, done: function (res) {
if (res.code == 0) {
window.location.reload();
}
}
}); //删除图片
$("#delete-img-btn").click(function () {
var checkeds = [];
$("input[name='file-id']:checkbox").each(function () {
if (true == $(this).is(':checked')) {
checkeds.push({
id: $(this).data('id'),
type: $(this).data('type')
});
}
});
if (checkeds.length == 0) {
layer.alert('请先选择需要删除的文件!');
}
else {
layer.confirm('删除后将无法恢复,请确认是否要删除所选文件?', {
btn: ['确定删除', '我在想想'] //按钮
}, function () {
$.ajax({
type: 'post',
url: 'CheckedFilesDelete',
data: { checkeds : checkeds },
success: function (result) {
if (result.code == 0) {
window.location.reload();
}
else {
showMsg(result.msg);
}
}
})
}, function () {
});
}
})
}) //添加图片至编辑器
$(".file-img").click(function () {
var url = $(this).data("url"),
title = $(this).data("title"); //添加确认
layer.confirm('是否需要添加此图片?', {
btn: ['确认添加', '我在想想'] //按钮
}, function () {
editor.execCommand('mceInsertContent', false, '<img alt="' + title + '" src="' + url + '"/>');
editor.windowManager.close();
}, function () {});
}) </script>

 Ps: 还有很多的不足之处,希望能一起成长, 我的博客地址 jiojun.com