Files
Yi.Admin/Yi.Ai.Vue3/src/pages/ranking/index.vue
2026-02-01 19:32:46 +08:00

1323 lines
32 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.
<script setup lang="ts">
import { Trophy, User, Cpu, CirclePlus, CircleCheck } from '@element-plus/icons-vue';
import { ref, computed, onMounted } from 'vue';
import { ElMessage } from 'element-plus';
import { getRankingList } from '@/api/ranking';
import { RankingTypeEnum, type RankingItemDto } from '@/api/ranking/types';
// 加载状态
const loading = ref(false);
// 模型排行数据
const modelRankingList = ref<RankingItemDto[]>([]);
// 工具排行数据
const toolRankingList = ref<RankingItemDto[]>([]);
// 获取排行榜数据
async function fetchRankingData() {
loading.value = true;
try {
const [modelRes, toolRes] = await Promise.all([
getRankingList({ type: RankingTypeEnum.Model }),
getRankingList({ type: RankingTypeEnum.Tool }),
]);
if (modelRes.code === 200) {
modelRankingList.value = modelRes.data;
}
if (toolRes.code === 200) {
toolRankingList.value = toolRes.data;
}
}
catch (error) {
console.error('获取排行榜数据失败:', error);
ElMessage.error('获取排行榜数据失败');
}
finally {
loading.value = false;
}
}
// 获取排名样式
function getRankClass(rank: number) {
if (rank === 1) return 'rank-1';
if (rank === 2) return 'rank-2';
if (rank === 3) return 'rank-3';
return 'rank-normal';
}
// 更新时间
const updateTime = computed(() => {
const now = new Date();
return now.toLocaleString('zh-CN', {
year: 'numeric',
month: '2-digit',
day: '2-digit',
hour: '2-digit',
minute: '2-digit',
});
});
// AI编程能力计算器弹窗
const calculatorVisible = ref(false);
const calcStep = ref<1 | 2 | 3>(1);
const selectedModel = ref<RankingItemDto | null>(null);
const selectedTool = ref<RankingItemDto | null>(null);
// 计算AI编程能力分数
const calculatedScore = computed(() => {
if (!selectedModel.value || !selectedTool.value) return null;
const score = selectedModel.value.score * 0.65 + selectedTool.value.score * 0.35;
return score.toFixed(1);
});
// 根据得分获取描述
const scoreDescription = computed(() => {
const score = parseFloat(calculatedScore.value || '0');
if (score === 100) return '天才大脑';
if (score >= 95) return '博士大脑';
if (score >= 90) return '程序员大脑';
if (score >= 80) return '实习生大脑';
if (score >= 70) return '猴脑';
if (score >= 60) return '猪脑';
return '傻逼';
});
// 打开计算器
function openCalculator() {
calculatorVisible.value = true;
calcStep.value = 1;
selectedModel.value = null;
selectedTool.value = null;
}
// 关闭计算器
function closeCalculator() {
calculatorVisible.value = false;
}
// 选择模型
function selectModel(model: RankingItemDto) {
selectedModel.value = model;
if (calcStep.value === 1) {
calcStep.value = 2;
}
}
// 选择工具
function selectTool(tool: RankingItemDto) {
selectedTool.value = tool;
if (calcStep.value === 2) {
calcStep.value = 3;
}
}
// 重新开始
function restartCalculator() {
calcStep.value = 1;
selectedModel.value = null;
selectedTool.value = null;
}
// 页面加载时获取数据
onMounted(() => {
fetchRankingData();
});
</script>
<template>
<div class="ranking-container">
<!-- 页面标题 -->
<div class="ranking-header content-wrapper">
<div class="header-content">
<div class="title-section">
<div class="title-icon">
<el-icon size="40"><Trophy /></el-icon>
</div>
<div class="title-text">
<h1 class="main-title">意心Ai全球大模型实时排行榜编程</h1>
<p class="subtitle">基于综合性能用户活跃度代码质量等多维度评估</p>
</div>
</div>
<el-button type="primary" class="calculator-btn" @click="openCalculator">
<el-icon><CirclePlus /></el-icon>
点击测测当前你的Ai编程能力
</el-button>
</div>
</div>
<!-- 主内容区 -->
<div class="ranking-content content-wrapper">
<!-- 左侧模型排行 -->
<div class="ranking-section">
<div class="section-header">
<div class="section-title">
<el-icon size="24"><Cpu /></el-icon>
<span>模型排行编程</span>
</div>
<el-tag type="primary" effect="plain">Top {{ modelRankingList.length }}</el-tag>
</div>
<!-- 加载状态 -->
<div v-if="loading" class="loading-wrapper">
<el-skeleton :rows="8" animated />
</div>
<!-- 排行列表 -->
<div v-else class="ranking-list">
<div
v-for="(item, index) in modelRankingList"
:key="item.id"
class="ranking-item"
:class="getRankClass(index + 1)"
>
<div class="rank-number">
<span v-if="index + 1 <= 3" class="rank-medal">
<el-icon size="20"><Trophy /></el-icon>
</span>
<span v-else>{{ index + 1 }}</span>
</div>
<div class="rank-logo">
<el-image
v-if="item.logoUrl"
:src="item.logoUrl"
:alt="item.name"
class="logo-image"
fit="cover"
/>
<div v-else class="logo-placeholder">
<el-icon><Cpu /></el-icon>
</div>
</div>
<div class="rank-middle">
<div class="rank-info">
<div class="rank-name">{{ item.name }}</div>
<div class="rank-meta">
<span class="provider">{{ item.provider }}</span>
<span v-if="item.description" class="divider">|</span>
<span class="description">{{ item.description }}</span>
</div>
</div>
<div class="rank-progress">
<div class="progress-bar">
<div
class="progress-fill"
:style="{ width: `${item.score}%` }"
/>
</div>
<div class="progress-score">
<span class="score-value">{{ item.score }}</span>
<span class="score-label"></span>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- 右侧工具排行 -->
<div class="ranking-section">
<div class="section-header">
<div class="section-title">
<el-icon size="24"><User /></el-icon>
<span>工具排行编程</span>
</div>
<el-tag type="success" effect="plain">Top {{ toolRankingList.length }}</el-tag>
</div>
<!-- 加载状态 -->
<div v-if="loading" class="loading-wrapper">
<el-skeleton :rows="8" animated />
</div>
<!-- 排行列表 -->
<div v-else class="ranking-list">
<div
v-for="(item, index) in toolRankingList"
:key="item.id"
class="ranking-item"
:class="getRankClass(index + 1)"
>
<div class="rank-number">
<span v-if="index + 1 <= 3" class="rank-medal">
<el-icon size="20"><Trophy /></el-icon>
</span>
<span v-else>{{ index + 1 }}</span>
</div>
<div class="rank-logo">
<el-image
v-if="item.logoUrl"
:src="item.logoUrl"
:alt="item.name"
class="logo-image"
fit="cover"
/>
<div v-else class="logo-placeholder">
<el-icon><User /></el-icon>
</div>
</div>
<div class="rank-middle">
<div class="rank-info">
<div class="rank-name">{{ item.name }}</div>
<div class="rank-meta">
<span class="provider">{{ item.provider }}</span>
<span v-if="item.description" class="divider">|</span>
<span class="description">{{ item.description }}</span>
</div>
</div>
<div class="rank-progress">
<div class="progress-bar">
<div
class="progress-fill"
:style="{ width: `${item.score}%` }"
/>
</div>
<div class="progress-score">
<span class="score-value">{{ item.score }}</span>
<span class="score-label"></span>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- AI编程能力计算器弹窗 -->
<el-dialog
v-model="calculatorVisible"
title="AI编程能力计算器"
width="800px"
:close-on-click-modal="false"
class="calculator-dialog"
>
<!-- 步骤1选择模型 -->
<div v-if="calcStep === 1" class="calc-step">
<div class="step-header">
<div class="step-number">1</div>
<div class="step-title">请选择你正在使用的大模型</div>
</div>
<div class="step-list">
<div
v-for="(item, index) in modelRankingList"
:key="item.id"
class="step-item"
:class="{ active: selectedModel?.id === item.id }"
@click="selectModel(item)"
>
<div class="step-item-rank" :class="getRankClass(index + 1)">{{ index + 1 }}</div>
<div class="step-item-logo">
<el-image
v-if="item.logoUrl"
:src="item.logoUrl"
:alt="item.name"
class="logo-image"
fit="cover"
/>
<div v-else class="logo-placeholder">
<el-icon><Cpu /></el-icon>
</div>
</div>
<div class="step-item-info">
<div class="step-item-name">{{ item.name }}</div>
<div class="step-item-meta">
<span class="provider">{{ item.provider }}</span>
<span v-if="item.description" class="divider">|</span>
<span class="desc">{{ item.description }}</span>
</div>
</div>
<div class="step-item-score">{{ item.score }}</div>
</div>
</div>
</div>
<!-- 步骤2选择工具 -->
<div v-if="calcStep === 2" class="calc-step">
<div class="step-header">
<div class="step-number">2</div>
<div class="step-title">请选择你正在使用的编程工具</div>
<div v-if="selectedModel" class="step-selected">
已选模型<span>{{ selectedModel.name }}</span>
</div>
</div>
<div class="step-list">
<div
v-for="(item, index) in toolRankingList"
:key="item.id"
class="step-item"
:class="{ active: selectedTool?.id === item.id }"
@click="selectTool(item)"
>
<div class="step-item-rank" :class="getRankClass(index + 1)">{{ index + 1 }}</div>
<div class="step-item-logo">
<el-image
v-if="item.logoUrl"
:src="item.logoUrl"
:alt="item.name"
class="logo-image"
fit="cover"
/>
<div v-else class="logo-placeholder">
<el-icon><User /></el-icon>
</div>
</div>
<div class="step-item-info">
<div class="step-item-name">{{ item.name }}</div>
<div class="step-item-meta">
<span class="provider">{{ item.provider }}</span>
<span v-if="item.description" class="divider">|</span>
<span class="desc">{{ item.description }}</span>
</div>
</div>
<div class="step-item-score">{{ item.score }}</div>
</div>
</div>
</div>
<!-- 步骤3计算结果 -->
<div v-if="calcStep === 3" class="calc-step result-step">
<div class="result-header">
<el-icon size="48" color="#67c23a"><CircleCheck /></el-icon>
<h3>计算完成</h3>
</div>
<div class="result-content">
<div class="result-combination">
<div class="result-item">
<div class="result-label">大模型</div>
<div class="result-value">{{ selectedModel?.name }}</div>
<div class="result-score">{{ selectedModel?.score }} × 65%</div>
</div>
<div class="result-plus">+</div>
<div class="result-item">
<div class="result-label">编程工具</div>
<div class="result-value">{{ selectedTool?.name }}</div>
<div class="result-score">{{ selectedTool?.score }} × 35%</div>
</div>
</div>
<div class="result-divider" />
<div class="result-final">
<div class="result-final-label">AI编程能力综合评分</div>
<div class="result-final-score">{{ calculatedScore }}<span></span></div>
<div class="result-congrats">恭喜你陪伴你的AI是一个<span class="brain-type">{{ scoreDescription }}</span></div>
</div>
</div>
</div>
<template #footer>
<div class="dialog-footer">
<el-button v-if="calcStep > 1" @click="calcStep--">上一步</el-button>
<el-button v-if="calcStep === 3" type="primary" @click="restartCalculator">重新计算</el-button>
<el-button @click="closeCalculator">关闭</el-button>
</div>
</template>
</el-dialog>
<!-- 底部说明 -->
<div class="ranking-footer content-wrapper">
<div class="footer-content">
<el-alert
title="排行榜说明"
type="info"
:closable="false"
show-icon
>
<template #default>
<div class="footer-desc">
<p> 模型排行综合评估主要全网编程能力指数意心Ai平台实测指数代码生成能力推理速度准确率多语言支持等维度</p>
<p> 工具排行综合评估主要全网编程能力指数意心Ai平台实测指数用户活跃度功能完整性易用性社区反馈等维度</p>
<p> 数据实时更新以上排行仅意心Ai平台模型综合编程能力对比</p>
</div>
</template>
</el-alert>
</div>
</div>
</div>
</template>
<style scoped lang="scss">
.ranking-container {
width: 100%;
height: 100%;
overflow-y: auto;
background: linear-gradient(135deg, #f5f7fa 0%, #e4e7ed 100%);
padding: 24px;
box-sizing: border-box;
}
// 内容包装器 - 限制最大宽度并居中
.content-wrapper {
max-width: 1400px;
margin: 0 auto;
}
// 页面头部
.ranking-header {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
border-radius: 16px;
padding: 32px 40px;
margin-bottom: 24px;
box-shadow: 0 8px 32px rgba(102, 126, 234, 0.3);
.header-content {
display: flex;
justify-content: space-between;
align-items: center;
flex-wrap: wrap;
gap: 16px;
}
.title-section {
display: flex;
align-items: center;
gap: 20px;
.title-icon {
width: 70px;
height: 70px;
background: rgba(255, 255, 255, 0.2);
backdrop-filter: blur(10px);
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
color: white;
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.2);
}
.title-text {
.main-title {
font-size: 32px;
font-weight: 800;
color: white;
margin: 0 0 8px 0;
letter-spacing: -0.5px;
text-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
}
.subtitle {
font-size: 15px;
color: rgba(255, 255, 255, 0.9);
margin: 0;
}
}
}
.update-time {
display: flex;
align-items: center;
gap: 8px;
color: rgba(255, 255, 255, 0.9);
font-size: 14px;
background: rgba(255, 255, 255, 0.15);
padding: 10px 18px;
border-radius: 30px;
backdrop-filter: blur(10px);
}
.calculator-btn {
background: rgba(255, 255, 255, 0.2);
backdrop-filter: blur(10px);
border: 1px solid rgba(255, 255, 255, 0.3);
color: white;
font-size: 14px;
font-weight: 600;
padding: 12px 24px;
height: auto;
border-radius: 30px;
transition: all 0.3s;
position: relative;
overflow: hidden;
animation: btnPulse 2s ease-in-out infinite;
// 光效扫过动画
&::before {
content: '';
position: absolute;
top: 0;
left: -100%;
width: 100%;
height: 100%;
background: linear-gradient(
90deg,
transparent,
rgba(255, 255, 255, 0.4),
transparent
);
animation: lightSweep 3s ease-in-out infinite;
}
// 发光光环
&::after {
content: '';
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 100%;
height: 100%;
border-radius: 30px;
border: 2px solid rgba(255, 255, 255, 0.6);
opacity: 0;
animation: glowRing 2s ease-out infinite;
}
&:hover {
background: rgba(255, 255, 255, 0.3);
transform: translateY(-2px) scale(1.05);
box-shadow:
0 4px 20px rgba(0, 0, 0, 0.2),
0 0 30px rgba(255, 255, 255, 0.3);
animation: none;
&::before {
animation: none;
}
&::after {
animation: none;
opacity: 0;
}
}
.el-icon {
margin-right: 6px;
animation: iconBounce 1s ease-in-out infinite;
}
}
}
// 按钮脉冲动画
@keyframes btnPulse {
0%, 100% {
transform: scale(1);
box-shadow:
0 0 0 0 rgba(255, 255, 255, 0.4),
0 4px 15px rgba(0, 0, 0, 0.1);
}
50% {
transform: scale(1.03);
box-shadow:
0 0 0 8px rgba(255, 255, 255, 0),
0 6px 20px rgba(0, 0, 0, 0.15);
}
}
// 光效扫过动画
@keyframes lightSweep {
0% {
left: -100%;
}
50%, 100% {
left: 100%;
}
}
// 发光光环动画
@keyframes glowRing {
0% {
transform: translate(-50%, -50%) scale(1);
opacity: 0.6;
}
100% {
transform: translate(-50%, -50%) scale(1.5);
opacity: 0;
}
}
// 图标跳动动画
@keyframes iconBounce {
0%, 100% {
transform: translateY(0);
}
50% {
transform: translateY(-3px);
}
}
// 主内容区
.ranking-content {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 20px;
margin-bottom: 24px;
width: 100%;
box-sizing: border-box;
@media (max-width: 1024px) {
grid-template-columns: 1fr;
}
}
// 排行区域
.ranking-section {
background: white;
border-radius: 16px;
padding: 20px;
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.06);
transition: transform 0.3s, box-shadow 0.3s;
min-width: 0;
overflow: hidden;
&:hover {
box-shadow: 0 8px 30px rgba(0, 0, 0, 0.1);
}
.section-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 20px;
padding-bottom: 16px;
border-bottom: 2px solid #f0f0f0;
.section-title {
display: flex;
align-items: center;
gap: 12px;
font-size: 20px;
font-weight: 700;
color: #303133;
.el-icon {
color: #667eea;
}
}
}
.loading-wrapper {
padding: 40px 20px;
}
.ranking-list {
display: flex;
flex-direction: column;
gap: 12px;
}
.ranking-item {
display: flex;
align-items: center;
gap: 12px;
padding: 14px;
border-radius: 12px;
background: #f8f9fa;
transition: all 0.3s;
border: 2px solid transparent;
&:hover {
background: white;
border-color: #667eea;
transform: translateX(4px);
box-shadow: 0 4px 12px rgba(102, 126, 234, 0.15);
}
// 前三名特殊样式
&.rank-1 {
background: linear-gradient(135deg, #fff8e1 0%, #ffecb3 100%);
border-color: #ffc107;
.rank-number {
background: linear-gradient(135deg, #ffc107, #ff8f00);
color: white;
}
.progress-fill {
background: linear-gradient(90deg, #ffc107 0%, #ff8f00 100%);
}
.progress-score .score-value {
color: #ff8f00;
}
}
&.rank-2 {
background: linear-gradient(135deg, #f5f5f5 0%, #e0e0e0 100%);
border-color: #9e9e9e;
.rank-number {
background: linear-gradient(135deg, #9e9e9e, #616161);
color: white;
}
.progress-fill {
background: linear-gradient(90deg, #9e9e9e 0%, #616161 100%);
}
.progress-score .score-value {
color: #616161;
}
}
&.rank-3 {
background: linear-gradient(135deg, #fff3e0 0%, #ffe0b2 100%);
border-color: #ff9800;
.rank-number {
background: linear-gradient(135deg, #ff9800, #f57c00);
color: white;
}
.progress-fill {
background: linear-gradient(90deg, #ff9800 0%, #f57c00 100%);
}
.progress-score .score-value {
color: #f57c00;
}
}
.rank-number {
width: 40px;
height: 40px;
display: flex;
align-items: center;
justify-content: center;
font-size: 16px;
font-weight: 700;
color: #606266;
background: white;
border-radius: 50%;
flex-shrink: 0;
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.06);
.rank-medal {
display: flex;
align-items: center;
justify-content: center;
}
}
.rank-logo {
width: 40px;
height: 40px;
flex-shrink: 0;
border-radius: 8px;
overflow: hidden;
background: white;
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.06);
display: flex;
align-items: center;
justify-content: center;
.logo-image {
width: 100%;
height: 100%;
}
.logo-placeholder {
width: 100%;
height: 100%;
display: flex;
align-items: center;
justify-content: center;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
font-size: 18px;
}
}
.rank-middle {
flex: 1;
min-width: 0;
display: flex;
flex-direction: column;
gap: 8px;
}
.rank-info {
.rank-name {
font-size: 16px;
font-weight: 600;
color: #303133;
margin-bottom: 4px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.rank-meta {
font-size: 12px;
color: #909399;
display: flex;
align-items: center;
gap: 6px;
min-width: 0;
.provider {
color: #667eea;
font-weight: 600;
background: rgba(102, 126, 234, 0.1);
padding: 1px 6px;
border-radius: 4px;
font-size: 11px;
flex-shrink: 0;
}
.divider {
color: #dcdfe6;
flex-shrink: 0;
}
.description {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
min-width: 0;
}
}
}
.rank-progress {
display: flex;
align-items: center;
gap: 12px;
.progress-bar {
flex: 1;
height: 8px;
background: #e4e7ed;
border-radius: 4px;
overflow: hidden;
.progress-fill {
height: 100%;
background: linear-gradient(90deg, #667eea 0%, #764ba2 100%);
border-radius: 4px;
transition: width 0.5s ease;
}
}
.progress-score {
display: flex;
align-items: baseline;
gap: 2px;
flex-shrink: 0;
min-width: 60px;
justify-content: flex-end;
.score-value {
font-size: 18px;
font-weight: 700;
color: #667eea;
}
.score-label {
font-size: 12px;
color: #909399;
}
}
}
.rank-score {
display: none;
}
}
}
// 计算器弹窗样式
.calculator-dialog {
.calc-step {
.step-header {
display: flex;
align-items: center;
gap: 12px;
margin-bottom: 20px;
padding-bottom: 16px;
border-bottom: 2px solid #f0f0f0;
.step-number {
width: 36px;
height: 36px;
display: flex;
align-items: center;
justify-content: center;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
font-size: 18px;
font-weight: 700;
border-radius: 50%;
}
.step-title {
font-size: 18px;
font-weight: 700;
color: #303133;
}
.step-selected {
margin-left: auto;
font-size: 13px;
color: #909399;
background: #f5f7fa;
padding: 6px 12px;
border-radius: 6px;
span {
color: #667eea;
font-weight: 600;
}
}
}
.step-list {
display: flex;
flex-direction: column;
gap: 10px;
max-height: 400px;
overflow-y: auto;
padding-right: 8px;
.step-item {
display: flex;
align-items: center;
gap: 10px;
padding: 12px;
background: #f8f9fa;
border-radius: 10px;
cursor: pointer;
transition: all 0.3s;
border: 2px solid transparent;
&:hover {
background: white;
border-color: #667eea;
box-shadow: 0 4px 12px rgba(102, 126, 234, 0.15);
transform: translateX(4px);
}
&.active {
background: white;
border-color: #667eea;
box-shadow: 0 4px 12px rgba(102, 126, 234, 0.2);
.step-item-rank {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
}
}
.step-item-rank {
width: 28px;
height: 28px;
display: flex;
align-items: center;
justify-content: center;
font-size: 13px;
font-weight: 700;
color: #606266;
background: white;
border-radius: 6px;
flex-shrink: 0;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.06);
&.rank-1 {
background: linear-gradient(135deg, #ffc107, #ff8f00);
color: white;
}
&.rank-2 {
background: linear-gradient(135deg, #9e9e9e, #616161);
color: white;
}
&.rank-3 {
background: linear-gradient(135deg, #ff9800, #f57c00);
color: white;
}
}
.step-item-logo {
width: 36px;
height: 36px;
flex-shrink: 0;
border-radius: 6px;
overflow: hidden;
background: white;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.06);
display: flex;
align-items: center;
justify-content: center;
.logo-image {
width: 100%;
height: 100%;
}
.logo-placeholder {
width: 100%;
height: 100%;
display: flex;
align-items: center;
justify-content: center;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
font-size: 16px;
}
}
.step-item-info {
flex: 1;
min-width: 0;
.step-item-name {
font-size: 14px;
font-weight: 600;
color: #303133;
margin-bottom: 2px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.step-item-meta {
font-size: 12px;
color: #909399;
display: flex;
align-items: center;
gap: 6px;
min-width: 0;
.provider {
color: #667eea;
font-weight: 600;
background: rgba(102, 126, 234, 0.1);
padding: 1px 6px;
border-radius: 4px;
font-size: 11px;
flex-shrink: 0;
}
.divider {
color: #dcdfe6;
flex-shrink: 0;
}
.desc {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
min-width: 0;
}
}
}
.step-item-score {
font-size: 15px;
font-weight: 700;
color: #667eea;
flex-shrink: 0;
}
}
}
}
.result-step {
text-align: center;
padding: 20px;
.result-header {
margin-bottom: 30px;
h3 {
font-size: 24px;
font-weight: 700;
color: #303133;
margin: 16px 0 0 0;
}
}
.result-content {
background: #f8f9fa;
border-radius: 16px;
padding: 30px;
.result-combination {
display: flex;
align-items: center;
justify-content: center;
gap: 20px;
margin-bottom: 24px;
.result-item {
flex: 1;
max-width: 200px;
background: white;
padding: 20px;
border-radius: 12px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);
.result-label {
font-size: 13px;
color: #909399;
margin-bottom: 8px;
}
.result-value {
font-size: 16px;
font-weight: 700;
color: #303133;
margin-bottom: 8px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.result-score {
font-size: 14px;
color: #667eea;
font-weight: 500;
}
}
.result-plus {
font-size: 24px;
font-weight: 700;
color: #909399;
}
}
.result-divider {
height: 1px;
background: #e4e7ed;
margin: 24px 0;
}
.result-final {
.result-final-label {
font-size: 14px;
color: #909399;
margin-bottom: 12px;
}
.result-final-score {
font-size: 56px;
font-weight: 800;
color: #667eea;
line-height: 1;
span {
font-size: 20px;
font-weight: 500;
margin-left: 4px;
}
}
.result-congrats {
margin-top: 20px;
font-size: 16px;
color: #606266;
.brain-type {
font-size: 24px;
font-weight: 700;
color: #ff6b6b;
margin-left: 4px;
}
}
}
}
}
.dialog-footer {
display: flex;
justify-content: flex-end;
gap: 12px;
}
}
// 底部说明
.ranking-footer {
.footer-content {
max-width: 100%;
}
.footer-desc {
p {
margin: 4px 0;
font-size: 13px;
color: #606266;
}
}
}
// 响应式
@media (max-width: 768px) {
.ranking-container {
padding: 16px;
}
.ranking-header {
padding: 24px 20px;
.title-section {
.title-icon {
width: 50px;
height: 50px;
.el-icon {
font-size: 24px;
}
}
.title-text {
.main-title {
font-size: 22px;
}
.subtitle {
font-size: 13px;
}
}
}
}
.ranking-section {
padding: 16px;
.section-title {
font-size: 18px;
}
.ranking-item {
padding: 10px;
gap: 10px;
.rank-number {
width: 34px;
height: 34px;
font-size: 13px;
}
.rank-logo {
width: 36px;
height: 36px;
}
.rank-info {
.rank-name {
font-size: 14px;
}
.rank-meta {
font-size: 11px;
gap: 4px;
.provider {
font-size: 10px;
padding: 1px 4px;
}
}
}
.rank-score {
.score-value {
font-size: 16px;
}
}
}
}
}
</style>