优化
This commit is contained in:
@ -15,7 +15,9 @@ import com.ruoyi.bgt.service.IBgtProjectRecruitService;
|
||||
import com.ruoyi.common.core.controller.BaseController;
|
||||
import com.ruoyi.common.core.domain.AjaxResult;
|
||||
import com.ruoyi.common.core.page.TableDataInfo;
|
||||
import com.ruoyi.common.core.redis.RedisCache;
|
||||
import com.ruoyi.common.enums.RecruitApplyStatus;
|
||||
import com.ruoyi.common.util.MessageUtil;
|
||||
import com.ruoyi.wgz.bo.req.WgzAppPersonalBasicInformationReq;
|
||||
import com.ruoyi.wgz.bo.res.WgzAppPersonalBasicInformationRes;
|
||||
import com.ruoyi.wgz.service.IWgzAttendanceService;
|
||||
@ -53,6 +55,8 @@ public class AppBgtMessageController extends BaseController {
|
||||
|
||||
private final IBgtProjectRecruitService iBgtProjectRecruitService;
|
||||
|
||||
private final RedisCache redisCache;
|
||||
|
||||
@ApiOperation("未读消息统计")
|
||||
@GetMapping("/countUnread")
|
||||
public AjaxResult<BgtMessageCountVO> count() {
|
||||
@ -74,10 +78,14 @@ public class AppBgtMessageController extends BaseController {
|
||||
@ApiOperation("已读")
|
||||
@PutMapping("/read/{id}")
|
||||
public AjaxResult<Boolean> read(@PathVariable(value = "id") Long id) {
|
||||
BgtMessage bgtMessage = new BgtMessage();
|
||||
bgtMessage.setId(id);
|
||||
bgtMessage.setReadStatus("1");
|
||||
return AjaxResult.success(iBgtMessageService.updateById(bgtMessage));
|
||||
BgtMessage bgtMessage = iBgtMessageService.getById(id);
|
||||
boolean b = true;
|
||||
if("0".equals(bgtMessage.getReadStatus())){
|
||||
MessageUtil.readMessagePush(bgtMessage.getRecipientType(), bgtMessage.getRecipientId(), bgtMessage.getMessageLargeType(), bgtMessage.getReadStatus());
|
||||
bgtMessage.setReadStatus("1");
|
||||
b = iBgtMessageService.updateById(bgtMessage);
|
||||
}
|
||||
return AjaxResult.success(b);
|
||||
}
|
||||
|
||||
@ApiOperation("已操作")
|
||||
|
@ -0,0 +1,47 @@
|
||||
package com.ruoyi.web.controller.common;
|
||||
|
||||
import com.ruoyi.common.util.SseUtil;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/sse")
|
||||
public class SseController {
|
||||
|
||||
|
||||
/**
|
||||
* 客户端订阅SSE连接(适配2.4.7)
|
||||
*/
|
||||
@GetMapping(path = "/subscribe", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
|
||||
public SseEmitter subscribe(String userId,String prefix) {
|
||||
return SseUtil.subscribe(userId,prefix);
|
||||
}
|
||||
|
||||
// /**
|
||||
// * 触发消息数量推送(适配2.4.7)
|
||||
// */
|
||||
// @GetMapping("/push")
|
||||
// public void pushMessageCount(String userId) {
|
||||
// SseEmitter emitter = emitterMap.get(userId);
|
||||
// if (emitter != null) {
|
||||
// BgtMessageCountVO bgtMessageCountVO = new BgtMessageCountVO();
|
||||
// bgtMessageCountVO.setTaskMessageCount(1);
|
||||
// bgtMessageCountVO.setSettlementMessageCount(0);
|
||||
// try {
|
||||
// // 发送自定义事件(客户端通过事件名监听)
|
||||
// emitter.send(SseEmitter.event()
|
||||
// .id(String.valueOf(System.currentTimeMillis()))
|
||||
// .name("messageCount")
|
||||
// .data(JSONUtil.toJsonStr(bgtMessageCountVO))
|
||||
// );
|
||||
// } catch (IOException e) {
|
||||
// emitter.completeWithError(e);
|
||||
// emitterMap.remove(userId); // 异常时清理无效连接
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
@ -11,7 +11,6 @@ import com.ruoyi.common.constant.Constants;
|
||||
import com.ruoyi.common.core.domain.AjaxResult;
|
||||
import com.ruoyi.common.core.domain.entity.BgtUser;
|
||||
import com.ruoyi.common.domain.Annex;
|
||||
import com.ruoyi.common.domain.AnnexRecord;
|
||||
import com.ruoyi.common.exception.BaseException;
|
||||
import com.ruoyi.common.service.IAnnexRecordService;
|
||||
import com.ruoyi.common.service.IAnnexService;
|
||||
@ -34,15 +33,16 @@ import java.nio.charset.Charset;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipInputStream;
|
||||
|
||||
/**
|
||||
* 登录验证
|
||||
*
|
||||
* @author ruoyi
|
||||
* 压缩文件上传控制器(整合路径收集与验证逻辑)
|
||||
*/
|
||||
@Api(value = "网页模板上传", tags = {"网页模板上传"})
|
||||
@RequiredArgsConstructor(onConstructor_ = @Autowired)
|
||||
@ -57,9 +57,9 @@ public class UploadZipController {
|
||||
private final IBgtUserService bgtUserService;
|
||||
private final IBgtProjectRecruitApplyService recruitApplyService;
|
||||
|
||||
private static final String TEMP_DIR = "ruoyi/uploadPath/temporaryZip"; //临时解压
|
||||
private static final String SAVE_DIR = "ruoyi/uploadPath/recruit"; //保存目录
|
||||
private static final String RECORD_DIR = "ruoyi/uploadPath/record"; //记录目录
|
||||
private static final String TEMP_DIR = "ruoyi/uploadPath/temporaryZip"; // 临时解压目录
|
||||
private static final String SAVE_DIR = "ruoyi/uploadPath/recruit"; // 最终保存目录
|
||||
private static final String RECORD_DIR = "ruoyi/uploadPath/record"; // 记录目录
|
||||
|
||||
@ApiOperation("上传压缩文件")
|
||||
@PostMapping("/upload-zip")
|
||||
@ -71,14 +71,14 @@ public class UploadZipController {
|
||||
}
|
||||
|
||||
String originalFilename = file.getOriginalFilename();
|
||||
|
||||
if (originalFilename == null || !originalFilename.toLowerCase().endsWith(".zip")) {
|
||||
throw new BaseException("上传的文件不是有效的 ZIP 文件!");
|
||||
}
|
||||
String[] split = originalFilename.split("_");
|
||||
if (split.length != 2 || !split[0].equals(recruitId.toString())) {
|
||||
throw new BaseException("文件名与所选择招工不匹配");
|
||||
}
|
||||
// String[] split = originalFilename.split("_");
|
||||
// if (split.length != 2 || !split[0].equals(recruitId.toString())) {
|
||||
// throw new BaseException("文件名与所选择招工不匹配");
|
||||
// }
|
||||
|
||||
BgtProjectRecruit recruit = recruitService.queryById(recruitId);
|
||||
if (recruit == null) {
|
||||
throw new BaseException("招工信息不存在!");
|
||||
@ -90,79 +90,151 @@ public class UploadZipController {
|
||||
}
|
||||
|
||||
String username = bgtUser.getUsername();
|
||||
String firstLevelFolderName = "";
|
||||
String firstLevelFolderName = recruitId + "_" + DigestUtil.md5Hex(recruit.getRecruitName());
|
||||
try {
|
||||
// 保存上传的压缩文件
|
||||
String s = DigestUtil.md5Hex(recruit.getRecruitName());
|
||||
firstLevelFolderName = recruitId + "_" + s;
|
||||
// 保存并解压ZIP文件
|
||||
File zipFile = new File(TEMP_DIR, firstLevelFolderName + ".zip");
|
||||
ensureDirectoryExists(zipFile.getParentFile());
|
||||
try (OutputStream os = new FileOutputStream(zipFile)) {
|
||||
os.write(file.getBytes());
|
||||
}
|
||||
|
||||
// 解压压缩文件
|
||||
File extractDir = new File(TEMP_DIR, firstLevelFolderName);
|
||||
ensureDirectoryExists(extractDir);
|
||||
extractZipFile(zipFile, extractDir);
|
||||
|
||||
// 处理解压后的文件夹
|
||||
processExtractedFolder(extractDir, recruitId);
|
||||
// 收集目标路径(仅BaoXian/HeTong目录下的最底层文件)
|
||||
// 收集路径(返回Map和目录列表)
|
||||
Object[] paths = collectLeafPaths(extractDir);
|
||||
Map<String, String> leafFileMap = (Map<String, String>) paths[0]; // 改为Map
|
||||
List<String> targetDirPaths = (List<String>) paths[1];
|
||||
|
||||
// 将解压后的文件移动到 SAVE_DIR
|
||||
moveFilesToSaveDir(extractDir, recruitId, username);
|
||||
// 处理SAVE_DIR中已有文件的重命名(关键新增逻辑)
|
||||
processExistingFilesInSaveDir(targetDirPaths, recruitId);
|
||||
|
||||
// 异步执行 RECORD_DIR 操作和删除临时文件操作
|
||||
asyncProcessRecordAndDeleteTemp(extractDir, zipFile, recruitId, username, userId);
|
||||
// 修改后(新调用方式)
|
||||
processExtractedFolder(targetDirPaths, recruitId); // 传递收集的targetDirPaths
|
||||
// 移动文件到SAVE_DIR(使用收集的路径)
|
||||
moveFilesToSaveDir(extractDir, recruitId, username, leafFileMap);
|
||||
|
||||
// 异步清理临时文件(仅保留清理逻辑)
|
||||
asyncDeleteTempFiles(extractDir, zipFile);
|
||||
|
||||
return AjaxResult.success("文件上传并处理成功");
|
||||
} catch (Exception e) {
|
||||
// 删除临时文件和文件夹
|
||||
File extractDir = new File(TEMP_DIR, firstLevelFolderName);
|
||||
deleteFolder(extractDir);
|
||||
File zipFile = new File(TEMP_DIR, firstLevelFolderName + ".zip");
|
||||
deleteFolder(zipFile);
|
||||
deleteFolder(new File(TEMP_DIR, firstLevelFolderName));
|
||||
deleteFolder(new File(TEMP_DIR, firstLevelFolderName + ".zip"));
|
||||
e.printStackTrace();
|
||||
return AjaxResult.error("文件处理过程中出现错误");
|
||||
}
|
||||
}
|
||||
|
||||
@Async
|
||||
public CompletableFuture<Void> asyncProcessRecordAndDeleteTemp(File extractDir, File zipFile, Long recruitId, String username, Long userId) {
|
||||
return CompletableFuture.runAsync(() -> {
|
||||
try {
|
||||
// 移动到 RECORD_DIR
|
||||
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMddHHmmss");
|
||||
String timeStamp = LocalDateTime.now().format(formatter);
|
||||
BgtProjectRecruit recruit = recruitService.queryById(recruitId);
|
||||
String s = DigestUtil.md5Hex(recruit.getRecruitName());
|
||||
String firstLevelFolderName = recruitId + "_" + s;
|
||||
File recordDestDir = new File(RECORD_DIR, firstLevelFolderName);
|
||||
ensureDirectoryExists(recordDestDir);
|
||||
/**
|
||||
* 收集最底层文件路径(仅BaoXian/HeTong目录下的文件)
|
||||
* @param extractDir 解压根目录
|
||||
* @return [文件路径列表, 目录路径列表]
|
||||
*/
|
||||
private Object[] collectLeafPaths(File extractDir) {
|
||||
Map<String, String> leafFileMap = new HashMap<>(); // key: 倒数第二层/倒数第一层/文件名,value: 完整相对路径
|
||||
List<String> targetDirPaths = new ArrayList<>();
|
||||
collectLeafPathsRecursive(extractDir, extractDir, leafFileMap, targetDirPaths);
|
||||
return new Object[]{leafFileMap, targetDirPaths};
|
||||
}
|
||||
|
||||
List<AnnexRecord> annexRecordList = new ArrayList<>();
|
||||
moveFilesToRecordDirRecursively(extractDir, recordDestDir, timeStamp, annexRecordList, recruitId, username, userId);
|
||||
|
||||
if (CollectionUtil.isNotEmpty(annexRecordList)) {
|
||||
annexRecordService.saveBatch(annexRecordList);
|
||||
}
|
||||
/**
|
||||
* 递归收集路径(核心逻辑:验证倒数第一层目录名)
|
||||
*/
|
||||
private void collectLeafPathsRecursive(File baseDir, File currentDir,
|
||||
Map<String, String> leafFileMap, List<String> targetDirPaths) {
|
||||
File[] files = currentDir.listFiles();
|
||||
if (files == null || files.length == 0) return;
|
||||
|
||||
// 删除临时文件和文件夹
|
||||
deleteFolder(extractDir);
|
||||
if (!zipFile.delete()) {
|
||||
System.err.println("无法删除压缩文件: " + zipFile.getAbsolutePath());
|
||||
}
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
boolean hasSubDir = false;
|
||||
for (File file : files) {
|
||||
if (file.isDirectory()) {
|
||||
hasSubDir = true;
|
||||
collectLeafPathsRecursive(baseDir, file, leafFileMap, targetDirPaths);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (!hasSubDir) {
|
||||
for (File file : files) {
|
||||
if (file.isFile()) {
|
||||
String relativePath = getRelativePath(file, baseDir); // 完整相对路径(如:张三_123/BaoXian/文件.pdf)
|
||||
String[] pathParts = relativePath.split(Pattern.quote(File.separator));
|
||||
|
||||
if (pathParts.length >= 3) {
|
||||
String secondLastDir = pathParts[pathParts.length - 3]; // 倒数第二层(如:张三_123)
|
||||
String lastDir = pathParts[pathParts.length - 2]; // 倒数第一层(如:BaoXian)
|
||||
String fileName = pathParts[pathParts.length - 1]; // 文件名(如:文件.pdf)
|
||||
|
||||
if ("BaoXian".equals(lastDir) || "HeTong".equals(lastDir)) {
|
||||
// 构造key:倒数第二层/倒数第一层/文件名(如:张三_123/BaoXian/文件.pdf)
|
||||
String key = secondLastDir + File.separator + lastDir + File.separator + fileName;
|
||||
leafFileMap.put(key, relativePath); // 存入Map
|
||||
|
||||
// 收集目录路径(倒数第二层/倒数第一层/)
|
||||
String dirPath = secondLastDir + File.separator + lastDir + File.separator;
|
||||
if (!targetDirPaths.contains(dirPath)) {
|
||||
targetDirPaths.add(dirPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理SAVE_DIR中已有文件的重命名(添加时间戳)
|
||||
*/
|
||||
private void processExistingFilesInSaveDir(List<String> targetDirPaths, Long recruitId) throws IOException {
|
||||
BgtProjectRecruit recruit = recruitService.queryById(recruitId);
|
||||
String firstLevelFolder = recruitId + "_" + DigestUtil.md5Hex(recruit.getRecruitName());
|
||||
File saveBaseDir = new File(SAVE_DIR, firstLevelFolder);
|
||||
|
||||
for (String dirPath : targetDirPaths) {
|
||||
File targetDir = new File(saveBaseDir, dirPath);
|
||||
if (targetDir.exists() && targetDir.isDirectory()) {
|
||||
File[] existingFiles = targetDir.listFiles();
|
||||
if (existingFiles != null) {
|
||||
for (File existingFile : existingFiles) {
|
||||
if (existingFile.isFile() && !isTimestampedFile(existingFile.getName())) {
|
||||
String newFileName = addTimestampToFileName(existingFile.getName());
|
||||
File newFile = new File(targetDir, newFileName);
|
||||
if (!existingFile.renameTo(newFile)) {
|
||||
throw new IOException("重命名失败: " + existingFile.getAbsolutePath());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断文件名是否已包含时间戳(格式:xxx_yyyyMMddHHmmss.xxx)
|
||||
*/
|
||||
private boolean isTimestampedFile(String fileName) {
|
||||
return fileName.matches("^.*_\\d{14}\\..*$");
|
||||
}
|
||||
|
||||
/**
|
||||
* 为文件名添加时间戳(格式:原文件名_yyyyMMddHHmmss.扩展名)
|
||||
*/
|
||||
private String addTimestampToFileName(String originalName) {
|
||||
String timestamp = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss"));
|
||||
int lastDotIndex = originalName.lastIndexOf('.');
|
||||
if (lastDotIndex == -1) {
|
||||
return originalName + "_" + timestamp;
|
||||
}
|
||||
return originalName.substring(0, lastDotIndex) + "_" + timestamp + originalName.substring(lastDotIndex);
|
||||
}
|
||||
|
||||
private void ensureDirectoryExists(File directory) throws IOException {
|
||||
if (!directory.exists()) {
|
||||
if (!directory.mkdirs()) {
|
||||
throw new IOException("无法创建目录: " + directory.getAbsolutePath());
|
||||
}
|
||||
if (!directory.exists() && !directory.mkdirs()) {
|
||||
throw new IOException("无法创建目录: " + directory.getAbsolutePath());
|
||||
}
|
||||
}
|
||||
|
||||
@ -170,20 +242,12 @@ public class UploadZipController {
|
||||
try (ZipInputStream zis = new ZipInputStream(new FileInputStream(zipFile), Charset.forName("ISO-8859-15"))) {
|
||||
ZipEntry zipEntry;
|
||||
while ((zipEntry = zis.getNextEntry()) != null) {
|
||||
File destFile = newFile(extractDir, zipEntry);
|
||||
if (zipEntry.isDirectory()) {
|
||||
// 是目录,不重命名,直接创建目录
|
||||
File newDir = new File(extractDir, zipEntry.getName());
|
||||
ensureDirectoryExists(newDir);
|
||||
ensureDirectoryExists(destFile);
|
||||
} else {
|
||||
// 是文件,进行重命名
|
||||
String originalFileName = zipEntry.getName();
|
||||
String newFileName = renameFile(originalFileName);
|
||||
File newFile = new File(extractDir, newFileName);
|
||||
// 为文件创建父目录
|
||||
ensureDirectoryExists(newFile.getParentFile());
|
||||
|
||||
// 写入文件内容
|
||||
try (BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(newFile))) {
|
||||
ensureDirectoryExists(destFile.getParentFile());
|
||||
try (BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(destFile))) {
|
||||
byte[] bytesIn = new byte[4096];
|
||||
int read;
|
||||
while ((read = zis.read(bytesIn)) != -1) {
|
||||
@ -193,277 +257,181 @@ public class UploadZipController {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
private String renameFile(String originalFileName) {
|
||||
int lastIndexOfSlash = originalFileName.lastIndexOf('/');
|
||||
int lastIndexOfDot = originalFileName.lastIndexOf('.');
|
||||
|
||||
// 获取文件所在的目录路径
|
||||
String directoryPath = lastIndexOfSlash != -1 ? originalFileName.substring(0, lastIndexOfSlash + 1) : "";
|
||||
// 获取文件扩展名
|
||||
String fileExtension = lastIndexOfDot != -1 ? originalFileName.substring(lastIndexOfDot) : "";
|
||||
// 获取文件名(不包含扩展名)
|
||||
String fileNameWithoutExtension = lastIndexOfSlash != -1 && lastIndexOfDot != -1 ?
|
||||
originalFileName.substring(lastIndexOfSlash + 1, lastIndexOfDot) :
|
||||
originalFileName;
|
||||
|
||||
// 将 MD5 值转换为一个整数
|
||||
String s = DigestUtil.md5Hex(fileNameWithoutExtension);
|
||||
|
||||
|
||||
return directoryPath + s + fileExtension;
|
||||
originalFileName.substring(lastIndexOfSlash + 1, lastIndexOfDot) : originalFileName;
|
||||
return directoryPath + DigestUtil.md5Hex(fileNameWithoutExtension) + fileExtension;
|
||||
}
|
||||
|
||||
private File newFile(File destinationDir, ZipEntry zipEntry) throws IOException {
|
||||
File destFile = new File(destinationDir, zipEntry.getName());
|
||||
|
||||
String destDirPath = destinationDir.getCanonicalPath();
|
||||
String destFilePath = destFile.getCanonicalPath();
|
||||
|
||||
if (!destFilePath.startsWith(destDirPath + File.separator)) {
|
||||
throw new IOException("Entry is outside of the target dir: " + zipEntry.getName());
|
||||
}
|
||||
|
||||
return destFile;
|
||||
}
|
||||
|
||||
private void processExtractedFolder(File extractDir, Long recruitId) {
|
||||
File[] firstLevelFiles = extractDir.listFiles();
|
||||
private void processExtractedFolder(List<String> targetDirPaths, Long recruitId) {
|
||||
List<Long> insuranceUserIds = new ArrayList<>(); // 存储需要删除保险附件的用户ID
|
||||
List<Long> contractUserIds = new ArrayList<>(); // 存储需要删除合同附件的用户ID
|
||||
List<Long> recruitApplyIds = new ArrayList<>(); // 存储关联的招工申请ID
|
||||
|
||||
// 保险 2
|
||||
List<Long> insurance = new ArrayList<>();
|
||||
// 劳务合同 1
|
||||
List<Long> contract = new ArrayList<>();
|
||||
// 招工申请Id
|
||||
List<Long> recruitApplyIds = new ArrayList<>();
|
||||
|
||||
|
||||
if (firstLevelFiles != null) {
|
||||
for (File firstLevelFile : firstLevelFiles) {
|
||||
String firstLevelFolderName = firstLevelFile.getName();
|
||||
System.out.println("第一层文件夹名称: " + firstLevelFolderName);
|
||||
String[] split = firstLevelFolderName.split("_");
|
||||
String card = split[1];
|
||||
WgzUser wgzUser = wgzUserService.findByIdentityCard(card);
|
||||
if (wgzUser == null) {
|
||||
throw new BaseException("文件格式错误");
|
||||
}
|
||||
BgtProjectRecruitApply oneByUserIdAndRecruitId = recruitApplyService.getOneByUserIdAndRecruitId(wgzUser.getUserId(), recruitId);
|
||||
if (oneByUserIdAndRecruitId == null) {
|
||||
throw new BaseException("状态不对");
|
||||
}
|
||||
recruitApplyIds.add(oneByUserIdAndRecruitId.getId());
|
||||
if (firstLevelFile.isDirectory()) {
|
||||
File[] secondLevelFiles = firstLevelFile.listFiles();
|
||||
if (secondLevelFiles != null) {
|
||||
for (File secondLevelFile : secondLevelFiles) {
|
||||
String secondLevelFolderName = secondLevelFile.getName();
|
||||
System.out.println("第二层文件夹名称: " + secondLevelFolderName);
|
||||
if (secondLevelFile.isDirectory()) {
|
||||
File[] thirdLevelFiles = secondLevelFile.listFiles();
|
||||
if (thirdLevelFiles != null && thirdLevelFiles.length > 0) {
|
||||
// 删除数据库里的附件
|
||||
if ("BaoXian".equals(secondLevelFolderName)) {
|
||||
insurance.add(wgzUser.getUserId());
|
||||
}
|
||||
if ("HeTong".equals(secondLevelFolderName)) {
|
||||
contract.add(wgzUser.getUserId());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// 遍历目标目录路径,解析关键信息
|
||||
for (String dirPath : targetDirPaths) {
|
||||
// dirPath格式示例:"张三_110101199001011234/BaoXian/" 或 "李四_120101199002024567/HeTong/"
|
||||
String[] pathParts = dirPath.split(Pattern.quote(File.separator));
|
||||
if (pathParts.length < 2) {
|
||||
throw new BaseException("目录路径格式异常: " + dirPath);
|
||||
}
|
||||
|
||||
// 解析倒数第二层目录(名字_身份证号)和类型目录(BaoXian/HeTong)
|
||||
String secondLastDir = pathParts[0]; // 格式:名字_身份证号
|
||||
String lastDir = pathParts[1]; // 格式:BaoXian 或 HeTong(末尾可能有斜杠,需处理)
|
||||
lastDir = lastDir.replaceAll("/$", ""); // 移除末尾斜杠
|
||||
|
||||
// 验证类型目录是否合法
|
||||
if (!"BaoXian".equals(lastDir) && !"HeTong".equals(lastDir)) {
|
||||
continue; // 非目标类型目录,跳过
|
||||
}
|
||||
|
||||
// 从"名字_身份证号"中提取身份证号
|
||||
String[] nameIdCard = secondLastDir.split("_");
|
||||
if (nameIdCard.length != 2) {
|
||||
throw new BaseException("倒数第二层目录格式错误(需为'名字_身份证号'): " + secondLastDir);
|
||||
}
|
||||
String idCard = nameIdCard[1];
|
||||
|
||||
// 根据身份证号查询用户
|
||||
WgzUser wgzUser = wgzUserService.findByIdentityCard(idCard);
|
||||
if (wgzUser == null) {
|
||||
throw new BaseException("身份证号对应的用户不存在: " + idCard);
|
||||
}
|
||||
Long userId = wgzUser.getUserId();
|
||||
|
||||
// 查询用户对应的招工申请记录
|
||||
BgtProjectRecruitApply apply = recruitApplyService.getOneByUserIdAndRecruitId(userId, recruitId);
|
||||
if (apply == null) {
|
||||
throw new BaseException("用户未参与当前招工或申请记录不存在: 用户ID=" + userId + ", 招工ID=" + recruitId);
|
||||
}
|
||||
Long applyId = apply.getId();
|
||||
|
||||
// 根据类型分类收集数据
|
||||
if ("BaoXian".equals(lastDir)) {
|
||||
insuranceUserIds.add(userId);
|
||||
} else {
|
||||
contractUserIds.add(userId);
|
||||
}
|
||||
recruitApplyIds.add(applyId);
|
||||
}
|
||||
if (CollectionUtil.isNotEmpty(insurance)) {
|
||||
annexService.deleteByUserIdAndRecruitIdAndType(insurance, recruitId, "2", recruitApplyIds);
|
||||
|
||||
// 执行附件删除(与原逻辑一致,仅调整入参)
|
||||
if (CollectionUtil.isNotEmpty(insuranceUserIds)) {
|
||||
annexService.deleteByUserIdAndRecruitIdAndType(insuranceUserIds, recruitId, "2", recruitApplyIds);
|
||||
}
|
||||
if (CollectionUtil.isNotEmpty(contract)) {
|
||||
annexService.deleteByUserIdAndRecruitIdAndType(contract, recruitId, "1", recruitApplyIds);
|
||||
if (CollectionUtil.isNotEmpty(contractUserIds)) {
|
||||
annexService.deleteByUserIdAndRecruitIdAndType(contractUserIds, recruitId, "1", recruitApplyIds);
|
||||
}
|
||||
}
|
||||
|
||||
private void moveFilesToSaveDir(File sourceDir, Long recruitId, String username) throws IOException {
|
||||
// 移动到 SAVE_DIR
|
||||
private void moveFilesToSaveDir(File sourceDir, Long recruitId, String username, Map<String, String> leafFileMap) throws IOException {
|
||||
File saveDestDir = new File(SAVE_DIR);
|
||||
ensureDirectoryExists(saveDestDir);
|
||||
|
||||
BgtProjectRecruit recruit = recruitService.queryById(recruitId);
|
||||
String s = DigestUtil.md5Hex(recruit.getRecruitName());
|
||||
String firstLevelFolderName = recruit.getId() + "_" + s;
|
||||
String firstLevelFolderName = recruit.getId() + "_" + DigestUtil.md5Hex(recruit.getRecruitName());
|
||||
File firstLevelDestDir = new File(saveDestDir, firstLevelFolderName);
|
||||
ensureDirectoryExists(firstLevelDestDir);
|
||||
|
||||
File[] firstLevelFiles = sourceDir.listFiles();
|
||||
List<Annex> annexList = new ArrayList<>();
|
||||
if (firstLevelFiles != null) {
|
||||
for (File firstLevelFile : firstLevelFiles) {
|
||||
if (firstLevelFile.isDirectory()) {
|
||||
for (Map.Entry<String, String> entry : leafFileMap.entrySet()) {
|
||||
String key = entry.getKey(); // 格式:倒数第二层/倒数第一层/文件名(如:张三_123/BaoXian/文件.pdf)
|
||||
String relativePath = entry.getValue(); // 完整相对路径(如:张三_123/BaoXian/文件.pdf)
|
||||
|
||||
String firstLevelName = firstLevelFile.getName(); //解压目录
|
||||
File secondLevelDestDir = new File(firstLevelDestDir, firstLevelName); //保存目录
|
||||
|
||||
File[] secondLevelFiles = firstLevelFile.listFiles();
|
||||
if (secondLevelFiles != null) {
|
||||
for (File secondLevelfile : secondLevelFiles) {
|
||||
if (secondLevelfile.isDirectory()) {
|
||||
String secondLevelName = secondLevelfile.getName(); //解压目录
|
||||
File thirdLevelDestDir = new File(secondLevelDestDir, secondLevelName); //保存目录
|
||||
|
||||
File[] thirdLevelFiles = secondLevelfile.listFiles();
|
||||
if (thirdLevelFiles != null && thirdLevelFiles.length > 0) {
|
||||
deleteFolder(thirdLevelDestDir);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
moveFilesRecursively(firstLevelFile, firstLevelDestDir, annexList, recruitId, username);
|
||||
// 原文件路径:解压目录 + 相对路径
|
||||
File sourceFile = new File(sourceDir,relativePath);
|
||||
if (!sourceFile.exists() || !sourceFile.isFile()) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// 拆分原文件路径为目录部分和文件名部分
|
||||
String originalFileName = sourceFile.getName(); // 原文件名(含扩展名)
|
||||
String parentDirPath = key.substring(0, key.length() - originalFileName.length()); // 目录路径(如 "张三_123/BaoXian/")
|
||||
|
||||
// 分离文件名主体和扩展名(例如 "原文件" 和 ".pdf")
|
||||
int lastDotIndex = originalFileName.lastIndexOf('.');
|
||||
String fileNameWithoutExt = (lastDotIndex == -1) ? originalFileName : originalFileName.substring(0, lastDotIndex);
|
||||
String fileExtension = (lastDotIndex == -1) ? "" : originalFileName.substring(lastDotIndex);
|
||||
|
||||
// 生成MD5文件名(对文件名主体进行哈希,保留扩展名)
|
||||
String md5FileName = DigestUtil.md5Hex(fileNameWithoutExt); // MD5哈希值
|
||||
String newFileName = md5FileName + fileExtension; // 新文件名(如 "d41d8cd98f00b204e9800998ecf8427e.pdf")
|
||||
|
||||
// 构建目标文件路径(原目录结构 + MD5文件名)
|
||||
String newFilePath = parentDirPath + newFileName;
|
||||
File destFile = new File(firstLevelDestDir, newFilePath);
|
||||
ensureDirectoryExists(destFile.getParentFile());
|
||||
|
||||
// 复制文件到目标目录
|
||||
try (InputStream in = new FileInputStream(sourceFile);
|
||||
OutputStream out = new FileOutputStream(destFile)) {
|
||||
byte[] buffer = new byte[4096];
|
||||
int length;
|
||||
while ((length = in.read(buffer)) > 0) {
|
||||
out.write(buffer, 0, length);
|
||||
}
|
||||
}
|
||||
|
||||
// 记录附件信息(更新文件名为MD5后的值)
|
||||
String newRelativePath = SAVE_DIR + File.separator + newFilePath;
|
||||
newRelativePath = newRelativePath.replace("\\", "/").replace("ruoyi/uploadPath", "/profile");
|
||||
|
||||
String[] pathParts = relativePath.split(Pattern.quote(File.separator));
|
||||
String parentName = pathParts[pathParts.length - 3]; // 倒数第二层目录名(用户标识)
|
||||
String dirName = pathParts[pathParts.length - 2]; // 倒数第一层目录名(BaoXian/HeTong)
|
||||
|
||||
String[] userParts = parentName.split("_");
|
||||
String card = userParts[1];
|
||||
WgzUser wgzUser = wgzUserService.findByIdentityCard(card);
|
||||
BgtProjectRecruitApply apply = recruitApplyService.getOneByUserIdAndRecruitId(wgzUser.getUserId(), recruitId);
|
||||
|
||||
Annex annex = new Annex();
|
||||
annex.setAnnexName(newFileName);
|
||||
annex.setAnnexUrl(newRelativePath);
|
||||
annex.setAnnexType("BaoXian".equals(dirName) ? "2" : "1");
|
||||
annex.setUserType(Constants.WGZ);
|
||||
annex.setUserId(wgzUser.getUserId());
|
||||
annex.setRecruitId(recruitId);
|
||||
annex.setRecruitApplyId(apply.getId());
|
||||
annex.setCreateBy(username);
|
||||
annex.setUpdateBy(username);
|
||||
annexList.add(annex);
|
||||
}
|
||||
|
||||
if (CollectionUtil.isNotEmpty(annexList)) {
|
||||
annexService.saveBatch(annexList);
|
||||
}
|
||||
}
|
||||
|
||||
private void moveFilesRecursively(File source, File destination, List<Annex> annexList, Long recruitId, String username) throws IOException {
|
||||
if (source.isDirectory()) {
|
||||
File newDir = new File(destination, source.getName());
|
||||
ensureDirectoryExists(newDir);
|
||||
File[] files = source.listFiles();
|
||||
if (files != null) {
|
||||
for (File file : files) {
|
||||
moveFilesRecursively(file, newDir, annexList, recruitId, username);
|
||||
@Async
|
||||
public CompletableFuture<Void> asyncDeleteTempFiles(File extractDir, File zipFile) {
|
||||
return CompletableFuture.runAsync(() -> {
|
||||
try {
|
||||
// 仅清理临时解压目录和ZIP文件
|
||||
deleteFolder(extractDir);
|
||||
if (!zipFile.delete()) {
|
||||
System.err.println("无法删除压缩文件: " + zipFile.getAbsolutePath());
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
} else {
|
||||
File destFile = new File(destination, source.getName());
|
||||
ensureDirectoryExists(destFile.getParentFile());
|
||||
try (InputStream in = new FileInputStream(source);
|
||||
OutputStream out = new FileOutputStream(destFile)) {
|
||||
byte[] buffer = new byte[4096];
|
||||
int length;
|
||||
while ((length = in.read(buffer)) > 0) {
|
||||
out.write(buffer, 0, length);
|
||||
}
|
||||
}
|
||||
String relativePath = SAVE_DIR + File.separator + getRelativePath(source, new File(TEMP_DIR));
|
||||
relativePath = relativePath.replace("\\", "/").replace("ruoyi/uploadPath", "/profile");
|
||||
System.out.println("文件在项目里的相对目录: " + relativePath);
|
||||
// 存到数据库
|
||||
String parentName = destination.getParentFile().getName();
|
||||
System.out.println("上上一级文件名: " + parentName);
|
||||
String[] split = parentName.split("_");
|
||||
String card = split[1];
|
||||
WgzUser wgzUser = wgzUserService.findByIdentityCard(card);
|
||||
|
||||
BgtProjectRecruitApply oneByUserIdAndRecruitId = recruitApplyService.getOneByUserIdAndRecruitId(wgzUser.getUserId(), recruitId);
|
||||
|
||||
String name = destination.getName();
|
||||
System.out.println("上一级文件名: " + name);
|
||||
String type = "";
|
||||
if ("BaoXian".equals(name)) {
|
||||
type = "2";
|
||||
}
|
||||
if ("HeTong".equals(name)) {
|
||||
type = "1";
|
||||
}
|
||||
Annex annex = new Annex();
|
||||
annex.setAnnexName(destFile.getName());
|
||||
annex.setAnnexUrl(relativePath);
|
||||
annex.setAnnexType(type);
|
||||
annex.setUserType(Constants.WGZ);
|
||||
annex.setUserId(wgzUser.getUserId());
|
||||
annex.setRecruitId(recruitId);
|
||||
annex.setRecruitApplyId(oneByUserIdAndRecruitId.getId());
|
||||
annex.setCreateBy(username);
|
||||
annex.setUpdateBy(username);
|
||||
annexList.add(annex);
|
||||
}
|
||||
}
|
||||
|
||||
private void moveFilesToRecordDirRecursively(File source, File destination, String timeStamp, List<AnnexRecord> annexRecordList, Long recruitId, String username, Long userId) throws IOException {
|
||||
if (source.isDirectory()) {
|
||||
String folderName = source.getName();
|
||||
String[] parts = folderName.split("_");
|
||||
if (parts.length > 0 && parts[0].matches("\\d+") && parts.length > 1 && parts[0].equals(recruitId.toString())) {
|
||||
// 如果parts第一部分是数字并且长度大于1,跳过这一级目录的创建,直接处理下一级目录
|
||||
File[] files = source.listFiles();
|
||||
if (files != null) {
|
||||
for (File file : files) {
|
||||
moveFilesToRecordDirRecursively(file, destination, timeStamp, annexRecordList, recruitId, username, userId);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
File newDir = new File(destination, folderName);
|
||||
ensureDirectoryExists(newDir);
|
||||
File[] files = source.listFiles();
|
||||
if (files != null) {
|
||||
for (File file : files) {
|
||||
moveFilesToRecordDirRecursively(file, newDir, timeStamp, annexRecordList, recruitId, username, userId);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// 获取文件名和扩展名
|
||||
String fileName = source.getName();
|
||||
int dotIndex = fileName.lastIndexOf('.');
|
||||
String nameWithoutExtension = dotIndex == -1 ? fileName : fileName.substring(0, dotIndex);
|
||||
String extension = dotIndex == -1 ? "" : fileName.substring(dotIndex);
|
||||
|
||||
// 在文件名后面添加时间戳
|
||||
String newFileName = nameWithoutExtension + "_" + timeStamp + extension;
|
||||
File destFile = new File(destination, newFileName);
|
||||
|
||||
ensureDirectoryExists(destFile.getParentFile());
|
||||
try (InputStream in = new FileInputStream(source);
|
||||
OutputStream out = new FileOutputStream(destFile)) {
|
||||
byte[] buffer = new byte[4096];
|
||||
int length;
|
||||
while ((length = in.read(buffer)) > 0) {
|
||||
out.write(buffer, 0, length);
|
||||
}
|
||||
}
|
||||
|
||||
// 记录文件信息到数据库
|
||||
String relativePath = RECORD_DIR + File.separator + getRelativePath(destFile, new File(RECORD_DIR));
|
||||
relativePath = relativePath.replace("\\", "/").replace("ruoyi/uploadPath", "/profile");
|
||||
|
||||
String parentName = destination.getParentFile().getName();
|
||||
String[] split = parentName.split("_");
|
||||
String card = split[1];
|
||||
WgzUser wgzUser = wgzUserService.findByIdentityCard(card);
|
||||
|
||||
BgtProjectRecruitApply oneByUserIdAndRecruitId = recruitApplyService.getOneByUserIdAndRecruitId(wgzUser.getUserId(), recruitId);
|
||||
|
||||
String name = destination.getName();
|
||||
String type = "";
|
||||
if ("BaoXian".equals(name)) {
|
||||
type = "2";
|
||||
}
|
||||
if ("HeTong".equals(name)) {
|
||||
type = "1";
|
||||
}
|
||||
|
||||
AnnexRecord annexRecord = new AnnexRecord();
|
||||
annexRecord.setAnnexName(newFileName);
|
||||
annexRecord.setAnnexUrl(relativePath);
|
||||
annexRecord.setAnnexType(type);
|
||||
annexRecord.setUserType(Constants.WGZ);
|
||||
annexRecord.setUserId(wgzUser.getUserId());
|
||||
annexRecord.setRecruitId(recruitId);
|
||||
annexRecord.setRecruitApplyId(oneByUserIdAndRecruitId.getId());
|
||||
annexRecord.setCreateBy(username);
|
||||
annexRecord.setUpdateBy(username);
|
||||
annexRecord.setCreateUserId(userId);
|
||||
annexRecord.setCreateUserType(Constants.BGT);
|
||||
annexRecordList.add(annexRecord);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private String getRelativePath(File file, File baseDir) {
|
||||
|
@ -3,6 +3,8 @@ package com.ruoyi.web.controller.fbs;
|
||||
import com.ruoyi.common.core.controller.BaseController;
|
||||
import com.ruoyi.common.core.domain.AjaxResult;
|
||||
import com.ruoyi.common.core.page.TableDataInfo;
|
||||
import com.ruoyi.common.core.redis.RedisCache;
|
||||
import com.ruoyi.common.util.MessageUtil;
|
||||
import com.ruoyi.fbs.domain.FbsMessage;
|
||||
import com.ruoyi.fbs.domain.dto.FbsMessageDetailDTO;
|
||||
import com.ruoyi.fbs.domain.dto.FbsMessageMyListDTO;
|
||||
@ -29,7 +31,7 @@ import org.springframework.web.bind.annotation.*;
|
||||
public class AppFbsMessageController extends BaseController {
|
||||
|
||||
private final IFbsMessageService iFbsMessageService;
|
||||
|
||||
private final RedisCache redisCache;
|
||||
@ApiOperation("分包商未读消息统计")
|
||||
@GetMapping("/countUnread")
|
||||
public AjaxResult<FbsMessageCountVO> count() {
|
||||
@ -54,10 +56,14 @@ public class AppFbsMessageController extends BaseController {
|
||||
@ApiOperation("分包商消息已读")
|
||||
@PutMapping("/read/{id}")
|
||||
public AjaxResult<Boolean> read(@PathVariable(value = "id") Long id) {
|
||||
FbsMessage fbsMessage = new FbsMessage();
|
||||
fbsMessage.setId(id);
|
||||
fbsMessage.setReadStatus("1");
|
||||
return AjaxResult.success(iFbsMessageService.updateById(fbsMessage));
|
||||
FbsMessage fbsMessage = iFbsMessageService.getById(id);
|
||||
boolean b = true;
|
||||
if("0".equals(fbsMessage.getReadStatus())){
|
||||
MessageUtil.readMessagePush(fbsMessage.getRecipientType(), fbsMessage.getRecipientId(), fbsMessage.getMessageLargeType(), fbsMessage.getReadStatus());
|
||||
fbsMessage.setReadStatus("1");
|
||||
b = iFbsMessageService.updateById(fbsMessage);
|
||||
}
|
||||
return AjaxResult.success(b);
|
||||
}
|
||||
|
||||
@ApiOperation("分包商消息已操作")
|
||||
@ -69,4 +75,10 @@ public class AppFbsMessageController extends BaseController {
|
||||
return AjaxResult.success(iFbsMessageService.updateById(fbsMessage));
|
||||
}
|
||||
|
||||
@ApiOperation("消息详情")
|
||||
@GetMapping("/detail/{id}")
|
||||
public AjaxResult<FbsMessage> detail(@PathVariable(value = "id") Long id) {
|
||||
return AjaxResult.success(iFbsMessageService.getById(id));
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -148,6 +148,15 @@
|
||||
return AjaxResult.success(iWgzUserService.userPersonalBasicInformation(req));
|
||||
}
|
||||
|
||||
/**
|
||||
* 【我的】总收入
|
||||
*/
|
||||
@GetMapping("/grossIncome")
|
||||
public AjaxResult<BigDecimal> grossIncome() {
|
||||
return AjaxResult.success(iWgzPayCalculationService.grossIncome());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 【我的】【实名认证】实名认证
|
||||
*/
|
||||
|
@ -3,6 +3,7 @@ package com.ruoyi.web.controller.zbf;
|
||||
import com.ruoyi.common.core.controller.BaseController;
|
||||
import com.ruoyi.common.core.domain.AjaxResult;
|
||||
import com.ruoyi.common.core.page.TableDataInfo;
|
||||
import com.ruoyi.common.util.MessageUtil;
|
||||
import com.ruoyi.zbf.domain.ZbfMessage;
|
||||
import com.ruoyi.zbf.domain.dto.ZbfMessageDetailDTO;
|
||||
import com.ruoyi.zbf.domain.dto.ZbfMessageMyListDTO;
|
||||
@ -29,7 +30,6 @@ import org.springframework.web.bind.annotation.*;
|
||||
public class AppZbfMessageController extends BaseController {
|
||||
|
||||
private final IZbfMessageService iZbfMessageService;
|
||||
|
||||
/**
|
||||
* 查询消息列表
|
||||
*/
|
||||
@ -55,10 +55,14 @@ public class AppZbfMessageController extends BaseController {
|
||||
@ApiOperation("总包方消息已读")
|
||||
@PutMapping("/read/{id}")
|
||||
public AjaxResult<Boolean> read(@PathVariable(value = "id") Long id) {
|
||||
ZbfMessage zbfMessage = new ZbfMessage();
|
||||
zbfMessage.setId(id);
|
||||
zbfMessage.setReadStatus("1");
|
||||
return AjaxResult.success(iZbfMessageService.updateById(zbfMessage));
|
||||
ZbfMessage zbfMessage = iZbfMessageService.getById(id);
|
||||
boolean b= true;
|
||||
if("0".equals(zbfMessage.getReadStatus())){
|
||||
MessageUtil.readMessagePush(zbfMessage.getRecipientType(), zbfMessage.getRecipientId(), zbfMessage.getMessageLargeType(), zbfMessage.getReadStatus());
|
||||
zbfMessage.setReadStatus("1");
|
||||
iZbfMessageService.updateById(zbfMessage);
|
||||
}
|
||||
return AjaxResult.success(b);
|
||||
}
|
||||
|
||||
@ApiOperation("总包方消息已操作")
|
||||
|
@ -86,7 +86,7 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter
|
||||
* hasRole | 如果有参数,参数表示角色,则其角色可以访问
|
||||
* permitAll | 用户可以任意访问
|
||||
* rememberMe | 允许通过remember-me登录的用户访问
|
||||
* authenticated | 用户登录后可访问
|
||||
* authenticated | 用户登录后可访问 "/sse/subscribe",
|
||||
*/
|
||||
@Override
|
||||
protected void configure(HttpSecurity httpSecurity) throws Exception
|
||||
|
@ -17,12 +17,12 @@ import com.ruoyi.bgt.domain.vo.BgtMessageDetailVO;
|
||||
import com.ruoyi.bgt.domain.vo.BgtMessageVO;
|
||||
import com.ruoyi.bgt.mapper.BgtMessageMapper;
|
||||
import com.ruoyi.bgt.service.IBgtMessageService;
|
||||
import com.ruoyi.bgt.service.IBgtProjectRecruitApplyService;
|
||||
import com.ruoyi.bgt.service.IBgtProjectRecruitService;
|
||||
import com.ruoyi.bgt.service.IBgtWageApplicationService;
|
||||
import com.ruoyi.common.core.mybatisplus.core.ServicePlusImpl;
|
||||
import com.ruoyi.common.core.page.TableDataInfo;
|
||||
import com.ruoyi.common.core.redis.RedisCache;
|
||||
import com.ruoyi.common.enums.BgtMessageType;
|
||||
import com.ruoyi.common.util.MessageUtil;
|
||||
import com.ruoyi.common.utils.PageUtils;
|
||||
import com.ruoyi.common.utils.SecurityUtils;
|
||||
import com.ruoyi.fbs.domain.FbsProjectTask;
|
||||
@ -32,7 +32,10 @@ import com.ruoyi.fbs.service.IFbsProjectTaskService;
|
||||
import com.ruoyi.wgz.domain.WgzDailyClock;
|
||||
import com.ruoyi.wgz.domain.WgzLeave;
|
||||
import com.ruoyi.wgz.domain.WgzReissueacard;
|
||||
import com.ruoyi.wgz.service.*;
|
||||
import com.ruoyi.wgz.service.IWgzDailyClockService;
|
||||
import com.ruoyi.wgz.service.IWgzLeaveService;
|
||||
import com.ruoyi.wgz.service.IWgzReissueacardService;
|
||||
import com.ruoyi.wgz.service.IWgzUserService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.stereotype.Service;
|
||||
@ -59,15 +62,7 @@ import static com.ruoyi.common.constants.WgzAndBgtMessageConstant.OPERATION_NEED
|
||||
public class BgtMessageServiceImpl extends ServicePlusImpl<BgtMessageMapper, BgtMessage> implements IBgtMessageService {
|
||||
|
||||
@Autowired
|
||||
@Lazy
|
||||
private IBgtProjectRecruitApplyService recruitApplyService;
|
||||
|
||||
@Autowired
|
||||
private IBgtProjectRecruitService recruitService;
|
||||
|
||||
@Autowired
|
||||
@Lazy
|
||||
private IWgzPayCalculationService payCalculationService;
|
||||
private RedisCache redisCache;
|
||||
|
||||
@Autowired
|
||||
@Lazy
|
||||
@ -170,11 +165,14 @@ public class BgtMessageServiceImpl extends ServicePlusImpl<BgtMessageMapper, Bgt
|
||||
@Override
|
||||
@Transactional
|
||||
public Boolean sendAMessage(BgtMessage bo) {
|
||||
return save(bo);
|
||||
boolean save = save(bo);
|
||||
MessageUtil.saveMessagePush(bo.getRecipientType(), bo.getRecipientId(), bo.getMessageLargeType(), bo.getIsOperation());
|
||||
return save;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BgtMessageCountVO countUnread() {
|
||||
// Object cacheObject = redisCache.getCacheObject(REIDS_KEY + SecurityUtils.getAppUserId());
|
||||
List<BgtMessage> bgtMessages = baseMapper.selectList(Wrappers.<BgtMessage>lambdaQuery()
|
||||
.eq(BgtMessage::getRecipientId, SecurityUtils.getAppUserId())
|
||||
.eq(BgtMessage::getReadStatus, "0"));
|
||||
@ -189,6 +187,7 @@ public class BgtMessageServiceImpl extends ServicePlusImpl<BgtMessageMapper, Bgt
|
||||
.eq(BgtMessage::getRecipientId, SecurityUtils.getAppUserId())
|
||||
.eq(BgtMessage::getIsOperation, OPERATION_NEED));
|
||||
bgtMessageCountVO.setHandleMessageCount(handle);
|
||||
redisCache.setCacheObject(REDIS_KEY+SecurityUtils.getAppUserId(), bgtMessageCountVO);
|
||||
return bgtMessageCountVO;
|
||||
}
|
||||
|
||||
@ -283,6 +282,7 @@ public class BgtMessageServiceImpl extends ServicePlusImpl<BgtMessageMapper, Bgt
|
||||
wrapper.eq(BgtMessage::getTableName, tableName);
|
||||
wrapper.set(BgtMessage::getIsOperation, OPERATION_ALREADY);
|
||||
update(wrapper);
|
||||
MessageUtil.operationMessagePush(recipientType, recipientId, 1);
|
||||
}
|
||||
|
||||
|
||||
|
@ -611,7 +611,7 @@ public class BgtProjectRecruitApplyServiceImpl extends ServicePlusImpl<BgtProjec
|
||||
.setRecipientId(vo.getUserId())
|
||||
.setHeadline(map.get(HEADLINE))
|
||||
.setSubheading(map.get(SUBHEADING))
|
||||
.setTableId(vo.getRecruitId())
|
||||
.setTableId(vo.getId())
|
||||
.setTableName(SqlHelper.table(BgtProjectRecruitApply.class).getTableName())
|
||||
.setMessageLargeType(LARGE_OTHER)
|
||||
.setMessageSmallType(SMALL_EXIT);
|
||||
@ -741,7 +741,7 @@ public class BgtProjectRecruitApplyServiceImpl extends ServicePlusImpl<BgtProjec
|
||||
throw new RuntimeException("修改招工申请信息失败!");
|
||||
}
|
||||
//3-2、修改消息
|
||||
boolean b = iWgzMessageService.updateById(new WgzMessage().setId(req.getMessageId()).setIsOperation("2"));
|
||||
boolean b = iWgzMessageService.updateOperationStatus(req.getMessageId());
|
||||
if (!b) {
|
||||
throw new RuntimeException("修改消息失败!");
|
||||
}
|
||||
|
@ -9,17 +9,19 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.baomidou.mybatisplus.extension.toolkit.SqlHelper;
|
||||
import com.ruoyi.bgt.bo.BgtProjectTaskProgressQueryBo;
|
||||
import com.ruoyi.bgt.domain.BgtMessage;
|
||||
import com.ruoyi.bgt.domain.BgtProjectRecruit;
|
||||
import com.ruoyi.bgt.domain.BgtProjectTaskProgress;
|
||||
import com.ruoyi.bgt.domain.dto.BgtProjectTaskProgressQueryDTO;
|
||||
import com.ruoyi.bgt.domain.vo.BgtProjectTaskProgressDetailVO;
|
||||
import com.ruoyi.bgt.domain.vo.BgtProjectTaskProgressVO;
|
||||
import com.ruoyi.bgt.mapper.BgtProjectTaskProgressMapper;
|
||||
import com.ruoyi.bgt.service.IBgtMessageService;
|
||||
import com.ruoyi.bgt.service.IBgtProjectRecruitApplyService;
|
||||
import com.ruoyi.bgt.service.IBgtProjectRecruitService;
|
||||
import com.ruoyi.bgt.service.IBgtProjectTaskProgressService;
|
||||
import com.ruoyi.common.core.mybatisplus.core.ServicePlusImpl;
|
||||
import com.ruoyi.common.core.page.TableDataInfo;
|
||||
import com.ruoyi.common.enums.AuditStatus;
|
||||
import com.ruoyi.common.enums.RecruitStatus;
|
||||
import com.ruoyi.common.exception.BaseException;
|
||||
import com.ruoyi.common.utils.PageUtils;
|
||||
import com.ruoyi.common.utils.SecurityUtils;
|
||||
@ -55,7 +57,7 @@ public class BgtProjectTaskProgressServiceImpl extends ServicePlusImpl<BgtProjec
|
||||
@Autowired
|
||||
private IBgtMessageService bgtMessageService;
|
||||
@Autowired
|
||||
private IBgtProjectRecruitApplyService recruitApplyService;
|
||||
private IBgtProjectRecruitService recruitService;
|
||||
|
||||
@Override
|
||||
public BgtProjectTaskProgress queryById(Long id){
|
||||
@ -159,6 +161,16 @@ public class BgtProjectTaskProgressServiceImpl extends ServicePlusImpl<BgtProjec
|
||||
if(lastProgress>=entity.getProgress()){
|
||||
throw new BaseException("当前进度不能小于等于上一个进度");
|
||||
}
|
||||
if(entity.getProgress()==100){
|
||||
List<BgtProjectRecruit> recruitList = recruitService.list(Wrappers.<BgtProjectRecruit>lambdaQuery()
|
||||
.eq(BgtProjectRecruit::getTaskId, entity.getTaskId())
|
||||
.ne(BgtProjectRecruit::getStatus, RecruitStatus.OVERDUE.getCode())
|
||||
);
|
||||
if(CollectionUtil.isNotEmpty(recruitList)){
|
||||
throw new BaseException("招工结束前不能完成任务");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
@ -7,6 +7,7 @@ import java.util.Map;
|
||||
|
||||
public class BgtMessageConstant {
|
||||
// 公共常量
|
||||
public static final String REDIS_KEY = "messageCount:bgt:";
|
||||
|
||||
public static final String BGT_LARGE_TASK = "1"; //大类型-任务
|
||||
public static final String BGT_LARGE_SETTLEMENT = "2"; //大类型-结算
|
||||
|
@ -10,6 +10,7 @@ import static com.ruoyi.common.constants.BgtMessageConstant.SUBHEADING;
|
||||
|
||||
public class FbsMessageConstant {
|
||||
// 公共常量
|
||||
public static final String REDIS_KEY = "messageCount:fbs:";
|
||||
|
||||
public static final String FBS_LARGE_TASK = "1"; //大类型-项目
|
||||
public static final String FBS_LARGE_SETTLEMENT = "2"; //大类型-结算
|
||||
|
@ -3,12 +3,14 @@ package com.ruoyi.common.constants;
|
||||
import java.util.Map;
|
||||
|
||||
public class WgzAndBgtMessageConstant {
|
||||
|
||||
public static final String REDIS_KEY = "messageCount:wgz:";
|
||||
// 公共常量
|
||||
public static final String USERTYPE_SYSTEM = "0"; //系统
|
||||
public static final String USERTYPE_WGZ = "1"; //务工者
|
||||
public static final String USERTYPE_BGT = "2"; //包工头
|
||||
public static final String USERTYPE_FBS = "3"; //分包商
|
||||
public static final String USERTYPE_ZBF = "4"; //分包商
|
||||
public static final String USERTYPE_ZBF = "4"; //总包方
|
||||
|
||||
//系统ID
|
||||
public static final Long SYSTEM_ID = 0L;
|
||||
|
@ -11,6 +11,8 @@ import static com.ruoyi.common.constants.BgtMessageConstant.SUBHEADING;
|
||||
public class ZbfMessageConstant {
|
||||
// 公共常量
|
||||
|
||||
public static final String REDIS_KEY = "messageCount:zbf:";
|
||||
|
||||
public static final String ZBF_LARGE_TASK = "1"; //大类型-任务
|
||||
public static final String ZBF_LARGE_SETTLEMENT = "2"; //大类型-结算
|
||||
public static final String ZBF_LARGE_OTHER = "3"; //大类型-其它
|
||||
|
@ -64,4 +64,6 @@ public class CompanyAuthenticateDTO {
|
||||
@ApiModelProperty("资质与荣誉")
|
||||
private String url;
|
||||
|
||||
@ApiModelProperty("备注")
|
||||
private String remark;
|
||||
}
|
||||
|
@ -0,0 +1,297 @@
|
||||
package com.ruoyi.common.util;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import com.ruoyi.bgt.domain.vo.BgtMessageCountVO;
|
||||
import com.ruoyi.common.constants.BgtMessageConstant;
|
||||
import com.ruoyi.common.constants.FbsMessageConstant;
|
||||
import com.ruoyi.common.constants.WgzAndBgtMessageConstant;
|
||||
import com.ruoyi.common.constants.ZbfMessageConstant;
|
||||
import com.ruoyi.common.core.redis.RedisCache;
|
||||
import com.ruoyi.common.utils.spring.SpringUtils;
|
||||
import com.ruoyi.fbs.domain.vo.FbsMessageCountVO;
|
||||
import com.ruoyi.wgz.bo.res.WgzAppMessageTypeStatisticsRes;
|
||||
import com.ruoyi.zbf.domain.vo.ZbfMessageCountVO;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import static com.ruoyi.common.constants.BgtMessageConstant.*;
|
||||
import static com.ruoyi.common.constants.FbsMessageConstant.*;
|
||||
import static com.ruoyi.common.constants.WgzAndBgtMessageConstant.OPERATION_NEED;
|
||||
import static com.ruoyi.common.constants.ZbfMessageConstant.*;
|
||||
|
||||
public class MessageUtil {
|
||||
|
||||
//获取日志
|
||||
public static final Logger log = LoggerFactory.getLogger(MessageUtil.class);
|
||||
|
||||
/**
|
||||
* 保存消息是像客户端发送消息
|
||||
*
|
||||
* @param recipientType 用户类型
|
||||
* @param recipientId 用户ID
|
||||
* @param messageLargeType 消息大类型
|
||||
* @param isOperation 操作类型
|
||||
*/
|
||||
public static void saveMessagePush(String recipientType, Long recipientId, String messageLargeType, String isOperation) {
|
||||
try {
|
||||
String messageKey = "";
|
||||
String data = "";
|
||||
String redisKey = "";
|
||||
Object cacheObject;
|
||||
RedisCache redisCache = SpringUtils.getBean(RedisCache.class);
|
||||
switch (recipientType) {
|
||||
case WgzAndBgtMessageConstant.USERTYPE_WGZ:
|
||||
redisKey = WgzAndBgtMessageConstant.REDIS_KEY + recipientId;
|
||||
messageKey = SseUtil.WGZ_PREFIX + recipientId;
|
||||
cacheObject = redisCache.getCacheObject(redisKey);
|
||||
if (cacheObject != null) {
|
||||
WgzAppMessageTypeStatisticsRes res = (WgzAppMessageTypeStatisticsRes) cacheObject;
|
||||
Map<String, Integer> mp = res.getMp();
|
||||
if ("0".equals(messageLargeType)) {
|
||||
mp.put("0", mp.get("0") + 1);
|
||||
} else if ("1".equals(messageLargeType)) {
|
||||
mp.put("1", mp.get("1") + 1);
|
||||
} else if ("2".equals(messageLargeType)) {
|
||||
mp.put("2", mp.get("2") + 1);
|
||||
}
|
||||
if (OPERATION_NEED.equals(isOperation)) {
|
||||
mp.put("3", mp.get("3") + 1);
|
||||
}
|
||||
redisCache.setCacheObject(redisKey, res);
|
||||
data = JSONUtil.toJsonStr(res);
|
||||
}
|
||||
break;
|
||||
case WgzAndBgtMessageConstant.USERTYPE_BGT:
|
||||
redisKey = BgtMessageConstant.REDIS_KEY + recipientId;
|
||||
messageKey = SseUtil.BGT_PREFIX + recipientId;
|
||||
cacheObject = redisCache.getCacheObject(redisKey);
|
||||
if (cacheObject != null) {
|
||||
BgtMessageCountVO bgtMessageCountVO = (BgtMessageCountVO) cacheObject;
|
||||
if (BGT_LARGE_TASK.equals(messageLargeType)) {
|
||||
bgtMessageCountVO.setTaskMessageCount(bgtMessageCountVO.getTaskMessageCount() + 1);
|
||||
} else if (BGT_LARGE_SETTLEMENT.equals(messageLargeType)) {
|
||||
bgtMessageCountVO.setSettlementMessageCount(bgtMessageCountVO.getSettlementMessageCount() + 1);
|
||||
} else if (BGT_LARGE_OTHER.equals(messageLargeType)) {
|
||||
bgtMessageCountVO.setOtherMessageCount(bgtMessageCountVO.getOtherMessageCount() + 1);
|
||||
}
|
||||
if (OPERATION_NEED.equals(isOperation)) {
|
||||
bgtMessageCountVO.setHandleMessageCount(bgtMessageCountVO.getHandleMessageCount() + 1);
|
||||
}
|
||||
redisCache.setCacheObject(redisKey, bgtMessageCountVO);
|
||||
data = JSONUtil.toJsonStr(bgtMessageCountVO);
|
||||
}
|
||||
break;
|
||||
case WgzAndBgtMessageConstant.USERTYPE_FBS:
|
||||
redisKey = FbsMessageConstant.REDIS_KEY + recipientId;
|
||||
messageKey = SseUtil.FBS_PREFIX + recipientId;
|
||||
cacheObject = redisCache.getCacheObject(redisKey);
|
||||
if (cacheObject != null) {
|
||||
FbsMessageCountVO fbsMessageCountVO = (FbsMessageCountVO) cacheObject;
|
||||
if (FBS_LARGE_TASK.equals(messageLargeType)) {
|
||||
fbsMessageCountVO.setTaskMessageCount(fbsMessageCountVO.getTaskMessageCount() + 1);
|
||||
} else if (FBS_LARGE_SETTLEMENT.equals(messageLargeType)) {
|
||||
fbsMessageCountVO.setSettlementMessageCount(fbsMessageCountVO.getSettlementMessageCount() + 1);
|
||||
} else if (FBS_LARGE_OTHER.equals(messageLargeType)) {
|
||||
fbsMessageCountVO.setOtherMessageCount(fbsMessageCountVO.getOtherMessageCount() + 1);
|
||||
}
|
||||
if (OPERATION_NEED.equals(isOperation)) {
|
||||
fbsMessageCountVO.setHandleMessageCount(fbsMessageCountVO.getHandleMessageCount() + 1);
|
||||
}
|
||||
redisCache.setCacheObject(redisKey, fbsMessageCountVO);
|
||||
data = JSONUtil.toJsonStr(fbsMessageCountVO);
|
||||
}
|
||||
break;
|
||||
case WgzAndBgtMessageConstant.USERTYPE_ZBF:
|
||||
redisKey = ZbfMessageConstant.REDIS_KEY + recipientId;
|
||||
messageKey = SseUtil.ZBF_PREFIX + recipientId;
|
||||
cacheObject = redisCache.getCacheObject(redisKey);
|
||||
if (cacheObject != null) {
|
||||
ZbfMessageCountVO zbfMessageCountVO = (ZbfMessageCountVO) cacheObject;
|
||||
if (ZBF_LARGE_TASK.equals(messageLargeType)) {
|
||||
zbfMessageCountVO.setTaskMessageCount(zbfMessageCountVO.getTaskMessageCount() + 1);
|
||||
} else if (ZBF_LARGE_SETTLEMENT.equals(messageLargeType)) {
|
||||
zbfMessageCountVO.setSettlementMessageCount(zbfMessageCountVO.getSettlementMessageCount() + 1);
|
||||
} else if (ZBF_LARGE_OTHER.equals(messageLargeType)) {
|
||||
zbfMessageCountVO.setOtherMessageCount(zbfMessageCountVO.getOtherMessageCount() + 1);
|
||||
}
|
||||
if (OPERATION_NEED.equals(isOperation)) {
|
||||
zbfMessageCountVO.setHandleMessageCount(zbfMessageCountVO.getHandleMessageCount() + 1);
|
||||
}
|
||||
redisCache.setCacheObject(redisKey, zbfMessageCountVO);
|
||||
data = JSONUtil.toJsonStr(zbfMessageCountVO);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if(StrUtil.isNotBlank(data)){
|
||||
SseUtil.pushMessage(messageKey, data);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("sse推送异常", e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static void readMessagePush(String recipientType, Long recipientId, String messageLargeType, String readStatus) {
|
||||
try {
|
||||
String messageKey = "";
|
||||
String data = "";
|
||||
String redisKey;
|
||||
Object cacheObject;
|
||||
RedisCache redisCache = SpringUtils.getBean(RedisCache.class);
|
||||
switch (recipientType) {
|
||||
case WgzAndBgtMessageConstant.USERTYPE_WGZ:
|
||||
redisKey = WgzAndBgtMessageConstant.REDIS_KEY + recipientId;
|
||||
messageKey = SseUtil.WGZ_PREFIX + recipientId;
|
||||
|
||||
cacheObject = redisCache.getCacheObject(redisKey);
|
||||
if (cacheObject != null && "0".equals(readStatus)) {
|
||||
WgzAppMessageTypeStatisticsRes res = (WgzAppMessageTypeStatisticsRes) cacheObject;
|
||||
Map<String, Integer> mp = res.getMp();
|
||||
if ("0".equals(messageLargeType)) {
|
||||
mp.put("0", mp.get("0") - 1);
|
||||
} else if ("1".equals(messageLargeType)) {
|
||||
mp.put("1", mp.get("1") - 1);
|
||||
} else if ("2".equals(messageLargeType)) {
|
||||
mp.put("2", mp.get("2") - 1);
|
||||
}
|
||||
redisCache.setCacheObject(redisKey, res);
|
||||
data = JSONUtil.toJsonStr(res);
|
||||
}
|
||||
break;
|
||||
case WgzAndBgtMessageConstant.USERTYPE_BGT:
|
||||
redisKey = BgtMessageConstant.REDIS_KEY + recipientId;
|
||||
messageKey = SseUtil.BGT_PREFIX + recipientId;
|
||||
|
||||
cacheObject = redisCache.getCacheObject(redisKey);
|
||||
if (cacheObject != null && "0".equals(readStatus)) {
|
||||
BgtMessageCountVO bgtMessageCountVO = (BgtMessageCountVO) cacheObject;
|
||||
if (BGT_LARGE_TASK.equals(messageLargeType)) {
|
||||
bgtMessageCountVO.setTaskMessageCount(bgtMessageCountVO.getTaskMessageCount() - 1);
|
||||
} else if (BGT_LARGE_SETTLEMENT.equals(messageLargeType)) {
|
||||
bgtMessageCountVO.setSettlementMessageCount(bgtMessageCountVO.getSettlementMessageCount() - 1);
|
||||
} else if (BGT_LARGE_OTHER.equals(messageLargeType)) {
|
||||
bgtMessageCountVO.setOtherMessageCount(bgtMessageCountVO.getOtherMessageCount() - 1);
|
||||
}
|
||||
redisCache.setCacheObject(redisKey, bgtMessageCountVO);
|
||||
data = JSONUtil.toJsonStr(bgtMessageCountVO);
|
||||
}
|
||||
|
||||
break;
|
||||
case WgzAndBgtMessageConstant.USERTYPE_FBS:
|
||||
redisKey = FbsMessageConstant.REDIS_KEY + recipientId;
|
||||
messageKey = SseUtil.FBS_PREFIX + recipientId;
|
||||
|
||||
cacheObject = redisCache.getCacheObject(redisKey);
|
||||
if (cacheObject != null && "0".equals(readStatus)) {
|
||||
FbsMessageCountVO fbsMessageCountVO = (FbsMessageCountVO) cacheObject;
|
||||
if (FBS_LARGE_TASK.equals(messageLargeType)) {
|
||||
fbsMessageCountVO.setTaskMessageCount(fbsMessageCountVO.getTaskMessageCount() - 1);
|
||||
} else if (FBS_LARGE_SETTLEMENT.equals(messageLargeType)) {
|
||||
fbsMessageCountVO.setSettlementMessageCount(fbsMessageCountVO.getSettlementMessageCount() - 1);
|
||||
} else if (FBS_LARGE_OTHER.equals(messageLargeType)) {
|
||||
fbsMessageCountVO.setOtherMessageCount(fbsMessageCountVO.getOtherMessageCount() - 1);
|
||||
}
|
||||
redisCache.setCacheObject(redisKey, fbsMessageCountVO);
|
||||
data = JSONUtil.toJsonStr(fbsMessageCountVO);
|
||||
}
|
||||
break;
|
||||
case WgzAndBgtMessageConstant.USERTYPE_ZBF:
|
||||
redisKey = ZbfMessageConstant.REDIS_KEY + recipientId;
|
||||
messageKey = SseUtil.ZBF_PREFIX + recipientId;
|
||||
|
||||
cacheObject = redisCache.getCacheObject(redisKey);
|
||||
if (cacheObject != null && "0".equals(readStatus)) {
|
||||
ZbfMessageCountVO zbfMessageCountVO = (ZbfMessageCountVO) cacheObject;
|
||||
if (ZBF_LARGE_TASK.equals(messageLargeType)) {
|
||||
zbfMessageCountVO.setTaskMessageCount(zbfMessageCountVO.getTaskMessageCount() - 1);
|
||||
} else if (ZBF_LARGE_SETTLEMENT.equals(messageLargeType)) {
|
||||
zbfMessageCountVO.setSettlementMessageCount(zbfMessageCountVO.getSettlementMessageCount() - 1);
|
||||
} else if (ZBF_LARGE_OTHER.equals(messageLargeType)) {
|
||||
zbfMessageCountVO.setOtherMessageCount(zbfMessageCountVO.getOtherMessageCount() - 1);
|
||||
}
|
||||
redisCache.setCacheObject(redisKey, zbfMessageCountVO);
|
||||
data = JSONUtil.toJsonStr(zbfMessageCountVO);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if(StrUtil.isNotBlank(data)){
|
||||
SseUtil.pushMessage(messageKey, data);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("sse推送异常", e);
|
||||
}
|
||||
}
|
||||
|
||||
public static void operationMessagePush(String recipientType, Long recipientId, Integer num) {
|
||||
try {
|
||||
String messageKey = "";
|
||||
String data = "";
|
||||
String redisKey;
|
||||
Object cacheObject;
|
||||
RedisCache redisCache = SpringUtils.getBean(RedisCache.class);
|
||||
switch (recipientType) {
|
||||
case WgzAndBgtMessageConstant.USERTYPE_WGZ:
|
||||
redisKey = WgzAndBgtMessageConstant.REDIS_KEY + recipientId;
|
||||
messageKey = SseUtil.WGZ_PREFIX + recipientId;
|
||||
cacheObject = redisCache.getCacheObject(redisKey);
|
||||
if (cacheObject != null) {
|
||||
WgzAppMessageTypeStatisticsRes res = (WgzAppMessageTypeStatisticsRes) cacheObject;
|
||||
Map<String, Integer> mp = res.getMp();
|
||||
mp.put("3", mp.get("3") - num);
|
||||
redisCache.setCacheObject(redisKey, res);
|
||||
data = JSONUtil.toJsonStr(res);
|
||||
}
|
||||
break;
|
||||
case WgzAndBgtMessageConstant.USERTYPE_BGT:
|
||||
redisKey = BgtMessageConstant.REDIS_KEY + recipientId;
|
||||
messageKey = SseUtil.BGT_PREFIX + recipientId;
|
||||
cacheObject = redisCache.getCacheObject(redisKey);
|
||||
if (cacheObject != null) {
|
||||
BgtMessageCountVO bgtMessageCountVO = (BgtMessageCountVO) cacheObject;
|
||||
bgtMessageCountVO.setHandleMessageCount(bgtMessageCountVO.getHandleMessageCount() - num);
|
||||
redisCache.setCacheObject(redisKey, bgtMessageCountVO);
|
||||
data = JSONUtil.toJsonStr(bgtMessageCountVO);
|
||||
}
|
||||
|
||||
break;
|
||||
case WgzAndBgtMessageConstant.USERTYPE_FBS:
|
||||
redisKey = FbsMessageConstant.REDIS_KEY + recipientId;
|
||||
messageKey = SseUtil.FBS_PREFIX + recipientId;
|
||||
cacheObject = redisCache.getCacheObject(redisKey);
|
||||
if (cacheObject != null) {
|
||||
FbsMessageCountVO fbsMessageCountVO = (FbsMessageCountVO) cacheObject;
|
||||
fbsMessageCountVO.setHandleMessageCount(fbsMessageCountVO.getHandleMessageCount() - num);
|
||||
redisCache.setCacheObject(redisKey, fbsMessageCountVO);
|
||||
data = JSONUtil.toJsonStr(fbsMessageCountVO);
|
||||
}
|
||||
|
||||
break;
|
||||
case WgzAndBgtMessageConstant.USERTYPE_ZBF:
|
||||
redisKey = ZbfMessageConstant.REDIS_KEY + recipientId;
|
||||
messageKey = SseUtil.ZBF_PREFIX + recipientId;
|
||||
cacheObject = redisCache.getCacheObject(redisKey);
|
||||
if (cacheObject != null) {
|
||||
ZbfMessageCountVO zbfMessageCountVO = (ZbfMessageCountVO) cacheObject;
|
||||
zbfMessageCountVO.setHandleMessageCount(zbfMessageCountVO.getHandleMessageCount() - num);
|
||||
redisCache.setCacheObject(redisKey, zbfMessageCountVO);
|
||||
data = JSONUtil.toJsonStr(zbfMessageCountVO);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if(StrUtil.isNotBlank(data)){
|
||||
SseUtil.pushMessage(messageKey, data);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("sse推送异常", e);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,75 @@
|
||||
package com.ruoyi.common.util;
|
||||
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import com.ruoyi.common.core.redis.RedisCache;
|
||||
import com.ruoyi.common.utils.spring.SpringUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
public class SseUtil {
|
||||
//日志
|
||||
private static final Logger log = LoggerFactory.getLogger(SseUtil.class);
|
||||
|
||||
private final static Map<String, SseEmitter> emitterMap = new ConcurrentHashMap<>();
|
||||
|
||||
public static final String WGZ_PREFIX = "wgz-";
|
||||
public static final String BGT_PREFIX = "bgt-";
|
||||
public static final String FBS_PREFIX = "fbs-";
|
||||
public static final String ZBF_PREFIX = "zbf-";
|
||||
public static SseEmitter subscribe(String userId,String prefix) {
|
||||
// Spring Boot 2.4.7中SseEmitter构造函数支持超时时间(单位:毫秒)
|
||||
SseEmitter emitter = new SseEmitter(1 * 60 * 1000L); // 30分钟超时
|
||||
|
||||
// 存储emitter并设置回调(2.4.7中回调机制与主流版本一致)
|
||||
String key = prefix + "-" +userId;
|
||||
emitterMap.put(key, emitter);
|
||||
|
||||
// 利用闭包特性捕获userId和prefix
|
||||
emitter.onCompletion(() -> emitterMap.remove(key));
|
||||
emitter.onTimeout(() -> {
|
||||
emitter.complete();
|
||||
emitterMap.remove(key);
|
||||
log.info("用户{}连接已超时", key);
|
||||
});
|
||||
emitter.onError(e -> emitterMap.remove(key));
|
||||
|
||||
String redisKey = "messageCount:"+prefix+":"+userId;
|
||||
|
||||
Object cacheObj = SpringUtils.getBean(RedisCache.class).getCacheObject(redisKey);
|
||||
// String name = cacheObj == null ? "connect" + userId : "messageCount";
|
||||
String data = cacheObj == null ? "连接已建立,用户ID:" + userId : JSONUtil.toJsonStr(cacheObj);
|
||||
// 发送初始连接确认
|
||||
try {
|
||||
emitter.send(SseEmitter.event()
|
||||
// .id("init")
|
||||
// .name(name)
|
||||
.data(data)
|
||||
);
|
||||
} catch (IOException e) {
|
||||
emitter.completeWithError(e);
|
||||
}
|
||||
return emitter;
|
||||
}
|
||||
|
||||
public static void pushMessage(String key,String data){
|
||||
SseEmitter emitter = emitterMap.get(key);
|
||||
if (emitter != null) {
|
||||
try {
|
||||
// 发送自定义事件(客户端通过事件名监听)
|
||||
emitter.send(SseEmitter.event()
|
||||
// .id(String.valueOf(System.currentTimeMillis()))
|
||||
// .name("messageCount")
|
||||
.data(data)
|
||||
);
|
||||
} catch (IOException e) {
|
||||
emitter.completeWithError(e);
|
||||
emitterMap.remove(key); // 异常时清理无效连接
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -46,4 +46,6 @@ public class FbsProjectDetailVO {
|
||||
@ApiModelProperty("标段列表")
|
||||
private List<FbsProjectSectionListVO> sectionList;
|
||||
|
||||
@ApiModelProperty("备注")
|
||||
private String remark;
|
||||
}
|
||||
|
@ -22,6 +22,11 @@ public class FbsProjectSectionListVO {
|
||||
@ApiModelProperty("项目地址")
|
||||
private String projectAddress;
|
||||
|
||||
|
||||
@ApiModelProperty("标段描述")
|
||||
private String sectionDescribe;
|
||||
|
||||
|
||||
@ApiModelProperty("分包列表")
|
||||
private List<FbsProjectSubcontractingListVO> subList;
|
||||
|
||||
|
@ -6,9 +6,12 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.ruoyi.common.constants.FbsMessageConstant;
|
||||
import com.ruoyi.common.core.mybatisplus.core.ServicePlusImpl;
|
||||
import com.ruoyi.common.core.page.TableDataInfo;
|
||||
import com.ruoyi.common.core.redis.RedisCache;
|
||||
import com.ruoyi.common.enums.BgtMessageType;
|
||||
import com.ruoyi.common.util.MessageUtil;
|
||||
import com.ruoyi.common.utils.PageUtils;
|
||||
import com.ruoyi.common.utils.SecurityUtils;
|
||||
import com.ruoyi.fbs.bo.FbsMessageQueryBo;
|
||||
@ -20,6 +23,7 @@ import com.ruoyi.fbs.domain.vo.FbsMessageDetailVO;
|
||||
import com.ruoyi.fbs.domain.vo.FbsMessageVO;
|
||||
import com.ruoyi.fbs.mapper.FbsMessageMapper;
|
||||
import com.ruoyi.fbs.service.IFbsMessageService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.time.LocalTime;
|
||||
@ -41,6 +45,9 @@ import static com.ruoyi.common.constants.WgzAndBgtMessageConstant.OPERATION_NEED
|
||||
@Service
|
||||
public class FbsMessageServiceImpl extends ServicePlusImpl<FbsMessageMapper, FbsMessage> implements IFbsMessageService {
|
||||
|
||||
@Autowired
|
||||
private RedisCache redisCache;
|
||||
|
||||
@Override
|
||||
public FbsMessage queryById(Long id){
|
||||
return getById(id);
|
||||
@ -122,6 +129,8 @@ public class FbsMessageServiceImpl extends ServicePlusImpl<FbsMessageMapper, Fbs
|
||||
.eq(FbsMessage::getRecipientId, SecurityUtils.getAppUserId())
|
||||
.eq(FbsMessage::getIsOperation, OPERATION_NEED));
|
||||
fbsMessageCountVO.setHandleMessageCount(handle);
|
||||
|
||||
redisCache.setCacheObject(FbsMessageConstant.REDIS_KEY+SecurityUtils.getAppUserId(), fbsMessageCountVO);
|
||||
return fbsMessageCountVO;
|
||||
}
|
||||
|
||||
@ -208,7 +217,9 @@ public class FbsMessageServiceImpl extends ServicePlusImpl<FbsMessageMapper, Fbs
|
||||
|
||||
@Override
|
||||
public Boolean sendAMessage(FbsMessage bo) {
|
||||
return save(bo);
|
||||
boolean save = save(bo);
|
||||
MessageUtil.saveMessagePush(bo.getRecipientType(), bo.getRecipientId(), bo.getMessageLargeType(), bo.getIsOperation());
|
||||
return save;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -222,6 +233,8 @@ public class FbsMessageServiceImpl extends ServicePlusImpl<FbsMessageMapper, Fbs
|
||||
wrapper.eq(FbsMessage::getTableName, tableName);
|
||||
wrapper.set(FbsMessage::getIsOperation, OPERATION_ALREADY);
|
||||
update(wrapper);
|
||||
MessageUtil.operationMessagePush(recipientType, recipientId, 1);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -233,5 +246,6 @@ public class FbsMessageServiceImpl extends ServicePlusImpl<FbsMessageMapper, Fbs
|
||||
wrapper.eq(FbsMessage::getTableName, tableName);
|
||||
wrapper.set(FbsMessage::getIsOperation, OPERATION_ALREADY);
|
||||
update(wrapper);
|
||||
MessageUtil.operationMessagePush(recipientType, recipientId, tableIds.size());
|
||||
}
|
||||
}
|
||||
|
@ -29,6 +29,7 @@ import com.ruoyi.common.enums.RecruitApplyStatus;
|
||||
import com.ruoyi.common.enums.TaskApplyStatus;
|
||||
import com.ruoyi.common.exception.BaseException;
|
||||
import com.ruoyi.common.util.DataUtil;
|
||||
import com.ruoyi.common.util.ValidUtil;
|
||||
import com.ruoyi.common.utils.DateUtils;
|
||||
import com.ruoyi.common.utils.PageUtils;
|
||||
import com.ruoyi.common.utils.SecurityUtils;
|
||||
@ -168,6 +169,9 @@ public class FbsProjectTaskServiceImpl extends ServicePlusImpl<FbsProjectTaskMap
|
||||
if( fbsUser.getCompanyId()==null){
|
||||
throw new BaseException("尚未企业认证");
|
||||
}
|
||||
if (!ValidUtil.isValidChineseMobile(entity.getTaskContactPhone())) {
|
||||
throw new BaseException("手机号格式不正确");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -1,15 +1,14 @@
|
||||
package com.ruoyi.wgz.service;
|
||||
|
||||
import com.ruoyi.wgz.bo.req.WgzAppConfirmRegistrationReq;
|
||||
import com.ruoyi.common.core.mybatisplus.core.IServicePlus;
|
||||
import com.ruoyi.common.core.page.TableDataInfo;
|
||||
import com.ruoyi.wgz.bo.WgzMessageQueryBo;
|
||||
import com.ruoyi.wgz.bo.req.WgzAppGetMessageListReq;
|
||||
import com.ruoyi.wgz.bo.req.WgzAppReadUnreadReq;
|
||||
import com.ruoyi.wgz.bo.res.WgzAppGetMessageListRes;
|
||||
import com.ruoyi.wgz.bo.res.WgzAppMessageTypeStatisticsRes;
|
||||
import com.ruoyi.wgz.bo.res.WgzAppRegistrationInformationRes;
|
||||
import com.ruoyi.wgz.domain.WgzMessage;
|
||||
import com.ruoyi.wgz.bo.WgzMessageQueryBo;
|
||||
import com.ruoyi.common.core.mybatisplus.core.IServicePlus;
|
||||
import com.ruoyi.common.core.page.TableDataInfo;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
|
||||
import java.time.LocalDate;
|
||||
@ -98,4 +97,9 @@ public interface IWgzMessageService extends IServicePlus<WgzMessage> {
|
||||
* 修改已读未读状态
|
||||
*/
|
||||
Boolean userReadUnread(@Validated WgzAppReadUnreadReq req);
|
||||
|
||||
/**
|
||||
* 修改操作状态
|
||||
*/
|
||||
Boolean updateOperationStatus(Long id);
|
||||
}
|
||||
|
@ -153,4 +153,9 @@ public interface IWgzPayCalculationService extends IServicePlus<WgzPayCalculatio
|
||||
* 获取任务下已审核通过的数据
|
||||
*/
|
||||
List<WgzPayCalculation> getPassListByTaskIds(List<Long> taskIds);
|
||||
|
||||
/**
|
||||
* 总收入
|
||||
*/
|
||||
BigDecimal grossIncome();
|
||||
}
|
||||
|
@ -8,10 +8,13 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.ruoyi.bgt.domain.BgtProjectRecruit;
|
||||
import com.ruoyi.bgt.service.IBgtProjectRecruitApplyService;
|
||||
import com.ruoyi.bgt.service.IBgtProjectRecruitService;
|
||||
import com.ruoyi.common.constants.WgzAndBgtMessageConstant;
|
||||
import com.ruoyi.common.core.domain.entity.SysDictData;
|
||||
import com.ruoyi.common.core.mybatisplus.core.ServicePlusImpl;
|
||||
import com.ruoyi.common.core.page.TableDataInfo;
|
||||
import com.ruoyi.common.core.redis.RedisCache;
|
||||
import com.ruoyi.common.service.IAnnexService;
|
||||
import com.ruoyi.common.util.MessageUtil;
|
||||
import com.ruoyi.common.utils.PageUtils;
|
||||
import com.ruoyi.common.utils.SecurityUtils;
|
||||
import com.ruoyi.system.service.ISysDictTypeService;
|
||||
@ -69,6 +72,8 @@ public class WgzMessageServiceImpl extends ServicePlusImpl<WgzMessageMapper, Wgz
|
||||
|
||||
@Autowired
|
||||
private IBgtProjectRecruitService iBgtProjectRecruitService;
|
||||
@Autowired
|
||||
private RedisCache redisCache;
|
||||
|
||||
@Override
|
||||
public WgzMessage queryById(Long id){
|
||||
@ -143,7 +148,9 @@ public class WgzMessageServiceImpl extends ServicePlusImpl<WgzMessageMapper, Wgz
|
||||
|
||||
@Override
|
||||
public Boolean sendAMessage(WgzMessage bo) {
|
||||
return save(bo);
|
||||
boolean save = save(bo);
|
||||
MessageUtil.saveMessagePush(bo.getRecipientType(), bo.getRecipientId(), bo.getMessageLargeType(), bo.getIsOperation());
|
||||
return save;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -192,7 +199,9 @@ public class WgzMessageServiceImpl extends ServicePlusImpl<WgzMessageMapper, Wgz
|
||||
);
|
||||
mp.put("3",daiBanCount);
|
||||
}
|
||||
return res.setMp(mp);
|
||||
res.setMp(mp);
|
||||
redisCache.setCacheObject(WgzAndBgtMessageConstant.REDIS_KEY+SecurityUtils.getAppUserId(), res);
|
||||
return res;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -256,10 +265,25 @@ public class WgzMessageServiceImpl extends ServicePlusImpl<WgzMessageMapper, Wgz
|
||||
|
||||
@Override
|
||||
public Boolean userReadUnread(WgzAppReadUnreadReq req) {
|
||||
WgzMessage wgzMessage = new WgzMessage().setId(req.getMessageId()).setReadStatus("1");
|
||||
return baseMapper.updateById(wgzMessage) > 0;
|
||||
WgzMessage wgzMessage = baseMapper.selectById(req.getMessageId());
|
||||
boolean b = true;
|
||||
if("0".equals(wgzMessage.getReadStatus())){
|
||||
MessageUtil.readMessagePush(wgzMessage.getRecipientType(), wgzMessage.getRecipientId(), wgzMessage.getMessageLargeType(), wgzMessage.getReadStatus());
|
||||
wgzMessage.setReadStatus("1");
|
||||
b = baseMapper.updateById(wgzMessage) > 0;
|
||||
}
|
||||
|
||||
return b;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean updateOperationStatus(Long id) {
|
||||
WgzMessage wgzMessage = baseMapper.selectById(id);
|
||||
MessageUtil.operationMessagePush(wgzMessage.getRecipientType(), wgzMessage.getRecipientId(), 1);
|
||||
wgzMessage.setIsOperation("2");
|
||||
return baseMapper.updateById(wgzMessage) > 0;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断招工是否已招满或已过期
|
||||
|
@ -701,4 +701,19 @@ public class WgzPayCalculationServiceImpl extends ServicePlusImpl<WgzPayCalculat
|
||||
.eq(WgzPayCalculation::getAuditorType, AuditStatus.PASS.getCode());
|
||||
return list(wrapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BigDecimal grossIncome() {
|
||||
LambdaQueryWrapper<WgzPayCalculation> wrapper = new LambdaQueryWrapper<>();
|
||||
wrapper.in(WgzPayCalculation::getUserId, SecurityUtils.getAppUserId())
|
||||
.eq(WgzPayCalculation::getAuditorType, AuditStatus.PASS.getCode());
|
||||
List<WgzPayCalculation> list = list(wrapper);
|
||||
BigDecimal total = BigDecimal.ZERO;
|
||||
for (WgzPayCalculation wgzPayCalculation : list) {
|
||||
//金额*天数=实际工资
|
||||
total = total.add(wgzPayCalculation.getRecruitAmount().multiply(new BigDecimal(wgzPayCalculation.getNum())));
|
||||
}
|
||||
|
||||
return total;
|
||||
}
|
||||
}
|
||||
|
@ -16,4 +16,7 @@ public class ZbfSubSwitchListDTO {
|
||||
|
||||
@ApiModelProperty("总包方用户")
|
||||
private Long zbfUserId;
|
||||
|
||||
@ApiModelProperty("项目ID")
|
||||
private Long projectId;
|
||||
}
|
||||
|
@ -19,6 +19,9 @@ public class ZbfProjectSectionListVO {
|
||||
@ApiModelProperty("标段名称")
|
||||
private String sectionName;
|
||||
|
||||
@ApiModelProperty("标段描述")
|
||||
private String sectionDescribe;
|
||||
|
||||
@ApiModelProperty("项目地址")
|
||||
private String projectAddress;
|
||||
|
||||
|
@ -6,9 +6,12 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.ruoyi.common.constants.ZbfMessageConstant;
|
||||
import com.ruoyi.common.core.mybatisplus.core.ServicePlusImpl;
|
||||
import com.ruoyi.common.core.page.TableDataInfo;
|
||||
import com.ruoyi.common.core.redis.RedisCache;
|
||||
import com.ruoyi.common.enums.BgtMessageType;
|
||||
import com.ruoyi.common.util.MessageUtil;
|
||||
import com.ruoyi.common.utils.PageUtils;
|
||||
import com.ruoyi.common.utils.SecurityUtils;
|
||||
import com.ruoyi.zbf.bo.ZbfMessageQueryBo;
|
||||
@ -20,6 +23,7 @@ import com.ruoyi.zbf.domain.vo.ZbfMessageDetailVO;
|
||||
import com.ruoyi.zbf.domain.vo.ZbfMessageVO;
|
||||
import com.ruoyi.zbf.mapper.ZbfMessageMapper;
|
||||
import com.ruoyi.zbf.service.IZbfMessageService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.time.LocalTime;
|
||||
@ -40,6 +44,8 @@ import static com.ruoyi.common.constants.WgzAndBgtMessageConstant.OPERATION_NEED
|
||||
@Service
|
||||
public class ZbfMessageServiceImpl extends ServicePlusImpl<ZbfMessageMapper, ZbfMessage> implements IZbfMessageService {
|
||||
|
||||
@Autowired
|
||||
private RedisCache redisCache;
|
||||
@Override
|
||||
public ZbfMessage queryById(Long id){
|
||||
return getById(id);
|
||||
@ -107,7 +113,9 @@ public class ZbfMessageServiceImpl extends ServicePlusImpl<ZbfMessageMapper, Zbf
|
||||
|
||||
@Override
|
||||
public Boolean sendAMessage(ZbfMessage bo) {
|
||||
return save(bo);
|
||||
boolean save = save(bo);
|
||||
MessageUtil.saveMessagePush(bo.getRecipientType(), bo.getRecipientId(), bo.getMessageLargeType(), bo.getIsOperation());
|
||||
return save;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -121,6 +129,7 @@ public class ZbfMessageServiceImpl extends ServicePlusImpl<ZbfMessageMapper, Zbf
|
||||
wrapper.eq(ZbfMessage::getTableName, tableName);
|
||||
wrapper.set(ZbfMessage::getIsOperation, OPERATION_ALREADY);
|
||||
update(wrapper);
|
||||
MessageUtil.operationMessagePush(recipientType, recipientId, 1);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -132,6 +141,7 @@ public class ZbfMessageServiceImpl extends ServicePlusImpl<ZbfMessageMapper, Zbf
|
||||
wrapper.eq(ZbfMessage::getTableName, tableName);
|
||||
wrapper.set(ZbfMessage::getIsOperation, OPERATION_ALREADY);
|
||||
update(wrapper);
|
||||
MessageUtil.operationMessagePush(recipientType, recipientId, tableIds.size());
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -150,6 +160,7 @@ public class ZbfMessageServiceImpl extends ServicePlusImpl<ZbfMessageMapper, Zbf
|
||||
.eq(ZbfMessage::getRecipientId, SecurityUtils.getAppUserId())
|
||||
.eq(ZbfMessage::getIsOperation, OPERATION_NEED));
|
||||
zbfMessageCountVO.setHandleMessageCount(handle);
|
||||
redisCache.setCacheObject(ZbfMessageConstant.REDIS_KEY+SecurityUtils.getAppUserId(), zbfMessageCountVO);
|
||||
return zbfMessageCountVO;
|
||||
}
|
||||
|
||||
|
@ -204,9 +204,6 @@ public class ZbfProjectServiceImpl extends ServicePlusImpl<ZbfProjectMapper, Zbf
|
||||
}
|
||||
subListVO.add(fbsProjectSubcontractingListVO);
|
||||
}
|
||||
if (CollectionUtil.isEmpty(subListVO)) {
|
||||
continue;
|
||||
}
|
||||
FbsProjectSectionListVO fbsProjectSectionListVO = new FbsProjectSectionListVO();
|
||||
BeanUtil.copyProperties(zbfProjectSection, fbsProjectSectionListVO);
|
||||
fbsProjectSectionListVO.setSubList(subListVO);
|
||||
@ -363,9 +360,6 @@ public class ZbfProjectServiceImpl extends ServicePlusImpl<ZbfProjectMapper, Zbf
|
||||
}
|
||||
subListVO.add(fbsProjectSubcontractingListVO);
|
||||
}
|
||||
if (CollectionUtil.isEmpty(subListVO)) {
|
||||
continue;
|
||||
}
|
||||
FbsProjectSectionListVO fbsProjectSectionListVO = new FbsProjectSectionListVO();
|
||||
BeanUtil.copyProperties(zbfProjectSection, fbsProjectSectionListVO);
|
||||
fbsProjectSectionListVO.setSubList(subListVO);
|
||||
@ -543,15 +537,25 @@ public class ZbfProjectServiceImpl extends ServicePlusImpl<ZbfProjectMapper, Zbf
|
||||
public TableDataInfo<FbsProgressListVO> fbsProgressList(FbsProgressListDTO dto) {
|
||||
Page<FbsProgressListVO> fbsProgressListVOPage = new Page<>();
|
||||
//查询所有创建的任务
|
||||
List<FbsProjectTask> taskList = fbsProjectTaskService.list(Wrappers.<FbsProjectTask>lambdaQuery()
|
||||
LambdaQueryWrapper<FbsProjectTask> wrapper = Wrappers.<FbsProjectTask>lambdaQuery()
|
||||
.eq(FbsProjectTask::getCreateId, SecurityUtils.getAppUserId())
|
||||
.eq(FbsProjectTask::getProjectId, dto.getProjectId())
|
||||
);
|
||||
List<Long> taskIds = taskList.stream().map(FbsProjectTask::getId).collect(Collectors.toList());
|
||||
.orderByDesc(FbsProjectTask::getId);
|
||||
Page<FbsProjectTask> fbsProjectTaskPage = fbsProjectTaskService.getBaseMapper().selectPage(PageUtils.buildPage(), wrapper);
|
||||
List<Long> taskIds = fbsProjectTaskPage.getRecords().stream().map(FbsProjectTask::getId).collect(Collectors.toList());
|
||||
if (CollectionUtil.isNotEmpty(taskIds)) {
|
||||
TableDataInfo<BgtProjectTaskProgress> progressByTaskIds = bgtProjectTaskProgressService.getProgressByTaskIds(dto.getPageSize(), dto.getPageNum(), taskIds);
|
||||
fbsProgressListVOPage.setTotal(progressByTaskIds.getTotal());
|
||||
fbsProgressListVOPage.setRecords(BeanUtil.copyToList(progressByTaskIds.getRows(), FbsProgressListVO.class));
|
||||
List<BgtProjectTaskProgress> progressByTaskIds = bgtProjectTaskProgressService.getProgressByTaskIds(taskIds);
|
||||
Map<Long, Integer> map = progressByTaskIds.stream().collect(Collectors.toMap(BgtProjectTaskProgress::getTaskId, BgtProjectTaskProgress::getProgress));
|
||||
ArrayList<FbsProgressListVO> fbsProgressListVOS = new ArrayList<>();
|
||||
for (FbsProjectTask fbsProjectTask : fbsProjectTaskPage.getRecords()) {
|
||||
FbsProgressListVO fbsProgressListVO = new FbsProgressListVO();
|
||||
fbsProgressListVO.setId(fbsProjectTask.getId());
|
||||
fbsProgressListVO.setTaskName(fbsProjectTask.getTaskName());
|
||||
fbsProgressListVO.setProgress(map.get(fbsProjectTask.getId())==null?0:map.get(fbsProjectTask.getId()));
|
||||
fbsProgressListVOS.add(fbsProgressListVO);
|
||||
}
|
||||
fbsProgressListVOPage.setTotal(fbsProjectTaskPage.getTotal());
|
||||
fbsProgressListVOPage.setRecords(fbsProgressListVOS);
|
||||
}
|
||||
return PageUtils.buildDataInfo(fbsProgressListVOPage);
|
||||
}
|
||||
@ -586,8 +590,9 @@ public class ZbfProjectServiceImpl extends ServicePlusImpl<ZbfProjectMapper, Zbf
|
||||
|
||||
//已支付金额
|
||||
vo.setPayAmount(BigDecimal.ZERO);
|
||||
if (CollectionUtil.isNotEmpty(subIds)) {
|
||||
List<BgtWageApplication> payList = bgtWageApplicationService.getPassListByTaskIds(subIds);
|
||||
if (CollectionUtil.isNotEmpty(taskList)) {
|
||||
List<Long> taskIds = taskList.stream().map(FbsProjectTask::getId).collect(Collectors.toList());
|
||||
List<BgtWageApplication> payList = bgtWageApplicationService.getPassListByTaskIds(taskIds);
|
||||
BigDecimal payAmount = payList.stream().map(BgtWageApplication::getApplicantAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
|
||||
vo.setPayAmount(payAmount);
|
||||
}
|
||||
@ -867,7 +872,8 @@ public class ZbfProjectServiceImpl extends ServicePlusImpl<ZbfProjectMapper, Zbf
|
||||
.eq(FbsProjectTask::getProjectId, id)
|
||||
.isNotNull(FbsProjectTask::getUserId)
|
||||
);
|
||||
zbfPersonCountVO.setBgtCount(list.size());
|
||||
Set<Long> collect = list.stream().map(FbsProjectTask::getUserId).collect(Collectors.toSet());
|
||||
zbfPersonCountVO.setBgtCount(collect.size());
|
||||
List<Long> taskIds = list.stream().map(FbsProjectTask::getId).collect(Collectors.toList());
|
||||
zbfPersonCountVO.setWgzCount(0);
|
||||
if (CollectionUtil.isNotEmpty(taskIds)) {
|
||||
@ -924,14 +930,24 @@ public class ZbfProjectServiceImpl extends ServicePlusImpl<ZbfProjectMapper, Zbf
|
||||
public TableDataInfo<ZbfProgressListVO> zbfProgressList(ZbfProgressListDTO dto) {
|
||||
Page<ZbfProgressListVO> voPage = new Page<>();
|
||||
//查询所有创建的任务
|
||||
List<FbsProjectTask> taskList = fbsProjectTaskService.list(Wrappers.<FbsProjectTask>lambdaQuery()
|
||||
LambdaQueryWrapper<FbsProjectTask> wrapper = Wrappers.<FbsProjectTask>lambdaQuery()
|
||||
.eq(FbsProjectTask::getProjectId, dto.getProjectId())
|
||||
);
|
||||
List<Long> taskIds = taskList.stream().map(FbsProjectTask::getId).collect(Collectors.toList());
|
||||
.orderByDesc(FbsProjectTask::getId);
|
||||
Page<FbsProjectTask> fbsProjectTaskPage = fbsProjectTaskService.getBaseMapper().selectPage(PageUtils.buildPage(), wrapper);
|
||||
List<Long> taskIds = fbsProjectTaskPage.getRecords().stream().map(FbsProjectTask::getId).collect(Collectors.toList());
|
||||
if (CollectionUtil.isNotEmpty(taskIds)) {
|
||||
TableDataInfo<BgtProjectTaskProgress> progressByTaskIds = bgtProjectTaskProgressService.getProgressByTaskIds(dto.getPageSize(), dto.getPageNum(), taskIds);
|
||||
voPage.setTotal(progressByTaskIds.getTotal());
|
||||
voPage.setRecords(BeanUtil.copyToList(progressByTaskIds.getRows(), ZbfProgressListVO.class));
|
||||
List<BgtProjectTaskProgress> progressByTaskIds = bgtProjectTaskProgressService.getProgressByTaskIds(taskIds);
|
||||
Map<Long, Integer> map = progressByTaskIds.stream().collect(Collectors.toMap(BgtProjectTaskProgress::getTaskId, BgtProjectTaskProgress::getProgress));
|
||||
ArrayList<ZbfProgressListVO> zbfProgressListVOS = new ArrayList<>();
|
||||
for (FbsProjectTask fbsProjectTask : fbsProjectTaskPage.getRecords()) {
|
||||
ZbfProgressListVO zbfProgressListVO = new ZbfProgressListVO();
|
||||
zbfProgressListVO.setId(fbsProjectTask.getId());
|
||||
zbfProgressListVO.setTaskName(fbsProjectTask.getTaskName());
|
||||
zbfProgressListVO.setProgress(map.get(fbsProjectTask.getId())==null?0:map.get(fbsProjectTask.getId()));
|
||||
zbfProgressListVOS.add(zbfProgressListVO);
|
||||
}
|
||||
voPage.setTotal(fbsProjectTaskPage.getTotal());
|
||||
voPage.setRecords(zbfProgressListVOS);
|
||||
}
|
||||
return PageUtils.buildDataInfo(voPage);
|
||||
}
|
||||
@ -980,6 +996,7 @@ public class ZbfProjectServiceImpl extends ServicePlusImpl<ZbfProjectMapper, Zbf
|
||||
LambdaQueryWrapper<ZbfProject> wrapper = new LambdaQueryWrapper<>();
|
||||
wrapper.eq(ZbfProject::getUserId, SecurityUtils.getAppUserId());
|
||||
wrapper.like(StrUtil.isNotBlank(dto.getProjectName()), ZbfProject::getProjectName, dto.getProjectName());
|
||||
wrapper.orderByDesc(ZbfProject::getId);
|
||||
Page<ZbfProject> result = page(PageUtils.buildPage(), wrapper);
|
||||
return PageUtils.buildDataInfo(result);
|
||||
}
|
||||
|
@ -56,17 +56,19 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
</select>
|
||||
|
||||
<select id="getProgressByTaskIds" resultType="com.ruoyi.bgt.domain.BgtProjectTaskProgress">
|
||||
SELECT t.*
|
||||
FROM bgt_project_task_progress t
|
||||
JOIN (
|
||||
SELECT task_id, MAX(progress) AS maxProgress
|
||||
SELECT *
|
||||
FROM (
|
||||
SELECT
|
||||
*,
|
||||
ROW_NUMBER() OVER (PARTITION BY task_id ORDER BY progress DESC) as rn
|
||||
FROM bgt_project_task_progress
|
||||
WHERE audit_status = '2' and task_id IN
|
||||
WHERE audit_status = '2'
|
||||
AND task_id IN
|
||||
<foreach item="taskId" collection="taskIds" open="(" separator="," close=")">
|
||||
#{taskId}
|
||||
</foreach>
|
||||
GROUP BY task_id
|
||||
) sub ON t.task_id = sub.task_id AND t.progress = sub.maxProgress
|
||||
) AS sub
|
||||
WHERE sub.rn = 1 order by create_time desc
|
||||
</select>
|
||||
|
||||
</mapper>
|
||||
|
@ -35,7 +35,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
SELECT zps.id,zps.project_id,zps.section_name
|
||||
FROM zbf_project_section zps
|
||||
left JOIN zbf_project zp ON zps.project_id = zp.id
|
||||
WHERE zp.user_id = #{dto.zbfUserId}
|
||||
WHERE zp.id = #{dto.projectId} and zp.user_id = #{dto.zbfUserId}
|
||||
</select>
|
||||
|
||||
</mapper>
|
||||
|
@ -197,6 +197,23 @@
|
||||
>
|
||||
确认上传
|
||||
</el-button>
|
||||
<div style="background-color: #f5f7fa; border-radius: 4px">
|
||||
<h4 style="margin: 0 0 10px 0; color: #409eff">操作流程:</h4>
|
||||
<ol style="margin: 0; padding-left: 20px">
|
||||
<li>选择主题</li>
|
||||
<li>勾选需要上传文件的人员</li>
|
||||
<li>点击"下载模板"按钮</li>
|
||||
<li>解压下载的模板文件</li>
|
||||
<li>将图片或PDF文件放入相应人员的文件夹中</li>
|
||||
<li>压缩文件夹并上传</li>
|
||||
</ol>
|
||||
<h4 style="margin: 15px 0 10px 0; color: #f56c6c">注意事项:</h4>
|
||||
<ul style="margin: 0; padding-left: 20px">
|
||||
<li>请确保压缩文件为.zip格式</li>
|
||||
<li>压缩层级不要过深,建议直接压缩人员文件夹</li>
|
||||
<li>每个人员的文件请放入对应的文件夹中</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 查看详情弹窗 -->
|
||||
@ -260,8 +277,8 @@
|
||||
mounted() {
|
||||
const protocol = window.location.protocol;
|
||||
const host = window.location.host;
|
||||
this.baseUrl = `${protocol}//${host}`; // 动态获取基础 URL
|
||||
// 获取 URL 中的 userId 参数
|
||||
// this.baseUrl = `${protocol}//${host}/lhyg`; // 动态获取基础 URL
|
||||
// 获取 URL 中的 userId 参数
|
||||
const urlParams = new URLSearchParams(window.location.search);
|
||||
this.userId = urlParams.get("userId");
|
||||
console.log("userId", this.userId);
|
||||
|
Reference in New Issue
Block a user