---恢復內容開始---
一、需求分析
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() + "\n"); 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() + "\n"); 23 setKSYScomboxInfo(); 24 System.out.println("重新加以后 醫生名稱combobox大小:" + comboBox_YSMC.getItems().size() + "\n"); 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("醫生名稱輸出:\n\n"); 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("醫生名稱輸出完畢\n\n"); 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 + "\n結束時間:" + 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 登錄界面
當輸入框輸入有空時:
當編號輸入正確,密碼錯誤時:
當輸入信息均正常時,登錄成功,界面成功跳轉:
- 掛號模塊測試:
當點擊科室輸入框時: