- 添加 results_results-list 和 results_results-detail 路由及页面 - 实现比赛列表展示,支持跳转到实时结果详情 - 在结果详情页面添加分组和题目切换功能 - 集成游戏统计 API,实时获取队伍答题数据 - 添加 TeamResultCard 和 GroupTabs 可复用组件 - 更新国际化配置和类型定义
115 lines
3.4 KiB
Vue
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>
|