Browse Source

公式文本和数组相互转换

gangyj 3 years ago
parent
commit
9efebe634f

+ 12 - 1
src/api/formula/formula.js

@@ -10,4 +10,15 @@ export const getTypeMap = (params) => {
   })
 }
 
-
+export const saveFormula = ({formula,remark,wbsId,elementId}) => {
+  return request({
+    url: '/api/blade-manager/formula/save',
+    method: 'post',
+    data: {
+      formula,
+      remark,
+      wbsId,
+      elementId,
+    }
+  })
+}

+ 24 - 5
src/views/formula/edit.vue

@@ -96,8 +96,8 @@
                 <el-link :underline="false" type="primary" class="mg-r-20" @click="eleAddFormula">元素添加到公式</el-link>
                 <el-link :underline="false" type="primary" class="mg-r-10" @click="addBrackets('(',false)">(</el-link>
                 <el-link :underline="false" type="primary" class="mg-r-10" @click="addBrackets(')',true)">)</el-link>
-                <el-link :underline="false" type="primary" class="mg-r-10" @click="addBrackets('[',false)">【</el-link>
-                <el-link :underline="false" type="primary" class="mg-r-10" @click="addBrackets(']',true)">】</el-link>
+                <!-- <el-link :underline="false" type="primary" class="mg-r-10" @click="addBrackets('[',false)">【</el-link>
+                <el-link :underline="false" type="primary" class="mg-r-10" @click="addBrackets(']',true)">】</el-link> -->
                 <el-link :underline="false" type="primary" @click="addText">输入值</el-link>
               </div>
             </div>
@@ -222,13 +222,14 @@ import { getLazytree,selectByNodeTable,selectFormElements} from "@/api/manager/w
 import { getProjectList } from "@/api/manager/projectinfo";
 import { findContractByProjectId } from "@/api/manager/contractinfo";
 import { getDetail as getEleDeatil } from "@/api/manager/wbsformelement";
-import { getTypeMap } from "@/api/formula/formula";
+import { getTypeMap,saveFormula } from "@/api/formula/formula";
 import {mapGetters} from "vuex";
 
 import formulaItem from "./component/formulaItem"
 import formulaTemplate from "./component/formulaTemplate"
 
 import {formulaArrayToString} from "./formulaArrayToString"
+import {formulaStringToArray} from "./formulaStringToArray"
 export default {
   components: {
     formulaItem,
@@ -316,6 +317,8 @@ export default {
       this.getEleDeatil();
       this.getProjectList();
       this.getTypeMap();
+
+      this.formulaStringToArray();
     },
 
     //懒加载树
@@ -508,7 +511,7 @@ export default {
 
     //在等式模式下点选计算式
     equationSelect(index,indexPath){
-      if(!this.equationSelectEle && this.equationSelectEle.type == 'Element'){
+      if(!this.equationSelectEle ||(this.equationSelectEle && this.equationSelectEle.type != 'Element') ){
         this.$message({
           type: "warning",
           message: "请先选中元素"
@@ -607,7 +610,23 @@ export default {
     //保存公式
     saveFormula(){
       let text = formulaArrayToString(this.processFormula,this.resultFormula);
-      console.log(text);
+      //console.log(text);
+      saveFormula({
+        formula:text,
+        remark:'',
+        wbsId:this.wbsid,
+        elementId:this.eleid
+      }).then(()=>{
+        this.$message({
+          type: "success",
+          message: "保存成功"
+        });
+      })
+    },
+
+    //把公式文本还原数组
+    formulaStringToArray(){
+      formulaStringToArray('');
     },
 
     getNodeDetail(data) {

+ 29 - 10
src/views/formula/formulaArrayToString.js

@@ -1,26 +1,45 @@
 
 
 function transformArguments(children,curEle){
-  let fcReg = /(FC\.\S+\().+(\))/;
+  let fcReg = /(FC\.\S+\()(.+)\)/;
   let fcText = '';
   for (let i = (children.length-1); i >= 0; i--) {
     let ele = children[i];
     //console.log(ele.name)
     let tmpArr = fcReg.exec(ele.template.ft);
     fcText = tmpArr[1] + fcText;//fc.XX( 左括号部分
+    let argList = tmpArr[2].split(",");//括号里面参数部分#1,#2..
+    //console.log(argList)
     //console.log(text)
-    ele.arguments.forEach((arg,index)=>{
-      if(arg.type == 'Element'){
-        if(i != (children.length-1) && curEle.id == arg.id){
-          //不是第一个嵌套的公式,且和当前挂载的是同一个元素
-          //认为这个参数是之前公式计算的结果,不再写入元素
+    argList.forEach((argText,index)=>{
+      if(argText.indexOf('#')>-1){
+        //#动态参数
+        let argIndex = index;
+        for (let j = 0; j < ele.template.args.length; j++) {
+          if(ele.template.args[j].key == argText){
+            //找到相同的#编码
+            argIndex = j;
+            break;
+          }
+        }
+        let arg = ele.arguments[argIndex];
+        
+        if(arg && arg.type == 'Element'){
+          if(i != (children.length-1) && curEle.id == arg.id){
+            //不是第一个嵌套的公式,且和当前挂载的是同一个元素
+            //认为这个参数是之前公式计算的结果,不再写入元素
+          }else{
+            fcText += `E[${arg.tableElementKey}]`;
+          }
         }else{
-          fcText += `E[${arg.tableElementKey}]`;
+          fcText += arg?arg:'""';
         }
+
       }else{
-        fcText += arg;
+        //已有参数
+        fcText += argText?argText:'';
       }
-      if(index != ele.arguments.length-1){
+      if(index != argList.length-1){
         fcText += ',';
       }
     })
@@ -59,6 +78,6 @@ export const formulaArrayToString = (processFormula,resultFormula) => {
     text = resText.replace(`E[${resultFormula[0].tableElementKey}]`,text);
   }
 
-  console.log(text);
+  //console.log(text);
   return text;
 }

+ 136 - 0
src/views/formula/formulaStringToArray.js

@@ -0,0 +1,136 @@
+
+
+
+export const formulaStringToArray = (text) => {
+  
+  text = "FC.pow(FC.pow(E[assa_faf],3),2)+FC.date(E[assa_aff],我的)";
+
+  // 匹配开始的FC.xxx(
+  const startFCRegExp = /^FC\.([a-zA-Z]+)\(/;
+  const startBracketsReg = /^\(/;//左括号
+  const endBracketsReg = /^\)/;//右括号
+  const elementReg = /^E\[(.[^\]]+_.[^\]]+)\]/;//元素
+  const commaReg = /^,/;//逗号
+  const operatorReg = /^\+|-|\*|÷/;//加减乘除
+  const wordReg = /^[\u4e00-\u9fa5\w'"-]+/;//文本
+
+  let resArr = [];//结果数组
+  let strIndex = 0;//位置索引
+  let nuText = text;//未处理的字符串
+  //let startStack = [];//方法体开始部分和左括号 放进来的栈
+  let contentStack = [];//内容放进来的栈
+  let elementArr = [];//存放元素的数组
+
+  while (strIndex < text.length) {
+    nuText = text.substring(strIndex);
+    if(startFCRegExp.test(nuText)){
+      //console.log('匹配FC开始部分')
+      //匹配FC开始部分FC.xxx(
+      let regRes = nuText.match(startFCRegExp);
+      let startText = regRes[0];//匹配到的文本
+
+      //startStack.push(startText);
+      contentStack.push({
+        type:'Function',
+        children:[],
+        tag:startText
+      });
+
+      strIndex += startText.length;//索引移动
+    }else if(endBracketsReg.test(nuText)){
+      //console.log('匹配右括号')
+      //匹配右括号
+      let endBrackets = nuText.match(endBracketsReg)[0];
+
+      let popObj = contentStack.pop();
+      if(contentStack.length > 0){
+        let content =contentStack[contentStack.length - 1];
+        popObj.parent = content;
+        content.children.push(popObj);
+      }else{
+        //匹配完成最顶层的一整个方法体,或括号
+        resArr.push(popObj);
+      }
+
+      strIndex += endBrackets.length;//索引移动
+    }else if(startBracketsReg.test(nuText)){
+      //console.log('匹配左括号')
+      //匹配左括号
+      let startBrackets = nuText.match(startBracketsReg)[0];
+
+      contentStack.push({
+        type:'Brackets',
+        children:[],
+        tag:startBrackets
+      });
+
+      strIndex += startBrackets.length;//索引移动
+    }else if(elementReg.test(nuText)){
+      //console.log('匹配元素')
+      //匹配元素
+      let eleArr = nuText.match(elementReg);
+      let obj = {
+        type:'Element',
+        tableElementKey:eleArr[1],
+        children:[],
+        tag:eleArr[0]
+      }
+      let content =contentStack[contentStack.length - 1];
+      obj.parent = content;
+      content.children.push(obj);
+
+      elementArr.push(obj)
+
+      strIndex += eleArr[0].length;//索引移动
+    }else if(commaReg.test(nuText)){
+      //console.log('匹配逗号')
+      //匹配逗号
+      let comma = nuText.match(commaReg)[0];
+
+      contentStack[contentStack.length - 1].children.push({
+        type:'Comma',
+        tag:comma
+      });
+
+      strIndex += comma.length;//索引移动
+    }else if(operatorReg.test(nuText)){
+      //console.log('匹配加减乘除')
+      //匹配加减乘除
+      let operator = nuText.match(operatorReg)[0];
+      let obj = {
+        type:'Operator',
+        name:operator,
+        tag:operator,
+      }
+      if(contentStack.length > 0){
+        //不然就在方法体或括号里面
+        contentStack[contentStack.length - 1].children.push(obj);
+      }else{
+        //如果没有,那就是在最上层
+        resArr.push(obj);
+      }
+
+      strIndex += operator.length;//索引移动
+    }else if(wordReg.test(nuText)){
+      //匹配文本
+      let word = nuText.match(wordReg)[0];
+      console.log('匹配文本',word)
+
+      contentStack[contentStack.length - 1].children.push({
+        type:'Text',
+        tag:word
+      });
+
+      strIndex += word.length;//索引移动
+    }
+    else{
+      console.log('匹配不到:',nuText)
+      //匹配不到
+      strIndex++
+    }
+  }
+
+  console.log(contentStack)
+  console.log(resArr);
+  return resArr;
+}