@@ -88,16 +88,24 @@
|
|||||||
striped
|
striped
|
||||||
:columns="columns"
|
:columns="columns"
|
||||||
:data="list"
|
:data="list"
|
||||||
|
:row-key="rowKey"
|
||||||
|
:expanded-row-keys="expandedRowKeys"
|
||||||
|
@update:expanded-row-keys="updateExpandedRowKeys"
|
||||||
|
:row-props="rowProps"
|
||||||
/>
|
/>
|
||||||
</n-tab-pane>
|
</n-tab-pane>
|
||||||
</n-tabs>
|
</n-tabs>
|
||||||
</template>
|
</template>
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
import { h } from "vue"
|
||||||
import { formatISO, sub, type Duration } from "date-fns"
|
import { formatISO, sub, type Duration } from "date-fns"
|
||||||
import { getSubmissionStatistics } from "oj/api"
|
import { getSubmissionStatistics } from "oj/api"
|
||||||
import { DURATION_OPTIONS } from "utils/constants"
|
import { DURATION_OPTIONS } from "utils/constants"
|
||||||
import { Doughnut } from "vue-chartjs"
|
import { Doughnut } from "vue-chartjs"
|
||||||
import { Chart as ChartJS, ArcElement, Title, Tooltip, Legend } from "chart.js"
|
import { Chart as ChartJS, ArcElement, Title, Tooltip, Legend } from "chart.js"
|
||||||
|
import { NButton, NFlex, NText, type DataTableRowKey } from "naive-ui"
|
||||||
|
import { JUDGE_STATUS } from "utils/constants"
|
||||||
|
import type { SUBMISSION_RESULT } from "utils/types"
|
||||||
|
|
||||||
// 注册 Chart.js 组件
|
// 注册 Chart.js 组件
|
||||||
ChartJS.register(ArcElement, Title, Tooltip, Legend)
|
ChartJS.register(ArcElement, Title, Tooltip, Legend)
|
||||||
@@ -115,7 +123,34 @@ const options: SelectOption[] = [
|
|||||||
{ label: "30分钟内", value: "minutes:30" },
|
{ label: "30分钟内", value: "minutes:30" },
|
||||||
].concat(DURATION_OPTIONS)
|
].concat(DURATION_OPTIONS)
|
||||||
|
|
||||||
const columns: DataTableColumn[] = [
|
function openSubmission(id: string) {
|
||||||
|
window.open(`/submission/${id}`, "_blank", "noopener")
|
||||||
|
}
|
||||||
|
|
||||||
|
const columns: DataTableColumn<UserStatistic>[] = [
|
||||||
|
{
|
||||||
|
type: "expand",
|
||||||
|
renderExpand: (row) => {
|
||||||
|
return h(NFlex, { size: "small", wrap: true }, () =>
|
||||||
|
row.submission_items.map((item) =>
|
||||||
|
h(
|
||||||
|
NButton,
|
||||||
|
{
|
||||||
|
size: "small",
|
||||||
|
tertiary: true,
|
||||||
|
type: JUDGE_STATUS[item.result]?.type ?? "default",
|
||||||
|
style: "width: 120px",
|
||||||
|
onClick: (event: MouseEvent) => {
|
||||||
|
event.stopPropagation()
|
||||||
|
openSubmission(item.id)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
() => item.id.toString().slice(0, 12),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
},
|
||||||
|
},
|
||||||
{ title: "用户", key: "username" },
|
{ title: "用户", key: "username" },
|
||||||
{ title: "提交数", key: "submission_count" },
|
{ title: "提交数", key: "submission_count" },
|
||||||
{ title: "已解决", key: "accepted_count" },
|
{ title: "已解决", key: "accepted_count" },
|
||||||
@@ -145,11 +180,16 @@ interface UserStatistic {
|
|||||||
submission_count: number
|
submission_count: number
|
||||||
accepted_count: number
|
accepted_count: number
|
||||||
correct_rate: string
|
correct_rate: string
|
||||||
|
submission_items: Array<{
|
||||||
|
id: string
|
||||||
|
result: SUBMISSION_RESULT
|
||||||
|
}>
|
||||||
}
|
}
|
||||||
|
|
||||||
const list = ref<UserStatistic[]>([])
|
const list = ref<UserStatistic[]>([])
|
||||||
const listUnaccepted = ref<string[]>([])
|
const listUnaccepted = ref<string[]>([])
|
||||||
const [unaccepted, toggleUnaccepted] = useToggle()
|
const [unaccepted, toggleUnaccepted] = useToggle()
|
||||||
|
const expandedRowKeys = ref<DataTableRowKey[]>([])
|
||||||
|
|
||||||
// 饼图数据 - 提交正确率分布
|
// 饼图数据 - 提交正确率分布
|
||||||
const pieChartData = computed(() => {
|
const pieChartData = computed(() => {
|
||||||
@@ -270,5 +310,24 @@ async function handleStatistics() {
|
|||||||
|
|
||||||
toggleUnaccepted(false)
|
toggleUnaccepted(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function rowKey(row: UserStatistic): DataTableRowKey {
|
||||||
|
return row.username
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateExpandedRowKeys(keys: DataTableRowKey[]) {
|
||||||
|
expandedRowKeys.value = keys.slice(-1)
|
||||||
|
}
|
||||||
|
|
||||||
|
function rowProps(row: UserStatistic) {
|
||||||
|
return {
|
||||||
|
style: "cursor: pointer;",
|
||||||
|
onClick: () => {
|
||||||
|
const key = rowKey(row)
|
||||||
|
const isExpanded = expandedRowKeys.value.includes(key)
|
||||||
|
expandedRowKeys.value = isExpanded ? [] : [key]
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
<style scoped></style>
|
<style scoped></style>
|
||||||
|
|||||||
Reference in New Issue
Block a user