wangguoyu 3 månader sedan
förälder
incheckning
00329744d0

+ 3 - 3
pages/newEnglish/components/mainCard.vue

@@ -1,6 +1,6 @@
 <template>
 	<swiper class="word-view-swiper-box" :indicator-dots="false" :autoplay="false" :circular="false">
-		<swiper-item>
+	<!-- 	<swiper-item>
 			<view class="swiper-item uni-bg-red">
 				<xuePage :active-word="activeWord" :active-words="activeWords" @play-audio="handlePlayAudio" :pageData="pageData"></xuePage>
 			</view>
@@ -9,10 +9,10 @@
 			<view class="swiper-item uni-bg-red">
 				<pinPageVue :active-word="activeWord" :active-words="activeWords" @play-audio="handlePlayAudio"></pinPageVue>
 			</view>
-		</swiper-item>
+		</swiper-item> -->
 		<swiper-item>
 			<view class="swiper-item uni-bg-blue">
-				<readContent :active-word="activeWord" :pageData="pageData" :active-words="activeWords"></readContent>
+				<readContent :active-word="activeWord" :pageData="pageData" @play-audio="handlePlayAudio" :active-words="activeWords"></readContent>
 			</view>
 		</swiper-item>
 		<swiper-item>

+ 238 - 26
pages/newEnglish/components/readContent.vue

@@ -4,43 +4,55 @@
 		<view class="words-xuan-box">
 			<!-- 单词区 -->
 			<view class="show-words-box"> {{data.name}} </view>
-			<!--  音标区  -->
-			<view class="yb-play-box">
-				<text>{{data.yinbiao}}</text>
-				<!-- active -->
-
-				<icon class="yb-play-btn"></icon>
-				<icon class="yb-playing-btn" v-if="false"></icon>
-			</view>
 
 			<view style="text-align: center;">
-				<text v-if="data.jianyi&&data.jianyi.length>0" v-for="(item,index) in data.jianyi"
-					:key="index">
+				<text v-if="data.jianyi&&data.jianyi.length>0" v-for="(item,index) in data.jianyi" :key="index">
 					{{item}}
 				</text>
 			</view>
 
-			<view>
-				<view class="audio-play-btn"></view>
-				<!-- 播放 -->
-				<view class="audio-playing-btn" v-if="false"></view>
+			<view class="yb-play-box xue-yb-play-box">
+				<yinbiaoTxtVue :yinbiao="activeWord.yinbiao"></yinbiaoTxtVue>
+				<!-- 音频播放 -->
+				<audioTwoVue :active-word="activeWord" @play-audio="handlePlay"></audioTwoVue>
 			</view>
+			<view class="container">
+				<!-- 	<view class="status">{{ recordingStatus }}</view> -->
+				<!-- 	<view class="duration" v-if="isRecording">录音时长: {{ Math.floor(duration) }}秒</view> -->
+				<button class="record-btn" :class="{ recording: isRecording, disabled: isPlaying }"
+					@touchstart="handleTouchStart" @touchend="handleTouchEnd" @touchcancel="handleTouchEnd"
+					:disabled="isPlaying">
+					{{ isRecording ? '松开结束' : '按住录音' }}
+					<!-- 	<view v-if="isPlaying" class="disabled-mask">播放中不可录音</view> -->
+				</button>
 
+				<button class="play-btn" @click="playVoice" v-if="voicePath">
+					播放小喇叭
+				</button>
+				<!-- 		<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>
 </template>
 
 <script setup>
-	import selectWordsVue from './selectWords.vue';
 	import selectTypesVue from './selectTypes.vue';
+	import audioTwoVue from './audioTwo.vue';
+	import yinbiaoTxtVue from "./yinbiaoTxt.vue"
 	import {
 		onLoad
 	} from "@dcloudio/uni-app"
 	import {
 		reactive,
 		ref,
-		onMounted
+		onMounted,
+		onUnmounted
 	} from 'vue';
+
 	const props = defineProps({
 		activeWord: {
 			type: Object,
@@ -52,26 +64,226 @@
 			type: Array
 		},
 	})
+	const emits = defineEmits(['play-audio'])
 	let tabFlag = ref(1)
 	const audioInfo = ref(null)
-
 	const data = reactive({
 		name: '',
 		yinbiao: '',
-		jianyi:[]
+		jianyi: []
 	})
 
-	onLoad(() => {
-		initItem()
-	})
+	// 录音相关状态
+	const isRecording = ref(false)
+	const isPlaying = ref(false)
+	const voicePath = ref('')
+	const duration = ref(0)
+	const timer = ref(null)
+	const recordingStatus = ref('准备就绪')
+	const startTime = ref(0)
+	const longPressTimer = ref(null) // 长按计时器
 
-	function initItem() {
-		console.log('data',data);
+
+	// 获取录音和音频播放管理器
+	const recorderManager = uni.getRecorderManager()
+	const innerAudioContext = uni.createInnerAudioContext()
+
+	// 初始化录音器
+	const initRecorder = () => {
+		recorderManager.onStart(() => {
+			console.log('recorder start')
+			isRecording.value = true
+			//	recordingStatus.value = '录音中...'
+			//	startTime.value = Date.now()
+			//	startTimer()
+		})
+		recorderManager.onStop((res) => {
+			//	const recordTime = (Date.now() - startTime.value) / 1000 // 计算实际录音时间
+			isRecording.value = false
+			// if (recordTime < 3) {
+			// 	uni.showToast({
+			// 		title: '录音时间太短,需3秒以上',
+			// 		icon: 'none'
+			// 	})
+			// 	return
+			// }
+
+			if (res.tempFilePath) {
+				voicePath.value = res.tempFilePath
+				uni.showToast({
+					title: '录音成功',
+					icon: 'success'
+				})
+			} else {
+				uni.showToast({
+					title: '录音失败',
+					icon: 'none'
+				})
+			}
+		})
+
+		recorderManager.onError((res) => {
+			console.error('recorder error', res)
+			//stopTimer()
+			isRecording.value = false
+			//recordingStatus.value = `录音错误: ${res.errMsg}`
+			uni.showToast({
+				title: `录音出错: ${res.errMsg}`,
+				icon: 'none'
+			})
+		})
+
+		innerAudioContext.onPlay(() => {
+			isPlaying.value = true
+			//recordingStatus.value = '播放中...'
+		})
+
+		innerAudioContext.onEnded(() => {
+			isPlaying.value = false
+			//recordingStatus.value = '播放完成'
+		})
+
+		innerAudioContext.onError((res) => {
+			isPlaying.value = false
+			console.error('play error', res)
+			uni.showToast({
+				title: '播放失败',
+				icon: 'none'
+			})
+		})
+	}
+	async function handlePlay(opt) {
+		emits('play-audio', opt)
+	}
+	// 检查权限
+	const checkPermission = () => {
+		uni.authorize({
+			scope: 'scope.record',
+			success: () => {
+				console.log('已授权录音权限')
+			},
+			fail: (err) => {
+				console.log('未授权录音权限', err)
+				uni.showModal({
+					title: '提示',
+					content: '需要录音权限才能使用此功能',
+					confirmText: '去设置',
+					success: (res) => {
+						if (res.confirm) {
+							uni.openSetting()
+						}
+					}
+				})
+			}
+		})
+	}
+
+	// 处理触摸开始(移动端)
+	const handleTouchStart = (e) => {
+		e.preventDefault()
+		if (isPlaying.value) return
+
+		// 设置长按计时器,500ms后才开始录音
+		longPressTimer.value = setTimeout(() => {
+			startRecording()
+		}, 400)
+	}
+
+	// 处理触摸结束(移动端)
+	const handleTouchEnd = (e) => {
+		e.preventDefault()
+		clearTimeout(longPressTimer.value)
+		if (isRecording.value) {
+			endRecording()
+		}
+	}
+
+	// 处理触摸取消(移动端,如被系统中断)
+	const handleTouchCancel = (e) => {
+		handleTouchEnd(e) // 与touchend同样处理
+	}
+	// 开始录音
+	const startRecording = () => {
+		if (isRecording.value) return
+
+		console.log('开始录音')
+		//recordingStatus.value = '准备录音...'
+		isRecording.value = true // 提前设置状态,避免延迟
+		//	startTime.value = Date.now()
+		//	startTimer()
+
+		const options = {
+			duration: 60000,
+			sampleRate: 44100,
+			numberOfChannels: 1,
+			encodeBitRate: 192000,
+			format: 'mp3',
+			frameSize: 50
+		}
+
+		recorderManager.start(options)
+	}
+
+	// 结束录音
+	const endRecording = () => {
+		if (!isRecording.value) return
+
+		console.log('停止录音')
+		isRecording.value = false
+		//stopTimer()
+		recorderManager.stop()
+	}
+	const getRecordingDuration = () => {
+		if (!isRecording.value) return 0
+		return Math.floor((Date.now() - startTime.value) / 1000)
+	}
+	// 播放录音
+	const playVoice = () => {
+		if (isRecording.value || !voicePath.value) return
+
+		console.log('播放录音:', voicePath.value)
+		innerAudioContext.src = voicePath.value
+		innerAudioContext.play()
+	}
+
+	// // 计时器相关
+	// const startTimer = () => {
+	//   duration.value = 0
+	//   const start = Date.now()
+	//   timer.value = setInterval(() => {
+	//     // 计算实际经过的时间(毫秒),然后转换为秒
+	//     const elapsed = Math.floor((Date.now() - start) / 1000)
+	//     duration.value = elapsed
+	//   }, 200) // 缩短检查间隔,但计算基于实际时间差
+	// }
+
+	// const stopTimer = () => {
+	//   if (timer.value) {
+	//     clearInterval(timer.value)
+	//     timer.value = null
+	//   }
+	//   duration.value = 0
+	// }
+
+	// 初始化单词数据
+	const initItem = () => {
 		data.name = props.activeWord.name;
 		data.yinbiao = props.activeWord.yinbiao;
 		data.jianyi = props.activeWord.jianyi;
+		console.log('data',data);
 	}
-</script>
 
-<style>
-</style>
+	onMounted(() => {
+			initItem()
+		initRecorder()
+		checkPermission()
+	
+	})
+
+	onUnmounted(() => {
+		//stopTimer()
+		clearTimeout(longPressTimer.value)
+		recorderManager.stop()
+		innerAudioContext.stop()
+	})
+</script>

+ 390 - 0
pages/newEnglish/components/readContent2.vue

@@ -0,0 +1,390 @@
+<template>
+	<view>
+		<selectTypesVue activeSelect="3"></selectTypesVue>
+		<view class="words-xuan-box">
+			<!-- 单词区 -->
+			<view class="show-words-box"> {{data.name}} </view>
+			<!--  音标区  -->
+			<view class="yb-play-box">
+				<text>{{data.yinbiao}}</text>
+				<icon class="yb-play-btn"></icon>
+				<icon class="yb-playing-btn" v-if="false"></icon>
+			</view>
+
+			<view style="text-align: center;">
+				<text v-if="data.jianyi&&data.jianyi.length>0" v-for="(item,index) in data.jianyi" :key="index">
+					{{item}}
+				</text>
+			</view>
+
+			<view>
+				<view class="audio-play-btn"></view>
+				<view class="audio-playing-btn" v-if="false"></view>
+			</view>
+			<view class="container">
+				<view class="status">{{ recordingStatus }}</view>
+				<view class="duration" v-if="isRecording">录音时长: {{ Math.floor(duration) }}秒</view>
+
+				<button class="record-btn" :class="{ recording: isRecording, disabled: isPlaying }"
+					@touchstart="handleTouchStart" @touchend="handleTouchEnd" @touchcancel="handleTouchEnd"
+					@mousedown="handleMouseDown" @mouseup="handleMouseUp" @mouseleave="handleMouseLeave"
+					:disabled="isPlaying">
+					{{ isRecording ? '松开结束' : '按住录音' }}
+					<view v-if="isPlaying" class="disabled-mask">播放中不可录音</view>
+				</button>
+
+				<button class="play-btn" :class="{ disabled: isRecording || !voicePath }" @click="playVoice"
+					:disabled="isRecording || !voicePath">
+					{{ isPlaying ? '播放中...' : '播放录音' }}
+					<view v-if="isRecording" class="disabled-mask">录音中不可播放</view>
+				</button>
+
+				<view class="tips">提示:长按按钮录音,松开结束(需3秒以上)</view>
+			</view>
+		</view>
+	</view>
+</template>
+
+<script setup>
+	import selectTypesVue from './selectTypes.vue';
+	import {
+		onLoad
+	} from "@dcloudio/uni-app"
+	import {
+		reactive,
+		ref,
+		onMounted,
+		onUnmounted
+	} from 'vue';
+
+	const props = defineProps({
+		activeWord: {
+			type: Object,
+		},
+		pageData: {
+			type: Object,
+		},
+		activeWords: {
+			type: Array
+		},
+	})
+
+	let tabFlag = ref(1)
+	const audioInfo = ref(null)
+	const data = reactive({
+		name: '',
+		yinbiao: '',
+		jianyi: []
+	})
+
+	// 录音相关状态
+	const isRecording = ref(false)
+	const isPlaying = ref(false)
+	const voicePath = ref('')
+	const duration = ref(0)
+	const timer = ref(null)
+	const recordingStatus = ref('准备就绪')
+	const startTime = ref(0)
+	const longPressTimer = ref(null) // 长按计时器
+	const MIN_RECORD_TIME = 3 // 最小录音时间3秒
+
+	// 获取录音和音频播放管理器
+	const recorderManager = uni.getRecorderManager()
+	const innerAudioContext = uni.createInnerAudioContext()
+
+	// 初始化录音器
+	const initRecorder = () => {
+		recorderManager.onStart(() => {
+			console.log('recorder start')
+			isRecording.value = true
+			recordingStatus.value = '录音中...'
+			startTime.value = Date.now()
+			startTimer()
+		})
+
+		recorderManager.onStop((res) => {
+			console.log('recorder stop', res)
+			const recordTime = (Date.now() - startTime.value) / 1000
+
+			stopTimer()
+			isRecording.value = false
+
+			if (recordTime < MIN_RECORD_TIME) {
+				recordingStatus.value = '录音时间太短(需3秒以上)'
+				uni.showToast({
+					title: '录音时间太短,需3秒以上',
+					icon: 'none'
+				})
+				return
+			}
+
+			if (res.tempFilePath) {
+				voicePath.value = res.tempFilePath
+				recordingStatus.value = `录音完成,时长: ${Math.floor(recordTime)}秒`
+				uni.showToast({
+					title: '录音成功',
+					icon: 'success'
+				})
+			} else {
+				recordingStatus.value = '录音失败'
+				uni.showToast({
+					title: '录音失败',
+					icon: 'none'
+				})
+			}
+		})
+
+		recorderManager.onError((res) => {
+			console.error('recorder error', res)
+			stopTimer()
+			isRecording.value = false
+			recordingStatus.value = `录音错误: ${res.errMsg}`
+			uni.showToast({
+				title: `录音出错: ${res.errMsg}`,
+				icon: 'none'
+			})
+		})
+
+		innerAudioContext.onPlay(() => {
+			isPlaying.value = true
+			recordingStatus.value = '播放中...'
+		})
+
+		innerAudioContext.onEnded(() => {
+			isPlaying.value = false
+			recordingStatus.value = '播放完成'
+		})
+
+		innerAudioContext.onError((res) => {
+			isPlaying.value = false
+			console.error('play error', res)
+			uni.showToast({
+				title: '播放失败',
+				icon: 'none'
+			})
+		})
+	}
+
+	// 检查权限
+	const checkPermission = () => {
+		uni.authorize({
+			scope: 'scope.record',
+			success: () => {
+				console.log('已授权录音权限')
+			},
+			fail: (err) => {
+				console.log('未授权录音权限', err)
+				uni.showModal({
+					title: '提示',
+					content: '需要录音权限才能使用此功能',
+					confirmText: '去设置',
+					success: (res) => {
+						if (res.confirm) {
+							uni.openSetting()
+						}
+					}
+				})
+			}
+		})
+	}
+
+	// 处理触摸开始(移动端)
+	const handleTouchStart = (e) => {
+		e.preventDefault()
+		if (isPlaying.value) return
+
+		// 设置长按计时器,500ms后才开始录音
+		longPressTimer.value = setTimeout(() => {
+			startRecording()
+		}, 400)
+	}
+
+	// 处理触摸结束(移动端)
+	const handleTouchEnd = (e) => {
+		e.preventDefault()
+		clearTimeout(longPressTimer.value)
+		if (isRecording.value) {
+			endRecording()
+		}
+	}
+
+	// 处理触摸取消(移动端,如被系统中断)
+	const handleTouchCancel = (e) => {
+		handleTouchEnd(e) // 与touchend同样处理
+	}
+	// 处理鼠标按下(桌面端)
+	const handleMouseDown = (e) => {
+		e.preventDefault()
+		if (isPlaying.value) return
+
+		longPressTimer.value = setTimeout(() => {
+			startRecording()
+		}, 500)
+	}
+
+	// 处理鼠标抬起(桌面端)
+	const handleMouseUp = (e) => {
+		e.preventDefault()
+		clearTimeout(longPressTimer.value)
+		if (isRecording.value) {
+			endRecording()
+		}
+	}
+
+	// 处理鼠标移出按钮区域
+	const handleMouseLeave = (e) => {
+		clearTimeout(longPressTimer.value)
+		if (isRecording.value) {
+			endRecording()
+		}
+	}
+
+	// 开始录音
+	const startRecording = () => {
+		if (isRecording.value) return
+
+		console.log('开始录音')
+		recordingStatus.value = '准备录音...'
+		isRecording.value = true // 提前设置状态,避免延迟
+		startTime.value = Date.now()
+		startTimer()
+
+		const options = {
+			duration: 60000,
+			sampleRate: 44100,
+			numberOfChannels: 1,
+			encodeBitRate: 192000,
+			format: uni.getSystemInfoSync().platform === 'android' ? 'amr' : 'mp3',
+			frameSize: 50
+		}
+
+		recorderManager.start(options)
+	}
+
+	// 结束录音
+	const endRecording = () => {
+		if (!isRecording.value) return
+
+		console.log('停止录音')
+		isRecording.value = false
+		stopTimer()
+		recorderManager.stop()
+	}
+	// 播放录音
+	const playVoice = () => {
+		if (isRecording.value || !voicePath.value) return
+
+		console.log('播放录音:', voicePath.value)
+		innerAudioContext.src = voicePath.value
+		innerAudioContext.play()
+	}
+
+	// 计时器相关
+	const startTimer = () => {
+		duration.value = 0
+		timer.value = setInterval(() => {
+			duration.value += 1 // 每秒增加1,而不是0.1
+		}, 1000) // 间隔改为1000ms
+	}
+
+	const stopTimer = () => {
+		if (timer.value) {
+			clearInterval(timer.value)
+			timer.value = null
+		}
+		duration.value = 0
+	}
+
+	// 初始化单词数据
+	const initItem = () => {
+		data.name = props.activeWord.name;
+		data.yinbiao = props.activeWord.yinbiao;
+		data.jianyi = props.activeWord.jianyi;
+	}
+
+	onMounted(() => {
+		initRecorder()
+		checkPermission()
+		initItem()
+	})
+
+	onUnmounted(() => {
+		stopTimer()
+		clearTimeout(longPressTimer.value)
+		recorderManager.stop()
+		innerAudioContext.stop()
+	})
+</script>
+
+<style>
+	.container {
+		padding: 20px;
+		display: flex;
+		flex-direction: column;
+		align-items: center;
+	}
+	
+	.status {
+		margin: 20px 0;
+		color: #666;
+		font-size: 16px;
+		min-height: 24px;
+	}
+	
+	.duration {
+		margin-bottom: 20px;
+		color: #333;
+		font-weight: bold;
+	}
+	
+	.record-btn {
+		background-color: #4CAF50;
+		color: white;
+		margin: 10px 0;
+		width: 80%;
+		padding: 15px 0;
+		border: none;
+		border-radius: 5px;
+		position: relative;
+	}
+	
+	.record-btn.recording {
+		background-color: #F44336;
+	}
+	
+	.play-btn {
+		background-color: #2196F3;
+		color: white;
+		margin: 10px 0;
+		width: 80%;
+		padding: 15px 0;
+		border: none;
+		border-radius: 5px;
+	}
+	
+	.disabled {
+		opacity: 0.7;
+		position: relative;
+	}
+	
+	.disabled-mask {
+		position: absolute;
+		top: 0;
+		left: 0;
+		right: 0;
+		bottom: 0;
+		background: rgba(0, 0, 0, 0.5);
+		color: white;
+		display: flex;
+		align-items: center;
+		justify-content: center;
+		font-size: 14px;
+	}
+	
+	.tips {
+		margin-top: 20px;
+		color: #999;
+		font-size: 12px;
+		text-align: center;
+	}
+</style>

+ 289 - 0
pages/newEnglish/components/readContent3.vue

@@ -0,0 +1,289 @@
+<template>
+	<view>
+		<selectTypesVue activeSelect="3"></selectTypesVue>
+		<view class="words-xuan-box">
+			<!-- 单词区 -->
+			<view class="show-words-box"> {{data.name}} </view>
+			<!--  音标区  -->
+			<view class="yb-play-box">
+				<text>{{data.yinbiao}}</text>
+				<!-- active -->
+
+				<icon class="yb-play-btn"></icon>
+				<icon class="yb-playing-btn" v-if="false"></icon>
+			</view>
+
+			<view style="text-align: center;">
+				<text v-if="data.jianyi&&data.jianyi.length>0" v-for="(item,index) in data.jianyi" :key="index">
+					{{item}}
+				</text>
+			</view>
+
+			<view>
+				<view class="audio-play-btn"></view>
+				<!-- 播放中 -->
+				<view class="audio-playing-btn" v-if="false"></view>
+			</view>
+			<view class="container">
+				<view class="status">{{ recordingStatus }}</view>
+				<view class="duration" v-if="isRecording">录音时长: {{ duration.toFixed(1) }}秒</view>
+				<button class="record-btn" :class="{ recording: isRecording }" @touchstart="startRecord"
+					@touchend="endRecord" @mousedown="startRecord" @mouseup="endRecord" @mouseleave="handleMouseLeave">
+					{{ isRecording ? '松开结束' : '按住录音' }}
+				</button>
+				<button class="play-btn" :disabled="!voicePath || isPlaying" @click="playVoice">
+					{{ isPlaying ? '播放中...' : '播放录音' }}
+				</button>
+				<view class="tips">提示:按住按钮录音,松开结束(需3秒以上)</view>
+			</view>
+		</view>
+	</view>
+</template>
+
+<script setup>
+	import selectWordsVue from './selectWords.vue';
+	import selectTypesVue from './selectTypes.vue';
+	import {
+		onLoad
+	} from "@dcloudio/uni-app"
+	import {
+		reactive,
+		ref,
+		onMounted,
+		onUnmounted
+	} from 'vue';
+	const props = defineProps({
+		activeWord: {
+			type: Object,
+		},
+		pageData: {
+			type: Object,
+		},
+		activeWords: {
+			type: Array
+		},
+	})
+
+
+
+	let tabFlag = ref(1)
+	const audioInfo = ref(null)
+
+	const data = reactive({
+		name: '',
+		yinbiao: '',
+		jianyi: []
+	})
+	// 状态定义
+	const isRecording = ref(false)
+	const isPlaying = ref(false)
+	const voicePath = ref('')
+	const duration = ref(0)
+	const timer = ref(null)
+	const recordingStatus = ref('准备就绪')
+	const startTime = ref(0)
+	
+	// 获取录音和音频播放管理器
+	const recorderManager = uni.getRecorderManager()
+	const innerAudioContext = uni.createInnerAudioContext()
+	
+	// 初始化录音器
+	const initRecorder = () => {
+	  // 录音开始回调
+	  recorderManager.onStart(() => {
+	    console.log('recorder start')
+	    isRecording.value = true
+	    recordingStatus.value = '录音中...'
+	    startTime.value = Date.now()
+	    startTimer()
+	  })
+	  
+	  // 录音停止回调
+	  recorderManager.onStop((res) => {
+	    console.log('recorder stop', res)
+	    const recordTime = (Date.now() - startTime.value) / 1000
+	    
+	    stopTimer()
+	    isRecording.value = false
+	    
+	    if (recordTime < 3) {
+	      recordingStatus.value = '录音时间太短(需3秒以上)'
+	      uni.showToast({
+	        title: '录音时间太短,需3秒以上',
+	        icon: 'none'
+	      })
+	      return
+	    }
+	    
+	    if (res.tempFilePath) {
+	      voicePath.value = res.tempFilePath
+	      recordingStatus.value = `录音完成,时长: ${recordTime.toFixed(1)}秒`
+	      uni.showToast({
+	        title: '录音成功',
+	        icon: 'success'
+	      })
+	    } else {
+	      recordingStatus.value = '录音失败'
+	      uni.showToast({
+	        title: '录音失败',
+	        icon: 'none'
+	      })
+	    }
+	  })
+	  
+	  // 录音错误回调
+	  recorderManager.onError((res) => {
+	    console.error('recorder error', res)
+	    stopTimer()
+	    isRecording.value = false
+	    recordingStatus.value = `录音错误: ${res.errMsg}`
+	    uni.showToast({
+	      title: `录音出错: ${res.errMsg}`,
+	      icon: 'none'
+	    })
+	  })
+	  
+	  // 音频播放相关回调
+	  innerAudioContext.onPlay(() => {
+	    isPlaying.value = true
+	    recordingStatus.value = '播放中...'
+	  })
+	  
+	  innerAudioContext.onEnded(() => {
+	    isPlaying.value = false
+	    recordingStatus.value = '播放完成'
+	  })
+	  
+	  innerAudioContext.onError((res) => {
+	    isPlaying.value = false
+	    console.error('play error', res)
+	    uni.showToast({
+	      title: '播放失败',
+	      icon: 'none'
+	    })
+	  })
+	}
+	
+	// 检查权限
+	const checkPermission = () => {
+	  uni.authorize({
+	    scope: 'scope.record',
+	    success: () => {
+	      console.log('已授权录音权限')
+	    },
+	    fail: (err) => {
+	      console.log('未授权录音权限', err)
+	      uni.showModal({
+	        title: '提示',
+	        content: '需要录音权限才能使用此功能',
+	        confirmText: '去设置',
+	        success: (res) => {
+	          if (res.confirm) {
+	            uni.openSetting()
+	          }
+	        }
+	      })
+	    }
+	  })
+	}
+	
+	// 开始录音
+	const startRecord = (e) => {
+	  // 阻止默认行为,防止触摸事件触发其他行为
+	  e.preventDefault()
+	  
+	  if (isRecording.value) return
+	  
+	  console.log('开始录音')
+	  recordingStatus.value = '准备录音...'
+	  
+	  // 适配不同平台的录音参数
+	  const options = {
+	    duration: 60000, // 最长60秒
+	    sampleRate: 44100,
+	    numberOfChannels: 1,
+	    encodeBitRate: 192000,
+	    format: 'mp3',
+	    frameSize: 50 // iOS特定配置
+	  }
+	  
+	  // Android可能需要不同的配置
+	  if (uni.getSystemInfoSync().platform === 'android') {
+	    options.format = 'amr' // Android上amr格式兼容性更好
+	  }
+	  
+	  recorderManager.start(options)
+	}
+	
+	// 结束录音
+	const endRecord = (e) => {
+	  // 阻止默认行为
+	  e.preventDefault()
+	  
+	  if (!isRecording.value) return
+	  
+	  console.log('停止录音')
+	  recorderManager.stop()
+	}
+	
+	// 处理鼠标移出按钮区域的情况
+	const handleMouseLeave = (e) => {
+	  if (isRecording.value) {
+	    endRecord(e)
+	  }
+	}
+	
+	// 计时器相关
+	const startTimer = () => {
+	  duration.value = 0
+	  timer.value = setInterval(() => {
+	    duration.value += 0.1
+	  }, 100)
+	}
+	
+	const stopTimer = () => {
+	  if (timer.value) {
+	    clearInterval(timer.value)
+	    timer.value = null
+	  }
+	}
+	
+	// 播放录音
+	const playVoice = () => {
+	  if (!voicePath.value) {
+	    uni.showToast({
+	      title: '没有可播放的录音',
+	      icon: 'none'
+	    })
+	    return
+	  }
+	  
+	  console.log('播放录音:', voicePath.value)
+	  innerAudioContext.src = voicePath.value
+	  innerAudioContext.play()
+	}
+	
+	// 生命周期钩子
+	onMounted(() => {
+	  initRecorder()
+	  checkPermission()
+	  initItem()
+	})
+	
+	onUnmounted(() => {
+	  // 组件卸载时清理资源
+	  stopTimer()
+	  recorderManager.stop()
+	  innerAudioContext.stop()
+	})
+
+	function initItem() {
+		console.log('data', data);
+		data.name = props.activeWord.name;
+		data.yinbiao = props.activeWord.yinbiao;
+		data.jianyi = props.activeWord.jianyi;
+	}
+</script>
+
+<style>
+</style>

+ 2 - 1
pages/newEnglish/index.vue

@@ -262,7 +262,8 @@
 		url,
 		code
 	}) {
-		// console.log('播放', url)
+	 console.log('播放', url)
+	 console.log('播放', code)
 		const cachedPath = await cacheAudio(url);
 		if (cachedPath.includes('.mp3')) {
 			// console.log('地址:', cachedPath)

+ 7 - 2
pages/study/index.vue

@@ -517,8 +517,13 @@
 			})
 		} else {
 			uni.redirectTo({
-				url: '/pages/wordList/wordList?jieId=' + data.jieId
-			})
+				url: '/pages/wordList/wordList?jieId=666' 
+			})	
+				
+				
+			// 	uni.redirectTo({
+			// 	url: '/pages/wordList/wordList?jieId=' + data.jieId
+			// })
 		}
 	}