AI代码评测系统心得
业务需求
需求:开发带有用户权限管理系统的在线代码评测,测验的系统,使学生可以快速编码HTML且可以实时预览、测评。教师可以在线上布置作业,查看学生的测评记录
项目
项目构思
该项目需要用到权限管理系统,由于有若依开发的经验,决定采用若依前后端分离系统
该系统有三个主要页面
测验记录页面
测验任务页面
在线测验页面
基于若依系统,可以自动生成(测验记录+测验任务)的基础页面模版。使用element-plus快速绘制,封装通用组件
代码编辑器
富文本编辑器
封装通用hooks(科大讯飞会话api调用)
echars测验结果显示弹窗封装
数据库表
组件封装
代码编辑器Monaco Editor vue3+vite
安装依赖
npm install monaco-editor npm install vite-plugin-monaco-editor
在vue.config.ts/js中添加
import monacoEditorPlugin from 'vite-plugin-monaco-editor' plugins: [monacoEditorPlugin({})],
创建配置文件editor.js
export default { folding: true, // 是否折叠 foldingHighlight: true, // 折叠等高线 foldingStrategy: "indentation", // 折叠方式 auto | indentation showFoldingControls: "always", // 是否一直显示折叠 always | mouseover disableLayerHinting: true, // 等宽优化 emptySelectionClipboard: false, // 空选择剪切板 selectionClipboard: false, // 选择剪切板 automaticLayout: true, // 自动布局 codeLens: false, // 代码镜头 scrollBeyondLastLine: false, // 滚动完最后一行后再滚动一屏幕 colorDecorators: true, // 颜色装饰器 accessibilitySupport: "off", // 辅助功能支持 "auto" | "off" | "on" lineNumbers: "on", // 行号 取值: "on" | "off" | "relative" | "interval" | function lineNumbersMinChars: 5, // 行号最小字符 number readOnly: false, //是否只读 取值 true | false fontSize: 16,//编辑区字体大小 minimap: { enabled: false },//隐藏编辑区缩略图 }
创建组件
<template> // 宽高由父组件决定 <div ref="editorContainer" style="width: 100%; height: 100%;"></div> </template> <script setup> import * as monaco from 'monaco-editor' import options from "./editor.js"; const eimts = defineEmits(['update:modelValue']) // 传两个值 const props = defineProps({ language: { type: String, default: 'javascript' }, modelValue: { type: String, default: '' } }) const editorContainer = ref(null) const editor = ref(null) onMounted(() => { // 创建editor实例 editor.value = monaco.editor.create(editorContainer.value, { value: props.modelValue, language: props.language, ...options }) // 做节流处理 let timer = null editor.value.onDidChangeModelContent(() => { clearTimeout(timer) timer = setTimeout(() => { eimts('update:modelValue', toRaw(editor.value).getValue()) }, 1000) }); // 组件与父组件双向绑定 watch(() => props.modelValue, (newValue) => { try { const currentPosition = toRaw(editor.value).getPosition(); toRaw(editor.value).setValue(newValue) toRaw(editor.value).setPosition(currentPosition); } catch (error) { } }) }) </script> <style scoped> /* 样式 */ </style>
vue3 v-md-editor markdown编辑器
安装依赖
# 使用 npm npm i @kangc/v-md-editor@next -S # 使用 yarn yarn add @kangc/v-md-editor@next
在main挂载
import './assets/main.css' import { createApp } from 'vue' import App from './App.vue' import router from './router' // markdown编辑器 import VMdEditor from '@kangc/v-md-editor'; import '@kangc/v-md-editor/lib/style/base-editor.css'; import githubTheme from '@kangc/v-md-editor/lib/theme/github.js'; import '@kangc/v-md-editor/lib/theme/style/github.css'; import hljs from 'highlight.js'; // highlightjs VMdEditor.use(githubTheme, { Hljs: hljs, }); // markdown 预览 markdown解析需要的配置项目 import VMdPreview from '@kangc/v-md-editor/lib/preview'; // import '@kangc/v-md-editor/lib/style/preview.css' // import githubTheme from '@kangc/v-md-editor/lib/theme/github'; import '@kangc/v-md-editor/lib/theme/style/github.css'; // import hljs from 'highlight.js'; VMdPreview.use(githubTheme, { Hljs: hljs, }); const app = createApp(App) app.use(router) app.use(VMdEditor) app.use(VMdPreview) app.mount('#app')
MarkdownEdit.vue
<script setup> import { ref } from 'vue' import { RouterLink } from 'vue-router' const text = ref("") </script> <template> <main> <div style="width:80vw;"> <h3>markdown编辑器</h3> <RouterLink to="/read">markdown预览测试</RouterLink> <v-md-editor v-model="text" height="700px" ></v-md-editor> </div> </main> </template>
MarkdownRead.vue
<script setup> import { ref } from 'vue' const contentA = ref() const readText = ()=>{ // 请求的是我自己的接口地址,后端代码逻辑就是存到数据库中的一个text文件,然后下面完整的代码中,我提供了我的markdown文本 fetch('http://robin.com/Article/18') .then(response => response.text()) .then(data => { contentA.value = JSON.parse(data).content //console.log(contentA.value) }) .catch((error) => console.error('Error:', error)); } readText() </script> <template> <div class="about"> <div> <v-md-preview :text="contentA"></v-md-preview> </div> </div> </template> <style> @media (min-width: 1024px) { .about { min-height: 100vh; min-width: 1024px; margin: 0 auto; display: flex; align-items: center; } } </style>