Files
reader-star/apps/admin/src/views/user/analysis/index.vue

255 lines
7.6 KiB
Vue
Raw Normal View History

<script setup lang="ts">
import { computed, onBeforeUnmount, ref } from 'vue'
import { useRoute } from 'vue-router'
import CompetitionLayout from '@/components/custom/user/CompetitionLayout.vue'
import { useRouterPush } from '@/hooks/common/router'
import { fetchCheckNextStep, fetchGetCurrentQuestion } from '@/service/api/game'
import { useCompetitionStore } from '@/store/modules/competition'
const store = useCompetitionStore()
const { routerPushByKey } = useRouterPush()
const route = useRoute()
const activityId = computed(() => route.query?.activityId as string)
const groupsId = computed(() => route.query?.groupsId as string)
const teamId = computed(() => route.query?.teamId as string)
const teamIds = computed(() => route.query?.teamIds as string)
const currentQuestionMainInfo = computed(() => store.currentQuestionMainInfo)
const TeamGroup_QuestionID = computed(() => currentQuestionMainInfo.value?.TeamGroup_QuestionID || 0)
const zoomedImage = ref<string | null>(null)
const isCompleted = ref(false)
const showNextBtn = ref(false)
// Mock team data
const teams = ref([
{
id: 1,
name: '第一队',
writtenCount: 16,
correctCount: 13,
score: 13,
manualScore: null as number | null,
image: 'https://via.placeholder.com/300x400?text=Team+1+Answer',
},
{
id: 2,
name: '第二队',
writtenCount: 15,
correctCount: 12,
score: 12,
manualScore: null as number | null,
image: 'https://via.placeholder.com/300x400?text=Team+2+Answer',
},
{
id: 3,
name: '第三队',
writtenCount: 18,
correctCount: 15,
score: 15,
manualScore: null as number | null,
image: 'https://via.placeholder.com/300x400?text=Team+3+Answer',
},
{
id: 4,
name: '第四队',
writtenCount: 14,
correctCount: 10,
score: 10,
manualScore: null as number | null,
image: 'https://via.placeholder.com/300x400?text=Team+4+Answer',
},
])
function handleZoom(img: string) {
zoomedImage.value = img
}
function handleBack() {
routerPushByKey('user_game', {
query: {
activityId: activityId.value,
groupsId: groupsId.value,
teamId: teamId.value,
teamIds: teamIds.value,
},
})
}
function handleNext() {
if (isCompleted.value) {
routerPushByKey('user_groups', {
query: {
activityId: activityId.value,
},
})
return
}
routerPushByKey('user_draw', {
query: {
activityId: activityId.value,
groupsId: groupsId.value,
teamId: teamId.value,
teamIds: teamIds.value,
},
})
// 清空当前题目信息
store.initData()
}
/**
* 获取题目详情
* 检测是否还有题可以抽取如果data为0则提示没有题可抽取
*/
async function initQuestions() {
if (!activityId.value)
return
try {
const { data: outlineData, error } = await fetchGetCurrentQuestion({
ActivityID: Number(activityId.value),
GroupID: Number(groupsId.value),
RoundType: 0,
})
// eslint-disable-next-line no-console
console.log(outlineData, 'outlineData')
if (error) {
window?.$message?.error(error.message)
}
isCompleted.value = outlineData?.data?.IsCompleted || false
}
catch (error) {
window.$message?.error('获取题目失败,请重试')
console.error(error)
}
}
const timer = ref<ReturnType<typeof setInterval> | undefined>(undefined)
/** 定时刷新 检查评委是否已经完成打分,是否可以下一步 fetchCheckNextStep */
async function checkNextStep() {
if (!activityId.value || !groupsId.value)
return
try {
const { data: nextStepData, error } = await fetchCheckNextStep(TeamGroup_QuestionID.value || 0)
// eslint-disable-next-line no-console
console.log(nextStepData, 'nextStepData')
if (error) {
window?.$message?.error(error.message)
}
const isUse = nextStepData?.data?.IsUse || false
showNextBtn.value = isUse
if (isUse) {
await initQuestions()
clearInterval(timer.value)
}
}
catch (error) {
window.$message?.error('检查是否可以下一步失败,请重试')
console.error(error)
}
}
// 定时刷新 检查是否可以下一步
timer.value = setInterval(checkNextStep, 2000)
/** 销毁 定时刷新 检查是否可以下一步 */
onBeforeUnmount(() => {
clearInterval(timer.value)
})
</script>
<template>
<CompetitionLayout
:show-title="true" :show-back="false" :show-next="showNextBtn" title="答题图解" action-position="top"
back-btn-text="返回" :next-btn-text="isCompleted ? '该组已完成,回到选组' : '下一题'" btn-theme="light" @back="handleBack"
@next="handleNext"
>
<div class="relative h-full w-full flex flex-col items-center px-12 pt-10 font-sans">
<!-- Content -->
<div class="w-full flex flex-col flex-1 overflow-hidden">
<div class="mb-2 text-xl text-red-600 font-bold">
备注由AI模型评判
</div>
<div v-if="teams && teams.length > 0" class="grid grid-cols-4 h-full gap-6 pb-8">
<div
v-for="team in teams" :key="team.id"
class="flex flex-col border-2 border-gray-200 rounded-xl bg-white/90 p-4 shadow-sm"
>
<div class="mb-2 text-xl text-gray-800 font-bold">
{{ team.name }}
</div>
<!-- Answer Image Area -->
<div
class="relative mb-4 flex-1 cursor-zoom-in overflow-hidden border border-gray-300 rounded bg-gray-50"
@click="handleZoom(team.image)"
>
<!-- Grid Background Simulation -->
<div class="pointer-events-none absolute inset-0 grid grid-cols-8 gap-px bg-gray-200 opacity-20">
<div v-for="n in 64" :key="n" class="bg-white" />
</div>
<!-- Simulated Handwriting/Content -->
<div class="absolute inset-0 flex items-center justify-center text-gray-400">
(点击放大查看详情)
</div>
</div>
<!-- Stats & Score -->
<div class="flex flex-col gap-2">
<div class="text-sm text-gray-700 font-medium">
写了数量{{ team.writtenCount }}正确{{ team.correctCount }}积分{{ team.score }}
</div>
<div class="flex items-center justify-between">
<span class="text-red-500 font-bold">评委当场评</span>
</div>
<div class="relative">
<input
v-model="team.manualScore" type="number"
class="w-full border border-gray-300 rounded px-3 py-2 text-sm focus:border-blue-500 focus:outline-none"
placeholder="留个输入框,修改正确积分"
>
</div>
</div>
</div>
</div>
</div>
<!-- Zoom Modal -->
<div
v-if="zoomedImage" class="fixed inset-0 z-50 flex items-center justify-center bg-black/80 backdrop-blur-sm"
@click="zoomedImage = null"
>
<div class="relative max-h-[90vh] max-w-[90vw] p-4">
<img :src="zoomedImage" class="max-h-full max-w-full rounded bg-white shadow-2xl" alt="Zoomed Answer">
<div class="absolute bottom-4 left-1/2 text-sm text-white/80 -translate-x-1/2">
点击任意处关闭
</div>
</div>
</div>
</div>
</CompetitionLayout>
</template>
<style scoped>
/* Custom Scrollbar for content if needed */
::-webkit-scrollbar {
width: 8px;
}
::-webkit-scrollbar-track {
background: transparent;
}
::-webkit-scrollbar-thumb {
background: #cbd5e1;
border-radius: 4px;
}
</style>