From afa1689cb6661f2a243d9820523a488ed1a798b7 Mon Sep 17 00:00:00 2001 From: furongxin <419481438@qq.com> Date: Wed, 5 Jun 2024 09:28:30 +0800 Subject: [PATCH] =?UTF-8?q?=E8=80=83=E5=8B=A4=E8=AE=BE=E5=A4=87=E6=A8=A1?= =?UTF-8?q?=E5=9D=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../yudao-module-system-biz/pom.xml | 5 ++ .../equipment/AttendanceMachineApiImpl.java | 42 +++++++++- .../AttendanceMachineController.java | 77 ++++++++++++++++++- .../admin/equipment/UsersExtController.java | 34 ++++++-- .../AddUserToAttendanceMachineVO.java | 11 ++- .../AttendanceMachinePasswordVO.java | 6 +- .../AttendanceMachineRespVO.java | 2 +- .../vo/userExt/UsersExtPageReqVO.java | 9 +++ .../equipment/vo/userExt/UsersExtRespVO.java | 9 ++- .../vo/websocket/UpdateFaceImgVO.java | 21 +++++ .../vo/websocket/UpdatePasswordVO.java | 18 +++++ .../vo/websocket/WebsocketBaseVO.java | 21 +++++ .../equipment/AttendanceMachineConvert.java | 39 ++++++++++ .../convert/equipment/UsersExtConvert.java | 25 ++++-- .../equipment/DistributeRecordDO.java | 10 ++- .../dal/dataobject/equipment/UsersExtDO.java | 3 +- .../equipment/AttendanceMachineMapper.java | 1 - .../equipment/DistributeRecordMapper.java | 5 ++ .../job/equipment/AttendanceMachineJob.java | 50 ++++++++++++ .../equipment/AttendanceMachineService.java | 8 +- .../AttendanceMachineServiceImpl.java | 49 ++++++++---- .../equipment/DistributeRecordService.java | 17 ++-- .../DistributeRecordServiceImpl.java | 25 ++++-- .../service/equipment/UsersExtService.java | 9 ++- .../equipment/UsersExtServiceImpl.java | 67 ++++++++++++++-- .../src/main/resources/application.yaml | 13 ++++ .../equipment/AttendanceMachineMapper.xml | 30 +++++--- .../equipment/DistributeRecordMapper.xml | 41 ++++++++++ .../mapper/equipment/UsersExtMapper.xml | 7 +- 29 files changed, 574 insertions(+), 80 deletions(-) create mode 100644 yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/equipment/vo/websocket/UpdateFaceImgVO.java create mode 100644 yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/equipment/vo/websocket/UpdatePasswordVO.java create mode 100644 yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/equipment/vo/websocket/WebsocketBaseVO.java create mode 100644 yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/convert/equipment/AttendanceMachineConvert.java create mode 100644 yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/job/equipment/AttendanceMachineJob.java create mode 100644 yudao-module-system/yudao-module-system-biz/src/main/resources/mapper/equipment/DistributeRecordMapper.xml diff --git a/yudao-module-system/yudao-module-system-biz/pom.xml b/yudao-module-system/yudao-module-system-biz/pom.xml index d1cd7990..ffe9265f 100644 --- a/yudao-module-system/yudao-module-system-biz/pom.xml +++ b/yudao-module-system/yudao-module-system-biz/pom.xml @@ -81,6 +81,11 @@ yudao-spring-boot-starter-security + + cn.iocoder.cloud + yudao-spring-boot-starter-websocket + + cn.iocoder.cloud diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/equipment/AttendanceMachineApiImpl.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/equipment/AttendanceMachineApiImpl.java index 3c20a921..b8c67897 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/equipment/AttendanceMachineApiImpl.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/equipment/AttendanceMachineApiImpl.java @@ -1,10 +1,18 @@ package cn.iocoder.yudao.module.system.api.equipment; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.system.api.equipment.dto.AttendanceUpdateDTO; +import cn.iocoder.yudao.module.system.api.equipment.dto.DistributeRecordDTO; +import cn.iocoder.yudao.module.system.controller.admin.equipment.vo.attendancemachine.AddUserToAttendanceMachineVO; +import cn.iocoder.yudao.module.system.controller.admin.equipment.vo.attendancemachine.AttendanceMachinePasswordVO; +import cn.iocoder.yudao.module.system.dal.dataobject.equipment.DistributeRecordDO; import cn.iocoder.yudao.module.system.service.equipment.AttendanceMachineService; +import cn.iocoder.yudao.module.system.service.equipment.DistributeRecordService; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.RestController; import javax.annotation.Resource; +import java.util.List; @RestController // 提供 RESTful API 接口,给 Feign 调用 @Validated @@ -13,9 +21,37 @@ public class AttendanceMachineApiImpl implements AttendanceMachineApi{ @Resource private AttendanceMachineService attendanceMachineService; - @Override - public void updateAttendanceMachineStatus(String deviceNo) { + @Resource + private DistributeRecordService distributeRecordService; - attendanceMachineService.updateAttendanceMachineStatus(deviceNo); + @Override + public void createDistributeRecord(List recordDTO) { + + List distributeRecordDO = BeanUtils.toBean(recordDTO, DistributeRecordDO.class); + + distributeRecordService.createDistributeRecord(distributeRecordDO); + } + + @Override + public void updateDistributeRecord(List recordDTO) { + + distributeRecordService.updateDistributeRecord(BeanUtils.toBean(recordDTO, DistributeRecordDO.class)); + } + + @Override + public void updateAttendance(AttendanceUpdateDTO updateDTO) { + + AddUserToAttendanceMachineVO updateVO = BeanUtils.toBean(updateDTO, AddUserToAttendanceMachineVO.class); + attendanceMachineService.addUserToAttendanceMachine(updateVO); + } + + @Override + public void updateDevicePassword(String deviceNo, String oldPassword, String newPassword) { + + AttendanceMachinePasswordVO passwordVO = new AttendanceMachinePasswordVO(); + passwordVO.setDeviceNo(deviceNo); + passwordVO.setOldPassword(oldPassword); + passwordVO.setNewPassword(newPassword); + attendanceMachineService.updatePassword(passwordVO); } } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/equipment/AttendanceMachineController.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/equipment/AttendanceMachineController.java index 4bb7ab2a..d46487a5 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/equipment/AttendanceMachineController.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/equipment/AttendanceMachineController.java @@ -2,20 +2,34 @@ package cn.iocoder.yudao.module.system.controller.admin.equipment; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.json.JsonUtils; +import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder; +import cn.iocoder.yudao.module.infra.api.websocket.WebSocketSenderApi; import cn.iocoder.yudao.module.system.controller.admin.equipment.vo.attendancemachine.*; import cn.iocoder.yudao.module.system.controller.admin.equipment.vo.userExt.UsersExtRespVO; +import cn.iocoder.yudao.module.system.controller.admin.equipment.vo.websocket.UpdatePasswordVO; +import cn.iocoder.yudao.module.system.controller.admin.equipment.vo.websocket.WebsocketBaseVO; +import cn.iocoder.yudao.module.system.dal.dataobject.equipment.DistributeRecordDO; import cn.iocoder.yudao.module.system.service.equipment.AttendanceMachineService; +import cn.iocoder.yudao.module.system.service.equipment.DistributeRecordService; +import com.baomidou.mybatisplus.core.toolkit.IdWorker; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.tags.Tag; +import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; import javax.annotation.Resource; import javax.validation.Valid; +import java.util.Collections; +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.error; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; +import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.REQUEST_FAILURE; @Tag(name = "管理后台 - 考勤设备") @@ -27,6 +41,15 @@ public class AttendanceMachineController { @Resource private AttendanceMachineService attendanceMachineService; + @Resource + private StringRedisTemplate stringRedisTemplate; + + @Resource + private WebSocketSenderApi webSocketSenderApi; + + @Resource + private DistributeRecordService recordService; + @PostMapping("/create") @Operation(summary = "创建考勤设备") @PreAuthorize("@ss.hasPermission('system:attendance-machine:create')") @@ -48,8 +71,58 @@ public class AttendanceMachineController { @PreAuthorize("@ss.hasPermission('system:attendance-machine:update')") public CommonResult updateAttendanceMachine(@Valid @RequestBody AttendanceMachinePasswordVO updateReqVO) { - attendanceMachineService.updatePassword(updateReqVO); - return success(true); + // 将密码信息 储存在redis中 + stringRedisTemplate.opsForValue().set(updateReqVO.getDeviceNo(), updateReqVO.getOldPassword() + "-" + updateReqVO.getNewPassword()); + + String requestId = IdWorker.get32UUID(); + // 设备修改密码命令信息 + UpdatePasswordVO passwordVO = new UpdatePasswordVO().setOld_password(updateReqVO.getOldPassword()) + .setNew_password(updateReqVO.getNewPassword()); + WebsocketBaseVO data = new WebsocketBaseVO() + .setFrom("") + .setTo(updateReqVO.getDeviceNo()) + .setExtra(requestId + "_" + getLoginUserId()) + .setData(passwordVO); + + // 设置 设备下发记录 + DistributeRecordDO recordDO = new DistributeRecordDO(); + recordDO.setRequestId(requestId); + recordDO.setDeviceNo(updateReqVO.getDeviceNo()); + recordDO.setUserId(getLoginUserId()); + recordDO.setType(3); + recordDO.setResult("通讯失败"); + + // 更新下发记录信息 + recordService.createDistributeRecord(Collections.singletonList(recordDO)); + + // 设备租户ID + TenantContextHolder.setTenantId(1L); + // 发送修改密码命令给设备 + webSocketSenderApi.sendSN(updateReqVO.getDeviceNo(), "attendance-message-send", JsonUtils.toJsonString(data)); + + Long startTime = System.currentTimeMillis(); + while (true) { + + if (stringRedisTemplate.opsForValue().get(updateReqVO.getDeviceNo()) == null) { + + return success(true); + }else if ("false".equals(stringRedisTemplate.opsForValue().get(updateReqVO.getDeviceNo()))) { + + Integer code = Integer.valueOf(stringRedisTemplate.opsForValue().get(updateReqVO.getDeviceNo() + "msg").split("_")[0]); + String msg = stringRedisTemplate.opsForValue().get(updateReqVO.getDeviceNo() + "msg").split("_")[1]; + + // 清楚 redis缓存 + stringRedisTemplate.delete(updateReqVO.getDeviceNo()); + stringRedisTemplate.delete(updateReqVO.getDeviceNo() + "msg"); + return error(code, msg); + } + + Long currentTime = System.currentTimeMillis(); + if (currentTime - startTime > 3000) { + + throw exception(REQUEST_FAILURE); + } + } } @PutMapping("/update-user") diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/equipment/UsersExtController.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/equipment/UsersExtController.java index ffaeb2fb..92aa46cd 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/equipment/UsersExtController.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/equipment/UsersExtController.java @@ -4,7 +4,6 @@ import cn.hutool.core.collection.CollUtil; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageParam; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; @@ -14,12 +13,15 @@ import cn.iocoder.yudao.module.system.controller.admin.equipment.vo.userExt.User import cn.iocoder.yudao.module.system.controller.admin.equipment.vo.userExt.UsersExtRespVO; import cn.iocoder.yudao.module.system.controller.admin.equipment.vo.userExt.UsersExtSaveReqVO; import cn.iocoder.yudao.module.system.controller.admin.user.vo.user.UserImportRespVO; +import cn.iocoder.yudao.module.system.convert.equipment.AttendanceMachineConvert; import cn.iocoder.yudao.module.system.convert.equipment.UsersExtConvert; import cn.iocoder.yudao.module.system.dal.dataobject.dept.DeptDO; import cn.iocoder.yudao.module.system.dal.dataobject.equipment.AttendanceMachineDO; +import cn.iocoder.yudao.module.system.dal.dataobject.equipment.DistributeRecordDO; import cn.iocoder.yudao.module.system.dal.dataobject.equipment.UsersExtDO; import cn.iocoder.yudao.module.system.service.dept.DeptService; import cn.iocoder.yudao.module.system.service.equipment.AttendanceMachineService; +import cn.iocoder.yudao.module.system.service.equipment.DistributeRecordService; import cn.iocoder.yudao.module.system.service.equipment.UsersExtService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; @@ -39,11 +41,15 @@ import javax.annotation.Resource; import javax.servlet.http.HttpServletResponse; import javax.validation.Valid; import java.io.IOException; +import java.util.Arrays; +import java.util.HashSet; import java.util.List; import java.util.Map; +import java.util.stream.Collectors; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT; import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; @@ -62,6 +68,9 @@ public class UsersExtController { @Resource private AttendanceMachineService attendanceMachineService; + @Resource + private DistributeRecordService recordService; + @RequestMapping(value = "/create", method = {RequestMethod.POST, RequestMethod.PUT}) // 解决 uni-app 不支持 Put 上传文件的问题) @Operation(summary = "上传照片") @@ -102,9 +111,7 @@ public class UsersExtController { // 获得部门信息Map Map deptDOMap = deptService.getDeptMap(convertList(attendanceMachineDO, AttendanceMachineDO::getDeptId)); - List respVOS = BeanUtils.toBean(attendanceMachineDO, AttendanceMachineRespVO.class); - - return success(CollectionUtils.convertList(respVOS, respVO -> respVO.setDeptName(deptDOMap.get(respVO.getDeptId()).getName()))); + return success(AttendanceMachineConvert.INSTANCE.convertList(attendanceMachineDO, deptDOMap)); } @GetMapping("/page") @@ -119,8 +126,23 @@ public class UsersExtController { //获得部门Map Map deptMap = deptService.getDeptMap(convertList(pageResult.getList(), UsersExtRespVO::getDeptId)); - return success(new PageResult<>(UsersExtConvert.INSTANCE.convertList(pageResult.getList(), deptMap) - , pageResult.getTotal())); + // 获得 下发或修改状态信息 + List type = Arrays.asList(1,2); + List recordDOs = recordService.getDistributeRecord(convertList(pageResult.getList(), UsersExtRespVO::getUserId), type); + Map recordDOMap = convertMap(recordDOs, DistributeRecordDO::getUserId); + + List respVOS = UsersExtConvert.INSTANCE.convertList(pageResult.getList(), deptMap, recordDOMap); + + // 判断是否已下发 + if (pageReqVO.getIsIssued() != null && pageReqVO.getIsIssued() == 0) { + + respVOS = respVOS.stream().filter(data -> data.getDevices() == null || !new HashSet<>(data.getDevices()).containsAll(pageReqVO.getDeviceNos())).collect(Collectors.toList()); + }else if (pageReqVO.getIsIssued() != null && pageReqVO.getIsIssued() == 1) { + + respVOS = respVOS.stream().filter(data -> data.getDevices() != null && new HashSet<>(data.getDevices()).containsAll(pageReqVO.getDeviceNos())).collect(Collectors.toList()); + } + + return success(new PageResult<>(respVOS, pageResult.getTotal())); } return success(BeanUtils.toBean(pageResult, UsersExtRespVO.class)); diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/equipment/vo/attendancemachine/AddUserToAttendanceMachineVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/equipment/vo/attendancemachine/AddUserToAttendanceMachineVO.java index 98d563f5..8eb3ca89 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/equipment/vo/attendancemachine/AddUserToAttendanceMachineVO.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/equipment/vo/attendancemachine/AddUserToAttendanceMachineVO.java @@ -1,6 +1,5 @@ package cn.iocoder.yudao.module.system.controller.admin.equipment.vo.attendancemachine; -import cn.iocoder.yudao.module.system.controller.admin.equipment.vo.userExt.UsersExtRespVO; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; @@ -11,13 +10,13 @@ import java.util.List; @Data public class AddUserToAttendanceMachineVO { - @Schema(description = "下发用户列表") - @NotNull(message = "下发用户不能为空") - private List userInfo; + @Schema(description = "下发用户编号", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "下发用户编号不能为空") + private List userId; - @Schema(description = "设备号列表", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "设备号", requiredMode = Schema.RequiredMode.REQUIRED) @NotNull(message = "设备号不能为空") - private List deviceNos; + private String deviceNo; @Schema(description = "下发或删除 | 0下发, 1删除") private Integer method; diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/equipment/vo/attendancemachine/AttendanceMachinePasswordVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/equipment/vo/attendancemachine/AttendanceMachinePasswordVO.java index c07e67be..f1192d1a 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/equipment/vo/attendancemachine/AttendanceMachinePasswordVO.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/equipment/vo/attendancemachine/AttendanceMachinePasswordVO.java @@ -11,9 +11,9 @@ import javax.validation.constraints.NotNull; @Data public class AttendanceMachinePasswordVO { - @Schema(description = "设备ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") - @NotNull(message = "设备ID不能为空") - private Long id; + @Schema(description = "设备号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "设备号不能为空") + private String deviceNo; @Schema(description = "旧密码", requiredMode = Schema.RequiredMode.REQUIRED, example = "123456") @NotEmpty(message = "旧密码不能为空") diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/equipment/vo/attendancemachine/AttendanceMachineRespVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/equipment/vo/attendancemachine/AttendanceMachineRespVO.java index 5dc8862d..6fef49ee 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/equipment/vo/attendancemachine/AttendanceMachineRespVO.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/equipment/vo/attendancemachine/AttendanceMachineRespVO.java @@ -36,6 +36,6 @@ public class AttendanceMachineRespVO { @ExcelProperty("设备名称") private String deviceName; - @Schema(description = "是否在线 | 0否 1是") + @Schema(description = "是否在线 | 0离线 1在线") private Integer isOnLine; } \ No newline at end of file diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/equipment/vo/userExt/UsersExtPageReqVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/equipment/vo/userExt/UsersExtPageReqVO.java index 8314c747..54757093 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/equipment/vo/userExt/UsersExtPageReqVO.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/equipment/vo/userExt/UsersExtPageReqVO.java @@ -30,6 +30,15 @@ public class UsersExtPageReqVO extends PageParam { @Schema(description = "是否录入人脸 | 0:未录入 1:已录入") private Integer isEnter; + @Schema(description = "用户类型") + private Integer userType; + + @Schema(description = "是否下发 | 0否 1是") + private Integer isIssued; + + @Schema(description = "设备号集合") + private List deviceNos; + @Schema(description = "创建时间") @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) private LocalDateTime[] createTime; diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/equipment/vo/userExt/UsersExtRespVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/equipment/vo/userExt/UsersExtRespVO.java index 95c4faa5..07e595b0 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/equipment/vo/userExt/UsersExtRespVO.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/equipment/vo/userExt/UsersExtRespVO.java @@ -1,6 +1,5 @@ package cn.iocoder.yudao.module.system.controller.admin.equipment.vo.userExt; -import cn.iocoder.yudao.module.system.controller.admin.worklog.vo.upload.UploadUserFile; import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; import com.alibaba.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; @@ -36,8 +35,14 @@ public class UsersExtRespVO { @ExcelProperty("人脸图片") private String faceImg; + @Schema(description = "绑定的考勤机设备号") + private String attendanceMachineNos; + @Schema(description = "绑定的考勤机设备号集合") - private List attendanceMachineNos; + private List devices; + + @Schema(description = "下发结果") + private String result; @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) private LocalDateTime createTime; diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/equipment/vo/websocket/UpdateFaceImgVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/equipment/vo/websocket/UpdateFaceImgVO.java new file mode 100644 index 00000000..e95600b3 --- /dev/null +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/equipment/vo/websocket/UpdateFaceImgVO.java @@ -0,0 +1,21 @@ +package cn.iocoder.yudao.module.system.controller.admin.equipment.vo.websocket; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +@Schema(description = "修改人看图片命令 VO") +@Data +public class UpdateFaceImgVO { + + @Schema(description = "指令") + private String cmd = "editUser"; + + @Schema(description = "用户id") + private String user_id; + + @Schema(description = "修改类型") + private Integer edit_mode = 1; + + @Schema(description = "人脸图片url") + private String face_template; +} diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/equipment/vo/websocket/UpdatePasswordVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/equipment/vo/websocket/UpdatePasswordVO.java new file mode 100644 index 00000000..40732b2f --- /dev/null +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/equipment/vo/websocket/UpdatePasswordVO.java @@ -0,0 +1,18 @@ +package cn.iocoder.yudao.module.system.controller.admin.equipment.vo.websocket; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +@Schema(description = "修改设备密码 VO") +@Data +public class UpdatePasswordVO { + + @Schema(description = "指令号,此处固定为 setPassword") + private String cmd = "setPassword"; + + @Schema(description = "设备当前密码") + private String old_password; + + @Schema(description = "新密码") + private String new_password; +} diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/equipment/vo/websocket/WebsocketBaseVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/equipment/vo/websocket/WebsocketBaseVO.java new file mode 100644 index 00000000..71d518d2 --- /dev/null +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/equipment/vo/websocket/WebsocketBaseVO.java @@ -0,0 +1,21 @@ +package cn.iocoder.yudao.module.system.controller.admin.equipment.vo.websocket; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +@Data +public class WebsocketBaseVO { + + @Schema(description = "固定为 to_device") + private String cmd = "to_device"; + + private String from; + + private String extra; + + @Schema(description = "目标设备号", requiredMode = Schema.RequiredMode.REQUIRED) + private String to; + + @Schema(description = "具体指令中的数据格式") + private Object data; +} diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/convert/equipment/AttendanceMachineConvert.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/convert/equipment/AttendanceMachineConvert.java new file mode 100644 index 00000000..e91b70e8 --- /dev/null +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/convert/equipment/AttendanceMachineConvert.java @@ -0,0 +1,39 @@ +package cn.iocoder.yudao.module.system.convert.equipment; + +import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.system.controller.admin.equipment.vo.attendancemachine.AttendanceMachineRespVO; +import cn.iocoder.yudao.module.system.dal.dataobject.dept.DeptDO; +import cn.iocoder.yudao.module.system.dal.dataobject.equipment.AttendanceMachineDO; +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + +import java.util.List; +import java.util.Map; + +@Mapper +public interface AttendanceMachineConvert { + + AttendanceMachineConvert INSTANCE = Mappers.getMapper(AttendanceMachineConvert.class); + + default List convertList(List list, Map deptMap) { + + return CollectionUtils.convertList(list, data -> convert(data, deptMap.get(data.getDeptId()))); + } + + default AttendanceMachineRespVO convert(AttendanceMachineDO attendanceMachineDO, DeptDO deptDO) { + + AttendanceMachineRespVO respVO = new AttendanceMachineRespVO(); + if (attendanceMachineDO != null) { + + respVO = BeanUtils.toBean(attendanceMachineDO, AttendanceMachineRespVO.class); + respVO.setIsOnLine(attendanceMachineDO.getStatus()); + + if (deptDO != null) { + respVO.setDeptName(deptDO.getName()); + } + } + + return respVO; + } +} diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/convert/equipment/UsersExtConvert.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/convert/equipment/UsersExtConvert.java index 267fedb1..0824974f 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/convert/equipment/UsersExtConvert.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/convert/equipment/UsersExtConvert.java @@ -1,12 +1,13 @@ package cn.iocoder.yudao.module.system.convert.equipment; import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; +import cn.iocoder.yudao.framework.common.util.json.JsonUtils; import cn.iocoder.yudao.module.system.controller.admin.equipment.vo.userExt.UsersExtRespVO; import cn.iocoder.yudao.module.system.dal.dataobject.dept.DeptDO; +import cn.iocoder.yudao.module.system.dal.dataobject.equipment.DistributeRecordDO; import org.mapstruct.Mapper; import org.mapstruct.factory.Mappers; -import java.time.LocalDateTime; import java.util.List; import java.util.Map; @@ -15,18 +16,32 @@ public interface UsersExtConvert { UsersExtConvert INSTANCE = Mappers.getMapper(UsersExtConvert.class); - default List convertList(List list, Map deptMap) { + default List convertList(List list, Map deptMap, Map recordDOMap) { - return CollectionUtils.convertList(list, user -> convert(user, deptMap.get(user.getDeptId()))); + return CollectionUtils.convertList(list, user -> convert(user, deptMap.get(user.getDeptId()), recordDOMap.get(user.getUserId()))); } - default UsersExtRespVO convert(UsersExtRespVO usersExtDO, DeptDO dept) { + default UsersExtRespVO convert(UsersExtRespVO usersExtDO, DeptDO dept, DistributeRecordDO recordDO) { if (dept != null) { usersExtDO.setDeptName(dept.getName()); } - usersExtDO.setFaceImg(usersExtDO.getFaceImg() + "?time=" + LocalDateTime.now().getSecond()); + if (usersExtDO.getFaceImg() != null) { + + usersExtDO.setFaceImg(usersExtDO.getFaceImg() + "?time=" + System.currentTimeMillis()); + } + + if (usersExtDO.getAttendanceMachineNos() != null) { + + usersExtDO.setDevices(JsonUtils.parseArray(usersExtDO.getAttendanceMachineNos(), String.class)); + } + + if (recordDO != null) { + + usersExtDO.setResult(recordDO.getResult()); + usersExtDO.setCreateTime(recordDO.getCreateTime()); + } return usersExtDO; } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/equipment/DistributeRecordDO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/equipment/DistributeRecordDO.java index 4ce4c96a..4533c953 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/equipment/DistributeRecordDO.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/equipment/DistributeRecordDO.java @@ -24,6 +24,10 @@ public class DistributeRecordDO extends BaseDO { */ @TableId private Long id; + /** + * 记录编号 + */ + private String requestId; /** * 设备编号 */ @@ -34,9 +38,13 @@ public class DistributeRecordDO extends BaseDO { private Long userId; /** * 记录类型 - * 0删除 1下发 + * 0删除 1下发 2修改 */ private Integer type; + /** + * 错误码 + */ + private Integer code; /** * 下发结果 */ diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/equipment/UsersExtDO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/equipment/UsersExtDO.java index 0a6ee4c0..ed40b5f8 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/equipment/UsersExtDO.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/equipment/UsersExtDO.java @@ -1,7 +1,6 @@ package cn.iocoder.yudao.module.system.dal.dataobject.equipment; import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; -import cn.iocoder.yudao.module.system.controller.admin.worklog.vo.upload.UploadUserFile; import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; @@ -15,7 +14,7 @@ import java.util.List; * * @author 符溶馨 */ -@TableName("system_users_ext") +@TableName(value = "system_users_ext", autoResultMap = true) @Data @EqualsAndHashCode(callSuper = true) @ToString(callSuper = true) diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/equipment/AttendanceMachineMapper.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/equipment/AttendanceMachineMapper.java index 76472185..0a50b6b5 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/equipment/AttendanceMachineMapper.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/equipment/AttendanceMachineMapper.java @@ -20,7 +20,6 @@ public interface AttendanceMachineMapper extends BaseMapperX selectAttendancePage(@Param("page") IPage mpPage, @Param("reqVO") AttendanceMachinePageReqVO pageReqVO); -// @Param("deviceNos")List deviceNos); AttendanceMachineRespVO selectAttendanceByAssetsNo(@Param("assetsNo") String assetsNo); diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/equipment/DistributeRecordMapper.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/equipment/DistributeRecordMapper.java index 9bae8a19..a87da948 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/equipment/DistributeRecordMapper.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/equipment/DistributeRecordMapper.java @@ -3,6 +3,10 @@ package cn.iocoder.yudao.module.system.dal.mysql.equipment; import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; import cn.iocoder.yudao.module.system.dal.dataobject.equipment.DistributeRecordDO; import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.Collection; +import java.util.List; /** * 考勤机下发记录 Mapper @@ -12,4 +16,5 @@ import org.apache.ibatis.annotations.Mapper; @Mapper public interface DistributeRecordMapper extends BaseMapperX { + List selectListByUserIdAndType(@Param("userId") List userId, @Param("type") Collection type); } \ No newline at end of file diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/job/equipment/AttendanceMachineJob.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/job/equipment/AttendanceMachineJob.java new file mode 100644 index 00000000..470824dd --- /dev/null +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/job/equipment/AttendanceMachineJob.java @@ -0,0 +1,50 @@ +package cn.iocoder.yudao.module.system.job.equipment; + +import cn.iocoder.yudao.framework.tenant.core.job.TenantJob; +import cn.iocoder.yudao.framework.websocket.core.session.WebSocketSessionManager; +import cn.iocoder.yudao.module.system.dal.dataobject.equipment.AttendanceMachineDO; +import cn.iocoder.yudao.module.system.service.equipment.AttendanceMachineService; +import com.github.yulichang.toolkit.SpringContentUtils; +import lombok.extern.slf4j.Slf4j; +import org.springframework.data.redis.core.StringRedisTemplate; +import org.springframework.scheduling.annotation.EnableScheduling; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Component; + +import javax.annotation.Resource; +import java.util.List; + +@Component +@Slf4j +@EnableScheduling +public class AttendanceMachineJob { + + @Resource + private AttendanceMachineService attendanceMachineService; + + @Resource + private StringRedisTemplate stringRedisTemplate; + + @Scheduled(initialDelay = 5000, fixedRate = 30000) + @TenantJob + public void updateAttendanceMachineStatus() { + + // 获得所有在线的设备 + List attendanceMachineDOS = attendanceMachineService.getListByStatus(); + for (AttendanceMachineDO reqDO : attendanceMachineDOS) { + + // redis数据不存在,则为离线状态 + if (stringRedisTemplate.opsForValue().get(reqDO.getDeviceNo()) == null) { + + attendanceMachineService.updateAttendanceMachineStatus(reqDO.getDeviceNo(), 0, null); + + //同步 删除对应sessionId + WebSocketSessionManager webSocketSessionManager = SpringContentUtils.getBean(WebSocketSessionManager.class); + webSocketSessionManager.removeSession(webSocketSessionManager.getSessionByDeviceNum(reqDO.getDeviceNo())); + }else { + + attendanceMachineService.updateAttendanceMachineStatus(reqDO.getDeviceNo(), 1, stringRedisTemplate.opsForValue().get(reqDO.getDeviceNo())); + } + } + } +} diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/equipment/AttendanceMachineService.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/equipment/AttendanceMachineService.java index 79b9e318..967ad233 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/equipment/AttendanceMachineService.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/equipment/AttendanceMachineService.java @@ -34,7 +34,7 @@ public interface AttendanceMachineService { * 更新考勤设备 状态 * @param deviceNo 设备号 */ - void updateAttendanceMachineStatus(String deviceNo); + void updateAttendanceMachineStatus(String deviceNo, Integer status, String dateTime); /** * 考勤设备密码修改 @@ -78,4 +78,10 @@ public interface AttendanceMachineService { * @param addReqVO 下发信息 */ void addUserToAttendanceMachine(AddUserToAttendanceMachineVO addReqVO); + + /** + * 获得所有在线的设备 + * @return 设备列表 + */ + List getListByStatus(); } \ No newline at end of file diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/equipment/AttendanceMachineServiceImpl.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/equipment/AttendanceMachineServiceImpl.java index d804f7d5..3a50f832 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/equipment/AttendanceMachineServiceImpl.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/equipment/AttendanceMachineServiceImpl.java @@ -10,7 +10,7 @@ import cn.iocoder.yudao.module.system.controller.admin.equipment.vo.userExt.User import cn.iocoder.yudao.module.system.dal.dataobject.assets.AssetsTypeDO; import cn.iocoder.yudao.module.system.dal.dataobject.dept.DeptDO; import cn.iocoder.yudao.module.system.dal.dataobject.equipment.AttendanceMachineDO; -import cn.iocoder.yudao.module.system.dal.dataobject.equipment.DistributeRecordDO; +import cn.iocoder.yudao.module.system.dal.dataobject.equipment.UsersExtDO; import cn.iocoder.yudao.module.system.dal.mysql.equipment.AttendanceMachineMapper; import cn.iocoder.yudao.module.system.service.assets.AssetsTypeService; import cn.iocoder.yudao.module.system.service.assets.DeptAssetsInOutStockService; @@ -24,14 +24,15 @@ import org.springframework.validation.annotation.Validated; import javax.annotation.Resource; import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Map; -import java.util.stream.Collectors; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; +import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.ATTENDANCE_MACHINE_NOT_EXISTS; import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.ATTENDANCE_PASSWORD_NOT_EQUAL; @@ -110,9 +111,15 @@ public class AttendanceMachineServiceImpl implements AttendanceMachineService { } @Override - public void updateAttendanceMachineStatus(String deviceNo) { + public void updateAttendanceMachineStatus(String deviceNo, Integer status, String dateTime) { - attendanceMachineMapper.update(new AttendanceMachineDO().setStatus(1).setRequestTime(LocalDateTime.now()), + AttendanceMachineDO updateDO = new AttendanceMachineDO(); + updateDO.setStatus(status); + updateDO.setUpdater(getLoginUserId().toString()); + if (status == 1) { + updateDO.setRequestTime(LocalDateTime.parse(dateTime, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))); + } + attendanceMachineMapper.update(updateDO, new LambdaUpdateWrapper().eq(AttendanceMachineDO::getDeviceNo, deviceNo)); } @@ -120,7 +127,7 @@ public class AttendanceMachineServiceImpl implements AttendanceMachineService { public void updatePassword(AttendanceMachinePasswordVO updateReqVO) { //校验 旧密码 - AttendanceMachineDO attendanceMachineDO = attendanceMachineMapper.selectById(updateReqVO.getId()); + AttendanceMachineDO attendanceMachineDO = attendanceMachineMapper.selectOne(AttendanceMachineDO::getDeviceNo, updateReqVO.getDeviceNo()); if (attendanceMachineDO == null) { throw exception(ATTENDANCE_MACHINE_NOT_EXISTS); @@ -134,10 +141,9 @@ public class AttendanceMachineServiceImpl implements AttendanceMachineService { //更新 attendanceMachineDO = new AttendanceMachineDO() - .setId(updateReqVO.getId()) .setPassword(passwordEncoder.encode(updateReqVO.getNewPassword())); - attendanceMachineMapper.updateById(attendanceMachineDO); + attendanceMachineMapper.update(attendanceMachineDO, new LambdaUpdateWrapper().eq(AttendanceMachineDO::getDeviceNo, updateReqVO.getDeviceNo())); } private void validateAttendanceMachineExists(Long id) { @@ -196,29 +202,39 @@ public class AttendanceMachineServiceImpl implements AttendanceMachineService { @Override public void addUserToAttendanceMachine(AddUserToAttendanceMachineVO addReqVO) { - List recordDOS = new ArrayList<>(); + //获得 用户已绑定设备信息 + List usersExtDO = usersExtService.getListByUserId(addReqVO.getUserId()); // 更新用户已下发设备列表 - List userInfo = addReqVO.getUserInfo(); if (addReqVO.getMethod() == 0) { - userInfo.forEach(data -> { + usersExtDO.forEach(data -> { List deviceNo = data.getAttendanceMachineNos(); // 添加不重复的设备号 - deviceNo.addAll(addReqVO.getDeviceNos().stream().filter(var -> !deviceNo.contains(var)).collect(Collectors.toList())); + if (deviceNo == null || deviceNo.isEmpty()) { + + deviceNo = new ArrayList<>(); + deviceNo.add(addReqVO.getDeviceNo()); + }else { + + if (!deviceNo.contains(addReqVO.getDeviceNo())) { + + deviceNo.add(addReqVO.getDeviceNo()); + } + } //设备 用户绑定设备 data.setAttendanceMachineNos(deviceNo); }); }else if (addReqVO.getMethod() == 1) { - userInfo.forEach(data -> { + usersExtDO.forEach(data -> { List deviceNo = data.getAttendanceMachineNos(); // 添加设备号 - deviceNo.removeAll(addReqVO.getDeviceNos()); + deviceNo.remove(addReqVO.getDeviceNo()); //设备 用户绑定设备 data.setAttendanceMachineNos(deviceNo); @@ -226,9 +242,12 @@ public class AttendanceMachineServiceImpl implements AttendanceMachineService { } // 更新 用户信息 - usersExtService.updateListUsersExt(userInfo); + usersExtService.updateListUsersExt(usersExtDO); + } - //同步 插入 下发记录 + @Override + public List getListByStatus() { + return attendanceMachineMapper.selectList(); } } \ No newline at end of file diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/equipment/DistributeRecordService.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/equipment/DistributeRecordService.java index 36002817..857ffe55 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/equipment/DistributeRecordService.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/equipment/DistributeRecordService.java @@ -3,6 +3,8 @@ package cn.iocoder.yudao.module.system.service.equipment; import cn.iocoder.yudao.module.system.dal.dataobject.equipment.DistributeRecordDO; import javax.validation.Valid; +import java.util.Collection; +import java.util.List; /** * 考勤机下发记录 Service 接口 @@ -15,15 +17,20 @@ public interface DistributeRecordService { * 创建考勤机下发记录 * * @param createReqVO 创建信息 - * @return 编号 */ - Long createDistributeRecord(@Valid DistributeRecordDO createReqVO); + void createDistributeRecord(@Valid List createReqVO); /** - * 获得考勤机下发记录 + * 更新 考勤机下发记录 + * @param updateReqVO 更新信息 + */ + void updateDistributeRecord(@Valid List updateReqVO); + + /** + * 获得最新的 下发或修改的考勤机下发记录 * - * @param id 编号 + * @param userId 用户编号编号 * @return 考勤机下发记录 */ - DistributeRecordDO getDistributeRecord(Long id); + List getDistributeRecord(List userId, Collection type); } \ No newline at end of file diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/equipment/DistributeRecordServiceImpl.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/equipment/DistributeRecordServiceImpl.java index bc4ef4da..98fcb565 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/equipment/DistributeRecordServiceImpl.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/equipment/DistributeRecordServiceImpl.java @@ -1,11 +1,14 @@ package cn.iocoder.yudao.module.system.service.equipment; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; import cn.iocoder.yudao.module.system.dal.dataobject.equipment.DistributeRecordDO; import cn.iocoder.yudao.module.system.dal.mysql.equipment.DistributeRecordMapper; import org.springframework.stereotype.Service; import org.springframework.validation.annotation.Validated; import javax.annotation.Resource; +import java.util.Collection; +import java.util.List; /** * 考勤机下发记录 Service 实现类 @@ -20,17 +23,27 @@ public class DistributeRecordServiceImpl implements DistributeRecordService { private DistributeRecordMapper distributeRecordMapper; @Override - public Long createDistributeRecord(DistributeRecordDO createReqVO) { + public void createDistributeRecord(List createReqVO) { // 插入 - distributeRecordMapper.insert(createReqVO); - // 返回 - return createReqVO.getId(); + distributeRecordMapper.insertBatch(createReqVO); } @Override - public DistributeRecordDO getDistributeRecord(Long id) { - return distributeRecordMapper.selectById(id); + public void updateDistributeRecord(List updateReqVO) { + + for (DistributeRecordDO updateDO : updateReqVO) { + + distributeRecordMapper.update(updateDO, + new LambdaQueryWrapperX() + .eq(DistributeRecordDO::getUserId, updateDO.getUserId()) + .eq(DistributeRecordDO::getRequestId, updateDO.getRequestId())); + } } + @Override + public List getDistributeRecord(List userId, Collection type) { + + return distributeRecordMapper.selectListByUserIdAndType(userId, type); + } } \ No newline at end of file diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/equipment/UsersExtService.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/equipment/UsersExtService.java index 3330eb9b..2c2a9dec 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/equipment/UsersExtService.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/equipment/UsersExtService.java @@ -40,7 +40,7 @@ public interface UsersExtService { * * @param updateDo 更新信息 */ - void updateListUsersExt(@Valid List updateDo); + void updateListUsersExt(@Valid List updateDo); /** * 删除用户人脸信息 @@ -55,6 +55,13 @@ public interface UsersExtService { */ UsersExtDO getUsersExt(Long id); + /** + * 获得指定得用户信息列表 + * @param userId 用户编号 + * @return + */ + List getListByUserId(List userId); + /** * 获得用户信息拓展分页 * diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/equipment/UsersExtServiceImpl.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/equipment/UsersExtServiceImpl.java index d5451d17..2eede9a8 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/equipment/UsersExtServiceImpl.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/equipment/UsersExtServiceImpl.java @@ -3,21 +3,28 @@ package cn.iocoder.yudao.module.system.service.equipment; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.io.IoUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.json.JsonUtils; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.framework.mybatis.core.util.MyBatisUtils; +import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder; import cn.iocoder.yudao.module.infra.api.file.FileApi; +import cn.iocoder.yudao.module.infra.api.websocket.WebSocketSenderApi; import cn.iocoder.yudao.module.system.controller.admin.equipment.vo.userExt.UserExtImportVO; import cn.iocoder.yudao.module.system.controller.admin.equipment.vo.userExt.UsersExtPageReqVO; import cn.iocoder.yudao.module.system.controller.admin.equipment.vo.userExt.UsersExtRespVO; import cn.iocoder.yudao.module.system.controller.admin.equipment.vo.userExt.UsersExtSaveReqVO; +import cn.iocoder.yudao.module.system.controller.admin.equipment.vo.websocket.UpdateFaceImgVO; +import cn.iocoder.yudao.module.system.controller.admin.equipment.vo.websocket.WebsocketBaseVO; import cn.iocoder.yudao.module.system.controller.admin.user.vo.user.UserImportRespVO; import cn.iocoder.yudao.module.system.dal.dataobject.dept.DeptDO; +import cn.iocoder.yudao.module.system.dal.dataobject.equipment.DistributeRecordDO; import cn.iocoder.yudao.module.system.dal.dataobject.equipment.UsersExtDO; import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO; import cn.iocoder.yudao.module.system.dal.mysql.equipment.UsersExtMapper; import cn.iocoder.yudao.module.system.service.dept.DeptService; import cn.iocoder.yudao.module.system.service.user.AdminUserService; import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.core.toolkit.IdWorker; import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -26,13 +33,11 @@ import org.springframework.web.multipart.MultipartFile; import javax.annotation.Resource; import java.io.IOException; -import java.util.ArrayList; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; +import java.util.*; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; +import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.*; /** @@ -58,6 +63,12 @@ public class UsersExtServiceImpl implements UsersExtService { @Resource private AdminUserService userService; + @Resource + private WebSocketSenderApi webSocketSenderApi; + + @Resource + private DistributeRecordService recordService; + @Override public Long createUsersExt(UsersExtDO updateDO, MultipartFile file) throws IOException { @@ -96,6 +107,41 @@ public class UsersExtServiceImpl implements UsersExtService { updateDO.setFaceImg(url); usersExtMapper.updateById(usersExtDO); } + + // 判断用户是否已下发至考勤设备 + if (usersExtDO.getAttendanceMachineNos() != null) { + + String requestId = IdWorker.get32UUID(); + WebsocketBaseVO baseVO = new WebsocketBaseVO() + .setFrom("") + .setExtra(requestId + "_" + getLoginUserId()); + for (String deviceNo : usersExtDO.getAttendanceMachineNos()) { + + // 设备指令信息 + UpdateFaceImgVO faceImgVO = new UpdateFaceImgVO(); + faceImgVO.setUser_id(String.valueOf(usersExtDO.getUserId())); + faceImgVO.setFace_template(url); + + baseVO.setTo(deviceNo); + baseVO.setData(faceImgVO); + + // 设置 设备下发记录 + DistributeRecordDO recordDO = new DistributeRecordDO(); + recordDO.setRequestId(requestId); + recordDO.setDeviceNo(deviceNo); + recordDO.setUserId(usersExtDO.getUserId()); + recordDO.setType(2); + recordDO.setResult("通讯失败"); + + // 更新下发记录信息 + recordService.createDistributeRecord(Collections.singletonList(recordDO)); + + // 设备租户ID + TenantContextHolder.setTenantId(1L); + // 发送指令至设备 更新设备上人脸图片 + webSocketSenderApi.sendSN(deviceNo, "attendance-message-send", JsonUtils.toJsonString(baseVO)); + } + } } // 返回 @@ -113,12 +159,10 @@ public class UsersExtServiceImpl implements UsersExtService { } @Override - public void updateListUsersExt(List updateDo) { + public void updateListUsersExt(List updateDo) { // 更新 - List update = BeanUtils.toBean(updateDo, UsersExtDO.class); - - usersExtMapper.updateBatch(update); + usersExtMapper.updateBatch(updateDo); } @Override @@ -145,9 +189,16 @@ public class UsersExtServiceImpl implements UsersExtService { @Override public UsersExtDO getUsersExt(Long id) { + return usersExtMapper.selectById(id); } + @Override + public List getListByUserId(List userId) { + + return usersExtMapper.selectList(UsersExtDO::getUserId, userId); + } + @Override public PageResult getUsersExtPage(UsersExtPageReqVO pageReqVO) { diff --git a/yudao-module-system/yudao-module-system-biz/src/main/resources/application.yaml b/yudao-module-system/yudao-module-system-biz/src/main/resources/application.yaml index e528a4d1..63316fc2 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/resources/application.yaml +++ b/yudao-module-system/yudao-module-system-biz/src/main/resources/application.yaml @@ -135,6 +135,19 @@ yudao: web: admin-ui: url: http://sys.znkjfw.com # Admin 管理后台 UI 的地址 + websocket: + enable: true # websocket的开关 + path: /infra/ws # 路径 + sender-type: local # 消息发送的类型,可选值为 local、redis、rocketmq、kafka、rabbitmq + sender-rocketmq: + topic: ${spring.application.name}-websocket # 消息发送的 RocketMQ Topic + consumer-group: ${spring.application.name}-websocket-consumer # 消息发送的 RocketMQ Consumer Group + sender-rabbitmq: + exchange: ${spring.application.name}-websocket-exchange # 消息发送的 RabbitMQ Exchange + queue: ${spring.application.name}-websocket-queue # 消息发送的 RabbitMQ Queue + sender-kafka: + topic: ${spring.application.name}-websocket # 消息发送的 Kafka Topic + consumer-group: ${spring.application.name}-websocket-consumer # 消息发送的 Kafka Consumer Group swagger: title: 管理后台 description: 提供管理员管理的所有功能 diff --git a/yudao-module-system/yudao-module-system-biz/src/main/resources/mapper/equipment/AttendanceMachineMapper.xml b/yudao-module-system/yudao-module-system-biz/src/main/resources/mapper/equipment/AttendanceMachineMapper.xml index 31ede6e5..1025c89c 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/resources/mapper/equipment/AttendanceMachineMapper.xml +++ b/yudao-module-system/yudao-module-system-biz/src/main/resources/mapper/equipment/AttendanceMachineMapper.xml @@ -15,7 +15,8 @@ a.assets_no AS assetsNo, b.device_no AS deviceNo, c.dept_id AS deptId, - b.device_name AS deviceName + b.device_name AS deviceName, + b.status AS isOnLine FROM zc_assets a LEFT JOIN kq_attendance_machine b ON a.assets_no = b.assets_no @@ -29,12 +30,9 @@ AND b.device_name LIKE CONCAT('%', #{reqVO.deviceName}, '%') - - - - - - + + AND b.status = #{reqVO.isOnLine} + + SELECT + a.user_id, + a.result, + b.create_time + FROM + kq_distribute_record a, + ( + SELECT + user_id, + MAX( create_time ) AS create_time + FROM + kq_distribute_record + WHERE + type IN + + #{type} + + AND user_id IN + + #{userId} + + GROUP BY + user_id + ) b + WHERE + a.user_id = b.user_id + AND a.create_time = b.create_time + + \ No newline at end of file diff --git a/yudao-module-system/yudao-module-system-biz/src/main/resources/mapper/equipment/UsersExtMapper.xml b/yudao-module-system/yudao-module-system-biz/src/main/resources/mapper/equipment/UsersExtMapper.xml index e2e6186a..fe39163a 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/resources/mapper/equipment/UsersExtMapper.xml +++ b/yudao-module-system/yudao-module-system-biz/src/main/resources/mapper/equipment/UsersExtMapper.xml @@ -45,12 +45,15 @@ - and b.create_time >= #{reqVO.createTime[0]} + AND b.create_time >= #{reqVO.createTime[0]} - and b.create_time <= #{reqVO.createTime[1]} + AND b.create_time <= #{reqVO.createTime[1]} + + AND a.user_type = #{reqVO.userType} + \ No newline at end of file