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

+ 86 - 0
backend/ruoyi-modules/ruoyi-zsjy/src/main/java/org/dromara/zsjy/controller/InternshipInfoController.java

@@ -0,0 +1,86 @@
+package org.dromara.zsjy.controller;
+
+import cn.dev33.satoken.annotation.SaCheckPermission;
+import org.dromara.common.core.domain.R;
+import org.dromara.common.mybatis.core.page.PageQuery;
+import org.dromara.common.mybatis.core.page.TableDataInfo;
+import org.dromara.common.web.core.BaseController;
+import org.dromara.zsjy.domain.vo.InternshipInfoVO;
+import org.dromara.zsjy.domain.bo.InternshipInfoQueryBO;
+import org.dromara.zsjy.service.IInternshipInfoService;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import jakarta.validation.constraints.NotEmpty;
+import lombok.RequiredArgsConstructor;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+import jakarta.servlet.http.HttpServletResponse;
+
+/**
+ * 实习信息管理Controller
+ *
+ * @author system
+ * @date 2025-01-03
+ */
+@Validated
+@RequiredArgsConstructor
+@RestController
+@RequestMapping("/zsjy/internship")
+@Tag(name = "实习信息管理", description = "班主任查看学生实习情况管理")
+public class InternshipInfoController extends BaseController {
+
+    private final IInternshipInfoService internshipInfoService;
+
+    /**
+     * 查询学生实习信息列表(班主任专用)
+     */
+    @Operation(summary = "查询学生实习信息列表", description = "班主任查看本班学生实习情况")
+    @SaCheckPermission("zsjy:internship:list")
+    @GetMapping("/list")
+    public TableDataInfo<InternshipInfoVO> list(@Validated InternshipInfoQueryBO queryBO, PageQuery pageQuery) {
+        return internshipInfoService.queryPageList(queryBO, pageQuery);
+    }
+
+    /**
+     * 获取学生实习信息详细信息
+     */
+    @Operation(summary = "获取学生实习详情", description = "查看单个学生的实习详细信息")
+    @SaCheckPermission("zsjy:internship:query")
+    @GetMapping("/{studentId}")
+    public R<InternshipInfoVO> getInfo(
+        @Parameter(description = "学生ID", required = true)
+        @PathVariable Long studentId) {
+        return R.ok(internshipInfoService.queryById(studentId));
+    }
+
+    /**
+     * 导出学生实习信息列表
+     */
+    @Operation(summary = "导出学生实习信息", description = "导出班级学生实习情况数据")
+    @SaCheckPermission("zsjy:internship:export")
+    @PostMapping("/export")
+    public void export(@Validated InternshipInfoQueryBO queryBO, HttpServletResponse response) {
+        internshipInfoService.exportInternshipInfo(queryBO, response);
+    }
+
+    /**
+     * 获取班主任管理的班级信息
+     */
+    @Operation(summary = "获取班主任班级", description = "获取当前登录班主任管理的班级列表")
+    @SaCheckPermission("zsjy:internship:class")
+    @GetMapping("/classes")
+    public R<?> getTeacherClasses() {
+        return R.ok(internshipInfoService.getTeacherClasses());
+    }
+
+    /**
+     * 统计实习状态数据
+     */
+    @Operation(summary = "实习状态统计", description = "统计班级学生实习状态分布")
+    @SaCheckPermission("zsjy:internship:statistics")
+    @GetMapping("/statistics")
+    public R<?> getInternshipStatistics(@Validated InternshipInfoQueryBO queryBO) {
+        return R.ok(internshipInfoService.getInternshipStatistics(queryBO));
+    }
+}

+ 139 - 0
backend/ruoyi-modules/ruoyi-zsjy/src/main/java/org/dromara/zsjy/domain/bo/InternshipInfoQueryBO.java

@@ -0,0 +1,139 @@
+package org.dromara.zsjy.domain.bo;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import org.dromara.common.core.validate.QueryGroup;
+import org.dromara.common.mybatis.core.domain.BaseEntity;
+
+import java.io.Serial;
+import java.util.Date;
+
+/**
+ * 学生实习信息查询业务对象 InternshipInfoQueryBO
+ *
+ * @author system
+ * @date 2025-01-03
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+@Schema(description = "学生实习信息查询业务对象")
+public class InternshipInfoQueryBO extends BaseEntity {
+
+    @Serial
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 学号
+     */
+    @Schema(description = "学号")
+    private String studentNo;
+
+    /**
+     * 学生姓名
+     */
+    @Schema(description = "学生姓名")
+    private String studentName;
+
+    /**
+     * 班级ID
+     */
+    @Schema(description = "班级ID")
+    private String classId;
+
+    /**
+     * 班级名称
+     */
+    @Schema(description = "班级名称")
+    private String className;
+
+    /**
+     * 年级
+     */
+    @Schema(description = "年级")
+    private String grade;
+
+    /**
+     * 学院名称
+     */
+    @Schema(description = "学院名称")
+    private String collegeName;
+
+    /**
+     * 专业名称
+     */
+    @Schema(description = "专业名称")
+    private String majorName;
+
+    /**
+     * 性别:0-男,1-女
+     */
+    @Schema(description = "性别:0-男,1-女")
+    private String gender;
+
+    /**
+     * 实习状态:1-进行中,2-已完成,3-已暂停,4-已终止,null-未实习
+     */
+    @Schema(description = "实习状态:1-进行中,2-已完成,3-已暂停,4-已终止,null-未实习")
+    private String internshipStatus;
+
+    /**
+     * 实习单位名称
+     */
+    @Schema(description = "实习单位名称")
+    private String companyName;
+
+    /**
+     * 实习单位地址
+     */
+    @Schema(description = "实习单位地址")
+    private String companyAddress;
+
+    /**
+     * 实习岗位
+     */
+    @Schema(description = "实习岗位")
+    private String internshipPosition;
+
+    /**
+     * 实习协议状态:1-已签署,2-未签署
+     */
+    @Schema(description = "实习协议状态:1-已签署,2-未签署")
+    private String agreementStatus;
+
+    /**
+     * 班主任ID(用于数据权限控制)
+     */
+    @Schema(description = "班主任ID", hidden = true)
+    private Long classTeacherId;
+
+    /**
+     * 辅导员ID(用于数据权限控制)
+     */
+    @Schema(description = "辅导员ID", hidden = true)
+    private Long counselorId;
+
+    /**
+     * 实习开始日期 - 开始
+     */
+    @Schema(description = "实习开始日期-开始")
+    private Date internshipStartDateBegin;
+
+    /**
+     * 实习开始日期 - 结束
+     */
+    @Schema(description = "实习开始日期-结束")
+    private Date internshipStartDateEnd;
+
+    /**
+     * 实习结束日期 - 开始
+     */
+    @Schema(description = "实习结束日期-开始")
+    private Date internshipEndDateBegin;
+
+    /**
+     * 实习结束日期 - 结束
+     */
+    @Schema(description = "实习结束日期-结束")
+    private Date internshipEndDateEnd;
+}

+ 202 - 0
backend/ruoyi-modules/ruoyi-zsjy/src/main/java/org/dromara/zsjy/domain/vo/InternshipInfoVO.java

@@ -0,0 +1,202 @@
+package org.dromara.zsjy.domain.vo;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.io.Serial;
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.util.Date;
+
+/**
+ * 学生实习信息视图对象 InternshipInfoVO
+ *
+ * @author system
+ * @date 2025-01-03
+ */
+@Data
+@Schema(description = "学生实习信息视图对象")
+public class InternshipInfoVO implements Serializable {
+
+    @Serial
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 学生ID
+     */
+    @Schema(description = "学生ID")
+    private Long studentId;
+
+    /**
+     * 学号
+     */
+    @Schema(description = "学号")
+    private String studentNo;
+
+    /**
+     * 学生姓名
+     */
+    @Schema(description = "学生姓名")
+    private String studentName;
+
+    /**
+     * 性别:0-男,1-女
+     */
+    @Schema(description = "性别:0-男,1-女")
+    private String gender;
+
+    /**
+     * 手机号码
+     */
+    @Schema(description = "手机号码")
+    private String phone;
+
+    /**
+     * 班级ID
+     */
+    @Schema(description = "班级ID")
+    private String classId;
+
+    /**
+     * 班级名称
+     */
+    @Schema(description = "班级名称")
+    private String className;
+
+    /**
+     * 年级
+     */
+    @Schema(description = "年级")
+    private String grade;
+
+    /**
+     * 学院名称
+     */
+    @Schema(description = "学院名称")
+    private String collegeName;
+
+    /**
+     * 专业名称
+     */
+    @Schema(description = "专业名称")
+    private String majorName;
+
+    /**
+     * 辅导员姓名
+     */
+    @Schema(description = "辅导员姓名")
+    private String counselorName;
+
+    /**
+     * 班主任姓名
+     */
+    @Schema(description = "班主任姓名")
+    private String classTeacherName;
+
+    /**
+     * 实习信息ID
+     */
+    @Schema(description = "实习信息ID")
+    private Long internshipId;
+
+    /**
+     * 实习状态:1-进行中,2-已完成,3-已暂停,4-已终止
+     */
+    @Schema(description = "实习状态:1-进行中,2-已完成,3-已暂停,4-已终止,null-未实习")
+    private String internshipStatus;
+
+    /**
+     * 实习状态显示名称
+     */
+    @Schema(description = "实习状态显示名称")
+    private String internshipStatusName;
+
+    /**
+     * 实习单位名称
+     */
+    @Schema(description = "实习单位名称")
+    private String companyName;
+
+    /**
+     * 实习单位地址
+     */
+    @Schema(description = "实习单位地址")
+    private String companyAddress;
+
+    /**
+     * 实习岗位
+     */
+    @Schema(description = "实习岗位")
+    private String internshipPosition;
+
+    /**
+     * 实习薪资
+     */
+    @Schema(description = "实习薪资")
+    private BigDecimal internshipAllowance;
+
+    /**
+     * 实习开始时间
+     */
+    @Schema(description = "实习开始时间")
+    @JsonFormat(pattern = "yyyy-MM-dd")
+    private Date internshipStartDate;
+
+    /**
+     * 实习结束时间
+     */
+    @Schema(description = "实习结束时间")
+    @JsonFormat(pattern = "yyyy-MM-dd")
+    private Date internshipEndDate;
+
+    /**
+     * 联系人姓名
+     */
+    @Schema(description = "联系人姓名")
+    private String contactPersonName;
+
+    /**
+     * 联系人电话
+     */
+    @Schema(description = "联系人电话")
+    private String contactPersonPhone;
+
+    /**
+     * 实习协议状态:1-已签署,2-未签署
+     */
+    @Schema(description = "实习协议状态:1-已签署,2-未签署")
+    private String agreementStatus;
+
+    /**
+     * 备注信息
+     */
+    @Schema(description = "备注信息")
+    private String remark;
+
+    /**
+     * 创建者
+     */
+    @Schema(description = "创建者")
+    private Long createBy;
+
+    /**
+     * 创建时间
+     */
+    @Schema(description = "创建时间")
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private Date createTime;
+
+    /**
+     * 更新者
+     */
+    @Schema(description = "更新者")
+    private Long updateBy;
+
+    /**
+     * 更新时间
+     */
+    @Schema(description = "更新时间")
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private Date updateTime;
+}

+ 54 - 0
backend/ruoyi-modules/ruoyi-zsjy/src/main/java/org/dromara/zsjy/mapper/InternshipInfoMapper.java

@@ -0,0 +1,54 @@
+package org.dromara.zsjy.mapper;
+
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
+import org.dromara.zsjy.domain.bo.InternshipInfoQueryBO;
+import org.dromara.zsjy.domain.vo.InternshipInfoVO;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * 实习信息管理Mapper接口
+ *
+ * @author system
+ * @date 2025-01-03
+ */
+@Mapper
+public interface InternshipInfoMapper {
+
+    /**
+     * 查询学生实习信息列表
+     *
+     * @param page 分页参数(可选)
+     * @param queryBO 查询条件
+     * @return 学生实习信息列表
+     */
+    List<InternshipInfoVO> selectInternshipInfoList(@Param("page") Page<InternshipInfoVO> page,
+                                                   @Param("queryBO") InternshipInfoQueryBO queryBO);
+
+    /**
+     * 根据学生ID查询实习信息详情
+     *
+     * @param studentId 学生ID
+     * @return 学生实习信息详情
+     */
+    InternshipInfoVO selectInternshipInfoById(@Param("studentId") Long studentId);
+
+    /**
+     * 查询班主任管理的班级信息
+     *
+     * @param teacherId 班主任ID
+     * @return 班级信息列表
+     */
+    List<Map<String, Object>> selectTeacherClasses(@Param("teacherId") Long teacherId);
+
+    /**
+     * 查询实习状态统计数据
+     *
+     * @param queryBO 查询条件
+     * @return 统计数据
+     */
+    Map<String, Object> selectInternshipStatistics(@Param("queryBO") InternshipInfoQueryBO queryBO);
+}

+ 75 - 0
backend/ruoyi-modules/ruoyi-zsjy/src/main/java/org/dromara/zsjy/service/IInternshipInfoService.java

@@ -0,0 +1,75 @@
+package org.dromara.zsjy.service;
+
+import org.dromara.common.mybatis.core.page.PageQuery;
+import org.dromara.common.mybatis.core.page.TableDataInfo;
+import org.dromara.zsjy.domain.vo.InternshipInfoVO;
+import org.dromara.zsjy.domain.bo.InternshipInfoQueryBO;
+import jakarta.servlet.http.HttpServletResponse;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * 实习信息管理Service接口
+ *
+ * @author system
+ * @date 2025-01-03
+ */
+public interface IInternshipInfoService {
+
+    /**
+     * 查询学生实习信息分页列表(班主任专用)
+     *
+     * @param queryBO 查询条件
+     * @param pageQuery 分页参数
+     * @return 学生实习信息分页列表
+     */
+    TableDataInfo<InternshipInfoVO> queryPageList(InternshipInfoQueryBO queryBO, PageQuery pageQuery);
+
+    /**
+     * 查询学生实习信息列表(不分页)
+     *
+     * @param queryBO 查询条件
+     * @return 学生实习信息列表
+     */
+    List<InternshipInfoVO> queryList(InternshipInfoQueryBO queryBO);
+
+    /**
+     * 根据学生ID查询实习信息详情
+     *
+     * @param studentId 学生ID
+     * @return 学生实习信息详情
+     */
+    InternshipInfoVO queryById(Long studentId);
+
+    /**
+     * 导出学生实习信息
+     *
+     * @param queryBO 查询条件
+     * @param response HTTP响应对象
+     */
+    void exportInternshipInfo(InternshipInfoQueryBO queryBO, HttpServletResponse response);
+
+    /**
+     * 获取班主任管理的班级信息
+     *
+     * @return 班级信息列表
+     */
+    List<Map<String, Object>> getTeacherClasses();
+
+    /**
+     * 获取实习状态统计数据
+     *
+     * @param queryBO 查询条件
+     * @return 统计数据
+     */
+    Map<String, Object> getInternshipStatistics(InternshipInfoQueryBO queryBO);
+
+    /**
+     * 根据当前用户获取数据权限范围
+     * (用于限制班主任只能查看自己班级的学生)
+     *
+     * @param queryBO 查询条件(会被设置权限参数)
+     */
+    void setDataPermission(InternshipInfoQueryBO queryBO);
+}

+ 188 - 0
backend/ruoyi-modules/ruoyi-zsjy/src/main/java/org/dromara/zsjy/service/impl/InternshipInfoServiceImpl.java

@@ -0,0 +1,188 @@
+package org.dromara.zsjy.service.impl;
+
+import cn.hutool.core.bean.BeanUtil;
+import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.util.ObjectUtil;
+import cn.hutool.core.util.StrUtil;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.dromara.common.core.utils.MapstructUtils;
+import org.dromara.common.core.utils.StringUtils;
+import org.dromara.common.excel.utils.ExcelUtil;
+import org.dromara.common.mybatis.core.page.PageQuery;
+import org.dromara.common.mybatis.core.page.TableDataInfo;
+import org.dromara.common.satoken.utils.LoginHelper;
+import org.dromara.zsjy.domain.bo.InternshipInfoQueryBO;
+import org.dromara.zsjy.domain.vo.InternshipInfoVO;
+import org.dromara.zsjy.mapper.InternshipInfoMapper;
+import org.dromara.zsjy.service.IInternshipInfoService;
+import org.springframework.stereotype.Service;
+import jakarta.servlet.http.HttpServletResponse;
+
+import java.util.*;
+
+/**
+ * 实习信息管理Service业务层处理
+ *
+ * @author system
+ * @date 2025-01-03
+ */
+@Slf4j
+@RequiredArgsConstructor
+@Service
+public class InternshipInfoServiceImpl implements IInternshipInfoService {
+
+    private final InternshipInfoMapper internshipInfoMapper;
+
+    /**
+     * 查询学生实习信息分页列表(班主任专用)
+     */
+    @Override
+    public TableDataInfo<InternshipInfoVO> queryPageList(InternshipInfoQueryBO queryBO, PageQuery pageQuery) {
+        // 设置数据权限
+        setDataPermission(queryBO);
+
+        // 创建分页对象
+        Page<InternshipInfoVO> page = pageQuery.build();
+
+        // 查询数据
+        List<InternshipInfoVO> list = internshipInfoMapper.selectInternshipInfoList(page, queryBO);
+
+        // 处理实习状态显示名称
+        processInternshipStatusName(list);
+
+        return TableDataInfo.build(page);
+    }
+
+    /**
+     * 查询学生实习信息列表(不分页)
+     */
+    @Override
+    public List<InternshipInfoVO> queryList(InternshipInfoQueryBO queryBO) {
+        // 设置数据权限
+        setDataPermission(queryBO);
+
+        // 查询数据
+        List<InternshipInfoVO> list = internshipInfoMapper.selectInternshipInfoList(null, queryBO);
+
+        // 处理实习状态显示名称
+        processInternshipStatusName(list);
+
+        return list;
+    }
+
+    /**
+     * 根据学生ID查询实习信息详情
+     */
+    @Override
+    public InternshipInfoVO queryById(Long studentId) {
+        if (ObjectUtil.isNull(studentId)) {
+            return null;
+        }
+
+        InternshipInfoVO vo = internshipInfoMapper.selectInternshipInfoById(studentId);
+
+        if (ObjectUtil.isNotNull(vo)) {
+            // 处理实习状态显示名称
+            processInternshipStatusName(Collections.singletonList(vo));
+        }
+
+        return vo;
+    }
+
+    /**
+     * 导出学生实习信息
+     */
+    @Override
+    public void exportInternshipInfo(InternshipInfoQueryBO queryBO, HttpServletResponse response) {
+        List<InternshipInfoVO> list = queryList(queryBO);
+        ExcelUtil.exportExcel(list, "学生实习信息", InternshipInfoVO.class, response);
+    }
+
+    /**
+     * 获取班主任管理的班级信息
+     */
+    @Override
+    public List<Map<String, Object>> getTeacherClasses() {
+        // 获取当前登录用户ID
+        Long currentUserId = LoginHelper.getUserId();
+
+        return internshipInfoMapper.selectTeacherClasses(currentUserId);
+    }
+
+    /**
+     * 获取实习状态统计数据
+     */
+    @Override
+    public Map<String, Object> getInternshipStatistics(InternshipInfoQueryBO queryBO) {
+        // 设置数据权限
+        setDataPermission(queryBO);
+
+        // 查询统计数据
+        Map<String, Object> statistics = internshipInfoMapper.selectInternshipStatistics(queryBO);
+
+        if (ObjectUtil.isNull(statistics)) {
+            statistics = new HashMap<>();
+            statistics.put("totalCount", 0);
+            statistics.put("internshipCount", 0);
+            statistics.put("noInternshipCount", 0);
+            statistics.put("internshipRate", "0.00%");
+        }
+
+        return statistics;
+    }
+
+    /**
+     * 根据当前用户获取数据权限范围
+     */
+    @Override
+    public void setDataPermission(InternshipInfoQueryBO queryBO) {
+        try {
+            // 获取当前登录用户ID
+            Long currentUserId = LoginHelper.getUserId();
+
+            if (ObjectUtil.isNotNull(currentUserId)) {
+                // 设置班主任ID用于数据权限控制
+                queryBO.setClassTeacherId(currentUserId);
+
+                log.debug("设置数据权限:班主任ID={}", currentUserId);
+            }
+        } catch (Exception e) {
+            log.warn("获取数据权限失败:{}", e.getMessage());
+        }
+    }
+
+    /**
+     * 处理实习状态显示名称
+     */
+    private void processInternshipStatusName(List<InternshipInfoVO> list) {
+        if (CollUtil.isEmpty(list)) {
+            return;
+        }
+
+        for (InternshipInfoVO vo : list) {
+            String status = vo.getInternshipStatus();
+            String statusName = getInternshipStatusName(status);
+            vo.setInternshipStatusName(statusName);
+        }
+    }
+
+    /**
+     * 获取实习状态显示名称
+     */
+    private String getInternshipStatusName(String status) {
+        if (StrUtil.isBlank(status)) {
+            return "未实习";
+        }
+
+        return switch (status) {
+            case "1" -> "进行中";
+            case "2" -> "已完成";
+            case "3" -> "已暂停";
+            case "4" -> "已终止";
+            default -> "未知状态";
+        };
+    }
+}

+ 197 - 0
backend/ruoyi-modules/ruoyi-zsjy/src/main/resources/mapper/InternshipInfoMapper.xml

@@ -0,0 +1,197 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="org.dromara.zsjy.mapper.InternshipInfoMapper">
+
+    <!-- 实习信息结果映射 -->
+    <resultMap type="org.dromara.zsjy.domain.vo.InternshipInfoVO" id="InternshipInfoVOResult">
+        <id     property="studentId"              column="student_id"           />
+        <result property="studentNo"              column="student_no"           />
+        <result property="studentName"            column="student_name"         />
+        <result property="gender"                 column="gender"               />
+        <result property="phone"                  column="phone"                />
+        <result property="classId"                column="class_id"             />
+        <result property="className"              column="class_name"           />
+        <result property="grade"                  column="grade"                />
+        <result property="collegeName"            column="college_name"         />
+        <result property="majorName"              column="major_name"           />
+        <result property="counselorName"          column="counselor_name"       />
+        <result property="classTeacherName"       column="class_teacher_name"   />
+        <result property="internshipId"           column="internship_id"        />
+        <result property="internshipStatus"       column="internship_status"    />
+        <result property="companyName"            column="company_name"         />
+        <result property="companyAddress"         column="company_address"      />
+        <result property="internshipPosition"     column="internship_position"  />
+        <result property="internshipAllowance"    column="internship_allowance" />
+        <result property="internshipStartDate"    column="internship_start_date" />
+        <result property="internshipEndDate"      column="internship_end_date"   />
+        <result property="contactPersonName"      column="contact_person_name"   />
+        <result property="contactPersonPhone"     column="contact_person_phone"  />
+        <result property="agreementStatus"        column="agreement_status"      />
+        <result property="remark"                 column="remark"                />
+        <result property="createBy"               column="create_by"             />
+        <result property="createTime"             column="create_time"           />
+        <result property="updateBy"               column="update_by"             />
+        <result property="updateTime"             column="update_time"           />
+    </resultMap>
+
+    <!-- 基础SQL片段 -->
+    <sql id="selectInternshipInfoVo">
+        SELECT
+            s.id as student_id,
+            s.student_no,
+            s.name as student_name,
+            s.gender,
+            s.phone,
+            s.class_id,
+            s.class_name,
+            s.grade,
+            s.college_name,
+            s.major_name,
+            s.counselor_name,
+            s.class_teacher_name,
+            c.class_teacher_id,
+            c.counselor_id,
+            i.internship_id as internship_id,
+            i.internship_status,
+            i.company_name,
+            i.company_address,
+            i.position_name as internship_position,
+            i.internship_allowance,
+            i.start_date as internship_start_date,
+            i.end_date as internship_end_date,
+            i.company_contact as contact_person_name,
+            i.company_phone as contact_person_phone,
+            i.status as agreement_status,
+            COALESCE(i.remark, s.remark) as remark,
+            COALESCE(i.create_by, s.create_by) as create_by,
+            COALESCE(i.create_time, s.create_time) as create_time,
+            COALESCE(i.update_by, s.update_by) as update_by,
+            COALESCE(i.update_time, s.update_time) as update_time
+        FROM xg_student_msg s
+        LEFT JOIN xg_class_msg c ON s.class_id = c.id AND c.tenant_id = '000000'
+        LEFT JOIN zsjy_internship_info i ON s.id = i.student_id AND i.deleted = 0 AND i.tenant_id = '000000'
+        WHERE s.deleted = 0
+        AND c.deleted = 0
+        AND s.student_status = '1'
+        AND s.tenant_id = '000000'
+    </sql>
+
+    <!-- 查询条件SQL片段 -->
+    <sql id="selectInternshipInfoWhere">
+        <if test="queryBO.studentNo != null and queryBO.studentNo != ''">
+            AND s.student_no LIKE CONCAT('%', #{queryBO.studentNo}, '%')
+        </if>
+        <if test="queryBO.studentName != null and queryBO.studentName != ''">
+            AND s.name LIKE CONCAT('%', #{queryBO.studentName}, '%')
+        </if>
+        <if test="queryBO.classId != null and queryBO.classId != ''">
+            AND s.class_id = #{queryBO.classId}
+        </if>
+        <if test="queryBO.className != null and queryBO.className != ''">
+            AND s.class_name LIKE CONCAT('%', #{queryBO.className}, '%')
+        </if>
+        <if test="queryBO.grade != null and queryBO.grade != ''">
+            AND s.grade = #{queryBO.grade}
+        </if>
+        <if test="queryBO.collegeName != null and queryBO.collegeName != ''">
+            AND s.college_name LIKE CONCAT('%', #{queryBO.collegeName}, '%')
+        </if>
+        <if test="queryBO.majorName != null and queryBO.majorName != ''">
+            AND s.major_name LIKE CONCAT('%', #{queryBO.majorName}, '%')
+        </if>
+        <if test="queryBO.gender != null and queryBO.gender != ''">
+            AND s.gender = #{queryBO.gender}
+        </if>
+        <if test="queryBO.internshipStatus != null and queryBO.internshipStatus != ''">
+            <choose>
+                <when test="queryBO.internshipStatus == 'null'">
+                    AND i.internship_status IS NULL
+                </when>
+                <otherwise>
+                    AND i.internship_status = #{queryBO.internshipStatus}
+                </otherwise>
+            </choose>
+        </if>
+        <if test="queryBO.companyName != null and queryBO.companyName != ''">
+            AND i.company_name LIKE CONCAT('%', #{queryBO.companyName}, '%')
+        </if>
+        <if test="queryBO.companyAddress != null and queryBO.companyAddress != ''">
+            AND i.company_address LIKE CONCAT('%', #{queryBO.companyAddress}, '%')
+        </if>
+        <if test="queryBO.internshipPosition != null and queryBO.internshipPosition != ''">
+            AND i.internship_position LIKE CONCAT('%', #{queryBO.internshipPosition}, '%')
+        </if>
+        <if test="queryBO.agreementStatus != null and queryBO.agreementStatus != ''">
+            AND i.agreement_status = #{queryBO.agreementStatus}
+        </if>
+        <if test="queryBO.internshipStartDateBegin != null">
+            AND i.internship_start_date >= #{queryBO.internshipStartDateBegin}
+        </if>
+        <if test="queryBO.internshipStartDateEnd != null">
+            AND i.internship_start_date &lt;= #{queryBO.internshipStartDateEnd}
+        </if>
+        <if test="queryBO.internshipEndDateBegin != null">
+            AND i.internship_end_date >= #{queryBO.internshipEndDateBegin}
+        </if>
+        <if test="queryBO.internshipEndDateEnd != null">
+            AND i.internship_end_date &lt;= #{queryBO.internshipEndDateEnd}
+        </if>
+        <!-- 数据权限控制:班主任只能查看自己班级的学生 -->
+        <if test="queryBO.classTeacherId != null">
+            AND c.class_teacher_id = #{queryBO.classTeacherId}
+        </if>
+        <if test="queryBO.counselorId != null">
+            AND c.counselor_id = #{queryBO.counselorId}
+        </if>
+    </sql>
+
+    <!-- 查询学生实习信息列表 -->
+    <select id="selectInternshipInfoList" parameterType="org.dromara.zsjy.domain.bo.InternshipInfoQueryBO"
+            resultMap="InternshipInfoVOResult">
+        <include refid="selectInternshipInfoVo"/>
+        <include refid="selectInternshipInfoWhere"/>
+        ORDER BY s.class_name, s.student_no
+    </select>
+
+    <!-- 根据学生ID查询实习信息详情 -->
+    <select id="selectInternshipInfoById" parameterType="Long" resultMap="InternshipInfoVOResult">
+        <include refid="selectInternshipInfoVo"/>
+        AND s.id = #{studentId}
+    </select>
+
+    <!-- 查询班主任管理的班级信息 -->
+    <select id="selectTeacherClasses" parameterType="Long" resultType="map">
+        SELECT
+            c.id as value,
+            c.class_name as label,
+            c.grade,
+            c.college_name,
+            c.major_name,
+            c.current_student_count
+        FROM xg_class_msg c
+        WHERE c.deleted = 0
+        AND c.class_status = '1'
+        AND c.class_teacher_id = #{teacherId}
+        AND c.tenant_id = '000000'
+        ORDER BY c.grade DESC, c.class_name
+    </select>
+
+    <!-- 查询实习状态统计数据 -->
+    <select id="selectInternshipStatistics" parameterType="org.dromara.zsjy.domain.bo.InternshipInfoQueryBO"
+            resultType="map">
+        SELECT
+            COUNT(*) as totalCount,
+            COUNT(CASE WHEN i.internship_status IS NOT NULL AND i.internship_status != '' THEN i.internship_id END) as internshipCount,
+            COUNT(CASE WHEN i.internship_status IS NULL OR i.internship_status = '' THEN 1 END) as noInternshipCount,
+            CONCAT(ROUND(IFNULL(COUNT(CASE WHEN i.internship_status IS NOT NULL AND i.internship_status != '' THEN i.internship_id END) * 100.0 / NULLIF(COUNT(*), 0), 0), 2), '%') as internshipRate
+        FROM xg_student_msg s
+        LEFT JOIN xg_class_msg c ON s.class_id = c.id AND c.tenant_id = '000000'
+        LEFT JOIN zsjy_internship_info i ON s.id = i.student_id AND i.deleted = 0 AND i.tenant_id = '000000'
+        WHERE s.deleted = 0
+        AND c.deleted = 0
+        AND s.student_status = '1'
+        AND s.tenant_id = '000000'
+        <include refid="selectInternshipInfoWhere"/>
+    </select>
+
+</mapper>