submission list.
This commit is contained in:
@@ -15,6 +15,7 @@
|
|||||||
"@vueuse/core": "^9.10.0",
|
"@vueuse/core": "^9.10.0",
|
||||||
"@vueuse/integrations": "^9.10.0",
|
"@vueuse/integrations": "^9.10.0",
|
||||||
"axios": "^1.2.2",
|
"axios": "^1.2.2",
|
||||||
|
"copy-text-to-clipboard": "^3.0.1",
|
||||||
"element-plus": "^2.2.28",
|
"element-plus": "^2.2.28",
|
||||||
"normalize.css": "^8.0.1",
|
"normalize.css": "^8.0.1",
|
||||||
"party-js": "^2.2.0",
|
"party-js": "^2.2.0",
|
||||||
|
|||||||
7
pnpm-lock.yaml
generated
7
pnpm-lock.yaml
generated
@@ -9,6 +9,7 @@ specifiers:
|
|||||||
'@vueuse/core': ^9.10.0
|
'@vueuse/core': ^9.10.0
|
||||||
'@vueuse/integrations': ^9.10.0
|
'@vueuse/integrations': ^9.10.0
|
||||||
axios: ^1.2.2
|
axios: ^1.2.2
|
||||||
|
copy-text-to-clipboard: ^3.0.1
|
||||||
element-plus: ^2.2.28
|
element-plus: ^2.2.28
|
||||||
monaco-editor: ^0.34.1
|
monaco-editor: ^0.34.1
|
||||||
normalize.css: ^8.0.1
|
normalize.css: ^8.0.1
|
||||||
@@ -31,6 +32,7 @@ dependencies:
|
|||||||
'@vueuse/core': 9.10.0_vue@3.2.45
|
'@vueuse/core': 9.10.0_vue@3.2.45
|
||||||
'@vueuse/integrations': 9.10.0_axios@1.2.2+vue@3.2.45
|
'@vueuse/integrations': 9.10.0_axios@1.2.2+vue@3.2.45
|
||||||
axios: 1.2.2
|
axios: 1.2.2
|
||||||
|
copy-text-to-clipboard: 3.0.1
|
||||||
element-plus: 2.2.28_vue@3.2.45
|
element-plus: 2.2.28_vue@3.2.45
|
||||||
normalize.css: 8.0.1
|
normalize.css: 8.0.1
|
||||||
party-js: 2.2.0
|
party-js: 2.2.0
|
||||||
@@ -722,6 +724,11 @@ packages:
|
|||||||
delayed-stream: 1.0.0
|
delayed-stream: 1.0.0
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
|
/copy-text-to-clipboard/3.0.1:
|
||||||
|
resolution: {integrity: sha512-rvVsHrpFcL4F2P8ihsoLdFHmd404+CMg71S756oRSeQgqk51U3kicGdnvfkrxva0xXH92SjGS62B0XIJsbh+9Q==}
|
||||||
|
engines: {node: '>=12'}
|
||||||
|
dev: false
|
||||||
|
|
||||||
/cross-spawn/7.0.3:
|
/cross-spawn/7.0.3:
|
||||||
resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==}
|
resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==}
|
||||||
engines: {node: '>= 8'}
|
engines: {node: '>= 8'}
|
||||||
|
|||||||
@@ -66,11 +66,27 @@ export function getSubmission(id: string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function submissionExists(problemID: number) {
|
export function submissionExists(problemID: number) {
|
||||||
return http.get("submission_exists", {
|
return useAxios(
|
||||||
params: { problem_id: problemID },
|
"submission_exists",
|
||||||
})
|
{ params: { problem_id: problemID } },
|
||||||
|
http,
|
||||||
|
{ immediate: false }
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export function submitCode(data: SubmitCodePayload) {
|
export function submitCode(data: SubmitCodePayload) {
|
||||||
return http.post("submission", data)
|
return http.post("submission", data)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function listSubmissions(params: {
|
||||||
|
myself: "1" | "0"
|
||||||
|
result: string
|
||||||
|
username: string
|
||||||
|
page: number
|
||||||
|
contest_id: string
|
||||||
|
problem_id: string
|
||||||
|
limit: number
|
||||||
|
offset: number
|
||||||
|
}) {
|
||||||
|
return useAxios("submissions", { params }, http)
|
||||||
|
}
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ import { SOURCES } from "utils/constants"
|
|||||||
import { Problem } from "utils/types"
|
import { Problem } from "utils/types"
|
||||||
import Monaco from "~/shared/Monaco/index.vue"
|
import Monaco from "~/shared/Monaco/index.vue"
|
||||||
import { useCodeStore } from "oj/store/code"
|
import { useCodeStore } from "oj/store/code"
|
||||||
import { submissionExists } from "oj/api"
|
|
||||||
|
|
||||||
import SubmitPanel from "./SubmitPanel.vue"
|
import SubmitPanel from "./SubmitPanel.vue"
|
||||||
import TestcasePanel from "./TestcasePanel.vue"
|
import TestcasePanel from "./TestcasePanel.vue"
|
||||||
@@ -22,7 +21,6 @@ code.value = props.problem.template[code.language] || SOURCES[code.language]
|
|||||||
|
|
||||||
const tab = ref("test")
|
const tab = ref("test")
|
||||||
const submitPanelRef = ref<{ submit: Function }>()
|
const submitPanelRef = ref<{ submit: Function }>()
|
||||||
const [tried] = useToggle()
|
|
||||||
|
|
||||||
watch(() => code.language, reset)
|
watch(() => code.language, reset)
|
||||||
|
|
||||||
@@ -34,15 +32,6 @@ function change(value: string) {
|
|||||||
code.value = value
|
code.value = value
|
||||||
}
|
}
|
||||||
|
|
||||||
onMounted(() => {
|
|
||||||
checkIfTried()
|
|
||||||
})
|
|
||||||
|
|
||||||
async function checkIfTried() {
|
|
||||||
const res = await submissionExists(props.problem.id)
|
|
||||||
tried.value = res.data
|
|
||||||
}
|
|
||||||
|
|
||||||
function onTab(pane: TabsPaneContext) {
|
function onTab(pane: TabsPaneContext) {
|
||||||
if (pane.paneName === "submit") {
|
if (pane.paneName === "submit") {
|
||||||
submitPanelRef && submitPanelRef.value!.submit()
|
submitPanelRef && submitPanelRef.value!.submit()
|
||||||
@@ -62,6 +51,9 @@ function onTab(pane: TabsPaneContext) {
|
|||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
<el-button @click="reset">重置</el-button>
|
<el-button @click="reset">重置</el-button>
|
||||||
|
<el-button @click="$router.push(`/status?problem=${problem.id}`)">
|
||||||
|
提交信息
|
||||||
|
</el-button>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-form>
|
</el-form>
|
||||||
<Monaco
|
<Monaco
|
||||||
|
|||||||
@@ -1,9 +1,11 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { Flag, CloseBold, Select } from "@element-plus/icons-vue"
|
import { Flag, CloseBold, Select, CopyDocument } from "@element-plus/icons-vue"
|
||||||
|
import copy from "copy-text-to-clipboard"
|
||||||
import { useCodeStore } from "oj/store/code"
|
import { useCodeStore } from "oj/store/code"
|
||||||
import { SOURCES } from "utils/constants"
|
import { SOURCES } from "utils/constants"
|
||||||
import { Problem } from "utils/types"
|
import { Problem } from "utils/types"
|
||||||
import { createTestSubmission } from "utils/judge"
|
import { createTestSubmission } from "utils/judge"
|
||||||
|
import { submissionExists } from "oj/api"
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
problem: Problem
|
problem: Problem
|
||||||
@@ -16,7 +18,12 @@ type Sample = Problem["samples"][number] & {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const props = defineProps<Props>()
|
const props = defineProps<Props>()
|
||||||
|
const route = useRoute()
|
||||||
|
const contestID = <string>route.params.contestID
|
||||||
|
const { data: hasSolved, execute } = submissionExists(props.problem.id)
|
||||||
|
if (contestID) {
|
||||||
|
execute()
|
||||||
|
}
|
||||||
const samples = ref<Sample[]>(
|
const samples = ref<Sample[]>(
|
||||||
props.problem.samples.map((sample, index) => ({
|
props.problem.samples.map((sample, index) => ({
|
||||||
...sample,
|
...sample,
|
||||||
@@ -77,6 +84,16 @@ const type = (status: Sample["status"]) =>
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
<el-alert
|
||||||
|
v-if="problem.my_status === 0 || (contestID && hasSolved)"
|
||||||
|
type="success"
|
||||||
|
:closable="false"
|
||||||
|
center
|
||||||
|
title="🎉 本 题 已 经 被 你 解 决 啦"
|
||||||
|
effect="dark"
|
||||||
|
>
|
||||||
|
</el-alert>
|
||||||
|
|
||||||
<h1>{{ problem.title }}</h1>
|
<h1>{{ problem.title }}</h1>
|
||||||
<p class="title">描述</p>
|
<p class="title">描述</p>
|
||||||
<div class="content" v-html="problem.description"></div>
|
<div class="content" v-html="problem.description"></div>
|
||||||
@@ -107,10 +124,22 @@ const type = (status: Sample["status"]) =>
|
|||||||
></el-button>
|
></el-button>
|
||||||
</el-space>
|
</el-space>
|
||||||
<el-descriptions border direction="vertical" :column="2">
|
<el-descriptions border direction="vertical" :column="2">
|
||||||
<el-descriptions-item width="50%" label="输入">
|
<el-descriptions-item width="50%">
|
||||||
|
<template #label>
|
||||||
|
<el-space>
|
||||||
|
<span>输入</span>
|
||||||
|
<el-icon @click="copy(sample.input)"><CopyDocument /> </el-icon>
|
||||||
|
</el-space>
|
||||||
|
</template>
|
||||||
<div class="testcase">{{ sample.input }}</div>
|
<div class="testcase">{{ sample.input }}</div>
|
||||||
</el-descriptions-item>
|
</el-descriptions-item>
|
||||||
<el-descriptions-item width="50%" label="输出">
|
<el-descriptions-item width="50%">
|
||||||
|
<template #label>
|
||||||
|
<el-space>
|
||||||
|
<span>输出</span>
|
||||||
|
<el-icon @click="copy(sample.output)"><CopyDocument /> </el-icon>
|
||||||
|
</el-space>
|
||||||
|
</template>
|
||||||
<div class="testcase">{{ sample.output }}</div>
|
<div class="testcase">{{ sample.output }}</div>
|
||||||
</el-descriptions-item>
|
</el-descriptions-item>
|
||||||
<el-descriptions-item label="运行结果" v-if="sample.status === 'failed'">
|
<el-descriptions-item label="运行结果" v-if="sample.status === 'failed'">
|
||||||
@@ -131,6 +160,7 @@ const type = (status: Sample["status"]) =>
|
|||||||
margin: 24px 0 16px 0;
|
margin: 24px 0 16px 0;
|
||||||
color: var(--el-color-primary);
|
color: var(--el-color-primary);
|
||||||
}
|
}
|
||||||
|
|
||||||
.testcaseTitle {
|
.testcaseTitle {
|
||||||
margin-bottom: 24px;
|
margin-bottom: 24px;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,18 +0,0 @@
|
|||||||
<script setup lang="ts">
|
|
||||||
import Pagination from "~/shared/Pagination/index.vue"
|
|
||||||
|
|
||||||
const query = reactive({
|
|
||||||
page: 1,
|
|
||||||
limit: 10,
|
|
||||||
})
|
|
||||||
const total = ref(100)
|
|
||||||
</script>
|
|
||||||
<template>
|
|
||||||
<el-table max-height="calc(100vh - 171px)"></el-table>
|
|
||||||
<Pagination
|
|
||||||
:total="total"
|
|
||||||
v-model:limit="query.limit"
|
|
||||||
v-model:page="query.page"
|
|
||||||
/>
|
|
||||||
</template>
|
|
||||||
<style scoped></style>
|
|
||||||
@@ -2,9 +2,9 @@
|
|||||||
import Editor from "./components/Editor.vue"
|
import Editor from "./components/Editor.vue"
|
||||||
import ProblemContent from "./components/ProblemContent.vue"
|
import ProblemContent from "./components/ProblemContent.vue"
|
||||||
import ProblemInfo from "./components/ProblemInfo.vue"
|
import ProblemInfo from "./components/ProblemInfo.vue"
|
||||||
import SubmissionList from "./components/SubmissionList.vue"
|
|
||||||
import { getProblem } from "oj/api"
|
import { getProblem } from "oj/api"
|
||||||
import { isDesktop, isMobile } from "~/shared/composables/breakpoints"
|
import { isDesktop, isMobile } from "~/shared/composables/breakpoints"
|
||||||
|
import { TabsPaneContext } from "element-plus"
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
problemID: string
|
problemID: string
|
||||||
@@ -16,7 +16,6 @@ const props = withDefaults(defineProps<Props>(), {
|
|||||||
})
|
})
|
||||||
|
|
||||||
const { data: problem, isFinished } = getProblem(props.problemID)
|
const { data: problem, isFinished } = getProblem(props.problemID)
|
||||||
|
|
||||||
provide("problem", readonly(problem))
|
provide("problem", readonly(problem))
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@@ -33,11 +32,8 @@ provide("problem", readonly(problem))
|
|||||||
<el-tab-pane v-if="isMobile" label="代码编辑" lazy>
|
<el-tab-pane v-if="isMobile" label="代码编辑" lazy>
|
||||||
<Editor :problem="problem" />
|
<Editor :problem="problem" />
|
||||||
</el-tab-pane>
|
</el-tab-pane>
|
||||||
<el-tab-pane label="提交列表" lazy>
|
|
||||||
<SubmissionList />
|
|
||||||
</el-tab-pane>
|
|
||||||
<el-tab-pane label="比赛信息" v-if="props.contestID" lazy></el-tab-pane>
|
<el-tab-pane label="比赛信息" v-if="props.contestID" lazy></el-tab-pane>
|
||||||
<el-tab-pane label="统计信息" lazy>
|
<el-tab-pane label="题目信息" lazy>
|
||||||
<ProblemInfo :problem="problem" />
|
<ProblemInfo :problem="problem" />
|
||||||
</el-tab-pane>
|
</el-tab-pane>
|
||||||
</el-tabs>
|
</el-tabs>
|
||||||
|
|||||||
@@ -1,5 +1,18 @@
|
|||||||
<script setup lang="ts"></script>
|
<script setup lang="ts">
|
||||||
|
import Pagination from "~/shared/Pagination/index.vue"
|
||||||
<template>status list</template>
|
|
||||||
|
|
||||||
|
const query = reactive({
|
||||||
|
page: 1,
|
||||||
|
limit: 10,
|
||||||
|
})
|
||||||
|
const total = ref(100)
|
||||||
|
</script>
|
||||||
|
<template>
|
||||||
|
<el-table max-height="calc(100vh - 171px)"></el-table>
|
||||||
|
<Pagination
|
||||||
|
:total="total"
|
||||||
|
v-model:limit="query.limit"
|
||||||
|
v-model:page="query.page"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
<style scoped></style>
|
<style scoped></style>
|
||||||
|
|||||||
Reference in New Issue
Block a user