feat: 报告页面

This commit is contained in:
杨航
2025-11-06 15:34:28 +08:00
parent a61e01816f
commit 7c17fdfa5c
18 changed files with 1651 additions and 183 deletions
+1 -1
View File
@@ -4,7 +4,7 @@ ENV = 'development'
# VITE_APP_BASE_API_Url = 'https://aits.jlbank.com.cn:7001'
VITE_APP_BASE_API_Url = 'https://aitstest.jlbank.com.cn:7001'
VITE_APP_BASE_API_Url = 'https://aitstest.jlbank.com.cn:7002'
# VITE_APP_BASE_API_Url = 'http://192.168.247.200'
# VITE_APP_BASE_API_Url = 'http://aitscdn.jlbank.com.cn:7001'
# VITE_APP_BASE_API_Url = 'http://192.168.108.129'
+27
View File
@@ -483,6 +483,33 @@
"titleNView": false
}
}
},
{
"path": "pages/sparring/talk",
"style": {
"navigationBarTitleText": "AI陪练通话",
"app-plus": {
"titleNView": false
}
}
},
{
"path": "pages/sparring/result",
"style": {
"navigationBarTitleText": "AI陪练报告",
"app-plus": {
"titleNView": false
}
}
},
{
"path": "pages/static/study",
"style": {
"navigationBarTitleText": "学习分析",
"app-plus": {
"titleNView": false
}
}
}
],
"tabBar": {
+20 -4
View File
@@ -9,11 +9,15 @@
</view>
</view>
</view>
<view class="title">
<view class="title" v-if="fromType === 'crs'">
<image class="title-icon" src="@/static/images/course/edit.png" alt=""> </image>
改进建议
</view>
<view class="total-score">
<view class="title" v-if="fromType === 'tra'">
<image class="title-icon icon-tra" src="@/static/images/sparring/den-icon.png" alt=""> </image>
维度分析
</view>
<view class="total-score" v-if="fromType === 'crs'">
<view class="score-num">{{ score }}</view>
<image class="total-score-icon" src="@/static/images/course/score.png" alt=""></image>
</view>
@@ -37,6 +41,10 @@
size:{
default: 262,
type: [Number,String]
},
fromType:{
default: 'crs',
type: String
}
},
data(){
@@ -96,7 +104,7 @@
return `polygon(${_tx}% ${_ty}%, ${_rx}% ${_ry}%, ${_bx}% ${_by}%, ${_lx}% ${_ly}%, ${_lxl}% ${_lyl}%)`
},
styleFiveResult(){
let score = this.dataList
let score = this.dataValue
if(score.length >= 5){
let base = 50
let _tx = 50
@@ -253,9 +261,17 @@
line-height: 46rpx;
font-size: 32rpx;
color: #fff;
.title-icon{
position: relative;
.title-icon {
width: 27rpx;
height: 27rpx;
&.icon-tra{
position: relative;
top: 4rpx;
width: 32rpx;
height: 32rpx;
}
}
}
.total-score{
+119 -81
View File
@@ -4,19 +4,23 @@
<view v-for="width in 3" :class="`percent-${width * 25}`"></view>
<view class="data-box">
<view class="line-box">
<view v-for="width in 3" :class="`percent-${width * 25}`"></view>
<view v-for="width in 3" :class="`percent-${width * 25}`"></view>
</view>
</view>
</view>
<view class="title">
<image class="title-icon" src="@/static/images/course/edit.png" alt=""> </image>
<view class="title" v-if="fromType === 'crs'">
<image class="title-icon" src="@/static/images/course/edit.png" alt=""> </image>
改进建议
</view>
<view class="total-score">
<view class="score-num">{{props.score}}</view>
<image class="total-score-icon" src="@/static/images/course/score.png" alt=""></image>
<view class="title" v-if="fromType === 'tra'">
<image class="title-icon icon-tra" src="@/static/images/sparring/den-icon.png" alt=""> </image>
维度分析
</view>
<view v-for="item,index in props.dataList" :class="['score-item', 'score-item'+(index+1)]">
<view class="total-score" v-if="fromType === 'crs'">
<view class="score-num">{{ props.score }}</view>
<image class="total-score-icon" src="@/static/images/course/score.png" alt=""></image>
</view>
<view v-for="item,index in props.dataList" :class="['score-item', 'score-item'+(index+1)]">
<view class="score-item-name">{{ item.gradeDimensName || item.gradeDimens }}</view>
<view class="score-item-score">{{ item.anlyGrade }}</view>
</view>
@@ -24,81 +28,90 @@
</template>
<script setup>
import { ref, computed} from "vue"
import {
ref,
computed
} from "vue"
const props = defineProps({
dataList:{
default:() => [],
dataList: {
default: () => [],
type: Array
},
score:{
score: {
default: 0,
type: [Number,String]
type: [Number, String]
},
size:{
size: {
default: 262,
type: [Number,String]
type: [Number, String]
},
fromType: {
default: 'crs',
type: String
}
})
const dataValue = computed(() => {
return props.dataList.map(t=>t.anlyGrade)
return props.dataList.map(t => t.anlyGrade)
})
const chartWidth = computed(() => props.size + 'rpx')
const chartHeight = computed(() => props.size + 'rpx')
const scoreMarginX = computed(() => {
return props.size/2 + 'rpx'
return props.size / 2 + 'rpx'
})
const scoreMarginY = computed(() => {
return (props.size/2 + 30) + 'rpx'
return (props.size / 2 + 30) + 'rpx'
})
const scoreMarginAbsX = computed(() => {
return '-' + (props.size/2 ) + 'rpx'
return '-' + (props.size / 2) + 'rpx'
})
const scoreMarginAbsY = computed(() => {
return '-' + (props.size/2 - 25) + 'rpx'
return '-' + (props.size / 2 - 25) + 'rpx'
})
const styleFour = ref('polygon(50% 0%, 100% 50%, 50% 100%, 0% 50%)')
const styleFourResult = computed(()=>{
const styleFourResult = computed(() => {
let score = dataValue.value
if(score.length>=4){
if (score.length >= 4) {
let _tx = 50
let _ty = 50 - Math.floor((score[0]/100)*50)
let _rx = 50 + Math.floor((score[1]/100)*50)
let _ty = 50 - Math.floor((score[0] / 100) * 50)
let _rx = 50 + Math.floor((score[1] / 100) * 50)
let _ry = 50
let _bx = 50
let _by = 50 + Math.floor((score[2]/100)*50)
let _lx = 50 - Math.floor((score[3]/100)*50)
let _by = 50 + Math.floor((score[2] / 100) * 50)
let _lx = 50 - Math.floor((score[3] / 100) * 50)
let _ly = 50
return `polygon(${_tx}% ${_ty}%, ${_rx}% ${_ry}%, ${_bx}% ${_by}%, ${_lx}% ${_ly}%)`
}else{
} else {
return `polygon(${0}% ${50}%, ${50}% ${100}%, ${100}% ${50}%, ${50}% ${0}%)`
}
})
</script>
<style lang="scss" scoped>
.chart-box{
.chart-box {
width: 100%;
height: 580rpx;
background:linear-gradient( 270deg, #4a74ff 0%, #6fa7fe 100%);
background: linear-gradient(270deg, #4a74ff 0%, #6fa7fe 100%);
overflow: hidden;
position: relative;
border-radius: 16rpx;
margin-bottom: 20rpx;
.cont-box{
.cont-box {
background-color: #87abfe;
width: v-bind(chartWidth);
height: v-bind(chartHeight);
clip-path: v-bind(styleFour);
clip-path: v-bind(styleFour);
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
margin-top: 25rpx;
&::before{
&::before {
content: '';
display: block;
width: 100%;
height: 3rpx;
height: 3rpx;
background-color: rgba(255, 255, 255, .3);
position: absolute;
top: 50%;
@@ -106,11 +119,12 @@
transform: translate(-50%, -50%);
z-index: 20;
}
&::after{
&::after {
content: '';
display: block;
height: 100%;
width: 3rpx;
width: 3rpx;
background-color: rgba(255, 255, 255, .3);
position: absolute;
top: 50%;
@@ -118,24 +132,26 @@
transform: translate(-50%, -50%);
z-index: 20;
}
@for $i from 1 through 3 {
.percent-#{$i*25}{
.percent-#{$i*25} {
width: $i * 25%;
height: $i * 25%;
clip-path: v-bind(styleFour);
clip-path: v-bind(styleFour);
background-color: rgba(255, 255, 255, .3);
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
z-index: (4 - $i) * 2;
&::before{
&::before {
content: '';
display: block;
width: calc(100% - 10rpx);
height: calc(100% - 10rpx);
background-color: #87abfe;
clip-path: v-bind(styleFour);
clip-path: v-bind(styleFour);
position: absolute;
top: 50%;
left: 50%;
@@ -143,56 +159,69 @@
}
}
}
.data-box{
width: 100%;
height: 100%;
clip-path: v-bind(styleFourResult);
.data-box {
width: 100%;
height: 100%;
clip-path: v-bind(styleFourResult);
position: absolute;
background-color: #fff;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
z-index: 12;
overflow: hidden;
.line-box {
display: block;
width: calc(100% - 24rpx);
height: calc(100% - 24rpx);
// background-color: #6691fe;
background-color: #6691fe;
clip-path: v-bind(styleFourResult);
position: absolute;
background-color: #fff;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
z-index: 12;
overflow: hidden;
.line-box{
display: block;
width: calc(100% - 24rpx);
height: calc(100% - 24rpx);
// background-color: #6691fe;
background-color: #6691fe;
clip-path: v-bind(styleFourResult);
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
z-index: 14;
}
@for $i from 1 through 3 {
.percent-#{$i*25}{
background-color: rgba(255, 255, 255, .1);
z-index: (4 - $i) * 2 + 10;
&::before{
background-color: #6692ff;
}
z-index: 14;
}
@for $i from 1 through 3 {
.percent-#{$i*25} {
background-color: rgba(255, 255, 255, .1);
z-index: (4 - $i) * 2 + 10;
&::before {
background-color: #6692ff;
}
}
}
}
}
.title{
.title {
padding: 24rpx;
line-height: 46rpx;
font-size: 32rpx;
color: #fff;
.title-icon{
position: relative;
.title-icon {
width: 27rpx;
height: 27rpx;
&.icon-tra{
position: relative;
top: 4rpx;
width: 32rpx;
height: 32rpx;
}
}
}
.total-score{
.total-score {
position: absolute;
right: 30rpx;
top:30rpx;
top: 30rpx;
width: 100rpx;
height: 80rpx;
line-height: 70rpx;
@@ -200,53 +229,62 @@
color: #fff;
white-space: nowrap;
text-shadow: 0 4px 12px rgba(0, 0, 0, .33);
.score-num{
.score-num {
display: inline-block;
font-size: 60rpx;
line-height: 70rpx;
font-weight: bold;
}
.total-score-icon{
.total-score-icon {
width: 100%;
height: 16rpx;
position: absolute;
bottom:0;
left:0;
bottom: 0;
left: 0;
}
}
.score-item{
.score-item {
position: absolute;
color: #fff;
width: 120rpx;
text-align: center;
.score-item-name{
.score-item-name {
font-size: 28rpx;
line-height: 36rpx;
margin-bottom: 4rpx;
}
.score-item-score{
.score-item-score {
font-size: 38rpx;
line-height: 46rpx;
font-weight: bold;
}
&.score-item1{
&.score-item1 {
left: 50%;
margin-left: -60rpx;
bottom: 50%;
transform: translateY(v-bind(scoreMarginAbsY));
}
&.score-item2{
&.score-item2 {
right: 0%;
top: 50%;
transform: translate(calc(v-bind(scoreMarginAbsX) + 60rpx), calc(-50% + 25rpx));
}
&.score-item3{
&.score-item3 {
left: 50%;
margin-left: -60rpx;
top: 50%;
transform: translateY(v-bind(scoreMarginY));
}
&.score-item4{
&.score-item4 {
left: 0%;
top: 50%;
transform: translate(calc(v-bind(scoreMarginX) - 60rpx), calc(-50% + 25rpx));
+348
View File
@@ -0,0 +1,348 @@
<template>
<view class="chart-box" :style="allStyle">
<view class="cont-box">
<view v-for="width in 7" :class="'total-line total-line' + width"></view>
<view v-for="width in 3" :class="`percent-${width * 25}`"></view>
<view class="data-box">
<view class="line-box">
<view v-for="width in 3" :class="`percent-${width * 25}`"></view>
</view>
</view>
</view>
<view class="title" v-if="fromType === 'crs'">
<image class="title-icon" src="@/static/images/course/edit.png" alt=""> </image>
改进建议
</view>
<view class="title" v-if="fromType === 'tra'">
<image class="title-icon icon-tra" src="@/static/images/sparring/den-icon.png" alt=""> </image>
维度分析22
</view>
<view class="total-score" v-if="fromType === 'crs'">
<view class="score-num">{{ score }}</view>
<image class="total-score-icon" src="@/static/images/course/score.png" alt=""></image>
</view>
<view v-for="(item,index) in dataList" :class="['score-item', 'score-item'+(index+1)]">
<view class="score-item-name">维度{{ item }}</view>
<view class="score-item-score">{{ item }}</view>
</view>
</view>
</template>
<script>
export default{
props:{
dataList:{
default:() => [10,20,30,40,50,60,78],
type: Array
},
score:{
default: 0,
type: [Number,String]
},
size:{
default: 262,
type: [Number,String]
},
fromType:{
default: 'crs',
type: String
}
},
data(){
return {
}
},
computed:{
dataValue(){
return this.dataList//.map(t=>t.anlyGrade)
},
chartWidth(){
return this.size + 'rpx'
},
chartHeight(){
return this.size + 'rpx'
},
styleFive(){
return this.generateHeptagonClipPath()
},
styleFiveResult(){
return this.generateHeptagonDataClipPath()
},
verticesList(){
return this.calculateHeptagonVertices()
},
allStyle(){
let _obj = {
'--styleFive': this.styleFive,
'--styleFiveResult': this.styleFiveResult,
'--chartWidth': this.chartWidth,
'--chartHeight': this.chartHeight,
'--boxSize': this.size + 'rpx'
}
this.verticesList.forEach((t,index)=>{
_obj[`--pointX${index+1}`] = t.x/100
_obj[`--pointY${index+1}`] = t.y/100
// _obj[`--pointX${index+1}`] = t.cssX
// _obj[`--pointY${index+1}`] = t.cssY
})
return _obj
}
},
methods:{
// 正七边形顶点计算函数
calculateHeptagonVertices(radius = 50, angleOffset = 0) {
const sides = 7;
const vertices = [];
const centerX = 50;
const centerY = 50;
// 将角度偏移转换为弧度
const offsetRad = (angleOffset * Math.PI) / 180;
for (let i = 0; i < sides; i++) {
// 计算每个顶点的角度(弧度)
const angle = (2 * Math.PI * i) / sides + offsetRad;
// 计算顶点坐标(百分比)
const x = centerX + radius * Math.cos(angle);
const y = centerY + radius * Math.sin(angle);
// 计算顶点坐标(百分比)
const dataX = centerX + radius * Math.cos(angle) * this.dataValue[i] / 100;
const dataY = centerY + radius * Math.sin(angle) * this.dataValue[i] / 100;
vertices.push({
x: x,
y: y,
cssX: x + '%',
cssY: y + '%',
dataX: dataX + '%',
dataY: dataY + '%'
});
}
console.log(vertices)
return vertices;
},
// 生成CSS clip-path多边形值
generateHeptagonClipPath(radius = 50, angleOffset = 0) {
const vertices = this.calculateHeptagonVertices(radius, angleOffset);
const polygonPoints = vertices.map(v => `${v.cssX} ${v.cssY}`).join(', ');
return `polygon(${polygonPoints})`;
},
// 生成CSS clip-path多边形值
generateHeptagonDataClipPath(radius = 50, angleOffset = 0) {
const vertices = this.calculateHeptagonVertices(radius, angleOffset);
const polygonPoints = vertices.map(v => `${v.dataX} ${v.dataY}`).join(', ');
return `polygon(${polygonPoints})`;
}
}
}
</script>
<style lang="scss" scoped>
.chart-box{
width: 100%;
height: 580rpx;
background:linear-gradient( 270deg, #4a74ff 0%, #6fa7fe 100%);
overflow: hidden;
position: relative;
border-radius: 16rpx;
margin-bottom: 20rpx;
.cont-box{
background-color: #87abfe;
width: var(--chartWidth);
height: var(--chartHeight);
clip-path: var(--styleFive);
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
margin-top: 25rpx;
.total-line{
width: 100%;
height: 3rpx;
background: linear-gradient(90deg, #00000000 0% 50%, rgba(255, 255, 255, .3) 50% 100%);
position: absolute;
overflow: hidden;
z-index: 20;
top: 50%;
left: 0%;
&.total-line1{
transform: rotateZ(calc(360deg * 1 / 7));
}
&.total-line2{
transform: rotateZ(calc(360deg * 2 / 7));
}
&.total-line3{
transform: rotateZ(calc(360deg * 3 / 7));
}
&.total-line4{
transform: rotateZ(calc(360deg * 4 / 7));
}
&.total-line5{
transform: rotateZ(calc(360deg * 5 / 7));
}
&.total-line6{
transform: rotateZ(calc(360deg * 6 / 7));
}
&.total-line7{
transform: rotateZ(calc(360deg * 7 / 7));
}
}
@for $i from 1 through 3 {
.percent-#{$i*25}{
width: $i * 25%;
height: $i * 25%;
clip-path: var(--styleFive);
background-color: rgba(255, 255, 255, .3);
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
z-index: (4 - $i) * 2;
&::before{
content: '';
display: block;
width: calc(100% - 10rpx);
height: calc(100% - 10rpx);
background-color: #87abfe;
clip-path: var(--styleFive);
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
}
}
.data-box{
width: 100%;
height: 100%;
clip-path: var(--styleFiveResult);
position: absolute;
background-color: #fff;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
z-index: 12;
overflow: hidden;
.line-box{
display: block;
width: calc(100% - 24rpx);
height: calc(100% - 24rpx);
// background-color: #6691fe;
background-color: #6691fe;
clip-path: var(--styleFiveResult);
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
z-index: 14;
}
@for $i from 1 through 3 {
.percent-#{$i*25}{
background-color: rgba(255, 255, 255, .1);
z-index: (4 - $i) * 2 + 10;
&::before{
background-color: #6692ff;
}
}
}
}
}
.title{
padding: 24rpx;
line-height: 46rpx;
font-size: 32rpx;
color: #fff;
position: relative;
.title-icon {
width: 27rpx;
height: 27rpx;
&.icon-tra{
position: relative;
top: 4rpx;
width: 32rpx;
height: 32rpx;
}
}
}
.total-score{
position: absolute;
right: 30rpx;
top:30rpx;
width: 100rpx;
height: 80rpx;
line-height: 70rpx;
font-size: 30rpx;
color: #fff;
white-space: nowrap;
text-shadow: 0 4px 12px rgba(0, 0, 0, .33);
.score-num{
display: inline-block;
font-size: 60rpx;
line-height: 70rpx;
font-weight: bold;
}
.total-score-icon{
width: 100%;
height: 16rpx;
position: absolute;
bottom:0;
left:0;
}
}
.score-item{
position: absolute;
color: #fff;
width: 120rpx;
text-align: center;
.score-item-name{
font-size: 28rpx;
line-height: 36rpx;
margin-bottom: 4rpx;
}
.score-item-score{
font-size: 38rpx;
line-height: 46rpx;
font-weight: bold;
}
&.score-item1{
left: 50%;
top: 50%;
transform: translateX(calc(-50% + var(--boxSize)/2 + 60rpx));
}
&.score-item2{
left: calc(var(--pointX2) * var(--boxSize));
top: calc(50% + (var(--pointY2) * var(--boxSize) / 2));
transform: translate(calc(-50% + var(--boxSize)/2 + 80rpx), 30rpx);
}
&.score-item3{
left: calc(var(--pointX3) * var(--boxSize));
top: calc(50% + (var(--pointY3) * var(--boxSize) / 2));
transform: translate(calc(-50% + var(--boxSize)/2 + 50rpx), 30rpx);
}
&.score-item4{
left: calc(var(--pointX4) * var(--boxSize));
top: calc(50% + (var(--pointY4) * var(--boxSize) / 2));
transform: translate(calc(-50% + var(--boxSize)/2 - 10rpx), -30rpx);
}
&.score-item5{
left: calc(var(--pointX5) * var(--boxSize));
top: calc(50% + (var(--pointY5) * var(--boxSize) / 2));
transform: translate(calc(-50% + var(--boxSize)/2 - 10rpx), -120rpx);
}
&.score-item6{
left: calc(var(--pointX6) * var(--boxSize));
top: calc(50% + (var(--pointY6) * var(--boxSize) / 2));
transform: translate(calc(-50% + var(--boxSize)/2 + 60rpx), calc(-170rpx - 50%));
}
&.score-item7{
left: calc(var(--pointX6) * var(--boxSize));
top: calc(50% + (var(--pointY6) * var(--boxSize) / 2));
transform: translate(calc(-50% + var(--boxSize)/2 + 210rpx), calc(-150rpx - 50%));
}
}
}
</style>
+342
View File
@@ -0,0 +1,342 @@
<template>
<view class="chart-box" :style="allStyle">
<view class="cont-box">
<view v-for="width in 7" :class="'total-line total-line' + width"></view>
<view v-for="width in 3" :class="`percent-${width * 25}`"></view>
<view class="data-box">
<view class="line-box">
<view v-for="width in 3" :class="`percent-${width * 25}`"></view>
</view>
</view>
</view>
<view class="title" v-if="fromType === 'crs'">
<image class="title-icon" src="@/static/images/course/edit.png" alt=""> </image>
改进建议
</view>
<view class="title" v-if="fromType === 'tra'">
<image class="title-icon icon-tra" src="@/static/images/sparring/den-icon.png" alt=""> </image>
维度分析22
</view>
<view class="total-score" v-if="fromType === 'crs'">
<view class="score-num">{{ score }}</view>
<image class="total-score-icon" src="@/static/images/course/score.png" alt=""></image>
</view>
<view v-for="(item,index) in dataList" :class="['score-item', 'score-item'+(index+1)]">
<view class="score-item-name">维度维{{ item }}</view>
<view class="score-item-score">{{ item }}</view>
</view>
</view>
</template>
<script>
export default{
props:{
dataList:{
default:() => [20,30,40,50,60,78],
type: Array
},
score:{
default: 0,
type: [Number,String]
},
size:{
default: 262,
type: [Number,String]
},
fromType:{
default: 'crs',
type: String
}
},
data(){
return {
}
},
computed:{
dataValue(){
return this.dataList//.map(t=>t.anlyGrade)
},
chartWidth(){
return this.size + 'rpx'
},
chartHeight(){
return this.size + 'rpx'
},
styleFive(){
return this.generateHeptagonClipPath()
},
styleFiveResult(){
return this.generateHeptagonDataClipPath()
},
verticesList(){
return this.calculateHeptagonVertices()
},
allStyle(){
let _obj = {
'--styleFive': this.styleFive,
'--styleFiveResult': this.styleFiveResult,
'--chartWidth': this.chartWidth,
'--chartHeight': this.chartHeight,
'--boxSize': this.size + 'rpx'
}
this.verticesList.forEach((t,index)=>{
_obj[`--pointX${index+1}`] = t.x/100
_obj[`--pointY${index+1}`] = t.y/100
// _obj[`--pointX${index+1}`] = t.cssX
// _obj[`--pointY${index+1}`] = t.cssY
})
return _obj
}
},
methods:{
// 正七边形顶点计算函数
calculateHeptagonVertices(radius = 50, angleOffset = 0) {
const sides = 6;
const vertices = [];
const centerX = 50;
const centerY = 50;
// 将角度偏移转换为弧度
const offsetRad = (angleOffset * Math.PI) / 180;
for (let i = 0; i < sides; i++) {
// 计算每个顶点的角度(弧度)
const angle = (2 * Math.PI * i) / sides + offsetRad;
// 计算顶点坐标(百分比)
const x = centerX + radius * Math.cos(angle);
const y = centerY + radius * Math.sin(angle);
// 计算顶点坐标(百分比)
const dataX = centerX + radius * Math.cos(angle) * this.dataValue[i] / 100;
const dataY = centerY + radius * Math.sin(angle) * this.dataValue[i] / 100;
vertices.push({
x: x,
y: y,
cssX: x + '%',
cssY: y + '%',
dataX: dataX + '%',
dataY: dataY + '%'
});
}
console.log(vertices)
return vertices;
},
// 生成CSS clip-path多边形值
generateHeptagonClipPath(radius = 50, angleOffset = 0) {
const vertices = this.calculateHeptagonVertices(radius, angleOffset);
const polygonPoints = vertices.map(v => `${v.cssX} ${v.cssY}`).join(', ');
return `polygon(${polygonPoints})`;
},
// 生成CSS clip-path多边形值
generateHeptagonDataClipPath(radius = 50, angleOffset = 0) {
const vertices = this.calculateHeptagonVertices(radius, angleOffset);
const polygonPoints = vertices.map(v => `${v.dataX} ${v.dataY}`).join(', ');
return `polygon(${polygonPoints})`;
}
}
}
</script>
<style lang="scss" scoped>
.chart-box{
width: 100%;
height: 580rpx;
background:linear-gradient( 270deg, #4a74ff 0%, #6fa7fe 100%);
overflow: hidden;
position: relative;
border-radius: 16rpx;
margin-bottom: 20rpx;
.cont-box{
background-color: #87abfe;
width: var(--chartWidth);
height: var(--chartHeight);
clip-path: var(--styleFive);
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
margin-top: 25rpx;
.total-line{
width: 100%;
height: 3rpx;
background: linear-gradient(90deg, #00000000 0% 50%, rgba(255, 255, 255, .3) 50% 100%);
position: absolute;
overflow: hidden;
z-index: 20;
top: 50%;
left: 0%;
&.total-line1{
transform: rotateZ(calc(360deg * 1 / 6));
}
&.total-line2{
transform: rotateZ(calc(360deg * 2 / 6));
}
&.total-line3{
transform: rotateZ(calc(360deg * 3 / 6));
}
&.total-line4{
transform: rotateZ(calc(360deg * 4 / 6));
}
&.total-line5{
transform: rotateZ(calc(360deg * 5 / 6));
}
&.total-line6{
transform: rotateZ(calc(360deg * 6 / 6));
}
}
@for $i from 1 through 3 {
.percent-#{$i*25}{
width: $i * 25%;
height: $i * 25%;
clip-path: var(--styleFive);
background-color: rgba(255, 255, 255, .3);
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
z-index: (4 - $i) * 2;
&::before{
content: '';
display: block;
width: calc(100% - 10rpx);
height: calc(100% - 10rpx);
background-color: #87abfe;
clip-path: var(--styleFive);
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
}
}
.data-box{
width: 100%;
height: 100%;
clip-path: var(--styleFiveResult);
position: absolute;
background-color: #fff;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
z-index: 12;
overflow: hidden;
.line-box{
display: block;
width: calc(100% - 24rpx);
height: calc(100% - 24rpx);
// background-color: #6691fe;
background-color: #6691fe;
clip-path: var(--styleFiveResult);
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
z-index: 14;
}
@for $i from 1 through 3 {
.percent-#{$i*25}{
background-color: rgba(255, 255, 255, .1);
z-index: (4 - $i) * 2 + 10;
&::before{
background-color: #6692ff;
}
}
}
}
}
.title{
padding: 24rpx;
line-height: 46rpx;
font-size: 32rpx;
color: #fff;
position: relative;
.title-icon {
width: 27rpx;
height: 27rpx;
&.icon-tra{
position: relative;
top: 4rpx;
width: 32rpx;
height: 32rpx;
}
}
}
.total-score{
position: absolute;
right: 30rpx;
top:30rpx;
width: 100rpx;
height: 80rpx;
line-height: 70rpx;
font-size: 30rpx;
color: #fff;
white-space: nowrap;
text-shadow: 0 4px 12px rgba(0, 0, 0, .33);
.score-num{
display: inline-block;
font-size: 60rpx;
line-height: 70rpx;
font-weight: bold;
}
.total-score-icon{
width: 100%;
height: 16rpx;
position: absolute;
bottom:0;
left:0;
}
}
.score-item{
position: absolute;
color: #fff;
width: 120rpx;
text-align: center;
.score-item-name{
font-size: 28rpx;
line-height: 36rpx;
margin-bottom: 4rpx;
}
.score-item-score{
font-size: 38rpx;
line-height: 46rpx;
font-weight: bold;
}
&.score-item1{
left: 50%;
top: 50%;
transform: translate(calc(-50% + var(--boxSize)/2 + 60rpx), -50%);
margin-top: 25rpx;
}
&.score-item2{
left: calc(var(--pointX2) * var(--boxSize));
top: calc(50% + (var(--pointY2) * var(--boxSize) / 2));
transform: translate(calc(-50% + var(--boxSize)/2 + 80rpx), 30rpx);
}
&.score-item3{
left: calc(var(--pointX3) * var(--boxSize));
top: calc(50% + (var(--pointY3) * var(--boxSize) / 2));
transform: translate(calc(-50% + var(--boxSize)/2 + 50rpx), 30rpx);
}
&.score-item4{
left: calc(var(--pointX4) * var(--boxSize));
top: 50% ;
transform: translate(calc(-50% + var(--boxSize)/2 - 10rpx), -50%);
margin-top: 25rpx;
}
&.score-item5{
left: calc(var(--pointX5) * var(--boxSize));
top: calc(50% + (var(--pointY5) * var(--boxSize) / 2));
transform: translate(calc(-50% + var(--boxSize)/2 + 50rpx), calc(-160rpx - 50%));
}
&.score-item6{
left: calc(var(--pointX6) * var(--boxSize));
top: calc(50% + (var(--pointY6) * var(--boxSize) / 2));
transform: translate(calc(-50% + var(--boxSize)/2 + 80rpx), calc(-160rpx - 50%));
}
}
}
</style>
+136 -97
View File
@@ -7,19 +7,23 @@
<view v-for="width in 3" :class="`percent-${width * 25}`"></view>
<view class="data-box">
<view class="line-box">
<view v-for="width in 3" :class="`percent-${width * 25}`"></view>
<view v-for="width in 3" :class="`percent-${width * 25}`"></view>
</view>
</view>
</view>
<view class="title">
<image class="title-icon" src="@/static/images/course/edit.png" alt=""> </image>
<view class="title" v-if="fromType === 'crs'">
<image class="title-icon" src="@/static/images/course/edit.png" alt=""> </image>
改进建议
</view>
<view class="total-score">
<view class="score-num">{{props.score}}</view>
<image class="total-score-icon" src="@/static/images/course/score.png" alt="" ></image>
<view class="title" v-if="fromType === 'tra'">
<image class="title-icon icon-tra" src="@/static/images/sparring/den-icon.png" alt=""> </image>
维度分析
</view>
<view v-for="item,index in props.dataList" :class="['score-item', 'score-item'+(index+1)]">
<view class="total-score" v-if="fromType === 'crs'">
<view class="score-num">{{ props.score }}</view>
<image class="total-score-icon" src="@/static/images/course/score.png" alt=""></image>
</view>
<view v-for="item,index in props.dataList" :class="['score-item', 'score-item'+(index+1)]">
<view class="score-item-name">{{ item.gradeDimensName || item.gradeDimens }}</view>
<view class="score-item-score">{{ item.anlyGrade }}</view>
</view>
@@ -27,130 +31,144 @@
</template>
<script setup>
import { ref, computed} from "vue"
import {
ref,
computed
} from "vue"
const props = defineProps({
dataList:{
default:() => [],
dataList: {
default: () => [],
type: Array
},
score:{
score: {
default: 0,
type: [Number,String]
type: [Number, String]
},
size:{
size: {
default: 262,
type: [Number,String]
type: [Number, String]
},
fromType: {
default: 'crs',
type: String
}
})
const dataValue = computed(() => {
return props.dataList.map(t=>t.anlyGrade)
return props.dataList.map(t => t.anlyGrade)
})
let _scale = .9
const chartWidth = computed(() => props.size / _scale + 'rpx')
const chartHeight = computed(() => props.size / _scale + 'rpx')
const scoreMarginX = computed(() => {
return (props.size/2 + 20) + 'rpx'
return (props.size / 2 + 20) + 'rpx'
})
const scoreMarginAbsY = computed(() => {
return '-' + (props.size/2 - 40) + 'rpx'
return '-' + (props.size / 2 - 40) + 'rpx'
})
const scoreMarginPercentY = computed(() => {
let score = dataValue.value
return setPercent(80, Math.round(100 * 1.732 / 6 * _scale * 100)/100) + '%'
return setPercent(80, Math.round(100 * 1.732 / 6 * _scale * 100) / 100) + '%'
})
const styleFour = computed(()=>{
const styleFour = computed(() => {
// let _blank = (50 - Math.round(100 * 1.732 / 3))/2
// let _margin = _blank +
let _tx = 50
let _ty = 50 - Math.round(100 * 1.732 / 3)* _scale
let _rx = 50 + 50 *_scale
let _ry = 50 + Math.round(100 * 1.732 / 6)* _scale
let _bx = 50 - 50 *_scale
let _by = 50 + Math.round(100 * 1.732 / 6)* _scale
let _tx = 50
let _ty = 50 - Math.round(100 * 1.732 / 3) * _scale
let _rx = 50 + 50 * _scale
let _ry = 50 + Math.round(100 * 1.732 / 6) * _scale
let _bx = 50 - 50 * _scale
let _by = 50 + Math.round(100 * 1.732 / 6) * _scale
return `polygon(${_tx}% ${_ty}%, ${_rx}% ${_ry}%, ${_bx}% ${_by}%)`
})
const styleFourResult = computed(()=>{
const styleFourResult = computed(() => {
let score = dataValue.value
if(score.length >= 3){
let _tx = 50
let _ty = 50 - setPercent(score[0], Math.round(100 * 1.732 / 3 * _scale * 100)/100)
let _rx = 50 + setPercent(score[1], Math.round(50 *_scale * 100)/100)
let _ry = 50 + setPercent(score[1], Math.round(100 * 1.732 / 6 * _scale * 100)/100)
let _bx = 50 - setPercent(score[2], Math.round(50 *_scale * 100)/100)
let _by = 50 + setPercent(score[2], Math.round(100 * 1.732 / 6 * _scale * 100)/100)
if (score.length >= 3) {
let _tx = 50
let _ty = 50 - setPercent(score[0], Math.round(100 * 1.732 / 3 * _scale * 100) / 100)
let _rx = 50 + setPercent(score[1], Math.round(50 * _scale * 100) / 100)
let _ry = 50 + setPercent(score[1], Math.round(100 * 1.732 / 6 * _scale * 100) / 100)
let _bx = 50 - setPercent(score[2], Math.round(50 * _scale * 100) / 100)
let _by = 50 + setPercent(score[2], Math.round(100 * 1.732 / 6 * _scale * 100) / 100)
return `polygon(${_tx}% ${_ty}%, ${_rx}% ${_ry}%, ${_bx}% ${_by}%)`
}else{
} else {
return styleFour.value
}
})
const setPercent = (precent, show) => {
return Math.floor((precent/100) * show)
return Math.floor((precent / 100) * show)
}
</script>
<style lang="scss" scoped>
.chart-box{
.chart-box {
width: 100%;
height: 580rpx;
background:linear-gradient( 270deg, #4a74ff 0%, #6fa7fe 100%);
background: linear-gradient(270deg, #4a74ff 0%, #6fa7fe 100%);
overflow: hidden;
position: relative;
border-radius: 16rpx;
margin-bottom: 20rpx;
.cont-box{
.cont-box {
background-color: #87abfe;
width: v-bind(chartWidth);
height: v-bind(chartHeight);
clip-path: v-bind(styleFour);
clip-path: v-bind(styleFour);
position: absolute;
top: calc(60% + 20rpx);
left: 50%;
transform: translate(-50%, -50%);
.total-line{
.total-line {
width: 57.7%;
height: 3rpx;
height: 3rpx;
background-color: rgba(255, 255, 255, .3);
position: absolute;
overflow: hidden;
z-index: 20;
&.total-line1{
&.total-line1 {
top: 64.5%;
left: 46.5%;
transform: rotateZ(30deg);
}
&.total-line2{
&.total-line2 {
top: 64.5%;
left:-4.5%;
left: -4.5%;
transform: rotateZ(150deg);
}
&.total-line3{
&.total-line3 {
top: 21.5%;
left: 21%;
transform: rotateZ(-90deg);
}
}
@for $i from 1 through 3 {
.percent-#{$i*25}{
.percent-#{$i*25} {
width: $i * 25%;
height: $i * 25%;
clip-path: v-bind(styleFour);
clip-path: v-bind(styleFour);
background-color: rgba(255, 255, 255, .3);
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
z-index: (4 - $i) * 2;
&::before{
&::before {
content: '';
display: block;
width: calc(100% - 10rpx);
height: calc(100% - 10rpx);
background-color: #87abfe;
clip-path: v-bind(styleFour);
clip-path: v-bind(styleFour);
position: absolute;
top: 50%;
left: 50%;
@@ -158,56 +176,69 @@
}
}
}
.data-box{
width: 100%;
height: 100%;
clip-path: v-bind(styleFourResult);
.data-box {
width: 100%;
height: 100%;
clip-path: v-bind(styleFourResult);
position: absolute;
background-color: #fff;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
z-index: 12;
overflow: hidden;
.line-box {
display: block;
width: calc(100% - 24rpx);
height: calc(100% - 24rpx);
// background-color: #6691fe;
background-color: #6691fe;
clip-path: v-bind(styleFourResult);
position: absolute;
background-color: #fff;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
z-index: 12;
overflow: hidden;
.line-box{
display: block;
width: calc(100% - 24rpx);
height: calc(100% - 24rpx);
// background-color: #6691fe;
background-color: #6691fe;
clip-path: v-bind(styleFourResult);
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
z-index: 14;
}
@for $i from 1 through 3 {
.percent-#{$i*25}{
background-color: rgba(255, 255, 255, .1);
z-index: (4 - $i) * 2 + 10;
&::before{
background-color: #6692ff;
}
z-index: 14;
}
@for $i from 1 through 3 {
.percent-#{$i*25} {
background-color: rgba(255, 255, 255, .1);
z-index: (4 - $i) * 2 + 10;
&::before {
background-color: #6692ff;
}
}
}
}
}
.title{
.title {
padding: 24rpx;
line-height: 46rpx;
font-size: 32rpx;
color: #fff;
.title-icon{
position: relative;
.title-icon {
width: 27rpx;
height: 27rpx;
&.icon-tra{
position: relative;
top: 4rpx;
width: 32rpx;
height: 32rpx;
}
}
}
.total-score{
.total-score {
position: absolute;
right: 30rpx;
top:30rpx;
top: 30rpx;
width: 100rpx;
height: 80rpx;
line-height: 70rpx;
@@ -215,47 +246,55 @@
color: #fff;
white-space: nowrap;
text-shadow: 0 4px 12px rgba(0, 0, 0, .33);
.score-num{
.score-num {
display: inline-block;
font-size: 60rpx;
line-height: 70rpx;
font-weight: bold;
}
.total-score-icon{
.total-score-icon {
width: 100%;
height: 16rpx;
position: absolute;
bottom:0;
left:0;
bottom: 0;
left: 0;
}
}
.score-item{
.score-item {
position: absolute;
color: #fff;
width: 120rpx;
text-align: center;
.score-item-name{
.score-item-name {
font-size: 28rpx;
line-height: 36rpx;
margin-bottom: 4rpx;
}
.score-item-score{
.score-item-score {
font-size: 38rpx;
line-height: 46rpx;
font-weight: bold;
}
&.score-item1{
&.score-item1 {
left: 50%;
margin-left: -60rpx;
bottom: 50%;
transform: translateY(v-bind(scoreMarginAbsY));
}
&.score-item2{
left: calc( 50% + v-bind(scoreMarginX));
&.score-item2 {
left: calc(50% + v-bind(scoreMarginX));
bottom: calc(v-bind(scoreMarginPercentY) - 30rpx);
}
&.score-item3{
right: calc( 50% + v-bind(scoreMarginX));
&.score-item3 {
right: calc(50% + v-bind(scoreMarginX));
bottom: calc(v-bind(scoreMarginPercentY) - 30rpx);
}
}
+225
View File
@@ -0,0 +1,225 @@
<template>
<uni-popup ref="feedbackPopupRef" class="popup">
<view class="feedback_popup_div" :style="{marginBottom:feedback_popup_bottom}">
<view class="title_div">
<view class="text">
反馈
</view>
<view class="popup_back_div" @click="openFeedback(false)">
<image :src="optionErrorIcon('#000000')" class="img"></image>
</view>
</view>
<view class="feedback_item_div">
<view class="feedback_item"
:class="{'feedback_item_clidked':feedbackInfo.type.includes(feedback_type_item.value)}"
@click="feedback_item_click(feedback_type_item.value)"
v-for="feedback_type_item in feedbackTypeList">{{feedback_type_item.label}}</view>
</view>
<view class="feedback_text_area_div">
<uv-textarea height="124" count :maxlength="100" placeholder="请输入反馈内容..." :adjustPosition="false"
v-model="feedbackInfo.text"></uv-textarea>
</view>
<view class="feedback_button">
<uv-button class="button" type="primary" :throttleTime="100" text="提交" color="#0066FF"
custom-style="color:#FFFFFF;borderRadius:16rpx;height:92rpx;"
@click="submit_feedback_fun()"></uv-button>
</view>
</view>
</uni-popup>
</template>
<script setup>
import {
ref,
reactive,
computed,
onMounted,
nextTick
} from 'vue';
import {
insertTraAskFeedback
} from "@/api/dialog.js"
import {
optionErrorIcon
} from '@/common/imgSvg'
import common from '../../../common/common';
const emit = defineEmits(['feedbackAnswer'])
const feedback_popup_bottom = ref('0px') // 反馈框下距离
const feedbackPopupRef = ref(null)
// FM("01", "虚假信息"),
// AE("02", "回答不准确"),
// NH("03", "没有帮助"),
// OTHER("04", "其他"),
const feedbackTypeList = reactive([{
value: "01",
label: "场景问题",
}, {
value: "02",
label: "功能问题",
}, {
value: "03",
label: "没有帮助",
}, {
value: "04",
label: "其他",
}])
const feedbackInfo = ref({
type: [], // 反馈类型
text: '', // 反馈内容
traId: '', // ID
})
const feedback_item_click = (value) => {
// 单选
// feedbackInfo.value.type = [value]
// 多选
if (feedbackInfo.value.type.includes(value)) {
feedbackInfo.value.type = feedbackInfo.value.type.filter(item => item !== value); // 如果已存在,则从数组中移除
} else {
feedbackInfo.value.type.push(value); // 如果不存在,则添加到数组中
}
}
const answerData = ref({})
// 反馈提交
const submit_feedback_fun = () => {
if(!feedbackInfo.value.text){
common.msg('反馈内容不能为空!')
return
}
// todo 待接口
const params = JSON.parse(JSON.stringify({
askId: answerData.value.seqNo,
fbkTyp: feedbackInfo.value.type.join(','),
reqBatch: answerData.value.reqBatch,
fbkContent: feedbackInfo.value.text
}))
insertTraAskFeedback(params).then(res=>{
common.msg('反馈提交成功!')
feedbackInfo.value = {
type: [], // 反馈类型
text: '', // 反馈内容
traId: '', // ID
}
close()
emit('feedbackAnswer', params)
})
}
const openFeedback = (status) => {
if (status) {
feedbackPopupRef.value.open('bottom')
const systemInfo = uni.getSystemInfoSync();
// 安全区域底部到屏幕底部的高度(即底部安全区域高度)
const safeAreaBottomHeight = systemInfo.screenHeight - systemInfo.safeArea.bottom;
//#ifdef APP-PLUS
nextTick(() => {
uni.onKeyboardHeightChange(res => {
let keyboardHeight = res.height;
// 仅在iOS端补偿安全区域高度
if (systemInfo.platform === 'ios') {
keyboardHeight = Math.max(0, keyboardHeight - safeAreaBottomHeight); // 避免负数
}
feedback_popup_bottom.value = `${keyboardHeight}px`;
});
})
// #endif
} else {
feedbackPopupRef.value.close()
}
}
const open = (data) => {
answerData.value = JSON.parse(JSON.stringify(data))
openFeedback(true)
}
const close = () => {
openFeedback(null)
}
defineExpose({
open,
close
})
</script>
<style scoped lang="scss">
.feedback_popup_div {
width: 100%;
height: 100%;
background-color: #FFFFFF;
padding: 10rpx 34rpx;
display: flex;
flex-direction: column;
align-items: center;
border-radius: 16rpx 16rpx 0px 0px;
position: relative;
.title_div {
width: 100%;
text-align: center;
padding: 30rpx 0;
font-family: PingFangSC;
font-weight: 600;
font-size: 34rpx;
color: #000000;
text-align: center;
font-style: normal;
border-bottom: 2rpx solid #EFEFEF;
}
.popup_back_div {
width: 60rpx;
height: 60rpx;
position: absolute;
top: 30rpx;
right: 30rpx;
display: flex;
align-items: center;
justify-content: center;
z-index: 99;
.img {
width: 30rpx;
height: 30rpx;
}
}
.feedback_item.feedback_item_clidked {
border: 2rpx solid #0066FF !important;
background-color: #fff !important;
}
.feedback_item_div {
// display: flex;
// align-items: center;
// justify-content: space-between;
width: 100%;
margin: 30rpx 0;
.feedback_item {
float: left;
width: calc(50% - 20rpx);
border: 2rpx solid #F0F0F0;
background-color: #F0F0F0;
border-radius: 16rpx;
padding: 26rpx 36rpx;
font-family: PingFangSC;
font-weight: 500;
font-size: 30rpx;
color: #000000;
text-align: center;
margin-bottom: 20rpx;
&:nth-child(2n){
margin-left: 40rpx;
}
}
}
.feedback_text_area_div {
width: 100%;
margin-bottom: 40rpx;
}
.feedback_button {
width: 100%;
margin-bottom: 20rpx;
}
}
</style>
+388
View File
@@ -0,0 +1,388 @@
<template>
<view class="result-cont">
<view class="top-box">
<view class="top-title">
<view class="back-icon" @click="common.navigateBack()"></view>
{{ '陪练报告' }}
<view class="feedback-icon" @click="feedbackNow"></view>
</view>
</view>
<view class="body-content">
<view class="body-top">
<view class="body-top-title">
{{'陪练名称陪练名称陪练名称陪练名称陪练名称陪练名称陪练名称陪练名称陪练名称'}}
</view>
<view class="body-top-time">
陪练时长{{'12分 15秒'}}
</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="talk-item"></view>
</view>
<view :class="['body-top-collepse-cont', showAllTalk?'show-all':'']">
<view class="talk-item"></view>
</view>
</view>
<view class="body-bottom">
<view class="body-bottom-title">维度评价总览</view>
<view class="body-bottom-item">
<view class="item-title">话术完整性 {{ 88 }}
<image class="item-title-icon" src="@/static/images/sparring/info-icon.png"></image>
</view>
<view class="item-cont">逻辑贯穿性逻辑贯穿性逻辑贯穿性逻辑贯穿性逻辑贯穿性逻辑贯穿性逻辑贯穿性逻辑贯穿性逻辑贯穿性逻辑贯穿性逻辑贯穿性逻辑贯穿性</view>
</view>
<view class="body-bottom-item">
<view class="item-title">话术完整性 {{ 88 }}
<image class="item-title-icon" src="@/static/images/sparring/info-icon.png"></image>
</view>
<view class="item-cont">逻辑贯穿性逻辑贯穿性逻辑贯穿性逻辑贯穿性逻辑贯穿性逻辑贯穿性逻辑贯穿性逻辑贯穿性逻辑贯穿性逻辑贯穿性逻辑贯穿性逻辑贯穿性</view>
</view>
<view class="body-bottom-item">
<view class="item-title">话术完整性 {{ 88 }}
<image class="item-title-icon" src="@/static/images/sparring/info-icon.png"></image>
</view>
<view class="item-cont">逻辑贯穿性逻辑贯穿性逻辑贯穿性逻辑贯穿性逻辑贯穿性逻辑贯穿性逻辑贯穿性逻辑贯穿性逻辑贯穿性逻辑贯穿性逻辑贯穿性逻辑贯穿性</view>
</view>
<view class="body-bottom-item">
<view class="item-title">话术完整性 {{ 88 }}
<image class="item-title-icon" src="@/static/images/sparring/info-icon.png"></image>
</view>
<view class="item-cont">逻辑贯穿性逻辑贯穿性逻辑贯穿性逻辑贯穿性逻辑贯穿性逻辑贯穿性逻辑贯穿性逻辑贯穿性逻辑贯穿性逻辑贯穿性逻辑贯穿性逻辑贯穿性</view>
</view>
<view :class="['body-bottom-static', 'pass','fialed']">
<view class="static-tip">得分</view>
<view class="static-score">{{ 97 }}</view>
<view class="static-desc">革命尚未成功同志仍需努力</view>
<view class="static-charts">
<!-- <ChartThree v-if="length === 3" fromType="tra" :dataList="evalDimens" />
<ChartFour v-if="length === 4" fromType="tra" :dataList="evalDimens" />
<ChartFive v-if="length === 5" fromType="tra" :dataList="evalDimens" />-->
<ChartSix fromType="tra" />
<!-- <ChartSeven v-if="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
} from '@dcloudio/uni-app';
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';
const traId = ref('')
const feedbackRef = ref()
const roleInfo = ref({})
const showAllTalk = ref(false)
const length = ref(6)
const tabList = ref([
{
name: '全部',
value: ''
},
{
name: '优秀',
value: '01'
},
{
name: '欠佳',
value: '02'
}
])
const evalDimens = [{
gradeDimensName: '维度1',
anlyGrade: 60
}, {
gradeDimensName: '维度2',
anlyGrade: 80
}, {
gradeDimensName: '维度3',
anlyGrade: 30
}]
const feedbackNow = () => {
feedbackRef.value.open({});
}
const changeTab = (info) => {
console.log(info)
}
onLoad((params) => {
traId.value = params.traId;
});
onMounted(() => {})
</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;
}
.top-box {
height: 90rpx;
width: 100%;
position: fixed;
top: var(--status-bar-height);
left: 0;
z-index: 2;
.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 {
position: relative;
.collepse-tab{
position: absolute;
width: 360rpx;
right: 120rpx;
top: 4rpx;
}
.collepse-btn {
position: absolute;
right: 0;
top: 20rpx;
width: 108rpx;
height: 46rpx;
border: 2rpx solid #d4dce8;
border-radius: 23rpx;
&.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;
}
&-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;
}
}
.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;
}
.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;
background-color: #0f0;
}
.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>
+10
View File
@@ -0,0 +1,10 @@
<template>
<!-- 通话 -->
<view>通话</view>
</template>
<script>
</script>
<style>
</style>
+8
View File
@@ -0,0 +1,8 @@
<template>
</template>
<script>
</script>
<style>
</style>
+27
View File
@@ -89,6 +89,33 @@
"titleNView": false
}
}
},
{
"path": "pages/sparring/talk",
"style": {
"navigationBarTitleText": "AI陪练通话",
"app-plus": {
"titleNView": false
}
}
},
{
"path": "pages/sparring/result",
"style": {
"navigationBarTitleText": "AI陪练报告",
"app-plus": {
"titleNView": false
}
}
},
{
"path": "pages/static/study",
"style": {
"navigationBarTitleText": "学习分析",
"app-plus": {
"titleNView": false
}
}
}
]
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 796 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 755 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 976 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 822 B