This commit is contained in:
zt
2025-11-11 16:41:55 +08:00
parent 23dc2f2759
commit 0941197ca9
8 changed files with 263 additions and 6 deletions

View File

@ -9,6 +9,11 @@ import org.dromara.contractor.domain.SubConstructionUser;
import org.dromara.contractor.domain.dto.constructionuser.*;
import org.dromara.contractor.domain.exportvo.BusConstructionUserExportVo;
import org.dromara.contractor.domain.vo.constructionuser.*;
import org.dromara.project.domain.bo.BusAttendanceBo;
import org.dromara.project.domain.dto.attendance.TodayUserDto;
import org.dromara.project.domain.dto.attendance.TwoWeekDto;
import org.dromara.project.domain.vo.BusAttendanceVo;
import org.dromara.project.domain.vo.attendance.AttendanceTodayUserVo;
import org.dromara.system.domain.vo.SysOssVo;
import org.springframework.web.multipart.MultipartFile;
@ -253,4 +258,7 @@ public interface ISubConstructionUserService extends IService<SubConstructionUse
* @return 施工人员
*/
SubConstructionUser getByUserId(Long sysUserId);
TableDataInfo<AttendanceTodayUserVo> todayUserList(TodayUserDto dto, PageQuery pageQuery);
}

View File

@ -3,10 +3,7 @@ package org.dromara.contractor.service.impl;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.DesensitizedUtil;
import cn.hutool.core.util.IdcardUtil;
import cn.hutool.core.util.PhoneUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.*;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
@ -49,9 +46,12 @@ import org.dromara.contractor.service.ISubConstructionUserFileService;
import org.dromara.contractor.service.ISubConstructionUserService;
import org.dromara.contractor.service.ISubContractorService;
import org.dromara.project.domain.*;
import org.dromara.project.domain.dto.attendance.TodayUserDto;
import org.dromara.project.domain.dto.attendance.TwoWeekDto;
import org.dromara.project.domain.enums.BusAttendanceClockStatusEnum;
import org.dromara.project.domain.enums.BusAttendanceCommuterEnum;
import org.dromara.project.domain.enums.BusConstructionUserAttendanceStatusEnum;
import org.dromara.project.domain.vo.attendance.AttendanceTodayUserVo;
import org.dromara.project.domain.vo.projectteam.BusProjectTeamAppVo;
import org.dromara.project.service.*;
import org.dromara.system.domain.SysUser;
@ -1586,4 +1586,47 @@ public class SubConstructionUserServiceImpl extends ServiceImpl<SubConstructionU
.last("limit 1")
.one();
}
@Override
public TableDataInfo<AttendanceTodayUserVo> todayUserList(TodayUserDto dto, PageQuery pageQuery) {
LambdaQueryWrapper<SubConstructionUser> wrapper = new LambdaQueryWrapper<>();
wrapper.eq(SubConstructionUser::getUserRole, "0")
.eq(SubConstructionUser::getProjectId, dto.getProjectId())
.eq(dto.getTeamId() != null, SubConstructionUser::getTeamId, dto.getTeamId())
.eq(StrUtil.isNotBlank(dto.getTypeOfWork()), SubConstructionUser::getTypeOfWork, dto.getTypeOfWork())
.like(StrUtil.isNotBlank(dto.getUserName()), SubConstructionUser::getUserName, dto.getUserName())
.isNotNull(SubConstructionUser::getTeamId);
if("1".equals(dto.getType())){
wrapper.in(SubConstructionUser::getSysUserId, dto.getUserIds());
}else if("2".equals(dto.getType())){
if(dto.getIsToday()){
wrapper.notIn(CollectionUtil.isNotEmpty(dto.getUserIds()),SubConstructionUser::getSysUserId, dto.getUserIds());
}else {
wrapper.in(SubConstructionUser::getSysUserId, dto.getUserIds());
}
}else{
wrapper.in(SubConstructionUser::getSysUserId, dto.getUserIds());
}
Page<SubConstructionUser> result = this.page(pageQuery.build(), wrapper);
List<SubConstructionUser> records = result.getRecords();
List<Long> list1 = records.stream().map(SubConstructionUser::getTeamId).toList();
List<BusProjectTeam> busProjectTeams = projectTeamService.listByIds(list1);
Map<Long, String> teamMap = busProjectTeams.stream().collect(Collectors.toMap(BusProjectTeam::getId, BusProjectTeam::getTeamName));
ArrayList<AttendanceTodayUserVo> attendanceTodayUserVos = new ArrayList<>();
for (SubConstructionUser constructionUser : records) {
AttendanceTodayUserVo attendanceTodayUserVo = new AttendanceTodayUserVo();
attendanceTodayUserVo.setUserId(constructionUser.getSysUserId());
attendanceTodayUserVo.setUserName(constructionUser.getUserName());
attendanceTodayUserVo.setTypeOfWork(constructionUser.getTypeOfWork());
attendanceTodayUserVo.setTeamName(teamMap.get(constructionUser.getTeamId()));
attendanceTodayUserVos.add(attendanceTodayUserVo);
}
return new TableDataInfo<AttendanceTodayUserVo>(attendanceTodayUserVos, result.getTotal());
}
}

View File

@ -3,6 +3,10 @@ package org.dromara.job.attendance;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.aizuda.snailjob.client.job.core.annotation.JobExecutor;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
@ -337,6 +341,10 @@ public class AttendanceJob {
if (!list.contains(String.valueOf(number))) {
return true;
}
//检查是否假期 https://timor.tech/api/holiday/info/2025-12-31
String format = LocalDateTimeUtil.format(date, "yyyy-MM-dd");
String s = HttpUtil.get("https://timor.tech/api/holiday/info/" + format);
return false;
}
@ -364,4 +372,40 @@ public class AttendanceJob {
return workWageByWorkType.getWage();
}
public static void main(String[] args) {
// 待查询的日期格式yyyy-MM-dd
String format = "2025-10-01";
// 调用API获取结果
String s = HttpUtil.get("https://timor.tech/api/holiday/info/" + format);
// 解析JSON
JSONObject json = JSONUtil.parseObj(s);
// 先判断服务是否正常code=0
if (json.getInt("code") == 0) {
// 获取type对象
JSONObject typeObj = json.getJSONObject("type");
if (typeObj != null) {
// 获取type字段的值
int type = typeObj.getInt("type");
// 判断是否为节假日2或调休3
if (type == 2) {
System.out.println(format + " 是节假日:" + typeObj.getStr("name"));
} else if (type == 3) {
System.out.println(format + " 是调休:" + typeObj.getStr("name"));
} else {
System.out.println(format + " 不是节假日或调休(类型:" + type + "");
}
} else {
System.out.println("解析type字段失败");
}
} else {
System.out.println("API调用失败错误码" + json.getInt("code"));
}
}
}

View File

@ -134,6 +134,14 @@ public class BusAttendanceController extends BaseController {
return R.ok(busAttendanceService.getTodayAttendanceData(dto));
}
/**
* 查询当天出勤人员
*/
@GetMapping("/list/attendanceUser")
public TableDataInfo<AttendanceTodayUserVo> getTodayAttendanceUser(TodayUserDto dto, PageQuery pageQuery) {
return busAttendanceService.getTodayAttendanceUser(dto,pageQuery);
}
@PostMapping("/exportList")
public void exportList(AttendanceExportDto dto, HttpServletResponse response) {
busAttendanceService.getExportList(dto, response);

View File

@ -0,0 +1,43 @@
package org.dromara.project.domain.dto.attendance;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import java.time.LocalDate;
import java.util.List;
@Data
public class TodayUserDto {
/**
* 人员姓名
*/
private String userName;
/**
* 班组id
*/
private Long teamId;
/**
* 工种
*/
private String typeOfWork;
/**
* 项目id
*/
private Long projectId;
@JsonFormat(pattern = "yyyy-MM-dd")
private LocalDate date;
private List<Long> userIds;
/**
* 出勤状态 1-全勤 2-缺勤 3-请假
*/
private String type;
private Boolean isToday;
}

View File

@ -0,0 +1,27 @@
package org.dromara.project.domain.vo.attendance;
import lombok.Data;
import org.dromara.common.translation.annotation.Translation;
import org.dromara.common.translation.constant.TransConstant;
@Data
public class AttendanceTodayUserVo {
private Long userId;
private String userName;
/**
* 工种(字典type_of_work)
*/
private String typeOfWork;
@Translation(type = TransConstant.DICT_TYPE_TO_LABEL, mapper = "typeOfWork",other = "type_of_work")
private String typeOfWorkName;
/**
* 班组名称
*/
private String teamName;
}

View File

@ -185,6 +185,12 @@ public interface IBusAttendanceService extends IService<BusAttendance>{
*/
BusAttendanceClockDateForTwoWeekVo getTodayAttendanceData(TwoWeekDto dto);
/**
* 获取项目当天的出勤人员
*/
TableDataInfo<AttendanceTodayUserVo> getTodayAttendanceUser(TodayUserDto dto, PageQuery pageQuery);
/**
* 获取导出的考勤数据
*/

View File

@ -1654,6 +1654,10 @@ public class BusAttendanceServiceImpl extends ServiceImpl<BusAttendanceMapper, B
String todayStr = currentDate.format(DateTimeFormatter.ISO_LOCAL_DATE); // 结果:"2024-10-10"
if(currentDate.isEqual(now)){
vo.setAbsenteeism(allUserIds.size()- full);
}
int count = 0;
if (CollectionUtil.isNotEmpty(allUserIds)) {
count = (int) leaveService.count(Wrappers.<BusLeave>lambdaQuery()
@ -1703,7 +1707,7 @@ public class BusAttendanceServiceImpl extends ServiceImpl<BusAttendanceMapper, B
count = (int) leaveService.count(Wrappers.<BusLeave>lambdaQuery()
.eq(BusLeave::getProjectId, dto.getProjectId())
.in(BusLeave::getUserId, allUserIds)
.eq(dto.getTeamId() != null, BusLeave::getTeamId, allUserIds)
.eq(dto.getTeamId() != null, BusLeave::getTeamId, dto.getTeamId())
// 关键:给日期字符串加单引号,避免 SQL 语法错误
.apply("DATE(start_time) <= {0}", todayStr)
.apply("DATE(end_time) >= {0}", todayStr)
@ -1746,7 +1750,7 @@ public class BusAttendanceServiceImpl extends ServiceImpl<BusAttendanceMapper, B
vo.setClockDate(now);
vo.setAttendance(full);
vo.setHalfAttendance(half);
vo.setAbsenteeism(absent);
vo.setAbsenteeism(allUserIds.size() - count-full-half);
//计算考勤率
vo.setAllUserNum(allUserIds.size() - count);
vo.setLeave(count);
@ -1756,6 +1760,80 @@ public class BusAttendanceServiceImpl extends ServiceImpl<BusAttendanceMapper, B
return vo;
}
@Override
public TableDataInfo<AttendanceTodayUserVo> getTodayAttendanceUser(TodayUserDto dto, PageQuery pageQuery) {
LocalDate date = dto.getDate();
if (date == null) {
date = LocalDate.now();
}
if("1".equals(dto.getType())){
List<BusAttendance> list = list(Wrappers.<BusAttendance>lambdaQuery()
.eq(BusAttendance::getClockDate, date)
.eq(BusAttendance::getProjectId, dto.getProjectId())
.in(BusAttendance::getClockStatus, ATTENDANCE_LIST)
);
List<Long> list1 = list.stream().map(BusAttendance::getUserId).distinct().toList();
if(CollectionUtil.isEmpty(list1)){
return TableDataInfo.build();
}
dto.setUserIds(list1);
}else if("2".equals(dto.getType())){
List<BusAttendance> list = list(Wrappers.<BusAttendance>lambdaQuery()
.eq(BusAttendance::getClockDate, date)
.eq(BusAttendance::getProjectId, dto.getProjectId())
.in(BusAttendance::getClockStatus, ATTENDANCE_LIST)
);
List<Long> list1 = list.stream().map(BusAttendance::getUserId).distinct().toList();
if(date.isEqual(LocalDate.now())){
String todayStr = date.format(DateTimeFormatter.ISO_LOCAL_DATE);
List<BusLeave> list2 = leaveService.list(Wrappers.<BusLeave>lambdaQuery()
.eq(BusLeave::getProjectId, dto.getProjectId())
.eq(dto.getTeamId() != null, BusLeave::getTeamId, dto.getTeamId())
// 关键:给日期字符串加单引号,避免 SQL 语法错误
.apply("DATE(start_time) <= {0}", todayStr)
.apply("DATE(end_time) >= {0}", todayStr));
List<Long> list11 = list2.stream().map(BusLeave::getUserId).distinct().toList();
ArrayList<Long> longs = new ArrayList<>();
longs.addAll(list1);
longs.addAll(list11);
dto.setUserIds(longs);
dto.setIsToday(true);
}else{
List<BusAttendance> unlocks = list(Wrappers.<BusAttendance>lambdaQuery()
.eq(BusAttendance::getClockDate, date)
.eq(BusAttendance::getProjectId, dto.getProjectId())
.eq(BusAttendance::getClockStatus, BusAttendanceClockStatusEnum.UNCLOCK.getValue())
);
List<Long> list11 = new ArrayList<>(unlocks.stream().map(BusAttendance::getUserId).distinct().toList());
list11.removeAll(list1);
dto.setUserIds(list11);
dto.setIsToday(false);
if(CollectionUtil.isEmpty(list11)){
return TableDataInfo.build();
}
}
}else if("3".equals(dto.getType())){
String todayStr = date.format(DateTimeFormatter.ISO_LOCAL_DATE);
List<BusLeave> list2 = leaveService.list(Wrappers.<BusLeave>lambdaQuery()
.eq(BusLeave::getProjectId, dto.getProjectId())
.eq(dto.getTeamId() != null, BusLeave::getTeamId, dto.getTeamId())
// 关键:给日期字符串加单引号,避免 SQL 语法错误
.apply("DATE(start_time) <= {0}", todayStr)
.apply("DATE(end_time) >= {0}", todayStr));
List<Long> list11 = list2.stream().map(BusLeave::getUserId).distinct().toList();
if(CollectionUtil.isEmpty(list11)){
return TableDataInfo.build();
}
dto.setUserIds(list11);
}
return constructionUserService.todayUserList(dto, pageQuery);
}
@Override
public void getExportList(AttendanceExportDto dto, HttpServletResponse response) {
try (OutputStream outputStream = response.getOutputStream()) {