This commit is contained in:
weizhong committed 2025-08-18 12:03:52 +08:00
commit 56ede5d005
469 files changed
+70832 -49238

No files matched your search

+7
View File
@@ -407,6 +407,13 @@
<version>${revision}</version>
</dependency>
<!-- 招生就业管理模块 -->
<dependency>
<groupId>org.dromara</groupId>
<artifactId>ruoyi-zsjy</artifactId>
<version>${revision}</version>
</dependency>
<!-- 社团管理模块 -->
<!-- <dependency>
<groupId>org.dromara</groupId>
+3 -3
View File
@@ -136,17 +136,17 @@
</dependency>
<!-- 学生考核管理模块 -->
<dependency>
<!-- <dependency>
<groupId>org.dromara</groupId>
<artifactId>ruoyi-xskh</artifactId>
<version>${revision}</version>
</dependency>
</dependency> -->
<!-- 奖惩补贴管理模块 -->
<dependency>
<groupId>org.dromara</groupId>
<artifactId>ruoyi-jcbt</artifactId>
<version>${revision}</version>
</dependency>
</dependency>
<!-- 社团管理模块 -->
<!-- <dependency>
@@ -371,3 +371,10 @@ mybatis-plus:
lazy-loading-enabled: true
# 开启积极懒加载
aggressive-lazy-loading: false
--- # 高德地图配置
amap:
# 高德地图API密钥(请替换为您的实际密钥)
key: 920750e421cd6357ddf60ee1e929e0dd
# 高德地图API基础URL
url: https://restapi.amap.com
@@ -163,9 +163,9 @@ mybatis-plus:
mapperLocations: classpath*:mapper/**/*Mapper.xml
# 实体扫描,多个package用逗号或者分号分隔
typeAliasesPackage: org.dromara.**.domain
# 临时禁用SQL日志(减少系统负担)
# configuration:
# log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
# 启用SQL日志输出,用于调试数据库插入问题
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
global-config:
dbConfig:
# 主键类型
+1 -1
View File
@@ -22,7 +22,7 @@
<module>ruoyi-cw</module>
<module>ruoyi-rs</module>
<module>ruoyi-xljk</module>
<module>ruoyi-jcbt</module>
<module>ruoyi-jcbt</module>
<!-- <module>ruoyi-stgl</module> -->
</modules>
@@ -41,29 +41,30 @@ public interface CwApprovalRecordMapper extends BaseMapperPlus<CwApprovalRecord,
* @param nodeStatus 节点状态
* @return 审批记录列表
*/
List<CwApprovalRecordVo> selectPendingByApproverId(@Param("approverId") Long approverId, @Param("nodeStatus") String nodeStatus);
List<CwApprovalRecordVo> selectPendingByApproverId(@Param("approverId") Long approverId,
@Param("nodeStatus") String nodeStatus);
/**
* 根据审批人ID和节点编码查询审批记录
*
* @param approverId 审批人ID
* @param nodeCode 节点编码
* @param nodeCode 节点编码
* @param nodeStatus 节点状态
* @return 审批记录列表
*/
List<CwApprovalRecordVo> selectByApproverAndNode(@Param("approverId") Long approverId,
@Param("nodeCode") String nodeCode,
@Param("nodeStatus") String nodeStatus);
@Param("nodeCode") String nodeCode,
@Param("nodeStatus") String nodeStatus);
/**
* 根据节点编码查询审批记录
*
* @param nodeCode 节点编码
* @param nodeCode 节点编码
* @param nodeStatus 节点状态
* @return 审批记录列表
*/
List<CwApprovalRecordVo> selectByNode(@Param("nodeCode") String nodeCode,
@Param("nodeStatus") String nodeStatus);
@Param("nodeStatus") String nodeStatus);
/**
* 查询财务审批节点的待审批记录(包含waiting和pending状态)
@@ -91,11 +92,11 @@ public interface CwApprovalRecordMapper extends BaseMapperPlus<CwApprovalRecord,
* 根据申报ID和节点编码查询审批记录
*
* @param applicationId 申报ID
* @param nodeCode 节点编码
* @param nodeCode 节点编码
* @return 审批记录
*/
CwApprovalRecordVo selectByApplicationAndNode(@Param("applicationId") Long applicationId,
@Param("nodeCode") String nodeCode);
@Param("nodeCode") String nodeCode);
/**
* 根据申报ID删除审批记录
@@ -109,11 +110,11 @@ public interface CwApprovalRecordMapper extends BaseMapperPlus<CwApprovalRecord,
* 查询当前审批节点记录
*
* @param applicationId 申报ID
* @param nodeStatus 节点状态
* @param nodeStatus 节点状态
* @return 当前审批节点记录
*/
CwApprovalRecordVo selectCurrentApprovalNode(@Param("applicationId") Long applicationId,
@Param("nodeStatus") String nodeStatus);
@Param("nodeStatus") String nodeStatus);
/**
* 批量插入审批记录
@@ -127,7 +128,7 @@ public interface CwApprovalRecordMapper extends BaseMapperPlus<CwApprovalRecord,
* 分页查询审批记录(支持关联查询)
*
* @param page 分页参数
* @param bo 查询条件
* @param bo 查询条件
* @return 分页结果
*/
IPage<CwApprovalRecordVo> selectPageWithJoin(IPage<CwApprovalRecordVo> page, @Param("bo") CwApprovalRecordBo bo);
@@ -140,4 +141,12 @@ public interface CwApprovalRecordMapper extends BaseMapperPlus<CwApprovalRecord,
*/
CwApprovalRecordVo selectByIdWithJoin(@Param("id") Long id);
/**
* 查询具有院领导审批权限的用户列表
* 查找具有 'cw:approval:leader' 权限的用户
*
* @return 可选审批人列表
*/
List<java.util.Map<String, Object>> selectAvailableApprovers();
}
@@ -37,7 +37,6 @@ import java.util.*;
import java.util.stream.Collectors;
import org.dromara.common.core.utils.SpringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
/**
* 审批记录Service业务层处理
@@ -56,9 +55,6 @@ public class CwApprovalRecordServiceImpl implements ICwApprovalRecordService {
private final ISysUserService sysUserService;
private final ISysDeptService sysDeptService;
@Autowired
private JdbcTemplate jdbcTemplate;
/**
* 根据主键查询审批记录
*/
@@ -90,7 +86,8 @@ public class CwApprovalRecordServiceImpl implements ICwApprovalRecordService {
*/
@Override
public TableDataInfo<CwApprovalRecordVo> queryPageList(CwApprovalRecordBo bo, PageQuery pageQuery) {
log.info("🔍 开始查询审批记录,查询参数:deptId={}, pageNum={}, pageSize={}", bo.getDeptId(), pageQuery.getPageNum(), pageQuery.getPageSize());
log.info("🔍 开始查询审批记录,查询参数:deptId={}, pageNum={}, pageSize={}", bo.getDeptId(), pageQuery.getPageNum(),
pageQuery.getPageSize());
// 🔧 使用新的关联查询方法(支持完整字段显示)
Page<CwApprovalRecordVo> page = pageQuery.build();
@@ -167,7 +164,7 @@ public class CwApprovalRecordServiceImpl implements ICwApprovalRecordService {
for (int i = 0; i < Math.min(result.getRecords().size(), 2); i++) {
CwApprovalRecordVo record = result.getRecords().get(i);
log.info("📋 记录{}详情:id={}, 申报编号={}, 项目名称={}, 申报人={}, 部门={}, 总投资={}, 当前审批人={}, 状态={}",
i+1, record.getId(), record.getApplicationNo(), record.getProjectName(),
i + 1, record.getId(), record.getApplicationNo(), record.getProjectName(),
record.getApplicantName(), record.getDeptName(), record.getTotalInvestment(),
record.getCurrentApproverName(), record.getApprovalStatus());
}
@@ -196,7 +193,8 @@ public class CwApprovalRecordServiceImpl implements ICwApprovalRecordService {
private LambdaQueryWrapper<CwApprovalRecord> buildQueryWrapper(CwApprovalRecordBo bo) {
LambdaQueryWrapper<CwApprovalRecord> lqw = Wrappers.lambdaQuery();
lqw.eq(bo.getApplicationId() != null, CwApprovalRecord::getApplicationId, bo.getApplicationId());
lqw.eq(StringUtils.isNotBlank(bo.getApplicationNo()), CwApprovalRecord::getApplicationNo, bo.getApplicationNo());
lqw.eq(StringUtils.isNotBlank(bo.getApplicationNo()), CwApprovalRecord::getApplicationNo,
bo.getApplicationNo());
lqw.eq(StringUtils.isNotBlank(bo.getNodeCode()), CwApprovalRecord::getNodeCode, bo.getNodeCode());
lqw.eq(StringUtils.isNotBlank(bo.getNodeStatus()), CwApprovalRecord::getNodeStatus, bo.getNodeStatus());
lqw.eq(bo.getApproverId() != null, CwApprovalRecord::getApproverId, bo.getApproverId());
@@ -212,7 +210,8 @@ public class CwApprovalRecordServiceImpl implements ICwApprovalRecordService {
if (currentDeptId != null) {
// 查询该部门的项目申报ID列表
lqw.inSql(CwApprovalRecord::getApplicationId,
"SELECT id FROM cw_project_application WHERE department_id = " + currentDeptId + " AND deleted = 0");
"SELECT id FROM cw_project_application WHERE department_id = " + currentDeptId
+ " AND deleted = 0");
// 只显示部门审批节点的记录
lqw.eq(CwApprovalRecord::getNodeCode, "dept_approve");
@@ -234,7 +233,8 @@ public class CwApprovalRecordServiceImpl implements ICwApprovalRecordService {
try {
Long deptId = Long.valueOf(bo.getDeptId());
lqw.in(CwApprovalRecord::getApplicationId,
"SELECT id FROM cw_project_application WHERE department_id = " + deptId + " AND deleted = 0");
"SELECT id FROM cw_project_application WHERE department_id = " + deptId
+ " AND deleted = 0");
} catch (NumberFormatException e) {
log.warn("无效的部门ID格式:{}", bo.getDeptId());
}
@@ -245,11 +245,11 @@ public class CwApprovalRecordServiceImpl implements ICwApprovalRecordService {
// 其他查询条件 - 暂时注释掉,避免复杂的关联查询导致编译错误
// if (StringUtils.isNotBlank(bo.getProjectName())) {
// // 项目名称查询需要关联查询,暂时跳过
// // 项目名称查询需要关联查询,暂时跳过
// }
// if (StringUtils.isNotBlank(bo.getApplicantName())) {
// // 申报人姓名查询需要关联查询,暂时跳过
// // 申报人姓名查询需要关联查询,暂时跳过
// }
if (StringUtils.isNotBlank(bo.getApproverName())) {
@@ -304,8 +304,8 @@ public class CwApprovalRecordServiceImpl implements ICwApprovalRecordService {
if (deptId != null) {
// 通过关联查询,只显示本部门用户提交的申报对应的审批记录
lqw.exists("SELECT 1 FROM cw_project_application a " +
"WHERE a.id = cw_approval_record.application_id " +
"AND a.department_id = " + deptId);
"WHERE a.id = cw_approval_record.application_id " +
"AND a.department_id = " + deptId);
// 🔧 关键修复:部门领导也需要过滤为自己作为审批人的记录
lqw.eq(CwApprovalRecord::getApproverId, currentUserId);
log.debug("部门领导权限过滤完成:deptId={}, approverId={}", deptId, currentUserId);
@@ -383,8 +383,8 @@ public class CwApprovalRecordServiceImpl implements ICwApprovalRecordService {
// 查询当前用户已审批的记录(精确匹配已完成的状态)
LambdaQueryWrapper<CwApprovalRecord> queryWrapper = Wrappers.lambdaQuery();
queryWrapper.eq(CwApprovalRecord::getApproverId, currentUserId)
.in(CwApprovalRecord::getNodeStatus, Arrays.asList("approved", "rejected", "returned"))
.orderByDesc(CwApprovalRecord::getEndTime);
.in(CwApprovalRecord::getNodeStatus, Arrays.asList("approved", "rejected", "returned"))
.orderByDesc(CwApprovalRecord::getEndTime);
return baseMapper.selectList(queryWrapper);
});
@@ -544,8 +544,8 @@ public class CwApprovalRecordServiceImpl implements ICwApprovalRecordService {
@Override
@Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRES_NEW)
public Boolean createApprovalProcess(Long applicationId, String applicationNo,
Long currentUserId, String currentUserName,
Long currentDeptId, String currentTenantId) {
Long currentUserId, String currentUserName,
Long currentDeptId, String currentTenantId) {
log.info("🚀 开始创建审批流程:applicationId={}, applicationNo={}", applicationId, applicationNo);
log.info("📋 使用用户上下文:userId={}, userName={}, deptId={}, tenantId={}",
currentUserId, currentUserName, currentDeptId, currentTenantId);
@@ -565,15 +565,15 @@ public class CwApprovalRecordServiceImpl implements ICwApprovalRecordService {
log.error("❌ 申报记录不存在:applicationId={}", applicationId);
throw new RuntimeException("申报记录不存在");
}
log.info("✅ 成功获取申报信息:projectName={}, status={}", application.getProjectName(), application.getApprovalStatus());
log.info("✅ 成功获取申报信息:projectName={}, status={}", application.getProjectName(),
application.getApprovalStatus());
// 🔧 重要修复:清理该申报的旧审批记录(避免重复数据)
log.info("🧹 开始清理申报ID={}的旧审批记录...", applicationId);
try {
int deletedCount = baseMapper.delete(
Wrappers.<CwApprovalRecord>lambdaQuery()
.eq(CwApprovalRecord::getApplicationId, applicationId)
);
Wrappers.<CwApprovalRecord>lambdaQuery()
.eq(CwApprovalRecord::getApplicationId, applicationId));
log.info("✅ 清理旧审批记录完成:删除{}条记录", deletedCount);
} catch (Exception e) {
log.error("❌ 清理旧审批记录失败:applicationId={}, error={}", applicationId, e.getMessage(), e);
@@ -587,8 +587,8 @@ public class CwApprovalRecordServiceImpl implements ICwApprovalRecordService {
// 第1节点:部门审批(提交时只创建这一个记录)
CwApprovalRecord deptRecord = createApprovalRecord(applicationId, applicationNo,
"dept_approve", "部门审批", 1, "waiting",
currentUserId, currentUserName, currentDeptId, currentTenantId);
"dept_approve", "部门审批", 1, "waiting",
currentUserId, currentUserName, currentDeptId, currentTenantId);
records.add(deptRecord);
log.info("✅ 创建部门审批记录:ID={}, 审批人={}", deptRecord.getId(), deptRecord.getApproverName());
@@ -602,8 +602,8 @@ public class CwApprovalRecordServiceImpl implements ICwApprovalRecordService {
for (int i = 0; i < records.size(); i++) {
CwApprovalRecord record = records.get(i);
log.info("📋 记录{}详情: ID={}, ApplicationId={}, NodeCode={}, ApproverId={}, CreateBy={}, TenantId={}",
i+1, record.getId(), record.getApplicationId(), record.getNodeCode(),
record.getApproverId(), record.getCreateBy(), record.getTenantId());
i + 1, record.getId(), record.getApplicationId(), record.getNodeCode(),
record.getApproverId(), record.getCreateBy(), record.getTenantId());
}
// 批量插入审批记录
@@ -626,11 +626,10 @@ public class CwApprovalRecordServiceImpl implements ICwApprovalRecordService {
try {
// 直接使用Mapper在当前事务中更新,避免调用Service层的新事务
int updateCount = applicationMapper.update(null,
Wrappers.<CwProjectApplication>lambdaUpdate()
.set(CwProjectApplication::getApprovalStatus, "approving")
.set(CwProjectApplication::getUpdateTime, new Date())
.eq(CwProjectApplication::getId, applicationId)
);
Wrappers.<CwProjectApplication>lambdaUpdate()
.set(CwProjectApplication::getApprovalStatus, "approving")
.set(CwProjectApplication::getUpdateTime, new Date())
.eq(CwProjectApplication::getId, applicationId));
if (updateCount > 0) {
log.info("✅ 申报状态直接更新成功:applicationId={} -> approving, 影响行数={}", applicationId, updateCount);
@@ -673,10 +672,10 @@ public class CwApprovalRecordServiceImpl implements ICwApprovalRecordService {
}
private CwApprovalRecord createApprovalRecord(Long applicationId, String applicationNo,
String nodeCode, String nodeName,
Integer nodeOrder, String nodeStatus,
Long currentUserId, String currentUserName,
Long currentDeptId, String currentTenantId) {
String nodeCode, String nodeName,
Integer nodeOrder, String nodeStatus,
Long currentUserId, String currentUserName,
Long currentDeptId, String currentTenantId) {
CwApprovalRecord record = new CwApprovalRecord();
// 生成唯一ID(批量插入需要手动生成)
@@ -709,7 +708,7 @@ public class CwApprovalRecordServiceImpl implements ICwApprovalRecordService {
record.setCreateDept(currentDeptId);
record.setTenantId(currentTenantId);
// 设置其他必需字段(为批量插入提供完整数据)
// 设置其他必需字段(为批量插入提供完整数据)
record.setIsDelegate(false);
record.setIsOvertime(false);
@@ -748,7 +747,7 @@ public class CwApprovalRecordServiceImpl implements ICwApprovalRecordService {
* 根据节点类型设置审批人
*/
private void setApproverByNodeCode(CwApprovalRecord record, String nodeCode,
Long currentUserId, String currentUserName) {
Long currentUserId, String currentUserName) {
// 根据审批节点类型查找正确的审批人,而不是使用申报人
try {
switch (nodeCode) {
@@ -875,12 +874,12 @@ public class CwApprovalRecordServiceImpl implements ICwApprovalRecordService {
try {
// SQL查询:查找该部门内具有project_dept_manage角色的用户
String sql = "SELECT ur.user_id FROM sys_user_role ur " +
"INNER JOIN sys_role r ON ur.role_id = r.role_id " +
"INNER JOIN sys_user u ON ur.user_id = u.user_id " +
"WHERE r.role_key = 'project_dept_manage' " +
"AND u.dept_id = " + deptId + " " +
"AND u.del_flag = 0 AND u.status = 0 " +
"LIMIT 1";
"INNER JOIN sys_role r ON ur.role_id = r.role_id " +
"INNER JOIN sys_user u ON ur.user_id = u.user_id " +
"WHERE r.role_key = 'project_dept_manage' " +
"AND u.dept_id = " + deptId + " " +
"AND u.del_flag = 0 AND u.status = 0 " +
"LIMIT 1";
log.info("查找部门审批人SQL:{}", sql);
@@ -958,8 +957,8 @@ public class CwApprovalRecordServiceImpl implements ICwApprovalRecordService {
// 更新当前审批记录
CwApprovalRecordBo updateBo = new CwApprovalRecordBo();
updateBo.setId(currentRecord.getId());
updateBo.setNodeStatus("approve".equals(approveAction) ? "approved" :
"reject".equals(approveAction) ? "rejected" : "returned");
updateBo.setNodeStatus("approve".equals(approveAction) ? "approved"
: "reject".equals(approveAction) ? "rejected" : "returned");
updateBo.setApproveAction(approveAction);
updateBo.setApproveOpinion(approveOpinion);
updateBo.setEndTime(new Date());
@@ -974,7 +973,7 @@ public class CwApprovalRecordServiceImpl implements ICwApprovalRecordService {
} catch (Exception e) {
log.error("处理审批失败:applicationId={}, nodeCode={}, error={}",
applicationId, nodeCode, e.getMessage(), e);
applicationId, nodeCode, e.getMessage(), e);
throw new RuntimeException("处理审批失败:" + e.getMessage(), e);
}
}
@@ -1020,8 +1019,8 @@ public class CwApprovalRecordServiceImpl implements ICwApprovalRecordService {
// 根据节点类型创建对应的审批记录
CwApprovalRecord newRecord = createApprovalRecordForNode(applicationId, application.getApplicationNo(),
nextNodeCode, application.getCreateBy(), application.getApplicantName(),
application.getDepartmentId(), LoginHelper.getTenantId());
nextNodeCode, application.getCreateBy(), application.getApplicantName(),
application.getDepartmentId(), LoginHelper.getTenantId());
if (newRecord != null) {
// 插入新的审批记录
@@ -1046,7 +1045,7 @@ public class CwApprovalRecordServiceImpl implements ICwApprovalRecordService {
return true;
} catch (Exception e) {
log.error("启动下一个审批节点失败:applicationId={}, nodeCode={}, error={}",
applicationId, nextNodeCode, e.getMessage(), e);
applicationId, nextNodeCode, e.getMessage(), e);
throw new RuntimeException("启动下一个审批节点失败:" + e.getMessage());
}
}
@@ -1055,8 +1054,8 @@ public class CwApprovalRecordServiceImpl implements ICwApprovalRecordService {
* 动态创建指定节点的审批记录
*/
private CwApprovalRecord createApprovalRecordForNode(Long applicationId, String applicationNo,
String nodeCode, Long createBy, String createByName,
Long deptId, String tenantId) {
String nodeCode, Long createBy, String createByName,
Long deptId, String tenantId) {
try {
String nodeName;
Integer nodeOrder;
@@ -1077,11 +1076,11 @@ public class CwApprovalRecordServiceImpl implements ICwApprovalRecordService {
// 创建审批记录
CwApprovalRecord record = createApprovalRecord(applicationId, applicationNo,
nodeCode, nodeName, nodeOrder, "waiting",
createBy, createByName, deptId, tenantId);
nodeCode, nodeName, nodeOrder, "waiting",
createBy, createByName, deptId, tenantId);
log.info("✅ 动态创建审批记录:nodeCode={}, nodeName={}, approverId={}",
nodeCode, nodeName, record.getApproverId());
nodeCode, nodeName, record.getApproverId());
return record;
} catch (Exception e) {
@@ -1124,7 +1123,7 @@ public class CwApprovalRecordServiceImpl implements ICwApprovalRecordService {
return checkApprovalPermission(applicationId, "dept_approve");
}
/**
/**
* 获取可选审批人列表(院领导)
* 修改为基于权限角色查找:查找具有cw:approval:leader权限的用户
*/
@@ -1135,46 +1134,22 @@ public class CwApprovalRecordServiceImpl implements ICwApprovalRecordService {
List<Map<String, Object>> approvers = new ArrayList<>();
try {
// 使用原生SQL查询具有cw:approval:leader权限的用户
String sql = """
SELECT DISTINCT
u.user_id,
u.user_name,
u.nick_name,
COALESCE(d.dept_name, '未分配部门') as dept_name,
COALESCE(d.dept_id, 0) as dept_id
FROM sys_user u
LEFT JOIN sys_dept d ON u.dept_id = d.dept_id
INNER JOIN sys_user_role ur ON u.user_id = ur.user_id
INNER JOIN sys_role r ON ur.role_id = r.role_id
INNER JOIN sys_role_menu rm ON r.role_id = rm.role_id
INNER JOIN sys_menu m ON rm.menu_id = m.menu_id
WHERE m.perms = 'cw:approval:leader'
AND u.status = '0'
AND u.del_flag = '0'
AND r.status = '0'
ORDER BY u.user_name
""";
// 🔧 使用Mapper方法查询具有cw:approval:leader权限的用户
log.info("执行Mapper查询查找具有cw:approval:leader权限的用户");
log.info("执行权限查询SQL查找具有cw:approval:leader权限的用户");
// 直接调用Mapper方法,不需要手动转换结果
List<Map<String, Object>> results = baseMapper.selectAvailableApprovers();
// 执行SQL查询
List<Map<String, Object>> results = jdbcTemplate.queryForList(sql);
log.info("Mapper查询结果:找到 {} 个具有院领导审批权限的用户", results.size());
log.info("SQL查询结果:找到 {} 个具有院领导审批权限的用户", results.size());
// 转换查询结果为返回格式
for (Map<String, Object> row : results) {
Map<String, Object> approver = new HashMap<>();
approver.put("userId", row.get("user_id"));
approver.put("userName", row.get("user_name"));
approver.put("nickName", row.get("nick_name"));
approver.put("deptName", row.get("dept_name"));
approver.put("deptId", row.get("dept_id"));
approvers.add(approver);
// 直接使用查询结果,Mapper已经处理了字段映射
approvers.addAll(results);
// 记录查询到的审批人信息
for (Map<String, Object> approver : approvers) {
log.info("添加院领导审批人: userId={}, userName={}, nickName={}, deptName={}",
row.get("user_id"), row.get("user_name"), row.get("nick_name"), row.get("dept_name"));
approver.get("userId"), approver.get("userName"), approver.get("nickName"),
approver.get("deptName"));
}
// 如果基于权限查询没有找到用户,使用原有的部门查询作为备选方案
@@ -1230,11 +1205,10 @@ public class CwApprovalRecordServiceImpl implements ICwApprovalRecordService {
// 1. 查找当前用户的待审批记录
CwApprovalRecord currentRecord = baseMapper.selectOne(
Wrappers.lambdaQuery(CwApprovalRecord.class)
.eq(CwApprovalRecord::getApplicationId, applicationId)
.eq(CwApprovalRecord::getApproverId, currentUserId)
.eq(CwApprovalRecord::getNodeStatus, "waiting")
);
Wrappers.lambdaQuery(CwApprovalRecord.class)
.eq(CwApprovalRecord::getApplicationId, applicationId)
.eq(CwApprovalRecord::getApproverId, currentUserId)
.eq(CwApprovalRecord::getNodeStatus, "waiting"));
if (currentRecord == null) {
throw new RuntimeException("未找到待审批记录或您没有审批权限");
@@ -1263,7 +1237,7 @@ public class CwApprovalRecordServiceImpl implements ICwApprovalRecordService {
throw new RuntimeException("更新审批记录失败");
}
// 3. 更新项目申请状态
// 3. 更新项目申请状态
String newStatus;
if ("approve".equals(approveAction)) {
// 分管领导审批通过,整个审批流程完成
@@ -1292,7 +1266,8 @@ public class CwApprovalRecordServiceImpl implements ICwApprovalRecordService {
*/
@Override
@Transactional(rollbackFor = Exception.class)
public void financeApproval(Long applicationId, String approveAction, String approveOpinion, Long selectedApproverId) {
public void financeApproval(Long applicationId, String approveAction, String approveOpinion,
Long selectedApproverId) {
Long currentUserId = LoginHelper.getUserId();
log.info("🔍 财务审批开始:applicationId={}, userId={}, action={}, selectedApproverId={}",
applicationId, currentUserId, approveAction, selectedApproverId);
@@ -1306,24 +1281,22 @@ public class CwApprovalRecordServiceImpl implements ICwApprovalRecordService {
log.info("🔍 查询财务审批记录:applicationId={}, nodeCode=finance_approve, nodeStatus=waiting", applicationId);
List<CwApprovalRecord> records = baseMapper.selectList(
Wrappers.lambdaQuery(CwApprovalRecord.class)
.eq(CwApprovalRecord::getApplicationId, applicationId)
.eq(CwApprovalRecord::getNodeCode, "finance_approve")
.eq(CwApprovalRecord::getNodeStatus, "waiting")
.orderByDesc(CwApprovalRecord::getCreateTime)
);
Wrappers.lambdaQuery(CwApprovalRecord.class)
.eq(CwApprovalRecord::getApplicationId, applicationId)
.eq(CwApprovalRecord::getNodeCode, "finance_approve")
.eq(CwApprovalRecord::getNodeStatus, "waiting")
.orderByDesc(CwApprovalRecord::getCreateTime));
if (records.isEmpty()) {
log.error("❌ 未找到财务审批记录:applicationId={}", applicationId);
// 查询所有相关记录用于调试
List<CwApprovalRecord> allRecords = baseMapper.selectList(
Wrappers.lambdaQuery(CwApprovalRecord.class)
.eq(CwApprovalRecord::getApplicationId, applicationId)
);
Wrappers.lambdaQuery(CwApprovalRecord.class)
.eq(CwApprovalRecord::getApplicationId, applicationId));
log.error("📋 该申请的所有审批记录:{}", allRecords.size());
for (CwApprovalRecord record : allRecords) {
log.error("📋 记录详情:nodeCode={}, nodeStatus={}, approverId={}",
record.getNodeCode(), record.getNodeStatus(), record.getApproverId());
record.getNodeCode(), record.getNodeStatus(), record.getApproverId());
}
throw new RuntimeException("未找到待审批记录或该申请已被处理");
}
@@ -1335,7 +1308,8 @@ public class CwApprovalRecordServiceImpl implements ICwApprovalRecordService {
}
log.info("✅ 找到财务审批记录:recordId={}, nodeCode={}, nodeStatus={}, approverId={}",
currentRecord.getId(), currentRecord.getNodeCode(), currentRecord.getNodeStatus(), currentRecord.getApproverId());
currentRecord.getId(), currentRecord.getNodeCode(), currentRecord.getNodeStatus(),
currentRecord.getApproverId());
// 3. 更新当前审批记录
Date now = new Date();
@@ -1392,23 +1366,21 @@ public class CwApprovalRecordServiceImpl implements ICwApprovalRecordService {
private void updateLeaderApproverAndStart(Long applicationId, Long selectedApproverId) {
// 1. 查找分管领导审批记录(先按waiting状态查找)
CwApprovalRecord leaderRecord = baseMapper.selectOne(
Wrappers.lambdaQuery(CwApprovalRecord.class)
.eq(CwApprovalRecord::getApplicationId, applicationId)
.eq(CwApprovalRecord::getNodeCode, "leader_approve")
.eq(CwApprovalRecord::getNodeStatus, "waiting")
);
Wrappers.lambdaQuery(CwApprovalRecord.class)
.eq(CwApprovalRecord::getApplicationId, applicationId)
.eq(CwApprovalRecord::getNodeCode, "leader_approve")
.eq(CwApprovalRecord::getNodeStatus, "waiting"));
// 2. 如果waiting状态未找到,尝试查找pending状态(兼容处理)
if (leaderRecord == null) {
leaderRecord = baseMapper.selectOne(
Wrappers.lambdaQuery(CwApprovalRecord.class)
.eq(CwApprovalRecord::getApplicationId, applicationId)
.eq(CwApprovalRecord::getNodeCode, "leader_approve")
.eq(CwApprovalRecord::getNodeStatus, "pending")
);
Wrappers.lambdaQuery(CwApprovalRecord.class)
.eq(CwApprovalRecord::getApplicationId, applicationId)
.eq(CwApprovalRecord::getNodeCode, "leader_approve")
.eq(CwApprovalRecord::getNodeStatus, "pending"));
}
// 3. 如果仍未找到,动态创建分管领导审批记录
// 3. 如果仍未找到,动态创建分管领导审批记录
if (leaderRecord == null) {
log.warn("未找到分管领导审批记录,开始动态创建:applicationId={}", applicationId);
@@ -1426,17 +1398,16 @@ public class CwApprovalRecordServiceImpl implements ICwApprovalRecordService {
// 创建分管领导审批记录
leaderRecord = createApprovalRecord(
applicationId,
applicationVo.getApplicationNo(),
"leader_approve",
"分管领导审批",
3, // leader_approve 节点顺序
"waiting",
currentUserId,
currentUserName,
currentDeptId,
currentTenantId
);
applicationId,
applicationVo.getApplicationNo(),
"leader_approve",
"分管领导审批",
3, // leader_approve 节点顺序
"waiting",
currentUserId,
currentUserName,
currentDeptId,
currentTenantId);
// 保存到数据库
int result = baseMapper.insert(leaderRecord);
@@ -1447,7 +1418,7 @@ public class CwApprovalRecordServiceImpl implements ICwApprovalRecordService {
log.info("✅ 动态创建分管领导审批记录成功:recordId={}", leaderRecord.getId());
}
// 2. 获取选择的院领导信息
// 2. 获取选择的院领导信息
try {
SysUserVo selectedUser = sysUserService.selectUserById(selectedApproverId);
if (selectedUser == null) {
@@ -1470,12 +1441,12 @@ public class CwApprovalRecordServiceImpl implements ICwApprovalRecordService {
throw new RuntimeException("更新分管领导审批记录失败");
}
log.info("✅ 成功指定院领导审批人:userId={}, userName={}",
log.info("✅ 成功指定院领导审批人:userId={}, userName={}",
selectedApproverId, selectedUser.getUserName());
} catch (Exception e) {
log.error("❌ 更新分管领导审批人失败:applicationId={}, selectedApproverId={}, error={}",
applicationId, selectedApproverId, e.getMessage(), e);
applicationId, selectedApproverId, e.getMessage(), e);
throw new RuntimeException("指定院领导审批人失败:" + e.getMessage());
}
}
@@ -234,4 +234,25 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
ORDER BY ar.create_time DESC
</select>
<!-- 查询具有院领导审批权限的用户列表 -->
<select id="selectAvailableApprovers" resultType="java.util.Map">
SELECT DISTINCT
u.user_id as userId,
u.user_name as userName,
u.nick_name as nickName,
COALESCE(d.dept_name, '未分配部门') as deptName,
COALESCE(d.dept_id, 0) as deptId
FROM sys_user u
LEFT JOIN sys_dept d ON u.dept_id = d.dept_id
INNER JOIN sys_user_role ur ON u.user_id = ur.user_id
INNER JOIN sys_role r ON ur.role_id = r.role_id
INNER JOIN sys_role_menu rm ON r.role_id = rm.role_id
INNER JOIN sys_menu m ON rm.menu_id = m.menu_id
WHERE m.perms = 'cw:approval:leader'
AND u.status = '0'
AND u.del_flag = '0'
AND r.status = '0'
ORDER BY u.user_name
</select>
</mapper>
@@ -70,6 +70,7 @@ public class JcbtScholarshipApplicationServiceImpl implements IJcbtScholarshipAp
* 查询奖学金申请记录详情
*/
@Override
@Transactional(rollbackFor = Exception.class)
public JcbtScholarshipApplicationVo queryById(Long id) {
return baseMapper.selectByIdWithRelations(id);
}
@@ -78,10 +79,13 @@ public class JcbtScholarshipApplicationServiceImpl implements IJcbtScholarshipAp
* 查询奖学金申请记录分页列表
*/
@Override
public TableDataInfo<JcbtScholarshipApplicationVo> queryPageList(JcbtScholarshipApplicationBo bo, PageQuery pageQuery) {
@Transactional(rollbackFor = Exception.class)
public TableDataInfo<JcbtScholarshipApplicationVo> queryPageList(JcbtScholarshipApplicationBo bo,
PageQuery pageQuery) {
LambdaQueryWrapper<JcbtScholarshipApplication> lqw = buildQueryWrapper(bo);
// 使用自定义分页查询(包含关联表信息)
Page<JcbtScholarshipApplicationVo> result = baseMapper.selectJcbtScholarshipApplicationPage(pageQuery.build(), lqw);
Page<JcbtScholarshipApplicationVo> result = baseMapper.selectJcbtScholarshipApplicationPage(pageQuery.build(),
lqw);
return TableDataInfo.build(result);
}
@@ -89,6 +93,7 @@ public class JcbtScholarshipApplicationServiceImpl implements IJcbtScholarshipAp
* 查询奖学金申请记录列表
*/
@Override
@Transactional(rollbackFor = Exception.class)
public List<JcbtScholarshipApplicationVo> queryList(JcbtScholarshipApplicationBo bo) {
LambdaQueryWrapper<JcbtScholarshipApplication> lqw = buildQueryWrapper(bo);
return baseMapper.selectVoList(lqw);
@@ -98,18 +103,21 @@ public class JcbtScholarshipApplicationServiceImpl implements IJcbtScholarshipAp
Map<String, Object> params = bo.getParams();
LambdaQueryWrapper<JcbtScholarshipApplication> lqw = Wrappers.lambdaQuery();
lqw.eq(ObjectUtil.isNotNull(bo.getBatchId()), JcbtScholarshipApplication::getBatchId, bo.getBatchId());
lqw.eq(ObjectUtil.isNotNull(bo.getScholarshipTypeId()), JcbtScholarshipApplication::getScholarshipTypeId, bo.getScholarshipTypeId());
lqw.eq(ObjectUtil.isNotNull(bo.getScholarshipTypeId()), JcbtScholarshipApplication::getScholarshipTypeId,
bo.getScholarshipTypeId());
lqw.eq(StringUtils.isNotBlank(bo.getStudentNo()), JcbtScholarshipApplication::getStudentNo, bo.getStudentNo());
lqw.like(StringUtils.isNotBlank(bo.getStudentName()), JcbtScholarshipApplication::getStudentName, bo.getStudentName());
lqw.like(StringUtils.isNotBlank(bo.getStudentName()), JcbtScholarshipApplication::getStudentName,
bo.getStudentName());
lqw.eq(ObjectUtil.isNotNull(bo.getStudentId()), JcbtScholarshipApplication::getStudentId, bo.getStudentId());
lqw.eq(ObjectUtil.isNotNull(bo.getDeptId()), JcbtScholarshipApplication::getDeptId, bo.getDeptId());
lqw.eq(ObjectUtil.isNotNull(bo.getClassId()), JcbtScholarshipApplication::getClassId, bo.getClassId());
// 已删除 applicantType 和 applicantId 字段
lqw.eq(StringUtils.isNotBlank(bo.getStatus()), JcbtScholarshipApplication::getCurrentStatus, bo.getStatus());
// 支持前端 applicationStatus 查询参数
lqw.eq(StringUtils.isNotBlank(bo.getApplicationStatus()), JcbtScholarshipApplication::getCurrentStatus, bo.getApplicationStatus());
lqw.eq(StringUtils.isNotBlank(bo.getApplicationStatus()), JcbtScholarshipApplication::getCurrentStatus,
bo.getApplicationStatus());
lqw.between(params.get("beginCreateTime") != null && params.get("endCreateTime") != null,
JcbtScholarshipApplication::getCreateTime, params.get("beginCreateTime"), params.get("endCreateTime"));
JcbtScholarshipApplication::getCreateTime, params.get("beginCreateTime"), params.get("endCreateTime"));
// 注意:排序在XML中处理,避免SQL语法错误
// lqw.orderByDesc(JcbtScholarshipApplication::getCreateTime);
return lqw;
@@ -122,7 +130,8 @@ public class JcbtScholarshipApplicationServiceImpl implements IJcbtScholarshipAp
@Transactional(rollbackFor = Exception.class)
public Boolean insertByBo(JcbtScholarshipApplicationBo bo) {
// 检查申请资格
Map<String, Object> eligibilityCheck = checkStudentEligibility(bo.getStudentId(), bo.getBatchId(), bo.getScholarshipTypeId());
Map<String, Object> eligibilityCheck = checkStudentEligibility(bo.getStudentId(), bo.getBatchId(),
bo.getScholarshipTypeId());
if (!(Boolean) eligibilityCheck.get("eligible")) {
throw new RuntimeException((String) eligibilityCheck.get("message"));
}
@@ -254,15 +263,14 @@ public class JcbtScholarshipApplicationServiceImpl implements IJcbtScholarshipAp
@Override
@Transactional(rollbackFor = Exception.class)
public Boolean batchSubmitApplicationsByTeacher(Long batchId, Long scholarshipTypeId, Long classId,
List<JcbtScholarshipApplicationBo> studentApplications) {
List<JcbtScholarshipApplicationBo> studentApplications) {
// 检查班级名额 - 使用和前端一致的查询方法
log.info("开始检查班级名额 - 批次ID: {}, 奖学金类型ID: {}, 班级ID: {}, 申请人数: {}",
batchId, scholarshipTypeId, classId, studentApplications.size());
// 使用和前端getScholarshipTypesWithQuota一致的查询方法
JcbtScholarshipQuotaVo classQuota = quotaService.selectClassQuota(classId, scholarshipTypeId, batchId);
log.info("班级名额查询结果: {}", classQuota != null ?
String.format("ID=%s, 总名额=%s, 已用=%s, 可用=%s, 状态=%s",
log.info("班级名额查询结果: {}", classQuota != null ? String.format("ID=%s, 总名额=%s, 已用=%s, 可用=%s, 状态=%s",
classQuota.getId(), classQuota.getTotalQuota(), classQuota.getUsedQuota(),
classQuota.getAvailableQuota(), classQuota.getStatus()) : "null");
@@ -306,7 +314,8 @@ public class JcbtScholarshipApplicationServiceImpl implements IJcbtScholarshipAp
if (classQuota != null) {
// 有班级名额分配,更新班级名额
log.info("更新班级名额使用情况 - ID: {}, 原已用: {}, 原可用: {}, 新增申请: {}",
classQuota.getId(), classQuota.getUsedQuota(), classQuota.getAvailableQuota(), studentApplications.size());
classQuota.getId(), classQuota.getUsedQuota(), classQuota.getAvailableQuota(),
studentApplications.size());
// 注意:这里需要调用全校名额表的更新方法,而不是班级名额表的方法
quotaService.updateQuotaUsage(classQuota.getId(), studentApplications.size());
@@ -334,6 +343,7 @@ public class JcbtScholarshipApplicationServiceImpl implements IJcbtScholarshipAp
* 查询班主任负责班级的申请记录
*/
@Override
@Transactional(rollbackFor = Exception.class)
public List<JcbtScholarshipApplicationVo> queryApplicationsByApplicant(Long applicantId, Long batchId) {
// TODO: 重新设计查询逻辑,因为applicantId字段已删除
// 可能需要通过班级ID或其他方式查询班主任负责的申请记录
@@ -344,6 +354,7 @@ public class JcbtScholarshipApplicationServiceImpl implements IJcbtScholarshipAp
* 查询班级的申请记录
*/
@Override
@Transactional(rollbackFor = Exception.class)
public List<JcbtScholarshipApplicationVo> queryApplicationsByClass(Long classId, Long batchId) {
return baseMapper.selectApplicationsByClass(classId, batchId);
}
@@ -352,6 +363,7 @@ public class JcbtScholarshipApplicationServiceImpl implements IJcbtScholarshipAp
* 查询待审核的申请记录
*/
@Override
@Transactional(rollbackFor = Exception.class)
public List<JcbtScholarshipApplicationVo> queryPendingApplications(Long reviewerId, String status) {
return baseMapper.selectPendingApplications(reviewerId, status);
}
@@ -360,6 +372,7 @@ public class JcbtScholarshipApplicationServiceImpl implements IJcbtScholarshipAp
* 检查学生申请资格和限制
*/
@Override
@Transactional(rollbackFor = Exception.class)
public Map<String, Object> checkStudentEligibility(Long studentId, Long batchId, Long scholarshipTypeId) {
Map<String, Object> result = new HashMap<>();
@@ -383,7 +396,7 @@ public class JcbtScholarshipApplicationServiceImpl implements IJcbtScholarshipAp
@Override
@Transactional(rollbackFor = Exception.class)
public Boolean batchReviewApplications(List<Long> applicationIds, String status, Long reviewerId,
String reviewerName, String reviewComment) {
String reviewerName, String reviewComment) {
return baseMapper.batchUpdateStatus(applicationIds, status, reviewerId, reviewerName, reviewComment) > 0;
}
@@ -429,6 +442,7 @@ public class JcbtScholarshipApplicationServiceImpl implements IJcbtScholarshipAp
* 获取申请统计数据
*/
@Override
@Transactional(rollbackFor = Exception.class)
public Map<String, Object> getApplicationStatistics(Long batchId, Long deptId) {
List<JcbtScholarshipApplicationVo> statistics = baseMapper.selectApplicationStatistics(batchId, deptId);
@@ -443,6 +457,7 @@ public class JcbtScholarshipApplicationServiceImpl implements IJcbtScholarshipAp
* 查询可申请的奖学金类型列表
*/
@Override
@Transactional(rollbackFor = Exception.class)
public List<Map<String, Object>> queryAvailableScholarshipTypes(Long classId, Long batchId) {
// 查询该班级在该批次的名额分配情况
List<JcbtScholarshipClassQuotaVo> quotas = classQuotaService.queryQuotasByClass(classId, batchId);
@@ -466,6 +481,7 @@ public class JcbtScholarshipApplicationServiceImpl implements IJcbtScholarshipAp
* 获取班级名额使用情况
*/
@Override
@Transactional(rollbackFor = Exception.class)
public Map<String, Object> getClassQuotaUsage(Long classId, Long batchId) {
List<JcbtScholarshipClassQuotaVo> quotas = classQuotaService.queryQuotasByClass(classId, batchId);
@@ -485,7 +501,7 @@ public class JcbtScholarshipApplicationServiceImpl implements IJcbtScholarshipAp
// ========== 班主任申请专用接口实现 ==========
/**
/**
* 根据班主任用户ID获取完整的班级信息
* 自包含方法,避免跨模块调用,直接使用SQL查询
*/
@@ -493,26 +509,26 @@ public class JcbtScholarshipApplicationServiceImpl implements IJcbtScholarshipAp
try {
// 使用自定义SQL一次性关联查询所有需要的信息
String sql = """
SELECT
cm.id as class_id,
cm.class_name,
cm.class_code,
cm.grade,
cm.college_id,
cm.college_name,
cm.major_id,
cm.major_name,
cm.class_teacher_id,
cm.class_teacher_name,
cm.current_student_count,
cm.class_status,
cm.class_type
FROM xg_class_msg cm
WHERE cm.class_teacher_id = ?
AND cm.deleted = 0
AND cm.class_status = '1'
ORDER BY cm.grade DESC, cm.class_name ASC
""";
SELECT
cm.id as class_id,
cm.class_name,
cm.class_code,
cm.grade,
cm.college_id,
cm.college_name,
cm.major_id,
cm.major_name,
cm.class_teacher_id,
cm.class_teacher_name,
cm.current_student_count,
cm.class_status,
cm.class_type
FROM xg_class_msg cm
WHERE cm.class_teacher_id = ?
AND cm.deleted = 0
AND cm.class_status = '1'
ORDER BY cm.grade DESC, cm.class_name ASC
""";
// 执行查询
List<Map<String, Object>> result = jdbcTemplate.queryForList(sql, teacherId);
@@ -530,6 +546,7 @@ public class JcbtScholarshipApplicationServiceImpl implements IJcbtScholarshipAp
* 重构后的获取班级信息方法 - 自包含,无跨模块依赖
*/
@Override
@Transactional(rollbackFor = Exception.class)
public Map<String, Object> getClassInfoByTeacher(Long userId) {
Map<String, Object> result = new HashMap<>();
@@ -582,8 +599,9 @@ public class JcbtScholarshipApplicationServiceImpl implements IJcbtScholarshipAp
/**
* 从Map构建班级结果信息
*/
private void buildClassResultFromMap(Map<String, Object> result, Long teacherId, String teacherName, Map<String, Object> classInfo) {
result.put("teacherId", teacherId.toString());
private void buildClassResultFromMap(Map<String, Object> result, Long teacherId, String teacherName,
Map<String, Object> classInfo) {
result.put("teacherId", teacherId.toString());
result.put("teacherName", teacherName);
result.put("classId", classInfo.get("class_id") != null ? classInfo.get("class_id").toString() : "");
result.put("className", (String) classInfo.get("class_name"));
@@ -613,36 +631,37 @@ public class JcbtScholarshipApplicationServiceImpl implements IJcbtScholarshipAp
return option;
}
/**
/**
* 确认选择班级(当用户从多个班级中选择一个时调用)
*/
@Override
@Transactional(rollbackFor = Exception.class)
public Map<String, Object> confirmClassSelection(Long teacherId, Long classId) {
Map<String, Object> result = new HashMap<>();
try {
// 验证该班级确实属于该老师 - 使用自包含查询
String sql = """
SELECT
cm.id as class_id,
cm.class_name,
cm.class_code,
cm.grade,
cm.college_id,
cm.college_name,
cm.major_id,
cm.major_name,
cm.class_teacher_id,
cm.class_teacher_name,
cm.current_student_count,
cm.class_status,
cm.class_type
FROM xg_class_msg cm
WHERE cm.class_teacher_id = ?
AND cm.id = ?
AND cm.deleted = 0
AND cm.class_status = '1'
""";
SELECT
cm.id as class_id,
cm.class_name,
cm.class_code,
cm.grade,
cm.college_id,
cm.college_name,
cm.major_id,
cm.major_name,
cm.class_teacher_id,
cm.class_teacher_name,
cm.current_student_count,
cm.class_status,
cm.class_type
FROM xg_class_msg cm
WHERE cm.class_teacher_id = ?
AND cm.id = ?
AND cm.deleted = 0
AND cm.class_status = '1'
""";
List<Map<String, Object>> classList = jdbcTemplate.queryForList(sql, teacherId, classId);
@@ -663,38 +682,39 @@ public class JcbtScholarshipApplicationServiceImpl implements IJcbtScholarshipAp
}
}
/**
/**
* 获取班级学生列表(用于勾选)- 使用自包含查询
*/
@Override
@Transactional(rollbackFor = Exception.class)
public List<Map<String, Object>> getClassStudents(Long classId) {
List<Map<String, Object>> students = new ArrayList<>();
try {
// 使用自包含查询获取学生列表,关联班级表获取学院和专业信息
String sql = """
SELECT
sm.id,
sm.student_no,
sm.name,
sm.gender,
sm.phone,
sm.email,
sm.student_status,
cm.college_id,
cm.college_name,
cm.major_id,
cm.major_name,
cm.class_name,
cm.grade
FROM xg_student_msg sm
LEFT JOIN xg_class_msg cm ON sm.class_id = cm.id
WHERE sm.class_id = ?
AND sm.deleted = 0
AND sm.student_status = '1'
AND (cm.deleted IS NULL OR cm.deleted = 0)
ORDER BY sm.student_no ASC
""";
SELECT
sm.id,
sm.student_no,
sm.name,
sm.gender,
sm.phone,
sm.email,
sm.student_status,
cm.college_id,
cm.college_name,
cm.major_id,
cm.major_name,
cm.class_name,
cm.grade
FROM xg_student_msg sm
LEFT JOIN xg_class_msg cm ON sm.class_id = cm.id
WHERE sm.class_id = ?
AND sm.deleted = 0
AND sm.student_status = '1'
AND (cm.deleted IS NULL OR cm.deleted = 0)
ORDER BY sm.student_no ASC
""";
List<Map<String, Object>> studentList = jdbcTemplate.queryForList(sql, classId);
@@ -702,7 +722,8 @@ public class JcbtScholarshipApplicationServiceImpl implements IJcbtScholarshipAp
for (Map<String, Object> student : studentList) {
Map<String, Object> studentMap = new HashMap<>();
studentMap.put("id", student.get("id"));
studentMap.put("studentCode", student.get("student_no") != null ? student.get("student_no").toString() : "");
studentMap.put("studentCode",
student.get("student_no") != null ? student.get("student_no").toString() : "");
studentMap.put("studentName", student.get("name") != null ? student.get("name").toString() : "");
// 性别转换:0-男,1-女
@@ -715,14 +736,20 @@ public class JcbtScholarshipApplicationServiceImpl implements IJcbtScholarshipAp
studentMap.put("phone", student.get("phone") != null ? student.get("phone").toString() : "");
studentMap.put("email", student.get("email") != null ? student.get("email").toString() : "");
studentMap.put("status", student.get("student_status") != null ? student.get("student_status").toString() : "1");
studentMap.put("status",
student.get("student_status") != null ? student.get("student_status").toString() : "1");
// 添加学院和专业信息
studentMap.put("collegeId", student.get("college_id") != null ? student.get("college_id").toString() : "");
studentMap.put("collegeName", student.get("college_name") != null ? student.get("college_name").toString() : "");
studentMap.put("majorId", student.get("major_id") != null ? student.get("major_id").toString() : "");
studentMap.put("majorName", student.get("major_name") != null ? student.get("major_name").toString() : "");
studentMap.put("className", student.get("class_name") != null ? student.get("class_name").toString() : "");
studentMap.put("collegeId",
student.get("college_id") != null ? student.get("college_id").toString() : "");
studentMap.put("collegeName",
student.get("college_name") != null ? student.get("college_name").toString() : "");
studentMap.put("majorId",
student.get("major_id") != null ? student.get("major_id").toString() : "");
studentMap.put("majorName",
student.get("major_name") != null ? student.get("major_name").toString() : "");
studentMap.put("className",
student.get("class_name") != null ? student.get("class_name").toString() : "");
studentMap.put("grade", student.get("grade") != null ? student.get("grade").toString() : "");
students.add(studentMap);
@@ -739,10 +766,11 @@ public class JcbtScholarshipApplicationServiceImpl implements IJcbtScholarshipAp
}
}
/**
/**
* 根据批次获取可申请的奖学金类型
*/
@Override
@Transactional(rollbackFor = Exception.class)
public List<Map<String, Object>> getScholarshipTypesByBatch(Long batchId) {
List<Map<String, Object>> scholarshipTypes = new ArrayList<>();
@@ -752,21 +780,24 @@ public class JcbtScholarshipApplicationServiceImpl implements IJcbtScholarshipAp
if (batchTypeIds != null && !batchTypeIds.isEmpty()) {
for (Long scholarshipTypeId : batchTypeIds) {
// 查询奖学金类型基本信息
JcbtScholarshipTypeVo typeInfo = scholarshipTypeService.queryById(scholarshipTypeId);
// 查询奖学金类型基本信息
JcbtScholarshipTypeVo typeInfo = scholarshipTypeService.queryById(scholarshipTypeId);
if (typeInfo != null && typeInfo.getStatus() == 1) { // 只返回启用的类型
Map<String, Object> scholarshipType = new HashMap<>();
scholarshipType.put("id", scholarshipTypeId);
scholarshipType.put("name", typeInfo.getTypeName());
scholarshipType.put("amount", typeInfo.getAwardAmount());
scholarshipType.put("description", typeInfo.getDescription());
scholarshipType.put("typeCategory", typeInfo.getTypeCategory());
scholarshipType.put("levelType", typeInfo.getLevelType());
Map<String, Object> scholarshipType = new HashMap<>();
scholarshipType.put("id", scholarshipTypeId);
scholarshipType.put("name", typeInfo.getTypeName());
scholarshipType.put("amount", typeInfo.getAwardAmount());
scholarshipType.put("description", typeInfo.getDescription());
scholarshipType.put("typeCategory", typeInfo.getTypeCategory());
scholarshipType.put("levelType", typeInfo.getLevelType());
// 查询该类型在该批次下的名额统计信息
List<JcbtScholarshipQuotaVo> quotaList = quotaService.queryListByBatchAndType(batchId, scholarshipTypeId);
int totalQuota = quotaList.stream().mapToInt(q -> q.getTotalQuota() != null ? q.getTotalQuota() : 0).sum();
int usedQuota = quotaList.stream().mapToInt(q -> q.getUsedQuota() != null ? q.getUsedQuota() : 0).sum();
List<JcbtScholarshipQuotaVo> quotaList = quotaService.queryListByBatchAndType(batchId,
scholarshipTypeId);
int totalQuota = quotaList.stream()
.mapToInt(q -> q.getTotalQuota() != null ? q.getTotalQuota() : 0).sum();
int usedQuota = quotaList.stream()
.mapToInt(q -> q.getUsedQuota() != null ? q.getUsedQuota() : 0).sum();
int availableQuota = totalQuota - usedQuota;
scholarshipType.put("totalQuota", totalQuota);
@@ -805,6 +836,7 @@ public class JcbtScholarshipApplicationServiceImpl implements IJcbtScholarshipAp
* 根据批次和班级获取带名额信息的奖学金类型(班主任专用)
*/
@Override
@Transactional(rollbackFor = Exception.class)
public List<Map<String, Object>> getScholarshipTypesWithQuota(Long batchId, Long classId) {
List<Map<String, Object>> scholarshipTypes = new ArrayList<>();
@@ -822,8 +854,7 @@ public class JcbtScholarshipApplicationServiceImpl implements IJcbtScholarshipAp
// 查询奖学金类型基本信息
JcbtScholarshipTypeVo typeInfo = scholarshipTypeService.queryById(scholarshipTypeId);
log.info("奖学金类型基本信息: {}", typeInfo != null ?
String.format("ID=%s, 名称=%s, 状态=%s, 金额=%s, 等级=%s",
log.info("奖学金类型基本信息: {}", typeInfo != null ? String.format("ID=%s, 名称=%s, 状态=%s, 金额=%s, 等级=%s",
typeInfo.getId(), typeInfo.getTypeName(), typeInfo.getStatus(),
typeInfo.getAwardAmount(), typeInfo.getLevelType()) : "null");
@@ -837,14 +868,18 @@ public class JcbtScholarshipApplicationServiceImpl implements IJcbtScholarshipAp
scholarshipType.put("levelType", typeInfo.getLevelType());
// 查询该班级在该奖学金类型下的名额分配信息(从jcbt_scholarship_quota表查询)
log.info("开始查询班级名额 - SQL参数: classId={}, scholarshipTypeId={}, batchId={}", classId, scholarshipTypeId, batchId);
log.info("执行SQL: SELECT * FROM jcbt_scholarship_quota WHERE allocation_level = 'CLASS' AND target_dept_id = {} AND scholarship_type_id = {} AND batch_id = {} AND status = 'ACTIVE'", classId, scholarshipTypeId, batchId);
log.info("开始查询班级名额 - SQL参数: classId={}, scholarshipTypeId={}, batchId={}", classId,
scholarshipTypeId, batchId);
log.info(
"执行SQL: SELECT * FROM jcbt_scholarship_quota WHERE allocation_level = 'CLASS' AND target_dept_id = {} AND scholarship_type_id = {} AND batch_id = {} AND status = 'ACTIVE'",
classId, scholarshipTypeId, batchId);
JcbtScholarshipQuotaVo classQuota = quotaService.selectClassQuota(classId, scholarshipTypeId, batchId);
log.info("班级名额查询结果: {}", classQuota != null ?
String.format("ID=%s, 总名额=%s, 已用=%s, 可用=%s, 状态=%s",
classQuota.getId(), classQuota.getTotalQuota(), classQuota.getUsedQuota(),
classQuota.getAvailableQuota(), classQuota.getStatus()) : "null");
JcbtScholarshipQuotaVo classQuota = quotaService.selectClassQuota(classId, scholarshipTypeId,
batchId);
log.info("班级名额查询结果: {}",
classQuota != null ? String.format("ID=%s, 总名额=%s, 已用=%s, 可用=%s, 状态=%s",
classQuota.getId(), classQuota.getTotalQuota(), classQuota.getUsedQuota(),
classQuota.getAvailableQuota(), classQuota.getStatus()) : "null");
if (classQuota != null) {
// 有班级名额分配
@@ -852,7 +887,8 @@ public class JcbtScholarshipApplicationServiceImpl implements IJcbtScholarshipAp
scholarshipType.put("hasQuota", true);
int totalQuota = classQuota.getTotalQuota() != null ? classQuota.getTotalQuota() : 0;
int usedQuota = classQuota.getUsedQuota() != null ? classQuota.getUsedQuota() : 0;
int availableQuota = classQuota.getAvailableQuota() != null ? classQuota.getAvailableQuota() : Math.max(0, totalQuota - usedQuota);
int availableQuota = classQuota.getAvailableQuota() != null ? classQuota.getAvailableQuota()
: Math.max(0, totalQuota - usedQuota);
scholarshipType.put("totalQuota", totalQuota);
scholarshipType.put("usedQuota", usedQuota);
@@ -860,44 +896,49 @@ public class JcbtScholarshipApplicationServiceImpl implements IJcbtScholarshipAp
scholarshipType.put("quotaStatus", availableQuota > 0 ? "available" : "full");
log.info("班级名额处理结果 - 类型: {}, 总名额: {}, 已用: {}, 可用: {}, 状态: {}",
typeInfo.getTypeName(), totalQuota, usedQuota, availableQuota, availableQuota > 0 ? "available" : "full");
typeInfo.getTypeName(), totalQuota, usedQuota, availableQuota,
availableQuota > 0 ? "available" : "full");
} else {
// 没有班级名额分配,查询全校统计信息
log.info("未找到班级名额分配,开始查询全校名额");
log.info("执行全校名额查询SQL - 参数: batchId={}, scholarshipTypeId={}", batchId, scholarshipTypeId);
List<JcbtScholarshipQuotaVo> quotaList = quotaService.queryListByBatchAndType(batchId, scholarshipTypeId);
List<JcbtScholarshipQuotaVo> quotaList = quotaService.queryListByBatchAndType(batchId,
scholarshipTypeId);
log.info("全校名额查询结果数量: {}", quotaList != null ? quotaList.size() : 0);
if (quotaList != null && !quotaList.isEmpty()) {
for (int i = 0; i < quotaList.size(); i++) {
JcbtScholarshipQuotaVo quota = quotaList.get(i);
log.info("全校名额[{}]: ID={}, 分配级别={}, 目标部门={}, 总名额={}, 已用={}, 可用={}",
i, quota.getId(), quota.getAllocationLevel(), quota.getTargetDeptName(),
quota.getTotalQuota(), quota.getUsedQuota(), quota.getAvailableQuota());
i, quota.getId(), quota.getAllocationLevel(), quota.getTargetDeptName(),
quota.getTotalQuota(), quota.getUsedQuota(), quota.getAvailableQuota());
}
}
int totalQuota = quotaList.stream().mapToInt(q -> q.getTotalQuota() != null ? q.getTotalQuota() : 0).sum();
int usedQuota = quotaList.stream().mapToInt(q -> q.getUsedQuota() != null ? q.getUsedQuota() : 0).sum();
int totalQuota = quotaList.stream()
.mapToInt(q -> q.getTotalQuota() != null ? q.getTotalQuota() : 0).sum();
int usedQuota = quotaList.stream()
.mapToInt(q -> q.getUsedQuota() != null ? q.getUsedQuota() : 0).sum();
int availableQuota = Math.max(0, totalQuota - usedQuota);
scholarshipType.put("hasQuota", false);
scholarshipType.put("totalQuota", totalQuota);
scholarshipType.put("usedQuota", usedQuota);
scholarshipType.put("availableQuota", availableQuota);
scholarshipType.put("quotaStatus", totalQuota > 0 ? (availableQuota > 0 ? "available" : "full") : "unlimited");
scholarshipType.put("quotaStatus",
totalQuota > 0 ? (availableQuota > 0 ? "available" : "full") : "unlimited");
log.info("全校名额统计结果 - 类型: {} (全校), 总名额: {}, 已用: {}, 可用: {}, 状态: {}",
typeInfo.getTypeName(), totalQuota, usedQuota, availableQuota,
totalQuota > 0 ? (availableQuota > 0 ? "available" : "full") : "unlimited");
typeInfo.getTypeName(), totalQuota, usedQuota, availableQuota,
totalQuota > 0 ? (availableQuota > 0 ? "available" : "full") : "unlimited");
}
scholarshipTypes.add(scholarshipType);
log.info("奖学金类型 {} 处理完成,添加到结果列表", typeInfo.getTypeName());
} else {
log.warn("奖学金类型被跳过 - ID: {}, 原因: {}", scholarshipTypeId,
typeInfo == null ? "类型信息不存在" : "状态未启用(status=" + typeInfo.getStatus() + ")");
typeInfo == null ? "类型信息不存在" : "状态未启用(status=" + typeInfo.getStatus() + ")");
}
}
@@ -928,7 +969,8 @@ public class JcbtScholarshipApplicationServiceImpl implements IJcbtScholarshipAp
for (int i = 0; i < scholarshipTypes.size(); i++) {
Map<String, Object> type = scholarshipTypes.get(i);
log.info("结果[{}]: 名称={}, 状态={}, 总名额={}, 可用名额={}",
i, type.get("name"), type.get("quotaStatus"), type.get("totalQuota"), type.get("availableQuota"));
i, type.get("name"), type.get("quotaStatus"), type.get("totalQuota"),
type.get("availableQuota"));
}
} else {
log.warn("批次 {} 未关联任何奖学金类型", batchId);
@@ -948,6 +990,7 @@ public class JcbtScholarshipApplicationServiceImpl implements IJcbtScholarshipAp
* 测试班级名额查询(用于SQL日志调试)
*/
@Override
@Transactional(rollbackFor = Exception.class)
public Map<String, Object> testClassQuotaQuery(Long classId, Long scholarshipTypeId, Long batchId) {
Map<String, Object> result = new HashMap<>();
@@ -960,7 +1003,8 @@ public class JcbtScholarshipApplicationServiceImpl implements IJcbtScholarshipAp
// 执行查询
log.info("💾 执行班级名额查询...");
JcbtScholarshipClassQuotaVo classQuota = classQuotaService.queryAvailableQuota(classId, scholarshipTypeId, batchId);
JcbtScholarshipClassQuotaVo classQuota = classQuotaService.queryAvailableQuota(classId, scholarshipTypeId,
batchId);
// 记录查询结束时间
long endTime = System.currentTimeMillis();
@@ -971,23 +1015,24 @@ public class JcbtScholarshipApplicationServiceImpl implements IJcbtScholarshipAp
if (classQuota != null) {
log.info("✅ 查询成功,找到班级名额记录");
log.info("📊 名额详情: ID={}, 批次ID={}, 奖学金类型ID={}, 班级ID={}",
classQuota.getId(), classQuota.getBatchId(), classQuota.getScholarshipTypeId(), classQuota.getClassId());
classQuota.getId(), classQuota.getBatchId(), classQuota.getScholarshipTypeId(),
classQuota.getClassId());
log.info("📈 名额数据: 总名额={}, 已用名额={}, 可用名额={}, 状态={}",
classQuota.getTotalQuota(), classQuota.getUsedQuota(), classQuota.getAvailableQuota(), classQuota.getStatus());
classQuota.getTotalQuota(), classQuota.getUsedQuota(), classQuota.getAvailableQuota(),
classQuota.getStatus());
result.put("found", true);
result.put("data", Map.of(
"id", classQuota.getId(),
"batchId", classQuota.getBatchId(),
"scholarshipTypeId", classQuota.getScholarshipTypeId(),
"classId", classQuota.getClassId(),
"totalQuota", classQuota.getTotalQuota(),
"usedQuota", classQuota.getUsedQuota(),
"availableQuota", classQuota.getAvailableQuota(),
"status", classQuota.getStatus(),
"createTime", classQuota.getCreateTime(),
"updateTime", classQuota.getUpdateTime()
));
"id", classQuota.getId(),
"batchId", classQuota.getBatchId(),
"scholarshipTypeId", classQuota.getScholarshipTypeId(),
"classId", classQuota.getClassId(),
"totalQuota", classQuota.getTotalQuota(),
"usedQuota", classQuota.getUsedQuota(),
"availableQuota", classQuota.getAvailableQuota(),
"status", classQuota.getStatus(),
"createTime", classQuota.getCreateTime(),
"updateTime", classQuota.getUpdateTime()));
} else {
log.warn("⚠️ 未找到班级名额记录");
log.info("🔍 可能原因:");
@@ -1033,6 +1078,7 @@ public class JcbtScholarshipApplicationServiceImpl implements IJcbtScholarshipAp
* 测试全校名额查询(用于SQL日志调试)
*/
@Override
@Transactional(rollbackFor = Exception.class)
public Map<String, Object> testSchoolQuotaQuery(Long batchId, Long scholarshipTypeId) {
Map<String, Object> result = new HashMap<>();
@@ -1063,9 +1109,11 @@ public class JcbtScholarshipApplicationServiceImpl implements IJcbtScholarshipAp
for (int i = 0; i < quotaList.size(); i++) {
JcbtScholarshipQuotaVo quota = quotaList.get(i);
log.info("📈 记录[{}]: ID={}, 分配级别={}, 目标部门ID={}, 目标部门={}",
i, quota.getId(), quota.getAllocationLevel(), quota.getTargetDeptId(), quota.getTargetDeptName());
i, quota.getId(), quota.getAllocationLevel(), quota.getTargetDeptId(),
quota.getTargetDeptName());
log.info("📊 名额[{}]: 总名额={}, 已用={}, 预留={}, 可用={}, 状态={}",
i, quota.getTotalQuota(), quota.getUsedQuota(), quota.getReservedQuota(), quota.getAvailableQuota(), quota.getStatus());
i, quota.getTotalQuota(), quota.getUsedQuota(), quota.getReservedQuota(),
quota.getAvailableQuota(), quota.getStatus());
Map<String, Object> quotaDetail = new HashMap<>();
quotaDetail.put("id", quota.getId());
@@ -1099,11 +1147,10 @@ public class JcbtScholarshipApplicationServiceImpl implements IJcbtScholarshipAp
result.put("count", quotaList.size());
result.put("details", quotaDetails);
result.put("summary", Map.of(
"totalQuota", totalQuota,
"usedQuota", usedQuota,
"availableQuota", availableQuota,
"calculatedAvailable", Math.max(0, totalQuota - usedQuota)
));
"totalQuota", totalQuota,
"usedQuota", usedQuota,
"availableQuota", availableQuota,
"calculatedAvailable", Math.max(0, totalQuota - usedQuota)));
} else {
log.warn("⚠️ 未找到全校名额记录");
+9 -2
View File
@@ -1,7 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>org.dromara</groupId>
<artifactId>ruoyi-modules</artifactId>
@@ -100,6 +99,14 @@
<artifactId>ruoyi-common-sse</artifactId>
</dependency>
<!-- HTTP客户端依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
</dependencies>
</project>
@@ -21,6 +21,9 @@ import org.dromara.system.domain.vo.SysRegionVo;
import org.dromara.system.domain.bo.SysRegionBo;
import org.dromara.system.service.ISysRegionService;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.system.domain.bo.GeocodingRequestBo;
import org.dromara.system.domain.vo.GeocodingResponseVo;
import org.dromara.system.service.IAmapService;
/**
* 行政区划
@@ -35,6 +38,7 @@ import org.dromara.common.mybatis.core.page.TableDataInfo;
public class SysRegionController extends BaseController {
private final ISysRegionService sysRegionService;
private final IAmapService amapService;
/**
* 查询行政区划列表
@@ -110,4 +114,17 @@ public class SysRegionController extends BaseController {
List<SysRegionVo> tree = sysRegionService.getRegionTree();
return R.ok(tree);
}
/**
* 逆地理编码
*
* @param request 请求参数
* @return 逆地理编码结果
*/
@SaCheckPermission("system:SysRegion:geocode")
@PostMapping("/reverse-geocode")
public R<GeocodingResponseVo> reverseGeocode(@Validated @RequestBody GeocodingRequestBo request) {
GeocodingResponseVo result = amapService.reverseGeocode(request);
return R.ok(result);
}
}
@@ -0,0 +1,47 @@
package org.dromara.system.domain.bo;
import lombok.Data;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.DecimalMin;
import jakarta.validation.constraints.DecimalMax;
/**
* 逆地理编码请求参数
*
* @author zlwu
* @date 2025-01-03
*/
@Data
public class GeocodingRequestBo {
/**
* 经度
*/
@NotNull(message = "经度不能为空")
@DecimalMin(value = "-180.0", message = "经度范围必须在-180到180之间")
@DecimalMax(value = "180.0", message = "经度范围必须在-180到180之间")
private Double longitude;
/**
* 纬度
*/
@NotNull(message = "纬度不能为空")
@DecimalMin(value = "-90.0", message = "纬度范围必须在-90到90之间")
@DecimalMax(value = "90.0", message = "纬度范围必须在-90到90之间")
private Double latitude;
/**
* 返回格式,默认json
*/
private String output = "json";
/**
* 批量查询控制,默认1
*/
private Integer batch = 1;
/**
* 道路等级,默认0
*/
private Integer roadlevel = 0;
}
@@ -0,0 +1,268 @@
package org.dromara.system.domain.vo;
import lombok.Data;
import com.fasterxml.jackson.annotation.JsonFormat;
import java.util.Date;
/**
* 逆地理编码响应结果
*
* @author zlwu
* @date 2025-01-03
*/
@Data
public class GeocodingResponseVo {
/**
* 状态码
*/
private String status;
/**
* 状态信息
*/
private String info;
/**
* 信息码
*/
private String infocode;
/**
* 逆地理编码结果
*/
private Regeocode regeocode;
/**
* 创建者
*/
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;
/**
* 逆地理编码结果详情
*/
@Data
public static class Regeocode {
/**
* 地址信息
*/
private String formattedAddress;
/**
* 地址组件
*/
private AddressComponent addressComponent;
/**
* 兴趣点信息
*/
private Poi[] pois;
/**
* 道路信息
*/
private Road[] roads;
/**
* 道路交叉口信息
*/
private RoadIntersection[] roadIntersections;
/**
* 兴趣区域信息
*/
private Aoi[] aois;
}
/**
* 地址组件
*/
@Data
public static class AddressComponent {
/**
* 国家
*/
private String country;
/**
* 省份
*/
private String province;
/**
* 城市
*/
private String city;
/**
* 区县
*/
private String district;
/**
* 乡镇
*/
private String township;
/**
* 街道
*/
private String street;
/**
* 门牌号
*/
private String number;
/**
* 行政区划代码
*/
private String adcode;
/**
* 城市编码
*/
private String citycode;
}
/**
* 兴趣点信息
*/
@Data
public static class Poi {
/**
* 兴趣点ID
*/
private String id;
/**
* 兴趣点名称
*/
private String name;
/**
* 兴趣点类型
*/
private String type;
/**
* 兴趣点地址
*/
private String address;
/**
* 兴趣点距离
*/
private String distance;
/**
* 兴趣点位置
*/
private String location;
}
/**
* 道路信息
*/
@Data
public static class Road {
/**
* 道路ID
*/
private String id;
/**
* 道路名称
*/
private String name;
/**
* 道路距离
*/
private String distance;
/**
* 道路方向
*/
private String direction;
/**
* 道路位置
*/
private String location;
}
/**
* 道路交叉口信息
*/
@Data
public static class RoadIntersection {
/**
* 交叉口ID
*/
private String id;
/**
* 交叉口名称
*/
private String name;
/**
* 交叉口距离
*/
private String distance;
/**
* 交叉口位置
*/
private String location;
}
/**
* 兴趣区域信息
*/
@Data
public static class Aoi {
/**
* 兴趣区域ID
*/
private String id;
/**
* 兴趣区域名称
*/
private String name;
/**
* 兴趣区域面积
*/
private String area;
/**
* 兴趣区域距离
*/
private String distance;
/**
* 兴趣区域类型
*/
private String type;
}
}
@@ -0,0 +1,21 @@
package org.dromara.system.service;
import org.dromara.system.domain.bo.GeocodingRequestBo;
import org.dromara.system.domain.vo.GeocodingResponseVo;
/**
* 高德地图服务接口
*
* @author zlwu
* @date 2025-01-03
*/
public interface IAmapService {
/**
* 逆地理编码
*
* @param request 请求参数
* @return 逆地理编码结果
*/
GeocodingResponseVo reverseGeocode(GeocodingRequestBo request);
}
@@ -0,0 +1,80 @@
package org.dromara.system.service.impl;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.dromara.system.domain.bo.GeocodingRequestBo;
import org.dromara.system.domain.vo.GeocodingResponseVo;
import org.dromara.system.service.IAmapService;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import cn.hutool.http.HttpUtil;
/**
* 高德地图服务实现类
*
* @author zlwu
* @date 2025-01-03
*/
@Slf4j
@RequiredArgsConstructor
@Service
public class AmapServiceImpl implements IAmapService {
@Value("${amap.key:}")
private String amapKey;
@Value("${amap.url:https://restapi.amap.com}")
private String amapUrl;
@Override
public GeocodingResponseVo reverseGeocode(GeocodingRequestBo request) {
try {
// 构建请求URL
String url = buildGeocodeUrl(request);
log.info("高德地图逆地理编码请求URL: {}", url);
// 发送HTTP请求
String response = HttpUtil.get(url);
log.info("高德地图逆地理编码响应: {}", response);
if (StrUtil.isBlank(response)) {
throw new RuntimeException("高德地图API返回空响应");
}
// 解析JSON响应
GeocodingResponseVo result = JSONUtil.toBean(response, GeocodingResponseVo.class);
// 检查API响应状态
if (!"1".equals(result.getStatus())) {
log.error("高德地图API返回错误: status={}, info={}", result.getStatus(), result.getInfo());
throw new RuntimeException("高德地图API返回错误: " + result.getInfo());
}
return result;
} catch (Exception e) {
log.error("高德地图逆地理编码失败", e);
throw new RuntimeException("逆地理编码失败: " + e.getMessage());
}
}
/**
* 构建逆地理编码请求URL
*
* @param request 请求参数
* @return 完整的请求URL
*/
private String buildGeocodeUrl(GeocodingRequestBo request) {
StringBuilder urlBuilder = new StringBuilder(amapUrl);
urlBuilder.append("/v3/geocode/regeo");
urlBuilder.append("?key=").append(amapKey);
urlBuilder.append("&location=").append(request.getLongitude()).append(",").append(request.getLatitude());
urlBuilder.append("&output=").append(request.getOutput());
urlBuilder.append("&batch=").append(request.getBatch());
urlBuilder.append("&roadlevel=").append(request.getRoadlevel());
return urlBuilder.toString();
}
}
@@ -21,6 +21,7 @@ import org.dromara.xg.domain.vo.XgClassMsgVo;
import org.dromara.xg.domain.bo.XgClassMsgBo;
import org.dromara.xg.service.IXgClassMsgService;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.satoken.utils.LoginHelper;
/**
* 班级信息-新版
@@ -63,8 +64,7 @@ public class XgClassMsgController extends BaseController {
*/
@SaCheckPermission("classMsg:classMsg:query")
@GetMapping("/{id}")
public R<XgClassMsgVo> getInfo(@NotNull(message = "主键不能为空")
@PathVariable Long id) {
public R<XgClassMsgVo> getInfo(@NotNull(message = "主键不能为空") @PathVariable Long id) {
return R.ok(xgClassMsgService.queryById(id));
}
@@ -98,8 +98,22 @@ public class XgClassMsgController extends BaseController {
@SaCheckPermission("classMsg:classMsg:remove")
@Log(title = "班级信息-新版", businessType = BusinessType.DELETE)
@DeleteMapping("/{ids}")
public R<Void> remove(@NotEmpty(message = "主键不能为空")
@PathVariable Long[] ids) {
public R<Void> remove(@NotEmpty(message = "主键不能为空") @PathVariable Long[] ids) {
return toAjax(xgClassMsgService.deleteWithValidByIds(List.of(ids), true));
}
/**
* 获取当前登录人作为班主任所管理的班级列表
*/
@SaCheckPermission("classMsg:classMsg:list")
@GetMapping("/myClassListAsTeacher")
public R<List<XgClassMsgVo>> myClassListAsTeacher() {
Long userId = LoginHelper.getUserId();
XgClassMsgBo bo = new XgClassMsgBo();
bo.setClassTeacherId(userId);
// 仅查询正常状态班级(1-正常)
bo.setClassStatus("1");
List<XgClassMsgVo> list = xgClassMsgService.queryList(bo);
return R.ok(list);
}
}
@@ -114,6 +114,19 @@ public class XgDormBedController extends BaseController {
return R.ok(list);
}
/**
* 查询当前用户所在学院的指定房间床位详细信息列表(包含学生信息)
*
* @param roomId 房间ID
*/
@SaCheckPermission("dormbed:dormBed:query")
@GetMapping("/details/college/room/{roomId}")
public R<List<XgDormBedDetailVo>> getBedDetailsByRoomIdForCurrentUserCollege(
@NotNull(message = "房间ID不能为空") @PathVariable Long roomId) {
List<XgDormBedDetailVo> list = xgDormBedService.queryBedDetailsByRoomIdForCurrentUserCollege(roomId);
return R.ok(list);
}
/**
* 查询指定宿舍楼的床位详细信息列表(包含学生信息)
*
@@ -126,4 +139,19 @@ public class XgDormBedController extends BaseController {
List<XgDormBedDetailVo> list = xgDormBedService.queryBedDetailsByBuildingId(buildingId);
return R.ok(list);
}
/**
* 查询指定房间中属于指定班级的床位详细信息列表(包含学生信息)
*
* @param roomId 房间ID
* @param classId 班级ID
*/
@SaCheckPermission("dormbed:dormBed:query")
@GetMapping("/details/room/{roomId}/class/{classId}")
public R<List<XgDormBedDetailVo>> getBedDetailsByRoomIdAndClassId(
@NotNull(message = "房间ID不能为空") @PathVariable Long roomId,
@NotNull(message = "班级ID不能为空") @PathVariable Long classId) {
List<XgDormBedDetailVo> list = xgDormBedService.queryBedDetailsByRoomIdAndClassId(roomId, classId);
return R.ok(list);
}
}
@@ -20,8 +20,12 @@ import org.dromara.common.excel.utils.ExcelUtil;
import org.dromara.xg.domain.vo.XgDormBedStudentVo;
import org.dromara.xg.domain.bo.XgDormBedStudentBo;
import org.dromara.xg.domain.bo.XgDormBedBatchAllocateBo;
import org.dromara.xg.domain.bo.XgDormBedBatchAllocateToClassBo;
import org.dromara.xg.service.IXgDormBedStudentService;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.xg.domain.bo.XgDormBedBatchRecallBo;
import org.dromara.xg.domain.vo.DormBuildingTreeVo;
import org.dromara.xg.domain.bo.XgDormSelectiveAllocationBo;
/**
* 床位学生分配关系
@@ -115,4 +119,217 @@ public class XgDormBedStudentController extends BaseController {
return toAjax(xgDormBedStudentService.batchAllocateBedsToCollege(bo));
}
/**
* 批量分配床位给班级
*
* @param bo 批量分配给班级参数
*/
@SaCheckPermission("dormBedStudent:dormBedStudent:add")
@Log(title = "批量分配床位给班级", businessType = BusinessType.INSERT)
@RepeatSubmit()
@PostMapping("/batchAllocateToClass")
public R<Void> batchAllocateBedsToClass(
@Validated(AddGroup.class) @RequestBody XgDormBedBatchAllocateToClassBo bo) {
return toAjax(xgDormBedStudentService.batchAllocateBedsToClass(bo));
}
/**
* 批量收回宿舍床位
*/
@SaCheckPermission("dormBedStudent:dormBedStudent:edit")
@Log(title = "批量收回宿舍床位", businessType = BusinessType.UPDATE)
@RepeatSubmit()
@PostMapping("/batchRecall")
public R<Void> batchRecallBeds(@Validated(AddGroup.class) @RequestBody XgDormBedBatchRecallBo bo) {
return toAjax(xgDormBedStudentService.batchRecallBeds(bo));
}
/**
* 批量回收班级分配床位(保留学院分配)
*/
@SaCheckPermission("dormBedStudent:dormBedStudent:edit")
@Log(title = "批量回收班级分配床位", businessType = BusinessType.UPDATE)
@RepeatSubmit()
@PostMapping("/batchRecallClassAllocation")
public R<Void> batchRecallClassAllocation(@Validated(AddGroup.class) @RequestBody XgDormBedBatchRecallBo bo) {
return toAjax(xgDormBedStudentService.batchRecallClassAllocation(bo));
}
/**
* 获取当前用户二级学院的宿舍楼树形结构
* 校区-宿舍区-宿舍楼三级结构,校区和宿舍区不可选,只有宿舍楼可以选择
*/
@SaCheckPermission("dormBedStudent:dormBedStudent:list")
@GetMapping("/currentUserCollegeDormTree")
public R<List<DormBuildingTreeVo>> getCurrentUserCollegeDormBuildingTree() {
List<DormBuildingTreeVo> treeData = xgDormBedStudentService.getCurrentUserCollegeDormBuildingTree();
return R.ok(treeData);
}
/**
* 获取班主任管理的班级宿舍楼树形结构
* 只显示班主任管理班级分配到的宿舍楼
*/
@SaCheckPermission("dormBedStudent:dormBedStudent:list")
@GetMapping("/getClassTeacherDormTree")
public R<List<DormBuildingTreeVo>> getClassTeacherDormTree(@RequestParam(required = false) Long classId) {
List<DormBuildingTreeVo> treeData = xgDormBedStudentService.getClassTeacherDormTree(classId);
return R.ok(treeData);
}
/**
* 获取班主任管理班级的房间床位详情(带学生信息)
*/
@SaCheckPermission("dormBedStudent:dormBedStudent:list")
@GetMapping("/getClassTeacherBedDetails")
public R<List<Object>> getClassTeacherBedDetails(@RequestParam(required = false) Long buildingId,
@RequestParam(required = false) Long classId) {
List<Object> bedDetails = xgDormBedStudentService.getClassTeacherBedDetails(buildingId, classId);
return R.ok(bedDetails);
}
/**
* 获取班主任管理的未分配床位学生列表
*/
@SaCheckPermission("dormBedStudent:dormBedStudent:list")
@GetMapping("/getClassTeacherUnallocatedStudents")
public R<List<Object>> getClassTeacherUnallocatedStudents(@RequestParam(required = false) Long classId) {
List<Object> students = xgDormBedStudentService.getClassTeacherUnallocatedStudents(classId);
return R.ok(students);
}
/**
* 班主任一键随机分配床位
*/
@SaCheckPermission("dormBedStudent:dormBedStudent:add")
@Log(title = "班主任随机分配床位", businessType = BusinessType.INSERT)
@RepeatSubmit()
@PostMapping("/classTeacherRandomAllocation")
public R<Void> classTeacherRandomAllocation(@RequestParam(required = false) Long buildingId,
@RequestParam(required = false) Long classId) {
return toAjax(xgDormBedStudentService.classTeacherRandomAllocation(buildingId, classId));
}
/**
* 班主任一键按学号分配床位
*/
@SaCheckPermission("dormBedStudent:dormBedStudent:add")
@Log(title = "班主任按学号分配床位", businessType = BusinessType.INSERT)
@RepeatSubmit()
@PostMapping("/classTeacherStudentNoAllocation")
public R<Void> classTeacherStudentNoAllocation(@RequestParam(required = false) Long buildingId,
@RequestParam(required = false) Long classId) {
return toAjax(xgDormBedStudentService.classTeacherStudentNoAllocation(buildingId, classId));
}
/**
* 班主任选择性分配床位(弹窗模式)
*/
@SaCheckPermission("dormBedStudent:dormBedStudent:add")
@Log(title = "班主任选择性分配床位", businessType = BusinessType.INSERT)
@RepeatSubmit()
@PostMapping("/classTeacherSelectiveAllocation")
public R<Void> classTeacherSelectiveAllocation(@Validated @RequestBody XgDormSelectiveAllocationBo allocationParams,
@RequestParam(required = false) Long classId) {
return toAjax(xgDormBedStudentService.classTeacherSelectiveAllocation(allocationParams, classId));
}
/**
* 班主任一键收回床位
*/
@SaCheckPermission("dormBedStudent:dormBedStudent:edit")
@Log(title = "班主任收回床位", businessType = BusinessType.UPDATE)
@RepeatSubmit()
@PostMapping("/classTeacherRecallBeds")
public R<Void> classTeacherRecallBeds(@RequestParam(required = false) Long buildingId,
@RequestParam(required = false) Long classId) {
return toAjax(xgDormBedStudentService.classTeacherRecallBeds(buildingId, classId));
}
/**
* 班主任收回选中床位
*/
@SaCheckPermission("dormBedStudent:dormBedStudent:edit")
@Log(title = "班主任收回选中床位", businessType = BusinessType.UPDATE)
@RepeatSubmit()
@PostMapping("/classTeacherRecallSelectedBeds")
public R<Void> classTeacherRecallSelectedBeds(@RequestBody List<Long> bedIds,
@RequestParam(required = false) Long classId) {
return toAjax(xgDormBedStudentService.classTeacherRecallSelectedBeds(bedIds, classId));
}
/**
* 班主任批量退宿
*/
@SaCheckPermission("dormBedStudent:dormBedStudent:edit")
@Log(title = "班主任批量退宿", businessType = BusinessType.UPDATE)
@RepeatSubmit()
@PostMapping("/classTeacherStayawaySelectedBeds")
public R<Void> classTeacherStayawaySelectedBeds(@RequestBody List<Long> bedIds,
@RequestParam(required = false) Long classId) {
return toAjax(xgDormBedStudentService.classTeacherStayawaySelectedBeds(bedIds, classId));
}
/**
* 班主任床位互换
* 将两个学生的床位进行互换
*/
@SaCheckPermission("dormBedStudent:dormBedStudent:edit")
@Log(title = "班主任床位互换", businessType = BusinessType.UPDATE)
@RepeatSubmit()
@PostMapping("/classTeacherExchangeBeds")
public R<Void> classTeacherExchangeBeds(@RequestParam Long sourceStudentId,
@RequestParam Long targetStudentId,
@RequestParam(required = false) Long classId) {
return toAjax(xgDormBedStudentService.classTeacherExchangeBeds(sourceStudentId, targetStudentId, classId));
}
/**
* 班主任床位移动
* 将学生从当前床位移动到指定的空闲床位
*/
@SaCheckPermission("dormBedStudent:dormBedStudent:edit")
@Log(title = "班主任床位移动", businessType = BusinessType.UPDATE)
@RepeatSubmit()
@PostMapping("/classTeacherMoveBed")
public R<Void> classTeacherMoveBed(@RequestParam Long sourceStudentId,
@RequestParam Long targetBedId,
@RequestParam(required = false) Long classId) {
return toAjax(xgDormBedStudentService.classTeacherMoveBed(sourceStudentId, targetBedId, classId));
}
/**
* 获取班级所有已入住宿舍的学生床位信息
* 包含床位信息(校区名称、宿舍区名称、楼栋名称、房间名称、床位名称)
* 和学生信息(学生姓名、学号、性别)
*/
@SaCheckPermission("dormBedStudent:dormBedStudent:list")
@GetMapping("/getClassOccupiedBedDetails")
public R<List<Object>> getClassOccupiedBedDetails(@RequestParam(required = false) Long classId) {
List<Object> occupiedBedDetails = xgDormBedStudentService.getClassOccupiedBedDetails(classId);
return R.ok(occupiedBedDetails);
}
/**
* 获取班级所有未安排学生的床位信息
* 包含床位信息(校区名称、宿舍区名称、楼栋名称、房间名称、床位名称)
*/
@SaCheckPermission("dormBedStudent:dormBedStudent:list")
@GetMapping("/getClassUnoccupiedBedDetails")
public R<List<Object>> getClassUnoccupiedBedDetails(@RequestParam(required = false) Long classId) {
List<Object> unoccupiedBedDetails = xgDormBedStudentService.getClassUnoccupiedBedDetails(classId);
return R.ok(unoccupiedBedDetails);
}
/**
* 根据房间ID获取住在当前房间的所有学生信息
* 包含学生姓名、学号、性别、学院名称、专业名称、班级名称、床位编码、床位ID
*/
@SaCheckPermission("dormBedStudent:dormBedStudent:list")
@GetMapping("/getRoomStudents")
public R<List<Object>> getRoomStudents(@RequestParam Long roomId) {
List<Object> roomStudents = xgDormBedStudentService.getRoomStudents(roomId);
return R.ok(roomStudents);
}
}
@@ -0,0 +1,152 @@
package org.dromara.xg.controller;
import java.util.List;
import lombok.RequiredArgsConstructor;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.constraints.*;
import cn.dev33.satoken.annotation.SaCheckPermission;
import org.springframework.web.bind.annotation.*;
import org.springframework.validation.annotation.Validated;
import org.dromara.common.idempotent.annotation.RepeatSubmit;
import org.dromara.common.log.annotation.Log;
import org.dromara.common.web.core.BaseController;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.core.domain.R;
import org.dromara.common.core.validate.AddGroup;
import org.dromara.common.core.validate.EditGroup;
import org.dromara.common.log.enums.BusinessType;
import org.dromara.common.excel.utils.ExcelUtil;
import org.dromara.xg.domain.vo.DormHygieneCheckExportVo;
import org.dromara.xg.domain.vo.XgDormHygieneCheckVo;
import org.dromara.xg.domain.bo.XgDormHygieneCheckBo;
import org.dromara.xg.domain.bo.XgDormHygieneCheckCompleteBo;
import org.dromara.xg.service.IXgDormHygieneCheckService;
import org.dromara.common.mybatis.core.page.TableDataInfo;
/**
* 宿舍卫生检查
*
* @author zlwu
* @date 2025-08-16
*/
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/dormHygieneCheck/dormHygieneCheck")
public class XgDormHygieneCheckController extends BaseController {
private final IXgDormHygieneCheckService xgDormHygieneCheckService;
/**
* 查询宿舍卫生检查列表
*/
@SaCheckPermission("dormHygieneCheck:dormHygieneCheck:list")
@GetMapping("/list")
public TableDataInfo<XgDormHygieneCheckVo> list(XgDormHygieneCheckBo bo, PageQuery pageQuery) {
return xgDormHygieneCheckService.queryPageList(bo, pageQuery);
}
/**
* 导出宿舍卫生检查列表
*/
@SaCheckPermission("dormHygieneCheck:dormHygieneCheck:export")
@Log(title = "宿舍卫生检查", businessType = BusinessType.EXPORT)
@PostMapping("/export")
public void export(XgDormHygieneCheckBo bo, HttpServletResponse response) {
List<XgDormHygieneCheckVo> list = xgDormHygieneCheckService.queryList(bo);
ExcelUtil.exportExcel(list, "宿舍卫生检查", XgDormHygieneCheckVo.class, response);
}
/**
* 获取宿舍卫生检查详细信息
*
* @param id 主键
*/
@SaCheckPermission("dormHygieneCheck:dormHygieneCheck:query")
@GetMapping("/{id}")
public R<XgDormHygieneCheckVo> getInfo(@NotNull(message = "主键不能为空") @PathVariable Long id) {
return R.ok(xgDormHygieneCheckService.queryById(id));
}
/**
* 新增宿舍卫生检查
*/
@SaCheckPermission("dormHygieneCheck:dormHygieneCheck:add")
@Log(title = "宿舍卫生检查", businessType = BusinessType.INSERT)
@RepeatSubmit()
@PostMapping()
public R<Void> add(@Validated(AddGroup.class) @RequestBody XgDormHygieneCheckBo bo) {
return toAjax(xgDormHygieneCheckService.insertByBo(bo));
}
/**
* 新增宿舍卫生检查(包含学生评分数据)
*/
@SaCheckPermission("dormHygieneCheck:dormHygieneCheck:add")
@Log(title = "宿舍卫生检查", businessType = BusinessType.INSERT)
@RepeatSubmit()
@PostMapping("/addWithStudentScores")
public R<Void> addWithStudentScores(@Validated(AddGroup.class) @RequestBody XgDormHygieneCheckCompleteBo bo) {
return toAjax(xgDormHygieneCheckService.insertWithStudentScores(bo));
}
/**
* 修改宿舍卫生检查
*/
@SaCheckPermission("dormHygieneCheck:dormHygieneCheck:edit")
@Log(title = "宿舍卫生检查", businessType = BusinessType.UPDATE)
@RepeatSubmit()
@PutMapping()
public R<Void> edit(@Validated(EditGroup.class) @RequestBody XgDormHygieneCheckBo bo) {
return toAjax(xgDormHygieneCheckService.updateByBo(bo));
}
/**
* 修改宿舍卫生检查(包含学生评分数据)
*/
@SaCheckPermission("dormHygieneCheck:dormHygieneCheck:edit")
@Log(title = "宿舍卫生检查", businessType = BusinessType.UPDATE)
@RepeatSubmit()
@PutMapping("/updateWithStudentScores")
public R<Void> updateWithStudentScores(@Validated(EditGroup.class) @RequestBody XgDormHygieneCheckCompleteBo bo) {
return toAjax(xgDormHygieneCheckService.updateWithStudentScores(bo));
}
/**
* 删除宿舍卫生检查
*
* @param ids 主键串
*/
@SaCheckPermission("dormHygieneCheck:dormHygieneCheck:remove")
@Log(title = "宿舍卫生检查", businessType = BusinessType.DELETE)
@DeleteMapping("/{ids}")
public R<Void> remove(@NotEmpty(message = "主键不能为空") @PathVariable Long[] ids) {
return toAjax(xgDormHygieneCheckService.deleteWithValidByIds(List.of(ids), true));
}
/**
* 导出宿舍卫生检查列表(包含学生卫生情况)
*/
@SaCheckPermission("dormHygieneCheck:dormHygieneCheck:export")
@Log(title = "宿舍卫生检查", businessType = BusinessType.EXPORT)
@PostMapping("/advancedExport")
public void advancedExport(XgDormHygieneCheckBo bo, HttpServletResponse response) {
List<DormHygieneCheckExportVo> list = xgDormHygieneCheckService.queryExportList(bo);
ExcelUtil.exportExcel(list, "宿舍卫生检查数据", DormHygieneCheckExportVo.class, response);
}
/**
* 根据学生ID查询该学生宿舍的卫生检查信息
*
* @param studentId 学生ID
*/
@SaCheckPermission("dormHygieneCheck:dormHygieneCheck:query")
@GetMapping("/student/{studentId}")
public R<List<XgDormHygieneCheckVo>> getHygieneChecksByStudentId(
@NotNull(message = "学生ID不能为空") @PathVariable Long studentId) {
List<XgDormHygieneCheckVo> list = xgDormHygieneCheckService.queryByStudentId(studentId);
return R.ok(list);
}
}
@@ -0,0 +1,127 @@
package org.dromara.xg.controller;
import java.util.List;
import lombok.RequiredArgsConstructor;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.constraints.*;
import cn.dev33.satoken.annotation.SaCheckPermission;
import org.springframework.web.bind.annotation.*;
import org.springframework.validation.annotation.Validated;
import org.dromara.common.idempotent.annotation.RepeatSubmit;
import org.dromara.common.log.annotation.Log;
import org.dromara.common.web.core.BaseController;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.core.domain.R;
import org.dromara.common.core.validate.AddGroup;
import org.dromara.common.core.validate.EditGroup;
import org.dromara.common.log.enums.BusinessType;
import org.dromara.common.excel.utils.ExcelUtil;
import org.dromara.xg.domain.vo.XgDormHygieneStudentScoreVo;
import org.dromara.xg.domain.bo.XgDormHygieneStudentScoreBo;
import org.dromara.xg.service.IXgDormHygieneStudentScoreService;
import org.dromara.common.mybatis.core.page.TableDataInfo;
/**
* 宿舍卫生检查学生评分
*
* @author zlwu
* @date 2025-08-16
*/
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/dormHygieneStudentScore/dormHygieneStudentScore")
public class XgDormHygieneStudentScoreController extends BaseController {
private final IXgDormHygieneStudentScoreService xgDormHygieneStudentScoreService;
/**
* 查询宿舍卫生检查学生评分列表
*/
@SaCheckPermission("dormHygieneStudentScore:dormHygieneStudentScore:list")
@GetMapping("/list")
public TableDataInfo<XgDormHygieneStudentScoreVo> list(XgDormHygieneStudentScoreBo bo, PageQuery pageQuery) {
return xgDormHygieneStudentScoreService.queryPageList(bo, pageQuery);
}
/**
* 导出宿舍卫生检查学生评分列表
*/
@SaCheckPermission("dormHygieneStudentScore:dormHygieneStudentScore:export")
@Log(title = "宿舍卫生检查学生评分", businessType = BusinessType.EXPORT)
@PostMapping("/export")
public void export(XgDormHygieneStudentScoreBo bo, HttpServletResponse response) {
List<XgDormHygieneStudentScoreVo> list = xgDormHygieneStudentScoreService.queryList(bo);
ExcelUtil.exportExcel(list, "宿舍卫生检查学生评分", XgDormHygieneStudentScoreVo.class, response);
}
/**
* 获取宿舍卫生检查学生评分详细信息
*
* @param id 主键
*/
@SaCheckPermission("dormHygieneStudentScore:dormHygieneStudentScore:query")
@GetMapping("/{id}")
public R<XgDormHygieneStudentScoreVo> getInfo(@NotNull(message = "主键不能为空") @PathVariable Long id) {
return R.ok(xgDormHygieneStudentScoreService.queryById(id));
}
/**
* 新增宿舍卫生检查学生评分
*/
@SaCheckPermission("dormHygieneStudentScore:dormHygieneStudentScore:add")
@Log(title = "宿舍卫生检查学生评分", businessType = BusinessType.INSERT)
@RepeatSubmit()
@PostMapping()
public R<Void> add(@Validated(AddGroup.class) @RequestBody XgDormHygieneStudentScoreBo bo) {
return toAjax(xgDormHygieneStudentScoreService.insertByBo(bo));
}
/**
* 修改宿舍卫生检查学生评分
*/
@SaCheckPermission("dormHygieneStudentScore:dormHygieneStudentScore:edit")
@Log(title = "宿舍卫生检查学生评分", businessType = BusinessType.UPDATE)
@RepeatSubmit()
@PutMapping()
public R<Void> edit(@Validated(EditGroup.class) @RequestBody XgDormHygieneStudentScoreBo bo) {
return toAjax(xgDormHygieneStudentScoreService.updateByBo(bo));
}
/**
* 删除宿舍卫生检查学生评分
*
* @param ids 主键串
*/
@SaCheckPermission("dormHygieneStudentScore:dormHygieneStudentScore:remove")
@Log(title = "宿舍卫生检查学生评分", businessType = BusinessType.DELETE)
@DeleteMapping("/{ids}")
public R<Void> remove(@NotEmpty(message = "主键不能为空") @PathVariable Long[] ids) {
return toAjax(xgDormHygieneStudentScoreService.deleteWithValidByIds(List.of(ids), true));
}
/**
* 根据卫生检查ID查询学生评分列表
*
* @param hygieneCheckId 卫生检查ID
*/
@SaCheckPermission("dormHygieneStudentScore:dormHygieneStudentScore:query")
@GetMapping("/getByCheckId/{hygieneCheckId}")
public R<List<XgDormHygieneStudentScoreVo>> getByCheckId(
@NotNull(message = "卫生检查ID不能为空") @PathVariable Long hygieneCheckId) {
return R.ok(xgDormHygieneStudentScoreService.queryByHygieneCheckId(hygieneCheckId));
}
/**
* 批量删除指定卫生检查的学生评分记录
*
* @param hygieneCheckId 卫生检查ID
*/
@SaCheckPermission("dormHygieneStudentScore:dormHygieneStudentScore:remove")
@Log(title = "批量删除学生评分", businessType = BusinessType.DELETE)
@DeleteMapping("/deleteByCheckId/{hygieneCheckId}")
public R<Void> deleteByCheckId(@NotNull(message = "卫生检查ID不能为空") @PathVariable Long hygieneCheckId) {
return toAjax(xgDormHygieneStudentScoreService.deleteByHygieneCheckId(hygieneCheckId));
}
}
@@ -45,6 +45,27 @@ public class XgDormRoomController extends BaseController {
return xgDormRoomService.queryPageList(bo, pageQuery);
}
/**
* 查询当前用户所在学院的宿舍房间信息列表
*/
@SaCheckPermission("xgss:dormRoom:list")
@GetMapping("/college/list")
public TableDataInfo<XgDormRoomVo> collegeList(XgDormRoomBo bo, PageQuery pageQuery) {
return xgDormRoomService.queryPageListByCurrentUserCollege(bo, pageQuery);
}
/**
* 查询指定班级的宿舍房间信息列表
*/
@SaCheckPermission("xgss:dormRoom:list")
@GetMapping("/class/{classId}/list")
public TableDataInfo<XgDormRoomVo> classRoomList(
@NotNull(message = "班级ID不能为空") @PathVariable Long classId,
XgDormRoomBo bo,
PageQuery pageQuery) {
return xgDormRoomService.queryPageListByClassId(bo, pageQuery, classId);
}
/**
* 导出宿舍房间信息列表
*/
@@ -63,8 +84,7 @@ public class XgDormRoomController extends BaseController {
*/
@SaCheckPermission("xgss:dormRoom:query")
@GetMapping("/{id}")
public R<XgDormRoomVo> getInfo(@NotNull(message = "主键不能为空")
@PathVariable Long id) {
public R<XgDormRoomVo> getInfo(@NotNull(message = "主键不能为空") @PathVariable Long id) {
return R.ok(xgDormRoomService.queryById(id));
}
@@ -98,8 +118,7 @@ public class XgDormRoomController extends BaseController {
@SaCheckPermission("xgss:dormRoom:remove")
@Log(title = "宿舍房间信息", businessType = BusinessType.DELETE)
@DeleteMapping("/{ids}")
public R<Void> remove(@NotEmpty(message = "主键不能为空")
@PathVariable Long[] ids) {
public R<Void> remove(@NotEmpty(message = "主键不能为空") @PathVariable Long[] ids) {
return toAjax(xgDormRoomService.deleteWithValidByIds(List.of(ids), true));
}
}
@@ -0,0 +1,207 @@
package org.dromara.xg.controller;
import java.util.ArrayList;
import java.util.List;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.constraints.*;
import cn.dev33.satoken.annotation.SaCheckPermission;
import org.springframework.web.bind.annotation.*;
import org.springframework.beans.BeanUtils;
import org.springframework.validation.annotation.Validated;
import org.dromara.common.idempotent.annotation.RepeatSubmit;
import org.dromara.common.log.annotation.Log;
import org.dromara.common.web.core.BaseController;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.core.domain.R;
import org.dromara.common.core.validate.AddGroup;
import org.dromara.common.core.validate.EditGroup;
import org.dromara.common.log.enums.BusinessType;
import org.dromara.common.excel.utils.ExcelUtil;
import org.dromara.xg.domain.vo.XgDormViolationVo;
import org.dromara.xg.domain.bo.XgDormViolationBo;
import org.dromara.xg.domain.vo.StudentOptionVo;
import org.dromara.xg.domain.vo.XgDormViolationExportVo;
import org.dromara.xg.domain.vo.XgDormViolationImportVo;
import org.dromara.xg.domain.bo.StudentOptionBo;
import org.dromara.xg.service.IXgDormViolationService;
import org.springframework.web.multipart.MultipartFile;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.satoken.utils.LoginHelper;
/**
* 宿舍违纪记录
*
* @author zlwu
* @date 2025-08-16
*/
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/dormViolation/dormViolation")
@Slf4j
public class XgDormViolationController extends BaseController {
private final IXgDormViolationService xgDormViolationService;
/**
* 查询宿舍违纪记录列表
*/
@SaCheckPermission("dormViolation:dormViolation:list")
@GetMapping("/list")
public TableDataInfo<XgDormViolationVo> list(XgDormViolationBo bo, PageQuery pageQuery) {
return xgDormViolationService.queryPageList(bo, pageQuery);
}
/**
* 导出宿舍违纪记录列表
*/
@SaCheckPermission("dormViolation:dormViolation:export")
@Log(title = "宿舍违纪记录", businessType = BusinessType.EXPORT)
@PostMapping("/export")
public void export(XgDormViolationBo bo, HttpServletResponse response) {
List<XgDormViolationVo> list = xgDormViolationService.queryList(bo);
List<XgDormViolationExportVo> exportList = new ArrayList<XgDormViolationExportVo>();
for (XgDormViolationVo vo : list) {
XgDormViolationExportVo exportVo = new XgDormViolationExportVo();
BeanUtils.copyProperties(vo, exportVo);
exportList.add(exportVo);
}
ExcelUtil.exportExcel(exportList, "宿舍违纪记录", XgDormViolationExportVo.class, response);
}
/**
* 获取宿舍违纪记录详细信息
*
* @param id 主键
*/
@SaCheckPermission("dormViolation:dormViolation:query")
@GetMapping("/{id}")
public R<XgDormViolationVo> getInfo(@NotNull(message = "主键不能为空") @PathVariable Long id) {
return R.ok(xgDormViolationService.queryById(id));
}
/**
* 新增宿舍违纪记录
*/
@SaCheckPermission("dormViolation:dormViolation:add")
@Log(title = "宿舍违纪记录", businessType = BusinessType.INSERT)
@RepeatSubmit()
@PostMapping()
public R<Void> add(@Validated(AddGroup.class) @RequestBody XgDormViolationBo bo) {
return toAjax(xgDormViolationService.insertByBo(bo));
}
/**
* 修改宿舍违纪记录
*/
@SaCheckPermission("dormViolation:dormViolation:edit")
@Log(title = "宿舍违纪记录", businessType = BusinessType.UPDATE)
@RepeatSubmit()
@PutMapping()
public R<Void> edit(@Validated(EditGroup.class) @RequestBody XgDormViolationBo bo) {
return toAjax(xgDormViolationService.updateByBo(bo));
}
/**
* 删除宿舍违纪记录
*
* @param ids 主键串
*/
@SaCheckPermission("dormViolation:dormViolation:remove")
@Log(title = "宿舍违纪记录", businessType = BusinessType.DELETE)
@DeleteMapping("/{ids}")
public R<Void> remove(@NotEmpty(message = "主键不能为空") @PathVariable Long[] ids) {
return toAjax(xgDormViolationService.deleteWithValidByIds(List.of(ids), true));
}
/**
* 获取学生选择器选项列表(支持按学号、姓名检索)
*/
@SaCheckPermission("dormViolation:dormViolation:list")
@GetMapping("/studentOptions")
public TableDataInfo<StudentOptionVo> getStudentOptions(StudentOptionBo bo, PageQuery pageQuery) {
return xgDormViolationService.getStudentOptions(bo, pageQuery);
}
/**
* 根据学生ID获取学生详细信息
*
* @param studentId 学生ID
*/
@SaCheckPermission("dormViolation:dormViolation:list")
@GetMapping("/student/{studentId}")
public R<StudentOptionVo> getStudentById(@NotNull(message = "学生ID不能为空") @PathVariable Long studentId) {
return R.ok(xgDormViolationService.getStudentById(studentId));
}
/**
* 下载宿舍违纪记录导入模板
*/
@Log(title = "宿舍违纪记录", businessType = BusinessType.EXPORT)
@SaCheckPermission("dormViolation:dormViolation:import")
@PostMapping("/importTemplate")
public void importTemplate(HttpServletResponse response) {
// ExcelUtil.exportExcel(
// List.of(new XgDormViolationImportVo()),
// "宿舍违纪记录",
// XgDormViolationImportVo.class,
// response);
try {
// 设置响应头
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
response.setCharacterEncoding("utf-8");
String fileName = "宿舍违纪信息导入模板.xlsx";
fileName = java.net.URLEncoder.encode(fileName, "UTF-8").replaceAll("\\+",
"%20");
response.setHeader("Content-disposition", "attachment;filename*=utf-8''" +
fileName);
// 读取模板文件
org.springframework.core.io.Resource resource = new org.springframework.core.io.ClassPathResource(
"dormViolation_template.xlsx");
java.io.InputStream inputStream = resource.getInputStream();
java.io.OutputStream outputStream = response.getOutputStream();
// 复制文件内容到响应流
byte[] buffer = new byte[1024];
int bytesRead;
while ((bytesRead = inputStream.read(buffer)) != -1) {
outputStream.write(buffer, 0, bytesRead);
}
// 关闭流
inputStream.close();
outputStream.flush();
outputStream.close();
} catch (Exception e) {
log.error("宿舍违纪信息导入模板失败", e);
try {
response.setContentType("text/html;charset=utf-8");
response.getWriter().write("下载模板失败:" + e.getMessage());
} catch (Exception ex) {
log.error("写入错误响应失败", ex);
}
}
}
/**
* 导入宿舍违纪记录数据
*
* @param file Excel文件
* @param updateSupport 是否更新支持,如果已存在,则进行更新数据
*/
@Log(title = "宿舍违纪记录", businessType = BusinessType.IMPORT)
@SaCheckPermission("dormViolation:dormViolation:import")
@PostMapping("/importData")
public R<Void> importData(MultipartFile file, boolean updateSupport) throws Exception {
List<XgDormViolationImportVo> violationList = ExcelUtil.importExcel(file.getInputStream(),
XgDormViolationImportVo.class);
String operName = LoginHelper.getUsername();
String message = xgDormViolationService.importDormViolation(violationList, updateSupport, operName);
return R.ok(message);
}
}
@@ -0,0 +1,114 @@
package org.dromara.xg.controller;
import java.util.List;
import lombok.RequiredArgsConstructor;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.constraints.*;
import cn.dev33.satoken.annotation.SaCheckPermission;
import org.springframework.web.bind.annotation.*;
import org.springframework.validation.annotation.Validated;
import org.dromara.common.idempotent.annotation.RepeatSubmit;
import org.dromara.common.log.annotation.Log;
import org.dromara.common.web.core.BaseController;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.core.domain.R;
import org.dromara.common.core.validate.AddGroup;
import org.dromara.common.core.validate.EditGroup;
import org.dromara.common.log.enums.BusinessType;
import org.dromara.common.excel.utils.ExcelUtil;
import org.dromara.xg.domain.vo.XgHolidayStayVo;
import org.dromara.xg.domain.bo.XgHolidayStayBo;
import org.dromara.xg.domain.vo.StudentOptionVo;
import org.dromara.xg.domain.bo.StudentOptionBo;
import org.dromara.xg.service.IXgHolidayStayService;
import org.dromara.common.mybatis.core.page.TableDataInfo;
/**
* 假期留宿管理
*
* @author zlwu
* @date 2025-08-15
*/
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/holidayStay/holidayStay")
public class XgHolidayStayController extends BaseController {
private final IXgHolidayStayService xgHolidayStayService;
/**
* 查询假期留宿管理列表
*/
@SaCheckPermission("holidayStay:holidayStay:list")
@GetMapping("/list")
public TableDataInfo<XgHolidayStayVo> list(XgHolidayStayBo bo, PageQuery pageQuery) {
return xgHolidayStayService.queryPageList(bo, pageQuery);
}
/**
* 导出假期留宿管理列表
*/
@SaCheckPermission("holidayStay:holidayStay:export")
@Log(title = "假期留宿管理", businessType = BusinessType.EXPORT)
@PostMapping("/export")
public void export(XgHolidayStayBo bo, HttpServletResponse response) {
List<XgHolidayStayVo> list = xgHolidayStayService.queryList(bo);
ExcelUtil.exportExcel(list, "假期留宿管理", XgHolidayStayVo.class, response);
}
/**
* 获取假期留宿管理详细信息
*
* @param id 主键
*/
@SaCheckPermission("holidayStay:holidayStay:query")
@GetMapping("/{id}")
public R<XgHolidayStayVo> getInfo(@NotNull(message = "主键不能为空") @PathVariable Long id) {
return R.ok(xgHolidayStayService.queryById(id));
}
/**
* 新增假期留宿管理
*/
@SaCheckPermission("holidayStay:holidayStay:add")
@Log(title = "假期留宿管理", businessType = BusinessType.INSERT)
@RepeatSubmit()
@PostMapping()
public R<Void> add(@Validated(AddGroup.class) @RequestBody XgHolidayStayBo bo) {
return toAjax(xgHolidayStayService.insertByBo(bo));
}
/**
* 修改假期留宿管理
*/
@SaCheckPermission("holidayStay:holidayStay:edit")
@Log(title = "假期留宿管理", businessType = BusinessType.UPDATE)
@RepeatSubmit()
@PutMapping()
public R<Void> edit(@Validated(EditGroup.class) @RequestBody XgHolidayStayBo bo) {
return toAjax(xgHolidayStayService.updateByBo(bo));
}
/**
* 删除假期留宿管理
*
* @param ids 主键串
*/
@SaCheckPermission("holidayStay:holidayStay:remove")
@Log(title = "假期留宿管理", businessType = BusinessType.DELETE)
@DeleteMapping("/{ids}")
public R<Void> remove(@NotEmpty(message = "主键不能为空") @PathVariable Long[] ids) {
return toAjax(xgHolidayStayService.deleteWithValidByIds(List.of(ids), true));
}
/**
* 获取学生选择器选项列表(支持按学号、姓名检索)
*/
@SaCheckPermission("holidayStay:holidayStay:list")
@GetMapping("/studentOptions")
public TableDataInfo<StudentOptionVo> getStudentOptions(StudentOptionBo bo, PageQuery pageQuery) {
return xgHolidayStayService.getStudentOptions(bo, pageQuery);
}
}
@@ -1286,4 +1286,15 @@ public class XgStudentMsgController extends BaseController {
List<XgStudentTreeVo> studentTree = xgStudentMsgService.getStudentTree(secondaryCollegeId);
return R.ok(studentTree);
}
/**
* 获取当前用户所在学院的学生信息树
*/
@SaCheckPermission("studentMsg:studentMsg:list")
@GetMapping("/getCurrentUserStudentTree")
public R<List<XgStudentTreeVo>> getCurrentUserStudentTree() {
log.info("获取当前用户所在学院的学生信息树");
List<XgStudentTreeVo> studentTree = xgStudentMsgService.getCurrentUserStudentTree();
return R.ok(studentTree);
}
}
@@ -0,0 +1,138 @@
package org.dromara.xg.convert;
import cn.hutool.core.util.StrUtil;
import cn.idev.excel.converters.Converter;
import cn.idev.excel.enums.CellDataTypeEnum;
import cn.idev.excel.metadata.GlobalConfiguration;
import cn.idev.excel.metadata.data.ReadCellData;
import cn.idev.excel.metadata.data.WriteCellData;
import cn.idev.excel.metadata.property.ExcelContentProperty;
import org.dromara.common.core.utils.SpringUtils;
import org.dromara.xg.domain.vo.StudentOptionVo;
import org.dromara.xg.service.IXgDormViolationService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
/**
* 学生信息Excel转换器
* 将学生ID转换为学生详细信息(学号、姓名、学院名称、专业名称、班级名称)
*
* @author zlwu
* @date 2025-01-03
*/
public class StudentInfoExcelConvert implements Converter<String> {
private static final Logger log = LoggerFactory.getLogger(StudentInfoExcelConvert.class);
@Override
public Class<String> supportJavaTypeKey() {
return String.class;
}
@Override
public CellDataTypeEnum supportExcelTypeKey() {
return CellDataTypeEnum.STRING;
}
@Override
public String convertToJavaData(ReadCellData<?> cellData, ExcelContentProperty contentProperty,
GlobalConfiguration globalConfiguration) {
String value = cellData.getStringValue();
if (StrUtil.isBlank(value)) {
return "";
}
try {
// 获取服务实例
IXgDormViolationService dormViolationService = SpringUtils.getBean(IXgDormViolationService.class);
if (dormViolationService == null) {
log.warn("无法获取宿舍违纪服务实例,返回原始值");
return value;
}
// 分割学号(逗号分隔)
String[] studentNoArray = value.split(",");
List<String> studentIdList = Arrays.stream(studentNoArray)
.map(String::trim)
.filter(StrUtil::isNotBlank)
.map(studentNo -> {
try {
StudentOptionVo student = dormViolationService.getStudentByStudentNo(studentNo);
if (student != null) {
return student.getId().toString();
} else {
log.warn("未找到学号为 {} 的学生", studentNo);
return null;
}
} catch (Exception e) {
log.error("根据学号查询学生信息失败,学号: {}", studentNo, e);
return null;
}
})
.filter(id -> id != null)
.collect(Collectors.toList());
return String.join(",", studentIdList);
} catch (Exception e) {
log.error("学号转学生ID失败,原始值: {}", value, e);
return "";
}
}
@Override
public WriteCellData<String> convertToExcelData(String value, ExcelContentProperty contentProperty,
GlobalConfiguration globalConfiguration) {
if (StrUtil.isBlank(value)) {
return new WriteCellData<>("");
}
try {
// 获取服务实例
IXgDormViolationService dormViolationService = SpringUtils.getBean(IXgDormViolationService.class);
if (dormViolationService == null) {
log.warn("无法获取宿舍违纪服务实例,返回原始值");
return new WriteCellData<>(value);
}
// 分割学生ID(逗号分隔)
String[] idArray = value.split(",");
List<String> studentInfoList = Arrays.stream(idArray)
.map(String::trim)
.filter(StrUtil::isNotBlank)
.map(idStr -> {
try {
Long studentId = Long.parseLong(idStr);
StudentOptionVo student = dormViolationService.getStudentById(studentId);
if (student != null) {
// 格式:学号-姓名(学院-专业-班级)
return String.format("%s-%s(%s-%s-%s)",
student.getStudentNo(),
student.getName(),
student.getCollegeName(),
student.getMajorName(),
student.getClassName());
} else {
return idStr + "-未知学生";
}
} catch (NumberFormatException e) {
log.warn("无效的学生ID格式: {}", idStr);
return idStr + "-格式错误";
} catch (Exception e) {
log.error("查询学生信息失败,学生ID: {}", idStr, e);
return idStr + "-查询失败";
}
})
.collect(Collectors.toList());
String convertedValue = String.join("; ", studentInfoList);
return new WriteCellData<>(convertedValue);
} catch (Exception e) {
log.error("学生信息转换失败,原始值: {}", value, e);
return new WriteCellData<>(value + "-转换失败");
}
}
}
@@ -0,0 +1,143 @@
package org.dromara.xg.domain;
import org.dromara.common.tenant.core.TenantEntity;
import com.baomidou.mybatisplus.annotation.*;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.util.Date;
import com.fasterxml.jackson.annotation.JsonFormat;
import java.io.Serial;
/**
* 宿舍卫生检查对象 xg_dorm_hygiene_check
*
* @author zlwu
* @date 2025-08-16
*/
@Data
@EqualsAndHashCode(callSuper = true)
@TableName("xg_dorm_hygiene_check")
public class XgDormHygieneCheck extends TenantEntity {
@Serial
private static final long serialVersionUID = 1L;
/**
* 主键ID
*/
@TableId(value = "id")
private Long id;
/**
* 删除标志(0代表存在 1代表删除)
*/
@TableLogic(value = "0", delval = "1")
private Long deleted;
/**
* 检查标题
*/
private String checkTitle;
/**
* 检查日期
*/
private Date checkDate;
/**
* 检查员ID,关联sys_user.id
*/
private Long checkerId;
/**
* 检查员姓名
*/
private String checkerName;
/**
* 检查类型(1日常检查 2专项检查 3突击检查 4复查)
*/
private String checkType;
/**
* 检查级别(1宿管员 2学院 3学校)
*/
private String checkLevel;
/**
* 宿舍房间ID,关联xg_dorm_room.id
*/
private Long roomId;
/**
* 房间编号
*/
private String roomCode;
/**
* 房间名称
*/
private String roomName;
/**
* 宿舍楼ID,关联xg_dorm_building.id
*/
private Long buildingId;
/**
* 宿舍楼名称
*/
private String buildingName;
/**
* 宿舍区ID,关联xg_dorm_area.id
*/
private Long areaId;
/**
* 宿舍区名称
*/
private String areaName;
/**
* 校区ID,关联xg_dorm_campus.id
*/
private Long campusId;
/**
* 校区名称
*/
private String campusName;
/**
* 宿舍总分(0-100分)
*/
private Double totalScore;
/**
* 卫生等级(A优秀 B良好 C合格 D不合格)
*/
private String hygieneGrade;
/**
* 附件OSS ID列表,逗号分隔
*/
private String attachmentIds;
/**
* 检查总结
*/
private String checkSummary;
/**
* 整改建议
*/
private String improvementSuggestions;
/**
* 检查备注
*/
private String checkRemarks;
}
@@ -0,0 +1,126 @@
package org.dromara.xg.domain;
import org.dromara.common.tenant.core.TenantEntity;
import com.baomidou.mybatisplus.annotation.*;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.io.Serial;
/**
* 宿舍卫生检查学生评分对象 xg_dorm_hygiene_student_score
*
* @author zlwu
* @date 2025-08-16
*/
@Data
@EqualsAndHashCode(callSuper = true)
@TableName("xg_dorm_hygiene_student_score")
public class XgDormHygieneStudentScore extends TenantEntity {
@Serial
private static final long serialVersionUID = 1L;
/**
* 主键ID
*/
@TableId(value = "id")
private Long id;
/**
* 删除标志(0代表存在 1代表删除)
*/
@TableLogic(value = "0", delval = "1")
private Long deleted;
/**
* 卫生检查ID,关联xg_dorm_hygiene_check.id
*/
private Long hygieneCheckId;
/**
* 学生ID,关联xg_student_msg.id
*/
private Long studentId;
/**
* 学号
*/
private String studentNo;
/**
* 学生姓名
*/
private String studentName;
/**
* 班级ID
*/
private Long classId;
/**
* 班级名称
*/
private String className;
/**
* 专业ID
*/
private Long majorId;
/**
* 专业名称
*/
private String majorName;
/**
* 学院ID
*/
private Long collegeId;
/**
* 学院名称
*/
private String collegeName;
/**
* 床位ID,关联xg_dorm_bed.id
*/
private Long bedId;
/**
* 床位编号
*/
private String bedCode;
/**
* 学生个人得分(0-100分)
*/
private Double studentScore;
/**
* 是否在寝(1在寝 2外出 3请假 4其他)
*/
private String attendanceStatus;
/**
* 学生评级(A优秀 B良好 C合格 D不合格)
*/
private String studentGrade;
/**
* 是否为寝室长(0否 1是)
*/
private Long isResponsiblePerson;
/**
* 评分备注
*/
private String scoreRemarks;
/**
* 改进意见
*/
private String improvementNotes;
}
@@ -0,0 +1,168 @@
package org.dromara.xg.domain;
import org.dromara.common.tenant.core.TenantEntity;
import com.baomidou.mybatisplus.annotation.*;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.util.Date;
import com.fasterxml.jackson.annotation.JsonFormat;
import java.io.Serial;
/**
* 宿舍违纪记录对象 xg_dorm_violation
*
* @author zlwu
* @date 2025-08-16
*/
@Data
@EqualsAndHashCode(callSuper = true)
@TableName("xg_dorm_violation")
public class XgDormViolation extends TenantEntity {
@Serial
private static final long serialVersionUID = 1L;
/**
* 违纪记录ID(主键)
*/
@TableId(value = "id")
private Long id;
/**
* 学生ID
*/
private Long studentId;
/**
* 学生姓名
*/
private String studentName;
/**
* 学号
*/
private String studentNo;
/**
* 学院ID
*/
private Long collegeId;
/**
* 学院名称
*/
private String collegeName;
/**
* 专业ID
*/
private Long majorId;
/**
* 专业名称
*/
private String majorName;
/**
* 班级ID
*/
private Long classId;
/**
* 班级名称
*/
private String className;
/**
* 校区ID
*/
private Long campusId;
/**
* 校区名称
*/
private String campusName;
/**
* 宿舍区域ID
*/
private Long areaId;
/**
* 宿舍区域名称
*/
private String areaName;
/**
* 宿舍楼ID
*/
private Long buildingId;
/**
* 宿舍楼名称
*/
private String buildingName;
/**
* 宿舍房间ID
*/
private Long roomId;
/**
* 房间名称
*/
private String roomName;
/**
* 床位ID
*/
private Long bedId;
/**
* 床位名称
*/
private String bedName;
/**
* 违纪类型
*/
private String violationType;
/**
* 违纪等级:1轻微 2一般 3严重 4特别严重
*/
private String violationLevel;
/**
* 违纪发生时间
*/
private Date violationTime;
/**
* 违纪行为描述
*/
private String violationDescription;
/**
* 涉及其他学生id(逗号分隔)
*/
private String involvedStudents;
/**
* 附件OSS ID列表(逗号分隔)
*/
private String attachmentOssIds;
/**
* 删除标志(0代表存在 1代表删除)
*/
private String deleted;
/**
* 备注
*/
private String remark;
}
@@ -0,0 +1,203 @@
package org.dromara.xg.domain;
import org.dromara.common.tenant.core.TenantEntity;
import com.baomidou.mybatisplus.annotation.*;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.util.Date;
import com.fasterxml.jackson.annotation.JsonFormat;
import java.io.Serial;
/**
* 假期留宿管理对象 xg_holiday_stay
*
* @author zlwu
* @date 2025-08-15
*/
@Data
@EqualsAndHashCode(callSuper = true)
@TableName("xg_holiday_stay")
public class XgHolidayStay extends TenantEntity {
@Serial
private static final long serialVersionUID = 1L;
/**
* 主键ID
*/
@TableId(value = "id")
private Long id;
/**
* 删除标志(0代表存在 1代表删除)
*/
private Long deleted;
/**
* 学生ID,关联xg_student_msg.id
*/
private Long studentId;
/**
* 学生姓名
*/
private String studentName;
/**
* 学号
*/
private String studentNo;
/**
* 班级ID
*/
private Long classId;
/**
* 班级名称
*/
private String className;
/**
* 专业ID
*/
private Long majorId;
/**
* 专业名称
*/
private String majorName;
/**
* 学院ID
*/
private Long collegeId;
/**
* 学院名称
*/
private String collegeName;
/**
* 校区ID,关联xg_dorm_campus.id
*/
private Long campusId;
/**
* 校区名称
*/
private String campusName;
/**
* 宿舍区ID,关联xg_dorm_area.id
*/
private Long areaId;
/**
* 宿舍区名称
*/
private String areaName;
/**
* 宿舍楼ID,关联xg_dorm_building.id
*/
private Long buildingId;
/**
* 宿舍楼名称
*/
private String buildingName;
/**
* 房间ID,关联xg_dorm_room.id
*/
private Long roomId;
/**
* 房间名称
*/
private String roomName;
/**
* 床位ID,关联xg_dorm_bed.id
*/
private Long bedId;
/**
* 床位名称
*/
private String bedName;
/**
* 假期类型(寒假、暑假、春节假期、国庆假期等)
*/
private String holidayType;
/**
* 申请留宿开始日期
*/
private Date applyStartDate;
/**
* 申请留宿结束日期
*/
private Date applyEndDate;
/**
* 留宿原因(必填)
*/
private String stayReason;
/**
* 留宿原因类型(学习、实习、家庭困难、其他)
*/
private String stayReasonType;
/**
* 学生联系电话
*/
private String studentPhone;
/**
* 紧急联系人姓名
*/
private String emergencyContact;
/**
* 紧急联系人电话
*/
private String emergencyPhone;
/**
* 家长同意(0否 1是)
*/
private String parentConsent;
/**
* 附件OSS文件ID,多个用逗号分隔(申请材料、证明文件等)
*/
private String attachmentOssIds;
/**
* 扩展字段1
*/
private String extField1;
/**
* 扩展字段2
*/
private String extField2;
/**
* 扩展字段3
*/
private String extField3;
/**
* 备注信息
*/
private String remark;
}
@@ -516,7 +516,7 @@ public class XgStudentMsg extends TenantEntity {
private String dormitoryRoom;
/**
* 扩展字段1
* 扩展字段1 - 床位id
*/
private String extField1;
@@ -516,7 +516,7 @@ public class XgStudentMsgBatch extends TenantEntity {
private String dormitoryRoom;
/**
* 扩展字段1
* 扩展字段1 - 床位id
*/
private String extField1;
@@ -1,5 +1,6 @@
package org.dromara.xg.domain;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import lombok.EqualsAndHashCode;
@@ -70,8 +71,9 @@ public class XgSysDept extends BaseEntity {
private String delFlag;
/**
* 父部门名称
* 父部门名称(冗余字段,用于显示,不持久化到数据库)
*/
@TableField(exist = false)
private String parentName;
/**
@@ -0,0 +1,21 @@
package org.dromara.xg.domain.bo;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.dromara.common.mybatis.core.domain.BaseEntity;
/**
* 学生选择器查询业务对象
*
* @author zlwu
* @date 2025-08-15
*/
@Data
@EqualsAndHashCode(callSuper = true)
public class StudentOptionBo extends BaseEntity {
/**
* 搜索关键字(学号或姓名)
*/
private String keyword;
}
@@ -0,0 +1,49 @@
package org.dromara.xg.domain.bo;
import io.github.linpeilie.annotations.AutoMapper;
import jakarta.validation.constraints.NotEmpty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.dromara.common.core.validate.AddGroup;
import org.dromara.common.mybatis.core.domain.BaseEntity;
import java.util.List;
/**
* 床位批量分配给班级业务对象 xg_dorm_bed_batch_allocate_to_class
*
* @author zlwu
* @date 2025-01-27
*/
@Data
@EqualsAndHashCode(callSuper = true)
public class XgDormBedBatchAllocateToClassBo extends BaseEntity {
/**
* 床位ID列表
*/
@NotEmpty(message = "床位ID列表不能为空", groups = { AddGroup.class })
private List<Long> bedIds;
/**
* 班级ID列表
*/
@NotEmpty(message = "班级ID列表不能为空", groups = { AddGroup.class })
private List<Long> classIds;
/**
* 班级人数列表(与classIds一一对应)
*/
private List<Integer> classStudentCounts;
/**
* 楼栋ID
*/
private Long buildingId;
/**
* 楼栋类型(1-男生楼,2-女生楼)
*/
private String buildingType;
}
@@ -0,0 +1,23 @@
package org.dromara.xg.domain.bo;
import jakarta.validation.constraints.NotEmpty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.dromara.common.core.validate.AddGroup;
import org.dromara.common.mybatis.core.domain.BaseEntity;
import java.util.List;
/**
* 床位批量收回业务对象
*/
@Data
@EqualsAndHashCode(callSuper = true)
public class XgDormBedBatchRecallBo extends BaseEntity {
/**
* 床位ID列表
*/
@NotEmpty(message = "床位ID列表不能为空", groups = { AddGroup.class })
private List<Long> bedIds;
}
@@ -0,0 +1,151 @@
package org.dromara.xg.domain.bo;
import org.dromara.xg.domain.XgDormHygieneCheck;
import org.dromara.common.mybatis.core.domain.BaseEntity;
import org.dromara.common.core.validate.AddGroup;
import org.dromara.common.core.validate.EditGroup;
import io.github.linpeilie.annotations.AutoMapper;
import lombok.Data;
import lombok.EqualsAndHashCode;
import jakarta.validation.constraints.*;
import java.util.Date;
import com.fasterxml.jackson.annotation.JsonFormat;
/**
* 宿舍卫生检查业务对象 xg_dorm_hygiene_check
*
* @author zlwu
* @date 2025-08-16
*/
@Data
@EqualsAndHashCode(callSuper = true)
@AutoMapper(target = XgDormHygieneCheck.class, reverseConvertGenerate = false)
public class XgDormHygieneCheckBo extends BaseEntity {
/**
* 主键ID
*/
@NotNull(message = "主键ID不能为空", groups = { EditGroup.class })
private Long id;
/**
* 删除标志(0代表存在 1代表删除)
*/
private Long deleted;
/**
* 检查标题
*/
@NotBlank(message = "检查标题不能为空", groups = { AddGroup.class, EditGroup.class })
private String checkTitle;
/**
* 检查日期
*/
@NotNull(message = "检查日期不能为空", groups = { AddGroup.class, EditGroup.class })
private Date checkDate;
/**
* 检查员ID,关联sys_user.id
*/
@NotNull(message = "检查员ID,关联sys_user.id不能为空", groups = { AddGroup.class, EditGroup.class })
private Long checkerId;
/**
* 检查员姓名
*/
@NotBlank(message = "检查员姓名不能为空", groups = { AddGroup.class, EditGroup.class })
private String checkerName;
/**
* 检查类型(1日常检查 2专项检查 3突击检查 4复查)
*/
private String checkType;
/**
* 检查级别(1宿管员 2学院 3学校)
*/
private String checkLevel;
/**
* 宿舍房间ID,关联xg_dorm_room.id
*/
@NotNull(message = "宿舍房间ID,关联xg_dorm_room.id不能为空", groups = { AddGroup.class, EditGroup.class })
private Long roomId;
/**
* 房间编号
*/
@NotBlank(message = "房间编号不能为空", groups = { AddGroup.class, EditGroup.class })
private String roomCode;
/**
* 房间名称
*/
@NotBlank(message = "房间名称不能为空", groups = { AddGroup.class, EditGroup.class })
private String roomName;
/**
* 宿舍楼ID,关联xg_dorm_building.id
*/
@NotNull(message = "宿舍楼ID,关联xg_dorm_building.id不能为空", groups = { AddGroup.class, EditGroup.class })
private Long buildingId;
/**
* 宿舍楼名称
*/
@NotBlank(message = "宿舍楼名称不能为空", groups = { AddGroup.class, EditGroup.class })
private String buildingName;
/**
* 宿舍区ID,关联xg_dorm_area.id
*/
private Long areaId;
/**
* 宿舍区名称
*/
private String areaName;
/**
* 校区ID,关联xg_dorm_campus.id
*/
private Long campusId;
/**
* 校区名称
*/
private String campusName;
/**
* 宿舍总分(0-100分)
*/
private Double totalScore;
/**
* 卫生等级(A优秀 B良好 C合格 D不合格)
*/
private String hygieneGrade;
/**
* 附件OSS ID列表,逗号分隔
*/
private String attachmentIds;
/**
* 检查总结
*/
private String checkSummary;
/**
* 整改建议
*/
private String improvementSuggestions;
/**
* 检查备注
*/
private String checkRemarks;
}
@@ -0,0 +1,169 @@
package org.dromara.xg.domain.bo;
import org.dromara.xg.domain.XgDormHygieneCheck;
import org.dromara.common.core.validate.AddGroup;
import org.dromara.common.core.validate.EditGroup;
import io.github.linpeilie.annotations.AutoMapper;
import lombok.Data;
import jakarta.validation.constraints.*;
import jakarta.validation.Valid;
import java.util.List;
import java.util.Date;
import com.fasterxml.jackson.annotation.JsonFormat;
/**
* 宿舍卫生检查完整表单业务对象(包含学生评分数据)
*
* @author zlwu
* @date 2025-01-28
*/
@Data
@AutoMapper(target = XgDormHygieneCheck.class, reverseConvertGenerate = false)
public class XgDormHygieneCheckCompleteBo {
/**
* 主键ID
*/
@NotNull(message = "主键ID不能为空", groups = { EditGroup.class })
private Long id;
/**
* 删除标志(0代表存在 1代表删除)
*/
private Long deleted;
/**
* 检查标题
*/
@NotBlank(message = "检查标题不能为空", groups = { AddGroup.class, EditGroup.class })
private String checkTitle;
/**
* 检查日期
*/
@NotNull(message = "检查日期不能为空", groups = { AddGroup.class, EditGroup.class })
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date checkDate;
/**
* 检查员ID,关联sys_user.id
*/
@NotNull(message = "检查员ID不能为空", groups = { AddGroup.class, EditGroup.class })
private Long checkerId;
/**
* 检查员姓名
*/
@NotBlank(message = "检查员姓名不能为空", groups = { AddGroup.class, EditGroup.class })
private String checkerName;
/**
* 检查类型(1日常检查 2专项检查 3突击检查 4复查)
*/
private String checkType;
/**
* 检查级别(1宿管员 2学院 3学校)
*/
private String checkLevel;
/**
* 宿舍房间ID,关联xg_dorm_room.id
*/
@NotNull(message = "宿舍房间ID不能为空", groups = { AddGroup.class, EditGroup.class })
private Long roomId;
/**
* 房间编号
*/
@NotBlank(message = "房间编号不能为空", groups = { AddGroup.class, EditGroup.class })
private String roomCode;
/**
* 房间名称
*/
@NotBlank(message = "房间名称不能为空", groups = { AddGroup.class, EditGroup.class })
private String roomName;
/**
* 宿舍楼ID,关联xg_dorm_building.id
*/
@NotNull(message = "宿舍楼ID不能为空", groups = { AddGroup.class, EditGroup.class })
private Long buildingId;
/**
* 宿舍楼名称
*/
@NotBlank(message = "宿舍楼名称不能为空", groups = { AddGroup.class, EditGroup.class })
private String buildingName;
/**
* 宿舍区ID,关联xg_dorm_area.id
*/
private Long areaId;
/**
* 宿舍区名称
*/
private String areaName;
/**
* 校区ID,关联xg_dorm_campus.id
*/
private Long campusId;
/**
* 校区名称
*/
private String campusName;
/**
* 宿舍总分(0-100分)
*/
@Min(value = 0, message = "宿舍总分不能小于0")
@Max(value = 100, message = "宿舍总分不能大于100")
private Double totalScore;
/**
* 卫生等级(A优秀 B良好 C合格 D不合格)
*/
private String hygieneGrade;
/**
* 附件OSS ID列表,逗号分隔
*/
private String attachmentIds;
/**
* 检查总结
*/
private String checkSummary;
/**
* 整改建议
*/
private String improvementSuggestions;
/**
* 检查备注
*/
private String checkRemarks;
/**
* 学生评分数据列表
*/
@Valid
@NotEmpty(message = "学生评分数据不能为空", groups = { AddGroup.class, EditGroup.class })
private List<XgDormHygieneStudentScoreBo> studentScores;
// 基础字段(用于VO类映射)
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;
}
@@ -0,0 +1,129 @@
package org.dromara.xg.domain.bo;
import org.dromara.xg.domain.XgDormHygieneStudentScore;
import org.dromara.common.mybatis.core.domain.BaseEntity;
import org.dromara.common.core.validate.AddGroup;
import org.dromara.common.core.validate.EditGroup;
import io.github.linpeilie.annotations.AutoMapper;
import lombok.Data;
import lombok.EqualsAndHashCode;
import jakarta.validation.constraints.*;
/**
* 宿舍卫生检查学生评分业务对象 xg_dorm_hygiene_student_score
*
* @author zlwu
* @date 2025-08-16
*/
@Data
@EqualsAndHashCode(callSuper = true)
@AutoMapper(target = XgDormHygieneStudentScore.class, reverseConvertGenerate = false)
public class XgDormHygieneStudentScoreBo extends BaseEntity {
/**
* 主键ID
*/
@NotNull(message = "主键ID不能为空", groups = { EditGroup.class })
private Long id;
/**
* 删除标志(0代表存在 1代表删除)
*/
private Long deleted;
/**
* 卫生检查ID,关联xg_dorm_hygiene_check.id
*/
// @NotNull(message = "卫生检查ID,关联xg_dorm_hygiene_check.id不能为空", groups = {
// EditGroup.class })
private Long hygieneCheckId;
/**
* 学生ID,关联xg_student_msg.id
*/
@NotNull(message = "学生ID,关联xg_student_msg.id不能为空", groups = { AddGroup.class, EditGroup.class })
private Long studentId;
/**
* 学号
*/
@NotBlank(message = "学号不能为空", groups = { AddGroup.class, EditGroup.class })
private String studentNo;
/**
* 学生姓名
*/
@NotBlank(message = "学生姓名不能为空", groups = { AddGroup.class, EditGroup.class })
private String studentName;
/**
* 班级ID
*/
private Long classId;
/**
* 班级名称
*/
private String className;
/**
* 专业ID
*/
private Long majorId;
/**
* 专业名称
*/
private String majorName;
/**
* 学院ID
*/
private Long collegeId;
/**
* 学院名称
*/
private String collegeName;
/**
* 床位ID,关联xg_dorm_bed.id
*/
private Long bedId;
/**
* 床位编号
*/
private String bedCode;
/**
* 学生个人得分(0-100分)
*/
private Double studentScore;
/**
* 是否在寝(1在寝 2外出 3请假 4其他)
*/
private String attendanceStatus;
/**
* 学生评级(A优秀 B良好 C合格 D不合格)
*/
private String studentGrade;
/**
* 是否为寝室长(0否 1是)
*/
private Long isResponsiblePerson;
/**
* 评分备注
*/
private String scoreRemarks;
/**
* 改进意见
*/
private String improvementNotes;
}
@@ -0,0 +1,35 @@
package org.dromara.xg.domain.bo;
import lombok.Data;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotBlank;
import java.util.List;
/**
* 班主任选择性分配床位请求参数
*
* @author zlwu
* @date 2025-01-27
*/
@Data
public class XgDormSelectiveAllocationBo {
/**
* 选择的床位ID数组
*/
@NotEmpty(message = "床位ID列表不能为空")
private List<Long> bedIds;
/**
* 选择的学生ID数组
*/
@NotEmpty(message = "学生ID列表不能为空")
private List<Long> studentIds;
/**
* 分配类型:random-随机分配,studentNo-按学号分配
*/
@NotBlank(message = "分配类型不能为空")
private String allocationType;
}
@@ -0,0 +1,178 @@
package org.dromara.xg.domain.bo;
import org.dromara.xg.domain.XgDormViolation;
import org.dromara.common.mybatis.core.domain.BaseEntity;
import org.dromara.common.core.validate.AddGroup;
import org.dromara.common.core.validate.EditGroup;
import io.github.linpeilie.annotations.AutoMapper;
import lombok.Data;
import lombok.EqualsAndHashCode;
import jakarta.validation.constraints.*;
import java.util.Date;
import com.fasterxml.jackson.annotation.JsonFormat;
/**
* 宿舍违纪记录业务对象 xg_dorm_violation
*
* @author zlwu
* @date 2025-08-16
*/
@Data
@EqualsAndHashCode(callSuper = true)
@AutoMapper(target = XgDormViolation.class, reverseConvertGenerate = false)
public class XgDormViolationBo extends BaseEntity {
/**
* 违纪记录ID(主键)
*/
@NotNull(message = "违纪记录ID(主键)不能为空", groups = { EditGroup.class })
private Long id;
/**
* 学生ID
*/
@NotNull(message = "学生ID不能为空", groups = { AddGroup.class, EditGroup.class })
private Long studentId;
/**
* 学生姓名
*/
@NotBlank(message = "学生姓名不能为空", groups = { AddGroup.class, EditGroup.class })
private String studentName;
/**
* 学号
*/
@NotBlank(message = "学号不能为空", groups = { AddGroup.class, EditGroup.class })
private String studentNo;
/**
* 学院ID
*/
private Long collegeId;
/**
* 学院名称
*/
private String collegeName;
/**
* 专业ID
*/
private Long majorId;
/**
* 专业名称
*/
private String majorName;
/**
* 班级ID
*/
private Long classId;
/**
* 班级名称
*/
private String className;
/**
* 校区ID
*/
private Long campusId;
/**
* 校区名称
*/
private String campusName;
/**
* 宿舍区域ID
*/
private Long areaId;
/**
* 宿舍区域名称
*/
private String areaName;
/**
* 宿舍楼ID
*/
@NotNull(message = "宿舍楼ID不能为空", groups = { AddGroup.class, EditGroup.class })
private Long buildingId;
/**
* 宿舍楼名称
*/
@NotBlank(message = "宿舍楼名称不能为空", groups = { AddGroup.class, EditGroup.class })
private String buildingName;
/**
* 宿舍房间ID
*/
@NotNull(message = "宿舍房间ID不能为空", groups = { AddGroup.class, EditGroup.class })
private Long roomId;
/**
* 房间名称
*/
@NotBlank(message = "房间名称不能为空", groups = { AddGroup.class, EditGroup.class })
private String roomName;
/**
* 床位ID
*/
private Long bedId;
/**
* 床位名称
*/
private String bedName;
/**
* 违纪类型
*/
@NotBlank(message = "违纪类型不能为空", groups = { AddGroup.class, EditGroup.class })
private String violationType;
/**
* 违纪等级:1轻微 2一般 3严重 4特别严重
*/
@NotBlank(message = "违纪等级:1轻微 2一般 3严重 4特别严重不能为空", groups = { AddGroup.class, EditGroup.class })
private String violationLevel;
/**
* 违纪发生时间
*/
@NotNull(message = "违纪发生时间不能为空", groups = { AddGroup.class, EditGroup.class })
private Date violationTime;
/**
* 违纪行为描述
*/
@NotBlank(message = "违纪行为描述不能为空", groups = { AddGroup.class, EditGroup.class })
private String violationDescription;
/**
* 涉及其他学生id(逗号分隔)
*/
private String involvedStudents;
/**
* 附件OSS ID列表(逗号分隔)
*/
private String attachmentOssIds;
/**
* 删除标志(0代表存在 1代表删除)
*/
private String deleted;
/**
* 备注
*/
private String remark;
}
@@ -0,0 +1,213 @@
package org.dromara.xg.domain.bo;
import org.dromara.xg.domain.XgHolidayStay;
import org.dromara.common.mybatis.core.domain.BaseEntity;
import org.dromara.common.core.validate.AddGroup;
import org.dromara.common.core.validate.EditGroup;
import io.github.linpeilie.annotations.AutoMapper;
import lombok.Data;
import lombok.EqualsAndHashCode;
import jakarta.validation.constraints.*;
import java.util.Date;
import com.fasterxml.jackson.annotation.JsonFormat;
/**
* 假期留宿管理业务对象 xg_holiday_stay
*
* @author zlwu
* @date 2025-08-15
*/
@Data
@EqualsAndHashCode(callSuper = true)
@AutoMapper(target = XgHolidayStay.class, reverseConvertGenerate = false)
public class XgHolidayStayBo extends BaseEntity {
/**
* 主键ID
*/
@NotNull(message = "主键ID不能为空", groups = { EditGroup.class })
private Long id;
/**
* 删除标志(0代表存在 1代表删除)
*/
private Long deleted;
/**
* 学生ID,关联xg_student_msg.id
*/
@NotNull(message = "学生ID,关联xg_student_msg.id不能为空", groups = { AddGroup.class, EditGroup.class })
private Long studentId;
/**
* 学生姓名
*/
@NotBlank(message = "学生姓名不能为空", groups = { AddGroup.class, EditGroup.class })
private String studentName;
/**
* 学号
*/
@NotBlank(message = "学号不能为空", groups = { AddGroup.class, EditGroup.class })
private String studentNo;
/**
* 班级ID
*/
private Long classId;
/**
* 班级名称
*/
private String className;
/**
* 专业ID
*/
private Long majorId;
/**
* 专业名称
*/
private String majorName;
/**
* 学院ID
*/
private Long collegeId;
/**
* 学院名称
*/
private String collegeName;
/**
* 校区ID,关联xg_dorm_campus.id
*/
private Long campusId;
/**
* 校区名称
*/
private String campusName;
/**
* 宿舍区ID,关联xg_dorm_area.id
*/
private Long areaId;
/**
* 宿舍区名称
*/
private String areaName;
/**
* 宿舍楼ID,关联xg_dorm_building.id
*/
private Long buildingId;
/**
* 宿舍楼名称
*/
private String buildingName;
/**
* 房间ID,关联xg_dorm_room.id
*/
private Long roomId;
/**
* 房间名称
*/
private String roomName;
/**
* 床位ID,关联xg_dorm_bed.id
*/
private Long bedId;
/**
* 床位名称
*/
private String bedName;
/**
* 假期类型(寒假、暑假、春节假期、国庆假期等)
*/
@NotBlank(message = "假期类型(寒假、暑假、春节假期、国庆假期等)不能为空", groups = { AddGroup.class, EditGroup.class })
private String holidayType;
/**
* 申请留宿开始日期
*/
@NotNull(message = "申请留宿开始日期不能为空", groups = { AddGroup.class, EditGroup.class })
private Date applyStartDate;
/**
* 申请留宿结束日期
*/
@NotNull(message = "申请留宿结束日期不能为空", groups = { AddGroup.class, EditGroup.class })
private Date applyEndDate;
/**
* 留宿原因(必填)
*/
@NotBlank(message = "留宿原因(必填)不能为空", groups = { AddGroup.class, EditGroup.class })
private String stayReason;
/**
* 留宿原因类型(学习、实习、家庭困难、其他)
*/
private String stayReasonType;
/**
* 学生联系电话
*/
@NotBlank(message = "学生联系电话不能为空", groups = { AddGroup.class, EditGroup.class })
private String studentPhone;
/**
* 紧急联系人姓名
*/
@NotBlank(message = "紧急联系人姓名不能为空", groups = { AddGroup.class, EditGroup.class })
private String emergencyContact;
/**
* 紧急联系人电话
*/
@NotBlank(message = "紧急联系人电话不能为空", groups = { AddGroup.class, EditGroup.class })
private String emergencyPhone;
/**
* 家长同意(0否 1是)
*/
@NotBlank(message = "家长同意(0否 1是)不能为空", groups = { AddGroup.class, EditGroup.class })
private String parentConsent;
/**
* 附件OSS文件ID,多个用逗号分隔(申请材料、证明文件等)
*/
private String attachmentOssIds;
/**
* 扩展字段1
*/
private String extField1;
/**
* 扩展字段2
*/
private String extField2;
/**
* 扩展字段3
*/
private String extField3;
/**
* 备注信息
*/
private String remark;
}
@@ -517,7 +517,7 @@ public class XgStudentMsgBatchBo extends BaseEntity {
private String dormitoryRoom;
/**
* 扩展字段1
* 扩展字段1 扩展字段1 - 床位id
*/
private String extField1;
@@ -517,7 +517,7 @@ public class XgStudentMsgBo extends BaseEntity {
private String dormitoryRoom;
/**
* 扩展字段1
* 扩展字段1 扩展字段1 - 床位id
*/
private String extField1;
@@ -0,0 +1,183 @@
package org.dromara.xg.domain.vo;
import lombok.Data;
import java.util.Date;
import com.fasterxml.jackson.annotation.JsonFormat;
import org.dromara.xg.convert.StudentInfoExcelConvert;
import org.dromara.xg.domain.XgDormHygieneCheck;
import org.dromara.xg.domain.XgDormViolation;
import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
import cn.idev.excel.annotation.ExcelProperty;
import org.dromara.common.excel.annotation.ExcelDictFormat;
import org.dromara.common.excel.convert.ExcelDictConvert;
import io.github.linpeilie.annotations.AutoMapper;
import java.io.Serial;
import java.io.Serializable;
/**
* 宿舍卫生检查导出 视图对象 dorm_hygiene_check_export
*
* @author Lion Li
* @date 2025-01-29
*/
@Data
@ExcelIgnoreUnannotated
@AutoMapper(target = XgDormHygieneCheck.class)
public class DormHygieneCheckExportVo implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* 检查标题
*/
@ExcelProperty(value = "检查标题")
private String checkTitle;
/**
* 检查日期
*/
@ExcelProperty(value = "检查日期")
private String checkDate;
/**
* 检查员姓名
*/
@ExcelProperty(value = "检查员")
private String checkerName;
/**
* 检查类型
*/
@ExcelProperty(value = "检查类型")
private String checkTypeText;
/**
* 检查级别
*/
@ExcelProperty(value = "检查级别")
private String checkLevelText;
/**
* 校区名称
*/
@ExcelProperty(value = "校区")
private String campusName;
/**
* 宿舍区名称
*/
@ExcelProperty(value = "宿舍区")
private String areaName;
/**
* 宿舍楼名称
*/
@ExcelProperty(value = "宿舍楼")
private String buildingName;
/**
* 房间名称
*/
@ExcelProperty(value = "房间号")
private String roomName;
/**
* 宿舍总分
*/
@ExcelProperty(value = "宿舍总分")
private Double totalScore;
/**
* 卫生等级
*/
@ExcelProperty(value = "卫生等级")
private String hygieneGradeText;
/**
* 学号
*/
@ExcelProperty(value = "学号")
private String studentNo;
/**
* 学生姓名
*/
@ExcelProperty(value = "学生姓名")
private String studentName;
/**
* 班级名称
*/
@ExcelProperty(value = "班级")
private String className;
/**
* 专业名称
*/
@ExcelProperty(value = "专业")
private String majorName;
/**
* 学院名称
*/
@ExcelProperty(value = "学院")
private String collegeName;
/**
* 床位编号
*/
@ExcelProperty(value = "床位号")
private String bedCode;
/**
* 学生个人得分
*/
@ExcelProperty(value = "个人得分")
private Integer studentScore;
/**
* 出勤状态
*/
@ExcelProperty(value = "出勤状态")
private String attendanceStatusText;
/**
* 学生评级
*/
@ExcelProperty(value = "个人评级")
private String studentGradeText;
/**
* 是否为寝室长
*/
// @ExcelProperty(value = "是否寝室长")
// private String isResponsiblePersonText;
/**
* 评分备注
*/
// @ExcelProperty(value = "评分备注")
// private String scoreRemarks;
/**
* 改进意见
*/
// @ExcelProperty(value = "改进意见")
// private String improvementNotes;
/**
* 检查总结
*/
@ExcelProperty(value = "检查总结")
private String checkSummary;
/**
* 整改建议
*/
@ExcelProperty(value = "整改建议")
private String improvementSuggestions;
}
@@ -0,0 +1,156 @@
package org.dromara.xg.domain.vo;
import lombok.Data;
import com.fasterxml.jackson.annotation.JsonFormat;
import java.io.Serial;
import java.io.Serializable;
import java.util.Date;
/**
* 学生选择器选项视图对象
*
* @author zlwu
* @date 2025-08-15
*/
@Data
public class StudentOptionVo implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* 学生ID
*/
private Long id;
/**
* 学号
*/
private String studentNo;
/**
* 学生姓名
*/
private String name;
/**
* 性别:0-男,1-女
*/
private String gender;
/**
* 学院ID
*/
private Long collegeId;
/**
* 学院名称
*/
private String collegeName;
/**
* 专业ID
*/
private Long majorId;
/**
* 专业名称
*/
private String majorName;
/**
* 班级ID
*/
private Long classId;
/**
* 班级名称
*/
private String className;
/**
* 学生联系电话
*/
private String phone;
/**
* 宿舍信息
*/
private DormInfo dormInfo;
/**
* 基础字段 - 创建者
*/
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;
@Data
public static class DormInfo implements Serializable {
/**
* 校区ID
*/
private Long campusId;
/**
* 校区名称
*/
private String campusName;
/**
* 宿舍区ID
*/
private Long areaId;
/**
* 宿舍区名称
*/
private String areaName;
/**
* 宿舍楼ID
*/
private Long buildingId;
/**
* 宿舍楼名称
*/
private String buildingName;
/**
* 房间ID
*/
private Long roomId;
/**
* 房间名称
*/
private String roomName;
/**
* 床位ID
*/
private Long bedId;
/**
* 床位名称
*/
private String bedName;
}
}
@@ -0,0 +1,177 @@
package org.dromara.xg.domain.vo;
import java.util.Date;
import com.fasterxml.jackson.annotation.JsonFormat;
import org.dromara.xg.domain.XgDormHygieneCheck;
import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
import cn.idev.excel.annotation.ExcelProperty;
import org.dromara.common.excel.annotation.ExcelDictFormat;
import org.dromara.common.excel.convert.ExcelDictConvert;
import io.github.linpeilie.annotations.AutoMapper;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
import java.util.Date;
/**
* 宿舍卫生检查视图对象 xg_dorm_hygiene_check
*
* @author zlwu
* @date 2025-08-16
*/
@Data
@ExcelIgnoreUnannotated
@AutoMapper(target = XgDormHygieneCheck.class)
public class XgDormHygieneCheckVo implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* 主键ID
*/
@ExcelProperty(value = "主键ID")
private Long id;
/**
* 删除标志(0代表存在 1代表删除)
*/
@ExcelProperty(value = "删除标志", converter = ExcelDictConvert.class)
@ExcelDictFormat(readConverterExp = "0=代表存在,1=代表删除")
private Long deleted;
/**
* 检查标题
*/
@ExcelProperty(value = "检查标题")
private String checkTitle;
/**
* 检查日期
*/
@ExcelProperty(value = "检查日期")
private Date checkDate;
/**
* 检查员ID,关联sys_user.id
*/
@ExcelProperty(value = "检查员ID,关联sys_user.id")
private Long checkerId;
/**
* 检查员姓名
*/
@ExcelProperty(value = "检查员姓名")
private String checkerName;
/**
* 检查类型(1日常检查 2专项检查 3突击检查 4复查)
*/
@ExcelProperty(value = "检查类型", converter = ExcelDictConvert.class)
@ExcelDictFormat(dictType = "xg_dorm_hygiene_check_type")
private String checkType;
/**
* 检查级别(1宿管员 2学院 3学校)
*/
@ExcelProperty(value = "检查级别", converter = ExcelDictConvert.class)
@ExcelDictFormat(dictType = "xg_dorm_hygiene_check_level")
private String checkLevel;
/**
* 宿舍房间ID,关联xg_dorm_room.id
*/
@ExcelProperty(value = "宿舍房间ID,关联xg_dorm_room.id")
private Long roomId;
/**
* 房间编号
*/
@ExcelProperty(value = "房间编号")
private String roomCode;
/**
* 房间名称
*/
@ExcelProperty(value = "房间名称")
private String roomName;
/**
* 宿舍楼ID,关联xg_dorm_building.id
*/
@ExcelProperty(value = "宿舍楼ID,关联xg_dorm_building.id")
private Long buildingId;
/**
* 宿舍楼名称
*/
@ExcelProperty(value = "宿舍楼名称")
private String buildingName;
/**
* 宿舍区ID,关联xg_dorm_area.id
*/
@ExcelProperty(value = "宿舍区ID,关联xg_dorm_area.id")
private Long areaId;
/**
* 宿舍区名称
*/
@ExcelProperty(value = "宿舍区名称")
private String areaName;
/**
* 校区ID,关联xg_dorm_campus.id
*/
@ExcelProperty(value = "校区ID,关联xg_dorm_campus.id")
private Long campusId;
/**
* 校区名称
*/
@ExcelProperty(value = "校区名称")
private String campusName;
/**
* 宿舍总分(0-100分)
*/
@ExcelProperty(value = "宿舍总分", converter = ExcelDictConvert.class)
@ExcelDictFormat(readConverterExp = "0=-100分")
private Double totalScore;
/**
* 卫生等级(A优秀 B良好 C合格 D不合格)
*/
@ExcelProperty(value = "卫生等级", converter = ExcelDictConvert.class)
@ExcelDictFormat(dictType = "xg_dorm_hygiene_grade")
private String hygieneGrade;
/**
* 附件OSS ID列表,逗号分隔
*/
@ExcelProperty(value = "附件OSS ID列表,逗号分隔")
private String attachmentIds;
/**
* 检查总结
*/
@ExcelProperty(value = "检查总结")
private String checkSummary;
/**
* 整改建议
*/
@ExcelProperty(value = "整改建议")
private String improvementSuggestions;
/**
* 检查备注
*/
@ExcelProperty(value = "检查备注")
private String checkRemarks;
}
@@ -0,0 +1,157 @@
package org.dromara.xg.domain.vo;
import org.dromara.xg.domain.XgDormHygieneStudentScore;
import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
import cn.idev.excel.annotation.ExcelProperty;
import org.dromara.common.excel.annotation.ExcelDictFormat;
import org.dromara.common.excel.convert.ExcelDictConvert;
import io.github.linpeilie.annotations.AutoMapper;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
import java.util.Date;
/**
* 宿舍卫生检查学生评分视图对象 xg_dorm_hygiene_student_score
*
* @author zlwu
* @date 2025-08-16
*/
@Data
@ExcelIgnoreUnannotated
@AutoMapper(target = XgDormHygieneStudentScore.class)
public class XgDormHygieneStudentScoreVo implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* 主键ID
*/
@ExcelProperty(value = "主键ID")
private Long id;
/**
* 删除标志(0代表存在 1代表删除)
*/
@ExcelProperty(value = "删除标志", converter = ExcelDictConvert.class)
@ExcelDictFormat(readConverterExp = "0=代表存在,1=代表删除")
private Long deleted;
/**
* 卫生检查ID,关联xg_dorm_hygiene_check.id
*/
@ExcelProperty(value = "卫生检查ID,关联xg_dorm_hygiene_check.id")
private Long hygieneCheckId;
/**
* 学生ID,关联xg_student_msg.id
*/
@ExcelProperty(value = "学生ID,关联xg_student_msg.id")
private Long studentId;
/**
* 学号
*/
@ExcelProperty(value = "学号")
private String studentNo;
/**
* 学生姓名
*/
@ExcelProperty(value = "学生姓名")
private String studentName;
/**
* 班级ID
*/
@ExcelProperty(value = "班级ID")
private Long classId;
/**
* 班级名称
*/
@ExcelProperty(value = "班级名称")
private String className;
/**
* 专业ID
*/
@ExcelProperty(value = "专业ID")
private Long majorId;
/**
* 专业名称
*/
@ExcelProperty(value = "专业名称")
private String majorName;
/**
* 学院ID
*/
@ExcelProperty(value = "学院ID")
private Long collegeId;
/**
* 学院名称
*/
@ExcelProperty(value = "学院名称")
private String collegeName;
/**
* 床位ID,关联xg_dorm_bed.id
*/
@ExcelProperty(value = "床位ID,关联xg_dorm_bed.id")
private Long bedId;
/**
* 床位编号
*/
@ExcelProperty(value = "床位编号")
private String bedCode;
/**
* 学生个人得分(0-100分)
*/
@ExcelProperty(value = "学生个人得分", converter = ExcelDictConvert.class)
@ExcelDictFormat(readConverterExp = "0=-100分")
private Double studentScore;
/**
* 是否在寝(1在寝 2外出 3请假 4其他)
*/
@ExcelProperty(value = "是否在寝", converter = ExcelDictConvert.class)
@ExcelDictFormat(dictType = "xg_student_attendance_status")
private String attendanceStatus;
/**
* 学生评级(A优秀 B良好 C合格 D不合格)
*/
@ExcelProperty(value = "学生评级", converter = ExcelDictConvert.class)
@ExcelDictFormat(dictType = "xg_dorm_hygiene_grade")
private String studentGrade;
/**
* 是否为寝室长(0否 1是)
*/
@ExcelProperty(value = "是否为寝室长", converter = ExcelDictConvert.class)
@ExcelDictFormat(dictType = "sys_yesno")
private Long isResponsiblePerson;
/**
* 评分备注
*/
@ExcelProperty(value = "评分备注")
private String scoreRemarks;
/**
* 改进意见
*/
@ExcelProperty(value = "改进意见")
private String improvementNotes;
}
@@ -0,0 +1,206 @@
package org.dromara.xg.domain.vo;
import java.util.Date;
import com.fasterxml.jackson.annotation.JsonFormat;
import org.dromara.xg.convert.StudentInfoExcelConvert;
import org.dromara.xg.domain.XgDormViolation;
import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
import cn.idev.excel.annotation.ExcelProperty;
import org.dromara.common.excel.annotation.ExcelDictFormat;
import org.dromara.common.excel.convert.ExcelDictConvert;
import io.github.linpeilie.annotations.AutoMapper;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
import java.util.Date;
/**
* 宿舍违纪记录视图对象 xg_dorm_violation
*
* @author zlwu
* @date 2025-08-16
*/
@Data
@ExcelIgnoreUnannotated
@AutoMapper(target = XgDormViolation.class)
public class XgDormViolationExportVo implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* 违纪记录ID(主键)
*/
@ExcelProperty(value = "违纪记录ID")
private Long id;
/**
* 学生ID
*/
// @ExcelProperty(value = "学生ID")
// private Long studentId;
/**
* 学生姓名
*/
@ExcelProperty(value = "学生姓名")
private String studentName;
/**
* 学号
*/
@ExcelProperty(value = "学号")
private String studentNo;
/**
* 学院ID
*/
// @ExcelProperty(value = "学院ID")
// private Long collegeId;
/**
* 学院名称
*/
@ExcelProperty(value = "学院名称")
private String collegeName;
/**
* 专业ID
*/
// @ExcelProperty(value = "专业ID")
// private Long majorId;
/**
* 专业名称
*/
@ExcelProperty(value = "专业名称")
private String majorName;
/**
* 班级ID
*/
// @ExcelProperty(value = "班级ID")
// private Long classId;
/**
* 班级名称
*/
@ExcelProperty(value = "班级名称")
private String className;
/**
* 校区ID
*/
// @ExcelProperty(value = "校区ID")
// private Long campusId;
/**
* 校区名称
*/
@ExcelProperty(value = "校区名称")
private String campusName;
/**
* 宿舍区域ID
*/
// @ExcelProperty(value = "宿舍区域ID")
// private Long areaId;
/**
* 宿舍区域名称
*/
@ExcelProperty(value = "宿舍区域名称")
private String areaName;
/**
* 宿舍楼ID
*/
// @ExcelProperty(value = "宿舍楼ID")
// private Long buildingId;
/**
* 宿舍楼名称
*/
@ExcelProperty(value = "宿舍楼名称")
private String buildingName;
/**
* 宿舍房间ID
*/
// @ExcelProperty(value = "宿舍房间ID")
// private Long roomId;
/**
* 房间名称
*/
@ExcelProperty(value = "房间名称")
private String roomName;
/**
* 床位ID
*/
// @ExcelProperty(value = "床位ID")
// private Long bedId;
/**
* 床位名称
*/
@ExcelProperty(value = "床位名称")
private String bedName;
/**
* 违纪类型
*/
@ExcelProperty(value = "违纪类型", converter = ExcelDictConvert.class)
@ExcelDictFormat(dictType = "dorm_violation_type")
private String violationType;
/**
* 违纪等级:1轻微 2一般 3严重 4特别严重
*/
@ExcelProperty(value = "违纪等级", converter = ExcelDictConvert.class)
@ExcelDictFormat(dictType = "dorm_violation_level")
private String violationLevel;
/**
* 违纪发生时间
*/
@ExcelProperty(value = "违纪发生时间")
private Date violationTime;
/**
* 违纪行为描述
*/
@ExcelProperty(value = "违纪行为描述")
private String violationDescription;
/**
* 涉及其他学生id(逗号分隔)
*/
@ExcelProperty(value = "涉及其他学生id", converter = StudentInfoExcelConvert.class)
// @ExcelDictFormat(readConverterExp = "逗=号分隔")
private String involvedStudents;
/**
* 附件OSS ID列表(逗号分隔)
*/
// @ExcelProperty(value = "附件OSS ID列表", converter = ExcelDictConvert.class)
// @ExcelDictFormat(readConverterExp = "逗=号分隔")
// private String attachmentOssIds;
/**
* 删除标志(0代表存在 1代表删除)
*/
// @ExcelProperty(value = "删除标志", converter = ExcelDictConvert.class)
// @ExcelDictFormat(readConverterExp = "0=代表存在,1=代表删除")
// private String deleted;
/**
* 备注
*/
@ExcelProperty(value = "备注")
private String remark;
}
@@ -0,0 +1,96 @@
package org.dromara.xg.domain.vo;
import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
import cn.idev.excel.annotation.ExcelProperty;
import lombok.Data;
import org.dromara.common.excel.annotation.ExcelDictFormat;
import org.dromara.common.excel.convert.ExcelDictConvert;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import java.io.Serial;
import java.io.Serializable;
import java.util.Date;
/**
* 宿舍违纪记录导入视图对象 xg_dorm_violation_import
*
* @author zlwu
* @date 2025-01-31
*/
@Data
@ExcelIgnoreUnannotated
public class XgDormViolationImportVo implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* 学生姓名
*/
@NotBlank(message = "学生姓名不能为空")
@ExcelProperty(value = "学生姓名")
private String studentName;
/**
* 学号
*/
@NotBlank(message = "学号不能为空")
@ExcelProperty(value = "学号")
private String studentNo;
/**
* 学院名称
*/
@ExcelProperty(value = "学院名称")
private String collegeName;
/**
* 专业名称
*/
@ExcelProperty(value = "专业名称")
private String majorName;
/**
* 班级名称
*/
@ExcelProperty(value = "班级名称")
private String className;
/**
* 违纪类型
*/
@NotBlank(message = "违纪类型不能为空")
@ExcelProperty(value = "违纪类型", converter = ExcelDictConvert.class)
@ExcelDictFormat(dictType = "dorm_violation_type")
private String violationType;
/**
* 违纪等级
*/
@NotBlank(message = "违纪等级不能为空")
@ExcelProperty(value = "违纪等级", converter = ExcelDictConvert.class)
@ExcelDictFormat(dictType = "dorm_violation_level")
private String violationLevel;
/**
* 违纪发生时间
*/
@NotNull(message = "违纪发生时间不能为空")
@ExcelProperty(value = "违纪发生时间")
private Date violationTime;
/**
* 违纪行为描述
*/
@NotBlank(message = "违纪行为描述不能为空")
@ExcelProperty(value = "违纪行为描述")
private String violationDescription;
/**
* 备注
*/
@ExcelProperty(value = "备注")
private String remark;
}
@@ -0,0 +1,205 @@
package org.dromara.xg.domain.vo;
import java.util.Date;
import com.fasterxml.jackson.annotation.JsonFormat;
import org.dromara.xg.domain.XgDormViolation;
import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
import cn.idev.excel.annotation.ExcelProperty;
import org.dromara.common.excel.annotation.ExcelDictFormat;
import org.dromara.common.excel.convert.ExcelDictConvert;
import io.github.linpeilie.annotations.AutoMapper;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
import java.util.Date;
/**
* 宿舍违纪记录视图对象 xg_dorm_violation
*
* @author zlwu
* @date 2025-08-16
*/
@Data
@ExcelIgnoreUnannotated
@AutoMapper(target = XgDormViolation.class)
public class XgDormViolationVo implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* 违纪记录ID(主键)
*/
@ExcelProperty(value = "违纪记录ID", converter = ExcelDictConvert.class)
@ExcelDictFormat(readConverterExp = "主=键")
private Long id;
/**
* 学生ID
*/
@ExcelProperty(value = "学生ID")
private Long studentId;
/**
* 学生姓名
*/
@ExcelProperty(value = "学生姓名")
private String studentName;
/**
* 学号
*/
@ExcelProperty(value = "学号")
private String studentNo;
/**
* 学院ID
*/
@ExcelProperty(value = "学院ID")
private Long collegeId;
/**
* 学院名称
*/
@ExcelProperty(value = "学院名称")
private String collegeName;
/**
* 专业ID
*/
@ExcelProperty(value = "专业ID")
private Long majorId;
/**
* 专业名称
*/
@ExcelProperty(value = "专业名称")
private String majorName;
/**
* 班级ID
*/
@ExcelProperty(value = "班级ID")
private Long classId;
/**
* 班级名称
*/
@ExcelProperty(value = "班级名称")
private String className;
/**
* 校区ID
*/
@ExcelProperty(value = "校区ID")
private Long campusId;
/**
* 校区名称
*/
@ExcelProperty(value = "校区名称")
private String campusName;
/**
* 宿舍区域ID
*/
@ExcelProperty(value = "宿舍区域ID")
private Long areaId;
/**
* 宿舍区域名称
*/
@ExcelProperty(value = "宿舍区域名称")
private String areaName;
/**
* 宿舍楼ID
*/
@ExcelProperty(value = "宿舍楼ID")
private Long buildingId;
/**
* 宿舍楼名称
*/
@ExcelProperty(value = "宿舍楼名称")
private String buildingName;
/**
* 宿舍房间ID
*/
@ExcelProperty(value = "宿舍房间ID")
private Long roomId;
/**
* 房间名称
*/
@ExcelProperty(value = "房间名称")
private String roomName;
/**
* 床位ID
*/
@ExcelProperty(value = "床位ID")
private Long bedId;
/**
* 床位名称
*/
@ExcelProperty(value = "床位名称")
private String bedName;
/**
* 违纪类型
*/
@ExcelProperty(value = "违纪类型", converter = ExcelDictConvert.class)
@ExcelDictFormat(dictType = "dorm_violation_type")
private String violationType;
/**
* 违纪等级:1轻微 2一般 3严重 4特别严重
*/
@ExcelProperty(value = "违纪等级:1轻微 2一般 3严重 4特别严重", converter = ExcelDictConvert.class)
@ExcelDictFormat(dictType = "dorm_violation_level")
private String violationLevel;
/**
* 违纪发生时间
*/
@ExcelProperty(value = "违纪发生时间")
private Date violationTime;
/**
* 违纪行为描述
*/
@ExcelProperty(value = "违纪行为描述")
private String violationDescription;
/**
* 涉及其他学生id(逗号分隔)
*/
@ExcelProperty(value = "涉及其他学生id", converter = ExcelDictConvert.class)
@ExcelDictFormat(readConverterExp = "逗=号分隔")
private String involvedStudents;
/**
* 附件OSS ID列表(逗号分隔)
*/
@ExcelProperty(value = "附件OSS ID列表", converter = ExcelDictConvert.class)
@ExcelDictFormat(readConverterExp = "逗=号分隔")
private String attachmentOssIds;
/**
* 删除标志(0代表存在 1代表删除)
*/
@ExcelProperty(value = "删除标志", converter = ExcelDictConvert.class)
@ExcelDictFormat(readConverterExp = "0=代表存在,1=代表删除")
private String deleted;
/**
* 备注
*/
@ExcelProperty(value = "备注")
private String remark;
}
@@ -0,0 +1,250 @@
package org.dromara.xg.domain.vo;
import java.util.Date;
import com.fasterxml.jackson.annotation.JsonFormat;
import org.dromara.xg.domain.XgHolidayStay;
import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
import cn.idev.excel.annotation.ExcelProperty;
import org.dromara.common.excel.annotation.ExcelDictFormat;
import org.dromara.common.excel.convert.ExcelDictConvert;
import io.github.linpeilie.annotations.AutoMapper;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
import java.util.Date;
/**
* 假期留宿管理视图对象 xg_holiday_stay
*
* @author zlwu
* @date 2025-08-15
*/
@Data
@ExcelIgnoreUnannotated
@AutoMapper(target = XgHolidayStay.class)
public class XgHolidayStayVo implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* 主键ID
*/
@ExcelProperty(value = "主键ID")
private Long id;
/**
* 删除标志(0代表存在 1代表删除)
*/
@ExcelProperty(value = "删除标志", converter = ExcelDictConvert.class)
@ExcelDictFormat(readConverterExp = "0=代表存在,1=代表删除")
private Long deleted;
/**
* 学生ID,关联xg_student_msg.id
*/
@ExcelProperty(value = "学生ID,关联xg_student_msg.id")
private Long studentId;
/**
* 学生姓名
*/
@ExcelProperty(value = "学生姓名")
private String studentName;
/**
* 学号
*/
@ExcelProperty(value = "学号")
private String studentNo;
/**
* 班级ID
*/
@ExcelProperty(value = "班级ID")
private Long classId;
/**
* 班级名称
*/
@ExcelProperty(value = "班级名称")
private String className;
/**
* 专业ID
*/
@ExcelProperty(value = "专业ID")
private Long majorId;
/**
* 专业名称
*/
@ExcelProperty(value = "专业名称")
private String majorName;
/**
* 学院ID
*/
@ExcelProperty(value = "学院ID")
private Long collegeId;
/**
* 学院名称
*/
@ExcelProperty(value = "学院名称")
private String collegeName;
/**
* 校区ID,关联xg_dorm_campus.id
*/
@ExcelProperty(value = "校区ID,关联xg_dorm_campus.id")
private Long campusId;
/**
* 校区名称
*/
@ExcelProperty(value = "校区名称")
private String campusName;
/**
* 宿舍区ID,关联xg_dorm_area.id
*/
@ExcelProperty(value = "宿舍区ID,关联xg_dorm_area.id")
private Long areaId;
/**
* 宿舍区名称
*/
@ExcelProperty(value = "宿舍区名称")
private String areaName;
/**
* 宿舍楼ID,关联xg_dorm_building.id
*/
@ExcelProperty(value = "宿舍楼ID,关联xg_dorm_building.id")
private Long buildingId;
/**
* 宿舍楼名称
*/
@ExcelProperty(value = "宿舍楼名称")
private String buildingName;
/**
* 房间ID,关联xg_dorm_room.id
*/
@ExcelProperty(value = "房间ID,关联xg_dorm_room.id")
private Long roomId;
/**
* 房间名称
*/
@ExcelProperty(value = "房间名称")
private String roomName;
/**
* 床位ID,关联xg_dorm_bed.id
*/
@ExcelProperty(value = "床位ID,关联xg_dorm_bed.id")
private Long bedId;
/**
* 床位名称
*/
@ExcelProperty(value = "床位名称")
private String bedName;
/**
* 假期类型(寒假、暑假、春节假期、国庆假期等)
*/
@ExcelProperty(value = "假期类型", converter = ExcelDictConvert.class)
@ExcelDictFormat(dictType = "xg_holiday_type")
private String holidayType;
/**
* 申请留宿开始日期
*/
@ExcelProperty(value = "申请留宿开始日期")
private Date applyStartDate;
/**
* 申请留宿结束日期
*/
@ExcelProperty(value = "申请留宿结束日期")
private Date applyEndDate;
/**
* 留宿原因(必填)
*/
@ExcelProperty(value = "留宿原因", converter = ExcelDictConvert.class)
@ExcelDictFormat(readConverterExp = "必=填")
private String stayReason;
/**
* 留宿原因类型(学习、实习、家庭困难、其他)
*/
@ExcelProperty(value = "留宿原因类型", converter = ExcelDictConvert.class)
@ExcelDictFormat(dictType = "xg_stay_reason_type")
private String stayReasonType;
/**
* 学生联系电话
*/
@ExcelProperty(value = "学生联系电话")
private String studentPhone;
/**
* 紧急联系人姓名
*/
@ExcelProperty(value = "紧急联系人姓名")
private String emergencyContact;
/**
* 紧急联系人电话
*/
@ExcelProperty(value = "紧急联系人电话")
private String emergencyPhone;
/**
* 家长同意(0否 1是)
*/
@ExcelProperty(value = "家长同意", converter = ExcelDictConvert.class)
@ExcelDictFormat(dictType = "sys_yesno")
private String parentConsent;
/**
* 附件OSS文件ID,多个用逗号分隔(申请材料、证明文件等)
*/
@ExcelProperty(value = "附件OSS文件ID,多个用逗号分隔", converter = ExcelDictConvert.class)
@ExcelDictFormat(readConverterExp = "申=请材料、证明文件等")
private String attachmentOssIds;
/**
* 扩展字段1
*/
@ExcelProperty(value = "扩展字段1")
private String extField1;
/**
* 扩展字段2
*/
@ExcelProperty(value = "扩展字段2")
private String extField2;
/**
* 扩展字段3
*/
@ExcelProperty(value = "扩展字段3")
private String extField3;
/**
* 备注信息
*/
@ExcelProperty(value = "备注信息")
private String remark;
}
@@ -623,7 +623,7 @@ public class XgStudentMsgBatchVo implements Serializable {
private String dormitoryRoom;
/**
* 扩展字段1
* 扩展字段1 扩展字段1 - 床位id
*/
@ExcelProperty(value = "扩展字段1")
private String extField1;
@@ -623,7 +623,7 @@ public class XgStudentMsgVo implements Serializable {
private String dormitoryRoom;
/**
* 扩展字段1
* 扩展字段1 扩展字段1 - 床位id
*/
@ExcelProperty(value = "扩展字段1")
private String extField1;
@@ -129,4 +129,122 @@ public interface XgDormBedMapper extends BaseMapperPlus<XgDormBed, XgDormBedVo>
""")
List<XgDormBedDetailVo> selectBedDetailsByBuildingId(@Param("buildingId") Long buildingId);
/**
* 查询指定房间中属于指定学院的床位详细信息列表(包含学生信息)
*
* @param roomId 房间ID
* @param collegeId 学院ID
* @return 床位详细信息列表
*/
@Select("""
SELECT
b.id,
b.bed_code,
b.bed_name,
b.room_id,
r.room_name,
b.bed_type,
b.bed_status,
b.remark as bed_remark,
b.create_by,
b.create_time,
b.update_by,
b.update_time,
bs.id as assignment_id,
bs.assign_time,
bs.status as assignment_status,
bs.college_id,
college_dept.dept_name as college_name,
bs.major_id,
major_dept.dept_name as major_name,
bs.class_id,
class_dept.dept_name as class_name,
c.class_code,
c.grade,
bs.student_id,
s.student_no,
s.name as student_name,
s.gender as student_gender,
s.phone as student_phone,
s.id_card as student_id_card
FROM xg_dorm_bed b
LEFT JOIN xg_dorm_room r ON b.room_id = r.id
INNER JOIN xg_dorm_bed_student bs ON b.id = bs.bed_id AND bs.status = '0' AND bs.deleted = '0'
LEFT JOIN sys_dept college_dept ON bs.college_id = college_dept.dept_id AND college_dept.del_flag = '0'
LEFT JOIN sys_dept major_dept ON bs.major_id = major_dept.dept_id AND major_dept.del_flag = '0'
LEFT JOIN sys_dept class_dept ON bs.class_id = class_dept.dept_id AND class_dept.del_flag = '0'
LEFT JOIN xg_class_msg c ON bs.class_id = c.id AND c.deleted = 0
LEFT JOIN xg_student_msg s ON bs.student_id = s.id AND s.deleted = 0
WHERE b.room_id = #{roomId}
AND bs.college_id = #{collegeId}
AND b.deleted = '0'
ORDER BY b.bed_code
""")
List<XgDormBedDetailVo> selectBedDetailsByRoomIdAndCollegeId(@Param("roomId") Long roomId,
@Param("collegeId") Long collegeId);
/**
* 查询指定房间中属于指定班级的床位详细信息列表(包含学生信息)
*
* @param roomId 房间ID
* @param classId 班级ID
* @return 床位详细信息列表
*/
@Select("""
SELECT
b.id,
b.bed_code,
b.bed_name,
b.room_id,
r.room_name,
b.bed_type,
b.bed_status,
b.remark as bed_remark,
b.create_by,
b.create_time,
b.update_by,
b.update_time,
bs.id as assignment_id,
bs.assign_time,
bs.status as assignment_status,
bs.college_id,
college_dept.dept_name as college_name,
bs.major_id,
major_dept.dept_name as major_name,
bs.class_id,
class_dept.dept_name as class_name,
c.class_code,
c.grade,
bs.student_id,
s.student_no,
s.name as student_name,
s.gender as student_gender,
s.phone as student_phone,
s.id_card as student_id_card
FROM xg_dorm_bed b
LEFT JOIN xg_dorm_room r ON b.room_id = r.id
INNER JOIN xg_dorm_bed_student bs ON b.id = bs.bed_id AND bs.status = '0' AND bs.deleted = '0'
LEFT JOIN sys_dept college_dept ON bs.college_id = college_dept.dept_id AND college_dept.del_flag = '0'
LEFT JOIN sys_dept major_dept ON bs.major_id = major_dept.dept_id AND major_dept.del_flag = '0'
LEFT JOIN sys_dept class_dept ON bs.class_id = class_dept.dept_id AND class_dept.del_flag = '0'
LEFT JOIN xg_class_msg c ON bs.class_id = c.id AND c.deleted = 0
LEFT JOIN xg_student_msg s ON bs.student_id = s.id AND s.deleted = 0
WHERE b.room_id = #{roomId}
AND bs.class_id = #{classId}
AND b.deleted = '0'
ORDER BY b.bed_code
""")
List<XgDormBedDetailVo> selectBedDetailsByRoomIdAndClassId(@Param("roomId") Long roomId,
@Param("classId") Long classId);
}
@@ -3,6 +3,11 @@ package org.dromara.xg.mapper;
import org.dromara.xg.domain.XgDormBedStudent;
import org.dromara.xg.domain.vo.XgDormBedStudentVo;
import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import java.util.List;
import java.util.Map;
/**
* 床位学生分配关系Mapper接口
@@ -12,4 +17,175 @@ import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
*/
public interface XgDormBedStudentMapper extends BaseMapperPlus<XgDormBedStudent, XgDormBedStudentVo> {
/**
* 查询班级已入住床位详情(通过SQL关联查询,按楼栋、房间、床位排序)
*
* @param classId 班级ID
* @return 班级已入住床位详情列表
*/
@Select("""
SELECT
bs.bed_id,
bs.student_id,
bs.class_id,
bs.college_id,
-- 床位信息
b.bed_name,
b.bed_type,
b.bed_code,
-- 房间信息
r.id as room_id,
r.room_name,
r.room_code,
-- 楼栋信息
building.id as building_id,
building.building_name,
building.building_code,
building.building_type,
-- 宿舍区信息
area.id as area_id,
area.area_name,
-- 校区信息
campus.id as campus_id,
campus.campus_name,
-- 学生信息
s.student_no,
s.name as student_name,
s.gender,
s.phone,
s.id_card
FROM xg_dorm_bed_student bs
INNER JOIN xg_dorm_bed b ON bs.bed_id = b.id AND b.deleted = '0'
INNER JOIN xg_dorm_room r ON b.room_id = r.id AND r.deleted = '0'
INNER JOIN xg_dorm_building building ON r.building_id = building.id AND building.deleted = '0'
INNER JOIN xg_dorm_area area ON building.area_id = area.id AND area.deleted = '0'
INNER JOIN xg_dorm_campus campus ON area.campus_id = campus.id AND campus.deleted = '0'
INNER JOIN xg_student_msg s ON bs.student_id = s.id AND s.deleted = 0
WHERE bs.class_id = #{classId}
AND bs.student_id IS NOT NULL
AND bs.status = '0'
AND bs.deleted = '0'
AND s.student_status = '1'
ORDER BY
campus.campus_name,
area.area_name,
building.building_code,
r.room_code,
b.bed_code
""")
List<Map<String, Object>> selectClassOccupiedBedDetails(@Param("classId") Long classId);
/**
* 查询班级未分配学生床位详情(通过SQL关联查询,按楼栋、房间、床位排序)
*
* @param classId 班级ID
* @return 班级未分配学生床位详情列表
*/
@Select("""
SELECT
bs.bed_id,
bs.class_id,
bs.college_id,
-- 床位信息
b.bed_name,
b.bed_type,
b.bed_code,
-- 房间信息
r.id as room_id,
r.room_name,
r.room_code,
-- 楼栋信息
building.id as building_id,
building.building_name,
building.building_code,
building.building_type,
-- 宿舍区信息
area.id as area_id,
area.area_name,
-- 校区信息
campus.id as campus_id,
campus.campus_name
FROM xg_dorm_bed_student bs
INNER JOIN xg_dorm_bed b ON bs.bed_id = b.id AND b.deleted = '0' AND b.bed_status = '1'
INNER JOIN xg_dorm_room r ON b.room_id = r.id AND r.deleted = '0'
INNER JOIN xg_dorm_building building ON r.building_id = building.id AND building.deleted = '0'
INNER JOIN xg_dorm_area area ON building.area_id = area.id AND area.deleted = '0'
INNER JOIN xg_dorm_campus campus ON area.campus_id = campus.id AND campus.deleted = '0'
WHERE bs.class_id = #{classId}
AND bs.student_id IS NULL
AND bs.status = '0'
AND bs.deleted = '0'
ORDER BY
campus.campus_name,
area.area_name,
building.building_code,
r.room_code,
b.bed_code
""")
List<Map<String, Object>> selectClassUnoccupiedBedDetails(@Param("classId") Long classId);
/**
* 根据房间ID查询住在当前房间的所有学生信息
* 包含学生姓名、学号、性别、学院名称、专业名称、班级名称、床位编码、床位ID
*
* @param roomId 房间ID
* @return 房间学生信息列表
*/
@Select("""
SELECT
bs.student_id,
bs.bed_id,
-- 学生基本信息
s.student_no,
s.name as student_name,
s.gender,
-- 床位信息
b.bed_name,
b.bed_code,
-- 班级信息
c.class_name,
-- 学院信息
d.dept_name as college_name,
-- 专业信息(通过班级关联)
major.dept_name as major_name
FROM xg_dorm_bed_student bs
INNER JOIN xg_dorm_bed b ON bs.bed_id = b.id AND b.deleted = '0'
INNER JOIN xg_student_msg s ON bs.student_id = s.id AND s.deleted = 0
LEFT JOIN xg_class_msg c ON s.class_id = c.id AND c.deleted = 0
LEFT JOIN sys_dept d ON c.college_id = d.dept_id AND d.del_flag = '0'
LEFT JOIN sys_dept major ON c.major_id = major.dept_id AND major.del_flag = '0'
WHERE b.room_id = #{roomId}
AND bs.student_id IS NOT NULL
AND bs.status = '0'
AND bs.deleted = '0'
AND s.student_status = '1'
ORDER BY b.bed_code, s.student_no
""")
List<Map<String, Object>> selectRoomStudents(@Param("roomId") Long roomId);
}
@@ -0,0 +1,26 @@
package org.dromara.xg.mapper;
import org.dromara.xg.domain.XgDormHygieneCheck;
import org.dromara.xg.domain.bo.XgDormHygieneCheckBo;
import org.dromara.xg.domain.vo.DormHygieneCheckExportVo;
import org.dromara.xg.domain.vo.XgDormHygieneCheckVo;
import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
import java.util.List;
/**
* 宿舍卫生检查Mapper接口
*
* @author zlwu
* @date 2025-08-16
*/
public interface XgDormHygieneCheckMapper extends BaseMapperPlus<XgDormHygieneCheck, XgDormHygieneCheckVo> {
/**
* 查询宿舍卫生检查导出列表(包含学生卫生情况)
*
* @param bo 查询条件
* @return 导出数据列表
*/
List<DormHygieneCheckExportVo> selectExportList(XgDormHygieneCheckBo bo);
}
@@ -0,0 +1,15 @@
package org.dromara.xg.mapper;
import org.dromara.xg.domain.XgDormHygieneStudentScore;
import org.dromara.xg.domain.vo.XgDormHygieneStudentScoreVo;
import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
/**
* 宿舍卫生检查学生评分Mapper接口
*
* @author zlwu
* @date 2025-08-16
*/
public interface XgDormHygieneStudentScoreMapper extends BaseMapperPlus<XgDormHygieneStudentScore, XgDormHygieneStudentScoreVo> {
}
@@ -0,0 +1,44 @@
package org.dromara.xg.mapper;
import org.dromara.xg.domain.XgDormViolation;
import org.dromara.xg.domain.vo.XgDormViolationVo;
import org.dromara.xg.domain.vo.StudentOptionVo;
import org.dromara.xg.domain.bo.StudentOptionBo;
import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.apache.ibatis.annotations.Param;
/**
* 宿舍违纪记录Mapper接口
*
* @author zlwu
* @date 2025-08-16
*/
public interface XgDormViolationMapper extends BaseMapperPlus<XgDormViolation, XgDormViolationVo> {
/**
* 查询学生选择器选项列表(支持按学号、姓名检索)
*
* @param page 分页参数
* @param bo 查询条件
* @return 学生选项列表
*/
Page<StudentOptionVo> selectStudentOptions(IPage<?> page, @Param("bo") StudentOptionBo bo);
/**
* 根据学生ID获取学生详细信息
*
* @param studentId 学生ID
* @return 学生详细信息
*/
StudentOptionVo selectStudentById(@Param("studentId") Long studentId);
/**
* 根据学号获取学生详细信息
*
* @param studentNo 学号
* @return 学生详细信息
*/
StudentOptionVo selectStudentByStudentNo(@Param("studentNo") String studentNo);
}
@@ -0,0 +1,37 @@
package org.dromara.xg.mapper;
import org.dromara.xg.domain.XgHolidayStay;
import org.dromara.xg.domain.vo.XgHolidayStayVo;
import org.dromara.xg.domain.vo.StudentOptionVo;
import org.dromara.xg.domain.bo.StudentOptionBo;
import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.apache.ibatis.annotations.Param;
/**
* 假期留宿管理Mapper接口
*
* @author zlwu
* @date 2025-08-15
*/
public interface XgHolidayStayMapper extends BaseMapperPlus<XgHolidayStay, XgHolidayStayVo> {
/**
* 查询学生选择器选项列表(支持按学号、姓名检索)
*
* @param page 分页参数
* @param bo 查询条件
* @return 学生选项列表
*/
Page<StudentOptionVo> selectStudentOptions(IPage<?> page, @Param("bo") StudentOptionBo bo);
/**
* 测试查询:简化版本,只查询学生基本信息
*
* @param page 分页参数
* @param bo 查询条件
* @return 学生选项列表
*/
Page<StudentOptionVo> selectStudentOptionsSimple(IPage<?> page, @Param("bo") StudentOptionBo bo);
}
@@ -19,71 +19,87 @@ import java.util.Map;
*/
public interface XgStudentMsgMapper extends BaseMapperPlus<XgStudentMsg, XgStudentMsgVo> {
/**
* 根据组织ID列表分页查询学生信息 用于导出
*
* @param page 分页参数
* @param queryWrapper 查询条件
* @param deptIds 组织ID列表
* @return 学生信息分页结果
*/
List<XgStudentMsgExportVo> queryPageListExportByDeptId(
@Param("ew") LambdaQueryWrapper<XgStudentMsg> queryWrapper,
@Param("deptIds") List<Long> deptIds);
/**
* 根据组织ID列表分页查询学生信息 用于导出
*
* @param page 分页参数
* @param queryWrapper 查询条件
* @param deptIds 组织ID列表
* @return 学生信息分页结果
*/
List<XgStudentMsgExportVo> queryPageListExportByDeptId(
@Param("ew") LambdaQueryWrapper<XgStudentMsg> queryWrapper,
@Param("deptIds") List<Long> deptIds);
/**
* 根据组织ID列表分页查询学生信息
*
* @param page 分页参数
* @param queryWrapper 查询条件
* @param deptIds 组织ID列表
* @return 学生信息分页结果
*/
Page<XgStudentMsgVo> selectPageByDeptIds(@Param("page") Page<XgStudentMsgVo> page,
@Param("ew") LambdaQueryWrapper<XgStudentMsg> queryWrapper,
@Param("deptIds") List<Long> deptIds);
/**
* 根据组织ID列表分页查询学生信息
*
* @param page 分页参数
* @param queryWrapper 查询条件
* @param deptIds 组织ID列表
* @return 学生信息分页结果
*/
Page<XgStudentMsgVo> selectPageByDeptIds(@Param("page") Page<XgStudentMsgVo> page,
@Param("ew") LambdaQueryWrapper<XgStudentMsg> queryWrapper,
@Param("deptIds") List<Long> deptIds);
/**
* 根据班级ID和姓名查询学生信息列表
*
* @param classId 班级ID
* @param name 学生姓名(模糊查询)
* @return 学生信息列表
*/
List<XgStudentMsgVo> selectStudentsByClassId(@Param("classId") String classId, @Param("name") String name);
/**
* 根据班级ID和姓名查询学生信息列表
*
* @param classId 班级ID
* @param name 学生姓名(模糊查询)
* @return 学生信息列表
*/
List<XgStudentMsgVo> selectStudentsByClassId(@Param("classId") String classId, @Param("name") String name);
/**
* 根据学生ID查询班主任ID
*
* @param studentId 学生ID
* @return 班主任ID
*/
Long selectClassTeacherIdByStudentId(@Param("studentId") Long studentId);
/**
* 根据学生ID查询班主任ID
*
* @param studentId 学生ID
* @return 班主任ID
*/
Long selectClassTeacherIdByStudentId(@Param("studentId") Long studentId);
/**
* 根据学生ID查询学院ID
*
* @param studentId 学生ID
* @return 学院ID
*/
Long selectCollegeIdByStudentId(@Param("studentId") Long studentId);
/**
* 根据学生ID查询学院ID
*
* @param studentId 学生ID
* @return 学院ID
*/
Long selectCollegeIdByStudentId(@Param("studentId") Long studentId);
/**
* 根据学院ID和角色Key查询具备该角色的用户列表
*
* @param collegeId 学院ID
* @param roleKey 角色Key
* @return 用户ID列表
*/
List<Long> selectUserIdsByCollegeIdAndRoleKey(@Param("collegeId") Long collegeId,
@Param("roleKey") String roleKey);
/**
* 根据学院ID和角色Key查询具备该角色的用户列表
*
* @param collegeId 学院ID
* @param roleKey 角色Key
* @return 用户ID列表
*/
List<Long> selectUserIdsByCollegeIdAndRoleKey(@Param("collegeId") Long collegeId,
@Param("roleKey") String roleKey);
/**
* 查询二级学院下的学院、专业、班级学生统计信息
*
* @param secondaryCollegeId 二级学院ID
* @return 学生统计信息列表
*/
List<Map<String, Object>> getCollegeStudentStats(@Param("secondaryCollegeId") Long secondaryCollegeId);
/**
* 查询二级学院下的学院、专业、班级学生统计信息
*
* @param secondaryCollegeId 二级学院ID
* @return 学生统计信息列表
*/
List<Map<String, Object>> getCollegeStudentStats(@Param("secondaryCollegeId") Long secondaryCollegeId);
/**
* 查询二级学院下的学院、专业、班级学生统计信息(按床位分配统计)
*
* @param secondaryCollegeId 二级学院ID
* @return 学生统计信息列表
*/
List<Map<String, Object>> getCollegeStudentStatsByClass(@Param("secondaryCollegeId") Long secondaryCollegeId);
/**
* 查询二级学院下的学院床位分配统计信息(基于college_id统计)
*
* @param secondaryCollegeId 二级学院ID
* @return 学院床位分配统计信息列表
*/
List<Map<String, Object>> getCollegeBedAssignmentStats(@Param("secondaryCollegeId") Long secondaryCollegeId);
}
@@ -75,6 +75,14 @@ public interface IXgDormBedService {
*/
List<XgDormBedDetailVo> queryBedDetailsByRoomId(Long roomId);
/**
* 查询当前用户所在学院的指定房间床位详细信息列表(包含学生信息)
*
* @param roomId 房间ID
* @return 床位详细信息列表
*/
List<XgDormBedDetailVo> queryBedDetailsByRoomIdForCurrentUserCollege(Long roomId);
/**
* 查询指定宿舍楼的床位详细信息列表(包含学生信息)
*
@@ -82,4 +90,13 @@ public interface IXgDormBedService {
* @return 床位详细信息列表
*/
List<XgDormBedDetailVo> queryBedDetailsByBuildingId(Long buildingId);
/**
* 查询指定房间中属于指定班级的床位详细信息列表(包含学生信息)
*
* @param roomId 房间ID
* @param classId 班级ID
* @return 床位详细信息列表
*/
List<XgDormBedDetailVo> queryBedDetailsByRoomIdAndClassId(Long roomId, Long classId);
}
@@ -3,12 +3,17 @@ package org.dromara.xg.service;
import org.dromara.xg.domain.vo.XgDormBedStudentVo;
import org.dromara.xg.domain.bo.XgDormBedStudentBo;
import org.dromara.xg.domain.bo.XgDormBedBatchAllocateBo;
import org.dromara.xg.domain.bo.XgDormBedBatchAllocateToClassBo;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.mybatis.core.page.PageQuery;
import java.util.Collection;
import java.util.List;
import org.dromara.xg.domain.bo.XgDormBedBatchRecallBo;
import org.dromara.xg.domain.vo.DormBuildingTreeVo;
import org.dromara.xg.domain.bo.XgDormSelectiveAllocationBo;
/**
* 床位学生分配关系Service接口
*
@@ -75,4 +80,166 @@ public interface IXgDormBedStudentService {
*/
Boolean batchAllocateBedsToCollege(
XgDormBedBatchAllocateBo bo);
/**
* 批量分配床位给班级
*
* @param bo 批量分配给班级请求参数
* @return 是否分配成功
*/
Boolean batchAllocateBedsToClass(XgDormBedBatchAllocateToClassBo bo);
/**
* 批量收回宿舍床位
*
* @param bo 批量收回请求参数
* @return 是否成功
*/
Boolean batchRecallBeds(XgDormBedBatchRecallBo bo);
/**
* 批量回收班级分配床位(保留学院分配)
*
* @param bo 批量回收请求参数
* @return 是否成功
*/
Boolean batchRecallClassAllocation(XgDormBedBatchRecallBo bo);
/**
* 获取当前用户二级学院的宿舍楼树形结构
* 校区-宿舍区-宿舍楼三级结构,校区和宿舍区不可选,只有宿舍楼可以选择
*
* @return 宿舍楼树形结构数据
*/
List<DormBuildingTreeVo> getCurrentUserCollegeDormBuildingTree();
/**
* 获取班主任管理的班级宿舍楼树形结构
* 只显示班主任管理班级分配到的宿舍楼
*
* @param classId 班级ID,可为空;为空时取当前用户管理的首个班级
* @return 宿舍楼树形结构数据
*/
List<DormBuildingTreeVo> getClassTeacherDormTree(Long classId);
/**
* 获取班主任管理班级的房间床位详情(带学生信息)
*
* @param buildingId 宿舍楼ID,为空则查询所有楼栋
* @param classId 班级ID,可为空
* @return 房间床位详情列表
*/
List<Object> getClassTeacherBedDetails(Long buildingId, Long classId);
/**
* 获取班主任管理的未分配床位学生列表
*
* @param classId 班级ID,可为空
* @return 未分配床位的学生列表
*/
List<Object> getClassTeacherUnallocatedStudents(Long classId);
/**
* 班主任一键随机分配床位
*
* @param buildingId 宿舍楼ID,为空则全部分配
* @param classId 班级ID,可为空
* @return 是否分配成功
*/
Boolean classTeacherRandomAllocation(Long buildingId, Long classId);
/**
* 班主任一键按学号分配床位
*
* @param buildingId 宿舍楼ID,为空则全部分配
* @param classId 班级ID,可为空
* @return 是否分配成功
*/
Boolean classTeacherStudentNoAllocation(Long buildingId, Long classId);
/**
* 班主任选择性分配床位(弹窗模式)
*
* @param allocationParams 分配参数(含班级ID等)
* @param classId 班级ID,可为空
* @return 是否分配成功
*/
Boolean classTeacherSelectiveAllocation(XgDormSelectiveAllocationBo allocationParams, Long classId);
/**
* 班主任一键收回床位
*
* @param buildingId 宿舍楼ID,为空则全部收回
* @param classId 班级ID,可为空
* @return 是否收回成功
*/
Boolean classTeacherRecallBeds(Long buildingId, Long classId);
/**
* 班主任收回选中床位
*
* @param bedIds 床位ID列表
* @param classId 班级ID
* @return 是否收回成功
*/
Boolean classTeacherRecallSelectedBeds(List<Long> bedIds, Long classId);
/**
* 班主任批量退宿
*
* @param bedIds 床位ID列表
* @param classId 班级ID
* @return 是否退宿成功
*/
Boolean classTeacherStayawaySelectedBeds(List<Long> bedIds, Long classId);
/**
* 班主任床位互换
* 将两个学生的床位进行互换
*
* @param sourceStudentId 源学生ID
* @param targetStudentId 目标学生ID
* @param classId 班级ID
* @return 是否互换成功
*/
Boolean classTeacherExchangeBeds(Long sourceStudentId, Long targetStudentId, Long classId);
/**
* 班主任床位移动
* 将学生从当前床位移动到指定的空闲床位
*
* @param sourceBedId 源床位ID
* @param targetBedId 目标床位ID
* @param classId 班级ID
* @return 是否移动成功
*/
Boolean classTeacherMoveBed(Long sourceStudentId, Long targetBedId, Long classId);
/**
* 获取班级所有已入住宿舍的学生床位信息
* 包含床位信息(校区名称、宿舍区名称、楼栋名称、房间名称、床位名称)
* 和学生信息(学生姓名、学号、性别)
*
* @param classId 班级ID,可为空
* @return 已入住床位详情列表
*/
List<Object> getClassOccupiedBedDetails(Long classId);
/**
* 获取班级所有未安排学生的床位信息
* 包含床位信息(校区名称、宿舍区名称、楼栋名称、房间名称、床位名称)
*
* @param classId 班级ID,可为空
* @return 未安排学生的床位详情列表
*/
List<Object> getClassUnoccupiedBedDetails(Long classId);
/**
* 根据房间ID获取住在当前房间的所有学生信息
* 包含学生姓名、学号、性别、学院名称、专业名称、班级名称、床位编码、床位ID
*
* @param roomId 房间ID
* @return 房间学生信息列表
*/
List<Object> getRoomStudents(Long roomId);
}
@@ -0,0 +1,103 @@
package org.dromara.xg.service;
import org.dromara.xg.domain.vo.DormHygieneCheckExportVo;
import org.dromara.xg.domain.vo.XgDormHygieneCheckVo;
import org.dromara.xg.domain.bo.XgDormHygieneCheckBo;
import org.dromara.xg.domain.bo.XgDormHygieneCheckCompleteBo;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.mybatis.core.page.PageQuery;
import java.util.Collection;
import java.util.List;
/**
* 宿舍卫生检查Service接口
*
* @author zlwu
* @date 2025-08-16
*/
public interface IXgDormHygieneCheckService {
/**
* 查询宿舍卫生检查
*
* @param id 主键
* @return 宿舍卫生检查
*/
XgDormHygieneCheckVo queryById(Long id);
/**
* 分页查询宿舍卫生检查列表
*
* @param bo 查询条件
* @param pageQuery 分页参数
* @return 宿舍卫生检查分页列表
*/
TableDataInfo<XgDormHygieneCheckVo> queryPageList(XgDormHygieneCheckBo bo, PageQuery pageQuery);
/**
* 查询符合条件的宿舍卫生检查列表
*
* @param bo 查询条件
* @return 宿舍卫生检查列表
*/
List<XgDormHygieneCheckVo> queryList(XgDormHygieneCheckBo bo);
/**
* 新增宿舍卫生检查
*
* @param bo 宿舍卫生检查
* @return 是否新增成功
*/
Boolean insertByBo(XgDormHygieneCheckBo bo);
/**
* 修改宿舍卫生检查
*
* @param bo 宿舍卫生检查
* @return 是否修改成功
*/
Boolean updateByBo(XgDormHygieneCheckBo bo);
/**
* 校验并批量删除宿舍卫生检查信息
*
* @param ids 待删除的主键集合
* @param isValid 是否进行有效性校验
* @return 是否删除成功
*/
Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
/**
* 新增宿舍卫生检查(包含学生评分数据)
*
* @param bo 完整的宿舍卫生检查数据,包含学生评分信息
* @return 是否新增成功
*/
Boolean insertWithStudentScores(XgDormHygieneCheckCompleteBo bo);
/**
* 修改宿舍卫生检查(包含学生评分数据)
*
* @param bo 完整的宿舍卫生检查数据,包含学生评分信息
* @return 是否修改成功
*/
Boolean updateWithStudentScores(XgDormHygieneCheckCompleteBo bo);
/**
* 查询宿舍卫生检查导出列表(包含学生卫生情况)
*
* @param bo 查询条件
* @return 导出数据列表
*/
List<DormHygieneCheckExportVo> queryExportList(XgDormHygieneCheckBo bo);
/**
* 根据学生ID查询该学生宿舍的卫生检查信息
*
* @param studentId 学生ID
* @return 卫生检查信息列表
*/
List<XgDormHygieneCheckVo> queryByStudentId(Long studentId);
}
@@ -0,0 +1,84 @@
package org.dromara.xg.service;
import org.dromara.xg.domain.vo.XgDormHygieneStudentScoreVo;
import org.dromara.xg.domain.bo.XgDormHygieneStudentScoreBo;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.mybatis.core.page.PageQuery;
import java.util.Collection;
import java.util.List;
/**
* 宿舍卫生检查学生评分Service接口
*
* @author zlwu
* @date 2025-08-16
*/
public interface IXgDormHygieneStudentScoreService {
/**
* 查询宿舍卫生检查学生评分
*
* @param id 主键
* @return 宿舍卫生检查学生评分
*/
XgDormHygieneStudentScoreVo queryById(Long id);
/**
* 分页查询宿舍卫生检查学生评分列表
*
* @param bo 查询条件
* @param pageQuery 分页参数
* @return 宿舍卫生检查学生评分分页列表
*/
TableDataInfo<XgDormHygieneStudentScoreVo> queryPageList(XgDormHygieneStudentScoreBo bo, PageQuery pageQuery);
/**
* 查询符合条件的宿舍卫生检查学生评分列表
*
* @param bo 查询条件
* @return 宿舍卫生检查学生评分列表
*/
List<XgDormHygieneStudentScoreVo> queryList(XgDormHygieneStudentScoreBo bo);
/**
* 新增宿舍卫生检查学生评分
*
* @param bo 宿舍卫生检查学生评分
* @return 是否新增成功
*/
Boolean insertByBo(XgDormHygieneStudentScoreBo bo);
/**
* 修改宿舍卫生检查学生评分
*
* @param bo 宿舍卫生检查学生评分
* @return 是否修改成功
*/
Boolean updateByBo(XgDormHygieneStudentScoreBo bo);
/**
* 校验并批量删除宿舍卫生检查学生评分信息
*
* @param ids 待删除的主键集合
* @param isValid 是否进行有效性校验
* @return 是否删除成功
*/
Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
/**
* 根据卫生检查ID查询学生评分列表
*
* @param hygieneCheckId 卫生检查ID
* @return 学生评分列表
*/
List<XgDormHygieneStudentScoreVo> queryByHygieneCheckId(Long hygieneCheckId);
/**
* 根据卫生检查ID删除学生评分记录
*
* @param hygieneCheckId 卫生检查ID
* @return 是否删除成功
*/
Boolean deleteByHygieneCheckId(Long hygieneCheckId);
}
@@ -33,6 +33,25 @@ public interface IXgDormRoomService {
*/
TableDataInfo<XgDormRoomVo> queryPageList(XgDormRoomBo bo, PageQuery pageQuery);
/**
* 分页查询当前用户所在学院的宿舍房间信息列表
*
* @param bo 查询条件
* @param pageQuery 分页参数
* @return 宿舍房间信息分页列表
*/
TableDataInfo<XgDormRoomVo> queryPageListByCurrentUserCollege(XgDormRoomBo bo, PageQuery pageQuery);
/**
* 分页查询指定班级的宿舍房间信息列表
*
* @param bo 查询条件
* @param pageQuery 分页参数
* @param classId 班级ID
* @return 宿舍房间信息分页列表
*/
TableDataInfo<XgDormRoomVo> queryPageListByClassId(XgDormRoomBo bo, PageQuery pageQuery, Long classId);
/**
* 查询符合条件的宿舍房间信息列表
*
@@ -0,0 +1,106 @@
package org.dromara.xg.service;
import org.dromara.xg.domain.vo.XgDormViolationVo;
import org.dromara.xg.domain.bo.XgDormViolationBo;
import org.dromara.xg.domain.vo.StudentOptionVo;
import org.dromara.xg.domain.bo.StudentOptionBo;
import org.dromara.xg.domain.vo.XgDormViolationImportVo;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.mybatis.core.page.PageQuery;
import java.util.Collection;
import java.util.List;
/**
* 宿舍违纪记录Service接口
*
* @author zlwu
* @date 2025-08-16
*/
public interface IXgDormViolationService {
/**
* 查询宿舍违纪记录
*
* @param id 主键
* @return 宿舍违纪记录
*/
XgDormViolationVo queryById(Long id);
/**
* 分页查询宿舍违纪记录列表
*
* @param bo 查询条件
* @param pageQuery 分页参数
* @return 宿舍违纪记录分页列表
*/
TableDataInfo<XgDormViolationVo> queryPageList(XgDormViolationBo bo, PageQuery pageQuery);
/**
* 查询符合条件的宿舍违纪记录列表
*
* @param bo 查询条件
* @return 宿舍违纪记录列表
*/
List<XgDormViolationVo> queryList(XgDormViolationBo bo);
/**
* 新增宿舍违纪记录
*
* @param bo 宿舍违纪记录
* @return 是否新增成功
*/
Boolean insertByBo(XgDormViolationBo bo);
/**
* 修改宿舍违纪记录
*
* @param bo 宿舍违纪记录
* @return 是否修改成功
*/
Boolean updateByBo(XgDormViolationBo bo);
/**
* 校验并批量删除宿舍违纪记录信息
*
* @param ids 待删除的主键集合
* @param isValid 是否进行有效性校验
* @return 是否删除成功
*/
Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
/**
* 获取学生选择器选项列表(支持按学号、姓名检索)
*
* @param bo 查询条件
* @param pageQuery 分页参数
* @return 学生选项分页列表
*/
TableDataInfo<StudentOptionVo> getStudentOptions(StudentOptionBo bo, PageQuery pageQuery);
/**
* 根据学生ID获取学生详细信息
*
* @param studentId 学生ID
* @return 学生详细信息
*/
StudentOptionVo getStudentById(Long studentId);
/**
* 根据学号获取学生详细信息
*
* @param studentNo 学号
* @return 学生详细信息
*/
StudentOptionVo getStudentByStudentNo(String studentNo);
/**
* 导入宿舍违纪记录数据
*
* @param importList 导入的宿舍违纪记录列表
* @param isUpdateSupport 是否支持更新已存在的记录
* @param operName 操作人员名称
* @return 导入结果信息
*/
String importDormViolation(List<XgDormViolationImportVo> importList, boolean isUpdateSupport, String operName);
}
@@ -0,0 +1,80 @@
package org.dromara.xg.service;
import org.dromara.xg.domain.vo.XgHolidayStayVo;
import org.dromara.xg.domain.bo.XgHolidayStayBo;
import org.dromara.xg.domain.vo.StudentOptionVo;
import org.dromara.xg.domain.bo.StudentOptionBo;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.mybatis.core.page.PageQuery;
import java.util.Collection;
import java.util.List;
/**
* 假期留宿管理Service接口
*
* @author zlwu
* @date 2025-08-15
*/
public interface IXgHolidayStayService {
/**
* 查询假期留宿管理
*
* @param id 主键
* @return 假期留宿管理
*/
XgHolidayStayVo queryById(Long id);
/**
* 分页查询假期留宿管理列表
*
* @param bo 查询条件
* @param pageQuery 分页参数
* @return 假期留宿管理分页列表
*/
TableDataInfo<XgHolidayStayVo> queryPageList(XgHolidayStayBo bo, PageQuery pageQuery);
/**
* 查询符合条件的假期留宿管理列表
*
* @param bo 查询条件
* @return 假期留宿管理列表
*/
List<XgHolidayStayVo> queryList(XgHolidayStayBo bo);
/**
* 新增假期留宿管理
*
* @param bo 假期留宿管理
* @return 是否新增成功
*/
Boolean insertByBo(XgHolidayStayBo bo);
/**
* 修改假期留宿管理
*
* @param bo 假期留宿管理
* @return 是否修改成功
*/
Boolean updateByBo(XgHolidayStayBo bo);
/**
* 校验并批量删除假期留宿管理信息
*
* @param ids 待删除的主键集合
* @param isValid 是否进行有效性校验
* @return 是否删除成功
*/
Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
/**
* 获取学生选择器选项列表(支持按学号、姓名检索)
*
* @param bo 查询条件
* @param pageQuery 分页参数
* @return 学生选项分页列表
*/
TableDataInfo<StudentOptionVo> getStudentOptions(StudentOptionBo bo, PageQuery pageQuery);
}
@@ -161,4 +161,11 @@ public interface IXgStudentMsgService {
* @return 学生信息树
*/
List<XgStudentTreeVo> getStudentTree(Long secondaryCollegeId);
/**
* 获取当前用户所在学院的学生信息树
*
* @return 学生信息树
*/
List<XgStudentTreeVo> getCurrentUserStudentTree();
}
@@ -88,6 +88,7 @@ public class XgClassMsgServiceImpl implements IXgClassMsgService {
lqw.eq(StringUtils.isNotBlank(bo.getClassType()), XgClassMsg::getClassType, bo.getClassType());
lqw.eq(StringUtils.isNotBlank(bo.getGrade()), XgClassMsg::getGrade, bo.getGrade());
lqw.eq(StringUtils.isNotBlank(bo.getClassStatus()), XgClassMsg::getClassStatus, bo.getClassStatus());
lqw.eq(bo.getClassTeacherId() != null, XgClassMsg::getClassTeacherId, bo.getClassTeacherId());
return lqw;
}
@@ -14,12 +14,22 @@ import org.dromara.xg.domain.bo.XgDormBedBo;
import org.dromara.xg.domain.vo.XgDormBedVo;
import org.dromara.xg.domain.vo.XgDormBedDetailVo;
import org.dromara.xg.domain.XgDormBed;
import org.dromara.xg.domain.XgDormRoom;
import org.dromara.xg.domain.XgDormBedStudent;
import org.dromara.xg.domain.XgSysDept;
import org.dromara.xg.mapper.XgDormBedMapper;
import org.dromara.xg.mapper.XgDormRoomMapper;
import org.dromara.xg.mapper.XgDormBedStudentMapper;
import org.dromara.xg.mapper.XgSysDeptMapper;
import org.dromara.xg.service.IXgDormBedService;
import org.dromara.common.satoken.utils.LoginHelper;
import java.util.List;
import java.util.Map;
import java.util.Collection;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.ArrayList;
/**
* 宿舍床位信息Service业务层处理
@@ -33,6 +43,9 @@ import java.util.Collection;
public class XgDormBedServiceImpl implements IXgDormBedService {
private final XgDormBedMapper baseMapper;
private final XgDormRoomMapper xgDormRoomMapper;
private final XgDormBedStudentMapper xgDormBedStudentMapper;
private final XgSysDeptMapper xgSysDeptMapper;
/**
* 查询宿舍床位信息
@@ -41,7 +54,7 @@ public class XgDormBedServiceImpl implements IXgDormBedService {
* @return 宿舍床位信息
*/
@Override
public XgDormBedVo queryById(Long id){
public XgDormBedVo queryById(Long id) {
return baseMapper.selectVoById(id);
}
@@ -117,8 +130,8 @@ public class XgDormBedServiceImpl implements IXgDormBedService {
/**
* 保存前的数据校验
*/
private void validEntityBeforeSave(XgDormBed entity){
//TODO 做一些数据校验,如唯一约束
private void validEntityBeforeSave(XgDormBed entity) {
// TODO 做一些数据校验,如唯一约束
}
/**
@@ -130,8 +143,8 @@ public class XgDormBedServiceImpl implements IXgDormBedService {
*/
@Override
public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
if(isValid){
//TODO 做一些业务上的校验,判断是否需要校验
if (isValid) {
// TODO 做一些业务上的校验,判断是否需要校验
}
return baseMapper.deleteByIds(ids) > 0;
}
@@ -147,6 +160,26 @@ public class XgDormBedServiceImpl implements IXgDormBedService {
return baseMapper.selectBedDetailsByRoomId(roomId);
}
/**
* 查询当前用户所在学院的指定房间床位详细信息列表(包含学生信息)
*
* @param roomId 房间ID
* @return 床位详细信息列表
*/
@Override
public List<XgDormBedDetailVo> queryBedDetailsByRoomIdForCurrentUserCollege(Long roomId) {
// 1. 获取当前用户的学院ID
Long currentUserCollegeId = getCurrentUserCollegeId();
if (currentUserCollegeId == null) {
log.warn("无法获取当前用户的学院信息,返回空结果");
return new ArrayList<>();
}
// 2. 直接查询指定房间中属于当前学院的床位详细信息
// 通过SQL关联xg_dorm_bed_student表,只返回分配给当前学院的床位
return baseMapper.selectBedDetailsByRoomIdAndCollegeId(roomId, currentUserCollegeId);
}
/**
* 查询指定宿舍楼的床位详细信息列表(包含学生信息)
*
@@ -157,4 +190,117 @@ public class XgDormBedServiceImpl implements IXgDormBedService {
public List<XgDormBedDetailVo> queryBedDetailsByBuildingId(Long buildingId) {
return baseMapper.selectBedDetailsByBuildingId(buildingId);
}
/**
* 查询指定房间中属于指定班级的床位详细信息列表(包含学生信息)
*
* @param roomId 房间ID
* @param classId 班级ID
* @return 床位详细信息列表
*/
@Override
public List<XgDormBedDetailVo> queryBedDetailsByRoomIdAndClassId(Long roomId, Long classId) {
return baseMapper.selectBedDetailsByRoomIdAndClassId(roomId, classId);
}
/**
* 获取当前用户的二级学院ID
* 通过当前用户的部门id,向上寻找包括他自己,找到dept_category前几位是xy-的就是二级学院
* 或者parent_id = 101的部门就是二级学院
*/
private Long getCurrentUserCollegeId() {
try {
Long currentUserId = LoginHelper.getUserId();
Long currentDeptId = LoginHelper.getDeptId();
if (currentUserId == null || currentDeptId == null) {
log.warn("用户未登录或没有部门信息");
return null;
}
// 首先查找parent_id = 101的部门(使用LambdaQueryWrapper)
LambdaQueryWrapper<XgSysDept> parentQuery = Wrappers.lambdaQuery();
parentQuery.eq(XgSysDept::getParentId, 101L)
.eq(XgSysDept::getStatus, "0")
.eq(XgSysDept::getDelFlag, "0")
.and(wrapper -> wrapper.eq(XgSysDept::getDeptId, currentDeptId)
.or().like(XgSysDept::getAncestors, "," + currentDeptId + ",") // 中间位置
.or().likeRight(XgSysDept::getAncestors, currentDeptId + ",") // 开头位置
.or().likeLeft(XgSysDept::getAncestors, "," + currentDeptId) // 末尾位置
.or().eq(XgSysDept::getAncestors, currentDeptId.toString())) // 单独一个值
.last("LIMIT 1");
List<XgSysDept> parentColleges = xgSysDeptMapper.selectList(parentQuery);
if (!parentColleges.isEmpty()) {
return parentColleges.get(0).getDeptId();
}
// 如果上面的查询没找到,尝试通过dept_category查找
LambdaQueryWrapper<XgSysDept> categoryQuery = Wrappers.lambdaQuery();
categoryQuery.likeRight(XgSysDept::getDeptCategory, "xy-")
.eq(XgSysDept::getStatus, "0")
.eq(XgSysDept::getDelFlag, "0")
.and(wrapper -> wrapper.eq(XgSysDept::getDeptId, currentDeptId)
.or().like(XgSysDept::getAncestors, "," + currentDeptId + ",") // 中间位置
.or().likeRight(XgSysDept::getAncestors, currentDeptId + ",") // 开头位置
.or().likeLeft(XgSysDept::getAncestors, "," + currentDeptId) // 末尾位置
.or().eq(XgSysDept::getAncestors, currentDeptId.toString())) // 单独一个值
.last("LIMIT 1");
List<XgSysDept> categoryColleges = xgSysDeptMapper.selectList(categoryQuery);
return categoryColleges.isEmpty() ? null : categoryColleges.get(0).getDeptId();
} catch (Exception e) {
log.error("获取当前用户二级学院ID失败", e);
return null;
}
}
/**
* 获取分配给指定学院的房间ID列表
*/
private Set<Long> getCollegeAllocatedRoomIds(Long collegeId) {
try {
LambdaQueryWrapper<XgDormBedStudent> queryWrapper = Wrappers.lambdaQuery();
queryWrapper.select(XgDormBedStudent::getRoomId)
.eq(XgDormBedStudent::getCollegeId, collegeId)
.eq(XgDormBedStudent::getStatus, "0")
.eq(XgDormBedStudent::getDeleted, "0")
.isNotNull(XgDormBedStudent::getRoomId)
.groupBy(XgDormBedStudent::getRoomId);
List<XgDormBedStudent> roomRecords = xgDormBedStudentMapper.selectList(queryWrapper);
return roomRecords.stream()
.map(XgDormBedStudent::getRoomId)
.collect(Collectors.toSet());
} catch (Exception e) {
log.error("获取学院 {} 分配的房间ID列表失败", collegeId, e);
return Set.of();
}
}
/**
* 获取分配给指定学院的宿舍楼ID列表
*/
private Set<Long> getCollegeAllocatedBuildingIds(Long collegeId) {
try {
LambdaQueryWrapper<XgDormBedStudent> queryWrapper = Wrappers.lambdaQuery();
queryWrapper.select(XgDormBedStudent::getBuildingId)
.eq(XgDormBedStudent::getCollegeId, collegeId)
.eq(XgDormBedStudent::getStatus, "0")
.eq(XgDormBedStudent::getDeleted, "0")
.isNotNull(XgDormBedStudent::getBuildingId)
.groupBy(XgDormBedStudent::getBuildingId);
List<XgDormBedStudent> buildingRecords = xgDormBedStudentMapper.selectList(queryWrapper);
return buildingRecords.stream()
.map(XgDormBedStudent::getBuildingId)
.collect(Collectors.toSet());
} catch (Exception e) {
log.error("获取学院 {} 分配的宿舍楼ID列表失败", collegeId, e);
return Set.of();
}
}
}
@@ -0,0 +1,511 @@
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.mybatis.core.page.PageQuery;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
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.vo.DormHygieneCheckExportVo;
import org.dromara.xg.domain.vo.XgDormHygieneCheckVo;
import org.dromara.xg.domain.XgDormHygieneCheck;
import org.dromara.xg.domain.XgDormHygieneStudentScore;
import org.dromara.xg.mapper.XgDormHygieneCheckMapper;
import org.dromara.xg.mapper.XgDormHygieneStudentScoreMapper;
import org.dromara.xg.service.IXgDormHygieneCheckService;
import org.dromara.xg.service.IXgStudentMsgService;
import org.dromara.system.service.ISysDictDataService;
import java.util.List;
import java.util.Map;
import java.util.Collection;
/**
* 宿舍卫生检查Service业务层处理
*
* @author zlwu
* @date 2025-08-16
*/
@Slf4j
@RequiredArgsConstructor
@Service
public class XgDormHygieneCheckServiceImpl implements IXgDormHygieneCheckService {
private final XgDormHygieneCheckMapper baseMapper;
private final XgDormHygieneStudentScoreMapper studentScoreMapper;
private final IXgStudentMsgService xgStudentMsgService;
private final ISysDictDataService sysDictDataService;
/**
* 查询宿舍卫生检查
*
* @param id 主键
* @return 宿舍卫生检查
*/
@Override
public XgDormHygieneCheckVo queryById(Long id) {
return baseMapper.selectVoById(id);
}
/**
* 分页查询宿舍卫生检查列表
*
* @param bo 查询条件
* @param pageQuery 分页参数
* @return 宿舍卫生检查分页列表
*/
@Override
public TableDataInfo<XgDormHygieneCheckVo> queryPageList(XgDormHygieneCheckBo bo, PageQuery pageQuery) {
LambdaQueryWrapper<XgDormHygieneCheck> lqw = buildQueryWrapper(bo);
Page<XgDormHygieneCheckVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
return TableDataInfo.build(result);
}
/**
* 查询符合条件的宿舍卫生检查列表
*
* @param bo 查询条件
* @return 宿舍卫生检查列表
*/
@Override
public List<XgDormHygieneCheckVo> queryList(XgDormHygieneCheckBo bo) {
LambdaQueryWrapper<XgDormHygieneCheck> lqw = buildQueryWrapper(bo);
return baseMapper.selectVoList(lqw);
}
private LambdaQueryWrapper<XgDormHygieneCheck> buildQueryWrapper(XgDormHygieneCheckBo bo) {
Map<String, Object> params = bo.getParams();
LambdaQueryWrapper<XgDormHygieneCheck> lqw = Wrappers.lambdaQuery();
// lqw.orderByAsc(XgDormHygieneCheck::getId);
lqw.orderByDesc(XgDormHygieneCheck::getCreateTime);
lqw.eq(bo.getDeleted() != null, XgDormHygieneCheck::getDeleted, bo.getDeleted());
lqw.like(StringUtils.isNotBlank(bo.getCheckTitle()), XgDormHygieneCheck::getCheckTitle, bo.getCheckTitle());
lqw.eq(bo.getCheckDate() != null, XgDormHygieneCheck::getCheckDate, bo.getCheckDate());
lqw.eq(bo.getCheckerId() != null, XgDormHygieneCheck::getCheckerId, bo.getCheckerId());
lqw.like(StringUtils.isNotBlank(bo.getCheckerName()), XgDormHygieneCheck::getCheckerName, bo.getCheckerName());
lqw.eq(StringUtils.isNotBlank(bo.getCheckType()), XgDormHygieneCheck::getCheckType, bo.getCheckType());
lqw.eq(StringUtils.isNotBlank(bo.getCheckLevel()), XgDormHygieneCheck::getCheckLevel, bo.getCheckLevel());
lqw.eq(bo.getRoomId() != null, XgDormHygieneCheck::getRoomId, bo.getRoomId());
lqw.like(StringUtils.isNotBlank(bo.getRoomCode()), XgDormHygieneCheck::getRoomCode, bo.getRoomCode());
lqw.like(StringUtils.isNotBlank(bo.getRoomName()), XgDormHygieneCheck::getRoomName, bo.getRoomName());
lqw.eq(bo.getBuildingId() != null, XgDormHygieneCheck::getBuildingId, bo.getBuildingId());
lqw.like(StringUtils.isNotBlank(bo.getBuildingName()), XgDormHygieneCheck::getBuildingName,
bo.getBuildingName());
lqw.eq(bo.getAreaId() != null, XgDormHygieneCheck::getAreaId, bo.getAreaId());
lqw.like(StringUtils.isNotBlank(bo.getAreaName()), XgDormHygieneCheck::getAreaName, bo.getAreaName());
lqw.eq(bo.getCampusId() != null, XgDormHygieneCheck::getCampusId, bo.getCampusId());
lqw.like(StringUtils.isNotBlank(bo.getCampusName()), XgDormHygieneCheck::getCampusName, bo.getCampusName());
lqw.eq(bo.getTotalScore() != null, XgDormHygieneCheck::getTotalScore, bo.getTotalScore());
lqw.eq(StringUtils.isNotBlank(bo.getHygieneGrade()), XgDormHygieneCheck::getHygieneGrade, bo.getHygieneGrade());
lqw.eq(StringUtils.isNotBlank(bo.getAttachmentIds()), XgDormHygieneCheck::getAttachmentIds,
bo.getAttachmentIds());
lqw.like(StringUtils.isNotBlank(bo.getCheckSummary()), XgDormHygieneCheck::getCheckSummary,
bo.getCheckSummary());
lqw.like(StringUtils.isNotBlank(bo.getImprovementSuggestions()), XgDormHygieneCheck::getImprovementSuggestions,
bo.getImprovementSuggestions());
lqw.like(StringUtils.isNotBlank(bo.getCheckRemarks()), XgDormHygieneCheck::getCheckRemarks,
bo.getCheckRemarks());
return lqw;
}
/**
* 新增宿舍卫生检查
*
* @param bo 宿舍卫生检查
* @return 是否新增成功
*/
@Override
public Boolean insertByBo(XgDormHygieneCheckBo bo) {
XgDormHygieneCheck add = MapstructUtils.convert(bo, XgDormHygieneCheck.class);
validEntityBeforeSave(add);
boolean flag = baseMapper.insert(add) > 0;
if (flag) {
bo.setId(add.getId());
}
return flag;
}
/**
* 修改宿舍卫生检查
*
* @param bo 宿舍卫生检查
* @return 是否修改成功
*/
@Override
public Boolean updateByBo(XgDormHygieneCheckBo bo) {
XgDormHygieneCheck update = MapstructUtils.convert(bo, XgDormHygieneCheck.class);
validEntityBeforeSave(update);
return baseMapper.updateById(update) > 0;
}
/**
* 保存前的数据校验
*/
private void validEntityBeforeSave(XgDormHygieneCheck entity) {
// TODO 做一些数据校验,如唯一约束
}
/**
* 校验并批量删除宿舍卫生检查信息
*
* @param ids 待删除的主键集合
* @param isValid 是否进行有效性校验
* @return 是否删除成功
*/
@Override
public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
if (isValid) {
// TODO 做一些业务上的校验,判断是否需要校验
}
return baseMapper.deleteByIds(ids) > 0;
}
/**
* 新增宿舍卫生检查(包含学生评分数据)
*
* @param bo 完整的宿舍卫生检查数据,包含学生评分信息
* @return 是否新增成功
*/
@Override
@Transactional(rollbackFor = Exception.class)
public Boolean insertWithStudentScores(XgDormHygieneCheckCompleteBo bo) {
// 1. 转换并保存主表数据
XgDormHygieneCheck add = MapstructUtils.convert(bo, XgDormHygieneCheck.class);
validEntityBeforeSave(add);
boolean flag = baseMapper.insert(add) > 0;
log.info("add: {}", add);
log.info("bo: {}", bo);
log.info("flag: {}", flag);
if (flag && bo.getStudentScores() != null && !bo.getStudentScores().isEmpty()) {
// 2. 保存学生评分数据
for (XgDormHygieneStudentScoreBo studentScoreBo : bo.getStudentScores()) {
XgDormHygieneStudentScore studentScore = MapstructUtils.convert(studentScoreBo,
XgDormHygieneStudentScore.class);
studentScore.setHygieneCheckId(add.getId());
// 根据学生ID查询学生完整信息,补充学院、专业、班级信息
if (studentScoreBo.getStudentId() != null) {
try {
var studentInfo = xgStudentMsgService.queryById(studentScoreBo.getStudentId());
if (studentInfo != null) {
// 补充学院信息
if (studentScore.getCollegeId() == null
&& StringUtils.isNotBlank(studentInfo.getCollegeId())) {
try {
studentScore.setCollegeId(Long.valueOf(studentInfo.getCollegeId()));
} catch (NumberFormatException e) {
log.warn("学院ID转换失败,学生ID: {}, 学院ID: {}", studentScoreBo.getStudentId(),
studentInfo.getCollegeId());
}
}
if (StringUtils.isBlank(studentScore.getCollegeName())) {
studentScore.setCollegeName(studentInfo.getCollegeName());
}
// 补充专业信息
if (studentScore.getMajorId() == null && StringUtils.isNotBlank(studentInfo.getMajorId())) {
try {
studentScore.setMajorId(Long.valueOf(studentInfo.getMajorId()));
} catch (NumberFormatException e) {
log.warn("专业ID转换失败,学生ID: {}, 专业ID: {}", studentScoreBo.getStudentId(),
studentInfo.getMajorId());
}
}
if (StringUtils.isBlank(studentScore.getMajorName())) {
studentScore.setMajorName(studentInfo.getMajorName());
}
// 补充班级信息
if (studentScore.getClassId() == null && StringUtils.isNotBlank(studentInfo.getClassId())) {
try {
studentScore.setClassId(Long.valueOf(studentInfo.getClassId()));
} catch (NumberFormatException e) {
log.warn("班级ID转换失败,学生ID: {}, 班级ID: {}", studentScoreBo.getStudentId(),
studentInfo.getClassId());
}
}
if (StringUtils.isBlank(studentScore.getClassName())) {
studentScore.setClassName(studentInfo.getClassName());
}
log.info("补充学生信息 - 学生ID: {}, 学院: {}, 专业: {}, 班级: {}",
studentScoreBo.getStudentId(),
studentInfo.getCollegeName(),
studentInfo.getMajorName(),
studentInfo.getClassName());
}
} catch (Exception e) {
log.warn("查询学生信息失败,学生ID: {}, 错误: {}", studentScoreBo.getStudentId(), e.getMessage());
}
}
log.info("studentScore: {}", studentScore);
log.info("studentScoreBo: {}", studentScoreBo);
studentScoreMapper.insert(studentScore);
}
}
return flag;
}
/**
* 修改宿舍卫生检查(包含学生评分数据)
*
* @param bo 完整的宿舍卫生检查数据,包含学生评分信息
* @return 是否修改成功
*/
@Override
@Transactional(rollbackFor = Exception.class)
public Boolean updateWithStudentScores(XgDormHygieneCheckCompleteBo bo) {
// 1. 更新主表数据
XgDormHygieneCheck update = MapstructUtils.convert(bo, XgDormHygieneCheck.class);
validEntityBeforeSave(update);
boolean flag = baseMapper.updateById(update) > 0;
if (flag && bo.getStudentScores() != null && !bo.getStudentScores().isEmpty()) {
// 2. 逻辑删除原有学生评分记录
LambdaQueryWrapper<XgDormHygieneStudentScore> deleteWrapper = Wrappers.lambdaQuery();
deleteWrapper.eq(XgDormHygieneStudentScore::getHygieneCheckId, bo.getId());
studentScoreMapper.delete(deleteWrapper);
// 3. 插入新的学生评分记录
for (XgDormHygieneStudentScoreBo studentScoreBo : bo.getStudentScores()) {
XgDormHygieneStudentScore studentScore = MapstructUtils.convert(studentScoreBo,
XgDormHygieneStudentScore.class);
studentScore.setHygieneCheckId(bo.getId());
studentScore.setId(null);
// 根据学生ID查询学生完整信息,补充学院、专业、班级信息
if (studentScoreBo.getStudentId() != null) {
try {
var studentInfo = xgStudentMsgService.queryById(studentScoreBo.getStudentId());
if (studentInfo != null) {
// 补充学院信息
if (studentScore.getCollegeId() == null
&& StringUtils.isNotBlank(studentInfo.getCollegeId())) {
try {
studentScore.setCollegeId(Long.valueOf(studentInfo.getCollegeId()));
} catch (NumberFormatException e) {
log.warn("学院ID转换失败,学生ID: {}, 学院ID: {}", studentScoreBo.getStudentId(),
studentInfo.getCollegeId());
}
}
if (StringUtils.isBlank(studentScore.getCollegeName())) {
studentScore.setCollegeName(studentInfo.getCollegeName());
}
// 补充专业信息
if (studentScore.getMajorId() == null && StringUtils.isNotBlank(studentInfo.getMajorId())) {
try {
studentScore.setMajorId(Long.valueOf(studentInfo.getMajorId()));
} catch (NumberFormatException e) {
log.warn("专业ID转换失败,学生ID: {}, 专业ID: {}", studentScoreBo.getStudentId(),
studentInfo.getMajorId());
}
}
if (StringUtils.isBlank(studentScore.getMajorName())) {
studentScore.setMajorName(studentInfo.getMajorName());
}
// 补充班级信息
if (studentScore.getClassId() == null && StringUtils.isNotBlank(studentInfo.getClassId())) {
try {
studentScore.setClassId(Long.valueOf(studentInfo.getClassId()));
} catch (NumberFormatException e) {
log.warn("班级ID转换失败,学生ID: {}, 班级ID: {}", studentScoreBo.getStudentId(),
studentInfo.getClassId());
}
}
if (StringUtils.isBlank(studentScore.getClassName())) {
studentScore.setClassName(studentInfo.getClassName());
}
log.info("更新时补充学生信息 - 学生ID: {}, 学院: {}, 专业: {}, 班级: {}",
studentScoreBo.getStudentId(),
studentInfo.getCollegeName(),
studentInfo.getMajorName(),
studentInfo.getClassName());
}
} catch (Exception e) {
log.warn("查询学生信息失败,学生ID: {}, 错误: {}", studentScoreBo.getStudentId(), e.getMessage());
}
}
studentScoreMapper.insert(studentScore);
}
}
return flag;
}
/**
* 查询宿舍卫生检查导出列表(包含学生卫生情况)
*
* @param bo 查询条件
* @return 导出数据列表
*/
@Override
public List<DormHygieneCheckExportVo> queryExportList(XgDormHygieneCheckBo bo) {
// 调用mapper查询导出数据
List<DormHygieneCheckExportVo> exportList = baseMapper.selectExportList(bo);
// 转换字典值为文本
for (DormHygieneCheckExportVo exportVo : exportList) {
// 转换检查类型
exportVo.setCheckTypeText(convertCheckTypeToText(exportVo.getCheckTypeText()));
// 转换检查级别
exportVo.setCheckLevelText(convertCheckLevelToText(exportVo.getCheckLevelText()));
// 转换卫生等级
exportVo.setHygieneGradeText(convertHygieneGradeToText(exportVo.getHygieneGradeText()));
// 转换出勤状态
exportVo.setAttendanceStatusText(convertAttendanceStatusToText(exportVo.getAttendanceStatusText()));
// 转换学生评级
exportVo.setStudentGradeText(convertStudentGradeToText(exportVo.getStudentGradeText()));
// 转换是否寝室长
// exportVo.setIsResponsiblePersonText(convertResponsiblePersonToText(exportVo.getIsResponsiblePersonText()));
}
return exportList;
}
/**
* 根据学生ID查询该学生宿舍的卫生检查信息
*
* @param studentId 学生ID
* @return 卫生检查信息列表
*/
@Override
public List<XgDormHygieneCheckVo> queryByStudentId(Long studentId) {
if (studentId == null) {
log.warn("学生ID为空,无法查询卫生检查信息");
return List.of();
}
// 1. 通过学生ID查询学生评分记录,获取卫生检查ID列表
LambdaQueryWrapper<XgDormHygieneStudentScore> studentScoreWrapper = Wrappers.lambdaQuery();
studentScoreWrapper.eq(XgDormHygieneStudentScore::getStudentId, studentId);
studentScoreWrapper.eq(XgDormHygieneStudentScore::getDeleted, 0); // 只查询未删除的记录
List<XgDormHygieneStudentScore> studentScores = studentScoreMapper.selectList(studentScoreWrapper);
if (studentScores.isEmpty()) {
log.info("学生ID: {} 没有找到相关的卫生检查记录", studentId);
return List.of();
}
// 2. 提取卫生检查ID列表
List<Long> hygieneCheckIds = studentScores.stream()
.map(XgDormHygieneStudentScore::getHygieneCheckId)
.distinct()
.toList();
// 3. 根据卫生检查ID列表查询卫生检查信息
LambdaQueryWrapper<XgDormHygieneCheck> hygieneCheckWrapper = Wrappers.lambdaQuery();
hygieneCheckWrapper.in(XgDormHygieneCheck::getId, hygieneCheckIds);
hygieneCheckWrapper.eq(XgDormHygieneCheck::getDeleted, 0); // 只查询未删除的记录
hygieneCheckWrapper.orderByDesc(XgDormHygieneCheck::getCreateTime); // 按创建时间倒序排列
List<XgDormHygieneCheckVo> result = baseMapper.selectVoList(hygieneCheckWrapper);
log.info("学生ID: {} 查询到 {} 条卫生检查记录", studentId, result.size());
return result;
}
/**
* 转换检查类型代码为文本
*/
private String convertCheckTypeToText(String checkType) {
if (StringUtils.isEmpty(checkType)) {
return "";
}
try {
return sysDictDataService.selectDictLabel("xg_dorm_hygiene_check_type", checkType);
} catch (Exception e) {
log.warn("获取字典标签失败,字典类型: xg_dorm_hygiene_check_type, 字典值: {}, 错误: {}", checkType, e.getMessage());
return checkType;
}
}
/**
* 转换检查级别代码为文本
*/
private String convertCheckLevelToText(String checkLevel) {
if (StringUtils.isEmpty(checkLevel)) {
return "";
}
try {
return sysDictDataService.selectDictLabel("xg_dorm_hygiene_check_level", checkLevel);
} catch (Exception e) {
log.warn("获取字典标签失败,字典类型: xg_dorm_hygiene_check_level, 字典值: {}, 错误: {}", checkLevel, e.getMessage());
return checkLevel;
}
}
/**
* 转换卫生等级代码为文本
*/
private String convertHygieneGradeToText(String hygieneGrade) {
if (StringUtils.isEmpty(hygieneGrade)) {
return "";
}
try {
return sysDictDataService.selectDictLabel("xg_dorm_hygiene_grade", hygieneGrade);
} catch (Exception e) {
log.warn("获取字典标签失败,字典类型: xg_dorm_hygiene_grade, 字典值: {}, 错误: {}", hygieneGrade, e.getMessage());
return hygieneGrade;
}
}
/**
* 转换出勤状态代码为文本
*/
private String convertAttendanceStatusToText(String attendanceStatus) {
if (StringUtils.isEmpty(attendanceStatus)) {
return "";
}
try {
return sysDictDataService.selectDictLabel("xg_student_attendance_status", attendanceStatus);
} catch (Exception e) {
log.warn("获取字典标签失败,字典类型: xg_student_attendance_status, 字典值: {}, 错误: {}", attendanceStatus, e.getMessage());
return attendanceStatus;
}
}
/**
* 转换学生评级代码为文本
*/
private String convertStudentGradeToText(String studentGrade) {
if (StringUtils.isEmpty(studentGrade)) {
return "";
}
try {
return sysDictDataService.selectDictLabel("xg_dorm_hygiene_grade", studentGrade);
} catch (Exception e) {
log.warn("获取字典标签失败,字典类型: xg_dorm_hygiene_grade, 字典值: {}, 错误: {}", studentGrade, e.getMessage());
return studentGrade;
}
}
/**
* 转换是否寝室长代码为文本
*/
private String convertResponsiblePersonToText(String isResponsiblePerson) {
if (StringUtils.isEmpty(isResponsiblePerson)) {
return "否";
}
return "1".equals(isResponsiblePerson) ? "是" : "否";
}
}
@@ -0,0 +1,186 @@
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.mybatis.core.page.PageQuery;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.dromara.xg.domain.bo.XgDormHygieneStudentScoreBo;
import org.dromara.xg.domain.vo.XgDormHygieneStudentScoreVo;
import org.dromara.xg.domain.XgDormHygieneStudentScore;
import org.dromara.xg.mapper.XgDormHygieneStudentScoreMapper;
import org.dromara.xg.service.IXgDormHygieneStudentScoreService;
import java.util.List;
import java.util.Map;
import java.util.Collection;
/**
* 宿舍卫生检查学生评分Service业务层处理
*
* @author zlwu
* @date 2025-08-16
*/
@Slf4j
@RequiredArgsConstructor
@Service
public class XgDormHygieneStudentScoreServiceImpl implements IXgDormHygieneStudentScoreService {
private final XgDormHygieneStudentScoreMapper baseMapper;
/**
* 查询宿舍卫生检查学生评分
*
* @param id 主键
* @return 宿舍卫生检查学生评分
*/
@Override
public XgDormHygieneStudentScoreVo queryById(Long id) {
return baseMapper.selectVoById(id);
}
/**
* 分页查询宿舍卫生检查学生评分列表
*
* @param bo 查询条件
* @param pageQuery 分页参数
* @return 宿舍卫生检查学生评分分页列表
*/
@Override
public TableDataInfo<XgDormHygieneStudentScoreVo> queryPageList(XgDormHygieneStudentScoreBo bo,
PageQuery pageQuery) {
LambdaQueryWrapper<XgDormHygieneStudentScore> lqw = buildQueryWrapper(bo);
Page<XgDormHygieneStudentScoreVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
return TableDataInfo.build(result);
}
/**
* 查询符合条件的宿舍卫生检查学生评分列表
*
* @param bo 查询条件
* @return 宿舍卫生检查学生评分列表
*/
@Override
public List<XgDormHygieneStudentScoreVo> queryList(XgDormHygieneStudentScoreBo bo) {
LambdaQueryWrapper<XgDormHygieneStudentScore> lqw = buildQueryWrapper(bo);
return baseMapper.selectVoList(lqw);
}
private LambdaQueryWrapper<XgDormHygieneStudentScore> buildQueryWrapper(XgDormHygieneStudentScoreBo bo) {
Map<String, Object> params = bo.getParams();
LambdaQueryWrapper<XgDormHygieneStudentScore> lqw = Wrappers.lambdaQuery();
lqw.orderByAsc(XgDormHygieneStudentScore::getId);
lqw.eq(bo.getDeleted() != null, XgDormHygieneStudentScore::getDeleted, bo.getDeleted());
lqw.eq(bo.getHygieneCheckId() != null, XgDormHygieneStudentScore::getHygieneCheckId, bo.getHygieneCheckId());
lqw.eq(bo.getStudentId() != null, XgDormHygieneStudentScore::getStudentId, bo.getStudentId());
lqw.eq(StringUtils.isNotBlank(bo.getStudentNo()), XgDormHygieneStudentScore::getStudentNo, bo.getStudentNo());
lqw.like(StringUtils.isNotBlank(bo.getStudentName()), XgDormHygieneStudentScore::getStudentName,
bo.getStudentName());
lqw.eq(bo.getClassId() != null, XgDormHygieneStudentScore::getClassId, bo.getClassId());
lqw.like(StringUtils.isNotBlank(bo.getClassName()), XgDormHygieneStudentScore::getClassName, bo.getClassName());
lqw.eq(bo.getMajorId() != null, XgDormHygieneStudentScore::getMajorId, bo.getMajorId());
lqw.like(StringUtils.isNotBlank(bo.getMajorName()), XgDormHygieneStudentScore::getMajorName, bo.getMajorName());
lqw.eq(bo.getCollegeId() != null, XgDormHygieneStudentScore::getCollegeId, bo.getCollegeId());
lqw.like(StringUtils.isNotBlank(bo.getCollegeName()), XgDormHygieneStudentScore::getCollegeName,
bo.getCollegeName());
lqw.eq(bo.getBedId() != null, XgDormHygieneStudentScore::getBedId, bo.getBedId());
lqw.like(StringUtils.isNotBlank(bo.getBedCode()), XgDormHygieneStudentScore::getBedCode, bo.getBedCode());
lqw.eq(bo.getStudentScore() != null, XgDormHygieneStudentScore::getStudentScore, bo.getStudentScore());
lqw.eq(StringUtils.isNotBlank(bo.getAttendanceStatus()), XgDormHygieneStudentScore::getAttendanceStatus,
bo.getAttendanceStatus());
lqw.eq(StringUtils.isNotBlank(bo.getStudentGrade()), XgDormHygieneStudentScore::getStudentGrade,
bo.getStudentGrade());
lqw.eq(bo.getIsResponsiblePerson() != null, XgDormHygieneStudentScore::getIsResponsiblePerson,
bo.getIsResponsiblePerson());
lqw.like(StringUtils.isNotBlank(bo.getScoreRemarks()), XgDormHygieneStudentScore::getScoreRemarks,
bo.getScoreRemarks());
lqw.like(StringUtils.isNotBlank(bo.getImprovementNotes()), XgDormHygieneStudentScore::getImprovementNotes,
bo.getImprovementNotes());
return lqw;
}
/**
* 新增宿舍卫生检查学生评分
*
* @param bo 宿舍卫生检查学生评分
* @return 是否新增成功
*/
@Override
public Boolean insertByBo(XgDormHygieneStudentScoreBo bo) {
XgDormHygieneStudentScore add = MapstructUtils.convert(bo, XgDormHygieneStudentScore.class);
validEntityBeforeSave(add);
boolean flag = baseMapper.insert(add) > 0;
if (flag) {
bo.setId(add.getId());
}
return flag;
}
/**
* 修改宿舍卫生检查学生评分
*
* @param bo 宿舍卫生检查学生评分
* @return 是否修改成功
*/
@Override
public Boolean updateByBo(XgDormHygieneStudentScoreBo bo) {
XgDormHygieneStudentScore update = MapstructUtils.convert(bo, XgDormHygieneStudentScore.class);
validEntityBeforeSave(update);
return baseMapper.updateById(update) > 0;
}
/**
* 保存前的数据校验
*/
private void validEntityBeforeSave(XgDormHygieneStudentScore entity) {
// TODO 做一些数据校验,如唯一约束
}
/**
* 校验并批量删除宿舍卫生检查学生评分信息
*
* @param ids 待删除的主键集合
* @param isValid 是否进行有效性校验
* @return 是否删除成功
*/
@Override
public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
if (isValid) {
// TODO 做一些业务上的校验,判断是否需要校验
}
return baseMapper.deleteByIds(ids) > 0;
}
/**
* 根据卫生检查ID查询学生评分列表
*
* @param hygieneCheckId 卫生检查ID
* @return 学生评分列表
*/
@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);
}
/**
* 根据卫生检查ID删除学生评分记录
*
* @param hygieneCheckId 卫生检查ID
* @return 是否删除成功
*/
@Override
public Boolean deleteByHygieneCheckId(Long hygieneCheckId) {
LambdaQueryWrapper<XgDormHygieneStudentScore> lqw = Wrappers.lambdaQuery();
lqw.eq(XgDormHygieneStudentScore::getHygieneCheckId, hygieneCheckId);
return baseMapper.delete(lqw) > 0;
}
}
@@ -13,12 +13,19 @@ import org.springframework.stereotype.Service;
import org.dromara.xg.domain.bo.XgDormRoomBo;
import org.dromara.xg.domain.vo.XgDormRoomVo;
import org.dromara.xg.domain.XgDormRoom;
import org.dromara.xg.domain.XgDormBedStudent;
import org.dromara.xg.domain.XgSysDept;
import org.dromara.xg.mapper.XgDormRoomMapper;
import org.dromara.xg.mapper.XgDormBedStudentMapper;
import org.dromara.xg.mapper.XgSysDeptMapper;
import org.dromara.xg.service.IXgDormRoomService;
import org.dromara.common.satoken.utils.LoginHelper;
import java.util.List;
import java.util.Map;
import java.util.Collection;
import java.util.Set;
import java.util.stream.Collectors;
/**
* 宿舍房间信息Service业务层处理
@@ -32,6 +39,8 @@ import java.util.Collection;
public class XgDormRoomServiceImpl implements IXgDormRoomService {
private final XgDormRoomMapper baseMapper;
private final XgDormBedStudentMapper xgDormBedStudentMapper;
private final XgSysDeptMapper xgSysDeptMapper;
/**
* 查询宿舍房间信息
@@ -58,6 +67,68 @@ public class XgDormRoomServiceImpl implements IXgDormRoomService {
return TableDataInfo.build(result);
}
/**
* 分页查询当前用户所在学院的宿舍房间信息列表
*
* @param bo 查询条件
* @param pageQuery 分页参数
* @return 宿舍房间信息分页列表
*/
@Override
public TableDataInfo<XgDormRoomVo> queryPageListByCurrentUserCollege(XgDormRoomBo bo, PageQuery pageQuery) {
// 1. 获取当前用户的学院ID
Long currentUserCollegeId = getCurrentUserCollegeId();
if (currentUserCollegeId == null) {
log.warn("无法获取当前用户的学院信息,返回空结果");
return TableDataInfo.build(new Page<>());
}
// 2. 获取分配给当前学院的房间ID列表
Set<Long> collegeAllocatedRoomIds = getCollegeAllocatedRoomIds(currentUserCollegeId);
if (collegeAllocatedRoomIds.isEmpty()) {
log.info("当前学院 {} 没有分配的房间,返回空结果", currentUserCollegeId);
return TableDataInfo.build(new Page<>());
}
// 3. 构建查询条件,只查询分配给当前学院的具体房间,并支持额外的过滤条件
LambdaQueryWrapper<XgDormRoom> lqw = buildQueryWrapper(bo);
lqw.in(XgDormRoom::getId, collegeAllocatedRoomIds);
Page<XgDormRoomVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
return TableDataInfo.build(result);
}
/**
* 分页查询指定班级的宿舍房间信息列表
*
* @param bo 查询条件
* @param pageQuery 分页参数
* @param classId 班级ID
* @return 宿舍房间信息分页列表
*/
@Override
public TableDataInfo<XgDormRoomVo> queryPageListByClassId(XgDormRoomBo bo, PageQuery pageQuery, Long classId) {
// 1. 参数校验
if (classId == null) {
log.warn("班级ID不能为空,返回空结果");
return TableDataInfo.build(new Page<>());
}
// 2. 获取分配给指定班级的房间ID列表
Set<Long> classAllocatedRoomIds = getClassAllocatedRoomIds(classId);
if (classAllocatedRoomIds.isEmpty()) {
log.info("班级 {} 没有分配的房间,返回空结果", classId);
return TableDataInfo.build(new Page<>());
}
// 3. 构建查询条件,只查询分配给指定班级的具体房间,并支持额外的过滤条件
LambdaQueryWrapper<XgDormRoom> lqw = buildQueryWrapper(bo);
lqw.in(XgDormRoom::getId, classAllocatedRoomIds);
Page<XgDormRoomVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
return TableDataInfo.build(result);
}
/**
* 查询符合条件的宿舍房间信息列表
*
@@ -138,4 +209,105 @@ public class XgDormRoomServiceImpl implements IXgDormRoomService {
}
return baseMapper.deleteByIds(ids) > 0;
}
/**
* 获取当前用户的二级学院ID
* 通过当前用户的部门id,向上寻找包括他自己,找到dept_category前几位是xy-的就是二级学院
* 或者parent_id = 101的部门就是二级学院
*/
private Long getCurrentUserCollegeId() {
try {
Long currentUserId = LoginHelper.getUserId();
Long currentDeptId = LoginHelper.getDeptId();
if (currentUserId == null || currentDeptId == null) {
log.warn("用户未登录或没有部门信息");
return null;
}
// 首先查找parent_id = 101的部门(使用LambdaQueryWrapper)
LambdaQueryWrapper<XgSysDept> parentQuery = Wrappers.lambdaQuery();
parentQuery.eq(XgSysDept::getParentId, 101L)
.eq(XgSysDept::getStatus, "0")
.eq(XgSysDept::getDelFlag, "0")
.and(wrapper -> wrapper.eq(XgSysDept::getDeptId, currentDeptId)
.or().like(XgSysDept::getAncestors, "," + currentDeptId + ",") // 中间位置
.or().likeRight(XgSysDept::getAncestors, currentDeptId + ",") // 开头位置
.or().likeLeft(XgSysDept::getAncestors, "," + currentDeptId) // 末尾位置
.or().eq(XgSysDept::getAncestors, currentDeptId.toString())) // 单独一个值
.last("LIMIT 1");
List<XgSysDept> parentColleges = xgSysDeptMapper.selectList(parentQuery);
if (!parentColleges.isEmpty()) {
return parentColleges.get(0).getDeptId();
}
// 如果上面的查询没找到,尝试通过dept_category查找
LambdaQueryWrapper<XgSysDept> categoryQuery = Wrappers.lambdaQuery();
categoryQuery.likeRight(XgSysDept::getDeptCategory, "xy-")
.eq(XgSysDept::getStatus, "0")
.eq(XgSysDept::getDelFlag, "0")
.and(wrapper -> wrapper.eq(XgSysDept::getDeptId, currentDeptId)
.or().like(XgSysDept::getAncestors, "," + currentDeptId + ",") // 中间位置
.or().likeRight(XgSysDept::getAncestors, currentDeptId + ",") // 开头位置
.or().likeLeft(XgSysDept::getAncestors, "," + currentDeptId) // 末尾位置
.or().eq(XgSysDept::getAncestors, currentDeptId.toString())) // 单独一个值
.last("LIMIT 1");
List<XgSysDept> categoryColleges = xgSysDeptMapper.selectList(categoryQuery);
return categoryColleges.isEmpty() ? null : categoryColleges.get(0).getDeptId();
} catch (Exception e) {
log.error("获取当前用户二级学院ID失败", e);
return null;
}
}
/**
* 获取分配给指定学院的房间ID列表
*/
private Set<Long> getCollegeAllocatedRoomIds(Long collegeId) {
try {
LambdaQueryWrapper<XgDormBedStudent> queryWrapper = Wrappers.lambdaQuery();
queryWrapper.select(XgDormBedStudent::getRoomId)
.eq(XgDormBedStudent::getCollegeId, collegeId)
.eq(XgDormBedStudent::getStatus, "0")
.eq(XgDormBedStudent::getDeleted, "0")
.isNotNull(XgDormBedStudent::getRoomId)
.groupBy(XgDormBedStudent::getRoomId);
List<XgDormBedStudent> roomRecords = xgDormBedStudentMapper.selectList(queryWrapper);
return roomRecords.stream()
.map(XgDormBedStudent::getRoomId)
.collect(Collectors.toSet());
} catch (Exception e) {
log.error("获取学院 {} 分配的房间ID列表失败", collegeId, e);
return Set.of();
}
}
/**
* 获取分配给指定班级的房间ID列表
*/
private Set<Long> getClassAllocatedRoomIds(Long classId) {
try {
LambdaQueryWrapper<XgDormBedStudent> queryWrapper = Wrappers.lambdaQuery();
queryWrapper.select(XgDormBedStudent::getRoomId)
.eq(XgDormBedStudent::getClassId, classId)
.eq(XgDormBedStudent::getStatus, "0")
.eq(XgDormBedStudent::getDeleted, "0")
.isNotNull(XgDormBedStudent::getRoomId)
.groupBy(XgDormBedStudent::getRoomId);
List<XgDormBedStudent> roomRecords = xgDormBedStudentMapper.selectList(queryWrapper);
return roomRecords.stream()
.map(XgDormBedStudent::getRoomId)
.collect(Collectors.toSet());
} catch (Exception e) {
log.error("获取班级 {} 分配的房间ID列表失败", classId, e);
return Set.of();
}
}
}
@@ -0,0 +1,290 @@
package org.dromara.xg.service.impl;
import org.dromara.common.core.utils.MapstructUtils;
import org.dromara.common.core.utils.StringUtils;
import cn.hutool.core.util.ObjectUtil;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.mybatis.core.page.PageQuery;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.dromara.xg.domain.bo.XgDormViolationBo;
import org.dromara.xg.domain.vo.XgDormViolationVo;
import org.dromara.xg.domain.bo.StudentOptionBo;
import org.dromara.xg.domain.vo.StudentOptionVo;
import org.dromara.xg.domain.vo.XgDormViolationImportVo;
import org.dromara.xg.domain.XgDormViolation;
import org.dromara.xg.mapper.XgDormViolationMapper;
import org.dromara.xg.service.IXgDormViolationService;
import java.util.List;
import java.util.Map;
import java.util.Collection;
/**
* 宿舍违纪记录Service业务层处理
*
* @author zlwu
* @date 2025-08-16
*/
@Slf4j
@RequiredArgsConstructor
@Service
public class XgDormViolationServiceImpl implements IXgDormViolationService {
private final XgDormViolationMapper baseMapper;
/**
* 查询宿舍违纪记录
*
* @param id 主键
* @return 宿舍违纪记录
*/
@Override
public XgDormViolationVo queryById(Long id) {
return baseMapper.selectVoById(id);
}
/**
* 分页查询宿舍违纪记录列表
*
* @param bo 查询条件
* @param pageQuery 分页参数
* @return 宿舍违纪记录分页列表
*/
@Override
public TableDataInfo<XgDormViolationVo> queryPageList(XgDormViolationBo bo, PageQuery pageQuery) {
LambdaQueryWrapper<XgDormViolation> lqw = buildQueryWrapper(bo);
Page<XgDormViolationVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
return TableDataInfo.build(result);
}
/**
* 查询符合条件的宿舍违纪记录列表
*
* @param bo 查询条件
* @return 宿舍违纪记录列表
*/
@Override
public List<XgDormViolationVo> queryList(XgDormViolationBo bo) {
LambdaQueryWrapper<XgDormViolation> lqw = buildQueryWrapper(bo);
return baseMapper.selectVoList(lqw);
}
private LambdaQueryWrapper<XgDormViolation> buildQueryWrapper(XgDormViolationBo bo) {
Map<String, Object> params = bo.getParams();
LambdaQueryWrapper<XgDormViolation> lqw = Wrappers.lambdaQuery();
lqw.orderByAsc(XgDormViolation::getId);
lqw.eq(bo.getStudentId() != null, XgDormViolation::getStudentId, bo.getStudentId());
lqw.like(StringUtils.isNotBlank(bo.getStudentName()), XgDormViolation::getStudentName, bo.getStudentName());
lqw.like(StringUtils.isNotBlank(bo.getStudentNo()), XgDormViolation::getStudentNo, bo.getStudentNo());
lqw.eq(bo.getCollegeId() != null, XgDormViolation::getCollegeId, bo.getCollegeId());
lqw.like(StringUtils.isNotBlank(bo.getCollegeName()), XgDormViolation::getCollegeName, bo.getCollegeName());
lqw.eq(bo.getMajorId() != null, XgDormViolation::getMajorId, bo.getMajorId());
lqw.like(StringUtils.isNotBlank(bo.getMajorName()), XgDormViolation::getMajorName, bo.getMajorName());
lqw.eq(bo.getClassId() != null, XgDormViolation::getClassId, bo.getClassId());
lqw.like(StringUtils.isNotBlank(bo.getClassName()), XgDormViolation::getClassName, bo.getClassName());
lqw.eq(bo.getCampusId() != null, XgDormViolation::getCampusId, bo.getCampusId());
lqw.like(StringUtils.isNotBlank(bo.getCampusName()), XgDormViolation::getCampusName, bo.getCampusName());
lqw.eq(bo.getAreaId() != null, XgDormViolation::getAreaId, bo.getAreaId());
lqw.like(StringUtils.isNotBlank(bo.getAreaName()), XgDormViolation::getAreaName, bo.getAreaName());
lqw.eq(bo.getBuildingId() != null, XgDormViolation::getBuildingId, bo.getBuildingId());
lqw.like(StringUtils.isNotBlank(bo.getBuildingName()), XgDormViolation::getBuildingName, bo.getBuildingName());
lqw.eq(bo.getRoomId() != null, XgDormViolation::getRoomId, bo.getRoomId());
lqw.like(StringUtils.isNotBlank(bo.getRoomName()), XgDormViolation::getRoomName, bo.getRoomName());
lqw.eq(bo.getBedId() != null, XgDormViolation::getBedId, bo.getBedId());
lqw.like(StringUtils.isNotBlank(bo.getBedName()), XgDormViolation::getBedName, bo.getBedName());
lqw.eq(StringUtils.isNotBlank(bo.getViolationType()), XgDormViolation::getViolationType, bo.getViolationType());
lqw.eq(StringUtils.isNotBlank(bo.getViolationLevel()), XgDormViolation::getViolationLevel,
bo.getViolationLevel());
lqw.eq(bo.getViolationTime() != null, XgDormViolation::getViolationTime, bo.getViolationTime());
lqw.like(StringUtils.isNotBlank(bo.getViolationDescription()), XgDormViolation::getViolationDescription,
bo.getViolationDescription());
lqw.like(StringUtils.isNotBlank(bo.getInvolvedStudents()), XgDormViolation::getInvolvedStudents,
bo.getInvolvedStudents());
lqw.like(StringUtils.isNotBlank(bo.getAttachmentOssIds()), XgDormViolation::getAttachmentOssIds,
bo.getAttachmentOssIds());
lqw.eq(StringUtils.isNotBlank(bo.getDeleted()), XgDormViolation::getDeleted, bo.getDeleted());
return lqw;
}
/**
* 新增宿舍违纪记录
*
* @param bo 宿舍违纪记录
* @return 是否新增成功
*/
@Override
public Boolean insertByBo(XgDormViolationBo bo) {
XgDormViolation add = MapstructUtils.convert(bo, XgDormViolation.class);
validEntityBeforeSave(add);
boolean flag = baseMapper.insert(add) > 0;
if (flag) {
bo.setId(add.getId());
}
return flag;
}
/**
* 修改宿舍违纪记录
*
* @param bo 宿舍违纪记录
* @return 是否修改成功
*/
@Override
public Boolean updateByBo(XgDormViolationBo bo) {
XgDormViolation update = MapstructUtils.convert(bo, XgDormViolation.class);
validEntityBeforeSave(update);
return baseMapper.updateById(update) > 0;
}
/**
* 保存前的数据校验
*/
private void validEntityBeforeSave(XgDormViolation entity) {
// TODO 做一些数据校验,如唯一约束
}
/**
* 校验并批量删除宿舍违纪记录信息
*
* @param ids 待删除的主键集合
* @param isValid 是否进行有效性校验
* @return 是否删除成功
*/
@Override
public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
if (isValid) {
// TODO 做一些业务上的校验,判断是否需要校验
}
return baseMapper.deleteByIds(ids) > 0;
}
/**
* 获取学生选择器选项列表(支持按学号、姓名检索)
*
* @param bo 查询条件
* @param pageQuery 分页参数
* @return 学生选项分页列表
*/
@Override
public TableDataInfo<StudentOptionVo> getStudentOptions(StudentOptionBo bo, PageQuery pageQuery) {
Page<StudentOptionVo> result = baseMapper.selectStudentOptions(pageQuery.build(), bo);
return TableDataInfo.build(result);
}
/**
* 根据学生ID获取学生详细信息
*
* @param studentId 学生ID
* @return 学生详细信息
*/
@Override
public StudentOptionVo getStudentById(Long studentId) {
return baseMapper.selectStudentById(studentId);
}
/**
* 根据学号获取学生详细信息
*
* @param studentNo 学号
* @return 学生详细信息
*/
@Override
public StudentOptionVo getStudentByStudentNo(String studentNo) {
return baseMapper.selectStudentByStudentNo(studentNo);
}
/**
* 导入宿舍违纪记录数据
*
* @param importList 导入的宿舍违纪记录列表
* @param isUpdateSupport 是否支持更新已存在的记录
* @param operName 操作人员名称
* @return 导入结果信息
*/
@Override
public String importDormViolation(List<XgDormViolationImportVo> importList, boolean isUpdateSupport,
String operName) {
if (ObjectUtil.isNull(importList) || importList.isEmpty()) {
throw new RuntimeException("导入宿舍违纪记录数据不能为空!");
}
int successNum = 0;
int failureNum = 0;
StringBuilder successMsg = new StringBuilder();
StringBuilder failureMsg = new StringBuilder();
for (XgDormViolationImportVo importVo : importList) {
try {
// 通过学号查询学生信息
StudentOptionVo student = this.getStudentByStudentNo(importVo.getStudentNo());
if (student == null) {
failureNum++;
String msg = "<br/>" + failureNum + "、学号 " + importVo.getStudentNo() + " 的学生信息不存在";
failureMsg.append(msg);
continue;
}
// 验证学生姓名是否匹配
// if (!student.getStudentName().equals(importVo.getStudentName())) {
// failureNum++;
// String msg = "<br/>" + failureNum + "、学号 " + importVo.getStudentNo() + "
// 对应的学生姓名不匹配,数据库中为:"
// + student.getStudentName() + ",导入数据为:" + importVo.getStudentName();
// failureMsg.append(msg);
// continue;
// }
// 创建宿舍违纪记录
XgDormViolation violation = new XgDormViolation();
violation.setStudentId(student.getId());
violation.setStudentName(student.getName());
violation.setStudentNo(student.getStudentNo());
violation.setCollegeId(student.getCollegeId());
violation.setCollegeName(student.getCollegeName());
violation.setMajorId(student.getMajorId());
violation.setMajorName(student.getMajorName());
violation.setClassId(student.getClassId());
violation.setClassName(student.getClassName());
violation.setCampusId(student.getDormInfo().getCampusId());
violation.setCampusName(student.getDormInfo().getCampusName());
violation.setAreaId(student.getDormInfo().getAreaId());
violation.setAreaName(student.getDormInfo().getAreaName());
violation.setBuildingId(student.getDormInfo().getBuildingId());
violation.setBuildingName(student.getDormInfo().getBuildingName());
violation.setRoomId(student.getDormInfo().getRoomId());
violation.setRoomName(student.getDormInfo().getRoomName());
violation.setBedId(student.getDormInfo().getBedId());
violation.setBedName(student.getDormInfo().getBedName());
violation.setViolationType(importVo.getViolationType());
violation.setViolationLevel(importVo.getViolationLevel());
violation.setViolationTime(importVo.getViolationTime());
violation.setViolationDescription(importVo.getViolationDescription());
violation.setRemark(importVo.getRemark());
// 插入数据
baseMapper.insert(violation);
successNum++;
successMsg.append("<br/>" + successNum + "、学号 " + importVo.getStudentNo() + " 的宿舍违纪记录导入成功");
} catch (Exception e) {
failureNum++;
String msg = "<br/>" + failureNum + "、学号 " + importVo.getStudentNo() + " 导入失败:" + e.getMessage();
failureMsg.append(msg);
log.error("导入宿舍违纪记录失败", e);
}
}
if (failureNum > 0) {
failureMsg.insert(0, "很抱歉,导入失败!共 " + failureNum + " 条数据格式不正确,错误如下:");
throw new RuntimeException(failureMsg.toString());
} else {
successMsg.insert(0, "恭喜您,数据已全部导入成功!共 " + successNum + " 条,数据如下:");
}
return successMsg.toString();
}
}
@@ -0,0 +1,217 @@
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.mybatis.core.page.PageQuery;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.dromara.xg.domain.bo.XgHolidayStayBo;
import org.dromara.xg.domain.vo.XgHolidayStayVo;
import org.dromara.xg.domain.XgHolidayStay;
import org.dromara.xg.domain.bo.StudentOptionBo;
import org.dromara.xg.domain.vo.StudentOptionVo;
import org.dromara.xg.mapper.XgHolidayStayMapper;
import org.dromara.xg.service.IXgHolidayStayService;
import java.util.List;
import java.util.Map;
import java.util.Collection;
/**
* 假期留宿管理Service业务层处理
*
* @author zlwu
* @date 2025-08-15
*/
@Slf4j
@RequiredArgsConstructor
@Service
public class XgHolidayStayServiceImpl implements IXgHolidayStayService {
private final XgHolidayStayMapper baseMapper;
/**
* 查询假期留宿管理
*
* @param id 主键
* @return 假期留宿管理
*/
@Override
public XgHolidayStayVo queryById(Long id) {
return baseMapper.selectVoById(id);
}
/**
* 分页查询假期留宿管理列表
*
* @param bo 查询条件
* @param pageQuery 分页参数
* @return 假期留宿管理分页列表
*/
@Override
public TableDataInfo<XgHolidayStayVo> queryPageList(XgHolidayStayBo bo, PageQuery pageQuery) {
LambdaQueryWrapper<XgHolidayStay> lqw = buildQueryWrapper(bo);
Page<XgHolidayStayVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
return TableDataInfo.build(result);
}
/**
* 查询符合条件的假期留宿管理列表
*
* @param bo 查询条件
* @return 假期留宿管理列表
*/
@Override
public List<XgHolidayStayVo> queryList(XgHolidayStayBo bo) {
LambdaQueryWrapper<XgHolidayStay> lqw = buildQueryWrapper(bo);
return baseMapper.selectVoList(lqw);
}
private LambdaQueryWrapper<XgHolidayStay> buildQueryWrapper(XgHolidayStayBo bo) {
Map<String, Object> params = bo.getParams();
LambdaQueryWrapper<XgHolidayStay> lqw = Wrappers.lambdaQuery();
lqw.orderByAsc(XgHolidayStay::getId);
lqw.eq(bo.getDeleted() != null, XgHolidayStay::getDeleted, bo.getDeleted());
lqw.eq(bo.getStudentId() != null, XgHolidayStay::getStudentId, bo.getStudentId());
lqw.like(StringUtils.isNotBlank(bo.getStudentName()), XgHolidayStay::getStudentName, bo.getStudentName());
lqw.like(StringUtils.isNotBlank(bo.getStudentNo()), XgHolidayStay::getStudentNo, bo.getStudentNo());
lqw.eq(bo.getClassId() != null, XgHolidayStay::getClassId, bo.getClassId());
lqw.like(StringUtils.isNotBlank(bo.getClassName()), XgHolidayStay::getClassName, bo.getClassName());
lqw.eq(bo.getMajorId() != null, XgHolidayStay::getMajorId, bo.getMajorId());
lqw.like(StringUtils.isNotBlank(bo.getMajorName()), XgHolidayStay::getMajorName, bo.getMajorName());
lqw.eq(bo.getCollegeId() != null, XgHolidayStay::getCollegeId, bo.getCollegeId());
lqw.like(StringUtils.isNotBlank(bo.getCollegeName()), XgHolidayStay::getCollegeName, bo.getCollegeName());
lqw.eq(bo.getCampusId() != null, XgHolidayStay::getCampusId, bo.getCampusId());
lqw.like(StringUtils.isNotBlank(bo.getCampusName()), XgHolidayStay::getCampusName, bo.getCampusName());
lqw.eq(bo.getAreaId() != null, XgHolidayStay::getAreaId, bo.getAreaId());
lqw.like(StringUtils.isNotBlank(bo.getAreaName()), XgHolidayStay::getAreaName, bo.getAreaName());
lqw.eq(bo.getBuildingId() != null, XgHolidayStay::getBuildingId, bo.getBuildingId());
lqw.like(StringUtils.isNotBlank(bo.getBuildingName()), XgHolidayStay::getBuildingName, bo.getBuildingName());
lqw.eq(bo.getRoomId() != null, XgHolidayStay::getRoomId, bo.getRoomId());
lqw.like(StringUtils.isNotBlank(bo.getRoomName()), XgHolidayStay::getRoomName, bo.getRoomName());
lqw.eq(bo.getBedId() != null, XgHolidayStay::getBedId, bo.getBedId());
lqw.like(StringUtils.isNotBlank(bo.getBedName()), XgHolidayStay::getBedName, bo.getBedName());
lqw.eq(StringUtils.isNotBlank(bo.getHolidayType()), XgHolidayStay::getHolidayType, bo.getHolidayType());
lqw.ge(bo.getApplyStartDate() != null, XgHolidayStay::getApplyStartDate, bo.getApplyStartDate());
lqw.le(bo.getApplyEndDate() != null, XgHolidayStay::getApplyEndDate, bo.getApplyEndDate());
lqw.like(StringUtils.isNotBlank(bo.getStayReason()), XgHolidayStay::getStayReason, bo.getStayReason());
lqw.eq(StringUtils.isNotBlank(bo.getStayReasonType()), XgHolidayStay::getStayReasonType,
bo.getStayReasonType());
lqw.like(StringUtils.isNotBlank(bo.getStudentPhone()), XgHolidayStay::getStudentPhone, bo.getStudentPhone());
lqw.like(StringUtils.isNotBlank(bo.getEmergencyContact()), XgHolidayStay::getEmergencyContact,
bo.getEmergencyContact());
lqw.like(StringUtils.isNotBlank(bo.getEmergencyPhone()), XgHolidayStay::getEmergencyPhone,
bo.getEmergencyPhone());
lqw.eq(StringUtils.isNotBlank(bo.getParentConsent()), XgHolidayStay::getParentConsent, bo.getParentConsent());
lqw.like(StringUtils.isNotBlank(bo.getAttachmentOssIds()), XgHolidayStay::getAttachmentOssIds,
bo.getAttachmentOssIds());
lqw.eq(StringUtils.isNotBlank(bo.getExtField1()), XgHolidayStay::getExtField1, bo.getExtField1());
lqw.eq(StringUtils.isNotBlank(bo.getExtField2()), XgHolidayStay::getExtField2, bo.getExtField2());
lqw.eq(StringUtils.isNotBlank(bo.getExtField3()), XgHolidayStay::getExtField3, bo.getExtField3());
// 添加状态过滤逻辑
addStatusFilter(lqw, bo);
return lqw;
}
/**
* 添加状态过滤条件
*
* @param lqw 查询条件构造器
* @param bo 查询参数对象
*/
private void addStatusFilter(LambdaQueryWrapper<XgHolidayStay> lqw, XgHolidayStayBo bo) {
// 从参数中获取状态过滤条件
if (bo.getParams() != null) {
String statusType = (String) bo.getParams().get("statusType");
String currentTime = (String) bo.getParams().get("currentTime");
if (StringUtils.isNotBlank(statusType) && StringUtils.isNotBlank(currentTime)) {
if ("valid".equals(statusType)) {
// 有效状态:结束时间 >= 当前时间 AND 结束时间不为空
lqw.ge(XgHolidayStay::getApplyEndDate, currentTime)
.isNotNull(XgHolidayStay::getApplyEndDate);
log.debug("添加有效状态过滤条件: apply_end_date >= {} AND apply_end_date IS NOT NULL", currentTime);
} else if ("invalid".equals(statusType)) {
// 失效状态:结束时间 < 当前时间 OR 结束时间为空
lqw.and(wrapper -> wrapper
.lt(XgHolidayStay::getApplyEndDate, currentTime)
.or()
.isNull(XgHolidayStay::getApplyEndDate));
log.debug("添加失效状态过滤条件: apply_end_date < {} OR apply_end_date IS NULL", currentTime);
}
}
}
}
/**
* 新增假期留宿管理
*
* @param bo 假期留宿管理
* @return 是否新增成功
*/
@Override
public Boolean insertByBo(XgHolidayStayBo bo) {
XgHolidayStay add = MapstructUtils.convert(bo, XgHolidayStay.class);
validEntityBeforeSave(add);
boolean flag = baseMapper.insert(add) > 0;
if (flag) {
bo.setId(add.getId());
}
return flag;
}
/**
* 修改假期留宿管理
*
* @param bo 假期留宿管理
* @return 是否修改成功
*/
@Override
public Boolean updateByBo(XgHolidayStayBo bo) {
XgHolidayStay update = MapstructUtils.convert(bo, XgHolidayStay.class);
validEntityBeforeSave(update);
return baseMapper.updateById(update) > 0;
}
/**
* 保存前的数据校验
*/
private void validEntityBeforeSave(XgHolidayStay entity) {
// TODO 做一些数据校验,如唯一约束
}
/**
* 校验并批量删除假期留宿管理信息
*
* @param ids 待删除的主键集合
* @param isValid 是否进行有效性校验
* @return 是否删除成功
*/
@Override
public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
if (isValid) {
// TODO 做一些业务上的校验,判断是否需要校验
}
return baseMapper.deleteByIds(ids) > 0;
}
/**
* 获取学生选择器选项列表(支持按学号、姓名检索)
*
* @param bo 查询条件
* @param pageQuery 分页参数
* @return 学生选项分页列表
*/
@Override
public TableDataInfo<StudentOptionVo> getStudentOptions(StudentOptionBo bo, PageQuery pageQuery) {
Page<StudentOptionVo> result = baseMapper.selectStudentOptions(pageQuery.build(), bo);
return TableDataInfo.build(result);
}
}
@@ -167,6 +167,7 @@ public class XgStudentManagerSourceServiceImpl implements IXgStudentManagerSourc
}
@Override
@Transactional(readOnly = true)
public List<String> getAuthSourceNames(Long managerId) {
// 1. 查询xg_student_manager_source表,manager_id=managerId, deleted=0,
// status=0,获取auth_source
@@ -190,6 +191,7 @@ public class XgStudentManagerSourceServiceImpl implements IXgStudentManagerSourc
}
@Override
@Transactional(readOnly = true)
public List<XgStudentManagerDeptTreeVo> getCurrentUserAuthDeptTree() {
// 获取当前登录用户ID
Long currentUserId = LoginHelper.getUserId();
@@ -37,11 +37,13 @@ import org.dromara.xg.mapper.XgStudentManagerSourceMapper;
import org.dromara.xg.mapper.XgClassTeacherCounselorRelMapper;
import org.dromara.xg.mapper.XgClassMsgMapper;
import org.dromara.xg.mapper.XgDormBedStudentMapper;
import org.dromara.xg.mapper.XgSysDeptMapper;
import org.dromara.xg.domain.XgStudentManager;
import org.dromara.xg.domain.XgStudentManagerSource;
import org.dromara.xg.domain.XgClassTeacherCounselorRel;
import org.dromara.xg.domain.XgClassMsg;
import org.dromara.xg.domain.XgDormBedStudent;
import org.dromara.xg.domain.XgSysDept;
import org.dromara.common.satoken.utils.LoginHelper;
import java.util.stream.Collectors;
@@ -73,6 +75,7 @@ public class XgStudentMsgServiceImpl implements IXgStudentMsgService {
private final XgClassTeacherCounselorRelMapper xgClassTeacherCounselorRelMapper;
private final XgClassMsgMapper xgClassMsgMapper;
private final XgDormBedStudentMapper xgDormBedStudentMapper;
private final XgSysDeptMapper xgSysDeptMapper;
/**
* 查询学生信息
@@ -1159,20 +1162,80 @@ public class XgStudentMsgServiceImpl implements IXgStudentMsgService {
}
/**
* 获取学生信息树(二级学院下的学院、专业、班级统计信息)
* 获取学生信息树(二级学院下的学院床位分配统计信息)
* 基于college_id判断床位分配情况,只显示学院层级
*
* @param secondaryCollegeId 二级学院ID,默认101
* @return 学生信息树
*/
@Override
public List<XgStudentTreeVo> getStudentTree(Long secondaryCollegeId) {
log.info("开始构建学生信息树,二级学院ID: {}", secondaryCollegeId);
log.info("开始构建学生信息树(基于college_id床位分配统计),二级学院ID: {}", secondaryCollegeId);
List<XgStudentTreeVo> result = new ArrayList<>();
try {
// 1. 查询二级学院下的所有学院信息,并统计男女生人数
List<Map<String, Object>> collegeStats = baseMapper.getCollegeStudentStats(secondaryCollegeId);
// 1. 查询二级学院下的所有学院信息,并统计男女生床位分配情况
// 使用新的查询方法,基于college_id统计床位分配
List<Map<String, Object>> collegeStats = baseMapper.getCollegeBedAssignmentStats(secondaryCollegeId);
log.info("查询到 {} 个学院的床位分配统计", collegeStats.size());
// 2. 构建学院节点(只显示学院层级)
for (Map<String, Object> collegeItem : collegeStats) {
Object collegeIdObj = collegeItem.get("college_id");
Long collegeId = collegeIdObj instanceof Long ? (Long) collegeIdObj
: Long.valueOf(collegeIdObj.toString());
String collegeName = (String) collegeItem.get("college_name");
// 获取统计数据
Integer maleTotal = ((Number) collegeItem.get("male_total")).intValue();
Integer femaleTotal = ((Number) collegeItem.get("female_total")).intValue();
Integer maleAssigned = ((Number) collegeItem.get("male_assigned")).intValue();
Integer femaleAssigned = ((Number) collegeItem.get("female_assigned")).intValue();
XgStudentTreeVo collegeNode = new XgStudentTreeVo();
collegeNode.setId("college-" + collegeId);
collegeNode.setLabel(collegeName);
collegeNode.setType("college");
collegeNode.setCollegeId(collegeId);
collegeNode.setCollegeName(collegeName);
collegeNode.setMaleTotal(maleTotal);
collegeNode.setFemaleTotal(femaleTotal);
collegeNode.setMaleAssigned(maleAssigned);
collegeNode.setFemaleAssigned(femaleAssigned);
// 设置为null表示不展示子节点
collegeNode.setChildren(null);
result.add(collegeNode);
log.debug("学院 {} 统计 - 男生总数: {}, 女生总数: {}, 男生已分配: {}, 女生已分配: {}",
collegeName, maleTotal, femaleTotal, maleAssigned, femaleAssigned);
}
log.info("学生信息树构建完成,共 {} 个学院节点", result.size());
} catch (Exception e) {
log.error("构建学生信息树失败", e);
throw new RuntimeException("构建学生信息树失败: " + e.getMessage());
}
return result;
}
/**
* 获取学生信息树(二级学院下的学院、专业、班级统计信息)- 按班级床位分配统计
*
* @param secondaryCollegeId 二级学院ID,默认101
* @return 学生信息树
*/
public List<XgStudentTreeVo> getStudentTreeByClass(Long secondaryCollegeId) {
log.info("开始构建学生信息树(按床位分配统计),二级学院ID: {}", secondaryCollegeId);
List<XgStudentTreeVo> result = new ArrayList<>();
try {
// 1. 查询二级学院下的所有学院信息,并统计男女生人数(使用新的按班级床位分配统计方法)
List<Map<String, Object>> collegeStats = baseMapper.getCollegeStudentStatsByClass(secondaryCollegeId);
log.info("查询到 {} 个学院", collegeStats.size());
// 按学院分组
@@ -1190,131 +1253,199 @@ public class XgStudentMsgServiceImpl implements IXgStudentMsgService {
String collegeKey = collegeEntry.getKey();
List<Map<String, Object>> collegeMajors = collegeEntry.getValue();
if (!collegeMajors.isEmpty()) {
Map<String, Object> firstItem = collegeMajors.get(0);
Object collegeIdObj = firstItem.get("college_id");
Long collegeId = collegeIdObj instanceof Long ? (Long) collegeIdObj
: Long.valueOf(collegeIdObj.toString());
String collegeName = (String) firstItem.get("college_name");
String[] keyParts = collegeKey.split("_");
Long collegeId = Long.valueOf(keyParts[0]);
String collegeName = keyParts[1];
XgStudentTreeVo collegeNode = new XgStudentTreeVo();
collegeNode.setId("college-" + collegeId);
collegeNode.setLabel(collegeName);
collegeNode.setType("college");
collegeNode.setCollegeId(collegeId);
collegeNode.setCollegeName(collegeName);
collegeNode.setChildren(new ArrayList<>());
// 计算学院级别的统计信息
int collegeMaleTotal = 0;
int collegeFemaleTotal = 0;
int collegeMaleAssigned = 0;
int collegeFemaleAssigned = 0;
// 统计学院人数
int collegeMaleTotal = 0, collegeFemaleTotal = 0;
int collegeMaleAssigned = 0, collegeFemaleAssigned = 0;
for (Map<String, Object> item : collegeMajors) {
collegeMaleTotal += ((Number) item.get("male_total")).intValue();
collegeFemaleTotal += ((Number) item.get("female_total")).intValue();
collegeMaleAssigned += ((Number) item.get("male_assigned")).intValue();
collegeFemaleAssigned += ((Number) item.get("female_assigned")).intValue();
}
// 按专业分组
Map<String, List<Map<String, Object>>> majorMap = collegeMajors.stream()
.collect(Collectors.groupingBy(item -> {
Object majorIdObj = item.get("major_id");
Long majorId = majorIdObj instanceof Long ? (Long) majorIdObj
: Long.valueOf(majorIdObj.toString());
String majorName = (String) item.get("major_name");
return majorId + "_" + majorName;
}));
XgStudentTreeVo collegeNode = new XgStudentTreeVo();
collegeNode.setId(collegeId.toString());
collegeNode.setLabel(collegeName);
collegeNode.setType("college");
collegeNode.setCollegeId(collegeId);
collegeNode.setCollegeName(collegeName);
collegeNode.setMaleTotal(collegeMaleTotal);
collegeNode.setFemaleTotal(collegeFemaleTotal);
collegeNode.setMaleAssigned(collegeMaleAssigned);
collegeNode.setFemaleAssigned(collegeFemaleAssigned);
collegeNode.setChildren(new ArrayList<>());
// 3. 构建专业节点
for (Map.Entry<String, List<Map<String, Object>>> majorEntry : majorMap.entrySet()) {
String majorKey = majorEntry.getKey();
List<Map<String, Object>> majorClasses = majorEntry.getValue();
if (!majorClasses.isEmpty()) {
Map<String, Object> firstMajorItem = majorClasses.get(0);
Object majorIdObj = firstMajorItem.get("major_id");
// 按专业分组
Map<String, List<Map<String, Object>>> majorMap = collegeMajors.stream()
.collect(Collectors.groupingBy(item -> {
Object majorIdObj = item.get("major_id");
Long majorId = majorIdObj instanceof Long ? (Long) majorIdObj
: Long.valueOf(majorIdObj.toString());
String majorName = (String) firstMajorItem.get("major_name");
String majorName = (String) item.get("major_name");
return majorId + "_" + majorName;
}));
XgStudentTreeVo majorNode = new XgStudentTreeVo();
majorNode.setId("major-" + majorId);
majorNode.setLabel(majorName);
majorNode.setType("major");
majorNode.setCollegeId(collegeId);
majorNode.setCollegeName(collegeName);
majorNode.setMajorId(majorId);
majorNode.setMajorName(majorName);
majorNode.setChildren(new ArrayList<>());
// 3. 构建专业节点
for (Map.Entry<String, List<Map<String, Object>>> majorEntry : majorMap.entrySet()) {
String majorKey = majorEntry.getKey();
List<Map<String, Object>> majorClasses = majorEntry.getValue();
// 统计专业人数
int majorMaleTotal = 0, majorFemaleTotal = 0;
int majorMaleAssigned = 0, majorFemaleAssigned = 0;
String[] majorKeyParts = majorKey.split("_");
Long majorId = Long.valueOf(majorKeyParts[0]);
String majorName = majorKeyParts[1];
// 4. 构建班级节点
for (Map<String, Object> classItem : majorClasses) {
Object classIdObj = classItem.get("class_id");
Long classId = classIdObj instanceof Long ? (Long) classIdObj
: Long.valueOf(classIdObj.toString());
String className = (String) classItem.get("class_name");
String grade = (String) classItem.get("grade");
Integer maleTotal = ((Number) classItem.get("male_total")).intValue();
Integer femaleTotal = ((Number) classItem.get("female_total")).intValue();
Integer maleAssigned = ((Number) classItem.get("male_assigned")).intValue();
Integer femaleAssigned = ((Number) classItem.get("female_assigned")).intValue();
// 计算专业级别的统计信息
int majorMaleTotal = 0;
int majorFemaleTotal = 0;
int majorMaleAssigned = 0;
int majorFemaleAssigned = 0;
XgStudentTreeVo classNode = new XgStudentTreeVo();
classNode.setId("class-" + classId);
classNode.setLabel(className);
classNode.setType("class");
classNode.setCollegeId(collegeId);
classNode.setCollegeName(collegeName);
classNode.setMajorId(majorId);
classNode.setMajorName(majorName);
classNode.setClassId(classId);
classNode.setClassName(className);
classNode.setGrade(grade);
classNode.setMaleTotal(maleTotal);
classNode.setFemaleTotal(femaleTotal);
classNode.setMaleAssigned(maleAssigned);
classNode.setFemaleAssigned(femaleAssigned);
majorNode.getChildren().add(classNode);
// 累计专业人数
majorMaleTotal += maleTotal;
majorFemaleTotal += femaleTotal;
majorMaleAssigned += maleAssigned;
majorFemaleAssigned += femaleAssigned;
}
// 设置专业统计
majorNode.setMaleTotal(majorMaleTotal);
majorNode.setFemaleTotal(majorFemaleTotal);
majorNode.setMaleAssigned(majorMaleAssigned);
majorNode.setFemaleAssigned(majorFemaleAssigned);
collegeNode.getChildren().add(majorNode);
// 累计学院人数
collegeMaleTotal += majorMaleTotal;
collegeFemaleTotal += majorFemaleTotal;
collegeMaleAssigned += majorMaleAssigned;
collegeFemaleAssigned += majorFemaleAssigned;
}
for (Map<String, Object> item : majorClasses) {
majorMaleTotal += ((Number) item.get("male_total")).intValue();
majorFemaleTotal += ((Number) item.get("female_total")).intValue();
majorMaleAssigned += ((Number) item.get("male_assigned")).intValue();
majorFemaleAssigned += ((Number) item.get("female_assigned")).intValue();
}
// 设置学院统计
collegeNode.setMaleTotal(collegeMaleTotal);
collegeNode.setFemaleTotal(collegeFemaleTotal);
collegeNode.setMaleAssigned(collegeMaleAssigned);
collegeNode.setFemaleAssigned(collegeFemaleAssigned);
XgStudentTreeVo majorNode = new XgStudentTreeVo();
majorNode.setId(majorId.toString());
majorNode.setLabel(majorName);
majorNode.setType("major");
majorNode.setMajorId(majorId);
majorNode.setMajorName(majorName);
majorNode.setMaleTotal(majorMaleTotal);
majorNode.setFemaleTotal(majorFemaleTotal);
majorNode.setMaleAssigned(majorMaleAssigned);
majorNode.setFemaleAssigned(majorFemaleAssigned);
majorNode.setChildren(new ArrayList<>());
result.add(collegeNode);
// 4. 构建班级节点
for (Map<String, Object> classData : majorClasses) {
Object classIdObj = classData.get("class_id");
Long classId = classIdObj instanceof Long ? (Long) classIdObj
: Long.valueOf(classIdObj.toString());
String className = (String) classData.get("class_name");
String grade = (String) classData.get("grade");
int classMaleTotal = ((Number) classData.get("male_total")).intValue();
int classFemaleTotal = ((Number) classData.get("female_total")).intValue();
int classMaleAssigned = ((Number) classData.get("male_assigned")).intValue();
int classFemaleAssigned = ((Number) classData.get("female_assigned")).intValue();
XgStudentTreeVo classNode = new XgStudentTreeVo();
classNode.setId(classId.toString());
classNode.setLabel(className);
classNode.setType("class");
classNode.setGrade(grade);
classNode.setClassId(classId);
classNode.setClassName(className);
classNode.setMaleTotal(classMaleTotal);
classNode.setFemaleTotal(classFemaleTotal);
classNode.setMaleAssigned(classMaleAssigned);
classNode.setFemaleAssigned(classFemaleAssigned);
classNode.setChildren(new ArrayList<>());
majorNode.getChildren().add(classNode);
}
collegeNode.getChildren().add(majorNode);
}
result.add(collegeNode);
}
log.info("学生信息树构建完成,共 {} 个学院节点", result.size());
log.info("成功构建学生信息树,共 {} 个学院", result.size());
} catch (Exception e) {
log.error("构建学生信息树失败", e);
throw new RuntimeException("构建学生信息树失败: " + e.getMessage());
}
return result;
}
/**
* 获取当前用户所在学院的学生信息树
*
* @return 学生信息树
*/
@Override
public List<XgStudentTreeVo> getCurrentUserStudentTree() {
try {
// 1. 获取当前用户的二级学院ID
Long collegeId = getCurrentUserCollegeId();
if (collegeId == null) {
log.warn("无法获取当前用户的二级学院信息");
return new ArrayList<>();
}
log.info("获取到当前用户的学院ID: {}", collegeId);
// 2. 调用按床位分配统计的方法
return getStudentTreeByClass(collegeId);
} catch (Exception e) {
log.error("获取当前用户学院的学生信息树失败", e);
return new ArrayList<>();
}
}
/**
* 获取当前用户的二级学院ID
* 通过当前用户的部门id,向上寻找包括他自己,找到dept_category前几位是xy-的就是二级学院
* 或者parent_id = 101的部门就是二级学院
*/
private Long getCurrentUserCollegeId() {
try {
Long currentUserId = LoginHelper.getUserId();
Long currentDeptId = LoginHelper.getDeptId();
if (currentUserId == null || currentDeptId == null) {
log.warn("用户未登录或没有部门信息");
return null;
}
// 首先查找parent_id = 101的部门(使用LambdaQueryWrapper)
LambdaQueryWrapper<XgSysDept> parentQuery = Wrappers.lambdaQuery();
parentQuery.eq(XgSysDept::getParentId, 101L)
.eq(XgSysDept::getStatus, "0")
.eq(XgSysDept::getDelFlag, "0")
.and(wrapper -> wrapper.eq(XgSysDept::getDeptId, currentDeptId)
.or().like(XgSysDept::getAncestors, "," + currentDeptId + ",") // 中间位置
.or().likeRight(XgSysDept::getAncestors, currentDeptId + ",") // 开头位置
.or().likeLeft(XgSysDept::getAncestors, "," + currentDeptId) // 末尾位置
.or().eq(XgSysDept::getAncestors, currentDeptId.toString())) // 单独一个值
.last("LIMIT 1");
List<XgSysDept> parentColleges = xgSysDeptMapper.selectList(parentQuery);
if (!parentColleges.isEmpty()) {
return parentColleges.get(0).getDeptId();
}
// 如果上面的查询没找到,尝试通过dept_category查找
LambdaQueryWrapper<XgSysDept> categoryQuery = Wrappers.lambdaQuery();
categoryQuery.likeRight(XgSysDept::getDeptCategory, "xy-")
.eq(XgSysDept::getStatus, "0")
.eq(XgSysDept::getDelFlag, "0")
.and(wrapper -> wrapper.eq(XgSysDept::getDeptId, currentDeptId)
.or().like(XgSysDept::getAncestors, "," + currentDeptId + ",") // 中间位置
.or().likeRight(XgSysDept::getAncestors, currentDeptId + ",") // 开头位置
.or().likeLeft(XgSysDept::getAncestors, "," + currentDeptId) // 末尾位置
.or().eq(XgSysDept::getAncestors, currentDeptId.toString())) // 单独一个值
.last("LIMIT 1");
List<XgSysDept> categoryColleges = xgSysDeptMapper.selectList(categoryQuery);
return categoryColleges.isEmpty() ? null : categoryColleges.get(0).getDeptId();
} catch (Exception e) {
log.error("获取当前用户二级学院ID失败", e);
return null;
}
}
}
@@ -0,0 +1,121 @@
<?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.XgDormHygieneCheckMapper">
<resultMap type="org.dromara.xg.domain.vo.DormHygieneCheckExportVo" id="DormHygieneCheckExportResult">
<result property="checkTitle" column="check_title" />
<result property="checkDate" column="check_date" />
<result property="checkerName" column="checker_name" />
<result property="checkTypeText" column="check_type" />
<result property="checkLevelText" column="check_level" />
<result property="campusName" column="campus_name" />
<result property="areaName" column="area_name" />
<result property="buildingName" column="building_name" />
<result property="roomName" column="room_name" />
<result property="totalScore" column="total_score" />
<result property="hygieneGradeText" column="hygiene_grade" />
<result property="studentNo" column="student_no" />
<result property="studentName" column="student_name" />
<result property="className" column="class_name" />
<result property="majorName" column="major_name" />
<result property="collegeName" column="college_name" />
<result property="bedCode" column="bed_code" />
<result property="studentScore" column="student_score" />
<result property="attendanceStatusText" column="attendance_status" />
<result property="studentGradeText" column="student_grade" />
<result property="isResponsiblePersonText" column="is_responsible_person" />
<result property="scoreRemarks" column="score_remarks" />
<result property="improvementNotes" column="improvement_notes" />
<result property="checkSummary" column="check_summary" />
<result property="improvementSuggestions" column="improvement_suggestions" />
</resultMap>
<select id="selectExportList" parameterType="org.dromara.xg.domain.bo.XgDormHygieneCheckBo" resultMap="DormHygieneCheckExportResult">
SELECT
dhc.check_title,
DATE_FORMAT(dhc.check_date, '%Y-%m-%d') as check_date,
dhc.checker_name,
dhc.check_type,
dhc.check_level,
dhc.campus_name,
dhc.area_name,
dhc.building_name,
dhc.room_name,
dhc.total_score,
dhc.hygiene_grade,
dhc.check_summary,
dhc.improvement_suggestions,
COALESCE(dhss.student_no, '') as student_no,
COALESCE(dhss.student_name, '') as student_name,
COALESCE(dhss.class_name, '') as class_name,
COALESCE(dhss.major_name, '') as major_name,
COALESCE(dhss.college_name, '') as college_name,
COALESCE(dhss.bed_code, '') as bed_code,
COALESCE(dhss.student_score, 0) as student_score,
COALESCE(dhss.attendance_status, '') as attendance_status,
COALESCE(dhss.student_grade, '') as student_grade,
COALESCE(dhss.is_responsible_person, 0) as is_responsible_person,
COALESCE(dhss.score_remarks, '') as score_remarks,
COALESCE(dhss.improvement_notes, '') as improvement_notes
FROM xg_dorm_hygiene_check dhc
LEFT JOIN xg_dorm_hygiene_student_score dhss ON dhc.id = dhss.hygiene_check_id AND dhss.deleted = 0
<where>
dhc.deleted = 0
<if test="checkTitle != null and checkTitle != ''">
AND dhc.check_title LIKE CONCAT('%', #{checkTitle}, '%')
</if>
<if test="checkDate != null and checkDate != ''">
AND DATE_FORMAT(dhc.check_date, '%Y-%m-%d') = #{checkDate}
</if>
<if test="checkerId != null">
AND dhc.checker_id = #{checkerId}
</if>
<if test="checkerName != null and checkerName != ''">
AND dhc.checker_name LIKE CONCAT('%', #{checkerName}, '%')
</if>
<if test="checkType != null and checkType != ''">
AND dhc.check_type = #{checkType}
</if>
<if test="checkLevel != null and checkLevel != ''">
AND dhc.check_level = #{checkLevel}
</if>
<if test="roomId != null">
AND dhc.room_id = #{roomId}
</if>
<if test="roomName != null and roomName != ''">
AND dhc.room_name LIKE CONCAT('%', #{roomName}, '%')
</if>
<if test="buildingId != null">
AND dhc.building_id = #{buildingId}
</if>
<if test="buildingName != null and buildingName != ''">
AND dhc.building_name LIKE CONCAT('%', #{buildingName}, '%')
</if>
<if test="areaId != null">
AND dhc.area_id = #{areaId}
</if>
<if test="areaName != null and areaName != ''">
AND dhc.area_name LIKE CONCAT('%', #{areaName}, '%')
</if>
<if test="campusId != null">
AND dhc.campus_id = #{campusId}
</if>
<if test="campusName != null and campusName != ''">
AND dhc.campus_name LIKE CONCAT('%', #{campusName}, '%')
</if>
<if test="hygieneGrade != null and hygieneGrade != ''">
AND dhc.hygiene_grade = #{hygieneGrade}
</if>
<if test="params != null and params.beginTime != null and params.beginTime != ''">
AND dhc.check_date &gt;= #{params.beginTime}
</if>
<if test="params != null and params.endTime != null and params.endTime != ''">
AND dhc.check_date &lt;= #{params.endTime}
</if>
</where>
ORDER BY dhc.check_date DESC, dhc.id ASC, dhss.student_no ASC
</select>
</mapper>
@@ -0,0 +1,7 @@
<?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.XgDormHygieneStudentScoreMapper">
</mapper>
@@ -0,0 +1,160 @@
<?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.XgDormViolationMapper">
<!-- 学生选项查询结果映射 -->
<resultMap id="StudentOptionResult" type="org.dromara.xg.domain.vo.StudentOptionVo">
<id property="id" column="id"/>
<result property="studentNo" column="student_no"/>
<result property="name" column="name"/>
<result property="gender" column="gender"/>
<result property="collegeId" column="college_id"/>
<result property="collegeName" column="college_name"/>
<result property="majorId" column="major_id"/>
<result property="majorName" column="major_name"/>
<result property="classId" column="class_id"/>
<result property="className" column="class_name"/>
<result property="phone" column="phone"/>
<result property="createBy" column="create_by"/>
<result property="createTime" column="create_time"/>
<result property="updateBy" column="update_by"/>
<result property="updateTime" column="update_time"/>
<association property="dormInfo" javaType="org.dromara.xg.domain.vo.StudentOptionVo$DormInfo">
<result property="campusId" column="campus_id"/>
<result property="campusName" column="campus_name"/>
<result property="areaId" column="area_id"/>
<result property="areaName" column="area_name"/>
<result property="buildingId" column="building_id"/>
<result property="buildingName" column="building_name"/>
<result property="roomId" column="room_id"/>
<result property="roomName" column="room_name"/>
<result property="bedId" column="bed_id"/>
<result property="bedName" column="bed_name"/>
</association>
</resultMap>
<!-- 查询学生选择器选项列表 -->
<select id="selectStudentOptions" resultMap="StudentOptionResult">
SELECT
s.id,
s.student_no,
s.name,
s.gender,
s.college_id,
s.college_name,
s.major_id,
s.major_name,
s.class_id,
s.class_name,
s.phone,
s.create_by,
s.create_time,
s.update_by,
s.update_time,
COALESCE(dc.id, NULL) as campus_id,
COALESCE(dc.campus_name, NULL) as campus_name,
COALESCE(da.id, NULL) as area_id,
COALESCE(da.area_name, NULL) as area_name,
COALESCE(db.id, NULL) as building_id,
COALESCE(db.building_name, NULL) as building_name,
COALESCE(dr.id, NULL) as room_id,
COALESCE(dr.room_name, NULL) as room_name,
COALESCE(bed.id, NULL) as bed_id,
COALESCE(bed.bed_name, NULL) as bed_name
FROM xg_student_msg s
LEFT JOIN xg_dorm_bed_student dbs ON s.id = dbs.student_id AND dbs.deleted = 0
LEFT JOIN xg_dorm_bed bed ON dbs.bed_id = bed.id AND bed.deleted = 0
LEFT JOIN xg_dorm_room dr ON bed.room_id = dr.id AND dr.deleted = 0
LEFT JOIN xg_dorm_building db ON dr.building_id = db.id AND db.deleted = 0
LEFT JOIN xg_dorm_area da ON db.area_id = da.id AND da.deleted = 0
LEFT JOIN xg_dorm_campus dc ON da.campus_id = dc.id AND dc.deleted = 0
WHERE s.deleted = 0
AND s.student_status = '1'
<if test="bo.keyword != null and bo.keyword != ''">
AND (s.student_no LIKE CONCAT('%', #{bo.keyword}, '%')
OR s.name LIKE CONCAT('%', #{bo.keyword}, '%'))
</if>
ORDER BY s.student_no ASC
</select>
<!-- 根据学生ID获取学生详细信息 -->
<select id="selectStudentById" resultMap="StudentOptionResult">
SELECT
s.id,
s.student_no,
s.name,
s.gender,
s.college_id,
s.college_name,
s.major_id,
s.major_name,
s.class_id,
s.class_name,
s.phone,
s.create_by,
s.create_time,
s.update_by,
s.update_time,
COALESCE(dc.id, NULL) as campus_id,
COALESCE(dc.campus_name, NULL) as campus_name,
COALESCE(da.id, NULL) as area_id,
COALESCE(da.area_name, NULL) as area_name,
COALESCE(db.id, NULL) as building_id,
COALESCE(db.building_name, NULL) as building_name,
COALESCE(dr.id, NULL) as room_id,
COALESCE(dr.room_name, NULL) as room_name,
COALESCE(bed.id, NULL) as bed_id,
COALESCE(bed.bed_name, NULL) as bed_name
FROM xg_student_msg s
LEFT JOIN xg_dorm_bed_student dbs ON s.id = dbs.student_id AND dbs.deleted = 0
LEFT JOIN xg_dorm_bed bed ON dbs.bed_id = bed.id AND bed.deleted = 0
LEFT JOIN xg_dorm_room dr ON bed.room_id = dr.id AND dr.deleted = 0
LEFT JOIN xg_dorm_building db ON dr.building_id = db.id AND db.deleted = 0
LEFT JOIN xg_dorm_area da ON db.area_id = da.id AND da.deleted = 0
LEFT JOIN xg_dorm_campus dc ON da.campus_id = dc.id AND dc.deleted = 0
WHERE s.deleted = 0
AND s.id = #{studentId}
</select>
<!-- 根据学号获取学生详细信息 -->
<select id="selectStudentByStudentNo" resultMap="StudentOptionResult">
SELECT
s.id,
s.student_no,
s.name,
s.gender,
s.college_id,
s.college_name,
s.major_id,
s.major_name,
s.class_id,
s.class_name,
s.phone,
s.create_by,
s.create_time,
s.update_by,
s.update_time,
COALESCE(dc.id, NULL) as campus_id,
COALESCE(dc.campus_name, NULL) as campus_name,
COALESCE(da.id, NULL) as area_id,
COALESCE(da.area_name, NULL) as area_name,
COALESCE(db.id, NULL) as building_id,
COALESCE(db.building_name, NULL) as building_name,
COALESCE(dr.id, NULL) as room_id,
COALESCE(dr.room_name, NULL) as room_name,
COALESCE(bed.id, NULL) as bed_id,
COALESCE(bed.bed_name, NULL) as bed_name
FROM xg_student_msg s
LEFT JOIN xg_dorm_bed_student dbs ON s.id = dbs.student_id AND dbs.deleted = 0
LEFT JOIN xg_dorm_bed bed ON dbs.bed_id = bed.id AND bed.deleted = 0
LEFT JOIN xg_dorm_room dr ON bed.room_id = dr.id AND dr.deleted = 0
LEFT JOIN xg_dorm_building db ON dr.building_id = db.id AND db.deleted = 0
LEFT JOIN xg_dorm_area da ON db.area_id = da.id AND da.deleted = 0
LEFT JOIN xg_dorm_campus dc ON da.campus_id = dc.id AND dc.deleted = 0
WHERE s.deleted = 0
AND s.student_no = #{studentNo}
</select>
</mapper>
@@ -0,0 +1,82 @@
<?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.XgHolidayStayMapper">
<!-- 学生选项查询结果映射 -->
<resultMap id="StudentOptionResult" type="org.dromara.xg.domain.vo.StudentOptionVo">
<id property="id" column="id"/>
<result property="studentNo" column="student_no"/>
<result property="name" column="name"/>
<result property="gender" column="gender"/>
<result property="collegeId" column="college_id"/>
<result property="collegeName" column="college_name"/>
<result property="majorId" column="major_id"/>
<result property="majorName" column="major_name"/>
<result property="classId" column="class_id"/>
<result property="className" column="class_name"/>
<result property="phone" column="phone"/>
<result property="createBy" column="create_by"/>
<result property="createTime" column="create_time"/>
<result property="updateBy" column="update_by"/>
<result property="updateTime" column="update_time"/>
<association property="dormInfo" javaType="org.dromara.xg.domain.vo.StudentOptionVo$DormInfo">
<result property="campusId" column="campus_id"/>
<result property="campusName" column="campus_name"/>
<result property="areaId" column="area_id"/>
<result property="areaName" column="area_name"/>
<result property="buildingId" column="building_id"/>
<result property="buildingName" column="building_name"/>
<result property="roomId" column="room_id"/>
<result property="roomName" column="room_name"/>
<result property="bedId" column="bed_id"/>
<result property="bedName" column="bed_name"/>
</association>
</resultMap>
<!-- 查询学生选择器选项列表 -->
<select id="selectStudentOptions" resultMap="StudentOptionResult">
SELECT
s.id,
s.student_no,
s.name,
s.gender,
s.college_id,
s.college_name,
s.major_id,
s.major_name,
s.class_id,
s.class_name,
s.phone,
s.create_by,
s.create_time,
s.update_by,
s.update_time,
COALESCE(dc.id, NULL) as campus_id,
COALESCE(dc.campus_name, NULL) as campus_name,
COALESCE(da.id, NULL) as area_id,
COALESCE(da.area_name, NULL) as area_name,
COALESCE(db.id, NULL) as building_id,
COALESCE(db.building_name, NULL) as building_name,
COALESCE(dr.id, NULL) as room_id,
COALESCE(dr.room_name, NULL) as room_name,
COALESCE(bed.id, NULL) as bed_id,
COALESCE(bed.bed_name, NULL) as bed_name
FROM xg_student_msg s
LEFT JOIN xg_dorm_bed_student dbs ON s.id = dbs.student_id AND dbs.deleted = 0
LEFT JOIN xg_dorm_bed bed ON dbs.bed_id = bed.id AND bed.deleted = 0
LEFT JOIN xg_dorm_room dr ON bed.room_id = dr.id AND dr.deleted = 0
LEFT JOIN xg_dorm_building db ON dr.building_id = db.id AND db.deleted = 0
LEFT JOIN xg_dorm_area da ON db.area_id = da.id AND da.deleted = 0
LEFT JOIN xg_dorm_campus dc ON da.campus_id = dc.id AND dc.deleted = 0
WHERE s.deleted = 0
AND s.student_status = '1'
<if test="bo.keyword != null and bo.keyword != ''">
AND (s.student_no LIKE CONCAT('%', #{bo.keyword}, '%')
OR s.name LIKE CONCAT('%', #{bo.keyword}, '%'))
</if>
ORDER BY s.student_no ASC
</select>
</mapper>
@@ -200,4 +200,100 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
ORDER BY c.grade DESC, sm.college_name, sm.major_name, sm.class_name
</select>
<!-- 查询二级学院下的学院、专业、班级学生统计信息(按床位分配统计) -->
<select id="getCollegeStudentStatsByClass" resultType="java.util.Map">
SELECT
c.grade,
sm.college_id,
sm.college_name,
sm.major_id,
sm.major_name,
sm.class_id,
sm.class_name,
COALESCE(SUM(CASE WHEN sm.gender = '0' AND sm.is_boarder = 1 THEN 1 ELSE 0 END), 0) AS male_total,
COALESCE(SUM(CASE WHEN sm.gender = '1' AND sm.is_boarder = 1 THEN 1 ELSE 0 END), 0) AS female_total,
COALESCE((
SELECT COUNT(DISTINCT dbs.bed_id)
FROM xg_dorm_bed_student dbs
LEFT JOIN xg_dorm_bed db ON dbs.bed_id = db.id
LEFT JOIN xg_dorm_room dr ON db.room_id = dr.id
LEFT JOIN xg_dorm_building dbuild ON dr.building_id = dbuild.id
WHERE dbs.class_id = sm.class_id
AND dbs.deleted = '0'
AND dbs.status = '0'
AND db.deleted = '0'
AND dbuild.building_type = '1'
), 0) AS male_assigned,
COALESCE((
SELECT COUNT(DISTINCT dbs.bed_id)
FROM xg_dorm_bed_student dbs
LEFT JOIN xg_dorm_bed db ON dbs.bed_id = db.id
LEFT JOIN xg_dorm_room dr ON db.room_id = dr.id
LEFT JOIN xg_dorm_building dbuild ON dr.building_id = dbuild.id
WHERE dbs.class_id = sm.class_id
AND dbs.deleted = '0'
AND dbs.status = '0'
AND db.deleted = '0'
AND dbuild.building_type = '2'
), 0) AS female_assigned
FROM xg_student_msg sm
LEFT JOIN xg_class_msg c ON sm.class_id = c.id
LEFT JOIN sys_dept d ON sm.college_id = d.dept_id
WHERE sm.deleted = 0
AND sm.student_status = '1'
AND sm.is_boarder = 1
AND (d.parent_id = #{secondaryCollegeId} OR d.dept_id = #{secondaryCollegeId} OR FIND_IN_SET(#{secondaryCollegeId}, d.ancestors))
AND sm.college_id IS NOT NULL
AND sm.major_id IS NOT NULL
AND sm.class_id IS NOT NULL
GROUP BY c.grade, sm.college_id, sm.college_name, sm.major_id, sm.major_name, sm.class_id, sm.class_name
ORDER BY c.grade DESC, sm.college_name, sm.major_name, sm.class_name
</select>
<!-- 查询二级学院下的学院床位分配统计信息(基于学生表统计需求,基于床位分配表统计已分配) -->
<select id="getCollegeBedAssignmentStats" resultType="java.util.Map">
SELECT
sm.college_id,
sm.college_name,
COALESCE(SUM(CASE WHEN sm.gender = '0' AND sm.is_boarder = 1 THEN 1 ELSE 0 END), 0) AS male_total,
COALESCE(SUM(CASE WHEN sm.gender = '1' AND sm.is_boarder = 1 THEN 1 ELSE 0 END), 0) AS female_total,
COALESCE((
SELECT COUNT(*)
FROM xg_dorm_bed_student dbs
LEFT JOIN xg_dorm_bed db ON dbs.bed_id = db.id
LEFT JOIN xg_dorm_room dr ON db.room_id = dr.id
LEFT JOIN xg_dorm_building dbuild ON dr.building_id = dbuild.id
WHERE dbs.college_id = sm.college_id
AND dbs.deleted = '0'
AND dbs.status = '0'
AND db.deleted = '0'
AND dr.deleted = '0'
AND dbuild.deleted = '0'
AND dbuild.building_type = '1'
), 0) AS male_assigned,
COALESCE((
SELECT COUNT(*)
FROM xg_dorm_bed_student dbs
LEFT JOIN xg_dorm_bed db ON dbs.bed_id = db.id
LEFT JOIN xg_dorm_room dr ON db.room_id = dr.id
LEFT JOIN xg_dorm_building dbuild ON dr.building_id = dbuild.id
WHERE dbs.college_id = sm.college_id
AND dbs.deleted = '0'
AND dbs.status = '0'
AND db.deleted = '0'
AND dr.deleted = '0'
AND dbuild.deleted = '0'
AND dbuild.building_type = '2'
), 0) AS female_assigned
FROM xg_student_msg sm
LEFT JOIN sys_dept d ON sm.college_id = d.dept_id
WHERE sm.deleted = 0
AND sm.student_status = '1'
AND sm.is_boarder = 1
AND (d.parent_id = #{secondaryCollegeId} OR d.dept_id = #{secondaryCollegeId} OR FIND_IN_SET(#{secondaryCollegeId}, d.ancestors))
AND sm.college_id IS NOT NULL
GROUP BY sm.college_id, sm.college_name
ORDER BY sm.college_name
</select>
</mapper>
+6
View File
@@ -104,6 +104,12 @@
<artifactId>ruoyi-workflow</artifactId>
</dependency>
<!-- 学工管理模块 - 用于获取学生基础信息 -->
<dependency>
<groupId>org.dromara</groupId>
<artifactId>ruoyi-xg</artifactId>
</dependency>
</dependencies>
</project>
@@ -5,14 +5,20 @@ 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.common.satoken.utils.LoginHelper;
import org.dromara.zsjy.domain.vo.InternshipInfoVO;
import org.dromara.zsjy.domain.bo.InternshipInfoQueryBO;
import org.dromara.zsjy.domain.bo.InternshipInfoAddBO;
import org.dromara.zsjy.domain.bo.InternshipInfoEditBO;
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 lombok.extern.slf4j.Slf4j;
import org.dromara.common.core.validate.AddGroup;
import org.dromara.common.core.validate.EditGroup;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import jakarta.servlet.http.HttpServletResponse;
@@ -23,6 +29,7 @@ import jakarta.servlet.http.HttpServletResponse;
* @author system
* @date 2025-01-03
*/
@Slf4j
@Validated
@RequiredArgsConstructor
@RestController
@@ -39,7 +46,18 @@ public class InternshipInfoController extends BaseController {
@SaCheckPermission("zsjy:internship:list")
@GetMapping("/list")
public TableDataInfo<InternshipInfoVO> list(@Validated InternshipInfoQueryBO queryBO, PageQuery pageQuery) {
return internshipInfoService.queryPageList(queryBO, pageQuery);
log.info("=== Controller层调试 ===");
log.info("接口被调用: /zsjy/internship/list");
log.info("查询参数: {}", queryBO);
log.info("分页参数: pageNum={}, pageSize={}", pageQuery.getPageNum(), pageQuery.getPageSize());
TableDataInfo<InternshipInfoVO> result = internshipInfoService.queryPageList(queryBO, pageQuery);
log.info("Controller返回结果: total={}, rows.size={}",
result.getTotal(), result.getRows() != null ? result.getRows().size() : "null");
log.info("=== Controller层调试结束 ===");
return result;
}
/**
@@ -83,4 +101,128 @@ public class InternshipInfoController extends BaseController {
public R<?> getInternshipStatistics(@Validated InternshipInfoQueryBO queryBO) {
return R.ok(internshipInfoService.getInternshipStatistics(queryBO));
}
/**
* 学生获取自己的实习信息(移动端专用)
*/
@Operation(summary = "学生获取实习信息", description = "学生查看自己的实习信息(移动端)")
@GetMapping("/student/info")
public R<InternshipInfoVO> getStudentInfo() {
log.info("=== 学生获取实习信息 ===");
log.info("当前用户ID: {}", LoginHelper.getUserId());
try {
Long currentUserId = LoginHelper.getUserId();
if (currentUserId == null) {
log.error("用户ID为空,无法获取实习信息");
return R.fail("用户未登录");
}
InternshipInfoVO result = internshipInfoService.queryById(currentUserId);
if (result != null) {
log.info("成功获取学生实习信息,学生ID: {}", currentUserId);
return R.ok(result);
} else {
log.info("学生暂无实习信息,学生ID: {}", currentUserId);
return R.fail("暂无实习信息");
}
} catch (Exception e) {
log.error("获取学生实习信息异常,用户ID: {},错误信息: {}", LoginHelper.getUserId(), e.getMessage(), e);
return R.fail("获取实习信息失败:" + e.getMessage());
}
}
/**
* 新增实习信息
*/
@Operation(summary = "新增实习信息", description = "为学生新增实习信息")
@SaCheckPermission("zsjy:internship:add")
@PostMapping
public R<Void> add(@RequestBody @Validated(AddGroup.class) InternshipInfoAddBO addBO) {
log.info("新增实习信息请求,参数:{}", addBO);
try {
Boolean result = internshipInfoService.insertInternshipInfo(addBO);
if (result) {
log.info("新增实习信息成功,学生ID:{}", addBO.getStudentId());
return R.ok();
} else {
log.error("新增实习信息失败,学生ID:{}", addBO.getStudentId());
return R.fail("新增实习信息失败");
}
} catch (Exception e) {
log.error("新增实习信息异常,学生ID:{},错误信息:{}", addBO.getStudentId(), e.getMessage(), e);
return R.fail("新增实习信息失败:" + e.getMessage());
}
}
/**
* 33
*/
@Operation(summary = "修改实习信息", description = "修改学生实习信息")
@SaCheckPermission("zsjy:internship:edit")
@PutMapping
public R<Void> edit(@RequestBody @Validated(EditGroup.class) InternshipInfoEditBO editBO) {
log.info("修改实习信息请求,参数:{}", editBO);
try {
Boolean result = internshipInfoService.updateInternshipInfo(editBO);
if (result) {
log.info("修改实习信息成功,实习信息ID:{}", editBO.getInternshipId());
return R.ok();
} else {
log.error("修改实习信息失败,实习信息ID:{}", editBO.getInternshipId());
return R.fail("修改实习信息失败");
}
} catch (Exception e) {
log.error("修改实习信息异常,实习信息ID:{},错误信息:{}", editBO.getInternshipId(), e.getMessage(), e);
return R.fail("修改实习信息失败:" + e.getMessage());
}
}
/**
* 删除实习信息
*/
@Operation(summary = "删除实习信息", description = "删除学生实习信息")
@SaCheckPermission("zsjy:internship:remove")
@DeleteMapping("/{internshipIds}")
public R<Void> remove(@Parameter(description = "实习信息ID串")
@PathVariable Long[] internshipIds) {
log.info("删除实习信息请求,IDs:{}", (Object) internshipIds);
try {
Boolean result = internshipInfoService.deleteInternshipInfo(internshipIds);
if (result) {
log.info("删除实习信息成功,IDs:{}", (Object) internshipIds);
return R.ok();
} else {
log.error("删除实习信息失败,IDs:{}", (Object) internshipIds);
return R.fail("删除实习信息失败");
}
} catch (Exception e) {
log.error("删除实习信息异常,IDs:{},错误信息:{}", internshipIds, e.getMessage(), e);
return R.fail("删除实习信息失败:" + e.getMessage());
}
}
/**
* 获取当前学生的实习信息
*/
@Operation(summary = "获取当前学生实习信息", description = "获取当前登录学生的实习信息,用于月度总结等功能")
@SaCheckPermission("zsjy:internship:query")
@GetMapping("/current")
public R<InternshipInfoVO> getCurrentStudentInternship() {
try {
log.info("=== 获取当前学生实习信息接口被调用 ===");
InternshipInfoVO result = internshipInfoService.getCurrentStudentInternship();
if (result != null) {
log.info("成功获取当前学生实习信息,实习ID:{}", result.getInternshipId());
return R.ok(result);
} else {
log.info("当前学生没有实习信息");
return R.ok(); // 返回空数据,前端需要处理这种情况
}
} catch (Exception e) {
log.error("获取当前学生实习信息失败:{}", e.getMessage(), e);
return R.fail("获取实习信息失败:" + e.getMessage());
}
}
}
@@ -0,0 +1,120 @@
package org.dromara.zsjy.controller;
import cn.dev33.satoken.annotation.SaCheckPermission;
import org.dromara.common.core.domain.R;
import org.dromara.common.core.validate.AddGroup;
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.bo.CheckInGroup;
import org.dromara.zsjy.domain.bo.ZsjyInternshipDailyAddBo;
import org.dromara.zsjy.domain.bo.ZsjyInternshipDailyQueryBo;
import org.dromara.zsjy.domain.vo.ZsjyInternshipDailyVo;
import org.dromara.zsjy.service.IZsjyInternshipDailyService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.util.List;
import java.util.Map;
/**
* 实习日常管理Controller
*
* @author system
* @date 2025-01-03
*/
@Slf4j
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/zsjy/internship/daily")
@Tag(name = "实习日常管理", description = "学生实习日常打卡签到管理")
public class ZsjyInternshipDailyController extends BaseController {
private final IZsjyInternshipDailyService dailyService;
/**
* 查询实习日常记录列表
*/
@Operation(summary = "查询实习日常记录列表", description = "班主任查看学生实习日常记录")
@SaCheckPermission("zsjy:internshipdaily:list")
@GetMapping("/list")
public TableDataInfo<ZsjyInternshipDailyVo> list(@Validated ZsjyInternshipDailyQueryBo queryBo, PageQuery pageQuery) {
log.info("=== Controller层调试 ===");
log.info("接口被调用: /zsjy/internship/daily/list");
log.info("查询参数: {}", queryBo);
log.info("分页参数: {}", pageQuery);
return dailyService.queryPageList(queryBo, pageQuery);
}
/**
* 学生签到打卡
*/
@Operation(summary = "学生签到打卡", description = "学生进行实习日常签到打卡")
@SaCheckPermission("zsjy:internshipdaily:checkin")
@PostMapping("/checkin")
public R<Void> checkIn(@Validated(CheckInGroup.class) @RequestBody ZsjyInternshipDailyAddBo addBo) {
log.info("=== Controller层调试 ===");
log.info("接口被调用: /zsjy/internship/daily/checkin");
log.info("签到参数: {}", addBo);
return dailyService.checkIn(addBo);
}
/**
* 获取学生考勤日历
*/
@Operation(summary = "获取学生考勤日历", description = "查看指定学生的考勤日历数据")
@SaCheckPermission("zsjy:internshipdaily:calendar")
@GetMapping("/calendar")
public R<List<Map<String, Object>>> getCalendar(
@Parameter(description = "学生ID", required = true) @RequestParam Long studentId,
@Parameter(description = "年份") @RequestParam(required = false) Integer year,
@Parameter(description = "月份") @RequestParam(required = false) Integer month) {
log.info("=== Controller层调试 ===");
log.info("接口被调用: /zsjy/internship/daily/calendar");
log.info("学生ID: {}, 查询年月: {}-{}", studentId, year, month);
return dailyService.getCalendarData(studentId, year, month);
}
/**
* 获取考勤统计数据
*/
@Operation(summary = "获取考勤统计数据", description = "查看实习生考勤统计分析")
@SaCheckPermission("zsjy:internshipdaily:statistics")
@GetMapping("/statistics")
public R<Map<String, Object>> getStatistics(@Validated ZsjyInternshipDailyQueryBo queryBo) {
log.info("=== Controller层调试 ===");
log.info("接口被调用: /zsjy/internship/daily/statistics");
log.info("统计参数: {}", queryBo);
return dailyService.getStatistics(queryBo);
}
/**
* 获取学生个人月度考勤统计(移动端专用)
*/
@Operation(summary = "获取学生月度统计", description = "获取指定学生的月度考勤统计数据")
@SaCheckPermission("zsjy:internshipdaily:statistics")
@GetMapping("/monthly-statistics")
public R<Map<String, Object>> getStudentMonthlyStatistics(
@Parameter(description = "学生ID", required = true) @RequestParam Long studentId,
@Parameter(description = "年份", required = true) @RequestParam Integer year,
@Parameter(description = "月份", required = true) @RequestParam Integer month) {
log.info("=== Controller层调试 ===");
log.info("接口被调用: /zsjy/internship/daily/monthly-statistics");
log.info("学生ID: {}, 年月: {}-{}", studentId, year, month);
return dailyService.getStudentMonthlyStatistics(studentId, year, month);
}
}
@@ -0,0 +1,238 @@
package org.dromara.zsjy.controller;
import cn.dev33.satoken.annotation.SaCheckPermission;
import org.dromara.common.core.domain.R;
import org.dromara.common.core.validate.AddGroup;
import org.dromara.common.core.validate.EditGroup;
import org.dromara.common.excel.utils.ExcelUtil;
import org.dromara.common.log.annotation.Log;
import org.dromara.common.log.enums.BusinessType;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.web.core.BaseController;
import jakarta.servlet.http.HttpServletResponse;
import org.dromara.zsjy.domain.bo.ZsjyInternshipMonthlyAddBo;
import org.dromara.zsjy.domain.bo.ZsjyInternshipMonthlyQueryBo;
import org.dromara.zsjy.domain.vo.ZsjyInternshipMonthlyVo;
import org.dromara.zsjy.service.IZsjyInternshipMonthlyService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.util.List;
import java.util.Map;
/**
* 学生月度实习总结Controller
*
* @author system
* @date 2025-01-03
*/
@Slf4j
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/zsjy/internship/monthly")
@Tag(name = "学生月度实习总结", description = "学生月度实习总结填写管理")
public class ZsjyInternshipMonthlyController extends BaseController {
private final IZsjyInternshipMonthlyService monthlyService;
/**
* 查询学生月度实习总结列表
*/
@Operation(summary = "查询学生月度实习总结列表", description = "学生查看自己的月度总结列表")
@SaCheckPermission("zsjy:internshipmonthly:list")
@GetMapping("/list")
public TableDataInfo<ZsjyInternshipMonthlyVo> list(@Validated ZsjyInternshipMonthlyQueryBo queryBo, PageQuery pageQuery) {
log.info("=== Controller层调试 ===");
log.info("接口被调用: /zsjy/internship/monthly/list");
log.info("查询参数: {}", queryBo);
log.info("分页参数: {}", pageQuery);
return monthlyService.queryPageList(queryBo, pageQuery);
}
/**
* 查询学生月度实习总结详细信息
*/
@Operation(summary = "查询学生月度实习总结详细信息", description = "根据ID查询月度总结详情")
@SaCheckPermission("zsjy:internshipmonthly:query")
@GetMapping("/{monthlyId}")
public R<ZsjyInternshipMonthlyVo> getInfo(@Parameter(description = "月度总结ID")
@PathVariable Long monthlyId) {
log.info("查询月度总结详情, ID: {}", monthlyId);
return R.ok(monthlyService.queryById(monthlyId));
}
/**
* 新增学生月度实习总结
*/
@Operation(summary = "新增学生月度实习总结", description = "学生创建新的月度总结")
@SaCheckPermission("zsjy:internshipmonthly:add")
@PostMapping
public R<Void> add(@Validated(AddGroup.class) @RequestBody ZsjyInternshipMonthlyAddBo addBo) {
log.info("新增月度总结: {}", addBo);
if (!monthlyService.insertByBo(addBo)) {
return R.fail("新增月度总结失败");
}
return R.ok();
}
/**
* 修改学生月度实习总结
*/
@Operation(summary = "修改学生月度实习总结", description = "学生编辑自己的月度总结")
@SaCheckPermission("zsjy:internshipmonthly:edit")
@PutMapping
public R<Void> edit(@Validated(EditGroup.class) @RequestBody ZsjyInternshipMonthlyAddBo addBo) {
log.info("修改月度总结: {}", addBo);
if (!monthlyService.updateByBo(addBo)) {
return R.fail("修改月度总结失败");
}
return R.ok();
}
/**
* 删除学生月度实习总结
*/
@Operation(summary = "删除学生月度实习总结", description = "学生删除自己的草稿状态月度总结")
@SaCheckPermission("zsjy:internshipmonthly:remove")
@DeleteMapping("/{monthlyIds}")
public R<Void> remove(@Parameter(description = "月度总结ID串")
@PathVariable Long[] monthlyIds) {
log.info("删除月度总结, IDs: {}", (Object) monthlyIds);
if (!monthlyService.deleteByIds(List.of(monthlyIds))) {
return R.fail("删除月度总结失败");
}
return R.ok();
}
/**
* 提交月度总结审批
*/
@Operation(summary = "提交月度总结审批", description = "学生提交月度总结给班主任审批")
@SaCheckPermission("zsjy:internshipmonthly:submit")
@PutMapping("/submit/{monthlyId}")
public R<Void> submit(@Parameter(description = "月度总结ID")
@PathVariable Long monthlyId) {
log.info("提交月度总结审批, ID: {}", monthlyId);
if (!monthlyService.submitForApproval(monthlyId)) {
return R.fail("提交月度总结失败");
}
return R.ok();
}
/**
* 自动保存草稿
*/
@Operation(summary = "自动保存草稿", description = "学生编辑时自动保存草稿")
@SaCheckPermission("zsjy:internshipmonthly:autosave")
@PostMapping("/autosave")
public R<Void> autoSave(@RequestBody ZsjyInternshipMonthlyAddBo addBo) {
log.info("自动保存草稿: {}", addBo);
if (!monthlyService.autoSaveDraft(addBo)) {
return R.fail("自动保存失败");
}
return R.ok();
}
/**
* 检查月份是否存在总结
*/
@Operation(summary = "检查月份是否存在总结", description = "检查学生某月是否已有总结记录")
@SaCheckPermission("zsjy:internshipmonthly:check")
@GetMapping("/check/{summaryMonth}")
public R<Boolean> checkMonth(@Parameter(description = "总结月份")
@PathVariable String summaryMonth,
@Parameter(description = "排除的总结ID")
@RequestParam(required = false) Long monthlyId) {
log.info("检查月份总结, 月份: {}, 排除ID: {}", summaryMonth, monthlyId);
Boolean exists = monthlyService.checkMonthExists(null, summaryMonth, monthlyId);
return R.ok(exists);
}
/**
* 获取月度总结模板
*/
@Operation(summary = "获取月度总结模板", description = "获取指定月份的总结模板信息")
@SaCheckPermission("zsjy:internshipmonthly:template")
@GetMapping("/template/{summaryMonth}")
public R<ZsjyInternshipMonthlyVo> getTemplate(@Parameter(description = "总结月份")
@PathVariable String summaryMonth) {
log.info("获取月度总结模板, 月份: {}", summaryMonth);
ZsjyInternshipMonthlyVo template = monthlyService.getMonthlyTemplate(summaryMonth);
return R.ok(template);
}
/**
* 查询学生指定实习的月度总结列表
*/
@Operation(summary = "查询学生指定实习的月度总结列表", description = "查询学生某个实习的所有月度总结")
@SaCheckPermission("zsjy:internshipmonthly:list")
@GetMapping("/internship/{internshipId}")
public R<List<ZsjyInternshipMonthlyVo>> listByInternship(@Parameter(description = "实习ID")
@PathVariable Long internshipId) {
log.info("查询实习月度总结列表, 实习ID: {}", internshipId);
List<ZsjyInternshipMonthlyVo> list = monthlyService.queryByStudentAndInternship(null, internshipId);
return R.ok(list);
}
/**
* 统计学生各状态的总结数量
*/
@Operation(summary = "统计学生各状态的总结数量", description = "统计学生草稿、待审核、已审核等状态的总结数量")
@SaCheckPermission("zsjy:internshipmonthly:statistics")
@GetMapping("/statistics")
public R<List<Object>> statistics() {
log.info("统计学生月度总结状态");
List<Object> statistics = monthlyService.countByStatus(null);
return R.ok(statistics);
}
/**
* 获取学生当前实习信息
*/
@Operation(summary = "获取学生当前实习信息", description = "获取当前登录学生的进行中实习信息")
@SaCheckPermission("zsjy:internshipmonthly:add")
@GetMapping("/current-internship")
public R<Map<String, Object>> getCurrentInternship() {
log.info("获取学生当前实习信息");
Map<String, Object> internshipInfo = monthlyService.getCurrentInternshipInfo();
if (internshipInfo == null || internshipInfo.isEmpty()) {
return R.fail("您当前没有进行中的实习记录");
}
return R.ok(internshipInfo);
}
/**
* 导出学生月度实习总结
*/
@Operation(summary = "导出学生月度实习总结", description = "导出学生的月度总结数据")
@SaCheckPermission("zsjy:internshipmonthly:export")
@Log(title = "学生月度实习总结", businessType = BusinessType.EXPORT)
@PostMapping("/export")
public void export(@RequestBody ZsjyInternshipMonthlyQueryBo queryBo, HttpServletResponse response) {
log.info("导出月度总结: {}", queryBo);
List<ZsjyInternshipMonthlyVo> list = monthlyService.queryList(queryBo);
ExcelUtil.exportExcel(list, "学生月度实习总结", ZsjyInternshipMonthlyVo.class, response);
}
}
@@ -0,0 +1,131 @@
package org.dromara.zsjy.controller;
import cn.dev33.satoken.annotation.SaCheckPermission;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.Parameters;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import lombok.RequiredArgsConstructor;
import org.dromara.common.core.domain.R;
import org.dromara.common.core.validate.AddGroup;
import org.dromara.common.core.validate.EditGroup;
import org.dromara.common.excel.utils.ExcelUtil;
import org.dromara.common.idempotent.annotation.RepeatSubmit;
import org.dromara.common.log.annotation.Log;
import org.dromara.common.log.enums.BusinessType;
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.bo.ZsjyInternshipVisitBo;
import org.dromara.zsjy.domain.bo.ZsjyInternshipVisitQueryBo;
import org.dromara.zsjy.domain.vo.ZsjyInternshipVisitVo;
import org.dromara.zsjy.service.IZsjyInternshipVisitService;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/**
* 班主任走访Controller
*
* @author system
* @date 2025-01-03
*/
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/zsjy/internshipVisit")
@Tag(name = "班主任走访管理", description = "班主任走访管理")
public class ZsjyInternshipVisitController extends BaseController {
private final IZsjyInternshipVisitService zsjyInternshipVisitService;
/**
* 查询班主任走访列表
*/
@Operation(summary = "查询班主任走访列表")
@SaCheckPermission("zsjy:internshipVisit:list")
@GetMapping("/list")
public TableDataInfo<ZsjyInternshipVisitVo> list(ZsjyInternshipVisitQueryBo bo, PageQuery pageQuery) {
return zsjyInternshipVisitService.queryPageList(bo, pageQuery);
}
/**
* 导出班主任走访列表
*/
@Operation(summary = "导出班主任走访列表")
@SaCheckPermission("zsjy:internshipVisit:export")
@Log(title = "班主任走访", businessType = BusinessType.EXPORT)
@PostMapping("/export")
public void export(ZsjyInternshipVisitQueryBo bo, HttpServletResponse response) {
List<ZsjyInternshipVisitVo> list = zsjyInternshipVisitService.queryList(bo);
ExcelUtil.exportExcel(list, "班主任走访", ZsjyInternshipVisitVo.class, response);
}
/**
* 获取班主任走访详细信息
*/
@Operation(summary = "获取班主任走访详细信息")
@SaCheckPermission("zsjy:internshipVisit:query")
@GetMapping("/{visitId}")
@Parameters({
@Parameter(name = "visitId", description = "走访记录ID", required = true)
})
public R<ZsjyInternshipVisitVo> getInfo(@NotNull(message = "走访记录ID不能为空")
@PathVariable Long visitId) {
return R.ok(zsjyInternshipVisitService.queryById(visitId));
}
/**
* 新增班主任走访
*/
@Operation(summary = "新增班主任走访")
@SaCheckPermission("zsjy:internshipVisit:add")
@Log(title = "班主任走访", businessType = BusinessType.INSERT)
@RepeatSubmit()
@PostMapping()
public R<Void> add(@Validated(AddGroup.class) @RequestBody ZsjyInternshipVisitBo bo) {
return toAjax(zsjyInternshipVisitService.insertByBo(bo));
}
/**
* 修改班主任走访
*/
@Operation(summary = "修改班主任走访")
@SaCheckPermission("zsjy:internshipVisit:edit")
@Log(title = "班主任走访", businessType = BusinessType.UPDATE)
@RepeatSubmit()
@PutMapping()
public R<Void> edit(@Validated(EditGroup.class) @RequestBody ZsjyInternshipVisitBo bo) {
return toAjax(zsjyInternshipVisitService.updateByBo(bo));
}
/**
* 删除班主任走访
*/
@Operation(summary = "删除班主任走访")
@SaCheckPermission("zsjy:internshipVisit:remove")
@Log(title = "班主任走访", businessType = BusinessType.DELETE)
@DeleteMapping("/{visitIds}")
@Parameters({
@Parameter(name = "visitIds", description = "走访记录ID串", required = true)
})
public R<Void> remove(@NotEmpty(message = "走访记录ID不能为空")
@PathVariable Long[] visitIds) {
return toAjax(zsjyInternshipVisitService.deleteWithValidByIds(List.of(visitIds), true));
}
/**
* 获取可选项列表(学生选择)
*/
@Operation(summary = "获取可选项列表")
@SaCheckPermission("zsjy:internshipVisit:list")
@GetMapping("/options")
public R<List<ZsjyInternshipVisitVo>> getOptions() {
List<ZsjyInternshipVisitVo> list = zsjyInternshipVisitService.getStudentOptions();
return R.ok(list);
}
}
@@ -0,0 +1,186 @@
package org.dromara.zsjy.domain;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.dromara.common.mybatis.core.domain.BaseEntity;
import java.io.Serial;
import java.math.BigDecimal;
import java.sql.Time;
import java.time.LocalDate;
import java.time.LocalTime;
import java.util.Date;
/**
* 实习日常管理实体对象 zsjy_internship_daily
*
* @author system
* @date 2025-01-03
*/
@Data
@EqualsAndHashCode(callSuper = true)
@TableName("zsjy_internship_daily")
public class ZsjyInternshipDaily extends BaseEntity {
@Serial
private static final long serialVersionUID = 1L;
/**
* 日常记录ID (对应数据库daily_id字段)
*/
@TableId(value = "daily_id", type = IdType.ASSIGN_ID)
private Long id;
/**
* 租户ID
*/
@TableField("tenant_id")
private String tenantId;
/**
* 实习ID
*/
@TableField("internship_id")
private Long internshipId;
/**
* 学生ID
*/
@TableField("student_id")
private Long studentId;
/**
* 签到日期
*/
@TableField("check_date")
private LocalDate checkDate;
/**
* 签到时间
*/
@TableField("check_in_time")
private LocalTime checkInTime;
/**
* 签到地点 (对应数据库check_in_location字段)
*/
@TableField("check_in_location")
private String checkInLocation;
/**
* 签到经度 (对应数据库longitude字段)
*/
@TableField("longitude")
private BigDecimal longitude;
/**
* 签到纬度 (对应数据库latitude字段)
*/
@TableField("latitude")
private BigDecimal latitude;
/**
* 工作内容/日总结
*/
@TableField("daily_summary")
private String dailySummary;
/**
* 图片附件(JSON格式)
*/
@TableField("images")
private String images;
/**
* 是否异常(0正常 1异常)
*/
@TableField("is_exception")
private String isException;
/**
* 异常原因
*/
@TableField("exception_reason")
private String exceptionReason;
/**
* 异常处理状态(0待处理 1已处理)
*/
@TableField("exception_status")
private String exceptionStatus;
/**
* 考勤状态(0=未签到 1=正常 2=迟到 3=早退 4=旷工)
*/
@TableField("status")
private String status;
/**
* 备注
*/
@TableField("remark")
private String remark;
// ==================== 扩展字段(数据库中不存在,通过关联查询获取) ====================
/**
* 学生姓名 (通过student_id关联查询获取)
*/
@TableField(exist = false)
private String studentName;
/**
* 学号 (通过student_id关联查询获取)
*/
@TableField(exist = false)
private String studentNumber;
/**
* 班级名称 (通过student_id关联查询获取)
*/
@TableField(exist = false)
private String className;
/**
* 实习单位名称 (通过internship_id关联查询获取)
*/
@TableField(exist = false)
private String companyName;
/**
* 实习岗位 (通过internship_id关联查询获取)
*/
@TableField(exist = false)
private String position;
/**
* 签到经度 (业务扩展字段,当前只有签退经度)
*/
@TableField(exist = false)
private BigDecimal checkInLongitude;
/**
* 签到纬度 (业务扩展字段,当前只有签退纬度)
*/
@TableField(exist = false)
private BigDecimal checkInLatitude;
/**
* 签退时间 (业务扩展字段,当前只有签到时间)
*/
@TableField(exist = false)
private LocalTime checkOutTime;
/**
* 工作时长(小时) (业务计算字段)
*/
@TableField(exist = false)
private BigDecimal workDuration;
}
@@ -0,0 +1,170 @@
package org.dromara.zsjy.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.mybatis.core.domain.BaseEntity;
import java.io.Serial;
import java.math.BigDecimal;
import java.util.Date;
/**
* 实习信息实体对象 zsjy_internship_info
*
* @author system
* @date 2025-01-03
*/
@Data
@EqualsAndHashCode(callSuper = true)
@TableName("zsjy_internship_info")
public class ZsjyInternshipInfo extends BaseEntity {
@Serial
private static final long serialVersionUID = 1L;
/**
* 实习信息ID
*/
@TableId(value = "internship_id")
private Long internshipId;
/**
* 学生ID
*/
private Long studentId;
/**
* 学号
*/
private String studentNo;
/**
* 学生姓名
*/
private String studentName;
/**
* 性别
*/
private String gender;
/**
* 学院ID
*/
private Long collegeId;
/**
* 专业ID
*/
private Long majorId;
/**
* 班级ID
*/
private Long classId;
/**
* 联系电话
*/
private String phone;
/**
* 实习单位名称
*/
private String companyName;
/**
* 实习单位地址
*/
private String companyAddress;
/**
* 行业类型
*/
private String companyIndustry;
/**
* 单位规模
*/
private String companyScale;
/**
* 单位联系人
*/
private String companyContact;
/**
* 联系人电话
*/
private String companyPhone;
/**
* 岗位名称
*/
private String positionName;
/**
* 岗位职责
*/
private String positionDuties;
/**
* 实习津贴
*/
private BigDecimal internshipAllowance;
/**
* 工作时长
*/
private String workHours;
/**
* 住宿地址
*/
private String accommodationAddress;
/**
* 住宿类型
*/
private String accommodationType;
/**
* 住宿费用
*/
private BigDecimal accommodationCost;
/**
* 实习开始日期
*/
private Date startDate;
/**
* 实习结束日期
*/
private Date endDate;
/**
* 实际结束日期
*/
private Date actualEndDate;
/**
* 状态(0正常 1停用)
*/
private String status;
/**
* 实习状态(1进行中 2已完成 3中断)
*/
private String internshipStatus;
/**
* 删除标志(0代表存在 1代表删除)
*/
@TableLogic(value = "0", delval = "1")
private Long deleted;
}
@@ -0,0 +1,191 @@
package org.dromara.zsjy.domain;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.dromara.common.mybatis.core.domain.BaseEntity;
import java.io.Serial;
import java.math.BigDecimal;
import java.util.Date;
/**
* 学生月度实习总结实体对象 zsjy_internship_monthly
*
* @author system
* @date 2025-01-03
*/
@Data
@EqualsAndHashCode(callSuper = true)
@TableName("zsjy_internship_monthly")
public class ZsjyInternshipMonthly extends BaseEntity {
@Serial
private static final long serialVersionUID = 1L;
/**
* 月度总结ID (对应数据库monthly_id字段)
*/
@TableId(value = "monthly_id", type = IdType.ASSIGN_ID)
private Long id;
/**
* 租户ID
*/
@TableField("tenant_id")
private String tenantId;
/**
* 实习ID
*/
@TableField("internship_id")
private Long internshipId;
/**
* 学生ID
*/
@TableField("student_id")
private Long studentId;
/**
* 总结月份 (格式: 2025-01)
*/
@TableField("summary_month")
private String summaryMonth;
/**
* 月份序号 (1-12)
*/
@TableField("month_number")
private Integer monthNumber;
/**
* 工作内容 (必填,500字以内)
*/
@TableField("work_content")
private String workContent;
/**
* 主要成果
*/
@TableField("achievements")
private String achievements;
/**
* 学习收获
*/
@TableField("learning_gains")
private String learningGains;
/**
* 遇到的问题
*/
@TableField("problems_encountered")
private String problemsEncountered;
/**
* 自我评价
*/
@TableField("self_evaluation")
private String selfEvaluation;
/**
* 下月工作计划
*/
@TableField("next_month_plan")
private String nextMonthPlan;
/**
* 专业技能自评 (1-10分)
*/
@TableField("professional_skills")
private Integer professionalSkills;
/**
* 沟通技能自评 (1-10分)
*/
@TableField("communication_skills")
private Integer communicationSkills;
/**
* 团队协作自评 (1-10分) - 修正字段映射
*/
@TableField("teamwork_ability")
private Integer teamworkAbility;
/**
* 学习能力自评 (1-10分)
*/
@TableField("learning_ability")
private Integer learningAbility;
/**
* 工作态度自评 (1-10分)
*/
@TableField("work_attitude")
private Integer workAttitude;
/**
* 审核状态 (0:待审核 1:已审核 2:审核拒绝 3:草稿) - 修正字段映射
*/
@TableField("review_status")
private Integer reviewStatus;
/**
* 审核人ID - 修正字段映射
*/
@TableField("review_by")
private Long reviewBy;
/**
* 审核时间
*/
@TableField("review_time")
private Date reviewTime;
/**
* 审核评分 (百分制)
*/
@TableField("review_score")
private BigDecimal reviewScore;
/**
* 审核意见 - 修正字段映射
*/
@TableField("review_comment")
private String reviewComment;
/**
* 提交时间
*/
@TableField("submit_time")
private Date submitTime;
/**
* 字数统计
*/
@TableField("word_count")
private Integer wordCount;
/**
* 是否逾期 (0:未逾期 1:已逾期)
*/
@TableField("is_overdue")
private Integer isOverdue;
/**
* 提交截止日期 - 修正字段映射
*/
@TableField("submit_deadline")
private Date submitDeadline;
/**
* 附件信息 (JSON格式存储)
*/
@TableField("attachments")
private String attachments;
}
@@ -0,0 +1,173 @@
package org.dromara.zsjy.domain;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.dromara.common.mybatis.core.domain.BaseEntity;
import java.io.Serial;
import java.util.Date;
/**
* 班主任走访实体对象 zsjy_internship_visit
*
* @author system
* @date 2025-01-03
*/
@Data
@EqualsAndHashCode(callSuper = true)
@TableName("zsjy_internship_visit")
public class ZsjyInternshipVisit extends BaseEntity {
@Serial
private static final long serialVersionUID = 1L;
/**
* 走访记录ID
*/
@TableId(value = "visit_id", type = IdType.ASSIGN_ID)
private Long visitId;
/**
* 租户ID
*/
@TableField("tenant_id")
private String tenantId;
/**
* 实习ID
*/
@TableField("internship_id")
private Long internshipId;
/**
* 学生ID
*/
@TableField("student_id")
private Long studentId;
/**
* 企业名称
*/
@TableField("company_name")
private String companyName;
/**
* 企业地址
*/
@TableField("company_address")
private String companyAddress;
/**
* 走访时间
*/
@TableField("visit_date")
private Date visitDate;
/**
* 走访人员
*/
@TableField("visitor_name")
private String visitorName;
/**
* 走访人员职务
*/
@TableField("visitor_position")
private String visitorPosition;
/**
* 走访目的
*/
@TableField("visit_purpose")
private String visitPurpose;
/**
* 企业情况
*/
@TableField("company_situation")
private String companySituation;
/**
* 学生表现
*/
@TableField("student_performance")
private String studentPerformance;
/**
* 发现问题
*/
@TableField("problems_found")
private String problemsFound;
/**
* 改进建议
*/
@TableField("suggestions")
private String suggestions;
/**
* 走访总结
*/
@TableField("visit_summary")
private String visitSummary;
/**
* 现场照片(JSON格式)
*/
@TableField("visit_images")
private String visitImages;
/**
* 走访文件附件(JSON格式)
*/
@TableField("visit_files")
private String visitFiles;
/**
* 走访状态:数据库存储数字编码(0-草稿 1-已提交 2-已审核)
*/
@TableField("status")
private String status;
/**
* 备注
*/
@TableField("remark")
private String remark;
// ==================== 扩展字段(数据库中不存在,通过关联查询获取) ====================
/**
* 学生姓名 (通过student_id关联查询获取)
*/
@TableField(exist = false)
private String studentName;
/**
* 学号 (通过student_id关联查询获取)
*/
@TableField(exist = false)
private String studentNumber;
/**
* 班级名称 (通过student_id关联查询获取)
*/
@TableField(exist = false)
private String className;
/**
* 专业名称 (通过student_id关联查询获取)
*/
@TableField(exist = false)
private String majorName;
/**
* 学院名称 (通过student_id关联查询获取)
*/
@TableField(exist = false)
private String collegeName;
}
@@ -0,0 +1,11 @@
package org.dromara.zsjy.domain.bo;
/**
* 签到验证组
* 用于签到时的数据验证,不包含签退相关字段的验证
*
* @author system
* @date 2025-01-03
*/
public interface CheckInGroup {
}
@@ -0,0 +1,167 @@
package org.dromara.zsjy.domain.bo;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import org.dromara.common.core.validate.AddGroup;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Pattern;
import jakarta.validation.constraints.Positive;
import java.io.Serial;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.Date;
/**
* 实习信息新增业务对象 InternshipInfoAddBO
*
* @author system
* @date 2025-01-03
*/
@Data
@Schema(description = "实习信息新增业务对象")
public class InternshipInfoAddBO implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* 学生ID
*/
@Schema(description = "学生ID")
@NotNull(message = "学生ID不能为空", groups = {AddGroup.class})
private Long studentId;
/**
* 实习状态:1-进行中,2-已完成,3-已暂停,4-已终止
*/
@Schema(description = "实习状态:1-进行中,2-已完成,3-已暂停,4-已终止")
@NotBlank(message = "实习状态不能为空", groups = {AddGroup.class})
@Pattern(regexp = "^[1-4]$", message = "实习状态只能是1-进行中,2-已完成,3-已暂停,4-已终止", groups = {AddGroup.class})
private String internshipStatus;
/**
* 实习单位名称
*/
@Schema(description = "实习单位名称")
@NotBlank(message = "实习单位名称不能为空", groups = {AddGroup.class})
private String companyName;
/**
* 实习单位地址
*/
@Schema(description = "实习单位地址")
private String companyAddress;
/**
* 单位联系人
*/
@Schema(description = "单位联系人")
private String companyContact;
/**
* 联系人电话
*/
@Schema(description = "联系人电话")
@Pattern(regexp = "^1[3-9]\\d{9}$", message = "联系人电话格式不正确", groups = {AddGroup.class})
private String companyPhone;
/**
* 行业类型
*/
@Schema(description = "行业类型")
private String companyIndustry;
/**
* 单位规模
*/
@Schema(description = "单位规模")
private String companyScale;
/**
* 实习岗位
*/
@Schema(description = "实习岗位")
@NotBlank(message = "实习岗位不能为空", groups = {AddGroup.class})
private String internshipPosition;
/**
* 实习薪资
*/
@Schema(description = "实习薪资")
@Positive(message = "实习薪资必须大于0", groups = {AddGroup.class})
private BigDecimal internshipAllowance;
/**
* 实习开始时间
*/
@Schema(description = "实习开始时间")
@JsonFormat(pattern = "yyyy-MM-dd")
@NotNull(message = "实习开始时间不能为空", groups = {AddGroup.class})
private Date internshipStartDate;
/**
* 实习结束时间
*/
@Schema(description = "实习结束时间")
@JsonFormat(pattern = "yyyy-MM-dd")
private Date internshipEndDate;
/**
* 联系人姓名
*/
@Schema(description = "联系人姓名")
private String contactPersonName;
/**
* 联系人电话
*/
@Schema(description = "联系人电话")
@Pattern(regexp = "^1[3-9]\\d{9}$", message = "联系人电话格式不正确", groups = {AddGroup.class})
private String contactPersonPhone;
/**
* 岗位职责
*/
@Schema(description = "岗位职责")
private String positionDuties;
/**
* 工作时长
*/
@Schema(description = "工作时长")
private String workHours;
/**
* 住宿地址
*/
@Schema(description = "住宿地址")
private String accommodationAddress;
/**
* 住宿类型
*/
@Schema(description = "住宿类型")
private String accommodationType;
/**
* 住宿费用
*/
@Schema(description = "住宿费用")
private BigDecimal accommodationCost;
/**
* 实习协议状态:1-已签署,2-未签署
*/
@Schema(description = "实习协议状态:1-已签署,2-未签署")
@Pattern(regexp = "^[1-2]$", message = "实习协议状态只能是1-已签署,2-未签署", groups = {AddGroup.class})
private String agreementStatus;
/**
* 备注信息
*/
@Schema(description = "备注信息")
private String remark;
}
@@ -0,0 +1,174 @@
package org.dromara.zsjy.domain.bo;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import org.dromara.common.core.validate.EditGroup;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Pattern;
import jakarta.validation.constraints.Positive;
import java.io.Serial;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.Date;
/**
* 实习信息修改业务对象 InternshipInfoEditBO
*
* @author system
* @date 2025-01-03
*/
@Data
@Schema(description = "实习信息修改业务对象")
public class InternshipInfoEditBO implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* 实习信息ID
*/
@Schema(description = "实习信息ID")
@NotNull(message = "实习信息ID不能为空", groups = {EditGroup.class})
private Long internshipId;
/**
* 学生ID
*/
@Schema(description = "学生ID")
@NotNull(message = "学生ID不能为空", groups = {EditGroup.class})
private Long studentId;
/**
* 实习状态:1-进行中,2-已完成,3-已暂停,4-已终止
*/
@Schema(description = "实习状态:1-进行中,2-已完成,3-已暂停,4-已终止")
@NotBlank(message = "实习状态不能为空", groups = {EditGroup.class})
@Pattern(regexp = "^[1-4]$", message = "实习状态只能是1-进行中,2-已完成,3-已暂停,4-已终止", groups = {EditGroup.class})
private String internshipStatus;
/**
* 实习单位名称
*/
@Schema(description = "实习单位名称")
@NotBlank(message = "实习单位名称不能为空", groups = {EditGroup.class})
private String companyName;
/**
* 实习单位地址
*/
@Schema(description = "实习单位地址")
private String companyAddress;
/**
* 单位联系人
*/
@Schema(description = "单位联系人")
private String companyContact;
/**
* 联系人电话
*/
@Schema(description = "联系人电话")
@Pattern(regexp = "^1[3-9]\\d{9}$", message = "联系人电话格式不正确", groups = {EditGroup.class})
private String companyPhone;
/**
* 行业类型
*/
@Schema(description = "行业类型")
private String companyIndustry;
/**
* 单位规模
*/
@Schema(description = "单位规模")
private String companyScale;
/**
* 实习岗位
*/
@Schema(description = "实习岗位")
@NotBlank(message = "实习岗位不能为空", groups = {EditGroup.class})
private String internshipPosition;
/**
* 实习薪资
*/
@Schema(description = "实习薪资")
@Positive(message = "实习薪资必须大于0", groups = {EditGroup.class})
private BigDecimal internshipAllowance;
/**
* 实习开始时间
*/
@Schema(description = "实习开始时间")
@JsonFormat(pattern = "yyyy-MM-dd")
@NotNull(message = "实习开始时间不能为空", groups = {EditGroup.class})
private Date internshipStartDate;
/**
* 实习结束时间
*/
@Schema(description = "实习结束时间")
@JsonFormat(pattern = "yyyy-MM-dd")
private Date internshipEndDate;
/**
* 联系人姓名
*/
@Schema(description = "联系人姓名")
private String contactPersonName;
/**
* 联系人电话
*/
@Schema(description = "联系人电话")
@Pattern(regexp = "^1[3-9]\\d{9}$", message = "联系人电话格式不正确", groups = {EditGroup.class})
private String contactPersonPhone;
/**
* 岗位职责
*/
@Schema(description = "岗位职责")
private String positionDuties;
/**
* 工作时长
*/
@Schema(description = "工作时长")
private String workHours;
/**
* 住宿地址
*/
@Schema(description = "住宿地址")
private String accommodationAddress;
/**
* 住宿类型
*/
@Schema(description = "住宿类型")
private String accommodationType;
/**
* 住宿费用
*/
@Schema(description = "住宿费用")
private BigDecimal accommodationCost;
/**
* 实习协议状态:1-已签署,2-未签署
*/
@Schema(description = "实习协议状态:1-已签署,2-未签署")
@Pattern(regexp = "^[1-2]$", message = "实习协议状态只能是1-已签署,2-未签署", groups = {EditGroup.class})
private String agreementStatus;
/**
* 备注信息
*/
@Schema(description = "备注信息")
private String remark;
}
@@ -0,0 +1,241 @@
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.AddGroup;
import org.dromara.common.mybatis.core.domain.BaseEntity;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size;
import java.io.Serial;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalTime;
import java.util.Date;
/**
* 实习日常管理新增业务对象 ZsjyInternshipDailyAddBo
*
* @author system
* @date 2025-01-03
*/
@Data
@EqualsAndHashCode(callSuper = true)
@Schema(description = "实习日常管理新增业务对象")
public class ZsjyInternshipDailyAddBo extends BaseEntity {
@Serial
private static final long serialVersionUID = 1L;
/**
* 实习ID
*/
@Schema(description = "实习ID", requiredMode = Schema.RequiredMode.REQUIRED)
@NotNull(message = "实习ID不能为空", groups = {AddGroup.class, CheckInGroup.class})
private Long internshipId;
/**
* 学生ID
*/
@Schema(description = "学生ID", requiredMode = Schema.RequiredMode.REQUIRED)
@NotNull(message = "学生ID不能为空", groups = {AddGroup.class, CheckInGroup.class})
private Long studentId;
/**
* 签到日期
*/
@Schema(description = "签到日期", requiredMode = Schema.RequiredMode.REQUIRED)
@NotNull(message = "签到日期不能为空", groups = {AddGroup.class, CheckInGroup.class})
private LocalDate checkDate;
/**
* 签到时间
*/
@Schema(description = "签到时间", requiredMode = Schema.RequiredMode.REQUIRED)
@NotNull(message = "签到时间不能为空", groups = {AddGroup.class, CheckInGroup.class})
private LocalTime checkInTime;
/**
* 签退时间
*/
@Schema(description = "签退时间")
private LocalTime checkOutTime;
/**
* 签到地点 (前端传递字段,映射到数据库check_in_location字段)
*/
@Schema(description = "签到地点", requiredMode = Schema.RequiredMode.REQUIRED)
@NotNull(message = "签到地点不能为空", groups = {CheckInGroup.class})
@Size(max = 500, message = "签到地点长度不能超过500个字符")
private String checkInLocation;
/**
* 签到纬度 (前端传递字段,映射到数据库latitude字段)
*/
@Schema(description = "签到纬度", requiredMode = Schema.RequiredMode.REQUIRED)
@NotNull(message = "签到纬度不能为空", groups = {CheckInGroup.class})
private BigDecimal latitude;
/**
* 签到经度 (前端传递字段,映射到数据库longitude字段)
*/
@Schema(description = "签到经度", requiredMode = Schema.RequiredMode.REQUIRED)
@NotNull(message = "签到经度不能为空", groups = {CheckInGroup.class})
private BigDecimal longitude;
/**
* 签退地点 (对应数据库check_in_location字段,实际存储签退地点)
*/
@Schema(description = "签退地点", requiredMode = Schema.RequiredMode.REQUIRED)
@NotNull(message = "签退地点不能为空", groups = {AddGroup.class})
@Size(max = 500, message = "签退地点长度不能超过500个字符")
private String checkOutLocation;
/**
* 签退纬度 (对应数据库latitude字段)
*/
@Schema(description = "签退纬度", requiredMode = Schema.RequiredMode.REQUIRED)
@NotNull(message = "签退纬度不能为空", groups = {AddGroup.class})
private BigDecimal checkOutLatitude;
/**
* 签退经度 (对应数据库longitude字段)
*/
@Schema(description = "签退经度", requiredMode = Schema.RequiredMode.REQUIRED)
@NotNull(message = "签退经度不能为空", groups = {AddGroup.class})
private BigDecimal checkOutLongitude;
/**
* 工作内容 (对应数据库daily_summary字段)
*/
@Schema(description = "工作内容", requiredMode = Schema.RequiredMode.REQUIRED)
@NotNull(message = "工作内容不能为空", groups = {AddGroup.class})
@Size(max = 1000, message = "工作内容长度不能超过1000个字符")
private String workContent;
/**
* 图片附件(JSON格式)
*/
@Schema(description = "图片附件")
private String images;
/**
* 是否异常(0正常 1异常)
*/
@Schema(description = "是否异常")
private String isException;
/**
* 异常原因
*/
@Schema(description = "异常原因")
private String exceptionReason;
/**
* 考勤状态(0=未签到 1=正常 2=迟到 3=早退 4=旷工)
*/
@Schema(description = "考勤状态")
private String status;
/**
* 备注
*/
@Schema(description = "备注")
@Size(max = 500, message = "备注长度不能超过500个字符")
private String remark;
// ==================== 扩展字段(用于显示,不存储到数据库) ====================
/**
* 学生姓名(扩展字段,用于显示)
*/
@Schema(description = "学生姓名", hidden = true)
private String studentName;
/**
* 学生学号(扩展字段,用于显示)
*/
@Schema(description = "学生学号", hidden = true)
private String studentNumber;
/**
* 班级名称(扩展字段,用于显示)
*/
@Schema(description = "班级名称", hidden = true)
private String className;
/**
* 企业名称(扩展字段,用于显示)
*/
@Schema(description = "企业名称", hidden = true)
private String companyName;
/**
* 实习岗位(扩展字段,用于显示)
*/
@Schema(description = "实习岗位", hidden = true)
private String position;
// ==================== 兼容移动端字段(前端可能使用的别名) ====================
/**
* 日总结(兼容移动端,实际映射为workContent)
*/
@Schema(description = "日总结", hidden = true)
private String dailySummary;
// ==================== 数据转换方法(处理前端字段映射) ====================
/**
* 处理移动端兼容字段映射
* 将移动端使用的字段名映射到实际的字段
*/
public void processCompatibleFields() {
// 处理经纬度映射(签到时映射到签退字段存储)
if (this.latitude != null && this.checkOutLatitude == null) {
this.checkOutLatitude = this.latitude;
}
if (this.longitude != null && this.checkOutLongitude == null) {
this.checkOutLongitude = this.longitude;
}
// 处理工作内容映射
if (this.dailySummary != null && this.workContent == null) {
this.workContent = this.dailySummary;
}
// 处理签到位置映射(签到时映射到签退字段存储)
if (this.checkInLocation != null && this.checkOutLocation == null) {
this.checkOutLocation = this.checkInLocation;
}
}
/**
* 获取实际的签退地点(优先使用checkOutLocation,否则使用checkInLocation)
*/
public String getActualCheckOutLocation() {
return this.checkOutLocation != null ? this.checkOutLocation : this.checkInLocation;
}
/**
* 获取实际的签退经度(优先使用checkOutLongitude,否则使用longitude)
*/
public BigDecimal getActualCheckOutLongitude() {
return this.checkOutLongitude != null ? this.checkOutLongitude : this.longitude;
}
/**
* 获取实际的签退纬度(优先使用checkOutLatitude,否则使用latitude)
*/
public BigDecimal getActualCheckOutLatitude() {
return this.checkOutLatitude != null ? this.checkOutLatitude : this.latitude;
}
/**
* 获取实际的工作内容(优先使用workContent,否则使用dailySummary)
*/
public String getActualWorkContent() {
return this.workContent != null ? this.workContent : this.dailySummary;
}
}
@@ -0,0 +1,91 @@
package org.dromara.zsjy.domain.bo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.dromara.common.mybatis.core.domain.BaseEntity;
import java.io.Serial;
import java.util.Date;
/**
* 实习日常管理查询业务对象 ZsjyInternshipDailyQueryBo
*
* @author system
* @date 2025-01-03
*/
@Data
@EqualsAndHashCode(callSuper = true)
@Schema(description = "实习日常管理查询业务对象")
public class ZsjyInternshipDailyQueryBo extends BaseEntity {
@Serial
private static final long serialVersionUID = 1L;
/**
* 学生ID
*/
@Schema(description = "学生ID")
private Long studentId;
/**
* 学号
*/
@Schema(description = "学号")
private String studentNo;
/**
* 学生姓名
*/
@Schema(description = "学生姓名")
private String studentName;
/**
* 实习ID
*/
@Schema(description = "实习ID")
private Long internshipId;
/**
* 打卡开始日期
*/
@Schema(description = "打卡开始日期")
private Date checkDateStart;
/**
* 打卡结束日期
*/
@Schema(description = "打卡结束日期")
private Date checkDateEnd;
/**
* 是否异常(0正常 1异常)
*/
@Schema(description = "是否异常")
private String isException;
/**
* 异常处理状态(0待处理 1已处理)
*/
@Schema(description = "异常处理状态")
private String exceptionStatus;
/**
* 状态(0正常 1停用)
*/
@Schema(description = "状态")
private String status;
/**
* 公司名称
*/
@Schema(description = "公司名称")
private String companyName;
/**
* 班主任ID(用于权限控制)
*/
@Schema(description = "班主任ID")
private Long headTeacherId;
}
@@ -0,0 +1,147 @@
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.AddGroup;
import org.dromara.common.core.validate.EditGroup;
import org.dromara.common.mybatis.core.domain.BaseEntity;
import jakarta.validation.constraints.*;
import java.util.Date;
/**
* 学生月度实习总结新增/编辑对象 ZsjyInternshipMonthlyAddBo
*
* @author system
* @date 2025-01-03
*/
@Data
@EqualsAndHashCode(callSuper = true)
@Schema(description = "学生月度实习总结新增/编辑对象")
public class ZsjyInternshipMonthlyAddBo extends BaseEntity {
/**
* 月度总结ID
*/
@Schema(description = "月度总结ID")
@NotNull(message = "月度总结ID不能为空", groups = { EditGroup.class })
private Long monthlyId;
/**
* 实习ID
*/
@Schema(description = "实习ID")
@NotNull(message = "实习ID不能为空", groups = { AddGroup.class, EditGroup.class })
private Long internshipId;
/**
* 总结月份 (格式: 2025-01)
*/
@Schema(description = "总结月份")
@NotBlank(message = "总结月份不能为空", groups = { AddGroup.class, EditGroup.class })
@Pattern(regexp = "^\\d{4}-\\d{2}$", message = "月份格式应为 YYYY-MM", groups = { AddGroup.class, EditGroup.class })
private String summaryMonth;
/**
* 工作内容 (必填,500字以内)
*/
@Schema(description = "工作内容")
@NotBlank(message = "工作内容不能为空", groups = { AddGroup.class, EditGroup.class })
@Size(max = 500, message = "工作内容不能超过500字", groups = { AddGroup.class, EditGroup.class })
private String workContent;
/**
* 主要成果
*/
@Schema(description = "主要成果")
@Size(max = 500, message = "主要成果不能超过500字", groups = { AddGroup.class, EditGroup.class })
private String achievements;
/**
* 学习收获
*/
@Schema(description = "学习收获")
@Size(max = 500, message = "学习收获不能超过500字", groups = { AddGroup.class, EditGroup.class })
private String learningGains;
/**
* 遇到的问题(包含解决方案,按2-A方案合并)
*/
@Schema(description = "遇到的问题")
@Size(max = 1000, message = "遇到的问题不能超过1000字", groups = { AddGroup.class, EditGroup.class })
private String problemsEncountered;
/**
* 自我评价
*/
@Schema(description = "自我评价")
@Size(max = 500, message = "自我评价不能超过500字", groups = { AddGroup.class, EditGroup.class })
private String selfEvaluation;
/**
* 下月工作计划
*/
@Schema(description = "下月工作计划")
@Size(max = 500, message = "下月工作计划不能超过500字", groups = { AddGroup.class, EditGroup.class })
private String nextMonthPlan;
/**
* 专业技能自评 (1-10分)
*/
@Schema(description = "专业技能自评")
@Min(value = 1, message = "专业技能自评最小值为1", groups = { AddGroup.class, EditGroup.class })
@Max(value = 10, message = "专业技能自评最大值为10", groups = { AddGroup.class, EditGroup.class })
private Integer professionalSkills;
/**
* 沟通技能自评 (1-10分)
*/
@Schema(description = "沟通技能自评")
@Min(value = 1, message = "沟通技能自评最小值为1", groups = { AddGroup.class, EditGroup.class })
@Max(value = 10, message = "沟通技能自评最大值为10", groups = { AddGroup.class, EditGroup.class })
private Integer communicationSkills;
/**
* 团队协作自评 (1-10分) - 修正字段映射
*/
@Schema(description = "团队协作自评")
@Min(value = 1, message = "团队协作自评最小值为1", groups = { AddGroup.class, EditGroup.class })
@Max(value = 10, message = "团队协作自评最大值为10", groups = { AddGroup.class, EditGroup.class })
private Integer teamworkAbility;
/**
* 学习能力自评 (1-10分)
*/
@Schema(description = "学习能力自评")
@Min(value = 1, message = "学习能力自评最小值为1", groups = { AddGroup.class, EditGroup.class })
@Max(value = 10, message = "学习能力自评最大值为10", groups = { AddGroup.class, EditGroup.class })
private Integer learningAbility;
/**
* 工作态度自评 (1-10分)
*/
@Schema(description = "工作态度自评")
@Min(value = 1, message = "工作态度自评最小值为1", groups = { AddGroup.class, EditGroup.class })
@Max(value = 10, message = "工作态度自评最大值为10", groups = { AddGroup.class, EditGroup.class })
private Integer workAttitude;
/**
* 附件信息 (JSON格式存储)
*/
@Schema(description = "附件信息")
private String attachments;
/**
* 审核状态 (0-待审核 1-已审核 2-审核拒绝 3-草稿)
*/
@Schema(description = "审核状态")
private Integer reviewStatus;
/**
* 提交时间
*/
@Schema(description = "提交时间")
private Date submitTime;
}
@@ -0,0 +1,61 @@
package org.dromara.zsjy.domain.bo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.dromara.common.mybatis.core.domain.BaseEntity;
/**
* 学生月度实习总结查询对象 ZsjyInternshipMonthlyQueryBo
*
* @author system
* @date 2025-01-03
*/
@Data
@EqualsAndHashCode(callSuper = true)
@Schema(description = "学生月度实习总结查询对象")
public class ZsjyInternshipMonthlyQueryBo extends BaseEntity {
/**
* 学生ID
*/
@Schema(description = "学生ID")
private Long studentId;
/**
* 总结月份 (格式: 2025-01)
*/
@Schema(description = "总结月份")
private String summaryMonth;
/**
* 审核状态 (0:待审核 1:已审核 2:审核拒绝 3:草稿)
*/
@Schema(description = "审核状态")
private Integer status;
/**
* 实习ID
*/
@Schema(description = "实习ID")
private Long internshipId;
/**
* 是否逾期 (0:未逾期 1:已逾期)
*/
@Schema(description = "是否逾期")
private Integer isOverdue;
/**
* 开始月份
*/
@Schema(description = "开始月份")
private String startMonth;
/**
* 结束月份
*/
@Schema(description = "结束月份")
private String endMonth;
}
Loaded 100 of 469 files, more files were not shown because too many files have changed in this diff. Show more