feat(admin): 新增用户排行榜功能并优化活动流程
- 新增用户排行榜页面和待发布页面,支持查看和发布排行榜 - 新增排行榜相关API接口,包括获取活动排行列表、修改队伍分数、发布排名和获取用户排名列表 - 新增RankPublishStatus枚举,用于管理排行榜发布状态 - 在活动卡片中新增结束活动按钮,点击后调用结束活动接口并生成排行榜数据 - 优化用户活动首页,只显示已发布和处理中的活动 - 调整游戏页面定时刷新间隔从2秒改为3秒,优化性能 - 修复排行榜详情页分数输入最大值限制问题 - 清理未使用的代码文件,移除results-detail-copy相关组件和路由 - 更新路由配置和类型定义,支持新的排行榜页面
This commit is contained in:
@ -3,6 +3,7 @@ import { NButton, NGi, NGrid, NSpace } from 'naive-ui'
|
||||
import { computed, onMounted, ref } from 'vue'
|
||||
import { useRouterPush } from '@/hooks/common/router'
|
||||
import { fetchCopyActivity, fetchDeleteActivity, fetchGetActivityList } from '@/service/api/competition'
|
||||
import { endActivity } from '@/service/api/result'
|
||||
import { useAppStore } from '@/store/modules/app'
|
||||
import CompetitionAddModal from '../competition-add/index.vue'
|
||||
|
||||
@ -94,6 +95,39 @@ function toDetail(item: Api.Competition.CompetitionItem) {
|
||||
routerPushByKey('competition_competition-detail', { query: { Id: item.Id.toString() } })
|
||||
}
|
||||
|
||||
async function handleCloseActivity(item: Api.Competition.CompetitionItem) {
|
||||
const d = window.$dialog?.warning({
|
||||
title: '确认结束',
|
||||
content: `确定结束活动:${item.Name}吗?结束活动后将生成排行榜数据。`,
|
||||
positiveText: '确认结束',
|
||||
negativeText: '取消',
|
||||
onPositiveClick: async () => {
|
||||
if (d) {
|
||||
d.loading = true
|
||||
}
|
||||
try {
|
||||
const { error } = await endActivity(item.Id)
|
||||
if (error) {
|
||||
window.$message?.error(error.message || '结束活动失败')
|
||||
return false
|
||||
}
|
||||
window.$message?.success(`已结束活动:${item.Name}`)
|
||||
fetchActivityList()
|
||||
return true
|
||||
}
|
||||
catch (e: any) {
|
||||
window.$message?.error(e.message || '操作失败')
|
||||
return false
|
||||
}
|
||||
finally {
|
||||
if (d) {
|
||||
d.loading = false
|
||||
}
|
||||
}
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
onMounted(() => fetchActivityList())
|
||||
</script>
|
||||
|
||||
@ -122,7 +156,7 @@ onMounted(() => fetchActivityList())
|
||||
<!-- 响应式布局:手机1列,平板2列,中屏3列,大屏4列 -->
|
||||
<NGrid :x-gap="gap" :y-gap="gap" responsive="screen" item-responsive>
|
||||
<NGi v-for="item in competitionListRef" :key="item.Id" span="24 s:12 m:8 l:6" @click="toDetail(item)">
|
||||
<CompetitionCard :item="item" @copy="handleCopy" @delete="handleDelete" />
|
||||
<CompetitionCard :item="item" @copy="handleCopy" @delete="handleDelete" @close="handleCloseActivity" />
|
||||
</NGi>
|
||||
</NGrid>
|
||||
|
||||
|
||||
@ -10,6 +10,7 @@ const props = defineProps<Props>()
|
||||
const emit = defineEmits<{
|
||||
(e: 'copy', item: Api.Competition.CompetitionItem): void
|
||||
(e: 'delete', item: Api.Competition.CompetitionItem): void
|
||||
(e: 'close', item: Api.Competition.CompetitionItem): void
|
||||
}>()
|
||||
|
||||
const { options: publishStatusOptions } = useDict('publish_status')
|
||||
@ -83,6 +84,20 @@ const decorationBgClass = computed(() => {
|
||||
<div
|
||||
class="absolute right-4 top-4 z-20 flex gap-2 opacity-0 transition-opacity duration-300 group-hover:opacity-100"
|
||||
>
|
||||
<NTooltip v-if="[PublishStatus.Published, PublishStatus.Processing].includes(item.PublishStatus)">
|
||||
<template #trigger>
|
||||
<NButton
|
||||
circle secondary size="small" type="warning"
|
||||
class="shadow-sm backdrop-blur-sm !bg-white/80 hover:!bg-orange-50" @click.stop="emit('close', item)"
|
||||
>
|
||||
<template #icon>
|
||||
<icon-ic:round-stop-circle class="text-icon" />
|
||||
</template>
|
||||
</NButton>
|
||||
</template>
|
||||
结束活动
|
||||
</NTooltip>
|
||||
|
||||
<NTooltip>
|
||||
<template #trigger>
|
||||
<NButton
|
||||
|
||||
Reference in New Issue
Block a user