预约管理功能,包括检查项管理、检查组管理、体检套餐管理、预约设置等、预约管理属于系统的基础功能,主要就是管理一些体检的基础数据。
检查组是检查项的集合
需要用到的表和其中的关联表,检查项和检查组是多对多关系
根据数据表也可以自己创建实体类,两者存在对应关系,一张表对应一个实体类(POJO),关联表不存在实体类。
实体类之间存在多对多关系,可以通过在实体类中建立一个List集合来对应关系。
因为使用到检查组时一定会检索到检查组,所以在检查组中声明了检查项。
但是使用检查项时不一定会使用到检查组,所以检查项中没必要声明检查组
各个模块都有可能使用到这些实体类,将POJO实体类复制到health_common工程中
创建新的包pojo
消息常量类
返回结果Result和PageResult(分页查询返回的结果类)类,放到health_common工程中
注:返回结果指的是SpringMVC中controller的返回结果,项目中所有的增删改查操作发送的请求,基于的都是ajax异步请求(可以用F12查看过程),请求完成后,在controller中处理,完成后controller将结果封装成PageResult对象,PageResult对象将结果转换成json数据,写回到前端页面。
Result类是除了分页查询返回结果类的所有返回结果类
QueryPageBean类,封装查询条件,页面输入的查询条件作为类的参数
创建新的包entity
复制资源包到health_backend模块下的webapp中
注:此处js资源中的axios.js文件是使用ajax必须的文件,vue.js文件是使用vue必须的文件
启动项目,因为项目依赖zookeeper基础服务,所以需要安装windows单机的zookeeper
三.zookeeper安装使用
zookeeper是apache hadoop项目下的一个子项目,是一个树形管理目录
zookeeper是一个分布式,开源的分布式应用程序的协调服务
主要功能是:配置管理,分布式锁,集群管理
目前开发阶段需要依赖zookeeper,但是不需要启动虚拟机,所以我们直接下载文件在windows环境下运行即可。
windows环境下安装zookeeper
1.首先去官网下载文件
2.解压到常用安装软件目录
3.运行zkServer.cmd文件
执行闪退:编辑zkServer.cmd末尾添加pause 。这样运行出错就不会退出,会提示错误信息,方便找到原因。
缺少zoo.cfg文件:将conf目录下的zoo_sample.cfg文件,复制一份,重命名为zoo.cfg。
如果
出现ZooKeeper audit is disabled,zoo.cfg新增一行
audit.enable=true
成功启动后可以在logs目录中查看日志
项目运行之前,对项目整体进行编译
因为在backend项目中的pom文件中引入了tomcat7,所以在backend的plugins中可以看到插件
如果pom文件中tomcat爆红,可以添加一个版本号
启动tomcat
根据tomcat定义来确认访问路径
成功访问
iframe标签可以直接引用其它页面。
menuList可以遍历出所有的子级菜单
menuList中的linkUrl对应页面名称,点击菜单的时候就可以跳转到相关页面
通过href超链接跳转,linkUrl对应了页面名
新建检查项功能应该在点击新建后弹出弹层,所以在默认情况下该弹层是隐藏的,单击新增后展示此页面
visible.sync表示控制当前窗口是显示还是隐藏,:visible.sync表示绑定的控制值是动态的。
diaglogFormVisible是在vue对象中创建的一个模型数据
dialogFormVisible: false,//增加表单是否可见
默认值为false,表示默认此弹层不可见
为新建按钮绑定一个单击事件(@Click),对应的函数是handleCreate()
新建
// 弹出添加窗口
handleCreate() {
},
当单击新建按钮时,触发对应函数handleCreate(),此时修改:visible.sync对应的控制值diaglogFormVisible发生变化,使弹层展示
handleCreate() {
// 弹出新增页面
this.dialogFormVisible=true;
},
取消按钮绑定的事件,把模型数据修改为false,从而使弹层取消展示
取消
el-diaglog自带的×按钮也可以取消弹层展示
取消弹层展示后清空表单内容
表单输入框的内容和模型数据V-model绑定了,每次弹出之后,重新设置模型数据值,将数据值设置为空的json即可实现清空表单内容功能。
// 重置表单
resetForm() {
//重置表单数据
this.formData = {};
},
// 弹出添加窗口
handleCreate() {
// 弹出新增页面
this.dialogFormVisible=true;
//将json数据直接赋空值:{}
this.formData = {};
},
这样做可以重置表单,但是弹出新增功能就和重置表单功能粘合了,我们的原则是方法单一,即每个方法只完成一个功能。重置表单功能作为单一的一个方法,我们需要用到这个功能时直接调用这个方法即可。
在VUE对象中定义校验规则(rules)
rules: {//校验规则 code: [{ required: true, message: '项目编码为必填项', trigger: 'blur' }], name: [{ required: true, message: '项目名称为必填项', trigger: 'blur' }] }
在以下输入域中应用规则
提交表单数据使用ajax异步请求方式提交,点击提交按钮后,首先对表单数据进行一个整体校验,校验成功后,将表单数据获取,表单数据都绑定在VUE对象的模型数据(formData)中了。所以提交表单就是提交formData,发送ajax请求。
注:alter();方法可以检验触发事件@handleAdd
// 1.表单校验,获取表单对象refs
this.$refs["dataAddForm"].validate((valid) => {
alert(valid);
});
表单数据对应的ref="dataAddForm",通过this.refs获取到表单数据,validate方法是一个箭头函数,如果表单校验通过,那么其中的valid值会是ture值。
controller端收到网页请求后,会产生一个响应(res),而在之前common模块中,已经封装好了controller的返回结果,定义res是一个Reslut类型的java对象,SpringMVC会自动将Result对象转化成json,flag,message。
// console.log(this.formData); //通过开发者模式观察通过校验后的表单数据
//添加
handleAdd () {
alert();
// 1.表单校验,获取表单对象refs
this.$refs['dataAddForm'].validate((valid) => {
if(valid) {
// 表单检验通过,发送Ajax请求,将录入的数据提交到后台进行处理
// console.log(this.formData); //通过开发者模式观察通过校验后的表单数据
//引用axios文件来发送Ajax请求,post(请求地址,请求体(json数据)),发送后需要一个回调函数then,res是服务端(controller)响应的结果
axios.post("/checkitem/add.do",this.formData).then((res) =>{
//Result对象中包含的flag属性,res.data是固定写法,拿到的就是controller响应的数据
//表单提交后,无论添加成功或者失败,都关闭新增窗口
this.dialogFormVisible = false;
if(res.data.flag){//执行成功
//调用分页查询方法,查询出最新的数据
this.findPage();
//弹出提示信息
this.$message({
message:res.data.message,
type:'success'
});
}else{//执行失败
//弹出提示
this.$message.error(res.data.message);
}
});
}
else{//校验不通过
this.$message.error("数据校验失败,请检查输入信息是否正确");
return false;
}
});
},
res.data是一个固定写法
如果controller端没有响应,则不涉及到Result类的调用,则没有res.data的使用。直接使用 this.$message.*****来展示返回结果即可
在backend模块下新建controller路径,路径下新建CheckItemController类
controller用来响应前端发送的ajax请求
@RestController
//@RestController包含@Controller注解,同时包含ResponseBody;直接让方法返回java对象,SpringMVC框架会自动将java对象转化成json.
@RequestMapping("/checkitem")
//匹配请求路径
请求路径和前端发送请求的路径对应
public void add(CheckItem checkItem);
方法中也要加一个注解匹配请求路径,对应前端的请求路径
@RequestMapping("/add")//匹配请求
public Result add(@RequestBody CheckItem checkItem){
}
//此controller对应实体类是CheckItem,所以方法的参数是CheckItem。前端提交的formData是json数据,SpringMVC无法封装,需要加一个注解才能封装json数据;@RequestBody解析提交的数据,封装成CheckItem对象
@Reference//zookeeper服务中心去查找CheckItemService的服务
private CheckItemService checkItemService;
checkItemService.add(checkItem);
使用try-catch来验证是否调用服务层成功
try{
checkItemService.add(checkItem);
}catch(Exception e){
e.printStackTrace();
//服务调用失败
return new Result(false, MessageConstant.ADD_CHECKITEM_FAIL);
}
return new Result(true, MessageConstant.ADD_CHECKITEM_SUCCESS);
服务层就是dubbo服务层,这个层级用来将controller处理过的前端提交的数据保存到数据库中
public void add(CheckItem checkItem);
//发布服务,使用dubbo的服务注解
@Service(interfaceClass = CheckItemService.class)
@Autowired
private CheckItemDao checkItemDao;
因为基于mybatis的动态代理方式,所以dao接口无需创建实现类,匹配一个xml映射文件即可
头文件可以复制粘贴,sql语句的id对应dao接口中的方法名,parameterType(参数类型)必须和dao接口中指定的参数保持一致
mapper标签的namespace必须和dao接口的完整路径对应
insert into t_checkitem(code,name,sex,age,price,type,remark,attention)
values
(#{code},#{name},#{sex},#{age},#{price},#{type},#{remark},#{attention})
配置文件中的参数,要让dubbo能够扫描到服务层
service实现类中的注解需要添加参数,因为添加了事务注解,所以@Service必须指明实现的是哪个接口
//事务注解
@Transactional
//发布服务,使用dubbo的服务注解
@Service(interfaceClass = CheckItemService.class)
总结后台代码开发流程
1.分析检查项分页查询实现原理
项目所有分页功能都是基于ajax的异步请求来完成的,请求参数和后台响应数据格式都使用json数据格式。
前端的请求参数包括页码,每页显示记录数,查询条件
请求参数的json格式为:{currentPage:1,pageSize:10,queryString:''itcast''}
后台响应数据包括总记录数、当前页需要展示的数据集合。
响应数据的json格式为:{total:1000,rows:[]}
具体流程如下
2.完善页面
定义分页相关的模型数据 pagination
pagination: {//分页相关模型数据
currentPage: 1,//当前页码
pageSize:10,//每页显示的记录数
total:0,//总记录数
queryString:null//查询条件
},
dataList: [],//当前页要展示的分页列表数据
定义分页查询的方法findPage()
这个方法在页面加载完成时调用,可以使用钩子函数来完成,钩子函数:在VUE对象初始化完成后自动执行
findPage() {
//发送ajax请求,提交分页相关参数(页码,每页显示记录数,查询条件)
var param = {
currentPage:this.pagination.currentPage,
pageSize:this.pagination.pageSize,
queryString:this.pagination.queryString
};//构造json对象,封装相关参数
axios.post("checkitem/findPage.do",param).then((res) =>{
//解析controller响应回的数据,为模型数据赋值,将响应回的数据赋给模型数据进行展示
this.pagination.total = res.data.total;
this.dataList = res.data.rows;
});
},
用户点击查询按钮或者点击分页条中的页码时也需要调用findPage方法重新发起查询请求。
为查询按钮绑定单击事件,调用findPage方法
当页码发生改变时,也要调用findPage()方法,分页条自带的事件@current-change,当页码发生改变时自动触发该事件,该事件绑定的方法可以使用传入页码参数(currentPage)和调用findPage()方法来实现页码改变和分页查询功能。
//切换页码
handleCurrentChange(currentPage) {
//设置最新的页码
this.pagination.currentPage = currentPage;
//调用findPage()方法进行分页查询
this.findPage();
},
总结:该方法的调用时机有:页面加载完成时,页码改变时,用户点击查询按钮时
在checkItemController中添加对应的方法来接受前端的参数
参数是QueryPageBean
//检查项分页查询
@RequestMapping("/findPage")//匹配请求
public PageResult findPAge(@RequestBody QueryPageBean queryPageBean){
PageResult pageResult = checkItemService.pageQuery(queryPageBean);
return pageResult;
}
在checkItemService中添加对应方法
在checkItemController对应的方法中调用checkItemService中对应的方法
注:var快捷键可以快速实现代码书写,例如下
checkItemService.pageQuery(queryPageBean).var == PageResult pageResult = checkItemService.pageQuery(queryPageBean);
然后将得到的参数pageResult返回
controller只是向dubbo服务调用了方法
在service的实现类中将分页查询方法拓展
在CheckItemDao接口中拓展出SQL对应方法
mybatis框架了提供了分页助手插件,减少sql语句的书写量
没有分页助手插件情况下,sql语句实现分页查询,limit后面是页码和查询条数,这两个参数是动态的,根据currentPage和pageSize来计算
//select * from t_checkitem limit 0,10
使用分页助手插件后,不需手动书写limit后面的语句了,由助手进行自动拼接
在checkItemDAO.xml文件中新建SQL语句
在服务实现类中调用CheckItemDao中的的方法
关闭tomcat服务,对项目进行安装
删除操作需要缓冲空间,在点击删除后,弹出弹框再次确认是否删除。
ElementUI提供了$confirm方法来实现确认提示信息弹框效果
handleDelete(row) {//row对象是一个json对象,里面有
//alert(row.id);
this.$confirm("确定要删除这条数据吗?","提示",{
type:"warning"
}).then(()=>{
//用户点击确定按钮,发送ajax请求,将要删除数据的id提交到controller进行处理
axios.get("/checkitem/delete.do?id=" + row.id).then((res)=>{
if(res.data.flag){
//执行成功
//弹出删除成功提示信息
this.$message({
type:"success",
message:res.data.message
});
}else{
//执行失败
this.$message.error(res.data.message);
}
this.findPage();
});
}).catch(()=>{
this.$message({
type:"info",
message:"操作取消"
});
});
}
后台代码开发依据五个步骤:
1Controller(Backend)
2服务接口(interface)
3服务实现类(service_provider)
在实现类中定义实现方法:
代码逻辑:检查项和检查组之前存在n对m关系,检查项不能直接删除,需要判断当前检查项是否和检查组关联,如果已经和检查组进行了关联则不允许删除
4Dao接口(service_provider)
5Mapper映射文件(service_provider)
1.前端代码
绑定编辑单击事件,单击编辑时展示页面
// 弹出编辑窗口
handleUpdate(row) {
//显示窗口
this.dialogFormVisible4Edit = true;
//显示数据,发送ajax请求根据id查询当前检查项数据
axios.get("/checkitem/findById.do?id=" + row.id).then((res) => {
if(res.data.flag){
//执行成功,进行回显,基于VUE的数据绑定来实现
this.formData = res.data.data;
}else{
//查询失败,弹出提示
this.$message.error(res.data.message);
}
});
},
编辑完成后,点击确定按钮进行提交,进行表单校验。
//编辑完成后确认
handleEdit() {
//表单校验
this.$refs['dataEditForm'].validate((valid) => {
if(valid){
//表单校验通过,提交编辑后的数据
axios.post("/checkitem/edit.do",this.formData).then((res) =>{
if(res.data.flag){//判断本次操作是否成功
//弹出成功信息
this.$message({
type:"success",
message:res.data.message
});
}else{//本次操作失败
this.$message.error(res.data.message);
}
}).finally(() =>{//finally方法不管成功还是失败都会执行
this.findPage();
//关闭编辑窗口
this.dialogFormVisible4Edit = false;
});
}else{
//表单校验失败,不提交
this.$message.error("表单校验失败!");
return false;//后面代码不执行
}
});
},
axios自带的方法:
//finally方法不管成功还是失败都会执行
2.Controller
首先显示要编辑的数据
//显示要编辑的检查项
@RequestMapping("/findById")//匹配请求
public Result findById(Integer id){
try{//查询应该存在一个返回对象,返回对象是checkItem
CheckItem checkItem = checkItemService.findById(id);
return new Result(true, MessageConstant.QUERY_CHECKITEM_SUCCESS,checkItem);
}catch(Exception e){
e.printStackTrace();
//服务调用失败
return new Result(false, MessageConstant.QUERY_CHECKITEM_FAIL);
}
}
再实现检查项的编辑更新
//编辑检查项
@RequestMapping("/edit")//匹配请求
public Result delete(@RequestBody CheckItem checkItem){
try{
checkItemService.edit(checkItem);
}catch(Exception e){
e.printStackTrace();
//服务调用失败
return new Result(false, MessageConstant.EDIT_CHECKGROUP_FAIL);
}
return new Result(true, MessageConstant.EDIT_CHECKGROUP_SUCCESS);
}
3.服务接口interface
4.服务实现类Impl
声明实现方法后,调用Dao方法
5.Dao接口
声明方法
6.Mapper文件
使用动态sql来实现编辑操作,如果传过来的参数不为空,则将参数进行更新
至此检查项功能完成