OJ在线评测系统 前端创建题目(增) 更新题目(改) 题目列表(查) 以及做题页面的开发 基于VUECLI脚手架画界面

目录

前端创建页面的开发一

创建一个路由

用acro design写

前端创建页面的开发二

题目管理页面

搜索

最終效果

题目更新页面的开发

携带参数的那种

修改路由

页码更新细节

我们先处理菜单项的权限控制和权限隐藏

在这里改

属性绑定一个函数

可以参考聚合搜索项目状态改变和url状态同步

就会触发loadData函数

当分页页号改变时 触发@page-change事件 通过改变searchParams的数值

然后

题目列表搜索页

代码

设置路由

做题页面

代码

路由


前端创建页面的开发一

创建一个路由

  {path: "/add/question",name: "创建题目",component: AddQuestionView,meta: {access: ACCESS_ENUM.USER,},},

用acro design写

<template><div id="addQuestionView" style="max-width: 800px; margin: 0 auto"><h2 style="margin-bottom: 16px">创建题目</h2><a-form :model="form" label-align="left"><a-form-item label="标题"><a-input v-model="form.title" placeholder="" /></a-form-item><a-form-item label="标签"><a-input-tag v-model="form.tags" placeholder="请选择标签" allow-clear /></a-form-item><a-form-item label="题目内容"><MdEditor :value="form.content" :handle-change="onContentChange" /></a-form-item><a-form-item label="答案"><MdEditor :value="form.answer" :handle-change="onAnswerChange" /></a-form-item><a-form-item label="判题配置一"><div><a-form-item label="时间限制"><a-input-numberv-model="form.judgeConfig.timeLimit"placeholder="请输入时间限制"mode="button"min="0"size="large"/></a-form-item></div></a-form-item><a-form-item label="判题配置二"><div><a-form-item label="内存限制"><a-input-numberv-model="form.judgeConfig.memoryLimit"placeholder="请输入内存限制"mode="button"min="0"size="large"/></a-form-item></div></a-form-item><a-form-item label="判题配置三"><div><a-form-item label="堆栈限制"><a-input-numberv-model="form.judgeConfig.stackLimit"placeholder="请输入堆栈限制"mode="button"min="0"size="large"/></a-form-item></div></a-form-item><a-form-item label="测试用例配置"><!-- 使用表格布局或者 flex 布局 --><table><tbody><tr v-for="(judgeCaseItem, index) of form.judgeCase" :key="index"><td><a-form-item :label="`输入用例-${index}`" no-style><a-inputv-model="judgeCaseItem.input"placeholder="请输入测试输入用例"/></a-form-item></td><td><a-form-item :label="`输出用例-${index}`" no-style><a-inputv-model="judgeCaseItem.output"placeholder="请输入测试输出用例"/></a-form-item></td><td><a-button status="danger" @click="handleDelete(index)">删除</a-button></td></tr></tbody></table><div style="margin-top: 16px"><a-button @click="handleAdd" type="outline" status="success">新增测试用例</a-button></div></a-form-item><a-form-item style="text-align: center"><a-button type="primary" style="min-width: 200px" @click="doSubmit">提交</a-button></a-form-item></a-form></div>
</template><script setup lang="ts">
import { onMounted, ref } from "vue";
import MdEditor from "@/components/MdEditor.vue";
import { QuestionControllerService } from "../../../generated";
import message from "@arco-design/web-vue/es/message";
import { useRoute } from "vue-router";const route = useRoute();
// 如果页面地址包含 update,视为更新页面
const updatePage = route.path.includes("update");let form = ref({title: "",tags: [],answer: "",content: "",judgeConfig: {memoryLimit: 1000,stackLimit: 1000,timeLimit: 1000,},judgeCase: [{input: "",output: "",},],
});/*** 根据题目 id 获取老的数据*/
const loadData = async () => {const id = route.query.id;if (!id) {return;}const res = await QuestionControllerService.getQuestionByIdUsingGet(id as any);if (res.code === 0) {form.value = res.data as any;// json 转 js 对象if (!form.value.judgeCase) {form.value.judgeCase = [{input: "",output: "",},];} else {form.value.judgeCase = JSON.parse(form.value.judgeCase as any);}if (!form.value.judgeConfig) {form.value.judgeConfig = {memoryLimit: 1000,stackLimit: 1000,timeLimit: 1000,};} else {form.value.judgeConfig = JSON.parse(form.value.judgeConfig as any);}if (!form.value.tags) {form.value.tags = [];} else {form.value.tags = JSON.parse(form.value.tags as any);}} else {message.error("加载失败," + res.message);}
};onMounted(() => {loadData();
});const doSubmit = async () => {console.log(form.value);// 区分更新还是创建if (updatePage) {const res = await QuestionControllerService.updateQuestionUsingPost(form.value);if (res.code === 0) {message.success("更新成功");} else {message.error("更新失败," + res.message);}} else {const res = await QuestionControllerService.addQuestionUsingPost(form.value);if (res.code === 0) {message.success("创建成功");} else {message.error("创建失败," + res.message);}}
};/*** 新增判题用例*/
const handleAdd = () => {form.value.judgeCase.push({input: "",output: "",});
};/*** 删除判题用例*/
const handleDelete = (index: number) => {form.value.judgeCase.splice(index, 1);
};const onContentChange = (value: string) => {form.value.content = value;
};const onAnswerChange = (value: string) => {form.value.answer = value;
};
</script><style scoped>
#addQuestionView {
}
</style>

前端创建页面的开发二

开发的是其他增删改查页面

题目管理页面

查看

搜索

<template><div id="manageQuestionView"><a-table:ref="tableRef":columns="columns":data="dataList":pagination="{showTotal: true,pageSize: searchParams.pageSize,current: searchParams.current,total,}"@page-change="onPageChange"><template #optional="{ record }"><a-space><a-button type="primary" @click="doUpdate(record)"> 修改</a-button><a-button status="danger" @click="doDelete(record)">删除</a-button></a-space></template></a-table></div>
</template><script setup lang="ts">
import { onMounted, ref, watchEffect } from "vue";
import {Page_Question_,Question,QuestionControllerService,
} from "../../../generated";
import message from "@arco-design/web-vue/es/message";
import * as querystring from "querystring";
import { useRouter } from "vue-router";const tableRef = ref();const dataList = ref([]);
const total = ref(0);
const searchParams = ref({pageSize: 10,current: 1,
});const loadData = async () => {const res = await QuestionControllerService.listQuestionByPageUsingPost(searchParams.value);if (res.code === 0) {dataList.value = res.data.records;total.value = res.data.total;} else {message.error("加载失败," + res.message);}
};/*** 监听 searchParams 变量,改变时触发页面的重新加载*/
watchEffect(() => {loadData();
});/*** 页面加载时,请求数据*/
onMounted(() => {loadData();
});// {id: "1", title: "A+ D", content: "新的题目内容", tags: "["二叉树"]", answer: "新的答案", submitNum: 0,…}const columns = [{title: "题目id",dataIndex: "id",},{title: "标题",dataIndex: "title",},{title: "内容",dataIndex: "content",},{title: "标签",dataIndex: "tags",},{title: "答案",dataIndex: "answer",},{title: "提交数",dataIndex: "submitNum",},{title: "通过数",dataIndex: "acceptedNum",},{title: "判题配置",dataIndex: "judgeConfig",},{title: "判题用例",dataIndex: "judgeCase",},{title: "创建者",dataIndex: "userId",},{title: "创建时间",dataIndex: "createTime",},{title: "操作",slotName: "optional",},
];const onPageChange = (page: number) => {searchParams.value = {...searchParams.value,current: page,};
};const doDelete = async (question: Question) => {const res = await QuestionControllerService.deleteQuestionUsingPost({id: question.id,});if (res.code === 0) {message.success("删除成功");loadData();} else {message.error("删除失败");}
};const router = useRouter();const doUpdate = (question: Question) => {router.push({path: "/update/question",query: {id: question.id,},});
};
</script><style scoped>
#manageQuestionView {
}
</style>

最終效果

题目更新页面的开发

写一个动态路由

携带参数的那种

const router = useRouter();const doUpdate = (question: Question) => {router.push({path: "/update/question",query: {id: question.id,},});
};

修改路由

  {path: "/update/question",name: "更新题目",component: AddQuestionView,meta: {access: ACCESS_ENUM.USER,hideInMenu: true,},},

页码更新细节

我们的管理题目页面不能分页

我们先处理菜单项的权限控制和权限隐藏

在这里改

在组件里面定义属性

属性绑定一个函数

const onPageChange = (page: number) => {searchParams.value = {...searchParams.value,current: page,};
};

可以参考聚合搜索项目状态改变和url状态同步

当我们的属性改变了

就会触发loadData函数

当分页页号改变时 触发@page-change事件 通过改变searchParams的数值

并且通过watchEffect监听searchParams的改变

然后执行loadData重新加载速度

实现页号变化时触发数据的重新加载

然后

/*** 监听 searchParams 变量,改变时触发页面的重新加载*/
watchEffect(() => {loadData();
});

题目列表搜索页

代码

<template><div id="questionsView"><a-form :model="searchParams" layout="inline"><a-form-item field="title" label="名称" style="min-width: 240px"><a-input v-model="searchParams.title" placeholder="请输入名称" /></a-form-item><a-form-item field="tags" label="标签" style="min-width: 240px"><a-input-tag v-model="searchParams.tags" placeholder="请输入标签" /></a-form-item><a-form-item><a-button type="primary" @click="doSubmit">提交</a-button></a-form-item></a-form><a-divider size="0" /><a-table:ref="tableRef":columns="columns":data="dataList":pagination="{showTotal: true,pageSize: searchParams.pageSize,current: searchParams.current,total,}"@page-change="onPageChange"><template #tags="{ record }"><a-space wrap><a-tag v-for="(tag, index) of record.tags" :key="index" color="green">{{ tag }}</a-tag></a-space></template><template #acceptedRate="{ record }">{{`${record.submitNum ? record.acceptedNum / record.submitNum : "0"}% (${record.acceptedNum}/${record.submitNum})`}}</template><template #createTime="{ record }">{{ moment(record.createTime).format("YYYY-MM-DD") }}</template><template #optional="{ record }"><a-space><a-button type="primary" @click="toQuestionPage(record)">做题</a-button></a-space></template></a-table></div>
</template><script setup lang="ts">
import { onMounted, ref, watchEffect } from "vue";
import {Page_Question_,Question,QuestionControllerService,QuestionQueryRequest,
} from "../../../generated";
import message from "@arco-design/web-vue/es/message";
import * as querystring from "querystring";
import { useRouter } from "vue-router";
import moment from "moment";const tableRef = ref();const dataList = ref([]);
const total = ref(0);
const searchParams = ref<QuestionQueryRequest>({title: "",tags: [],pageSize: 8,current: 1,
});const loadData = async () => {const res = await QuestionControllerService.listQuestionVoByPageUsingPost(searchParams.value);if (res.code === 0) {dataList.value = res.data.records;total.value = res.data.total;} else {message.error("加载失败," + res.message);}
};/*** 监听 searchParams 变量,改变时触发页面的重新加载*/
watchEffect(() => {loadData();
});/*** 页面加载时,请求数据*/
onMounted(() => {loadData();
});// {id: "1", title: "A+ D", content: "新的题目内容", tags: "["二叉树"]", answer: "新的答案", submitNum: 0,…}const columns = [{title: "题号",dataIndex: "id",},{title: "题目名称",dataIndex: "title",},{title: "标签",slotName: "tags",},{title: "通过率",slotName: "acceptedRate",},{title: "创建时间",slotName: "createTime",},{slotName: "optional",},
];const onPageChange = (page: number) => {searchParams.value = {...searchParams.value,current: page,};
};const router = useRouter();/*** 跳转到做题页面* @param question*/
const toQuestionPage = (question: Question) => {router.push({path: `/view/question/${question.id}`,});
};/*** 确认搜索,重新加载数据*/
const doSubmit = () => {// 这里需要重置搜索页号searchParams.value = {...searchParams.value,current: 1,};
};
</script><style scoped>
#questionsView {max-width: 1280px;margin: 0 auto;
}
</style>

设置路由

  {path: "/questions",name: "浏览题目",component: QuestionsView,},

做题页面

代码

<template><div id="viewQuestionView"><a-row :gutter="[24, 24]"><a-col :md="12" :xs="24"><a-tabs default-active-key="question"><a-tab-pane key="question" title="题目"><a-card v-if="question" :title="question.title"><a-descriptionstitle="判题条件":column="{ xs: 1, md: 2, lg: 3 }"><a-descriptions-item label="时间限制">{{ question.judgeConfig.timeLimit ?? 0 }}</a-descriptions-item><a-descriptions-item label="内存限制">{{ question.judgeConfig.memoryLimit ?? 0 }}</a-descriptions-item><a-descriptions-item label="堆栈限制">{{ question.judgeConfig.stackLimit ?? 0 }}</a-descriptions-item></a-descriptions><MdViewer :value="question.content || ''" /><template #extra><a-space wrap><a-tagv-for="(tag, index) of question.tags":key="index"color="green">{{ tag }}</a-tag></a-space></template></a-card></a-tab-pane><a-tab-pane key="comment" title="评论" disabled> 评论区</a-tab-pane><a-tab-pane key="answer" title="答案"> 暂时无法查看答案</a-tab-pane></a-tabs></a-col><a-col :md="12" :xs="24"><a-form :model="form" layout="inline"><a-form-itemfield="language"label="编程语言"style="min-width: 240px"><a-selectv-model="form.language":style="{ width: '320px' }"placeholder="选择编程语言"><a-option>java</a-option><a-option>cpp</a-option><a-option>go</a-option><a-option>html</a-option></a-select></a-form-item></a-form><CodeEditor:value="form.code as string":language="form.language":handle-change="changeCode"/><a-divider size="0" /><a-button type="primary" style="min-width: 200px" @click="doSubmit">提交代码</a-button></a-col></a-row></div>
</template><script setup lang="ts">
import { onMounted, ref, watchEffect, withDefaults, defineProps } from "vue";
import message from "@arco-design/web-vue/es/message";
import CodeEditor from "@/components/CodeEditor.vue";
import MdViewer from "@/components/MdViewer.vue";import {QuestionControllerService,QuestionSubmitAddRequest,QuestionVO,
} from "../../../generated";interface Props {id: string;
}const props = withDefaults(defineProps<Props>(), {id: () => "",
});const question = ref<QuestionVO>();const loadData = async () => {const res = await QuestionControllerService.getQuestionVoByIdUsingGet(props.id as any);if (res.code === 0) {question.value = res.data;} else {message.error("加载失败," + res.message);}
};const form = ref<QuestionSubmitAddRequest>({language: "java",code: "",
});/*** 提交代码*/
const doSubmit = async () => {if (!question.value?.id) {return;}const res = await QuestionControllerService.doQuestionSubmitUsingPost({...form.value,questionId: question.value.id,});if (res.code === 0) {message.success("提交成功");} else {message.error("提交失败," + res.message);}
};/*** 页面加载时,请求数据*/
onMounted(() => {loadData();
});const changeCode = (value: string) => {form.value.code = value;
};
</script><style>
#viewQuestionView {max-width: 1400px;margin: 0 auto;
}#viewQuestionView .arco-space-horizontal .arco-space-item {margin-bottom: 0 !important;
}
</style>

路由

  {path: "/view/question/:id",name: "在线做题",component: ViewQuestionView,props: true,meta: {access: ACCESS_ENUM.USER,hideInMenu: true,},},

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/434881.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Spring Boot项目连接Oracle数据库启动报错:Undefined Error

描述&#xff1a;远程拉下来的代码&#xff0c;配置了maven仓库后&#xff0c;未进行其他修改&#xff0c;自己本地启动报错。 报错现状&#xff1a; 解决&#xff1a;添加参数-Duser.nameuser后&#xff0c;启动成功。 原因分析&#xff1a; 分析一&#xff1a; maven仓…

第三节-类与对象(中)

1.类的6个默认成员函数 如果一个类中什么成员都没有&#xff0c;简称为空类&#xff08;空类大小为1&#xff09;。 空类中真的什么都没有吗&#xff1f;并不是&#xff0c;任何类在什么都不写时&#xff0c;编译器会自动生成以下6个默认成员函数。 默认成员函数&#xff1a;…

【html网页制作】旅游风景主题网页制作含css动画及js特效(8页面附效果源码)

HTMLCSS旅游风景主题旅游网页制作 &#x1f354;涉及知识&#x1f964;写在前面&#x1f367;一、网页主题&#x1f333;二、网页效果菜单切换效果PageA、整体页Page1、首页Page2、旅行趣事页Page3、旅行美景页Page4、旅行指南页Page5、旅行视频页Page6、留言页Page7、西湖简介…

论文阅读(十一):CBAM: Convolutional Block Attention Module

文章目录 1.Introduction2.Convolutional Block Attention ModuleExperimentsConclusion 论文题目&#xff1a;CBAM: Convolutional Block Attention Module&#xff08;CBAM&#xff1a;卷积注意力机制&#xff09;   论文链接&#xff1a;点击跳转   代码链接&#xff1a…

汽车3d动画渲染选择哪个?选择最佳云渲染解决方案

面临汽车3D动画渲染挑战&#xff1f;选择正确的云渲染服务至关重要。探索最佳解决方案&#xff0c;优化渲染效率&#xff0c;快速呈现逼真动画。 汽车3d动画渲染选择哪个&#xff1f; 对于汽车3D动画渲染&#xff0c;选择哪个渲染器取决于你的项目需求、预算和期望的效果。Ble…

Llama 3.1 技术研究报告-2

3.3 基础设施、扩展性和效率 我们描述了⽀持Llama 3 405B⼤规模预训练的硬件和基础设施&#xff0c;并讨论了⼏项优化措施&#xff0c;这些措施提⾼了训练效率。 3.3.1 训练基础设施 Llama 1和2模型在Meta的AI研究超级集群&#xff08;Lee和Sengupta&#xff0c;2022&#x…

探索存内计算的未来,高能效内存计算实训专场有感~

写在前面&#xff0c;首先感谢活动方&#xff1a;存内计算开发者社区的邀请来参加本次探索存内计算的未来&#xff0c;高能效内存计算实训专场。下面我给大家分享一下本次的活动实操感受&#x1f600;。 活动议程 本次活动邀请存内技术专家李阳老师分享存内计算是什么&#xf…

Subdominator:一款针对漏洞奖励计划的子域名安全枚举工具

关于Subdominator Subdominator是一款针对漏洞奖励计划的子域名安全枚举工具&#xff0c;可用于在漏洞搜寻和侦察过程中进行被动子域名枚举。它旨在通过高效枚举子域名和各种免费被动资源来帮助研究人员和网络安全专业人员发现潜在的安全漏洞。 Subdominator 与各种免费和付费…

计算机前沿技术-人工智能算法-大语言模型-最新研究进展-2024-09-24

计算机前沿技术-人工智能算法-大语言模型-最新研究进展-2024-09-24 1. Enriching Datasets with Demographics through Large Language Models: What’s in a Name? K AlNuaimi, G Marti, M Ravaut, A AlKetbi, A Henschel… - arXiv preprint arXiv …, 2024 通过大型语言…

python获取百度地图路径规划

自制语音助手想做一个查询交通路线的功能&#xff0c;于是就想到了百度地图。在百度地图的服务器端应用中&#xff0c;提供了“轻量级路线规划”API接口&#xff0c;正好可以满足需求。要用这个接口&#xff0c;需要注册百度地图账号并创建一个服务器端的应用。有关开通百度地图…

Docekrfile和docker compose编写指南及注意事项

Dockerfile 基础语法 我们通过编写dockerfile,将每一层要做的事情使用语法固定下来&#xff0c;之后运行指令就可以通过docker来制作自己的镜像了。 构建镜像的指令&#xff1a;docker build /path -t imageName:tag 注意&#xff0c;docker build后的path必须是dockerfile…

Selenium与数据库结合:数据爬取与存储的技术实践

目录 一、Selenium与数据库结合的基础概念 1.1 Selenium简介 1.2 数据库简介 1.3 Selenium与数据库结合的优势 二、Selenium爬取数据的基本步骤 2.1 环境准备 2.2 编写爬虫代码 2.3 数据提取 2.4 异常处理 三、数据存储到数据库 3.1 数据库连接 3.2 数据存储 3.3 …

网络编程(10)——json序列化

十、day10 今天学习如何使用jsoncpp将json数据解析为c对象&#xff0c;将c对象序列化为json数据。jsoncp经常在网络通信中使用&#xff0c;也就是服务器和客户端的通信一般使用json&#xff08;可视化好&#xff09;&#xff1b;而protobuf一般在服务器之间的通信中使用 json…

【YashanDB知识库】yashandb执行包含带oracle dblink表的sql时性能差

本文内容来自YashanDB官网&#xff0c;具体内容请见https://www.yashandb.com/newsinfo/7396959.html?templateId1718516 问题现象 yashandb执行带oracle dblink表的sql性能差&#xff1a; 同样的语句&#xff0c;同样的数据&#xff0c;oracle通过dblink访问远端oracle执行…

可视化服务编排:jvs-logic API出参加密实战教程

在现代软件开发与系统集成的过程中&#xff0c;API&#xff08;应用程序接口&#xff09;非常重要&#xff0c;它能使不同系统之间连接&#xff0c;进行数据交换和功能调用。当然&#xff0c;数据交换的数据安全肯定是不可忽视的&#xff0c;为了确保数据在传输过程中的保密性和…

虫情测报灯的工作原理

TH-CQ3】果园、森林等区域病虫害的实时监测、预警和科学管理。病虫害监测系统通常由以下几个部分组成&#xff1a;包括图像传感器、声音传感器、气象传感器等&#xff0c;用于实时采集作物及其周围环境的数据&#xff0c;如叶片变化、虫鸣声、温度、湿度、光照等。对采集到的数…

基于RealSense D435相机实现手部姿态重定向

基于Intel RealSense D435相机和MediaPipe的手部姿态检测&#xff0c;进一步简单实现手部姿态与机器人末端的重定向&#xff0c;获取手部的6D坐标&#xff08;包括位置和姿态&#xff09;。 假设已经按照【基于 RealSenseD435i相机实现手部姿态检测】配置好所需的库和环境&…

海口网站建设的最佳实践

海口网站建设的最佳实践 随着互联网的迅猛发展&#xff0c;海口的企业和个人越来越重视网站建设。一个高质量的网站不仅能提升企业形象&#xff0c;还能有效促进品牌传播和业务发展。以下是海口网站建设的一些最佳实践&#xff0c;希望能为相关从业者提供帮助。 1. 明确目标和…

一文说清楚:如何学习好K8s、OpenStack、Docker、Linux?

大家好&#xff0c;我是你们熟悉的-CloudJourney。在这个信息爆炸的时代&#xff0c;我一直致力于通过博客、公众号等平台&#xff0c;与大家分享关于Linux、K8S、Docker、网络、服务器以及OpenStack等前沿技术的见解与心得。然而&#xff0c;随着交流的深入&#xff0c;我逐渐…

[论文精读]TorWard: Discovery, Blocking, and Traceback of Malicious Traffic Over Tor

期刊名称&#xff1a;IEEE Transactions on Information Forensics and Security 发布链接&#xff1a;TorWard: Discovery, Blocking, and Traceback of Malicious Traffic Over Tor | IEEE Journals & Magazine | IEEE Xplore 中文译名&#xff1a;TorWard&#xff1a;…