Compare commits
4 Commits
a7cf35e6bf
...
0d03fdd782
| Author | SHA1 | Date | |
|---|---|---|---|
| 0d03fdd782 | |||
| a76263375a | |||
| 9bc58c6270 | |||
| 7b505ec4aa |
@ -5,7 +5,8 @@
|
||||
|
||||
# VITE_SERVICE_BASE_URL=http://api.ydzx.qyzhjy.com
|
||||
|
||||
VITE_SERVICE_BASE_URL=http://api.ydzx.qyzhjy.com/
|
||||
# VITE_SERVICE_BASE_URL=http://api.ydzx.qyzhjy.com/
|
||||
VITE_SERVICE_BASE_URL=http://172.16.10.130:5000
|
||||
|
||||
VITE_OTHER_SERVICE_BASE_URL= `{
|
||||
"demo": "http://localhost:9528"
|
||||
|
||||
@ -151,8 +151,8 @@ function handleClick() {
|
||||
}
|
||||
|
||||
&.is-disabled {
|
||||
color: #eb5e55;
|
||||
filter: grayscale(0.5);
|
||||
color: red;
|
||||
// filter: grayscale(0.5);
|
||||
opacity: 0.6;
|
||||
}
|
||||
|
||||
|
||||
@ -229,12 +229,12 @@ watch(titleBgUrl, (newUrl) => {
|
||||
<!-- Header -->
|
||||
<header class="page-header flex items-center px-8 text-[30px] text-[#333333] font-bold">
|
||||
<!-- 左侧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">
|
||||
</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">
|
||||
</div>
|
||||
|
||||
@ -450,16 +450,15 @@ watch(titleBgUrl, (newUrl) => {
|
||||
|
||||
.page-header {
|
||||
position: absolute;
|
||||
top: -50px;
|
||||
top: -58px;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 180px;
|
||||
height: 196px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
padding: 20px 44px;
|
||||
font-weight: 700;
|
||||
color: $secondary-color;
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
.main-content {
|
||||
|
||||
@ -214,7 +214,7 @@ init()
|
||||
<template #prefix>
|
||||
<SvgIcon :icon="tab.icon" :local-icon="tab.localIcon" class="inline-block align-text-bottom text-16px" />
|
||||
</template>
|
||||
<div class="max-w-240px ellipsis-text">
|
||||
<div class="max-w-240px ellipsis-text text-14px">
|
||||
{{ tab.label }}
|
||||
</div>
|
||||
</PageTab>
|
||||
|
||||
@ -8,7 +8,7 @@ defineOptions({ name: 'QuestionStore' })
|
||||
const currentCategory = ref<any>(null)
|
||||
|
||||
// Resize logic
|
||||
const siderWidth = ref(525)
|
||||
const siderWidth = ref(535)
|
||||
const LOCAL_STORAGE_KEY = 'question-store-sider-width'
|
||||
const minWidth = 300
|
||||
const maxWidth = 800
|
||||
|
||||
@ -231,10 +231,10 @@ onMounted(() => {
|
||||
>
|
||||
<div class="flex items-center gap-2 overflow-hidden">
|
||||
<SvgIcon
|
||||
icon="carbon:folder" class="flex-shrink-0 text-lg"
|
||||
icon="carbon:folder" class="flex-shrink-0 text-sm"
|
||||
:class="selectedKey === item.Id ? 'text-primary' : 'text-gray-400'"
|
||||
/>
|
||||
<span class="truncate font-medium">{{ item.Name }} - {{ item.QuestionContent }}</span>
|
||||
<span class="truncate text-16px font-medium">{{ item.Name }} - {{ item.QuestionContent }}</span>
|
||||
</div>
|
||||
|
||||
<!-- Action Buttons -->
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
<!-- eslint-disable no-console -->
|
||||
<script lang="ts" setup>
|
||||
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 { computed, onMounted, onUnmounted, ref, watch } from 'vue'
|
||||
import { useRoute } from 'vue-router'
|
||||
@ -33,6 +33,9 @@ const questionInfo = ref<Api.Competition.QuestionListDetailRound>() // 题目详
|
||||
const currentQuestionDetailID = ref<number | string>('') // 当前选中的题目详情 ID
|
||||
|
||||
const nowTs = ref(Date.now())
|
||||
useIntervalFn(() => {
|
||||
nowTs.value = Date.now()
|
||||
}, 1000)
|
||||
// 判断当前activityId是正在比赛的活动
|
||||
const isActiveActivityId = computed(() => {
|
||||
if (!currentQuestion.value)
|
||||
@ -254,7 +257,9 @@ async function fetchCurrentQuestion(shouldSync = true) {
|
||||
return
|
||||
}
|
||||
currentQuestion.value = data?.data || {}
|
||||
const endTime = new Date(currentQuestion.value.EndTime)
|
||||
console.warn('current question', currentQuestion.value)
|
||||
console.log('当前题目结束时间是:', endTime.toLocaleString())
|
||||
// 只在初始化时同步选中题,轮询时不同步
|
||||
if (shouldSync) {
|
||||
syncCurrentQuestionSelection()
|
||||
@ -265,6 +270,42 @@ async function fetchCurrentQuestion(shouldSync = true) {
|
||||
}
|
||||
}
|
||||
|
||||
const blobSizeCache = new Map<string, number>()
|
||||
const objectUrlCache = new Map<string, string>()
|
||||
|
||||
async function checkAndUpdateImage(uniqueId: string, originalUrl: string, item: any) {
|
||||
try {
|
||||
const timestamp = Date.now()
|
||||
const separator = originalUrl.includes('?') ? '&' : '?'
|
||||
const fetchUrl = `${originalUrl}${separator}_t=${timestamp}`
|
||||
|
||||
const response = await fetch(fetchUrl)
|
||||
if (!response.ok)
|
||||
return
|
||||
const blob = await response.blob()
|
||||
|
||||
const prevSize = blobSizeCache.get(uniqueId)
|
||||
if (prevSize === blob.size) {
|
||||
return // 内容大小未变,认为图片没变,不更新 src,避免闪烁
|
||||
}
|
||||
|
||||
blobSizeCache.set(uniqueId, blob.size)
|
||||
const objectUrl = URL.createObjectURL(blob)
|
||||
|
||||
const oldUrl = objectUrlCache.get(uniqueId)
|
||||
if (oldUrl) {
|
||||
URL.revokeObjectURL(oldUrl)
|
||||
}
|
||||
objectUrlCache.set(uniqueId, objectUrl)
|
||||
|
||||
// 替换为本地 Blob URL,由于数据已在内存中,更新时不会闪烁
|
||||
item.AnswerValuePicture = objectUrl
|
||||
}
|
||||
catch (e) {
|
||||
console.error('Silent image update failed:', e)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取答题卡数据
|
||||
*/
|
||||
@ -366,13 +407,22 @@ async function fetchAnswerData() {
|
||||
// 强制更新图片 URL,防止缓存
|
||||
// 优先使用 ans 中的图片,如果没有则回退到 answerData 中的图片
|
||||
const imageUrl = ans.AnswerValuePicture || (parsedAnswers.length === 1 && parsedAnswers[0] === ans ? answerData.UserAnswerPicture : '')
|
||||
|
||||
const uniqueId = `${answerData.TeamId}-${ans.Guid}`
|
||||
let finalImageUrl = imageUrl
|
||||
|
||||
if (imageUrl) {
|
||||
if (oldAns && oldAns._originalUrl === imageUrl) {
|
||||
finalImageUrl = oldAns.AnswerValuePicture
|
||||
}
|
||||
else {
|
||||
finalImageUrl = imageUrl
|
||||
}
|
||||
}
|
||||
|
||||
const cleanBaseUrl = ''
|
||||
const timestamp = new Date().getTime()
|
||||
|
||||
finalImageUrl = `${finalImageUrl}?_t=${timestamp}`
|
||||
console.log(finalImageUrl, 'finalImageUrl')
|
||||
|
||||
// 判断是否手动干预:
|
||||
// 1. 本地存储有状态 (hasStoredStatus) 或有分数 (hasStoredScore)
|
||||
// 2. 内存中有手动标记 (oldAns._isManual)
|
||||
@ -402,6 +452,7 @@ async function fetchAnswerData() {
|
||||
QuestionDetailID: answerData.QuestionDetaiID, // [新增] 注意后端字段拼写
|
||||
AnswerText: ans.AnswerText,
|
||||
AnswerValuePicture: finalImageUrl,
|
||||
_originalUrl: imageUrl,
|
||||
_baseImgUrl: cleanBaseUrl,
|
||||
_t: timestamp, // 保存时间戳
|
||||
Score: finalScore,
|
||||
@ -410,17 +461,21 @@ async function fetchAnswerData() {
|
||||
_aiStatus: aiStatus,
|
||||
_aiScore: aiScore,
|
||||
}
|
||||
if (imageUrl) {
|
||||
checkAndUpdateImage(uniqueId, imageUrl, resultItem)
|
||||
}
|
||||
return resultItem
|
||||
}
|
||||
|
||||
// 如果没有手动编辑
|
||||
return {
|
||||
const resultItem = {
|
||||
...ans,
|
||||
TeamId: answerData.TeamId, // [新增] 注入 TeamId
|
||||
QuestionId: answerData.QuestionId, // [新增]
|
||||
QuestionDetailID: answerData.QuestionDetaiID, // [新增] 注意后端字段拼写
|
||||
AnswerText: ans.AnswerText,
|
||||
AnswerValuePicture: finalImageUrl,
|
||||
_originalUrl: imageUrl,
|
||||
_baseImgUrl: cleanBaseUrl,
|
||||
_t: timestamp, // 保存时间戳
|
||||
Status: ans.Status,
|
||||
@ -429,6 +484,10 @@ async function fetchAnswerData() {
|
||||
Score: null, // 默认 null
|
||||
_isManual: false,
|
||||
}
|
||||
if (imageUrl) {
|
||||
checkAndUpdateImage(uniqueId, imageUrl, resultItem)
|
||||
}
|
||||
return resultItem
|
||||
})
|
||||
|
||||
return {
|
||||
@ -466,9 +525,6 @@ async function handleNexCurrentQuestion() {
|
||||
currentQuestionId.value = currentQuestion.value?.QuestionID || currentQuestionId.value
|
||||
currentGroupId.value = currentQuestion.value?.TeamGroupID || currentGroupId.value
|
||||
}
|
||||
|
||||
// 更新当前时间戳,以便重新计算 canPublish
|
||||
nowTs.value = Date.now()
|
||||
}
|
||||
|
||||
function handlePublish() {
|
||||
@ -617,25 +673,23 @@ function startPolling() {
|
||||
}
|
||||
|
||||
fetchAnswerData() // 立即获取
|
||||
nowTs.value = Date.now()
|
||||
pollingTimer.value = setInterval(() => {
|
||||
// 每次轮询前再次检查是否过期
|
||||
const currentEndTime = (currentQuestion.value as any)?.EndTime
|
||||
if (currentEndTime) {
|
||||
// 增加 5s 缓冲时间
|
||||
const endTs = new Date(currentEndTime).getTime() + 3000
|
||||
// 增加 1s 缓冲时间
|
||||
const endTs = new Date(currentEndTime).getTime() + 1000
|
||||
if (Date.now() > endTs) {
|
||||
console.log('题目时间已到(含3s缓冲),停止轮询', currentEndTime)
|
||||
console.log('题目时间已到(含1s缓冲),停止轮询', currentEndTime)
|
||||
stopPolling()
|
||||
return
|
||||
}
|
||||
}
|
||||
nowTs.value = Date.now()
|
||||
|
||||
// 轮询时同时更新当前题目信息(获取最新的 EndTime),但不触发同步
|
||||
fetchCurrentQuestion(false)
|
||||
fetchAnswerData()
|
||||
}, 3000)
|
||||
}, 2000)
|
||||
}
|
||||
|
||||
function stopPolling() {
|
||||
|
||||
@ -117,6 +117,42 @@ async function checkNextStep() {
|
||||
}
|
||||
}
|
||||
|
||||
const blobSizeCache = new Map<string, number>()
|
||||
const objectUrlCache = new Map<string, string>()
|
||||
|
||||
async function checkAndUpdateImage(uniqueId: string, originalUrl: string, team: any) {
|
||||
try {
|
||||
const timestamp = Date.now()
|
||||
const separator = originalUrl.includes('?') ? '&' : '?'
|
||||
const fetchUrl = `${originalUrl}${separator}_t=${timestamp}`
|
||||
|
||||
const response = await fetch(fetchUrl)
|
||||
if (!response.ok)
|
||||
return
|
||||
const blob = await response.blob()
|
||||
|
||||
const prevSize = blobSizeCache.get(uniqueId)
|
||||
if (prevSize === blob.size) {
|
||||
return // 内容大小未变,认为图片没变,不更新 src,避免闪烁
|
||||
}
|
||||
|
||||
blobSizeCache.set(uniqueId, blob.size)
|
||||
const objectUrl = URL.createObjectURL(blob)
|
||||
|
||||
const oldUrl = objectUrlCache.get(uniqueId)
|
||||
if (oldUrl) {
|
||||
URL.revokeObjectURL(oldUrl)
|
||||
}
|
||||
objectUrlCache.set(uniqueId, objectUrl)
|
||||
|
||||
// 替换为本地 Blob URL,由于数据已在内存中,更新时不会闪烁
|
||||
team.UserAnswerPicture = objectUrl
|
||||
}
|
||||
catch (e) {
|
||||
console.error('Silent image update failed:', e)
|
||||
}
|
||||
}
|
||||
|
||||
/** 获取游戏现场统计结果 */
|
||||
async function fetchGetGameStatisticsData() {
|
||||
if (store.currentQuestionInfo && store.currentQuestionDetail) {
|
||||
@ -129,12 +165,25 @@ async function fetchGetGameStatisticsData() {
|
||||
const { data } = await fetchGetGameStatistics(_params)
|
||||
const rawTeams = (data?.data as any[]) || []
|
||||
|
||||
// 为每个队伍的图片 URL 添加时间戳,防止缓存
|
||||
teams.value = rawTeams.map((team) => {
|
||||
const uniqueId = team.TeamID || team.TeamName || Math.random().toString()
|
||||
team._uniqueId = uniqueId
|
||||
|
||||
if (team.UserAnswerPicture) {
|
||||
const timestamp = Date.now()
|
||||
const separator = team.UserAnswerPicture.includes('?') ? '&' : '?'
|
||||
team.UserAnswerPicture = `${team.UserAnswerPicture}${separator}_t=${timestamp}`
|
||||
const originalUrl = team.UserAnswerPicture
|
||||
const oldTeam = teams.value.find(t => t._uniqueId === uniqueId)
|
||||
|
||||
if (oldTeam && oldTeam.UserAnswerPicture && oldTeam._originalUrl === originalUrl) {
|
||||
// 保持原有的 URL,避免每次轮询都刷新
|
||||
team.UserAnswerPicture = oldTeam.UserAnswerPicture
|
||||
}
|
||||
else {
|
||||
team.UserAnswerPicture = originalUrl
|
||||
}
|
||||
team._originalUrl = originalUrl
|
||||
|
||||
// 后台静默获取最新图片并对比
|
||||
checkAndUpdateImage(uniqueId, originalUrl, team)
|
||||
}
|
||||
return team
|
||||
})
|
||||
@ -164,11 +213,11 @@ onBeforeUnmount(() => {
|
||||
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">
|
||||
<div class="relative h-full w-full flex flex-col items-center px-10 pt-10px 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">
|
||||
备注:评委正在评分中,请等待。。。
|
||||
备注:评委正在评分中,请等待...
|
||||
</div>
|
||||
|
||||
<div v-if="teams && teams.length > 0" class="grid grid-cols-4 h-full gap-6 pb-8">
|
||||
@ -177,15 +226,17 @@ onBeforeUnmount(() => {
|
||||
class="flex flex-col border-2 border-gray-200 rounded-xl bg-white/90 p-4 shadow-sm"
|
||||
>
|
||||
<div
|
||||
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 justify-between 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="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>
|
||||
</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>
|
||||
<span class="overflow-hidden text-ellipsis whitespace-nowrap text-lg text-white font-bold drop-shadow">{{ team.TeamName }}</span>
|
||||
<div class="flex shrink-0 gap-2">
|
||||
<span class="whitespace-nowrap rounded-full bg-green-100/90 px-3 py-1.5 text-sm">
|
||||
评委评分 <span class="text-lg text-orange-600 font-bold">{{ team.ResultPotins }}</span>
|
||||
</span>
|
||||
<span class="whitespace-nowrap rounded-full bg-orange-100/60 px-3 py-1.5 text-sm">
|
||||
AI评分 <span class="text-md text-orange-600 font-bold">{{ team.Points }}</span>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Answer Image Area -->
|
||||
|
||||
@ -288,7 +288,7 @@ onMounted(async () => {
|
||||
// [过冲状态]
|
||||
// 飞到眼前一点点 (Z=50px)
|
||||
// 角度稍微回弹 (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% {
|
||||
@ -328,8 +328,8 @@ onMounted(async () => {
|
||||
// [翻转状态]
|
||||
// rotateY(180deg): 绕Y轴旋转180度,实现翻面
|
||||
// scale(1.05): 翻转同时放大1.05倍,产生"向观众逼近"的视觉冲击力
|
||||
transform: rotateY(180deg) scale(1.06);
|
||||
box-shadow: 0 20px 40px -5px rgba(0, 0, 0, 0.3); // [动态阴影] 翻转浮起时阴影更深、更扩散
|
||||
transform: rotateY(180deg) scale(1.08);
|
||||
box-shadow: 0 10px 20px -5px rgba(0, 0, 0, 0.3); // [动态阴影] 翻转浮起时阴影更深、更扩散
|
||||
}
|
||||
}
|
||||
|
||||
@ -344,7 +344,7 @@ onMounted(async () => {
|
||||
|
||||
border-radius: 20px;
|
||||
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 {
|
||||
// background-color: #fff;
|
||||
transform: rotateY(180deg);
|
||||
transform: rotateY(200deg);
|
||||
// border: 4px solid #fff;
|
||||
|
||||
.card-content-design {
|
||||
@ -409,7 +409,7 @@ onMounted(async () => {
|
||||
// animation-delay: 0.2s; 确保卡片翻转到一半(正对屏幕)时才开始闪光,
|
||||
// 模拟光线随着角度变化掠过卡片表面的物理效果
|
||||
animation: shine-sweep 3s ease-out forwards;
|
||||
animation-delay: 0.2s;
|
||||
animation-delay: 1s;
|
||||
}
|
||||
}
|
||||
|
||||
@ -455,14 +455,14 @@ onMounted(async () => {
|
||||
|
||||
10% {
|
||||
// 刚进入时瞬间变亮
|
||||
opacity: 0.8;
|
||||
opacity: 0.8; // 0.8 是一个半透明值,模拟光束的透明度,值越大越透明
|
||||
}
|
||||
|
||||
100% {
|
||||
// 扫出视野
|
||||
top: 50%;
|
||||
left: 150%;
|
||||
opacity: 0;
|
||||
opacity: 0.6;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -40,11 +40,17 @@ function buildOption(list: BarDatum[]): ECOption {
|
||||
const correct = list.map(i => i.correct)
|
||||
|
||||
return {
|
||||
// 禁用动画,避免频繁刷新时的抖动
|
||||
// 启用动画,让柱子变化更平滑
|
||||
animation: false,
|
||||
animationDuration: 800,
|
||||
animationEasing: 'linear', // 动画缓动函数,平滑过渡,cubicOut|linear|quadOut|quadIn
|
||||
tooltip: {
|
||||
trigger: 'axis',
|
||||
axisPointer: { type: 'shadow' },
|
||||
backgroundColor: 'rgba(255, 255, 255, 0.9)',
|
||||
borderColor: '#3b82f6',
|
||||
borderWidth: 1,
|
||||
textStyle: { color: '#1e3a8a' },
|
||||
},
|
||||
legend: {
|
||||
data: ['答题数量', '预估得分'],
|
||||
@ -52,17 +58,18 @@ function buildOption(list: BarDatum[]): ECOption {
|
||||
right: 0,
|
||||
icon: 'circle',
|
||||
textStyle: {
|
||||
color: '#666',
|
||||
color: '#64748b',
|
||||
fontSize: 12,
|
||||
},
|
||||
},
|
||||
grid: { left: 16, right: 16, top: 40, bottom: 0, containLabel: true },
|
||||
grid: { left: 16, right: 16, top: 70, bottom: 0, containLabel: true },
|
||||
xAxis: {
|
||||
type: 'category',
|
||||
data: categories,
|
||||
axisTick: { show: false }, // 隐藏 x 轴刻度线
|
||||
axisLine: { show: false }, // 隐藏 x 轴线
|
||||
axisLabel: {
|
||||
color: '#003366', // 深蓝色字体
|
||||
color: '#1e3a8a', // 深蓝色字体
|
||||
fontWeight: 'bold',
|
||||
fontSize: 14,
|
||||
margin: 16,
|
||||
@ -82,6 +89,7 @@ function buildOption(list: BarDatum[]): ECOption {
|
||||
type: 'bar',
|
||||
data: total,
|
||||
barWidth: 24,
|
||||
barGap: '40%', // 柱子间的间隙
|
||||
itemStyle: {
|
||||
// 从上到下:浅蓝 -> 深蓝
|
||||
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
|
||||
@ -89,14 +97,17 @@ function buildOption(list: BarDatum[]): ECOption {
|
||||
{ offset: 1, color: '#3b82f6' }, // blue-500 (底部深色)
|
||||
]),
|
||||
borderRadius: [4, 4, 0, 0],
|
||||
shadowBlur: 10,
|
||||
shadowColor: 'rgba(59, 130, 246, 0.2)',
|
||||
shadowOffsetY: 4,
|
||||
},
|
||||
label: {
|
||||
show: true,
|
||||
position: 'top',
|
||||
color: '#003366', // 深蓝色
|
||||
color: '#1e3a8a', // 深蓝色
|
||||
fontWeight: 'bold',
|
||||
fontSize: 18,
|
||||
offset: [0, 2],
|
||||
fontSize: 16,
|
||||
offset: [0, -4],
|
||||
},
|
||||
},
|
||||
{
|
||||
@ -111,14 +122,17 @@ function buildOption(list: BarDatum[]): ECOption {
|
||||
{ offset: 1, color: '#f97316' }, // orange-500 (底部深色)
|
||||
]),
|
||||
borderRadius: [4, 4, 0, 0],
|
||||
shadowBlur: 10,
|
||||
shadowColor: 'rgba(249, 115, 22, 0.2)',
|
||||
shadowOffsetY: 4,
|
||||
},
|
||||
label: {
|
||||
show: true,
|
||||
position: 'top',
|
||||
color: '#ea580c', // orange-600
|
||||
fontWeight: 'bold',
|
||||
fontSize: 18,
|
||||
offset: [0, 2],
|
||||
fontSize: 16,
|
||||
offset: [0, -4],
|
||||
},
|
||||
},
|
||||
],
|
||||
|
||||
@ -185,7 +185,7 @@ watch(
|
||||
>
|
||||
<!-- 上方:词组 -->
|
||||
<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 }}
|
||||
</div>
|
||||
</div>
|
||||
@ -215,9 +215,9 @@ watch(
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 模板: 诗词常识 -->
|
||||
<!-- 模板: 加时赛诗词常识 -->
|
||||
<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>
|
||||
</div>
|
||||
@ -445,8 +445,7 @@ watch(
|
||||
:deep(p),
|
||||
:deep(span),
|
||||
:deep(div) {
|
||||
font-size: 2.2rem;
|
||||
/* text-5xl */
|
||||
font-size: 2rem;
|
||||
}
|
||||
}
|
||||
|
||||
@ -494,15 +493,14 @@ watch(
|
||||
.association-word {
|
||||
background: url('@/assets/imgs/user/dui-kuang.png') no-repeat center;
|
||||
background-size: 100% 100%;
|
||||
min-width: 160px;
|
||||
min-width: 170px;
|
||||
height: 70px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 32px;
|
||||
font-weight: bold;
|
||||
color: white;
|
||||
padding: 0 20px;
|
||||
letter-spacing: 0.2em;
|
||||
}
|
||||
|
||||
.association-char {
|
||||
|
||||
@ -157,13 +157,13 @@ function rowClassName(row: TeamData) {
|
||||
<template>
|
||||
<CompetitionLayout :show-back="false" :show-next="false" :show-title="false">
|
||||
<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" />
|
||||
<!-- <p class="mt--16px text-center text-18px text-#6b778d">
|
||||
"勤学如春起之苗,不见其增,日有所长"
|
||||
</p> -->
|
||||
<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"
|
||||
/>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user