diff --git a/backend/pom.xml b/backend/pom.xml index 950c890a..66e4440d 100644 --- a/backend/pom.xml +++ b/backend/pom.xml @@ -407,6 +407,13 @@ ${revision} + + + org.dromara + ruoyi-zsjy + ${revision} + + - + org.dromara diff --git a/backend/ruoyi-modules/pom.xml b/backend/ruoyi-modules/pom.xml index 212e63c6..2983d764 100644 --- a/backend/ruoyi-modules/pom.xml +++ b/backend/ruoyi-modules/pom.xml @@ -16,7 +16,7 @@ ruoyi-workflow ruoyi-xg - + ruoyi-zsjy ruoyi-hq ruoyi-aqbw ruoyi-cw diff --git a/backend/ruoyi-modules/ruoyi-zsjy/src/main/java/org/dromara/zsjy/controller/ZsjyInternshipDailyController.java b/backend/ruoyi-modules/ruoyi-zsjy/src/main/java/org/dromara/zsjy/controller/ZsjyInternshipDailyController.java index 2c46276b..2e39137e 100644 --- a/backend/ruoyi-modules/ruoyi-zsjy/src/main/java/org/dromara/zsjy/controller/ZsjyInternshipDailyController.java +++ b/backend/ruoyi-modules/ruoyi-zsjy/src/main/java/org/dromara/zsjy/controller/ZsjyInternshipDailyController.java @@ -72,15 +72,15 @@ public class ZsjyInternshipDailyController extends BaseController { */ @Operation(summary = "获取学生考勤日历", description = "查看指定学生的考勤日历数据") @SaCheckPermission("zsjy:internshipdaily:calendar") - @GetMapping("/calendar/{studentId}") + @GetMapping("/calendar") public R>> getCalendar( - @Parameter(description = "学生ID", required = true) @PathVariable Long studentId, + @Parameter(description = "学生ID", required = true) @RequestParam Long studentId, @Parameter(description = "年份") @RequestParam(required = false) Integer year, @Parameter(description = "月份") @RequestParam(required = false) Integer month) { log.info("=== Controller层调试 ==="); - log.info("接口被调用: /zsjy/internship/daily/calendar/{}", studentId); - log.info("查询年月: {}-{}", year, month); + log.info("接口被调用: /zsjy/internship/daily/calendar"); + log.info("学生ID: {}, 查询年月: {}-{}", studentId, year, month); return dailyService.getCalendarData(studentId, year, month); } diff --git a/backend/ruoyi-modules/ruoyi-zsjy/src/main/java/org/dromara/zsjy/domain/ZsjyInternshipDaily.java b/backend/ruoyi-modules/ruoyi-zsjy/src/main/java/org/dromara/zsjy/domain/ZsjyInternshipDaily.java index 16e0229b..df363b7e 100644 --- a/backend/ruoyi-modules/ruoyi-zsjy/src/main/java/org/dromara/zsjy/domain/ZsjyInternshipDaily.java +++ b/backend/ruoyi-modules/ruoyi-zsjy/src/main/java/org/dromara/zsjy/domain/ZsjyInternshipDaily.java @@ -69,25 +69,25 @@ public class ZsjyInternshipDaily extends BaseEntity { * 签到地点 (对应数据库check_in_location字段) */ @TableField("check_in_location") - private String checkOutLocation; + private String checkInLocation; /** * 签到经度 (对应数据库longitude字段) */ @TableField("longitude") - private BigDecimal checkOutLongitude; + private BigDecimal longitude; /** * 签到纬度 (对应数据库latitude字段) */ @TableField("latitude") - private BigDecimal checkOutLatitude; + private BigDecimal latitude; /** * 工作内容/日总结 */ @TableField("daily_summary") - private String workContent; + private String dailySummary; /** * 图片附件(JSON格式) @@ -157,11 +157,7 @@ public class ZsjyInternshipDaily extends BaseEntity { @TableField(exist = false) private String position; - /** - * 签到地点 (业务扩展字段,当前只有签退地点) - */ - @TableField(exist = false) - private String checkInLocation; + /** * 签到经度 (业务扩展字段,当前只有签退经度) diff --git a/backend/ruoyi-modules/ruoyi-zsjy/src/main/java/org/dromara/zsjy/domain/vo/ZsjyInternshipDailyVo.java b/backend/ruoyi-modules/ruoyi-zsjy/src/main/java/org/dromara/zsjy/domain/vo/ZsjyInternshipDailyVo.java index 8f7e4844..61b1e74e 100644 --- a/backend/ruoyi-modules/ruoyi-zsjy/src/main/java/org/dromara/zsjy/domain/vo/ZsjyInternshipDailyVo.java +++ b/backend/ruoyi-modules/ruoyi-zsjy/src/main/java/org/dromara/zsjy/domain/vo/ZsjyInternshipDailyVo.java @@ -7,7 +7,7 @@ import lombok.Data; import java.io.Serial; import java.io.Serializable; import java.math.BigDecimal; -import java.sql.Time; +import java.time.LocalTime; import java.util.Date; /** @@ -53,7 +53,14 @@ public class ZsjyInternshipDailyVo implements Serializable { */ @Schema(description = "签到时间") @JsonFormat(pattern = "HH:mm:ss") - private Time checkInTime; + private LocalTime checkInTime; + + /** + * 签退时间 + */ + @Schema(description = "签退时间") + @JsonFormat(pattern = "HH:mm:ss") + private LocalTime checkOutTime; /** * 签到位置 @@ -155,6 +162,18 @@ public class ZsjyInternshipDailyVo implements Serializable { @Schema(description = "学号") private String studentNo; + /** + * 学号(前端兼容字段) + */ + @Schema(description = "学号") + private String studentNumber; + + /** + * 工作时长(小时) + */ + @Schema(description = "工作时长") + private BigDecimal workDuration; + /** * 公司名称 */ diff --git a/backend/ruoyi-modules/ruoyi-zsjy/src/main/java/org/dromara/zsjy/service/impl/ZsjyInternshipDailyServiceImpl.java b/backend/ruoyi-modules/ruoyi-zsjy/src/main/java/org/dromara/zsjy/service/impl/ZsjyInternshipDailyServiceImpl.java index 9f5c97db..724291dd 100644 --- a/backend/ruoyi-modules/ruoyi-zsjy/src/main/java/org/dromara/zsjy/service/impl/ZsjyInternshipDailyServiceImpl.java +++ b/backend/ruoyi-modules/ruoyi-zsjy/src/main/java/org/dromara/zsjy/service/impl/ZsjyInternshipDailyServiceImpl.java @@ -50,7 +50,7 @@ public class ZsjyInternshipDailyServiceImpl implements IZsjyInternshipDailyServi public TableDataInfo queryPageList(ZsjyInternshipDailyQueryBo queryBo, PageQuery pageQuery) { Page page = pageQuery.build(); List list = baseMapper.selectDailyList(page, queryBo); - return TableDataInfo.build(page); + return TableDataInfo.build(list); } /** @@ -97,10 +97,10 @@ public class ZsjyInternshipDailyServiceImpl implements IZsjyInternshipDailyServi entity.setStudentId(addBo.getStudentId()); entity.setCheckDate(addBo.getCheckDate()); entity.setCheckInTime(addBo.getCheckInTime()); - entity.setCheckOutLocation(addBo.getCheckOutLocation()); // 对应数据库check_in_location字段 - entity.setCheckOutLatitude(addBo.getCheckOutLatitude()); // 对应数据库latitude字段 - entity.setCheckOutLongitude(addBo.getCheckOutLongitude()); // 对应数据库longitude字段 - entity.setWorkContent(addBo.getWorkContent()); // 对应数据库daily_summary字段 + entity.setCheckInLocation(addBo.getCheckOutLocation()); // 对应数据库check_in_location字段 + entity.setLatitude(addBo.getCheckOutLatitude()); // 对应数据库latitude字段 + entity.setLongitude(addBo.getCheckOutLongitude()); // 对应数据库longitude字段 + entity.setDailySummary(addBo.getWorkContent()); // 对应数据库daily_summary字段 entity.setImages(addBo.getImages()); entity.setIsException(addBo.getIsException()); entity.setExceptionReason(addBo.getExceptionReason()); @@ -188,11 +188,10 @@ public class ZsjyInternshipDailyServiceImpl implements IZsjyInternshipDailyServi // 2. 补充统计信息 if (ObjectUtil.isNull(statistics)) { statistics = new HashMap<>(); - statistics.put("totalDays", 0); - statistics.put("attendanceDays", 0); - statistics.put("exceptionDays", 0); - statistics.put("pendingExceptions", 0); - statistics.put("attendanceRate", 0.0); + statistics.put("totalStudents", 0); + statistics.put("todayCheckedIn", 0); + statistics.put("todayLate", 0); + statistics.put("attendanceRate", "0%"); } return R.ok(statistics); diff --git a/backend/ruoyi-modules/ruoyi-zsjy/src/main/resources/mapper/ZsjyInternshipDailyMapper.xml b/backend/ruoyi-modules/ruoyi-zsjy/src/main/resources/mapper/ZsjyInternshipDailyMapper.xml index 55e10ec7..e1904a0e 100644 --- a/backend/ruoyi-modules/ruoyi-zsjy/src/main/resources/mapper/ZsjyInternshipDailyMapper.xml +++ b/backend/ruoyi-modules/ruoyi-zsjy/src/main/resources/mapper/ZsjyInternshipDailyMapper.xml @@ -9,6 +9,7 @@ + @@ -26,7 +27,9 @@ + + @@ -37,6 +40,7 @@ d.student_id, d.check_date, d.check_in_time, + d.check_out_time, d.check_in_location, d.latitude, d.longitude, @@ -54,7 +58,13 @@ -- 关联查询扩展字段 i.student_name, i.student_no, - i.company_name + i.company_name, + -- 计算工作时长(小时) + CASE + WHEN d.check_in_time IS NOT NULL AND d.check_out_time IS NOT NULL THEN + ROUND(TIMESTAMPDIFF(MINUTE, d.check_in_time, d.check_out_time) / 60.0, 2) + ELSE NULL + END as work_duration FROM zsjy_internship_daily d LEFT JOIN zsjy_internship_info i ON d.internship_id = i.internship_id @@ -126,34 +136,43 @@ SELECT - COUNT(*) as totalDays, - SUM(CASE WHEN check_in_time IS NOT NULL THEN 1 ELSE 0 END) as attendanceDays, - SUM(CASE WHEN is_exception = '1' THEN 1 ELSE 0 END) as exceptionDays, - SUM(CASE WHEN is_exception = '1' AND exception_status = '0' THEN 1 ELSE 0 END) as pendingExceptions, - ROUND( - SUM(CASE WHEN check_in_time IS NOT NULL THEN 1 ELSE 0 END) * 100.0 / - NULLIF(COUNT(*), 0), 2 + -- 实习学生总数 + (SELECT COUNT(DISTINCT student_id) + FROM zsjy_internship_daily + WHERE deleted = 0) as totalStudents, + + -- 今日已签到 + (SELECT COUNT(DISTINCT student_id) + FROM zsjy_internship_daily + WHERE deleted = 0 + AND check_date = CURDATE() + AND check_in_time IS NOT NULL) as todayCheckedIn, + + -- 今日迟到(假设9:00之后签到为迟到) + (SELECT COUNT(DISTINCT student_id) + FROM zsjy_internship_daily + WHERE deleted = 0 + AND check_date = CURDATE() + AND check_in_time > '09:00:00') as todayLate, + + -- 本月出勤率 + CONCAT( + ROUND( + (SELECT COUNT(*) + FROM zsjy_internship_daily + WHERE deleted = 0 + AND YEAR(check_date) = YEAR(CURDATE()) + AND MONTH(check_date) = MONTH(CURDATE()) + AND check_in_time IS NOT NULL) * 100.0 / + NULLIF( + (SELECT COUNT(*) + FROM zsjy_internship_daily + WHERE deleted = 0 + AND YEAR(check_date) = YEAR(CURDATE()) + AND MONTH(check_date) = MONTH(CURDATE())), 0 + ), 1 + ), '%' ) as attendanceRate - FROM zsjy_internship_daily d - LEFT JOIN zsjy_internship_info i ON d.internship_id = i.internship_id - - d.deleted = 0 - - AND d.student_id = #{queryBo.studentId} - - - AND d.internship_id = #{queryBo.internshipId} - - - AND d.check_date >= #{queryBo.checkDateStart} - - - AND d.check_date <= #{queryBo.checkDateEnd} - - - AND i.company_name LIKE CONCAT('%', #{queryBo.companyName}, '%') - - diff --git a/web/src/views/zsjy/internship/daily/checkin.vue b/web/src/views/zsjy/internship/daily/checkin.vue index 0c736d48..8b476ddf 100644 --- a/web/src/views/zsjy/internship/daily/checkin.vue +++ b/web/src/views/zsjy/internship/daily/checkin.vue @@ -36,7 +36,7 @@ 已签到 - {{ parseTime(todayRecord.checkInTime, '{h}:{i}') }} + {{ todayRecord.checkInTime }} @@ -184,12 +184,12 @@ - {{ scope.row.checkInTime ? parseTime(scope.row.checkInTime, '{h}:{i}') : '-' }} + {{ scope.row.checkInTime || '-' }} - {{ scope.row.checkOutTime ? parseTime(scope.row.checkOutTime, '{h}:{i}') : '-' }} + {{ scope.row.checkOutTime || '-' }} diff --git a/web/src/views/zsjy/internship/daily/index.vue b/web/src/views/zsjy/internship/daily/index.vue index dbac2d0d..e0d4cd01 100644 --- a/web/src/views/zsjy/internship/daily/index.vue +++ b/web/src/views/zsjy/internship/daily/index.vue @@ -151,7 +151,7 @@ {{ scope.row.studentName }} 学号:{{ scope.row.studentNumber }} - 班级:{{ scope.row.className }} + @@ -161,8 +161,8 @@ - {{ parseTime(scope.row.checkInTime, '{y}-{m}-{d}') }} - {{ parseTime(scope.row.checkInTime, '{h}:{i}') }} + {{ parseTime(scope.row.checkDate, '{y}-{m}-{d}') }} + {{ scope.row.checkInTime }} 未签到 @@ -171,8 +171,8 @@ - {{ parseTime(scope.row.checkOutTime, '{y}-{m}-{d}') }} - {{ parseTime(scope.row.checkOutTime, '{h}:{i}') }} + {{ parseTime(scope.row.checkDate, '{y}-{m}-{d}') }} + {{ scope.row.checkOutTime }} 未签退 @@ -231,10 +231,10 @@ {{ currentRecord.className }} {{ currentRecord.companyName }} - {{ currentRecord.checkInTime ? parseTime(currentRecord.checkInTime) : '未签到' }} + {{ currentRecord.checkInTime || '未签到' }} - {{ currentRecord.checkOutTime ? parseTime(currentRecord.checkOutTime) : '未签退' }} + {{ currentRecord.checkOutTime || '未签退' }} {{ currentRecord.workDuration ? currentRecord.workDuration + '小时' : '-' }} @@ -406,9 +406,10 @@ -
{{ parseTime(todayRecord.checkInTime, '{h}:{i}') }}
{{ todayRecord.checkInTime }}