yjwang 1 день назад
Родитель
Сommit
c22d0dce06
3 измененных файлов с 172 добавлено и 167 удалено
  1. 167 165
      src/components/Editor/wang.vue
  2. 3 2
      src/utils/safeHtml.js
  3. 2 0
      vue.config.js

+ 167 - 165
src/components/Editor/wang.vue

@@ -1,165 +1,167 @@
-<template>  

-    <div>

-      <div  ref='editor1' class="myedit"></div>

-    </div> 

-</template>  

-  

-<script>  

-  import E from 'wangeditor'

-  import { safeHtml } from '@/utils/safeHtml'

-  import { getToken } from '@/utils/auth'

-  export default {  

-    name: 'editoritem',  

-    data() {  

-      return {

-        uploadUrl:process.env.VUE_APP_BASE_API+"/common/uploadWang",

-        editor: null

-      }  

-    },

-    created() {

-       

-      

-    },

-    beforeDestroy() {

-      // 销毁编辑器

-      if(this.editor!=null){

-        this.editor.destroy()

-        this.editor = null

-      }

-      

-    },

-    methods:{

-      initEditor(){

-        var that=this;

-        if(this.editor==null){

-            //创建编辑器

-            this.editor = new E(that.$refs.editor1 )

-            this.editor.config.uploadImgServer = this.uploadUrl;

-            this.editor.config.uploadImgMaxSize = 2 * 1024 * 1024 // 2M

-            this.editor.config.uploadImgAccept = ['jpg', 'jpeg', 'png', 'gif', 'bmp', 'webp']

-            this.editor.config.uploadFileName = 'fileName'

-            // wangEditor 内置上传需携带鉴权头

-            this.editor.config.uploadImgHeaders = {

-              Authorization: 'Bearer ' + getToken()

-            }

-            this.editor.config.zIndex = 1

-            this.editor.config.menus = [

-              'head',

-              'bold',

-              'fontSize',

-              'fontName',

-              'italic',

-              'underline',

-              'strikeThrough',

-              'indent',

-              'lineHeight',

-              'foreColor',

-              'backColor',

-              'link',

-              'list',

-              'todo',

-              'justify',

-              'quote',

-              'emoticon',

-              'image',

-              // 'video',

-              'table',

-              'code',

-              'splitLine',

-              'undo',

-              'redo',

-          ]

-          this.editor.config.onchange = function (newHtml) {

-            console.log(newHtml)

-            that.$emit("on-text-change", newHtml);

-          }

-          this.editor.config.pasteFilterStyle = true

-          // 粘贴内容经 DOMPurify 消毒,防止 XSS

-          this.editor.config.pasteTextHandle = function (content) {

-            return safeHtml(content)

-          }

-          // 配置触发 onchange 的时间频率,默认为 200ms

-          this.editor.config.onchangeTimeout = 500 // 修改为 500ms

-            this.editor.config.uploadImgHooks = {

-                // 上传图片之前:刷新 Token

-                before: function(xhr) {

-                    that.editor.config.uploadImgHeaders = {

-                      Authorization: 'Bearer ' + getToken()

-                    }

-                    try {

-                      xhr.setRequestHeader('Authorization', 'Bearer ' + getToken())

-                    } catch (e) {

-                      // 部分浏览器对已设置头会抛错,忽略即可

-                    }

-                },

-                // 图片上传并返回了结果,图片插入已成功

-                success: function(xhr) {

-                    //console.log('success', xhr)

-                },

-                // 图片上传并返回了结果,但图片插入时出错了

-                fail: function(xhr, editor, resData) {

-                    console.log('fail', resData)

-                },

-                // 上传图片出错,一般为 http 请求的错误

-                error: function(xhr, editor, resData) {

-                    console.log('error', xhr, resData)

-                },

-                // 上传图片超时

-                timeout: function(xhr) {

-                    //console.log('timeout')

-                },

-                // 图片上传并返回了结果,想要自己把图片插入到编辑器中

-                // 例如服务器端返回的不是 { errno: 0, data: [...] } 这种格式,可使用 customInsert

-                customInsert: function(insertImg, result, editor) {

-                      console.log(result);

-                      // 鉴权失败或无 url 时不插入

-                      if (!result || !result.data || !result.data[0] || !result.data[0].url) {

-                        that.$message && that.$message.error('图片上传失败,请重新登录后重试')

-                        return

-                      }

-                      // 图片上传并返回结果,自定义插入图片的事件(而不是编辑器自动插入图片!!!)

-                      // insertImg 是插入图片的函数,editor 是编辑器对象,result 是服务器端返回的结果

-                      // 举例:假如上传图片成功后,服务器端返回的是 {url:'....'} 这种格式,即可这样插入图片:

-                      var url =   result.data[0].url

-                      console.log(url);

-                      insertImg(url)

-                      // result 必须是一个 JSON 格式字符串!!!否则报错

-                }

-            }

-            this.editor.create()

-        }

-        this.editor.txt.html("");

-      },

-      setText(text){

-        if(this.editor==null){

-          this.initEditor()

-        }

-        if(text==undefined||text==null){

-          this.editor.txt.html("");

-        }

-        else{

-          this.editor.txt.html(text);

-        }

-        

-      },

-     }

-   

-  }  

-</script>  

-  

-<style scoped>

-.toolbar {

-  border: 1px solid #ccc;

-}

-.myedit {

-  min-height: 300px;

-  z-index: 1 !important;

-}

-.w-e-toolbar{

-  z-index: 1 !important;

-}

-.w-e-text-container{

-  z-index: 1 !important;

-}

- 

-</style>

+<template>  
+    <div>
+      <div  ref='editor1' class="myedit"></div>
+    </div> 
+</template>  
+  
+<script>  
+  import E from 'wangeditor'
+  import { getToken } from '@/utils/auth'
+  export default {  
+    name: 'editoritem',  
+    data() {  
+      return {
+        uploadUrl:process.env.VUE_APP_BASE_API+"/common/uploadWang",
+        editor: null
+      }  
+    },
+    created() {
+       
+      
+    },
+    beforeDestroy() {
+      // 销毁编辑器
+      if(this.editor!=null){
+        this.editor.destroy()
+        this.editor = null
+      }
+      
+    },
+    methods:{
+      initEditor(){
+        var that=this;
+        if(this.editor==null){
+            //创建编辑器
+            this.editor = new E(that.$refs.editor1 )
+            this.editor.config.uploadImgServer = this.uploadUrl;
+            this.editor.config.uploadImgMaxSize = 2 * 1024 * 1024 // 2M
+            this.editor.config.uploadImgAccept = ['jpg', 'jpeg', 'png', 'gif', 'bmp', 'webp']
+            this.editor.config.uploadFileName = 'fileName'
+            // wangEditor 内置上传需携带鉴权头
+            this.editor.config.uploadImgHeaders = {
+              Authorization: 'Bearer ' + getToken()
+            }
+            this.editor.config.zIndex = 1
+            this.editor.config.menus = [
+              'head',
+              'bold',
+              'fontSize',
+              'fontName',
+              'italic',
+              'underline',
+              'strikeThrough',
+              'indent',
+              'lineHeight',
+              'foreColor',
+              'backColor',
+              'link',
+              'list',
+              'todo',
+              'justify',
+              'quote',
+              'emoticon',
+              'image',
+              // 'video',
+              'table',
+              'code',
+              'splitLine',
+              'undo',
+              'redo',
+          ]
+          this.editor.config.onchange = function (newHtml) {
+            console.log(newHtml)
+            that.$emit("on-text-change", newHtml);
+          }
+          this.editor.config.pasteFilterStyle = true
+          // 粘贴内容经 DOMPurify 消毒(复用 main.js 挂载的 $safeHtml,避免异步 chunk 二次解析 dompurify)
+          this.editor.config.pasteTextHandle = function (content) {
+            if (typeof that.$safeHtml === 'function') {
+              return that.$safeHtml(content)
+            }
+            return content
+          }
+          // 配置触发 onchange 的时间频率,默认为 200ms
+          this.editor.config.onchangeTimeout = 500 // 修改为 500ms
+            this.editor.config.uploadImgHooks = {
+                // 上传图片之前:刷新 Token
+                before: function(xhr) {
+                    that.editor.config.uploadImgHeaders = {
+                      Authorization: 'Bearer ' + getToken()
+                    }
+                    try {
+                      xhr.setRequestHeader('Authorization', 'Bearer ' + getToken())
+                    } catch (e) {
+                      // 部分浏览器对已设置头会抛错,忽略即可
+                    }
+                },
+                // 图片上传并返回了结果,图片插入已成功
+                success: function(xhr) {
+                    //console.log('success', xhr)
+                },
+                // 图片上传并返回了结果,但图片插入时出错了
+                fail: function(xhr, editor, resData) {
+                    console.log('fail', resData)
+                },
+                // 上传图片出错,一般为 http 请求的错误
+                error: function(xhr, editor, resData) {
+                    console.log('error', xhr, resData)
+                },
+                // 上传图片超时
+                timeout: function(xhr) {
+                    //console.log('timeout')
+                },
+                // 图片上传并返回了结果,想要自己把图片插入到编辑器中
+                // 例如服务器端返回的不是 { errno: 0, data: [...] } 这种格式,可使用 customInsert
+                customInsert: function(insertImg, result, editor) {
+                      console.log(result);
+                      // 鉴权失败或无 url 时不插入
+                      if (!result || !result.data || !result.data[0] || !result.data[0].url) {
+                        that.$message && that.$message.error('图片上传失败,请重新登录后重试')
+                        return
+                      }
+                      // 图片上传并返回结果,自定义插入图片的事件(而不是编辑器自动插入图片!!!)
+                      // insertImg 是插入图片的函数,editor 是编辑器对象,result 是服务器端返回的结果
+                      // 举例:假如上传图片成功后,服务器端返回的是 {url:'....'} 这种格式,即可这样插入图片:
+                      var url =   result.data[0].url
+                      console.log(url);
+                      insertImg(url)
+                      // result 必须是一个 JSON 格式字符串!!!否则报错
+                }
+            }
+            this.editor.create()
+        }
+        this.editor.txt.html("");
+      },
+      setText(text){
+        if(this.editor==null){
+          this.initEditor()
+        }
+        if(text==undefined||text==null){
+          this.editor.txt.html("");
+        }
+        else{
+          this.editor.txt.html(text);
+        }
+        
+      },
+     }
+   
+  }  
+</script>  
+  
+<style scoped>
+.toolbar {
+  border: 1px solid #ccc;
+}
+.myedit {
+  min-height: 300px;
+  z-index: 1 !important;
+}
+.w-e-toolbar{
+  z-index: 1 !important;
+}
+.w-e-text-container{
+  z-index: 1 !important;
+}
+ 
+</style>

+ 3 - 2
src/utils/safeHtml.js

@@ -1,10 +1,11 @@
-import DOMPurify from 'dompurify'
-
 /**
  * 对 HTML 进行消毒,防止 XSS
+ * 使用 CommonJS require,兼容 webpack4 生产构建对 dompurify(exports) 的解析
  * @param {string} dirty 原始 HTML
  * @returns {string} 安全 HTML
  */
+const DOMPurify = require('dompurify')
+
 export function safeHtml(dirty) {
   if (dirty == null || dirty === '') {
     return ''

+ 2 - 0
vue.config.js

@@ -25,6 +25,8 @@ module.exports = {
   lintOnSave: process.env.NODE_ENV === 'development',
   // 如果你不需要生产环境的 source map,可以将其设置为 false 以加速生产环境构建。
   productionSourceMap: false,
+  // dompurify 3.x 使用 package exports,webpack4 需转译,避免生产分包后模块为 undefined
+  transpileDependencies: ['dompurify'],
   // webpack-dev-server 相关配置
   devServer: {
     host: '0.0.0.0',