vue-element-plus-admin 里面wangEditor 上传图片以及从word复制粘贴图文不显示图片问题。

 1、打开前言 | vue-element-plus-admin
 2、找到相关链接

3、拉取代码https://github.com/kailong321200875/vue-element-plus-admin
4、拿到代码找到src->components->Editor.vue模块

Editor.vue模块

<script setup lang="ts">
import { onBeforeUnmount, computed, PropType, unref, nextTick, ref, watch, shallowRef } from 'vue'
import { Editor, Toolbar } from '@wangeditor/editor-for-vue'
import { IDomEditor, IEditorConfig, i18nChangeLanguage } from '@wangeditor/editor'
import { propTypes } from '@/utils/propTypes'
import { isNumber } from '@/utils/is'
import { ElMessage } from 'element-plus'
import { useLocaleStore } from '@/store/modules/locale'
import { upFileData } from '@/api/common'
import type { InsertFnType } from './types'
import {extractImageDataFromRtf, replaceImagesFileSourceWithInlineRepresentation } from './customPasteFile'

const PATH_IMG_URL = import.meta.env.VITE_API_BASE_IMG_PATH

const localeStore = useLocaleStore()

const currentLocale = computed(() => localeStore.getCurrentLocale)

i18nChangeLanguage(unref(currentLocale).lang)

const props = defineProps({
  editorId: propTypes.string.def('wangeEditor-1'),
  height: propTypes.oneOfType([Number, String]).def('500px'),
  editorConfig: {
    type: Object as PropType<IEditorConfig>,
    default: () => undefined
  },
  modelValue: propTypes.string.def('')
})

const emit = defineEmits(['change', 'update:modelValue'])

// 编辑器实例,必须用 shallowRef
const editorRef = shallowRef<IDomEditor>()

const toolbarConfig = reactive({
  excludeKeys: [
    'uploadVideo'
  ]
})

const valueHtml = ref('')

watch(
  () => props.modelValue,
  (val: string) => {
    if (val === unref(valueHtml)) return
    valueHtml.value = val
  },
  {
    immediate: true
  }
)

// 监听
watch(
  () => valueHtml.value,
  (val: string) => {
    emit('update:modelValue', val)
  }
)

const handleCreated = (editor: IDomEditor) => {
  editorRef.value = editor
}
// 编辑器配置
const editorConfig = computed((): IEditorConfig => {
  return Object.assign(
    {
      readOnly: false,
      customAlert: (s: string, t: string) => {
        switch (t) {
          case 'success':
            ElMessage.success(s)
            break
          case 'info':
            ElMessage.info(s)
            break
          case 'warning':
            ElMessage.warning(s)
            break
          case 'error':
            ElMessage.error(s)
            break
          default:
            ElMessage.info(s)
            break
        }
      },
      autoFocus: false,
      scroll: true,
      uploadImgShowBase64: true,
      MENU_CONF: {
        'uploadImage': {
          async customUpload(file: File, insertFn: InsertFnType) {  // TS 语法
            const formData = new FormData()
            formData.append('file', file)
            upFileData(formData).then(res => {
              if (res && res.data) {
                insertFn(PATH_IMG_URL + res.data.fileUrl, res.data.fileName, PATH_IMG_URL + res.data.fileUrl)
              }
            })
          }
        },
      },
    },
    props.editorConfig || {}
  )
})

/**
     * 自定义粘贴。可阻止编辑器的默认粘贴,实现自己的粘贴逻辑。
     * @param editor 
     * @param event 
     * @returns 
     */
const customPaste=(editor: IDomEditor, event): boolean => {
  let html = event?.clipboardData.getData('text/html');

  const rtf = event?.clipboardData.getData('text/rtf');

  // 该条件分支即表示要自定义word粘贴
  if (html && rtf) {
    // 列表缩进会超出边框,直接过滤掉
    html = html.replace(/text\-indent:\-(.*?)pt/gi, '')

    // 从html内容中查找粘贴内容中是否有图片元素,并返回img标签的属性src值的集合
    const imgSrcs = html.match(/<v:imagedata [^>]*src=['"]([^'"]+)[^>]*>/g);
    // 如果有
    if (imgSrcs && Array.isArray(imgSrcs) && imgSrcs.length) {
      // 从rtf内容中查找图片数据
      const rtfImageData = extractImageDataFromRtf(rtf);
      console.log(rtfImageData,'ref')
      // 如果找到
      if (rtfImageData.length) {
        // TODO:此处可以将图片上传到自己的服务器上,
      
      //   // 执行替换:将html内容中的img标签的src替换成ref中的图片数据,如果上面上传了则为图片路径
        html = replaceImagesFileSourceWithInlineRepresentation(html, imgSrcs, rtfImageData)
        editor.dangerouslyInsertHtml(html);
      }
    } else {
       return true;
    }
    // 阻止默认的粘贴行为
    event.preventDefault();
    return false;
  } else {
    return true;
  }
}

const editorStyle = computed(() => {
  return {
    height: isNumber(props.height) ? `${props.height}px` : props.height
  }
})

// 回调函数
const handleChange = (editor: IDomEditor) => {
  emit('change', editor)
}

// 组件销毁时,及时销毁编辑器
onBeforeUnmount(() => {
  const editor = unref(editorRef.value)

  // 销毁,并移除 editor
  editor?.destroy()
})

const getEditorRef = async (): Promise<IDomEditor> => {
  await nextTick()
  return unref(editorRef.value) as IDomEditor
}

defineExpose({
  getEditorRef
})
</script>

<template>
  <div class="border-1 border-solid border-[var(--el-border-color)] z-10">
    <!-- 工具栏 -->
    <Toolbar :editor="editorRef" :editorId="editorId" :defaultConfig="toolbarConfig"
      class="border-0 b-b-1 border-solid border-[var(--el-border-color)]" />
    <!-- 编辑器 -->
    <Editor v-model="valueHtml" :editorId="editorId" :defaultConfig="editorConfig" :style="editorStyle"
      @on-change="handleChange" @on-created="handleCreated" @custom-paste="customPaste" />
    <!-- <div class="hideSource" style="margin-top: 10px;width: 100%;">
        <textarea
          v-model="valueHtml"
          style="width: 100%; height: 200px; outline: none"
        ></textarea>
      </div> -->
  </div>
</template>

<style src="@wangeditor/editor/dist/css/style.css"></style>

 问题一:图片上传

修改上传图片自定义功能

后端接口

5、创建customPasteFile.ts模块

/**
 * 从rtf内容中匹配返回图片数据的集合
 * @param rtfData
 * @return Array
 */
export const extractImageDataFromRtf = (rtfData) => {
    if (!rtfData) {
        return [];
    }
    const regexPictureHeader = /{\\pict[\s\S]+?({\\\*\\blipuid\s?[\da-fA-F]+)[\s}]*/
    const regexPicture = new RegExp('(?:(' + regexPictureHeader.source + '))([\\da-fA-F\\s]+)\\}', 'g');
    const images = rtfData.match(regexPicture);
    const result =ref([]) as any;
    if (images) {
        for (const image of images) {
            const imageType =ref(false) as any
            if (image.includes('\\pngblip')) {
                imageType.value = 'image/png';
            } else if (image.includes('\\jpegblip')) {
                imageType.value = 'image/jpeg';
            }
            if (imageType.value) {
                result.value.push({
                    hex: image.replace(regexPictureHeader, '').replace(/[^\da-fA-F]/g, ''),
                    type: imageType.value
                });
            }
        }
    }
    return result.value;
}
/**
 * 将html内容中img标签的属性值替换
 * @param htmlData html内容
 * @param imageSrcs html中img的属性src的值的集合
 * @param imagesHexSources rtf中图片数据的集合,与html内容中的img标签对应
 * @param isBase64Data 是否是Base64的图片数据
 * @return String
 */
export const replaceImagesFileSourceWithInlineRepresentation=(htmlData, imageSrcs, imagesHexSources, isBase64Data =
    true) => {
    if (imageSrcs.length === imagesHexSources.length) {
        for (let i = 0; i < imageSrcs.length; i++) {
            const newSrc = isBase64Data ?
                `<div id="w-e-image-container-1100" class="w-e-image-container"><img src='data:${imagesHexSources[i].type};base64,${_convertHexToBase64(imagesHexSources[i].hex)}'/></div>` :
                imagesHexSources[i];
            htmlData = htmlData.replace(imageSrcs[i], newSrc);
        }
    }
    return htmlData;
}
/**
 * 十六进制转base64
 */
export const _convertHexToBase64=(hexString)=>{
    return btoa(hexString.match(/\w{2}/g).map(char => {
        return String.fromCharCode(parseInt(char, 16));
    }).join(''));
}

6、组件使用

 

问题二:从word复制粘贴图文不显示图片问题

主要修改了参考文章里面部分代码 

1、修改从html内容中查找粘贴内容中是否有图片元素,并返回img标签的属性src值的集合

// 从html内容中查找粘贴内容中是否有图片元素,并返回img标签的属性src值的集合
const imgSrcs = html.match(/<v:imagedata [^>]*src=['"]([^'"]+)[^>]*>/g);

 2、修改将html内容中img标签的属性值替换

 const newSrc = isBase64Data ?
                `<div id="w-e-image-container-1100" class="w-e-image-container"><img src='data:${imagesHexSources[i].type};base64,${_convertHexToBase64(imagesHexSources[i].hex)}'/></div>` :
                imagesHexSources[i];

参考文章
解决wangEditor从word复制粘贴图片,带有页眉页脚的问题_wangeditor复制粘贴-CSDN博客

https://element-plus-admin-doc.cn/components/editor.html

  • 10
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
vue-element-admin显示图片有多种方式。其中一种方式是使用require()来包裹图片的url。以下是几种写法的示例代码: ```html <template> <div> <el-image :src="imageUrl" style="height: 100%" /> <el-image :src="require('@/assets/img.png')" style="height: 100%" /> <img :src="imageUrl" style="height: 100%" /> <img :src="require('@/assets/img.png')" style="height: 100%" /> </div> </template> <script> export default { name: 'TestImage', data() { return { imageUrl: require('@/assets/img.png') } } } </script> ``` 以上代码展示了如何在vue-element-admin中使用require()来显示图片。您可以通过在el-image或img标签的src属性中使用require()来引用图片的url。这样做可以确保图片能够正确加载并显示在页面上。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [vue + element 如何显示本地图片](https://blog.csdn.net/weixin_43851264/article/details/123202455)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] - *2* [vue-element-admin:vue-element-admin](https://download.csdn.net/download/weixin_42120275/18219106)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] - *3* [vue3-element-admin:vue-element-adminvue3版本](https://download.csdn.net/download/weixin_42110533/15640212)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值