Files
tra-app/src/pages/sparring/result.vue
T
2025-11-25 15:49:51 +08:00

661 lines
16 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<view class="result-cont">
<view class="sparring-result-loading" v-show="showLoading">
<view class="loading-img">
</view>
</view>
<view class="top-box">
<view class="top-title">
<view class="back-icon" @click="goBack()"></view>
{{ '陪练报告' }}
<view class="feedback-icon" @click="feedbackNow"></view>
<view class="top-desc">内容由AI生成</view>
</view>
</view>
<view class="body-content">
<view class="body-top">
<view class="body-top-title">
{{ traInfo.traName}}
</view>
<view class="body-top-time">
陪练时长{{traTm}}
</view>
<view class="body-top-tip">陪练详情</view>
<view class="body-top-collepse-title">
<view :class="['collepse-btn', showAllTalk?'show-all':'']" @click="showAllTalk = !showAllTalk"></view>
<view class="collepse-tab">
<uv-tabs :list="tabList" @click="changeTab" :scrollable="false" active-style="font-weight:bold; color:#000;"
class="font_pf my_tabs" :inactive-style="{ color: '#333333', fontSize: '28rpx', fontWeight: '500' }"
:activeStyle="{ color: '#333333', fontSize: '28rpx', fontWeight: '600' }"></uv-tabs>
</view>
<!-- 头像信息 -->
<view class="user-info" v-if="showTalkList.length>0 && showTalkList[0].type==='question'">
<!-- <view class="avatar-box">
<ImagePreview class="img-box" :src="roleInfo?.ossAddr"></ImagePreview>
</view>
<view class="ai-name">
{{ roleInfo?.chaName }}
</view> -->
</view>
<view class="loading-box" v-if="isLoading"></view>
<TalkingPreviewItem class="talk-item" v-for="item in showTalkList" :talkingType="item.type"
:talkingInfo="item" :roleInfo="roleInfo" :traId="traId" :execId="execId" :isAnswering="false"
:activeVoiceId="activeVoiceTalkingItemId" @handleEvents="talkItemEvents"></TalkingPreviewItem>
</view>
<view :class="['body-top-collepse-cont', showAllTalk?'show-all':'']">
<TalkingPreviewItem class="talk-item" v-for="item in hideTalkList" :talkingType="item.type"
:talkingInfo="item" :roleInfo="roleInfo" :traId="traId" :execId="execId" :isAnswering="false"
:activeVoiceId="activeVoiceTalkingItemId" @handleEvents="talkItemEvents"></TalkingPreviewItem>
</view>
</view>
<view class="body-bottom">
<view class="body-bottom-title">维度评价总览</view>
<view class="body-bottom-item" v-for="item in evalDimens">
<view class="item-title">{{item.gradeDimensName}} {{ item.traGrade }}
<!-- <image class="item-title-icon" src="@/static/images/sparring/info-icon.png"></image> -->
</view>
<view class="item-cont">{{item.settDesc}}</view>
</view>
<view :class="['body-bottom-static', isPass?'pass':'fialed']">
<view class="static-tip">得分</view>
<view class="static-score">{{ totalScore }}</view>
<view class="static-desc" v-if="!!hitBanWords">{{'朋友你挺能说违禁词啊'}}</view>
<view class="static-desc" v-if="!!hitBanWords">以下均为违禁词:<text style="color: red;">{{hitBanWords}}</text></view>
<view class="static-desc" v-else>{{!isPass?'你这个得分不容易的':'恭喜你过关斩将顺利通关'}}</view>
<view class="static-charts">
<ChartThree v-if="evalDimens.length === 3" fromType="tra" :dataList="evalDimens" />
<ChartFour v-if="evalDimens.length === 4" fromType="tra" :dataList="evalDimens" />
<ChartFive v-if="evalDimens.length === 5" fromType="tra" :dataList="evalDimens" />
<ChartSix v-if="evalDimens.length === 6" fromType="tra" :dataList="evalDimens" />
<ChartSeven v-if="evalDimens.length === 7" fromType="tra" :dataList="evalDimens" />
</view>
</view>
</view>
</view>
<Feedback ref="feedbackRef" />
</view>
</template>
<script setup>
import {
ref,
onMounted,
computed
} from 'vue'
import {
onShow,
onLoad,
onUnload,
onBackPress
} from '@dcloudio/uni-app';
import common from '@/common/common'
import Feedback from './components/feedback.vue';
import ChartFour from '@/pages/course/components/chartFour.vue';
import ChartThree from '@/pages/course/components/chartThree.vue';
import ChartFive from '@/pages/course/components/chartFive.vue';
import ChartSix from '@/pages/course/components/chartSix.vue';
import ChartSeven from '@/pages/course/components/chartSeven.vue';
import TalkingPreviewItem from './components/talking-preview-item.vue'
import ImagePreview from '@/components/image-preview/image-preview.vue';
import {
partnerChatReport
} from "@/api/sparring.js"
const traId = ref('')
const execId = ref('')
const talkingType = ref('')
const feedbackRef = ref()
const roleInfo = ref({})
const showAllTalk = ref(false)
const traInfo = ref({})
const traTm = ref('')
const activeVoiceTalkingItemId = ref('')
const tabList = ref([{
name: '全部',
value: ''
},
{
name: '优秀',
value: '01'
},
{
name: '欠佳',
value: '02'
}
])
const showTalkList = computed(() => {
return allTalkList.value.slice(0, 2)
})
const hideTalkList = computed(() => {
return allTalkList.value.slice(2)
})
const allTalkList = computed(() => {
if (!filterType.value) {
return traPartnerExecuteAnswerRecords.value
} else if (filterType.value === '01') {
return traPartnerExecuteAnswerRecords.value.filter((t, index) => {
return t.talkingText.indexOf('#15b859') >= 0 || traPartnerExecuteAnswerRecords.value[index + 1]
?.talkingText.indexOf('#15b859') >= 0
})
} else if (filterType.value === '02') {
return traPartnerExecuteAnswerRecords.value.filter((t, index) => {
return t.talkingText.indexOf('#d70c18') >= 0 || traPartnerExecuteAnswerRecords.value[index + 1]
?.talkingText.indexOf('#d70c18') >= 0
})
}
})
// 关闭播放状态
const changePlayItemId = (id = '') => {
activeVoiceTalkingItemId.value = id
}
const talkItemEvents = ({
type,
data,
id,
info = {}
}) => {
switch (type) {
case 'changePlay':
activeVoiceTalkingItemId.value = id;
break;
case 'scrollToBottom':
break;
default:
break;
}
};
const feedbackNow = () => {
feedbackRef.value.open({
traId: traId.value
});
}
const filterType = ref('')
const changeTab = (info) => {
filterType.value = info.value
}
const evalDimens = ref([])
const hitBanWords = ref('')
const traPartnerExecuteAnswerRecords = ref([])
const totalScore = ref(0)
const showLoading = ref(true)
const isPass = ref(false)
const negativeList = ref([]) // 劣质话术
const positiveList = ref([]) // 劣质话术
const isLoading = ref(false)
const getData = () => {
isLoading.value = true
partnerChatReport({
traId: traId.value,
execId: execId.value,
talkingType: isPreview.value? 'preview' : 'practice'
// traId: 'PARTNERINFO02501812207220251103160409000007402',
// execId: 'db2f275b-c04a-4572-83dd-74a95ff49d67'
}).then(res => {
if (res.body.reportFlag){
traInfo.value = res.body.traPartnerInfo || {}
roleInfo.value = res.body.traPartnerCharacterInfoVo || {}
traTm.value = res.body.traTm || '0'
isPass.value = res.body.traPartnerExecuteHisVo?.traResult === 'P'
totalScore.value = res.body.traPartnerExecuteHisVo?.traGrade || '0'
positiveList.value = res.body.positiveList || []
negativeList.value = res.body.negativeList || []
hitBanWords.value = res.body.traPartnerExecuteHisVo?.hitBanWords || ''
let _evalDimens = res.body.traPartnerSettlement || []
evalDimens.value = _evalDimens.map(t => {
return {
...t,
anlyGrade: t.traGrade,
gradeDimensName: t.gradeDimensName || '维度'
}
})
let _talkingList = res.body.traPartnerExecuteAnswerRecords || []
traPartnerExecuteAnswerRecords.value = _talkingList.map(t => {
let _content = setTextColor(t.content)
if (t.openStyle === '02') {
return {
...t,
type: 'question',
talkingText: _content,
isLoading: false,
execLogId: t.execLogId || '',
intrctWay: '02',
id: t.execLogId,
...t,
}
} else if (t.openStyle === '01') {
return {
...t,
type: 'answer',
talkingText: _content,
isLoading: false,
execLogId: t.execLogId || '',
id: t.execLogId,
}
} else {
return t
}
})
isLoading.value = false
setTimeout(() => {
showLoading.value = false
}, 800)
} else {
setTimeout(getData, 2000)
}
}).catch(()=>{
isLoading.value = false
})
}
const setTextColor = (str) => {
let _str = str
positiveList.value.forEach(t => {
_str = _str.split(t).join(`<span style="color: #15b859;text-decoration:underline;">${t}</span>`)
})
negativeList.value.forEach(t => {
_str = _str.split(t).join(`<span style="color: #d70c18;text-decoration:underline;">${t}</span>`)
})
return _str
}
const isPreview = ref(false)
const isOver = ref(false)
const goBack = () => {
if(isOver.value){
common.navigateBack(3)
}else{
common.navigateBack()
}
}
onLoad((params) => {
traId.value = params.traId;
execId.value = params.execId
talkingType.value = params.type;
showLoading.value = true
isPreview.value = params.isPreview === '1'
isOver.value = params.isOver === '1'
getData()
});
onMounted(() => {})
onBackPress((res) => res.from === 'backbutton');
</script>
<style scoped lang="scss">
.result-cont {
position: absolute;
overflow-x: hidden;
overflow-y: hidden;
left: 0;
top: 0;
height: 100vh;
width: 100%;
box-sizing: border-box;
background-color: #f2f6fd;
z-index: 1;
padding: calc(var(--status-bar-height) + 90rpx) 0 0rpx;
// background-image: url(@/static/images/sparring/bg.png);
// background-size: cover;
}
.sparring-result-loading {
position: fixed;
z-index: 20;
height: 100vh;
width: 100vw;
background-image: url(@/static/images/sparring/bg.png);
.loading-img {
position: absolute;
width: 380rpx;
height: 540rpx;
top: 40%;
transform: translateY(-50%) translateX(-50%);
left: 50%;
padding-top: 540rpx;
line-height: 50rpx;
box-sizing: border-box;
text-align: center;
background-image: url(@/static/images/sparring/waiting.png);
background-repeat: no-repeat;
background-size: 380rpx 590rpx;
&::after {
content: '报告生成中,请耐心等待 ~ ';
display: block;
position: absolute;
left: 0%;
width: 100%;
bottom: -50rpx;
height: 50rpx;
line-height: 50rpx;
text-align: center;
font-size: 28rpx;
}
}
}
.top-box {
height: 90rpx;
width: 100%;
position: fixed;
top: var(--status-bar-height);
left: 0;
z-index: 2;
.top-desc{
position: absolute;
bottom: 0;
font-size: 18rpx;
color: #999;
left: 50%;
transform: translateX(-50%);
}
.top-title {
height: 90rpx;
// background-color: red;
text-align: center;
font-size: 33rpx;
padding: 10rpx 100rpx 0;
line-height: 46rpx;
box-sizing: border-box;
font-weight: 500;
color: #000;
position: relative;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
// margin-bottom: 23rpx;
.arrow-icon {
position: absolute;
left: 36rpx;
top: 20rpx;
color: #fff !important;
}
.feedback-icon {
position: absolute;
width: 40rpx;
height: 40rpx;
cursor: pointer;
right: 50rpx;
top: 33rpx;
transform: translateY(-50%);
background: url(@/static/images/sparring/feedback.png) no-repeat;
background-size: 28rpx 28rpx;
background-position: center;
}
.back-icon {
position: absolute;
width: 40rpx;
height: 40rpx;
cursor: pointer;
left: 50rpx;
top: 33rpx;
transform: translateY(-50%);
}
.back-icon::before,
.back-icon::after {
content: '';
position: absolute;
transition: all 0.3s ease;
}
.back-icon::after {
top: 25%;
left: 25%;
width: 40%;
height: 40%;
border-top: 4rpx solid #000;
border-left: 4rpx solid #000;
transform: rotate(-45deg);
}
}
}
.body-content {
height: 100%;
padding: 10rpx 24rpx 20rpx;
box-sizing: border-box;
overflow-y: auto;
.body-top {
background-color: #fff;
padding: 16rpx 24rpx;
margin-bottom: 16rpx;
.body-top-title {
font-size: 38rpx;
line-height: 60rpx;
}
.body-top-time {
padding: 30rpx 0 28rpx 40rpx;
border-bottom: 2rpx solid #eee;
line-height: 26rpx;
font-size: 25rpx;
color: #666;
background-image: url(@/static/images/sparring/time-icon.png);
background-repeat: no-repeat;
background-position: left center;
background-size: 28rpx 30rpx;
}
.body-top-tip {
font-size: 32rpx;
line-height: 88rpx;
}
.body-top-collepse-title {
padding-top: 10rpx;
position: relative;
min-height: 100rpx;
.user-info {
overflow: hidden;
height: 92rpx;
.avatar-box {
float: left;
width: 76rpx;
height: 76rpx;
border: 3rpx solid #fff;
// background-color: #f1f1f1;
overflow: hidden;
border-radius: 10rpx;
margin-right: 16rpx;
margin-bottom: 16rpx;
.img-box {
width: 76rpx;
height: 76rpx;
overflow: hidden;
}
}
.ai-name {
float: left;
color: #666;
font-size: 25rpx;
line-height: 35rpx;
width: 140rpx;
white-space: pre-wrap;
.ai-name-desc {
color: #999;
margin-left: 16rpx;
display: inline-block;
}
}
}
.loading-box{
min-height: 180rpx;
width: 100%;
background: url(@/static/images/examination/getting_in.gif) no-repeat;
background-position: center;
background-size: auto 160rpx;
margin-top: 100rpx;
}
.collepse-tab {
position: absolute;
width: 300rpx;
right: 120rpx;
top: 0rpx;
z-index: 10;
}
.collepse-btn {
position: absolute;
right: 0;
top: 20rpx;
width: 108rpx;
height: 46rpx;
border: 2rpx solid #d4dce8;
border-radius: 23rpx;
z-index: 10;
&.show-all {
&::after {
transform: translate(-50%, calc(-50% - 3rpx)) rotate(225deg);
}
}
&::after {
content: '';
position: absolute;
transition: all 0.3s ease;
top: 50%;
left: 50%;
width: 14rpx;
height: 14rpx;
border-top: 2rpx solid #06f;
border-left: 2rpx solid #06f;
transform: translate(-50%, -50%) rotate(135deg);
}
}
}
.body-top-collepse-cont {
max-height: 0rpx;
transition: all 0.5s ease;
overflow: hidden;
&.show-all {
max-height: 5000rpx;
transition: all 0.5s ease;
}
}
}
.body-bottom {
padding: 16rpx 24rpx;
background-color: #fff;
&-title {
font-size: 32rpx;
line-height: 64rpx;
font-weight: 600;
}
&-item {
padding: 23rpx 0;
.item-title {
// line-height: 40rpx;
// margin-bottom: 24rpx;
// font-weight: 500;
// .item-title-icon{
// width: 24rpx;
// height: 26rpx;
// position: relative;
// top: 2rpx;
// left: 10rpx;
// }
line-height: 40rpx;
position: relative;
padding: 0rpx 46rpx 0rpx 26rpx;
line-height: 42rpx;
font-size: 29rpx;
margin-bottom: 16rpx;
&::before {
content: '';
display: block;
background-color: #000;
width: 12rpx;
height: 12rpx;
border-radius: 50%;
position: absolute;
left: 0rpx;
top: 14rpx;
}
}
.item-cont {
font-size: 28rpx;
line-height: 50rpx;
}
}
&-static {
border-top: 2px solid #eee;
padding-top: 38rpx;
background-repeat: no-repeat;
background-size: 270rpx 190rpx;
background-position: right 40rpx;
&.fialed {
background-image: url(@/static/images/sparring/def-res.png);
}
&.pass {
background-image: url(@/static/images/sparring/pass-res.png);
}
.static-tip {
line-height: 44rpx;
font-size: 32rpx;
margin-bottom: 24rpx;
font-weight: 600;
}
.static-score {
font-size: 66rpx;
color: #06f;
font-family: Arial, Helvetica, sans-serif;
marign-bottom: 20rpx;
}
.static-desc {
color: #999;
font-size: 25rpx;
margin-bottom: 32rpx;
}
}
}
}
.talk-item {
// height: 200rpx;
overflow: hidden;
}
.my_tabs {
// 解决这个圆角的图片,开穿透
:deep(.uv-tabs__wrapper__nav__line) {
background: linear-gradient(90deg, #06f 0%, rgb(0, 159, 255) 50%, rgb(255, 255, 255) 100%) !important;
}
:deep(.uv-tabs__wrapper__nav__item) {
padding: 0 20rpx !important;
}
}
</style>