| | |
| | | <!-- @format --> |
| | | |
| | | <template> |
| | | <div class="page-main" @scroll="throttledScrollHandler"> |
| | | <div id="searchDomBox" style="display: none"> |
| | |
| | | <chapterTwo v-if="showCatalogList.indexOf(3) > -1" :showPageList="loadPageList"></chapterTwo> |
| | | <chapterThree v-if="showCatalogList.indexOf(4) > -1" :showPageList="loadPageList"></chapterThree> |
| | | <chapterFour v-if="showCatalogList.indexOf(5) > -1" :showPageList="loadPageList"></chapterFour> |
| | | <assemblyOne v-if="showCatalogList.indexOf(6) > -1" :showPageList="loadPageList"></assemblyOne> |
| | | <!-- <assemblyTwo v-if="showCatalogList.indexOf(7) > -1" :showPageList="loadPageList" @openPDFChange="swdtChange" /> --> |
| | | <chapterfive v-if="showCatalogList.indexOf(6) > -1" :showPageList="loadPageList"></chapterfive> |
| | | <chapterSix v-if="showCatalogList.indexOf(7) > -1" :showPageList="loadPageList"></chapterSix> |
| | | <chapterSeven v-if="showCatalogList.indexOf(8) > -1" :showPageList="loadPageList"></chapterSeven> |
| | | <chapterEight v-if="showCatalogList.indexOf(9) > -1" :showPageList="loadPageList"></chapterEight> |
| | | <chapterNine v-if="showCatalogList.indexOf(10) > -1" :showPageList="loadPageList"></chapterNine> |
| | | |
| | | |
| | | <!-- <ChapterFour |
| | | v-if="showCatalogList.indexOf(5) > -1" |
| | | :showPageList="loadPageList" |
| | | :questionData="questionDataMap" |
| | | /> --> |
| | | <!-- <ChapterFive |
| | | v-if="showCatalogList.indexOf(6) > -1" |
| | | :showPageList="loadPageList" |
| | | :questionData="questionDataMap" |
| | | @Upload_initViewer="changeDomViewer" |
| | | /> --> |
| | | <!-- <chapterSix |
| | | v-if="showCatalogList.indexOf(7) > -1" |
| | | :showPageList="loadPageList" |
| | | :questionData="questionDataMap" |
| | | /> --> |
| | | <!-- <chapterSeven |
| | | v-if="showCatalogList.indexOf(8) > -1" |
| | | :showPageList="loadPageList" |
| | | :questionData="questionDataMap" |
| | | @eventSwdt="swdtChange" |
| | | @Upload_initViewer="changeDomViewer" |
| | | /> --> |
| | | <!-- <chapterEight |
| | | v-if="showCatalogList.indexOf(9) > -1" |
| | | :showPageList="loadPageList" |
| | | :questionData="questionDataMap" |
| | | /> --> |
| | | <!-- <chapterNine |
| | | v-if="showCatalogList.indexOf(10) > -1" |
| | | :showPageList="loadPageList" |
| | | :questionData="questionDataMap" |
| | | /> --> |
| | | <!-- <chapter010 |
| | | v-if="showCatalogList.indexOf(11) > -1" |
| | | :showPageList="loadPageList" |
| | | /> --> |
| | | <!-- <chapter011 |
| | | v-if="showCatalogList.indexOf(12) > -1" |
| | | :showPageList="loadPageList" |
| | | /> --> |
| | | <!-- <chapter012 |
| | | v-if="showCatalogList.indexOf(13) > -1" |
| | | :showPageList="loadPageList" |
| | | /> --> |
| | | <!-- <chapter013 |
| | | v-if="showCatalogList.indexOf(14) > -1" |
| | | :showPageList="loadPageList" |
| | | /> --> |
| | | <!-- <chapter014 |
| | | v-if="showCatalogList.indexOf(15) > -1" |
| | | :showPageList="loadPageList" |
| | | /> --> |
| | | <!-- <chapter015 |
| | | v-if="showCatalogList.indexOf(16) > -1" |
| | | :showPageList="loadPageList" |
| | | /> --> |
| | | <!-- <chapter016 |
| | | v-if="showCatalogList.indexOf(17) > -1" |
| | | :showPageList="loadPageList" |
| | | /> --> |
| | | <!-- <chapter017 |
| | | v-if="showCatalogList.indexOf(18) > -1" |
| | | :showPageList="loadPageList" |
| | | /> --> |
| | | <!-- <chapter018 |
| | | v-if="showCatalogList.indexOf(19) > -1" |
| | | :showPageList="loadPageList" |
| | | /> --> |
| | | </div> |
| | | </div> |
| | | </template> |
| | | |
| | | <script> |
| | | import Vue from 'vue' |
| | | import pageHeader from './front001' |
| | | 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 chapterSeven from './chapter007.vue' |
| | | import chapterEight from './chapter008.vue' |
| | | import chapterNine from './chapter009.vue' |
| | | |
| | | import Vue from "vue"; |
| | | |
| | | import pageHeader from "./front001"; |
| | | import chapterOne from "./chapter001.vue"; |
| | | import chapterTwo from "./chapter002.vue"; |
| | | import chapterThree from "./chapter003.vue"; |
| | | import chapterFour from "./chapter004.vue"; |
| | | import assemblyOne from "./testDynaicTable.vue"; |
| | | import assemblyTwo from "./testPp.vue"; |
| | | |
| | | // import ChapterFour from "./testPp"; |
| | | // import ChapterFive from "./chapter005"; |
| | | // import chapterSix from "./chapter006"; |
| | | // import chapterSeven from "./chapter007"; |
| | | // import chapterEight from "./chapter008"; |
| | | // import chapterNine from "./chapter009"; |
| | | // import chapter010 from "./chapter010"; |
| | | // import chapter011 from "./chapter011"; |
| | | // import chapter012 from "./chapter012"; |
| | | // import chapter013 from "./chapter013"; |
| | | // import chapter014 from "./chapter014"; |
| | | // import chapter015 from "./chapter015"; |
| | | // import chapter016 from "./chapter016"; |
| | | // import chapter017 from "./chapter017"; |
| | | // import chapter018 from "./chapter018"; |
| | | import NoteIcon from "@/assets/images/biji.png"; |
| | | import _ from "lodash"; |
| | | import getQuestionList from "@/assets/methods/examination"; |
| | | import testData from "../../js/examinationList"; |
| | | import Swiper from "swiper/bundle"; |
| | | import "swiper/swiper-bundle.css"; |
| | | import Viewer from "viewerjs"; |
| | | import "viewerjs/dist/viewer.css"; |
| | | import NoteIcon from '@/assets/images/biji.png' |
| | | import _ from 'lodash' |
| | | import getQuestionList from '@/assets/methods/examination' |
| | | import testData from '../../js/examinationList' |
| | | import Swiper from 'swiper/bundle' |
| | | import 'swiper/swiper-bundle.css' |
| | | import Viewer from 'viewerjs' |
| | | import 'viewerjs/dist/viewer.css' |
| | | export default { |
| | | data() { |
| | | return { |
| | | catalogLength: 7, // 总章节数 |
| | | catalogLength: 10, // 总章节数 |
| | | showCatalogList: [], // 显示的章节 |
| | | loadThreshold: 300, // 触发加载阈值 |
| | | throttleThreshold: 100, // 节流阈值 |
| | |
| | | questionDataMap: {}, |
| | | renderSignMap: {}, |
| | | highlightData: null, |
| | | }; |
| | | } |
| | | }, |
| | | computed: { |
| | | fontSize() { |
| | | return this.$store.state.qiankun.fontSize; |
| | | return this.$store.state.qiankun.fontSize |
| | | }, |
| | | pageZoom() { |
| | | return this.$store.state.qiankun.scale / 100; |
| | | return this.$store.state.qiankun.scale / 100 |
| | | }, |
| | | }, |
| | | watch: { |
| | |
| | | // 调用父层方法 |
| | | this.$store.state.qiankun.catalogChange({ |
| | | showCatalogList: newVal, |
| | | }); |
| | | }) |
| | | } |
| | | // 启动页码观察 |
| | | setTimeout(() => { |
| | | this.initObservation(); |
| | | this.initThemeColor(); |
| | | }, 500); |
| | | this.initObservation() |
| | | this.initThemeColor() |
| | | }, 500) |
| | | }, |
| | | }, |
| | | loadPageList: { |
| | | handler(newVal, oldVal) { |
| | | setTimeout(() => { |
| | | this.initSwiper(); |
| | | this.initViewer(); |
| | | this.readText(); |
| | | }, 200); |
| | | this.initSwiper() |
| | | this.initViewer() |
| | | this.readText() |
| | | }, 200) |
| | | }, |
| | | }, |
| | | pageZoom: { |
| | | handler(newVal, oldVal) { |
| | | const scrollBox = ( |
| | | this.container ? this.container : document |
| | | ).querySelector(".page-main"); |
| | | scrollBox.scrollTop = (scrollBox.scrollTop / oldVal) * newVal; |
| | | ).querySelector('.page-main') |
| | | scrollBox.scrollTop = (scrollBox.scrollTop / oldVal) * newVal |
| | | }, |
| | | }, |
| | | }, |
| | | mounted() { |
| | | // 默认加载章节 |
| | | this.showCatalogList = [1]; |
| | | this.showCatalogList = [1] |
| | | // 滚动监听节流 |
| | | this.throttledScrollHandler = _.throttle( |
| | | this.scrollFun, |
| | | this.throttleThreshold, |
| | | { leading: true, trailing: false } |
| | | ); |
| | | ) |
| | | // 定义子层方法 |
| | | if (this.setGlobalState) { |
| | | // 提供页面跳转功能 |
| | | this.setGlobalState({ |
| | | gotoPage: (catalog, page) => { |
| | | this.gotoPage(catalog, page); |
| | | this.gotoPage(catalog, page) |
| | | }, |
| | | // 渲染笔记、高亮、划线 |
| | | renderSign: (type, data) => { |
| | | // 因为调整为页面懒加载,所以渲染标记也需要按照页面进行处理,先储存数据,页面加载完成再渲染对应的标记; |
| | | this.handelSignData(type, data); |
| | | this.handelSignData(type, data) |
| | | // this.renderSign(type, data); |
| | | }, |
| | | // 删除笔记、高亮、划线 |
| | | delSign: (data) => { |
| | | this.delSign(data); |
| | | this.delSign(data) |
| | | }, |
| | | // 全文检索 |
| | | searchBookByKeyword: (keyword) => { |
| | | return this.searchTextByPage(keyword); |
| | | return this.searchTextByPage(keyword) |
| | | }, |
| | | // 跳转检索结果位置 |
| | | jumpSearchItem: (data) => { |
| | | this.searchItemLocation(data); |
| | | this.searchItemLocation(data) |
| | | }, |
| | | }); |
| | | }) |
| | | } |
| | | |
| | | // 创建一个新的 Intersection Observer 实例,用于观察目标元素和执行相应的回调函数。 |
| | | // new IntersectionObserver(callback, options):使用之前定义的 callback 回调函数和 options 配置选项来初始化 Intersection Observer 实例。 |
| | | this.observer = new IntersectionObserver(this.pageChangeCallback, { |
| | | root: null, // 指定根元素,这里设为 null,表示选取整个视窗作为根元素。 |
| | | rootMargin: "0px", // 指定根元素的边界,这里设为 "0px",表示根元素的边界和视窗的边界重合 |
| | | rootMargin: '0px', // 指定根元素的边界,这里设为 "0px",表示根元素的边界和视窗的边界重合 |
| | | threshold: 0.5, // 指定交叉比例,这里设为 0.5,表示当目标元素一半或更多显示在视窗中时触发回调函数。 |
| | | }); |
| | | }) |
| | | |
| | | this.loadPageObserver = new IntersectionObserver(this.loadPageCallback, { |
| | | root: null, // 指定根元素,这里设为 null,表示选取整个视窗作为根元素。 |
| | | rootMargin: "0px", // 指定根元素的边界,这里设为 "0px",表示根元素的边界和视窗的边界重合 |
| | | rootMargin: '0px', // 指定根元素的边界,这里设为 "0px",表示根元素的边界和视窗的边界重合 |
| | | threshold: 0, // 指定交叉比例,这里设为 0.5,表示当目标元素一半或更多显示在视窗中时触发回调函数。 |
| | | }); |
| | | }) |
| | | |
| | | // 启动页码观察 |
| | | setTimeout(() => { |
| | | this.initObservation(); |
| | | this.initThemeColor(); |
| | | }, 500); |
| | | this.initObservation() |
| | | this.initThemeColor() |
| | | }, 500) |
| | | |
| | | // 测试页面跳转 |
| | | setTimeout(() => { |
| | | this.gotoPage(4, 127); |
| | | // setTimeout(() => { |
| | | // this.gotoPage(1, 41) |
| | | // setTimeout(() => { |
| | | // this.renderSign("Highlight", { |
| | | // id: "2ACA9359", |
| | |
| | | // ids: ["2ACA9359"] |
| | | // }); |
| | | // }, 2000); |
| | | // }, 5000); |
| | | //}, 5000); |
| | | |
| | | // const pageDom = (this.container ? this.container : document) |
| | | // .querySelector("#app") |
| | |
| | | // txt: " 运动系统是由骨、骨连结和骨骼肌三部分组成的。全身的骨通过骨连结组成人体骨骼(见图1-1)。骨骼是人体的支架,具有保护内脏器官、供肌肉附着和作为肌肉运动的杠杆等作用。在神经系统的支配下,肌肉收缩牵动所附着的骨绕着关节转动,使身体产生各种动作。所以,运动系统具有运动、支持和保护等功能,幼年时期的骨骼还具有造血功能。 ", |
| | | // txtIndex: 57 |
| | | // }); |
| | | }, 500); |
| | | // }, 500) |
| | | }, |
| | | methods: { |
| | | swdtChange(data) { |
| | | console.log("子应用pdf", data); |
| | | console.log('子应用pdf', data) |
| | | if (this.$store.state.qiankun && this.$store.state.qiankun.openPDF) { |
| | | if (data.type == "pdf") { |
| | | if (data.type == 'pdf') { |
| | | this.$store.state.qiankun.openPDF({ |
| | | data: data.data, |
| | | }); |
| | | }) |
| | | } else { |
| | | this.$store.state.qiankun.chooseWords({ |
| | | type: data.type, |
| | | data: data.data, |
| | | }); |
| | | }) |
| | | } |
| | | } |
| | | }, |
| | | changeDomViewer() { |
| | | this.initViewer(); |
| | | this.initViewer() |
| | | }, |
| | | // setZoom1() { |
| | | // let scale = this.$store.state.qiankun.scale + 10; |
| | |
| | | if (event.target.scrollTop > this.previousScrollTop) { |
| | | // 向下 |
| | | const currentScrollTop = |
| | | event.target.scrollTop + event.target.offsetHeight; |
| | | event.target.scrollTop + event.target.offsetHeight |
| | | if ( |
| | | currentScrollTop >= |
| | | event.target.scrollHeight - this.loadThreshold |
| | |
| | | // 加载下一章 |
| | | this.showCatalogList.push( |
| | | this.showCatalogList[this.showCatalogList.length - 1] + 1 |
| | | ); |
| | | ) |
| | | if (this.showCatalogList.length > 3) { |
| | | // 超过三章隐藏顶部一章 |
| | | this.showCatalogList.shift(); |
| | | this.showCatalogList.shift() |
| | | } |
| | | } |
| | | } |
| | | } else if (event.target.scrollTop < this.previousScrollTop) { |
| | | // 向上 |
| | | const currentScrollTop = event.target.scrollTop; |
| | | const currentScrollTop = event.target.scrollTop |
| | | if (currentScrollTop <= this.loadThreshold) { |
| | | // 到达阈值 |
| | | if (this.showCatalogList[0] > 0) { |
| | | // 加载上一章 |
| | | this.showCatalogList.unshift(this.showCatalogList[0] - 1); |
| | | this.showCatalogList.unshift(this.showCatalogList[0] - 1) |
| | | if (this.showCatalogList.length > 3) { |
| | | // 超过三章隐藏底部一章 |
| | | this.showCatalogList.pop(); |
| | | this.showCatalogList.pop() |
| | | } |
| | | } |
| | | } |
| | | } |
| | | // showCatalogList 当前显示的三个章节,watch监听传递给主应用 |
| | | // 更新上一次滚动的位置 |
| | | this.previousScrollTop = event.target.scrollTop; |
| | | this.previousScrollTop = event.target.scrollTop |
| | | }, |
| | | // 章节、页面跳转 |
| | | gotoPage(catalog, page) { |
| | | |
| | | if (catalog >= 0 && catalog <= this.catalogLength) { |
| | | // 处理渲染章节 |
| | | if (catalog == 0) { |
| | | this.showCatalogList = [0, 1]; |
| | | this.showCatalogList = [0, 1] |
| | | } else if (catalog == this.catalogLength) { |
| | | this.showCatalogList = [ |
| | | this.catalogLength - 2, |
| | | this.catalogLength - 1, |
| | | this.catalogLength, |
| | | ]; |
| | | ] |
| | | } else { |
| | | this.showCatalogList = [catalog - 1, catalog, catalog + 1]; |
| | | this.showCatalogList = [catalog - 1, catalog, catalog + 1] |
| | | } |
| | | setTimeout(() => { |
| | | // 跳转页码 |
| | | const pageDom = ( |
| | | this.container ? this.container : document |
| | | ).querySelector(`[page="${page}"]`); |
| | | ).querySelector(`[page="${page}"]`) |
| | | |
| | | if (pageDom) { |
| | | pageDom.scrollIntoView(); |
| | | pageDom.scrollIntoView() |
| | | } else { |
| | | console.log("页码错误!"); |
| | | |
| | | console.log('页码错误!') |
| | | } |
| | | }, 500); |
| | | }, 500) |
| | | } else { |
| | | console.log("章节错误!"); |
| | | console.log('章节错误!') |
| | | } |
| | | }, |
| | | |
| | |
| | | handelSignData(type, data) { |
| | | if (this.loadPageList.indexOf(Number(data.page)) > -1) { |
| | | // 立即渲染 |
| | | this.renderSign(type, data); |
| | | this.renderSign(type, data) |
| | | } |
| | | |
| | | // 储存数据 |
| | | if (!this.renderSignMap[type]) this.renderSignMap[type] = {}; |
| | | if (!this.renderSignMap[type]) this.renderSignMap[type] = {} |
| | | if (!this.renderSignMap[type][data.page]) |
| | | this.renderSignMap[type][data.page] = []; |
| | | this.renderSignMap[type][data.page].push(data); |
| | | this.renderSignMap[type][data.page] = [] |
| | | this.renderSignMap[type][data.page].push(data) |
| | | }, |
| | | |
| | | // 渲染标记 |
| | | renderSign(type, data) { |
| | | // 父层设置禁止渲染标记时不再进行渲染 |
| | | if (this.$store.state.qiankun.disableSign) { |
| | | return false; |
| | | return false |
| | | } |
| | | const existence = ( |
| | | this.container ? this.container : document |
| | | ).querySelector(`[dataid="${data.id}"]`); |
| | | ).querySelector(`[dataid="${data.id}"]`) |
| | | // 去重 |
| | | if (!existence) { |
| | | const pageDom = ( |
| | | this.container ? this.container : document |
| | | ).querySelector(`[page="${data.page}"]`); |
| | | ).querySelector(`[page="${data.page}"]`) |
| | | // 创建 createTreeWalker 迭代器,用于遍历文本节点,保存到一个数组 |
| | | const treeWalker = document.createTreeWalker( |
| | | pageDom, |
| | | NodeFilter.SHOW_TEXT |
| | | ); |
| | | const allTextNodes = []; |
| | | let currentNode = treeWalker.nextNode(); |
| | | ) |
| | | const allTextNodes = [] |
| | | let currentNode = treeWalker.nextNode() |
| | | while (currentNode) { |
| | | allTextNodes.push(currentNode); |
| | | currentNode = treeWalker.nextNode(); |
| | | allTextNodes.push(currentNode) |
| | | currentNode = treeWalker.nextNode() |
| | | } |
| | | for (let i = 0; i < allTextNodes.length; i++) { |
| | | const textDom = allTextNodes[i]; |
| | | const textDom = allTextNodes[i] |
| | | if (textDom.textContent.indexOf(data.txt) > -1) { |
| | | let reg = new RegExp(`${data.txt}`, "ig"); |
| | | let reg = new RegExp(`${data.txt}`, 'ig') |
| | | switch (type) { |
| | | case "Highlight": |
| | | case 'Highlight': |
| | | // 高亮 |
| | | textDom.parentNode.innerHTML = |
| | | textDom.parentNode.innerHTML.replace( |
| | | reg, |
| | | `<span datatype="Highlight" dataid="${data.id}" style="background: ${data.color};" class="highLight" onclick="signClick('Highlight','${data.id}','${data.chapterNum}')">${data.txt}</span>` |
| | | ); |
| | | break; |
| | | case "Dashing": |
| | | ) |
| | | break |
| | | case 'Dashing': |
| | | // 划线 |
| | | textDom.parentNode.innerHTML = |
| | | textDom.parentNode.innerHTML.replace( |
| | | reg, |
| | | `<span datatype="Dashing" dataid="${data.id}" style="text-decoration-color:${data.color};" class="underline" onclick="signClick('Dashing','${data.id}','${data.chapterNum}')">${data.txt}</span>` |
| | | ); |
| | | break; |
| | | case "Note": |
| | | ) |
| | | break |
| | | case 'Note': |
| | | // 笔记 |
| | | textDom.parentNode.innerHTML = |
| | | textDom.parentNode.innerHTML.replace( |
| | | reg, |
| | | `<span datatype="Note" dataid="${data.id}" style="border-bottom-color:${data.color}" class="notesline" onclick="signClick('Note','${data.id}','${data.chapterNum}')" onmouseover="noteHover('Note','${data.id}','${data.chapterNum}')" onmouseout="noteOut('Note')">${data.txt}<img src="${NoteIcon}"/></span>` |
| | | ); |
| | | break; |
| | | ) |
| | | break |
| | | } |
| | | } |
| | | } |
| | |
| | | delSign({ ids, type }) { |
| | | if (ids && ids.length) { |
| | | for (let i = 0; i < ids.length; i++) { |
| | | const id = ids[i]; |
| | | const id = ids[i] |
| | | const dom = ( |
| | | this.container ? this.container : document |
| | | ).querySelector(`[dataid="${id}"]`); |
| | | ).querySelector(`[dataid="${id}"]`) |
| | | dom.parentNode.innerHTML = dom.parentNode.innerHTML.replace( |
| | | dom.outerHTML, |
| | | dom.outerText |
| | | ); |
| | | ) |
| | | } |
| | | } |
| | | if (type) { |
| | | const doms = ( |
| | | this.container ? this.container : document |
| | | ).querySelectorAll(`[datatype="${type}"]`); |
| | | ).querySelectorAll(`[datatype="${type}"]`) |
| | | for (let i = 0; i < doms.length; i++) { |
| | | const dom = doms[i]; |
| | | const dom = doms[i] |
| | | dom.parentNode.innerHTML = dom.parentNode.innerHTML.replace( |
| | | dom.outerHTML, |
| | | dom.outerText |
| | | ); |
| | | ) |
| | | } |
| | | } |
| | | }, |
| | | initObservation() { |
| | | const sections = ( |
| | | this.container ? this.container : document |
| | | ).querySelectorAll(".page-box"); |
| | | ).querySelectorAll('.page-box') |
| | | sections.forEach((section) => { |
| | | if (this.config.activeBook && this.config.activeBook.tryPageCount) { |
| | | const page = section.getAttribute("page"); |
| | | const page = section.getAttribute('page') |
| | | if (Number(page) > this.config.activeBook.tryPageCount) { |
| | | let chapterDom = this.getParentWithClass(section, "chapter"); |
| | | const chapterNum = chapterDom.getAttribute("num"); |
| | | this.catalogLength = Number(chapterNum) - 1; |
| | | section.remove(); |
| | | return false; |
| | | let chapterDom = this.getParentWithClass(section, 'chapter') |
| | | const chapterNum = chapterDom.getAttribute('num') |
| | | this.catalogLength = Number(chapterNum) - 1 |
| | | section.remove() |
| | | return false |
| | | } |
| | | } |
| | | // observer 观察每个元素,以便在它们进入或离开视窗时触发回调函数。 |
| | | const isObserver = section.getAttribute("observer"); |
| | | const isLoadObserver = section.getAttribute("loadObserver"); |
| | | const isObserver = section.getAttribute('observer') |
| | | const isLoadObserver = section.getAttribute('loadObserver') |
| | | if (!isObserver) { |
| | | this.observer.observe(section); |
| | | section.setAttribute("observer", "1"); |
| | | this.observer.observe(section) |
| | | section.setAttribute('observer', '1') |
| | | } |
| | | if (!isLoadObserver) { |
| | | this.loadPageObserver.observe(section); |
| | | section.setAttribute("loadObserver", "1"); |
| | | this.loadPageObserver.observe(section) |
| | | section.setAttribute('loadObserver', '1') |
| | | } |
| | | }); |
| | | }) |
| | | }, |
| | | initThemeColor() { |
| | | // 获取各种需要主题色的节点 |
| | | const colorDom = ( |
| | | this.container ? this.container : document |
| | | ).querySelectorAll(".theme-color"); |
| | | ).querySelectorAll('.theme-color') |
| | | const backgroundColorDom = ( |
| | | this.container ? this.container : document |
| | | ).querySelectorAll(".theme-back"); |
| | | ).querySelectorAll('.theme-back') |
| | | const borderColorDom = ( |
| | | this.container ? this.container : document |
| | | ).querySelectorAll(".theme-border"); |
| | | ).querySelectorAll('.theme-border') |
| | | // 获取配置的主题色 |
| | | const bookThemeColor = |
| | | this.config.activeBook && this.config.activeBook.bookThemeColor |
| | | ? this.config.activeBook.bookThemeColor |
| | | : null; |
| | | : null |
| | | const chapterThemeColor = |
| | | this.config.activeBook && this.config.activeBook.chapterThemeColor |
| | | ? this.config.activeBook.chapterThemeColor |
| | | : null; |
| | | : null |
| | | const pageThemeColor = |
| | | this.config.activeBook && this.config.activeBook.pageThemeColor |
| | | ? this.config.activeBook.pageThemeColor |
| | | : null; |
| | | : null |
| | | colorDom.forEach((domItem) => { |
| | | // 获取章节、页码 |
| | | let pageDom = this.getParentWithClass(domItem, "page-box"); |
| | | let chapterDom = this.getParentWithClass(domItem, "chapter"); |
| | | let page, chapterNum; |
| | | if (pageDom) page = pageDom.getAttribute("page"); |
| | | if (chapterDom) chapterNum = chapterDom.getAttribute("num"); |
| | | let pageDom = this.getParentWithClass(domItem, 'page-box') |
| | | let chapterDom = this.getParentWithClass(domItem, 'chapter') |
| | | let page, chapterNum |
| | | if (pageDom) page = pageDom.getAttribute('page') |
| | | if (chapterDom) chapterNum = chapterDom.getAttribute('num') |
| | | // 向上匹配主题色 |
| | | const themeColor = |
| | | page && pageThemeColor && pageThemeColor[page] |
| | | ? pageThemeColor[page] |
| | | : chapterNum && chapterThemeColor && chapterThemeColor[chapterNum] |
| | | ? chapterThemeColor[chapterNum] |
| | | : bookThemeColor; |
| | | : bookThemeColor |
| | | if (themeColor) { |
| | | domItem.style.color = themeColor; |
| | | domItem.style.color = themeColor |
| | | } |
| | | }); |
| | | }) |
| | | backgroundColorDom.forEach((domItem) => { |
| | | // 获取章节、页码 |
| | | let pageDom = this.getParentWithClass(domItem, "page-box"); |
| | | let chapterDom = this.getParentWithClass(domItem, "chapter"); |
| | | let page, chapterNum; |
| | | if (pageDom) page = pageDom.getAttribute("page"); |
| | | if (chapterDom) chapterNum = chapterDom.getAttribute("num"); |
| | | let pageDom = this.getParentWithClass(domItem, 'page-box') |
| | | let chapterDom = this.getParentWithClass(domItem, 'chapter') |
| | | let page, chapterNum |
| | | if (pageDom) page = pageDom.getAttribute('page') |
| | | if (chapterDom) chapterNum = chapterDom.getAttribute('num') |
| | | // 向上匹配主题色 |
| | | const themeColor = |
| | | page && pageThemeColor && pageThemeColor[page] |
| | | ? pageThemeColor[page] |
| | | : chapterNum && chapterThemeColor && chapterThemeColor[chapterNum] |
| | | ? chapterThemeColor[chapterNum] |
| | | : bookThemeColor; |
| | | : bookThemeColor |
| | | if (themeColor) { |
| | | domItem.style.backgroundColor = themeColor; |
| | | domItem.style.backgroundColor = themeColor |
| | | } |
| | | }); |
| | | }) |
| | | borderColorDom.forEach((domItem) => { |
| | | // 获取章节、页码 |
| | | let pageDom = this.getParentWithClass(domItem, "page-box"); |
| | | let chapterDom = this.getParentWithClass(domItem, "chapter"); |
| | | let page, chapterNum; |
| | | if (pageDom) page = pageDom.getAttribute("page"); |
| | | if (chapterDom) chapterNum = chapterDom.getAttribute("num"); |
| | | let pageDom = this.getParentWithClass(domItem, 'page-box') |
| | | let chapterDom = this.getParentWithClass(domItem, 'chapter') |
| | | let page, chapterNum |
| | | if (pageDom) page = pageDom.getAttribute('page') |
| | | if (chapterDom) chapterNum = chapterDom.getAttribute('num') |
| | | // 向上匹配主题色 |
| | | const themeColor = |
| | | page && pageThemeColor && pageThemeColor[page] |
| | | ? pageThemeColor[page] |
| | | : chapterNum && chapterThemeColor && chapterThemeColor[chapterNum] |
| | | ? chapterThemeColor[chapterNum] |
| | | : bookThemeColor; |
| | | : bookThemeColor |
| | | if (themeColor) { |
| | | domItem.style.borderColor = themeColor; |
| | | domItem.style.borderColor = themeColor |
| | | } |
| | | }); |
| | | }) |
| | | }, |
| | | getParentWithClass(element, className) { |
| | | console.log(element, className, "element, className"); |
| | | console.log(element, className, 'element, className') |
| | | while (element.parentElement) { |
| | | element = element.parentElement; |
| | | element = element.parentElement |
| | | if (element.classList.contains(className)) { |
| | | return element; |
| | | return element |
| | | } |
| | | } |
| | | }, |
| | |
| | | entries.forEach((entry) => { |
| | | //entry.isIntersecting:检查当前目标元素是否与根元素相交。 |
| | | if (entry.isIntersecting) { |
| | | const target = entry.target; |
| | | const target = entry.target |
| | | //entry.target:获取当前目标元素 |
| | | const page = target.getAttribute("page"); |
| | | const page = target.getAttribute('page') |
| | | const catalogDom = this.tool.getParentNodeByClassName( |
| | | target, |
| | | "chapter" |
| | | ); |
| | | const catalog = catalogDom.getAttribute("num"); |
| | | let text = null; |
| | | if (target.querySelector("p")) { |
| | | text = target.querySelector("p").textContent.substring(0, 50); |
| | | 'chapter' |
| | | ) |
| | | const catalog = catalogDom.getAttribute('num') |
| | | let text = null |
| | | if (target.querySelector('p')) { |
| | | text = target.querySelector('p').textContent.substring(0, 50) |
| | | } |
| | | // 返回页码和章节信息 |
| | | if (this.$store.state.qiankun && this.$store.state.qiankun.pageChange) |
| | |
| | | page: page, |
| | | catalog: catalog, |
| | | text, |
| | | }); |
| | | }) |
| | | // const sections = Array.from(document.querySelectorAll(".section")); |
| | | //sections:获取所有具有 .section 类名的元素,并转换为数组。 |
| | | // let index = sections.findIndex((section) => section === target) + 1; |
| | | //index:查找当前目标元素在 sections 数组中的索引,并加 1,用于确定当前页码。 |
| | | } |
| | | }); |
| | | }) |
| | | }, |
| | | loadPageCallback(entries, observer) { |
| | | entries.forEach(async (entry) => { |
| | | if (entry.isIntersecting) { |
| | | const target = entry.target; |
| | | const page = target.getAttribute("page"); |
| | | const target = entry.target |
| | | const page = target.getAttribute('page') |
| | | if (this.loadPageList.indexOf(Number(page)) == -1) { |
| | | const catalogDom = this.tool.getParentNodeByClassName( |
| | | target, |
| | | "chapter" |
| | | ); |
| | | 'chapter' |
| | | ) |
| | | // 添加页码 |
| | | this.loadPageList.push(Number(page)); |
| | | const catalog = catalogDom.getAttribute("num"); |
| | | this.loadPageList.push(Number(page)) |
| | | const catalog = catalogDom.getAttribute('num') |
| | | if (!this.questionDataMap[page]) { |
| | | if (testData && testData[catalog]) { |
| | | if (testData[catalog][page]) { |
| | |
| | | page, |
| | | testData[catalog][page], |
| | | this.config.activeBook |
| | | ); |
| | | ) |
| | | } else { |
| | | const obj = {}; |
| | | const obj = {} |
| | | for (let key in testData[catalog][page]) { |
| | | obj[key] = await getQuestionList( |
| | | [], |
| | | testData[catalog][page][key], |
| | | this.config.activeBook |
| | | ); |
| | | ) |
| | | } |
| | | this.questionDataMap[page] = obj; |
| | | this.questionDataMap[page] = obj |
| | | } |
| | | } |
| | | } |
| | |
| | | for (const key in this.renderSignMap) { |
| | | if (this.renderSignMap[key][page]) { |
| | | this.renderSignMap[key][page].forEach((item) => { |
| | | this.renderSign(key, item); |
| | | }); |
| | | this.renderSign(key, item) |
| | | }) |
| | | } |
| | | } |
| | | // 处理高亮 |
| | |
| | | const pageTextList = document.createTreeWalker( |
| | | target, |
| | | NodeFilter.SHOW_TEXT |
| | | ); |
| | | ) |
| | | // 匹配关键字 |
| | | const allPageTextNodes = []; |
| | | let currentNode = pageTextList.nextNode(); |
| | | const allPageTextNodes = [] |
| | | let currentNode = pageTextList.nextNode() |
| | | while (currentNode) { |
| | | allPageTextNodes.push(currentNode); |
| | | currentNode = pageTextList.nextNode(); |
| | | allPageTextNodes.push(currentNode) |
| | | currentNode = pageTextList.nextNode() |
| | | } |
| | | for (let i = 0; i < allPageTextNodes.length; i++) { |
| | | const textDom = allPageTextNodes[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"; |
| | | 'background-color 0.8s' |
| | | textDom.parentNode.scrollIntoView() |
| | | textDom.parentNode.style.backgroundColor = '#79bbf0' |
| | | setTimeout(() => { |
| | | textDom.parentNode.style.backgroundColor = ""; |
| | | }, 1000); |
| | | textDom.parentNode.style.backgroundColor = '' |
| | | }, 1000) |
| | | } |
| | | } |
| | | }, 100); |
| | | }, 100) |
| | | } |
| | | if (this.loadPageList.length > 5) { |
| | | // 超过5页 |
| | | this.loadPageList.shift(); |
| | | this.loadPageList.shift() |
| | | } |
| | | } |
| | | } |
| | | }); |
| | | }) |
| | | }, |
| | | initSwiper() { |
| | | const doms = ( |
| | | this.container ? this.container : document |
| | | ).querySelectorAll(".swiper-img"); |
| | | ).querySelectorAll('.swiper-img') |
| | | for (let i = 0; i < doms.length; i++) { |
| | | const dom = doms[i]; |
| | | const dom = doms[i] |
| | | new Swiper(dom, { |
| | | loop: false, // 无缝 |
| | | autoplay: { |
| | |
| | | spaceBetween: 30, // 间隔 |
| | | // 如果需要前进后退按钮 |
| | | navigation: { |
| | | nextEl: dom.querySelector(".swiper-button-next"), |
| | | prevEl: dom.querySelector(".swiper-button-prev"), |
| | | nextEl: dom.querySelector('.swiper-button-next'), |
| | | prevEl: dom.querySelector('.swiper-button-prev'), |
| | | }, |
| | | // 窗口变化,重新init,针对F11全屏和放大缩小,必须加 |
| | | observer: true, |
| | |
| | | // ), |
| | | // clickable: true // 分页器可以点击 |
| | | // } |
| | | }); |
| | | }) |
| | | } |
| | | const pptDoms = ( |
| | | this.container ? this.container : document |
| | | ).querySelectorAll(".swiper_ppt"); |
| | | ).querySelectorAll('.swiper_ppt') |
| | | for (let i = 0; i < pptDoms.length; i++) { |
| | | const dom = pptDoms[i]; |
| | | const dom = pptDoms[i] |
| | | new Swiper(dom, { |
| | | loop: false, // 无缝 |
| | | autoplay: false, |
| | |
| | | spaceBetween: 30, // 间隔 |
| | | // 如果需要前进后退按钮 |
| | | navigation: { |
| | | nextEl: dom.querySelector(".swiper-button-next"), |
| | | prevEl: dom.querySelector(".swiper-button-prev"), |
| | | nextEl: dom.querySelector('.swiper-button-next'), |
| | | prevEl: dom.querySelector('.swiper-button-prev'), |
| | | }, |
| | | // 窗口变化,重新init,针对F11全屏和放大缩小,必须加 |
| | | observer: true, |
| | | observeParents: true, |
| | | on: { |
| | | init: (value) => { |
| | | let currentPage = value.activeIndex + 1; // 获取当前页(从1开始计数) |
| | | let totalPages = value.slides.length; // 获取总页数 |
| | | var paginationInfoEl = dom.querySelector(".pageBox"); |
| | | let currentPage = value.activeIndex + 1 // 获取当前页(从1开始计数) |
| | | let totalPages = value.slides.length // 获取总页数 |
| | | var paginationInfoEl = dom.querySelector('.pageBox') |
| | | if (paginationInfoEl) |
| | | paginationInfoEl.textContent = currentPage + "/" + totalPages; |
| | | paginationInfoEl.textContent = currentPage + '/' + totalPages |
| | | }, |
| | | slideChange: (value) => { |
| | | let currentPage = value.activeIndex + 1; // 获取当前页(从1开始计数) |
| | | let totalPages = value.slides.length; // 获取总页数 |
| | | var paginationInfoEl = dom.querySelector(".pageBox"); |
| | | let currentPage = value.activeIndex + 1 // 获取当前页(从1开始计数) |
| | | let totalPages = value.slides.length // 获取总页数 |
| | | var paginationInfoEl = dom.querySelector('.pageBox') |
| | | if (paginationInfoEl) |
| | | paginationInfoEl.textContent = currentPage + "/" + totalPages; |
| | | paginationInfoEl.textContent = currentPage + '/' + totalPages |
| | | }, |
| | | }, |
| | | }); |
| | | }) |
| | | } |
| | | }, |
| | | initViewer() { |
| | | const doms = ( |
| | | this.container ? this.container : document |
| | | ).querySelectorAll(".openImgBox"); |
| | | ).querySelectorAll('.openImgBox') |
| | | for (let i = 0; i < doms.length; i++) { |
| | | const dom = doms[i]; |
| | | const dom = doms[i] |
| | | new Viewer(dom, { |
| | | container: this.container |
| | | ? this.container.querySelector("#app") |
| | | : "body", |
| | | ? this.container.querySelector('#app') |
| | | : 'body', |
| | | navbar: true, // 显示导航栏 |
| | | toolbar: true, // 显示工具栏 |
| | | title: true, // 显示标题 |
| | | }); |
| | | }) |
| | | } |
| | | }, |
| | | // 根据关键字全文检索 |
| | | searchTextByPage(keyword) { |
| | | const searchResult = []; |
| | | let catalogIndex = 0; |
| | | const searchResult = [] |
| | | let catalogIndex = 0 |
| | | // 所有章节组件(每本书制作时单独配置) |
| | | const pageData = { |
| | | |
| | | pageHeader, |
| | | chapterOne, |
| | | chapterTwo, |
| | | chapterThree, |
| | | chapterFour, |
| | | assemblyOne, |
| | | assemblyTwo |
| | | }; |
| | | chapterfive, |
| | | chapterSix, |
| | | chapterSeven, |
| | | chapterEight, |
| | | chapterNine |
| | | // assemblyOne, |
| | | // assemblyTwo, |
| | | } |
| | | // 遍历所有章节文件 |
| | | for (const key in pageData) { |
| | | catalogIndex++; |
| | | let pageComponent, pageExample; |
| | | catalogIndex++ |
| | | let pageComponent, pageExample |
| | | // 先渲染一次当前章节文件(这时页面的内容为空),获取页码信息 |
| | | pageComponent = Vue.extend(pageData[key]); |
| | | pageComponent = Vue.extend(pageData[key]) |
| | | pageExample = new pageComponent({ |
| | | propsData: { |
| | | showPageList: [], |
| | | questionData: {}, |
| | | isSearch: true, |
| | | }, |
| | | }); |
| | | }) |
| | | pageExample.$mount( |
| | | (this.container ? this.container : document).querySelector( |
| | | "#searchContent" |
| | | '#searchContent' |
| | | ) |
| | | ); |
| | | ) |
| | | // 获取页码 |
| | | const pageDom = (this.container ? this.container : document) |
| | | .querySelector("#searchDomBox") |
| | | .querySelectorAll(".page-box"); |
| | | const pages = []; |
| | | .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"))); |
| | | const pageDomItem = pageDom[i] |
| | | pages.push(Number(pageDomItem.getAttribute('page'))) |
| | | } |
| | | // 获取页面结束,卸载销毁 |
| | | pageExample.$destroy(); |
| | | (this.container ? this.container : document).querySelector( |
| | | "#searchDomBox" |
| | | ).innerHTML = '<div id="searchContent"></div>'; |
| | | 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]; |
| | | const pageNum = pages[i] |
| | | // 动态渲染对应章节的页码 |
| | | pageComponent = Vue.extend(pageData[key]); |
| | | pageComponent = Vue.extend(pageData[key]) |
| | | pageExample = new pageComponent({ |
| | | propsData: { |
| | | showPageList: [pageNum], |
| | | questionData: {}, |
| | | isSearch: true, |
| | | }, |
| | | }); |
| | | }) |
| | | pageExample.$mount( |
| | | (this.container ? this.container : document).querySelector( |
| | | "#searchContent" |
| | | '#searchContent' |
| | | ) |
| | | ); |
| | | ) |
| | | // 获取对应页面dom |
| | | const thisPageDom = (this.container ? this.container : document) |
| | | .querySelector("#searchDomBox") |
| | | .querySelector(`[page="${pageNum}"]`); |
| | | .querySelector('#searchDomBox') |
| | | .querySelector(`[page="${pageNum}"]`) |
| | | if (thisPageDom) { |
| | | // 获取页面所有text节点 |
| | | const pageTextList = document.createTreeWalker( |
| | | thisPageDom, |
| | | NodeFilter.SHOW_TEXT |
| | | ); |
| | | ) |
| | | // 匹配关键字 |
| | | const allPageTextNodes = []; |
| | | let currentNode = pageTextList.nextNode(); |
| | | const allPageTextNodes = [] |
| | | let currentNode = pageTextList.nextNode() |
| | | while (currentNode) { |
| | | allPageTextNodes.push(currentNode); |
| | | currentNode = pageTextList.nextNode(); |
| | | allPageTextNodes.push(currentNode) |
| | | currentNode = pageTextList.nextNode() |
| | | } |
| | | for (let i = 0; i < allPageTextNodes.length; i++) { |
| | | const textDom = allPageTextNodes[i]; |
| | | let txtIndex = textDom.textContent.indexOf(keyword); |
| | | const textDom = allPageTextNodes[i] |
| | | let txtIndex = textDom.textContent.indexOf(keyword) |
| | | if (txtIndex > -1) { |
| | | // 记录关键字所在页码、章节以及匹配到的段落 |
| | | searchResult.push({ |
| | |
| | | catalog: catalogIndex, |
| | | txt: textDom.textContent, |
| | | txtIndex: txtIndex, |
| | | }); |
| | | }) |
| | | } |
| | | } |
| | | // 结束,卸载销毁 |
| | | pageExample.$destroy(); |
| | | (this.container ? this.container : document).querySelector( |
| | | "#searchDomBox" |
| | | ).innerHTML = '<div id="searchContent"></div>'; |
| | | pageExample.$destroy() |
| | | ; (this.container ? this.container : document).querySelector( |
| | | '#searchDomBox' |
| | | ).innerHTML = '<div id="searchContent"></div>' |
| | | } |
| | | } |
| | | } |
| | | } |
| | | // 输出搜索结果 |
| | | console.log(searchResult); |
| | | return searchResult; |
| | | console.log(searchResult) |
| | | return searchResult |
| | | }, |
| | | // 根据检索结果跳转对应位置并高亮 |
| | | searchItemLocation(data) { |
| | | // 记录高亮信息 |
| | | this.highlightData = data; |
| | | this.highlightData = data |
| | | // 跳转 |
| | | this.gotoPage(data.catalog, data.page, () => { }); |
| | | this.gotoPage(data.catalog, data.page, () => { }) |
| | | }, |
| | | readText() { |
| | | const doms = ( |
| | | this.container ? this.container : document |
| | | ).querySelectorAll(".read-aloud"); |
| | | ).querySelectorAll('.read-aloud') |
| | | for (let index = 0; index < doms.length; index++) { |
| | | const dom = doms[index]; |
| | | let id = null; |
| | | dom.addEventListener("click", (e) => { |
| | | if (e.srcElement.nodeName == "svg") { |
| | | id = dom.getAttribute("readId") |
| | | } else if (e.srcElement.nodeName == "g") { |
| | | const svgDom = e.srcElement.parentNode; |
| | | id = svgDom.getAttribute("readId"); |
| | | const dom = doms[index] |
| | | let id = null |
| | | dom.addEventListener('click', (e) => { |
| | | if (e.srcElement.nodeName == 'svg') { |
| | | id = dom.getAttribute('readId') |
| | | } else if (e.srcElement.nodeName == 'g') { |
| | | const svgDom = e.srcElement.parentNode |
| | | id = svgDom.getAttribute('readId') |
| | | } else { |
| | | const svgDom = e.srcElement.parentNode.parentNode; |
| | | id = svgDom.getAttribute("readId"); |
| | | const svgDom = e.srcElement.parentNode.parentNode |
| | | id = svgDom.getAttribute('readId') |
| | | } |
| | | const item = (this.container ? this.container : document).querySelector("#" + id).innerText; |
| | | console.log(item, 233); |
| | | |
| | | const item = ( |
| | | this.container ? this.container : document |
| | | ).querySelector('#' + id).innerText |
| | | console.log(item, 233) |
| | | }) |
| | | } |
| | | } |
| | | }, |
| | | }, |
| | | components: { |
| | | pageHeader, |
| | |
| | | chapterTwo, |
| | | chapterThree, |
| | | chapterFour, |
| | | assemblyOne, |
| | | assemblyTwo |
| | | chapterfive, |
| | | chapterSix, |
| | | chapterSeven, |
| | | chapterEight, |
| | | chapterNine |
| | | // assemblyOne, |
| | | // assemblyTwo, |
| | | // ChapterFour, |
| | | // ChapterFive, |
| | | // chapterSix, |
| | |
| | | // chapter017, |
| | | // chapter018, |
| | | }, |
| | | }; |
| | | } |
| | | </script> |