unknown
2024-06-12 62a6b29d24207428219882556c77ffb5941b7943
src/books/artAndDance/view/components/index.vue
@@ -1,5 +1,8 @@
<template>
  <div class="page-main" @scroll="throttledScrollHandler">
    <div id="searchDomBox" style="display: none">
      <div id="searchContent"></div>
    </div>
    <div
      class="page-content"
      :style="{
@@ -13,7 +16,6 @@
        :showPageList="loadPageList"
      ></pageHeader>
      <chapterOne
        @saveCharacters="saveCharacters"
        v-if="showCatalogList.indexOf(2) > -1"
        :showPageList="loadPageList"
      ></chapterOne>
@@ -22,7 +24,24 @@
        :showPageList="loadPageList"
      >
      </chapterTwo>
      <chapterThree
      v-if="showCatalogList.indexOf(4) > -1"
        :showPageList="loadPageList"
      ></chapterThree>
      <chapterFour
      v-if="showCatalogList.indexOf(5) > -1"
        :showPageList="loadPageList"
      ></chapterFour>
      <chapterFive
      v-if="showCatalogList.indexOf(6) > -1"
        :showPageList="loadPageList"
      ></chapterFive>
      <chapterSix
        v-if="showCatalogList.indexOf(7) > -1"
        :showPageList="loadPageList"
      ></chapterSix>
    </div>
  </div>
</template>
@@ -30,6 +49,10 @@
import pageHeader from "./header.vue";
import chapterOne from "./chapter001.vue";
import chapterTwo from "./chapter002.vue";
import chapterThree from "./chapter003.vue"
import chapterFour from './chapter004.vue'
import chapterFive from './chapter005.vue'
import chapterSix from './chapter006.vue'
import NoteIcon from "@/assets/images/biji.png";
import _ from "lodash";
import Swiper from "swiper/bundle";
@@ -37,9 +60,10 @@
import Viewer from "viewerjs";
import "viewerjs/dist/viewer.css";
export default {
  name:"pageContent",
  data() {
    return {
      catalogLength: 3, // 总章节数
      catalogLength: 7, // 总章节数
      showCatalogList: [], // 显示的章节
      loadThreshold: 300, // 触发加载阈值
      throttleThreshold: 100, // 节流阈值
@@ -48,8 +72,9 @@
      observer: null,
      loadPageObserver: null,
      loadPageList: [],
      questionData: {},
      questionDataMap: {},
      renderSignMap: {},
      highlightData: null,
    };
  },
  computed: {
@@ -87,6 +112,14 @@
        }, 200);
      },
    },
    pageZoom: {
      handler(newVal, oldVal) {
        const scrollBox = (
          this.container ? this.container : document
        ).querySelector(".page-main");
        scrollBox.scrollTop = (scrollBox.scrollTop / oldVal) * newVal;
      },
    },
  },
  mounted() {
    // 默认加载章节
@@ -113,6 +146,14 @@
        // 删除笔记、高亮、划线
        delSign: (data) => {
          this.delSign(data);
        },
        // 全文检索
        searchBookByKeyword: (keyword) => {
          return this.searchTextByPage(keyword);
        },
        // 跳转检索结果位置
        jumpSearchItem: (data) => {
          this.searchItemLocation(data);
        },
      });
    }
@@ -154,9 +195,36 @@
    //   });
    // }, 2000);
    //   }, 5000);
    // }, 1000);
    // const pageDom = (this.container ? this.container : document)
    //   .querySelector("#app")
    //   .querySelectorAll(".page-box");
    // 检索
    // console.log(this.searchTextByPage("保护内脏器官"), "searchTextByPage");
    // 检索跳转
    // this.searchItemLocation({
    //   catalog: 2,
    //   page: 10,
    //   txt: " 运动系统是由骨、骨连结和骨骼肌三部分组成的。全身的骨通过骨连结组成人体骨骼(见图1-1)。骨骼是人体的支架,具有保护内脏器官、供肌肉附着和作为肌肉运动的杠杆等作用。在神经系统的支配下,肌肉收缩牵动所附着的骨绕着关节转动,使身体产生各种动作。所以,运动系统具有运动、支持和保护等功能,幼年时期的骨骼还具有造血功能。 ",
    //   txtIndex: 57
    // });
    // }, 5000);
  },
  methods: {
    // setZoom1() {
    //   let scale = this.$store.state.qiankun.scale + 10;
    //   const scrollBox = (
    //     this.container ? this.container : document
    //   ).querySelector(".page-main");
    //   this.$store.commit("setZoom", scale);
    // },
    // setZoom2() {
    //   let scale = this.$store.state.qiankun.scale - 10;
    //   const scrollBox = (
    //     this.container ? this.container : document
    //   ).querySelector(".page-main");
    //   this.$store.commit("setZoom", scale);
    // },
    // 滚动监听
    scrollFun(event) {
      // 判断向上滚动还是向下滚动
@@ -249,6 +317,10 @@
    // 渲染标记
    renderSign(type, data) {
      // 父层设置禁止渲染标记时不再进行渲染
      if (this.$store.state.qiankun.disableSign) {
        return false;
      }
      const existence = (
        this.container ? this.container : document
      ).querySelector(`[dataid="${data.id}"]`);
@@ -258,10 +330,7 @@
          this.container ? this.container : document
        ).querySelector(`[page="${data.page}"]`);
        // 创建 createTreeWalker 迭代器,用于遍历文本节点,保存到一个数组
        const treeWalker = document.createTreeWalker(
          pageDom,
          NodeFilter.SHOW_TEXT
        );
        const treeWalker = document.createTreeWalker(pageDom, NodeFilter.SHOW_TEXT);
        const allTextNodes = [];
        let currentNode = treeWalker.nextNode();
        while (currentNode) {
@@ -437,6 +506,7 @@
      });
    },
    getParentWithClass(element, className) {
      console.log(element, className, "element, className");
      while (element.parentElement) {
        element = element.parentElement;
        if (element.classList.contains(className)) {
@@ -459,7 +529,7 @@
          const catalog = catalogDom.getAttribute("num");
          let text = null;
          if (target.querySelector("p")) {
            text = target.querySelector("p").textContent.substring(0, 20);
            text = target.querySelector("p").textContent.substring(0, 50);
          }
          // 返回页码和章节信息
          if (this.$store.state.qiankun && this.$store.state.qiankun.pageChange)
@@ -485,12 +555,14 @@
              target,
              "chapter"
            );
            // 添加页码
            this.loadPageList.push(Number(page));
            const catalog = catalogDom.getAttribute("num");
            // if (!this.questionData[page]) {
            // if (!this.questionDataMap[page]) {
            //   if (testData && testData[catalog]) {
            //     if (testData[catalog][page]) {
            //       if (Array.isArray(testData[catalog][page])) {
            //         this.questionData[page] = await getQuestionList(
            //         this.questionDataMap[page] = await getQuestionList(
            //           page,
            //           testData[catalog][page],
            //           this.config.activeBook
@@ -504,14 +576,12 @@
            //             this.config.activeBook
            //           );
            //         }
            //         this.questionData[page] = obj;
            //         this.questionDataMap[page] = obj;
            //       }
            //       console.log("题目", this.questionData);
            //       console.log("题目", this.questionDataMap);
            //     }
            //   }
            // }
            // 添加页码
            this.loadPageList.push(Number(page));
            // 渲染这一页的标记
            for (const key in this.renderSignMap) {
              if (this.renderSignMap[key][page]) {
@@ -519,6 +589,36 @@
                  this.renderSign(key, item);
                });
              }
            }
            // 处理高亮
            if (this.highlightData) {
              // 高亮行
              setTimeout(() => {
                // 获取页面所有text节点
                const pageTextList = document.createTreeWalker(target, NodeFilter.SHOW_TEXT);
                // 匹配关键字
                const allPageTextNodes = [];
                let currentNode = pageTextList.nextNode();
                while (currentNode) {
                  allPageTextNodes.push(currentNode);
                  currentNode = pageTextList.nextNode();
                }
                for (let i = 0; i < allPageTextNodes.length; i++) {
                  const textDom = allPageTextNodes[i];
                  let txtIndex = textDom.textContent.indexOf(
                    this.highlightData.txt
                  );
                  if (txtIndex > -1) {
                    textDom.parentNode.style.transition =
                      "background-color 0.8s";
                    textDom.parentNode.scrollIntoView();
                    textDom.parentNode.style.backgroundColor = "#79bbf0";
                    setTimeout(() => {
                      textDom.parentNode.style.backgroundColor = "";
                    }, 1000);
                  }
                }
              }, 100);
            }
            if (this.loadPageList.length > 5) {
              // 超过5页
@@ -623,24 +723,126 @@
        });
      }
    },
    // 点击事件:将生僻单词传给 主应用 从而调用词典功能
    saveCharacters(event, word) {
      console.log("生僻字", event, word);
      if (this.$store.state.qiankun && this.$store.state.qiankun.chooseWords) {
        this.$store.state.qiankun.chooseWords({
          type: "word",
          word,
          x: event.pageX,
          y: event.pageY,
    // 根据关键字全文检索
    searchTextByPage(keyword) {
      const searchResult = [];
      let catalogIndex = 0;
      // 所有章节组件(每本书制作时单独配置)
      const pageData = {
        pageHeader,
        chapterOne,
        chapterTwo,
        chapterThree,
        chapterFour,
        chapterFive,
        chapterSix,
      };
      // 遍历所有章节文件
      for (const key in pageData) {
        catalogIndex++;
        let pageComponent, pageExample;
        // 先渲染一次当前章节文件(这时页面的内容为空),获取页码信息
        pageComponent = Vue.extend(pageData[key]);
        pageExample = new pageComponent({
          propsData: {
            showPageList: [],
            questionData: {},
            isSearch: true
          },
        });
        pageExample.$mount(
          (this.container ? this.container : document).querySelector(
            "#searchContent"
          )
        );
        // 获取页码
        const pageDom = (this.container ? this.container : document)
          .querySelector("#searchDomBox")
          .querySelectorAll(".page-box");
        const pages = [];
        for (let i = 0; i < pageDom.length; i++) {
          const pageDomItem = pageDom[i];
          pages.push(Number(pageDomItem.getAttribute("page")));
        }
        // 获取页面结束,卸载销毁
        pageExample.$destroy();
        (this.container ? this.container : document).querySelector(
          "#searchDomBox"
        ).innerHTML = '<div id="searchContent"></div>';
        // 遍历页码
        if (pages.length) {
          for (let i = 0; i < pages.length; i++) {
            const pageNum = pages[i];
            // 动态渲染对应章节的页码
            pageComponent = Vue.extend(pageData[key]);
            pageExample = new pageComponent({
              propsData: {
                showPageList: [pageNum],
                questionData: {},
                isSearch: true
              },
            });
            pageExample.$mount(
              (this.container ? this.container : document).querySelector(
                "#searchContent"
              )
            );
            // 获取对应页面dom
            const thisPageDom = (this.container ? this.container : document)
              .querySelector("#searchDomBox")
              .querySelector(`[page="${pageNum}"]`);
            if (thisPageDom) {
              // 获取页面所有text节点
              const pageTextList = document.createTreeWalker(thisPageDom, NodeFilter.SHOW_TEXT);
              // 匹配关键字
              const allPageTextNodes = [];
              let currentNode = pageTextList.nextNode();
              while (currentNode) {
                allPageTextNodes.push(currentNode);
                currentNode = pageTextList.nextNode();
              }
              for (let i = 0; i < allPageTextNodes.length; i++) {
                const textDom = allPageTextNodes[i];
                let txtIndex = textDom.textContent.indexOf(keyword);
                if (txtIndex > -1) {
                  // 记录关键字所在页码、章节以及匹配到的段落
                  searchResult.push({
                    page: pageNum,
                    catalog: catalogIndex,
                    txt: textDom.textContent,
                    txtIndex: txtIndex,
                  });
                }
              }
              // 结束,卸载销毁
              pageExample.$destroy();
              (this.container ? this.container : document).querySelector(
                "#searchDomBox"
              ).innerHTML = '<div id="searchContent"></div>';
            }
          }
        }
      }
      // chooseWords
      // 输出搜索结果
      console.log(searchResult);
      return searchResult;
    },
    // 根据检索结果跳转对应位置并高亮
    searchItemLocation(data) {
      // 记录高亮信息
      this.highlightData = data;
      // 跳转
      this.gotoPage(data.catalog, data.page, () => {});
    },
  },
  components: {
    pageHeader,
    chapterOne,
    chapterTwo,
    chapterThree,
    chapterFour,
    chapterFive,
    chapterSix,
  },
};
</script>