From d849360af576d63dcfebe1bd73e0a690c9c119ed Mon Sep 17 00:00:00 2001 From: Guan Date: Mon, 9 Mar 2026 16:14:03 +0800 Subject: [PATCH 1/2] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E4=BA=86=E4=BD=8D?= =?UTF-8?q?=E7=BD=AE=E7=AE=A1=E7=90=86=EF=BC=8C=E4=BD=8D=E7=BD=AE=E7=AE=A1?= =?UTF-8?q?=E7=90=86=E7=94=A8=E4=BA=8E=E8=BE=85=E5=8A=A9=E8=B5=84=E4=BA=A7?= =?UTF-8?q?=E7=AE=A1=E7=90=86=E5=92=8C=E6=8E=92=E8=AF=BE=E7=9A=84=E5=8A=9F?= =?UTF-8?q?=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../admin/controller/LocationController.java | 58 ++++++ .../mdd/admin/service/ILocationService.java | 38 ++++ .../service/impl/LocationServiceImpl.java | 167 ++++++++++++++++++ .../validate/LocationCreateValidate.java | 36 ++++ .../validate/LocationUpdateValidate.java | 35 ++++ .../java/com/mdd/admin/vo/LocationAllVo.java | 54 ++++++ .../java/com/mdd/common/entity/Location.java | 55 ++++++ .../mdd/common/enums/LocationStatusEnum.java | 11 ++ .../com/mdd/common/mapper/LocationMapper.java | 10 ++ 9 files changed, 464 insertions(+) create mode 100644 server/like-admin/src/main/java/com/mdd/admin/controller/LocationController.java create mode 100644 server/like-admin/src/main/java/com/mdd/admin/service/ILocationService.java create mode 100644 server/like-admin/src/main/java/com/mdd/admin/service/impl/LocationServiceImpl.java create mode 100644 server/like-admin/src/main/java/com/mdd/admin/validate/LocationCreateValidate.java create mode 100644 server/like-admin/src/main/java/com/mdd/admin/validate/LocationUpdateValidate.java create mode 100644 server/like-admin/src/main/java/com/mdd/admin/vo/LocationAllVo.java create mode 100644 server/like-common/src/main/java/com/mdd/common/entity/Location.java create mode 100644 server/like-common/src/main/java/com/mdd/common/enums/LocationStatusEnum.java create mode 100644 server/like-common/src/main/java/com/mdd/common/mapper/LocationMapper.java 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 { +} From 8b32bf5edef3729de5c96c56f7c07442f1d78183 Mon Sep 17 00:00:00 2001 From: XiuHe <1109326957@qq.com> Date: Mon, 9 Mar 2026 16:28:46 +0800 Subject: [PATCH 2/2] =?UTF-8?q?=E5=AE=8C=E5=96=84=E4=BD=8D=E7=BD=AE?= =?UTF-8?q?=E9=83=A8=E5=88=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- admin/src/api/location.ts | 31 +++ admin/src/hooks/useDictOptions.ts | 25 +- admin/src/views/assets/location/edit.vue | 232 +++++-------------- admin/src/views/assets/location/index.vue | 114 ++++++--- admin/src/views/assets/unfixedinfo/index.vue | 2 +- 5 files changed, 191 insertions(+), 213 deletions(-) create mode 100644 admin/src/api/location.ts diff --git a/admin/src/api/location.ts b/admin/src/api/location.ts new file mode 100644 index 00000000..562032c7 --- /dev/null +++ b/admin/src/api/location.ts @@ -0,0 +1,31 @@ +import request from '@/utils/request' + +// 获取所有位置 +export function getLocationList() { + return request.get({ url: '/location/list' }) +} + +// 添加位置 +export function addLocation(params?: any) { + return request.post({ url: '/location/add', params }) +} + +// 修改位置 +export function updateLocation(params?: any) { + return request.post({ url: '/location/update', params }) +} + +// 获取指定位置 +export function getLocation(params?: any) { + return request.get({ url: '/location/detail', params }) +} + +// 删除位置 +export function deleteLocation(params?: any) { + return request.post({ url: '/location/del', params }) +} + +// 返回指定位置的所有子位置 +export function getSubLocations(params?: any) { + return request.get({ url: '/location/children', params }) +} \ No newline at end of file diff --git a/admin/src/hooks/useDictOptions.ts b/admin/src/hooks/useDictOptions.ts index 19cbd8d0..597f606e 100644 --- a/admin/src/hooks/useDictOptions.ts +++ b/admin/src/hooks/useDictOptions.ts @@ -47,14 +47,27 @@ export function useDictOptions(options: Options) { } } -export function useDictData(id: number) { +export function useDictData>(ids: number | number[]) { + const dictIds = Array.isArray(ids) ? ids : [ids] const dictData: any = reactive({}) - const refresh = async () => { - const data = await getDictList({ - type_id: id - }) - Object.assign(dictData, data.lists) + + // 初始化单个字典 + const initDict = async (id: number) => { + const data = await getDictList({ type_id: id }) + dictData[id] = {} + Object.assign(dictData[id], data.lists) // 保持原有数据结构 } + + // 刷新字典(支持指定ID,不传则刷新所有) + const refresh = async (targetIds?: number | number[]) => { + const targetDictIds = targetIds + ? Array.isArray(targetIds) ? targetIds : [targetIds] + : dictIds + // 并行加载指定字典 + await Promise.all(targetDictIds.map(initDict)) + } + + // 初始化所有字典 const initPromise = refresh() return { diff --git a/admin/src/views/assets/location/edit.vue b/admin/src/views/assets/location/edit.vue index dca71a33..18c6fc81 100644 --- a/admin/src/views/assets/location/edit.vue +++ b/admin/src/views/assets/location/edit.vue @@ -9,17 +9,10 @@ @close="handleClose" > - - - 目录 - 菜单 - 按钮 - - - + - - + + - - - - - -
- -
- 访问的路由地址,如:`user`,如外网地址需内链访问则以`http(s)://`开头 -
-
-
- -
- + + -
- 访问的组件路径,如:`user/setting`,默认在`views`目录下 -
-
+
-
- + -
- 访问详情页面,编辑页面时,菜单高亮显示,如`/consumer/lists` -
-
+
- -
- -
- 将作为server端API验权使用,如`auth.admin/user`,请谨慎修改 -
-
+ + - -
-
- -
-
- 访问路由的默认传递参数,如:`{"id": 1, "name": - "admin"}`或`id=1&name=admin` -
-
+ + - -
- - 缓存 - 不缓存 - -
选择缓存则会被`keep-alive`缓存
-
-
- -
- - 显示 - 隐藏 - -
- 选择隐藏则路由将不会出现在侧边栏,但仍然可以访问 -
-
-
- -
- - 正常 - 停用 - -
选择停用则路由将不会出现在侧边栏,也不能被访问
-
-
- -
- -
数值越大越排前
-
+ +
@@ -164,9 +75,9 @@