- 添加题库管理页面及相关组件 - 实现排行榜管理功能,包括列表和详情页 - 新增实时结果展示页面 - 添加模板制作和管理功能 - 完善路由配置和国际化支持 - 新增阿里云OSS文件上传服务 - 添加多种工具函数和类型定义 - 优化表格和表单组件 - 调整布局和样式细节
185 lines
5.5 KiB
Vue
185 lines
5.5 KiB
Vue
<script setup lang="tsx">
|
||
import { NButton, NCard, NTag } from 'naive-ui'
|
||
import { reactive } from 'vue'
|
||
import { useRouter } from 'vue-router'
|
||
import { defaultTransform, useNaivePaginatedTable, useTableOperate } from '@/hooks/common/table'
|
||
import { fetchGetUserList } from '@/service/api'
|
||
import { useAppStore } from '@/store/modules/app'
|
||
import RankSearch from './modules/rank-search.vue'
|
||
|
||
const appStore = useAppStore()
|
||
const router = useRouter()
|
||
|
||
const searchParams: Api.SystemManage.UserSearchParams = reactive({
|
||
current: 1,
|
||
size: 10,
|
||
status: null,
|
||
userName: null,
|
||
userGender: null,
|
||
nickName: null,
|
||
userPhone: null,
|
||
userEmail: null,
|
||
})
|
||
|
||
const rankTitle = '排行榜管理列表'
|
||
|
||
const statusMap: Record<string, string> = {
|
||
1: '已发布',
|
||
2: '待审核',
|
||
}
|
||
|
||
const { columns, columnChecks, data, getData, getDataByPage, loading, mobilePagination } = useNaivePaginatedTable({
|
||
api: () => fetchGetUserList(searchParams),
|
||
transform: (response) => {
|
||
const transformed = defaultTransform(response)
|
||
// Mocking data for Rank Management based on User API response
|
||
const mockCompetitions = ['阅读之星-辞海遨游环节 (2026)', '古诗词大会年度精英巅峰赛', '趣味百科常识挑战周']
|
||
const mockDates = ['2026.01.12', '2026.01.15', '2026.01.18']
|
||
const mockScales = ['40 支队伍', '24 支队伍', '60 支队伍']
|
||
const mockScores = ['145', '180', '120']
|
||
const mockTimes = ['2026-01-22 16:30:12', '2026-01-22 12:00:00', '2026-01-21 18:22:45']
|
||
|
||
transformed.data.forEach((item, index) => {
|
||
const mockIndex = index % 3
|
||
item.userName = mockCompetitions[mockIndex] // Competition Name
|
||
item.userEmail = mockDates[mockIndex] // Activity Date (using userEmail field)
|
||
item.userPhone = mockScales[mockIndex] // Team Scale (using userPhone field)
|
||
item.nickName = mockScores[mockIndex] // Max Score (using nickName field)
|
||
// item.createTime is typically available, we'll simulate update time
|
||
item.createTime = mockTimes[mockIndex]
|
||
// Status: 1 (Published), 2 (Pending)
|
||
item.status = (index % 2 === 0) ? '2' : '1'
|
||
})
|
||
return transformed
|
||
},
|
||
onPaginationParamsChange: (params) => {
|
||
searchParams.current = params.page
|
||
searchParams.size = params.pageSize
|
||
},
|
||
columns: () => [
|
||
{
|
||
type: 'selection',
|
||
align: 'center',
|
||
width: 48,
|
||
},
|
||
{
|
||
key: 'userName',
|
||
title: '比赛活动名称',
|
||
align: 'left',
|
||
minWidth: 200,
|
||
},
|
||
{
|
||
key: 'userEmail',
|
||
title: '活动日期',
|
||
align: 'center',
|
||
minWidth: 120,
|
||
},
|
||
{
|
||
key: 'userPhone',
|
||
title: '队伍规模',
|
||
align: 'center',
|
||
minWidth: 100,
|
||
},
|
||
{
|
||
key: 'nickName',
|
||
title: '最高积分',
|
||
align: 'center',
|
||
minWidth: 100,
|
||
render: row => (
|
||
<span class="text-primary font-bold">
|
||
{row.nickName}
|
||
{' '}
|
||
Pts
|
||
</span>
|
||
),
|
||
},
|
||
{
|
||
key: 'createTime',
|
||
title: '最后更新时间',
|
||
align: 'center',
|
||
minWidth: 160,
|
||
},
|
||
{
|
||
key: 'status',
|
||
title: '发布状态',
|
||
align: 'center',
|
||
width: 100,
|
||
render: (row) => {
|
||
if (row.status === null)
|
||
return null
|
||
const label = statusMap[row.status] || '未知'
|
||
// 1: Published (Success/Green), 2: Pending (Warning/Orange)
|
||
return <NTag type={row.status === '1' ? 'success' : 'warning'}>{label}</NTag>
|
||
},
|
||
},
|
||
{
|
||
key: 'operate',
|
||
title: '操作',
|
||
align: 'center',
|
||
width: 120,
|
||
render: row => (
|
||
<div class="flex-center">
|
||
<NButton type="primary" text onClick={() => edit(row.id)}>
|
||
进入排行详情
|
||
</NButton>
|
||
</div>
|
||
),
|
||
},
|
||
],
|
||
})
|
||
|
||
const {
|
||
drawerVisible,
|
||
operateType,
|
||
editingData,
|
||
handleEdit,
|
||
checkedRowKeys,
|
||
onBatchDeleted,
|
||
} = useTableOperate(data, 'id', getData)
|
||
|
||
function edit(id: number) {
|
||
router.push({ name: 'rank_rank-detail', query: { id } })
|
||
}
|
||
|
||
function handleBatchPublish() {
|
||
window.$message?.success('批量发布成功')
|
||
}
|
||
</script>
|
||
|
||
<template>
|
||
<div class="min-h-500px flex-col-stretch gap-16px overflow-hidden lt-sm:overflow-auto">
|
||
<RankSearch v-model:model="searchParams" @search="getDataByPage" />
|
||
<NCard :bordered="false" size="small" class="card-wrapper sm:flex-1-hidden">
|
||
<template #header>
|
||
<div class="flex items-center justify-between">
|
||
<div>
|
||
<div class="text-16px font-bold">
|
||
{{ rankTitle }}
|
||
</div>
|
||
<div class="mt-4px text-12px text-gray-500">
|
||
您可以对所有比赛场次的最终积分进行核对、修正,并正式发布结果。
|
||
</div>
|
||
</div>
|
||
<NButton type="primary" ghost class="ml-auto" @click="handleBatchPublish">
|
||
<template #icon>
|
||
<icon-ic-round-upload class="text-icon" />
|
||
</template>
|
||
批量发布至终端
|
||
</NButton>
|
||
</div>
|
||
</template>
|
||
<!-- <template #header-extra>
|
||
<TableHeaderOperation v-model:columns="columnChecks" :disabled-delete="checkedRowKeys.length === 0"
|
||
:loading="loading" @add="handleAdd" @delete="handleBatchDelete" @refresh="getData" />
|
||
</template> -->
|
||
<NDataTable
|
||
v-model:checked-row-keys="checkedRowKeys" :columns="columns" :data="data" size="small" striped
|
||
:flex-height="!appStore.isMobile" :scroll-x="962" :loading="loading" remote :row-key="row => row.id"
|
||
:pagination="mobilePagination" class="sm:h-full"
|
||
/>
|
||
</NCard>
|
||
</div>
|
||
</template>
|
||
|
||
<style scoped></style>
|