补充了“位置详情”接口

This commit is contained in:
Guan 2026-03-09 16:14:03 +08:00
parent 97416cc49b
commit 56161be195
10 changed files with 540 additions and 0 deletions

View File

@ -0,0 +1,67 @@
package com.mdd.admin.controller;
import com.mdd.admin.service.ILocationService;
import com.mdd.admin.validate.LocationCreateValidate;
import com.mdd.admin.vo.LocationDetailVo;
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 com.mdd.common.validator.annotation.IDMust;
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<LocationAllVo> list(){
LocationAllVo locationAllVo = iLocationService.list();
return AjaxResult.success(locationAllVo);
}
@GetMapping("/detail")
@ApiOperation(value = "位置详情")
public AjaxResult<LocationDetailVo> detail(@Validated @IDMust() @RequestParam("id") Integer id) {
LocationDetailVo detail = iLocationService.detail(id);
return AjaxResult.success(detail);
}
@PostMapping("/add")
@ApiOperation(value = "添加新位置", notes = "若父位置楼层不为0")
public AjaxResult<Object> add(@Validated @RequestBody LocationCreateValidate validate) {
iLocationService.add(validate);
return AjaxResult.success();
}
@PostMapping("/update")
@ApiOperation(value = "更新位置")
public AjaxResult<Object> update(@Validated @RequestBody LocationUpdateValidate validate) {
iLocationService.update(validate);
return AjaxResult.success();
}
@PostMapping("/del")
@ApiOperation(value = "联级删除指定位置")
public AjaxResult<Object> del(@Validated @RequestBody IdValidate idValidate) {
iLocationService.del(idValidate);
return AjaxResult.success();
}
@PostMapping("/children")
@ApiOperation(value = "返回指定位置的所有子位置", notes = "可用于删除某位置前,查看该位置有什么子位置")
public AjaxResult<LocationAllVo> children(@Validated @RequestBody IdValidate idValidate) {
LocationAllVo locationAllVo = iLocationService.children(idValidate);
return AjaxResult.success(locationAllVo);
}
}

View File

@ -0,0 +1,44 @@
package com.mdd.admin.service;
import com.mdd.admin.validate.LocationCreateValidate;
import com.mdd.admin.vo.LocationDetailVo;
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);
/**
* 位置详情
* */
LocationDetailVo detail(Integer id);
}

View File

@ -0,0 +1,179 @@
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.vo.LocationDetailVo;
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<Integer, List<Location>> 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<Integer, List<Location>> map = getMap();
sort(root, map);
return root;
}
/**
* 联级删除指定位置
* */
@Override
public void del(IdValidate idValidate) {
Location location = locationMapper.selectById(idValidate.getId());
Map<Integer, List<Location>> 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<Integer, List<Location>> map = getMap();
updateFloor(location, floorNumber, map);
}
}
/**
* 位置详情
* */
@Override
public LocationDetailVo detail(Integer id) {
LocationDetailVo vo = new LocationDetailVo();
Location location = locationMapper.selectById(id);
BeanUtils.copyProperties(location,vo);
return vo;
}
/**
* 递归排序树
* */
private void sort(LocationAllVo parent, Map<Integer, List<Location>> map) {
List<LocationAllVo> children = new ArrayList<>(); // 新建所有子列表
List<Location> 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<Integer, List<Location>> map) {
locationMapper.deleteById(id);
List<Location> locations = map.get(id);
if(locations == null) return;
for(Location location : locations)
del(location.getId(), map);
}
/**
* 递归更新树从某位置开始全部更新为指定楼层
* */
private void updateFloor(Location parent, Integer floorNumber, Map<Integer, List<Location>> map) {
// 先更新父节点
parent.setFloorNumber(floorNumber);
locationMapper.updateById(parent);
// 子节点留到下一递归更新
List<Location> locations = map.get(parent.getId());
if(locations == null) return;
for(Location location : locations){
updateFloor(location, floorNumber, map);
}
}
/**
* 获得所有位置的父->子表
* */
private Map<Integer, List<Location>> getMap(){
Map<Integer, List<Location>> map = new HashMap<>();
List<Location> 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;
}
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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<LocationAllVo> 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;
}

View File

@ -0,0 +1,49 @@
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;
@Data
@ApiModel("位置详情")
public class LocationDetailVo 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 = "外部系统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;
}

View File

@ -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;
}

View File

@ -0,0 +1,11 @@
package com.mdd.common.enums;
/**
* 位置管理中位置的状态枚举
* */
public enum LocationStatusEnum {
active, // 正常
inactive, // 停用
building, // 建造中
demolished // 已拆除
}

View File

@ -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<Location> {
}