zhongshujie
2024-10-16 218a387c6191311ed29b1aa81612e0aa3b4fa9dc
src/components/matching/matching.vue
@@ -1,41 +1,114 @@
<template>
  <div class="connect" id="connect" ref="connect"  @mousemove="mousemove" @mouseup="(e) => touchend(e)">
    <div class="answer"    >
      <div class="answer-box">
        <div
          class="answer-box-item"
          v-for="(item, index) in leftArr"
          :key="index"
          ref="left"
          @mousedown="(e) => touchstart(e, item, index)"
        >
          {{ item.label.txt }}
  <div class="matching">
    <div
      class="connect"
      id="connect"
      ref="connect"
      @mousemove="mousemove"
      @mouseup="(e) => touchend(e)"
    >
      <div class="answer">
        <div class="answer-box">
          <div
            class="answer-box-item"
            v-for="(item, index) in leftArr"
            :key="index"
            ref="left"
            @mousedown="(e) => touchstart(e, item, index)"
            :style="{ backgroundColor: primaryColor,border:'1px solid' + bordercolor }"
            v-html="item.label.txt"
          ></div>
        </div>
        <div class="answer-box">
          <div
            class="answer-box-item tl-le"
            v-for="(item, index) in rightArr"
            :key="index"
            ref="right"
            :style="{ backgroundColor: primaryColor,border:'1px solid' + bordercolor }"
            v-html="item.label.txt"
          ></div>
        </div>
      </div>
      <div class="answer-box">
        <div
          class="answer-box-item"
          v-for="(item, index) in rightArr"
          :key="index"
          ref="right"
        >
          {{ item.label.txt }}
        </div>
      </div>
      <canvas
        class="connect-canvasA"
        :width="clientWidth"
        :height="clientHeight"
        ref="canvasA"
      ></canvas>
      <canvas
        class="connect-canvasB"
        :width="clientWidth"
        :height="clientHeight"
        ref="canvasB"
      ></canvas>
    </div>
    <canvas
      class="connect-canvasA"
      :width="clientWidth"
      :height="clientHeight"
      ref="canvasA"
    ></canvas>
    <canvas
      class="connect-canvasB"
      :width="clientWidth"
      :height="clientHeight"
      ref="canvasB"
    ></canvas>
    <!-- 按钮 -->
    <div class="btn-bottom">
      <el-button @click="submitData">提交</el-button>
      <el-button @click="saveData" :style="{ borderColor: bordercolor }"
        >保存</el-button
      >
      <el-button @click="redo">重做</el-button>
      <el-button @click="handleAnswer" :style="{ borderColor: bordercolor }"
        >查看答案</el-button
      >
    </div>
    <!-- 解析 -->
    <ul class="show-answer" v-if="isShowAnswer">
      <li v-if="isRight !== null">
        答案结果:
        <!-- <span v-if="isRight" style="color: #83e089">正确</span>
        <span v-if="isRight == false" style="color: #d81e06">错误</span> -->
        <!-- 正确 -->
        <svg t="1718283080456" class="icon" viewBox="0 0 1024 1024" version="1.1"
          xmlns="http://www.w3.org/2000/svg" p-id="97920" xmlns:xlink="http://www.w3.org/1999/xlink"
          width="20" height="20" v-if="isRight">
          <path
            d="M1005.038 514.114c0 271.97-220.503 492.457-492.48 492.457-271.962 0-492.449-220.487-492.449-492.457 0-271.984 220.487-492.464 492.449-492.464 271.977 0 492.48 220.48 492.48 492.464z"
            fill="#F5CB2B" p-id="97921"></path>
          <path
            d="M288.394 516.789c-19.68 0-35.773-16.094-35.773-35.773v-85.854c0-19.673 16.093-35.773 35.773-35.773 19.68 0 35.773 16.101 35.773 35.773v85.854c0 19.679-16.093 35.773-35.773 35.773zM736.752 516.789c-19.68 0-35.773-16.094-35.773-35.773v-85.854c0-19.673 16.094-35.773 35.773-35.773 19.681 0 35.773 16.101 35.773 35.773v85.854c0 19.679-16.092 35.773-35.773 35.773z"
            fill="#3E3417" p-id="97922"></path>
          <path
            d="M511.79 702.128c-154.229 0-196.709-88.296-198.441-92.056-5.787-12.56-0.302-27.433 12.266-33.227 12.567-5.778 27.425-0.294 33.227 12.259 1.115 2.253 32.73 62.942 152.949 62.942 120.521 0 153.476-61.549 154.816-64.163 5.967-12.484 20.825-17.616 33.303-11.656 12.492 5.961 17.69 21.067 11.738 33.544-1.809 3.775-45.885 92.357-199.858 92.357z"
            fill="#3E3417" p-id="97923"></path>
          <path
            d="M259.703 569.793c0 39.579-32.096 71.652-71.667 71.652-39.586 0-71.653-32.073-71.653-71.652 0-39.586 32.066-71.659 71.653-71.659 39.571 0 71.667 32.073 71.667 71.659zM949.298 569.793c0 39.579-32.082 71.652-71.652 71.652-39.586 0-71.651-32.073-71.651-71.652 0-39.586 32.065-71.659 71.651-71.659 39.57 0 71.652 32.073 71.652 71.659z"
            fill="#EC7184" p-id="97924"></path>
        </svg>
        <!-- 错误 -->
        <svg t="1718283143947" class="icon" viewBox="0 0 1024 1024" version="1.1"
          xmlns="http://www.w3.org/2000/svg" p-id="110219" xmlns:xlink="http://www.w3.org/1999/xlink"
          width="20" height="20" v-if="isRight == false">
          <path d="M512 512m-512 0a512 512 0 1 0 1024 0 512 512 0 1 0-1024 0Z" fill="#F9DF1E" p-id="110220"></path>
          <path
            d="M704.984615 433.230769h-7.876923c-27.569231-7.876923-106.338462-47.261538-86.646154-90.584615 11.815385-35.446154 110.276923-59.076923 165.415385-70.892308 11.815385-3.938462 19.692308 3.938462 23.630769 15.753846 3.938462 11.815385-3.938462 19.692308-15.753846 23.63077-66.953846 11.815385-129.969231 35.446154-137.846154 47.261538 3.938462 7.876923 35.446154 27.569231 63.015385 39.384615 11.815385 3.938462 15.753846 15.753846 11.815385 27.569231-3.938462 3.938462-7.876923 7.876923-15.753847 7.876923z"
            fill="#542913" p-id="110221"></path>
          <path
            d="M797.198342 462.421106a78.769231 39.384615 56.995 1 0 66.057691-42.906563 78.769231 39.384615 56.995 1 0-66.057691 42.906563Z"
            fill="#4DCEFF" p-id="110222"></path>
          <path
            d="M512 707.465846m-157.538462 0a157.538462 157.538462 0 1 0 315.076924 0 157.538462 157.538462 0 1 0-315.076924 0Z"
            fill="#542913" p-id="110223"></path>
          <path
            d="M393.846154 809.865846v-11.815384c7.876923-59.076923 59.076923-98.461538 118.153846-94.523077 59.076923-3.938462 110.276923 35.446154 118.153846 94.523077v11.815384c-59.076923 63.015385-157.538462 70.892308-220.553846 11.815385-7.876923 0-11.815385-3.938462-15.753846-11.815385z"
            fill="#EA3B3B" p-id="110224"></path>
          <path
            d="M319.015385 433.230769c-7.876923 0-15.753846-3.938462-19.692308-11.815384-3.938462-11.815385 0-19.692308 11.815385-23.63077 31.507692-11.815385 63.015385-35.446154 63.015384-43.323077-7.876923-11.815385-70.892308-31.507692-137.846154-43.323076-11.815385-3.938462-15.753846-15.753846-15.753846-23.63077 3.938462-11.815385 11.815385-19.692308 23.630769-15.753846 55.138462 11.815385 153.6 35.446154 165.415385 70.892308 15.753846 47.261538-63.015385 82.707692-86.646154 90.584615h-3.938461z"
            fill="#542913" p-id="110225"></path>
          <path
            d="M145.776323 508.859333a39.384615 78.769231 33.005 1 0 85.813125-132.115383 39.384615 78.769231 33.005 1 0-85.813125 132.115383Z"
            fill="#4DCEFF" p-id="110226"></path>
        </svg>
      </li>
      <li class="show-answer-box">
        <div>答案:</div>
        <div>
          <img :src="question.answerImg" alt="" class="w100" />
        </div>
      </li>
    </ul>
  </div>
</template>
@@ -56,7 +129,11 @@
      scrollTop: 0,
      debounce: false,
      checkItem: null,
      checkItemIndex:null
      checkItemIndex: null,
      isShowAnswer: false,
      isRight: null,
      value: [],
      pageNum: null,
    };
  },
  props: {
@@ -69,18 +146,20 @@
        };
      },
    },
    value: {
      type: Array,
      default: () => {
        return [];
      },
    },
    item: {
    question: {
      type: Object,
      default: () => {
        return [];
      },
    },
    primaryColor: {
      type: String,
      default: "#fff",
    },
    bordercolor:{
      type:String,
      default:'#f49a4c'
    }
  },
  watch: {
    rawData: {
@@ -91,6 +170,8 @@
    },
  },
  mounted() {
    // 获取当前页码,用于匹配本次存储题目数据
    this.pageNum = this.handlePage();
    // 添加滚动事件 监听 解决因为滚动引起的拖动线不对的问题
    window.addEventListener(
      "scroll",
@@ -112,6 +193,7 @@
    this.$nextTick(() => {
      this.drawing();
    });
    this.getAnswer();
  },
  methods: {
    init() {
@@ -150,14 +232,16 @@
    },
    // 触摸结束
    touchend(e, index) {
      console.log("抬起", e,this.checkItem);
      this.isDragging = false;
      if (this.item.showAnswer) {
      if (this.question.showAnswer) {
        return false;
      }
      // let event = e.changedTouches[0];
      // document.elementFromPoint 重点,根据x,y坐标 取当前元素 所有能运行的逻辑 都依托于这里。
      let dom = document.elementFromPoint(e.pageX, e.pageY);
      let dom = (this.container ? this.container : document).elementFromPoint(
        e.pageX,
        e.pageY
      );
      // 右边的dom是哪个
      let right = this.rightDom.find((r) => r.bom === dom);
      // 不管是哪个都清除掉 底部的线
@@ -188,15 +272,14 @@
        })
        .filter((r) => r.right !== undefined);
      this.$emit("input", model);
      this.item.userChoise = model;
      console.log(JSON.stringify(model));
      this.question.userChoise = model;
      // console.log(JSON.stringify(model));
    },
    // 触摸开始
    touchstart(e, item,index) {
    touchstart(e, item, index) {
      this.isDragging = true;
      console.log("按下", e);
      this.checkItem = item
      this.checkItemIndex = index
      this.checkItem = item;
      this.checkItemIndex = index;
      e.stopPropagation();
      // let event = e.targetTouches[0];
      item.line = [
@@ -208,7 +291,7 @@
    // touchmove(e, item) {
    //     if(!this.isDragging) return false
    //     console.log('移动',e);
    //     if (this.item.showAnswer) {
    //     if (this.question.showAnswer) {
    //         return false;
    //     }
    //     // let event = e.targetTouches[0];
@@ -220,10 +303,9 @@
    // 移动中
    mousemove(e) {
      if (!this.isDragging) return false;
      if (this.item.showAnswer) {
      if (this.question.showAnswer) {
        return false;
      }
      // let event = e.targetTouches[0];
      this.checkItem.line[2] = e.pageX;
      this.checkItem.line[3] =
        e.pageY - this.$refs.connect.getBoundingClientRect().y + this.scrollTop;
@@ -251,8 +333,8 @@
      canvasA.lineWidth = 2;
      for (let i = 0; i < this.leftArr.length; i++) {
        const line = this.leftArr[i].line;
        console.log(line);
        console.log(this.leftArr[i]);
        // console.log(line);
        // console.log(this.leftArr[i]);
        if (line.length) {
          canvasA.moveTo(line[0], line[1]);
          canvasA.lineTo(line[2], line[3]);
@@ -272,9 +354,104 @@
      let rightY = rightEvent.offsetTop + rightEvent.clientHeight / 2;
      return [leftX, leftY, rightX, rightY];
    },
    mouseup() {
      console.log("大盒子抬起", this.isDragging);
      this.isDragging = false;
    areArraysEqual(array1, array2) {
      // 如果两个数组长度不同,则它们不等
      if (array1.length !== array2.length) {
        return false;
      }
      // 遍历数组并比较每个对象的属性
      for (let i = 0; i < array1.length; i++) {
        const obj1 = array1[i];
        const obj2 = array2[i];
        // 如果对象的left或right属性不相等,则数组不等
        if (obj1.left !== obj2.left || obj1.right !== obj2.right) {
          return false;
        }
      }
      // 如果所有对象都匹配,则数组相等
      return true;
    },
    // 查看答案
    handleAnswer() {
      this.isShowAnswer = !this.isShowAnswer;
    },
    // 提交
    submitData() {
      const answerArr = [];
      const values = this.question.options.values;
      for (let index = 0; index < values.length; index++) {
        const item = values[index];
        const rightIndex = this.question.options.linkValues.findIndex(
          (citem) => citem.oldId == item.oldId
        );
        answerArr.push({
          left: index,
          right: rightIndex,
        });
      }
      console.log(this.question.userChoise,answerArr);
      this.isRight = this.areArraysEqual(this.question.userChoise, answerArr);
      this.isShowAnswer = true;
    },
    // 获取当前页码
    handlePage() {
      let pageNum = null;
      const element = (
        this.container ? this.container : document
      ).querySelector("matching");
      if (element) {
        pageNum = this.getParentWithClass(element, "page-box").getAttribute(
          "page"
        );
      }
      return pageNum;
    },
    getParentWithClass(element, className) {
      while (element.parentElement) {
        element = element.parentElement;
        if (element.classList.contains(className)) {
          return element;
        }
      }
    },
    // 获取本地存储题目答案
    getAnswer() {
      const data = localStorage.getItem(
        this.config.activeBook.name + "-matching-" + this.pageNum
      );
      if (data) {
        this.value = JSON.parse(data);
      }
    },
    // 保存
    saveData() {
      if (this.question.userChoise.length)
        localStorage.setItem(
          this.config.activeBook.name + "-matching-" + this.pageNum,
          JSON.stringify(this.question.userChoise)
        );
      // console.log('保存成功',this.config.activeBook.name,this.pageNum);
    },
    // 重做
    redo() {
      this.question.showAnswer = false;
      localStorage.removeItem(
        this.config.activeBook.name + "-matching-" + this.pageNum
      );
      this.value = [];
      for (let index = 0; index < this.leftArr.length; index++) {
        const item = this.leftArr[index];
        item.value = [];
        item.line = [];
      }
      this.leftArr;
      this.drawing();
      this.isShowAnswer = false;
      this.isRight = null
    },
  },
};
@@ -313,14 +490,14 @@
    text-align: center;
    &-item {
      cursor: pointer;
      z-index: 2;
      // display: inline-flex;
      padding: 10px;
      border-radius: 4px;
      box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
      margin-bottom: 20px;
      line-height: 40px;
      padding: 20px 0;
      line-height: 24px;
      padding: 6px;
    }
    &-item:last-child {
@@ -328,11 +505,49 @@
    }
  }
}
.tl-le {
  text-align: left;
}
.connect {
  -webkit-user-select: none; /* Safari */
  -moz-user-select: none; /* Firefox */
  -ms-user-select: none; /* IE10+/Edge */
  user-select: none; /* 标准语法 */
}
.show-answer {
  margin: 30px auto;
  width: 100%;
  height: min-content;
  box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
  li {
    padding: 10px;
  }
}
.btn-bottom {
  width: 70%;
  margin: 70px auto 0 auto;
  display: flex;
  justify-content: space-evenly;
  flex-wrap: wrap;
  .el-button {
    margin-top: 10px;
  }
}
.el-button {
  height: 30px;
  padding: 7px;
  min-width: 78px;
}
.answer-box-item {
  /deep/ .un1 {
    -webkit-text-emphasis-style: dot;
    -moz-text-emphasis-style: dot;
    -ms-text-emphasis-style: dot;
    text-emphasis-style: dot;
    -webkit-text-emphasis-position: under;
    -moz-text-emphasis-position: under;
    -ms-text-emphasis-position: under;
    text-emphasis-position: under;
  }
}
</style>