使用 UEditor富文本编辑器 实现仿CSDN的发布博客的功能

写在开头
最近在做一个美食博客的网站系统,需要实现发布文章页面的效果(类似CSDN的Markdown写文章的功能),所以使用了UEditor编辑器代替了Markdown的编辑器,发布文章的时候可以将文章的html生成出来并直接插入到数据库数据中。

先看一下效果
在这里插入图片描述
在这里插入图片描述
下面详细介绍一步一步实现改功能

下载UEditor文件

gitee下载地址:https://gitee.com/chef_git/ueditor
在这里插入图片描述
下载ZIP解压后将UEditor文件夹放在web目录下
在这里插入图片描述

UEditor的使用

<!DOCTYPE HTML>
<html lang="en-US">
<head>
    <meta charset="UTF-8">
    <title>ueditor demo</title>
</head>
<body>
<!-- 加载编辑器的容器 -->
<script id="container" name="content" type="text/plain">这里写你的初始化内容</script>
<!-- 配置文件 -->
<script type="text/javascript" src="ueditor/ueditor.config.js"></script>
<!-- 编辑器源码文件 -->
<script type="text/javascript" src="ueditor/ueditor.all.js"></script>
<!-- 实例化编辑器 -->
<script type="text/javascript">
    var ue = UE.getEditor('container',{
        initialFrameHeight :600,

    });

    var ready=function () {

        var html = ue.getContent();//获取html内容,返回: <p>hello</p>

        var text=ue.getContentTxt();//获取纯文本内容

        alert(html);
    };

</script>

<button type="button" onclick="ready()">发布文章</button>
</body>
</html>

进入正题:发布文章页面

实现异步上传图片的功能

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <!-- 上述3个meta标签*必须*放在最前面,任何其他内容都*必须*跟随其后! -->
    <title>写文章</title>

    <!-- Bootstrap -->
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/css/bootstrap.min.css" rel="stylesheet">

    <!-- HTML5 shim 和 Respond.js 是为了让 IE8 支持 HTML5 元素和媒体查询(media queries)功能 -->
    <!-- 警告:通过 file:// 协议(就是直接将 html 页面拖拽到浏览器中)访问页面时 Respond.js 不起作用 -->
    <!--[if lt IE 9]>
    <script src="https://cdn.jsdelivr.net/npm/html5shiv@3.7.3/dist/html5shiv.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/respond.js@1.4.2/dest/respond.min.js"></script>
    <![endif]-->
    <!-- jQuery (Bootstrap 的所有 JavaScript 插件都依赖 jQuery,所以必须放在前边) -->
    <script src="https://cdn.jsdelivr.net/npm/jquery@1.12.4/dist/jquery.min.js"></script>
    <!-- 加载 Bootstrap 的所有 JavaScript 插件。你也可以根据需要只加载单个插件。 -->
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/js/bootstrap.min.js"></script>
</head>
<body>

<!--1.顶部导航条-->
<nav class="navbar navbar-default" style="margin-bottom: 0px">
    <div class="container-fluid">
        <!-- Brand and toggle get grouped for better mobile display -->
        <div class="navbar-header">
            <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1" aria-expanded="false">
                <span class="sr-only">Toggle navigation</span>
                <span class="icon-bar"></span>
                <span class="icon-bar"></span>
                <span class="icon-bar"></span>
            </button>
            <a class="navbar-brand" href="#">&#9668 文章管理</a>
        </div>

        <!-- Collect the nav links, forms, and other content for toggling -->
        <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
            <!--搜索框-->
            <form class="navbar-form navbar-left">
                <div class="form-group">
                    <input type="text" class="form-control" placeholder="请输入文章标题" style="width: 1050px;" id="search_input">&nbsp;&nbsp;<span id="tishi" style="font-weight: bold;">0</span>/200
                </div>
                <script>
                    $('#search_input').on('input focus keyup',
                        function(){
                            var strs   = $(this).val();
                            remain = strs.length;
                            var content_msg = remain;
                            $(this).next().html(content_msg);
                            //.next() 方法返回被选元素的后一个同级元素。
                        }
                    );
                </script>

                &nbsp;
                <button type="submit" class="btn btn-default">保存草稿</button>
                &nbsp;
                <button type="button" class="btn btn-default btn-danger"  id="btn_put">发布文章</button>
            </form>
            <ul class="nav navbar-nav navbar-right">
 <!--               <li><a href="#">Link</a></li>
                <li class="dropdown">
                    <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">Dropdown <span class="caret"></span></a>
                    <ul class="dropdown-menu">
                        <li><a href="#">Action</a></li>
                        <li><a href="#">Another action</a></li>
                        <li><a href="#">Something else here</a></li>
                        <li role="separator" class="divider"></li>
                        <li><a href="#">Separated link</a></li>
                    </ul>
                </li>-->
                <li class="dropdown">
                    <a href="#" class="" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false" style="padding: 0px;margin-top: 5px;margin-right: 10px;"><img src="img/about-img/1.jpg" class="img-responsive img-circle" style="width: 40px;height: 40px;"/></a>
                    <ul class="dropdown-menu" style="width: 40px;">
                        <li><a href="#">博文管理</a></li>
                        <li><a href="#">我的博客</a></li>
                        <li role="separator" class="divider"></li>
                        <li><a href="#">退出</a></li>
                    </ul>
                </li>
            </ul>
        </div><!-- /.navbar-collapse -->
    </div><!-- /.container-fluid -->
</nav>

<!--2.UEditor编辑器-->
<div class="container-fluid" style="padding: 0px;">
    <!-- 加载编辑器的容器 -->
    <script id="container" name="content" type="text/plain">这里写你的文章内容</script>
    <!-- 配置文件 -->
    <script type="text/javascript" src="ueditor/ueditor.config.js"></script>
    <!-- 编辑器源码文件 -->
    <script type="text/javascript" src="ueditor/ueditor.all.js"></script>

    <!-- 实例化编辑器 -->
    <script type="text/javascript">
        var ue = UE.getEditor('container',{
            initialFrameHeight :590,
            initialFrameWidth :1534,
        });
        /*
        UEditor的后台配置失败!!!!
        ue.loadServerConfig();
        alert(ue.isServerConfigLoaded());*/
        var ready=function () {//点击发布文章按钮



            var html = ue.getContent();//获取html内容,返回: <p>hello</p>

            var text=ue.getContentTxt();//获取纯文本内容

            alert(html);
        };

    </script>


    <!--点击按钮,跳出面板-->
    <script>
        $("#btn_put").click(function () {
            $("#myModalLabel").text("发布文章");
            var summary=ue.getContentTxt().substring(0,200);
            $("#txt_statu").val(summary);
            $('#myModal').modal();
        });
    </script>
    <div class="modal fade" id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel">
        <div class="modal-dialog" role="document">
            <div class="modal-content">
                <div class="modal-header">
                    <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
                    <h4 class="modal-title" id="myModalLabel">发布文章</h4>
                </div>
                <div class="modal-body">

                    <div class="form-group">
                        <label for="txt_departmentname">文章标签</label>
                        <input type="text" name="txt_departmentname" class="form-control" id="txt_departmentname" placeholder="自定义文章标签 ( 多个使用“、”分开!)">
                    </div>
                    <div class="form-group">
                        <label>分类专栏</label>
                        <select class="form-control" id="type_select">
                            <option>请选择</option>
                            <option>美食人生</option>
                            <option>美食评论</option>
                            <option>大厨授课</option>
                            <option>达人推荐</option>
                            <option>旅途美食</option>
                            <option>回家吃饭</option>
                            <option>饭后甜点</option>
                        </select>
                    </div>
                    <div class="form-group">
                        <label>文章类型</label>
                        <select class="form-control">
                            <option>请选择</option>
                            <option>原创</option>
                            <option>转载</option>
                            <option>翻译</option>
                        </select>
                    </div>
                    <div class="form-group">
                        <label for="txt_statu">摘要</label>
                        <input type="text" name="txt_statu" class="form-control" id="txt_statu" placeholder="摘要">
                    </div>
                    <div class="form-group">
                        <label>文章图片</label>
                        <!--实现上传图片-->
                        <form action="/upload" enctype="multipart/form-data" method="post" id="upload_img">
                            <div class="row" style="height: auto;width: 94%;margin-left: 10px;cursor: pointer;border:1px gainsboro solid;border-radius: 10px 10px;" id="upload_div">
                                <img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAAEbUlEQVR4Xu2aTWgdVRTHz5l8LfyiipKlLnSnC9G4MQYrCIIUdSGVWjCmyTkTMbS6EJFCFqULwQ/CwzcnL1aN1UUofi3cqKWmIFJEEDeCIt1WF2mpEIKZd+TKPHkZ33tzZ+7MvD7e3E3g3Tvnnv/vnnPmzr1BGPKGQ64fKgBVBAw5gSoFhjwAqiLYtxQQkUcB4AgAhKp6ipm/6kc09gWAiBwFgLdigo8R0dtlQygdQBfxLd2lQygVQIL4vkAoDYCl+BaERSKql5EOpQAQER8A3kkpqBQIhQPIKL60SCgUgKP4UiAUBiAn8f9CQMS5hYWFUylTyGp4IQB6iVfVLUT8DQDub/dQVS8AwJ2IuK+D54qIR4qAkDuA1dXV51X13U74I/EzqvoKIh6KjTkNAK+r6rdlQsgVQCR+zURtHEBLPBH9HATB6U4AiOiwiNxdJoTcANiKN2B6ATD9BgIAnAeAmzqlQ7PZPOz7/kdWSZ4wKBcAvcQDwBUAmDYr3/IlCUAE4V4AOFs0BGcA9Xr9kOd5H3YK+0j8fiL6sX0hbACUBcEJQBbxNinQDktECo2EzACyik8LwCYSVPVpZj6TpSZkAuAiPgsACwjmUOVgFgipAbiKzwqgKAipAIjIEwDwSZqC1yksbYtgp2cTaoKJhAPM/KVtOlgDWF5e9iYnJ8029sYOxs2r7n/VvpsTLgCSIkFVLzLzHbkDWF9fv257e/svV/EuKRB/O0Q7xuvjPo2Pj++bnZ29bAPBOgIixzcRcbrNcKqVT7MRsnFeRB5Q1a8R8T8IqvorM99l87wZkwpAvV6/3fO8GgA8pKrfI+LL7Ts820ldU6B9nkajcU8Yhm8i4hQAbIZhuLS4uPi7rS+pANgaTRqXJ4CkuZL6KwBJhIroryKgx3lAEcB72axSoGziee0D8vK7ioC8SKaxUxXBqgh2PxVOE0l5jLWqAWtrazfv7u4eRMQ/d3Z2vlhaWtpxmVxEzC3PbLsNc5fAzOY/RjK3jY2Nka2tradU9VZVPeP7/h9JxhIB1Gq1W8bGxr4DgNYHxi+jo6NTc3NzV5OMd+sPguAlRHyjvb/ZbD7rctQdfa5/joiPR3avqOoMM//ktA8QEfPx80LMyDwRmQuQTG1lZWViYmLiUwB4LDJQI6IXMxmLHgqC4BlE/Dhm4wMies4VwDkAmImF6wlmPu7isHnWfF2av77vX3S1JSInAOC1mJ/nmPlhJwBBEMTPAIy9k0S0ZzJXAa7PB0FwEhFfjQHYZOY9ixefJ7EGVACqCBjyFBARc0G5p5Co6nlENL9fS+0RAHgwVgPOMrP5vWuzqQHvIWLPV8m1RCEG4H1m3rPhSl0Eo8sQ884exPYkEX3mFAGqiiJyARHvGyQCqvoDEU0hojoBiDYst3me1wCAA4MAwdwNjIyMTM/Pz19K8jexBrQbaDQa+8MwPIaINyQZ7lO/2f/XEfEbIvrbxodUAGwMDtqYCsCgrVje/lYRkDfRQbNXRcCgrVje/g59BPwDxZ9wX+EKb6cAAAAASUVORK5CYII=" alt="" class="col-md-offset-4">
                                <span class="vicp-hint">点击上传图片至此处</span>
                            </div>
                            <input type="file" name="file" id="upload_file" style="display: none;"/>
                            <!--<input type="submit" value="upload">-->
                        </form>
                    </div>
                </div>
                <div class="modal-footer">
                    <button type="button" class="btn btn-default" data-dismiss="modal"><span class="glyphicon glyphicon-remove" aria-hidden="true"></span>取消</button>
                    <button type="button" id="btn_submit" class="btn btn-primary" data-dismiss="modal"><span class="glyphicon glyphicon-floppy-disk" aria-hidden="true"></span>发布文章</button>
                </div>

                <script>
                    var imgUrl;
                    $("#upload_div").click(function () {//div点击触发inputfile按钮上传文件的功能
                        $("#upload_file").click();
                    });

                    $("#upload_file").change(function () {//选中文件后,异步上传文件并获取上传文件的地址
                        var fromData = new FormData($("#upload_img")[0]);
                        /*$("#upload_img").submit();//非异步提交上传文件的表单*/
                        $.ajax( {/*异步提交上传文件的表单*/
                            url:'/upload',
                            data:fromData,
                            type:'post',
                            //ajax2.0可以不用设置请求头,但是jq帮我们自动设置了,这样的话需要我们自己取消掉
                            contentType:false,
                            //取消帮我们格式化数据,是什么就是什么
                            processData:false,
                            success:function(data){
                                console.log(data);
                                //异步刷新图片
                                var imgPath=$("#upload_file").val().split("\\");
                                var imgName=imgPath[2];
                                imgUrl='/img/blog-img/'+imgName;
                                $("#upload_div").html('<img src="'+imgUrl+'" alt="" class="img-responsive img-rounded">\n');
                            }
                    });

                        /*alert(imgUrl);*/
                    });

                    $("#btn_submit").click(function () {//点击发布文章按钮,异步提交文章数据,跳转页面
                        //title,
                        var title=$("#search_input").val();
                        if (title){
                            console.log("title"+title);
                        } else {
                            alert("标题不能为空!");
                            return;
                        }
                        // summary,
                        var summary=ue.getContentTxt().substring(0,200);
                        if (summary=="这里写你的文章内容" || summary==""){
                            alert("文章内容什么也没写哦!");
                            return;
                        }
                        console.log("summary"+summary);
                        // releaseDate,
                        var date=new Date();
                        console.log("date"+date);
                        // content,
                        var content=ue.getContentTxt();
                        console.log("content"+content);
                        // typeid,
                        var typeName=$("#type_select").val();
                        if (typeName=="请选择"){
                            alert("请选择文章类型!");
                            return;
                        } else {
                            var typeid;
                            switch (typeName) {
                                case "美食人生":typeid=1;break;
                                case "美食评论":typeid=2;break;
                                case "大厨授课":typeid=3;break;
                                case "达人推荐":typeid=4;break;
                                case "旅途美食":typeid=5;break;
                                case "回家吃饭":typeid=6;break;
                                case "饭后甜点":typeid=7;break;
                            }
                            /*alert(typeid);*/
                        }
                        // keyWord,
                        var keyWord=$("#txt_departmentname").val();
                        /*alert(keyWord);*/
                        // imgUrl,
                        imgUrl=imgUrl.substr(1);//去掉第一个 "/"
                        // author
                        var author="chif";
                        blog={title:title,summary:summary,releaseDate:date,likes:0,replyHit:0,content:content,typeid:typeid,keyWord:keyWord,imgUrl:imgUrl,author:author};
                        //ajax 发布博客
                        $.post("/addBlog",blog,function (data) {
                            /*var result=$.parseJSON(data);*/
                            alert(data);
                        })

                    });
                </script>
            </div>
        </div>
    </div>
</div>

</body>
</html>

页面中ajax请求的后台接口

/upload

package com.chif.controller;
 
import com.alibaba.druid.support.json.JSONUtils;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.commons.CommonsMultipartFile;
 
import javax.servlet.http.HttpServletRequest;
import java.io.*;
 
@Controller
public class FileController {
    //@RequestParam("file") 将name=file控件得到的文件封装成CommonsMultipartFile 对象
    //批量上传CommonsMultipartFile则为数组即可
    @RequestMapping("/upload")
    @ResponseBody
    public String fileUpload(@RequestParam("file") CommonsMultipartFile file , HttpServletRequest request) throws IOException {
 
        //获取文件名 : file.getOriginalFilename();
        String uploadFileName = file.getOriginalFilename();
 
        //如果文件名为空,直接回到首页!
        if ("".equals(uploadFileName)){
            return "redirect:/index.jsp";
        }
        System.out.println("上传文件名 : "+uploadFileName);
 
        //上传路径保存设置
        String path = request.getServletContext().getRealPath("/img/blog-img");
        //如果路径不存在,创建一个
        File realPath = new File(path);
        if (!realPath.exists()){
            realPath.mkdir();
        }
        System.out.println("上传文件保存地址:"+realPath);
 
        InputStream is = file.getInputStream(); //文件输入流
        OutputStream os = new FileOutputStream(new File(realPath,uploadFileName)); //文件输出流
 
        //读取写出
        int len=0;
        byte[] buffer = new byte[1024];
        while ((len=is.read(buffer))!=-1){
            os.write(buffer,0,len);
            os.flush();
        }
        os.close();
        is.close();
        return JSONUtils.toJSONString("上传文件成功!");
    }
}

/addBlog

/**
     * 增加一篇博客
     * @param blog
     * @return
     */
    @RequestMapping("/addBlog")
    public String addBook(Blog blog){
        blogService.addBlog(blog);
        return "发布成功";
    }
  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
为了禁止vue-ueditor-wrap富文本编辑器的编辑功能,你可以在使用组件的地方加上一个属性来禁用编辑。根据引用和引用中的代码,你可以在main.js和App.vue中添加以下代码: 在main.js中: ``` import VueUeditorWrap from 'vue-ueditor-wrap' Vue.component('vue-ueditor-wrap', { ...VueUeditorWrap, props: { disabled: { type: Boolean, default: false } }, mounted: function() { if (this.disabled) { this.$refs.ueditor.setDisabled() } } }) new Vue({ render: h => h(App), }).$mount('#app') ``` 在App.vue中: ``` <template> <div id="app"> <VueUeditorWrap :disabled="true"></VueUeditorWrap> </div> </template> <script> import VueUeditorWrap from 'vue-ueditor-wrap' export default { components: { VueUeditorWrap } } </script> ``` 这样设置之后,vue-ueditor-wrap富文本编辑器就会被禁用,用户将无法编辑其中的内容。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [vue-ueditor-wrap百度富文本的使用](https://blog.csdn.net/qq_52883064/article/details/129875979)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 50%"] - *2* *3* [vue项目引入vue-ueditor-wrap富文本编辑器](https://blog.csdn.net/weixin_45966674/article/details/123498254)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值