安装
npm install vue-quill-editor -S
//vue-quill-editor的增强模块
npm install quill-image-extend-module --save-dev
新建 HelloWorld.vue
<template>
<div class="quill-wrap">
<input ref="fileRef" type="file" v-show="false" @change="addImg($event)" />
<quill-editor
ref="myQuillEditor"
v-model="contentData" @change="changeData($event)"
:options="editorOption"
/>
</div>
</template>
<script>
import "quill/dist/quill.snow.css";
import { quillEditor, Quill } from "vue-quill-editor";
import { container, ImageExtend, QuillWatch } from "quill-image-extend-module";
Quill.register("modules/ImageExtend", ImageExtend);
import { watermark, client, getFileNameUUID,multipartUpload } from "@/utils/alioss";
export default {
components: { quillEditor },
data() {
const dataThis = this;
const toolbarOptions = [
["bold", "italic", "underline", "strike"], // toggled buttons
["blockquote", "code-block"],
[{ header: 1 }, { header: 2 }], // custom button values
[{ list: "ordered" }, { list: "bullet" }],
[{ script: "sub" }, { script: "super" }], // superscript/subscript
[{ indent: "-1" }, { indent: "+1" }], // outdent/indent
[{ direction: "rtl" }], // text direction
[{ size: ["small", false, "large", "huge"] }], // custom dropdown
[{ header: [1, 2, 3, 4, 5, 6, false] }],
[{ color: [] }, { background: [] }], // dropdown with defaults from theme
[{ font: [] }],
[{ align: [] }],
["link", "image", "video"],
// ["clean"], // remove formatting button
];
return {
dataType: 1, //1 图片 2 视频
fileList: [],
editorOption: {
// 富文本框参数设置
modules: {
toolbar: {
container: toolbarOptions,
handlers: {
image: (value) => {
if (value) {
// 当点击.editor-img-plus时。触发上传图片事件
dataThis.dataType = 1;
dataThis.$refs["fileRef"].click();
} else {
this.quill.format("image", false);
}
},
video: (value) => {
if (value) {
// 当点击.editor-img-plus时。触发上传图片事件
dataThis.dataType = 1;
dataThis.$refs["fileRef"].click();
} else {
this.quill.format("video", false);
}
},
},
},
},
},
};
},
model: {
prop: 'content',
event: 'update'
},
props: {
content: ''
},
computed: {
contentData: {
get(){ return this.content;},
set(V){this.$emit('update', V);}
}
},
methods: {
changeData(e){
this.$emit('update', e.html);
},
addImg(event) {
var file = event.target.files[0];
let type = file.type;
if (type.indexOf("image") != -1) {
const isLt2M = file.size / 1024 / 1024 < 5; //5m
if (!isLt2M) {
this.$message.error("图片大小不能超过 5MB!");
return false;
}
} else if (type.indexOf("video") != -1) {
const isLt2M = file.size / 1024 / 1024 < 30; //30m
if (!isLt2M) {
this.$message.error("视频大小不能超过 30MB!");
return false;
}
} else {
this.$message.error("文件格式错误");
return false;
}
let fileName = '';
if(type.indexOf('image') != -1){
fileName = getFileNameUUID()+'.jpg';
}else if(type.indexOf('video') != -1){
fileName = getFileNameUUID()+'.mp4';
}
this.openFullScreen();
multipartUpload(fileName,file,{},(url)=>{
// console.log(url);
file.response = {url};
console.log(url);
let quill = this.$refs.myQuillEditor.quill;
// 获取光标所在位置
let length = quill.getSelection().index;
if(type.indexOf('image') != -1){
// 插入图片,url为服务器返回的图片链接地址
quill.insertEmbed(length, 'image', url)
}else if(type.indexOf('video') != -1){
quill.insertEmbed(length, 'video', url)
}
// 调整光标到最后
quill.setSelection(length + 1)
this.openFullScreenClose();
});
},
openFullScreen() {
let loading = this.$loading({
lock: true,
text: 'Loading',
spinner: 'el-icon-loading',
background: 'rgba(0, 0, 0, 0.7)'
});
this.loading = loading;
},
openFullScreenClose(){
if(this.loading){
this.loading.close();
}
},
},
};
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
h1,
h2 {
font-weight: normal;
}
ul {
list-style-type: none;
padding: 0;
}
li {
display: inline-block;
margin: 0 10px;
}
a {
color: #42b983;
}
</style>
alioss js文件
const OSS = require('ali-oss');
//水印
const watermark = '?x-oss-process=image/resize,w_300/watermark,image_bG9nby9sb2dvLnBuZw==,t_50,g_se,x_10,y_10';
//地址 oss-cn-shenzhen
const fileHost = 'oos region';
//签名
const bucketName = 'OOS bucket';
//id
const accessId = '阿里云OOS accessId ';
//签名
const accessKey = '阿里云OOS accessKey ';
//阿里云配置
let client = new OSS({
region: fileHost,
accessKeyId: accessId,
accessKeySecret: accessKey,
secure: true,
bucket: bucketName
})
/**
* 生成随机文件名称
* 规则八位随机字符,加下划线连接时间戳
*/
const getFileNameUUID = () => {
function rx() {
return (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1)
}
return `${+new Date()}_${rx()}${rx()}`
}
const multipartUpload = (fileName, file,config,callback)=>{
client.multipartUpload(fileName, file, config).then(results => {
// console.log(results.res.requestUrls);
if(results.res.requestUrls[0].indexOf('?') != -1){
let url = results.res.requestUrls[0].split('?')[0].replace("bucketec.oss-cn-shenzhen.aliyuncs.com","映射的域名");;
// console.log(url);
if(callback){
callback(url);
}
}else{
//console.log('图片100k以内')
let url = results.res.requestUrls[0].replace("bucketec.oss-cn-shenzhen.aliyuncs.com","映射的域名");
// console.log(url);
if(callback){
callback(url);
}
}
}).catch((err) => {
console.log(err);
});
}
export {
watermark,
client,
getFileNameUUID,
multipartUpload
}
组件引用(注意对应组件的路径
)
<template>
<div>
<hello-world v-model="contentData" ></hello-world>
<el-button type="primary" @click="dataClick" >主要按钮</el-button>
</div>
</template>
<script>
import HelloWorld from '@/components/HelloWorld'
export default {
components: { HelloWorld },
data() {
return {
contentData:'',
};
},
methods: {
dataClick(){
console.log(this.contentData);
}
},
};
</script>
效果图