vue-quill-editor的⼤图⽚上传问题解决
项⽬中有个使⽤vue-quill-editor富⽂本编辑器的功能,当上传⼤图⽚时,图⽚资源会被转成base64格式,当图⽚过⼤时字符串的⼤⼩可能达到2M以上,数据库⽆法保存。
vue-quill-editor提供了⼀个handlers可以⾃定义图⽚上传的⽅式,意思是点击这个图⽚按钮的时候,会出发⼀个回调,可以在回调⾥触发⾃⼰的⽂件上传开关。这⾥我⽤的⽂件上传是antd-vue的a-upload属性。
quill-quill-editor:
<quill-editor
v-model="message"
:options="editorOption"
@change="change">
<div id="toolbar" slot="toolbar"></div>
</quill-editor>
参数:
editorOption: {
modules: {
toolbar: {
container: [
["bold", "italic", "underline", "strike"], //加粗,斜体,下划线,删除线
["blockquote", "code-block"], //引⽤,代码块
[{ header: 1 }, { header: 2 }], // 标题,键值对的形式;1、2表⽰字体⼤⼩
[{ list: "ordered" }, { list: "bullet" }], //列表
[{ script: "sub" }, { script: "super" }], // 上下标
[{ indent: "-1" }, { indent: "+1" }], // 缩进
[{ direction: "rtl" }], // ⽂本⽅向
[{ size: ["small", false, "large", "huge"] }], // 字体⼤⼩
[{ header: [1, 2, 3, 4, 5, 6, false] }], //⼏级标题
[{ color: [] }, { background: [] }], // 字体颜⾊,字体背景颜⾊
[{ font: [] }], //字体
[{ align: [] }], //对齐⽅式
["clean"], //清除字体样式
["image"], //上传图⽚
],
handlers: {
image: (value) => {
if (value) {
          //  触发antd-vue的modal对话框
this.visible = true;
} else {
this.quill.format("image", false);
}
},
},
},
syntax: {
highlight: (text) => hljs.highlightAuto(text).value,
},
},
},
说明:
这⾥的思路是当点击图⽚按钮时,显⽰antd-vue的对话框,上传组件就放在对话框中
通过上传组件选择图⽚,并通过后端给的上传接⼝获取返回的地址
然后把返回的地址使⽤字符串处理把img的src动态拼接到内容中
对话框:
<a-modal
title="选择图⽚"
:visible="visible"
@ok="handleOk"
@cancel="handleCancel"
:closable="false"
okText="确定"
cancelText="取消"
:file-list="fileList"
:before-upload="beforeUpload"
>
<a-upload
class="pdupload"
name="file"
:
multiple="false"
:action="$api.upload"
@change="handleChange1"
accept=".jpg, .jpeg, .png, .webp"
:fileList="fl"
>
<a-button>
<a-icon type="upload"/>选择图⽚
</a-button>
<span >最多⼀次上传1张图⽚</span> </a-upload>
</a-modal>
handleChange1(info) {
console.log("图⽚", info);
if (info.fileList.length > 1) {
this.$message.warning("每次仅能上传⼀张图⽚!");
return;
}
this.fl = info.fileList;
if (info.file.status !== "uploading") {
console.log(info.file, info.fileList);
}
if (info.file.status === "done") {
this.detailImage = sponse.file_url;
this.$message.success(`${info.file.name}上传成功`);
} else if (info.file.status === "error") {
this.$(`${info.file.name}上传失败`);
}
},
handleOk() {
this.visible = false;
// 把图⽚⽤img标签的形式添加到详情中
console.log("结束标签所处位置", ssage.lastIndexOf("</p>"));
if (this.detailImage) {
let n = ssage.lastIndexOf("</p>");
let s = ssage;
let s1 = s.substring(0, n);
let domS = `<img src='${this.detailImage}'/></p>`;
s1 += domS;
}
// 清空已经选择的图⽚
this.fl = [];
this.detailImage = "";
},
handleCancel() {
this.visible = false;
}
组件源码
多文本编辑器editor什么意思<template>
<div class="pro_detail">
<!-- 产品详情组件 -->
<common-tit title="产品详情"></common-tit>
<quill-editor
v-model="message"
:options="editorOption"
@change="change">
<div id="toolbar" slot="toolbar"></div>
</quill-editor>
<a-modal
title="选择图⽚"
:visible="visible"
@ok="handleOk"
@cancel="handleCancel"
:closable="false"
okText="确定"
cancelText="取消"
:
file-list="fileList"
:before-upload="beforeUpload"
>
<a-upload
class="pdupload"
name="file"
:multiple="false"
:action="$api.upload"
@change="handleChange1"
accept=".jpg, .jpeg, .png, .webp"
:fileList="fl"
>
<a-button>
<a-icon type="upload"/>选择图⽚
</a-button>
<span >最多⼀次上传1张图⽚</span> </a-upload>
</a-modal>
</div>
</template>
<script>
import CommonTit from "../CommonTit";
export default {
components: { CommonTit },
props: ["proDetail"],
data() {
return {
fl: [],
visible: false,
previewVisible: false,
detailImage: "",
message: "",
editorOption: {
modules: {
toolbar: {
container: [
["bold", "italic", "underline", "strike"], //加粗,斜体,下划线,删除线
["blockquote", "code-block"], //引⽤,代码块
[{ header: 1 }, { header: 2 }], // 标题,键值对的形式;1、2表⽰字体⼤⼩
[{ list: "ordered" }, { list: "bullet" }], //列表
[{ script: "sub" }, { script: "super" }], // 上下标
[{ indent: "-1" }, { indent: "+1" }], // 缩进
[{ direction: "rtl" }], // ⽂本⽅向
[{ size: ["small", false, "large", "huge"] }], // 字体⼤⼩
[{ header: [1, 2, 3, 4, 5, 6, false] }], //⼏级标题
[{ color: [] }, { background: [] }], // 字体颜⾊,字体背景颜⾊
[{ font: [] }], //字体
[{ align: [] }], //对齐⽅式
["clean"], //清除字体样式
["image"], //上传图⽚
],
handlers: {
image: (value) => {
if (value) {
this.visible = true;
} else {
this.quill.format("image", false);
}
},
},
},
syntax: {
highlight: (text) => hljs.highlightAuto(text).value,
},
},
},
};
},
methods: {
change() {
console.ssage);
this.$emit("update:proDetail", ssage);
},
handleChange1(info) {
console.log("图⽚", info);
if (info.fileList.length > 1) {
this.$message.warning("每次仅能上传⼀张图⽚!");
return;
}
this.fl = info.fileList;
if (info.file.status !== "uploading") {
console.log(info.file, info.fileList);
}
if (info.file.status === "done") {
this.detailImage = sponse.file_url;
this.$message.success(`${info.file.name}上传成功`);
} else if (info.file.status === "error") {
this.$(`${info.file.name}上传失败`);
}
},
handleOk() {
this.visible = false;
// 把图⽚⽤img标签的形式添加到详情中
console.log("当前内容:", ssage);
console.log("结束标签所处位置", ssage.lastIndexOf("</p>"));      if (this.detailImage) {
let n = ssage.lastIndexOf("</p>");
let s = ssage;
let s1 = s.substring(0, n);
let domS = `<img src='${this.detailImage}'/></p>`;
s1 += domS;
}
// 清空已经选择的图⽚
this.fl = [];
this.detailImage = "";
},
handleCancel() {
this.visible = false;
},
},
mounted() {
},
};
</script>
<style lang="scss" scoped>
.pro_detail {
height: 594px !important;
border-bottom-width: 0;
.quill-editor {
text-align: left;
height: 491px;
>>> .ql-toolbar .ql-formats {
margin-right: 0;
}
}
>>> .ant-upload {
display: flex;
flex-direction: column;
}
}
</style>