1 parent
23844ae301
commit
d25b5dbe6d
268 files changed
+3684
-8861
No files matched your search
@@ -13,11 +13,7 @@
|
||||
@change="onUsernameChange"
|
||||
@clear="onUsernameChange"
|
||||
/>
|
||||
<n-select
|
||||
style="width: 140px"
|
||||
:options="options"
|
||||
v-model:value="urlDuration"
|
||||
/>
|
||||
<n-select style="width: 140px" :options="options" v-model:value="urlDuration" />
|
||||
</n-flex>
|
||||
</n-flex>
|
||||
|
||||
@@ -74,9 +70,7 @@ aiStore.targetUsername = urlUsername.value
|
||||
aiStore.duration = urlDuration.value
|
||||
|
||||
const subOptions = computed<Duration>(
|
||||
() =>
|
||||
durationFromValue(aiStore.duration) ??
|
||||
durationFromValue(DURATION_OPTIONS[0].value)!,
|
||||
() => durationFromValue(aiStore.duration) ?? durationFromValue(DURATION_OPTIONS[0].value)!,
|
||||
)
|
||||
|
||||
const start = computed(() => formatISO(sub(new Date(), subOptions.value)))
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
<template>
|
||||
<n-card title="几次做对" size="small" v-if="show">
|
||||
<template #header-extra>
|
||||
<n-text depth="3" style="font-size: 12px">
|
||||
通过前提交了几次,看有没有在死磕
|
||||
</n-text>
|
||||
<n-text depth="3" style="font-size: 12px"> 通过前提交了几次,看有没有在死磕 </n-text>
|
||||
</template>
|
||||
<div class="chart">
|
||||
<Bar :key="chartKey" :data="data" :options="options" />
|
||||
@@ -13,13 +11,7 @@
|
||||
<script setup lang="ts">
|
||||
import type { ChartOptions } from "chart.js"
|
||||
import { Bar } from "vue-chartjs"
|
||||
import {
|
||||
Chart as ChartJS,
|
||||
CategoryScale,
|
||||
LinearScale,
|
||||
BarElement,
|
||||
Tooltip,
|
||||
} from "chart.js"
|
||||
import { Chart as ChartJS, CategoryScale, LinearScale, BarElement, Tooltip } from "chart.js"
|
||||
import { useAIStore } from "oj/store/ai"
|
||||
import { useChartTheme } from "shared/composables/chartTheme"
|
||||
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
<template>
|
||||
<n-card title="难度分布" size="small" v-if="show">
|
||||
<template #header-extra>
|
||||
<n-text depth="3" style="font-size: 12px">
|
||||
看看简单题和难题各做了多少
|
||||
</n-text>
|
||||
<n-text depth="3" style="font-size: 12px"> 看看简单题和难题各做了多少 </n-text>
|
||||
</template>
|
||||
<div style="height: 300px">
|
||||
<Bar :key="chartKey" :data="data" :options="options" />
|
||||
@@ -14,13 +12,7 @@
|
||||
<script setup lang="ts">
|
||||
import type { ChartOptions } from "chart.js"
|
||||
import { Bar } from "vue-chartjs"
|
||||
import {
|
||||
Chart as ChartJS,
|
||||
CategoryScale,
|
||||
LinearScale,
|
||||
BarElement,
|
||||
Tooltip,
|
||||
} from "chart.js"
|
||||
import { Chart as ChartJS, CategoryScale, LinearScale, BarElement, Tooltip } from "chart.js"
|
||||
import { useAIStore } from "oj/store/ai"
|
||||
import { useChartTheme } from "shared/composables/chartTheme"
|
||||
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
<template>
|
||||
<n-card :title="title" size="small" v-if="show">
|
||||
<template #header-extra>
|
||||
<n-text depth="3" style="font-size: 12px">
|
||||
做题量和提交质量的变化
|
||||
</n-text>
|
||||
<n-text depth="3" style="font-size: 12px"> 做题量和提交质量的变化 </n-text>
|
||||
</template>
|
||||
<div class="chart">
|
||||
<Chart type="bar" :key="chartKey" :data="data" :options="options" />
|
||||
@@ -67,10 +65,7 @@ const show = computed(() => aiStore.durationData.length > 0)
|
||||
// 而且逐题的等级在下面的解题表格里本来就有
|
||||
const data = computed<ChartData<"bar" | "line">>(() => ({
|
||||
labels: aiStore.durationData.map((duration) =>
|
||||
[
|
||||
parseTime(duration.start, "M月D日"),
|
||||
parseTime(duration.end, "M月D日"),
|
||||
].join("~"),
|
||||
[parseTime(duration.start, "M月D日"), parseTime(duration.end, "M月D日")].join("~"),
|
||||
),
|
||||
datasets: [
|
||||
{
|
||||
@@ -155,14 +150,11 @@ const options = computed<ChartOptions<"bar" | "line">>(() => ({
|
||||
},
|
||||
footer: (items: TooltipItem<"bar" | "line">[]) => {
|
||||
const index = items[0]?.dataIndex
|
||||
const bucket =
|
||||
index === undefined ? undefined : aiStore.durationData[index]
|
||||
const bucket = index === undefined ? undefined : aiStore.durationData[index]
|
||||
if (!bucket) return ""
|
||||
const lines = [`本期等级: ${bucket.grade || "无"}`]
|
||||
if (bucket.submissionCount > 0) {
|
||||
lines.push(
|
||||
`通过 ${bucket.acceptedCount} 次 / 共提交 ${bucket.submissionCount} 次`,
|
||||
)
|
||||
lines.push(`通过 ${bucket.acceptedCount} 次 / 共提交 ${bucket.submissionCount} 次`)
|
||||
}
|
||||
return lines
|
||||
},
|
||||
|
||||
@@ -11,13 +11,7 @@
|
||||
<script setup lang="ts">
|
||||
import type { ChartOptions } from "chart.js"
|
||||
import { Bar } from "vue-chartjs"
|
||||
import {
|
||||
Chart as ChartJS,
|
||||
CategoryScale,
|
||||
LinearScale,
|
||||
BarElement,
|
||||
Tooltip,
|
||||
} from "chart.js"
|
||||
import { Chart as ChartJS, CategoryScale, LinearScale, BarElement, Tooltip } from "chart.js"
|
||||
import { useAIStore } from "oj/store/ai"
|
||||
import { useChartTheme } from "shared/composables/chartTheme"
|
||||
import { JUDGE_STATUS } from "utils/constants"
|
||||
@@ -75,9 +69,7 @@ const data = computed(() => ({
|
||||
],
|
||||
}))
|
||||
|
||||
const total = computed(() =>
|
||||
grouped.value.reduce((sum, [, item]) => sum + item.count, 0),
|
||||
)
|
||||
const total = computed(() => grouped.value.reduce((sum, [, item]) => sum + item.count, 0))
|
||||
|
||||
const options = computed<ChartOptions<"bar">>(() => ({
|
||||
indexAxis: "y",
|
||||
|
||||
@@ -11,14 +11,7 @@
|
||||
<script setup lang="ts">
|
||||
import type { ChartOptions } from "chart.js"
|
||||
import { Bar } from "vue-chartjs"
|
||||
import {
|
||||
Chart as ChartJS,
|
||||
CategoryScale,
|
||||
LinearScale,
|
||||
BarElement,
|
||||
Tooltip,
|
||||
Legend,
|
||||
} from "chart.js"
|
||||
import { Chart as ChartJS, CategoryScale, LinearScale, BarElement, Tooltip, Legend } from "chart.js"
|
||||
import { useAIStore } from "oj/store/ai"
|
||||
import { useChartTheme } from "shared/composables/chartTheme"
|
||||
|
||||
@@ -31,8 +24,7 @@ const { chartKey } = useChartTheme()
|
||||
// 第二个 tab 里列成表格。这里直接画出来,不用改后端和契约
|
||||
const items = computed(() =>
|
||||
[...aiStore.detailsData.flowcharts].sort(
|
||||
(a, b) =>
|
||||
b.bestScore - a.bestScore || a.problemId.localeCompare(b.problemId),
|
||||
(a, b) => b.bestScore - a.bestScore || a.problemId.localeCompare(b.problemId),
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
<template>
|
||||
<n-card title="过去一年的提交热力图" size="small">
|
||||
<template #header-extra>
|
||||
<n-text depth="3" style="font-size: 12px">
|
||||
每格一周,激励持续学习
|
||||
</n-text>
|
||||
<n-text depth="3" style="font-size: 12px"> 每格一周,激励持续学习 </n-text>
|
||||
</template>
|
||||
<n-spin :show="aiStore.loading.heatmap" :delay="50">
|
||||
<div
|
||||
@@ -154,8 +152,7 @@ const tooltipStyle = computed(() => ({
|
||||
top: `${tooltip.value?.y}px`,
|
||||
}))
|
||||
|
||||
const getTooltipText = (count: number) =>
|
||||
count === 0 ? "这周没有提交" : `这周提交了 ${count} 次`
|
||||
const getTooltipText = (count: number) => (count === 0 ? "这周没有提交" : `这周提交了 ${count} 次`)
|
||||
|
||||
const showTooltip = (e: MouseEvent, cell: Cell) => {
|
||||
const rect = (e.target as HTMLElement).getBoundingClientRect()
|
||||
|
||||
@@ -1,9 +1,5 @@
|
||||
<template>
|
||||
<n-alert
|
||||
:show-icon="false"
|
||||
type="success"
|
||||
v-if="aiStore.detailsData.solvedCount"
|
||||
>
|
||||
<n-alert :show-icon="false" type="success" v-if="aiStore.detailsData.solvedCount">
|
||||
<span>{{ durationLabel }},</span>
|
||||
<span>你一共解决 </span>
|
||||
<b class="charming"> {{ aiStore.detailsData.solvedCount }} </b>
|
||||
@@ -33,10 +29,7 @@ const durationLabel = computed(() => {
|
||||
return `在 ${parseTime(aiStore.detailsData.start, "HH:mm")} - ${parseTime(aiStore.detailsData.end, "HH:mm")} 期间`
|
||||
} else if (aiStore.duration.includes("days")) {
|
||||
return `在 ${parseTime(aiStore.detailsData.end, "MM月DD日")}`
|
||||
} else if (
|
||||
aiStore.duration.includes("weeks") ||
|
||||
aiStore.duration.includes("months")
|
||||
) {
|
||||
} else if (aiStore.duration.includes("weeks") || aiStore.duration.includes("months")) {
|
||||
return `在 ${parseTime(aiStore.detailsData.start, "MM月DD日")} - ${parseTime(aiStore.detailsData.end, "MM月DD日")} 期间`
|
||||
} else {
|
||||
return `在 ${parseTime(aiStore.detailsData.start, "YYYY年MM月DD日")} - ${parseTime(aiStore.detailsData.end, "YYYY年MM月DD日")} 期间`
|
||||
|
||||
@@ -79,12 +79,7 @@ const columns: DataTableColumn<SolvedProblem>[] = [
|
||||
text: true,
|
||||
onClick: () => {
|
||||
if (row.problem.contestId) {
|
||||
router.push(
|
||||
"/contest/" +
|
||||
row.problem.contestId +
|
||||
"/problem/" +
|
||||
row.problem.displayId,
|
||||
)
|
||||
router.push("/contest/" + row.problem.contestId + "/problem/" + row.problem.displayId)
|
||||
} else {
|
||||
router.push("/problem/" + row.problem.displayId)
|
||||
}
|
||||
@@ -102,8 +97,7 @@ const columns: DataTableColumn<SolvedProblem>[] = [
|
||||
{
|
||||
// 用后端下发的 rankScope,不要看 className 有没有值:班里只有一个人时
|
||||
// 后端会回退到全服排名,那种学生原来看到的是「班级排名」配全服数据
|
||||
title: () =>
|
||||
aiStore.detailsData.rankScope === "class" ? "班级排名" : "全服排名",
|
||||
title: () => (aiStore.detailsData.rankScope === "class" ? "班级排名" : "全服排名"),
|
||||
key: "rank",
|
||||
width: 100,
|
||||
align: "center",
|
||||
@@ -119,12 +113,7 @@ const columns: DataTableColumn<SolvedProblem>[] = [
|
||||
{
|
||||
title: () =>
|
||||
h(NTooltip, null, {
|
||||
trigger: () =>
|
||||
h(
|
||||
"span",
|
||||
{ style: "cursor:help; border-bottom: 1px dashed" },
|
||||
"等级",
|
||||
),
|
||||
trigger: () => h("span", { style: "cursor:help; border-bottom: 1px dashed" }, "等级"),
|
||||
default: () =>
|
||||
h("div", null, [
|
||||
h("div", null, "基于同时段排名的百分位:"),
|
||||
|
||||
@@ -11,13 +11,7 @@
|
||||
<script setup lang="ts">
|
||||
import type { ChartOptions } from "chart.js"
|
||||
import { Bar } from "vue-chartjs"
|
||||
import {
|
||||
Chart as ChartJS,
|
||||
CategoryScale,
|
||||
LinearScale,
|
||||
BarElement,
|
||||
Tooltip,
|
||||
} from "chart.js"
|
||||
import { Chart as ChartJS, CategoryScale, LinearScale, BarElement, Tooltip } from "chart.js"
|
||||
import { useAIStore } from "oj/store/ai"
|
||||
import { useChartTheme } from "shared/composables/chartTheme"
|
||||
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
<template>
|
||||
<n-card title="时间活跃度分析" size="small" v-if="show">
|
||||
<template #header-extra>
|
||||
<n-text depth="3" style="font-size: 12px">
|
||||
基于全部提交,发现做题高峰时段
|
||||
</n-text>
|
||||
<n-text depth="3" style="font-size: 12px"> 基于全部提交,发现做题高峰时段 </n-text>
|
||||
</template>
|
||||
<div style="height: 300px">
|
||||
<Bar :key="chartKey" :data="data" :options="options" />
|
||||
@@ -56,18 +54,14 @@ const activityMatrix = computed(() => {
|
||||
return matrix
|
||||
})
|
||||
|
||||
const show = computed(() =>
|
||||
aiStore.detailsData.activity.some((item) => item.count > 0),
|
||||
)
|
||||
const show = computed(() => aiStore.detailsData.activity.some((item) => item.count > 0))
|
||||
|
||||
// 为每个时间段准备数据集
|
||||
const data = computed(() => {
|
||||
const datasets = TIME_PERIODS.map((period, periodIndex) => {
|
||||
return {
|
||||
label: period.label,
|
||||
data: WEEKDAYS.map(
|
||||
(_, weekday) => activityMatrix.value[weekday][periodIndex],
|
||||
),
|
||||
data: WEEKDAYS.map((_, weekday) => activityMatrix.value[weekday][periodIndex]),
|
||||
backgroundColor: getTimePeriodColor(periodIndex),
|
||||
borderColor: getTimePeriodColor(periodIndex),
|
||||
borderWidth: 1,
|
||||
|
||||
Reference in new issue
Block a user