update
Some checks failed
Deploy / deploy (push) Has been cancelled

This commit is contained in:
2025-10-24 11:19:46 +08:00
parent d766433068
commit d384d15aa6
2 changed files with 46 additions and 28 deletions

View File

@@ -361,6 +361,9 @@ export function getProblemSetBadges(problemSetId: number) {
} }
// 获取题单用户进度列表 // 获取题单用户进度列表
export function getProblemSetUserProgress(problemSetId: number) { export function getProblemSetUserProgress(
return http.get(`problemset/${problemSetId}/users_progress`) problemSetId: number,
params?: { limit?: number; offset?: number },
) {
return http.get(`problemset/${problemSetId}/users_progress`, { params })
} }

View File

@@ -1,43 +1,49 @@
<script setup lang="ts"> <script setup lang="ts">
import { h, computed, ref, onMounted } from "vue" import { h, computed, ref, onMounted, watch } from "vue"
import { Icon } from "@iconify/vue"
import { parseTime } from "utils/functions" import { parseTime } from "utils/functions"
import { ProblemSetProgress } from "utils/types" import { ProblemSetProgress } from "utils/types"
import { getProblemSetUserProgress } from "../../api" import { getProblemSetUserProgress } from "../../api"
import { NP, NProgress, NTag, useMessage } from "naive-ui" import { NTag } from "naive-ui"
import { usePagination } from "shared/composables/pagination"
const message = useMessage() import Pagination from "shared/components/Pagination.vue"
const route = useRoute() const route = useRoute()
const problemSetId = computed(() => Number(route.params.problemSetId)) const problemSetId = computed(() => Number(route.params.problemSetId))
const progress = ref<ProblemSetProgress[]>([]) const progress = ref<ProblemSetProgress[]>([])
const loading = ref(false) const loading = ref(false)
const total = ref(0)
// 使用分页 composable
const { query } = usePagination({}, { defaultLimit: 10 })
// 加载用户进度数据 // 加载用户进度数据
async function loadUserProgress() { async function loadUserProgress() {
loading.value = true loading.value = true
try { const offset = (query.page - 1) * query.limit
const res = await getProblemSetUserProgress(problemSetId.value) const res = await getProblemSetUserProgress(problemSetId.value, {
progress.value = res.data limit: query.limit,
} catch (err: any) { offset,
message.error("加载用户进度失败:" + (err.data || "未知错误")) })
} finally {
progress.value = res.data.results
total.value = res.data.total
loading.value = false loading.value = false
}
} }
// 监听分页参数变化
watch([() => query.page, () => query.limit], loadUserProgress)
// 计算统计数据 // 计算统计数据
const stats = computed(() => { const stats = computed(() => {
const total = progress.value.length
const completed = progress.value.filter((p) => p.is_completed).length const completed = progress.value.filter((p) => p.is_completed).length
const avgProgress = const avgProgress =
total > 0 progress.value.length > 0
? progress.value.reduce((sum, p) => sum + p.progress_percentage, 0) / ? progress.value.reduce((sum, p) => sum + p.progress_percentage, 0) /
total progress.value.length
: 0 : 0
return { return {
total, total: total.value,
completed, completed,
avgProgress: Math.round(avgProgress), avgProgress: Math.round(avgProgress),
} }
@@ -51,7 +57,11 @@ const progressColumns = [
title: "排名", title: "排名",
key: "rank", key: "rank",
width: 80, width: 80,
render: (row: ProblemSetProgress, index: number) => index + 1, render: (row: ProblemSetProgress, index: number) => {
// 计算全局排名:当前页偏移 + 当前行索引 + 1
const globalRank = (query.page - 1) * query.limit + index + 1
return globalRank
},
}, },
{ {
title: "用户", title: "用户",
@@ -116,16 +126,10 @@ const progressColumns = [
}, },
}, },
] ]
</script> </script>
<template> <template>
<div> <div>
<n-flex justify="space-between" align="center" style="margin-bottom: 16px">
<n-h3 style="margin: 0">用户进度</n-h3>
<n-text depth="3"> {{ stats.total }} 人参与</n-text>
</n-flex>
<!-- 统计信息卡片 --> <!-- 统计信息卡片 -->
<n-grid :cols="3" :x-gap="16" style="margin-bottom: 16px"> <n-grid :cols="3" :x-gap="16" style="margin-bottom: 16px">
<n-grid-item> <n-grid-item>
@@ -140,18 +144,29 @@ const progressColumns = [
</n-grid-item> </n-grid-item>
<n-grid-item> <n-grid-item>
<n-card size="small"> <n-card size="small">
<n-statistic label="平均进度" :value="stats.avgProgress.toFixed(0) + '%'" /> <n-statistic
label="平均进度"
:value="stats.avgProgress.toFixed(0) + '%'"
/>
</n-card> </n-card>
</n-grid-item> </n-grid-item>
</n-grid> </n-grid>
<n-data-table <n-data-table
:loading="loading"
:columns="progressColumns" :columns="progressColumns"
:data="progress" :data="progress"
:loading="loading"
:pagination="false" :pagination="false"
:bordered="false" :bordered="false"
:single-line="false" :single-line="false"
/> />
<Pagination
:total="total"
:limit="query.limit"
:page="query.page"
@update:limit="(limit: number) => (query.limit = limit)"
@update:page="(page: number) => (query.page = page)"
/>
</div> </div>
</template> </template>