修改播放声音通用组件

This commit is contained in:
田岩
2025-08-27 21:04:34 +08:00
parent 42b22ebc95
commit b68783956e
13 changed files with 221 additions and 149 deletions
+3 -3
View File
@@ -24,12 +24,12 @@ VITE_APP_BASE_API_Url = 'https://aitstest.jlbank.com.cn:7001'
# 线上 # 线上
# VITE_APP_BASE_H5_API_Url = 'https://aitstest.jlbank.com.cn:7001' # VITE_APP_BASE_H5_API_Url = 'https://aitstest.jlbank.com.cn:7001'
VITE_APP_BASE_H5_API_Url = 'https://aitstest.jlbank.com.cn:7001' VITE_APP_BASE_H5_API_Url = 'http://25.18.122.66:9786'
# VITE_APP_BASE_H5_API_Url_TRAAPP = 'http://25.64.16.130:9601' # VITE_APP_BASE_H5_API_Url_TRAAPP = 'http://25.64.16.130:9601'
VITE_APP_BASE_H5_API_Url_TRASTUDY = 'http://25.64.16.130:9602' #VITE_APP_BASE_H5_API_Url_TRASTUDY = 'http://25.64.16.130:9602'
VITE_APP_BASE_H5_API_Url_TRAASK = 'http://25.64.16.144:9605' #VITE_APP_BASE_H5_API_Url_TRAASK = 'http://25.64.16.144:9605'
# 王洋洋 # 王洋洋
+12
View File
@@ -0,0 +1,12 @@
import request from '@/api/request'
const base_url = '/trastudy'
export const queryTraStdyInfoPreviewPaging = (data) => {
return request({
url: base_url + '/traStdyInfoPreview/queryTraStdyInfoPreviewPaging',
method: 'post',
toastErrors: true,
data
});
};
+21 -4
View File
@@ -102,6 +102,7 @@
type: String type: String
} }
}); });
const audioStore = useAudioStore(); const audioStore = useAudioStore();
const { dataInfo } = toRefs(props); const { dataInfo } = toRefs(props);
const status = computed(() => props.status); const status = computed(() => props.status);
@@ -146,11 +147,15 @@
}; };
const playVoice = () => { const playVoice = () => {
console.log('播放音频', props.dataInfo.voicePath); // isPlaying.value = true;
isPlaying.value = true; console.log('点击播放');
audioStore.playAudio(props.dataInfo.voicePath); audioStore.playAudio();
}; };
onMounted(() => { onMounted(() => {
// 2. 监听 Store 中 isPlaying 的变化,实时同步
const unsubscribe = audioStore.$subscribe((mutation, state) => {
isPlaying.value = state.isPlaying;
});
// 注册播放完成回调 // 注册播放完成回调
audioStore.onAudioEnded(() => { audioStore.onAudioEnded(() => {
console.log('播放完成(通过回调)'); console.log('播放完成(通过回调)');
@@ -158,17 +163,29 @@
isPlaying.value = false; isPlaying.value = false;
}, 60); }, 60);
}); });
// 注册播放错误回调 // 注册播放错误回调
audioStore.onAudioError((error) => { audioStore.onAudioError((error) => {
console.error('播放错误(通过回调):', error); console.error('播放错误(通过回调):', error);
}); });
// 声音加载完毕
audioStore.onAudioLoaded((e) => {
voiceTime.value = (Math.ceil(e.duration) || 1) + 's';
});
watch(
() => props.dataInfo.voicePath,
(newVal) => {
audioStore.setAudioSrc(newVal);
},
{ deep: true, immediate: true }
);
}); });
onUnload(() => { onUnload(() => {
// 1. 停止当前播放(优先处理,避免音频继续播放) // 1. 停止当前播放(优先处理,避免音频继续播放)
audioStore.stopAudio(); audioStore.stopAudio();
// 2. 移除当前组件注册的回调(避免内存泄漏) // 2. 移除当前组件注册的回调(避免内存泄漏)
audioStore.removeCallbacks(); audioStore.removeCallbacks();
unsubscribe();
}); });
</script> </script>
+3 -3
View File
@@ -25,7 +25,7 @@
{{ subject_data.qnsContent }} {{ subject_data.qnsContent }}
</view> </view>
<view :style="props.mode==='mistake'?animationStyle:{}" class="collapse-wrapper" ref="wrapperRef"> <view :style="props.mode === 'mistake' ? animationStyle : {}" class="collapse-wrapper" ref="wrapperRef">
<view class="collapse-content" ref="contentRef"> <view class="collapse-content" ref="contentRef">
<view class="option_div"> <view class="option_div">
<template v-if="qnsTyp === 'ES'"> <template v-if="qnsTyp === 'ES'">
@@ -96,7 +96,7 @@
const emit = defineEmits(['subject_click', 'update:modelValue']); const emit = defineEmits(['subject_click', 'update:modelValue']);
const props = defineProps({ const props = defineProps({
modelValue: { modelValue: {
type: Array, type: [Array, Object],
default: () => [] default: () => []
}, },
item: { item: {
@@ -147,7 +147,7 @@
let answerText = props.item?.my_answer || props.item.anserResult || []; let answerText = props.item?.my_answer || props.item.anserResult || [];
// item_answer 是答题结果,可以是对象 数组 字符串类型 // item_answer 是答题结果,可以是对象 数组 字符串类型
const item_answer = ref(typeof answerText === 'string' ? answerText.split(',') : answerText); const item_answer = ref(typeof answerText === 'string' ? answerText.split(',') : answerText);
const feedback_click = () => { const feedback_click = () => {
emit('subject_click', 'feedback', props.item); emit('subject_click', 'feedback', props.item);
}; };
+49 -33
View File
@@ -48,10 +48,7 @@
:clearResult="true" :clearResult="true"
v-model="item.my_answer" v-model="item.my_answer"
></Subject> ></Subject>
<!-- <CharactersSubject :item="item" v-if="item.qnsTyp === 'ES'" :mode="mode" {{ item.my_answer }}
:activeVoiceId="activeVoiceId" :voicePathValue="voicePathValue"
@subject_click="subject_click">
</CharactersSubject> -->
</scroll-view> </scroll-view>
</view> </view>
</swiper-item> </swiper-item>
@@ -89,13 +86,12 @@
<view class="touch-btn-div" :class="{ show: showTouchBtn }"> <view class="touch-btn-div" :class="{ show: showTouchBtn }">
<TouchBtn <TouchBtn
class="talk-btns" class="talk-btns"
ref="touchBtnRef"
@submit="touchBtnSubmit" @submit="touchBtnSubmit"
loadingText="问题回答中,请在问题回答结束后重试!" loadingText="问题回答中,请在问题回答结束后重试!"
:isLoading="!answerIsOver" :isLoading="!answerIsOver"
:isDisabled="touchIsDisabled" :isDisabled="touchIsDisabled"
/> />
</view> </view>
</view> </view>
@@ -114,7 +110,7 @@
:class="{ :class="{
current: index === questionNumber, current: index === questionNumber,
mark: markList.includes(item.qnsId), mark: markList.includes(item.qnsId),
completed: completedList.includes(item.qnsId) completed: completedListStatus[index]
}" }"
@click="clikc_sheet_item(index)" @click="clikc_sheet_item(index)"
> >
@@ -161,10 +157,12 @@
const feedbackRef = ref(null); const feedbackRef = ref(null);
const dialogRef = ref(null); const dialogRef = ref(null);
const popupRef = ref(null); const popupRef = ref(null);
const touchBtnRef = ref(null);
let examinationStartTime = 0; // 考试开始时间 let examinationStartTime = 0; // 考试开始时间
const mode = ref('examination'); // 考试 examination 练习practice const mode = ref('examination'); // 考试 examination 练习practice
const paperData = reactive({ const paperData = reactive({
crsId: '', // 课程ID,通过课程id是否为空字符串判断这个试卷是课程考试还是考试中心考试
execId: '', // 执行ID execId: '', // 执行ID
examId: '', // 考试ID examId: '', // 考试ID
papersId: '', // 试卷ID papersId: '', // 试卷ID
@@ -175,7 +173,7 @@
const popup_input_bottom = ref('0px'); const popup_input_bottom = ref('0px');
const questionNumber = ref(0); // 题号 const questionNumber = ref(0); // 题号
const systemInfo = uni.getSystemInfoSync(); const systemInfo = uni.getSystemInfoSync();
const topic = computed({ const topic = computed({
get: () => topicList[questionNumber.value], get: () => topicList[questionNumber.value],
set: (val) => (topicList[questionNumber.value] = val) set: (val) => (topicList[questionNumber.value] = val)
@@ -183,9 +181,21 @@
const showTouchBtn = computed(() => { const showTouchBtn = computed(() => {
return topicList[questionNumber.value]['qnsTyp'] === 'ES'; return topicList[questionNumber.value]['qnsTyp'] === 'ES';
}); });
const completedList = computed(() => {
return []; // 答题卡判断每道题的状态
const completedListStatus = computed(() => {
return topicList.map((res) => {
// 问答题
if (res.qnsTyp === 'ES') {
return !!res.my_answer.anserResult;
} else if (typeof res.my_answer === 'string') {
return res.my_answer !== '';
} else if (Array.isArray(res.my_answer)) {
return res.my_answer.length !== 0;
}
});
}); });
// 下面语音组件的禁用状态判断 // 下面语音组件的禁用状态判断
const touchIsDisabled = computed(() => { const touchIsDisabled = computed(() => {
return topic.value?.es_status !== '' && topic.value?.es_status !== undefined; return topic.value?.es_status !== '' && topic.value?.es_status !== undefined;
@@ -244,32 +254,36 @@
// 录音按钮提交 // 录音按钮提交
const touchBtnSubmit = (type, submitObj) => { const touchBtnSubmit = (type, submitObj) => {
const old_text = touchBtnRef.value?.clearinputText(); // 清除发送框数据
if (type === 'voice') { if (type === 'voice') {
uploadRecordNow(submitObj); topic.value.es_status = '00'; // 00转圈
const voicePath = submitObj;
commonUploadVoiceFile(voicePath, '/traask/traAskchat/voiceTrans', {})
.then((res) => {
let _res = JSON.parse(res.data);
if (_res.rtnCode === '0000') {
topic.value.es_status = '02';
topic.value.my_answer = {
anserResult: _res.body.transContent,
ossKey: _res.body.fileId,
ossAddr: _res.body.ossFileAddr,
voicePath: voicePath
};
}
})
.catch((err) => {
topic.value.es_status = ''; // 取消转圈
// 失败了再把发送框数据还原回去
touchBtnRef.value?.clearinputText(old_text); // 清除发送框数据
common.msg('系统异常,请联系管理员');
});
} else if (type === 'text') { } else if (type === 'text') {
topic.value.es_status = '01';
topic.value.anserResult = submitObj; // 正确答案文字内容
// submitProblemEssayQuestion({ anserResult: submitObj });
} }
}; };
// 发送语音
const uploadRecordNow = (voicePath) => {
commonUploadVoiceFile(voicePath, '/traask/traAskchat/voiceTrans', {})
.then((res) => {
let _res = JSON.parse(res.data);
voicePathValue.value = voicePath;
console.log('_res', _res, voicePath);
if (_res.rtnCode === '0000') {
}
})
.catch((err) => {
uni.showToast({
title: '系统异常,请联系管理员',
icon: 'none',
duration: 1000
});
});
};
// 发送文本
const submitAnswerNow = (val, cb = null) => {};
// 初始化时检查 // 初始化时检查
onLoad(() => { onLoad(() => {
const examination = getPageCache('examination'); const examination = getPageCache('examination');
@@ -279,7 +293,8 @@
} }
// 记录起始时间 // 记录起始时间
examinationStartTime = new Date().getTime(); examinationStartTime = new Date().getTime();
paperData.crsId = examination.crsId;
paperData.execId = examination.execId; paperData.execId = examination.execId;
paperData.examId = examination.examId; paperData.examId = examination.examId;
paperData.papersId = examination.papersId; paperData.papersId = examination.papersId;
@@ -433,8 +448,9 @@
if (res.body.flagQuery === 'Y') { if (res.body.flagQuery === 'Y') {
// 需要查分 // 需要查分
const examLenTm = 678; const examLenTm = 678;
common.redirectTo( common.redirectTo(
`/pages/examination/result?execId=${res.body.execId}&examLenTm=${examLenTm}&papersName=${paperData.papersName}` `/pages/examination/result?execId=${res.body.execId}&examLenTm=${examLenTm}&papersName=${paperData.papersName}&papersId=${paperData.papersId}&mode=${mode.value}&crsId=${paperData.crsId}`
); );
} else { } else {
// todo 此处应该有个弹窗交代下结果 // todo 此处应该有个弹窗交代下结果
+73 -17
View File
@@ -81,7 +81,7 @@
时长{{ result.examLenTm }} 时长{{ result.examLenTm }}
</view> </view>
<view class="fl1"></view> <view class="fl1"></view>
<view class="examination"> <view class="examination" @click="goExamRanking">
<view>考试排行榜</view> <view>考试排行榜</view>
<view class="back-icon"></view> <view class="back-icon"></view>
</view> </view>
@@ -125,7 +125,7 @@
</template> </template>
<script setup> <script setup>
import { onLoad } from '@dcloudio/uni-app'; import { onLoad, onUnload } from '@dcloudio/uni-app';
import { ref, reactive, computed, onMounted, nextTick, getCurrentInstance } from 'vue'; import { ref, reactive, computed, onMounted, nextTick, getCurrentInstance } from 'vue';
import { queryPaperExamScore } from '@/api/examination.js'; import { queryPaperExamScore } from '@/api/examination.js';
import Subject from '@/components/examination/subject.vue'; import Subject from '@/components/examination/subject.vue';
@@ -133,12 +133,15 @@
const pass_status = ref(0); const pass_status = ref(0);
const sheet_swiper_index = ref(0); const sheet_swiper_index = ref(0);
const result = reactive({ const result = reactive({
crsId: '',
execId: '', execId: '',
papersId: '',
mode: '',
papersName: '', papersName: '',
examLenTm: '', examLenTm: '',
examGrade: '' examGrade: ''
}); });
const sheet_swiper_change = (event) => { const sheet_swiper_change = (event) => {
sheet_swiper_index.value = event.detail.current; sheet_swiper_index.value = event.detail.current;
}; };
@@ -167,6 +170,16 @@
const scroll = (event) => { const scroll = (event) => {
}; };
// 跳转到去考试页面
const goExamRanking = () => {
// 首先判断是课程跳入还是考试中心跳入
if(result.crsId !== '') {
common.navigateTo('/pages/examRanking/index?crsId=' + result.crsId)
} else {
common.navigateTo('/pages/examRanking/index?papersId=' + result.papersId)
}
}
const getStatusClass = (index) => { const getStatusClass = (index) => {
const remainder = index % 3; const remainder = index % 3;
@@ -177,30 +190,73 @@
const animationfinish = (event) => { const animationfinish = (event) => {
console.log('event', event); console.log('event', event);
}; };
// 定义请求计数器和定时器引用
const requestCount = ref(0);
const timerId = ref(null);
const get_result = () => { const get_result = () => {
setTimeout(() => { // 重置计数器(首次调用时)
queryPaperExamScore({ if (requestCount.value === 0) {
execId: result.execId requestCount.value = 0;
}).then(({ body }) => { }
console.log('分数返回', body);
if (body.isWait === 'Y') { // 检查是否已达到最大请求次数
get_result(); if (requestCount.value >= 15) {
} else if (body.isWait === 'N') { console.log('已达到最大请求次数(15次),停止请求');
pass_status.value = body.examResult === 'P' ? 1 : -1; // p通过 return;
result.examGrade = body.examGrade; }
topicList.push(...body.qnsInfoVo);
} timerId.value = setTimeout(() => {
}); // 每次请求前计数器+1
}, 1000); requestCount.value++;
queryPaperExamScore({
execId: result.execId
}).then(({ body }) => {
console.log(`${requestCount.value}次请求返回`, body);
if (body.isWait === 'Y') {
// 未完成且未达上限,继续请求
if (requestCount.value < 15) {
get_result();
} else {
console.log('已达到最大请求次数,停止等待');
}
} else if (body.isWait === 'N') {
// 完成请求,处理结果
pass_status.value = body.examResult === 'P' ? 1 : -1;
result.examGrade = body.examGrade;
topicList.push(...body.qnsInfoVo);
}
}).catch(err => {
console.error('请求失败', err);
// 请求失败也计入次数,避免无限重试
if (requestCount.value < 15) {
get_result();
}
});
}, 2000);
}; };
// 初始化时检查 // 初始化时检查
onLoad((e) => { onLoad((e) => {
result.crsId = e.crsId;
result.execId = e.execId; result.execId = e.execId;
result.papersName = e.papersName; result.papersName = e.papersName;
result.examLenTm = e.examLenTm; result.examLenTm = e.examLenTm;
result.mode = e.mode;
result.papersId = e.papersId;
get_result(); get_result();
}); });
// 页面卸载时清除定时器,终止请求
onUnload(() => {
if (timerId.value) {
clearTimeout(timerId.value);
timerId.value = null;
}
});
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">
+1
View File
@@ -113,6 +113,7 @@
get: () => topicList[questionNumber.value], get: () => topicList[questionNumber.value],
set: (val) => (topicList[questionNumber.value] = val) set: (val) => (topicList[questionNumber.value] = val)
}); });
const showTouchBtn = computed(() => { const showTouchBtn = computed(() => {
return topic.value?.qnsTyp === 'ES'; return topic.value?.qnsTyp === 'ES';
}); });
@@ -3,108 +3,79 @@
<scroll-view scroll-y="true" class="scroll-Y" @scrolltolower="scrolltolower" :show-scrollbar="false"> <scroll-view scroll-y="true" class="scroll-Y" @scrolltolower="scrolltolower" :show-scrollbar="false">
<view class="item" v-for="item in data_list"> <view class="item" v-for="item in data_list">
<view class="img_div"> <view class="img_div">
<image class="img" src="@/static/images/test/4.png" mode="scaleToFill"></image> <image-preview class="img" :imgId="item.imgId" mode="scaleToFill"></image-preview>
</view> </view>
<view class="right_div"> <view class="right_div">
<view class="title ellipsis-text"> <view class="title ellipsis-text">{{ item.crsName }}</view>
对公小程序开户操作流对公小程序开户操作流程
</view>
<view class="tag_div"> <view class="tag_div">
<view class="tag"> <view class="tag" v-for="tag in item.tagCataList">{{ tag.tagName }}</view>
公金业务
</view>
<view class="tag">
中级
</view>
<view class="tag">
中级
</view>
<view class="tag">
中级
</view>
<view class="tag">
中级
</view>
<view class="tag">
中级
</view>
</view> </view>
<view class="time_and_num"></view> <view class="time_and_num"></view>
</view> </view>
</view> </view>
<list-no-data v-if="total == 0 && status == 'nomore'"></list-no-data>
<uv-load-more v-if="total != 0" :status="status" loadmore-text="轻轻上拉加载" :height="30"></uv-load-more> <uv-load-more v-if="total != 0" :status="status" loadmore-text="轻轻上拉加载" :height="30"></uv-load-more>
</scroll-view> </scroll-view>
</view> </view>
</template> </template>
<script setup> <script setup>
const status = ref('loading') // loadmore - loading - nomore - const status = ref('loading'); // loadmore - loading - nomore -
const limit = 15 const limit = 15;
const total = ref(-1) const total = ref(-1);
const page = ref(0) const page = ref(0);
const data_list = reactive([]) const data_list = reactive([]);
import { import { ref, reactive, onMounted, nextTick } from 'vue';
ref, import { queryTraStdyInfoPreviewPaging } from '@/api/preview.js';
reactive,
onMounted,
nextTick
} from 'vue'
import {
queryTraCrsBbsInfoByCrsId
} from '@/api/courseDetail.js';
const getData = (from = '') => { const getData = (from = '') => {
if (from == 'first') { if (from == 'first') {
if (total.value !== -1) { if (total.value !== -1) {
return return;
} }
status.value = 'loading' status.value = 'loading';
total.value = -1 total.value = -1;
page.value = 1 page.value = 1;
data_list.length = 0 data_list.length = 0;
} else { } else {
if (status.value !== 'loadmore' && status.value !== '') return if (status.value !== 'loadmore' && status.value !== '') return;
status.value = 'loading' status.value = 'loading';
page.value++ page.value++;
} }
console.log(status.value, '阿斯顿撒'); queryTraStdyInfoPreviewPaging({
page: page.value,
setTimeout(() => { limit: limit
queryTraCrsBbsInfoByCrsId({ })
crsId: 'CRS0250181220722025070408313900000018729', .then((res) => {
page: page.value, total.value = res.total;
limit: limit data_list.push(...res.body);
}).then(res => {
total.value = res.total
data_list.push(...res.body)
}).finally(() => {
if (data_list.length >= total.value) {
status.value = 'nomore'
} else {
status.value = 'loadmore'
}
}) })
}, 200) .finally(() => {
} if (data_list.length >= total.value) {
status.value = 'nomore';
} else {
status.value = 'loadmore';
}
});
};
const scrolltolower = (item) => { const scrolltolower = (item) => {
getData() getData();
}; };
defineExpose({ defineExpose({
getData getData
}) });
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">
.scroll_div { .scroll_div {
background-color: #F1F5FA; background-color: #f1f5fa;
padding: 22rpx; padding: 22rpx;
} }
.scroll-Y { .scroll-Y {
height: calc(100vh - var(--status-bar-height) - 54rpx - 88rpx - 20rpx - 44rpx); height: calc(100vh - var(--status-bar-height) - 54rpx - 88rpx - 20rpx - 44rpx);
background-color: #fff; background-color: #fff;
border-radius: 16rpx; border-radius: 16rpx;
} }
.scroll-Y .item { .scroll-Y .item {
height: 170rpx; height: 170rpx;
margin: 32rpx 22rpx; margin: 32rpx 22rpx;
@@ -119,7 +90,6 @@
.img { .img {
width: 224rpx; width: 224rpx;
height: 168rpx; height: 168rpx;
} }
.subscript { .subscript {
@@ -135,8 +105,8 @@
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
background-color: #EF5705; background-color: #ef5705;
color: #FFFFFF; color: #ffffff;
} }
} }
@@ -166,16 +136,15 @@
padding: 0 10rpx; padding: 0 10rpx;
margin-right: 14rpx; margin-right: 14rpx;
border-radius: 8rpx; border-radius: 8rpx;
border: 2rpx solid #FFA150; border: 2rpx solid #ffa150;
font-family: PingFangSC; font-family: PingFangSC;
font-weight: 500; font-weight: 500;
font-size: 23rpx; font-size: 23rpx;
color: #FFA150; color: #ffa150;
display: flex; display: flex;
justify-content: center; justify-content: center;
align-items: center; align-items: center;
} }
} }
.time_and_num { .time_and_num {
@@ -192,4 +161,4 @@
} }
} }
} }
</style> </style>
+2 -2
View File
@@ -31,8 +31,8 @@
<script setup> <script setup>
// 我的预览 // 我的预览
import PreviewAiSparring from './components/preview-ai-sparring.vue' import PreviewAiSparring from './components/previewAiSparring.vue'
import PreviewCourse from './components/preview-course.vue' import PreviewCourse from './components/previewCourse.vue'
import { import {
reactive, reactive,
ref, ref,
+4 -4
View File
@@ -4,11 +4,12 @@
scroll-y="true" scroll-y="true"
class="scroll-Y" class="scroll-Y"
:refresher-enabled="false" :refresher-enabled="false"
:show-scrollbar="false"
@scrolltolower="scrolltolower" @scrolltolower="scrolltolower"
> >
<!-- 主体 --> <!-- 主体 -->
<view class="content"> <view class="content">
<itemVue :item="item" v-for="item in data_list"></itemVue> <itemVue :item="item" v-for="item in data_list"></itemVue>
<list-no-data v-if="total == 0 && status == 'nomore'"></list-no-data> <list-no-data v-if="total == 0 && status == 'nomore'"></list-no-data>
<uv-load-more v-if="total != 0" :status="status" loadmore-text="轻轻上拉加载" :height="30"></uv-load-more> <uv-load-more v-if="total != 0" :status="status" loadmore-text="轻轻上拉加载" :height="30"></uv-load-more>
</view> </view>
@@ -20,13 +21,12 @@
import { queryTraExamPapersPage } from '@/api/testingHall.js'; import { queryTraExamPapersPage } from '@/api/testingHall.js';
import { queryTraCrsBbsInfoByCrsId } from '@/api/courseDetail.js'; import { queryTraCrsBbsInfoByCrsId } from '@/api/courseDetail.js';
import itemVue from './content-item.vue'; import itemVue from './content-item.vue';
const status = ref('loadmore'); // loadmore - 加载前,loading - 加载中,nomore - 没有数据 const status = ref('loadmore'); // loadmore - 加载前,loading - 加载中,nomore - 没有数据
const limit = 15; const limit = 15;
const total = ref(-1); const total = ref(-1);
const page = ref(0); const page = ref(0);
const data_list = reactive([]); const data_list = reactive([]);
const triggered = ref(false); const triggered = ref(false);
const _freshing = ref(false); const _freshing = ref(false);
const offset = ref(0); const offset = ref(0);
@@ -38,7 +38,7 @@
default: 0 default: 0
} }
}); });
const onRefresh = () => { const onRefresh = () => {
if (_freshing.value) return; if (_freshing.value) return;
_freshing.value = true; _freshing.value = true;
+1 -1
View File
@@ -159,7 +159,7 @@
examId: detailData.examId examId: detailData.examId
}) })
.then((res) => { .then((res) => {
setPageCache('examination', { ...res.body, examId: detailData.examId }); setPageCache('examination', { ...res.body, examId: detailData.examId});
common.navigateTo('/pages/examination/index'); common.navigateTo('/pages/examination/index');
}) })
.finally(() => { .finally(() => {
+8 -7
View File
@@ -68,8 +68,10 @@ export const useAudioStore = defineStore('audioStore', {
// 音频可以播放时触发(此时通常能获取到时长) // 音频可以播放时触发(此时通常能获取到时长)
this.audioInstance.onCanplay(() => { this.audioInstance.onCanplay(() => {
// 尝试获取时长(部分环境需要延迟一点) // 尝试获取时长(部分环境需要延迟一点)
console.log('尝试获取时长(部分环境需要延迟一点)');
setTimeout(() => { setTimeout(() => {
const duration = this.audioInstance.duration || 0; const duration = this.audioInstance.duration || 0;
console.log('尝试获duration', duration);
if (duration > 0) { if (duration > 0) {
this.duration = duration; this.duration = duration;
this.isLoaded = true; this.isLoaded = true;
@@ -114,12 +116,11 @@ export const useAudioStore = defineStore('audioStore', {
try { try {
// 先停止当前播放并清空旧地址 // 先停止当前播放并清空旧地址
this.audioInstance.stop(); // this.audioInstance.stop();
this.audioInstance.src = ''; // this.audioInstance.src = '';
// 设置新地址并加载(不自动播放) // 设置新地址并加载(不自动播放)
this.audioInstance.src = src; this.audioInstance.src = src;
this.audioInstance.load(); // 手动触发加载 // this.audioInstance.load(); // 手动触发加载
} catch (err) { } catch (err) {
this.isLoading = false; this.isLoading = false;
this.errorMsg = `设置音频失败: ${err.message}`; this.errorMsg = `设置音频失败: ${err.message}`;
@@ -134,11 +135,12 @@ export const useAudioStore = defineStore('audioStore', {
} }
// 已在播放则暂停 // 已在播放则暂停
console.log('已在播放则暂停', this.isPlaying);
if (this.isPlaying) { if (this.isPlaying) {
this.pauseAudio(); this.pauseAudio();
return; return;
} }
console.log('未加载完成则等待加载', this.isLoaded);
// 未加载完成则等待加载 // 未加载完成则等待加载
if (!this.isLoaded) { if (!this.isLoaded) {
this.isLoading = true; this.isLoading = true;
@@ -175,7 +177,7 @@ export const useAudioStore = defineStore('audioStore', {
resetAudioState() { resetAudioState() {
this.isPlaying = false; this.isPlaying = false;
this.isLoading = false; this.isLoading = false;
this.currentSrc = ''; // this.currentSrc = '';
// 清空地址避免残留 // 清空地址避免残留
if (this.audioInstance) { if (this.audioInstance) {
this.audioInstance.src = ''; this.audioInstance.src = '';
@@ -225,7 +227,6 @@ export const useAudioStore = defineStore('audioStore', {
this.callbacks.onLoaded = callback; this.callbacks.onLoaded = callback;
} }
}, },
} }
}); });