经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » JSJS库框架 » jQuery » 查看文章
Tinymce 编辑器添加自定义图片管理插件
来源:cnblogs  作者:JioJun  时间:2018/9/30 11:22:57  对本文有异议

在使用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; 获取编辑器对象,进行图片插入操作

  1. tinymce.PluginManager.add("filemanager", function (editor, url) {
  2. editor.addButton("filemanager", {
  3. title: "图片管理",
  4. icon: 'image',
  5. onclick: function () {
  6. editor.windowManager.open({
  7. title: "图片管理",
  8. url: "/Administrator/Filemanager/Editor",
  9. width: window.innerWidth * 0.9,
  10. height: window.innerHeight * 0.8
  11. }, {
  12. editor: editor // pointer to access editor from cshtml
  13. })
  14. }
  15. })
  16. });

  

2. 相册功能实现

文件夹管理实体类

  1. public class FileManagerDirectoryEntity : BaseEntity
  2. {
  3. /// <summary>
  4. /// 父级Id
  5. /// </summary>
  6. public int ParentId { get; set; }
  7.  
  8. /// <summary>
  9. /// 文件夹名称
  10. /// </summary>
  11. public string Name { get; set; }
  12.  
  13. /// <summary>
  14. /// 路径
  15. /// </summary>
  16. public string FullPath { get; set; }
  17.  
  18. /// <summary>
  19. /// 子文件数量
  20. /// </summary>
  21. public int ChildrenCount { get; set; }
  22. }

  

文件管理实体类

  1. public class FileManagerDirectoryEntity : BaseEntity
  2. {
  3. /// <summary>
  4. /// 父级Id
  5. /// </summary>
  6. public int ParentId { get; set; }
  7.  
  8. /// <summary>
  9. /// 文件夹名称
  10. /// </summary>
  11. public string Name { get; set; }
  12.  
  13. /// <summary>
  14. /// 路径
  15. /// </summary>
  16. public string FullPath { get; set; }
  17.  
  18. /// <summary>
  19. /// 子文件数量
  20. /// </summary>
  21. public int ChildrenCount { get; set; }
  22. }

  

相册功能具体实现controller

  1. public class FileManagerController : Controller
  2. {
  3.  
  4. #region Core
  5. private readonly IRepository<FileManagerDirectoryEntity> _fileManagerDirectoryRepository;
  6. private readonly IRepository<FileManagerFilesEntity> _fileManagerFilesRepository;
  7. private const string smallImage = "_small";
  8.  
  9. public FileManagerController(
  10. IRepository<FileManagerDirectoryEntity> fileManagerDirectoryRepository,
  11. IRepository<FileManagerFilesEntity> fileManagerFilesRepository
  12. )
  13. {
  14. this._fileManagerDirectoryRepository = fileManagerDirectoryRepository;
  15. this._fileManagerFilesRepository = fileManagerFilesRepository;
  16. }
  17.  
  18. #endregion
  19.  
  20.  
  21. /// <summary>
  22. /// 编辑器插件
  23. /// 获取文件数据
  24. /// </summary>
  25. /// <param name="dirId"></param>
  26. /// <returns></returns>
  27. public ActionResult Editor(int dirId = 0) {
  28.  
  29. List<FileManagerFileModel> modelList = new List<FileManagerFileModel>();
  30. //加载该文件夹下的文件夹
  31. var dirList = _fileManagerDirectoryRepository.Table
  32. .Where(x=>x.ParentId==dirId)
  33. .OrderByDescending(x=>x.CreateTime)
  34. .ToList();
  35. foreach(var item in dirList)
  36. {
  37.  
  38. FileManagerFileModel model = new FileManagerFileModel();
  39. model.Id = item.Id;
  40. model.Name = item.Name;
  41. model.FullPath = item.FullPath;
  42. model.FileType = 2;
  43. model.ChildrenCount = item.ChildrenCount;
  44. modelList.Add(model);
  45. }
  46.  
  47. //加载该文件夹下的图片文件
  48. var fileList = _fileManagerFilesRepository.Table
  49. .Where(x => x.DirectoryId == dirId)
  50. .OrderByDescending(x => x.CreateTime)
  51. .ToList();
  52. foreach (var item in fileList)
  53. {
  54.  
  55. FileManagerFileModel model = new FileManagerFileModel();
  56. model.Id = item.Id;
  57. model.Name = item.Name;
  58. model.FullPath = item.FullPath;
  59. model.SmallFullPath = item.FullPath + smallImage + item.FileExt;
  60. model.FileType = 1;
  61. modelList.Add(model);
  62. }
  63.  
  64. return View(modelList);
  65. }
  66.  
  67. /// <summary>
  68. /// 创建文件夹
  69. /// </summary>
  70. /// <param name="dirId"></param>
  71. /// <returns></returns>
  72. public ActionResult _AddDirectory(int dirId) {
  73. return View();
  74. }
  75.  
  76. /// <summary>
  77. /// 文件夹信息保存
  78. /// </summary>
  79. /// <param name="dirId"></param>
  80. /// <param name="dirName"></param>
  81. /// <returns></returns>
  82. public ActionResult _AddDirectorySave(int dirId , string dirName) {
  83. var parentDirEntity = _fileManagerDirectoryRepository.GetById(dirId);
  84. if (!string.IsNullOrEmpty(dirName))
  85. {
  86. var parentDirPath = parentDirEntity == null ? "/Content/FileManager/" : parentDirEntity.FullPath;
  87. if(parentDirEntity != null)
  88. {
  89. parentDirEntity.ChildrenCount++;
  90. }
  91.  
  92. FileManagerDirectoryEntity entity = new FileManagerDirectoryEntity();
  93. entity.ParentId = dirId;
  94. entity.Name = dirName;
  95. entity.FullPath = string.Format("{0}/{1}/", parentDirPath, Guid.NewGuid());
  96. if (!Directory.Exists(Server.MapPath(entity.FullPath)))
  97. {
  98. Directory.CreateDirectory(Server.MapPath(entity.FullPath));
  99. }
  100.  
  101. _fileManagerDirectoryRepository.Insert(entity);
  102. _fileManagerDirectoryRepository.SaveChanges();
  103. }
  104. return RedirectToAction("Editor",new { dirId = dirId});
  105. }
  106.  
  107. /// <summary>
  108. /// 上传图片
  109. /// </summary>
  110. /// <param name="dirId"></param>
  111. /// <returns></returns>
  112. public JsonResult UploadImage(int dirId)
  113. {
  114. //路径地址
  115. string fileUrl = "";
  116. var parentDirEntity = _fileManagerDirectoryRepository.GetById(dirId);
  117. var parentDirPath = parentDirEntity == null ? "/Content/FileManager/" : parentDirEntity.FullPath;
  118.  
  119. HttpFileCollectionBase postfile = HttpContext.Request.Files;
  120. if (postfile == null)
  121. {
  122. return Json(new { code = 1, msg = "文件不能为空" });
  123. }
  124.  
  125. var file = postfile[0];
  126. string extName = Path.GetExtension(file.FileName);
  127.  
  128. using (System.Drawing.Image image = System.Drawing.Image.FromStream(file.InputStream))
  129. {
  130.  
  131. string fileName = Guid.NewGuid().ToString() + extName;
  132. string smallImgName = string.Format("{0}{1}{2}", fileName, smallImage, extName);
  133.  
  134. string route = Server.MapPath(parentDirPath);
  135. fileUrl = Path.Combine(parentDirPath, fileName);
  136. string savePath = Path.Combine(route, fileName);
  137. //缩略图路径
  138. string smallImgPath = Path.Combine(route, smallImgName);
  139.  
  140. //生成缩略图
  141. try
  142. {
  143. ImageResizer.Fit(image, 160, 160, ImageResizeMode.Crop, ImageResizeScale.Down).Save(smallImgPath);
  144. }
  145. catch (Exception)
  146. {
  147. return Json(new { flag = false, msg = "生成缩略图出错!" });
  148. }
  149.  
  150. file.SaveAs(savePath);
  151. }
  152.  
  153. #region 添加数据到素材表
  154. FileManagerFilesEntity entity = new FileManagerFilesEntity();
  155. entity.FileExt = extName;
  156. entity.FullPath = fileUrl;
  157. entity.Name = Path.GetFileNameWithoutExtension(file.FileName);
  158. entity.DirectoryId = dirId;
  159. entity.Size = file.ContentLength;
  160.  
  161. _fileManagerFilesRepository.Insert(entity);
  162. _fileManagerFilesRepository.SaveChanges();
  163. #endregion
  164.  
  165.  
  166. if (parentDirEntity != null)
  167. {
  168. parentDirEntity.ChildrenCount++;
  169. }
  170. _fileManagerDirectoryRepository.SaveChanges();
  171.  
  172. return Json(new { code = 0 });
  173. }
  174.  
  175.  
  176.  
  177. public class DeleteFilesParams
  178. {
  179. public int Id { get; set; }
  180.  
  181. public int Type { get; set; }
  182. }
  183.  
  184. /// <summary>
  185. /// 删除选中文件夹及图片
  186. /// </summary>
  187. /// <returns></returns>
  188. public JsonResult CheckedFilesDelete(List<DeleteFilesParams> checkeds)
  189. {
  190. var directoryList = _fileManagerDirectoryRepository.Table.ToList();
  191. var fileList = _fileManagerFilesRepository.Table.ToList();
  192.  
  193.  
  194. foreach(var item in checkeds)
  195. {
  196. //删除图片
  197. if (item.Type == 1)
  198. {
  199. var fileEntity = fileList.FirstOrDefault(x => x.Id == item.Id);
  200. string path = Server.MapPath(fileEntity.FullPath);
  201. if (System.IO.File.Exists(path))
  202. {
  203. System.IO.File.Delete(path);
  204. }
  205.  
  206.  
  207. var parentDir = directoryList.Find(x => x.Id == fileEntity.DirectoryId);
  208. if (parentDir != null)
  209. {
  210. parentDir.ChildrenCount--;
  211. }
  212.  
  213. _fileManagerFilesRepository.Delete(fileEntity);
  214. }
  215. else
  216. {
  217. var dirEntity = directoryList.FirstOrDefault(x => x.Id == item.Id);
  218. DeleteChildDirFiles(dirEntity.Id, directoryList, fileList);
  219. string path = Server.MapPath(dirEntity.FullPath);
  220. if (Directory.Exists(path))
  221. {
  222. Directory.Delete(path, true);
  223. }
  224.  
  225.  
  226. var parentDir = directoryList.Find(x => x.Id == dirEntity.ParentId);
  227. if (parentDir != null)
  228. {
  229. parentDir.ChildrenCount--;
  230. }
  231.  
  232. _fileManagerDirectoryRepository.Delete(dirEntity);
  233. }
  234. }
  235. _fileManagerFilesRepository.SaveChanges();
  236. _fileManagerDirectoryRepository.SaveChanges();
  237.  
  238. return Json(new { code = 0 });
  239. }
  240.  
  241. public void DeleteChildDirFiles(int pid,List<FileManagerDirectoryEntity> dirList, List<FileManagerFilesEntity> files) {
  242. var dirEntityList = dirList.Where(x => x.ParentId == pid);
  243. var fileEntityList = files.Where(x => x.DirectoryId == pid);
  244. foreach (var item in dirEntityList)
  245. {
  246. DeleteChildDirFiles(item.Id, dirList, files);
  247. _fileManagerDirectoryRepository.Delete(item);
  248. }
  249.  
  250. foreach (var item in fileEntityList)
  251. {
  252. _fileManagerFilesRepository.Delete(item);
  253. }
  254. _fileManagerDirectoryRepository.SaveChanges();
  255. _fileManagerFilesRepository.SaveChanges();
  256.  
  257. }
  258. }

 

文件管理页面 Editor.chtml

 

  1. @using Web.Areas.Administrator.Models
  2. @model List<FileManagerFileModel>
  3. @{
  4. Layout = null;
  5. }
  6.  
  7. <!DOCTYPE html>
  8. <html>
  9. <head>
  10. <meta name="viewport" content="width=device-width" />
  11. <title>文件管理</title>
  12. <link href="/Assets/iconfont/iconfont.css" rel="stylesheet" />
  13. <link href="/Scripts/layui/css/layui.css" rel="stylesheet" />
  14. <style>
  15. body { background: #f6f6f6; }
  16. .toolbar { padding: 10px; background: #fff; }
  17. .toolbar i.iconfont{margin-right:10px;}
  18. .file-list{margin:20px;}
  19. .file-list li { float: left; background:#fff; margin-bottom:20px; margin-right:20px; }
  20. .file-list li .img-wapper { width:160px; }
  21. .file-list li .img-wapper img{width:100%; height:160px;}
  22. .file-list li .file-name { padding: 0 10px; width: 100%; overflow:hidden; line-height: 30px; height:30px; color: #666; font-size: 12px; background: #fafafa; }
  23. .file-list li .file-name .layui-form-checkbox{width:140px !important; overflow:hidden !important; }
  24. .file-list li:hover { box-shadow: 0 0 10px rgba(0,0,0,.1); }
  25. .file-list li:hover .file-name { background: #f5f5f5;}
  26. </style>
  27. </head>
  28. <body>
  29. <div class="toolbar">
  30. <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"])})">
  31. <i class="iconfont icon-directory"></i>
  32. 新建文件夹
  33. </a>
  34. <button id="upload-img-btn" type="button" class="layui-btn"><i class="iconfont icon-photo"></i>上传图片</button>
  35. <button id="delete-img-btn" type="button" class="layui-btn layui-btn-danger"><i class="iconfont icon-photo"></i>删除图片</button>
  36. </div>
  37. <div class="layui-form">
  38. <ul class="file-list">
  39. @if (!string.IsNullOrWhiteSpace(Request["dirId"]))
  40. {
  41. <li class="file-item">
  42. <div class="img-wapper">
  43. <a href="javascript:history.back(-1);">
  44. <img src="/Assets/images/default/admin_directory_back.png" alt="返回上级" title="返回上级" />
  45. </a>
  46. </div>
  47. <div class="file-name">
  48. ...
  49. </div>
  50. </li>
  51. }
  52. @if (Model.Any())
  53. {
  54. foreach (var item in Model)
  55. {
  56. <li class="file-item">
  57. @if (item.FileType == 1)
  58. {
  59. <div class="img-wapper">
  60. <a href="javascript:;" class="file-img" data-url="@item.FullPath" data-title="@item.Name">
  61. <img src="@item.SmallFullPath" title="@item.Name" />
  62. </a>
  63. </div>
  64. <div class="file-name">
  65. <input type="checkbox" name="file-id" lay-skin="primary" title="@item.Name" data-id="@item.Id" data-type="1">
  66. </div>
  67. }
  68. else
  69. {
  70. <div class="img-wapper">
  71. <a href="@Url.Action("Editor",new { dirId=item.Id})">
  72. @if (item.ChildrenCount > 0)
  73. {
  74. <img src="/Assets/images/default/admin_directory_files.png" title="@item.Name" />
  75. }
  76. else
  77. {
  78. <img src="/Assets/images/default/admin_directory.png" title="@item.Name" />
  79. }
  80. </a>
  81. </div>
  82. <div class="file-name">
  83. <input type="checkbox" name="file-id" lay-skin="primary" title="@item.Name" data-id="@item.Id" data-type="2">
  84. </div>
  85. }
  86. </li>
  87. }
  88. }
  89. </ul>
  90. </div>
  91. <input id="dirId" value="@Request["dirId"]" hidden>
  92. <script src="~/Scripts/jquery-3.2.1.min.js"></script>
  93. <script src="/Scripts/layui/layui.js"></script>
  94. <script>
  95. //获取tinymce编辑器
  96. var editor = top.tinymce.activeEditor.windowManager.getParams().editor;
  97.  
  98. layui.use(['upload'], function () {
  99. var upload = layui.upload;
  100. var dirId = $("#dirId").val() == "" ? 0 : $("#dirId").val();
  101. upload.render({ //允许上传的文件后缀
  102. elem: '#upload-img-btn'
  103. , url: 'UploadImage?dirId=' + dirId
  104. , accept: 'file' //普通文件
  105. , multiple: true
  106. , size: 1024 * 2 //限制文件大小,单位 KB
  107. , exts: 'jpg|jpeg|png|gif' //只允许上传压缩文件
  108. , done: function (res) {
  109. if (res.code == 0) {
  110. window.location.reload();
  111. }
  112. }
  113. });
  114.  
  115. //删除图片
  116. $("#delete-img-btn").click(function () {
  117. var checkeds = [];
  118. $("input[name='file-id']:checkbox").each(function () {
  119. if (true == $(this).is(':checked')) {
  120. checkeds.push({
  121. id: $(this).data('id'),
  122. type: $(this).data('type')
  123. });
  124. }
  125. });
  126. if (checkeds.length == 0) {
  127. layer.alert('请先选择需要删除的文件!');
  128. }
  129. else {
  130. layer.confirm('删除后将无法恢复,请确认是否要删除所选文件?', {
  131. btn: ['确定删除', '我在想想'] //按钮
  132. }, function () {
  133. $.ajax({
  134. type: 'post',
  135. url: 'CheckedFilesDelete',
  136. data: { checkeds : checkeds },
  137. success: function (result) {
  138. if (result.code == 0) {
  139. window.location.reload();
  140. }
  141. else {
  142. showMsg(result.msg);
  143. }
  144. }
  145. })
  146. }, function () {
  147. });
  148. }
  149. })
  150. })
  151.  
  152. //添加图片至编辑器
  153. $(".file-img").click(function () {
  154. var url = $(this).data("url"),
  155. title = $(this).data("title");
  156.  
  157. //添加确认
  158. layer.confirm('是否需要添加此图片?', {
  159. btn: ['确认添加', '我在想想'] //按钮
  160. }, function () {
  161. editor.execCommand('mceInsertContent', false, '<img alt="' + title + '" src="' + url + '"/>');
  162. editor.windowManager.close();
  163. }, function () {});
  164. })
  165. </script>
  166. <script>
  167. //layui基本代码
  168. $(function () {
  169. layui.use(['element', 'form', "layer"], function () {
  170. var element = layui.element;
  171.  
  172. //表单渲染
  173. var form = layui.form;
  174. form.on('submit(formDemo)', function (data) {
  175. layer.msg(JSON.stringify(data.field));
  176. return false;
  177. });
  178. form.render();
  179.  
  180. //异步加载modal
  181. $(document).on("click", '[data-toggle="modal"]', function (e) {
  182. var $this = $(this),
  183. url = $(this).data('url'),
  184. title = $(this).data("title")
  185. if (url) {
  186. $.ajax({
  187. url: url,
  188. data: { rnd: Math.random() },
  189. //dataType: 'html',
  190. success: function (data) {
  191. //示范一个公告层
  192. layer.open({
  193. type: 1
  194. , title: title //不显示标题栏
  195. , shade: 0.8
  196. , shadeClose: true
  197. , fixed: false
  198. , area: ["900px"]
  199. , offset: '40px'
  200. , id: 'ajax-modal-wapper' //设定一个id,防止重复弹出
  201. , move: false //禁止拖拽
  202. , content: data
  203. });
  204. },
  205. error: function (XMLHttpRequest, textStatus, errorThrown) {
  206. alert('加载出错。' + textStatus + '. ' + XMLHttpRequest.status);
  207. },
  208. complete: function () {
  209. }
  210. });
  211. }
  212. });
  213. });
  214. })
  215. </script>
  216. </body>
  217. </html>

  

新增文件夹页面 _AddDirectory.chtml

  1. @{
  2. Layout = null;
  3. }
  4.  
  5. <div class="modal-content" style="padding-top:20px;">
  6. <form class="layui-form" action="_AddDirectorySave" method="post" enctype="multipart/form-data">
  7. <input name="dirId" value="@Request["dirId"]" hidden>
  8. <div class="layui-form-item">
  9. <label class="layui-form-label" for="dirName">文件夹名称</label>
  10. <div class="layui-input-block">
  11. <input class="layui-input" id="dirName" lay-verify="required" name="dirName" placeholder="请输入文件夹名称" type="text" value="">
  12. </div>
  13. </div>
  14. <div class="layui-form-item">
  15. <div class="layui-input-block">
  16. <button class="layui-btn" lay-submit lay-filter="account-form" type="submit">保存信息</button>
  17. </div>
  18. </div>
  19. </form>
  20. </div>

  

 

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

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

  1. <script>
  2. //获取tinymce编辑器
  3. var editor = top.tinymce.activeEditor.windowManager.getParams().editor;
  4.  
  5. layui.use(['upload'], function () {
  6. var upload = layui.upload;
  7. var dirId = $("#dirId").val() == "" ? 0 : $("#dirId").val();
  8. upload.render({ //允许上传的文件后缀
  9. elem: '#upload-img-btn'
  10. , url: 'UploadImage?dirId=' + dirId
  11. , accept: 'file' //普通文件
  12. , multiple: true
  13. , size: 1024 * 2 //限制文件大小,单位 KB
  14. , exts: 'jpg|jpeg|png|gif' //只允许上传压缩文件
  15. , done: function (res) {
  16. if (res.code == 0) {
  17. window.location.reload();
  18. }
  19. }
  20. });
  21.  
  22. //删除图片
  23. $("#delete-img-btn").click(function () {
  24. var checkeds = [];
  25. $("input[name='file-id']:checkbox").each(function () {
  26. if (true == $(this).is(':checked')) {
  27. checkeds.push({
  28. id: $(this).data('id'),
  29. type: $(this).data('type')
  30. });
  31. }
  32. });
  33. if (checkeds.length == 0) {
  34. layer.alert('请先选择需要删除的文件!');
  35. }
  36. else {
  37. layer.confirm('删除后将无法恢复,请确认是否要删除所选文件?', {
  38. btn: ['确定删除', '我在想想'] //按钮
  39. }, function () {
  40. $.ajax({
  41. type: 'post',
  42. url: 'CheckedFilesDelete',
  43. data: { checkeds : checkeds },
  44. success: function (result) {
  45. if (result.code == 0) {
  46. window.location.reload();
  47. }
  48. else {
  49. showMsg(result.msg);
  50. }
  51. }
  52. })
  53. }, function () {
  54. });
  55. }
  56. })
  57. })
  58.  
  59. //添加图片至编辑器
  60. $(".file-img").click(function () {
  61. var url = $(this).data("url"),
  62. title = $(this).data("title");
  63.  
  64. //添加确认
  65. layer.confirm('是否需要添加此图片?', {
  66. btn: ['确认添加', '我在想想'] //按钮
  67. }, function () {
  68. editor.execCommand('mceInsertContent', false, '<img alt="' + title + '" src="' + url + '"/>');
  69. editor.windowManager.close();
  70. }, function () {});
  71. })
  72. </script>

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

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号