网站集群系统建设定制包装需要多少钱
摘要 本文首先介绍了在线课程管理系统的现状及开发背景,然后论述了系统的设计目标、系统需求、总体设计方案以及系统的详细设计和实现,最后对在线课程管理系统进行了系统检测并提出了还需要改进的问题。本系统能够实现教师管理,科目管理,教学计划管理,学生管理,课程管理,课程留言管理,课程收藏管理,通知公告管理等功能[1]。在设计方面,本系统采用B/S三层结构,采用MVC模式,这种模式通过VUE技术来表现页面的动态设计,从系统的安全性和代码的可重用性方面考虑,运用springboot对程序的关键代码进行封装,后台数据库选用MySQL数据库。经过设计开发测试,基本满足了用户的相关需求,较好实现了在线课程管理系统相关的功能和模块。
关键字 在线课程管理系统; springboot框架; MySQL数据库
4.1 系统设计目标
系统设计的时候,就要制定需要达成的目标。在功能上,要严格符合设计需求,不仅仅要减少操作步骤,也要符合预期。因此,在规范化的今天设计出符合项目要求的系统,必须要达到下面设定的目标。
第一个目标就是友好性:友好性主要体现在用户使用过程中,不会对系统的操作产生一种不满,减少操作者的愤怒,这是相当重要的一个体现。前几年好多软件在这个友好性方面失去了市场,就是因为在友好性这方面没有做好。国内互联网发展初期,软件设计的目的就是能用就行,至于友好性的对比,那是不存在的,因为硬件效率比较低,计算机属于新兴行业,所以大哥不说二哥,都是不友好的。随着计算机硬件的提升,很多开发者开始注意到要牺牲一定的计算器性能来提升友好性,因为计算机发展到现在,第一印象很重要,一个软件设计的不好看,会让大部分人对其产生质疑,所以要在友好性上面下很大功夫进行雕琢。
第二个目标就是安全性:安全性其实贯穿着整个软件行业的发展史,计算机就是为解决人类重复性计算以及数据存储的目的而诞生的,很多行业都需要计算机来进行计算,减少出错几率,并且把数据保留,可以实时查询,所以数据的安全性也很重要。
只要保证数据安全性的前提,开发出符合功能需求的友好界面操作,那么就达到了系统设计的目的。
4.2功能结构设计
本系统主要是基于数据的增加,修改,删除等操作,使用者能够通过提前设定的登录功能进入指定的操作区,这里对使用者设计的功能进行结构展示。
管理员功能结构图的绘制结果见图4.1。管理员登录进入本系统操作的功能包括对教学计划,通知公告,教师,学生,课程信息进行增删改查,以及管理课程收藏和课程留言,管理班级等信息。

图4.1 管理员功能结构图
教师功能结构图的绘制结果见图4.2。教师登录进入本系统操作的功能包括新增教学计划,新增课程信息,对学生的课程留言进行回复,查看通知公告。

图4.2 教师功能结构图
学生功能结构图的绘制结果见图4.3。学生登录进入本系统操作的功能包括观看课程视频,查看课程知识,对课程留言,查看通知公告,更改个人信息。

图4.3 学生功能结构图
4.3数据库设计
如果说设计系统的功能很重要,那么设计该系统的数据库将更重要,毕竟系统服务于用户,数据库服务于系统,用户访问系统,操作系统的所有数据都要依赖于数据库,而系统的数据几乎都是保存在数据库中的,所以,一个高质量的程序,必然拥有一个安全,快速响应,稳定可靠的数据库。本系统的MySQL数据库可以通过SQL语言来实现对系统数据的管理,包括在指定表中插入数据,在规定的表中更改数据,以及删除指定表中的部分数据等操作。一般来说,像MySQL这样的关系型数据库,对于结构化查询语言SQL都能很好的进行支持[8]。
4.3.1 数据库概念设计
本节内容主要是使用图形的方式来描述数据库中的实体,每个实体的相应属性,还有实体之间的相互联系,常用的Visio工具即可满足绘制E-R图的需求。E-R图是由矩形,椭圆,菱形等图形元素组成,矩形框中主要写实体的名称,椭圆框中主要是登记该实体的属性,而菱形框中主要是登记实体之间的联系名称,最后使用实心线段把这些图形元素进行连接,即可完成E-R图的绘制[9]。当初步得到一个E-R图时,需要进行检查,使用分析的方式去修改,重构E-R图,以达到消除数据冗余[10],或者是消除实体间联系冗余的目的。从而保持数据库的完整性,以及降低数据库维护上面的难度[11]。
- 使用Visio这样的常用的实体属性图绘制工具来绘制教师实体属性图,绘制结果见图4.3。
 

图4.3 教师实体属性图
- 使用Visio这样的常用的实体属性图绘制工具来绘制课程实体属性图,绘制结果见图4.4。
 

图4.4 课程实体属性图
- 使用Visio这样的常用的实体属性图绘制工具来绘制教学计划实体属性图,绘制结果见图4.5。
 

图4.5 教学计划实体属性图
- 使用Visio这样的常用的实体属性图绘制工具来绘制学生实体属性图,绘制结果见图4.6。
 

图4.6 学生实体属性图
- 绘制的上述实体间存在的联系见图4.7。
 

图4.7 实体间关系E-R图
4.3.2 数据库物理设计
本系统数据在数据库中都是通过各种二维表进行记录保存的,在数据库中设计这样的二维表也是比较重要的内容,因为它影响着数据的存储效率。在设计二维表也就是关系模型之前,一些有关二维表方面的常用概念需要进行充分了解。
关系:一张具体的数据表即表示关系,关系的名称与数据表的名称保持一致;
元组:数据表中,每行显示的数据即代表元组;
属性:数据表中,每列表示的数据即代表属性;
关键字:数据表中,为了与其他数据表进行区分,则需要在每张表中进行主键的设置;
通过上节内容可以知晓数据库中的各个实体,并通过一定方式把这些实体表示的内容进行数据表的转换,通常来说,每个实体都会对应一张具体的数据表,在本系统指定的数据库中创建命名好的数据库,才可以对数据表进行创建与设计。在线课程管理系统数据表设计结果展示如表4.1,表4.2,表4.3,表4.4,表4.5,表4.6,表4.7,表4.8:
表4.1 通知公告表
|   字段  |   注释  |   类型  |   空  | 
|   id (主键)  |   主键  |   int(11)  |   否  | 
|   gonggao_name  |   通知公告名称  |   varchar(200)  |   是  | 
|   gonggao_photo  |   通知公告图片  |   varchar(200)  |   是  | 
|   gonggao_types  |   通知公告类型  |   int(11)  |   否  | 
|   insert_time  |   通知公告发布时间  |   timestamp  |   是  | 
|   gonggao_content  |   通知公告详情  |   text  |   是  | 
|   create_time  |   创建时间  |   timestamp  |   是  | 
表4.2 教师表
|   字段  |   注释  |   类型  |   空  | 
|   id (主键)  |   主键  |   int(11)  |   否  | 
|   username  |   账户  |   varchar(200)  |   是  | 
|   password  |   密码  |   varchar(200)  |   是  | 
|   jiaoshi_name  |   教师姓名  |   varchar(200)  |   是  | 
|   jiaoshi_phone  |   教师手机号  |   varchar(200)  |   是  | 
|   jiaoshi_id_number  |   教师身份证号  |   varchar(200)  |   是  | 
|   jiaoshi_photo  |   教师头像  |   varchar(200)  |   是  | 
|   sex_types  |   性别  |   int(11)  |   是  | 
|   jiaoshi_email  |   电子邮箱  |   varchar(200)  |   是  | 
|   create_time  |   创建时间  |   timestamp  |   是  | 
表4.3 教学计划表
|   字段  |   注释  |   类型  |   空  | 
|   id (主键)  |   主键  |   int(11)  |   否  | 
|   jiaoshi_id  |   教师  |   int(11)  |   是  | 
续表4.3
|   字段  |   注释  |   类型  |   空  | 
|   kecheng_id  |   课程  |   int(11)  |   是  | 
|   jiaoxuejihua_uuid_number  |   教学计划编号  |   varchar(200)  |   是  | 
|   jiaoxuejihua_name  |   教学计划名称  |   varchar(200)  |   是  | 
|   jiaoxuejihua_file  |   教学计划文件  |   varchar(200)  |   是  | 
|   jiaoxuejihua_types  |   教学计划类型  |   int(11)  |   是  | 
|   jiaoxuejihua_content  |   教学计划内容  |   text  |   是  | 
|   insert_time  |   记录时间  |   timestamp  |   是  | 
|   create_time  |   创建时间  |   timestamp  |   是  | 
表4.4 课程表
|   字段  |   注释  |   类型  |   空  | 
|   id (主键)  |   主键  |   int(11)  |   否  | 
|   jiaoshi_id  |   教师  |   int(11)  |   是  | 
|   kecheng_name  |   课程名称  |   varchar(200)  |   是  | 
|   kecheng_uuid_number  |   课程编号  |   varchar(200)  |   是  | 
|   kecheng_photo  |   课程照片  |   varchar(200)  |   是  | 
|   kecheng_video  |   课程视频  |   varchar(200)  |   是  | 
|   kecheng_file  |   课件  |   varchar(200)  |   是  | 
|   kecheng_types  |   科目  |   int(11)  |   是  | 
|   kecheng_clicknum  |   课程热度  |   int(11)  |   是  | 
|   kecheng_content  |   课程内容  |   text  |   是  | 
|   zhishiyaodian_content  |   知识要点  |   text  |   是  | 
|   kaoshidagang_content  |   考试大纲  |   text  |   是  | 
|   shangxia_types  |   是否上架  |   int(11)  |   是  | 
|   kecheng_delete  |   逻辑删除  |   int(11)  |   是  | 
|   create_time  |   创建时间  |   timestamp  |   是  | 
表4.5 课程收藏表
|   字段  |   注释  |   类型  |   空  | 
|   id (主键)  |   主键  |   int(11)  |   否  | 
|   kecheng_id  |   课程  |   int(11)  |   是  | 
|   xuesheng_id  |   学生  |   int(11)  |   是  | 
|   kecheng_collection_types  |   类型  |   int(11)  |   是  | 
|   insert_time  |   收藏时间  |   timestamp  |   是  | 
|   create_time  |   创建时间  |   timestamp  |   是  | 
表4.6 课程留言表
|   字段  |   注释  |   类型  |   空  | 
|   id (主键)  |   主键  |   int(11)  |   否  | 
|   kecheng_id  |   课程  |   int(11)  |   是  | 
|   xuesheng_id  |   学生  |   int(11)  |   是  | 
|   kecheng_liuyan_text  |   留言内容  |   text  |   是  | 
|   insert_time  |   留言时间  |   timestamp  |   是  | 
|   reply_text  |   回复内容  |   text  |   是  | 
|   update_time  |   回复时间  |   timestamp  |   是  | 
|   create_time  |   创建时间  |   timestamp  |   是  | 
表4.7 管理员表
|   字段  |   注释  |   类型  |   空  | 
|   id (主键)  |   主键  |   bigint(20)  |   否  | 
|   username  |   用户名  |   varchar(100)  |   否  | 
|   password  |   密码  |   varchar(100)  |   否  | 
|   role  |   角色  |   varchar(100)  |   是  | 
|   addtime  |   新增时间  |   timestamp  |   否  | 
表4.8 学生表
|   字段  |   注释  |   类型  |   空  | 
|   id (主键)  |   主键  |   int(11)  |   否  | 
|   username  |   账户  |   varchar(200)  |   是  | 
|   password  |   密码  |   varchar(200)  |   是  | 
|   xuesheng_name  |   学生姓名  |   varchar(200)  |   是  | 
|   xuesheng_phone  |   学生手机号  |   varchar(200)  |   是  | 
|   xuesheng_id_number  |   学生身份证号  |   varchar(200)  |   是  | 
|   xuesheng_photo  |   学生头像  |   varchar(200)  |   是  | 
|   sex_types  |   性别  |   int(11)  |   是  | 
|   banji_types  |   班级  |   int(11)  |   是  | 
|   xuesheng_email  |   电子邮箱  |   varchar(200)  |   是  | 
|   create_time  |   创建时间  |   timestamp  |   是  | 
5.1管理员功能实现
5.1.1 通知公告管理
管理员进入如图5.1所示的通知公告管理界面之后,管理员点击信息显示栏中最右侧的修改,删除按钮可依次完成通知公告信息的修改,删除等操作。通知公告信息有通知公告名称,通知公告内容等信息[12]。

图5.1 通知公告管理界面
添加通知@RequestMapping("/save")
 public R save(@RequestBody GonggaoEntity gonggao, HttpServletRequest request){
     logger.debug("save方法:,,Controller:{},,gonggao:{}",this.getClass().getName(),gonggao.toString());
     String role = String.valueOf(request.getSession().getAttribute("role"));
     if(false)
         return R.error(511,"永远不会进入");
     Wrapper<GonggaoEntity> queryWrapper = new EntityWrapper<GonggaoEntity>()
         .eq("gonggao_name", gonggao.getGonggaoName())
         .eq("gonggao_types", gonggao.getGonggaoTypes())
         ;
     logger.info("sql语句:"+queryWrapper.getSqlSegment());
     GonggaoEntity gonggaoEntity = gonggaoService.selectOne(queryWrapper);
     if(gonggaoEntity==null){
         gonggao.setInsertTime(new Date());
         gonggao.setCreateTime(new Date());
         gonggaoService.insert(gonggao);
         return R.ok();
     }else {
         return R.error(511,"表中有相同数据");
     }
 }
5.1.2 教师管理
管理员进入如图5.2所示的教师管理界面之后,管理员点击信息显示栏中最右侧的修改,删除按钮可依次完成教师信息的修改,删除等操作。

图5.2 教师管理界面
教师删除@RequestMapping("/delete")
 public R delete(@RequestBody Integer[] ids){
logger.debug("delete:,,Controller:{},,ids:{}",this.getClass().getName(),ids.toString());
     jiaoshiService.deleteBatchIds(Arrays.asList(ids));
     return R.ok();
 }
5.1.3 学生管理
管理员进入如图5.3所示的学生管理界面之后,管理员点击信息显示栏中最右侧的修改,删除按钮可依次完成学生信息的修改,删除等操作。学生的账号密码,管理员也能重置。

图5.3 学生管理界面
学生删除@RequestMapping("/delete")
 public R delete(@RequestBody Integer[] ids){
logger.debug("delete:,,Controller:{},,ids:{}",this.getClass().getName(),ids.toString());
     xueshengService.deleteBatchIds(Arrays.asList(ids));
     return R.ok();
 }
5.2 教师功能实现
5.2.1 教学计划管理
教师进入如图5.4所示的教学计划管理界面之后,教师点击信息显示栏中最右侧的修改,删除按钮可依次完成教学计划信息的修改,删除等操作。教学计划信息包括教学计划文件,教学计划名称,教学计划编号等信息,教师可以添加教学计划。

图5.4 教学计划管理界面
添加教学计划@RequestMapping("/save")
 public R save(@RequestBody JiaoxuejihuaEntity jiaoxuejihua, HttpServletRequest request){
     logger.debug("save方法:,,Controller:{},,jiaoxuejihua:{}",this.getClass().getName(),jiaoxuejihua.toString());
     String role = String.valueOf(request.getSession().getAttribute("role"));
     if(false)
         return R.error(511,"永远不会进入");
     else if("教师".equals(role))
         jiaoxuejihua.setJiaoshiId(Integer.valueOf(String.valueOf(request.getSession().getAttribute("userId"))));
     Wrapper<JiaoxuejihuaEntity> queryWrapper = new EntityWrapper<JiaoxuejihuaEntity>()
         .eq("jiaoshi_id", jiaoxuejihua.getJiaoshiId())
         .eq("kecheng_id", jiaoxuejihua.getKechengId())
         .eq("jiaoxuejihua_uuid_number", jiaoxuejihua.getJiaoxuejihuaUuidNumber())
         .eq("jiaoxuejihua_name", jiaoxuejihua.getJiaoxuejihuaName())
         .eq("jiaoxuejihua_types", jiaoxuejihua.getJiaoxuejihuaTypes())
         ;
     logger.info("sql语句:"+queryWrapper.getSqlSegment());
     JiaoxuejihuaEntity jiaoxuejihuaEntity = jiaoxuejihuaService.selectOne(queryWrapper);
     if(jiaoxuejihuaEntity==null){
         jiaoxuejihua.setInsertTime(new Date());
         jiaoxuejihua.setCreateTime(new Date());
         jiaoxuejihuaService.insert(jiaoxuejihua);
         return R.ok();
     }else {
         return R.error(511,"表中有相同数据");
     }
 }
5.2.2 课程管理
教师进入如图5.5所示的课程管理界面之后,教师点击信息显示栏中最右侧的修改,删除,下架按钮可依次完成课程信息的修改,删除,下架等操作。课程信息包括课程热度,课程视频,课程编号,课程名称等信息。教师也能添加课程[13]。

图5.5 课程管理界面
添加课程@RequestMapping("/save")
 public R save(@RequestBody KechengEntity kecheng, HttpServletRequest request){
     logger.debug("save方法:,,Controller:{},,kecheng:{}",this.getClass().getName(),kecheng.toString());
     String role = String.valueOf(request.getSession().getAttribute("role"));
     if(false)
         return R.error(511,"永远不会进入");
     else if("教师".equals(role))
         kecheng.setJiaoshiId(Integer.valueOf(String.valueOf(request.getSession().getAttribute("userId"))));
     Wrapper<KechengEntity> queryWrapper = new EntityWrapper<KechengEntity>()
         .eq("jiaoshi_id", kecheng.getJiaoshiId())
         .eq("kecheng_name", kecheng.getKechengName())
         .eq("kecheng_uuid_number", kecheng.getKechengUuidNumber())
         .eq("kecheng_video", kecheng.getKechengVideo())
         .eq("kecheng_types", kecheng.getKechengTypes())
         .eq("kecheng_clicknum", kecheng.getKechengClicknum())
         .eq("shangxia_types", kecheng.getShangxiaTypes())
         .eq("kecheng_delete", kecheng.getKechengDelete())
         ;
     logger.info("sql语句:"+queryWrapper.getSqlSegment());
     KechengEntity kechengEntity = kechengService.selectOne(queryWrapper);
     if(kechengEntity==null){
         kecheng.setKechengClicknum(1);
         kecheng.setShangxiaTypes(1);
         kecheng.setKechengDelete(1);
         kecheng.setCreateTime(new Date());
         kechengService.insert(kecheng);
         return R.ok();
     }else {
         return R.error(511,"表中有相同数据");
     }
 }
5.2.3 课程留言管理
教师进入如图5.6所示的课程留言管理界面之后,教师点击信息显示栏中最右侧的详情,回复按钮可依次完成课程留言信息的详情查看,留言回复等操作。

图5.6 课程留言管理界面
回复留言   @RequestMapping("/update")
 public R update(@RequestBody KechengLiuyanEntity kechengLiuyan, HttpServletRequest request){
         logger.debug("update方法:,,Controller:{},,kechengLiuyan:{}",this.getClass().getName(),kechengLiuyan.toString());
         String role = String.valueOf(request.getSession().getAttribute("role"));
//        if(false)
//            return R.error(511,"永远不会进入");
//        else if("学生".equals(role))
//            kechengLiuyan.setXueshengId(Integer.valueOf(String.valueOf(request.getSession().getAttribute("userId"))));
        //根据字段查询是否有相同数据
        Wrapper<KechengLiuyanEntity> queryWrapper = new EntityWrapper<KechengLiuyanEntity>()
             .eq("id",0)
             ;
         logger.info("sql语句:"+queryWrapper.getSqlSegment());
         KechengLiuyanEntity kechengLiuyanEntity = kechengLiuyanService.selectOne(queryWrapper);
         kechengLiuyan.setUpdateTime(new Date());
         if(kechengLiuyanEntity==null){
             kechengLiuyanService.updateById(kechengLiuyan);//根据id更新
            return R.ok();
         }else {
             return R.error(511,"表中有相同数据");
         }
     }
5.3 学生功能实现
5.3.1 课程信息
学生进入如图5.7所示的课程信息界面之后,学生通过播放课程视频的方式学习课程知识,学生也能查看课程的知识要点,考试大纲等信息,还可以发布课程的留言信息。

图5-7 课程信息界面
5.3.2 通知公告
学生进入如图5.8所示的通知公告界面之后,学生根据通知公告类型筛选通知公告信息,学生可以查看通知公告的具体内容。

图5-8 通知公告界面
5.3.3 更改个人信息
学生进入如图5.9所示的更改个人信息界面之后,学生重新上传头像来替换现有的头像,以及对电子邮箱,手机号等产生变化的数据进行更改,更改了数据之后,需要学生点击更新信息按钮来保存更改的数据。

图5.9 更改个人信息界面
更改个人信息  @RequestMapping("/update")
 public R update(@RequestBody XueshengEntity xuesheng, HttpServletRequest request){logger.debug("update方法:,,Controller:{},,xuesheng:{}",this.getClass().getName(),xuesheng.toString());
         String role = String.valueOf(request.getSession().getAttribute("role"));
//        if(false)
//            return R.error(511,"永远不会进入");
        //根据字段查询是否有相同数据
        Wrapper<XueshengEntity> queryWrapper = new EntityWrapper<XueshengEntity>()
             .notIn("id",xuesheng.getId())
             .andNew()
             .eq("username", xuesheng.getUsername())
             .or()
             .eq("xuesheng_phone", xuesheng.getXueshengPhone())
             .or()
             .eq("xuesheng_id_number", xuesheng.getXueshengIdNumber());
         logger.info("sql语句:"+queryWrapper.getSqlSegment());
         XueshengEntity xueshengEntity = xueshengService.selectOne(queryWrapper);
         if("".equals(xuesheng.getXueshengPhoto()) || "null".equals(xuesheng.getXueshengPhoto())){
                 xuesheng.setXueshengPhoto(null); }
         if(xueshengEntity==null){
             xueshengService.updateById(xuesheng);//根据id更新
            return R.ok(); }else {
             return R.error(511,"账户或者学生手机号或者学生身份证号已经被使用");}}
