This commit is contained in:
杨航
2025-12-16 10:12:59 +08:00
parent 66ed67f7b2
commit f6f3020556
3 changed files with 151 additions and 126 deletions
+2 -2
View File
@@ -4,8 +4,8 @@ ENV = 'development.yh'
# VITE_APP_BASE_H5_API_Url = 'http://25.18.122.65:7001' # VITE_APP_BASE_H5_API_Url = 'http://25.18.122.65:7001'
VITE_APP_BASE_H5_API_Url = 'http://25.18.122.91:9786' # VITE_APP_BASE_H5_API_Url = 'http://25.18.122.91:9786'
# VITE_APP_BASE_H5_API_Url = 'http://25.18.122.78:9786' VITE_APP_BASE_H5_API_Url = 'http://25.18.122.78:9786'
# VITE_APP_BASE_API_Url = 'https://aitstest.jlbank.com.cn:7002' # VITE_APP_BASE_API_Url = 'https://aitstest.jlbank.com.cn:7002'
# VITE_APP_BASE_H5_API_Url_TRAEXAM = 'http://25.64.32.154:9604' # VITE_APP_BASE_H5_API_Url_TRAEXAM = 'http://25.64.32.154:9604'
# VITE_APP_BASE_H5_API_Url_TRAPRACTICE = 'http://25.64.32.156:9603' # VITE_APP_BASE_H5_API_Url_TRAPRACTICE = 'http://25.64.32.156:9603'
+13 -14
View File
@@ -12,8 +12,7 @@
{{'语音对话'}} {{'语音对话'}}
</view> </view>
</view> --> </view> -->
<uni-popup ref="talkModelRef" type="bottom" @click="hideOverlayTalking" @touchend="hideOverlayTalking" <uni-popup ref="talkModelRef" type="bottom" @click="hideOverlayTalking" mask-background-color="rgba(0,0,0,0.9)">
mask-background-color="rgba(0,0,0,0.9)">
<view class="overlay-box"> <view class="overlay-box">
<view class="circle-bg-box"> <view class="circle-bg-box">
<view class="icon-box"> <view class="icon-box">
@@ -130,6 +129,7 @@
const isStartNum = ref(0); const isStartNum = ref(0);
const isStopNum = ref(0); const isStopNum = ref(0);
const isGettingPermission = ref(false) const isGettingPermission = ref(false)
const isHandleClosed = ref(false)
const initRecord = () => { const initRecord = () => {
recordObjCom.value = uni.getRecorderManager(); recordObjCom.value = uni.getRecorderManager();
unref(recordObjCom)?.onStop((res, duration) => { unref(recordObjCom)?.onStop((res, duration) => {
@@ -173,10 +173,10 @@
setTimeout(() => { setTimeout(() => {
startFlag.value = 2; startFlag.value = 2;
}, 1000); }, 1000);
setRecordTime() if ((isStopNum.value === isStartNum.value) || isHandleClosed.value) {
if (isStopNum.value === isStartNum.value) {
stopRecord(); stopRecord();
} else { } else {
setRecordTime()
showTalkingModel.value = true; showTalkingModel.value = true;
} }
}); });
@@ -206,6 +206,7 @@
unref(recordObjCom).start({ unref(recordObjCom).start({
format: formatType.value format: formatType.value
}); });
// showTalkingModel.value = true;
}; };
const stopRecord = () => { const stopRecord = () => {
@@ -216,31 +217,31 @@
isGettingPermission.value = false isGettingPermission.value = false
}, 1000) }, 1000)
console.log(10, '验证停止方法存在') console.log(10, '验证停止方法存在')
closeModel(); closeModel();
unref(recordObjCom).stop(); unref(recordObjCom).stop();
} else { } else {
console.log(11, '验证停止方法不存在') console.log(11, '验证停止方法不存在')
isGettingPermission.value = false isGettingPermission.value = false
setTimeout(() => {
closeModel(); closeModel();
}, 300)
} }
} catch { } catch {
console.log(12, '验证错误') console.log(12, '验证错误')
isGettingPermission.value = false isGettingPermission.value = false
closeModel(); closeModel();
} }
}; };
const closeModel = (cb = () => {}) => { const closeModel = (cb = () => {}) => {
console.log(99, '关闭弹窗') console.log(99, '关闭弹窗')
isStopNum.value = isStartNum.value; isStopNum.value = isStartNum.value;
setTimeout(() => { isHandleClosed.value = true
isTalking.value = false;
}, 800);
setTimeout(() => { setTimeout(() => {
showTalkingModel.value = false; showTalkingModel.value = false;
cb && cb(); cb && cb();
}, 350); }, 300);
setTimeout(() => {
isTalking.value = false;
isHandleClosed.value = false
}, 1000);
}; };
// #endif // #endif
//#ifndef APP-PLUS //#ifndef APP-PLUS
@@ -334,7 +335,6 @@
}); });
return false return false
} else if (_state === 'not determined') { } else if (_state === 'not determined') {
// startRecord()
return true return true
} else { } else {
return true return true
@@ -383,7 +383,6 @@
touchY.value = obj.changedTouches[0].pageY; touchY.value = obj.changedTouches[0].pageY;
baseY.value = obj.currentTarget.offsetTop; baseY.value = obj.currentTarget.offsetTop;
//#ifdef APP-PLUS //#ifdef APP-PLUS
// canStart.value = false
startRecord(); startRecord();
// #endif // #endif
setTimeout(() => { setTimeout(() => {
+136 -110
View File
@@ -11,14 +11,9 @@
</view> </view>
<view class="top-desc">内容由AI生成</view> <view class="top-desc">内容由AI生成</view>
</view> </view>
<scroll-view <scroll-view :class="[' body-content index-dialog-body', detailInfo.traInterTyp === '01' ? 'talking-type1' : '']"
:class="[' body-content index-dialog-body', detailInfo.traInterTyp === '01' ? 'talking-type1' : '']" :scroll-y="true" refresher-default-style="none" :scroll-top="scrollTop" :show-scrollbar="false"
:scroll-y="true" :scroll-with-animation="false">
refresher-default-style="none"
:scroll-top="scrollTop"
:show-scrollbar="false"
:scroll-with-animation="false"
>
<view :class="['body-content-role', showRoleInfo ? '' : 'hide-info']"> <view :class="['body-content-role', showRoleInfo ? '' : 'hide-info']">
<view :class="['role-title']"> <view :class="['role-title']">
<ImagePreview class="role-title-avatar" :src="detailInfo.ossAddr" :isCache="true"></ImagePreview> <ImagePreview class="role-title-avatar" :src="detailInfo.ossAddr" :isCache="true"></ImagePreview>
@@ -28,16 +23,10 @@
<text class="card-title-name">{{ detailInfo.chaName }}</text> <text class="card-title-name">{{ detailInfo.chaName }}</text>
<text class="card-title-age">{{ detailInfo.chaAge }}</text> <text class="card-title-age">{{ detailInfo.chaAge }}</text>
<text class="card-title-img"> <text class="card-title-img">
<image <image class="card-title-icon" v-if="detailInfo.gender === 'm' || detailInfo.gender === '01'"
class="card-title-icon" src="@/static/images/me/man.png"></image>
v-if="detailInfo.gender === 'm' || detailInfo.gender === '01'" <image class="card-title-icon" v-if="detailInfo.gender === 'f' || detailInfo.gender === '02'"
src="@/static/images/me/man.png" src="@/static/images/me/wuman.png"></image>
></image>
<image
class="card-title-icon"
v-if="detailInfo.gender === 'f' || detailInfo.gender === '02'"
src="@/static/images/me/wuman.png"
></image>
</text> </text>
</view> </view>
<view class="role-desc"> <view class="role-desc">
@@ -74,45 +63,24 @@
<view class="tip-text">-请点击下方按钮开始{{ detailInfo.traInterTypDesc }}</view> <view class="tip-text">-请点击下方按钮开始{{ detailInfo.traInterTypDesc }}</view>
</view> </view>
<view class="talking-box" v-else> <view class="talking-box" v-else>
<TalkingItem <TalkingItem v-for="(item, index) in talkingList" :talkingType="item.type" :talkingInfo="item"
v-for="(item, index) in talkingList" :roleInfo="detailInfo" :traId="traId" :execId="execId" :isExam="talkingType === '02'"
:talkingType="item.type" :isLast="index + 1 === talkingList.length" :isAnswering="!answerIsOver"
:talkingInfo="item" :activeVoiceId="activeVoiceTalkingItemId" @handleEvents="talkItemEvents"></TalkingItem>
:roleInfo="detailInfo"
:traId="traId"
:execId="execId"
:isExam="talkingType === '02'"
:isLast="index + 1 === talkingList.length"
:isAnswering="!answerIsOver"
:activeVoiceId="activeVoiceTalkingItemId"
@handleEvents="talkItemEvents"
></TalkingItem>
</view> </view>
</scroll-view> </scroll-view>
<view class="over-btn-box" v-if="detailInfo.traInterTyp === '01'"> <view class="over-btn-box" v-if="detailInfo.traInterTyp === '01'">
<view class="over-btn" @click="overTalking">结束陪练</view> <view class="over-btn" @click="overTalking">结束陪练</view>
</view> </view>
<TouchBtn <TouchBtn class="body-bottom" @uploadVoice="uploadRecordNow" @startRecord="changePlayItemId('')"
class="body-bottom" :isLoading="!answerIsOver" :isDisabled="false" v-if="detailInfo.traInterTyp === '01'" />
@uploadVoice="uploadRecordNow"
@startRecord="changePlayItemId('')"
:isLoading="!answerIsOver"
:isDisabled="false"
v-if="detailInfo.traInterTyp === '01'"
/>
<view class="body-bottom" v-else> <view class="body-bottom" v-else>
<view class="body-bottom-btn" @click="toTalking"> <view class="body-bottom-btn" @click="beforeToTalking">
<view class="center-text"> <view class="center-text">
<image <image class="type-icon" src="@/static/images/sparring/video-icon.png"
class="type-icon" v-if="detailInfo.traInterTyp === '03'"></image>
src="@/static/images/sparring/video-icon.png" <image class="type-icon" src="@/static/images/sparring/phone-icon.png"
v-if="detailInfo.traInterTyp === '03'" v-else-if="detailInfo.traInterTyp === '02'"></image>
></image>
<image
class="type-icon"
src="@/static/images/sparring/phone-icon.png"
v-else-if="detailInfo.traInterTyp === '02'"
></image>
<image v-else class="type-icon" src="@/static/images/sparring/talk-icon.png"></image> <image v-else class="type-icon" src="@/static/images/sparring/talk-icon.png"></image>
{{ detailInfo.traInterTypDesc }} {{ detailInfo.traInterTypDesc }}
</view> </view>
@@ -125,27 +93,62 @@
</template> </template>
<script setup> <script setup>
import { ref, unref, onMounted, computed, nextTick } from 'vue'; import {
import { onShow, onHide, onLoad, onUnload, onLaunch, onBackPress } from '@dcloudio/uni-app'; ref,
unref,
onMounted,
computed,
nextTick
} from 'vue';
import {
onShow,
onHide,
onLoad,
onUnload,
onLaunch,
onBackPress
} from '@dcloudio/uni-app';
import common from '@/common/common'; import common from '@/common/common';
import { getPhoneEnvBool } from '@/common/common'; import {
getPhoneEnvBool
} from '@/common/common';
import TouchBtn from './components/touchBtn.vue'; import TouchBtn from './components/touchBtn.vue';
import ImagePreview from '@/components/image-preview/image-preview.vue'; import ImagePreview from '@/components/image-preview/image-preview.vue';
import { commonUploadVoiceFile } from '@/api/common.js'; import {
import { queryTraPartnerCharacterInfoById, partnerChatReportTrigger } from '@/api/sparring.js'; commonUploadVoiceFile
import { useSocketStore } from '@/store/socket.js'; } from '@/api/common.js';
import { useStorageStore } from '@/store/storage.js'; import {
import { storeToRefs } from 'pinia'; queryTraPartnerCharacterInfoById,
partnerChatReportTrigger,
checkTraPartnerInfoById
} from '@/api/sparring.js';
import {
useSocketStore
} from '@/store/socket.js';
import {
useStorageStore
} from '@/store/storage.js';
import {
storeToRefs
} from 'pinia';
import TalkingItem from './components/talking-item.vue'; import TalkingItem from './components/talking-item.vue';
import badge from '@/components/points-and-badge/badge'; import badge from '@/components/points-and-badge/badge';
import points from '@/components/points-and-badge/points'; import points from '@/components/points-and-badge/points';
import usePointsAndBadge from '@/components/points-and-badge/usePointsAndBadge'; import usePointsAndBadge from '@/components/points-and-badge/usePointsAndBadge';
import { initRecord } from '@/composables/useExamSubject.js'; import {
initRecord
} from '@/composables/useExamSubject.js';
import permissionApi from '@/common/permission' import permissionApi from '@/common/permission'
const { pointAndBadgesRun, badgeRef, pointsRef } = usePointsAndBadge(); const {
pointAndBadgesRun,
badgeRef,
pointsRef
} = usePointsAndBadge();
const socketStore = useSocketStore(); const socketStore = useSocketStore();
const { SocketObj } = storeToRefs(socketStore); const {
SocketObj
} = storeToRefs(socketStore);
const traId = ref(''); const traId = ref('');
const chaId = ref(''); const chaId = ref('');
@@ -195,6 +198,7 @@
}); });
}; };
const uploadRecordNow = (voicePath, voiceTime) => { const uploadRecordNow = (voicePath, voiceTime) => {
console.log(voicePath, voiceTime)
//#ifndef APP-PLUS //#ifndef APP-PLUS
// h5 假数据 // h5 假数据
// #endif // #endif
@@ -244,20 +248,30 @@
}); });
// #endif // #endif
}; };
const beforeToTalking = () => {
checkTraPartnerInfoById({
traId: traId.value
}).then(res => {
if (res.body.inRange) {
toTalking()
} else {
common.show('提示', res.body.message, false)
}
})
}
const toTalking = async () => { const toTalking = async () => {
try { try {
//#ifdef APP-PLUS //#ifdef APP-PLUS
console.log('申请权限'); console.log('申请权限');
try { try {
// await initRecord(); // await initRecord();
await permissionApi.judgeIosPermission('record') await permissionApi.judgeIosPermission('record')
await permissionApi.judgeIosPermission('camera') await permissionApi.judgeIosPermission('camera')
} catch(e) { } catch (e) {
console.error('摄像头或者麦克风权限申请失败:', e); console.error('摄像头或者麦克风权限申请失败:', e);
return; return;
} }
//#endif //#endif
common.setPageCache('tipMsgsceneDesc', { common.setPageCache('tipMsgsceneDesc', {
ossAddr: detailInfo.value.ossAddr, ossAddr: detailInfo.value.ossAddr,
@@ -267,15 +281,15 @@
}); });
common.redirectTo( common.redirectTo(
'/pages/sparring/talk?traId=' + '/pages/sparring/talk?traId=' +
traId.value + traId.value +
'&chaId=' + '&chaId=' +
chaId.value + chaId.value +
'&type=' + '&type=' +
talkingType.value + talkingType.value +
'&traInterTyp=' + '&traInterTyp=' +
detailInfo.value.traInterTyp + detailInfo.value.traInterTyp +
'&isPreview=' + '&isPreview=' +
(isPreview.value ? '1' : '0') (isPreview.value ? '1' : '0')
); );
} catch (err) { } catch (err) {
console.error('申请权限失败'); console.error('申请权限失败');
@@ -287,7 +301,12 @@
activeVoiceTalkingItemId.value = id; activeVoiceTalkingItemId.value = id;
}; };
const talkItemEvents = ({ type, data, id, info = {} }) => { const talkItemEvents = ({
type,
data,
id,
info = {}
}) => {
switch (type) { switch (type) {
case 'changePlay': case 'changePlay':
activeVoiceTalkingItemId.value = id; activeVoiceTalkingItemId.value = id;
@@ -339,13 +358,13 @@
socketStore?.closeSocket(); socketStore?.closeSocket();
common.redirectTo( common.redirectTo(
'/pages/sparring/result?isOver=1&traId=' + '/pages/sparring/result?isOver=1&traId=' +
traId.value + traId.value +
'&execId=' + '&execId=' +
execId.value + execId.value +
'&type=' + '&type=' +
talkingType.value + talkingType.value +
'&isPreview=' + '&isPreview=' +
(isPreview.value ? '1' : '') (isPreview.value ? '1' : '')
); );
}); });
}) })
@@ -354,7 +373,11 @@
}); });
}); });
unref(SocketObj).on('message', (res) => { unref(SocketObj).on('message', (res) => {
const { rtnCode, body, commond } = JSON.parse(res.data); const {
rtnCode,
body,
commond
} = JSON.parse(res.data);
let _id = new Date().getTime() + 'id'; let _id = new Date().getTime() + 'id';
if (rtnCode === '0000') { if (rtnCode === '0000') {
if (commond === 'ASK-OPEN') { if (commond === 'ASK-OPEN') {
@@ -475,13 +498,13 @@
socketStore?.closeSocket(); socketStore?.closeSocket();
common.redirectTo( common.redirectTo(
'/pages/sparring/result?isOver=1&traId=' + '/pages/sparring/result?isOver=1&traId=' +
traId.value + traId.value +
'&execId=' + '&execId=' +
execId.value + execId.value +
'&type=' + '&type=' +
talkingType.value + talkingType.value +
'&isPreview=' + '&isPreview=' +
(isPreview.value ? '1' : '') (isPreview.value ? '1' : '')
); );
return; return;
} }
@@ -521,10 +544,10 @@
}; };
const overNow = (cb = () => {}) => { const overNow = (cb = () => {}) => {
partnerChatReportTrigger({ partnerChatReportTrigger({
execId: execId.value, execId: execId.value,
traId: traId.value, traId: traId.value,
talkingType: isPreview.value ? 'preview' : 'practice' talkingType: isPreview.value ? 'preview' : 'practice'
}) })
.then((res) => { .then((res) => {
watchFlag.value = 1; watchFlag.value = 1;
sendMessage({ sendMessage({
@@ -537,13 +560,13 @@
changePlayItemId(''); changePlayItemId('');
common.redirectTo( common.redirectTo(
'/pages/sparring/result?isOver=1&traId=' + '/pages/sparring/result?isOver=1&traId=' +
traId.value + traId.value +
'&execId=' + '&execId=' +
execId.value + execId.value +
'&type=' + '&type=' +
talkingType.value + talkingType.value +
'&isPreview=' + '&isPreview=' +
(isPreview.value ? '1' : '') (isPreview.value ? '1' : '')
); );
// pointAndBadgesRun(talkingType.value === '01'? '07': '08', '', ()=>{ // pointAndBadgesRun(talkingType.value === '01'? '07': '08', '', ()=>{
// common.redirectTo('/pages/sparring/result?isOver=1&traId=' + traId.value + '&execId=' + execId.value + '&type=' + talkingType.value + '&isPreview=' + (isPreview.value ?'1':'')) // common.redirectTo('/pages/sparring/result?isOver=1&traId=' + traId.value + '&execId=' + execId.value + '&type=' + talkingType.value + '&isPreview=' + (isPreview.value ?'1':''))
@@ -899,15 +922,18 @@
text-align: center; text-align: center;
} }
} }
.talking-desc{
.talking-desc {
// padding-top: 24rpx; // padding-top: 24rpx;
padding: 24rpx 20rpx 0; padding: 24rpx 20rpx 0;
font-size: 24rpx; font-size: 24rpx;
// text-align: center; // text-align: center;
color: #999; color: #999;
} }
.talking-box { .talking-box {
padding-top: 24rpx; padding-top: 24rpx;
.tip-text { .tip-text {
color: #7295cb; color: #7295cb;
text-align: center; text-align: center;
@@ -976,4 +1002,4 @@
} }
} }
} }
</style> </style>