新增AI分析
Some checks failed
Deploy / deploy (push) Has been cancelled

This commit is contained in:
2025-09-24 01:02:34 +08:00
parent b3091db7b2
commit e71611ff1c
19 changed files with 636 additions and 45 deletions

View File

@@ -0,0 +1,126 @@
<template>
<div class="chart">
<Chart type="bar" :data="data" :options="options" />
</div>
</template>
<script setup lang="ts">
import type { ChartData, ChartOptions, TooltipItem } from "chart.js"
import { Chart } from "vue-chartjs"
import { parseTime } from "~/utils/functions"
import { WeeklyData } from "~/utils/types"
const props = defineProps<{
weeklyData: WeeklyData[]
duration: string
}>()
const gradeOrder = ["C", "B", "A", "S"] as const
const title = computed(() => {
if (props.duration === "months:2") {
return "过去两个月的每周综合情况一览图"
} else if (props.duration === "months:6") {
return "过去半年的每月综合情况一览图"
} else if (props.duration === "years:1") {
return "过去一年的每月综合情况一览图"
} else {
return "过去四周的综合情况一览图"
}
})
const data = computed<ChartData<"bar" | "line">>(() => {
return {
labels: props.weeklyData.map((weekly) => {
let prefix = "周"
if (weekly.unit === "months") {
prefix = "月"
}
return [
parseTime(weekly.start, "M月D日"),
parseTime(weekly.end, "M月D日"),
].join("")
}),
datasets: [
{
type: "bar",
label: "完成题目数量",
data: props.weeklyData.map((weekly) => weekly.problem_count),
yAxisID: "y",
},
{
type: "bar",
label: "总提交次数",
data: props.weeklyData.map((weekly) => weekly.submission_count),
yAxisID: "y",
},
{
type: "line",
label: "等级",
data: props.weeklyData.map((weekly) =>
gradeOrder.indexOf(weekly.grade || "C"),
),
tension: 0.4,
yAxisID: "y1",
barThickness: 10,
},
],
}
})
const options = computed<ChartOptions<"bar" | "line">>(() => {
return {
interaction: {
intersect: false,
},
maintainAspectRatio: false,
scales: {
y: {
ticks: {
stepSize: 1,
},
},
y1: {
type: "linear",
position: "right",
min: -1,
max: gradeOrder.length,
ticks: {
stepSize: 1,
callback: (v) => {
const idx = Number(v)
return gradeOrder[idx] || ""
},
},
},
},
plugins: {
title: {
text: title.value,
display: true,
font: {
size: 20,
},
},
tooltip: {
callbacks: {
label: (ctx: TooltipItem<"bar">) => {
const dsLabel = ctx.dataset.label || ""
if ((ctx.dataset as any).yAxisID === "y1") {
const idx = Number(ctx.parsed.y)
return `${dsLabel}: ${gradeOrder[idx] || ""}`
}
return `${dsLabel}: ${ctx.formattedValue}`
},
},
},
},
}
})
</script>
<style scoped>
.chart {
height: 300px;
width: 100%;
}
</style>