add charts.
This commit is contained in:
46
package-lock.json
generated
46
package-lock.json
generated
@@ -12,6 +12,7 @@
|
|||||||
"@monaco-editor/loader": "^1.3.2",
|
"@monaco-editor/loader": "^1.3.2",
|
||||||
"@vueuse/core": "^9.11.1",
|
"@vueuse/core": "^9.11.1",
|
||||||
"axios": "1.2.3",
|
"axios": "1.2.3",
|
||||||
|
"chart.js": "^4.2.0",
|
||||||
"copy-text-to-clipboard": "^3.0.1",
|
"copy-text-to-clipboard": "^3.0.1",
|
||||||
"date-fns": "^2.29.3",
|
"date-fns": "^2.29.3",
|
||||||
"highlight.js": "^11.7.0",
|
"highlight.js": "^11.7.0",
|
||||||
@@ -19,6 +20,7 @@
|
|||||||
"party-js": "^2.2.0",
|
"party-js": "^2.2.0",
|
||||||
"pinia": "^2.0.29",
|
"pinia": "^2.0.29",
|
||||||
"vue": "^3.2.45",
|
"vue": "^3.2.45",
|
||||||
|
"vue-chartjs": "^5.2.0",
|
||||||
"vue-router": "^4.1.6"
|
"vue-router": "^4.1.6"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
@@ -485,6 +487,11 @@
|
|||||||
"resolved": "https://registry.npmmirror.com/@juggle/resize-observer/-/resize-observer-3.4.0.tgz",
|
"resolved": "https://registry.npmmirror.com/@juggle/resize-observer/-/resize-observer-3.4.0.tgz",
|
||||||
"integrity": "sha512-dfLbk+PwWvFzSxwk3n5ySL0hfBog779o8h68wK/7/APo/7cgyWp5jcXockbxdk5kFRkbeXWm4Fbi9FrdN381sA=="
|
"integrity": "sha512-dfLbk+PwWvFzSxwk3n5ySL0hfBog779o8h68wK/7/APo/7cgyWp5jcXockbxdk5kFRkbeXWm4Fbi9FrdN381sA=="
|
||||||
},
|
},
|
||||||
|
"node_modules/@kurkle/color": {
|
||||||
|
"version": "0.3.2",
|
||||||
|
"resolved": "https://registry.npmmirror.com/@kurkle/color/-/color-0.3.2.tgz",
|
||||||
|
"integrity": "sha512-fuscdXJ9G1qb7W8VdHi+IwRqij3lBkosAm4ydQtEmbY58OzHXqQhvlxqEkoz0yssNVn38bcpRWgA9PP+OGoisw=="
|
||||||
|
},
|
||||||
"node_modules/@mdit-vue/plugin-component": {
|
"node_modules/@mdit-vue/plugin-component": {
|
||||||
"version": "0.11.2",
|
"version": "0.11.2",
|
||||||
"resolved": "https://registry.npmmirror.com/@mdit-vue/plugin-component/-/plugin-component-0.11.2.tgz",
|
"resolved": "https://registry.npmmirror.com/@mdit-vue/plugin-component/-/plugin-component-0.11.2.tgz",
|
||||||
@@ -1008,6 +1015,17 @@
|
|||||||
"node": ">=8"
|
"node": ">=8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/chart.js": {
|
||||||
|
"version": "4.2.0",
|
||||||
|
"resolved": "https://registry.npmmirror.com/chart.js/-/chart.js-4.2.0.tgz",
|
||||||
|
"integrity": "sha512-wbtcV+QKeH0F7gQZaCJEIpsNriFheacouJQTVIjITi3eQA8bTlIBoknz0+dgV79aeKLNMAX+nDslIVE/nJ3rzA==",
|
||||||
|
"dependencies": {
|
||||||
|
"@kurkle/color": "^0.3.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"pnpm": "^7.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/chokidar": {
|
"node_modules/chokidar": {
|
||||||
"version": "3.5.3",
|
"version": "3.5.3",
|
||||||
"resolved": "https://registry.npmmirror.com/chokidar/-/chokidar-3.5.3.tgz",
|
"resolved": "https://registry.npmmirror.com/chokidar/-/chokidar-3.5.3.tgz",
|
||||||
@@ -2491,6 +2509,15 @@
|
|||||||
"@vue/shared": "3.2.45"
|
"@vue/shared": "3.2.45"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/vue-chartjs": {
|
||||||
|
"version": "5.2.0",
|
||||||
|
"resolved": "https://registry.npmmirror.com/vue-chartjs/-/vue-chartjs-5.2.0.tgz",
|
||||||
|
"integrity": "sha512-d3zpKmGZr2OWHQ1xmxBcAn5ShTG917+/UCLaSpaCDDqT0U7DBsvFzTs69ZnHCgKoXT55GZDW8YEj9Av+dlONLA==",
|
||||||
|
"peerDependencies": {
|
||||||
|
"chart.js": "^4.1.1",
|
||||||
|
"vue": "^3.0.0-0 || ^2.7.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/vue-router": {
|
"node_modules/vue-router": {
|
||||||
"version": "4.1.6",
|
"version": "4.1.6",
|
||||||
"resolved": "https://registry.npmmirror.com/vue-router/-/vue-router-4.1.6.tgz",
|
"resolved": "https://registry.npmmirror.com/vue-router/-/vue-router-4.1.6.tgz",
|
||||||
@@ -2824,6 +2851,11 @@
|
|||||||
"resolved": "https://registry.npmmirror.com/@juggle/resize-observer/-/resize-observer-3.4.0.tgz",
|
"resolved": "https://registry.npmmirror.com/@juggle/resize-observer/-/resize-observer-3.4.0.tgz",
|
||||||
"integrity": "sha512-dfLbk+PwWvFzSxwk3n5ySL0hfBog779o8h68wK/7/APo/7cgyWp5jcXockbxdk5kFRkbeXWm4Fbi9FrdN381sA=="
|
"integrity": "sha512-dfLbk+PwWvFzSxwk3n5ySL0hfBog779o8h68wK/7/APo/7cgyWp5jcXockbxdk5kFRkbeXWm4Fbi9FrdN381sA=="
|
||||||
},
|
},
|
||||||
|
"@kurkle/color": {
|
||||||
|
"version": "0.3.2",
|
||||||
|
"resolved": "https://registry.npmmirror.com/@kurkle/color/-/color-0.3.2.tgz",
|
||||||
|
"integrity": "sha512-fuscdXJ9G1qb7W8VdHi+IwRqij3lBkosAm4ydQtEmbY58OzHXqQhvlxqEkoz0yssNVn38bcpRWgA9PP+OGoisw=="
|
||||||
|
},
|
||||||
"@mdit-vue/plugin-component": {
|
"@mdit-vue/plugin-component": {
|
||||||
"version": "0.11.2",
|
"version": "0.11.2",
|
||||||
"resolved": "https://registry.npmmirror.com/@mdit-vue/plugin-component/-/plugin-component-0.11.2.tgz",
|
"resolved": "https://registry.npmmirror.com/@mdit-vue/plugin-component/-/plugin-component-0.11.2.tgz",
|
||||||
@@ -3275,6 +3307,14 @@
|
|||||||
"fill-range": "^7.0.1"
|
"fill-range": "^7.0.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"chart.js": {
|
||||||
|
"version": "4.2.0",
|
||||||
|
"resolved": "https://registry.npmmirror.com/chart.js/-/chart.js-4.2.0.tgz",
|
||||||
|
"integrity": "sha512-wbtcV+QKeH0F7gQZaCJEIpsNriFheacouJQTVIjITi3eQA8bTlIBoknz0+dgV79aeKLNMAX+nDslIVE/nJ3rzA==",
|
||||||
|
"requires": {
|
||||||
|
"@kurkle/color": "^0.3.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"chokidar": {
|
"chokidar": {
|
||||||
"version": "3.5.3",
|
"version": "3.5.3",
|
||||||
"resolved": "https://registry.npmmirror.com/chokidar/-/chokidar-3.5.3.tgz",
|
"resolved": "https://registry.npmmirror.com/chokidar/-/chokidar-3.5.3.tgz",
|
||||||
@@ -4375,6 +4415,12 @@
|
|||||||
"@vue/shared": "3.2.45"
|
"@vue/shared": "3.2.45"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"vue-chartjs": {
|
||||||
|
"version": "5.2.0",
|
||||||
|
"resolved": "https://registry.npmmirror.com/vue-chartjs/-/vue-chartjs-5.2.0.tgz",
|
||||||
|
"integrity": "sha512-d3zpKmGZr2OWHQ1xmxBcAn5ShTG917+/UCLaSpaCDDqT0U7DBsvFzTs69ZnHCgKoXT55GZDW8YEj9Av+dlONLA==",
|
||||||
|
"requires": {}
|
||||||
|
},
|
||||||
"vue-router": {
|
"vue-router": {
|
||||||
"version": "4.1.6",
|
"version": "4.1.6",
|
||||||
"resolved": "https://registry.npmmirror.com/vue-router/-/vue-router-4.1.6.tgz",
|
"resolved": "https://registry.npmmirror.com/vue-router/-/vue-router-4.1.6.tgz",
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
"@monaco-editor/loader": "^1.3.2",
|
"@monaco-editor/loader": "^1.3.2",
|
||||||
"@vueuse/core": "^9.11.1",
|
"@vueuse/core": "^9.11.1",
|
||||||
"axios": "1.2.3",
|
"axios": "1.2.3",
|
||||||
|
"chart.js": "^4.2.0",
|
||||||
"copy-text-to-clipboard": "^3.0.1",
|
"copy-text-to-clipboard": "^3.0.1",
|
||||||
"date-fns": "^2.29.3",
|
"date-fns": "^2.29.3",
|
||||||
"highlight.js": "^11.7.0",
|
"highlight.js": "^11.7.0",
|
||||||
@@ -21,6 +22,7 @@
|
|||||||
"party-js": "^2.2.0",
|
"party-js": "^2.2.0",
|
||||||
"pinia": "^2.0.29",
|
"pinia": "^2.0.29",
|
||||||
"vue": "^3.2.45",
|
"vue": "^3.2.45",
|
||||||
|
"vue-chartjs": "^5.2.0",
|
||||||
"vue-router": "^4.1.6"
|
"vue-router": "^4.1.6"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
|||||||
@@ -1,32 +1,72 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import Monaco from "../shared/Monaco.vue"
|
import Monaco from "~/shared/Monaco.vue"
|
||||||
import raw from "./step-1/1.c?raw"
|
import { isDesktop } from "~/shared/composables/breakpoints"
|
||||||
|
|
||||||
const route = useRoute()
|
const route = useRoute()
|
||||||
const id = route.hash.replace("#step-", "") || "1"
|
const router = useRouter()
|
||||||
|
|
||||||
const Md = defineAsyncComponent(() => import(`./step-${id}/index.md`))
|
const TOTAL = 3
|
||||||
|
|
||||||
const code = ref(raw)
|
const Mds = Array.from({ length: TOTAL }, (_, i) => i + 1).map((v) =>
|
||||||
|
defineAsyncComponent(() => import(`./step-${v}/index.md`))
|
||||||
|
)
|
||||||
|
const code = ref("")
|
||||||
|
const step = computed(() => {
|
||||||
|
if (!route.params.step || !route.params.step.length) return 1
|
||||||
|
else {
|
||||||
|
return parseInt(route.params.step[0].split("-")[1])
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
function change(value: string) {
|
watch(
|
||||||
code.value = value
|
() => route.params.step,
|
||||||
|
async (value) => {
|
||||||
|
if (route.name !== "learn") return
|
||||||
|
try {
|
||||||
|
const raw = await import(`./${value[0]}/main.c?raw`)
|
||||||
|
code.value = raw.default
|
||||||
|
} catch (err) {
|
||||||
|
router.replace("/learn/step-1")
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ immediate: true }
|
||||||
|
)
|
||||||
|
|
||||||
|
function change(v: string) {
|
||||||
|
code.value = v
|
||||||
|
}
|
||||||
|
function prev() {
|
||||||
|
router.push(`/learn/step-${step.value - 1}`)
|
||||||
|
}
|
||||||
|
function next() {
|
||||||
|
router.push(`/learn/step-${step.value + 1}`)
|
||||||
|
}
|
||||||
|
function run() {
|
||||||
|
console.log(code.value)
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<n-grid :cols="2">
|
<n-grid v-if="isDesktop" :cols="24">
|
||||||
<n-gi>
|
<n-gi :span="10">
|
||||||
<Md />
|
<n-scrollbar style="max-height: calc(100vh - 92px)">
|
||||||
<n-space justify="space-between">
|
<component :is="Mds[step - 1]"></component>
|
||||||
<n-button text type="primary">上一步</n-button>
|
<n-space justify="space-around">
|
||||||
<n-button text type="primary">下一步</n-button>
|
<n-button v-if="step !== 1" text type="primary" @click="prev">
|
||||||
</n-space>
|
上一步
|
||||||
|
</n-button>
|
||||||
|
<n-button v-if="step !== TOTAL" text type="primary" @click="next">
|
||||||
|
下一步
|
||||||
|
</n-button>
|
||||||
|
</n-space>
|
||||||
|
</n-scrollbar>
|
||||||
</n-gi>
|
</n-gi>
|
||||||
<n-gi>
|
<n-gi :span="14" class="relative">
|
||||||
|
<n-button type="primary" class="action" @click="run">运行</n-button>
|
||||||
<Monaco :value="code" @change="change" />
|
<Monaco :value="code" @change="change" />
|
||||||
|
<div></div>
|
||||||
</n-gi>
|
</n-gi>
|
||||||
</n-grid>
|
</n-grid>
|
||||||
|
<div v-else></div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
@@ -64,4 +104,15 @@ function change(value: string) {
|
|||||||
text-align: right;
|
text-align: right;
|
||||||
color: rgba(115, 138, 148, 0.4);
|
color: rgba(115, 138, 148, 0.4);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.relative {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.action {
|
||||||
|
position: absolute;
|
||||||
|
top: 10px;
|
||||||
|
right: 10px;
|
||||||
|
z-index: 10;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -13,3 +13,99 @@ int main() {
|
|||||||
```
|
```
|
||||||
|
|
||||||
123
|
123
|
||||||
|
|
||||||
|
# 11
|
||||||
|
|
||||||
|
## 1
|
||||||
|
|
||||||
|
哈哈
|
||||||
|
|
||||||
|
```c {3-4}
|
||||||
|
#include<stdio.h>
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
123
|
||||||
|
|
||||||
|
# 11
|
||||||
|
|
||||||
|
## 1
|
||||||
|
|
||||||
|
哈哈
|
||||||
|
|
||||||
|
```c {3-4}
|
||||||
|
#include<stdio.h>
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
123
|
||||||
|
|
||||||
|
# 11
|
||||||
|
|
||||||
|
## 1
|
||||||
|
|
||||||
|
哈哈
|
||||||
|
|
||||||
|
```c {3-4}
|
||||||
|
#include<stdio.h>
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
123
|
||||||
|
|
||||||
|
# 11
|
||||||
|
|
||||||
|
## 1
|
||||||
|
|
||||||
|
哈哈
|
||||||
|
|
||||||
|
```c {3-4}
|
||||||
|
#include<stdio.h>
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
123
|
||||||
|
|
||||||
|
# 11
|
||||||
|
|
||||||
|
## 1
|
||||||
|
|
||||||
|
哈哈
|
||||||
|
|
||||||
|
```c {3-4}
|
||||||
|
#include<stdio.h>
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
123
|
||||||
|
|
||||||
|
# 11
|
||||||
|
|
||||||
|
## 1
|
||||||
|
|
||||||
|
哈哈
|
||||||
|
|
||||||
|
```c {3-4}
|
||||||
|
#include<stdio.h>
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
123
|
||||||
|
|||||||
1
src/learn/step-2/index.md
Normal file
1
src/learn/step-2/index.md
Normal file
@@ -0,0 +1 @@
|
|||||||
|
asas
|
||||||
1
src/learn/step-2/main.c
Normal file
1
src/learn/step-2/main.c
Normal file
@@ -0,0 +1 @@
|
|||||||
|
1212121212
|
||||||
0
src/learn/step-3/index.md
Normal file
0
src/learn/step-3/index.md
Normal file
0
src/learn/step-3/main.c
Normal file
0
src/learn/step-3/main.c
Normal file
28
src/main.ts
28
src/main.ts
@@ -8,7 +8,19 @@ import { routes } from "./routes"
|
|||||||
import App from "./App.vue"
|
import App from "./App.vue"
|
||||||
|
|
||||||
import { toggleLogin } from "./shared/composables/modal"
|
import { toggleLogin } from "./shared/composables/modal"
|
||||||
import { init } from "./shared/composables/monaco"
|
import { init as monacoInit } from "./shared/composables/monaco"
|
||||||
|
|
||||||
|
import {
|
||||||
|
Chart as ChartJS,
|
||||||
|
Title,
|
||||||
|
Colors,
|
||||||
|
Tooltip,
|
||||||
|
Legend,
|
||||||
|
BarElement,
|
||||||
|
ArcElement,
|
||||||
|
CategoryScale,
|
||||||
|
LinearScale,
|
||||||
|
} from "chart.js"
|
||||||
|
|
||||||
const router = createRouter({
|
const router = createRouter({
|
||||||
history: createWebHistory(),
|
history: createWebHistory(),
|
||||||
@@ -26,7 +38,19 @@ router.beforeEach((to, from, next) => {
|
|||||||
next()
|
next()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
init()
|
|
||||||
|
monacoInit()
|
||||||
|
|
||||||
|
ChartJS.register(
|
||||||
|
CategoryScale,
|
||||||
|
LinearScale,
|
||||||
|
BarElement,
|
||||||
|
ArcElement,
|
||||||
|
Colors,
|
||||||
|
Title,
|
||||||
|
Tooltip,
|
||||||
|
Legend
|
||||||
|
)
|
||||||
const pinia = createPinia()
|
const pinia = createPinia()
|
||||||
const app = createApp(App)
|
const app = createApp(App)
|
||||||
app.use(router)
|
app.use(router)
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { DIFFICULTY } from "utils/constants"
|
import { Pie } from "vue-chartjs"
|
||||||
|
import { DIFFICULTY, JUDGE_STATUS } from "utils/constants"
|
||||||
import { getACRate, getTagColor, parseTime } from "utils/functions"
|
import { getACRate, getTagColor, parseTime } from "utils/functions"
|
||||||
import { isDesktop } from "~/shared/composables/breakpoints"
|
import { isDesktop } from "~/shared/composables/breakpoints"
|
||||||
import { Problem } from "utils/types"
|
import { Problem } from "utils/types"
|
||||||
@@ -7,7 +8,30 @@ import { Problem } from "utils/types"
|
|||||||
interface Props {
|
interface Props {
|
||||||
problem: Problem
|
problem: Problem
|
||||||
}
|
}
|
||||||
defineProps<Props>()
|
const props = defineProps<Props>()
|
||||||
|
|
||||||
|
const data = computed(() => {
|
||||||
|
const status = props.problem.statistic_info
|
||||||
|
const labels = []
|
||||||
|
for (let i in status) {
|
||||||
|
if (status[i] === 0) {
|
||||||
|
delete status[i]
|
||||||
|
}
|
||||||
|
// @ts-ignore
|
||||||
|
labels.push(JUDGE_STATUS[i]["name"])
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
labels,
|
||||||
|
datasets: [{ data: Object.values(status), hoverOffset: 4 }],
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const options = ref({
|
||||||
|
responsive: true,
|
||||||
|
plugins: {
|
||||||
|
title: { text: "提交结果的比例", display: true, font: { size: 20 } },
|
||||||
|
},
|
||||||
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
@@ -49,4 +73,14 @@ defineProps<Props>()
|
|||||||
</n-space>
|
</n-space>
|
||||||
</n-descriptions-item>
|
</n-descriptions-item>
|
||||||
</n-descriptions>
|
</n-descriptions>
|
||||||
|
<div class="pie">
|
||||||
|
<Pie :data="data" :options="options" />
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
<style scoped>
|
||||||
|
.pie {
|
||||||
|
width: 100%;
|
||||||
|
max-width: 500px;
|
||||||
|
margin: 24px auto;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|||||||
88
src/oj/rank/components/Chart.vue
Normal file
88
src/oj/rank/components/Chart.vue
Normal file
@@ -0,0 +1,88 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { Bar } from "vue-chartjs"
|
||||||
|
import { Rank } from "~/utils/types"
|
||||||
|
|
||||||
|
const props = defineProps<{ rankData: Rank[] }>()
|
||||||
|
|
||||||
|
const data = computed(() => ({
|
||||||
|
labels: props.rankData.map((rank) => rank.user.username),
|
||||||
|
datasets: [
|
||||||
|
{
|
||||||
|
label: "已解决",
|
||||||
|
data: props.rankData.map((rank) => rank.accepted_number),
|
||||||
|
backgroundColor: [
|
||||||
|
"rgba(255, 99, 132, 0.2)",
|
||||||
|
"rgba(255, 159, 64, 0.2)",
|
||||||
|
"rgba(55, 66, 250, 0.2)",
|
||||||
|
"rgba(75, 192, 192, 0.2)",
|
||||||
|
"rgba(54, 162, 235, 0.2)",
|
||||||
|
"rgba(153, 102, 255, 0.2)",
|
||||||
|
"rgba(48, 51, 107, 0.2)",
|
||||||
|
"rgba(249, 202, 36, 0.2)",
|
||||||
|
"rgba(106, 176, 76, 0.2)",
|
||||||
|
"rgba(119, 139, 235, 0.2)",
|
||||||
|
],
|
||||||
|
borderColor: [
|
||||||
|
"rgba(255, 99, 132, 0.6)",
|
||||||
|
"rgba(255, 159, 64, 0.6)",
|
||||||
|
"rgba(55, 66, 250, 0.6)",
|
||||||
|
"rgba(75, 192, 192, 0.6)",
|
||||||
|
"rgba(54, 162, 235, 0.6)",
|
||||||
|
"rgba(153, 102, 255, 0.6)",
|
||||||
|
"rgba(48, 51, 107, 0.6)",
|
||||||
|
"rgba(249, 202, 36, 0.6)",
|
||||||
|
"rgba(106, 176, 76, 0.6)",
|
||||||
|
"rgba(119, 139, 235, 0.6)",
|
||||||
|
],
|
||||||
|
hoverBackgroundColor: [
|
||||||
|
"rgba(255, 99, 132, 0.8)",
|
||||||
|
"rgba(255, 159, 64, 0.8)",
|
||||||
|
"rgba(55, 66, 250, 0.8)",
|
||||||
|
"rgba(75, 192, 192, 0.8)",
|
||||||
|
"rgba(54, 162, 235, 0.8)",
|
||||||
|
"rgba(153, 102, 255, 0.8)",
|
||||||
|
"rgba(48, 51, 107, 0.8)",
|
||||||
|
"rgba(249, 202, 36, 0.8)",
|
||||||
|
"rgba(106, 176, 76, 0.8)",
|
||||||
|
"rgba(119, 139, 235, 0.8)",
|
||||||
|
],
|
||||||
|
hoverBorderColor: [
|
||||||
|
"rgba(255, 99, 132, 1)",
|
||||||
|
"rgba(255, 159, 64, 1)",
|
||||||
|
"rgba(55, 66, 250, 1)",
|
||||||
|
"rgba(75, 192, 192, 1)",
|
||||||
|
"rgba(54, 162, 235, 1)",
|
||||||
|
"rgba(153, 102, 255, 1)",
|
||||||
|
"rgba(48, 51, 107, 1)",
|
||||||
|
"rgba(249, 202, 36, 1)",
|
||||||
|
"rgba(106, 176, 76, 1)",
|
||||||
|
"rgba(119, 139, 235, 1)",
|
||||||
|
],
|
||||||
|
borderWidth: 2,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "总提交数",
|
||||||
|
data: props.rankData.map((rank) => rank.submission_number),
|
||||||
|
hidden: true,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}))
|
||||||
|
|
||||||
|
const options = ref({
|
||||||
|
plugins: {
|
||||||
|
title: {
|
||||||
|
text: "全校前十名的提交者(不包括超管)",
|
||||||
|
display: true,
|
||||||
|
font: { size: 20 },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
<template>
|
||||||
|
<Bar class="chart" :data="data" :options="options" />
|
||||||
|
</template>
|
||||||
|
<style scoped>
|
||||||
|
.chart {
|
||||||
|
margin-bottom: 24px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { DataTableColumn, NButton, NButtonGroup } from "naive-ui"
|
import { DataTableColumn, NButton } from "naive-ui"
|
||||||
|
import Chart from "./components/Chart.vue"
|
||||||
import Pagination from "~/shared/Pagination.vue"
|
import Pagination from "~/shared/Pagination.vue"
|
||||||
import { Rank } from "utils/types"
|
import { Rank } from "utils/types"
|
||||||
import { getRank } from "oj/api"
|
import { getRank } from "oj/api"
|
||||||
@@ -11,13 +12,18 @@ const query = reactive({
|
|||||||
limit: 10,
|
limit: 10,
|
||||||
page: 1,
|
page: 1,
|
||||||
})
|
})
|
||||||
|
const rankData = ref<Rank[]>([])
|
||||||
|
|
||||||
async function listRanks() {
|
async function listRanks() {
|
||||||
const offset = (query.page - 1) * query.limit
|
const offset = (query.page - 1) * query.limit
|
||||||
const res = await getRank(offset, query.limit)
|
const res = await getRank(offset, query.limit)
|
||||||
data.value = res.data.results
|
data.value = res.data.results
|
||||||
total.value = res.data.total
|
total.value = res.data.total
|
||||||
|
if (query.page === 1) {
|
||||||
|
rankData.value = data.value
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const columns: DataTableColumn<Rank>[] = [
|
const columns: DataTableColumn<Rank>[] = [
|
||||||
{
|
{
|
||||||
title: "排名",
|
title: "排名",
|
||||||
@@ -61,6 +67,7 @@ onMounted(listRanks)
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
<Chart v-if="!!rankData.length" :rankData="rankData" />
|
||||||
<n-data-table striped size="small" :data="data" :columns="columns" />
|
<n-data-table striped size="small" :data="data" :columns="columns" />
|
||||||
<Pagination
|
<Pagination
|
||||||
:total="total"
|
:total="total"
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
export const routes = [
|
import { RouteRecordRaw } from "vue-router"
|
||||||
|
|
||||||
|
export const routes: RouteRecordRaw[] = [
|
||||||
{
|
{
|
||||||
path: "/",
|
path: "/",
|
||||||
component: () => import("~/shared/layout/default.vue"),
|
component: () => import("~/shared/layout/default.vue"),
|
||||||
@@ -41,7 +43,12 @@ export const routes = [
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: "learn",
|
path: "learn",
|
||||||
|
redirect: "learn/step-1",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: "learn/:step+",
|
||||||
component: () => import("learn/index.vue"),
|
component: () => import("learn/index.vue"),
|
||||||
|
name: "learn",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ const defaultValue = computed(() => route.path.split("/")[1] || "problem")
|
|||||||
const menus: MenuOption[] = [
|
const menus: MenuOption[] = [
|
||||||
{
|
{
|
||||||
label: () =>
|
label: () =>
|
||||||
h(RouterLink, { to: "/learn#step-1" }, { default: () => "自学" }),
|
h(RouterLink, { to: "/learn/step-1" }, { default: () => "自学" }),
|
||||||
key: "learn",
|
key: "learn",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -96,7 +96,7 @@ export interface Problem {
|
|||||||
total_score: number
|
total_score: number
|
||||||
submission_number: number
|
submission_number: number
|
||||||
accepted_number: number
|
accepted_number: number
|
||||||
statistic_info: {}
|
statistic_info: { [key in string]: number }
|
||||||
share_submission: boolean
|
share_submission: boolean
|
||||||
contest: null
|
contest: null
|
||||||
my_status: number
|
my_status: number
|
||||||
|
|||||||
Reference in New Issue
Block a user