<template>
  <div class="results-page page-container">
    <h1 class="section-title">面试评估结果</h1>

    <div v-if="loading" class="loading-container">
      <el-skeleton :rows="10" animated />
    </div>

    <div v-else-if="!results" class="no-results card">
      <el-empty description="未找到面试结果" />
      <el-button type="primary" @click="$router.push('/setup')" class="action-button">开始新的面试</el-button>
    </div>

    <div v-else class="results-content">
      <!-- 能力雷达图 -->
      <div class="card radar-section">
        <h2>能力评估</h2>
        <div class="radar-container">
          <canvas ref="radarCanvas" width="400" height="400"></canvas>
        </div>
        <div class="ability-legend">
          <div class="legend-item" v-for="(ability, index) in abilities" :key="index">
            <span class="legend-color" :style="{backgroundColor: ability.color}"></span>
            <span class="legend-label">{{ ability.name }}</span>
            <span class="legend-score">{{ ability.score }}/100</span>
          </div>
        </div>
      </div>

      <!-- 优势与不足 -->
      <div class="card strengths-weaknesses">
        <el-row :gutter="20">
          <el-col :span="12">
            <h2>优势</h2>
            <ul class="strengths-list">
              <li v-for="(strength, index) in results.strengths" :key="index">
                <i class="el-icon-check"></i> {{ strength }}
              </li>
            </ul>
          </el-col>
          <el-col :span="12">
            <h2>需要改进</h2>
            <ul class="improvements-list">
              <li v-for="(improvement, index) in results.improvements" :key="index">
                <i class="el-icon-warning"></i> {{ improvement }}
              </li>
            </ul>
          </el-col>
        </el-row>
      </div>

      <!-- 问题详情 -->
      <div class="card questions-section">
        <h2>问题详情</h2>
        <el-collapse accordion>
          <el-collapse-item
              v-for="(item, index) in results.questionScores"
              :key="index"
              :title="`问题 ${index + 1}: ${item.question}`">
            <div class="question-detail">
              <div class="question-content">
                <h4>你的回答:</h4>
                <p class="answer-text">{{ item.answer }}</p>
                <h4>反馈:</h4>
                <p class="feedback-text">{{ item.feedback }}</p>
              </div>
            </div>
          </el-collapse-item>
        </el-collapse>
      </div>

      <!-- 改进建议 -->
      <div class="card recommendations">
        <h2>改进建议</h2>
        <div class="recommendation-card">
          <p>{{ results.recommendations }}</p>
        </div>
      </div>

      <div class="actions">
        <el-button type="primary" @click="$router.push('/setup')" class="action-button">开始新的面试</el-button>
        <el-button @click="$router.push('/profile')" class="action-button">返回个人中心</el-button>
        <!-- 删除下面这行 -->
        <!-- <el-button type="success" @click="downloadReport" class="action-button">下载报告</el-button> -->
      </div>
    </div>
  </div>
</template>

<script setup>
import { ref, onMounted, nextTick } from 'vue';
import { useRoute, useRouter } from 'vue-router';
import { ElMessage } from 'element-plus';
import { interviewAPI } from '../services/api';

const route = useRoute();
const router = useRouter();
const sessionId = route.params.sessionId;

const results = ref(null);
const loading = ref(true);
const radarCanvas = ref(null);

// 五个能力维度
const abilities = ref([
  { name: '专业知识水平', score: 0, color: '#409EFF' },
  { name: '技能匹配度', score: 0, color: '#67C23A' },
  { name: '语言表达能力', score: 0, color: '#E6A23C' },
  { name: '逻辑思维能力', score: 0, color: '#F56C6C' },
  { name: '创新性', score: 0, color: '#909399' }
]);

onMounted(async () => {
  try {
    const response = await interviewAPI.getInterviewResults(sessionId);
    results.value = response.data;
    
    // 根据现有数据计算五个维度的分数
    calculateAbilityScores();
    
    console.log('计算后的能力数据:', abilities.value);
    
    // 等待DOM更新后绘制雷达图
    await nextTick();
    
    // 延迟一点确保Canvas完全渲染
    setTimeout(() => {
      drawRadarChart();
    }, 100);
    
  } catch (error) {
    console.error('获取面试结果失败:', error);
    ElMessage.error('获取面试结果失败');
  } finally {
    loading.value = false;
  }
});

// 计算五个维度的分数
const calculateAbilityScores = () => {
  if (!results.value) return;
  
  // 基于现有的评分数据计算各维度分数
  // 这里可以根据实际的评估逻辑进行调整
  abilities.value[0].score = Math.round(results.value.contentScore || 75); // 专业知识水平
  abilities.value[1].score = 0; // 技能匹配度 - 修改为0分
  abilities.value[2].score = 20; // 语言表达能力 - 修改为20分
  abilities.value[3].score = Math.round(results.value.contentScore * 0.8 || 72); // 逻辑思维能力
  abilities.value[4].score = Math.round(results.value.overallScore * 0.7 || 68); // 创新性
};

// 绘制雷达图
// 绘制雷达图
const drawRadarChart = () => {
  const canvas = radarCanvas.value;
  if (!canvas) {
    console.log('Canvas元素未找到');
    return;
  }
  
  const ctx = canvas.getContext('2d');
  if (!ctx) {
    console.log('无法获取Canvas上下文');
    return;
  }
  
  // 设置Canvas实际尺寸
  const dpr = window.devicePixelRatio || 1;
  const rect = canvas.getBoundingClientRect();
  canvas.width = rect.width * dpr;
  canvas.height = rect.height * dpr;
  ctx.scale(dpr, dpr);
  
  const centerX = rect.width / 2;
  const centerY = rect.height / 2;
  const radius = Math.min(rect.width, rect.height) / 2 - 60; // 留出标签空间
  const levels = 5;
  
  console.log('开始绘制雷达图', { centerX, centerY, radius, abilities: abilities.value });
  
  // 清空画布
  ctx.clearRect(0, 0, canvas.width, canvas.height);
  
  // 绘制背景网格 - 正五边形
  ctx.strokeStyle = '#e0e0e0';
  ctx.lineWidth = 1;
  
  const angleStep = (2 * Math.PI) / 5; // 固定为5边形
  
  // 绘制同心正五边形
  for (let level = 1; level <= levels; level++) {
    ctx.beginPath();
    const levelRadius = (radius / levels) * level;
    
    for (let i = 0; i < 5; i++) {
      const angle = i * angleStep - Math.PI / 2; // 从顶部开始
      const x = centerX + Math.cos(angle) * levelRadius;
      const y = centerY + Math.sin(angle) * levelRadius;
      
      if (i === 0) {
        ctx.moveTo(x, y);
      } else {
        ctx.lineTo(x, y);
      }
    }
    ctx.closePath();
    ctx.stroke();
  }
  
  // 绘制轴线和标签
  ctx.strokeStyle = '#e0e0e0';
  for (let i = 0; i < 5; i++) {
    const angle = i * angleStep - Math.PI / 2;
    const x = centerX + Math.cos(angle) * radius;
    const y = centerY + Math.sin(angle) * radius;
    
    // 绘制轴线
    ctx.beginPath();
    ctx.moveTo(centerX, centerY);
    ctx.lineTo(x, y);
    ctx.stroke();
    
    // 绘制标签
    ctx.fillStyle = '#333';
    ctx.font = '12px Arial';
    ctx.textAlign = 'center';
    ctx.textBaseline = 'middle';
    
    const labelDistance = radius + 30;
    const labelX = centerX + Math.cos(angle) * labelDistance;
    const labelY = centerY + Math.sin(angle) * labelDistance;
    
    const abilityName = abilities.value[i]?.name || `维度${i+1}`;
    ctx.fillText(abilityName, labelX, labelY);
  }
  
  // 绘制数据多边形
  if (abilities.value && abilities.value.length >= 5) {
    // 先绘制数据点
    const dataPoints = [];
    for (let i = 0; i < 5; i++) {
      const angle = i * angleStep - Math.PI / 2;
      const score = abilities.value[i]?.score || 0;
      const distance = (score / 100) * radius;
      const x = centerX + Math.cos(angle) * distance;
      const y = centerY + Math.sin(angle) * distance;
      dataPoints.push({ x, y });
      
      // 绘制数据点
      ctx.save();
      ctx.fillStyle = abilities.value[i]?.color || '#409EFF';
      ctx.beginPath();
      ctx.arc(x, y, 5, 0, 2 * Math.PI); // 稍微增大数据点
      ctx.fill();
      ctx.strokeStyle = '#fff';
      ctx.lineWidth = 2;
      ctx.stroke(); // 给数据点加白色边框
      ctx.restore();
    }
    
    // 绘制连接线形成的多边形 - 使用不同颜色
    ctx.beginPath();
    ctx.fillStyle = 'rgba(255, 99, 132, 0.15)'; // 粉红色半透明填充
    ctx.strokeStyle = '#FF6384'; // 粉红色边框
    ctx.lineWidth = 3; // 加粗连接线
    
    // 连接所有数据点
    for (let i = 0; i < dataPoints.length; i++) {
      if (i === 0) {
        ctx.moveTo(dataPoints[i].x, dataPoints[i].y);
      } else {
        ctx.lineTo(dataPoints[i].x, dataPoints[i].y);
      }
    }
    
    ctx.closePath();
    ctx.fill(); // 填充多边形
    ctx.stroke(); // 绘制边框
    
    // 可选:添加渐变效果
    const gradient = ctx.createRadialGradient(centerX, centerY, 0, centerX, centerY, radius);
    gradient.addColorStop(0, 'rgba(255, 99, 132, 0.3)');
    gradient.addColorStop(1, 'rgba(255, 99, 132, 0.05)');
    
    ctx.beginPath();
    for (let i = 0; i < dataPoints.length; i++) {
      if (i === 0) {
        ctx.moveTo(dataPoints[i].x, dataPoints[i].y);
      } else {
        ctx.lineTo(dataPoints[i].x, dataPoints[i].y);
      }
    }
    ctx.closePath();
    ctx.fillStyle = gradient;
    ctx.fill();
  }
  
  console.log('雷达图绘制完成');
};

// 删除下面的函数
// const downloadReport = () => {
//   ElMessage.success('报告下载功能将在后续版本中提供');
// };
</script>

<style scoped>
.results-page {
  max-width: 1000px;
  margin: 0 auto;
  padding: 20px;
}

.loading-container {
  padding: 30px;
  background: white;
  border-radius: 8px;
  box-shadow: var(--card-shadow);
}

.radar-section {
  margin-bottom: 30px;
  text-align: center;
}

.radar-container {
  display: flex;
  justify-content: center;
  margin: 20px 0;
}

.ability-legend {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 20px;
  margin-top: 20px;
}

.legend-item {
  display: flex;
  align-items: center;
  gap: 8px;
}

.legend-color {
  width: 12px;
  height: 12px;
  border-radius: 50%;
}

.legend-label {
  font-size: 14px;
  color: #333;
}

.legend-score {
  font-size: 14px;
  font-weight: bold;
  color: #666;
}

.strengths-weaknesses, .questions-section, .recommendations {
  margin-bottom: 30px;
}

.strengths-list li, .improvements-list li {
  margin-bottom: 10px;
  padding: 8px;
  border-radius: 4px;
}

.strengths-list li {
  background-color: rgba(103, 194, 58, 0.1);
  color: #67C23A;
}

.improvements-list li {
  background-color: rgba(230, 162, 60, 0.1);
  color: #E6A23C;
}

.question-detail {
  display: flex;
  gap: 20px;
}

.question-content {
  flex: 1;
}

.answer-text, .feedback-text {
  background-color: #f5f7fa;
  padding: 10px;
  border-radius: 4px;
  margin-bottom: 15px;
  white-space: pre-wrap;
}

.recommendation-card {
  background-color: #f5f7fa;
  border-radius: 8px;
  padding: 20px;
  line-height: 1.8;
  white-space: pre-wrap;
}

.actions {
  margin-top: 30px;
  display: flex;
  gap: 15px;
  justify-content: center;
}

.action-button {
  min-width: 120px;
}

.no-results {
  padding: 40px;
  text-align: center;
}
</style>
posted on 2025-05-21 20:45  leapss  阅读(6)  评论(0)    收藏  举报