东软云医院(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 待缴费 2 待检查 3 已检查 4 已退费 | |
开立时间(创建时间) | 系统当前时间 | 默认系统时间 |
是否有效active | 1 正常 0 已删除 | 默认1 |
检验实体:
字段 | 约束 | 备注 |
---|---|---|
患者信息 | 必填 | |
检查项目名称 | 必填 | |
价格 | ||
状态 | 1 待缴费 2 待检查 3 已检查 4 已退费 | |
开立时间 | 系统当前时间 |
2.2.3 退号
根据患者病历号查询患者信息如果未诊断可以退号。
2.2.4 退费
【应用场景】:。
【操作描述】:根据患者病历号查询已收费的项目,如果项目待检查、待检验可以退费
2.2.5 病历首页
【应用场景】:当医生首次接诊患者时,需要询问患者的一些信息,该信息称为“病历首页”,主要内容包括:主诉、现病史、现病治疗情况、既往史、过敏史、体格检查、
初步诊断(西医)或初步诊断(中医)、检查建议、注意事项,所有项目必填。
【操作描述】:患者选择、暂存病历首页、提交病历首页、清屏、存为模板、引用模板病历、常用诊断管理、查看历史病历。
患者选择:通过点击患者姓名,显示对应患者的病历首页信息。
提交病历首页:医生输入完患者的病历首页信息之后,点击“提交”按钮,系统检查所有项目是否填写完整,填写完整之后,系统保存患者病历首页信息。之后医生才可以进行检查、检验操作。
2.2.6 检查申请
血常规 100
肝肾功能 180
由医生根据系统预设的检查项目,提供选择并开具申请
预设的检查项目
预设检查项目实体:
字段 | 约束 | 备注 |
---|---|---|
检查项目名称 | 必填 | |
价格 |
2.2.7 检验申请
由医生根据系统预设的检验项目,提供选择并开具申请
预设的检查项目
预设检验项目实体:
字段 | 约束 | 备注 |
---|---|---|
检验项目名称 | 必填 | |
价格 |
2.2.8 诊必
2.3 非功能性需求
3 设计成果
使用Powerdesigner设计表的物理模型==>生成sql语句
3.2 数据库脚本
/*==============================================================*/
/* 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 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 处理中文编码
- 封装通用的请求处理
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返回
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 命令:
vue create his-front
5.2 配置默认配置文件
端口,关闭eslint校验
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
设置 通用的前缀
import axios from 'axios';
axios.defaults.baseURL = "http://127.0.0.1:8080/his";
Vue.prototype.axios = axios ;
6.Vuex 使用
6.1 需要安装
npm install vuex --save
6.2 创建store对象
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存储数据
this.$store.commit('logonUser',user)
使用mapMutations 简化写法
从vuex中引入 mapMutations
jsimport { mapMutations } from 'vuex'
使用mapMutations将操作引入到 组件中
jsimport { mapMutations } from 'vuex' export default { // ... methods: { ...mapMutations(['logonUser'}) } }
6.5 从store 获取数据
jsimport 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函数
jsimport 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 将状态持久化
使用插件
jsnpm install vuex-persistedstate --save
给store添加插件
jsimport createPersistedState from "vuex-persistedstate" const store = new Vuex.Store({ // ... plugins: [createPersistedState()] })
7 后端权限验证
8 基于ssm框架
- 后端ssm框架(设置后端跨域)
- 前端vuejs项目
- 创建项目
- 添加依赖
"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
在main.js中引入elementui
jsimport ElementUI from 'element-ui'; import 'element-ui/lib/theme-chalk/index.css'; Vue.use(ElementUI);
App.vue制作框架的布局
在左侧布局中使用element-ui的菜单
修改菜单的响应方式,router
创建路由表
CRUD
