优化
This commit is contained in:
@ -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<WgzAppUserClockRangeRes> userClockRange() {
|
||||
|
||||
WgzAppUserClockRangeRes wgzAppUserClockRangeRes = new WgzAppUserClockRangeRes();
|
||||
//1、获取当前用户信息
|
||||
Long appUserId = SecurityUtils.getAppUserId();
|
||||
LambdaQueryWrapper<BgtProjectRecruitApply> lqw = Wrappers.lambdaQuery();
|
||||
lqw.eq(BgtProjectRecruitApply::getUserId, appUserId).
|
||||
eq(BgtProjectRecruitApply::getStatus, RecruitApplyStatus.WORKING.getCode()); //包工头+务工者同意 or 进场 才算进场ok
|
||||
List<BgtProjectRecruitApply> 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);
|
||||
}
|
||||
|
||||
/**
|
||||
* 【考勤打卡】【打卡日历】 打卡日历记录
|
||||
*/
|
||||
|
@ -54,9 +54,9 @@ public class TokenService {
|
||||
public LoginUser getLoginUser(HttpServletRequest request) {
|
||||
// 获取请求携带的令牌
|
||||
|
||||
String clientIP = ServletUtils.getClientIP();
|
||||
|
||||
String token = getToken(request);
|
||||
// log.info("用户当前token:{}", token);
|
||||
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;
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
@ -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;
|
||||
|
||||
|
||||
}
|
||||
|
@ -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;
|
||||
|
||||
}
|
@ -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<WgzAttendanceMappe
|
||||
}
|
||||
//3、根据工地id得到完整的工地信息
|
||||
BgtProjectRecruit appById = iBgtProjectRecruitService.getAppById(by.getRecruitId());
|
||||
|
||||
//4、在进场时间时才能打卡,如果有退场记录就不允许打卡
|
||||
if (by.getEntryTime() == null || !by.getStatus().equals("5")) {
|
||||
throw new RuntimeException("需要进场才能实现打卡操作!");
|
||||
@ -179,6 +181,10 @@ public class WgzAttendanceServiceImpl extends ServicePlusImpl<WgzAttendanceMappe
|
||||
if (by.getLeaveTime() != null) {
|
||||
throw new RuntimeException("您已离场,无法进行打卡操作!");
|
||||
}
|
||||
//验证打卡范围
|
||||
if (!LocationUtils.isInRange(appById.getCentralLatitude(), appById.getCentralLongitude(), req.getCurrentLat(), req.getCurrentLon(), appById.getRangeRadius())) {
|
||||
throw new RuntimeException("打卡位置不在工地范围内,请重新打卡!");
|
||||
}
|
||||
//5、查看当前人、当前工地、当天的打卡记录
|
||||
String formattedDate = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
|
||||
WgzAttendance we = publicFindByUserIdWait(appUserId, by.getRecruitId(), formattedDate);
|
||||
|
Reference in New Issue
Block a user