闫增涛
2024-07-02 92845ee4a3898c4c65bc85bbbe777e4595897e3d
语音阅读小窗
2个文件已修改
9个文件已添加
171 ■■■■■ 已修改文件
src/assets/images/voice/fudu.png 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/images/voice/gendu.png 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/images/voice/gendubofang.png 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/images/voice/pause.png 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/images/voice/play.png 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/images/voice/shangyiju.png 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/images/voice/sudu.png 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/images/voice/xiayiju.png 补丁 | 查看 | 原始文档 | blame | 历史
src/views/components/voiceReader.vue 128 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/examination/index.vue 24 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/readerPages/webHome.vue 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/images/voice/fudu.png
src/assets/images/voice/gendu.png
src/assets/images/voice/gendubofang.png
src/assets/images/voice/pause.png
src/assets/images/voice/play.png
src/assets/images/voice/shangyiju.png
src/assets/images/voice/sudu.png
src/assets/images/voice/xiayiju.png
src/views/components/voiceReader.vue
New file
@@ -0,0 +1,128 @@
<template>
  <div class="voiceReader">
    <ul class="reader-box">
      <li @click="changePlay">
        <img :src="readerState.isPlay ? playIcon : pauseIcon" alt="" />
        <span>{{ readerState.isPlay ? '播放' : '暂停' }}</span>
      </li>
      <li>
        <img :src="prevIcon" alt="" class="next-icon" />
        <span>上一句</span>
      </li>
      <li>
        <img :src="nextIcon" alt="" class="next-icon" />
        <span>下一句</span>
      </li>
      <li>
        <img :src="repeateIcon" alt="" />
        <span>复读</span>
      </li>
      <li>
        <img :src="followIcon" alt="" />
        <span>跟读</span>
      </li>
      <li>
        <img :src="followPlayIcon" alt="" />
        <span>跟读播放</span>
      </li>
      <li class="voice-dropDown">
        <el-dropdown @command="changeSpeed">
          <div class="el-dropdown-link dropDown-box">
            <img :src="speedIcon" alt="" />
            <span> 速度 </span>
          </div>
          <template #dropdown>
            <el-dropdown-menu>
              <el-dropdown-item v-for="(item, index) in readerState.speedList" :key="index" :command="item">{{
                item
              }}x</el-dropdown-item>
            </el-dropdown-menu>
          </template>
        </el-dropdown>
      </li>
    </ul>
  </div>
</template>
<script setup lang="ts">
import { reactive } from 'vue'
import playIcon from '@/assets/images/voice/play.png'
import pauseIcon from '@/assets/images/voice/pause.png'
import prevIcon from '@/assets/images/voice/shangyiju.png'
import nextIcon from '@/assets/images/voice/xiayiju.png'
import repeateIcon from '@/assets/images/voice/fudu.png'
import followIcon from '@/assets/images/voice/gendu.png'
import followPlayIcon from '@/assets/images/voice/gendubofang.png'
import speedIcon from '@/assets/images/voice/sudu.png'
const readerState = reactive({
  isPlay: false,
  selecte: '', // 选中
  speed:"", // 播放速度
  speedList: ['0.5', '0.8', '1.0', '1.5']
})
const changePlay = () => {
  if (readerState.isPlay) {
    readerState.isPlay = false
  } else {
    readerState.isPlay = true
  }
}
const changeSpeed = (command:string) => {
  console.log('速度',command);
}
</script>
<style scoped lang="less">
.voiceReader {
  height: 58px;
  width: 500px;
  border: 1px solid #0093ff;
  background-color: #fff;
  border-radius: 8px;
}
.reader-box {
  width: 100%;
  height: 100%;
  display: flex;
  justify-content: space-evenly;
  align-items: center;
  font-size: 12px;
  color: #2c2c2c;
  li {
    display: flex;
    flex-direction: column;
    align-items: center;
    cursor: pointer;
    img {
      width: 20px;
      object-fit: contain;
      margin-top: 5px;
    }
  }
}
.next-icon {
  width: 16px !important;
}
.el-dropdown-link {
  height: 100%;
}
.voice-dropDown {
  .dropDown-box {
    display: flex;
    flex-direction: column;
    align-items: center;
    img {
      margin-top: 5px;
    }
  }
  /deep/ .el-tooltip__trigger:focus {
    outline: none;  // unset 这个也行
  }
}
.el-dropdown-menu {
    background-color: #2C2C2C ;
    border-color: #2C2C2C !important;
  }
</style>
src/views/examination/index.vue
@@ -624,16 +624,16 @@
      domain: 'collectData',
      keys: [props.activeBook.bookId]
    })
    .then(async (res) => {
    .then(async (res:any) => {
      try {
        const collect = JSON.parse(res[0].value)
        if (collect.length) {
          examination.collectList = collect.find((citem) => citem.type == 'bits').collectList
          examination.collectList = collect.find((citem:any) => citem.type == 'bits').collectList
          examination.allCollect[0].collectList = collect.find(
            (citem) => citem.type == 'bits'
            (citem:any) => citem.type == 'bits'
          ).collectList
          examination.allCollect[1].collectList = collect.find(
            (citem) => citem.type == 'json'
            (citem:any) => citem.type == 'json'
          ).collectList
        }
      } catch (error) {}
@@ -665,7 +665,7 @@
const getCollectDataList = async () => {
  // 开始请求
  let oldData = null
  let oldList = []
  let oldList:any = []
  let cardList = [
    {
      catalogName: '单选题',
@@ -688,11 +688,11 @@
      infoList: []
    }
  ]
  let singleChoiceArr = [] // 单选
  let judgeArr = [] // 判断
  let shortArr = [] // 简答
  let multipleChoiceArr = [] // 多选
  let completionArr = [] // 填空
  let singleChoiceArr:any = [] // 单选
  let judgeArr:any = [] // 判断
  let shortArr:any = [] // 简答
  let multipleChoiceArr:any = [] // 多选
  let completionArr:any = [] // 填空
  // 11
  for (let qindex = 0; qindex < examination.collectList.length; qindex++) {
    const qitem = examination.collectList[qindex]
@@ -786,7 +786,7 @@
        questionObj.stem.stemImage = getPublicImage(questionObj.stem.stemImage, 150)
      }
      if (questionObj.optionStyle == 'Image' || questionObj.optionStyle == 'TxtAndImage') {
        questionObj.option.forEach((optionItem) => {
        questionObj.option.forEach((optionItem:any) => {
          if (optionItem.img) optionItem.img = getPublicImage(optionItem.img, 150)
        })
      }
@@ -808,7 +808,7 @@
          questionObj.questionType == 'judge' ||
          questionObj.questionType == 'multipleChoice')
      ) {
        questionObj.option.forEach((item) => {
        questionObj.option.forEach((item:any) => {
          if (item.txt)
            item.txt = item.txt
              .replace(/\<img/gi, '<img class="option-rich-img"')
src/views/readerPages/webHome.vue
@@ -815,6 +815,10 @@
            </div>
          </div>
        </div>
        <!-- 语音阅读组件 -->
         <!-- <div class="voice-reader">
          <voiceReader />
         </div> -->
      </div>
      <!-- 教学组件 -->
      <div class="toolBox">
@@ -1242,6 +1246,10 @@
    :type="examinationData.type"
    :infoType="examinationData.infoType"
  />
  <!-- 计算器 -->
   <el-dialog title="计算器" align-center v-model="calculatorVisble" width="40%">
   </el-dialog>
</template>
<script setup lang="ts">
@@ -1263,6 +1271,7 @@
import dictionary from '@/views/components/dictionary.vue'
import newWord from '@/views/components/newWord.vue'
import wrongQuestion from '@/views/components/wrongQuestion.vue'
import voiceReader from '@/views/components/voiceReader.vue'
import { ElMessage, ElMessageBox, valueEquals } from 'element-plus'
import logo from '@/assets/images/header/logo.png'
import mulu from '@/assets/images/menu/mulu.png'
@@ -2698,6 +2707,7 @@
const siweiVisble = ref(false)
const modelToolVisble = ref(false)
const shengciVisble = ref(false)
const calculatorVisble = ref(false)
const activeTool = ref(0)
const toolState = reactive({
  open: true
@@ -2726,6 +2736,10 @@
      case '生词卡片':
        resourceUrl.value = bookConfig.value.resourceUrl
        shengciVisble.value = true
        break
      case '计算器':
      calculatorVisble.value = true
      break
    }
  } else {
    ElMessageBox.confirm('请先登录!', {
@@ -5129,4 +5143,9 @@
    width: 100%;
  }
}
.voice-reader {
  position:absolute;
  bottom:30px;
  left:50px;
}
</style>