diff --git a/smoke/smoke.mjs b/smoke/smoke.mjs index 2032c3c..b84c0dc 100644 --- a/smoke/smoke.mjs +++ b/smoke/smoke.mjs @@ -98,6 +98,9 @@ ok("classroom Edit equipments 按数量替换", editQty.code === 0, editQty.msg) const roomsAfterQty = await api("GET", "/api/classroom/List", { params: { buildingId, page: 1, count: 20 } }); const room1Qty = roomsAfterQty.data.list.find(r => r.serID === room1); ok("Edit 后设备数量为 3(名称×3)", room1Qty && room1Qty.equipmentQtys && room1Qty.equipmentQtys[eqSeedId] === 3 && /冒烟设备.*×3$/.test(room1Qty.equipmentNames), JSON.stringify(room1Qty && room1Qty.equipmentQtys)); +// 回归:编辑时保留原有设备关联(先删后插撞 (classroom_id, equipment_id) 唯一键) +const editKeep = await api("POST", "/api/classroom/Edit", { json: { serID: room1, status: "closed", equipments: [{ equipmentId: eqSeedId, quantity: 3 }] } }); +ok("classroom Edit 保留原设备关联", editKeep.code === 0, editKeep.msg); const editClear = await api("POST", "/api/classroom/Edit", { json: { serID: room1, equipmentIds: [] } }); ok("classroom Edit 旧字段 equipmentIds 清空设备(兼容)", editClear.code === 0, editClear.msg); const room2code = roomsAfterEdit.data.list[1].roomCode; diff --git a/src/main/java/com/yunhai/acaclassroom/controller/api/ClassroomController.java b/src/main/java/com/yunhai/acaclassroom/controller/api/ClassroomController.java index 7dbb0f6..bba5109 100644 --- a/src/main/java/com/yunhai/acaclassroom/controller/api/ClassroomController.java +++ b/src/main/java/com/yunhai/acaclassroom/controller/api/ClassroomController.java @@ -50,7 +50,7 @@ public class ClassroomController { return classroomService.floors(buildingId); } - /** 全校教室扁平列表(教室管理页「空间筛选树」数据源,轻量字段)。 */ + /** 全校教室扁平列表(教室管理页「楼层筛选树」数据源,轻量字段)。 */ @GetMapping("Tree") public List> tree() { return classroomService.tree(); diff --git a/src/main/java/com/yunhai/acaclassroom/service/IClassroomService.java b/src/main/java/com/yunhai/acaclassroom/service/IClassroomService.java index bcd56a7..ac8e492 100644 --- a/src/main/java/com/yunhai/acaclassroom/service/IClassroomService.java +++ b/src/main/java/com/yunhai/acaclassroom/service/IClassroomService.java @@ -36,7 +36,7 @@ public interface IClassroomService { /** 楼栋下已有教室的楼层列表(升序,筛选项用)。 */ List floors(Integer buildingId); - /** 全校教室扁平列表(空间筛选树数据源,仅轻量字段)。 */ + /** 全校教室扁平列表(楼层筛选树数据源,仅轻量字段)。 */ List> tree(); /** 批量添加教室,返回 {created, skipped, total}。 */ diff --git a/src/main/java/com/yunhai/acaclassroom/service/impl/ClassroomService.java b/src/main/java/com/yunhai/acaclassroom/service/impl/ClassroomService.java index aaf8943..8492d15 100644 --- a/src/main/java/com/yunhai/acaclassroom/service/impl/ClassroomService.java +++ b/src/main/java/com/yunhai/acaclassroom/service/impl/ClassroomService.java @@ -128,7 +128,7 @@ public class ClassroomService implements IClassroomService { // 类型名映射 Map typeNames = typeRepository.findBySchIdOrderBySortOrderAscIdAsc(schId).stream() .collect(Collectors.toMap(ClassroomType::getId, ClassroomType::getTypeName, (a, b) -> a)); - // 校区/楼栋名映射(列表跨楼栋时行内直接展示,空间筛选树与详情面板用) + // 校区/楼栋名映射(列表跨楼栋时行内直接展示,楼层筛选树与详情面板用) Map campusNames = campusRepository.findBySchIdOrderBySortOrderAscIdAsc(schId).stream() .collect(Collectors.toMap(com.yunhai.acaclassroom.entity.Campus::getId, com.yunhai.acaclassroom.entity.Campus::getCampusName, (a, b) -> a)); @@ -357,6 +357,9 @@ public class ClassroomService implements IClassroomService { Map equipmentMap = sanitizeEquipmentMap(req.getEquipments(), req.getEquipmentIds(), r.getSchId()); classroomEquipmentRepository.deleteBySchIdAndClassroomId(r.getSchId(), r.getId()); + // 先落盘删除:Hibernate 同一事务内 INSERT 先于 DELETE 执行, + // 不 flush 会让“保留原设备”的重插撞 (classroom_id, equipment_id) 唯一键。 + classroomEquipmentRepository.flush(); equipmentMap.forEach((eqId, qty) -> { com.yunhai.acaclassroom.entity.ClassroomEquipment ce = new com.yunhai.acaclassroom.entity.ClassroomEquipment();