优化富文本编辑器,粘贴其他网站时,通过上传服务器将图片转为base64格式
This commit is contained in:
parent
53c8857e9d
commit
9c40455709
|
|
@ -146,3 +146,15 @@ export const setArticleCategories = (data) => {
|
|||
data
|
||||
})
|
||||
}
|
||||
|
||||
// @Summary 更新文章分类
|
||||
// @Produce application/json
|
||||
// @Param menu Object
|
||||
// @Router /cms/article/setChannels [put]
|
||||
export const getImgData = (params) => {
|
||||
return service({
|
||||
url: '/cms/article/getImgData',
|
||||
method: 'get',
|
||||
params
|
||||
})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
<template>
|
||||
<div class="border border-solid border-gray-100 h-full">
|
||||
<div class="border border-solid border-gray-100 h-full" v-loading="loadingShow">
|
||||
<Toolbar :editor="editorRef" :default-config="toolbarConfig" mode="default" />
|
||||
<Editor v-model="valueHtml" class="overflow-y-hidden mt-0.5" :style="style" :default-config="editorConfig"
|
||||
mode="default" @onCreated="handleCreated" @onChange="change" @customPaste="customPaste" />
|
||||
|
|
@ -16,7 +16,9 @@ import { onBeforeUnmount, ref, shallowRef, watch } from 'vue'
|
|||
import { Editor, Toolbar } from '@wangeditor/editor-for-vue'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import { getUrl } from '@/utils/image'
|
||||
import { getImgData } from '@/api/article'
|
||||
|
||||
const loadingShow = ref(false)
|
||||
const emits = defineEmits(['change', 'update:modelValue'])
|
||||
const change = (editor) => {
|
||||
emits('change', editor)
|
||||
|
|
@ -74,40 +76,73 @@ const handleCreated = (editor) => {
|
|||
}
|
||||
|
||||
const customPaste = (editor, event, callback) => {
|
||||
// 显示蒙版
|
||||
loadingShow.value = true
|
||||
|
||||
let htmlData = event.clipboardData.getData('text/html') // 获取粘贴的 html
|
||||
// console.log(htmlData)
|
||||
let rtfData = event.clipboardData.getData('text/rtf') // 获取粘贴的 html
|
||||
// console.log('-------------- rtfData --------------', rtfData)
|
||||
|
||||
htmlData = htmlData.replace(/<\/?span[^>]*>/g, '');
|
||||
htmlData = htmlData.replace(/<\/?font[^>]*>/g, '');
|
||||
// htmlData = htmlData.replace(/<p[^>]*(?:>|\s[^>]*>)/gi, '<p>');
|
||||
htmlData = htmlData.replace(/<img/g, '<img referrerpolicy="no-referrer"')
|
||||
// console.log('111111111111 replace after 1111111111', htmlData)
|
||||
|
||||
|
||||
// 从html内容中查找粘贴内容中是否有图片元素,并返回img标签的属性src值的集合
|
||||
const imgSrcs = htmlData.match(/<img [^>]*src=['"]([^'"]+)[^>]*>/g);
|
||||
// console.log('imgSrcs', imgSrcs)
|
||||
if (rtfData !== "") {
|
||||
// 处理 word 内图片
|
||||
// 从html内容中查找粘贴内容中是否有图片元素,并返回img标签的属性src值的集合
|
||||
const imgSrcs = htmlData.match(/<img [^>]*src=['"]([^'"]+)[^>]*>/g);
|
||||
// 如果有
|
||||
if (imgSrcs && Array.isArray(imgSrcs) && imgSrcs.length) {
|
||||
// console.log('imgSrcs', imgSrcs)
|
||||
// 从rtf内容中查找图片数据
|
||||
const rtfImageData = extractImageDataFromRtf(rtfData);
|
||||
// console.log('rtfImageData', rtfImageData)
|
||||
// 如果找到
|
||||
if (rtfImageData.length) {
|
||||
// TODO:此处可以将图片上传到自己的服务器上,
|
||||
|
||||
// 执行替换:将html内容中的img标签的src替换成ref中的图片数据,如果上面上传了则为图片路径
|
||||
htmlData = replaceImageFile(htmlData, imgSrcs, rtfImageData)
|
||||
// console.log('22222222222222222 replace after 22222222222222222', htmlData)
|
||||
// console.log('22222222222222222 ----------- 22222222222222222', htmlData)
|
||||
editor.dangerouslyInsertHtml(htmlData);
|
||||
loadingShow.value = false
|
||||
callback(false)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (imgSrcs && Array.isArray(imgSrcs) && imgSrcs.length) {
|
||||
convertImgToBase64(imgSrcs).then(imgList => {
|
||||
imgList.forEach(item => {
|
||||
htmlData = htmlData.replace(item.src, item.tar)
|
||||
})
|
||||
// console.log('33333333333333333 ----------- 33333333333333333', htmlData)
|
||||
editor.dangerouslyInsertHtml(htmlData);
|
||||
// 隐藏蒙版
|
||||
loadingShow.value = false
|
||||
callback(false)
|
||||
})
|
||||
} else {
|
||||
loadingShow.value = false
|
||||
callback(false)
|
||||
}
|
||||
}
|
||||
event.preventDefault()
|
||||
}
|
||||
|
||||
const convertImgToBase64 = async (data) => {
|
||||
let replaces = []
|
||||
for (let i = 0; i < data.length; i++) {
|
||||
const imgSrc = data[i].match(/src=['"]([^'"]+)['"]/)
|
||||
if (!imgSrc) {
|
||||
return
|
||||
}
|
||||
// 发到服务器上并转为base64
|
||||
const res = await getImgData({ url: imgSrc[1] })
|
||||
if (res && res.data) {
|
||||
replaces.push({ src: data[i], tar: `<img src='${res.data.imgData}' />` })
|
||||
}
|
||||
}
|
||||
|
||||
editor.dangerouslyInsertHtml(htmlData);
|
||||
event.preventDefault()
|
||||
callback(false)
|
||||
return replaces
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -125,16 +160,16 @@ const extractImageDataFromRtf = (rtfData) => {
|
|||
const result = ref([])
|
||||
if (images) {
|
||||
for (const image of images) {
|
||||
const imageType = ref(false)
|
||||
let imageType = ''
|
||||
if (image.includes('\\pngblip')) {
|
||||
imageType.value = 'image/png'
|
||||
imageType = 'image/png'
|
||||
} else if (image.includes('\\jpegblip')) {
|
||||
imageType.value = 'image/jpeg'
|
||||
imageType = 'image/jpeg'
|
||||
}
|
||||
if (imageType.value) {
|
||||
if (imageType) {
|
||||
result.value.push({
|
||||
hex: image.replace(regexPictureHeader, '').replace(/[^\da-fA-F]/g, ''),
|
||||
type: imageType.value
|
||||
type: imageType
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -439,7 +439,7 @@ watch(() => tableData.value, () => {
|
|||
})
|
||||
|
||||
// ----- 查询 -----
|
||||
const getTableData = async valid => {
|
||||
const getTableData = async () => {
|
||||
const res = await getArticleList({ page: page.value, pageSize: pageSize.value, ...searchInfo.value })
|
||||
if (res.code === 0) {
|
||||
tableData.value = res.data.list
|
||||
|
|
|
|||
Loading…
Reference in New Issue