更新首页列表
This commit is contained in:
@@ -36,7 +36,7 @@ export function getWebsiteConfig() {
|
||||
export async function getProblemList(
|
||||
offset = 0,
|
||||
limit = 10,
|
||||
searchParams: any = {}
|
||||
searchParams: any = {},
|
||||
) {
|
||||
let params: any = {
|
||||
paging: true,
|
||||
@@ -129,7 +129,7 @@ export async function getContestProblems(contestID: string) {
|
||||
|
||||
export function getContestRank(
|
||||
contestID: string,
|
||||
query: { limit: number; offset: number; force_refresh: "1" | "0" }
|
||||
query: { limit: number; offset: number; force_refresh: "1" | "0" },
|
||||
) {
|
||||
return http.get("contest_rank", {
|
||||
params: {
|
||||
|
||||
@@ -24,7 +24,7 @@ const passwordFormVisible = computed(
|
||||
() =>
|
||||
contestStore.isPrivate &&
|
||||
!contestStore.access &&
|
||||
!contestStore.isContestAdmin
|
||||
!contestStore.isContestAdmin,
|
||||
)
|
||||
</script>
|
||||
|
||||
|
||||
@@ -37,7 +37,7 @@ const columns: DataTableColumn<Contest>[] = [
|
||||
h(
|
||||
NTag,
|
||||
{ type: CONTEST_STATUS[row.status]["type"] },
|
||||
() => CONTEST_STATUS[row.status]["name"]
|
||||
() => CONTEST_STATUS[row.status]["name"],
|
||||
),
|
||||
},
|
||||
{
|
||||
@@ -95,13 +95,13 @@ watch(
|
||||
() => {
|
||||
query.page = 1
|
||||
routerPush()
|
||||
}
|
||||
},
|
||||
)
|
||||
watch(
|
||||
() => route.name === "contests" && route.query,
|
||||
(newVal) => {
|
||||
if (newVal) listContests()
|
||||
}
|
||||
},
|
||||
)
|
||||
|
||||
function rowProps(row: Contest) {
|
||||
|
||||
@@ -33,7 +33,7 @@ const { resume, pause } = useIntervalFn(
|
||||
10000,
|
||||
{
|
||||
immediate: false,
|
||||
}
|
||||
},
|
||||
)
|
||||
|
||||
const query = reactive({
|
||||
@@ -64,7 +64,7 @@ const columns = ref<DataTableColumn<ContestRank>[]>([
|
||||
type: "info",
|
||||
onClick: () => router.push("/user?name=" + row.user.username),
|
||||
},
|
||||
() => row.user.username
|
||||
() => row.user.username,
|
||||
),
|
||||
},
|
||||
{
|
||||
@@ -119,7 +119,7 @@ async function addColumns() {
|
||||
window.open(data.href, "_blank")
|
||||
},
|
||||
},
|
||||
() => problem.title
|
||||
() => problem.title,
|
||||
),
|
||||
render: (row) => {
|
||||
if (row.submission_info[problem.id]) {
|
||||
@@ -134,7 +134,7 @@ async function addColumns() {
|
||||
h(
|
||||
NIcon,
|
||||
{ size: 16, style: "transform: translate(-2px, 3px)" },
|
||||
() => h(GoldMedal)
|
||||
() => h(GoldMedal),
|
||||
),
|
||||
secondsToDuration(status.ac_time),
|
||||
]
|
||||
@@ -143,7 +143,7 @@ async function addColumns() {
|
||||
errorNumber = h(
|
||||
"p",
|
||||
{ style: "margin: 0" },
|
||||
`(-${status.error_number})`
|
||||
`(-${status.error_number})`,
|
||||
)
|
||||
}
|
||||
return h("div", [acTime, errorNumber])
|
||||
@@ -182,7 +182,7 @@ watch(
|
||||
() => {
|
||||
query.page = 1
|
||||
listRanks()
|
||||
}
|
||||
},
|
||||
)
|
||||
watch(autoRefresh, (checked) => (checked ? resume() : pause()))
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ const contestID = !!route.params.contestID ? route.params.contestID : null
|
||||
|
||||
const storageKey = computed(
|
||||
() =>
|
||||
`problem_${problem.value!._id}_contest_${contestID}_lang_${code.language}`
|
||||
`problem_${problem.value!._id}_contest_${contestID}_lang_${code.language}`,
|
||||
)
|
||||
|
||||
onMounted(() => {
|
||||
@@ -26,7 +26,7 @@ onMounted(() => {
|
||||
})
|
||||
|
||||
const editorHeight = computed(() =>
|
||||
isDesktop.value ? "calc(100vh - 133px)" : "calc(100vh - 172px)"
|
||||
isDesktop.value ? "calc(100vh - 133px)" : "calc(100vh - 172px)",
|
||||
)
|
||||
|
||||
function changeCode(v: string) {
|
||||
|
||||
@@ -23,7 +23,7 @@ const samples = ref<Sample[]>(
|
||||
msg: "",
|
||||
status: "not_test",
|
||||
loading: false,
|
||||
}))
|
||||
})),
|
||||
)
|
||||
|
||||
async function test(sample: Sample, index: number) {
|
||||
@@ -202,7 +202,8 @@ function type(status: ProblemStatus) {
|
||||
border: 1px solid rgb(239, 239, 245);
|
||||
word-break: break-word;
|
||||
box-sizing: border-box;
|
||||
transition: background-color 0.3s cubic-bezier(0.4, 0, 0.2, 1),
|
||||
transition:
|
||||
background-color 0.3s cubic-bezier(0.4, 0, 0.2, 1),
|
||||
border-color 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
}
|
||||
|
||||
@@ -219,13 +220,15 @@ function type(status: ProblemStatus) {
|
||||
width: 100%;
|
||||
border-spacing: 0;
|
||||
border: 1px solid rgba(239, 239, 245, 1);
|
||||
transition: background-color 0.3s cubic-bezier(0.4, 0, 0.2, 1),
|
||||
transition:
|
||||
background-color 0.3s cubic-bezier(0.4, 0, 0.2, 1),
|
||||
border-color 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
}
|
||||
|
||||
.problemContent > .content > table th {
|
||||
background-color: rgba(250, 250, 252, 1);
|
||||
transition: background-color 0.3s cubic-bezier(0.4, 0, 0.2, 1),
|
||||
transition:
|
||||
background-color 0.3s cubic-bezier(0.4, 0, 0.2, 1),
|
||||
border-color 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,100 +1,100 @@
|
||||
<script lang="ts" setup>
|
||||
import { useUserStore } from "~/shared/store/user"
|
||||
import { Submission } from "~/utils/types"
|
||||
import { parseTime } from "~/utils/functions"
|
||||
import { LANGUAGE_SHOW_VALUE } from "~/utils/constants"
|
||||
import { getSubmissions } from "~/oj/api"
|
||||
import { isDesktop } from "~/shared/composables/breakpoints"
|
||||
import SubmissionResultTag from "~/shared/SubmissionResultTag.vue"
|
||||
import Pagination from "~/shared/Pagination.vue"
|
||||
import { NButton } from "naive-ui"
|
||||
|
||||
const userStore = useUserStore()
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
|
||||
const columns: DataTableColumn<Submission>[] = [
|
||||
{
|
||||
title: "提交时间",
|
||||
key: "create_time",
|
||||
width: 200,
|
||||
render: (row) =>
|
||||
parseTime(
|
||||
row.create_time,
|
||||
isDesktop ? "YYYY-MM-DD HH:mm:ss" : "M-D hh:mm"
|
||||
),
|
||||
},
|
||||
{
|
||||
title: "编号",
|
||||
key: "id",
|
||||
minWidth: 160,
|
||||
render: (row) => {
|
||||
if (row.show_link) {
|
||||
return h(
|
||||
NButton,
|
||||
{
|
||||
text: true,
|
||||
type: "info",
|
||||
onClick: () => {
|
||||
const data = router.resolve("/submission/" + row.id)
|
||||
window.open(data.href, "_blank")
|
||||
},
|
||||
},
|
||||
() => row.id.slice(0, 12)
|
||||
)
|
||||
} else {
|
||||
return row.id.slice(0, 12)
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
title: "状态",
|
||||
key: "status",
|
||||
width: 140,
|
||||
render: (row) => h(SubmissionResultTag, { result: row.result }),
|
||||
},
|
||||
{
|
||||
title: "语言",
|
||||
key: "language",
|
||||
width: 100,
|
||||
render: (row) => LANGUAGE_SHOW_VALUE[row.language],
|
||||
},
|
||||
]
|
||||
|
||||
const submissions = ref<Submission[]>([])
|
||||
const total = ref(0)
|
||||
const query = reactive({
|
||||
limit: 10,
|
||||
page: 1,
|
||||
})
|
||||
|
||||
async function listSubmissions() {
|
||||
const offset = query.limit * (query.page - 1)
|
||||
const res = await getSubmissions({
|
||||
...query,
|
||||
myself: "1",
|
||||
offset,
|
||||
problem_id: <string>route.params.problemID ?? "",
|
||||
contest_id: <string>route.params.contestID ?? "",
|
||||
})
|
||||
submissions.value = res.data.results
|
||||
total.value = res.data.total
|
||||
}
|
||||
onMounted(listSubmissions)
|
||||
watch(query, listSubmissions)
|
||||
</script>
|
||||
<template>
|
||||
<n-data-table
|
||||
v-if="userStore.isAuthed"
|
||||
striped
|
||||
:columns="columns"
|
||||
:data="submissions"
|
||||
/>
|
||||
<Pagination
|
||||
v-if="userStore.isAuthed"
|
||||
:total="total"
|
||||
v-model:limit="query.limit"
|
||||
v-model:page="query.page"
|
||||
/>
|
||||
<n-alert type="error" v-if="!userStore.isAuthed" title="请先登录" />
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { useUserStore } from "~/shared/store/user"
|
||||
import { Submission } from "~/utils/types"
|
||||
import { parseTime } from "~/utils/functions"
|
||||
import { LANGUAGE_SHOW_VALUE } from "~/utils/constants"
|
||||
import { getSubmissions } from "~/oj/api"
|
||||
import { isDesktop } from "~/shared/composables/breakpoints"
|
||||
import SubmissionResultTag from "~/shared/SubmissionResultTag.vue"
|
||||
import Pagination from "~/shared/Pagination.vue"
|
||||
import { NButton } from "naive-ui"
|
||||
|
||||
const userStore = useUserStore()
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
|
||||
const columns: DataTableColumn<Submission>[] = [
|
||||
{
|
||||
title: "提交时间",
|
||||
key: "create_time",
|
||||
width: 200,
|
||||
render: (row) =>
|
||||
parseTime(
|
||||
row.create_time,
|
||||
isDesktop ? "YYYY-MM-DD HH:mm:ss" : "M-D hh:mm",
|
||||
),
|
||||
},
|
||||
{
|
||||
title: "编号",
|
||||
key: "id",
|
||||
minWidth: 160,
|
||||
render: (row) => {
|
||||
if (row.show_link) {
|
||||
return h(
|
||||
NButton,
|
||||
{
|
||||
text: true,
|
||||
type: "info",
|
||||
onClick: () => {
|
||||
const data = router.resolve("/submission/" + row.id)
|
||||
window.open(data.href, "_blank")
|
||||
},
|
||||
},
|
||||
() => row.id.slice(0, 12),
|
||||
)
|
||||
} else {
|
||||
return row.id.slice(0, 12)
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
title: "状态",
|
||||
key: "status",
|
||||
width: 140,
|
||||
render: (row) => h(SubmissionResultTag, { result: row.result }),
|
||||
},
|
||||
{
|
||||
title: "语言",
|
||||
key: "language",
|
||||
width: 100,
|
||||
render: (row) => LANGUAGE_SHOW_VALUE[row.language],
|
||||
},
|
||||
]
|
||||
|
||||
const submissions = ref<Submission[]>([])
|
||||
const total = ref(0)
|
||||
const query = reactive({
|
||||
limit: 10,
|
||||
page: 1,
|
||||
})
|
||||
|
||||
async function listSubmissions() {
|
||||
const offset = query.limit * (query.page - 1)
|
||||
const res = await getSubmissions({
|
||||
...query,
|
||||
myself: "1",
|
||||
offset,
|
||||
problem_id: <string>route.params.problemID ?? "",
|
||||
contest_id: <string>route.params.contestID ?? "",
|
||||
})
|
||||
submissions.value = res.data.results
|
||||
total.value = res.data.total
|
||||
}
|
||||
onMounted(listSubmissions)
|
||||
watch(query, listSubmissions)
|
||||
</script>
|
||||
<template>
|
||||
<n-data-table
|
||||
v-if="userStore.isAuthed"
|
||||
striped
|
||||
:columns="columns"
|
||||
:data="submissions"
|
||||
/>
|
||||
<Pagination
|
||||
v-if="userStore.isAuthed"
|
||||
:total="total"
|
||||
v-model:limit="query.limit"
|
||||
v-model:page="query.page"
|
||||
/>
|
||||
<n-alert type="error" v-if="!userStore.isAuthed" title="请先登录" />
|
||||
</template>
|
||||
|
||||
@@ -39,17 +39,21 @@ const { start: fetchSubmission } = useTimeoutFn(
|
||||
}
|
||||
},
|
||||
2000,
|
||||
{ immediate: false }
|
||||
{ immediate: false },
|
||||
)
|
||||
|
||||
const judging = computed(
|
||||
() =>
|
||||
!!(submission.value && submission.value.result === SubmissionStatus.judging)
|
||||
!!(
|
||||
submission.value && submission.value.result === SubmissionStatus.judging
|
||||
),
|
||||
)
|
||||
|
||||
const pending = computed(
|
||||
() =>
|
||||
!!(submission.value && submission.value.result === SubmissionStatus.pending)
|
||||
!!(
|
||||
submission.value && submission.value.result === SubmissionStatus.pending
|
||||
),
|
||||
)
|
||||
|
||||
const submitting = computed(
|
||||
@@ -57,7 +61,7 @@ const submitting = computed(
|
||||
!!(
|
||||
submission.value &&
|
||||
submission.value.result === SubmissionStatus.submitting
|
||||
)
|
||||
),
|
||||
)
|
||||
|
||||
const submitDisabled = computed(() => {
|
||||
@@ -186,7 +190,7 @@ watch(
|
||||
size: party.variation.skew(2, 0.3),
|
||||
})
|
||||
}
|
||||
}
|
||||
},
|
||||
)
|
||||
</script>
|
||||
|
||||
|
||||
@@ -1,47 +1,47 @@
|
||||
<script setup lang="ts">
|
||||
import { code } from "oj/composables/code"
|
||||
import { createTestSubmission } from "~/utils/judge"
|
||||
|
||||
const input = ref("")
|
||||
const output = ref("")
|
||||
|
||||
async function test() {
|
||||
output.value = "运行中..."
|
||||
const res = await createTestSubmission(code, input.value)
|
||||
output.value = res.output
|
||||
}
|
||||
function clear() {
|
||||
const id = setTimeout(() => {
|
||||
clearTimeout(id)
|
||||
output.value = ""
|
||||
}, 200)
|
||||
}
|
||||
</script>
|
||||
<template>
|
||||
<n-popover
|
||||
trigger="click"
|
||||
placement="bottom-end"
|
||||
scrollable
|
||||
:show-arrow="false"
|
||||
style="max-height: 600px; max-width: 800px"
|
||||
@clickoutside="clear"
|
||||
>
|
||||
<template #trigger>
|
||||
<n-button>快速测试</n-button>
|
||||
</template>
|
||||
<n-space vertical>
|
||||
<n-input type="textarea" v-model:value="input" />
|
||||
<n-space justify="end">
|
||||
<n-button @click="test">运行</n-button>
|
||||
</n-space>
|
||||
<div class="testcase">{{ output }}</div>
|
||||
</n-space>
|
||||
</n-popover>
|
||||
</template>
|
||||
<style scoped>
|
||||
.testcase {
|
||||
white-space: pre;
|
||||
font-size: 16px;
|
||||
font-family: "Consolas";
|
||||
}
|
||||
</style>
|
||||
<script setup lang="ts">
|
||||
import { code } from "oj/composables/code"
|
||||
import { createTestSubmission } from "~/utils/judge"
|
||||
|
||||
const input = ref("")
|
||||
const output = ref("")
|
||||
|
||||
async function test() {
|
||||
output.value = "运行中..."
|
||||
const res = await createTestSubmission(code, input.value)
|
||||
output.value = res.output
|
||||
}
|
||||
function clear() {
|
||||
const id = setTimeout(() => {
|
||||
clearTimeout(id)
|
||||
output.value = ""
|
||||
}, 200)
|
||||
}
|
||||
</script>
|
||||
<template>
|
||||
<n-popover
|
||||
trigger="click"
|
||||
placement="bottom-end"
|
||||
scrollable
|
||||
:show-arrow="false"
|
||||
style="max-height: 600px; max-width: 800px"
|
||||
@clickoutside="clear"
|
||||
>
|
||||
<template #trigger>
|
||||
<n-button>快速测试</n-button>
|
||||
</template>
|
||||
<n-space vertical>
|
||||
<n-input type="textarea" v-model:value="input" />
|
||||
<n-space justify="end">
|
||||
<n-button @click="test">运行</n-button>
|
||||
</n-space>
|
||||
<div class="testcase">{{ output }}</div>
|
||||
</n-space>
|
||||
</n-popover>
|
||||
</template>
|
||||
<style scoped>
|
||||
.testcase {
|
||||
white-space: pre;
|
||||
font-size: 16px;
|
||||
font-family: "Consolas";
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -7,6 +7,7 @@ import Pagination from "~/shared/Pagination.vue"
|
||||
import { NSpace, NTag } from "naive-ui"
|
||||
import ProblemStatus from "./components/ProblemStatus.vue"
|
||||
import { getProblemTagList } from "~/shared/api"
|
||||
import { isDesktop } from "~/shared/composables/breakpoints"
|
||||
|
||||
interface Tag {
|
||||
id: number
|
||||
@@ -36,6 +37,7 @@ const userStore = useUserStore()
|
||||
const problems = ref<ProblemFiltered[]>([])
|
||||
const total = ref(0)
|
||||
const tags = ref<Tag[]>([])
|
||||
const [showTag, toggleShowTag] = useToggle(isDesktop.value)
|
||||
|
||||
const query = reactive<Query>({
|
||||
keyword: <string>route.query.keyword ?? "",
|
||||
@@ -112,14 +114,14 @@ watch(
|
||||
() => {
|
||||
query.page = 1
|
||||
routerPush()
|
||||
}
|
||||
},
|
||||
)
|
||||
|
||||
watch(
|
||||
() => route.path === "/" && route.query,
|
||||
(newVal) => {
|
||||
if (newVal) listProblems()
|
||||
}
|
||||
},
|
||||
)
|
||||
|
||||
// TODO: 这里会在登录时候执行两次,有BUG
|
||||
@@ -130,7 +132,7 @@ onMounted(() => {
|
||||
listTags()
|
||||
})
|
||||
|
||||
const columns: DataTableColumn<ProblemFiltered>[] = [
|
||||
const baseColumns: DataTableColumn<ProblemFiltered>[] = [
|
||||
{
|
||||
title: "状态",
|
||||
key: "status",
|
||||
@@ -157,6 +159,12 @@ const columns: DataTableColumn<ProblemFiltered>[] = [
|
||||
{ title: "通过率", key: "rate", width: 100 },
|
||||
]
|
||||
|
||||
const columns = computed(() =>
|
||||
userStore.isAuthed
|
||||
? baseColumns
|
||||
: baseColumns.filter((c: any) => c.key !== "status"),
|
||||
)
|
||||
|
||||
function rowProps(row: ProblemFiltered) {
|
||||
return {
|
||||
style: "cursor: pointer",
|
||||
@@ -191,20 +199,22 @@ function rowProps(row: ProblemFiltered) {
|
||||
</n-space>
|
||||
</n-form-item>
|
||||
</n-form>
|
||||
<n-button @click="toggleShowTag()" quaternary>标签</n-button>
|
||||
</n-space>
|
||||
<n-space>
|
||||
<div class="tagTitle">标签</div>
|
||||
<n-button
|
||||
@click="chooseTag(tag)"
|
||||
v-for="tag in tags"
|
||||
:key="tag.id"
|
||||
size="small"
|
||||
secondary
|
||||
:type="tag.checked ? 'success' : 'default'"
|
||||
>
|
||||
{{ tag.name }}
|
||||
</n-button>
|
||||
</n-space>
|
||||
<n-collapse-transition :show="showTag">
|
||||
<n-space>
|
||||
<n-button
|
||||
@click="chooseTag(tag)"
|
||||
v-for="tag in tags"
|
||||
:key="tag.id"
|
||||
size="small"
|
||||
secondary
|
||||
:type="tag.checked ? 'success' : 'default'"
|
||||
>
|
||||
{{ tag.name }}
|
||||
</n-button>
|
||||
</n-space>
|
||||
</n-collapse-transition>
|
||||
<n-data-table
|
||||
striped
|
||||
:data="problems"
|
||||
|
||||
@@ -47,7 +47,7 @@ const columns: DataTableColumn<Rank>[] = [
|
||||
type: "info",
|
||||
onClick: () => router.push("/user?name=" + row.user.username),
|
||||
},
|
||||
() => row.user.username
|
||||
() => row.user.username,
|
||||
),
|
||||
},
|
||||
{ title: "自我介绍", key: "mood", minWidth: 200 },
|
||||
@@ -67,7 +67,7 @@ watch(
|
||||
() => {
|
||||
query.page = 1
|
||||
listRanks()
|
||||
}
|
||||
},
|
||||
)
|
||||
|
||||
onMounted(listRanks)
|
||||
|
||||
@@ -48,11 +48,11 @@ export const useContestStore = defineStore("contest", () => {
|
||||
() =>
|
||||
userStore.isSuperAdmin ||
|
||||
(userStore.isAuthed &&
|
||||
contest.value?.created_by.id === userStore.user!.id)
|
||||
contest.value?.created_by.id === userStore.user!.id),
|
||||
)
|
||||
|
||||
const isPrivate = computed(
|
||||
() => contest.value!.contest_type === ContestType.private
|
||||
() => contest.value!.contest_type === ContestType.private,
|
||||
)
|
||||
|
||||
async function init(contestID: string) {
|
||||
|
||||
@@ -102,7 +102,7 @@ watch(
|
||||
() => {
|
||||
query.page = 1
|
||||
routerPush()
|
||||
}
|
||||
},
|
||||
)
|
||||
|
||||
watch(
|
||||
@@ -111,7 +111,7 @@ watch(
|
||||
route.query,
|
||||
(newVal) => {
|
||||
if (newVal) listSubmissions()
|
||||
}
|
||||
},
|
||||
)
|
||||
|
||||
const columns = computed(() => {
|
||||
@@ -123,7 +123,7 @@ const columns = computed(() => {
|
||||
render: (row) =>
|
||||
parseTime(
|
||||
row.create_time,
|
||||
isDesktop ? "YYYY-MM-DD HH:mm:ss" : "M-D hh:mm"
|
||||
isDesktop ? "YYYY-MM-DD HH:mm:ss" : "M-D hh:mm",
|
||||
),
|
||||
},
|
||||
{
|
||||
@@ -139,7 +139,7 @@ const columns = computed(() => {
|
||||
type: "info",
|
||||
onClick: () => router.push("/submission/" + row.id),
|
||||
},
|
||||
() => row.id.slice(0, 12)
|
||||
() => row.id.slice(0, 12),
|
||||
)
|
||||
} else {
|
||||
return row.id.slice(0, 12)
|
||||
@@ -175,7 +175,7 @@ const columns = computed(() => {
|
||||
}
|
||||
},
|
||||
},
|
||||
() => row.problem
|
||||
() => row.problem,
|
||||
),
|
||||
},
|
||||
{
|
||||
@@ -208,7 +208,7 @@ const columns = computed(() => {
|
||||
type: "info",
|
||||
onClick: () => router.push("/user?name=" + row.username),
|
||||
},
|
||||
() => row.username
|
||||
() => row.username,
|
||||
),
|
||||
},
|
||||
]
|
||||
@@ -225,7 +225,7 @@ const columns = computed(() => {
|
||||
type: "primary",
|
||||
onClick: () => rejudge(row.id),
|
||||
},
|
||||
() => "重新判题"
|
||||
() => "重新判题",
|
||||
),
|
||||
})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user