### 依赖环境

- 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. 将教材目录信息入库
4. 添加授课资源
5. 查询授课资源列表

### 分工（包含学生 PC 端、学生移动端、教师 PC 端）

#### 斯麦尔

1. 数字教材包的加解密
2. 数字教材包离线阅读解密
3. 数字教材内容展示
4. 数字教材页面交互，包括：目录、书签、笔记、高亮、授课资源。（业务平台提供数据接口）
5. 数字教材授课资源交互，包括：资源上传、教师笔记添加、资源展示、资源与教材关联。（业务平台提供数据接口，业务平台提供教师资源阅读服务）
6. 多类数字教材阅读行为回传。（业务平台提供数据接口）

#### 业务方

1. 数字教材包上传、解密

2. 将教材目录信息入库

3. 解析数字教材包中的 localViewData.js 文件

4. 教师资源阅读服务（图片、音频、视频、WORD、EXCEL、PPT、PDF）

5. 教师资源文件上传、数据存储

6. 阅读器与业务系统[交互接口](#所需接口)

### 所需接口

1. 笔记添加、编辑、删除、列表查询（学生）
2. 授课资源添加、编辑、删除、列表查询（教师）
3. 高亮添加、删除、列表查询（可根据教材内容排序）
4. 书签添加、删除、列表查询
5. 文件上传
6. 授课资源列表查询
7. 教师资源下载
8. 授课资源阅读服务（WORD、EXCEL、PPT、PDF）
9. 更新用户学习次数、学习时长

### 引入组件

##### 1.组件包形式引用

![image-20230110174057846](C:\Users\FYF\AppData\Roaming\Typora\typora-user-images\image-20230110174057846.png)

```
在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

数字教材阅读器组件，用于渲染数字教材

<img src="I:\国开\代码\digital-textbook-web\packages\xml-components\noteImages\image-20230110085842152.png" style="zoom: 80%;" />

##### 代码示例

```vue
<template>
  <div class="xml-read">
    <xml-digital-teaching
      v-if="digitalTeaching"
      ref="xmlDigitalTeaching"
      :textBookData="textBookData"
      :catalogList="catalogList"
      :looseLeafData="looseLeafData"
      :location="location"
      :notesList="data.notes.list"
      :bookmarkList="data.bookmark.list"
      :resourcesList="data.resources.list"
      :highlightList="data.highlight.list"
      :isTrial="isTrial"
      :isTrialIndex="isTrialIndex"
      :userType="userType"
      :setting="setting"
      @updateReadLocation="updateReadLocation"
      @addNote="addNote"
      @editNote="editNote"
      @deleteNote="deleteNote"
      @deleteHighlight="deleteHighlight"
      @addTeacherNote="addTeacherNote"
      @editTeacherNote="editTeacherNote"
      @deleteTeacherNote="deleteTeacherNote"
      @addHighlight="addHighlight"
      @updateNotes="updateNotes"
      @addBookmark="addBookmark"
      @deleteBookmark="deleteBookmark"
      @downloadFile="downloadFile"
      @addResources="addResources"
      @deleteResource="deleteResource"
      @editResources="editResources"
      @settingChange="settingChange"
      :action="action"
      :headers="headers"
      :isShowTeacherResource="true"
      :continueReading="true"
      :basisPath="basisPath"
      :pageType="pageType"
      :isOpenStudy="true"
      officePreviewPath="https://idocview.xxxxxxx.com/view/url?url="
    />
  </div>
</template>

<script>
export default {
  data() {
    return {
      action: 'http://60.xxxx.137.15:8081/admin-api/teachingMaterial/resource/upload/16550/6940601956829184',
      headers: {
        Authorization: `eyJhbGciOiJIUzUxMiJ9.eyJsb2dpbl91c2VyX2tleSI6IjYyMDFlYjA3LTY4ZWUtNGJhOC1iMjc3LTk4MjU0ZGI0MzUwMSJ9.zvW8Rr8ShOvwH5i7Cvl9bgp4MtznyLusrY86LMLW7MplNOjRp6j8lx6zkAD4_CvNXVF7v7MsYcRhN90DvhTq1g`
      },
      digitalTeaching: true,
      textBookData: LOCAL_VIEW_DETAIL,
      catalogList: LOCAL_VIEW_CATALOG,
      looseLeafData: LOCAL_VIEW_DATA,
      location: '',
      basisPath: 'https://www.xxxxx.com/file/1685523466073/',
      pageType: 'pc',
      isTrial: false,
      isTrialIndex: 10,
      userType: 'teacher',
      data: {
        notes: {
          list: []
        },
        bookmark: {
          list: []
        },
        highlight: {
          list: []
        },
        resources: {
          list: []
        }
      },
      setting: {}
    }
  },

  created() {
    this.userType = this.$route.query.userType || 'student'
    if (this.$route.query.type) {
      this.pageType = this.$route.query.type
      // this.isTrialIndex = Number(this.$route.query.isTrialIndex)
      if (this.$route.query.isTrialIndex) {
        this.isTrial = true
      }
    }

    this.location = localStorage.getItem(this.textBookData.id)
    setTimeout(() => {
      this.getData()
      // this.getSetting()
    }, 800)
  },

  methods: {
    // 学生笔记操作 start
    addNote(model) {
      this.addData('notes', model)
    },
    editNote(model) {
      this.updateData('notes', model)
    },
    deleteNote(model, feedback) {
      this.deleteData('notes', model)
      feedback()
    },

    // 教师笔记操作 start
    addTeacherNote(model, rollback) {
      this.addData('resources', model)
    },
    editTeacherNote(model) {
      this.updateData('resources', model)
    },
    deleteTeacherNote(model, feedback) {
      this.deleteData('resources', model)
      feedback()
    },

    // 高亮操作
    addHighlight(model, rollback) {
      this.addData('highlight', model)
    },
    // 高亮删除
    deleteHighlight(model, rollback) {
      this.deleteData('highlight', model)
      console.log(model, 'model')
    },

    settingChange(key, value) {
      // let newSetting = Object.assign({}, this.setting, { [key]: value })
      // localStorage.setItem('setting_#_' + this.textBookData.id, JSON.stringify(newSetting))
      // this.setting = JSON.parse(localStorage.getItem('setting_#_' + this.textBookData.id)) || {}
    },

    // 更新笔记
    updateNotes(model) {
      this.updateData('notes', model)
    },

    // 添加书签
    addBookmark(e) {
      this.addData('bookmark', e)
    },

    // 删除书签
    deleteBookmark(e) {
      this.deleteData('bookmark', e)
    },

    // 添加数据
    addData(type, item) {
      this.data[type].list.push(item)
      let list = JSON.stringify(this.data)
      localStorage.setItem('simulated-data_' + this.textBookData.id, list)
      this.getData(type, item)
    },

    // 查询数据
    getData(type, item) {
      setTimeout(() => {
        this.data = JSON.parse(localStorage.getItem('simulated-data_' + this.textBookData.id)) || {
          notes: {
            list: []
          },
          bookmark: {
            list: []
          },
          highlight: {
            list: []
          },
          resources: {
            list: []
          }
        }
      }, 300)
    },
    getSetting() {
      this.setting = JSON.parse(localStorage.getItem('setting_#_' + this.textBookData.id)) || {}
    },

    // 更新数据
    updateData(type, item) {
      console.log(item)
      let i = this.data[type].list.findIndex((items) => items.id == item.id)
      this.data[type].list[i] = item
      let list = JSON.stringify(this.data)
      localStorage.setItem('simulated-data_' + this.textBookData.id, list)
      this.getData(type, item)
    },

    // 删除数据
    deleteData(type, item) {
      console.log(item, 'deleteData')
      let i = this.data[type].list.findIndex((items) => items.id == item.id)
      this.data[type].list.splice(i, 1)
      let list = JSON.stringify(this.data)
      localStorage.setItem('simulated-data_' + this.textBookData.id, list)
      this.getData(type, item)
    },

    // 下载资源文件
    downloadFile(e) {},

    // 更新阅读进度
    updateReadLocation(newLocation) {
      localStorage.setItem(this.textBookData.id, newLocation.location)
    },

    // 添加教师资源
    addResources(e) {
      this.addData('resources', e)
    },
    // 删除教师资源
    deleteResource(e) {
      this.deleteData('resources', e)
    },
    // 编辑教师资源
    editResources(e) {
      this.updateData('resources', e)
    }
  }
}
</script>
```

##### 参数说明

| 参数                                 | 说明                                                          | 类型    | 默认值                      |
| ------------------------------------ | ------------------------------------------------------------- | ------- | --------------------------- |
| systemEnvId                          | 使用阅读器系统 ID，由斯麦尔提供                               | String  | 无                          |
| navBarHeight                         | 业务系统导航栏高度                                            | Number  | 0                           |
| classId                              | 班级唯一标识                                                  | String  | 无                          |
| gradesName                           | 班级名称                                                      | String  | 无                          |
| userType                             | 用户类型，可选 teacher、student                               | String  | student                     |
| isShowTeacherResource                | 是否显示教师资源                                              | Boolean | false                       |
| learningDuration                     | 已学习总时长                                                  | Number  | 0                           |
| [textBookData](#textBookData.json)   | 教材详细信息                                                  | Object  | 无                          |
| [catalogList](#catalogList.json)     | 教材目录列表                                                  | Array   | 无                          |
| [looseLeafData](#looseLeafData.json) | 所有活页信息                                                  | Object  | 无                          |
| basisPath                            | 资源文件在服务器基础路径                                      | String  | 无                          |
| location                             | 阅读开始位置                                                  | String  | 无                          |
| [notesList](#notesList)              | 笔记列表                                                      | Array   | 无                          |
| highlightList                        | 高亮列表                                                      | Array   | 无                          |
| [bookmarkList](#bookmarkList)        | 书签列表                                                      | Array   | 无                          |
| [highlightList](#highlightList)      | 高亮列表                                                      | Array   | 无                          |
| [resourcesList](#resourcesList)      | 授课资源列表                                                  | Array   | 无                          |
| pageType                             | 页面类型 h5、pc、pad                                          | String  | h5                          |
| loadingMode                          | 阅读模式可选 roll：无限滚动、page：按章节                     | String  | roll                        |
| catalogLevel                         | 目录显示的最小层级                                            | Number  | 3                           |
| isTrial                              | 是否为试读模式                                                | Boolean | false                       |
| isTrialIndex                         | 试读百分比                                                    | Number  | 10                          |
| trialChapterList                     | 可试读的章节，isTrialIndex 传 0 时生效，['xxxxx']             | Array   | 无                          |
| chapterId                            | 打开教材指定章节，章节 ID                                     | String  | 无                          |
| continueReading                      | 是否以弹窗形式提示用户继续阅读，chapterId 为空时生效          | Boolean | false                       |
| downloadType                         | 下载资源方式 pop-up：弹窗提示,click:下载回调                  | String  | pop-up                      |
| isOpenHyperlink                      | 移动端是否可以直接打开超链接                                  | Boolean | false                       |
| linkOpenLabel                        | pc 端链接是否打开新标签                                       | Boolean | true                        |
| officePreviewPath                    | ffice 在线预览路径 格式：地址加参数名：https:www.xxx.com?src= | String  | 微软在线预览                |
| trialText                            | 试读结束提示语，富文本格式                                    | String  | 试读结束                    |
| action                               | 文件上传地址，上传教师资源时必传                              | String  | 无                          |
| headers                              | 设置上传的请求头部                                            | Object  | 无                          |
| data                                 | 上传时附带的额外参数                                          | Object  | 无                          |
| fileSize                             | 最大上传文件大小,单位 M                                       | Number  | 300                         |
| isOpenStudy                          | 是否开启学情统计和班级                                             | Boolean | true                       |
| teacherData                          | 教师端学情统计                                                | Object  | [teacherData](#teacherData) |
| studentData                          | 学生端学情统计                                                | Object  | [studentData](#studentData) |
| getCatalogStudent                    | 获取目录学习情况                                              | Array   | [generalAPI](#generalAPI)   |
| isAddMark                            | 是否可以添加书签、笔记                                        | Boolean | true                        |
| updateFREQUENCY                      | 音视频更新回调频率                                            | String  | 10s                         |
| robotData                            | 智能云端应用调用参数                                          | Object  | [robotData](#robotData)     |
| isOperation                          | 是否可以操作（用于点击后接口无响应，重复操作）                | Boolean | true                        |

##### 事件

| 事件名             | 说明         | 回调参数                                         |
| ------------------ | ------------ | ------------------------------------------------ |
| updateReadLocation | 更新阅读进度 | [newLocation](#newLocation)：当前阅读位置信息    |
| addNote            | 确认添加笔记 | [notesInfo](#notesInfo):添加笔记信息             |
| editNote           | 更新笔记     | [notesInfo](#notesInfo):更新笔记信息             |
| deleteNote         | 删除笔记     | [notesInfo](#notesInfo):删除笔记信息             |
| addBookmark        | 添加书签     | [bookmarkInfo](#bookmarkInfo):添加书签信息       |
| deleteBookmark     | 删除书签     | [bookmarkInfo](#bookmarkInfo):删除书签信息       |
| addHighlight       | 添加高亮     | [highlightInfo](#highlightInfo):添加高亮信息     |
| deleteHighlight    | 删除高亮     | [highlightInfo](#highlightInfo):删除高亮信息     |
| addTestPaper       | 添加试卷     | [testPaperInfo](#testPaperInfo):添加试卷信息     |
| deleteTestPaper    | 删除试卷     | [testPaperInfo](#testPaperInfo):删除试卷信息     |
| addResources       | 添加授课资源 | [resourcesInfo](#resourcesInfo):添加授课资源信息 |
| editResources      | 编辑授课资源 | [resourcesInfo](#resourcesInfo):添加授课资源信息 |
| deleteResource     | 删除授课资源 | [resourcesInfo](#resourcesInfo):删除授课资源信息 |
| addTeacherNote     | 添加教师笔记 | [notesInfo](#notesInfo):笔记信息                 |
| editTeacherNote    | 修改教师笔记 | [notesInfo](#notesInfo):笔记信息                 |
| deleteTeacherNote  | 删除教师笔记 | [notesInfo](#notesInfo):笔记信息                 |
| downloadFile       | 下载资源     | [fileInfo](#fileInfo):资源信息                   |
| settingChange      | 阅读设置     |                                                  |
| joinClass          | 加入班级     | {code:输入的激活码}                              |
| learningStatistics | 更新学习统计 | [statisticsInfo](#statisticsInfo)                |
| changeClass        | 切换班级     | 班级信息                                         |
| clickToRespond     | 按钮点击回调 | {type:[按钮类型](#按钮类型)，data:{}}            |

##### 保存阅读进度

> updateReadLocation 监听实时更新当前阅读位置信息，下次进入将位置信息传入组件

##### 添加笔记

> addNote 确认添加笔记事件返回笔记 Id，对应的位置信息，选择内容，笔记内容，==添加成功更新笔记列表数据==
>
> editNote 更新笔记事件返回笔记 Id，笔记内容等信息
>
> deleteNote 删除笔记事件返回笔记 Id 等信息，==删除成功更新笔记列表数据==

##### 添加书签

> addBookmark 添加书签事件返回图书位置等信息，==添加成功更新书签列表数据==
>
> deleteBookmark 删除书签事件返回书签 ID 等信息，==删除成功更新书签列表数据==

##### 添加高亮

> addHighlight 添加高亮事件返回图书位置等信息，==添加成功更新高亮列表数据==
>
> deleteHighlight 删除高亮事件返回高亮 ID 等信息，==删除成功更新高亮列表数据==

##### 教师端添加试题

> addTestPaper 添加试题事件返回图书位置等信息，==添加成功更新资源列表数据==
>
> deleteTestPaper 删除试题事件返回试题 ID 等信息，==删除成功更新资源列表数据==

##### 教师端添加资源

> addResources 添加资源事件返回图书位置等信息，==添加成功更新资源列表数据==
>
> deleteResources 删除资源事件返回资源 ID 等信息，==删除成功更新资源列表数据==

##### 下载资源

> downloadFile 下载资源事件，返回资源文件信息

##### 组件内部方法

| 方法名      | 说明       | 参数                                             |
| ----------- | ---------- | ------------------------------------------------ |
| showToast   | 提示框     | text:提示的文字 , type : warning、success、error |
| READER_MODE | 沉浸式阅读 | type: initial 初始值、immersive 沉浸式阅读       |

##### 数据格式

###### textBookData.json

```json
{
  "createBy": null,
  "createByName": null,
  "createTime": "2023-01-10 22:44:25",
  "delFlag": null,
  "delTime": null,
  "examineDesc": null,
  "examineStatus": "0",
  "id": "1612822675944177664",
  "isbn": null,
  "params": {},
  "remark": null,
  "searchValue": null,
  "submitTime": null,
  "textBooksAuthor": null,
  "textBooksDesc": null,
  "textBooksFileUrl": "",
  "textBooksName": "测试所有组件",
  "textBooksType": null,
  "updateBy": null,
  "updateByName": null,
  "updateTime": "2023-01-12 13:56:07"
}
```

###### catalogList.json

```json
{
  "data": [
    {
      "children": [],
      "id": "1612822676606877696",
      "label": "章节1",
      "level": null,
      "orderNum": null,
      "parentId": null
    }
  ]
}
```

###### looseLeafData.json

```json
{
  "1612822676606877696": {
    "createBy": "admin",
    "createByName": null,
    "createTime": "2023-01-10 22:44:26",
    "delFlag": "0",
    "delTime": null,
    "examineDesc": null,
    "examineStatus": "0",
    "id": "1612822676606877696",
    "looseLeafDesc": null,
    "looseLeafFileUrl": "",
    "looseLeafInfo": "[{\"data\": {\"pGroupData\": {\"textData\": {\"html\": \"<span>暂无内容</span><div><span>这是文本</span></div><div><span><br/></span></div>\"}}, \"extendParams\": {}}, \"xmlCompRef\": \"xml-single-text-group0.9220515733715631\", \"componentsName\": \"xml-single-text-group\"}, {\"data\": {\"pGroupData\": {\"titleTextData\": {\"html\": \"<p style=\\\"font-size: 16px;font-family: PingFang SC;font-weight: 400;color: #FFFFFF;margin-block-start: 5px;margin-block-end: 5px;\\\">这是标题</p>\"}}, \"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
{
  "chapterId": "章节ID",
  "chaptName": "章节名",
  "location": "", //当前阅读位置
  "schedule": "", //当前阅读进度
  "learningTime": "", //本次学习时长
  "learningDuration": "", //总学习时长,需要每次进阅读器前传入历史阅读总时长
  "chapterSchedule": "本章节学习进度",
  "learningChapter": "本次阅读章数"，
   learningChapterList: [],//本次学习的章节id组
   "firstLevelId"："一级章节id"
}
```

###### 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": ""
}
```

###### statisticsInfo

**通用参数**

```json
//图片每放大预览调用一次；音视频每播放10秒调用一次；答题每提交答案调用一次
{
    type:'学习类型'，//image:图片，audio：音频，video：视频，question:答题
    firstLevelId: '章节所在一级标题的Id',
    firstLevelLabel: '章节所在一级标题的名称',
    locationChapterId: '当前内容阅读所在目录id',
    locationLabel: '当前内容阅读所在目录名称',
    chapterId: '章节Id',
    label: '章节名字',
    xmlCompRef:'学习内容唯一ID',
    location:'学习内容在教材中的位置信息',
}
```

**特定参数**

==音频==

```json
{
  "duration": "音频总时长",
  "time": "当前播放时长"
}
```

==视频==

```json
{
  "duration": "视频总时长",
  "time": "当前播放时长"
}
```

==试题==

```json
{
  "pass": "回答是否正确，true：正确；false：错误",
  "question": "试题信息"
}
```

###### studentData:

```json
{
    nickname:'',//名字
    className:'',//默认班级
	  img:'',//头像
    learningProgress:'',//学习进度
    learnNum :'',//学习次数
    learnTime:'',//本次学习时长
    totalLearnTime:'',//学习总时长
    chapterNum:'',//本次学习章节数量
    learnChapter:'',//总学习章节
    noteNum:'',//笔记数量
    bookmarkNum:'',//书签数量
    lineationNum:'',//划线数量
    imgLearnNum:0,//图片学习次数
    musicTime:10，//音频学习时长
    videoTime:10，//视频学习时长
    completionRate:0,//试题完成率
    accuracy:0,//试题正确率
    "imageNum": 0, //学习图片个数
    "testNum": 0, //试题学习个数
    "musicNum": 0, //音频学习个数
    "videoNum": 0, //视频学习个数

}
```

###### teacherData:

```json
{
  "nickname": "", //名字
  "className": "", //默认班级
  "img": "", //头像
  "totalLearnTime": "", //授课时长
  "learnNum": "", //授课次数
  "learningProgress": "", //学习进度
  "thisLearnTime": "", //本次授课时长
  "studentList": [
    {
      "nickname": "", //名字
      "className": "", //默认班级
      "img": "", //头像
      "learningProgress": "", //学习进度
      "learnNum": "", //学习次数
      "learnTime": "", //本次学习时长
      "totalLearnTime": 0, //学习总时长
      "chapterNum": "", //本次学习章节数量
      "learnChapter": 0, //总学习章节
      "noteNum": "", //笔记数量
      "bookmarkNum": "", //书签数量
      "lineationNum": "", //划线数量
      "imgLearnNum": 0, //图片学习次数
      "musicTime": 0, //音频学习时长
      "videoTime": 0, //视频学习时长
      "completionRate": 0, //试题完成率
      "accuracy": 0, //试题正确率
      "imageNum": 0, //学习图片个数
      "testNum": 0, //试题学习个数
      "musicNum": 0, //音频学习个数
      "videoNum": 0, //视频学习个数
    },
  ] //班级学员
}
```

###### robotData:

```json
{
  "appId": "", //应用ID
  "token": "", //应用token
  "baseUrl": "", //新建对话接口地址
  "conversationUrl": "" //大模型对话接口
}
```

###### 按钮类型

```json
{
  "value": 0,
  "label": "点击学习情况"
}
```

###### generalAPI

```vue
<template>
  <xml-digital-teaching :generalAPI="generalAPI" />
</template>
<script>
export default {
  data() {
    return {
      generalAPI: {
        isCatalogStudent: true, //是否开启查询章节学期情况
        getCatalogStudent: (e) => this.getCatalogStudent(e)
      }
    }
  },
  methods: {
    /**
     * e.chapterId  章节id
     */
    getCatalogStudent(e) {
      return new Promise((resolve, reject) => {
        let data = {
          chapterId: '0', //章节id
          studyTime: 0, //本章学习时间，单位秒
          studyProgress: '100', //本章学习进度
          testProgress: '0', //本章试题完成进度
          accuracy: '', //本章试题正确率
          testNum:'0',//本章试题完成个数
        }
        // 模拟异步操作
        setTimeout(() => {
          resolve({ data })
        }, 1000)
      })
    }
  }
}
</script>
```

### 阅读器功能

#### 语音评测

1、传入配置

~~~vue
<script>
export default {
    provide() {
    return {
      getXmlShadowingConfig: () => ({
        APPID: 'xxxxx',
        API_SECRET: 'xxxxxxxxxxxxxxxxxxxxxxxxxx',
        API_KEY: 'xxxxxxxxxxxxxxxxxxxxxxxxxx'
      }),
    }
  },
}
</script>
~~~



### 工具方法

##### 格式化教材数据

```javascript
import XML from './plugin/xml-digital-teaching/lib/index'
XML.formatTextBook({
  textBookData: this.textBookData,
  catalogList: this.catalogList,
  looseLeafData: this.looseLeafData,
  isTrial: true
}).then((res) => {
  console.log(res)
})
```

- 请求参数

| 参数             | 说明                                              | 类型    | 是否必填 |
| ---------------- | ------------------------------------------------- | ------- | -------- |
| textBookData     | 教材信息                                          | Object  | true     |
| catalogList      | 目录                                              | Array   | true     |
| looseLeafData    | 教材内容                                          | Object  | true     |
| isTrial          | 是否试读                                          | Boolean | false    |
| isTrialIndex     | 试读百分比                                        | Number  | false    |
| trialChapterList | 可试读的章节，isTrialIndex 传 0 时生效，['xxxxx'] | Array   | false    |

- 返回值

| 参数             | 说明                        | 类型   |
| ---------------- | --------------------------- | ------ |
| componentList    | 可阅读的块                  | Array  |
| catalogList      | notUsable:为不可 阅读的章节 | Array  |
| textBookResource | 教材各类资源统计            | Object |
