update wuzhen

This commit is contained in:
wuzhen committed 2025-08-14 15:33:20 +08:00
1 parent 96caabab43
commit b28889161c
6 files changed
+100 -61

No files matched your search

@@ -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;
/**
* 签到经度 (业务扩展字段,当前只有签退经度)
@@ -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;
/**
* 公司名称
*/
@@ -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);
@@ -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>
<!-- 检查学生当日是否已签到 -->
@@ -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
View File
@@ -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);
});
};