优化富文本编辑器,粘贴其他网站时,通过上传服务器将图片转为base64格式
This commit is contained in:
parent
53c8857e9d
commit
9c40455709
|
|
@ -146,3 +146,15 @@ export const setArticleCategories = (data) => {
|
||||||
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>
|
<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" />
|
<Toolbar :editor="editorRef" :default-config="toolbarConfig" mode="default" />
|
||||||
<Editor v-model="valueHtml" class="overflow-y-hidden mt-0.5" :style="style" :default-config="editorConfig"
|
<Editor v-model="valueHtml" class="overflow-y-hidden mt-0.5" :style="style" :default-config="editorConfig"
|
||||||
mode="default" @onCreated="handleCreated" @onChange="change" @customPaste="customPaste" />
|
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 { Editor, Toolbar } from '@wangeditor/editor-for-vue'
|
||||||
import { ElMessage } from 'element-plus'
|
import { ElMessage } from 'element-plus'
|
||||||
import { getUrl } from '@/utils/image'
|
import { getUrl } from '@/utils/image'
|
||||||
|
import { getImgData } from '@/api/article'
|
||||||
|
|
||||||
|
const loadingShow = ref(false)
|
||||||
const emits = defineEmits(['change', 'update:modelValue'])
|
const emits = defineEmits(['change', 'update:modelValue'])
|
||||||
const change = (editor) => {
|
const change = (editor) => {
|
||||||
emits('change', editor)
|
emits('change', editor)
|
||||||
|
|
@ -74,40 +76,73 @@ const handleCreated = (editor) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
const customPaste = (editor, event, callback) => {
|
const customPaste = (editor, event, callback) => {
|
||||||
|
// 显示蒙版
|
||||||
|
loadingShow.value = true
|
||||||
|
|
||||||
let htmlData = event.clipboardData.getData('text/html') // 获取粘贴的 html
|
let htmlData = event.clipboardData.getData('text/html') // 获取粘贴的 html
|
||||||
// console.log(htmlData)
|
// console.log(htmlData)
|
||||||
let rtfData = event.clipboardData.getData('text/rtf') // 获取粘贴的 html
|
let rtfData = event.clipboardData.getData('text/rtf') // 获取粘贴的 html
|
||||||
// console.log('-------------- rtfData --------------', rtfData)
|
// console.log('-------------- rtfData --------------', rtfData)
|
||||||
|
|
||||||
htmlData = htmlData.replace(/<\/?span[^>]*>/g, '');
|
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"')
|
htmlData = htmlData.replace(/<img/g, '<img referrerpolicy="no-referrer"')
|
||||||
// console.log('111111111111 replace after 1111111111', htmlData)
|
// console.log('111111111111 replace after 1111111111', htmlData)
|
||||||
|
|
||||||
|
// 从html内容中查找粘贴内容中是否有图片元素,并返回img标签的属性src值的集合
|
||||||
|
const imgSrcs = htmlData.match(/<img [^>]*src=['"]([^'"]+)[^>]*>/g);
|
||||||
|
// console.log('imgSrcs', imgSrcs)
|
||||||
if (rtfData !== "") {
|
if (rtfData !== "") {
|
||||||
// 处理 word 内图片
|
// 处理 word 内图片
|
||||||
// 从html内容中查找粘贴内容中是否有图片元素,并返回img标签的属性src值的集合
|
|
||||||
const imgSrcs = htmlData.match(/<img [^>]*src=['"]([^'"]+)[^>]*>/g);
|
|
||||||
// 如果有
|
|
||||||
if (imgSrcs && Array.isArray(imgSrcs) && imgSrcs.length) {
|
if (imgSrcs && Array.isArray(imgSrcs) && imgSrcs.length) {
|
||||||
// console.log('imgSrcs', imgSrcs)
|
|
||||||
// 从rtf内容中查找图片数据
|
// 从rtf内容中查找图片数据
|
||||||
const rtfImageData = extractImageDataFromRtf(rtfData);
|
const rtfImageData = extractImageDataFromRtf(rtfData);
|
||||||
// console.log('rtfImageData', rtfImageData)
|
|
||||||
// 如果找到
|
// 如果找到
|
||||||
if (rtfImageData.length) {
|
if (rtfImageData.length) {
|
||||||
// TODO:此处可以将图片上传到自己的服务器上,
|
|
||||||
|
|
||||||
// 执行替换:将html内容中的img标签的src替换成ref中的图片数据,如果上面上传了则为图片路径
|
// 执行替换:将html内容中的img标签的src替换成ref中的图片数据,如果上面上传了则为图片路径
|
||||||
htmlData = replaceImageFile(htmlData, imgSrcs, rtfImageData)
|
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);
|
return replaces
|
||||||
event.preventDefault()
|
|
||||||
callback(false)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -125,16 +160,16 @@ const extractImageDataFromRtf = (rtfData) => {
|
||||||
const result = ref([])
|
const result = ref([])
|
||||||
if (images) {
|
if (images) {
|
||||||
for (const image of images) {
|
for (const image of images) {
|
||||||
const imageType = ref(false)
|
let imageType = ''
|
||||||
if (image.includes('\\pngblip')) {
|
if (image.includes('\\pngblip')) {
|
||||||
imageType.value = 'image/png'
|
imageType = 'image/png'
|
||||||
} else if (image.includes('\\jpegblip')) {
|
} else if (image.includes('\\jpegblip')) {
|
||||||
imageType.value = 'image/jpeg'
|
imageType = 'image/jpeg'
|
||||||
}
|
}
|
||||||
if (imageType.value) {
|
if (imageType) {
|
||||||
result.value.push({
|
result.value.push({
|
||||||
hex: image.replace(regexPictureHeader, '').replace(/[^\da-fA-F]/g, ''),
|
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 })
|
const res = await getArticleList({ page: page.value, pageSize: pageSize.value, ...searchInfo.value })
|
||||||
if (res.code === 0) {
|
if (res.code === 0) {
|
||||||
tableData.value = res.data.list
|
tableData.value = res.data.list
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue