登录页面设计
登录页面设计思路-分为三个角色进行登录,分别为学生,教师,管理员。
前端将登录设计为表单形式,通过选项组件绑定角色参数,向后端传递角色信息,通过表单绑定向后端传递登录者所有信息
<div style="display: flex; gap: 20px;"><vs-radio color="rgb(59,222,200)" v-model="form.type" val="学生">学生</vs-radio><vs-radio v-model="form.type" val="教师">教师</vs-radio><vs-radio danger v-model="form.type" val="管理员">管理员</vs-radio></div>
@PostMapping("/user/login")public Map<String,Object> Login(@RequestBody User user){Map<String,Object> map = new HashMap<>();User u = userService.LoginByUserName(user.getUserNumber());Map<String,String>payload = new HashMap<>();if(u!=null){if(user.getPassword().equals(u.getPassword()) && user.getType().equals(u.getType())){if (u.getType().equals("学生")){String className = userService.FindClassNameByClassId(u.getClassid());map.put("className",className);}payload.put("id",u.getId().toString());payload.put("username",u.getUserNumber());String token = JWTUtil.createToken(payload);System.out.println("token为"+token);map.put("UserInfo",u);map.put("userId",u.getId());map.put("code",200);map.put("status",token);map.put("msg","登陆成功");}else {map.put("msg","密码错误");map.put("status",0);}}else{map.put("msg","不存在该用户");map.put("status",0);}return map;}
通过在数据库中存入type字段,实现与后台对接并实现特定角色登录
考试系统设计
附:一张设计手稿,随笔字丑请忽略
设计思路(可结合下面数据表进行理解):
1.试卷表:每一张试卷都对应一个特有的PaperId,并且在表中存有PaperName(试卷名),PaperTime(考试时间),PaperImageSrc(考试封面图),后续可以自信添加字段,丰富考卷所具有的信息。
2.题目表:每一道题目都有一个PaperId,可以以此将隶属与对应试卷的题目信息读取,每一道题目含有独有的QuestionId(题目ID),QuestionContent(题目内容),QuestionScore(题目的得分,可以通过组卷时设置对应分数,实现灵活组卷),QuestionType(题目类型),通过这个字段可以定义题目对应的不同类型。
3.题目细节表:每一条数据都有一个独有的QuestionId,可以让它属于对应的题目,QuesitonOption(题目选项表,设置ABCD等类型的选项内容),可以通过读取对应细节有几条数据来设置它为单选题还是填空题,QuestionCorrect(选项是否正确),通过此字段判断选项正确与否。
4.题目商店表:用于老师的组卷功能,QuestionId,QuestionContent,QuestionType,QuestionTheme(问题主题,方便用于搜索,但是VueSax搜索不需要后端数据即可实现)。
思路串联:
一、用户对应考卷的设计:通过UserNumber字段从f_exam_userneedexam表中查询该用户对应的所有PaperId,然后通过此PaperId查询f_exam_paper表中考卷具体信息,即可展示用户对应所需的考试信息。
二、考卷的设计:一张试卷对应独特的PaperId,一道题目衔接对应的PaperId(衔接试卷表),题目选项衔接对应的QuestionId(衔接题目表)。
//把试卷组好@GetMapping("/exam/SelectAllQustionByPaperIdUpdate")public List<QuestionWithOptions> SelectAllQustionByPaperIdUpdate(@RequestParam Integer PaperId){List<QuestionWithOptions> questionsWithOptions = new ArrayList<>();List<Questions> allQuestions = userExamService.SelectAllQustionByPaperIdUpdate(PaperId);for (Questions question : allQuestions) {List<Options> options = userExamService.SelectAllQustionByQuestionId(question.getQuestionId());QuestionWithOptions questionWithOptions = new QuestionWithOptions(question, options);questionsWithOptions.add(questionWithOptions);}// System.out.println("第一组数据测试获取问题列表"+questionsWithOptions.get(0).getQuestion());
// System.out.println("第一组数据测试获取选项列表"+questionsWithOptions.get(0).getOptions());
// System.out.println("第一组数据测试获取选项列表的第一个选项内容"+questionsWithOptions.get(0).getOptions().get(0));
// System.out.println("第一组数据测试获取选项列表的第二个选项内容"+questionsWithOptions.get(0).getOptions().get(1));
// System.out.println("第一组数据"+questionsWithOptions.get(0));
// System.out.println("返回的最终数据"+questionsWithOptions);return questionsWithOptions;}
@Data
public class QuestionWithOptions {private Questions question;private List<Options> options;
}
<vs-dialog scroll overflow-hidden auto-width blur not-close :prevent-close="true" full-screen v-model="ExamActive"><div><h1>考卷</h1><div v-for="(questionWithOptions, index) in examQuestions" :key="index"><h2>{{ questionWithOptions.question.questionContent }}</h2><div v-for="(option, i) in questionWithOptions.options" :key="i"><label>
<!-- <vs-checkbox :value="option" v-model="selectedOptions[index]">-->
<!-- {{ option.questionOption }}-->
<!-- </vs-checkbox>--><input type="radio" :value="option" v-model="selectedOptions[index]">{{ option.questionOption }}</label></div></div><vs-button gradient @click="submitExam">提交</vs-button></div></vs-dialog>
export default {data(){return{UserNumber:"",UserName:"",examInfo:[],active: false,input1: '',input2: '',checkbox1: false,ExamActive: false,examQuestions: [], // 包含问题和选项的数组selectedOptions: [], // 用户选择的答案// JSON格式理解//// 数组和对象// LJL:[ ExamRecord:{// PaperId: "",// ExamUserNumber: "",// ExamUserName: "",// },, ExamRecord1:{// PaperId: "",// ExamUserNumber: "",// ExamUserName: "",// },]ExamRecord:{paperId: "",examUserNumber: "",examUserName: "",},UserAnswer:{Answers:"",UserNumber:"",UserName:"",PaperId:"",},PaperId:""}},methods:{StartExam(){this.active = !this.active;this.ExamActive = !this.ExamActive;this.ExamRecord = {paperId: this.PaperId,examUserNumber: this.UserNumber,examUserName: this.UserName};//插入开考记录this.$ExamApi.insertRecordFromStartExam(this.ExamRecord).then(res=>{console.log(this.ExamRecord)}).catch(err=>console.log(err))},SelectExamByPaperId(paperId) {this.active = !this.activethis.PaperId = paperIdthis.$ExamApi.SelectAllQustionByPaperIdUpdate(paperId).then(res=>{this.examQuestions = res.dataconsole.log(res.data)// 初始化选项this.selectedOptions = new Array(this.examQuestions.length).fill("");console.log(this.selectedOptions)}).catch(err=>console.log(err))// 这里可以根据 paperId 执行你需要的逻辑,比如打开对应考试的详情页面等},submitExam() {this.UserAnswer={Answers: this.selectedOptions,UserName: this.UserName,UserNumber: this.UserNumber,PaperId: this.PaperId}this.$ExamApi.insertUserAnswerAndSubmitExamToAddScore(this.UserAnswer).then(res=>{console.log(this.UserAnswer)this.openNotification('top-center', '#7d33ff', `<i class='bx bx-bell' ></i>`)this.ExamActive = !this.ExamActive})// 这里可以将用户的答案发送给后端进行处理},//获取当前用户所需要的考试信息UserNeedExamByUserNumber(){// this.$loginApi.UserLogin(this.loginData).then(res=>{this.$ExamApi.UserNeedExamByUserNumber(this.UserNumber).then(res=>{this.examInfo = res.data.dataobjectconsole.log("查询到的考试信息为")console.log(this.examInfo)}).catch(err=>console.log(err))},getCoverUrl(coverUrl) {return this.$config.getBaseUrl()+coverUrl;},//消息通知框openNotification(position = null, color, icon) {const noti = this.$vs.notification({icon,color,position,title: '恭喜您!,顺利完成了测试!',text: `您将可以在考试查询界面,查询到自己的成绩以及答题情况!!!`})}},mounted() {this.UserNumber = sessionStorage.getItem("userNumber");this.UserName = sessionStorage.getItem("userName");this.UserNeedExamByUserNumber();}
}
三、点击开考的设计:向f_exam_record(考试记录表)中插入,考试人员信息(ExamUserNumber,ExamUserName),开考时间(ExamStartTime),对应试卷PaperId。此时每条数据对应的ExamScore和ExamEndTime为空,通过交卷执行Update操作进行记录。
四、点击交卷的设计:
将用户所选的选项进行遍历,分别插入f_exam_user_answer(用户答题内容表,用于查看用户答题具体情况,即生成一份用户答题内容卷),记录用户所答题的具体信息。
通过以下代码获取此用户所作的卷子记录(通过用户学号,开考时间的降序排序,限制为一条数据,获取用户当前所考的最新试卷,用于插入交卷时间和总分)
<!-- 获得记录Id--><select id="SelectRecordId" parameterType="String" resultType="Integer">SELECT * from f_exam_record where ExamUserNumber = #{ExamUserNumber} ORDER BY ExamStartTime DESC LIMIT 1</select>
通过遍历questionCorrect字段,以获取哪条记录为正确选项,如果questionCorrect为true,通过此记录的QuestionId和PaperId在f_exam_question表中查找此题对应的QuestionScore值,然后在此时定义Score对象进行计算总分(避免了异步冲突),然后将总分以及交卷时间插入记录表格。
@PostMapping("/exam/insertUserAnswerAndSubmitExamToAddScore")public void insertUserAnswer(@RequestBody Map<String, Object> requestData) {List<Map<String, Object>> answersMapList = (List<Map<String, Object>>) requestData.get("Answers");String userName = (String) requestData.get("UserName");String userNumber = (String) requestData.get("UserNumber");Integer recordId = userExamService.SelectRecordId(userNumber);Integer PaperId = (Integer) requestData.get("PaperId");int score = 0;for (Map<String, Object> answerMap : answersMapList) {UserAnswer userAnswer = new UserAnswer();userAnswer.setId((int) answerMap.get("id"));userAnswer.setQuestionId((int) answerMap.get("questionId"));userAnswer.setQuestionOption((String) answerMap.get("questionOption"));userAnswer.setQuestionCorrect((boolean) answerMap.get("questionCorrect"));userAnswer.setExamUserNumber(userNumber);userAnswer.setExamUserName(userName);userAnswer.setRecordId(recordId);userExamService.insertUserAnswer(userAnswer);if((Boolean) answerMap.get("questionCorrect")==true){ExamRequestScore examRequestScore = new ExamRequestScore();examRequestScore.setPaperId(PaperId);examRequestScore.setQuestionId(userAnswer.getQuestionId());Integer s = userExamService.selectScoreFromStoreByQuestionIdAndPaperId(examRequestScore);score = s+score;System.out.println("编号为"+userAnswer.getQuestionId()+"的问题回答正确"+"并且正确答案的分数为:"+s);System.out.println("总分为"+score);}}ExamRecord examRecord = new ExamRecord();examRecord.setPaperId(PaperId);examRecord.setExamUserNumber(userNumber);examRecord.setExamScore(score);System.out.println("examRecord"+examRecord);userExamService.updateRecordFromEndExam(examRecord);}