---恢复内容开始---
一、需求分析
1.题目要求
采用桌面应用程序模式,开发一个医院挂号系统,管理包括人员、号种及其挂号费用,挂号退号等信息,完成登录、挂号、查询和统计打印功能。数据库表如下所示,建立索引的目的是加速访问,请自行确定每个索引要涉及哪些字段。
T_KSXX (科室信息表)
字段名称
字段类型
主键
索引
可空
备注
KSBH
CHAR(6)
是
是
否
科室编号,数字
KSMC
CHAR(10)
否
否
否
科室名称
PYZS
CHAR(8)
否
否
否
科室名称的拼音字首
T_BRXX (病人信息表)
字段名称
字段类型
主键
索引
可空
备注
BRBH
CHAR(6)
是
是
否
病人编号,数字
BRMC
CHAR(10)
否
否
否
病人名称
DLKL
CHAR(8)
否
否
否
登录口令
YCJE
DECIMAL(10,2)
否
否
否
病人预存金额
DLRQ
DateTime
否
否
是
最后一次登录日期及时间
T_KSYS (科室医生表)
字段名称
字段类型
主键
索引
可空
备注
YSBH
CHAR(6)
是
是
否
医生编号,数字,第1索引
KSBH
CHAR(6)
否
是
否
所属科室编号,第2索引
YSMC
CHAR(10)
否
否
否
医生名称
PYZS
CHAR(4)
否
否
否
医生名称的拼音字首
DLKL
CHAR(8)
否
否
否
登录口令
SFZJ
BOOL
否
否
否
是否专家
DLRQ
DATETIME
否
否
是
最后一次登录日期及时间
T_HZXX (号种信息表)
字段名称
字段类型
主键
索引
可空
备注
HZBH
CHAR(6)
是
是
否
号种编号,数字,第1索引
HZMC
CHAR(12)
否
否
否
号种名称
PYZS
CHAR(4)
否
否
否
号种名称的拼音字首
KSBH
CHAR(6)
否
是
否
号种所属科室,第2索引
SFZJ
BOOL
否
否
否
是否专家号
GHRS
INT
否
否
否
每日限定的挂号人数
GHFY
DECIMAL(8,2)
否
否
否
挂号费
T_GHXX (挂号信息表)
字段名称
字段类型
主键
索引
可空
备注
GHBH
CHAR(6)
是
是
否
挂号的顺序编号,数字
HZBH
CHAR(6)
否
是
否
号种编号
YSBH
CHAR(6)
否
是
否
医生编号
BRBH
CHAR(6)
否
是
否
病人编号
GHRC
INT
否
是
否
该病人该号种的挂号人次
THBZ
BOOL
否
否
否
退号标志=true为已退号码
GHFY
DECIMAL(8,2)
否
否
否
病人的实际挂号费用
RQSJ
DATETIME
否
否
否
挂号日期时间
为了减少编程工作量,T_KSXX、T_BRXX、T_KSYS、T_HZXX的信息手工录入数据库,每个表至少录入6条记录,所有类型为CHAR(6)的字段数据从“000001”开始,连续编码且中间不得空缺。为病人开发的桌面应用程序要实现的主要功能具体如下:
(1)病人登录:输入自己的病人编号和密码,经验证无误后登录。
(2)病人挂号:病人处于登录状态,选择科室、号种和医生(非专家医生不得挂专家号,专家医生可以挂普通号);输入缴费金额,计算并显示找零金额后完成挂号。所得挂号的编号从系统竞争获得生成,挂号的顺序编号连续编码不得空缺。
功能(2)的界面如下所示,在光标停在“科室名称”输入栏时,可在输入栏下方弹出下拉列表框,显示所有科室的“科室编号”、“科室名称”和“拼音字首”,此时可通过鼠标点击或输入科室名称的拼音字首两种输入方式获得“科室编号”,用于插入T_GHXX表。注意,采用拼音字首输入时可同时完成下拉列表框的科室过滤,使得下拉列表框中符合条件的科室越来越少,例如,初始为“内一科”和“内二课”。其它输入栏,如“医生姓名”、“号种类别”、“号种名称”也可同时支持两种方式混合输入。
每种号种挂号限定当日人次,挂号人数超过规定数量不得挂号。一个数据一致的程序要保证:挂号总人数等于当日各号种的挂号人次之和,病人的账务应保证开支平衡。已退号码不得用于重新挂号,每个号重的GHRC数据应连续不间断,GHRC从1开始。若病人有预存金额则直接扣除挂号费,此时“交款金额”和“找零金额”处于灰色不可操作状态。
为医生开发的桌面应用程序要实现的主要功能具体如下:
(1)医生登录:输入自己的医生编号和密码,经验证无误后登录。
(2)病人列表:医生处于登录状态,显示自己的挂号病人列表,按照挂号编号升序排列。显示结果如下表所示。
挂号编号
病人名称
挂号日期时间
号种类别
000001
章紫衣
2018-12-30 11:52:26
专家号
000003
范冰冰
2018-12-30 11:53:26
普通号
000004
刘德华
2018-12-30 11:54:28
普通号
(3)收入列表:医生处于登录状态,显示所有科室不同医生不同号种起止日期内的收入合计,起始日期不输入时默认为当天零时开始,截止日期至当前时间为止。时间输入和显示结果如下表所示。
起始时间:2018-12-30 00:00:00截止时间:2018-12-30 12:20:00
科室名称
医生编号
医生名称
号种类别
挂号人次
收入合计
感染科
000001
李时珍
专家号
24
48
感染科
000001
李时珍
普通号
10
10
内一科
000002
扁鹊
普通号
23
23
保健科
000003
华佗
专家号
10
20
病人应用程序和医生应用程序可采用主窗口加菜单的方式实现。例如,医生应用程序有三个菜单项,分别为“病人列表”、“收入列表”和“退出系统”等。
考虑到客户端应用程序要在多台计算机上运行,而这些机器的时间各不相同,客户端程序每次在启动时需要同数据库服务器校准时间,可以建立一个时间服务程序或者直接取数据库时间校准。建议大家使用MS SQL数据库开发。
挂号时锁定票号可能导致死锁,为了防止死锁或系统响应变慢,建议大家不要锁死数据库表或者字段。程序编写完成后,同时启动两个挂号程序进行单步调试,以便测试两个病人是否会抢到同一个号、或者有号码不连续或丢号的现象。
系统考核目标:(1)挂号后数据库数据包括挂号时间不会出现不一致或时序颠倒现象,以及挂号人次超过该号种当日限定数量的问题;(2)挂号号码和挂号人次不会出现不连续或丢号问题;(3)病人的开支应平衡,并应和医院的收入平衡;(4)系统界面友好、操作简洁,能支持全键盘操作、全鼠标操作或者混合操作;(5)能支持下拉列表框过滤输入;(6)系统响应迅速,不会出现死锁;(7)统计报表应尽可能不采用多重或者多个循环实现;(8)若采用时间服务器程序校准时间,最好能采用心跳检测机制,显示客户端的上线和下线情况。
思考题:当病人晚上11:59:59秒取得某号种的挂号价格10元,当他确定保存时价格在第2天00:00:00已被调整为20元,在编程时如何保证挂号费用与当天价格相符?
2.需求分析
从要求可知,应该有一个登陆界面,医生和病人均可以用这个页面登陆。对信息进行检查以后,启动对应的医生界面或病人挂号界面,再做对应的业务。总的工作包括对数据库的查询,插入,更新等,以及对病人挂号的业务逻辑的实现,并医生的对已经挂号的病人信息进行查询,并对指定时间的所有科室医生对应的挂号信息进行统计等等。
一、系统设计
1.概要设计
介绍设计思路、原理。将一个复杂系统按功能进行模块划分、建立模块的层次结构及调用关系、确定模块间的接口及人机界面等。
要有总体结构、总体流程(图)。
系统总共分为三个大模块,登陆、医生、病人等。有三个界面,三个controller,一个main界面。总体流程图如下:
图2.1 总体流程图
医生界面
登陆完成后,根据医生信息显示对应的病人列表。根据时间统计出各个科室对应的医生挂号记录以及挂号人次总费用等信息。流程图如下:
图 2.2 医生查询流程图
登陆界面
系统启动后第一个启动的界面是登陆界面,对编辑框进行非空检查,用户选择身份并点击确认以后,信息和数据库信息进行匹配,匹配成功后,即可登录。如果,信息不匹配,则进行提示并清空编辑框,继续等待用户输入,默认身份是医生。流程图如下:
图 2.3 登录界面流程图
病人挂号界面
病人登录成功后,启动病人挂号界面。选择挂号科室后,医生编辑框对过滤信息进行重新检查,医生选择完毕后,根据医生是否专家来确定是否专家编辑框的信息,等待用户选择,根据以上信息,显示号种类别,点击确认挂号按钮以后,对病人卡里余额进行检查,如果挂号费用够用,则从卡里余额扣除费用,如果不够用,则要求用户输入交款金额,再重新对余额进行检查,如果够用,则把找零金额一起放回卡里余额。显示挂号号码,保证下一次挂号号码不能出现已经挂好了的号码,多个客户端必须连续等。流程图如下:
图 2.4 病人挂号界面流程图
1.详细设计
图形用户界面用JavaFx来实现,使用intellijIDEA编辑器编辑代码,图形界面用JavaFX Scene Builder 1.1来设计,设计完成后绑定对应控件的id,然后在controller里面定义对应的控件,并使用即可,具体实现如下:
1.登录模块
首先有一个全局的Stage,是总的舞台,其他的页面花在这个舞台上面。
1 public class FXMLTest extendsApplication {2 privateStage stage;3 private final double MINIMUM_WINDOW_WIDTH = 700.0;4 private final double MINIMUM_WINDOW_HEIGHT = 370.0;5 private static FXMLLoader myloader = null;6 publicString BR_name;7
8 @Override9 public void start(Stage primaryStage) throwsException {10
11 }12 public static voidmain(String[] args) {13 launch(args);14 }15
16 }
继承自Application,重写start方法,在main方法里面调用就好。
Start方法里面启动舞台stage:
1 @Override2 public void start(Stage primaryStage) throwsException {3 stage =primaryStage;4 stage.setTitle("登陆界面");5 stage.setMinWidth(MINIMUM_WINDOW_WIDTH);6 stage.setMinHeight(MINIMUM_WINDOW_HEIGHT);7 gotologin();8 stage.setResizable(false);9 stage.show();10 }
在gotologin()方法里面加载登录界面以及css样式文件:
public voidgotologin(){try{
LoginController login= (LoginController) replaceSceneContent("登陆界面","FXML_LOGIN.fxml","Login.css",MINIMUM_WINDOW_WIDTH,MINIMUM_WINDOW_HEIGHT,0);
login.setApp(this);
}catch(Exception ex) {
Logger.getLogger(FXMLTest.class.getName()).log(Level.SEVERE, null, ex);
}
}
为了提高开发效率,获取界面controller并加载到stage的部分功能统一用一个函数replaceSceneContent(),再把此application传入到controller,为了在界面控制类controller里面调用或者返回到总的application类,加载其他的页面。
1 private Initializable replaceSceneContent(String title,String fxml,String css,double width,double height,int type) throwsException {2 FXMLLoader loader = newFXMLLoader();3 InputStream in = FXMLTest.class.getResourceAsStream(fxml);4 loader.setBuilderFactory(newJavaFXBuilderFactory());5 loader.setLocation(FXMLTest.class.getResource(fxml));6 SplitPane Spage;7 AnchorPane Apage;8 if (type == 0) {9 Apage =(AnchorPane) loader.load(in);10 Scene scene = newScene(Apage, width, height);11 scene.getStylesheets().add(FXMLTest.class.getResource(css).toExternalForm());12 stage.setTitle(title);13 stage.setScene(scene);14 stage.sizeToScene();15 } else if (type == 1) {16 Spage =(SplitPane) loader.load(in);17 Scene scene = newScene(Spage, width, height);18 scene.getStylesheets().add(FXMLTest.class.getResource(css).toExternalForm());19 stage.setTitle(title);20 stage.setScene(scene);21 stage.sizeToScene();22 } else{23
24 }25 myloader =loader;26 return(Initializable) loader.getController();27 }
使用界面设计器实现的界面如下:
启动之后的界面如下:
显然,使用了css样式文件之后界面变得更精美。
当用户输入编号以及密码之后,选择登录身份,点击登录按钮即可登录。点击清楚按钮时,清楚输入框的内容。业务逻辑如下:第一步,获取输入框以及选择框的值。第二步,对输入框进行非空检查,符合以后,与数据库用户信息进行匹配并返回匹配结果。第三步,用户信息匹配则登录成功,加载对应的界面,并结束登录界面。否则,提示错误,并清空输入