二层数组:根据快捷打分算出比率,给嵌套数组的每一个分值乘以比率,并向下取整,若此时差值是正数,就再次循环数组,给每个分数加1,同时差值减1,直到差值为0
<template>
<scroll-view :scroll-y="true" class="container_cr">
<view class="cr_wrapper">
<view class="label">
快捷打分
</view>
<view class="slider">
<u-slider id="scoreID" :class="`score${fastScore}`" v-model="fastScore" @change="toFastMark" step="10"
min="70" max="90" height="8"></u-slider>
</view>
<view class="cate" v-for="item in arr">
<view class="title">{{item.title}}</view>
<view v-for="record in item.classSettingVOList" class="indicatorBox">
<view class="indicator">
{{record.content}}
</view>
<view class="markBox">
评分:<u-number-box v-model="record.trueScore" :max="record.score" :min="0"
bgColor="#F5F6FB"></u-number-box>
</view>
</view>
</view>
<view class="cate">
<view class="title">听课主要内容记录(不得为空)</view>
<view class="indicatorBox">
<u--textarea v-model="info.advice" placeholder="听课主要内容记录(不得为空)"></u--textarea>
</view>
</view>
</view>
<view class="btnBox">
<text class="defaultBtn" @click="toSubmit(0)">暂存</text>
<text class="primaryBtn" @click="toSubmit(1)">提交</text>
</view>
</scroll-view>
</template>
<script>
import {
getEvaluateData,
saveClassEvaluate
} from '../../service/patrol';
export default {
name: "classReview",
props: ['lessonId'],
data() {
return {
fastScore: 80,
info: {},
arr: [{
title: '师德师风(10分)',
classSettingVOList: [{
content: '1.紧扣教学大纲内容,内容饱满、材料丰富、理论和实践相结合、详略得当。(5分)',
score: 7,
mark: 0
}, {
content: '2.教学设计合理,科学性,系统性强,融入学科发展新成果,新理论。(5分)',
score: 13,
mark: 0
}]
}, {
title: '师德师风(10分)',
classSettingVOList: [{
content: '1.紧扣教学大纲内容,内容饱满、材料丰富、理论和实践相结合、详略得当。(5分)',
score: 10,
mark: 0
}]
}, {
title: '师德师风(10分)',
classSettingVOList: [{
content: '1.紧扣教学大纲内容,内容饱满、材料丰富、理论和实践相结合、详略得当。(5分)',
score: 10,
mark: 0
}, {
content: '2.教学设计合理,科学性,系统性强,融入学科发展新成果,新理论。(5分)',
score: 10,
mark: 0
}]
}, {
title: '师德师风(10分)',
classSettingVOList: [{
content: '1.紧扣教学大纲内容,内容饱满、材料丰富、理论和实践相结合、详略得当。(5分)',
score: 10,
mark: 0
}]
},
{
title: '师德师风(10分)',
classSettingVOList: [{
content: '1.紧扣教学大纲内容,内容饱满、材料丰富、理论和实践相结合、详略得当。(5分)',
score: 10,
mark: 0
}, {
content: '2.教学设计合理,科学性,系统性强,融入学科发展新成果,新理论。(5分)',
score: 10,
mark: 0
}]
}, {
title: '师德师风(10分)',
classSettingVOList: [{
content: '1.紧扣教学大纲内容,内容饱满、材料丰富、理论和实践相结合、详略得当。(5分)',
score: 10,
mark: 0
}, {
content: '2.教学设计合理,科学性,系统性强,融入学科发展新成果,新理论。(5分)',
score: 10,
mark: 0
}]
}
]
};
},
watch: {},
mounted() {
this.getDetail()
},
computed: {
targetScore() {
let total = this.arr.reduce((pre, cur) => {
return pre + cur.classSettingVOList.reduce((kidPre, kidCur) => {
return kidPre + kidCur.score
}, 0)
}, 0)
return Math.ceil((this.fastScore / 100) * total)
}
},
methods: {
toSubmit(type) {
if (!this.info.advice) return uni.showToast({
icon: 'error',
title: '听课记录不得为空!'
})
let param = {
advice: this.info.advice,
evaluateSettingDTOList: '',
state: type,
id: this.info.id,
lessonId: this.lessonId,
score:0
}
param.score=this.arr.reduce((pre, cur) => {
return pre + cur.classSettingVOList.reduce((kidPre, kidCur) => {
return kidPre + (kidCur.trueScore||0)
}, 0)
}, 0)
param.evaluateSettingDTOList = this.arr.map(item => {
let kids = item?.classSettingVOList?.map(record => {
return {
evalDetailId: record.evalDetailId,
id: record.id,
trueScore: record.trueScore
}
})
return {
evaluateId: item.evaluateId,
insertClassSettingDTOList: kids
}
})
saveClassEvaluate(param).then(res => {
if (res.code == 200) {
uni.showToast({
icon: 'success',
title: '点评成功!'
})
}
})
},
getDetail() {
getEvaluateData({
lessonId: this.lessonId
}).then(res => {
this.info = res.data
this.arr = res?.data?.evaluateSettingDTOList
})
},
toFastMark() {
let total = this.arr.reduce((pre, cur) => {
return pre + cur.classSettingVOList.reduce((kidPre, kidCur) => {
return kidPre + kidCur.score
}, 0)
}, 0)
let temp = JSON.parse(JSON.stringify(this.arr))
let rate = (this.fastScore / 100).toFixed(1)
console.log(this.targetScore, '快捷打分', rate)
temp = temp.map(item => {
let kids = []
kids = item.classSettingVOList.map(val => {
return {
...val,
trueScore: Math.floor(val.score * rate)
}
})
return {
...item,
classSettingVOList: kids
}
})
let tempTotal = temp?.reduce((pre, cur) => {
return pre + cur.classSettingVOList.reduce((kidPre, kidCur) => {
return kidPre + kidCur.trueScore
}, 0)
}, 0)
let distance = this.targetScore - tempTotal
console.log(temp, '第一次数组', distance)
this.arr = JSON.parse(JSON.stringify(this.equal(temp, distance)))
},
equal(arr, dis) {
let step = 1
let tempArr = []
let dis1 = dis
tempArr = arr.map(item => {
let kids = []
item.classSettingVOList.forEach((val, vi) => {
let mark = val.trueScore
if (mark + step <= val.score && dis1 != 0) {
if (dis1 - step < 0) {
step = dis1
}
mark = mark + step
dis1 = dis1 - step
}
console.log(vi, '---', val.trueScore, mark, dis1)
kids.push({
...val,
trueScore: mark
})
})
return {
...item,
classSettingVOList: kids
}
})
let verifyTotal = tempArr?.reduce((pre, cur) => {
return pre + cur.classSettingVOList.reduce((kidPre, kidCur) => {
return kidPre + kidCur.trueScore
}, 0)
}, 0)
console.log(verifyTotal, '补足差值', this.fastScore)
if (verifyTotal == this.targetScore) {
return tempArr
} else {
this.equal(tempArr, this.targetScore - verifyTotal)
}
},
}
}
</script>
<style lang="scss" scoped>
.container_cr {
box-sizing: border-box;
width: 100%;
height: 100%;
position: relative;
.cr_wrapper {
padding: 0 40rpx 154rpx;
}
.btnBox {
box-sizing: border-box;
position: fixed;
bottom: 48rpx;
width: 100%;
background-color: #FAFAFA;
height: 96rpx;
padding: 16rpx 32rpx;
display: flex;
flex-direction: row;
gap: 30rpx;
.defaultBtn {
border: 1px solid #DCDEE0;
background: #FFFFFF;
color: #323233;
}
.primaryBtn {
background: #3070F9;
color: #fff;
}
.defaultBtn,
.primaryBtn {
flex: 1;
display: inline-block;
height: 64rpx;
line-height: 60rpx;
text-align: center;
border-radius: 2px;
}
}
.label {
font-size: 28rpx;
}
.slider {
width: 100%;
margin-bottom: 48rpx;
padding: 0 48rpx;
box-sizing: border-box;
::v-deep .uni-slider-tap-area {
position: relative;
z-index: 1;
&::before {
position: absolute;
content: '70分';
top: 32rpx;
left: -16rpx;
font-size: 28rpx;
}
&::after {
position: absolute;
content: '90分';
top: 28rpx;
right: -16rpx;
font-size: 28rpx;
}
}
::v-deep .uni-slider-handle-wrapper {
position: relative;
z-index: 1;
&::before {
position: absolute;
content: '';
top: -8rpx;
left: -16rpx;
z-index: 2;
width: 12rpx;
height: 12rpx;
border-radius: 50%;
border: 4rpx solid #155BD4;
}
&::after {
position: absolute;
content: '';
top: -8rpx;
right: -16rpx;
z-index: 0;
width: 12rpx;
height: 12rpx;
border-radius: 50%;
border: 4rpx solid #DCDEE0;
}
}
::v-deep uni-slider {
position: relative;
&::before {
position: absolute;
content: '';
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 12rpx;
height: 12rpx;
border-radius: 50%;
background-color: #fff;
}
&::after {
font-size: 28rpx;
position: absolute;
content: '80分';
top: calc(50% + 12rpx);
left: 50%;
transform: translateX(-50%);
white-space: nowrap;
}
}
.score70 {
::v-deep uni-slider::before {
border: 4rpx solid #DCDEE0;
z-index: 2;
}
}
.score80 {
::v-deep uni-slider::before {
border: 4rpx solid #DCDEE0;
z-index: 0;
display: none;
}
}
.score90 {
::v-deep uni-slider::before {
border: 4rpx solid #155BD4;
z-index: 2
}
}
::v-deep uni-slider .uni-slider-thumb {
box-sizing: border-box;
border: 4rpx solid #155BD4;
background-color: #fff;
z-index: 2 !important;
}
}
.cate {
margin-bottom: 40rpx;
line-height: 40rpx;
font-size: 28rpx;
.title {
font-weight: 600;
margin-left: 24rpx;
position: relative;
margin-bottom: 32rpx;
&::before {
position: absolute;
content: '';
width: 12rpx;
height: 12rpx;
border-radius: 50%;
background-color: #3070F9;
left: -20rpx;
top: 50%;
transform: translateY(-50%);
}
}
.indicatorBox {
margin-bottom: 22rpx;
.indicator {
margin-bottom: 12rpx;
}
.markBox {
display: flex;
flex-direction: row;
justify-content: flex-end;
align-items: center;
::v-deep .u-number-box__input {
background-color: #fff !important;
border: 2rpx solid #DCDEE0;
margin: 0;
}
::v-deep .u-number-box__minus {
border: 2rpx solid #DCDEE0;
border-right: none;
}
::v-deep .u-number-box__plus {
border: 2rpx solid #DCDEE0;
border-left: none;
}
}
}
}
}
</style>
/**
*
* @param targetScore 目标分值(快捷打分的总分值) 如:80(整数)
* @param templateScore 各小项的分值 如:[10,20,10...](数组中包含整数)
* @returns {*}
*/
export function flatScore(targetScore, templateScore) {
let totalScore = templateScore.reduce((a, b) => a + b)
let rate = targetScore / totalScore;
let result = templateScore.map((it) => Math.floor(it * rate));
let rest = targetScore - result.reduce((a, b) => a + b);
// console.log('rest', rest)
let [pos, bit] = [0, 1];
while (rest > 0) {
if (result[pos] + bit <= templateScore[pos]) {
result[pos] += bit;
rest -= bit;
}
pos = pos < templateScore.length ? pos + 1 : 0;
}
return result;
}