wuzhen 1 год назад
Родитель
Сommit
b28889161c

+ 5 - 9
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;
+
 
     /**
      * 签到经度 (业务扩展字段,当前只有签退经度)

+ 21 - 2
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;
+
     /**
      * 公司名称
      */

+ 8 - 9
backend/ruoyi-modules/ruoyi-zsjy/src/main/java/org/dromara/zsjy/service/impl/ZsjyInternshipDailyServiceImpl.java

@@ -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);

+ 47 - 28
backend/ruoyi-modules/ruoyi-zsjy/src/main/resources/mapper/ZsjyInternshipDailyMapper.xml

@@ -9,6 +9,7 @@
         <result property="studentId"              column="student_id"             />
         <result property="checkDate"              column="check_date"             />
         <result property="checkInTime"            column="check_in_time"          />
+        <result property="checkOutTime"           column="check_out_time"         />
         <result property="checkInLocation"        column="check_in_location"      />
         <result property="latitude"               column="latitude"               />
         <result property="longitude"              column="longitude"              />
@@ -26,7 +27,9 @@
         <!-- 扩展字段 -->
         <result property="studentName"            column="student_name"           />
         <result property="studentNo"              column="student_no"             />
+        <result property="studentNumber"          column="student_no"             />
         <result property="companyName"            column="company_name"           />
+        <result property="workDuration"           column="work_duration"          />
     </resultMap>
 
     <!-- 基础SQL片段 -->
@@ -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
     </sql>
@@ -126,34 +136,43 @@
     <!-- 获取考勤统计数据 -->
     <select id="selectStatistics" resultType="java.util.Map">
         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
-        <where>
-            d.deleted = 0
-            <if test="queryBo.studentId != null">
-                AND d.student_id = #{queryBo.studentId}
-            </if>
-            <if test="queryBo.internshipId != null">
-                AND d.internship_id = #{queryBo.internshipId}
-            </if>
-            <if test="queryBo.checkDateStart != null">
-                AND d.check_date &gt;= #{queryBo.checkDateStart}
-            </if>
-            <if test="queryBo.checkDateEnd != null">
-                AND d.check_date &lt;= #{queryBo.checkDateEnd}
-            </if>
-            <if test="queryBo.companyName != null and queryBo.companyName != ''">
-                AND i.company_name LIKE CONCAT('%', #{queryBo.companyName}, '%')
-            </if>
-        </where>
     </select>
 
     <!-- 检查学生当日是否已签到 -->

+ 3 - 3
web/src/views/zsjy/internship/daily/checkin.vue

@@ -36,7 +36,7 @@
                 <el-icon class="status-icon success"><SuccessFilled /></el-icon>
                 <div class="status-text">
                   <h4>已签到</h4>
-                  <p>{{ parseTime(todayRecord.checkInTime, '{h}:{i}') }}</p>
+                  <p>{{ todayRecord.checkInTime }}</p>
                 </div>
               </div>
               <div v-else class="not-checked-in">
@@ -184,12 +184,12 @@
           </el-table-column>
           <el-table-column label="签到时间" width="100">
             <template #default="scope">
-              {{ scope.row.checkInTime ? parseTime(scope.row.checkInTime, '{h}:{i}') : '-' }}
+              {{ scope.row.checkInTime || '-' }}
             </template>
           </el-table-column>
           <el-table-column label="签退时间" width="100">
             <template #default="scope">
-              {{ scope.row.checkOutTime ? parseTime(scope.row.checkOutTime, '{h}:{i}') : '-' }}
+              {{ scope.row.checkOutTime || '-' }}
             </template>
           </el-table-column>
           <el-table-column label="工作时长" width="100">

+ 16 - 10
web/src/views/zsjy/internship/daily/index.vue

@@ -151,7 +151,7 @@
               <div class="student-info">
                 <div class="student-name">{{ scope.row.studentName }}</div>
                 <div class="student-number">学号:{{ scope.row.studentNumber }}</div>
-                <div class="student-class">班级:{{ scope.row.className }}</div>
+                <!-- <div class="student-class">班级:{{ scope.row.className }}</div> -->
               </div>
             </template>
           </el-table-column>
@@ -161,8 +161,8 @@
           <el-table-column label="签到时间" min-width="120" align="center">
             <template #default="scope">
               <div v-if="scope.row.checkInTime">
-                <div>{{ parseTime(scope.row.checkInTime, '{y}-{m}-{d}') }}</div>
-                <div class="time-detail">{{ parseTime(scope.row.checkInTime, '{h}:{i}') }}</div>
+                <div>{{ parseTime(scope.row.checkDate, '{y}-{m}-{d}') }}</div>
+                <div class="time-detail">{{ scope.row.checkInTime }}</div>
               </div>
               <span v-else class="text-danger">未签到</span>
             </template>
@@ -171,8 +171,8 @@
           <el-table-column label="签退时间" min-width="120" align="center">
             <template #default="scope">
               <div v-if="scope.row.checkOutTime">
-                <div>{{ parseTime(scope.row.checkOutTime, '{y}-{m}-{d}') }}</div>
-                <div class="time-detail">{{ parseTime(scope.row.checkOutTime, '{h}:{i}') }}</div>
+                <div>{{ parseTime(scope.row.checkDate, '{y}-{m}-{d}') }}</div>
+                <div class="time-detail">{{ scope.row.checkOutTime }}</div>
               </div>
               <span v-else class="text-muted">未签退</span>
             </template>
@@ -231,10 +231,10 @@
           <el-descriptions-item label="班级">{{ currentRecord.className }}</el-descriptions-item>
           <el-descriptions-item label="实习单位">{{ currentRecord.companyName }}</el-descriptions-item>
           <el-descriptions-item label="签到时间">
-            {{ currentRecord.checkInTime ? parseTime(currentRecord.checkInTime) : '未签到' }}
+            {{ currentRecord.checkInTime || '未签到' }}
           </el-descriptions-item>
           <el-descriptions-item label="签退时间">
-            {{ currentRecord.checkOutTime ? parseTime(currentRecord.checkOutTime) : '未签退' }}
+            {{ currentRecord.checkOutTime || '未签退' }}
           </el-descriptions-item>
           <el-descriptions-item label="工作时长">
             {{ currentRecord.workDuration ? currentRecord.workDuration + '小时' : '-' }}
@@ -406,9 +406,10 @@
   </div>
 </template>
 
-<script setup name="InternshipDaily">
-import { listInternshipDaily, getCalendar, getStatistics, addInternshipDaily } from "@/api/zsjy/internshipDaily";
-import { parseTime } from "@/utils/ruoyi";
+<script setup name="InternshipDaily" lang="ts">
+import { listInternshipDaily, getCalendar, getStatistics, addInternshipDaily } from '@/api/zsjy/internshipDaily';
+import { parseTime } from '@/utils/ruoyi';
+import { User, Check, Warning, TrendCharts } from '@element-plus/icons-vue';
 
 const { proxy } = getCurrentInstance();
 
@@ -508,8 +509,13 @@ const getList = () => {
 
 // 获取统计数据
 const getStatisticsData = () => {
+  console.log('正在获取统计数据...');
   getStatistics().then(response => {
+    console.log('统计数据响应:', response);
     statistics.value = response.data || {};
+    console.log('设置的统计数据:', statistics.value);
+  }).catch(error => {
+    console.error('获取统计数据失败:', error);
   });
 };