Files
hzdyjs/web/src/views/stgl/activity/components/ActivityRatingView.vue
T
2025-09-01 16:30:58 +08:00

286 lines
8.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>
<div class="activity-rating-view">
<div v-if="ratings.length === 0" class="empty-state">
<el-empty description="暂无评分信息" :image-size="80" />
</div>
<div v-else>
<!-- 移除统计信息部分 -->
<el-table :data="ratings" height="600" border stripe>
<!-- 基本信息 - 减少宽度 -->
<el-table-column label="评分人信息" width="160" fixed="left">
<template #default="scope">
<div class="user-info-compact">
<div class="user-name">{{ scope.row.userName || '未知用户' }}</div>
<div class="user-detail" v-if="scope.row.studentNo">{{ scope.row.studentNo }}</div>
<div class="user-detail" v-if="scope.row.phoneNumber">{{ scope.row.phoneNumber }}</div>
</div>
</template>
</el-table-column>
<!-- 所属信息 - 减少宽度 -->
<el-table-column label="所属信息" width="140">
<template #default="scope">
<div class="dept-info-compact">
<div class="dept-detail" v-if="scope.row.deptName">{{ scope.row.deptName }}</div>
<div class="dept-detail" v-if="scope.row.majorName">{{ scope.row.majorName }}</div>
</div>
</template>
</el-table-column>
<!-- 总评分 - 减少宽度 -->
<el-table-column label="总评分" width="100" align="center">
<template #default="scope">
<div class="rating-display-compact">
<el-rate :model-value="scope.row.ratingScore" disabled size="small" />
<div class="rating-number">{{ scope.row.ratingScore }}</div>
</div>
</template>
</el-table-column>
<!-- 各项分数 - 减少宽度 -->
<el-table-column label="内容" width="70" align="center">
<template #default="scope">
<div v-if="scope.row.contentScore" class="score-badge-small">
{{ scope.row.contentScore }}
</div>
<span v-else class="no-score">-</span>
</template>
</el-table-column>
<el-table-column label="组织" width="70" align="center">
<template #default="scope">
<div v-if="scope.row.organizationScore" class="score-badge-small">
{{ scope.row.organizationScore }}
</div>
<span v-else class="no-score">-</span>
</template>
</el-table-column>
<el-table-column label="体验" width="70" align="center">
<template #default="scope">
<div v-if="scope.row.experienceScore" class="score-badge-small">
{{ scope.row.experienceScore }}
</div>
<span v-else class="no-score">-</span>
</template>
</el-table-column>
<!-- 评分备注 - 扩大宽度,取消tooltip,直接显示完整内容 -->
<el-table-column label="评分备注" min-width="300">
<template #default="scope">
<div class="rating-comment-full">
{{ scope.row.ratingComment || '无备注' }}
</div>
</template>
</el-table-column>
<!-- 评分时间 - 简化显示格式,减少宽度 -->
<el-table-column label="评分时间" width="120" align="center" fixed="right">
<template #default="scope">
<div class="rating-time-compact">
{{ formatDateTimeCompact(scope.row.ratingTime) }}
</div>
</template>
</el-table-column>
</el-table>
</div>
</div>
</template>
<script setup lang="ts">
import { ref, computed, onMounted, watch } from 'vue';
import { getActivityRatings } from '@/api/stgl/activity';
import { ActivityRatingVO } from '@/api/stgl/activity/types';
interface Props {
activityId: string | number;
}
const props = defineProps<Props>();
const ratings = ref<ActivityRatingVO[]>([]);
const loading = ref(false);
// 修复平均评分计算 - 确保数值类型正确转换
const averageRating = computed(() => {
if (ratings.value.length === 0) return 0;
const sum = ratings.value.reduce((total, rating) => {
// 确保评分是数字类型
const score = typeof rating.ratingScore === 'string' ? parseFloat(rating.ratingScore) : rating.ratingScore;
return total + (isNaN(score) ? 0 : score);
}, 0);
return Math.round((sum / ratings.value.length) * 10) / 10; // 保留一位小数
});
// 计算最高评分
const maxRating = computed(() => {
if (ratings.value.length === 0) return 0;
return Math.max(...ratings.value.map((rating) => {
const score = typeof rating.ratingScore === 'string' ? parseFloat(rating.ratingScore) : rating.ratingScore;
return isNaN(score) ? 0 : score;
}));
});
// 计算最低评分
const minRating = computed(() => {
if (ratings.value.length === 0) return 0;
return Math.min(...ratings.value.map((rating) => {
const score = typeof rating.ratingScore === 'string' ? parseFloat(rating.ratingScore) : rating.ratingScore;
return isNaN(score) ? 0 : score;
}));
});
// 简化的日期时间格式化
const formatDateTimeCompact = (dateStr?: string): string => {
if (!dateStr) return '';
const date = new Date(dateStr);
return date.toLocaleString('zh-CN', {
month: '2-digit',
day: '2-digit',
hour: '2-digit',
minute: '2-digit'
});
};
// 加载评分数据
const loadRatings = async () => {
if (!props.activityId) {
ratings.value = [];
return;
}
loading.value = true;
try {
console.log('开始加载活动评分数据,活动ID:', props.activityId);
const res = await getActivityRatings(props.activityId);
ratings.value = res.data || [];
console.log('成功加载评分数据,活动ID:', props.activityId, '评分数量:', ratings.value.length);
} catch (error: any) {
// 如果是404错误,说明后端暂未实现该功能,静默处理
if (error.response?.status === 404) {
console.log('活动评分功能暂未实现,活动ID:', props.activityId);
} else {
console.error('加载评分数据失败,活动ID:', props.activityId, '错误:', error);
}
ratings.value = [];
} finally {
loading.value = false;
}
};
// 监听 activityId 变化,自动重新加载评分数据
watch(() => props.activityId, (newId, oldId) => {
console.log('活动ID发生变化:', oldId, '->', newId);
if (newId && newId !== oldId) {
loadRatings();
}
}, { immediate: true }); // immediate: true 确保组件挂载时也会执行一次
// 移除 onMounted,因为 watch 的 immediate: true 已经覆盖了这个功能
</script>
<style scoped>
.activity-rating-view {
padding: 16px;
}
.empty-state {
text-align: center;
padding: 60px 20px;
}
/* 紧凑的评分人信息样式 */
.user-info-compact {
padding: 4px 2px;
line-height: 1.3;
}
.user-name {
font-weight: 600;
color: #303133;
font-size: 13px;
margin-bottom: 2px;
}
.user-detail {
font-size: 11px;
color: #606266;
line-height: 1.2;
}
/* 紧凑的所属信息样式 */
.dept-info-compact {
padding: 4px 2px;
line-height: 1.3;
}
.dept-detail {
font-size: 11px;
color: #606266;
line-height: 1.2;
}
/* 紧凑的评分显示样式 */
.rating-display-compact {
display: flex;
flex-direction: column;
align-items: center;
gap: 2px;
}
.rating-number {
font-size: 11px;
color: #606266;
font-weight: 500;
}
/* 小号分数徽章样式 */
.score-badge-small {
display: inline-flex;
align-items: center;
justify-content: center;
width: 24px;
height: 24px;
background: linear-gradient(135deg, #409eff 0%, #67c23a 100%);
color: white;
border-radius: 50%;
font-size: 11px;
font-weight: 600;
}
.no-score {
color: #c0c4cc;
font-size: 11px;
}
/* 完整评分备注样式 */
.rating-comment-full {
padding: 8px 12px;
font-size: 13px;
line-height: 1.5;
color: #303133;
word-wrap: break-word;
word-break: break-all;
white-space: pre-wrap;
max-height: none;
}
/* 紧凑的时间显示样式 */
.rating-time-compact {
font-size: 11px;
color: #606266;
line-height: 1.3;
}
/* 表格行高优化 */
:deep(.el-table .el-table__row) {
height: auto !important;
}
:deep(.el-table .el-table__cell) {
padding: 8px 0 !important;
}
</style>