从选课系统看软件开发周期
需求分析:
校园选课系统的目的是为每一个学生建立一个选课档案,负责管理一个学生从选课到考试结束的所用信息。
本选课系统分为用户管理,课程管理,系别管理,选课管理等几大模块,其功能涵盖了选课管理的主要方面,同时具有信息存储及时,检索迅速、查找方便、可靠性高、存储量大、保密性好、寿命长、成本低等优点,满足了学校的实际要求,大大提高了选课管理的效率。
用户需求:
(1)系统功能要求
- 系别/课程/用户的录入
在学期开始时由系统管理员利用系统量录入系别、录入课程、录入学生、录入教师、学生选课,以节约人员加快速度。
- 系别/课程/用户的修改
由系统管理员得到学校相关人员的同意后进行修改操作,包括录入成绩及修改成绩,并且保留操作记录。
- 系别/课程/用户的删除
学校相关人员同意后,由系统管理员删除记录,并且系统本身应记录该事件并保存原始数据。
- 系别/课程/用户/选课的查询
用户根据用户名以及相对应的密码登陆系统,然后可以根据其权限查看对应的相关信息。密码初始化由用户自身进行修改,系统对每次用户操作的数据应该在一定的时间段内保留。
(2)系统安全性
- 系统应该防止未登录及没有权限的访问,要求有较高的安全性。
可行性研究:
可行性研究的目的是用最小的代价在尽可能短的时间里确定问题是否能解决。我们具体从下面四个方面进行分析:
(1)技术上的可行性
技术上的可行性分析主要分析现有技术条件能否顺利完成开发工作,软硬件配置能否满足开发者需要等,现代计算机硬件和软件技术的飞速发展,为系统的建设提供了技术条件。由于对校园选课系统这一类的系统进行开发已有一定的时期,有很多成功的实例,技术基础也已经非常雄厚,因而技术上的准备应该不成问题。
(2)经济上的可行性
主要是对项目的经济效益进行评价,一方面是支出的费用,其中包括设备购置费,软件开发费,管理和维护费,人员工资和培训费等。一方面是效益,包括降低办公费用,提高办公室效率,为学校管理提供方便。由于选课系统是一个比较小型的系统,所以从人力、物力、财力方面来说都是可行的。
(3)管理上的可行性
主要是管理人员对开发信息系统是否支持,现有管理制度和方法是否科学,规章制度是否齐全,原始数据是否正确等,学籍管理系统比较完善的规章制度和管理方法为系统的建设提供了保障。
(4)社会可行性
社会可行性研究是对系统投入使用后对社会可能带来的影响进行分析,比如是否为人们所接受,是否为社会带来利益。
可行性分析的最后成果是可行性分析报告,可行性分析报告包括下列内容:
1、选课管理系统的总体目标及主要功能。
2、从经济,技术,管理,社会等方面论证方案的可行性。
经过对用户需求进行调查,做出了用户需求分析,从而确定了系统设计的几大模块以满足学校的实际要求。在可行性研究方面,主要从技术、经济、管理和社会四个角度对系统的可行性进行分析,并最终做出了可行性分析报告。
概念结构设计:
E-R 图
逻辑结构设计:
数据字典
主要涉及以下几个表,分别是:用户信息表、系别信息表、课程信息表、选课信息表。以下是数据字典
用户信息表:
字段 | 备注 |
---|---|
user_id | 用户号 |
user_name | 用户名 |
user_sex | 用户性别 |
user_age | 用户年龄 |
user_phone | 用户手机号 |
password | 密码 |
role | 用户角色(student/teacher) |
系别信息表:
字段 | 备注 |
---|---|
dept_id | 系号 |
dept_name | 系名 |
课程信息表:
字段 | 备注 |
---|---|
course_id | 课程号 |
course_name | 课程名 |
course_credit | 学分 |
spare_time | 课程余量 |
选课信息表:
字段 | 备注 |
---|---|
course_id | 课程号 |
user_id | 用户号 |
grade | 成绩 |
数据流程图
业务流程图
关系模型
根据转换规则,将E-R模型转换成关系模型
用户信息表 (学号, 姓名, 年龄, 性别, 系号) 主键: 学号, 外键: 系号
课程信息表 (课程号, 课程名, 学分, 课余量) 主键: 课程号
系别信息表 (系号, 系名) 主键: 系号
选课信息表 (学号, 课程号, 成绩) 主键: 学号和课程号(联合主键)
物理结构设计:
基本表
用户信息表:
列名 | 数据类型 | 允许空 | 主键 | 约束条件 |
---|---|---|---|---|
user_id | int(11) | 否 | 是 | 自增 |
user_name | char(30) | 否 | 否 | |
user_sex | int(1) | 是 | 否 | 0/1 默认0 |
user_age | int(2) | 是 | 否 | |
user_phone | int(11) | 否 | 否 | |
dept_id | int(11) | 否 | 否 | 外键 |
role | char(16) | 是 | 否 | 默认student |
password | char(16) | 是 | 否 | 默认123456 |
系别信息表:
列名 | 数据类型 | 允许空 | 主键 | 约束条件 |
---|---|---|---|---|
dept_id | int(11) | 否 | 是 | 自增 |
dept_name | char(30) | 否 | 否 |
课程信息表:
列名 | 数据类型 | 允许空 | 主键 | 约束条件 |
---|---|---|---|---|
course_id | int(11) | 否 | 是 | 自增 |
course_name | char(30) | 否 | 否 | |
course_credit | int(2) | 否 | 否 | |
spare_time | int(2) | 是 | 否 | 默认20 |
选课信息表:
列名 | 数据类型 | 允许空 | 主键 | 约束条件 |
---|---|---|---|---|
course_id | int(11) | 否 | 是 | |
user_id | int(11) | 否 | 否 | |
grade | int(3) | 否 | 否 | 0~100 |
索引
用户信息表的主索引列为: user_id
系别信息表的主索引列为: dept_id
课程信息表的主索引列为: course_id
选课信息表的主索引列为: (course_id,user_id)
视图
关系数据模型分析的结果,不同的用户看到的数据不一致,需要定义不同的用户视图,但考虑到数据库与前台开发程序的连接比较复杂,所以数据库没有单独定义用户视图,用有选择性select 语句代替不同的用户视图
创建数据库:
- 登录mysql:
mysql -u root -p
(root为账号名)root
(root为密码)
- 创建数据库
show databases;
查看所有数据库create database mysql_test;
(mysql_test为数据库名)
- 选择数据库
use mysql_test;
选择数据库
创建表:
用户信息表:
mysql> create table user(-> user_id int(11) not null auto_increment,-> user_name char(30) not null,-> user_sex int(1) null default 0,-> user_age int(2) null,-> user_phone char(11) not null,-> password char(16) null default '123456',-> dept_id int(11) not null,-> role char(16) null default 'student',-> primary key(user_id),-> FOREIGN KEY (`dept_id`) REFERENCES `dept` (`dept_id`)-> );
结果:
系别信息表:
mysql> create table dept(-> dept_id int(11) not null auto_increment,-> dept_name char(30) not null,-> primary key(dept_id),-> );
结果:
课程信息表:
mysql> create table course(-> course_id int(11) not null auto_increment,-> course_name char(30) not null,-> course_credit int(2) not null,-> spare_time int(2) null default 20-> primary key(course_id),-> );
结果:
选课信息表:
mysql> create table elective(-> course_id int(11) not null,-> user_id int(11) not null,-> grade int(3) not null,-> primary key(course_id,user_id),-> );
结果:
操作纪录:
用户表
// 联表查询用户列表
const USERLIST_SQL = `select user_id, user_name, user_sex, user_phone, user_age, user.dept_id, dept_name, role from user join dept on user.dept_id=dept.dept_id`
// 联表查询用户详情
const USERROLELIST_SQL = `select user_id, user_name, user_sex, user_phone, user_age, user.dept_id, dept_name, role from user join dept on user.dept_id=dept.dept_id where role=?`;
// 联表查询用户详情
const USERINFO_SQL = `select user_id, user_name, user_sex, user_phone, user_age, user.dept_id, role from user cross join dept on user.dept_id=dept.dept_id where user_id=?`;
// 添加用户
const USERADD_SQL = `insert into user set ?`;
// 修改用户
const USERUPDATE_SQL = `update user set user_name=?, user_sex=?, user_phone=?, user_age=?, dept_id=? where user_id=?`;
// 修改密码
const PASSWORDUPDATE_SQL = `update user set password=? where user_id=?`;
// 删除用户
const USERDELETE_SQL = `delete from user where user_id=?`;
查询系别表
// 查询系别列表SQL:
const DEPTLIST_SQL = `select * from dept`;
// 查询系别详情SQL:
const DEPTINFO_SQL = `select * from dept where dept_id=?`;
// 添加系别
const DEPTADD_SQL = `insert into dept set ?`;
// 修改系别
const DEPTUPDATE_SQL = `update dept set dept_name=? where dept_id=?`;
// 删除系别
const DEPTDELETE_SQL = `delete from dept where dept_id=?`;
课程表
// 查询教师课程列表
const COURSELIST_SQL = `select * from course`;
//查询教师课表详情
const COURSEINFO_SQL = `select * from course where course_id=?`;
// 联表综合查询学生课程列表
const ELECTIVEUSERID_SQL = `select course.course_id,course.course_name,course.course_credit,course.spare_time,case when course.course_id=elective.course_id and elective.user_id=? then 1 else 0 end as isElective from mysql_test.course left join mysql_test.elective on course.course_id=elective.course_id and elective.user_id=?;`;
// 联表综合查询学生课程详情
const ELECTIVEUSERIDINFO_SQL = `select course.course_id,course.course_name,course.course_credit,course.spare_time,case when course.course_id=elective.course_id and elective.user_id=? then 1 else 0 end as isElective from course,elective where course.course_id=? and course.course_id=elective.course_id and elective.user_id=?;`;
// 添加课程
const COURSEADD_SQL = `insert into course set ?`;
// 修改课程
const COURSEUPDATE_SQL = `update course set course_name=?, course_credit=? where course_id=?`;
// 修改课余量
const COURSESPARETIME_SQL = `update course set spare_time=? where course_id=?`;
// 删除课程
const COURSEDELETE_SQL = `delete from course where course_id=?`;
选课信息表
// 联表查询选课列表
const ELECTIVELIST_SQL = `select elective.user_id, elective.course_id, elective.grade, user.user_name, course.course_name from user,course,elective where elective.user_id=user.user_id and elective.course_id=course.course_id`;
// 联表查询用户选课详情
const ELECTIVEUSERLIST_SQL = `select elective.user_id, elective.course_id, elective.grade, user.user_name, course.course_name from user,course,elective where elective.user_id=user.user_id and elective.course_id=course.course_id and elective.user_id=?`;
// 选课详情
const ELECTIVEINFO_SQL = `select elective.user_id, elective.course_id, elective.grade, user.user_name, course.course_name from user,course,elective where elective.user_id=user.user_id and elective.course_id=course.course_id and elective.user_id=? and elective.course_id=?`;
// 添加选课
const ELECTIVEADD_SQL = `insert into elective set ?`;
// 修改成绩
const ELECTIVEUPDATE_SQL = `update elective set grade=? where user_id=? and course_id=?`;
// 删除选课
const ELECTIVEDELETE_SQL = `delete from elective where user_id=? and course_id=?`;
界面设计:
学生
数据库连接:
/*** 数据库连接* @param {*} sql 是sql语句* @param {*} values 是sql语句中的具体值* @returns */
const query = (sql, values) => {return new Promise((resolve, reject) => {//初始化连接池pools["data"].getConnection((err, connection) => {if (err) {console.log(err, "数据库连接失败");} else {console.log("数据库连接成功");//操作数据库connection.query(sql, values, (err, results) => {if (err) {reject(err);} else {connection.release();resolve({result: true,data: results,});}});}});});
};
功能实现:
整体功能实现代码量较多,在此处仅以选课模块功能进行展示
教师查询选课列表
/*** 获取选课列表* @url /elective/list*/
router.post("/list", async (ctx) => {const request = ctx.request.body;const { grade } = request;let res = {};if (grade) {res = JSON.parse(JSON.stringify(await query(ELECTIVEGRADE_SQL, [grade])));} else {res = JSON.parse(JSON.stringify(await query(ELECTIVELIST_SQL)));}if (res.result) {ctx.body = {status: 200,result: true,data: res.data,message: "获取成功",};} else {ctx.body = {status: 200,result: false,message: "获取失败",};}
});
学生查询选课列表
/*** 根据token获取选课列表* @url /elective/user/list*/
router.post("/user/list", async (ctx) => {const request = ctx.request.body;const user_id = ctx.request.header.token;let res = JSON.parse(JSON.stringify(await query(ELECTIVEUSERLIST_SQL, [user_id])));if (res.result) {ctx.body = {status: 200,result: true,data: res.data,message: "获取成功",};} else {ctx.body = {status: 200,result: false,message: "获取失败",};}
});
获取选课详情
/*** 获取选课详情* @url /elective/:user_id/:course_id/info*/
router.get("/:user_id/:course_id/info", async (ctx) => {const params = ctx.params;const { user_id, course_id } = params;const res = JSON.parse(JSON.stringify(await query(ELECTIVEINFO_SQL, [user_id, course_id])));if (res.result) {ctx.body = {status: 200,result: true,data: {...res.data[0],},message: "获取成功",};} else {ctx.body = {status: 200,result: false,message: "获取失败",};}
});
学生选课
/*** 添加选课* @url /elective/:course_id/info*/
router.post(`/:course_id/info`, async (ctx) => {const params = ctx.params;const user_id = ctx.request.header.token;const { course_id } = params;const data = JSON.parse(JSON.stringify(await query(ELECTIVEINFO_SQL, [user_id, course_id])));const queryData = {user_id,course_id,};if (data.result && data.data.length !== 0) {ctx.body = {status: 200,result: false,message: "已选课",};return;}const courseInfo = JSON.parse(JSON.stringify(await query(COURSEINFO_SQL, [course_id])));let item = courseInfo.data[0];if (item.spare_time == 0) {ctx.body = {status: 200,result: false,message: "课程余量不足",};return;}item.spare_time--;const course = await query(COURSESPARETIME_SQL, [item.spare_time, course_id]);const res = await query(ELECTIVEADD_SQL, queryData);if (res.result && course.result) {ctx.body = {status: 200,result: true,message: "选课成功",};} else {ctx.body = {status: 200,result: false,message: "选课失败",};}
});
录入成绩及修改成绩
/*** 修改成绩* @url /elective/:user_id/:course_id/info*/
router.put(`/:user_id/:course_id/info`, async (ctx) => {const request = ctx.request.body;const { user_id, course_id } = ctx.params;const { grade } = request;const queryData = [grade, user_id, course_id];const res = await query(ELECTIVEUPDATE_SQL, queryData);if (res.result) {ctx.body = {status: 200,result: true,message: "修改成功",};} else {ctx.body = {status: 200,result: false,message: "修改失败",};}
});
删除选课
/*** 删除选课* @url /elective/:user_id/:course_id/info*/
router.delete(`/:user_id/:course_id/info`, async (ctx) => {const { user_id, course_id } = ctx.params;if (course_id && user_id) {const res = await query(ELECTIVEDELETE_SQL, [user_id, course_id]);if (res.result) {ctx.body = {status: 200,result: true,message: "删除成功",};} else {ctx.body = {status: 200,result: false,message: "删除失败",};}}
});
功能测试:
登录验证功能测试
编号 | 测试内容 | 测试结果 |
---|---|---|
1 | 输入错误的用户名和密码,应提示"用户不存在" | 通过 |
2 | 输入正确的用户名和错误的密码,应提示"密码不正确" | 通过 |
3 | 不输入用户名和密码,应提示"请输入用户名/请输入密码" | 通过 |
4 | 输入学生用户名和密码,进入学生主页 | 通过 |
5 | 输入教师用户名和密码,进入教师主页 | 通过 |
修改密码功能测试
编号 | 测试内容 | 测试结果 |
---|---|---|
1 | 原密码/新密码/确认密码不填,提示请输入 | 通过 |
2 | 原密码输入错误,应提示"原密码不正确" | 通过 |
3 | 原密码和新密码输入一致,应提示"新密码不能与原密码一致" | 通过 |
4 | 新密码和确认密码不一致,应提示"两次输入不一致" | 通过 |
5 | 原密码/新密码/确认密码正确填写,应提示"修改成功,请重新登录" | 通过 |
用户管理功能测试
编号 | 测试内容 | 测试结果 |
---|---|---|
1 | 添加不存在的用户,应提示"添加成功" | 通过 |
2 | 添加存在的用户,应提示"用户已存在" | 通过 |
3 | 修改用户,应提示"修改成功" | 通过 |
4 | 删除用户,应提示"删除成功" | 通过 |
5 | 输入用户ID查询,结果为对应用户数据 | 通过 |
6 | 选择用户角色查询,结果为对应角色的用户数据 | 通过 |
课程管理功能测试
编号 | 测试内容 | 测试结果 |
---|---|---|
1 | 添加不存在的课程,应提示"添加成功" | 通过 |
2 | 添加存在的课程,应提示"课程已存在" | 通过 |
3 | 修改课程,应提示"修改成功" | 通过 |
4 | 删除课程,应提示"删除成功" | 通过 |
5 | 输入课程ID查询,结果为对应课程数据 | 通过 |
系别管理功能测试
编号 | 测试内容 | 测试结果 |
---|---|---|
1 | 添加不存在的系别,应提示"添加成功" | 通过 |
2 | 添加存在的系别,应提示"系别已存在" | 通过 |
3 | 修改系别,应提示"修改成功" | 通过 |
4 | 删除系别,应提示"删除成功" | 通过 |
5 | 输入系别ID查询,结果为对应系别数据 | 通过 |
选课管理功能测试
编号 | 测试内容 | 测试结果 |
---|---|---|
1 | 学生选课,应提示"选课成功" | 通过 |
2 | 录入选课成绩,应提示"录入成功" | 通过 |
3 | 修改选课成绩,应提示"修改成功" | 通过 |
4 | 删除选课,应提示"删除成功" | 通过 |
5 | 选择课程,结果为对应选课数据 | 通过 |
6 | 课余量为0时再选课,应提示"课程余量不足" | 通过 |
总结:
- 本系统是对选课系统的的简单实现,模拟了一个简单应用的开发生命周期,实现整个的开发流程可以更好体验项目开发思想,可以很大程度提升自身技术。
- 本系统web端采用的技术栈Vue+Element-UI,服务端采用的是Node.js+Koa2,数据库语言采用的是MySql。
- 对本项目有兴趣的同学可以移步仓库。
- 有兴趣的同学可以关注下前端小溪公众号
从选课系统看软件开发周期相关推荐
- 软件可用性测试mantis,学生选课系统-软件可用性测试实验.doc
学生选课系统-软件可用性测试实验 实验报告 课程名称:软件测试方法和技术 学生姓名: 学号: 院系:计算机 班级:1202 组别:1 任课教师:张建东 指导老师:张建东 目录 一.实验目的: 实验组成 ...
- 从奥运门票系统瘫痪到家乐福踩踏事件看软件设计中业务模型的处理
从奥运门票系统瘫痪到家乐福踩踏事件看软件设计中业务模型的处理 作者:郭方明 完成日期:2007-11-17 version 1.0 联系信箱:gfm.job@Gmail.com 注:转载文章,请注明作 ...
- Windows系统win10系统看图pdf阅读器软件推荐
描述:Windows系统win10系统看图pdf阅读器软件推荐 名称 : 看图王
- python实现复旦大学选课系统自动抢课神器抢课软件Courcegoblin抢课软件ver 1.0
朋友最近遇上选课困难,手速慢,总是抢不到心仪的课程,我目前正好找不到爬虫项目练手,于是写了个面向复旦选课系统的抢课小软件帮助朋友抢课 首先需要这些模块: import requests import ...
- 基于Java毕业设计学生选课系统源码+系统+mysql+lw文档+部署软件
基于Java毕业设计学生选课系统源码+系统+mysql+lw文档+部署软件 基于Java毕业设计学生选课系统源码+系统+mysql+lw文档+部署软件 本源码技术栈: 项目架构:B/S架构 开发语言: ...
- 用什么软件做选课系统好啊
菜鸟新到,希望大家给我一些帮助,本人不是专业的开发人员,但是无奈接到了给学员做选课系统的任务,现在正是开发调研阶段,请问大家用什么软件开发的好啊?
- 选课系统软件测试计划规划,职业生涯规划测评系统 测评软件
原标题:职业生涯规划测评系统 测评软件 职业生涯规划测评系统 测评软件 <职业生涯规划与评测系统>是由我单位联合北京师范大学.清华大学的多位心理学专家和职业规划专家,专门针对高中生的专业选 ...
- 采用ASP.NET使用C#.NET语言开发的在线学生选课系统(源码+数据库+论文)
随着在校大学生人数的不断增加,教务系统的数据量也不断的上涨.针对学生选课这一环节,本系统从学生网上自主选课以及教师的课程信息发布两个大方面进行了设计,基本实现了学生的在线信息查询.选课功能.教师添加课 ...
- (附源码)mysql+ssm学生选课系统 毕业设计 170920
摘 要 本论文主要论述了如何使用JAVA语言开发一个学生选课系统,本系统将严格按照软件开发流程进行各个阶段的工作,采用B/S架构,面向对象编程思想进行项目开发.在引言中,作者将论述学生选课系统的当前 ...
- jsp+sql的学生选课系统过程
本次课程的作品为"学生选课系统",选此课题初衷是毕竟自己作为一个学生来说最为贴近的就是学生选课系统,平常都是作为一个用户来使用这个系统,没有什么深入的了解其中的实现原理,所以抱着试 ...
最新文章
- tf.boolean_mask()的详细用法
- VS Resharper快捷键没了处理办法
- 35岁老程序员因身体原因没加班,老板:不想干就滚蛋
- 烙饼啊烙饼{转自ITEO
- nginx pdo_mysql_lnmp环境,安装PHP7的扩展pdo_mysql报错的问题?
- 数字化转型知识方法系列之:数字化转型的基本认识与参考架构
- 不同vlan通信(三层交换)
- Python要self的理由
- 查看jdk版本号和安装目录
- linux考勤机密码,一种基于Linux操作系统的考勤机的制作方法
- 手把手教你:微信小程序内嵌网页或H5页面
- Mac突然连接不上WiFi的问题
- html 自动排序表格,表格排序.html
- c语言实现alsa播放
- 算法之十大滤波算法详解
- 数据建模基础知识——实体关系图
- Ubuntu14.04使用Systemback进行系统克隆
- 2020 年 “联想杯”全国高校程序设计在线邀请赛暨第三届上海理工大学程序设计竞赛热身赛B. 回文串
- tinymce配置及功能实现详解
- vue+node---使用element框架实现的前后台用户登录注册功能
热门文章
- DroidCam通过数据线调用手机摄像头的方法一
- Raytrace学习的阶段性总结
- 图像切割之(五)活动轮廓模型之Snake模型简单介绍
- 计算机专业软考初级有用吗,软考:初级程序员考试有没有必要考?
- 7-5 游客检票 - 实验3 简单的计算及输入输出 -《Python编程基础及应用实验教程》(高等教育出版社)
- std::numeric_limits的一个使用注意事项
- 无线通信设备安装工程概预算编制_建筑安装工程,预算编制中易遗漏总结分享...
- win8 32位系统上如何运行校园翼讯客户端
- VNPY_IB API封装
- 网络安全--通过握手包破解WiFi(详细教程)