fix: 攀枝花东区-缴费分支代码处理

This commit is contained in:
2025-05-15 23:21:29 +08:00
parent bafd4aa3ab
commit 6bef534d7d
1097 changed files with 12395 additions and 61340 deletions
@@ -1,154 +0,0 @@
package com.yida.data.common.excel;
import cc.mrbird.febs.common.redis.service.RedisService;
import cn.hutool.core.lang.UUID;
import cn.hutool.json.JSONUtil;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.support.ExcelTypeEnum;
import com.baomidou.mybatisplus.extension.service.IService;
import com.yida.data.common.core.entity.EasyExcelExportBaseDTO;
import com.yida.data.common.core.enums.FileDealStatusEnum;
import com.yida.data.common.core.file.IExportExcelClient;
import com.yida.data.common.core.file.common.export.ExportExcelData;
import com.yida.data.common.core.file.common.export.SelectExportData;
import com.yida.data.common.core.utils.FileUtil;
import com.yida.data.common.service.CommonService;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.StopWatch;
import java.io.File;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
/**
* 导出excel工具类
*
* @author ZYJ
* @date 2023/10/19 16:49
*/
@Data
@Slf4j
@AllArgsConstructor
public abstract class DefaultExportExcelClient<T extends SelectExportData, R extends EasyExcelExportBaseDTO, O, BaseService extends IService<O>>
implements IExportExcelClient<T> {
/**
* 导出的service层
*/
protected final BaseService baseService;
protected final RedisService redisService;
protected final CommonService commonService;
protected final String exportCacheKey;
protected final String uploadUrl;
public Class<R> getClassR() {
Type sType = getClass().getGenericSuperclass();
Type[] generics = ((ParameterizedType) sType).getActualTypeArguments();
return (Class<R>) (generics[1]);
}
/**
* 查询excel 导出需要的数据
*
* @param t 查询条件
* @return java.util.List<O>
* @author ZYJ
* @date 2023/12/12 16:54
*/
public abstract List<O> selectExportData(T t);
/**
* 处理单条数据
*
* @param o 需要处理的数据
* @return R
* @author ZYJ
* @date 2023/12/13 13:58
*/
public abstract R handleSingleData(O o);
@Override
public void exportExcelData(T t) {
File file = null;
try {
StopWatch stopWatch = new StopWatch();
stopWatch.start();
// 生成导出成功excel文件名
String fileName = FileUtil.getLocalUploadAddress() + UUID.randomUUID() + ".xls";
// 查询需要导出的文件信息
List<O> dataList = this.selectExportData(t);
// 添加处理总数量
redisService.hset(this.exportCacheKey, t.getKey(), ExportExcelData.builder()
.key(t.getKey())
.exportStatus(FileDealStatusEnum.DEALING.getStatus())
.total(dataList.size())
.finish(0)
.build());
// 处理数据
List<R> list = new ArrayList<>();
// 完成数量
int finishNumber = 0;
for (O o : dataList) {
try {
R r = this.handleSingleData(o);
list.add(r);
} catch (Exception e) {
log.error("{}导出错误: {}", t.getFunctionName(), JSONUtil.toJsonStr(o));
} finally {
finishNumber += 1;
redisService.hset(this.exportCacheKey, t.getKey(), ExportExcelData.builder()
.key(t.getKey())
.exportStatus(FileDealStatusEnum.DEALING.getStatus())
.total(dataList.size())
.finish(finishNumber)
.build());
}
}
// 导出数据
file = new File(fileName);
EasyExcel.write(file, getClassR())
.excelType(ExcelTypeEnum.XLS)
.sheet("数据导出")
.doWrite(list);
// 上传文件到媒资
String fileUrl = FileUtil.uploadFileToMediaServer(uploadUrl, file);
// 处理完成
ExportExcelData exportExcelData = ExportExcelData.builder()
.key(t.getKey())
.exportStatus(FileDealStatusEnum.DEAL_SUCCESS.getStatus())
.fileName(fileName)
.total(dataList.size())
.finish(finishNumber)
.filePath(fileUrl)
.build();
redisService.hset(this.exportCacheKey, t.getKey(), exportExcelData);
// 添加处理时间
stopWatch.stop();
log.info("{}数据总共耗时: {}", t.getFunctionName(), stopWatch.getTotalTimeSeconds() + "");
} catch (Exception e) {
log.error("{}导出失败", t.getFunctionName(), e);
// 添加处理失败的结果
redisService.hset(this.exportCacheKey, t.getKey(), ExportExcelData.builder()
.key(t.getKey())
.exportStatus(FileDealStatusEnum.DEAL_FAIL.getStatus())
.build());
} finally {
if (Objects.nonNull(file)) {
cn.hutool.core.io.FileUtil.del(file);
}
}
}
@Override
public Object selectExportInfo(String key) {
return redisService.hget(exportCacheKey, key);
}
}
@@ -1,285 +0,0 @@
package com.yida.data.common.excel;
import cc.mrbird.febs.common.redis.service.RedisService;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.support.ExcelTypeEnum;
import com.baomidou.mybatisplus.extension.service.IService;
import com.yida.data.common.core.entity.constant.CachePrefixConstant;
import com.yida.data.common.core.enums.FileDealStatusEnum;
import com.yida.data.common.core.file.IExportLargeClient;
import com.yida.data.common.core.file.common.DownloadFileChunk;
import com.yida.data.common.core.file.common.export.ExportLargeData;
import com.yida.data.common.core.file.common.export.SelectExportData;
import com.yida.data.common.core.exception.FebsException;
import com.yida.data.common.core.utils.file.ChunkUtil;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.util.StopWatch;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.file.Files;
import java.util.*;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
/**
* 导出大文件工具类
* zip文件
*
* @author ZYJ
* @date 2023/10/19 16:49
*/
@Data
@Slf4j
@AllArgsConstructor
public abstract class DefaultExportLargeClient<T extends SelectExportData, O, BaseService extends IService<O>>
implements IExportLargeClient<T> {
/**
* 导出的service层
*/
protected final BaseService baseService;
protected final RedisService redisService;
protected final String exportCacheKey;
protected final String uploadUrl;
/**
* 查询大文件导出需要的数据
*
* @param t 查询条件
* @return java.util.Map<java.lang.String, java.lang.String>
* @author ZYJ
* @date 2023/10/20 16:09
*/
public abstract Map<String, String> selectExportData(T t);
@Override
public void exportLargeData(T t) {
// 查询需要导出的文件信息
Map<String, String> map = this.selectExportData(t);
// zip文件
File file = null;
// 错误信息文件
File errorFile = null;
try {
StopWatch stopWatch = new StopWatch();
stopWatch.start();
// 生成的文件名称
String fileName = com.yida.data.common.core.utils.FileUtil.getLocalUploadAddress() + t.getKey() + ".zip";
file = new File(fileName);
ZipOutputStream zos = new ZipOutputStream(Files.newOutputStream(file.toPath()));
// 添加处理总数量
redisService.hset(this.exportCacheKey, t.getKey(), ExportLargeData.builder()
.key(t.getKey())
.exportStatus(FileDealStatusEnum.DEALING.getStatus())
.total(map.size())
.finish(0)
.build());
// 完成数量
int finishNumber = 0;
// 错误数量
int errorNumber = 0;
// 是否完成流程
boolean flag;
// 错误信息
Map<String, String> errorMap = new HashMap<>();
for (Map.Entry<String, String> entry : map.entrySet()) {
flag = true;
String name = "";
String fileUrl = "";
try {
// 文件名称
name = entry.getKey();
// log.info("处理数据: {}", name);
// 文件地址
fileUrl = entry.getValue();
// 下载文件
URL url = new URL(fileUrl);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
String message = connection.getHeaderField(0);
if (StringUtils.isNotEmpty(message)) {
if (message.startsWith("HTTP/1.1 404")) {
flag = false;
// 添加错误数据
errorMap.put(name, fileUrl);
errorNumber += 1;
finishNumber += 1;
redisService.hset(this.exportCacheKey, t.getKey(), ExportLargeData.builder()
.key(t.getKey())
.exportStatus(FileDealStatusEnum.DEALING.getStatus())
.total(map.size())
.finish(finishNumber)
.error(errorNumber)
.build());
continue;
}
zos.putNextEntry(new ZipEntry(name + ".jpg"));
InputStream fis = connection.getInputStream();
byte[] buffer = new byte[1024];
int r = 0;
while ((r = fis.read(buffer)) != -1) {
zos.write(buffer, 0, r);
}
fis.close();
}
} catch (Exception e) {
flag = false;
// 添加错误数据
if (StrUtil.isNotBlank(name) && StrUtil.isNotBlank(fileUrl)) {
errorMap.put(name, fileUrl);
}
errorNumber += 1;
finishNumber += 1;
redisService.hset(this.exportCacheKey, t.getKey(), ExportLargeData.builder()
.key(t.getKey())
.exportStatus(FileDealStatusEnum.DEALING.getStatus())
.total(map.size())
.finish(finishNumber)
.error(errorNumber)
.build());
} finally {
if (flag) {
finishNumber += 1;
redisService.hset(this.exportCacheKey, t.getKey(), ExportLargeData.builder()
.key(t.getKey())
.exportStatus(FileDealStatusEnum.DEALING.getStatus())
.total(map.size())
.finish(finishNumber)
.error(errorNumber)
.build());
}
}
}
zos.flush();
zos.close();
stopWatch.stop();
// 处理错误数据
String errorFileUrl = "";
if (CollUtil.isNotEmpty(errorMap)) {
// 表头list的生成,实际的表头信息可以从数据库或者缓存等处动态读取
List<List<String>> allColList = new ArrayList<>();
// 姓名表头
allColList.add(CollUtil.newArrayList("名称"));
// 校区表头
allColList.add(CollUtil.newArrayList("地址"));
// 处理错误数据
List<List<String>> exportErrorDataList = new ArrayList<>();
errorMap.forEach((k, v) -> exportErrorDataList.add(CollUtil.newArrayList(k, v)));
String errorFileName = com.yida.data.common.core.utils.FileUtil.getLocalUploadAddress() + t.getKey() + ".xls";
errorFile = new File(errorFileName);
// 导出错误数据
EasyExcel.write(errorFile)
.excelType(ExcelTypeEnum.XLS)
// 这里放入动态头
.head(allColList).sheet("错误信息")
// 当然这里数据也可以用 List<List<String>> 去传入
.doWrite(exportErrorDataList);
// 上传文件到媒资
errorFileUrl = com.yida.data.common.core.utils.FileUtil.uploadFileToMediaServer(uploadUrl, errorFile);
}
// 处理完成
ExportLargeData exportLargeData = ExportLargeData.builder()
.key(t.getKey())
.exportStatus(FileDealStatusEnum.DEAL_SUCCESS.getStatus())
.fileName(fileName)
.fileSize(new File(fileName).length())
.total(map.size())
.finish(finishNumber)
.error(errorNumber)
.build();
if (StrUtil.isNotBlank(errorFileUrl)) {
exportLargeData.setErrorFilePath(errorFileUrl);
}
redisService.hset(this.exportCacheKey, t.getKey(), exportLargeData);
log.info("导出照片数据总共耗时: {}", stopWatch.getTotalTimeSeconds() + "");
} catch (Exception e) {
log.error("导出大文件失败", e);
// 添加处理失败的结果
redisService.hset(this.exportCacheKey, t.getKey(), ExportLargeData.builder()
.key(t.getKey())
.exportStatus(FileDealStatusEnum.DEAL_FAIL.getStatus())
.build());
// 删除本地zip文件
if (Objects.nonNull(file)) {
FileUtil.del(file);
}
} finally {
// 删除本地错误信息文件
if (Objects.nonNull(errorFile)) {
FileUtil.del(errorFile);
}
}
}
@Override
public Object selectExportInfo(String key) {
return redisService.hget(exportCacheKey, key);
}
@Override
public void downLoadChunk(DownloadFileChunk dto, HttpServletResponse response) {
// 生成的文件信息
File resultFile = null;
Integer index = null;
Integer chunkTotal = null;
try {
// 获取缓存信息
ExportLargeData exportLargeData = (ExportLargeData) redisService.hget(this.exportCacheKey, dto.getKey());
String fileName = exportLargeData.getFileName();
String[] splits = fileName.split("\\.");
String type = splits[splits.length - 1];
String resultFileName = com.yida.data.common.core.utils.FileUtil.getLocalUploadAddress() + dto.getKey() + "." + type;
// 生成的分片文件
resultFile = new File(resultFileName);
// 分片信息
Integer chunkSize = dto.getChunkSize();
index = dto.getIndex();
chunkTotal = dto.getChunkTotal();
long offset = (long) chunkSize * (index - 1);
if (Objects.equals(index, chunkTotal)) {
offset = resultFile.length() - chunkSize;
}
byte[] chunk = ChunkUtil.getChunk(index, chunkSize, resultFileName, offset);
log.info("下载文件分片" + resultFileName + "," + index + "," + chunkSize + "," + chunk.length + "," + offset);
// response.addHeader("Access-Control-Allow-Origin","Content-Disposition");
response.addHeader("Content-Disposition", "attachment;filename=" + fileName);
response.addHeader("Content-Length", String.valueOf(chunk.length));
// response.setHeader("filename", fileName);
response.setContentType("application/octet-stream");
ServletOutputStream out = response.getOutputStream();
out.write(chunk);
out.flush();
out.close();
} catch (Exception e) {
log.error("下载分片失败", e);
throw new FebsException("下载分片失败");
} finally {
if (Objects.nonNull(resultFile) && Objects.nonNull(index)
&& Objects.nonNull(chunkTotal) && index.equals(chunkTotal)) {
FileUtil.del(resultFile);
}
}
}
}