zhangrui.i
zhangrui.i
发布于 2024-03-01 / 4 阅读
0
0

记VUE整合百度富文本(ueditor)

参考文档: https://hc199421.gitee.io/vue-ueditor-wrap/#/home

1. 下载发布版本

image-lpub.png

上述版本前端没区别主要是后端对应不同版本, 随意下载一个版本即可,我这里下载的是ueditor1_4_3_3-utf8-jsp.zip

解压后如下图

image-brtg.png

将解压后的文件拷贝到vue项目中

image-tdfz.png

vue-cli2中我们放入的是static文件夹,设置UEDITOR_HOME_URL/static/UEditor/
vue-cli3中放入的是public文件夹,设置UEDITOR_HOME_URL/UEditor/
另外jsp文件夹下为后端内容,此处忽略未拷贝

2.安装vue-ueditor-wrap

npm install vue-ueditor-wrap --save

组件中引入,自定义组件

<template>
<vue-ueditor-wrap v-model="dataStr" mode="observer" :observer-options="observerOptions" :observer-debounce-time="50" :config="myConfig" ></vue-ueditor-wrap>
</template>

<script>
  import VueUeditorWrap from 'vue-ueditor-wrap'
  export default {
    name: 'UEditor',
    components: {
      VueUeditorWrap,
    },
    data() {
      return {
        dataStr: '请输入内容',
        observerOptions: {
          attributes: true, // 是否监听 DOM 元素的属性变化
          attributeFilter: ['src', 'style', 'type', 'name'], // 只有在该数组中的属性值的变化才会监听
          characterData: true, // 是否监听文本节点
          childList: true, // 是否监听子节点
          subtree: true, // 是否监听后代元素
        },
        myConfig: {
          
          toolbars: [[
            'fullscreen', 'source', '|', 'undo', 'redo', '|',
            'bold', 'italic', 'underline', 'fontborder', 'strikethrough', 'superscript', 'subscript', 'removeformat', 'formatmatch', 'autotypeset', 'blockquote', 'pasteplain', '|', 'forecolor', 'backcolor', 'insertorderedlist', 'insertunorderedlist', 'selectall', 'cleardoc', '|',
            'rowspacingtop', 'rowspacingbottom', 'lineheight', '|',
            'customstyle', 'paragraph', 'fontfamily', 'fontsize', '|',
            'directionalityltr', 'directionalityrtl', 'indent', '|',
            'justifyleft', 'justifycenter', 'justifyright', 'justifyjustify', '|', 'touppercase', 'tolowercase', '|',
            'link', 'unlink', 'anchor', '|', 'imagenone', 'imageleft', 'imageright', 'imagecenter', '|',
            'simpleupload', 'insertimage', 'emotion', 'scrawl', 'attachment',  'insertframe', 'insertcode', 'pagebreak', 'template', 'background', '|',
            'horizontal', 'date', 'time', 'spechars',  '|',
            'inserttable', 'deletetable', 'insertparagraphbeforetable', 'insertrow', 'deleterow', 'insertcol', 'deletecol', 'mergecells', 'mergeright', 'mergedown', 'splittocells', 'splittorows', 'splittocols', 'charts', '|',
            'print', 'preview', 'searchreplace', 'drafts', 'help'
          ]],
          // 编辑器不自动被内容撑高
          autoHeightEnabled: false,
          // 初始容器高度
          initialFrameHeight: 400,
          // 初始容器宽度
          initialFrameWidth: '100%',
          // 上传文件接口(这个地址是我为了方便各位体验文件上传功能搭建的临时接口,请勿在生产环境使用!!!)
          serverUrl: `${process.env.VUE_APP_BASE_API}/app-school/v1/public/index/api/admin/ueditor/`,
          UEDITOR_HOME_URL:
          process.env.NODE_ENV === 'development'
          ? '/static/ueditor/'
          : `${process.env.VUE_APP_PUBLIC_PATH}static/ueditor/`,
        },
      }
    },
    watch: {
      dataStr(val) {
        console.log('watch dataStr',this.dataStr)
      }
    },
    methods: {
      handleUpdate(data) {
        console.log('handleUpdate',data)
      }
    }
  }
</script>

<style lang="less" scoped>
  ::v-deep .edui-default .edui-toolbar {
    line-height: 20px;
    .edui-combox .edui-combox-body,
    .edui-button,
    .edui-splitbutton,
    .edui-menubutton {
      line-height: 20px;
    }
  }
</style>

3.后端配置

/* 前后端通信相关的配置,注释只允许使用多行方式 */
{
  /* 上传图片配置项 */
  "imageActionName": "uploadimage", /* 执行上传图片的action名称 */
  "imageFieldName": "upfile", /* 提交的图片表单名称 */
  "imageMaxSize": 2048000, /* 上传大小限制,单位B */
  "imageAllowFiles": [".png", ".jpg", ".jpeg", ".gif", ".bmp"], /* 上传图片格式显示 */
  "imageCompressEnable": true, /* 是否压缩图片,默认是true */
  "imageCompressBorder": 1600, /* 图片压缩最长边限制 */
  "imageInsertAlign": "none", /* 插入的图片浮动方式 */
  "imageUrlPrefix": "", /* 图片访问路径前缀 */
  "imagePathFormat": "/ueditor/jsp/upload/image/{yyyy}{mm}{dd}/{time}{rand:6}", /* 上传保存路径,可以自定义保存路径和文件名格式 */
  /* {filename} 会替换成原文件名,配置这项需要注意中文乱码问题 */
  /* {rand:6} 会替换成随机数,后面的数字是随机数的位数 */
  /* {time} 会替换成时间戳 */
  /* {yyyy} 会替换成四位年份 */
  /* {yy} 会替换成两位年份 */
  /* {mm} 会替换成两位月份 */
  /* {dd} 会替换成两位日期 */
  /* {hh} 会替换成两位小时 */
  /* {ii} 会替换成两位分钟 */
  /* {ss} 会替换成两位秒 */
  /* 非法字符 \ : * ? " < > | */
  /* 具请体看线上文档: fex.baidu.com/ueditor/#use-format_upload_filename */
  
  /* 涂鸦图片上传配置项 */
  "scrawlActionName": "uploadscrawl", /* 执行上传涂鸦的action名称 */
  "scrawlFieldName": "upfile", /* 提交的图片表单名称 */
  "scrawlPathFormat": "/ueditor/jsp/upload/image/{yyyy}{mm}{dd}/{time}{rand:6}", /* 上传保存路径,可以自定义保存路径和文件名格式 */
  "scrawlMaxSize": 2048000, /* 上传大小限制,单位B */
  "scrawlUrlPrefix": "", /* 图片访问路径前缀 */
  "scrawlInsertAlign": "none",
  
  /* 截图工具上传 */
  "snapscreenActionName": "uploadimage", /* 执行上传截图的action名称 */
  "snapscreenPathFormat": "/ueditor/jsp/upload/image/{yyyy}{mm}{dd}/{time}{rand:6}", /* 上传保存路径,可以自定义保存路径和文件名格式 */
  "snapscreenUrlPrefix": "", /* 图片访问路径前缀 */
  "snapscreenInsertAlign": "none", /* 插入的图片浮动方式 */
  
  /* 抓取远程图片配置 */
  "catcherLocalDomain": ["127.0.0.1", "localhost", "img.baidu.com"],
  "catcherActionName": "catchimage", /* 执行抓取远程图片的action名称 */
  "catcherFieldName": "source", /* 提交的图片列表表单名称 */
  "catcherPathFormat": "/ueditor/jsp/upload/image/{yyyy}{mm}{dd}/{time}{rand:6}", /* 上传保存路径,可以自定义保存路径和文件名格式 */
  "catcherUrlPrefix": "", /* 图片访问路径前缀 */
  "catcherMaxSize": 2048000, /* 上传大小限制,单位B */
  "catcherAllowFiles": [".png", ".jpg", ".jpeg", ".gif", ".bmp"], /* 抓取图片格式显示 */
  
  /* 上传视频配置 */
  "videoActionName": "uploadvideo", /* 执行上传视频的action名称 */
  "videoFieldName": "upfile", /* 提交的视频表单名称 */
  "videoPathFormat": "/ueditor/jsp/upload/video/{yyyy}{mm}{dd}/{time}{rand:6}", /* 上传保存路径,可以自定义保存路径和文件名格式 */
  "videoUrlPrefix": "", /* 视频访问路径前缀 */
  "videoMaxSize": 102400000, /* 上传大小限制,单位B,默认100MB */
  "videoAllowFiles": [
    ".flv", ".swf", ".mkv", ".avi", ".rm", ".rmvb", ".mpeg", ".mpg",
    ".ogg", ".ogv", ".mov", ".wmv", ".mp4", ".webm", ".mp3", ".wav", ".mid"], /* 上传视频格式显示 */
  
  /* 上传文件配置 */
  "fileActionName": "uploadfile", /* controller里,执行上传视频的action名称 */
  "fileFieldName": "upfile", /* 提交的文件表单名称 */
  "filePathFormat": "/ueditor/jsp/upload/file/{yyyy}{mm}{dd}/{time}{rand:6}", /* 上传保存路径,可以自定义保存路径和文件名格式 */
  "fileUrlPrefix": "", /* 文件访问路径前缀 */
  "fileMaxSize": 51200000, /* 上传大小限制,单位B,默认50MB */
  "fileAllowFiles": [
    ".png", ".jpg", ".jpeg", ".gif", ".bmp",
    ".flv", ".swf", ".mkv", ".avi", ".rm", ".rmvb", ".mpeg", ".mpg",
    ".ogg", ".ogv", ".mov", ".wmv", ".mp4", ".webm", ".mp3", ".wav", ".mid",
    ".rar", ".zip", ".tar", ".gz", ".7z", ".bz2", ".cab", ".iso",
    ".doc", ".docx", ".xls", ".xlsx", ".ppt", ".pptx", ".pdf", ".txt", ".md", ".xml"
  ], /* 上传文件格式显示 */
  
  /* 列出指定目录下的图片 */
  "imageManagerActionName": "listimage", /* 执行图片管理的action名称 */
  "imageManagerListPath": "/ueditor/jsp/upload/image/", /* 指定要列出图片的目录 */
  "imageManagerListSize": 20, /* 每次列出文件数量 */
  "imageManagerUrlPrefix": "", /* 图片访问路径前缀 */
  "imageManagerInsertAlign": "none", /* 插入的图片浮动方式 */
  "imageManagerAllowFiles": [".png", ".jpg", ".jpeg", ".gif", ".bmp"], /* 列出的文件类型 */
  
  /* 列出指定目录下的文件 */
  "fileManagerActionName": "listfile", /* 执行文件管理的action名称 */
  "fileManagerListPath": "/ueditor/jsp/upload/file/", /* 指定要列出文件的目录 */
  "fileManagerUrlPrefix": "", /* 文件访问路径前缀 */
  "fileManagerListSize": 20, /* 每次列出文件数量 */
  "fileManagerAllowFiles": [
    ".png", ".jpg", ".jpeg", ".gif", ".bmp",
    ".flv", ".swf", ".mkv", ".avi", ".rm", ".rmvb", ".mpeg", ".mpg",
    ".ogg", ".ogv", ".mov", ".wmv", ".mp4", ".webm", ".mp3", ".wav", ".mid",
    ".rar", ".zip", ".tar", ".gz", ".7z", ".bz2", ".cab", ".iso",
    ".doc", ".docx", ".xls", ".xlsx", ".ppt", ".pptx", ".pdf", ".txt", ".md", ".xml"
  ] /* 列出的文件类型 */
  
}
package com.huayun.bo.ioae.controller;

import com.alibaba.fastjson.JSONException;
import com.huayun.bo.ioae.controller.model.FileModel;
import com.huayun.bo.ioae.controller.model.FileVO;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.HashMap;
import java.util.Map;

/**
* 百度Ueditor配置及文件上传支持
* @author liuyulei
* 2022/5/10 9:47
* @version 1.0
*/
@RestController()
@RequestMapping("/api/public/ueditor")
@Api(tags = "百度Ueditor配置及文件上传支持")
public class UeditorBaseController {
    
    /**
    * 配置内容常量,用于缓存配置信息,避免每次由硬盘读取
    */
    private static String config;
    
    @GetMapping(value = "/",produces = "application/javascript")
    @ApiOperation(value = "获取ueditor配置")
    @ApiImplicitParam(name = "callback", value = "jsonp的callback", required = true, dataType = "String")
    public String config(String callback) throws JSONException {
        
        return "/**/"+callback+"("+ getConfig() +");";
        
    }
    
    /**
    * 文件上传<br>
    * 接受POST请求<br>
    * 同时支持多择文件上传和截图上传
    * @param upfile 文件流
    * @return
    * @throws JSONException
    * @throws IOException
    */
    @PostMapping(value = "/")
    @ApiOperation(value = "ueditor文件/图片上传")
    public Map upload(MultipartFile upfile) throws JSONException, IOException {
        Map result = new HashMap(16);
        if (upfile != null && upfile.getOriginalFilename() != null) {
            
            //文件类型
            String contentType= upfile.getContentType();
            //获取文件名称后缀
            String ext = contentType.substring(contentType.lastIndexOf("/") + 1, contentType.length());
            
            //if(!FileUtil.isAllowUpImg(ext)){
            //
            //    result.put("state","不允许上传的文件格式,请上传gif,jpg,png,jpeg,mp4格式文件。");
            //    return  result;
            //
            //}
            
            FileModel input  = new FileModel();
            input.setName(upfile.getOriginalFilename());
            input.setStream(upfile.getInputStream());
            input.setExt(ext);
            FileVO file  = null;//this.fileManager.upload(input, "ueditor");
            String url  = file.getUrl();
            String title = file.getName();
            String original = file.getName();
            result.put("state","SUCCESS");
            result.put("url", url);
            result.put("title", title);
            result.put("name", title);
            result.put("original", original);
            result.put("type","."+file.getExt());
            return  result;
            
        }else{
            
            result.put("state","没有读取要上传的文件");
            return  result;
        }
        
        
    }
    
    /**
    * 获取配置<br>
    * 如果config中已经存在,则直接返回,否则由硬盘读取<br>
    * 读取文件为/resource/ueditor_config.json<br><br>
    * @return
    */
    private String getConfig() {
        
        if (config == null || config.isEmpty()) {
            config = readFile("/config/ueditor_config.json");
        }
        
        return config;
    }
    
    private String readFile(String resource) {
        
        String stripped = resource.startsWith("/") ? resource.substring(1)
            : resource;
        
        InputStream stream = null;
        ClassLoader classLoader = Thread.currentThread()
            .getContextClassLoader();
        if (classLoader != null) {
            stream = classLoader.getResourceAsStream(stripped);
            
        }
        
        return readStreamToString(stream);
        
    }
    
    private String readStreamToString(InputStream stream) {
        StringBuilder fileContentsb = new StringBuilder();
        String fileContent = "";
        
        try {
            InputStreamReader read = new InputStreamReader(stream, "utf-8");
            BufferedReader reader = new BufferedReader(read);
            String line;
            while ((line = reader.readLine()) != null) {
                fileContentsb.append(line + "\n");
            }
            read.close();
            reader.close();
            fileContent = fileContentsb.toString();
        } catch (Exception ex) {
            fileContent = "";
        }
        return fileContent;
    }
    
    
}

package com.huayun.bo.ioae.controller.model;

import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;

import javax.validation.constraints.NotEmpty;
import java.io.InputStream;

/**
 * 文件上传入参
 * @author liuyulei
 * 2022/5/10 9:42
 * @version 1.0
 */
@ApiModel
public class FileModel {
    /**
     * 文件流
     */
    @ApiModelProperty(name = "stream", value = "文件流", required = true)
    private InputStream stream;
    /**
     * 文件名称
     */
    @NotEmpty(message = "文件名称不能为空")
    @ApiModelProperty(name = "name", value = "文件名称", required = true)
    private String name;
    /**
     * 文件后缀
     */
    private String ext;

    public InputStream getStream() {
        return stream;
    }

    public void setStream(InputStream stream) {
        this.stream = stream;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getExt() {
        return ext;
    }

    public void setExt(String ext) {
        this.ext = ext;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) {
            return true;
        }
        if (o == null || getClass() != o.getClass()) {
            return false;
        }

        FileModel fileDTO = (FileModel) o;

        if (stream != null ? !stream.equals(fileDTO.stream) : fileDTO.stream != null) {
            return false;
        }
        if (name != null ? !name.equals(fileDTO.name) : fileDTO.name != null) {
            return false;
        }
        return ext != null ? ext.equals(fileDTO.ext) : fileDTO.ext == null;
    }

    @Override
    public int hashCode() {
        int result = stream != null ? stream.hashCode() : 0;
        result = 31 * result + (name != null ? name.hashCode() : 0);
        result = 31 * result + (ext != null ? ext.hashCode() : 0);
        return result;
    }
}

package com.huayun.bo.ioae.controller.model;

import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;

/**
 * 文件上传返回值封装
 * @author liuyulei
 * 2022/5/10 9:47
 * @version 1.0
 */
@ApiModel
public class FileVO {
	/** 文件名称 */
	@ApiModelProperty(name="name",value="文件名称",required=true)
	private String name;
	/** 文件后缀 */
	@ApiModelProperty(name="ext",value="文件后缀",required=true)
	private String ext;
	/** url */
	@ApiModelProperty(name="url",value="图片地址",required=true)
	private String url;


	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}

	@Override
	public String toString() {
		return "FileVO{" +
				"name='" + name + '\'' +
				", ext='" + ext + '\'' +
				", url='" + url + '\'' +
				'}';
	}

	public String getExt() {
		return ext;
	}
	public void setExt(String ext) {
		this.ext = ext;
	}
	public String getUrl() {
		return url;
	}
	public void setUrl(String url) {
		this.url = url;
	}




}

后端接口自行实现文件上传服务器,在UeditorBaseController.java中进行适配即可


评论