1. 导入Excel表格
Java后端代码
一、导入easyExcel的jar包依赖
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>easyexcel</artifactId>
<version>2.2.3</version>
</dependency>
二、创建对应的数据模型,字段需求相同时,可复用
import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.annotation.write.style.ColumnWidth;
import com.alibaba.excel.annotation.write.style.ContentRowHeight;
import com.alibaba.excel.annotation.write.style.HeadRowHeight;
import lombok.Data;
@ContentRowHeight(26)
@HeadRowHeight(30)
@Data
public class DrugsDTO {
@ColumnWidth(16)
@ExcelProperty(value = "药品编码")
private String drugsCode;
@ColumnWidth(26)
@ExcelProperty(value = "药品名称")
private String drugsName;
@ColumnWidth(18)
@ExcelProperty(value = "药品规格")
private String drugsFormat;
@ColumnWidth(14)
@ExcelProperty(value = "药品剂型")
private String drugsDosage;
@ColumnWidth(14)
@ExcelProperty(value = "药品类型")
private String drugsType;
@ColumnWidth(14)
@ExcelProperty(value = "药品单价")
private Double drugsPrice;
@ColumnWidth(18)
@ExcelProperty(value = "拼音助记码")
private String mnemonicCode;
@ColumnWidth(14)
@ExcelProperty(value = "包装单位")
private String drugsUnit;
}
三、创建读取excel表格的监听器
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import lombok.extern.slf4j.Slf4j;
import org.neuedu.entity.HisDrugs;
import org.neuedu.entity.dto.DrugsDTO;
import org.neuedu.service.IHisConstantCategoryService;
import org.neuedu.service.IHisDrugsService;
import org.springframework.beans.BeanUtils;
import java.util.ArrayList;
import java.util.List;
@Slf4j
public class DrugsDataListener extends AnalysisEventListener<DrugsDTO> {
private IHisConstantCategoryService constantCategoryService;
private IHisDrugsService drugsService;
public DrugsDataListener(IHisConstantCategoryService constantCategoryService,IHisDrugsService drugsService){
this.constantCategoryService = constantCategoryService;
this.drugsService = drugsService;
}
private static final Integer BATCH_COUNT = 1000;
List<HisDrugs> list = new ArrayList<>();
@Override
public void invoke(DrugsDTO drugsDTO, AnalysisContext analysisContext) {
log.debug("读取的行数据:{}",drugsDTO);
HisDrugs drugs = new HisDrugs();
Integer drugsDosageId = constantCategoryService.getIdByConstantCategoryName(drugsDTO.getDrugsDosage());
if(drugsDosageId != -1){
drugs.setDrugsDosageId(drugsDosageId);
}
Integer drugsTypeId = constantCategoryService.getIdByConstantCategoryName(drugsDTO.getDrugsType());
if(drugsTypeId != -1){
drugs.setDrugsTypeId(drugsTypeId);
}
BeanUtils.copyProperties(drugsDTO,drugs);
list.add(drugs);
if(list.size() >= BATCH_COUNT){
this.saveData();
list.clear();
}
}
public void saveData(){
log.debug("开始执行批量插入~");
drugsService.saveBatch(list);
log.debug("批量插入执行完毕~");
}
@Override
public void doAfterAllAnalysed(AnalysisContext analysisContext) {
if(list.size() > 0){
this.saveData();
}
log.debug("所有数据解析完成!");
}
}
四、Controller前端控制器代码
@ApiOperation("非药品目录Excel文件导入")
@ApiImplicitParam(name = "file",value = "excel文档",required = true)
@PostMapping("/fileUpload")
public ResponseEntity excelImport(MultipartFile file) throws Exception{
EasyExcel
.read(file.getInputStream(), DrugsDTO.class, new DrugsDataListener(constantCategoryService,drugsService))
.sheet()
.doRead();
return ResponseEntity.ok("非药品目录导入成功");
}
vue前端代码
五、axios异步请求的统一处理httpAxios.js
在判断请求方式为post或put的基础上,增加了文件上传的判断
import axios from 'axios'
import qs from 'qs'
import router from "@/router"
import {Loading,Message} from 'element-ui'
axios.defaults.timeout = 5000;
axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded;charset=UTF-8'
axios.defaults.baseURL = '/api';
let loadingInstance;
axios.interceptors.request.use(request => {
console.log("开始请求:",request.url,",参数:",JSON.stringify(request.params));
loadingInstance = Loading.service({
lock: true,
text: '数据加载中,请稍后...',
spinner: 'el-icon-loading',
background: 'rgba(0, 0, 0, 0.7)'
});
if (request.method === 'post' || request.method === 'put') {
let currentUrl = request.url.split('/')[request.url.split('/').length-1];
if(currentUrl !== 'fileUpload'){
request.data = qs.stringify(request.data)
}
}
if(request.method === 'get'){
let curUrl = request.url.split('/')[request.url.split('/').length - 1];
if(curUrl === 'downLoad'){
request.responseType = 'blob';
return request;
}
}
return request;
},err => {
loadingInstance.close();
Message.error('请求超时!');
return Promise.reject(err)
}
);
axios.interceptors.response.use(response => {
console.log("请求完毕数据:",response.data);
loadingInstance.close();
if(response.config.responseType === 'blob'){
let blob = new Blob([response.data],{type:'application/vnd.ms-excel;charset=utf-8'});
let downloadElement = document.createElement('a');
let href = window.URL.createObjectURL(blob);
downloadElement.href = href;
downloadElement.download = decodeURI(response.headers['content-disposition'].split('=')[1]);
document.body.appendChild(downloadElement);
downloadElement.click();
document.body.removeChild(downloadElement);
window.URL.revokeObjectURL(href);
return;
}
if (response.data.code === 200) {
return response.data
}else if (response.data.code === 504) {
Message.error('服务器被吃了⊙﹏⊙∥');
} else if(response.data.code === 404){
Message.error('请求地址不存在!');
router.replace({path:'/404'})
}else if (response.data.code === 403) {
Message.error('权限不足,请联系管理员!');
router.replace({path:'/403'})
} else if (response.data.code === 401) {
router.replace({
path: '/login',
query: {
redirect: router.currentRoute.fullPath
}
});
}else{
}
return response.data
},err => {
loadingInstance.close();
Message.error('请求失败,请稍后再试');
return Promise.reject(err)
}
);
let http = {
get(url, params = {}){
return axios.get(url, {params})
},
post(url, params = {}){
return axios.post(url, params)
},
del(url, params = {}){
return axios.delete(url, {params})
},
put(url, params = {}){
return axios.put(url, params)
},
upload(url, params = {}){
return axios.post(url, params,{
headers: {
'Content-Type': 'multipart/form-data'
}
})
}
};
export default http;
六、具体发请求的drugs.js
import http from './httpAxios';
export default {
importExcel(file){
return http.upload('/his-drugs/fileUpload',file);
}
}
七、js的路由index.js
import drugs from './drugs.js';
export default {
drugs,
}
八、vue部分,Drugs.vue
<template>
<div id="drugs">
<div class="container">
<!-- 导入导出部分 -->
<el-form :inline="true" :model="query" class="demo-form-inline" size="mini">
<el-form-item>
<el-input v-model="query.search" clearable placeholder="药品编码/名称/拼音助记码"></el-input>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="pageSearchHandler" icon="el-icon-search">查询</el-button>
<!-- 根据查询结果导出查询出来所有的数据 -->
<el-button type="info" @click="exportPageHandler" icon="el-icon-download">导出</el-button>
</el-form-item>
<el-form-item>
<!--
action:上传的地址,这里我们通过axios 进行代理,不直接写
http-request:覆盖默认的上传行为,可以自定义上传的实现
show-file-list:是否显示已上传的文件列表
-->
<el-upload action="" :http-request="importHandler" :show-file-list="false">
<el-button type="info" icon="el-icon-upload2">导入</el-button>
</el-upload>
</el-form-item>
</el-form>
</div>
</div>
</template>
<script>
export default {
name: 'Drugs',
data(){
return {
query:{
search: '', //查询条件:药品编码 或 药品名称 或 拼音助记码
}
}
},
methods:{
// 导入,这里会自动把上传的文件带过来
importHandler(data){
// - 通过异步的形式上传文件,需要模拟表单的形式
//创建表单对象
let form = new FormData();
//后端接收参数,可以接收多个参数
form.append('file',data.file);
this.$api.drugs.importExcel(form).then(res=>{
//提示信息
if(res.code === 200){
this.$message.success(res.msg);
//重新加载数据
this.pageSearchHandler();
}
});
}
}
};
</script>
<style scoped>
</style>
2.导出excel表格
后端Java部分
一、和导入excel的操作相同的部分,导入jar包相同,数据模型drugsDTO复用
二、使用MyBatisPlus 的条件构造器,在Mapper接口中编写方法
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.toolkit.Constants;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import org.neuedu.entity.HisDrugs;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.neuedu.entity.dto.DrugsDTO;
import java.util.List;
public interface HisDrugsMapper extends BaseMapper<HisDrugs> {
@Select("SELECT drugs_code,drugs_name,drugs_format,\n" +
"(select constant_name from his_constant_category where id = his_drugs.drugs_dosage_id) drugs_dosage,\n" +
"(select constant_name from his_constant_category where id = his_drugs.drugs_type_id) drugs_type,\n" +
"drugs_price,mnemonic_code,drugs_unit FROM his_drugs ${ew.customSqlSegment}")
List<DrugsDTO> excelExport(@Param(Constants.WRAPPER) Wrapper<DrugsDTO> wrapper);
}
三、在service中编写对应的方法接口
import org.neuedu.entity.HisDrugs;
import com.baomidou.mybatisplus.extension.service.IService;
import org.neuedu.entity.dto.DrugsDTO;
import java.util.List;
public interface IHisDrugsService extends IService<HisDrugs> {
List<DrugsDTO> excelExport(String search);
}
四、在service实现类中实现方法,并完成条件构造的逻辑
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import org.neuedu.entity.HisDrugs;
import org.neuedu.entity.dto.DrugsDTO;
import org.neuedu.mapper.HisDrugsMapper;
import org.neuedu.service.IHisDrugsService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class HisDrugsServiceImpl extends ServiceImpl<HisDrugsMapper, HisDrugs> implements IHisDrugsService {
@Override
public List<DrugsDTO> excelExport(String search) {
QueryWrapper<DrugsDTO> wrapper = new QueryWrapper<>();
wrapper.like(StringUtils.isNotBlank(search),"drugs_code",search)
.or()
.like(StringUtils.isNotBlank(search),"drugs_name",search)
.or()
.like(StringUtils.isNotBlank(search),"mnemonic_code",search)
.eq("del_mark",0);
return baseMapper.excelExport(wrapper);
}
}
五、Controller前端控制器的编写
@ApiOperation("非药品目录导出")
@ApiImplicitParam(name = "search",value = "查询条件:药品编码 或 药品名称 或 拼音助记码")
@GetMapping("/downLoad")
public void excelExport(HttpServletResponse response, String search) throws Exception{
List<DrugsDTO> list = drugsService.excelExport(search);
response.setContentType("application/vnd.ms-excel;charset=utf-8");
String fileName = URLEncoder.encode("非药品目录-" + LocalDate.now().toString(), "utf-8");
response.setHeader("Content-disposition","attachment;filename=" + fileName + ".xlsx");
EasyExcel.write(response.getOutputStream(),DrugsDTO.class)
.sheet("非药品目录")
.doWrite(list);
}
前端部分代码
六、在httpAxios.js中判断为get请求之后,再判断是否为文件下载;下载的时候需要通过创建下载链接来操作,把下载的 blob 数据转为 excel,上面代码已经展示出来了
七、具体发请求的drugs.js
import http from './httpAxios';
export default {
excelExport(search){
return http.get('his-drugs/downLoad',search);
}
}
八、drugs.vue文件中js使用
methods:{
exportPageHandler(){
console.log(this.query.search);
this.$api.drugs.excelExport({search:this.query.search});
}
},