This commit is contained in:
zlwu committed 2026-06-26 15:30:27 +08:00
commit 1155a976b9
49 files changed
+3227 -424

No files matched your search

@@ -0,0 +1,56 @@
package org.dromara.xg.controller;
import cn.dev33.satoken.annotation.SaCheckPermission;
import lombok.RequiredArgsConstructor;
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.xg.domain.bo.ClassTeacherDormQueryBo;
import org.dromara.xg.domain.vo.ClassTeacherClassInfoVo;
import org.dromara.xg.domain.vo.ClassTeacherDormRollCallVo;
import org.dromara.xg.domain.vo.ClassTeacherDormViolationVo;
import org.dromara.xg.service.IXgClassTeacherDormViewService;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* 班主任宿舍情况查看(违纪 + 点名,只读)
*/
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/classTeacherDorm/classTeacherDorm")
public class XgClassTeacherDormViewController extends BaseController {
private final IXgClassTeacherDormViewService classTeacherDormViewService;
/**
* 当前班主任所带班级信息
*/
@SaCheckPermission("classTeacherDorm:classTeacherDorm:query")
@GetMapping("/myClass")
public R<ClassTeacherClassInfoVo> myClass() {
return R.ok(classTeacherDormViewService.getMyClassInfo());
}
/**
* 本班宿舍违纪记录(卫生检查 + 宿舍违纪登记)
*/
@SaCheckPermission("classTeacherDorm:classTeacherDorm:query")
@GetMapping("/violation/list")
public TableDataInfo<ClassTeacherDormViolationVo> violationList(ClassTeacherDormQueryBo bo, PageQuery pageQuery) {
return classTeacherDormViewService.queryViolationPage(bo, pageQuery);
}
/**
* 本班宿舍点名明细
*/
@SaCheckPermission("classTeacherDorm:classTeacherDorm:query")
@GetMapping("/rollCall/list")
public TableDataInfo<ClassTeacherDormRollCallVo> rollCallList(ClassTeacherDormQueryBo bo, PageQuery pageQuery) {
return classTeacherDormViewService.queryRollCallPage(bo, pageQuery);
}
}
@@ -0,0 +1,40 @@
package org.dromara.xg.domain;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableLogic;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.dromara.common.tenant.core.TenantEntity;
import java.io.Serial;
/**
* 宿舍卫生检查扣分明细对象 xg_dorm_hygiene_check_deduction
*/
@Data
@EqualsAndHashCode(callSuper = true)
@TableName("xg_dorm_hygiene_check_deduction")
public class XgDormHygieneCheckDeduction extends TenantEntity {
@Serial
private static final long serialVersionUID = 1L;
@TableId(value = "id")
private Long id;
@TableLogic(value = "0", delval = "1")
private Long deleted;
private Long hygieneCheckId;
private Long disciplineTypeId;
private String disciplineTypeName;
private Double score;
private Integer sortOrder;
private String remark;
}
@@ -0,0 +1,25 @@
package org.dromara.xg.domain.bo;
import lombok.Data;
/**
* 班主任宿舍情况查询条件
*/
@Data
public class ClassTeacherDormQueryBo {
/** 开始日期 yyyy-MM-dd,默认当天 */
private String beginDate;
/** 结束日期 yyyy-MM-dd,默认当天 */
private String endDate;
/** 学号 */
private String studentNo;
/** 学生姓名 */
private String studentName;
/** 点名状态(宿舍点名 Tab 筛选,字典 xg_dorm_roll_call_status) */
private String rollCallStatus;
}
@@ -7,6 +7,7 @@ import io.github.linpeilie.annotations.AutoMapper;
import lombok.Data;
import jakarta.validation.constraints.*;
import jakarta.validation.Valid;
import org.dromara.xg.domain.bo.XgDormHygieneCheckDeductionBo;
import java.util.List;
import java.util.Date;
import com.fasterxml.jackson.annotation.JsonFormat;
@@ -159,6 +160,11 @@ public class XgDormHygieneCheckCompleteBo {
*/
private String disciplineTypeName;
/**
* 扣分明细列表
*/
private List<XgDormHygieneCheckDeductionBo> deductionItems;
/**
* 学生评分数据列表
*/
@@ -0,0 +1,30 @@
package org.dromara.xg.domain.bo;
import io.github.linpeilie.annotations.AutoMapper;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import org.dromara.xg.domain.XgDormHygieneCheckDeduction;
/**
* 宿舍卫生检查扣分明细业务对象
*/
@Data
@AutoMapper(target = XgDormHygieneCheckDeduction.class, reverseConvertGenerate = false)
public class XgDormHygieneCheckDeductionBo {
private Long id;
private Long hygieneCheckId;
@NotNull(message = "扣分项类型不能为空")
private Long disciplineTypeId;
private String disciplineTypeName;
@NotNull(message = "扣分分值不能为空")
private Double score;
private Integer sortOrder;
private String remark;
}
@@ -95,7 +95,6 @@ public class XgViolationDataBo {
/**
* 违纪原因
*/
@NotBlank(message = "违纪原因不能为空")
private String disciplineReason;
/**
@@ -0,0 +1,26 @@
package org.dromara.xg.domain.vo;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
/**
* 班主任班级信息
*/
@Data
public class ClassTeacherClassInfoVo implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
private Long classId;
private String className;
private String classCode;
private String collegeName;
private String majorName;
}
@@ -0,0 +1,48 @@
package org.dromara.xg.domain.vo;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
import java.util.Date;
/**
* 班主任查看-宿舍点名明细
*/
@Data
public class ClassTeacherDormRollCallVo implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
private Long id;
private Long studentId;
private String studentNo;
private String studentName;
private String className;
private String batchNo;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date checkDate;
private String checkerName;
private String buildingName;
private String roomName;
private String bedCode;
/** 0在寝 1请假 2不在 3空床位 */
private String rollCallStatus;
private String leaveTypeName;
private String remark;
}
@@ -0,0 +1,55 @@
package org.dromara.xg.domain.vo;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.Date;
/**
* 班主任查看-宿舍违纪记录
*/
@Data
public class ClassTeacherDormViolationVo implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
private Long id;
/** hygiene_check / dorm_violation */
private String dataSource;
/** 来源名称 */
private String dataSourceName;
private Long studentId;
private String studentNo;
private String studentName;
private String className;
private String buildingName;
private String roomName;
private String violationTypeName;
private BigDecimal scoreDeduction;
private String violationLevel;
@JsonFormat(pattern = "yyyy-MM-dd")
private Date violationDate;
private String violationReason;
private String status;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date createTime;
}
@@ -90,6 +90,12 @@ public class DormHygieneCheckExportVo implements Serializable {
@ExcelProperty(value = "宿舍总分")
private Double totalScore;
/**
* 扣分项明细
*/
@ExcelProperty(value = "扣分项")
private String disciplineTypeName;
/**
* 卫生等级
*/
@@ -0,0 +1,39 @@
package org.dromara.xg.domain.vo;
import io.github.linpeilie.annotations.AutoMapper;
import lombok.Data;
import org.dromara.xg.domain.XgDormHygieneCheckDeduction;
import java.io.Serial;
import java.io.Serializable;
/**
* 宿舍卫生检查扣分明细视图对象
*/
@Data
@AutoMapper(target = XgDormHygieneCheckDeduction.class)
public class XgDormHygieneCheckDeductionVo implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
private Long id;
private Long hygieneCheckId;
private Long disciplineTypeId;
private String disciplineTypeName;
private Double score;
private Integer sortOrder;
private String remark;
/** 前端展示用:类型最低扣分 */
private Double minScore;
/** 前端展示用:类型最高扣分 */
private Double maxScore;
}
@@ -13,6 +13,8 @@ import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
import java.util.Date;
import java.util.List;
import org.dromara.xg.domain.vo.XgDormHygieneCheckDeductionVo;
/**
* 宿舍卫生检查视图对象 xg_dorm_hygiene_check
@@ -183,4 +185,9 @@ public class XgDormHygieneCheckVo implements Serializable {
@ExcelProperty(value = "违纪类型名称")
private String disciplineTypeName;
/**
* 扣分明细列表
*/
private List<XgDormHygieneCheckDeductionVo> deductionItems;
}
@@ -113,6 +113,11 @@ public class XgDormHygieneStudentScoreVo implements Serializable {
@ExcelProperty(value = "床位编号")
private String bedCode;
/**
* 性别(0男 1女,来自xg_student_msg,查询时关联填充)
*/
private String gender;
/**
* 学生个人得分(0-100分)
*/
@@ -0,0 +1,27 @@
package org.dromara.xg.mapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.apache.ibatis.annotations.Param;
import org.dromara.xg.domain.bo.ClassTeacherDormQueryBo;
import org.dromara.xg.domain.vo.ClassTeacherClassInfoVo;
import org.dromara.xg.domain.vo.ClassTeacherDormRollCallVo;
import org.dromara.xg.domain.vo.ClassTeacherDormViolationVo;
/**
* 班主任宿舍情况查询 Mapper
*/
public interface XgClassTeacherDormViewMapper {
ClassTeacherClassInfoVo selectClassByTeacherId(@Param("teacherId") Long teacherId);
IPage<ClassTeacherDormViolationVo> selectViolationPage(
Page<ClassTeacherDormViolationVo> page,
@Param("classId") Long classId,
@Param("bo") ClassTeacherDormQueryBo bo);
IPage<ClassTeacherDormRollCallVo> selectRollCallPage(
Page<ClassTeacherDormRollCallVo> page,
@Param("classId") Long classId,
@Param("bo") ClassTeacherDormQueryBo bo);
}
@@ -0,0 +1,16 @@
package org.dromara.xg.mapper;
import org.apache.ibatis.annotations.Param;
import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
import org.dromara.xg.domain.XgDormHygieneCheckDeduction;
import org.dromara.xg.domain.vo.XgDormHygieneCheckDeductionVo;
import java.util.List;
/**
* 宿舍卫生检查扣分明细Mapper接口
*/
public interface XgDormHygieneCheckDeductionMapper extends BaseMapperPlus<XgDormHygieneCheckDeduction, XgDormHygieneCheckDeductionVo> {
List<XgDormHygieneCheckDeductionVo> selectVoListByHygieneCheckId(@Param("hygieneCheckId") Long hygieneCheckId);
}
@@ -4,6 +4,10 @@ import org.dromara.xg.domain.XgDormHygieneStudentScore;
import org.dromara.xg.domain.vo.XgDormHygieneStudentScoreVo;
import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
* 宿舍卫生检查学生评分Mapper接口
*
@@ -12,4 +16,12 @@ import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
*/
public interface XgDormHygieneStudentScoreMapper extends BaseMapperPlus<XgDormHygieneStudentScore, XgDormHygieneStudentScoreVo> {
/**
* 根据卫生检查ID查询学生评分列表(关联学生档案补充性别)
*
* @param hygieneCheckId 卫生检查ID
* @return 学生评分列表
*/
List<XgDormHygieneStudentScoreVo> selectVoListByHygieneCheckId(@Param("hygieneCheckId") Long hygieneCheckId);
}
@@ -0,0 +1,20 @@
package org.dromara.xg.service;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.xg.domain.bo.ClassTeacherDormQueryBo;
import org.dromara.xg.domain.vo.ClassTeacherClassInfoVo;
import org.dromara.xg.domain.vo.ClassTeacherDormRollCallVo;
import org.dromara.xg.domain.vo.ClassTeacherDormViolationVo;
/**
* 班主任宿舍情况查看 Service
*/
public interface IXgClassTeacherDormViewService {
ClassTeacherClassInfoVo getMyClassInfo();
TableDataInfo<ClassTeacherDormViolationVo> queryViolationPage(ClassTeacherDormQueryBo bo, PageQuery pageQuery);
TableDataInfo<ClassTeacherDormRollCallVo> queryRollCallPage(ClassTeacherDormQueryBo bo, PageQuery pageQuery);
}
@@ -0,0 +1,16 @@
package org.dromara.xg.service;
import org.dromara.xg.domain.bo.XgDormHygieneCheckDeductionBo;
import org.dromara.xg.domain.vo.XgDormHygieneCheckDeductionVo;
import java.util.List;
/**
* 宿舍卫生检查扣分明细Service接口
*/
public interface IXgDormHygieneCheckDeductionService {
List<XgDormHygieneCheckDeductionVo> listByHygieneCheckId(Long hygieneCheckId);
void replaceByHygieneCheckId(Long hygieneCheckId, List<XgDormHygieneCheckDeductionBo> items);
}
@@ -0,0 +1,75 @@
package org.dromara.xg.service.impl;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.RequiredArgsConstructor;
import org.dromara.common.core.exception.ServiceException;
import org.dromara.common.core.utils.StringUtils;
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.xg.domain.bo.ClassTeacherDormQueryBo;
import org.dromara.xg.domain.vo.ClassTeacherClassInfoVo;
import org.dromara.xg.domain.vo.ClassTeacherDormRollCallVo;
import org.dromara.xg.domain.vo.ClassTeacherDormViolationVo;
import org.dromara.xg.mapper.XgClassTeacherDormViewMapper;
import org.dromara.xg.service.IXgClassTeacherDormViewService;
import org.springframework.stereotype.Service;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
/**
* 班主任宿舍情况查看 Service 实现
*/
@Service
@RequiredArgsConstructor
public class XgClassTeacherDormViewServiceImpl implements IXgClassTeacherDormViewService {
private static final DateTimeFormatter DATE_FMT = DateTimeFormatter.ofPattern("yyyy-MM-dd");
private final XgClassTeacherDormViewMapper classTeacherDormViewMapper;
@Override
public ClassTeacherClassInfoVo getMyClassInfo() {
Long teacherId = LoginHelper.getUserId();
ClassTeacherClassInfoVo info = classTeacherDormViewMapper.selectClassByTeacherId(teacherId);
if (info == null) {
throw new ServiceException("当前账号未绑定班主任班级,无法查看");
}
return info;
}
@Override
public TableDataInfo<ClassTeacherDormViolationVo> queryViolationPage(ClassTeacherDormQueryBo bo, PageQuery pageQuery) {
Long classId = resolveClassId();
normalizeDateRange(bo);
Page<ClassTeacherDormViolationVo> page = pageQuery.disableDefaultOrder().build();
IPage<ClassTeacherDormViolationVo> result = classTeacherDormViewMapper.selectViolationPage(page, classId, bo);
return TableDataInfo.build(result);
}
@Override
public TableDataInfo<ClassTeacherDormRollCallVo> queryRollCallPage(ClassTeacherDormQueryBo bo, PageQuery pageQuery) {
Long classId = resolveClassId();
normalizeDateRange(bo);
Page<ClassTeacherDormRollCallVo> page = pageQuery.disableDefaultOrder().build();
IPage<ClassTeacherDormRollCallVo> result = classTeacherDormViewMapper.selectRollCallPage(page, classId, bo);
return TableDataInfo.build(result);
}
private Long resolveClassId() {
ClassTeacherClassInfoVo info = getMyClassInfo();
return info.getClassId();
}
private void normalizeDateRange(ClassTeacherDormQueryBo bo) {
String today = LocalDate.now().format(DATE_FMT);
if (StringUtils.isBlank(bo.getEndDate())) {
bo.setEndDate(today);
}
if (StringUtils.isBlank(bo.getBeginDate())) {
bo.setBeginDate(today);
}
}
}
@@ -0,0 +1,57 @@
package org.dromara.xg.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.RequiredArgsConstructor;
import org.dromara.common.core.utils.MapstructUtils;
import org.dromara.xg.domain.XgDormHygieneCheckDeduction;
import org.dromara.xg.domain.bo.XgDormHygieneCheckDeductionBo;
import org.dromara.xg.domain.vo.XgDormHygieneCheckDeductionVo;
import org.dromara.xg.mapper.XgDormHygieneCheckDeductionMapper;
import org.dromara.xg.service.IXgDormHygieneCheckDeductionService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.Collections;
import java.util.List;
/**
* 宿舍卫生检查扣分明细Service业务层处理
*/
@RequiredArgsConstructor
@Service
public class XgDormHygieneCheckDeductionServiceImpl implements IXgDormHygieneCheckDeductionService {
private final XgDormHygieneCheckDeductionMapper baseMapper;
@Override
public List<XgDormHygieneCheckDeductionVo> listByHygieneCheckId(Long hygieneCheckId) {
if (hygieneCheckId == null) {
return Collections.emptyList();
}
return baseMapper.selectVoListByHygieneCheckId(hygieneCheckId);
}
@Override
@Transactional(rollbackFor = Exception.class)
public void replaceByHygieneCheckId(Long hygieneCheckId, List<XgDormHygieneCheckDeductionBo> items) {
if (hygieneCheckId == null) {
return;
}
LambdaQueryWrapper<XgDormHygieneCheckDeduction> deleteWrapper = Wrappers.lambdaQuery();
deleteWrapper.eq(XgDormHygieneCheckDeduction::getHygieneCheckId, hygieneCheckId);
baseMapper.delete(deleteWrapper);
if (items == null || items.isEmpty()) {
return;
}
int sortOrder = 1;
for (XgDormHygieneCheckDeductionBo item : items) {
XgDormHygieneCheckDeduction entity = MapstructUtils.convert(item, XgDormHygieneCheckDeduction.class);
entity.setId(null);
entity.setHygieneCheckId(hygieneCheckId);
entity.setSortOrder(item.getSortOrder() != null ? item.getSortOrder() : sortOrder++);
baseMapper.insert(entity);
}
}
}
@@ -14,10 +14,12 @@ import org.springframework.transaction.annotation.Transactional;
import org.dromara.xg.domain.bo.XgDormHygieneCheckBo;
import org.dromara.xg.domain.bo.XgDormHygieneCheckCompleteBo;
import org.dromara.xg.domain.bo.XgDormHygieneStudentScoreBo;
import org.dromara.xg.domain.bo.XgDormHygieneCheckDeductionBo;
import org.dromara.xg.domain.bo.XgHygieneCheckViolationBo;
import org.dromara.xg.domain.bo.XgViolationDataBo;
import org.dromara.xg.domain.vo.DormHygieneCheckExportVo;
import org.dromara.xg.domain.vo.XgDormHygieneCheckVo;
import org.dromara.xg.domain.vo.XgDormHygieneCheckDeductionVo;
import org.dromara.xg.domain.XgDormHygieneCheck;
import org.dromara.xg.domain.XgDormHygieneStudentScore;
import org.dromara.xg.mapper.XgDormHygieneCheckMapper;
@@ -26,6 +28,7 @@ import org.dromara.xg.service.IXgDormHygieneCheckService;
import org.dromara.xg.service.IXgStudentMsgService;
import org.dromara.xg.service.IXgHygieneCheckViolationService;
import org.dromara.xg.service.IXgDormHygieneStudentScoreService;
import org.dromara.xg.service.IXgDormHygieneCheckDeductionService;
import org.dromara.xg.mapper.XgHygieneCheckViolationMapper;
import org.dromara.system.service.ISysDictDataService;
import org.springframework.context.ApplicationContext;
@@ -41,6 +44,10 @@ import java.util.stream.Collectors;
import org.dromara.xg.domain.vo.XgHygieneCheckViolationVo;
import org.dromara.xg.domain.XgHygieneCheckViolation;
import java.util.Collections;
import java.util.ArrayList;
import org.dromara.common.core.exception.ServiceException;
import java.math.BigDecimal;
import java.math.RoundingMode;
/**
* 宿舍卫生检查Service业务层处理
@@ -60,6 +67,7 @@ public class XgDormHygieneCheckServiceImpl implements IXgDormHygieneCheckService
private final IXgHygieneCheckViolationService violationService;
private final IXgDormHygieneStudentScoreService studentScoreService;
private final XgHygieneCheckViolationMapper violationMapper;
private final IXgDormHygieneCheckDeductionService deductionService;
private final ApplicationContext applicationContext;
/**
@@ -70,7 +78,21 @@ public class XgDormHygieneCheckServiceImpl implements IXgDormHygieneCheckService
*/
@Override
public XgDormHygieneCheckVo queryById(Long id) {
return baseMapper.selectVoById(id);
XgDormHygieneCheckVo vo = baseMapper.selectVoById(id);
if (vo == null) {
return null;
}
List<XgDormHygieneCheckDeductionVo> deductionItems = deductionService.listByHygieneCheckId(id);
if (deductionItems.isEmpty() && vo.getDisciplineTypeId() != null) {
XgDormHygieneCheckDeductionVo legacyItem = new XgDormHygieneCheckDeductionVo();
legacyItem.setDisciplineTypeId(vo.getDisciplineTypeId());
legacyItem.setDisciplineTypeName(vo.getDisciplineTypeName());
legacyItem.setScore(vo.getTotalScore());
legacyItem.setSortOrder(1);
deductionItems = List.of(legacyItem);
}
vo.setDeductionItems(deductionItems);
return vo;
}
/**
@@ -644,8 +666,10 @@ public class XgDormHygieneCheckServiceImpl implements IXgDormHygieneCheckService
@Transactional(rollbackFor = Exception.class)
public Long saveCompleteData(XgDormHygieneCheckCompleteBo bo) {
try {
List<XgDormHygieneCheckDeductionBo> deductionItems = resolveDeductionItems(bo);
// 1. 转换并保存主表数据
XgDormHygieneCheck add = MapstructUtils.convert(bo, XgDormHygieneCheck.class);
applyDeductionSummary(add, deductionItems);
validEntityBeforeSave(add);
boolean flag = baseMapper.insert(add) > 0;
log.info("保存宿舍卫生检查主表数据: {}", add);
@@ -657,6 +681,9 @@ public class XgDormHygieneCheckServiceImpl implements IXgDormHygieneCheckService
Long hygieneCheckId = add.getId();
// 1.1 保存扣分明细
deductionService.replaceByHygieneCheckId(hygieneCheckId, deductionItems);
// 2. 保存学生评分数据
if (bo.getStudentScores() != null && !bo.getStudentScores().isEmpty()) {
for (XgDormHygieneStudentScoreBo studentScoreBo : bo.getStudentScores()) {
@@ -901,8 +928,13 @@ public class XgDormHygieneCheckServiceImpl implements IXgDormHygieneCheckService
setFieldValue(disciplineRecordBo, "disciplineDate", java.time.LocalDate.now());
}
// 设置违纪原因和内容
setFieldValue(disciplineRecordBo, "disciplineReason", violationBo.getDisciplineReason());
// 设置违纪原因和内容(原因为空时使用违纪类型名称兜底,满足下游非空校验)
String disciplineReason = StringUtils.isNotBlank(violationBo.getDisciplineReason())
? violationBo.getDisciplineReason().trim()
: StringUtils.isNotBlank(violationBo.getDisciplineTypeName())
? violationBo.getDisciplineTypeName()
: "宿舍卫生检查违纪";
setFieldValue(disciplineRecordBo, "disciplineReason", disciplineReason);
setFieldValue(disciplineRecordBo, "disciplineContent", violationBo.getDisciplineContent());
// 设置扣分分值
@@ -1005,8 +1037,10 @@ public class XgDormHygieneCheckServiceImpl implements IXgDormHygieneCheckService
@Transactional(rollbackFor = Exception.class)
public Boolean updateCompleteData(XgDormHygieneCheckCompleteBo bo) {
try {
List<XgDormHygieneCheckDeductionBo> deductionItems = resolveDeductionItems(bo);
// 1. 更新主表数据
XgDormHygieneCheck update = MapstructUtils.convert(bo, XgDormHygieneCheck.class);
applyDeductionSummary(update, deductionItems);
validEntityBeforeSave(update);
boolean flag = baseMapper.updateById(update) > 0;
log.info("更新宿舍卫生检查主表数据: {}", update);
@@ -1018,6 +1052,9 @@ public class XgDormHygieneCheckServiceImpl implements IXgDormHygieneCheckService
Long hygieneCheckId = update.getId();
// 1.1 更新扣分明细
deductionService.replaceByHygieneCheckId(hygieneCheckId, deductionItems);
// 2. 更新学生评分数据 - 先删除旧数据,再插入新数据
LambdaQueryWrapper<XgDormHygieneStudentScore> scoreWrapper = Wrappers.lambdaQuery();
scoreWrapper.eq(XgDormHygieneStudentScore::getHygieneCheckId, hygieneCheckId);
@@ -1341,4 +1378,63 @@ public class XgDormHygieneCheckServiceImpl implements IXgDormHygieneCheckService
}
}
private List<XgDormHygieneCheckDeductionBo> resolveDeductionItems(XgDormHygieneCheckCompleteBo bo) {
if (bo.getDeductionItems() != null && !bo.getDeductionItems().isEmpty()) {
List<XgDormHygieneCheckDeductionBo> items = new ArrayList<>();
Set<Long> typeIds = new HashSet<>();
int sortOrder = 1;
for (XgDormHygieneCheckDeductionBo item : bo.getDeductionItems()) {
if (item == null || item.getDisciplineTypeId() == null) {
continue;
}
if (!typeIds.add(item.getDisciplineTypeId())) {
continue;
}
XgDormHygieneCheckDeductionBo normalized = new XgDormHygieneCheckDeductionBo();
normalized.setId(item.getId());
normalized.setHygieneCheckId(bo.getId());
normalized.setDisciplineTypeId(item.getDisciplineTypeId());
normalized.setDisciplineTypeName(item.getDisciplineTypeName());
normalized.setScore(item.getScore() != null ? item.getScore() : 0D);
normalized.setSortOrder(item.getSortOrder() != null ? item.getSortOrder() : sortOrder++);
normalized.setRemark(item.getRemark());
items.add(normalized);
}
return items;
}
if (bo.getDisciplineTypeId() != null) {
XgDormHygieneCheckDeductionBo legacyItem = new XgDormHygieneCheckDeductionBo();
legacyItem.setDisciplineTypeId(bo.getDisciplineTypeId());
legacyItem.setDisciplineTypeName(bo.getDisciplineTypeName());
legacyItem.setScore(bo.getTotalScore() != null ? bo.getTotalScore() : 0D);
legacyItem.setSortOrder(1);
return List.of(legacyItem);
}
return Collections.emptyList();
}
private void applyDeductionSummary(XgDormHygieneCheck entity, List<XgDormHygieneCheckDeductionBo> items) {
if (items == null || items.isEmpty()) {
entity.setTotalScore(0D);
entity.setDisciplineTypeId(null);
entity.setDisciplineTypeName(null);
return;
}
double total = items.stream()
.map(item -> item.getScore() != null ? item.getScore() : 0D)
.mapToDouble(Double::doubleValue)
.sum();
BigDecimal totalDecimal = BigDecimal.valueOf(total).setScale(2, RoundingMode.HALF_UP);
if (totalDecimal.doubleValue() > 100D) {
throw new ServiceException("宿舍合计扣分不能超过100分");
}
entity.setTotalScore(totalDecimal.doubleValue());
entity.setDisciplineTypeId(items.get(0).getDisciplineTypeId());
String typeNames = items.stream()
.map(XgDormHygieneCheckDeductionBo::getDisciplineTypeName)
.filter(StringUtils::isNotBlank)
.collect(Collectors.joining("、"));
entity.setDisciplineTypeName(typeNames);
}
}
@@ -164,11 +164,7 @@ public class XgDormHygieneStudentScoreServiceImpl implements IXgDormHygieneStude
*/
@Override
public List<XgDormHygieneStudentScoreVo> queryByHygieneCheckId(Long hygieneCheckId) {
LambdaQueryWrapper<XgDormHygieneStudentScore> lqw = Wrappers.lambdaQuery();
lqw.eq(XgDormHygieneStudentScore::getHygieneCheckId, hygieneCheckId);
lqw.eq(XgDormHygieneStudentScore::getDeleted, 0); // 只查询未删除的记录
lqw.orderByAsc(XgDormHygieneStudentScore::getId);
return baseMapper.selectVoList(lqw);
return baseMapper.selectVoListByHygieneCheckId(hygieneCheckId);
}
/**
@@ -23,6 +23,8 @@ import org.dromara.xg.mapper.XgDormRollCallDetailMapper;
import org.dromara.xg.mapper.XgDormRoomMapper;
import org.dromara.xg.mapper.XgDormBedMapper;
import org.dromara.xg.mapper.XgDormBuildingMapper;
import org.dromara.xg.mapper.XgStudentMsgMapper;
import org.dromara.xg.domain.XgStudentMsg;
import org.dromara.xg.domain.XgDormRoom;
import org.dromara.xg.domain.XgDormBuilding;
import org.dromara.xg.domain.XgDormBed;
@@ -45,6 +47,7 @@ public class XgDormRollCallServiceImpl implements IXgDormRollCallService {
private final XgDormRoomMapper roomMapper;
private final XgDormBedMapper bedMapper;
private final XgDormBuildingMapper buildingMapper;
private final XgStudentMsgMapper studentMsgMapper;
@Override
public XgDormRollCallVo queryById(Long id) {
@@ -274,6 +277,7 @@ public class XgDormRollCallServiceImpl implements IXgDormRollCallService {
private void saveDetails(Long rollCallId, List<XgDormRollCallDetailBo> details) {
if (details == null || details.isEmpty()) return;
for (XgDormRollCallDetailBo detailBo : details) {
fillDetailClassInfo(detailBo);
XgDormRollCallDetail detail = new XgDormRollCallDetail();
detail.setRollCallId(rollCallId);
detail.setBedId(detailBo.getBedId());
@@ -296,4 +300,35 @@ public class XgDormRollCallServiceImpl implements IXgDormRollCallService {
detailMapper.insert(detail);
}
}
private void fillDetailClassInfo(XgDormRollCallDetailBo detailBo) {
if (detailBo.getStudentId() == null) {
return;
}
if (detailBo.getClassId() != null && StringUtils.isNotBlank(detailBo.getClassName())) {
return;
}
XgStudentMsg student = studentMsgMapper.selectById(detailBo.getStudentId());
if (student == null) {
return;
}
if (detailBo.getClassId() == null && StringUtils.isNotBlank(student.getClassId())) {
detailBo.setClassId(Long.valueOf(student.getClassId()));
}
if (StringUtils.isBlank(detailBo.getClassName())) {
detailBo.setClassName(student.getClassName());
}
if (detailBo.getMajorId() == null && StringUtils.isNotBlank(student.getMajorId())) {
detailBo.setMajorId(Long.valueOf(student.getMajorId()));
}
if (StringUtils.isBlank(detailBo.getMajorName())) {
detailBo.setMajorName(student.getMajorName());
}
if (detailBo.getCollegeId() == null && StringUtils.isNotBlank(student.getCollegeId())) {
detailBo.setCollegeId(Long.valueOf(student.getCollegeId()));
}
if (StringUtils.isBlank(detailBo.getCollegeName())) {
detailBo.setCollegeName(student.getCollegeName());
}
}
}
@@ -0,0 +1,138 @@
<?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.xg.mapper.XgClassTeacherDormViewMapper">
<select id="selectClassByTeacherId" resultType="org.dromara.xg.domain.vo.ClassTeacherClassInfoVo">
SELECT
cm.id AS classId,
cm.class_name AS className,
cm.class_code AS classCode,
cm.college_name AS collegeName,
cm.major_name AS majorName
FROM xg_class_msg cm
WHERE cm.deleted = 0
AND cm.class_status = '1'
AND (
cm.class_teacher_id = #{teacherId}
OR EXISTS (
SELECT 1 FROM xg_class_teacher_counselor_rel rel
WHERE rel.class_id = cm.id
AND rel.teacher_id = #{teacherId}
AND rel.teacher_type = 'class_teacher'
AND rel.deleted = 0
AND (rel.end_date IS NULL OR rel.end_date &gt; NOW())
)
)
ORDER BY cm.create_time DESC
LIMIT 1
</select>
<select id="selectViolationPage" resultType="org.dromara.xg.domain.vo.ClassTeacherDormViolationVo">
SELECT * FROM (
SELECT
hcv.id AS id,
'hygiene_check' AS dataSource,
'卫生检查' AS dataSourceName,
hcv.student_id AS studentId,
hcv.student_no AS studentNo,
hcv.student_name AS studentName,
sm.class_name AS className,
hc.building_name AS buildingName,
hc.room_name AS roomName,
hcv.discipline_type_name AS violationTypeName,
dr.score_deduction AS scoreDeduction,
NULL AS violationLevel,
COALESCE(dr.discipline_date, DATE(hcv.create_time)) AS violationDate,
dr.discipline_reason COLLATE utf8mb4_general_ci AS violationReason,
hcv.status AS status,
hcv.create_time AS create_time
FROM xg_hygiene_check_violation hcv
INNER JOIN xskh_discipline_record dr ON hcv.discipline_record_id = dr.id AND dr.deleted = 0
INNER JOIN xg_dorm_hygiene_check hc ON hcv.hygiene_check_id = hc.id AND hc.deleted = 0
INNER JOIN xg_student_msg sm ON hcv.student_id = sm.id AND sm.deleted = 0
WHERE hcv.deleted = 0
AND sm.class_id = #{classId}
UNION ALL
SELECT
dv.id AS id,
'dorm_violation' AS dataSource,
'宿舍违纪登记' AS dataSourceName,
dv.student_id AS studentId,
dv.student_no AS studentNo,
dv.student_name AS studentName,
dv.class_name AS className,
dv.building_name AS buildingName,
dv.room_name AS roomName,
dv.violation_type AS violationTypeName,
NULL AS scoreDeduction,
dv.violation_level AS violationLevel,
COALESCE(dv.violation_time, dv.create_time) AS violationDate,
dv.violation_description AS violationReason,
'1' AS status,
dv.create_time AS create_time
FROM xg_dorm_violation dv
LEFT JOIN xg_student_msg sm2 ON dv.student_id = sm2.id AND sm2.deleted = 0
WHERE (dv.deleted = '0' OR dv.deleted = 0)
AND COALESCE(dv.class_id, sm2.class_id) = #{classId}
) t
WHERE 1 = 1
<if test="bo.beginDate != null and bo.beginDate != ''">
AND t.violationDate &gt;= CONCAT(#{bo.beginDate}, ' 00:00:00')
</if>
<if test="bo.endDate != null and bo.endDate != ''">
AND t.violationDate &lt;= CONCAT(#{bo.endDate}, ' 23:59:59')
</if>
<if test="bo.studentNo != null and bo.studentNo != ''">
AND t.studentNo LIKE CONCAT('%', #{bo.studentNo}, '%')
</if>
<if test="bo.studentName != null and bo.studentName != ''">
AND t.studentName LIKE CONCAT('%', #{bo.studentName}, '%')
</if>
ORDER BY t.create_time DESC
</select>
<select id="selectRollCallPage" resultType="org.dromara.xg.domain.vo.ClassTeacherDormRollCallVo">
SELECT
d.id AS id,
d.student_id AS studentId,
d.student_no AS studentNo,
d.student_name AS studentName,
d.class_name AS className,
r.batch_no AS batchNo,
r.check_date AS checkDate,
r.checker_name AS checkerName,
r.building_name AS buildingName,
r.room_name AS roomName,
d.bed_code AS bedCode,
d.roll_call_status AS rollCallStatus,
d.leave_type_name AS leaveTypeName,
r.remark AS remark
FROM xg_dorm_roll_call_detail d
INNER JOIN xg_dorm_roll_call r ON d.roll_call_id = r.id AND r.deleted = 0
INNER JOIN xg_student_msg sm ON d.student_id = sm.id AND sm.deleted = 0
WHERE d.deleted = 0
AND sm.class_id = #{classId}
AND d.roll_call_status != '3'
<if test="bo.beginDate != null and bo.beginDate != ''">
AND r.check_date &gt;= CONCAT(#{bo.beginDate}, ' 00:00:00')
</if>
<if test="bo.endDate != null and bo.endDate != ''">
AND r.check_date &lt;= CONCAT(#{bo.endDate}, ' 23:59:59')
</if>
<if test="bo.studentNo != null and bo.studentNo != ''">
AND d.student_no LIKE CONCAT('%', #{bo.studentNo}, '%')
</if>
<if test="bo.studentName != null and bo.studentName != ''">
AND d.student_name LIKE CONCAT('%', #{bo.studentName}, '%')
</if>
<if test="bo.rollCallStatus != null and bo.rollCallStatus != ''">
AND d.roll_call_status = #{bo.rollCallStatus}
</if>
ORDER BY r.check_date DESC, d.student_no ASC
</select>
</mapper>
@@ -0,0 +1,25 @@
<?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.xg.mapper.XgDormHygieneCheckDeductionMapper">
<select id="selectVoListByHygieneCheckId" resultType="org.dromara.xg.domain.vo.XgDormHygieneCheckDeductionVo">
SELECT
d.id,
d.hygiene_check_id AS hygieneCheckId,
d.discipline_type_id AS disciplineTypeId,
d.discipline_type_name AS disciplineTypeName,
d.score,
d.sort_order AS sortOrder,
d.remark,
dt.min_score AS minScore,
dt.max_score AS maxScore
FROM xg_dorm_hygiene_check_deduction d
LEFT JOIN xskh_discipline_type dt ON dt.id = d.discipline_type_id AND dt.deleted = 0
WHERE d.hygiene_check_id = #{hygieneCheckId}
AND d.deleted = 0
ORDER BY d.sort_order ASC, d.id ASC
</select>
</mapper>
@@ -15,6 +15,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<result property="buildingName" column="building_name" />
<result property="roomName" column="room_name" />
<result property="totalScore" column="total_score" />
<result property="disciplineTypeName" column="discipline_type_name" />
<result property="hygieneGradeText" column="hygiene_grade" />
<result property="studentNo" column="student_no" />
<result property="studentName" column="student_name" />
@@ -44,6 +45,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
dhc.building_name,
dhc.room_name,
dhc.total_score,
dhc.discipline_type_name,
dhc.hygiene_grade,
dhc.check_summary,
dhc.improvement_suggestions,
@@ -4,4 +4,35 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="org.dromara.xg.mapper.XgDormHygieneStudentScoreMapper">
<select id="selectVoListByHygieneCheckId" resultType="org.dromara.xg.domain.vo.XgDormHygieneStudentScoreVo">
SELECT
ss.id,
ss.deleted,
ss.hygiene_check_id AS hygieneCheckId,
ss.student_id AS studentId,
ss.student_no AS studentNo,
ss.student_name AS studentName,
ss.class_id AS classId,
ss.class_name AS className,
ss.major_id AS majorId,
ss.major_name AS majorName,
ss.college_id AS collegeId,
ss.college_name AS collegeName,
ss.bed_id AS bedId,
ss.bed_code AS bedCode,
ss.student_score AS studentScore,
ss.attendance_status AS attendanceStatus,
ss.student_grade AS studentGrade,
ss.is_responsible_person AS isResponsiblePerson,
ss.score_remarks AS scoreRemarks,
ss.improvement_notes AS improvementNotes,
COALESCE(sm_by_id.gender, sm_by_no.gender) AS gender
FROM xg_dorm_hygiene_student_score ss
LEFT JOIN xg_student_msg sm_by_id ON sm_by_id.id = ss.student_id AND sm_by_id.deleted = 0
LEFT JOIN xg_student_msg sm_by_no ON sm_by_no.student_no = ss.student_no AND sm_by_no.deleted = 0
WHERE ss.hygiene_check_id = #{hygieneCheckId}
AND ss.deleted = 0
ORDER BY ss.id ASC
</select>
</mapper>