diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/wgz/WgzAppController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/wgz/WgzAppController.java index 82d03ec..e8ea589 100644 --- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/wgz/WgzAppController.java +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/wgz/WgzAppController.java @@ -1,7 +1,9 @@ package com.ruoyi.web.controller.wgz; + import cn.hutool.core.collection.CollectionUtil; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; + import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.ruoyi.bgt.domain.BgtProjectRecruit; import com.ruoyi.bgt.domain.BgtProjectRecruitApply; import com.ruoyi.bgt.domain.dto.BgtAttendanceDetailDTO; @@ -17,6 +19,7 @@ import com.ruoyi.common.core.page.TableDataInfo; import com.ruoyi.common.domain.Annex; import com.ruoyi.common.domain.dto.AnnexDTO; + import com.ruoyi.common.enums.RecruitApplyStatus; import com.ruoyi.common.service.IAnnexService; import com.ruoyi.common.utils.SecurityUtils; import com.ruoyi.system.service.ISysDictTypeService; @@ -324,6 +327,29 @@ return AjaxResult.success(iWgzAttendanceService.userSubmitTheClock(req)); } + @ApiOperation("【考勤打卡】【打卡】 获取打卡范围") + //@PreAuthorize("@ss.hasPermi('wgzApp:user:userSubmitTheClock')") + @GetMapping("/WgzAppUserClockRange") + public AjaxResult userClockRange() { + + WgzAppUserClockRangeRes wgzAppUserClockRangeRes = new WgzAppUserClockRangeRes(); + //1、获取当前用户信息 + Long appUserId = SecurityUtils.getAppUserId(); + LambdaQueryWrapper lqw = Wrappers.lambdaQuery(); + lqw.eq(BgtProjectRecruitApply::getUserId, appUserId). + eq(BgtProjectRecruitApply::getStatus, RecruitApplyStatus.WORKING.getCode()); //包工头+务工者同意 or 进场 才算进场ok + List bgtProjectRecruitApplies = iBgtProjectRecruitApplyService.list(lqw); + if (CollectionUtil.isEmpty(bgtProjectRecruitApplies)) { + return AjaxResult.success(wgzAppUserClockRangeRes); + } + //3、根据工地id得到完整的工地信息 + BgtProjectRecruit appById = iBgtProjectRecruitService.getById(bgtProjectRecruitApplies.get(0).getRecruitId()); + wgzAppUserClockRangeRes.setCentralLatitude(appById.getCentralLatitude()); + wgzAppUserClockRangeRes.setCentralLongitude(appById.getCentralLongitude()); + wgzAppUserClockRangeRes.setRangeRadius(appById.getRangeRadius()); + return AjaxResult.success(wgzAppUserClockRangeRes); + } + /** * 【考勤打卡】【打卡日历】 打卡日历记录 */ diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/TokenService.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/TokenService.java index 7644dca..a971d49 100644 --- a/ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/TokenService.java +++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/TokenService.java @@ -54,9 +54,9 @@ public class TokenService { public LoginUser getLoginUser(HttpServletRequest request) { // 获取请求携带的令牌 + String clientIP = ServletUtils.getClientIP(); - String token = getToken(request); -// log.info("用户当前token:{}", token); + String token = getToken(request); if (Validator.isNotEmpty(token)) { Claims claims = parseToken(token); // 解析对应的权限以及用户信息 @@ -66,8 +66,8 @@ public class TokenService { String userId = (String) claims.get(Constants.LOGIN_USER_ID); String userKey = getTokenKey(type, userId); LoginUser user = redisCache.getCacheObject(userKey); -// log.info("用户当前类型:{}", claims); if(user==null || !uuid.equals(user.getToken())){ + log.info("用户ip:{},用户ID:{},用户类型:{},用户当前token:{}",clientIP,userId,type,token); throw new BaseException("999","您的账号在其他设备登录"); } return user; diff --git a/ruoyi-system/src/main/java/com/ruoyi/bgt/domain/BgtProjectRecruit.java b/ruoyi-system/src/main/java/com/ruoyi/bgt/domain/BgtProjectRecruit.java index 9858a75..aab2536 100644 --- a/ruoyi-system/src/main/java/com/ruoyi/bgt/domain/BgtProjectRecruit.java +++ b/ruoyi-system/src/main/java/com/ruoyi/bgt/domain/BgtProjectRecruit.java @@ -140,6 +140,15 @@ public class BgtProjectRecruit implements Serializable { @ApiModelProperty("下班时间") private LocalTime endWorkTime; + @ApiModelProperty("中心点经度") + private Double centralLongitude; + + @ApiModelProperty("'中心点纬度'") + private Double centralLatitude; + + @ApiModelProperty("'半径'") + private Double rangeRadius; + @ApiModelProperty("工种") private String typeOfWork; diff --git a/ruoyi-system/src/main/java/com/ruoyi/bgt/domain/vo/BgtProjectRecruitDetailVO.java b/ruoyi-system/src/main/java/com/ruoyi/bgt/domain/vo/BgtProjectRecruitDetailVO.java index bef3c75..0e36d2c 100644 --- a/ruoyi-system/src/main/java/com/ruoyi/bgt/domain/vo/BgtProjectRecruitDetailVO.java +++ b/ruoyi-system/src/main/java/com/ruoyi/bgt/domain/vo/BgtProjectRecruitDetailVO.java @@ -119,4 +119,13 @@ public class BgtProjectRecruitDetailVO implements Serializable { @ApiModelProperty("招工状态(1-进行中,2-已招满,3-已过期)") private String status; + + @ApiModelProperty("中心点经度") + private Double centralLongitude; + + @ApiModelProperty("'中心点纬度'") + private Double centralLatitude; + + @ApiModelProperty("'半径'") + private Double rangeRadius; } diff --git a/ruoyi-system/src/main/java/com/ruoyi/common/util/LocationUtils.java b/ruoyi-system/src/main/java/com/ruoyi/common/util/LocationUtils.java new file mode 100644 index 0000000..ff5f7d0 --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/common/util/LocationUtils.java @@ -0,0 +1,68 @@ +package com.ruoyi.common.util; + +import com.ruoyi.common.exception.BaseException; + +public class LocationUtils { + private static final double EARTH_RADIUS = 6371000; + + /** + * 计算两点间的球面距离(Haversine 公式) + * @throws IllegalArgumentException 如果任何参数为 null + */ + public static double haversine(Double lat1, Double lon1, Double lat2, Double lon2) { + validateCoordinates(lat1, lon1, lat2, lon2); + + double lat1Rad = Math.toRadians(lat1); + double lon1Rad = Math.toRadians(lon1); + double lat2Rad = Math.toRadians(lat2); + double lon2Rad = Math.toRadians(lon2); + + double dLat = lat2Rad - lat1Rad; + double dLon = lon2Rad - lon1Rad; + + double a = Math.sin(dLat / 2) * Math.sin(dLat / 2) + + Math.cos(lat1Rad) * Math.cos(lat2Rad) * + Math.sin(dLon / 2) * Math.sin(dLon / 2); + double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a)); + + return EARTH_RADIUS * c; + } + + /** + * 判断当前坐标是否在打卡范围内 + * @throws IllegalArgumentException 如果中心点坐标或范围为 null + */ + public static boolean isInRange(Double centerLat, Double centerLon, + Double currentLat, Double currentLon, + Double rangeMeters) { + if (rangeMeters == null || rangeMeters < 0) { + throw new BaseException("打卡范围不能为空且必须为正数"); + } + + if (currentLat == null || currentLon == null) { + return false; // 当前位置为 null 时视为不在范围内 + } + + validateCoordinates(centerLat, centerLon); + + double distance = haversine(centerLat, centerLon, currentLat, currentLon); + return distance <= rangeMeters; + } + + // 参数校验方法 + private static void validateCoordinates(Double... coords) { + for (Double coord : coords) { + if (coord == null) { + throw new BaseException("经纬度坐标不能为空"); + } + } + } + + + public static void main(String[] args) { + + double haversine = haversine(29.623956, 106.508291, 29.623906, 106.508314); + System.out.println(haversine); + } + +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/wgz/bo/req/WgzAppSubmitTheClockReq.java b/ruoyi-system/src/main/java/com/ruoyi/wgz/bo/req/WgzAppSubmitTheClockReq.java index e62e486..21a9129 100644 --- a/ruoyi-system/src/main/java/com/ruoyi/wgz/bo/req/WgzAppSubmitTheClockReq.java +++ b/ruoyi-system/src/main/java/com/ruoyi/wgz/bo/req/WgzAppSubmitTheClockReq.java @@ -1,6 +1,5 @@ package com.ruoyi.wgz.bo.req; -import com.ruoyi.common.annotation.Excel; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; @@ -26,4 +25,14 @@ public class WgzAppSubmitTheClockReq implements Serializable { @ApiModelProperty("打卡位置") @NotBlank(message = "打卡位置不能为空") private String pnchOsition; + + @ApiModelProperty("当前位置纬度") + @NotNull(message = "当前位置纬度不能为空") + private Double currentLat; + + @ApiModelProperty("当前位置经度") + @NotNull(message = "当前位置经度不能为空") + private Double currentLon; + + } diff --git a/ruoyi-system/src/main/java/com/ruoyi/wgz/bo/res/WgzAppUserClockRangeRes.java b/ruoyi-system/src/main/java/com/ruoyi/wgz/bo/res/WgzAppUserClockRangeRes.java new file mode 100644 index 0000000..1b711ec --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/wgz/bo/res/WgzAppUserClockRangeRes.java @@ -0,0 +1,18 @@ +package com.ruoyi.wgz.bo.res; + +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +@Data +public class WgzAppUserClockRangeRes { + + @ApiModelProperty("中心点经度") + private Double centralLongitude; + + @ApiModelProperty("'中心点纬度'") + private Double centralLatitude; + + @ApiModelProperty("'半径'") + private Double rangeRadius; + +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/wgz/service/impl/WgzAttendanceServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/wgz/service/impl/WgzAttendanceServiceImpl.java index fe86c60..0b3a5a6 100644 --- a/ruoyi-system/src/main/java/com/ruoyi/wgz/service/impl/WgzAttendanceServiceImpl.java +++ b/ruoyi-system/src/main/java/com/ruoyi/wgz/service/impl/WgzAttendanceServiceImpl.java @@ -18,6 +18,7 @@ import com.ruoyi.common.core.page.TableDataInfo; import com.ruoyi.common.exception.BaseException; import com.ruoyi.common.util.DataUtil; import com.ruoyi.common.util.LocalDateToChineseWeekday; +import com.ruoyi.common.util.LocationUtils; import com.ruoyi.common.utils.DateUtils; import com.ruoyi.common.utils.PageUtils; import com.ruoyi.common.utils.SecurityUtils; @@ -172,6 +173,7 @@ public class WgzAttendanceServiceImpl extends ServicePlusImpl