美文网首页
文本框整体删除及运算校验

文本框整体删除及运算校验

作者: biyu6 | 来源:发表于2021-09-17 17:35 被阅读0次

    需求:
    1.通过点击按钮和运算符将按钮和运算符的文字赋值到input框中,input框不能输入,但是可以删除,以及光标插入。
    2.删除时,运算符直接删,但是文字按钮需要整体删除。(如,在"社保个人"光标在"人"后点击删除时,直接删除"社保个人"这几个字)
    3.保存时需要对input的内容进行校验,判断是否是一个正常的公式。

    截图:


    截屏2021-09-17 下午5.33.14.png
    <!-- 科目公式配置 -->
    <template>
      <div>
        <el-form ref="elForm" size="medium" label-width="100px">
          <el-form-item label="绩效工资=">
            <el-input id="inputRef" type="textarea" placeholder="请选择" :value="salary" @input="inputChange"
              :autosize="{minRows: 4, maxRows: 4}" :style="{width: '100%'}"></el-input>
          </el-form-item>
          <div style="text-align: center;">
            <el-tag v-for="(item,index) in symbolList" :key="index" style="margin: 5px;" @click="add(item)">{{item}}</el-tag>
          </div>
        </el-form>
        <el-tabs type="border-card" style="margin-top: 30px;">
          <el-tab-pane v-for="(item,index) in allData" :key="index"  :label="item.title">
            <el-tag v-for="(item1,idx) in item.list" :key="idx" style="margin: 5px;"@click="add(item1.name)">{{item1.name}}</el-tag>
          </el-tab-pane>
        </el-tabs>
        <div style=" margin-top: 65px; text-align: right;">
           <el-button type="primary" style="margin-left: 10px;" @click.native="submitForm">保 存</el-button>
           <el-button @click.native="closeBtn">取 消</el-button>
         </div>
      </div>
    </template>
    
    <script>
      import { insertInputTxt } from "@/utils/ruoyi";
      export default {
        data() {
          return {
            salary:"",
            symbolList:['+','-','*','/','(',')','%'], //符号数组
            allData:[],
          }
        },
        methods: {
          open(data) {
            var allData = [
              {title:'薪酬数据',list:[{id:'101',name:'基本工资'},{id:'102',name:'岗位工资'}]},
              {title:'考勤数据',list:[{id:'103',name:'应到天数'},{id:'104',name:'实到天数'},{id:'105',name:'请假天数'}]},
              {title:'变动项目',list:[{id:'106',name:'社保个人'},{id:'107',name:'公积金个人'},{id:'108',name:'变动项目合计'}]},
              {title:'自定义科目',list:[{id:'109',name:'自定义科目1'},{id:'110',name:'绩效比例数'}]},
            ]
            var all = {title:'全部',list:[]}
            var li = []
            allData.forEach((item,index) =>{
              li = li.concat(item.list)
            })
            this.$set(all,'list',li)
            allData.unshift(all) //添加all数据到allData数组的第一位
            // console.log(allData)
            this.allData = allData
            if(data){//修改赋值
              this.salary = data
            }else{ //新增清空上次的值,
              this.salary = ''
            }
          },
          add(text){
            this.salary = insertInputTxt('inputRef',text)
          },
          inputChange(val){
            //1.只允许按钮插入,不允许手动输入,允许手动删除
            if(this.salary.length > val.length){
              this.salary = val
            }
            //2.删除时获取光标前后的文字
            var elInput = document.getElementById('inputRef');
            var startPos = elInput.selectionStart;
            var endPos = elInput.selectionEnd;
            if (startPos === undefined || endPos === undefined) return
            var txt = elInput.value;
            var q = txt.substring(0, startPos) //光标前面的文字
            var h = txt.substring(endPos) //光标后面的文字
            // console.log( "光标前面的文字:" + q)
            //3.删除的逻辑处理:获取光标前的最后一项文字(不算运算符)
           var arr = q.split(/[\+\-\*\/\(\)\%]/).filter(Boolean) //按字符集分割字符串,然后去掉空的元素
           var lastStr = arr.pop() //删除数组的最后一项,返回的是数组的最后一项
           // console.log("最后一项:" + lastStr)
           if(lastStr){
             //判断光标前的最后一项文字是否是完整的科目(在全部数据中存在)
             var qbData = this.allData[0].list
             var isWZ = false //是否完整科目
             qbData.forEach(item =>{
               if(item.name === lastStr){
                 isWZ = true //是完整科目
               }
             })
             if(!isWZ){ //如果不是完整科目,就在光标前的文字中删除该不完整的科目
               q = q.substr(0, q.length - lastStr.length); //在q中删除lastStr
             }
             //如果是完整科目,那就意味着光标删除的只是一个运算符,不用做额外处理
             this.salary = q + h //拼接光标前后字段即可
             setTimeout(() => { //删除文字后,让光标定位到删除的地方,需要加个延时,不然代码会失效
               elInput.focus()
               elInput.selectionStart = elInput.selectionEnd = q.length
             }, 50); //延时尽量小,不然容易误删最后面的文字
           }
          },
          checkFormulaText(){//分割字符串
            var resultStr = this.salary
            var errorMsg = ""
            //拦截1:判断公式中 基本工资岗位工资 中间没有运算符
            var arr = resultStr.split(/[\+\-\*\/\(\)\%]/).filter(Boolean) //按字符集分割字符串,然后去掉空的元素
            var qbData = this.allData[0].list
            var qbList = []
            qbData.forEach(item =>{
              qbList.push(item.name)
            })
            var isSuccess = true
            arr.forEach(name =>{
              if(!qbList.includes(name)){ //数组中没有这条数据
                errorMsg = "公式配置错误,请检查:" + name
                isSuccess = false
              }
            })
            //拦截2:公式中有以下错误的运算符
            var errorList = [
              "++","+-","+*","+/","+%",
              "-+","--","-*","-/","-%",
              "*+","*-","**","*/","*%",
              "/+","/-","/*","//","/%",
              "%+","%-","%*","%/","%%",
              "(+","(-","(*","(/","(%",
              "+)","-)","*)","/)","%)",
              "()",")("
            ]
            errorList.forEach(item =>{
              if(resultStr.indexOf(item) != -1){ //字符串包含
                errorMsg = "公式配置错误,请检查:" + item
                isSuccess = false
              }
            });
            //拦截3:公式中(的个数与)的个数不相同
            var sub1 = (resultStr.match(/\(/g)||[]).length
            var sub2 = (resultStr.match(/\)/g)||[]).length
            if(sub1 !== sub2){
              errorMsg = "公式配置错误,请检查()是否匹配"
              isSuccess = false
            }
            //拦截4:公式中()的位置是否反了 社保个人)+(岗位工资
            var sub1F = resultStr.indexOf('\(')
            var sub2F = resultStr.indexOf('\)')
            var sub1E = resultStr.lastIndexOf('\(')
            var sub2E = resultStr.lastIndexOf('\)')
            if(sub2F < sub1F || sub2E < sub1E ){ // )首次出现的位置 小于 ( 首次出现的位置; 或者 ) 最后出现的位置 小于 (最后出现的位置
              errorMsg = "公式配置错误,请检查()是否匹配"
              isSuccess = false
            }
            //拦截5: 公式中,公积金个人(自定义科目1)实到天数
            if(sub1F !== 0){ //如果(不是第一位,获取每个(前面的一个字符,看看是不是符号,不是符号,就报错
              var idxList = this.getStrPositions(resultStr,'(')
              var isE = false
              idxList.forEach(item =>{
                var dd = resultStr.substr(item-1,1) //获取(前面一个字符
                if(!this.symbolList.includes(dd)){ //不是符号,报错
                  isE = true
                }
              })
              if(isE){
                errorMsg = "公式配置错误,请检查(运算符"
                isSuccess = false
              }
            }
            if(sub2E !== resultStr.length-1){ //如果)不是最后一位,获取每一个)后面的一个字符,看看是不是符号,不是符号,就报错
              var idxList = this.getStrPositions(resultStr,')')
              var isE = false
              idxList.forEach(item =>{
                var dd = resultStr.substr(item+1,1) //获取)后面的一个字符
                if(!this.symbolList.includes(dd)){ //不是符号,报错
                  isE = true
                }
              })
              if(isE){
                errorMsg ="公式配置错误,请检查)运算符"
                isSuccess = false
              }
            }
            //拦截6:公式的开头和结尾有非法运算符
            if(resultStr.length > 0){
              var firstChart = resultStr.substr(0,1) //第一个字符
              var firstErrorList = ["+","-","*","/","%",")"]
              firstErrorList.forEach(item =>{
                if(firstChart === item){
                  errorMsg = "公式配置错误,开头不能是:" + item
                  isSuccess = false
                }
              });
              var endChart =  resultStr.substr(-1) //最后一个字符
              var endErrorList = ["+","-","*","/","%","("]
              endErrorList.forEach(item =>{
                if(endChart === item){
                  errorMsg = "公式配置错误,结尾不能是:" + item
                  isSuccess = false
                }
              });
            }else{
              errorMsg ="请配置公式"
              isSuccess = false
            }
            if(!isSuccess){
              this.msgError(errorMsg)
            }
            return isSuccess
          },
          getStrPositions(str,subStr){
            var indexs=[];
            var string=str;
            while(true){
                var index=string.lastIndexOf(subStr);
                if(index!=-1){
                    string=string.substr(0,index)+string.substr(index+subStr.length,string.length);
                    indexs.push(index);
    
                }else{
                    break;
                }
            }
            return indexs;
          },
          submitForm() {
            if(this.checkFormulaText()){
              this.$emit('closeConfigFormula',{msg:this.salary}); //通知父组件改变
            }
          },
          closeBtn(){
            this.$emit('closeConfigFormula',{msg:''}); //通知父组件改变
          }
        }
      }
    </script>
    
    
    
    /** input在光标前插入文字
     * id:input绑定的id
     * insertTxt:要插入的文本
     * 返回:插入后的所有文本
     */
    export function insertInputTxt(id,insertTxt) {
        var elInput = document.getElementById(id);
        var startPos = elInput.selectionStart;
        var endPos = elInput.selectionEnd;
        if (startPos === undefined || endPos === undefined) return
        var txt = elInput.value;
        var result = txt.substring(0, startPos) + insertTxt + txt.substring(endPos)
        elInput.value = result;
        elInput.focus();
        elInput.selectionStart = startPos + insertTxt.length;
        elInput.selectionEnd = startPos + insertTxt.length;
        return result;
    }
    
    

    相关文章

      网友评论

          本文标题:文本框整体删除及运算校验

          本文链接:https://www.haomeiwen.com/subject/nghsgltx.html