add problem.
This commit is contained in:
3
components.d.ts
vendored
3
components.d.ts
vendored
@@ -12,6 +12,9 @@ declare module '@vue/runtime-core' {
|
|||||||
ElCol: typeof import('element-plus/es')['ElCol']
|
ElCol: typeof import('element-plus/es')['ElCol']
|
||||||
ElConfigProvider: typeof import('element-plus/es')['ElConfigProvider']
|
ElConfigProvider: typeof import('element-plus/es')['ElConfigProvider']
|
||||||
ElContainer: typeof import('element-plus/es')['ElContainer']
|
ElContainer: typeof import('element-plus/es')['ElContainer']
|
||||||
|
ElDescription: typeof import('element-plus/es')['ElDescription']
|
||||||
|
ElDescriptions: typeof import('element-plus/es')['ElDescriptions']
|
||||||
|
ElDescriptionsItem: typeof import('element-plus/es')['ElDescriptionsItem']
|
||||||
ElDialog: typeof import('element-plus/es')['ElDialog']
|
ElDialog: typeof import('element-plus/es')['ElDialog']
|
||||||
ElDropdown: typeof import('element-plus/es')['ElDropdown']
|
ElDropdown: typeof import('element-plus/es')['ElDropdown']
|
||||||
ElDropdownItem: typeof import('element-plus/es')['ElDropdownItem']
|
ElDropdownItem: typeof import('element-plus/es')['ElDropdownItem']
|
||||||
|
|||||||
@@ -1,17 +1,12 @@
|
|||||||
import { getACRate } from "./../utils/functions"
|
import { getACRate } from "./../utils/functions"
|
||||||
|
import { DIFFICULTY } from "./../utils/constants"
|
||||||
import http from "./../utils/http"
|
import http from "./../utils/http"
|
||||||
|
|
||||||
const difficultDict = {
|
|
||||||
Low: "简单",
|
|
||||||
Mid: "中等",
|
|
||||||
High: "困难",
|
|
||||||
}
|
|
||||||
|
|
||||||
function filterResult(result: any) {
|
function filterResult(result: any) {
|
||||||
const newResult: any = {
|
const newResult: any = {
|
||||||
displayID: result._id,
|
displayID: result._id,
|
||||||
title: result.title,
|
title: result.title,
|
||||||
difficulty: difficultDict[<"Low" | "Mid" | "High">result.difficulty],
|
difficulty: DIFFICULTY[<"Low" | "Mid" | "High">result.difficulty],
|
||||||
tags: result.tags,
|
tags: result.tags,
|
||||||
submission: result.submission_number,
|
submission: result.submission_number,
|
||||||
rate: getACRate(result.accepted_number, result.submission_number),
|
rate: getACRate(result.accepted_number, result.submission_number),
|
||||||
|
|||||||
@@ -1,78 +0,0 @@
|
|||||||
<template>
|
|
||||||
<el-select v-model="language">
|
|
||||||
<el-option value="c">C</el-option>
|
|
||||||
<el-option value="python">Python</el-option>
|
|
||||||
</el-select>
|
|
||||||
<div ref="monacoEditorRef" style="height: 300px"></div>
|
|
||||||
</template>
|
|
||||||
<script lang="ts" setup>
|
|
||||||
import editorWorker from "monaco-editor/esm/vs/editor/editor.worker?worker"
|
|
||||||
import jsonWorker from "monaco-editor/esm/vs/language/json/json.worker?worker"
|
|
||||||
import cssWorker from "monaco-editor/esm/vs/language/css/css.worker?worker"
|
|
||||||
import htmlWorker from "monaco-editor/esm/vs/language/html/html.worker?worker"
|
|
||||||
import tsWorker from "monaco-editor/esm/vs/language/typescript/ts.worker?worker"
|
|
||||||
|
|
||||||
import * as monaco from "monaco-editor"
|
|
||||||
import { nextTick, ref, onBeforeUnmount, onMounted } from "vue"
|
|
||||||
|
|
||||||
const text = ref("")
|
|
||||||
const monacoEditorRef = ref()
|
|
||||||
const language = ref("C")
|
|
||||||
|
|
||||||
// @ts-ignore
|
|
||||||
self.MonacoEnvironment = {
|
|
||||||
getWorker(workerId: string, label: string) {
|
|
||||||
if (label === "json") {
|
|
||||||
return new jsonWorker()
|
|
||||||
}
|
|
||||||
if (label === "css" || label === "scss" || label === "less") {
|
|
||||||
return new cssWorker()
|
|
||||||
}
|
|
||||||
if (label === "html" || label === "handlebars" || label === "razor") {
|
|
||||||
return new htmlWorker()
|
|
||||||
}
|
|
||||||
if (label === "typescript" || label === "javascript") {
|
|
||||||
return new tsWorker()
|
|
||||||
}
|
|
||||||
return new editorWorker()
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
onBeforeUnmount(() => {
|
|
||||||
editor.dispose()
|
|
||||||
})
|
|
||||||
|
|
||||||
onMounted(() => {
|
|
||||||
editorInit()
|
|
||||||
})
|
|
||||||
|
|
||||||
let editor: monaco.editor.IStandaloneCodeEditor
|
|
||||||
|
|
||||||
function editorInit() {
|
|
||||||
nextTick(() => {
|
|
||||||
!editor
|
|
||||||
? (editor = monaco.editor.create(monacoEditorRef.value, {
|
|
||||||
value: text.value, // 编辑器初始显示文字
|
|
||||||
language: "python", // 语言支持自行查阅demo
|
|
||||||
automaticLayout: true, // 自适应布局
|
|
||||||
theme: "vs", // 官方自带三种主题vs, hc-black, or vs-dark
|
|
||||||
foldingStrategy: "indentation",
|
|
||||||
renderLineHighlight: "all", // 行亮
|
|
||||||
selectOnLineNumbers: true, // 显示行号
|
|
||||||
minimap: {
|
|
||||||
enabled: false,
|
|
||||||
},
|
|
||||||
readOnly: false, // 只读
|
|
||||||
fontSize: 16, // 字体大小
|
|
||||||
scrollBeyondLastLine: false, // 取消代码后面一大段空白
|
|
||||||
overviewRulerBorder: false, // 不要滚动条的边框
|
|
||||||
}))
|
|
||||||
: editor.setValue("")
|
|
||||||
// 监听值的变化
|
|
||||||
editor.onDidChangeModelContent(() => {
|
|
||||||
text.value = editor.getValue()
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
<style scoped></style>
|
|
||||||
@@ -1,15 +1,28 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { onMounted } from "vue"
|
import { onMounted, ref } from "vue"
|
||||||
import { useRoute } from "vue-router"
|
import { useRoute } from "vue-router"
|
||||||
import Editor from "../components/editor.vue"
|
import Editor from "./editor.vue"
|
||||||
import { getProblem } from "../api"
|
import { getProblem } from "../api"
|
||||||
|
import ProblemContent from "./problem-content.vue"
|
||||||
|
import ProblemInfo from "./problem-info.vue"
|
||||||
|
|
||||||
const route = useRoute()
|
const route = useRoute()
|
||||||
|
const code = ref("print('hello world')")
|
||||||
|
const language = ref("C")
|
||||||
|
const problem = ref({
|
||||||
|
created_by: {},
|
||||||
|
io_mode: {},
|
||||||
|
languages: [],
|
||||||
|
samples: [],
|
||||||
|
statistic_info: {},
|
||||||
|
tags: [],
|
||||||
|
template: {},
|
||||||
|
})
|
||||||
|
|
||||||
async function init() {
|
async function init() {
|
||||||
const id = route.params.id as string
|
const id = route.params.id as string
|
||||||
const res = await getProblem(id)
|
const res = await getProblem(id)
|
||||||
console.log(res.data)
|
problem.value = res.data
|
||||||
}
|
}
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
@@ -21,12 +34,17 @@ onMounted(() => {
|
|||||||
<el-row>
|
<el-row>
|
||||||
<el-col :span="12">
|
<el-col :span="12">
|
||||||
<el-tabs type="border-card">
|
<el-tabs type="border-card">
|
||||||
<el-tab-pane label="题目描述">1</el-tab-pane>
|
<el-tab-pane label="题目描述">
|
||||||
<el-tab-pane label="提交信息">2</el-tab-pane>
|
<ProblemContent :problem="problem" />
|
||||||
|
</el-tab-pane>
|
||||||
|
<el-tab-pane label="题目信息">
|
||||||
|
<ProblemInfo :problem="problem" />
|
||||||
|
</el-tab-pane>
|
||||||
|
<el-tab-pane label="提交信息">3</el-tab-pane>
|
||||||
</el-tabs>
|
</el-tabs>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="12">
|
<el-col :span="12">
|
||||||
<Editor />
|
<Editor :value="code" :language="language" />
|
||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
133
src/oj/problem/editor.vue
Normal file
133
src/oj/problem/editor.vue
Normal file
@@ -0,0 +1,133 @@
|
|||||||
|
<script lang="ts" setup>
|
||||||
|
import editorWorker from "monaco-editor/esm/vs/editor/editor.worker?worker"
|
||||||
|
import jsonWorker from "monaco-editor/esm/vs/language/json/json.worker?worker"
|
||||||
|
import cssWorker from "monaco-editor/esm/vs/language/css/css.worker?worker"
|
||||||
|
import htmlWorker from "monaco-editor/esm/vs/language/html/html.worker?worker"
|
||||||
|
import tsWorker from "monaco-editor/esm/vs/language/typescript/ts.worker?worker"
|
||||||
|
|
||||||
|
import * as monaco from "monaco-editor"
|
||||||
|
import {
|
||||||
|
nextTick,
|
||||||
|
ref,
|
||||||
|
onBeforeUnmount,
|
||||||
|
onMounted,
|
||||||
|
watch,
|
||||||
|
defineProps,
|
||||||
|
} from "vue"
|
||||||
|
|
||||||
|
const props = defineProps(["value", "language"])
|
||||||
|
|
||||||
|
const value = ref(props.value || "")
|
||||||
|
const language = ref(props.language || "C")
|
||||||
|
|
||||||
|
const monacoEditorRef = ref()
|
||||||
|
|
||||||
|
// @ts-ignore
|
||||||
|
self.MonacoEnvironment = {
|
||||||
|
getWorker(workerId: string, label: string) {
|
||||||
|
if (label === "json") {
|
||||||
|
return new jsonWorker()
|
||||||
|
}
|
||||||
|
if (label === "css" || label === "scss" || label === "less") {
|
||||||
|
return new cssWorker()
|
||||||
|
}
|
||||||
|
if (label === "html" || label === "handlebars" || label === "razor") {
|
||||||
|
return new htmlWorker()
|
||||||
|
}
|
||||||
|
if (label === "typescript" || label === "javascript") {
|
||||||
|
return new tsWorker()
|
||||||
|
}
|
||||||
|
return new editorWorker()
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
function reset() {
|
||||||
|
if (editor) {
|
||||||
|
editor.getModel()!.setValue(props.value || "")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onBeforeUnmount(() => {
|
||||||
|
editor && editor.dispose()
|
||||||
|
})
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
editorInit()
|
||||||
|
})
|
||||||
|
|
||||||
|
watch(language, () => {
|
||||||
|
if (editor) {
|
||||||
|
monaco.editor.setModelLanguage(
|
||||||
|
editor.getModel()!,
|
||||||
|
language.value.toLowerCase()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
let editor: monaco.editor.IStandaloneCodeEditor
|
||||||
|
|
||||||
|
function editorInit() {
|
||||||
|
nextTick(() => {
|
||||||
|
if (editor) {
|
||||||
|
editor.setValue("")
|
||||||
|
} else {
|
||||||
|
editor = monaco.editor.create(monacoEditorRef.value, {
|
||||||
|
value: value.value, // 编辑器初始显示文字
|
||||||
|
language: language.value.toLowerCase(),
|
||||||
|
automaticLayout: true, // 自适应布局
|
||||||
|
theme: "vs", // 官方自带三种主题vs, hc-black, or vs-dark
|
||||||
|
minimap: {
|
||||||
|
enabled: false,
|
||||||
|
},
|
||||||
|
fontSize: 24, // 字体大小
|
||||||
|
scrollBeyondLastLine: false, // 取消代码后面一大段空白
|
||||||
|
overviewRulerBorder: false, // 不要滚动条的边框
|
||||||
|
})
|
||||||
|
}
|
||||||
|
// 监听值的变化
|
||||||
|
editor.onDidChangeModelContent(() => {
|
||||||
|
value.value = editor.getValue()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<el-form :inline="true">
|
||||||
|
<el-form-item label="语言" label-width="60">
|
||||||
|
<el-select class="language" v-model="language">
|
||||||
|
<el-option value="C">C</el-option>
|
||||||
|
<el-option value="Python">Python</el-option>
|
||||||
|
<el-option value="CPP">C++</el-option>
|
||||||
|
<el-option value="Java">Java</el-option>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item>
|
||||||
|
<el-button @click="reset">重置</el-button>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
<div ref="monacoEditorRef" class="editor"></div>
|
||||||
|
<el-tabs type="border-card">
|
||||||
|
<el-tab-pane label="测试用例"> 1 </el-tab-pane>
|
||||||
|
<el-tab-pane label="执行结果"> 2 </el-tab-pane>
|
||||||
|
</el-tabs>
|
||||||
|
<el-form class="actions">
|
||||||
|
<el-form-item>
|
||||||
|
<el-button>运行</el-button>
|
||||||
|
<el-button type="primary">提交</el-button>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.language {
|
||||||
|
width: 100px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.editor {
|
||||||
|
height: 500px;
|
||||||
|
}
|
||||||
|
.actions {
|
||||||
|
margin-top: 20px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -1,8 +1,9 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { onMounted, ref, reactive, watch, VueElement } from "vue"
|
import { onMounted, ref, reactive, watch } from "vue"
|
||||||
import { useRoute, useRouter } from "vue-router"
|
import { useRoute, useRouter } from "vue-router"
|
||||||
import { useUserStore } from "../../shared/stores/user"
|
import { useUserStore } from "../../shared/stores/user"
|
||||||
import { filterEmptyValue } from "../../utils/functions"
|
import { filterEmptyValue } from "../../utils/functions"
|
||||||
|
import { getTagColor } from "../../utils/constants"
|
||||||
import { getProblemList, getProblemTagList, getRandomProblemID } from "../api"
|
import { getProblemList, getProblemTagList, getRandomProblemID } from "../api"
|
||||||
|
|
||||||
const difficultyOptions = [
|
const difficultyOptions = [
|
||||||
@@ -27,14 +28,6 @@ const query = reactive({
|
|||||||
limit: parseInt(<string>route.query.limit) || 10,
|
limit: parseInt(<string>route.query.limit) || 10,
|
||||||
})
|
})
|
||||||
|
|
||||||
function getTagColor(tag: string) {
|
|
||||||
return {
|
|
||||||
简单: "success",
|
|
||||||
中等: "",
|
|
||||||
困难: "danger",
|
|
||||||
}[tag]
|
|
||||||
}
|
|
||||||
|
|
||||||
async function listTags() {
|
async function listTags() {
|
||||||
const res = await getProblemTagList()
|
const res = await getProblemTagList()
|
||||||
tags.value = res.data
|
tags.value = res.data
|
||||||
|
|||||||
7
src/oj/problem/problem-content.vue
Normal file
7
src/oj/problem/problem-content.vue
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
const { problem } = defineProps(["problem"])
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template></template>
|
||||||
|
|
||||||
|
<style scoped></style>
|
||||||
40
src/oj/problem/problem-info.vue
Normal file
40
src/oj/problem/problem-info.vue
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { defineProps } from "vue"
|
||||||
|
import { DIFFICULTY, getTagColor } from "../../utils/constants"
|
||||||
|
|
||||||
|
const { problem } = defineProps(["problem"])
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<el-descriptions border>
|
||||||
|
<el-descriptions-item label="ID">
|
||||||
|
{{ problem._id }}
|
||||||
|
</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="出题人">
|
||||||
|
{{ problem.created_by.username }}
|
||||||
|
</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="难度">
|
||||||
|
<el-tag :type="getTagColor(problem.difficulty)">
|
||||||
|
{{ DIFFICULTY[<"Low" | "Mid" | "High">problem.difficulty] }}
|
||||||
|
</el-tag>
|
||||||
|
</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="时间限制">
|
||||||
|
{{ problem.time_limit }}毫秒
|
||||||
|
</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="内存限制">
|
||||||
|
{{ problem.memory_limit }}MB
|
||||||
|
</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="类型">
|
||||||
|
{{ problem.rule_type }}
|
||||||
|
</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="标签">
|
||||||
|
<el-space>
|
||||||
|
<el-tag type="info" v-for="tag in problem.tags" :key="tag">
|
||||||
|
{{ tag }}
|
||||||
|
</el-tag>
|
||||||
|
</el-space>
|
||||||
|
</el-descriptions-item>
|
||||||
|
</el-descriptions>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped></style>
|
||||||
@@ -119,11 +119,26 @@ export const STORAGE_KEY = {
|
|||||||
USER: "user",
|
USER: "user",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const DIFFICULTY = {
|
||||||
|
Low: "简单",
|
||||||
|
Mid: "中等",
|
||||||
|
High: "困难",
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getTagColor(tag: string) {
|
||||||
|
return {
|
||||||
|
Low: "success",
|
||||||
|
Mid: "",
|
||||||
|
High: "danger",
|
||||||
|
简单: "success",
|
||||||
|
中等: "",
|
||||||
|
困难: "danger",
|
||||||
|
}[tag]
|
||||||
|
}
|
||||||
|
|
||||||
export function buildProblemCodeKey(problemID: number, contestID = null) {
|
export function buildProblemCodeKey(problemID: number, contestID = null) {
|
||||||
if (contestID) {
|
if (contestID) {
|
||||||
return `${STORAGE_KEY.PROBLEM_CODE}_${contestID}_${problemID}`
|
return `${STORAGE_KEY.PROBLEM_CODE}_${contestID}_${problemID}`
|
||||||
}
|
}
|
||||||
return `${STORAGE_KEY.PROBLEM_CODE}_NaN_${problemID}`
|
return `${STORAGE_KEY.PROBLEM_CODE}_NaN_${problemID}`
|
||||||
}
|
}
|
||||||
|
|
||||||
export const GOOGLE_ANALYTICS_ID = "UA-111499601-1"
|
|
||||||
|
|||||||
Reference in New Issue
Block a user