设备打卡
This commit is contained in:
@ -0,0 +1,118 @@
|
||||
package org.dromara.project.controller;
|
||||
|
||||
import cn.dev33.satoken.annotation.SaIgnore;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.dromara.common.core.domain.R;
|
||||
import org.dromara.common.web.core.BaseController;
|
||||
import org.dromara.project.domain.BusAttendanceMachine;
|
||||
import org.dromara.project.domain.dto.attendance.*;
|
||||
import org.dromara.project.service.IBusAttendanceMachineService;
|
||||
import org.dromara.project.service.IBusAttendanceService;
|
||||
import org.springframework.mock.web.MockMultipartFile;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.Base64;
|
||||
|
||||
/**
|
||||
* 考勤
|
||||
*
|
||||
* @author Lion Li
|
||||
* @date 2025-08-05
|
||||
*/
|
||||
@Validated
|
||||
@RequiredArgsConstructor
|
||||
@RestController
|
||||
@RequestMapping()
|
||||
@Slf4j
|
||||
public class BusAttendanceDeviceController extends BaseController {
|
||||
|
||||
private final IBusAttendanceService busAttendanceService;
|
||||
|
||||
private final IBusAttendanceMachineService busAttendanceMachineService;
|
||||
|
||||
@PostMapping("/api/v1/record/face")
|
||||
@SaIgnore
|
||||
public R<Boolean> punchCardByFace(@RequestBody DeviceDto dto) {
|
||||
//打印接收数据
|
||||
log.info("接收数据:{}", dto);
|
||||
if (dto.getLogs().isEmpty()) {
|
||||
return R.fail("没有数据");
|
||||
}
|
||||
Log first = dto.getLogs().getFirst();
|
||||
|
||||
Long userId = Long.valueOf(first.getUser_id());
|
||||
|
||||
BusAttendanceMachine one = busAttendanceMachineService.lambdaQuery()
|
||||
.eq(BusAttendanceMachine::getSn, dto.getSn())
|
||||
.last("limit 1")
|
||||
.one();
|
||||
if (one == null || one.getProjectId() == null) {
|
||||
return R.fail("考勤机不存在或未关联项目");
|
||||
}
|
||||
|
||||
String recogTime = first.getRecog_time();
|
||||
|
||||
LocalDateTime localDateTime = LocalDateTime.parse(recogTime, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
|
||||
|
||||
BusAttendancePunchCardByFaceReq req = new BusAttendancePunchCardByFaceReq();
|
||||
DeviceLocation location = first.getLocation();
|
||||
req.setLat(location.getLatitude());
|
||||
req.setLng(location.getLongitude());
|
||||
req.setProjectId(one.getProjectId());
|
||||
req.setUserId(userId);
|
||||
req.setPunchTime(localDateTime);
|
||||
//打印req
|
||||
log.info("请求参数:{}", req);
|
||||
//base64转MultipartFile
|
||||
try {
|
||||
// 假设first.getImage()返回base64字符串,且你有一个文件名
|
||||
MultipartFile file = convert(first.getPhoto(), "face.jpg");
|
||||
log.info("开始打卡");
|
||||
return R.ok(busAttendanceService.punchCardByFace(file, req));
|
||||
} catch (IOException e) {
|
||||
return R.fail("文件转换失败");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static MultipartFile convert(String base64String, String fileName) throws IOException {
|
||||
// 先进行URL解码(如果是URL编码过的数据)
|
||||
try {
|
||||
base64String = java.net.URLDecoder.decode(base64String, "UTF-8");
|
||||
} catch (Exception e) {
|
||||
// 如果不是URL编码的数据,直接跳过
|
||||
}
|
||||
|
||||
// 去除base64前缀(如data:image/png;base64,)
|
||||
if (base64String.contains(",")) {
|
||||
base64String = base64String.split(",")[1];
|
||||
}
|
||||
|
||||
// 解码base64字符串
|
||||
byte[] decodedBytes = Base64.getDecoder().decode(base64String);
|
||||
|
||||
// 创建MultipartFile对象
|
||||
return new MockMultipartFile(fileName, fileName, "image/jpeg", decodedBytes);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
@ -5,6 +5,7 @@ import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* @author lilemy
|
||||
@ -41,4 +42,9 @@ public class BusAttendancePunchCardByFaceReq implements Serializable {
|
||||
*/
|
||||
private Long userId;
|
||||
|
||||
/**
|
||||
* 打卡时间
|
||||
*/
|
||||
private LocalDateTime punchTime;
|
||||
|
||||
}
|
||||
|
||||
@ -0,0 +1,14 @@
|
||||
package org.dromara.project.domain.dto.attendance;
|
||||
|
||||
|
||||
import lombok.Data;
|
||||
import org.apache.poi.ss.formula.functions.Count;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
public class DeviceDto {
|
||||
private String sn;
|
||||
private int Count;
|
||||
private List<Log> logs;
|
||||
}
|
||||
@ -0,0 +1,9 @@
|
||||
package org.dromara.project.domain.dto.attendance;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class DeviceLocation {
|
||||
private String longitude;
|
||||
private String latitude;
|
||||
}
|
||||
@ -0,0 +1,12 @@
|
||||
package org.dromara.project.domain.dto.attendance;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class Log {
|
||||
private String user_id;
|
||||
private String recog_type;
|
||||
private String recog_time;
|
||||
private String photo;
|
||||
private DeviceLocation location;
|
||||
}
|
||||
@ -326,7 +326,11 @@ public class BusAttendanceServiceImpl extends ServiceImpl<BusAttendanceMapper, B
|
||||
}
|
||||
synchronized (userId.toString().intern()) {
|
||||
// 记录当前打卡时间
|
||||
|
||||
LocalDateTime now = LocalDateTime.now();
|
||||
if(req.getPunchTime() != null){
|
||||
now = req.getPunchTime();
|
||||
}
|
||||
|
||||
//打卡范围
|
||||
if (!checkInRange(req)) {
|
||||
@ -617,6 +621,9 @@ public class BusAttendanceServiceImpl extends ServiceImpl<BusAttendanceMapper, B
|
||||
public Boolean checkInRange(BusAttendancePunchCardByFaceReq req) {
|
||||
// 获取当前用户
|
||||
Long userId = LoginHelper.getUserId();
|
||||
if (req.getUserId() != null) {
|
||||
userId = req.getUserId();
|
||||
}
|
||||
Long projectId = req.getProjectId();
|
||||
|
||||
SysUserVo sysUserVo = userService.queryById(userId);
|
||||
|
||||
Reference in New Issue
Block a user