Sfoglia il codice sorgente

fix: 人员导出逻辑调整

lixuesong 1 settimana fa
parent
commit
c7cfea2b3a

+ 2 - 0
hnqz-upms/hnqz-upms-api/src/main/java/com/qunzhixinxi/hnqz/admin/api/constant/CacheConstants.java

@@ -99,6 +99,8 @@ public interface CacheConstants {
 
     String NEW_EXCEL_COMMON_REPORT_CACHE = "new_excel_export:common_report:%s";
 
+    String ASYNC_EXPORT_LIMIT_KEY = "async_export:limit";
+
     /**
      * 异步导出缓存key
      */

+ 13 - 7
hnqz-upms/hnqz-upms-api/src/main/java/com/qunzhixinxi/hnqz/admin/api/model/excel/SysUserExcelModel.java

@@ -1,6 +1,7 @@
 package com.qunzhixinxi.hnqz.admin.api.model.excel;
 
 import com.alibaba.excel.annotation.ExcelProperty;
+import com.alibaba.excel.annotation.write.style.ColumnWidth;
 import lombok.Data;
 
 import java.io.Serializable;
@@ -18,43 +19,48 @@ public class SysUserExcelModel implements Serializable {
 	/**
 	 * 人员名称
 	 */
-	@ExcelProperty(value = "人员名称", index = 1)
+	@ExcelProperty(value = "人员名称", index = 0)
+	@ColumnWidth(15)
 	private String realName;
 
 	/**
 	 * 手机号
 	 */
-	@ExcelProperty(value = "手机号", index = 2)
+	@ExcelProperty(value = "手机号", index = 1)
+	@ColumnWidth(20)
 	private String phoneNumber;
 
 	/**
 	 * 人员角色
 	 */
-	@ExcelProperty(value = "人员角色", index = 3)
+	@ExcelProperty(value = "人员角色", index = 2)
+	@ColumnWidth(20)
 	private String roleList;
 
 	/**
 	 * 派工方
 	 */
-	@ExcelProperty(value = "派工方", index = 4)
+	@ExcelProperty(value = "派工方", index = 3)
+	@ColumnWidth(20)
 	private String deptName;
 
 	/**
 	 * 状态
 	 */
-	@ExcelProperty(value = "状态", index = 5)
+	@ExcelProperty(value = "启停状态", index = 4)
 	private String lockFlag;
 
 	/**
 	 * 创建时间
 	 */
-	@ExcelProperty(value = "创建时间", index = 6)
+	@ExcelProperty(value = "创建时间", index = 5)
+	@ColumnWidth(20)
 	private String createTime;
 
 	/**
 	 * 证书状态
 	 */
-	@ExcelProperty(value = "是/否备案", index = 7)
+	@ExcelProperty(value = "是/否备案", index = 6)
 	private String certificateFlag;
 
 }

+ 5 - 0
hnqz-upms/hnqz-upms-biz/src/main/java/com/qunzhixinxi/hnqz/admin/config/UpmsConfig.java

@@ -64,4 +64,9 @@ public class UpmsConfig {
 	 */
 	private Integer pltEntId;
 
+	/**
+	 * 异步导出限制个数(全局)
+	 */
+	private Integer asyncExportLimit = 3;
+
 }

+ 13 - 1
hnqz-upms/hnqz-upms-biz/src/main/java/com/qunzhixinxi/hnqz/admin/controller/user/SysUserExportController.java

@@ -1,6 +1,7 @@
 package com.qunzhixinxi.hnqz.admin.controller.user;
 
 import com.qunzhixinxi.hnqz.admin.api.dto.SysUserDTO;
+import com.qunzhixinxi.hnqz.admin.api.entity.WmReportOpt;
 import com.qunzhixinxi.hnqz.admin.api.model.excel.SysUserExcelModel;
 import com.qunzhixinxi.hnqz.admin.service.SysUserExportService;
 import com.qunzhixinxi.hnqz.common.core.util.R;
@@ -8,6 +9,7 @@ import com.qunzhixinxi.hnqz.common.log.annotation.SysLog;
 import com.qunzhixinxi.hnqz.common.security.util.SecurityUtils;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
+import org.springframework.web.bind.annotation.GetMapping;
 import org.springframework.web.bind.annotation.PostMapping;
 import org.springframework.web.bind.annotation.RequestBody;
 import org.springframework.web.bind.annotation.RequestMapping;
@@ -35,8 +37,18 @@ public class SysUserExportController {
 	 * @return {@link List }<{@link SysUserExcelModel }> 用户信息
 	 */
 	@SysLog("导出用户信息")
-	@PostMapping("/export-user-info")
+	@PostMapping("/export-user")
 	public R<Boolean> exportUser(@RequestBody SysUserDTO.OnList query) {
 		return R.ok(userExportService.asyncExport(SecurityUtils.getUser(), SecurityUtils.getRoles(), query));
 	}
+
+	/**
+	 * 导出用户信息的结果
+	 *
+	 * @return {@link WmReportOpt } 状态和结果
+	 */
+	@GetMapping("/export-user-result")
+	public R<WmReportOpt> exportResult() {
+		return R.ok(userExportService.exportResult(SecurityUtils.getUser()));
+	}
 }

+ 46 - 11
hnqz-upms/hnqz-upms-biz/src/main/java/com/qunzhixinxi/hnqz/admin/service/impl/SysUserExportServiceImpl.java

@@ -3,6 +3,7 @@ package com.qunzhixinxi.hnqz.admin.service.impl;
 import cn.hutool.core.bean.BeanUtil;
 import cn.hutool.core.collection.CollUtil;
 import cn.hutool.core.date.DatePattern;
+import cn.hutool.core.io.FileUtil;
 import cn.hutool.core.util.StrUtil;
 import com.alibaba.excel.EasyExcel;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
@@ -19,6 +20,7 @@ import com.qunzhixinxi.hnqz.admin.api.entity.SysUserCertificate;
 import com.qunzhixinxi.hnqz.admin.api.entity.SysUserRole;
 import com.qunzhixinxi.hnqz.admin.api.entity.WmReportOpt;
 import com.qunzhixinxi.hnqz.admin.api.model.excel.SysUserExcelModel;
+import com.qunzhixinxi.hnqz.admin.config.UpmsConfig;
 import com.qunzhixinxi.hnqz.admin.controller.user.SysUserController;
 import com.qunzhixinxi.hnqz.admin.event.UserExportEvent;
 import com.qunzhixinxi.hnqz.admin.mapper.SysAreaEntityMapper;
@@ -31,6 +33,7 @@ import com.qunzhixinxi.hnqz.admin.service.SysFileService;
 import com.qunzhixinxi.hnqz.admin.service.SysUserAreaService;
 import com.qunzhixinxi.hnqz.admin.service.SysUserExportService;
 import com.qunzhixinxi.hnqz.admin.util.OsEnvUtils;
+import com.qunzhixinxi.hnqz.common.core.exception.BizException;
 import com.qunzhixinxi.hnqz.common.core.util.SpringContextHolder;
 import com.qunzhixinxi.hnqz.common.security.service.HnqzUser;
 import lombok.RequiredArgsConstructor;
@@ -74,6 +77,7 @@ public class SysUserExportServiceImpl implements SysUserExportService {
 	private final SysDeptMapper deptMapper;
 	private final SysUserCertificateMapper userCertificateMapper;
 	private final SysFileService fileService;
+	private final UpmsConfig upmsConfig;
 
 	private static final long DEF_REPORT_TTL = 7L * 24 * 60 * 60 * 1000;
 	private static final String ERROR_MSG_UNKNOWN = "ERROR_未知错误,请联系管理员";
@@ -91,6 +95,22 @@ public class SysUserExportServiceImpl implements SysUserExportService {
 	 */
 	@Override
 	public Boolean asyncExport(HnqzUser user, List<Integer> roles, SysUserDTO.OnList query) {
+		// 使用Redis原子操作实现限流,避免使用synchronized影响并发性能
+		String key = CacheConstants.ASYNC_EXPORT_LIMIT_KEY;
+		Long increment = redisTemplate.opsForValue().increment(key);
+
+		// 设置key的过期时间,避免计数器无限增长
+		if (increment != null && increment.equals(1L)) {
+			redisTemplate.expire(key, 1, TimeUnit.MINUTES);
+		}
+
+		// 检查是否超过限流阈值
+		if (increment != null && increment > upmsConfig.getAsyncExportLimit()) {
+			// 超过限流阈值时,减少计数器并抛出异常
+			redisTemplate.opsForValue().decrement(key);
+			throw new BizException("系统繁忙,请稍后再试");
+		}
+
 		SpringContextHolder.getApplicationContext().publishEvent(new UserExportEvent(user, roles, query));
 		return Boolean.TRUE;
 	}
@@ -105,12 +125,20 @@ public class SysUserExportServiceImpl implements SysUserExportService {
 	 */
 	@Override
 	public Boolean export(HnqzUser user, List<Integer> roles, SysUserDTO.OnList query) {
+		// 缓存key
 		String key = String.format(CacheConstants.ASYNC_EXPORT_CACHE, ExportType.USER.getType(), user.getId());
 
+		// 临时文件路径
+		String tempPath = OsEnvUtils.getEachEnvPaths().get(OsEnvUtils.TargetFile.TEMP.getName());
+		// 缓存文件名
+		String fileName = tempPath + "人员_" + DateTimeFormatter.ofPattern(DatePattern.PURE_DATE_PATTERN)
+				.format(LocalDateTime.now()) + RandomStringUtils.randomNumeric(6) + ".xlsx";
+
 		// 查询用户列表
 		List<SysUser> users = this.listUsers(user, roles, query);
 
-		if (CollUtil.isNotEmpty(users)) {
+		if (CollUtil.isEmpty(users)) {
+			log.info("用户列表为空");
 			redisTemplate.opsForValue().set(key, ERROR_MSG_NO_DATA, DEF_REPORT_TTL, TimeUnit.MILLISECONDS);
 			return Boolean.FALSE;
 		}
@@ -144,7 +172,7 @@ public class SysUserExportServiceImpl implements SysUserExportService {
 					userCertificateMapper.selectList(Wrappers.<SysUserCertificate>lambdaQuery()
 							.in(SysUserCertificate::getUserId, userIds)
 							.eq(SysUserCertificate::getType, "REG")
-							.select(SysUserCertificate::getCertificateId));
+							.select(SysUserCertificate::getCertificateId, SysUserCertificate::getUserId));
 
 			Map<Integer, Long> userCertMap = userCertificates.stream()
 					.collect(Collectors.groupingBy(SysUserCertificate::getUserId, Collectors.counting()));
@@ -152,6 +180,13 @@ public class SysUserExportServiceImpl implements SysUserExportService {
 			// 转为excel列表
 			List<SysUserExcelModel> excelModels = users.stream().map(u -> {
 				SysUserExcelModel excelModel = BeanUtil.copyProperties(u, SysUserExcelModel.class, "lockFlag");
+				excelModel.setRealName(u.getRealname());
+				excelModel.setPhoneNumber(u.getPhone());
+				// 锁定状态
+				excelModel.setLockFlag("0".equals(u.getLockFlag()) ? "活跃" : "休眠");
+				// 创建时间
+				excelModel.setCreateTime(u.getCreateTime().format(DateTimeFormatter.ofPattern(DatePattern.NORM_DATETIME_PATTERN)));
+
 				// 派工方
 				SysDept dept = deptMap.get(u.getDeptId());
 				if (dept != null) {
@@ -171,17 +206,10 @@ public class SysUserExportServiceImpl implements SysUserExportService {
 				long certCount = userCertMap.getOrDefault(u.getUserId(), 0L);
 				excelModel.setCertificateFlag(certCount > 0 ? "是" : "否");
 
-				// 锁定状态
-				excelModel.setLockFlag("0".equals(u.getLockFlag()) ? "活跃" : "休眠");
-
-
 				return excelModel;
 			}).collect(Collectors.toList());
 
 			// 写入excel文件
-			String tempPath = OsEnvUtils.getEachEnvPaths().get(OsEnvUtils.TargetFile.TEMP.getName());
-			String fileName = tempPath + "人员_" + DateTimeFormatter.ofPattern(DatePattern.PURE_TIME_PATTERN)
-					.format(LocalDateTime.now()) + RandomStringUtils.randomNumeric(6) + ".xlsx";
 			EasyExcel.write(fileName, SysUserExcelModel.class).sheet("人员")
 					.doWrite(excelModels);
 			log.info("人员导出生成缓存文件:{}", fileName);
@@ -198,13 +226,20 @@ public class SysUserExportServiceImpl implements SysUserExportService {
 				resultValue = ERROR_MSG_UPLOAD_FAIL;
 			}
 		} catch (Exception e) {
-			log.error("人员导出写入文件失败", e);
+			log.error("人员导出失败", e);
 			resultValue = ERROR_MSG_UNKNOWN;
+		} finally {
+			// 移除缓存文件
+			FileUtil.del(fileName);
+
+			// 删除限流key
+			String limitKey = CacheConstants.ASYNC_EXPORT_LIMIT_KEY;
+			redisTemplate.delete(limitKey);
 		}
 
 		redisTemplate.opsForValue().set(key, resultValue, DEF_REPORT_TTL, TimeUnit.MILLISECONDS);
 
-		return Boolean.FALSE;
+		return StrUtil.startWith(resultValue, "ERROR") ? Boolean.FALSE : Boolean.TRUE;
 	}
 
 	/**