uniapp评价组件
组件目录 components/Evaluation.vue
<template><view class="evaluation-container"><!-- 综合评价 --><view class="evaluation-item" @tap="parentTap"><text class="label label-1">综合评价</text><view class="rating-icons"><imagev-for="(icon, index) in ratingIcons":key="index":class="['rating-icon', { active: icon.active }]":src="icon.active ? icon.selectedSrcDynamic : icon.unselectedSrc"@tap.stop="setRating(index)"/></view><text class="comment-text">{{ getCommentText(ratingIcons.filter(i => i.active).length) }}</text></view><!-- 描述相符 --><view class="evaluation-item" @tap="parentTap"><text class="label">描述相符</text><view class="heart-icons"><imagev-for="(heart, index) in descriptionHearts":key="index":class="['heart-icon', { active: heart.active }]":src="heart.active ? '/static/evaluate/heart-filled.png' : '/static/evaluate/heart-empty.png'"@tap.stop="setHeart(index, 'description')"/></view><text class="comment-text">{{ getCommentText(descriptionHearts.filter(i => i.active).length) }}</text></view><!-- 物流服务 --><view class="evaluation-item" @tap="parentTap"><text class="label">物流服务</text><view class="heart-icons"><imagev-for="(heart, index) in logisticsHearts":key="index":class="['heart-icon', { active: heart.active }]":src="heart.active ? '/static/evaluate/heart-filled.png' : '/static/evaluate/heart-empty.png'"@tap.stop="setHeart(index, 'logistics')"/></view><text class="comment-text">{{ getCommentText(logisticsHearts.filter(i => i.active).length) }}</text></view><!-- 服务态度 --><view class="evaluation-item" @tap="parentTap"><text class="label">服务态度</text><view class="heart-icons"><imagev-for="(heart, index) in serviceHearts":key="index":class="['heart-icon', { active: heart.active }]":src="heart.active ? '/static/evaluate/heart-filled.png' : '/static/evaluate/heart-empty.png'"@tap.stop="setHeart(index, 'service')"/></view><text class="comment-text">{{ getCommentText(serviceHearts.filter(i => i.active).length) }}</text></view></view>
</template><script>
export default {name: 'Evaluation',props: {defaultValues: {type: Object,default: () => ({})},readonly: {type: Boolean,default: false}},data() {return {ratingIcons: [{unselectedSrc: '/static/evaluate/face-very-bad-unselected.png',selectedSrc: '/static/evaluate/face-very-bad.png',selectedSrcDynamic: null,active: false},{unselectedSrc: '/static/evaluate/face-bad-unselected.png',selectedSrc: '/static/evaluate/face-bad.png',selectedSrcDynamic: null,active: false},{unselectedSrc: '/static/evaluate/face-neutral-unselected.png',selectedSrc: '/static/evaluate/face-neutral.png',selectedSrcDynamic: null,active: false},{unselectedSrc: '/static/evaluate/face-good-unselected.png',selectedSrc: '/static/evaluate/face-good.png',selectedSrcDynamic: null,active: false},{unselectedSrc: '/static/evaluate/face-very-good-unselected.png',selectedSrc: '/static/evaluate/face-very-good.png',selectedSrcDynamic: null,active: false}],descriptionHearts: Array(5).fill({ active: false }).map(h => ({ ...h })),logisticsHearts: Array(5).fill({ active: false }).map(h => ({ ...h })),serviceHearts: Array(5).fill({ active: false }).map(h => ({ ...h })),commentTexts: ['很差', '不满意', '一般', '满意', '超赞']};},mounted() {this.initEvaluation(this.defaultValues);},methods: {parentTap() {},setRating(index) {if (this.readonly) return;const selectedSrc = this.ratingIcons[index].selectedSrc;this.ratingIcons.forEach((icon, i) => {icon.active = i <= index;icon.selectedSrcDynamic = i <= index ? selectedSrc : null;});},setHeart(index, type) {if (this.readonly) return;const hearts = this[type + 'Hearts'];hearts.forEach((heart, i) => {heart.active = i <= index;});},getResult() {return {overall: this.ratingIcons.filter(i => i.active).length,description: this.descriptionHearts.filter(i => i.active).length,logistics: this.logisticsHearts.filter(i => i.active).length,service: this.serviceHearts.filter(i => i.active).length};},initEvaluation({ overall = 0, description = 0, logistics = 0, service = 0 }) {const selectedSrc = this.ratingIcons[overall - 1]?.selectedSrc || null;this.ratingIcons.forEach((icon, i) => {icon.active = i < overall;icon.selectedSrcDynamic = i < overall ? selectedSrc : null;});const setHearts = (arr, score) => {arr.forEach((item, i) => {item.active = i < score;});};setHearts(this.descriptionHearts, description);setHearts(this.logisticsHearts, logistics);setHearts(this.serviceHearts, service);},getCommentText(count) {if (count === 0) return '';return this.commentTexts[count - 1];}}
};
</script><style scoped>
.evaluation-container {/* padding: 20px; */
}
.evaluation-item {display: flex;align-items: center;margin-bottom: 28rpx;
}
.label{font-size: 28rpx;color: #2D2D2D;
}
.label-1{color: #0F1724;font-weight: 600;
}.rating-icons,
.heart-icons {display: flex;/* gap: 10px; */
}
.rating-icon,
.heart-icon {width: 60rpx;height: 60rpx;margin-left: 30rpx;
}/* 动画效果 */
@keyframes bounce {0% {transform: scale(1);}40% {transform: scale(1.3);}100% {transform: scale(1);}
}.rating-icon.active,
.heart-icon.active {animation: bounce 0.3s ease;
}/* 文案样式 */
.comment-text {margin-left: 24rpx;font-weight: 600;font-size: 28rpx;color: #0F1724;white-space: nowrap;
}
</style>
页面使用
<template><view><Evaluationref="evaluation":default-values="{ overall: 0, description: 0, logistics: 0, service: 0 }":readonly="false"/><button @tap="submit">提交</button></view>
</template><script>
import Evaluation from '@/components/Evaluation.vue';export default {components: { Evaluation },methods: {submit() {const result = this.$refs.evaluation.getResult();console.log('提交评分结果', result);}}
};
</script>
readonly是否允许点击一般详情页可以传true不让点击