---恢复内容开始---
一、需求分析
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 extends Application { 2 private Stage 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 public String BR_name; 7 8 @Override 9 public void start(Stage primaryStage) throws Exception { 10 11 } 12 public static void main(String[] args) { 13 launch(args); 14 } 15 16 }
继承自Application,重写start方法,在main方法里面调用就好。
Start方法里面启动舞台stage:
1 @Override 2 public void start(Stage primaryStage) throws Exception { 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 void gotologin(){ 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) throws Exception { 2 FXMLLoader loader = new FXMLLoader(); 3 InputStream in = FXMLTest.class.getResourceAsStream(fxml); 4 loader.setBuilderFactory(new JavaFXBuilderFactory()); 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 = new Scene(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 = new Scene(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样式文件之后界面变得更精美。
当用户输入编号以及密码之后,选择登录身份,点击登录按钮即可登录。点击清楚按钮时,清楚输入框的内容。业务逻辑如下:第一步,获取输入框以及选择框的值。第二步,对输入框进行非空检查,符合以后,与数据库用户信息进行匹配并返回匹配结果。第三步,用户信息匹配则登录成功,加载对应的界面,并结束登录界面。否则,提示错误,并清空输入框,等待用户输入。具体实现算法如下:
首先绑定登录按钮所对应的函数:
@FXML public void LOGIN_M(ActionEvent event) { int type = choiceBox.getSelectionModel().getSelectedIndex(); application.userlogin(account.getText(), password.getText(),type); }
调用父类的userlogin方法:
1 public void userlogin(String account,String password,int type){ 2 if (type == 0) { 3 if (DataBaseUtil.checkDoctor(account, password)) { 4 //stage.setResizable(true); 5 gotoYSmain(); 6 String YsName = DataBaseUtil.getYSinfo(account); 7 setYsInfo(YsName,account); 8 } else { 9 Alert information = new Alert(Alert.AlertType.INFORMATION,"登陆失败!"); 10 information.setTitle("提示"); //设置标题,不设置默认标题为本地语言的information 11 information.setHeaderText("错误:"); //设置头标题,默认标题为本地语言的information 12 information.showAndWait(); //显示弹窗,同时后续代码等挂起 13 Button infor = new Button("确定"); 14 System.out.println("登陆失败!"); 15 } 16 } else { 17 if (DataBaseUtil.check_bingren(account, password)) { 18 //stage.setResizable(true); 19 gotomain(); 20 HashMap<String,Double> BRinfo = DataBaseUtil.getBRinfo(account); 21 Set set = BRinfo.keySet(); 22 String BrName = set.iterator().next().toString(); 23 Double BrYuCun = BRinfo.get(BrName); 24 setBrInfo(account,BrName,BrYuCun); 25 } else { 26 Alert information = new Alert(Alert.AlertType.INFORMATION,"登陆失败!"); 27 information.setTitle("提示"); //设置标题,不设置默认标题为本地语言的information 28 information.setHeaderText("错误:"); //设置头标题,默认标题为本地语言的information 29 Button infor = new Button("确定"); 30 information.showAndWait(); //显示弹窗,同时后续代码等挂起 31 System.out.println("登陆失败!"); 32 } 33 } 34 35 }
根据type值来确定登录者身份,并与数据库信息进行匹配。
1 /** 2 * 医生登陆检查 3 * @param account 4 * @param password 5 * @return 6 */ 7 public static boolean checkDoctor(String account, String password) { 8 boolean checkbool = false; 9 try { 10 Connection con = null; //定义一个MYSQL链接对象 11 Class.forName("com.mysql.jdbc.Driver").newInstance();//MYSQL驱动 12 con = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/java_yiyuan", "root", "root"); //链接本地MYSQL 13 Statement stmt; //创建声明 14 stmt = con.createStatement(); 15 16 String password_fromDb; 17 String selectSql = "select DLKL from t_ksys where YSBH='"+account+"'"; 18 ResultSet selectRes = stmt.executeQuery(selectSql); 19 if (selectRes.next()) { 20 password_fromDb = selectRes.getString("DLKL"); 21 if (password_fromDb.equals(password)) { 22 checkbool = true; 23 } 24 } 25 con.close(); 26 } catch (Exception e) { 27 System.out.print("医生登陆检查---checkDoctor----MYSQL ERROR:" + e.getMessage()); 28 } 29 return checkbool; 30 }
为了代码的简洁性,把数据库查询方法一律统一管理。
1 /** 2 * 病人登陆检查 3 * @param account 4 * @param password 5 * @return 6 */ 7 public static boolean check_bingren(String account, String password) { 8 boolean checkbool = false; 9 try { 10 Connection con = null; //定义一个MYSQL链接对象 11 Class.forName("com.mysql.jdbc.Driver").newInstance();//MYSQL驱动 12 con = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/java_yiyuan", "root", "root"); //链接本地MYSQL 13 Statement stmt; //创建声明 14 stmt = con.createStatement(); 15 16 String password_fromDb; 17 String selectSql = "SELECT DLKL FROM t_brxx where BRBH='"+account+"'"; 18 ResultSet selectRes = stmt.executeQuery(selectSql); 19 if (selectRes.next()) { 20 password_fromDb = selectRes.getString("DLKL"); 21 if (password_fromDb.equals(password)) { 22 checkbool = true; 23 } 24 } 25 con.close(); 26 } catch (Exception e) { 27 System.out.print("病人登陆检查----check_bingren----MYSQL ERROR:" + e.getMessage()); 28 } 29 return checkbool; 30 }
从上述代码可知,当用户信息匹配成功以后,界面需要重新加载,gotoYSmain()是加载医生界面,gotoMain()是加载病人挂号界面。
1. 病人挂号模块
挂号模块提供给病人进行挂号,业务逻辑简单,用户只需要选择科室、科室医生、号种类别以及使用余额或者交款的方式进行付费以后即可得到挂号号码。输入框有自动过滤输入内容的功能,当用户输入科室名称或名称的大写下拉框会过滤显示对应的内容,也可以点击后根据下拉框的值来选择科室。科室选择完毕后,该科室的医生姓名会实时从数据库查询后,等待用户选择或输入,同样有过滤功能。下一步选择号种类别,有专家号和普通号,是根据医生是否专家来确定号种类别,医生是专家时,可以选择专家和普通号,当医生非专家时,只能选择普通号,输入框的值会在用户选择了医生之后会实时查询数据库在显示。此时,号中名称会显示出来,等待用户点击确定按钮,进行非空检查以后,根据票价从用户的余额去扣费,如果余额足够,则扣费完成后显示挂号号码,否则要求用户输入交款金额,再进行挂号。
第一步,启动挂号界面:
1 public void gotomain(){ 2 try { 3 MainController main = (MainController) replaceSceneContent("医院挂号系统","FXML_MAIN.fxml","main.css",700,450,1); 4 main.setApp(this); 5 } catch (Exception ex) { 6 Logger.getLogger(FXMLTest.class.getName()).log(Level.SEVERE, null, ex); 7 } 8 }
在controller里面用到的数据类型有:
1 private HashMap<String, String> KSYSinfo = null; 2 HashMap<String, String> KSinfo = null; 3 HashMap<String, String> HZinfo = null; 4 private double BrYuCun = 0; 5 private String BRBH; 6 private FXMLTest application; 7 public String Text_KSMC;//科室名称 8 public String Text_KSYS;//科室医生 9 public String Text_HZLB;//号中类别
在initialize()方法里面对科室信息、医生信息以及病人余额等信息初始化,并对输入框的输入内容进行监听,当有变化时,进行数据更新:
1 @Override 2 public void initialize(URL url, ResourceBundle rb) { 3 4 /*科室信息获取*/ 5 KSinfo = DataBaseUtil.getKSinfo(); 6 Set set = KSinfo.keySet(); 7 Iterator iter = set.iterator(); 8 while (iter.hasNext()) { 9 String key = (String) iter.next(); 10 comboBox_KSMC.getItems().addAll(key); 11 } 12 13 comboBox_KSMC.setEditable(true); 14 comboBox_KSMC.setOnAction((Event ev) -> { 15 Text_KSMC = comboBox_KSMC.getEditor().getText().trim(); 16 17 System.out.println("医生名称combobox大小:" + comboBox_YSMC.getItems().size() + " "); 18 int size = comboBox_YSMC.getItems().size(); 19 for (int i = 0; i < size; i++) { 20 comboBox_YSMC.getItems().remove(0); 21 } 22 System.out.println("删除后 医生名称combobox大小:" + comboBox_YSMC.getItems().size() + " "); 23 setKSYScomboxInfo(); 24 System.out.println("重新加以后 医生名称combobox大小:" + comboBox_YSMC.getItems().size() + " "); 25 setHZMC(); 26 }); 27 new AutoCompleteComboBoxListener<ComboBox>(comboBox_KSMC); 28 29 /*医生信息获取*/ 30 KSYSinfo = DataBaseUtil.getKSYSinfo("all"); 31 Set set1 = KSYSinfo.keySet(); 32 Iterator iter1 = set1.iterator(); 33 while (iter1.hasNext()) { 34 String key = (String) iter1.next(); 35 comboBox_YSMC.getItems().addAll(key); 36 } 37 comboBox_YSMC.setEditable(true); 38 comboBox_YSMC.setOnAction((Event ev) -> { 39 Text_KSYS = comboBox_YSMC.getEditor().getText().trim(); 40 int size = comboBox_HZLB.getItems().size(); 41 for (int i = 0; i < size; i++) { 42 comboBox_HZLB.getItems().remove(0); 43 } 44 setHZLB_combo_Box(Text_KSYS); 45 progres_indct.setProgress(0); 46 TextField_JKJE.setEditable(true); 47 }); 48 new AutoCompleteComboBoxListener<ComboBox>(comboBox_YSMC); 49 50 comboBox_HZLB.getItems().addAll("普通号","专家号"); 51 comboBox_HZLB.setEditable(true); 52 //comboBox_HZLB.getSelectionModel().select(0); 53 comboBox_HZLB.setOnAction((Event ev) -> { 54 Text_HZLB = comboBox_HZLB.getEditor().getText().trim(); 55 setHZMC(); 56 }); 57 new AutoCompleteComboBoxListener<ComboBox>(comboBox_HZLB); 58 59 HZinfo = DataBaseUtil.getHZBHinfo(); 60 61 }
根据医生名称设置号种类别:
1 private void setHZLB_combo_Box(String KSYS) { 2 int isZJ = DataBaseUtil.isZJ(KSYS); 3 if (isZJ==1) { 4 comboBox_HZLB.getItems().addAll("专家号","普通号"); 5 } else { 6 comboBox_HZLB.getItems().addAll("普通号"); 7 } 8 }
设置医生信息下拉框的值:
1 private void setKSYScomboxInfo() { 2 KSYSinfo = DataBaseUtil.getKSYSinfo(KSinfo.get(Text_KSMC).trim()); 3 Set set1 = KSYSinfo.keySet(); 4 Iterator iter1 = set1.iterator(); 5 while (iter1.hasNext()) { 6 String key = (String) iter1.next(); 7 comboBox_YSMC.getItems().addAll(key); 8 } 9 }
当点击确定按钮时,进行非空检查以及查询扣费等:
1 @FXML 2 public void onGuaHaoStart() { 3 progres_indct.setProgress(0); 4 if (comboBox_KSMC.getEditor().getText().isEmpty()) { 5 Alert information = new Alert(Alert.AlertType.INFORMATION, "科室名称不能为空!"); 6 information.setTitle("提示"); //设置标题,不设置默认标题为本地语言的information 7 information.setHeaderText("错误:"); //设置头标题,默认标题为本地语言的information 8 Button infor = new Button("确定"); 9 information.showAndWait(); //显示弹窗,同时后续代码等挂起 10 } else if (comboBox_HZLB.getEditor().getText().isEmpty()) { 11 Alert information = new Alert(Alert.AlertType.INFORMATION, "号种类别不能为空!"); 12 information.setTitle("提示"); //设置标题,不设置默认标题为本地语言的information 13 information.setHeaderText("错误:"); //设置头标题,默认标题为本地语言的information 14 Button infor = new Button("确定"); 15 information.showAndWait(); //显示弹窗,同时后续代码等挂起 16 } else if (comboBox_YSMC.getEditor().getText().isEmpty()) { 17 Alert information = new Alert(Alert.AlertType.INFORMATION, "科室医生不能为空!"); 18 information.setTitle("提示"); //设置标题,不设置默认标题为本地语言的information 19 information.setHeaderText("错误:"); //设置头标题,默认标题为本地语言的information 20 Button infor = new Button("确定"); 21 information.showAndWait(); //显示弹窗,同时后续代码等挂起 22 } else { 23 int BhType = 1; 24 if (comboBox_HZLB.getEditor().getText().trim().equals("普通号")) { 25 BhType = 0; 26 } 27 TextField_YJJE.setText(String.valueOf(DataBaseUtil.getGHFY(Text_KSMC,BhType))); 28 System.out.println("余额位:"+BrYuCun+", valueOf(TextField_YJJE.getText()):"+Double.valueOf(TextField_YJJE.getText())); 29 if (BrYuCun < Double.valueOf(TextField_YJJE.getText())) { 30 //当病人预存不足时,请求输入缴款金额,再进行合法性检查,如果正确并够用就挂号。 31 if (TextField_JKJE.getText().isEmpty()) { 32 Alert information = new Alert(Alert.AlertType.INFORMATION, "您的余额不足,交款金额不能为空!"); 33 information.setTitle("提示"); //设置标题,不设置默认标题为本地语言的information 34 information.setHeaderText("错误:"); //设置头标题,默认标题为本地语言的information 35 Button infor = new Button("确定"); 36 information.showAndWait(); //显示弹窗,同时后续代码等挂起 37 TextField_JKJE.setFocusTraversable(true); 38 return; 39 } else if (isNumeric(TextField_JKJE.getText())) { 40 if (Double.valueOf(TextField_JKJE.getText()) < Double.valueOf(TextField_YJJE.getText())) { 41 Alert information = new Alert(Alert.AlertType.INFORMATION, "交款金额不足!"); 42 information.setTitle("提示"); //设置标题,不设置默认标题为本地语言的information 43 information.setHeaderText("错误:"); //设置头标题,默认标题为本地语言的information 44 Button infor = new Button("确定"); 45 information.showAndWait(); //显示弹窗,同时后续代码等挂起 46 TextField_JKJE.setFocusTraversable(true); 47 return; 48 } else { 49 TextField_JKJE.setEditable(false); 50 double AfterYuE = Double.valueOf(TextField_JKJE.getText()) - Double.valueOf(TextField_YJJE.getText()); 51 52 int returnFromDBC = DataBaseUtil.setBrYuE(BRBH, AfterYuE+BrYuCun); 53 if (returnFromDBC == 0) { 54 Alert information = new Alert(Alert.AlertType.INFORMATION, "挂号成功,更新卡余额失败!"); 55 information.setTitle("提示"); //设置标题,不设置默认标题为本地语言的information 56 information.setHeaderText("错误:"); //设置头标题,默认标题为本地语言的information 57 Button infor = new Button("确定"); 58 information.showAndWait(); //显示弹窗,同时后续代码等挂起 59 } 60 BrYuCun = BrYuCun + AfterYuE;//对应的更新本类中的余额变量 61 TextField_ZLJE.setText(""+BrYuCun); 62 63 for (int i = 1; i <= 50; i++) { 64 progres_indct.setProgress(((double)i)/50); 65 } 66 67 TextField_ZLJE.setText(BrYuCun + ""); 68 69 Date now= new Date(); 70 DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); 71 String dateTimeString = df.format(now); 72 System.out.println("000001 " + KSYSinfo.get(Text_KSYS) + " " + BRBH + " " + Double.valueOf(TextField_YJJE.getText()) + " " + dateTimeString); 73 74 String getGHBH = onGetTingGuaHao(KSYSinfo.get(Text_KSYS), BRBH, Double.valueOf(TextField_YJJE.getText()), dateTimeString); 75 76 TextField_GHHM.setText(""+getGHBH); 77 78 if (BrYuCun > Double.valueOf(TextField_YJJE.getText())) { 79 TextField_JKJE.setText("有余额,无需交款!"); 80 } else { 81 TextField_JKJE.setText(null); 82 } 83 84 return; 85 } 86 } else { 87 Alert information = new Alert(Alert.AlertType.INFORMATION, "您的余额不足,请输入交款金额!"); 88 information.setTitle("提示"); //设置标题,不设置默认标题为本地语言的information 89 information.setHeaderText("错误:"); //设置头标题,默认标题为本地语言的information 90 Button infor = new Button("确定"); 91 information.showAndWait(); //显示弹窗,同时后续代码等挂起 92 TextField_JKJE.setFocusTraversable(true); 93 TextField_JKJE.setEditable(true); 94 TextField_JKJE.setText(""); 95 return; 96 } 97 98 } else { 99 TextField_JKJE.setEditable(false); 100 TextField_JKJE.setText("有余额,无需交款!"); 101 102 setTextField_GHHM(); 103 } 104 } 105 }
用到的一些小的工具方法:
1 public void setTextField_GHHM() { 2 3 double AfterYuE = BrYuCun - Double.valueOf(TextField_YJJE.getText()); 4 int returnFromDBC = DataBaseUtil.setBrYuE(BRBH, AfterYuE); 5 if (returnFromDBC == 0) { 6 Alert information = new Alert(Alert.AlertType.INFORMATION, "扣除余额失败,请重试!"); 7 information.setTitle("提示"); //设置标题,不设置默认标题为本地语言的information 8 information.setHeaderText("错误:"); //设置头标题,默认标题为本地语言的information 9 Button infor = new Button("确定"); 10 information.showAndWait(); //显示弹窗,同时后续代码等挂起 11 } 12 BrYuCun = AfterYuE; 13 System.out.println("剩下的余额为:" + AfterYuE + ",数据库返回:"+returnFromDBC); 14 15 16 for (int i = 1; i <= 50; i++) { 17 progres_indct.setProgress(((double)i)/50); 18 } 19 20 TextField_ZLJE.setText(BrYuCun + ""); 21 22 Date now= new Date(); 23 DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); 24 String dateTimeString = df.format(now); 25 System.out.println("000001 " + KSYSinfo.get(Text_KSYS) + " " + BRBH + " " + Double.valueOf(TextField_YJJE.getText()) + " " + dateTimeString); 26 27 String getGHBH = onGetTingGuaHao(KSYSinfo.get(Text_KSYS), BRBH, Double.valueOf(TextField_YJJE.getText()), dateTimeString); 28 29 TextField_GHHM.setText(""+getGHBH); 30 } 31 32 public String onGetTingGuaHao(String YSBH, String BRBH, double GHFY, String RQSJ) { 33 String HZBH = ""; 34 Set set2 = HZinfo.keySet(); 35 Iterator iter2 = set2.iterator(); 36 while (iter2.hasNext()) { 37 String key = (String) iter2.next(); 38 if (key.contains(Text_KSMC.trim()) && key.contains(Text_HZLB.trim())) { 39 HZBH = HZinfo.get(key.trim()); 40 break; 41 } 42 } 43 44 String GHBH = "0"; 45 GHBH = DataBaseUtil.getGuaHao(HZBH,YSBH,BRBH,GHFY,RQSJ); 46 return GHBH; 47 } 48 49 public static boolean isNumeric(String str){ 50 Pattern pattern = Pattern.compile("[0-9]*"); 51 return pattern.matcher(str).matches(); 52 } 53 54 @FXML 55 public void ClearAll() { 56 TextField_JKJE.setEditable(true); 57 comboBox_KSMC.getSelectionModel().clearSelection(); 58 comboBox_HZLB.getSelectionModel().clearSelection(); 59 comboBox_YSMC.getSelectionModel().clearSelection(); 60 TextField_HZMC.setText(null); 61 TextField_JKJE.setText(null); 62 TextField_YJJE.setText(null); 63 //TextField_ZLJE.setText(null); 64 TextField_GHHM.setText(null); 65 progres_indct.setProgress(0); 66 } 67 68 public void setHZMC() { 69 TextField_HZMC.setText(Text_KSMC+" "+Text_HZLB); 70 progres_indct.setProgress(0); 71 TextField_JKJE.setEditable(true); 72 } 73 74 public void setBRinfo(String userName) { 75 label_user_name.setText(userName + " 您好!"); 76 TextField_ZLJE.setText("" + BrYuCun); 77 }
病人登陆成功之后,获取名称以及预存金额,利用HASHMAP来保存得到的数据,方便处理:
1 /** 2 * 病人登陆成功之后,获取名称以及预存金额 3 * @param BRBH 4 * @return 5 */ 6 public static HashMap<String, Double> getBRinfo(String BRBH) { 7 HashMap<String, Double> BrName = new HashMap<>(); 8 try { 9 Connection con = null; //定义一个MYSQL链接对象 10 Class.forName("com.mysql.jdbc.Driver").newInstance();//MYSQL驱动 11 con = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/java_yiyuan", "root", "root"); //链接本地MYSQL 12 Statement stmt; //创建声明 13 stmt = con.createStatement(); 14 15 String selectSql = "SELECT BRMC,YCJE FROM t_brxx where BRBH='"+BRBH+"'"; 16 ResultSet selectRes = stmt.executeQuery(selectSql); 17 18 if (selectRes.next()) { 19 double BrYuCun_fromDb = selectRes.getDouble("YCJE"); 20 BrName.put(selectRes.getString("BRMC"), BrYuCun_fromDb); 21 return BrName; 22 } 23 con.close(); 24 } catch (Exception e) { 25 System.out.print("病人登陆成功之后,获取名称以及预存金额----getBRinfo----MYSQL ERROR:" + e.getMessage()); 26 } 27 return BrName; 28 }
扣病人余额:
1 /** 2 * 扣病人余额 3 * @param BRBH 4 * @param AfterYuE 5 * @return 6 */ 7 public static int setBrYuE(String BRBH, double AfterYuE) { 8 9 try { 10 Connection con = null; //定义一个MYSQL链接对象 11 Class.forName("com.mysql.jdbc.Driver").newInstance();//MYSQL驱动 12 con = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/java_yiyuan", "root", "root"); //链接本地MYSQL 13 Statement stmt; //创建声明 14 stmt = con.createStatement(); 15 16 String userBianHao_fromDb; 17 18 String selectSql = "SELECT * FROM t_brxx where BRBH='"+BRBH+"'"; 19 ResultSet selectRes = stmt.executeQuery(selectSql); 20 21 if (selectRes.next()) { 22 String updateSql = "UPDATE t_brxx set YCJE = " + AfterYuE + " where BRBH = '" + BRBH + "'"; 23 int i = stmt.executeUpdate(updateSql); 24 return i; 25 } 26 con.close(); 27 } catch (Exception e) { 28 System.out.print("扣病人余额---setBrYuE---MYSQL ERROR:" + e.getMessage()); 29 } 30 return 0; 31 }
获取科室信息:
1 public static HashMap<String, String> getKSinfo() { 2 HashMap<String, String> KsName = new HashMap<>(); 3 //ArrayList<String> KsName = new ArrayList<>(); 4 try { 5 Connection con = null; //定义一个MYSQL链接对象 6 Class.forName("com.mysql.jdbc.Driver").newInstance();//MYSQL驱动 7 con = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/java_yiyuan", "root", "root"); //链接本地MYSQL 8 Statement stmt; //创建声明 9 stmt = con.createStatement(); 10 11 String PYZS_fromDb, KSMC_fromDb, KSBH_fromDb; 12 13 String selectSql = "SELECT * FROM t_ksxx"; 14 ResultSet selectRes = stmt.executeQuery(selectSql); 15 16 while (selectRes.next()) { //循环输出结果集 17 PYZS_fromDb = selectRes.getString("PYZS"); 18 KSMC_fromDb = selectRes.getString("KSMC"); 19 KSBH_fromDb = selectRes.getString("KSBH"); 20 if (!PYZS_fromDb.isEmpty()) { 21 KsName.put(PYZS_fromDb, KSBH_fromDb); 22 } 23 24 if (!KSMC_fromDb.isEmpty()) { 25 KsName.put(KSMC_fromDb, KSBH_fromDb); 26 } 27 System.out.println(PYZS_fromDb + KSMC_fromDb); 28 } 29 con.close(); 30 } catch (Exception e) { 31 System.out.print("MYSQL ERROR:" + e.getMessage()); 32 } 33 return KsName; 34 }
获取科室医生信息:
1 public static HashMap<String, String> getKSYSinfo(String KSBH) { 2 HashMap<String, String> KsYsName = new HashMap<>(); 3 try { 4 Connection con = null; //定义一个MYSQL链接对象 5 Class.forName("com.mysql.jdbc.Driver").newInstance();//MYSQL驱动 6 con = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/java_yiyuan", "root", "root"); //链接本地MYSQL 7 Statement stmt; //创建声明 8 stmt = con.createStatement(); 9 10 String YSMC_fromDb, PYZS_fromDb, YSBH_fromDb; 11 12 String selectSql; 13 if (KSBH.equals("all")) { 14 selectSql = "SELECT * FROM t_ksys"; 15 } else { 16 selectSql = "SELECT * FROM t_ksys WHERE KSBH = '"+KSBH+"'"; 17 } 18 19 ResultSet selectRes = stmt.executeQuery(selectSql); 20 21 System.out.println("医生名称输出: "); 22 23 while (selectRes.next()) { //循环输出结果集 24 25 YSMC_fromDb = selectRes.getString("YSMC"); 26 PYZS_fromDb = selectRes.getString("PYZS"); 27 YSBH_fromDb = selectRes.getString("YSBH"); 28 if (!YSMC_fromDb.isEmpty()) { 29 KsYsName.put(YSMC_fromDb.trim(), YSBH_fromDb); 30 } 31 32 if (!PYZS_fromDb.isEmpty()) { 33 KsYsName.put(PYZS_fromDb.trim(), YSBH_fromDb); 34 } 35 System.out.println(YSMC_fromDb.trim() + " " + PYZS_fromDb); 36 } 37 System.out.println("医生名称输出完毕 "); 38 con.close(); 39 } catch (Exception e) { 40 System.out.print("MYSQL ERROR:" + e.getMessage()); 41 } 42 return KsYsName; 43 }
根据号种获取票价:
1 public static double getGHFY(String HZMC, int SFZJ) { 2 try { 3 Connection con = null; //定义一个MYSQL链接对象 4 Class.forName("com.mysql.jdbc.Driver").newInstance();//MYSQL驱动 5 con = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/java_yiyuan", "root", "root"); //链接本地MYSQL 6 Statement stmt; //创建声明 7 stmt = con.createStatement(); 8 9 boolean sfzj_fromDb; 10 String HZMC_fromDb; 11 String PYZS_fromDb; 12 13 String selectSql = "SELECT * FROM t_hzxx"; 14 ResultSet selectRes = stmt.executeQuery(selectSql); 15 16 while (selectRes.next()) { //循环输出结果集 17 sfzj_fromDb = selectRes.getBoolean("SFZJ"); 18 HZMC_fromDb = selectRes.getString("HZMC"); 19 PYZS_fromDb = selectRes.getString("PYZS"); 20 double GHFY_fromDb = selectRes.getDouble("GHFY"); 21 22 System.out.println(String.valueOf(SFZJ) + sfzj_fromDb + HZMC_fromDb + GHFY_fromDb); 23 24 if (HZMC_fromDb.startsWith(HZMC) || PYZS_fromDb.startsWith(HZMC)) { 25 if (SFZJ == 1 && sfzj_fromDb) { 26 return GHFY_fromDb; 27 } else if (SFZJ == 0 && !sfzj_fromDb) { 28 return GHFY_fromDb; 29 } 30 } 31 32 } 33 con.close(); 34 } catch (Exception e) { 35 System.out.print("MYSQL ERROR:" + e.getMessage()); 36 } 37 38 return 0; 39 }
开始挂号,根据数据库当前最新的挂号号码计算新的号码并返回:
1 public static String getGuaHao(String hzbh, String ysbh, String brbh, double ghfy, String rqsj) { 2 String GHBH = "0"; 3 4 try { 5 Connection con = null; //定义一个MYSQL链接对象 6 Class.forName("com.mysql.jdbc.Driver").newInstance();//MYSQL驱动 7 con = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/java_yiyuan", "root", "root"); //链接本地MYSQL 8 Statement stmt; //创建声明 9 stmt = con.createStatement(); 10 11 boolean sfzj_fromDb; 12 String GHBH_fromDb, HZBH_fromDb,GHRC_fromDb; 13 int Current_GHBH = 1, Current_GHRC = 1; 14 15 String selectSql = "SELECT * FROM t_ghxx"; 16 ResultSet selectRes = stmt.executeQuery(selectSql); 17 ResultSet selectRes_1 = selectRes; 18 19 while (selectRes.next()) { //循环输出结果集 20 GHBH_fromDb = selectRes.getString("GHBH"); 21 HZBH_fromDb = selectRes.getString("HZBH"); 22 GHRC_fromDb = selectRes.getString("GHRC"); 23 if (Integer.parseInt(GHBH_fromDb) > Current_GHBH) { 24 Current_GHBH = Integer.parseInt(GHBH_fromDb); 25 } 26 if (HZBH_fromDb.equals(hzbh)) { 27 if (Integer.parseInt(GHRC_fromDb) > Current_GHRC) { 28 Current_GHRC = Integer.parseInt(GHRC_fromDb); 29 } 30 } 31 } 32 33 Current_GHRC++; 34 Current_GHBH++; 35 36 int GHRC = 5; 37 int THBZ = 1; 38 System.out.println("时间:" + rqsj + "挂号费用:" + ghfy); 39 String updateSql = "INSERT INTO t_ghxx (GHBH,HZBH,YSBH,BRBH,GHRC,THBZ,GHFY,RQSJ) VALUES('" + String.format("%06d", Current_GHBH) + "','" + hzbh + "','" + ysbh + "','" + brbh + "','" + Current_GHRC + "'," + 40 "'" + THBZ + "','" + ghfy + "','" + rqsj + "')"; 41 int i = stmt.executeUpdate(updateSql); 42 if (i != 0) { 43 GHBH = String.format("%06d", Current_GHBH); 44 } 45 con.close(); 46 } catch (Exception e) { 47 System.out.print("MYSQL ERROR:" + e.getMessage()); 48 } 49 50 return GHBH; 51 }
根据号种名称获取号种编号:
1 public static HashMap<String, String> getHZBHinfo() { 2 HashMap<String, String> HzInfo = new HashMap<>(); 3 try { 4 Connection con = null; //定义一个MYSQL链接对象 5 Class.forName("com.mysql.jdbc.Driver").newInstance();//MYSQL驱动 6 con = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/java_yiyuan", "root", "root"); //链接本地MYSQL 7 Statement stmt; //创建声明 8 stmt = con.createStatement(); 9 10 String HZMC_fromDb, PYZS_fromDb, HZBH_fromDb; 11 12 String selectSql = "SELECT * FROM t_hzxx"; 13 ResultSet selectRes = stmt.executeQuery(selectSql); 14 15 while (selectRes.next()) { //循环输出结果集 16 HZMC_fromDb = selectRes.getString("HZMC"); 17 PYZS_fromDb = selectRes.getString("PYZS"); 18 HZBH_fromDb = selectRes.getString("HZBH"); 19 if (!HZMC_fromDb.isEmpty()) { 20 HzInfo.put(HZMC_fromDb, HZBH_fromDb); 21 } 22 23 if (!PYZS_fromDb.isEmpty()) { 24 HzInfo.put(PYZS_fromDb, HZBH_fromDb); 25 } 26 } 27 con.close(); 28 } catch (Exception e) { 29 System.out.print("MYSQL ERROR:" + e.getMessage()); 30 } 31 return HzInfo; 32 }
判断医生是否专家:
1 public static int isZJ(String ksys) { 2 3 int isZJ = 0; 4 5 try { 6 Connection con = null; //定义一个MYSQL链接对象 7 Class.forName("com.mysql.jdbc.Driver").newInstance();//MYSQL驱动 8 con = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/java_yiyuan", "root", "root"); //链接本地MYSQL 9 Statement stmt; //创建声明 10 stmt = con.createStatement(); 11 12 String selectSql = "SELECT SFZJ FROM t_ksys where YSMC='" + ksys + "' OR PYZS='" + ksys + "'"; 13 ResultSet selectRes = stmt.executeQuery(selectSql); 14 15 if (selectRes.next()) { 16 isZJ = selectRes.getInt("SFZJ"); 17 return isZJ; 18 } 19 con.close(); 20 } catch (Exception e) { 21 System.out.print("MYSQL ERROR:" + e.getMessage()); 22 } 23 24 return 0; 25 }
最后挂号成功,并显示挂号号码,界面如下:
3. 医生界面
当医生通过登录界面登录成功后,界面会跳转到医生查询界面。
1 public void gotoYSmain(){ 2 try { 3 YiShengController main = (YiShengController) replaceSceneContent("医生治疗系统","FXML_YISHENG.fxml","main.css",700,450,0); 4 main.setApp(this); 5 } catch (Exception ex) { 6 Logger.getLogger(FXMLTest.class.getName()).log(Level.SEVERE, null, ex); 7 } 8 }
需要输出该医生所下的病人的信息以及所有科室医生指定时间内的收入列表统计,因此,需要两个表格来处理数据。医生界面控制器controller的变量如下:
private String YSBH_in_Controller; private ObservableList<BrColumn> data = FXCollections.observableArrayList(); private ObservableList<SrColumn> Srdata = FXCollections.observableArrayList(); private FXMLTest application; @FXML TableColumn GHBH_1,BRMC_1,GhTime_1,HzType_1; @FXML TableColumn KSMC_2,YSBH_2,YSMC_2,HZLB_2,GHRC_2,SRHJ_2; @FXML TableView<BrColumn> BrTableView; @FXML TableView<SrColumn> SrTableView; @FXML private Label label_user_name;
为了获取医生需要查询的时间,用两个DatePicer来实现年月日的获取,时钟和分钟的获取使用两个combox设置0~23,0~59来实现。在界面初始化时,进行手动初始化:
1 @Override 2 public void initialize(URL location, ResourceBundle resources) { 3 DatePicer_start.setValue(LocalDate.now()); 4 DatePicer_end.setValue(DatePicer_start.getValue().plusDays(1)); 5 6 for (int i = 0; i < 24; i++) { 7 ComboBox_S_1.getItems().addAll(i + " 点"); 8 ComboBox_E_1.getItems().addAll(i + " 点"); 9 } 10 ComboBox_S_1.getSelectionModel().select(0); 11 ComboBox_E_1.getSelectionModel().select(0); 12 13 for (int i = 0; i < 60; i++) { 14 ComboBox_S_2.getItems().addAll(i + " 分"); 15 ComboBox_E_2.getItems().addAll(i + " 分"); 16 } 17 ComboBox_S_2.getSelectionModel().select(0); 18 ComboBox_E_2.getSelectionModel().select(0); 19 20 21 }
当医生界面加载完成的同时,病人列表会自动加载到表格里面,当点击刷新按钮时,会更新病人列表:
1 @FXML 2 public void setTableData() { 3 GHBH_1.setCellValueFactory(new PropertyValueFactory("GHBH")); 4 BRMC_1.setCellValueFactory(new PropertyValueFactory("BRMC")); 5 GhTime_1.setCellValueFactory(new PropertyValueFactory("GHTime")); 6 HzType_1.setCellValueFactory(new PropertyValueFactory("HZLB")); 7 data = DataBaseUtil.getBrLieBiao(YSBH_in_Controller); 8 BrTableView.setItems(data); 9 }
获取病人列表使用的是ObservableList,从数据库获取该医生对应数据的代码如下:
1 /** 2 * 获取医生:YSBH 下对应的病人列表 3 * @param YSBH 4 * @return 5 */ 6 public static ObservableList<BrColumn> getBrLieBiao(String YSBH) { 7 final ObservableList<BrColumn> data = FXCollections.observableArrayList(); 8 String YsName = null; 9 try { 10 Connection con = null; //定义一个MYSQL链接对象 11 Class.forName("com.mysql.jdbc.Driver").newInstance();//MYSQL驱动 12 con = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/java_yiyuan", "root", "root"); //链接本地MYSQL 13 Statement stmt, stmt1, stmt2; //创建声明 14 stmt = con.createStatement(); 15 stmt1 = con.createStatement(); 16 stmt2 = con.createStatement(); 17 18 String userBianHao_fromDb; 19 String GHBH = null, HZBH = null, BRBH = null, RQSJ = null; 20 Boolean SFZJ = null; 21 String BRMC = null; 22 23 String selectSql1, selectSql2; 24 ResultSet selectRes1, selectRes2; 25 26 String selectSql = "SELECT * FROM t_ghxx where YSBH='" + YSBH + "'"; 27 ResultSet selectRes = stmt.executeQuery(selectSql); 28 29 while (selectRes.next()) { //循环输出结果集 30 GHBH = selectRes.getString("GHBH"); 31 HZBH = selectRes.getString("HZBH"); 32 BRBH = selectRes.getString("BRBH"); 33 RQSJ = selectRes.getString("RQSJ"); 34 35 //HZBH 36 selectSql1 = "SELECT * FROM t_hzxx"; 37 selectRes1 = stmt1.executeQuery(selectSql1); 38 String HZBH_from_db = null; 39 while (selectRes1.next()) { //循环输出结果集 40 HZBH_from_db = selectRes1.getString("HZBH"); 41 if (HZBH_from_db.equals(HZBH)) { 42 SFZJ = selectRes1.getBoolean("SFZJ"); 43 break; 44 } 45 } 46 47 //BRBH 48 selectSql2 = "SELECT * FROM t_brxx"; 49 selectRes2 = stmt2.executeQuery(selectSql2); 50 String BRBH_from_db = null; 51 while (selectRes2.next()) { //循环输出结果集 52 BRBH_from_db = selectRes2.getString("BRBH"); 53 if (BRBH_from_db.equals(BRBH)) { 54 BRMC = selectRes2.getString("BRMC"); 55 break; 56 } 57 } 58 data.addAll(new BrColumn(GHBH, BRMC, RQSJ, SFZJ ? "普通号" : "专家号")); 59 } 60 61 con.close(); 62 } catch (Exception e) { 63 System.out.print("MYSQL ERROR:" + e.getMessage()); 64 } 65 return data; 66 }
ObservableList需要适配器来实现数据的显示,需要一个类:
1 package sample; 2 public class BrColumn { 3 private String GHBH; 4 private String BRMC; 5 private String GHTime; 6 private String HZLB; 7 8 public BrColumn(String GHBH, String BRMC,String GHTime,String HZLB) { 9 this.GHBH = GHBH; 10 this.BRMC = BRMC; 11 this.GHTime = GHTime; 12 this.HZLB = HZLB; 13 } 14 15 //get 16 public String getGHBH() { 17 return GHBH; 18 } 19 20 public String getBRMC() { 21 return BRMC; 22 } 23 24 public String getGHTime() { 25 return GHTime; 26 } 27 28 public String getHZLB() { 29 return HZLB; 30 } 31 32 //set 33 public void setGHBH(String GHBH) { 34 this.GHBH = GHBH; 35 } 36 37 public void setBRMC(String BRMC) { 38 this.GHBH = BRMC; 39 } 40 41 public void setGHTime(String GHTime) { 42 this.GHBH = GHTime; 43 } 44 45 public void setHZLB(String HZLB) { 46 this.GHBH = HZLB; 47 } 48 }
收入列表根据用户选择的时间来查询:
1 @FXML 2 public void startCalculate() { 3 int S_1 = Integer.parseInt(ComboBox_S_1.getSelectionModel().getSelectedItem().toString().replace("点", "").replace("分", "").trim()); 4 int S_2 = Integer.parseInt(ComboBox_S_2.getSelectionModel().getSelectedItem().toString().replace("点", "").replace("分", "").trim()); 5 int E_1 = Integer.parseInt(ComboBox_E_1.getSelectionModel().getSelectedItem().toString().replace("点", "").replace("分", "").trim()); 6 int E_2 = Integer.parseInt(ComboBox_E_2.getSelectionModel().getSelectedItem().toString().replace("点", "").replace("分", "").trim()); 7 String startTime = DatePicer_start.getValue().toString() + " " + String.format("%02d", S_1) + ":" + String.format("%02d", S_2) + ":00"; 8 String endTime = DatePicer_end.getValue().toString() + " " + String.format("%02d", E_1) + ":" + String.format("%02d", E_2) + ":00"; 9 10 System.out.println("开始时间:" + startTime + " 结束时间:" + endTime); 11 12 KSMC_2.setCellValueFactory(new PropertyValueFactory("KSMC")); 13 YSBH_2.setCellValueFactory(new PropertyValueFactory("YSBH")); 14 YSMC_2.setCellValueFactory(new PropertyValueFactory("YSMC")); 15 HZLB_2.setCellValueFactory(new PropertyValueFactory("HZLB")); 16 GHRC_2.setCellValueFactory(new PropertyValueFactory("GHRC")); 17 SRHJ_2.setCellValueFactory(new PropertyValueFactory("SRHJ")); 18 19 Srdata = DataBaseUtil.getShouRuLieBiao(startTime,endTime); 20 SrTableView.setItems(Srdata); 21 22 }
从数据库获取数据的过程如下,是根据时间间隔来查询并返回数据:
1 public static ObservableList<SrColumn> getShouRuLieBiao(String startTime, String endTime) { 2 final ObservableList<SrColumn> data = FXCollections.observableArrayList(); 3 ObservableList<SrColumn> new_data = FXCollections.observableArrayList(); 4 String YsName = null; 5 try { 6 Connection con = null; //定义一个MYSQL链接对象 7 Class.forName("com.mysql.jdbc.Driver").newInstance();//MYSQL驱动 8 con = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/java_yiyuan", "root", "root"); //链接本地MYSQL 9 Statement stmt, stmt1, stmt2, stmt3; //创建声明 10 stmt = con.createStatement(); 11 stmt1 = con.createStatement(); 12 stmt2 = con.createStatement(); 13 stmt3 = con.createStatement(); 14 15 String YSBH_fromDb; 16 String HZBH_fromDb; 17 18 String YSMC = null, HZBH = null, BRBH = null, RQSJ = null, KSMC = null, HZLB = null; 19 Boolean SFZJ = null; 20 String BRMC = null; 21 double GHFY = 0; 22 23 String selectSql1, selectSql2, selectSql3; 24 ResultSet selectRes1, selectRes2, selectRes3; 25 26 String selectSql = "SELECT * FROM t_ghxx WHERE RQSJ BETWEEN '" + startTime + "' and '" + endTime + "'"; 27 ResultSet selectRes = stmt.executeQuery(selectSql); 28 System.out.println("开始统计:"); 29 30 while (selectRes.next()) { //循环输出结果集 31 YSBH_fromDb = selectRes.getString("YSBH"); 32 HZBH_fromDb = selectRes.getString("HZBH"); 33 GHFY = selectRes.getDouble("GHFY"); 34 System.out.println("in1:"); 35 System.out.println("YSBH_fromDb:"+YSBH_fromDb+" HZBH_fromDb:"+HZBH_fromDb+" GHFY:"+GHFY); 36 37 //YSMC 38 selectSql1 = "SELECT * FROM t_ksys"; 39 selectRes1 = stmt1.executeQuery(selectSql1); 40 String YSBH_from_db = null; 41 String KSBH_from_db = null; 42 while (selectRes1.next()) { //循环输出结果集 43 YSBH_from_db = selectRes1.getString("YSBH"); 44 System.out.println("in 1111:YSBH_from_db="+YSBH_from_db); 45 if (YSBH_from_db.equals(YSBH_fromDb)) { 46 YSMC = selectRes1.getString("YSMC"); 47 KSBH_from_db = selectRes1.getString("KSBH"); 48 System.out.println("in 1111:YSBH_from_db="+YSBH_from_db+" YSMC="+YSMC+" KSBH_from_db="+KSBH_from_db); 49 break; 50 } 51 } 52 53 //KSMC 54 selectSql2 = "SELECT * FROM t_ksxx"; 55 selectRes2 = stmt2.executeQuery(selectSql2); 56 String KSBH_from_db1 = null; 57 while (selectRes2.next()) { //循环输出结果集 58 KSBH_from_db1 = selectRes2.getString("KSBH"); 59 System.out.println("in 2222:KSBH_from_db1="+KSBH_from_db1); 60 if (KSBH_from_db.equals(KSBH_from_db1)) { 61 KSMC = selectRes2.getString("KSMC"); 62 System.out.println("in 2222:KSBH_from_db1=" + KSBH_from_db1 + " KSMC=" + KSMC); 63 break; 64 } 65 } 66 67 //HZLB 68 selectSql3 = "SELECT * FROM t_hzxx"; 69 selectRes3 = stmt3.executeQuery(selectSql3); 70 String HZBH_from_db = null; 71 while (selectRes3.next()) { //循环输出结果集 72 HZBH_from_db = selectRes3.getString("HZBH"); 73 System.out.println("in 3333:HZBH_from_db="+HZBH_from_db); 74 if (HZBH_from_db.equals(HZBH_fromDb)) { 75 SFZJ = selectRes3.getBoolean("SFZJ"); 76 System.out.println("in 3333:HZBH_from_db=" + HZBH_from_db + " SFZJ=" + SFZJ); 77 break; 78 } 79 } 80 data.addAll(new SrColumn(KSMC, YSBH_fromDb, YSMC, SFZJ ? "专家号":"普通号" , 0, GHFY)); 81 } 82 83 Object[] mydata = data.toArray(); 84 for (int i = 0; i < mydata.length; i++) { 85 SrColumn iidata = (SrColumn) mydata[i]; 86 int GHRC = 0; 87 double SRHJ = 0; 88 for (int j = 0; j < mydata.length; j++) { 89 SrColumn jjdata = (SrColumn) mydata[j]; 90 System.out.println("iidata 数据:"+iidata.getKSMC()+iidata.getYSBH()+ iidata.getYSMC()+iidata.getHZLB()+ GHRC+ " "+SRHJ); 91 if (!jjdata.isVisited()) { 92 if (iidata.getKSMC().contains(jjdata.getKSMC()) && iidata.getYSBH().contains(jjdata.getYSBH()) && iidata.getYSMC().contains(jjdata.getYSMC()) && iidata.getHZLB().contains(jjdata.getHZLB())) { 93 GHRC++; 94 SRHJ += jjdata.getSRHJ(); 95 ((SrColumn) mydata[j]).setVisited(true); 96 System.out.println(" 数据:" + jjdata.getKSMC() + jjdata.getYSBH() + jjdata.getYSMC() + jjdata.getHZLB() + GHRC + " " + SRHJ); 97 } else { 98 System.out.println(" 数据:" + jjdata.getKSMC() + jjdata.getYSBH() + jjdata.getYSMC() + jjdata.getHZLB() + GHRC + " " + SRHJ); 99 } 100 } 101 } 102 System.out.println("第 "+i+" 次循环数据:"+iidata.getKSMC()+iidata.getYSBH()+ iidata.getYSMC()+iidata.getHZLB()+ GHRC+ " "+SRHJ); 103 if (GHRC != 0) { 104 new_data.addAll(new SrColumn(iidata.getKSMC(), iidata.getYSBH(), iidata.getYSMC(), iidata.getHZLB(), GHRC, SRHJ)); 105 } 106 107 } 108 109 con.close(); 110 } catch (Exception e) { 111 System.out.print("MYSQL ERROR:" + e.getMessage()); 112 } 113 return new_data; 114 }
数据库的查询有点复杂,因为需要嵌套查询,因此效率并不是想象中那么快,在学习了数据库课程以后,继续优化。适配器类如下:
1 package sample; 2 3 public class SrColumn { 4 private String KSMC; 5 private String YSBH; 6 private String YSMC; 7 private String HZLB; 8 private int GHRC; 9 private double SRHJ; 10 private boolean isVisited = false; 11 12 public SrColumn(String KSMC, String YSBH, String YSMC, String HZLB, int GHRC, double SRHJ) { 13 this.KSMC = KSMC; 14 this.YSBH = YSBH; 15 this.YSMC = YSMC; 16 this.HZLB = HZLB; 17 this.GHRC = GHRC; 18 this.SRHJ = SRHJ; 19 } 20 21 22 public String getKSMC() { 23 return KSMC; 24 } 25 26 public void setKSMC(String KSMC) { 27 this.KSMC = KSMC; 28 } 29 30 public String getYSBH() { 31 return YSBH; 32 } 33 34 public void setYSBH(String YSBH) { 35 this.YSBH = YSBH; 36 } 37 38 public String getYSMC() { 39 return YSMC; 40 } 41 42 public void setYSMC(String YSMC) { 43 this.YSMC = YSMC; 44 } 45 46 public String getHZLB() { 47 return HZLB; 48 } 49 50 public void setHZLB(String HZLB) { 51 this.HZLB = HZLB; 52 } 53 54 public int getGHRC() { 55 return GHRC; 56 } 57 58 public void setGHRC(int GHRC) { 59 this.GHRC = GHRC; 60 } 61 62 public double getSRHJ() { 63 return SRHJ; 64 } 65 66 public void setSRHJ(int SRHJ) { 67 this.SRHJ = SRHJ; 68 } 69 70 public boolean isVisited() { 71 return isVisited; 72 } 73 74 public void setVisited(boolean visited) { 75 isVisited = visited; 76 } 77 }
一、软件测试
对照题目要求,构造测试例,给出程序界面截图,举证题目要求的功能(以及自行补充的功能)已实现。
1. 登录模块测试
系统运行启动后如下:
图2.9 登录界面
当输入框输入有空时:
当编号输入正确,密码错误时:
当输入信息均正常时,登录成功,界面成功跳转:
- 挂号模块测试:
当点击科室输入框时: