当前位置: 代码迷 >> 综合 >> Tinymce 编辑器添加自定义图片管理插件
  详细解决方案

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

热度:41   发布时间:2024-01-20 07:56:36.0

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

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

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

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

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 Coreprivate 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();#endregionif (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