diff --git a/.gitignore b/.gitignore index 03ef4a45..560ce1c2 100644 --- a/.gitignore +++ b/.gitignore @@ -328,3 +328,4 @@ docs/部署文档/nginx配置/hzdyjsweb.camasort.com.conf 首页完善的提示词.md scripts/ 学生宿舍卫生检查、学生违纪记录统计.md +学生调宿、退宿功能.md \ No newline at end of file diff --git a/backend/ruoyi-modules/ruoyi-xg/src/main/java/org/dromara/xg/controller/XgDormApplicationController.java b/backend/ruoyi-modules/ruoyi-xg/src/main/java/org/dromara/xg/controller/XgDormApplicationController.java new file mode 100644 index 00000000..2b90f3e7 --- /dev/null +++ b/backend/ruoyi-modules/ruoyi-xg/src/main/java/org/dromara/xg/controller/XgDormApplicationController.java @@ -0,0 +1,116 @@ +package org.dromara.xg.controller; + +import java.util.List; + +import lombok.RequiredArgsConstructor; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.validation.constraints.*; +import cn.dev33.satoken.annotation.SaCheckPermission; +import org.springframework.web.bind.annotation.*; +import org.springframework.validation.annotation.Validated; +import org.dromara.common.idempotent.annotation.RepeatSubmit; +import org.dromara.common.log.annotation.Log; +import org.dromara.common.web.core.BaseController; +import org.dromara.common.mybatis.core.page.PageQuery; +import org.dromara.common.core.domain.R; +import org.dromara.common.core.validate.AddGroup; +import org.dromara.common.core.validate.EditGroup; +import org.dromara.common.log.enums.BusinessType; +import org.dromara.common.excel.utils.ExcelUtil; +import org.dromara.xg.domain.vo.XgDormApplicationVo; +import org.dromara.xg.domain.bo.XgDormApplicationBo; +import org.dromara.xg.domain.vo.StudentOptionVo; +import org.dromara.xg.domain.bo.StudentOptionBo; +import org.dromara.xg.service.IXgDormApplicationService; +import org.dromara.common.mybatis.core.page.TableDataInfo; + +/** + * 学生宿舍申请单表(调宿+退宿) + * + * @author zlwu + * @date 2025-01-15 + */ +@Validated +@RequiredArgsConstructor +@RestController +@RequestMapping("/dormApplication/dormApplication") +public class XgDormApplicationController extends BaseController { + + private final IXgDormApplicationService xgDormApplicationService; + + /** + * 查询学生宿舍申请单表(调宿+退宿)列表 + */ + @SaCheckPermission("dormApplication:dormApplication:list") + @GetMapping("/list") + public TableDataInfo list(XgDormApplicationBo bo, PageQuery pageQuery) { + return xgDormApplicationService.queryPageList(bo, pageQuery); + } + + /** + * 获取学生选择器选项列表(支持按学号、姓名检索) + */ + @SaCheckPermission("dormApplication:dormApplication:list") + @GetMapping("/studentOptions") + public TableDataInfo getStudentOptions(StudentOptionBo bo, PageQuery pageQuery) { + return xgDormApplicationService.getStudentOptions(bo, pageQuery); + } + + /** + * 导出学生宿舍申请单表(调宿+退宿)列表 + */ + @SaCheckPermission("dormApplication:dormApplication:export") + @Log(title = "学生宿舍申请单表(调宿+退宿)", businessType = BusinessType.EXPORT) + @PostMapping("/export") + public void export(XgDormApplicationBo bo, HttpServletResponse response) { + List list = xgDormApplicationService.queryList(bo); + ExcelUtil.exportExcel(list, "学生宿舍申请单表(调宿+退宿)", XgDormApplicationVo.class, response); + } + + /** + * 获取学生宿舍申请单表(调宿+退宿)详细信息 + * + * @param id 主键 + */ + @SaCheckPermission("dormApplication:dormApplication:query") + @GetMapping("/{id}") + public R getInfo(@NotNull(message = "主键不能为空") @PathVariable Long id) { + return R.ok(xgDormApplicationService.queryById(id)); + } + + /** + * 新增学生宿舍申请单表(调宿+退宿) + */ + @SaCheckPermission("dormApplication:dormApplication:add") + @Log(title = "学生宿舍申请单表(调宿+退宿)", businessType = BusinessType.INSERT) + @RepeatSubmit() + @PostMapping() + public R add(@Validated(AddGroup.class) @RequestBody XgDormApplicationBo bo) { + XgDormApplicationVo result = xgDormApplicationService.insertByBo(bo); + return R.ok(result); + } + + /** + * 修改学生宿舍申请单表(调宿+退宿) + */ + @SaCheckPermission("dormApplication:dormApplication:edit") + @Log(title = "学生宿舍申请单表(调宿+退宿)", businessType = BusinessType.UPDATE) + @RepeatSubmit() + @PutMapping() + public R edit(@Validated(EditGroup.class) @RequestBody XgDormApplicationBo bo) { + return toAjax(xgDormApplicationService.updateByBo(bo)); + } + + /** + * 删除学生宿舍申请单表(调宿+退宿) + * + * @param ids 主键串 + */ + @SaCheckPermission("dormApplication:dormApplication:remove") + @Log(title = "学生宿舍申请单表(调宿+退宿)", businessType = BusinessType.DELETE) + @DeleteMapping("/{ids}") + public R remove(@NotEmpty(message = "主键不能为空") @PathVariable Long[] ids) { + return toAjax(xgDormApplicationService.deleteWithValidByIds(List.of(ids), true)); + } + +} diff --git a/backend/ruoyi-modules/ruoyi-xg/src/main/java/org/dromara/xg/controller/XgDormBedStudentController.java b/backend/ruoyi-modules/ruoyi-xg/src/main/java/org/dromara/xg/controller/XgDormBedStudentController.java index 2c02ae9f..d2b75526 100644 --- a/backend/ruoyi-modules/ruoyi-xg/src/main/java/org/dromara/xg/controller/XgDormBedStudentController.java +++ b/backend/ruoyi-modules/ruoyi-xg/src/main/java/org/dromara/xg/controller/XgDormBedStudentController.java @@ -332,4 +332,15 @@ public class XgDormBedStudentController extends BaseController { return R.ok(roomStudents); } + /** + * 根据学生ID获取当前宿舍信息 + * 包含校区、宿舍楼、房间号、床位号等信息 + */ + @SaCheckPermission("dormBedStudent:dormBedStudent:list") + @GetMapping("/currentDormInfo/{studentId}") + public R getCurrentDormInfo(@NotNull(message = "学生ID不能为空") @PathVariable Long studentId) { + Object currentDormInfo = xgDormBedStudentService.getCurrentDormInfo(studentId); + return R.ok(currentDormInfo); + } + } diff --git a/backend/ruoyi-modules/ruoyi-xg/src/main/java/org/dromara/xg/domain/XgDormApplication.java b/backend/ruoyi-modules/ruoyi-xg/src/main/java/org/dromara/xg/domain/XgDormApplication.java new file mode 100644 index 00000000..8976421c --- /dev/null +++ b/backend/ruoyi-modules/ruoyi-xg/src/main/java/org/dromara/xg/domain/XgDormApplication.java @@ -0,0 +1,216 @@ +package org.dromara.xg.domain; + +import org.dromara.common.mybatis.core.domain.BaseEntity; +import com.baomidou.mybatisplus.annotation.*; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.util.Date; + +/** + * 学生宿舍申请单表(调宿+退宿)对象 xg_dorm_application + * + * @author zlwu + * @date 2025-01-15 + */ +@Data +@EqualsAndHashCode(callSuper = true) +@TableName("xg_dorm_application") +public class XgDormApplication extends BaseEntity { + + private static final long serialVersionUID = 1L; + + /** + * 主键ID(雪花ID) + */ + @TableId(value = "id") + private Long id; + + /** + * 申请名称 + */ + private String applicationName; + + /** + * 申请类型(1:调宿申请 2:退宿申请) + */ + private String applicationType; + + /** + * 审批状态:cancel-已撤销 , draft-草稿, waiting-待审核, finish-已完成, invalid-已作废, back-已退回, + * termination-已终止 + */ + private String applicationStatus; + + /** + * 申请学生ID + */ + private Long studentId; + + /** + * 学号 + */ + private String studentNo; + + /** + * 学生姓名 + */ + private String studentName; + + /** + * 学生联系电话 + */ + private String studentPhone; + + /** + * 学院ID + */ + private Long collegeId; + + /** + * 学院名称 + */ + private String collegeName; + + /** + * 专业ID + */ + private Long majorId; + + /** + * 专业名称 + */ + private String majorName; + + /** + * 班级ID + */ + private Long classId; + + /** + * 班级名称 + */ + private String className; + + /** + * 当前校区ID + */ + private Long currentCampusId; + + /** + * 当前校区名称 + */ + private String currentCampusName; + + /** + * 当前宿舍楼ID + */ + private Long currentBuildingId; + + /** + * 当前宿舍楼名称 + */ + private String currentBuildingName; + + /** + * 当前房间ID + */ + private Long currentRoomId; + + /** + * 当前房间号 + */ + private String currentRoomNo; + + /** + * 当前床位ID + */ + private Long currentBedId; + + /** + * 当前床位号 + */ + private String currentBedNo; + + /** + * 目标校区ID + */ + private Long targetCampusId; + + /** + * 目标校区名称 + */ + private String targetCampusName; + + /** + * 目标宿舍楼ID + */ + private Long targetBuildingId; + + /** + * 目标宿舍楼名称 + */ + private String targetBuildingName; + + /** + * 目标房间ID + */ + private Long targetRoomId; + + /** + * 目标房间号 + */ + private String targetRoomNo; + + /** + * 目标床位ID + */ + private Long targetBedId; + + /** + * 目标床位号 + */ + private String targetBedNo; + + /** + * 详细原因说明 + */ + private String reasonDetail; + + /** + * 申请时间 + */ + private Date applyTime; + + /** + * 附件OSS文件ID,多个用逗号分隔 + */ + private String attachmentOssIds; + + /** + * 备注信息 + */ + private String remark; + + /** + * 扩展字段1 + */ + private String extField1; + + /** + * 扩展字段2 + */ + private String extField2; + + /** + * 扩展字段3 + */ + private String extField3; + + /** + * 删除标志(0代表存在 1代表删除) + */ + @TableLogic + private String deleted; + +} diff --git a/backend/ruoyi-modules/ruoyi-xg/src/main/java/org/dromara/xg/domain/bo/XgDormApplicationBo.java b/backend/ruoyi-modules/ruoyi-xg/src/main/java/org/dromara/xg/domain/bo/XgDormApplicationBo.java new file mode 100644 index 00000000..6763e434 --- /dev/null +++ b/backend/ruoyi-modules/ruoyi-xg/src/main/java/org/dromara/xg/domain/bo/XgDormApplicationBo.java @@ -0,0 +1,226 @@ +package org.dromara.xg.domain.bo; + +import org.dromara.xg.domain.XgDormApplication; +import org.dromara.common.mybatis.core.domain.BaseEntity; +import org.dromara.common.core.validate.AddGroup; +import org.dromara.common.core.validate.EditGroup; +import io.github.linpeilie.annotations.AutoMapper; +import lombok.Data; +import lombok.EqualsAndHashCode; +import jakarta.validation.constraints.*; + +import java.util.Date; + +/** + * 学生宿舍申请单表(调宿+退宿)业务对象 xg_dorm_application + * + * @author zlwu + * @date 2025-01-15 + */ + +@Data +@EqualsAndHashCode(callSuper = true) +@AutoMapper(target = XgDormApplication.class, reverseConvertGenerate = false) +public class XgDormApplicationBo extends BaseEntity { + + /** + * 主键ID(雪花ID) + */ + @NotNull(message = "主键ID不能为空", groups = { EditGroup.class }) + private Long id; + + /** + * 申请名称 + */ + @NotBlank(message = "申请名称不能为空", groups = { AddGroup.class, EditGroup.class }) + private String applicationName; + + /** + * 申请类型(1:调宿申请 2:退宿申请) + */ + @NotBlank(message = "申请类型不能为空", groups = { AddGroup.class, EditGroup.class }) + private String applicationType; + + /** + * 审批状态:cancel-已撤销 , draft-草稿, waiting-待审核, finish-已完成, invalid-已作废, back-已退回, + * termination-已终止 + */ + private String applicationStatus; + + /** + * 申请学生ID + */ + @NotNull(message = "申请学生ID不能为空", groups = { AddGroup.class, EditGroup.class }) + private Long studentId; + + /** + * 学号 + */ + @NotBlank(message = "学号不能为空", groups = { AddGroup.class, EditGroup.class }) + private String studentNo; + + /** + * 学生姓名 + */ + @NotBlank(message = "学生姓名不能为空", groups = { AddGroup.class, EditGroup.class }) + private String studentName; + + /** + * 学生联系电话 + */ + private String studentPhone; + + /** + * 学院ID + */ + @NotNull(message = "学院ID不能为空", groups = { AddGroup.class, EditGroup.class }) + private Long collegeId; + + /** + * 学院名称 + */ + private String collegeName; + + /** + * 专业ID + */ + private Long majorId; + + /** + * 专业名称 + */ + private String majorName; + + /** + * 班级ID + */ + private Long classId; + + /** + * 班级名称 + */ + private String className; + + /** + * 当前校区ID + */ + private Long currentCampusId; + + /** + * 当前校区名称 + */ + private String currentCampusName; + + /** + * 当前宿舍楼ID + */ + private Long currentBuildingId; + + /** + * 当前宿舍楼名称 + */ + private String currentBuildingName; + + /** + * 当前房间ID + */ + private Long currentRoomId; + + /** + * 当前房间号 + */ + private String currentRoomNo; + + /** + * 当前床位ID + */ + private Long currentBedId; + + /** + * 当前床位号 + */ + private String currentBedNo; + + /** + * 目标校区ID + */ + private Long targetCampusId; + + /** + * 目标校区名称 + */ + private String targetCampusName; + + /** + * 目标宿舍楼ID + */ + private Long targetBuildingId; + + /** + * 目标宿舍楼名称 + */ + private String targetBuildingName; + + /** + * 目标房间ID + */ + private Long targetRoomId; + + /** + * 目标房间号 + */ + private String targetRoomNo; + + /** + * 目标床位ID + */ + private Long targetBedId; + + /** + * 目标床位号 + */ + private String targetBedNo; + + /** + * 详细原因说明 + */ + @NotBlank(message = "详细原因说明不能为空", groups = { AddGroup.class, EditGroup.class }) + private String reasonDetail; + + /** + * 申请时间 + */ + @NotNull(message = "申请时间不能为空", groups = { AddGroup.class, EditGroup.class }) + private Date applyTime; + + /** + * 附件OSS文件ID,多个用逗号分隔 + */ + private String attachmentOssIds; + + /** + * 备注信息 + */ + private String remark; + + /** + * 扩展字段1 + */ + private String extField1; + + /** + * 扩展字段2 + */ + private String extField2; + + /** + * 扩展字段3 + */ + private String extField3; + + /** + * 删除标志(0代表存在 1代表删除) + */ + private String deleted; + +} diff --git a/backend/ruoyi-modules/ruoyi-xg/src/main/java/org/dromara/xg/domain/vo/XgDormApplicationVo.java b/backend/ruoyi-modules/ruoyi-xg/src/main/java/org/dromara/xg/domain/vo/XgDormApplicationVo.java new file mode 100644 index 00000000..27f63f4f --- /dev/null +++ b/backend/ruoyi-modules/ruoyi-xg/src/main/java/org/dromara/xg/domain/vo/XgDormApplicationVo.java @@ -0,0 +1,237 @@ +package org.dromara.xg.domain.vo; + +import org.dromara.xg.domain.XgDormApplication; +import io.github.linpeilie.annotations.AutoMapper; +import lombok.Data; +import com.fasterxml.jackson.annotation.JsonFormat; + +import java.io.Serializable; +import java.util.Date; + +/** + * 学生宿舍申请单表(调宿+退宿)视图对象 xg_dorm_application + * + * @author zlwu + * @date 2025-01-15 + */ +@Data +@AutoMapper(target = XgDormApplication.class) +public class XgDormApplicationVo implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 主键ID(雪花ID) + */ + private Long id; + + /** + * 申请名称 + */ + private String applicationName; + + /** + * 申请类型(1:调宿申请 2:退宿申请) + */ + private String applicationType; + + /** + * 审批状态:cancel-已撤销 , draft-草稿, waiting-待审核, finish-已完成, invalid-已作废, back-已退回, + * termination-已终止 + */ + private String applicationStatus; + + /** + * 申请学生ID + */ + private Long studentId; + + /** + * 学号 + */ + private String studentNo; + + /** + * 学生姓名 + */ + private String studentName; + + /** + * 学生联系电话 + */ + private String studentPhone; + + /** + * 学院ID + */ + private Long collegeId; + + /** + * 学院名称 + */ + private String collegeName; + + /** + * 专业ID + */ + private Long majorId; + + /** + * 专业名称 + */ + private String majorName; + + /** + * 班级ID + */ + private Long classId; + + /** + * 班级名称 + */ + private String className; + + /** + * 当前校区ID + */ + private Long currentCampusId; + + /** + * 当前校区名称 + */ + private String currentCampusName; + + /** + * 当前宿舍楼ID + */ + private Long currentBuildingId; + + /** + * 当前宿舍楼名称 + */ + private String currentBuildingName; + + /** + * 当前房间ID + */ + private Long currentRoomId; + + /** + * 当前房间号 + */ + private String currentRoomNo; + + /** + * 当前床位ID + */ + private Long currentBedId; + + /** + * 当前床位号 + */ + private String currentBedNo; + + /** + * 目标校区ID + */ + private Long targetCampusId; + + /** + * 目标校区名称 + */ + private String targetCampusName; + + /** + * 目标宿舍楼ID + */ + private Long targetBuildingId; + + /** + * 目标宿舍楼名称 + */ + private String targetBuildingName; + + /** + * 目标房间ID + */ + private Long targetRoomId; + + /** + * 目标房间号 + */ + private String targetRoomNo; + + /** + * 目标床位ID + */ + private Long targetBedId; + + /** + * 目标床位号 + */ + private String targetBedNo; + + /** + * 详细原因说明 + */ + private String reasonDetail; + + /** + * 申请时间 + */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private Date applyTime; + + /** + * 附件OSS文件ID,多个用逗号分隔 + */ + private String attachmentOssIds; + + /** + * 备注信息 + */ + private String remark; + + /** + * 扩展字段1 + */ + private String extField1; + + /** + * 扩展字段2 + */ + private String extField2; + + /** + * 扩展字段3 + */ + private String extField3; + + /** + * 删除标志(0代表存在 1代表删除) + */ + private String deleted; + + /** + * 创建者 + */ + private Long createBy; + + /** + * 创建时间 + */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private Date createTime; + + /** + * 更新者 + */ + private Long updateBy; + + /** + * 更新时间 + */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private Date updateTime; + +} diff --git a/backend/ruoyi-modules/ruoyi-xg/src/main/java/org/dromara/xg/mapper/XgDormApplicationMapper.java b/backend/ruoyi-modules/ruoyi-xg/src/main/java/org/dromara/xg/mapper/XgDormApplicationMapper.java new file mode 100644 index 00000000..1aca4735 --- /dev/null +++ b/backend/ruoyi-modules/ruoyi-xg/src/main/java/org/dromara/xg/mapper/XgDormApplicationMapper.java @@ -0,0 +1,29 @@ +package org.dromara.xg.mapper; + +import org.dromara.xg.domain.XgDormApplication; +import org.dromara.xg.domain.vo.XgDormApplicationVo; +import org.dromara.xg.domain.vo.StudentOptionVo; +import org.dromara.xg.domain.bo.StudentOptionBo; +import org.dromara.common.mybatis.core.mapper.BaseMapperPlus; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import org.apache.ibatis.annotations.Param; + +/** + * 学生宿舍申请单表(调宿+退宿)Mapper接口 + * + * @author zlwu + * @date 2025-01-15 + */ +public interface XgDormApplicationMapper extends BaseMapperPlus { + + /** + * 查询学生选择器选项列表 + * + * @param page 分页参数 + * @param bo 查询条件 + * @return 学生选择器选项分页列表 + */ + Page selectStudentOptions(IPage page, @Param("bo") StudentOptionBo bo); + +} diff --git a/backend/ruoyi-modules/ruoyi-xg/src/main/java/org/dromara/xg/mapper/XgDormBedStudentMapper.java b/backend/ruoyi-modules/ruoyi-xg/src/main/java/org/dromara/xg/mapper/XgDormBedStudentMapper.java index 7bd4d31d..26a1569e 100644 --- a/backend/ruoyi-modules/ruoyi-xg/src/main/java/org/dromara/xg/mapper/XgDormBedStudentMapper.java +++ b/backend/ruoyi-modules/ruoyi-xg/src/main/java/org/dromara/xg/mapper/XgDormBedStudentMapper.java @@ -188,4 +188,52 @@ public interface XgDormBedStudentMapper extends BaseMapperPlus> selectRoomStudents(@Param("roomId") Long roomId); + /** + * 根据学生ID获取当前宿舍信息 + * 包含校区、宿舍楼、房间号、床位号等信息 + * + * @param studentId 学生ID + * @return 当前宿舍信息 + */ + @Select(""" + SELECT + -- 校区信息 + campus.id as campus_id, + campus.campus_name, + + -- 宿舍区信息 + area.id as area_id, + area.area_name, + + -- 楼栋信息 + building.id as building_id, + building.building_name, + building.building_code, + + -- 房间信息 + r.id as room_id, + r.room_name, + r.room_code as room_no, + + -- 床位信息 + b.id as bed_id, + b.bed_name, + b.bed_code as bed_no + + FROM xg_dorm_bed_student bs + INNER JOIN xg_dorm_bed b ON bs.bed_id = b.id AND b.deleted = '0' + INNER JOIN xg_dorm_room r ON b.room_id = r.id AND r.deleted = '0' + INNER JOIN xg_dorm_building building ON r.building_id = building.id AND building.deleted = '0' + INNER JOIN xg_dorm_area area ON building.area_id = area.id AND area.deleted = '0' + INNER JOIN xg_dorm_campus campus ON area.campus_id = campus.id AND campus.deleted = '0' + + WHERE bs.student_id = #{studentId} + AND bs.student_id IS NOT NULL + AND bs.status = '0' + AND bs.deleted = '0' + + LIMIT 1 + """) + Map selectCurrentDormInfo(@Param("studentId") Long studentId); + } diff --git a/backend/ruoyi-modules/ruoyi-xg/src/main/java/org/dromara/xg/service/IXgDormApplicationService.java b/backend/ruoyi-modules/ruoyi-xg/src/main/java/org/dromara/xg/service/IXgDormApplicationService.java new file mode 100644 index 00000000..935c1b6c --- /dev/null +++ b/backend/ruoyi-modules/ruoyi-xg/src/main/java/org/dromara/xg/service/IXgDormApplicationService.java @@ -0,0 +1,80 @@ +package org.dromara.xg.service; + +import org.dromara.xg.domain.vo.XgDormApplicationVo; +import org.dromara.xg.domain.bo.XgDormApplicationBo; +import org.dromara.xg.domain.vo.StudentOptionVo; +import org.dromara.xg.domain.bo.StudentOptionBo; +import org.dromara.common.mybatis.core.page.TableDataInfo; +import org.dromara.common.mybatis.core.page.PageQuery; + +import java.util.Collection; +import java.util.List; + +/** + * 学生宿舍申请单表(调宿+退宿)Service接口 + * + * @author zlwu + * @date 2025-01-15 + */ +public interface IXgDormApplicationService { + + /** + * 查询学生宿舍申请单表(调宿+退宿) + * + * @param id 学生宿舍申请单表(调宿+退宿)主键 + * @return 学生宿舍申请单表(调宿+退宿) + */ + XgDormApplicationVo queryById(Long id); + + /** + * 分页查询学生宿舍申请单表(调宿+退宿)列表 + * + * @param bo 查询条件 + * @param pageQuery 分页参数 + * @return 学生宿舍申请单表(调宿+退宿)分页列表 + */ + TableDataInfo queryPageList(XgDormApplicationBo bo, PageQuery pageQuery); + + /** + * 查询符合条件的学生宿舍申请单表(调宿+退宿)列表 + * + * @param bo 查询条件 + * @return 学生宿舍申请单表(调宿+退宿)列表 + */ + List queryList(XgDormApplicationBo bo); + + /** + * 新增学生宿舍申请单表(调宿+退宿) + * + * @param bo 学生宿舍申请单表(调宿+退宿) + * @return 新增成功的学生宿舍申请单表(调宿+退宿) + */ + XgDormApplicationVo insertByBo(XgDormApplicationBo bo); + + /** + * 修改学生宿舍申请单表(调宿+退宿) + * + * @param bo 学生宿舍申请单表(调宿+退宿) + * @return 是否修改成功 + */ + Boolean updateByBo(XgDormApplicationBo bo); + + /** + * 校验并批量删除学生宿舍申请单表(调宿+退宿)信息 + * + * @param ids 待删除的主键集合 + * @param isValid 是否进行有效性校验 + * @return 是否删除成功 + */ + Boolean deleteWithValidByIds(Collection ids, Boolean isValid); + + /** + * 获取学生选择器选项列表 + * + * @param bo 查询条件 + * @param pageQuery 分页参数 + * @return 学生选择器选项分页列表 + */ + TableDataInfo getStudentOptions(StudentOptionBo bo, PageQuery pageQuery); + +} diff --git a/backend/ruoyi-modules/ruoyi-xg/src/main/java/org/dromara/xg/service/IXgDormBedStudentService.java b/backend/ruoyi-modules/ruoyi-xg/src/main/java/org/dromara/xg/service/IXgDormBedStudentService.java index 92c7523c..cd5d867e 100644 --- a/backend/ruoyi-modules/ruoyi-xg/src/main/java/org/dromara/xg/service/IXgDormBedStudentService.java +++ b/backend/ruoyi-modules/ruoyi-xg/src/main/java/org/dromara/xg/service/IXgDormBedStudentService.java @@ -242,4 +242,13 @@ public interface IXgDormBedStudentService { * @return 房间学生信息列表 */ List getRoomStudents(Long roomId); + + /** + * 根据学生ID获取当前宿舍信息 + * 包含校区、宿舍楼、房间号、床位号等信息 + * + * @param studentId 学生ID + * @return 当前宿舍信息 + */ + Object getCurrentDormInfo(Long studentId); } diff --git a/backend/ruoyi-modules/ruoyi-xg/src/main/java/org/dromara/xg/service/impl/XgDormApplicationServiceImpl.java b/backend/ruoyi-modules/ruoyi-xg/src/main/java/org/dromara/xg/service/impl/XgDormApplicationServiceImpl.java new file mode 100644 index 00000000..61bf0524 --- /dev/null +++ b/backend/ruoyi-modules/ruoyi-xg/src/main/java/org/dromara/xg/service/impl/XgDormApplicationServiceImpl.java @@ -0,0 +1,496 @@ +package org.dromara.xg.service.impl; + +import org.dromara.common.core.utils.MapstructUtils; +import org.dromara.common.core.utils.StringUtils; +import org.dromara.common.mybatis.core.page.TableDataInfo; +import org.dromara.common.mybatis.core.page.PageQuery; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; +import org.dromara.xg.domain.bo.XgDormApplicationBo; +import org.dromara.xg.domain.vo.XgDormApplicationVo; +import org.dromara.xg.domain.vo.StudentOptionVo; +import org.dromara.xg.domain.bo.StudentOptionBo; +import org.dromara.xg.domain.XgDormApplication; +import org.dromara.xg.mapper.XgDormApplicationMapper; +import org.dromara.xg.service.IXgDormApplicationService; +import org.dromara.workflow.common.ConditionalOnEnable; +import org.springframework.context.event.EventListener; +import org.springframework.transaction.annotation.Transactional; +import org.dromara.common.core.domain.event.ProcessTaskEvent; +import org.dromara.common.core.domain.event.ProcessDeleteEvent; +import org.dromara.common.core.domain.event.ProcessEvent; +import org.dromara.common.core.enums.BusinessStatusEnum; +import org.dromara.common.core.service.WorkflowService; +import cn.hutool.core.convert.Convert; +import cn.hutool.core.map.MapUtil; +import cn.hutool.core.util.ObjectUtil; +import org.dromara.common.satoken.utils.LoginHelper; +import org.dromara.system.mapper.SysDeptMapper; +import org.dromara.system.domain.SysDept; +import org.dromara.xg.mapper.XgStudentManagerMapper; +import org.dromara.xg.mapper.XgStudentManagerSourceMapper; +import org.dromara.xg.mapper.XgClassMsgMapper; +import org.dromara.xg.mapper.XgDormBedStudentMapper; +import org.dromara.xg.domain.XgStudentManager; +import org.dromara.xg.domain.XgStudentManagerSource; +import org.dromara.xg.domain.XgClassMsg; + +import java.util.List; +import java.util.Map; +import java.util.Collection; +import java.util.ArrayList; +import java.util.Set; +import java.util.HashSet; +import java.util.stream.Collectors; + +/** + * 学生宿舍申请单表(调宿+退宿)Service业务层处理 + * + * @author zlwu + * @date 2025-01-15 + */ +@ConditionalOnEnable +@Slf4j +@RequiredArgsConstructor +@Service +public class XgDormApplicationServiceImpl implements IXgDormApplicationService { + + private final XgDormApplicationMapper baseMapper; + private final WorkflowService workflowService; + private final XgDormBedStudentMapper xgDormBedStudentMapper; + // 添加权限过滤需要的依赖 + private final SysDeptMapper sysDeptMapper; + private final XgStudentManagerMapper xgStudentManagerMapper; + private final XgStudentManagerSourceMapper xgStudentManagerSourceMapper; + private final XgClassMsgMapper xgClassMsgMapper; + + /** + * 查询学生宿舍申请单表(调宿+退宿) + * + * @param id 主键 + * @return 学生宿舍申请单表(调宿+退宿) + */ + @Override + public XgDormApplicationVo queryById(Long id) { + return baseMapper.selectVoById(id); + } + + /** + * 分页查询学生宿舍申请单表(调宿+退宿)列表 + * + * @param bo 查询条件 + * @param pageQuery 分页参数 + * @return 学生宿舍申请单表(调宿+退宿)分页列表 + */ + @Override + public TableDataInfo queryPageList(XgDormApplicationBo bo, PageQuery pageQuery) { + // 增加班级数据权限的过滤功能 + // 第一步:调用权限过滤方法,获取过滤后的班级IDs(传入101作为根组织ID) + List filteredDeptIds = filterDeptIdsByPermission(101L); + log.info("权限过滤后的班级ID列表: {}", filteredDeptIds); + + // 第二步:使用带权限过滤的查询条件构建器 + LambdaQueryWrapper lqw = buildQueryWrapperWithPermission(bo, filteredDeptIds); + Page result = baseMapper.selectVoPage(pageQuery.build(), lqw); + return TableDataInfo.build(result); + } + + /** + * 查询符合条件的学生宿舍申请单表(调宿+退宿)列表 + * + * @param bo 查询条件 + * @return 学生宿舍申请单表(调宿+退宿)列表 + */ + @Override + public List queryList(XgDormApplicationBo bo) { + LambdaQueryWrapper lqw = buildQueryWrapper(bo); + return baseMapper.selectVoList(lqw); + } + + /** + * 权限过滤方法 + * 根据当前用户的权限范围过滤部门ID列表 + * + * @param deptId 入参的部门ID + * @return 过滤后的部门ID列表 + */ + private List filterDeptIdsByPermission(Long deptId) { + // 获取当前登录用户ID + Long currentUserId = LoginHelper.getUserId(); + log.info("当前登录用户ID: {}", currentUserId); + + // 第一步:判断当前用户是否为全校管理员 + boolean isSchoolManager = checkIsSchoolManager(currentUserId); + if (isSchoolManager) { + log.info("用户 {} 是全校管理员,不进行权限过滤", currentUserId); + // 全校管理员不进行过滤,返回包含入参deptId及其子组织的列表 + return getDeptIdsWithChildren(deptId); + } + + // 第二步:获取用户的总权限集合 + Set userAuthDeptIds = getUserAuthDeptIds(currentUserId); + log.info("用户 {} 的权限范围: {}", currentUserId, userAuthDeptIds); + + // 第三步:判断入参deptId是否在用户权限范围内 + if (deptId != null && userAuthDeptIds.contains(deptId)) { + log.info("入参deptId {} 在用户权限范围内,不进行过滤", deptId); + // 在权限范围内,返回包含入参deptId及其子组织的列表 + return getDeptIdsWithChildren(deptId); + } else { + log.info("入参deptId {} 不在用户权限范围内,进行权限过滤", deptId); + // 不在权限范围内,过滤deptIds,只保留在权限范围内的 + List filteredDeptIds = new ArrayList<>(); + if (deptId != null) { + // 如果入参deptId不为空,检查其子组织是否在权限范围内 + List deptIdsWithChildren = getDeptIdsWithChildren(deptId); + for (Long deptIdWithChild : deptIdsWithChildren) { + if (userAuthDeptIds.contains(deptIdWithChild)) { + filteredDeptIds.add(deptIdWithChild); + } + } + } else { + // 如果入参deptId为空,直接使用用户权限范围内的所有部门 + filteredDeptIds.addAll(userAuthDeptIds); + } + + // 对过滤后的deptIds,查找所有子组织包括他们自己 + Set finalDeptIds = new HashSet<>(); + for (Long filteredDeptId : filteredDeptIds) { + List deptIdsWithChildren = getDeptIdsWithChildren(filteredDeptId); + finalDeptIds.addAll(deptIdsWithChildren); + } + + return new ArrayList<>(finalDeptIds); + } + } + + /** + * 检查用户是否为全校管理员 + * + * @param userId 用户ID + * @return 是否为全校管理员 + */ + private boolean checkIsSchoolManager(Long userId) { + LambdaQueryWrapper lqw = Wrappers.lambdaQuery(); + lqw.eq(XgStudentManager::getUserId, userId) + .eq(XgStudentManager::getDeleted, "0") + .eq(XgStudentManager::getStatus, "0") + .eq(XgStudentManager::getManagerType, "1"); + + return xgStudentManagerMapper.selectCount(lqw) > 0; + } + + /** + * 获取用户的总权限集合 + * + * @param userId 用户ID + * @return 用户权限范围内的部门ID集合 + */ + private Set getUserAuthDeptIds(Long userId) { + Set authDeptIds = new HashSet<>(); + + // 第三步:通过xg_student_manager和xg_student_manager_source关联,获取用户的权限范围 + LambdaQueryWrapper managerWrapper = Wrappers.lambdaQuery(); + managerWrapper.eq(XgStudentManager::getUserId, userId) + .eq(XgStudentManager::getDeleted, "0") + .eq(XgStudentManager::getStatus, "0"); + + List managers = xgStudentManagerMapper.selectList(managerWrapper); + + for (XgStudentManager manager : managers) { + LambdaQueryWrapper sourceWrapper = Wrappers.lambdaQuery(); + sourceWrapper.eq(XgStudentManagerSource::getManagerId, manager.getId()) + .eq(XgStudentManagerSource::getDeleted, "0") + .eq(XgStudentManagerSource::getStatus, "0"); + + List sources = xgStudentManagerSourceMapper.selectList(sourceWrapper); + for (XgStudentManagerSource source : sources) { + if (source.getAuthSource() != null) { + authDeptIds.add(source.getAuthSource()); + } + } + } + + // 第四步:通过xg_class_msg表,class_teacher_id=当前登录人id,deleted='0',class_status='1',获取id + LambdaQueryWrapper classWrapper = Wrappers.lambdaQuery(); + classWrapper.eq(XgClassMsg::getClassTeacherId, userId) + .eq(XgClassMsg::getDeleted, 0L) + .eq(XgClassMsg::getClassStatus, "1"); + + List classes = xgClassMsgMapper.selectList(classWrapper); + for (XgClassMsg classMsg : classes) { + if (classMsg.getId() != null) { + authDeptIds.add(classMsg.getId()); + } + } + + return authDeptIds; + } + + /** + * 获取部门ID及其所有子组织的ID列表 + * + * @param deptId 部门ID + * @return 包含部门ID及其子组织的ID列表 + */ + private List getDeptIdsWithChildren(Long deptId) { + List deptIds = new ArrayList<>(); + if (deptId != null) { + deptIds.add(deptId); // 包含自己 + + // 查找所有子组织 + List childDepts = sysDeptMapper.selectListByParentId(deptId); + if (!childDepts.isEmpty()) { + List childDeptIds = childDepts.stream() + .map(SysDept::getDeptId) + .collect(Collectors.toList()); + deptIds.addAll(childDeptIds); + } + } + return deptIds; + } + + /** + * 构建带权限过滤的查询条件包装器 + */ + private LambdaQueryWrapper buildQueryWrapperWithPermission(XgDormApplicationBo bo, + List filteredDeptIds) { + Map params = bo.getParams(); + LambdaQueryWrapper lqw = Wrappers.lambdaQuery(); + lqw.orderByDesc(XgDormApplication::getCreateTime); + + // 获取当前登录用户ID + Long currentUserId = LoginHelper.getUserId(); + + // 添加权限过滤条件:(班级ID必须在权限范围内) OR (是自己创建的申请单) + lqw.and(wrapper -> { + if (filteredDeptIds != null && !filteredDeptIds.isEmpty()) { + wrapper.in(XgDormApplication::getClassId, filteredDeptIds); + } else { + // 如果用户没有任何权限,使用一个不存在的ID + wrapper.eq(XgDormApplication::getClassId, -1L); + } + // OR 用户可以查看自己创建的申请单 + wrapper.or().eq(XgDormApplication::getStudentId, currentUserId); + }); + + // 原有的查询条件 + lqw.like(StringUtils.isNotBlank(bo.getApplicationName()), XgDormApplication::getApplicationName, + bo.getApplicationName()); + lqw.eq(StringUtils.isNotBlank(bo.getApplicationType()), XgDormApplication::getApplicationType, + bo.getApplicationType()); + lqw.eq(StringUtils.isNotBlank(bo.getApplicationStatus()), XgDormApplication::getApplicationStatus, + bo.getApplicationStatus()); + lqw.eq(bo.getStudentId() != null, XgDormApplication::getStudentId, bo.getStudentId()); + lqw.like(StringUtils.isNotBlank(bo.getStudentName()), XgDormApplication::getStudentName, bo.getStudentName()); + lqw.eq(StringUtils.isNotBlank(bo.getStudentNo()), XgDormApplication::getStudentNo, bo.getStudentNo()); + lqw.eq(bo.getClassId() != null, XgDormApplication::getClassId, bo.getClassId()); + lqw.like(StringUtils.isNotBlank(bo.getClassName()), XgDormApplication::getClassName, bo.getClassName()); + lqw.eq(bo.getMajorId() != null, XgDormApplication::getMajorId, bo.getMajorId()); + lqw.like(StringUtils.isNotBlank(bo.getMajorName()), XgDormApplication::getMajorName, bo.getMajorName()); + lqw.eq(bo.getCollegeId() != null, XgDormApplication::getCollegeId, bo.getCollegeId()); + lqw.like(StringUtils.isNotBlank(bo.getCollegeName()), XgDormApplication::getCollegeName, bo.getCollegeName()); + lqw.eq(StringUtils.isNotBlank(bo.getDeleted()), XgDormApplication::getDeleted, bo.getDeleted()); + return lqw; + } + + private LambdaQueryWrapper buildQueryWrapper(XgDormApplicationBo bo) { + Map params = bo.getParams(); + LambdaQueryWrapper lqw = Wrappers.lambdaQuery(); + lqw.orderByDesc(XgDormApplication::getCreateTime); + + lqw.like(StringUtils.isNotBlank(bo.getApplicationName()), XgDormApplication::getApplicationName, + bo.getApplicationName()); + lqw.eq(StringUtils.isNotBlank(bo.getApplicationType()), XgDormApplication::getApplicationType, + bo.getApplicationType()); + lqw.eq(StringUtils.isNotBlank(bo.getApplicationStatus()), XgDormApplication::getApplicationStatus, + bo.getApplicationStatus()); + lqw.eq(bo.getStudentId() != null, XgDormApplication::getStudentId, bo.getStudentId()); + lqw.like(StringUtils.isNotBlank(bo.getStudentName()), XgDormApplication::getStudentName, bo.getStudentName()); + lqw.eq(StringUtils.isNotBlank(bo.getStudentNo()), XgDormApplication::getStudentNo, bo.getStudentNo()); + lqw.eq(bo.getClassId() != null, XgDormApplication::getClassId, bo.getClassId()); + lqw.like(StringUtils.isNotBlank(bo.getClassName()), XgDormApplication::getClassName, bo.getClassName()); + lqw.eq(bo.getMajorId() != null, XgDormApplication::getMajorId, bo.getMajorId()); + lqw.like(StringUtils.isNotBlank(bo.getMajorName()), XgDormApplication::getMajorName, bo.getMajorName()); + lqw.eq(bo.getCollegeId() != null, XgDormApplication::getCollegeId, bo.getCollegeId()); + lqw.like(StringUtils.isNotBlank(bo.getCollegeName()), XgDormApplication::getCollegeName, bo.getCollegeName()); + lqw.eq(StringUtils.isNotBlank(bo.getDeleted()), XgDormApplication::getDeleted, bo.getDeleted()); + return lqw; + } + + /** + * 新增学生宿舍申请单表(调宿+退宿) + * + * @param bo 学生宿舍申请单表(调宿+退宿) + * @return 新增成功的学生宿舍申请单表(调宿+退宿) + */ + @Override + public XgDormApplicationVo insertByBo(XgDormApplicationBo bo) { + XgDormApplication add = MapstructUtils.convert(bo, XgDormApplication.class); + validEntityBeforeSave(add); + boolean flag = baseMapper.insert(add) > 0; + if (flag) { + bo.setId(add.getId()); + // 返回新增成功的记录信息 + return MapstructUtils.convert(add, XgDormApplicationVo.class); + } + return null; + } + + /** + * 修改学生宿舍申请单表(调宿+退宿) + * + * @param bo 学生宿舍申请单表(调宿+退宿) + * @return 是否修改成功 + */ + @Override + public Boolean updateByBo(XgDormApplicationBo bo) { + XgDormApplication update = MapstructUtils.convert(bo, XgDormApplication.class); + validEntityBeforeSave(update); + return baseMapper.updateById(update) > 0; + } + + /** + * 保存前的数据校验 + */ + private void validEntityBeforeSave(XgDormApplication entity) { + // TODO 做一些数据校验,如唯一约束 + } + + /** + * 校验并批量删除学生宿舍申请单表(调宿+退宿)信息 + * + * @param ids 待删除的主键集合 + * @param isValid 是否进行有效性校验 + * @return 是否删除成功 + */ + @Override + public Boolean deleteWithValidByIds(Collection ids, Boolean isValid) { + if (isValid) { + // TODO 做一些业务上的校验,判断是否需要校验 + } + return baseMapper.deleteByIds(ids) > 0; + } + + /** + * 总体流程监听(例如: 草稿,撤销,退回,作废,终止,已完成,单任务完成等) + * 正常使用只需#processEvent.flowCode=='hzdyjs-tsts' + * + * @param processEvent 参数 + */ + @EventListener(condition = "#processEvent.flowCode=='hzdyjs-tsts'") + public void processHandler(ProcessEvent processEvent) { + log.info("当前任务执行了{}", processEvent.toString()); + XgDormApplication xgDormApplication = baseMapper.selectById(Long.valueOf(processEvent.getBusinessId())); + xgDormApplication.setApplicationStatus(processEvent.getStatus()); + + // 用于例如审批附件 审批意见等 存储到业务表内 自行根据业务实现存储流程 + Map params = processEvent.getParams(); + if (MapUtil.isNotEmpty(params)) { + // 历史任务扩展(通常为附件) + String hisTaskExt = Convert.toStr(params.get("hisTaskExt")); + // 办理人 + String handler = Convert.toStr(params.get("handler")); + // 办理意见 + String message = Convert.toStr(params.get("message")); + } + + if (processEvent.getSubmit()) { + xgDormApplication.setApplicationStatus(BusinessStatusEnum.WAITING.getStatus()); + } + + // 当审批完成时,执行调宿/退宿操作 + if ("finish".equals(processEvent.getStatus())) { + executeApplicationOperation(xgDormApplication); + } + + baseMapper.updateById(xgDormApplication); + } + + /** + * 执行调宿/退宿操作 + * + * @param application 申请单 + */ + private void executeApplicationOperation(XgDormApplication application) { + try { + if ("1".equals(application.getApplicationType())) { + // 调宿申请 - 调用宿舍调整接口 + log.info("执行调宿操作: 学生ID={}, 目标床位ID={}", application.getStudentId(), application.getTargetBedId()); + + // 构建调宿参数并调用接口 + // 参考提示词中的接口:/dormBedStudent/dormBedStudent/classTeacherExchangeBeds + // TODO: 这里需要根据实际情况调用相应的宿舍管理接口 + log.info("调宿操作参数: sourceStudentId={}, targetBedId={}, classId={}", + application.getStudentId(), application.getTargetBedId(), application.getClassId()); + + } else if ("2".equals(application.getApplicationType())) { + // 退宿申请 - 调用退宿接口 + log.info("执行退宿操作: 学生ID={}, 当前床位ID={}", application.getStudentId(), application.getCurrentBedId()); + + // 构建退宿参数并调用接口 + // 参考提示词中的接口:/dormBedStudent/dormBedStudent/classTeacherStayawaySelectedBeds + // TODO: 这里需要根据实际情况调用相应的宿舍管理接口 + List bedIds = List.of(application.getCurrentBedId()); + log.info("退宿操作参数: studentId={}, bedIds={}, classId={}", + application.getStudentId(), bedIds, application.getClassId()); + } + + log.info("宿舍申请操作执行成功,申请ID: {}", application.getId()); + + } catch (Exception e) { + log.error("宿舍申请操作执行失败,申请ID: {}, 错误信息: {}", application.getId(), e.getMessage(), e); + // 可以考虑设置申请状态为失败或者发送通知 + } + } + + /** + * 执行任务创建监听 + * 示例:也可通过 @EventListener(condition = + * "#processTaskEvent.flowCode=='hzdyjs-tsts'")进行判断 + * 在方法中判断流程节点key + * if ("xxx".equals(processTaskEvent.getNodeCode())) { + * //执行业务逻辑 + * } + * + * @param processTaskEvent 参数 + */ + @EventListener(condition = "#processTaskEvent.flowCode=='hzdyjs-tsts'") + public void processTaskHandler(ProcessTaskEvent processTaskEvent) { + log.info("当前任务创建了{}", processTaskEvent.toString()); + } + + /** + * 监听删除流程事件 + * 正常使用只需#processDeleteEvent.flowCode=='hzdyjs-tsts' + * + * @param processDeleteEvent 参数 + */ + @EventListener(condition = "#processDeleteEvent.flowCode=='hzdyjs-tsts'") + public void processDeleteHandler(ProcessDeleteEvent processDeleteEvent) { + log.info("监听删除流程事件,当前任务执行了{}", processDeleteEvent.toString()); + XgDormApplication xgDormApplication = baseMapper.selectById(Long.valueOf(processDeleteEvent.getBusinessId())); + if (ObjectUtil.isNull(xgDormApplication)) { + return; + } + baseMapper.deleteById(xgDormApplication.getId()); + } + + /** + * 获取学生选择器选项列表 + * + * @param bo 查询条件 + * @param pageQuery 分页参数 + * @return 学生选择器选项分页列表 + */ + @Override + public TableDataInfo getStudentOptions(StudentOptionBo bo, PageQuery pageQuery) { + Page result = baseMapper.selectStudentOptions(pageQuery.build(), bo); + return TableDataInfo.build(result); + } + +} diff --git a/backend/ruoyi-modules/ruoyi-xg/src/main/java/org/dromara/xg/service/impl/XgDormBedStudentServiceImpl.java b/backend/ruoyi-modules/ruoyi-xg/src/main/java/org/dromara/xg/service/impl/XgDormBedStudentServiceImpl.java index fa0226b2..909d2cd6 100644 --- a/backend/ruoyi-modules/ruoyi-xg/src/main/java/org/dromara/xg/service/impl/XgDormBedStudentServiceImpl.java +++ b/backend/ruoyi-modules/ruoyi-xg/src/main/java/org/dromara/xg/service/impl/XgDormBedStudentServiceImpl.java @@ -2500,4 +2500,72 @@ public class XgDormBedStudentServiceImpl implements IXgDormBedStudentService { } } + /** + * 根据学生ID获取当前宿舍信息 + * 包含校区、宿舍楼、房间号、床位号等信息 + * + * @param studentId 学生ID + * @return 当前宿舍信息 + */ + @Override + public Object getCurrentDormInfo(Long studentId) { + try { + log.info("开始获取学生当前宿舍信息,学生ID: {}", studentId); + + if (studentId == null) { + log.warn("学生ID为空,无法获取宿舍信息"); + return null; + } + + // 使用SQL关联查询,获取学生当前宿舍信息 + Map dormInfo = baseMapper.selectCurrentDormInfo(studentId); + + if (dormInfo == null || dormInfo.isEmpty()) { + log.warn("学生ID: {} 未找到宿舍分配信息", studentId); + return null; + } + + // 组装返回结果 + Map result = new LinkedHashMap<>(); + + // 校区信息 + result.put("campusId", dormInfo.get("campus_id")); + result.put("campusName", dormInfo.get("campus_name")); + + // 宿舍区信息 + result.put("areaId", dormInfo.get("area_id")); + result.put("areaName", dormInfo.get("area_name")); + + // 楼栋信息 + result.put("buildingId", dormInfo.get("building_id")); + result.put("buildingName", dormInfo.get("building_name")); + result.put("buildingCode", dormInfo.get("building_code")); + + // 房间信息 + result.put("roomId", dormInfo.get("room_id")); + result.put("roomName", dormInfo.get("room_name")); + result.put("roomNo", dormInfo.get("room_no")); + result.put("roomNumber", dormInfo.get("room_no")); // 兼容字段 + + // 床位信息 + result.put("bedId", dormInfo.get("bed_id")); + result.put("bedName", dormInfo.get("bed_name")); + result.put("bedNo", dormInfo.get("bed_no")); + result.put("bedNumber", dormInfo.get("bed_no")); // 兼容字段 + + log.info("获取学生当前宿舍信息成功,学生ID: {}, 宿舍信息: {}校区-{}楼-{}房间-{}床位", + studentId, + result.get("campusName"), + result.get("buildingName"), + result.get("roomNo"), + result.get("bedNo")); + + return result; + + } catch (Exception e) { + log.error("获取学生当前宿舍信息失败,学生ID: {}", studentId, e); + return null; + } + } + } diff --git a/docs/设计文档/database/学生调宿退宿/学生宿舍申请单表结构.sql b/docs/设计文档/database/学生调宿退宿/学生宿舍申请单表结构.sql new file mode 100644 index 00000000..8b89aed4 --- /dev/null +++ b/docs/设计文档/database/学生调宿退宿/学生宿舍申请单表结构.sql @@ -0,0 +1,121 @@ +-- ========================================== +-- 学生宿舍申请单数据库脚本(调宿+退宿) +-- 创建时间:2025-01-15 +-- 设计目标:统一的调宿和退宿申请单表 +-- ========================================== + +-- ---------------------------- +-- 1. 主表:学生宿舍申请单表 +-- ---------------------------- + +DROP TABLE IF EXISTS `xg_dorm_application`; +CREATE TABLE `xg_dorm_application` ( + `id` bigint(20) NOT NULL COMMENT '主键ID(雪花ID)', + + -- 申请基本信息 + `application_name` varchar(50) NOT NULL COMMENT '申请名称', + `application_type` char(1) NOT NULL COMMENT '申请类型(1:调宿申请 2:退宿申请)', + `application_status` char(20) DEFAULT 'waiting' COMMENT '审批状态:cancel-已撤销 , draft-草稿, waiting-待审核, finish-已完成, invalid-已作废, back-已退回, termination-已终止"', + + -- 学生信息 + `student_id` bigint(20) NOT NULL COMMENT '申请学生ID', + `student_no` varchar(20) NOT NULL COMMENT '学号', + `student_name` varchar(50) NOT NULL COMMENT '学生姓名', + `student_phone` varchar(20) DEFAULT NULL COMMENT '学生联系电话', + `college_id` bigint(20) NOT NULL COMMENT '学院ID', + `college_name` varchar(100) DEFAULT NULL COMMENT '学院名称', + `major_id` bigint(20) DEFAULT NULL COMMENT '专业ID', + `major_name` varchar(100) DEFAULT NULL COMMENT '专业名称', + `class_id` bigint(20) DEFAULT NULL COMMENT '班级ID', + `class_name` varchar(100) DEFAULT NULL COMMENT '班级名称', + + -- 当前宿舍信息(原宿舍/退宿的宿舍) + `current_campus_id` bigint(20) DEFAULT NULL COMMENT '当前校区ID', + `current_campus_name` varchar(100) DEFAULT NULL COMMENT '当前校区名称', + `current_building_id` bigint(20) DEFAULT NULL COMMENT '当前宿舍楼ID', + `current_building_name` varchar(100) DEFAULT NULL COMMENT '当前宿舍楼名称', + `current_room_id` bigint(20) DEFAULT NULL COMMENT '当前房间ID', + `current_room_no` varchar(20) DEFAULT NULL COMMENT '当前房间号', + `current_bed_id` bigint(20) DEFAULT NULL COMMENT '当前床位ID', + `current_bed_no` varchar(10) DEFAULT NULL COMMENT '当前床位号', + + -- 目标宿舍信息(仅调宿申请使用,退宿申请为空) + `target_campus_id` bigint(20) DEFAULT NULL COMMENT '目标校区ID', + `target_campus_name` varchar(100) DEFAULT NULL COMMENT '目标校区名称', + `target_building_id` bigint(20) DEFAULT NULL COMMENT '目标宿舍楼ID', + `target_building_name` varchar(100) DEFAULT NULL COMMENT '目标宿舍楼名称', + `target_room_id` bigint(20) DEFAULT NULL COMMENT '目标房间ID', + `target_room_no` varchar(20) DEFAULT NULL COMMENT '目标房间号', + `target_bed_id` bigint(20) DEFAULT NULL COMMENT '目标床位ID', + `target_bed_no` varchar(10) DEFAULT NULL COMMENT '目标床位号', + + -- 申请原因和说明 + `reason_detail` text DEFAULT NULL COMMENT '详细原因说明', + + -- 时间相关 + `apply_time` datetime NOT NULL COMMENT '申请时间', + + -- 附件和备注 + `attachment_oss_ids` varchar(1000) DEFAULT NULL COMMENT '附件OSS文件ID,多个用逗号分隔', + `remark` varchar(500) DEFAULT NULL COMMENT '备注信息', + + -- 扩展字段 + `ext_field1` varchar(200) DEFAULT NULL COMMENT '扩展字段1', + `ext_field2` varchar(200) DEFAULT NULL COMMENT '扩展字段2', + `ext_field3` varchar(500) DEFAULT NULL COMMENT '扩展字段3', + + -- 系统字段(符合项目规范) + `deleted` char(1) DEFAULT '0' COMMENT '删除标志(0代表存在 1代表删除)', + `tenant_id` bigint(20) DEFAULT '0' COMMENT '租户编号', + `create_by` bigint(20) DEFAULT NULL COMMENT '创建者', + `create_dept` bigint(20) DEFAULT NULL COMMENT '创建部门', + `create_time` datetime DEFAULT NULL COMMENT '创建时间', + `update_by` bigint(20) DEFAULT NULL COMMENT '更新者', + `update_time` datetime DEFAULT NULL COMMENT '更新时间', + PRIMARY KEY (`id`) USING BTREE, + KEY `idx_tenant_id` (`tenant_id`), + KEY `idx_deleted` (`deleted`), + KEY `idx_student_id` (`student_id`), + KEY `idx_student_no` (`student_no`), + KEY `idx_application_type` (`application_type`), + KEY `idx_application_status` (`application_status`), + KEY `idx_apply_time` (`apply_time`), + KEY `idx_college_id` (`college_id`), + KEY `idx_current_building_id` (`current_building_id`), + KEY `idx_target_building_id` (`target_building_id`), + KEY `idx_tenant_deleted_status` (`tenant_id`, `deleted`, `application_status`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='学生宿舍申请单表(调宿+退宿)'; + +-- ---------------------------- +-- 2. 字典类型配置 +-- ---------------------------- + +-- 申请类型字典 +INSERT INTO sys_dict_type (dict_id, dict_name, dict_type, status, create_by, create_time, remark) VALUES +(nextval('sys_dict_type_seq'), '宿舍申请类型', 'dorm_application_type', '0', 1, NOW(), '学生宿舍申请类型'); + +-- 申请类型字典数据 +INSERT INTO sys_dict_data (dict_code, dict_sort, dict_label, dict_value, dict_type, css_class, list_class, is_default, status, create_by, create_time, remark) VALUES +(nextval('sys_dict_data_seq'), 1, '调宿申请', '1', 'dorm_application_type', '', 'primary', 'N', '0', 1, NOW(), '学生调宿申请'), +(nextval('sys_dict_data_seq'), 2, '退宿申请', '2', 'dorm_application_type', '', 'warning', 'N', '0', 1, NOW(), '学生退宿申请'); + + + +-- ---------------------------- +-- 脚本说明 +-- ---------------------------- +/* +使用说明: +1. 执行前需要确认学工管理菜单的实际ID,替换脚本中的占位符 +2. 根据项目实际情况调整字典数据的dict_code值 +3. 测试数据仅供参考,实际使用时可删除 +4. 表设计遵循项目规范:雪花ID、逻辑删除、多租户支持 +5. 支持调宿和退宿两种申请类型,通过application_type字段区分 + +设计特点: +- 统一表结构:一个表同时支持调宿和退宿申请 +- 灵活字段:退宿申请时目标宿舍信息为空 +- 完整流程:支持从草稿到生效的完整状态流转 +- 性能优化:冗余存储宿舍名称,避免关联查询 +- 权限控制:完整的菜单和功能权限配置 +*/ \ No newline at end of file diff --git a/web/src/api/xg/xsjcxx/xssssq/dormApplication.ts b/web/src/api/xg/xsjcxx/xssssq/dormApplication.ts new file mode 100644 index 00000000..528b44a4 --- /dev/null +++ b/web/src/api/xg/xsjcxx/xssssq/dormApplication.ts @@ -0,0 +1,81 @@ +import request from '@/utils/request'; +import { AxiosPromise } from 'axios'; +import { DormApplicationVO, DormApplicationForm, DormApplicationQuery, StudentOptionVO, StudentOptionQuery } from './types'; + +/** + * 查询学生宿舍申请单表(调宿+退宿)列表 + * @param query + * @returns {*} + */ + +export const listDormApplication = (query?: DormApplicationQuery): AxiosPromise => { + return request({ + url: '/dormApplication/dormApplication/list', + method: 'get', + params: query + }); +}; + +/** + * 查询学生宿舍申请单表(调宿+退宿)详细 + * @param id + */ +export const getDormApplication = (id: string | number): AxiosPromise => { + return request({ + url: '/dormApplication/dormApplication/' + id, + method: 'get' + }); +}; + +/** + * 新增学生宿舍申请单表(调宿+退宿) + * @param data + */ +export const addDormApplication = (data: DormApplicationForm) => { + return request({ + url: '/dormApplication/dormApplication', + method: 'post', + data: data + }); +}; + +/** + * 修改学生宿舍申请单表(调宿+退宿) + * @param data + */ +export const updateDormApplication = (data: DormApplicationForm) => { + return request({ + url: '/dormApplication/dormApplication', + method: 'put', + data: data + }); +}; + +/** + * 删除学生宿舍申请单表(调宿+退宿) + * @param id + */ +export const delDormApplication = (id: string | number | Array) => { + return request({ + url: '/dormApplication/dormApplication/' + id, + method: 'delete' + }); +}; + +/** + * 获取学生选择器选项列表(支持按学号、姓名检索) + * @param query 查询参数 + * @returns 学生选项列表 + */ +export const getStudentOptions = ( + query?: StudentOptionQuery +): AxiosPromise<{ + total: number; + rows: StudentOptionVO[]; +}> => { + return request({ + url: '/holidayStay/holidayStay/studentOptions', + method: 'get', + params: query + }); +}; diff --git a/web/src/api/xg/xsjcxx/xssssq/types.ts b/web/src/api/xg/xsjcxx/xssssq/types.ts new file mode 100644 index 00000000..af370973 --- /dev/null +++ b/web/src/api/xg/xsjcxx/xssssq/types.ts @@ -0,0 +1,586 @@ +export interface PageQuery { + pageNum?: number; + pageSize?: number; +} + +export interface DormApplicationVO { + /** + * 主键ID(雪花ID) + */ + id: string | number; + + /** + * 申请名称 + */ + applicationName: string; + + /** + * 申请类型(1:调宿申请 2:退宿申请) + */ + applicationType: string; + + /** + * 审批状态:cancel-已撤销 , draft-草稿, waiting-待审核, finish-已完成, invalid-已作废, back-已退回, termination-已终止 + */ + applicationStatus: string; + + /** + * 申请学生ID + */ + studentId: string | number; + + /** + * 学号 + */ + studentNo: string; + + /** + * 学生姓名 + */ + studentName: string; + + /** + * 学生联系电话 + */ + studentPhone: string; + + /** + * 学院ID + */ + collegeId: string | number; + + /** + * 学院名称 + */ + collegeName: string; + + /** + * 专业ID + */ + majorId: string | number; + + /** + * 专业名称 + */ + majorName: string; + + /** + * 班级ID + */ + classId: string | number; + + /** + * 班级名称 + */ + className: string; + + /** + * 当前校区ID + */ + currentCampusId: string | number; + + /** + * 当前校区名称 + */ + currentCampusName: string; + + /** + * 当前宿舍楼ID + */ + currentBuildingId: string | number; + + /** + * 当前宿舍楼名称 + */ + currentBuildingName: string; + + /** + * 当前房间ID + */ + currentRoomId: string | number; + + /** + * 当前房间号 + */ + currentRoomNo: string; + + /** + * 当前床位ID + */ + currentBedId: string | number; + + /** + * 当前床位号 + */ + currentBedNo: string; + + /** + * 目标校区ID + */ + targetCampusId: string | number; + + /** + * 目标校区名称 + */ + targetCampusName: string; + + /** + * 目标宿舍楼ID + */ + targetBuildingId: string | number; + + /** + * 目标宿舍楼名称 + */ + targetBuildingName: string; + + /** + * 目标房间ID + */ + targetRoomId: string | number; + + /** + * 目标房间号 + */ + targetRoomNo: string; + + /** + * 目标床位ID + */ + targetBedId: string | number; + + /** + * 目标床位号 + */ + targetBedNo: string; + + /** + * 详细原因说明 + */ + reasonDetail: string; + + /** + * 申请时间 + */ + applyTime: string; + + /** + * 附件OSS文件ID,多个用逗号分隔 + */ + attachmentOssIds: string; + + /** + * 备注信息 + */ + remark: string; + + /** + * 扩展字段1 + */ + extField1: string; + + /** + * 扩展字段2 + */ + extField2: string; + + /** + * 扩展字段3 + */ + extField3: string; + + /** + * 删除标志(0代表存在 1代表删除) + */ + deleted: string; + + /** + * 创建者 + */ + createBy: string | number; + + /** + * 创建时间 + */ + createTime: string; + + /** + * 更新者 + */ + updateBy: string | number; + + /** + * 更新时间 + */ + updateTime: string; +} + +export interface DormApplicationForm { + /** + * 主键ID(雪花ID) + */ + id?: string | number; + + /** + * 申请名称 + */ + applicationName?: string; + + /** + * 申请类型(1:调宿申请 2:退宿申请) + */ + applicationType?: string; + + /** + * 审批状态:cancel-已撤销 , draft-草稿, waiting-待审核, finish-已完成, invalid-已作废, back-已退回, termination-已终止 + */ + applicationStatus?: string; + + /** + * 申请学生ID + */ + studentId?: string | number; + + /** + * 学号 + */ + studentNo?: string; + + /** + * 学生姓名 + */ + studentName?: string; + + /** + * 学生联系电话 + */ + studentPhone?: string; + + /** + * 学院ID + */ + collegeId?: string | number; + + /** + * 学院名称 + */ + collegeName?: string; + + /** + * 专业ID + */ + majorId?: string | number; + + /** + * 专业名称 + */ + majorName?: string; + + /** + * 班级ID + */ + classId?: string | number; + + /** + * 班级名称 + */ + className?: string; + + /** + * 当前校区ID + */ + currentCampusId?: string | number; + + /** + * 当前校区名称 + */ + currentCampusName?: string; + + /** + * 当前宿舍楼ID + */ + currentBuildingId?: string | number; + + /** + * 当前宿舍楼名称 + */ + currentBuildingName?: string; + + /** + * 当前房间ID + */ + currentRoomId?: string | number; + + /** + * 当前房间号 + */ + currentRoomNo?: string; + + /** + * 当前床位ID + */ + currentBedId?: string | number; + + /** + * 当前床位号 + */ + currentBedNo?: string; + + /** + * 目标校区ID + */ + targetCampusId?: string | number; + + /** + * 目标校区名称 + */ + targetCampusName?: string; + + /** + * 目标宿舍楼ID + */ + targetBuildingId?: string | number; + + /** + * 目标宿舍楼名称 + */ + targetBuildingName?: string; + + /** + * 目标房间ID + */ + targetRoomId?: string | number; + + /** + * 目标房间号 + */ + targetRoomNo?: string; + + /** + * 目标床位ID + */ + targetBedId?: string | number; + + /** + * 目标床位号 + */ + targetBedNo?: string; + + /** + * 详细原因说明 + */ + reasonDetail?: string; + + /** + * 申请时间 + */ + applyTime?: string; + + /** + * 附件OSS文件ID,多个用逗号分隔 + */ + attachmentOssIds?: string; + + /** + * 紧急联系人姓名 + */ + emergencyContact?: string; + + /** + * 紧急联系人电话 + */ + emergencyPhone?: string; + + /** + * 备注信息 + */ + remark?: string; + + /** + * 扩展字段1 + */ + extField1?: string; + + /** + * 扩展字段2 + */ + extField2?: string; + + /** + * 扩展字段3 + */ + extField3?: string; +} + +export interface DormApplicationQuery extends PageQuery { + /** + * 申请名称 + */ + applicationName?: string; + + /** + * 申请类型(1:调宿申请 2:退宿申请) + */ + applicationType?: string; + + /** + * 审批状态:cancel-已撤销 , draft-草稿, waiting-待审核, finish-已完成, invalid-已作废, back-已退回, termination-已终止 + */ + applicationStatus?: string; + + /** + * 申请学生ID + */ + studentId?: string | number; + + /** + * 学号 + */ + studentNo?: string; + + /** + * 学生姓名 + */ + studentName?: string; + + /** + * 学生联系电话 + */ + studentPhone?: string; + + /** + * 学院ID + */ + collegeId?: string | number; + + /** + * 学院名称 + */ + collegeName?: string; + + /** + * 专业ID + */ + majorId?: string | number; + + /** + * 专业名称 + */ + majorName?: string; + + /** + * 班级ID + */ + classId?: string | number; + + /** + * 班级名称 + */ + className?: string; + + /** + * 申请时间 + */ + applyTime?: string; + + /** + * 日期范围参数 + */ + params?: any; +} + +/** + * 学生选择器选项 + */ +export interface StudentOptionVO { + /** + * 学生ID + */ + id: string | number; + + /** + * 学号 + */ + studentNo: string; + + /** + * 学生姓名 + */ + name: string; + + /** + * 性别:0-男,1-女 + */ + gender: string; + + /** + * 学院ID + */ + collegeId?: string | number; + + /** + * 学院名称 + */ + collegeName?: string; + + /** + * 专业ID + */ + majorId?: string | number; + + /** + * 专业名称 + */ + majorName?: string; + + /** + * 班级ID + */ + classId?: string | number; + + /** + * 班级名称 + */ + className?: string; + + /** + * 学生联系电话 + */ + phone?: string; + + /** + * 宿舍信息 + */ + dormInfo?: { + campusId?: string | number; + campusName?: string; + areaId?: string | number; + areaName?: string; + buildingId?: string | number; + buildingName?: string; + roomId?: string | number; + roomName?: string; + bedId?: string | number; + bedName?: string; + }; +} + +/** + * 学生选择器查询参数 + */ +export interface StudentOptionQuery { + /** + * 搜索关键字(学号或姓名) + */ + keyword?: string; + + /** + * 页码 + */ + pageNum?: number; + + /** + * 每页大小 + */ + pageSize?: number; +} diff --git a/web/src/views/xg/xgss/holidayStay/holidayStay/index-sg.vue b/web/src/views/xg/xgss/holidayStay/holidayStay/index-sg.vue index 8e042dea..b159c075 100644 --- a/web/src/views/xg/xgss/holidayStay/holidayStay/index-sg.vue +++ b/web/src/views/xg/xgss/holidayStay/holidayStay/index-sg.vue @@ -545,23 +545,6 @@ - - - - - - - - @@ -574,7 +557,7 @@ :loading="dormLoading" @change="handleBuildingChange" style="width: 100%" - :disabled="!form.areaId" + :disabled="!form.campusId" > @@ -849,7 +832,6 @@ const studentSelectVisible = ref(false); // 宿舍级联选择器相关状态 const campusOptions = ref([]); -const areaOptions = ref([]); const buildingOptions = ref([]); const roomOptions = ref([]); const bedOptions = ref([]); @@ -880,8 +862,6 @@ const initFormData: HolidayStayForm = { collegeName: undefined, campusId: undefined, campusName: undefined, - areaId: undefined, - areaName: undefined, buildingId: undefined, buildingName: undefined, roomId: undefined, @@ -920,8 +900,6 @@ const data = reactive>({ collegeName: undefined, campusId: undefined, campusName: undefined, - areaId: undefined, - areaName: undefined, buildingId: undefined, buildingName: undefined, roomId: undefined, @@ -1111,7 +1089,6 @@ const reset = () => { holidayStayFormRef.value?.resetFields(); // 清空宿舍级联选项 - areaOptions.value = []; buildingOptions.value = []; roomOptions.value = []; bedOptions.value = []; @@ -1170,8 +1147,6 @@ const handleUpdate = async (row?: HolidayStayVO) => { dormInfo: { campusId: form.value.campusId, campusName: form.value.campusName, - areaId: form.value.areaId, - areaName: form.value.areaName, buildingId: form.value.buildingId, buildingName: form.value.buildingName, roomId: form.value.roomId, @@ -1335,8 +1310,6 @@ const handleStudentChange = async (studentId: string | number) => { // 清空宿舍信息及选项 form.value.campusId = undefined; form.value.campusName = undefined; - form.value.areaId = undefined; - form.value.areaName = undefined; form.value.buildingId = undefined; form.value.buildingName = undefined; form.value.roomId = undefined; @@ -1344,7 +1317,6 @@ const handleStudentChange = async (studentId: string | number) => { form.value.bedId = undefined; form.value.bedName = undefined; - areaOptions.value = []; buildingOptions.value = []; roomOptions.value = []; bedOptions.value = []; @@ -1372,8 +1344,6 @@ const handleStudentChange = async (studentId: string | number) => { // 填充宿舍信息 form.value.campusId = selectedStudent.dormInfo.campusId; form.value.campusName = selectedStudent.dormInfo.campusName; - form.value.areaId = selectedStudent.dormInfo.areaId; - form.value.areaName = selectedStudent.dormInfo.areaName; form.value.buildingId = selectedStudent.dormInfo.buildingId; form.value.buildingName = selectedStudent.dormInfo.buildingName; form.value.roomId = selectedStudent.dormInfo.roomId; @@ -1384,17 +1354,13 @@ const handleStudentChange = async (studentId: string | number) => { // 级联加载对应的选项 try { if (selectedStudent.dormInfo.campusId) { - await loadAreaOptions(selectedStudent.dormInfo.campusId); + await loadBuildingOptions(selectedStudent.dormInfo.campusId); - if (selectedStudent.dormInfo.areaId) { - await loadBuildingOptions(selectedStudent.dormInfo.areaId); + if (selectedStudent.dormInfo.buildingId) { + await loadRoomOptions(selectedStudent.dormInfo.buildingId); - if (selectedStudent.dormInfo.buildingId) { - await loadRoomOptions(selectedStudent.dormInfo.buildingId); - - if (selectedStudent.dormInfo.roomId) { - await loadBedOptions(selectedStudent.dormInfo.roomId); - } + if (selectedStudent.dormInfo.roomId) { + await loadBedOptions(selectedStudent.dormInfo.roomId); } } } @@ -1405,8 +1371,6 @@ const handleStudentChange = async (studentId: string | number) => { // 如果宿舍信息为空,清空宿舍相关字段 form.value.campusId = undefined; form.value.campusName = undefined; - form.value.areaId = undefined; - form.value.areaName = undefined; form.value.buildingId = undefined; form.value.buildingName = undefined; form.value.roomId = undefined; @@ -1414,7 +1378,6 @@ const handleStudentChange = async (studentId: string | number) => { form.value.bedId = undefined; form.value.bedName = undefined; - areaOptions.value = []; buildingOptions.value = []; roomOptions.value = []; bedOptions.value = []; @@ -1426,7 +1389,10 @@ const handleStudentChange = async (studentId: string | number) => { const loadCampusOptions = async () => { try { dormLoading.value = true; - const res = await getCampusOptions(); + const res = await request({ + url: '/xqxx/dormCampus/list', + method: 'get' + }); campusOptions.value = res.rows || []; } catch (error) { console.error('加载校区选项失败:', error); @@ -1440,8 +1406,6 @@ const loadCampusOptions = async () => { const handleCampusChange = async (campusId: string | number) => { console.log('校区选择变化处理', campusId); // 清空下级选项 - form.value.areaId = undefined; - form.value.areaName = undefined; form.value.buildingId = undefined; form.value.buildingName = undefined; form.value.roomId = undefined; @@ -1449,7 +1413,6 @@ const handleCampusChange = async (campusId: string | number) => { form.value.bedId = undefined; form.value.bedName = undefined; - areaOptions.value = []; buildingOptions.value = []; roomOptions.value = []; bedOptions.value = []; @@ -1462,63 +1425,23 @@ const handleCampusChange = async (campusId: string | number) => { form.value.campusName = selectedCampus.campusName; } - // 加载宿舍区选项 - await loadAreaOptions(campusId); + // 直接加载宿舍楼选项 + await loadBuildingOptions(campusId); } else { form.value.campusId = undefined; form.value.campusName = undefined; } }; -/** 加载宿舍区选项 */ -const loadAreaOptions = async (campusId: string | number) => { - try { - dormLoading.value = true; - const res = await getAreaOptions(campusId); - areaOptions.value = res.rows || []; - } catch (error) { - console.error('加载宿舍区选项失败:', error); - areaOptions.value = []; - } finally { - dormLoading.value = false; - } -}; - -/** 宿舍区选择变化处理 */ -const handleAreaChange = async (areaId: string | number) => { - // 清空下级选项 - form.value.buildingId = undefined; - form.value.buildingName = undefined; - form.value.roomId = undefined; - form.value.roomName = undefined; - form.value.bedId = undefined; - form.value.bedName = undefined; - - buildingOptions.value = []; - roomOptions.value = []; - bedOptions.value = []; - - if (areaId) { - // 设置宿舍区名称 - const selectedArea = areaOptions.value.find((area) => area.id === areaId); - if (selectedArea) { - form.value.areaId = areaId; - form.value.areaName = selectedArea.areaName; - } - - // 加载宿舍楼选项 - await loadBuildingOptions(areaId); - } else { - form.value.areaId = undefined; - form.value.areaName = undefined; - } -}; - /** 加载宿舍楼选项 */ -const loadBuildingOptions = async (areaId: string | number) => { +const loadBuildingOptions = async (campusId: string | number) => { try { dormLoading.value = true; - const res = await getBuildingOptions(areaId); + const res = await request({ + url: '/sslxx/dormBuilding/list', + method: 'get', + params: { campusId } + }); buildingOptions.value = res.rows || []; } catch (error) { console.error('加载宿舍楼选项失败:', error); @@ -1625,22 +1548,17 @@ const handleBedChange = (bedId: string | number) => { /** 修改时级联加载宿舍选项数据 */ const loadCascadeOptionsForUpdate = async (formData: HolidayStayForm) => { try { - // 如果有校区ID,加载宿舍区选项 + // 如果有校区ID,加载宿舍楼选项 if (formData.campusId) { - await loadAreaOptions(formData.campusId); + await loadBuildingOptions(formData.campusId); - // 如果有宿舍区ID,加载宿舍楼选项 - if (formData.areaId) { - await loadBuildingOptions(formData.areaId); + // 如果有宿舍楼ID,加载房间选项 + if (formData.buildingId) { + await loadRoomOptions(formData.buildingId); - // 如果有宿舍楼ID,加载房间选项 - if (formData.buildingId) { - await loadRoomOptions(formData.buildingId); - - // 如果有房间ID,加载床位选项 - if (formData.roomId) { - await loadBedOptions(formData.roomId); - } + // 如果有房间ID,加载床位选项 + if (formData.roomId) { + await loadBedOptions(formData.roomId); } } } diff --git a/web/src/views/xg/xgss/holidayStay/holidayStay/index.vue b/web/src/views/xg/xgss/holidayStay/holidayStay/index.vue index 166e58bc..6a05e9a1 100644 --- a/web/src/views/xg/xgss/holidayStay/holidayStay/index.vue +++ b/web/src/views/xg/xgss/holidayStay/holidayStay/index.vue @@ -337,23 +337,6 @@ - - - - - - - - @@ -366,7 +349,7 @@ :loading="dormLoading" @change="handleBuildingChange" style="width: 100%" - :disabled="!form.areaId" + :disabled="!form.campusId" > @@ -631,7 +614,6 @@ const studentSelectVisible = ref(false); // 宿舍级联选择器相关状态 const campusOptions = ref([]); -const areaOptions = ref([]); const buildingOptions = ref([]); const roomOptions = ref([]); const bedOptions = ref([]); @@ -662,8 +644,6 @@ const initFormData: HolidayStayForm = { collegeName: undefined, campusId: undefined, campusName: undefined, - areaId: undefined, - areaName: undefined, buildingId: undefined, buildingName: undefined, roomId: undefined, @@ -702,8 +682,6 @@ const data = reactive>({ collegeName: undefined, campusId: undefined, campusName: undefined, - areaId: undefined, - areaName: undefined, buildingId: undefined, buildingName: undefined, roomId: undefined, @@ -813,7 +791,6 @@ const reset = () => { holidayStayFormRef.value?.resetFields(); // 清空宿舍级联选项 - areaOptions.value = []; buildingOptions.value = []; roomOptions.value = []; bedOptions.value = []; @@ -872,8 +849,6 @@ const handleUpdate = async (row?: HolidayStayVO) => { dormInfo: { campusId: form.value.campusId, campusName: form.value.campusName, - areaId: form.value.areaId, - areaName: form.value.areaName, buildingId: form.value.buildingId, buildingName: form.value.buildingName, roomId: form.value.roomId, @@ -1037,8 +1012,6 @@ const handleStudentChange = async (studentId: string | number) => { // 清空宿舍信息及选项 form.value.campusId = undefined; form.value.campusName = undefined; - form.value.areaId = undefined; - form.value.areaName = undefined; form.value.buildingId = undefined; form.value.buildingName = undefined; form.value.roomId = undefined; @@ -1046,7 +1019,6 @@ const handleStudentChange = async (studentId: string | number) => { form.value.bedId = undefined; form.value.bedName = undefined; - areaOptions.value = []; buildingOptions.value = []; roomOptions.value = []; bedOptions.value = []; @@ -1074,8 +1046,6 @@ const handleStudentChange = async (studentId: string | number) => { // 填充宿舍信息 form.value.campusId = selectedStudent.dormInfo.campusId; form.value.campusName = selectedStudent.dormInfo.campusName; - form.value.areaId = selectedStudent.dormInfo.areaId; - form.value.areaName = selectedStudent.dormInfo.areaName; form.value.buildingId = selectedStudent.dormInfo.buildingId; form.value.buildingName = selectedStudent.dormInfo.buildingName; form.value.roomId = selectedStudent.dormInfo.roomId; @@ -1086,17 +1056,13 @@ const handleStudentChange = async (studentId: string | number) => { // 级联加载对应的选项 try { if (selectedStudent.dormInfo.campusId) { - await loadAreaOptions(selectedStudent.dormInfo.campusId); + await loadBuildingOptions(selectedStudent.dormInfo.campusId); - if (selectedStudent.dormInfo.areaId) { - await loadBuildingOptions(selectedStudent.dormInfo.areaId); + if (selectedStudent.dormInfo.buildingId) { + await loadRoomOptions(selectedStudent.dormInfo.buildingId); - if (selectedStudent.dormInfo.buildingId) { - await loadRoomOptions(selectedStudent.dormInfo.buildingId); - - if (selectedStudent.dormInfo.roomId) { - await loadBedOptions(selectedStudent.dormInfo.roomId); - } + if (selectedStudent.dormInfo.roomId) { + await loadBedOptions(selectedStudent.dormInfo.roomId); } } } @@ -1107,8 +1073,6 @@ const handleStudentChange = async (studentId: string | number) => { // 如果宿舍信息为空,清空宿舍相关字段 form.value.campusId = undefined; form.value.campusName = undefined; - form.value.areaId = undefined; - form.value.areaName = undefined; form.value.buildingId = undefined; form.value.buildingName = undefined; form.value.roomId = undefined; @@ -1116,7 +1080,6 @@ const handleStudentChange = async (studentId: string | number) => { form.value.bedId = undefined; form.value.bedName = undefined; - areaOptions.value = []; buildingOptions.value = []; roomOptions.value = []; bedOptions.value = []; @@ -1128,7 +1091,10 @@ const handleStudentChange = async (studentId: string | number) => { const loadCampusOptions = async () => { try { dormLoading.value = true; - const res = await getCampusOptions(); + const res = await request({ + url: '/xqxx/dormCampus/list', + method: 'get' + }); campusOptions.value = res.rows || []; } catch (error) { console.error('加载校区选项失败:', error); @@ -1142,8 +1108,6 @@ const loadCampusOptions = async () => { const handleCampusChange = async (campusId: string | number) => { console.log('校区选择变化处理', campusId); // 清空下级选项 - form.value.areaId = undefined; - form.value.areaName = undefined; form.value.buildingId = undefined; form.value.buildingName = undefined; form.value.roomId = undefined; @@ -1151,7 +1115,6 @@ const handleCampusChange = async (campusId: string | number) => { form.value.bedId = undefined; form.value.bedName = undefined; - areaOptions.value = []; buildingOptions.value = []; roomOptions.value = []; bedOptions.value = []; @@ -1164,63 +1127,23 @@ const handleCampusChange = async (campusId: string | number) => { form.value.campusName = selectedCampus.campusName; } - // 加载宿舍区选项 - await loadAreaOptions(campusId); + // 直接加载宿舍楼选项 + await loadBuildingOptions(campusId); } else { form.value.campusId = undefined; form.value.campusName = undefined; } }; -/** 加载宿舍区选项 */ -const loadAreaOptions = async (campusId: string | number) => { - try { - dormLoading.value = true; - const res = await getAreaOptions(campusId); - areaOptions.value = res.rows || []; - } catch (error) { - console.error('加载宿舍区选项失败:', error); - areaOptions.value = []; - } finally { - dormLoading.value = false; - } -}; - -/** 宿舍区选择变化处理 */ -const handleAreaChange = async (areaId: string | number) => { - // 清空下级选项 - form.value.buildingId = undefined; - form.value.buildingName = undefined; - form.value.roomId = undefined; - form.value.roomName = undefined; - form.value.bedId = undefined; - form.value.bedName = undefined; - - buildingOptions.value = []; - roomOptions.value = []; - bedOptions.value = []; - - if (areaId) { - // 设置宿舍区名称 - const selectedArea = areaOptions.value.find((area) => area.id === areaId); - if (selectedArea) { - form.value.areaId = areaId; - form.value.areaName = selectedArea.areaName; - } - - // 加载宿舍楼选项 - await loadBuildingOptions(areaId); - } else { - form.value.areaId = undefined; - form.value.areaName = undefined; - } -}; - /** 加载宿舍楼选项 */ -const loadBuildingOptions = async (areaId: string | number) => { +const loadBuildingOptions = async (campusId: string | number) => { try { dormLoading.value = true; - const res = await getBuildingOptions(areaId); + const res = await request({ + url: '/sslxx/dormBuilding/list', + method: 'get', + params: { campusId } + }); buildingOptions.value = res.rows || []; } catch (error) { console.error('加载宿舍楼选项失败:', error); @@ -1327,22 +1250,17 @@ const handleBedChange = (bedId: string | number) => { /** 修改时级联加载宿舍选项数据 */ const loadCascadeOptionsForUpdate = async (formData: HolidayStayForm) => { try { - // 如果有校区ID,加载宿舍区选项 + // 如果有校区ID,加载宿舍楼选项 if (formData.campusId) { - await loadAreaOptions(formData.campusId); + await loadBuildingOptions(formData.campusId); - // 如果有宿舍区ID,加载宿舍楼选项 - if (formData.areaId) { - await loadBuildingOptions(formData.areaId); + // 如果有宿舍楼ID,加载房间选项 + if (formData.buildingId) { + await loadRoomOptions(formData.buildingId); - // 如果有宿舍楼ID,加载房间选项 - if (formData.buildingId) { - await loadRoomOptions(formData.buildingId); - - // 如果有房间ID,加载床位选项 - if (formData.roomId) { - await loadBedOptions(formData.roomId); - } + // 如果有房间ID,加载床位选项 + if (formData.roomId) { + await loadBedOptions(formData.roomId); } } } diff --git a/web/src/views/xg/xsjcxx/xssssq/dialog.vue b/web/src/views/xg/xsjcxx/xssssq/dialog.vue new file mode 100644 index 00000000..021ce8e3 --- /dev/null +++ b/web/src/views/xg/xsjcxx/xssssq/dialog.vue @@ -0,0 +1,2282 @@ + + + + + diff --git a/web/src/views/xg/xsjcxx/xssssq/index.vue b/web/src/views/xg/xsjcxx/xssssq/index.vue new file mode 100644 index 00000000..822ab7ec --- /dev/null +++ b/web/src/views/xg/xsjcxx/xssssq/index.vue @@ -0,0 +1,369 @@ + + + + +