package com.boman.file.service; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import com.alibaba.fastjson.TypeReference; import com.boman.common.core.utils.SecurityUtils; import com.boman.common.core.utils.ServletUtils; import com.boman.common.core.utils.obj.ObjectUtils; import com.boman.common.core.utils.poi.ExcelUtil; import com.boman.common.redis.RedisKey; import com.boman.common.redis.service.RedisService; import com.boman.domain.*; import com.boman.domain.constant.CacheConstants; import com.boman.domain.constant.MaskConstant; import com.boman.domain.dto.AjaxResult; import com.boman.domain.dto.ExportExcelDto; import com.boman.domain.dto.FormDataDto; import com.boman.domain.dto.ImportExcelDto; import com.boman.domain.utils.CamelLowerUnderScore; import com.boman.domain.utils.ThreadPoolService; import com.boman.file.utils.FileUploadUtils; import com.boman.system.api.RemoteDeptService; import com.boman.system.api.model.LoginUser; import com.boman.web.core.api.RemoteAttendanceService; import com.boman.web.core.api.RemoteObjService; import com.boman.web.core.api.RemoteVaccineInfoService; import com.google.common.base.CaseFormat; import org.apache.commons.beanutils.BeanUtils; import org.apache.commons.lang3.BooleanUtils; import org.apache.http.impl.client.HttpClients; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Value; import org.springframework.cloud.context.config.annotation.RefreshScope; import org.springframework.context.annotation.Primary; import org.springframework.stereotype.Service; import org.springframework.web.client.RestTemplate; import org.springframework.web.multipart.MultipartFile; import javax.annotation.Resource; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.lang.reflect.InvocationTargetException; import java.util.*; import java.util.concurrent.TimeUnit; import static com.boman.common.core.utils.obj.ObjectUtils.*; /** * 本地文件存储 * * @author ruoyi */ @Primary @Service @RefreshScope public class LocalSysFileServiceImpl implements ISysFileService { private static final Logger LOGGER = LoggerFactory.getLogger(LocalSysFileServiceImpl.class); public static final String DOWNLOADING = "downloading"; @Resource private RemoteObjService remoteObjService; @Resource private RedisService redisService; @Resource private RemoteAttendanceService remoteAttendanceService; @Resource private RemoteVaccineInfoService remoteVaccineInfoService; @Resource private RemoteDeptService remoteDeptService; /** * 资源映射路径 前缀 */ @Value("${file.prefix}") public String localFilePrefix; /** * 域名或本机访问地址 */ @Value("${file.domain}") public String domain; /** * 上传文件存储在本地的根路径 */ @Value("${file.path}") private String localFilePath; /******************************* 考勤表中的常量 *******************************/ public static final String USERNAME= "userName"; public static final String DEPT_NAME= "deptName"; public static final String ATTENDANCE_TABLE_LEAVE_OR_SUM= "attendanceTableLeaveOrSum"; public static final String ATTENDANCE_TABLE_LATE_SUM= "attendanceTableLateSum"; public static final String ATTENDANCE_TABLE_LEAVE_SUM= "attendanceTableLeaveSum"; public static final String DATE= "date"; /** * 本地文件上传接口 * * @param file 上传的文件 * @return 访问地址 * @throws Exception */ @Override public String uploadFile(MultipartFile file) throws Exception { String name = FileUploadUtils.upload(localFilePath, file); String url = domain + localFilePrefix + name; LOGGER.info("上传的路径为: {}", url); return url; } /** * 功能描述: 上传base64 * * @param base64 base64 * @return java.lang.String */ @Override public String uploadFileBase64(String base64) throws IOException { MultipartFile multipartFile = FileUploadUtils.base64ToMultipart(base64); String name = FileUploadUtils.upload(localFilePath, multipartFile); String path = domain + localFilePrefix + name; LOGGER.info("上传的路径为: {}", path); return path; } /** * 功能描述: 通用的导入接口 * * @param multipartFile multipartFile * @param tableName tableName * @return java.util.List */ @Override public AjaxResult importExcelCommon(MultipartFile multipartFile, String tableName) throws Exception { Objects.requireNonNull(multipartFile, "multipartFile is empty"); ObjectUtils.requireNonNull(tableName, "tableName is empty"); GenTable genTable = redisService.getCacheObject(RedisKey.TABLE_INFO + tableName); List columns = genTable.getColumns(); ExcelUtil util = new ExcelUtil<>(JSONObject.class); List list = util.importCommonExcel("", multipartFile.getInputStream(), columns); ImportExcelDto dto = new ImportExcelDto(); dto.setDataList(list); dto.setTableName(tableName); return remoteObjService.importCommonData(dto); } /** * 功能描述: 通用的导出接口 * * @param response response * @param dto tableName * empty(true=>只带表头的excel,不含数据, false=>带数据的excel) * condition 查询条件 * @return com.boman.domain.dto.AjaxResult */ @Override public AjaxResult exportExcelCommon(HttpServletResponse response, ExportExcelDto dto) { String tableName = dto.getTableName(); Boolean empty = dto.getEmpty(); ObjectUtils.requireNonNull(tableName, "exportExcelCommon tableName is empty"); ObjectUtils.requireNonNull(empty, "exportExcelCommon empty is empty"); GenTable genTable = redisService.getCacheObject(RedisKey.TABLE_INFO + tableName); List columns = genTable.getColumns(); columns = ExcelUtil.filterData(columns, 4, MaskConstant.LIST_VISIBLE::equals); ExcelUtil util = new ExcelUtil<>(JSONObject.class); List> list; if (BooleanUtils.isTrue(empty)) { list = new ArrayList<>(0); } else { list = getData(dto, tableName, columns); } try { util.exportExcelCommon(response, list, "sheet1", columns, empty, false); } catch (IOException e) { e.printStackTrace(); } return null; } /** * 功能描述: 通用的导出接口 * * @param response response * @param dto tableName * empty(true=>只带表头的excel,不含数据, false=>带数据的excel) * condition 查询条件 * @return com.boman.domain.dto.AjaxResult */ @Override public AjaxResult asyncExportExcelCommon(HttpServletRequest request, HttpServletResponse response, ExportExcelDto dto) { String tableName = dto.getTableName(); Boolean empty = dto.getEmpty(); ObjectUtils.requireNonNull(tableName, "exportExcelCommon tableName is empty"); ObjectUtils.requireNonNull(empty, "exportExcelCommon empty is empty"); GenTable genTable = redisService.getCacheObject(RedisKey.TABLE_INFO + tableName); List allColumn = genTable.getColumns(); List columns = ExcelUtil.filterData(allColumn, 4, MaskConstant.LIST_VISIBLE::equals); String filename = UUID.randomUUID() + ".xlsx"; String fileAbsPath = localFilePath + "/" + filename; String fileStaticPath = domain + localFilePrefix + "/" + filename; File file = new File(fileAbsPath); ExcelUtil util = new ExcelUtil<>(JSONObject.class); String username = SecurityUtils.getUsername(); String token = SecurityUtils.getToken(request); LoginUser loginUser = redisService.getCacheObject(CacheConstants.LOGIN_TOKEN_KEY + token); Long deptId = loginUser.getSysUser().getDeptId(); List sysDepts = remoteDeptService.listChildrenDepts(deptId); List deptIdList = new ArrayList<>(); if (sysDepts != null && sysDepts.size() > 0) { for (SysDept sysDept : sysDepts) { Long id = sysDept.getId(); deptIdList.add(id); } } ThreadPoolService.execute(() -> { List> list; int size = 0; Boolean emptyIn = empty; if (BooleanUtils.isTrue(emptyIn)) { list = new ArrayList<>(0); } else { LOGGER.info("开始查询, 线程名称: {}", Thread.currentThread().getName()); long currentTimeMillis = System.currentTimeMillis(); list = getData1(dto, tableName, columns, token); if (isEmpty(list)) { size = 0; emptyIn = true; } else { size = list.size(); } LOGGER.info("查询到的数据长度为: {}, 查询耗时:{}秒, 文件:{}", size, (System.currentTimeMillis() - currentTimeMillis) / 1000, filename); } try { util.asyncExportExcelCommon(new FileOutputStream(file), list, "sheet1", columns, emptyIn, false); // long timeout = 2L; // if (size > 100000 && size < 500000) { // timeout = 5L; // } else if(size > 500000){ // timeout = 10L; // } String key = RedisKey.ASYNC_DOWNLOAD_YMJZ + username; JSONObject jsonObject = new JSONObject(); jsonObject.put("fileStaticPath", fileStaticPath); jsonObject.put("fileAbsPath", fileAbsPath); redisService.setCacheObject(key, jsonObject); } catch (IOException e) { LOGGER.error("导出失败", e); e.printStackTrace(); } }); return AjaxResult.success("成功", fileStaticPath); } /** * 功能描述: 通用的导出接口 * * @param response response * @param info 查询条件 * @return com.boman.domain.dto.AjaxResult */ @Override public AjaxResult asyncExportYmjzExcel(HttpServletResponse response, VaccineInfoOperation info) throws IOException { GenTable genTable = redisService.getCacheObject(RedisKey.TABLE_INFO + "vaccine_info"); List allColumn = genTable.getColumns(); List columns = ExcelUtil.filterData(allColumn, 4, MaskConstant.LIST_VISIBLE::equals); String filename = UUID.randomUUID() + ".xlsx"; String fileAbsPath = localFilePath + "/" + filename; String fileStaticPath = domain + localFilePrefix + "/" + filename; File file = new File(fileAbsPath); ExcelUtil util = new ExcelUtil<>(JSONObject.class); String username = SecurityUtils.getUsername(); ThreadPoolService.execute(() -> { List> list; LOGGER.info("开始查询, 线程名称: {}", Thread.currentThread().getName()); long currentTimeMillis = System.currentTimeMillis(); String key = RedisKey.ASYNC_DOWNLOAD_YMJZ + username; JSONObject jsonObject = new JSONObject(); jsonObject.put("fileStaticPath", fileStaticPath); jsonObject.put("fileAbsPath", fileAbsPath); redisService.setCacheObject(key, jsonObject); list = listYmjz(info, columns); boolean empty = isEmpty(list); int size = BooleanUtils.isFalse(empty) ? 0 : list.size(); LOGGER.info("查询到的数据长度为: {}, 查询耗时:{}秒", size, (System.currentTimeMillis() - currentTimeMillis) / 1000); try { util.asyncExportExcelCommon(new FileOutputStream(file), list, "sheet1", columns, empty, false); long timeout = 2L; if (size > 100000 && size < 500000) { timeout = 5L; } else if (size > 500000) { timeout = 10L; } } catch (IOException e) { LOGGER.error("导出失败", e); e.printStackTrace(); } }); return AjaxResult.success("成功", fileStaticPath); } private List> getData(ExportExcelDto dto, String tableName, List columns) { List> list = null; FormDataDto condition = new FormDataDto(); condition.setTable(tableName); condition.setFixedData(new JSONObject(dto.getCondition())); condition.setPageSize(Integer.MAX_VALUE); condition.setPageNo(1); AjaxResult ajaxResult = remoteObjService.getByMap(condition); if (AjaxResult.checkSuccess(ajaxResult)) { list = ((List>) ajaxResult.get(AjaxResult.DATA_TAG)); handleNullColumnValue(list, map(columns, GenTableColumn::getColumnName)); } return list; } private List> getData1(ExportExcelDto dto, String tableName, List columns, String token) { List> list = null; Map formData = dto.getCondition(); String idCard = (String) formData.get("idCard"); String userName = (String) formData.get("userName"); String phoneNum = (String) formData.get("phoneNum"); String jici = (String) formData.get("jici"); String keyIndustries = (String) formData.get("keyIndustries"); String vaccineName = (String) formData.get("vaccineName"); String vaccinationPlace = (String) formData.get("vaccinationPlace"); String isVaccination = (String) formData.get("isVaccination"); String shouldBe = (String) formData.get("shouldBe"); String shouldSlow = (String) formData.get("shouldSlow"); Integer deptIdTemp = (Integer) formData.get("deptId"); Long deptId; if (deptIdTemp == null) { LoginUser loginUser = redisService.getCacheObject(CacheConstants.LOGIN_TOKEN_KEY + token); deptId = loginUser.getSysUser().getDeptId(); } else { deptId = deptIdTemp.longValue(); } List sysDepts = remoteDeptService.listChildrenDepts(deptId); List deptIdList = new ArrayList<>(); if (sysDepts != null && sysDepts.size() > 0) { for (SysDept sysDept : sysDepts) { Long id = sysDept.getId(); deptIdList.add(id); } } FormDataDto condition = new FormDataDto(); condition.setTable(tableName); JSONObject jsonObject = new JSONObject(); jsonObject.put("dept_id", deptIdList); jsonObject.put("is_del", 'N'); if (isNotEmpty(idCard)) { jsonObject.put("id_card", idCard); } if (isNotEmpty(phoneNum)) { jsonObject.put("phone_num", phoneNum); } if (isNotEmpty(userName)) { jsonObject.put("user_name", userName); } if (isNotEmpty(jici)) { jsonObject.put("jici", jici); } if (isNotEmpty(keyIndustries)) { jsonObject.put("key_industries", keyIndustries); } if (isNotEmpty(vaccineName)) { jsonObject.put("vaccine_name", vaccineName); } if (isNotEmpty(vaccinationPlace)) { jsonObject.put("vaccination_place", vaccinationPlace); } if (isNotEmpty(isVaccination)) { jsonObject.put("is_vaccination", isVaccination); } if (isNotEmpty(shouldBe)) { jsonObject.put("should_be", shouldBe); } if (isNotEmpty(shouldSlow)) { jsonObject.put("should_slow", shouldSlow); } condition.setFixedData(jsonObject); condition.setPageSize(Integer.MAX_VALUE); condition.setPageNo(1); AjaxResult ajaxResult = remoteObjService.getByMap(condition); if (AjaxResult.checkSuccess(ajaxResult)) { list = ((List>) ajaxResult.get(AjaxResult.DATA_TAG)); handleNullColumnValue(list, map(columns, GenTableColumn::getColumnName)); } return list; } /** * 功能描述: 单独去查疫苗接种信息的 * * @param info info * @return java.util.List> */ private List> listYmjz(VaccineInfoOperation info, List columns) { // TableDataInfo list = remoteObjService.list(info); // LOGGER.info("查询结果:{}", JSON.toJSONString(list)); // List rows = list.getRows(); // return JSON.parseObject(JSON.toJSONString(rows), new TypeReference>>() { // }.getType()); List> list = null; FormDataDto condition = new FormDataDto(); condition.setTable("vaccine_info"); condition.setFixedData(new JSONObject()); condition.setPageSize(Integer.MAX_VALUE); condition.setPageNo(1); AjaxResult ajaxResult = remoteObjService.getByMap(condition); if (AjaxResult.checkSuccess(ajaxResult)) { list = ((List>) ajaxResult.get(AjaxResult.DATA_TAG)); handleNullColumnValue(list, map(columns, GenTableColumn::getColumnName)); } return list; } /** * 功能描述: 导出数据,只是sql不一样,其余的都是通用接口的内容 * * @param response response * @param dto tableName * empty(true=>只带表头的excel,不含数据, false=>带数据的excel) * condition 查询条件 * @return com.boman.domain.dto.AjaxResult */ @Override public AjaxResult statisticsByMonth(HttpServletResponse response, ExportExcelDto dto) { String tableName = dto.getTableName(); Boolean empty = dto.getEmpty(); ObjectUtils.requireNonNull(tableName, "exportExcelCommon tableName is empty"); ObjectUtils.requireNonNull(empty, "exportExcelCommon empty is empty"); ExcelUtil util = new ExcelUtil<>(JSONObject.class); List> list = null; if (BooleanUtils.isTrue(empty)) { list = new ArrayList<>(0); } else { AjaxResult ajaxResult = remoteAttendanceService.statisticsByMonth(dto.getCondition()); if (AjaxResult.checkSuccess(ajaxResult)) { list = ((List>) ajaxResult.get(AjaxResult.DATA_TAG)); // 导出不需要user_id, 同时把map中的value换成int List> newList = new ArrayList<>(list.size()); for (Map map : list) { map.remove("user_id"); for (Map.Entry entry : map.entrySet()) { Object value = entry.getValue(); if (value instanceof Double) { Double value1 = (Double) value; entry.setValue(value1.intValue()); } } Map newMap = new LinkedHashMap<>(map.size()); newMap.put(USERNAME, map.get(USERNAME)); newMap.put(DEPT_NAME, map.get(DEPT_NAME)); newMap.put(ATTENDANCE_TABLE_LATE_SUM, map.get(ATTENDANCE_TABLE_LATE_SUM)); newMap.put(ATTENDANCE_TABLE_LEAVE_SUM, map.get(ATTENDANCE_TABLE_LEAVE_SUM)); newMap.put(ATTENDANCE_TABLE_LEAVE_OR_SUM, map.get(ATTENDANCE_TABLE_LEAVE_OR_SUM)); newMap.put(DATE, map.get(DATE)); newList.add(newMap); } list = newList; } } try { util.exportExcelCommon(response, list, "sheet1", null, empty, true); } catch (IOException e) { LOGGER.error("考勤统计导出失败,导出数据为:{}", list); e.printStackTrace(); } return null; } /** * 功能描述: 通用的导入接口 * * @param dto@return java.util.List */ @Override public List importExcelCommon(ImportExcelDto dto) throws Exception { return null; } public void handleNullColumnValue(List> result, List showData) { for (Map map : result) { Set resultKeySet = map.keySet(); for (String columnName : showData) { if (!resultKeySet.contains(columnName)) { map.put(columnName, ""); } } } } /** * 功能描述: 获取系统配置 * * @return java.lang.String */ @Override public String getConfigPath() { return localFilePrefix + "_._" + domain + "_._" + localFilePath; } }