Skip to content

东软云医院(HIS)的项目

1 开发过程

1.1 需求分析:

做的目标:

1)业务流程

2)功能模块: 识别参与者以及功能

a. 挂号收费员:

a) 挂号: 收集信息(类型,约束) 身份证(18位)、姓名等等....

b) 收费

3)原型制作: Axure8

4)形成《需求规格说明书》。

1.2 设计阶段:

设计ER关系,以及物流模型

设计文档: 数据结构

使用powerdisinger设计数据库

1.3 编码:

前后端分离:vuesjs +javaweb(servlet+jdbc)

设计项目:

1) Element-ui(界面组件)、axios用于网络请求封装、各种组件的封装

2) Controller、Service、Dao三层架构 jdbcutil工具类,json格式(fastjson的类库)

3) Controller 封装: doGet 、doPost String type = request.getParameter(“type”);

4) 响应内容进行封装(json)

String json = ""; PrintWriter out = response.getWriter(); out.write(json); out.flush(); out.close();

5) 对编码进行处理CharsetFilter

6) 对跨域处理CrossFilter

7) 权限认证(先设计、后实现)

1.4测试:

​ 1) 单元测试

​ 2) 系统测试

1.5 部署、验收

2.需求成果

2.1系统用例

2.2 功能需求

2.2.1挂号

在患者到医院看病的时候首先要进行门诊挂号,在挂号处登记患者的基本信息、挂号级别、挂号科室及医生,患者缴费之后,打印挂号发票。挂号完成患者就可以到医生站接受看诊服务了,否则到医生站是看不到该患者的。

挂号时输入的信息包括:病历号(自动生成,唯一、必填)、姓名(必填)、性别(必填)、年龄、出生日期(年龄和出生日期填一个,另一个自动计算)、身份证号、家庭住址、挂号级别(必填)、挂号科室(必填)、看诊医生(必填)、是否要病历本(如要单独收费1元)、应收金额(由系统根据挂号的级别及看诊医生,是否要病历本,自动算出)

病人实体(诊疗信息):

字段约束备注
姓名长度2-100字符
身份证号18位字符
性别男、女
出生日期跟年龄2选一必填
家庭住址
挂号级别从系统预设信息中选择
挂号科室从科室中选择
看诊医生选择对应级别的科室的医生
是否要病历本是否选择项
应收金额数字
主诉大段文字描述,内容可能比价长
现病史、
现病治疗情况
既往史
过敏史
体格检查
状态1 已挂号 2 已接诊 3 已退号
挂号时间(创建时间)系统当前时间

挂号级别

字段约束备注
级别
费用数字

科室

字段约束备注
科室名称
办公地址
负责人

医生

字段约束备注
姓名
性别
电话号
出生日期
所属级别
所属科室

2.2.2收费

【应用场景】:当患者到医生站看诊后,医生会根据患者病情开立相应的检查、检验或药品等收费项目,该功能主要实现对这些项目进行收费,收费同时同时打印发票。

【操作描述】:收费

  1. 收费:输入患者病历号,自动显示患者挂号信息、该患者未收费状态的项目及预收费总额。点击“收费”按钮,实收金额,系统自动算出找零金额。点击“确认”按钮,收费结束,。

收费结束后,医生站、药房、医技站看到该项目为已收费状态,可以进行药品发放、医技检查/化验登记等。

检查实体:

字段约束备注
患者信息必填
检查项目名称必填
价格
状态1 待缴费 2 待检查 3 已检查 4 已退费
开立时间(创建时间)系统当前时间默认系统时间
是否有效active1 正常 0 已删除默认1

检验实体:

字段约束备注
患者信息必填
检查项目名称必填
价格
状态1 待缴费 2 待检查 3 已检查 4 已退费
开立时间系统当前时间

2.2.3 退号

根据患者病历号查询患者信息如果未诊断可以退号。

2.2.4 退费

【应用场景】:。

【操作描述】:根据患者病历号查询已收费的项目,如果项目待检查、待检验可以退费

2.2.5 病历首页

【应用场景】:当医生首次接诊患者时,需要询问患者的一些信息,该信息称为“病历首页”,主要内容包括:主诉、现病史、现病治疗情况、既往史、过敏史、体格检查、

初步诊断(西医)或初步诊断(中医)、检查建议、注意事项,所有项目必填。

【操作描述】:患者选择、暂存病历首页、提交病历首页、清屏、存为模板、引用模板病历、常用诊断管理、查看历史病历。

  1. 患者选择:通过点击患者姓名,显示对应患者的病历首页信息。

  2. 提交病历首页:医生输入完患者的病历首页信息之后,点击“提交”按钮,系统检查所有项目是否填写完整,填写完整之后,系统保存患者病历首页信息。之后医生才可以进行检查、检验操作。

2.2.6 检查申请

血常规 100

肝肾功能 180

由医生根据系统预设的检查项目,提供选择并开具申请

预设的检查项目

预设检查项目实体:

字段约束备注
检查项目名称必填
价格

2.2.7 检验申请

由医生根据系统预设的检验项目,提供选择并开具申请

预设的检查项目

预设检验项目实体:

字段约束备注
检验项目名称必填
价格

2.2.8 诊必

2.3 非功能性需求

3 设计成果

使用Powerdesigner设计表的物理模型==>生成sql语句

物理模型[下载]

2020-12-22_094249

3.2 数据库脚本

sql
/*==============================================================*/
/* DBMS name:      MySQL 5.0                                    */
/* Created on:     2020/12/22 10:26:43                          */
/*==============================================================*/


CREATE DATABASE /*!32312 IF NOT EXISTS*/ his1222 /*!40100 DEFAULT CHARACTER SET utf8 */;
USE his1222;


drop table if exists check_apply;

drop table if exists check_item;

drop table if exists constant_item;

drop table if exists constant_type;

drop table if exists department;

drop table if exists inspect_apply;

drop table if exists inspect_item;

drop table if exists menu;

drop table if exists regist_level;

drop table if exists register;

drop table if exists role;

drop table if exists role_menu;

drop table if exists user;

drop table if exists user_role;

/*==============================================================*/
/* Table: check_apply                                           */
/*==============================================================*/
create table check_apply
(
   id                   int not null auto_increment comment 'id',
   register_id          int comment '病历号',
   item_id              int comment '项目id',
   item_name            varchar(100) comment '项目名称',
   fee                  decimal(8,2) comment '检查费用',
   status               int comment '状态',
   active               int default 1 comment '是否有效,1 有效,0 失效',
   createtime           datetime default CURRENT_TIMESTAMP comment '创建时间',
   primary key (id)
);

alter table check_apply comment '检查申请';

/*==============================================================*/
/* Table: check_item                                            */
/*==============================================================*/
create table check_item
(
   id                   int not null auto_increment comment 'id',
   name                 varchar(100) comment '检查名称',
   fee                  decimal(8,2) comment '检查费用',
   active               int default 1 comment '是否有效,1 有效,0 失效',
   createtime           datetime default CURRENT_TIMESTAMP comment '创建时间',
   primary key (id)
);

alter table check_item comment '检查项目';

/*==============================================================*/
/* Table: constant_item                                         */
/*==============================================================*/
create table constant_item
(
   id                   int not null auto_increment comment 'id',
   type_id              int comment '类别id',
   code                 varchar(100) comment '常数项代码',
   name                 varchar(100) comment '常数项名称',
   sort                 int comment '排序',
   active               int default 1 comment '是否有效,1 有效,0 失效',
   createtime           datetime default CURRENT_TIMESTAMP comment '创建时间',
   primary key (id)
);

alter table constant_item comment '常数项表';

/*==============================================================*/
/* Table: constant_type                                         */
/*==============================================================*/
create table constant_type
(
   id                   int not null auto_increment comment '主键id',
   code                 varchar(100) comment '代码',
   name                 varchar(100) comment '名称',
   active               int default 1 comment '是否有效,1 有效,0 失效',
   createtime           datetime default CURRENT_TIMESTAMP comment '创建时间',
   primary key (id)
);

alter table constant_type comment '常数类别';

/*==============================================================*/
/* Table: department                                            */
/*==============================================================*/
create table department
(
   id                   int not null auto_increment comment 'id',
   name                 varchar(100) comment '名称',
   address              varchar(200) comment '办公地址',
   leader               varchar(100) comment '负责人',
   active               int default 1 comment '是否有效,1 有效,0 失效',
   createtime           datetime default CURRENT_TIMESTAMP comment '创建时间',
   primary key (id)
);

alter table department comment '科室';

/*==============================================================*/
/* Table: inspect_apply                                         */
/*==============================================================*/
create table inspect_apply
(
   id                   int not null comment 'id',
   item_id              int comment '项目id',
   item_name            varchar(100) comment '项目名称',
   fee                  decimal(8,2) comment '检查费用',
   status               int comment '状态',
   register_id          int comment '病历号',
   active               int default 1 comment '是否有效,1 有效,0 失效',
   createtime           datetime default CURRENT_TIMESTAMP comment '创建时间',
   primary key (id)
);

alter table inspect_apply comment '检验申请';

/*==============================================================*/
/* Table: inspect_item                                          */
/*==============================================================*/
create table inspect_item
(
   id                   int not null auto_increment comment 'id',
   name                 varchar(100) comment '检查名称',
   fee                  decimal(8,2) comment '检查费用',
   active               int default 1 comment '是否有效,1 有效,0 失效',
   createtime           datetime default CURRENT_TIMESTAMP comment '创建时间',
   primary key (id)
);

alter table inspect_item comment '检验项目';

/*==============================================================*/
/* Table: menu                                                  */
/*==============================================================*/
create table menu
(
   menu_id              int not null auto_increment comment '菜单id',
   menu_name            varchar(100) comment '菜单名称',
   url                  varchar(100) comment '菜单url',
   parent_id            int comment '上级菜单id',
   active               int default 1 comment '是否有效,1 有效,0 失效',
   createtime           datetime default CURRENT_TIMESTAMP comment '创建时间',
   primary key (menu_id)
);

alter table menu comment '菜单';

/*==============================================================*/
/* Table: regist_level                                          */
/*==============================================================*/
create table regist_level
(
   id                   int not null auto_increment comment 'id',
   name                 varchar(100) comment '名称',
   fee                  decimal(8,2) comment '费用',
   active               int default 1 comment '是否有效,1 有效,0 失效',
   createtime           datetime default CURRENT_TIMESTAMP comment '创建时间',
   primary key (id)
);

alter table regist_level comment '挂号级别';

/*==============================================================*/
/* Table: register                                              */
/*==============================================================*/
create table register
(
   id                   int not null auto_increment comment 'id病历号',
   name                 varchar(100) comment '姓名',
   gender               int comment '性别',
   idno                 varchar(100) comment '身份证号',
   birthday             date comment '出生日期',
   age                  int comment '年龄',
   address              varchar(200) comment '家庭住址',
   regsit_level_id      int comment '挂号级别',
   dept_id              int comment '挂号科室',
   doctor_id            int comment '看诊医生',
   book                 int comment '是否要病历本',
   visittime            date comment '看诊时间',
   fee                  decimal(8,2) comment '挂号费用',
   readme               varchar(500) comment '主诉',
   present              varchar(500) comment '现病史',
   present_treat        varchar(500) comment '现病史治疗情况',
   history              varchar(500) comment '既往史',
   allergy              varchar(500) comment '过敏史',
   disease              varchar(500) comment '确诊疾病',
   suit                 varchar(500) comment '处置方案',
   drug                 varchar(500) comment '药品清单',
   status               int comment '状态',
   active               int default 1 comment '是否有效,1 有效,0 失效',
   createtime           datetime default CURRENT_TIMESTAMP comment '创建时间',
   primary key (id)
);

alter table register comment '诊疗信息';

/*==============================================================*/
/* Table: role                                                  */
/*==============================================================*/
create table role
(
   role_id              int not null auto_increment comment '角色id',
   role_name            varchar(100) comment '角色名称',
   active               int default 1 comment '是否有效,1 有效,0 失效',
   createtime           datetime default CURRENT_TIMESTAMP comment '创建时间',
   primary key (role_id)
);

alter table role comment '角色';

/*==============================================================*/
/* Table: role_menu                                             */
/*==============================================================*/
create table role_menu
(
   menu_id              int not null comment '菜单id',
   role_id              int not null comment '角色id',
   primary key (menu_id, role_id)
);

alter table role_menu comment '角色菜单信息';

/*==============================================================*/
/* Table: user                                                  */
/*==============================================================*/
create table user
(
   user_id              int not null auto_increment comment '医生id',
   username             varchar(100) comment '用户名',
   password             varchar(100) comment '密码',
   realname             varchar(100) comment '真实姓名',
   telephone            varchar(20) comment '电话号码',
   dept_id              int comment 'id',
   user_type            int comment '医生类型',
   lastlogin            datetime comment '最后登录时间',
   active               int default 1 comment '是否有效,1 有效,0 失效',
   createtime           datetime default CURRENT_TIMESTAMP comment '创建时间',
   primary key (user_id)
);

alter table user comment '医生-用户信息';

/*==============================================================*/
/* Table: user_role                                             */
/*==============================================================*/
create table user_role
(
   user_id              int not null comment '医生id',
   role_id              int not null comment '角色id',
   primary key (user_id, role_id)
);

alter table user_role comment '用户角色';

alter table role_menu add constraint FK_Reference_1 foreign key (menu_id)
      references menu (menu_id) on delete restrict on update restrict;

alter table role_menu add constraint FK_Reference_2 foreign key (role_id)
      references role (role_id) on delete restrict on update restrict;

alter table user add constraint FK_Reference_5 foreign key (dept_id)
      references department (id) on delete restrict on update restrict;

alter table user_role add constraint FK_Reference_3 foreign key (user_id)
      references user (user_id) on delete restrict on update restrict;

alter table user_role add constraint FK_Reference_4 foreign key (role_id)
      references role (role_id) on delete restrict on update restrict;

3.3 创建数据库

4 后端项目

全量代码详见:Gitee

4.1. Servlet +json形式 使用jdbcutil持久层操作

创建聚合项目

└─his ├─his-server └─his-jdbcutil

his-server

4.2 基于servlet API的 Javaweb项目

1 修改web.xml中的版本

<?xml version="1.0" encoding="UTF-8"?>

<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
                      http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
         version="3.1">

</web-app>

2 添加依赖,修改jdk为1.8

xml
<?xml version="1.0" encoding="UTF-8"?>

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>com.neuedu</groupId>
  <artifactId>his-server</artifactId>
  <version>1.0</version>


  <packaging>war</packaging>

  <name>his-server后台</name>


  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <maven.compiler.source>1.8</maven.compiler.source>
    <maven.compiler.target>1.8</maven.compiler.target>
  </properties>

  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.11</version>
      <scope>test</scope>
    </dependency>

    <dependency>
      <groupId>javax.servlet</groupId>
      <artifactId>javax.servlet-api</artifactId>
      <version>3.0.1</version>
      <!--作用域  provided  参与编译,运行时抛弃 -->
      <scope>provided</scope>
    </dependency>

    <!-- https://mvnrepository.com/artifact/javax.servlet.jsp/jsp-api -->
    <dependency>
      <groupId>javax.servlet.jsp</groupId>
      <artifactId>jsp-api</artifactId>
      <version>2.1</version>
      <scope>provided</scope>
    </dependency>


    <dependency>
      <groupId>com.neuedu</groupId>
      <artifactId>jdbcutil</artifactId>
      <version>1.0</version>
    </dependency>

    <!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
    <dependency>
      <groupId>org.projectlombok</groupId>
      <artifactId>lombok</artifactId>
      <version>1.18.12</version>
      <scope>provided</scope>
    </dependency>




  </dependencies>

</project>

4.3 设计框架

  • CharsetFilter 处理中文编码
  • 封装通用的请求处理
java
package com.neuedu.his.servlet;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

/**
 * 项目:      his
 * 类名:       BaseServlet
 * 创建时间:  2020/12/22  11:04
 * 描述 :     基础Servlet
 * 作者 :     张金山
 * QQ :     314649444
 * Site:      https://jshand.gitee.io
 */

public class BaseServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
       String function = request.getParameter("type");

        Class<? extends BaseServlet> clazz = this.getClass();

        try {
            Method method = clazz.getDeclaredMethod(function, HttpServletRequest.class, HttpServletResponse.class);

            method.invoke(this,request,response);

        } catch (NoSuchMethodException e) {
            System.out.println("请求无法处理,未找到方法"+function);
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }

    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        this.doGet(req, resp);
    }
}
  • 封装通用的json返回
java
CommonResult result = CommonResult.noHanlder();
 
CommonResult result = CommonResult.error("系统出错了,请联系管理员");


protected  void out(HttpServletResponse response, Object data) throws IOException {

	response.setContentType("application/json");

	String json = JSON.toJSONString(data, SerializerFeature.WriteDateUseDateFormat);
	PrintWriter out = response.getWriter();
	
	out.write(json);
	out.flush();
	out.close();
}
  • 通用的参数封装

5. 前端项目搭建

全量代码:https://gitee.com/harbin-university-18-java1/his-front.git

使用vuejs实现前后端分离 vuejs2.x 使用vue-cli脚手架(4.x)

5.1 命令:

sh
vue create his-front

5.2 配置默认配置文件

端口,关闭eslint校验

js
module.exports = {
	lintOnSave: false,
	devServer: {
		port: 80 //修改启动端口
	}
}

5.3 添加依赖

  • vue-router

  • axios

  • element-UI

    npm i element-ui -S
    npm install axios
    npm install vue-router
  • 在main.js中添加router

  • 引用elementUI

  • 引用axios

  • 设置 通用的前缀

js
import axios from 'axios';

axios.defaults.baseURL = "http://127.0.0.1:8080/his";
Vue.prototype.axios = axios ;

6.Vuex 使用

6.1 需要安装

sh
npm install vuex --save

6.2 创建store对象

js
import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

const store = new Vuex.Store({
  //state 存储状态
  state: {
    user: null
  },
  
  //用于修改状态的 方法
  mutations: {
	  
	//将登录的用户,存储到状态中
    logonUser (state,user) {
      state.user = user
    }
  }
})


export default store;

6.3 将上述对象绑定到 Vue实例中

new Vue({
  el: '#app',
  store
})

项目中的绑定

import Vue from 'vue'
import App from './App.vue'

import router from '@/router/router.js'

import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';

import axios from '@/util/axiosutil'  // {get :function} 
import store from '@/util/store'  



Vue.prototype.axios = axios ;

Vue.use(ElementUI);


Vue.config.productionTip = false

new Vue({
	router,
	store,
  render: h => h(App),
}).$mount('#app')

6.4 向store存储数据

js
this.$store.commit('logonUser',user)
  • 使用mapMutations 简化写法

    从vuex中引入 mapMutations

    js
    import { mapMutations } from 'vuex'

    使用mapMutations将操作引入到 组件中

    js
    import { mapMutations } from 'vuex'
    
    export default {
      // ...
      methods: {
        ...mapMutations(['logonUser'})
      }
    }

    6.5 从store 获取数据

    js
    import Vue from 'vue'
    import Vuex from 'vuex'
    
    Vue.use(Vuex)
    
    const store = new Vuex.Store({
    	//state 存储状态
    	state: {},
    
    	//用于修改状态的 方法
    	mutations: {},
    	
    	//用户获取状态的数据
    	getters: {
    		getuser: state => {
    			return state.user
    		}
    	}
    })
    
    
    export default store;

    使用getters获取数据

    this.$store.getters.getuser

    或者mapGetters函数

    js
    import Menu from '@/components/menu'
    	import { mapGetters } from 'vuex'
    	
    	export default {
    		name: 'Home',
    		components: {
    			Menu
    		},
    		data() {
    			return {
    				username:'',
    			}
    		},
    		methods: {
    			
    		},
    		computed:{
    			...mapGetters(['getuser'])
    		},
    		created() {
    			// console.log("登录用户:")
    			// console.log(this.$store.getters.getuser);
    			// this.username = this.$store.getters.getuser.realname
    		}
    	}

    6.5 将状态持久化

    使用插件

    js
    npm install vuex-persistedstate  --save

    给store添加插件

    js
    import createPersistedState from "vuex-persistedstate"
    const store = new Vuex.Store({
      // ...
      plugins: [createPersistedState()]
    })

7 后端权限验证

8 基于ssm框架

  • 后端ssm框架(设置后端跨域)
  • 前端vuejs项目
    • 创建项目
    • 添加依赖
json
"dependencies": {
    "axios": "^0.21.1",
    "core-js": "^3.6.5",
    "element-ui": "^2.15.1",
    "vue": "^2.6.11",
    "vue-router": "^3.5.1",
    "vuex": "^3.6.2",
    "vuex-persistedstate": "*"
  },
  • 整合element-ui

    1. 在main.js中引入elementui

      js
      import ElementUI from 'element-ui';
      import 'element-ui/lib/theme-chalk/index.css';
      
      Vue.use(ElementUI);
    2. App.vue制作框架的布局

    3. 在左侧布局中使用element-ui的菜单

    4. 修改菜单的响应方式,router

    5. 创建路由表

  • CRUD

Released under the MIT License.