fix: 修复UI样式和轮询逻辑问题
- 修复ActionButton禁用状态颜色错误 - 调整CompetitionLayout布局和z-index层级 - 修正analysis页面评委评分显示位置 - 优化QuestionRenderer字体大小和间距 - 改进cover页面卡片翻转动画效果 - 修复results-detail页面轮询逻辑和时间同步
This commit is contained in:
@ -151,8 +151,8 @@ function handleClick() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
&.is-disabled {
|
&.is-disabled {
|
||||||
color: #eb5e55;
|
color: red;
|
||||||
filter: grayscale(0.5);
|
// filter: grayscale(0.5);
|
||||||
opacity: 0.6;
|
opacity: 0.6;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -229,12 +229,12 @@ watch(titleBgUrl, (newUrl) => {
|
|||||||
<!-- Header -->
|
<!-- Header -->
|
||||||
<header class="page-header flex items-center px-8 text-[30px] text-[#333333] font-bold">
|
<header class="page-header flex items-center px-8 text-[30px] text-[#333333] font-bold">
|
||||||
<!-- 左侧logo -->
|
<!-- 左侧logo -->
|
||||||
<div class="flex cursor-pointer items-center" @click="handleBackHome">
|
<div class="!z-index-99 flex cursor-pointer items-center" @click="handleBackHome">
|
||||||
<img :src="cqLogo" alt="重庆logo" class="h-18 w-auto">
|
<img :src="cqLogo" alt="重庆logo" class="h-18 w-auto">
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 中间文字 -->
|
<!-- 中间文字 -->
|
||||||
<div class="flex flex-1 justify-center">
|
<div class="!z-index-99 flex flex-1 justify-center">
|
||||||
<img :src="qwLogo" alt="重庆logo" class="h-14 w-auto">
|
<img :src="qwLogo" alt="重庆logo" class="h-14 w-auto">
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -450,16 +450,15 @@ watch(titleBgUrl, (newUrl) => {
|
|||||||
|
|
||||||
.page-header {
|
.page-header {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: -50px;
|
top: -58px;
|
||||||
left: 0;
|
left: 0;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 180px;
|
height: 196px;
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
padding: 20px 44px;
|
padding: 20px 44px;
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
color: $secondary-color;
|
color: $secondary-color;
|
||||||
z-index: 10;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.main-content {
|
.main-content {
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
<!-- eslint-disable no-console -->
|
<!-- eslint-disable no-console -->
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { Icon } from '@iconify/vue'
|
import { Icon } from '@iconify/vue'
|
||||||
import { useStorage } from '@vueuse/core'
|
import { useIntervalFn, useStorage } from '@vueuse/core'
|
||||||
import { NButton, NCard, NImage, NInputNumber, NTag, useMessage } from 'naive-ui'
|
import { NButton, NCard, NImage, NInputNumber, NTag, useMessage } from 'naive-ui'
|
||||||
import { computed, onMounted, onUnmounted, ref, watch } from 'vue'
|
import { computed, onMounted, onUnmounted, ref, watch } from 'vue'
|
||||||
import { useRoute } from 'vue-router'
|
import { useRoute } from 'vue-router'
|
||||||
@ -33,6 +33,9 @@ const questionInfo = ref<Api.Competition.QuestionListDetailRound>() // 题目详
|
|||||||
const currentQuestionDetailID = ref<number | string>('') // 当前选中的题目详情 ID
|
const currentQuestionDetailID = ref<number | string>('') // 当前选中的题目详情 ID
|
||||||
|
|
||||||
const nowTs = ref(Date.now())
|
const nowTs = ref(Date.now())
|
||||||
|
useIntervalFn(() => {
|
||||||
|
nowTs.value = Date.now()
|
||||||
|
}, 1000)
|
||||||
// 判断当前activityId是正在比赛的活动
|
// 判断当前activityId是正在比赛的活动
|
||||||
const isActiveActivityId = computed(() => {
|
const isActiveActivityId = computed(() => {
|
||||||
if (!currentQuestion.value)
|
if (!currentQuestion.value)
|
||||||
@ -254,7 +257,9 @@ async function fetchCurrentQuestion(shouldSync = true) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
currentQuestion.value = data?.data || {}
|
currentQuestion.value = data?.data || {}
|
||||||
|
const endTime = new Date(currentQuestion.value.EndTime)
|
||||||
console.warn('current question', currentQuestion.value)
|
console.warn('current question', currentQuestion.value)
|
||||||
|
console.log('当前题目结束时间是:', endTime.toLocaleString())
|
||||||
// 只在初始化时同步选中题,轮询时不同步
|
// 只在初始化时同步选中题,轮询时不同步
|
||||||
if (shouldSync) {
|
if (shouldSync) {
|
||||||
syncCurrentQuestionSelection()
|
syncCurrentQuestionSelection()
|
||||||
@ -466,9 +471,6 @@ async function handleNexCurrentQuestion() {
|
|||||||
currentQuestionId.value = currentQuestion.value?.QuestionID || currentQuestionId.value
|
currentQuestionId.value = currentQuestion.value?.QuestionID || currentQuestionId.value
|
||||||
currentGroupId.value = currentQuestion.value?.TeamGroupID || currentGroupId.value
|
currentGroupId.value = currentQuestion.value?.TeamGroupID || currentGroupId.value
|
||||||
}
|
}
|
||||||
|
|
||||||
// 更新当前时间戳,以便重新计算 canPublish
|
|
||||||
nowTs.value = Date.now()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function handlePublish() {
|
function handlePublish() {
|
||||||
@ -617,25 +619,23 @@ function startPolling() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fetchAnswerData() // 立即获取
|
fetchAnswerData() // 立即获取
|
||||||
nowTs.value = Date.now()
|
|
||||||
pollingTimer.value = setInterval(() => {
|
pollingTimer.value = setInterval(() => {
|
||||||
// 每次轮询前再次检查是否过期
|
// 每次轮询前再次检查是否过期
|
||||||
const currentEndTime = (currentQuestion.value as any)?.EndTime
|
const currentEndTime = (currentQuestion.value as any)?.EndTime
|
||||||
if (currentEndTime) {
|
if (currentEndTime) {
|
||||||
// 增加 5s 缓冲时间
|
// 增加 1s 缓冲时间
|
||||||
const endTs = new Date(currentEndTime).getTime() + 3000
|
const endTs = new Date(currentEndTime).getTime() + 1000
|
||||||
if (Date.now() > endTs) {
|
if (Date.now() > endTs) {
|
||||||
console.log('题目时间已到(含3s缓冲),停止轮询', currentEndTime)
|
console.log('题目时间已到(含1s缓冲),停止轮询', currentEndTime)
|
||||||
stopPolling()
|
stopPolling()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
nowTs.value = Date.now()
|
|
||||||
|
|
||||||
// 轮询时同时更新当前题目信息(获取最新的 EndTime),但不触发同步
|
// 轮询时同时更新当前题目信息(获取最新的 EndTime),但不触发同步
|
||||||
fetchCurrentQuestion(false)
|
fetchCurrentQuestion(false)
|
||||||
fetchAnswerData()
|
fetchAnswerData()
|
||||||
}, 3000)
|
}, 2000)
|
||||||
}
|
}
|
||||||
|
|
||||||
function stopPolling() {
|
function stopPolling() {
|
||||||
|
|||||||
@ -168,7 +168,7 @@ onBeforeUnmount(() => {
|
|||||||
<!-- Content -->
|
<!-- Content -->
|
||||||
<div class="w-full flex flex-col flex-1 overflow-hidden">
|
<div class="w-full flex flex-col flex-1 overflow-hidden">
|
||||||
<div class="mb-2 text-xl text-red-600 font-bold">
|
<div class="mb-2 text-xl text-red-600 font-bold">
|
||||||
备注:评委正在评分中,请等待。。。
|
备注:评委正在评分中,请等待...
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div v-if="teams && teams.length > 0" class="grid grid-cols-4 h-full gap-6 pb-8">
|
<div v-if="teams && teams.length > 0" class="grid grid-cols-4 h-full gap-6 pb-8">
|
||||||
@ -180,12 +180,12 @@ onBeforeUnmount(() => {
|
|||||||
class="mb-3 flex items-center gap-2 rounded-full from-sky-300 to-cyan-200 bg-gradient-to-r px-4 py-2 shadow-sm"
|
class="mb-3 flex items-center gap-2 rounded-full from-sky-300 to-cyan-200 bg-gradient-to-r px-4 py-2 shadow-sm"
|
||||||
>
|
>
|
||||||
<span class="text-lg text-white font-bold drop-shadow">{{ team.TeamName }}</span>
|
<span class="text-lg text-white font-bold drop-shadow">{{ team.TeamName }}</span>
|
||||||
|
<span class="rounded-full bg-green-100/90 px-5 py-2 text-sm">
|
||||||
|
评委评分 <span class="text-lg text-orange-600 font-bold">{{ team.ResultPotins }}</span>
|
||||||
|
</span>
|
||||||
<span class="rounded-full bg-orange-100/60 px-5 py-2 text-sm">
|
<span class="rounded-full bg-orange-100/60 px-5 py-2 text-sm">
|
||||||
AI评分 <span class="text-md text-orange-600 font-bold">{{ team.Points }}</span>
|
AI评分 <span class="text-md text-orange-600 font-bold">{{ team.Points }}</span>
|
||||||
</span>
|
</span>
|
||||||
<span class="rounded-full bg-green-100/60 px-5 py-2 text-sm">
|
|
||||||
评委评分 <span class="text-md text-green-600 font-bold">{{ team.ResultPotins }}</span>
|
|
||||||
</span>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Answer Image Area -->
|
<!-- Answer Image Area -->
|
||||||
|
|||||||
@ -288,7 +288,7 @@ onMounted(async () => {
|
|||||||
// [过冲状态]
|
// [过冲状态]
|
||||||
// 飞到眼前一点点 (Z=50px)
|
// 飞到眼前一点点 (Z=50px)
|
||||||
// 角度稍微回弹 (rotateY -15deg)
|
// 角度稍微回弹 (rotateY -15deg)
|
||||||
transform: translate3d(0, -20px, 50px) rotateY(-15deg) rotateX(-10deg) scale(1.05);
|
transform: translate3d(0, -20px, 50px) rotateY(-15deg) rotateX(-10deg) scale(1.2);
|
||||||
}
|
}
|
||||||
|
|
||||||
100% {
|
100% {
|
||||||
@ -328,8 +328,8 @@ onMounted(async () => {
|
|||||||
// [翻转状态]
|
// [翻转状态]
|
||||||
// rotateY(180deg): 绕Y轴旋转180度,实现翻面
|
// rotateY(180deg): 绕Y轴旋转180度,实现翻面
|
||||||
// scale(1.05): 翻转同时放大1.05倍,产生"向观众逼近"的视觉冲击力
|
// scale(1.05): 翻转同时放大1.05倍,产生"向观众逼近"的视觉冲击力
|
||||||
transform: rotateY(180deg) scale(1.06);
|
transform: rotateY(180deg) scale(1.08);
|
||||||
box-shadow: 0 20px 40px -5px rgba(0, 0, 0, 0.3); // [动态阴影] 翻转浮起时阴影更深、更扩散
|
box-shadow: 0 10px 20px -5px rgba(0, 0, 0, 0.3); // [动态阴影] 翻转浮起时阴影更深、更扩散
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -344,7 +344,7 @@ onMounted(async () => {
|
|||||||
|
|
||||||
border-radius: 20px;
|
border-radius: 20px;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
// border: 1px solid rgba(255, 255, 255, 0.5); // 增加微妙的边框
|
// border: 1px solid rgba(231, 215, 144, 0.5); // 增加微妙的边框
|
||||||
}
|
}
|
||||||
|
|
||||||
// 正面(实际是卡背图案)
|
// 正面(实际是卡背图案)
|
||||||
@ -367,7 +367,7 @@ onMounted(async () => {
|
|||||||
// 背面(实际是内容面)
|
// 背面(实际是内容面)
|
||||||
.flip-card-back {
|
.flip-card-back {
|
||||||
// background-color: #fff;
|
// background-color: #fff;
|
||||||
transform: rotateY(180deg);
|
transform: rotateY(200deg);
|
||||||
// border: 4px solid #fff;
|
// border: 4px solid #fff;
|
||||||
|
|
||||||
.card-content-design {
|
.card-content-design {
|
||||||
@ -409,7 +409,7 @@ onMounted(async () => {
|
|||||||
// animation-delay: 0.2s; 确保卡片翻转到一半(正对屏幕)时才开始闪光,
|
// animation-delay: 0.2s; 确保卡片翻转到一半(正对屏幕)时才开始闪光,
|
||||||
// 模拟光线随着角度变化掠过卡片表面的物理效果
|
// 模拟光线随着角度变化掠过卡片表面的物理效果
|
||||||
animation: shine-sweep 3s ease-out forwards;
|
animation: shine-sweep 3s ease-out forwards;
|
||||||
animation-delay: 0.2s;
|
animation-delay: 1s;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -455,14 +455,14 @@ onMounted(async () => {
|
|||||||
|
|
||||||
10% {
|
10% {
|
||||||
// 刚进入时瞬间变亮
|
// 刚进入时瞬间变亮
|
||||||
opacity: 0.8;
|
opacity: 0.8; // 0.8 是一个半透明值,模拟光束的透明度,值越大越透明
|
||||||
}
|
}
|
||||||
|
|
||||||
100% {
|
100% {
|
||||||
// 扫出视野
|
// 扫出视野
|
||||||
top: 50%;
|
top: 50%;
|
||||||
left: 150%;
|
left: 150%;
|
||||||
opacity: 0;
|
opacity: 0.6;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -185,7 +185,7 @@ watch(
|
|||||||
>
|
>
|
||||||
<!-- 上方:词组 -->
|
<!-- 上方:词组 -->
|
||||||
<div class="flex flex-wrap justify-center gap-4">
|
<div class="flex flex-wrap justify-center gap-4">
|
||||||
<div v-for="(word, index) in associationWords" :key="`word-${index}`" class="association-word text-bold">
|
<div v-for="(word, index) in associationWords" :key="`word-${index}`" class="association-word text-bold text-center text-3xl">
|
||||||
{{ word }}
|
{{ word }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -215,9 +215,9 @@ watch(
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 模板: 诗词常识 -->
|
<!-- 模板: 加时赛诗词常识 -->
|
||||||
<div v-else-if="template === QuestionCategoryEnum.PoetryCommonKnowledge" class="w-full flex flex-col items-center">
|
<div v-else-if="template === QuestionCategoryEnum.PoetryCommonKnowledge" class="w-full flex flex-col items-center">
|
||||||
<div class="mb-1 p-16 text-3xl text-gray-800 font-bold leading-relaxed line-height-20">
|
<div class="line-height mb-1 p-16 text-3xl text-gray-800 font-bold leading-relaxed">
|
||||||
<div class="rich-content" v-html="content" />
|
<div class="rich-content" v-html="content" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -445,8 +445,7 @@ watch(
|
|||||||
:deep(p),
|
:deep(p),
|
||||||
:deep(span),
|
:deep(span),
|
||||||
:deep(div) {
|
:deep(div) {
|
||||||
font-size: 2.2rem;
|
font-size: 2rem;
|
||||||
/* text-5xl */
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -494,15 +493,14 @@ watch(
|
|||||||
.association-word {
|
.association-word {
|
||||||
background: url('@/assets/imgs/user/dui-kuang.png') no-repeat center;
|
background: url('@/assets/imgs/user/dui-kuang.png') no-repeat center;
|
||||||
background-size: 100% 100%;
|
background-size: 100% 100%;
|
||||||
min-width: 160px;
|
min-width: 170px;
|
||||||
height: 70px;
|
height: 70px;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
font-size: 32px;
|
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
color: white;
|
color: white;
|
||||||
padding: 0 20px;
|
letter-spacing: 0.2em;
|
||||||
}
|
}
|
||||||
|
|
||||||
.association-char {
|
.association-char {
|
||||||
|
|||||||
@ -157,13 +157,13 @@ function rowClassName(row: TeamData) {
|
|||||||
<template>
|
<template>
|
||||||
<CompetitionLayout :show-back="false" :show-next="false" :show-title="false">
|
<CompetitionLayout :show-back="false" :show-next="false" :show-title="false">
|
||||||
<div class="leaderboard-container h-100%">
|
<div class="leaderboard-container h-100%">
|
||||||
<div class="leaderboard-header">
|
<div class="leaderboard-header !z-index-99">
|
||||||
<NImage :src="title" alt="logo" preview-disabled class="mt--42px" object-fit="contain" />
|
<NImage :src="title" alt="logo" preview-disabled class="mt--42px" object-fit="contain" />
|
||||||
<!-- <p class="mt--16px text-center text-18px text-#6b778d">
|
<!-- <p class="mt--16px text-center text-18px text-#6b778d">
|
||||||
"勤学如春起之苗,不见其增,日有所长"
|
"勤学如春起之苗,不见其增,日有所长"
|
||||||
</p> -->
|
</p> -->
|
||||||
<ActionButton
|
<ActionButton
|
||||||
v-if="hasExtraTimeBtn" class="z-index-99 position-absolute right-20px top-20px" type="text"
|
v-if="hasExtraTimeBtn" class="!z-index-100 position-absolute right-20px top-20px" type="text"
|
||||||
text="加时赛" @click="handleAddTime"
|
text="加时赛" @click="handleAddTime"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user