首页 > 其他分享 >vue-code-diff 实现版本对比,带内容覆盖(仅组件,待完善内容解析)

vue-code-diff 实现版本对比,带内容覆盖(仅组件,待完善内容解析)

时间:2022-10-21 16:26:53浏览次数:62  
标签:code version ruleOptions label vue let key diff type

<template>
  <div class="version-diff-content">
    <div class="version-diff-top">
      <div>
        <el-select v-model="versionDiffSelected.selectOne.version" placeholder="" size="mini">
          <el-option 
          v-for="item in tagList" 
          :key="item.commitId" 
          :value="item.commitId" 
          :label="item.msg" />
        </el-select>
      </div>
      <div>
        <el-button type="primary" size="mini" @click="handleContrast">对比</el-button>
      </div>
      <div>
        <el-select 
        :disabled="!!replaceData"
        v-model="versionDiffSelected.selectTwo.version" 
        placeholder="" 
        size="mini">
          <el-option 
          v-for="item in tagList" 
          :key="item.commitId" 
          :value="item.commitId" 
          :label="item.msg" />
        </el-select>
      </div>
    </div>

    <div v-loading="diffLoading" :element-loading-text="diffLoadingText">
      <el-scrollbar class="version-diff-bottom"> 
        <div 
        v-if=" versionDiffSelected.selectOne.json != versionDiffSelected.selectTwo.json "
        class="version-diff-bottom-item"
        >
          <code-diff 
          class="center"
          :renderNothingWhenEmpty="true"
          :old-string="versionDiffSelected.selectOne.json" 
          :new-string="versionDiffSelected.selectTwo.json" 
          :context="10"
          outputFormat="side-by-side" />


          
          <div id="diffView" style="margin-top:10px"></div>
        </div>

        <div 
        class="version-diff-bottom-item flex-center"
        v-if=" 
        versionDiffSelected.selectOne.json !== undefined && 
        versionDiffSelected.selectTwo.json !== undefined && 
        versionDiffSelected.selectOne.json == versionDiffSelected.selectTwo.json ">
          规则无变化
        </div>
        
      </el-scrollbar>
    </div>
  </div>
</template>

<script>
import { readAssetTree } from '@/api/rule/asset'
import { getVersionDifference } from "@/api/rule/project"
import { getRuleFileString } from "@/utils/getRuleString"
import CodeDiff from 'vue-code-diff'
export default {
  components: { CodeDiff },
  props: {
    // 版本列表
    tagList: {
      type: Array,
      default: (() => {return []})
    },
    // 对比的数据,用于请求接口获取参数
    objectForm: {
      type: Object,
    },
    // 当前规则数据,有则传递数据,后面不用重新请求
    momentRule: {
      type: Object,
      default: (() => {return {}})
    },
    // 被替换的数据(需要做当前内容的替换时传递)
    replaceData: {
      type: Object,
      default: null
    }
  },
  data() {
    return {
      versionDiffDialog: false,
      diffLoading: false,
      diffLoadingText: "规则对比中,请稍后......",
      versionDiffData: "",
      versionDiffSelected: {
        selectOne: {
          version: "",
          json: undefined,
          rule: ""
        },
        selectTwo: {
          version: "",
          json: undefined,
          rule: ""
        },
      },
    }
  },

  watch: {
    versionDiffDialogProp: {
      handler(n) {
        this.versionDiffDialog = n
      }
    }
  },

  methods: {
    // 执行版本对比
    handleContrast() {
      console.log("对比的版本", this.versionDiffSelected)
      if( this.versionDiffSelected.selectOne.version == this.versionDiffSelected.selectTwo.version ){
        this.$message.warning("相同的版本")
        return
      }

      this.diffLoading = true
      let { type, parentPath, aliasName, projectName, spaceName } = this.objectForm

      const diffPromiseList = [];                     // 这里存放异步操作的 Promise
      const output = (version, key) => new Promise((resolve) => {
        if( version ){
          // 获取历史版本
          let data = { commitId: version, projectName, spaceName, type, parentPath, aliasName  }
          getVersionDifference(data).then((response) => {
            console.log("历史版本数据", response)
            resolve({responseData: response, key: key})
          })
        }else{
          // 获取当前规则内容
          if( this.replaceData ){
            resolve(
              {
                responseData: {
                  code: 200,
                  data: this.momentRule
                }, 
                key: key
              }
            )
          }else{
            readAssetTree({ projectName, spaceName, type, parentPath, aliasName }).then(response => {
              console.log("规则数据", response)
              resolve({responseData: response, key: key})
            })
          }
          
        }

      });

      // 生成全部的异步操作
      for( let key in this.versionDiffSelected ) {
        if( key == "selectOne" || key == "selectTwo" ){
          let version = this.versionDiffSelected[key].version
          diffPromiseList.push(output(version, key));
        }
        
      }

      // 异步操作完成之后,输出resolve的数据
      Promise.all(diffPromiseList).then((allResponse) => {
        console.log("版本对比获取对比数据", allResponse)
        allResponse.forEach((response) => {
          let ruleData

          if (response.responseData.code == 200) {
            ruleData = response.responseData.data.content? JSON.parse(response.responseData.data.content): [] 
            
            this.versionDiffSelected[response.key].rule = ruleData

            // 获取规则自然语言
            this.versionDiffSelected[response.key].json = getRuleFileString(ruleData)
          }
          
          this.diffLoading = false
        })

        // 获取对比元素,添加覆盖按钮
        if( this.replaceData ){
          setTimeout(() => {
            this.getDiffDome()
          }, 100)
        }
        
      });
    },

    getDiffDome() {
      let diffBox = document.getElementsByClassName("d2h-diff-tbody")

      let ruleOptionsObj = {
        left: {
          actionType: "",
          map: [
            {
              type: "if",
              label: "如果"
            },
            {
              type: "do",
              label: "那么"
            },
            {
              type: "else",
              label: "否则"
            }
          ],
          if: {
            label: "如果",
            children: []
          },
          do: {
            label: "那么",
            children: []
          },
          else: {
            label: "否则",
            children: []
          },

          childrenMap: {}
        },
        right: {
          actionType: "",
          map: [
            {
              type: "if",
              label: "如果"
            },
            {
              type: "do",
              label: "那么"
            },
            {
              type: "else",
              label: "否则"
            }
          ],
          if: {
            label: "如果",
            children: []
          },
          do: {
            label: "那么",
            children: []
          },
          else: {
            label: "否则",
            children: []
          },

          childrenMap: {}
        }
        
      }
      
      diffBox.forEach((parentDome, parentIndex) => {
        let ruleOptions
        parentDome.children.forEach((childrenItem, row) => {
          if( parentIndex == 0 ){
            ruleOptions = ruleOptionsObj.left
          }else{
            ruleOptions = ruleOptionsObj.right
          }

          // 获取规则对应数据
          ruleOptions.map.forEach((ruleOptionItem) => {
            if( childrenItem.outerText.replace(/\s*/g,"") == ruleOptionItem.label ){
              ruleOptions.actionType = ruleOptionItem.type
            }
          })

          // 筛选去除类型的标题
          if( ruleOptions.map.filter(v => v.label == childrenItem.outerText).length == 0 ){

            let childrenData = {
              index: row,
              hasData: !!childrenItem.outerText.replace(/\s*/g,""),
              childrenItem
            }

            if( 
            ruleOptions.actionType && 
            childrenItem && 
            childrenItem.outerText.replace(/\s*/g,"") != ruleOptions[ruleOptions.actionType].label){
              ruleOptions[ruleOptions.actionType].children.push(childrenData)

              ruleOptions.childrenMap[row] = {
                type: ruleOptions.actionType,
                index: ruleOptions[ruleOptions.actionType].children.length - 1,
                hasData: !!childrenItem.outerText.replace(/\s*/g,"")
              }
            }
            
          }
          
          

          if( parentIndex == 0 && (childrenItem.outerText[0] == "+" || childrenItem.outerText[0] == "-") ){
            let btn = document.createElement('div')
            btn.innerHTML = "=>"
            btn.style.cursor="pointer"
            childrenItem.appendChild(btn)

            btn.addEventListener('click', () => {
              this.overDiff( childrenItem, row, parentDome, parentIndex, ruleOptionsObj )
            })
          }
          
        })
      })
      
      console.log(5346643, ruleOptionsObj)
    },

    // 规则不同覆盖
    overDiff( childrenItem, row, parentDome, parentIndex, ruleOptionsObj ){
      console.log("覆盖", childrenItem, row, parentDome, parentIndex, ruleOptionsObj)

      // 获取选择的覆盖规则
      let selectRuleChildren = ruleOptionsObj.left.childrenMap[row]

      let selectRuleType = selectRuleChildren.type
      let selectRuleTypeIndex = selectRuleChildren.index

      let selectTypeInfo = ruleOptionsObj.left[selectRuleType]
      
      // 获取选择的覆盖规则的index
      let selectRuleIndex = -1
      selectTypeInfo.children.forEach((v, i) => {
        if( i <= selectRuleTypeIndex && v.hasData ){
          selectRuleIndex ++
        }
      })
      let selectRule = this.versionDiffSelected.selectOne.rule[selectRuleChildren.type][selectRuleIndex]
      console.log("覆盖选择规则", selectRule)

      // 获取被覆盖的规则
      // let selectRuleType = selectRuleChildren.type
      // let selectRuleTypeIndex = selectRuleChildren.index
      let overTypeInfo = ruleOptionsObj.right[selectRuleType]
      
      // 获取被覆盖规则的当条规则的index
      let overRuleIndex = -1
      overTypeInfo.children.forEach((v, i) => {
        if( i <= selectRuleTypeIndex && v.hasData ){
          overRuleIndex ++
        }
      })
      
      let overRuleDataType = this.versionDiffSelected.selectTwo.rule[selectRuleChildren.type]

      // 根据被覆盖的规则是否有内容,判断有内容做覆盖操作,无内容做插入操作
      if( ruleOptionsObj.right.childrenMap[row].hasData ){
        overRuleDataType.splice( overRuleIndex, 1, selectRule )
      }else{
        overRuleDataType.splice( overRuleIndex + 1, 0, selectRule )
      }
      
      setTimeout(() => {
        this.replaceData[selectRuleChildren.type] = overRuleDataType

        this.$emit("reSetData", this.replaceData)

        this.versionDiffSelected.selectTwo.json = getRuleFileString(this.replaceData)
        // 获取对比元素
        setTimeout(() => {
          this.getDiffDome()
        }, 500)
      }, 100)
      
      

      console.log("获取被覆盖规则的当条规则的index", overRuleIndex, overRuleDataType, this.replaceData)

    },
  }
}
</script>

<style lang="scss" scoped> 
.version-diff-content{
  .version-diff-top{
    width: 100%;
    display: flex;
    justify-content: space-between;
  }
}
::v-deep .version-diff-bottom{
  .el-scrollbar__view{
    height: 460px;
    display: flex;
  }
  .version-diff-bottom-item{
    width: 100%;
    margin-top: 10px;
  }
  // 解决vue-code-diff对不齐和显示下拉标志问题
  .center {
    max-height: 600px;
    overflow-y: auto;
    overflow-x: hidden;
    /* 样式穿透-起始行左右对齐,*/
    .d2h-code-side-line{
      height:15px;
    }
    code.hljs{
      padding: 0;
    }
    
    // 删除行统计显示
    .d2h-code-side-linenumber{
      display: none;
    }
    .d2h-code-side-line{
      padding: unset;
    }
    .d2h-code-line-ctn{
      width: unset;
    }

    // 删除第一行的统计结果
    .d2h-info {
      display: none;
    }
  }
}
</style>

 

标签:code,version,ruleOptions,label,vue,let,key,diff,type
From: https://www.cnblogs.com/yan122/p/16813836.html

相关文章

  • Educational Codeforces Round 138 (Rated for Div. 2) ABC(二分)
    只能说这场的出题人不适合我食用,ABC都读了假题,离谱啊~A.CowardlyRooks题目大意:给定一个棋盘n*n的大小,左下角的顶点在(1,1);给定了棋盘格上的m个棋子坐标。这m个棋子......
  • Chrome 浏览器安装Vue插件方法
    谷歌浏览器扩展程序 首先去github下载vue.zip文件插件 下载地址:https://github.com/vuejs/vue-devtools不要去下载默认分支的 下载后解压验证npm是否安装成......
  • 「题解」Codeforces 1730F Almost Sorted
    给定一个长度为\(n\)的置换\(p\),以及一个正整数\(k\).对于一个置换\(q\),要求对于所有满足\(1\leqi<j\leqn\)的\(i,j\),有以下不等式成立:\[p_{q_i}\leqp_{q_j}+......
  • #yyds干货盘点# LeetCode 腾讯精选练习 50 题:最长回文子串
    题目:给你一个字符串s,找到s中最长的回文子串。 示例1:输入:s="babad"输出:"bab"解释:"aba"同样是符合题意的答案。示例2:输入:s="cbbd"输出:"bb"代码实现:publicclassSo......
  • 面试题vue组件的相关问题
    面试题vue组件的相关问题什么是组件什么是组件:组件(Component)是Vue.js最强大的功能之一。组件可以扩展HTML元素,封装可重用的代码。一个页面可以由多个组件构成,......
  • vue中执行异步函数async和await的用法
    一、async基础用法async函数,会返回一个promise对象,可以用.then调用async函数中return的结果asyncfunctionhelloAsync(){return"返回结果";}con......
  • 只需三步 带你了解 Vue事件总线(EventBus)
    第一步:直接在项目中的 main.js 初始化 EventBus ://main.jsVue.prototype.$EventBus=newVue()第二步:找到两个页面A和B,A向B发送事件<!--A.vue--><templat......
  • Vue深度监听
    1.监听一般写法watch:{ a(newVal,oldVal){ console.log(newVal); }}2.当监听对象属性时watch:{ "obj.name"(newVal,oldVal){ console.log(newVal); }}3.......
  • Vue3 SFC 和 TSX 方式自定义组件实现 v-model
    1v-model1.1理解v-modelv-model是vue3中的一个内置指令,很多表单元素都可以使用这个属性,如input、checkbox等,咱可以在自定义组件中实现v-model。v-model本质上......
  • #yyds干货盘点# LeetCode 腾讯精选练习 50 题:寻找两个正序数组的中位数
    题目:给定两个大小分别为m和n的正序(从小到大)数组 nums1和 nums2。请你找出并返回这两个正序数组的中位数。算法的时间复杂度应该为O(log(m+n))。 示例1:输入:num......