2026-01-22 15:13:26 +08:00

182 lines
6.1 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="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>