前言
在本文中笔者使用的是wangEditor,wangEditor是比较轻量级 web 富文本编辑器,配置方便,使用简单。 话不多说先看示例图
一、vue引入富文本
npm install --save wangeditor
版本:3.1.1
二、使用步骤
1.自定义组件
代码如下(示例):
<template>
<div>
<div id="editor" ref="myEditor"></div>
<slot></slot>
</div>
</template>
<script>
import WangEditor from 'wangeditor'
export default {
name: 'ComponentWangeditor',
data () {
return {
edit: ''
}
},
props: {
value: {
type: String,
default: ''
},
config: {
type: Array,
default: () => {
return {}
}
},
uploadConfig: {
type: Array,
default: () => {
return {
method: 'http', // 支持custom(objurl)和http(服务器)和base64
url: '/'
}
}
}
},
computed: {
customConfig () {
return {
pasteFilterStyle: false, // 关闭掉粘贴样式的过滤
pasteIgnoreImg: false, // 粘贴时不忽略图片
showLinkImg: false,
menus:[ // 菜单配置
'head', // 标题
'bold', // 粗体
'fontSize', // 字号
'fontName', // 字体
'italic', // 斜体
'underline', // 下划线
'strikeThrough', // 删除线
//'foreColor', // 文字颜色
//'backColor', // 背景颜色
//'link', // 插入链接
'list', // 列表
'justify', // 对齐方式
//'quote', // 引用
'emoticon', // 表情
'image', // 插入图片
// 'table', // 表格
// 'code', // 插入代码
'undo', // 撤销
'redo' // 重复
],
...this.config
}
}
},
watch: {
value: {
deep: true,
handler(val){
this.editor.txt.html(val)// 生成编辑器
}
}
},
components: {},
methods: {
readBlobAsDataURL (blob, callback) {
var a = new FileReader()
a.onload = function (e) { callback(e.target.result) }
a.readAsDataURL(blob)
},
initEditor () {
var self = this
this.editor = new WangEditor(this.$refs.myEditor)
// 配置 onchange 事件
this.editor.customConfig = this.customConfig
// 将图片大小限制为 1M 2M的话就写2*1024*1024
this.editor.customConfig.uploadImgMaxSize = 1 * 1024 * 1024
//限制一次最多上传 1 张图片
this.editor.customConfig.uploadImgMaxLength = 1
this.editor.change = function () { // 编辑区域内容变化时
self.$emit('input', this.txt.html())
self.$emit('onchange', this.txt.html(), this.txt)
// editor.txt.html('.....') //设置编辑器内容
// editor.txt.clear() //清空编辑器内容
// editor.txt.append('<p>追加的内容</p>')//继续追加内容。
// editor.txt.text() // 读取 text
// editor.txt.getJSON() // 获取 JSON 格式的内容
}
this.editor.customConfig.customUploadImg = function (files, insert) {
if (self.uploadConfig.method === 'custom') {
if (self.uploadConfig.callback) {
self.uploadConfig.callback(files, insert)
}
}
if (self.uploadConfig.method === 'base64') {
files.forEach(file => {
self.readBlobAsDataURL(file, function (dataurl) {
insert(dataurl)
})
})
}
if (self.uploadConfig.method === 'http') {
if (self.uploadConfig.callback) {
self.uploadConfig.callback(files, insert)
} else {
var formData = new FormData()
files.forEach(file => {
formData.append('file', file)
})
self.$axios.post(self.uploadConfig.url, formData).then(({ data }) => {
if (data.status === 'success') {
insert(data.url)
}
})
}
}
}
this.editor.create() // 生成编辑器
this.editor.txt.text(this.value) // 生成编辑器
this.$emit('oninit', this.editor)
}
},
beforeCreate () {
},
created () {
},
beforeMount () {
},
mounted () {
this.initEditor()
}
}
</script>
<style >
.w-e-toolbar{
flex-wrap:wrap;
}
</style>
2.注册以及使用组件
代码如下(示例):
<template>
<div>
<antd-editor :uploadConfig="editorUploadConfig" v-model="editorContent" @onchange="changeEditor" @oninit="getEditor" />
</div>
</template>
引入组件
import { AntdEditor } from '@/components'
<script>
import { sysConsultiveEdit } from '@/api/modular/edu/consultiveManage'
import { AntdEditor } from '@/components'
import { imgUpload } from '@/api/modular/system/fileManage'
export default {
components: {
AntdEditor
},
data() {
return {
editorContentText: '',
editorUploadConfig: {
method: 'custom',
callback: this.editorUploadImage
},
editorContent: '',
labelCol: {
xs: {
span: 24
},
sm: {
span: 5
}
},
wrapperCol: {
xs: {
span: 24
},
sm: {
span: 15
}
},
visible: false,
confirmLoading: false,
form: this.$form.createForm(this),
loading: false,
pic: ''
}
},
methods: {
/**
* 编辑器回调上传及回传图片url
*/
editorUploadImage (files, insert) {
const formData = new FormData()
files.forEach(file => {
formData.append('file', file)
formData.append('tag',"wangEdit")
})
imgUpload(formData).then((res) => {
if (res.success) {
insert(res.data)
} else {
this.$message.error('编辑器上传图片失败:' + res.message)
}
})
},
getEditor (editor) {
this.editor = editor
},
changeEditor (html, ele) {
this.editorContent = html
this.editorContentText = ele.text()
},
selfUpload(data) {
const formData = new FormData()
formData.append('file', data.file)
formData.append('tag', 'article')
imgUpload(formData).then((res) => {
if (res.success) {
console.log(res.data)
this.pic=res.data
this.$message.success('上传成功')
} else {
this.$message.error('上传失败:' + res.message)
}
})
},
beforeUpload(file) {
const isJPG = file.type === 'image/jpeg' || file.type === 'image/jpg' || file.type === 'image/png' || file.type ===
'image/bmp'
if (!isJPG) {
this.$message.error('请上传图片文件');
}
const isLt2M = file.size / 1024 / 1024 < 1;
if (!isLt2M) {
this.$message.error('文件大小应小于 1M');
}
return isJPG && isLt2M
},
edit(record) {
this.visible = true
this.pic= record.pic
this.test = decodeURIComponent(record.content)
setTimeout(() => {
this.form.setFieldsValue({
aid: record.aid,
catid: record.catid,
title: record.title,
summary: record.summary,
pic: record.pic,
content: decode(record.content),
status: record.status,
createTime: record.createTime,
readNum: record.readNum,
shareNum: record.shareNum,
sortId: record.sortId,
location: record.location,
});
}, 100)
},
handleSubmit() {
const {
form: {
validateFields
}
} = this
this.confirmLoading = true
validateFields((errors, values) => {
if (!errors) {
values.content = this.editorContent
sysConsultiveEdit(values).then((res) => {
console.log(values)
values.pic=this.pic
this.confirmLoading = false
if (res.code === 200) {
this.$message.success('编辑成功')
this.visible = false
this.confirmLoading = false
this.handleCancel()
this.$emit('ok', values)
} else {
this.$message.info('编辑失败:' + res.message)
}
}).finally((res) => {
this.confirmLoading = false
})
} else {
this.confirmLoading = false
}
})
},
handleCancel() {
this.form.resetFields()
this.visible = false
}
}
}
</script>
后端
1.controller ResponseData 是自己封装的请求响应实体
@Data
public class ResponseData {
public static final String DEFAULT_SUCCESS_MESSAGE = "请求成功";
public static final String DEFAULT_ERROR_MESSAGE = "网络异常";
public static final String DEFAULT_ERROR_DATA_DUPLICATION="数据重复";
public static final String REPEAT_SUBMIT="重复提交";
public static final String DATA_EXCEPTION_ERROR="数据异常";
public static final Integer DEFAULT_SUCCESS_CODE = 200;
public static final Integer DEFAULT_ERROR_CODE = 500;
/**
* 请求是否成功
*/
private Boolean success;
/**
* 响应状态码
*/
private Integer code;
/**
* 响应信息
*/
private String message;
/**
* 响应对象
*/
private Object data;
public ResponseData() {
}
public ResponseData(Boolean success, Integer code, String message, Object data) {
this.success = success;
this.code = code;
this.message = message;
this.data = data;
}
public static SuccessResponseData success() {
return new SuccessResponseData();
}
public static SuccessResponseData success(Object object) {
return new SuccessResponseData(object);
}
public static SuccessResponseData success(Integer code, String message, Object object) {
return new SuccessResponseData(code, message, object);
}
public static ErrorResponseData error(String message) {
return new ErrorResponseData(message);
}
public static ErrorResponseData error(Integer code, String message) {
return new ErrorResponseData(code, message);
}
public static ErrorResponseData error(Integer code, String message, Object object) {
return new ErrorResponseData(code, message, object);
}
}
@PostMapping("/sysFileInfo/uploadMsg")
@BusinessLog(title = "文件信息表_上传文件", opType = LogAnnotionOpTypeEnum.OTHER)
public ResponseData uploadMsg(@RequestPart("file") MultipartFile file, @RequestParam String tag) {
re
Impl
@Override
public ResponseData uploadMsgFile(MultipartFile file, String tag) {
// 获取文件后缀
String fileSuffix = null;
if (ObjectUtil.isNotEmpty(file.getOriginalFilename())) {
fileSuffix = StrUtil.subAfter(file.getOriginalFilename(), SymbolConstant.PERIOD, true);
}
// 生成文件的最终名称
String finalName = UUID.randomUUID().toString().replace("-","") + SymbolConstant.PERIOD + fileSuffix;
// 存储文件
byte[] bytes;
try {
bytes = file.getBytes();
String s = OSSUtil.uploadBytes(bytes, tag + "/" + finalName);
if(ObjectUtil.isNotNull(s)){
return new SuccessResponseData(s);
}
} catch (IOException e) {
throw new ServiceException(SysFileInfoExceptionEnum.ERROR_FILE);
}
return new SuccessResponseData(ResponseData.DEFAULT_ERROR_CODE, ResponseData.DEFAULT_ERROR_MESSAGE, SysFileInfoExceptionEnum.ERROR_FILE);
}
3.文件上传OOS工具类
package com.zyedu.sys.core.aliyun;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.model.OSSObjectSummary;
import com.aliyun.oss.model.ObjectListing;
import com.aliyun.oss.model.PutObjectRequest;
import com.zyedu.sys.config.AliyunConfig;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;
import javax.annotation.PostConstruct;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
@Slf4j
@Component
public class OSSUtil {
@Autowired
private AliyunConfig ossConfig;
public static OSSUtil ossUtil;
@PostConstruct
public void init() {
ossUtil = this;
}
//获取OSSClient实例
private static OSS getOSSClient() {
OSS ossClient = new OSSClientBuilder().build(ossUtil.ossConfig.getEndpoint(), ossUtil.ossConfig.getAccessKeyId(), ossUtil.ossConfig.getAccessKeySecret());
return ossClient;
}
/**
* 本地文件方式上传
*
* @param file 文件
* @param key 路径/名称
*/
public static void uploadFile(File file, String key) {
OSS ossClient = getOSSClient();
// 上传文件流
ossClient.putObject(ossUtil.ossConfig.getBucket(), key, file);
// 关闭client
ossClient.shutdown();
}
/**
* MultipartFile方式上传
*
* @param file
* @param key
* @return
* @throws IOException
*/
public static String uploadPic(MultipartFile file, String key) throws IOException {
OSS ossClient = getOSSClient();
ossClient.putObject(ossUtil.ossConfig.getBucket(), key, file.getInputStream());
ossClient.shutdown();
return key;
}
/**
* 字符串方式上传
*
* @param ctx
* @param key
*/
public static void uploadString(String ctx, String key) {
OSS ossClient = getOSSClient();
PutObjectRequest putObjectRequest = new PutObjectRequest(ossUtil.ossConfig.getBucket(), key, new ByteArrayInputStream(ctx.getBytes()));
// 上传字符串。
ossClient.putObject(putObjectRequest);
// 关闭OSSClient。
ossClient.shutdown();
}
/**
* Byte数组方式上传
*
* @param content
* @param key
*/
public static String uploadBytes(byte[] content, String key) {
OSS ossClient = getOSSClient();
ossClient.putObject(ossUtil.ossConfig.getBucket(), key, new ByteArrayInputStream(content));
// 关闭OSSClient
ossClient.shutdown();
return ossUtil.ossConfig.getUrl()+key;
}
/**
* 网络流方式上传
*
* @param uri
* @param key
* @throws IOException
*/
public static void uploadInputUri(String uri, String key) throws IOException {
OSS ossClient = getOSSClient();
InputStream inputStream = new URL(uri).openStream();
ossClient.putObject(ossUtil.ossConfig.getBucket(), key, inputStream);
// 关闭OSSClient
ossClient.shutdown();
}
// 删除文件
public static void deleteFile(String key) {
// 创建OSSClient实例
OSS ossClient = getOSSClient();
// 删除Object
ossClient.deleteObject(ossUtil.ossConfig.getBucket(), key);
// 关闭client
ossClient.shutdown();
}
//获取存储对象的名字
public static void listObject() {
OSS ossClient = getOSSClient();
// 获取指定bucket下的所有Object信息
ObjectListing listing = ossClient.listObjects(ossUtil.ossConfig.getBucket());
// 遍历所有Object
for (OSSObjectSummary objectSummary : listing.getObjectSummaries()) {
log.info(objectSummary.getKey());
}
}
}
4.AliyunConfig配置实体类
@Data
@Component
@ConfigurationProperties(prefix = "aliyun")
public class AliyunConfig {
private String accessKeyId;
private String accessKeySecret;
private String endpoint;
private String bucket;
private String url;
}
5.application.yml配置文件
aliyun:
accessKeyId:你的accessKeyId
accessKeySecret: 你的accessKeySecret
endpoint: https://oss-cn-shanghai.aliyuncs.com //这个是示例
bucket: 你的bucket
版权说明
文章采用: 《署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0)》许可协议授权。版权声明:未标注转载均为本站原创,转载时请以链接形式注明文章出处。如有侵权、不妥之处,请联系站长删除。敬请谅解!