Parcourir la source

初始化提交

main
1341924763@qq.com il y a 1 semaine
Parent
révision
c8d1422000

+ 59
- 0
zs-manager/src/main/java/com/ruoyi/zhushi/controller/DkAppController.java Voir le fichier

@@ -0,0 +1,59 @@
package com.ruoyi.zhushi.controller;

import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.zhushi.entity.AppDTO;
import com.ruoyi.zhushi.entity.DkCheckInRecord;
import com.ruoyi.zhushi.service.DkAppService;
import com.ruoyi.zhushi.service.DkAttendanceGroupService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;

/**
* 打卡控制台
*/
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/dk/app")
@Slf4j
public class DkAppController extends BaseController {


@Autowired
private DkAttendanceGroupService dkAttendanceGroupService;

@Autowired
private DkAppService dkAppService;


@GetMapping("/queryAttendanceGroupBYUserId")
public R<AppDTO> queryAttendanceGroupBYUserId(long userId) {
return R.ok(dkAttendanceGroupService.queryAttendanceGroupBYUserId(userId));
}

// 上班打卡
@GetMapping("/checkIn")
public R<String> checkIn(AppDTO appDTO) {
return R.ok(dkAppService.checkIn(appDTO));
}

// 下班打卡
@GetMapping("/checkOut")
public R<String> checkOut(AppDTO appDTO) {
return R.ok(dkAppService.checkOut(appDTO));
}

// 获取当日当前员工考勤状态
@GetMapping("/getCurrentDayRecord")
public R<List<DkCheckInRecord>> getAttendanceStatus(AppDTO appDTO) {
return R.ok(dkAppService.getCurrentDayRecord(appDTO));
}
}

+ 66
- 0
zs-manager/src/main/java/com/ruoyi/zhushi/entity/AppDTO.java Voir le fichier

@@ -0,0 +1,66 @@
package com.ruoyi.zhushi.entity;

import com.ruoyi.common.core.domain.BaseEntity;
import lombok.Data;

import java.util.List;

@Data
public class AppDTO extends BaseEntity {

// 用户id
private long id;

// 考勤组名称
private String attendanceGroupName;

// 用户id
private long userId;

// 用户名
private String userName;

// 打卡描述
private String description;

// 工作日
private List<String> workDays;

// private List<String> workDaysList;

// 上班开始时间打卡
private String workStartTime;

// 上班结束时间打卡
private String workEndTime;

// 是否允许迟到
private Boolean allowLate;

// 允许迟到范围
private Integer lateRange;

// 是否允许早退
private Boolean allowEarly;

// 允许早退范围
private Integer earlyRange;

// 关联区域id
private Long areaId;

// 成员数据
private List<DkAttendanceGroupAndUser> members;

// 经度
private double lng;

// 纬度
private double lat;

// 允许打卡半径
private int radius;

// 是否迟到打卡
private String isCheckInLate;
}

+ 15
- 0
zs-manager/src/main/java/com/ruoyi/zhushi/service/DkAppService.java Voir le fichier

@@ -0,0 +1,15 @@
package com.ruoyi.zhushi.service;

import com.ruoyi.zhushi.entity.AppDTO;
import com.ruoyi.zhushi.entity.DkCheckInRecord;

import java.util.List;

public interface DkAppService {

String checkIn(AppDTO appDTO);

String checkOut(AppDTO appDTO);

List<DkCheckInRecord> getCurrentDayRecord(AppDTO appDTO);
}

+ 173
- 0
zs-manager/src/main/java/com/ruoyi/zhushi/service/impl/DkAppServiceImpl.java Voir le fichier

@@ -0,0 +1,173 @@
package com.ruoyi.zhushi.service.impl;

import com.ruoyi.zhushi.entity.AppDTO;
import com.ruoyi.zhushi.entity.DkCheckInRecord;
import com.ruoyi.zhushi.entity.DkCheckInRecordDTO;
import com.ruoyi.zhushi.mapper.DkAttendanceGroupMapper;
import com.ruoyi.zhushi.mapper.DkRecordMapper;
import com.ruoyi.zhushi.service.DkAppService;
import com.ruoyi.zhushi.util.GeoDistanceUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.Duration;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
import java.util.List;

@Service
public class DkAppServiceImpl implements DkAppService {

@Autowired
private DkAttendanceGroupMapper dkAttendanceGroupMapper;

@Autowired
private DkRecordMapper dkRecordMapper;

@Override
public String checkIn(AppDTO appDTO) {
AppDTO appDTO1 = dkAttendanceGroupMapper.queryAttendanceGroupBYUserId(appDTO.getUserId());
// 打卡开始时间
String workStartTime = appDTO1.getWorkStartTime();
if(workStartTime == null){
return "系统设置错误";
}

// 根据经纬度计算两点之间的距离
double distanceKm = GeoDistanceUtil.getDistanceKm(appDTO.getLat(), appDTO.getLng(), appDTO1.getLat(), appDTO1.getLng());
if (distanceKm > appDTO.getRadius()) {
return "超出范围";
}

// 解析给定的时分秒(格式:HH:mm:ss 或 HH:mm)
boolean result = canSignIn(workStartTime);
DkCheckInRecord dkCheckInRecord = new DkCheckInRecord();
if(!result){
boolean b = allowCheckIn(workStartTime, appDTO.getLateRange());
if(!b){
dkCheckInRecord.setSysUserId(appDTO.getUserId());
dkCheckInRecord.setSysUserName(appDTO.getUserName());
dkCheckInRecord.setCheckInTime(LocalDateTime.now());
dkCheckInRecord.setCheckInStatus("2");
dkCheckInRecord.setCheckInType("startCheckIn");
dkRecordMapper.insert(dkCheckInRecord);
return "迟到打卡";
}
dkCheckInRecord.setSysUserId(appDTO.getUserId());
dkCheckInRecord.setSysUserName(appDTO.getUserName());
dkCheckInRecord.setCheckInTime(LocalDateTime.now());
dkCheckInRecord.setCheckInStatus("1");
dkCheckInRecord.setCheckInType("startCheckIn");
dkRecordMapper.insert(dkCheckInRecord);
return "打卡成功";
}


dkCheckInRecord.setSysUserId(appDTO.getUserId());
dkCheckInRecord.setSysUserName(appDTO.getUserName());
dkCheckInRecord.setCheckInTime(LocalDateTime.now());
dkCheckInRecord.setCheckInStatus("1");
dkCheckInRecord.setCheckInType("startCheckIn");
dkRecordMapper.insert(dkCheckInRecord);
return "打卡成功";
}

// 判断是否可以签到(给定时间是否在当前时间之前)
public static boolean canSignIn(String timeStr) {
// 解析给定的时分秒(格式:HH:mm:ss 或 HH:mm)
DateTimeFormatter formatter = timeStr.contains(":") ?
(timeStr.length() > 5 ? DateTimeFormatter.ofPattern("HH:mm:ss") :
DateTimeFormatter.ofPattern("HH:mm")) :
DateTimeFormatter.ofPattern("HHmmss");

LocalTime givenTime = LocalTime.parse(timeStr, formatter);
LocalTime currentTime = LocalTime.now();

// 如果给定时间在当前时间之前,则可以签到
return givenTime.isBefore(currentTime);
}

public static boolean allowCheckIn(String timeStr, long maxDifferenceMinutes) {
try {
// 解析输入的时间字符串
DateTimeFormatter formatter = timeStr.contains(":") ?
(timeStr.length() > 5 ? DateTimeFormatter.ofPattern("HH:mm:ss") :
DateTimeFormatter.ofPattern("HH:mm")) :
DateTimeFormatter.ofPattern("HHmmss");

LocalTime inputTime = LocalTime.parse(timeStr, formatter);
LocalTime currentTime = LocalTime.now();

// 计算时间差(绝对值)
Duration duration = Duration.between(inputTime, currentTime);
long diffMinutes = Math.abs(duration.toMinutes());

// 判断是否超过最大允许时间差
return diffMinutes <= maxDifferenceMinutes;
} catch (DateTimeParseException e) {
System.err.println("时间格式解析错误: " + e.getMessage());
return false; // 格式错误时默认不允许打卡
}
}

@Override
public String checkOut(AppDTO appDTO) {
AppDTO appDTO1 = dkAttendanceGroupMapper.queryAttendanceGroupBYUserId(appDTO.getUserId());
// 根据经纬度计算两点之间的距离
double distanceKm = GeoDistanceUtil.getDistanceKm(appDTO.getLat(), appDTO.getLng(), appDTO1.getLat(), appDTO1.getLng());
if (distanceKm > appDTO.getRadius()){
return "超出范围";
}

// 打卡开始时间
String workEndTime = appDTO1.getWorkEndTime();
if(workEndTime == null){
return "系统设置错误";
}

// 解析给定的时分秒(格式:HH:mm:ss 或 HH:mm)
boolean result = canSignIn(workEndTime);
if(result){
if(appDTO1.getAllowEarly()){
boolean b = allowCheckIn(workEndTime, appDTO.getEarlyRange());
if(!b){
return "不允许超出提前打卡范围";
}
// 签到成功
DkCheckInRecord dkCheckInRecord = new DkCheckInRecord();
dkCheckInRecord.setSysUserId(appDTO.getUserId());
dkCheckInRecord.setSysUserName(appDTO.getUserName());
dkCheckInRecord.setCheckInTime(LocalDateTime.now());
dkCheckInRecord.setCheckInStatus("0");
dkCheckInRecord.setCheckInType("endCheckIn");
dkRecordMapper.insertOrUpdate(dkCheckInRecord);
return "打卡成功";
}
DkCheckInRecord dkCheckInRecord = new DkCheckInRecord();
dkCheckInRecord.setSysUserId(appDTO.getUserId());
dkCheckInRecord.setSysUserName(appDTO.getUserName());
dkCheckInRecord.setCheckInTime(LocalDateTime.now());
dkCheckInRecord.setCheckInStatus("0");
dkCheckInRecord.setCheckInType("endCheckIn");
dkRecordMapper.insertOrUpdate(dkCheckInRecord);
return "提前打卡";
}else{
DkCheckInRecord dkCheckInRecord = new DkCheckInRecord();
dkCheckInRecord.setSysUserId(appDTO.getUserId());
dkCheckInRecord.setSysUserName(appDTO.getUserName());
dkCheckInRecord.setCheckInTime(LocalDateTime.now());
dkCheckInRecord.setCheckInStatus("0");
dkCheckInRecord.setCheckInType("endCheckIn");
dkRecordMapper.insertOrUpdate(dkCheckInRecord);
return "打卡成功";
}
}

@Override
public List<DkCheckInRecord> getCurrentDayRecord(AppDTO appDTO) {
List<DkCheckInRecord> currentDayRecords = dkRecordMapper.getCurrentDayRecord(appDTO.getUserId());
return currentDayRecords;
}
}

+ 44
- 0
zs-manager/src/main/java/com/ruoyi/zhushi/util/GeoDistanceUtil.java Voir le fichier

@@ -0,0 +1,44 @@
package com.ruoyi.zhushi.util;

/**
* 经纬度距离计算工具类
*/
public class GeoDistanceUtil {
private static final double EARTH_RADIUS = 6371000; // 地球半径(米)

/**
* 计算两点间的距离(米)
*/
public static double getDistance(double lat1, double lng1, double lat2, double lng2) {
double dLat = Math.toRadians(lat2 - lat1);
double dLng = Math.toRadians(lng2 - lng1);

double a = Math.sin(dLat / 2) * Math.sin(dLat / 2) +
Math.cos(Math.toRadians(lat1)) * Math.cos(Math.toRadians(lat2)) *
Math.sin(dLng / 2) * Math.sin(dLng / 2);

double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
return EARTH_RADIUS * c;
}

/**
* 计算两点间的距离(公里)
*/
public static double getDistanceKm(double lat1, double lng1, double lat2, double lng2) {
return getDistance(lat1, lng1, lat2, lng2) / 1000;
}

/**
* 判断两点是否在指定范围内
* @param lat1 点1纬度
* @param lng1 点1经度
* @param lat2 点2纬度
* @param lng2 点2经度
* @param maxDistance 最大距离(米)
* @return 是否在范围内
*/
public static boolean isInRange(double lat1, double lng1, double lat2, double lng2, double maxDistance) {
double distance = getDistance(lat1, lng1, lat2, lng2);
return distance <= maxDistance;
}
}

+ 38
- 0
zs-manager/src/main/resources/mapper/DkAttendanceGroupMapper.xml Voir le fichier

@@ -0,0 +1,38 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="com.ruoyi.zhushi.mapper.DkAttendanceGroupMapper">
<resultMap id="DkAttendanceGroupRusult" type="com.ruoyi.zhushi.entity.AppDTO">
<id property="id" column="id"/>
<result property="attendanceGroupName" column="name"/>
<result property="description" column="description"/>
<result property="workStartTime" column="workStartTime"/>
<result property="workEndTime" column="workEndTime"/>
<result property="lng" column="lng"/>
<result property="lat" column="lat"/>
<result property="radius" column="radius"/>
</resultMap>

<select id="queryAttendanceGroupBYUserId" resultMap="DkAttendanceGroupRusult">
select DISTINCT t.`name`, t.description,
t.work_start_time workStartTime,
t.work_end_time workEndTime,
t.allow_early allowEarly,
t.early_range earlyRange,
t.allow_late allowLate,
t.late_range lateRange,
c.lng lng, c.lat lat, c.radius
from dk_check_in_attendance_team_and_user u
LEFT JOIN dk_check_in_attendance_team t on t.id = u.attendance_team_id
left JOIN dk_check_in_config c on c.id = t.area_id
<where>
t.work_start_time is not null
<if test="userId != null and userId != ''">
AND u.user_id = #{userId}
</if>
</where>
</select>

</mapper>

+ 38
- 0
zs-manager/src/main/resources/mapper/DkRecordMapper.xml Voir le fichier

@@ -0,0 +1,38 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="com.ruoyi.zhushi.mapper.DkRecordMapper">
<resultMap id="DkRecordResult" type="com.ruoyi.zhushi.entity.DkCheckInRecord">
<id property="id" column="id"/>
<result property="sysUserId" column="sys_user_id"/>
<result property="sysUserName" column="sys_user_name"/>
<result property="checkInTime" column="check_in_time"/>
<result property="latitude" column="latitude"/>
<result property="longitude" column="longitude"/>
<result property="checkInStatus" column="check_in_status"/>
<result property="checkInType" column="check_in_type"/>
</resultMap>

<select id="getCurrentDayRecord" resultMap="DkRecordResult">
select DISTINCT t.`name`, t.description,
t.work_start_time workStartTime,
t.work_end_time workEndTime,
t.allow_early allowEarly,
t.early_range earlyRange,
t.allow_late allowLate,
t.late_range lateRange,
c.lng lng, c.lat lat, c.radius
from dk_check_in_attendance_team_and_user u
LEFT JOIN dk_check_in_attendance_team t on t.id = u.attendance_team_id
left JOIN dk_check_in_config c on c.id = t.area_id
<where>
check_in_time >= CURDATE() AND create_time &lt; CURDATE() + INTERVAL 1 DAY
<if test="userId != null and userId != ''">
AND u.user_id = #{userId}
</if>
</where>
</select>

</mapper>

Chargement…
Annuler
Enregistrer