程序员开发实例大全宝库

网站首页 > 编程文章 正文

适逢数据库大作业,借题发挥分享一下Flutter桌面程序实战~

zazugpt 2024-08-25 17:26:29 编程文章 16 ℃ 0 评论
欢迎大家关注我的微信公众号“IT工匠”获取更多资源(涉及算法、数据结构、java、深度学习、计算机网络、python、Android等互联网技术资料)。

废话

这两天没好好更新文章,原因是在写作业呜呜,终于写完了,今天总得发点什么吧,想了想不如就发这两天写的作业哈哈(这也就决定了这篇文章的结构有点偏课程性)。这个项目是一个Flutter和Mysql的结合体,主要涉及到的技术栈为Mysql在flutter项目中的应用、Flutter在桌面程序的应用,本来文中很多地方应该放动图,但是最近是非常时期,怕被xx,所以只能放静图,感兴趣的读者可以获取文末源码在自己的电脑上跑一下,保证可以爽到!

环境说明

Mysql+dart+flutter

系统介绍

本系统是一个“学生选课系统”,系统需要登录,登录用户分为管理员学生,二者的功能如下:

管理员

  1. 查看当前系统所有的课程
  2. 发布新的课程供学生选课
  3. 查看所有学生的选课情况

学生

  1. 查看当前的所有课程
  2. 对自己喜欢的课进行选课操作
  3. 查看自己已经中选的课程
  4. 退选自己已经中选的课程

系统设计

本系统分为两大部分:数据库图形界面

数据库

建立三个数据库表:学生表(Student)、课程表(Course)、学生选课表(Sc),每个表的结构如下:

学生表(Student)

课程表(Course)

选课表(Sc)

另外为了满足管理员对学生选课情况的管理,建立了视图AdminScView:

AdminScView

图形界面

图形界面的设计较为简单,主要涉及到:

  • 注册登录模块
  • 管理员管理课程模块
  • 管理员管理学生模块
  • 管理员管理学生选课模块
  • 学生选课模块
  • 学生退课模块

将数据库中的表项以ListView的形式展示出来即可。

系统实现

系统的实现也分两部分:数据库部分、图形界面部分。

数据库部分

数据库连接

数据库部分使用dart中的sqljocky插件进行orcle数据库的连接:

 static Future init() async {
 if (conn == null) {
 var s = ConnectionSettings(
 user: "root",
 password: "xie.159753.",
 host: "localhost",
 port: 3306,
 db: DataBaseConfigure.DatabaseName,
 );
 conn = await MySqlConnection.connect(s);
 }
 if (conn != null) {
 print('数据库连接成功');
 return true;
 } else {
 return false;
 }
 }

用户登录

用户登录的逻辑主要是从数据库中查询,看是否存在当前用户即密码是否正确:

 static logInStudent(String username, String passwd) async {
 StreamedResults results =
 await conn.execute("select Sno from student where Sname='$username';");
 try{
 User user = User(username,passwd,UserType.STUDENT,(await results.elementAt(0))[0]);
 return user;
 }catch(e){
 return null;
 }
 }

数据初始化

数据初始化主要是从数据库中的不同表格查询对应数据,然后将数据以list的形式返回:

初始化课程

 static initCourse() async {
 StreamedResults results =
 await conn.execute("select * from course order by Cno;");
 List<TableBean> courses = [];
 courses.add(TableBean(TableBeanName.COURSE, ["课程号", "课程名", "先修课程", "学分"]));
 results.forEach((Row row) {
 TableBean course = TableBean(
 TableBeanName.COURSE, [row[0], row[1], row[2], row[3].toString()]);
 courses.add(course);
 });
 return courses;
 }

初始化学生

static initStudent() async {
 StreamedResults results =
 await conn.execute("select * from Student order by Sno;");
 List<TableBean> students = [];
 students
 .add(TableBean(TableBeanName.STUDENT, ["学号", "姓名", "性别", "年龄", "系别"]));
 results.forEach((Row row) {
 TableBean student = TableBean(TableBeanName.STUDENT,
 [row[0], row[1], row[2], row[3].toString(), row[4]]);
 students.add(student);
 });
 return students;
 }

初始化选课管理数据

 static initStCourse(String sno) async {
 StreamedResults results = await conn.execute(
 "select course.Cno,course.Cname,course.Cpno,course.Ccredit from course,sc where sc.Cno=course.Cno and sc.Sno='$sno';");
 List<TableBean> courses = [];
 results.forEach((Row row) {
 TableBean course = TableBean(TableBeanName.STCOURSE,
 [row[0], row[1], row[2], row[3].toString(), "true"]);
 courses.add(course);
 });
 StreamedResults results1 = await conn.execute(
 " select * from course where Cno not in (select course.Cno from course,sc where sc.Cno=course.Cno and sc.Sno='$sno');");
 results1.forEach((Row row) {
 TableBean course = TableBean(TableBeanName.STCOURSE,
 [row[0], row[1], row[2], row[3].toString(), "false"]);
 courses.add(course);
 });
 return courses;
 }

初始化选课数据

 static initAdminSc() async {
 StreamedResults results =
 await conn.execute("select * from ${DataBaseConfigure.AdminScView};");
 List<TableBean> scViews = [];
 scViews.add(TableBean(
 TableBeanName.ADMINSC, ["学号", "姓名", "课程号", "课程名", "学分", "成绩"]));
 results.forEach((Row row) {
 TableBean scView = TableBean(TableBeanName.ADMINSC, [
 row[0],
 row[1],
 row[2],
 row[3],
 row[4].toString(),
 row[5].toString()
 ]);
 scViews.add(scView);
 });
 return scViews;
 }

初始化学生个人所选的课程

 static initMyCourses(String userName) async {
 StreamedResults results = await conn.execute(
 "select Cno,Cname,Ccredit,Grade from ${DataBaseConfigure.AdminScView} where Sname='$userName';");
 List<TableBean> myCourses = [];
 myCourses
 .add(TableBean(TableBeanName.MYCOURSES, ["课程号", "课程名", "学分", "成绩"]));
 results.forEach((Row row) {
 TableBean scView = TableBean(TableBeanName.MYCOURSES,
 [row[0], row[1], row[2].toString(), row[3].toString()]);
 myCourses.add(scView);
 });
 return myCourses;
 }

数据新增

管理员新增课程

static _insertCourse(TableBean course) async {
 /**
 * 查询的流程是:
 * 1. 查询表中是否已存在该课程,若已存在,抛出异常
 * 2. 查询课程数量,设置当前课程id,插入课程
 * 3. 返回当前course对象
 */
 StreamedResults results = await conn.execute(
 "insert into course values('${course[0]}','${course[1]}','${course[2]}',${course[3]});");
 if (results != null) {
 return true;
 } else {
 return false;
 }
 }

学生注册(新增)

static _insertStudent(TableBean student) async {
 /**
 * 查询的流程是:
 * 1. 查询表中是否已存在该课程,若已存在,抛出异常
 * 2. 查询课程数量,设置当前课程id,插入课程
 * 3. 返回当前course对象
 */
 StreamedResults results = await conn.execute(
 "insert into student values('${student[0]}','${student[1]}','${student[2]}',${student[3]},'${student[4]}');");
 if (results != null) {
 return true;
 } else {
 return false;
 }
 }

学生选课

 static Future selectCourse(String Sno, String Cno) async {
 conn.execute("insert into sc values('$Sno','$Cno',NULL);");
 }

数据删除

管理员删除课程

 static _deleteCourse(TableBean course) {
 conn.execute("delete from course where Cno='${course[0]}';");
 }

管理员将学生开除(删除)

static _deleteStudent(TableBean student) async {
 conn.execute("delete from student where Sno='${student[0]}';");
 }

学生退选课程

 static void cancelCourse(String userNo, String Cno) {
 conn.execute("delete from sc where Sno='$userNo' and Cno='$Cno';");
 }

数据更新

管理员更新课程信息

static _updateCourse(TableBean course) {
 conn.execute(
 "update course set Cname='${course[1]}',Cpno='${course[2]}',Ccredit=${course[3]} where Cno=${course[0]};");
 }

管理员更新学生信息

 static _updateStudent(TableBean student) {
 conn.execute(
 "update student set Sname='${student[1]}',Sdept='${student[2]}',Sage=${student[3]},Ssex='${student[4]}'where sno=${student[0]};");
 }

图形界面部分

图形界面较为简单,主要分为以下几个部分:

注册登录

注册登录部分比较简单,展示基本的输入框即按钮即可,核心代码如下:

 @override
 Widget build(BuildContext context) {
 // TODO: implement build
 return new Scaffold(
 key: _scaffoldKey,
 resizeToAvoidBottomPadding: false,
 body: new Stack(children: <Widget>[
 new GestureDetector(
 onTap: () {
 FocusScope.of(context).requestFocus(new FocusNode());
 },
 ),
 _buildLogInWidgets(),
 _buildProgress(),
 ]));
 }

列表展示

列表展示的主要功能是将查询到的数据以列表的形式展示出来,这里为了代码的重用性可以自定义ListView:

abstract class ListViewCallBack {
 onItemClick(TableBean item);
}
class TableListView extends StatefulWidget {
 final List<TableBean> datas;
 final ListViewCallBack listViewCallBack;
 TableListView(this.datas, this.listViewCallBack);
 @override
 State<StatefulWidget> createState() => _ListViewState();
}
class _ListViewState extends State<TableListView> {
 @override
 Widget build(BuildContext context) {
 List<TableItemWidget> tableItems = [];
 for (TableBean tableBean in widget.datas) {
 tableItems.add(TableItemWidget(tableBean));
 }
 return ListView.builder(
 itemCount: tableItems.length,
 itemBuilder: (BuildContext context, int index) {
 return GestureDetector(
 onTap: () => widget.listViewCallBack
 .onItemClick(widget.datas[index]),
 child: tableItems[index]);
 });
 }
}

系统评估

系统评估主要是对核心功能的测试,主要分为以下几个部分:

注册登录模块评估

管理员模块评估

课程管理模块评估

初始数据:

image-20190604231204585

新增课程”伟大的数据库”:

新增成功:

image-20190604232528591

查看课程详情:

将上图中的”网络”课程的先修课程改为6:

删除上图中的”网络“课程:

学生管理模块评估

初始界面:

新增学生:

新增成功:

查看单个学生的详细信息:

将上图中的学生姓名改为”测试修改”:

删除上图中的”测试修改”学生:

选课管理模块评估

初始页面:

查看具体的选课条目:

退出登陆

学生模块评估

查看课程模块

初始数据:

查看某个课程的具体信息:

选中该门课:

查看已选课程

初始数据:

查看具体课程信息:

源码

源码地址:https://github.com/DmrfCoder/DataBaseCourseDesgin

Tags:

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表