feat: 新增测试页面并优化用户界面及API调用
- 新增测试页面 `/test`,用于展示题目答案的交互式网格和列表布局 - 为 CompetitionLayout 组件添加标题背景类型支持,优化视觉一致性 - 更新 `fetchUpdateCurrentQuestionUse` API 参数,简化调用逻辑 - 优化用户界面细节,包括图标替换、样式调整和布局改进
This commit is contained in:
26
apps/admin/src/assets/imgs/user/event-card-bg-icon.svg
Normal file
26
apps/admin/src/assets/imgs/user/event-card-bg-icon.svg
Normal file
File diff suppressed because one or more lines are too long
|
After Width: | Height: | Size: 2.6 MiB |
File diff suppressed because one or more lines are too long
|
Before Width: | Height: | Size: 825 KiB After Width: | Height: | Size: 1.2 MiB |
21
apps/admin/src/assets/imgs/user/title-bg2.svg
Normal file
21
apps/admin/src/assets/imgs/user/title-bg2.svg
Normal file
File diff suppressed because one or more lines are too long
|
After Width: | Height: | Size: 4.0 MiB |
@ -1,7 +1,9 @@
|
||||
<script lang="ts" setup>
|
||||
import VScaleScreen from 'v-scale-screen'
|
||||
import { onMounted, ref } from 'vue'
|
||||
import { computed, onMounted, ref } from 'vue'
|
||||
import _defaultBg from '@/assets/imgs/user/home-bg.svg'
|
||||
import titleBg2 from '@/assets/imgs/user/title-bg2.svg'
|
||||
import _defaultTitleBg from '@/assets/imgs/user/title-bg.svg'
|
||||
import { useRouterPush } from '@/hooks/common/router'
|
||||
|
||||
interface Props {
|
||||
@ -25,6 +27,8 @@ interface Props {
|
||||
btnTheme?: 'primary' | 'light'
|
||||
/** 是否禁用下一步按钮 */
|
||||
nextDisabled?: boolean
|
||||
/** 标题区域背景图片URL,不传则使用默认 title-bg.svg */
|
||||
titleBgType?: number
|
||||
}
|
||||
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
@ -38,6 +42,7 @@ const props = withDefaults(defineProps<Props>(), {
|
||||
backBtnText: undefined,
|
||||
btnTheme: 'primary',
|
||||
nextDisabled: false,
|
||||
titleBgType: 1,
|
||||
})
|
||||
|
||||
const emit = defineEmits<{
|
||||
@ -45,8 +50,15 @@ const emit = defineEmits<{
|
||||
(e: 'next'): void
|
||||
}>()
|
||||
|
||||
const titleBgUrlMapping: Record<number, string> = {
|
||||
1: _defaultTitleBg,
|
||||
2: titleBg2,
|
||||
}
|
||||
|
||||
const { routerPushByKey } = useRouterPush()
|
||||
|
||||
const titleBgUrl = computed(() => titleBgUrlMapping[props.titleBgType] || _defaultBg)
|
||||
|
||||
// const router = useRouter()
|
||||
const innerBgUrl = ref(_defaultBg)
|
||||
|
||||
@ -108,7 +120,7 @@ onMounted(() => {
|
||||
<section v-if="showTitle" class="title-section">
|
||||
<Transition name="fade-slide-down" appear>
|
||||
<div v-if="showContent" class="title-section">
|
||||
<div class="scroll-bg">
|
||||
<div class="scroll-bg" :style="{ backgroundImage: `url(${titleBgUrl})` }">
|
||||
<h1 class="main-title">
|
||||
{{ title }}
|
||||
</h1>
|
||||
@ -123,16 +135,20 @@ onMounted(() => {
|
||||
</main>
|
||||
|
||||
<!-- Footer Action -->
|
||||
<footer class="page-footer w-full flex items-center justify-between px-20" :class="[actionPosition, btnTheme]">
|
||||
<button class="action-btn back-btn" :class="{ 'text-btn': backBtnText }" :style="{ visibility: showBack ? 'visible' : 'hidden' }" @click="handleBack">
|
||||
<footer
|
||||
class="page-footer w-full flex items-center justify-between px-20"
|
||||
:class="[actionPosition, btnTheme]"
|
||||
>
|
||||
<button
|
||||
class="action-btn back-btn" :class="{ 'text-btn': backBtnText }"
|
||||
:style="{ visibility: showBack ? 'visible' : 'hidden' }" @click="handleBack"
|
||||
>
|
||||
<span v-if="backBtnText" class="btn-text">{{ backBtnText }}</span>
|
||||
<SvgIcon v-else icon="mdi:arrow-left" class="arrow-icon" />
|
||||
</button>
|
||||
|
||||
<button
|
||||
v-if="showNext"
|
||||
class="action-btn next-btn text-btn"
|
||||
:class="{ 'is-disabled': nextDisabled }"
|
||||
v-if="showNext" class="action-btn next-btn text-btn" :class="{ 'is-disabled': nextDisabled }"
|
||||
@click="handleNext"
|
||||
>
|
||||
<span class="btn-text">{{ nextBtnText || '下一步' }}</span>
|
||||
@ -148,14 +164,14 @@ onMounted(() => {
|
||||
<style lang="scss" scoped>
|
||||
.title-section {
|
||||
margin: 10px auto;
|
||||
width: 405px;
|
||||
height: 150px;
|
||||
width: 412px;
|
||||
height: 165px;
|
||||
|
||||
.scroll-bg {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
position: relative;
|
||||
background: url('@/assets/imgs/user/title-bg.svg') no-repeat center center;
|
||||
background: no-repeat center center;
|
||||
background-size: 100% 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
@ -31,6 +31,7 @@ export const views: Record<LastLevelRouteKey, RouteComponent | (() => Promise<Ro
|
||||
results: () => import("@/views/results/index.vue"),
|
||||
"template_template-detail": () => import("@/views/template/template-detail/index.vue"),
|
||||
"template_template-list": () => import("@/views/template/template-list/index.vue"),
|
||||
test: () => import("@/views/test/index.vue"),
|
||||
user_analysis: () => import("@/views/user/analysis/index.vue"),
|
||||
user_cover: () => import("@/views/user/cover/index.vue"),
|
||||
user_draw: () => import("@/views/user/draw/index.vue"),
|
||||
|
||||
@ -223,6 +223,15 @@ export const generatedRoutes: GeneratedRoute[] = [
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: 'test',
|
||||
path: '/test',
|
||||
component: 'layout.base$view.test',
|
||||
meta: {
|
||||
title: 'test',
|
||||
i18nKey: 'route.test'
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'user',
|
||||
path: '/user',
|
||||
|
||||
@ -182,6 +182,7 @@ const routeMap: RouteMap = {
|
||||
"template": "/template",
|
||||
"template_template-detail": "/template/template-detail",
|
||||
"template_template-list": "/template/template-list",
|
||||
"test": "/test",
|
||||
"user": "/user",
|
||||
"user_analysis": "/user/analysis",
|
||||
"user_cover": "/user/cover",
|
||||
|
||||
@ -1,10 +1,10 @@
|
||||
import { request } from '../request'
|
||||
|
||||
/** 评委消费题目,表示用了该题目 */
|
||||
export function fetchUpdateCurrentQuestionUse(data: Api.Competition.GetCurrentQuestionParams) {
|
||||
export function fetchUpdateCurrentQuestionUse(TeamGroupID: string) {
|
||||
return request<App.Service.Response>({
|
||||
url: `/Base/ActivityMain/UpdateCurrentQuestionUse?ActivityID=${data.ActivityID}&GroupID=${data.GroupID}&RoundType=${data.RoundType}&isUse=${data.isUse}`,
|
||||
url: `/Base/ActivityMain/UpdateCurrentQuestionUse?TeamGroupID=${TeamGroupID}`,
|
||||
method: 'post',
|
||||
data,
|
||||
data: { TeamGroupID },
|
||||
})
|
||||
}
|
||||
|
||||
3
apps/admin/src/typings/elegant-router.d.ts
vendored
3
apps/admin/src/typings/elegant-router.d.ts
vendored
@ -36,6 +36,7 @@ declare module "@elegant-router/types" {
|
||||
"template": "/template";
|
||||
"template_template-detail": "/template/template-detail";
|
||||
"template_template-list": "/template/template-list";
|
||||
"test": "/test";
|
||||
"user": "/user";
|
||||
"user_analysis": "/user/analysis";
|
||||
"user_cover": "/user/cover";
|
||||
@ -88,6 +89,7 @@ declare module "@elegant-router/types" {
|
||||
| "rank"
|
||||
| "results"
|
||||
| "template"
|
||||
| "test"
|
||||
| "user"
|
||||
>;
|
||||
|
||||
@ -121,6 +123,7 @@ declare module "@elegant-router/types" {
|
||||
| "results"
|
||||
| "template_template-detail"
|
||||
| "template_template-list"
|
||||
| "test"
|
||||
| "user_analysis"
|
||||
| "user_cover"
|
||||
| "user_draw"
|
||||
|
||||
@ -2,15 +2,20 @@
|
||||
import { useIntervalFn } from '@vueuse/core'
|
||||
import { NButton } from 'naive-ui'
|
||||
import { storeToRefs } from 'pinia'
|
||||
import { onUnmounted, ref } from 'vue'
|
||||
import { computed, onUnmounted, ref } from 'vue'
|
||||
import { useRoute } from 'vue-router'
|
||||
import { fetchUpdateCurrentQuestionUse } from '@/service/api/result'
|
||||
import { useActivityInfoStore } from '@/store/modules/activityinfo'
|
||||
import GroupTabs, { type GroupItem } from './modules/GroupTabs.vue'
|
||||
import TeamResultCard, { type AICharacter, type TeamResult } from './modules/TeamResultCard.vue'
|
||||
|
||||
const activityInfoStore = useActivityInfoStore()
|
||||
// eslint-disable-next-line unused-imports/no-unused-vars
|
||||
const { activityId, groupId } = storeToRefs(activityInfoStore)
|
||||
|
||||
const route = useRoute()
|
||||
const TeamGroupID = computed(() => route.query?.TeamGroupID as string)
|
||||
|
||||
// --- 模拟数据和状态 ---
|
||||
|
||||
const groups = ref<GroupItem[]>(Array.from({ length: 8 }).map((_, i) => ({
|
||||
@ -173,19 +178,15 @@ function handleNext() {
|
||||
}
|
||||
|
||||
function handlePublish() {
|
||||
fetchGetQuestionDetailData()
|
||||
window.$message?.success('结果已发布')
|
||||
if (TeamGroupID.value) {
|
||||
fetchGetQuestionDetailData()
|
||||
window.$message?.success('结果已发布')
|
||||
}
|
||||
}
|
||||
|
||||
async function fetchGetQuestionDetailData() {
|
||||
const params = {
|
||||
ActivityID: Number(activityId.value),
|
||||
GroupID: Number(groupId.value),
|
||||
RoundType: 0 as Api.Competition.CompetitionRoundType,
|
||||
}
|
||||
|
||||
try {
|
||||
const { data: outlineData, error } = await fetchUpdateCurrentQuestionUse({ ...params, isUse: true })
|
||||
const { data: outlineData, error } = await fetchUpdateCurrentQuestionUse(TeamGroupID.value)
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(outlineData, 'outlineData')
|
||||
if (error) {
|
||||
|
||||
@ -131,7 +131,7 @@ async function handleSave() {
|
||||
|
||||
const params: Api.Template.AddTemplateParams = {
|
||||
id,
|
||||
pageNo: '1',
|
||||
pageNo: '1761.172.8.66',
|
||||
name: templateInfo.value.name,
|
||||
backGroundUrl: templateInfo.value.backGroundUrl || '',
|
||||
width: Math.round(templateInfo.value.width),
|
||||
|
||||
229
apps/admin/src/views/test/index.vue
Normal file
229
apps/admin/src/views/test/index.vue
Normal file
@ -0,0 +1,229 @@
|
||||
<script lang="ts" setup>
|
||||
import { Icon } from '@iconify/vue'
|
||||
import { NCard, NImage, NSpace } from 'naive-ui'
|
||||
import { ref, watch } from 'vue'
|
||||
|
||||
interface AnswerItem {
|
||||
id: number
|
||||
label?: string
|
||||
imageUrl: string // 在真实场景中是学生答题截图的URL
|
||||
status: 'correct' | 'wrong' // 初始状态由大模型判定
|
||||
type: 'grid' | 'line' // 'grid'对应方格题(如汉字),'line'对应横线题(如词语)
|
||||
}
|
||||
|
||||
interface QuestionGroup {
|
||||
id: number
|
||||
title: string
|
||||
items: AnswerItem[]
|
||||
layout: 'grid' | 'list' // 布局方式
|
||||
}
|
||||
|
||||
interface Round {
|
||||
id: number
|
||||
title: string
|
||||
subTitle?: string
|
||||
groups: QuestionGroup[]
|
||||
}
|
||||
|
||||
// 模拟数据
|
||||
const rounds = ref<Round[]>([
|
||||
{
|
||||
id: 1,
|
||||
title: '第一轮',
|
||||
subTitle: '汉字大比拼',
|
||||
groups: [
|
||||
{
|
||||
id: 101,
|
||||
title: '汉字听写 1',
|
||||
layout: 'grid',
|
||||
items: [
|
||||
{ id: 1, label: '1', imageUrl: 'https://placehold.co/100x100?text=汉', status: 'correct', type: 'grid' },
|
||||
{ id: 2, label: '2', imageUrl: 'https://placehold.co/100x100?text=字', status: 'correct', type: 'grid' },
|
||||
{ id: 3, label: '3', imageUrl: 'https://placehold.co/100x100?text=听', status: 'correct', type: 'grid' },
|
||||
{ id: 4, label: '4', imageUrl: 'https://placehold.co/100x100?text=写', status: 'correct', type: 'grid' },
|
||||
{ id: 5, label: '5', imageUrl: 'https://placehold.co/100x100?text=一', status: 'correct', type: 'grid' },
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 102,
|
||||
title: '汉字听写 2',
|
||||
layout: 'grid',
|
||||
items: [
|
||||
{ id: 6, label: '1', imageUrl: 'https://placehold.co/100x100?text=错', status: 'wrong', type: 'grid' },
|
||||
{ id: 7, label: '2', imageUrl: 'https://placehold.co/100x100?text=误', status: 'wrong', type: 'grid' },
|
||||
{ id: 8, label: '3', imageUrl: 'https://placehold.co/100x100?text=示', status: 'wrong', type: 'grid' },
|
||||
{ id: 9, label: '4', imageUrl: 'https://placehold.co/100x100?text=例', status: 'wrong', type: 'grid' },
|
||||
{ id: 10, label: '5', imageUrl: 'https://placehold.co/100x100?text=!', status: 'wrong', type: 'grid' },
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 103,
|
||||
title: '汉字加一加',
|
||||
layout: 'grid',
|
||||
items: Array.from({ length: 10 }).map((_, i) => ({
|
||||
id: 20 + i,
|
||||
imageUrl: `https://placehold.co/100x100?text=${i + 1}`,
|
||||
status: i === 4 ? 'wrong' : 'correct', // 第5个模拟错误
|
||||
type: 'grid',
|
||||
})),
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
title: '第一轮',
|
||||
subTitle: '词语大比拼',
|
||||
groups: [
|
||||
{
|
||||
id: 201,
|
||||
title: '词语听写',
|
||||
layout: 'list',
|
||||
items: [
|
||||
{ id: 301, label: '1.', imageUrl: 'https://placehold.co/400x60?text=词语答案一', status: 'correct', type: 'line' },
|
||||
{ id: 302, label: '2.', imageUrl: 'https://placehold.co/400x60?text=词语答案二', status: 'correct', type: 'line' },
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 202,
|
||||
title: '成语写一写 1',
|
||||
layout: 'list',
|
||||
items: [
|
||||
{ id: 303, label: '1.', imageUrl: 'https://placehold.co/200x60?text=成语一', status: 'correct', type: 'line' },
|
||||
{ id: 304, label: '2.', imageUrl: 'https://placehold.co/200x60?text=成语二', status: 'wrong', type: 'line' },
|
||||
{ id: 305, label: '3.', imageUrl: 'https://placehold.co/200x60?text=成语三', status: 'wrong', type: 'line' },
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 203,
|
||||
title: '成语写一写 2',
|
||||
layout: 'list',
|
||||
items: [
|
||||
{ id: 306, label: '1.', imageUrl: 'https://placehold.co/600x60?text=长成语答案测试', status: 'correct', type: 'line' },
|
||||
{ id: 307, label: '2.', imageUrl: 'https://placehold.co/600x60?text=另一个答案', status: 'correct', type: 'line' },
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
])
|
||||
|
||||
// 切换状态逻辑:点击后 Correct <-> Wrong
|
||||
function toggleStatus(item: AnswerItem) {
|
||||
item.status = item.status === 'correct' ? 'wrong' : 'correct'
|
||||
}
|
||||
|
||||
watch(() => rounds.value, (val) => {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(val, 'v')
|
||||
}, {
|
||||
deep: true,
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="min-h-screen bg-gray-50 p-4">
|
||||
<NSpace vertical size="large">
|
||||
<NCard v-for="round in rounds" :key="round.id" :title="`${round.title} · ${round.subTitle}`" size="huge">
|
||||
<div class="flex flex-col gap-8">
|
||||
<div v-for="group in round.groups" :key="group.id">
|
||||
<h3 class="mb-4 text-lg text-gray-700 font-medium">
|
||||
{{ group.title }}
|
||||
</h3>
|
||||
|
||||
<!-- Grid Layout (Grid Items) -->
|
||||
<div v-if="group.layout === 'grid'" class="flex flex-wrap gap-4">
|
||||
<div
|
||||
v-for="item in group.items"
|
||||
:key="item.id"
|
||||
class="group relative cursor-pointer transition-all duration-200"
|
||||
@click="toggleStatus(item)"
|
||||
>
|
||||
<!-- Image Container with Status Border -->
|
||||
<div
|
||||
class="relative overflow-hidden border-2 rounded-md border-dashed bg-white p-1"
|
||||
:class="[
|
||||
item.status === 'correct' ? 'border-green-500' : 'border-red-500',
|
||||
]"
|
||||
>
|
||||
<NImage
|
||||
:src="item.imageUrl"
|
||||
preview-disabled
|
||||
object-fit="contain"
|
||||
:class="group.layout === 'grid' ? 'w-24 h-24' : ''"
|
||||
/>
|
||||
|
||||
<!-- Status Icon Overlay -->
|
||||
<div class="absolute z-10 rounded-full bg-white -right-3 -top-3">
|
||||
<Icon
|
||||
v-if="item.status === 'correct'"
|
||||
icon="mdi:check-circle"
|
||||
class="text-2xl text-green-500"
|
||||
/>
|
||||
<Icon
|
||||
v-else
|
||||
icon="mdi:close-circle"
|
||||
class="text-2xl text-red-500"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Label if exists -->
|
||||
<div v-if="item.label" class="mt-1 text-center text-sm text-gray-500">
|
||||
{{ item.label }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- List Layout (Line Items) -->
|
||||
<div v-else class="flex flex-col gap-4">
|
||||
<!-- Using a grid for lines to handle multiple per row if needed, or just flex-wrap -->
|
||||
<div class="flex flex-wrap gap-x-8 gap-y-4">
|
||||
<div
|
||||
v-for="item in group.items"
|
||||
:key="item.id"
|
||||
class="relative cursor-pointer transition-all duration-200"
|
||||
@click="toggleStatus(item)"
|
||||
>
|
||||
<div class="flex items-center gap-2">
|
||||
<span v-if="item.label" class="w-6 text-gray-600 font-medium">{{ item.label }}</span>
|
||||
|
||||
<div
|
||||
class="relative overflow-hidden border-2 rounded-md border-dashed bg-white px-2 py-1"
|
||||
:class="[
|
||||
item.status === 'correct' ? 'border-green-500' : 'border-red-500',
|
||||
]"
|
||||
>
|
||||
<NImage
|
||||
:src="item.imageUrl"
|
||||
preview-disabled
|
||||
object-fit="contain"
|
||||
height="50"
|
||||
/>
|
||||
|
||||
<!-- Status Icon Overlay -->
|
||||
<div class="absolute z-10 rounded-full bg-white shadow-sm -right-3 -top-3">
|
||||
<Icon
|
||||
v-if="item.status === 'correct'"
|
||||
icon="mdi:check-circle"
|
||||
class="text-2xl text-green-500"
|
||||
/>
|
||||
<Icon
|
||||
v-else
|
||||
icon="mdi:close-circle"
|
||||
class="text-2xl text-red-500"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</NCard>
|
||||
</NSpace>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
/* Ensure icons are visible and positioned correctly */
|
||||
</style>
|
||||
@ -134,7 +134,8 @@ onMounted(async () => {
|
||||
|
||||
<template>
|
||||
<CompetitionLayout
|
||||
:show-back="true" :show-next="showNextButton" :title="activityName" @back="handleBack"
|
||||
:show-back="true" :show-next="showNextButton" :title="activityName" :title-bg-type="2"
|
||||
@back="handleBack"
|
||||
@next="handleNext"
|
||||
>
|
||||
<div class="h-screen w-full overflow-y-auto font-sans">
|
||||
|
||||
@ -70,24 +70,15 @@ onMounted(() => {
|
||||
|
||||
<template>
|
||||
<CompetitionLayout
|
||||
:show-back="true"
|
||||
:show-next="isAllEnd"
|
||||
next-btn-text="查看队伍结果"
|
||||
title="展示组别"
|
||||
@back="handleBack"
|
||||
@next="handleNext"
|
||||
:show-back="true" :show-next="isAllEnd" next-btn-text="查看队伍结果" :title-bg-type="2"
|
||||
title="展示组别" @back="handleBack" @next="handleNext"
|
||||
>
|
||||
<!-- Groups Grid -->
|
||||
<div class="groups-container">
|
||||
<TransitionGroup name="list-anim" tag="div" class="groups-grid">
|
||||
<div
|
||||
v-for="(item, index) in groups"
|
||||
v-show="showContent"
|
||||
:key="item.Id"
|
||||
class="group-item"
|
||||
:class="{ 'is-disabled': item.IsEnd }"
|
||||
:style="{ '--delay': `${index * 0.05}s` }"
|
||||
@click="selectGroup(item)"
|
||||
v-for="(item, index) in groups" v-show="showContent" :key="item.Id" class="group-item"
|
||||
:class="{ 'is-disabled': item.IsEnd }" :style="{ '--delay': `${index * 0.05}s` }" @click="selectGroup(item)"
|
||||
>
|
||||
<div class="icon-wrapper">
|
||||
<div class="flower-bg" />
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
<script lang="ts" setup>
|
||||
import { NCarousel } from 'naive-ui'
|
||||
import { NCarousel, NImage } from 'naive-ui'
|
||||
import { computed, onMounted, ref } from 'vue'
|
||||
import beacon from '@/assets/imgs/user/event-card-bg-icon.svg'
|
||||
import CompetitionLayout from '@/components/custom/user/CompetitionLayout.vue'
|
||||
import { useRouterPush } from '@/hooks/common/router'
|
||||
import { fetchGetActivityList } from '@/service/api/competition'
|
||||
@ -81,7 +82,8 @@ onMounted(() => {
|
||||
<template>
|
||||
<CompetitionLayout
|
||||
:show-back="false" :show-next="false" title="赛事总览" action-position="top" back-btn-text="返回"
|
||||
btn-theme="light" @back="handleBack" @next="handleNext"
|
||||
btn-theme="light" :title-bg-type="2" @back="handleBack"
|
||||
@next="handleNext"
|
||||
>
|
||||
<!-- Cards Section -->
|
||||
<div class="cards-container">
|
||||
@ -106,7 +108,11 @@ onMounted(() => {
|
||||
<div class="card-top-bar" />
|
||||
<div class="card-body">
|
||||
<div class="icon-wrapper">
|
||||
<SvgIcon :local-icon="item.icon" class="event-icon" />
|
||||
<NImage
|
||||
:src="beacon"
|
||||
preview-disabled
|
||||
object-fit="contain"
|
||||
/>
|
||||
</div>
|
||||
<div class="text-content">
|
||||
<h3 class="event-title">
|
||||
@ -168,20 +174,12 @@ onMounted(() => {
|
||||
}
|
||||
|
||||
.icon-wrapper {
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
background: rgba(255, 255, 255, 0.6);
|
||||
border-radius: 50%;
|
||||
width: 170px;
|
||||
height: 161px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin-bottom: 30px;
|
||||
box-shadow: 0 4px 10px rgba(0, 0, 0, 0.05);
|
||||
|
||||
.event-icon {
|
||||
font-size: 48px;
|
||||
color: $secondary-color;
|
||||
}
|
||||
margin: 30px 0;
|
||||
}
|
||||
|
||||
.text-content {
|
||||
@ -203,8 +201,8 @@ onMounted(() => {
|
||||
transform: translateY(-10px);
|
||||
|
||||
.icon-wrapper {
|
||||
transform: scale(1.1) rotate(5deg);
|
||||
transition: transform 0.4s cubic-bezier(0.175, 0.885, 0.32, 1.275);
|
||||
transform: scale(1.1) rotate(2deg);
|
||||
transition: transform 0.8s cubic-bezier(0.175, 0.885, 0.32, 1.275);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -62,8 +62,6 @@ function handleNext() {
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import '@/styles/scss/variables.scss';
|
||||
|
||||
.rules-content-wrapper {
|
||||
width: 100%;
|
||||
max-height: 80%;
|
||||
@ -76,7 +74,6 @@ function handleNext() {
|
||||
margin-top: 10px;
|
||||
font-size: 28px;
|
||||
line-height: 2;
|
||||
// color: #5d4037; // Dark brown/grey text
|
||||
|
||||
.intro-text {
|
||||
margin-bottom: 30px;
|
||||
|
||||
Reference in New Issue
Block a user