95992828九五至尊2

上下端分离项目,前后端分离ueditor富文本编辑器的利用

四月 9th, 2019  |  882828九五至尊手机版

近年在写八个要好的后台管理连串(重假设写着玩的,用来熟谙后端java的文化,方今只是会不难的写点接口),想在类型中编辑一个宣布信息小说的意义,想到了使用百度的ueditor富文本编辑器,网上找了无数java版本的素材,可是超越百分之五十皆在此之前后端都在1个工程项目下,页面是jsp的。由于本人这么些连串是把前后端拆分开成前后端分离的。所以在根据看了网上的资料以及日益的摸索下,达成了在内外端分离的景况下把ueditor集成到系统中。项目页面如图:

先是,谈下那篇小说中的前后端所提到到的技术框架内容。

 

       
尽管是后端的田管项目,但全体项目,是行使前后端分离的方法成功,那样做的指标也是产品化的须求;

882828九五至尊手机版 1

        前者,vue+vuex+vue
router+webpack+elementUI的方案成功框架的搭建,当中使用了superUI来作为后端登六之后的主页面框架,中间集成vue的大型单页应用;

证实:由于ueditor的上传文件的意义私下认可是上传在项目工程目录下的,而本身这里是把文件上传播其它2个汤姆cat服务器下的,所以笔者自身独自写了2个上传接口,并且还要修改config.json文件。 

        后端,springboot+spring+springmvc+spring
serurity+mybatis+maven+redis+dubbo

 

+zookeeper的不二等秘书籍来营造项目框架和管理,提要求前端restful风格的接口。此处还提供app端、PC
WEB端的接口。

近来为了记录ueditor的施用,小编在那边把有关ueditor那1块独立拿出去,写了二个简练的小demo,上边记录进程,如有不足之处,敬请提出。

       
U艾德itor此前平素有在档次中接纳,作为国内开源的富文本编辑器,有百度的强大技术帮衬,全部来说是不错的精选,百度也提供了php、asp、.net、jsp的本子。原有的类型是采用全部式的开发格局,采取的是jsp的页面开发技术,所以集成起来相对来说越发便于,只必要依据文书档案的办法将前端集成进去,然后后端获得源码之后,针对文件上传的类修改最后存款和储蓄的主意即可将文件等上传到本人的服务器了。

1、下载ueditor

打开http://ueditor.baidu.com/website/download.html#ueditor

亟待下载三个压缩包

1、下载完整源码,并解压

2、下载jsp版本【UTF-8】,并解压

   源码版本是为了选用在那之中的java文件,而后来发现在源码版本中尚无ueditor.all.min.js文件,而在前者是索要引进这几个js文件的,所以须要再把jsp版本下载下来,该版本中有该js文件。

882828九五至尊手机版 2      
882828九五至尊手机版 3

 

     不过,由于决定了做上下端分离的秘籍,必然就会有新的坑,尤其是还挑选了新的技艺vue.js+elementUI的那种艺术。那么也不得不甩手一搏,不多啰嗦,介绍完,立刻起初正事。

二、java后台部分

     
  一、下载U艾德itor官网最新的jsp版本的包,下载完毕解压之后收获1个ueditor一_4_3_叁-utf八-jsp的文件夹,里面富含的内容如下:

 2.1、config.json文件

在java项目标 src/main/webapp
目录下新建1个conf目录,然后在解压后的源码版本中的 jsp
目录下找到config.json文件,把它复制到新建的conf目录下,并做修改。

该文件是用来配置ueditor编辑器的上传文件的成效的种种参数的。

 882828九五至尊手机版 4

882828九五至尊手机版 5

里头,imageActionName属性的取值“uploadimage”要铭记,后续上传接口中要用到

 

 882828九五至尊手机版 6

二.二、把源码版本中的 jsp/src/com 目录下的 baidu 那几个文件夹拷贝到项目com.lin包下

  拷贝后,里面java文件肯定会报错,只需修改各样java文件的package包路径和引用别的文件的路线即可。

882828九五至尊手机版 7

 

 其它是因为在上一步中,把config.json文件放置到了src/main/webapp/conf目录下,而在ConfigManager类中必要读取该json文件的内容,所以必要在ConfigManager.java文件中期维修改少量代码,大于在170多行,修改如下:

882828九五至尊手机版 8

 

除却jsp的文书夹之外,别的的文本和文书夹复制到前端项目中的static用于存放静态文件的目录下,结构如下:

二.三、项目常量配置-config.properties

#host地址
host=http://172.16.4.160:8081/ssm_project
#文件上传服务器地址(ip+端口)
uploadHost=http://172.16.4.160:8090/
#普通图片上传保存目录
imagePath = file/image/
#系统用户头像上传保存目录
headImgPath = file/image/headImg/
#系统用户默认头像
sysUserDefImg = sysUser-default.jpg
#文本文件上传保存目录
documentPath = file/document/
#音频文件上传保存目录
soundPath = file/sound/
#视频文件上传保存目录
videoPath = file/video/
#ueditor编辑器上传文件保存目录(包括图片、视频、音频、文本等文件)
ueditor = file/ueditor/

882828九五至尊手机版 9

二.四、新建上传工具类-Upload.java

882828九五至尊手机版,该文件其实在自家十二月二号的博客——前后端分离跨服务器文件上传-Java SpringMVC版
中已有,为了方便清楚,那里再度把代码贴出来。

package com.lin.utils;

import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.UUID;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.io.FilenameUtils;
import org.springframework.web.multipart.MultipartFile;

import com.sun.jersey.api.client.Client;
import com.sun.jersey.api.client.WebResource;


/**
 * 上传文件工具类
 * @author libo
 */
public class Upload {

    /**
     * 上传文件
     * @param request
     * @param response
     * @param serverPath    服务器地址:(http://172.16.5.102:8090/)
     * @param path             文件路径(不包含服务器地址:upload/)
     * @return
     */
    public static String upload(Client client, MultipartFile file, HttpServletRequest request,HttpServletResponse response, String serverPath, String path){
        // 文件名称生成策略(日期时间+uuid )
        UUID uuid = UUID.randomUUID();
        Date d = new Date();
        SimpleDateFormat format = new SimpleDateFormat("yyyyMMddHHmmss");
        String formatDate = format.format(d);
        // 获取文件的扩展名
        String extension = FilenameUtils.getExtension(file.getOriginalFilename());
        // 文件名
        String fileName = formatDate + "-" + uuid + "." + extension;
        //相对路径
        String relaPath = path + fileName;

        String a = serverPath + path.substring(0, path.lastIndexOf("/"));
        File file2 = new File(a);
        if(!file2.exists()){
            boolean mkdirs = file2.mkdirs();
            System.out.println(mkdirs);
        }

        // 另一台tomcat的URL(真实路径)
        String realPath = serverPath + relaPath;
        // 设置请求路径
        WebResource resource = client.resource(realPath);

        // 发送开始post get put(基于put提交)
        try {
            resource.put(String.class, file.getBytes());
            return fileName+";"+relaPath+";"+realPath;
        } catch (IOException e) {
            e.printStackTrace();
            return "";
        }
    }

}

 

 

二.5、新建U艾德itorController.java文件,编写上传接口

package com.lin.controller;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.io.FilenameUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import org.springframework.web.multipart.MultipartResolver;
import org.springframework.web.multipart.commons.CommonsMultipartResolver;

import com.lin.baidu.ueditor.ActionEnter;
import com.lin.utils.ResponseUtils;
import com.lin.utils.Upload;
import com.sun.jersey.api.client.Client;

import net.sf.json.JSONObject;
/**
 * baidu-ueditor
 * @author libo
 */
@Controller
@RequestMapping("/ueditor")
public class UEditorController {
    @Value(value="${ueditor}")    //后台图片保存地址
    private String ueditor;

    @Value(value="${uploadHost}")
    private String uploadHost;    //项目host路径    

    /**
     * ueditor文件上传(上传到外部服务器)
     * @param request
     * @param response
     * @param action
     */
    @ResponseBody
    @RequestMapping(value="/ueditorUpload.do", method={RequestMethod.GET, RequestMethod.POST})
    public void editorUpload(HttpServletRequest request, HttpServletResponse response, String action) {
        response.setContentType("application/json");
        String rootPath = request.getSession().getServletContext().getRealPath("/");

        try {
            if("config".equals(action)){    //如果是初始化
                String exec = new ActionEnter(request, rootPath).exec();
                PrintWriter writer = response.getWriter();
                writer.write(exec);
                writer.flush();
                writer.close();
            }else if("uploadimage".equals(action) || "uploadvideo".equals(action) || "uploadfile".equals(action)){    //如果是上传图片、视频、和其他文件
                try {
                    MultipartResolver resolver = new CommonsMultipartResolver(request.getSession().getServletContext());
                    MultipartHttpServletRequest Murequest = resolver.resolveMultipart(request);       
                    Map<String, MultipartFile> files = Murequest.getFileMap();//得到文件map对象
                    // 实例化一个jersey
                    Client client = new Client();

                    for(MultipartFile pic: files.values()){
                        JSONObject jo = new JSONObject();
                        long size = pic.getSize();    //文件大小
                        String originalFilename = pic.getOriginalFilename();  //原来的文件名
                        String uploadInfo = Upload.upload(client, pic, request, response, uploadHost, ueditor);
                        if(!"".equals(uploadInfo)){    //如果上传成功
                            String[] infoList = uploadInfo.split(";");
                            jo.put("state", "SUCCESS");
                            jo.put("original", originalFilename);
                            jo.put("size", size);
                            jo.put("title", infoList[1]);
                            jo.put("type", FilenameUtils.getExtension(pic.getOriginalFilename()));
                            jo.put("url", infoList[2]);
                        }else{    //如果上传失败
                        }
                        ResponseUtils.renderJson(response, jo.toString());
                    }
                }catch (Exception e) {
                    e.printStackTrace();
                }
            }
        } catch (Exception e) {
        }
    }
}

其中:

if("config".equals(action)){ 
这段代码是用来判断是否是初始化上传的,因为在点击多图上传弹出上传窗口的时候,是会请求这个接口,经测试,如果没有该段判断,前端的上传是无法使用的。

   else if(“uploadimage”.equals(action)
|| “uploadvideo”.equals(action) || “uploadfile”.equals(action)){ 

   这一有的代码判断中,
uploadimage,uploadvideo,uploadfile
那多个值,都以缘于于conf.json文件中的配置,由此那叁个接口既能够上传图片,也足以上传其余品种文件。

  
此外接口再次来到的json字段,也是固定的。

 

那Ritter别表明jsp目录下的财富为何不放进来,因为大家是vue搭建的档次,jsp页面肯定是不会放在前端的种类中的,包蕴config.json也坐落后端用于解析,那里前面会解释那样做的缘故。

3、前端部分

       
②、前端将文件放进来之后,暂且先那样,我们来整治后端的东西。那里将jsp目录下的lib目中的ueditor.jar文件中的全部类全部拿出来(具体方式本身说了算,反编写翻译工具可能获得源码都得以),放到后端项目中,然后在control层新建2个UeditorController.java的类,如下:

三.壹、demo目录结构

 882828九五至尊手机版 10

在ueditor-demo目录下新建lib目录,然后从前边解压的jsp版本中,把dialogs、lang、themes、third-party多少个公文夹和ueditor.all.min.js、ueditor.config.js、ueditor.parse.js、ueditor.parse.min.js八个js文件复制到lib目录下,并添加jQuery(用来进行ajax提交数据)

 1 /**
 2  * 用于处理关于ueditor插件相关的请求
 3  * @author Guoqing
 4  *
 5  */
 6 @RestController
 7 @CrossOrigin
 8 @RequestMapping("/sys/ueditor")
 9 public class UeditorController extends BaseController {
10 
11     @RequestMapping(value = "/exec")
12     @ResponseBody
13     public String exec(HttpServletRequest request) throws UnsupportedEncodingException{ 
14         request.setCharacterEncoding("utf-8");
15         String rootPath = request.getRealPath("/");
16         return new ActionEnter( request, rootPath).exec();
17     }
18 }

叁.贰、文件修改

 该类首要处理,ueditor与后端服务器的相互,通过action=”区别的项目来处理,在这之中action=config为加载配置项,action=uploadImg
图片上传,在ActionEntor类中,你能够依据分化的呼吁类型来处理;

1、修改ueditor.config.js

修改服务器统一请求接口路径 –
serverUrl属性的值修改为后台上传文件的接口地址

882828九五至尊手机版 11

拍卖当action=config时的动静,有限补助前端的编辑器各项文件上传作用,能够寻常使用。

 

然后jsp目录下的config.json文件放到java/main/resources目录下,修改ConfigManager.java类,如下:

二、修改dialogs/image/image.js、dialogs/video/video.js、dialogs/attachment/attachment.js多个文本

 这四个文件分别对应图片上传、摄像上传、附属类小部件上传,主假若要去掉暗中认可设置的请求头(能够一向在那八个js文件中删掉该段代码),不然无法上传文件

   2.1、dialogs/image/image.js大概在706行

        882828九五至尊手机版 12

   2.2、dialogs/video/video.js大概在719行

        882828九五至尊手机版 13

   2.3、dialogs/attachment/attachment.js大概在488行

        882828九五至尊手机版 14

 

882828九五至尊手机版 15

3.3、index.html

在页面中需求引进ueditor.config.js、ueditor.all.min.js和zh-cn.js

在body元素中写二个script元素,给2个id,这里为editor,并设置type=”text/plain”,那么些id主假诺透过它来初叶化ueditor实例的。

开端化的不二等秘书诀是在通过 UE.get艾德itor(‘script标签id’,
{})。

那里有三个参数,第3个参数是script标签的id值,第叁个参数是三个目的,能够用来设置ueditor编辑框的宽高等属性,那里只设置了宽高。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>ueditor-demo</title>
    <script src="/lib/jquery.min.js"></script>
    <script src="/lib/ueditor/ueditor.config.js"></script>
    <script src="/lib/ueditor/ueditor.all.min.js"></script>
    <script src="/lib/ueditor/lang/zh-cn/zh-cn.js"></script>
    <style>
        #submit {
            width: 100px;
            height: 30px;
            line-height: 30px;
            font-size: 16px;
        }
    </style>
</head>
<body>
<h2>ueditor测试使用</h2>
<script id="editor" type="text/plain"></script>
<div style="margin-top: 20px; text-align: center;">
    <input type="button" class="btn btn-blue w-100" value="提 交" id="submit">
</div>

<script>

    $(function () {
        //实例化编辑器
        var ue = UE.getEditor('editor',{
            initialFrameWidth:"100%",   //初始化宽度
            initialFrameHeight:400,     //初始化高度
        });

        $('#submit').click(function () {
            //获取ueditor编辑框中的html文本内容
            var content = UE.getEditor('editor').getContent();
            $.ajax({
                url: 'http://172.16.4.160:8081/ssm_project/news/addNews.do',
                type: 'POST',
                data: {
                    content: content,
                },
                dataType: 'json',
                success: function (res) {
                    console.log(res);
                },
                error: function () {
                    console.log(res);
                }
            })
        })
    })

</script>
</body>

</html>

UE.get艾德itor(‘editor’).getContent()方法就足以获取到编辑框中的html文本,然后调用添加接口,就足以把html格式的文件保存到数据库中了。

那会儿就足以在劳动环境下访问该index.html页面,即可看出ueditor富文本编辑框,并展开上传文件并保留到数据库中。

诠释掉原有的读取配置文件的格局,添加新的读取路径,那样保障ueditor在开端化能够正确的加载配置文件。此时,修改前端项目中ueditor.config.js中的serverUrl的值为:

 

// 服务器统一请求接口路径
, serverUrl:  "http://localhost:8080/sys/ueditor/exec"

4、效果

882828九五至尊手机版 16

 

882828九五至尊手机版 17

 

 882828九五至尊手机版 18

注意:在测试在此之前,需求先运转文件服务器——其它三个汤姆cat服务器
,至于有关那壹块的牵线,请参考10月二号的1篇博客:前后端分离跨服务器文件上传-Java
SpringMVC版

 

备注:由于这里是内外端分离的,涉及到跨域的标题,所以也在网上也查了无独有偶素材,自个儿也尝试了很数次,都无法完成单图上传,由此那里就在ueditor.config.js中,把单图上传给去掉了。

由于本人是做web前端开发的,只是目前在学学java,因而项目或许demo中都有无数不足之处。要是大家有建议,欢迎在评论区提议。

 

而,针对ActionEnter.java类中,如下代码后的文件上传的拍卖,请我们针对作者的上传格局和文书服务器采取符合本身的法子:

switch ( actionCode ) {
            //读取配置文件时的请求处理
            case ActionMap.CONFIG:
                return this.configManager.getAllConfig().toString();
            //上传图片、视频、文件时的处理
            case ActionMap.UPLOAD_IMAGE:
            case ActionMap.UPLOAD_SCRAWL:
            case ActionMap.UPLOAD_VIDEO:
            case ActionMap.UPLOAD_FILE:
                conf = this.configManager.getConfig( actionCode );
                state = new Uploader( request, conf, baseFileService ).doExec();
                break;
              //抓取远程图片时的处理方式,此处也可以关闭

               //当从网页上复制内容到编辑器中,如果图片与该域名不同源,则会自动抓到本地的服务器保存 
            case ActionMap.CATCH_IMAGE:
                conf = configManager.getConfig( actionCode );
                String[] list = this.request.getParameterValues( (String)conf.get( "fieldName" ) );
                state = new ImageHunter( conf ).capture( list );
                break;
             //上传多文件时的文件在线管理
            case ActionMap.LIST_IMAGE:
            case ActionMap.LIST_FILE:
                conf = configManager.getConfig( actionCode );
                int start = this.getStartIndex();
                state = new FileManager( conf ).listFile( start );
                break;

        }
        return state.toJSONString();

 

接下去是前者的处理,介于大家的渴求。我将本来的demo进行了优化,将编辑器封装成组件的艺术,方便调用,代码如下:

<template>
  <div>
    <script id="editor" type="text/plain" ></script>
  </div>
</template>

<script>
  import AppConfig from '@/config'
  import '../../../../../../static/ueditor/ueditor.config.js'
  import '../../../../../../static/ueditor/ueditor.all.js'
  import '../../../../../../static/ueditor/lang/zh-cn/zh-cn.js'

  export default {
    name: "UEditor",
    props: {
      id: {
          type: String
      },
      config: {
          type: Object
      }
    },
    data() {
      return {
        editor: null
      }
    },
    mounted() {
      //初始化UE
      const _this = this;
      this.editor = UE.getEditor('editor',this.config);
    },
    destoryed() {
      this.editor.destory();
    },
    methods:{
      getUEContent: function(){
       return this.editor.getContent();
      }
    }
  }
</script>

 导出组件:

var UEditor =  require('./src/ueditor.vue');


module.exports = {
  UEditor
}

那里之所以是用1个模态框的主意来加载编辑器,是因为会设有编辑器工具栏浮动的题目,假如不经常,请依照如下的布署来处理即可;

页面调用:

<template>
  <div id="app" class="hello">
    <el-button size="primary" type="info" icon="plus" @click="openWindow">打开窗口</el-button>
    <el-dialog title="新增菜单" size="small" v-model="addFormVisible" :close-on-click-modal="false">
      <div>
        <el-button size="primary" type="info" icon="plus" @click="getContent">获取内容</el-button>
        <UEditor :config=config ref="ueditor"></UEditor>
      </div>
    </el-dialog>

  </div>
</template>

<script>
  import {UEditor} from './ueditor/index.js'

  export default{
      name: 'hello',
      components: {UEditor},
      data(){
        return {
          config: {
            /*//可以在此处定义工具栏的内容
            toolbars: [
              ['fullscreen', 'source','|', 'undo', 'redo','|','bold', 'italic', 'underline', 'fontborder', 'strikethrough',
                '|','superscript','subscript','|', 'forecolor', 'backcolor','|', 'removeformat','|', 'insertorderedlist', 'insertunorderedlist',
                '|','selectall', 'cleardoc','fontfamily','fontsize','justifyleft','justifyright','justifycenter','justifyjustify','|',
                'link','unlink']
            ],*/
            autoHeightEnabled: false,
            autoFloatEnabled: true,  //是否工具栏可浮动
            initialContent:'请输入内容',   //初始化编辑器的内容,也可以通过textarea/script给值,看官网例子
            autoClearinitialContent:true, //是否自动清除编辑器初始内容,注意:如果focus属性设置为true,这个也为真,那么编辑器一上来就会触发导致初始化的内容看不到了
            initialFrameWidth: null,
            initialFrameHeight: 450,
            BaseUrl: '',
            UEDITOR_HOME_URL: 'static/ueditor/'
          },
          addFormVisible: false
        }
      },
      methods: {
        openWindow: function(){
            this.addFormVisible = true;
        },
        //获取文档内容
        getContent: function(){
          let content = this.$refs.ueditor.getUEContent();
          console.log(content);
          alert(content);
        }
      }
  }

</script>

 

由来,旗开得胜,包蕴文件上传下载等片段全体化解,然则要声美素佳儿(Friso)点的是,当现身接口与页面计划域名不相同时,点击选用图片上传会出现iframe跨域的难点。

2017-0玖-0捌的换代,作者曾经由此改变源码的办法,处理了单图选取文件上传存在跨域的题材,处理格局当然正是将原有的form.submit的表单上传格局,更改为ajax的上传格局;

ueditor.all.js 2450三行的艺术替换,源码如下:

      /**
           * 2017-09-07 改掉了ueditor源码,将本身的单文件上传的方法改为ajax上传,主要目的是为了解决跨域的问题
           * @author Guoqing
           */
          domUtils.on(input, 'change', function() {
              if(!input.value) return;
              var loadingId = 'loading_' + (+new Date()).toString(36);
              var imageActionUrl = me.getActionUrl(me.getOpt('imageActionName'));
              var allowFiles = me.getOpt('imageAllowFiles');

              me.focus();
              me.execCommand('inserthtml', '<img class="loadingclass" id="' + loadingId + '" src="' + me.options.themePath + me.options.theme +'spacer.gif" title="' + (me.getLang('simpleupload.loading') || '') + '" >');

              /!* 判断后端配置是否没有加载成功 *!/
              if (!me.getOpt('imageActionName')) {
                errorHandler(me.getLang('autoupload.errorLoadConfig'));
                return;
              }
              // 判断文件格式是否错误
              var filename = input.value,
                fileext = filename ? filename.substr(filename.lastIndexOf('.')):'';
              if (!fileext || (allowFiles && (allowFiles.join('') + '.').indexOf(fileext.toLowerCase() + '.') == -1)) {
                showErrorLoader(me.getLang('simpleupload.exceedTypeError'));
                return;
              }

              var params = utils.serializeParam(me.queryCommandValue('serverparam')) || '';
              var action = utils.formatUrl(imageActionUrl + (imageActionUrl.indexOf('?') == -1 ? '?' : '&') + params);
              var formData = new FormData();
              formData.append("upfile", form[0].files[0] );
              $.ajax({
                url: action,
                type: 'POST',
                cache: false,
                data: formData,
                processData: false,
                contentType: false,
                success: function (data) {
                  data = JSON.parse(data);
                  var link, loader,
                    body = (iframe.contentDocument || iframe.contentWindow.document).body,
                    result = body.innerText || body.textContent || '';
                  link = me.options.imageUrlPrefix + data.url;

                  if(data.state == 'SUCCESS' && data.url) {
                    loader = me.document.getElementById(loadingId);
                    loader.setAttribute('src', link);
                    loader.setAttribute('_src', link);
                    loader.setAttribute('title', data.title || '');
                    loader.setAttribute('alt', data.original || '');
                    loader.removeAttribute('id');
                    domUtils.removeClasses(loader, 'loadingclass');
                  } else {
                    showErrorLoader && showErrorLoader(data.state);
                  }
                  form.reset();
                }
              });
              function showErrorLoader(title){
                if(loadingId) {
                  var loader = me.document.getElementById(loadingId);
                  loader && domUtils.remove(loader);
                  me.fireEvent('showmessage', {
                    'id': loadingId,
                    'content': title,
                    'type': 'error',
                    'timeout': 4000
                  });
                }
              }
            });

 

好了,假诺上述对您有帮衬的话,请顺手点个赞,感谢各位大虾们啦!

 

意义图如下:

882828九五至尊手机版 19

882828九五至尊手机版 20

 

/************************华丽丽的分割线*************************/

2017-11-2九 响应我们的供给,前后端项目都提供了源码的demo 
请上github上查看,如还有标题,请多多沟通

https://github.com/coderliguoqing

882828九五至尊手机版 21

迎接围观、点赞!

 

自己只是一个不想做程序员的好程序员。

 

Your Comments

近期评论

    功能


    网站地图xml地图