From 70dc6384498b6756ac61723d7e140379931c7519 Mon Sep 17 00:00:00 2001 From: huliyong <2783385703@qq.com> Date: Mon, 10 Nov 2025 02:47:39 +0800 Subject: [PATCH] update --- .../java/org/jeecg/config/shiro/ShiroConfig.java | 1 + .../clockin/service/impl/ClockinServiceImpl.java | 217 ++++++++++++++++++--- .../xcx/user/controller/XcxLoginController.java | 6 + .../modules/xcx/user/service/ILoginService.java | 3 + .../xcx/user/service/impl/LoginServiceImpl.java | 47 +++++ 5 files changed, 248 insertions(+), 26 deletions(-) diff --git a/jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/config/shiro/ShiroConfig.java b/jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/config/shiro/ShiroConfig.java index 936222b..dc1d98b 100644 --- a/jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/config/shiro/ShiroConfig.java +++ b/jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/config/shiro/ShiroConfig.java @@ -74,6 +74,7 @@ public class ShiroConfig { filterChainDefinitionMap.put("/team/list", "anon"); filterChainDefinitionMap.put("/login/login", "anon"); + filterChainDefinitionMap.put("/login/loginTest", "anon"); filterChainDefinitionMap.put("/sys/oss/file/upload", "anon"); //图片上传验证放开 filterChainDefinitionMap.put("/sys/common/upload", "anon"); //图片上传验证放开 filterChainDefinitionMap.put("/sys/cas/client/validateLogin", "anon"); //cas验证登录 diff --git a/jeecg-boot-module-system/src/main/java/org/jeecg/modules/xcx/clockin/service/impl/ClockinServiceImpl.java b/jeecg-boot-module-system/src/main/java/org/jeecg/modules/xcx/clockin/service/impl/ClockinServiceImpl.java index a72e716..a3bac90 100644 --- a/jeecg-boot-module-system/src/main/java/org/jeecg/modules/xcx/clockin/service/impl/ClockinServiceImpl.java +++ b/jeecg-boot-module-system/src/main/java/org/jeecg/modules/xcx/clockin/service/impl/ClockinServiceImpl.java @@ -179,19 +179,102 @@ public class ClockinServiceImpl implements IClockinService { public Result clockInTotal(ClockInTotalReq clockInTotalReq) { Map map = new HashMap<>(); HanHaiMember hanHaiMember = shiroRealm.checkUserTokenIsEffectHanHaiAccount(clockInTotalReq.getToken()); - ClockinTeamLog clockinTeamLog = clockinTeamLogService.lambdaQuery() - .eq(ClockinTeamLog::getDelFlag, 0) - .eq(ClockinTeamLog::getUserId, hanHaiMember.getId()) - .one(); - ClockInProject clockInProject = clockInProjectService.lambdaQuery() - .eq(ClockInProject::getDelFlag, 0) - .eq(ClockInProject::getTeamId, clockinTeamLog.getTeamId()) - .one(); - + + // 解析日期参数,获取月份信息 Date date = new Date(); if(StringUtils.isNotBlank(clockInTotalReq.getDate())){ date = DateUtils2.getDate(clockInTotalReq.getDate()); } + + // 计算当月的开始日期和结束日期 + Date monthStartDate = DateUtils2.beforeXFirstDayOfMonth(date); // 当月第一天 00:00:00 + Date monthEndDate = DateUtils2.currentXDayOfMonth(date); // 当月最后一天 23:59:59 + + // 从用户在该月份的打卡记录中获取项目ID + List monthClockinLogList = clockinLogService.lambdaQuery() + .eq(ClockinLog::getDelFlag, 0) + .eq(ClockinLog::getUserId, hanHaiMember.getId()) + .ge(ClockinLog::getClockInTime, monthStartDate) + .le(ClockinLog::getClockInTime, monthEndDate) + .list(); + + if(monthClockinLogList == null || monthClockinLogList.isEmpty()){ + // 如果该月份没有打卡记录,返回空数据 + map.put("date", new ArrayList<>()); + map.put("normal", 0); + map.put("noCard", 0); + map.put("abnormal", 0); + return Result.OK(map); + } + + // 从打卡记录中提取项目ID(去重) + Set projectIdSet = new HashSet<>(); + for(ClockinLog log : monthClockinLogList){ + if(StringUtils.isNotBlank(log.getProjectId())){ + projectIdSet.add(log.getProjectId()); + } + } + + if(projectIdSet.isEmpty()){ + // 如果没有有效的项目ID,返回空数据 + map.put("date", new ArrayList<>()); + map.put("normal", 0); + map.put("noCard", 0); + map.put("abnormal", 0); + return Result.OK(map); + } + + // 根据项目ID直接查询项目信息 + List clockInProjectList = clockInProjectService.lambdaQuery() + .eq(ClockInProject::getDelFlag, 0) + .in(ClockInProject::getId, projectIdSet) + .list(); + + if(clockInProjectList == null || clockInProjectList.isEmpty()){ + // 如果项目不存在,返回空数据 + map.put("date", new ArrayList<>()); + map.put("normal", 0); + map.put("noCard", 0); + map.put("abnormal", 0); + return Result.OK(map); + } + + // 构建项目ID到项目的映射 + Map projectMap = new HashMap<>(); + for(ClockInProject project : clockInProjectList){ + projectMap.put(project.getId(), project); + } + + // 预先加载所有项目的时区信息,避免在循环中重复查询 + Set timeZoneIdSet = new HashSet<>(); + for(ClockInProject project : clockInProjectList){ + if(StringUtils.isNotBlank(project.getTimeZone())){ + timeZoneIdSet.add(project.getTimeZone()); + } + } + Map timeZoneMap = new HashMap<>(); + if(!timeZoneIdSet.isEmpty()){ + List timeZoneList = clockInTimeZoneService.lambdaQuery() + .in(ClockInTimeZone::getId, timeZoneIdSet) + .list(); + for(ClockInTimeZone timeZone : timeZoneList){ + timeZoneMap.put(timeZone.getId(), timeZone); + } + } + + // 将月份的打卡记录按日期分组,格式:yyyy-MM-dd -> List + Map> dateLogMap = new HashMap<>(); + for(ClockinLog log : monthClockinLogList){ + Date clockInTime = log.getClockInTime(); + if(clockInTime != null){ + String dateStr = DateUtils2.getDateString(clockInTime, "yyyy-MM-dd"); + dateLogMap.computeIfAbsent(dateStr, k -> new ArrayList<>()).add(log); + } + } + + // 用户在该月份有打卡记录 + boolean hasAnyClockInRecord = true; + String nowDay2 = DateUtils2.getNowDay2(DateUtils2.currentXDayOfMonth(date)); Integer n = Integer.parseInt(nowDay2); String yyyymm = DateUtils2.getYYYYMM(date); @@ -203,8 +286,8 @@ public class ClockinServiceImpl implements IClockinService { //未打卡 Integer abnormal = 0; Long todayDate = DateUtils2.getTodayTwelve(); + for (int i = 1;i <= n;i++){ - ClockInTotalResp clockInTotalResp = new ClockInTotalResp(); String dd = i+""; if(i < 10){ @@ -223,28 +306,110 @@ public class ClockinServiceImpl implements IClockinService { if(DayOfWeek.SATURDAY.equals(localDateTime.getDayOfWeek()) || DayOfWeek.SUNDAY.equals(localDateTime.getDayOfWeek())){ type = 1; } - List clockInProjectItemList = clockInProjectItemService.lambdaQuery() - .eq(ClockInProjectItem::getDelFlag, 0) - .eq(ClockInProjectItem::getType,type) - .eq(ClockInProjectItem::getProjectId, clockInProject.getId()) - .list(); - Integer clockInTotal = clockinLogService.getClockInTotal(hanHaiMember.getId(), yyyymmdd); + + // 从已查询的打卡记录中获取当天的打卡记录 + List clockinLogList = dateLogMap.getOrDefault(yyyymmdd, new ArrayList<>()); + + // 按项目分组统计打卡记录 + Map> projectLogMap = new HashMap<>(); + for(ClockinLog log : clockinLogList){ + String projectId = log.getProjectId(); + if(StringUtils.isNotBlank(projectId)){ + projectLogMap.computeIfAbsent(projectId, k -> new ArrayList<>()).add(log); + } + } + + // 计算应该打卡的总次数和实际打卡的总次数 + int totalExpectedCount = 0; // 应该打卡的总次数 + int totalActualCount = clockinLogList.size(); // 实际打卡的总次数 + + // 遍历所有项目,确保所有项目都被统计 + for(ClockInProject project : clockInProjectList){ + if(StringUtils.isBlank(project.getTimeZone())){ + continue; + } + + // 从缓存中获取项目的时区信息 + ClockInTimeZone clockInTimeZone = timeZoneMap.get(project.getTimeZone()); + if(clockInTimeZone == null){ + continue; + } + + // 根据项目时区判断该日期是工作日还是周末 + try { + // 将日期转换为项目时区的日期时间 + LocalDateTime dateTime = LocalDateTime.of( + localDateTime.getYear(), + localDateTime.getMonthValue(), + localDateTime.getDayOfMonth(), + 0, 0, 0 + ); + ZonedDateTime systemZonedDateTime = dateTime.atZone(ZoneId.systemDefault()); + ZonedDateTime projectZonedDateTime = systemZonedDateTime.withZoneSameInstant(ZoneId.of(clockInTimeZone.getTimeZone())); + LocalDateTime projectLocalDateTime = projectZonedDateTime.toLocalDateTime(); + + Integer projectType = 0; + DayOfWeek dayOfWeek = projectLocalDateTime.getDayOfWeek(); + if(DayOfWeek.SATURDAY.equals(dayOfWeek) || DayOfWeek.SUNDAY.equals(dayOfWeek)){ + projectType = 1; + } + + // 获取该项目在这一天应该打卡的次数 + List clockInProjectItemList = clockInProjectItemService.lambdaQuery() + .eq(ClockInProjectItem::getDelFlag, 0) + .eq(ClockInProjectItem::getType, projectType) + .eq(ClockInProjectItem::getProjectId, project.getId()) + .list(); + + totalExpectedCount += clockInProjectItemList.size(); + } catch (Exception e) { + log.error("处理项目时区失败, projectId: {}, timeZone: {}", project.getId(), project.getTimeZone(), e); + // 如果时区转换失败,使用系统时区的类型 + List clockInProjectItemList = clockInProjectItemService.lambdaQuery() + .eq(ClockInProjectItem::getDelFlag, 0) + .eq(ClockInProjectItem::getType, type) + .eq(ClockInProjectItem::getProjectId, project.getId()) + .list(); + totalExpectedCount += clockInProjectItemList.size(); + } + } + clockInTotalResp.setDate(yyyymmdd); - - if(clockInTotal == 0){// 2未打卡 - - abnormal = abnormal+1; - - clockInTotalResp.setType(2); - }else if(clockInTotal 0){ + abnormal = abnormal+1; + clockInTotalResp.setType(2); + clockInTotalResp.setNum(totalExpectedCount); + clockInTotalResps.add(clockInTotalResp); + } else if(totalExpectedCount == 0){ + // 如果不需要打卡,跳过这一天的统计 + continue; + } else { + abnormal = abnormal+1; + clockInTotalResp.setType(2); + clockInTotalResp.setNum(totalExpectedCount); + clockInTotalResps.add(clockInTotalResp); + } + } else if(totalExpectedCount == 0){ + // 如果有打卡记录但没有应该打卡的次数(可能是数据异常),标记为正常 + clockInTotalResp.setType(0); + normal = normal+1; + clockInTotalResp.setNum(0); + clockInTotalResps.add(clockInTotalResp); + } else if(totalActualCount < totalExpectedCount){ clockInTotalResp.setType(1); noCard = noCard+1; - }else{//0正常 + clockInTotalResp.setNum(totalExpectedCount - totalActualCount); + clockInTotalResps.add(clockInTotalResp); + } else { clockInTotalResp.setType(0); normal = normal+1; + clockInTotalResp.setNum(0); + clockInTotalResps.add(clockInTotalResp); } - clockInTotalResp.setNum(clockInProjectItemList.size()-clockInTotal); - clockInTotalResps.add(clockInTotalResp); } map.put("date",clockInTotalResps); map.put("normal",normal); diff --git a/jeecg-boot-module-system/src/main/java/org/jeecg/modules/xcx/user/controller/XcxLoginController.java b/jeecg-boot-module-system/src/main/java/org/jeecg/modules/xcx/user/controller/XcxLoginController.java index 5bab312..bf63497 100644 --- a/jeecg-boot-module-system/src/main/java/org/jeecg/modules/xcx/user/controller/XcxLoginController.java +++ b/jeecg-boot-module-system/src/main/java/org/jeecg/modules/xcx/user/controller/XcxLoginController.java @@ -27,4 +27,10 @@ public class XcxLoginController { return loginService.officialLogin(loginReq); } + @ApiOperation(value = "测试登录") + @PostMapping("/loginTest") + public Result officialLogin(String id){ + return loginService.officialLoginTest(id); + } + } diff --git a/jeecg-boot-module-system/src/main/java/org/jeecg/modules/xcx/user/service/ILoginService.java b/jeecg-boot-module-system/src/main/java/org/jeecg/modules/xcx/user/service/ILoginService.java index 31afd7d..5668477 100644 --- a/jeecg-boot-module-system/src/main/java/org/jeecg/modules/xcx/user/service/ILoginService.java +++ b/jeecg-boot-module-system/src/main/java/org/jeecg/modules/xcx/user/service/ILoginService.java @@ -7,4 +7,7 @@ public interface ILoginService { Result officialLogin(LoginReq loginReq); + + Result officialLoginTest(String id); + } diff --git a/jeecg-boot-module-system/src/main/java/org/jeecg/modules/xcx/user/service/impl/LoginServiceImpl.java b/jeecg-boot-module-system/src/main/java/org/jeecg/modules/xcx/user/service/impl/LoginServiceImpl.java index 743ff10..1650477 100644 --- a/jeecg-boot-module-system/src/main/java/org/jeecg/modules/xcx/user/service/impl/LoginServiceImpl.java +++ b/jeecg-boot-module-system/src/main/java/org/jeecg/modules/xcx/user/service/impl/LoginServiceImpl.java @@ -152,4 +152,51 @@ public class LoginServiceImpl implements ILoginService { return result; } + + + + /** + * 授权登录测试 + * @param id + * @return + */ + @Override + @Transactional(rollbackOn = Exception.class) + public Result officialLoginTest(String id){ + Result result = new Result<>(); + Map map = new HashMap<>(); + + HanHaiMember member = memberService.getById(id); + if (member == null) { + throw new JeecgBootException("无效ID"); + } + ClockinTeamLog clockinTeamLog = clockinTeamLogService.lambdaQuery() + .eq(ClockinTeamLog::getDelFlag, 0) + .eq(ClockinTeamLog::getUserId, member.getId()) + .one(); + if(clockinTeamLog != null){ + ClockinTeam clockinTeam = clockinTeamService.lambdaQuery() + .eq(ClockinTeam::getDelFlag, 0) + .eq(ClockinTeam::getId, clockinTeamLog.getTeamId()) + .one(); + member.setTeam(clockinTeam); + } + ClockinAuth clockinAuth = clockinAuthService.lambdaQuery() + .eq(ClockinAuth::getDelFlag, 0) + .eq(ClockinAuth::getUserId, member.getId()) + .one(); + member.setAuth(clockinAuth); + // 生成token返回给小程序端 + String token = JwtUtil.sign(member.getAppletOpenid(), member.getAppletOpenid()); + redisUtil.set(CommonConstant.PREFIX_USER_TOKEN + token, token); + // 设置超时时间 + redisUtil.expire(CommonConstant.PREFIX_USER_TOKEN + token, JwtUtil.EXPIRE_TIME / 100); + map.put("userInfo", member); + map.put("token", token); + //用户id做im账号 + result.setResult(map); + result.setCode(200); + + return result; + } }