一.新增套餐
(1).完善页面
新增套餐 分为两部分 第一是套餐的基本信息 第二是 套餐所关联的检查组的信息
其中新增套餐与之前检查项 检查组的新增还有所不同 又增加了上传图片的功能
-
完善handleCreate方法,发送ajax请求查询所有检查组数据并将结果赋值给tableData模型数据用 于页面表格展示
// 弹出添加窗口 handleCreate() { this.dialogFormVisible = true; this.resetForm(); axios.get("/checkgroup/findAll.do").then((res)=> { if(res.data.flag){ this.tableData = res.data.data; }else{ this.$message.error(res.data.message); } }); }
2.分别在CheckGroupController、CheckGroupService、CheckGroupServiceImpl、 CheckGroupDao、CheckGroupDao.xml中扩展方法查询所有检查组数据
(1)CheckGroupController
//查询所有
@RequestMapping("/findAll")
public Result findAll(){
List<CheckGroup> checkGroupList = checkGroupService.findAll();
if(checkGroupList != null && checkGroupList.size() > 0){
Result result = new Result(true, MessageConstant.QUERY_CHECKGROUP_SUCCESS);
result.setData(checkGroupList);
return result;
}
return new Result(false,MessageConstant.QUERY_CHECKGROUP_FAIL);
}
(2) CheckGroupService
List<CheckGroup> findAll();
(3)CheckGroupServiceImpl、
public List<CheckGroup> findAll() {
return checkGroupDao.findAll();
}
(4)CheckGroupDao
List<CheckGroup> findAll();
(5)CheckGroupDao.xml
<select id="findAll" resultType="com.itheima.pojo.CheckGroup">
select * from t_checkgroup
</select>
(2)图片上传功能
1.此处使用的是ElementUI提供的上传组件el-upload,提供了多种不同的上传效果,上传成功后可以进行 预览。
(1)定义模型数据,用于后面上传文件的图片预览:
imageUrl:null,//模型数据,用于上传图片完成后图片预览
(2)定义上传组件:
<!--
el-upload:上传组件
action:上传的提交地址
auto-upload:选中文件后是否自动上传
name:上传文件的名称,服务端可以根据名称获得上传的文件对象
show-file-list:是否显示已上传文件列表
on-success:文件上传成功时的钩子
before-upload:上传文件之前的钩子
-->
<el-upload
class="avatar-uploader"
action="/setmeal/upload.do"
:auto-upload="autoUpload"
name="imgFile"
:show-file-list="false"
:on-success="handleAvatarSuccess"
:before-upload="beforeAvatarUpload">
<!--用于上传图片预览-->
<img v-if="imageUrl" :src="imageUrl" class="avatar">
<!--用于展示上传图标-->
<i v-else class="el-icon-plus avatar-uploader-icon"></i>
</el-upload>
(3)定义对应的钩子函数
//文件上传成功后的钩子,response为服务端返回的值,file为当前上传的文件封装成的js对象
handleAvatarSuccess(response, file) {
this.imageUrl = "http://pqjroc654.bkt.clouddn.com/"+response.data;
this.$message({
message: response.message,
type: response.flag ? 'success' : 'error'
});
//设置模型数据(图片名称),后续提交ajax请求时会提交到后台最终保存到数据库
this.formData.img = response.data;
}
//上传文件之前的钩子
beforeAvatarUpload(file) {
const isJPG = file.type === 'image/jpeg';
const isLt2M = file.size / 1024 / 1024 < 2;
if (!isJPG) {
this.$message.error('上传套餐图片只能是 JPG 格式!');
}
if (!isLt2M) {
this.$message.error('上传套餐图片大小不能超过 2MB!');
}
return isJPG && isLt2M;
}
(4)创建SetmealController,接收上传的文件
/**
* 套餐管理
*/
@RestController
@RequestMapping("/setmeal")
public class SetmealController {
@Reference
private SetmealService setmealService;
//图片上传
@RequestMapping("/upload")
public Result upload(@RequestParam("imgFile")MultipartFile imgFile){
try{
//获取原始文件名
String originalFilename = imgFile.getOriginalFilename();
int lastIndexOf = originalFilename.lastIndexOf(".");
//获取文件后缀
String suffix = originalFilename.substring(lastIndexOf - 1);
//使用UUID随机产生文件名称,防止同名文件覆盖
String fileName = UUID.randomUUID().toString() + suffix;
QiniuUtils.upload2Qiniu(imgFile.getBytes(),fileName);
//图片上传成功
Result result = new Result(true,
MessageConstant.PIC_UPLOAD_SUCCESS);
result.setData(fileName);
return result;
}catch (Exception e){
e.printStackTrace();
//图片上传失败
return new Result(false,MessageConstant.PIC_UPLOAD_FAIL);
}
}
}
(5)注意:别忘了在spring配置文件中配置文件上传组件
<!--文件上传组件-->
<bean id="multipartResolver"
class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<property name="maxUploadSize" value="104857600" />
<property name="maxInMemorySize" value="4096" />
<property name="defaultEncoding" value="UTF-8"/>
</bean>
(3)提交请求
(1)完善页面:
当用户点击提交按钮之后 调用handAdd() 方法 发送ajax请求提交表单数据
//添加
handleAdd () {
axios.post("/setmeal/add.do?checkgroupIds=" +
this.checkgroupIds,this.formData).
then((response)=> {
this.dialogFormVisible = false;
if(response.data.flag){
this.$message({
message: response.data.message,
type: 'success'
});
}else{
this.$message.error(response.data.message);
}
}).finally(()=> {
this.findPage();
});
}
(2)后台代码
(1)Controller层
//新增
@RequestMapping("/add")
public Result add(@RequestBody Setmeal setmeal, Integer[] checkgroupIds){
try {
setmealService.add(setmeal,checkgroupIds);
}catch (Exception e){
//新增套餐失败
return new Result(false,MessageConstant.ADD_SETMEAL_FAIL);
}
//新增套餐成功
return new Result(true,MessageConstant.ADD_SETMEAL_SUCCESS);
}
(2)Service层
/**
* 体检套餐服务接口
*/
public interface SetmealService {
public void add(Setmeal setmeal, Integer[] checkgroupIds);
}
(3)服务实现类
/**
* 体检套餐服务实现类
*/
@Service(interfaceClass = SetmealService.class)
@Transactional
public class SetmealServiceImpl implements SetmealService {
@Autowired
private SetmealDao setmealDao;
//新增套餐
public void add(Setmeal setmeal, Integer[] checkgroupIds) {
setmealDao.add(setmeal);
if(checkgroupIds != null && checkgroupIds.length > 0){
//绑定套餐和检查组的多对多关系
setSetmealAndCheckGroup(setmeal.getId(),checkgroupIds);
}
}
//绑定套餐和检查组的多对多关系
private void setSetmealAndCheckGroup(Integer id, Integer[] checkgroupIds) {
for (Integer checkgroupId : checkgroupIds) {
Map<String,Integer> map = new HashMap<>();
map.put("setmeal_id",id);
map.put("checkgroup_id",checkgroupId);
setmealDao.setSetmealAndCheckGroup(map);
}
}
}
(4)Dao接口:
public interface SetmealDao {
public void add(Setmeal setmeal);
public void setSetmealAndCheckGroup(Map<String, Integer> map);
}
(5)Mapper映射文件
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.itheima.dao.SetmealDao" >
<!--新增-->
<insert id="add" parameterType="com.itheima.pojo.Setmeal">
<selectKey resultType="java.lang.Integer" order="AFTER"
keyProperty="id">
SELECT LAST_INSERT_ID()
</selectKey>
insert into t_setmeal
(code,name,sex,age,helpCode,price,remark,attention,img)
values
(#{code},#{name},#{sex},#{age},#{helpCode},#{price},#{remark},#
{attention},#{img})
</insert>
<!--绑定套餐和检查组多对多关系-->
<insert id="setSetmealAndCheckGroup" parameterType="hashmap">
insert into t_setmeal_checkgroup
(setmeal_id,checkgroup_id)
values
(#{setmeal_id},#{checkgroup_id})
</insert>
</mapper>
二.完善文件上传的功能:
前面我们已经完成了文件上传,将图片存储在了七牛云服务器中。但是这个过程存在一个问题,就是如 果用户只上传了图片而没有最终保存套餐信息到我们的数据库,这时我们上传的图片就变为了垃圾图 片。对于这些垃圾图片我们需要定时清理来释放磁盘空间。这就需要我们能够区分出来哪些是垃圾图 片,哪些不是垃圾图片。如何实现呢? 方案就是利用redis来保存图片名称,具体做法为:
1、当用户上传图片后,将图片名称保存到redis的一个Set集合中,例如集合名称为 setmealPicResources
2、当用户添加套餐后,将图片名称保存到redis的另一个Set集合中,例如集合名称为 setmealPicDbResources
3、计算setmealPicResources集合与setmealPicDbResources集合的差值,结果就是垃圾图片的名称 集合,清理这些图片即可。
实现步骤:
1.(1)在health_backend项目中提供Spring配置文件spring-redis.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/springbeans.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/springmvc.xsd
http://code.alibabatech.com/schema/dubbo
http://code.alibabatech.com/schema/dubbo/dubbo.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/springcontext.xsd">
<!--Jedis连接池的相关配置-->
<bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig">
<property name="maxTotal">
<value>200</value>
</property>
<property name="maxIdle">
<value>50</value>
</property>
<property name="testOnBorrow" value="true"/>
<property name="testOnReturn" value="true"/>
</bean>
<bean id="jedisPool" class="redis.clients.jedis.JedisPool">
<constructor-arg name="poolConfig" ref="jedisPoolConfig" />
<constructor-arg name="host" value="127.0.0.1" />
<constructor-arg name="port" value="6379" type="int" />
<constructor-arg name="timeout" value="30000" type="int" />
</bean>
</beans>
2.(2)在health_common工程中提供Redis常量类
package com.itheima.constant;
public class RedisConstant {
//套餐图片所有图片名称
public static final String SETMEAL_PIC_RESOURCES = "setmealPicResources";
//套餐图片保存在数据库中的图片名称
public static final String SETMEAL_PIC_DB_RESOURCES =
"setmealPicDbResources";
}
3.(3)完善SetmealController,在文件上传成功后将图片名称保存到redis集合中
@Autowired
private JedisPool jedisPool;
//图片上传
@RequestMapping("/upload")
public Result upload(@RequestParam("imgFile")MultipartFile imgFile){
try{
//获取原始文件名
String originalFilename = imgFile.getOriginalFilename();
int lastIndexOf = originalFilename.lastIndexOf(".");
//获取文件后缀
String suffix = originalFilename.substring(lastIndexOf - 1);
//使用UUID随机产生文件名称,防止同名文件覆盖
String fileName = UUID.randomUUID().toString() + suffix;
QiniuUtils.upload2Qiniu(imgFile.getBytes(),fileName);
//图片上传成功
Result result = new Result(true, MessageConstant.PIC_UPLOAD_SUCCESS);
result.setData(fileName);
//将上传图片名称存入Redis,基于Redis的Set集合存储
jedisPool.getResource().sadd(RedisConstant.SETMEAL_PIC_RESOURCES,fileName);
return result;
}catch (Exception e){
e.printStackTrace();
//图片上传失败
return new Result(false,MessageConstant.PIC_UPLOAD_FAIL);
}
}
4.(4)在health_service_provider项目中提供Spring配置文件applicationContext-redis.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/springbeans.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/springmvc.xsd
http://code.alibabatech.com/schema/dubbo
http://code.alibabatech.com/schema/dubbo/dubbo.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/springcontext.xsd">
<!--Jedis连接池的相关配置-->
<bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig">
<property name="maxTotal">
<value>200</value>
</property>
<property name="maxIdle">
<value>50</value>
</property>
<property name="testOnBorrow" value="true"/>
<property name="testOnReturn" value="true"/>
</bean>
<bean id="jedisPool" class="redis.clients.jedis.JedisPool">
<constructor-arg name="poolConfig" ref="jedisPoolConfig" />
<constructor-arg name="host" value="127.0.0.1" />
<constructor-arg name="port" value="6379" type="int" />
<constructor-arg name="timeout" value="30000" type="int" />
</bean>
</beans>
5.(5)完善SetmealServiceImpl服务类,在保存完成套餐信息后将图片名称存储到redis集合中\
@Autowired
private JedisPool jedisPool;
//新增套餐
public void add(Setmeal setmeal, Integer[] checkgroupIds) {
setmealDao.add(setmeal);
if(checkgroupIds != null && checkgroupIds.length > 0){
setSetmealAndCheckGroup(setmeal.getId(),checkgroupIds);
}
//将图片名称保存到Redis
savePic2Redis(setmeal.getImg());
}
//将图片名称保存到Redis
private void savePic2Redis(String pic){
jedisPool.getResource().sadd(RedisConstant.SETMEAL_PIC_DB_RESOURCES,pic);
}
三。删除检查套餐信息 根据id删除检查套餐信息 并根据套餐id 删除 与套餐关联的检查组id;
(1)页面:
deleteById(row){
this.$confirm( "您确定要删除当前数据吗" ,"提示" , {//确认框
type: 'warning'
}).then(()=>{
//用户点击了确定按钮 发送ajax请求 将检查项id 提交到Controller进行处理
axios.delete("/setmeal/delete.do?id="+row.id).then((res)=>{
if(res.data.flag){
//执行成功
//弹出提示成功消息
this.$message({
type:'success',
message:res.data.message
});
//重新查询
this.findPage();
}else{
//执行失败
this.$message.error(res.data.message);
}
}).catch((res)=>{
this.showMessage(res);
});
}).catch(()=>{
this.$message({
type:'info',
message:'操作已取消'
});
})
}
(2)后台代码:
1.Controller层:
//根据套餐id 删除套餐 并删除套餐的检查组的多对多关系表;
@DeleteMapping("/delete")
public Result delete(Integer id){
try {
setmealService.delete(id);
return new Result(true,MessageConstant.DELETE_SETMEAL_SUCCESS);
} catch (Exception e) {
e.printStackTrace();
return new Result(true,MessageConstant.DELETE_SETMEAL_FAIL);
}
}
2.Service层:
void delete(Integer id);
3.服务实现类:
@Override
//根据套餐id 删除套餐 和 清除套餐与检查组之间的多对多对应关系表
public void delete(Integer id) {
setmealDao.deleteAssocication(id);
setmealDao.delete(id);
}
4.Dao接口:
void delete(Integer id);
5.Mapper.xml:
<!-- 根据套餐id 删除 套餐与检查组之间的关系-->
<delete id="deleteAssocication">
delete from t_setmeal_checkgroup where setmeal_id = #{id}
</delete>
<!-- 根据套餐id 删除 套餐 -->
<delete id="delete">
delete from t_setmeal where id = #{id}
</delete>