提交
This commit is contained in:
1 parent
6aa2345f2e
commit
4075b903cf
6 files changed
+1216
No files matched your search
+51
@@ -270,4 +270,55 @@ public class XgDormBedStudentController extends BaseController {
|
||||
return toAjax(xgDormBedStudentService.classTeacherStayawaySelectedBeds(bedIds, classId));
|
||||
}
|
||||
|
||||
/**
|
||||
* 班主任床位互换
|
||||
* 将两个有学生的床位进行互换
|
||||
*/
|
||||
@SaCheckPermission("dormBedStudent:dormBedStudent:edit")
|
||||
@Log(title = "班主任床位互换", businessType = BusinessType.UPDATE)
|
||||
@RepeatSubmit()
|
||||
@PostMapping("/classTeacherExchangeBeds")
|
||||
public R<Void> classTeacherExchangeBeds(@RequestParam Long sourceBedId,
|
||||
@RequestParam Long targetBedId,
|
||||
@RequestParam(required = false) Long classId) {
|
||||
return toAjax(xgDormBedStudentService.classTeacherExchangeBeds(sourceBedId, targetBedId, classId));
|
||||
}
|
||||
|
||||
/**
|
||||
* 班主任床位移动
|
||||
* 将学生从当前床位移动到指定的空闲床位
|
||||
*/
|
||||
@SaCheckPermission("dormBedStudent:dormBedStudent:edit")
|
||||
@Log(title = "班主任床位移动", businessType = BusinessType.UPDATE)
|
||||
@RepeatSubmit()
|
||||
@PostMapping("/classTeacherMoveBed")
|
||||
public R<Void> classTeacherMoveBed(@RequestParam Long sourceBedId,
|
||||
@RequestParam Long targetBedId,
|
||||
@RequestParam(required = false) Long classId) {
|
||||
return toAjax(xgDormBedStudentService.classTeacherMoveBed(sourceBedId, targetBedId, classId));
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取班级所有已入住宿舍的学生床位信息
|
||||
* 包含床位信息(校区名称、宿舍区名称、楼栋名称、房间名称、床位名称)
|
||||
* 和学生信息(学生姓名、学号、性别)
|
||||
*/
|
||||
@SaCheckPermission("dormBedStudent:dormBedStudent:list")
|
||||
@GetMapping("/getClassOccupiedBedDetails")
|
||||
public R<List<Object>> getClassOccupiedBedDetails(@RequestParam(required = false) Long classId) {
|
||||
List<Object> occupiedBedDetails = xgDormBedStudentService.getClassOccupiedBedDetails(classId);
|
||||
return R.ok(occupiedBedDetails);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取班级所有未安排学生的床位信息
|
||||
* 包含床位信息(校区名称、宿舍区名称、楼栋名称、房间名称、床位名称)
|
||||
*/
|
||||
@SaCheckPermission("dormBedStudent:dormBedStudent:list")
|
||||
@GetMapping("/getClassUnoccupiedBedDetails")
|
||||
public R<List<Object>> getClassUnoccupiedBedDetails(@RequestParam(required = false) Long classId) {
|
||||
List<Object> unoccupiedBedDetails = xgDormBedStudentService.getClassUnoccupiedBedDetails(classId);
|
||||
return R.ok(unoccupiedBedDetails);
|
||||
}
|
||||
|
||||
}
|
||||
+41
@@ -192,4 +192,45 @@ public interface IXgDormBedStudentService {
|
||||
* @return 是否退宿成功
|
||||
*/
|
||||
Boolean classTeacherStayawaySelectedBeds(List<Long> bedIds, Long classId);
|
||||
|
||||
/**
|
||||
* 班主任床位互换
|
||||
* 将两个有学生的床位进行互换
|
||||
*
|
||||
* @param sourceBedId 源床位ID
|
||||
* @param targetBedId 目标床位ID
|
||||
* @param classId 班级ID
|
||||
* @return 是否互换成功
|
||||
*/
|
||||
Boolean classTeacherExchangeBeds(Long sourceBedId, Long targetBedId, Long classId);
|
||||
|
||||
/**
|
||||
* 班主任床位移动
|
||||
* 将学生从当前床位移动到指定的空闲床位
|
||||
*
|
||||
* @param sourceBedId 源床位ID
|
||||
* @param targetBedId 目标床位ID
|
||||
* @param classId 班级ID
|
||||
* @return 是否移动成功
|
||||
*/
|
||||
Boolean classTeacherMoveBed(Long sourceBedId, Long targetBedId, Long classId);
|
||||
|
||||
/**
|
||||
* 获取班级所有已入住宿舍的学生床位信息
|
||||
* 包含床位信息(校区名称、宿舍区名称、楼栋名称、房间名称、床位名称)
|
||||
* 和学生信息(学生姓名、学号、性别)
|
||||
*
|
||||
* @param classId 班级ID,可为空
|
||||
* @return 已入住床位详情列表
|
||||
*/
|
||||
List<Object> getClassOccupiedBedDetails(Long classId);
|
||||
|
||||
/**
|
||||
* 获取班级所有未安排学生的床位信息
|
||||
* 包含床位信息(校区名称、宿舍区名称、楼栋名称、房间名称、床位名称)
|
||||
*
|
||||
* @param classId 班级ID,可为空
|
||||
* @return 未安排学生的床位详情列表
|
||||
*/
|
||||
List<Object> getClassUnoccupiedBedDetails(Long classId);
|
||||
}
|
||||
+319
@@ -1873,4 +1873,323 @@ public class XgDormBedStudentServiceImpl implements IXgDormBedStudentService {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 班主任床位互换
|
||||
* 将两个有学生的床位进行互换
|
||||
*/
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public Boolean classTeacherExchangeBeds(Long sourceBedId, Long targetBedId, Long classId) {
|
||||
try {
|
||||
log.info("班主任床位互换开始,源床位ID: {}, 目标床位ID: {}, 班级ID: {}", sourceBedId, targetBedId, classId);
|
||||
|
||||
// 1. 校验参数
|
||||
if (sourceBedId == null || targetBedId == null) {
|
||||
throw new RuntimeException("床位ID不能为空");
|
||||
}
|
||||
if (sourceBedId.equals(targetBedId)) {
|
||||
throw new RuntimeException("不能选择相同的床位进行互换");
|
||||
}
|
||||
|
||||
// 2. 获取源床位和目标床位的分配信息
|
||||
LambdaQueryWrapper<XgDormBedStudent> queryWrapper = Wrappers.lambdaQuery();
|
||||
queryWrapper.in(XgDormBedStudent::getBedId, sourceBedId, targetBedId)
|
||||
.eq(XgDormBedStudent::getDeleted, "0");
|
||||
List<XgDormBedStudent> bedStudents = baseMapper.selectList(queryWrapper);
|
||||
|
||||
if (bedStudents.size() != 2) {
|
||||
throw new RuntimeException("互换床位必须都已分配学生");
|
||||
}
|
||||
|
||||
// 3. 找到对应的分配记录
|
||||
XgDormBedStudent sourceBedStudent = bedStudents.stream()
|
||||
.filter(bs -> bs.getBedId().equals(sourceBedId))
|
||||
.findFirst()
|
||||
.orElseThrow(() -> new RuntimeException("未找到源床位的分配记录"));
|
||||
|
||||
XgDormBedStudent targetBedStudent = bedStudents.stream()
|
||||
.filter(bs -> bs.getBedId().equals(targetBedId))
|
||||
.findFirst()
|
||||
.orElseThrow(() -> new RuntimeException("未找到目标床位的分配记录"));
|
||||
|
||||
// 4. 验证班级权限(如果指定了班级ID)
|
||||
if (classId != null) {
|
||||
if (!classId.equals(sourceBedStudent.getClassId()) && !classId.equals(targetBedStudent.getClassId())) {
|
||||
throw new RuntimeException("没有权限操作这些床位");
|
||||
}
|
||||
}
|
||||
|
||||
// 5. 执行互换:交换两个记录的床位ID
|
||||
Long tempStudentId = sourceBedStudent.getStudentId();
|
||||
Long tempClassId = sourceBedStudent.getClassId();
|
||||
|
||||
// 更新源床位分配记录
|
||||
sourceBedStudent.setStudentId(targetBedStudent.getStudentId());
|
||||
sourceBedStudent.setClassId(targetBedStudent.getClassId());
|
||||
sourceBedStudent.setUpdateTime(new Date());
|
||||
sourceBedStudent.setUpdateBy(LoginHelper.getUserId());
|
||||
|
||||
// 更新目标床位分配记录
|
||||
targetBedStudent.setStudentId(tempStudentId);
|
||||
targetBedStudent.setClassId(tempClassId);
|
||||
targetBedStudent.setUpdateTime(new Date());
|
||||
targetBedStudent.setUpdateBy(LoginHelper.getUserId());
|
||||
|
||||
// 6. 更新数据库
|
||||
baseMapper.updateById(sourceBedStudent);
|
||||
baseMapper.updateById(targetBedStudent);
|
||||
|
||||
log.info("班主任床位互换成功");
|
||||
return true;
|
||||
|
||||
} catch (Exception e) {
|
||||
log.error("班主任床位互换失败", e);
|
||||
throw new RuntimeException("床位互换失败:" + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 班主任床位移动
|
||||
* 将学生从当前床位移动到指定的空闲床位
|
||||
*/
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public Boolean classTeacherMoveBed(Long sourceBedId, Long targetBedId, Long classId) {
|
||||
try {
|
||||
log.info("班主任床位移动开始,源床位ID: {}, 目标床位ID: {}, 班级ID: {}", sourceBedId, targetBedId, classId);
|
||||
|
||||
// 1. 校验参数
|
||||
if (sourceBedId == null || targetBedId == null) {
|
||||
throw new RuntimeException("床位ID不能为空");
|
||||
}
|
||||
if (sourceBedId.equals(targetBedId)) {
|
||||
throw new RuntimeException("不能选择相同的床位进行移动");
|
||||
}
|
||||
|
||||
// 2. 检查源床位是否有学生分配
|
||||
LambdaQueryWrapper<XgDormBedStudent> sourceQueryWrapper = Wrappers.lambdaQuery();
|
||||
sourceQueryWrapper.eq(XgDormBedStudent::getBedId, sourceBedId)
|
||||
.eq(XgDormBedStudent::getDeleted, "0");
|
||||
XgDormBedStudent sourceBedStudent = baseMapper.selectOne(sourceQueryWrapper);
|
||||
|
||||
if (sourceBedStudent == null) {
|
||||
throw new RuntimeException("源床位未分配学生");
|
||||
}
|
||||
|
||||
// 3. 验证班级权限(如果指定了班级ID)
|
||||
if (classId != null && !classId.equals(sourceBedStudent.getClassId())) {
|
||||
throw new RuntimeException("没有权限操作此床位");
|
||||
}
|
||||
|
||||
// 4. 检查目标床位是否空闲
|
||||
LambdaQueryWrapper<XgDormBedStudent> targetQueryWrapper = Wrappers.lambdaQuery();
|
||||
targetQueryWrapper.eq(XgDormBedStudent::getBedId, targetBedId)
|
||||
.eq(XgDormBedStudent::getDeleted, "0");
|
||||
XgDormBedStudent targetBedStudent = baseMapper.selectOne(targetQueryWrapper);
|
||||
|
||||
if (targetBedStudent != null) {
|
||||
throw new RuntimeException("目标床位已被占用");
|
||||
}
|
||||
|
||||
// 5. 检查目标床位是否存在且可用
|
||||
XgDormBed targetBed = xgDormBedMapper.selectById(targetBedId);
|
||||
if (targetBed == null || !"0".equals(targetBed.getDeleted())) {
|
||||
throw new RuntimeException("目标床位不存在");
|
||||
}
|
||||
if (!"0".equals(targetBed.getBedStatus())) {
|
||||
throw new RuntimeException("目标床位不可用(维修中或其他状态)");
|
||||
}
|
||||
|
||||
// 6. 创建目标床位的新分配记录
|
||||
XgDormBedStudent newBedStudent = new XgDormBedStudent();
|
||||
newBedStudent.setBedId(targetBedId);
|
||||
newBedStudent.setStudentId(sourceBedStudent.getStudentId());
|
||||
newBedStudent.setClassId(sourceBedStudent.getClassId());
|
||||
newBedStudent.setCollegeId(sourceBedStudent.getCollegeId());
|
||||
newBedStudent.setCreateTime(new Date());
|
||||
newBedStudent.setCreateBy(LoginHelper.getUserId());
|
||||
newBedStudent.setDeleted("0");
|
||||
|
||||
// 7. 插入新记录
|
||||
baseMapper.insert(newBedStudent);
|
||||
|
||||
// 8. 删除源床位的分配记录
|
||||
sourceBedStudent.setDeleted("1");
|
||||
sourceBedStudent.setUpdateTime(new Date());
|
||||
sourceBedStudent.setUpdateBy(LoginHelper.getUserId());
|
||||
baseMapper.updateById(sourceBedStudent);
|
||||
|
||||
log.info("班主任床位移动成功");
|
||||
return true;
|
||||
|
||||
} catch (Exception e) {
|
||||
log.error("班主任床位移动失败", e);
|
||||
throw new RuntimeException("床位移动失败:" + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取班级所有已入住宿舍的学生床位信息
|
||||
* 包含床位信息(校区名称、宿舍区名称、楼栋名称、房间名称、床位名称)
|
||||
* 和学生信息(学生姓名、学号、性别)
|
||||
*/
|
||||
@Override
|
||||
public List<Object> getClassOccupiedBedDetails(Long classId) {
|
||||
try {
|
||||
log.info("开始获取班级已入住床位详情,班级ID: {}", classId);
|
||||
|
||||
// 查询已分配学生的床位信息
|
||||
List<Map<String, Object>> bedDetails = baseMapper.selectMaps(
|
||||
Wrappers.lambdaQuery(XgDormBedStudent.class)
|
||||
.select(XgDormBedStudent::getBedId, XgDormBedStudent::getStudentId,
|
||||
XgDormBedStudent::getClassId, XgDormBedStudent::getCollegeId)
|
||||
.eq(XgDormBedStudent::getClassId, classId)
|
||||
.isNotNull(XgDormBedStudent::getStudentId)
|
||||
.eq(XgDormBedStudent::getStatus, "0")
|
||||
.eq(XgDormBedStudent::getDeleted, "0"));
|
||||
|
||||
List<Object> result = new ArrayList<>();
|
||||
|
||||
for (Map<String, Object> bedStudent : bedDetails) {
|
||||
Long bedId = (Long) bedStudent.get("bed_id");
|
||||
Long studentId = (Long) bedStudent.get("student_id");
|
||||
|
||||
// 查询床位详细信息
|
||||
XgDormBed bed = xgDormBedMapper.selectById(bedId);
|
||||
if (bed == null)
|
||||
continue;
|
||||
|
||||
XgDormRoom room = xgDormRoomMapper.selectById(bed.getRoomId());
|
||||
if (room == null)
|
||||
continue;
|
||||
|
||||
XgDormBuilding building = xgDormBuildingMapper.selectById(room.getBuildingId());
|
||||
if (building == null)
|
||||
continue;
|
||||
|
||||
XgDormArea area = xgDormAreaMapper.selectById(building.getAreaId());
|
||||
if (area == null)
|
||||
continue;
|
||||
|
||||
XgDormCampus campus = xgDormCampusMapper.selectById(area.getCampusId());
|
||||
if (campus == null)
|
||||
continue;
|
||||
|
||||
// 查询学生信息
|
||||
XgStudentMsg student = xgStudentMsgMapper.selectById(studentId);
|
||||
if (student == null)
|
||||
continue;
|
||||
|
||||
// 组装结果数据
|
||||
Map<String, Object> detailInfo = new LinkedHashMap<>();
|
||||
|
||||
// 床位信息
|
||||
detailInfo.put("bedId", bedId);
|
||||
detailInfo.put("campusName", campus.getCampusName());
|
||||
detailInfo.put("areaName", area.getAreaName());
|
||||
detailInfo.put("buildingName", building.getBuildingName());
|
||||
detailInfo.put("roomName", room.getRoomName());
|
||||
detailInfo.put("bedName", bed.getBedName());
|
||||
detailInfo.put("bedType", bed.getBedType());
|
||||
|
||||
// 床位性别类型(基于楼栋类型)
|
||||
String bedGenderType = building.getBuildingType(); // 1男生楼 2女生楼 3混合楼
|
||||
detailInfo.put("bedGenderType", bedGenderType);
|
||||
|
||||
// 学生信息
|
||||
detailInfo.put("studentId", studentId);
|
||||
detailInfo.put("studentName", student.getName());
|
||||
detailInfo.put("studentNo", student.getStudentNo());
|
||||
detailInfo.put("gender", student.getGender());
|
||||
|
||||
result.add(detailInfo);
|
||||
}
|
||||
|
||||
log.info("获取班级已入住床位详情成功,共{}条记录", result.size());
|
||||
return result;
|
||||
|
||||
} catch (Exception e) {
|
||||
log.error("获取班级已入住床位详情失败", e);
|
||||
return Collections.emptyList();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取班级所有未安排学生的床位信息
|
||||
* 包含床位信息(校区名称、宿舍区名称、楼栋名称、房间名称、床位名称)
|
||||
*/
|
||||
@Override
|
||||
public List<Object> getClassUnoccupiedBedDetails(Long classId) {
|
||||
try {
|
||||
log.info("开始获取班级未分配学生床位详情,班级ID: {}", classId);
|
||||
|
||||
// 查询分配给班级但未分配学生的床位信息
|
||||
List<Map<String, Object>> bedDetails = baseMapper.selectMaps(
|
||||
Wrappers.lambdaQuery(XgDormBedStudent.class)
|
||||
.select(XgDormBedStudent::getBedId, XgDormBedStudent::getClassId,
|
||||
XgDormBedStudent::getCollegeId)
|
||||
.eq(XgDormBedStudent::getClassId, classId)
|
||||
.isNull(XgDormBedStudent::getStudentId)
|
||||
.eq(XgDormBedStudent::getStatus, "0")
|
||||
.eq(XgDormBedStudent::getDeleted, "0"));
|
||||
|
||||
List<Object> result = new ArrayList<>();
|
||||
|
||||
for (Map<String, Object> bedStudent : bedDetails) {
|
||||
Long bedId = (Long) bedStudent.get("bed_id");
|
||||
|
||||
// 查询床位详细信息
|
||||
XgDormBed bed = xgDormBedMapper.selectById(bedId);
|
||||
if (bed == null)
|
||||
continue;
|
||||
|
||||
// 确保床位可用
|
||||
if (!"1".equals(bed.getBedStatus()) || !"0".equals(bed.getDeleted())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
XgDormRoom room = xgDormRoomMapper.selectById(bed.getRoomId());
|
||||
if (room == null)
|
||||
continue;
|
||||
|
||||
XgDormBuilding building = xgDormBuildingMapper.selectById(room.getBuildingId());
|
||||
if (building == null)
|
||||
continue;
|
||||
|
||||
XgDormArea area = xgDormAreaMapper.selectById(building.getAreaId());
|
||||
if (area == null)
|
||||
continue;
|
||||
|
||||
XgDormCampus campus = xgDormCampusMapper.selectById(area.getCampusId());
|
||||
if (campus == null)
|
||||
continue;
|
||||
|
||||
// 组装结果数据
|
||||
Map<String, Object> detailInfo = new LinkedHashMap<>();
|
||||
|
||||
// 床位信息
|
||||
detailInfo.put("bedId", bedId);
|
||||
detailInfo.put("campusName", campus.getCampusName());
|
||||
detailInfo.put("areaName", area.getAreaName());
|
||||
detailInfo.put("buildingName", building.getBuildingName());
|
||||
detailInfo.put("roomName", room.getRoomName());
|
||||
detailInfo.put("bedName", bed.getBedName());
|
||||
detailInfo.put("bedType", bed.getBedType());
|
||||
|
||||
// 床位性别类型(基于楼栋类型)
|
||||
String bedGenderType = building.getBuildingType(); // 1男生楼 2女生楼 3混合楼
|
||||
detailInfo.put("bedGenderType", bedGenderType);
|
||||
|
||||
result.add(detailInfo);
|
||||
}
|
||||
|
||||
log.info("获取班级未分配学生床位详情成功,共{}条记录", result.size());
|
||||
return result;
|
||||
|
||||
} catch (Exception e) {
|
||||
log.error("获取班级未分配学生床位详情失败", e);
|
||||
return Collections.emptyList();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -215,3 +215,60 @@ export const classTeacherStayawaySelectedBeds = (bedIds: number[], classId?: str
|
||||
params: { classId }
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 班主任床位互换
|
||||
* 将两个有学生的床位进行互换
|
||||
* @param sourceBedId 源床位ID
|
||||
* @param targetBedId 目标床位ID
|
||||
* @param classId 班级ID,可为空
|
||||
*/
|
||||
export const classTeacherExchangeBeds = (sourceBedId: number, targetBedId: number, classId?: string | number) => {
|
||||
return request({
|
||||
url: '/dormBedStudent/dormBedStudent/classTeacherExchangeBeds',
|
||||
method: 'post',
|
||||
params: { sourceBedId, targetBedId, classId }
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 班主任床位移动
|
||||
* 将学生从当前床位移动到指定的空闲床位
|
||||
* @param sourceBedId 源床位ID
|
||||
* @param targetBedId 目标床位ID
|
||||
* @param classId 班级ID,可为空
|
||||
*/
|
||||
export const classTeacherMoveBed = (sourceBedId: number, targetBedId: number, classId?: string | number) => {
|
||||
return request({
|
||||
url: '/dormBedStudent/dormBedStudent/classTeacherMoveBed',
|
||||
method: 'post',
|
||||
params: { sourceBedId, targetBedId, classId }
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 获取班级所有已入住宿舍的学生床位信息
|
||||
* 包含床位信息(校区名称、宿舍区名称、楼栋名称、房间名称、床位名称)
|
||||
* 和学生信息(学生姓名、学号、性别)
|
||||
* @param classId 班级ID,可为空
|
||||
*/
|
||||
export const getClassOccupiedBedDetails = (classId?: string | number) => {
|
||||
return request({
|
||||
url: '/dormBedStudent/dormBedStudent/getClassOccupiedBedDetails',
|
||||
method: 'get',
|
||||
params: { classId }
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 获取班级所有未安排学生的床位信息
|
||||
* 包含床位信息(校区名称、宿舍区名称、楼栋名称、房间名称、床位名称)
|
||||
* @param classId 班级ID,可为空
|
||||
*/
|
||||
export const getClassUnoccupiedBedDetails = (classId?: string | number) => {
|
||||
return request({
|
||||
url: '/dormBedStudent/dormBedStudent/getClassUnoccupiedBedDetails',
|
||||
method: 'get',
|
||||
params: { classId }
|
||||
});
|
||||
};
|
||||
@@ -100,6 +100,7 @@
|
||||
<el-button type="info" icon="Sort" size="small" @click="handleStudentNoAllocation">按学号分配</el-button> -->
|
||||
<el-button type="warning" icon="RefreshLeft" size="small" @click="handleRecallBeds">收回选中床位</el-button>
|
||||
<el-button type="danger" icon="House" size="small" @click="handleStayawayBeds">退宿选中床位</el-button>
|
||||
<el-button type="info" icon="Switch" size="small" @click="handleBedTransfer">调宿</el-button>
|
||||
</el-col>
|
||||
<el-col :span="12" style="text-align: right">
|
||||
<el-button
|
||||
@@ -294,6 +295,17 @@
|
||||
:parent-class-info="currentClassInfo"
|
||||
@success="handleAllocationSuccess"
|
||||
/>
|
||||
|
||||
<!-- 调宿管理对话框 -->
|
||||
<bed-transfer-dialog
|
||||
v-model="bedTransferDialog.visible"
|
||||
:title="bedTransferDialog.title"
|
||||
:selected-bed="bedTransferDialog.selectedBed"
|
||||
:building-info="bedTransferDialog.buildingInfo"
|
||||
:class-id="activeClassId"
|
||||
:parent-class-info="currentClassInfo"
|
||||
@success="handleAllocationSuccess"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -325,6 +337,7 @@ import ElMessageBox from 'element-plus/es/components/message-box/index';
|
||||
|
||||
// 引入子组件
|
||||
import SelectiveAllocationDialog from './components/SelectiveAllocationDialog.vue';
|
||||
import BedTransferDialog from './components/BedTransferDialog.vue';
|
||||
|
||||
// 组件状态
|
||||
const dormTreeRef = ref();
|
||||
@@ -411,6 +424,14 @@ const selectiveAllocationDialog = reactive({
|
||||
buildingInfo: undefined as DormBuildingTreeVO | undefined
|
||||
});
|
||||
|
||||
// 调宿对话框
|
||||
const bedTransferDialog = reactive({
|
||||
visible: false,
|
||||
title: '调宿管理',
|
||||
selectedBed: undefined as any | undefined,
|
||||
buildingInfo: undefined as DormBuildingTreeVO | undefined
|
||||
});
|
||||
|
||||
// 表格最大高度计算
|
||||
const tableMaxHeight = computed(() => {
|
||||
// 根据不同屏幕尺寸动态调整预留空间
|
||||
@@ -814,6 +835,31 @@ const handleStayawayBeds = async () => {
|
||||
}
|
||||
};
|
||||
|
||||
/** 调宿管理 */
|
||||
const handleBedTransfer = () => {
|
||||
if (!selectedBuilding.value) {
|
||||
ElMessage.warning('请先选择宿舍楼');
|
||||
return;
|
||||
}
|
||||
|
||||
// 获取选中的已分配床位
|
||||
const selectedAllocatedBeds = selectedRows.value.filter((row) => row.isBed && row.studentId);
|
||||
|
||||
if (selectedAllocatedBeds.length === 0) {
|
||||
ElMessage.warning('请先勾选要调宿的床位(必须是已分配学生的床位)!');
|
||||
return;
|
||||
}
|
||||
|
||||
if (selectedAllocatedBeds.length > 1) {
|
||||
ElMessage.warning('调宿操作一次只能选择一个床位!');
|
||||
return;
|
||||
}
|
||||
|
||||
bedTransferDialog.selectedBed = selectedAllocatedBeds[0];
|
||||
bedTransferDialog.buildingInfo = selectedBuilding.value;
|
||||
bedTransferDialog.visible = true;
|
||||
};
|
||||
|
||||
/** 分配成功回调 */
|
||||
const handleAllocationSuccess = () => {
|
||||
// 清除缓存,确保数据刷新
|
||||
|
||||
@@ -0,0 +1,702 @@
|
||||
<template>
|
||||
<el-dialog v-model="dialogVisible" :title="title" width="1000px" :before-close="handleClose" destroy-on-close class="bed-transfer-dialog">
|
||||
<div class="transfer-container">
|
||||
<!-- 当前选中床位信息 -->
|
||||
<div class="current-bed-info">
|
||||
<div class="info-header">
|
||||
<h3 class="info-title">
|
||||
<el-icon><Avatar /></el-icon>
|
||||
当前选中床位
|
||||
</h3>
|
||||
</div>
|
||||
|
||||
<el-card v-if="props.selectedBed" shadow="hover" class="bed-card">
|
||||
<div class="bed-info-grid">
|
||||
<div class="info-item">
|
||||
<span class="label">学生姓名:</span>
|
||||
<span class="value">{{ props.selectedBed.studentName }}</span>
|
||||
</div>
|
||||
<div class="info-item">
|
||||
<span class="label">学号:</span>
|
||||
<span class="value">{{ props.selectedBed.studentNo }}</span>
|
||||
</div>
|
||||
<div class="info-item">
|
||||
<span class="label">性别:</span>
|
||||
<el-tag v-if="props.selectedBed.studentGender === '0'" type="primary" size="small">男</el-tag>
|
||||
<el-tag v-else-if="props.selectedBed.studentGender === '1'" class="female-tag" size="small">女</el-tag>
|
||||
</div>
|
||||
<!-- <div class="info-item">
|
||||
<span class="label">校区:</span>
|
||||
<span class="value">{{ props.selectedBed.campusName || '未知' }}</span>
|
||||
</div>
|
||||
<div class="info-item">
|
||||
<span class="label">区域:</span>
|
||||
<span class="value">{{ props.selectedBed.areaName || '未知' }}</span>
|
||||
</div>
|
||||
<div class="info-item">
|
||||
<span class="label">楼栋:</span>
|
||||
<span class="value">{{ props.selectedBed.buildingName || '未知' }}</span>
|
||||
</div> -->
|
||||
<div class="info-item">
|
||||
<span class="label">房间号:</span>
|
||||
<span class="value">{{ props.selectedBed.roomName }}</span>
|
||||
</div>
|
||||
<div class="info-item">
|
||||
<span class="label">床位号:</span>
|
||||
<span class="value">{{ props.selectedBed.bedName }}</span>
|
||||
</div>
|
||||
<div class="info-item">
|
||||
<span class="label">床位类型:</span>
|
||||
<el-tag v-if="props.selectedBed.bedType === '1'" type="success" size="small">下铺</el-tag>
|
||||
<el-tag v-else-if="props.selectedBed.bedType === '2'" type="warning" size="small">上铺</el-tag>
|
||||
<el-tag v-else-if="props.selectedBed.bedType === '3'" type="danger" size="small">中铺</el-tag>
|
||||
<el-tag v-else type="info" size="small">独立床</el-tag>
|
||||
</div>
|
||||
</div>
|
||||
</el-card>
|
||||
</div>
|
||||
|
||||
<!-- 调宿模式选择 -->
|
||||
<div class="transfer-mode">
|
||||
<div class="mode-header">
|
||||
<h3 class="mode-title">
|
||||
<el-icon><Switch /></el-icon>
|
||||
调宿模式
|
||||
</h3>
|
||||
</div>
|
||||
|
||||
<el-radio-group v-model="transferMode" @change="handleModeChange">
|
||||
<el-radio value="exchange">
|
||||
<el-icon><Refresh /></el-icon>
|
||||
床位互换
|
||||
<span class="mode-desc">与另一个有学生的床位互换</span>
|
||||
</el-radio>
|
||||
<el-radio value="move">
|
||||
<el-icon><Right /></el-icon>
|
||||
移动床位
|
||||
<span class="mode-desc">移动到一个空闲的床位</span>
|
||||
</el-radio>
|
||||
</el-radio-group>
|
||||
</div>
|
||||
|
||||
<!-- 目标床位选择区域 -->
|
||||
<div class="target-bed-area">
|
||||
<div class="area-header">
|
||||
<h3 class="area-title">
|
||||
<el-icon><House /></el-icon>
|
||||
目标床位选择
|
||||
<el-tag v-if="transferMode === 'exchange'" type="warning" size="small">请选择有学生的床位</el-tag>
|
||||
<el-tag v-else type="success" size="small">请选择空闲床位</el-tag>
|
||||
<el-tag v-if="props.selectedBed?.studentGender" type="info" size="small">
|
||||
已过滤:仅显示{{ props.selectedBed.studentGender === '0' ? '男生' : '女生' }}可住床位
|
||||
</el-tag>
|
||||
</h3>
|
||||
<div class="stats">
|
||||
<span v-if="selectedTargetBed"> 已选择目标床位:{{ selectedTargetBed.roomName }} - {{ selectedTargetBed.bedName }} </span>
|
||||
<span v-else class="text-gray-500">请选择目标床位</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="search-bar">
|
||||
<el-input v-model="bedSearchKey" placeholder="搜索房间号、床位号" prefix-icon="Search" clearable @input="handleBedSearch" />
|
||||
</div>
|
||||
|
||||
<div class="bed-list" v-loading="bedLoading">
|
||||
<el-table
|
||||
ref="bedTableRef"
|
||||
:data="filteredBedList"
|
||||
row-key="id"
|
||||
height="300"
|
||||
max-height="300"
|
||||
:tree-props="{ children: 'children', hasChildren: 'hasChildren' }"
|
||||
:expand-row-keys="expandRowKeys"
|
||||
@expand-change="handleExpandChange"
|
||||
@current-change="handleTargetBedSelection"
|
||||
highlight-current-row
|
||||
>
|
||||
<el-table-column prop="roomName" label="房间/床位" min-width="180">
|
||||
<template #default="scope">
|
||||
<span v-if="!scope.row.isBed" class="inline-flex items-center gap-1 whitespace-nowrap">
|
||||
<el-icon><House /></el-icon>
|
||||
{{ scope.row.roomName }}
|
||||
</span>
|
||||
<span v-else class="inline-flex items-center gap-1 whitespace-nowrap">
|
||||
<el-icon><Avatar /></el-icon>
|
||||
{{ scope.row.bedName }}
|
||||
</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="校区" width="100" align="center">
|
||||
<template #default="scope">
|
||||
<span v-if="scope.row.campusName" class="text-gray-700">{{ scope.row.campusName }}</span>
|
||||
<span v-else class="text-gray-400">—</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="楼栋" width="120" align="center">
|
||||
<template #default="scope">
|
||||
<span v-if="scope.row.buildingName" class="text-gray-700">{{ scope.row.buildingName }}</span>
|
||||
<span v-else class="text-gray-400">—</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="类型" width="80" align="center">
|
||||
<template #default="scope">
|
||||
<template v-if="scope.row.isBed">
|
||||
<el-tag v-if="scope.row.bedType === '1'" type="success" size="small">下铺</el-tag>
|
||||
<el-tag v-if="scope.row.bedType === '2'" type="warning" size="small">上铺</el-tag>
|
||||
<el-tag v-if="scope.row.bedType === '3'" type="danger" size="small">中铺</el-tag>
|
||||
<el-tag v-if="!scope.row.bedType || scope.row.bedType === '4'" type="info" size="small">独立床</el-tag>
|
||||
</template>
|
||||
<span v-else class="text-gray-400">
|
||||
<span>{{ scope.row.roomType === '1' ? '标准间' : scope.row.roomType === '2' ? '单人间' : '套间' }}</span>
|
||||
</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="性别" width="80" align="center">
|
||||
<template #default="scope">
|
||||
<template v-if="scope.row.isBed">
|
||||
<el-tag v-if="scope.row.bedGenderType === '1'" type="primary" size="small">男生</el-tag>
|
||||
<el-tag v-if="scope.row.bedGenderType === '2'" type="danger" size="small">女生</el-tag>
|
||||
<el-tag v-if="scope.row.bedGenderType === '3'" type="info" size="small">混合</el-tag>
|
||||
</template>
|
||||
<template v-else>
|
||||
<el-tag v-if="scope.row.buildingType === '1'" type="primary" size="small">男生楼</el-tag>
|
||||
<el-tag v-if="scope.row.buildingType === '2'" type="danger" size="small">女生楼</el-tag>
|
||||
<el-tag v-if="scope.row.buildingType === '3'" type="info" size="small">混合楼</el-tag>
|
||||
</template>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="状态" width="80" align="center">
|
||||
<template #default="scope">
|
||||
<template v-if="scope.row.isBed">
|
||||
<el-tag v-if="scope.row.studentId" type="warning" size="small">已分配</el-tag>
|
||||
<el-tag v-else type="success" size="small">空闲</el-tag>
|
||||
</template>
|
||||
<span v-else class="text-gray-400">—</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="学生" width="100" align="center">
|
||||
<template #default="scope">
|
||||
<span v-if="scope.row.isBed && scope.row.studentName">{{ scope.row.studentName }}</span>
|
||||
<span v-else-if="scope.row.isBed" class="text-gray-400">—</span>
|
||||
<span v-else class="text-gray-400">—</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="学号" width="100" align="center">
|
||||
<template #default="scope">
|
||||
<span v-if="scope.row.isBed && scope.row.studentNo">{{ scope.row.studentNo }}</span>
|
||||
<span v-else-if="scope.row.isBed" class="text-gray-400">—</span>
|
||||
<span v-else class="text-gray-400">—</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<!-- <el-table-column label="性别" width="60" align="center">
|
||||
<template #default="scope">
|
||||
<template v-if="scope.row.isBed && scope.row.studentGender !== undefined">
|
||||
<el-tag v-if="scope.row.studentGender === '0'" type="primary" size="small">男</el-tag>
|
||||
<el-tag v-else-if="scope.row.studentGender === '1'" class="female-tag" size="small">女</el-tag>
|
||||
</template>
|
||||
<span v-else-if="scope.row.isBed" class="text-gray-400">—</span>
|
||||
<span v-else class="text-gray-400">—</span>
|
||||
</template>
|
||||
</el-table-column> -->
|
||||
</el-table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<template #footer>
|
||||
<div class="dialog-footer">
|
||||
<el-button @click="handleClose">取消</el-button>
|
||||
<el-button type="primary" @click="handleConfirm" :disabled="!selectedTargetBed" :loading="confirmLoading">
|
||||
确认{{ transferMode === 'exchange' ? '互换' : '移动' }}
|
||||
</el-button>
|
||||
</div>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, reactive, computed, watch, nextTick } from 'vue';
|
||||
import { Avatar, House, Switch, Refresh, Right } from '@element-plus/icons-vue';
|
||||
import ElMessage from 'element-plus/es/components/message/index';
|
||||
import ElMessageBox from 'element-plus/es/components/message-box/index';
|
||||
// 导入调宿相关的API方法
|
||||
import { getClassTeacherBedDetails, classTeacherExchangeBeds, classTeacherMoveBed } from '@/api/xg/xgss/dormBedStudent/dormBedStudent';
|
||||
// @ts-expect-error 新添加的API方法,类型定义可能尚未更新
|
||||
import { getClassOccupiedBedDetails, getClassUnoccupiedBedDetails } from '@/api/xg/xgss/dormBedStudent/dormBedStudent';
|
||||
|
||||
// 定义 props
|
||||
const props = defineProps<{
|
||||
title?: string;
|
||||
selectedBed?: any;
|
||||
buildingInfo?: any;
|
||||
classId?: string;
|
||||
parentClassInfo?: any;
|
||||
}>();
|
||||
|
||||
// 定义 emits
|
||||
const emit = defineEmits<{
|
||||
'update:modelValue': [value: boolean];
|
||||
success: [];
|
||||
}>();
|
||||
|
||||
// 定义 model
|
||||
const dialogVisible = defineModel<boolean>({ default: false });
|
||||
|
||||
// 状态变量
|
||||
const transferMode = ref<'exchange' | 'move'>('exchange'); // 调宿模式
|
||||
const selectedTargetBed = ref<any>(null); // 选中的目标床位
|
||||
const bedSearchKey = ref(''); // 床位搜索关键字
|
||||
const bedLoading = ref(false); // 床位数据加载状态
|
||||
const confirmLoading = ref(false); // 确认按钮加载状态
|
||||
const expandRowKeys = ref<string[]>([]); // 展开的房间行
|
||||
const bedTableRef = ref(); // 床位表格引用
|
||||
|
||||
// 床位数据
|
||||
const bedList = ref<any[]>([]);
|
||||
|
||||
// 过滤后的床位列表
|
||||
const filteredBedList = computed(() => {
|
||||
if (!bedSearchKey.value) {
|
||||
return bedList.value;
|
||||
}
|
||||
|
||||
const keyword = bedSearchKey.value.toLowerCase();
|
||||
return bedList.value.filter((room) => {
|
||||
if (room.roomName.toLowerCase().includes(keyword)) {
|
||||
return true;
|
||||
}
|
||||
if (room.children) {
|
||||
const hasMatchBed = room.children.some((bed: any) => bed.bedName.toLowerCase().includes(keyword));
|
||||
if (hasMatchBed) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
});
|
||||
});
|
||||
|
||||
// 监听对话框显示状态
|
||||
watch(dialogVisible, (newVal) => {
|
||||
if (newVal) {
|
||||
loadBedData();
|
||||
} else {
|
||||
resetDialog();
|
||||
}
|
||||
});
|
||||
|
||||
// 监听调宿模式变化
|
||||
const handleModeChange = () => {
|
||||
selectedTargetBed.value = null;
|
||||
bedTableRef.value?.setCurrentRow(null);
|
||||
|
||||
// 根据新的调宿模式重新加载床位数据
|
||||
loadBedData();
|
||||
};
|
||||
|
||||
// 加载床位数据
|
||||
const loadBedData = async () => {
|
||||
if (!props.classId) return;
|
||||
|
||||
bedLoading.value = true;
|
||||
try {
|
||||
let response;
|
||||
if (transferMode.value === 'exchange') {
|
||||
// 互换模式:获取已分配学生的床位信息
|
||||
response = await getClassOccupiedBedDetails(props.classId);
|
||||
} else {
|
||||
// 移动模式:获取未分配学生的床位信息
|
||||
response = await getClassUnoccupiedBedDetails(props.classId);
|
||||
}
|
||||
|
||||
let rawData = response.data || [];
|
||||
|
||||
// 在互换模式下,过滤掉当前选中的床位
|
||||
if (transferMode.value === 'exchange' && props.selectedBed?.id) {
|
||||
const originalCount = rawData.length;
|
||||
rawData = rawData.filter((bed: any) => bed.bedId !== props.selectedBed.id);
|
||||
const filteredCount = rawData.length;
|
||||
console.log(`互换模式过滤当前床位:原始床位 ${originalCount} 个,过滤后 ${filteredCount} 个`);
|
||||
}
|
||||
|
||||
// 根据当前学生性别过滤床位数据
|
||||
const filteredData = filterBedsByGender(rawData);
|
||||
|
||||
// 转换数据格式为树形结构(按房间分组)
|
||||
const processedData = convertToBedTreeData(filteredData);
|
||||
bedList.value = processedData;
|
||||
|
||||
// 自动展开所有房间
|
||||
await nextTick();
|
||||
expandRowKeys.value = processedData.map((room: any) => String(room.id));
|
||||
} catch (error) {
|
||||
console.error('加载床位数据失败', error);
|
||||
ElMessage.error('加载床位数据失败');
|
||||
} finally {
|
||||
bedLoading.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
// 根据当前学生性别过滤床位数据
|
||||
const filterBedsByGender = (bedDetails: any[]) => {
|
||||
if (!props.selectedBed?.studentGender) {
|
||||
console.warn('当前学生性别信息缺失,跳过性别过滤');
|
||||
return bedDetails; // 如果没有学生性别信息,不进行过滤
|
||||
}
|
||||
|
||||
const currentStudentGender = props.selectedBed.studentGender; // '0'男 '1'女
|
||||
const originalCount = bedDetails.length;
|
||||
|
||||
const filteredBeds = bedDetails.filter((bed: any) => {
|
||||
const bedGenderType = bed.bedGenderType; // '1'男生楼 '2'女生楼 '3'混合楼
|
||||
|
||||
// 混合楼的床位可以分配给任何性别的学生
|
||||
if (bedGenderType === '3') {
|
||||
return true;
|
||||
}
|
||||
|
||||
// 男学生只能分配到男生楼的床位
|
||||
if (currentStudentGender === '0' && bedGenderType === '1') {
|
||||
return true;
|
||||
}
|
||||
|
||||
// 女学生只能分配到女生楼的床位
|
||||
if (currentStudentGender === '1' && bedGenderType === '2') {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
const filteredCount = filteredBeds.length;
|
||||
console.log(`性别过滤结果:原始床位 ${originalCount} 个,过滤后 ${filteredCount} 个(${currentStudentGender === '0' ? '男学生' : '女学生'})`);
|
||||
|
||||
return filteredBeds;
|
||||
};
|
||||
|
||||
// 将床位详情数据转换为树形结构
|
||||
const convertToBedTreeData = (bedDetails: any[]) => {
|
||||
const roomMap = new Map();
|
||||
|
||||
bedDetails.forEach((bed: any) => {
|
||||
const roomKey = `${bed.buildingName}-${bed.roomName}`;
|
||||
|
||||
if (!roomMap.has(roomKey)) {
|
||||
roomMap.set(roomKey, {
|
||||
id: `room_${bed.bedId}_${Math.random()}`, // 使用随机ID避免冲突
|
||||
roomName: bed.roomName,
|
||||
buildingName: bed.buildingName,
|
||||
areaName: bed.areaName,
|
||||
campusName: bed.campusName,
|
||||
roomType: '1', // 默认标准间
|
||||
buildingType: bed.bedGenderType, // 楼栋性别类型
|
||||
isBed: false,
|
||||
children: []
|
||||
});
|
||||
}
|
||||
|
||||
const room = roomMap.get(roomKey);
|
||||
room.children.push({
|
||||
id: bed.bedId,
|
||||
bedName: bed.bedName,
|
||||
bedType: bed.bedType || '0',
|
||||
bedGenderType: bed.bedGenderType, // 床位性别类型:1男生楼 2女生楼 3混合楼
|
||||
studentId: bed.studentId || null,
|
||||
studentName: bed.studentName || null,
|
||||
studentNo: bed.studentNo || null,
|
||||
studentGender: bed.gender || null,
|
||||
roomName: bed.roomName,
|
||||
buildingName: bed.buildingName,
|
||||
areaName: bed.areaName,
|
||||
campusName: bed.campusName,
|
||||
isBed: true
|
||||
});
|
||||
});
|
||||
|
||||
return Array.from(roomMap.values());
|
||||
};
|
||||
|
||||
// 处理床位搜索
|
||||
const handleBedSearch = () => {
|
||||
// 搜索后自动展开所有房间
|
||||
nextTick(() => {
|
||||
if (filteredBedList.value.length > 0) {
|
||||
expandRowKeys.value = filteredBedList.value.map((room) => String(room.id));
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
// 处理行展开
|
||||
const handleExpandChange = (row: any, expanded: boolean) => {
|
||||
const expandKey = String(row.id);
|
||||
if (expanded) {
|
||||
if (!expandRowKeys.value.includes(expandKey)) {
|
||||
expandRowKeys.value.push(expandKey);
|
||||
}
|
||||
} else {
|
||||
const index = expandRowKeys.value.indexOf(expandKey);
|
||||
if (index !== -1) {
|
||||
expandRowKeys.value.splice(index, 1);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// 处理目标床位选择
|
||||
const handleTargetBedSelection = (currentRow: any) => {
|
||||
if (!currentRow || !currentRow.isBed) {
|
||||
selectedTargetBed.value = null;
|
||||
return;
|
||||
}
|
||||
|
||||
// 不能选择当前床位自己
|
||||
if (currentRow.id === props.selectedBed?.id) {
|
||||
ElMessage.warning('不能选择当前床位自己');
|
||||
bedTableRef.value?.setCurrentRow(null);
|
||||
selectedTargetBed.value = null;
|
||||
return;
|
||||
}
|
||||
|
||||
// 根据模式验证选择
|
||||
if (transferMode.value === 'exchange') {
|
||||
// 互换模式:必须选择有学生的床位
|
||||
if (!currentRow.studentId) {
|
||||
ElMessage.warning('互换模式下,请选择有学生的床位');
|
||||
bedTableRef.value?.setCurrentRow(null);
|
||||
selectedTargetBed.value = null;
|
||||
return;
|
||||
}
|
||||
|
||||
// 互换模式:验证两个学生的性别是否适合各自的目标床位
|
||||
const currentStudentGender = props.selectedBed?.studentGender;
|
||||
const targetStudentGender = currentRow.studentGender;
|
||||
const currentBedGenderType = props.selectedBed?.bedGenderType;
|
||||
const targetBedGenderType = currentRow.bedGenderType;
|
||||
|
||||
if (currentStudentGender && targetStudentGender && currentBedGenderType && targetBedGenderType) {
|
||||
// 检查当前学生是否适合目标床位
|
||||
const currentStudentCanUseTargetBed =
|
||||
targetBedGenderType === '3' || // 混合楼
|
||||
(currentStudentGender === '0' && targetBedGenderType === '1') || // 男学生到男生楼
|
||||
(currentStudentGender === '1' && targetBedGenderType === '2'); // 女学生到女生楼
|
||||
|
||||
// 检查目标学生是否适合当前床位
|
||||
const targetStudentCanUseCurrentBed =
|
||||
currentBedGenderType === '3' || // 混合楼
|
||||
(targetStudentGender === '0' && currentBedGenderType === '1') || // 男学生到男生楼
|
||||
(targetStudentGender === '1' && currentBedGenderType === '2'); // 女学生到女生楼
|
||||
|
||||
if (!currentStudentCanUseTargetBed || !targetStudentCanUseCurrentBed) {
|
||||
const currentGenderText = currentStudentGender === '0' ? '男生' : '女生';
|
||||
const targetGenderText = targetStudentGender === '0' ? '男生' : '女生';
|
||||
ElMessage.warning(`性别不匹配:${currentGenderText}和${targetGenderText}无法在这两个床位间互换`);
|
||||
bedTableRef.value?.setCurrentRow(null);
|
||||
selectedTargetBed.value = null;
|
||||
return;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// 移动模式:必须选择空闲床位
|
||||
if (currentRow.studentId) {
|
||||
ElMessage.warning('移动模式下,请选择空闲床位');
|
||||
bedTableRef.value?.setCurrentRow(null);
|
||||
selectedTargetBed.value = null;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
selectedTargetBed.value = currentRow;
|
||||
};
|
||||
|
||||
// 确认操作
|
||||
const handleConfirm = async () => {
|
||||
if (!selectedTargetBed.value) {
|
||||
ElMessage.warning('请先选择目标床位');
|
||||
return;
|
||||
}
|
||||
|
||||
confirmLoading.value = true;
|
||||
try {
|
||||
const confirmMessage =
|
||||
transferMode.value === 'exchange'
|
||||
? `确认将 ${props.selectedBed.studentName}(${props.selectedBed.roomName}-${props.selectedBed.bedName})与 ${selectedTargetBed.value.studentName}(${selectedTargetBed.value.roomName}-${selectedTargetBed.value.bedName})进行床位互换吗?`
|
||||
: `确认将 ${props.selectedBed.studentName}(${props.selectedBed.roomName}-${props.selectedBed.bedName})移动到 ${selectedTargetBed.value.roomName}-${selectedTargetBed.value.bedName} 吗?`;
|
||||
|
||||
await ElMessageBox.confirm(confirmMessage, '确认调宿', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
});
|
||||
|
||||
// 调用API
|
||||
if (transferMode.value === 'exchange') {
|
||||
await classTeacherExchangeBeds(props.selectedBed.id, selectedTargetBed.value.id, props.classId);
|
||||
} else {
|
||||
await classTeacherMoveBed(props.selectedBed.id, selectedTargetBed.value.id, props.classId);
|
||||
}
|
||||
|
||||
ElMessage.success(`${transferMode.value === 'exchange' ? '互换' : '移动'}成功`);
|
||||
emit('success');
|
||||
handleClose();
|
||||
} catch (error: any) {
|
||||
if (error !== 'cancel') {
|
||||
console.error('调宿操作失败', error);
|
||||
ElMessage.error('调宿操作失败');
|
||||
}
|
||||
} finally {
|
||||
confirmLoading.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
// 关闭对话框
|
||||
const handleClose = () => {
|
||||
dialogVisible.value = false;
|
||||
};
|
||||
|
||||
// 重置对话框
|
||||
const resetDialog = () => {
|
||||
transferMode.value = 'exchange';
|
||||
selectedTargetBed.value = null;
|
||||
bedSearchKey.value = '';
|
||||
bedList.value = [];
|
||||
expandRowKeys.value = [];
|
||||
confirmLoading.value = false;
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.bed-transfer-dialog {
|
||||
min-height: 600px;
|
||||
}
|
||||
|
||||
.transfer-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 20px;
|
||||
}
|
||||
|
||||
.current-bed-info .info-header,
|
||||
.transfer-mode .mode-header,
|
||||
.target-bed-area .area-header {
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.info-title,
|
||||
.mode-title,
|
||||
.area-title {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
font-size: 16px;
|
||||
font-weight: bold;
|
||||
color: var(--el-color-primary);
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.bed-card {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.bed-info-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.info-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.info-item .label {
|
||||
font-weight: 500;
|
||||
color: #666;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.info-item .value {
|
||||
font-weight: 600;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.transfer-mode {
|
||||
border: 1px solid #e4e7ed;
|
||||
border-radius: 4px;
|
||||
padding: 16px;
|
||||
background-color: #fafafa;
|
||||
}
|
||||
|
||||
.transfer-mode :deep(.el-radio) {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 12px;
|
||||
padding: 8px;
|
||||
border-radius: 4px;
|
||||
transition: all 0.3s;
|
||||
}
|
||||
|
||||
.transfer-mode :deep(.el-radio:hover) {
|
||||
background-color: #f0f9ff;
|
||||
}
|
||||
|
||||
.transfer-mode :deep(.el-radio.is-checked) {
|
||||
background-color: #e1f5fe;
|
||||
}
|
||||
|
||||
.mode-desc {
|
||||
color: #999;
|
||||
font-size: 13px;
|
||||
margin-left: 8px;
|
||||
}
|
||||
|
||||
.target-bed-area .area-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.stats {
|
||||
font-size: 14px;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.search-bar {
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.bed-name {
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.female-tag {
|
||||
background-color: rgba(255, 105, 180, 0.1) !important;
|
||||
color: #ff69b4 !important;
|
||||
border-color: rgba(255, 105, 180, 0.1) !important;
|
||||
}
|
||||
|
||||
.dialog-footer {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
/* 表格样式 */
|
||||
:deep(.el-table) {
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
:deep(.el-table .el-table__row) {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
:deep(.el-table .el-table__row:hover) {
|
||||
background-color: #f5f7fa;
|
||||
}
|
||||
|
||||
:deep(.el-table .current-row) {
|
||||
background-color: #e6f7ff !important;
|
||||
}
|
||||
|
||||
:deep(.el-table .current-row:hover) {
|
||||
background-color: #d1eeff !important;
|
||||
}
|
||||
</style>
|
||||
Reference in new issue
Block a user