wangguoyu před 2 měsíci
rodič
revize
814f8757ba
1 změnil soubory, kde provedl 139 přidání a 36 odebrání
  1. 139 36
      pages/newEnglish/components/readContent.vue

+ 139 - 36
pages/newEnglish/components/readContent.vue

@@ -1,50 +1,55 @@
 <!-- 单词区 && 音标区:最多16位,超过换行 -->
 <!-- 单音节最长:swimming 多音节最长:transportation -->
 <template>
-		<selectTypesVue activeSelect="3"></selectTypesVue>
-		<view class="ezy-border-body">
-			<view class="words-du-box">
-		
+	<selectTypesVue activeSelect="3"></selectTypesVue>
+	<view class="ezy-border-body">
+		<view class="words-du-box">
+
 			<view class="du-body-box">
-			<!-- 单词区 -->
-			<view class="word-circle-box">{{data.name}}</view>
-			<!-- 音标区 -->
-			<view class="yb-play-box du-yb-play-box">
-				<yinbiaoTxtVue :yinbiao="activeWord.yinbiao"></yinbiaoTxtVue>
-				<!-- 音频播放 -->
-				<audioTwoVue :active-word="activeWord" @play-audio="handlePlay"></audioTwoVue>
-			</view>
-			<view class="pin-words-explain-box du-words-explain-box">
-				<view class="words-explain-item" v-if="data.jianyi&&data.jianyi.length>0"
-					v-for="(item,index) in data.jianyi" :key="index">
-					{{item}}
+				<!-- 单词区 -->
+				<view class="word-circle-box">{{data.name}}</view>
+				<!-- 音标区 -->
+				<view class="yb-play-box du-yb-play-box">
+					<yinbiaoTxtVue :yinbiao="activeWord.yinbiao"></yinbiaoTxtVue>
+					<!-- 音频播放 -->
+					<audioTwoVue :active-word="activeWord" @play-audio="handlePlay"></audioTwoVue>
+				</view>
+				<view class="pin-words-explain-box du-words-explain-box">
+					<view class="words-explain-item" v-if="data.jianyi&&data.jianyi.length>0"
+						v-for="(item,index) in data.jianyi" :key="index">
+						{{item}}
+					</view>
 				</view>
 			</view>
-		</view>
 
-		<view class="mike-play-box">
-			<view class="mike-play-tip" v-if="isRecording">录音中...</view>
-			<view class="mike-play-tip" v-else>长按 读一读</view>
-			<!-- 	<view class="status">{{ recordingStatus }}</view> -->
-			<!-- 	<view class="duration" v-if="isRecording">录音时长: {{ Math.floor(duration) }}秒</view> -->
-			<view class="du-btn-box">
-				<button class="play-btn" :class="{ 'playing-btn': isPlaying}" @click="playVoice"
-					v-if="voicePath"></button>
-				<button class="mike-btn" :class="{ 'mike-az-btn': isRecording}" @touchstart="handleTouchStart"
-					@touchend="handleTouchEnd" @touchcancel="handleTouchEnd" :disabled="isPlaying">
-					<!--{{ isRecording ? '松开结束' : '按住录音' }}
+			<view class="mike-play-box">
+				<view class="mike-play-tip" v-if="isRecording">录音中...</view>
+				<view class="mike-play-tip" v-else>长按 读一读</view>
+				<!-- 	<view class="status">{{ recordingStatus }}</view> -->
+				<!-- 	<view class="duration" v-if="isRecording">录音时长: {{ Math.floor(duration) }}秒</view> -->
+				<view class="du-btn-box">
+					<button class="play-btn" :class="{ 'playing-btn': isPlaying}" @click="playVoice"
+						v-if="voicePath"></button>
+					<button class="mike-btn" :class="{ 'mike-az-btn': isRecording}" @touchstart="handleTouchStart"
+						@touchend="handleTouchEnd" @touchcancel="handleTouchEnd" :disabled="isPlaying">
+						<!--{{ isRecording ? '松开结束' : '按住录音' }}
 						<view v-if="isPlaying" class="disabled-mask">播放中不可录音</view> -->
-				</button>
-			</view>
+					</button>
+				</view>
 
-			<!-- 		<button class="play-btn" :class="{ disabled: isRecording || !voicePath }" @click="playVoice"
+				<!-- 		<button class="play-btn" :class="{ disabled: isRecording || !voicePath }" @click="playVoice"
 				:disabled="isRecording || !voicePath">
 				{{ isPlaying ? '播放中...' : '播放录音' }}
 				<view v-if="isRecording" class="disabled-mask">录音中不可播放</view>
 			</button> -->
+			</view>
 		</view>
-	  </view>
 	</view>
+	<uni-popup ref="statusPopup" :animation="false" :is-mask-click="false"
+		mask-background-color="rgba(51, 137, 217, 0.95);">
+		<view class="ezy-image-dialog luyin">
+		</view>
+	</uni-popup>
 </template>
 
 <script setup>
@@ -95,7 +100,9 @@
 	// 获取录音和音频播放管理器
 	const recorderManager = uni.getRecorderManager()
 	const innerAudioContext = uni.createInnerAudioContext()
-
+	const statusPopup = ref(null)
+	const popupImage = ref('')
+	const statusAudio = uni.createInnerAudioContext()
 	// 初始化录音器
 	const initRecorder = () => {
 		recorderManager.onStart(() => {
@@ -124,6 +131,7 @@
 					title: '录音成功',
 					icon: 'success'
 				})
+				showStatusPopup('', '录音成功!', '/static/mp3/newYingyu/right-tip.mp3')
 			} else {
 				uni.showToast({
 					title: '录音失败',
@@ -166,15 +174,98 @@
 			})
 		})
 	}
+
+
+	const showStatusPopup = (imagePath, text, audioPath) => {
+		console.log('audioPath', audioPath);
+		// 播放音效
+		statusAudio.stop()
+		statusAudio.src = audioPath
+		statusAudio.play()
+
+		// 显示弹窗
+		statusPopup.value.open()
+
+	}
+
+	const checkMicrophonePermission = async () => {
+		try {
+			// 1. 检查平台
+			const {
+				platform
+			} = uni.getSystemInfoSync()
+
+			// 2. Android权限处理
+			if (platform === 'android') {
+				console.log('1111');
+				const status = await new Promise(resolve => {
+					plus.android.requestPermissions(
+						['android.permission.RECORD_AUDIO'],
+						(result) => {
+							console.log('22222', result);
+							if (result.deniedAlways?.length) {
+								resolve(false) // 永久拒绝
+							} else if (result.denied?.length) {
+								resolve(false) // 拒绝
+							} else {
+								resolve(true) // 已授权
+							}
+						},
+						() => resolve(false) // 出错
+					)
+				})
+				console.log('status', status);
+				if (!status) {
+					uni.showToast({
+						title: '需要麦克风权限',
+						icon: 'none'
+					})
+					return false
+				}
+			}
+			// 3. iOS权限处理
+			else if (platform === 'ios') {
+				const granted = await new Promise(resolve => {
+					plus.ios.import('AVAudioSession').then(AVAudioSession => {
+						const session = plus.ios.invoke(AVAudioSession, 'sharedInstance')
+						plus.ios.invoke(session, 'requestRecordPermission:', resolve)
+						plus.ios.deleteObject(session)
+					}).catch(() => resolve(false))
+				})
+
+				if (!granted) {
+					uni.showToast({
+						title: '请在设置中允许麦克风权限',
+						icon: 'none'
+					})
+					return false
+				}
+			}
+
+			return true
+		} catch (error) {
+			console.error('权限检查错误:', error)
+			return false
+		}
+	}
+
 	async function handlePlay(opt) {
 		emits('play-audio', opt)
 	}
 
 	// 处理触摸开始(移动端)
-	const handleTouchStart = (e) => {
+	const handleTouchStart = async(e) => {
 		e.preventDefault()
 		if (isPlaying.value) return
 
+		// 先检查权限
+		const hasPermission = await checkMicrophonePermission()
+		if (!hasPermission) {
+			return
+		}
+
+
+
 		// 设置长按计时器,500ms后才开始录音
 		longPressTimer.value = setTimeout(() => {
 			startRecording()
@@ -195,9 +286,16 @@
 		handleTouchEnd(e) // 与touchend同样处理
 	}
 	// 开始录音
-	const startRecording = () => {
+	const startRecording = async () => {
 		if (isRecording.value || !isRecorderReady.value) return
 
+		const hasPermission = await checkMicrophonePermission()
+		if (!hasPermission) {
+			// 权限被拒绝后重置状态
+			isRecording.value = false
+			isRecorderReady.value = true
+			return
+		}
 		console.log('开始录音')
 		//recordingStatus.value = '准备录音...'
 		isRecording.value = true // 提前设置状态,避免延迟
@@ -215,7 +313,7 @@
 		}
 
 		try {
-			recorderManager.start(options)
+			await recorderManager.start(options)
 		} catch (e) {
 			console.error('启动录音失败:', e)
 			isRecording.value = false
@@ -283,6 +381,10 @@
 	onMounted(() => {
 		initItem()
 		initRecorder()
+		statusAudio.autoplay = false
+		statusAudio.onEnded(() => {
+			statusPopup.value.close()
+		})
 	})
 
 	onUnmounted(() => {
@@ -293,6 +395,7 @@
 			recorderManager.stop()
 			innerAudioContext.stop()
 			innerAudioContext.destroy()
+			statusAudio.destroy()
 		} catch (e) {
 			console.error('清理资源时出错:', e)
 		}