### 依赖环境
* node \>=16.0.0
* npm \>=6.14.13
* vue 2.0
* jquery ^3.6.3
* xe-utils ^3.5.6
* element-ui ^2.15.9
### 阅读器对接流程
1. 部署数字教材包
2. 解析数字教材包中的localViewData.js文件
3. 将教材目录信息入库
6. 添加授课资源
7. 查询授课资源列表
### 分工(包含学生PC端、学生移动端、教师PC端)
#### 斯麦尔
1. 数字教材包的加解密
2. 数字教材包离线阅读解密
3. 数字教材内容展示
4. 数字教材页面交互,包括:目录、书签、笔记、高亮、授课资源。(业务平台提供数据接口)
6. 数字教材授课资源交互,包括:资源上传、教师笔记添加、资源展示、资源与教材关联。(业务平台提供数据接口,业务平台提供教师资源阅读服务)
7. 多类数字教材阅读行为回传。(业务平台提供数据接口)
#### 业务方
1. 数字教材包上传、解密
2. 将教材目录信息入库
3. 解析数字教材包中的localViewData.js文件
4. 教师资源阅读服务(图片、音频、视频、WORD、EXCEL、PPT、PDF)
5. 教师资源文件上传、数据存储
6. 阅读器与业务系统[交互接口](#所需接口)
### 所需接口
1. 笔记添加、编辑、删除、列表查询(学生)
2. 授课资源添加、编辑、删除、列表查询(教师)
3. 高亮添加、删除、列表查询(可根据教材内容排序)
4. 书签添加、删除、列表查询
5. 文件上传
7. 授课资源列表查询
14. 教师资源下载
15. 授课资源阅读服务(WORD、EXCEL、PPT、PDF)
16. 更新用户学习次数、学习时长
### 引入组件
##### 1.组件包形式引用

~~~
在src文件夹中新建plugin文件夹,将组件包解压到plugin文件夹
~~~
在 main.js 中写入以下内容:
~~~javascript
import Vue from 'vue'
import XML from "./plugin/xml-digital-teaching/lib/index";
import "./plugin/xml-digital-teaching/lib/theme/index.css";
import App from './App.vue'
Vue.use(XML)
new Vue({
render: h => h(App),
}).$mount('#app')
~~~
### 组件
#### xmlDigitalTeaching
数字教材阅读器组件,用于渲染数字教材
##### 代码示例
~~~vue
这是标题
\"}}, \"extendParams\": {}}, \"xmlCompRef\": \"titleFirst0.15542352103317736\", \"componentsName\": \"titleFirst\"}, {\"data\": {\"pGroupData\": {\"imageData\": {\"imageList\": [{\"link\": \"\", \"title\": \"开发-2-背景\", \"source\": \"upload\", \"content\": \"说明\", \"uploadFileUrl\": \"./image/5fdb8395-fc66-44e3-91e6-e6167af9677c.jpg\"}], \"imageMode\": \"dan-tu\", \"showEffect\": \"hua-lang\", \"clickEffect\": \"dian-ji-fang-da\"}}, \"extendParams\": {}}, \"xmlCompRef\": \"xml-single-image-group0.9871052058974397\", \"componentsName\": \"xml-single-image-group\"}, {\"data\": {\"pGroupData\": {\"musicData\": {\"playMode\": \"dan-ci\", \"playStyle\": \"yuan-wen\", \"musicSetList\": [{\"link\": \"\", \"title\": \"周杰伦-红尘客栈\", \"source\": \"upload\", \"content\": \"内容\", \"materialId\": \"\", \"coverFileUrl\": \"./defaultCover/audio-player.png\", \"uploadFileUrl\": \"./audio/c69259f3-7bd0-4ab8-ba33-6ff626811829.mp3\"}], \"scheduleControl\": \"yes\"}}, \"extendParams\": {}}, \"xmlCompRef\": \"xml-single-music-group0.4729416469673975\", \"componentsName\": \"xml-single-music-group\"}, {\"data\": {\"pGroupData\": {\"videoData\": {\"link\": \"\", \"playMode\": \"xun-huan\", \"playStyle\": \"yuan-wen\", \"videoSetList\": [{\"link\": \"\", \"title\": \"1659943488674121\", \"source\": \"upload\", \"content\": \"内容\", \"materialId\": \"\", \"coverFileUrl\": \"\", \"uploadFileUrl\": \"./video/2d4e8a72-ab40-4e54-b213-41bc3a17e055.mp4\"}], \"scheduleControl\": \"yes\"}}, \"extendParams\": {}}, \"xmlCompRef\": \"xml-single-video-group0.9655721950423428\", \"componentsName\": \"xml-single-video-group\"}, {\"data\": {\"pGroupData\": {\"resourceData\": {\"resourceType\": \"zhan-nei\", \"resourceSetList\": [{\"link\": \"\", \"title\": \"java\", \"source\": \"upload\", \"content\": \"内容\", \"fileSize\": 26163, \"fileFormat\": \"zip\", \"materialId\": \"\", \"coverFileUrl\": \"./defaultCover/pdf-resource.png\", \"uploadFileUrl\": \"./resource/f76b7c64-57dc-4d6f-9fc2-88fc189def15.zip\"}]}}, \"extendParams\": {}}, \"xmlCompRef\": \"xml-single-resource-group0.6167344288655028\", \"componentsName\": \"xml-single-resource-group\"}, {\"data\": {\"pGroupData\": {\"ebookData\": {\"ebookSetList\": [{\"isbn\": \"isbn\", \"link\": \"\", \"name\": \"新冠诊疗方案-第9版\", \"author\": \"作者\", \"source\": \"upload\", \"content\": \"内容\", \"publisher\": \"出版社\", \"fileFormat\": \"pdf\", \"materialId\": \"\", \"coverFileUrl\": \"./defaultCover/epub.png\", \"uploadFileUrl\": \"./ebook/dbb05383-520c-4ff4-801c-c3bdd219c271.pdf\"}], \"resourceType\": \"inside\"}}, \"extendParams\": {}}, \"xmlCompRef\": \"xml-single-ebook-group0.12258282282201893\", \"componentsName\": \"xml-single-ebook-group\"}]", "looseLeafModule":"1", "looseLeafName":null, "looseLeafType":null, "params":{}, "remark":null, "searchValue":null, "submitTime":null, "tmpLooseId":null, "updateBy":"1", "updateByName":null, "updateTime":"2023-01-12 13:55:38" } } ~~~ ###### newLocation ~~~json { location: '', //当前阅读位置 schedule: '', //当前阅读进度 learningTime: '', //本次学习时长 learningDuration: '' //总学习时长 } ~~~ ###### notesInfo ~~~json { blockIndex: 6, //选中内容块在教材中的索引 chapterOrderNum: 2, //章排序字段 id: 1717740841473, //主键 location: 'xml-digital-teaching/1780053976781262849/paragraphRedtheme50.4890346943653967', //所在块的位置信息(章id+块id+段id) locationChapterId: '1780053976781262849', //所在章节id markEfiCode: 'mark(0/0:112,0/0:125)', //选中内容 markId: 'mark__2f63d588-f672-4a07-9541-c964b292e9a6', //笔记标记id noteContent: '输入的笔记内容', selectionText: '理论与实践、智能车竞赛任务', styleType: 'mk-underline__dashed', textOrderNum: '6000000000112',//选中内容排序字段 topChapterId: '1780053976781262849', //所在章节一级目录id topChapterLabel: '内容简介', type: 'note__student' } ~~~ ###### notesList ~~~json [{ blockIndex: 6, chapterOrderNum: 2, id: 1717740841473, location: 'xml-digital-teaching/1780053976781262849/paragraphRedtheme50.4890346943653967', locationChapterId: '1780053976781262849', markEfiCode: 'mark(0/0:112,0/0:125)', markId: 'mark__2f63d588-f672-4a07-9541-c964b292e9a6', noteContent: '输入的笔记内容', selectionText: '理论与实践、智能车竞赛任务', styleType: 'mk-underline__dashed', textOrderNum: '6000000000112', topChapterId: '1780053976781262849', topChapterLabel: '内容简介', type: 'note__student' }, { blockIndex: 6, chapterOrderNum: 2, id: 1717740841473, location: 'xml-digital-teaching/1780053976781262849/paragraphRedtheme50.4890346943653967', locationChapterId: '1780053976781262849', markEfiCode: 'mark(0/0:112,0/0:125)', markId: 'mark__2f63d588-f672-4a07-9541-c964b292e9a6', noteContent: '输入的笔记内容', selectionText: '理论与实践、智能车竞赛任务', styleType: 'mk-underline__dashed', textOrderNum: '6000000000112', topChapterId: '1780053976781262849', topChapterLabel: '内容简介', type: 'note__student' }] ~~~ ###### bookmarkInfo ~~~json { bookmarkId: 1717740959575, bookmarkText: '版权信息', chapterId: '1780053976143728640', chapterOrderNum: 2, classId: '', creationTime: '2024-06-07T06:15:59.575Z', firstLevelId: '1780053976143728640', firstLevelLabel: '版权信息', id: 1717740959575, location: 'xml-digital-teaching/1780053976143728640/splitlineTwentythreeLibrary0.5093659374044828', locationChapterId: '1780053976781262849', orderNum: 2, type: 'bookmark' } ~~~ ###### bookmarkList ~~~json [{ bookmarkId: 1717740959575, bookmarkText: '版权信息', chapterId: '1780053976143728640', chapterOrderNum: 2, classId: '', creationTime: '2024-06-07T06:15:59.575Z', firstLevelId: '1780053976143728640', firstLevelLabel: '版权信息', id: 1717740959575, location: 'xml-digital-teaching/1780053976143728640/splitlineTwentythreeLibrary0.5093659374044828', locationChapterId: '1780053976781262849', orderNum: 2, type: 'bookmark' },{ bookmarkId: 1717740959575, bookmarkText: '版权信息', chapterId: '1780053976143728640', chapterOrderNum: 2, classId: '', creationTime: '2024-06-07T06:15:59.575Z', firstLevelId: '1780053976143728640', firstLevelLabel: '版权信息', id: 1717740959575, location: 'xml-digital-teaching/1780053976143728640/splitlineTwentythreeLibrary0.5093659374044828', locationChapterId: '1780053976781262849', orderNum: 2, type: 'bookmark' }] ~~~ ###### highlightInfo ~~~json { blockIndex: 8, chapterOrderNum: 3, id: 1717741063393, location: 'xml-digital-teaching/1780053977133584385/xml-single-text-group0.3489658035103893', locationChapterId: '1780053977133584385', markEfiCode: 'mark(1/0:104,1/0:120)', markId: 'mark__ab53333b-07a7-4318-bd7c-b20d492103cf', selectionText: '汽车为研究对象的创意性科技竞赛,', styleType: 'mk-hightlight__default', textOrderNum: '8000001000104', topChapterId: '1780053977133584385', topChapterLabel: '前言', type: 'highlight__student' } ~~~ ###### highlightList ~~~json [{ blockIndex: 8, chapterOrderNum: 3, id: 1717741063393, location: 'xml-digital-teaching/1780053977133584385/xml-single-text-group0.3489658035103893', locationChapterId: '1780053977133584385', markEfiCode: 'mark(1/0:104,1/0:120)', markId: 'mark__ab53333b-07a7-4318-bd7c-b20d492103cf', selectionText: '汽车为研究对象的创意性科技竞赛,', styleType: 'mk-hightlight__default', textOrderNum: '8000001000104', topChapterId: '1780053977133584385', topChapterLabel: '前言', type: 'highlight__student' },{ blockIndex: 8, chapterOrderNum: 3, id: 1717741063393, location: 'xml-digital-teaching/1780053977133584385/xml-single-text-group0.3489658035103893', locationChapterId: '1780053977133584385', markEfiCode: 'mark(1/0:104,1/0:120)', markId: 'mark__ab53333b-07a7-4318-bd7c-b20d492103cf', selectionText: '汽车为研究对象的创意性科技竞赛,', styleType: 'mk-hightlight__default', textOrderNum: '8000001000104', topChapterId: '1780053977133584385', topChapterLabel: '前言', type: 'highlight__student' }] ~~~ ###### testPaperInfo ~~~json { paperName: "试卷名称", resourcesType:"paper", location: "添加资源的位置信息", textBookId: "教材Id", chapterId:"章节Id", orderNum:"排序字段" questionList: [{ //单选题 "data": { "pGroupData": { "questionData": { "showAnswer": "true", "showAnalysis": "true", "showRecommend": "true", "questionSetList": [{ "id": //试题id, "stem": { "content": 题干, "fileInfo": { "fileUrl": //题干的文件路径, "duration": //音频或者视频的时长, "fileName": //文件名, "fileType": "video/mp4" //文件类型, "fileSuffix": "mp4" //文件后缀 } }, "fileUrl": //文件地址, "analysis": { "content": //解析内容, "fileInfo": { "fileUrl": //解析文件路径 "duration": //音频或者视频的时长, "fileName": //文件名, "fileType": "video/mp4" //文件类型, "fileSuffix": "mp4" //文件后缀 } }, "duration": //音频时长, "fileName": //文件名, "fileType": //文件类型, "subjectId": "", "fileSuffix": //文件后缀, "includeAudio": "1", "questionType": "2", "answerSequence": "", "questionOption": [{ "title": "A", "content": 选项内容, "fileInfo": { "fileUrl": 文件地址, "duration": //音频或者视频的时长, "fileName": //文件名, "fileType": "video/mp4" //文件类型, "fileSuffix": "mp4" //文件后缀 } }, { "title": "B", "content": 选项内容, "fileInfo": { "duration": //音频或者视频的时长, "fileName": //文件名, "fileType": "video/mp4" //文件类型, "fileSuffix": "mp4" //文件后缀 } }, { "title": "C", "content": 选项内容, "fileInfo": { "duration": //音频或者视频的时长, "fileName": //文件名, "fileType": "video/mp4" //文件类型, "fileSuffix": "mp4" //文件后缀 } }, { "title": "D", "content": 选项内容, "fileInfo": { "duration": //音频或者视频的时长, "fileName": //文件名, "fileType": "video/mp4" //文件类型, "fileSuffix": "mp4" //文件后缀 } }], "standardAnswer": [{ "title": "A", "content": 标答内容, "fileInfo": { "fileUrl": //文件地址, "duration": //音频或者视频的时长, "fileName": //文件名, "fileType": "video/mp4" //文件类型, "fileSuffix": "mp4" //文件后缀 } }], "playbackControl": "0", "knowledgePointVoList": [] }] } }, "extendParams": {} }, }, { //多选题 "data": { "pGroupData": { "questionData": { "showAnswer": "true", "showAnalysis": "true", "showRecommend": "true", "questionSetList": [{ "id": //试题id, "stem": { "content": 题干, "fileInfo": { "fileUrl": //题干的文件路径, "duration": //音频或者视频的时长, "fileName": //文件名, "fileType": "video/mp4" //文件类型, "fileSuffix": "mp4" //文件后缀 } }, "fileUrl": //文件地址, "analysis": { "content": //解析内容, "fileInfo": { "fileUrl": //解析文件路径 "duration": //音频或者视频的时长, "fileName": //文件名, "fileType": "video/mp4" //文件类型, "fileSuffix": "mp4" //文件后缀 } }, "duration": //音频时长, "fileName": //文件名, "fileType": //文件类型, "subjectId": "", "fileSuffix": //文件后缀, "includeAudio": "1", "questionType": "2", "answerSequence": "", "questionOption": [{ "title": "A", "content": 选项内容, "fileInfo": { "fileUrl": 文件地址, "duration": //音频或者视频的时长, "fileName": //文件名, "fileType": "video/mp4" //文件类型, "fileSuffix": "mp4" //文件后缀 } }, { "title": "B", "content": 选项内容, "fileInfo": { "duration": //音频或者视频的时长, "fileName": //文件名, "fileType": "video/mp4" //文件类型, "fileSuffix": "mp4" //文件后缀 } }, { "title": "C", "content": 选项内容, "fileInfo": { "duration": //音频或者视频的时长, "fileName": //文件名, "fileType": "video/mp4" //文件类型, "fileSuffix": "mp4" //文件后缀 } }, { "title": "D", "content": 选项内容, "fileInfo": { "duration": //音频或者视频的时长, "fileName": //文件名, "fileType": "video/mp4" //文件类型, "fileSuffix": "mp4" //文件后缀 } }], "standardAnswer": [{ "title": "A", "content": 标答内容, "fileInfo": { "fileUrl": //文件地址, "duration": //音频或者视频的时长, "fileName": //文件名, "fileType": "video/mp4" //文件类型, "fileSuffix": "mp4" //文件后缀 } }, { "title": "C", "content": //标答内容, "fileInfo": { "fileUrl": //文件地址, "duration": //音频或者视频的时长, "fileName": //文件名, "fileType": "video/mp4" //文件类型, "fileSuffix": "mp4" //文件后缀 } }, { "title": "D", "content": //标答内容, "fileInfo": { "fileUrl": //文件地址, "duration": //音频或者视频的时长, "fileName": //文件名, "fileType": "video/mp4" //文件类型, "fileSuffix": "mp4" //文件后缀 } }], "playbackControl": "0", "knowledgePointVoList": [] }] } }, "extendParams": {} }, }, { //判断题 "data": { "pGroupData": { "questionData": { "showAnswer": "true", "showAnalysis": "true", "showRecommend": "true", "questionSetList": [{ "id": //试题id, "stem": { "content": //题干内容, "fileInfo": { "fileUrl": //文件地址, "duration": //音频或者视频的时长, "fileName": //文件名, "fileType": "video/mp4" //文件类型, "fileSuffix": "mp4" //文件后缀 } }, "fileUrl": 文件路径, "analysis": { "content": 解析内容, "fileInfo": { "fileUrl": //解析文件地址, "duration": //音频或者视频的时长, "fileName": //文件名, "fileType": "video/mp4" //文件类型, "fileSuffix": "mp4" //文件后缀 } }, "fileType": //类型, "subjectId": "", "fileSuffix": //文件后缀, "includeAudio": "1", "questionType": "3", "answerSequence": "", "questionOption": "[]", "standardAnswer": ["正确"] //标答, "playbackControl": "0", "knowledgePointVoList": [] }] } }, "extendParams": {} }, }, { //简答题 "data": { "pGroupData": { "questionData": { "showAnswer": "true", "showAnalysis": "true", "showRecommend": "true", "questionSetList": [{ "id": //试题id, "stem": { "content": 题干内容, "fileInfo": { "fileUrl": //文件地址, "duration": //音频或者视频的时长, "fileName": //文件名, "fileType": "video/mp4" //文件类型, "fileSuffix": "mp4" //文件后缀 } }, "fileUrl": //文件地址, "analysis": { "content": //解析内容, "fileInfo": { "fileUrl": //解析文件地址, "duration": //音频或者视频的时长, "fileName": //文件名, "fileType": "video/mp4" //文件类型, "fileSuffix": "mp4" //文件后缀 } }, "duration": //音频或者视频的时长, "fileName": //文件名, "fileType": //文件类型, "subjectId": "", "fileSuffix": //后缀, "includeAudio": "1", "questionType": "13", "answerSequence": "", "questionOption": "[]", "standardAnswer": { "content": 标答内容 "fileInfo": { "fileUrl": //文件地址, "duration": //音频或者视频的时长, "fileName": //文件名, "fileType": "video/mp4" //文件类型, "fileSuffix": "mp4" //文件后缀 } }, "playbackControl": "0", "knowledgePointVoList": [] }] } }, "extendParams": {} }, }, { //填空题 "data": { "pGroupData": { "questionData": { "showAnswer": "true", "showAnalysis": "true", "showRecommend": "true", "questionSetList": [{ "id": 试题id, "stem": { "content": 题干 ", "fileInfo": { "fileUrl": //文件地址, "duration": //音频或者视频的时长, "fileName": //文件名, "fileType": "video/mp4" //文件类型, "fileSuffix": "mp4" //文件后缀 } }, "fileUrl": //文件地址, "analysis": { "content": 解析内容, "fileInfo": { "fileUrl": //解析文件地址, "duration": //音频或者视频的时长, "fileName": //文件名, "fileType": "video/mp4" //文件类型, "fileSuffix": "mp4" //文件后缀 } }, "duration": //音频或者视频的时长, "fileName": //文件名, "fileType": "video/mp4" //文件类型, "subjectId": "", "fileSuffix": "mp4" //文件后缀, "includeAudio": "1", "questionType": "10", "answerSequence": "A,B;", "questionOption": "[]", "standardAnswer": [{ "title": "A", "content": //选项内容, "fileInfo": {} }, { "title": "B", "content": //选项内容, "fileInfo": {} }], "playbackControl": "0", "knowledgePointVoList": [] }] } }, "extendParams": {} }, } ] } ~~~ ###### resourcesInfo ~~~json { blockIndex: 28, chapterId: '7038441430792015872', chapterOrderNum: 4, creationTime: '2024-06-07T06:20:11.119Z', duration: 0, fileExt: 'jpg', fileUrl: 'https://cmp-uploadfile-dev.oss-cn-beijing.aliyuncs.com/teaching_material/16574/7027199990597632.jpg', firstLevelId: '1607971683998171136', firstLevelLabel: '项目一 工业机器人概述', id: 1717741211119, isDownload: 0, isStudentShow: 0, location: 'xml-digital-teaching/7038441430792015872/xml-single-text-group0.7097987508783292', locationChapterId: '1607971683998171136', markEfiCode: 'mark(2/0/0:56,2/0/0:71)', markId: 'mark__96d6b7b0-0c25-42cd-8244-c2a4a997b964', noteContent: '', orderNum: 0, resourcesName: '40.jpg', resourcesType: 'image', selectionText: '美国机器人协会给机器人下的定义', textBookId: '1607971683880730624', textOrderNum: '28000002000056', type: 'note__teacher' } ~~~ ###### resourcesList ~~~json [{ blockIndex: 28, chapterId: '7038441430792015872', chapterOrderNum: 4, creationTime: '2024-06-07T06:20:11.119Z', duration: 0, fileExt: 'jpg', fileUrl: 'https://cmp-uploadfile-dev.oss-cn-beijing.aliyuncs.com/teaching_material/16574/7027199990597632.jpg', firstLevelId: '1607971683998171136', firstLevelLabel: '项目一 工业机器人概述', id: 1717741211119, isDownload: 0, isStudentShow: 0, location: 'xml-digital-teaching/7038441430792015872/xml-single-text-group0.7097987508783292', locationChapterId: '1607971683998171136', markEfiCode: 'mark(2/0/0:56,2/0/0:71)', markId: 'mark__96d6b7b0-0c25-42cd-8244-c2a4a997b964', noteContent: '', orderNum: 0, resourcesName: '40.jpg', resourcesType: 'image', selectionText: '美国机器人协会给机器人下的定义', textBookId: '1607971683880730624', textOrderNum: '28000002000056', type: 'note__teacher' },{ blockIndex: 28, chapterId: '7038441430792015872', chapterOrderNum: 4, creationTime: '2024-06-07T06:20:11.119Z', duration: 0, fileExt: 'jpg', fileUrl: 'https://cmp-uploadfile-dev.oss-cn-beijing.aliyuncs.com/teaching_material/16574/7027199990597632.jpg', firstLevelId: '1607971683998171136', firstLevelLabel: '项目一 工业机器人概述', id: 1717741211119, isDownload: 0, isStudentShow: 0, location: 'xml-digital-teaching/7038441430792015872/xml-single-text-group0.7097987508783292', locationChapterId: '1607971683998171136', markEfiCode: 'mark(2/0/0:56,2/0/0:71)', markId: 'mark__96d6b7b0-0c25-42cd-8244-c2a4a997b964', noteContent: '', orderNum: 0, resourcesName: '40.jpg', resourcesType: 'image', selectionText: '美国机器人协会给机器人下的定义', textBookId: '1607971683880730624', textOrderNum: '28000002000056', type: 'note__teacher' } ] ~~~ ###### fileInfo: ~~~json { content:'', coverFileUrl:'', fileFormat:'', fileSize:'', link:'', materialId:'', source:'', title:'', uploadFileUrl:'' } ~~~