YM
2024-05-31 65b5cd16cc9d9ab4b346a37107a44011550f701b
src/books/childHealth/view/content/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="{
@@ -15,57 +18,57 @@
      <chapterOne
        v-if="showCatalogList.indexOf(2) > -1"
        :showPageList="loadPageList"
        :questionData="questionData"
        :questionData="questionDataMap"
      ></chapterOne>
      <chapterTwo
        v-if="showCatalogList.indexOf(3) > -1"
        :showPageList="loadPageList"
        :questionData="questionData"
        :questionData="questionDataMap"
      ></chapterTwo>
      <chapterThree
        v-if="showCatalogList.indexOf(4) > -1"
        :showPageList="loadPageList"
        :questionData="questionData"
        :questionData="questionDataMap"
      ></chapterThree>
      <chapterFour
        v-if="showCatalogList.indexOf(5) > -1"
        :showPageList="loadPageList"
        :questionData="questionData"
        :questionData="questionDataMap"
      ></chapterFour>
      <chapterFive
        v-if="showCatalogList.indexOf(6) > -1"
        :showPageList="loadPageList"
        :questionData="questionData"
        :questionData="questionDataMap"
      ></chapterFive>
      <chapterSix
        v-if="showCatalogList.indexOf(7) > -1"
        :showPageList="loadPageList"
        :questionData="questionData"
        :questionData="questionDataMap"
      ></chapterSix>
      <chapterSeven
        v-if="showCatalogList.indexOf(8) > -1"
        :showPageList="loadPageList"
        :questionData="questionData"
        :questionData="questionDataMap"
      ></chapterSeven>
      <chapterEight
        v-if="showCatalogList.indexOf(9) > -1"
        :showPageList="loadPageList"
        :questionData="questionData"
        :questionData="questionDataMap"
      ></chapterEight>
      <chapterNine
        v-if="showCatalogList.indexOf(10) > -1"
        :showPageList="loadPageList"
        :questionData="questionData"
        :questionData="questionDataMap"
      ></chapterNine>
      <chapterTen
        v-if="showCatalogList.indexOf(11) > -1"
        :showPageList="loadPageList"
        :questionData="questionData"
        :questionData="questionDataMap"
      ></chapterTen>
      <chapterEleven
        v-if="showCatalogList.indexOf(12) > -1"
        :showPageList="loadPageList"
        :questionData="questionData"
        :questionData="questionDataMap"
      ></chapterEleven>
      <chapterTwelve
        v-if="showCatalogList.indexOf(13) > -1"
@@ -80,6 +83,7 @@
</template>
<script>
import Vue from "vue";
import pageHeader from "./components/header.vue";
import chapterOne from "./components/chapter001.vue";
import chapterTwo from "./components/chapter002.vue";
@@ -114,7 +118,7 @@
      observer: null,
      loadPageObserver: null,
      loadPageList: [],
      questionData: {},
      questionDataMap: {},
      renderSignMap: {}
    };
  },
@@ -204,7 +208,7 @@
    }, 500);
    // 测试页面跳转
    // setTimeout(() => {
    setTimeout(() => {
    //   this.gotoPage(1, 10);
    //   setTimeout(() => {
    //     this.renderSign("Highlight", {
@@ -220,7 +224,20 @@
    //   });
    // }, 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: {
    // 滚动监听
@@ -269,7 +286,7 @@
      this.previousScrollTop = event.target.scrollTop;
    },
    // 章节、页面跳转
    gotoPage(catalog, page) {
    gotoPage(catalog, page, callback) {
      if (catalog >= 0 && catalog <= this.catalogLength) {
        // 处理渲染章节
        if (catalog == 0) {
@@ -290,6 +307,7 @@
          ).querySelector(`[page="${page}"]`);
          if (pageDom) {
            pageDom.scrollIntoView();
            if (callback) callback();
          } else {
            console.log("页码错误!");
          }
@@ -324,10 +342,9 @@
          this.container ? this.container : document
        ).querySelector(`[page="${data.page}"]`);
        // 创建 createTreeWalker 迭代器,用于遍历文本节点,保存到一个数组
        const treeWalker = document.createTreeWalker(
          pageDom,
          NodeFilter.SHOW_TEXT
        );
        const treeWalker = (
          this.container ? this.container : document
        ).createTreeWalker(pageDom, NodeFilter.SHOW_TEXT);
        const allTextNodes = [];
        let currentNode = treeWalker.nextNode();
        while (currentNode) {
@@ -503,6 +520,7 @@
      });
    },
    getParentWithClass(element, className) {
      console.log(element, className, "element, className");
      while (element.parentElement) {
        element = element.parentElement;
        if (element.classList.contains(className)) {
@@ -552,11 +570,11 @@
              "chapter"
            );
            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
@@ -570,9 +588,9 @@
                        this.config.activeBook
                      );
                    }
                    this.questionData[page] = obj;
                    this.questionDataMap[page] = obj;
                  }
                  console.log("题目", this.questionData);
                  console.log("题目", this.questionDataMap);
                }
              }
            }
@@ -647,6 +665,152 @@
          title: true // 显示标题
        });
      }
    },
    // 根据关键字全文检索
    searchTextByPage(keyword) {
      const searchResult = [];
      let catalogIndex = 0;
      // 所有章节组件(每本书制作时单独配置)
      const pageData = {
        pageHeader,
        chapterOne,
        chapterTwo,
        chapterThree,
        chapterFour,
        chapterFive,
        chapterSix,
        chapterSeven,
        chapterEight,
        chapterNine,
        chapterTen,
        chapterEleven,
        chapterTwelve,
        chapterThirteen
      };
      // 遍历所有章节文件
      for (const key in pageData) {
        catalogIndex++;
        let pageComponent, pageExample;
        // 先渲染一次当前章节文件(这时页面的内容为空),获取页码信息
        pageComponent = Vue.extend(pageData[key]);
        pageExample = new pageComponent({
          propsData: {
            showPageList: [],
            questionData: {}
          }
        });
        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: {}
              }
            });
            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 = (
                this.container ? this.container : 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>';
            }
          }
        }
      }
      // 输出搜索结果
      console.log(searchResult);
      return searchResult;
    },
    // 根据检索结果跳转对应位置并高亮
    searchItemLocation(data) {
      // 跳转
      this.gotoPage(data.catalog, data.page, () => {
        // 高亮行
        const thisPageDom = (
          this.container ? this.container : document
        ).querySelector(`[page="${data.page}"]`);
        if (thisPageDom) {
          // 获取页面所有text节点
          const pageTextList = (
            this.container ? this.container : 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(data.txt);
            if (txtIndex > -1) {
              textDom.parentNode.style.transition = "background-color 0.8s";
              textDom.parentNode.scrollIntoView();
              textDom.parentNode.backgroundColor = "#79bbf0";
              setTimeout(() => {
                textDom.parentNode.backgroundColor = "";
              }, 2000);
            }
          }
        }
      });
    }
  },
  components: {