''
liukangdong
2024-05-22 6cfaee4a1edbe47f7c9da41905e8d877ed590dc4
admin/src/components/common/RichEditor.vue
@@ -1,158 +1,162 @@
<template>
  <div style="border: 1px solid #ccc;">
  <div class="wang_editor">
    <Toolbar
      style="border-bottom: 1px solid #ccc"
      :editor="editor"
      :defaultConfig="toolbarConfig"
      :default-config="toolbarConfig"
      :mode="mode"
    />
    <Editor
      style="height: 300px; overflow-y: hidden;"
      :value="content.content"
      v-model="html"
      style="min-height: 200px"
      :default-config="editorConfig"
      :mode="mode"
      :defaultConfig="editorConfig"
      @onCreated="onCreated"
      @onChange="onChange"
      @input="html=$event"
    />
  </div>
</template>
<script>
import { Editor, Toolbar } from '@wangeditor/editor-for-vue'
import '@wangeditor/editor/dist/css/style.css'
import axios from 'axios'
import { uploadFile } from '@/api'
const uploadConfig = {
  action: uploadFile, // 必填参数 图片上传地址
  methods: 'POST', // 必填参数 图片上传方式
  token: '', // 可选参数 如果需要token验证,假设你的token有存放在sessionStorage
  name: 'file', // 必填参数 文件的参数名
  size: 500, // 可选参数   图片大小,单位为Kb, 1M = 1024Kb
  accept: 'image/png, image/gif, image/jpeg, image/bmp, image/x-icon' // 可选 可上传的图片格式
}
export default {
  name: 'RichEditor',
  components: { Editor, Toolbar },
  components: {
    Editor,
    Toolbar
  },
  props: {
    content: {
      type: Object,
      default: () => {}
    info: {
      type: String,
      default: ''
    },
    default: {
      type: String,
      default: ''
    },
    placeholder: {
      type: String,
      default: '请输入内容...'
    }
  },
  data() {
  data () {
    return {
      editor: null,
      html: '<p><br></p>',
      toolbarConfig: {
        toolbarKeys: [
          "headerSelect",
          "blockquote",
          "|",
          "bold",
          "underline",
          "italic",
          {
              "key": "group-more-style",
              "title": "更多",
              "iconSvg": "<svg viewBox=\"0 0 1024 1024\"><path d=\"M204.8 505.6m-76.8 0a76.8 76.8 0 1 0 153.6 0 76.8 76.8 0 1 0-153.6 0Z\"></path><path d=\"M505.6 505.6m-76.8 0a76.8 76.8 0 1 0 153.6 0 76.8 76.8 0 1 0-153.6 0Z\"></path><path d=\"M806.4 505.6m-76.8 0a76.8 76.8 0 1 0 153.6 0 76.8 76.8 0 1 0-153.6 0Z\"></path></svg>",
              "menuKeys": [
                  "through",
                  "code",
                  "sup",
                  "sub",
                  "clearStyle"
              ]
          },
          "color",
          "bgColor",
          "|",
          "fontSize",
          "fontFamily",
          "lineHeight",
          "|",
          "bulletedList",
          "numberedList",
          "todo",
          {
              "key": "group-justify",
              "title": "对齐",
              "iconSvg": "<svg viewBox=\"0 0 1024 1024\"><path d=\"M768 793.6v102.4H51.2v-102.4h716.8z m204.8-230.4v102.4H51.2v-102.4h921.6z m-204.8-230.4v102.4H51.2v-102.4h716.8zM972.8 102.4v102.4H51.2V102.4h921.6z\"></path></svg>",
              "menuKeys": [
                  "justifyLeft",
                  "justifyRight",
                  "justifyCenter",
                  "justifyJustify"
              ]
          },
          {
              "key": "group-indent",
              "title": "缩进",
              "iconSvg": "<svg viewBox=\"0 0 1024 1024\"><path d=\"M0 64h1024v128H0z m384 192h640v128H384z m0 192h640v128H384z m0 192h640v128H384zM0 832h1024v128H0z m0-128V320l256 192z\"></path></svg>",
              "menuKeys": [
                  "indent",
                  "delIndent"
              ]
          },
          // "|",
          "emotion",
          "insertLink",
          {
              "key": "group-image",
              "title": "图片",
              "iconSvg": "<svg viewBox=\"0 0 1024 1024\"><path d=\"M959.877 128l0.123 0.123v767.775l-0.123 0.122H64.102l-0.122-0.122V128.123l0.122-0.123h895.775zM960 64H64C28.795 64 0 92.795 0 128v768c0 35.205 28.795 64 64 64h896c35.205 0 64-28.795 64-64V128c0-35.205-28.795-64-64-64zM832 288.01c0 53.023-42.988 96.01-96.01 96.01s-96.01-42.987-96.01-96.01S682.967 192 735.99 192 832 234.988 832 288.01zM896 832H128V704l224.01-384 256 320h64l224.01-192z\"></path></svg>",
              "menuKeys": [
                  "insertImage",
                  "uploadImage"
              ]
          },
          "insertTable",
          "codeBlock",
          "divider",
          "|",
          "undo",
          "redo",
          "|",
          "fullScreen"
        ]
      },
      toolbarConfig: {},
      editorConfig: {
        placeholder: '请输入内容...',
        placeholder: this.placeholder,
        MENU_CONF: {
          uploadImage: {
            // server: '/api/upload',
            name: 'file',
            server: process.env.VUE_APP_API_PREFIX + '/visitsAdmin/cloudService/public/uploadLocal',
            html: this.info,
            server: uploadFile,
            // 单个文件的最大体积限制,默认为 2M
            maxFileSize: 5 * 1024 * 1024, // 1M
            // 选择文件时的类型限制,默认为 ['image/*'] 。如不想限制,则设置为 []
            allowedFileTypes: ['image/*'],
            // 自定义上传参数,例如传递验证的 token 等。参数会被添加到 formData 中,一起上传到服务端
            meta: {
              folder: 'shop'
              token: '',
              otherKey: '',
              folder: 'COURSE_IMG'
            },
            onBeforeUpload(file) {    // JS 语法
              // file 选中的文件,格式如 { key: file }
              // debugger
              return file
            // 自定义增加 http  header
            headers: {
              token: localStorage.getItem('token') || ''
              // Accept: 'text/x-json',
              // otherKey: 'xxx'
            },
            onSuccess(file, res) {
                console.log(`${file.name} 上传成功`, res)
            // 跨域是否传递 cookie ,默认为 false
            withCredentials: true,
            // 超时时间,默认为 10 秒
            timeout: 5 * 1000, // 5 秒
            onSuccess (file, res) { // TS 语法
              // onSuccess(file, res) {          // JS 语法
              console.log(`${file.name} 上传成功`, res)
            },
            onError(file, err, res) {
              console.log(`${file.name} 上传出错`, err, res)
            },
          },
            customUpload (file, insertFn) { // TS 语法
              // file 即选中的文件
              // 自己实现上传,并得到图片 url alt href
              // var form = new FormData()
              // form.append('image', file)
              // form.append('folder', 'COURSE_IMG')
              var formData = new FormData()
              formData.append(file.name, file)
              formData.append('image', file)
              formData.append('folder', 'member')
              // formData.append('type', '')
              var xhr = new XMLHttpRequest()
              xhr.open(uploadConfig.methods, uploadConfig.action, true)
              // 上传数据成功,会触发
              xhr.send(formData)
              xhr.onreadystatechange = () => {
                // 若响应完成且请求成功
                if (xhr.readyState === 4 && xhr.status === 200) {
                  const result = JSON.parse(xhr.responseText)
                  console.log('result', result);
                  insertFn(result.data.url, '', result.data.url)
                }
              }
            },
            customInsert (res, insertFn) { // TS 语法
              // customInsert(res, insertFn) {                  // JS 语法
              // res 即服务端的返回结果
              console.log(res.data.url)
              // 从 res 中找到 url alt href ,然后插入图片
              insertFn(res.url)
            }
          }
        }
      },
      mode: 'default', // or 'simple'
      mode: 'default' // or 'simple'
    }
  },
  beforeDestroy() {
  emits: ['input'],
  computed: {
    html: {
      get () {
        return this.info || ''
      },
      set (newValue) {
        this.$emit('input', newValue)
      }
    }
  },
  mounted () {
    setTimeout(() => {
      this.info = this.default
    }, 1200)
  },
  beforeDestroy () {
    const editor = this.editor
    if (editor == null) return
    editor.destroy() // 组件销毁时,及时销毁编辑器
  },
  methods: {
    onCreated (editor) {
      this.editor = Object.seal(editor)
      this.editor = Object.seal(editor) // 一定要用 Object.seal() ,否则会报错
      this.$emit('input', '123123')
    },
    onChange (editor) {
      console.log(this.html);
      // debugger
      if (!this.html||this.content.content==this.html) {
        return
      }
      this.$emit('edit', this.html)
    },
  },
    test () {
      console.log(this.info)
    }
  }
}
</script>
<style src="@wangeditor/editor/dist/css/style.css"></style>
<style lang="scss" scoped>
.wang_editor {
  border: 1px solid;
}
</style>