当前位置: 首页 > 后端技术 > PHP

高校教务系统中课程的简单实现

时间:2023-03-30 05:28:10 PHP

高校教务系统课程的简单实现零、需求分析:抛开需求谈课程就是玩流氓在很多高校教务系统或者第三方教务软件中,都有一个不可或缺的重要功能——课程表,作为整个教务软件中使用频率最高的功能,课程的好坏直接决定了课程的用户体验。系统。不过,对于刚刚接触软件开发的我来说,无论是前端界面还是后端代码,似乎都有些难度。想给和我一样正在开发教务系统相关软件的朋友一些思路,于是诞生了这个博客。如图为某教务软件的排课表界面:1.E-R——数据应该如何存储(本文以MySQL为例)1.第一个问题:数据表A课程是一个实体,因为一个课程包含了很多类,所以会有很多条数据。如果只有一张数据表,每个类都会作为单独的数据写入表中。无疑会产生大量的冗余数据(因为对于某个班级中的每一门课程,他们的课程名、班级、老师都是一样的),还会有其他问题,比如课程是一个对象,而且这种方式存储的数据,同一个A课程被拆分成多个对象,数据访问不方便。那么应该怎么写呢?——为课程创建数据表(名为Course表),为班级创建数据表(名为Course_info表)。这样一来,课程与班级就是多对一的实体关系。2、第二个问题:课程信息有哪些字段?首先声明关于时间表示的关键字段:week(第一周,第二周...)week,int类型week(Monday,Tuesday...)weekday,int类型classtime(一等班,二等班...)begin,int类型对于同一门课程,不同的周和不同的时间段,上课的教室会有所不同,也就是说,对于同一门课程的每一节课,week,period,和三个值中的任意两个课堂随着第三个值的变化而变化,并且这三个值中至少有一个会在每个班级发生变化;对于同一门课程,课程名称、教师、班级这三个值都是相同的。因此,这两个数据表中应该存储什么内容就很明显了——不变的存储在Course表中,变化的存储在Course_info表中。Course表的字段:Course_info表的字段:Course表数据:Course_info表数据:可以看出,只要course_id字段正确指向Course表的对象,无论课程时间或课堂如何变化,课程还是原来的课程,老师还是原来的老师。3.第三个问题:课程的大小。大学课程,一个大班,会持续几个连续的section(请看本文第一张图),所以在数据库中,每个class保存一个大section,或者section,是个问题。一开始的想法是把它们都存储成大段,每个段有两个小节,把一天分成五个小节,但是随之而来的问题是,如果一节课是三个小节怎么办?于是,我换个思路,省小节,把一个班分成11个小节。这种方式出现了一个问题:一大段是一个对象。如果您保存小节,您将强行将一个大节拆分为两个或三个对象。可能你觉得这样无伤大雅,但试想一下,一旦你需要记录签到状态,三个section就是三个object。这样,在二堂课期间,一堂课的签到信息就失效了。如果想再次看到二班的签到信息,需要重新签到,影响用户体验。因此,一个合理的方案是将一天分成11节,每节课存储一个起点(启示节的课号)和长度(一节课持续多少节)。这样就解决了上面提到的所有问题:一个类就是一个对象,同时时间段足够详细。对Course_info表做如下修改,增加duration:修改数据:2.后端有合理的数据库支持,后端的查询方法很容易写:从session并取出当前Time信息:week,week,sectionnumber根据登录信息,从学生与课程的关联表(Score表,本文未提及)中获取该学生所有课程的ids,是一个int类型的数组,根据得到的数组,在Course表中,取出该学生修过的所有课程循环,对于每一门课程,在Course_in表中,查找该学生本周的所有课程(week)和thisweek(weekday)新建一个二维数组,作为课表,因为一周7天,每天有11小节,所以二维数组的大小是7*11。此时,刚刚查询到的每一个班级就是该学生本周的班级。所以只需要按照工作日(weekday)和开始段(begin)将数据填入schedule数组的对应位置,就可以将schedule传给前端了。(代码以ThinkPHP为例)//获取学生id$studentId=session('studentId');//查询本学期所有课程,(成绩表是学生、课程、成绩的关联表)$score=newScore();$getScore=$score->where(['course_id'=>$courseIds,'student_id'=>$studentId])->select();//创建课程表数组$coursetable=array('1'=>array('0','0','0','0','0','0','0','0'),'2'=>数组('0','0','0','0','0','0','0','0'),'3'=>数组('0','0','0','0','0','0','0','0'),'4'=>array('0','0','0','0','0','0','0','0'),'5'=>array('0','0','0','0','0','0','0','0'),'6'=>array('0','0','0','0','0','0','0','0'),'7'=>数组('0','0','0','0','0','0','0','0'),'8'=>数组('0','0','0','0','0','0','0','0'),'9'=>array('0','0','0','0','0','0','0','0'),'10'=>array('0','0','0','0','0','0','0','0'),'11'=>array('0','0','0','0','0','0','0','0'));//存放本学期所有课程的course_id$scoreIds=[];foreach($getScoreas$score){array_push($scoreIds,$score->course_id);}}//针对每门课程,查询所有课程(单位:section)$courseinfos=Courseinfo::where(['course_id'=>$scoreIds,'week'=>$week])->select();//将每门课程填入时间表foreach($courseinfosas$key=>$acourseinfo){{$coursetable[$acourseinfo->begin][$acourseinfo->weekday]=$acourseinfo;}}//传入课程表$this->assign('coursetable',$coursetable);三、前端1、已知:后端传入一个7*11的数组,在合适的位置有相应的课程。如果没有课程,则值为零。所以只需要在前端加一个7*11循环就可以了//循环生成表格//$i是表格的行,value是小节(begin),$j是表的列,值为星期几(工作日)for($i=0;$i<11;$i++){for($j=0;$j<7;$j++){if(weekday==$j和begin==$i的值在curriculum中存在){ThiscelldisplaysTheinformationofthiscourse}}}2.解决单元格合并的问题还是在这张图里。可以看到,当课程持续两到三节课时,连续两三个单元格会显示这节课的信息,而实际上数据库中只存储了第一节课的信息。因此需要合并单元格。使用HTML表格的rowspan标签,您可以轻松合并单元格。合并前的代码:星期一星期二合并前123456合并前789012合并前当rowspan=1时,不进行合并,相当于不写。合并代码后效果如下:MondayTuesday合并前123456789012而当rowspan改为3时,可以发现最右边的单元格被合并了。然而,实际上,合并只是表面上的说法。如果你细心一点,你一定注意到第二行和第三行分别少了一个标签。与其说rowspan是一个合并单元格,倒不如说:rowspan改变了原来单元格的高度。那么问题来了,为什么下面这行少了一个呢?如果上一行使用rowspan,后面几行保持不变,会发生什么?星期一星期二合并后123456234789012567cell非常坚韧,一旦启用rowspan,上层cell将强行“挤压”下层cell-使其向右移动一个单位。但是这个一定不能出现在课表里——不可能显示原来周三到周四的课,因为第一节课有两节课吧?!因此,需要动态判断。我们知道一个cell有两种状态:显示和不显示(不显示可以不写这行,或者用css定义一个样式“disappear”。当class等于这个样式时,cell会不显示。而一个class有3种状态:last2bars,3bars,4bars。所以对于每个cell,需要判断它上面的cell是否有长度等于2的class,判断cell是否上面它有一个长度为3的类,它上面的上层cell中是否有一个长度为4的类——如果满足以上三个条件中的任何一个,则这个cell处于隐藏状态,否则处于显示状态,但是还有一种情况需要考虑,就是数组下标不能超出范围。比如对于第一行(第一小节)的单元格,如果你请求它上面的单元格(第零小节),它会超出数组的范围并导致错误。因此,第一节,第二节和third部分需要单独处理。其他部分可以使用循环来保证不会超出索引。由于我实际项目中的代码比较乱,就不贴了。我只提供实现这个功能的逻辑,供大家参考。4.总结在我看来,最大的难点在于数据库。数据如何存储,实体关系如何建立,一个类是大段存储还是小段存储……这些都是需要考虑的问题。数据库结构是一个系统的基石,不合理的结构会大大增加开发难度,甚至可能因为数据库结构不合理而导致项目失败。另一个问题是前端输出信息时的判断。为了防止使用rowspan造成单元格错误,需要根据前几行的数据判断当前单元格是否显示。如果上面有类,就不显示了,就完美了。解决了问题。唯一不足的是,如果不用后端语言,只用HTML写循环和判断会非常非常麻烦。这也是我没有列出代码的原因——如果可以直接在前端使用JS或者使用PHP代码循环,这样可以降低复杂度。可能这种功能简单到在老大面前不值一提,但是作为一个初学者,实现这个功能真的是费了很大的力气,想了半天。大概花了四五天的时间才想出这个方案。路漫漫其修远兮,路漫漫其修远兮,我们都在成长。总有一天,当我们回首过去的自己,一定会发现,这段时间的自己一直在不断进步,脸上洋溢着欣慰的笑容。