|
|
@@ -1,14 +1,25 @@
|
|
|
<script lang="ts" setup>
|
|
|
-import { QuillEditor } from "@vueup/vue-quill"
|
|
|
+import { QuillEditor, Quill } from "@vueup/vue-quill"
|
|
|
import "@vueup/vue-quill/dist/vue-quill.snow.css"
|
|
|
|
|
|
-const props = defineProps<{
|
|
|
- modelValue?: string
|
|
|
- height?: number
|
|
|
- minHeight?: number
|
|
|
- readOnly?: boolean
|
|
|
-}>()
|
|
|
+const props = withDefaults(
|
|
|
+ defineProps<{
|
|
|
+ modelValue?: string
|
|
|
+ height?: number
|
|
|
+ minHeight?: number
|
|
|
+ readOnly?: boolean
|
|
|
+ fileSize?: number
|
|
|
+ type?: "url" | "base64"
|
|
|
+ }>(),
|
|
|
+ {
|
|
|
+ type: "url",
|
|
|
+ fileSize: 5
|
|
|
+ }
|
|
|
+)
|
|
|
defineEmits<(e: "update:modelValue", v: string) => void>()
|
|
|
+const quillEditorRef = ref()
|
|
|
+const uploadRef = ref()
|
|
|
+
|
|
|
const options = ref({
|
|
|
theme: "snow",
|
|
|
bounds: document.body,
|
|
|
@@ -26,11 +37,72 @@ const options = ref({
|
|
|
[{ align: [] }], // 对齐方式
|
|
|
["clean"], // 清除文本格式
|
|
|
["link", "image", "video"] // 链接、图片、视频
|
|
|
- ]
|
|
|
+ ],
|
|
|
+ handlers: {
|
|
|
+ image: (value: boolean) => {
|
|
|
+ if (value) {
|
|
|
+ // 调用element图片上传
|
|
|
+ uploadRef.value.click()
|
|
|
+ } else {
|
|
|
+ Quill.format("image", true)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
},
|
|
|
placeholder: "请输入内容",
|
|
|
readOnly: props.readOnly
|
|
|
})
|
|
|
+const upload = reactive({
|
|
|
+ headers: {
|
|
|
+ Authorization: "Bearer " + getToken(),
|
|
|
+ ClientId: import.meta.env.VITE_APP_CLIENT_ID
|
|
|
+ },
|
|
|
+ url: import.meta.env.VITE_APP_BASE_API + "/resource/oss/upload"
|
|
|
+})
|
|
|
+
|
|
|
+// 图片上传成功返回图片地址
|
|
|
+const handleUploadSuccess = (res: any) => {
|
|
|
+ // 如果上传成功
|
|
|
+ if (res.code === 200) {
|
|
|
+ // 获取富文本实例
|
|
|
+ const quill = toRaw(quillEditorRef.value).getQuill()
|
|
|
+ // 获取光标位置
|
|
|
+ const length = quill.selection.savedRange.index
|
|
|
+ // 插入图片,res为服务器返回的图片链接地址
|
|
|
+ quill.insertEmbed(length, "image", res.data.url)
|
|
|
+ // 调整光标到最后
|
|
|
+ quill.setSelection(length + 1)
|
|
|
+ } else {
|
|
|
+ message.msgError("图片插入失败")
|
|
|
+ }
|
|
|
+ message.closeLoading()
|
|
|
+}
|
|
|
+
|
|
|
+// 图片上传前拦截
|
|
|
+const handleBeforeUpload = (file: any) => {
|
|
|
+ const type = ["image/jpeg", "image/jpg", "image/png", "image/svg"]
|
|
|
+ const isJPG = type.includes(file.type)
|
|
|
+ //检验文件格式
|
|
|
+ if (!isJPG) {
|
|
|
+ message.msgError(`图片格式错误!`)
|
|
|
+ return false
|
|
|
+ }
|
|
|
+ // 校检文件大小
|
|
|
+ if (props.fileSize) {
|
|
|
+ const isLt = file.size / 1024 / 1024 < props.fileSize
|
|
|
+ if (!isLt) {
|
|
|
+ message.msgError(`上传文件大小不能超过 ${props.fileSize} MB!`)
|
|
|
+ return false
|
|
|
+ }
|
|
|
+ }
|
|
|
+ message.loading("正在上传文件,请稍候...")
|
|
|
+ return true
|
|
|
+}
|
|
|
+
|
|
|
+// 图片失败拦截
|
|
|
+const handleUploadError = (err: any) => {
|
|
|
+ message.msgError("上传文件失败")
|
|
|
+}
|
|
|
|
|
|
const styles = computed(() => {
|
|
|
const style: any = {}
|
|
|
@@ -57,7 +129,22 @@ watch(
|
|
|
|
|
|
<template>
|
|
|
<div class="editor">
|
|
|
+ <div>
|
|
|
+ <el-upload
|
|
|
+ v-if="type === 'url'"
|
|
|
+ :action="upload.url"
|
|
|
+ :before-upload="handleBeforeUpload"
|
|
|
+ :on-success="handleUploadSuccess"
|
|
|
+ :on-error="handleUploadError"
|
|
|
+ class="editor-img-uploader"
|
|
|
+ name="file"
|
|
|
+ :show-file-list="false"
|
|
|
+ :headers="upload.headers">
|
|
|
+ <i ref="uploadRef"></i>
|
|
|
+ </el-upload>
|
|
|
+ </div>
|
|
|
<quill-editor
|
|
|
+ ref="quillEditorRef"
|
|
|
v-model:content="content"
|
|
|
contentType="html"
|
|
|
@textChange="(e) => $emit('update:modelValue', content)"
|