LIVE_YE il y a 2 semaines
Parent
commit
b2c1230219
28 fichiers modifiés avec 748 ajouts et 130 suppressions
  1. 129 50
      ruoyi-admin/src/main/java/com/ruoyi/web/controller/kaoqin/KaoQinController.java
  2. 1 2
      ruoyi-admin/src/main/java/com/ruoyi/web/controller/kaoqin/KaoqinRecordController.java
  3. 38 27
      ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysProfileController.java
  4. 5 3
      ruoyi-admin/src/main/resources/application-druid.yml
  5. 4 2
      ruoyi-admin/src/main/resources/application-prod.yml
  6. 18 1
      ruoyi-admin/src/main/resources/application.yml
  7. 20 0
      ruoyi-common/src/main/java/com/ruoyi/common/config/RuoYiConfig.java
  8. 16 0
      ruoyi-common/src/main/java/com/ruoyi/common/constant/Constants.java
  9. 11 0
      ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysUser.java
  10. 102 4
      ruoyi-common/src/main/java/com/ruoyi/common/utils/DateUtils.java
  11. 42 2
      ruoyi-common/src/main/java/com/ruoyi/common/utils/file/FileUploadUtils.java
  12. 3 2
      ruoyi-framework/src/main/java/com/ruoyi/framework/config/ResourcesConfig.java
  13. 1 1
      ruoyi-framework/src/main/java/com/ruoyi/framework/config/SecurityConfig.java
  14. 9 11
      ruoyi-system/src/main/java/com/ruoyi/mqtt/service/MqttMessageListener.java
  15. 2 2
      ruoyi-system/src/main/java/com/ruoyi/mqtt/service/MqttService.java
  16. 11 0
      ruoyi-system/src/main/java/com/ruoyi/system/domain/CardReplacementRecord.java
  17. 11 0
      ruoyi-system/src/main/java/com/ruoyi/system/domain/KaoqinRecord.java
  18. 3 0
      ruoyi-system/src/main/java/com/ruoyi/system/mapper/KaoqinRecordMapper.java
  19. 3 0
      ruoyi-system/src/main/java/com/ruoyi/system/service/IKaoqinRecordService.java
  20. 93 8
      ruoyi-system/src/main/java/com/ruoyi/system/service/Task.java
  21. 1 0
      ruoyi-system/src/main/java/com/ruoyi/system/service/impl/BusinessTripServiceImpl.java
  22. 55 1
      ruoyi-system/src/main/java/com/ruoyi/system/service/impl/CardReplacementRecordServiceImpl.java
  23. 132 0
      ruoyi-system/src/main/java/com/ruoyi/system/service/impl/KaoqinRecordServiceImpl.java
  24. 2 2
      ruoyi-system/src/main/resources/mapper/system/BusinessTripMapper.xml
  25. 6 1
      ruoyi-system/src/main/resources/mapper/system/CardReplacementRecordMapper.xml
  26. 1 0
      ruoyi-system/src/main/resources/mapper/system/KaoqinConfigMapper.xml
  27. 15 4
      ruoyi-system/src/main/resources/mapper/system/KaoqinRecordMapper.xml
  28. 14 7
      ruoyi-system/src/main/resources/mapper/system/SysUserMapper.xml

+ 129 - 50
ruoyi-admin/src/main/java/com/ruoyi/web/controller/kaoqin/KaoQinController.java

@@ -1,8 +1,11 @@
 package com.ruoyi.web.controller.kaoqin;
 
+import com.google.gson.Gson;
+import com.google.gson.reflect.TypeToken;
 import com.ruoyi.common.annotation.Log;
 import com.ruoyi.common.core.controller.BaseController;
 import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.common.core.domain.entity.SysDept;
 import com.ruoyi.common.core.domain.entity.SysDictData;
 import com.ruoyi.common.core.page.TableDataInfo;
 import com.ruoyi.common.core.redis.RedisCache;
@@ -13,9 +16,7 @@ import com.ruoyi.common.utils.StringUtils;
 import com.ruoyi.common.utils.poi.ExcelUtil;
 import com.ruoyi.system.domain.*;
 import com.ruoyi.system.domain.vo.BaobiaoVo;
-import com.ruoyi.system.mapper.BusinessTripMapper;
-import com.ruoyi.system.mapper.CardReplacementRecordMapper;
-import com.ruoyi.system.mapper.RecordLeaveMapper;
+import com.ruoyi.system.mapper.*;
 import com.ruoyi.system.service.ICardReplacementRecordService;
 import com.ruoyi.system.service.IKaoqinConfigService;
 import com.ruoyi.system.service.IKaoqinRecordService;
@@ -31,6 +32,8 @@ import java.util.*;
 import java.util.stream.Collectors;
 
 import static com.ruoyi.common.constant.CacheConstants.WEEK;
+import static com.ruoyi.common.constant.Constants.ONE;
+import static com.ruoyi.common.constant.Constants.SIX;
 
 /**
  * 实现考勤打卡
@@ -62,9 +65,15 @@ public class KaoQinController extends BaseController {
     @Autowired
     private BusinessTripMapper businessTripMapper;
 
+    @Autowired
+    private AttendanceTimeMapper attendanceTimeMapper;
+
     @Autowired
     private RedisCache redisCache;
 
+    @Autowired
+    private SysDeptMapper deptMapper;
+
     /**
      * 定位打卡提供计算参数
      *
@@ -74,8 +83,10 @@ public class KaoQinController extends BaseController {
     @PreAuthorize("@ss.hasPermi('kaoqin:daKa:param')")
     @GetMapping(value = "/daKa")
     public AjaxResult daKa(KaoqinConfig kaoqinConfig) {
+        //查询考勤规则
+        KaoqinConfig kaoqinConfigDept = kaoqinConfigService.selectKaoqinConfigBynew();
         //先去 根据当前人员的部门id查询是否有规则,没有再去查祖籍列表
-        KaoqinConfig kaoqinConfigDept = kaoqinConfigService.selectKaoqinConfigByDeptId(kaoqinConfig.getDeptId());
+        /*KaoqinConfig kaoqinConfigDept = kaoqinConfigService.selectKaoqinConfigByDeptId(kaoqinConfig.getDeptId());
         if (kaoqinConfigDept == null) {
             //根据部门祖籍列表,查询该部门考勤范围 ,经纬度
             List<KaoqinConfig> kaoqinConfigs = kaoqinConfigService.selectKaoqinConfigList(kaoqinConfig);
@@ -92,7 +103,7 @@ public class KaoQinController extends BaseController {
                     }
                 }
             }
-        }
+        }*/
         return AjaxResult.success(kaoqinConfigDept);
     }
 
@@ -126,7 +137,7 @@ public class KaoQinController extends BaseController {
         for (SysDictData sysDictDatum : sysDictData) {
             //获取异常的值
             String dictValue = sysDictDatum.getDictValue();
-            if (!"1".equals(dictValue)) {
+            if (!ONE.equals(dictValue)) {
                 //获取异常名称
                 String dictLabel = dictToString(sysDictDatum.getDictValue());
                 Long aLong = 0L;
@@ -138,29 +149,38 @@ public class KaoQinController extends BaseController {
             String kaTypeAmOut = kaoQinRecord.getKaTypeAmOut();
             String kaTypePmIn = kaoQinRecord.getKaTypePmIn();
             String kaTypePmOut = kaoQinRecord.getKaTypePmOut();
-            if (!"1".equals(kaTypeAmIn) && StringUtils.isNotBlank(kaTypeAmIn)) {
+            if (!ONE.equals(kaTypeAmIn) && StringUtils.isNotBlank(kaTypeAmIn)) {
                 //获取异常名称
                 String dictLabel = dictToString(kaTypeAmIn);
                 map.compute(dictLabel, (k, aLong) -> aLong + 1);
-                count = count + 1;
+                if (!SIX.equals(kaTypeAmIn)) {
+                    count = count + 1;
+                }
+
             }
-            if (!"1".equals(kaTypeAmOut) && StringUtils.isNotBlank(kaTypeAmOut)) {
+            if (!ONE.equals(kaTypeAmOut) && StringUtils.isNotBlank(kaTypeAmOut)) {
                 //获取异常名称
                 String dictLabel = dictToString(kaTypeAmOut);
                 map.compute(dictLabel, (k, aLong) -> aLong + 1);
-                count = count + 1;
+                if (!SIX.equals(kaTypeAmIn)) {
+                    count = count + 1;
+                }
             }
-            if (!"1".equals(kaTypePmIn) && StringUtils.isNotBlank(kaTypePmIn)) {
+            if (!ONE.equals(kaTypePmIn) && StringUtils.isNotBlank(kaTypePmIn)) {
                 //获取异常名称
                 String dictLabel = dictToString(kaTypePmIn);
                 map.compute(dictLabel, (k, aLong) -> aLong + 1);
-                count = count + 1;
+                if (!SIX.equals(kaTypeAmIn)) {
+                    count = count + 1;
+                }
             }
-            if (!"1".equals(kaTypePmOut) && StringUtils.isNotBlank(kaTypePmOut)) {
+            if (!ONE.equals(kaTypePmOut) && StringUtils.isNotBlank(kaTypePmOut)) {
                 //获取异常名称
                 String dictLabel = dictToString(kaTypePmOut);
                 map.compute(dictLabel, (k, aLong) -> aLong + 1);
-                count = count + 1;
+                if (!SIX.equals(kaTypeAmIn)) {
+                    count = count + 1;
+                }
             }
         }
         map.put("count", count);
@@ -181,50 +201,94 @@ public class KaoQinController extends BaseController {
         cardReplacementRecord.setUserId(kaoqinRecord.getUserId());
         String qDate = kaoqinRecord.getKaYear() + "-" + kaoqinRecord.getKaMonth() + "-01";
         cardReplacementRecord.setApplicationDate(qDate);
+        //cardReplacementRecord.setIsPass("2");
         List<CardReplacementRecord> cardReplacementRecordList = cardReplacementRecordMapper.selectCardReplacementRecordList(cardReplacementRecord);
         Map<String, List<CardReplacementRecord>> cardReplacementCollect = cardReplacementRecordList.stream().collect(Collectors.groupingBy(CardReplacementRecord::getApplicationDate));
         //查询传入月请假信息
         RecordLeave recordLeave = new RecordLeave();
         String month = kaoqinRecord.getKaYear() + "-" + kaoqinRecord.getKaMonth();
-        recordLeave.setStartTime(DateUtils.convertStringToDate(month + "-" + "01 00:00:00"));
+        recordLeave.setStartTime(DateUtils.parseDate(month + "-" + "01 00:00:00"));
         String fin = DateUtils.getLastDayOfMonth(Integer.parseInt(kaoqinRecord.getKaYear()), Integer.parseInt(kaoqinRecord.getKaMonth()));
-        recordLeave.setEndTime(DateUtils.convertStringToDate(fin + " 23:59:59"));
+        recordLeave.setEndTime(DateUtils.parseDate(fin + " 23:59:59"));
         recordLeave.setAbsenteeId(String.valueOf(kaoqinRecord.getUserId()));
+        //recordLeave.setIsPass("2");
         List<RecordLeave> recordLeaves = recordLeaveMapper.selectRecordLeaveList(recordLeave);
         //查询传入月出差信息
         BusinessTrip businessTrip = new BusinessTrip();
-        businessTrip.setStartTime(DateUtils.convertStringToDate(month + "-" + "01 00:00:00"));
-        businessTrip.setEndTime(DateUtils.convertStringToDate(fin + " 23:59:59"));
+        businessTrip.setStartTime(DateUtils.parseDate(month + "-" + "01 00:00:00"));
+        businessTrip.setEndTime(DateUtils.parseDate(fin + " 23:59:59"));
         businessTrip.setUserId(kaoqinRecord.getUserId());
+        //businessTrip.setIsPass("2");
         List<BusinessTrip> businessTrips = businessTripMapper.selectBusinessTripListLb(businessTrip);
 
+        //查询考勤日期
+        SysDept sysDept = deptMapper.selectDeptById(kaoqinRecord.getDeptId());
+        //查询部门考勤日期规则
+        AttendanceTime attendanceTime = new AttendanceTime();
+        attendanceTime.setDeptName(sysDept.getDeptName());
+        List<AttendanceTime> attendanceTimes = attendanceTimeMapper.selectAttendanceTimeList(attendanceTime);
+
+        String key = "monthHoliday" + kaoqinRecord.getKaYear() + "-" + kaoqinRecord.getKaMonth();
+        String jsonResult = redisCache.getCacheObject(key);
+        Map<String, Integer> holidayMap = new HashMap<>();
+        if(StringUtils.isNotBlank(jsonResult)){
+            Gson gson = new Gson();
+            //判断当天天是否是法定节假日  0 上班 1周末 2节假日 mapKey为去掉-的日期:20250101
+            holidayMap = gson.fromJson(jsonResult,
+                    new TypeToken<Map<String, Integer>>() {
+                    }.getType());
+        }
+
+
+        //获取月份的所有日期
+        List<String> allDate = DateUtils.getAllDateStringsInMonth(Integer.parseInt(kaoqinRecord.getKaYear()), Integer.parseInt(kaoqinRecord.getKaMonth()));
         List list = new ArrayList();
+        Map<String, List<KaoqinRecord>> collect = new HashMap<>();
         if (kaoqinRecords != null && kaoqinRecords.size() > 0) {
-            Map<String, List<KaoqinRecord>> collect = kaoqinRecords.stream().collect(Collectors.groupingBy(KaoqinRecord::getKaTime));
-            for (String date : collect.keySet()) {
+            collect = kaoqinRecords.stream().collect(Collectors.groupingBy(KaoqinRecord::getKaTime));
+        }
 
-                List<RecordLeave> recordList = new ArrayList<>();
-                List<BusinessTrip> businessList = new ArrayList<>();
-                //请假信息
-                for (RecordLeave recordLeaf : recordLeaves) {
-                    if (DateUtils.isDateBetween(DateUtils.convertStringToDate(date), recordLeaf.getStartTime(), recordLeaf.getEndTime())) {
-                        recordList.add(recordLeaf);
-                    }
+        for (String date : allDate) {
 
-                }
-                //出差信息
-                for (BusinessTrip trip : businessTrips) {
-                    if (DateUtils.isDateBetween(DateUtils.convertStringToDate(date), trip.getStartTime(), trip.getEndTime())) {
-                        businessList.add(trip);
+            Map<String, Object> map = new HashMap();
+            //日期
+            map.put("data", date);
+            //1上班 2休息
+            map.put("type", "1");
+            //判断放假还是工作 0 上班 1周末 2节假日
+            if (holidayMap.containsKey(date.replace("-", "")) && 0 != holidayMap.get(date.replace("-", ""))) {
+                map.put("type", "2");
+            }
+            if(attendanceTimes != null && !attendanceTimes.isEmpty()){
+                for (AttendanceTime time : attendanceTimes) {
+                    if(DateUtils.isDateBetween(DateUtils.parseDate(date), time.getStartTime(), time.getEndTime())){
+                        map.put("type", "2");
+                        break;
                     }
+                }
+            }
 
+            List<RecordLeave> recordList = new ArrayList<>();
+            List<BusinessTrip> businessList = new ArrayList<>();
+            //请假信息
+            for (RecordLeave recordLeaf : recordLeaves) {
+                if (DateUtils.isDateBetween(DateUtils.parseDate(date), recordLeaf.getStartTime(), recordLeaf.getEndTime())) {
+                    recordList.add(recordLeaf);
                 }
 
+            }
+            //出差信息
+            for (BusinessTrip trip : businessTrips) {
+                if (DateUtils.isDateBetween(DateUtils.parseDate(date), trip.getStartTime(), trip.getEndTime())) {
+                    businessList.add(trip);
+                }
 
-                Map<String, Object> map = new HashMap();
-                List<KaoqinRecord> kaoqinRecords1 = collect.get(date);
-                //定义标签显示状态
-                String abnormal = "";
+            }
+            //定义标签显示状态
+            String abnormal = "";
+            List<KaoqinRecord> kaoqinRecords1 = new ArrayList<>();
+            if (collect.containsKey(date)) {
+                kaoqinRecords1 = collect.get(date);
                 Boolean flag = true;
                 for (KaoqinRecord record : kaoqinRecords1) {
                     String kaTypeAmIn = record.getKaTypeAmIn();
@@ -253,20 +317,19 @@ public class KaoQinController extends BaseController {
                 } else {
                     abnormal = abnormal.substring(0, abnormal.length() - 1);
                 }
-                //日期
-                map.put("data", date);
-                //标签显示状态
-                map.put("info", abnormal);
-                //打卡记录列表
-                map.put("list", kaoqinRecords1);
-                //补卡信息
-                map.put("bk", cardReplacementCollect.get(date));
-                //请假信息
-                map.put("qj", recordList);
-                //出差信息
-                map.put("cc", businessList);
-                list.add(map);
             }
+
+            //标签显示状态
+            map.put("info", abnormal);
+            //打卡记录列表
+            map.put("list", kaoqinRecords1);
+            //补卡信息
+            map.put("bk", cardReplacementCollect.get(date));
+            //请假信息
+            map.put("qj", recordList);
+            //出差信息
+            map.put("cc", businessList);
+            list.add(map);
         }
         return AjaxResult.success(list);
     }
@@ -392,6 +455,7 @@ public class KaoQinController extends BaseController {
             BigDecimal todayBd = new BigDecimal(todayMap.get(s));
             BigDecimal yesterdayBd = new BigDecimal(yesterdayMap.get(s));
             BigDecimal fz = todayBd.subtract(yesterdayBd);
+            //比较是否等于0,返回true则不等于0,返回false,则等于0
             if (fz.compareTo(BigDecimal.ZERO) != 0) {
                 BigDecimal percentage = BigDecimal.ZERO;
                 //昨天数据>0
@@ -407,7 +471,12 @@ public class KaoQinController extends BaseController {
                     zz = (percentage.multiply(new BigDecimal("-1"))) + "%";
                     ;
                 }
+            } else {
+                if (yesterdayBd.compareTo(BigDecimal.ZERO) == 0) {
+                    zz = "100%";
+                }
             }
+
             mapZj.put("bfb", zz);
             mapZj.put("zf", zt);
             map.put(s, mapZj);
@@ -465,6 +534,10 @@ public class KaoQinController extends BaseController {
                     zz = (percentage.multiply(new BigDecimal("-1"))) + "%";
                     ;
                 }
+            } else {
+                if (yesterdayBd.compareTo(BigDecimal.ZERO) == 0) {
+                    zz = "100%";
+                }
             }
             mapZj.put("bfb", zz);
             mapZj.put("zf", zt);
@@ -579,6 +652,8 @@ public class KaoQinController extends BaseController {
         Long zt = 0L;
         //缺卡打卡次数
         Long qk = 0L;
+        //补卡打卡次数
+        Long bk = 0L;
         //记录该月打卡总人数
         Long count = Long.valueOf(kaoQinRecords.size());
         SysDictData dictData = new SysDictData();
@@ -622,6 +697,7 @@ public class KaoQinController extends BaseController {
         cd = todayMap.get("2");
         zt = todayMap.get("4");
         qk = todayMap.get("5");
+        bk = todayMap.get("6");
 
         map.put("zs", count);
         map.put("zc", zc);
@@ -629,6 +705,7 @@ public class KaoQinController extends BaseController {
         map.put("cd", cd);
         map.put("zt", zt);
         map.put("qk", qk);
+        map.put("bk", bk);
         return map;
     }
 
@@ -644,6 +721,8 @@ public class KaoQinController extends BaseController {
             str = "zt";
         } else if ("5".equals(value)) {
             str = "qk";
+        } else if ("6".equals(value)) {
+            str = "bk";
         }
         return str;
     }
@@ -692,7 +771,7 @@ public class KaoQinController extends BaseController {
             int num = 0;
             if (recordLeaves != null && !recordLeaves.isEmpty()) {
                 for (RecordLeave recordLeaf : recordLeaves) {
-                    if (DateUtils.isDateBetween(DateUtils.convertStringToDate(weekDates.get(i)), recordLeaf.getStartTime(), recordLeaf.getEndTime())) {
+                    if (DateUtils.isDateBetween(DateUtils.parseDate(weekDates.get(i)), recordLeaf.getStartTime(), recordLeaf.getEndTime())) {
                         num++;
                     }
                 }

+ 1 - 2
ruoyi-admin/src/main/java/com/ruoyi/web/controller/kaoqin/KaoqinRecordController.java

@@ -50,8 +50,7 @@ public class KaoqinRecordController extends BaseController
     {
         startPage();
         List<KaoqinRecord> list = kaoqinRecordService.selectKaoqinRecordList(kaoqinRecord);
-        KaoqinConfig kaoqinConfigDept = kaoqinConfigService.selectKaoqinConfigBynew();
-        return getDataTableNum(list,kaoqinConfigDept.getKaNum());
+        return getDataTable(list);
     }
 
     /**

+ 38 - 27
ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysProfileController.java

@@ -24,17 +24,17 @@ import com.ruoyi.common.utils.file.MimeTypeUtils;
 import com.ruoyi.framework.web.service.TokenService;
 import com.ruoyi.system.service.ISysUserService;
 
+import static com.ruoyi.common.constant.Constants.TWO;
 import static com.ruoyi.common.utils.SecurityUtils.checkStrongPwd;
 
 /**
  * 个人信息 业务处理
- * 
+ *
  * @author ruoyi
  */
 @RestController
 @RequestMapping("/system/user/profile")
-public class SysProfileController extends BaseController
-{
+public class SysProfileController extends BaseController {
     @Autowired
     private ISysUserService userService;
 
@@ -45,8 +45,7 @@ public class SysProfileController extends BaseController
      * 个人信息
      */
     @GetMapping
-    public AjaxResult profile()
-    {
+    public AjaxResult profile() {
         LoginUser loginUser = getLoginUser();
         SysUser user = loginUser.getUser();
         AjaxResult ajax = AjaxResult.success(user);
@@ -60,27 +59,23 @@ public class SysProfileController extends BaseController
      */
     @Log(title = "个人信息", businessType = BusinessType.UPDATE)
     @PostMapping("/put")
-    public AjaxResult updateProfile(@RequestBody SysUser user)
-    {
+    public AjaxResult updateProfile(@RequestBody SysUser user) {
         LoginUser loginUser = getLoginUser();
         SysUser sysUser = loginUser.getUser();
         user.setUserName(sysUser.getUserName());
         if (StringUtils.isNotEmpty(user.getPhonenumber())
-                && UserConstants.NOT_UNIQUE.equals(userService.checkPhoneUnique(user)))
-        {
+                && UserConstants.NOT_UNIQUE.equals(userService.checkPhoneUnique(user))) {
             return error("修改用户'" + user.getUserName() + "'失败,手机号码已存在");
         }
         if (StringUtils.isNotEmpty(user.getEmail())
-                && UserConstants.NOT_UNIQUE.equals(userService.checkEmailUnique(user)))
-        {
+                && UserConstants.NOT_UNIQUE.equals(userService.checkEmailUnique(user))) {
             return error("修改用户'" + user.getUserName() + "'失败,邮箱账号已存在");
         }
         user.setUserId(sysUser.getUserId());
         user.setPassword(null);
         user.setAvatar(null);
         user.setDeptId(null);
-        if (userService.updateUserProfile(user) > 0)
-        {
+        if (userService.updateUserProfile(user) > 0) {
             // 更新缓存用户信息
             sysUser.setNickName(user.getNickName());
             sysUser.setPhonenumber(user.getPhonenumber());
@@ -97,25 +92,21 @@ public class SysProfileController extends BaseController
      */
     @Log(title = "个人信息", businessType = BusinessType.UPDATE)
     @PostMapping("/updatePwd")
-    public AjaxResult updatePwd(String oldPassword, String newPassword)
-    {
+    public AjaxResult updatePwd(String oldPassword, String newPassword) {
         LoginUser loginUser = getLoginUser();
         String userName = loginUser.getUsername();
         String password = loginUser.getPassword();
-        if (!SecurityUtils.matchesPassword(oldPassword, password))
-        {
+        if (!SecurityUtils.matchesPassword(oldPassword, password)) {
             return error("修改密码失败,旧密码错误");
         }
-        if (SecurityUtils.matchesPassword(newPassword, password))
-        {
+        if (SecurityUtils.matchesPassword(newPassword, password)) {
             return error("新密码不能与旧密码相同");
         }
 
         if ("1".equals(checkStrongPwd(newPassword))) {
             return AjaxResult.error("密码必须包含数字、大小写字母、特殊符号且大于8位");
         }
-        if (userService.resetUserPwd(userName, SecurityUtils.encryptPassword(newPassword)) > 0)
-        {
+        if (userService.resetUserPwd(userName, SecurityUtils.encryptPassword(newPassword)) > 0) {
             // 更新缓存用户密码
             loginUser.getUser().setPassword(SecurityUtils.encryptPassword(newPassword));
             tokenService.setLoginUser(loginUser);
@@ -129,14 +120,11 @@ public class SysProfileController extends BaseController
      */
     @Log(title = "用户头像", businessType = BusinessType.UPDATE)
     @PostMapping("/avatar")
-    public AjaxResult avatar(@RequestParam("avatarfile") MultipartFile file) throws Exception
-    {
-        if (!file.isEmpty())
-        {
+    public AjaxResult avatar(@RequestParam("avatarfile") MultipartFile file) throws Exception {
+        if (!file.isEmpty()) {
             LoginUser loginUser = getLoginUser();
             String avatar = FileUploadUtils.upload(RuoYiConfig.getAvatarPath(), file, MimeTypeUtils.IMAGE_EXTENSION);
-            if (userService.updateUserAvatar(loginUser.getUsername(), avatar))
-            {
+            if (userService.updateUserAvatar(loginUser.getUsername(), avatar)) {
                 AjaxResult ajax = AjaxResult.success();
                 ajax.put("imgUrl", avatar);
                 // 更新缓存用户头像
@@ -147,4 +135,27 @@ public class SysProfileController extends BaseController
         }
         return error("上传图片异常,请联系管理员");
     }
+
+    /**
+     * 头像上传
+     */
+    @Log(title = "用户头像", businessType = BusinessType.UPDATE)
+    @PostMapping("/face")
+    public AjaxResult face(@RequestParam("file") MultipartFile file, @RequestParam("userId") Long userId,@RequestParam("nickName") String nickName) throws Exception {
+        if (!file.isEmpty()) {
+            String newFileName = userId+"_"+nickName;
+            String face = FileUploadUtils.uploadFileName(RuoYiConfig.getFacePath(), file, MimeTypeUtils.IMAGE_EXTENSION,newFileName);
+            //保存进数据库
+            SysUser user = new SysUser();
+            user.setUserId(userId);
+            user.setFacePhoto(face);
+            user.setFaceType(TWO);
+            userService.updateUserProfile(user);
+            AjaxResult ajax = AjaxResult.success();
+            ajax.put("imgUrl", face);
+            return ajax;
+
+        }
+        return error("上传图片异常,请联系管理员");
+    }
 }

+ 5 - 3
ruoyi-admin/src/main/resources/application-druid.yml

@@ -10,6 +10,8 @@ ruoyi:
     demoEnabled: false
     # 文件路径 示例( Windows配置D:/ruoyi/uploadPath,Linux配置 /home/ruoyi/uploadPath)
     profile: D:/ruoyi/uploadPath
+    # 人脸照片地址
+    faceUrl: D:/face/uploadPath
     # 获取ip地址开关
     addressEnabled: false
     # 验证码类型 math 数组计算 char 字符验证
@@ -36,9 +38,9 @@ spring:
     # redis 配置
     redis:
         # 地址
-        host: 192.168.101.10
+        host: 60.171.161.56
         # 端口,默认为6379
-        port: 6379
+        port: 20001
         # 数据库索引
         database: 12
         # 密码
@@ -61,7 +63,7 @@ spring:
         druid:
             # 主库数据源
             master:
-                url: jdbc:mysql://192.168.101.10:3306/OA_kaoqin?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
+                url: jdbc:mysql://60.171.161.56:25143/OA_kaoqin?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
                 username: root
                 password: Boman123
             # 从库数据源

+ 4 - 2
ruoyi-admin/src/main/resources/application-prod.yml

@@ -8,8 +8,10 @@ ruoyi:
     copyrightYear: 2023
     # 实例演示开关
     demoEnabled: false
-    # 文件路径 示例( Windows配置D:/ruoyi/uploadPath,Linux配置 /home/ruoyi/uploadPath)
-    profile: /home/ruoyi/OA_kaoqin/uploadPath
+    # 文件路径 示例( Windows配置D:/ruoyi/uploadPath,Linux配置 /home/zxy/OA_kaoqin/uploadPath)
+    profile: /home/zxy/OA_kaoqin/uploadPath
+    # 人脸照片地址
+    faceUrl: /home/data/faceRecognition
     # 获取ip地址开关
     addressEnabled: false
     # 验证码类型 math 数组计算 char 字符验证

+ 18 - 1
ruoyi-admin/src/main/resources/application.yml

@@ -41,7 +41,7 @@ token:
     # 令牌密钥
     secret: abcdefghijklmnopqrstuvwxyz
     # 令牌有效期(默认30分钟)
-    expireTime: 30
+    expireTime: 21600
   
 # MyBatis配置
 mybatis:
@@ -73,3 +73,20 @@ xss:
   excludes: /system/notice,/system/app/new
   # 匹配链接
   urlPatterns: /system/*,/monitor/*,/tool/*,/system/app/new
+
+# MQTT配置
+mqtt:
+  #  server-uri: tcp://13.229.167.76:1883
+  #server-uri: tcp://60.171.161.56:20009
+  server-uri: tcp://13.229.167.76:1883
+  #  server-uri: tcp://127.0.0.1:1883
+  client-id: JavaClientBoman
+  username: admin
+  password: 9o0p(O)P
+  default-topic: toServer_punchStat
+  default-qos: 1
+  timeout: 30
+  keep-alive: 60
+  clean-session: true
+  auto-reconnect: true
+  command-timeout: 10

+ 20 - 0
ruoyi-common/src/main/java/com/ruoyi/common/config/RuoYiConfig.java

@@ -27,6 +27,9 @@ public class RuoYiConfig
     /** 上传路径 */
     private static String profile;
 
+    /** 人脸照片地址 */
+    private static String faceUrl;
+
     /** 获取地址开关 */
     private static boolean addressEnabled;
 
@@ -101,6 +104,14 @@ public class RuoYiConfig
         RuoYiConfig.captchaType = captchaType;
     }
 
+    public static String getFaceUrl() {
+        return faceUrl;
+    }
+
+    public void setFaceUrl(String faceUrl) {
+        RuoYiConfig.faceUrl = faceUrl;
+    }
+
     /**
      * 获取导入上传路径
      */
@@ -117,6 +128,15 @@ public class RuoYiConfig
         return getProfile() + "/avatar";
     }
 
+
+    /**
+     * 获取人脸上传路径
+     */
+    public static String getFacePath()
+    {
+        return getFaceUrl() + "/face";
+    }
+
     /**
      * 获取下载路径
      */

+ 16 - 0
ruoyi-common/src/main/java/com/ruoyi/common/constant/Constants.java

@@ -144,4 +144,20 @@ public class Constants
      */
     public static final String[] JOB_ERROR_STR = { "java.net.URL", "javax.naming.InitialContext", "org.yaml.snakeyaml",
             "org.springframework", "org.apache", "com.ruoyi.common.utils.file", "com.ruoyi.common.config" };
+
+
+    /**
+     * 1,2,3,4,5,6,7,8,9,10
+     */
+    public static final String ZERO = "0";
+    public static final String ONE = "1";
+    public static final String TWO = "2";
+    public static final String THREE = "3";
+    public static final String FOUR = "4";
+    public static final String FIVE = "5";
+    public static final String SIX = "6";
+    public static final String SEVEN = "7";
+    public static final String EIGHT = "8";
+    public static final String NINE = "9";
+    public static final String TEN = "10";
 }

+ 11 - 0
ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysUser.java

@@ -55,6 +55,9 @@ public class SysUser extends BaseEntity
     /** 人脸照片 */
     private String facePhoto;
 
+    /** 是否认证 1:已认证,2:未认证 */
+    private String faceType;
+
     /** 密码 */
     private String password;
 
@@ -341,6 +344,14 @@ public class SysUser extends BaseEntity
         this.facePhoto = facePhoto;
     }
 
+    public String getFaceType() {
+        return faceType;
+    }
+
+    public void setFaceType(String faceType) {
+        this.faceType = faceType;
+    }
+
     @Override
     public String toString() {
         return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)

+ 102 - 4
ruoyi-common/src/main/java/com/ruoyi/common/utils/DateUtils.java

@@ -7,10 +7,9 @@ import java.time.*;
 import java.time.format.DateTimeFormatter;
 import java.time.format.DateTimeParseException;
 import java.time.temporal.TemporalAdjusters;
-import java.util.ArrayList;
-import java.util.Calendar;
-import java.util.Date;
-import java.util.List;
+import java.util.*;
+import java.util.stream.Collectors;
+import java.util.stream.IntStream;
 
 import org.apache.commons.lang3.time.DateFormatUtils;
 
@@ -37,6 +36,8 @@ public class DateUtils extends org.apache.commons.lang3.time.DateUtils {
             "yyyy/MM/dd", "yyyy/MM/dd HH:mm:ss", "yyyy/MM/dd HH:mm", "yyyy/MM",
             "yyyy.MM.dd", "yyyy.MM.dd HH:mm:ss", "yyyy.MM.dd HH:mm", "yyyy.MM"};
 
+    private static final DateTimeFormatter TIME_FORMATTER = DateTimeFormatter.ofPattern("HH:mm:ss");
+
     public static String getDateNow() {
         return dateTimeNow(YYYYMMDD);
     }
@@ -341,4 +342,101 @@ public class DateUtils extends org.apache.commons.lang3.time.DateUtils {
         return dates;
     }
 
+    /**
+     * 获取月份所有日期(默认格式 yyyy-MM-dd)
+     */
+    public static List<String> getAllDateStringsInMonth(int year, int month) {
+        return getAllDateStringsInMonth(year, month, "yyyy-MM-dd");
+    }
+
+    /**
+     * 获取月份所有日期(自定义格式)
+     * @param year    年份
+     * @param month   月份 (1-12)
+     * @param pattern 日期格式模式 (如 "yyyy-MM-dd", "MM/dd/yyyy")
+     * @return 日期字符串列表
+     */
+    public static List<String> getAllDateStringsInMonth(int year, int month, String pattern) {
+        YearMonth yearMonth = YearMonth.of(year, month);
+        DateTimeFormatter formatter = DateTimeFormatter.ofPattern(pattern);
+
+        return IntStream.rangeClosed(1, yearMonth.lengthOfMonth())
+                .mapToObj(day -> LocalDate.of(year, month, day))
+                .map(date -> date.format(formatter))
+                .collect(Collectors.toList());
+    }
+
+    /**
+     * 比较两个时间字符串
+     * @param time1 时间字符串1
+     * @param time2 时间字符串2
+     * @param pattern 时间格式(如 "yyyy-MM-dd HH:mm:ss")
+     * @return
+     *   -1:time1 < time2
+     *    0:time1 = time2
+     *    1:time1 > time2
+     * @throws DateTimeParseException 当格式不匹配时抛出异常
+     */
+    public static int compareTimes(String time1, String time2, String pattern) {
+        Objects.requireNonNull(time1, "Time1 cannot be null");
+        Objects.requireNonNull(time2, "Time2 cannot be null");
+
+        DateTimeFormatter formatter = DateTimeFormatter.ofPattern(pattern);
+
+        // 根据格式长度自动判断时间类型
+        if (pattern.contains("y") && pattern.length() <= 10) {
+            LocalDate date1 = LocalDate.parse(time1, formatter);
+            LocalDate date2 = LocalDate.parse(time2, formatter);
+            return date1.compareTo(date2);
+        } else if (!pattern.contains("y")) {
+            LocalTime t1 = LocalTime.parse(time1, formatter);
+            LocalTime t2 = LocalTime.parse(time2, formatter);
+            return t1.compareTo(t2);
+        } else {
+            LocalDateTime dt1 = LocalDateTime.parse(time1, formatter);
+            LocalDateTime dt2 = LocalDateTime.parse(time2, formatter);
+            return dt1.compareTo(dt2);
+        }
+    }
+
+    /**
+     * 检查目标时间是否在时间区间内(包含边界)
+     *
+     * @param target 目标时间 (格式: HH:mm:ss)
+     * @param start 开始时间 (格式: HH:mm:ss)
+     * @param end 结束时间 (格式: HH:mm:ss)
+     * @return
+     *   true - 在区间内(包含边界)
+     *   false - 不在区间内
+     * @throws DateTimeParseException 如果时间格式无效
+     */
+    public static boolean isInTimeRange(String target, String start, String end) {
+        LocalTime targetTime = parseTime(target);
+        LocalTime startTime = parseTime(start);
+        LocalTime endTime = parseTime(end);
+
+        // 处理跨午夜的时间区间(如 23:00 到 01:00)
+        if (startTime.isAfter(endTime)) {
+            // 目标时间在开始时间之后(如 23:30)或在结束时间之前(如 00:30)
+            return targetTime.isAfter(startTime) || targetTime.equals(startTime) ||
+                    targetTime.isBefore(endTime) || targetTime.equals(endTime);
+        } else {
+            // 普通时间区间(不跨午夜)
+            return (targetTime.isAfter(startTime) || targetTime.equals(startTime)) &&
+                    (targetTime.isBefore(endTime) || targetTime.equals(endTime));
+        }
+    }
+
+    // 解析时间字符串
+    private static LocalTime parseTime(String timeStr) {
+        return LocalTime.parse(timeStr, TIME_FORMATTER);
+    }
+
+    public static void main(String[] args) {
+
+        String full1 = "09:30:00";
+        String full2 = "09:30:00";
+        System.out.println(compareTimes(full1, full2, "HH:mm:ss")); // 0
+    }
+
 }

+ 42 - 2
ruoyi-common/src/main/java/com/ruoyi/common/utils/file/FileUploadUtils.java

@@ -28,9 +28,9 @@ public class FileUploadUtils
     public static final long DEFAULT_MAX_SIZE = 50 * 1024 * 1024;
 
     /**
-     * 默认的文件名最大长度 100
+     * 默认的文件名最大长度 200
      */
-    public static final int DEFAULT_FILE_NAME_LENGTH = 100;
+    public static final int DEFAULT_FILE_NAME_LENGTH = 200;
 
     /**
      * 默认上传的地址
@@ -117,6 +117,38 @@ public class FileUploadUtils
         return getPathFileName(baseDir, fileName);
     }
 
+
+    /**
+     * 文件上传,自定义文件名(去除日期路径)
+     *
+     * @param baseDir 相对应用的基目录
+     * @param file 上传的文件
+     * @param allowedExtension 上传文件类型
+     * @return 返回上传成功的文件名
+     * @throws FileSizeLimitExceededException 如果超出最大大小
+     * @throws FileNameLengthLimitExceededException 文件名太长
+     * @throws IOException 比如读写文件出错时
+     * @throws InvalidExtensionException 文件校验异常
+     */
+    public static final String uploadFileName(String baseDir, MultipartFile file, String[] allowedExtension,String fileName)
+            throws FileSizeLimitExceededException, IOException, FileNameLengthLimitExceededException,
+            InvalidExtensionException
+    {
+        int fileNamelength = Objects.requireNonNull(file.getOriginalFilename()).length();
+        if (fileNamelength > FileUploadUtils.DEFAULT_FILE_NAME_LENGTH)
+        {
+            throw new FileNameLengthLimitExceededException(FileUploadUtils.DEFAULT_FILE_NAME_LENGTH);
+        }
+
+        fileName =  StringUtils.format("{}.{}",fileName, getExtension(file));
+        assertAllowed(file, allowedExtension);
+
+        String absPath = getAbsoluteFile(baseDir, fileName).getAbsolutePath();
+        file.transferTo(Paths.get(absPath));
+        return getFacePathFileName(baseDir, fileName);
+    }
+
+
     /**
      * 编码文件名
      */
@@ -147,6 +179,14 @@ public class FileUploadUtils
         return Constants.RESOURCE_PREFIX + "/" + currentDir + "/" + fileName;
     }
 
+    public static final String getFacePathFileName(String uploadDir, String fileName) throws IOException
+    {
+        int dirLastIndex = RuoYiConfig.getFaceUrl().length() + 1;
+        String currentDir = StringUtils.substring(uploadDir, dirLastIndex);
+        return Constants.RESOURCE_PREFIX + "/" + currentDir + "/" + fileName;
+    }
+
+
     /**
      * 文件大小校验
      *

+ 3 - 2
ruoyi-framework/src/main/java/com/ruoyi/framework/config/ResourcesConfig.java

@@ -31,12 +31,13 @@ public class ResourcesConfig implements WebMvcConfigurer
     {
         /** 本地文件上传路径 */
         registry.addResourceHandler(Constants.RESOURCE_PREFIX + "/**")
-                .addResourceLocations("file:" + RuoYiConfig.getProfile() + "/");
+                .addResourceLocations("file:" + RuoYiConfig.getFaceUrl() + "/","file:" + RuoYiConfig.getProfile() + "/");
+
 
         /** swagger配置 */
         registry.addResourceHandler("/swagger-ui/**")
                 .addResourceLocations("classpath:/META-INF/resources/webjars/springfox-swagger-ui/")
-                .setCacheControl(CacheControl.maxAge(5, TimeUnit.HOURS).cachePublic());;
+                .setCacheControl(CacheControl.maxAge(5, TimeUnit.HOURS).cachePublic());
     }
 
     /**

+ 1 - 1
ruoyi-framework/src/main/java/com/ruoyi/framework/config/SecurityConfig.java

@@ -113,7 +113,7 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter
                 // 对于登录login 注册register 验证码captchaImage 允许匿名访问
                 .antMatchers("/login","/loginApp", "/register", "/captchaImage","/index/**","/sms/sendSmsOnly","/sms/getCode","/system/app/new").permitAll()
                 // 静态资源,可匿名访问
-                .antMatchers(HttpMethod.GET, "/", "/*.html", "/**/*.html", "/**/*.css", "/**/*.js", "/profile/**").permitAll()
+                .antMatchers(HttpMethod.GET, "/", "/*.html", "/**/*.html", "/**/*.css", "/**/*.js", "/profile/**","/faceProfile/**").permitAll()
                 .antMatchers("/swagger-ui.html", "/swagger-resources/**", "/webjars/**", "/*/api-docs", "/druid/**").permitAll()
                 // 除上面外的所有请求全部需要鉴权认证
                 .anyRequest().authenticated()

+ 9 - 11
ruoyi-system/src/main/java/com/ruoyi/mqtt/service/MqttMessageListener.java

@@ -1,6 +1,7 @@
 package com.ruoyi.mqtt.service;
 
 import com.ruoyi.common.model.MqttMessage;
+import com.ruoyi.system.service.IKaoqinRecordService;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.context.event.EventListener;
@@ -20,7 +21,8 @@ import org.springframework.stereotype.Component;
 @Component
 public class MqttMessageListener {
 
-
+    @Autowired
+    private IKaoqinRecordService kaoqinRecordService;
 
 
     /**
@@ -35,22 +37,18 @@ public class MqttMessageListener {
         /**
          * 返回值为
          {
-         "userId":"人员id",
-         "time":"时间",
-
-         "photoUrl":"算法截图URL",
+         "filename":"文件名(id_name)",
+         "time":"时间"
          }
          */
 
 
         // 例如:解析JSON消息内容,更新数据库,触发其他操作等
 
-/*        // 可以根据主题进行不同的处理
-        if (message.getTopic().startsWith("device/")) {
-            handleDeviceMessage(message);
-        } else if (message.getTopic().startsWith("alert/")) {
-            handleAlertMessage(message);
-        }*/
+        // 可以根据主题进行不同的处理
+        if (message.getTopic().equals("toServer_punchStat")) {
+            kaoqinRecordService.faceDate(message);
+        }
     }
 
 

+ 2 - 2
ruoyi-system/src/main/java/com/ruoyi/mqtt/service/MqttService.java

@@ -42,7 +42,7 @@ public class MqttService {
      * 在服务启动时订阅默认主题
      */
     @PostConstruct
-    /*public void init() {
+    public void init() {
         // 如果配置了默认主题,则自动订阅
         if (mqttProperties.getDefaultTopic() != null && !mqttProperties.getDefaultTopic().isEmpty()) {
             try {
@@ -53,7 +53,7 @@ public class MqttService {
                 log.error("自动订阅默认主题失败: {}", e.getMessage(), e);
             }
         }
-    }*/
+    }
 
     /**
      * 销毁方法

+ 11 - 0
ruoyi-system/src/main/java/com/ruoyi/system/domain/CardReplacementRecord.java

@@ -59,6 +59,9 @@ public class CardReplacementRecord extends BaseEntity
     @Excel(name = "是否通过 0:未处理,1:不通过,2:通过")
     private String isPass;
 
+    /** 打卡分类 1:上午上班 2:上午下班 3:下午上班 4:下午下班 */
+    private String kaSort;
+
     /** 当前所属部门id合集 */
     private List<Long> deptIds;
 
@@ -168,6 +171,14 @@ public class CardReplacementRecord extends BaseEntity
         this.applicationDate = applicationDate;
     }
 
+    public String getKaSort() {
+        return kaSort;
+    }
+
+    public void setKaSort(String kaSort) {
+        this.kaSort = kaSort;
+    }
+
     @Override
     public String toString() {
         return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)

+ 11 - 0
ruoyi-system/src/main/java/com/ruoyi/system/domain/KaoqinRecord.java

@@ -44,6 +44,9 @@ public class KaoqinRecord extends BaseEntity
 
     private String ancestors;
 
+    /***今日考勤配置次数*/
+    private String kaNum;
+
     /** 打卡时间 年 */
     @Excel(name = "打卡时间 年")
     private String kaYear;
@@ -510,6 +513,14 @@ public class KaoqinRecord extends BaseEntity
         this.endTime = endTime;
     }
 
+    public String getKaNum() {
+        return kaNum;
+    }
+
+    public void setKaNum(String kaNum) {
+        this.kaNum = kaNum;
+    }
+
     @Override
     public String toString() {
         return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)

+ 3 - 0
ruoyi-system/src/main/java/com/ruoyi/system/mapper/KaoqinRecordMapper.java

@@ -1,6 +1,7 @@
 package com.ruoyi.system.mapper;
 
 import com.ruoyi.system.domain.KaoqinRecord;
+import org.apache.ibatis.annotations.Param;
 
 import java.util.List;
 
@@ -59,4 +60,6 @@ public interface KaoqinRecordMapper
      * @return 结果
      */
     public int deleteKaoqinRecordByRecordIds(Long[] recordIds);
+
+    public KaoqinRecord selectKaoqinRecordByRecordByUser(@Param("userId")Long userId, @Param("date")String date);
 }

+ 3 - 0
ruoyi-system/src/main/java/com/ruoyi/system/service/IKaoqinRecordService.java

@@ -1,5 +1,6 @@
 package com.ruoyi.system.service;
 
+import com.ruoyi.common.model.MqttMessage;
 import com.ruoyi.system.domain.KaoqinRecord;
 
 import java.util.List;
@@ -59,4 +60,6 @@ public interface IKaoqinRecordService
      * @return 结果
      */
     public int deleteKaoqinRecordByRecordId(Long recordId);
+
+    void faceDate(MqttMessage message);
 }

+ 93 - 8
ruoyi-system/src/main/java/com/ruoyi/system/service/Task.java

@@ -1,12 +1,18 @@
 package com.ruoyi.system.service;
 
 
+import com.google.gson.Gson;
+import com.google.gson.reflect.TypeToken;
+import com.ruoyi.common.constant.Constants;
 import com.ruoyi.common.core.domain.entity.SysUser;
+import com.ruoyi.common.core.redis.RedisCache;
 import com.ruoyi.common.utils.DateUtils;
 import com.ruoyi.common.utils.HolidayUtils;
 import com.ruoyi.system.domain.AttendanceTime;
+import com.ruoyi.system.domain.KaoqinConfig;
 import com.ruoyi.system.domain.KaoqinRecord;
 import com.ruoyi.system.mapper.AttendanceTimeMapper;
+import com.ruoyi.system.mapper.KaoqinConfigMapper;
 import com.ruoyi.system.mapper.KaoqinRecordMapper;
 import com.ruoyi.system.mapper.SysUserMapper;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -14,11 +20,15 @@ import org.springframework.scheduling.annotation.Async;
 import org.springframework.scheduling.annotation.Scheduled;
 import org.springframework.stereotype.Component;
 
+import javax.annotation.PostConstruct;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Map;
+import java.util.concurrent.TimeUnit;
 import java.util.stream.Collectors;
 
+import static com.ruoyi.common.constant.Constants.*;
+
 @Component
 public class Task {
 
@@ -28,6 +38,10 @@ public class Task {
     private KaoqinRecordMapper kaoqinRecordMapper;
     @Autowired
     private AttendanceTimeMapper attendanceTimeMapper;
+    @Autowired
+    private KaoqinConfigMapper kaoqinConfigMapper;
+    @Autowired
+    private RedisCache redisCache;
 
     /***
      * 定时插入未打卡数据
@@ -45,11 +59,13 @@ public class Task {
             //是节假日的话不需要插入数据,直接返回
             return;
         }
-        //查询考勤规则
+        //查询考勤日期规则
         AttendanceTime attendanceTime = new AttendanceTime();
         List<AttendanceTime> attendanceTimes = attendanceTimeMapper.selectAttendanceTimeList(attendanceTime);
         //根据部门分类
         //Map<Long, List<AttendanceTime>> collect = attendanceTimes.stream().collect(Collectors.groupingBy(AttendanceTime::getDeptId));
+        KaoqinConfig kaoqinConfig = kaoqinConfigMapper.selectKaoqinConfigBynew();
+
         //获取所有有部门的人员
         List<SysUser> userList = userMapper.selectUserListNoDept();
         //获取前一天的所有考勤记录
@@ -60,13 +76,13 @@ public class Task {
             boolean blt = false;
             if(attendanceTimes != null && !attendanceTimes.isEmpty()){
                 for (AttendanceTime time : attendanceTimes) {
-                    if(time.getDeptName().contains(sysUser.getDept().getDeptName()) && DateUtils.isDateBetween(DateUtils.convertStringToDate(data), time.getStartTime(), time.getEndTime())){
+                    if(time.getDeptName().contains(sysUser.getDept().getDeptName()) && DateUtils.isDateBetween(DateUtils.parseDate(data), time.getStartTime(), time.getEndTime())){
                         blt = true;
                         break;
                     }
                 }
             }
-            if(!blt){
+            if(blt){
                 continue;
             }
             boolean bl = true;
@@ -90,11 +106,14 @@ public class Task {
                 kaoqinRecords.setKaDay(datas[2]);
                 kaoqinRecords.setKaWeek(DateUtils.dateToWeek(data));
                 kaoqinRecords.setKaTime(data);
-                kaoqinRecords.setKaTypeAmIn("5");
-                kaoqinRecords.setKaTypeAmOut("5");
-                kaoqinRecords.setKaTypePmIn("5");
-                kaoqinRecords.setKaTypePmOut("5");
-                kaoqinRecords.setKaStatus("2");
+                kaoqinRecords.setKaTypeAmIn(FIVE);
+                kaoqinRecords.setKaNum(kaoqinConfig.getKaNum());
+                if (kaoqinConfig!=null && "4".equals(kaoqinConfig.getKaNum())) {
+                    kaoqinRecords.setKaTypeAmOut(FIVE);
+                    kaoqinRecords.setKaTypePmIn(FIVE);
+                }
+                kaoqinRecords.setKaTypePmOut(FIVE);
+                kaoqinRecords.setKaStatus(TWO);
                 kaoqinRecords.setCreateTime(DateUtils.getNowDate());
                 kaoqinRecordMapper.insertKaoqinRecord(kaoqinRecords);
             }
@@ -108,5 +127,71 @@ public class Task {
         System.out.println(data);
     }*/
 
+    /***
+     * 定时插入未打卡数据
+     */
+    @Async
+    //@Scheduled(cron = "0 0/2 * * * ? ")
+    @Scheduled(cron = "0 0 2 25 * ? ")
+    public void getHoliday() {
+        //获取当前年份
+        int year=Integer.parseInt(DateUtils.getYear());
+        int month=Integer.parseInt(DateUtils.justMonth());
+        if(month==12){
+            year = year +1;
+            month = 1;
+        }else{
+            month = month + 1;
+        }
+        //查询下一个月份的放假信息
+        List<String> allDate = DateUtils.getAllDateStringsInMonth(year, month);
+        String dateList = String.join(",", allDate);
+        String jsonResult = HolidayUtils.request(dateList);
+        String key = "monthHoliday"+year+"-"+month;
+        //保存两个月时间
+        redisCache.setCacheObject(key,jsonResult);
+
+        System.out.println(jsonResult);
+
+    }
+
+    /***
+     * 项目初始化时缓存当前月和下一个月的放假信息
+     * @throws InterruptedException
+     */
+    @PostConstruct
+    public void init() throws InterruptedException {
+        //获取当前年份
+        String year=DateUtils.getYear();
+        String month=DateUtils.justMonth();
+        //查询当前月份的放假信息
+        List<String> allDateDq = DateUtils.getAllDateStringsInMonth(Integer.parseInt(year), Integer.parseInt(month));
+        String dateListDq = String.join(",", allDateDq);
+        String jsonResultDq = HolidayUtils.request(dateListDq);
+        String keyDq = "monthHoliday"+year+"-"+month;
+        //保存两个月时间
+        redisCache.setCacheObject(keyDq,jsonResultDq);
+        //睡眠1.1秒(获取假期接口限制),每秒最多访问2次
+        Thread.sleep(1100);
+
+        //查询下一个月份的放假信息
+        if("12".equals(month)){
+            year = String.valueOf(Integer.parseInt(year) + 1);
+            month = "01";
+        }else{
+            month = String.valueOf(Integer.parseInt(month) + 1);
+            if(Integer.parseInt(month)<10){
+                month = "0"+month;
+            }
+        }
+        List<String> allDate = DateUtils.getAllDateStringsInMonth(Integer.parseInt(year), Integer.parseInt(month));
+        String dateList = String.join(",", allDate);
+        String jsonResult = HolidayUtils.request(dateList);
+        String key = "monthHoliday"+year+"-"+month;
+        //保存两个月时间
+        redisCache.setCacheObject(key,jsonResult);
+    }
+
+
 
 }

+ 1 - 0
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/BusinessTripServiceImpl.java

@@ -91,6 +91,7 @@ public class BusinessTripServiceImpl implements IBusinessTripService
         int index = businessTripMapper.insertBusinessTrip(businessTrip);
 
         BusinessUser bu = new BusinessUser();
+        bu.setBusinessId(businessTrip.getId());
         bu.setAbsenteeId(user.getUserId());
         bu.setAbsenteeName(user.getNickName());
         bu.setDeptId(user.getDeptId());

+ 55 - 1
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/CardReplacementRecordServiceImpl.java

@@ -10,7 +10,9 @@ import com.ruoyi.common.exception.ServiceException;
 import com.ruoyi.common.utils.DateUtils;
 import com.ruoyi.common.utils.SecurityUtils;
 import com.ruoyi.common.utils.StringUtils;
+import com.ruoyi.system.domain.KaoqinRecord;
 import com.ruoyi.system.domain.ProcessConfiguration;
+import com.ruoyi.system.mapper.KaoqinRecordMapper;
 import com.ruoyi.system.mapper.ProcessConfigurationMapper;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
@@ -18,6 +20,8 @@ import com.ruoyi.system.mapper.CardReplacementRecordMapper;
 import com.ruoyi.system.domain.CardReplacementRecord;
 import com.ruoyi.system.service.ICardReplacementRecordService;
 
+import static com.ruoyi.common.constant.Constants.*;
+
 /**
  * 补卡记录Service业务层处理
  * 
@@ -33,6 +37,9 @@ public class CardReplacementRecordServiceImpl implements ICardReplacementRecordS
     @Autowired
     private ProcessConfigurationMapper processConfigurationMapper;
 
+    @Autowired
+    private KaoqinRecordMapper kaoqinRecordMapper;
+
     /**
      * 查询补卡记录
      * 
@@ -124,6 +131,53 @@ public class CardReplacementRecordServiceImpl implements ICardReplacementRecordS
     public int putPass(CardReplacementRecord cardReplacementRecord) {
         //获取当前人员信息
         SysUser user = SecurityUtils.getLoginUser().getUser();
+        //查询打卡信息
+        if(TWO.equals(cardReplacementRecord.getIsPass())){
+            String date = DateUtils.getDate();
+            KaoqinRecord kaoqinRecord = kaoqinRecordMapper.selectKaoqinRecordByRecordByUser(user.getUserId(),date);
+            if(kaoqinRecord != null){
+                if(ONE.equals(cardReplacementRecord.getKaSort())){
+                    kaoqinRecord.setKaTypeAmIn(SIX);
+                } else if (TWO.equals(cardReplacementRecord.getKaSort())) {
+                    kaoqinRecord.setKaTypeAmOut(SIX);
+                } else if (THREE.equals(cardReplacementRecord.getKaSort())) {
+                    kaoqinRecord.setKaTypePmIn(SIX);
+                } else if (FOUR.equals(cardReplacementRecord.getKaSort())) {
+                    kaoqinRecord.setKaTypePmOut(SIX);
+                }
+                kaoqinRecordMapper.updateKaoqinRecord(kaoqinRecord);
+            }else{
+                kaoqinRecord = new KaoqinRecord();
+                //将日期拆分成年月日的数组
+                String[] datas = date.split("-");
+                KaoqinRecord kaoqinRecords = new KaoqinRecord();
+                kaoqinRecords.setUserId(user.getUserId());
+                kaoqinRecords.setUserName(user.getNickName());
+                kaoqinRecords.setPhone(user.getPhonenumber());
+                kaoqinRecords.setDeptId(user.getDeptId());
+                kaoqinRecords.setDeptName(user.getDept().getDeptName());
+                kaoqinRecords.setAncestors(user.getDept().getAncestors());
+                kaoqinRecords.setKaYear(datas[0]);
+                kaoqinRecords.setKaMonth(datas[1]);
+                kaoqinRecords.setKaDay(datas[2]);
+                kaoqinRecords.setKaWeek(DateUtils.dateToWeek(date));
+                kaoqinRecords.setKaTime(date);
+                kaoqinRecords.setKaStatus(TWO);
+                if(ONE.equals(cardReplacementRecord.getKaSort())){
+                    kaoqinRecord.setKaTypeAmIn(SIX);
+                } else if (TWO.equals(cardReplacementRecord.getKaSort())) {
+                    kaoqinRecord.setKaTypeAmOut(SIX);
+                } else if (THREE.equals(cardReplacementRecord.getKaSort())) {
+                    kaoqinRecord.setKaTypePmIn(SIX);
+                } else if (FOUR.equals(cardReplacementRecord.getKaSort())) {
+                    kaoqinRecord.setKaTypePmOut(SIX);
+                }
+                kaoqinRecords.setCreateTime(DateUtils.getNowDate());
+                kaoqinRecordMapper.insertKaoqinRecord(kaoqinRecord);
+            }
+
+        }
+
         cardReplacementRecord.setExaminersId(user.getUserId());
         cardReplacementRecord.setExaminersName(user.getNickName());
         return cardReplacementRecordMapper.updateCardReplacementRecord(cardReplacementRecord);
@@ -137,7 +191,7 @@ public class CardReplacementRecordServiceImpl implements ICardReplacementRecordS
             //获取当前人员补卡配置所在的部门id
             ProcessConfiguration processConfiguration = new ProcessConfiguration();
             processConfiguration.setUserId(user.getUserId());
-            processConfiguration.setType("1");
+            processConfiguration.setType(ONE);
             List<ProcessConfiguration> list = processConfigurationMapper.selectProcessConfigurationList(processConfiguration);
             List<Long> deptIds = list.stream().map(ProcessConfiguration::getDeptId).collect(Collectors.toList());
             cardReplacementRecord.setDeptIds(deptIds);

+ 132 - 0
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/KaoqinRecordServiceImpl.java

@@ -2,15 +2,23 @@ package com.ruoyi.system.service.impl;
 
 import java.util.List;
 
+import com.alibaba.fastjson2.JSONObject;
 import com.ruoyi.common.core.domain.entity.SysUser;
+import com.ruoyi.common.model.MqttMessage;
 import com.ruoyi.common.utils.DateUtils;
 import com.ruoyi.common.utils.SecurityUtils;
+import com.ruoyi.system.domain.KaoqinConfig;
 import com.ruoyi.system.domain.KaoqinRecord;
+import com.ruoyi.system.mapper.KaoqinConfigMapper;
 import com.ruoyi.system.mapper.KaoqinRecordMapper;
+import com.ruoyi.system.mapper.SysUserMapper;
 import com.ruoyi.system.service.IKaoqinRecordService;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.scheduling.annotation.Async;
 import org.springframework.stereotype.Service;
 
+import static com.ruoyi.common.constant.Constants.*;
+
 
 /**
  * 考勤记录Service业务层处理
@@ -24,6 +32,12 @@ public class KaoqinRecordServiceImpl implements IKaoqinRecordService
     @Autowired
     private KaoqinRecordMapper kaoqinRecordMapper;
 
+    @Autowired
+    private KaoqinConfigMapper kaoqinConfigMapper;
+
+    @Autowired
+    private SysUserMapper sysUserMapper;
+
     /**
      * 查询考勤记录
      * 
@@ -104,4 +118,122 @@ public class KaoqinRecordServiceImpl implements IKaoqinRecordService
     {
         return kaoqinRecordMapper.deleteKaoqinRecordByRecordId(recordId);
     }
+
+    @Async("threadPoolTaskExecutor")
+    @Override
+    public void faceDate(MqttMessage message) {
+        /**
+         * 返回值为
+         {
+         "filename":"文件名(id_name)",
+         "time":"时间 (yyyy-MM-dd HH:mm:ss)"
+         }
+         */
+        String payload = message.getPayload();
+        JSONObject jsonObject = JSONObject.parseObject(payload);
+        String filename = jsonObject.getString("filename");
+        String time = jsonObject.getString("time");
+        String userId = filename.split("_")[0];
+        String nickName = filename.split("_")[1];
+        String date = time.split(" ")[0];
+        //查询打卡信息
+        KaoqinRecord kaoqinRecord = kaoqinRecordMapper.selectKaoqinRecordByRecordByUser(Long.getLong(userId),date);
+        //查询考勤规则
+        KaoqinConfig kaoqinConfig = kaoqinConfigMapper.selectKaoqinConfigBynew();
+        if(kaoqinRecord == null){
+            //根据id查询人员信息
+            SysUser sysUser = sysUserMapper.selectUserById(Long.getLong(userId));
+            String[] dates = date.split("-");
+            KaoqinRecord kaoqinRecords = new KaoqinRecord();
+            kaoqinRecords.setUserId(Long.getLong(userId));
+            kaoqinRecords.setUserName(sysUser.getNickName());
+            kaoqinRecords.setPhone(sysUser.getPhonenumber());
+            kaoqinRecords.setDeptId(sysUser.getDeptId());
+            kaoqinRecords.setDeptName(sysUser.getDept().getDeptName());
+            kaoqinRecords.setAncestors(sysUser.getDept().getAncestors());
+            kaoqinRecords.setKaYear(dates[0]);
+            kaoqinRecords.setKaMonth(dates[1]);
+            kaoqinRecords.setKaDay(dates[2]);
+            kaoqinRecords.setKaWeek(DateUtils.dateToWeek(date));
+            kaoqinRecords.setKaTime(date);
+            kaoqinRecords.setCreateTime(DateUtils.getNowDate());
+            //此次打卡为第一次打卡
+            //判断是否在上班卡之前打卡
+            if(DateUtils.compareTimes(time.split(" ")[1],DateUtils.parseDateToStr("HH:mm:ss",kaoqinConfig.getKaTimeAmIn()),"HH:mm:ss")<=0){
+                //在上班之前打卡
+                kaoqinRecords.setKaTimeAmIn(DateUtils.parseDate(time));
+                kaoqinRecords.setKaTypeAmIn(ONE);
+                kaoqinRecords.setKaStatus(ONE);
+
+            }else{
+                //在上班之后打卡
+                //判断配置要打几次卡
+                if(TWO.equals(kaoqinConfig.getKaNum())){
+                    if(DateUtils.compareTimes(time.split(" ")[1],DateUtils.parseDateToStr("HH:mm:ss",kaoqinConfig.getKaTimePmOut()),"HH:mm:ss")>=0){
+                        //正常下班
+                        kaoqinRecords.setKaTimePmOut(DateUtils.parseDate(time));
+                        kaoqinRecords.setKaTypePmOut(ONE);
+                    }else{
+                        //迟到
+                        kaoqinRecords.setKaTimeAmIn(DateUtils.parseDate(time));
+                        kaoqinRecords.setKaTypeAmIn(TWO);
+                    }
+
+                }else if(FOUR.equals(kaoqinConfig.getKaNum())){
+                    if(DateUtils.compareTimes(time.split(" ")[1],DateUtils.parseDateToStr("HH:mm:ss",kaoqinConfig.getKaTimeAmOut()),"HH:mm:ss")<0){
+                        //正常下班
+                        kaoqinRecords.setKaTimeAmIn(DateUtils.parseDate(time));
+                        kaoqinRecords.setKaTypeAmIn(TWO);
+                    }else if(DateUtils.isInTimeRange(time.split(" ")[1],DateUtils.parseDateToStr("HH:mm:ss",kaoqinConfig.getKaTimeAmOut()), DateUtils.parseDateToStr("HH:mm:ss",kaoqinConfig.getKaTimeAmIn()))){
+                        kaoqinRecords.setKaTimePmIn(DateUtils.parseDate(time));
+                        kaoqinRecords.setKaTypePmIn(ONE);
+                    }else if(DateUtils.isInTimeRange(time.split(" ")[1],DateUtils.parseDateToStr("HH:mm:ss",kaoqinConfig.getKaTimePmIn()), DateUtils.parseDateToStr("HH:mm:ss",kaoqinConfig.getKaTimePmOut()))){
+                        kaoqinRecords.setKaTimePmIn(DateUtils.parseDate(time));
+                        kaoqinRecords.setKaTypePmIn(TWO);
+                    }else if(DateUtils.compareTimes(time.split(" ")[1],DateUtils.parseDateToStr("HH:mm:ss",kaoqinConfig.getKaTimePmOut()),"HH:mm:ss")>=0){
+                        kaoqinRecords.setKaTimePmOut(DateUtils.parseDate(time));
+                        kaoqinRecords.setKaTypePmOut(ONE);
+                    }
+                }
+            }
+            kaoqinRecordMapper.insertKaoqinRecord(kaoqinRecords);
+        }else{
+            if(DateUtils.compareTimes(time.split(" ")[1],DateUtils.parseDateToStr("HH:mm:ss",kaoqinConfig.getKaTimeAmIn()),"HH:mm:ss")<=0){
+                //在上班之前打卡
+                kaoqinRecord.setKaTimeAmIn(DateUtils.parseDate(time));
+                kaoqinRecord.setKaTypeAmIn(ONE);
+                kaoqinRecord.setKaStatus(ONE);
+
+            }else{
+                if(TWO.equals(kaoqinConfig.getKaNum())){
+                    if(DateUtils.compareTimes(time.split(" ")[1],DateUtils.parseDateToStr("HH:mm:ss",kaoqinConfig.getKaTimePmOut()),"HH:mm:ss")>=0){
+                        //正常下班
+                        kaoqinRecord.setKaTimePmOut(DateUtils.parseDate(time));
+                        kaoqinRecord.setKaTypePmOut(ONE);
+                    }else{
+                        //迟到
+                        kaoqinRecord.setKaTimePmOut(DateUtils.parseDate(time));
+                        kaoqinRecord.setKaTypePmOut(FOUR);
+                    }
+
+                }else if(FOUR.equals(kaoqinConfig.getKaNum())){
+                    if(DateUtils.compareTimes(time.split(" ")[1],DateUtils.parseDateToStr("HH:mm:ss",kaoqinConfig.getKaTimeAmOut()),"HH:mm:ss")<0){
+                        //正常下班
+                        kaoqinRecord.setKaTimeAmIn(DateUtils.parseDate(time));
+                        kaoqinRecord.setKaTypeAmIn(TWO);
+                    }else if(DateUtils.isInTimeRange(time.split(" ")[1],DateUtils.parseDateToStr("HH:mm:ss",kaoqinConfig.getKaTimeAmOut()), DateUtils.parseDateToStr("HH:mm:ss",kaoqinConfig.getKaTimeAmIn()))){
+                        kaoqinRecord.setKaTimePmIn(DateUtils.parseDate(time));
+                        kaoqinRecord.setKaTypePmIn(ONE);
+                    }else if(DateUtils.isInTimeRange(time.split(" ")[1],DateUtils.parseDateToStr("HH:mm:ss",kaoqinConfig.getKaTimePmIn()), DateUtils.parseDateToStr("HH:mm:ss",kaoqinConfig.getKaTimePmOut()))){
+                        kaoqinRecord.setKaTimePmIn(DateUtils.parseDate(time));
+                        kaoqinRecord.setKaTypePmIn(TWO);
+                    }else if(DateUtils.compareTimes(time.split(" ")[1],DateUtils.parseDateToStr("HH:mm:ss",kaoqinConfig.getKaTimePmOut()),"HH:mm:ss")>=0){
+                        kaoqinRecord.setKaTimePmOut(DateUtils.parseDate(time));
+                        kaoqinRecord.setKaTypePmOut(ONE);
+                    }
+                }
+            }
+            kaoqinRecordMapper.updateKaoqinRecord(kaoqinRecord);
+        }
+    }
 }

+ 2 - 2
ruoyi-system/src/main/resources/mapper/system/BusinessTripMapper.xml

@@ -85,10 +85,10 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="isPass != null  and isPass != ''"> and t.is_pass = #{isPass}</if>
             <if test="submitTime != null "> and t.submit_time = #{submitTime}</if>
             <if test="startTime != null ">
-                AND date_format(start_time,'%y%m%d %H:%i:%s') &gt;=  date_format(#{startTime},'%y%m%d %H:%i:%s')
+                AND date_format(t.start_time,'%y%m%d %H:%i:%s') &gt;=  date_format(#{startTime},'%y%m%d %H:%i:%s')
             </if>
             <if test="endTime != null ">
-                AND date_format(end_time,'%y%m%d %H:%i:%s') &lt;=  date_format(#{endTime},'%y%m%d %H:%i:%s')
+                AND date_format(t.end_time,'%y%m%d %H:%i:%s') &lt;=  date_format(#{endTime},'%y%m%d %H:%i:%s')
             </if>
         </where>
         order by t.is_pass, t.submit_time desc

+ 6 - 1
ruoyi-system/src/main/resources/mapper/system/CardReplacementRecordMapper.xml

@@ -16,11 +16,12 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         <result property="examinersId"    column="examiners_id"    />
         <result property="examinersName"    column="examiners_name"    />
         <result property="isPass"    column="is_pass"    />
+        <result property="kaSort"    column="ka_sort"    />
         <result property="createTime" column="create_time" />
     </resultMap>
 
     <sql id="selectCardReplacementRecordVo">
-        select id, user_id, user_name, dept_id,dept_name, application_time,application_date, reason, examiners_id, examiners_name, is_pass,create_time from card_replacement_record
+        select id, user_id, user_name, dept_id,dept_name, application_time,application_date, reason, examiners_id, examiners_name, is_pass,ka_sort,create_time from card_replacement_record
     </sql>
 
     <select id="selectCardReplacementRecordList" parameterType="CardReplacementRecord" resultMap="CardReplacementRecordResult">
@@ -35,6 +36,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="reason != null  and reason != ''"> and reason = #{reason}</if>
             <if test="examinersName != null  and examinersName != ''"> and examiners_name like concat('%', #{examinersName}, '%')</if>
             <if test="isPass != null  and isPass != ''"> and is_pass = #{isPass}</if>
+            <if test="kaSort != null  and kaSort != ''"> and ka_sort = #{kaSort}</if>
             <if test="deptIds!=null and deptIds.size() >0">
                 and dept_id in
                 <foreach item="deptId" collection="deptIds" open="(" separator="," close=")">
@@ -67,6 +69,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="examinersId != null">examiners_id,</if>
             <if test="examinersName != null">examiners_name,</if>
             <if test="isPass != null">is_pass,</if>
+            <if test="kaSort != null ">ka_sort,</if>
             create_time
          </trim>
         <trim prefix="values (" suffix=")" suffixOverrides=",">
@@ -80,6 +83,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="examinersId != null">#{examinersId},</if>
             <if test="examinersName != null">#{examinersName},</if>
             <if test="isPass != null">#{isPass},</if>
+            <if test="kaSort != null ">#{kaSort},</if>
             sysdate()
          </trim>
     </insert>
@@ -97,6 +101,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="examinersId != null">examiners_id = #{examinersId},</if>
             <if test="examinersName != null">examiners_name = #{examinersName},</if>
             <if test="isPass != null">is_pass = #{isPass},</if>
+            <if test="kaSort != null">ka_sort = #{kaSort},</if>
         </trim>
         where id = #{id}
     </update>

+ 1 - 0
ruoyi-system/src/main/resources/mapper/system/KaoqinConfigMapper.xml

@@ -46,6 +46,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="kaTimePmOut != null "> and ka_time_pm_out = #{kaTimePmOut}</if>
             <if test="isPhoto != null and isPhoto!= ''"> and is_photo = #{isPhoto}</if>
         </where>
+        order by update_time desc
     </select>
     
     <select id="selectKaoqinConfigByKaoqinId" parameterType="Long" resultMap="KaoqinConfigResult">

+ 15 - 4
ruoyi-system/src/main/resources/mapper/system/KaoqinRecordMapper.xml

@@ -12,6 +12,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         <result property="deptId"    column="dept_id"    />
         <result property="deptName"    column="dept_name"    />
         <result property="ancestors"    column="ancestors"    />
+        <result property="kaNum"    column="ka_num"    />
         <result property="kaYear"    column="ka_year"    />
         <result property="kaMonth"    column="ka_month"    />
         <result property="kaDay"    column="ka_day"    />
@@ -32,8 +33,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         <result property="kaTypeAmOut"    column="ka_type_am_out"    />
         <result property="kaTypePmIn"    column="ka_type_pm_in"    />
         <result property="kaTypePmOut"    column="ka_type_pm_out"    />
-        <result property="kaAmInPhoto"    column="ka_am_out_photo"    />
-        <result property="kaAmOutPhoto"    column="ka_type_pm_photo"    />
+        <result property="kaAmInPhoto"    column="ka_am_in_photo"    />
+        <result property="kaAmOutPhoto"    column="ka_am_out_photo"    />
         <result property="kaPmInPhoto"    column="ka_pm_in_photo"    />
         <result property="kaPmOutPhoto"    column="ka_pm_out_photo"    />
         <result property="kaStatus"    column="ka_status"    />
@@ -48,7 +49,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
     </resultMap>
 
     <sql id="selectKaoqinRecordVo">
-        select record_id, user_id, user_name,phone, dept_id, dept_name, ancestors, ka_year, ka_month, ka_day, ka_week, ka_time, ka_address_am_in, ka_log, ka_lat, ka_sort, ka_address_am_out, ka_address_pm_in, ka_address_pm_out, ka_time_am_in, ka_time_am_out, ka_time_pm_in, ka_time_pm_out, ka_type_am_in, ka_type_am_out, ka_type_pm_in, ka_type_pm_out,ka_am_in_photo,ka_am_out_photo,ka_pm_in_photo,ka_pm_out_photo, ka_status, create_by, create_time, update_by, update_time, remark_am_in, remark_am_out, remark_pm_in, remark_pm_out from kaoqin_record
+        select record_id, user_id, user_name,phone, dept_id, dept_name, ancestors,ka_num, ka_year, ka_month, ka_day, ka_week, ka_time, ka_address_am_in, ka_log, ka_lat, ka_sort, ka_address_am_out, ka_address_pm_in, ka_address_pm_out, ka_time_am_in, ka_time_am_out, ka_time_pm_in, ka_time_pm_out, ka_type_am_in, ka_type_am_out, ka_type_pm_in, ka_type_pm_out,ka_am_in_photo,ka_am_out_photo,ka_pm_in_photo,ka_pm_out_photo, ka_status, create_by, create_time, update_by, update_time, remark_am_in, remark_am_out, remark_pm_in, remark_pm_out from kaoqin_record
     </sql>
 
     <select id="selectKaoqinRecordList" parameterType="KaoqinRecord" resultMap="KaoqinRecordResult">
@@ -59,6 +60,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="phone != null  and phone != ''"> and phone = #{phone}</if>
             <if test="deptName != null  and deptName != ''"> and dept_name like concat( #{deptName}, '%')</if>
             <if test="deptId != null  and deptId != ''"> and find_in_set(#{deptId}, ancestors)</if>
+            <if test="kaNum != null  and kaNum != ''"> and ka_num = #{kaNum}</if>
             <if test="kaYear != null  and kaYear != ''"> and ka_year = #{kaYear}</if>
             <if test="kaMonth != null  and kaMonth != ''"> and ka_month = #{kaMonth}</if>
             <if test="kaDay != null  and kaDay != ''"> and ka_day = #{kaDay}</if>
@@ -93,13 +95,19 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="remarkPmIn != null  and remarkPmIn != ''"> and remark_pm_in = #{remarkPmIn}</if>
             <if test="remarkPmOut != null  and remarkPmOut != ''"> and remark_pm_out = #{remarkPmOut}</if>
         </where>
+        order by ka_time desc
     </select>
     
     <select id="selectKaoqinRecordByRecordId" parameterType="Long" resultMap="KaoqinRecordResult">
         <include refid="selectKaoqinRecordVo"/>
         where record_id = #{recordId}
     </select>
-        
+
+    <select id="selectKaoqinRecordByRecordByUser" parameterType="KaoqinRecord" resultMap="KaoqinRecordResult">
+        <include refid="selectKaoqinRecordVo"/>
+        where user_id = #{userId} and ka_time = #{date} limit 1
+    </select>
+
     <insert id="insertKaoqinRecord" parameterType="KaoqinRecord" useGeneratedKeys="true" keyProperty="recordId">
         insert into kaoqin_record
         <trim prefix="(" suffix=")" suffixOverrides=",">
@@ -109,6 +117,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="deptId != null">dept_id,</if>
             <if test="deptName != null">dept_name,</if>
             <if test="ancestors != null">ancestors,</if>
+            <if test="kaNum != null">ka_num ,</if>
             <if test="kaYear != null and kaYear != ''">ka_year,</if>
             <if test="kaMonth != null and kaMonth != ''">ka_month,</if>
             <if test="kaDay != null and kaDay != ''">ka_day,</if>
@@ -150,6 +159,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="deptId != null">#{deptId},</if>
             <if test="deptName != null">#{deptName},</if>
             <if test="ancestors != null">#{ancestors},</if>
+            <if test="kaNum != null">#{kaNum},</if>
             <if test="kaYear != null and kaYear != ''">#{kaYear},</if>
             <if test="kaMonth != null and kaMonth != ''">#{kaMonth},</if>
             <if test="kaDay != null and kaDay != ''">#{kaDay},</if>
@@ -195,6 +205,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="deptId != null">dept_id = #{deptId},</if>
             <if test="deptName != null">dept_name = #{deptName},</if>
             <if test="ancestors != null">ancestors = #{ancestors},</if>
+            <if test="kaNum != null ">ka_num = #{kaNum},</if>
             <if test="kaYear != null and kaYear != ''">ka_year = #{kaYear},</if>
             <if test="kaMonth != null and kaMonth != ''">ka_month = #{kaMonth},</if>
             <if test="kaDay != null and kaDay != ''">ka_day = #{kaDay},</if>

+ 14 - 7
ruoyi-system/src/main/resources/mapper/system/SysUserMapper.xml

@@ -13,7 +13,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         <result property="phonenumber"  column="phonenumber"  />
         <result property="sex"          column="sex"          />
         <result property="avatar"       column="avatar"       />
-		<result property="facePhoto"       column="face_photo"       />
+		<result property="facePhoto"    column="face_photo"   />
+		<result property="faceType"    column="face_type"   />
         <result property="password"     column="password"     />
         <result property="status"       column="status"       />
         <result property="delFlag"      column="del_flag"     />
@@ -51,7 +52,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
     </resultMap>
 	
 	<sql id="selectUserVo">
-        select u.user_id, u.dept_id, u.user_name, u.nick_name, u.email, u.avatar,u.face_photo, u.phonenumber, u.password, u.sex, u.status, u.del_flag, u.login_ip, u.login_date, u.create_by, u.create_time, u.remark,
+        select u.user_id, u.dept_id, u.user_name, u.nick_name, u.email, u.avatar,u.face_photo,u.face_type, u.phonenumber, u.password, u.sex, u.status, u.del_flag, u.login_ip, u.login_date, u.create_by, u.create_time, u.remark,
         d.dept_id, d.parent_id, d.ancestors, d.dept_name, d.order_num, d.leader, d.status as dept_status,
         r.role_id, r.role_name, r.role_key, r.role_sort, r.data_scope, r.status as role_status
         from sys_user u
@@ -61,7 +62,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
     </sql>
     
     <select id="selectUserList" parameterType="SysUser" resultMap="SysUserResult">
-		select u.user_id, u.dept_id, u.nick_name, u.user_name, u.email, u.avatar,u.face_photo, u.phonenumber, u.sex, u.status, u.del_flag, u.login_ip, u.login_date, u.create_by, u.create_time, u.remark, d.dept_name, d.leader from sys_user u
+		select u.user_id, u.dept_id, u.nick_name, u.user_name, u.email, u.avatar,u.face_photo,u.face_type, u.phonenumber, u.sex, u.status, u.del_flag, u.login_ip, u.login_date, u.create_by, u.create_time, u.remark, d.dept_name, d.leader from sys_user u
 		left join sys_dept d on u.dept_id = d.dept_id
 		where u.del_flag = '0'
 		<if test="userId != null and userId != 0">
@@ -73,6 +74,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
 		<if test="nickName != null and nickName != ''">
 			AND u.nick_name like concat('%', #{nickName}, '%')
 		</if>
+		<if test="faceType != null and faceType != ''">
+			AND u.face_type = #{faceType}
+		</if>
 		<if test="status != null and status != ''">
 			AND u.status = #{status}
 		</if>
@@ -96,7 +100,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
 	</select>
 	
 	<select id="selectAllocatedList" parameterType="SysUser" resultMap="SysUserResult">
-	    select distinct u.user_id, u.dept_id, u.user_name, u.nick_name, u.face_photo,u.email, u.phonenumber, u.status, u.create_time
+	    select distinct u.user_id, u.dept_id, u.user_name, u.nick_name, u.face_photo,u.face_type,u.email, u.phonenumber, u.status, u.create_time
 	    from sys_user u
 			 left join sys_dept d on u.dept_id = d.dept_id
 			 left join sys_user_role ur on u.user_id = ur.user_id
@@ -113,7 +117,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
 	</select>
 	
 	<select id="selectUnallocatedList" parameterType="SysUser" resultMap="SysUserResult">
-	    select distinct u.user_id, u.dept_id, u.user_name, u.nick_name, u.face_photo,u.email, u.phonenumber, u.status, u.create_time
+	    select distinct u.user_id, u.dept_id, u.user_name, u.nick_name, u.face_photo,u.face_type,u.email, u.phonenumber, u.status, u.create_time
 	    from sys_user u
 			 left join sys_dept d on u.dept_id = d.dept_id
 			 left join sys_user_role ur on u.user_id = ur.user_id
@@ -170,6 +174,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  			<if test="email != null and email != ''">email,</if>
  			<if test="avatar != null and avatar != ''">avatar,</if>
 			<if test="facePhoto != null and facePhoto != ''">face_photo,</if>
+			<if test="faceType != null and faceType != ''">face_type,</if>
  			<if test="phonenumber != null and phonenumber != ''">phonenumber,</if>
  			<if test="sex != null and sex != ''">sex,</if>
  			<if test="password != null and password != ''">password,</if>
@@ -185,6 +190,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  			<if test="email != null and email != ''">#{email},</if>
  			<if test="avatar != null and avatar != ''">#{avatar},</if>
 			<if test="facePhoto != null and facePhoto != ''">#{facePhoto},</if>
+			<if test="faceType != null and faceType != ''">#{faceType},</if>
  			<if test="phonenumber != null and phonenumber != ''">#{phonenumber},</if>
  			<if test="sex != null and sex != ''">#{sex},</if>
  			<if test="password != null and password != ''">#{password},</if>
@@ -206,6 +212,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  			<if test="sex != null and sex != ''">sex = #{sex},</if>
  			<if test="avatar != null and avatar != ''">avatar = #{avatar},</if>
 			<if test="facePhoto != null and facePhoto != ''">face_photo= #{facePhoto},</if>
+			<if test="faceType != null and faceType != ''">face_type= #{faceType},</if>
  			<if test="password != null and password != ''">password = #{password},</if>
 			<if test="applyFor != null and applyFor != ''">apply_for = #{applyFor},</if>
  			<if test="status != null and status != ''">status = #{status},</if>
@@ -249,7 +256,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
 
 
 	<select id="allocationList" parameterType="SysUser" resultMap="SysUserResult">
-		select u.user_id, u.dept_id, u.nick_name, u.user_name,u.face_photo, u.email, u.avatar, u.phonenumber, u.sex, u.status, u.del_flag, u.login_ip, u.login_date, u.create_by, u.create_time, u.remark, d.dept_name, d.leader
+		select u.user_id, u.dept_id, u.nick_name, u.user_name,u.face_photo,u.face_type, u.email, u.avatar, u.phonenumber, u.sex, u.status, u.del_flag, u.login_ip, u.login_date, u.create_by, u.create_time, u.remark, d.dept_name, d.leader
 		from sys_user u
 		where u.del_flag = '0'
 		  and (u.dept_id = 0 or u.dept_id is null)
@@ -278,7 +285,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
 	</select>
 
 	<select id="selectUserListNoDept" parameterType="SysUser" resultMap="SysUserResult">
-		select u.user_id, u.dept_id, u.nick_name, u.user_name, u.email, u.avatar,u.face_photo, u.phonenumber, u.sex, u.status, u.del_flag, u.login_ip, u.login_date, u.create_by, u.create_time, u.remark, d.dept_name, d.leader, d.ancestors from sys_user u
+		select u.user_id, u.dept_id, u.nick_name, u.user_name, u.email, u.avatar,u.face_photo,u.face_type, u.phonenumber, u.sex, u.status, u.del_flag, u.login_ip, u.login_date, u.create_by, u.create_time, u.remark, d.dept_name, d.leader, d.ancestors from sys_user u
 		left join sys_dept d on u.dept_id = d.dept_id
 		where u.del_flag = '0'
 		  and u.dept_id !=0 and u.dept_id !='' and u.dept_id is not null