闫增涛
2025-04-14 2cac4a0f4ea0b1cf7bff4759fae8136c72792563
src/views/readerPages/webHome.vue
@@ -440,7 +440,11 @@
                            @click="goPlay(item)"
                            size="20"
                            class="icon hover"
                            v-if="item.resourceType != '视频' && item.resourceType != '音频' && item.resourceType != '图片'"
                            v-if="
                              item.resourceType != '视频' &&
                              item.resourceType != '音频' &&
                              item.resourceType != '图片'
                            "
                          >
                            <View />
                          </el-icon>
@@ -644,6 +648,18 @@
            <!-- 画笔画布 -->
            <div class="canvas-box" v-show="canvasShow">
              <canvas id="canvasRef" :width="canvasWith" :height="canvasheight"></canvas>
            </div>
            <!-- 番茄闹钟组件 -->
            <div
              class="watch-box"
              v-if="pomodoroRef && pomodoroRef.isShow"
              :style="{ top:position.x + 'px', left:position.y + 'px'}"
            >
              <p @mousedown.native="mouseDown">{{ formatTime(pomodoroRef.pageData.currentTime) }}</p>
              <span @click="()=> pomodoroRef.isRuning ? pomodoroRef.pauseFun() : pomodoroRef.startFun()">{{pomodoroRef.isRuning ? '暂停': '开始'}}</span>
              <span @click="pomodoroRef.resetFun" >重置</span>
              <span @click="pomodoroRef.handleRestFun(false)">长休息</span>
              <span @click="pomodoroRef.handleRestFun(true)">短休息</span>
            </div>
          </div>
        </div>
@@ -1152,9 +1168,12 @@
      <video controls controlslist="nodownload" :src="testVideo"></video>
    </div>
    <!-- <div class="wordBox" v-if="resourType == 'word'">
      <vue-office-docx :src="testWord" />
    </div> -->
    <div class="wordBox" v-if="resourType == 'PDF' || resourType == 'PPT' || resourType == 'WORD'">
      <div v-for="(item, index) in showData" :key="index" class="pdfItem" :page="index + 1">
        <img :src="item.showSrc" alt="" style="min-height: 550px" loading="lazy" />
        <el-divider content-position="center"> 第 {{ index + 1 }} 页 </el-divider>
      </div>
    </div>
  </el-dialog>
  <div class="audioBox" v-show="false">
    <!-- <video controls controlslist="nodownload" :src="testVideo"></video> -->
@@ -1263,6 +1282,11 @@
  </el-dialog>
  <el-dialog title="模型工具" align-center v-model="modelToolVisble" width="80%" class="myDialogs">
    <div class="wendabox">
      <iframe :src="sceneUrl" frameborder="0"></iframe>
    </div>
  </el-dialog>
  <el-dialog title="模型工具" align-center v-model="modelTool" width="80%" class="myDialogs">
    <div class="wendabox">
      <iframe src="https://adjam93.github.io/threejs-model-viewer/#" frameborder="0"></iframe>
    </div>
  </el-dialog>
@@ -1282,12 +1306,7 @@
      <wrongQuestion />
    </div>
  </el-dialog>
  <el-dialog
    title="公式编辑"
    align-center
    v-model="formulaDialog"
    class="myDialogs"
  >
  <el-dialog title="公式编辑" align-center v-model="formulaDialog" class="myDialogs">
    <div class="wendabox">
      <formula />
    </div>
@@ -1305,14 +1324,19 @@
    <!-- <calculatorNew></calculatorNew> -->
    <iframe src="https://www.geogebra.org/scientific" frameborder="0" class="iframe-box"></iframe>
  </el-dialog>
  <!-- 番茄闹钟 -->
  <!-- <pomodoro ref="pomodoroRef" /> -->
</template>
<script setup lang="ts">
import examination from '@/views/examination/index.vue'
import pomodoro from '@/views/components/pomodoro.vue'
import { ref, reactive, watch, onMounted, onBeforeMount, onBeforeUnmount, inject } from 'vue'
import { useRouter, useRoute } from 'vue-router'
import { ElMessage, ElMessageBox, valueEquals } from 'element-plus'
import { useFormatData } from '@/hooks/public'
import useClipboard from 'vue-clipboard3'
const { toClipboard } = useClipboard()
const { formatTime } = useFormatData()
const MG: any = inject('MG')
const toolClass = inject('toolClass')
//获取路由器
@@ -1482,7 +1506,6 @@
        window.qiankunState.initTestBook(localStorage.getItem('bookId') + '', tryPageCount.value)
      }
    }
  })
  // 定义父层方法
@@ -1572,7 +1595,6 @@
  // if (window.qiankunState && window.qiankunState.getAnswers){
  //   window.qiankunState.getAnswers(localStorage.getItem(""))
  // }
})
onBeforeUnmount(() => {
@@ -1623,6 +1645,7 @@
  }
  MG.store.getProductList(obj).then((res) => {
    console.log(res.datas, '图书信息')
    if (!res.datas.length) return
    bookInfo.value = res.datas[0]
    if (res.datas[0].purchasedSaleMethodIdList.includes(res.datas[0].defaultSaleMethodId)) {
      isBuy.value = true
@@ -1795,6 +1818,11 @@
      icon: fanqiezhong,
      isShow: bookConfig.value.textbookComponents.indexOf('E4DC9777') > -1
    }
    // {
    //   name: '番茄闹钟',
    //   icon: fanqiezhong,
    //   isShow: true
    // }
  ]
  floatingToolBox = [
    {
@@ -1886,9 +1914,9 @@
      if (localStorage.getItem('chapter') && localStorage.getItem('startPage')) {
        let chapter = Number(localStorage.getItem('chapter'))
        let start = Number(localStorage.getItem('startPage'))
        if (window.qiankunState && window.qiankunState.gotoPage) {
          window.qiankunState.gotoPage(chapter,start)
          window.qiankunState.gotoPage(chapter, start)
          localStorage.removeItem('chapter')
          localStorage.removeItem('startPage')
        }
@@ -1896,7 +1924,6 @@
    })
    .catch(function (error) {
      listLoading.value = false
    })
}
const defaultProps = {
@@ -2047,8 +2074,17 @@
            if (!activeClassify.value) {
              activeClassify.value = classifySelectList.value[0].key
              defaultResourceList.value.forEach((resItem1) => {
                if (resItem1.resourceType != '图片' && resItem1.resourceType != '视频' && resItem1.resourceType != '音频') {
                if (resItem1.resourceType == classifySelectList.value[0].title) {
                  resourceDataList.value.push(resItem1)
                }
                if (activeClassify.value == 'other') {
                  if (
                    resItem1.resourceType != '图片' &&
                    resItem1.resourceType != '视频' &&
                    resItem1.resourceType != '音频'
                  ) {
                    resourceDataList.value.push(resItem1)
                  }
                }
              })
            }
@@ -2121,8 +2157,17 @@
            if (!activeClassify.value) {
              activeClassify.value = classifySelectList.value[0].key
              teacherResourceList.value.forEach((resItem1) => {
                if (resItem1.resourceType != '图片' && resItem1.resourceType != '视频' && resItem1.resourceType != '音频') {
                if (resItem1.resourceType == classifySelectList.value[0].title) {
                  resourceDataList.value.push(resItem1)
                }
                if (activeClassify.value == 'other') {
                  if (
                    resItem1.resourceType != '图片' &&
                    resItem1.resourceType != '视频' &&
                    resItem1.resourceType != '音频'
                  ) {
                    resourceDataList.value.push(resItem1)
                  }
                }
              })
            }
@@ -2156,7 +2201,10 @@
  }
}
//资源播放视频
const sceneUrl = ref()
const showData = ref()
const goPlay = (data, index) => {
  console.log(data.resourceType, 123)
  resourType.value = data.resourceType
  if (data.resourceType == '视频') {
    if (data.md5) {
@@ -2173,6 +2221,59 @@
      testAudio.value = bookConfig.value.resourceUrl + '/' + data.resourcePath
    }
    autoPlay()
  } else if (data.resourceType == '模型') {
    console.log(data, 222)
    let file = bookConfig.value.requestCtx + '/file/api/ApiDownload?md5=' + data.md5
    console.log(file.exd, 777)
    const ctx = 'https://jsek.bnuic.com'
    if (data.md5) {
      sceneUrl.value =
        'https://jsek.bnuic.com/books/book/civilAviation/static/modelView/index.html?md5=' +
        data.md5 +
        '&name=je' +
        '&domain=' +
        ctx +
        '&exd=obj' +
        '&target=iframe'
    } else {
      sceneUrl.value = bookConfig.value.resourceUrl + '/' + data.resourcePath
    }
    modelToolVisble.value = true
    // if (data.md5) {
    //   window.open(bookConfig.value.requestCtx + '/file/api/ApiDownload?md5=' + data.md5)
    // } else if (data.resourcePath) {
    //   window.open(bookConfig.value.resourceUrl + '/' + data.resourcePath)
    // }
  } else if (data.resourceType == 'PPT' || data.resourceType == 'PDF') {
    let md5 = data.md5
    let dataList = []
    MG.file
      .getPdfInfo({
        md5
      })
      .then((res: any) => {
        console.log()
        if (res && res.totalPages) {
          for (let i = 0; i < res.totalPages; i++) {
            const src =
              bookConfig.value.requestCtx +
              '/file/GetPdfPageImage?md5=' +
              md5 +
              '&index=' +
              (i + 1) +
              '&dpi=300'
            dataList.push({
              showSrc: src
            })
          }
          console.log(dataList)
          showData.value = dataList
          // 启动页码观察
          setTimeout(() => {
            resourVisble.value = true
          }, 500)
        }
      })
  } else {
    if (data.md5) {
      window.open(bookConfig.value.requestCtx + '/file/api/ApiDownload?md5=' + data.md5)
@@ -2185,7 +2286,7 @@
  //   testWord.value = bookConfig.value.resourceUrl + '/' + data.resourcePath
  // }
}
const goDownload =(data) =>{
const goDownload = (data) => {
  if (data.md5) {
    window.open(bookConfig.value.requestCtx + '/file/api/ApiDownload?md5=' + data.md5)
  } else if (data.resourcePath) {
@@ -2331,6 +2432,15 @@
              collectResourceList.value.forEach((resItem1) => {
                if (resItem1.resourceType == classifySelectList.value[0].title) {
                  resourceDataList.value.push(resItem1)
                }
                if (activeClassify.value == 'other') {
                  if (
                    resItem1.resourceType != '图片' &&
                    resItem1.resourceType != '视频' &&
                    resItem1.resourceType != '音频'
                  ) {
                    resourceDataList.value.push(resItem1)
                  }
                }
              })
            }
@@ -2817,22 +2927,24 @@
      break
  }
}
type pomodoroType = InstanceType<typeof Pomodoro>
const baiduVisible = ref(false)
const wendaVisible = ref(false)
const cidianVisible = ref(false)
const functionVisible = ref(false)
const siweiVisble = ref(false)
const modelToolVisble = ref(false)
const modelTool = ref(false)
const shengciVisble = ref(false)
const calculatorVisble = ref(false)
const pomodoroRef = ref<pomodoroType>()
const activeTool = ref(0)
const toolState = reactive({
  open: true
})
const resourceUrl = ref('')
const selectTeachTools = (item) => {
const selectTeachTools = (item: any) => {
  if (token) {
    activeTool.value = item.name
    switch (item.name) {
@@ -2846,7 +2958,7 @@
        siweiVisble.value = true
        break
      case '模型工具':
        modelToolVisble.value = true
        modelTool.value = true
        break
      case '词典':
        cidianVisible.value = true
@@ -2857,6 +2969,8 @@
        break
      case '计算器':
        calculatorVisble.value = true
      case '番茄闹钟':
        pomodoroRef.value.setDialogVisable(true)
        break
    }
  } else {
@@ -2935,7 +3049,6 @@
//浮窗工具栏点击事件
const floatItemHandle = (item) => {
  console.log(floatingToolData.activeToolData, 'floatingToolData.activeToolData')
  if (floatingToolData.activeToolData == '画笔') {
    floatingToolData.activeToolData = ''
  } else {
@@ -3172,7 +3285,6 @@
//跳转
const goReMark = (item) => {
  console.log(item)
  if (window.qiankunState && window.qiankunState.gotoPage) {
    window.qiankunState.gotoPage(Number(item.chapterNum), Number(item.page))
  }
@@ -3257,7 +3369,6 @@
}
//取消回调
const closeFn = (base64: any) => {
  console.log(base64)
  floatingToolData.activeToolData = ''
}
//保存截图
@@ -3504,7 +3615,6 @@
        window.speechSynthesis.cancel()
        const synth = window.speechSynthesis
        const utterance = new SpeechSynthesisUtterance(dialogToolData.txt)
        console.log(utterance, 1)
        utterance.lang = 'zh-CN' // 设置语言为中文
        synth.speak(utterance)
        showToolBox.value = false
@@ -3541,10 +3651,8 @@
        showToolBox.value = false
        // cidianVisible.value = true
        console.log(dialogToolData.txt)
        break
      case '百科':
        console.log('https://baike.baidu.com/item/' + dialogToolData.txt)
        baiduVisible.value = true
        break
    }
@@ -3785,7 +3893,6 @@
            const item = res[i]
            // 储值
            let data = catalogueData.value.find((item1) => item1.chapter == Number(item.key))
            // console.log(data,'666')
            let dataList = []
            if (catalogueData.value.length > 0) {
              catalogueData.value.forEach((item1) => {
@@ -3827,7 +3934,6 @@
              })
            }
          }
          console.log(scribeData.noteList, 'scribeData.noteList')
        }
        listLoading.value = false
      })
@@ -3901,13 +4007,11 @@
  document.addEventListener('mousemove', function (event) {
    var x = event.offsetX
    var y = event.offsetY
    // console.log('鼠标坐标位置:', x, y)
    noteContent.top = event.clientY + 20
    noteContent.left = event.clientX
  })
}
window.noteOut = (type) => {
  console.log(type, 123)
  noteContent.show = false
}
@@ -3957,7 +4061,6 @@
//笔记跳转
const jumpContent = (item) => {
  console.log(item)
  if (window.qiankunState && window.qiankunState.gotoPage) {
    window.qiankunState.gotoPage(Number(item.chapterNum), Number(item.page))
  }
@@ -3965,7 +4068,6 @@
//菜单笔记编辑
const update = (item) => {
  console.log(item)
  dialogToolData.chapter = item.chapterNum
  noteColorActive.value = item.color
  formData.id = item.id
@@ -4048,13 +4150,11 @@
        }
      ])
      .then((res) => {
        console.log(res[0][0], 'cid')
        if (res.length > 0 && res[0].length > 0) {
          res[0].map((item) => {
            item.trans = JSON.parse(item.trans)
          })
          dictionaryData.data = res[0][0]
          console.log(dictionaryData.data, '14')
          dictionaryData.showContent = true
        }
      })
@@ -4149,6 +4249,29 @@
const formulaDialog = ref(false)
const openFormulaDialog = () => {
  formulaDialog.value = true
}
// 番茄钟移动
const isMove = ref<boolean>(false)
const position = reactive({x:100,y:100})
const dragOffset = reactive({x:0,y:0})
const mouseDown = (e: MouseEvent) => {
  isMove.value = true
  dragOffset.x = e.clientX - position.x
  dragOffset.y = e.clientY - position.y
  document.addEventListener('mousemove', mouseMove)
  document.addEventListener('mouseup', mouseUp)
}
const mouseUp = (e: MouseEvent) => {
  isMove.value = false
  document.removeEventListener('mousemove', mouseMove)
  document.removeEventListener('mouseup', mouseUp)
}
const mouseMove = (e: MouseEvent) => {
  if (isMove.value) {
    position.x = e.clientX - dragOffset.x
    position.y = e.clientY - dragOffset.y
  }
}
</script>
@@ -4900,6 +5023,33 @@
          z-index: 96;
          background: rgba(255, 255, 255, 0.2);
        }
        .watch-box {
          display: flex;
          align-items: center;
          position: absolute;
          background-color: #555;
          color: #fff;
          padding: 10px;
          border-radius: 5px;
          width: max-content;
          p {
            cursor: move;
            padding: 0 8px;
            font-size: 18px;
            border-radius: 4px;
            margin-right: 10px;
            background-color: #666;
          }
          span {
            cursor: pointer;
            border-right: 1px solid #fff;
            padding: 0 4px;
            font-size: 14px;
            &:last-child {
              border-right: none;
            }
          }
        }
      }
    }
@@ -5306,7 +5456,7 @@
.wendabox {
  width: 100%;
  height: 95vh;
  height: 82vh;
  iframe {
    width: 100%;
@@ -5407,6 +5557,17 @@
.wordBox {
  height: 600px;
  width: 100%;
  overflow-y: scroll;
  img {
    display: block;
    margin: 0 auto;
    width: 90%;
    height: auto;
    box-shadow: 0px 0px 10px 1px rgba(0, 0, 0, 0.1);
    object-fit: contain;
  }
}
.imgUrlBox {
@@ -5424,7 +5585,7 @@
  left: 50px;
}
.iframe-box {
  width:100%;
  width: 100%;
  height: 800px;
}
</style>