欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

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

程序员文章站 2022-05-28 14:04:02
功能实现:用户可以通过文件夹来管理自己的图片,以便在进行文章编辑的时候来快速找到图片将其插入编辑器中, 在使用Tinymce的过程中需要用到图片上传功能,而提供的上传插件在上传文件后是给了一个连接地址,就想用户需要什么图片,不能用最直观的方式表现出来么! 虽然官网上也有一个文件管理的插件moxiem... ......

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

虽然官网上也有一个文件管理的插件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: 还有很多的不足之处,希望能一起成长, 我的博客地址