java
<el-upload
v-model:file-list="fileList"
:action="app.api+'/student/student/import'"
:headers="{
// 'Content-Type': 'multipart/form-data;boundary=----split-boundary', 此处切记不要加,否则会造成后端报错 Required request part 'file' is not present
'token':token
}"
name="file"//此处默认为file
class="upload-demo"
@on-success="handleSuccess"
:on-error="handleAvatarSuccess"
:limit="3"
:on-progress="beforeAvatarUpload"
>
<!--:auto-upload="false"-->
<!-- :http-request="replaceRes"-->
<span v-if="jinDu">
<el-progress style="width: 245px; height: 19px" :text-inside="true" :stroke-width="20"
:percentage="percentage"/>
</span>
<span v-if="isUpload" style="color: #59c2c7;cursor:pointer;"
@click="uploadChangeValue">导入学生学籍信息</span>
<template #tip>
<span style="color: #ff8282; margin-left: 20px">{{ importText }}</span>
</template>
</el-upload>
<script lang="ts" setup>
//此处后端穿了一个流给前端,所以需要解析一下,然后赋值给一个按钮,在点击时候才下载!!!
const handleSuccess = (response: any) => {
console.log(response)
if (Object.values(response.headers)[0] == 'application/vnd.ms-excel;charset=UTF-8') {
const url = window.URL.createObjectURL(new Blob([response.data]));
// 创建a标签,并隐藏a标签
let link = document.createElement('a')
link.style.display = 'none'
// a标签的href属性指定下载链接
link.href = url
//setAttribute() 方法添加指定的属性,并为其赋指定的值
// 后缀格式.csv/.xsls要和需要和后端返回格式相同,这里以.csv为例
link.setAttribute('download', '文件名称.xlsx')
document.body.appendChild(link)
link.click()
document.body.removeChild(link)
}
};
//此处用于实时监听进度条进度
const beforeAvatarUpload = (event: any) => {
let loadProgress = Math.floor(event.percent); //这就是当前上传的进度
//可以进行其他逻辑
percentage.value = loadProgress;
importText.value = "学籍信息导入中......";
if (percentage.value == 100) {
importText.value = "学籍导入成功!"
}
};
</script>
java
@PostMapping("import")
@ApiOperation("导入")
@RequiresPermissions("student:student:import")
@ApiImplicitParam(name = "file", value = "文件", paramType = "query", dataType = "file")
public void importExcel(@RequestParam("file") MultipartFile file, HttpServletResponse response) throws Exception {
UserDetail userDetail = SecurityUser.getUser();
//保存所有的表单信息、如果表达有错误、将返回给客户端
if (userWithErrorListInMap == null) {
userWithErrorListInMap = new HashMap<>();
}
//每次都清空数据
userWithErrorListInMap.put(userDetail.getId(), new ArrayList<>());
ZsRef<Boolean> hasError = new ZsRef<>();
new ExcelServiceListener<StudentExcel, StudentEntity>(studentService, file.getInputStream()) {
private List<RegionEntity> regionList;
/**
* 地区编码 去掉末尾的数字0, 用于判断权限
*/
private String userRegionCodeForPermission;
private SchoolEntity schoolForPermission;
@Override
public void invoke(StudentExcel data, AnalysisContext context) {
if (regionList == null) {
regionList = regionService.selectList(new HashMap<>());
}
if (userDetail.getRegionCode() != null) {
//去掉地区编码后面的0
userRegionCodeForPermission = userDetail.getRegionCode().replaceAll("0+?$", "");
}
if (userDetail.getSchoolCode() != null) {
schoolForPermission = schoolService.selectByParams("schoolCode", userDetail.getSchoolCode());
}
// 校验姓名
if (data.getName() == null) {
hasError.value = true;
data.setName(data.getName() + "##名字不能为空, 长度最多四汉字");
}
// 校验性别
if (data.getGender() == 2) {
hasError.value = true;
data.setGenderStr(data.getGenderStr() + "##性别只能是(男、女)中的一个");
}
// 校验身份证号
if (isEmpty(data.getIdCard()) || data.getIdCard().length() != 18) {
hasError.value = true;
data.setName(data.getName() + "##身份证长度18位");
}
if (isEmpty(data.getNation())) {
hasError.value = true;
data.setNation(data.getNation() + "##民族不能为空");
}
// ************************ 校验地区 *********************************
// 判断地区表中是否包含含这一项
RegionEntity region1 = null, region2 = null;
for (RegionEntity item : regionList) {
if (data.getRegion1() != null && data.getRegion1().contains(item.getName())) {
region1 = item;
}
if (data.getRegion2() != null && data.getRegion2().contains(item.getName())) {
region2 = item;
}
}
// RegionEntity region = regionList.stream().filter(r -> r.getName().contains(data.getRegion())).findFirst().orElse(null);
if (region1 == null) {
hasError.value = true;
data.setRegion1(data.getRegion1() + "##城市不存在");
}
if (region2 == null) {
if (data.getRegion1().contains("济源")) {
//济源没有区县
} else {
hasError.value = true;
data.setRegion2(data.getRegion2() + "##区县不存在");
}
}
if (region1 != null && region2 != null) {
data.setRegionCode(region2.getCode());
//判断地区和学校 是否具备权限
if (isNotEmpty(userDetail.getRegionCode())) {
if (String.valueOf(data.getRegionCode()).startsWith(userRegionCodeForPermission)) {
//具备权限
} else {
hasError.value = true;
data.setRegion2(data.getRegion2() + "##不具备该地区的权限");
}
}
}
//判断是否具备该学校的权限
if (isNotEmpty(userDetail.getSchoolCode())) {
if (isEquals(schoolForPermission.getName(), data.getSchoolName())) {
//具备权限
} else {
hasError.value = true;
data.setSchoolName(data.getSchoolName() + "##不具备该学校的权限");
}
} else {
//不需要判断学校权限
}
if (isEquals(hasError.value, true)) {
userWithErrorListInMap.get(userDetail.getId()).add(data);
} else {
//没有错误的才添加
super.list.add(data);
}
}
@Override
public void doAfterAllAnalysed(AnalysisContext context) {
if (isEquals(hasError.value, true)) {
// 有错误, 不入库
} else {
studentService.saveStudentWidthSchoolAndClass(super.list);
}
}
}.start(2);
if (Objects.equals(hasError.value, true)) {
String errorFileName = file.getOriginalFilename().replace(".xlsx", "错误提示.xlsx");
export(response, errorFileName, userWithErrorListInMap.get(userDetail.getId()));
} else {
PrintWriter pw = response.getWriter();
//逻辑删除导入学籍时学籍不存在的学校班级(当前学期)
schoolService.deleteBySchoolCode();
gradeClassService.deleteByClassCode();
//恢复导入学籍时学籍存在但逻辑删除的学校班级(当前学期)
schoolService.updateBySchoolCode();
gradeClassService.updateByClassCode();
pw.write(ZsJson.toJson(new Result<>()));
pw.close();
}
System.out.println("excel解析完成");
}
下载一个后端返回的流文件
java
const downLoadExport=()=>{
axios({
method: 'post',
url: baseUrl+"/electric/electricassets/download/assets",
headers: {
"Content-Type": "application/json;charset=UTF-8",
"token":getToken()
},
responseType: 'blob'
}).then(response => {
if (Object.values(response.headers)[0]=='application/vnd.ms-excel;charset=UTF-8'){
const url = window.URL.createObjectURL(new Blob([response.data]));
// 创建a标签,并隐藏a标签
let link = document.createElement('a')
link.style.display = 'none'
// a标签的href属性指定下载链接
link.href = url
//setAttribute() 方法添加指定的属性,并为其赋指定的值
// 后缀格式.csv/.xsls要和需要和后端返回格式相同,这里以.csv为例
link.setAttribute('download', '文件名称.xlsx')
document.body.appendChild(link)
link.click()
document.body.removeChild(link)
}
})
}