add problem.

This commit is contained in:
2023-01-05 10:24:06 +08:00
parent 56e28abfa6
commit f88c053848
9 changed files with 228 additions and 102 deletions

3
components.d.ts vendored
View File

@@ -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']

View File

@@ -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),

View File

@@ -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>

View File

@@ -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
View 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>

View File

@@ -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

View File

@@ -0,0 +1,7 @@
<script setup lang="ts">
const { problem } = defineProps(["problem"])
</script>
<template></template>
<style scoped></style>

View 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>

View File

@@ -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"