vue实现公式编辑器组件

实现方式一

1、效果图

2、实现代码 

组件弹框实现 样式自己调整  公式的数字与汉字元素、符号 建立元素表 动态获取

完整代码(calculate.vue)

<template>
    <div id="formulaPage">
      <div
        ref="formulaView"
        class="formulaView"
        contentEditable="false"
        @click="recordPosition"
        @keyup="editEnter($event)"
        @copy="copy($event)"
        @paste="paste($event)"
      />
      <div class="infomationContent">
        <div class="infomationContent-leftFlexbox">
          <div class="tab">
            <ul style="width: 200px">
              <li
                v-for="(v, i) in Num"
                :key="i"
                class="numberClass"
                :style="{ background: v.backgroundColor }"
                @click="addItem($event, 2, v, false)"
              >
                {
   
   { v.displayValue }}
              </li>
            </ul>
          </div>
          <div class="tab">
            <ul style="width: 500px">
              <li
                v-for="(v, i) in customType"
                :key="i"
                class="typeClass"
                :style="{ background: v.backgroundColor }"
                :class="{ noclick: v.isFlag }"
                @click="addItem($event, 2, v, v.isFlag)"
              >
                {
   
   { v.displayValue }}
              </li>
            </ul>
          </div>
          <div class="tab">
            <ul style="width: 200px">
              <li
                v-for="(v, i) in Symbol"
                :key="i"
                class="symbolClass"
                :style="{ background: v.backgroundColor }"
                @click="addItem($event, 2, v, false)"
              >
                {
   
   { v.displayValue }}
              </li>
            </ul>
          </div>
        </div>
        <div class="infomationContent-rightBtnbox">
          <div class="imgboxinfo" style="margin-bottom: 32px">
            <img src="@/assets/images/rolback.png" alt="" style="width: 40px; height: 40px" @click="deleteHumerText" />
          </div>
          <div class="imgboxinfo">
            <img src="@/assets/images/calSave.png" alt="" style="width: 40px; height: 40px" @click="onSaveformulaEvent" />
          </div>
        </div>
      </div>
   
      <!-- <div class="footerComtent">
        <el-button type="primary" style="width: 200px; height: 30px" @click="onSaveformulaEvent">保存</el-button>
      </div> -->
      <!-- <button @click="parsingFormula('(长+宽+高)*2')">反向解析公式</button> -->
      <!-- <button @click="deleteHumerText()">删除</button> -->
    </div>
  </template>
   
  <script>
   
  export default {
    name: 'FormulaPage',
    props: {
      content: { type: String, default: '' },
      recoverdate: {
        type: Array,
        default: () => []
      },
      domflag: {
        type: String,
        default: ''
      }
    },
    data() {
      return {
        // 权限分类 元素分类不可用集合
        btnsRuleArray: {
          offer: ['thickness', 'nailmouth', 'bellsocket', 'gramweight'], // 报价
          weight: ['thickness', 'unitprice'], // 重量
          areavolume: ['gramweight', 'unitprice'] // 体积、面积、纸宽、纸长
        },
        // 公式字符串
        formulaStr: '',
        // 公式编辑器最后光标位置
        formulaLastRange: null,
        Num: [{
          "displayValue":"1",
          "saveValue":"1"
        },{
          "displayValue":"2",
          "saveValue":"2"
        },{
          "displayValue":"3",
          "saveValue":"3"
        },{
          "displayValue":"4",
          "saveValue":"4"
        },{
          "displayValue":"5",
          "saveValue":"5"
        },{
          "displayValue":"6",
          "saveValue":"6"
        },{
          "displayValue":"7",
          "saveValue":"7"
        },{
          "displayValue":"8",
          "saveValue":"8"
        },{
          "displayValue":"9",
          "saveValue":"9"
        },{
          "displayValue":"0",
          "saveValue":"0"
        },{
          "displayValue":".",
          "saveValue":"."
        }],
        Symbol: [
        {
          "displayValue":"+",
          "saveValue":"+"
        },{
          "displayValue":"-",
          "saveValue":"-"
        },{
          "displayValue":"x",
          "saveValue":"*"
        },{
          "displayValue":"÷",
          "saveValue":"/"
        },{
          "displayValue":"(",
          "saveValue":"("
        },{
          "displayValue":")",
          "saveValue":")"
        },{
          "displayValue":"{",
          "saveValue":"{"
        },{
          "displayValue":"}",
          "saveValue":"}"
        },
        ],
        customType: [{
          "displayValue":"上报产量",
          "saveValue":"report_production"
        },{
          "displayValue":"实际产量",
          "saveValue":"reality_production"
        },{
          "displayValue":"红矿",
          "saveValue":"red_ore"
        },{
          "displayValue":"青堆",
          "saveValue":"black_stack"
        },{
          "displayValue":"红堆",
          "saveValue":"red_stack"
        },{
          "displayValue":"煤存",
          "saveValue":"coal_storage"
        },{
          "displayValue":"槽存",
          "saveValue":"slot_storage"
        },{
          "displayValue":"土耗",
          "saveValue":"soil_used"
        },{
          "displayValue":"土存",
          "saveValue":"soil_stock"
        },{
          "displayValue":"煤耗",
          "saveValue":"coal_used"
        },{
          "displayValue":"产量",
          "saveValue":"production"
        },{
          "displayValue":"用电量",
          "saveValue":"meter_used"
        }],
        backFormulaStrArray: [] // 按键值存储编辑器数据
      }
    },
    created() {
      this.backFormulaStrArray = []
   
      if (this.recoverdate) {
        this.backFormulaStrArray = this.recoverdate
        this.$nextTick(function () {
          this.parsingFormulaCustom(this.recoverdate)
        })
      }
   
    //   this.getList()
    },
    methods: {
      /** 查询所有公式元素 */
      getList() {
        listElement({ pageNum: 1, pageSize: 50 }).then(response => {
          response.rows.forEach(item => {
            item.isFlag = false
            if (this.domflag) {
              const newLegth = this.btnsRuleArray[this.domflag].filter(e => e == item.saveValue)
              if (newLegth.length > 0) {
                item.isFlag = true
              }
            }
          })
          const numberDate = response.rows
            .filter(e => {
              return e.elementType == 'number'
            })
            .sort((a, b) => {
              return a.order - b.order
            })
          const formulaElementDate = response.rows
            .filter(e => {
              return e.elementType == 'formulaElement'
            })
            .sort((a, b) => {
              return a.order - b.order
            })
          const symbolDate = response.rows
            .filter(e => {
              return e.elementType == 'symbol'
            })
            .sort((a, b) => {
              return a.order - b.order
            })
          this.Num = numberDate
          this.Symbol = symbolDate
          this.customType = formulaElementDate
        })
      },
      // 删除操作---从最后删除
      deleteHumerText() {
        if (this.backFormulaStrArray.length > 0) {
          this.backFormulaStrArray.splice(-1, 1)
          while (this.$refs.formulaView.firstChild) {
            this.$refs.formulaView.removeChild(this.$refs.formulaView.firstChild)
          }
          this.backFormulaStrArray.forEach(item => {
            const fd = document.createDocumentFragment()
            const empty = document.createTextNode(' ')
            const formulaEl = document.createTextNode(' ' + item.displayValue + ' ')
            fd.appendChild(empty)
            fd.appendChild(formulaEl)
            fd.appendChild(empty)
            this.$refs.formulaView.appendChild(fd)
   
            // 创建新的光标对象
            var range = document.createRange()
            // 光标对象的范围界定
            range.selectNodeContents(formulaEl)
            // 光标位置定位
            range.setStart(formulaEl, formulaEl.data.length - 1)
   
            // 使光标开始和光标结束重叠
            range.collapse(true)
            // 清除选定对象的所有光标对象
            window.getSelection().removeAllRanges()
            // 插入新的光标对象
            window.getSelection().addRange(range)
   
            // 保存新光标
            this.recordPosition()
          })
        }
        
      },
      // 保存数据 回调父组件
      onSaveformulaEvent() {
        const strParams = this.backFormulaStrArray.map(e => e.saveValue).join('')
        const strParamsValue = this.backFormulaStrArray.map(e => e.displayValue).join('')
   
        const newbackFormulaStrArray = []
        this.backFormulaStrArray.forEach(item => {
          const obj = {
            displayValue: item.displayValue,
            elementType: item.elementType,
            saveValue: item.saveValue
          }
   
          newbackFormulaStrArray.push(obj)
        })
   
        this.parsingFormula('')
        this.$emit('onChangeSuccess', strParams, strParamsValue, newbackFormulaStrArray)
        this.backFormulaStrArray = []
        console.log(strParams)
        console.log(strParamsValue)
        console.log(newbackFormulaStrArray)
        // const ifLegal1 = [...strParamsValue].reduce((a, i) => (i === '(' ? a + 1 : a - 1), 0)
      },
      isValidate(str) {
        const inArr = []
   
        const arr = str.split('')
   
        for (const s of arr) {
          if (s === '{' || s === '[' || s === '(') {
            // 入栈
            inArr.push(s)
          }
          if (s === '}' || s === ']' || s === ')') {
            let temp
            switch (s) {
              case '}':
                temp = '{'
                break
              case ']':
                temp = '['
                break
              case ')':
                temp = '('
                break
            }
            // 出栈
            const out = inArr.pop()
   
            if (temp !== out) {
              return false
            }
          }
        }
        return true
      },
      // 获取公式
      getFormula: function () {
        var nodes = this.$refs.formulaView.childNodes
        var str = ''
        for (let i = 0; i < nodes.length; i++) {
          var el = nodes[i]
          if (el.nodeName == 'SPAN') {
            // console.log(el);
            str += '#' + el.innerHTML.trim() + '#'
          } else {
            // console.log(el.data);
            str += el.data ? el.data.trim() : ''
          }
        }
        // console.log(str);
        this.formulaStr = str
      },
      // 点选时记录光标位置
      recordPosition: function () {
        // 保存最后光标点
        this.formulaLastRange = window.getSelection().getRangeAt(0)
      },
      // 添加字段 type 1 字段  2 公式
      addItem: function (e, type, itemRows, isusable) {
        if (isusable) {
          e.preventDefault()
          return false
        }
        if (this.backFormulaStrArray.length > 0) {
          if (itemRows.elementType == 'formulaElement' || itemRows.elementType == 'symbol') {
            // 检验连续相同两个元素不能重复 符号/元素
            if (this.backFormulaStrArray[this.backFormulaStrArray.length - 1].displayValue == itemRows.displayValue) {
              e.preventDefault()
              return false
            }
            // 检验不同元素连续两个不能是用一个类型
            if (
              this.backFormulaStrArray[this.backFormulaStrArray.length - 1].elementType == 'formulaElement' &&
              itemRows.elementType == 'formulaElement'
            ) {
              e.preventDefault()
              return false
            }
   
            if (
              this.backFormulaStrArray[this.backFormulaStrArray.length - 1].elementType == 'number' &&
              itemRows.elementType == 'formulaElement'
            ) {
              e.preventDefault()
              return false
            }
          }
          if (itemRows.elementType == 'number' && itemRows.saveValue == '.') {
            if (this.backFormulaStrArray[this.backFormulaStrArray.length - 1].displayValue == itemRows.displayValue) {
              e.preventDefault()
              return false
            }
          }
   
          //  this.backFormulaStrArray.forEach(item => {
          //         console.log(item.displayValue,itemRows.displayValue)
          // const reg = RegExp(`(${item.displayValue})\1`, 'g'))
          // console.log(strParamsValue.match(reg))
          // })
        }
   
        this.backFormulaStrArray.push(itemRows)
   
        const isValiStr = this.backFormulaStrArray.map(e => e.displayValue).join('')
        if (!this.isValidate(isValiStr)) {
          this.backFormulaStrArray.splice(-1, 1)
          e.preventDefault()
          return false
        }
   
        // 当前元素所有子节点
        var nodes = this.$refs.formulaView.childNodes
        // 当前子元素偏移量
        var offset = this.formulaLastRange && this.formulaLastRange.startOffset
        // 当前光标后的元素
        var nextEl = this.formulaLastRange && this.formulaLastRange.endContainer
   
        // 创建节点片段
        var fd = document.createDocumentFragment()
        // 创建字段节点  空白间隔节点  公式节点
        var spanEl = document.createElement('span')
        spanEl.setAttribute('contentEditable', false)
        // 标识为新添加元素 用于定位光标
        spanEl.setAttribute('new-el', true)
        spanEl.innerHTML = e.target.innerHTML
        var empty = document.createTextNode(' ')
        var formulaEl = document.createTextNode(' ' + e.target.innerHTML + ' ')
   
        // 区分文本节点替换 还是父节点插入
        if (nextEl && nextEl.className != 'formulaView') {
          // 获取文本节点内容
          var content = nextEl.data
          // 添加前段文本
          fd.appendChild(document.createTextNode(content.substr(0, offset) + ' '))
          fd.appendChild(type == 1 ? spanEl : formulaEl)
          // 添加后段文本
          fd.appendChild(document.createTextNode(' ' + content.substr(offset)))
          // 替换节点
          this.$refs.formulaView.replaceChild(fd, nextEl)
        } else {
          // 添加前段文本
          fd.appendChild(empty)
          fd.appendChild(type == 1 ? spanEl : formulaEl)
          fd.appendChild(empty)
   
          // 如果有偏移元素且不是最后节点  中间插入节点  最后添加节点
          if (nodes.length && nodes.length > offset) {
            this.$refs.formulaView.insertBefore(fd, nextEl && nextEl.className != 'formulaView' ? nextEl : nodes[offset])
          } else {
            this.$refs.formulaView.appendChild(fd)
          }
        }
   
        // 遍历光标偏移数据 删除标志
        var elOffSet = 0
        for (let i = 0; i < nodes.length; i++) {
          const el = nodes[i]
          // console.log(el,el.nodeName == 'SPAN'&&el.getAttribute('new-el'));
          if (el.nodeName == 'SPAN' && el.getAttribute('new-el')) {
            elOffSet = i
            el.removeAttribute('new-el')
          }
        }
   
        // 创建新的光标对象
        var range = document.createRange()
        // 光标对象的范围界定
        range.selectNodeContents(type == 1 ? this.$refs.formulaView : formulaEl)
        // 光标位置定位
        range.setStart(
          type == 1 ? this.$refs.formulaView : formulaEl,
          type == 1 ? elOffSet + 1 : formulaEl.data.length - 1
        )
   
        // 使光标开始和光标结束重叠
        range.collapse(true)
        // 清除选定对象的所有光标对象
        window.getSelection().removeAllRanges()
        // 插入新的光标对象
        window.getSelection().addRange(range)
   
        // 保存新光标
        this.recordPosition()
      },
      // 复制
      copy: function (e) {
        // 选中复制内容
        e.preventDefault()
        //
        var selContent = document.getSelection().toString().split('\n')[0]
        // 替换选中内容
        e.clipboardData.setData('text/plain', selContent)
      },
      // 输入回车
      editEnter: function (e) {
        e.preventDefault()
        if (e.keyCode == 13) {
          // 获取标签内容 并把多个换行替换成1个
          var content = this.$refs.formulaView.innerHTML.replace(/(<div><br><\/div>){2,2}/g, '<div><br></div>')
          // 记录是否第一行回车
          var divCount = this.$refs.formulaView.querySelectorAll('div')
          // var tE = this.$refs.formulaView.querySelect('div');
          // console.log(this.$refs.formulaView.childNodes);
          // console.log(this.$refs.formulaView.querySelectorAll("div"));
          // 获取当前元素内所有子节点
          var childNodes = this.$refs.formulaView.childNodes
          // 记录当前光标子节点位置
          var rangeIndex = 0
          for (let i = 0; i < childNodes.length; i++) {
            var one = childNodes[i]
            if (one.nodeName == 'DIV') {
              rangeIndex = i
            }
          }
          // 如果有替换则进行光标复位
          if (divCount.length >= 1) {
            // 替换回车插入的div标签
            content = content.replace(/<div>|<\/div>/g, function (word) {
              // console.log(word);
              if (word == '<div>') {
                // 如果是第一行不在替换br
                return divCount.length > 1 ? ' ' : ' <br>'
              } else if (word == '</div>') {
                return ' '
              }
            })
            // 更新替换内容,光标复位
            this.$refs.formulaView.innerHTML = content
            // 创建新的光标对象
            var range = document.createRange()
            // 光标对象的范围界定为新建的表情节点
            range.selectNodeContents(this.$refs.formulaView)
            // 光标位置定位在表情节点的最大长度
            range.setStart(this.$refs.formulaView, rangeIndex + (divCount.length > 1 ? 0 : 1))
            // 使光标开始和光标结束重叠
            range.collapse(true)
            // 清除选定对象的所有光标对象
            window.getSelection().removeAllRanges()
            // 插入新的光标对象
            window.getSelection().addRange(range)
          }
        }
        // 保存最后光标点
        this.formulaLastRange = window.getSelection().getRangeAt(0)
      },
      // 获取粘贴事件
      paste: function (e) {
        e.preventDefault()
        // var txt=e.clipboardData.getData();
        // console.log(e, e.clipboardData.getData());
        return ''
      },
      // 公式反向解析
      parsingFormula: function (formulaStr) {
        // 渲染视口
        var view = this.$refs.formulaView
        // 反向解析公式
        var str = formulaStr.replace(/#(.+?)#/g, function (word, $1) {
          // console.log(word,$1);
          return "<span contentEditable='false'>" + $1 + '</span>'
        })
   
        // console.log(str,fd.innerHTML);
        view.innerHTML = str
        // this.$refs.formulaView.appendChild(fd);
   
        // 创建新的光标对象
        var range = document.createRange()
        // 光标对象的范围界定为新建的表情节点
        range.selectNodeContents(view)
        // 光标位置定位在表情节点的最大长度
        range.setStart(view, view.childNodes.length)
   
        // 使光标开始和光标结束重叠
        range.collapse(true)
        // 清除选定对象的所有光标对象
        window.getSelection().removeAllRanges()
        // 插入新的光标对象
        window.getSelection().addRange(range)
   
        // 保存新光标
        this.recordPosition()
      },
      parsingFormulaCustom(arrayDatelist) {
        arrayDatelist.forEach(item => {
          // 当前元素所有子节点
          const nodes = this.$refs.formulaView.childNodes
          // 当前子元素偏移量
          const offset = this.formulaLastRange && this.formulaLastRange.startOffset
          // 当前光标后的元素
          const nextEl = this.formulaLastRange && this.formulaLastRange.endContainer
          const fd = document.createDocumentFragment()
          const empty = document.createTextNode(' ')
          const formulaEl = document.createTextNode(' ' + item.displayValue + ' ')
   
          if (nextEl && nextEl.className != 'formulaView') {
            var content = nextEl.data
            fd.appendChild(document.createTextNode(content.substr(0, offset) + ' '))
            fd.appendChild(formulaEl)
            fd.appendChild(document.createTextNode(' ' + content.substr(offset)))
            this.$refs.formulaView.replaceChild(fd, nextEl)
          } else {
            fd.appendChild(empty)
            fd.appendChild(formulaEl)
            fd.appendChild(empty)
            // 如果有偏移元素且不是最后节点  中间插入节点  最后添加节点
            if (nodes.length && nodes.length > offset) {
              this.$refs.formulaView.insertBefore(
                fd,
                nextEl && nextEl.className != 'formulaView' ? nextEl : nodes[offset]
              )
            } else {
              this.$refs.formulaView.appendChild(fd)
            }
          }
   
          // 创建新的光标对象
          var range = document.createRange()
          // 光标对象的范围界定
          range.selectNodeContents(formulaEl)
          // 光标位置定位
          range.setStart(formulaEl, formulaEl.data.length - 1)
   
          // 使光标开始和光标结束重叠
          range.collapse(true)
          // 清除选定对象的所有光标对象
          window.getSelection().removeAllRanges()
          // 插入新的光标对象
          window.getSelection().addRange(range)
   
          // 保存新光标
          this.recordPosition()
        })
      }
    }
  }
  </script>
   
  <style lang="scss">
  #formulaPage {
    width: 100%;
    height: 100%;
   
    > .formulaView {
      margin-bottom: 20px;
      min-height: 130px;
      width: 100%;
      padding: 5px;
      border: 5px solid rgb(198, 226, 255);
      resize: both;
      overflow: auto;
      line-height: 25px;
      font-size: 20px;
      span {
        user-select: none;
        display: inline-block;
        /* // margin: 0 3px; */
        height: 20px;
        line-height: 20px;
        /* // letter-spacing: 2px; */
        border-radius: 3px;
        white-space: nowrap;
        &:first-child {
          margin-left: 0;
        }
      }
    }
    .footerComtent {
      margin-top: 20px;
      display: flex;
      align-items: center;
      justify-content: center;
    }
    .infomationContent {
      display: flex;
      &-leftFlexbox {
        flex: 1;
        display: flex;
        > .tab {
          flex: 1;
          > ul {
            margin: 0;
            padding: 0;
            display: flex;
            flex-wrap: wrap;
            /* // justify-content: space-between; */
            &:after {
              content: '';
              display: table;
              clear: both;
            }
            > li {
              /* // margin-right: 20px; */
              margin: 5px 10px;
              width: 65px;
              text-align: center;
              float: left;
              padding: 0 10px;
              height: 30px;
              line-height: 30px;
              border-radius: 5px;
              font-weight: bold;
              border: 1px solid #fff;
              list-style-type: none;
              cursor: pointer;
              -moz-user-select: none; /* 火狐 */
              -webkit-user-select: none; /* 谷歌、Safari */
              -ms-user-select: none; /* IE10+ */
              user-select: none;
              user-drag: none;
              box-shadow: 0px 0px 2px 2px rgba(55, 114, 203, 0.2), /*下面深蓝色立体阴影*/ 0px 0px 6px 1px #4379d0,
                /*内部暗色阴影*/ 0 -15px 2px 2px rgba(55, 114, 203, 0.1) inset;
              color: #333333;
            }
   
            > li:hover {
              color: #fff;
              /* // color: #409eff; */
              border-color: #c6e2ff;
              background-color: #ecf5ff;
            }
            > li:active {
              color: #3a8ee6;
              border-color: #3a8ee6;
              outline: none;
            }
            .numberClass {
              width: 40px;
            }
            .typeClass {
              width: 100px
            }
            .symbolClass {
            }
            .noclick {
              cursor: not-allowed !important;
              background: #bcc0c4 !important;
              color: #e4eaf1 !important;
              border: none !important;
            }
          }
        }
      }
      &-rightBtnbox {
        width: 50px;
        padding-top: 10px;
        box-sizing: border-box;
        .imgboxinfo {
          width: 40px;
          height: 40px;
          img {
            cursor: pointer;
          }
        }
      }
    }
  }
  </style>

在父组件中引用即可

实现方式二

 1、效果图

2、实现代码

<!-- 配置计算公式 -->
    <el-dialog title="计算公式配置" :visible.sync="dragOpen" append-to-body :close-on-click-modal="false" width="1050px">
      <el-form label-width="90px" size="medium">
        <el-row>
          <el-col :span="24">
            <el-form-item label="调度指标:">
              <div style="border: 1px solid #c2ddf8;padding: 5px;">

                <draggable class="dragArea list-group" :list="indexLists" :group="{ name: 'people', pull: 'clone', put: false }" animation="300">
                  <el-tag v-for="tag in indexLists" :key="tag.id" effect="dark" class="fomula-tag" style="margin-right: 5px;" type="success">
                    {
   
   {tag.dictLabel}}
                  </el-tag>
                </draggable>
              </div>
            </el-form-item>
          </el-col>
          <el-col :span="24"></el-col>
        </el-row>
        <el-row>
          <el-col :span="24">
            <el-form-item label="运算符号:">
              <div style="border: 1px solid #c2ddf8;padding: 5px;">
                <draggable class="dragArea list-group" :list="operatorOptions" :group="{ name: 'people', pull: 'clone', put: false }" animation="300">
                  <el-tag v-for="tag in operatorOptions" :key="tag.id" effect="dark" class="fomula-tag" @click="tagClick(tag)" style="margin-right: 5px;background-color: #7c9096;border: none;width: 40px;text-align: center">
                    {
   
   {tag.dictLabel}}
                  </el-tag>
                </draggable>
              </div>
            </el-form-item>
          </el-col>
          <el-col :span="24"></el-col>
        </el-row>
        <el-row>
          <el-col :span="24">
            <el-form-item label="算数符号:">
              <div style="border: 1px solid #c2ddf8;padding: 5px;">
                <draggable class="dragArea list-group" :list="nums" :group="{ name: 'people', pull: 'clone', put: false }" animation="300">
                  <el-tag v-for="tag in nums" :key="tag.id" effect="dark" class="fomula-tag" @click="tagClick(tag)" style="margin-right: 5px;background-color: #2bcdff;border: none;width: 40px;text-align: center">
                    {
   
   {tag.dictLabel}}
                  </el-tag>
                </draggable>
              </div>
            </el-form-item>
          </el-col>
          <el-col :span="24"></el-col>
        </el-row>

        <el-row>
          <el-col :span="24">
            <el-form-item label="结果集:">
              <div style="border: 5px solid #c2ddf8;padding: 5px;position: relative;">
                <draggable class="list-group" :list="resultR" group="people" animation="300" style="height:100px;" @change="log">
                  <el-tag v-for="tag in resultR" :key="tag.id" effect="dark" @click="tagClick(tag)" closable @close="handleClose(tag)" style="margin-right: 5px;">
                    {
   
   {tag.dictLabel}}
                  </el-tag>
                </draggable>

                <el-popover placement="left" title="公式:" trigger="hover" :content="previewFormula">
                  <i class="el-icon-view show-fomula" slot="reference"></i>
                </el-popover>
              </div>
            </el-form-item>
          </el-col>
          <el-col :span="24">
            <div class="explain">
              {
   
   {explain}}
            </div>
          </el-col>
        </el-row>
      </el-form>
      <div slot="footer" class="dialog-footer">
        <el-button type="primary" @click="submitDrag" v-if="this.confDisabled">保 存</el-button>
        <el-button @click="cancelDrag">取 消</el-button>
      </div>
    </el-dialog>

js方法

import draggable from 'vuedraggable'

​​​​​​​

watch: {
      'resultR': {
        handler: function () {
          this.refreshFormula();
        }
      },
    },
    methods: {
      log() {
        this.refreshFormula();
      },
      refreshFormula() {
        this.previewFormula = "";
        if (this.resultR !== undefined && this.resultR !== null && this.resultR !== []) {
          for (let i = 0; i < this.resultR.length; i++) {
            this.previewFormula += this.resultR[i].dictLabel;
          }
        }
        console.log("this.previewFormula")
        console.log(this.previewFormula)
      },
handleDrag(item) {
        indexList({ "factory": item.factory }).then(resp => {
          this.indexLists = resp.data;
          this.resultFormula = this.form.indicatorFormula
          if (typeof this.resultFormula !== 'undefined' && this.resultFormula.length > 0) {
            const strArr = this.resultFormula.split(',')
            this.resultR = [];
            for (let i = 0; i < strArr.length; i++) {
              let indexBoolean = false
              for (let j = 0; j < this.indexLists.length; j++) {
                if (this.indexLists[j].dictValue === strArr[i]) {
                  this.resultR.push(this.indexLists[j]);
                  indexBoolean = true
                }
              }
              if (!indexBoolean) {
                let opBoolean = false
                for (let z = 0; z < this.operatorOptions.length; z++) {
                  if (this.operatorOptions[z].dictValue === strArr[i]) {
                    this.resultR.push(this.operatorOptions[z]);
                    opBoolean = true
                  }
                }
                if (!opBoolean) {
                  for (let c = 0; c < this.nums.length; c++) {
                    if (this.nums[c].dictValue === strArr[i]) {
                      this.resultR.push(this.nums[c]);
                    }
                  }
                }
              }

            }
          }
          this.dragOpen = true;
        })
      },
      submitDrag() {
        console.log(this.resultR)
        this.resultFormula = ''
        for (let i = 0; i < this.resultR.length; i++) {
          this.resultFormula = this.resultFormula + this.resultR[i].dictValue + ","
        }
        this.$set(this.form, 'indicatorFormula', this.resultFormula.substring(0, this.resultFormula.length - 1));
        this.dragOpen = false;
        this.resultR = [];
        this.previewFormula = '';
      },
      cancelDrag() {
        this.dragOpen = false;
        this.previewFormula = '';
      },
      tagClick(item) {

      },
      handleClose(item) {
        this.resultR.splice(this.resultR.findIndex(i => i.dictValue === item.dictValue), 1);
      },
}

css代码

<style>
  .mpc-model-dialogue-box .el-dialog {
    width: 29%;
    height: auto;
  }

  .clearfix .el-checkbox__inner {
    margin-bottom: 8px;
  }

  .clearfix .el-checkbox__label {
    width: 100%;
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
    font-size: 16px;
    font-weight: bold;
    color: #409EFF;
  }

  .cardClass .el-card__header {
    padding: 10px 15px 0px;
  }

  .show-fomula {
    position: absolute;
    bottom: 10px;
    right: 10px;
    font-size: 20px;
    color: #237aeb;
  }

  .show-fomula:hover {
    opacity: 0.5;
    transition: 1s;
    transform: scale(1.3);
  }
  

  .fomula-tag:hover {
    opacity: 0.5;
    transform: scale(1.1);
    background-color: #2d52f7 !important;
  }
  

  .edit-fomula:hover {
    opacity: 0.5;
    transition: 1s;
    transform: scale(1.3);
    color: #43bb0b;
  }

  .explain {
    font-weight: bold;
    color: red;
    font-size: 12px;
    float: right;
  }
</style>

猜你喜欢

转载自blog.csdn.net/askuld/article/details/134996471