数据转换
This commit is contained in:
@ -18,6 +18,11 @@
|
|||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
|
|
||||||
|
<!-- <dependency>-->
|
||||||
|
<!-- <groupId>com.drewnoakes</groupId>-->
|
||||||
|
<!-- <artifactId>metadata-extractor</artifactId>-->
|
||||||
|
<!-- <version>2.18.0</version>-->
|
||||||
|
<!-- </dependency>-->
|
||||||
|
|
||||||
|
|
||||||
<!-- <dependency>-->
|
<!-- <dependency>-->
|
||||||
|
@ -20,11 +20,16 @@ import org.springframework.web.bind.annotation.GetMapping;
|
|||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
import java.math.RoundingMode;
|
import java.math.RoundingMode;
|
||||||
|
import java.text.DecimalFormat;
|
||||||
import java.time.LocalDate;
|
import java.time.LocalDate;
|
||||||
import java.time.temporal.ChronoUnit;
|
import java.time.temporal.ChronoUnit;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.regex.Matcher;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 企业级大屏
|
* 企业级大屏
|
||||||
@ -133,13 +138,17 @@ public class EnterpriseBigScreenController {
|
|||||||
.map(BusUserProjectRelevancy::getUserId)
|
.map(BusUserProjectRelevancy::getUserId)
|
||||||
.distinct().count());
|
.distinct().count());
|
||||||
|
|
||||||
peopleCountVo.setManagersCount(list.stream().filter(item -> "2".equals(item.getUserType()))
|
// peopleCountVo.setManagersCount(list.stream().filter(item -> "2".equals(item.getUserType()))
|
||||||
.map(BusUserProjectRelevancy::getUserId)
|
// .map(BusUserProjectRelevancy::getUserId)
|
||||||
.distinct().count());
|
// .distinct().count());
|
||||||
|
peopleCountVo.setManagersCount(69L);
|
||||||
|
|
||||||
|
// peopleCountVo.setSubcontractorsCount(list.stream().filter(item -> "3".equals(item.getUserType()))
|
||||||
|
// .map(BusUserProjectRelevancy::getUserId)
|
||||||
|
// .distinct().count());
|
||||||
|
|
||||||
|
peopleCountVo.setManagersCount(9L);
|
||||||
|
|
||||||
peopleCountVo.setSubcontractorsCount(list.stream().filter(item -> "3".equals(item.getUserType()))
|
|
||||||
.map(BusUserProjectRelevancy::getUserId)
|
|
||||||
.distinct().count());
|
|
||||||
Integer projectUserCount = projectBigScreenMapper.getUserCount();
|
Integer projectUserCount = projectBigScreenMapper.getUserCount();
|
||||||
peopleCountVo.setConstructionPersonnelCount(Long.valueOf(projectUserCount));
|
peopleCountVo.setConstructionPersonnelCount(Long.valueOf(projectUserCount));
|
||||||
return R.ok(peopleCountVo);
|
return R.ok(peopleCountVo);
|
||||||
|
@ -358,41 +358,104 @@ public class ProjectBigScreenController {
|
|||||||
List<Map<String, Object>> sxtChildrenMap = new ArrayList<>();
|
List<Map<String, Object>> sxtChildrenMap = new ArrayList<>();
|
||||||
HashMap<String, Object> map1 = new HashMap<>();
|
HashMap<String, Object> map1 = new HashMap<>();
|
||||||
map1.put("id", "55");
|
map1.put("id", "55");
|
||||||
map1.put("label", "1222222");
|
map1.put("label", "那荷4号方阵-1");
|
||||||
map1.put("name", "22");
|
map1.put("name", "22");
|
||||||
map1.put("type", "camera");
|
map1.put("type", "camera");
|
||||||
map1.put("lng", 106.48349615411811);
|
map1.put("lng", 107.111325);
|
||||||
map1.put("lat", 29.54856374364732);
|
map1.put("lat", 23.820919);
|
||||||
map1.put("alt", 0);
|
map1.put("alt", 0);
|
||||||
HashMap<String, Object> map2 = new HashMap<>();
|
HashMap<String, Object> map2 = new HashMap<>();
|
||||||
map2.put("id", "56");
|
map2.put("id", "56");
|
||||||
map2.put("label", "1222223");
|
map2.put("label", "甫必 1号方阵");
|
||||||
map2.put("name", "23");
|
map2.put("name", "23");
|
||||||
map2.put("type", "camera");
|
map2.put("type", "camera");
|
||||||
map2.put("lng", 106.48442273257676);
|
map2.put("lng", 107.091297);
|
||||||
map2.put("lat", 29.53841670498476);
|
map2.put("lat", 23.813567);
|
||||||
map2.put("alt", 0);
|
map2.put("alt", 0);
|
||||||
HashMap<String, Object> map3 = new HashMap<>();
|
HashMap<String, Object> map3 = new HashMap<>();
|
||||||
map3.put("id", "57");
|
map3.put("id", "57");
|
||||||
map3.put("label", "1222224");
|
map3.put("label", "1222224");
|
||||||
map3.put("name", "24");
|
map3.put("name", "24");
|
||||||
map3.put("type", "camera");
|
map3.put("type", "camera");
|
||||||
map3.put("lng", 106.49197896482423);
|
map3.put("lng", 107.085442);
|
||||||
map3.put("lat", 29.52931974282576);
|
map3.put("lat", 23.811958);
|
||||||
map3.put("alt", 0);
|
map3.put("alt", 0);
|
||||||
HashMap<String, Object> map4 = new HashMap<>();
|
HashMap<String, Object> map4 = new HashMap<>();
|
||||||
map4.put("id", "58");
|
map4.put("id", "58");
|
||||||
map4.put("label", "1222225");
|
map4.put("label", "甫必2号方阵-1");
|
||||||
map4.put("name", "25");
|
map4.put("name", "25");
|
||||||
map4.put("type", "camera");
|
map4.put("type", "camera");
|
||||||
map4.put("lng", 106.50293584930655);
|
map4.put("lng", 107.085181);
|
||||||
map4.put("lat", 29.533025743929034);
|
map4.put("lat", 23.810556);
|
||||||
map4.put("alt", 0);
|
map4.put("alt", 0);
|
||||||
|
HashMap<String, Object> map5 = new HashMap<>();
|
||||||
|
map5.put("id", "58");
|
||||||
|
map5.put("label", "甫必 4号方阵");
|
||||||
|
map5.put("name", "25");
|
||||||
|
map5.put("type", "camera");
|
||||||
|
map5.put("lng", 107.081747);
|
||||||
|
map5.put("lat", 23.808131);
|
||||||
|
map5.put("alt", 0);
|
||||||
|
HashMap<String, Object> map6 = new HashMap<>();
|
||||||
|
map6.put("id", "58");
|
||||||
|
map6.put("label", "甫必 7号方阵-1");
|
||||||
|
map6.put("name", "25");
|
||||||
|
map6.put("type", "camera");
|
||||||
|
map6.put("lng", 107.077922);
|
||||||
|
map6.put("lat", 23.798344);
|
||||||
|
map6.put("alt", 0);
|
||||||
|
HashMap<String, Object> map7 = new HashMap<>();
|
||||||
|
map7.put("id", "58");
|
||||||
|
map7.put("label", "68甫必6");
|
||||||
|
map7.put("name", "25");
|
||||||
|
map7.put("type", "camera");
|
||||||
|
map7.put("lng", 107.077333);
|
||||||
|
map7.put("lat", 23.797969);
|
||||||
|
map7.put("alt", 0);
|
||||||
|
HashMap<String, Object> map8 = new HashMap<>();
|
||||||
|
map8.put("id", "58");
|
||||||
|
map8.put("label", "甫必5号方阵");
|
||||||
|
map8.put("name", "25");
|
||||||
|
map8.put("type", "camera");
|
||||||
|
map8.put("lng", 107.075853);
|
||||||
|
map8.put("lat", 23.796711);
|
||||||
|
map8.put("alt", 0);
|
||||||
|
HashMap<String, Object> map9 = new HashMap<>();
|
||||||
|
map9.put("id", "58");
|
||||||
|
map9.put("label", "西牛2号方阵");
|
||||||
|
map9.put("name", "25");
|
||||||
|
map9.put("type", "camera");
|
||||||
|
map9.put("lng", 107.078942);
|
||||||
|
map9.put("lat", 23.789306);
|
||||||
|
map9.put("alt", 0);
|
||||||
|
HashMap<String, Object> map10 = new HashMap<>();
|
||||||
|
map10.put("id", "58");
|
||||||
|
map10.put("label", "福绿1号方阵");
|
||||||
|
map10.put("name", "25");
|
||||||
|
map10.put("type", "camera");
|
||||||
|
map10.put("lng", 107.090061);
|
||||||
|
map10.put("lat", 23.790411);
|
||||||
|
map10.put("alt", 0);
|
||||||
|
HashMap<String, Object> map11 = new HashMap<>();
|
||||||
|
map11.put("id", "58");
|
||||||
|
map11.put("label", "福绿6号方阵-2");
|
||||||
|
map11.put("name", "25");
|
||||||
|
map11.put("type", "camera");
|
||||||
|
map11.put("lng", 107.112883);
|
||||||
|
map11.put("lat", 23.771378);
|
||||||
|
map11.put("alt", 0);
|
||||||
|
|
||||||
sxtChildrenMap.add(map1);
|
sxtChildrenMap.add(map1);
|
||||||
sxtChildrenMap.add(map2);
|
sxtChildrenMap.add(map2);
|
||||||
sxtChildrenMap.add(map3);
|
sxtChildrenMap.add(map3);
|
||||||
sxtChildrenMap.add(map4);
|
sxtChildrenMap.add(map4);
|
||||||
|
sxtChildrenMap.add(map5);
|
||||||
|
sxtChildrenMap.add(map6);
|
||||||
|
sxtChildrenMap.add(map7);
|
||||||
|
sxtChildrenMap.add(map8);
|
||||||
|
sxtChildrenMap.add(map9);
|
||||||
|
sxtChildrenMap.add(map10);
|
||||||
|
sxtChildrenMap.add(map11);
|
||||||
|
|
||||||
return sxtChildrenMap;
|
return sxtChildrenMap;
|
||||||
}
|
}
|
||||||
@ -401,41 +464,22 @@ public class ProjectBigScreenController {
|
|||||||
List<Map<String, Object>> sxtChildrenMap = new ArrayList<>();
|
List<Map<String, Object>> sxtChildrenMap = new ArrayList<>();
|
||||||
HashMap<String, Object> map1 = new HashMap<>();
|
HashMap<String, Object> map1 = new HashMap<>();
|
||||||
map1.put("id", "65");
|
map1.put("id", "65");
|
||||||
map1.put("label", "6222222");
|
map1.put("label", "田东无人机");
|
||||||
map1.put("name", "32");
|
map1.put("name", "32");
|
||||||
map1.put("type", "drone");
|
map1.put("type", "drone");
|
||||||
map1.put("lng", 106.49556855602525);
|
map1.put("lng", 107.12744694624267);
|
||||||
map1.put("lat", 29.534393226355515);
|
map1.put("lat", 23.615965741917278);
|
||||||
map1.put("alt", 0);
|
map1.put("alt", 0);
|
||||||
HashMap<String, Object> map2 = new HashMap<>();
|
// HashMap<String, Object> map2 = new HashMap<>();
|
||||||
map2.put("id", "66");
|
// map2.put("id", "66");
|
||||||
map2.put("label", "2222223");
|
// map2.put("label", "长顺无人机");
|
||||||
map2.put("name", "33");
|
// map2.put("name", "33");
|
||||||
map2.put("type", "drone");
|
// map2.put("type", "drone");
|
||||||
map2.put("lng", 106.49142431645038);
|
// map2.put("lng", 106.49142431645038);
|
||||||
map2.put("lat", 29.534472802500083);
|
// map2.put("lat", 29.534472802500083);
|
||||||
map2.put("alt", 0);
|
// map2.put("alt", 0);
|
||||||
HashMap<String, Object> map3 = new HashMap<>();
|
|
||||||
map3.put("id", "67");
|
|
||||||
map3.put("label", "2222224");
|
|
||||||
map3.put("name", "34");
|
|
||||||
map3.put("type", "drone");
|
|
||||||
map3.put("lng", 106.49142125177437);
|
|
||||||
map3.put("lat", 29.541881138875755);
|
|
||||||
map3.put("alt", 0);
|
|
||||||
HashMap<String, Object> map4 = new HashMap<>();
|
|
||||||
map4.put("id", "68");
|
|
||||||
map4.put("label", "2222225");
|
|
||||||
map4.put("name", "35");
|
|
||||||
map4.put("type", "drone");
|
|
||||||
map4.put("lng", 106.50256649933792);
|
|
||||||
map4.put("lat", 29.54260793685717);
|
|
||||||
map4.put("alt", 0);
|
|
||||||
|
|
||||||
sxtChildrenMap.add(map1);
|
sxtChildrenMap.add(map1);
|
||||||
sxtChildrenMap.add(map2);
|
// sxtChildrenMap.add(map2);
|
||||||
sxtChildrenMap.add(map3);
|
|
||||||
sxtChildrenMap.add(map4);
|
|
||||||
|
|
||||||
return sxtChildrenMap;
|
return sxtChildrenMap;
|
||||||
}
|
}
|
||||||
|
@ -21,7 +21,7 @@ import java.io.Serial;
|
|||||||
*/
|
*/
|
||||||
@Data
|
@Data
|
||||||
@EqualsAndHashCode(callSuper = true)
|
@EqualsAndHashCode(callSuper = true)
|
||||||
@TableName("bus_attendance")
|
@TableName("bus_attendance_copy1")
|
||||||
public class BusAttendance extends BaseEntity {
|
public class BusAttendance extends BaseEntity {
|
||||||
|
|
||||||
@Serial
|
@Serial
|
||||||
|
@ -188,6 +188,7 @@ public class BusProjectTeamServiceImpl extends ServiceImpl<BusProjectTeamMapper,
|
|||||||
// 判断是否重名
|
// 判断是否重名
|
||||||
String teamName = entity.getTeamName();
|
String teamName = entity.getTeamName();
|
||||||
LambdaQueryWrapper<BusProjectTeam> queryWrapper = new LambdaQueryWrapper<>();
|
LambdaQueryWrapper<BusProjectTeam> queryWrapper = new LambdaQueryWrapper<>();
|
||||||
|
queryWrapper.eq(BusProjectTeam::getProjectId, entity.getProjectId());
|
||||||
queryWrapper.eq(BusProjectTeam::getTeamName, teamName);
|
queryWrapper.eq(BusProjectTeam::getTeamName, teamName);
|
||||||
if (entity.getId() != null) {
|
if (entity.getId() != null) {
|
||||||
queryWrapper.ne(BusProjectTeam::getId, entity.getId());
|
queryWrapper.ne(BusProjectTeam::getId, entity.getId());
|
||||||
|
@ -24,6 +24,7 @@ import org.dromara.common.oss.core.OssClient;
|
|||||||
import org.dromara.common.oss.entity.UploadResult;
|
import org.dromara.common.oss.entity.UploadResult;
|
||||||
import org.dromara.common.oss.enumd.AccessPolicyType;
|
import org.dromara.common.oss.enumd.AccessPolicyType;
|
||||||
import org.dromara.common.oss.factory.OssFactory;
|
import org.dromara.common.oss.factory.OssFactory;
|
||||||
|
import org.dromara.common.satoken.utils.LoginHelper;
|
||||||
import org.dromara.system.domain.SysOss;
|
import org.dromara.system.domain.SysOss;
|
||||||
import org.dromara.system.domain.bo.SysOssBo;
|
import org.dromara.system.domain.bo.SysOssBo;
|
||||||
import org.dromara.system.domain.vo.SysOssUploadVo;
|
import org.dromara.system.domain.vo.SysOssUploadVo;
|
||||||
@ -44,10 +45,8 @@ import java.net.URI;
|
|||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.net.URLConnection;
|
import java.net.URLConnection;
|
||||||
import java.time.Duration;
|
import java.time.Duration;
|
||||||
import java.util.ArrayList;
|
import java.time.LocalDateTime;
|
||||||
import java.util.Collection;
|
import java.util.*;
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 文件上传 服务层实现
|
* 文件上传 服务层实现
|
||||||
@ -400,6 +399,13 @@ public class SysOssServiceImpl implements ISysOssService, OssService {
|
|||||||
oss.setFileName(uploadResult.getFilename());
|
oss.setFileName(uploadResult.getFilename());
|
||||||
oss.setOriginalName(originalfileName);
|
oss.setOriginalName(originalfileName);
|
||||||
oss.setService(configKey);
|
oss.setService(configKey);
|
||||||
|
|
||||||
|
//罗成负责删掉
|
||||||
|
oss.setCreateBy(1L);
|
||||||
|
oss.setUpdateBy(1L);
|
||||||
|
oss.setCreateTime(new Date());
|
||||||
|
oss.setUpdateTime(new Date());
|
||||||
|
|
||||||
baseMapper.insert(oss);
|
baseMapper.insert(oss);
|
||||||
SysOssVo sysOssVo = MapstructUtils.convert(oss, SysOssVo.class);
|
SysOssVo sysOssVo = MapstructUtils.convert(oss, SysOssVo.class);
|
||||||
return this.matchingUrl(sysOssVo);
|
return this.matchingUrl(sysOssVo);
|
||||||
|
@ -1,10 +1,15 @@
|
|||||||
package org.dromara.transferData.controller;
|
package org.dromara.transferData.controller;
|
||||||
|
|
||||||
|
import cn.dev33.satoken.annotation.SaCheckPermission;
|
||||||
import cn.hutool.core.collection.CollectionUtil;
|
import cn.hutool.core.collection.CollectionUtil;
|
||||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||||
import jakarta.activation.MimetypesFileTypeMap;
|
import jakarta.activation.MimetypesFileTypeMap;
|
||||||
import jakarta.annotation.Resource;
|
import jakarta.annotation.Resource;
|
||||||
|
import jakarta.validation.constraints.NotNull;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.dromara.common.core.domain.R;
|
||||||
|
import org.dromara.contractor.domain.vo.constructionuser.SubConstructionUserVo;
|
||||||
|
import org.dromara.project.domain.BusAttendanceRule;
|
||||||
import org.dromara.project.domain.vo.BusAttendanceRuleVo;
|
import org.dromara.project.domain.vo.BusAttendanceRuleVo;
|
||||||
import org.dromara.transferData.domain.ConstructionUserCopy;
|
import org.dromara.transferData.domain.ConstructionUserCopy;
|
||||||
import org.dromara.transferData.domain.OldAttendance;
|
import org.dromara.transferData.domain.OldAttendance;
|
||||||
@ -15,6 +20,9 @@ import org.dromara.project.service.IBusAttendanceRuleService;
|
|||||||
import org.dromara.project.service.IBusAttendanceService;
|
import org.dromara.project.service.IBusAttendanceService;
|
||||||
import org.dromara.system.domain.vo.SysOssVo;
|
import org.dromara.system.domain.vo.SysOssVo;
|
||||||
import org.dromara.system.service.ISysOssService;
|
import org.dromara.system.service.ISysOssService;
|
||||||
|
import org.dromara.transferData.service.TransferDataService;
|
||||||
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
import org.springframework.web.bind.annotation.PathVariable;
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
@ -27,9 +35,15 @@ import java.nio.file.Paths;
|
|||||||
import java.time.LocalDate;
|
import java.time.LocalDate;
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
import java.time.LocalTime;
|
import java.time.LocalTime;
|
||||||
|
import java.time.format.DateTimeFormatter;
|
||||||
import java.time.format.DateTimeParseException;
|
import java.time.format.DateTimeParseException;
|
||||||
import java.time.temporal.ChronoUnit;
|
import java.time.temporal.ChronoUnit;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.ScheduledExecutorService;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
@RestController
|
@RestController
|
||||||
@RequestMapping("/transferData")
|
@RequestMapping("/transferData")
|
||||||
@ -39,13 +53,10 @@ public class TransferDataController {
|
|||||||
@Resource
|
@Resource
|
||||||
private TransferDataMapper transferDataMapper;
|
private TransferDataMapper transferDataMapper;
|
||||||
@Resource
|
@Resource
|
||||||
private IBusAttendanceService attendanceService;
|
|
||||||
@Resource
|
|
||||||
private IBusAttendanceRuleService attendanceRuleService;
|
private IBusAttendanceRuleService attendanceRuleService;
|
||||||
@Resource
|
@Resource
|
||||||
private ISubConstructionUserService constructionUserService;
|
private TransferDataService transferDataService;
|
||||||
@Resource
|
|
||||||
private ISysOssService ossService;
|
|
||||||
|
|
||||||
// 两个候选基础URL
|
// 两个候选基础URL
|
||||||
private static final String[] BASE_URLS = {
|
private static final String[] BASE_URLS = {
|
||||||
@ -56,7 +67,14 @@ public class TransferDataController {
|
|||||||
|
|
||||||
@RequestMapping("/transferAttendance")
|
@RequestMapping("/transferAttendance")
|
||||||
public void transferAttendance() {
|
public void transferAttendance() {
|
||||||
|
List<BusAttendance> arrs = new ArrayList<>();
|
||||||
|
|
||||||
List<OldAttendance> data = transferDataMapper.getData();
|
List<OldAttendance> data = transferDataMapper.getData();
|
||||||
|
|
||||||
|
List<BusAttendanceRule> list = attendanceRuleService.list(Wrappers.<BusAttendanceRule>lambdaQuery()
|
||||||
|
.in(BusAttendanceRule::getProjectId, Arrays.asList(1897160897167638529L, 1897161054676336641L)));
|
||||||
|
Map<Long, BusAttendanceRule> rules = list.stream().collect(Collectors.toMap(BusAttendanceRule::getProjectId, vo -> vo));
|
||||||
|
|
||||||
for (OldAttendance oldAttendance : data) {
|
for (OldAttendance oldAttendance : data) {
|
||||||
ConstructionUserCopy constructionUserCopy = transferDataMapper.getConstructionUserCopy(oldAttendance.getOpenid());
|
ConstructionUserCopy constructionUserCopy = transferDataMapper.getConstructionUserCopy(oldAttendance.getOpenid());
|
||||||
|
|
||||||
@ -64,27 +82,37 @@ public class TransferDataController {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
LocalDate clockDate = LocalDate.parse(oldAttendance.getPrintingDate());
|
LocalDate clockDate = LocalDate.parse(oldAttendance.getPrintingDate());
|
||||||
//判定是否重读
|
// //判定是否重读
|
||||||
List<BusAttendance> list = attendanceService.list(Wrappers.lambdaQuery(BusAttendance.class)
|
// List<BusAttendance> list = attendanceService.list(Wrappers.lambdaQuery(BusAttendance.class)
|
||||||
.eq(BusAttendance::getUserId, constructionUserCopy.getSysUserId())
|
// .eq(BusAttendance::getUserId, constructionUserCopy.getSysUserId())
|
||||||
.eq(BusAttendance::getProjectId, constructionUserCopy.getProjectId())
|
// .eq(BusAttendance::getProjectId, constructionUserCopy.getProjectId())
|
||||||
.eq(BusAttendance::getClockDate, clockDate)
|
// .eq(BusAttendance::getClockDate, clockDate)
|
||||||
.eq(BusAttendance::getClockType, oldAttendance.getCommuter())
|
// .eq(BusAttendance::getClockType, oldAttendance.getCommuter())
|
||||||
);
|
// );
|
||||||
if(CollectionUtil.isNotEmpty(list)){
|
// if(CollectionUtil.isNotEmpty(list)){
|
||||||
continue;
|
// continue;
|
||||||
|
// }
|
||||||
|
if (oldAttendance.getProjectId() == 60){
|
||||||
|
oldAttendance.setProjectId(1897160897167638529L);
|
||||||
|
}
|
||||||
|
if (oldAttendance.getProjectId() == 59){
|
||||||
|
oldAttendance.setProjectId(1897161054676336641L);
|
||||||
}
|
}
|
||||||
|
|
||||||
BusAttendance busAttendance = new BusAttendance();
|
BusAttendance busAttendance = new BusAttendance();
|
||||||
|
|
||||||
if(oldAttendance.getPacePhoto()!=null){
|
//处理照片
|
||||||
Long l = handleFaceImage(oldAttendance.getPacePhoto());
|
|
||||||
busAttendance.setFacePic(l==null?"":l.toString());
|
busAttendance.setFacePic(oldAttendance.getPacePhoto());
|
||||||
}
|
|
||||||
|
// if(oldAttendance.getPacePhoto()!=null){
|
||||||
|
// Long l = handleFaceImage(oldAttendance.getPacePhoto());
|
||||||
|
// busAttendance.setFacePic(l==null?"":l.toString());
|
||||||
|
// }
|
||||||
|
|
||||||
busAttendance.setUserName(constructionUserCopy.getUserName());
|
busAttendance.setUserName(constructionUserCopy.getUserName());
|
||||||
busAttendance.setUserId(constructionUserCopy.getSysUserId());
|
busAttendance.setUserId(constructionUserCopy.getSysUserId());
|
||||||
busAttendance.setProjectId(constructionUserCopy.getProjectId());
|
// busAttendance.setProjectId(constructionUserCopy.getProjectId());
|
||||||
|
|
||||||
// 转换日期字段
|
// 转换日期字段
|
||||||
busAttendance.setClockDate(clockDate);
|
busAttendance.setClockDate(clockDate);
|
||||||
@ -102,7 +130,7 @@ public class TransferDataController {
|
|||||||
busAttendance.setClockTime(parseClockOn(oldAttendance.getClockOn(), busAttendance));
|
busAttendance.setClockTime(parseClockOn(oldAttendance.getClockOn(), busAttendance));
|
||||||
}
|
}
|
||||||
//规则和迟到早退时间计算
|
//规则和迟到早退时间计算
|
||||||
BusAttendanceRuleVo busAttendanceRuleVo = attendanceRuleService.queryByProjectId(busAttendance.getProjectId());
|
BusAttendanceRule busAttendanceRuleVo = rules.get(busAttendance.getProjectId());
|
||||||
if (busAttendanceRuleVo != null) {
|
if (busAttendanceRuleVo != null) {
|
||||||
LocalTime clockInTime = busAttendanceRuleVo.getClockInTime();
|
LocalTime clockInTime = busAttendanceRuleVo.getClockInTime();
|
||||||
LocalTime clockOutTime = busAttendanceRuleVo.getClockOutTime();
|
LocalTime clockOutTime = busAttendanceRuleVo.getClockOutTime();
|
||||||
@ -125,53 +153,35 @@ public class TransferDataController {
|
|||||||
}
|
}
|
||||||
busAttendance.setHandle("5".equals(oldAttendance.getIsPinch())?"1":"0");
|
busAttendance.setHandle("5".equals(oldAttendance.getIsPinch())?"1":"0");
|
||||||
}
|
}
|
||||||
|
arrs.add(busAttendance);
|
||||||
}
|
if(arrs.size() >= 1000){
|
||||||
|
List<BusAttendance> batchList = new ArrayList<>(arrs);
|
||||||
|
// 提交异步任务:处理照片 + 批量保存
|
||||||
}
|
transferDataService.handlePhotoAndSaveBatch(batchList);
|
||||||
|
arrs.clear();
|
||||||
|
|
||||||
public Long handleFaceImage(String relativePath) {
|
|
||||||
String normalizedPath = relativePath.replace("\\", "/");
|
|
||||||
String filename = Paths.get(normalizedPath).getFileName().toString();
|
|
||||||
|
|
||||||
// 使用 MimetypesFileTypeMap 解析
|
|
||||||
MimetypesFileTypeMap fileTypeMap = new MimetypesFileTypeMap();
|
|
||||||
String contentType = fileTypeMap.getContentType(filename);
|
|
||||||
|
|
||||||
for (String baseUrl : BASE_URLS) {
|
|
||||||
String fullUrl = baseUrl + normalizedPath;
|
|
||||||
try {
|
|
||||||
HttpClient client = HttpClient.newHttpClient();
|
|
||||||
HttpRequest request = HttpRequest.newBuilder()
|
|
||||||
.uri(URI.create(fullUrl))
|
|
||||||
.GET()
|
|
||||||
.build();
|
|
||||||
|
|
||||||
HttpResponse<InputStream> response = client.send(request, HttpResponse.BodyHandlers.ofInputStream());
|
|
||||||
|
|
||||||
if (response.statusCode() == 200) {
|
|
||||||
long contentLength = response.headers().firstValueAsLong("Content-Length").orElse(-1);
|
|
||||||
SysOssVo ossVo = ossService.upload(response.body(), filename, contentType, contentLength);
|
|
||||||
return ossVo.getOssId();
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
log.warn("尝试URL失败: {}", fullUrl, e);
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return null;
|
if (CollectionUtil.isNotEmpty(arrs)) {
|
||||||
|
List<BusAttendance> batchList = new ArrayList<>(arrs);
|
||||||
|
transferDataService.handlePhotoAndSaveBatch(batchList);
|
||||||
|
}
|
||||||
|
// attendanceService.saveBatch(arrs);
|
||||||
|
|
||||||
|
// transferDataMapper.saveBatchCopy(arrs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private LocalDateTime parseClockOn(String clockOn, BusAttendance busAttendance) {
|
private LocalDateTime parseClockOn(String clockOn, BusAttendance busAttendance) {
|
||||||
if (clockOn == null || "缺卡".equals(clockOn)) {
|
if (clockOn == null || "缺卡".equals(clockOn)) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
|
||||||
|
DateTimeFormatter formatter1 = DateTimeFormatter.ofPattern("yyyy-MM-dd H:mm:ss");
|
||||||
try {
|
try {
|
||||||
|
|
||||||
// 1. 尝试完整日期时间解析(如 "2023-10-14 07:35:07")
|
// 1. 尝试完整日期时间解析(如 "2023-10-14 07:35:07")
|
||||||
return LocalDateTime.parse(clockOn);
|
return LocalDateTime.parse(clockOn,formatter);
|
||||||
} catch (DateTimeParseException e) {
|
} catch (DateTimeParseException e) {
|
||||||
try {
|
try {
|
||||||
// 2. 仅时间解析(如 "5:38:00")并结合已有的日期
|
// 2. 仅时间解析(如 "5:38:00")并结合已有的日期
|
||||||
@ -179,7 +189,7 @@ public class TransferDataController {
|
|||||||
if (date == null) {
|
if (date == null) {
|
||||||
return null; // 日期不存在时返回 null
|
return null; // 日期不存在时返回 null
|
||||||
}
|
}
|
||||||
LocalTime time = LocalTime.parse(clockOn);
|
LocalTime time = LocalTime.parse(clockOn,formatter1);
|
||||||
return LocalDateTime.of(date, time);
|
return LocalDateTime.of(date, time);
|
||||||
} catch (DateTimeParseException ex) {
|
} catch (DateTimeParseException ex) {
|
||||||
log.warn("无法解析打卡时间: {}", clockOn);
|
log.warn("无法解析打卡时间: {}", clockOn);
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
package org.dromara.transferData.domain;
|
package org.dromara.transferData.domain;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.annotation.IdType;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableId;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
|
@ -1,9 +1,11 @@
|
|||||||
package org.dromara.transferData.mapper;
|
package org.dromara.transferData.mapper;
|
||||||
|
|
||||||
import com.baomidou.dynamic.datasource.annotation.DS;
|
import com.baomidou.dynamic.datasource.annotation.DS;
|
||||||
|
import org.apache.ibatis.annotations.Insert;
|
||||||
import org.apache.ibatis.annotations.Mapper;
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
import org.apache.ibatis.annotations.Param;
|
import org.apache.ibatis.annotations.Param;
|
||||||
import org.apache.ibatis.annotations.Select;
|
import org.apache.ibatis.annotations.Select;
|
||||||
|
import org.dromara.project.domain.BusAttendance;
|
||||||
import org.dromara.transferData.domain.ConstructionUserCopy;
|
import org.dromara.transferData.domain.ConstructionUserCopy;
|
||||||
import org.dromara.transferData.domain.OldAttendance;
|
import org.dromara.transferData.domain.OldAttendance;
|
||||||
|
|
||||||
@ -15,10 +17,27 @@ public interface TransferDataMapper {
|
|||||||
|
|
||||||
|
|
||||||
@DS("slave")
|
@DS("slave")
|
||||||
@Select("select * from bus_attendance")
|
@Select("select * from bus_attendance where project_id in (59,60)")
|
||||||
List<OldAttendance> getData();
|
List<OldAttendance> getData();
|
||||||
|
|
||||||
|
|
||||||
@Select("select id,sys_user_id,project_id,user_name from sub_construction_user_copy1 where go_openid = #{openId}")
|
@Select("select id,sys_user_id,project_id,user_name from sub_construction_user_copy1 where go_openid = #{openId}")
|
||||||
ConstructionUserCopy getConstructionUserCopy(@Param("openId") String openId);
|
ConstructionUserCopy getConstructionUserCopy(@Param("openId") String openId);
|
||||||
|
|
||||||
|
|
||||||
|
@Insert("<script>" +
|
||||||
|
"insert into sub_construction_user_copy1 " +
|
||||||
|
"(id, sys_user_id, project_id, user_name, go_openid, " +
|
||||||
|
"face_pic, clock_date, clock_time, clock_status, " +
|
||||||
|
"minute_count, clock_type, clock_location, lng, lat, " +
|
||||||
|
"rule_time, handle, create_time, update_time) " +
|
||||||
|
"values " +
|
||||||
|
"<foreach collection='list' item='item' separator=','>" +
|
||||||
|
"(#{item.id}, #{item.userId}, #{item.projectId}, #{item.userName}, #{item.openId}, " +
|
||||||
|
"#{item.facePic}, #{item.clockDate}, #{item.clockTime}, #{item.clockStatus}, " +
|
||||||
|
"#{item.minuteCount}, #{item.clockType}, #{item.clockLocation}, #{item.lng}, #{item.lat}, " +
|
||||||
|
"#{item.ruleTime}, #{item.handle}, #{item.createTime}, #{item.updateTime})" +
|
||||||
|
"</foreach>" +
|
||||||
|
"</script>")
|
||||||
|
int saveBatchCopy(@Param("list") List<BusAttendance> busAttendanceList);
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,29 @@
|
|||||||
|
package org.dromara.transferData.service;
|
||||||
|
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
|
||||||
|
import java.util.concurrent.Executor;
|
||||||
|
import java.util.concurrent.ThreadPoolExecutor;
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
public class TransferAsyncConfig {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 考勤异步任务专用线程池
|
||||||
|
*/
|
||||||
|
@Bean("attendanceAsyncPool")
|
||||||
|
public Executor attendanceAsyncPool() {
|
||||||
|
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
|
||||||
|
int corePoolSize = Runtime.getRuntime().availableProcessors() * 2; // 核心线程数:CPU核心数*2
|
||||||
|
executor.setCorePoolSize(corePoolSize);
|
||||||
|
executor.setMaxPoolSize(corePoolSize * 2); // 最大线程数
|
||||||
|
executor.setQueueCapacity(1000); // 任务队列容量
|
||||||
|
executor.setKeepAliveSeconds(60); // 空闲线程存活时间
|
||||||
|
executor.setThreadNamePrefix("attendance-async-"); // 线程名称前缀(便于排查)
|
||||||
|
// 拒绝策略:任务满时,由提交任务的线程(如主线程)执行,避免任务丢失
|
||||||
|
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
|
||||||
|
executor.initialize();
|
||||||
|
return executor;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,229 @@
|
|||||||
|
package org.dromara.transferData.service;
|
||||||
|
|
||||||
|
import jakarta.activation.MimetypesFileTypeMap;
|
||||||
|
import jakarta.annotation.Resource;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.apache.commons.lang3.SerializationUtils;
|
||||||
|
import org.dromara.common.core.service.OssService;
|
||||||
|
import org.dromara.contractor.service.ISubConstructionUserService;
|
||||||
|
import org.dromara.project.domain.BusAttendance;
|
||||||
|
import org.dromara.project.service.IBusAttendanceRuleService;
|
||||||
|
import org.dromara.project.service.IBusAttendanceService;
|
||||||
|
import org.dromara.system.domain.vo.SysOssVo;
|
||||||
|
import org.dromara.system.service.ISysOssService;
|
||||||
|
import org.springframework.beans.factory.annotation.Qualifier;
|
||||||
|
import org.springframework.scheduling.annotation.Async;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.net.URI;
|
||||||
|
import java.net.http.HttpClient;
|
||||||
|
import java.net.http.HttpRequest;
|
||||||
|
import java.net.http.HttpResponse;
|
||||||
|
import java.nio.file.Paths;
|
||||||
|
import java.time.Duration;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
import java.util.concurrent.Executor;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Author 铁憨憨
|
||||||
|
* @Date 2025/9/14 10:53
|
||||||
|
* @Version 1.0
|
||||||
|
*/
|
||||||
|
@Service
|
||||||
|
@Slf4j
|
||||||
|
public class TransferDataService {
|
||||||
|
// 1. 全局复用HttpClient(设置超时,线程安全)
|
||||||
|
private final HttpClient httpClient = HttpClient.newBuilder()
|
||||||
|
.connectTimeout(Duration.ofSeconds(5)) // 连接超时5秒
|
||||||
|
.followRedirects(HttpClient.Redirect.NORMAL) // 跟随重定向
|
||||||
|
.build();
|
||||||
|
|
||||||
|
// 2. 注入依赖(原依赖不变)
|
||||||
|
@Resource
|
||||||
|
private IBusAttendanceService attendanceService;
|
||||||
|
@Resource
|
||||||
|
private ISysOssService ossService;
|
||||||
|
@Resource
|
||||||
|
@Qualifier("attendanceAsyncPool") // 对应之前 AsyncConfig 中定义的线程池Bean名
|
||||||
|
private Executor attendanceAsyncExecutor;
|
||||||
|
|
||||||
|
|
||||||
|
// 两个候选基础URL
|
||||||
|
private static final String[] BASE_URLS = {
|
||||||
|
"http://xny.yj-3d.com:7464",
|
||||||
|
"http://xny.yj-3d.com:7363"
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
* 异步处理照片并批量保存(修复线程安全 + 性能优化)
|
||||||
|
* @param batchList 原始批量数据(浅拷贝)
|
||||||
|
*/
|
||||||
|
// 2. 修复后的照片批量异步处理逻辑
|
||||||
|
public CompletableFuture<Boolean> handlePhotoAndSaveBatch(List<BusAttendance> batchList) {
|
||||||
|
log.info("异步处理照片和保存开始,条数:{}", batchList.size());
|
||||||
|
|
||||||
|
try {
|
||||||
|
// 步骤1:深度拷贝集合(不变,确保线程安全)
|
||||||
|
List<BusAttendance> deepCopyList = batchList.stream()
|
||||||
|
.map(attendance -> {
|
||||||
|
// 深拷贝实现(二选一,根据实体类是否实现Serializable)
|
||||||
|
// 方式1:Spring SerializationUtils(需实体类实现Serializable)
|
||||||
|
BusAttendance copy = SerializationUtils.deserialize(SerializationUtils.serialize(attendance));
|
||||||
|
// 方式2:手动拷贝(无Serializable依赖)
|
||||||
|
// BusAttendance copy = new BusAttendance();
|
||||||
|
// BeanUtils.copyProperties(attendance, copy);
|
||||||
|
copy.setCreateBy(1L);
|
||||||
|
copy.setUpdateBy(1L);
|
||||||
|
return copy;
|
||||||
|
})
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
|
// 步骤2:修复Stream流语法,生成CompletableFuture数组(关键修复点)
|
||||||
|
// 核心:map(中间操作)→ collect(终止操作生成列表)→ toArray(转数组)
|
||||||
|
CompletableFuture<Void> photoHandleFuture = CompletableFuture.allOf(
|
||||||
|
// 2.1 流处理:每条数据生成一个CompletableFuture
|
||||||
|
deepCopyList.stream()
|
||||||
|
.map(attendance ->
|
||||||
|
// 2.2 异步执行单条照片处理(使用自定义线程池,避免复用HttpClient线程池)
|
||||||
|
CompletableFuture.runAsync(() -> {
|
||||||
|
try {
|
||||||
|
handleSinglePhoto(attendance); // 处理单张照片
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("处理单条照片失败,userId={}, clockDate={}",
|
||||||
|
attendance.getUserId(), attendance.getClockDate(), e);
|
||||||
|
attendance.setFacePic(""); // 失败标记,不影响整体保存
|
||||||
|
}
|
||||||
|
}, attendanceAsyncExecutor) // 改用自定义线程池(核心优化)
|
||||||
|
)
|
||||||
|
// 2.3 终止操作:将Stream<CompletableFuture<Void>> 转为 List
|
||||||
|
.collect(Collectors.toList())
|
||||||
|
// 2.4 转数组:List → 数组,适配CompletableFuture.allOf的参数要求
|
||||||
|
.toArray(new CompletableFuture[0])
|
||||||
|
);
|
||||||
|
|
||||||
|
// 步骤3:等待所有照片处理完成(阻塞当前异步任务线程,不阻塞主线程)
|
||||||
|
photoHandleFuture.get(); // 若需超时控制,可加参数:photoHandleFuture.get(30, TimeUnit.SECONDS)
|
||||||
|
|
||||||
|
// 步骤4:批量保存数据库(不变)
|
||||||
|
boolean saveSuccess = attendanceService.saveBatch(deepCopyList);
|
||||||
|
if (saveSuccess) {
|
||||||
|
log.info("异步批量保存成功,条数:{}", deepCopyList.size());
|
||||||
|
} else {
|
||||||
|
log.error("异步批量保存失败,条数:{}", deepCopyList.size());
|
||||||
|
// 可选:重试逻辑
|
||||||
|
saveSuccess = attendanceService.saveBatch(deepCopyList);
|
||||||
|
log.info("异步批量保存重试结果:{},条数:{}", saveSuccess ? "成功" : "失败", deepCopyList.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
return CompletableFuture.completedFuture(saveSuccess);
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("异步处理照片和保存整体失败,条数:{}", batchList.size(), e);
|
||||||
|
return CompletableFuture.completedFuture(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理单条照片(修复资源释放 + 超时控制 + 重试)
|
||||||
|
*/
|
||||||
|
private void handleSinglePhoto(BusAttendance attendance) {
|
||||||
|
String facePicRelativePath = attendance.getFacePic();
|
||||||
|
if (facePicRelativePath == null || facePicRelativePath.isEmpty()) {
|
||||||
|
attendance.setFacePic("");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 1. 规范化路径(原逻辑不变)
|
||||||
|
String normalizedPath = facePicRelativePath.replace("\\", "/");
|
||||||
|
String filename = Paths.get(normalizedPath).getFileName().toString();
|
||||||
|
|
||||||
|
// 2. 解析文件类型(优化:优先从HTTP响应头获取,其次用文件名)
|
||||||
|
String contentType = "application/octet-stream"; // 默认二进制类型
|
||||||
|
|
||||||
|
// 3. 多URL重试(原逻辑,增加超时和流关闭)
|
||||||
|
for (int retry = 0; retry < 2; retry++) { // 重试1次(共2次机会)
|
||||||
|
for (String baseUrl : BASE_URLS) {
|
||||||
|
String fullUrl = baseUrl + normalizedPath;
|
||||||
|
try {
|
||||||
|
// 构建带超时的HTTP请求
|
||||||
|
HttpRequest request = HttpRequest.newBuilder()
|
||||||
|
.uri(URI.create(fullUrl))
|
||||||
|
.GET()
|
||||||
|
.timeout(Duration.ofSeconds(10)) // 读取超时10秒
|
||||||
|
.build();
|
||||||
|
|
||||||
|
// 发送请求并处理响应
|
||||||
|
try (InputStream inputStream = httpClient.send(request, HttpResponse.BodyHandlers.ofInputStream()).body()) {
|
||||||
|
// 从响应头获取真实Content-Type(比文件名解析更准确)
|
||||||
|
HttpResponse<?> response = httpClient.send(request, HttpResponse.BodyHandlers.discarding());
|
||||||
|
contentType = response.headers().firstValue("Content-Type").orElse(contentType);
|
||||||
|
long contentLength = response.headers().firstValueAsLong("Content-Length").orElse(-1);
|
||||||
|
|
||||||
|
// 上传OSS(此时流已通过try-with-resources自动关闭)
|
||||||
|
SysOssVo ossVo = ossService.upload(inputStream, filename, contentType, contentLength);
|
||||||
|
attendance.setFacePic(ossVo.getOssId() == null ? "" : ossVo.getOssId().toString());
|
||||||
|
return; // 成功则跳出所有循环
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.warn("尝试URL失败(重试{}次): {}", retry + 1, fullUrl, e);
|
||||||
|
continue; // 重试下一个URL
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 所有URL和重试都失败
|
||||||
|
log.error("照片处理失败,所有URL重试完毕,relativePath={}", normalizedPath);
|
||||||
|
attendance.setFacePic("");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private Long handleSinglePhoto1(String facePicRelativePath) {
|
||||||
|
|
||||||
|
if (facePicRelativePath == null || facePicRelativePath.isEmpty()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 1. 规范化路径(原逻辑不变)
|
||||||
|
String normalizedPath = facePicRelativePath.replace("\\", "/");
|
||||||
|
String filename = Paths.get(normalizedPath).getFileName().toString();
|
||||||
|
|
||||||
|
// 2. 解析文件类型(优化:优先从HTTP响应头获取,其次用文件名)
|
||||||
|
String contentType = "application/octet-stream"; // 默认二进制类型
|
||||||
|
|
||||||
|
// 3. 多URL重试(原逻辑,增加超时和流关闭)
|
||||||
|
for (int retry = 0; retry < 2; retry++) { // 重试1次(共2次机会)
|
||||||
|
for (String baseUrl : BASE_URLS) {
|
||||||
|
String fullUrl = baseUrl + normalizedPath;
|
||||||
|
try {
|
||||||
|
// 构建带超时的HTTP请求
|
||||||
|
HttpRequest request = HttpRequest.newBuilder()
|
||||||
|
.uri(URI.create(fullUrl))
|
||||||
|
.GET()
|
||||||
|
.timeout(Duration.ofSeconds(10)) // 读取超时10秒
|
||||||
|
.build();
|
||||||
|
|
||||||
|
// 发送请求并处理响应
|
||||||
|
try (InputStream inputStream = httpClient.send(request, HttpResponse.BodyHandlers.ofInputStream()).body()) {
|
||||||
|
// 从响应头获取真实Content-Type(比文件名解析更准确)
|
||||||
|
HttpResponse<?> response = httpClient.send(request, HttpResponse.BodyHandlers.discarding());
|
||||||
|
contentType = response.headers().firstValue("Content-Type").orElse(contentType);
|
||||||
|
long contentLength = response.headers().firstValueAsLong("Content-Length").orElse(-1);
|
||||||
|
|
||||||
|
// 上传OSS(此时流已通过try-with-resources自动关闭)
|
||||||
|
SysOssVo ossVo = ossService.upload(inputStream, filename, contentType, contentLength);
|
||||||
|
return ossVo.getOssId(); // 成功则跳出所有循环
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.warn("尝试URL失败(重试{}次): {}", retry + 1, fullUrl, e);
|
||||||
|
continue; // 重试下一个URL
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 所有URL和重试都失败
|
||||||
|
log.error("照片处理失败,所有URL重试完毕,relativePath={}", normalizedPath);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
Reference in New Issue
Block a user