feat(user): 重构用户端竞赛流程,集成后端API并优化交互体验
- 新增 `activityinfo` store 管理活动信息,支持持久化 - 重构 `competition` store,分离数据层与流程控制,新增音效管理 - 新增游戏API模块 (`game.ts`),实现抽题、题目详情、提交结果等接口 - 用户端页面全面对接后端数据:首页轮播展示活动列表,组别/队伍页动态加载,封面页显示题目卡片 - 抽题页改为竹签翻转动画,游戏页集成题目详情与倒计时 - 优化布局组件,支持点击返回首页,统一路由参数传递 - 更新类型定义,支持富文本题目渲染 - 添加 `activityinfo` 拼写检查词条
This commit is contained in:
@ -1,9 +1,12 @@
|
||||
<script lang="ts" setup>
|
||||
import { onMounted, ref } from 'vue'
|
||||
import { useRoute } from 'vue-router'
|
||||
import CompetitionLayout from '@/components/custom/user/CompetitionLayout.vue'
|
||||
import { useRouterPush } from '@/hooks/common/router'
|
||||
import { fetchGetTeamListByGroupId } from '@/service/api/competition'
|
||||
|
||||
const { routerPushByKey } = useRouterPush()
|
||||
const { routerPushByKey, routerBack } = useRouterPush()
|
||||
const route = useRoute()
|
||||
|
||||
interface TeamItem {
|
||||
id: number
|
||||
@ -11,17 +14,40 @@ interface TeamItem {
|
||||
icon: string
|
||||
}
|
||||
|
||||
const teams = ref<TeamItem[]>([
|
||||
{ id: 1, name: '1号代表队', icon: 'star' },
|
||||
{ id: 2, name: '2号代表队', icon: 'star' },
|
||||
{ id: 3, name: '3号代表队', icon: 'star' },
|
||||
{ id: 4, name: '4号代表队', icon: 'star' },
|
||||
])
|
||||
const teams = ref<TeamItem[]>([])
|
||||
const loading = ref(false)
|
||||
const activityId = route.query.activityId
|
||||
const groupsId = route.query.groupsId
|
||||
|
||||
async function getTeams() {
|
||||
if (!groupsId)
|
||||
return
|
||||
|
||||
loading.value = true
|
||||
try {
|
||||
const { data, error } = await fetchGetTeamListByGroupId(Number(groupsId))
|
||||
if (error) {
|
||||
window?.$message?.error(error.message)
|
||||
return
|
||||
}
|
||||
const list = data?.data || []
|
||||
if (list && Array.isArray(list)) {
|
||||
teams.value = list.map((item: any) => ({
|
||||
id: item.Id,
|
||||
name: item.Name,
|
||||
icon: 'star', // Default icon
|
||||
}))
|
||||
}
|
||||
}
|
||||
finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
const showContent = ref(false)
|
||||
|
||||
function handleBack() {
|
||||
routerPushByKey('user_groups')
|
||||
routerBack()
|
||||
}
|
||||
|
||||
function handleNext() {
|
||||
@ -31,12 +57,13 @@ function handleNext() {
|
||||
|
||||
function selectTeam(_id: number) {
|
||||
// 选择队伍逻辑
|
||||
routerPushByKey('user_cover', { query: { id: _id.toString() } })
|
||||
routerPushByKey('user_cover', { query: { activityId, groupsId, teamId: _id } })
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
setTimeout(() => {
|
||||
showContent.value = true
|
||||
getTeams()
|
||||
}, 100)
|
||||
})
|
||||
</script>
|
||||
@ -61,8 +88,7 @@ onMounted(() => {
|
||||
<TransitionGroup name="list-anim" tag="div" class="teams-grid">
|
||||
<div
|
||||
v-for="(item, index) in teams" v-show="showContent" :key="item.id" class="team-item"
|
||||
:style="{ '--delay': `${index * 0.1}s` }"
|
||||
@click="selectTeam(item.id)"
|
||||
:style="{ '--delay': `${index * 0.1}s` }" @click="selectTeam(item.id)"
|
||||
>
|
||||
<div class="icon-wrapper">
|
||||
<img src="@/assets/imgs/user/star-icon.svg" alt="team-icon" class="h-full w-full object-cover">
|
||||
|
||||
Reference in New Issue
Block a user