Sfoglia il codice sorgente

英语题追加音频播放

wangxy 4 mesi fa
parent
commit
ef085d18b4

+ 102 - 72
components/chengji/chengji.vue

@@ -1,62 +1,66 @@
 <template>
-	<uni-popup ref="popupRef" :animation="false" :is-mask-click="false"
-	 mask-background-color="rgba(255, 255, 255, 0.6);" class="ezy-popup-width-all">
-		<view class="ezy-result-page"  :style="{backgroundImage: 'url(' + courseBjFun() + ')'}">
-			<view class="icon-title-navBar-box">
-				<view @click="handleBack" class="nav-bar-icon"></view>
-				<view class="nav-bar-title">成绩</view>
-			</view>
-			<view class="shiti-frame-box">
-				<w-swiper :list="list" :positionIndex="current" class="result-exam-swiper">
-					<template v-slot:default="{item,index}">
-						<view class="body" v-if="item.mta_show">
-							<danxuan :question="item" showError v-if="item.type == '1'"></danxuan>
-							<panduan :question="item" showError v-if="item.type == '2'"></panduan>
-              <tiankong :question="item" showError v-if="item.type == '3'" :placeholders="item.placeholders"></tiankong>
-              <yingyu code="cj" :question="item" showError v-if="item.type == '4'" :placeholders="item.placeholders"></yingyu>
-							<view class="answer-content-box">
-								<view class="answer-dtjx-row">
-									<view class="answer-title"></view>
-									<!-- 答案解析 -->
-									<view @click="showJiexiPopup(item)" class="answer-btn"></view>
-								</view>
-								<view class="answer-btn-box" v-if="item.type!=3">
-									<!-- 你的答案 -->
-									<view class="answer-item-left">
-										<text class="answer-item-title">您的答案</text>
-										<text class="answer-item-error">{{showAnswerReply(item)}}</text>
-										<view class="answer-line"></view>
+		<uni-popup ref="popupRef" :animation="false" :is-mask-click="false"
+			mask-background-color="rgba(255, 255, 255, 0.6);" class="ezy-popup-width-all">
+			<view class="ezy-result-page" :style="{backgroundImage: 'url(' + courseBjFun() + ')'}">
+				<view class="icon-title-navBar-box">
+					<view @click="handleBack" class="nav-bar-icon"></view>
+					<view class="nav-bar-title">成绩</view>
+				</view>
+				<view class="shiti-frame-box">
+			
+					<w-swiper :list="myList" :positionIndex="current" class="result-exam-swiper" @change="onSwiperChange">
+						<template v-slot:default="{item,index}">
+							<view class="body" v-if="item.mta_show">
+								<danxuan :question="item" showError v-if="item.type == '1'"></danxuan>
+								<panduan :question="item" showError v-if="item.type == '2'"></panduan>
+								<tiankong :question="item" showError v-if="item.type == '3'"
+									:placeholders="item.placeholders"></tiankong>
+								<yingyu code="cj" :question="item" showError v-if="item.type == '4'"
+									:placeholders="item.placeholders"></yingyu>
+								<view class="answer-content-box">
+									<view class="answer-dtjx-row">
+										<view class="answer-title"></view>
+										<!-- 答案解析 -->
+										<view @click="showJiexiPopup(item)" class="answer-btn"></view>
 									</view>
-									<!-- 答案 -->
-									<view class="answer-item-right">
-										<text class="answer-item-title">正确答案</text>
-										<text class="answer-item-correct">{{showAnswerResult(item)}}</text>
+									<view class="answer-btn-box" v-if="item.type!=3">
+										<!-- 你的答案 -->
+										<view class="answer-item-left">
+											<text class="answer-item-title">您的答案</text>
+											<text class="answer-item-error">{{showAnswerReply(item)}}</text>
+											<view class="answer-line"></view>
+										</view>
+										<!-- 答案 -->
+										<view class="answer-item-right">
+											<text class="answer-item-title">正确答案</text>
+											<text class="answer-item-correct">{{showAnswerResult(item)}}</text>
+										</view>
 									</view>
-								</view>
-								<view  v-else>
-									<!-- 答案 -->
-									<view class="tiankong-answer-content-box">
-										<!-- <text class="answer-item-title">正确答案</text> -->
-										<view v-for="(ict,cindex) in showAnswerResult(item)" :key="cindex" class="tiankong-answer-row">
-										  <text>{{cindex+1}}. </text>
-										  <text v-for="(xItem,xindex) in ict" :key="xindex">
-											<text > {{xItem}} </text>
-											<text v-if="xindex != ict.length-1">/</text>
-										  </text>
+									<view v-else>
+										<!-- 答案 -->
+										<view class="tiankong-answer-content-box">
+											<!-- <text class="answer-item-title">正确答案</text> -->
+											<view v-for="(ict,cindex) in showAnswerResult(item)" :key="cindex"
+												class="tiankong-answer-row">
+												<text>{{cindex+1}}. </text>
+												<text v-for="(xItem,xindex) in ict" :key="xindex">
+													<text> {{xItem}} </text>
+													<text v-if="xindex != ict.length-1">/</text>
+												</text>
+											</view>
 										</view>
 									</view>
+		
 								</view>
-								
 							</view>
-						</view>
-					</template>
-				</w-swiper>
-			</view>
+						</template>
+					</w-swiper>
+				</view>
 			</view>
-		<!-- 解析浮层数据 -->
-		<questionJiexi ref="jiexiRef" :cardId="cardId"></questionJiexi>
-		<questionJiexiYingyu ref="jiexiRefYingyu" :cardId="cardId"></questionJiexiYingyu>
-	</uni-popup>
+			<!-- 解析浮层数据 -->
+			<questionJiexi ref="jiexiRef" :cardId="cardId"></questionJiexi>
+			<questionJiexiYingyu ref="jiexiRefYingyu" :cardId="cardId" :code="code"></questionJiexiYingyu>
+		</uni-popup>
 </template>
 
 <script setup>
@@ -65,13 +69,13 @@
 	import wSwiper from '@/components/wSwiper/wSwiper.vue';
 	import danxuan from "@/components/question/danxuan.vue";
 	import panduan from "@/components/question/panduan.vue";
-  import tiankong from "@/components/question/tiankong.vue";
-  import yingyu from "@/components/question/yingyu/danxuan.vue";
+	import tiankong from "@/components/question/tiankong.vue";
+	import yingyu from "@/components/question/yingyu/danxuan.vue";
 	import {
 		useQuestionTools
 	} from "@/components/question/useQuestionTools.js";
 	import cacheManager from "@/utils/cacheManager";
-	
+	import {computed} from "vue";
 	const {
 		getLetterByIndex
 	} = useQuestionTools();
@@ -85,33 +89,51 @@
 			type: Array,
 		},
 		cardId: {
-			type: [String,Number],
+			type: [String, Number],
 			default: 1
+		},
+		code: {
+			type: String,
+			default: 'cj'
 		}
 	})
+	
+	const myList = computed(() => {
+		return props.list.map(item => {
+			return {
+				...item,
+				code: 'cj'
+			}
+		})
+	})
 
 	const emits = defineEmits(['back'])
 
 	const current = ref(0)
 	const popupRef = ref(null)
 	const jiexiRef = ref(null);
-	const jiexiRefYingyu = ref(null);
+	const jiexiRefYingyu = ref(null)
+
+	function onSwiperChange(index) {
+		uni.$emit('swiper-change', index)
+	}
 
 	// 切换成绩
 	function showPopup() {
 		popupRef.value.open()
 	}
 
-  function closePopup() {
-    popupRef.value.close()
-  }
+	function closePopup() {
+		popupRef.value.close()
+	}
 
 	// 展示
 	function showJiexiPopup(data) {
-		if (data.type != 4 ) {
+		if (data.type != 4) {
 			jiexiRef.value.showPopup(data);
 		} else {
 			jiexiRefYingyu.value.showPopup(data);
+			uni.$emit('question-jiexi-close')
 		}
 	}
 
@@ -124,39 +146,47 @@
 		if (item.type == 1) {
 			// 单选题
 			return getLetterByIndex(item.result)
-		} else if (item.type == 2){
+		} else if (item.type == 2) {
 			if (item.result == 1) {
 				return '正确'
 			} else {
 				return '错误'
 			}
+		} else if (item.type == 4) {
+			return getLetterByIndex(item.result)
 		} else {
 			return item.result
 		}
 	}
-	
-	
+
+
 	function showAnswerReply(item) {
 		if (item.type == 1) {
-      if (item.reply == null) {
-        return '未答'
-      }
+			if (item.reply == null) {
+				return '未答'
+			}
 			// 单选题
 			return getLetterByIndex(item.reply)
-		} else if (item.type == 2){
-      if (item.reply == null) {
-        return '未答'
-      }
+		} else if (item.type == 2) {
+			if (item.reply == null) {
+				return '未答'
+			}
 			if (item.reply == 1) {
 				return '正确'
 			} else {
 				return '错误'
 			}
+		} else if(item.type == 4) {
+			if (item.reply == null) {
+				return '未答'
+			}
+			// 单选题
+			return getLetterByIndex(item.reply)
 		} else {
 			return item.reply
 		}
 	}
-	
+
 	function courseBjFun() {
 		const cardId = Number(props.cardId);
 		switch (cardId) {
@@ -175,4 +205,4 @@
 		showPopup,
 		closePopup
 	})
-</script>
+</script>

+ 3 - 3
components/question/danxuan.vue

@@ -5,9 +5,9 @@
 		<!-- 题干区域 -->
 		<rich-text :nodes="data.name" class="ezy-shiti-question"></rich-text>
 		<!-- 选项区域 -->
-		<view v-for="(item,index) in data.contents" class="danxuan-option-box" :class="formatClass(index)" :key="index" @click="onSelect(index)">
-			<text class="option-change">{{item.number}}</text>
-			<rich-text :nodes="item.label" class="option-question" @itemclick="onSelect(index)"></rich-text>
+		<view v-for="(item,index) in data.contents" class="danxuan-option-box" :class="formatClass(index)" :key="index">
+			<text class="option-change"  @click="onSelect(index)">{{item.number}}</text>
+			<rich-text :nodes="item.label" class="option-question"></rich-text>
 		</view>
 	</view>
 </template>

+ 4 - 5
components/question/yingyu/danxuan.vue

@@ -6,9 +6,9 @@
 		<textReplaceIconVue :code="code" :question="question" :text="question.name" :placeholders="placeholders" class="ezy-shiti-question">
 		</textReplaceIconVue>
 		<!-- 选项区域 -->
-		<view v-for="(item,index) in data.contents" class="yingyu-danxuan-option-box" :class="formatClass(index)" :key="index" @click="onSelect(index)">
-			<text class="option-change">{{item.number}}</text>
-			<textReplaceIconVue :code="code" :question="question" :text="item.label" :placeholders="placeholders" @itemclick="onSelect(index)" class="option-question">
+		<view v-for="(item,index) in data.contents" class="yingyu-danxuan-option-box" :class="formatClass(index)" :key="index">
+			<text class="option-change" @click="onSelect(index)">{{item.number}}</text>
+			<textReplaceIconVue :code="code" :question="question" :text="item.label" :placeholders="placeholders" class="option-question">
 			</textReplaceIconVue>
 		</view>
 	</view>
@@ -44,7 +44,7 @@
 		},
 		code: {
 			type: String,
-		}
+		},
 	})
 	const data = reactive({
 		name: '', //题干数据
@@ -68,7 +68,6 @@
 	}
 	
 	function formatData(val) {
-		console.log('val',val);
 		if (val) {
 			data.name = val.name;
 			data.contents = val.optList.map((item, index) => {

+ 65 - 23
components/question/yingyu/mtaRadio.vue

@@ -6,40 +6,82 @@
 	import {
 		useAudio
 	} from './useAudio';
+	import { onUnmounted } from "vue"
+	
 	let historyData = null;
 	const {
 		handlePlay,
 		handleStop,
 		innerAudioContext
 	} = useAudio();
-	// 播放
-	uni.$on('do-yy-audio-play', (data) => {
-    if (historyData) {
-      if (historyData.stId != data.stId && historyData.index != data.index) {
-        // 播放中切换其他音频时发出事件
-        uni.$emit('reset-playing-status', historyData);
-        historyData = null
-        return;
-      }
-
-      if (historyData.stId != data.stId ) {
-        // 播放中切换其他音频时发出事件
-        uni.$emit('reset-playing-status', historyData);
-        historyData = null
-        return;
-      }
-    }
+	let num = 0;
+	let alreadyplay = false; // 是否是首次播放
+	function doPlay(data) {
+		// console.log('dddd')
+		if (historyData) {
+			if (historyData.stId == data.stId && historyData.index == data.index) {
+				// 播放中切换其他音频时发出事件 同题切换音频
+				historyData = null
+				// console.log('切换同频 暂停或播放')
+				uni.$emit('reset-playing-status', historyData);
+				return;
+			}
+			
+			if (historyData.stId == data.stId && historyData.index != data.index) {
+				// 播放中切换其他音频时发出事件 同题切换音频
+				uni.$emit('reset-playing-status', historyData);
+				// console.log('切换同题 不同音频')
+				handlePlay(data)
+				historyData = data;
+				return;
+			}
 
+			if (historyData.stId != data.stId) {
+				// 播放中切换其他音频时发出事件 切换其他试题
+				uni.$emit('reset-playing-status', historyData);
+				historyData = null
+				// console.log('切换不同题')
+				return;
+			}
+		}
+	
+		if (num == 1) {
+			// console.log('执行播放 已拦截')
+			num = 0;
+			alreadyplay = true
+			return;
+		}
+		// console.log('执行播放')
 		handlePlay(data)
-    historyData = data;
-  })
-	// 暂停
-	uni.$on('do-yy-audio-stop', () => {
+		historyData = data;
+		num++;
+		if (!alreadyplay) {
+			num = 0;
+			alreadyplay = true;
+		}
+	}
+	function doPause() {
+		handleStop()
+	}
+	function doStop(){
 		handleStop()
+	}
+	uni.$emit('swiper-change', () => {
+		num = 0;
 	})
+	// 播放
+	uni.$on('do-yy-audio-play', doPlay)
+	// 暂停
+	uni.$on('do-yy-audio-stop', doPause)
 	// 销毁
-	uni.$on('destory-stop', () => {
-		handleStop()
+	uni.$on('destory-stop', doStop)
+	onUnmounted(() => {
+		// 播放
+		uni.$off('do-yy-audio-play', doPlay)
+		// 暂停
+		uni.$off('do-yy-audio-stop', doPause)
+		// 销毁
+		uni.$off('destory-stop', doStop)
 	})
 </script>
 

+ 79 - 61
components/question/yingyu/textReplaceIcon.vue

@@ -7,6 +7,7 @@
 	import {
 		debounce
 	} from '@/utils/common';
+	import {UseAudio} from "./useAudio.js"
 	export default {
 		props: {
 			placeholders: { // 占位符
@@ -21,13 +22,12 @@
 			},
 			code: {
 				type: String
-			}
+			},
 		},
 		data() {
 			return {
 				myflag: 0,
 				isplaying: null,
-				isFirst: -1,
 			}
 		},
 		computed: {
@@ -64,90 +64,104 @@
 			},
 		},
 		methods: {
-			handleClick() {
-				this.$emit('@itemclick')
-			},
-			audioClick(data) {
-				if (this.isFirst >= 0) {
-					uni.$emit('do-yy-audio-stop', data);
-					this.isFirst = -1
-					return;
-				}
-				if (this.isplaying) {
-					uni.$emit('do-yy-audio-stop', data);
-					this.isFirst++;
-					return;
-				}
-				// 初次播放
-				if (!this.isplaying) {
-					uni.$emit('do-yy-audio-play', data);
-					this.isFirst++;
-					return;
-				}
-			}
-		},
-		created() {
-			// 切换不同播放音频时 重置状态
-			uni.$on('reset-playing-status', (data) => {
+			onResetPlayStatus(data) {
 				if (this.isplaying) {
 					if (data.stId == this.isplaying.stId && data.index == this.isplaying.index) {
 						this.isplaying = null;
 					}
 				}
-			})
-			// 音频播放
-			uni.$on('yy-audio-playing', (data) => {
+			},
+			onYYAudioPlaying(data) {
 				if (this.isplaying) {
 					// 存在播放实例 并且播放非同一音频
-					if (this.isplaying.stId != data.value.stId) {
+					if (this.isplaying.stId != data.stId) {
 						this.isplaying = null;
 					}
 				} else {
 					// 不存在播放实例 
 					this.isplaying = data;
 				}
-			})
-			// 音频异常  重置音频
-			uni.$on('yy-audio-error', (data) => {
+			},
+			onYYAudioError() {
 				this.isplaying = null;
-			})
-			// 音频自然播放结束  重置音频
-			uni.$on('yy-audio-end', (data) => {
+			},
+			onYYAudioEnd() {
 				this.isplaying = null;
-			})
-			// 音频销毁 重置音频
-			uni.$on('destory-stop', (data) => {
+			},
+			onDestoryStop() {
 				this.isplaying = null;
-			})
-			// 试题切换 重置音频
-			uni.$on('swiper-change', () => {
+			},
+			onSwiperChange() {
 				this.isplaying = null;
-			})
-			// 解析关闭 重置音频
-			uni.$on('question-jiexi-close', () => {
+				UseAudio.create().instance.stop();
+			},
+			onQuestionJiexiClose() {
 				this.isplaying = null;
-			})
-			uni.$on('unitTest-submit', () => {
+				UseAudio.create().instance.stop();
+			},
+			onUnitTestSubmit() {
+				this.isplaying = null;
+				UseAudio.create().instance.stop();
+			},
+			onBackOutPage() {
 				this.isplaying = null;
-			})
+				UseAudio.create().instance.stop();
+			},
+			
+			handleClick() {
+				this.$emit('itemclick')
+			},
+			audioClick(data) {
+				UseAudio.create().instance.play(data);
+			},
+		},
+		created() {
+			// 切换不同播放音频时 重置状态
+			uni.$on('reset-playing-status', this.onResetPlayStatus)
+			// 音频播放
+			uni.$on('yy-audio-playing', this.onYYAudioPlaying)
+			// 音频异常  重置音频
+			uni.$on('yy-audio-error', this.onYYAudioError)
+			// 音频自然播放结束  重置音频
+			uni.$on('yy-audio-end', this.onYYAudioEnd)
+			// 音频销毁 重置音频
+			uni.$on('destory-stop', this.onDestoryStop)
+			// 试题切换 重置音频
+			uni.$on('swiper-change',this.onSwiperChange)
+			// 解析关闭 重置音频
+			uni.$on('question-jiexi-close', this.onQuestionJiexiClose)
+			uni.$on('unitTest-submit', this.onUnitTestSubmit)
+			uni.$on('back-outpage', this.onBackOutPage)
+		},
+		destroyed() {
+			// 切换不同播放音频时 重置状态
+			uni.$off('reset-playing-status', this.onResetPlayStatus)
+			// 音频播放
+			uni.$off('yy-audio-playing', this.onYYAudioPlaying)
+			// 音频异常  重置音频
+			uni.$off('yy-audio-error', this.onYYAudioError)
+			// 音频自然播放结束  重置音频
+			uni.$off('yy-audio-end', this.onYYAudioEnd)
+			// 音频销毁 重置音频
+			uni.$off('destory-stop', this.onDestoryStop)
+			// 试题切换 重置音频
+			uni.$off('swiper-change',this.onSwiperChange)
+			// 解析关闭 重置音频
+			uni.$off('question-jiexi-close', this.onQuestionJiexiClose)
+			uni.$off('unitTest-submit', this.onUnitTestSubmit)
+			uni.$off('back-outpage', this.onBackOutPage)
+			
+		
 		}
 	}
 </script>
 <script module="YY" lang="renderjs">
 	export default {
-		props: {
-			placeholders: { // 占位符
-				type: Array,
-				required: true
-			},
-			code: {
-				type: String
-			}
-		},
 		data() {
 			return {
 				myQ: null,
-				callbacks: []
+				callbacks: [],
+				status: '',
 			}
 		},
 		methods: {
@@ -189,8 +203,10 @@
 				if (!question) {
 					return;
 				}
+		
+				this.callbacks = [];
 				question.placeholders.forEach((item, index) => {
-					const cId = this.code ? `t_${question.stId}_${index}_${this.code}` :
+					const cId = question.code ? `t_${question.stId}_${index}_${question.code}` :
 						`t_${question.stId}_${index}`
 					const dom = document.getElementById(cId)
 					if (dom) {
@@ -204,9 +220,11 @@
 								stId: question.stId,
 								index
 							})
-						}, 100)
+						}, 10)
+						
 						this.callbacks.push({
 							index: index,
+							stId: question.stId,
 							callback: callbackFn
 						})
 						dom && dom.addEventListener('click', this.callbacks.find(cIte => cIte.index === index)

+ 127 - 28
components/question/yingyu/useAudio.js

@@ -1,9 +1,16 @@
-import {nextTick, ref} from "vue";
-import { debounce } from "@/utils/common";
+import {
+	nextTick,
+	ref,
+	onUnmounted
+} from "vue";
+import {
+	debounce
+} from "@/utils/common";
 
 export function useAudio() {
 	const innerAudioContext = ref(null);
 	const options = ref(null);
+
 	function createAudio(audioUrl) {
 		const innerAudioContext = uni.createInnerAudioContext();
 		innerAudioContext.autoplay = false;
@@ -13,70 +20,162 @@ export function useAudio() {
 			uni.$emit('yy-audio-playing', options);
 		});
 		innerAudioContext.onError((res) => {
-		  uni.$emit('yy-audio-error')
+			uni.$emit('yy-audio-error')
 		});
 		innerAudioContext.onEnded(() => {
 			// 播放结束
-			uni.$emit('yy-audio-end',options)
+			uni.$emit('yy-audio-end', options)
 		})
 		return innerAudioContext;
 	}
+
 	function changeSource(url) {
-		innerAudioContext.src= url;
+		innerAudioContext.src = url;
 		innerAudioContext.currentTime = 0;
 	}
-	
+
 	const debuncePlay = debounce((myOption) => {
 		innerAudioContext.value = createAudio(myOption.url);
 		innerAudioContext.value.play()
-	},50)
-	
+	}, 50)
+
 	function handlePlay(data) {
 		if (innerAudioContext.value) {
-			innerAudioContext.value.stop();
+			innerAudioContext.value.pause();
 			innerAudioContext.value.destroy();
 			innerAudioContext.value = null;
-			uni.$emit('destory-stop')	
+			uni.$emit('destory-stop')
 		}
 		options.value = data;
 		debuncePlay(data);
 	}
-	
+
 	function handleStop() {
-		// console.log('stop')
 		if (innerAudioContext.value) {
+			innerAudioContext.value.pause();
 			innerAudioContext.value.destroy();
 			innerAudioContext.value = null;
-			uni.$emit('destory-stop')	
+			uni.$emit('destory-stop')
 		}
 	}
-	// 离开当前页面 停止播放
-	uni.$on('back-outpage',() => {
+
+	function doBackOutpage() {
 		handleStop();
-	})
+	}
 
-	// 播放过程中点击同一个视频触发终止
-	uni.$on('repeat-play-to-stop',() => {
+	function doRepeatPlayToStop() {
 		handleStop();
-	})
+	}
 
-	// 试题切换停止播放
-	uni.$on('swiper-change',() => {
+	function doSwiperChange() {
 		handleStop();
-	})
-	// 解析关闭 停止播放
-	uni.$on('question-jiexi-close',() => {
+	}
+
+	function doQuestionJiexiClose() {
 		handleStop();
-	})
-	// 交卷 停止播放
-	uni.$on('unitTest-submit', () => {
+	}
+
+	function doUnitestSubmit() {
 		handleStop();
+	}
+
+	// 离开当前页面 停止播放
+	uni.$on('back-outpage', doBackOutpage)
+
+	// 播放过程中点击同一个视频触发终止
+	uni.$on('repeat-play-to-stop', doRepeatPlayToStop)
+
+	// 试题切换停止播放
+	uni.$on('swiper-change', doSwiperChange)
+	// 解析关闭 停止播放
+	uni.$on('question-jiexi-close', doQuestionJiexiClose)
+	// 交卷 停止播放
+	uni.$on('unitTest-submit', doUnitestSubmit)
+	onUnmounted(() => {
+		uni.$off('back-outpage', doBackOutpage)
+		uni.$off('repeat-play-to-stop', doRepeatPlayToStop)
+		// 试题切换停止播放
+		uni.$off('swiper-change', doSwiperChange)
+		// 解析关闭 停止播放
+		uni.$off('question-jiexi-close', doQuestionJiexiClose)
+		// 交卷 停止播放
+		uni.$off('unitTest-submit', doUnitestSubmit)
 	})
-	
 	return {
 		options,
 		handlePlay,
 		handleStop,
 		innerAudioContext
 	}
+}
+
+
+export class UseAudio {
+	instance = null;
+	options = null;
+	doPlay = debounce((data) => {
+		if (this.options) {
+			if(this.options.stId == data.stId && this.options.index == data.index) {
+				// console.log('同一个音频播放应该暂停')
+				uni.$emit('reset-playing-status', this.options)
+				this.innerAudioContext.pause();
+				this.destory();
+				this.init();
+				return;
+			}
+			
+			// 切换不同音频
+			if(this.options.stId !== data.stId || this.options.index != data.index) {
+				// console.log('切换不同音频')
+				uni.$emit('reset-playing-status', this.options)
+			}
+		}
+		this.options = data;
+		this.innerAudioContext.src = data.url;
+		this.innerAudioContext.play();
+	},50)
+	constructor() {
+		this.init();
+	}
+
+	init() {
+		this.innerAudioContext = uni.createInnerAudioContext();
+		this.innerAudioContext.autoplay = false;
+		this.innerAudioContext.onPlay(() => {
+			uni.$emit("yy-audio-playing", this.options);
+		});
+		this.innerAudioContext.onError(() => {
+			uni.$emit("yy-audio-error", this.options);
+		});
+		this.innerAudioContext.onEnded(() => {
+			uni.$emit("yy-audio-end", this.options);
+		});
+	}
+
+	static create() {
+		if (this.instance) {
+			return this;
+		}
+		this.instance = new UseAudio()
+		return this;
+	}
+
+
+	play(data) {
+		this.doPlay(data);
+	}
+
+	pause() {
+		this.innerAudioContext.pause();
+	}
+
+	stop() {
+		this.innerAudioContext.stop();
+	}
+
+	destory() {
+		this.innerAudioContext.destroy();
+		this.innerAudioContext = null;
+		this.options = null;
+	}
 }

+ 4 - 3
components/questionJiexi/questionJiexiYingyu.vue

@@ -13,7 +13,7 @@
 						<view class="slfx-title"></view>
 						<!-- <view class="slfx-content"> {{data.answer}}</view> -->
 						<!-- <rich-text class="slfx-content" :nodes="data.answer"></rich-text> -->
-						<textReplaceIconVue	:question="data" :text="data.answer" :placeholders="data.placeholders" class="slfx-content"></textReplaceIconVue>
+						<textReplaceIconVue :code="code" :question="data" :text="data.answer" :placeholders="data.placeholders" class="slfx-content"></textReplaceIconVue>
 
 						<!-- 视频讲解 -->
 						<view class="spjj-title" v-if="videoId"></view>
@@ -48,6 +48,9 @@
 				type: [String,Number],
 				default: 1
 			},
+			code: {
+				type: String
+			}
 		},
 		data() {
 			return {
@@ -61,11 +64,9 @@
 			}
 		},
 		onHide() {
-			console.log('onHideonHideonHideonHide');
 			this.hideFlag = 'hide'
 		},
 		onUnload() {
-			console.log('onUnloadonUnloadonUnloadonUnloadonUnload');
 			this.hideFlag = 'hide'
 		},
 		methods: {

+ 2 - 43
pages/unitTest/index.vue

@@ -12,7 +12,7 @@
 						<danxuan :question="item" v-if="item.type == '1'"></danxuan>
 						<panduan :question="item" v-if="item.type == '2'"></panduan>
 						<tiankong :question="item" v-if="item.type == '3'" :placeholders="item.placeholders"></tiankong>
-						<yingyuDanxuan :question="ceshiData" v-if="item.type == '4'" :placeholders="item.placeholders">
+						<yingyuDanxuan :question="item" v-if="item.type == '4'" :placeholders="item.placeholders">
 						</yingyuDanxuan>
 					</view>
 				</template>
@@ -34,8 +34,6 @@
 		<!-- 填空 -->
 		<FillItem :value="result" ref="popupRef" @blur="onBlur"></FillItem>
 
-		<!-- 音频播放组件 -->
-		<mtaRadio></mtaRadio>
 	</view>
 
 </template>
@@ -47,8 +45,7 @@
 	import danxuan from "@/components/question/danxuan.vue";
 	import panduan from "@/components/question/panduan.vue";
 	import tiankong from "@/components/question/tiankong.vue";
-	 import yingyuDanxuan from "@/components/question/yingyu/danxuanCeshi.vue";
-	//import yingyuDanxuan from "@/components/question/yingyu/danxuan.vue";
+	import yingyuDanxuan from "@/components/question/yingyu/danxuan.vue";
 	import chengji from "@/components/chengji/chengji.vue";
 	import uniPointsVue from '@/components/points/uni-points.vue';
 	import * as httpUnit from "@/api/unitTest.js"
@@ -67,8 +64,6 @@
 		onLoad
 	} from "@dcloudio/uni-app"
 
-
-
 	const {
 		count,
 		total,
@@ -96,42 +91,6 @@
 	const popupRef = ref(null);
 	const result = ref('');
 	const curTiankong = ref(null);
-
-	const ceshiData = reactive({
-			"stId": 378,
-			"type": 4,
-			"name": "<p>发音:/b/ 1231[yingyu1]</p>",
-			"result": "0",
-			"answer": "<p>单词book发音为/bʊk/ [yingyu5]; 单词pool的发音是/puːl/ [yingyu4]。</p>",
-			"audios": "https://ezy-app.oss-cn-beijing.aliyuncs.com/test/resource/uploadFile1a3bd1236181491b8de49e84857a9163.MP3,https://ezy-app.oss-cn-beijing.aliyuncs.com/test/resource/uploadFile16b16267eafb43b6a272b8b212049ae4.MP3,https://ezy-app.oss-cn-beijing.aliyuncs.com/test/resource/uploadFileb23646275ada46769e76a3ae0dba230e.MP3,https://ezy-app.oss-cn-beijing.aliyuncs.com/test/resource/uploadFileeff5e2bb7a6f4a0d9bc78b503ebea846.MP3,https://ezy-app.oss-cn-beijing.aliyuncs.com/test/resource/uploadFile6cbe483d691b4e5eb13401e301d62c9c.mp3",
-			"jiangjie": null,
-			"optList": [{
-				"neirong": "<p>book [yingyu2]</p>",
-				"audio":"https://ezy-app.oss-cn-beijing.aliyuncs.com/test/resource/uploadFile1a3bd1236181491b8de49e84857a9163.MP3"
-			}, {
-				"neirong": "<p>pool [yingyu3]</p>",
-				"audio":"https://ezy-app.oss-cn-beijing.aliyuncs.com/test/resource/uploadFile16b16267eafb43b6a272b8b212049ae4.MP3"
-			}]
-		},
-		{
-			"stId": 379,
-			"type": 4,
-			"name": "<p>判断划线部分发音是否相同。</p><p><br></p><p>park  [yingyu1]</p><p><br></p><p>cup [yingyu2]</p>",
-			"result": "0",
-			"answer": "<p>在单词park中,p发 /p/音 [yingyu3];在单词cup中,p发/p/音 [yingyu4],故发音相同。</p>",
-			"audios": "https://ezy-app.oss-cn-beijing.aliyuncs.com/test/resource/uploadFile304fcea7440e400ca2bd0207354b2fa3.MP3,https://ezy-app.oss-cn-beijing.aliyuncs.com/test/resource/uploadFile052863fbfd074e718c63509db47f0f6c.MP3,https://ezy-app.oss-cn-beijing.aliyuncs.com/test/resource/uploadFilefee406d7614443609b450b4f260b33e5.MP3,https://ezy-app.oss-cn-beijing.aliyuncs.com/test/resource/uploadFile725a16a4dea642ccaf0129ae877b4a7c.MP3",
-			"jiangjie": null,
-			"optList": [{
-				"neirong": "<p>相同</p>",
-					"audio":"https://ezy-app.oss-cn-beijing.aliyuncs.com/test/resource/uploadFile1a3bd1236181491b8de49e84857a9163.MP3"
-			}, {
-				"neirong": "<p>不同</p>",
-					"audio":"https://ezy-app.oss-cn-beijing.aliyuncs.com/test/resource/uploadFile1a3bd1236181491b8de49e84857a9163.MP3"
-			}]
-		}
-	);
-
-
 	function getPopupRef() {
 		return popupRef.value;
 	}

+ 2 - 4
pages/wrong/index.vue

@@ -66,9 +66,7 @@
 		</view>
 
 		<cuoti ref="wrongRef" :cardId="cardId" :list="data.wrongList" @back="handleBackFromCuoti"></cuoti>
-		<CustomTabBar :cardId="cardId" :nianji="nianji" :zhangId="zhangId"></CustomTabBar>
-    <!-- 音频播放组件 -->
-    <mtaRadio></mtaRadio>
+		<CustomTabBar :cardId="cardId+''" :nianji="nianji" :zhangId="zhangId"></CustomTabBar>
 	</view>
 </template>
 
@@ -84,7 +82,6 @@
 		onLoad
 	} from "@dcloudio/uni-app";
 	import cuoti from "@/components/chengji/chengji.vue";
-  import mtaRadio from '@/components/question/yingyu/mtaRadio.vue'
 	import {
 		getWrongInfo
 	} from "@/api/wrong";
@@ -134,6 +131,7 @@
 
 	function handleBackFromCuoti() {
 		wrongRef.value.closePopup();
+		uni.$emit('back-outpage')
 	}
 
 	function onChangeTab(e) {