分包考勤机
This commit is contained in:
@ -176,7 +176,7 @@ mybatis-plus:
|
||||
# 数据加密
|
||||
mybatis-encryptor:
|
||||
# 是否开启加密
|
||||
enable: false
|
||||
enable: true
|
||||
# 默认加密算法
|
||||
algorithm: BASE64
|
||||
# 编码方式 BASE64/HEX。默认BASE64
|
||||
|
||||
@ -0,0 +1,65 @@
|
||||
package org.dromara.contractor.controller;
|
||||
|
||||
import cn.dev33.satoken.annotation.SaCheckPermission;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.dromara.common.core.domain.R;
|
||||
import org.dromara.common.idempotent.annotation.RepeatSubmit;
|
||||
import org.dromara.common.log.annotation.Log;
|
||||
import org.dromara.common.log.enums.BusinessType;
|
||||
import org.dromara.common.web.core.BaseController;
|
||||
import org.dromara.contractor.domain.dto.attendancemachineuser.SubAttendanceMachineSendInfoUserReq;
|
||||
import org.dromara.contractor.domain.dto.attendancemachineuser.SubAttendanceMachineUserQueryReq;
|
||||
import org.dromara.contractor.domain.dto.attendancemachineuser.SubAttendanceMachineUserRemoveReq;
|
||||
import org.dromara.contractor.domain.vo.SubAttendanceMachineUserVo;
|
||||
import org.dromara.contractor.service.ISubAttendanceMachineUserService;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 分包考勤机用户
|
||||
*
|
||||
* @author lilemy
|
||||
* @date 2025-11-21 15:38
|
||||
*/
|
||||
@Validated
|
||||
@RequiredArgsConstructor
|
||||
@RestController
|
||||
@RequestMapping("/contractor/attendanceMachineUser")
|
||||
public class SubAttendanceMachineUserController extends BaseController {
|
||||
|
||||
private final ISubAttendanceMachineUserService subAttendanceMachineUserService;
|
||||
|
||||
/**
|
||||
* 查询考勤机用户列表
|
||||
*/
|
||||
@SaCheckPermission("contractor:attendanceMachineUser:list")
|
||||
@GetMapping("/list")
|
||||
public R<List<SubAttendanceMachineUserVo>> list(SubAttendanceMachineUserQueryReq req) {
|
||||
return R.ok(subAttendanceMachineUserService.queryList(req));
|
||||
}
|
||||
|
||||
/**
|
||||
* 下发用户到考勤机中
|
||||
*/
|
||||
@SaCheckPermission("contractor:attendanceMachineUser:add")
|
||||
@Log(title = "分包考勤机用户", businessType = BusinessType.INSERT)
|
||||
@RepeatSubmit()
|
||||
@PostMapping("/send")
|
||||
public R<String> sendPersonInfo(@Validated @RequestBody SubAttendanceMachineSendInfoUserReq req) {
|
||||
return R.ok(subAttendanceMachineUserService.sendPersonInfo(req));
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除考勤机用户
|
||||
*/
|
||||
@SaCheckPermission("contractor:attendanceMachineUser:remove")
|
||||
@Log(title = "分包考勤机用户", businessType = BusinessType.DELETE)
|
||||
@RepeatSubmit()
|
||||
@DeleteMapping()
|
||||
public R<Void> remove(@Validated @RequestBody SubAttendanceMachineUserRemoveReq req) {
|
||||
return toAjax(subAttendanceMachineUserService.remove(req));
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,32 @@
|
||||
package org.dromara.contractor.domain.dto.attendancemachineuser;
|
||||
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author lilemy
|
||||
* @date 2025-11-21 15:36
|
||||
*/
|
||||
@Data
|
||||
public class SubAttendanceMachineSendInfoUserReq implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = -6517799483848691652L;
|
||||
|
||||
/**
|
||||
* 考勤机主键ID
|
||||
*/
|
||||
@NotNull(message = "考勤机不能为空")
|
||||
private Long machineId;
|
||||
|
||||
/**
|
||||
* 用户ID列表
|
||||
*/
|
||||
@NotNull(message = "用户列表不能为空")
|
||||
private List<Long> userIds;
|
||||
|
||||
}
|
||||
@ -0,0 +1,46 @@
|
||||
package org.dromara.contractor.domain.dto.attendancemachineuser;
|
||||
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* @author lilemy
|
||||
* @date 2025-11-21 15:36
|
||||
*/
|
||||
@Data
|
||||
public class SubAttendanceMachineUserQueryReq implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = -1629819732452840391L;
|
||||
|
||||
/**
|
||||
* 考勤机主键ID
|
||||
*/
|
||||
@NotNull(message = "考勤机不能为空")
|
||||
private Long machineId;
|
||||
|
||||
/**
|
||||
* 项目ID
|
||||
*/
|
||||
@NotNull(message = "项目不能为空")
|
||||
private Long projectId;
|
||||
|
||||
/**
|
||||
* 分包ID
|
||||
*/
|
||||
@NotNull(message = "分包不能为空")
|
||||
private Long contractorId;
|
||||
|
||||
/**
|
||||
* 用户名称
|
||||
*/
|
||||
private String userName;
|
||||
|
||||
/**
|
||||
* 标识(是否下发)
|
||||
*/
|
||||
private Integer identifying;
|
||||
}
|
||||
@ -0,0 +1,31 @@
|
||||
package org.dromara.contractor.domain.dto.attendancemachineuser;
|
||||
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author lilemy
|
||||
* @date 2025-11-21 15:36
|
||||
*/
|
||||
@Data
|
||||
public class SubAttendanceMachineUserRemoveReq implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = -8880884070612972760L;
|
||||
|
||||
/**
|
||||
* 考勤机主键ID
|
||||
*/
|
||||
@NotNull(message = "考勤机不能为空")
|
||||
private Long machineId;
|
||||
|
||||
/**
|
||||
* 用户ID列表
|
||||
*/
|
||||
@NotNull(message = "用户列表不能为空")
|
||||
private List<Long> userIds;
|
||||
}
|
||||
@ -1,28 +1,23 @@
|
||||
package org.dromara.project.domain;
|
||||
package org.dromara.contractor.domain.vo;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
|
||||
/**
|
||||
* 考勤机用户对象 bus_attendance_machine_user
|
||||
* 考勤机用户视图对象
|
||||
*
|
||||
* @author lilemy
|
||||
* @date 2025-10-15
|
||||
* @date 2025-11-21
|
||||
*/
|
||||
@Data
|
||||
public class BusAttendanceMachineUser implements Serializable {
|
||||
public class SubAttendanceMachineUserVo implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 主键ID
|
||||
*/
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 考勤机主键ID
|
||||
*/
|
||||
@ -31,26 +26,21 @@ public class BusAttendanceMachineUser implements Serializable {
|
||||
/**
|
||||
* 班组ID
|
||||
*/
|
||||
private Long teamId;
|
||||
private Long contractorId;
|
||||
|
||||
/**
|
||||
* 用户ID
|
||||
*/
|
||||
private Long userId;
|
||||
|
||||
/**
|
||||
* 用户名称
|
||||
*/
|
||||
private String userName;
|
||||
|
||||
/**
|
||||
* 标识(是否下发)
|
||||
*/
|
||||
private Integer identifying;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
private Date createTime;
|
||||
|
||||
/**
|
||||
* 更新时间
|
||||
*/
|
||||
private Date updateTime;
|
||||
|
||||
}
|
||||
@ -0,0 +1,41 @@
|
||||
package org.dromara.contractor.service;
|
||||
|
||||
import org.dromara.contractor.domain.dto.attendancemachineuser.SubAttendanceMachineSendInfoUserReq;
|
||||
import org.dromara.contractor.domain.dto.attendancemachineuser.SubAttendanceMachineUserQueryReq;
|
||||
import org.dromara.contractor.domain.dto.attendancemachineuser.SubAttendanceMachineUserRemoveReq;
|
||||
import org.dromara.contractor.domain.vo.SubAttendanceMachineUserVo;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 分包考勤机用户Service接口
|
||||
*
|
||||
* @author lilemy
|
||||
* @date 2025-11-21 15:33
|
||||
*/
|
||||
public interface ISubAttendanceMachineUserService {
|
||||
|
||||
/**
|
||||
* 查询符合条件的考勤机用户列表
|
||||
*
|
||||
* @param req 查询条件
|
||||
* @return 考勤机用户列表
|
||||
*/
|
||||
List<SubAttendanceMachineUserVo> queryList(SubAttendanceMachineUserQueryReq req);
|
||||
|
||||
/**
|
||||
* 下发用户到考勤机中
|
||||
*
|
||||
* @param req 下发用户参数
|
||||
* @return 下发结果
|
||||
*/
|
||||
String sendPersonInfo(SubAttendanceMachineSendInfoUserReq req);
|
||||
|
||||
/**
|
||||
* 删除考勤机用户
|
||||
*
|
||||
* @param req 删除参数
|
||||
* @return 删除结果
|
||||
*/
|
||||
Boolean remove(SubAttendanceMachineUserRemoveReq req);
|
||||
}
|
||||
@ -0,0 +1,182 @@
|
||||
package org.dromara.contractor.service.impl;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.dromara.common.core.constant.HttpStatus;
|
||||
import org.dromara.common.core.exception.ServiceException;
|
||||
import org.dromara.common.core.utils.StringUtils;
|
||||
import org.dromara.contractor.domain.SubConstructionUser;
|
||||
import org.dromara.contractor.domain.dto.attendancemachineuser.SubAttendanceMachineSendInfoUserReq;
|
||||
import org.dromara.contractor.domain.dto.attendancemachineuser.SubAttendanceMachineUserQueryReq;
|
||||
import org.dromara.contractor.domain.dto.attendancemachineuser.SubAttendanceMachineUserRemoveReq;
|
||||
import org.dromara.contractor.domain.vo.SubAttendanceMachineUserVo;
|
||||
import org.dromara.contractor.service.ISubAttendanceMachineUserService;
|
||||
import org.dromara.contractor.service.ISubConstructionUserService;
|
||||
import org.dromara.mobileAttendanceMachine.DeviceMessageSender;
|
||||
import org.dromara.mobileAttendanceMachine.KqjEntity;
|
||||
import org.dromara.project.domain.BusAttendanceMachine;
|
||||
import org.dromara.project.service.IBusAttendanceMachineService;
|
||||
import org.dromara.system.domain.vo.SysOssVo;
|
||||
import org.dromara.system.domain.vo.SysUserVo;
|
||||
import org.dromara.system.service.ISysOssService;
|
||||
import org.dromara.system.service.ISysUserService;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 分包考勤机用户Service业务层处理
|
||||
*
|
||||
* @author lilemy
|
||||
* @date 2025-11-21 15:35
|
||||
*/
|
||||
@Slf4j
|
||||
@RequiredArgsConstructor
|
||||
@Service
|
||||
public class SubAttendanceMachineUserServiceImpl implements ISubAttendanceMachineUserService {
|
||||
|
||||
private final IBusAttendanceMachineService attendanceMachineService;
|
||||
|
||||
private final DeviceMessageSender deviceMessageSender;
|
||||
|
||||
private final ISubConstructionUserService constructionUserService;
|
||||
|
||||
private final ISysUserService userService;
|
||||
|
||||
private final ISysOssService ossService;
|
||||
|
||||
/**
|
||||
* 查询符合条件的考勤机用户列表
|
||||
*
|
||||
* @param req 查询条件
|
||||
* @return 考勤机用户列表
|
||||
*/
|
||||
@Override
|
||||
public List<SubAttendanceMachineUserVo> queryList(SubAttendanceMachineUserQueryReq req) {
|
||||
List<SysUserVo> userVoList = userService.selectFbUserList(req.getProjectId(), List.of(req.getContractorId()), req.getUserName());
|
||||
if (CollUtil.isEmpty(userVoList)) {
|
||||
return CollUtil.newArrayList();
|
||||
}
|
||||
BusAttendanceMachine machine = attendanceMachineService.getById(req.getMachineId());
|
||||
if (machine == null) {
|
||||
throw new ServiceException("考勤机不存在", HttpStatus.NOT_FOUND);
|
||||
}
|
||||
// 判断选择分包和考勤机是否一致
|
||||
if (StringUtils.isBlank(machine.getContractors())) {
|
||||
throw new ServiceException("考勤机未绑定分包", HttpStatus.NOT_FOUND);
|
||||
}
|
||||
if (!Arrays.stream(machine.getContractors().split(","))
|
||||
.map(Long::parseLong)
|
||||
.collect(Collectors.toSet()).contains(req.getContractorId())) {
|
||||
throw new ServiceException("所选分包与考勤机不匹配", HttpStatus.NOT_FOUND);
|
||||
}
|
||||
// 获取考勤机里的用户
|
||||
Set<String> userIdList = new HashSet<>();
|
||||
try {
|
||||
KqjEntity.CommonResponse response = deviceMessageSender.getAllUsers(machine.getSn());
|
||||
int code = response.getData().getCode();
|
||||
if (code == 0 || code == 200) {
|
||||
log.info("获取考勤机数据成功:{}", response.getData());
|
||||
String[] userIds = response.getData().getUserIds();
|
||||
userIdList = Arrays.stream(userIds).collect(Collectors.toSet());
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("获取考勤机用户失败,sn:{}", machine.getSn(), e);
|
||||
throw new ServiceException("获取考勤机用户失败", HttpStatus.ERROR);
|
||||
}
|
||||
Set<String> finalUserIdList = userIdList;
|
||||
return userVoList.stream().map(userVo -> {
|
||||
SubAttendanceMachineUserVo vo = new SubAttendanceMachineUserVo();
|
||||
vo.setMachineId(req.getMachineId());
|
||||
vo.setContractorId(req.getContractorId());
|
||||
vo.setUserId(userVo.getUserId());
|
||||
vo.setUserName(userVo.getUserName());
|
||||
if (CollUtil.isEmpty(finalUserIdList)) {
|
||||
vo.setIdentifying(0);
|
||||
} else if (finalUserIdList.contains(userVo.getUserId().toString())) {
|
||||
vo.setIdentifying(1);
|
||||
} else {
|
||||
vo.setIdentifying(0);
|
||||
}
|
||||
return vo;
|
||||
}).toList();
|
||||
}
|
||||
|
||||
/**
|
||||
* 下发用户到考勤机中
|
||||
*
|
||||
* @param req 下发用户参数
|
||||
* @return 下发结果
|
||||
*/
|
||||
@Override
|
||||
public String sendPersonInfo(SubAttendanceMachineSendInfoUserReq req) {
|
||||
Long machineId = req.getMachineId();
|
||||
List<Long> userIds = req.getUserIds();
|
||||
BusAttendanceMachine machine = attendanceMachineService.getById(machineId);
|
||||
if (machine == null) {
|
||||
throw new ServiceException("考勤机不存在");
|
||||
}
|
||||
List<SubConstructionUser> userList = constructionUserService.lambdaQuery()
|
||||
.in(SubConstructionUser::getSysUserId, userIds)
|
||||
.list();
|
||||
// 获取用户人脸照信息
|
||||
List<Long> faceIds = userList.stream().map(SubConstructionUser::getFacePic).map(Long::parseLong).distinct().toList();
|
||||
List<SysOssVo> ossVos = ossService.listByIds(faceIds);
|
||||
Map<Long, SysOssVo> ossVoMap = ossVos.stream()
|
||||
.collect(Collectors.toMap(SysOssVo::getOssId, v -> v));
|
||||
// 返回数据
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("用户:[");
|
||||
int count = 0;
|
||||
for (SubConstructionUser user : userList) {
|
||||
String facePic = user.getFacePic();
|
||||
if (StringUtils.isBlank(facePic)) {
|
||||
sb.append(user.getUserName()).append(" ");
|
||||
count++;
|
||||
continue;
|
||||
}
|
||||
SysOssVo ossVo = ossVoMap.get(Long.parseLong(facePic));
|
||||
if (ossVo == null) {
|
||||
sb.append(user.getUserName()).append(" ");
|
||||
count++;
|
||||
continue;
|
||||
}
|
||||
Boolean result = deviceMessageSender.sendPersonnelInformation(machine.getSn(),
|
||||
user.getSysUserId().toString(), user.getUserName(), ossVo.getUrl());
|
||||
log.info("考勤机 Sn:{} ,用户:{} 下发成功", machine.getSn(), user.getUserName());
|
||||
if (!result) {
|
||||
sb.append(user.getUserName()).append(" ");
|
||||
count++;
|
||||
}
|
||||
}
|
||||
sb.append("] 下发失败");
|
||||
return count == 0 ? "下发成功" : sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除考勤机用户
|
||||
*
|
||||
* @param req 删除参数
|
||||
* @return 删除结果
|
||||
*/
|
||||
@Override
|
||||
public Boolean remove(SubAttendanceMachineUserRemoveReq req) {
|
||||
Long machineId = req.getMachineId();
|
||||
List<Long> userIds = req.getUserIds();
|
||||
BusAttendanceMachine machine = attendanceMachineService.getById(machineId);
|
||||
if (machine == null) {
|
||||
throw new ServiceException("考勤机不存在", HttpStatus.NOT_FOUND);
|
||||
}
|
||||
String[] userIdArray = userIds.stream()
|
||||
.map(String::valueOf) // 将 Long 转成 String
|
||||
.toArray(String[]::new);
|
||||
try {
|
||||
KqjEntity.CommonResponse response = deviceMessageSender.batchDeleteUsers(machine.getSn(), userIdArray);
|
||||
return response.getData().getCode() == 0 || response.getData().getCode() == 200;
|
||||
} catch (Exception e) {
|
||||
throw new ServiceException("删除考勤机用户失败", HttpStatus.ERROR);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -3,49 +3,49 @@ package org.dromara.gps.service.impl;
|
||||
import cn.hutool.core.collection.CollectionUtil;
|
||||
import cn.hutool.json.JSONObject;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
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.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.dromara.vehicle.domain.VehVehicleInfo;
|
||||
import org.dromara.vehicle.domain.vo.VehVehicleInfoVo;
|
||||
import org.dromara.vehicle.service.IVehVehicleInfoService;
|
||||
import org.dromara.vehicle.service.IVehVehicleTripService;
|
||||
import org.dromara.websocket.websocket.service.InitOnStartWebSocketServer;
|
||||
import org.dromara.common.core.exception.ServiceException;
|
||||
import org.dromara.common.core.utils.MapstructUtils;
|
||||
import org.dromara.common.core.utils.StringUtils;
|
||||
import org.dromara.common.mybatis.core.page.TableDataInfo;
|
||||
import org.dromara.common.mybatis.core.page.PageQuery;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.dromara.common.mybatis.core.page.TableDataInfo;
|
||||
import org.dromara.common.redis.utils.RedisUtils;
|
||||
import org.dromara.common.websocket.dto.WebSocketMessageDto;
|
||||
import org.dromara.common.websocket.holder.WebSocketSessionHolder;
|
||||
import org.dromara.common.websocket.utils.WebSocketUtils;
|
||||
import org.dromara.gps.domain.GpsEquipment;
|
||||
import org.dromara.gps.domain.GpsManmachine;
|
||||
import org.dromara.gps.domain.bo.GpsEquipmentBo;
|
||||
import org.dromara.gps.domain.bo.GpsEquipmentSonBo;
|
||||
import org.dromara.gps.domain.vo.GpsEquipmentSonVo;
|
||||
import org.dromara.gps.domain.vo.GpsEquipmentVo;
|
||||
import org.dromara.gps.domain.vo.GpsProjectVo;
|
||||
import org.dromara.gps.domain.vo.GpsUserVo;
|
||||
import org.dromara.gps.mapper.GpsEquipmentMapper;
|
||||
import org.dromara.gps.mapper.GpsManmachineMapper;
|
||||
import org.dromara.gps.service.IGpsEquipmentService;
|
||||
import org.dromara.gps.service.IGpsEquipmentSonService;
|
||||
import org.dromara.project.domain.vo.project.BusProjectVo;
|
||||
import org.dromara.project.service.IBusProjectService;
|
||||
import org.dromara.system.domain.vo.SysUserVo;
|
||||
import org.dromara.system.service.ISysUserService;
|
||||
import org.dromara.vehicle.domain.VehVehicleInfo;
|
||||
import org.dromara.vehicle.domain.vo.VehVehicleInfoVo;
|
||||
import org.dromara.vehicle.service.IVehVehicleInfoService;
|
||||
import org.dromara.vehicle.service.IVehVehicleTripService;
|
||||
import org.dromara.websocket.websocket.service.InitOnStartWebSocketServer;
|
||||
import org.dromara.websocket.websocket.service.VehicleWebSocketServer;
|
||||
import org.redisson.api.DeletedObjectListener;
|
||||
import org.redisson.api.ExpiredObjectListener;
|
||||
import org.redisson.api.listener.SetObjectListener;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.dromara.gps.domain.bo.GpsEquipmentBo;
|
||||
import org.dromara.gps.domain.vo.GpsEquipmentVo;
|
||||
import org.dromara.gps.domain.GpsEquipment;
|
||||
import org.dromara.gps.mapper.GpsEquipmentMapper;
|
||||
import org.dromara.gps.service.IGpsEquipmentService;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
@ -63,7 +63,8 @@ import java.util.*;
|
||||
@RequiredArgsConstructor
|
||||
@Service
|
||||
@Slf4j
|
||||
public class GpsEquipmentServiceImpl extends ServiceImpl<GpsEquipmentMapper, GpsEquipment> implements IGpsEquipmentService {
|
||||
public class GpsEquipmentServiceImpl extends ServiceImpl<GpsEquipmentMapper, GpsEquipment>
|
||||
implements IGpsEquipmentService {
|
||||
|
||||
private final GpsEquipmentMapper baseMapper;
|
||||
|
||||
@ -289,7 +290,6 @@ public class GpsEquipmentServiceImpl extends ServiceImpl<GpsEquipmentMapper, Gps
|
||||
}
|
||||
|
||||
|
||||
|
||||
Set<Long> sessionsAll = WebSocketSessionHolder.getSessionsAll();
|
||||
|
||||
if (!sessionsAll.isEmpty()) {
|
||||
@ -319,17 +319,17 @@ public class GpsEquipmentServiceImpl extends ServiceImpl<GpsEquipmentMapper, Gps
|
||||
private String buildPushMessage(GpsEquipmentSonBo sonBo) {
|
||||
// 构造消息对象(包含关键信息)
|
||||
JSONObject messageObj = new JSONObject();
|
||||
messageObj.put("type", "GPS_DATA_UPDATE"); // 消息类型
|
||||
messageObj.put("clientId", sonBo.getClientId()); // 设备唯一标识
|
||||
messageObj.put("projectId", sonBo.getProjectId().toString()); // 项目ID
|
||||
messageObj.put("userId", sonBo.getUserId().toString()); // 关联用户ID
|
||||
messageObj.set("type", "GPS_DATA_UPDATE"); // 消息类型
|
||||
messageObj.set("clientId", sonBo.getClientId()); // 设备唯一标识
|
||||
messageObj.set("projectId", sonBo.getProjectId().toString()); // 项目ID
|
||||
messageObj.set("userId", sonBo.getUserId().toString()); // 关联用户ID
|
||||
|
||||
// 位置信息
|
||||
JSONObject locationObj = new JSONObject();
|
||||
locationObj.put("latitude", sonBo.getLocLatitude().toString()); // 纬度
|
||||
locationObj.put("longitude", sonBo.getLocLongitude().toString()); // 经度
|
||||
locationObj.put("altitude", sonBo.getLocAltitude().toString()); // 海拔
|
||||
messageObj.put("location", locationObj);
|
||||
locationObj.set("latitude", sonBo.getLocLatitude().toString()); // 纬度
|
||||
locationObj.set("longitude", sonBo.getLocLongitude().toString()); // 经度
|
||||
locationObj.set("altitude", sonBo.getLocAltitude().toString()); // 海拔
|
||||
messageObj.set("location", locationObj);
|
||||
|
||||
// 转换为String类型返回
|
||||
return messageObj.toString();
|
||||
@ -341,19 +341,19 @@ public class GpsEquipmentServiceImpl extends ServiceImpl<GpsEquipmentMapper, Gps
|
||||
private String ueStructureJsonMessage(GpsEquipmentSonBo sonBo, String modelId) {
|
||||
// 构造消息对象(包含关键信息)
|
||||
JSONObject messageObj = new JSONObject();
|
||||
messageObj.put("type", "location"); // 消息类型
|
||||
messageObj.set("type", "location"); // 消息类型
|
||||
|
||||
JSONObject data = new JSONObject();
|
||||
data.put("id", modelId);
|
||||
data.set("id", modelId);
|
||||
|
||||
// 位置信息
|
||||
JSONObject position = new JSONObject();
|
||||
position.put("lat", sonBo.getLocLatitude().toString()); // 纬度
|
||||
position.put("lng", sonBo.getLocLongitude().toString()); // 经度
|
||||
position.put("alt", sonBo.getLocAltitude().toString()); // 海拔
|
||||
position.set("lat", sonBo.getLocLatitude().toString()); // 纬度
|
||||
position.set("lng", sonBo.getLocLongitude().toString()); // 经度
|
||||
position.set("alt", sonBo.getLocAltitude().toString()); // 海拔
|
||||
|
||||
data.put("position", position);
|
||||
messageObj.put("data", data); // 设备唯一标识
|
||||
data.set("position", position);
|
||||
messageObj.set("data", data); // 设备唯一标识
|
||||
|
||||
// 转换为String类型返回
|
||||
return messageObj.toString();
|
||||
@ -366,16 +366,18 @@ public class GpsEquipmentServiceImpl extends ServiceImpl<GpsEquipmentMapper, Gps
|
||||
private String vehicleStructureJsonMessage(GpsEquipmentSonBo sonBo) {
|
||||
// 构造消息对象(包含关键信息)
|
||||
JSONObject messageObj = new JSONObject();
|
||||
messageObj.put("locLatitude", sonBo.getLocLatitude().toString()); // 消息类型
|
||||
messageObj.put("locLongitude", sonBo.getLocLongitude().toString()); // 消息类型
|
||||
messageObj.set("locLatitude", sonBo.getLocLatitude().toString()); // 消息类型
|
||||
messageObj.set("locLongitude", sonBo.getLocLongitude().toString()); // 消息类型
|
||||
// 转换为String类型返回
|
||||
return messageObj.toString();
|
||||
}
|
||||
|
||||
|
||||
private static final int DEVICE_ALIVE_TIMEOUT = 120; // 5分钟
|
||||
|
||||
/**
|
||||
* 更新设备存活状态到Redis并添加过期监听
|
||||
*
|
||||
* @param clientId 设备ID
|
||||
*/
|
||||
private void updateDeviceAliveStatus(String clientId) {
|
||||
@ -412,10 +414,9 @@ public class GpsEquipmentServiceImpl extends ServiceImpl<GpsEquipmentMapper, Gps
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 处理设备离线
|
||||
*
|
||||
* @param clientId 设备ID
|
||||
*/
|
||||
private void handleDeviceOffline(String clientId) {
|
||||
@ -434,9 +435,12 @@ public class GpsEquipmentServiceImpl extends ServiceImpl<GpsEquipmentMapper, Gps
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* GPS人机关联绑定
|
||||
*
|
||||
* @param bo
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public Boolean bindManmachine(GpsEquipmentBo bo) {
|
||||
@ -488,8 +492,9 @@ public class GpsEquipmentServiceImpl extends ServiceImpl<GpsEquipmentMapper, Gps
|
||||
|
||||
/**
|
||||
* 获取设备绑定用户列表
|
||||
* @param bo
|
||||
* @return
|
||||
*
|
||||
* @param bo 设备信息
|
||||
* @return GPS人机关联视图对象列表
|
||||
*/
|
||||
@Override
|
||||
public List<GpsUserVo> getUserList(GpsEquipmentBo bo) {
|
||||
|
||||
@ -3,6 +3,7 @@ package org.dromara.job.project;
|
||||
import jakarta.annotation.Resource;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.dromara.project.constant.BusProjectConstant;
|
||||
import org.springframework.data.redis.connection.RedisConnectionFactory;
|
||||
import org.springframework.data.redis.core.Cursor;
|
||||
import org.springframework.data.redis.core.ScanOptions;
|
||||
import org.springframework.data.redis.core.StringRedisTemplate;
|
||||
@ -35,12 +36,17 @@ public class DeleteProjectCache {
|
||||
.count(1000) // 每次 scan 的数量
|
||||
.build();
|
||||
Set<String> keysToDelete = new HashSet<>();
|
||||
Cursor<byte[]> cursor = stringRedisTemplate.getConnectionFactory()
|
||||
.getConnection()
|
||||
.scan(scanOptions);
|
||||
RedisConnectionFactory connectionFactory = stringRedisTemplate.getConnectionFactory();
|
||||
if (connectionFactory == null) {
|
||||
log.error("Redis 连接工厂异常");
|
||||
return;
|
||||
}
|
||||
try (Cursor<byte[]> cursor = connectionFactory.getConnection()
|
||||
.keyCommands().scan(scanOptions)) {
|
||||
while (cursor.hasNext()) {
|
||||
keysToDelete.add(new String(cursor.next()));
|
||||
}
|
||||
}
|
||||
// 批量删除
|
||||
if (!keysToDelete.isEmpty()) {
|
||||
log.info("清理项目缓存,共 {} 条:{}", keysToDelete.size(), keysToDelete);
|
||||
|
||||
@ -13,8 +13,9 @@ import org.dromara.common.log.enums.BusinessType;
|
||||
import org.dromara.common.mybatis.core.page.PageQuery;
|
||||
import org.dromara.common.mybatis.core.page.TableDataInfo;
|
||||
import org.dromara.common.web.core.BaseController;
|
||||
import org.dromara.project.domain.dto.attendancemachine.BusAttendanceMachineContractorUpdateReq;
|
||||
import org.dromara.project.domain.dto.attendancemachine.BusAttendanceMachineQueryReq;
|
||||
import org.dromara.project.domain.dto.attendancemachine.BusAttendanceMachineUpdateReq;
|
||||
import org.dromara.project.domain.dto.attendancemachine.BusAttendanceMachineTeamUpdateReq;
|
||||
import org.dromara.project.domain.vo.BusAttendanceMachineVo;
|
||||
import org.dromara.project.service.IBusAttendanceMachineService;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
@ -69,14 +70,25 @@ public class BusAttendanceMachineController extends BaseController {
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改考勤机
|
||||
* 修改考勤机班组
|
||||
*/
|
||||
@SaCheckPermission("project:attendanceMachine:edit")
|
||||
@Log(title = "考勤机", businessType = BusinessType.UPDATE)
|
||||
@RepeatSubmit()
|
||||
@PutMapping()
|
||||
public R<Void> edit(@Validated @RequestBody BusAttendanceMachineUpdateReq req) {
|
||||
return toAjax(busAttendanceMachineService.updateByBo(req));
|
||||
@PutMapping("/team")
|
||||
public R<Void> edit(@Validated @RequestBody BusAttendanceMachineTeamUpdateReq req) {
|
||||
return toAjax(busAttendanceMachineService.updateTeam(req));
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改考勤机分包
|
||||
*/
|
||||
@SaCheckPermission("project:attendanceMachine:edit")
|
||||
@Log(title = "考勤机", businessType = BusinessType.UPDATE)
|
||||
@RepeatSubmit()
|
||||
@PutMapping("/contractor")
|
||||
public R<Void> editContractor(@Validated @RequestBody BusAttendanceMachineContractorUpdateReq req) {
|
||||
return toAjax(busAttendanceMachineService.updateContractor(req));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -18,7 +18,7 @@ import org.springframework.web.bind.annotation.*;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 考勤机用户
|
||||
* 班组考勤机用户
|
||||
*
|
||||
* @author lilemy
|
||||
* @date 2025-10-15
|
||||
@ -44,7 +44,7 @@ public class BusAttendanceMachineUserController extends BaseController {
|
||||
* 下发用户到考勤机中
|
||||
*/
|
||||
@SaCheckPermission("project:attendanceMachineUser:add")
|
||||
@Log(title = "考勤机用户", businessType = BusinessType.INSERT)
|
||||
@Log(title = "班组考勤机用户", businessType = BusinessType.INSERT)
|
||||
@RepeatSubmit()
|
||||
@PostMapping("/send")
|
||||
public R<String> sendPersonInfo(@Validated @RequestBody BusAttendanceMachineSendInfoUserReq req) {
|
||||
@ -55,7 +55,7 @@ public class BusAttendanceMachineUserController extends BaseController {
|
||||
* 删除考勤机用户
|
||||
*/
|
||||
@SaCheckPermission("project:attendanceMachineUser:remove")
|
||||
@Log(title = "考勤机用户", businessType = BusinessType.DELETE)
|
||||
@Log(title = "班组考勤机用户", businessType = BusinessType.DELETE)
|
||||
@RepeatSubmit()
|
||||
@DeleteMapping()
|
||||
public R<Void> remove(@Validated @RequestBody BusAttendanceMachineUserRemoveReq req) {
|
||||
|
||||
@ -47,6 +47,11 @@ public class BusAttendanceMachine implements Serializable {
|
||||
*/
|
||||
private String teams;
|
||||
|
||||
/**
|
||||
* 分包id,多个逗号分隔
|
||||
*/
|
||||
private String contractors;
|
||||
|
||||
/**
|
||||
* 备注
|
||||
*/
|
||||
|
||||
@ -0,0 +1,40 @@
|
||||
package org.dromara.project.domain.dto.attendancemachine;
|
||||
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* @author lilemy
|
||||
* @date 2025-11-21 10:56
|
||||
*/
|
||||
@Data
|
||||
public class BusAttendanceMachineContractorUpdateReq implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 4141889040329671715L;
|
||||
|
||||
/**
|
||||
* 主键ID
|
||||
*/
|
||||
@NotNull(message = "主键ID不能为空")
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 项目ID
|
||||
*/
|
||||
@NotNull(message = "项目ID不能为空")
|
||||
private Long projectId;
|
||||
|
||||
/**
|
||||
* 分包id,多个逗号分隔
|
||||
*/
|
||||
private String contractors;
|
||||
|
||||
/**
|
||||
* 备注
|
||||
*/
|
||||
private String remark;
|
||||
}
|
||||
@ -11,7 +11,7 @@ import java.io.Serializable;
|
||||
* @date 2025-10-15 16:15
|
||||
*/
|
||||
@Data
|
||||
public class BusAttendanceMachineUpdateReq implements Serializable {
|
||||
public class BusAttendanceMachineTeamUpdateReq implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 4764015594443520162L;
|
||||
@ -8,6 +8,7 @@ import org.dromara.common.excel.annotation.ExcelDictFormat;
|
||||
import org.dromara.common.excel.convert.ExcelDictConvert;
|
||||
import org.dromara.common.translation.annotation.Translation;
|
||||
import org.dromara.common.translation.constant.TransConstant;
|
||||
import org.dromara.contractor.domain.vo.contractor.SubContractorVo;
|
||||
import org.dromara.project.domain.BusAttendanceMachine;
|
||||
import org.dromara.project.domain.vo.projectteam.BusProjectTeamVo;
|
||||
|
||||
@ -68,11 +69,22 @@ public class BusAttendanceMachineVo implements Serializable {
|
||||
@ExcelProperty(value = "班组id,多个逗号分隔")
|
||||
private String teams;
|
||||
|
||||
/**
|
||||
* 分包id,多个逗号分隔
|
||||
*/
|
||||
@ExcelProperty(value = "分包id,多个逗号分隔")
|
||||
private String contractors;
|
||||
|
||||
/**
|
||||
* 班组列表
|
||||
*/
|
||||
private List<BusProjectTeamVo> teamsList;
|
||||
|
||||
/**
|
||||
* 分包列表
|
||||
*/
|
||||
private List<SubContractorVo> contractorsList;
|
||||
|
||||
/**
|
||||
* 备注
|
||||
*/
|
||||
|
||||
@ -1,15 +1,13 @@
|
||||
package org.dromara.project.service;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import jakarta.validation.constraints.NotEmpty;
|
||||
import org.dromara.common.mybatis.core.page.PageQuery;
|
||||
import org.dromara.common.mybatis.core.page.TableDataInfo;
|
||||
import org.dromara.project.domain.BusAttendanceMachine;
|
||||
import org.dromara.project.domain.dto.attendancemachine.BusAttendanceMachineContractorUpdateReq;
|
||||
import org.dromara.project.domain.dto.attendancemachine.BusAttendanceMachineQueryReq;
|
||||
import org.dromara.project.domain.dto.attendancemachine.BusAttendanceMachineUpdateReq;
|
||||
import org.dromara.project.domain.dto.attendancemachine.BusAttendanceMachineTeamUpdateReq;
|
||||
import org.dromara.project.domain.vo.BusAttendanceMachineVo;
|
||||
import org.springframework.scheduling.annotation.Async;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
@ -55,12 +53,20 @@ public interface IBusAttendanceMachineService extends IService<BusAttendanceMach
|
||||
void insertBySn(String sn);
|
||||
|
||||
/**
|
||||
* 修改考勤机
|
||||
* 修改考勤机(班组)
|
||||
*
|
||||
* @param req 考勤机
|
||||
* @return 是否修改成功
|
||||
*/
|
||||
Boolean updateByBo(BusAttendanceMachineUpdateReq req);
|
||||
Boolean updateTeam(BusAttendanceMachineTeamUpdateReq req);
|
||||
|
||||
/**
|
||||
* 修改考勤机(分包)
|
||||
*
|
||||
* @param req 考勤机
|
||||
* @return 是否修改成功
|
||||
*/
|
||||
Boolean updateContractor(BusAttendanceMachineContractorUpdateReq req);
|
||||
|
||||
/**
|
||||
* 修改考勤机状态
|
||||
@ -79,6 +85,10 @@ public interface IBusAttendanceMachineService extends IService<BusAttendanceMach
|
||||
*/
|
||||
Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
|
||||
|
||||
|
||||
/**
|
||||
* 重发下发考勤机所有人员
|
||||
*
|
||||
* @param ids 待重发考勤机的主键集合
|
||||
*/
|
||||
void reissue(Collection<Long> ids);
|
||||
}
|
||||
|
||||
@ -8,7 +8,7 @@ import org.dromara.project.domain.vo.BusAttendanceMachineUserVo;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 考勤机用户Service接口
|
||||
* 班组考勤机用户Service接口
|
||||
*
|
||||
* @author lilemy
|
||||
* @date 2025-10-15
|
||||
|
||||
@ -8,20 +8,25 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import jakarta.annotation.Resource;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.dromara.common.core.constant.HttpStatus;
|
||||
import org.dromara.common.core.exception.ServiceException;
|
||||
import org.dromara.common.core.utils.StringUtils;
|
||||
import org.dromara.common.mybatis.core.page.PageQuery;
|
||||
import org.dromara.common.mybatis.core.page.TableDataInfo;
|
||||
import org.dromara.contractor.domain.SubConstructionUser;
|
||||
import org.dromara.contractor.domain.SubContractor;
|
||||
import org.dromara.contractor.domain.vo.contractor.SubContractorVo;
|
||||
import org.dromara.contractor.service.ISubConstructionUserService;
|
||||
import org.dromara.contractor.service.ISubContractorService;
|
||||
import org.dromara.mobileAttendanceMachine.DeviceMessageSender;
|
||||
import org.dromara.project.domain.BusAttendanceMachine;
|
||||
import org.dromara.project.domain.BusProject;
|
||||
import org.dromara.project.domain.BusProjectTeam;
|
||||
import org.dromara.project.domain.BusProjectTeamMember;
|
||||
import org.dromara.project.domain.dto.attendancemachine.BusAttendanceMachineContractorUpdateReq;
|
||||
import org.dromara.project.domain.dto.attendancemachine.BusAttendanceMachineQueryReq;
|
||||
import org.dromara.project.domain.dto.attendancemachine.BusAttendanceMachineUpdateReq;
|
||||
import org.dromara.project.domain.dto.attendancemachine.BusAttendanceMachineTeamUpdateReq;
|
||||
import org.dromara.project.domain.vo.BusAttendanceMachineVo;
|
||||
import org.dromara.project.domain.vo.projectteam.BusProjectTeamVo;
|
||||
import org.dromara.project.mapper.BusAttendanceMachineMapper;
|
||||
@ -30,7 +35,9 @@ import org.dromara.project.service.IBusProjectService;
|
||||
import org.dromara.project.service.IBusProjectTeamMemberService;
|
||||
import org.dromara.project.service.IBusProjectTeamService;
|
||||
import org.dromara.system.domain.vo.SysOssVo;
|
||||
import org.dromara.system.domain.vo.SysUserVo;
|
||||
import org.dromara.system.service.ISysOssService;
|
||||
import org.dromara.system.service.ISysUserService;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.scheduling.annotation.Async;
|
||||
@ -45,6 +52,7 @@ import java.util.stream.Collectors;
|
||||
* @author lilemy
|
||||
* @date 2025-10-15
|
||||
*/
|
||||
@Slf4j
|
||||
@RequiredArgsConstructor
|
||||
@Service
|
||||
public class BusAttendanceMachineServiceImpl extends ServiceImpl<BusAttendanceMachineMapper, BusAttendanceMachine>
|
||||
@ -59,6 +67,9 @@ public class BusAttendanceMachineServiceImpl extends ServiceImpl<BusAttendanceMa
|
||||
@Resource
|
||||
private IBusProjectTeamMemberService projectTeamMemberService;
|
||||
|
||||
@Resource
|
||||
private ISubContractorService contractorService;
|
||||
|
||||
@Resource
|
||||
private DeviceMessageSender deviceMessageSender;
|
||||
|
||||
@ -70,6 +81,9 @@ public class BusAttendanceMachineServiceImpl extends ServiceImpl<BusAttendanceMa
|
||||
@Lazy
|
||||
private ISysOssService ossService;
|
||||
|
||||
@Resource
|
||||
private ISysUserService userService;
|
||||
|
||||
|
||||
/**
|
||||
* 查询考勤机
|
||||
@ -94,18 +108,37 @@ public class BusAttendanceMachineServiceImpl extends ServiceImpl<BusAttendanceMa
|
||||
LambdaQueryWrapper<BusAttendanceMachine> lqw = buildQueryWrapper(req);
|
||||
Page<BusAttendanceMachineVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
|
||||
List<BusAttendanceMachineVo> records = result.getRecords();
|
||||
// 获取班组id列表
|
||||
List<Long> teamIds = records.stream()
|
||||
.map(BusAttendanceMachineVo::getTeams)
|
||||
.filter(StringUtils::isNotBlank)
|
||||
.flatMap(team -> Arrays.stream(team.split(",")) // flatMap 展开内部 stream
|
||||
.map(Long::parseLong))
|
||||
.toList();
|
||||
if (CollUtil.isEmpty(teamIds)) {
|
||||
// 获取分包id列表
|
||||
List<Long> contractorIds = records.stream()
|
||||
.map(BusAttendanceMachineVo::getContractors)
|
||||
.filter(StringUtils::isNotBlank)
|
||||
.flatMap(contractor -> Arrays.stream(contractor.split(",")) // flatMap 展开内部 stream
|
||||
.map(Long::parseLong))
|
||||
.toList();
|
||||
if (CollUtil.isEmpty(teamIds) && CollUtil.isEmpty(contractorIds)) {
|
||||
return TableDataInfo.build(result);
|
||||
}
|
||||
Map<Long, String> teamMap = new HashMap<>();
|
||||
Map<Long, String> contractorMap = new HashMap<>();
|
||||
if (CollUtil.isNotEmpty(teamIds)) {
|
||||
List<BusProjectTeam> projectTeams = projectTeamService.listByIds(teamIds);
|
||||
Map<Long, String> teamMap = projectTeams.stream()
|
||||
teamMap = projectTeams.stream()
|
||||
.collect(Collectors.toMap(BusProjectTeam::getId, BusProjectTeam::getTeamName));
|
||||
}
|
||||
if (CollUtil.isNotEmpty(contractorIds)) {
|
||||
List<SubContractor> contractors = contractorService.listByIds(contractorIds);
|
||||
contractorMap = contractors.stream()
|
||||
.collect(Collectors.toMap(SubContractor::getId, SubContractor::getName));
|
||||
}
|
||||
Map<Long, String> finalTeamMap = teamMap;
|
||||
Map<Long, String> finalContractorMap = contractorMap;
|
||||
records.forEach(machine -> {
|
||||
String teams = machine.getTeams();
|
||||
if (StringUtils.isNotBlank(teams)) {
|
||||
@ -113,11 +146,22 @@ public class BusAttendanceMachineServiceImpl extends ServiceImpl<BusAttendanceMa
|
||||
List<BusProjectTeamVo> teamVoList = t.stream().map(teamId -> {
|
||||
BusProjectTeamVo vo = new BusProjectTeamVo();
|
||||
vo.setId(teamId);
|
||||
vo.setTeamName(teamMap.getOrDefault(teamId, "未命名"));
|
||||
vo.setTeamName(finalTeamMap.getOrDefault(teamId, "未命名"));
|
||||
return vo;
|
||||
}).toList();
|
||||
machine.setTeamsList(teamVoList);
|
||||
}
|
||||
String contractors = machine.getContractors();
|
||||
if (StringUtils.isNotBlank(contractors)) {
|
||||
List<Long> c = Arrays.stream(contractors.split(",")).map(Long::parseLong).toList();
|
||||
List<SubContractorVo> contractorVoList = c.stream().map(contractorId -> {
|
||||
SubContractorVo vo = new SubContractorVo();
|
||||
vo.setId(contractorId);
|
||||
vo.setName(finalContractorMap.getOrDefault(contractorId, "未命名"));
|
||||
return vo;
|
||||
}).toList();
|
||||
machine.setContractorsList(contractorVoList);
|
||||
}
|
||||
});
|
||||
result.setRecords(records);
|
||||
return TableDataInfo.build(result);
|
||||
@ -173,7 +217,7 @@ public class BusAttendanceMachineServiceImpl extends ServiceImpl<BusAttendanceMa
|
||||
* @return 是否修改成功
|
||||
*/
|
||||
@Override
|
||||
public Boolean updateByBo(BusAttendanceMachineUpdateReq req) {
|
||||
public Boolean updateTeam(BusAttendanceMachineTeamUpdateReq req) {
|
||||
Long id = req.getId();
|
||||
BusAttendanceMachine oldMachine = this.getById(id);
|
||||
if (oldMachine == null) {
|
||||
@ -188,7 +232,7 @@ public class BusAttendanceMachineServiceImpl extends ServiceImpl<BusAttendanceMa
|
||||
throw new ServiceException("所选项目不存在", HttpStatus.NOT_FOUND);
|
||||
}
|
||||
String teams = req.getTeams();
|
||||
if (StringUtils.isBlank(teams) && StringUtils.isBlank(oldMachine.getTeams())) {
|
||||
if (StringUtils.isBlank(teams)) {
|
||||
throw new ServiceException("请选择班组", HttpStatus.BAD_REQUEST);
|
||||
}
|
||||
if (StringUtils.isNotBlank(teams)) {
|
||||
@ -200,6 +244,11 @@ public class BusAttendanceMachineServiceImpl extends ServiceImpl<BusAttendanceMa
|
||||
if (projectTeams.size() != teamIds.size()) {
|
||||
throw new ServiceException("所选班组不存在", HttpStatus.NOT_FOUND);
|
||||
}
|
||||
projectTeams.forEach(team -> {
|
||||
if (!team.getProjectId().equals(projectId)) {
|
||||
throw new ServiceException(team.getTeamName() + "不属于所选项目", HttpStatus.BAD_REQUEST);
|
||||
}
|
||||
});
|
||||
String oldTeams = oldMachine.getTeams();
|
||||
if (StringUtils.isNotBlank(oldTeams)) {
|
||||
List<Long> oldTeamIds = Arrays.stream(oldTeams.split(","))
|
||||
@ -247,7 +296,12 @@ public class BusAttendanceMachineServiceImpl extends ServiceImpl<BusAttendanceMa
|
||||
.in(SubConstructionUser::getSysUserId, userIds)
|
||||
.list();
|
||||
for (SubConstructionUser user : users) {
|
||||
SysOssVo ossVo = ossService.getById(Long.valueOf(user.getFacePic()));
|
||||
if (ossVo != null) {
|
||||
// 添加考勤机中用户
|
||||
deviceMessageSender.sendPersonnelInformation(machine.getSn(), user.getSysUserId().toString(),
|
||||
user.getUserName(), ossVo.getUrl());
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@ -264,13 +318,141 @@ public class BusAttendanceMachineServiceImpl extends ServiceImpl<BusAttendanceMa
|
||||
.list();
|
||||
for (SubConstructionUser user : users) {
|
||||
// 添加考勤机中用户
|
||||
SysOssVo ossVo = ossService.getById(Long.valueOf(user.getFacePic()));
|
||||
if (ossVo != null) {
|
||||
// 添加考勤机中用户
|
||||
deviceMessageSender.sendPersonnelInformation(machine.getSn(), user.getSysUserId().toString(),
|
||||
user.getUserName(), ossVo.getUrl());
|
||||
}
|
||||
}
|
||||
projectTeams.forEach(team -> {
|
||||
if (!team.getProjectId().equals(projectId)) {
|
||||
throw new ServiceException(team.getTeamName() + "不属于所选项目", HttpStatus.BAD_REQUEST);
|
||||
}
|
||||
}
|
||||
return this.updateById(machine);
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改考勤机(分包)
|
||||
*
|
||||
* @param req 考勤机
|
||||
* @return 是否修改成功
|
||||
*/
|
||||
@Override
|
||||
public Boolean updateContractor(BusAttendanceMachineContractorUpdateReq req) {
|
||||
Long id = req.getId();
|
||||
BusAttendanceMachine oldMachine = this.getById(id);
|
||||
if (oldMachine == null) {
|
||||
throw new ServiceException("考勤机不存在", HttpStatus.NOT_FOUND);
|
||||
}
|
||||
BusAttendanceMachine machine = new BusAttendanceMachine();
|
||||
BeanUtils.copyProperties(req, machine);
|
||||
// 判断分包是否属于所选项目
|
||||
Long projectId = req.getProjectId();
|
||||
BusProject project = projectService.getById(projectId);
|
||||
if (project == null) {
|
||||
throw new ServiceException("所选项目不存在", HttpStatus.NOT_FOUND);
|
||||
}
|
||||
String contractors = req.getContractors();
|
||||
if (StringUtils.isNotBlank(contractors)) {
|
||||
List<Long> contractorIds = Arrays.stream(contractors.split(","))
|
||||
.map(Long::parseLong)
|
||||
.distinct()
|
||||
.toList();
|
||||
List<SubContractor> subContractors = contractorService.listByIds(contractorIds);
|
||||
if (subContractors.size() != contractorIds.size()) {
|
||||
throw new ServiceException("所选分包不存在", HttpStatus.NOT_FOUND);
|
||||
}
|
||||
subContractors.forEach(contractor -> {
|
||||
if (!contractor.getProjectId().equals(projectId)) {
|
||||
throw new ServiceException(contractor.getName() + "不属于所选项目", HttpStatus.BAD_REQUEST);
|
||||
}
|
||||
});
|
||||
String oldContractors = oldMachine.getContractors();
|
||||
if (StringUtils.isNotBlank(oldContractors)) {
|
||||
List<Long> oldContractorIds = Arrays.stream(oldContractors.split(","))
|
||||
.map(Long::parseLong)
|
||||
.distinct()
|
||||
.toList();
|
||||
// 获取新增的分包ID
|
||||
List<Long> added = contractorIds.stream()
|
||||
.filter(t -> !oldContractorIds.contains(t))
|
||||
.toList();
|
||||
// 获取删除的分包ID
|
||||
List<Long> deleted = oldContractorIds.stream()
|
||||
.filter(t -> !contractorIds.contains(t))
|
||||
.toList();
|
||||
// 删除的分包不为空时,删除考勤机中对应的人数
|
||||
if (CollUtil.isNotEmpty(deleted)) {
|
||||
// 获取待删除的分包的所有用户id
|
||||
List<Long> userIds = userService.selectFbUserList(projectId, deleted, null)
|
||||
.stream().map(SysUserVo::getUserId).toList();
|
||||
if (CollUtil.isNotEmpty(userIds)) {
|
||||
String[] userIdArray = userIds.stream()
|
||||
.map(String::valueOf) // 将 Long 转成 String
|
||||
.toArray(String[]::new);
|
||||
try {
|
||||
deviceMessageSender.batchDeleteUsers(machine.getSn(), userIdArray);
|
||||
} catch (Exception e) {
|
||||
throw new ServiceException("删除考勤机用户失败", HttpStatus.ERROR);
|
||||
}
|
||||
}
|
||||
}
|
||||
// 新增的分包不为空时,添加考勤机中对应人
|
||||
if (CollUtil.isNotEmpty(added)) {
|
||||
// 获取待添加到考勤机的分包的所有用户id
|
||||
List<Long> userIds = userService.selectFbUserList(projectId, deleted, null)
|
||||
.stream().map(SysUserVo::getUserId).toList();
|
||||
// 获取待添加到考勤机的用户信息
|
||||
List<SubConstructionUser> users = constructionUserService.lambdaQuery()
|
||||
.in(SubConstructionUser::getSysUserId, userIds)
|
||||
.list();
|
||||
// 获取用户的头像
|
||||
List<Long> faceIds = users.stream().map(SubConstructionUser::getFacePic).map(Long::valueOf).distinct().toList();
|
||||
List<SysOssVo> faceList = ossService.listByIds(faceIds);
|
||||
Map<Long, String> faceMap = new HashMap<>();
|
||||
if (faceList != null) {
|
||||
faceMap = faceList.stream().collect(Collectors.toMap(SysOssVo::getOssId, SysOssVo::getUrl));
|
||||
}
|
||||
for (SubConstructionUser user : users) {
|
||||
// 添加考勤机中用户
|
||||
String facePic = user.getFacePic();
|
||||
String faceUrl = StringUtils.isNotBlank(facePic) ? faceMap.get(Long.valueOf(facePic)) : "";
|
||||
if (StringUtils.isNotBlank(faceUrl)) {
|
||||
// 添加考勤机中用户
|
||||
deviceMessageSender.sendPersonnelInformation(machine.getSn(), user.getSysUserId().toString(),
|
||||
user.getUserName(), faceUrl);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// 添加考勤机中对应人
|
||||
List<Long> userIds = userService.selectFbUserList(machine.getProjectId(), contractorIds, null)
|
||||
.stream().map(SysUserVo::getUserId)
|
||||
.toList();
|
||||
// 获取待添加到考勤机的用户信息
|
||||
List<SubConstructionUser> users = constructionUserService.lambdaQuery()
|
||||
.in(SubConstructionUser::getSysUserId, userIds)
|
||||
.list();
|
||||
if (CollUtil.isEmpty(users)) {
|
||||
throw new ServiceException("所选分包没有用户", HttpStatus.NOT_FOUND);
|
||||
}
|
||||
// 获取用户的头像
|
||||
List<Long> faceIds = users.stream().map(SubConstructionUser::getFacePic).map(Long::valueOf).distinct().toList();
|
||||
List<SysOssVo> faceList = ossService.listByIds(faceIds);
|
||||
Map<Long, String> faceMap = new HashMap<>();
|
||||
if (faceList != null) {
|
||||
faceMap = faceList.stream().collect(Collectors.toMap(SysOssVo::getOssId, SysOssVo::getUrl));
|
||||
}
|
||||
for (SubConstructionUser user : users) {
|
||||
// 添加考勤机中用户
|
||||
String facePic = user.getFacePic();
|
||||
String faceUrl = StringUtils.isNotBlank(facePic) ? faceMap.get(Long.valueOf(facePic)) : "";
|
||||
if (StringUtils.isNotBlank(faceUrl)) {
|
||||
// 添加考勤机中用户
|
||||
deviceMessageSender.sendPersonnelInformation(machine.getSn(), user.getSysUserId().toString(),
|
||||
user.getUserName(), faceUrl);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return this.updateById(machine);
|
||||
}
|
||||
@ -303,12 +485,29 @@ public class BusAttendanceMachineServiceImpl extends ServiceImpl<BusAttendanceMa
|
||||
*/
|
||||
@Override
|
||||
public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
|
||||
List<BusAttendanceMachine> machines = this.listByIds(ids);
|
||||
if (CollUtil.isEmpty(machines) || machines.size() != ids.size()) {
|
||||
throw new ServiceException("数据不存在");
|
||||
}
|
||||
if (isValid) {
|
||||
//TODO 做一些业务上的校验,判断是否需要校验
|
||||
// 删除考勤机下发的人员
|
||||
for (BusAttendanceMachine machine : machines) {
|
||||
try {
|
||||
deviceMessageSender.deleteAllUsers(machine.getSn());
|
||||
} catch (Exception e) {
|
||||
log.error("删除考勤人员异常", e);
|
||||
throw new ServiceException("删除考勤人员异常");
|
||||
}
|
||||
}
|
||||
}
|
||||
return baseMapper.deleteByIds(ids) > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 重发下发考勤机所有人员
|
||||
*
|
||||
* @param ids 待重发考勤机的主键集合
|
||||
*/
|
||||
@Async
|
||||
@Override
|
||||
public void reissue(Collection<Long> ids) {
|
||||
@ -323,28 +522,38 @@ public class BusAttendanceMachineServiceImpl extends ServiceImpl<BusAttendanceMa
|
||||
}
|
||||
|
||||
String teams = machine.getTeams();
|
||||
if (StrUtil.isBlank(teams)) {
|
||||
String contractors = machine.getContractors();
|
||||
if (StrUtil.isBlank(teams) && StrUtil.isBlank(contractors)) {
|
||||
continue;
|
||||
}
|
||||
List<Long> userIds = new ArrayList<>();
|
||||
if (StrUtil.isNotBlank(teams)) {
|
||||
List<Long> oldTeamIds = Arrays.stream(teams.split(","))
|
||||
.map(Long::parseLong)
|
||||
.distinct()
|
||||
.toList();
|
||||
|
||||
List<Long> userIds = projectTeamMemberService.lambdaQuery()
|
||||
List<Long> teamUserIds = projectTeamMemberService.lambdaQuery()
|
||||
.select(BusProjectTeamMember::getMemberId)
|
||||
.in(BusProjectTeamMember::getTeamId, oldTeamIds)
|
||||
.list()
|
||||
.stream().map(BusProjectTeamMember::getMemberId)
|
||||
.toList();
|
||||
userIds.addAll(teamUserIds);
|
||||
}
|
||||
if (StrUtil.isNotBlank(contractors)) {
|
||||
List<Long> oldContractorIds = Arrays.stream(contractors.split(","))
|
||||
.map(Long::parseLong)
|
||||
.distinct()
|
||||
.toList();
|
||||
List<SysUserVo> userVos = userService.selectFbUserList(machine.getProjectId(), oldContractorIds, null);
|
||||
userIds.addAll(userVos.stream().map(SysUserVo::getUserId).distinct().toList());
|
||||
}
|
||||
if (CollUtil.isEmpty(userIds)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
List<SubConstructionUser> users = constructionUserService.lambdaQuery()
|
||||
.in(SubConstructionUser::getSysUserId, userIds)
|
||||
.list();
|
||||
|
||||
Map<Long, String> faceMap = new HashMap<>();
|
||||
List<String> list = users.stream().map(SubConstructionUser::getFacePic).filter(StrUtil::isNotBlank).toList();
|
||||
if (CollUtil.isNotEmpty(list)) {
|
||||
|
||||
@ -28,7 +28,7 @@ import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 考勤机用户Service业务层处理
|
||||
* 班组考勤机用户Service业务层处理
|
||||
*
|
||||
* @author lilemy
|
||||
* @date 2025-10-15
|
||||
|
||||
@ -5,9 +5,6 @@ import org.dromara.common.mybatis.core.page.TableDataInfo;
|
||||
import org.dromara.project.domain.dto.attendance.SubTodayUserDto;
|
||||
import org.dromara.project.domain.dto.attendance.SubTwoWeekDto;
|
||||
import org.dromara.project.domain.dto.attendance.SubUserAttendanceQueryReq;
|
||||
import org.dromara.project.domain.dto.attendance.TodayUserDto;
|
||||
import org.dromara.project.domain.vo.attendance.AttendanceTodayUserVo;
|
||||
import org.dromara.project.domain.vo.attendance.SubUserAttendanceTotalVo;
|
||||
import org.dromara.system.domain.SysUser;
|
||||
import org.dromara.system.domain.bo.SysUserBo;
|
||||
import org.dromara.system.domain.dto.AppUserUpdatePasswordDto;
|
||||
@ -15,7 +12,6 @@ import org.dromara.system.domain.dto.FbUserListDto;
|
||||
import org.dromara.system.domain.dto.role.SysRoleProjectDto;
|
||||
import org.dromara.system.domain.vo.SysUserExportVo;
|
||||
import org.dromara.system.domain.vo.SysUserVo;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@ -32,6 +28,16 @@ public interface ISysUserService {
|
||||
|
||||
TableDataInfo<SysUserVo> selectPageFbUserList(FbUserListDto user, PageQuery pageQuery);
|
||||
|
||||
/**
|
||||
* 获取分包用户列表
|
||||
*
|
||||
* @param projectId 项目id
|
||||
* @param contractorIds 分包id列表
|
||||
* @param nickName 用户昵称
|
||||
* @return 分包用户列表
|
||||
*/
|
||||
List<SysUserVo> selectFbUserList(Long projectId, List<Long> contractorIds, String nickName);
|
||||
|
||||
/**
|
||||
* 根据条件分页查询用户列表
|
||||
*
|
||||
@ -260,6 +266,7 @@ public interface ISysUserService {
|
||||
|
||||
/**
|
||||
* 根据部门 ID 获取用户 ID -> 名称 映射
|
||||
*
|
||||
* @param deptId
|
||||
* @return
|
||||
*/
|
||||
|
||||
@ -16,7 +16,6 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import jakarta.annotation.Resource;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.aspectj.apache.bcel.generic.RET;
|
||||
import org.dromara.common.core.constant.CacheNames;
|
||||
import org.dromara.common.core.constant.SystemConstants;
|
||||
import org.dromara.common.core.domain.dto.UserDTO;
|
||||
@ -43,8 +42,6 @@ import org.dromara.project.domain.BusUserProjectRelevancy;
|
||||
import org.dromara.project.domain.dto.attendance.SubTodayUserDto;
|
||||
import org.dromara.project.domain.dto.attendance.SubTwoWeekDto;
|
||||
import org.dromara.project.domain.dto.attendance.SubUserAttendanceQueryReq;
|
||||
import org.dromara.project.domain.dto.attendance.TodayUserDto;
|
||||
import org.dromara.project.domain.vo.attendance.SubUserAttendanceTotalVo;
|
||||
import org.dromara.project.domain.vo.projectteam.BusProjectTeamAppVo;
|
||||
import org.dromara.project.service.IBusProjectTeamService;
|
||||
import org.dromara.project.service.IBusUserProjectRelevancyService;
|
||||
@ -58,14 +55,12 @@ import org.dromara.system.domain.vo.SysRoleVo;
|
||||
import org.dromara.system.domain.vo.SysUserExportVo;
|
||||
import org.dromara.system.domain.vo.SysUserVo;
|
||||
import org.dromara.system.mapper.*;
|
||||
import org.dromara.system.service.ISysOssService;
|
||||
import org.dromara.system.service.ISysRoleService;
|
||||
import org.dromara.system.service.ISysUserFileService;
|
||||
import org.dromara.system.service.ISysUserService;
|
||||
import org.springframework.cache.annotation.CacheEvict;
|
||||
import org.springframework.cache.annotation.Cacheable;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
@ -188,6 +183,26 @@ public class SysUserServiceImpl implements ISysUserService, UserService {
|
||||
return TableDataInfo.build(page);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取分包用户列表
|
||||
*
|
||||
* @param projectId 项目id
|
||||
* @param contractorIds 分包id列表
|
||||
* @param nickName 用户昵称
|
||||
* @return 分包用户列表
|
||||
*/
|
||||
@Override
|
||||
public List<SysUserVo> selectFbUserList(Long projectId, List<Long> contractorIds, String nickName) {
|
||||
LambdaQueryWrapper<SysUser> lqw = new LambdaQueryWrapper<>();
|
||||
lqw.eq(SysUser::getAppUserType, "2");
|
||||
lqw.exists(projectId != null, "SELECT 1 FROM bus_user_project_relevancy " +
|
||||
"WHERE bus_user_project_relevancy.user_id = u.user_id " +
|
||||
"AND project_id = {0}", projectId);
|
||||
lqw.in(CollUtil.isNotEmpty(contractorIds), SysUser::getContractorId, contractorIds);
|
||||
lqw.like(StringUtils.isNotBlank(nickName), SysUser::getNickName, nickName);
|
||||
return baseMapper.selectUserList(lqw);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据条件分页查询用户列表
|
||||
*
|
||||
|
||||
Reference in New Issue
Block a user