diff --git a/components.d.ts b/components.d.ts
index 193e614..742a9e2 100644
--- a/components.d.ts
+++ b/components.d.ts
@@ -24,6 +24,7 @@ declare module '@vue/runtime-core' {
ElHeader: typeof import('element-plus/es')['ElHeader']
ElIcon: typeof import('element-plus/es')['ElIcon']
ElInput: typeof import('element-plus/es')['ElInput']
+ ElLink: typeof import('element-plus/es')['ElLink']
ElMain: typeof import('element-plus/es')['ElMain']
ElMenu: typeof import('element-plus/es')['ElMenu']
ElMenuItem: typeof import('element-plus/es')['ElMenuItem']
@@ -38,10 +39,14 @@ declare module '@vue/runtime-core' {
ElTabPane: typeof import('element-plus/es')['ElTabPane']
ElTabs: typeof import('element-plus/es')['ElTabs']
ElTag: typeof import('element-plus/es')['ElTag']
+ IEpBell: typeof import('~icons/ep/bell')['default']
+ 'IEpCaret-': typeof import('~icons/ep/caret-')['default']
+ IEpCaretRight: typeof import('~icons/ep/caret-right')['default']
+ IEpLoading: typeof import('~icons/ep/loading')['default']
IEpSelect: typeof import('~icons/ep/select')['default']
IEpSemiSelect: typeof import('~icons/ep/semi-select')['default']
RouterLink: typeof import('vue-router')['RouterLink']
RouterView: typeof import('vue-router')['RouterView']
- UseNetwork: typeof import('@vueuse/components')['UseNetwork']
+ UseNetwork: typeof import("@vueuse/components")["UseNetwork"]
}
}
diff --git a/package-lock.json b/package-lock.json
index e65b6a0..f589dcd 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -15,6 +15,7 @@
"axios": "^1.2.2",
"element-plus": "^2.2.28",
"normalize.css": "^8.0.1",
+ "party-js": "^2.2.0",
"pinia": "^2.0.28",
"vue": "^3.2.45",
"vue-router": "^4.1.6"
@@ -1618,6 +1619,11 @@
"node": ">=10"
}
},
+ "node_modules/party-js": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmmirror.com/party-js/-/party-js-2.2.0.tgz",
+ "integrity": "sha512-50hGuALCpvDTrQLPQ1fgUgxKIWAH28ShVkmeK/3zhO0YJyCqkhrZhQEkWPxDYLvbFJ7YAXyROmFEu35gKpZLtQ=="
+ },
"node_modules/path-exists": {
"version": "4.0.0",
"resolved": "https://registry.npmmirror.com/path-exists/-/path-exists-4.0.0.tgz",
@@ -3324,6 +3330,11 @@
"p-limit": "^3.0.2"
}
},
+ "party-js": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmmirror.com/party-js/-/party-js-2.2.0.tgz",
+ "integrity": "sha512-50hGuALCpvDTrQLPQ1fgUgxKIWAH28ShVkmeK/3zhO0YJyCqkhrZhQEkWPxDYLvbFJ7YAXyROmFEu35gKpZLtQ=="
+ },
"path-exists": {
"version": "4.0.0",
"resolved": "https://registry.npmmirror.com/path-exists/-/path-exists-4.0.0.tgz",
diff --git a/package.json b/package.json
index 1bdb5fd..1d16ee9 100644
--- a/package.json
+++ b/package.json
@@ -17,6 +17,7 @@
"axios": "^1.2.2",
"element-plus": "^2.2.28",
"normalize.css": "^8.0.1",
+ "party-js": "^2.2.0",
"pinia": "^2.0.28",
"vue": "^3.2.45",
"vue-router": "^4.1.6"
diff --git a/src/App.vue b/src/App.vue
index 742bf3f..5651af3 100644
--- a/src/App.vue
+++ b/src/App.vue
@@ -1,10 +1,9 @@
-
+
diff --git a/src/main.ts b/src/main.ts
index c9833f2..f1b4340 100644
--- a/src/main.ts
+++ b/src/main.ts
@@ -5,58 +5,12 @@ import "normalize.css"
import loader from "@monaco-editor/loader"
import App from "./App.vue"
-import Home from "./oj/index.vue"
-import Problems from "./oj/problem/list.vue"
import storage from "./utils/storage"
+import routes from "./routes"
import { STORAGE_KEY } from "./utils/constants"
import { useLoginStore } from "./shared/stores/login"
-const routes = [
- {
- path: "/",
- component: Home,
- children: [
- { path: "", component: Problems },
- {
- path: "problem/:problemID",
- component: () => import("./oj/problem/detail.vue"),
- props: true,
- },
- {
- path: "status",
- component: () => import("./oj/status/list.vue"),
- meta: { requiresAuth: true },
- },
- {
- path: "status/:statusID",
- component: () => import("./oj/status/detail.vue"),
- props: true,
- },
- {
- path: "contest",
- component: () => import("./oj/contest/list.vue"),
- meta: { requiresAuth: true },
- },
- {
- path: "contest/:contestID",
- component: () => import("./oj/contest/detail.vue"),
- props: true,
- },
- {
- path: "contest/:contestID/problem/:problemID",
- component: () => import("./oj/problem/detail.vue"),
- props: true,
- },
- {
- path: "rank",
- component: () => import("./oj/rank/list.vue"),
- },
- ],
- },
- { path: "/admin", component: () => import("./admin/index.vue") },
-]
-
const router = createRouter({
history: createWebHistory(),
routes,
diff --git a/src/oj/api.ts b/src/oj/api.ts
index 177cc95..4f40fc1 100644
--- a/src/oj/api.ts
+++ b/src/oj/api.ts
@@ -1,6 +1,6 @@
import { getACRate } from "./../utils/functions"
import { DIFFICULTY } from "./../utils/constants"
-import { Problem, SubmitCodePayload } from "./../utils/types"
+import { Problem, SubmitCodePayload, Submission } from "./../utils/types"
import http from "./../utils/http"
import { useAxios } from "@vueuse/integrations/useAxios"
@@ -60,11 +60,17 @@ export function getProblem(id: string) {
}
export function getSubmission(id: string) {
- return http.get("submission", {
+ return http.get("submission", {
params: { id },
})
}
+export function submissionExists(problemID: number) {
+ return http.get("submission_exists", {
+ params: { problem_id: problemID },
+ })
+}
+
export function submitCode(data: SubmitCodePayload) {
return http.post("submission", data)
}
diff --git a/src/oj/components/submission-result-tag.vue b/src/oj/components/submission-result-tag.vue
new file mode 100644
index 0000000..fda1f48
--- /dev/null
+++ b/src/oj/components/submission-result-tag.vue
@@ -0,0 +1,16 @@
+
+
+
+
+ {{ JUDGE_STATUS[result]["name"] }}
+
+
+
+
diff --git a/src/oj/contest/detail.vue b/src/oj/contest/detail.vue
index e69de29..80b8d56 100644
--- a/src/oj/contest/detail.vue
+++ b/src/oj/contest/detail.vue
@@ -0,0 +1,5 @@
+
+
+contest detail
+
+
diff --git a/src/oj/problem/components/editor-exec.vue b/src/oj/problem/components/editor-exec.vue
new file mode 100644
index 0000000..e1bae57
--- /dev/null
+++ b/src/oj/problem/components/editor-exec.vue
@@ -0,0 +1,277 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ submitLabel }}
+
+
+
+
+
+
+ {{ msg }}
+
+
+
+
+
+
+
+
+
+ {{ submissionMemoryFormat(scope.row.memory) }}
+
+
+
+
+ {{ submissionTimeFormat(scope.row.real_time) }}
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/oj/problem/components/editor.vue b/src/oj/problem/components/editor.vue
index 42ab14a..f3883cf 100644
--- a/src/oj/problem/components/editor.vue
+++ b/src/oj/problem/components/editor.vue
@@ -1,39 +1,28 @@
-
+
重置
-
-
- 1
- 2
-
-
-
- 运行
-
- 提交
-
-
-
+ >
+
diff --git a/src/oj/problem/detail.vue b/src/oj/problem/detail.vue
index 471bb2c..0435f5d 100644
--- a/src/oj/problem/detail.vue
+++ b/src/oj/problem/detail.vue
@@ -13,7 +13,7 @@ const { data: problem, isFinished } = getProblem(problemID)
-
+
@@ -29,17 +29,13 @@ const { data: problem, isFinished } = getProblem(problemID)
- 3
+ 3
-
+
-
+
diff --git a/src/oj/problem/list.vue b/src/oj/problem/list.vue
index 356cd33..880fcf6 100644
--- a/src/oj/problem/list.vue
+++ b/src/oj/problem/list.vue
@@ -100,7 +100,7 @@ onMounted(listProblems)
-
+
{
- const visible = ref(false)
+ const [visible] = useToggle()
function show() {
visible.value = true
diff --git a/src/routes.ts b/src/routes.ts
new file mode 100644
index 0000000..e1d5d18
--- /dev/null
+++ b/src/routes.ts
@@ -0,0 +1,49 @@
+import Home from "./oj/index.vue"
+import Problems from "./oj/problem/list.vue"
+
+const routes = [
+ {
+ path: "/",
+ component: Home,
+ children: [
+ { path: "", component: Problems },
+ {
+ path: "problem/:problemID",
+ component: () => import("./oj/problem/detail.vue"),
+ props: true,
+ },
+ {
+ path: "status",
+ component: () => import("./oj/status/list.vue"),
+ meta: { requiresAuth: true },
+ },
+ {
+ path: "status/:statusID",
+ component: () => import("./oj/status/detail.vue"),
+ props: true,
+ },
+ {
+ path: "contest",
+ component: () => import("./oj/contest/list.vue"),
+ meta: { requiresAuth: true },
+ },
+ {
+ path: "contest/:contestID",
+ component: () => import("./oj/contest/detail.vue"),
+ props: true,
+ },
+ {
+ path: "contest/:contestID/problem/:problemID",
+ component: () => import("./oj/problem/detail.vue"),
+ props: true,
+ },
+ {
+ path: "rank",
+ component: () => import("./oj/rank/list.vue"),
+ },
+ ],
+ },
+ { path: "/admin", component: () => import("./admin/index.vue") },
+]
+
+export default routes
diff --git a/src/shared/split-panel/index.vue b/src/shared/split-panel/index.vue
new file mode 100644
index 0000000..b7405be
--- /dev/null
+++ b/src/shared/split-panel/index.vue
@@ -0,0 +1,140 @@
+
+
+
+
+
+
+
diff --git a/src/shared/split-panel/pane.vue b/src/shared/split-panel/pane.vue
new file mode 100644
index 0000000..cb85e96
--- /dev/null
+++ b/src/shared/split-panel/pane.vue
@@ -0,0 +1,40 @@
+
+
+
+
+
+
+
+
+
diff --git a/src/shared/split-panel/resizer.vue b/src/shared/split-panel/resizer.vue
new file mode 100644
index 0000000..2b85e2a
--- /dev/null
+++ b/src/shared/split-panel/resizer.vue
@@ -0,0 +1,43 @@
+
+
+
+
+
+
+
diff --git a/src/shared/stores/login.ts b/src/shared/stores/login.ts
index f4f00a4..b2cd9db 100644
--- a/src/shared/stores/login.ts
+++ b/src/shared/stores/login.ts
@@ -1,8 +1,8 @@
+import { useToggle } from "@vueuse/core"
import { defineStore } from "pinia"
-import { ref } from "vue"
export const useLoginStore = defineStore("login", () => {
- const visible = ref(false)
+ const [visible] = useToggle()
function show() {
visible.value = true
diff --git a/src/utils/constants.ts b/src/utils/constants.ts
index 3e961cc..4b096ed 100644
--- a/src/utils/constants.ts
+++ b/src/utils/constants.ts
@@ -1,72 +1,65 @@
+export enum SubmissionStatus {
+ compile_error = -2,
+ wrong_answer = -1,
+ accepted = 0,
+ time_limit_exceeded = 1 | 2,
+ memory_limit_exceeded = 3,
+ runtime_error = 4,
+ system_error = 5,
+ pending = 6,
+ judging = 7,
+ partial_accepted = 8,
+ submitting = 9,
+}
+
export const JUDGE_STATUS = {
"-2": {
- name: "Compile Error",
- short: "CE",
- color: "yellow",
- type: "warning",
+ name: "编译失败",
+ type: "error",
},
"-1": {
- name: "Wrong Answer",
- short: "WA",
- color: "red",
+ name: "答案错误",
type: "error",
},
"0": {
- name: "Accepted",
- short: "AC",
- color: "green",
+ name: "答案正确",
type: "success",
},
"1": {
- name: "Time Limit Exceeded",
- short: "TLE",
- color: "red",
+ name: "运行超时",
type: "error",
},
"2": {
- name: "Time Limit Exceeded",
- short: "TLE",
- color: "red",
+ name: "运行超时",
type: "error",
},
"3": {
- name: "Memory Limit Exceeded",
- short: "MLE",
- color: "red",
+ name: "内存超限",
type: "error",
},
"4": {
- name: "Runtime Error",
- short: "RE",
- color: "red",
+ name: "运行时错误",
type: "error",
},
"5": {
- name: "System Error",
- short: "SE",
- color: "red",
+ name: "系统错误",
type: "error",
},
"6": {
- name: "Pending",
- color: "yellow",
+ name: "等待评分",
type: "warning",
},
"7": {
- name: "Judging",
- color: "blue",
+ name: "正在评分",
type: "info",
},
"8": {
- name: "Partial Accepted",
- short: "PAC",
- color: "blue",
- type: "info",
+ name: "部分正确",
+ type: "warning",
},
"9": {
- name: "Submitting",
- color: "yellow",
- type: "warning",
+ name: "正在提交",
+ type: "info",
},
}
diff --git a/src/utils/functions.ts b/src/utils/functions.ts
index b7b938d..cd7de48 100644
--- a/src/utils/functions.ts
+++ b/src/utils/functions.ts
@@ -38,3 +38,15 @@ export function parseTime(utc: Date, format = "YYYY年M月D日") {
const time = useDateFormat(utc, format, { locales: "zh-CN" })
return time.value
}
+
+export function submissionMemoryFormat(memory: string) {
+ if (memory === undefined) return "--"
+ // 1048576 = 1024 * 1024
+ let t = parseInt(memory) / 1048576
+ return String(t.toFixed(0)) + "MB"
+}
+
+export function submissionTimeFormat(time: number) {
+ if (time === undefined) return "--"
+ return time + "ms"
+}
diff --git a/src/utils/http.ts b/src/utils/http.ts
index 2c27faf..e38824c 100644
--- a/src/utils/http.ts
+++ b/src/utils/http.ts
@@ -6,11 +6,10 @@ const http = axios.create({
xsrfCookieName: "csrftoken",
})
-// TODO
http.interceptors.response.use(
(res) => {
if (res.data.error) {
- // 若后端返回为登录,则为session失效,应退出当前登录用户
+ // // TODO: 若后端返回为登录,则为session失效,应退出当前登录用户
if (res.data.data.startsWith("Please login")) {
}
return Promise.reject(res.data)
diff --git a/src/utils/types.ts b/src/utils/types.ts
index 87ca769..819096c 100644
--- a/src/utils/types.ts
+++ b/src/utils/types.ts
@@ -7,6 +7,8 @@ export type LANGUAGE =
| "JavaScript"
| "Golang"
+export type SUBMISSION_RESULT = -2 | -1 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9
+
export interface Problem {
_id: string
id: number
@@ -56,3 +58,40 @@ export interface SubmitCodePayload {
code: string
contest_id?: number
}
+
+interface Info {
+ err: string | null
+ data: {
+ error: number
+ memory: number
+ output: null
+ result: SUBMISSION_RESULT
+ signal: number
+ cpu_time: number
+ exit_code: number
+ real_time: number
+ test_case: string
+ output_md5: string
+ }[]
+}
+
+export interface Submission {
+ id: string
+ create_time: Date
+ user_id: number
+ username: string
+ code: string
+ result: SUBMISSION_RESULT
+ info: Info
+ language: string
+ shared: boolean
+ statistic_info: {
+ score: number
+ err_info: string
+ }
+ ip: string
+ // TODO: 这里不知道是什么
+ contest: null
+ problem: number
+ can_unshare: boolean
+}