package com.ruoyi.web.controller.api; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.ruoyi.common.core.controller.BaseController; import com.ruoyi.common.core.domain.AjaxResult; import com.ruoyi.common.core.domain.entity.SysDept; import com.ruoyi.common.exception.ServiceException; import com.ruoyi.common.utils.DateUtils; import com.ruoyi.common.utils.StringUtils; import com.ruoyi.common.utils.bean.BeanUtils; import com.ruoyi.system.domain.Employee; import com.ruoyi.system.domain.SysVisitArea; import com.ruoyi.system.domain.SysVisitorRecord; import com.ruoyi.system.domain.vo.AreasList; import com.ruoyi.system.dto.SysVisitAreaTreeRequest; import com.ruoyi.system.dto.SysVisitorIdCardOutRequest; import com.ruoyi.system.dto.SysVisitorRecordAddRequest; import com.ruoyi.system.mapper.EmployeeMapper; import com.ruoyi.system.mapper.SysDeptMapper; import com.ruoyi.system.mapper.SysVisitAreaMapper; import com.ruoyi.system.mapper.SysVisitorRecordMapper; import com.ruoyi.system.service.ISysVisitAreaService; import com.ruoyi.system.utils.EmployeePhoneCrypto; import com.ruoyi.system.vo.SysVisitAreaVO; import com.ruoyi.web.controller.service.SysVisitorRecordService; import com.ruoyi.web.controller.service.VisitorRegisterSyncService; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiParam; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.transaction.annotation.Transactional; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import java.util.*; import java.util.stream.Collectors; @RestController @RequestMapping("/api/visitorRecord") @Api(tags = "现场访客登记-签离") public class SysApiVisitorRecordController extends BaseController { @Autowired private VisitorRegisterSyncService visitorRegisterSyncService; @Autowired private SysVisitorRecordService sysVisitorRecordService; @Autowired private SysVisitorRecordMapper visitorRecordMapper; @Autowired private SysVisitAreaMapper sysVisitAreaMapper; @Autowired private EmployeeMapper employeeMapper; @Autowired private SysDeptMapper sysDeptMapper; @PostMapping("/add") @ApiOperation(value = "访客登记", notes = "现场访客登记") @Transactional(rollbackFor = Exception.class) public AjaxResult add( @RequestBody @ApiParam(value = "访客登记信息", required = true) SysVisitorRecordAddRequest request) { // ================= 参数校验 ================= if (StringUtils.isBlank(request.getVisitorName())) { return AjaxResult.error("访客姓名不能为空"); } if (StringUtils.isBlank(request.getIntervieweeName())) { return AjaxResult.error("被访人不能为空"); } List employeeISList = employeeMapper.selectEnabledByEmployeeName(request.getIntervieweeName()); if (employeeISList.isEmpty()) { throw new ServiceException("被访人不存在,请联系工作人员"); }else { //重名 if (StringUtils.isNotEmpty(request.getBeVisitorPhone())) { String phoneHash = StringUtils.isEmpty(request.getBeVisitorPhone()) ? null : EmployeePhoneCrypto.hash(request.getBeVisitorPhone()); Employee employee = employeeMapper.selectOne(new LambdaQueryWrapper().eq(Employee::getContactPhoneHash, phoneHash)); if (employee == null) { throw new ServiceException("被访人不存在,请联系工作人员"); } } } // 签离的当天不能再次进入 签到 LambdaQueryWrapper yqwrapper = new LambdaQueryWrapper<>(); Date todayStart = DateUtils.truncate(new Date(), Calendar.DAY_OF_MONTH); // 当天 00:00:00 Date todayEnd = DateUtils.addMilliseconds(DateUtils.addDays(todayStart, 1), -1); // 当天 23:59:59 yqwrapper.eq(SysVisitorRecord::getIdCard, request.getIdCard()) .eq(SysVisitorRecord::getStatus, "VISITING") .ge(SysVisitorRecord::getSignTime, todayStart) //签离时间 >= 00:00:00 .le(SysVisitorRecord::getSignTime, todayEnd) //签离时间 <= 23:59:59 .orderByDesc(SysVisitorRecord::getRegisterTime) .last("limit 1"); SysVisitorRecord sysVisitorRecordYQ = visitorRecordMapper.selectOne(yqwrapper); if (sysVisitorRecordYQ != null) { throw new ServiceException("权限已回收,当天不可再次访问"); } if (StringUtils.isNotBlank(request.getIdCard())) { LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(); wrapper.eq(SysVisitorRecord::getIdCard, request.getIdCard()) .eq(SysVisitorRecord::getVisitorName, request.getVisitorName()) .eq(SysVisitorRecord::getDelFlag, "0") .in(SysVisitorRecord::getStatus, "VISITING", "PENDING_CONFIRM") .last("limit 1"); SysVisitorRecord oldRecord = visitorRecordMapper.selectOne(wrapper); if (oldRecord != null) { return AjaxResult.error("该访客当前已有未结束的登记,请勿重复登记"); } } // ================= 保存 ================= SysVisitorRecord record = new SysVisitorRecord(); BeanUtils.copyProperties(request, record); //查询地区 List areasList = null; //查询地区 if (StringUtils.isNotEmpty(record.getVisitAreaIds())) { String[] visitAreaIds = record.getVisitAreaIds().split(","); String visitArea = Arrays.stream(visitAreaIds) .map(id -> { SysVisitArea area = sysVisitAreaMapper.selectById(Long.parseLong(id.trim())); if (area == null || "1".equals(area.getDelFlag())) { throw new ServiceException("访问区域不存在,请联系工作人员"); } return area != null ? area.getAreaName() : null; }) .filter(Objects::nonNull) .collect(Collectors.joining(",")); // ====== 新增:构建 areas 数组 ====== areasList = Arrays.stream(visitAreaIds) .map(String::trim) .filter(StringUtils::isNotEmpty) .map(id -> { SysVisitArea area = sysVisitAreaMapper.selectById(Long.parseLong(id)); if (area == null) { throw new ServiceException("访问区域不存在,请联系工作人员"); } AreasList areas = new AreasList(); areas.setAreaCode(area.getAreaCode()); areas.setAreaName(area.getAreaName()); return areas; }) .filter(Objects::nonNull) .collect(Collectors.toList()); if (!areasList.isEmpty()) { record.setAreasList(areasList); } // 使用 visitArea if (StringUtils.isNotEmpty(visitArea)) { record.setVisitAreaNames(visitArea); record.setRemark("来访中,允许访问区域:" + visitArea); } } // 如果 visitAreaIds 为空,但 visitAreaNames 不为空,根据名称查询填充 visitAreaIds else if (StringUtils.isNotEmpty(record.getVisitAreaNames())) { String[] visitAreaNames = record.getVisitAreaNames().split(","); // 根据区域名称查询对应的ID,构建ID字符串 String visitAreaIdsStr = Arrays.stream(visitAreaNames) .map(String::trim) .filter(StringUtils::isNotEmpty) .map(name -> { // 根据区域名称查询区域信息(这里假设您有根据名称查询的方法) SysVisitAreaTreeRequest query = new SysVisitAreaTreeRequest(); query.setAreaName(name); List area = sysVisitAreaMapper.selectAreaTreeList(query); return area != null ? String.valueOf(area.get(0).getAreaId()) : null; }) .filter(Objects::nonNull) .collect(Collectors.joining(",")); if (StringUtils.isNotEmpty(visitAreaIdsStr)) { record.setVisitAreaIds(visitAreaIdsStr); } // 同时构建 areas 数组 areasList = Arrays.stream(visitAreaNames) .map(String::trim) .filter(StringUtils::isNotEmpty) .map(name -> { SysVisitAreaTreeRequest query = new SysVisitAreaTreeRequest(); query.setAreaName(name); List area = sysVisitAreaMapper.selectAreaTreeList(query); if (area == null || area.isEmpty()) { return null; } AreasList areas = new AreasList(); areas.setAreaCode(area.get(0).getAreaCode()); areas.setAreaName(area.get(0).getAreaName()); return areas; }) .filter(Objects::nonNull) .collect(Collectors.toList()); if (!areasList.isEmpty()) { record.setAreasList(areasList); record.setRemark("来访中,允许访问区域:" + record.getVisitAreaNames()); } } //查询接待人的部门 if (StringUtils.isNotEmpty(record.getIntervieweeName())) { List employee = employeeMapper.selectEnabledByEmployeeName(record.getIntervieweeName()); if (!employee.isEmpty()) { Employee employeeNo1 = employee.get(0); if (employeeNo1.getDeptId() != null) { SysDept sysDept = sysDeptMapper.selectDeptById(employeeNo1.getDeptId()); if (sysDept != null) { record.setIntervieweeDept(sysDept.getDeptName()); } } } } record.setRegisterNo(generateRegisterNo());//登记编号 // record.setRegisterType("ONSITE");//现场登记 record.setRegisterSource("访客机"); record.setStatus("VISITING");//来访中 record.setRegisterTime(new Date()); record.setCreateTime(new Date()); record.setDelFlag("0"); // ================= 同步到对端服务器 ================= try { AjaxResult syncResult = visitorRegisterSyncService.syncVisitorRegister(record); if (syncResult.isSuccess()) { logger.info("访客登记数据已同步到对端,远程ID:{}", syncResult.get("data")); // 可将远程ID保存到本地记录 // record.setRemoteId(syncResult.getRemoteId()); UpdateWrapper wrapper = new UpdateWrapper<>(); wrapper.eq("record_id", record.getRecordId()); // 指定ID条件 visitorRecordMapper.update(record, wrapper); } else { String msg = (String) syncResult.get("msg"); logger.error("访客登记同步失败:{}", msg); // 可选择是否允许本地登记成功但同步失败 // 如果要保证数据一致性,这里可以抛出异常回滚事务 throw new ServiceException(msg); } } catch (Exception e) { logger.error("访客登记同步异常", e); throw new ServiceException("服务器登记失败"); } int rows = visitorRecordMapper.insert(record); sysVisitorRecordService.registerVisitor(record); if (rows > 0) { return AjaxResult.success(record); } return AjaxResult.error("登记失败"); } @PostMapping("/idCardSingOut") @ApiOperation(value = "访客身份证签离", notes = "访客身份证签离") @Transactional(rollbackFor = Exception.class) public AjaxResult idCardSingOut( @RequestBody @ApiParam(value = "访客身份证签离", required = true) SysVisitorIdCardOutRequest request){ if (StringUtils.isEmpty(request.getIdCard())) { throw new ServiceException("请刷身份证"); } //todo 身份证号签离逻辑 LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); wrapper.eq(SysVisitorRecord::getIdCard, request.getIdCard()) .eq(SysVisitorRecord::getStatus, "VISITING") // status = 'VISITING' .orderByDesc(SysVisitorRecord::getRegisterTime) // register_time 倒序 .last("limit 1"); // 只取第一条 SysVisitorRecord record = visitorRecordMapper.selectOne(wrapper); if (record == null) { throw new ServiceException("请使用签到身份证"); } // 2. 校验状态 - 只有来访中或逾期滞留才能签离 String status = record.getStatus(); if (!"VISITING".equals(status) && !"PENDING_CONFIRM".equals(status)) { throw new ServiceException("当前状态不允许签离,状态为:" + status); } // 3. 校验有效期(可选:检查是否在有效期内) Date now = new Date(); if (record.getValidEndTime() != null && now.after(record.getValidEndTime())) { // 如果已过期,自动转为逾期签离状态 record.setStatus("OVERDUE_AUTO_SIGNED_OUT"); } else { record.setStatus("SIGNED_OUT"); } record.setSignVerifyMethod("MANUAL"); SysVisitorRecord visitorRecord = new SysVisitorRecord(); BeanUtils.copyBeanProp(visitorRecord, request); visitorRecord.setSignVerifyMethod(record.getSignVerifyMethod()); visitorRecord.setStatus(record.getStatus()); visitorRecord.setRecordId(record.getRecordId()); visitorRecord.setSignTime(new Date()); UpdateWrapper wrapperUpdate = new UpdateWrapper<>(); wrapperUpdate.eq("record_id", visitorRecord.getRecordId()); // 指定ID条件 visitorRecordMapper.update(visitorRecord, wrapperUpdate); return success(); } /** * 生成登记编号 * 格式: * VIS + 年月日 + 6位随机数 * 例如: * VIS20260707123456 */ private String generateRegisterNo() { String date = new java.text.SimpleDateFormat("yyyyMMddHHmmss").format(new Date()); String random = String.valueOf((int)((Math.random() * 900000) + 100000)); return "VIS" + date + random; } }