0


Vue + 富文本编辑器:打印模板设计

前言:

有的项目需要用到打印,如果只有少数的地方需要用到打印,一般只需要固定模板进行打印就行了,但是我们的项目总是与众不同,明明只要固定模板就可以完成需求的,非要添加一个灵活的打印模板,而且还涉及到拖拉填充文本,真是脑细胞不知道死掉了多少! ! ! (= ̄ω ̄=)喵了个咪

需求:

前端页面就是简单的三栏布局,如下图所示,基本就是这种,左边框中就是一个搜索框,加上需要向富文本编辑器中拖拽的内容,中间就是用来编辑模板的富文本编辑器,右边就是各类设置(弄的和真的一样ヽ(ー_ー)ノ,)

最主要的需求就是将左边的字段拖到富文本编辑器中,字段分为基础字段,以及一些算是表格字段,因为项目的打印模板多是用来编辑各类打印单据的,所以说用的到表格比较多,基础字段只能拖拽到富文本的其他区域,不能放在表格中,表格的字段只能放在表格中,不能拖放在其他区域;(注意:这种的项目需求一般需要用到的就是判断拖拽放置的目标标签,如果是这个标签就放置,不是就直接return 提示就行了)

前端布局就不多说了,相信这种布局对于大家来说就都是小菜一碟啦(┓(;´_`)┏)

核心内容:字段拖拽填充富文本编辑

准备:wangeditor v4 的版本(本来准备用v5的版本的,之前写的时候使用v4进行实验的,然后就忘了改了,因为要根据右边的模板设置操作编辑器的编辑部分,比较麻烦,所有就懒得换版本了)

官网:Introduction · wangEditor 用户文档

拖拽字段的渲染:因为富文本编辑器最终得到的是html片段,需要在其他的地方进行使用,前端再次使用的话是无法填充数据的,所以这里就让后端进行填充数据,我们根据后端返回的"字段名称"和"变量名"(后端进行定义,用于匹配填充数据),进行编辑模板,显示是“字段名称”,拖拽填充是"变量名称"(进行隐藏)(^_−)☆。

示例:

还有一点比较重要:拖拽的时候如何区分是“基础字段”还是“表格字段”

这里我用的方法是在获取后端数据的时候,进行数据处理,因为后端给的数据是分开的

例如:[{基础字段},{BOM字段},{工序字段}...]

所以这里在处理数据的时候给‘基础字段’和“其他字段”加了一个标识,用于区分拖拽的是哪一个字段;基础字段添加了一个:source-field,其他字段添加:BOM,最终这个标识渲染到拖拽元素的类名中:class=source-field(具体的上图有)

     async searchList(){
       let data=this.listQuery
      // 模板字段以及模糊查询
        await templateField(data).then(res=>{
         let datas=[]
         for (const key in res.data) {
               datas.push({name:key,every:res.data[key]})
         }
         let m=[]
         datas.forEach(item=>{
           if(item.name.includes('基础信息字段')){
            item.every.forEach((item,index)=>{
               item.class='source-field'  //添加标识
               item.id=index+1
            })
             m.unshift(item)
           }else{
            item.every.forEach((item,index)=>{
               item.class='BOM'     //添加标识
               item.id=index+1
            })
            m.push(item)
           }
        })
         this.fieldList=m
         })
      },

字段渲染过后就是拖拽填充:

常见的拖拽填充有:h5原生拖拽以及sortablejs等

h5拖拽:HTML5 拖放

sortablejs****网址:Sortable.js中文网

最初的时候使用的是sortablejs进行拖放,最后发现拖拽元素的文本无法放置在富文本编辑器中,因为sortablejs的封装和富文本编辑器的封装好像有冲突,所以被迫放弃(死磕好好长时间,最终放弃 (╬◣д◢) ),最终使用的是原生拖拽,原生的拖拽需要在标签上添加:draggable=true,表示是可以进行拖拽的,原生拖拽也是有事件的,这里就不多说,大家可以去看一下官网。

因为要进行拖拽放置文本,我们这里就需要进行处理数据,拼接成后端需要的格式;

基础字段填充:示例:订单号:{$orderNumber}

表格字段填充:示例:{$orderNumber}

这个时候我们用的原生拖拽事件是:拖拽开始的时候:@dragstart="onDragStart"

   onDragStart(event) {
         let flag=event.target.classList.contains('source-field')
         let BOM=event.target.classList.contains('BOM')
         event.dataTransfer.setData("flag",flag)
         event.dataTransfer.setData("BOM",BOM)
         let text=event.target.innerText
         let children= event.target.children[0].innerText
         // 判断数据拼接的方式
         if(flag){
            this.itemText = text+':${'+children+'}';
            this.$refs.editor.getItemText(this.itemText)
         }
         if(BOM) {
           this.itemText = '${'+children+'}';
           this.$refs.editor.getItemText(this.itemText)
         }
      },

我们在 触发事件时判断 触发该事件的元素是什么(e.target)

  1. 判断内容 innerHTML innerText
  2. 标签名 nodeName (判断的时候,标签名需要大写)
  3. 属性 e.target.hasAttribute(“属性名”); 有则是true 无则是false
  4. 类名 e.target.classList.contains(“类名”); 有则是true 无则是false

我们这边判断的类名:因为要根据我之前处理数据添加的标识判断拖拽的是什么字段,决定放置文本是什么样的拼接方式(如上代码)

同时我们又根据判断向event对象中添加一个标识,用于之后判断放置的位置(因为需求表格字段 只能放置表格中,基础字段不能放置表格中)至此拖拽基本完工,后面就是放置;❥(ゝω・✿ฺ)

这里我们需要转到写有富文本编辑的组件中,利用监听监听拖放事件:drgover和drop,drgover要进行阻止默认事件,

 // 监听拖放事件
       this.$refs.editor.addEventListener("dragover", this.onDragOver);
       this.$refs.editor.addEventListener("drop", this.onDrop);
 // 拖放事件
      onDragOver(event) {
         event.preventDefault();
      },
      // 拖放事件
      onDrop(event) {
         event.preventDefault();
         let Td=event.target.tagName
         let flag=event.dataTransfer.getData('flag')
         let BOM=event.dataTransfer.getData('BOM')

         // 判断基础信息字段不能拖动到表格中
         if (flag==='true') {
            if (flag==='true'&&Td=='TD'||flag==='true'&&Td=='TH') {
               this.$message.error('基础信息字段不能拖动到表格中');
             return
            }
             this.fillUp()
         }

        // 判断子列表信息只能放在表格中
         if (BOM==='true') {
            if (BOM==='true'&&Td=='TD') {
              this.fillUp()
              return
            } 
            this.$message.error('子列表字段只能拖拽到表格中,请先创建表格');
         }
      },
      // 富文本编辑器内容填充方法
      fillUp(){
           const selection = window.getSelection();
           let k=selection.anchorNode
           console.log(k.parentNode.tagName);
        //    console.log(k);
           if(!k.tagName&&k.parentNode.tagName!=='P'&&k.parentNode.tagName!=='SPAN'&&k!=='#text'&&k.parentNode.tagName!=='FONT'&&k.parentNode.tagName!=='B'){
                this.$message.error('拖放位置已有内容!');
           };

           if(k.tagName==='P'||k.parentNode.tagName==='P'||k.tagName==='TH'||k.tagName=='TD'||k=='#text'
              ||k.parentNode.tagName=='SPAN'||k.parentNode.tagName==='FONT'||k.parentNode.tagName=='B'){
              const range = selection.getRangeAt(0);
              const text = this.itemText;
              const node = document.createTextNode(text);
              range.deleteContents();
              range.insertNode(node);
            }
      },

这里我们先看上面代码中的【富文本编辑器内容填充的方法】

window.getSelection(),返回的是一个Selection对象,表示用户选择的文本范围或光标的位置,

这里我们用Selection对象属性是:anchorNode(返回选区起点所在的节点)拿到光标所在位置的节点,这里我是用来进行判断拖放位置是有内容的,因为在表格中如果选中原有的文本,在进行拖放表格的样式会发生错乱,所以这里做了一个阻止,只有没有文本的时候才能放置。

放置的时候,我们要用getRangeAt方法返回选区开始的节点,因为通常情况下,用户只能选择一个范围,所以只有一个选区,所以此方法一般为:getRangeAt(0)

返回节点之后就需要拿到原先的拖放的文本this.itemText,根据拖放的文本创建一个节点,然后利用deleteContents()方法从文档树中删除选中范围的所有内容,再将创建的节点插入到之前返回的节点;至此我们就完成拖放填充的富文本编辑中;(๑>ڡ<)☆

window.getSelection()详解:关于window.getSelection_xiao xu的博客-CSDN博客

富文本填充完成,我们这里就需要判断字段拖放的位置了

         event.preventDefault();
         let Td=event.target.tagName
         let flag=event.dataTransfer.getData('flag')
         let BOM=event.dataTransfer.getData('BOM')

         // 判断基础信息字段不能拖动到表格中
         if (flag==='true') {
            if (flag==='true'&&Td=='TD'||flag==='true'&&Td=='TH') {
               this.$message.error('基础信息字段不能拖动到表格中');
             return
            }
             this.fillUp()
         }

        // 判断子列表信息只能放在表格中
         if (BOM==='true') {
            if (BOM==='true'&&Td=='TD') {
              this.fillUp()
              return
            } 
            this.$message.error('子列表字段只能拖拽到表格中,请先创建表格');
         }

上面的代码是拖放事件中的一部分,完整代码在上上面,

先判断基础字段不能放置表格中:

因为表格中我们最终放置的标签是,这里我们需要拿到目标标签的tagName,然后我们在拿到之前用区分基础字段和表格字段的标识,主要就是用标识进行判断的,如果基础字段的标识为真,并且目标标签的tagName为TD,就进行弹窗提示:“基础字段不能拖动到表格中”,并且return出去,否则就是调用富文本填充的方法;

判断表格字段只能放表格中方法就是同上,具体的可以看代码,这里就省略了❥(ゝω・✿ฺ)

最后:至此整个核心描述完了,可能很多的细节没有讲到(比如模板设置控制编辑区域),因为我也是摸着石头过河,死磕了好多天才写出了,如果有不对的地方希望大家能指正,不喜勿喷,谢谢!后面还会写编辑模板的使用,这个又是一大难题(打印的时候) (⌒.−)=★

标签: 前端 javascript html5

本文转载自: https://blog.csdn.net/Xhfc_pf1996/article/details/130383986
版权归原作者 云雨海生 所有, 如有侵权,请联系我们删除。

“Vue + 富文本编辑器:打印模板设计”的评论:

还没有评论