|
@@ -153,7 +153,7 @@
|
|
|
<div class="operate-box" :style="{background:colorObj.contentBg}">
|
|
|
<div class="operate-box-inner" :style="{background:colorObj.contentInnerBg}">
|
|
|
<div class="operate-box-inner-content">
|
|
|
- <div class="operate-item">
|
|
|
+ <div class="operate-item" @click="changePlaySent('-')">
|
|
|
<svg-icon icon-class="Go-start" :style="{color:colorObj.type==='white'||colorObj.type==='darkGreen'?'#000':'#fff'}"></svg-icon>
|
|
|
<span :style="{color:colorObj.type==='armyGreen'?'#7C8983':''}">上一句</span>
|
|
|
</div>
|
|
@@ -162,16 +162,20 @@
|
|
|
<span :style="{color:colorObj.type==='armyGreen'?'#7C8983':''}">听对比</span>
|
|
|
</div>
|
|
|
<div class="operate-item">
|
|
|
- <b class="luyin-btn">
|
|
|
+ <b class="luyin-btn" v-if="!microphoneStatus" @click="microphone">
|
|
|
<svg-icon icon-class="Voice-luyin" :style="{color:'#fff'}"></svg-icon>
|
|
|
</b>
|
|
|
+ <img class="luyin-gif" @click="microphone" v-else src="../../../assets/voice-gif.png" />
|
|
|
+ <span v-if="microphoneStatus" class="record-time" :style="{color:'#F2555A',fontWeight: '600'}">{{
|
|
|
+ handleDateTime(recordtime)
|
|
|
+ }}</span>
|
|
|
</div>
|
|
|
- <div class="operate-item">
|
|
|
+ <div class="operate-item" @click="playmicrophone(selectIndex || selectIndex == 0 ? recordList[selectIndex].toltime : '')">
|
|
|
<svg-icon icon-class="Headphone-sound" :style="{color:colorObj.type==='white'||colorObj.type==='darkGreen'?'#000':'#fff'}"></svg-icon>
|
|
|
<span :style="{color:colorObj.type==='armyGreen'?'#7C8983':''}">我读的</span>
|
|
|
</div>
|
|
|
- <div class="operate-item">
|
|
|
- <svg-icon icon-class="Go-start" :style="{color:colorObj.type==='white'||colorObj.type==='darkGreen'?'#000':'#fff'}"></svg-icon>
|
|
|
+ <div class="operate-item" @click="changePlaySent('+')">
|
|
|
+ <svg-icon icon-class="Go-end" :style="{color:colorObj.type==='white'||colorObj.type==='darkGreen'?'#000':'#fff'}"></svg-icon>
|
|
|
<span :style="{color:colorObj.type==='armyGreen'?'#7C8983':''}">下一句</span>
|
|
|
</div>
|
|
|
</div>
|
|
@@ -218,6 +222,7 @@
|
|
|
|
|
|
<script>
|
|
|
import AudioLine from "@/components/common/AudioLine.vue"
|
|
|
+import Recorder from "js-audio-recorder"; // 录音插件
|
|
|
export default {
|
|
|
name: "ArticleView",
|
|
|
props: [ "titleFontsize", "wordFontsize", "colorObj","articleType","articleInfo"],
|
|
@@ -273,6 +278,24 @@ export default {
|
|
|
repeatAfter: false,
|
|
|
singleModel: false,
|
|
|
autoNextSent: false,
|
|
|
+ recorder: new Recorder({
|
|
|
+ sampleBits: 16, // 采样位数,支持 8 或 16,默认是16
|
|
|
+ sampleRate: 16000, // 采样率,支持 11025、16000、22050、24000、44100、48000,根据浏览器默认值,我的chrome是48000
|
|
|
+ numChannels: 1, // 声道,支持 1 或 2, 默认是1
|
|
|
+ }),
|
|
|
+ microphoneStatus: false,
|
|
|
+ hasMicro: "", // 录音后的样式class
|
|
|
+ wavblob: null,
|
|
|
+ audio: new window.Audio(),
|
|
|
+ recordList: [], // 录音文件数组
|
|
|
+ recordtime: 0, // 录音时长
|
|
|
+ timer: null, // 计时器
|
|
|
+ recordFile: 1, // 录音文件名
|
|
|
+ selectIndex: null, // 选中的录音索引
|
|
|
+ oldIndex: null, // 存储播放录音索引
|
|
|
+ playtime: 0, // 播放时间
|
|
|
+ isPlayings: false,
|
|
|
+ playSentIndex: -1, // 播放的句子索引
|
|
|
};
|
|
|
},
|
|
|
computed: {
|
|
@@ -287,8 +310,30 @@ export default {
|
|
|
watch: {},
|
|
|
//方法集合
|
|
|
methods: {
|
|
|
+ changePlaySent(type){
|
|
|
+ for(let i=0; i<this.resArr.timeList.length;i++){
|
|
|
+ if(this.curTime>=this.resArr.timeList[i].s&&this.curTime<this.resArr.timeList[i].e){
|
|
|
+ this.playSentIndex = i
|
|
|
+ break
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if(type==='-'){
|
|
|
+ if(this.playSentIndex>0){
|
|
|
+ this.playSentIndex--
|
|
|
+ }else{
|
|
|
+ this.playSentIndex=0
|
|
|
+ }
|
|
|
+ }else{
|
|
|
+ if(this.playSentIndex<this.resArr.wordsList.length-1){
|
|
|
+ this.playSentIndex++
|
|
|
+ }else{
|
|
|
+ this.playSentIndex=0
|
|
|
+ }
|
|
|
+ }
|
|
|
+ this.handleChangeTime(this.resArr.timeList[this.playSentIndex].s)
|
|
|
+ },
|
|
|
getCurTime(curTime) {
|
|
|
- this.curTime = curTime * 1000;
|
|
|
+ this.curTime = curTime * 1000;
|
|
|
},
|
|
|
handleData() {
|
|
|
let resArr = {
|
|
@@ -335,7 +380,133 @@ export default {
|
|
|
if(this[val]){
|
|
|
this[val1] = false
|
|
|
}
|
|
|
- }
|
|
|
+ },
|
|
|
+ // 开始录音
|
|
|
+ microphone() {
|
|
|
+ let _this = this;
|
|
|
+ if (!this.microphoneStatus) {
|
|
|
+ _this.hasMicro = "";
|
|
|
+ // _this.$emit("getWavblob", null);
|
|
|
+ // this.$emit("getSelectData", { type: "" });
|
|
|
+ // 开始录音
|
|
|
+ this.recorder.start();
|
|
|
+ this.microphoneStatus = true;
|
|
|
+ this.recordtime = 0;
|
|
|
+ this.isPlayings = false;
|
|
|
+ clearInterval(_this.timer);
|
|
|
+ _this.timer = setInterval(() => {
|
|
|
+ _this.recordtime++;
|
|
|
+ }, 1000);
|
|
|
+ this.$emit("handleParentPlay");
|
|
|
+ let obj = {
|
|
|
+ name: _this.fileName
|
|
|
+ ? _this.fileName + _this.recordFile
|
|
|
+ : "Recording " + _this.recordFile,
|
|
|
+ id: _this.recordFile + Math.round(Math.random() * 10),
|
|
|
+ };
|
|
|
+ if (this.selectData) obj.selectData = this.selectData;
|
|
|
+ _this.recordList.push(obj);
|
|
|
+ _this.recordFile++;
|
|
|
+ _this.selectIndex = _this.recordList.length - 1;
|
|
|
+ } else {
|
|
|
+ this.hasMicro = "normal";
|
|
|
+ this.recorder.stop();
|
|
|
+ clearInterval(_this.timer);
|
|
|
+ let toltime = this.recorder.duration; // 录音总时长
|
|
|
+ let fileSize = this.recorder.fileSize; // 录音总大小
|
|
|
+ // 录音结束,获取取录音数据
|
|
|
+ let wav = this.recorder.getWAVBlob(); // 获取 WAV 数据
|
|
|
+ // this.wavblob = wav;
|
|
|
+ this.microphoneStatus = false;
|
|
|
+ let reader = new window.FileReader();
|
|
|
+ reader.readAsDataURL(wav);
|
|
|
+ reader.onloadend = () => {
|
|
|
+ _this.recordList[_this.selectIndex].wavData = reader.result;
|
|
|
+ _this.recordList[_this.selectIndex].toltime = Math.floor(toltime);
|
|
|
+ _this.recordList[_this.selectIndex].fileSize = fileSize;
|
|
|
+
|
|
|
+ _this.wavblob = _this.recordList[_this.selectIndex].wavData;
|
|
|
+ _this.$emit("getWavblob", _this.wavblob);
|
|
|
+ _this.$emit(
|
|
|
+ "handleWav",
|
|
|
+ JSON.parse(JSON.stringify(_this.recordList)),
|
|
|
+ _this.tmIndex
|
|
|
+ );
|
|
|
+ if (this.recordList[this.selectIndex].selectData) {
|
|
|
+ this.$emit(
|
|
|
+ "getSelectData",
|
|
|
+ this.recordList[this.selectIndex].selectData
|
|
|
+ );
|
|
|
+ }
|
|
|
+ };
|
|
|
+ }
|
|
|
+ _this.$emit(
|
|
|
+ "getRerordStatus",
|
|
|
+ !_this.microphoneStatus && _this.recordList.length > 0
|
|
|
+ );
|
|
|
+ _this.$emit("getMicrophoneStatus", _this.microphoneStatus);
|
|
|
+ },
|
|
|
+ playmicrophone(totalTimes) {
|
|
|
+ if (this.hasMicro) {
|
|
|
+ this.isPlayings = true;
|
|
|
+ if (this.selectIndex || this.selectIndex == 0) {
|
|
|
+ let totalTime = totalTimes;
|
|
|
+ let _this = this;
|
|
|
+ if (!this.audio.paused) {
|
|
|
+ this.audio.pause();
|
|
|
+ clearInterval(_this.timer);
|
|
|
+ } else if (this.audio.paused && _this.oldIndex == _this.selectIndex) {
|
|
|
+ _this.audio.play();
|
|
|
+ if (_this.recordtime == 0) {
|
|
|
+ _this.recordtime = totalTimes;
|
|
|
+ _this.playtime = 0;
|
|
|
+ }
|
|
|
+ _this.timer = setInterval(() => {
|
|
|
+ if (_this.playtime < totalTime) {
|
|
|
+ _this.playtime++;
|
|
|
+ _this.recordtime = totalTime - _this.playtime;
|
|
|
+ } else {
|
|
|
+ clearInterval(_this.timer);
|
|
|
+ }
|
|
|
+ }, 1000);
|
|
|
+ } else {
|
|
|
+ _this.audio.pause();
|
|
|
+ _this.audio.load();
|
|
|
+ _this.audio.src = _this.wavblob;
|
|
|
+ _this.oldIndex = _this.selectIndex;
|
|
|
+ _this.audio.play();
|
|
|
+ _this.playtime = 0;
|
|
|
+ _this.recordtime = totalTime;
|
|
|
+ clearInterval(_this.timer);
|
|
|
+ _this.timer = setInterval(() => {
|
|
|
+ if (_this.playtime < totalTime) {
|
|
|
+ _this.playtime++;
|
|
|
+ _this.recordtime = totalTime - _this.playtime;
|
|
|
+ } else {
|
|
|
+ clearInterval(_this.timer);
|
|
|
+ }
|
|
|
+ }, 1000);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ },
|
|
|
+ // 格式化录音时长
|
|
|
+ handleDateTime(time) {
|
|
|
+ if (parseInt(time / 60) < 10) {
|
|
|
+ time =
|
|
|
+ ("0" + parseInt(time / 60)).substring(
|
|
|
+ ("0" + parseInt(time / 60)).length - 2
|
|
|
+ ) +
|
|
|
+ ":" +
|
|
|
+ ("0" + (time % 60)).substring(("0" + (time % 60)).length - 2);
|
|
|
+ } else {
|
|
|
+ time =
|
|
|
+ parseInt(time / 60) +
|
|
|
+ ":" +
|
|
|
+ ("0" + (time % 60)).substring(("0" + (time % 60)).length - 2);
|
|
|
+ }
|
|
|
+ return time;
|
|
|
+ },
|
|
|
},
|
|
|
//生命周期 - 创建完成(可以访问当前this实例)
|
|
|
created() {},
|
|
@@ -484,16 +655,24 @@ export default {
|
|
|
display: block;
|
|
|
width: 64px;
|
|
|
height: 64px;
|
|
|
- padding: 16px;
|
|
|
+ padding: 10px;
|
|
|
border-radius: 60px;
|
|
|
background: #F2555A;
|
|
|
box-shadow: 0px 8px 10px -5px rgba(0, 0, 0, 0.08), 0px 16px 24px 2px rgba(0, 0, 0, 0.04), 0px 6px 30px 5px rgba(0, 0, 0, 0.05);
|
|
|
}
|
|
|
+ .luyin-gif{
|
|
|
+ display: block;
|
|
|
+ width: 64px;
|
|
|
+ height: 64px;
|
|
|
+ border-radius: 60px;
|
|
|
+ box-shadow: 0px 8px 10px -5px rgba(0, 0, 0, 0.08), 0px 16px 24px 2px rgba(0, 0, 0, 0.04), 0px 6px 30px 5px rgba(0, 0, 0, 0.05);
|
|
|
+ }
|
|
|
.svg-icon{
|
|
|
display: block;
|
|
|
- width: 32px;
|
|
|
- height: 32px;
|
|
|
+ width: 44px;
|
|
|
+ height: 44px;
|
|
|
margin: 0 auto;
|
|
|
+ padding: 6px;
|
|
|
}
|
|
|
span{
|
|
|
color: #929CA8;
|