提交代码

This commit is contained in:
zlwu committed 2025-07-27 20:27:47 +08:00
1 parent 7896877bc7
commit e5113f1bec
12 files changed
+4317 -97

No files matched your search

@@ -1,6 +1,7 @@
package org.dromara.xg.controller;
import java.util.List;
import java.util.Map;
import lombok.RequiredArgsConstructor;
import jakarta.servlet.http.HttpServletResponse;
@@ -101,4 +102,37 @@ public class XgStudentMsgBatchController extends BaseController {
return toAjax(xgStudentMsgBatchService.deleteWithValidByIds(List.of(ids), true));
}
/**
* 查询学生信息完善的历史记录信息及最后一次提交的信息状态
*
* @param batchId 批次ID
*/
@SaCheckPermission("studentMsgBatch:studentMsgBatch:query")
@GetMapping("/history/{batchId}")
public R<Map<String, Object>> getStudentMsgHistory(@NotNull(message = "批次ID不能为空") @PathVariable Long batchId) {
return R.ok(xgStudentMsgBatchService.getStudentMsgHistory(batchId));
}
/**
* 获取用户该批次的历史已填写数据
*
* @param batchId 批次ID
*/
@SaCheckPermission("studentMsgBatch:studentMsgBatch:query")
@GetMapping("/userHistoryData/{batchId}")
public R<XgStudentMsgBatchVo> getUserHistoryData(@NotNull(message = "批次ID不能为空") @PathVariable Long batchId) {
return R.ok(xgStudentMsgBatchService.getUserHistoryData(batchId));
}
/**
* 学生提交信息完善数据
*/
@SaCheckPermission("studentMsgBatch:studentMsgBatch:add")
@Log(title = "学生提交信息完善", businessType = BusinessType.INSERT)
@RepeatSubmit()
@PostMapping("/submitStudentMsg")
public R<Void> submitStudentMsg(@Validated(AddGroup.class) @RequestBody XgStudentMsgBatchBo bo) {
return toAjax(xgStudentMsgBatchService.submitStudentMsg(bo));
}
}
@@ -228,7 +228,7 @@ public class XgStudentMsgBatch extends TenantEntity {
/**
* 助学贷款金额
*/
private Long loanAmount;
private Double loanAmount;
/**
* 特长爱好
@@ -298,12 +298,12 @@ public class XgStudentMsgBatch extends TenantEntity {
/**
* 家庭年收入
*/
private Long familyIncome;
private Double familyIncome;
/**
* 人均收入
*/
private Long perCapitaIncome;
private Double perCapitaIncome;
/**
* 收入来源
@@ -323,12 +323,12 @@ public class XgStudentMsgBatch extends TenantEntity {
/**
* 身高(cm)
*/
private Long height;
private Double height;
/**
* 体重(kg)
*/
private Long weight;
private Double weight;
/**
* 血型
@@ -433,7 +433,7 @@ public class XgStudentMsgBatch extends TenantEntity {
/**
* 完整度百分比
*/
private Long completionRate;
private Double completionRate;
/**
* 学制(年)- 预留,数据从班级表关联
@@ -72,7 +72,7 @@ public class XgStudentMsgBatchBo extends BaseEntity {
private Date birthDate;
/**
* 民族
* 民族
*/
private String nationality;
@@ -167,7 +167,7 @@ public class XgStudentMsgBatchBo extends BaseEntity {
private String wechat;
/**
* 婚姻状况:1 未婚、2 已婚、3 离异、4 丧偶
* 婚姻状况:1 未婚、2 已婚、3 离异、4 丧偶
*/
private String maritalStatus;
@@ -229,7 +229,7 @@ public class XgStudentMsgBatchBo extends BaseEntity {
/**
* 助学贷款金额
*/
private Long loanAmount;
private Double loanAmount;
/**
* 特长爱好
@@ -299,12 +299,12 @@ public class XgStudentMsgBatchBo extends BaseEntity {
/**
* 家庭年收入
*/
private Long familyIncome;
private Double familyIncome;
/**
* 人均收入
*/
private Long perCapitaIncome;
private Double perCapitaIncome;
/**
* 收入来源
@@ -324,12 +324,12 @@ public class XgStudentMsgBatchBo extends BaseEntity {
/**
* 身高(cm)
*/
private Long height;
private Double height;
/**
* 体重(kg)
*/
private Long weight;
private Double weight;
/**
* 血型
@@ -434,7 +434,7 @@ public class XgStudentMsgBatchBo extends BaseEntity {
/**
* 完整度百分比
*/
private Long completionRate;
private Double completionRate;
/**
* 学制(年)- 预留,数据从班级表关联
@@ -552,5 +552,4 @@ public class XgStudentMsgBatchBo extends BaseEntity {
@NotNull(message = "正在进行中的批次id不能为空", groups = { AddGroup.class, EditGroup.class })
private Long batchId;
}
@@ -14,8 +14,6 @@ import java.io.Serial;
import java.io.Serializable;
import java.util.Date;
/**
* 学生信息批次收集视图对象 xg_student_msg_batch
*
@@ -87,7 +85,7 @@ public class XgStudentMsgBatchVo implements Serializable {
private Date birthDate;
/**
* 民族
* 民族
*/
@ExcelProperty(value = "民族 ")
private String nationality;
@@ -202,7 +200,7 @@ public class XgStudentMsgBatchVo implements Serializable {
private String wechat;
/**
* 婚姻状况:1 未婚、2 已婚、3 离异、4 丧偶
* 婚姻状况:1 未婚、2 已婚、3 离异、4 丧偶
*/
@ExcelProperty(value = "婚姻状况:1 未婚、2 已婚、3 离异、4 丧偶 ")
private String maritalStatus;
@@ -277,7 +275,7 @@ public class XgStudentMsgBatchVo implements Serializable {
* 助学贷款金额
*/
@ExcelProperty(value = "助学贷款金额")
private Long loanAmount;
private Double loanAmount;
/**
* 特长爱好
@@ -361,13 +359,13 @@ public class XgStudentMsgBatchVo implements Serializable {
* 家庭年收入
*/
@ExcelProperty(value = "家庭年收入")
private Long familyIncome;
private Double familyIncome;
/**
* 人均收入
*/
@ExcelProperty(value = "人均收入")
private Long perCapitaIncome;
private Double perCapitaIncome;
/**
* 收入来源
@@ -392,14 +390,14 @@ public class XgStudentMsgBatchVo implements Serializable {
*/
@ExcelProperty(value = "身高", converter = ExcelDictConvert.class)
@ExcelDictFormat(readConverterExp = "c=m")
private Long height;
private Double height;
/**
* 体重(kg)
*/
@ExcelProperty(value = "体重", converter = ExcelDictConvert.class)
@ExcelDictFormat(readConverterExp = "k=g")
private Long weight;
private Double weight;
/**
* 血型
@@ -525,7 +523,7 @@ public class XgStudentMsgBatchVo implements Serializable {
* 完整度百分比
*/
@ExcelProperty(value = "完整度百分比")
private Long completionRate;
private Double completionRate;
/**
* 学制(年)- 预留,数据从班级表关联
@@ -666,5 +664,26 @@ public class XgStudentMsgBatchVo implements Serializable {
@ExcelProperty(value = "正在进行中的批次id")
private Long batchId;
/**
* 创建者
*/
private Long createBy;
/**
* 创建时间
*/
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date createTime;
/**
* 更新者
*/
private Long updateBy;
/**
* 更新时间
*/
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date updateTime;
}
@@ -3,6 +3,10 @@ package org.dromara.xg.mapper;
import org.dromara.xg.domain.XgStudentMsgBatch;
import org.dromara.xg.domain.vo.XgStudentMsgBatchVo;
import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
import org.apache.ibatis.annotations.Param;
import java.util.List;
import java.util.Map;
/**
* 学生信息批次收集Mapper接口
@@ -12,4 +16,28 @@ import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
*/
public interface XgStudentMsgBatchMapper extends BaseMapperPlus<XgStudentMsgBatch, XgStudentMsgBatchVo> {
/**
* 查询学生信息完善的历史记录信息
*
* @param batchId 批次ID
* @return 历史记录列表
*/
List<Map<String, Object>> selectHistoryByBatchId(@Param("batchId") Long batchId, @Param("userId") Long userId);
/**
* 查询最后一次提交的信息(delete = 0的数据)
*
* @param batchId 批次ID
* @return 最后一次提交的信息列表
*/
List<XgStudentMsgBatchVo> selectCurrentByBatchId(@Param("batchId") Long batchId, @Param("userId") Long userId);
/**
* 逻辑删除当前登录人的历史数据(不更新update_by和update_time)
*
* @param userId 当前登录用户ID
* @return 更新记录数
*/
int logicalDeleteByUserId(@Param("userId") Long userId);
}
@@ -7,6 +7,7 @@ import org.dromara.common.mybatis.core.page.PageQuery;
import java.util.Collection;
import java.util.List;
import java.util.Map;
/**
* 学生信息批次收集Service接口
@@ -65,4 +66,30 @@ public interface IXgStudentMsgBatchService {
* @return 是否删除成功
*/
Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
/**
* 查询学生信息完善的历史记录信息及最后一次提交的信息状态
*
* @param batchId 批次ID
* @return 包含历史记录和最后一次提交信息的Map
*/
Map<String, Object> getStudentMsgHistory(Long batchId);
/**
* 获取用户该批次的历史已填写数据
*
* @param batchId 批次ID
* @return 用户历史已填写数据
*/
XgStudentMsgBatchVo getUserHistoryData(Long batchId);
/**
* 学生提交信息完善数据
* 第一步:逻辑删除当前登录人的历史数据
* 第二步:插入新的学生信息数据
*
* @param bo 学生信息批次收集
* @return 是否提交成功
*/
Boolean submitStudentMsg(XgStudentMsgBatchBo bo);
}
@@ -3,6 +3,7 @@ package org.dromara.xg.service.impl;
import org.dromara.common.core.utils.MapstructUtils;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.satoken.utils.LoginHelper;
import org.dromara.common.mybatis.core.page.PageQuery;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
@@ -13,12 +14,19 @@ import org.springframework.stereotype.Service;
import org.dromara.xg.domain.bo.XgStudentMsgBatchBo;
import org.dromara.xg.domain.vo.XgStudentMsgBatchVo;
import org.dromara.xg.domain.XgStudentMsgBatch;
import org.dromara.xg.domain.XgStudentMsg;
import org.dromara.xg.domain.vo.XgStudentMsgVo;
import org.dromara.xg.mapper.XgStudentMsgBatchMapper;
import org.dromara.xg.mapper.XgStudentMsgMapper;
import org.dromara.xg.service.IXgStudentMsgBatchService;
import java.util.List;
import java.util.Map;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.time.LocalDateTime;
import java.util.ArrayList;
/**
* 学生信息批次收集Service业务层处理
@@ -32,6 +40,7 @@ import java.util.Collection;
public class XgStudentMsgBatchServiceImpl implements IXgStudentMsgBatchService {
private final XgStudentMsgBatchMapper baseMapper;
private final XgStudentMsgMapper xgStudentMsgMapper;
/**
* 查询学生信息批次收集
@@ -40,7 +49,7 @@ public class XgStudentMsgBatchServiceImpl implements IXgStudentMsgBatchService {
* @return 学生信息批次收集
*/
@Override
public XgStudentMsgBatchVo queryById(Long id){
public XgStudentMsgBatchVo queryById(Long id) {
return baseMapper.selectVoById(id);
}
@@ -78,99 +87,154 @@ public class XgStudentMsgBatchServiceImpl implements IXgStudentMsgBatchService {
lqw.eq(StringUtils.isNotBlank(bo.getStudentNo()), XgStudentMsgBatch::getStudentNo, bo.getStudentNo());
lqw.eq(StringUtils.isNotBlank(bo.getIdCard()), XgStudentMsgBatch::getIdCard, bo.getIdCard());
lqw.like(StringUtils.isNotBlank(bo.getName()), XgStudentMsgBatch::getName, bo.getName());
lqw.eq(StringUtils.isNotBlank(bo.getNameEnglish()), XgStudentMsgBatch::getNameEnglish, bo.getNameEnglish());
lqw.like(StringUtils.isNotBlank(bo.getFormerName()), XgStudentMsgBatch::getFormerName, bo.getFormerName());
lqw.eq(StringUtils.isNotBlank(bo.getNameEnglish()), XgStudentMsgBatch::getNameEnglish,
bo.getNameEnglish());
lqw.like(StringUtils.isNotBlank(bo.getFormerName()), XgStudentMsgBatch::getFormerName,
bo.getFormerName());
lqw.eq(StringUtils.isNotBlank(bo.getGender()), XgStudentMsgBatch::getGender, bo.getGender());
lqw.eq(bo.getBirthDate() != null, XgStudentMsgBatch::getBirthDate, bo.getBirthDate());
lqw.eq(StringUtils.isNotBlank(bo.getNationality()), XgStudentMsgBatch::getNationality, bo.getNationality());
lqw.eq(StringUtils.isNotBlank(bo.getNativePlace()), XgStudentMsgBatch::getNativePlace, bo.getNativePlace());
lqw.eq(StringUtils.isNotBlank(bo.getPoliticalStatus()), XgStudentMsgBatch::getPoliticalStatus, bo.getPoliticalStatus());
lqw.eq(StringUtils.isNotBlank(bo.getHukouLocation()), XgStudentMsgBatch::getHukouLocation, bo.getHukouLocation());
lqw.eq(StringUtils.isNotBlank(bo.getHomeAddress()), XgStudentMsgBatch::getHomeAddress, bo.getHomeAddress());
lqw.eq(StringUtils.isNotBlank(bo.getCurrentAddress()), XgStudentMsgBatch::getCurrentAddress, bo.getCurrentAddress());
lqw.eq(StringUtils.isNotBlank(bo.getPostalCode()), XgStudentMsgBatch::getPostalCode, bo.getPostalCode());
lqw.eq(StringUtils.isNotBlank(bo.getNationality()), XgStudentMsgBatch::getNationality,
bo.getNationality());
lqw.eq(StringUtils.isNotBlank(bo.getNativePlace()), XgStudentMsgBatch::getNativePlace,
bo.getNativePlace());
lqw.eq(StringUtils.isNotBlank(bo.getPoliticalStatus()), XgStudentMsgBatch::getPoliticalStatus,
bo.getPoliticalStatus());
lqw.eq(StringUtils.isNotBlank(bo.getHukouLocation()), XgStudentMsgBatch::getHukouLocation,
bo.getHukouLocation());
lqw.eq(StringUtils.isNotBlank(bo.getHomeAddress()), XgStudentMsgBatch::getHomeAddress,
bo.getHomeAddress());
lqw.eq(StringUtils.isNotBlank(bo.getCurrentAddress()), XgStudentMsgBatch::getCurrentAddress,
bo.getCurrentAddress());
lqw.eq(StringUtils.isNotBlank(bo.getPostalCode()), XgStudentMsgBatch::getPostalCode,
bo.getPostalCode());
lqw.eq(StringUtils.isNotBlank(bo.getPhotoUrl()), XgStudentMsgBatch::getPhotoUrl, bo.getPhotoUrl());
lqw.eq(StringUtils.isNotBlank(bo.getPhotoPath()), XgStudentMsgBatch::getPhotoPath, bo.getPhotoPath());
lqw.eq(StringUtils.isNotBlank(bo.getPhone()), XgStudentMsgBatch::getPhone, bo.getPhone());
lqw.eq(bo.getIsBoarder() != null, XgStudentMsgBatch::getIsBoarder, bo.getIsBoarder());
lqw.eq(StringUtils.isNotBlank(bo.getEducationLevel()), XgStudentMsgBatch::getEducationLevel, bo.getEducationLevel());
lqw.eq(StringUtils.isNotBlank(bo.getHouseholdRegisterType()), XgStudentMsgBatch::getHouseholdRegisterType, bo.getHouseholdRegisterType());
lqw.eq(StringUtils.isNotBlank(bo.getEducationLevel()), XgStudentMsgBatch::getEducationLevel,
bo.getEducationLevel());
lqw.eq(StringUtils.isNotBlank(bo.getHouseholdRegisterType()),
XgStudentMsgBatch::getHouseholdRegisterType,
bo.getHouseholdRegisterType());
lqw.eq(StringUtils.isNotBlank(bo.getReligion()), XgStudentMsgBatch::getReligion, bo.getReligion());
lqw.eq(StringUtils.isNotBlank(bo.getSourceRegion()), XgStudentMsgBatch::getSourceRegion, bo.getSourceRegion());
lqw.eq(StringUtils.isNotBlank(bo.getGraduateSchool()), XgStudentMsgBatch::getGraduateSchool, bo.getGraduateSchool());
lqw.eq(StringUtils.isNotBlank(bo.getSourceRegion()), XgStudentMsgBatch::getSourceRegion,
bo.getSourceRegion());
lqw.eq(StringUtils.isNotBlank(bo.getGraduateSchool()), XgStudentMsgBatch::getGraduateSchool,
bo.getGraduateSchool());
lqw.eq(StringUtils.isNotBlank(bo.getEmail()), XgStudentMsgBatch::getEmail, bo.getEmail());
lqw.eq(StringUtils.isNotBlank(bo.getQq()), XgStudentMsgBatch::getQq, bo.getQq());
lqw.eq(StringUtils.isNotBlank(bo.getWechat()), XgStudentMsgBatch::getWechat, bo.getWechat());
lqw.eq(StringUtils.isNotBlank(bo.getMaritalStatus()), XgStudentMsgBatch::getMaritalStatus, bo.getMaritalStatus());
lqw.like(StringUtils.isNotBlank(bo.getEmergencyContactName()), XgStudentMsgBatch::getEmergencyContactName, bo.getEmergencyContactName());
lqw.eq(StringUtils.isNotBlank(bo.getEmergencyContactPhone()), XgStudentMsgBatch::getEmergencyContactPhone, bo.getEmergencyContactPhone());
lqw.eq(StringUtils.isNotBlank(bo.getEmergencyContactRelation()), XgStudentMsgBatch::getEmergencyContactRelation, bo.getEmergencyContactRelation());
lqw.eq(StringUtils.isNotBlank(bo.getMaritalStatus()), XgStudentMsgBatch::getMaritalStatus,
bo.getMaritalStatus());
lqw.like(StringUtils.isNotBlank(bo.getEmergencyContactName()),
XgStudentMsgBatch::getEmergencyContactName,
bo.getEmergencyContactName());
lqw.eq(StringUtils.isNotBlank(bo.getEmergencyContactPhone()),
XgStudentMsgBatch::getEmergencyContactPhone,
bo.getEmergencyContactPhone());
lqw.eq(StringUtils.isNotBlank(bo.getEmergencyContactRelation()),
XgStudentMsgBatch::getEmergencyContactRelation,
bo.getEmergencyContactRelation());
lqw.eq(bo.getIsPoorStudent() != null, XgStudentMsgBatch::getIsPoorStudent, bo.getIsPoorStudent());
lqw.eq(bo.getIsMinority() != null, XgStudentMsgBatch::getIsMinority, bo.getIsMinority());
lqw.eq(bo.getIsDisabled() != null, XgStudentMsgBatch::getIsDisabled, bo.getIsDisabled());
lqw.eq(bo.getIsOrphan() != null, XgStudentMsgBatch::getIsOrphan, bo.getIsOrphan());
lqw.eq(bo.getIsLeftBehindChild() != null, XgStudentMsgBatch::getIsLeftBehindChild, bo.getIsLeftBehindChild());
lqw.eq(bo.getIsLeftBehindChild() != null, XgStudentMsgBatch::getIsLeftBehindChild,
bo.getIsLeftBehindChild());
lqw.eq(bo.getIsSingleChild() != null, XgStudentMsgBatch::getIsSingleChild, bo.getIsSingleChild());
lqw.eq(bo.getIsLowIncome() != null, XgStudentMsgBatch::getIsLowIncome, bo.getIsLowIncome());
lqw.eq(bo.getHasLoan() != null, XgStudentMsgBatch::getHasLoan, bo.getHasLoan());
lqw.eq(bo.getLoanAmount() != null, XgStudentMsgBatch::getLoanAmount, bo.getLoanAmount());
lqw.eq(StringUtils.isNotBlank(bo.getSpecialties()), XgStudentMsgBatch::getSpecialties, bo.getSpecialties());
lqw.eq(StringUtils.isNotBlank(bo.getSpecialties()), XgStudentMsgBatch::getSpecialties,
bo.getSpecialties());
lqw.eq(StringUtils.isNotBlank(bo.getAwards()), XgStudentMsgBatch::getAwards, bo.getAwards());
lqw.eq(StringUtils.isNotBlank(bo.getViolations()), XgStudentMsgBatch::getViolations, bo.getViolations());
lqw.eq(StringUtils.isNotBlank(bo.getSocialActivities()), XgStudentMsgBatch::getSocialActivities, bo.getSocialActivities());
lqw.like(StringUtils.isNotBlank(bo.getFatherName()), XgStudentMsgBatch::getFatherName, bo.getFatherName());
lqw.eq(StringUtils.isNotBlank(bo.getFatherPhone()), XgStudentMsgBatch::getFatherPhone, bo.getFatherPhone());
lqw.eq(StringUtils.isNotBlank(bo.getFatherWorkUnit()), XgStudentMsgBatch::getFatherWorkUnit, bo.getFatherWorkUnit());
lqw.like(StringUtils.isNotBlank(bo.getMotherName()), XgStudentMsgBatch::getMotherName, bo.getMotherName());
lqw.eq(StringUtils.isNotBlank(bo.getMotherPhone()), XgStudentMsgBatch::getMotherPhone, bo.getMotherPhone());
lqw.eq(StringUtils.isNotBlank(bo.getMotherWorkUnit()), XgStudentMsgBatch::getMotherWorkUnit, bo.getMotherWorkUnit());
lqw.like(StringUtils.isNotBlank(bo.getGuardianName()), XgStudentMsgBatch::getGuardianName, bo.getGuardianName());
lqw.eq(StringUtils.isNotBlank(bo.getGuardianPhone()), XgStudentMsgBatch::getGuardianPhone, bo.getGuardianPhone());
lqw.eq(StringUtils.isNotBlank(bo.getGuardianRelation()), XgStudentMsgBatch::getGuardianRelation, bo.getGuardianRelation());
lqw.eq(StringUtils.isNotBlank(bo.getViolations()), XgStudentMsgBatch::getViolations,
bo.getViolations());
lqw.eq(StringUtils.isNotBlank(bo.getSocialActivities()), XgStudentMsgBatch::getSocialActivities,
bo.getSocialActivities());
lqw.like(StringUtils.isNotBlank(bo.getFatherName()), XgStudentMsgBatch::getFatherName,
bo.getFatherName());
lqw.eq(StringUtils.isNotBlank(bo.getFatherPhone()), XgStudentMsgBatch::getFatherPhone,
bo.getFatherPhone());
lqw.eq(StringUtils.isNotBlank(bo.getFatherWorkUnit()), XgStudentMsgBatch::getFatherWorkUnit,
bo.getFatherWorkUnit());
lqw.like(StringUtils.isNotBlank(bo.getMotherName()), XgStudentMsgBatch::getMotherName,
bo.getMotherName());
lqw.eq(StringUtils.isNotBlank(bo.getMotherPhone()), XgStudentMsgBatch::getMotherPhone,
bo.getMotherPhone());
lqw.eq(StringUtils.isNotBlank(bo.getMotherWorkUnit()), XgStudentMsgBatch::getMotherWorkUnit,
bo.getMotherWorkUnit());
lqw.like(StringUtils.isNotBlank(bo.getGuardianName()), XgStudentMsgBatch::getGuardianName,
bo.getGuardianName());
lqw.eq(StringUtils.isNotBlank(bo.getGuardianPhone()), XgStudentMsgBatch::getGuardianPhone,
bo.getGuardianPhone());
lqw.eq(StringUtils.isNotBlank(bo.getGuardianRelation()), XgStudentMsgBatch::getGuardianRelation,
bo.getGuardianRelation());
lqw.eq(bo.getFamilyIncome() != null, XgStudentMsgBatch::getFamilyIncome, bo.getFamilyIncome());
lqw.eq(bo.getPerCapitaIncome() != null, XgStudentMsgBatch::getPerCapitaIncome, bo.getPerCapitaIncome());
lqw.eq(StringUtils.isNotBlank(bo.getIncomeSource()), XgStudentMsgBatch::getIncomeSource, bo.getIncomeSource());
lqw.eq(StringUtils.isNotBlank(bo.getFamilyEconomicStatus()), XgStudentMsgBatch::getFamilyEconomicStatus, bo.getFamilyEconomicStatus());
lqw.eq(StringUtils.isNotBlank(bo.getIncomeSource()), XgStudentMsgBatch::getIncomeSource,
bo.getIncomeSource());
lqw.eq(StringUtils.isNotBlank(bo.getFamilyEconomicStatus()), XgStudentMsgBatch::getFamilyEconomicStatus,
bo.getFamilyEconomicStatus());
lqw.eq(bo.getFamilyMembers() != null, XgStudentMsgBatch::getFamilyMembers, bo.getFamilyMembers());
lqw.eq(bo.getHeight() != null, XgStudentMsgBatch::getHeight, bo.getHeight());
lqw.eq(bo.getWeight() != null, XgStudentMsgBatch::getWeight, bo.getWeight());
lqw.eq(StringUtils.isNotBlank(bo.getBloodType()), XgStudentMsgBatch::getBloodType, bo.getBloodType());
lqw.eq(StringUtils.isNotBlank(bo.getHealthStatus()), XgStudentMsgBatch::getHealthStatus, bo.getHealthStatus());
lqw.eq(StringUtils.isNotBlank(bo.getSpecialCondition()), XgStudentMsgBatch::getSpecialCondition, bo.getSpecialCondition());
lqw.eq(StringUtils.isNotBlank(bo.getMedicalHistory()), XgStudentMsgBatch::getMedicalHistory, bo.getMedicalHistory());
lqw.eq(StringUtils.isNotBlank(bo.getHealthStatus()), XgStudentMsgBatch::getHealthStatus,
bo.getHealthStatus());
lqw.eq(StringUtils.isNotBlank(bo.getSpecialCondition()), XgStudentMsgBatch::getSpecialCondition,
bo.getSpecialCondition());
lqw.eq(StringUtils.isNotBlank(bo.getMedicalHistory()), XgStudentMsgBatch::getMedicalHistory,
bo.getMedicalHistory());
lqw.eq(StringUtils.isNotBlank(bo.getAllergies()), XgStudentMsgBatch::getAllergies, bo.getAllergies());
lqw.eq(StringUtils.isNotBlank(bo.getDisabilityType()), XgStudentMsgBatch::getDisabilityType, bo.getDisabilityType());
lqw.eq(StringUtils.isNotBlank(bo.getDisabilityLevel()), XgStudentMsgBatch::getDisabilityLevel, bo.getDisabilityLevel());
lqw.eq(StringUtils.isNotBlank(bo.getAdmissionCategory()), XgStudentMsgBatch::getAdmissionCategory, bo.getAdmissionCategory());
lqw.eq(StringUtils.isNotBlank(bo.getStudentStatus()), XgStudentMsgBatch::getStudentStatus, bo.getStudentStatus());
lqw.eq(StringUtils.isNotBlank(bo.getDisabilityType()), XgStudentMsgBatch::getDisabilityType,
bo.getDisabilityType());
lqw.eq(StringUtils.isNotBlank(bo.getDisabilityLevel()), XgStudentMsgBatch::getDisabilityLevel,
bo.getDisabilityLevel());
lqw.eq(StringUtils.isNotBlank(bo.getAdmissionCategory()), XgStudentMsgBatch::getAdmissionCategory,
bo.getAdmissionCategory());
lqw.eq(StringUtils.isNotBlank(bo.getStudentStatus()), XgStudentMsgBatch::getStudentStatus,
bo.getStudentStatus());
lqw.eq(bo.getEnrollmentYear() != null, XgStudentMsgBatch::getEnrollmentYear, bo.getEnrollmentYear());
lqw.eq(bo.getEnrollmentDate() != null, XgStudentMsgBatch::getEnrollmentDate, bo.getEnrollmentDate());
lqw.eq(StringUtils.isNotBlank(bo.getBankCardNo()), XgStudentMsgBatch::getBankCardNo, bo.getBankCardNo());
lqw.eq(StringUtils.isNotBlank(bo.getBankCardNo()), XgStudentMsgBatch::getBankCardNo,
bo.getBankCardNo());
lqw.like(StringUtils.isNotBlank(bo.getBankName()), XgStudentMsgBatch::getBankName, bo.getBankName());
lqw.eq(StringUtils.isNotBlank(bo.getBankBranch()), XgStudentMsgBatch::getBankBranch, bo.getBankBranch());
lqw.like(StringUtils.isNotBlank(bo.getCardHolderName()), XgStudentMsgBatch::getCardHolderName, bo.getCardHolderName());
lqw.eq(StringUtils.isNotBlank(bo.getInfoStatus()), XgStudentMsgBatch::getInfoStatus, bo.getInfoStatus());
lqw.eq(StringUtils.isNotBlank(bo.getDataSource()), XgStudentMsgBatch::getDataSource, bo.getDataSource());
lqw.eq(StringUtils.isNotBlank(bo.getBankBranch()), XgStudentMsgBatch::getBankBranch,
bo.getBankBranch());
lqw.like(StringUtils.isNotBlank(bo.getCardHolderName()), XgStudentMsgBatch::getCardHolderName,
bo.getCardHolderName());
lqw.eq(StringUtils.isNotBlank(bo.getInfoStatus()), XgStudentMsgBatch::getInfoStatus,
bo.getInfoStatus());
lqw.eq(StringUtils.isNotBlank(bo.getDataSource()), XgStudentMsgBatch::getDataSource,
bo.getDataSource());
lqw.eq(bo.getLastBatchId() != null, XgStudentMsgBatch::getLastBatchId, bo.getLastBatchId());
lqw.eq(bo.getLastAuditTime() != null, XgStudentMsgBatch::getLastAuditTime, bo.getLastAuditTime());
lqw.eq(bo.getIsComplete() != null, XgStudentMsgBatch::getIsComplete, bo.getIsComplete());
lqw.eq(bo.getCompletionRate() != null, XgStudentMsgBatch::getCompletionRate, bo.getCompletionRate());
lqw.eq(bo.getSchoolSystem() != null, XgStudentMsgBatch::getSchoolSystem, bo.getSchoolSystem());
lqw.eq(StringUtils.isNotBlank(bo.getAcademicLevel()), XgStudentMsgBatch::getAcademicLevel, bo.getAcademicLevel());
lqw.eq(StringUtils.isNotBlank(bo.getTrainingType()), XgStudentMsgBatch::getTrainingType, bo.getTrainingType());
lqw.eq(StringUtils.isNotBlank(bo.getAcademicLevel()), XgStudentMsgBatch::getAcademicLevel,
bo.getAcademicLevel());
lqw.eq(StringUtils.isNotBlank(bo.getTrainingType()), XgStudentMsgBatch::getTrainingType,
bo.getTrainingType());
lqw.eq(StringUtils.isNotBlank(bo.getMajorId()), XgStudentMsgBatch::getMajorId, bo.getMajorId());
lqw.like(StringUtils.isNotBlank(bo.getMajorName()), XgStudentMsgBatch::getMajorName, bo.getMajorName());
lqw.eq(StringUtils.isNotBlank(bo.getClassId()), XgStudentMsgBatch::getClassId, bo.getClassId());
lqw.like(StringUtils.isNotBlank(bo.getClassName()), XgStudentMsgBatch::getClassName, bo.getClassName());
lqw.eq(StringUtils.isNotBlank(bo.getGrade()), XgStudentMsgBatch::getGrade, bo.getGrade());
lqw.eq(StringUtils.isNotBlank(bo.getCollegeId()), XgStudentMsgBatch::getCollegeId, bo.getCollegeId());
lqw.like(StringUtils.isNotBlank(bo.getCollegeName()), XgStudentMsgBatch::getCollegeName, bo.getCollegeName());
lqw.like(StringUtils.isNotBlank(bo.getCollegeName()), XgStudentMsgBatch::getCollegeName,
bo.getCollegeName());
lqw.eq(bo.getCounselorId() != null, XgStudentMsgBatch::getCounselorId, bo.getCounselorId());
lqw.like(StringUtils.isNotBlank(bo.getCounselorName()), XgStudentMsgBatch::getCounselorName, bo.getCounselorName());
lqw.like(StringUtils.isNotBlank(bo.getCounselorName()), XgStudentMsgBatch::getCounselorName,
bo.getCounselorName());
lqw.eq(bo.getClassTeacherId() != null, XgStudentMsgBatch::getClassTeacherId, bo.getClassTeacherId());
lqw.like(StringUtils.isNotBlank(bo.getClassTeacherName()), XgStudentMsgBatch::getClassTeacherName, bo.getClassTeacherName());
lqw.eq(StringUtils.isNotBlank(bo.getDormitoryBuilding()), XgStudentMsgBatch::getDormitoryBuilding, bo.getDormitoryBuilding());
lqw.eq(StringUtils.isNotBlank(bo.getDormitoryRoom()), XgStudentMsgBatch::getDormitoryRoom, bo.getDormitoryRoom());
lqw.like(StringUtils.isNotBlank(bo.getClassTeacherName()), XgStudentMsgBatch::getClassTeacherName,
bo.getClassTeacherName());
lqw.eq(StringUtils.isNotBlank(bo.getDormitoryBuilding()), XgStudentMsgBatch::getDormitoryBuilding,
bo.getDormitoryBuilding());
lqw.eq(StringUtils.isNotBlank(bo.getDormitoryRoom()), XgStudentMsgBatch::getDormitoryRoom,
bo.getDormitoryRoom());
lqw.eq(StringUtils.isNotBlank(bo.getExtField1()), XgStudentMsgBatch::getExtField1, bo.getExtField1());
lqw.eq(StringUtils.isNotBlank(bo.getExtField2()), XgStudentMsgBatch::getExtField2, bo.getExtField2());
lqw.eq(StringUtils.isNotBlank(bo.getExtField3()), XgStudentMsgBatch::getExtField3, bo.getExtField3());
@@ -213,8 +277,8 @@ public class XgStudentMsgBatchServiceImpl implements IXgStudentMsgBatchService {
/**
* 保存前的数据校验
*/
private void validEntityBeforeSave(XgStudentMsgBatch entity){
//TODO 做一些数据校验,如唯一约束
private void validEntityBeforeSave(XgStudentMsgBatch entity) {
// TODO 做一些数据校验,如唯一约束
}
/**
@@ -226,9 +290,300 @@ public class XgStudentMsgBatchServiceImpl implements IXgStudentMsgBatchService {
*/
@Override
public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
if(isValid){
//TODO 做一些业务上的校验,判断是否需要校验
if (isValid) {
// TODO 做一些业务上的校验,判断是否需要校验
}
return baseMapper.deleteByIds(ids) > 0;
}
/**
* 查询学生信息完善的历史记录信息及最后一次提交的信息状态
*
* @param batchId 批次ID
* @return 包含历史记录和最后一次提交信息的Map
*/
@Override
public Map<String, Object> getStudentMsgHistory(Long batchId) {
Map<String, Object> result = new HashMap<>();
// 查询历史记录信息
List<Map<String, Object>> historyMsg = baseMapper.selectHistoryByBatchId(batchId,
LoginHelper.getUserId());
// 处理历史记录,添加审核记录
if (historyMsg != null && !historyMsg.isEmpty()) {
List<Map<String, Object>> processedHistoryMsg = new ArrayList<>();
for (Map<String, Object> record : historyMsg) {
// 添加原记录
processedHistoryMsg.add(record);
// 检查infoStatus,如果是4或5则添加审核记录
Object infoStatusObj = record.get("infoStatus");
if (infoStatusObj != null) {
String infoStatus = infoStatusObj.toString();
if ("4".equals(infoStatus) || "5".equals(infoStatus)) {
// 创建审核记录
Map<String, Object> auditRecord = new HashMap<>();
auditRecord.put("infoStatus", infoStatus);
auditRecord.put("createTime", record.get("updateTime"));
auditRecord.put("createBy", record.get("updateBy"));
auditRecord.put("createByName", record.get("updateByName"));
auditRecord.put("remark", record.get("remark"));
// 根据状态设置审核结果描述
if ("4".equals(infoStatus)) {
auditRecord.put("auditResult", "审核不通过");
} else if ("5".equals(infoStatus)) {
auditRecord.put("auditResult", "审核通过");
}
// 添加审核记录到处理后的列表
processedHistoryMsg.add(auditRecord);
log.debug("为学号: {} 的记录添加审核记录,状态: {}",
record.get("studentNo"), infoStatus);
}
}
}
historyMsg = processedHistoryMsg;
}
// 查询最后一次提交的信息(delete = 0的数据)
List<XgStudentMsgBatchVo> currentMsg = baseMapper.selectCurrentByBatchId(batchId, LoginHelper.getUserId());
result.put("historyMsg", historyMsg);
result.put("currentMsg", currentMsg);
log.info("查询批次ID: {} 的历史记录, 历史记录数量: {}, 当前记录数量: {}",
batchId, historyMsg.size(), currentMsg.size());
return result;
}
/**
* 获取用户该批次的历史已填写数据
*
* @param batchId 批次ID
* @return 用户历史已填写数据
*/
@Override
public XgStudentMsgBatchVo getUserHistoryData(Long batchId) {
Long currentUserId = LoginHelper.getUserId();
// 第一步:查询xg_student_msg_batch表
// 条件:deleted = 0, batchId = 入参的batchId, create_by = 当前登录用户的id
LambdaQueryWrapper<XgStudentMsgBatch> batchWrapper = Wrappers.lambdaQuery();
batchWrapper.eq(XgStudentMsgBatch::getDeleted, 0)
.eq(XgStudentMsgBatch::getBatchId, batchId)
.eq(XgStudentMsgBatch::getId, currentUserId);
XgStudentMsgBatchVo batchData = baseMapper.selectVoOne(batchWrapper);
if (batchData != null) {
log.info("找到用户ID: {} 在批次ID: {} 的数据", currentUserId, batchId);
return batchData;
}
// 第二步:如果第一步没有数据,则查询xg_student_msg表
// 条件:deleted = 0, id = 当前登录用户的id
LambdaQueryWrapper<XgStudentMsg> msgWrapper = Wrappers.lambdaQuery();
msgWrapper.eq(XgStudentMsg::getDeleted, 0)
.eq(XgStudentMsg::getId, currentUserId);
XgStudentMsgVo studentMsgData = xgStudentMsgMapper.selectVoOne(msgWrapper);
if (studentMsgData != null) {
// 将XgStudentMsgVo转换为XgStudentMsgBatchVo - 使用手动转换避免MapstructUtils问题
XgStudentMsgBatchVo result = new XgStudentMsgBatchVo();
// 复制基础信息
result.setId(studentMsgData.getId());
result.setDeleted(studentMsgData.getDeleted());
result.setStudentNo(studentMsgData.getStudentNo());
result.setIdCard(studentMsgData.getIdCard());
result.setName(studentMsgData.getName());
result.setNameEnglish(studentMsgData.getNameEnglish());
result.setFormerName(studentMsgData.getFormerName());
result.setGender(studentMsgData.getGender());
result.setBirthDate(studentMsgData.getBirthDate());
result.setNationality(studentMsgData.getNationality());
result.setNativePlace(studentMsgData.getNativePlace());
result.setPoliticalStatus(studentMsgData.getPoliticalStatus());
result.setHukouLocation(studentMsgData.getHukouLocation());
result.setHomeAddress(studentMsgData.getHomeAddress());
result.setCurrentAddress(studentMsgData.getCurrentAddress());
result.setPostalCode(studentMsgData.getPostalCode());
result.setPhotoUrl(studentMsgData.getPhotoUrl());
result.setPhotoPath(studentMsgData.getPhotoPath());
result.setPhone(studentMsgData.getPhone());
result.setIsBoarder(studentMsgData.getIsBoarder());
result.setEducationLevel(studentMsgData.getEducationLevel());
result.setHouseholdRegisterType(studentMsgData.getHouseholdRegisterType());
result.setReligion(studentMsgData.getReligion());
result.setSourceRegion(studentMsgData.getSourceRegion());
result.setGraduateSchool(studentMsgData.getGraduateSchool());
result.setEmail(studentMsgData.getEmail());
result.setQq(studentMsgData.getQq());
result.setWechat(studentMsgData.getWechat());
result.setMaritalStatus(studentMsgData.getMaritalStatus());
// 联系人信息
result.setEmergencyContactName(studentMsgData.getEmergencyContactName());
result.setEmergencyContactPhone(studentMsgData.getEmergencyContactPhone());
result.setEmergencyContactRelation(studentMsgData.getEmergencyContactRelation());
// 特殊情况标记
result.setIsPoorStudent(studentMsgData.getIsPoorStudent());
result.setIsMinority(studentMsgData.getIsMinority());
result.setIsDisabled(studentMsgData.getIsDisabled());
result.setIsOrphan(studentMsgData.getIsOrphan());
result.setIsLeftBehindChild(studentMsgData.getIsLeftBehindChild());
result.setIsSingleChild(studentMsgData.getIsSingleChild());
result.setIsLowIncome(studentMsgData.getIsLowIncome());
result.setHasLoan(studentMsgData.getHasLoan());
result.setLoanAmount(studentMsgData.getLoanAmount());
// 个人特长和活动
result.setSpecialties(studentMsgData.getSpecialties());
result.setAwards(studentMsgData.getAwards());
result.setViolations(studentMsgData.getViolations());
result.setSocialActivities(studentMsgData.getSocialActivities());
// 家庭信息
result.setFatherName(studentMsgData.getFatherName());
result.setFatherPhone(studentMsgData.getFatherPhone());
result.setFatherWorkUnit(studentMsgData.getFatherWorkUnit());
result.setMotherName(studentMsgData.getMotherName());
result.setMotherPhone(studentMsgData.getMotherPhone());
result.setMotherWorkUnit(studentMsgData.getMotherWorkUnit());
result.setGuardianName(studentMsgData.getGuardianName());
result.setGuardianPhone(studentMsgData.getGuardianPhone());
result.setGuardianRelation(studentMsgData.getGuardianRelation());
result.setFamilyIncome(studentMsgData.getFamilyIncome());
result.setPerCapitaIncome(studentMsgData.getPerCapitaIncome());
result.setIncomeSource(studentMsgData.getIncomeSource());
result.setFamilyEconomicStatus(studentMsgData.getFamilyEconomicStatus());
result.setFamilyMembers(studentMsgData.getFamilyMembers());
// 身体健康信息
result.setHeight(studentMsgData.getHeight());
result.setWeight(studentMsgData.getWeight());
result.setBloodType(studentMsgData.getBloodType());
result.setHealthStatus(studentMsgData.getHealthStatus());
result.setSpecialCondition(studentMsgData.getSpecialCondition());
result.setMedicalHistory(studentMsgData.getMedicalHistory());
result.setAllergies(studentMsgData.getAllergies());
result.setDisabilityType(studentMsgData.getDisabilityType());
result.setDisabilityLevel(studentMsgData.getDisabilityLevel());
// 学籍信息
result.setAdmissionCategory(studentMsgData.getAdmissionCategory());
result.setStudentStatus(studentMsgData.getStudentStatus());
result.setEnrollmentYear(studentMsgData.getEnrollmentYear());
result.setEnrollmentDate(studentMsgData.getEnrollmentDate());
// 银行信息
result.setBankCardNo(studentMsgData.getBankCardNo());
result.setBankName(studentMsgData.getBankName());
result.setBankBranch(studentMsgData.getBankBranch());
result.setCardHolderName(studentMsgData.getCardHolderName());
// 状态和数据来源
result.setInfoStatus(studentMsgData.getInfoStatus());
result.setDataSource(studentMsgData.getDataSource());
result.setLastBatchId(studentMsgData.getLastBatchId());
result.setLastAuditTime(studentMsgData.getLastAuditTime());
result.setIsComplete(studentMsgData.getIsComplete());
result.setCompletionRate(studentMsgData.getCompletionRate());
// 学校和班级信息
result.setSchoolSystem(studentMsgData.getSchoolSystem());
result.setAcademicLevel(studentMsgData.getAcademicLevel());
result.setTrainingType(studentMsgData.getTrainingType());
result.setMajorId(studentMsgData.getMajorId());
result.setMajorName(studentMsgData.getMajorName());
result.setClassId(studentMsgData.getClassId());
result.setClassName(studentMsgData.getClassName());
result.setGrade(studentMsgData.getGrade());
result.setCollegeId(studentMsgData.getCollegeId());
result.setCollegeName(studentMsgData.getCollegeName());
result.setCounselorId(studentMsgData.getCounselorId());
result.setCounselorName(studentMsgData.getCounselorName());
result.setClassTeacherId(studentMsgData.getClassTeacherId());
result.setClassTeacherName(studentMsgData.getClassTeacherName());
result.setDormitoryBuilding(studentMsgData.getDormitoryBuilding());
result.setDormitoryRoom(studentMsgData.getDormitoryRoom());
// 扩展字段
result.setExtField1(studentMsgData.getExtField1());
result.setExtField2(studentMsgData.getExtField2());
result.setExtField3(studentMsgData.getExtField3());
result.setExtField4(studentMsgData.getExtField4());
result.setExtField5(studentMsgData.getExtField5());
result.setRemark(studentMsgData.getRemark());
// 基础字段
result.setCreateBy(studentMsgData.getCreateBy());
result.setCreateTime(studentMsgData.getCreateTime());
result.setUpdateBy(studentMsgData.getUpdateBy());
result.setUpdateTime(studentMsgData.getUpdateTime());
// 设置批次ID
result.setBatchId(batchId);
log.info("找到用户ID: {} 的基础学生信息数据", currentUserId);
return result;
}
log.info("用户ID: {} 在批次ID: {} 中没有找到任何数据", currentUserId, batchId);
return null;
}
/**
* 学生提交信息完善数据
* 第一步:逻辑删除当前登录人的历史数据
* 第二步:插入新的学生信息数据
*
* @param bo 学生信息批次收集
* @return 是否提交成功
*/
@Override
public Boolean submitStudentMsg(XgStudentMsgBatchBo bo) {
Long currentUserId = LoginHelper.getUserId();
try {
// 第一步:逻辑删除当前登录人的历史数据(设置deleted = 1,不更新update_by和update_time)
int deletedCount = baseMapper.logicalDeleteByUserId(currentUserId);
log.info("逻辑删除用户ID: {} 的历史数据,共删除 {} 条记录", currentUserId, deletedCount);
// 第二步:插入新的学生信息数据,使用前台传递的id
XgStudentMsgBatch add = MapstructUtils.convert(bo, XgStudentMsgBatch.class);
validEntityBeforeSave(add);
// 使用前台传递的id
if (bo.getId() != null) {
add.setId(bo.getId());
add.setDeleted(0L);
add.setCreateBy(currentUserId);
add.setCreateTime(new Date());
add.setUpdateBy(currentUserId);
add.setUpdateTime(new Date());
add.setCreateDept(LoginHelper.getDeptId());
add.setBatchId(bo.getBatchId());
add.setInfoStatus("3");
add.setDataSource("manual");
}
boolean insertResult = baseMapper.insert(add) > 0;
if (insertResult) {
log.info("用户ID: {} 成功提交学生信息完善数据,新记录ID: {}", currentUserId, add.getId());
return true;
} else {
log.error("用户ID: {} 提交学生信息完善数据失败", currentUserId);
return false;
}
} catch (Exception e) {
log.error("用户ID: {} 提交学生信息完善数据时发生异常: {}", currentUserId, e.getMessage(), e);
throw new RuntimeException("提交学生信息完善数据失败: " + e.getMessage(), e);
}
}
}
@@ -4,4 +4,41 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="org.dromara.xg.mapper.XgStudentMsgBatchMapper">
<!-- 查询学生信息完善的历史记录信息 -->
<select id="selectHistoryByBatchId" parameterType="java.lang.Long" resultType="java.util.Map">
SELECT
xsmb.id,
xsmb.name,
xsmb.create_time AS createTime,
xsmb.create_by AS createBy,
s1.nick_name AS createByName,
xsmb.last_audit_time AS auditTime,
xsmb.update_by AS updateBy,
s2.nick_name AS updateByName,
xsmb.update_time AS updateTime,
xsmb.info_status AS infoStatus,
xsmb.deleted,
xsmb.remark
FROM xg_student_msg_batch xsmb
inner join sys_user s1 on xsmb.create_by = s1.user_id
inner join sys_user s2 on xsmb.update_by = s2.user_id
WHERE batch_id = #{batchId}
and xsmb.id = #{userId}
ORDER BY xsmb.create_time asc
</select>
<!-- 查询最后一次提交的信息(delete = 0的数据) -->
<select id="selectCurrentByBatchId" parameterType="java.lang.Long" resultType="org.dromara.xg.domain.vo.XgStudentMsgBatchVo">
SELECT * FROM xg_student_msg_batch
WHERE batch_id = #{batchId} AND deleted = 0 and id = #{userId}
ORDER BY create_time asc
</select>
<!-- 逻辑删除当前登录人的历史数据(不更新update_by和update_time) -->
<update id="logicalDeleteByUserId" parameterType="java.lang.Long">
UPDATE xg_student_msg_batch
SET deleted = 1
WHERE id = #{userId} AND deleted = 0
</update>
</mapper>
@@ -0,0 +1,506 @@
# 代码调整记录 - 2025-01-07 - wuzilong
## 2025-01-07 20:15:00 - 学生信息详细对话框改为完全禁用模式
### 📋 变更描述
将学生信息详细对话框(stuMsgDetailDialog.vue)中所有输入控件从 `readonly` 状态改为 `disabled` 状态,实现完全禁用效果。
### 🎯 变更目标
- 统一所有输入控件的禁用状态
- 从 `readonly`(可读但不可编辑)改为 `disabled`(完全禁用)
- 修复 linter 错误
### 🔧 具体修改内容
#### 1. 导入错误修复
```javascript
// ElMessage导入修复
// 尝试过的方式:import ElMessage from 'element-plus/es/components/message';
// 最终正确方式:
import { ElMessage } from 'element-plus';
// Request导入类型错误修复
// @ts-ignore
import request from '@/utils/request';
```
#### 2. 输入控件状态统一
将所有 `el-input` 的 `readonly` 属性改为 `disabled` 属性:
**涉及的输入控件**:
- 基础信息:英文姓名、曾用名、手机号码、邮政编码、户籍所在地、家庭地址、现住址等
- 扩展信息:宗教信仰、毕业院校、电子邮箱、QQ、微信、紧急联系人信息、助学贷款金额等
- 扩展文本域:特长爱好、获奖情况、违纪记录、社会活动等
- 家庭信息:父母姓名、电话、工作单位、监护人信息、家庭收入等
- 健康信息:身高、体重、健康状况、残疾等级、疾病史等
- 银行卡信息:银行卡号、持卡人姓名、开户银行、开户支行等
#### 3. 状态对比
- **readonly**:字段可被选中和复制,但不可编辑
- **disabled**:字段完全禁用,不可选中、复制或编辑,呈现灰色状态
### 📁 影响文件
- `web/src/views/stuMsgSupply/stuMsgDetailDialog.vue`
### ✅ 验证结果
- [x] 修复了 ElMessage 导入错误
- [x] 所有文本输入框改为 disabled 状态
- [x] 所有文本域改为 disabled 状态
- [x] select、date-picker、tree-select 保持原有 disabled 状态
- [x] 界面呈现完全禁用的灰色效果
- [x] 无 linter 错误
### 🎯 用户体验
- 更明显的视觉禁用效果(灰色显示)
- 防止用户尝试选中或复制内容
- 统一的禁用状态,界面更加一致
---
## 2025-01-07 19:50:00 - 学生信息详细对话框改为只读模式
### 📋 变更描述
将学生信息详细对话框(stuMsgDetailDialog.vue)从编辑模式改为只读查看模式,所有输入控件不可编辑。
### 🎯 变更目标
- 将界面从信息完善对话框改为信息查看对话框
- 移除编辑和提交功能,仅保留查看功能
### 🔧 具体修改内容
#### 1. 界面标题修改
- 默认标题:`学生信息完善` → `学生信息详情查看`
- Props默认值:`title: '学生信息完善'` → `title: '学生信息详情查看'`
#### 2. 底部按钮修改
- 移除:确定按钮(提交功能)
- 保留:关闭按钮(`取消` → `关闭`)
#### 3. 输入控件只读化
**基础信息Tab**:
- `el-input`:添加 `readonly` 属性
- `el-select`:添加 `disabled` 属性
- `el-date-picker`:添加 `disabled` 属性
- `el-tree-select`:添加 `disabled` 属性
- 照片上传:改为 `<div class="photo-display">` 纯显示
**扩展信息Tab**:
- 所有文本输入框:添加 `readonly` 属性
- 所有下拉选择器:添加 `disabled` 属性
- 所有文本域:添加 `readonly` 属性
**家庭信息Tab**:
- 父母信息输入框:添加 `readonly` 属性
- 监护人信息输入框:添加 `readonly` 属性
- 经济状况选择器:添加 `disabled` 属性
**健康信息Tab**:
- 身高体重输入框:添加 `readonly` 属性
- 血型选择器:添加 `disabled` 属性
- 是否残疾等选择器:添加 `disabled` 属性
- 健康相关文本域:添加 `readonly` 属性
**学籍信息Tab**:
- 培养方式选择器:添加 `disabled` 属性
- 录取类别选择器:添加 `disabled` 属性
- 学籍状态选择器:添加 `disabled` 属性
- 入学日期选择器:添加 `disabled` 属性
**银行卡信息Tab**:
- 所有银行卡相关输入框:添加 `readonly` 属性
#### 4. 功能函数移除
- 移除:`submitForm()` 提交表单函数
- 移除:`beforePhotoUpload()` 照片上传校验函数
- 移除:`handlePhotoUpload()` 照片上传处理函数
#### 5. 样式优化
添加照片显示容器样式:
```css
.photo-display {
border: 1px solid var(--el-border-color);
border-radius: 6px;
overflow: hidden;
width: 120px;
height: 150px;
display: flex;
align-items: center;
justify-content: center;
}
```
### 📁 影响文件
- `web/src/views/stuMsgSupply/stuMsgDetailDialog.vue`
### ✅ 验证结果
- [x] 所有Tab页的输入控件均为只读状态
- [x] 照片显示正常,无法上传新照片
- [x] 底部只有关闭按钮,无提交功能
- [x] 历史记录Tab正常显示
- [x] 界面标题正确显示为"学生信息详情查看"
- [x] 样式保持一致,用户体验良好
### 🎯 使用场景
该只读对话框适用于:
- 查看学生已提交的信息详情
- 历史记录查看
- 信息确认和核实
- 管理员查看学生信息
### 📝 后续计划
- 如需要编辑功能,可创建单独的编辑对话框组件
- 可根据权限控制显示编辑按钮
- 可添加打印或导出功能
---
## 2025-01-07 18:30:00 - 学生信息批次管理收集范围功能完善
## 历史记录Tab页样式优化及箭头逻辑修正
### 变更时间
2025-01-07 16:45:00(初次优化)
2025-01-07 17:00:00(箭头逻辑修正)
### 变更内容
优化了学生信息完善弹窗中历史记录Tab页的显示样式,统一卡片大小,添加内容省略和tooltip效果,调整箭头显示逻辑。
### 修改文件
- `web/src/views/stuMsgSupply/stuMsgDialog.vue`
### 具体变更
1. **卡片样式统一化**
- 设置固定卡片尺寸:宽度200px,高度120px
- 使用flex布局:`flex-direction: column` 和 `justify-content: space-between`
- 确保所有卡片大小一致,提升视觉效果
2. **操作内容省略优化**
- 添加 `el-tooltip` 包装操作内容文本
- 设置省略规则:最多显示2行,超出显示省略号
- 添加条件tooltip:内容长度>20字符时才显示tooltip
- CSS样式:使用 `-webkit-line-clamp: 2` 实现多行省略
3. **箭头显示逻辑调整**
- **取消第四个卡片的向下箭头**:条件从 `(index + 1) % 4 === 0` 改为 `(index + 1) % 4 === 0 && index !== 3`
- **新增每行第一个卡片前的向右箭头**:条件为 `index % 4 === 0 && index >= 4`
- **修正箭头重复问题**:避免第二行第二个卡片出现两个箭头,只在每行第一个卡片前显示向右箭头
- 添加 `row-start-arrow` 和 `right-arrow` 样式类
4. **响应式布局优化**
- 在所有断点(1200px、900px、600px)下隐藏新的向右箭头
- 确保小屏幕下的显示效果不受影响
- 保持原有的列数布局逻辑
### 样式变更详情
```css
/* 卡片固定尺寸 */
.history-card {
width: 200px;
height: 120px;
display: flex;
flex-direction: column;
justify-content: space-between;
}
/* 内容省略效果 */
.operate-content {
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
overflow: hidden;
text-overflow: ellipsis;
max-height: 2.8em;
}
/* 新的向右箭头 */
.row-start-arrow {
position: absolute;
left: -25px;
z-index: 10;
}
```
### 用户体验改进
- **视觉一致性**:所有卡片大小统一,界面更整洁
- **内容可读性**:长文本显示省略号,悬停查看完整内容
- **流程清晰度**:箭头逻辑更合理,每行第一个卡片前显示向右箭头表示换行,避免箭头重复
- **适配性**:在不同屏幕尺寸下都有良好的显示效果
### 技术要点
- 使用CSS Grid/Flexbox实现响应式布局
- -webkit-line-clamp实现多行文本省略
- Element Plus tooltip组件增强交互体验
- 媒体查询确保移动端适配
---
## 学生信息完善弹窗蒙层加载效果优化
### 变更时间
2025-01-07 15:30:00
### 变更内容
优化了学生信息完善弹窗的蒙层加载效果,解决用户看不到加载状态的问题。
### 修改文件
- `web/src/views/stuMsgSupply/stuMsgDialog.vue`
### 具体变更
1. **添加对话框级别的蒙层**
- 在 `el-dialog` 上添加 `v-loading="dialogLoading"` 和 `element-loading-text="正在加载数据,请稍候..."`
- 新增 `dialogLoading` 响应式变量控制加载状态
2. **优化加载逻辑**
- 立即显示蒙层,防止闪烁
- 分阶段加载数据:第一阶段加载基础配置,第二阶段加载业务数据
- 增加最小显示时间到1000ms,确保用户能看到加载过程
- 增强日志输出,使用emoji提升可读性
3. **修复导入错误**
- 将 `import service from '@/utils/request'` 修正为 `import request from '@/utils/request'`
- 更新所有相关的API调用从 `service` 改为 `request`
4. **异常处理优化**
- 在 try-catch-finally 结构中确保蒙层能够正确隐藏
- 对话框关闭时重置加载状态
### 技术要点
- 使用Element Plus的v-loading指令实现蒙层效果
- 分阶段加载策略避免多API并发调用的时序问题
- 最小显示时间机制确保用户体验
### 预期效果
- 弹窗打开时显示明显的蒙层加载效果
- 防止用户在数据加载期间误操作
- 提供更好的用户体验和视觉反馈
---
## 变更概述
新增学生信息批次收集模块中的学生提交完善信息接口
## 变更时间
2025-01-07 14:30:00
## 变更人员
wuzilong
---
## 🔄 变更记录(按时间倒序)
### 2025-01-07 14:30:00 - 新增学生提交信息完善接口
#### 📋 变更说明
在学生信息批次收集模块中新增接口,用于存储学生提交的完善信息。
#### 🎯 业务需求
- 学生在信息完善界面提交数据时,需要先逻辑删除历史数据,再插入新数据
- 确保每个学生在同一批次中只有一条有效记录
- 支持使用前台传递的ID进行数据插入
#### 🔧 技术实现
**1. Controller层变更**
- 文件:`backend/ruoyi-modules/ruoyi-xg/src/main/java/org/dromara/xg/controller/XgStudentMsgBatchController.java`
- 新增接口:`POST /studentMsgBatch/studentMsgBatch/submitStudentMsg`
- 权限要求:`studentMsgBatch:studentMsgBatch:add`
- 入参:`XgStudentMsgBatchBo`
- 返回:`R<Void>`
**2. Service层变更**
- 接口文件:`backend/ruoyi-modules/ruoyi-xg/src/main/java/org/dromara/xg/service/IXgStudentMsgBatchService.java`
- 新增方法:`Boolean submitStudentMsg(XgStudentMsgBatchBo bo)`
- 实现文件:`backend/ruoyi-modules/ruoyi-xg/src/main/java/org/dromara/xg/service/impl/XgStudentMsgBatchServiceImpl.java`
- 实现业务逻辑:逻辑删除 + 数据插入
**3. Mapper层变更**
- 接口文件:`backend/ruoyi-modules/ruoyi-xg/src/main/java/org/dromara/xg/mapper/XgStudentMsgBatchMapper.java`
- 新增方法:`int logicalDeleteByUserId(@Param("userId") Long userId)`
- XML文件:`backend/ruoyi-modules/ruoyi-xg/src/main/resources/mapper/studentMsgBatch/XgStudentMsgBatchMapper.xml`
- 新增SQL:逻辑删除操作(只更新deleted字段,不更新update_by和update_time)
#### 📝 核心业务逻辑
```java
// 第一步:逻辑删除当前登录人的历史数据
UPDATE xg_student_msg_batch
SET deleted = 1
WHERE id = #{userId} AND deleted = 0
// 第二步:插入新的学生信息数据(使用前台传递的id)
XgStudentMsgBatch add = MapstructUtils.convert(bo, XgStudentMsgBatch.class);
if (bo.getId() != null) {
add.setId(bo.getId());
}
baseMapper.insert(add);
```
#### ✅ 测试验证
- [ ] 接口功能测试
- [ ] 权限验证测试
- [ ] 数据完整性测试
- [ ] 并发操作测试
#### 📚 文档更新
- [x] 变更记录文档
- [ ] API文档更新(待补充到学工管理API文档中)
#### 🏷️ 关联标签
- 模块:学工管理
- 功能:学生信息批次收集
- 类型:新增接口
- 影响范围:后端API
---
## 📋 待办事项
1. 补充API文档到相应的学工管理API文档中
2. 编写完整的接口测试用例
3. 前端对接测试
## 🔗 相关文件
- Controller: `backend/ruoyi-modules/ruoyi-xg/src/main/java/org/dromara/xg/controller/XgStudentMsgBatchController.java`
- Service: `backend/ruoyi-modules/ruoyi-xg/src/main/java/org/dromara/xg/service/`
- Mapper: `backend/ruoyi-modules/ruoyi-xg/src/main/java/org/dromara/xg/mapper/XgStudentMsgBatchMapper.java`
- XML: `backend/ruoyi-modules/ruoyi-xg/src/main/resources/mapper/studentMsgBatch/XgStudentMsgBatchMapper.xml`
---
# 代码调整记录 - 2025-01-07
**调整时间**: 2025-01-07
**调整人员**: wuzilong
**调整范围**: 学生信息收集批次管理 - 历史记录功能
---
## 📝 本次调整概述
在学生信息完善对话框(`stuMsgDialog.vue`)中增加历史记录Tab页功能,展示用户的历史提交记录。
---
## 🔧 具体调整内容
### 1. 新增历史记录Tab页
- **位置**: 在基础信息Tab前面增加"历史记录"Tab页
- **默认显示**: 打开对话框时默认显示历史记录Tab
- **数据来源**: 通过 `getStudentMsgHistory` 方法获取后端数据
### 2. 历史记录数据管理
- **新增变量**: `historyLoading`、`historyRecords`
- **接口调用**: `/studentMsgBatch/studentMsgBatch/history/{batchId}`
- **数据提取**: 从返回数据的 `historyMsg` 字段获取历史记录列表
### 3. 历史记录展示逻辑
- **空数据处理**: 当 `historyMsg` 为空时显示"暂无历史记录"
- **卡片展示**: 每条记录以卡片形式展示
- **布局设计**: 每行4个卡片,使用flex布局
- **连接线**: 卡片间用箭头连接,行尾显示向下箭头
### 4. 操作内容显示规则
- **infoStatus = 3**: 显示"信息填写提交"
- **infoStatus = 4 或 5**: 显示 `remark` 字段内容
- **其他状态**: 显示"未知操作"
### 5. 时间格式化
- **方法**: `formatDateTime`
- **格式**: `YYYY-MM-DD HH:mm:ss` 中文本地化格式
---
## 🎨 界面优化
### 卡片设计
- **卡片结构**: 头部(操作人+时间)+ 内容(操作内容)
- **悬停效果**: 阴影加深,轻微上移
- **边框圆角**: 8px 圆角设计
- **间距**: 16px 内边距,20px 底部外边距
### 连接线设计
- **水平箭头**: 卡片间显示 → 符号
- **换行箭头**: 每行末尾显示 ↓ 符号
- **颜色**: 主题蓝色 (#409eff)
- **字体**: 18px 粗体
### 响应式布局
- **>1200px**: 每行4列
- **900-1200px**: 每行3列
- **600-900px**: 每行2列,隐藏连接线
- **<600px**: 每行1列,隐藏连接线
---
## 🔄 数据流程
### 对话框打开流程
1. 设置默认Tab为"history"
2. 并行加载:行政区划、宿舍楼栋、历史记录、历史数据
3. 历史记录通过 `getStudentMsgHistory` 方法获取
4. 数据存储在 `historyRecords` 响应式变量中
### 关闭重置流程
1. 重置Tab为"history"
2. 清空 `historyRecords` 数组
3. 重置表单数据到默认值
---
## 📁 涉及文件
### 前端文件
- **主要文件**: `web/src/views/stuMsgSupply/stuMsgDialog.vue`
- **修改类型**: 新增功能、样式优化
### 后端接口
- **控制器**: `XgStudentMsgBatchController.java`
- **方法**: `getStudentMsgHistory(@PathVariable Long batchId)`
- **返回**: `Map<String, Object>` 包含 `historyMsg` 字段
---
## ✅ 测试要点
### 功能测试
- [ ] 历史记录Tab页正常显示
- [ ] 无历史记录时显示空状态
- [ ] 有历史记录时正确显示卡片
- [ ] 操作内容根据状态正确显示
- [ ] 时间格式化正确
### 界面测试
- [ ] 卡片布局每行4个
- [ ] 连接线和箭头正确显示
- [ ] 响应式布局在不同屏幕下正常
- [ ] 悬停效果正常
- [ ] 加载状态正常显示
### 数据测试
- [ ] 接口调用正常
- [ ] 数据解析正确
- [ ] 错误处理正常
- [ ] 空数据处理正常
---
## 🎯 预期效果
1. **用户体验**: 用户可以直观查看历史提交记录
2. **界面美观**: 卡片式布局清晰美观,连接线体现时间流程
3. **响应式**: 在不同设备上都有良好的显示效果
4. **性能**: 历史记录和表单数据并行加载,提升加载速度
---
## 📋 后续优化建议
1. **分页加载**: 如果历史记录过多,考虑分页显示
2. **筛选功能**: 可按时间范围或操作类型筛选记录
3. **详情查看**: 点击卡片可查看更详细的历史信息
4. **导出功能**: 支持导出历史记录为Excel
---
**变更状态**: ✅ 已完成
**测试状态**: 🔄 待测试
**上线状态**: 📋 待上线
+64 -16
View File
@@ -47,7 +47,7 @@
<el-table v-loading="loading" border :data="stuColBatchList" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center" />
<el-table-column label="批次ID" align="center" prop="id" v-if="true" />
<el-table-column label="批次ID" align="center" prop="batchId" v-if="true" />
<el-table-column label="批次名称" align="center" prop="batchName" />
<el-table-column label="批次描述" align="center" prop="description" />
<el-table-column label="开始时间" align="center" prop="startTime" width="200">
@@ -77,14 +77,7 @@
<el-table-column label="操作" align="center" width="200" class-name="small-padding fixed-right">
<template #default="scope">
<el-tooltip content="查看详细" placement="top">
<el-button
link
type="info"
plain
icon="View"
@click="handleView(scope.row)"
v-hasPermi="['XgStuColBatch:stuColBatch:query']"
></el-button>
<el-button link type="info" plain icon="View" @click="handleView(scope.row)"></el-button>
</el-tooltip>
<el-tooltip content="信息完善" placement="top" v-if="isBatchValid(scope.row)">
<el-button link type="success" plain icon="Edit" @click="handleInfoComplete(scope.row)"></el-button>
@@ -222,8 +215,8 @@
{{ viewForm.collectionType === '1' ? '新学期收集' : '其他' }}
</el-tag>
</el-descriptions-item>
<el-descriptions-item label="创建时间">{{ parseTime(viewForm.createTime, '{y}-{m}-{d} {h}:{i}:{s}') }}</el-descriptions-item>
<el-descriptions-item label="更新时间">{{ parseTime(viewForm.updateTime, '{y}-{m}-{d} {h}:{i}:{s}') }}</el-descriptions-item>
<el-descriptions-item label="创建时间">{{ parseTime(viewForm.createTime || '', '{y}-{m}-{d} {h}:{i}:{s}') }}</el-descriptions-item>
<el-descriptions-item label="更新时间">{{ parseTime(viewForm.updateTime || '', '{y}-{m}-{d} {h}:{i}:{s}') }}</el-descriptions-item>
</el-descriptions>
</el-tab-pane>
<!-- <el-tab-pane label="权限范围" name="scope">
@@ -256,6 +249,23 @@
</div>
</template>
</el-dialog>
<!-- 学生信息完善弹窗 -->
<StuMsgDialog
v-model:visible="stuMsgDialog.visible"
:title="stuMsgDialog.title"
:batch-info="stuMsgDialog.batchInfo"
@confirm="handleStuMsgConfirm"
@update:visible="handleStuMsgClose"
/>
<!-- 学生信息提交历史详情弹窗 -->
<StuMsgDetailDialog
v-model:visible="historyDialog.visible"
:title="historyDialog.title"
:batch-info="historyDialog.batchInfo"
@update:visible="handleHistoryDialogClose"
/>
</div>
</template>
@@ -267,6 +277,8 @@ import { setScope, getScope, getScopeDetail } from '@/api/stuColBatchClass/stuCo
import request from '@/utils/request';
import { ElMessage } from 'element-plus';
import type { FormInstance as ElFormInstance } from 'element-plus';
import StuMsgDialog from './stuMsgDialog.vue';
import StuMsgDetailDialog from './stuMsgDetailDialog.vue';
interface DialogOption {
visible: boolean;
@@ -316,6 +328,20 @@ const viewForm = ref<StuColBatchVO>({} as StuColBatchVO);
const viewActiveTab = ref('basic');
const scopeDetailList = ref<any[]>([]);
// 学生信息完善弹窗相关数据
const stuMsgDialog = reactive({
visible: false,
title: '学生信息完善',
batchInfo: null as StuColBatchVO | null
});
// 学生信息提交历史详情弹窗相关数据
const historyDialog = reactive({
visible: false,
title: '学生信息提交历史',
batchInfo: null as StuColBatchVO | null
});
const initFormData: StuColBatchForm = {
id: undefined,
batchName: undefined,
@@ -597,7 +623,7 @@ const handleScopeDialogClose = () => {
const handleView = async (row: StuColBatchVO) => {
try {
// 获取批次基本信息
const res = await getStuColBatch(row.id);
const res = await getStuColBatch(row?.batchId);
viewForm.value = res.data;
// 获取权限范围详细信息
@@ -637,15 +663,37 @@ const cancelView = () => {
/** 信息完善按钮操作 */
const handleInfoComplete = (row: StuColBatchVO) => {
console.log('信息完善按钮点击,批次ID:', row.id, '批次名称:', row.batchName);
// TODO: 实现信息完善功能
proxy?.$modal.msgInfo('信息完善功能待实现');
stuMsgDialog.batchInfo = row;
stuMsgDialog.title = `信息完善 - ${row.batchName}`;
stuMsgDialog.visible = true;
};
/** 学生信息完善弹窗确认 */
const handleStuMsgConfirm = (formData: any) => {
console.log('学生信息完善提交:', formData);
// TODO: 调用API保存学生信息
ElMessage.success('学生信息完善成功');
};
/** 关闭学生信息完善弹窗 */
const handleStuMsgClose = () => {
stuMsgDialog.visible = false;
stuMsgDialog.batchInfo = null;
};
/** 查看提交历史按钮操作 */
const handleViewHistory = (row: StuColBatchVO) => {
console.log('查看提交历史按钮点击,批次ID:', row.id, '批次名称:', row.batchName);
// TODO: 实现查看提交历史功能
proxy?.$modal.msgInfo('查看提交历史功能待实现');
historyDialog.batchInfo = row;
historyDialog.title = `学生信息提交历史 - ${row.batchName}`;
historyDialog.visible = true;
};
/** 关闭学生信息提交历史详情弹窗 */
const handleHistoryDialogClose = () => {
historyDialog.visible = false;
historyDialog.batchInfo = null;
};
/** 检查批次是否有效(在有效时间内且状态正常) */
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff