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