| | |
| | | ></pageHeader> |
| | | <chapterOne |
| | | @saveCharacters="saveCharacters" |
| | | @closeMiniAudio="closeMiniAudio" |
| | | v-if="showCatalogList.indexOf(2) > -1" |
| | | :showPageList="loadPageList" |
| | | ></chapterOne> |
| | |
| | | <miniAudio |
| | | :path="audioPath" |
| | | :currentTime="currentTime" |
| | | @closeMiniAudio="closeMiniAudio" |
| | | ref="audioPlayer" |
| | | ></miniAudio> |
| | | </div> |
| | |
| | | import Viewer from "viewerjs"; |
| | | import "viewerjs/dist/viewer.css"; |
| | | export default { |
| | | name: "page-main", |
| | | data() { |
| | | return { |
| | | catalogLength: 2, // 总章节数 |
| | | catalogLength: 14, // 总章节数 |
| | | showCatalogList: [], // 显示的章节 |
| | | loadThreshold: 300, // 触发加载阈值 |
| | | throttleThreshold: 100, // 节流阈值 |
| | |
| | | observer: null, |
| | | loadPageObserver: null, |
| | | loadPageList: [], |
| | | questionData: {}, |
| | | questionDataMap: {}, |
| | | renderSignMap: {}, |
| | | highlightData: null, |
| | | audioPath: "", |
| | | currentTime: null, |
| | | videoList: [], |
| | |
| | | }, 200); |
| | | }, |
| | | }, |
| | | pageZoom: { |
| | | handler(newVal, oldVal) { |
| | | const scrollBox = ( |
| | | this.container ? this.container : document |
| | | ).querySelector(".page-main"); |
| | | scrollBox.scrollTop = (scrollBox.scrollTop / oldVal) * newVal; |
| | | }, |
| | | }, |
| | | }, |
| | | mounted() { |
| | | // 默认加载章节 |
| | |
| | | // 删除笔记、高亮、划线 |
| | | delSign: (data) => { |
| | | this.delSign(data); |
| | | }, |
| | | // 全文检索 |
| | | searchBookByKeyword: (keyword) => { |
| | | return this.searchTextByPage(keyword); |
| | | }, |
| | | // 跳转检索结果位置 |
| | | jumpSearchItem: (data) => { |
| | | this.searchItemLocation(data); |
| | | }, |
| | | }); |
| | | } |
| | |
| | | // }); |
| | | // }, 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) { |
| | | // 判断向上滚动还是向下滚动 |
| | | if (event.target.scrollTop > this.previousScrollTop) { |
| | | this.getAduio(); |
| | | this.getAduio() |
| | | // 向下 |
| | | const currentScrollTop = |
| | | event.target.scrollTop + event.target.offsetHeight; |
| | |
| | | } |
| | | } |
| | | } else if (event.target.scrollTop < this.previousScrollTop) { |
| | | this.handleAudio(); |
| | | this.handleAudio() |
| | | // 向上 |
| | | const currentScrollTop = event.target.scrollTop; |
| | | if (currentScrollTop <= this.loadThreshold) { |
| | |
| | | |
| | | // 渲染标记 |
| | | renderSign(type, data) { |
| | | // 父层设置禁止渲染标记时不再进行渲染 |
| | | if (this.$store.state.qiankun.disableSign) { |
| | | return false; |
| | | } |
| | | const existence = ( |
| | | this.container ? this.container : document |
| | | ).querySelector(`[dataid="${data.id}"]`); |
| | |
| | | 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) { |
| | |
| | | }); |
| | | }, |
| | | getParentWithClass(element, className) { |
| | | console.log(element, className, "element, className"); |
| | | while (element.parentElement) { |
| | | element = element.parentElement; |
| | | if (element.classList.contains(className)) { |
| | |
| | | "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 |
| | |
| | | // this.config.activeBook |
| | | // ); |
| | | // } |
| | | // this.questionData[page] = obj; |
| | | // this.questionDataMap[page] = obj; |
| | | // } |
| | | // console.log("题目", this.questionData); |
| | | // console.log("题目", this.questionDataMap); |
| | | // } |
| | | // } |
| | | // } |
| | |
| | | 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页 |
| | |
| | | }); |
| | | } |
| | | }, |
| | | // 点击事件:将生僻单词传给 主应用 从而调用词典功能 |
| | | // 根据关键字全文检索 |
| | | searchTextByPage(keyword) { |
| | | const searchResult = []; |
| | | let catalogIndex = 0; |
| | | // 所有章节组件(每本书制作时单独配置) |
| | | const pageData = { |
| | | pageHeader, |
| | | chapterOne, |
| | | }; |
| | | // 遍历所有章节文件 |
| | | 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 = 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.highlightData = data; |
| | | // 跳转 |
| | | this.gotoPage(data.catalog, data.page, () => {}); |
| | | }, |
| | | // 点击事件:将生僻单词传给 主应用 从而调用词典功能 |
| | | saveCharacters(event, word) { |
| | | console.log("生僻字", event, word); |
| | | if (this.$store.state.qiankun && this.$store.state.qiankun.chooseWords) { |
| | |
| | | } |
| | | } |
| | | }, |
| | | // 关闭mini video |
| | | closeMiniAudio() { |
| | | this.audioPath = '' |
| | | } |
| | | }, |
| | | components: { |
| | | pageHeader, |
| | | chapterOne, |
| | | miniAudio, |
| | | miniAudio |
| | | }, |
| | | }; |
| | | </script> |