forked from liweijie/education
初始化提交
This commit is contained in:
+184
@@ -0,0 +1,184 @@
|
||||
package com.roomroot.jwgl.service;
|
||||
|
||||
import com.roomroot.jwgl.dto.accountmanagement.AccountCreateDTO;
|
||||
import com.roomroot.jwgl.dto.accountmanagement.AccountDisableDTO;
|
||||
import com.roomroot.jwgl.dto.accountmanagement.AccountIdDTO;
|
||||
import com.roomroot.jwgl.dto.accountmanagement.AccountLoginDTO;
|
||||
import com.roomroot.jwgl.dto.accountmanagement.AccountLoginInformationQueryDTO;
|
||||
import com.roomroot.jwgl.dto.accountmanagement.AccountMergeDTO;
|
||||
import com.roomroot.jwgl.dto.accountmanagement.AccountPasswordChangeDTO;
|
||||
import com.roomroot.jwgl.dto.accountmanagement.AccountPasswordResetDTO;
|
||||
import com.roomroot.jwgl.dto.accountmanagement.AccountQueryDTO;
|
||||
import com.roomroot.jwgl.dto.accountmanagement.AccountRoleConfigurationDTO;
|
||||
import com.roomroot.jwgl.dto.accountmanagement.AccountRoleOptionQueryDTO;
|
||||
import com.roomroot.jwgl.dto.accountmanagement.AccountSsoSessionResolveDTO;
|
||||
import com.roomroot.jwgl.dto.accountmanagement.AccountUpdateDTO;
|
||||
import com.roomroot.jwgl.unit.PageResult;
|
||||
import com.roomroot.jwgl.vo.accountmanagement.AccountMergeResultVO;
|
||||
import com.roomroot.jwgl.vo.accountmanagement.AccountLoginCaptchaVO;
|
||||
import com.roomroot.jwgl.vo.accountmanagement.AccountLoginInformationVO;
|
||||
import com.roomroot.jwgl.vo.accountmanagement.AccountLoginVO;
|
||||
import com.roomroot.jwgl.vo.accountmanagement.AccountRoleOptionVO;
|
||||
import com.roomroot.jwgl.vo.accountmanagement.AccountRoleTypeVO;
|
||||
import com.roomroot.jwgl.vo.accountmanagement.AccountRoleVO;
|
||||
import com.roomroot.jwgl.vo.accountmanagement.AccountSsoSessionVO;
|
||||
import com.roomroot.jwgl.vo.accountmanagement.AccountVO;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 账户管理服务。
|
||||
*
|
||||
* <p>账户资料、启停、密码重置、角色配置和账户合并均集中在当前服务中,
|
||||
* 避免同一业务功能被拆分为多个相互依赖的业务类。</p>
|
||||
*/
|
||||
public interface AccountManagementService {
|
||||
|
||||
/**
|
||||
* 查询账户列表。
|
||||
*
|
||||
* @param dto 账户查询条件
|
||||
* @return 经过筛选和稳定排序的账户分页结果
|
||||
*/
|
||||
PageResult<AccountVO> list(AccountQueryDTO dto);
|
||||
|
||||
/**
|
||||
* 查询账户详情。
|
||||
*
|
||||
* @param dto 账户编号参数
|
||||
* @return 包含角色和数据范围的账户详情
|
||||
*/
|
||||
AccountVO get(AccountIdDTO dto);
|
||||
|
||||
/**
|
||||
* 新增账户并配置初始角色。
|
||||
*
|
||||
* @param dto 账户新增参数
|
||||
* @return 新增后的账户详情
|
||||
*/
|
||||
AccountVO add(AccountCreateDTO dto);
|
||||
|
||||
/**
|
||||
* 修改账户基本信息。
|
||||
*
|
||||
* @param dto 账户修改参数
|
||||
* @return 修改后的账户详情
|
||||
*/
|
||||
AccountVO update(AccountUpdateDTO dto);
|
||||
|
||||
/**
|
||||
* 停用账户。
|
||||
*
|
||||
* @param dto 账户停用参数
|
||||
* @return 停用后的账户详情
|
||||
*/
|
||||
AccountVO disable(AccountDisableDTO dto);
|
||||
|
||||
/**
|
||||
* 启用账户。
|
||||
*
|
||||
* @param dto 账户编号参数
|
||||
* @return 启用后的账户详情
|
||||
*/
|
||||
AccountVO enable(AccountIdDTO dto);
|
||||
|
||||
/**
|
||||
* 重置账户密码。
|
||||
*
|
||||
* @param dto 密码重置参数
|
||||
* @return 密码重置后的账户详情
|
||||
*/
|
||||
AccountVO resetPassword(AccountPasswordResetDTO dto);
|
||||
|
||||
/**
|
||||
* 当前登录账户修改自己的密码。
|
||||
*
|
||||
* @param dto 原密码、新密码和确认密码
|
||||
* @return 密码修改后的脱敏账户详情
|
||||
*/
|
||||
AccountVO changePassword(AccountPasswordChangeDTO dto);
|
||||
|
||||
/**
|
||||
* 查询当前登录账户的登录信息和成功登录历史。
|
||||
*
|
||||
* @param dto 登录历史分页参数
|
||||
* @return 当前账户的登录统计和成功登录历史
|
||||
*/
|
||||
AccountLoginInformationVO getLoginInformation(
|
||||
AccountLoginInformationQueryDTO dto);
|
||||
|
||||
/**
|
||||
* 生成本地账户登录使用的一次性图形验证码。
|
||||
*
|
||||
* @return 验证码编号、PNG 图片数据和有效秒数
|
||||
*/
|
||||
AccountLoginCaptchaVO generateLoginCaptcha();
|
||||
|
||||
/**
|
||||
* 使用本地登录账号和密码建立账户管理登录会话。
|
||||
*
|
||||
* @param dto 本地登录参数
|
||||
* @return 脱敏后的本地账户登录结果
|
||||
*/
|
||||
AccountLoginVO login(AccountLoginDTO dto);
|
||||
|
||||
/**
|
||||
* 校验统一身份认证会话并解析唯一的本地账户。
|
||||
*
|
||||
* <p>由于现有资料没有明确 LoginID 和 UserID 中哪一个固定对应本地统一账号,
|
||||
* 当前业务会同时把两者作为候选,并拒绝候选值指向不同本地账户的场景。
|
||||
* 校验成功后同时建立本项目的 Servlet Session 和在线用户记录。</p>
|
||||
*
|
||||
* @param dto SSO 会话解析参数
|
||||
* @return SSO 会话及其对应的本地账户信息
|
||||
*/
|
||||
AccountSsoSessionVO resolveSsoSession(
|
||||
AccountSsoSessionResolveDTO dto);
|
||||
|
||||
/**
|
||||
* 退出当前 HTTP 会话。
|
||||
*
|
||||
* <p>退出接口不接收业务参数,也不返回业务数据,因此不新增 DTO 或 VO。</p>
|
||||
*/
|
||||
void logout();
|
||||
|
||||
/**
|
||||
* 查询系统支持的全部角色类型。
|
||||
*
|
||||
* @return 按页面展示顺序排列的角色类型列表
|
||||
*/
|
||||
List<AccountRoleTypeVO> listRoleTypes();
|
||||
|
||||
/**
|
||||
* 查询指定角色类型下可供配置的身份。
|
||||
*
|
||||
* @param dto 角色身份查询条件
|
||||
* @return 经过数据库筛选、去重和稳定排序的角色身份分页结果
|
||||
*/
|
||||
PageResult<AccountRoleOptionVO> listRoleOptions(
|
||||
AccountRoleOptionQueryDTO dto);
|
||||
|
||||
/**
|
||||
* 查询账户已经绑定的角色和数据范围。
|
||||
*
|
||||
* @param dto 账户编号参数
|
||||
* @return 账户角色列表
|
||||
*/
|
||||
List<AccountRoleVO> listRoles(AccountIdDTO dto);
|
||||
|
||||
/**
|
||||
* 整体替换账户角色和数据范围。
|
||||
*
|
||||
* @param dto 账户角色配置参数
|
||||
* @return 配置完成后的账户详情
|
||||
*/
|
||||
AccountVO configureRoles(AccountRoleConfigurationDTO dto);
|
||||
|
||||
/**
|
||||
* 将源账户角色迁移到目标账户并停用源账户。
|
||||
*
|
||||
* @param dto 账户合并参数
|
||||
* @return 源账户和目标账户的最新信息
|
||||
*/
|
||||
AccountMergeResultVO merge(AccountMergeDTO dto);
|
||||
}
|
||||
+157
@@ -0,0 +1,157 @@
|
||||
package com.roomroot.jwgl.service;
|
||||
|
||||
import com.roomroot.jwgl.dto.affiliationsetting.PersonnelAffiliationDTO;
|
||||
import com.roomroot.jwgl.dto.affiliationsetting.PersonnelTransferDTO;
|
||||
import com.roomroot.jwgl.dto.affiliationsetting.ResearchOfficeAffiliationAddDTO;
|
||||
import com.roomroot.jwgl.dto.affiliationsetting.ResearchOfficeAffiliationIdDTO;
|
||||
import com.roomroot.jwgl.dto.affiliationsetting.ResearchOfficeAffiliationQueryDTO;
|
||||
import com.roomroot.jwgl.dto.affiliationsetting.ResearchOfficeOptionQueryDTO;
|
||||
import com.roomroot.jwgl.dto.affiliationsetting.TeachingClassAffiliationDTO;
|
||||
import com.roomroot.jwgl.vo.affiliationsetting.AffiliationDepartmentVO;
|
||||
import com.roomroot.jwgl.vo.affiliationsetting.PersonnelAffiliationVO;
|
||||
import com.roomroot.jwgl.vo.affiliationsetting.ResearchOfficeAffiliationVO;
|
||||
import com.roomroot.jwgl.vo.affiliationsetting.ResearchOfficeVO;
|
||||
import com.roomroot.jwgl.vo.affiliationsetting.TeachingClassAffiliationVO;
|
||||
import com.roomroot.jwgl.vo.affiliationsetting.TransferHistoryVO;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 隶属关系设置统一服务。
|
||||
*/
|
||||
public interface AffiliationSettingService {
|
||||
|
||||
/**
|
||||
* 查询可供隶属关系页面选择的启用部别。
|
||||
*
|
||||
* @param dto 查询条件
|
||||
* @return 可选部别列表
|
||||
*/
|
||||
List<AffiliationDepartmentVO> listResearchOfficeDepartments(
|
||||
ResearchOfficeOptionQueryDTO dto);
|
||||
|
||||
/**
|
||||
* 查询指定部别已经关联的教研室。
|
||||
*
|
||||
* @param dto 部别编号及查询条件
|
||||
* @return 已建立的教研室隶属关系列表
|
||||
*/
|
||||
List<ResearchOfficeAffiliationVO> listResearchOfficeAffiliations(
|
||||
ResearchOfficeAffiliationQueryDTO dto);
|
||||
|
||||
/**
|
||||
* 查询尚未分配且处于启用状态的教研室。
|
||||
*
|
||||
* @param dto 查询条件
|
||||
* @return 可添加的教研室列表
|
||||
*/
|
||||
List<ResearchOfficeVO> listAvailableResearchOffices(ResearchOfficeOptionQueryDTO dto);
|
||||
|
||||
/**
|
||||
* 新增教研室隶属关系。
|
||||
*
|
||||
* @param dto 部别编号和教研室编号
|
||||
* @return 新增后的隶属关系
|
||||
*/
|
||||
ResearchOfficeAffiliationVO addResearchOfficeAffiliation(
|
||||
ResearchOfficeAffiliationAddDTO dto);
|
||||
|
||||
/**
|
||||
* 解除教研室隶属关系。
|
||||
*
|
||||
* @param dto 隶属关系编号
|
||||
* @return 被解除的隶属关系
|
||||
*/
|
||||
ResearchOfficeAffiliationVO removeResearchOfficeAffiliation(
|
||||
ResearchOfficeAffiliationIdDTO dto);
|
||||
|
||||
/**
|
||||
* 查询可供教学班次隶属关系页面选择的启用部别。
|
||||
*
|
||||
* @param dto 查询条件
|
||||
* @return 可选部别列表
|
||||
*/
|
||||
List<AffiliationDepartmentVO> listTeachingClassDepartments(
|
||||
TeachingClassAffiliationDTO dto);
|
||||
|
||||
/**
|
||||
* 查询指定部别已经关联的教学班次。
|
||||
*
|
||||
* @param dto 部别编号及查询条件
|
||||
* @return 已建立的教学班次隶属关系列表
|
||||
*/
|
||||
List<TeachingClassAffiliationVO> listTeachingClassAffiliations(
|
||||
TeachingClassAffiliationDTO dto);
|
||||
|
||||
/**
|
||||
* 查询尚未分配给任何部别的教学班次。
|
||||
*
|
||||
* @param dto 查询条件
|
||||
* @return 可添加的教学班次列表
|
||||
*/
|
||||
List<TeachingClassAffiliationVO> listAvailableTeachingClasses(
|
||||
TeachingClassAffiliationDTO dto);
|
||||
|
||||
/**
|
||||
* 新增教学班次隶属关系。
|
||||
*
|
||||
* @param dto 部别编号和教学班次编号
|
||||
* @return 新增后的隶属关系
|
||||
*/
|
||||
TeachingClassAffiliationVO addTeachingClassAffiliation(
|
||||
TeachingClassAffiliationDTO dto);
|
||||
|
||||
/**
|
||||
* 解除教学班次隶属关系。
|
||||
*
|
||||
* @param dto 部别编号和教学班次编号
|
||||
* @return 被解除的隶属关系
|
||||
*/
|
||||
TeachingClassAffiliationVO removeTeachingClassAffiliation(
|
||||
TeachingClassAffiliationDTO dto);
|
||||
|
||||
// ============ 人员隶属关系统一接口(方向1新增)============
|
||||
|
||||
/**
|
||||
* 查询人员当前隶属关系。
|
||||
* <p>按人员类型+部门编号筛选,返回当前归属该部门的人员列表。</p>
|
||||
*
|
||||
* @param dto 查询条件(personnelType必填,departmentId可选筛选)
|
||||
* @return 人员隶属关系列表
|
||||
*/
|
||||
List<PersonnelAffiliationVO> listPersonnelAffiliations(PersonnelAffiliationDTO dto);
|
||||
|
||||
/**
|
||||
* 分配人员到部门/组织单元(首次归属,不写异动历史)。
|
||||
*
|
||||
* @param dto 分配参数(personnelType+personnelId+departmentId必填)
|
||||
* @return 分配后的人员隶属关系
|
||||
*/
|
||||
PersonnelAffiliationVO assignPersonnel(PersonnelAffiliationDTO dto);
|
||||
|
||||
/**
|
||||
* 解除人员隶属关系(清空当前归属,不写异动历史)。
|
||||
*
|
||||
* @param dto 解除参数(personnelType+personnelId必填)
|
||||
* @return 解除后的人员隶属关系
|
||||
*/
|
||||
PersonnelAffiliationVO unassignPersonnel(PersonnelAffiliationDTO dto);
|
||||
|
||||
/**
|
||||
* 人员异动调整(核心接口)。
|
||||
* <p>更新当前归属 + 记录旧归属到previousDept + 追加异动历史JSON +
|
||||
* 校验新教研室/学员队在SSJGJYS/SSJGXYD中已有部门关系。</p>
|
||||
*
|
||||
* @param dto 异动参数(含reason必填)
|
||||
* @return 异动后的人员隶属关系
|
||||
*/
|
||||
PersonnelAffiliationVO transferPersonnel(PersonnelTransferDTO dto);
|
||||
|
||||
/**
|
||||
* 查询人员异动历史。
|
||||
*
|
||||
* @param dto 查询参数(personnelType+personnelId必填)
|
||||
* @return 异动历史VO(含JSON原文)
|
||||
*/
|
||||
TransferHistoryVO getTransferHistory(PersonnelAffiliationDTO dto);
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
package com.roomroot.jwgl.service;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.roomroot.jwgl.entity.BZLB;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 保障类别 Service
|
||||
*/
|
||||
public interface BZLBService {
|
||||
|
||||
/**
|
||||
* 新增
|
||||
*
|
||||
* @param bzlb 保障类别
|
||||
*/
|
||||
void add(BZLB bzlb);
|
||||
|
||||
/**
|
||||
* 删除
|
||||
*
|
||||
* @param bh 编号
|
||||
*/
|
||||
void delete(String bh);
|
||||
|
||||
/**
|
||||
* 更新
|
||||
*
|
||||
* @param bzlb 保障类别
|
||||
*/
|
||||
void update(BZLB bzlb);
|
||||
|
||||
/**
|
||||
* 根据编号查询
|
||||
*
|
||||
* @param bh 编号
|
||||
* @return 保障类别
|
||||
*/
|
||||
BZLB getByBh(String bh);
|
||||
|
||||
/**
|
||||
* 分页查询
|
||||
*
|
||||
* @param pageNum 页码
|
||||
* @param pageSize 每页数量
|
||||
* @param bzlb 查询条件
|
||||
* @return 分页结果
|
||||
*/
|
||||
Page<BZLB> list(int pageNum, int pageSize, BZLB bzlb);
|
||||
|
||||
/**
|
||||
* 查询所有
|
||||
*
|
||||
* @return 所有保障类别
|
||||
*/
|
||||
List<BZLB> all();
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
package com.roomroot.jwgl.service;
|
||||
|
||||
import com.roomroot.jwgl.entity.JXLB;
|
||||
import com.roomroot.jwgl.unit.PageQuery;
|
||||
import com.roomroot.jwgl.unit.PageResult;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 教学楼表服务接口
|
||||
*/
|
||||
public interface BuildService {
|
||||
|
||||
/**
|
||||
* 新增教学楼
|
||||
*
|
||||
* @param jxlb 教学楼
|
||||
*/
|
||||
void add(JXLB jxlb);
|
||||
|
||||
/**
|
||||
* 删除教学楼
|
||||
*
|
||||
* @param id 主键
|
||||
*/
|
||||
void delete(String id);
|
||||
|
||||
/**
|
||||
* 更新教学楼
|
||||
*
|
||||
* @param jxlb 教学楼
|
||||
*/
|
||||
void update(JXLB jxlb);
|
||||
|
||||
/**
|
||||
* 根据教学楼代号查询
|
||||
*
|
||||
* @param id 唯一标识
|
||||
* @return 教学楼
|
||||
*/
|
||||
JXLB getById(String id);
|
||||
|
||||
/**
|
||||
* 分页查询教学楼列表
|
||||
*
|
||||
* @param query 分页参数
|
||||
* @param jxlb 查询条件
|
||||
* @return 分页结果
|
||||
*/
|
||||
PageResult<JXLB> pageList(PageQuery query, JXLB jxlb);
|
||||
|
||||
/**
|
||||
* 查询所有教学楼列表
|
||||
*
|
||||
* @param jxlb 查询条件
|
||||
* @return 教学楼列表
|
||||
*/
|
||||
List<JXLB> list(JXLB jxlb);
|
||||
|
||||
/**
|
||||
* 导入Excel文件
|
||||
*
|
||||
* @param file Excel文件
|
||||
* @return 导入数量
|
||||
*/
|
||||
int importExcel(MultipartFile file);
|
||||
|
||||
/**
|
||||
* 下载模板文件
|
||||
*
|
||||
* @param response HTTP响应
|
||||
*/
|
||||
void downloadTemplate(HttpServletResponse response);
|
||||
|
||||
/**
|
||||
* 生成下一个序号/教学楼代号
|
||||
*
|
||||
* @return 格式化后的序号
|
||||
*/
|
||||
String generateNextXh();
|
||||
}
|
||||
+75
@@ -0,0 +1,75 @@
|
||||
package com.roomroot.jwgl.service;
|
||||
|
||||
import com.roomroot.jwgl.entity.JXCDL;
|
||||
import com.roomroot.jwgl.unit.PageQuery;
|
||||
import com.roomroot.jwgl.unit.PageResult;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 教学场地历服务接口
|
||||
*/
|
||||
public interface ClassRoomCalendarService {
|
||||
|
||||
/**
|
||||
* 新增教学场地历
|
||||
*
|
||||
* @param jxcdl 教学场地历
|
||||
*/
|
||||
void add(JXCDL jxcdl);
|
||||
|
||||
/**
|
||||
* 删除教学场地历
|
||||
*
|
||||
* @param id 主键ID
|
||||
*/
|
||||
void delete(String id);
|
||||
|
||||
/**
|
||||
* 更新教学场地历
|
||||
*
|
||||
* @param jxcdl 教学场地历
|
||||
*/
|
||||
void update(JXCDL jxcdl);
|
||||
|
||||
/**
|
||||
* 根据ID查询
|
||||
*
|
||||
* @param id 主键ID
|
||||
* @return 教学场地历
|
||||
*/
|
||||
JXCDL getById(String id);
|
||||
|
||||
/**
|
||||
* 分页查询教学场地历列表
|
||||
*
|
||||
* @param query 分页参数
|
||||
* @param jxcdl 查询条件
|
||||
* @return 分页结果
|
||||
*/
|
||||
PageResult<JXCDL> pageList(PageQuery query, JXCDL jxcdl);
|
||||
|
||||
/**
|
||||
* 查询所有教学场地历列表
|
||||
*
|
||||
* @param jxcdl 查询条件
|
||||
* @return 教学场地历列表
|
||||
*/
|
||||
List<JXCDL> list(JXCDL jxcdl);
|
||||
|
||||
/**
|
||||
* 根据教室编号查询教学场地历列表
|
||||
*
|
||||
* @param jsbh 教室编号
|
||||
* @return 教学场地历列表
|
||||
*/
|
||||
List<JXCDL> listByJsbh(String jsbh);
|
||||
|
||||
/**
|
||||
* 根据日期查询教学场地历列表
|
||||
*
|
||||
* @param rq 日期
|
||||
* @return 教学场地历列表
|
||||
*/
|
||||
List<JXCDL> listByRq(String rq);
|
||||
}
|
||||
+68
@@ -0,0 +1,68 @@
|
||||
package com.roomroot.jwgl.service;
|
||||
|
||||
import com.roomroot.jwgl.entity.JSBKCB;
|
||||
import com.roomroot.jwgl.unit.PageQuery;
|
||||
import com.roomroot.jwgl.unit.PageResult;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 教室输出课程表服务接口
|
||||
*/
|
||||
public interface ClassRoomLessonService {
|
||||
|
||||
/**
|
||||
* 新增教室输出课程表
|
||||
*
|
||||
* @param jsbkcb 教室输出课程表
|
||||
*/
|
||||
void add(JSBKCB jsbkcb);
|
||||
|
||||
/**
|
||||
* 删除教室输出课程表
|
||||
*
|
||||
* @param id 主键ID
|
||||
*/
|
||||
void delete(String id);
|
||||
|
||||
/**
|
||||
* 更新教室输出课程表
|
||||
*
|
||||
* @param jsbkcb 教室输出课程表
|
||||
*/
|
||||
void update(JSBKCB jsbkcb);
|
||||
|
||||
/**
|
||||
* 根据ID查询
|
||||
*
|
||||
* @param id 主键ID
|
||||
* @return 教室输出课程表
|
||||
*/
|
||||
JSBKCB getById(String id);
|
||||
|
||||
/**
|
||||
* 根据教室编号和年度查询
|
||||
*
|
||||
* @param jsbh 教室编号
|
||||
* @param nd 年度
|
||||
* @return 教室输出课程表
|
||||
*/
|
||||
JSBKCB getByJsbhAndNd(String jsbh, Integer nd);
|
||||
|
||||
/**
|
||||
* 分页查询教室输出课程表列表
|
||||
*
|
||||
* @param query 分页参数
|
||||
* @param jsbkcb 查询条件
|
||||
* @return 分页结果
|
||||
*/
|
||||
PageResult<JSBKCB> pageList(PageQuery query, JSBKCB jsbkcb);
|
||||
|
||||
/**
|
||||
* 查询所有教室输出课程表列表
|
||||
*
|
||||
* @param jsbkcb 查询条件
|
||||
* @return 教室输出课程表列表
|
||||
*/
|
||||
List<JSBKCB> list(JSBKCB jsbkcb);
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
package com.roomroot.jwgl.service;
|
||||
|
||||
import com.roomroot.jwgl.entity.JSB;
|
||||
import com.roomroot.jwgl.unit.PageQuery;
|
||||
import com.roomroot.jwgl.unit.PageResult;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 教室表服务接口
|
||||
*/
|
||||
public interface ClassRoomService {
|
||||
|
||||
/**
|
||||
* 新增教室
|
||||
*
|
||||
* @param jsb 教室
|
||||
*/
|
||||
void add(JSB jsb);
|
||||
|
||||
/**
|
||||
* 删除教室
|
||||
*
|
||||
* @param id 唯一标识符
|
||||
*/
|
||||
void delete(String id);
|
||||
|
||||
/**
|
||||
* 更新教室
|
||||
*
|
||||
* @param jsb 教室
|
||||
*/
|
||||
void update(JSB jsb);
|
||||
|
||||
/**
|
||||
* 根据教室编号查询
|
||||
*
|
||||
* @param id 教室编号
|
||||
* @return 教室
|
||||
*/
|
||||
JSB getById(String id);
|
||||
|
||||
/**
|
||||
* 分页查询教室列表
|
||||
*
|
||||
* @param query 分页参数
|
||||
* @param jsb 查询条件
|
||||
* @return 分页结果
|
||||
*/
|
||||
PageResult<JSB> pageList(PageQuery query, JSB jsb);
|
||||
|
||||
/**
|
||||
* 查询所有教室列表
|
||||
*
|
||||
* @param jsb 查询条件
|
||||
* @return 教室列表
|
||||
*/
|
||||
List<JSB> list(JSB jsb);
|
||||
|
||||
/**
|
||||
* 根据教学楼代号查询教室列表
|
||||
*
|
||||
* @param jxldh 教学楼代号
|
||||
* @return 教室列表
|
||||
*/
|
||||
List<JSB> listByJxldh(String jxldh);
|
||||
}
|
||||
+52
@@ -0,0 +1,52 @@
|
||||
package com.roomroot.jwgl.service;
|
||||
|
||||
import com.roomroot.jwgl.entity.XYDRWB;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 学员队任务表服务接口
|
||||
*/
|
||||
public interface ClassSemesterCalendarService {
|
||||
|
||||
/**
|
||||
* 更新
|
||||
*
|
||||
* @param xydrwb 实体
|
||||
*/
|
||||
void update(XYDRWB xydrwb);
|
||||
|
||||
/**
|
||||
* 根据编号查询
|
||||
*
|
||||
* @param bh 编号
|
||||
* @return 实体
|
||||
*/
|
||||
XYDRWB getByBh(String bh);
|
||||
|
||||
/**
|
||||
* 条目批次复制
|
||||
*
|
||||
* @param sourceBhList 源学员队任务表编号列表
|
||||
* @param targetBhList 目标学员队期表编号列表
|
||||
* @return 包含count(复制数量)、failedSourceBhs(不存在的源编号)、failedTargetBhs(不存在的目标编号)
|
||||
*/
|
||||
Map<String, Object> batchCopy(List<String> sourceBhList, List<String> targetBhList);
|
||||
|
||||
/**
|
||||
* 按学期批次复制
|
||||
*
|
||||
* @param sourceXydxqbh 源学员队期表编号
|
||||
* @param targetBhList 目标学员队期表编号列表
|
||||
* @return 包含count(复制数量)、failedTargetBhs(不存在的目标编号)
|
||||
*/
|
||||
Map<String, Object> batchCopyBySemester(String sourceXydxqbh, List<String> targetBhList);
|
||||
|
||||
/**
|
||||
* 查询所有有效数据(DEL_FLAG = 0)
|
||||
*
|
||||
* @return 所有有效数据列表
|
||||
*/
|
||||
List<XYDRWB> listAllValid(XYDRWB xydrwb);
|
||||
}
|
||||
+116
@@ -0,0 +1,116 @@
|
||||
package com.roomroot.jwgl.service;
|
||||
|
||||
import com.roomroot.jwgl.entity.XYDNDXQJBXXB;
|
||||
import com.roomroot.jwgl.unit.PageQuery;
|
||||
import com.roomroot.jwgl.unit.PageResult;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 班次学期服务接口
|
||||
*/
|
||||
public interface ClassSemesterService {
|
||||
|
||||
/**
|
||||
* 新增
|
||||
*
|
||||
* @param xydndxqjbxxb 实体
|
||||
*/
|
||||
void add(XYDNDXQJBXXB xydndxqjbxxb);
|
||||
|
||||
/**
|
||||
* 删除
|
||||
*
|
||||
* @param bh 编号
|
||||
*/
|
||||
void delete(String bh);
|
||||
|
||||
/**
|
||||
* 批量删除
|
||||
*
|
||||
* @param bhList 编号列表
|
||||
*/
|
||||
void batchDelete(List<String> bhList);
|
||||
|
||||
/**
|
||||
* 更新
|
||||
*
|
||||
* @param xydndxqjbxxb 实体
|
||||
*/
|
||||
void update(XYDNDXQJBXXB xydndxqjbxxb);
|
||||
|
||||
/**
|
||||
* 根据编号查询
|
||||
*
|
||||
* @param bh 编号
|
||||
* @return 实体
|
||||
*/
|
||||
XYDNDXQJBXXB getByBh(String bh);
|
||||
|
||||
/**
|
||||
* 分页查询列表
|
||||
*
|
||||
* @param query 分页参数
|
||||
* @param xydndxqjbxxb 查询条件
|
||||
* @return 分页结果
|
||||
*/
|
||||
PageResult<XYDNDXQJBXXB> pageList(PageQuery query, XYDNDXQJBXXB xydndxqjbxxb);
|
||||
|
||||
/**
|
||||
* 查询所有有效数据(DEL_FLAG = 0)
|
||||
*
|
||||
* @return 所有有效数据列表
|
||||
*/
|
||||
List<XYDNDXQJBXXB> listAllValid();
|
||||
|
||||
/**
|
||||
* 根据选修班次列表批量添加班次学期
|
||||
*
|
||||
* @param startTime 时间范围开始
|
||||
* @param endTime 时间范围结束
|
||||
* @param nd 年度
|
||||
* @param xqdc 学期第次
|
||||
* @param xqkssj 学期开始时间
|
||||
* @param xqjssj 学期结束时间
|
||||
* @return 添加数量
|
||||
*/
|
||||
int batchAddFromElective(java.time.LocalDateTime startTime, java.time.LocalDateTime endTime,
|
||||
String nd, String xqdc, String xqkssj, String xqjssj);
|
||||
|
||||
/**
|
||||
* 批量修改开放教员排课状态
|
||||
*
|
||||
* @param bhList 编号列表
|
||||
* @param kfjypk 开放教员排课(0-否,1-是)
|
||||
* @return 更新数量
|
||||
*/
|
||||
int batchUpdateKfjypk(List<String> bhList, Integer kfjypk);
|
||||
|
||||
/**
|
||||
* 批量修改学期第次
|
||||
*
|
||||
* @param bhList 编号列表
|
||||
* @param xqdc 学期第次
|
||||
* @return 更新数量
|
||||
*/
|
||||
int batchUpdateXqdc(List<String> bhList, Integer xqdc);
|
||||
|
||||
/**
|
||||
* 批量修改教学任务编号
|
||||
*
|
||||
* @param bhList 编号列表
|
||||
* @param jxrwbh 教学任务编号
|
||||
* @return 更新数量
|
||||
*/
|
||||
int batchUpdateJxrwbh(List<String> bhList, String jxrwbh);
|
||||
|
||||
/**
|
||||
* 批量修改班次学期的日期范围,并同步更新日历记录
|
||||
*
|
||||
* @param bhList 编号列表
|
||||
* @param xqkssj 学期开始时间
|
||||
* @param xqjssj 学期结束时间
|
||||
* @return 更新数量
|
||||
*/
|
||||
int batchUpdateDateRange(List<String> bhList, String xqkssj, String xqjssj);
|
||||
}
|
||||
+548
@@ -0,0 +1,548 @@
|
||||
package com.roomroot.jwgl.service;
|
||||
|
||||
import com.roomroot.jwgl.dto.courserunning.ClassesImportDTO;
|
||||
import com.roomroot.jwgl.dto.courserunning.ImportRemoveDTO;
|
||||
import com.roomroot.jwgl.dto.courserunning.ScheduleAdjustApplyDTO;
|
||||
import com.roomroot.jwgl.dto.courserunning.ScheduleAdjustAuditDTO;
|
||||
import com.roomroot.jwgl.dto.courserunning.ScheduleAdjustQueryDTO;
|
||||
import com.roomroot.jwgl.dto.courserunning.SemesterImportDTO;
|
||||
import com.roomroot.jwgl.dto.courserunning.SingleCourseImportDTO;
|
||||
import com.roomroot.jwgl.dto.courserunning.TeachingPlanBatchFillDTO;
|
||||
import com.roomroot.jwgl.dto.courserunning.TeachingPlanFillDTO;
|
||||
import com.roomroot.jwgl.dto.courserunning.TeachingPlanQueryDTO;
|
||||
import com.roomroot.jwgl.dto.courserunning.TeachingSupportBatchPlanDTO;
|
||||
import com.roomroot.jwgl.dto.courserunning.TeachingSupportConfirmDTO;
|
||||
import com.roomroot.jwgl.dto.courserunning.TeachingSupportPlanDTO;
|
||||
import com.roomroot.jwgl.dto.courserunning.TeachingSupportUpdateDTO;
|
||||
import com.roomroot.jwgl.dto.courserunning.StudentLeaveApplyDTO;
|
||||
import com.roomroot.jwgl.dto.courserunning.StudentLeaveAuditDTO;
|
||||
import com.roomroot.jwgl.dto.courserunning.StudentLeaveQueryDTO;
|
||||
import com.roomroot.jwgl.dto.courserunning.OperationAnalysisQueryDTO;
|
||||
import com.roomroot.jwgl.dto.courserunning.ScheduleAdjustStrategyDTO;
|
||||
import com.roomroot.jwgl.unit.PageResult;
|
||||
import com.roomroot.jwgl.vo.courserunning.CourseRunningImportResultVO;
|
||||
import com.roomroot.jwgl.vo.courserunning.ScheduleAdjustApplyVO;
|
||||
import com.roomroot.jwgl.vo.courserunning.ScheduleAdjustDetailVO;
|
||||
import com.roomroot.jwgl.vo.courserunning.TeachingPlanDetailVO;
|
||||
import com.roomroot.jwgl.vo.courserunning.TeachingPlanFillResultVO;
|
||||
import com.roomroot.jwgl.vo.courserunning.TeachingPlanLessonVO;
|
||||
import com.roomroot.jwgl.vo.courserunning.TeachingSupportConfirmResultVO;
|
||||
import com.roomroot.jwgl.vo.courserunning.TeachingSupportHistoryVO;
|
||||
import com.roomroot.jwgl.vo.courserunning.TeachingSupportPlanVO;
|
||||
import com.roomroot.jwgl.vo.courserunning.TeachingSupportResourceVO;
|
||||
import com.roomroot.jwgl.vo.courserunning.StudentLeaveApplyVO;
|
||||
import com.roomroot.jwgl.vo.courserunning.StudentLeaveDetailVO;
|
||||
import com.roomroot.jwgl.vo.courserunning.OperationOverviewVO;
|
||||
import com.roomroot.jwgl.vo.courserunning.CourseCompletionByDeptVO;
|
||||
import com.roomroot.jwgl.vo.courserunning.VenueUsageRateVO;
|
||||
import com.roomroot.jwgl.vo.courserunning.ScheduleAdjustTrendVO;
|
||||
import com.roomroot.jwgl.vo.courserunning.ScheduleAdjustStrategyVO;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 课程教学运行管理服务接口。
|
||||
* <p>
|
||||
* 提供课程教学运行管理的全部业务能力,包括:<br>
|
||||
* 1. 教学运行数据导入:从课程教学计划编制子系统向课程教学运行管理子系统导入数据;<br>
|
||||
* 2. 教学实施计划填写:对已导入的课次进行教学实施计划内容的填写、查询和提交。
|
||||
* </p>
|
||||
*/
|
||||
public interface CourseRunningImportService {
|
||||
|
||||
// ==================== 教学运行数据导入 ====================
|
||||
|
||||
/**
|
||||
* 按学期导入课程。
|
||||
* <p>
|
||||
* 从课程教学计划编制子系统导入指定年度学期的所有课程安排数据。
|
||||
* </p>
|
||||
*
|
||||
* @param params 学期导入参数
|
||||
* @return 导入结果
|
||||
*/
|
||||
CourseRunningImportResultVO importBySemester(SemesterImportDTO params);
|
||||
|
||||
/**
|
||||
* 按教学班次导入课程。
|
||||
* <p>
|
||||
* 从课程教学计划编制子系统导入指定教学班次的课程安排数据。
|
||||
* </p>
|
||||
*
|
||||
* @param params 教学班次导入参数
|
||||
* @return 导入结果
|
||||
*/
|
||||
CourseRunningImportResultVO importByClasses(ClassesImportDTO params);
|
||||
|
||||
/**
|
||||
* 导入单门课程。
|
||||
* <p>
|
||||
* 从课程教学计划编制子系统导入指定教学班次的单门课程安排数据。
|
||||
* </p>
|
||||
*
|
||||
* @param params 单门课程导入参数
|
||||
* @return 导入结果
|
||||
*/
|
||||
CourseRunningImportResultVO importSingleCourse(SingleCourseImportDTO params);
|
||||
|
||||
/**
|
||||
* 删除已导入课程。
|
||||
* <p>
|
||||
* 删除已导入到课程教学运行管理子系统的课次数据,支持按学期、班次或单个课次删除。
|
||||
* </p>
|
||||
*
|
||||
* @param params 删除参数
|
||||
*/
|
||||
void removeImportedCourses(ImportRemoveDTO params);
|
||||
|
||||
// ==================== 教学实施计划填写 ====================
|
||||
|
||||
/**
|
||||
* 分页查询待填写或已填写的课次列表。
|
||||
* <p>
|
||||
* 根据查询条件(实施课程编号、年度、教学方法、日期范围、填写状态等)
|
||||
* 分页查询课次列表,返回课次基本信息及填写状态。
|
||||
* </p>
|
||||
/**
|
||||
* 分页查询待填写或已填写的课次列表。
|
||||
*
|
||||
* @param query 查询参数(包含分页信息和筛选条件)
|
||||
* @return 分页课次列表
|
||||
*/
|
||||
PageResult<TeachingPlanLessonVO> queryLessonList(TeachingPlanQueryDTO query);
|
||||
|
||||
/**
|
||||
* 按查询条件导出课次数据为 Excel 文件。
|
||||
*
|
||||
* @param query 查询参数(包含筛选条件)
|
||||
* @return Excel 文件字节数组
|
||||
*/
|
||||
byte[] exportLessonListToExcel(TeachingPlanQueryDTO query);
|
||||
|
||||
/**
|
||||
* 查询单个课次的教学实施计划详情。
|
||||
* <p>
|
||||
* 根据课次编号查询该课次的完整教学实施计划信息,包括教学内容、教学要点、
|
||||
* 教学方法、日期节次、班组信息、保障需求及教员备注等。
|
||||
* </p>
|
||||
*
|
||||
* @param sskcbbh 实施_课程表编号(课次编号)
|
||||
* @return 教学实施计划详情
|
||||
*/
|
||||
TeachingPlanDetailVO getTeachingPlanDetail(String sskcbbh);
|
||||
|
||||
/**
|
||||
* 单条填写教学实施计划。
|
||||
* <p>
|
||||
* 对单个课次填写教学实施计划内容,保存后填写状态更新为"已填写"。
|
||||
* </p>
|
||||
*
|
||||
* @param dto 教学实施计划填写参数
|
||||
* @return 填写结果
|
||||
*/
|
||||
TeachingPlanFillResultVO fillTeachingPlan(TeachingPlanFillDTO dto);
|
||||
|
||||
/**
|
||||
* 批量填写教学实施计划。
|
||||
* <p>
|
||||
* 一次性提交多个课次的教学实施计划填写数据,逐条处理并返回整体执行结果。
|
||||
* </p>
|
||||
*
|
||||
* @param dto 批量教学实施计划填写参数
|
||||
* @return 批量填写结果
|
||||
*/
|
||||
TeachingPlanFillResultVO batchFillTeachingPlan(TeachingPlanBatchFillDTO dto);
|
||||
|
||||
/**
|
||||
* 提交教学实施计划。
|
||||
* <p>
|
||||
* 将已填写的教学实施计划提交审核,提交后填写状态更新为"已提交",
|
||||
* 已提交的实施计划原则上不允许再修改,如需修改需先撤回。
|
||||
* </p>
|
||||
*
|
||||
* @param sskcbbh 实施_课程表编号(课次编号)
|
||||
*/
|
||||
void submitTeachingPlan(String sskcbbh);
|
||||
|
||||
// ==================== 调课管理 ====================
|
||||
|
||||
/**
|
||||
* 分页查询调课申请列表。
|
||||
* <p>
|
||||
* 根据查询条件(实施_课程表编号、申请教员、年度、审批状态、查收状态、
|
||||
* 删除状态、申请日期范围等)分页查询调课申请列表。
|
||||
* </p>
|
||||
*
|
||||
* @param query 查询参数(包含分页信息和筛选条件)
|
||||
* @return 分页调课申请列表
|
||||
*/
|
||||
PageResult<ScheduleAdjustApplyVO> queryScheduleAdjustList(ScheduleAdjustQueryDTO query);
|
||||
|
||||
/**
|
||||
* 查询单个调课申请的完整详情。
|
||||
* <p>
|
||||
* 根据调课申请编号查询该申请的完整信息,包括申请信息、调整后的内容、
|
||||
* 教研室审批状态、机关审批记录、关联的教室、辅助教员、学员队、保障明细等。
|
||||
* </p>
|
||||
*
|
||||
* @param ssdksqbh 调课申请编号
|
||||
* @return 调课申请详情
|
||||
*/
|
||||
ScheduleAdjustDetailVO getScheduleAdjustDetail(String ssdksqbh);
|
||||
|
||||
/**
|
||||
* 提交调课申请。
|
||||
* <p>
|
||||
* 教员提交调课申请,包含课次编号、调课事由、新的日期节次、新的教室、
|
||||
* 辅助教员、学员队、保障明细等完整信息。
|
||||
* 同时更新课次数据,将课次的日期节次替换为调整后的新值。
|
||||
* </p>
|
||||
*
|
||||
* @param dto 调课申请参数
|
||||
* @return 调课申请编号
|
||||
*/
|
||||
String submitScheduleAdjust(ScheduleAdjustApplyDTO dto);
|
||||
|
||||
/**
|
||||
* 教研室审批调课申请。
|
||||
* <p>
|
||||
* 教研室审批教员提交的调课申请,包含同意、发回、拒绝三种处理方式。
|
||||
* 同意时同步更新课次数据,发回时记录发回原因,拒绝时标记申请为已拒绝。
|
||||
* </p>
|
||||
*
|
||||
* @param dto 教研室审批参数
|
||||
*/
|
||||
void auditByTeachingOffice(ScheduleAdjustAuditDTO dto);
|
||||
|
||||
/**
|
||||
* 教研室查收调课申请。
|
||||
* <p>
|
||||
* 教研室查收调课申请,标记查收状态和查收时间。
|
||||
* </p>
|
||||
*
|
||||
* @param ssdksqbh 调课申请编号
|
||||
* @param csrbh 查收人编号
|
||||
*/
|
||||
void receiveByTeachingOffice(String ssdksqbh, String csrbh);
|
||||
|
||||
/**
|
||||
* 教学系审批调课申请。
|
||||
* <p>
|
||||
* 教学系审批教研室已同意的调课申请,包含同意、发回、拒绝三种处理方式。
|
||||
* 教学系同意后流转到机关审批。
|
||||
* </p>
|
||||
*
|
||||
* @param dto 教学系审批参数
|
||||
*/
|
||||
void auditByTeachingDepartment(ScheduleAdjustAuditDTO dto);
|
||||
|
||||
/**
|
||||
* 机关审批调课申请。
|
||||
* <p>
|
||||
* 机关审批教研室已同意的调课申请,包含同意、发回、拒绝三种处理方式。
|
||||
* 机关全部同意后调课申请最终生效,课次按调整后的内容执行。
|
||||
* </p>
|
||||
*
|
||||
* @param dto 机关审批参数
|
||||
*/
|
||||
void auditByAuthority(ScheduleAdjustAuditDTO dto);
|
||||
|
||||
/**
|
||||
* 机关查收调课申请。
|
||||
* <p>
|
||||
* 机关查收调课申请,标记查收状态和查收时间。
|
||||
* </p>
|
||||
*
|
||||
* @param ssdksqbh 调课申请编号
|
||||
* @param jgbh 机关编号
|
||||
* @param csrbh 查收人编号
|
||||
*/
|
||||
void receiveByAuthority(String ssdksqbh, String jgbh, String csrbh);
|
||||
|
||||
/**
|
||||
* 撤销调课申请。
|
||||
* <p>
|
||||
* 教员撤销自己提交的、未经过审批的调课申请。
|
||||
* 软删除调课申请,标记删除状态为1。
|
||||
* </p>
|
||||
*
|
||||
* @param ssdksqbh 调课申请编号
|
||||
* @param sqjybh 申请教员编号(用于权限校验)
|
||||
*/
|
||||
void cancelScheduleAdjust(String ssdksqbh, String sqjybh);
|
||||
|
||||
// ==================== 调课策略管理 ====================
|
||||
|
||||
/**
|
||||
* 查询调课策略列表。
|
||||
* <p>
|
||||
* 支持按策略类型筛选,返回所有策略(含停用)。
|
||||
* </p>
|
||||
*
|
||||
* @param cllx 策略类型:TIME_LIMIT/AUTO_APPROVE,为空时查询全部
|
||||
* @return 调课策略列表
|
||||
*/
|
||||
List<ScheduleAdjustStrategyVO> listScheduleAdjustStrategies(String cllx);
|
||||
|
||||
/**
|
||||
* 保存调课策略(新增或修改)。
|
||||
* <p>
|
||||
* 策略编号为空时执行新增,非空时执行修改。
|
||||
* </p>
|
||||
*
|
||||
* @param dto 策略参数
|
||||
* @return 策略编号
|
||||
*/
|
||||
String saveScheduleAdjustStrategy(ScheduleAdjustStrategyDTO dto);
|
||||
|
||||
/**
|
||||
* 删除调课策略。
|
||||
*
|
||||
* @param clbh 策略编号
|
||||
*/
|
||||
void deleteScheduleAdjustStrategy(String clbh);
|
||||
|
||||
// ==================== 教学保障管理 ====================
|
||||
|
||||
/**
|
||||
* 查询教学保障提供资源列表。
|
||||
* <p>
|
||||
* 从保障提供明细表中查询可供选择的保障资源,支持按保障类别编号筛选。
|
||||
* </p>
|
||||
*
|
||||
* @param bzlbbh 保障类别编号,为空时查询全部
|
||||
* @return 保障提供资源列表
|
||||
*/
|
||||
List<TeachingSupportResourceVO> querySupportResourceList(String bzlbbh);
|
||||
|
||||
/**
|
||||
* 查询课次的教学保障计划列表。
|
||||
* <p>
|
||||
* 根据课次编号查询该课次已登记的教学保障计划明细,包括保障名称、单位、
|
||||
* 数量、备注、确认状态及确认信息等。
|
||||
* </p>
|
||||
*
|
||||
* @param sskcbbh 实施_课程表编号(课次编号)
|
||||
* @return 教学保障计划列表
|
||||
*/
|
||||
List<TeachingSupportPlanVO> queryTeachingSupportPlanList(String sskcbbh);
|
||||
|
||||
/**
|
||||
* 登记单条教学保障计划。
|
||||
* <p>
|
||||
* 为指定课次登记一条教学保障需求,指定保障提供明细、数量、备注等信息。
|
||||
* </p>
|
||||
*
|
||||
* @param dto 教学保障计划登记参数
|
||||
* @return 课程表_保障明细编号
|
||||
*/
|
||||
String saveTeachingSupportPlan(TeachingSupportPlanDTO dto);
|
||||
|
||||
/**
|
||||
* 批量登记教学保障计划。
|
||||
* <p>
|
||||
* 一次性为指定课次登记多条教学保障需求。
|
||||
* </p>
|
||||
*
|
||||
* @param dto 教学保障计划批量登记参数
|
||||
*/
|
||||
void batchSaveTeachingSupportPlan(TeachingSupportBatchPlanDTO dto);
|
||||
|
||||
/**
|
||||
* 修改教学保障计划。
|
||||
* <p>
|
||||
* 修改已登记的教学保障计划,包括调整数量和备注信息。
|
||||
* 已确认的教学保障计划不允许修改,如需修改需先取消确认。
|
||||
* </p>
|
||||
*
|
||||
* @param dto 教学保障计划修改参数
|
||||
*/
|
||||
void updateTeachingSupportPlan(TeachingSupportUpdateDTO dto);
|
||||
|
||||
/**
|
||||
* 删除教学保障计划。
|
||||
* <p>
|
||||
* 删除已登记的教学保障计划。
|
||||
* 已确认的教学保障计划不允许删除,如需删除需先取消确认。
|
||||
* </p>
|
||||
*
|
||||
* @param kcbbzmxbh 课程表_保障明细编号
|
||||
*/
|
||||
void deleteTeachingSupportPlan(String kcbbzmxbh);
|
||||
|
||||
/**
|
||||
* 确认教学保障到位。
|
||||
* <p>
|
||||
* 确认某条教学保障计划已经落实到位,记录确认人、确认时间和确认备注。
|
||||
* 已确认的保障计划不允许重复确认。
|
||||
* </p>
|
||||
*
|
||||
* @param dto 教学保障到位确认参数
|
||||
*/
|
||||
void confirmTeachingSupport(TeachingSupportConfirmDTO dto);
|
||||
|
||||
/**
|
||||
* 批量确认教学保障到位。
|
||||
* <p>
|
||||
* 一次性确认多条教学保障计划已经落实到位,逐条处理并返回整体执行结果。
|
||||
* </p>
|
||||
*
|
||||
* @param dtoList 教学保障到位确认参数列表
|
||||
* @return 批量确认结果
|
||||
*/
|
||||
TeachingSupportConfirmResultVO batchConfirmTeachingSupport(List<TeachingSupportConfirmDTO> dtoList);
|
||||
|
||||
/**
|
||||
* 取消教学保障到位确认。
|
||||
* <p>
|
||||
* 取消某条教学保障计划的到位确认,恢复为未确认状态。
|
||||
* </p>
|
||||
*
|
||||
* @param kcbbzmxbh 课程表_保障明细编号
|
||||
*/
|
||||
void cancelConfirmTeachingSupport(String kcbbzmxbh);
|
||||
|
||||
/**
|
||||
* 查询教学保障历史联想列表。
|
||||
* <p>
|
||||
* 根据当前课次编号,查询同一实施课程下其他历史课次已登记过的保障物资,
|
||||
* 按保障提供明细编号聚合去重,统计历史使用次数、最近登记时间和平均数量,
|
||||
* 供教师在登记新保障时快速联想选择,避免重复录入。
|
||||
* </p>
|
||||
*
|
||||
* @param sskcbbh 当前课次编号(实施_课程表编号)
|
||||
* @return 历史联想保障物资列表
|
||||
*/
|
||||
List<TeachingSupportHistoryVO> listTeachingSupportHistory(String sskcbbh);
|
||||
|
||||
// ==================== 学员正课请假 ====================
|
||||
|
||||
/**
|
||||
* 分页查询学员请假申请列表。
|
||||
* <p>
|
||||
* 根据查询条件分页查询学员正课请假申请记录,支持按请假编号、学员编号、
|
||||
* 学员姓名、学员队编号、审批状态、年度、创建时间范围等多条件筛选。
|
||||
* </p>
|
||||
*
|
||||
* @param query 查询参数(包含分页信息和筛选条件)
|
||||
* @return 分页学员请假申请列表
|
||||
*/
|
||||
PageResult<StudentLeaveApplyVO> queryStudentLeaveList(StudentLeaveQueryDTO query);
|
||||
|
||||
/**
|
||||
* 查询学员请假申请详情。
|
||||
* <p>
|
||||
* 根据请假编号查询该申请的完整信息,包括学员信息、请假时间范围、
|
||||
* 审批状态、审批记录及关联课次列表。
|
||||
* </p>
|
||||
*
|
||||
* @param qjbh 请假编号
|
||||
* @return 学员请假申请详情
|
||||
*/
|
||||
StudentLeaveDetailVO getStudentLeaveDetail(String qjbh);
|
||||
|
||||
/**
|
||||
* 学员提交请假申请。
|
||||
* <p>
|
||||
* 学员在线提交正课请假申请,包含请假原因、时间范围、请假类型、
|
||||
* 关联课次等信息。系统自动生成请假编号并记录申请时间。
|
||||
* </p>
|
||||
*
|
||||
* @param dto 学员请假申请参数
|
||||
* @return 请假编号
|
||||
*/
|
||||
String submitStudentLeave(StudentLeaveApplyDTO dto);
|
||||
|
||||
/**
|
||||
* 教师审批学员请假申请。
|
||||
* <p>
|
||||
* 教师审批学员提交的正课请假申请,包含同意、拒绝、发回修改三种处理方式。
|
||||
* 审批通过后联动更新考勤记录。
|
||||
* </p>
|
||||
*
|
||||
* @param dto 教师审批参数
|
||||
*/
|
||||
void auditStudentLeave(StudentLeaveAuditDTO dto);
|
||||
|
||||
/**
|
||||
* 学员撤回请假申请。
|
||||
* <p>
|
||||
* 学员撤回自己提交的、未经过审批的请假申请。
|
||||
* </p>
|
||||
*
|
||||
* @param qjbh 请假编号
|
||||
* @param xybh 学员编号(用于权限校验)
|
||||
*/
|
||||
void cancelStudentLeave(String qjbh, String xybh);
|
||||
|
||||
/**
|
||||
* 学员查询自己的请假申请列表。
|
||||
* <p>
|
||||
* 学员自助查询接口,只能查看自己提交的请假记录,支持分页和按审批状态筛选。
|
||||
* 返回结果中请假类型已翻译为字典标签。
|
||||
* </p>
|
||||
*
|
||||
* @param query 查询参数(学员编号xybh必填,分页信息和审批状态可选)
|
||||
* @return 分页学员请假申请列表
|
||||
*/
|
||||
PageResult<StudentLeaveApplyVO> queryStudentOwnLeaveList(StudentLeaveQueryDTO query);
|
||||
|
||||
// ==================== 运行分析 ====================
|
||||
|
||||
/**
|
||||
* 获取教学运行概览指标。
|
||||
* <p>
|
||||
* 返回教学运行关键指标的汇总数据,包括整体排课完成率、学员缺勤率、
|
||||
* 场地平均使用率、教师周均课时等核心指标。
|
||||
* </p>
|
||||
*
|
||||
* @param query 查询参数(包含年度、学期筛选条件)
|
||||
* @return 运行概览指标
|
||||
*/
|
||||
OperationOverviewVO getOperationOverview(OperationAnalysisQueryDTO query);
|
||||
|
||||
/**
|
||||
* 获取各教学系排课完成率对比数据。
|
||||
* <p>
|
||||
* 返回各教学系的排课完成率,用于柱状图展示。
|
||||
* </p>
|
||||
*
|
||||
* @param query 查询参数(包含年度、学期筛选条件)
|
||||
* @return 各教学系排课完成率列表
|
||||
*/
|
||||
List<CourseCompletionByDeptVO> getCourseCompletionByDept(OperationAnalysisQueryDTO query);
|
||||
|
||||
/**
|
||||
* 获取场地使用率分布数据。
|
||||
* <p>
|
||||
* 返回不同场地类型的使用率分布情况,用于饼图展示。
|
||||
* </p>
|
||||
*
|
||||
* @param query 查询参数(包含年度、学期筛选条件)
|
||||
* @return 场地使用率分布列表
|
||||
*/
|
||||
List<VenueUsageRateVO> getVenueUsageRate(OperationAnalysisQueryDTO query);
|
||||
|
||||
/**
|
||||
* 获取学期调课频次趋势数据。
|
||||
* <p>
|
||||
* 返回学期内各时间段的调课频次变化趋势,用于折线图展示。
|
||||
* </p>
|
||||
*
|
||||
* @param query 查询参数(包含年度、学期筛选条件)
|
||||
* @return 调课频次趋势列表
|
||||
*/
|
||||
List<ScheduleAdjustTrendVO> getScheduleAdjustTrend(OperationAnalysisQueryDTO query);
|
||||
|
||||
/**
|
||||
* 导出运行分析报表为 Excel 文件。
|
||||
* <p>
|
||||
* 汇总运行概览、各教学系排课完成率、场地使用率分布、调课频次趋势四类数据,
|
||||
* 分别写入同一 Excel 文件的多个工作表,便于教学管理决策存档与汇报。
|
||||
* </p>
|
||||
*
|
||||
* @param query 查询参数(包含年度、学期筛选条件)
|
||||
* @return Excel 文件字节数组
|
||||
*/
|
||||
byte[] exportAnalysisToExcel(OperationAnalysisQueryDTO query);
|
||||
}
|
||||
+71
@@ -0,0 +1,71 @@
|
||||
package com.roomroot.jwgl.service;
|
||||
|
||||
import com.roomroot.jwgl.entity.KCBZ;
|
||||
import com.roomroot.jwgl.unit.PageQuery;
|
||||
import com.roomroot.jwgl.unit.PageResult;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 课程教学管理服务接口
|
||||
* <p>
|
||||
* 提供课程标准的增加、删除(填写撤回原因)、更新、查询(含课堂列表)及多版本管理。
|
||||
* </p>
|
||||
*/
|
||||
public interface CourseTeachingService {
|
||||
|
||||
/**
|
||||
* 新增课程标准(含课堂列表)
|
||||
*
|
||||
* @param kcbz 课程标准(ktList 附带课堂列表)
|
||||
*/
|
||||
void add(KCBZ kcbz);
|
||||
|
||||
/**
|
||||
* 撤回(删除)课程标准——填写撤回原因
|
||||
*
|
||||
* @param bh 课程标准编号
|
||||
* @param chyy 撤回原因
|
||||
*/
|
||||
void delete(String bh, String chyy);
|
||||
|
||||
/**
|
||||
* 更新课程标准(先删后插课堂列表)
|
||||
*
|
||||
* @param kcbz 课程标准(ktList 附带课堂列表)
|
||||
*/
|
||||
void update(KCBZ kcbz);
|
||||
|
||||
/**
|
||||
* 查询课程标准详情(含课堂列表)
|
||||
*
|
||||
* @param bh 编号
|
||||
* @return 课程标准(内嵌 ktList)
|
||||
*/
|
||||
KCBZ getById(String bh);
|
||||
|
||||
/**
|
||||
* 分页查询课程标准(含课堂列表)
|
||||
*
|
||||
* @param query 分页参数
|
||||
* @param kcbz 查询条件
|
||||
* @return 分页结果(每项内嵌 ktList)
|
||||
*/
|
||||
PageResult<KCBZ> pageList(PageQuery query, KCBZ kcbz);
|
||||
|
||||
/**
|
||||
* 查询某课程的所有版本
|
||||
*
|
||||
* @param kbh 课编号
|
||||
* @return 版本列表
|
||||
*/
|
||||
List<KCBZ> getVersionsByCourse(String kbh);
|
||||
|
||||
/**
|
||||
* 从课程表自动生成课程标准
|
||||
*
|
||||
* @param kbh 课编号
|
||||
* @return 课程标准编号
|
||||
*/
|
||||
String generateFromCourse(String kbh);
|
||||
}
|
||||
+82
@@ -0,0 +1,82 @@
|
||||
package com.roomroot.jwgl.service;
|
||||
|
||||
import com.roomroot.jwgl.dto.department.DepartmentCreateDTO;
|
||||
import com.roomroot.jwgl.dto.department.DepartmentIdDTO;
|
||||
import com.roomroot.jwgl.dto.department.DepartmentQueryDTO;
|
||||
import com.roomroot.jwgl.dto.department.DepartmentUpdateDTO;
|
||||
import com.roomroot.jwgl.vo.department.DepartmentTreeVO;
|
||||
import com.roomroot.jwgl.vo.department.DepartmentVO;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 部别管理服务。
|
||||
*/
|
||||
public interface DepartmentManagementService {
|
||||
|
||||
/**
|
||||
* 新增部别。
|
||||
*
|
||||
* @param dto 新增参数
|
||||
* @return 新增后的部别信息
|
||||
*/
|
||||
DepartmentVO add(DepartmentCreateDTO dto);
|
||||
|
||||
/**
|
||||
* 修改部别。
|
||||
*
|
||||
* @param dto 修改参数
|
||||
* @return 修改后的部别信息
|
||||
*/
|
||||
DepartmentVO update(DepartmentUpdateDTO dto);
|
||||
|
||||
/**
|
||||
* 查询单个部别。
|
||||
*
|
||||
* @param dto 部别编号参数
|
||||
* @return 部别详情
|
||||
*/
|
||||
DepartmentVO get(DepartmentIdDTO dto);
|
||||
|
||||
/**
|
||||
* 查询部别平铺列表。
|
||||
*
|
||||
* @param dto 查询条件
|
||||
* @return 部别列表
|
||||
*/
|
||||
List<DepartmentVO> list(DepartmentQueryDTO dto);
|
||||
|
||||
/**
|
||||
* 查询部别树。
|
||||
*
|
||||
* @param dto 查询条件
|
||||
* @return 部别树
|
||||
*/
|
||||
List<DepartmentTreeVO> tree(DepartmentQueryDTO dto);
|
||||
|
||||
/**
|
||||
* 停用部别。
|
||||
*
|
||||
* @param dto 部别编号参数
|
||||
* @return 停用后的部别信息
|
||||
*/
|
||||
DepartmentVO disable(DepartmentIdDTO dto);
|
||||
|
||||
/**
|
||||
* 启用部别。
|
||||
*
|
||||
* @param dto 部别编号参数
|
||||
* @return 启用后的部别信息
|
||||
*/
|
||||
DepartmentVO enable(DepartmentIdDTO dto);
|
||||
|
||||
/**
|
||||
* 删除部别(逻辑删除)。
|
||||
* <p>删除前必须确认不存在启用中的下级部别,
|
||||
* 并且不存在教研室、学员队、机关参谋或教学管理机构引用。</p>
|
||||
*
|
||||
* @param dto 部别编号参数
|
||||
* @return 被删除的部别信息
|
||||
*/
|
||||
DepartmentVO delete(DepartmentIdDTO dto);
|
||||
}
|
||||
+107
@@ -0,0 +1,107 @@
|
||||
package com.roomroot.jwgl.service;
|
||||
|
||||
import com.roomroot.jwgl.dto.departmentpersonnel.DepartmentPersonnelCreateDTO;
|
||||
import com.roomroot.jwgl.dto.departmentpersonnel.DepartmentPersonnelIdDTO;
|
||||
import com.roomroot.jwgl.dto.departmentpersonnel.DepartmentPersonnelImportDTO;
|
||||
import com.roomroot.jwgl.dto.departmentpersonnel.DepartmentPersonnelQueryDTO;
|
||||
import com.roomroot.jwgl.dto.departmentpersonnel.DepartmentPersonnelUpdateDTO;
|
||||
import com.roomroot.jwgl.vo.departmentpersonnel.DepartmentPersonnelDepartmentVO;
|
||||
import com.roomroot.jwgl.vo.departmentpersonnel.DepartmentPersonnelVO;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 部别人员管理服务。
|
||||
*/
|
||||
public interface DepartmentPersonnelService {
|
||||
|
||||
/**
|
||||
* 查询人员管理页面可选择的启用部别。
|
||||
*
|
||||
* @param dto 部别查询条件
|
||||
* @return 启用部别列表
|
||||
*/
|
||||
List<DepartmentPersonnelDepartmentVO> listDepartments(
|
||||
DepartmentPersonnelQueryDTO dto);
|
||||
|
||||
/**
|
||||
* 查询部别人员列表。
|
||||
*
|
||||
* @param dto 人员查询条件
|
||||
* @return 人员列表
|
||||
*/
|
||||
List<DepartmentPersonnelVO> list(DepartmentPersonnelQueryDTO dto);
|
||||
|
||||
/**
|
||||
* 查询部别人员详情。
|
||||
*
|
||||
* @param dto 人员编号参数
|
||||
* @return 人员详情
|
||||
*/
|
||||
DepartmentPersonnelVO get(DepartmentPersonnelIdDTO dto);
|
||||
|
||||
/**
|
||||
* 新增部别人员。
|
||||
*
|
||||
* @param dto 人员新增参数
|
||||
* @return 新增后的人员信息
|
||||
*/
|
||||
DepartmentPersonnelVO add(DepartmentPersonnelCreateDTO dto);
|
||||
|
||||
/**
|
||||
* 修改部别人员。
|
||||
*
|
||||
* @param dto 人员修改参数
|
||||
* @return 修改后的人员信息
|
||||
*/
|
||||
DepartmentPersonnelVO update(DepartmentPersonnelUpdateDTO dto);
|
||||
|
||||
/**
|
||||
* 将人员标记为离职。
|
||||
*
|
||||
* @param dto 人员编号参数
|
||||
* @return 离职后的人员信息
|
||||
*/
|
||||
DepartmentPersonnelVO leave(DepartmentPersonnelIdDTO dto);
|
||||
|
||||
/**
|
||||
* 将人员恢复为在职。
|
||||
*
|
||||
* @param dto 人员编号参数
|
||||
* @return 复职后的人员信息
|
||||
*/
|
||||
DepartmentPersonnelVO restore(DepartmentPersonnelIdDTO dto);
|
||||
|
||||
/**
|
||||
* 批量导入部别人员。
|
||||
*
|
||||
* @param dto 批量导入参数
|
||||
* @return 成功导入的人员列表
|
||||
*/
|
||||
List<DepartmentPersonnelVO> batchImport(DepartmentPersonnelImportDTO dto);
|
||||
|
||||
/**
|
||||
* 通过Excel文件导入部别人员。
|
||||
*
|
||||
* @param inputStream Excel文件输入流
|
||||
* @param fileName 文件名
|
||||
* @return 成功导入的人员列表
|
||||
*/
|
||||
List<DepartmentPersonnelVO> importFromExcel(java.io.InputStream inputStream, String fileName);
|
||||
|
||||
/**
|
||||
* 按查询条件导出人员数据。
|
||||
*
|
||||
* @param dto 导出筛选条件
|
||||
* @return 排序后的人员数据
|
||||
*/
|
||||
List<DepartmentPersonnelVO> export(DepartmentPersonnelQueryDTO dto);
|
||||
|
||||
/**
|
||||
* 按查询条件导出人员数据为 Excel 文件。
|
||||
*
|
||||
* @param dto 导出筛选条件
|
||||
* @return Excel 文件字节数组
|
||||
*/
|
||||
byte[] exportToExcel(DepartmentPersonnelQueryDTO dto);
|
||||
}
|
||||
@@ -0,0 +1,106 @@
|
||||
package com.roomroot.jwgl.service;
|
||||
|
||||
import com.roomroot.jwgl.dto.dict.DictDataBatchQueryDTO;
|
||||
import com.roomroot.jwgl.dto.dict.DictDataQueryDTO;
|
||||
import com.roomroot.jwgl.dto.dict.DictDataSaveDTO;
|
||||
import com.roomroot.jwgl.unit.PageResult;
|
||||
import com.roomroot.jwgl.vo.dict.DictDataVO;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 字典数据服务。
|
||||
* <p>
|
||||
* 负责字典数据的查询(单类型、分页、批量)、保存和删除业务逻辑。
|
||||
* 字典数据是字典类型下的具体选项,包含标签(显示文本)、值(存储值)、
|
||||
* 排序、状态、是否默认等属性,为前端下拉框、单选、多选等组件提供数据源。
|
||||
* </p>
|
||||
*/
|
||||
public interface DictDataService {
|
||||
|
||||
/**
|
||||
* 按类型编码查询全部启用的字典数据(不分页,用于前端下拉框)。
|
||||
* <p>
|
||||
* 返回指定字典类型下状态为启用的所有数据项,按排序号升序排列。
|
||||
* 仅返回启用状态的数据,保证前端下拉框中不展示已停用的选项。
|
||||
* </p>
|
||||
*
|
||||
* @param dictTypeCode 字典类型编码
|
||||
* @return 字典数据列表
|
||||
*/
|
||||
List<DictDataVO> listByType(String dictTypeCode);
|
||||
|
||||
/**
|
||||
* 分页查询字典数据列表(管理页面用)。
|
||||
* <p>
|
||||
* 根据查询条件进行分页筛选,支持按字典类型编码、关键字(匹配标签或值)、
|
||||
* 状态进行过滤,结果按排序号升序排列。
|
||||
* 与 {@link #listByType} 不同,此接口可查看启用和停用的全部数据项。
|
||||
* </p>
|
||||
*
|
||||
* @param dto 查询条件,包含分页参数和筛选条件
|
||||
* @return 字典数据分页结果
|
||||
*/
|
||||
PageResult<DictDataVO> page(DictDataQueryDTO dto);
|
||||
|
||||
/**
|
||||
* 批量查询多个类型的字典数据。
|
||||
* <p>
|
||||
* 根据传入的多个字典类型编码,一次性查询所有类型的启用数据,
|
||||
* 返回结果按类型编码分组,便于前端页面初始化时批量获取多个下拉框数据。
|
||||
* </p>
|
||||
*
|
||||
* @param dto 批量查询参数,包含字典类型编码列表
|
||||
* @return 按类型编码分组的数据
|
||||
*/
|
||||
Map<String, List<DictDataVO>> batchList(DictDataBatchQueryDTO dto);
|
||||
|
||||
/**
|
||||
* 保存字典数据(新增或编辑)。
|
||||
* <p>
|
||||
* 当 {@code dto.dictDataId} 为空时执行新增操作,
|
||||
* 当 {@code dto.dictDataId} 有值时执行编辑操作。
|
||||
* 保存时会校验关联的字典类型是否存在;
|
||||
* 若 {@code isDefault} 设置为 1,会自动取消该类型下其他数据的默认标记,
|
||||
* 保证同一类型下只有一个默认选项。
|
||||
* </p>
|
||||
*
|
||||
* @param dto 保存参数
|
||||
* @return 保存后的字典数据
|
||||
*/
|
||||
DictDataVO save(DictDataSaveDTO dto);
|
||||
|
||||
/**
|
||||
* 删除字典数据。
|
||||
* <p>
|
||||
* 根据字典数据ID删除单条记录,删除前校验数据是否存在。
|
||||
* </p>
|
||||
*
|
||||
* @param dictDataId 字典数据ID
|
||||
*/
|
||||
void delete(Long dictDataId);
|
||||
|
||||
/**
|
||||
* 获取字典数据的历史版本列表。
|
||||
* <p>
|
||||
* 返回该字典数据所有的历史快照信息,用于版本回溯查看。
|
||||
* </p>
|
||||
*
|
||||
* @param dictDataId 字典数据ID
|
||||
* @return 历史版本快照列表
|
||||
*/
|
||||
List<Map<String, Object>> getHistory(Long dictDataId);
|
||||
|
||||
/**
|
||||
* 回滚字典数据到指定版本。
|
||||
* <p>
|
||||
* 根据目标版本号,从历史快照中恢复数据,并创建新的版本记录。
|
||||
* </p>
|
||||
*
|
||||
* @param dictDataId 字典数据ID
|
||||
* @param targetVersion 目标版本号
|
||||
* @return 回滚后的字典数据详情
|
||||
*/
|
||||
DictDataVO rollback(Long dictDataId, Integer targetVersion);
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
package com.roomroot.jwgl.service;
|
||||
|
||||
import com.roomroot.jwgl.dto.dict.DictTypeQueryDTO;
|
||||
import com.roomroot.jwgl.dto.dict.DictTypeSaveDTO;
|
||||
import com.roomroot.jwgl.unit.PageResult;
|
||||
import com.roomroot.jwgl.vo.dict.DictTypeVO;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 字典类型服务。
|
||||
* <p>
|
||||
* 负责字典类型的查询、保存和删除业务逻辑。
|
||||
* 字典类型是对系统字典的分类,如课程类型、职称等级、教室用途等,
|
||||
* 每个类型下可维护多条具体的字典数据项。
|
||||
* </p>
|
||||
*/
|
||||
public interface DictTypeService {
|
||||
|
||||
/**
|
||||
* 分页查询字典类型列表。
|
||||
* <p>
|
||||
* 根据查询条件进行分页筛选,支持按关键字(匹配类型编码或名称)、
|
||||
* 所属分组、状态进行过滤,结果按创建时间降序排列。
|
||||
* </p>
|
||||
*
|
||||
* @param dto 查询条件,包含分页参数和筛选条件
|
||||
* @return 字典类型分页结果
|
||||
*/
|
||||
PageResult<DictTypeVO> page(DictTypeQueryDTO dto);
|
||||
|
||||
/**
|
||||
* 保存字典类型(新增或编辑)。
|
||||
* <p>
|
||||
* 当 {@code dto.dictTypeId} 为空时执行新增操作,
|
||||
* 当 {@code dto.dictTypeId} 有值时执行编辑操作。
|
||||
* 新增时校验字典类型编码全局唯一性;
|
||||
* 编辑时若修改了编码,同样需要校验新编码的唯一性。
|
||||
* </p>
|
||||
*
|
||||
* @param dto 保存参数
|
||||
* @return 保存后的字典类型
|
||||
*/
|
||||
DictTypeVO save(DictTypeSaveDTO dto);
|
||||
|
||||
/**
|
||||
* 删除字典类型。
|
||||
* <p>
|
||||
* 删除前校验字典类型是否存在,并检查该类型下是否有关联的字典数据项。
|
||||
* 若存在关联数据项,则抛出业务异常,禁止删除,防止影响已引用该字典的业务数据。
|
||||
* </p>
|
||||
*
|
||||
* @param dictTypeId 字典类型ID
|
||||
*/
|
||||
void delete(Long dictTypeId);
|
||||
|
||||
/**
|
||||
* 获取字典类型的历史版本列表。
|
||||
* <p>
|
||||
* 返回该字典类型所有的历史快照信息,用于版本回溯查看。
|
||||
* </p>
|
||||
*
|
||||
* @param dictTypeId 字典类型ID
|
||||
* @return 历史版本快照列表
|
||||
*/
|
||||
List<Map<String, Object>> getHistory(Long dictTypeId);
|
||||
|
||||
/**
|
||||
* 回滚字典类型到指定版本。
|
||||
* <p>
|
||||
* 根据目标版本号,从历史快照中恢复数据,并创建新的版本记录。
|
||||
* </p>
|
||||
*
|
||||
* @param dictTypeId 字典类型ID
|
||||
* @param targetVersion 目标版本号
|
||||
* @return 回滚后的字典类型详情
|
||||
*/
|
||||
DictTypeVO rollback(Long dictTypeId, Integer targetVersion);
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
package com.roomroot.jwgl.service;
|
||||
|
||||
import com.roomroot.jwgl.entity.XKZYXX;
|
||||
import com.roomroot.jwgl.unit.PageQuery;
|
||||
import com.roomroot.jwgl.unit.PageResult;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
* 学科专业管理服务接口
|
||||
* <p>
|
||||
* 提供学科、专业的增加、删除(逻辑删除)、更新、分页查询等功能。
|
||||
* 对应数据表:学科专业信息
|
||||
* </p>
|
||||
*/
|
||||
@Service
|
||||
public interface DisciplineService {
|
||||
|
||||
/**
|
||||
* 新增学科专业
|
||||
*
|
||||
* @param entity 学科专业实体
|
||||
*/
|
||||
void add(XKZYXX entity);
|
||||
|
||||
/**
|
||||
* 逻辑删除(停用)学科专业
|
||||
*
|
||||
* @param bSH 标识号
|
||||
*/
|
||||
void disable(String bSH);
|
||||
|
||||
/**
|
||||
* 更新学科专业
|
||||
*
|
||||
* @param entity 学科专业实体
|
||||
*/
|
||||
void update(XKZYXX entity);
|
||||
|
||||
/**
|
||||
* 根据标识号查询学科专业详情
|
||||
*
|
||||
* @param bSH 标识号
|
||||
* @return 学科专业实体
|
||||
*/
|
||||
XKZYXX getById(String bSH);
|
||||
|
||||
/**
|
||||
* 分页条件查询学科专业列表
|
||||
*
|
||||
* @param query 分页参数
|
||||
* @return 分页结果
|
||||
*/
|
||||
PageResult<XKZYXX> pageList(PageQuery query, XKZYXX xkzyxx);
|
||||
}
|
||||
@@ -0,0 +1,131 @@
|
||||
package com.roomroot.jwgl.service;
|
||||
|
||||
import com.roomroot.jwgl.dto.elective.AddClassDTO;
|
||||
import com.roomroot.jwgl.entity.*;
|
||||
import com.roomroot.jwgl.unit.PageQuery;
|
||||
import com.roomroot.jwgl.unit.PageResult;
|
||||
import com.roomroot.jwgl.vo.elective.*;
|
||||
import com.roomroot.jwgl.vo.elective.*;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 教学班次管理服务接口
|
||||
*/
|
||||
public interface ElectiveService {
|
||||
|
||||
// ========== 教学班次(学员队表) ==========
|
||||
|
||||
/** 新增教学班次(同时写入学员队表和学员队期表) */
|
||||
void add(AddClassDTO dto);
|
||||
|
||||
void disable(String xydbh);
|
||||
|
||||
void update(XYDB entity);
|
||||
|
||||
XYDB getById(String xydbh);
|
||||
|
||||
PageResult<XYDB> pageList(PageQuery query, XYDB cond);
|
||||
|
||||
/** 双表联查分页列表(含学号规则、注册开关) */
|
||||
PageResult<ElectiveClassVO> pageListWithPeriod(PageQuery query, ElectiveClassVO cond);
|
||||
|
||||
/**
|
||||
* 根据时间范围过滤学员队表
|
||||
* <p>
|
||||
* 查找入学日期和毕业日期包含指定时间范围的学员队
|
||||
* 即:入学日期 <= startTime 且 毕业日期 >= endTime
|
||||
* </p>
|
||||
*
|
||||
* @param startTime 时间范围开始
|
||||
* @param endTime 时间范围结束
|
||||
* @return 符合条件的学员队列表
|
||||
*/
|
||||
List<XYDB> filterByDateRange(LocalDateTime startTime, LocalDateTime endTime);
|
||||
|
||||
// ========== 学员队期(学号规则+注册设置) ==========
|
||||
|
||||
XYDQB getPeriodByXydbh(String xydbh);
|
||||
|
||||
void updatePeriod(XYDQB entity);
|
||||
|
||||
/** 设置是否允许学员自行注册 */
|
||||
void setRegistrationEnabled(String xydbh, Integer enabled);
|
||||
|
||||
/** 生成下一个学员学号(格式:入学年份年月日 + 三位流水号) */
|
||||
String generateNextStudentNumber(String xydbh);
|
||||
|
||||
// ========== 关联信息查询 ==========
|
||||
|
||||
/** 查询班次的课程列表(通过实施_课程学员队关联) */
|
||||
List<ClassScheduleVO> getClassCourses(String xydbh, Integer nd);
|
||||
|
||||
/** 查询班次的学期课程表 */
|
||||
List<ClassScheduleVO> getClassSchedule(String xydbh, Integer nd);
|
||||
|
||||
/** 查询班次的学员列表 */
|
||||
List<XYXX> getClassStudents(String xydbh);
|
||||
|
||||
/** 查询班次的学员成绩 */
|
||||
List<StudentGradeVO> getClassGrades(String xydbh, String kmbh);
|
||||
|
||||
/** 查询班次的学员缺勤记录 */
|
||||
List<StudentAbsenceVO> getClassAbsences(String xydbh, Integer nd);
|
||||
|
||||
// ========== 教学班次学期信息设置 ==========
|
||||
|
||||
/**
|
||||
* 查询教学楼列表(教学班次学期信息设置窗口 - 教学楼下拉框)
|
||||
*
|
||||
* @return 教学楼列表
|
||||
*/
|
||||
List<JXLB> listBuildings();
|
||||
|
||||
/**
|
||||
* 查询教室列表(教学班次学期信息设置窗口 - 专用教室选择)
|
||||
* <p>支持按教学楼代号过滤,以及按教室名称拼音首字母快速查找。</p>
|
||||
*
|
||||
* @param jxldh 教学楼代号(可选)
|
||||
* @param py 教室名称拼音首字母(可选,模糊匹配)
|
||||
* @return 教室列表
|
||||
*/
|
||||
List<JSB> listRooms(String jxldh, String py);
|
||||
|
||||
/**
|
||||
* 获取教学班次学期信息设置窗口的初始化默认值
|
||||
* <p>
|
||||
* 根据班次学制(入学/毕业日期)计算:
|
||||
* <ul>
|
||||
* <li>学制半年以内:学期第次固定为第一学期,开学日期=入学日期,结束日期=毕业日期</li>
|
||||
* <li>学制半年以上:按入学日期智能推断当前学期第次(可手动修改),
|
||||
* 开学/结束日期默认取窗口预设日期(presetKxrq/presetJsrq)</li>
|
||||
* <li>第二以上学期:默认预设上学期的专用教室</li>
|
||||
* </ul>
|
||||
* </p>
|
||||
*
|
||||
* @param xydbh 班次编号(学员队编号)
|
||||
* @param presetKxrq 窗口预设开学日期(yyyy-MM-dd,半年以上班次使用,可选)
|
||||
* @param presetJsrq 窗口预设结束日期(yyyy-MM-dd,半年以上班次使用,可选)
|
||||
* @return 初始化默认值
|
||||
*/
|
||||
SemesterInitVO getSemesterInit(String xydbh, String presetKxrq, String presetJsrq);
|
||||
|
||||
/**
|
||||
* 创建班次学期信息(教学班次学期信息设置窗口 - 确定按钮)
|
||||
* <p>
|
||||
* 自动处理默认逻辑:
|
||||
* <ul>
|
||||
* <li>学制半年以内:学期第次强制为第一学期(传入其他值将校验失败),
|
||||
* 开学/结束日期为空时默认取班次的入学/毕业日期</li>
|
||||
* <li>学制半年以上:学期第次为空时按入学日期智能推断;
|
||||
* 开学/结束日期需由窗口预设值传入,不允许为空</li>
|
||||
* <li>第二以上学期:专用教室为空时,默认预设上学期的专用教室</li>
|
||||
* <li>同一班次+年度+学期第次已存在时拒绝重复创建</li>
|
||||
* </ul>
|
||||
* </p>
|
||||
*
|
||||
* @param xydndxqjbxxb 班次学期信息(编号/变动时间/删除标记等由服务端自动填充)
|
||||
*/
|
||||
void addSemester(XYDNDXQJBXXB xydndxqjbxxb);
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
package com.roomroot.jwgl.service;
|
||||
|
||||
import com.roomroot.jwgl.dto.faculty.AddTeacherDTO;
|
||||
import com.roomroot.jwgl.entity.*;
|
||||
import com.roomroot.jwgl.unit.PageQuery;
|
||||
import com.roomroot.jwgl.unit.PageResult;
|
||||
import com.roomroot.jwgl.vo.faculty.TeacherListVO;
|
||||
|
||||
/**
|
||||
* 教研室与教员管理服务接口
|
||||
* <p>
|
||||
* 提供教研室、教员的增加、删除、更新、查询等功能管理,
|
||||
* 以及教员属性、年度综合评定、课程表等关联信息的查询。
|
||||
* </p>
|
||||
*/
|
||||
public interface FacultyService {
|
||||
|
||||
// ==================== 教研室管理 ====================
|
||||
|
||||
/**
|
||||
* 新增教研室
|
||||
*/
|
||||
void addJYSB(JYSB entity);
|
||||
|
||||
/**
|
||||
* 停用(逻辑删除)教研室
|
||||
*/
|
||||
void disableJYSB(String jYSDH);
|
||||
|
||||
/**
|
||||
* 更新教研室
|
||||
*/
|
||||
void updateJYSB(JYSB entity);
|
||||
|
||||
/**
|
||||
* 根据代号查询教研室详情
|
||||
*/
|
||||
JYSB getJYSBById(String jYSDH);
|
||||
|
||||
/**
|
||||
* 分页条件查询教研室列表
|
||||
*/
|
||||
PageResult<JYSB> pageJYSB(PageQuery query, JYSB cond);
|
||||
|
||||
// ==================== 教员管理 ====================
|
||||
|
||||
/**
|
||||
* 新增教员(同时创建教员属性记录)
|
||||
* <p>接收前端传回的教员基本信息和属性信息,一次性写入两张表。</p>
|
||||
*/
|
||||
void addJYB(AddTeacherDTO dto);
|
||||
|
||||
/**
|
||||
* 离职(逻辑删除)教员
|
||||
*/
|
||||
void disableJYB(String jYBH);
|
||||
|
||||
/**
|
||||
* 更新教员基本信息
|
||||
*/
|
||||
void updateJYB(JYB entity);
|
||||
|
||||
/**
|
||||
* 根据编号查询教员详情(含属性信息)
|
||||
*/
|
||||
JYB getJYBById(String jYBH);
|
||||
|
||||
/**
|
||||
* 分页条件查询教员列表
|
||||
*/
|
||||
/** 分页条件查询教员列表(三表联查) */
|
||||
PageResult<TeacherListVO> pageJYBDetail(PageQuery query, JYB cond);
|
||||
|
||||
// ==================== 教员属性管理 ====================
|
||||
|
||||
/**
|
||||
* 根据教员编号查询教员属性
|
||||
*/
|
||||
JYSX getJYSXByJYBH(String jYBH);
|
||||
|
||||
/**
|
||||
* 更新教员属性
|
||||
*/
|
||||
void updateJYSX(JYSX entity);
|
||||
|
||||
// ==================== 年度综合评定查询 ====================
|
||||
|
||||
/**
|
||||
* 分页查询年度综合评定_教员
|
||||
*/
|
||||
PageResult<NDZHPDJY> pageNDZHPDJY(PageQuery query, NDZHPDJY cond);
|
||||
|
||||
// ==================== 教员课程表查询 ====================
|
||||
|
||||
/**
|
||||
* 分页查询教员输出课程表
|
||||
*/
|
||||
PageResult<JYSCKCB> pageJYSCKCB(PageQuery query, JYSCKCB cond);
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
package com.roomroot.jwgl.service;
|
||||
|
||||
import com.roomroot.jwgl.entity.KCB;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 课程表服务接口
|
||||
*/
|
||||
public interface KCBService {
|
||||
|
||||
/**
|
||||
* 新增
|
||||
*
|
||||
* @param kcb 实体
|
||||
*/
|
||||
void add(KCB kcb);
|
||||
|
||||
/**
|
||||
* 删除
|
||||
*
|
||||
* @param kbh 课编号
|
||||
*/
|
||||
void delete(String kbh);
|
||||
|
||||
/**
|
||||
* 批量删除
|
||||
*
|
||||
* @param kbhList 课编号列表
|
||||
*/
|
||||
void batchDelete(List<String> kbhList);
|
||||
|
||||
/**
|
||||
* 更新
|
||||
*
|
||||
* @param kcb 实体
|
||||
*/
|
||||
void update(KCB kcb);
|
||||
|
||||
/**
|
||||
* 根据课编号查询
|
||||
*
|
||||
* @param kbh 课编号
|
||||
* @return 实体
|
||||
*/
|
||||
KCB getByKbh(String kbh);
|
||||
|
||||
/**
|
||||
* 查询所有数据
|
||||
*
|
||||
* @return 所有数据列表
|
||||
*/
|
||||
List<KCB> list();
|
||||
}
|
||||
@@ -0,0 +1,116 @@
|
||||
package com.roomroot.jwgl.service;
|
||||
|
||||
import com.roomroot.jwgl.dto.LeaveDTO;
|
||||
import com.roomroot.jwgl.dto.LeaveQueryDTO;
|
||||
import com.roomroot.jwgl.entity.XYJXQJB;
|
||||
import com.roomroot.jwgl.entity.XYQJSPB;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 请假服务接口
|
||||
*/
|
||||
public interface LeaveService {
|
||||
|
||||
/**
|
||||
* 新增请假(主表+课堂+学员)
|
||||
*
|
||||
* @param dto 请假DTO
|
||||
*/
|
||||
void add(LeaveDTO dto);
|
||||
|
||||
/**
|
||||
* 更新请假主表
|
||||
*
|
||||
* @param xyjxqjb 实体
|
||||
* @return 是否成功
|
||||
*/
|
||||
boolean update(XYJXQJB xyjxqjb);
|
||||
|
||||
/**
|
||||
* 删除请假(主表+课堂+学员+审批)
|
||||
*
|
||||
* @param bh 编号
|
||||
* @return 是否成功
|
||||
*/
|
||||
boolean delete(String bh);
|
||||
|
||||
/**
|
||||
* 根据编号查询请假主表
|
||||
*
|
||||
* @param bh 编号
|
||||
* @return 实体
|
||||
*/
|
||||
XYJXQJB getByBh(String bh);
|
||||
|
||||
/**
|
||||
* 查询所有请假主表数据
|
||||
*
|
||||
* @return 列表
|
||||
*/
|
||||
List<XYJXQJB> list();
|
||||
|
||||
/**
|
||||
* 根据条件查询请假主表数据
|
||||
* 支持起始时间、结束时间、创建时间范围查询
|
||||
*
|
||||
* @param queryDTO 查询条件
|
||||
* @return 列表
|
||||
*/
|
||||
List<XYJXQJB> list(LeaveQueryDTO queryDTO);
|
||||
|
||||
/**
|
||||
* 根据请假编号查询请假课堂列表
|
||||
*
|
||||
* @param qjbh 请假编号
|
||||
* @return 课堂编号列表
|
||||
*/
|
||||
List<String> listClassroomBhsByQjbh(String qjbh);
|
||||
|
||||
/**
|
||||
* 根据请假编号查询请假学员列表
|
||||
*
|
||||
* @param qjbh 请假编号
|
||||
* @return 学员编号列表
|
||||
*/
|
||||
List<String> listStudentBhsByQjbh(String qjbh);
|
||||
|
||||
// ===== 审批表 CRUD =====
|
||||
|
||||
/**
|
||||
* 新增审批
|
||||
*
|
||||
* @param xyqjspb 审批实体
|
||||
*/
|
||||
void addApproval(XYQJSPB xyqjspb);
|
||||
|
||||
/**
|
||||
* 删除审批
|
||||
*
|
||||
* @param bh 编号
|
||||
*/
|
||||
void deleteApproval(String bh);
|
||||
|
||||
/**
|
||||
* 更新审批
|
||||
*
|
||||
* @param xyqjspb 审批实体
|
||||
*/
|
||||
void updateApproval(XYQJSPB xyqjspb);
|
||||
|
||||
/**
|
||||
* 根据编号查询审批
|
||||
*
|
||||
* @param bh 编号
|
||||
* @return 审批实体
|
||||
*/
|
||||
XYQJSPB getApprovalByBh(String bh);
|
||||
|
||||
/**
|
||||
* 根据请假编号查询审批列表
|
||||
*
|
||||
* @param qjbh 请假编号
|
||||
* @return 审批列表
|
||||
*/
|
||||
List<XYQJSPB> listApprovalsByQjbh(String qjbh);
|
||||
}
|
||||
@@ -0,0 +1,172 @@
|
||||
package com.roomroot.jwgl.service;
|
||||
|
||||
import com.roomroot.jwgl.entity.*;
|
||||
import com.roomroot.jwgl.unit.PageQuery;
|
||||
import com.roomroot.jwgl.unit.PageResult;
|
||||
import com.roomroot.jwgl.vo.log.TeacherHoursVO;
|
||||
import com.roomroot.jwgl.vo.log.TeachingLogListVO;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
* 教学日志管理服务接口
|
||||
* <p>
|
||||
* 涵盖教学日志核心管理、课时核算标准、课时补助标准、联教联训、教师工作量等全功能。
|
||||
* </p>
|
||||
*/
|
||||
@Service
|
||||
public interface LogService {
|
||||
|
||||
// ==================== 教学日志核心 ====================
|
||||
|
||||
/** 新增教学日志 */
|
||||
void addTeachingLog(BCKTJXRZ entity);
|
||||
/** 更新教学日志 */
|
||||
void updateTeachingLog(BCKTJXRZ entity);
|
||||
/** 根据编号查询 */
|
||||
BCKTJXRZ getTeachingLogById(String bh);
|
||||
/** 分页条件查询(基于班次课堂教学日志) */
|
||||
PageResult<BCKTJXRZ> pageTeachingLog(PageQuery query, BCKTJXRZ cond);
|
||||
/** 分页条件查询教学日志列表(基于实施_课程表_日志联查,展示字段更丰富) */
|
||||
PageResult<TeachingLogListVO> pageTeachingLogDetail(PageQuery query, TeachingLogListVO cond);
|
||||
|
||||
// ==================== 教学日志(基于实施_课程表_日志 36字段表) ====================
|
||||
|
||||
/** 新增教学日志 */
|
||||
void addLog(SSKCB_RZ entity);
|
||||
/** 退回教学日志(填写退回意见) */
|
||||
void rejectLog(String bh, String thyj);
|
||||
/** 根据课表自动创建教学日志 */
|
||||
SSKCB_RZ autoCreateLog(String tybh);
|
||||
/** 导入教学日志 */
|
||||
void importLog(java.util.List<SSKCB_RZ> list);
|
||||
/** 批量上报教学日志(根据主键编号组将状态修改为已上报,仅对待上报数据生效,返回实际更新条数) */
|
||||
int batchReportLogs(java.util.List<String> bhList);
|
||||
/** 批量审核教学日志(根据主键编号组将状态修改为已审核,仅对已上报数据生效,返回实际更新条数) */
|
||||
int batchAuditLogs(java.util.List<String> bhList);
|
||||
/** 从 Excel 导入教学日志 */
|
||||
void importLogFromExcel(org.springframework.web.multipart.MultipartFile file);
|
||||
/** 导出教学日志 Excel */
|
||||
void exportLogExcel(TeachingLogListVO cond, jakarta.servlet.http.HttpServletResponse response);
|
||||
/** 提交审核(状态流转) */
|
||||
void submitApproval(String bh, String targetStatus);
|
||||
/** 审核通过 */
|
||||
void approve(String bh, String feedback);
|
||||
/** 审核退回 */
|
||||
void reject(String bh, String feedback);
|
||||
/** 自动创建教学日志(基于课表信息) */
|
||||
BCKTJXRZ autoCreateFromSchedule(String sskcbh);
|
||||
/** 对照课表查看教学日志填报状态 */
|
||||
PageResult<?> checkLogStatusBySchedule(PageQuery query, String jybh, Integer nd);
|
||||
|
||||
// ==================== 教学日志授课教员 ====================
|
||||
|
||||
void addLogTeacher(BCKTJXRZSKJY entity);
|
||||
PageResult<BCKTJXRZSKJY> pageLogTeacher(PageQuery query, BCKTJXRZSKJY cond);
|
||||
|
||||
// ==================== 教学日志学员学习情况 ====================
|
||||
|
||||
void addStudentLearningStatus(JXRZXYXXQK entity);
|
||||
PageResult<JXRZXYXXQK> pageStudentLearningStatus(PageQuery query, String jxrzbh);
|
||||
|
||||
// ==================== 课时核算标准 ====================
|
||||
|
||||
void addCalculationStandard(KSHBZ entity);
|
||||
void updateCalculationStandard(KSHBZ entity);
|
||||
KSHBZ getCalculationStandardById(String bh);
|
||||
PageResult<KSHBZ> pageCalculationStandard(PageQuery query, KSHBZ cond);
|
||||
|
||||
// ==================== 课时系数方案 ====================
|
||||
|
||||
/** 新增课时系数方案 */
|
||||
void addCoefficientPlan(KSXSFA entity);
|
||||
/** 更新课时系数方案(需含编号) */
|
||||
void updateCoefficientPlan(KSXSFA entity);
|
||||
/** 根据编号查询课时系数方案 */
|
||||
KSXSFA getCoefficientPlanById(String bh);
|
||||
/** 分页条件查询课时系数方案列表(名称模糊匹配) */
|
||||
PageResult<KSXSFA> pageCoefficientPlan(PageQuery query, KSXSFA cond);
|
||||
|
||||
// ==================== 课时费标准 ====================
|
||||
|
||||
void addFeeStandard(KSFBZ entity);
|
||||
void updateFeeStandard(KSFBZ entity);
|
||||
KSFBZ getFeeStandardById(String bh);
|
||||
PageResult<KSFBZ> pageFeeStandard(PageQuery query, KSFBZ cond);
|
||||
|
||||
// ==================== 技术职务课时费标准 ====================
|
||||
|
||||
void addTechPosFeeStandard(JSZWKSFBZ entity);
|
||||
void updateTechPosFeeStandard(JSZWKSFBZ entity);
|
||||
JSZWKSFBZ getTechPosFeeStandardById(String bh);
|
||||
PageResult<JSZWKSFBZ> pageTechPosFeeStandard(PageQuery query, JSZWKSFBZ cond);
|
||||
|
||||
// ==================== 课时补助项目 ====================
|
||||
|
||||
void addSubsidyProject(KSBZXM entity);
|
||||
void updateSubsidyProject(KSBZXM entity);
|
||||
KSBZXM getSubsidyProjectById(String bh);
|
||||
PageResult<KSBZXM> pageSubsidyProject(PageQuery query, KSBZXM cond);
|
||||
|
||||
// ==================== 教学日志课时补助审批表(汇总) ====================
|
||||
|
||||
void addSubsidyApproval(JXRZKSBZSPB entity);
|
||||
void updateSubsidyApproval(JXRZKSBZSPB entity);
|
||||
JXRZKSBZSPB getSubsidyApprovalById(String bh);
|
||||
PageResult<JXRZKSBZSPB> pageSubsidyApproval(PageQuery query, JXRZKSBZSPB cond);
|
||||
/** 计算汇总数据(总课时量、优质课时量、总补助金额) */
|
||||
void calculateSummary(String bh);
|
||||
|
||||
// ==================== 教学日志教员课时补助明细 ====================
|
||||
|
||||
PageResult<JXRZJYKSBZ> pageSubsidyDetail(PageQuery query, JXRZJYKSBZ cond);
|
||||
|
||||
// ==================== 教员课时补助 ====================
|
||||
|
||||
void addTeacherSubsidy(JYKSBZ entity);
|
||||
PageResult<JYKSBZ> pageTeacherSubsidy(PageQuery query, JYKSBZ cond);
|
||||
|
||||
|
||||
|
||||
// ==================== 年终课时费 ====================
|
||||
|
||||
void addYearEndFee(NZKSF entity);
|
||||
void updateYearEndFee(NZKSF entity);
|
||||
NZKSF getYearEndFeeById(String bh);
|
||||
PageResult<NZKSF> pageYearEndFee(PageQuery query, NZKSF cond);
|
||||
|
||||
// ==================== 教员年终课时费 ====================
|
||||
|
||||
PageResult<JYNZKSF> pageTeacherYearEndFee(PageQuery query, JYNZKSF cond);
|
||||
|
||||
// ==================== 教师工作量 ====================
|
||||
|
||||
void addWorkload(JZGZL entity);
|
||||
void updateWorkload(JZGZL entity);
|
||||
JZGZL getWorkloadById(String bh);
|
||||
PageResult<JZGZL> pageWorkload(PageQuery query, JZGZL cond);
|
||||
/** 自动统计课程教学工作量 */
|
||||
void calcCourseWorkload(String jybh, Integer nd, String xq);
|
||||
/** 比对各类教师工作量情况 */
|
||||
PageResult<?> compareWorkload(PageQuery query, Integer nd, String xq);
|
||||
|
||||
// ==================== 教学实施计划统计 ====================
|
||||
|
||||
PageResult<JXSSJHTJB> pageTeachingStats(PageQuery query, JXSSJHTJB cond);
|
||||
|
||||
// ==================== 教员课时查询管理 ====================
|
||||
|
||||
/**
|
||||
* 分页查询教员课时信息
|
||||
* <p>
|
||||
* 数据来源:学期教员信息表 JOIN 教员表 JOIN 教研室表。
|
||||
* 列表展示教研室名称、教员姓名、教员类别、当前/学期职称、当前/学期专业技术职务等级、
|
||||
* 主讲课时、辅讲课时、课程总课时、课程折算总课时、项目补助课时、总课时。
|
||||
* 支持按教员姓名、教研室、部系、年度(学期)、职称、职务等级以及各课时量数字范围(xx课时至xx课时)筛选。
|
||||
* </p>
|
||||
*
|
||||
* @param query 分页参数
|
||||
* @param cond 查询条件(含课时量范围)
|
||||
* @return 分页结果
|
||||
*/
|
||||
PageResult<TeacherHoursVO> pageTeacherHours(PageQuery query, TeacherHoursVO cond);
|
||||
}
|
||||
+98
@@ -0,0 +1,98 @@
|
||||
package com.roomroot.jwgl.service;
|
||||
|
||||
import com.roomroot.jwgl.dto.noticeannouncement.NoticeAnnouncementCreateDTO;
|
||||
import com.roomroot.jwgl.dto.noticeannouncement.NoticeAnnouncementIdDTO;
|
||||
import com.roomroot.jwgl.dto.noticeannouncement.NoticeAnnouncementPriorityDTO;
|
||||
import com.roomroot.jwgl.dto.noticeannouncement.NoticeAnnouncementPublishDTO;
|
||||
import com.roomroot.jwgl.dto.noticeannouncement.NoticeAnnouncementQueryDTO;
|
||||
import com.roomroot.jwgl.dto.noticeannouncement.NoticeAnnouncementRecipientQueryDTO;
|
||||
import com.roomroot.jwgl.dto.noticeannouncement.NoticeAnnouncementUpdateDTO;
|
||||
import com.roomroot.jwgl.dto.noticeannouncement.UserNoticeAnnouncementQueryDTO;
|
||||
import com.roomroot.jwgl.unit.PageResult;
|
||||
import com.roomroot.jwgl.vo.noticeannouncement.NoticeAnnouncementDetailVO;
|
||||
import com.roomroot.jwgl.vo.noticeannouncement.NoticeAnnouncementPublishResultVO;
|
||||
import com.roomroot.jwgl.vo.noticeannouncement.NoticeAnnouncementRecipientVO;
|
||||
import com.roomroot.jwgl.vo.noticeannouncement.NoticeAnnouncementStatisticsVO;
|
||||
import com.roomroot.jwgl.vo.noticeannouncement.NoticeAnnouncementVO;
|
||||
import com.roomroot.jwgl.vo.noticeannouncement.UserNoticeAnnouncementDetailVO;
|
||||
import com.roomroot.jwgl.vo.noticeannouncement.UserNoticeAnnouncementVO;
|
||||
|
||||
/**
|
||||
* 通知公告管理服务。
|
||||
*
|
||||
* <p>在同一个业务服务中维护公告生命周期、发布范围、接收人快照、
|
||||
* 用户阅读和统计查询,不为同一功能重复创建 Service 类。</p>
|
||||
*/
|
||||
public interface NoticeAnnouncementService {
|
||||
|
||||
/**
|
||||
* 分页查询后台通知公告。
|
||||
*/
|
||||
PageResult<NoticeAnnouncementVO> list(
|
||||
NoticeAnnouncementQueryDTO dto);
|
||||
|
||||
/**
|
||||
* 查询通知公告后台详情。
|
||||
*/
|
||||
NoticeAnnouncementDetailVO get(
|
||||
NoticeAnnouncementIdDTO dto);
|
||||
|
||||
/**
|
||||
* 新增一条拟制公告。
|
||||
*/
|
||||
NoticeAnnouncementDetailVO add(
|
||||
NoticeAnnouncementCreateDTO dto);
|
||||
|
||||
/**
|
||||
* 修改拟制或已下架公告。
|
||||
*/
|
||||
NoticeAnnouncementDetailVO update(
|
||||
NoticeAnnouncementUpdateDTO dto);
|
||||
|
||||
/**
|
||||
* 发布公告并生成接收人快照。
|
||||
*/
|
||||
NoticeAnnouncementPublishResultVO publish(
|
||||
NoticeAnnouncementPublishDTO dto);
|
||||
|
||||
/**
|
||||
* 下架已发布公告。
|
||||
*/
|
||||
NoticeAnnouncementDetailVO down(
|
||||
NoticeAnnouncementIdDTO dto);
|
||||
|
||||
/**
|
||||
* 删除拟制或已下架公告。
|
||||
*/
|
||||
void delete(NoticeAnnouncementIdDTO dto);
|
||||
|
||||
/**
|
||||
* 调整公告优先级。
|
||||
*/
|
||||
NoticeAnnouncementDetailVO updatePriority(
|
||||
NoticeAnnouncementPriorityDTO dto);
|
||||
|
||||
/**
|
||||
* 分页查询公告接收人和阅读明细。
|
||||
*/
|
||||
PageResult<NoticeAnnouncementRecipientVO> recipients(
|
||||
NoticeAnnouncementRecipientQueryDTO dto);
|
||||
|
||||
/**
|
||||
* 查询公告接收和阅读统计。
|
||||
*/
|
||||
NoticeAnnouncementStatisticsVO statistics(
|
||||
NoticeAnnouncementIdDTO dto);
|
||||
|
||||
/**
|
||||
* 分页查询当前登录账户可见的公告。
|
||||
*/
|
||||
PageResult<UserNoticeAnnouncementVO> userList(
|
||||
UserNoticeAnnouncementQueryDTO dto);
|
||||
|
||||
/**
|
||||
* 当前登录账户打开公告并完成阅读记录。
|
||||
*/
|
||||
UserNoticeAnnouncementDetailVO read(
|
||||
NoticeAnnouncementIdDTO dto);
|
||||
}
|
||||
+67
@@ -0,0 +1,67 @@
|
||||
package com.roomroot.jwgl.service;
|
||||
|
||||
import com.roomroot.jwgl.dto.notificationlog.NotificationLogExportDTO;
|
||||
import com.roomroot.jwgl.dto.notificationlog.NotificationLogIdDTO;
|
||||
import com.roomroot.jwgl.dto.notificationlog.NotificationLogQueryDTO;
|
||||
import com.roomroot.jwgl.dto.notificationlog.NotificationLogRecipientQueryDTO;
|
||||
import com.roomroot.jwgl.unit.PageResult;
|
||||
import com.roomroot.jwgl.vo.notificationlog.NotificationLogDetailVO;
|
||||
import com.roomroot.jwgl.vo.notificationlog.NotificationLogRecipientVO;
|
||||
import com.roomroot.jwgl.vo.notificationlog.NotificationLogStatisticsVO;
|
||||
import com.roomroot.jwgl.vo.notificationlog.NotificationLogVO;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 通知日志管理服务。
|
||||
*
|
||||
* <p>同一个业务服务将逐步维护通知发送历史、详情、接收阅读明细、
|
||||
* 汇总统计和导出能力,不为每个小功能重复创建 Service 类。</p>
|
||||
*/
|
||||
public interface NotificationLogService {
|
||||
|
||||
/**
|
||||
* 分页查询已经实际发送的通知日志。
|
||||
*
|
||||
* @param dto 通知日志查询条件
|
||||
* @return 经过筛选、统计补全和稳定排序的分页结果
|
||||
*/
|
||||
PageResult<NotificationLogVO> list(
|
||||
NotificationLogQueryDTO dto);
|
||||
|
||||
/**
|
||||
* 根据通知编号查询单条发送日志详情。
|
||||
*
|
||||
* @param dto 通知日志编号参数
|
||||
* @return 通知主体和完整发送、阅读统计
|
||||
*/
|
||||
NotificationLogDetailVO get(
|
||||
NotificationLogIdDTO dto);
|
||||
|
||||
/**
|
||||
* 分页查询指定通知的接收对象和阅读明细。
|
||||
*
|
||||
* @param dto 通知编号、分页和接收阅读筛选条件
|
||||
* @return 按账户去重的接收与阅读明细
|
||||
*/
|
||||
PageResult<NotificationLogRecipientVO> recipients(
|
||||
NotificationLogRecipientQueryDTO dto);
|
||||
|
||||
/**
|
||||
* 按当前筛选条件汇总通知发送和阅读情况。
|
||||
*
|
||||
* @param dto 通知日志筛选条件
|
||||
* @return 通知数量、发送结果和阅读情况汇总
|
||||
*/
|
||||
NotificationLogStatisticsVO statistics(
|
||||
NotificationLogExportDTO dto);
|
||||
|
||||
/**
|
||||
* 按当前筛选条件查询全部待导出的通知日志。
|
||||
*
|
||||
* @param dto 通知日志导出筛选条件
|
||||
* @return 与列表筛选和排序规则一致的全部通知日志
|
||||
*/
|
||||
List<NotificationLogVO> export(
|
||||
NotificationLogExportDTO dto);
|
||||
}
|
||||
+74
@@ -0,0 +1,74 @@
|
||||
package com.roomroot.jwgl.service;
|
||||
|
||||
import com.roomroot.jwgl.entity.JYSRWS;
|
||||
import com.roomroot.jwgl.unit.PageQuery;
|
||||
import com.roomroot.jwgl.unit.PageResult;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 教研室任务书服务接口
|
||||
*/
|
||||
public interface OfficeTaskBookService {
|
||||
|
||||
/**
|
||||
* 新增
|
||||
*
|
||||
* @param jysrws 实体
|
||||
*/
|
||||
void add(JYSRWS jysrws);
|
||||
|
||||
/**
|
||||
* 删除
|
||||
*
|
||||
* @param bh 编号
|
||||
*/
|
||||
void delete(String bh);
|
||||
|
||||
/**
|
||||
* 批量删除
|
||||
*
|
||||
* @param bhList 编号列表
|
||||
*/
|
||||
void batchDelete(List<String> bhList);
|
||||
|
||||
/**
|
||||
* 更新
|
||||
*
|
||||
* @param jysrws 实体
|
||||
*/
|
||||
void update(JYSRWS jysrws);
|
||||
|
||||
/**
|
||||
* 根据编号查询
|
||||
*
|
||||
* @param bh 编号
|
||||
* @return 实体
|
||||
*/
|
||||
JYSRWS getByBh(String bh);
|
||||
|
||||
/**
|
||||
* 分页查询列表
|
||||
*
|
||||
* @param query 分页参数
|
||||
* @param jysrws 查询条件
|
||||
* @return 分页结果
|
||||
*/
|
||||
PageResult<JYSRWS> pageList(PageQuery query, JYSRWS jysrws);
|
||||
|
||||
/**
|
||||
* 根据教学任务编号查询
|
||||
*
|
||||
* @param jxrwbh 教学任务编号
|
||||
* @return 教研室任务书列表
|
||||
*/
|
||||
List<JYSRWS> listByJxrwbh(String jxrwbh);
|
||||
|
||||
/**
|
||||
* 根据教研室代号查询
|
||||
*
|
||||
* @param jysdh 教研室代号
|
||||
* @return 教研室任务书列表
|
||||
*/
|
||||
List<JYSRWS> listByJysdh(String jysdh);
|
||||
}
|
||||
+59
@@ -0,0 +1,59 @@
|
||||
package com.roomroot.jwgl.service;
|
||||
|
||||
import com.roomroot.jwgl.dto.operationlog.OperationLogExportDTO;
|
||||
import com.roomroot.jwgl.dto.operationlog.OperationLogIdDTO;
|
||||
import com.roomroot.jwgl.dto.operationlog.OperationLogQueryDTO;
|
||||
import com.roomroot.jwgl.dto.operationlog.OperationLogRecordDTO;
|
||||
import com.roomroot.jwgl.unit.PageResult;
|
||||
import com.roomroot.jwgl.vo.operationlog.OperationLogDetailVO;
|
||||
import com.roomroot.jwgl.vo.operationlog.OperationLogModuleVO;
|
||||
import com.roomroot.jwgl.vo.operationlog.OperationLogVO;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 操作日志管理服务。
|
||||
*
|
||||
* <p>统一维护操作日志的查询、详情、导出和内部写入能力,
|
||||
* 不为同一业务功能重复创建多个业务服务类。</p>
|
||||
*/
|
||||
public interface OperationLogService {
|
||||
|
||||
/**
|
||||
* 分页查询操作日志。
|
||||
*
|
||||
* @param dto 查询条件
|
||||
* @return 经过筛选和稳定排序的操作日志分页结果
|
||||
*/
|
||||
PageResult<OperationLogVO> list(OperationLogQueryDTO dto);
|
||||
|
||||
/**
|
||||
* 查询操作日志页面可使用的模块选项。
|
||||
*
|
||||
* @return 与模块筛选校验规则保持一致的模块选项
|
||||
*/
|
||||
List<OperationLogModuleVO> modules();
|
||||
|
||||
/**
|
||||
* 根据编号查询操作日志详情。
|
||||
*
|
||||
* @param dto 操作日志编号参数
|
||||
* @return 操作日志、登录记录及操作账户的完整审计信息
|
||||
*/
|
||||
OperationLogDetailVO get(OperationLogIdDTO dto);
|
||||
|
||||
/**
|
||||
* 按筛选条件查询全部待导出的操作日志。
|
||||
*
|
||||
* @param dto 导出筛选条件
|
||||
* @return 经过统一筛选、排序和模块识别的操作日志列表
|
||||
*/
|
||||
List<OperationLogVO> export(OperationLogExportDTO dto);
|
||||
|
||||
/**
|
||||
* 写入一条由服务端自动采集的操作日志。
|
||||
*
|
||||
* @param dto 当前登录记录编号、操作内容和请求地址
|
||||
*/
|
||||
void record(OperationLogRecordDTO dto);
|
||||
}
|
||||
+58
@@ -0,0 +1,58 @@
|
||||
package com.roomroot.jwgl.service;
|
||||
|
||||
import com.roomroot.jwgl.entity.XQXLB;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 学期校历表服务接口
|
||||
*/
|
||||
public interface SemesterCalendarService {
|
||||
|
||||
/**
|
||||
* 新增学期校历
|
||||
*
|
||||
* @param startDate 学期起始日期
|
||||
* @param endDate 学期结束日期
|
||||
*/
|
||||
void add(String startDate,String endDate);
|
||||
|
||||
/**
|
||||
* 删除学期校历
|
||||
*
|
||||
* @param bh 编号
|
||||
*/
|
||||
void delete(String bh);
|
||||
|
||||
/**
|
||||
* 更新学期校历
|
||||
*
|
||||
* @param xqxlb 学期校历
|
||||
*/
|
||||
void update(XQXLB xqxlb);
|
||||
|
||||
/**
|
||||
* 根据编号查询学期校历
|
||||
*
|
||||
* @param bh 编号
|
||||
* @return 学期校历
|
||||
*/
|
||||
XQXLB getById(String bh);
|
||||
|
||||
/**
|
||||
* 根据年度查询学期校历列表(全量)
|
||||
*
|
||||
* @param nd 年度
|
||||
* @return 学期校历列表
|
||||
*/
|
||||
List<XQXLB> listByNd(Integer nd);
|
||||
|
||||
/**
|
||||
* 导入Excel文件解析
|
||||
*
|
||||
* @param file Excel文件
|
||||
* @return 导入数量
|
||||
*/
|
||||
int importExcel(org.springframework.web.multipart.MultipartFile file);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
package com.roomroot.jwgl.service;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import com.roomroot.jwgl.entity.XQ;
|
||||
import com.roomroot.jwgl.unit.PageQuery;
|
||||
import com.roomroot.jwgl.unit.PageResult;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 学期服务接口
|
||||
*/
|
||||
public interface SemesterService extends IService<XQ> {
|
||||
|
||||
/**
|
||||
* 新增学期
|
||||
*
|
||||
* @param xq 学期
|
||||
*/
|
||||
void add(XQ xq);
|
||||
|
||||
/**
|
||||
* 删除学期
|
||||
*
|
||||
* @param nd 年度(主键)
|
||||
*/
|
||||
void delete(Integer nd);
|
||||
|
||||
/**
|
||||
* 更新学期
|
||||
*
|
||||
* @param xq 学期
|
||||
*/
|
||||
void update(XQ xq);
|
||||
|
||||
/**
|
||||
* 根据年度查询
|
||||
*
|
||||
* @param nd 年度(主键)
|
||||
* @return 学期
|
||||
*/
|
||||
XQ getByNd(Integer nd);
|
||||
|
||||
/**
|
||||
* 分页查询学期列表
|
||||
*
|
||||
* @param query 分页参数
|
||||
* @param xq 查询条件
|
||||
* @return 分页结果
|
||||
*/
|
||||
PageResult<XQ> pageList(PageQuery query, XQ xq);
|
||||
|
||||
/**
|
||||
* 查询所有学期列表
|
||||
*
|
||||
* @return 学期列表
|
||||
*/
|
||||
List<XQ> list();
|
||||
}
|
||||
+57
@@ -0,0 +1,57 @@
|
||||
package com.roomroot.jwgl.service;
|
||||
|
||||
import com.roomroot.jwgl.entity.XYXX;
|
||||
import com.roomroot.jwgl.entity.XYKCCJ;
|
||||
import com.roomroot.jwgl.entity.XYKCGCCJ;
|
||||
import com.roomroot.jwgl.unit.PageQuery;
|
||||
import com.roomroot.jwgl.unit.PageResult;
|
||||
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 学员档案管理服务接口
|
||||
* <p>
|
||||
* 提供学员信息的增删改查、学籍异动管理,
|
||||
* 以及学员课程、成绩、课程表查询和 Excel 导出功能。
|
||||
* </p>
|
||||
*/
|
||||
public interface StudentRecordsService {
|
||||
|
||||
/** 新增学员 */
|
||||
void add(XYXX xyxx);
|
||||
|
||||
/** 删除学员(退学处理) */
|
||||
void delete(String bh);
|
||||
|
||||
/** 更新学员信息 */
|
||||
void update(XYXX xyxx);
|
||||
|
||||
/** 查询学员详情 */
|
||||
XYXX getById(String bh);
|
||||
|
||||
/** 分页查询学员列表 */
|
||||
PageResult<XYXX> pageList(PageQuery query, XYXX xyxx);
|
||||
|
||||
/** 学籍异动——留级 */
|
||||
void retainGrade(String bh);
|
||||
|
||||
/** 学籍异动——降级 */
|
||||
void downgrade(String bh);
|
||||
|
||||
/** 学籍异动——退学 */
|
||||
void dropOut(String bh);
|
||||
|
||||
// ========== 学员课程成绩查询 ==========
|
||||
|
||||
/** 查询学员的所有课程成绩 */
|
||||
List<XYKCCJ> getCourseGrades(String xybh);
|
||||
|
||||
/** 查询学员的所有课程过程成绩 */
|
||||
List<XYKCGCCJ> getCourseProcessGrades(String xybh);
|
||||
|
||||
// ========== Excel 导出 ==========
|
||||
|
||||
/** 导出学员课程成绩 Excel */
|
||||
void exportGradesExcel(String xybh, HttpServletResponse response);
|
||||
}
|
||||
+67
@@ -0,0 +1,67 @@
|
||||
package com.roomroot.jwgl.service;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.roomroot.jwgl.entity.XYDSCKCB;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 学员队输出课程表 Service
|
||||
*/
|
||||
public interface StudentTeamOutputScheduleService {
|
||||
|
||||
/**
|
||||
* 新增
|
||||
*
|
||||
* @param xydsckcb 学员队输出课程表
|
||||
*/
|
||||
void add(XYDSCKCB xydsckcb);
|
||||
|
||||
/**
|
||||
* 删除
|
||||
*
|
||||
* @param bh 编号
|
||||
*/
|
||||
void delete(String bh);
|
||||
|
||||
/**
|
||||
* 更新
|
||||
*
|
||||
* @param xydsckcb 学员队输出课程表
|
||||
*/
|
||||
void update(XYDSCKCB xydsckcb);
|
||||
|
||||
/**
|
||||
* 根据编号查询
|
||||
*
|
||||
* @param bh 编号
|
||||
* @return 学员队输出课程表
|
||||
*/
|
||||
XYDSCKCB getByBh(String bh);
|
||||
|
||||
/**
|
||||
* 根据年度和学员队编号查询
|
||||
*
|
||||
* @param nd 年度
|
||||
* @param xydbh 学员队编号
|
||||
* @return 学员队输出课程表
|
||||
*/
|
||||
XYDSCKCB getByNdAndXydbh(Integer nd, String xydbh);
|
||||
|
||||
/**
|
||||
* 分页查询
|
||||
*
|
||||
* @param pageNum 页码
|
||||
* @param pageSize 每页数量
|
||||
* @param xydsckcb 查询条件
|
||||
* @return 分页结果
|
||||
*/
|
||||
Page<XYDSCKCB> list(int pageNum, int pageSize, XYDSCKCB xydsckcb);
|
||||
|
||||
/**
|
||||
* 查询所有
|
||||
*
|
||||
* @return 所有学员队输出课程表
|
||||
*/
|
||||
List<XYDSCKCB> all();
|
||||
}
|
||||
+117
@@ -0,0 +1,117 @@
|
||||
package com.roomroot.jwgl.service;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.roomroot.jwgl.entity.XYDRWB;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 学员队任务表 Service
|
||||
*/
|
||||
public interface StudentTeamTaskService {
|
||||
|
||||
/**
|
||||
* 新增
|
||||
*
|
||||
* @param xydrwb 学员队任务
|
||||
*/
|
||||
void add(XYDRWB xydrwb);
|
||||
|
||||
/**
|
||||
* 删除
|
||||
*
|
||||
* @param bh 编号
|
||||
*/
|
||||
void delete(String bh);
|
||||
|
||||
/**
|
||||
* 更新
|
||||
*
|
||||
* @param xydrwb 学员队任务
|
||||
*/
|
||||
void update(XYDRWB xydrwb);
|
||||
|
||||
/**
|
||||
* 根据编号查询
|
||||
*
|
||||
* @param bh 编号
|
||||
* @return 学员队任务
|
||||
*/
|
||||
XYDRWB getByBh(String bh);
|
||||
|
||||
/**
|
||||
* 分页查询(按序号标识排序)
|
||||
*
|
||||
* @param pageNum 页码
|
||||
* @param pageSize 每页数量
|
||||
* @param xydrwb 查询条件
|
||||
* @return 分页结果
|
||||
*/
|
||||
Page<XYDRWB> list(int pageNum, int pageSize, XYDRWB xydrwb);
|
||||
|
||||
/**
|
||||
* 分页查询(按计划课次序号排序)
|
||||
*
|
||||
* @param pageNum 页码
|
||||
* @param pageSize 每页数量
|
||||
* @param xydrwb 查询条件
|
||||
* @return 分页结果
|
||||
*/
|
||||
Page<XYDRWB> groupList(int pageNum, int pageSize, XYDRWB xydrwb);
|
||||
|
||||
/**
|
||||
* 批量预设合班
|
||||
* <p>
|
||||
* 根据编号列表,按年度排序生成统一的计划课次序号
|
||||
* </p>
|
||||
*
|
||||
* @param bhList 编号列表
|
||||
* @return 更新数量
|
||||
*/
|
||||
int batchPresetMerge(List<String> bhList);
|
||||
|
||||
/**
|
||||
* 批量预设拆班
|
||||
* <p>
|
||||
* 根据编号列表,清空计划课次序号
|
||||
* </p>
|
||||
*
|
||||
* @param bhList 编号列表
|
||||
* @return 更新数量
|
||||
*/
|
||||
int batchPresetSplit(List<String> bhList);
|
||||
|
||||
/**
|
||||
* 查询所有
|
||||
*
|
||||
* @return 所有学员队任务
|
||||
*/
|
||||
List<XYDRWB> all();
|
||||
|
||||
/**
|
||||
* 自动生成必修课程
|
||||
* <p>
|
||||
* 根据学员队编号从学员队表获取专业代号,
|
||||
* 再根据专业代号和学期第次查询专业教学计划表,
|
||||
* 为当前班次自动生成必修课程,插入到学员队任务表。
|
||||
* 已存在的课程(按课编号判断)不会重复添加。
|
||||
* </p>
|
||||
*
|
||||
* @param xydbh 学员队编号
|
||||
* @param xqdc 学期第次
|
||||
* @return 新增数量
|
||||
*/
|
||||
int autoGenerateRequiredCourses(String xydbh, Integer xqdc);
|
||||
|
||||
/**
|
||||
* 批量复制课程
|
||||
* <p>
|
||||
* 根据传入的编号集合,复制课程信息,替换学员队编号为新的值
|
||||
* </p>
|
||||
*
|
||||
* @param bhList 源编号集合
|
||||
* @param newXydbh 新学员队编号
|
||||
* @return 新生成的编号集合
|
||||
*/
|
||||
List<String> copy(List<String> bhList, String newXydbh);
|
||||
}
|
||||
+78
@@ -0,0 +1,78 @@
|
||||
package com.roomroot.jwgl.service;
|
||||
|
||||
import com.roomroot.jwgl.dto.systeminitialization.SemesterInitializationSaveDTO;
|
||||
import com.roomroot.jwgl.dto.systeminitialization.SystemInitializationConfigurationSaveDTO;
|
||||
import com.roomroot.jwgl.dto.systeminitialization.SystemInitializationExecutionDTO;
|
||||
import com.roomroot.jwgl.dto.systeminitialization.SystemInitializationHistoricalImportDTO;
|
||||
import com.roomroot.jwgl.vo.systeminitialization.SemesterInitializationVO;
|
||||
import com.roomroot.jwgl.vo.systeminitialization.SystemInitializationConfigurationVO;
|
||||
import com.roomroot.jwgl.vo.systeminitialization.SystemInitializationExecutionResultVO;
|
||||
import com.roomroot.jwgl.vo.systeminitialization.SystemInitializationHistoricalImportResultVO;
|
||||
import com.roomroot.jwgl.vo.systeminitialization.SystemInitializationPrecheckVO;
|
||||
|
||||
/**
|
||||
* 系统初始化管理服务。
|
||||
*
|
||||
* <p>同一个业务服务统一维护系统基础参数、学期初始化、
|
||||
* 历史基础数据导入、预检查和最终执行确认。</p>
|
||||
*/
|
||||
public interface SystemInitializationService {
|
||||
|
||||
/**
|
||||
* 查询当前生效的系统基础参数。
|
||||
*
|
||||
* @return 当前系统基础参数
|
||||
*/
|
||||
SystemInitializationConfigurationVO getCurrentConfiguration();
|
||||
|
||||
/**
|
||||
* 保存新的系统基础参数版本。
|
||||
*
|
||||
* @param dto 系统基础参数
|
||||
* @return 新的当前配置
|
||||
*/
|
||||
SystemInitializationConfigurationVO saveConfiguration(
|
||||
SystemInitializationConfigurationSaveDTO dto);
|
||||
|
||||
/**
|
||||
* 查询当前学期。
|
||||
*
|
||||
* @return 当前学期
|
||||
*/
|
||||
SemesterInitializationVO getCurrentSemester();
|
||||
|
||||
/**
|
||||
* 保存指定年度和序号的学期。
|
||||
*
|
||||
* @param dto 学期初始化参数
|
||||
* @return 保存后的学期
|
||||
*/
|
||||
SemesterInitializationVO saveSemester(
|
||||
SemesterInitializationSaveDTO dto);
|
||||
|
||||
/**
|
||||
* 导入历史基础数据。
|
||||
*
|
||||
* @param dto 历史数据 Excel 文件
|
||||
* @return 导入结果
|
||||
*/
|
||||
SystemInitializationHistoricalImportResultVO
|
||||
importHistoricalData(
|
||||
SystemInitializationHistoricalImportDTO dto);
|
||||
|
||||
/**
|
||||
* 执行系统初始化预检查。
|
||||
*
|
||||
* @return 预检查汇总结果
|
||||
*/
|
||||
SystemInitializationPrecheckVO precheck();
|
||||
|
||||
/**
|
||||
* 完成系统初始化最终确认。
|
||||
*
|
||||
* @param dto 页面预检查快照和确认标志
|
||||
* @return 初始化执行结果
|
||||
*/
|
||||
SystemInitializationExecutionResultVO execute(
|
||||
SystemInitializationExecutionDTO dto);
|
||||
}
|
||||
+84
@@ -0,0 +1,84 @@
|
||||
package com.roomroot.jwgl.service;
|
||||
|
||||
import com.roomroot.jwgl.entity.JCXX;
|
||||
import com.roomroot.jwgl.unit.PageQuery;
|
||||
import com.roomroot.jwgl.unit.PageResult;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 教材信息服务接口
|
||||
*/
|
||||
public interface TeachingMaterialService {
|
||||
|
||||
/**
|
||||
* 新增教材信息
|
||||
*
|
||||
* @param jcxx 教材信息
|
||||
*/
|
||||
void add(JCXX jcxx);
|
||||
|
||||
/**
|
||||
* 删除教材信息
|
||||
*
|
||||
* @param id 编号
|
||||
*/
|
||||
void delete(String id);
|
||||
|
||||
/**
|
||||
* 更新教材信息
|
||||
*
|
||||
* @param jcxx 教材信息
|
||||
*/
|
||||
void update(JCXX jcxx);
|
||||
|
||||
/**
|
||||
* 根据编号查询
|
||||
*
|
||||
* @param id 唯一标识码
|
||||
* @return 教材信息
|
||||
*/
|
||||
JCXX getById(String id);
|
||||
|
||||
/**
|
||||
* 根据编号查询
|
||||
*
|
||||
* @param bh 编号
|
||||
* @return 教材信息
|
||||
*/
|
||||
JCXX getByBh(String bh);
|
||||
|
||||
/**
|
||||
* 分页查询教材信息列表
|
||||
*
|
||||
* @param query 分页参数
|
||||
* @param jcxx 查询条件
|
||||
* @return 分页结果
|
||||
*/
|
||||
PageResult<JCXX> pageList(PageQuery query, JCXX jcxx);
|
||||
|
||||
/**
|
||||
* 查询所有教材信息列表
|
||||
*
|
||||
* @param jcxx 查询条件
|
||||
* @return 教材信息列表
|
||||
*/
|
||||
List<JCXX> list(JCXX jcxx);
|
||||
|
||||
/**
|
||||
* 导入Excel文件
|
||||
*
|
||||
* @param file Excel文件
|
||||
* @return 导入数量
|
||||
*/
|
||||
int importExcel(MultipartFile file);
|
||||
|
||||
/**
|
||||
* 下载模板文件
|
||||
*
|
||||
* @param response HTTP响应
|
||||
*/
|
||||
void downloadTemplate(HttpServletResponse response);
|
||||
}
|
||||
+70
@@ -0,0 +1,70 @@
|
||||
package com.roomroot.jwgl.service;
|
||||
|
||||
import com.roomroot.jwgl.entity.JXSSJH;
|
||||
import com.roomroot.jwgl.unit.PageQuery;
|
||||
import com.roomroot.jwgl.unit.PageResult;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 导入数据表-教学实施计划服务接口
|
||||
*/
|
||||
public interface TeachingPlanService {
|
||||
|
||||
/**
|
||||
* 新增
|
||||
*
|
||||
* @param drsjbjxssjh 实体
|
||||
*/
|
||||
void add(JXSSJH drsjbjxssjh);
|
||||
|
||||
/**
|
||||
* 删除
|
||||
*
|
||||
* @param bsh 标识号
|
||||
*/
|
||||
void delete(String bsh);
|
||||
|
||||
/**
|
||||
* 更新
|
||||
*
|
||||
* @param drsjbjxssjh 实体
|
||||
*/
|
||||
void update(JXSSJH drsjbjxssjh);
|
||||
|
||||
/**
|
||||
* 根据标识号查询
|
||||
*
|
||||
* @param bsh 标识号
|
||||
* @return 实体
|
||||
*/
|
||||
JXSSJH getByBsh(String bsh);
|
||||
|
||||
/**
|
||||
* 分页查询列表
|
||||
*
|
||||
* @param query 分页参数
|
||||
* @param drsjbjxssjh 查询条件
|
||||
* @return 分页结果
|
||||
*/
|
||||
PageResult<JXSSJH> pageList(PageQuery query, JXSSJH drsjbjxssjh);
|
||||
|
||||
/**
|
||||
* 查询所有列表
|
||||
*
|
||||
* @param drsjbjxssjh 查询条件
|
||||
* @return 列表
|
||||
*/
|
||||
List<JXSSJH> list(JXSSJH drsjbjxssjh);
|
||||
|
||||
/**
|
||||
* 从Excel导入教学实施计划数据。
|
||||
* 标识号和登录编号自动生成,其他字段从Excel读取。
|
||||
*
|
||||
* @param file Excel文件
|
||||
* @return 导入的记录数
|
||||
* @throws Exception 解析或导入异常
|
||||
*/
|
||||
int importFromExcel(MultipartFile file) throws Exception;
|
||||
}
|
||||
+75
@@ -0,0 +1,75 @@
|
||||
package com.roomroot.jwgl.service;
|
||||
|
||||
import com.roomroot.jwgl.entity.JCKCMXX;
|
||||
import com.roomroot.jwgl.unit.PageQuery;
|
||||
import com.roomroot.jwgl.unit.PageResult;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 教材库存明细项服务接口
|
||||
*/
|
||||
public interface TeachingStockDetailService {
|
||||
|
||||
/**
|
||||
* 新增教材库存明细项
|
||||
*
|
||||
* @param jckcmxx 教材库存明细项
|
||||
*/
|
||||
void add(JCKCMXX jckcmxx);
|
||||
|
||||
/**
|
||||
* 删除教材库存明细项
|
||||
*
|
||||
* @param id 主键
|
||||
*/
|
||||
void delete(String id);
|
||||
|
||||
/**
|
||||
* 更新教材库存明细项
|
||||
*
|
||||
* @param jckcmxx 教材库存明细项
|
||||
*/
|
||||
void update(JCKCMXX jckcmxx);
|
||||
|
||||
/**
|
||||
* 根据ID查询
|
||||
*
|
||||
* @param id 主键
|
||||
* @return 教材库存明细项
|
||||
*/
|
||||
JCKCMXX getById(String id);
|
||||
|
||||
/**
|
||||
* 根据编号查询
|
||||
*
|
||||
* @param bh 编号
|
||||
* @return 教材库存明细项
|
||||
*/
|
||||
JCKCMXX getByBh(String bh);
|
||||
|
||||
/**
|
||||
* 根据教材库存单编号查询
|
||||
*
|
||||
* @param jckcdbbh 教材库存单编号
|
||||
* @return 教材库存明细项列表
|
||||
*/
|
||||
List<JCKCMXX> getByJckcdbbh(String jckcdbbh);
|
||||
|
||||
/**
|
||||
* 分页查询教材库存明细项列表
|
||||
*
|
||||
* @param query 分页参数
|
||||
* @param jckcmxx 查询条件
|
||||
* @return 分页结果
|
||||
*/
|
||||
PageResult<JCKCMXX> pageList(PageQuery query, JCKCMXX jckcmxx);
|
||||
|
||||
/**
|
||||
* 查询所有教材库存明细项列表
|
||||
*
|
||||
* @param jckcmxx 查询条件
|
||||
* @return 教材库存明细项列表
|
||||
*/
|
||||
List<JCKCMXX> list(JCKCMXX jckcmxx);
|
||||
}
|
||||
+67
@@ -0,0 +1,67 @@
|
||||
package com.roomroot.jwgl.service;
|
||||
|
||||
import com.roomroot.jwgl.entity.JCKCD;
|
||||
import com.roomroot.jwgl.unit.PageQuery;
|
||||
import com.roomroot.jwgl.unit.PageResult;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 教材库存单服务接口
|
||||
*/
|
||||
public interface TeachingStockService {
|
||||
|
||||
/**
|
||||
* 新增教材库存单
|
||||
*
|
||||
* @param jckcd 教材库存单
|
||||
*/
|
||||
void add(JCKCD jckcd);
|
||||
|
||||
/**
|
||||
* 删除教材库存单
|
||||
*
|
||||
* @param id 主键
|
||||
*/
|
||||
void delete(String id);
|
||||
|
||||
/**
|
||||
* 更新教材库存单
|
||||
*
|
||||
* @param jckcd 教材库存单
|
||||
*/
|
||||
void update(JCKCD jckcd);
|
||||
|
||||
/**
|
||||
* 根据ID查询
|
||||
*
|
||||
* @param id 主键
|
||||
* @return 教材库存单
|
||||
*/
|
||||
JCKCD getById(String id);
|
||||
|
||||
/**
|
||||
* 根据编号查询
|
||||
*
|
||||
* @param bh 编号
|
||||
* @return 教材库存单
|
||||
*/
|
||||
JCKCD getByBh(String bh);
|
||||
|
||||
/**
|
||||
* 分页查询教材库存单列表
|
||||
*
|
||||
* @param query 分页参数
|
||||
* @param jckcd 查询条件
|
||||
* @return 分页结果
|
||||
*/
|
||||
PageResult<JCKCD> pageList(PageQuery query, JCKCD jckcd);
|
||||
|
||||
/**
|
||||
* 查询所有教材库存单列表
|
||||
*
|
||||
* @param jckcd 查询条件
|
||||
* @return 教材库存单列表
|
||||
*/
|
||||
List<JCKCD> list(JCKCD jckcd);
|
||||
}
|
||||
+74
@@ -0,0 +1,74 @@
|
||||
package com.roomroot.jwgl.service;
|
||||
|
||||
import com.roomroot.jwgl.entity.JXRW;
|
||||
import com.roomroot.jwgl.unit.PageQuery;
|
||||
import com.roomroot.jwgl.unit.PageResult;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 教学任务服务接口
|
||||
*/
|
||||
public interface TeachingTaskService {
|
||||
|
||||
/**
|
||||
* 新增
|
||||
*
|
||||
* @param jxrw 实体
|
||||
*/
|
||||
void add(JXRW jxrw);
|
||||
|
||||
/**
|
||||
* 删除
|
||||
*
|
||||
* @param bh 编号
|
||||
*/
|
||||
void delete(String bh);
|
||||
|
||||
/**
|
||||
* 批量删除
|
||||
*
|
||||
* @param bhList 编号列表
|
||||
*/
|
||||
void batchDelete(List<String> bhList);
|
||||
|
||||
/**
|
||||
* 更新
|
||||
*
|
||||
* @param jxrw 实体
|
||||
*/
|
||||
void update(JXRW jxrw);
|
||||
|
||||
/**
|
||||
* 根据编号查询
|
||||
*
|
||||
* @param bh 编号
|
||||
* @return 实体
|
||||
*/
|
||||
JXRW getByBh(String bh);
|
||||
|
||||
/**
|
||||
* 分页查询列表
|
||||
*
|
||||
* @param query 分页参数
|
||||
* @param jxrw 查询条件
|
||||
* @return 分页结果
|
||||
*/
|
||||
PageResult<JXRW> pageList(PageQuery query, JXRW jxrw);
|
||||
|
||||
/**
|
||||
* 查询所有有效数据(DEL_FLAG = 0)
|
||||
*
|
||||
* @return 所有有效数据列表
|
||||
*/
|
||||
List<JXRW> listAllValid();
|
||||
|
||||
/**
|
||||
* 发布教学任务及教研室任务书
|
||||
* 根据教学任务编号修改状态为"发布",并批量更新所有关联的教研室任务书状态为"发布"
|
||||
*
|
||||
* @param bh 教学任务编号
|
||||
* @return 更新数量
|
||||
*/
|
||||
int batchPublish(String bh);
|
||||
}
|
||||
+56
@@ -0,0 +1,56 @@
|
||||
package com.roomroot.jwgl.service;
|
||||
|
||||
import com.roomroot.jwgl.entity.ZYB;
|
||||
import com.roomroot.jwgl.unit.PageQuery;
|
||||
import com.roomroot.jwgl.unit.PageResult;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
* 培养方案管理服务接口
|
||||
* <p>
|
||||
* 提供专业/培养方案的增加、删除(逻辑删除)、更新、分页查询等功能。
|
||||
* 对应数据表:专业表
|
||||
* 多版本通过培训类型(培训类型)字段区分。
|
||||
* </p>
|
||||
*/
|
||||
@Service
|
||||
public interface TrainingProgramService {
|
||||
|
||||
/**
|
||||
* 新增培养方案(专业)
|
||||
*
|
||||
* @param entity 专业表实体
|
||||
*/
|
||||
void add(ZYB entity);
|
||||
|
||||
/**
|
||||
* 逻辑删除(停用)培养方案
|
||||
*
|
||||
* @param zYDH 专业代号
|
||||
*/
|
||||
void disable(String zYDH);
|
||||
|
||||
/**
|
||||
* 更新培养方案
|
||||
*
|
||||
* @param entity 专业表实体
|
||||
*/
|
||||
void update(ZYB entity);
|
||||
|
||||
/**
|
||||
* 根据专业代号查询培养方案详情
|
||||
*
|
||||
* @param zYDH 专业代号
|
||||
* @return 专业表实体
|
||||
*/
|
||||
ZYB getById(String zYDH);
|
||||
|
||||
/**
|
||||
* 分页条件查询培养方案列表
|
||||
*
|
||||
* @param query 分页参数
|
||||
* @param cond 查询条件
|
||||
* @return 分页结果
|
||||
*/
|
||||
PageResult<ZYB> pageList(PageQuery query, ZYB cond);
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
package com.roomroot.jwgl.service;
|
||||
|
||||
import com.roomroot.jwgl.entity.ZYJXJHB;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 专业教学计划表服务接口
|
||||
*/
|
||||
public interface ZYJXJHBService {
|
||||
|
||||
/**
|
||||
* 新增
|
||||
*
|
||||
* @param zyjxjhb 实体
|
||||
*/
|
||||
void add(ZYJXJHB zyjxjhb);
|
||||
|
||||
/**
|
||||
* 删除(设置停用标识为1)
|
||||
*
|
||||
* @param bh 编号
|
||||
*/
|
||||
void delete(String bh);
|
||||
|
||||
/**
|
||||
* 批量删除(设置停用标识为1)
|
||||
*
|
||||
* @param bhList 编号列表
|
||||
*/
|
||||
void batchDelete(List<String> bhList);
|
||||
|
||||
/**
|
||||
* 更新
|
||||
*
|
||||
* @param zyjxjhb 实体
|
||||
*/
|
||||
void update(ZYJXJHB zyjxjhb);
|
||||
|
||||
/**
|
||||
* 根据编号查询
|
||||
*
|
||||
* @param bh 编号
|
||||
* @return 实体
|
||||
*/
|
||||
ZYJXJHB getByBh(String bh);
|
||||
|
||||
/**
|
||||
* 查询所有数据
|
||||
*
|
||||
* @return 所有数据列表
|
||||
*/
|
||||
List<ZYJXJHB> list();
|
||||
|
||||
/**
|
||||
* 根据专业代号和停用标识查询
|
||||
*
|
||||
* @param zydh 专业代号
|
||||
* @param ty 停用标识(0-正常,1-停用)
|
||||
* @return 列表
|
||||
*/
|
||||
List<ZYJXJHB> listByZydhAndTy(String zydh, Integer ty);
|
||||
}
|
||||
+2103
File diff suppressed because it is too large
Load Diff
+2165
File diff suppressed because it is too large
Load Diff
+66
@@ -0,0 +1,66 @@
|
||||
package com.roomroot.jwgl.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.roomroot.jwgl.entity.BZLB;
|
||||
import com.roomroot.jwgl.mapper.BZLBMapper;
|
||||
import com.roomroot.jwgl.service.BZLBService;
|
||||
import com.roomroot.jwgl.utils.UuidUtil;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import jakarta.annotation.Resource;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 保障类别 Service 实现
|
||||
*/
|
||||
@Service
|
||||
public class BZLBServiceImpl implements BZLBService {
|
||||
|
||||
@Resource
|
||||
private BZLBMapper bzlbMapper;
|
||||
|
||||
@Override
|
||||
public void add(BZLB bzlb) {
|
||||
bzlb.setBh(UuidUtil.getUUID());
|
||||
if (bzlb.getTy() == null) {
|
||||
bzlb.setTy(0);
|
||||
}
|
||||
bzlbMapper.insert(bzlb);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void delete(String bh) {
|
||||
bzlbMapper.deleteById(bh);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(BZLB bzlb) {
|
||||
bzlbMapper.updateById(bzlb);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BZLB getByBh(String bh) {
|
||||
return bzlbMapper.selectById(bh);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Page<BZLB> list(int pageNum, int pageSize, BZLB bzlb) {
|
||||
Page<BZLB> page = new Page<>(pageNum, pageSize);
|
||||
LambdaQueryWrapper<BZLB> wrapper = new LambdaQueryWrapper<>();
|
||||
if (bzlb != null) {
|
||||
wrapper.like(bzlb.getMc() != null, BZLB::getMc, bzlb.getMc());
|
||||
wrapper.eq(bzlb.getBmbh() != null, BZLB::getBmbh, bzlb.getBmbh());
|
||||
wrapper.eq(bzlb.getTy() != null, BZLB::getTy, bzlb.getTy());
|
||||
}
|
||||
wrapper.orderByDesc(BZLB::getBh);
|
||||
return bzlbMapper.selectPage(page, wrapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<BZLB> all() {
|
||||
LambdaQueryWrapper<BZLB> wrapper = new LambdaQueryWrapper<>();
|
||||
wrapper.eq(BZLB::getTy, 0);
|
||||
return bzlbMapper.selectList(wrapper);
|
||||
}
|
||||
}
|
||||
+211
@@ -0,0 +1,211 @@
|
||||
package com.roomroot.jwgl.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.roomroot.jwgl.entity.JXLB;
|
||||
import com.roomroot.jwgl.mapper.BuildMapper;
|
||||
import com.roomroot.jwgl.service.BuildService;
|
||||
import com.roomroot.jwgl.unit.PageQuery;
|
||||
import com.roomroot.jwgl.unit.PageResult;
|
||||
import com.roomroot.jwgl.utils.UuidUtil;
|
||||
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
|
||||
import org.apache.poi.ss.usermodel.*;
|
||||
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import jakarta.annotation.Resource;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.net.URLEncoder;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 教学楼表服务实现类
|
||||
*/
|
||||
@Service
|
||||
public class BuildServiceImpl implements BuildService {
|
||||
|
||||
@Resource
|
||||
private BuildMapper buildMapper;
|
||||
|
||||
@Override
|
||||
public void add(JXLB jxlb) {
|
||||
String uuid = UuidUtil.getUUID();
|
||||
jxlb.setId(uuid);
|
||||
jxlb.setDelFlag(0);
|
||||
buildMapper.insert(jxlb);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void delete(String id) {
|
||||
JXLB jxlb = getById(id);
|
||||
jxlb.setDelFlag(1);
|
||||
buildMapper.updateById(jxlb);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(JXLB jxlb) {
|
||||
buildMapper.updateById(jxlb);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JXLB getById(String id) {
|
||||
return buildMapper.selectById(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PageResult<JXLB> pageList(PageQuery query, JXLB jxlb) {
|
||||
jxlb.setDelFlag(0);
|
||||
Page<JXLB> page = new Page<>(query.getPageNum(), query.getPageSize());
|
||||
Page<JXLB> result = buildMapper.selectPageList(page, jxlb);
|
||||
return new PageResult<>(result.getRecords(), result.getTotal(),
|
||||
query.getPageNum(), query.getPageSize());
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<JXLB> list(JXLB jxlb) {
|
||||
LambdaQueryWrapper<JXLB> wrapper = new LambdaQueryWrapper<>();
|
||||
if (jxlb != null) {
|
||||
if (jxlb.getJxldh() != null && !jxlb.getJxldh().isEmpty()) {
|
||||
wrapper.like(JXLB::getJxldh, jxlb.getJxldh());
|
||||
}
|
||||
if (jxlb.getJxlmc() != null && !jxlb.getJxlmc().isEmpty()) {
|
||||
wrapper.like(JXLB::getJxlmc, jxlb.getJxlmc());
|
||||
}
|
||||
if (jxlb.getDd() != null && !jxlb.getDd().isEmpty()) {
|
||||
wrapper.like(JXLB::getDd, jxlb.getDd());
|
||||
}
|
||||
}
|
||||
wrapper.orderByAsc(JXLB::getXh);
|
||||
return buildMapper.selectList(wrapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int importExcel(MultipartFile file) {
|
||||
try (InputStream is = file.getInputStream();
|
||||
Workbook workbook = file.getOriginalFilename().endsWith(".xlsx")
|
||||
? new XSSFWorkbook(is) : new HSSFWorkbook(is)) {
|
||||
|
||||
Sheet sheet = workbook.getSheetAt(0);
|
||||
int count = 0;
|
||||
|
||||
// 在循环外获取起始序号
|
||||
int nextNum = getNextNumber();
|
||||
|
||||
// 从第二行开始读取数据(跳过表头)
|
||||
for (int i = 1; i <= sheet.getLastRowNum(); i++) {
|
||||
Row row = sheet.getRow(i);
|
||||
if (row == null) continue;
|
||||
|
||||
JXLB jxlb = new JXLB();
|
||||
|
||||
// 生成序号(数字字符串)和教学楼代号(三位补零)
|
||||
jxlb.setXh(String.valueOf(nextNum));
|
||||
jxlb.setJxldh(String.format("%03d", nextNum));
|
||||
nextNum++; // 递增序号
|
||||
|
||||
// 教学楼名称
|
||||
jxlb.setJxlmc(getCellValue(row, 2));
|
||||
|
||||
// 地点
|
||||
jxlb.setDd(getCellValue(row, 3));
|
||||
|
||||
// 备注
|
||||
jxlb.setBz(getCellValue(row, 4));
|
||||
|
||||
jxlb.setId(UuidUtil.getUUID());
|
||||
jxlb.setDelFlag(0);
|
||||
|
||||
buildMapper.insert(jxlb);
|
||||
count++;
|
||||
}
|
||||
return count;
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("Excel解析失败: " + e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void downloadTemplate(HttpServletResponse response) {
|
||||
try {
|
||||
// 从resources/template目录读取模板文件
|
||||
ClassPathResource resource = new ClassPathResource("template/template_jxcdgl.xls");
|
||||
InputStream is = resource.getInputStream();
|
||||
|
||||
// 设置响应头
|
||||
response.setContentType("application/vnd.ms-excel");
|
||||
response.setHeader("Content-Disposition", "attachment;filename=" +
|
||||
URLEncoder.encode("教学场地管理模板.xls", "UTF-8"));
|
||||
|
||||
// 输出文件
|
||||
OutputStream os = response.getOutputStream();
|
||||
byte[] buffer = new byte[1024];
|
||||
int len;
|
||||
while ((len = is.read(buffer)) != -1) {
|
||||
os.write(buffer, 0, len);
|
||||
}
|
||||
os.flush();
|
||||
is.close();
|
||||
os.close();
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("下载模板失败: " + e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String generateNextXh() {
|
||||
int nextNum = getNextNumber();
|
||||
return String.format("%03d", nextNum);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取下一个序号(数字)
|
||||
*/
|
||||
private int getNextNumber() {
|
||||
String maxXh = buildMapper.selectMaxXh();
|
||||
if (maxXh == null || maxXh.isEmpty()) {
|
||||
return 1;
|
||||
}
|
||||
try {
|
||||
return Integer.parseInt(maxXh) + 1;
|
||||
} catch (NumberFormatException e) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取单元格字符串值
|
||||
*/
|
||||
private String getCellValue(Row row, int index) {
|
||||
Cell cell = row.getCell(index, Row.MissingCellPolicy.CREATE_NULL_AS_BLANK);
|
||||
if (cell == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
CellType type = cell.getCellType();
|
||||
// 处理公式单元格
|
||||
if (type == CellType.FORMULA) {
|
||||
type = cell.getCachedFormulaResultType();
|
||||
}
|
||||
|
||||
switch (type) {
|
||||
case NUMERIC:
|
||||
double num = cell.getNumericCellValue();
|
||||
// 整数就去掉小数点后多余的 .0
|
||||
if (num == Math.floor(num)) {
|
||||
return String.valueOf((long) num);
|
||||
} else {
|
||||
return String.valueOf(num);
|
||||
}
|
||||
case STRING:
|
||||
return cell.getStringCellValue().trim();
|
||||
case BOOLEAN:
|
||||
return String.valueOf(cell.getBooleanCellValue());
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
+101
@@ -0,0 +1,101 @@
|
||||
package com.roomroot.jwgl.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.roomroot.jwgl.entity.JXCDL;
|
||||
import com.roomroot.jwgl.mapper.ClassRoomCalendarMapper;
|
||||
import com.roomroot.jwgl.service.ClassRoomCalendarService;
|
||||
import com.roomroot.jwgl.unit.PageQuery;
|
||||
import com.roomroot.jwgl.unit.PageResult;
|
||||
import com.roomroot.jwgl.utils.UuidUtil;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import jakarta.annotation.Resource;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 教学场地历服务实现类
|
||||
*/
|
||||
@Service
|
||||
public class ClassRoomCalendarServiceImpl implements ClassRoomCalendarService {
|
||||
|
||||
@Resource
|
||||
private ClassRoomCalendarMapper jxcdlMapper;
|
||||
|
||||
@Override
|
||||
public void add(JXCDL jxcdl) {
|
||||
jxcdl.setId(UuidUtil.getUUID());
|
||||
jxcdl.setDelFlag(0);
|
||||
jxcdl.setCjsj(LocalDateTime.now());
|
||||
jxcdlMapper.insert(jxcdl);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void delete(String id) {
|
||||
JXCDL jxcdl = getById(id);
|
||||
jxcdl.setDelFlag(1);
|
||||
jxcdlMapper.updateById(jxcdl);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(JXCDL jxcdl) {
|
||||
jxcdlMapper.updateById(jxcdl);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JXCDL getById(String id) {
|
||||
return jxcdlMapper.selectById(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PageResult<JXCDL> pageList(PageQuery query, JXCDL jxcdl) {
|
||||
jxcdl.setDelFlag(0);
|
||||
Page<JXCDL> page = new Page<>(query.getPageNum(), query.getPageSize());
|
||||
Page<JXCDL> result = jxcdlMapper.selectPageList(page, jxcdl);
|
||||
return new PageResult<>(result.getRecords(), result.getTotal(),
|
||||
query.getPageNum(), query.getPageSize());
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<JXCDL> list(JXCDL jxcdl) {
|
||||
LambdaQueryWrapper<JXCDL> wrapper = buildQueryWrapper(jxcdl);
|
||||
return jxcdlMapper.selectList(wrapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<JXCDL> listByJsbh(String jsbh) {
|
||||
return jxcdlMapper.selectByJsbh(jsbh);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<JXCDL> listByRq(String rq) {
|
||||
return jxcdlMapper.selectByRq(rq);
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建查询条件
|
||||
*/
|
||||
private LambdaQueryWrapper<JXCDL> buildQueryWrapper(JXCDL jxcdl) {
|
||||
LambdaQueryWrapper<JXCDL> wrapper = new LambdaQueryWrapper<>();
|
||||
if (jxcdl != null) {
|
||||
if (jxcdl.getBh() != null && !jxcdl.getBh().isEmpty()) {
|
||||
wrapper.like(JXCDL::getBh, jxcdl.getBh());
|
||||
}
|
||||
if (jxcdl.getMc() != null && !jxcdl.getMc().isEmpty()) {
|
||||
wrapper.like(JXCDL::getMc, jxcdl.getMc());
|
||||
}
|
||||
if (jxcdl.getJsbh() != null && !jxcdl.getJsbh().isEmpty()) {
|
||||
wrapper.eq(JXCDL::getJsbh, jxcdl.getJsbh());
|
||||
}
|
||||
if (jxcdl.getKpk() != null) {
|
||||
wrapper.eq(JXCDL::getKpk, jxcdl.getKpk());
|
||||
}
|
||||
if (jxcdl.getJc() != null) {
|
||||
wrapper.eq(JXCDL::getJc, jxcdl.getJc());
|
||||
}
|
||||
}
|
||||
wrapper.orderByAsc(JXCDL::getRq, JXCDL::getJc);
|
||||
return wrapper;
|
||||
}
|
||||
}
|
||||
+90
@@ -0,0 +1,90 @@
|
||||
package com.roomroot.jwgl.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.roomroot.jwgl.entity.JSBKCB;
|
||||
import com.roomroot.jwgl.mapper.ClassRoomLessonMapper;
|
||||
import com.roomroot.jwgl.service.ClassRoomLessonService;
|
||||
import com.roomroot.jwgl.unit.PageQuery;
|
||||
import com.roomroot.jwgl.unit.PageResult;
|
||||
import com.roomroot.jwgl.utils.UuidUtil;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import jakarta.annotation.Resource;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 教室输出课程表服务实现类
|
||||
*/
|
||||
@Service
|
||||
public class ClassRoomJSBKCBServiceImpl implements ClassRoomLessonService {
|
||||
|
||||
@Resource
|
||||
private ClassRoomLessonMapper jsbkcbMapper;
|
||||
|
||||
@Override
|
||||
public void add(JSBKCB jsbkcb) {
|
||||
jsbkcb.setDelFlag(0);
|
||||
jsbkcb.setId(UuidUtil.getUUID());
|
||||
jsbkcb.setGxsj(LocalDateTime.now());
|
||||
jsbkcbMapper.insert(jsbkcb);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void delete(String id) {
|
||||
JSBKCB jsbkcb = getById(id);
|
||||
jsbkcb.setDelFlag(1);
|
||||
jsbkcbMapper.updateById(jsbkcb);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(JSBKCB jsbkcb) {
|
||||
jsbkcbMapper.updateById(jsbkcb);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JSBKCB getById(String id) {
|
||||
return jsbkcbMapper.selectById(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JSBKCB getByJsbhAndNd(String jsbh, Integer nd) {
|
||||
return jsbkcbMapper.selectByJsbhAndNd(jsbh, nd);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PageResult<JSBKCB> pageList(PageQuery query, JSBKCB jsbkcb) {
|
||||
jsbkcb.setDelFlag(0);
|
||||
Page<JSBKCB> page = new Page<>(query.getPageNum(), query.getPageSize());
|
||||
Page<JSBKCB> result = jsbkcbMapper.selectPageList(page, jsbkcb);
|
||||
return new PageResult<>(result.getRecords(), result.getTotal(),
|
||||
query.getPageNum(), query.getPageSize());
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<JSBKCB> list(JSBKCB jsbkcb) {
|
||||
LambdaQueryWrapper<JSBKCB> wrapper = buildQueryWrapper(jsbkcb);
|
||||
return jsbkcbMapper.selectList(wrapper);
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建查询条件
|
||||
*/
|
||||
private LambdaQueryWrapper<JSBKCB> buildQueryWrapper(JSBKCB jsbkcb) {
|
||||
LambdaQueryWrapper<JSBKCB> wrapper = new LambdaQueryWrapper<>();
|
||||
if (jsbkcb != null) {
|
||||
if (jsbkcb.getNd() != null) {
|
||||
wrapper.eq(JSBKCB::getNd, jsbkcb.getNd());
|
||||
}
|
||||
if (jsbkcb.getJsbh() != null && !jsbkcb.getJsbh().isEmpty()) {
|
||||
wrapper.like(JSBKCB::getJsbh, jsbkcb.getJsbh());
|
||||
}
|
||||
if (jsbkcb.getYkb() != null) {
|
||||
wrapper.eq(JSBKCB::getYkb, jsbkcb.getYkb());
|
||||
}
|
||||
}
|
||||
wrapper.orderByDesc(JSBKCB::getGxsj);
|
||||
return wrapper;
|
||||
}
|
||||
}
|
||||
+97
@@ -0,0 +1,97 @@
|
||||
package com.roomroot.jwgl.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.roomroot.jwgl.entity.JSB;
|
||||
import com.roomroot.jwgl.mapper.ClassRoomMapper;
|
||||
import com.roomroot.jwgl.service.ClassRoomService;
|
||||
import com.roomroot.jwgl.unit.PageQuery;
|
||||
import com.roomroot.jwgl.unit.PageResult;
|
||||
import com.roomroot.jwgl.utils.UuidUtil;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import jakarta.annotation.Resource;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 教室表服务实现类
|
||||
*/
|
||||
@Service
|
||||
public class ClassRoomServiceImpl implements ClassRoomService {
|
||||
|
||||
@Resource
|
||||
private ClassRoomMapper jsbMapper;
|
||||
|
||||
@Override
|
||||
public void add(JSB jsb) {
|
||||
jsb.setId(UuidUtil.getUUID());
|
||||
jsb.setDelFlag(0);
|
||||
jsbMapper.insert(jsb);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void delete(String id) {
|
||||
JSB jsb = getById(id);
|
||||
jsb.setDelFlag(1);
|
||||
jsbMapper.updateById(jsb);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(JSB jsb) {
|
||||
jsbMapper.updateById(jsb);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JSB getById(String id) {
|
||||
return jsbMapper.selectById(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PageResult<JSB> pageList(PageQuery query, JSB jsb) {
|
||||
Page<JSB> page = new Page<>(query.getPageNum(), query.getPageSize());
|
||||
jsb.setDelFlag(0);
|
||||
Page<JSB> result = jsbMapper.selectPageList(page, jsb);
|
||||
return new PageResult<>(result.getRecords(), result.getTotal(),
|
||||
query.getPageNum(), query.getPageSize());
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<JSB> list(JSB jsb) {
|
||||
LambdaQueryWrapper<JSB> wrapper = buildQueryWrapper(jsb);
|
||||
return jsbMapper.selectList(wrapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<JSB> listByJxldh(String jxldh) {
|
||||
LambdaQueryWrapper<JSB> wrapper = new LambdaQueryWrapper<>();
|
||||
wrapper.eq(JSB::getJxldh, jxldh);
|
||||
wrapper.orderByAsc(JSB::getXh);
|
||||
return jsbMapper.selectList(wrapper);
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建查询条件
|
||||
*/
|
||||
private LambdaQueryWrapper<JSB> buildQueryWrapper(JSB jsb) {
|
||||
LambdaQueryWrapper<JSB> wrapper = new LambdaQueryWrapper<>();
|
||||
if (jsb != null) {
|
||||
if (jsb.getJsbh() != null && !jsb.getJsbh().isEmpty()) {
|
||||
wrapper.like(JSB::getJsbh, jsb.getJsbh());
|
||||
}
|
||||
if (jsb.getJsmc() != null && !jsb.getJsmc().isEmpty()) {
|
||||
wrapper.like(JSB::getJsmc, jsb.getJsmc());
|
||||
}
|
||||
if (jsb.getJxldh() != null && !jsb.getJxldh().isEmpty()) {
|
||||
wrapper.eq(JSB::getJxldh, jsb.getJxldh());
|
||||
}
|
||||
if (jsb.getJxcdlx() != null && !jsb.getJxcdlx().isEmpty()) {
|
||||
wrapper.eq(JSB::getJxcdlx, jsb.getJxcdlx());
|
||||
}
|
||||
if (jsb.getTy() != null) {
|
||||
wrapper.eq(JSB::getTy, jsb.getTy());
|
||||
}
|
||||
}
|
||||
wrapper.orderByAsc(JSB::getXh);
|
||||
return wrapper;
|
||||
}
|
||||
}
|
||||
+206
@@ -0,0 +1,206 @@
|
||||
package com.roomroot.jwgl.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.roomroot.jwgl.entity.XYDNDXQJBXXB;
|
||||
import com.roomroot.jwgl.entity.XYDRWB;
|
||||
import com.roomroot.jwgl.mapper.ClassSemesterCalendarMapper;
|
||||
import com.roomroot.jwgl.mapper.ClassSemesterMapper;
|
||||
import com.roomroot.jwgl.service.ClassSemesterCalendarService;
|
||||
import com.roomroot.jwgl.utils.UuidUtil;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
import jakarta.annotation.Resource;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* 学员队任务表服务实现类
|
||||
*/
|
||||
@Service
|
||||
public class ClassSemesterCalendarServiceImpl implements ClassSemesterCalendarService {
|
||||
|
||||
@Resource
|
||||
private ClassSemesterCalendarMapper classSemesterCalendarMapper;
|
||||
|
||||
@Resource
|
||||
private ClassSemesterMapper classSemesterMapper;
|
||||
|
||||
@Override
|
||||
public void update(XYDRWB xydrwb) {
|
||||
classSemesterCalendarMapper.updateById(xydrwb);
|
||||
}
|
||||
|
||||
@Override
|
||||
public XYDRWB getByBh(String bh) {
|
||||
return classSemesterCalendarMapper.selectById(bh);
|
||||
}
|
||||
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
@Override
|
||||
public Map<String, Object> batchCopy(List<String> sourceBhList, List<String> targetBhList) {
|
||||
List<String> failedSourceBhs = new ArrayList<>();
|
||||
List<String> failedTargetBhs = new ArrayList<>();
|
||||
int count = 0;
|
||||
|
||||
for (String targetBh : targetBhList) {
|
||||
// 根据目标学员队期表编号,获取学员队期表的学员队编号
|
||||
XYDNDXQJBXXB targetSemester = classSemesterMapper.selectById(targetBh);
|
||||
if (targetSemester == null) {
|
||||
failedTargetBhs.add(targetBh);
|
||||
continue;
|
||||
}
|
||||
String newXydbh = targetSemester.getXydbh();
|
||||
|
||||
for (String sourceBh : sourceBhList) {
|
||||
XYDRWB source = classSemesterCalendarMapper.selectById(sourceBh);
|
||||
if (source == null) {
|
||||
if (!failedSourceBhs.contains(sourceBh)) {
|
||||
failedSourceBhs.add(sourceBh);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
// 复制源记录,替换编号、学员队学期编号和学员队编号
|
||||
XYDRWB newRecord = new XYDRWB();
|
||||
newRecord.setBh(UuidUtil.getUUID());
|
||||
newRecord.setNd(source.getNd());
|
||||
newRecord.setXydbh(newXydbh);
|
||||
newRecord.setKbh(source.getKbh());
|
||||
newRecord.setXqdc(source.getXqdc());
|
||||
newRecord.setJybh(source.getJybh());
|
||||
newRecord.setKcxh(source.getKcxh());
|
||||
newRecord.setJsbh(source.getJsbh());
|
||||
newRecord.setRs(source.getRs());
|
||||
newRecord.setZks(source.getZks());
|
||||
newRecord.setXs(source.getXs());
|
||||
newRecord.setKlx(source.getKlx());
|
||||
newRecord.setJc(source.getJc());
|
||||
newRecord.setKsdd(source.getKsdd());
|
||||
newRecord.setKsbh(source.getKsbh());
|
||||
newRecord.setXz(source.getXz());
|
||||
newRecord.setJysdh(source.getJysdh());
|
||||
newRecord.setJysjhjybh(source.getJysjhjybh());
|
||||
newRecord.setJysjhbz(source.getJysjhbz());
|
||||
newRecord.setJhkcxh(source.getJhkcxh());
|
||||
newRecord.setXhbs(source.getXhbs());
|
||||
newRecord.setXydxqbh(targetBh);
|
||||
newRecord.setBz(source.getBz());
|
||||
newRecord.setXf(source.getXf());
|
||||
newRecord.setKsks(source.getKsks());
|
||||
newRecord.setBz2(source.getBz2());
|
||||
newRecord.setCjfz(source.getCjfz());
|
||||
newRecord.setBjrxypjf(source.getBjrxypjf());
|
||||
newRecord.setLlxs(source.getLlxs());
|
||||
newRecord.setSjxs(source.getSjxs());
|
||||
newRecord.setKsksbxs(source.getKsksbxs());
|
||||
newRecord.setPdxh(source.getPdxh());
|
||||
newRecord.setPdqsz(source.getPdqsz());
|
||||
newRecord.setPdaz(source.getPdaz());
|
||||
newRecord.setPdzzksj(source.getPdzzksj());
|
||||
newRecord.setPdbz(source.getPdbz());
|
||||
newRecord.setPdtbykxxbz(source.getPdtbykxxbz());
|
||||
newRecord.setPdzdyxsfbsj(source.getPdzdyxsfbsj());
|
||||
newRecord.setPdqyzdyxs(source.getPdqyzdyxs());
|
||||
newRecord.setDelFlag(0);
|
||||
|
||||
classSemesterCalendarMapper.insert(newRecord);
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
Map<String, Object> result = new HashMap<>();
|
||||
result.put("count", count);
|
||||
result.put("failedSourceBhs", failedSourceBhs);
|
||||
result.put("failedTargetBhs", failedTargetBhs);
|
||||
return result;
|
||||
}
|
||||
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
@Override
|
||||
public Map<String, Object> batchCopyBySemester(String sourceXydxqbh, List<String> targetBhList) {
|
||||
List<String> failedTargetBhs = new ArrayList<>();
|
||||
int count = 0;
|
||||
|
||||
// 查询源学员队期表编号下的所有任务条目
|
||||
LambdaQueryWrapper<XYDRWB> queryWrapper = new LambdaQueryWrapper<>();
|
||||
queryWrapper.eq(XYDRWB::getXydxqbh, sourceXydxqbh)
|
||||
.eq(XYDRWB::getDelFlag, 0);
|
||||
List<XYDRWB> sourceList = classSemesterCalendarMapper.selectList(queryWrapper);
|
||||
|
||||
if (CollectionUtils.isEmpty(sourceList) || CollectionUtils.isEmpty(targetBhList)) {
|
||||
Map<String, Object> result = new HashMap<>();
|
||||
result.put("count", 0);
|
||||
result.put("failedTargetBhs", failedTargetBhs);
|
||||
return result;
|
||||
}
|
||||
|
||||
for (String targetBh : targetBhList) {
|
||||
// 根据目标学员队期表编号,获取学员队期表的学员队编号
|
||||
XYDNDXQJBXXB targetSemester = classSemesterMapper.selectById(targetBh);
|
||||
if (targetSemester == null) {
|
||||
failedTargetBhs.add(targetBh);
|
||||
continue;
|
||||
}
|
||||
String newXydbh = targetSemester.getXydbh();
|
||||
|
||||
for (XYDRWB source : sourceList) {
|
||||
XYDRWB newRecord = new XYDRWB();
|
||||
newRecord.setBh(UuidUtil.getUUID());
|
||||
newRecord.setNd(source.getNd());
|
||||
newRecord.setXydbh(newXydbh);
|
||||
newRecord.setKbh(source.getKbh());
|
||||
newRecord.setXqdc(source.getXqdc());
|
||||
newRecord.setJybh(source.getJybh());
|
||||
newRecord.setKcxh(source.getKcxh());
|
||||
newRecord.setJsbh(source.getJsbh());
|
||||
newRecord.setRs(source.getRs());
|
||||
newRecord.setZks(source.getZks());
|
||||
newRecord.setXs(source.getXs());
|
||||
newRecord.setKlx(source.getKlx());
|
||||
newRecord.setJc(source.getJc());
|
||||
newRecord.setKsdd(source.getKsdd());
|
||||
newRecord.setKsbh(source.getKsbh());
|
||||
newRecord.setXz(source.getXz());
|
||||
newRecord.setJysdh(source.getJysdh());
|
||||
newRecord.setJysjhjybh(source.getJysjhjybh());
|
||||
newRecord.setJysjhbz(source.getJysjhbz());
|
||||
newRecord.setJhkcxh(source.getJhkcxh());
|
||||
newRecord.setXhbs(source.getXhbs());
|
||||
newRecord.setXydxqbh(targetBh);
|
||||
newRecord.setBz(source.getBz());
|
||||
newRecord.setXf(source.getXf());
|
||||
newRecord.setKsks(source.getKsks());
|
||||
newRecord.setBz2(source.getBz2());
|
||||
newRecord.setCjfz(source.getCjfz());
|
||||
newRecord.setBjrxypjf(source.getBjrxypjf());
|
||||
newRecord.setLlxs(source.getLlxs());
|
||||
newRecord.setSjxs(source.getSjxs());
|
||||
newRecord.setKsksbxs(source.getKsksbxs());
|
||||
newRecord.setPdxh(source.getPdxh());
|
||||
newRecord.setPdqsz(source.getPdqsz());
|
||||
newRecord.setPdaz(source.getPdaz());
|
||||
newRecord.setPdzzksj(source.getPdzzksj());
|
||||
newRecord.setPdbz(source.getPdbz());
|
||||
newRecord.setPdtbykxxbz(source.getPdtbykxxbz());
|
||||
newRecord.setPdzdyxsfbsj(source.getPdzdyxsfbsj());
|
||||
newRecord.setPdqyzdyxs(source.getPdqyzdyxs());
|
||||
newRecord.setDelFlag(0);
|
||||
|
||||
classSemesterCalendarMapper.insert(newRecord);
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
Map<String, Object> result = new HashMap<>();
|
||||
result.put("count", count);
|
||||
result.put("failedTargetBhs", failedTargetBhs);
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<XYDRWB> listAllValid(XYDRWB xydrwb) {
|
||||
xydrwb.setDelFlag(0);
|
||||
return classSemesterCalendarMapper.selectAllValid(xydrwb);
|
||||
}
|
||||
}
|
||||
+253
@@ -0,0 +1,253 @@
|
||||
package com.roomroot.jwgl.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.roomroot.jwgl.entity.XYDNDXQJBXXB;
|
||||
import com.roomroot.jwgl.entity.XYDB;
|
||||
import com.roomroot.jwgl.mapper.ClassSemesterCalendarMapper;
|
||||
import com.roomroot.jwgl.mapper.ClassSemesterMapper;
|
||||
import com.roomroot.jwgl.mapper.SemesterCalendarMapper;
|
||||
import com.roomroot.jwgl.service.ClassSemesterService;
|
||||
import com.roomroot.jwgl.service.ElectiveService;
|
||||
import com.roomroot.jwgl.unit.PageQuery;
|
||||
import com.roomroot.jwgl.unit.PageResult;
|
||||
import com.roomroot.jwgl.utils.UuidUtil;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
import jakarta.annotation.Resource;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 班次学期服务实现类
|
||||
*/
|
||||
@Service
|
||||
public class ClassSemesterServiceImpl implements ClassSemesterService {
|
||||
|
||||
@Resource
|
||||
private ClassSemesterMapper classSemesterMapper;
|
||||
|
||||
@Resource
|
||||
SemesterCalendarMapper semesterCalendarMapper;
|
||||
|
||||
@Resource
|
||||
ClassSemesterCalendarMapper classSemesterCalendarMapper;
|
||||
|
||||
@Resource
|
||||
private ElectiveService electiveService;
|
||||
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
@Override
|
||||
public void add(XYDNDXQJBXXB xydndxqjbxxb) {
|
||||
String uuid = UuidUtil.getUUID();
|
||||
xydndxqjbxxb.setBh(uuid);
|
||||
xydndxqjbxxb.setDelFlag(0);
|
||||
int insert = classSemesterMapper.insert(xydndxqjbxxb);
|
||||
}
|
||||
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
@Override
|
||||
public void delete(String bh) {
|
||||
XYDNDXQJBXXB xydndxqjbxxb = getByBh(bh);
|
||||
xydndxqjbxxb.setDelFlag(1);
|
||||
classSemesterMapper.updateById(xydndxqjbxxb);
|
||||
classSemesterCalendarMapper.deleteByBcxqBh(bh);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void batchDelete(List<String> bhList) {
|
||||
for (String bh : bhList) {
|
||||
XYDNDXQJBXXB xydndxqjbxxb = getByBh(bh);
|
||||
if (xydndxqjbxxb != null) {
|
||||
xydndxqjbxxb.setDelFlag(1);
|
||||
classSemesterMapper.updateById(xydndxqjbxxb);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(XYDNDXQJBXXB xydndxqjbxxb) {
|
||||
classSemesterMapper.updateById(xydndxqjbxxb);
|
||||
}
|
||||
|
||||
@Override
|
||||
public XYDNDXQJBXXB getByBh(String bh) {
|
||||
return classSemesterMapper.selectById(bh);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PageResult<XYDNDXQJBXXB> pageList(PageQuery query, XYDNDXQJBXXB xydndxqjbxxb) {
|
||||
xydndxqjbxxb.setDelFlag(0);
|
||||
Page<XYDNDXQJBXXB> page = new Page<>(query.getPageNum(), query.getPageSize());
|
||||
Page<XYDNDXQJBXXB> result = classSemesterMapper.selectPageList(page, xydndxqjbxxb);
|
||||
return new PageResult<>(result.getRecords(), result.getTotal(),
|
||||
query.getPageNum(), query.getPageSize());
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<XYDNDXQJBXXB> listAllValid() {
|
||||
return classSemesterMapper.selectAllValid();
|
||||
}
|
||||
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
@Override
|
||||
public int batchAddFromElective(LocalDateTime startTime, LocalDateTime endTime,
|
||||
String nd, String xqdc, String xqkssj, String xqjssj) {
|
||||
// 调用filterByDateRange获取符合条件的学员队列表
|
||||
List<XYDB> xydbList = electiveService.filterByDateRange(startTime, endTime);
|
||||
|
||||
if (CollectionUtils.isEmpty(xydbList)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int count = 0;
|
||||
for (XYDB xydb : xydbList) {
|
||||
// 校验是否已存在:根据班次编号、年度、学期第次查询
|
||||
XYDNDXQJBXXB existing = classSemesterMapper.selectByBcAndNdAndXqdc(xydb.getXydbh(), nd, xqdc);
|
||||
if (existing != null) {
|
||||
// 已存在,跳过
|
||||
continue;
|
||||
}
|
||||
|
||||
// 创建学员队年度学期基本信息
|
||||
XYDNDXQJBXXB xydndxqjbxxb = new XYDNDXQJBXXB();
|
||||
String uuid = UuidUtil.getUUID();
|
||||
xydndxqjbxxb.setBh(uuid);
|
||||
xydndxqjbxxb.setXydbh(xydb.getXydbh());
|
||||
xydndxqjbxxb.setNd(Integer.valueOf(nd));
|
||||
if("春季学期".equals(xqdc)){
|
||||
xqdc = "1";
|
||||
} else if("夏季学期".equals(xqdc)){
|
||||
xqdc = "2";
|
||||
} else if("秋季学期".equals(xqdc)){
|
||||
xqdc = "3";
|
||||
}
|
||||
xydndxqjbxxb.setXhbs(0);
|
||||
xydndxqjbxxb.setXqdc(Integer.valueOf(xqdc));
|
||||
xydndxqjbxxb.setKxrq(LocalDate.parse(xqkssj));
|
||||
xydndxqjbxxb.setJsrq(LocalDate.parse(xqjssj));
|
||||
xydndxqjbxxb.setYsbbh(0);
|
||||
xydndxqjbxxb.setJclb("双节次");
|
||||
xydndxqjbxxb.setXtms("");
|
||||
xydndxqjbxxb.setKfjypk(0);
|
||||
xydndxqjbxxb.setDelFlag(0);
|
||||
|
||||
int insert = classSemesterMapper.insert(xydndxqjbxxb);
|
||||
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int batchUpdateKfjypk(List<String> bhList, Integer kfjypk) {
|
||||
if (CollectionUtils.isEmpty(bhList)) {
|
||||
return 0;
|
||||
}
|
||||
int count = 0;
|
||||
for (String bh : bhList) {
|
||||
XYDNDXQJBXXB xydndxqjbxxb = classSemesterMapper.selectById(bh);
|
||||
if (xydndxqjbxxb != null) {
|
||||
xydndxqjbxxb.setKfjypk(kfjypk);
|
||||
classSemesterMapper.updateById(xydndxqjbxxb);
|
||||
count++;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int batchUpdateXqdc(List<String> bhList, Integer xqdc) {
|
||||
if (CollectionUtils.isEmpty(bhList)) {
|
||||
return 0;
|
||||
}
|
||||
int count = 0;
|
||||
for (String bh : bhList) {
|
||||
XYDNDXQJBXXB xydndxqjbxxb = classSemesterMapper.selectById(bh);
|
||||
if (xydndxqjbxxb != null) {
|
||||
xydndxqjbxxb.setXqdc(xqdc);
|
||||
classSemesterMapper.updateById(xydndxqjbxxb);
|
||||
count++;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int batchUpdateJxrwbh(List<String> bhList, String jxrwbh) {
|
||||
if (CollectionUtils.isEmpty(bhList)) {
|
||||
return 0;
|
||||
}
|
||||
int count = 0;
|
||||
for (String bh : bhList) {
|
||||
XYDNDXQJBXXB xydndxqjbxxb = classSemesterMapper.selectById(bh);
|
||||
if (xydndxqjbxxb != null) {
|
||||
xydndxqjbxxb.setJxrwbh(jxrwbh);
|
||||
classSemesterMapper.updateById(xydndxqjbxxb);
|
||||
count++;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
@Override
|
||||
public int batchUpdateDateRange(List<String> bhList, String xqkssj, String xqjssj) {
|
||||
if (CollectionUtils.isEmpty(bhList)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int count = 0;
|
||||
for (String bh : bhList) {
|
||||
// 查询学员队年度学期基本信息
|
||||
XYDNDXQJBXXB xydndxqjbxxb = classSemesterMapper.selectById(bh);
|
||||
if (xydndxqjbxxb == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// 更新日期范围
|
||||
xydndxqjbxxb.setKxrq(LocalDate.parse(xqkssj));
|
||||
xydndxqjbxxb.setJsrq(LocalDate.parse(xqjssj));
|
||||
classSemesterMapper.updateById(xydndxqjbxxb);
|
||||
|
||||
// // 删除日期范围之外的日历记录
|
||||
// classSemesterCalendarMapper.deleteOutsideDateRange(bh, xqkssj, xqjssj);
|
||||
//
|
||||
// // 查询现有任务记录
|
||||
// List<XYDRWB> existingCalendar = classSemesterCalendarMapper.selectByBcxqbhAndDateRange(bh, xqkssj, xqjssj);
|
||||
//
|
||||
// // 查询学期校历,用于补充缺少的记录
|
||||
// String kxrqStr = xydndxqjbxxb.getKxrq() != null ? xydndxqjbxxb.getKxrq().toString() : xqkssj;
|
||||
// String jsrqStr = xydndxqjbxxb.getJsrq() != null ? xydndxqjbxxb.getJsrq().toString() : xqjssj;
|
||||
// List<XQXLB> xqxlbs = semesterCalendarMapper.selectByNdAndJqsjRange(xydndxqjbxxb.getNd(), kxrqStr, jsrqStr);
|
||||
//
|
||||
// if (!CollectionUtils.isEmpty(xqxlbs)) {
|
||||
// // 提取已有编号
|
||||
// java.util.Set<String> existingBhs = new java.util.HashSet<>();
|
||||
// for (XYDRWB cal : existingCalendar) {
|
||||
// existingBhs.add(cal.getBh());
|
||||
// }
|
||||
//
|
||||
// // 补充缺少的记录
|
||||
// for (XQXLB xqxlb : xqxlbs) {
|
||||
// XYDRWB xydrwb = new XYDRWB();
|
||||
// String newBh = UuidUtil.getUUID();
|
||||
// if (!existingBhs.contains(newBh)) {
|
||||
// xydrwb.setBh(newBh);
|
||||
// xydrwb.setNd(xydndxqjbxxb.getNd());
|
||||
// xydrwb.setXydbh(xydndxqjbxxb.getXydbh());
|
||||
// xydrwb.setXqdc(xydndxqjbxxb.getXqdc());
|
||||
// xydrwb.setXydxqbh(bh);
|
||||
// xydrwb.setDelFlag(0);
|
||||
// classSemesterCalendarMapper.insert(xydrwb);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// count++;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
}
|
||||
+3025
File diff suppressed because it is too large
Load Diff
+111
@@ -0,0 +1,111 @@
|
||||
package com.roomroot.jwgl.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.roomroot.jwgl.entity.KCBZ;
|
||||
import com.roomroot.jwgl.entity.KTBZ;
|
||||
import com.roomroot.jwgl.mapper.KCBZMapper;
|
||||
import com.roomroot.jwgl.mapper.KTBZMapper;
|
||||
import com.roomroot.jwgl.service.CourseTeachingService;
|
||||
import com.roomroot.jwgl.unit.PageQuery;
|
||||
import com.roomroot.jwgl.unit.PageResult;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import jakarta.annotation.Resource;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 课程教学管理服务实现类
|
||||
* <p>
|
||||
* 实现课程标准的增删改查、多版本管理及自动生成。
|
||||
* 删除逻辑:填写撤回原因(非空=已撤回),不物理删除。
|
||||
* 查询仅返回未撤回(撤回原因为空)的数据。
|
||||
* </p>
|
||||
*/
|
||||
@Service
|
||||
public class CourseTeachingServiceImpl implements CourseTeachingService {
|
||||
|
||||
@Resource
|
||||
private KCBZMapper kcbzMapper;
|
||||
|
||||
@Resource
|
||||
private KTBZMapper ktbzMapper;
|
||||
|
||||
/** 填充课堂列表到课程标准 */
|
||||
private void fillKtList(KCBZ kcbz) {
|
||||
if (kcbz == null) return;
|
||||
List<KTBZ> ktList = ktbzMapper.selectByKcbh(kcbz.getBh());
|
||||
kcbz.setKtList(ktList != null ? ktList : new ArrayList<>());
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public void add(KCBZ kcbz) {
|
||||
kcbz.setChyy(null);
|
||||
kcbzMapper.insert(kcbz);
|
||||
List<KTBZ> ktList = kcbz.getKtList();
|
||||
if (ktList != null && !ktList.isEmpty()) {
|
||||
for (KTBZ kt : ktList) {
|
||||
kt.setKcbh(kcbz.getBh());
|
||||
ktbzMapper.insert(kt);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public void delete(String bh, String chyy) {
|
||||
KCBZ kcbz = new KCBZ();
|
||||
kcbz.setBh(bh);
|
||||
kcbz.setChyy(chyy);
|
||||
kcbzMapper.updateById(kcbz);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public void update(KCBZ kcbz) {
|
||||
kcbzMapper.updateById(kcbz);
|
||||
List<KTBZ> ktList = kcbz.getKtList();
|
||||
if (ktList != null && !ktList.isEmpty()) {
|
||||
for (KTBZ kt : ktList) {
|
||||
ktbzMapper.updateById(kt);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public KCBZ getById(String bh) {
|
||||
KCBZ kcbz = kcbzMapper.selectById(bh);
|
||||
fillKtList(kcbz);
|
||||
return kcbz;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PageResult<KCBZ> pageList(PageQuery query, KCBZ kcbz) {
|
||||
Page<KCBZ> page = new Page<>(query.getPageNum(), query.getPageSize());
|
||||
Page<KCBZ> result = kcbzMapper.selectPageList(page, kcbz);
|
||||
// 填充每项的课堂列表
|
||||
for (KCBZ item : result.getRecords()) {
|
||||
fillKtList(item);
|
||||
}
|
||||
return new PageResult<>(result.getRecords(), result.getTotal(),
|
||||
query.getPageNum(), query.getPageSize());
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<KCBZ> getVersionsByCourse(String kbh) {
|
||||
return kcbzMapper.selectVersionsByCourse(kbh);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public String generateFromCourse(String kbh) {
|
||||
KCBZ kcbz = new KCBZ();
|
||||
kcbz.setBh(kbh + "-STD");
|
||||
kcbz.setKbh(kbh);
|
||||
kcbz.setMc("课程标准-" + kbh);
|
||||
kcbzMapper.insert(kcbz);
|
||||
return kcbz.getBh();
|
||||
}
|
||||
}
|
||||
+942
@@ -0,0 +1,942 @@
|
||||
package com.roomroot.jwgl.service.impl;
|
||||
|
||||
import com.roomroot.jwgl.dto.department.DepartmentCreateDTO;
|
||||
import com.roomroot.jwgl.dto.department.DepartmentIdDTO;
|
||||
import com.roomroot.jwgl.dto.department.DepartmentQueryDTO;
|
||||
import com.roomroot.jwgl.dto.department.DepartmentUpdateDTO;
|
||||
import com.roomroot.jwgl.entity.SSJG;
|
||||
import com.roomroot.jwgl.mapper.SSJGMapper;
|
||||
import com.roomroot.jwgl.service.DepartmentManagementService;
|
||||
import com.roomroot.jwgl.unit.BusinessException;
|
||||
import com.roomroot.jwgl.utils.UuidUtil;
|
||||
import com.roomroot.jwgl.vo.department.DepartmentTreeVO;
|
||||
import com.roomroot.jwgl.vo.department.DepartmentVO;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.*;
|
||||
|
||||
import static com.roomroot.jwgl.utils.BasicManagementConstants.*;
|
||||
|
||||
/**
|
||||
* 部别管理服务实现。
|
||||
*/
|
||||
@Service
|
||||
public class DepartmentManagementServiceImpl implements DepartmentManagementService {
|
||||
|
||||
/** 部别管理数据访问对象。 */
|
||||
@Resource
|
||||
private SSJGMapper ssjgMapper;
|
||||
|
||||
/**
|
||||
* 新增部别。
|
||||
*
|
||||
* <p>处理顺序:校验参数、校验上级关系、校验同级重名、组装实体、
|
||||
* 写入数据库、重新查询并返回 VO。</p>
|
||||
*
|
||||
* @param dto 新增参数
|
||||
* @return 新增后的部别信息
|
||||
*/
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public DepartmentVO add(DepartmentCreateDTO dto) {
|
||||
// 第一步:防止业务层被直接调用时传入 null。
|
||||
if (dto == null) {
|
||||
throw new BusinessException(BAD_REQUEST, "新增参数不能为空");
|
||||
}
|
||||
|
||||
// 第二步:清理并校验数据库必填字段。
|
||||
String name = requireText(dto.getName(), "部别名称不能为空");
|
||||
String category = requireText(dto.getCategory(), "机关类别不能为空");
|
||||
|
||||
// 第三步:将空字符串形式的上级编号统一转换为 null,表示根节点。
|
||||
String parentId = normalizeText(dto.getParentId());
|
||||
|
||||
// 第四步:加载完整组织数据,用于检查上级节点和层级链路。
|
||||
List<SSJG> departments = selectAllDepartments();
|
||||
|
||||
// 第五步:确认上级存在、已启用,并且组织链路中不存在循环。
|
||||
validateParentChain(parentId, null, departments);
|
||||
|
||||
// 第六步:同一上级下不允许出现同名部别。
|
||||
ensureSiblingNameUnique(parentId, name, null);
|
||||
|
||||
/*
|
||||
* 第七步:将新增 DTO 转换为数据库实体。
|
||||
* Controller 和 Service 对外只使用 DTO/VO,SSJG 仅在持久层内部流转。
|
||||
*/
|
||||
SSJG department = new SSJG();
|
||||
department.setBH(UuidUtil.getOriginalUUID());
|
||||
department.setJGMC(name);
|
||||
department.setJGLB(category);
|
||||
department.setFLH(defaultClassificationCode(dto.getClassificationCode()));
|
||||
department.setFJH(defaultLevelNumber(dto.getLevelNumber()));
|
||||
department.setSJJGBH(parentId);
|
||||
department.setTY(false);
|
||||
department.setTYSJ(null);
|
||||
department.setJC(normalizeText(dto.getAbbreviation()));
|
||||
|
||||
// 第八步:执行新增,并校验数据库实际影响行数。
|
||||
if (ssjgMapper.insertDepartment(department) != 1) {
|
||||
throw new BusinessException("新增部别失败");
|
||||
}
|
||||
|
||||
// 第九步:重新查询数据库,返回包含上级名称等扩展字段的 VO。
|
||||
return loadDepartmentView(department.getBH());
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改部别。
|
||||
*
|
||||
* <p>处理顺序:校验编号和必填字段、校验新的上级关系、
|
||||
* 校验同级重名、组装更新实体、更新数据库、返回最新 VO。</p>
|
||||
*
|
||||
* @param dto 修改参数
|
||||
* @return 修改后的部别信息
|
||||
*/
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public DepartmentVO update(DepartmentUpdateDTO dto) {
|
||||
// 第一步:防止业务层被直接调用时传入 null。
|
||||
if (dto == null) {
|
||||
throw new BusinessException(BAD_REQUEST, "修改参数不能为空");
|
||||
}
|
||||
|
||||
// 第二步:校验部别编号,并确认待修改数据真实存在。
|
||||
String id = requireId(dto.getId());
|
||||
requireDepartment(id);
|
||||
|
||||
// 第三步:清理并校验数据库必填字段。
|
||||
String name = requireText(dto.getName(), "部别名称不能为空");
|
||||
String category = requireText(dto.getCategory(), "机关类别不能为空");
|
||||
|
||||
// 第四步:统一空上级编号的表达方式。
|
||||
String parentId = normalizeText(dto.getParentId());
|
||||
|
||||
// 第五步:读取完整组织结构,为移动节点校验提供数据。
|
||||
List<SSJG> departments = selectAllDepartments();
|
||||
|
||||
// 第六步:禁止选择自身或自身下级作为新的上级部别。
|
||||
validateParentChain(parentId, id, departments);
|
||||
|
||||
// 第七步:修改时排除自身,检查同一上级下是否存在其他同名部别。
|
||||
ensureSiblingNameUnique(parentId, name, id);
|
||||
|
||||
/*
|
||||
* 第八步:将修改 DTO 转换为更新实体。
|
||||
* 此处不设置停用字段,避免修改基本信息时意外改变启用状态。
|
||||
*/
|
||||
SSJG department = new SSJG();
|
||||
department.setBH(id);
|
||||
department.setJGMC(name);
|
||||
department.setJGLB(category);
|
||||
department.setFLH(defaultClassificationCode(dto.getClassificationCode()));
|
||||
department.setFJH(defaultLevelNumber(dto.getLevelNumber()));
|
||||
department.setSJJGBH(parentId);
|
||||
department.setJC(normalizeText(dto.getAbbreviation()));
|
||||
|
||||
// 第九步:更新基本信息,并校验数据库实际影响行数。
|
||||
if (ssjgMapper.updateDepartment(department) != 1) {
|
||||
throw new BusinessException("修改部别失败");
|
||||
}
|
||||
|
||||
// 第十步:重新查询并返回修改后的完整 VO。
|
||||
return loadDepartmentView(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询部别详情。
|
||||
*
|
||||
* @param dto 部别编号参数
|
||||
* @return 部别详情
|
||||
*/
|
||||
@Override
|
||||
public DepartmentVO get(DepartmentIdDTO dto) {
|
||||
// 第一步:兼容 dto 为 null 的直接调用场景,并校验编号。
|
||||
String id = requireId(dto == null ? null : dto.getId());
|
||||
|
||||
// 第二步:查询并组装包含上级名称和子节点标识的 VO。
|
||||
return loadDepartmentView(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询部别平铺列表。
|
||||
*
|
||||
* @param dto 查询条件
|
||||
* @return 排序后的部别列表
|
||||
*/
|
||||
@Override
|
||||
public List<DepartmentVO> list(DepartmentQueryDTO dto) {
|
||||
// 第一步:一次性读取全部部别,避免逐条查询形成 N+1 问题。
|
||||
List<SSJG> departments = selectAllDepartments();
|
||||
|
||||
// 第二步:建立编号索引,用于快速查找每个部别的上级名称。
|
||||
Map<String, SSJG> departmentMap = indexDepartments(departments);
|
||||
|
||||
// 第三步:收集被引用为上级的编号,用于计算 hasChildren。
|
||||
Set<String> parentIds = collectParentIds(departments);
|
||||
|
||||
// 第四步:创建最终返回列表。
|
||||
List<DepartmentVO> result = new ArrayList<>();
|
||||
|
||||
// 第五步:逐条应用查询条件,并将匹配实体转换为 VO。
|
||||
for (SSJG department : departments) {
|
||||
if (matches(department, dto)) {
|
||||
result.add(toDepartmentVO(department, departmentMap, parentIds));
|
||||
}
|
||||
}
|
||||
|
||||
// 第六步:按照分级号、分类号、名称依次排序。
|
||||
Collections.sort(result, new Comparator<DepartmentVO>() {
|
||||
@Override
|
||||
public int compare(DepartmentVO left, DepartmentVO right) {
|
||||
return compareDepartments(left, right);
|
||||
}
|
||||
});
|
||||
|
||||
// 第七步:返回平铺列表。
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询部别树。
|
||||
*
|
||||
* <p>查询条件命中子节点时,会同时保留该节点的所有祖先节点,
|
||||
* 从而保证前端仍能展示完整层级路径。</p>
|
||||
*
|
||||
* @param dto 查询条件
|
||||
* @return 排序后的部别树
|
||||
*/
|
||||
@Override
|
||||
public List<DepartmentTreeVO> tree(DepartmentQueryDTO dto) {
|
||||
// 第一步:读取全部部别,并建立编号到实体的索引。
|
||||
List<SSJG> departments = selectAllDepartments();
|
||||
Map<String, SSJG> departmentMap = indexDepartments(departments);
|
||||
|
||||
// 第二步:在构建树前检测数据库中的异常循环关系,避免无限递归。
|
||||
ensureTreeHasNoCycle(departments, departmentMap);
|
||||
|
||||
// 第三步:计算所有需要展示的节点编号,包括匹配节点及其祖先。
|
||||
Set<String> includedIds = collectIncludedTreeIds(departments, departmentMap, dto);
|
||||
|
||||
// 第四步:收集全部上级编号,用于设置节点的 hasChildren 字段。
|
||||
Set<String> parentIds = collectParentIds(departments);
|
||||
|
||||
// 第五步:建立树节点索引,后续可通过编号快速挂接父子关系。
|
||||
Map<String, DepartmentTreeVO> nodeMap = new HashMap<>();
|
||||
|
||||
// 第六步:只为需要展示的实体创建树节点。
|
||||
for (SSJG department : departments) {
|
||||
if (includedIds.contains(department.getBH())) {
|
||||
DepartmentVO departmentVO = toDepartmentVO(department, departmentMap, parentIds);
|
||||
nodeMap.put(department.getBH(), toTreeVO(departmentVO));
|
||||
}
|
||||
}
|
||||
|
||||
// 第七步:创建根节点集合。
|
||||
List<DepartmentTreeVO> roots = new ArrayList<>();
|
||||
|
||||
/*
|
||||
* 第八步:逐个挂接节点。
|
||||
* 展示集合中不存在上级节点时,将当前节点视为根节点;
|
||||
* 否则加入对应上级节点的 children 集合。
|
||||
*/
|
||||
for (SSJG department : departments) {
|
||||
DepartmentTreeVO node = nodeMap.get(department.getBH());
|
||||
if (node == null) {
|
||||
continue;
|
||||
}
|
||||
String parentId = normalizeText(department.getSJJGBH());
|
||||
DepartmentTreeVO parent = nodeMap.get(parentId);
|
||||
if (parent == null) {
|
||||
roots.add(node);
|
||||
} else {
|
||||
parent.getChildren().add(node);
|
||||
}
|
||||
}
|
||||
|
||||
// 第九步:递归排序根节点及所有层级的子节点。
|
||||
sortTree(roots);
|
||||
|
||||
// 第十步:返回完整树形结果。
|
||||
return roots;
|
||||
}
|
||||
|
||||
/**
|
||||
* 停用部别。
|
||||
*
|
||||
* <p>停用前必须确认不存在启用中的直接下级部别,
|
||||
* 并且不存在教研室、学员队、机关参谋或教学管理机构引用。</p>
|
||||
*
|
||||
* @param dto 部别编号参数
|
||||
* @return 停用后的部别信息
|
||||
*/
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public DepartmentVO disable(DepartmentIdDTO dto) {
|
||||
// 第一步:校验编号并查询待停用部别。
|
||||
String id = requireId(dto == null ? null : dto.getId());
|
||||
SSJG department = requireDepartment(id);
|
||||
|
||||
// 第二步:已停用时直接返回,保证接口幂等。
|
||||
if (Boolean.TRUE.equals(department.getTY())) {
|
||||
return loadDepartmentView(id);
|
||||
}
|
||||
|
||||
// 第三步:存在启用中的直接下级部别时,不允许停用当前部别。
|
||||
if (ssjgMapper.countActiveChildren(id) > 0) {
|
||||
throw new BusinessException(CONFLICT, "该部别存在启用中的下级部别,不能停用");
|
||||
}
|
||||
|
||||
// 第四步:存在其他业务数据引用时,不允许停用当前部别。
|
||||
if (ssjgMapper.countDepartmentReferences(id) > 0) {
|
||||
throw new BusinessException(CONFLICT,
|
||||
"该部别已被人员、教研室、学员队或教学管理机构引用,不能停用");
|
||||
}
|
||||
|
||||
// 第五步:将停用标志设为 true,并记录当前停用时间。
|
||||
if (ssjgMapper.updateDepartmentStatus(id, true, LocalDateTime.now()) != 1) {
|
||||
throw new BusinessException("停用部别失败");
|
||||
}
|
||||
|
||||
// 第六步:重新查询并返回停用后的最新状态。
|
||||
return loadDepartmentView(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* 启用部别。
|
||||
*
|
||||
* <p>启用前会检查上级及所有祖先部别均存在且处于启用状态。</p>
|
||||
*
|
||||
* @param dto 部别编号参数
|
||||
* @return 启用后的部别信息
|
||||
*/
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public DepartmentVO enable(DepartmentIdDTO dto) {
|
||||
// 第一步:校验编号并查询待启用部别。
|
||||
String id = requireId(dto == null ? null : dto.getId());
|
||||
SSJG department = requireDepartment(id);
|
||||
|
||||
// 第二步:已启用时直接返回,保证接口幂等。
|
||||
if (!Boolean.TRUE.equals(department.getTY())) {
|
||||
return loadDepartmentView(id);
|
||||
}
|
||||
|
||||
// 第三步:加载组织结构,检查上级链路的完整性和启用状态。
|
||||
List<SSJG> departments = selectAllDepartments();
|
||||
validateParentChain(normalizeText(department.getSJJGBH()), id, departments);
|
||||
|
||||
// 第四步:清除停用标志和停用时间。
|
||||
if (ssjgMapper.updateDepartmentStatus(id, false, null) != 1) {
|
||||
throw new BusinessException("启用部别失败");
|
||||
}
|
||||
|
||||
// 第五步:重新查询并返回启用后的最新状态。
|
||||
return loadDepartmentView(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除部别(逻辑删除)。
|
||||
*
|
||||
* <p>删除前必须确认不存在任何下级部别,
|
||||
* 并且不存在教研室、学员队、机关参谋或教学管理机构引用。
|
||||
* 逻辑删除后部别不再出现在列表和树形结构中。</p>
|
||||
*
|
||||
* @param dto 部别编号参数
|
||||
* @return 被删除的部别信息
|
||||
*/
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public DepartmentVO delete(DepartmentIdDTO dto) {
|
||||
// 第一步:校验编号并查询待删除部别。
|
||||
String id = requireId(dto == null ? null : dto.getId());
|
||||
SSJG department = requireDepartment(id);
|
||||
|
||||
// 第二步:删除前先构造返回 VO(逻辑删除后查不到数据)。
|
||||
List<SSJG> departments = selectAllDepartments();
|
||||
DepartmentVO vo = toDepartmentVO(
|
||||
department, indexDepartments(departments), collectParentIds(departments));
|
||||
|
||||
// 第三步:存在任何下级部别时,不允许删除当前部别。
|
||||
// 与停用不同,删除要求所有子部别先被删除,而非仅停用。
|
||||
for (SSJG child : departments) {
|
||||
if (id.equals(child.getSJJGBH())) {
|
||||
throw new BusinessException(CONFLICT, "该部别存在下级部别,请先删除下级部别");
|
||||
}
|
||||
}
|
||||
|
||||
// 第四步:存在其他业务数据引用时,不允许删除当前部别。
|
||||
if (ssjgMapper.countDepartmentReferences(id) > 0) {
|
||||
throw new BusinessException(CONFLICT,
|
||||
"该部别已被人员、教研室、学员队或教学管理机构引用,不能删除");
|
||||
}
|
||||
|
||||
// 第五步:执行逻辑删除,将 DEL_FLAG 置为 1。
|
||||
if (ssjgMapper.deleteDepartmentLogically(id) != 1) {
|
||||
throw new BusinessException("删除部别失败");
|
||||
}
|
||||
|
||||
// 第六步:返回删除前的部别信息。
|
||||
return vo;
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询部别并转换为详情 VO。
|
||||
*
|
||||
* @param id 部别编号
|
||||
* @return 部别详情 VO
|
||||
*/
|
||||
private DepartmentVO loadDepartmentView(String id) {
|
||||
// 第一步:查询目标部别,不存在时统一抛出业务异常。
|
||||
SSJG department = requireDepartment(id);
|
||||
|
||||
// 第二步:读取组织数据,为上级名称和子节点标识提供上下文。
|
||||
List<SSJG> departments = selectAllDepartments();
|
||||
|
||||
// 第三步:将实体转换为对外返回的 VO。
|
||||
return toDepartmentVO(department, indexDepartments(departments), collectParentIds(departments));
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询必然存在的部别。
|
||||
*
|
||||
* @param id 部别编号
|
||||
* @return 部别实体
|
||||
*/
|
||||
private SSJG requireDepartment(String id) {
|
||||
// 根据唯一编号查询数据库。
|
||||
SSJG department = ssjgMapper.selectDepartmentById(id);
|
||||
|
||||
// 未查询到数据时返回明确的 404 业务错误。
|
||||
if (department == null) {
|
||||
throw new BusinessException(NOT_FOUND, "部别不存在");
|
||||
}
|
||||
|
||||
// 返回已确认存在的部别实体。
|
||||
return department;
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询全部部别,并统一处理 Mapper 返回 null 的情况。
|
||||
*
|
||||
* @return 非 null 的部别集合
|
||||
*/
|
||||
private List<SSJG> selectAllDepartments() {
|
||||
// 调用 Mapper 获取全部部别。
|
||||
List<SSJG> departments = ssjgMapper.selectAllDepartments();
|
||||
|
||||
// Mapper 返回 null 时改为空集合,减少后续判空分支。
|
||||
return departments == null ? Collections.<SSJG>emptyList() : departments;
|
||||
}
|
||||
|
||||
/**
|
||||
* 校验同一上级下的部别名称唯一性。
|
||||
*
|
||||
* @param parentId 上级部别编号
|
||||
* @param name 部别名称
|
||||
* @param excludeId 修改时需要排除的当前部别编号
|
||||
*/
|
||||
private void ensureSiblingNameUnique(String parentId, String name, String excludeId) {
|
||||
// 数据库计数大于 0 表示存在冲突记录。
|
||||
if (ssjgMapper.countSiblingName(parentId, name, excludeId) > 0) {
|
||||
throw new BusinessException(CONFLICT, "同一上级部别下已存在同名部别");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 校验上级部别链路。
|
||||
*
|
||||
* <p>该方法同时检查:上级存在、上级启用、不能选择自身、
|
||||
* 不能移动到自己的下级、已有组织数据不能形成循环。</p>
|
||||
*
|
||||
* @param parentId 待选择的上级部别编号
|
||||
* @param currentId 当前部别编号;新增时为 null
|
||||
* @param departments 全部部别
|
||||
*/
|
||||
private void validateParentChain(String parentId, String currentId, List<SSJG> departments) {
|
||||
// 根节点没有上级,不需要继续校验。
|
||||
if (parentId == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 第一层快速判断:当前节点不能直接选择自己作为上级。
|
||||
if (parentId.equals(currentId)) {
|
||||
throw new BusinessException(CONFLICT, "上级部别不能选择当前部别");
|
||||
}
|
||||
|
||||
// 建立编号索引,后续沿祖先链逐级查询时保持 O(1) 查找。
|
||||
Map<String, SSJG> departmentMap = indexDepartments(departments);
|
||||
|
||||
// 记录已经访问的编号,用于识别数据库中的循环关系。
|
||||
Set<String> visited = new HashSet<>();
|
||||
|
||||
// 从待选择的上级节点开始向根节点逐级检查。
|
||||
String cursor = parentId;
|
||||
while (cursor != null) {
|
||||
// 遇到当前节点说明新上级位于当前节点的下级链路中。
|
||||
if (cursor.equals(currentId)) {
|
||||
throw new BusinessException(CONFLICT, "不能将部别移动到自己的下级部别中");
|
||||
}
|
||||
|
||||
// 同一编号在当前链路中出现两次,说明已有组织数据存在循环。
|
||||
if (!visited.add(cursor)) {
|
||||
throw new BusinessException("组织结构数据存在循环,请联系管理员处理");
|
||||
}
|
||||
|
||||
// 根据当前编号取得上级实体。
|
||||
SSJG parent = departmentMap.get(cursor);
|
||||
|
||||
// 引用了不存在的上级编号时,拒绝继续保存。
|
||||
if (parent == null) {
|
||||
throw new BusinessException(NOT_FOUND, "上级部别不存在");
|
||||
}
|
||||
|
||||
// 停用部别不能作为新增、移动或启用操作的有效上级。
|
||||
if (Boolean.TRUE.equals(parent.getTY())) {
|
||||
throw new BusinessException(CONFLICT, "上级部别已停用,不能选择");
|
||||
}
|
||||
|
||||
// 继续检查当前上级的上一级,直至到达根节点。
|
||||
cursor = normalizeText(parent.getSJJGBH());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 收集树形查询需要保留的部别编号。
|
||||
*
|
||||
* <p>命中查询条件的部别需要保留,同时保留它的全部祖先节点,
|
||||
* 这样筛选后的结果仍然是一棵层级完整、可以正常展示的树。</p>
|
||||
*
|
||||
* @param departments 全部部别
|
||||
* @param departmentMap 部别编号索引
|
||||
* @param dto 查询条件
|
||||
* @return 需要出现在查询结果树中的部别编号
|
||||
*/
|
||||
private Set<String> collectIncludedTreeIds(List<SSJG> departments,
|
||||
Map<String, SSJG> departmentMap,
|
||||
DepartmentQueryDTO dto) {
|
||||
// 第一步:创建结果集合,并利用 Set 自动去除重复编号。
|
||||
Set<String> includedIds = new HashSet<>();
|
||||
|
||||
// 第二步:逐个检查部别是否满足当前查询条件。
|
||||
for (SSJG department : departments) {
|
||||
// 未命中查询条件的部别不作为本次向上追溯的起点。
|
||||
if (!matches(department, dto)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* 第三步:从命中的部别开始沿上级链逐级向上追溯。
|
||||
* 当前节点和全部祖先节点都加入结果,确保筛选后的树不丢失层级路径。
|
||||
*/
|
||||
String cursor = department.getBH();
|
||||
while (cursor != null && includedIds.add(cursor)) {
|
||||
// 根据当前编号取得实体,再移动到它的上级部别。
|
||||
SSJG current = departmentMap.get(cursor);
|
||||
cursor = current == null ? null : normalizeText(current.getSJJGBH());
|
||||
}
|
||||
}
|
||||
|
||||
// 第四步:返回命中节点及其祖先节点的编号集合。
|
||||
return includedIds;
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查完整部别树是否存在循环关系。
|
||||
*
|
||||
* <p>从每个部别分别沿上级链向根节点追溯;同一条路径中再次遇到相同编号,
|
||||
* 即表示组织结构无法构成合法树,需要终止查询。</p>
|
||||
*
|
||||
* @param departments 全部部别
|
||||
* @param departmentMap 部别编号索引
|
||||
*/
|
||||
private void ensureTreeHasNoCycle(List<SSJG> departments, Map<String, SSJG> departmentMap) {
|
||||
// 第一步:以每个部别为起点,分别检查它所在的上级链路。
|
||||
for (SSJG department : departments) {
|
||||
// 第二步:为当前链路创建独立的访问记录。
|
||||
Set<String> path = new HashSet<>();
|
||||
SSJG cursor = department;
|
||||
|
||||
// 第三步:沿上级链持续追溯,直至到达根节点或断开的上级节点。
|
||||
while (cursor != null) {
|
||||
// 同一编号在当前链路重复出现,说明组织结构中存在循环。
|
||||
if (!path.add(cursor.getBH())) {
|
||||
throw new BusinessException("组织结构数据存在循环,请联系管理员处理");
|
||||
}
|
||||
|
||||
// 读取当前部别的上级编号,并将游标移动到上级部别。
|
||||
String parentId = normalizeText(cursor.getSJJGBH());
|
||||
cursor = parentId == null ? null : departmentMap.get(parentId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 按部别编号建立实体索引。
|
||||
*
|
||||
* @param departments 部别集合
|
||||
* @return 部别编号与实体的映射
|
||||
*/
|
||||
private Map<String, SSJG> indexDepartments(List<SSJG> departments) {
|
||||
// 第一步:创建用于快速查询部别的编号索引。
|
||||
Map<String, SSJG> result = new HashMap<>();
|
||||
|
||||
// 第二步:将每个部别实体按唯一编号写入索引。
|
||||
for (SSJG department : departments) {
|
||||
result.put(department.getBH(), department);
|
||||
}
|
||||
|
||||
// 第三步:返回构建完成的索引。
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 收集所有被其他部别引用的上级编号。
|
||||
*
|
||||
* @param departments 全部部别
|
||||
* @return 至少拥有一个下级部别的编号集合
|
||||
*/
|
||||
private Set<String> collectParentIds(List<SSJG> departments) {
|
||||
// 第一步:创建上级编号集合,并利用 Set 自动去重。
|
||||
Set<String> parentIds = new HashSet<>();
|
||||
|
||||
// 第二步:逐个读取部别的上级编号。
|
||||
for (SSJG department : departments) {
|
||||
String parentId = normalizeText(department.getSJJGBH());
|
||||
|
||||
// 根节点没有上级编号,不加入集合。
|
||||
if (parentId != null) {
|
||||
parentIds.add(parentId);
|
||||
}
|
||||
}
|
||||
|
||||
// 第三步:返回所有实际作为上级的部别编号。
|
||||
return parentIds;
|
||||
}
|
||||
|
||||
/**
|
||||
* 将部别实体转换为对外返回的详情 VO。
|
||||
*
|
||||
* @param department 部别实体
|
||||
* @param departmentMap 部别编号索引
|
||||
* @param parentIds 实际拥有下级的部别编号集合
|
||||
* @return 部别详情 VO
|
||||
*/
|
||||
private DepartmentVO toDepartmentVO(SSJG department,
|
||||
Map<String, SSJG> departmentMap,
|
||||
Set<String> parentIds) {
|
||||
// 第一步:创建独立的返回对象,避免直接暴露数据库实体。
|
||||
DepartmentVO vo = new DepartmentVO();
|
||||
|
||||
// 第二步:复制部别自身的基础信息。
|
||||
vo.setId(department.getBH());
|
||||
vo.setName(department.getJGMC());
|
||||
vo.setCategory(department.getJGLB());
|
||||
vo.setClassificationCode(department.getFLH());
|
||||
vo.setLevelNumber(department.getFJH());
|
||||
|
||||
// 第三步:设置上级编号,并通过索引补充上级名称。
|
||||
vo.setParentId(normalizeText(department.getSJJGBH()));
|
||||
SSJG parent = departmentMap.get(vo.getParentId());
|
||||
vo.setParentName(parent == null ? null : parent.getJGMC());
|
||||
|
||||
// 第四步:将实体的停用标志转换为更直观的启用状态,并保留停用时间。
|
||||
vo.setEnabled(!Boolean.TRUE.equals(department.getTY()));
|
||||
vo.setDisabledAt(department.getTYSJ());
|
||||
|
||||
// 第五步:补充简称和是否拥有下级节点等展示信息。
|
||||
vo.setAbbreviation(department.getJC());
|
||||
vo.setHasChildren(parentIds.contains(department.getBH()));
|
||||
|
||||
// 第六步:返回完成组装的详情 VO。
|
||||
return vo;
|
||||
}
|
||||
|
||||
/**
|
||||
* 将部别详情 VO 转换为可挂载子节点的树形 VO。
|
||||
*
|
||||
* @param source 部别详情 VO
|
||||
* @return 树形部别 VO
|
||||
*/
|
||||
private DepartmentTreeVO toTreeVO(DepartmentVO source) {
|
||||
// 第一步:创建树形返回对象,子节点集合由该类型自行初始化。
|
||||
DepartmentTreeVO target = new DepartmentTreeVO();
|
||||
|
||||
// 第二步:复制基础信息和层级信息。
|
||||
target.setId(source.getId());
|
||||
target.setName(source.getName());
|
||||
target.setCategory(source.getCategory());
|
||||
target.setClassificationCode(source.getClassificationCode());
|
||||
target.setLevelNumber(source.getLevelNumber());
|
||||
target.setParentId(source.getParentId());
|
||||
target.setParentName(source.getParentName());
|
||||
|
||||
// 第三步:复制状态信息和展示辅助字段。
|
||||
target.setEnabled(source.getEnabled());
|
||||
target.setDisabledAt(source.getDisabledAt());
|
||||
target.setAbbreviation(source.getAbbreviation());
|
||||
target.setHasChildren(source.getHasChildren());
|
||||
|
||||
// 第四步:返回尚未挂载子节点的树形 VO。
|
||||
return target;
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断部别是否满足查询条件。
|
||||
*
|
||||
* @param department 待判断的部别
|
||||
* @param dto 查询条件
|
||||
* @return 满足全部条件时返回 true
|
||||
*/
|
||||
private boolean matches(SSJG department, DepartmentQueryDTO dto) {
|
||||
// 未提供查询条件时,默认匹配全部部别。
|
||||
if (dto == null) {
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* 第一步:处理关键字模糊查询。
|
||||
* 关键字可匹配部别编号、名称、简称和分类号,且忽略英文字母大小写。
|
||||
*/
|
||||
String keyword = normalizeText(dto.getKeyword());
|
||||
if (keyword != null
|
||||
&& !containsIgnoreCase(department.getBH(), keyword)
|
||||
&& !containsIgnoreCase(department.getJGMC(), keyword)
|
||||
&& !containsIgnoreCase(department.getJC(), keyword)
|
||||
&& !containsIgnoreCase(department.getFLH(), keyword)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 第二步:存在部别类别条件时,按完整类别值忽略大小写匹配。
|
||||
String category = normalizeText(dto.getCategory());
|
||||
if (category != null && !category.equalsIgnoreCase(normalizeText(department.getJGLB()))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 第三步:存在启用状态条件时,将实体停用标志转换后进行比较。
|
||||
if (dto.getEnabled() != null) {
|
||||
boolean enabled = !Boolean.TRUE.equals(department.getTY());
|
||||
return dto.getEnabled().booleanValue() == enabled;
|
||||
}
|
||||
|
||||
// 所有已提供的查询条件均通过时,当前部别匹配成功。
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断源文本是否包含指定关键字,并忽略英文字母大小写。
|
||||
*
|
||||
* @param source 源文本
|
||||
* @param keyword 关键字
|
||||
* @return 包含关键字时返回 true
|
||||
*/
|
||||
private boolean containsIgnoreCase(String source, String keyword) {
|
||||
// 源文本为空时不能匹配;否则统一按 ROOT 区域规则转为小写后比较。
|
||||
return source != null
|
||||
&& source.toLowerCase(Locale.ROOT).contains(keyword.toLowerCase(Locale.ROOT));
|
||||
}
|
||||
|
||||
/**
|
||||
* 递归排序树中每一层的部别节点。
|
||||
*
|
||||
* @param nodes 当前层级的树节点
|
||||
*/
|
||||
private void sortTree(List<DepartmentTreeVO> nodes) {
|
||||
// 第一步:按照统一的部别排序规则排列当前层级。
|
||||
Collections.sort(nodes, new Comparator<DepartmentTreeVO>() {
|
||||
@Override
|
||||
public int compare(DepartmentTreeVO left, DepartmentTreeVO right) {
|
||||
return compareDepartments(left, right);
|
||||
}
|
||||
});
|
||||
|
||||
// 第二步:递归处理每个节点的子节点,保证整棵树的各层顺序一致。
|
||||
for (DepartmentTreeVO node : nodes) {
|
||||
sortTree(node.getChildren());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 按分级号、分类号、部别名称依次比较两个部别。
|
||||
*
|
||||
* @param left 左侧部别
|
||||
* @param right 右侧部别
|
||||
* @return 符合 Comparator 约定的比较结果
|
||||
*/
|
||||
private int compareDepartments(DepartmentVO left, DepartmentVO right) {
|
||||
// 第一优先级:分级号较小的部别排在前面,空值排在最后。
|
||||
int levelResult = compareNullableInteger(left.getLevelNumber(), right.getLevelNumber());
|
||||
if (levelResult != 0) {
|
||||
return levelResult;
|
||||
}
|
||||
|
||||
// 第二优先级:分级号相同时按分类号排序,空值排在最后。
|
||||
int classificationResult = compareNullableText(
|
||||
left.getClassificationCode(), right.getClassificationCode());
|
||||
if (classificationResult != 0) {
|
||||
return classificationResult;
|
||||
}
|
||||
|
||||
// 第三优先级:前两项相同时按部别名称排序。
|
||||
return compareNullableText(left.getName(), right.getName());
|
||||
}
|
||||
|
||||
/**
|
||||
* 比较两个允许为空的整数,空值统一排在非空值之后。
|
||||
*
|
||||
* @param left 左侧整数
|
||||
* @param right 右侧整数
|
||||
* @return 符合 Comparator 约定的比较结果
|
||||
*/
|
||||
private int compareNullableInteger(Integer left, Integer right) {
|
||||
// 两侧都为空时视为相等。
|
||||
if (left == null && right == null) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// 仅左侧为空时,将左侧排在后面。
|
||||
if (left == null) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
// 仅右侧为空时,将右侧排在后面。
|
||||
if (right == null) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// 两侧均有值时使用整数的自然顺序。
|
||||
return left.compareTo(right);
|
||||
}
|
||||
|
||||
/**
|
||||
* 比较两个允许为空的文本,空值统一排在非空值之后。
|
||||
*
|
||||
* @param left 左侧文本
|
||||
* @param right 右侧文本
|
||||
* @return 符合 Comparator 约定的比较结果
|
||||
*/
|
||||
private int compareNullableText(String left, String right) {
|
||||
// 两侧都为空时视为相等。
|
||||
if (left == null && right == null) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// 仅左侧为空时,将左侧排在后面。
|
||||
if (left == null) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
// 仅右侧为空时,将右侧排在后面。
|
||||
if (right == null) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// 优先忽略大小写比较,保证英文字母排序不受大小写直接影响。
|
||||
int ignoreCaseResult = left.compareToIgnoreCase(right);
|
||||
|
||||
// 忽略大小写后相等时再按原文本比较,使排序结果保持稳定且明确。
|
||||
return ignoreCaseResult == 0 ? left.compareTo(right) : ignoreCaseResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* 校验并规范化部别编号。
|
||||
*
|
||||
* @param id 原始部别编号
|
||||
* @return 去除首尾空白后的有效编号
|
||||
*/
|
||||
private String requireId(String id) {
|
||||
// 第一步:去除编号首尾空白,并将空字符串统一转换为 null。
|
||||
String normalizedId = normalizeText(id);
|
||||
|
||||
// 第二步:编号为空时返回参数错误。
|
||||
if (normalizedId == null) {
|
||||
throw new BusinessException(BAD_REQUEST, "部别编号不能为空");
|
||||
}
|
||||
|
||||
// 第三步:限制编号最大长度,避免传入不符合存储定义的值。
|
||||
if (normalizedId.length() > 36) {
|
||||
throw new BusinessException(BAD_REQUEST, "部别编号格式不正确");
|
||||
}
|
||||
|
||||
// 第四步:返回通过校验的规范化编号。
|
||||
return normalizedId;
|
||||
}
|
||||
|
||||
/**
|
||||
* 校验必填文本并去除首尾空白。
|
||||
*
|
||||
* @param value 原始文本
|
||||
* @param message 文本为空时使用的错误提示
|
||||
* @return 规范化后的非空文本
|
||||
*/
|
||||
private String requireText(String value, String message) {
|
||||
// 第一步:统一处理 null、空字符串和首尾空白。
|
||||
String normalized = normalizeText(value);
|
||||
|
||||
// 第二步:规范化后为空时抛出调用方指定的参数错误。
|
||||
if (normalized == null) {
|
||||
throw new BusinessException(BAD_REQUEST, message);
|
||||
}
|
||||
|
||||
// 第三步:返回通过必填校验的文本。
|
||||
return normalized;
|
||||
}
|
||||
|
||||
/**
|
||||
* 规范化分类号,并为空值提供默认值。
|
||||
*
|
||||
* @param value 原始分类号
|
||||
* @return 有效分类号;未填写时返回 0
|
||||
*/
|
||||
private String defaultClassificationCode(String value) {
|
||||
// 第一步:去除首尾空白,并将空字符串转换为 null。
|
||||
String normalized = normalizeText(value);
|
||||
|
||||
// 第二步:未填写分类号时使用系统默认分类号 0。
|
||||
return normalized == null ? "0" : normalized;
|
||||
}
|
||||
|
||||
/**
|
||||
* 校验分级号,并为空值提供默认值。
|
||||
*
|
||||
* @param value 原始分级号
|
||||
* @return 有效分级号;未填写时返回 0
|
||||
*/
|
||||
private Integer defaultLevelNumber(Integer value) {
|
||||
// 第一步:未填写分级号时使用系统默认分级号 0。
|
||||
if (value == null) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// 第二步:分级号不能为负数。
|
||||
if (value < 0) {
|
||||
throw new BusinessException(BAD_REQUEST, "分级号不能小于0");
|
||||
}
|
||||
|
||||
// 第三步:返回通过校验的分级号。
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* 统一规范化可选文本。
|
||||
*
|
||||
* @param value 原始文本
|
||||
* @return 去除首尾空白后的文本;null 或空字符串返回 null
|
||||
*/
|
||||
private String normalizeText(String value) {
|
||||
// 原始值为 null 时直接返回 null。
|
||||
if (value == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// 去除用户输入或数据库文本中的首尾空白。
|
||||
String normalized = value.trim();
|
||||
|
||||
// 去除空白后没有有效内容时统一返回 null。
|
||||
return normalized.isEmpty() ? null : normalized;
|
||||
}
|
||||
}
|
||||
+1171
File diff suppressed because it is too large
Load Diff
+524
@@ -0,0 +1,524 @@
|
||||
package com.roomroot.jwgl.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.roomroot.jwgl.dto.dict.DictDataBatchQueryDTO;
|
||||
import com.roomroot.jwgl.dto.dict.DictDataQueryDTO;
|
||||
import com.roomroot.jwgl.dto.dict.DictDataSaveDTO;
|
||||
import com.roomroot.jwgl.entity.SysDictData;
|
||||
import com.roomroot.jwgl.entity.SysDictType;
|
||||
import com.roomroot.jwgl.mapper.DictDataMapper;
|
||||
import com.roomroot.jwgl.mapper.DictTypeMapper;
|
||||
import com.roomroot.jwgl.service.DictDataService;
|
||||
|
||||
import com.roomroot.jwgl.unit.BusinessException;
|
||||
import com.roomroot.jwgl.unit.PageResult;
|
||||
import com.roomroot.jwgl.utils.PageResultUtil;
|
||||
import com.roomroot.jwgl.vo.dict.DictDataVO;
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 字典数据服务实现。
|
||||
* <p>
|
||||
* 实现字典数据的查询(单类型、分页、批量)、保存(新增/编辑)和删除业务逻辑。
|
||||
* 保存时校验关联类型是否存在,处理默认值唯一性,保证数据一致性。
|
||||
* </p>
|
||||
*/
|
||||
@Service
|
||||
public class DictDataServiceImpl implements DictDataService {
|
||||
|
||||
/**
|
||||
* 字典数据数据访问接口。
|
||||
*/
|
||||
@Resource
|
||||
private DictDataMapper dictDataMapper;
|
||||
|
||||
/**
|
||||
* 字典类型数据访问接口。
|
||||
* <p>用于保存字典数据时校验关联的字典类型是否存在。</p>
|
||||
*/
|
||||
@Resource
|
||||
private DictTypeMapper dictTypeMapper;
|
||||
|
||||
/**
|
||||
* JSON序列化工具
|
||||
*/
|
||||
private final ObjectMapper objectMapper = new ObjectMapper();
|
||||
|
||||
/**
|
||||
* 按类型编码查询全部启用的字典数据。
|
||||
* <p>
|
||||
* 构建查询条件:按类型编码精确匹配、状态为启用(1)、按排序号升序排列。
|
||||
* 查询结果转换为 VO 列表返回,用于前端下拉框等场景。
|
||||
* </p>
|
||||
*
|
||||
* @param dictTypeCode 字典类型编码
|
||||
* @return 启用的字典数据 VO 列表
|
||||
*/
|
||||
@Override
|
||||
public List<DictDataVO> listByType(String dictTypeCode) {
|
||||
// 第一步:构建 Lambda 查询条件。
|
||||
LambdaQueryWrapper<SysDictData> wrapper = new LambdaQueryWrapper<>();
|
||||
// 按类型编码精确匹配。
|
||||
wrapper.eq(SysDictData::getDictTypeCode, dictTypeCode);
|
||||
// 仅查询状态为启用的数据。
|
||||
wrapper.eq(SysDictData::getStatus, 1);
|
||||
// 按排序号升序排列,保证前端展示顺序一致。
|
||||
wrapper.orderByAsc(SysDictData::getDictSort);
|
||||
|
||||
// 第二步:执行查询。
|
||||
List<SysDictData> list = dictDataMapper.selectList(wrapper);
|
||||
// 第三步:将实体列表转换为 VO 列表返回。
|
||||
return list.stream().map(this::toVO).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
/**
|
||||
* 分页查询字典数据列表(管理页面用)。
|
||||
* <p>
|
||||
* 根据查询条件构建 MyBatis-Plus Lambda 查询包装器,
|
||||
* 支持按字典类型编码精确匹配、关键字(模糊匹配标签或值)、状态筛选,
|
||||
* 结果按排序号升序排列。分页查询完成后将实体列表转换为 VO 列表返回。
|
||||
* </p>
|
||||
*
|
||||
* @param dto 查询条件,包含分页参数和筛选条件
|
||||
* @return 字典数据分页结果
|
||||
*/
|
||||
@Override
|
||||
public PageResult<DictDataVO> page(DictDataQueryDTO dto) {
|
||||
// 第一步:创建 MyBatis-Plus 分页对象。
|
||||
Page<SysDictData> page = new Page<>(dto.getPageNum(), dto.getPageSize());
|
||||
// 第二步:构建 Lambda 查询条件包装器。
|
||||
LambdaQueryWrapper<SysDictData> wrapper = new LambdaQueryWrapper<>();
|
||||
|
||||
// 第三步:按字典类型编码精确匹配(必填条件)。
|
||||
wrapper.eq(SysDictData::getDictTypeCode, dto.getDictTypeCode());
|
||||
// 第四步:若有关键字,同时模糊匹配字典标签和字典值。
|
||||
if (dto.getKeyword() != null && !dto.getKeyword().isEmpty()) {
|
||||
wrapper.and(w -> w.like(SysDictData::getDictLabel, dto.getKeyword())
|
||||
.or()
|
||||
.like(SysDictData::getDictValue, dto.getKeyword()));
|
||||
}
|
||||
// 第五步:若指定了状态,按状态精确匹配。
|
||||
if (dto.getStatus() != null) {
|
||||
wrapper.eq(SysDictData::getStatus, dto.getStatus());
|
||||
}
|
||||
// 第六步:按排序号升序排列。
|
||||
wrapper.orderByAsc(SysDictData::getDictSort);
|
||||
|
||||
// 第七步:执行分页查询。
|
||||
Page<SysDictData> result = dictDataMapper.selectPage(page, wrapper);
|
||||
// 第八步:将查询结果的实体列表转换为 VO 列表。
|
||||
List<DictDataVO> records = result.getRecords().stream()
|
||||
.map(this::toVO)
|
||||
.collect(Collectors.toList());
|
||||
// 第九步:使用分页工具组装统一分页结果返回。
|
||||
return PageResultUtil.fromRecords(
|
||||
result,
|
||||
records,
|
||||
dto.getPageNum(),
|
||||
dto.getPageSize());
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量查询多个类型的字典数据。
|
||||
* <p>
|
||||
* 遍历传入的类型编码列表,依次调用 {@link #listByType} 查询每种类型的启用数据,
|
||||
* 将结果按类型编码分组放入 Map 中返回。
|
||||
* </p>
|
||||
*
|
||||
* @param dto 批量查询参数,包含字典类型编码列表
|
||||
* @return 按类型编码分组的字典数据 VO 列表
|
||||
*/
|
||||
@Override
|
||||
public Map<String, List<DictDataVO>> batchList(DictDataBatchQueryDTO dto) {
|
||||
// 第一步:初始化结果 Map。
|
||||
Map<String, List<DictDataVO>> result = new HashMap<>();
|
||||
// 第二步:若类型编码列表为空,直接返回空 Map。
|
||||
if (dto.getTypeCodes() == null || dto.getTypeCodes().isEmpty()) {
|
||||
return result;
|
||||
}
|
||||
|
||||
// 第三步:遍历每个类型编码,查询该类型的字典数据并放入 Map。
|
||||
for (String typeCode : dto.getTypeCodes()) {
|
||||
result.put(typeCode, listByType(typeCode));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存字典数据(新增或编辑)。
|
||||
* <p>
|
||||
* 根据 {@code dto.dictDataId} 判断是新增还是编辑:
|
||||
* <ul>
|
||||
* <li>保存前校验关联的字典类型是否存在。</li>
|
||||
* <li>若 {@code isDefault} 设置为 1,先清除该类型下其他数据的默认标记,保证唯一性。</li>
|
||||
* <li>新增:构建实体后插入数据库。</li>
|
||||
* <li>编辑:查询原记录,更新字段后写入数据库。</li>
|
||||
* </ul>
|
||||
* 整个操作在事务中执行。
|
||||
* </p>
|
||||
*
|
||||
* @param dto 保存参数
|
||||
* @return 保存后的字典数据 VO
|
||||
*/
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public DictDataVO save(DictDataSaveDTO dto) {
|
||||
// 第一步:校验关联的字典类型是否存在。
|
||||
SysDictType type = dictTypeMapper.selectOne(
|
||||
new LambdaQueryWrapper<SysDictType>()
|
||||
.eq(SysDictType::getDictTypeCode, dto.getDictTypeCode()));
|
||||
if (type == null) {
|
||||
throw new BusinessException("字典类型不存在");
|
||||
}
|
||||
|
||||
// 分支一:dictDataId 为空,执行新增操作。
|
||||
if (dto.getDictDataId() == null) {
|
||||
// 若设置为默认值,先清除该类型下其他数据的默认标记。
|
||||
if (dto.getIsDefault() != null && dto.getIsDefault() == 1) {
|
||||
clearDefault(dto.getDictTypeCode());
|
||||
}
|
||||
|
||||
// 构建字典数据实体并赋值。
|
||||
SysDictData entity = new SysDictData();
|
||||
entity.setDictTypeCode(dto.getDictTypeCode());
|
||||
entity.setDictLabel(dto.getDictLabel());
|
||||
entity.setDictValue(dto.getDictValue());
|
||||
entity.setDictSort(dto.getDictSort());
|
||||
entity.setCssClass(dto.getCssClass());
|
||||
entity.setListClass(dto.getListClass());
|
||||
entity.setIsDefault(dto.getIsDefault());
|
||||
entity.setStatus(dto.getStatus());
|
||||
entity.setRemark(dto.getRemark());
|
||||
|
||||
// --- 版本控制:新增时初始化版本号为1,历史快照为空数组 ---
|
||||
// 后续每次编辑都会通过 saveSnapshot 方法追加历史快照并递增版本号
|
||||
entity.setVersion(1);
|
||||
entity.setPrevSnapshot("[]");
|
||||
|
||||
// --- 逻辑删除:新增时显式标记为未删除 ---
|
||||
// @TableLogic 注解会使 MyBatis-Plus 自动在查询中追加 WHERE is_deleted=0 条件
|
||||
// 此处显式赋值,确保即使数据库默认值未生效也能正确标记
|
||||
entity.setIsDeleted(0);
|
||||
|
||||
// 插入数据库,create_time 和 create_by 由 MyBatis-Plus 自动填充。
|
||||
dictDataMapper.insert(entity);
|
||||
// 转换为 VO 返回。
|
||||
return toVO(entity);
|
||||
} else {
|
||||
// 分支二:dictDataId 有值,执行编辑操作。
|
||||
// 查询原记录。
|
||||
SysDictData exist = dictDataMapper.selectById(dto.getDictDataId());
|
||||
if (exist == null) {
|
||||
throw new BusinessException("字典数据不存在");
|
||||
}
|
||||
|
||||
// 若之前不是默认值,现在设置为默认值,则清除该类型下其他数据的默认标记。
|
||||
if (dto.getIsDefault() != null && dto.getIsDefault() == 1
|
||||
&& (exist.getIsDefault() == null || exist.getIsDefault() != 1)) {
|
||||
clearDefault(exist.getDictTypeCode());
|
||||
}
|
||||
|
||||
// --- 版本控制逻辑:将编辑前的旧数据存入历史快照 ---
|
||||
// saveSnapshot 方法会把当前 exist 对象(旧数据)转为 JSON 快照追加到 prevSnapshot 中,
|
||||
// 随后 exist 的字段会被新值覆盖,版本号递增后写回数据库
|
||||
saveSnapshot(exist);
|
||||
|
||||
// 更新实体字段。
|
||||
exist.setDictTypeCode(dto.getDictTypeCode());
|
||||
exist.setDictLabel(dto.getDictLabel());
|
||||
exist.setDictValue(dto.getDictValue());
|
||||
exist.setDictSort(dto.getDictSort());
|
||||
exist.setCssClass(dto.getCssClass());
|
||||
exist.setListClass(dto.getListClass());
|
||||
exist.setIsDefault(dto.getIsDefault());
|
||||
exist.setStatus(dto.getStatus());
|
||||
exist.setRemark(dto.getRemark());
|
||||
|
||||
// 版本号递增(每次编辑产生新版本,旧版本已在 saveSnapshot 中存入历史)
|
||||
exist.setVersion(exist.getVersion() + 1);
|
||||
|
||||
// 更新数据库,update_time 和 update_by 由 MyBatis-Plus 自动填充。
|
||||
dictDataMapper.updateById(exist);
|
||||
// 转换为 VO 返回。
|
||||
return toVO(exist);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存历史版本快照。
|
||||
* <p>
|
||||
* 将编辑前的实体对象构建为 JSON 快照,追加到 {@code prevSnapshot} 字段中。
|
||||
* 快照 JSON 结构示例:
|
||||
* <pre>
|
||||
* [
|
||||
* {
|
||||
* "version": 1,
|
||||
* "snapshotTime": "2026-08-01T10:00:00",
|
||||
* "dictLabel": "考试",
|
||||
* "dictValue": "1",
|
||||
* "dictSort": 1,
|
||||
* "cssClass": "danger",
|
||||
* "listClass": "default",
|
||||
* "isDefault": 1,
|
||||
* "status": 1,
|
||||
* "remark": "初始版本"
|
||||
* }
|
||||
* ]
|
||||
* </pre>
|
||||
* 历史版本数量上限为 20 个,超出后自动丢弃最早的版本。
|
||||
* </p>
|
||||
*
|
||||
* @param exist 编辑前的实体对象(即当前数据库中的旧数据)
|
||||
*/
|
||||
private void saveSnapshot(SysDictData exist) {
|
||||
try {
|
||||
// 构建当前版本的快照对象,包含版本号和所有业务字段
|
||||
Map<String, Object> snapshot = new HashMap<>();
|
||||
// 记录当前版本号,用于后续版本回滚时定位
|
||||
snapshot.put("version", exist.getVersion());
|
||||
// 记录快照生成时间,便于版本比对
|
||||
snapshot.put("snapshotTime", LocalDateTime.now().toString());
|
||||
// 注意:此处简化处理,实际项目中可能需要从安全上下文中获取操作人ID
|
||||
// snapshot.put("operatorId", SecurityUtils.getCurrentUserId());
|
||||
|
||||
// 保存业务字段(不含版本号、快照、删除标记等系统字段,仅记录业务数据)
|
||||
snapshot.put("dictLabel", exist.getDictLabel());
|
||||
snapshot.put("dictValue", exist.getDictValue());
|
||||
snapshot.put("dictSort", exist.getDictSort());
|
||||
snapshot.put("cssClass", exist.getCssClass());
|
||||
snapshot.put("listClass", exist.getListClass());
|
||||
snapshot.put("isDefault", exist.getIsDefault());
|
||||
snapshot.put("status", exist.getStatus());
|
||||
snapshot.put("remark", exist.getRemark());
|
||||
|
||||
// 解析现有的快照历史(prevSnapshot 为空时初始化为空列表)
|
||||
List<Map<String, Object>> history = new ArrayList<>();
|
||||
if (exist.getPrevSnapshot() != null && !exist.getPrevSnapshot().isEmpty()) {
|
||||
history = objectMapper.readValue(exist.getPrevSnapshot(),
|
||||
new TypeReference<List<Map<String, Object>>>() {});
|
||||
}
|
||||
|
||||
// 将当前快照追加到历史列表末尾
|
||||
history.add(snapshot);
|
||||
|
||||
// 限制历史版本数量(例如最多保留20个版本),超出则丢弃最早的版本
|
||||
// 保证 prevSnapshot 字段不会无限增长
|
||||
while (history.size() > 20) {
|
||||
history.remove(0);
|
||||
}
|
||||
|
||||
// 将更新后的历史记录序列化为 JSON 并写回实体
|
||||
// 注意:此处仅修改了实体对象的 prevSnapshot 字段,
|
||||
// 实际持久化由调用方(save/rollback 方法中的 updateById)完成
|
||||
exist.setPrevSnapshot(objectMapper.writeValueAsString(history));
|
||||
} catch (JsonProcessingException e) {
|
||||
throw new BusinessException("保存版本快照失败: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除字典数据。
|
||||
* <p>
|
||||
* 根据字典数据ID查询记录,校验数据是否存在,存在则执行逻辑删除(is_deleted置为1)。
|
||||
* 整个操作在事务中执行。
|
||||
* </p>
|
||||
*
|
||||
* @param dictDataId 字典数据ID
|
||||
*/
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void delete(Long dictDataId) {
|
||||
// 第一步:根据 ID 查询字典数据。
|
||||
SysDictData exist = dictDataMapper.selectById(dictDataId);
|
||||
if (exist == null) {
|
||||
throw new BusinessException("字典数据不存在");
|
||||
}
|
||||
// 第二步:执行删除。
|
||||
// 由于 SysDictData 实体类已添加 @TableLogic 注解,MyBatis-Plus 会自动将
|
||||
// deleteById 转换为 UPDATE sys_dict_data SET is_deleted = 1 WHERE dict_data_id = ?
|
||||
// 即逻辑删除(标记为已删除),而非物理删除,保留历史数据以便版本回溯
|
||||
dictDataMapper.deleteById(dictDataId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 清除指定类型下的默认标记。
|
||||
* <p>
|
||||
* 将指定字典类型下所有 {@code isDefault=1} 的数据项更新为 {@code isDefault=0},
|
||||
* 保证同一类型下只有一个默认选项。
|
||||
* </p>
|
||||
*
|
||||
* @param dictTypeCode 字典类型编码
|
||||
*/
|
||||
private void clearDefault(String dictTypeCode) {
|
||||
// 构建更新实体,只设置 isDefault 字段。
|
||||
SysDictData update = new SysDictData();
|
||||
update.setIsDefault(0);
|
||||
// 执行更新:按类型编码和默认标记匹配。
|
||||
dictDataMapper.update(update,
|
||||
new LambdaQueryWrapper<SysDictData>()
|
||||
.eq(SysDictData::getDictTypeCode, dictTypeCode)
|
||||
.eq(SysDictData::getIsDefault, 1));
|
||||
}
|
||||
|
||||
/**
|
||||
* 将字典数据实体转换为展示对象。
|
||||
* <p>
|
||||
* 提取实体中的有效字段赋值给 VO,用于对外返回统一的数据结构。
|
||||
* </p>
|
||||
*
|
||||
* @param entity 字典数据实体
|
||||
* @return 字典数据 VO
|
||||
*/
|
||||
private DictDataVO toVO(SysDictData entity) {
|
||||
DictDataVO vo = new DictDataVO();
|
||||
vo.setDictDataId(entity.getDictDataId());
|
||||
vo.setDictTypeCode(entity.getDictTypeCode());
|
||||
vo.setDictLabel(entity.getDictLabel());
|
||||
vo.setDictValue(entity.getDictValue());
|
||||
vo.setDictSort(entity.getDictSort());
|
||||
vo.setCssClass(entity.getCssClass());
|
||||
vo.setListClass(entity.getListClass());
|
||||
vo.setIsDefault(entity.getIsDefault());
|
||||
vo.setStatus(entity.getStatus());
|
||||
vo.setRemark(entity.getRemark());
|
||||
|
||||
// 版本控制字段
|
||||
vo.setVersion(entity.getVersion());
|
||||
vo.setPrevSnapshot(entity.getPrevSnapshot());
|
||||
|
||||
vo.setCreateTime(entity.getCreateTime());
|
||||
vo.setUpdateTime(entity.getUpdateTime());
|
||||
return vo;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取字典数据的历史版本列表。
|
||||
* <p>
|
||||
* 根据字典数据ID查询其 {@code prevSnapshot} 字段中存储的所有历史快照,
|
||||
* 解析为版本列表返回。每个版本快照包含版本号、快照时间和当时的业务字段值。
|
||||
* 当 {@code prevSnapshot} 为空时返回空列表。
|
||||
* </p>
|
||||
*
|
||||
* @param dictDataId 字典数据ID
|
||||
* @return 历史版本快照列表,每个元素为一个 Map,包含 version、snapshotTime 及各业务字段
|
||||
*/
|
||||
@Override
|
||||
public List<Map<String, Object>> getHistory(Long dictDataId) {
|
||||
// 根据 ID 查询字典数据(@TableLogic 自动过滤已删除记录)
|
||||
SysDictData exist = dictDataMapper.selectById(dictDataId);
|
||||
if (exist == null) {
|
||||
throw new BusinessException("字典数据不存在");
|
||||
}
|
||||
try {
|
||||
// 如果 prevSnapshot 为空或空字符串,直接返回空列表
|
||||
if (exist.getPrevSnapshot() == null || exist.getPrevSnapshot().isEmpty()) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
// 将 prevSnapshot JSON 解析为版本列表返回
|
||||
return objectMapper.readValue(exist.getPrevSnapshot(),
|
||||
new TypeReference<List<Map<String, Object>>>() {});
|
||||
} catch (JsonProcessingException e) {
|
||||
throw new BusinessException("获取历史版本失败: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 回滚字典数据到指定版本。
|
||||
* <p>
|
||||
* 根据目标版本号从历史快照 {@code prevSnapshot} 中查找对应的快照数据,
|
||||
* 将当前数据恢复到该版本的状态。回滚操作本身也会生成新的版本快照,
|
||||
* 保证版本链的完整性(回滚前的当前状态也被保留)。
|
||||
* </p>
|
||||
* <p>
|
||||
* 执行步骤:
|
||||
* <ol>
|
||||
* <li>查询字典数据是否存在</li>
|
||||
* <li>从 prevSnapshot 中解析历史版本列表</li>
|
||||
* <li>查找目标版本号对应的快照</li>
|
||||
* <li>将当前状态保存为新版本快照(回滚前的状态入历史)</li>
|
||||
* <li>从目标快照中恢复业务字段值</li>
|
||||
* <li>版本号递增并更新数据库</li>
|
||||
* </ol>
|
||||
* </p>
|
||||
*
|
||||
* @param dictDataId 字典数据ID
|
||||
* @param targetVersion 目标版本号,必须存在于历史快照中
|
||||
* @return 回滚后的字典数据详情
|
||||
*/
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public DictDataVO rollback(Long dictDataId, Integer targetVersion) {
|
||||
// 第一步:查询字典数据是否存在(@TableLogic 自动过滤已删除记录)
|
||||
SysDictData exist = dictDataMapper.selectById(dictDataId);
|
||||
if (exist == null) {
|
||||
throw new BusinessException("字典数据不存在");
|
||||
}
|
||||
|
||||
try {
|
||||
// 第二步:从 prevSnapshot 中解析历史版本列表
|
||||
List<Map<String, Object>> history = new ArrayList<>();
|
||||
if (exist.getPrevSnapshot() != null && !exist.getPrevSnapshot().isEmpty()) {
|
||||
history = objectMapper.readValue(exist.getPrevSnapshot(),
|
||||
new TypeReference<List<Map<String, Object>>>() {});
|
||||
}
|
||||
|
||||
// 第三步:在历史列表中查找目标版本号对应的快照
|
||||
Map<String, Object> targetSnapshot = null;
|
||||
for (Map<String, Object> snapshot : history) {
|
||||
if (targetVersion.equals(snapshot.get("version"))) {
|
||||
targetSnapshot = snapshot;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// 如果目标版本不存在,抛出异常
|
||||
if (targetSnapshot == null) {
|
||||
throw new BusinessException("目标版本不存在");
|
||||
}
|
||||
|
||||
// 第四步:将当前状态保存为新版本快照
|
||||
// (回滚操作本身也是一次编辑,回滚前的状态需要保留在历史中)
|
||||
saveSnapshot(exist);
|
||||
|
||||
// 第五步:从目标快照中恢复业务字段值
|
||||
exist.setDictLabel((String) targetSnapshot.get("dictLabel"));
|
||||
exist.setDictValue((String) targetSnapshot.get("dictValue"));
|
||||
if (targetSnapshot.get("dictSort") != null) {
|
||||
exist.setDictSort(((Number) targetSnapshot.get("dictSort")).intValue());
|
||||
}
|
||||
exist.setCssClass((String) targetSnapshot.get("cssClass"));
|
||||
exist.setListClass((String) targetSnapshot.get("listClass"));
|
||||
if (targetSnapshot.get("isDefault") != null) {
|
||||
exist.setIsDefault(((Number) targetSnapshot.get("isDefault")).intValue());
|
||||
}
|
||||
if (targetSnapshot.get("status") != null) {
|
||||
exist.setStatus(((Number) targetSnapshot.get("status")).intValue());
|
||||
}
|
||||
exist.setRemark((String) targetSnapshot.get("remark"));
|
||||
|
||||
// 第六步:版本号递增(回滚也算一次编辑,生成新版本)
|
||||
exist.setVersion(exist.getVersion() + 1);
|
||||
|
||||
// 第七步:更新数据库,update_time 和 update_by 由 MyBatis-Plus 自动填充
|
||||
dictDataMapper.updateById(exist);
|
||||
|
||||
// 转换为 VO 返回
|
||||
return toVO(exist);
|
||||
} catch (JsonProcessingException e) {
|
||||
throw new BusinessException("回滚版本失败: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
+430
@@ -0,0 +1,430 @@
|
||||
package com.roomroot.jwgl.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.roomroot.jwgl.dto.dict.DictTypeQueryDTO;
|
||||
import com.roomroot.jwgl.dto.dict.DictTypeSaveDTO;
|
||||
import com.roomroot.jwgl.entity.SysDictType;
|
||||
import com.roomroot.jwgl.entity.SysDictData;
|
||||
import com.roomroot.jwgl.mapper.DictDataMapper;
|
||||
import com.roomroot.jwgl.mapper.DictTypeMapper;
|
||||
import com.roomroot.jwgl.service.DictTypeService;
|
||||
import com.roomroot.jwgl.unit.BusinessException;
|
||||
import com.roomroot.jwgl.unit.PageResult;
|
||||
import com.roomroot.jwgl.utils.PageResultUtil;
|
||||
import com.roomroot.jwgl.vo.dict.DictTypeVO;
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 字典类型服务实现。
|
||||
* <p>
|
||||
* 实现字典类型的分页查询、保存(新增/编辑)和删除业务逻辑。
|
||||
* 保存时校验编码唯一性,删除时校验是否有关联数据,保证数据完整性。
|
||||
* </p>
|
||||
*/
|
||||
@Service
|
||||
public class DictTypeServiceImpl implements DictTypeService {
|
||||
|
||||
/**
|
||||
* 字典类型数据访问接口。
|
||||
*/
|
||||
@Resource
|
||||
private DictTypeMapper dictTypeMapper;
|
||||
|
||||
/**
|
||||
* 字典数据数据访问接口。
|
||||
* <p>用于删除字典类型时校验是否有关联数据。</p>
|
||||
*/
|
||||
@Resource
|
||||
private DictDataMapper dictDataMapper;
|
||||
|
||||
/**
|
||||
* JSON序列化工具
|
||||
*/
|
||||
private final ObjectMapper objectMapper = new ObjectMapper();
|
||||
|
||||
/**
|
||||
* 分页查询字典类型列表。
|
||||
* <p>
|
||||
* 根据查询条件构建 MyBatis-Plus Lambda 查询包装器,
|
||||
* 支持按关键字(模糊匹配类型编码或名称)、所属分组、状态筛选,
|
||||
* 结果按创建时间降序排列。分页查询完成后将实体列表转换为 VO 列表返回。
|
||||
* </p>
|
||||
*
|
||||
* @param dto 查询条件,包含分页参数和筛选条件
|
||||
* @return 字典类型分页结果
|
||||
*/
|
||||
@Override
|
||||
public PageResult<DictTypeVO> page(DictTypeQueryDTO dto) {
|
||||
// 第一步:创建 MyBatis-Plus 分页对象,传入当前页码和每页大小。
|
||||
Page<SysDictType> page = new Page<>(dto.getPageNum(), dto.getPageSize());
|
||||
// 第二步:构建 Lambda 查询条件包装器。
|
||||
LambdaQueryWrapper<SysDictType> wrapper = new LambdaQueryWrapper<>();
|
||||
|
||||
// 第三步:若有关键字,同时模糊匹配类型编码和类型名称。
|
||||
if (dto.getKeyword() != null && !dto.getKeyword().isEmpty()) {
|
||||
wrapper.and(w -> w.like(SysDictType::getDictTypeCode, dto.getKeyword())
|
||||
.or()
|
||||
.like(SysDictType::getDictTypeName, dto.getKeyword()));
|
||||
}
|
||||
// 第四步:若指定了所属分组,按分组精确匹配。
|
||||
if (dto.getDictGroup() != null && !dto.getDictGroup().isEmpty()) {
|
||||
wrapper.eq(SysDictType::getDictGroup, dto.getDictGroup());
|
||||
}
|
||||
// 第五步:若指定了状态,按状态精确匹配。
|
||||
if (dto.getStatus() != null) {
|
||||
wrapper.eq(SysDictType::getStatus, dto.getStatus());
|
||||
}
|
||||
// 第六步:按创建时间降序排列,新创建的类型排在前面。
|
||||
wrapper.orderByDesc(SysDictType::getCreateTime);
|
||||
|
||||
// 第七步:执行分页查询。
|
||||
Page<SysDictType> result = dictTypeMapper.selectPage(page, wrapper);
|
||||
// 第八步:将查询结果的实体列表转换为 VO 列表。
|
||||
List<DictTypeVO> records = result.getRecords().stream()
|
||||
.map(this::toVO)
|
||||
.collect(Collectors.toList());
|
||||
// 第九步:使用分页工具组装统一分页结果返回。
|
||||
return PageResultUtil.fromRecords(
|
||||
result,
|
||||
records,
|
||||
dto.getPageNum(),
|
||||
dto.getPageSize());
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存字典类型(新增或编辑)。
|
||||
* <p>
|
||||
* 根据 {@code dto.dictTypeId} 判断是新增还是编辑:
|
||||
* <ul>
|
||||
* <li>新增:校验类型编码全局唯一,构建实体后插入数据库。</li>
|
||||
* <li>编辑:查询原记录,若修改了编码则重新校验唯一性,更新字段后写入数据库。</li>
|
||||
* </ul>
|
||||
* 整个操作在事务中执行,保证数据一致性。
|
||||
* </p>
|
||||
*
|
||||
* @param dto 保存参数
|
||||
* @return 保存后的字典类型 VO
|
||||
*/
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public DictTypeVO save(DictTypeSaveDTO dto) {
|
||||
// 分支一:dictTypeId 为空,执行新增操作。
|
||||
if (dto.getDictTypeId() == null) {
|
||||
// 第一步:校验字典类型编码是否已存在。
|
||||
LambdaQueryWrapper<SysDictType> wrapper = new LambdaQueryWrapper<>();
|
||||
wrapper.eq(SysDictType::getDictTypeCode, dto.getDictTypeCode());
|
||||
if (dictTypeMapper.selectCount(wrapper) > 0) {
|
||||
throw new BusinessException("字典类型编码已存在");
|
||||
}
|
||||
|
||||
// 第二步:构建字典类型实体并赋值。
|
||||
SysDictType entity = new SysDictType();
|
||||
entity.setDictTypeCode(dto.getDictTypeCode());
|
||||
entity.setDictTypeName(dto.getDictTypeName());
|
||||
entity.setDictGroup(dto.getDictGroup());
|
||||
entity.setStatus(dto.getStatus());
|
||||
entity.setRemark(dto.getRemark());
|
||||
|
||||
// --- 版本控制:新增时初始化版本号为1,历史快照为空数组 ---
|
||||
// 后续每次编辑都会通过 saveSnapshot 方法追加历史快照并递增版本号
|
||||
entity.setVersion(1);
|
||||
entity.setPrevSnapshot("[]");
|
||||
|
||||
// --- 逻辑删除:新增时显式标记为未删除 ---
|
||||
// @TableLogic 注解会使 MyBatis-Plus 自动在查询中追加 WHERE is_deleted=0 条件
|
||||
// 此处显式赋值,确保即使数据库默认值未生效也能正确标记
|
||||
entity.setIsDeleted(0);
|
||||
|
||||
// 第三步:插入数据库,create_time 和 create_by 由 MyBatis-Plus 自动填充。
|
||||
dictTypeMapper.insert(entity);
|
||||
// 第四步:转换为 VO 返回。
|
||||
return toVO(entity);
|
||||
} else {
|
||||
// 分支二:dictTypeId 有值,执行编辑操作。
|
||||
// 第一步:根据 ID 查询原记录。
|
||||
SysDictType exist = dictTypeMapper.selectById(dto.getDictTypeId());
|
||||
if (exist == null) {
|
||||
throw new BusinessException("字典类型不存在");
|
||||
}
|
||||
|
||||
// 第二步:若修改了类型编码,校验新编码是否与其他记录冲突。
|
||||
if (!exist.getDictTypeCode().equals(dto.getDictTypeCode())) {
|
||||
LambdaQueryWrapper<SysDictType> wrapper = new LambdaQueryWrapper<>();
|
||||
wrapper.eq(SysDictType::getDictTypeCode, dto.getDictTypeCode());
|
||||
if (dictTypeMapper.selectCount(wrapper) > 0) {
|
||||
throw new BusinessException("字典类型编码已存在");
|
||||
}
|
||||
}
|
||||
|
||||
// --- 版本控制逻辑:将编辑前的旧数据存入历史快照 ---
|
||||
// saveSnapshot 方法会把当前 exist 对象(旧数据)转为 JSON 快照追加到 prevSnapshot 中,
|
||||
// 随后 exist 的字段会被新值覆盖,版本号递增后写回数据库
|
||||
saveSnapshot(exist);
|
||||
|
||||
// 第三步:更新实体字段。
|
||||
exist.setDictTypeCode(dto.getDictTypeCode());
|
||||
exist.setDictTypeName(dto.getDictTypeName());
|
||||
exist.setDictGroup(dto.getDictGroup());
|
||||
exist.setStatus(dto.getStatus());
|
||||
exist.setRemark(dto.getRemark());
|
||||
|
||||
// 版本号递增(每次编辑产生新版本,旧版本已在 saveSnapshot 中存入历史)
|
||||
exist.setVersion(exist.getVersion() + 1);
|
||||
|
||||
// 第四步:更新数据库,update_time 和 update_by 由 MyBatis-Plus 自动填充。
|
||||
dictTypeMapper.updateById(exist);
|
||||
// 第五步:转换为 VO 返回。
|
||||
return toVO(exist);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存历史版本快照。
|
||||
* <p>
|
||||
* 将编辑前的实体对象构建为 JSON 快照,追加到 {@code prevSnapshot} 字段中。
|
||||
* 快照 JSON 结构示例:
|
||||
* <pre>
|
||||
* [
|
||||
* {
|
||||
* "version": 1,
|
||||
* "snapshotTime": "2026-08-01T10:00:00",
|
||||
* "dictTypeCode": "course_type",
|
||||
* "dictTypeName": "课程类型",
|
||||
* "dictGroup": "教学数据",
|
||||
* "status": 1,
|
||||
* "remark": "初始版本"
|
||||
* }
|
||||
* ]
|
||||
* </pre>
|
||||
* 历史版本数量上限为 20 个,超出后自动丢弃最早的版本。
|
||||
* </p>
|
||||
*
|
||||
* @param exist 编辑前的实体对象(即当前数据库中的旧数据)
|
||||
*/
|
||||
private void saveSnapshot(SysDictType exist) {
|
||||
try {
|
||||
// 构建当前版本的快照对象,包含版本号和所有业务字段
|
||||
Map<String, Object> snapshot = new HashMap<>();
|
||||
// 记录当前版本号,用于后续版本回滚时定位
|
||||
snapshot.put("version", exist.getVersion());
|
||||
// 记录快照生成时间,便于版本比对
|
||||
snapshot.put("snapshotTime", LocalDateTime.now().toString());
|
||||
// 注意:此处简化处理,实际项目中可能需要从安全上下文中获取操作人ID
|
||||
// snapshot.put("operatorId", SecurityUtils.getCurrentUserId());
|
||||
|
||||
// 保存业务字段(不含版本号、快照、删除标记等系统字段,仅记录业务数据)
|
||||
snapshot.put("dictTypeCode", exist.getDictTypeCode());
|
||||
snapshot.put("dictTypeName", exist.getDictTypeName());
|
||||
snapshot.put("dictGroup", exist.getDictGroup());
|
||||
snapshot.put("status", exist.getStatus());
|
||||
snapshot.put("remark", exist.getRemark());
|
||||
|
||||
// 解析现有的快照历史(prevSnapshot 为空时初始化为空列表)
|
||||
List<Map<String, Object>> history = new ArrayList<>();
|
||||
if (exist.getPrevSnapshot() != null && !exist.getPrevSnapshot().isEmpty()) {
|
||||
history = objectMapper.readValue(exist.getPrevSnapshot(),
|
||||
new TypeReference<List<Map<String, Object>>>() {});
|
||||
}
|
||||
|
||||
// 将当前快照追加到历史列表末尾
|
||||
history.add(snapshot);
|
||||
|
||||
// 限制历史版本数量(例如最多保留20个版本),超出则丢弃最早的版本
|
||||
// 保证 prevSnapshot 字段不会无限增长
|
||||
while (history.size() > 20) {
|
||||
history.remove(0);
|
||||
}
|
||||
|
||||
// 将更新后的历史记录序列化为 JSON 并写回实体
|
||||
// 注意:此处仅修改了实体对象的 prevSnapshot 字段,
|
||||
// 实际持久化由调用方(save/rollback 方法中的 updateById)完成
|
||||
exist.setPrevSnapshot(objectMapper.writeValueAsString(history));
|
||||
} catch (JsonProcessingException e) {
|
||||
throw new BusinessException("保存版本快照失败: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除字典类型。
|
||||
* <p>
|
||||
* 删除前先校验字典类型是否存在,再通过字典类型编码查询该类型下是否有关联的字典数据项。
|
||||
* 若存在数据项,抛出业务异常禁止删除;若不存在,执行逻辑删除(is_deleted置为1)。
|
||||
* 整个操作在事务中执行。
|
||||
* </p>
|
||||
*
|
||||
* @param dictTypeId 字典类型ID
|
||||
*/
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void delete(Long dictTypeId) {
|
||||
// 第一步:根据 ID 查询字典类型。
|
||||
SysDictType exist = dictTypeMapper.selectById(dictTypeId);
|
||||
if (exist == null) {
|
||||
throw new BusinessException("字典类型不存在");
|
||||
}
|
||||
|
||||
// 第二步:通过类型编码查询该类型下是否有关联的字典数据项。
|
||||
LambdaQueryWrapper<SysDictData> wrapper = new LambdaQueryWrapper<>();
|
||||
wrapper.eq(SysDictData::getDictTypeCode, exist.getDictTypeCode());
|
||||
if (dictDataMapper.selectCount(wrapper) > 0) {
|
||||
throw new BusinessException("该字典类型下存在数据项,无法删除");
|
||||
}
|
||||
|
||||
// 第三步:执行删除。
|
||||
// 由于 SysDictType 实体类已添加 @TableLogic 注解,MyBatis-Plus 会自动将
|
||||
// deleteById 转换为 UPDATE sys_dict_type SET is_deleted = 1 WHERE dict_type_id = ?
|
||||
// 即逻辑删除(标记为已删除),而非物理删除,保留历史数据以便版本回溯
|
||||
dictTypeMapper.deleteById(dictTypeId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 将字典类型实体转换为展示对象。
|
||||
* <p>
|
||||
* 提取实体中的有效字段赋值给 VO,用于对外返回统一的数据结构。
|
||||
* </p>
|
||||
*
|
||||
* @param entity 字典类型实体
|
||||
* @return 字典类型 VO
|
||||
*/
|
||||
private DictTypeVO toVO(SysDictType entity) {
|
||||
DictTypeVO vo = new DictTypeVO();
|
||||
vo.setDictTypeId(entity.getDictTypeId());
|
||||
vo.setDictTypeCode(entity.getDictTypeCode());
|
||||
vo.setDictTypeName(entity.getDictTypeName());
|
||||
vo.setDictGroup(entity.getDictGroup());
|
||||
vo.setStatus(entity.getStatus());
|
||||
vo.setRemark(entity.getRemark());
|
||||
|
||||
// 版本控制字段
|
||||
vo.setVersion(entity.getVersion());
|
||||
vo.setPrevSnapshot(entity.getPrevSnapshot());
|
||||
|
||||
vo.setCreateTime(entity.getCreateTime());
|
||||
vo.setUpdateTime(entity.getUpdateTime());
|
||||
return vo;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取字典类型的历史版本列表。
|
||||
* <p>
|
||||
* 根据字典类型ID查询其 {@code prevSnapshot} 字段中存储的所有历史快照,
|
||||
* 解析为版本列表返回。每个版本快照包含版本号、快照时间和当时的业务字段值。
|
||||
* 当 {@code prevSnapshot} 为空时返回空列表。
|
||||
* </p>
|
||||
*
|
||||
* @param dictTypeId 字典类型ID
|
||||
* @return 历史版本快照列表,每个元素为一个 Map,包含 version、snapshotTime 及各业务字段
|
||||
*/
|
||||
@Override
|
||||
public List<Map<String, Object>> getHistory(Long dictTypeId) {
|
||||
// 根据 ID 查询字典类型(@TableLogic 自动过滤已删除记录)
|
||||
SysDictType exist = dictTypeMapper.selectById(dictTypeId);
|
||||
if (exist == null) {
|
||||
throw new BusinessException("字典类型不存在");
|
||||
}
|
||||
try {
|
||||
// 如果 prevSnapshot 为空或空字符串,直接返回空列表
|
||||
if (exist.getPrevSnapshot() == null || exist.getPrevSnapshot().isEmpty()) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
// 将 prevSnapshot JSON 解析为版本列表返回
|
||||
return objectMapper.readValue(exist.getPrevSnapshot(),
|
||||
new TypeReference<List<Map<String, Object>>>() {});
|
||||
} catch (JsonProcessingException e) {
|
||||
throw new BusinessException("获取历史版本失败: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 回滚字典类型到指定版本。
|
||||
* <p>
|
||||
* 根据目标版本号从历史快照 {@code prevSnapshot} 中查找对应的快照数据,
|
||||
* 将当前数据恢复到该版本的状态。回滚操作本身也会生成新的版本快照,
|
||||
* 保证版本链的完整性(回滚前的当前状态也被保留)。
|
||||
* </p>
|
||||
* <p>
|
||||
* 执行步骤:
|
||||
* <ol>
|
||||
* <li>查询字典类型是否存在</li>
|
||||
* <li>从 prevSnapshot 中解析历史版本列表</li>
|
||||
* <li>查找目标版本号对应的快照</li>
|
||||
* <li>将当前状态保存为新版本快照(回滚前的状态入历史)</li>
|
||||
* <li>从目标快照中恢复业务字段值</li>
|
||||
* <li>版本号递增并更新数据库</li>
|
||||
* </ol>
|
||||
* </p>
|
||||
*
|
||||
* @param dictTypeId 字典类型ID
|
||||
* @param targetVersion 目标版本号,必须存在于历史快照中
|
||||
* @return 回滚后的字典类型详情
|
||||
*/
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public DictTypeVO rollback(Long dictTypeId, Integer targetVersion) {
|
||||
// 第一步:查询字典类型是否存在(@TableLogic 自动过滤已删除记录)
|
||||
SysDictType exist = dictTypeMapper.selectById(dictTypeId);
|
||||
if (exist == null) {
|
||||
throw new BusinessException("字典类型不存在");
|
||||
}
|
||||
|
||||
try {
|
||||
// 第二步:从 prevSnapshot 中解析历史版本列表
|
||||
List<Map<String, Object>> history = new ArrayList<>();
|
||||
if (exist.getPrevSnapshot() != null && !exist.getPrevSnapshot().isEmpty()) {
|
||||
history = objectMapper.readValue(exist.getPrevSnapshot(),
|
||||
new TypeReference<List<Map<String, Object>>>() {});
|
||||
}
|
||||
|
||||
// 第三步:在历史列表中查找目标版本号对应的快照
|
||||
Map<String, Object> targetSnapshot = null;
|
||||
for (Map<String, Object> snapshot : history) {
|
||||
if (targetVersion.equals(snapshot.get("version"))) {
|
||||
targetSnapshot = snapshot;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// 如果目标版本不存在,抛出异常
|
||||
if (targetSnapshot == null) {
|
||||
throw new BusinessException("目标版本不存在");
|
||||
}
|
||||
|
||||
// 第四步:将当前状态保存为新版本快照
|
||||
// (回滚操作本身也是一次编辑,回滚前的状态需要保留在历史中)
|
||||
saveSnapshot(exist);
|
||||
|
||||
// 第五步:从目标快照中恢复业务字段值
|
||||
exist.setDictTypeCode((String) targetSnapshot.get("dictTypeCode"));
|
||||
exist.setDictTypeName((String) targetSnapshot.get("dictTypeName"));
|
||||
exist.setDictGroup((String) targetSnapshot.get("dictGroup"));
|
||||
if (targetSnapshot.get("status") != null) {
|
||||
exist.setStatus(((Number) targetSnapshot.get("status")).intValue());
|
||||
}
|
||||
exist.setRemark((String) targetSnapshot.get("remark"));
|
||||
|
||||
// 第六步:版本号递增(回滚也算一次编辑,生成新版本)
|
||||
exist.setVersion(exist.getVersion() + 1);
|
||||
|
||||
// 第七步:更新数据库,update_time 和 update_by 由 MyBatis-Plus 自动填充
|
||||
dictTypeMapper.updateById(exist);
|
||||
|
||||
// 转换为 VO 返回
|
||||
return toVO(exist);
|
||||
} catch (JsonProcessingException e) {
|
||||
throw new BusinessException("回滚版本失败: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
+69
@@ -0,0 +1,69 @@
|
||||
package com.roomroot.jwgl.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.roomroot.jwgl.entity.XKZYXX;
|
||||
import com.roomroot.jwgl.mapper.XKZYXXMapper;
|
||||
import com.roomroot.jwgl.service.DisciplineService;
|
||||
import com.roomroot.jwgl.unit.PageQuery;
|
||||
import com.roomroot.jwgl.unit.PageResult;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import jakarta.annotation.Resource;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 学科专业管理服务实现类
|
||||
* <p>
|
||||
* 实现学科、专业的增加、删除(逻辑删除)、更新、分页查询等功能。
|
||||
* 逻辑删除将 停用 字段置为 1(停用=0为启用,停用=1为已停用/删除)。
|
||||
* </p>
|
||||
*/
|
||||
@Service
|
||||
public class DisciplineServiceImpl implements DisciplineService {
|
||||
|
||||
@Resource
|
||||
private XKZYXXMapper xkzyxxMapper;
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public void add(XKZYXX entity) {
|
||||
entity.setTy(0);
|
||||
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
||||
entity.setTysj(sdf.format(new Date()));
|
||||
xkzyxxMapper.insert(entity);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public void disable(String bsh) {
|
||||
XKZYXX entity = new XKZYXX();
|
||||
entity.setBsh(bsh);
|
||||
entity.setTy(1);
|
||||
xkzyxxMapper.updateById(entity);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public void update(XKZYXX entity) {
|
||||
xkzyxxMapper.updateById(entity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public XKZYXX getById(String bsh) {
|
||||
LambdaQueryWrapper<XKZYXX> wrapper = new LambdaQueryWrapper<>();
|
||||
wrapper.eq(XKZYXX::getBsh, bsh)
|
||||
.eq(XKZYXX::getTy, 0);
|
||||
return xkzyxxMapper.selectOne(wrapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PageResult<XKZYXX> pageList(PageQuery query, XKZYXX xkzyxx) {
|
||||
Page<XKZYXX> page = new Page<>(query.getPageNum(), query.getPageSize());
|
||||
Page<XKZYXX> result = xkzyxxMapper.selectPageList(page, xkzyxx);
|
||||
return new PageResult<>(result.getRecords(), result.getTotal(),
|
||||
query.getPageNum(), query.getPageSize());
|
||||
}
|
||||
}
|
||||
+435
@@ -0,0 +1,435 @@
|
||||
package com.roomroot.jwgl.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.roomroot.jwgl.dto.elective.AddClassDTO;
|
||||
import com.roomroot.jwgl.entity.*;
|
||||
import com.roomroot.jwgl.mapper.*;
|
||||
import com.roomroot.jwgl.vo.elective.*;
|
||||
import com.roomroot.jwgl.mapper.*;
|
||||
import com.roomroot.jwgl.service.BuildService;
|
||||
import com.roomroot.jwgl.service.ElectiveService;
|
||||
import com.roomroot.jwgl.unit.BusinessException;
|
||||
import com.roomroot.jwgl.unit.PageQuery;
|
||||
import com.roomroot.jwgl.unit.PageResult;
|
||||
import com.roomroot.jwgl.utils.UuidUtil;
|
||||
import com.roomroot.jwgl.vo.elective.*;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
import java.util.List;
|
||||
|
||||
@Service
|
||||
public class ElectiveServiceImpl implements ElectiveService {
|
||||
|
||||
@Resource
|
||||
private XYDBMapper xydbMapper;
|
||||
|
||||
@Resource
|
||||
private XYDQBMapper xydqbMapper;
|
||||
|
||||
@Resource
|
||||
private SSKCBXYDMapper sskcbxydMapper;
|
||||
|
||||
@Resource
|
||||
private XYXXMapper xyxxMapper;
|
||||
|
||||
@Resource
|
||||
private XYKCCJMapper xykccjMapper;
|
||||
|
||||
@Resource
|
||||
private XYJXQJBMapper xyjxqjbMapper;
|
||||
|
||||
@Resource
|
||||
private BuildService buildService;
|
||||
|
||||
@Resource
|
||||
private ClassRoomMapper classRoomMapper;
|
||||
|
||||
@Resource
|
||||
private ClassSemesterMapper classSemesterMapper;
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public void add(AddClassDTO dto) {
|
||||
XYDB entity = dto.getClazz();
|
||||
xydbMapper.insert(entity);
|
||||
// 同时写入学员队期表(学号规则、注册设置)
|
||||
XYDQB period = dto.getPeriod();
|
||||
if (period != null) {
|
||||
period.setXydbh(entity.getXydbh());
|
||||
xydqbMapper.insert(period);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public void disable(String xydbh) {
|
||||
// 删除关联的学员队期记录
|
||||
LambdaQueryWrapper<XYDQB> wrapper = new LambdaQueryWrapper<>();
|
||||
wrapper.eq(XYDQB::getXydbh, xydbh);
|
||||
xydqbMapper.delete(wrapper);
|
||||
// 物理删除教学班次
|
||||
xydbMapper.deleteById(xydbh);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public void update(XYDB entity) {
|
||||
xydbMapper.updateById(entity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public XYDB getById(String xydbh) {
|
||||
return xydbMapper.selectById(xydbh);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PageResult<XYDB> pageList(PageQuery query, XYDB cond) {
|
||||
Page<XYDB> page = new Page<>(query.getPageNum(), query.getPageSize());
|
||||
Page<XYDB> result = xydbMapper.selectPageList(page, cond);
|
||||
return new PageResult<>(result.getRecords(), result.getTotal(),
|
||||
query.getPageNum(), query.getPageSize());
|
||||
}
|
||||
|
||||
@Override
|
||||
public PageResult<ElectiveClassVO> pageListWithPeriod(PageQuery query, ElectiveClassVO cond) {
|
||||
Page<ElectiveClassVO> page = new Page<>(query.getPageNum(), query.getPageSize());
|
||||
Page<ElectiveClassVO> result = xydbMapper.selectPageListWithPeriod(page, cond);
|
||||
return new PageResult<>(result.getRecords(), result.getTotal(),
|
||||
query.getPageNum(), query.getPageSize());
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<XYDB> filterByDateRange(LocalDateTime startTime, LocalDateTime endTime) {
|
||||
// 将 LocalDateTime 转换为字符串格式(达梦数据库要求)
|
||||
String startTimeStr = startTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm"));
|
||||
String endTimeStr = endTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm"));
|
||||
return xydbMapper.selectByDateRange(startTimeStr, endTimeStr);
|
||||
}
|
||||
|
||||
@Override
|
||||
public XYDQB getPeriodByXydbh(String xydbh) {
|
||||
LambdaQueryWrapper<XYDQB> wrapper = new LambdaQueryWrapper<>();
|
||||
wrapper.eq(XYDQB::getXydbh, xydbh);
|
||||
return xydqbMapper.selectOne(wrapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public void updatePeriod(XYDQB entity) {
|
||||
xydqbMapper.updateById(entity);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public void setRegistrationEnabled(String xydbh, Integer enabled) {
|
||||
XYDQB entity = getPeriodByXydbh(xydbh);
|
||||
if (entity != null) {
|
||||
entity.setYxzc(enabled);
|
||||
xydqbMapper.updateById(entity);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String generateNextStudentNumber(String xydbh) {
|
||||
XYDB clazz = xydbMapper.selectById(xydbh);
|
||||
if (clazz == null || clazz.getRxrq() == null) {
|
||||
throw new RuntimeException("教学班次不存在或未设置入学日期");
|
||||
}
|
||||
|
||||
// 入学日期前缀:yyyyMMdd
|
||||
String prefix = clazz.getRxrq().format(DateTimeFormatter.ofPattern("yyyyMMdd"));
|
||||
|
||||
// 查询该班次已生成的最大学号
|
||||
LambdaQueryWrapper<XYDQB> wrapper = new LambdaQueryWrapper<>();
|
||||
wrapper.eq(XYDQB::getXydbh, xydbh);
|
||||
XYDQB period = xydqbMapper.selectOne(wrapper);
|
||||
|
||||
// 取学号位数,默认3位
|
||||
int digits = (period != null && period.getXhws() != null) ? period.getXhws() : 3;
|
||||
|
||||
// 查询该前缀下已有最大流水号(通过学员信息表或其他方式)
|
||||
// 简单实现:从1开始,按prefix+流水号查询最大数
|
||||
String studentNumber = prefix + String.format("%0" + digits + "d", 1);
|
||||
return studentNumber;
|
||||
}
|
||||
|
||||
// ========== 关联信息查询 ==========
|
||||
|
||||
@Override
|
||||
public List<ClassScheduleVO> getClassCourses(String xydbh, Integer nd) {
|
||||
return sskcbxydMapper.selectScheduleByXydbh(xydbh, nd);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ClassScheduleVO> getClassSchedule(String xydbh, Integer nd) {
|
||||
return sskcbxydMapper.selectScheduleByXydbh(xydbh, nd);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<XYXX> getClassStudents(String xydbh) {
|
||||
// 先查学员队期编号
|
||||
LambdaQueryWrapper<XYDQB> pw = new LambdaQueryWrapper<>();
|
||||
pw.eq(XYDQB::getXydbh, xydbh);
|
||||
XYDQB period = xydqbMapper.selectOne(pw);
|
||||
if (period == null) return new java.util.ArrayList<>();
|
||||
// 再查学员
|
||||
LambdaQueryWrapper<XYXX> wrapper = new LambdaQueryWrapper<>();
|
||||
wrapper.eq(XYXX::getXydqbh, period.getBh());
|
||||
return xyxxMapper.selectList(wrapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<StudentGradeVO> getClassGrades(String xydbh, String kmbh) {
|
||||
// 学员课程成绩 + 学员信息表联查
|
||||
return xykccjMapper.selectGradeByXydbh(xydbh, kmbh);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<StudentAbsenceVO> getClassAbsences(String xydbh, Integer nd) {
|
||||
return xyjxqjbMapper.selectAbsenceByXydbh(xydbh, nd);
|
||||
}
|
||||
|
||||
// ========== 教学班次学期信息设置 ==========
|
||||
|
||||
@Override
|
||||
public List<JXLB> listBuildings() {
|
||||
return buildService.list(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<JSB> listRooms(String jxldh, String py) {
|
||||
LambdaQueryWrapper<JSB> wrapper = new LambdaQueryWrapper<>();
|
||||
if (jxldh != null && !jxldh.isEmpty()) {
|
||||
wrapper.eq(JSB::getJxldh, jxldh);
|
||||
}
|
||||
if (py != null && !py.isEmpty()) {
|
||||
wrapper.like(JSB::getPy, py);
|
||||
}
|
||||
wrapper.orderByAsc(JSB::getXh);
|
||||
return classRoomMapper.selectList(wrapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SemesterInitVO getSemesterInit(String xydbh, String presetKxrq, String presetJsrq) {
|
||||
XYDB clazz = xydbMapper.selectById(xydbh);
|
||||
if (clazz == null) {
|
||||
throw new BusinessException("教学班次不存在:" + xydbh);
|
||||
}
|
||||
|
||||
LocalDate rx = clazz.getRxrq() != null ? clazz.getRxrq().toLocalDate() : null;
|
||||
LocalDate by = clazz.getByrq() != null ? clazz.getByrq().toLocalDate() : null;
|
||||
|
||||
// 判断学制是否半年以内
|
||||
boolean halfYear = isHalfYear(rx, by);
|
||||
|
||||
// 学期第次:半年以内固定第一学期;半年以上按入学日期智能推断
|
||||
Integer xqdc = halfYear ? 1 : inferXqdc(rx, by, LocalDate.now());
|
||||
// 人才培养方案总学期数(半年一学期,向上取整)
|
||||
Integer totalXqdc = calcTotalXqdc(rx, by);
|
||||
|
||||
// 开学/结束日期:半年以内默认入学/毕业日期;半年以上默认窗口预设日期
|
||||
LocalDate kxrq;
|
||||
LocalDate jsrq;
|
||||
if (halfYear) {
|
||||
kxrq = rx;
|
||||
jsrq = by;
|
||||
} else {
|
||||
kxrq = parseDate(presetKxrq);
|
||||
jsrq = parseDate(presetJsrq);
|
||||
}
|
||||
|
||||
// 第二以上学期:默认预设上学期的专用教室
|
||||
String zyjsbh = getPrevRoom(xydbh, xqdc);
|
||||
String zyjsmc = null;
|
||||
if (zyjsbh != null && !zyjsbh.isEmpty()) {
|
||||
JSB room = classRoomMapper.selectById(zyjsbh);
|
||||
if (room != null) {
|
||||
zyjsmc = room.getJsmc();
|
||||
}
|
||||
}
|
||||
|
||||
SemesterInitVO vo = new SemesterInitVO();
|
||||
vo.setXydbh(xydbh);
|
||||
vo.setXydmc(clazz.getXydmc());
|
||||
vo.setHalfYear(halfYear);
|
||||
vo.setXqdc(xqdc);
|
||||
vo.setTotalXqdc(totalXqdc);
|
||||
vo.setKxrq(kxrq);
|
||||
vo.setJsrq(jsrq);
|
||||
vo.setZyjsbh(zyjsbh);
|
||||
vo.setZyjsmc(zyjsmc);
|
||||
vo.setJclb(clazz.getJclb());
|
||||
return vo;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void addSemester(XYDNDXQJBXXB xydndxqjbxxb) {
|
||||
if (xydndxqjbxxb == null || xydndxqjbxxb.getXydbh() == null || xydndxqjbxxb.getXydbh().isEmpty()) {
|
||||
throw new BusinessException("班次编号不能为空");
|
||||
}
|
||||
XYDB clazz = xydbMapper.selectById(xydndxqjbxxb.getXydbh());
|
||||
if (clazz == null) {
|
||||
throw new BusinessException("教学班次不存在:" + xydndxqjbxxb.getXydbh());
|
||||
}
|
||||
|
||||
LocalDate rx = clazz.getRxrq() != null ? clazz.getRxrq().toLocalDate() : null;
|
||||
LocalDate by = clazz.getByrq() != null ? clazz.getByrq().toLocalDate() : null;
|
||||
boolean halfYear = isHalfYear(rx, by);
|
||||
|
||||
// 学期第次:半年以内只能第一学期;半年以上为空时智能推断
|
||||
Integer xqdc = xydndxqjbxxb.getXqdc();
|
||||
if (halfYear) {
|
||||
if (xqdc != null && xqdc != 1) {
|
||||
throw new BusinessException("学制半年以内的班次,学期第次只能设置为第一学期");
|
||||
}
|
||||
xqdc = 1;
|
||||
} else if (xqdc == null) {
|
||||
xqdc = inferXqdc(rx, by, LocalDate.now());
|
||||
}
|
||||
xydndxqjbxxb.setXqdc(xqdc);
|
||||
|
||||
// 开学/结束日期:半年以内为空时默认入学/毕业日期;半年以上不允许为空(取窗口预设值)
|
||||
if (xydndxqjbxxb.getKxrq() == null) {
|
||||
if (halfYear) {
|
||||
xydndxqjbxxb.setKxrq(rx);
|
||||
} else {
|
||||
throw new BusinessException("学制半年以上的班次,开学日期不能为空,请使用窗口预设开学日期");
|
||||
}
|
||||
}
|
||||
if (xydndxqjbxxb.getJsrq() == null) {
|
||||
if (halfYear) {
|
||||
xydndxqjbxxb.setJsrq(by);
|
||||
} else {
|
||||
throw new BusinessException("学制半年以上的班次,结束日期不能为空,请使用窗口预设结束日期");
|
||||
}
|
||||
}
|
||||
|
||||
// 开学/结束日期先后校验
|
||||
if (xydndxqjbxxb.getKxrq() != null && xydndxqjbxxb.getJsrq() != null
|
||||
&& xydndxqjbxxb.getKxrq().isAfter(xydndxqjbxxb.getJsrq())) {
|
||||
throw new BusinessException("开学日期不能晚于结束日期");
|
||||
}
|
||||
|
||||
// 年度为空时默认入学日期所在年度
|
||||
if (xydndxqjbxxb.getNd() == null) {
|
||||
xydndxqjbxxb.setNd(rx != null ? rx.getYear() : LocalDate.now().getYear());
|
||||
}
|
||||
|
||||
// 第二以上学期:专用教室为空时默认预设上学期的专用教室
|
||||
if (xqdc > 1 && (xydndxqjbxxb.getZyjsbh() == null || xydndxqjbxxb.getZyjsbh().isEmpty())) {
|
||||
xydndxqjbxxb.setZyjsbh(getPrevRoom(xydndxqjbxxb.getXydbh(), xqdc));
|
||||
}
|
||||
|
||||
// 重复校验:同一班次+年度+学期第次不允许重复创建
|
||||
XYDNDXQJBXXB existing = classSemesterMapper.selectByBcAndNdAndXqdc(
|
||||
xydndxqjbxxb.getXydbh(),
|
||||
String.valueOf(xydndxqjbxxb.getNd()),
|
||||
String.valueOf(xqdc));
|
||||
if (existing != null) {
|
||||
throw new BusinessException("该班次 " + xydndxqjbxxb.getNd() + " 年度第 " + xqdc + " 学期的班次学期信息已存在,请勿重复添加");
|
||||
}
|
||||
|
||||
// 默认值填充
|
||||
xydndxqjbxxb.setBh(xydndxqjbxxb.getBh() == null ? UuidUtil.getUUID() : xydndxqjbxxb.getBh());
|
||||
xydndxqjbxxb.setBdsj(xydndxqjbxxb.getBdsj() == null ? LocalDateTime.now() : xydndxqjbxxb.getBdsj());
|
||||
xydndxqjbxxb.setXhbs(xydndxqjbxxb.getXhbs() == null ? 0 : xydndxqjbxxb.getXhbs());
|
||||
xydndxqjbxxb.setYsbbh(xydndxqjbxxb.getYsbbh() == null ? 0 : xydndxqjbxxb.getYsbbh());
|
||||
xydndxqjbxxb.setJclb(xydndxqjbxxb.getJclb() == null
|
||||
? (clazz.getJclb() != null ? clazz.getJclb() : "双节次") : xydndxqjbxxb.getJclb());
|
||||
xydndxqjbxxb.setKfjypk(xydndxqjbxxb.getKfjypk() == null ? 0 : xydndxqjbxxb.getKfjypk());
|
||||
xydndxqjbxxb.setXtms(xydndxqjbxxb.getXtms() == null ? "" : xydndxqjbxxb.getXtms());
|
||||
xydndxqjbxxb.setDelFlag(0);
|
||||
|
||||
classSemesterMapper.insert(xydndxqjbxxb);
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断学制是否半年以内(入学日期到毕业日期不超过 183 天)
|
||||
*/
|
||||
private boolean isHalfYear(LocalDate rx, LocalDate by) {
|
||||
if (rx == null || by == null) {
|
||||
return false;
|
||||
}
|
||||
return ChronoUnit.DAYS.between(rx, by) <= 183;
|
||||
}
|
||||
|
||||
/**
|
||||
* 计算人才培养方案总学期数(半年一学期,向上取整;入学日期缺失时按 1 处理)
|
||||
*/
|
||||
private Integer calcTotalXqdc(LocalDate rx, LocalDate by) {
|
||||
if (rx == null || by == null || !by.isAfter(rx)) {
|
||||
return 1;
|
||||
}
|
||||
long totalMonths = ChronoUnit.MONTHS.between(rx, by);
|
||||
return Math.max(1, (int) ((totalMonths + 5) / 6));
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据班次入学日期智能推断指定日期所在的学期第次(每半年为一个学期)
|
||||
* <p>
|
||||
* 半年以内的班次返回 1;半年以上的班次按 入学日期 到 指定日期 经过的月份
|
||||
* 每 6 个月为 1 个学期递增,且不超过人才培养方案总学期数。
|
||||
* </p>
|
||||
*/
|
||||
private Integer inferXqdc(LocalDate rx, LocalDate by, LocalDate target) {
|
||||
if (rx == null) {
|
||||
return 1;
|
||||
}
|
||||
if (target.isBefore(rx)) {
|
||||
return 1;
|
||||
}
|
||||
// 半年以内固定第一学期
|
||||
if (by != null && isHalfYear(rx, by)) {
|
||||
return 1;
|
||||
}
|
||||
long months = ChronoUnit.MONTHS.between(rx, target);
|
||||
int xqdc = (int) (months / 6) + 1;
|
||||
// 不超过总学期数
|
||||
Integer total = calcTotalXqdc(rx, by);
|
||||
return Math.min(xqdc, total);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取某班次指定学期第次的上一学期专用教室(用于第二以上学期的默认预设)
|
||||
*
|
||||
* @param xydbh 班次编号
|
||||
* @param xqdc 当前学期第次(<=1 时返回 null)
|
||||
* @return 上学期专用教室编号,不存在返回 null
|
||||
*/
|
||||
private String getPrevRoom(String xydbh, Integer xqdc) {
|
||||
if (xqdc == null || xqdc <= 1) {
|
||||
return null;
|
||||
}
|
||||
LambdaQueryWrapper<XYDNDXQJBXXB> wrapper = new LambdaQueryWrapper<>();
|
||||
wrapper.eq(XYDNDXQJBXXB::getXydbh, xydbh)
|
||||
.eq(XYDNDXQJBXXB::getXqdc, xqdc - 1)
|
||||
.eq(XYDNDXQJBXXB::getDelFlag, 0)
|
||||
.orderByDesc(XYDNDXQJBXXB::getNd)
|
||||
.last("LIMIT 1");
|
||||
XYDNDXQJBXXB prev = classSemesterMapper.selectOne(wrapper);
|
||||
return prev == null ? null : prev.getZyjsbh();
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析 yyyy-MM-dd 格式日期字符串,为空或格式错误返回 null
|
||||
*/
|
||||
private LocalDate parseDate(String date) {
|
||||
if (date == null || date.trim().isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
return LocalDate.parse(date.trim(), DateTimeFormatter.ofPattern("yyyy-MM-dd"));
|
||||
} catch (Exception e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
+159
@@ -0,0 +1,159 @@
|
||||
package com.roomroot.jwgl.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.roomroot.jwgl.dto.faculty.AddTeacherDTO;
|
||||
import com.roomroot.jwgl.entity.*;
|
||||
import com.roomroot.jwgl.mapper.*;
|
||||
import com.roomroot.jwgl.mapper.*;
|
||||
import com.roomroot.jwgl.service.FacultyService;
|
||||
import com.roomroot.jwgl.unit.PageQuery;
|
||||
import com.roomroot.jwgl.unit.PageResult;
|
||||
import com.roomroot.jwgl.vo.faculty.TeacherListVO;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import jakarta.annotation.Resource;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* 教研室与教员管理服务实现类
|
||||
* <p>
|
||||
* 实现教研室和教员的增删改查,以及关联属性、综合评定和课程表查询。
|
||||
* </p>
|
||||
*/
|
||||
@Service
|
||||
public class FacultyServiceImpl implements FacultyService {
|
||||
|
||||
@Resource
|
||||
private JYSBMapper jysbMapper;
|
||||
|
||||
@Resource
|
||||
private JYBMapper jybMapper;
|
||||
|
||||
@Resource
|
||||
private JYSXMapper jysxMapper;
|
||||
|
||||
@Resource
|
||||
private NDZHPDJYMapper ndzhpdyMapper;
|
||||
|
||||
@Resource
|
||||
private JYSCKCBMapper jysckcbMapper;
|
||||
|
||||
// ==================== 教研室管理 ====================
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public void addJYSB(JYSB entity) {
|
||||
if (entity.getTy() == null) {
|
||||
entity.setTy(false);
|
||||
}
|
||||
jysbMapper.insert(entity);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public void disableJYSB(String jysdh) {
|
||||
JYSB entity = new JYSB();
|
||||
entity.setJysdh(jysdh);
|
||||
entity.setTy(true);
|
||||
entity.setTysj(LocalDateTime.now());
|
||||
jysbMapper.updateById(entity);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public void updateJYSB(JYSB entity) {
|
||||
jysbMapper.updateById(entity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JYSB getJYSBById(String jysdh) {
|
||||
return jysbMapper.selectById(jysdh);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PageResult<JYSB> pageJYSB(PageQuery query, JYSB cond) {
|
||||
Page<JYSB> page = new Page<>(query.getPageNum(), query.getPageSize());
|
||||
Page<JYSB> result = jysbMapper.selectPageList(page, cond);
|
||||
return new PageResult<>(result.getRecords(), result.getTotal(),
|
||||
query.getPageNum(), query.getPageSize());
|
||||
}
|
||||
|
||||
// ==================== 教员管理 ====================
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public void addJYB(AddTeacherDTO dto) {
|
||||
JYB entity = dto.getTeacher();
|
||||
//离职状态默认为0
|
||||
entity.setLzzt(0);
|
||||
jybMapper.insert(entity);
|
||||
// 使用前端传入的教员属性数据
|
||||
JYSX jysx = dto.getAttributes();
|
||||
if (jysx != null) {
|
||||
jysx.setJybh(entity.getJybh());
|
||||
jysxMapper.insert(jysx);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public void disableJYB(String jybh) {
|
||||
JYB entity = new JYB();
|
||||
entity.setJybh(jybh);
|
||||
entity.setLzzt(1);
|
||||
jybMapper.updateById(entity);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public void updateJYB(JYB entity) {
|
||||
jybMapper.updateById(entity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JYB getJYBById(String jybh) {
|
||||
return jybMapper.selectById(jybh);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PageResult<TeacherListVO> pageJYBDetail(PageQuery query, JYB cond) {
|
||||
Page<TeacherListVO> page = new Page<>(query.getPageNum(), query.getPageSize());
|
||||
Page<TeacherListVO> result = jybMapper.selectTeacherPageList(page, cond);
|
||||
return new PageResult<>(result.getRecords(), result.getTotal(),
|
||||
query.getPageNum(), query.getPageSize());
|
||||
}
|
||||
|
||||
// ==================== 教员属性管理 ====================
|
||||
|
||||
@Override
|
||||
public JYSX getJYSXByJYBH(String jybh) {
|
||||
return jysxMapper.selectById(jybh);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public void updateJYSX(JYSX entity) {
|
||||
jysxMapper.updateById(entity);
|
||||
}
|
||||
|
||||
// ==================== 年度综合评定查询 ====================
|
||||
|
||||
@Override
|
||||
public PageResult<NDZHPDJY> pageNDZHPDJY(PageQuery query, NDZHPDJY cond) {
|
||||
Page<NDZHPDJY> page = new Page<>(query.getPageNum(), query.getPageSize());
|
||||
Page<NDZHPDJY> result = ndzhpdyMapper.selectPageList(page, cond);
|
||||
return new PageResult<>(result.getRecords(), result.getTotal(),
|
||||
query.getPageNum(), query.getPageSize());
|
||||
}
|
||||
|
||||
// ==================== 教员课程表查询 ====================
|
||||
|
||||
@Override
|
||||
public PageResult<JYSCKCB> pageJYSCKCB(PageQuery query, JYSCKCB cond) {
|
||||
Page<JYSCKCB> page = new Page<>(query.getPageNum(), query.getPageSize());
|
||||
Page<JYSCKCB> result = jysckcbMapper.selectPageList(page, cond);
|
||||
return new PageResult<>(result.getRecords(), result.getTotal(),
|
||||
query.getPageNum(), query.getPageSize());
|
||||
}
|
||||
}
|
||||
+59
@@ -0,0 +1,59 @@
|
||||
package com.roomroot.jwgl.service.impl;
|
||||
|
||||
import com.roomroot.jwgl.entity.KCB;
|
||||
import com.roomroot.jwgl.mapper.KCBMapper;
|
||||
import com.roomroot.jwgl.service.KCBService;
|
||||
import com.roomroot.jwgl.utils.UuidUtil;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import jakarta.annotation.Resource;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 课程表服务实现
|
||||
*/
|
||||
@Service
|
||||
public class KCBServiceImpl implements KCBService {
|
||||
|
||||
@Resource
|
||||
private KCBMapper kcbMapper;
|
||||
|
||||
@Override
|
||||
public void add(KCB kcb) {
|
||||
if (kcb.getCjsj() == null) {
|
||||
kcb.setCjsj(LocalDateTime.now());
|
||||
}
|
||||
if (kcb.getBdsj() == null) {
|
||||
kcb.setBdsj(LocalDateTime.now());
|
||||
}
|
||||
kcb.setBh(UuidUtil.getUUID());
|
||||
kcbMapper.insert(kcb);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void delete(String kbh) {
|
||||
kcbMapper.deleteById(kbh);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void batchDelete(List<String> kbhList) {
|
||||
kcbMapper.deleteBatchIds(kbhList);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(KCB kcb) {
|
||||
kcbMapper.updateById(kcb);
|
||||
}
|
||||
|
||||
@Override
|
||||
public KCB getByKbh(String kbh) {
|
||||
return kcbMapper.selectById(kbh);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<KCB> list() {
|
||||
return kcbMapper.selectList(null);
|
||||
}
|
||||
|
||||
}
|
||||
+205
@@ -0,0 +1,205 @@
|
||||
package com.roomroot.jwgl.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.roomroot.jwgl.dto.LeaveDTO;
|
||||
import com.roomroot.jwgl.dto.LeaveQueryDTO;
|
||||
import com.roomroot.jwgl.entity.QJKTB;
|
||||
import com.roomroot.jwgl.entity.QJXYB;
|
||||
import com.roomroot.jwgl.entity.XYJXQJB;
|
||||
import com.roomroot.jwgl.entity.XYQJSPB;
|
||||
import com.roomroot.jwgl.mapper.QJKTBMapper;
|
||||
import com.roomroot.jwgl.mapper.QJXYBMapper;
|
||||
import com.roomroot.jwgl.mapper.XYJXQJBMapper;
|
||||
import com.roomroot.jwgl.mapper.XYQJSPBMapper;
|
||||
import com.roomroot.jwgl.service.LeaveService;
|
||||
import com.roomroot.jwgl.utils.UuidUtil;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import jakarta.annotation.Resource;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 请假服务实现
|
||||
*/
|
||||
@Service
|
||||
public class LeaveServiceImpl implements LeaveService {
|
||||
|
||||
@Resource
|
||||
private XYJXQJBMapper xyjxqjbMapper;
|
||||
|
||||
@Resource
|
||||
private QJKTBMapper qjktbMapper;
|
||||
|
||||
@Resource
|
||||
private QJXYBMapper qjxybMapper;
|
||||
|
||||
@Resource
|
||||
private XYQJSPBMapper xyqjspbMapper;
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void add(LeaveDTO dto) {
|
||||
XYJXQJB leave = dto.getLeave();
|
||||
if (leave.getCjsj() == null) {
|
||||
leave.setCjsj(LocalDateTime.now());
|
||||
}
|
||||
|
||||
// 设置课堂数和学员人数
|
||||
if (dto.getSsktBhList() != null) {
|
||||
leave.setKts(dto.getSsktBhList().size());
|
||||
}
|
||||
if (dto.getXybh() != null) {
|
||||
leave.setXyrs(1);
|
||||
}
|
||||
|
||||
leave.setBh(UuidUtil.getUUID());
|
||||
leave.setZt("待审批");
|
||||
// 插入主表
|
||||
xyjxqjbMapper.insert(leave);
|
||||
String qjbh = leave.getBh();
|
||||
|
||||
// 批量插入请假课堂表
|
||||
if (dto.getSsktBhList() != null) {
|
||||
for (String ssktBh : dto.getSsktBhList()) {
|
||||
QJKTB qjktb = new QJKTB();
|
||||
qjktb.setQjbh(qjbh);
|
||||
qjktb.setSsktbh(ssktBh);
|
||||
qjktb.setBh(UuidUtil.getUUID());
|
||||
qjktbMapper.insert(qjktb);
|
||||
}
|
||||
}
|
||||
|
||||
// 插入请假学员表
|
||||
if (dto.getXybh() != null) {
|
||||
QJXYB qjxyb = new QJXYB();
|
||||
qjxyb.setQjbh(qjbh);
|
||||
qjxyb.setXybh(dto.getXybh());
|
||||
qjxyb.setBh(UuidUtil.getUUID());
|
||||
qjxybMapper.insert(qjxyb);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean update(XYJXQJB xyjxqjb) {
|
||||
// 检查审批表是否有内容
|
||||
if (hasApproval(xyjxqjb.getBh())) {
|
||||
return false;
|
||||
}
|
||||
xyjxqjbMapper.updateById(xyjxqjb);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public boolean delete(String bh) {
|
||||
// 检查审批表是否有内容
|
||||
if (hasApproval(bh)) {
|
||||
return false;
|
||||
}
|
||||
// 删除主表
|
||||
xyjxqjbMapper.deleteById(bh);
|
||||
// 删除请假课堂表
|
||||
LambdaQueryWrapper<QJKTB> qjktbWrapper = new LambdaQueryWrapper<>();
|
||||
qjktbWrapper.eq(QJKTB::getQjbh, bh);
|
||||
qjktbMapper.delete(qjktbWrapper);
|
||||
// 删除请假学员表
|
||||
LambdaQueryWrapper<QJXYB> qjxybWrapper = new LambdaQueryWrapper<>();
|
||||
qjxybWrapper.eq(QJXYB::getQjbh, bh);
|
||||
qjxybMapper.delete(qjxybWrapper);
|
||||
// 删除审批表
|
||||
LambdaQueryWrapper<XYQJSPB> xyqjspbWrapper = new LambdaQueryWrapper<>();
|
||||
xyqjspbWrapper.eq(XYQJSPB::getQjbh, bh);
|
||||
xyqjspbMapper.delete(xyqjspbWrapper);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查请假编号是否存在审批记录
|
||||
*/
|
||||
private boolean hasApproval(String qjbh) {
|
||||
LambdaQueryWrapper<XYQJSPB> wrapper = new LambdaQueryWrapper<>();
|
||||
wrapper.eq(XYQJSPB::getQjbh, qjbh);
|
||||
return xyqjspbMapper.selectCount(wrapper) > 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public XYJXQJB getByBh(String bh) {
|
||||
return xyjxqjbMapper.selectById(bh);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<XYJXQJB> list() {
|
||||
return xyjxqjbMapper.selectList(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<XYJXQJB> list(LeaveQueryDTO queryDTO) {
|
||||
LambdaQueryWrapper<XYJXQJB> wrapper = new LambdaQueryWrapper<>();
|
||||
// 精确匹配
|
||||
wrapper.eq(queryDTO.getBh() != null, XYJXQJB::getBh, queryDTO.getBh());
|
||||
wrapper.eq(queryDTO.getMc() != null, XYJXQJB::getMc, queryDTO.getMc());
|
||||
wrapper.eq(queryDTO.getZt() != null, XYJXQJB::getZt, queryDTO.getZt());
|
||||
wrapper.eq(queryDTO.getXydbh() != null, XYJXQJB::getXydbh, queryDTO.getXydbh());
|
||||
// 起始时间范围查询
|
||||
wrapper.ge(queryDTO.getQssjStart() != null, XYJXQJB::getQssj, queryDTO.getQssjStart());
|
||||
wrapper.le(queryDTO.getQssjEnd() != null, XYJXQJB::getQssj, queryDTO.getQssjEnd());
|
||||
// 结束时间范围查询
|
||||
wrapper.ge(queryDTO.getJssjStart() != null, XYJXQJB::getJssj, queryDTO.getJssjStart());
|
||||
wrapper.le(queryDTO.getJssjEnd() != null, XYJXQJB::getJssj, queryDTO.getJssjEnd());
|
||||
// 创建时间范围查询
|
||||
wrapper.ge(queryDTO.getCjsjStart() != null, XYJXQJB::getCjsj, queryDTO.getCjsjStart());
|
||||
wrapper.le(queryDTO.getCjsjEnd() != null, XYJXQJB::getCjsj, queryDTO.getCjsjEnd());
|
||||
return xyjxqjbMapper.selectList(wrapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> listClassroomBhsByQjbh(String qjbh) {
|
||||
LambdaQueryWrapper<QJKTB> wrapper = new LambdaQueryWrapper<>();
|
||||
wrapper.eq(QJKTB::getQjbh, qjbh);
|
||||
List<QJKTB> list = qjktbMapper.selectList(wrapper);
|
||||
return list.stream().map(QJKTB::getSsktbh).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> listStudentBhsByQjbh(String qjbh) {
|
||||
LambdaQueryWrapper<QJXYB> wrapper = new LambdaQueryWrapper<>();
|
||||
wrapper.eq(QJXYB::getQjbh, qjbh);
|
||||
List<QJXYB> list = qjxybMapper.selectList(wrapper);
|
||||
return list.stream().map(QJXYB::getXybh).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
// ===== 审批表 CRUD =====
|
||||
|
||||
@Override
|
||||
public void addApproval(XYQJSPB xyqjspb) {
|
||||
if (xyqjspb.getSpsj() == null) {
|
||||
xyqjspb.setSpsj(LocalDateTime.now());
|
||||
}
|
||||
xyqjspbMapper.insert(xyqjspb);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteApproval(String bh) {
|
||||
xyqjspbMapper.deleteById(bh);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateApproval(XYQJSPB xyqjspb) {
|
||||
xyqjspbMapper.updateById(xyqjspb);
|
||||
}
|
||||
|
||||
@Override
|
||||
public XYQJSPB getApprovalByBh(String bh) {
|
||||
return xyqjspbMapper.selectById(bh);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<XYQJSPB> listApprovalsByQjbh(String qjbh) {
|
||||
LambdaQueryWrapper<XYQJSPB> wrapper = new LambdaQueryWrapper<>();
|
||||
wrapper.eq(XYQJSPB::getQjbh, qjbh);
|
||||
return xyqjspbMapper.selectList(wrapper);
|
||||
}
|
||||
}
|
||||
+766
@@ -0,0 +1,766 @@
|
||||
package com.roomroot.jwgl.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.roomroot.jwgl.entity.*;
|
||||
import com.roomroot.jwgl.mapper.*;
|
||||
import com.roomroot.jwgl.mapper.*;
|
||||
import com.roomroot.jwgl.service.LogService;
|
||||
import com.roomroot.jwgl.unit.PageQuery;
|
||||
import com.roomroot.jwgl.unit.PageResult;
|
||||
import com.roomroot.jwgl.vo.log.TeacherHoursVO;
|
||||
import com.roomroot.jwgl.vo.log.TeachingLogListVO;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import jakarta.annotation.Resource;
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
/**
|
||||
* 教学日志管理服务实现
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
public class LogServiceImpl implements LogService {
|
||||
|
||||
@Resource
|
||||
private BCKTJXRZMapper bcktjxrzMapper;
|
||||
@Resource
|
||||
private SSKCB_RZMapper sskcbRzMapper;
|
||||
@Resource
|
||||
private BCKTJXRZSKJYMapper bcktjxrzskyMapper;
|
||||
@Resource
|
||||
private JXRZJYKSBZMapper jxrzjyksbzMapper;
|
||||
@Resource
|
||||
private JXRZKSBZSPBMapper jxrzksbzspbMapper;
|
||||
@Resource
|
||||
private JYKSBZMapper jyksbzMapper;
|
||||
@Resource
|
||||
private KSFBZMapper ksfbzMapper;
|
||||
@Resource
|
||||
private JSZWKSFBZMapper jszwksfbzMapper;
|
||||
@Resource
|
||||
private JYNZKSFMapper jynzksfMapper;
|
||||
@Resource
|
||||
private NZKSFMapper nzksfMapper;
|
||||
@Resource
|
||||
private KSBZXMMapper ksbzxmMapper;
|
||||
@Resource
|
||||
private SSKCBMapper sskcbMapper;
|
||||
@Resource
|
||||
private JXSSJHTJBMapper jxssjhtjbMapper;
|
||||
@Resource
|
||||
private KSHBZMapper kshbzMapper;
|
||||
|
||||
@Resource
|
||||
private KSXSFAMapper ksxsfaMapper;
|
||||
|
||||
@Resource
|
||||
private JZGZLMapper jzgzlMapper;
|
||||
@Resource
|
||||
private JXRZXYXXQKMapper jxrzxyxxqkMapper;
|
||||
|
||||
@Resource
|
||||
private TeacherHoursMapper teacherHoursMapper;
|
||||
|
||||
// ==================== 教学日志核心 ====================
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public void addTeachingLog(BCKTJXRZ entity) {
|
||||
if (entity.getZt() == null) entity.setZt("0");
|
||||
bcktjxrzMapper.insert(entity);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public void updateTeachingLog(BCKTJXRZ entity) {
|
||||
bcktjxrzMapper.updateById(entity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BCKTJXRZ getTeachingLogById(String bh) {
|
||||
return bcktjxrzMapper.selectById(bh);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PageResult<BCKTJXRZ> pageTeachingLog(PageQuery query, BCKTJXRZ cond) {
|
||||
Page<BCKTJXRZ> page = new Page<>(query.getPageNum(), query.getPageSize());
|
||||
Page<BCKTJXRZ> result = bcktjxrzMapper.selectPageList(page, cond);
|
||||
return new PageResult<>(result.getRecords(), result.getTotal(), query.getPageNum(), query.getPageSize());
|
||||
}
|
||||
|
||||
@Override
|
||||
public PageResult<TeachingLogListVO> pageTeachingLogDetail(PageQuery query, TeachingLogListVO cond) {
|
||||
Page<TeachingLogListVO> page = new Page<>(query.getPageNum(), query.getPageSize());
|
||||
Page<TeachingLogListVO> result = sskcbRzMapper.selectTeachingLogList(page, cond);
|
||||
return new PageResult<>(result.getRecords(), result.getTotal(), query.getPageNum(), query.getPageSize());
|
||||
}
|
||||
|
||||
// ==================== 教学日志(实施_课程表_日志 36字段表) ====================
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public void addLog(SSKCB_RZ entity) {
|
||||
fillNotNullDefaults(entity);
|
||||
sskcbRzMapper.insert(entity);
|
||||
}
|
||||
|
||||
/**
|
||||
* 为 NOT NULL 字段填充默认值
|
||||
*/
|
||||
private void fillNotNullDefaults(SSKCB_RZ entity) {
|
||||
if (entity.getTybh() == null) entity.setTybh(java.util.UUID.randomUUID().toString());
|
||||
if (entity.getJybh() == null) entity.setJybh(java.util.UUID.randomUUID().toString().substring(0, 8));
|
||||
if (entity.getZczt() == null) entity.setZczt(0);
|
||||
if (entity.getSdrs() == null) entity.setSdrs(0);
|
||||
if (entity.getJcks() == null) entity.setJcks(0);
|
||||
if (entity.getAtj() == null) entity.setAtj(0);
|
||||
if (entity.getRq() == null) entity.setRq(LocalDateTime.now());
|
||||
if (entity.getQsjc() == null) entity.setQsjc(0);
|
||||
if (entity.getJsjc() == null) entity.setJsjc(0);
|
||||
if (entity.getZt() == null) entity.setZt("系统创建");
|
||||
if (entity.getJxrzcjfs() == null) entity.setJxrzcjfs("手动");
|
||||
if (entity.getKckmbh() == null) entity.setKckmbh(java.util.UUID.randomUUID().toString().substring(0, 8));
|
||||
if (entity.getRwlb() == null) entity.setRwlb("其他");
|
||||
if (entity.getYdrs() == null) entity.setYdrs(0);
|
||||
if (entity.getSksjbd() == null) entity.setSksjbd(0);
|
||||
if (entity.getSkddbd() == null) entity.setSkddbd(0);
|
||||
if (entity.getKcbd() == null) entity.setKcbd(0);
|
||||
if (entity.getSkktbd() == null) entity.setSkktbd(0);
|
||||
if (entity.getRwlbbd() == null) entity.setRwlbbd(0);
|
||||
if (entity.getPxqbbd() == null) entity.setPxqbbd(0);
|
||||
if (entity.getSkfsbd() == null) entity.setSkfsbd(0);
|
||||
if (entity.getFzyzdjybd() == null) entity.setFzyzdjybd(0);
|
||||
if (entity.getCjsj() == null) entity.setCjsj(LocalDateTime.now());
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public void rejectLog(String bh, String thyj) {
|
||||
SSKCB_RZ entity = new SSKCB_RZ();
|
||||
entity.setBh(bh);
|
||||
entity.setZt("已退回");
|
||||
entity.setThyj(thyj);
|
||||
entity.setXgsj(LocalDateTime.now());
|
||||
sskcbRzMapper.updateById(entity);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public SSKCB_RZ autoCreateLog(String tybh) {
|
||||
SSKCB schedule = sskcbMapper.selectById(tybh);
|
||||
SSKCB_RZ log = new SSKCB_RZ();
|
||||
log.setTybh(tybh);
|
||||
if (schedule != null) {
|
||||
log.setRq(schedule.getRq());
|
||||
log.setQsjc(schedule.getJc());
|
||||
log.setJsjc(schedule.getJc());
|
||||
log.setJsfs(schedule.getJxff());
|
||||
log.setSkkt(schedule.getJxnr());
|
||||
}
|
||||
log.setZt("系统创建");
|
||||
log.setCjsj(LocalDateTime.now());
|
||||
log.setJxrzcjfs("自动创建");
|
||||
sskcbRzMapper.insert(log);
|
||||
return log;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public void importLog(java.util.List<SSKCB_RZ> list) {
|
||||
for (SSKCB_RZ item : list) {
|
||||
if (item.getZt() == null) item.setZt("系统创建");
|
||||
if (item.getCjsj() == null) item.setCjsj(LocalDateTime.now());
|
||||
sskcbRzMapper.insert(item);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public void importLogFromExcel(org.springframework.web.multipart.MultipartFile file) {
|
||||
try {
|
||||
org.apache.poi.ss.usermodel.Workbook wb = org.apache.poi.ss.usermodel.WorkbookFactory.create(file.getInputStream());
|
||||
try {
|
||||
org.apache.poi.ss.usermodel.Sheet sheet = wb.getSheetAt(0);
|
||||
int lastRow = sheet.getLastRowNum();
|
||||
for (int i = 1; i <= lastRow; i++) {
|
||||
org.apache.poi.ss.usermodel.Row row = sheet.getRow(i);
|
||||
if (row == null) continue;
|
||||
SSKCB_RZ entity = new SSKCB_RZ();
|
||||
entity.setRq(parseDate(getCellValue(row.getCell(3))));
|
||||
entity.setQsjc(toInt(getCellValue(row.getCell(4))));
|
||||
entity.setJsjc(toInt(getCellValue(row.getCell(5))));
|
||||
entity.setAtj("是".equals(getCellValue(row.getCell(6))) ? 1 : 0);
|
||||
entity.setSkdd(getCellValue(row.getCell(7)));
|
||||
entity.setKckmbh(getCellValue(row.getCell(8)));
|
||||
entity.setSkkt(getCellValue(row.getCell(10)));
|
||||
entity.setRwlb(getCellValue(row.getCell(11)));
|
||||
entity.setPxqbxx(getCellValue(row.getCell(12)));
|
||||
entity.setYdrs(toInt(getCellValue(row.getCell(13))));
|
||||
entity.setSdrs(toInt(getCellValue(row.getCell(14))));
|
||||
entity.setJsfs(getCellValue(row.getCell(15)));
|
||||
fillNotNullDefaults(entity);
|
||||
sskcbRzMapper.insert(entity);
|
||||
}
|
||||
} finally {
|
||||
wb.close();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("导入教学日志失败", e);
|
||||
throw new RuntimeException("导入教学日志失败:" + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private String getCellValue(org.apache.poi.ss.usermodel.Cell cell) {
|
||||
if (cell == null) return "";
|
||||
switch (cell.getCellType()) {
|
||||
case STRING:
|
||||
return cell.getStringCellValue().trim();
|
||||
case NUMERIC:
|
||||
if (org.apache.poi.ss.usermodel.DateUtil.isCellDateFormatted(cell)) {
|
||||
return new java.text.SimpleDateFormat("yyyy-MM-dd").format(cell.getDateCellValue());
|
||||
}
|
||||
double val = cell.getNumericCellValue();
|
||||
if (val == Math.floor(val) && !Double.isInfinite(val)) {
|
||||
return String.valueOf((long) val);
|
||||
}
|
||||
return String.valueOf(val);
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
private LocalDateTime parseDate(String str) {
|
||||
if (str == null || str.isEmpty()) return null;
|
||||
try {
|
||||
return LocalDateTime.parse(str + "T00:00:00");
|
||||
} catch (Exception e) {
|
||||
}
|
||||
try {
|
||||
return java.time.LocalDate.parse(str).atStartOfDay();
|
||||
} catch (Exception e) {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private Integer toInt(String str) {
|
||||
if (str == null || str.isEmpty()) return null;
|
||||
try {
|
||||
return Integer.parseInt(str.trim());
|
||||
} catch (Exception e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public int batchReportLogs(java.util.List<String> bhList) {
|
||||
if (bhList == null || bhList.isEmpty()) return 0;
|
||||
return sskcbRzMapper.update(null, new LambdaUpdateWrapper<SSKCB_RZ>()
|
||||
.in(SSKCB_RZ::getBh, bhList)
|
||||
.and(w -> w.isNull(SSKCB_RZ::getZt).or().notIn(SSKCB_RZ::getZt, "已上报", "已审核"))
|
||||
.set(SSKCB_RZ::getZt, "已上报")
|
||||
.set(SSKCB_RZ::getXgsj, LocalDateTime.now()));
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public int batchAuditLogs(java.util.List<String> bhList) {
|
||||
if (bhList == null || bhList.isEmpty()) return 0;
|
||||
return sskcbRzMapper.update(null, new LambdaUpdateWrapper<SSKCB_RZ>()
|
||||
.in(SSKCB_RZ::getBh, bhList)
|
||||
.eq(SSKCB_RZ::getZt, "已上报")
|
||||
.set(SSKCB_RZ::getZt, "已审核")
|
||||
.set(SSKCB_RZ::getXgsj, LocalDateTime.now()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void exportLogExcel(TeachingLogListVO cond, jakarta.servlet.http.HttpServletResponse response) {
|
||||
List<TeachingLogListVO> list = sskcbRzMapper.selectTeachingLogList(
|
||||
new Page<>(1, Integer.MAX_VALUE), cond).getRecords();
|
||||
try (org.apache.poi.xssf.usermodel.XSSFWorkbook wb = new org.apache.poi.xssf.usermodel.XSSFWorkbook()) {
|
||||
org.apache.poi.ss.usermodel.Sheet sheet = wb.createSheet("教学日志");
|
||||
String[] headers = {"序号", "主讲教员标识号", "主讲教员姓名", "授课日期", "起始节次",
|
||||
"结束节次", "按天记", "授课地点", "课标识号", "课名称", "授课课题",
|
||||
"任务类别", "培训期班", "应到人数", "实到人数", "授课方式", "分组指导教员"};
|
||||
org.apache.poi.ss.usermodel.Row headerRow = sheet.createRow(0);
|
||||
for (int i = 0; i < headers.length; i++) {
|
||||
headerRow.createCell(i).setCellValue(headers[i]);
|
||||
}
|
||||
int rowIdx = 1;
|
||||
for (TeachingLogListVO v : list) {
|
||||
org.apache.poi.ss.usermodel.Row row = sheet.createRow(rowIdx++);
|
||||
row.createCell(0).setCellValue(rowIdx - 1); // 序号
|
||||
row.createCell(1).setCellValue(v.getJybh() != null ? v.getJybh() : "");
|
||||
row.createCell(2).setCellValue(v.getJyxm() != null ? v.getJyxm() : "");
|
||||
row.createCell(3).setCellValue(v.getRq() != null ? v.getRq().toLocalDate().toString() : "");
|
||||
row.createCell(4).setCellValue(v.getQsjc() != null ? v.getQsjc() : 0);
|
||||
row.createCell(5).setCellValue(v.getJsjc() != null ? v.getJsjc() : 0);
|
||||
row.createCell(6).setCellValue(v.getAtj() != null && v.getAtj() == 1 ? "是" : "否");
|
||||
row.createCell(7).setCellValue(v.getSkdd() != null ? v.getSkdd() : "");
|
||||
row.createCell(8).setCellValue(v.getKckmbh() != null ? v.getKckmbh() : "");
|
||||
row.createCell(9).setCellValue(v.getKcmc() != null ? v.getKcmc() : "");
|
||||
row.createCell(10).setCellValue(v.getSkkt() != null ? v.getSkkt() : "");
|
||||
row.createCell(11).setCellValue(v.getRwlb() != null ? v.getRwlb() : "");
|
||||
row.createCell(12).setCellValue(v.getPxqbxx() != null ? v.getPxqbxx() : "");
|
||||
row.createCell(13).setCellValue(v.getYdrs() != null ? v.getYdrs() : 0);
|
||||
row.createCell(14).setCellValue(v.getSdrs() != null ? v.getSdrs() : 0);
|
||||
row.createCell(15).setCellValue(v.getJsfs() != null ? v.getJsfs() : "");
|
||||
row.createCell(16).setCellValue(""); // 分组指导教员(需扩展关联查询)
|
||||
}
|
||||
for (int i = 0; i < headers.length; i++) sheet.autoSizeColumn(i);
|
||||
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
|
||||
response.setHeader("Content-Disposition", "attachment; filename=teaching_log.xlsx");
|
||||
wb.write(response.getOutputStream());
|
||||
response.getOutputStream().flush();
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("导出失败", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public void submitApproval(String bh, String targetStatus) {
|
||||
BCKTJXRZ entity = new BCKTJXRZ();
|
||||
entity.setBh(bh);
|
||||
entity.setZt(targetStatus);
|
||||
bcktjxrzMapper.updateById(entity);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public void approve(String bh, String feedback) {
|
||||
BCKTJXRZ entity = new BCKTJXRZ();
|
||||
entity.setBh(bh);
|
||||
entity.setZt("5"); // 已审核通过
|
||||
entity.setJwbmfkyj(feedback);
|
||||
bcktjxrzMapper.updateById(entity);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public void reject(String bh, String feedback) {
|
||||
BCKTJXRZ entity = new BCKTJXRZ();
|
||||
entity.setBh(bh);
|
||||
entity.setZt("1"); // 退回至填写中
|
||||
entity.setJwbmfkyj(feedback);
|
||||
bcktjxrzMapper.updateById(entity);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public BCKTJXRZ autoCreateFromSchedule(String sskcbh) {
|
||||
SSKCB schedule = sskcbMapper.selectById(sskcbh);
|
||||
if (schedule == null) return null;
|
||||
BCKTJXRZ log = new BCKTJXRZ();
|
||||
log.setSskcbh(schedule.getSskcbh());
|
||||
log.setSskcbbh(schedule.getBh());
|
||||
log.setRq(schedule.getRq());
|
||||
log.setJc(schedule.getJc());
|
||||
log.setJxff(schedule.getJxff());
|
||||
log.setNd(schedule.getNd());
|
||||
log.setZt("0"); // 未填写
|
||||
bcktjxrzMapper.insert(log);
|
||||
return log;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PageResult<?> checkLogStatusBySchedule(PageQuery query, String jybh, Integer nd) {
|
||||
// 查询某教员的课表及对应教学日志状态
|
||||
Map<String, Object> result = new HashMap<>();
|
||||
// 此处实现对照查询逻辑
|
||||
Page<SSKCB> page = new Page<>(query.getPageNum(), query.getPageSize());
|
||||
LambdaQueryWrapper<SSKCB> wrapper = new LambdaQueryWrapper<>();
|
||||
if (jybh != null) wrapper.eq(SSKCB::getSskcbh, jybh);
|
||||
if (nd != null) wrapper.eq(SSKCB::getNd, nd);
|
||||
Page<SSKCB> schedulePage = sskcbMapper.selectPage(page, wrapper);
|
||||
return new PageResult<>(schedulePage.getRecords(), schedulePage.getTotal(), query.getPageNum(), query.getPageSize());
|
||||
}
|
||||
|
||||
// ==================== 教学日志授课教员 ====================
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public void addLogTeacher(BCKTJXRZSKJY entity) {
|
||||
bcktjxrzskyMapper.insert(entity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PageResult<BCKTJXRZSKJY> pageLogTeacher(PageQuery query, BCKTJXRZSKJY cond) {
|
||||
Page<BCKTJXRZSKJY> page = new Page<>(query.getPageNum(), query.getPageSize());
|
||||
LambdaQueryWrapper<BCKTJXRZSKJY> wrapper = new LambdaQueryWrapper<>();
|
||||
if (cond.getBcktjxrzbh() != null) wrapper.eq(BCKTJXRZSKJY::getBcktjxrzbh, cond.getBcktjxrzbh());
|
||||
if (cond.getFzjybh() != null) wrapper.eq(BCKTJXRZSKJY::getFzjybh, cond.getFzjybh());
|
||||
Page<BCKTJXRZSKJY> result = bcktjxrzskyMapper.selectPage(page, wrapper);
|
||||
return new PageResult<>(result.getRecords(), result.getTotal(), query.getPageNum(), query.getPageSize());
|
||||
}
|
||||
|
||||
// ==================== 教学日志学员学习情况 ====================
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public void addStudentLearningStatus(JXRZXYXXQK entity) {
|
||||
jxrzxyxxqkMapper.insert(entity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PageResult<JXRZXYXXQK> pageStudentLearningStatus(PageQuery query, String jxrzbh) {
|
||||
Page<JXRZXYXXQK> page = new Page<>(query.getPageNum(), query.getPageSize());
|
||||
LambdaQueryWrapper<JXRZXYXXQK> wrapper = new LambdaQueryWrapper<>();
|
||||
if (jxrzbh != null) wrapper.eq(JXRZXYXXQK::getJxrzbh, jxrzbh);
|
||||
Page<JXRZXYXXQK> result = jxrzxyxxqkMapper.selectPage(page, wrapper);
|
||||
return new PageResult<>(result.getRecords(), result.getTotal(), query.getPageNum(), query.getPageSize());
|
||||
}
|
||||
|
||||
// ==================== 课时核算标准 ====================
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public void addCalculationStandard(KSHBZ entity) {
|
||||
kshbzMapper.insert(entity);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public void updateCalculationStandard(KSHBZ entity) {
|
||||
kshbzMapper.updateById(entity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public KSHBZ getCalculationStandardById(String bh) {
|
||||
return kshbzMapper.selectById(bh);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PageResult<KSHBZ> pageCalculationStandard(PageQuery query, KSHBZ cond) {
|
||||
Page<KSHBZ> page = new Page<>(query.getPageNum(), query.getPageSize());
|
||||
LambdaQueryWrapper<KSHBZ> wrapper = new LambdaQueryWrapper<>();
|
||||
if (cond.getMc() != null) wrapper.like(KSHBZ::getMc, cond.getMc());
|
||||
Page<KSHBZ> result = kshbzMapper.selectPage(page, wrapper);
|
||||
return new PageResult<>(result.getRecords(), result.getTotal(), query.getPageNum(), query.getPageSize());
|
||||
}
|
||||
|
||||
// ==================== 课时系数方案 ====================
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public void addCoefficientPlan(KSXSFA entity) {
|
||||
ksxsfaMapper.insert(entity);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public void updateCoefficientPlan(KSXSFA entity) {
|
||||
ksxsfaMapper.updateById(entity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public KSXSFA getCoefficientPlanById(String bh) {
|
||||
return ksxsfaMapper.selectById(bh);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PageResult<KSXSFA> pageCoefficientPlan(PageQuery query, KSXSFA cond) {
|
||||
Page<KSXSFA> page = new Page<>(query.getPageNum(), query.getPageSize());
|
||||
LambdaQueryWrapper<KSXSFA> wrapper = new LambdaQueryWrapper<>();
|
||||
if (cond != null && cond.getMc() != null && !cond.getMc().isEmpty()) {
|
||||
wrapper.like(KSXSFA::getMc, cond.getMc());
|
||||
}
|
||||
wrapper.orderByDesc(KSXSFA::getCjsj);
|
||||
Page<KSXSFA> result = ksxsfaMapper.selectPage(page, wrapper);
|
||||
return new PageResult<>(result.getRecords(), result.getTotal(), query.getPageNum(), query.getPageSize());
|
||||
}
|
||||
|
||||
// ==================== 课时费标准 ====================
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public void addFeeStandard(KSFBZ entity) {
|
||||
entity.setCjsj(LocalDateTime.now());
|
||||
ksfbzMapper.insert(entity);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public void updateFeeStandard(KSFBZ entity) {
|
||||
entity.setXgsj(LocalDateTime.now());
|
||||
ksfbzMapper.updateById(entity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public KSFBZ getFeeStandardById(String bh) {
|
||||
return ksfbzMapper.selectById(bh);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PageResult<KSFBZ> pageFeeStandard(PageQuery query, KSFBZ cond) {
|
||||
Page<KSFBZ> page = new Page<>(query.getPageNum(), query.getPageSize());
|
||||
LambdaQueryWrapper<KSFBZ> wrapper = new LambdaQueryWrapper<>();
|
||||
if (cond.getMc() != null) wrapper.like(KSFBZ::getMc, cond.getMc());
|
||||
Page<KSFBZ> result = ksfbzMapper.selectPage(page, wrapper);
|
||||
return new PageResult<>(result.getRecords(), result.getTotal(), query.getPageNum(), query.getPageSize());
|
||||
}
|
||||
|
||||
// ==================== 技术职务课时费标准 ====================
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public void addTechPosFeeStandard(JSZWKSFBZ entity) {
|
||||
jszwksfbzMapper.insert(entity);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public void updateTechPosFeeStandard(JSZWKSFBZ entity) {
|
||||
jszwksfbzMapper.updateById(entity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JSZWKSFBZ getTechPosFeeStandardById(String bh) {
|
||||
return jszwksfbzMapper.selectById(bh);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PageResult<JSZWKSFBZ> pageTechPosFeeStandard(PageQuery query, JSZWKSFBZ cond) {
|
||||
Page<JSZWKSFBZ> page = new Page<>(query.getPageNum(), query.getPageSize());
|
||||
LambdaQueryWrapper<JSZWKSFBZ> wrapper = new LambdaQueryWrapper<>();
|
||||
if (cond.getJszwbh() != null) wrapper.eq(JSZWKSFBZ::getJszwbh, cond.getJszwbh());
|
||||
Page<JSZWKSFBZ> result = jszwksfbzMapper.selectPage(page, wrapper);
|
||||
return new PageResult<>(result.getRecords(), result.getTotal(), query.getPageNum(), query.getPageSize());
|
||||
}
|
||||
|
||||
|
||||
|
||||
// ==================== 课时补助项目 ====================
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public void addSubsidyProject(KSBZXM entity) {
|
||||
ksbzxmMapper.insert(entity);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public void updateSubsidyProject(KSBZXM entity) {
|
||||
ksbzxmMapper.updateById(entity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public KSBZXM getSubsidyProjectById(String bh) {
|
||||
return ksbzxmMapper.selectById(bh);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PageResult<KSBZXM> pageSubsidyProject(PageQuery query, KSBZXM cond) {
|
||||
Page<KSBZXM> page = new Page<>(query.getPageNum(), query.getPageSize());
|
||||
LambdaQueryWrapper<KSBZXM> wrapper = new LambdaQueryWrapper<>();
|
||||
if (cond.getMc() != null) wrapper.like(KSBZXM::getMc, cond.getMc());
|
||||
Page<KSBZXM> result = ksbzxmMapper.selectPage(page, wrapper);
|
||||
return new PageResult<>(result.getRecords(), result.getTotal(), query.getPageNum(), query.getPageSize());
|
||||
}
|
||||
|
||||
// ==================== 教学日志课时补助审批表(汇总) ====================
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public void addSubsidyApproval(JXRZKSBZSPB entity) {
|
||||
jxrzksbzspbMapper.insert(entity);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public void updateSubsidyApproval(JXRZKSBZSPB entity) {
|
||||
jxrzksbzspbMapper.updateById(entity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JXRZKSBZSPB getSubsidyApprovalById(String bh) {
|
||||
return jxrzksbzspbMapper.selectById(bh);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PageResult<JXRZKSBZSPB> pageSubsidyApproval(PageQuery query, JXRZKSBZSPB cond) {
|
||||
Page<JXRZKSBZSPB> page = new Page<>(query.getPageNum(), query.getPageSize());
|
||||
Page<JXRZKSBZSPB> result = jxrzksbzspbMapper.selectPageList(page, cond);
|
||||
return new PageResult<>(result.getRecords(), result.getTotal(), query.getPageNum(), query.getPageSize());
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public void calculateSummary(String bh) {
|
||||
JXRZKSBZSPB summary = jxrzksbzspbMapper.selectById(bh);
|
||||
if (summary == null) return;
|
||||
LambdaQueryWrapper<JXRZJYKSBZ> wrapper = new LambdaQueryWrapper<>();
|
||||
wrapper.eq(JXRZJYKSBZ::getJxrzksbzspbh, bh);
|
||||
List<JXRZJYKSBZ> details = jxrzjyksbzMapper.selectList(wrapper);
|
||||
float totalKsl = 0, totalYzksl = 0;
|
||||
BigDecimal totalAmount = BigDecimal.ZERO;
|
||||
for (JXRZJYKSBZ d : details) {
|
||||
if (d.getKsl() != null) totalKsl += d.getKsl();
|
||||
if (d.getSfyz() != null && d.getSfyz() == 1 && d.getKsl() != null) totalYzksl += d.getKsl();
|
||||
if (d.getKsbzje() != null) totalAmount = totalAmount.add(d.getKsbzje());
|
||||
}
|
||||
summary.setZksl(totalKsl);
|
||||
summary.setYzksl(totalYzksl);
|
||||
summary.setZbzje(totalAmount.floatValue());
|
||||
jxrzksbzspbMapper.updateById(summary);
|
||||
}
|
||||
|
||||
// ==================== 教学日志教员课时补助明细 ====================
|
||||
|
||||
@Override
|
||||
public PageResult<JXRZJYKSBZ> pageSubsidyDetail(PageQuery query, JXRZJYKSBZ cond) {
|
||||
Page<JXRZJYKSBZ> page = new Page<>(query.getPageNum(), query.getPageSize());
|
||||
LambdaQueryWrapper<JXRZJYKSBZ> wrapper = new LambdaQueryWrapper<>();
|
||||
if (cond.getJxrzksbzspbh() != null) wrapper.eq(JXRZJYKSBZ::getJxrzksbzspbh, cond.getJxrzksbzspbh());
|
||||
if (cond.getJybh() != null) wrapper.eq(JXRZJYKSBZ::getJybh, cond.getJybh());
|
||||
Page<JXRZJYKSBZ> result = jxrzjyksbzMapper.selectPage(page, wrapper);
|
||||
return new PageResult<>(result.getRecords(), result.getTotal(), query.getPageNum(), query.getPageSize());
|
||||
}
|
||||
|
||||
// ==================== 教员课时补助 ====================
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public void addTeacherSubsidy(JYKSBZ entity) {
|
||||
jyksbzMapper.insert(entity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PageResult<JYKSBZ> pageTeacherSubsidy(PageQuery query, JYKSBZ cond) {
|
||||
Page<JYKSBZ> page = new Page<>(query.getPageNum(), query.getPageSize());
|
||||
LambdaQueryWrapper<JYKSBZ> wrapper = new LambdaQueryWrapper<>();
|
||||
if (cond.getJybh() != null) wrapper.eq(JYKSBZ::getJybh, cond.getJybh());
|
||||
Page<JYKSBZ> result = jyksbzMapper.selectPage(page, wrapper);
|
||||
return new PageResult<>(result.getRecords(), result.getTotal(), query.getPageNum(), query.getPageSize());
|
||||
}
|
||||
|
||||
// ==================== 年终课时费 ====================
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public void addYearEndFee(NZKSF entity) {
|
||||
nzksfMapper.insert(entity);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public void updateYearEndFee(NZKSF entity) {
|
||||
nzksfMapper.updateById(entity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public NZKSF getYearEndFeeById(String bh) {
|
||||
return nzksfMapper.selectById(bh);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PageResult<NZKSF> pageYearEndFee(PageQuery query, NZKSF cond) {
|
||||
Page<NZKSF> page = new Page<>(query.getPageNum(), query.getPageSize());
|
||||
LambdaQueryWrapper<NZKSF> wrapper = new LambdaQueryWrapper<>();
|
||||
if (cond.getMc() != null) wrapper.like(NZKSF::getMc, cond.getMc());
|
||||
Page<NZKSF> result = nzksfMapper.selectPage(page, wrapper);
|
||||
return new PageResult<>(result.getRecords(), result.getTotal(), query.getPageNum(), query.getPageSize());
|
||||
}
|
||||
|
||||
// ==================== 教员年终课时费 ====================
|
||||
|
||||
@Override
|
||||
public PageResult<JYNZKSF> pageTeacherYearEndFee(PageQuery query, JYNZKSF cond) {
|
||||
Page<JYNZKSF> page = new Page<>(query.getPageNum(), query.getPageSize());
|
||||
LambdaQueryWrapper<JYNZKSF> wrapper = new LambdaQueryWrapper<>();
|
||||
if (cond.getJybh() != null) wrapper.eq(JYNZKSF::getJybh, cond.getJybh());
|
||||
if (cond.getNzksfbh() != null) wrapper.eq(JYNZKSF::getNzksfbh, cond.getNzksfbh());
|
||||
Page<JYNZKSF> result = jynzksfMapper.selectPage(page, wrapper);
|
||||
return new PageResult<>(result.getRecords(), result.getTotal(), query.getPageNum(), query.getPageSize());
|
||||
}
|
||||
|
||||
// ==================== 教师工作量 ====================
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public void addWorkload(JZGZL entity) {
|
||||
entity.setCjsj(LocalDateTime.now());
|
||||
entity.setXgsj(LocalDateTime.now());
|
||||
jzgzlMapper.insert(entity);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public void updateWorkload(JZGZL entity) {
|
||||
entity.setXgsj(LocalDateTime.now());
|
||||
jzgzlMapper.updateById(entity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JZGZL getWorkloadById(String bh) {
|
||||
return jzgzlMapper.selectById(bh);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PageResult<JZGZL> pageWorkload(PageQuery query, JZGZL cond) {
|
||||
Page<JZGZL> page = new Page<>(query.getPageNum(), query.getPageSize());
|
||||
LambdaQueryWrapper<JZGZL> wrapper = new LambdaQueryWrapper<>();
|
||||
if (cond.getJybh() != null) wrapper.eq(JZGZL::getJybh, cond.getJybh());
|
||||
if (cond.getNd() != null) wrapper.eq(JZGZL::getNd, cond.getNd());
|
||||
if (cond.getXq() != null) wrapper.eq(JZGZL::getXq, cond.getXq());
|
||||
Page<JZGZL> result = jzgzlMapper.selectPage(page, wrapper);
|
||||
return new PageResult<>(result.getRecords(), result.getTotal(), query.getPageNum(), query.getPageSize());
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public void calcCourseWorkload(String jybh, Integer nd, String xq) {
|
||||
// 统计课时量作为工作量
|
||||
LambdaQueryWrapper<BCKTJXRZSKJY> tw = new LambdaQueryWrapper<>();
|
||||
tw.eq(BCKTJXRZSKJY::getFzjybh, jybh).eq(BCKTJXRZSKJY::getNd, nd);
|
||||
long count = bcktjxrzskyMapper.selectCount(tw);
|
||||
JZGZL workload = new JZGZL();
|
||||
workload.setJybh(jybh);
|
||||
workload.setNd(nd);
|
||||
workload.setXq(xq);
|
||||
workload.setKcjxgzl((float) count);
|
||||
workload.setZgzl((float) count);
|
||||
jzgzlMapper.insert(workload);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PageResult<?> compareWorkload(PageQuery query, Integer nd, String xq) {
|
||||
Page<JZGZL> page = new Page<>(query.getPageNum(), query.getPageSize());
|
||||
LambdaQueryWrapper<JZGZL> wrapper = new LambdaQueryWrapper<>();
|
||||
if (nd != null) wrapper.eq(JZGZL::getNd, nd);
|
||||
if (xq != null) wrapper.eq(JZGZL::getXq, xq);
|
||||
wrapper.orderByDesc(JZGZL::getZgzl);
|
||||
Page<JZGZL> result = jzgzlMapper.selectPage(page, wrapper);
|
||||
return new PageResult<>(result.getRecords(), result.getTotal(), query.getPageNum(), query.getPageSize());
|
||||
}
|
||||
|
||||
// ==================== 教学实施计划统计 ====================
|
||||
|
||||
@Override
|
||||
public PageResult<JXSSJHTJB> pageTeachingStats(PageQuery query, JXSSJHTJB cond) {
|
||||
Page<JXSSJHTJB> page = new Page<>(query.getPageNum(), query.getPageSize());
|
||||
LambdaQueryWrapper<JXSSJHTJB> wrapper = new LambdaQueryWrapper<>();
|
||||
if (cond.getRq() != null) wrapper.ge(JXSSJHTJB::getRq, cond.getRq());
|
||||
wrapper.orderByDesc(JXSSJHTJB::getRq);
|
||||
Page<JXSSJHTJB> result = jxssjhtjbMapper.selectPage(page, wrapper);
|
||||
return new PageResult<>(result.getRecords(), result.getTotal(), query.getPageNum(), query.getPageSize());
|
||||
}
|
||||
|
||||
// ==================== 教员课时查询管理 ====================
|
||||
|
||||
@Override
|
||||
public PageResult<TeacherHoursVO> pageTeacherHours(PageQuery query, TeacherHoursVO cond) {
|
||||
Page<TeacherHoursVO> page = new Page<>(query.getPageNum(), query.getPageSize());
|
||||
Page<TeacherHoursVO> result = teacherHoursMapper.selectTeacherHoursPage(page, cond);
|
||||
return new PageResult<>(result.getRecords(), result.getTotal(), query.getPageNum(), query.getPageSize());
|
||||
}
|
||||
}
|
||||
+597
@@ -0,0 +1,597 @@
|
||||
package com.roomroot.jwgl.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.roomroot.jwgl.dto.noticeannouncement.NoticeAnnouncementCreateDTO;
|
||||
import com.roomroot.jwgl.dto.noticeannouncement.NoticeAnnouncementIdDTO;
|
||||
import com.roomroot.jwgl.dto.noticeannouncement.NoticeAnnouncementPriorityDTO;
|
||||
import com.roomroot.jwgl.dto.noticeannouncement.NoticeAnnouncementPublishDTO;
|
||||
import com.roomroot.jwgl.dto.noticeannouncement.NoticeAnnouncementQueryDTO;
|
||||
import com.roomroot.jwgl.dto.noticeannouncement.NoticeAnnouncementRecipientInsertDTO;
|
||||
import com.roomroot.jwgl.dto.noticeannouncement.NoticeAnnouncementRecipientQueryDTO;
|
||||
import com.roomroot.jwgl.dto.noticeannouncement.NoticeAnnouncementUpdateDTO;
|
||||
import com.roomroot.jwgl.dto.noticeannouncement.UserNoticeAnnouncementQueryDTO;
|
||||
import com.roomroot.jwgl.mapper.NoticeAnnouncementMapper;
|
||||
import com.roomroot.jwgl.service.NoticeAnnouncementService;
|
||||
import com.roomroot.common.exception.ServiceException;
|
||||
import com.roomroot.jwgl.unit.PageResult;
|
||||
import com.roomroot.jwgl.utils.PageResultUtil;
|
||||
import com.roomroot.jwgl.utils.UuidUtil;
|
||||
import com.roomroot.jwgl.vo.noticeannouncement.NoticeAnnouncementDetailVO;
|
||||
import com.roomroot.jwgl.vo.noticeannouncement.NoticeAnnouncementPublishResultVO;
|
||||
import com.roomroot.jwgl.vo.noticeannouncement.NoticeAnnouncementRecipientVO;
|
||||
import com.roomroot.jwgl.vo.noticeannouncement.NoticeAnnouncementStatisticsVO;
|
||||
import com.roomroot.jwgl.vo.noticeannouncement.NoticeAnnouncementVO;
|
||||
import com.roomroot.jwgl.vo.noticeannouncement.UserNoticeAnnouncementDetailVO;
|
||||
import com.roomroot.jwgl.vo.noticeannouncement.UserNoticeAnnouncementVO;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import jakarta.annotation.Resource;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
|
||||
import static com.roomroot.jwgl.utils.BasicManagementConstants.BAD_REQUEST;
|
||||
import static com.roomroot.jwgl.utils.BasicManagementConstants.NOT_FOUND;
|
||||
import static com.roomroot.jwgl.utils.NoticeAnnouncementConstants.RECIPIENT_INSERT_BATCH_SIZE;
|
||||
import static com.roomroot.jwgl.utils.NoticeAnnouncementConstants.SCOPE_ALL;
|
||||
import static com.roomroot.jwgl.utils.NoticeAnnouncementConstants.SCOPE_ALL_TEACHERS;
|
||||
import static com.roomroot.jwgl.utils.NoticeAnnouncementConstants.STATUS_DOWN;
|
||||
import static com.roomroot.jwgl.utils.NoticeAnnouncementConstants.STATUS_DRAFT;
|
||||
import static com.roomroot.jwgl.utils.NoticeAnnouncementConstants.STATUS_PUBLISHED;
|
||||
import static com.roomroot.jwgl.utils.NoticeAnnouncementUtil.completeDetail;
|
||||
import static com.roomroot.jwgl.utils.NoticeAnnouncementUtil.completeStatistics;
|
||||
import static com.roomroot.jwgl.utils.NoticeAnnouncementUtil.createRecipientRecords;
|
||||
import static com.roomroot.jwgl.utils.NoticeAnnouncementUtil.normalizeCreate;
|
||||
import static com.roomroot.jwgl.utils.NoticeAnnouncementUtil.normalizeNoticeId;
|
||||
import static com.roomroot.jwgl.utils.NoticeAnnouncementUtil.normalizePriority;
|
||||
import static com.roomroot.jwgl.utils.NoticeAnnouncementUtil.normalizePublish;
|
||||
import static com.roomroot.jwgl.utils.NoticeAnnouncementUtil.normalizeQuery;
|
||||
import static com.roomroot.jwgl.utils.NoticeAnnouncementUtil.normalizeRecipientAccountIds;
|
||||
import static com.roomroot.jwgl.utils.NoticeAnnouncementUtil.normalizeRecipientQuery;
|
||||
import static com.roomroot.jwgl.utils.NoticeAnnouncementUtil.normalizeUpdate;
|
||||
import static com.roomroot.jwgl.utils.NoticeAnnouncementUtil.normalizeUserQuery;
|
||||
import static com.roomroot.jwgl.utils.NoticeAnnouncementUtil.requireCurrentAccountId;
|
||||
import static com.roomroot.jwgl.utils.NoticeAnnouncementUtil.requireCurrentSessionId;
|
||||
import static com.roomroot.jwgl.utils.NoticeAnnouncementUtil.requireDeletableStatus;
|
||||
import static com.roomroot.jwgl.utils.NoticeAnnouncementUtil.requireDownableStatus;
|
||||
import static com.roomroot.jwgl.utils.NoticeAnnouncementUtil.requireEditableStatus;
|
||||
import static com.roomroot.jwgl.utils.NoticeAnnouncementUtil.requireExistingStatus;
|
||||
import static com.roomroot.jwgl.utils.NoticeAnnouncementUtil.requirePublishableStatus;
|
||||
import static com.roomroot.jwgl.utils.NoticeAnnouncementUtil.resolveScopeName;
|
||||
import static com.roomroot.jwgl.utils.NoticeAnnouncementUtil.startOfDay;
|
||||
import static com.roomroot.jwgl.utils.NoticeAnnouncementUtil.startOfNextDay;
|
||||
|
||||
/**
|
||||
* 通知公告管理服务实现。
|
||||
*
|
||||
* <p>当前类只编排公告业务流程;DTO 复制、固定校验、状态规则、
|
||||
* 会话读取、接收人去重和统计计算统一由通知公告工具类处理。</p>
|
||||
*/
|
||||
@Service
|
||||
public class NoticeAnnouncementServiceImpl
|
||||
implements NoticeAnnouncementService {
|
||||
|
||||
/**
|
||||
* 通知公告管理数据访问对象。
|
||||
*/
|
||||
@Resource
|
||||
private NoticeAnnouncementMapper noticeAnnouncementMapper;
|
||||
|
||||
/**
|
||||
* 分页查询后台通知公告。
|
||||
*/
|
||||
@Override
|
||||
@Transactional(readOnly = true)
|
||||
public PageResult<NoticeAnnouncementVO> list(
|
||||
NoticeAnnouncementQueryDTO dto) {
|
||||
// 第一步:规范化并校验后台分页筛选条件。
|
||||
NoticeAnnouncementQueryDTO query =
|
||||
normalizeQuery(dto);
|
||||
|
||||
// 第二步:把页面日期转换为数据库时间查询边界。
|
||||
LocalDateTime publishStartTime =
|
||||
startOfDay(query.getPublishStartDate());
|
||||
LocalDateTime publishEndExclusiveTime =
|
||||
startOfNextDay(query.getPublishEndDate());
|
||||
|
||||
// 第三步:创建 MyBatis-Plus 分页对象。
|
||||
Page<NoticeAnnouncementVO> page =
|
||||
new Page<>(
|
||||
query.getPageNum().longValue(),
|
||||
query.getPageSize().longValue());
|
||||
|
||||
// 第四步:执行公告筛选、接收阅读统计和稳定排序。
|
||||
Page<NoticeAnnouncementVO> selectedPage =
|
||||
noticeAnnouncementMapper
|
||||
.selectNoticeAnnouncementPage(
|
||||
page,
|
||||
query,
|
||||
publishStartTime,
|
||||
publishEndExclusiveTime);
|
||||
|
||||
// 第五步:返回项目统一分页结构。
|
||||
return PageResultUtil.fromPage(
|
||||
selectedPage,
|
||||
page,
|
||||
query.getPageNum(),
|
||||
query.getPageSize());
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询通知公告后台详情。
|
||||
*/
|
||||
@Override
|
||||
@Transactional(readOnly = true)
|
||||
public NoticeAnnouncementDetailVO get(
|
||||
NoticeAnnouncementIdDTO dto) {
|
||||
// 第一步:规范化公告编号。
|
||||
String id = normalizeNoticeId(dto);
|
||||
|
||||
// 第二步:查询并返回包含发布范围和统计信息的公告详情。
|
||||
return loadDetail(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增一条拟制公告。
|
||||
*/
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public NoticeAnnouncementDetailVO add(
|
||||
NoticeAnnouncementCreateDTO dto) {
|
||||
// 第一步:规范化并校验公告可编辑内容。
|
||||
NoticeAnnouncementCreateDTO notice =
|
||||
normalizeCreate(dto);
|
||||
|
||||
// 第二步:由服务端生成公告编号和创建时间。
|
||||
String id = UuidUtil.getOriginalUUID();
|
||||
LocalDateTime now = LocalDateTime.now();
|
||||
|
||||
// 第三步:固定按照拟制状态写入公告,不信任客户端状态数据。
|
||||
noticeAnnouncementMapper.insertNoticeAnnouncement(
|
||||
id,
|
||||
notice,
|
||||
now,
|
||||
STATUS_DRAFT);
|
||||
|
||||
// 第四步:重新查询并返回新增后的公告详情。
|
||||
return loadDetail(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改拟制或已下架公告。
|
||||
*/
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public NoticeAnnouncementDetailVO update(
|
||||
NoticeAnnouncementUpdateDTO dto) {
|
||||
// 第一步:规范化并校验公告编号和可编辑内容。
|
||||
NoticeAnnouncementUpdateDTO notice =
|
||||
normalizeUpdate(dto);
|
||||
|
||||
// 第二步:锁定公告行并取得当前状态。
|
||||
String status =
|
||||
noticeAnnouncementMapper
|
||||
.selectNoticeStatusForUpdate(
|
||||
notice.getId());
|
||||
|
||||
// 第三步:只允许修改拟制或已下架公告。
|
||||
requireEditableStatus(status);
|
||||
|
||||
// 第四步:更新公告内容,不改变状态和接收人快照。
|
||||
noticeAnnouncementMapper
|
||||
.updateNoticeAnnouncement(notice);
|
||||
|
||||
// 第五步:返回修改后的公告详情。
|
||||
return loadDetail(notice.getId());
|
||||
}
|
||||
|
||||
/**
|
||||
* 发布公告并生成接收人快照。
|
||||
*/
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public NoticeAnnouncementPublishResultVO publish(
|
||||
NoticeAnnouncementPublishDTO dto) {
|
||||
// 第一步:规范化公告编号、发布范围和指定部别编号。
|
||||
NoticeAnnouncementPublishDTO publish =
|
||||
normalizePublish(dto);
|
||||
|
||||
// 第二步:锁定公告行并校验拟制或已下架状态允许发布。
|
||||
String status =
|
||||
noticeAnnouncementMapper
|
||||
.selectNoticeStatusForUpdate(
|
||||
publish.getId());
|
||||
requirePublishableStatus(status);
|
||||
|
||||
/*
|
||||
* 第三步:按照全校、全体教员或指定部别解析有效账户。
|
||||
* 指定部别范围会同时校验部别是否存在且处于启用状态。
|
||||
*/
|
||||
List<String> accountIds =
|
||||
resolveRecipientAccountIds(publish);
|
||||
|
||||
// 第四步:去除空账户和重复账户。
|
||||
List<String> uniqueAccountIds =
|
||||
normalizeRecipientAccountIds(accountIds);
|
||||
if (uniqueAccountIds.isEmpty()) {
|
||||
throw new ServiceException("当前发布范围内没有可接收公告的有效账户",
|
||||
BAD_REQUEST);
|
||||
}
|
||||
|
||||
// 第五步:为每个接收账户生成独立的接收人快照记录。
|
||||
List<NoticeAnnouncementRecipientInsertDTO> recipients =
|
||||
createRecipientRecords(uniqueAccountIds);
|
||||
LocalDateTime publishTime = LocalDateTime.now();
|
||||
|
||||
/*
|
||||
* 第六步:删除上一轮发布的接收人快照。
|
||||
* 拟制公告通常没有旧快照,已下架公告重新发布时会替换旧快照。
|
||||
*/
|
||||
noticeAnnouncementMapper
|
||||
.deleteNoticeRecipients(publish.getId());
|
||||
|
||||
// 第七步:分批写入本轮发布的全部接收人快照。
|
||||
insertRecipientSnapshots(
|
||||
publish.getId(),
|
||||
recipients,
|
||||
publishTime);
|
||||
|
||||
// 第八步:更新公告发布状态、发布时间、全体标记并重置阅读次数。
|
||||
boolean all =
|
||||
SCOPE_ALL.equals(publish.getScopeType());
|
||||
noticeAnnouncementMapper.updateNoticePublishState(
|
||||
publish.getId(),
|
||||
STATUS_PUBLISHED,
|
||||
publishTime,
|
||||
all);
|
||||
|
||||
// 第九步:封装并返回本次发布结果。
|
||||
NoticeAnnouncementPublishResultVO result =
|
||||
new NoticeAnnouncementPublishResultVO();
|
||||
result.setId(publish.getId());
|
||||
result.setScopeType(publish.getScopeType());
|
||||
result.setScopeName(
|
||||
resolveScopeName(publish.getScopeType()));
|
||||
result.setRecipientCount(
|
||||
Integer.valueOf(uniqueAccountIds.size()));
|
||||
result.setPublishTime(publishTime);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 下架已发布公告。
|
||||
*/
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public NoticeAnnouncementDetailVO down(
|
||||
NoticeAnnouncementIdDTO dto) {
|
||||
// 第一步:规范化公告编号。
|
||||
String id = normalizeNoticeId(dto);
|
||||
|
||||
// 第二步:锁定公告行并校验当前状态必须为已发布。
|
||||
String status =
|
||||
noticeAnnouncementMapper
|
||||
.selectNoticeStatusForUpdate(id);
|
||||
requireDownableStatus(status);
|
||||
|
||||
// 第三步:把公告状态修改为已下架,保留本轮接收和阅读历史。
|
||||
noticeAnnouncementMapper.updateNoticeStatus(
|
||||
id, STATUS_DOWN);
|
||||
|
||||
// 第四步:返回下架后的公告详情。
|
||||
return loadDetail(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除拟制或已下架公告。
|
||||
*/
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void delete(NoticeAnnouncementIdDTO dto) {
|
||||
// 第一步:规范化公告编号。
|
||||
String id = normalizeNoticeId(dto);
|
||||
|
||||
// 第二步:锁定公告行并校验当前状态允许删除。
|
||||
String status =
|
||||
noticeAnnouncementMapper
|
||||
.selectNoticeStatusForUpdate(id);
|
||||
requireDeletableStatus(status);
|
||||
|
||||
// 第三步:先删除接收人快照,避免外键引用阻止公告删除。
|
||||
noticeAnnouncementMapper
|
||||
.deleteNoticeRecipients(id);
|
||||
|
||||
// 第四步:删除公告主体。
|
||||
noticeAnnouncementMapper
|
||||
.deleteNoticeAnnouncement(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* 调整公告优先级。
|
||||
*/
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public NoticeAnnouncementDetailVO updatePriority(
|
||||
NoticeAnnouncementPriorityDTO dto) {
|
||||
// 第一步:规范化公告编号并校验优先级范围。
|
||||
NoticeAnnouncementPriorityDTO priority =
|
||||
normalizePriority(dto);
|
||||
|
||||
// 第二步:锁定公告行并确认公告存在。
|
||||
String status =
|
||||
noticeAnnouncementMapper
|
||||
.selectNoticeStatusForUpdate(
|
||||
priority.getId());
|
||||
requireExistingStatus(status);
|
||||
|
||||
// 第三步:更新优先级,设置为0时取消置顶效果。
|
||||
noticeAnnouncementMapper.updateNoticePriority(
|
||||
priority.getId(),
|
||||
priority.getPriority());
|
||||
|
||||
// 第四步:返回调整后的公告详情。
|
||||
return loadDetail(priority.getId());
|
||||
}
|
||||
|
||||
/**
|
||||
* 分页查询公告接收人和阅读明细。
|
||||
*/
|
||||
@Override
|
||||
@Transactional(readOnly = true)
|
||||
public PageResult<NoticeAnnouncementRecipientVO>
|
||||
recipients(
|
||||
NoticeAnnouncementRecipientQueryDTO dto) {
|
||||
// 第一步:规范化公告编号、分页和接收人筛选条件。
|
||||
NoticeAnnouncementRecipientQueryDTO query =
|
||||
normalizeRecipientQuery(dto);
|
||||
|
||||
// 第二步:确认待查询公告存在。
|
||||
loadDetail(query.getId());
|
||||
|
||||
// 第三步:创建接收人明细分页对象。
|
||||
Page<NoticeAnnouncementRecipientVO> page =
|
||||
new Page<>(
|
||||
query.getPageNum().longValue(),
|
||||
query.getPageSize().longValue());
|
||||
|
||||
// 第四步:查询按账户去重后的接收和阅读明细。
|
||||
Page<NoticeAnnouncementRecipientVO> selectedPage =
|
||||
noticeAnnouncementMapper
|
||||
.selectNoticeRecipientPage(
|
||||
page, query);
|
||||
|
||||
// 第五步:返回项目统一分页结构。
|
||||
return PageResultUtil.fromPage(
|
||||
selectedPage,
|
||||
page,
|
||||
query.getPageNum(),
|
||||
query.getPageSize());
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询公告接收和阅读统计。
|
||||
*/
|
||||
@Override
|
||||
@Transactional(readOnly = true)
|
||||
public NoticeAnnouncementStatisticsVO statistics(
|
||||
NoticeAnnouncementIdDTO dto) {
|
||||
// 第一步:规范化公告编号。
|
||||
String id = normalizeNoticeId(dto);
|
||||
|
||||
// 第二步:确认待统计公告存在。
|
||||
loadDetail(id);
|
||||
|
||||
// 第三步:汇总唯一接收账户的接收和阅读人数。
|
||||
NoticeAnnouncementStatisticsVO statistics =
|
||||
noticeAnnouncementMapper
|
||||
.selectNoticeStatistics(id);
|
||||
|
||||
// 第四步:补全未读人数和阅读率并返回。
|
||||
return completeStatistics(statistics, id);
|
||||
}
|
||||
|
||||
/**
|
||||
* 分页查询当前登录账户可见的公告。
|
||||
*/
|
||||
@Override
|
||||
@Transactional(readOnly = true)
|
||||
public PageResult<UserNoticeAnnouncementVO> userList(
|
||||
UserNoticeAnnouncementQueryDTO dto) {
|
||||
// 第一步:规范化用户公告分页和筛选条件。
|
||||
UserNoticeAnnouncementQueryDTO query =
|
||||
normalizeUserQuery(dto);
|
||||
|
||||
// 第二步:只根据当前服务端会话查询真实账户编号。
|
||||
String accountId = currentAccountId();
|
||||
|
||||
// 第三步:创建用户公告分页对象。
|
||||
Page<UserNoticeAnnouncementVO> page =
|
||||
new Page<>(
|
||||
query.getPageNum().longValue(),
|
||||
query.getPageSize().longValue());
|
||||
|
||||
/*
|
||||
* 第四步:只查询当前账户具有接收快照且仍为已发布状态的公告,
|
||||
* 客户端不能通过提交其他账户编号越权查询。
|
||||
*/
|
||||
Page<UserNoticeAnnouncementVO> selectedPage =
|
||||
noticeAnnouncementMapper
|
||||
.selectUserNoticePage(
|
||||
page,
|
||||
accountId,
|
||||
query,
|
||||
STATUS_PUBLISHED);
|
||||
|
||||
// 第五步:返回项目统一分页结构。
|
||||
return PageResultUtil.fromPage(
|
||||
selectedPage,
|
||||
page,
|
||||
query.getPageNum(),
|
||||
query.getPageSize());
|
||||
}
|
||||
|
||||
/**
|
||||
* 当前登录账户打开公告并完成阅读记录。
|
||||
*/
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public UserNoticeAnnouncementDetailVO read(
|
||||
NoticeAnnouncementIdDTO dto) {
|
||||
// 第一步:规范化公告编号并识别当前真实账户。
|
||||
String id = normalizeNoticeId(dto);
|
||||
String accountId = currentAccountId();
|
||||
|
||||
/*
|
||||
* 第二步:锁定当前账户具有接收快照的已发布公告。
|
||||
* 公告不存在、已经下架或不属于当前账户时统一不返回公告内容。
|
||||
*/
|
||||
String status =
|
||||
noticeAnnouncementMapper
|
||||
.selectUserNoticeStatusForUpdate(
|
||||
id,
|
||||
accountId,
|
||||
STATUS_PUBLISHED);
|
||||
if (status == null) {
|
||||
throw new ServiceException("通知公告不存在或当前账户无权查看",
|
||||
NOT_FOUND);
|
||||
}
|
||||
|
||||
// 第三步:首次打开时标记已读和首次阅读时间,重复打开不会覆盖时间。
|
||||
LocalDateTime readTime = LocalDateTime.now();
|
||||
noticeAnnouncementMapper.markNoticeRecipientRead(
|
||||
id,
|
||||
accountId,
|
||||
readTime);
|
||||
|
||||
// 第四步:每次有效打开都增加公告累计阅读次数。
|
||||
noticeAnnouncementMapper
|
||||
.incrementNoticeReadCount(id);
|
||||
|
||||
// 第五步:重新查询并返回更新后的用户公告详情。
|
||||
UserNoticeAnnouncementDetailVO detail =
|
||||
noticeAnnouncementMapper
|
||||
.selectUserNoticeDetail(
|
||||
id,
|
||||
accountId,
|
||||
STATUS_PUBLISHED);
|
||||
if (detail == null) {
|
||||
throw new ServiceException("通知公告不存在或当前账户无权查看",
|
||||
NOT_FOUND);
|
||||
}
|
||||
return detail;
|
||||
}
|
||||
|
||||
/**
|
||||
* 按发布范围解析有效接收账户。
|
||||
*
|
||||
* @param publish 已完成规范化的发布参数
|
||||
* @return 数据库查询到的接收账户编号
|
||||
*/
|
||||
private List<String> resolveRecipientAccountIds(
|
||||
NoticeAnnouncementPublishDTO publish) {
|
||||
// 第一步:全校范围查询全部有效账户。
|
||||
if (SCOPE_ALL.equals(publish.getScopeType())) {
|
||||
return noticeAnnouncementMapper
|
||||
.selectAllActiveAccountIds();
|
||||
}
|
||||
|
||||
// 第二步:全体教员范围查询全部有效教员账户。
|
||||
if (SCOPE_ALL_TEACHERS.equals(
|
||||
publish.getScopeType())) {
|
||||
return noticeAnnouncementMapper
|
||||
.selectAllActiveTeacherAccountIds();
|
||||
}
|
||||
|
||||
/*
|
||||
* 第三步:指定部别范围先确认全部部别存在且启用,
|
||||
* 防止部分无效编号被静默忽略后产生错误发布范围。
|
||||
*/
|
||||
List<String> departmentIds =
|
||||
publish.getDepartmentIds();
|
||||
int activeDepartmentCount =
|
||||
noticeAnnouncementMapper
|
||||
.countActiveDepartments(
|
||||
departmentIds);
|
||||
if (activeDepartmentCount
|
||||
!= departmentIds.size()) {
|
||||
throw new ServiceException("选择的部别不存在或已经停用",
|
||||
BAD_REQUEST);
|
||||
}
|
||||
|
||||
// 第四步:返回指定部别关联的机关人员、教员、教研室和教学班次账户。
|
||||
return noticeAnnouncementMapper
|
||||
.selectActiveAccountIdsByDepartments(
|
||||
departmentIds);
|
||||
}
|
||||
|
||||
/**
|
||||
* 分批写入接收人快照。
|
||||
*
|
||||
* @param noticeId 公告编号
|
||||
* @param recipients 全部接收人记录
|
||||
* @param receivedTime 统一接收时间
|
||||
*/
|
||||
private void insertRecipientSnapshots(
|
||||
String noticeId,
|
||||
List<NoticeAnnouncementRecipientInsertDTO>
|
||||
recipients,
|
||||
LocalDateTime receivedTime) {
|
||||
// 第一步:按照固定批次大小切分接收人记录。
|
||||
for (int start = 0;
|
||||
start < recipients.size();
|
||||
start += RECIPIENT_INSERT_BATCH_SIZE) {
|
||||
int end = Math.min(
|
||||
start + RECIPIENT_INSERT_BATCH_SIZE,
|
||||
recipients.size());
|
||||
|
||||
// 第二步:使用单条批量 INSERT SELECT 写入当前批次。
|
||||
noticeAnnouncementMapper.insertNoticeRecipients(
|
||||
noticeId,
|
||||
recipients.subList(start, end),
|
||||
receivedTime);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据当前服务端会话取得真实账户编号。
|
||||
*
|
||||
* @return 当前登录账户编号
|
||||
*/
|
||||
private String currentAccountId() {
|
||||
// 第一步:只从当前 HTTP 请求读取服务端 SessionId。
|
||||
String sessionId = requireCurrentSessionId();
|
||||
|
||||
// 第二步:通过在线记录和登录信息表查询真实账户编号。
|
||||
String accountId =
|
||||
noticeAnnouncementMapper
|
||||
.selectAccountIdBySessionId(
|
||||
sessionId);
|
||||
|
||||
// 第三步:校验并返回当前会话对应的有效账户编号。
|
||||
return requireCurrentAccountId(accountId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询并补全公告后台详情。
|
||||
*
|
||||
* @param id 公告编号
|
||||
* @return 公告后台详情
|
||||
*/
|
||||
private NoticeAnnouncementDetailVO loadDetail(
|
||||
String id) {
|
||||
// 第一步:查询公告主体、发布范围和接收阅读统计。
|
||||
NoticeAnnouncementDetailVO detail =
|
||||
noticeAnnouncementMapper
|
||||
.selectNoticeAnnouncementDetail(id);
|
||||
|
||||
// 第二步:公告不存在时返回明确的资源不存在错误。
|
||||
if (detail == null) {
|
||||
throw new ServiceException("通知公告不存在",
|
||||
NOT_FOUND);
|
||||
}
|
||||
|
||||
// 第三步:补全范围说明和空统计值后返回。
|
||||
return completeDetail(detail);
|
||||
}
|
||||
|
||||
}
|
||||
+244
@@ -0,0 +1,244 @@
|
||||
package com.roomroot.jwgl.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.roomroot.jwgl.dto.notificationlog.NotificationLogExportDTO;
|
||||
import com.roomroot.jwgl.dto.notificationlog.NotificationLogIdDTO;
|
||||
import com.roomroot.jwgl.dto.notificationlog.NotificationLogQueryDTO;
|
||||
import com.roomroot.jwgl.dto.notificationlog.NotificationLogRecipientQueryDTO;
|
||||
import com.roomroot.jwgl.mapper.NotificationLogMapper;
|
||||
import com.roomroot.jwgl.service.NotificationLogService;
|
||||
import com.roomroot.jwgl.unit.PageResult;
|
||||
import com.roomroot.jwgl.utils.PageResultUtil;
|
||||
import com.roomroot.jwgl.vo.notificationlog.NotificationLogDetailVO;
|
||||
import com.roomroot.jwgl.vo.notificationlog.NotificationLogRecipientVO;
|
||||
import com.roomroot.jwgl.vo.notificationlog.NotificationLogStatisticsVO;
|
||||
import com.roomroot.jwgl.vo.notificationlog.NotificationLogVO;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import jakarta.annotation.Resource;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import static com.roomroot.jwgl.utils.NotificationLogUtil.completeDetail;
|
||||
import static com.roomroot.jwgl.utils.NotificationLogUtil.completeRecords;
|
||||
import static com.roomroot.jwgl.utils.NotificationLogUtil.completeStatistics;
|
||||
import static com.roomroot.jwgl.utils.NotificationLogUtil.normalizeExportQuery;
|
||||
import static com.roomroot.jwgl.utils.NotificationLogUtil.normalizeId;
|
||||
import static com.roomroot.jwgl.utils.NotificationLogUtil.normalizeQuery;
|
||||
import static com.roomroot.jwgl.utils.NotificationLogUtil.normalizeRecipientQuery;
|
||||
|
||||
/**
|
||||
* 通知日志管理服务实现。
|
||||
*
|
||||
* <p>当前类只编排通知日志业务流程,查询参数规范化和统计字段补全
|
||||
* 统一由通知日志工具类处理。</p>
|
||||
*/
|
||||
@Service
|
||||
public class NotificationLogServiceImpl
|
||||
implements NotificationLogService {
|
||||
|
||||
/**
|
||||
* 通知日志管理数据访问对象。
|
||||
*/
|
||||
@Resource
|
||||
private NotificationLogMapper notificationLogMapper;
|
||||
|
||||
/**
|
||||
* 分页查询已经实际发送的通知日志。
|
||||
*
|
||||
* @param dto 通知日志查询条件
|
||||
* @return 通知日志分页结果
|
||||
*/
|
||||
@Override
|
||||
@Transactional(readOnly = true)
|
||||
public PageResult<NotificationLogVO> list(
|
||||
NotificationLogQueryDTO dto) {
|
||||
// 第一步:规范化并校验分页、文本、时间和发送状态条件。
|
||||
NotificationLogQueryDTO query =
|
||||
normalizeQuery(dto);
|
||||
|
||||
// 第二步:创建 MyBatis-Plus 通知日志分页对象。
|
||||
Page<NotificationLogVO> page =
|
||||
new Page<>(
|
||||
query.getPageNum().longValue(),
|
||||
query.getPageSize().longValue());
|
||||
|
||||
// 第三步:查询已经产生接收记录的通知发送历史。
|
||||
Page<NotificationLogVO> selectedPage =
|
||||
notificationLogMapper
|
||||
.selectNotificationLogPage(
|
||||
page, query);
|
||||
|
||||
// 第四步:兼容 Mapper 返回 null,并确定用于读取分页总数的结果对象。
|
||||
Page<NotificationLogVO> resultPage =
|
||||
selectedPage == null ? page : selectedPage;
|
||||
|
||||
// 第五步:统一补全发送失败数、未读数、发送状态和阅读率。
|
||||
List<NotificationLogVO> records =
|
||||
completeRecords(resultPage.getRecords());
|
||||
|
||||
// 第六步:复用项目公共分页工具返回统一分页结构。
|
||||
return PageResultUtil.fromRecords(
|
||||
resultPage,
|
||||
records,
|
||||
query.getPageNum(),
|
||||
query.getPageSize());
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据通知编号查询单条发送日志详情。
|
||||
*
|
||||
* @param dto 通知日志编号参数
|
||||
* @return 通知主体和完整发送、阅读统计
|
||||
*/
|
||||
@Override
|
||||
@Transactional(readOnly = true)
|
||||
public NotificationLogDetailVO get(
|
||||
NotificationLogIdDTO dto) {
|
||||
// 第一步:规范化并校验通知日志编号。
|
||||
String id = normalizeId(dto);
|
||||
|
||||
// 第二步:查询已经实际产生接收记录的通知发送日志详情。
|
||||
NotificationLogDetailVO detail =
|
||||
notificationLogMapper
|
||||
.selectNotificationLogDetail(id);
|
||||
|
||||
// 第三步:校验日志存在并补全发送失败数、未读数和阅读率。
|
||||
return completeDetail(detail);
|
||||
}
|
||||
|
||||
/**
|
||||
* 分页查询指定通知的接收对象和阅读明细。
|
||||
*
|
||||
* @param dto 通知编号、分页和接收阅读筛选条件
|
||||
* @return 按账户去重的接收与阅读明细
|
||||
*/
|
||||
@Override
|
||||
@Transactional(readOnly = true)
|
||||
public PageResult<NotificationLogRecipientVO> recipients(
|
||||
NotificationLogRecipientQueryDTO dto) {
|
||||
// 第一步:规范化并校验通知编号、分页和接收阅读筛选条件。
|
||||
NotificationLogRecipientQueryDTO query =
|
||||
normalizeRecipientQuery(dto);
|
||||
|
||||
/*
|
||||
* 第二步:查询通知发送日志主体并校验存在性。
|
||||
* 即使明细筛选后为空,也能区分“没有匹配接收人”和“日志不存在”。
|
||||
*/
|
||||
completeDetail(
|
||||
notificationLogMapper
|
||||
.selectNotificationLogDetail(
|
||||
query.getId()));
|
||||
|
||||
// 第三步:创建 MyBatis-Plus 接收与阅读明细分页对象。
|
||||
Page<NotificationLogRecipientVO> page =
|
||||
new Page<>(
|
||||
query.getPageNum().longValue(),
|
||||
query.getPageSize().longValue());
|
||||
|
||||
// 第四步:按账户去重查询指定通知的接收和阅读明细。
|
||||
Page<NotificationLogRecipientVO> selectedPage =
|
||||
notificationLogMapper
|
||||
.selectNotificationLogRecipientPage(
|
||||
page, query);
|
||||
|
||||
// 第五步:兼容 Mapper 返回 null,并确定分页总数来源。
|
||||
Page<NotificationLogRecipientVO> resultPage =
|
||||
selectedPage == null ? page : selectedPage;
|
||||
|
||||
// 第六步:将异常空明细集合统一转换为空集合。
|
||||
List<NotificationLogRecipientVO> selectedRecords =
|
||||
resultPage.getRecords();
|
||||
List<NotificationLogRecipientVO> records =
|
||||
selectedRecords == null
|
||||
? Collections
|
||||
.<NotificationLogRecipientVO>emptyList()
|
||||
: selectedRecords;
|
||||
|
||||
// 第七步:复用项目公共分页工具返回统一分页结构。
|
||||
return PageResultUtil.fromRecords(
|
||||
resultPage,
|
||||
records,
|
||||
query.getPageNum(),
|
||||
query.getPageSize());
|
||||
}
|
||||
|
||||
/**
|
||||
* 按当前筛选条件汇总通知发送和阅读情况。
|
||||
*
|
||||
* @param dto 通知日志筛选条件
|
||||
* @return 通知数量、发送结果和阅读情况汇总
|
||||
*/
|
||||
@Override
|
||||
@Transactional(readOnly = true)
|
||||
public NotificationLogStatisticsVO statistics(
|
||||
NotificationLogExportDTO dto) {
|
||||
// 第一步:将统计条件转换为与列表一致的规范化查询条件。
|
||||
NotificationLogQueryDTO query =
|
||||
normalizeExportQuery(dto);
|
||||
|
||||
// 第二步:在数据库中汇总符合条件的通知和接收阅读数量。
|
||||
NotificationLogStatisticsVO statistics =
|
||||
notificationLogMapper
|
||||
.selectNotificationLogStatistics(
|
||||
query);
|
||||
|
||||
// 第三步:统一补全失败数、未读数和汇总阅读率。
|
||||
return completeStatistics(statistics);
|
||||
}
|
||||
|
||||
/**
|
||||
* 按当前筛选条件查询全部待导出的通知日志。
|
||||
*
|
||||
* @param dto 通知日志导出筛选条件
|
||||
* @return 与列表筛选和排序规则一致的全部通知日志
|
||||
*/
|
||||
@Override
|
||||
@Transactional(readOnly = true)
|
||||
public List<NotificationLogVO> export(
|
||||
NotificationLogExportDTO dto) {
|
||||
// 第一步:将导出条件转换为固定批次的列表查询参数。
|
||||
NotificationLogQueryDTO query =
|
||||
normalizeExportQuery(dto);
|
||||
|
||||
// 第二步:复用列表业务查询第一批通知日志。
|
||||
PageResult<NotificationLogVO> firstPage =
|
||||
list(query);
|
||||
|
||||
// 第三步:创建独立导出集合并加入第一批有效记录。
|
||||
List<NotificationLogVO> records =
|
||||
new ArrayList<>();
|
||||
if (firstPage.getRecords() != null) {
|
||||
records.addAll(firstPage.getRecords());
|
||||
}
|
||||
|
||||
// 第四步:读取总页数;没有后续批次时直接返回当前结果。
|
||||
Integer pageCount = firstPage.getPages();
|
||||
if (pageCount == null
|
||||
|| pageCount.intValue() <= 1) {
|
||||
return records;
|
||||
}
|
||||
|
||||
/*
|
||||
* 第五步:按照固定页码依次查询剩余日志。
|
||||
* 列表接口使用发送时间和通知编号双重倒序,跨页顺序保持稳定。
|
||||
*/
|
||||
for (int pageNum = 2;
|
||||
pageNum <= pageCount.intValue();
|
||||
pageNum++) {
|
||||
query.setPageNum(Integer.valueOf(pageNum));
|
||||
PageResult<NotificationLogVO> currentPage =
|
||||
list(query);
|
||||
|
||||
// 第六步:忽略异常空集合,按分页顺序追加有效日志。
|
||||
if (currentPage.getRecords() != null) {
|
||||
records.addAll(currentPage.getRecords());
|
||||
}
|
||||
}
|
||||
|
||||
// 第七步:返回与内部分页结果相互独立的完整导出集合。
|
||||
return records;
|
||||
}
|
||||
}
|
||||
+80
@@ -0,0 +1,80 @@
|
||||
package com.roomroot.jwgl.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.roomroot.jwgl.entity.JYSRWS;
|
||||
import com.roomroot.jwgl.mapper.OfficeTaskBookMapper;
|
||||
import com.roomroot.jwgl.service.OfficeTaskBookService;
|
||||
import com.roomroot.jwgl.unit.PageQuery;
|
||||
import com.roomroot.jwgl.unit.PageResult;
|
||||
import com.roomroot.jwgl.utils.UuidUtil;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import jakarta.annotation.Resource;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 教研室任务书服务实现类
|
||||
*/
|
||||
@Service
|
||||
public class OfficeTaskBookServiceImpl implements OfficeTaskBookService {
|
||||
|
||||
@Resource
|
||||
private OfficeTaskBookMapper officeTaskBookMapper;
|
||||
|
||||
@Override
|
||||
public void add(JYSRWS jysrws) {
|
||||
String uuid = UuidUtil.getUUID();
|
||||
jysrws.setBh(uuid);
|
||||
jysrws.setDelFlag(0);
|
||||
// 状态默认为未上报
|
||||
jysrws.setZt("未上报");
|
||||
officeTaskBookMapper.insert(jysrws);
|
||||
}
|
||||
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
@Override
|
||||
public void delete(String bh) {
|
||||
JYSRWS jysrws = getByBh(bh);
|
||||
if (jysrws != null) {
|
||||
jysrws.setDelFlag(1);
|
||||
officeTaskBookMapper.updateById(jysrws);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void batchDelete(List<String> bhList) {
|
||||
for (String bh : bhList) {
|
||||
delete(bh);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(JYSRWS jysrws) {
|
||||
officeTaskBookMapper.updateById(jysrws);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JYSRWS getByBh(String bh) {
|
||||
return officeTaskBookMapper.selectById(bh);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PageResult<JYSRWS> pageList(PageQuery query, JYSRWS jysrws) {
|
||||
jysrws.setDelFlag(0);
|
||||
Page<JYSRWS> page = new Page<>(query.getPageNum(), query.getPageSize());
|
||||
Page<JYSRWS> result = officeTaskBookMapper.selectPageList(page, jysrws);
|
||||
return new PageResult<>(result.getRecords(), result.getTotal(),
|
||||
query.getPageNum(), query.getPageSize());
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<JYSRWS> listByJxrwbh(String jxrwbh) {
|
||||
return officeTaskBookMapper.selectByJxrwbh(jxrwbh);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<JYSRWS> listByJysdh(String jysdh) {
|
||||
return officeTaskBookMapper.selectByJysdh(jysdh);
|
||||
}
|
||||
}
|
||||
+354
@@ -0,0 +1,354 @@
|
||||
package com.roomroot.jwgl.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.roomroot.jwgl.dto.operationlog.OperationLogExportDTO;
|
||||
import com.roomroot.jwgl.dto.operationlog.OperationLogIdDTO;
|
||||
import com.roomroot.jwgl.dto.operationlog.OperationLogQueryDTO;
|
||||
import com.roomroot.jwgl.dto.operationlog.OperationLogRecordDTO;
|
||||
import com.roomroot.jwgl.mapper.OperationLogMapper;
|
||||
import com.roomroot.jwgl.service.OperationLogService;
|
||||
import com.roomroot.common.exception.ServiceException;
|
||||
import com.roomroot.jwgl.unit.PageResult;
|
||||
import com.roomroot.jwgl.utils.PageResultUtil;
|
||||
import com.roomroot.jwgl.utils.UuidUtil;
|
||||
import com.roomroot.jwgl.vo.operationlog.OperationLogDetailVO;
|
||||
import com.roomroot.jwgl.vo.operationlog.OperationLogModuleVO;
|
||||
import com.roomroot.jwgl.vo.operationlog.OperationLogVO;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import jakarta.annotation.Resource;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import static com.roomroot.jwgl.utils.BasicManagementConstants.BAD_REQUEST;
|
||||
import static com.roomroot.jwgl.utils.BasicManagementConstants.CONTENT_KEYWORD_MAX_LENGTH;
|
||||
import static com.roomroot.jwgl.utils.BasicManagementConstants.CONFLICT;
|
||||
import static com.roomroot.jwgl.utils.BasicManagementConstants.IDENTIFIER_MAX_LENGTH;
|
||||
import static com.roomroot.jwgl.utils.BasicManagementConstants.NOT_FOUND;
|
||||
import static com.roomroot.jwgl.utils.BasicManagementConstants.OPERATION_CONTENT_MAX_LENGTH;
|
||||
import static com.roomroot.jwgl.utils.BasicManagementConstants.OPERATION_LOG_EXPORT_BATCH_SIZE;
|
||||
import static com.roomroot.jwgl.utils.BasicManagementConstants.OPERATION_URL_MAX_LENGTH;
|
||||
import static com.roomroot.jwgl.utils.BasicManagementConstants.OPERATOR_KEYWORD_MAX_LENGTH;
|
||||
import static com.roomroot.jwgl.utils.BasicManagementConstants.URL_KEYWORD_MAX_LENGTH;
|
||||
import static com.roomroot.jwgl.utils.OperationLogUtil.listOperationLogModules;
|
||||
import static com.roomroot.jwgl.utils.OperationLogUtil.optionalModule;
|
||||
import static com.roomroot.jwgl.utils.OperationLogUtil.optionalText;
|
||||
import static com.roomroot.jwgl.utils.OperationLogUtil.requiredText;
|
||||
import static com.roomroot.jwgl.utils.OperationLogUtil.resolveModule;
|
||||
|
||||
/**
|
||||
* 操作日志管理服务实现。
|
||||
*
|
||||
* <p>当前类统一编排分页查询、详情查询、导出和内部写入流程,
|
||||
* 参数辅助处理集中维护在操作日志工具类中。</p>
|
||||
*/
|
||||
@Service
|
||||
public class OperationLogServiceImpl implements OperationLogService {
|
||||
|
||||
/**
|
||||
* 操作日志数据访问对象。
|
||||
*/
|
||||
@Resource
|
||||
private OperationLogMapper operationLogMapper;
|
||||
|
||||
/**
|
||||
* 分页查询操作日志。
|
||||
*
|
||||
* <p>处理顺序:校验分页和时间范围、规范化查询条件、
|
||||
* 数据库联表筛选、识别模块名称、封装统一分页结果。</p>
|
||||
*
|
||||
* @param dto 查询条件
|
||||
* @return 经过筛选和稳定排序的操作日志分页结果
|
||||
*/
|
||||
@Override
|
||||
@Transactional(readOnly = true)
|
||||
public PageResult<OperationLogVO> list(OperationLogQueryDTO dto) {
|
||||
// 第一步:兼容业务层直接传入 null,并使用 DTO 中的默认分页参数。
|
||||
OperationLogQueryDTO query =
|
||||
dto == null ? new OperationLogQueryDTO() : dto;
|
||||
|
||||
// 第二步:校验页码,防止绕过控制器校验后生成无效分页语句。
|
||||
Integer pageNum = query.getPageNum();
|
||||
if (pageNum == null || pageNum.intValue() < 1) {
|
||||
throw new ServiceException("页码最小为1", BAD_REQUEST);
|
||||
}
|
||||
|
||||
// 第三步:校验每页记录数,保持与项目其他分页接口相同的上限。
|
||||
Integer pageSize = query.getPageSize();
|
||||
if (pageSize == null
|
||||
|| pageSize.intValue() < 1
|
||||
|| pageSize.intValue() > 100) {
|
||||
throw new ServiceException("每页大小必须在1到100之间",
|
||||
BAD_REQUEST);
|
||||
}
|
||||
|
||||
// 第四步:读取时间范围并校验开始时间不能晚于结束时间。
|
||||
LocalDateTime startTime = query.getStartTime();
|
||||
LocalDateTime endTime = query.getEndTime();
|
||||
if (startTime != null
|
||||
&& endTime != null
|
||||
&& startTime.isAfter(endTime)) {
|
||||
throw new ServiceException("开始时间不能晚于结束时间",
|
||||
BAD_REQUEST);
|
||||
}
|
||||
|
||||
// 第五步:规范化操作人关键字,空字符串按照未填写处理。
|
||||
String operatorKeyword = optionalText(
|
||||
query.getOperatorKeyword(),
|
||||
OPERATOR_KEYWORD_MAX_LENGTH,
|
||||
"操作人关键字");
|
||||
|
||||
// 第六步:规范化并校验模块名称,只允许查询系统已识别的模块。
|
||||
String module = optionalModule(query.getModule());
|
||||
|
||||
// 第七步:规范化操作内容关键字,防止业务层直接调用时绕过长度校验。
|
||||
String contentKeyword = optionalText(
|
||||
query.getContentKeyword(),
|
||||
CONTENT_KEYWORD_MAX_LENGTH,
|
||||
"操作内容关键字");
|
||||
|
||||
// 第八步:规范化请求地址关键字,空字符串按照未填写处理。
|
||||
String urlKeyword = optionalText(
|
||||
query.getUrlKeyword(),
|
||||
URL_KEYWORD_MAX_LENGTH,
|
||||
"请求地址关键字");
|
||||
|
||||
// 第九步:创建分页对象,由 MyBatis-Plus 生成达梦分页和总数语句。
|
||||
Page<OperationLogVO> page =
|
||||
new Page<>(pageNum.longValue(), pageSize.longValue());
|
||||
|
||||
/*
|
||||
* 第十步:在数据库中完成三表关联、组合筛选和稳定排序。
|
||||
* 操作人身份来源于登录记录关联账户,不接收客户端提交的账户编号。
|
||||
*/
|
||||
Page<OperationLogVO> selectedPage =
|
||||
operationLogMapper.selectOperationLogPage(
|
||||
page,
|
||||
startTime,
|
||||
endTime,
|
||||
operatorKeyword,
|
||||
module,
|
||||
contentKeyword,
|
||||
urlKeyword);
|
||||
|
||||
// 第十一步:兼容模拟测试或异常 Mapper 返回 null 分页对象的情况。
|
||||
Page<OperationLogVO> resultPage =
|
||||
selectedPage == null ? page : selectedPage;
|
||||
|
||||
// 第十二步:取得当前页记录,并将 null 集合统一转换为空集合。
|
||||
List<OperationLogVO> selectedRecords = resultPage.getRecords();
|
||||
List<OperationLogVO> records = selectedRecords == null
|
||||
? Collections.<OperationLogVO>emptyList()
|
||||
: selectedRecords;
|
||||
|
||||
/*
|
||||
* 第十三步:根据每条日志的请求地址补充模块名称。
|
||||
* 旧数据库没有模块字段,因此模块只用于页面展示和查询分类。
|
||||
*/
|
||||
for (OperationLogVO record : records) {
|
||||
if (record != null) {
|
||||
record.setModule(resolveModule(record.getUrl()));
|
||||
}
|
||||
}
|
||||
|
||||
// 第十四步:返回项目统一分页结构,总数由分页拦截器统计。
|
||||
return PageResultUtil.fromRecords(
|
||||
resultPage,
|
||||
records,
|
||||
pageNum,
|
||||
pageSize);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询操作日志页面可使用的模块选项。
|
||||
*
|
||||
* @return 与模块筛选白名单保持一致的模块选项
|
||||
*/
|
||||
@Override
|
||||
@Transactional(readOnly = true)
|
||||
public List<OperationLogModuleVO> modules() {
|
||||
// 调用操作日志工具类统一转换模块配置,业务层不重复维护固定选项。
|
||||
return listOperationLogModules();
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据编号查询操作日志详情。
|
||||
*
|
||||
* <p>处理顺序:校验并规范化编号、查询三表关联信息、
|
||||
* 校验日志是否存在、根据请求地址补充业务模块名称。</p>
|
||||
*
|
||||
* @param dto 操作日志编号参数
|
||||
* @return 操作日志详情
|
||||
*/
|
||||
@Override
|
||||
@Transactional(readOnly = true)
|
||||
public OperationLogDetailVO get(OperationLogIdDTO dto) {
|
||||
// 第一步:防止业务层被直接调用时传入空 DTO。
|
||||
if (dto == null) {
|
||||
throw new ServiceException("操作日志编号不能为空",
|
||||
BAD_REQUEST);
|
||||
}
|
||||
|
||||
// 第二步:去除日志编号首尾空白,并将空文本视为未填写。
|
||||
String id = dto.getId() == null
|
||||
? null
|
||||
: dto.getId().trim();
|
||||
if (id == null || id.isEmpty()) {
|
||||
throw new ServiceException("操作日志编号不能为空",
|
||||
BAD_REQUEST);
|
||||
}
|
||||
|
||||
/*
|
||||
* 第三步:使用公共标识符长度常量校验编号。
|
||||
* 固定长度统一维护在常量工具类中,不在业务实现类重复声明。
|
||||
*/
|
||||
if (id.length() > IDENTIFIER_MAX_LENGTH) {
|
||||
throw new ServiceException("操作日志编号格式不正确",
|
||||
BAD_REQUEST);
|
||||
}
|
||||
|
||||
// 第四步:根据日志编号联查操作日志、登录记录和账户信息。
|
||||
OperationLogDetailVO detail =
|
||||
operationLogMapper.selectOperationLogById(id);
|
||||
|
||||
// 第五步:日志不存在时返回明确的业务错误,不返回空成功结果。
|
||||
if (detail == null) {
|
||||
throw new ServiceException("操作日志不存在",
|
||||
NOT_FOUND);
|
||||
}
|
||||
|
||||
/*
|
||||
* 第六步:旧操作日志表没有模块字段,
|
||||
* 因此根据请求地址补充与列表接口一致的模块名称。
|
||||
*/
|
||||
detail.setModule(resolveModule(detail.getUrl()));
|
||||
|
||||
// 第七步:返回完成关联查询和模块补充的操作日志详情。
|
||||
return detail;
|
||||
}
|
||||
|
||||
/**
|
||||
* 按筛选条件查询全部待导出的操作日志。
|
||||
*
|
||||
* <p>处理顺序:转换导出条件、按照列表接口允许的最大页大小分批查询、
|
||||
* 汇总全部页面记录,并保持与页面列表完全一致的筛选和排序结果。</p>
|
||||
*
|
||||
* @param dto 导出筛选条件
|
||||
* @return 全部符合条件的操作日志
|
||||
*/
|
||||
@Override
|
||||
@Transactional(readOnly = true)
|
||||
public List<OperationLogVO> export(OperationLogExportDTO dto) {
|
||||
// 第一步:兼容业务层直接传入 null,并将其视为导出全部操作日志。
|
||||
OperationLogExportDTO export =
|
||||
dto == null ? new OperationLogExportDTO() : dto;
|
||||
|
||||
/*
|
||||
* 第二步:创建列表查询 DTO,只复制导出允许使用的筛选条件。
|
||||
* 导出接口不接收客户端分页参数,分页过程完全由服务端控制。
|
||||
*/
|
||||
OperationLogQueryDTO query = new OperationLogQueryDTO();
|
||||
query.setStartTime(export.getStartTime());
|
||||
query.setEndTime(export.getEndTime());
|
||||
query.setOperatorKeyword(export.getOperatorKeyword());
|
||||
query.setModule(export.getModule());
|
||||
query.setContentKeyword(export.getContentKeyword());
|
||||
query.setUrlKeyword(export.getUrlKeyword());
|
||||
query.setPageNum(Integer.valueOf(1));
|
||||
query.setPageSize(
|
||||
Integer.valueOf(OPERATION_LOG_EXPORT_BATCH_SIZE));
|
||||
|
||||
/*
|
||||
* 第三步:先查询第一页。
|
||||
* 该调用会复用已有的时间、文本、模块校验以及数据库筛选和稳定排序规则。
|
||||
*/
|
||||
PageResult<OperationLogVO> firstPage = list(query);
|
||||
|
||||
// 第四步:创建独立导出集合,并加入第一页返回的日志记录。
|
||||
List<OperationLogVO> exportedLogs = new ArrayList<>();
|
||||
if (firstPage.getRecords() != null) {
|
||||
exportedLogs.addAll(firstPage.getRecords());
|
||||
}
|
||||
|
||||
// 第五步:读取总页数;没有更多页面时直接返回第一页汇总结果。
|
||||
Integer pageCount = firstPage.getPages();
|
||||
if (pageCount == null || pageCount.intValue() <= 1) {
|
||||
return exportedLogs;
|
||||
}
|
||||
|
||||
/*
|
||||
* 第六步:按照固定页码依次查询剩余记录。
|
||||
* 列表查询使用操作时间和日志编号双重倒序,可以保证跨页顺序稳定。
|
||||
*/
|
||||
for (int pageNum = 2;
|
||||
pageNum <= pageCount.intValue();
|
||||
pageNum++) {
|
||||
query.setPageNum(Integer.valueOf(pageNum));
|
||||
PageResult<OperationLogVO> currentPage = list(query);
|
||||
|
||||
// 第七步:忽略异常空集合,并按查询页顺序追加有效日志。
|
||||
if (currentPage.getRecords() != null) {
|
||||
exportedLogs.addAll(currentPage.getRecords());
|
||||
}
|
||||
}
|
||||
|
||||
// 第八步:返回与内部分页结果集合相互独立的完整导出数据。
|
||||
return exportedLogs;
|
||||
}
|
||||
|
||||
/**
|
||||
* 写入一条由服务端自动采集的操作日志。
|
||||
*
|
||||
* <p>当前小功能只建立内部写入能力,登录记录编号由后续统一请求记录流程
|
||||
* 从服务端会话取得,不提供客户端写入接口。</p>
|
||||
*
|
||||
* @param dto 当前登录记录编号、操作内容和请求地址
|
||||
*/
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void record(OperationLogRecordDTO dto) {
|
||||
// 第一步:防止内部调用方传入空 DTO,避免产生缺少审计上下文的日志。
|
||||
if (dto == null) {
|
||||
throw new ServiceException("操作日志记录参数不能为空",
|
||||
BAD_REQUEST);
|
||||
}
|
||||
|
||||
// 第二步:校验并规范化当前请求关联的登录记录编号。
|
||||
String loginRecordId = requiredText(
|
||||
dto.getLoginRecordId(),
|
||||
IDENTIFIER_MAX_LENGTH,
|
||||
"登录记录编号");
|
||||
|
||||
// 第三步:校验并规范化服务端生成的业务操作内容。
|
||||
String operationContent = requiredText(
|
||||
dto.getOperationContent(),
|
||||
OPERATION_CONTENT_MAX_LENGTH,
|
||||
"操作内容");
|
||||
|
||||
// 第四步:校验并规范化当前请求的应用内访问地址。
|
||||
String url = requiredText(
|
||||
dto.getUrl(),
|
||||
OPERATION_URL_MAX_LENGTH,
|
||||
"请求地址");
|
||||
|
||||
/*
|
||||
* 第五步:由服务端生成日志编号和操作时间并写入数据库。
|
||||
* 调用方不能指定编号或时间,避免审计记录被伪造或覆盖。
|
||||
*/
|
||||
int affectedRows = operationLogMapper.insertOperationLog(
|
||||
UuidUtil.getOriginalUUID(),
|
||||
loginRecordId,
|
||||
LocalDateTime.now(),
|
||||
operationContent,
|
||||
url);
|
||||
|
||||
// 第六步:数据库未写入唯一记录时返回明确冲突错误。
|
||||
if (affectedRows != 1) {
|
||||
throw new ServiceException("操作日志记录失败",
|
||||
CONFLICT);
|
||||
}
|
||||
}
|
||||
}
|
||||
+200
@@ -0,0 +1,200 @@
|
||||
package com.roomroot.jwgl.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.roomroot.jwgl.entity.XQXLB;
|
||||
import com.roomroot.jwgl.mapper.SemesterCalendarMapper;
|
||||
import com.roomroot.jwgl.service.SemesterCalendarService;
|
||||
import com.roomroot.jwgl.utils.DateCourseUtil;
|
||||
import com.roomroot.jwgl.utils.UuidUtil;
|
||||
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
|
||||
import org.apache.poi.ss.usermodel.*;
|
||||
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import jakarta.annotation.Resource;
|
||||
import java.io.InputStream;
|
||||
import java.time.LocalDate;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 学期校历表服务实现类
|
||||
*/
|
||||
@Service
|
||||
public class SemesterCalendarServiceImpl implements SemesterCalendarService {
|
||||
|
||||
@Resource
|
||||
private SemesterCalendarMapper xqxlbMapper;
|
||||
|
||||
@Override
|
||||
public void add(String startDate,String endDateb) {
|
||||
Map<String, Object> dateWeekAndCourseMap = DateCourseUtil.getDateWeekAndCourseMap(startDate, endDateb);
|
||||
for (Map.Entry<String, Object> entry : dateWeekAndCourseMap.entrySet()) {
|
||||
String dateStr = entry.getKey();
|
||||
Page<XQXLB> page = new Page<>(0, 10);
|
||||
XQXLB query = new XQXLB();
|
||||
//将日期分为年度和月日
|
||||
LocalDate date = LocalDate.parse(dateStr, DateTimeFormatter.ofPattern("yyyy-MM-dd"));
|
||||
|
||||
int nd = date.getYear();
|
||||
String md = String.format("%02d%02d", date.getMonthValue(), date.getDayOfMonth());
|
||||
query.setJqsj(md);
|
||||
query.setNd(nd);
|
||||
Page<XQXLB> result = xqxlbMapper.selectPageList(page, query);
|
||||
if(result.getTotal() > 0){
|
||||
continue;
|
||||
}
|
||||
Map<String,Object> map = (Map<String, Object>) entry.getValue();
|
||||
Object course = map.get("course");
|
||||
if (course instanceof ArrayList<?>) {
|
||||
ArrayList<String> list = (ArrayList<String>) course;
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
String courseClass = list.get(i);
|
||||
XQXLB xqxlb = new XQXLB();
|
||||
//编号,用时间戳
|
||||
String bh = UuidUtil.getUUID();
|
||||
xqxlb.setBh(bh);
|
||||
//假期时间
|
||||
xqxlb.setJqsj(dateStr);
|
||||
//年度
|
||||
xqxlb.setNd(Integer.valueOf(nd));
|
||||
//节次
|
||||
xqxlb.setCourseClass(courseClass);
|
||||
xqxlb.setKpk(true);
|
||||
xqxlb.setBzxs(true);
|
||||
xqxlb.setZdpk(true);
|
||||
xqxlbMapper.insert(xqxlb);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void delete(String bh) {
|
||||
xqxlbMapper.deleteById(bh);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(XQXLB xqxlb) {
|
||||
xqxlbMapper.updateById(xqxlb);
|
||||
}
|
||||
|
||||
@Override
|
||||
public XQXLB getById(String bh) {
|
||||
return xqxlbMapper.selectById(bh);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<XQXLB> listByNd(Integer nd) {
|
||||
LambdaQueryWrapper<XQXLB> wrapper = new LambdaQueryWrapper<>();
|
||||
wrapper.eq(XQXLB::getNd, nd);
|
||||
return xqxlbMapper.selectList(wrapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int importExcel(MultipartFile file) {
|
||||
try (InputStream is = file.getInputStream();
|
||||
Workbook workbook = file.getOriginalFilename().endsWith(".xlsx")
|
||||
? new XSSFWorkbook(is) : new HSSFWorkbook(is)) {
|
||||
|
||||
Sheet sheet = workbook.getSheetAt(0);
|
||||
int count = 0;
|
||||
|
||||
// 从第二行开始读取数据(跳过表头)
|
||||
for (int i = 1; i <= sheet.getLastRowNum(); i++) {
|
||||
Row row = sheet.getRow(i);
|
||||
if (row == null) continue;
|
||||
|
||||
XQXLB xqxlb = new XQXLB();
|
||||
|
||||
// 编号
|
||||
xqxlb.setBh(UuidUtil.getUUID());
|
||||
|
||||
// 年度
|
||||
String nd = getCellValue(row, 0);
|
||||
if (nd != null && !nd.isEmpty()) {
|
||||
xqxlb.setNd(Integer.parseInt(nd));
|
||||
}
|
||||
|
||||
// 假期时间
|
||||
String jqsj = getCellValue(row, 1);
|
||||
xqxlb.setJqsj(jqsj);
|
||||
Page<XQXLB> page = new Page<>(0, 10);
|
||||
Page<XQXLB> result = xqxlbMapper.selectPageList(page, xqxlb);
|
||||
if(result.getTotal() > 0){
|
||||
continue;
|
||||
}
|
||||
|
||||
// 假期名称
|
||||
xqxlb.setJqmc(getCellValue(row, 2));
|
||||
|
||||
// 加粗
|
||||
String jc = getCellValue(row, 3);
|
||||
xqxlb.setJc(jc != null && "是".equals(jc));
|
||||
|
||||
// 备注
|
||||
xqxlb.setBz(getCellValue(row, 4));
|
||||
|
||||
// 可排课
|
||||
String kpk = getCellValue(row, 5);
|
||||
xqxlb.setKpk("是".equals(kpk));
|
||||
|
||||
// 备注显示
|
||||
String bzxs = getCellValue(row, 6);
|
||||
xqxlb.setBzxs("是".equals(bzxs));
|
||||
|
||||
// 自动排课
|
||||
String zdpk = getCellValue(row, 7);
|
||||
xqxlb.setZdpk("是".equals(zdpk));
|
||||
|
||||
// 节次
|
||||
xqxlb.setCourseClass(getCellValue(row, 8));
|
||||
|
||||
xqxlbMapper.insert(xqxlb);
|
||||
count++;
|
||||
}
|
||||
return count;
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("Excel解析失败: " + e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取单元格字符串值
|
||||
*/
|
||||
private String getCellValue(Row row, int index) {
|
||||
Cell cell = row.getCell(index, Row.MissingCellPolicy.CREATE_NULL_AS_BLANK);
|
||||
if (cell == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
CellType type = cell.getCellType();
|
||||
// 处理公式单元格
|
||||
if (type == CellType.FORMULA) {
|
||||
type = cell.getCachedFormulaResultType();
|
||||
}
|
||||
|
||||
switch (type) {
|
||||
case NUMERIC:
|
||||
double num = cell.getNumericCellValue();
|
||||
// 整数就去掉小数点后多余的 .0
|
||||
if (num == Math.floor(num)) {
|
||||
return String.valueOf((long) num);
|
||||
} else {
|
||||
return String.valueOf(num);
|
||||
}
|
||||
case STRING:
|
||||
return cell.getStringCellValue().trim();
|
||||
case BOOLEAN:
|
||||
return String.valueOf(cell.getBooleanCellValue());
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+91
@@ -0,0 +1,91 @@
|
||||
package com.roomroot.jwgl.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.roomroot.jwgl.entity.XQ;
|
||||
import com.roomroot.jwgl.mapper.SemesterMapper;
|
||||
import com.roomroot.jwgl.service.SemesterCalendarService;
|
||||
import com.roomroot.jwgl.service.SemesterService;
|
||||
import com.roomroot.jwgl.unit.PageQuery;
|
||||
import com.roomroot.jwgl.unit.PageResult;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import jakarta.annotation.Resource;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 学期服务实现类
|
||||
*/
|
||||
@Service
|
||||
public class SemesterServiceImpl extends ServiceImpl<SemesterMapper, XQ> implements SemesterService {
|
||||
|
||||
// 定义格式化器,静态常量只初始化一次
|
||||
private static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd");
|
||||
|
||||
@Resource
|
||||
private SemesterMapper semesterMapper;
|
||||
|
||||
@Resource
|
||||
SemesterCalendarService semesterCalendarService;
|
||||
|
||||
@Override
|
||||
public void add(XQ xq) {
|
||||
xq.setDelFlag(0);
|
||||
xq.setTkbsp(true);
|
||||
int insert = semesterMapper.insert(xq);
|
||||
if(insert > 0){
|
||||
LocalDateTime kxrq = xq.getKxrq();
|
||||
LocalDateTime jsrq = xq.getJsrq();
|
||||
|
||||
String startDate = localDateTimeToDateStr(kxrq);
|
||||
String endDate = localDateTimeToDateStr(jsrq);
|
||||
|
||||
semesterCalendarService.add(startDate, endDate);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* LocalDateTime 转为 yyyy-MM-dd 日期字符串
|
||||
* @param dateTime 日期时间对象
|
||||
* @return 格式:2026-07-22,入参null返回空串
|
||||
*/
|
||||
public static String localDateTimeToDateStr(LocalDateTime dateTime) {
|
||||
if (dateTime == null) {
|
||||
return "";
|
||||
}
|
||||
return dateTime.format(DATE_FORMATTER);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void delete(Integer nd) {
|
||||
semesterMapper.deleteById(nd);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(XQ xq) {
|
||||
semesterMapper.updateById(xq);
|
||||
}
|
||||
|
||||
@Override
|
||||
public XQ getByNd(Integer nd) {
|
||||
return semesterMapper.selectById(nd);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PageResult<XQ> pageList(PageQuery query, XQ xq) {
|
||||
Page<XQ> page = new Page<>(query.getPageNum(), query.getPageSize());
|
||||
Page<XQ> result = semesterMapper.selectPageList(page, xq);
|
||||
return new PageResult<>(result.getRecords(), result.getTotal(),
|
||||
query.getPageNum(), query.getPageSize());
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<XQ> list() {
|
||||
LambdaQueryWrapper<XQ> wrapper = new LambdaQueryWrapper<>();
|
||||
wrapper.orderByDesc(XQ::getNd);
|
||||
return semesterMapper.selectList(wrapper);
|
||||
}
|
||||
}
|
||||
+197
@@ -0,0 +1,197 @@
|
||||
package com.roomroot.jwgl.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.roomroot.jwgl.entity.XYXX;
|
||||
import com.roomroot.jwgl.entity.XYKCCJ;
|
||||
import com.roomroot.jwgl.entity.XYKCGCCJ;
|
||||
import com.roomroot.jwgl.mapper.XYXXMapper;
|
||||
import com.roomroot.jwgl.mapper.XYKCCJMapper;
|
||||
import com.roomroot.jwgl.mapper.XYKCGCCJMapper;
|
||||
import com.roomroot.jwgl.service.StudentRecordsService;
|
||||
import com.roomroot.jwgl.unit.PageQuery;
|
||||
import com.roomroot.jwgl.unit.PageResult;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import org.apache.poi.ss.usermodel.*;
|
||||
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import jakarta.annotation.Resource;
|
||||
import java.io.IOException;
|
||||
import java.net.URLEncoder;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 学员档案管理服务实现类
|
||||
*/
|
||||
@Service
|
||||
public class StudentRecordsServiceImpl implements StudentRecordsService {
|
||||
|
||||
@Resource
|
||||
private XYXXMapper xyxxMapper;
|
||||
|
||||
@Resource
|
||||
private XYKCCJMapper xykccjMapper;
|
||||
|
||||
@Resource
|
||||
private XYKCGCCJMapper xykgccjMapper;
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public void add(XYXX xyxx) {
|
||||
xyxxMapper.insert(xyxx);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public void delete(String bh) {
|
||||
XYXX xyxx = new XYXX();
|
||||
xyxx.setBh(bh);
|
||||
xyxx.setTxzt("退学");
|
||||
xyxxMapper.updateById(xyxx);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public void update(XYXX xyxx) {
|
||||
xyxxMapper.updateById(xyxx);
|
||||
}
|
||||
|
||||
@Override
|
||||
public XYXX getById(String bh) {
|
||||
return xyxxMapper.selectById(bh);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PageResult<XYXX> pageList(PageQuery query, XYXX xyxx) {
|
||||
Page<XYXX> page = new Page<>(query.getPageNum(), query.getPageSize());
|
||||
Page<XYXX> result = xyxxMapper.selectPageList(page, xyxx);
|
||||
return new PageResult<>(result.getRecords(), result.getTotal(),
|
||||
query.getPageNum(), query.getPageSize());
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public void retainGrade(String bh) {
|
||||
XYXX xyxx = new XYXX();
|
||||
xyxx.setBh(bh);
|
||||
xyxx.setLjzt("留级");
|
||||
xyxxMapper.updateById(xyxx);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public void downgrade(String bh) {
|
||||
XYXX xyxx = new XYXX();
|
||||
xyxx.setBh(bh);
|
||||
xyxx.setLjzt("降级");
|
||||
xyxxMapper.updateById(xyxx);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public void dropOut(String bh) {
|
||||
XYXX xyxx = new XYXX();
|
||||
xyxx.setBh(bh);
|
||||
xyxx.setTxzt("退学");
|
||||
xyxxMapper.updateById(xyxx);
|
||||
}
|
||||
|
||||
// ========== 学员课程成绩查询 ==========
|
||||
|
||||
@Override
|
||||
public List<XYKCCJ> getCourseGrades(String xybh) {
|
||||
return xykccjMapper.selectByStudentId(xybh);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<XYKCGCCJ> getCourseProcessGrades(String xybh) {
|
||||
return xykgccjMapper.selectByStudentId(xybh);
|
||||
}
|
||||
|
||||
// ========== Excel 导出 ==========
|
||||
|
||||
@Override
|
||||
public void exportGradesExcel(String xybh, HttpServletResponse response) {
|
||||
XYXX student = xyxxMapper.selectById(xybh);
|
||||
if (student == null) {
|
||||
throw new RuntimeException("学员不存在");
|
||||
}
|
||||
|
||||
List<XYKCCJ> grades = xykccjMapper.selectByStudentId(xybh);
|
||||
|
||||
try (Workbook workbook = new XSSFWorkbook()) {
|
||||
Sheet sheet = workbook.createSheet("课程成绩");
|
||||
|
||||
// 标题行样式
|
||||
Font headerFont = workbook.createFont();
|
||||
headerFont.setBold(true);
|
||||
headerFont.setFontHeightInPoints((short) 12);
|
||||
CellStyle headerStyle = workbook.createCellStyle();
|
||||
headerStyle.setFont(headerFont);
|
||||
headerStyle.setAlignment(HorizontalAlignment.CENTER);
|
||||
headerStyle.setBorderBottom(BorderStyle.THIN);
|
||||
headerStyle.setBorderTop(BorderStyle.THIN);
|
||||
headerStyle.setBorderLeft(BorderStyle.THIN);
|
||||
headerStyle.setBorderRight(BorderStyle.THIN);
|
||||
|
||||
CellStyle dataStyle = workbook.createCellStyle();
|
||||
dataStyle.setAlignment(HorizontalAlignment.CENTER);
|
||||
dataStyle.setBorderBottom(BorderStyle.THIN);
|
||||
dataStyle.setBorderTop(BorderStyle.THIN);
|
||||
dataStyle.setBorderLeft(BorderStyle.THIN);
|
||||
dataStyle.setBorderRight(BorderStyle.THIN);
|
||||
|
||||
// 学员信息行
|
||||
Row infoRow = sheet.createRow(0);
|
||||
infoRow.createCell(0).setCellValue("学员:" + student.getXm());
|
||||
infoRow.createCell(1).setCellValue("学号:" + student.getXh());
|
||||
|
||||
// 表头
|
||||
String[] headers = {"年度", "科目编号", "考试成绩", "平时成绩", "最终成绩",
|
||||
"补考成绩", "补考次数", "考试情况", "已通过", "备注"};
|
||||
Row headerRow = sheet.createRow(2);
|
||||
for (int i = 0; i < headers.length; i++) {
|
||||
Cell cell = headerRow.createCell(i);
|
||||
cell.setCellValue(headers[i]);
|
||||
cell.setCellStyle(headerStyle);
|
||||
}
|
||||
|
||||
// 数据行
|
||||
int rowIdx = 3;
|
||||
for (XYKCCJ g : grades) {
|
||||
Row row = sheet.createRow(rowIdx++);
|
||||
row.createCell(0).setCellValue(g.getNd() != null ? g.getNd().toString() : "");
|
||||
row.createCell(1).setCellValue(g.getKmbh() != null ? g.getKmbh() : "");
|
||||
row.createCell(2).setCellValue(g.getKscj() != null ? g.getKscj().toString() : "");
|
||||
row.createCell(3).setCellValue(g.getPscj() != null ? g.getPscj().toString() : "");
|
||||
row.createCell(4).setCellValue(g.getZzcj() != null ? g.getZzcj().toString() : "");
|
||||
row.createCell(5).setCellValue(g.getBkcj() != null ? g.getBkcj().toString() : "");
|
||||
row.createCell(6).setCellValue(g.getBkcs() != null ? g.getBkcs().toString() : "");
|
||||
row.createCell(7).setCellValue(g.getKsqk() != null ? g.getKsqk() : "");
|
||||
row.createCell(8).setCellValue(g.getYtg() != null && g.getYtg() == 1 ? "是" : "否");
|
||||
row.createCell(9).setCellValue(g.getBz() != null ? g.getBz() : "");
|
||||
|
||||
for (int i = 0; i < 10; i++) {
|
||||
row.getCell(i).setCellStyle(dataStyle);
|
||||
}
|
||||
}
|
||||
|
||||
// 自动列宽
|
||||
for (int i = 0; i < headers.length; i++) {
|
||||
sheet.autoSizeColumn(i);
|
||||
}
|
||||
|
||||
// 输出
|
||||
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
|
||||
response.setHeader("Content-Disposition",
|
||||
"attachment; filename=" + URLEncoder.encode(
|
||||
student.getXm() + "_课程成绩.xlsx", "UTF-8"));
|
||||
workbook.write(response.getOutputStream());
|
||||
response.getOutputStream().flush();
|
||||
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException("导出 Excel 失败", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
+62
@@ -0,0 +1,62 @@
|
||||
package com.roomroot.jwgl.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.roomroot.jwgl.entity.XYDSCKCB;
|
||||
import com.roomroot.jwgl.mapper.StudentTeamOutputScheduleMapper;
|
||||
import com.roomroot.jwgl.service.StudentTeamOutputScheduleService;
|
||||
import com.roomroot.jwgl.utils.UuidUtil;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 学员队输出课程表 Service实现
|
||||
*/
|
||||
@Service
|
||||
public class StudentTeamOutputScheduleServiceImpl implements StudentTeamOutputScheduleService {
|
||||
|
||||
@Autowired
|
||||
private StudentTeamOutputScheduleMapper xydsckcbMapper;
|
||||
|
||||
@Override
|
||||
public void add(XYDSCKCB xydsckcb) {
|
||||
xydsckcb.setBh(UuidUtil.getUUID());
|
||||
xydsckcb.setDelFlag(0);
|
||||
xydsckcbMapper.insert(xydsckcb);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void delete(String bh) {
|
||||
xydsckcbMapper.deleteById(bh);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(XYDSCKCB xydsckcb) {
|
||||
xydsckcbMapper.updateById(xydsckcb);
|
||||
}
|
||||
|
||||
@Override
|
||||
public XYDSCKCB getByBh(String bh) {
|
||||
return xydsckcbMapper.selectByBh(bh);
|
||||
}
|
||||
|
||||
@Override
|
||||
public XYDSCKCB getByNdAndXydbh(Integer nd, String xydbh) {
|
||||
return xydsckcbMapper.selectByNdAndXydbh(nd, xydbh);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Page<XYDSCKCB> list(int pageNum, int pageSize, XYDSCKCB xydsckcb) {
|
||||
Page<XYDSCKCB> page = new Page<>(pageNum, pageSize);
|
||||
return xydsckcbMapper.selectPageList(page, xydsckcb);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<XYDSCKCB> all() {
|
||||
LambdaQueryWrapper<XYDSCKCB> wrapper = new LambdaQueryWrapper<>();
|
||||
wrapper.eq(XYDSCKCB::getDelFlag, 0);
|
||||
return xydsckcbMapper.selectList(wrapper);
|
||||
}
|
||||
}
|
||||
+239
@@ -0,0 +1,239 @@
|
||||
package com.roomroot.jwgl.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.roomroot.jwgl.entity.XYDB;
|
||||
import com.roomroot.jwgl.entity.XYDNDXQJBXXB;
|
||||
import com.roomroot.jwgl.entity.XYDRWB;
|
||||
import com.roomroot.jwgl.entity.ZYJXJHB;
|
||||
import com.roomroot.jwgl.mapper.ClassSemesterMapper;
|
||||
import com.roomroot.jwgl.mapper.StudentTeamTaskMapper;
|
||||
import com.roomroot.jwgl.mapper.XYDBMapper;
|
||||
import com.roomroot.jwgl.mapper.ZYJXJHBMapper;
|
||||
import com.roomroot.jwgl.service.StudentTeamTaskService;
|
||||
import com.roomroot.jwgl.utils.UuidUtil;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 学员队任务表 Service实现
|
||||
*/
|
||||
@Service
|
||||
public class StudentTeamTaskServiceImpl implements StudentTeamTaskService {
|
||||
|
||||
@Autowired
|
||||
private StudentTeamTaskMapper xydrwbMapper;
|
||||
|
||||
@Autowired
|
||||
private ClassSemesterMapper classSemesterMapper;
|
||||
|
||||
@Autowired
|
||||
private XYDBMapper xydbMapper;
|
||||
|
||||
@Autowired
|
||||
private ZYJXJHBMapper zyjxjhbMapper;
|
||||
|
||||
@Override
|
||||
public void add(XYDRWB xydrwb) {
|
||||
xydrwb.setBh(UuidUtil.getUUID());
|
||||
xydrwb.setDelFlag(0);
|
||||
xydrwbMapper.insert(xydrwb);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void delete(String bh) {
|
||||
xydrwbMapper.deleteById(bh);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(XYDRWB xydrwb) {
|
||||
xydrwbMapper.updateById(xydrwb);
|
||||
}
|
||||
|
||||
@Override
|
||||
public XYDRWB getByBh(String bh) {
|
||||
return xydrwbMapper.selectById(bh);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Page<XYDRWB> list(int pageNum, int pageSize, XYDRWB xydrwb) {
|
||||
Page<XYDRWB> page = new Page<>(pageNum, pageSize);
|
||||
return xydrwbMapper.selectPageList(page, xydrwb);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Page<XYDRWB> groupList(int pageNum, int pageSize, XYDRWB xydrwb) {
|
||||
Page<XYDRWB> page = new Page<>(pageNum, pageSize);
|
||||
return xydrwbMapper.selectPageListGroup(page, xydrwb);
|
||||
}
|
||||
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
@Override
|
||||
public int batchPresetMerge(List<String> bhList) {
|
||||
if (CollectionUtils.isEmpty(bhList)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// 查询所有选中的记录
|
||||
List<XYDRWB> tasks = bhList.stream()
|
||||
.map(bh -> xydrwbMapper.selectById(bh))
|
||||
.filter(task -> task != null)
|
||||
.sorted(Comparator.comparing(XYDRWB::getNd, Comparator.nullsLast(Comparator.naturalOrder())))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
if (tasks.isEmpty()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// 获取第一条记录的年度,查询该年度的最大课次序号
|
||||
Integer nd = tasks.get(0).getNd();
|
||||
Integer maxKcxh = xydrwbMapper.selectMaxKcxhByNd(nd);
|
||||
int newKcxh = (maxKcxh == null ? 0 : maxKcxh) + 1;
|
||||
|
||||
// 为所有记录设置统一的课次序号
|
||||
int count = 0;
|
||||
for (XYDRWB task : tasks) {
|
||||
task.setKcxh(newKcxh);
|
||||
xydrwbMapper.updateById(task);
|
||||
count++;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
@Override
|
||||
public int batchPresetSplit(List<String> bhList) {
|
||||
if (CollectionUtils.isEmpty(bhList)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int count = 0;
|
||||
for (String bh : bhList) {
|
||||
XYDRWB task = xydrwbMapper.selectById(bh);
|
||||
if (task != null) {
|
||||
LambdaUpdateWrapper<XYDRWB> wrapper = new LambdaUpdateWrapper<>();
|
||||
wrapper.eq(XYDRWB::getBh, bh)
|
||||
.set(XYDRWB::getKcxh, null);
|
||||
xydrwbMapper.update(null, wrapper);
|
||||
count++;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<XYDRWB> all() {
|
||||
LambdaQueryWrapper<XYDRWB> wrapper = new LambdaQueryWrapper<>();
|
||||
wrapper.eq(XYDRWB::getDelFlag, 0);
|
||||
return xydrwbMapper.selectList(wrapper);
|
||||
}
|
||||
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
@Override
|
||||
public int autoGenerateRequiredCourses(String xydbh, Integer xqdc) {
|
||||
// 1. 根据学员队编号查询学员队表,获取专业代号
|
||||
XYDB xydb = xydbMapper.selectById(xydbh);
|
||||
if (xydb == null || xydb.getZydh() == null) {
|
||||
return 0;
|
||||
}
|
||||
String zydh = xydb.getZydh();
|
||||
|
||||
// 2. 根据专业代号和学期第次查询专业教学计划表(停用=0)
|
||||
LambdaQueryWrapper<ZYJXJHB> planWrapper = new LambdaQueryWrapper<>();
|
||||
planWrapper.eq(ZYJXJHB::getZydh, zydh)
|
||||
.eq(ZYJXJHB::getXqdc, xqdc)
|
||||
.eq(ZYJXJHB::getTy, 0);
|
||||
List<ZYJXJHB> planList = zyjxjhbMapper.selectList(planWrapper);
|
||||
if (CollectionUtils.isEmpty(planList)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// 3. 根据学员队编号和学期第次查询学员队期表,获取年度和学员队学期编号
|
||||
LambdaQueryWrapper<XYDNDXQJBXXB> semesterWrapper = new LambdaQueryWrapper<>();
|
||||
semesterWrapper.eq(XYDNDXQJBXXB::getXydbh, xydbh)
|
||||
.eq(XYDNDXQJBXXB::getXqdc, xqdc)
|
||||
.eq(XYDNDXQJBXXB::getDelFlag, 0)
|
||||
.orderByDesc(XYDNDXQJBXXB::getNd)
|
||||
.last("LIMIT 1");
|
||||
XYDNDXQJBXXB semester = classSemesterMapper.selectOne(semesterWrapper);
|
||||
if (semester == null) {
|
||||
return 0;
|
||||
}
|
||||
Integer nd = semester.getNd();
|
||||
String xydxqbh = semester.getBh();
|
||||
|
||||
// 4. 查询当前班次已存在的课程编号集合
|
||||
LambdaQueryWrapper<XYDRWB> existWrapper = new LambdaQueryWrapper<>();
|
||||
existWrapper.eq(XYDRWB::getXydxqbh, xydxqbh)
|
||||
.eq(XYDRWB::getDelFlag, 0);
|
||||
List<XYDRWB> existList = xydrwbMapper.selectList(existWrapper);
|
||||
List<String> existKbhs = existList.stream()
|
||||
.map(XYDRWB::getKbh)
|
||||
.filter(kbh -> kbh != null)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
// 5. 只添加缺少的课程
|
||||
int count = 0;
|
||||
for (ZYJXJHB plan : planList) {
|
||||
if (existKbhs.contains(plan.getKbh())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
XYDRWB newRecord = new XYDRWB();
|
||||
newRecord.setBh(UuidUtil.getUUID());
|
||||
newRecord.setNd(nd);
|
||||
newRecord.setXydbh(xydbh);
|
||||
newRecord.setKbh(plan.getKbh());
|
||||
newRecord.setXqdc(xqdc);
|
||||
newRecord.setKlx(plan.getKlx());
|
||||
newRecord.setXs(plan.getXs());
|
||||
newRecord.setJc(plan.getJc());
|
||||
newRecord.setZks(plan.getZks());
|
||||
newRecord.setXf(plan.getXf());
|
||||
newRecord.setKsks(plan.getKsks());
|
||||
newRecord.setCjfz(plan.getCjfz());
|
||||
newRecord.setBjrxypjf(plan.getBjrxypjf());
|
||||
newRecord.setLlxs(plan.getLlxs());
|
||||
newRecord.setSjxs(plan.getSjxs());
|
||||
newRecord.setKsksbxs(plan.getKsksbxs());
|
||||
newRecord.setJysdh(plan.getJysdh());
|
||||
newRecord.setXydxqbh(xydxqbh);
|
||||
newRecord.setJhkcxh(count+1);
|
||||
newRecord.setXhbs(count+1);
|
||||
newRecord.setBz2(0);
|
||||
newRecord.setPdtbykxxbz(1);
|
||||
newRecord.setPdqyzdyxs(0);
|
||||
newRecord.setDelFlag(0);
|
||||
|
||||
xydrwbMapper.insert(newRecord);
|
||||
count++;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> copy(List<String> bhList, String newXydbh) {
|
||||
List<String> newBhList = new java.util.ArrayList<>();
|
||||
for (String bh : bhList) {
|
||||
XYDRWB source = xydrwbMapper.selectById(bh);
|
||||
if (source == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
String newBh = UuidUtil.getUUID();
|
||||
source.setBh(newBh);
|
||||
source.setXydbh(newXydbh);
|
||||
source.setDelFlag(0);
|
||||
xydrwbMapper.insert(source);
|
||||
newBhList.add(newBh);
|
||||
}
|
||||
return newBhList;
|
||||
}
|
||||
}
|
||||
+374
@@ -0,0 +1,374 @@
|
||||
package com.roomroot.jwgl.service.impl;
|
||||
|
||||
import com.roomroot.jwgl.dto.systeminitialization.*;
|
||||
import com.roomroot.jwgl.mapper.SystemInitializationMapper;
|
||||
import com.roomroot.jwgl.service.SystemInitializationService;
|
||||
import com.roomroot.jwgl.unit.BusinessException;
|
||||
import com.roomroot.jwgl.utils.UuidUtil;
|
||||
import com.roomroot.jwgl.vo.systeminitialization.*;
|
||||
import com.roomroot.jwgl.vo.systeminitialization.*;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
import static com.roomroot.jwgl.utils.BasicManagementConstants.CONFLICT;
|
||||
import static com.roomroot.jwgl.utils.BasicManagementConstants.NOT_FOUND;
|
||||
import static com.roomroot.jwgl.utils.SystemInitializationUtil.*;
|
||||
|
||||
/**
|
||||
* 系统初始化管理服务实现。
|
||||
*
|
||||
* <p>当前实现只编排系统初始化业务流程,参数校验、Excel 解析、
|
||||
* 历史数据引用检查和返回对象组装统一由工具类负责。</p>
|
||||
*/
|
||||
@Service
|
||||
public class SystemInitializationServiceImpl
|
||||
implements SystemInitializationService {
|
||||
|
||||
/**
|
||||
* 系统初始化数据访问对象。
|
||||
*/
|
||||
@Resource
|
||||
private SystemInitializationMapper systemInitializationMapper;
|
||||
|
||||
/**
|
||||
* 查询当前生效的系统基础参数。
|
||||
*
|
||||
* @return 当前系统基础参数
|
||||
*/
|
||||
@Override
|
||||
@Transactional(readOnly = true)
|
||||
public SystemInitializationConfigurationVO
|
||||
getCurrentConfiguration() {
|
||||
// 第一步:按照系统版本表最大编号查询当前生效的基础参数。
|
||||
SystemInitializationConfigurationVO configuration =
|
||||
systemInitializationMapper
|
||||
.selectCurrentConfiguration();
|
||||
|
||||
// 第二步:系统尚未建立任何版本配置时返回明确的数据不存在异常。
|
||||
if (configuration == null) {
|
||||
throw new BusinessException(
|
||||
NOT_FOUND,
|
||||
"当前系统尚未配置初始化参数");
|
||||
}
|
||||
|
||||
// 第三步:返回已经由 Mapper 显式转换完成的系统基础参数 VO。
|
||||
return configuration;
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存新的系统基础参数版本。
|
||||
*
|
||||
* @param dto 系统基础参数
|
||||
* @return 保存后立即生效的新版本
|
||||
*/
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public SystemInitializationConfigurationVO saveConfiguration(
|
||||
SystemInitializationConfigurationSaveDTO dto) {
|
||||
// 第一步:查询当前配置,用于判断首次初始化和执行乐观版本校验。
|
||||
SystemInitializationConfigurationVO current =
|
||||
systemInitializationMapper
|
||||
.selectCurrentConfiguration();
|
||||
|
||||
// 第二步:规范化页面参数并校验期望版本与当前版本一致。
|
||||
SystemInitializationConfigurationSaveDTO configuration =
|
||||
prepareConfiguration(dto, current);
|
||||
|
||||
// 第三步:使用同一服务端时间生成本次配置版本时间。
|
||||
LocalDateTime versionDate = LocalDateTime.now();
|
||||
|
||||
/*
|
||||
* 第四步:首次配置只在版本表仍为空时写入;
|
||||
* 已有配置时复制全部非页面字段并新增下一条版本记录。
|
||||
*/
|
||||
int affectedRows;
|
||||
if (current == null) {
|
||||
affectedRows =
|
||||
systemInitializationMapper
|
||||
.insertInitialConfiguration(
|
||||
configuration,
|
||||
versionDate);
|
||||
} else {
|
||||
affectedRows =
|
||||
systemInitializationMapper
|
||||
.insertNextConfigurationVersion(
|
||||
configuration,
|
||||
versionDate);
|
||||
}
|
||||
|
||||
// 第五步:影响行数不是一条说明配置在保存期间发生并发变化。
|
||||
requireAffectedRows(
|
||||
affectedRows,
|
||||
1,
|
||||
"系统基础参数已变化,请刷新后重试");
|
||||
|
||||
// 第六步:重新读取并返回刚刚生效的最新配置版本。
|
||||
SystemInitializationConfigurationVO saved =
|
||||
systemInitializationMapper
|
||||
.selectCurrentConfiguration();
|
||||
if (saved == null) {
|
||||
throw new BusinessException(
|
||||
"系统基础参数保存后读取失败");
|
||||
}
|
||||
return saved;
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询当前学期。
|
||||
*
|
||||
* @return 当前学期
|
||||
*/
|
||||
@Override
|
||||
@Transactional(readOnly = true)
|
||||
public SemesterInitializationVO getCurrentSemester() {
|
||||
// 第一步:查询当前学期标志对应的最新学期记录。
|
||||
SemesterInitializationVO semester =
|
||||
systemInitializationMapper
|
||||
.selectCurrentSemester();
|
||||
|
||||
// 第二步:尚未设置当前学期时返回明确的数据不存在异常。
|
||||
if (semester == null) {
|
||||
throw new BusinessException(
|
||||
NOT_FOUND,
|
||||
"当前系统尚未设置当前学期");
|
||||
}
|
||||
|
||||
// 第三步:补充统一展示名称并返回学期参数。
|
||||
return completeSemesterName(semester);
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存指定年度和序号的学期。
|
||||
*
|
||||
* @param dto 学期初始化参数
|
||||
* @return 保存后的学期
|
||||
*/
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public SemesterInitializationVO saveSemester(
|
||||
SemesterInitializationSaveDTO dto) {
|
||||
// 第一步:规范化并校验学期年度、序号、时间范围和默认业务标志。
|
||||
SemesterInitializationSaveDTO semester =
|
||||
prepareSemester(dto);
|
||||
|
||||
// 第二步:禁止当前学期时间范围与其他学期发生重叠。
|
||||
int overlapCount =
|
||||
systemInitializationMapper
|
||||
.countOverlappingSemesters(semester);
|
||||
if (overlapCount > 0) {
|
||||
throw new BusinessException(
|
||||
CONFLICT,
|
||||
"学期时间范围与已有学期重叠");
|
||||
}
|
||||
|
||||
// 第三步:判断同一年度和序号的学期记录是否已经存在。
|
||||
SemesterInitializationVO existing =
|
||||
systemInitializationMapper.selectSemesterByKey(
|
||||
semester.getYear(),
|
||||
semester.getSequenceNumber());
|
||||
|
||||
// 第四步:目标学期设为当前学期时先清除其他记录的当前标志。
|
||||
if (Boolean.TRUE.equals(
|
||||
semester.getCurrentSemester())) {
|
||||
systemInitializationMapper
|
||||
.clearOtherCurrentSemesters(
|
||||
semester.getYear(),
|
||||
semester.getSequenceNumber());
|
||||
}
|
||||
|
||||
// 第五步:根据业务键是否存在选择新增或修改,不重复创建同一学期。
|
||||
int affectedRows;
|
||||
if (existing == null) {
|
||||
affectedRows =
|
||||
systemInitializationMapper
|
||||
.insertSemester(semester);
|
||||
} else {
|
||||
affectedRows =
|
||||
systemInitializationMapper
|
||||
.updateSemester(semester);
|
||||
}
|
||||
|
||||
// 第六步:保存未精确影响一条记录时中止整个学期切换事务。
|
||||
requireAffectedRows(
|
||||
affectedRows,
|
||||
1,
|
||||
"学期参数保存失败,请刷新后重试");
|
||||
|
||||
// 第七步:重新查询并返回保存后的完整学期参数。
|
||||
SemesterInitializationVO saved =
|
||||
systemInitializationMapper.selectSemesterByKey(
|
||||
semester.getYear(),
|
||||
semester.getSequenceNumber());
|
||||
if (saved == null) {
|
||||
throw new BusinessException(
|
||||
"学期参数保存后读取失败");
|
||||
}
|
||||
return completeSemesterName(saved);
|
||||
}
|
||||
|
||||
/**
|
||||
* 导入历史基础数据。
|
||||
*
|
||||
* @param dto 历史数据 Excel 文件
|
||||
* @return 导入结果
|
||||
*/
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public SystemInitializationHistoricalImportResultVO
|
||||
importHistoricalData(
|
||||
SystemInitializationHistoricalImportDTO dto) {
|
||||
// 第一步:解析 Excel 并完成工作表、标题、类型、长度和文件内重复校验。
|
||||
SystemInitializationHistoricalDataDTO data =
|
||||
parseHistoricalData(dto);
|
||||
|
||||
/*
|
||||
* 第二步:一次性读取数据库已有编号,
|
||||
* 在任何写入发生前完成覆盖冲突、所属部别引用和部别循环关系校验。
|
||||
*/
|
||||
data = prepareHistoricalData(
|
||||
data,
|
||||
systemInitializationMapper.selectDepartmentIds(),
|
||||
systemInitializationMapper
|
||||
.selectResearchOfficeIds(),
|
||||
systemInitializationMapper.selectPersonnelIds());
|
||||
|
||||
// 第三步:由服务端为每条教研室隶属关系生成独立关系编号。
|
||||
for (SystemInitializationResearchOfficeImportRowDTO row
|
||||
: data.getResearchOffices()) {
|
||||
row.setRelationId(UuidUtil.getOriginalUUID());
|
||||
}
|
||||
|
||||
// 第四步:使用统一时间记录历史停用数据状态和最终导入完成时间。
|
||||
LocalDateTime importedAt = LocalDateTime.now();
|
||||
|
||||
// 第五步:按照父节点优先顺序批量写入历史部别。
|
||||
if (!data.getDepartments().isEmpty()) {
|
||||
int departmentRows =
|
||||
systemInitializationMapper
|
||||
.insertHistoricalDepartments(
|
||||
data.getDepartments(),
|
||||
importedAt);
|
||||
requireAffectedRows(
|
||||
departmentRows,
|
||||
data.getDepartments().size(),
|
||||
"历史部别数据写入不完整");
|
||||
}
|
||||
|
||||
// 第六步:批量写入教研室基础信息。
|
||||
if (!data.getResearchOffices().isEmpty()) {
|
||||
int researchOfficeRows =
|
||||
systemInitializationMapper
|
||||
.insertHistoricalResearchOffices(
|
||||
data.getResearchOffices(),
|
||||
importedAt);
|
||||
requireAffectedRows(
|
||||
researchOfficeRows,
|
||||
data.getResearchOffices().size(),
|
||||
"历史教研室数据写入不完整");
|
||||
|
||||
// 第七步:在教研室写入成功后批量建立对应的部别隶属关系。
|
||||
int relationRows =
|
||||
systemInitializationMapper
|
||||
.insertHistoricalResearchOfficeRelations(
|
||||
data.getResearchOffices());
|
||||
requireAffectedRows(
|
||||
relationRows,
|
||||
data.getResearchOffices().size(),
|
||||
"历史教研室隶属关系写入不完整");
|
||||
}
|
||||
|
||||
// 第八步:批量写入部别人员,并保存原有在职和主官状态。
|
||||
if (!data.getPersonnel().isEmpty()) {
|
||||
int personnelRows =
|
||||
systemInitializationMapper
|
||||
.insertHistoricalPersonnel(
|
||||
data.getPersonnel());
|
||||
requireAffectedRows(
|
||||
personnelRows,
|
||||
data.getPersonnel().size(),
|
||||
"历史部别人员数据写入不完整");
|
||||
}
|
||||
|
||||
// 第九步:组装并返回本次事务实际完成的四张表写入数量。
|
||||
return buildHistoricalImportResult(
|
||||
data,
|
||||
importedAt);
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行系统初始化预检查。
|
||||
*
|
||||
* @return 预检查汇总结果
|
||||
*/
|
||||
@Override
|
||||
@Transactional(readOnly = true)
|
||||
public SystemInitializationPrecheckVO precheck() {
|
||||
// 第一步:执行最小数据库查询,验证当前连接和 SQL 执行能力。
|
||||
int databaseHealth =
|
||||
systemInitializationMapper
|
||||
.selectDatabaseHealth();
|
||||
|
||||
// 第二步:查询当前配置和当前学期,允许空值交给预检查项统一说明。
|
||||
SystemInitializationConfigurationVO configuration =
|
||||
systemInitializationMapper
|
||||
.selectCurrentConfiguration();
|
||||
SemesterInitializationVO semester =
|
||||
systemInitializationMapper
|
||||
.selectCurrentSemester();
|
||||
|
||||
// 第三步:统计三类初始化基础组织数据。
|
||||
int departmentCount =
|
||||
systemInitializationMapper.countDepartments();
|
||||
int researchOfficeCount =
|
||||
systemInitializationMapper
|
||||
.countResearchOffices();
|
||||
int personnelCount =
|
||||
systemInitializationMapper.countPersonnel();
|
||||
|
||||
// 第四步:统计部别层级、教研室隶属关系和人员所属部别中的失效引用。
|
||||
int brokenReferenceCount =
|
||||
systemInitializationMapper
|
||||
.countBrokenBaseReferences();
|
||||
|
||||
// 第五步:组装并返回包含全部检查项的统一预检查结果。
|
||||
return buildPrecheck(
|
||||
databaseHealth,
|
||||
configuration,
|
||||
semester,
|
||||
departmentCount,
|
||||
researchOfficeCount,
|
||||
personnelCount,
|
||||
brokenReferenceCount,
|
||||
LocalDateTime.now());
|
||||
}
|
||||
|
||||
/**
|
||||
* 完成系统初始化最终确认。
|
||||
*
|
||||
* @param dto 页面预检查快照和确认标志
|
||||
* @return 初始化执行结果
|
||||
*/
|
||||
@Override
|
||||
@Transactional(readOnly = true)
|
||||
public SystemInitializationExecutionResultVO execute(
|
||||
SystemInitializationExecutionDTO dto) {
|
||||
// 第一步:重新执行完整预检查,不信任页面缓存的检查结果。
|
||||
SystemInitializationPrecheckVO currentPrecheck =
|
||||
precheck();
|
||||
|
||||
/*
|
||||
* 第二步:校验明确确认标志、全部检查项、
|
||||
* 配置版本和当前学期均与页面预检查快照一致。
|
||||
*/
|
||||
validateExecution(dto, currentPrecheck);
|
||||
|
||||
// 第三步:返回最终确认使用的配置版本、学期和完成时间。
|
||||
return buildExecutionResult(
|
||||
currentPrecheck,
|
||||
LocalDateTime.now());
|
||||
}
|
||||
}
|
||||
+380
@@ -0,0 +1,380 @@
|
||||
package com.roomroot.jwgl.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.roomroot.jwgl.entity.JCXX;
|
||||
import com.roomroot.jwgl.mapper.TeachingMaterialMapper;
|
||||
import com.roomroot.jwgl.service.TeachingMaterialService;
|
||||
import com.roomroot.jwgl.unit.PageQuery;
|
||||
import com.roomroot.jwgl.unit.PageResult;
|
||||
import com.roomroot.jwgl.utils.DateUtils;
|
||||
import com.roomroot.jwgl.utils.UuidUtil;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
|
||||
import org.apache.poi.ss.usermodel.*;
|
||||
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import jakarta.annotation.Resource;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.math.BigDecimal;
|
||||
import java.net.URLEncoder;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 教材信息服务实现类
|
||||
*/
|
||||
@Service
|
||||
public class TeachingMaterialServiceImpl implements TeachingMaterialService {
|
||||
|
||||
@Resource
|
||||
private TeachingMaterialMapper teachingMaterialMapper;
|
||||
|
||||
@Override
|
||||
public void add(JCXX jcxx) {
|
||||
String uuid = UuidUtil.getUUID();
|
||||
jcxx.setId(uuid);
|
||||
jcxx.setDelFlag(0);
|
||||
jcxx.setCjsj(LocalDateTime.now());
|
||||
jcxx.setXgsj(LocalDateTime.now());
|
||||
String nextNum = getNextNumber();
|
||||
nextNum = getNextZeroFillCode(nextNum,4);
|
||||
jcxx.setBh(nextNum);
|
||||
teachingMaterialMapper.insert(jcxx);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void delete(String id) {
|
||||
JCXX jcxx = getById(id);
|
||||
jcxx.setDelFlag(1);
|
||||
jcxx.setXgsj(LocalDateTime.now());
|
||||
teachingMaterialMapper.updateById(jcxx);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(JCXX jcxx) {
|
||||
jcxx.setXgsj(LocalDateTime.now());
|
||||
teachingMaterialMapper.updateById(jcxx);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JCXX getByBh(String bh) {
|
||||
LambdaQueryWrapper<JCXX> wrapper = new LambdaQueryWrapper<>();
|
||||
wrapper.eq(JCXX::getBh, bh);
|
||||
return teachingMaterialMapper.selectOne(wrapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JCXX getById(String id) {
|
||||
LambdaQueryWrapper<JCXX> wrapper = new LambdaQueryWrapper<>();
|
||||
wrapper.eq(JCXX::getId, id);
|
||||
return teachingMaterialMapper.selectOne(wrapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PageResult<JCXX> pageList(PageQuery query, JCXX jcxx) {
|
||||
jcxx.setDelFlag(0);
|
||||
Page<JCXX> page = new Page<>(query.getPageNum(), query.getPageSize());
|
||||
Page<JCXX> result = teachingMaterialMapper.selectPageList(page, jcxx);
|
||||
return new PageResult<>(result.getRecords(), result.getTotal(),
|
||||
query.getPageNum(), query.getPageSize());
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<JCXX> list(JCXX jcxx) {
|
||||
LambdaQueryWrapper<JCXX> wrapper = new LambdaQueryWrapper<>();
|
||||
if (jcxx != null) {
|
||||
if (jcxx.getBh() != null && !jcxx.getBh().isEmpty()) {
|
||||
wrapper.like(JCXX::getBh, jcxx.getBh());
|
||||
}
|
||||
if (jcxx.getMc() != null && !jcxx.getMc().isEmpty()) {
|
||||
wrapper.like(JCXX::getMc, jcxx.getMc());
|
||||
}
|
||||
if (jcxx.getIsbn() != null && !jcxx.getIsbn().isEmpty()) {
|
||||
wrapper.like(JCXX::getIsbn, jcxx.getIsbn());
|
||||
}
|
||||
}
|
||||
wrapper.orderByDesc(JCXX::getCjsj);
|
||||
return teachingMaterialMapper.selectList(wrapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int importExcel(MultipartFile file) {
|
||||
try (InputStream is = file.getInputStream();
|
||||
Workbook workbook = file.getOriginalFilename().endsWith(".xlsx")
|
||||
? new XSSFWorkbook(is) : new HSSFWorkbook(is)) {
|
||||
|
||||
// 获取教材信息sheet
|
||||
Sheet sheet = workbook.getSheet("教材信息");
|
||||
if (sheet == null) {
|
||||
sheet = workbook.getSheetAt(0);
|
||||
}
|
||||
int count = 0;
|
||||
|
||||
// 在循环外获取起始编号
|
||||
String nextNum = getNextNumber();
|
||||
|
||||
// 从第二行开始读取数据(跳过表头)
|
||||
for (int i = 1; i <= sheet.getLastRowNum(); i++) {
|
||||
Row row = sheet.getRow(i);
|
||||
if (row == null) continue;
|
||||
|
||||
//获取编号
|
||||
// 跳过空行
|
||||
String bh = getCellValue(row, 0);
|
||||
|
||||
JCXX jcxx = getByBh(bh);
|
||||
String flag = "0";
|
||||
if(jcxx == null){
|
||||
jcxx = new JCXX();
|
||||
jcxx.setId(UuidUtil.getUUID());
|
||||
jcxx.setDelFlag(0);
|
||||
jcxx.setCjsj(LocalDateTime.now());
|
||||
// 生成编号(数字字符串)
|
||||
jcxx.setBh(bh == null?String.valueOf(nextNum):bh);
|
||||
nextNum = getNextZeroFillCode(nextNum,4);
|
||||
flag = "1";
|
||||
}
|
||||
jcxx.setXgsj(LocalDateTime.now());
|
||||
|
||||
// 教研室
|
||||
jcxx.setJysdh(getCellValue(row, 1));
|
||||
|
||||
// 教材代码
|
||||
jcxx.setJcdm(getCellValue(row, 2));
|
||||
|
||||
// 跳过空行
|
||||
String mc = getCellValue(row, 3);
|
||||
if (mc == null || mc.isEmpty()) continue;
|
||||
|
||||
// 名称
|
||||
jcxx.setMc(mc);
|
||||
|
||||
// ISBN
|
||||
jcxx.setIsbn(getCellValue(row, 4));
|
||||
|
||||
// 出版社
|
||||
jcxx.setCbs(getCellValue(row, 5));
|
||||
|
||||
// 版次
|
||||
jcxx.setBc(getCellValue(row, 6));
|
||||
|
||||
// 开本
|
||||
jcxx.setKb(getCellValue(row, 7));
|
||||
|
||||
// 作者
|
||||
//主编
|
||||
String zb = getCellValue(row, 8) == null ? "" : getCellValue(row, 8);
|
||||
//副主编
|
||||
String fzb = getCellValue(row, 9) == null ? "" : getCellValue(row, 9);
|
||||
//编者
|
||||
String bz = getCellValue(row, 10)==null?"":getCellValue(row, 10);
|
||||
|
||||
|
||||
jcxx.setZz(zb+" "+fzb+" "+bz);
|
||||
|
||||
// 定价
|
||||
String djStr = getCellValue(row, 11);
|
||||
if (djStr != null && !djStr.isEmpty()) {
|
||||
try {
|
||||
jcxx.setDj(new BigDecimal(djStr));
|
||||
} catch (NumberFormatException e) {
|
||||
jcxx.setDj(BigDecimal.ZERO);
|
||||
}
|
||||
}
|
||||
|
||||
// 教材分类
|
||||
jcxx.setJcfl(getCellValue(row, 12));
|
||||
|
||||
// 教材类型
|
||||
jcxx.setJclx(getCellValue(row, 13));
|
||||
|
||||
// 教材编写类型
|
||||
jcxx.setJcbxlx(getCellValue(row, 14));
|
||||
|
||||
//教材编写类型
|
||||
jcxx.setJcbxlx(getCellValue(row, 15)==null?"":getCellValue(row, 15));
|
||||
//教材密级
|
||||
jcxx.setJcmj(getCellValue(row, 16)==null?"":getCellValue(row, 16));
|
||||
|
||||
//编写单位
|
||||
jcxx.setBxdw(getCellValue(row, 17)==null?"":getCellValue(row, 17));
|
||||
|
||||
//责任教研室
|
||||
jcxx.setZrjyjlxff(getCellValue(row, 18)==null?"":getCellValue(row, 18));
|
||||
//教材重点类型
|
||||
jcxx.setJczdlx(getCellValue(row, 19)==null?"":getCellValue(row, 19));
|
||||
//教材层次
|
||||
jcxx.setJccc(getCellValue(row, 20)==null?"":getCellValue(row, 20));
|
||||
//教材来源
|
||||
jcxx.setJcly(getCellValue(row, 21)==null?"":getCellValue(row, 21));
|
||||
//出版方式
|
||||
jcxx.setCbfs(getCellValue(row, 22)==null?"":getCellValue(row, 22));
|
||||
//计量单位
|
||||
jcxx.setJldw(getCellValue(row, 23)==null?"":getCellValue(row, 23));
|
||||
//出版日期
|
||||
String dateStr = getCellValue(row, 24)==null?"":getCellValue(row, 24);
|
||||
LocalDateTime cbrq = DateUtils.parseAnyDate(dateStr);
|
||||
jcxx.setCbrq(cbrq);
|
||||
//自编教材立项日期
|
||||
jcxx.setJcmj(getCellValue(row, 25)==null?"":getCellValue(row, 25));
|
||||
//评选情况
|
||||
jcxx.setJcmj(getCellValue(row, 26)==null?"":getCellValue(row, 26));
|
||||
//颁发审定单位
|
||||
jcxx.setJcmj(getCellValue(row, 27)==null?"":getCellValue(row, 27));
|
||||
//责任教员及联系方式
|
||||
jcxx.setJcmj(getCellValue(row, 28)==null?"":getCellValue(row, 28));
|
||||
//需彩印
|
||||
jcxx.setJcmj(getCellValue(row, 29)==null?"":getCellValue(row, 29));
|
||||
//外协排版
|
||||
jcxx.setJcmj(getCellValue(row, 30)==null?"":getCellValue(row, 30));
|
||||
//备注
|
||||
jcxx.setJcmj(getCellValue(row, 31)==null?"":getCellValue(row, 31));
|
||||
//停用
|
||||
jcxx.setTy(false);
|
||||
jcxx.setXcy(false);
|
||||
|
||||
if("1".equals(flag)){
|
||||
teachingMaterialMapper.insert(jcxx);
|
||||
}else if("0".equals(flag)){
|
||||
teachingMaterialMapper.updateById(jcxx);
|
||||
}
|
||||
count++;
|
||||
}
|
||||
return count;
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("Excel解析失败: " + e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void downloadTemplate(HttpServletResponse response) {
|
||||
try {
|
||||
// 从resources/template目录读取模板文件
|
||||
ClassPathResource resource = new ClassPathResource("template/教材管理.xls");
|
||||
InputStream is = resource.getInputStream();
|
||||
|
||||
// 设置响应头
|
||||
response.setContentType("application/vnd.ms-excel");
|
||||
response.setHeader("Content-Disposition", "attachment;filename=" +
|
||||
URLEncoder.encode("教材管理导入模板.xls", "UTF-8"));
|
||||
|
||||
// 输出文件
|
||||
OutputStream os = response.getOutputStream();
|
||||
byte[] buffer = new byte[1024];
|
||||
int len;
|
||||
while ((len = is.read(buffer)) != -1) {
|
||||
os.write(buffer, 0, len);
|
||||
}
|
||||
os.flush();
|
||||
is.close();
|
||||
os.close();
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("下载模板失败: " + e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取下一个编号(四位补零)
|
||||
*/
|
||||
private String getNextNumber() {
|
||||
String maxBh = teachingMaterialMapper.selectMaxBh();
|
||||
String nextNum = "0001";
|
||||
if (maxBh != null && !maxBh.isEmpty()) {
|
||||
try {
|
||||
// 去掉前导零后解析
|
||||
nextNum = maxBh;
|
||||
} catch (NumberFormatException e) {
|
||||
nextNum = "0001";
|
||||
}
|
||||
}
|
||||
return nextNum;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据数据库最大补零编号,生成下一个编号
|
||||
* @param maxZeroCode 数据库查出的最大补零编号,为空则从00001开始
|
||||
* @param length 固定补零长度,例:5=00001
|
||||
* @return 下一个补零字符串编号
|
||||
*/
|
||||
public static String getNextZeroFillCode(String maxZeroCode, int length) {
|
||||
int num = 1;
|
||||
// 数据库有编号则解析+1
|
||||
if (maxZeroCode != null && maxZeroCode.trim().length() > 0) {
|
||||
num = Integer.parseInt(maxZeroCode.trim()) + 1;
|
||||
}
|
||||
// 格式化补零
|
||||
String format = "%0" + length + "d";
|
||||
return String.format(format, num);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取单元格字符串值
|
||||
*/
|
||||
private String getCellValue(Row row, int index) {
|
||||
Cell cell = row.getCell(index, Row.MissingCellPolicy.CREATE_NULL_AS_BLANK);
|
||||
if (cell == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
CellType type = cell.getCellType();
|
||||
// 处理公式单元格
|
||||
if (type == CellType.FORMULA) {
|
||||
type = cell.getCachedFormulaResultType();
|
||||
}
|
||||
|
||||
switch (type) {
|
||||
case NUMERIC:
|
||||
// 判断是否是日期格式
|
||||
if (DateUtil.isCellDateFormatted(cell)) {
|
||||
java.util.Date date = cell.getDateCellValue();
|
||||
if (date != null) {
|
||||
java.text.SimpleDateFormat sdf = new java.text.SimpleDateFormat("yyyy/MM/dd");
|
||||
return sdf.format(date);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
double num = cell.getNumericCellValue();
|
||||
// 整数就去掉小数点后多余的 .0
|
||||
if (num == Math.floor(num)) {
|
||||
return String.valueOf((long) num);
|
||||
} else {
|
||||
return String.valueOf(num);
|
||||
}
|
||||
case STRING:
|
||||
return cell.getStringCellValue().trim();
|
||||
case BOOLEAN:
|
||||
return String.valueOf(cell.getBooleanCellValue());
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析日期时间字符串
|
||||
*/
|
||||
private LocalDateTime parseDateTime(String dateStr) {
|
||||
// 尝试多种日期格式
|
||||
String[] patterns = {
|
||||
"yyyy-MM-dd HH:mm:ss",
|
||||
"yyyy-MM-dd",
|
||||
"yyyy/MM/dd",
|
||||
"yyyy年MM月dd日"
|
||||
};
|
||||
for (String pattern : patterns) {
|
||||
try {
|
||||
DateTimeFormatter formatter = DateTimeFormatter.ofPattern(pattern);
|
||||
return LocalDateTime.parse(dateStr, formatter);
|
||||
} catch (Exception e) {
|
||||
// 继续尝试下一个格式
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
+107
@@ -0,0 +1,107 @@
|
||||
package com.roomroot.jwgl.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.roomroot.jwgl.entity.JXSSJH;
|
||||
import com.roomroot.jwgl.mapper.TeachingPlanMapper;
|
||||
import com.roomroot.jwgl.service.TeachingPlanService;
|
||||
import com.roomroot.jwgl.unit.BusinessException;
|
||||
import com.roomroot.jwgl.unit.PageQuery;
|
||||
import com.roomroot.jwgl.unit.PageResult;
|
||||
import com.roomroot.jwgl.utils.ExcelParseUtil;
|
||||
import com.roomroot.jwgl.utils.UuidUtil;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 导入数据表-教学实施计划服务实现类
|
||||
*/
|
||||
@Service
|
||||
public class TeachingPlanServiceImpl implements TeachingPlanService {
|
||||
|
||||
@Resource
|
||||
private TeachingPlanMapper teachingPlanMapper;
|
||||
|
||||
@Override
|
||||
public void add(JXSSJH drsjbjxssjh) {
|
||||
String uuid = UuidUtil.getUUID();
|
||||
drsjbjxssjh.setBsh(uuid);
|
||||
drsjbjxssjh.setDelFlag(0);
|
||||
teachingPlanMapper.insert(drsjbjxssjh);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void delete(String bsh) {
|
||||
JXSSJH drsjbjxssjh = getByBsh(bsh);
|
||||
drsjbjxssjh.setDelFlag(1);
|
||||
teachingPlanMapper.updateById(drsjbjxssjh);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(JXSSJH drsjbjxssjh) {
|
||||
teachingPlanMapper.updateById(drsjbjxssjh);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JXSSJH getByBsh(String bsh) {
|
||||
return teachingPlanMapper.selectById(bsh);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PageResult<JXSSJH> pageList(PageQuery query, JXSSJH drsjbjxssjh) {
|
||||
drsjbjxssjh.setDelFlag(0);
|
||||
Page<JXSSJH> page = new Page<>(query.getPageNum(), query.getPageSize());
|
||||
Page<JXSSJH> result = teachingPlanMapper.selectPageList(page, drsjbjxssjh);
|
||||
return new PageResult<>(result.getRecords(), result.getTotal(),
|
||||
query.getPageNum(), query.getPageSize());
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<JXSSJH> list(JXSSJH drsjbjxssjh) {
|
||||
LambdaQueryWrapper<JXSSJH> wrapper = new LambdaQueryWrapper<>();
|
||||
if (drsjbjxssjh != null) {
|
||||
if (drsjbjxssjh.getNd() != null) {
|
||||
wrapper.eq(JXSSJH::getNd, drsjbjxssjh.getNd());
|
||||
}
|
||||
if (drsjbjxssjh.getKcmc() != null && !drsjbjxssjh.getKcmc().isEmpty()) {
|
||||
wrapper.like(JXSSJH::getKcmc, drsjbjxssjh.getKcmc());
|
||||
}
|
||||
if (drsjbjxssjh.getYtgjc() != null) {
|
||||
wrapper.eq(JXSSJH::getYtgjc, drsjbjxssjh.getYtgjc());
|
||||
}
|
||||
}
|
||||
wrapper.orderByAsc(JXSSJH::getXh);
|
||||
return teachingPlanMapper.selectList(wrapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public int importFromExcel(MultipartFile file) throws Exception {
|
||||
if (file == null || file.isEmpty()) {
|
||||
throw new BusinessException("导入文件不能为空");
|
||||
}
|
||||
List<JXSSJH> list = ExcelParseUtil.parseJXSSJHExcel(
|
||||
file.getInputStream(), file.getOriginalFilename());
|
||||
if (list.isEmpty()) {
|
||||
throw new BusinessException("Excel中无有效数据");
|
||||
}
|
||||
for (JXSSJH entity : list) {
|
||||
// 标识号自动生成
|
||||
entity.setBsh(UuidUtil.getUUID());
|
||||
// 登录编号自动生成
|
||||
entity.setDlbh(UuidUtil.getUUID());
|
||||
// 默认值
|
||||
entity.setYtgjc(false);
|
||||
entity.setYbhl(false);
|
||||
entity.setYbdr(false);
|
||||
entity.setYbcl(false);
|
||||
entity.setDelFlag(0);
|
||||
teachingPlanMapper.insert(entity);
|
||||
}
|
||||
return list.size();
|
||||
}
|
||||
}
|
||||
+106
@@ -0,0 +1,106 @@
|
||||
package com.roomroot.jwgl.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.roomroot.jwgl.entity.JCKCMXX;
|
||||
import com.roomroot.jwgl.mapper.TeachingStockDetailMapper;
|
||||
import com.roomroot.jwgl.service.TeachingStockDetailService;
|
||||
import com.roomroot.jwgl.unit.PageQuery;
|
||||
import com.roomroot.jwgl.unit.PageResult;
|
||||
import com.roomroot.jwgl.utils.UuidUtil;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import jakarta.annotation.Resource;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 教材库存明细项服务实现类
|
||||
*/
|
||||
@Service
|
||||
public class TeachingStockDetailServiceImpl implements TeachingStockDetailService {
|
||||
|
||||
@Resource
|
||||
private TeachingStockDetailMapper teachingStockDetailMapper;
|
||||
|
||||
@Override
|
||||
public void add(JCKCMXX jckcmxx) {
|
||||
String uuid = UuidUtil.getUUID();
|
||||
jckcmxx.setId(uuid);
|
||||
jckcmxx.setDelFlag(0);
|
||||
// 生成编号(四位补零)
|
||||
jckcmxx.setBh(getNextNumber());
|
||||
teachingStockDetailMapper.insert(jckcmxx);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void delete(String id) {
|
||||
JCKCMXX jckcmxx = getById(id);
|
||||
jckcmxx.setDelFlag(1);
|
||||
teachingStockDetailMapper.updateById(jckcmxx);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(JCKCMXX jckcmxx) {
|
||||
teachingStockDetailMapper.updateById(jckcmxx);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JCKCMXX getById(String id) {
|
||||
return teachingStockDetailMapper.selectById(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JCKCMXX getByBh(String bh) {
|
||||
LambdaQueryWrapper<JCKCMXX> wrapper = new LambdaQueryWrapper<>();
|
||||
wrapper.eq(JCKCMXX::getBh, bh);
|
||||
return teachingStockDetailMapper.selectOne(wrapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<JCKCMXX> getByJckcdbbh(String jckcdbbh) {
|
||||
return teachingStockDetailMapper.selectByJckcdbbh(jckcdbbh);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PageResult<JCKCMXX> pageList(PageQuery query, JCKCMXX jckcmxx) {
|
||||
jckcmxx.setDelFlag(0);
|
||||
Page<JCKCMXX> page = new Page<>(query.getPageNum(), query.getPageSize());
|
||||
Page<JCKCMXX> result = teachingStockDetailMapper.selectPageList(page, jckcmxx);
|
||||
return new PageResult<>(result.getRecords(), result.getTotal(),
|
||||
query.getPageNum(), query.getPageSize());
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<JCKCMXX> list(JCKCMXX jckcmxx) {
|
||||
LambdaQueryWrapper<JCKCMXX> wrapper = new LambdaQueryWrapper<>();
|
||||
if (jckcmxx != null) {
|
||||
if (jckcmxx.getBh() != null && !jckcmxx.getBh().isEmpty()) {
|
||||
wrapper.like(JCKCMXX::getBh, jckcmxx.getBh());
|
||||
}
|
||||
if (jckcmxx.getJckcdbbh() != null && !jckcmxx.getJckcdbbh().isEmpty()) {
|
||||
wrapper.eq(JCKCMXX::getJckcdbbh, jckcmxx.getJckcdbbh());
|
||||
}
|
||||
if (jckcmxx.getJcxxbh() != null && !jckcmxx.getJcxxbh().isEmpty()) {
|
||||
wrapper.like(JCKCMXX::getJcxxbh, jckcmxx.getJcxxbh());
|
||||
}
|
||||
}
|
||||
return teachingStockDetailMapper.selectList(wrapper);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取下一个编号(四位补零)
|
||||
*/
|
||||
private String getNextNumber() {
|
||||
String maxBh = teachingStockDetailMapper.selectMaxBh();
|
||||
int nextNum = 1;
|
||||
if (maxBh != null && !maxBh.isEmpty()) {
|
||||
try {
|
||||
// 去掉前导零后解析
|
||||
nextNum = Integer.parseInt(maxBh) + 1;
|
||||
} catch (NumberFormatException e) {
|
||||
nextNum = 1;
|
||||
}
|
||||
}
|
||||
return String.format("%04d", nextNum);
|
||||
}
|
||||
}
|
||||
+110
@@ -0,0 +1,110 @@
|
||||
package com.roomroot.jwgl.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.roomroot.jwgl.entity.JCKCD;
|
||||
import com.roomroot.jwgl.mapper.TeachingStockMapper;
|
||||
import com.roomroot.jwgl.service.TeachingStockService;
|
||||
import com.roomroot.jwgl.unit.PageQuery;
|
||||
import com.roomroot.jwgl.unit.PageResult;
|
||||
import com.roomroot.jwgl.utils.UuidUtil;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import jakarta.annotation.Resource;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 教材库存单服务实现类
|
||||
*/
|
||||
@Service
|
||||
public class TeachingStockServiceImpl implements TeachingStockService {
|
||||
|
||||
@Resource
|
||||
private TeachingStockMapper teachingStockMapper;
|
||||
|
||||
@Override
|
||||
public void add(JCKCD jckcd) {
|
||||
String uuid = UuidUtil.getUUID();
|
||||
jckcd.setId(uuid);
|
||||
jckcd.setDelFlag(0);
|
||||
jckcd.setCjsj(LocalDateTime.now());
|
||||
jckcd.setXgsj(LocalDateTime.now());
|
||||
// 生成编号(四位补零)
|
||||
jckcd.setBh(getNextNumber());
|
||||
teachingStockMapper.insert(jckcd);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void delete(String id) {
|
||||
JCKCD jckcd = getById(id);
|
||||
jckcd.setDelFlag(1);
|
||||
jckcd.setXgsj(LocalDateTime.now());
|
||||
teachingStockMapper.updateById(jckcd);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(JCKCD jckcd) {
|
||||
jckcd.setXgsj(LocalDateTime.now());
|
||||
teachingStockMapper.updateById(jckcd);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JCKCD getById(String id) {
|
||||
return teachingStockMapper.selectById(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JCKCD getByBh(String bh) {
|
||||
LambdaQueryWrapper<JCKCD> wrapper = new LambdaQueryWrapper<>();
|
||||
wrapper.eq(JCKCD::getBh, bh);
|
||||
return teachingStockMapper.selectOne(wrapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PageResult<JCKCD> pageList(PageQuery query, JCKCD jckcd) {
|
||||
jckcd.setDelFlag(0);
|
||||
Page<JCKCD> page = new Page<>(query.getPageNum(), query.getPageSize());
|
||||
Page<JCKCD> result = teachingStockMapper.selectPageList(page, jckcd);
|
||||
return new PageResult<>(result.getRecords(), result.getTotal(),
|
||||
query.getPageNum(), query.getPageSize());
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<JCKCD> list(JCKCD jckcd) {
|
||||
LambdaQueryWrapper<JCKCD> wrapper = new LambdaQueryWrapper<>();
|
||||
if (jckcd != null) {
|
||||
if (jckcd.getBh() != null && !jckcd.getBh().isEmpty()) {
|
||||
wrapper.like(JCKCD::getBh, jckcd.getBh());
|
||||
}
|
||||
if (jckcd.getMc() != null && !jckcd.getMc().isEmpty()) {
|
||||
wrapper.like(JCKCD::getMc, jckcd.getMc());
|
||||
}
|
||||
if (jckcd.getLb() != null && !jckcd.getLb().isEmpty()) {
|
||||
wrapper.eq(JCKCD::getLb, jckcd.getLb());
|
||||
}
|
||||
if (jckcd.getZt() != null && !jckcd.getZt().isEmpty()) {
|
||||
wrapper.eq(JCKCD::getZt, jckcd.getZt());
|
||||
}
|
||||
}
|
||||
wrapper.orderByDesc(JCKCD::getCjsj);
|
||||
return teachingStockMapper.selectList(wrapper);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取下一个编号(四位补零)
|
||||
*/
|
||||
private String getNextNumber() {
|
||||
String maxBh = teachingStockMapper.selectMaxBh();
|
||||
int nextNum = 1;
|
||||
if (maxBh != null && !maxBh.isEmpty()) {
|
||||
try {
|
||||
// 去掉前导零后解析
|
||||
nextNum = Integer.parseInt(maxBh) + 1;
|
||||
} catch (NumberFormatException e) {
|
||||
nextNum = 1;
|
||||
}
|
||||
}
|
||||
return String.format("%04d", nextNum);
|
||||
}
|
||||
}
|
||||
+128
@@ -0,0 +1,128 @@
|
||||
package com.roomroot.jwgl.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.roomroot.jwgl.entity.JXRW;
|
||||
import com.roomroot.jwgl.entity.JYSRWS;
|
||||
import com.roomroot.jwgl.mapper.TeachingTaskMapper;
|
||||
import com.roomroot.jwgl.mapper.OfficeTaskBookMapper;
|
||||
import com.roomroot.jwgl.service.TeachingTaskService;
|
||||
import com.roomroot.jwgl.unit.PageQuery;
|
||||
import com.roomroot.jwgl.unit.PageResult;
|
||||
import com.roomroot.jwgl.utils.UuidUtil;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import jakarta.annotation.Resource;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 教学任务服务实现类
|
||||
*/
|
||||
@Service
|
||||
public class TeachingTaskServiceImpl implements TeachingTaskService {
|
||||
|
||||
@Resource
|
||||
private TeachingTaskMapper teachingTaskMapper;
|
||||
|
||||
@Resource
|
||||
private OfficeTaskBookMapper officeTaskBookMapper;
|
||||
|
||||
@Override
|
||||
public void add(JXRW jxrw) {
|
||||
String uuid = UuidUtil.getUUID();
|
||||
jxrw.setBh(uuid);
|
||||
jxrw.setDelFlag(0);
|
||||
// 状态默认为未发布
|
||||
jxrw.setZt("上报");
|
||||
// 自动填充创建时间
|
||||
java.time.LocalDateTime now = java.time.LocalDateTime.now();
|
||||
jxrw.setCjsj(now); // 创建时间
|
||||
teachingTaskMapper.insert(jxrw);
|
||||
}
|
||||
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
@Override
|
||||
public void delete(String bh) {
|
||||
JXRW jxrw = getByBh(bh);
|
||||
if (jxrw != null) {
|
||||
jxrw.setDelFlag(1);
|
||||
teachingTaskMapper.updateById(jxrw);
|
||||
|
||||
// 同时删除对应的教研室任务书(教学任务编号 = 教学任务编号)
|
||||
LambdaQueryWrapper<JYSRWS> wrapper = new LambdaQueryWrapper<>();
|
||||
wrapper.eq(JYSRWS::getJxrwbh, bh);
|
||||
List<JYSRWS> jysrwsList = officeTaskBookMapper.selectList(wrapper);
|
||||
for (JYSRWS jysrws : jysrwsList) {
|
||||
jysrws.setDelFlag(1);
|
||||
officeTaskBookMapper.updateById(jysrws);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void batchDelete(List<String> bhList) {
|
||||
for (String bh : bhList) {
|
||||
delete(bh);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(JXRW jxrw) {
|
||||
teachingTaskMapper.updateById(jxrw);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JXRW getByBh(String bh) {
|
||||
return teachingTaskMapper.selectById(bh);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PageResult<JXRW> pageList(PageQuery query, JXRW jxrw) {
|
||||
jxrw.setDelFlag(0);
|
||||
Page<JXRW> page = new Page<>(query.getPageNum(), query.getPageSize());
|
||||
Page<JXRW> result = teachingTaskMapper.selectPageList(page, jxrw);
|
||||
return new PageResult<>(result.getRecords(), result.getTotal(),
|
||||
query.getPageNum(), query.getPageSize());
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<JXRW> listAllValid() {
|
||||
return teachingTaskMapper.selectList(
|
||||
new com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper<JXRW>()
|
||||
.eq(JXRW::getDelFlag, 0)
|
||||
);
|
||||
}
|
||||
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
@Override
|
||||
public int batchPublish(String bh) {
|
||||
if (bh == null || bh.isEmpty()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
JXRW jxrw = teachingTaskMapper.selectById(bh);
|
||||
if (jxrw == null || jxrw.getDelFlag() != 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// 更新教学任务状态为"发布"
|
||||
jxrw.setZt("发布");
|
||||
teachingTaskMapper.updateById(jxrw);
|
||||
|
||||
// 批量更新教研室任务书状态为"发布"
|
||||
LambdaQueryWrapper<JYSRWS> wrapper = new LambdaQueryWrapper<>();
|
||||
wrapper.eq(JYSRWS::getJxrwbh, bh)
|
||||
.eq(JYSRWS::getDelFlag, 0);
|
||||
List<JYSRWS> jysrwsList = officeTaskBookMapper.selectList(wrapper);
|
||||
|
||||
int count = 0;
|
||||
for (JYSRWS jysrws : jysrwsList) {
|
||||
jysrws.setZt("发布");
|
||||
officeTaskBookMapper.updateById(jysrws);
|
||||
count++;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
}
|
||||
+69
@@ -0,0 +1,69 @@
|
||||
package com.roomroot.jwgl.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.roomroot.jwgl.entity.ZYB;
|
||||
import com.roomroot.jwgl.mapper.ZYBMapper;
|
||||
import com.roomroot.jwgl.service.TrainingProgramService;
|
||||
import com.roomroot.jwgl.unit.PageQuery;
|
||||
import com.roomroot.jwgl.unit.PageResult;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import jakarta.annotation.Resource;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* 培养方案管理服务实现类
|
||||
* <p>
|
||||
* 实现专业/培养方案的增加、删除(逻辑删除)、更新、分页查询等功能。
|
||||
* 逻辑删除将 停用 字段置为 true(停用=false为启用,停用=true为已停用/删除)。
|
||||
* 多版本通过培训类型(培训类型)字段区分。
|
||||
* </p>
|
||||
*/
|
||||
@Service
|
||||
public class TrainingProgramServiceImpl implements TrainingProgramService {
|
||||
|
||||
@Resource
|
||||
private ZYBMapper zybMapper;
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public void add(ZYB entity) {
|
||||
entity.setTy(false);
|
||||
entity.setQysj(LocalDateTime.now());
|
||||
zybMapper.insert(entity);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public void disable(String zydh) {
|
||||
ZYB entity = new ZYB();
|
||||
entity.setZydh(zydh);
|
||||
entity.setTy(true);
|
||||
entity.setTysj(LocalDateTime.now());
|
||||
zybMapper.updateById(entity);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public void update(ZYB entity) {
|
||||
zybMapper.updateById(entity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ZYB getById(String zydh) {
|
||||
LambdaQueryWrapper<ZYB> wrapper = new LambdaQueryWrapper<>();
|
||||
wrapper.eq(ZYB::getZydh, zydh)
|
||||
.eq(ZYB::getTy, false);
|
||||
return zybMapper.selectOne(wrapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PageResult<ZYB> pageList(PageQuery query, ZYB cond) {
|
||||
Page<ZYB> page = new Page<>(query.getPageNum(), query.getPageSize());
|
||||
Page<ZYB> result = zybMapper.selectPageList(page, cond);
|
||||
return new PageResult<>(result.getRecords(), result.getTotal(),
|
||||
query.getPageNum(), query.getPageSize());
|
||||
}
|
||||
}
|
||||
+74
@@ -0,0 +1,74 @@
|
||||
package com.roomroot.jwgl.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
|
||||
import com.roomroot.jwgl.entity.ZYJXJHB;
|
||||
import com.roomroot.jwgl.mapper.ZYJXJHBMapper;
|
||||
import com.roomroot.jwgl.service.ZYJXJHBService;
|
||||
import com.roomroot.jwgl.utils.UuidUtil;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import jakarta.annotation.Resource;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 专业教学计划表服务实现
|
||||
*/
|
||||
@Service
|
||||
public class ZYJXJHBServiceImpl implements ZYJXJHBService {
|
||||
|
||||
@Resource
|
||||
private ZYJXJHBMapper zyjxjhbMapper;
|
||||
|
||||
@Override
|
||||
public void add(ZYJXJHB zyjxjhb) {
|
||||
zyjxjhb.setBh(UuidUtil.getUUID());
|
||||
if (zyjxjhb.getTy() == null) {
|
||||
zyjxjhb.setTy(0);
|
||||
}
|
||||
if (zyjxjhb.getQysj() == null) {
|
||||
zyjxjhb.setQysj(LocalDateTime.now());
|
||||
}
|
||||
zyjxjhbMapper.insert(zyjxjhb);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void delete(String bh) {
|
||||
LambdaUpdateWrapper<ZYJXJHB> wrapper = new LambdaUpdateWrapper<>();
|
||||
wrapper.eq(ZYJXJHB::getBh, bh)
|
||||
.set(ZYJXJHB::getTy, 1)
|
||||
.set(ZYJXJHB::getTysj, LocalDateTime.now());
|
||||
zyjxjhbMapper.update(null, wrapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void batchDelete(List<String> bhList) {
|
||||
for (String bh : bhList) {
|
||||
delete(bh);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(ZYJXJHB zyjxjhb) {
|
||||
zyjxjhbMapper.updateById(zyjxjhb);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ZYJXJHB getByBh(String bh) {
|
||||
return zyjxjhbMapper.selectById(bh);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ZYJXJHB> list() {
|
||||
return zyjxjhbMapper.selectList(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ZYJXJHB> listByZydhAndTy(String zydh, Integer ty) {
|
||||
LambdaQueryWrapper<ZYJXJHB> wrapper = new LambdaQueryWrapper<>();
|
||||
wrapper.eq(ZYJXJHB::getZydh, zydh)
|
||||
.eq(ZYJXJHB::getTy, ty);
|
||||
return zyjxjhbMapper.selectList(wrapper);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user