182 lines
6.1 KiB
Vue
Raw Normal View History

2026-01-20 13:21:50 +08:00
<template>
<!-- 医生满意度评价卡片 -->
<view class="evaluation-card">
<view class="evaluation-content">
<view class="evaluation-icon">
<uni-icons type="star-filled" size="24" color="#0877F1"></uni-icons>
</view>
<view class="evaluation-info">
<text class="evaluation-title">医生满意度评价</text>
<text class="evaluation-subtitle">您对医生的本次服务满意吗</text>
</view>
<view class="evaluation-btn">
<text class="btn-text" @click="openEvaluationPopup">评价</text>
</view>
</view>
</view>
<!-- 评价弹窗 -->
<uni-popup ref="evaluationPopup" type="bottom" :mask-click="false" class="evaluation-popup-wrapper">
<view class="evaluation-popup-container">
<view class="evaluation-popup">
<!-- 顶部指示条 -->
<view class="popup-indicator"></view>
<view class="popup-close" @click="closeEvaluationPopup">
<uni-icons type="closeempty" size="24" color="#999"></uni-icons>
</view>
<view v-if="doctorInfo" class="doctor-info-section">
<image class="doctor-avatar-large" :src="doctorInfo.avatar" mode="aspectFill">
</image>
<text class="doctor-name">{{ doctorInfo.name }}</text>
<text class="doctor-dept">{{ doctorInfo.title }} | {{ doctorInfo.department }}</text>
</view>
<view class="rating-section">
<view class="rate-wrapper">
<uni-rate v-model="evaluationRating" :max="5" :size="32" :margin="8" color="#e0e0e0" active-color="#0877F1"
:disabled="false"></uni-rate>
</view>
<text class="rating-text" :class="{ 'no-rating': evaluationRating === 0 }">{{ ratingText }}</text>
</view>
<view class="comment-section">
<textarea class="evaluation-textarea" v-model="evaluationComment" placeholder="分享您的就诊经历、治疗方式、治疗效果、医生对您的帮助。"
:maxlength="1000" show-confirm-bar="false"></textarea>
<view class="char-count">{{ evaluationComment.length }}/500</view>
</view>
<view class="evaluation-footer">
<button class="submit-evaluation-btn" @click="submitEvaluation">
提交评价
</button>
</view>
</view>
</view>
</uni-popup>
<!-- 评价完成提示弹窗 -->
<uni-popup ref="evaluationSuccessPopup" type="bottom" :mask-click="false" class="evaluation-popup-wrapper">
<view class="success-popup">
<view class="popup-close" @click="closeEvaluationSuccessPopup">
<uni-icons type="closeempty" size="24" color="#999"></uni-icons>
</view>
<view class="success-header-row">
<view class="success-icon">
<uni-icons type="checkmarkempty" size="48" color="#4CAF50"></uni-icons>
</view>
<text class="success-title">评价发布完成</text>
</view>
<view class="success-eval-box">
<view class="success-subtitle">对医生的总评价</view>
<view class="success-rating">
<uni-rate :value="evaluationRating" :max="5" :size="24" :margin="4" color="#0877F1" active-color="#0877F1"
:readonly="true" :touchable="false"></uni-rate>
<text class="success-rating-text">{{ ratingText }}</text>
</view>
<view class="success-comment" v-if="evaluationComment">
<text class="comment-text">{{ evaluationComment }}</text>
</view>
</view>
</view>
</uni-popup>
</template>
<script setup>
import { ref, computed } from 'vue';
import { getRate, submitRate } from '@/api/corp/rate';
import { toast } from '@/utils/widget';
// Props
const props = defineProps({
doctorInfo: {
type: Object,
default: () => ({})
},
extension: {
type: Object,
default: () => ({})
},
});
// Emits
const emit = defineEmits(['evaluationSubmitted', 'popupStatusChange']);
// 评价相关状态
const evaluationPopup = ref(null);
const evaluationSuccessPopup = ref(null);
const evaluationRating = ref(0);
const evaluationComment = ref('');
const record = ref(null)
const loading = ref(false);
// 计算评分文字
const ratingText = computed(() => {
const texts = ['请选择评分', '很不满意', '不满意', '一般', '满意', '非常满意'];
return texts[evaluationRating.value] || '请选择评分';
});
// 打开评价弹窗
const openEvaluationPopup = async () => {
evaluationRating.value = 0
evaluationComment.value = ''
const res = await getRate(props.extension.rateId);
if (res && res.success) {
record.value = res.data;
evaluationRating.value = typeof res.data.rate === 'number' ? res.data.rate : 0;
evaluationComment.value = typeof res.data.words === 'string' ? res.data.words : '';
if (record.value.status === 'init') {
evaluationPopup.value.open();
emit('popupStatusChange', true); // 通知父组件弹窗已打开
} else {
evaluationSuccessPopup.value.open();
emit('popupStatusChange', true); // 通知父组件弹窗已打开
}
} else {
toast('获取评价信息失败,请稍后重试');
}
};
// 关闭评价弹窗
const closeEvaluationPopup = () => {
evaluationPopup.value.close();
emit('popupStatusChange', false); // 通知父组件弹窗已关闭
};
// 关闭评价完成弹窗
const closeEvaluationSuccessPopup = () => {
evaluationSuccessPopup.value.close();
emit('popupStatusChange', false); // 通知父组件弹窗已关闭
};
// 提交评价
const submitEvaluation = async () => {
if (evaluationRating.value === 0) {
uni.showToast({ title: '请先评分', icon: 'none' });
return;
}
if (loading.value) return;
loading.value = true;
const res = await submitRate({
id: props.extension.rateId,
rate: evaluationRating.value,
words: evaluationComment.value
});
if (res && res.success) {
evaluationPopup.value.close();
setTimeout(() => {
evaluationSuccessPopup.value.open();
// 弹窗仍然保持打开状态,不需要额外通知
}, 600);
} else {
// 提交失败,弹窗关闭
emit('popupStatusChange', false);
}
loading.value = false
};
</script>
<style scoped lang="scss">
@import "../../chat.scss";
</style>