| @@ -20,4 +20,32 @@ public class NumberUtil extends cn.hutool.core.util.NumberUtil implements Number | |||
| return number == null ? 0 : number; | |||
| } | |||
| /** | |||
| * @Author yangkai | |||
| * @Description 将int类型的数据转化成X小时Y分钟的形式 | |||
| * @Date 2023/9/21 | |||
| * @Param | |||
| * @return | |||
| **/ | |||
| public static String convertMinutesToHoursMinutes(int minutes) { | |||
| if (minutes < 0) { | |||
| throw new IllegalArgumentException("分钟数不能为负数"); | |||
| } | |||
| int hours = minutes / 60; | |||
| int remainingMinutes = minutes % 60; | |||
| String hourMin = String.format("%d小时%d分钟", hours, remainingMinutes); | |||
| //如果小时数为0,则不显示"小时" | |||
| if (hours == 0) { | |||
| hourMin = String.format("%d分钟", remainingMinutes); | |||
| } | |||
| //如果分钟数为0,则不显示"分钟" | |||
| if (remainingMinutes == 0) { | |||
| hourMin = String.format("%d小时", hours); | |||
| } | |||
| return hourMin; | |||
| } | |||
| } | |||
| @@ -7,6 +7,7 @@ import java.text.DecimalFormat; | |||
| import java.text.ParseException; | |||
| import java.text.ParsePosition; | |||
| import java.text.SimpleDateFormat; | |||
| import java.time.LocalDate; | |||
| import java.time.LocalDateTime; | |||
| import java.time.LocalTime; | |||
| import java.time.ZoneId; | |||
| @@ -16,334 +17,358 @@ import java.util.GregorianCalendar; | |||
| import java.util.List; | |||
| public class DateUtils extends org.apache.commons.lang.time.DateUtils { | |||
| public DateUtils() { | |||
| } | |||
| public static Date getPushForwardDate(Date date, Integer num) { | |||
| if (date == null) { | |||
| return null; | |||
| } else { | |||
| Calendar calendar = Calendar.getInstance(); | |||
| calendar.setTime(date); | |||
| calendar.add(5, -(num - 1)); | |||
| calendar.set(11, 0); | |||
| calendar.set(12, 0); | |||
| calendar.set(13, 0); | |||
| calendar.set(14, 0); | |||
| return calendar.getTime(); | |||
| } | |||
| } | |||
| public static Date getFixedPushForwardDate(Date date, Integer num) { | |||
| if (date == null) { | |||
| return null; | |||
| } else { | |||
| Calendar calendar = Calendar.getInstance(); | |||
| calendar.setTime(date); | |||
| calendar.add(5, -(num)); | |||
| calendar.set(11, 0); | |||
| calendar.set(12, 0); | |||
| calendar.set(13, 0); | |||
| calendar.set(14, 0); | |||
| return calendar.getTime(); | |||
| } | |||
| } | |||
| public static Date getOfDayFirst(Date date) { | |||
| if (date == null) { | |||
| return null; | |||
| } else { | |||
| Calendar calendar = Calendar.getInstance(); | |||
| calendar.setTime(date); | |||
| calendar.set(11, 0); | |||
| calendar.set(12, 0); | |||
| calendar.set(13, 0); | |||
| calendar.set(14, 0); | |||
| return calendar.getTime(); | |||
| } | |||
| } | |||
| public static Date getOfDayLast(Date date) { | |||
| if (date == null) { | |||
| return null; | |||
| } else { | |||
| Calendar calendar = Calendar.getInstance(); | |||
| calendar.setTime(date); | |||
| calendar.set(11, 23); | |||
| calendar.set(12, 59); | |||
| calendar.set(13, 59); | |||
| calendar.set(14, 999); | |||
| return calendar.getTime(); | |||
| } | |||
| } | |||
| public static Date getPageDayLast(Date date) { | |||
| if (date == null) { | |||
| return null; | |||
| } else { | |||
| Calendar calendar = Calendar.getInstance(); | |||
| calendar.setTime(date); | |||
| calendar.add(5, -1); | |||
| calendar.set(11, 23); | |||
| calendar.set(12, 59); | |||
| calendar.set(13, 59); | |||
| calendar.set(14, 999); | |||
| return calendar.getTime(); | |||
| } | |||
| } | |||
| public static Date getFirstDayOfMonth(Date date) { | |||
| new SimpleDateFormat("yyyy-MM-dd "); | |||
| GregorianCalendar gcLast = (GregorianCalendar)Calendar.getInstance(); | |||
| gcLast.setTime(date); | |||
| gcLast.set(Calendar.DAY_OF_MONTH, 1); | |||
| return gcLast.getTime(); | |||
| } | |||
| public static Date getLastDayOfMonth(Date date) { | |||
| Calendar calendar = Calendar.getInstance(); | |||
| calendar.setTime(date); | |||
| calendar.set(Calendar.DAY_OF_MONTH, calendar.getActualMaximum(Calendar.DAY_OF_MONTH)); | |||
| return calendar.getTime(); | |||
| } | |||
| public static Date getAttendanceTime(Date date) { | |||
| Calendar calendar = Calendar.getInstance(); | |||
| calendar.setTime(date); | |||
| calendar.add(5, -2); | |||
| calendar.set(11, 23); | |||
| return calendar.getTime(); | |||
| } | |||
| public static String getStartTime() { | |||
| Date dNow = new Date(); | |||
| new Date(); | |||
| Calendar calendar = Calendar.getInstance(); | |||
| calendar.setTime(dNow); | |||
| calendar.add(5, -1); | |||
| Date dBefore = calendar.getTime(); | |||
| SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); | |||
| return sdf.format(dBefore); | |||
| } | |||
| /*/** | |||
| * @Author yangkai | |||
| * @Description 根据字符串日期返回星期几 | |||
| * @Param [datetime] | |||
| * @return java.lang.String | |||
| **/ | |||
| public static String dateToWeek(String datetime) { | |||
| SimpleDateFormat f = new SimpleDateFormat("yyyy-MM-dd"); | |||
| String[] weekDays = new String[]{"星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六"}; | |||
| Calendar cal = Calendar.getInstance(); | |||
| Date datet = null; | |||
| try { | |||
| datet = f.parse(datetime); | |||
| cal.setTime(datet); | |||
| } catch (ParseException var6) { | |||
| var6.printStackTrace(); | |||
| } | |||
| int w = cal.get(7) - 1; | |||
| if (w < 0) { | |||
| w = 0; | |||
| } | |||
| return weekDays[w]; | |||
| } | |||
| public static String getDatePoor(Date endDate, Date nowDate) { | |||
| long nd = 86400000L; | |||
| long nh = 3600000L; | |||
| long nm = 60000L; | |||
| long diff = endDate.getTime() - nowDate.getTime(); | |||
| long day = diff / nd; | |||
| long hour = diff % nd / nh; | |||
| long min = diff % nd % nh / nm; | |||
| return day + ":" + hour; | |||
| } | |||
| /** | |||
| * 1 2 3 4 5 6 7 | |||
| * 日 一 二 三 四 五 六 | |||
| * @param date | |||
| * @return | |||
| */ | |||
| public static Integer getDayOfWeek(Date date) { | |||
| Calendar calendar = Calendar.getInstance(); | |||
| calendar.setTime(date); | |||
| return calendar.get(Calendar.DAY_OF_WEEK); | |||
| } | |||
| public static List<String> generateNearlyDateString(Date currentDate, Integer nearlyDays) { | |||
| Calendar calendar = Calendar.getInstance(); | |||
| calendar.setTime(currentDate); | |||
| List<String> dateStringList = Lists.newLinkedList(); | |||
| for(int i = 0; i < nearlyDays; ++i) { | |||
| calendar.add(5, i == 0 ? 0 : -1); | |||
| dateStringList.add(formatDate(calendar.getTime(), "yyyy-MM-dd")); | |||
| } | |||
| return dateStringList; | |||
| } | |||
| public static String dateDiff(Date startDate, Date endDate) { | |||
| if (null != startDate && null != endDate) { | |||
| Long mills = endDate.getTime() - startDate.getTime(); | |||
| Integer minuteDiff = mills.intValue() / '\uea60'; | |||
| Integer hours = minuteDiff / 60; | |||
| Integer minutes = minuteDiff % 60; | |||
| String hoursStr = hours + "h"; | |||
| String minutesStr = minutes == 0 ? "" : minutes + "m"; | |||
| return hoursStr + minutesStr; | |||
| } else { | |||
| return "0h"; | |||
| } | |||
| } | |||
| public static Integer dateDiffMin(Date startDate, Date endDate) { | |||
| if (null != startDate && null != endDate) { | |||
| Long mills = endDate.getTime() - startDate.getTime(); | |||
| Integer minuteDiff = mills.intValue() / '\uea60'; | |||
| Integer hours = minuteDiff / 60; | |||
| Integer minutes = minuteDiff % 60; | |||
| return hours * 60 + minutes; | |||
| } else { | |||
| return 0; | |||
| } | |||
| } | |||
| public static String intToHourMin(Integer minuteDiff) { | |||
| Integer hours = minuteDiff / 60; | |||
| Integer minutes = minuteDiff % 60; | |||
| return hours+"小时"+ minutes+"分"; | |||
| } | |||
| public static String formatDate(Date date, String pattern) { | |||
| SimpleDateFormat sdf = new SimpleDateFormat(pattern); | |||
| return sdf.format(date); | |||
| } | |||
| public static Date praseStringToDate(String dateStr) throws ParseException { | |||
| SimpleDateFormat sdf = new SimpleDateFormat(); | |||
| return sdf.parse(dateStr); | |||
| } | |||
| public static Date parseLongToDate(Long dateLong) throws ParseException { | |||
| Calendar calendar = Calendar.getInstance(); | |||
| calendar.setTimeInMillis(dateLong); | |||
| return calendar.getTime(); | |||
| } | |||
| public static Date parseLongToDate(String dateLong) throws ParseException { | |||
| BigDecimal number = new BigDecimal(dateLong); | |||
| return parseLongToDate(number.doubleValue()); | |||
| } | |||
| public static Date parseLongToDate(Double dateLong) throws ParseException { | |||
| Calendar calendar = Calendar.getInstance(); | |||
| DecimalFormat df = new DecimalFormat("#"); // 创建DecimalFormat对象 | |||
| String str = df.format(dateLong); | |||
| if (str.indexOf(".")>-1) { | |||
| str = str.replace(".",""); | |||
| } | |||
| str = str.substring(0,13); | |||
| BigDecimal number = new BigDecimal(str); | |||
| calendar.setTimeInMillis(number.longValue()); | |||
| return calendar.getTime(); | |||
| } | |||
| public static String praseLongToDateString(Long dateLong) throws ParseException { | |||
| Calendar calendar = Calendar.getInstance(); | |||
| calendar.setTimeInMillis(dateLong); | |||
| Date date = calendar.getTime(); | |||
| return formatDate(date, "yyyy-MM-dd HH:mm:ss"); | |||
| } | |||
| public static String getMillsSecondsDouble() { | |||
| Long cutime = System.currentTimeMillis(); | |||
| String cutimeStr = String.valueOf(cutime); | |||
| BigDecimal d = new BigDecimal(cutimeStr.substring(0, 10) + "." + cutimeStr.substring(10)); | |||
| return d.stripTrailingZeros().toPlainString(); | |||
| } | |||
| /** | |||
| * | |||
| * @param time 2018-07-06 19:35:23 | |||
| * @param pattern yyyy-MM-dd HH:mm:ss | |||
| * @return | |||
| */ | |||
| public static Date parseStrToDate(String time, String pattern) { | |||
| SimpleDateFormat formatter = new SimpleDateFormat(pattern); | |||
| ParsePosition pos = new ParsePosition(0); | |||
| return formatter.parse(time, pos); | |||
| } | |||
| //形如yyyy-MM-dd格式的时间串,赠加或减少几天 | |||
| //如2022-06-06 增加一天 返回 2022-06-07 | |||
| public static String dateStrAdd(String dateStr, int addDays){ | |||
| Date date1 = DateUtils.parseStrToDate(dateStr, "yyyy-MM-dd"); | |||
| Date date2 = DateUtils.addDays(date1, addDays); | |||
| String dateStr2 = DateUtils.formatDate(date2, "yyyy-MM-dd"); | |||
| return dateStr2; | |||
| } | |||
| public static int dateStrDiff(String startDateStr, String endDateStr) { | |||
| Date date1 = DateUtils.parseStrToDate(startDateStr, "yyyy-MM-dd"); | |||
| Date date2 = DateUtils.parseStrToDate(endDateStr, "yyyy-MM-dd"); | |||
| Calendar cal1 = Calendar.getInstance(); | |||
| cal1.setTime(date1); | |||
| Calendar cal2 = Calendar.getInstance(); | |||
| cal2.setTime(date2); | |||
| int day1= cal1.get(Calendar.DAY_OF_YEAR); | |||
| int day2 = cal2.get(Calendar.DAY_OF_YEAR); | |||
| int year1 = cal1.get(Calendar.YEAR); | |||
| int year2 = cal2.get(Calendar.YEAR); | |||
| if (year1 != year2) {//同一年 | |||
| int timeDistance = 0; | |||
| for (int i = year1; i < year2; i++) { | |||
| if (i % 4 == 0 && i % 100 != 0 || i % 400 == 0) //闰年 | |||
| { | |||
| timeDistance += 366; | |||
| } else { | |||
| timeDistance += 365; | |||
| } | |||
| } | |||
| return timeDistance + (day2 - day1); | |||
| } else {// 不同年 | |||
| return day2 - day1; | |||
| } | |||
| } | |||
| public static LocalDateTime currentDateToLocalDateTime(){ | |||
| Date todayDate = new Date(); | |||
| return dateToLocalDateTime(todayDate); | |||
| } | |||
| public static LocalDateTime dateToLocalDateTime(Date date){ | |||
| LocalDateTime ldt = date.toInstant() | |||
| .atZone( ZoneId.systemDefault() ) | |||
| .toLocalDateTime(); | |||
| return ldt; | |||
| } | |||
| public static String isAmPm(){ | |||
| //判断当前时间是上午还是下午,上午返回am,下午返回pm | |||
| LocalTime currentTime = LocalTime.now(); | |||
| if (currentTime.isBefore(LocalTime.NOON)) { | |||
| return "am"; | |||
| } else { | |||
| return "pm"; | |||
| } | |||
| } | |||
| public DateUtils() { | |||
| } | |||
| public static Date getPushForwardDate(Date date, Integer num) { | |||
| if (date == null) { | |||
| return null; | |||
| } else { | |||
| Calendar calendar = Calendar.getInstance(); | |||
| calendar.setTime(date); | |||
| calendar.add(5, -(num - 1)); | |||
| calendar.set(11, 0); | |||
| calendar.set(12, 0); | |||
| calendar.set(13, 0); | |||
| calendar.set(14, 0); | |||
| return calendar.getTime(); | |||
| } | |||
| } | |||
| public static Date getFixedPushForwardDate(Date date, Integer num) { | |||
| if (date == null) { | |||
| return null; | |||
| } else { | |||
| Calendar calendar = Calendar.getInstance(); | |||
| calendar.setTime(date); | |||
| calendar.add(5, -(num)); | |||
| calendar.set(11, 0); | |||
| calendar.set(12, 0); | |||
| calendar.set(13, 0); | |||
| calendar.set(14, 0); | |||
| return calendar.getTime(); | |||
| } | |||
| } | |||
| public static Date getOfDayFirst(Date date) { | |||
| if (date == null) { | |||
| return null; | |||
| } else { | |||
| Calendar calendar = Calendar.getInstance(); | |||
| calendar.setTime(date); | |||
| calendar.set(11, 0); | |||
| calendar.set(12, 0); | |||
| calendar.set(13, 0); | |||
| calendar.set(14, 0); | |||
| return calendar.getTime(); | |||
| } | |||
| } | |||
| public static Date getOfDayLast(Date date) { | |||
| if (date == null) { | |||
| return null; | |||
| } else { | |||
| Calendar calendar = Calendar.getInstance(); | |||
| calendar.setTime(date); | |||
| calendar.set(11, 23); | |||
| calendar.set(12, 59); | |||
| calendar.set(13, 59); | |||
| calendar.set(14, 999); | |||
| return calendar.getTime(); | |||
| } | |||
| } | |||
| public static Date getPageDayLast(Date date) { | |||
| if (date == null) { | |||
| return null; | |||
| } else { | |||
| Calendar calendar = Calendar.getInstance(); | |||
| calendar.setTime(date); | |||
| calendar.add(5, -1); | |||
| calendar.set(11, 23); | |||
| calendar.set(12, 59); | |||
| calendar.set(13, 59); | |||
| calendar.set(14, 999); | |||
| return calendar.getTime(); | |||
| } | |||
| } | |||
| public static Date getFirstDayOfMonth(Date date) { | |||
| new SimpleDateFormat("yyyy-MM-dd "); | |||
| GregorianCalendar gcLast = (GregorianCalendar) Calendar.getInstance(); | |||
| gcLast.setTime(date); | |||
| gcLast.set(Calendar.DAY_OF_MONTH, 1); | |||
| return gcLast.getTime(); | |||
| } | |||
| public static Date getLastDayOfMonth(Date date) { | |||
| Calendar calendar = Calendar.getInstance(); | |||
| calendar.setTime(date); | |||
| calendar.set(Calendar.DAY_OF_MONTH, calendar.getActualMaximum(Calendar.DAY_OF_MONTH)); | |||
| return calendar.getTime(); | |||
| } | |||
| public static Date getAttendanceTime(Date date) { | |||
| Calendar calendar = Calendar.getInstance(); | |||
| calendar.setTime(date); | |||
| calendar.add(5, -2); | |||
| calendar.set(11, 23); | |||
| return calendar.getTime(); | |||
| } | |||
| public static String getStartTime() { | |||
| Date dNow = new Date(); | |||
| new Date(); | |||
| Calendar calendar = Calendar.getInstance(); | |||
| calendar.setTime(dNow); | |||
| calendar.add(5, -1); | |||
| Date dBefore = calendar.getTime(); | |||
| SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); | |||
| return sdf.format(dBefore); | |||
| } | |||
| /*/** | |||
| * @Author yangkai | |||
| * @Description 根据字符串日期返回星期几 | |||
| * @Param [datetime] | |||
| * @return java.lang.String | |||
| **/ | |||
| public static String dateToWeek(String datetime) { | |||
| SimpleDateFormat f = new SimpleDateFormat("yyyy-MM-dd"); | |||
| String[] weekDays = new String[]{"星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六"}; | |||
| Calendar cal = Calendar.getInstance(); | |||
| Date datet = null; | |||
| try { | |||
| datet = f.parse(datetime); | |||
| cal.setTime(datet); | |||
| } catch (ParseException var6) { | |||
| var6.printStackTrace(); | |||
| } | |||
| int w = cal.get(7) - 1; | |||
| if (w < 0) { | |||
| w = 0; | |||
| } | |||
| return weekDays[w]; | |||
| } | |||
| public static String getDatePoor(Date endDate, Date nowDate) { | |||
| long nd = 86400000L; | |||
| long nh = 3600000L; | |||
| long nm = 60000L; | |||
| long diff = endDate.getTime() - nowDate.getTime(); | |||
| long day = diff / nd; | |||
| long hour = diff % nd / nh; | |||
| long min = diff % nd % nh / nm; | |||
| return day + ":" + hour; | |||
| } | |||
| /** | |||
| * 1 2 3 4 5 6 7 | |||
| * 日 一 二 三 四 五 六 | |||
| * | |||
| * @param date | |||
| * @return | |||
| */ | |||
| public static Integer getDayOfWeek(Date date) { | |||
| Calendar calendar = Calendar.getInstance(); | |||
| calendar.setTime(date); | |||
| return calendar.get(Calendar.DAY_OF_WEEK); | |||
| } | |||
| public static List<String> generateNearlyDateString(Date currentDate, Integer nearlyDays) { | |||
| Calendar calendar = Calendar.getInstance(); | |||
| calendar.setTime(currentDate); | |||
| List<String> dateStringList = Lists.newLinkedList(); | |||
| for (int i = 0; i < nearlyDays; ++i) { | |||
| calendar.add(5, i == 0 ? 0 : -1); | |||
| dateStringList.add(formatDate(calendar.getTime(), "yyyy-MM-dd")); | |||
| } | |||
| return dateStringList; | |||
| } | |||
| public static String dateDiff(Date startDate, Date endDate) { | |||
| if (null != startDate && null != endDate) { | |||
| Long mills = endDate.getTime() - startDate.getTime(); | |||
| Integer minuteDiff = mills.intValue() / '\uea60'; | |||
| Integer hours = minuteDiff / 60; | |||
| Integer minutes = minuteDiff % 60; | |||
| String hoursStr = hours + "h"; | |||
| String minutesStr = minutes == 0 ? "" : minutes + "m"; | |||
| return hoursStr + minutesStr; | |||
| } else { | |||
| return "0h"; | |||
| } | |||
| } | |||
| public static Integer dateDiffMin(Date startDate, Date endDate) { | |||
| if (null != startDate && null != endDate) { | |||
| Long mills = endDate.getTime() - startDate.getTime(); | |||
| Integer minuteDiff = mills.intValue() / '\uea60'; | |||
| Integer hours = minuteDiff / 60; | |||
| Integer minutes = minuteDiff % 60; | |||
| return hours * 60 + minutes; | |||
| } else { | |||
| return 0; | |||
| } | |||
| } | |||
| public static String intToHourMin(Integer minuteDiff) { | |||
| Integer hours = minuteDiff / 60; | |||
| Integer minutes = minuteDiff % 60; | |||
| return hours + "小时" + minutes + "分"; | |||
| } | |||
| public static String formatDate(Date date, String pattern) { | |||
| SimpleDateFormat sdf = new SimpleDateFormat(pattern); | |||
| return sdf.format(date); | |||
| } | |||
| public static Date praseStringToDate(String dateStr) throws ParseException { | |||
| SimpleDateFormat sdf = new SimpleDateFormat(); | |||
| return sdf.parse(dateStr); | |||
| } | |||
| public static Date parseLongToDate(Long dateLong) throws ParseException { | |||
| Calendar calendar = Calendar.getInstance(); | |||
| calendar.setTimeInMillis(dateLong); | |||
| return calendar.getTime(); | |||
| } | |||
| public static Date parseLongToDate(String dateLong) throws ParseException { | |||
| BigDecimal number = new BigDecimal(dateLong); | |||
| return parseLongToDate(number.doubleValue()); | |||
| } | |||
| public static Date parseLongToDate(Double dateLong) throws ParseException { | |||
| Calendar calendar = Calendar.getInstance(); | |||
| DecimalFormat df = new DecimalFormat("#"); // 创建DecimalFormat对象 | |||
| String str = df.format(dateLong); | |||
| if (str.indexOf(".") > -1) { | |||
| str = str.replace(".", ""); | |||
| } | |||
| str = str.substring(0, 13); | |||
| BigDecimal number = new BigDecimal(str); | |||
| calendar.setTimeInMillis(number.longValue()); | |||
| return calendar.getTime(); | |||
| } | |||
| public static String praseLongToDateString(Long dateLong) throws ParseException { | |||
| Calendar calendar = Calendar.getInstance(); | |||
| calendar.setTimeInMillis(dateLong); | |||
| Date date = calendar.getTime(); | |||
| return formatDate(date, "yyyy-MM-dd HH:mm:ss"); | |||
| } | |||
| public static String getMillsSecondsDouble() { | |||
| Long cutime = System.currentTimeMillis(); | |||
| String cutimeStr = String.valueOf(cutime); | |||
| BigDecimal d = new BigDecimal(cutimeStr.substring(0, 10) + "." + cutimeStr.substring(10)); | |||
| return d.stripTrailingZeros().toPlainString(); | |||
| } | |||
| /** | |||
| * @param time 2018-07-06 19:35:23 | |||
| * @param pattern yyyy-MM-dd HH:mm:ss | |||
| * @return | |||
| */ | |||
| public static Date parseStrToDate(String time, String pattern) { | |||
| SimpleDateFormat formatter = new SimpleDateFormat(pattern); | |||
| ParsePosition pos = new ParsePosition(0); | |||
| return formatter.parse(time, pos); | |||
| } | |||
| //形如yyyy-MM-dd格式的时间串,赠加或减少几天 | |||
| //如2022-06-06 增加一天 返回 2022-06-07 | |||
| public static String dateStrAdd(String dateStr, int addDays) { | |||
| Date date1 = DateUtils.parseStrToDate(dateStr, "yyyy-MM-dd"); | |||
| Date date2 = DateUtils.addDays(date1, addDays); | |||
| String dateStr2 = DateUtils.formatDate(date2, "yyyy-MM-dd"); | |||
| return dateStr2; | |||
| } | |||
| public static int dateStrDiff(String startDateStr, String endDateStr) { | |||
| Date date1 = DateUtils.parseStrToDate(startDateStr, "yyyy-MM-dd"); | |||
| Date date2 = DateUtils.parseStrToDate(endDateStr, "yyyy-MM-dd"); | |||
| Calendar cal1 = Calendar.getInstance(); | |||
| cal1.setTime(date1); | |||
| Calendar cal2 = Calendar.getInstance(); | |||
| cal2.setTime(date2); | |||
| int day1 = cal1.get(Calendar.DAY_OF_YEAR); | |||
| int day2 = cal2.get(Calendar.DAY_OF_YEAR); | |||
| int year1 = cal1.get(Calendar.YEAR); | |||
| int year2 = cal2.get(Calendar.YEAR); | |||
| if (year1 != year2) {//同一年 | |||
| int timeDistance = 0; | |||
| for (int i = year1; i < year2; i++) { | |||
| if (i % 4 == 0 && i % 100 != 0 || i % 400 == 0) //闰年 | |||
| { | |||
| timeDistance += 366; | |||
| } else { | |||
| timeDistance += 365; | |||
| } | |||
| } | |||
| return timeDistance + (day2 - day1); | |||
| } else {// 不同年 | |||
| return day2 - day1; | |||
| } | |||
| } | |||
| public static LocalDateTime currentDateToLocalDateTime() { | |||
| Date todayDate = new Date(); | |||
| return dateToLocalDateTime(todayDate); | |||
| } | |||
| public static LocalDateTime dateToLocalDateTime(Date date) { | |||
| LocalDateTime ldt = date.toInstant() | |||
| .atZone(ZoneId.systemDefault()) | |||
| .toLocalDateTime(); | |||
| return ldt; | |||
| } | |||
| public static String isAmPm() { | |||
| //判断当前时间是上午还是下午,上午返回am,下午返回pm | |||
| LocalTime currentTime = LocalTime.now(); | |||
| if (currentTime.isBefore(LocalTime.NOON)) { | |||
| return "am"; | |||
| } else { | |||
| return "pm"; | |||
| } | |||
| } | |||
| public static String getChineseWeek(Date date) { | |||
| int week = LocalDate.parse(new SimpleDateFormat("yyyy-MM-dd").format(date)).getDayOfWeek().getValue(); | |||
| switch (week) { | |||
| case 1: | |||
| return "周一"; | |||
| case 2: | |||
| return "周二"; | |||
| case 3: | |||
| return "周三"; | |||
| case 4: | |||
| return "周四"; | |||
| case 5: | |||
| return "周五"; | |||
| case 6: | |||
| return "周六"; | |||
| case 7: | |||
| return "周日"; | |||
| default: | |||
| return ""; | |||
| } | |||
| } | |||
| } | |||
| @@ -4,7 +4,11 @@ import com.xueyi.common.web.entity.service.IBaseService; | |||
| import com.xueyi.system.common.domain.dto.DmHolidayDto; | |||
| import com.xueyi.system.common.domain.query.DmHolidayQuery; | |||
| import java.util.Date; | |||
| public interface IDmHolidayService extends IBaseService<DmHolidayQuery, DmHolidayDto> { | |||
| DmHolidayDto getTodayHoliday(); | |||
| DmHolidayDto isHoliday(Date date); | |||
| } | |||
| @@ -1,5 +1,6 @@ | |||
| package com.xueyi.system.common.service.impl; | |||
| import cn.hutool.core.date.LocalDateTimeUtil; | |||
| import com.xueyi.common.web.entity.service.impl.BaseServiceImpl; | |||
| import com.xueyi.system.common.domain.dto.DmHolidayDto; | |||
| import com.xueyi.system.common.domain.query.DmHolidayQuery; | |||
| @@ -8,14 +9,20 @@ import com.xueyi.system.common.service.IDmHolidayService; | |||
| import org.springframework.stereotype.Service; | |||
| import java.time.LocalDate; | |||
| import java.util.Date; | |||
| @Service | |||
| public class IDmHolidayServiceImpl extends BaseServiceImpl<DmHolidayQuery, DmHolidayDto, IDmHolidayManager> implements IDmHolidayService { | |||
| @Override | |||
| public DmHolidayDto getTodayHoliday() { | |||
| return isHoliday(new Date()); | |||
| } | |||
| @Override | |||
| public DmHolidayDto isHoliday(Date date) { | |||
| DmHolidayQuery query = new DmHolidayQuery(); | |||
| query.setDate(LocalDate.now()); | |||
| query.setDate(LocalDateTimeUtil.of(date).toLocalDate()); | |||
| DmHolidayDto dto = baseManager.selectTodayHoliday(query); | |||
| if (dto != null) { | |||
| return dto; | |||
| @@ -1,8 +1,19 @@ | |||
| package com.xueyi.system.staff.controller; | |||
| import com.alibaba.excel.EasyExcel; | |||
| import com.alibaba.excel.ExcelWriter; | |||
| import com.alibaba.excel.annotation.ExcelProperty; | |||
| import com.alibaba.excel.metadata.data.WriteCellData; | |||
| import com.alibaba.excel.util.BooleanUtils; | |||
| import com.alibaba.excel.util.ListUtils; | |||
| import com.alibaba.excel.write.handler.CellWriteHandler; | |||
| import com.alibaba.excel.write.handler.context.CellWriteHandlerContext; | |||
| import com.alibaba.excel.write.metadata.WriteSheet; | |||
| import com.alibaba.excel.write.metadata.style.WriteCellStyle; | |||
| import com.alibaba.excel.write.metadata.style.WriteFont; | |||
| import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; | |||
| import com.xueyi.common.core.utils.core.ObjectUtil; | |||
| import com.xueyi.common.core.utils.core.StrUtil; | |||
| import com.xueyi.common.core.utils.poi.ExcelUtil; | |||
| import com.xueyi.common.core.web.result.AjaxResult; | |||
| import com.xueyi.common.core.web.validate.V_A; | |||
| import com.xueyi.common.core.web.validate.V_E; | |||
| @@ -11,7 +22,6 @@ import com.xueyi.common.log.enums.BusinessType; | |||
| import com.xueyi.common.security.annotation.RequiresPermissions; | |||
| import com.xueyi.common.web.entity.controller.BaseController; | |||
| import com.xueyi.common.web.utils.DateUtils; | |||
| import com.xueyi.system.api.organize.domain.po.SysDeptPo; | |||
| import com.xueyi.system.organize.mapper.SysDeptMapper; | |||
| import com.xueyi.system.staff.domain.dto.DmEmpAttendanceDto; | |||
| import com.xueyi.system.staff.domain.model.DmEmpAttendanceConverter; | |||
| @@ -19,15 +29,30 @@ import com.xueyi.system.staff.domain.po.DmEmpAttendancePo; | |||
| import com.xueyi.system.staff.domain.query.DmEmpAttendanceQuery; | |||
| import com.xueyi.system.staff.mapper.DmEmpAttendanceMapper; | |||
| import com.xueyi.system.staff.service.IDmEmpAttendanceService; | |||
| import com.xueyi.system.staff.service.impl.DmEmpAttendanceServiceImpl; | |||
| import org.apache.poi.ss.usermodel.FillPatternType; | |||
| import org.apache.poi.ss.usermodel.IndexedColors; | |||
| import org.springframework.beans.factory.annotation.Autowired; | |||
| import org.springframework.validation.annotation.Validated; | |||
| import org.springframework.web.bind.annotation.*; | |||
| import org.springframework.web.bind.annotation.DeleteMapping; | |||
| import org.springframework.web.bind.annotation.GetMapping; | |||
| import org.springframework.web.bind.annotation.PathVariable; | |||
| import org.springframework.web.bind.annotation.PostMapping; | |||
| import org.springframework.web.bind.annotation.PutMapping; | |||
| import org.springframework.web.bind.annotation.RequestBody; | |||
| import org.springframework.web.bind.annotation.RequestMapping; | |||
| import org.springframework.web.bind.annotation.RestController; | |||
| import javax.servlet.http.HttpServletResponse; | |||
| import java.io.IOException; | |||
| import java.io.Serializable; | |||
| import java.lang.annotation.Annotation; | |||
| import java.net.URLEncoder; | |||
| import java.text.ParseException; | |||
| import java.util.ArrayList; | |||
| import java.util.Date; | |||
| import java.util.List; | |||
| import java.util.Set; | |||
| /** | |||
| * 员工考勤管理 业务处理 | |||
| @@ -44,6 +69,9 @@ public class DmEmpAttendanceController extends BaseController<DmEmpAttendanceQue | |||
| @Autowired | |||
| private DmEmpAttendanceConverter converter; | |||
| @Autowired | |||
| private DmEmpAttendanceServiceImpl attendanceService; | |||
| /** 定义节点名称 */ | |||
| @Override | |||
| protected String getNodeName() { | |||
| @@ -95,6 +123,38 @@ public class DmEmpAttendanceController extends BaseController<DmEmpAttendanceQue | |||
| @Autowired | |||
| private SysDeptMapper deptMapper; | |||
| private List<DmEmpAttendancePo> data() { | |||
| List<DmEmpAttendancePo> list = ListUtils.newArrayList(); | |||
| Date d = new Date(); | |||
| for (int i = 0; i < 10; i++) { | |||
| DmEmpAttendancePo data = new DmEmpAttendancePo(); | |||
| data.setDateStr(DateUtils.formatDate(d, "YYYY-MM-dd")); | |||
| data.setUserId(System.currentTimeMillis()); | |||
| data.setUserName(StrUtil.generateCode()); | |||
| data.setCheckInTime(new Date()); | |||
| data.setCheckOutTime(new Date()); | |||
| data.setWorkDuration(9288); | |||
| list.add(data); | |||
| } | |||
| return list; | |||
| } | |||
| private List<List<String>> head() { | |||
| List<List<String>> list = new ArrayList<List<String>>(); | |||
| List<String> head0 = new ArrayList<String>(); | |||
| head0.add("字符串" + System.currentTimeMillis()); | |||
| List<String> head1 = new ArrayList<String>(); | |||
| head1.add("数字" + System.currentTimeMillis()); | |||
| List<String> head2 = new ArrayList<String>(); | |||
| head2.add("日期" + System.currentTimeMillis()); | |||
| list.add(head0); | |||
| list.add(head1); | |||
| list.add(head2); | |||
| return list; | |||
| } | |||
| /** | |||
| * 员工考勤导出 | |||
| */ | |||
| @@ -102,38 +162,91 @@ public class DmEmpAttendanceController extends BaseController<DmEmpAttendanceQue | |||
| @PostMapping("/export") | |||
| @RequiresPermissions(Auth.DM_EMP_ATTENDANCE_EXPORT) | |||
| @Log(title = "员工考勤管理", businessType = BusinessType.EXPORT) | |||
| public void export(HttpServletResponse response, DmEmpAttendanceQuery dmEmpAttendance) { | |||
| // super.export(response, dmEmpAttendance); | |||
| ExcelUtil<DmEmpAttendanceDto> util = new ExcelUtil<>(DmEmpAttendanceDto.class); | |||
| QueryWrapper<DmEmpAttendancePo> query = new QueryWrapper<DmEmpAttendancePo>(); | |||
| try { | |||
| public void export(HttpServletResponse response, DmEmpAttendanceQuery dmEmpAttendance) { | |||
| Class<?> yourClass = DmEmpAttendancePo.class; // 替换成你的类 | |||
| Class<? extends Annotation> annotationClass = ExcelProperty.class; // 替换成你的注解类 | |||
| Set<String> annotatedFields = ObjectUtil.findAnnotatedFields(yourClass, annotationClass); | |||
| response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"); | |||
| response.setCharacterEncoding("utf-8"); | |||
| Date start = null; | |||
| Date end = null; | |||
| try (ExcelWriter excelWriter = EasyExcel.write(response.getOutputStream()).build()) { | |||
| QueryWrapper<DmEmpAttendancePo> query = new QueryWrapper<DmEmpAttendancePo>(); | |||
| if (dmEmpAttendance != null && dmEmpAttendance.getETimestamp() != null &&dmEmpAttendance.getETimestamp()>0) { | |||
| String sTime = DateUtils.formatDate(DateUtils.parseLongToDate(dmEmpAttendance.getSTimestamp()),"yyyy-MM-dd"); | |||
| String eTime = DateUtils.formatDate(DateUtils.parseLongToDate(dmEmpAttendance.getETimestamp()),"yyyy-MM-dd"); | |||
| start = DateUtils.parseLongToDate(dmEmpAttendance.getSTimestamp()); | |||
| end = DateUtils.parseLongToDate(dmEmpAttendance.getETimestamp()); | |||
| String sTime = DateUtils.formatDate(start,"yyyy-MM-dd"); | |||
| String eTime = DateUtils.formatDate(end,"yyyy-MM-dd"); | |||
| query.between("date_str",sTime, eTime); | |||
| } | |||
| if (dmEmpAttendance != null && dmEmpAttendance.getDeptId() !=null && dmEmpAttendance.getDeptId() > 0) { | |||
| query.eq("dept_id", dmEmpAttendance.getDeptId()); | |||
| } | |||
| List<DmEmpAttendancePo> list = mapper.selectList(query); | |||
| List<DmEmpAttendanceDto> dtos = new ArrayList<>(list.size()); | |||
| list.forEach(item ->{ | |||
| DmEmpAttendanceDto dto = converter.mapperDto(item); | |||
| dto = dto.fixExcel(); | |||
| dtos.add(dto); | |||
| SysDeptPo deptPo = deptMapper.selectById(item.getDeptId()); | |||
| if (deptPo!=null) { | |||
| dto.setDeptName(deptPo.getName()); | |||
| List<List<String>> re = new ArrayList<>(); | |||
| if (list != null && list.size() > 0) { | |||
| re = attendanceService.groupAndTransform(list, start, end); | |||
| } | |||
| String fileName = URLEncoder.encode("考勤数据导出", "UTF-8").replaceAll("\\+", "%20"); | |||
| response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx"); | |||
| WriteFont contentWriteFont = new WriteFont(); | |||
| contentWriteFont.setFontHeightInPoints((short)16); | |||
| contentWriteFont.setBold(true); | |||
| WriteFont contentWriteFont2 = new WriteFont(); | |||
| contentWriteFont2.setFontHeightInPoints((short)12); | |||
| contentWriteFont2.setColor(IndexedColors.RED.getIndex()); | |||
| List heads = DmEmpAttendancePo.head(DateUtils.parseLongToDate(dmEmpAttendance.getSTimestamp()), DateUtils.parseLongToDate(dmEmpAttendance.getETimestamp())); | |||
| WriteSheet writeSheet2 = EasyExcel.writerSheet(0, "考勤月度统计表").registerWriteHandler(new CellWriteHandler(){ | |||
| @Override | |||
| public void afterCellDispose(CellWriteHandlerContext context) { | |||
| if (BooleanUtils.isTrue(context.getHead())) { | |||
| WriteCellData<?> cellData = context.getFirstCellData(); | |||
| WriteCellStyle writeCellStyle = cellData.getOrCreateStyle(); | |||
| writeCellStyle.setFillForegroundColor(IndexedColors.LIGHT_GREEN.getIndex()); | |||
| writeCellStyle.setFillPatternType(FillPatternType.SOLID_FOREGROUND); | |||
| writeCellStyle.setShrinkToFit(true); | |||
| context.getRow().setHeight((short) (900)); | |||
| if (context.getRow().getRowNum()== 0 || context.getRow().getRowNum()== 1) { | |||
| writeCellStyle.setWriteFont(contentWriteFont); | |||
| } | |||
| context.getRow().getSheet().setColumnWidth(context.getColumnIndex(), 3000); | |||
| } else { | |||
| String str = context.getCell().getStringCellValue(); | |||
| if (str != null) { | |||
| context.getRow().setHeight((short) (450)); | |||
| } | |||
| if (str != null && (str.contains("迟到") || str.contains("早退")|| str.contains("缺勤"))) { | |||
| WriteCellData<?> cellData = context.getFirstCellData(); | |||
| WriteCellStyle writeCellStyle = cellData.getOrCreateStyle(); | |||
| writeCellStyle.setFillForegroundColor(IndexedColors.LIGHT_GREEN.getIndex()); | |||
| writeCellStyle.setFillPatternType(FillPatternType.SOLID_FOREGROUND); | |||
| writeCellStyle.setShrinkToFit(true); | |||
| writeCellStyle.setWriteFont(contentWriteFont2); | |||
| } | |||
| } | |||
| } | |||
| }); | |||
| util.exportExcel(response, dtos, StrUtil.format("{}数据", getNodeName())); | |||
| }).head(heads).build(); | |||
| excelWriter.write(re, writeSheet2); | |||
| WriteSheet writeSheet = EasyExcel.writerSheet(1, "考勤流水记录表").head(DmEmpAttendancePo.class).includeColumnFieldNames(annotatedFields).build(); | |||
| excelWriter.write(list, writeSheet); | |||
| } catch (IOException e) { | |||
| throw new RuntimeException(e); | |||
| } catch (ParseException e) { | |||
| throw new RuntimeException(e); | |||
| } | |||
| } | |||
| @@ -0,0 +1,46 @@ | |||
| package com.xueyi.system.staff.domain.converter; | |||
| import com.alibaba.excel.converters.Converter; | |||
| import com.alibaba.excel.enums.CellDataTypeEnum; | |||
| import com.alibaba.excel.metadata.GlobalConfiguration; | |||
| import com.alibaba.excel.metadata.data.WriteCellData; | |||
| import com.alibaba.excel.metadata.property.ExcelContentProperty; | |||
| import com.xueyi.common.cache.utils.DictUtil; | |||
| import com.xueyi.system.api.dict.domain.dto.SysDictDataDto; | |||
| import java.util.List; | |||
| /** | |||
| * @author yk | |||
| * @description EasyExcel 用户类型转换 int 转 string | |||
| * @date 2023-12-27 15:31 | |||
| */ | |||
| public class DescTypeConverter implements Converter<Integer> { | |||
| @Override | |||
| public Class supportJavaTypeKey() { | |||
| return Integer.class; | |||
| } | |||
| @Override | |||
| public CellDataTypeEnum supportExcelTypeKey() { | |||
| return CellDataTypeEnum.STRING; | |||
| } | |||
| @Override | |||
| public WriteCellData<String> convertToExcelData(Integer integer, ExcelContentProperty excelContentProperty, GlobalConfiguration globalConfiguration) throws Exception { | |||
| List<SysDictDataDto> dictDataDtos = DictUtil.getDictCache("dm_attendance_desc"); | |||
| String val = ""; | |||
| for (SysDictDataDto dictDataDto : dictDataDtos) { | |||
| if (dictDataDto.getValue().equals(integer.toString())) { | |||
| val = dictDataDto.getLabel(); | |||
| break; | |||
| } | |||
| } | |||
| return new WriteCellData<>(val); | |||
| } | |||
| } | |||
| @@ -0,0 +1,32 @@ | |||
| package com.xueyi.system.staff.domain.converter; | |||
| import com.alibaba.excel.converters.Converter; | |||
| import com.alibaba.excel.enums.CellDataTypeEnum; | |||
| import com.alibaba.excel.metadata.GlobalConfiguration; | |||
| import com.alibaba.excel.metadata.data.WriteCellData; | |||
| import com.alibaba.excel.metadata.property.ExcelContentProperty; | |||
| import com.xueyi.common.core.utils.core.NumberUtil; | |||
| /** | |||
| * @author yk | |||
| * @description EalExcel duration转换 | |||
| * @date 2023-12-27 15:31 | |||
| */ | |||
| public class DurationConverter implements Converter<Integer> { | |||
| @Override | |||
| public Class supportJavaTypeKey() { | |||
| return Integer.class; | |||
| } | |||
| @Override | |||
| public CellDataTypeEnum supportExcelTypeKey() { | |||
| return CellDataTypeEnum.STRING; | |||
| } | |||
| @Override | |||
| public WriteCellData<String> convertToExcelData(Integer integer, ExcelContentProperty excelContentProperty, GlobalConfiguration globalConfiguration) throws Exception { | |||
| return new WriteCellData<>(NumberUtil.convertMinutesToHoursMinutes(integer)); | |||
| } | |||
| } | |||
| @@ -0,0 +1,43 @@ | |||
| package com.xueyi.system.staff.domain.converter; | |||
| import com.alibaba.excel.converters.Converter; | |||
| import com.alibaba.excel.enums.CellDataTypeEnum; | |||
| import com.alibaba.excel.metadata.GlobalConfiguration; | |||
| import com.alibaba.excel.metadata.data.WriteCellData; | |||
| import com.alibaba.excel.metadata.property.ExcelContentProperty; | |||
| import com.xueyi.common.cache.utils.DictUtil; | |||
| import com.xueyi.system.api.dict.domain.dto.SysDictDataDto; | |||
| import java.util.List; | |||
| /** | |||
| * @author yk | |||
| * @description EasyExcel 用户类型转换 int 转 string | |||
| * @date 2023-12-27 15:31 | |||
| */ | |||
| public class UserTypeConverter implements Converter<Long> { | |||
| @Override | |||
| public Class supportJavaTypeKey() { | |||
| return Integer.class; | |||
| } | |||
| @Override | |||
| public CellDataTypeEnum supportExcelTypeKey() { | |||
| return CellDataTypeEnum.STRING; | |||
| } | |||
| @Override | |||
| public WriteCellData<String> convertToExcelData(Long integer, ExcelContentProperty excelContentProperty, GlobalConfiguration globalConfiguration) throws Exception { | |||
| List<SysDictDataDto> dictDataDtos = DictUtil.getDictCache("dm_emp_type"); | |||
| String val = ""; | |||
| for (SysDictDataDto dictDataDto : dictDataDtos) { | |||
| if (dictDataDto.getValue().equals(integer.toString())) { | |||
| val = dictDataDto.getLabel(); | |||
| break; | |||
| } | |||
| } | |||
| return new WriteCellData<>(val); | |||
| } | |||
| } | |||
| @@ -1,13 +1,25 @@ | |||
| package com.xueyi.system.staff.domain.po; | |||
| import com.alibaba.excel.annotation.ExcelProperty; | |||
| import com.alibaba.excel.annotation.format.DateTimeFormat; | |||
| import com.alibaba.excel.annotation.write.style.ColumnWidth; | |||
| import com.alibaba.excel.annotation.write.style.ContentRowHeight; | |||
| import com.alibaba.excel.annotation.write.style.HeadRowHeight; | |||
| import com.alibaba.excel.annotation.write.style.HeadStyle; | |||
| import com.alibaba.excel.enums.poi.FillPatternTypeEnum; | |||
| import com.alibaba.excel.util.ListUtils; | |||
| import com.baomidou.mybatisplus.annotation.TableName; | |||
| import com.xueyi.common.core.annotation.Excel; | |||
| import com.xueyi.common.core.web.tenant.base.TBaseEntity; | |||
| import com.xueyi.common.web.utils.DateUtils; | |||
| import com.xueyi.system.staff.domain.converter.DurationConverter; | |||
| import com.xueyi.system.staff.domain.converter.UserTypeConverter; | |||
| import lombok.Data; | |||
| import lombok.EqualsAndHashCode; | |||
| import java.io.Serial; | |||
| import java.util.Arrays; | |||
| import java.util.Date; | |||
| import java.util.List; | |||
| import static com.xueyi.common.core.constant.basic.EntityConstants.NAME; | |||
| import static com.xueyi.common.core.constant.basic.EntityConstants.REMARK; | |||
| @@ -22,39 +34,71 @@ import static com.xueyi.common.core.constant.basic.EntityConstants.STATUS; | |||
| @Data | |||
| @EqualsAndHashCode(callSuper = true) | |||
| @TableName(value = "dm_emp_attendance", excludeProperty = { STATUS, SORT, REMARK, NAME }) | |||
| @HeadRowHeight(40) | |||
| @ContentRowHeight(20) | |||
| @ColumnWidth(20) | |||
| @HeadStyle(fillForegroundColor = 34, fillPatternType = FillPatternTypeEnum.SOLID_FOREGROUND) | |||
| public class DmEmpAttendancePo extends TBaseEntity { | |||
| @Serial | |||
| private static final long serialVersionUID = 1L; | |||
| @ExcelProperty("日期") | |||
| @ColumnWidth(25) | |||
| private String dateStr; | |||
| /** 人员名 */ | |||
| @Excel(name = "人员名", sort = 3) | |||
| @ExcelProperty("人员名") | |||
| protected String userName; | |||
| /** 人员ID */ | |||
| @Excel(name = "人员ID", sort = 2) | |||
| protected Long userId; | |||
| /** 人员类型 */ | |||
| @Excel(name = "人员类型", readConverterExp = "5=员工,4=高管", sort = 4) | |||
| @ExcelProperty(value = "人员类型", converter = UserTypeConverter.class) | |||
| protected Long userType; | |||
| /** 当日最早打卡记录 */ | |||
| @DateTimeFormat("HH:mm") | |||
| @ExcelProperty("上班打卡") | |||
| protected Date checkInTime; | |||
| /** 当日最晚打卡记录 */ | |||
| @DateTimeFormat("HH:mm") | |||
| @ExcelProperty("下班打卡") | |||
| protected Date checkOutTime; | |||
| /** 工作时长(分钟) */ | |||
| @Excel(name = "工作时长", readConverterExp = "分=钟", sort = 8) | |||
| @ExcelProperty(value = "工作时长", converter = DurationConverter.class) | |||
| protected Integer workDuration; | |||
| /** 所属组织ID */ | |||
| protected Long deptId; | |||
| @Excel(name = "日期", sort = 1) | |||
| private String dateStr; | |||
| // @ExcelProperty(value = "考勤状态", converter = DescTypeConverter.class) | |||
| protected Integer descStatus; | |||
| public static List<List<String>> head(Date startDate, Date endDate) { | |||
| List<String> base = Arrays.asList("考勤记录", DateUtils.formatDate(startDate,"yyyy年MM月dd日")+" 到 "+DateUtils.formatDate(endDate,"yyyy年MM月dd日")); | |||
| List<List<String>> head = ListUtils.newArrayList(); | |||
| List<String> _headRow = ListUtils.newArrayList(base); | |||
| _headRow.add(DateUtils.formatDate(startDate, "姓名")); | |||
| head.add(_headRow); | |||
| //从startDate到endDate开始循环 | |||
| while (startDate.compareTo(endDate) <= 0) { | |||
| List<String> headRow = ListUtils.newArrayList(base); | |||
| headRow.add(DateUtils.formatDate(startDate, "MM月dd日")); | |||
| List<String> headRow2 = ListUtils.newArrayList(headRow); | |||
| headRow2.add(DateUtils.getChineseWeek(startDate)); | |||
| head.add(headRow2); | |||
| startDate = DateUtils.addDays(startDate, 1); | |||
| } | |||
| return head; | |||
| } | |||
| } | |||
| @@ -1,9 +1,13 @@ | |||
| package com.xueyi.system.staff.service; | |||
| import com.xueyi.common.web.annotation.TenantIgnore; | |||
| import com.xueyi.system.staff.domain.query.DmEmpAttendanceQuery; | |||
| import com.xueyi.system.staff.domain.dto.DmEmpAttendanceDto; | |||
| import com.xueyi.common.web.entity.service.IBaseService; | |||
| import com.xueyi.system.staff.domain.dto.DmEmpAttendanceDto; | |||
| import com.xueyi.system.staff.domain.po.DmEmpAttendancePo; | |||
| import com.xueyi.system.staff.domain.query.DmEmpAttendanceQuery; | |||
| import java.util.Date; | |||
| import java.util.List; | |||
| /** | |||
| * 员工考勤管理 服务层 | |||
| @@ -14,4 +18,7 @@ public interface IDmEmpAttendanceService extends IBaseService<DmEmpAttendanceQue | |||
| @TenantIgnore(tenantLine = true) | |||
| public Integer selectCountIgnoreTenant(); | |||
| public List<List<String>> groupAndTransform(List<DmEmpAttendancePo> list, Date start, Date end); | |||
| } | |||
| @@ -1,19 +1,31 @@ | |||
| package com.xueyi.system.staff.service.impl; | |||
| import cn.hutool.core.date.LocalDateTimeUtil; | |||
| import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; | |||
| import com.xueyi.common.cache.utils.DictUtil; | |||
| import com.xueyi.common.core.utils.DateUtil; | |||
| import com.xueyi.common.web.annotation.TenantIgnore; | |||
| import com.xueyi.common.web.entity.service.impl.BaseServiceImpl; | |||
| import com.xueyi.system.api.dict.domain.dto.SysDictDataDto; | |||
| import com.xueyi.system.staff.domain.dto.DmEmpAttendanceDto; | |||
| import com.xueyi.system.staff.domain.po.DmEmpAttendancePo; | |||
| import com.xueyi.system.staff.domain.query.DmEmpAttendanceQuery; | |||
| import com.xueyi.system.staff.manager.IDmEmpAttendanceManager; | |||
| import com.xueyi.system.staff.mapper.DmEmpAttendanceMapper; | |||
| import com.xueyi.system.staff.service.IDmEmpAttendanceService; | |||
| import com.xueyi.system.staff.manager.IDmEmpAttendanceManager; | |||
| import com.xueyi.common.web.entity.service.impl.BaseServiceImpl; | |||
| import org.springframework.beans.factory.annotation.Autowired; | |||
| import org.springframework.data.redis.core.RedisTemplate; | |||
| import org.springframework.stereotype.Service; | |||
| import java.io.Serializable; | |||
| import java.time.LocalDate; | |||
| import java.time.ZoneId; | |||
| import java.util.ArrayList; | |||
| import java.util.Collections; | |||
| import java.util.Date; | |||
| import java.util.List; | |||
| import java.util.Map; | |||
| import java.util.stream.Collectors; | |||
| /** | |||
| * 员工考勤管理 服务层处理 | |||
| @@ -54,6 +66,38 @@ public class DmEmpAttendanceServiceImpl extends BaseServiceImpl<DmEmpAttendanceQ | |||
| } | |||
| } | |||
| @Override | |||
| public List<List<String>> groupAndTransform(List<DmEmpAttendancePo> list, Date start, Date end) { | |||
| Map<String, Map<LocalDate, List<DmEmpAttendancePo>>> grouped = list.stream() | |||
| .collect(Collectors.groupingBy(DmEmpAttendancePo::getUserName, | |||
| Collectors.groupingBy(a -> LocalDate.ofInstant(DateUtil.parseDate(a.getDateStr()).toInstant(), ZoneId.systemDefault())))); | |||
| // Find start and end dates | |||
| LocalDate startDate = LocalDateTimeUtil.of(start).toLocalDate(); | |||
| LocalDate endDate = LocalDateTimeUtil.of(end).toLocalDate(); | |||
| List<SysDictDataDto> dictDataDtos = DictUtil.getDictCache("dm_attendance_desc"); | |||
| Map<String, String> dictMap = dictDataDtos.stream().collect(Collectors.toMap(SysDictDataDto::getValue, SysDictDataDto::getLabel)); | |||
| List<LocalDate> dateRange = startDate.datesUntil(endDate.plusDays(1)).collect(Collectors.toList()); | |||
| return grouped.entrySet().stream() | |||
| .map(entry -> { | |||
| List<String> row = new ArrayList<>(); | |||
| row.add(entry.getKey()); // Add name | |||
| for (LocalDate date : dateRange) { | |||
| List<DmEmpAttendancePo> dateList = entry.getValue().getOrDefault(date, Collections.emptyList()); | |||
| String status = dateList.isEmpty() ? "" : dictMap.get(dateList.get(0).getDescStatus().toString()); | |||
| row.add(status); | |||
| } | |||
| return row; | |||
| }) | |||
| .collect(Collectors.toList()); | |||
| } | |||
| public void updRedisCount(){ | |||
| if (redisTemplate.hasKey("dashboard:attendance")) { | |||
| redisTemplate.opsForValue().increment("dashboard:attendance"); | |||
| @@ -2,13 +2,18 @@ package com.xueyi.system.staff.service.impl; | |||
| import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; | |||
| import com.baomidou.mybatisplus.core.toolkit.StringUtils; | |||
| import com.xueyi.common.core.utils.DateUtil; | |||
| import com.xueyi.common.web.annotation.TenantIgnore; | |||
| import com.xueyi.common.web.entity.service.impl.BaseServiceImpl; | |||
| import com.xueyi.common.web.utils.DateUtils; | |||
| import com.xueyi.system.api.organize.domain.vo.SysDeptExt; | |||
| import com.xueyi.system.api.pass.domain.po.DmRecognizedRecordsPo; | |||
| import com.xueyi.system.api.staff.domain.dto.DmStaffDto; | |||
| import com.xueyi.system.api.staff.domain.po.DmStaffPo; | |||
| import com.xueyi.system.api.staff.domain.vo.DmStaffFeature; | |||
| import com.xueyi.system.common.domain.po.DmHolidayPo; | |||
| import com.xueyi.system.common.service.IDmHolidayService; | |||
| import com.xueyi.system.organize.mapper.SysDeptExtMapper; | |||
| import com.xueyi.system.staff.domain.po.DmEmpAttendancePo; | |||
| import com.xueyi.system.staff.domain.query.DmStaffQuery; | |||
| import com.xueyi.system.staff.manager.IDmStaffManager; | |||
| @@ -18,8 +23,11 @@ import com.xueyi.system.staff.service.IDmStaffService; | |||
| import org.springframework.beans.factory.annotation.Autowired; | |||
| import org.springframework.stereotype.Service; | |||
| import javax.annotation.PostConstruct; | |||
| import java.util.Date; | |||
| import java.util.HashMap; | |||
| import java.util.List; | |||
| import java.util.Map; | |||
| /** | |||
| * 人员管理 服务层处理 | |||
| @@ -29,12 +37,34 @@ import java.util.List; | |||
| @Service | |||
| public class DmStaffServiceImpl extends BaseServiceImpl<DmStaffQuery, DmStaffDto, IDmStaffManager> implements IDmStaffService { | |||
| // Map<String, Integer> STATUS_TYPE = MapUtil.; | |||
| private Map<String, Integer> statusMap; | |||
| @Autowired | |||
| private IDmHolidayService holidayService; | |||
| @PostConstruct | |||
| public void initializeMap() { | |||
| // 初始化Map | |||
| statusMap = new HashMap<>(); | |||
| statusMap.put("NORMAL", 0); | |||
| statusMap.put("BE_LATER", 1); | |||
| statusMap.put("LEAVE_EARLY", 2); | |||
| statusMap.put("ABSENCE", 3); | |||
| statusMap.put("OVERTIME", 4); | |||
| statusMap.put("LATER_AND_EARLY", 6); | |||
| // 继续初始化其他常量... | |||
| } | |||
| @Autowired | |||
| DmStaffMapper staffMapper; | |||
| @Autowired | |||
| DmEmpAttendanceMapper dmEmpAttendanceMapper; | |||
| @Autowired | |||
| SysDeptExtMapper sysDeptExtMapper; | |||
| @Autowired | |||
| private DmEmpAttendanceServiceImpl dmEmpAttendanceService; | |||
| /** | |||
| @@ -106,6 +136,7 @@ public class DmStaffServiceImpl extends BaseServiceImpl<DmStaffQuery, DmStaffDto | |||
| } | |||
| DmEmpAttendancePo empAttendance = dmEmpAttendanceMapper.findByEmpAndDate(checkTimeDateStr, userId); | |||
| SysDeptExt ext = sysDeptExtMapper.selectWorkTimeByDeptId(emp.getDeptId()); | |||
| if (null != empAttendance) { | |||
| @@ -115,12 +146,27 @@ public class DmStaffServiceImpl extends BaseServiceImpl<DmStaffQuery, DmStaffDto | |||
| empAttendance.setCheckOutTime(checkTime); | |||
| } | |||
| if (null!=empAttendance.getCheckInTime() && null != empAttendance.getCheckOutTime()) { | |||
| Date cin = empAttendance.getCheckInTime(); | |||
| Date cout = empAttendance.getCheckOutTime(); | |||
| Integer diffMin = DateUtils.dateDiffMin(cin, cout); | |||
| empAttendance.setWorkDuration(diffMin); | |||
| } | |||
| if (checkTime.getTime() < DateUtil.parseDate(ext.getOffDutyHourStart()).getTime()) { | |||
| if (statusMap.get("NORMAL") == empAttendance.getDescStatus()) { | |||
| empAttendance.setDescStatus(statusMap.get("LEAVE_EARLY")); | |||
| } else if (statusMap.get("BE_LATER") == empAttendance.getDescStatus()){ | |||
| empAttendance.setDescStatus(statusMap.get("LATER_AND_EARLY")); | |||
| } | |||
| } else { //如果修改考勤时间,则对应修改考勤状态 | |||
| if (statusMap.get("LATER_AND_EARLY") == empAttendance.getDescStatus()) { | |||
| empAttendance.setDescStatus(statusMap.get("BE_LATER")); | |||
| } else if (statusMap.get("LEAVE_EARLY") == empAttendance.getDescStatus()){ | |||
| empAttendance.setDescStatus(statusMap.get("NORMAL")); | |||
| } | |||
| } | |||
| QueryWrapper<DmEmpAttendancePo> wrapper = new QueryWrapper<>(); | |||
| wrapper.eq("id",empAttendance.getId()); | |||
| dmEmpAttendanceMapper.update(empAttendance, wrapper); | |||
| @@ -129,6 +175,17 @@ public class DmStaffServiceImpl extends BaseServiceImpl<DmStaffQuery, DmStaffDto | |||
| DmEmpAttendancePo ea = new DmEmpAttendancePo(); | |||
| Date checkDate = DateUtils.parseStrToDate(DateUtils.formatDate(checkTime, "yyyy-MM-dd HH:mm:ss"), "yyyy-MM-dd HH:mm:ss"); | |||
| ea.setCheckInTime(checkDate); | |||
| DmHolidayPo holidayPo = holidayService.isHoliday(checkDate); | |||
| if (checkDate.getTime() > DateUtil.parseDate(ext.getOnDutyHourEnd()).getTime()) { | |||
| ea.setDescStatus(statusMap.get("BE_LATER")); // 迟到 | |||
| if (holidayPo.getHoliday() == 1) { | |||
| ea.setDescStatus(statusMap.get("OVERTIME")); | |||
| } | |||
| } else { | |||
| if (holidayPo.getHoliday() == 1) { | |||
| ea.setDescStatus(statusMap.get("OVERTIME")); | |||
| } | |||
| } | |||
| ea.setDateStr(DateUtils.formatDate(new Date(), "yyyy-MM-dd")); | |||
| ea.setUserId(userId); | |||