fix(统计): 统计弹框里几处数字对不上——完成度圆环把交了没对的也算成完成、请假隐藏的人还算在班级人数里
- 代码统计「班级完成度」圆环的已完成改成做完的人数,和上面「完成人数」一致 - 流程图统计「班级人数」减掉请假隐藏的,和完成度的分母一致 - 流程图统计打开就查、开着自动刷新(一天以内的时间段,30 秒一次),按钮带转圈 - 两个面板统计失败时在按钮旁说一句,不再无声无息停在旧数字上 - 没完成的人全被隐藏时不再显示「全都完成了」 - 流程图统计的「未完成」页签在全班做完后不再整个消失 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
660f689a5c
commit
8d1521f3b6
2 files changed
+56
-10
No files matched your search
@@ -13,7 +13,8 @@
|
||||
clearable
|
||||
/>
|
||||
<n-select style="width: 120px" v-model:value="query.duration" :options="durationOptions" />
|
||||
<n-button type="primary" @click="handleStatistics">统计</n-button>
|
||||
<n-button type="primary" :loading="loading" @click="handleStatistics">统计</n-button>
|
||||
<n-text v-if="failed" type="error">统计没拉下来,稍后会自动再试</n-text>
|
||||
</n-flex>
|
||||
|
||||
<n-empty v-if="!hasResult" description="暂无数据" style="margin: 40px 0" />
|
||||
@@ -42,8 +43,9 @@
|
||||
</div>
|
||||
<div class="stat-item">
|
||||
<n-text>班级人数</n-text>
|
||||
<!-- 减掉请假隐藏的,和下面完成度的分母、代码统计面板是同一个数 -->
|
||||
<n-gradient-text type="warning" font-size="28">
|
||||
{{ data.personCount }}
|
||||
{{ adjustedPersonCount }}
|
||||
</n-gradient-text>
|
||||
</div>
|
||||
<div class="stat-item">
|
||||
@@ -102,8 +104,10 @@
|
||||
</n-grid>
|
||||
</n-tab-pane>
|
||||
|
||||
<!-- 有花名册就一直在(和代码统计面板一样):原来人一做完这个页签就整个消失,
|
||||
老师找不到「全都完成了」那句 -->
|
||||
<n-tab-pane
|
||||
v-if="data.dataUnaccepted.length > 0"
|
||||
v-if="data.personCount > 0 || data.dataUnaccepted.length > 0"
|
||||
name="unaccepted"
|
||||
:tab="`未完成(${visibleUnaccepted.length})`"
|
||||
>
|
||||
@@ -117,7 +121,10 @@
|
||||
</n-button>
|
||||
</n-flex>
|
||||
<n-flex size="large" align="center">
|
||||
<n-gradient-text v-if="visibleUnaccepted.length === 0" font-size="24" type="success">
|
||||
<n-text v-if="visibleUnaccepted.length === 0 && hiddenCount > 0" depth="3">
|
||||
没完成的 {{ hiddenCount }} 位都隐藏了
|
||||
</n-text>
|
||||
<n-gradient-text v-else-if="visibleUnaccepted.length === 0" font-size="24" type="success">
|
||||
全都完成了
|
||||
</n-gradient-text>
|
||||
<template v-for="item in visibleUnaccepted" :key="item.username">
|
||||
@@ -186,8 +193,6 @@ interface Props {
|
||||
|
||||
const props = defineProps<Props>()
|
||||
|
||||
const message = useMessage()
|
||||
|
||||
const durationOptions: SelectOption[] = [...PANEL_DURATION_OPTIONS]
|
||||
|
||||
// 班级、题号、时间段记一小时,理由见 useStatisticsQuery
|
||||
@@ -437,7 +442,14 @@ const subOptions = computed<Duration>(
|
||||
() => durationFromValue(query.duration) ?? durationFromValue(PANEL_DURATION_OPTIONS[0].value)!,
|
||||
)
|
||||
|
||||
const loading = ref(false)
|
||||
/** 上一次统计失败了。不弹 toast:会自动刷新,断网时会一直弹 */
|
||||
const failed = ref(false)
|
||||
|
||||
async function handleStatistics() {
|
||||
// 自动刷新和手点可能撞上,上一次没回来就跳过这一次
|
||||
if (loading.value) return
|
||||
loading.value = true
|
||||
const current = Date.now()
|
||||
const end = formatISO(current)
|
||||
const duration =
|
||||
@@ -446,15 +458,34 @@ async function handleStatistics() {
|
||||
const res = await getFlowchartStatistics(duration, query.problem, query.username)
|
||||
Object.assign(data, res)
|
||||
saveQuery()
|
||||
failed.value = false
|
||||
} catch (error) {
|
||||
message.error("获取流程图统计失败")
|
||||
failed.value = true
|
||||
console.error("获取流程图统计失败:", error)
|
||||
return
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
await nextTick()
|
||||
renderWordCloud()
|
||||
}
|
||||
|
||||
/**
|
||||
* 和代码统计面板一样:打开就查、开着就刷(老师是投在屏幕上盯着看的)。
|
||||
* 流程图统计要给词云分词,比代码统计重,所以 30 秒一次,而且只刷一天以内的时间段 ——
|
||||
* 查一周、一学年的是回头看,不是盯课堂,不必反复重算
|
||||
*/
|
||||
onMounted(handleStatistics)
|
||||
|
||||
const visibility = useDocumentVisibility()
|
||||
useIntervalFn(() => {
|
||||
if (visibility.value !== "visible") return
|
||||
if (query.duration === "all") return
|
||||
const d = subOptions.value
|
||||
if (d.weeks || d.months || d.years || (d.days ?? 0) > 1) return
|
||||
handleStatistics()
|
||||
}, 30_000)
|
||||
|
||||
onUnmounted(() => {
|
||||
if (wordcloudChart) {
|
||||
wordcloudChart.destroy()
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
<n-select style="width: 120px" v-model:value="query.duration" :options="options" />
|
||||
<n-button type="primary" :loading="loading" @click="handleStatistics"> 统计 </n-button>
|
||||
<n-button v-if="route.name !== 'submissions'" @click="goSubmissions"> 前往提交列表 </n-button>
|
||||
<n-text v-if="failed" type="error">统计没拉下来,15 秒后会自动再试</n-text>
|
||||
</n-flex>
|
||||
|
||||
<n-empty v-if="!hasResult" description="暂无数据" style="margin: 40px 0" />
|
||||
@@ -104,7 +105,11 @@
|
||||
恢复 {{ hiddenCount }} 位
|
||||
</n-button>
|
||||
</n-flex>
|
||||
<n-gradient-text v-if="unfinishedGroups.length === 0" font-size="24" type="success">
|
||||
<!-- 名单上的人全被「请假隐藏」了不等于全做完了,别让老师误以为全班过了 -->
|
||||
<n-text v-if="unfinishedGroups.length === 0 && hiddenCount > 0" depth="3">
|
||||
没完成的 {{ hiddenCount }} 位都隐藏了
|
||||
</n-text>
|
||||
<n-gradient-text v-else-if="unfinishedGroups.length === 0" font-size="24" type="success">
|
||||
全都完成了
|
||||
</n-gradient-text>
|
||||
<template v-for="group in unfinishedGroups" :key="group.title">
|
||||
@@ -647,9 +652,10 @@ const pieChartOptions = {
|
||||
},
|
||||
}
|
||||
|
||||
// 环形图数据 - 班级完成度
|
||||
// 环形图数据 - 班级完成度。「已完成」和上面数字行的「完成人数」是同一个数(做完的),
|
||||
// 原来这里用的是 list.length —— 那是所有交过的人,交了没对的也被画成了已完成
|
||||
const completionChartData = computed(() => {
|
||||
const completedCount = list.value.length
|
||||
const completedCount = doneList.value.length
|
||||
const uncompletedCount = Math.max(0, adjustedPersonCount.value - completedCount)
|
||||
return {
|
||||
labels: ["已完成", "未完成"],
|
||||
@@ -703,12 +709,21 @@ function goSubmissions() {
|
||||
}
|
||||
const loading = ref(false)
|
||||
|
||||
/**
|
||||
* 上一次统计失败了。原来没 catch,请求一失败面板上什么都不说,老师看着的还是旧数字。
|
||||
* 不弹 toast:每 15 秒自动刷新一次,断网时会一直弹
|
||||
*/
|
||||
const failed = ref(false)
|
||||
|
||||
async function handleStatistics() {
|
||||
// 自动刷新和手点可能撞上,上一次没回来就跳过这一次
|
||||
if (loading.value) return
|
||||
loading.value = true
|
||||
try {
|
||||
await fetchStatistics()
|
||||
failed.value = false
|
||||
} catch {
|
||||
failed.value = true
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user