diff --git a/server/like-admin/src/main/java/com/mdd/admin/controller/LocationController.java b/server/like-admin/src/main/java/com/mdd/admin/controller/LocationController.java new file mode 100644 index 00000000..08d84ce0 --- /dev/null +++ b/server/like-admin/src/main/java/com/mdd/admin/controller/LocationController.java @@ -0,0 +1,58 @@ +package com.mdd.admin.controller; + +import com.mdd.admin.service.ILocationService; +import com.mdd.admin.validate.LocationCreateValidate; +import com.mdd.admin.validate.LocationUpdateValidate; +import com.mdd.admin.validate.commons.IdValidate; +import com.mdd.admin.vo.LocationAllVo; +import com.mdd.common.core.AjaxResult; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import javax.annotation.Resource; + +@RestController +@RequestMapping("adminapi/location") +@Api(tags = "位置管理") +public class LocationController { + + @Resource + ILocationService iLocationService; + + @GetMapping("/list") + @ApiOperation(value = "获取所有位置(完整位置树)") + public AjaxResult list(){ + LocationAllVo locationAllVo = iLocationService.list(); + return AjaxResult.success(locationAllVo); + } + + @PostMapping("/add") + @ApiOperation(value = "添加新位置", notes = "若父位置楼层不为0,则") + public AjaxResult add(@Validated @RequestBody LocationCreateValidate validate) { + iLocationService.add(validate); + return AjaxResult.success(); + } + + @PostMapping("/update") + @ApiOperation(value = "更新位置") + public AjaxResult update(@Validated @RequestBody LocationUpdateValidate validate) { + iLocationService.update(validate); + return AjaxResult.success(); + } + + @PostMapping("/del") + @ApiOperation(value = "联级删除指定位置") + public AjaxResult del(@Validated @RequestBody IdValidate idValidate) { + iLocationService.del(idValidate); + return AjaxResult.success(); + } + + @PostMapping("/children") + @ApiOperation(value = "返回指定位置的所有子位置", notes = "可用于删除某位置前,查看该位置有什么子位置") + public AjaxResult children(@Validated @RequestBody IdValidate idValidate) { + LocationAllVo locationAllVo = iLocationService.children(idValidate); + return AjaxResult.success(locationAllVo); + } +} diff --git a/server/like-admin/src/main/java/com/mdd/admin/service/ILocationService.java b/server/like-admin/src/main/java/com/mdd/admin/service/ILocationService.java new file mode 100644 index 00000000..3151f850 --- /dev/null +++ b/server/like-admin/src/main/java/com/mdd/admin/service/ILocationService.java @@ -0,0 +1,38 @@ +package com.mdd.admin.service; + + +import com.mdd.admin.validate.LocationCreateValidate; +import com.mdd.admin.validate.LocationUpdateValidate; +import com.mdd.admin.validate.commons.IdValidate; +import com.mdd.admin.vo.LocationAllVo; + +/** + * 位置管理服务接口类 + * */ +public interface ILocationService { + + /** + * 物理位置新增 + * */ + void add(LocationCreateValidate createValidate); + + /** + * 以树状结构返回所有位置 + * */ + LocationAllVo list(); + + /** + * 以树状结构返回指定位置的所有子位置 + * */ + LocationAllVo children(IdValidate idValidate); + + /** + * 联级删除指定位置 + * */ + void del(IdValidate idValidate); + + /** + * 更新位置 + * */ + void update(LocationUpdateValidate validate); +} diff --git a/server/like-admin/src/main/java/com/mdd/admin/service/impl/LocationServiceImpl.java b/server/like-admin/src/main/java/com/mdd/admin/service/impl/LocationServiceImpl.java new file mode 100644 index 00000000..ebd9c6d4 --- /dev/null +++ b/server/like-admin/src/main/java/com/mdd/admin/service/impl/LocationServiceImpl.java @@ -0,0 +1,167 @@ +package com.mdd.admin.service.impl; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.mdd.admin.service.ILocationService; +import com.mdd.admin.validate.LocationCreateValidate; +import com.mdd.admin.validate.LocationUpdateValidate; +import com.mdd.admin.validate.commons.IdValidate; +import com.mdd.admin.vo.LocationAllVo; +import com.mdd.common.entity.Location; +import com.mdd.common.mapper.LocationMapper; +import org.springframework.beans.BeanUtils; +import org.springframework.stereotype.Service; +import org.springframework.util.Assert; + +import javax.annotation.Resource; +import java.util.*; + +/** + * 位置管理服务实现类 + * */ +@Service +public class LocationServiceImpl implements ILocationService { + + @Resource + private LocationMapper locationMapper; + + /** + * 物理位置新增 + * */ + @Override + public void add(LocationCreateValidate createValidate) { + Location newLocation = new Location(); + BeanUtils.copyProperties(createValidate,newLocation); + + if(createValidate.getParentId() != null){ + // 检测到父节点存在 + Location parent = locationMapper.selectById(createValidate.getParentId()); + Assert.notNull(parent,"父位置不存在"); + // 若父楼层不为0,则同步楼层 + if(parent.getFloorNumber() != 0){ + newLocation.setFloorNumber(parent.getFloorNumber()); + } + } + else newLocation.setParentId(0); // 默认设置为“0”节点的子节点 + + locationMapper.insert(newLocation); + + } + + /** + * 以树状结构返回所有位置 + * */ + @Override + public LocationAllVo list() { + LocationAllVo root = new LocationAllVo(); + root.setId(0); + Map> map = getMap(); + sort(root, map); // 空节点作为所有无父节点的父节点 + return root; + } + + /** + * 以树状结构返回指定位置的所有子位置 + * */ + @Override + public LocationAllVo children(IdValidate idValidate) { + Location location = locationMapper.selectById(idValidate.getId()); + LocationAllVo root = new LocationAllVo(); + BeanUtils.copyProperties(location,root); + Map> map = getMap(); + sort(root, map); + return root; + } + + /** + * 联级删除指定位置 + * */ + @Override + public void del(IdValidate idValidate) { + Location location = locationMapper.selectById(idValidate.getId()); + Map> map = getMap(); + Assert.notNull(location,"位置不存在"); + del(idValidate.getId(), map); + } + + /** + * 更新位置 + * */ + @Override + public void update(LocationUpdateValidate validate) { + Location location = locationMapper.selectById(validate.getId()); + BeanUtils.copyProperties(validate,location); + locationMapper.updateById(location); + // 获取需要对齐的楼层,若父节点存在,且父楼层不为0,则对齐父楼层,否则对齐当前楼层 + // 若检测到需要对齐的楼层为0层,不对齐 + Location parentLocation = locationMapper.selectById(validate.getParentId()); + int floorNumber; + if(parentLocation != null && parentLocation.getFloorNumber() != 0) + floorNumber = parentLocation.getFloorNumber(); + else + floorNumber = validate.getFloorNumber(); + + if(floorNumber != 0) { + Map> map = getMap(); + updateFloor(location, floorNumber, map); + } + + } + + /** + * 递归排序树 + * */ + private void sort(LocationAllVo parent, Map> map) { + List children = new ArrayList<>(); // 新建所有子列表 + List locations = map.get(parent.getId()); // 提取父节点的所有子节点 + if(locations == null) return; // 若没有子节点,返回 + for(Location location : locations){ // 遍历所有子节点 + LocationAllVo child = new LocationAllVo(); // 转化子节点类 + BeanUtils.copyProperties(location,child); + children.add(child); // 将转换后的子节点加入父节点 + sort(child,map); // 寻找该子节点的子节点 + } + parent.setChildLocation(children); // 将找到的所有子节点放入父节点中 + } + + /** + * 递归删除树 + * */ + private void del(Integer id, Map> map) { + locationMapper.deleteById(id); + List locations = map.get(id); + if(locations == null) return; + for(Location location : locations) + del(location.getId(), map); + } + + /** + * 递归更新树,从某位置开始,全部更新为指定楼层 + * */ + private void updateFloor(Location parent, Integer floorNumber, Map> map) { + // 先更新父节点 + parent.setFloorNumber(floorNumber); + locationMapper.updateById(parent); + // 子节点留到下一递归更新 + List locations = map.get(parent.getId()); + if(locations == null) return; + + for(Location location : locations){ + updateFloor(location, floorNumber, map); + } + } + + /** + * 获得所有位置的父->子表 + * */ + private Map> getMap(){ + Map> map = new HashMap<>(); + List locations = locationMapper.selectList(new QueryWrapper<>()); + if(locations == null) return map; + + for(Location location : locations){ + map.computeIfAbsent(location.getParentId(), k -> new ArrayList<>()).add(location); + } + + return map; + } +} diff --git a/server/like-admin/src/main/java/com/mdd/admin/validate/LocationCreateValidate.java b/server/like-admin/src/main/java/com/mdd/admin/validate/LocationCreateValidate.java new file mode 100644 index 00000000..33628658 --- /dev/null +++ b/server/like-admin/src/main/java/com/mdd/admin/validate/LocationCreateValidate.java @@ -0,0 +1,36 @@ +package com.mdd.admin.validate; + +import com.mdd.common.enums.LocationStatusEnum; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.io.Serializable; +import java.math.BigDecimal; + +@Data +@ApiModel("位置创建参数") +public class LocationCreateValidate implements Serializable { + private static final long serialVersionUID = 1L; + + @ApiModelProperty(value = "父位置") + private Integer parentId; + + @ApiModelProperty(value = "位置信息,如“教学楼A-301”") + private String name; + + @ApiModelProperty(value = "类型名称,如 campus校区, building建筑物, floor楼层, room房间, ER设备间") + private String type; + + @ApiModelProperty(value = "可容纳人数,非房间类型无意义,不应该填写") + private Integer capacity; + + @ApiModelProperty(value = "面积(平方米),非房间类型无意义,不应该填写") + private BigDecimal area; + + @ApiModelProperty(value = "楼层号,便于排序,若属于某个位置,则应该沿用父位置的楼层号(若楼层号存在),后端会始终保证楼层合法,默认值为无意义的0楼") + private Integer floorNumber = 0; + + @ApiModelProperty(value = "状态,根据枚举设置状态") + private LocationStatusEnum status; +} diff --git a/server/like-admin/src/main/java/com/mdd/admin/validate/LocationUpdateValidate.java b/server/like-admin/src/main/java/com/mdd/admin/validate/LocationUpdateValidate.java new file mode 100644 index 00000000..509293e2 --- /dev/null +++ b/server/like-admin/src/main/java/com/mdd/admin/validate/LocationUpdateValidate.java @@ -0,0 +1,35 @@ +package com.mdd.admin.validate; + +import com.mdd.common.enums.LocationStatusEnum; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.io.Serializable; +import java.math.BigDecimal; + +@Data +@ApiModel("位置更新参数") +public class LocationUpdateValidate implements Serializable { + private static final long serialVersionUID = 1L; + + private Integer id; + + @ApiModelProperty(value = "父位置id") + private Integer parentId; + + @ApiModelProperty(value = "位置名称") + private String name; + + @ApiModelProperty(value = "可容纳人数,非房间类型不应该填写") + private Integer capacity; + + @ApiModelProperty(value = "面积(平方米),非房间类型不应该填写") + private BigDecimal area; + + @ApiModelProperty(value = "楼层号,便于排序,若属于某个位置,则应该沿用父位置的楼层号(若楼层号存在),后端会始终保证楼层合法") + private Integer floorNumber; + + @ApiModelProperty(value = "状态,根据枚举设置状态") + private LocationStatusEnum status; +} diff --git a/server/like-admin/src/main/java/com/mdd/admin/vo/LocationAllVo.java b/server/like-admin/src/main/java/com/mdd/admin/vo/LocationAllVo.java new file mode 100644 index 00000000..b49acfb9 --- /dev/null +++ b/server/like-admin/src/main/java/com/mdd/admin/vo/LocationAllVo.java @@ -0,0 +1,54 @@ +package com.mdd.admin.vo; + +import com.mdd.common.enums.LocationStatusEnum; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.List; + +@Data +@ApiModel("完整位置树详情") +public class LocationAllVo implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty(value = "主键ID") + private Integer id; + + @ApiModelProperty(value = "位置信息,如“教学楼A-301”") + private String name; + + @ApiModelProperty(value = "类型名称,如 campus校区, building建筑物, floor楼层, room房间, ER设备间") + private String type; + + @ApiModelProperty(value = "子位置") + private List childLocation; + + @ApiModelProperty(value = "外部系统ID") + private Integer externalId; + + @ApiModelProperty(value = "外部系统标识") + private String externalSystem; + + @ApiModelProperty(value = "可容纳人数") + private Integer capacity; + + @ApiModelProperty(value = "面积(平方米)") + private BigDecimal area; + + @ApiModelProperty(value = "楼层号,便于排序") + private Integer floorNumber; + + @ApiModelProperty(value = "状态") + private LocationStatusEnum status; + + @ApiModelProperty(value = "创建时间") + private LocalDateTime createTime; + + @ApiModelProperty(value = "更新时间") + private LocalDateTime updateTime; +} diff --git a/server/like-common/src/main/java/com/mdd/common/entity/Location.java b/server/like-common/src/main/java/com/mdd/common/entity/Location.java new file mode 100644 index 00000000..8bce3619 --- /dev/null +++ b/server/like-common/src/main/java/com/mdd/common/entity/Location.java @@ -0,0 +1,55 @@ +package com.mdd.common.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.mdd.common.enums.LocationStatusEnum; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDateTime; + +@Data +@ApiModel("位置实体") +public class Location implements Serializable { + private static final long serialVersionUID = 1L; + + @TableId(value="id", type= IdType.AUTO) + @ApiModelProperty(value = "主键ID") + private Integer id; + + @ApiModelProperty(value = "位置信息,如“教学楼A-301”") + private String name; + + @ApiModelProperty(value = "类型名称,如 campus校区, building建筑物, floor楼层, room房间, ER设备间") + private String type; + + @ApiModelProperty(value = "父位置") + private Integer parentId; + + @ApiModelProperty(value = "外部系统ID") + private Integer externalId; + + @ApiModelProperty(value = "外部系统标识") + private String externalSystem; + + @ApiModelProperty(value = "可容纳人数") + private Integer capacity; + + @ApiModelProperty(value = "面积(平方米)") + private BigDecimal area; + + @ApiModelProperty(value = "楼层号,便于排序") + private Integer floorNumber; + + @ApiModelProperty(value = "状态") + private LocationStatusEnum status; + + @ApiModelProperty(value = "创建时间") + private LocalDateTime createTime; + + @ApiModelProperty(value = "更新时间") + private LocalDateTime updateTime; +} diff --git a/server/like-common/src/main/java/com/mdd/common/enums/LocationStatusEnum.java b/server/like-common/src/main/java/com/mdd/common/enums/LocationStatusEnum.java new file mode 100644 index 00000000..b326b452 --- /dev/null +++ b/server/like-common/src/main/java/com/mdd/common/enums/LocationStatusEnum.java @@ -0,0 +1,11 @@ +package com.mdd.common.enums; + +/** + * 位置管理中,位置的状态枚举 + * */ +public enum LocationStatusEnum { + active, // 正常 + inactive, // 停用 + building, // 建造中 + demolished // 已拆除 +} diff --git a/server/like-common/src/main/java/com/mdd/common/mapper/LocationMapper.java b/server/like-common/src/main/java/com/mdd/common/mapper/LocationMapper.java new file mode 100644 index 00000000..b09d9703 --- /dev/null +++ b/server/like-common/src/main/java/com/mdd/common/mapper/LocationMapper.java @@ -0,0 +1,10 @@ +package com.mdd.common.mapper; + +import com.mdd.common.core.basics.IBaseMapper; +import com.mdd.common.entity.Location; + +/** + * 位置管理Mapper + */ +public interface LocationMapper extends IBaseMapper { +}