Files
reader-star/apps/admin/src/views/results/results-detail-copy/modules/TeamResultCard.vue
rjl 2b50bd2c71 feat(results): 新增实时结果列表和详情页面,支持评委查看和评分
- 添加 results_results-list 和 results_results-detail 路由及页面
- 实现比赛列表展示,支持跳转到实时结果详情
- 在结果详情页面添加分组和题目切换功能
- 集成游戏统计 API,实时获取队伍答题数据
- 添加 TeamResultCard 和 GroupTabs 可复用组件
- 更新国际化配置和类型定义
2026-02-28 08:46:11 +08:00

115 lines
3.4 KiB
Vue

<script setup lang="ts">
import { NImage } from 'naive-ui'
export interface AICharacter {
id: string
char: string
isCorrect: boolean
}
export interface TeamResult {
id: number | string
name: string
correctCount: number
score: number
imageUrl: string
status: 'pending' | 'analyzing' | 'done'
aiData: AICharacter[]
}
// eslint-disable-next-line unused-imports/no-unused-vars
const props = defineProps<{
data: TeamResult
}>()
const emit = defineEmits<{
(e: 'toggle-correct', charId: string): void
(e: 'update-char', charId: string, newChar: string): void
}>()
// 切换正确状态
function handleCharClick(item: AICharacter) {
// eslint-disable-next-line vue/custom-event-name-casing
emit('toggle-correct', item.id)
}
</script>
<template>
<div class="h-full flex flex-col overflow-hidden border border-gray-100 rounded-xl bg-white shadow-sm">
<!-- 头部信息 -->
<div class="flex items-center justify-between border-b border-gray-100 bg-gray-50 px-4 py-3">
<h3 class="m-0 text-lg text-gray-800 font-bold">
{{ data.name }}
</h3>
<div class="flex gap-3 text-sm">
<span class="text-green-600 font-bold">正确 {{ data.correctCount }} </span>
<span class="text-blue-600 font-bold">积分 {{ data.score }} </span>
</div>
</div>
<!-- 图片区域 -->
<div class="relative aspect-[3/4] w-full flex items-center justify-center overflow-hidden border-b border-gray-100 bg-gray-100">
<!-- 图片居中 -->
<NImage
v-if="data.imageUrl"
:src="data.imageUrl"
class="h-full w-full flex items-center justify-center"
:img-props="{ class: 'w-full h-full object-contain object-center' }"
preview-disabled
/>
<div v-else class="h-full w-full flex items-center justify-center text-gray-400">
等待上传答题卡...
</div>
<!-- 加载遮罩 -->
<!-- <div
v-if="data.status === 'analyzing'"
class="absolute inset-0 bg-black/20 flex items-center justify-center backdrop-blur-[1px]"
>
<NSpin size="large" />
</div> -->
</div>
<!-- AI 结果网格 -->
<div class="min-h-[200px] flex-1 overflow-y-auto p-5">
<div v-if="data.aiData.length === 0" class="h-full flex items-center justify-center text-sm text-gray-400">
{{ data.status === 'pending' ? '等待识别...' : '暂无数据' }}
</div>
<div v-else class="grid grid-cols-8 gap-2">
<!--
grid-cols-5 控制宽度 (宽度由网格列数控制)
h-10 控制高度 (高度由固定高度类控制)
-->
<div
v-for="item in data.aiData"
:key="item.id"
class="h-14 w-14 flex cursor-pointer select-none items-center justify-center rounded-lg text-lg font-bold transition-all active:scale-95 hover:scale-105"
:class="[
item.isCorrect
? 'bg-green-100 text-green-600 border border-green-200'
: 'bg-red-100 text-red-600 border border-red-200',
]"
@click="handleCharClick(item)"
>
{{ item.char }}
</div>
</div>
</div>
</div>
</template>
<style scoped>
/* Custom scrollbar for the grid area if needed */
::-webkit-scrollbar {
width: 4px;
}
::-webkit-scrollbar-track {
background: transparent;
}
::-webkit-scrollbar-thumb {
background: #e5e7eb;
border-radius: 2px;
}
</style>