| | |
| | | <div class="project-section"> |
| | | <!-- 项目基本信息 --> |
| | | <h4>项目信息</h4> |
| | | <el-descriptions :column="2" border> |
| | | <el-descriptions-item label="项目名称"> |
| | | {{ projectDetail.projectName || '未填写' }} |
| | | <el-descriptions :column="2" border class="project-info"> |
| | | <el-descriptions-item label="比赛名称" :span="2"> |
| | | {{ competitionName || '未填写' }} |
| | | </el-descriptions-item> |
| | | <el-descriptions-item label="比赛名称"> |
| | | {{ projectDetail.activityName }} |
| | | <el-descriptions-item label="比赛阶段" :span="2"> |
| | | {{ stageName || projectDetail.activityName || '未填写' }} |
| | | </el-descriptions-item> |
| | | <el-descriptions-item label="参赛项目名称" :span="2"> |
| | | {{ projectDetail.projectName || '未填写' }} |
| | | </el-descriptions-item> |
| | | <el-descriptions-item label="项目描述" :span="2"> |
| | | <div class="description-content"> |
| | |
| | | import { useRoute, useRouter } from 'vue-router' |
| | | import { ElMessage, ElMessageBox } from 'element-plus' |
| | | import { Document, UserFilled } from '@element-plus/icons-vue' |
| | | import { getProjectDetail, getRatingStats, submitRating, getCurrentJudgeRating } from '@/api/projectReview' |
| | | import { getProjectDetail, getRatingStats, submitRating, getCurrentJudgeRating, getActiveActivities } from '@/api/projectReview' |
| | | import { userApi } from '@/api/user' |
| | | import { getUserInfo } from '@/utils/auth' |
| | | |
| | |
| | | const submitting = ref(false) |
| | | const projectDetail = ref(null) |
| | | const ratingStats = ref({ ratingCount: 0, averageScore: 0 }) |
| | | const competitionName = ref('') |
| | | const stageName = ref('') |
| | | const ratingItems = ref([]) |
| | | const ratingComment = ref('') |
| | | const previewVisible = ref(false) |
| | |
| | | |
| | | // 计算属性 |
| | | const projectId = computed(() => route.params.id) |
| | | const stageId = computed(() => route.query.stageId) |
| | | const stageId = computed(() => route.query.stageId || (projectDetail.value ? projectDetail.value.stageId : null)) |
| | | |
| | | const loadStageMeta = async () => { |
| | | try { |
| | | if (!projectDetail.value || !projectDetail.value.stageId) return |
| | | const stages = await getActiveActivities() |
| | | const stage = (stages || []).find(s => String(s.id) === String(projectDetail.value.stageId)) |
| | | if (stage) { |
| | | stageName.value = stage.name || '' |
| | | competitionName.value = stage.parent?.name || '' |
| | | } else { |
| | | stageName.value = projectDetail.value.activityName || '' |
| | | competitionName.value = '' |
| | | } |
| | | } catch (e) { |
| | | stageName.value = projectDetail.value?.activityName || '' |
| | | competitionName.value = '' |
| | | } |
| | | } |
| | | |
| | | // 权限验证方法 |
| | | const checkPermissions = async () => { |
| | |
| | | try { |
| | | const data = await getProjectDetail(projectId.value) |
| | | projectDetail.value = data |
| | | await loadStageMeta() |
| | | |
| | | // 初始化评分项 |
| | | if (data.ratingForm && data.ratingForm.items) { |
| | |
| | | return |
| | | } |
| | | |
| | | // 验证stageId |
| | | if (!stageId.value) { |
| | | // 统一获取stageId(优先路由参数,其次详情里的stageId) |
| | | const sid = stageId.value ? parseInt(stageId.value) : (projectDetail.value?.stageId ? parseInt(projectDetail.value.stageId) : null) |
| | | if (!sid) { |
| | | ElMessage.error('缺少比赛阶段信息,请重新进入页面') |
| | | return |
| | | } |
| | | |
| | | |
| | | // 验证评分 |
| | | const hasEmptyScore = ratingItems.value.some(item => item.score === 0 || item.score === null) |
| | | if (hasEmptyScore) { |
| | |
| | | |
| | | const ratingData = { |
| | | activityPlayerId: parseInt(projectId.value), |
| | | stageId: parseInt(stageId.value), |
| | | stageId: sid, |
| | | ratings: ratingItems.value.map(item => ({ |
| | | itemId: item.id, |
| | | score: item.score |
| | |
| | | .description-content { |
| | | line-height: 1.6; |
| | | color: #606266; |
| | | white-space: pre-wrap; |
| | | } |
| | | |
| | | .attachments { |
| | |
| | | :deep(.el-card__body) { |
| | | padding: 16px; |
| | | } |
| | | |
| | | /* 仅针对项目信息这组描述设置标签/内容宽度比例 */ |
| | | .project-info :deep(.el-descriptions__label) { |
| | | width: 40% !important; |
| | | min-width: 40%; |
| | | box-sizing: border-box; |
| | | } |
| | | .project-info :deep(.el-descriptions__content) { |
| | | width: 60% !important; |
| | | min-width: 60%; |
| | | box-sizing: border-box; |
| | | } |
| | | |
| | | /* 窄屏自适应:小屏时回退为上下结构 */ |
| | | @media (max-width: 768px) { |
| | | .project-info :deep(.el-descriptions__label), |
| | | .project-info :deep(.el-descriptions__content) { |
| | | width: 100% !important; |
| | | min-width: 100%; |
| | | } |
| | | } |
| | | </style> |