فهرست منبع

提交宿舍楼树形结构的代码

zlwu 1 سال پیش
والد
کامیت
92f2598017
21فایلهای تغییر یافته به همراه1150 افزوده شده و 509 حذف شده
  1. 39 0
      backend/ruoyi-modules/ruoyi-xg/src/main/java/org/dromara/xg/controller/XgDormBuildingTreeController.java
  2. 5 0
      backend/ruoyi-modules/ruoyi-xg/src/main/java/org/dromara/xg/domain/XgDormBuilding.java
  3. 36 0
      backend/ruoyi-modules/ruoyi-xg/src/main/java/org/dromara/xg/domain/bo/DormBuildingTreeBo.java
  4. 4 0
      backend/ruoyi-modules/ruoyi-xg/src/main/java/org/dromara/xg/domain/bo/XgDormBuildingBo.java
  5. 105 0
      backend/ruoyi-modules/ruoyi-xg/src/main/java/org/dromara/xg/domain/vo/DormBuildingInfoVo.java
  6. 49 0
      backend/ruoyi-modules/ruoyi-xg/src/main/java/org/dromara/xg/domain/vo/DormBuildingTreeVo.java
  7. 6 0
      backend/ruoyi-modules/ruoyi-xg/src/main/java/org/dromara/xg/domain/vo/XgDormBuildingVo.java
  8. 84 0
      backend/ruoyi-modules/ruoyi-xg/src/main/java/org/dromara/xg/mapper/XgDormBuildingTreeMapper.java
  9. 23 0
      backend/ruoyi-modules/ruoyi-xg/src/main/java/org/dromara/xg/service/IXgDormBuildingTreeService.java
  10. 155 0
      backend/ruoyi-modules/ruoyi-xg/src/main/java/org/dromara/xg/service/impl/XgDormBuildingTreeServiceImpl.java
  11. 1 0
      backend/ruoyi-modules/ruoyi-xg/src/main/resources/mapper/sslxx/XgDormBuildingMapper.xml
  12. 297 0
      backend/ruoyi-modules/ruoyi-xg/src/main/resources/mapper/xg/XgDormBuildingTreeMapper.xml
  13. 67 46
      docs/变更管理/code-adjust-record-2025-07-03-cursor.md
  14. 10 1
      docs/开发文档/API/API文档总览.md
  15. 187 413
      docs/开发文档/API/宿舍房间管理API.md
  16. 1 0
      docs/设计文档/database/学工管理-宿舍管理/宿舍管理数据库建表脚本.sql
  17. 3 0
      web/src/api/xgss/sslxx/dormBuilding/types.ts
  18. 2 2
      web/src/api/xgss/xsssfjgl/index.ts
  19. 18 2
      web/src/views/xgss/sslxx/dormBuilding/index.vue
  20. 56 36
      web/src/views/xgss/xsssfjgl/index.vue
  21. 2 9
      web/src/views/xgss/xsssgly/index.vue

+ 39 - 0
backend/ruoyi-modules/ruoyi-xg/src/main/java/org/dromara/xg/controller/XgDormBuildingTreeController.java

@@ -0,0 +1,39 @@
+package org.dromara.xg.controller;
+
+import java.util.List;
+
+import lombok.RequiredArgsConstructor;
+import cn.dev33.satoken.annotation.SaCheckPermission;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.validation.annotation.Validated;
+import org.dromara.common.web.core.BaseController;
+import org.dromara.common.core.domain.R;
+import org.dromara.xg.domain.vo.DormBuildingTreeVo;
+import org.dromara.xg.domain.bo.DormBuildingTreeBo;
+import org.dromara.xg.service.IXgDormBuildingTreeService;
+
+/**
+ * 宿舍楼树形结构控制器
+ *
+ * @author wuzilong
+ * @date 2025-07-03
+ */
+@Validated
+@RequiredArgsConstructor
+@RestController
+@RequestMapping("/xgss/dormBuildingTree")
+public class XgDormBuildingTreeController extends BaseController {
+
+    private final IXgDormBuildingTreeService xgDormBuildingTreeService;
+
+    /**
+     * 获取宿舍楼树形结构数据
+     * 校区-宿舍区-宿舍楼三级结构,校区和宿舍区不可选,只有宿舍楼可以选择
+     */
+    // @SaCheckPermission("xgss:dormBuildingTree:list")
+    @GetMapping("/list")
+    public R<List<DormBuildingTreeVo>> getDormBuildingTree(DormBuildingTreeBo bo) {
+        List<DormBuildingTreeVo> treeData = xgDormBuildingTreeService.getDormBuildingTree(bo);
+        return R.ok(treeData);
+    }
+}

+ 5 - 0
backend/ruoyi-modules/ruoyi-xg/src/main/java/org/dromara/xg/domain/XgDormBuilding.java

@@ -73,4 +73,9 @@ public class XgDormBuilding extends TenantEntity {
      */
      */
     private String remark;
     private String remark;
 
 
+    /**
+     * 总楼层数
+     */
+    private Integer floors;
+
 }
 }

+ 36 - 0
backend/ruoyi-modules/ruoyi-xg/src/main/java/org/dromara/xg/domain/bo/DormBuildingTreeBo.java

@@ -0,0 +1,36 @@
+package org.dromara.xg.domain.bo;
+
+import java.io.Serializable;
+import lombok.Data;
+
+/**
+ * 宿舍楼树查询业务对象
+ *
+ * @author wuzilong
+ * @date 2025-07-03
+ */
+@Data
+public class DormBuildingTreeBo implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 校区ID
+     */
+    private Long campusId;
+
+    /**
+     * 宿舍区ID
+     */
+    private Long areaId;
+
+    /**
+     * 宿舍楼名称(模糊查询)
+     */
+    private String buildingName;
+
+    /**
+     * 宿舍楼状态
+     */
+    private String status;
+}

+ 4 - 0
backend/ruoyi-modules/ruoyi-xg/src/main/java/org/dromara/xg/domain/bo/XgDormBuildingBo.java

@@ -65,5 +65,9 @@ public class XgDormBuildingBo extends BaseEntity {
      */
      */
     private Long sortOrder;
     private Long sortOrder;
 
 
+    /**
+     * 总楼层数
+     */
+    private Integer floors;
 
 
 }
 }

+ 105 - 0
backend/ruoyi-modules/ruoyi-xg/src/main/java/org/dromara/xg/domain/vo/DormBuildingInfoVo.java

@@ -0,0 +1,105 @@
+package org.dromara.xg.domain.vo;
+
+import java.io.Serializable;
+import java.util.Date;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import lombok.Data;
+
+/**
+ * 宿舍楼信息VO
+ *
+ * @author wuzilong
+ * @date 2025-07-03
+ */
+@Data
+public class DormBuildingInfoVo implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 宿舍楼ID
+     */
+    private Long id;
+
+    /**
+     * 宿舍楼名称
+     */
+    private String buildingName;
+
+    /**
+     * 宿舍楼编号
+     */
+    private String buildingCode;
+
+    /**
+     * 所属校区ID
+     */
+    private Long campusId;
+
+    /**
+     * 校区名称
+     */
+    private String campusName;
+
+    /**
+     * 所属宿舍区ID
+     */
+    private Long areaId;
+
+    /**
+     * 宿舍区名称
+     */
+    private String areaName;
+
+    /**
+     * 楼层数
+     */
+    private Integer floors;
+
+    /**
+     * 房间数
+     */
+    private Integer roomCount;
+
+    /**
+     * 床位数
+     */
+    private Integer bedCount;
+
+    /**
+     * 已使用床位数
+     */
+    private Integer usedBedCount;
+
+    /**
+     * 状态(0正常 1维修中 2停用)
+     */
+    private String status;
+
+    /**
+     * 备注
+     */
+    private String remark;
+
+    /**
+     * 创建者
+     */
+    private Long createBy;
+
+    /**
+     * 创建时间
+     */
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private Date createTime;
+
+    /**
+     * 更新者
+     */
+    private Long updateBy;
+
+    /**
+     * 更新时间
+     */
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private Date updateTime;
+}

+ 49 - 0
backend/ruoyi-modules/ruoyi-xg/src/main/java/org/dromara/xg/domain/vo/DormBuildingTreeVo.java

@@ -0,0 +1,49 @@
+package org.dromara.xg.domain.vo;
+
+import java.io.Serializable;
+import java.util.List;
+import com.fasterxml.jackson.annotation.JsonInclude;
+import lombok.Data;
+
+/**
+ * 宿舍楼树形结构VO
+ *
+ * @author wuzilong
+ * @date 2025-07-03
+ */
+@Data
+public class DormBuildingTreeVo implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 节点ID
+     */
+    private Long id;
+
+    /**
+     * 节点名称
+     */
+    private String label;
+
+    /**
+     * 节点类型 (campus:校区, area:宿舍区, building:宿舍楼)
+     */
+    private String type;
+
+    /**
+     * 是否禁用节点(校区和宿舍区节点禁用点击)
+     */
+    private Boolean disabled;
+
+    /**
+     * 宿舍楼层数(仅宿舍楼节点有此字段)
+     */
+    private Integer buildingFloors;
+
+    /**
+     * 子节点
+     */
+    @JsonInclude(JsonInclude.Include.NON_EMPTY)
+    private List<DormBuildingTreeVo> children;
+}

+ 6 - 0
backend/ruoyi-modules/ruoyi-xg/src/main/java/org/dromara/xg/domain/vo/XgDormBuildingVo.java

@@ -87,6 +87,12 @@ public class XgDormBuildingVo implements Serializable {
     @ExcelProperty(value = "排序号")
     @ExcelProperty(value = "排序号")
     private Long sortOrder;
     private Long sortOrder;
 
 
+    /**
+     * 总楼层数
+     */
+    @ExcelProperty(value = "总楼层数")
+    private Integer floors;
+
     // 基础字段
     // 基础字段
     private Long createBy; // 创建者
     private Long createBy; // 创建者
     private Date createTime; // 创建时间
     private Date createTime; // 创建时间

+ 84 - 0
backend/ruoyi-modules/ruoyi-xg/src/main/java/org/dromara/xg/mapper/XgDormBuildingTreeMapper.java

@@ -0,0 +1,84 @@
+package org.dromara.xg.mapper;
+
+import java.util.List;
+import org.apache.ibatis.annotations.Param;
+import org.dromara.xg.domain.vo.DormBuildingInfoVo;
+import org.dromara.xg.domain.bo.DormBuildingTreeBo;
+
+/**
+ * 宿舍楼树形结构Mapper接口
+ *
+ * @author wuzilong
+ * @date 2025-07-03
+ */
+public interface XgDormBuildingTreeMapper {
+
+    /**
+     * 获取所有校区信息
+     *
+     * @return 校区列表
+     */
+    List<DormBuildingInfoVo> selectCampusList();
+
+    /**
+     * 获取所有宿舍区信息
+     *
+     * @return 宿舍区列表
+     */
+    List<DormBuildingInfoVo> selectAreaList();
+
+    /**
+     * 获取所有宿舍楼信息
+     *
+     * @return 宿舍楼列表
+     */
+    List<DormBuildingInfoVo> selectBuildingList(DormBuildingTreeBo bo);
+
+    /**
+     * 获取全校管理员权限的宿舍楼信息
+     *
+     * @param userId 用户ID
+     * @param bo     查询参数
+     * @return 宿舍楼列表
+     */
+    List<DormBuildingInfoVo> selectBuildingsBySchoolAdmin(@Param("userId") Long userId,
+            @Param("bo") DormBuildingTreeBo bo);
+
+    /**
+     * 获取校区管理员权限的宿舍楼信息
+     *
+     * @param userId 用户ID
+     * @param bo     查询参数
+     * @return 宿舍楼列表
+     */
+    List<DormBuildingInfoVo> selectBuildingsByCampusAdmin(@Param("userId") Long userId,
+            @Param("bo") DormBuildingTreeBo bo);
+
+    /**
+     * 获取宿舍区管理员权限的宿舍楼信息
+     *
+     * @param userId 用户ID
+     * @param bo     查询参数
+     * @return 宿舍楼列表
+     */
+    List<DormBuildingInfoVo> selectBuildingsByAreaAdmin(@Param("userId") Long userId,
+            @Param("bo") DormBuildingTreeBo bo);
+
+    /**
+     * 获取宿舍楼管理员权限的宿舍楼信息
+     *
+     * @param userId 用户ID
+     * @param bo     查询参数
+     * @return 宿舍楼列表
+     */
+    List<DormBuildingInfoVo> selectBuildingsByBuildingAdmin(@Param("userId") Long userId,
+            @Param("bo") DormBuildingTreeBo bo);
+
+    /**
+     * 检查用户是否有宿舍管理权限
+     *
+     * @param userId 用户ID
+     * @return 管理员类型列表 (1全校管理员 2校区管理员 3宿舍区管理员 4宿舍楼管理员)
+     */
+    List<String> checkUserDormManagerType(@Param("userId") Long userId);
+}

+ 23 - 0
backend/ruoyi-modules/ruoyi-xg/src/main/java/org/dromara/xg/service/IXgDormBuildingTreeService.java

@@ -0,0 +1,23 @@
+package org.dromara.xg.service;
+
+import java.util.List;
+import org.dromara.xg.domain.vo.DormBuildingTreeVo;
+import org.dromara.xg.domain.bo.DormBuildingTreeBo;
+
+/**
+ * 宿舍楼树形结构服务接口
+ *
+ * @author wuzilong
+ * @date 2025-07-03
+ */
+public interface IXgDormBuildingTreeService {
+
+    /**
+     * 获取宿舍楼树形结构数据
+     *
+     * @param bo 查询参数
+     * @return 树形结构数据
+     */
+    List<DormBuildingTreeVo> getDormBuildingTree(DormBuildingTreeBo bo);
+
+}

+ 155 - 0
backend/ruoyi-modules/ruoyi-xg/src/main/java/org/dromara/xg/service/impl/XgDormBuildingTreeServiceImpl.java

@@ -0,0 +1,155 @@
+package org.dromara.xg.service.impl;
+
+import java.util.*;
+import java.util.stream.Collectors;
+
+import org.springframework.stereotype.Service;
+import lombok.RequiredArgsConstructor;
+import org.dromara.xg.service.IXgDormBuildingTreeService;
+import org.dromara.xg.mapper.XgDormBuildingTreeMapper;
+import org.dromara.xg.domain.vo.DormBuildingTreeVo;
+import org.dromara.xg.domain.vo.DormBuildingInfoVo;
+import org.dromara.xg.domain.bo.DormBuildingTreeBo;
+import org.dromara.common.satoken.utils.LoginHelper;
+
+/**
+ * 宿舍楼树形结构服务实现
+ *
+ * @author wuzilong
+ * @date 2025-07-03
+ */
+@RequiredArgsConstructor
+@Service
+public class XgDormBuildingTreeServiceImpl implements IXgDormBuildingTreeService {
+
+    private final XgDormBuildingTreeMapper dormBuildingTreeMapper;
+
+    /**
+     * 获取宿舍楼树形结构数据
+     *
+     * @param bo 查询参数
+     * @return 树形结构数据
+     */
+    @Override
+    public List<DormBuildingTreeVo> getDormBuildingTree(DormBuildingTreeBo bo) {
+        // 获取当前登录用户ID
+        Long userId = LoginHelper.getUserId();
+
+        // 查询用户管理权限类型
+        List<String> managerTypes = dormBuildingTreeMapper.checkUserDormManagerType(userId);
+
+        if (managerTypes == null || managerTypes.isEmpty()) {
+            // 没有宿舍管理权限,返回空列表
+            return new ArrayList<>();
+        }
+
+        // 获取所有宿舍楼数据(根据权限过滤)
+        List<DormBuildingInfoVo> buildingList = new ArrayList<>();
+
+        // 按照权限分别查询并合并结果(支持用户拥有多种角色的情况)
+        if (managerTypes.contains("1")) {
+            // 全校管理员,获取所有宿舍楼
+            buildingList = dormBuildingTreeMapper.selectBuildingsBySchoolAdmin(userId, bo);
+            // 全校管理员可以查看所有宿舍楼,无需继续查询其他权限
+        } else {
+            // 对于非全校管理员,合并多种权限的结果
+            Set<Long> addedBuildingIds = new HashSet<>(); // 用于去重
+
+            if (managerTypes.contains("2")) {
+                // 校区管理员,获取管理的校区下的宿舍楼
+                List<DormBuildingInfoVo> campusBuildings = dormBuildingTreeMapper.selectBuildingsByCampusAdmin(userId,
+                        bo);
+                for (DormBuildingInfoVo building : campusBuildings) {
+                    if (addedBuildingIds.add(building.getId())) {
+                        buildingList.add(building);
+                    }
+                }
+            }
+
+            if (managerTypes.contains("3")) {
+                // 宿舍区管理员,获取管理的宿舍区下的宿舍楼
+                List<DormBuildingInfoVo> areaBuildings = dormBuildingTreeMapper.selectBuildingsByAreaAdmin(userId, bo);
+                for (DormBuildingInfoVo building : areaBuildings) {
+                    if (addedBuildingIds.add(building.getId())) {
+                        buildingList.add(building);
+                    }
+                }
+            }
+
+            if (managerTypes.contains("4")) {
+                // 宿舍楼管理员,获取管理的宿舍楼
+                List<DormBuildingInfoVo> directBuildings = dormBuildingTreeMapper.selectBuildingsByBuildingAdmin(userId,
+                        bo);
+                for (DormBuildingInfoVo building : directBuildings) {
+                    if (addedBuildingIds.add(building.getId())) {
+                        buildingList.add(building);
+                    }
+                }
+            }
+        }
+
+        // 如果没有获取到宿舍楼数据,返回空列表
+        if (buildingList.isEmpty()) {
+            return new ArrayList<>();
+        }
+
+        // 获取相关校区和宿舍区数据
+        List<DormBuildingInfoVo> campusList = dormBuildingTreeMapper.selectCampusList();
+        List<DormBuildingInfoVo> areaList = dormBuildingTreeMapper.selectAreaList();
+
+        // 构建校区节点集合(第一层)
+        Map<Long, DormBuildingTreeVo> campusMap = new LinkedHashMap<>();
+        for (DormBuildingInfoVo campus : campusList) {
+            // 校区只保留有权限的宿舍楼所在的校区
+            if (buildingList.stream().anyMatch(b -> Objects.equals(b.getCampusId(), campus.getId()))) {
+                DormBuildingTreeVo campusNode = new DormBuildingTreeVo();
+                campusNode.setId(campus.getId());
+                campusNode.setLabel(campus.getBuildingName());
+                campusNode.setType("campus");
+                campusNode.setDisabled(true); // 校区节点禁止点击
+                campusNode.setChildren(new ArrayList<>());
+                campusMap.put(campus.getId(), campusNode);
+            }
+        }
+
+        // 构建宿舍区节点(第二层)
+        Map<Long, DormBuildingTreeVo> areaMap = new HashMap<>();
+        for (DormBuildingInfoVo area : areaList) {
+            // 宿舍区只保留有权限的宿舍楼所在的宿舍区
+            if (buildingList.stream().anyMatch(b -> Objects.equals(b.getAreaId(), area.getId()))) {
+                DormBuildingTreeVo areaNode = new DormBuildingTreeVo();
+                areaNode.setId(area.getId());
+                areaNode.setLabel(area.getBuildingName());
+                areaNode.setType("area");
+                areaNode.setDisabled(true); // 宿舍区节点禁止点击
+                areaNode.setChildren(new ArrayList<>());
+                areaMap.put(area.getId(), areaNode);
+
+                // 将宿舍区节点添加到对应的校区节点下
+                DormBuildingTreeVo campusNode = campusMap.get(area.getCampusId());
+                if (campusNode != null) {
+                    campusNode.getChildren().add(areaNode);
+                }
+            }
+        }
+
+        // 构建宿舍楼节点(第三层)
+        for (DormBuildingInfoVo building : buildingList) {
+            DormBuildingTreeVo buildingNode = new DormBuildingTreeVo();
+            buildingNode.setId(building.getId());
+            buildingNode.setLabel(building.getBuildingName());
+            buildingNode.setType("building");
+            buildingNode.setDisabled(false); // 宿舍楼节点可点击
+            buildingNode.setBuildingFloors(building.getFloors());
+
+            // 将宿舍楼节点添加到对应的宿舍区节点下
+            DormBuildingTreeVo areaNode = areaMap.get(building.getAreaId());
+            if (areaNode != null) {
+                areaNode.getChildren().add(buildingNode);
+            }
+        }
+
+        // 返回树形结构的根节点列表(校区节点列表)
+        return new ArrayList<>(campusMap.values());
+    }
+}

+ 1 - 0
backend/ruoyi-modules/ruoyi-xg/src/main/resources/mapper/sslxx/XgDormBuildingMapper.xml

@@ -15,6 +15,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             c.campus_name,
             c.campus_name,
             b.building_type,
             b.building_type,
             b.building_description,
             b.building_description,
+            b.floors,
             b.sort_order,
             b.sort_order,
             b.deleted,
             b.deleted,
             b.remark,
             b.remark,

+ 297 - 0
backend/ruoyi-modules/ruoyi-xg/src/main/resources/mapper/xg/XgDormBuildingTreeMapper.xml

@@ -0,0 +1,297 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper
+PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="org.dromara.xg.mapper.XgDormBuildingTreeMapper">
+
+    <resultMap id="BuildingInfoMap" type="org.dromara.xg.domain.vo.DormBuildingInfoVo">
+        <id property="id" column="id"/>
+        <result property="buildingName" column="building_name"/>
+        <result property="buildingCode" column="building_code"/>
+        <result property="campusId" column="campus_id"/>
+        <result property="campusName" column="campus_name"/>
+        <result property="areaId" column="area_id"/>
+        <result property="areaName" column="area_name"/>
+        <result property="floors" column="floors"/>
+        <result property="remark" column="remark"/>
+        <result property="createBy" column="create_by"/>
+        <result property="createTime" column="create_time"/>
+        <result property="updateBy" column="update_by"/>
+        <result property="updateTime" column="update_time"/>
+    </resultMap>
+
+    <!-- 获取所有校区信息 -->
+    <select id="selectCampusList" resultMap="BuildingInfoMap">
+        SELECT
+            id,
+            campus_name as building_name,
+            '0' as status
+        FROM
+            xg_dorm_campus
+        WHERE
+            deleted = '0'
+    </select>
+
+    <!-- 获取所有宿舍区信息 -->
+    <select id="selectAreaList" resultMap="BuildingInfoMap">
+        SELECT
+            a.id,
+            a.area_name as building_name,
+            a.campus_id,
+            c.campus_name,
+            '0' as status
+        FROM
+            xg_dorm_area a
+        LEFT JOIN
+            xg_dorm_campus c ON a.campus_id = c.id
+        WHERE
+            a.deleted = '0'
+    </select>
+
+    <!-- 获取所有宿舍楼信息 -->
+    <select id="selectBuildingList" parameterType="org.dromara.xg.domain.bo.DormBuildingTreeBo" resultMap="BuildingInfoMap">
+        SELECT
+            b.id,
+            b.building_name,
+            b.building_code,
+            b.campus_id,
+            c.campus_name,
+            b.area_id,
+            a.area_name,
+            b.floors,
+            b.remark,
+            b.create_by,
+            b.create_time,
+            b.update_by,
+            b.update_time
+        FROM
+            xg_dorm_building b
+        LEFT JOIN
+            xg_dorm_campus c ON b.campus_id = c.id
+        LEFT JOIN
+            xg_dorm_area a ON b.area_id = a.id
+        WHERE
+            b.deleted = '0'
+        <if test="campusId != null">
+            AND b.campus_id = #{campusId}
+        </if>
+        <if test="areaId != null">
+            AND b.area_id = #{areaId}
+        </if>
+        <if test="buildingName != null and buildingName != ''">
+            AND b.building_name like concat('%', #{buildingName}, '%')
+        </if>
+        <if test="status != null and status != ''">
+            AND b.status = #{status}
+        </if>
+    </select>
+
+    <!-- 检查用户是否有宿舍管理权限 -->
+    <select id="checkUserDormManagerType" resultType="String">
+        SELECT
+            DISTINCT manager_type
+        FROM
+            xg_dorm_manager
+        WHERE
+            user_id = #{userId}
+            AND deleted = '0'
+    </select>
+
+    <!-- 获取全校管理员权限的宿舍楼信息 -->
+    <select id="selectBuildingsBySchoolAdmin" resultMap="BuildingInfoMap">
+        SELECT
+            b.id,
+            b.building_name,
+            b.building_code,
+            b.campus_id,
+            c.campus_name,
+            b.area_id,
+            a.area_name,
+            b.floors,
+            b.remark,
+            b.create_by,
+            b.create_time,
+            b.update_by,
+            b.update_time
+        FROM
+            xg_dorm_building b
+        LEFT JOIN
+            xg_dorm_campus c ON b.campus_id = c.id
+        LEFT JOIN
+            xg_dorm_area a ON b.area_id = a.id
+        WHERE
+            b.deleted = '0'
+            AND EXISTS (
+                SELECT 1 FROM xg_dorm_manager m
+                WHERE m.user_id = #{userId}
+                AND m.manager_type = '1'
+                AND m.deleted = '0'
+            )
+        <if test="bo.campusId != null">
+            AND b.campus_id = #{bo.campusId}
+        </if>
+        <if test="bo.areaId != null">
+            AND b.area_id = #{bo.areaId}
+        </if>
+        <if test="bo.buildingName != null and bo.buildingName != ''">
+            AND b.building_name like concat('%', #{bo.buildingName}, '%')
+        </if>
+        <if test="bo.status != null and bo.status != ''">
+            AND b.status = #{bo.status}
+        </if>
+    </select>
+
+    <!-- 获取校区管理员权限的宿舍楼信息 -->
+    <select id="selectBuildingsByCampusAdmin" resultMap="BuildingInfoMap">
+        SELECT
+            b.id,
+            b.building_name,
+            b.building_code,
+            b.campus_id,
+            c.campus_name,
+            b.area_id,
+            a.area_name,
+            b.floors,
+            b.remark,
+            b.create_by,
+            b.create_time,
+            b.update_by,
+            b.update_time
+        FROM
+            xg_dorm_building b
+        LEFT JOIN
+            xg_dorm_campus c ON b.campus_id = c.id
+        LEFT JOIN
+            xg_dorm_area a ON b.area_id = a.id
+        WHERE
+            b.deleted = '0'
+            AND b.campus_id IN (
+                SELECT
+                    auth_source
+                FROM
+                    xg_dorm_manager m
+                JOIN
+                    xg_dorm_manager_source s ON m.id = s.manager_id
+                WHERE
+                    m.user_id = #{userId}
+                    AND m.manager_type = '2'
+                    AND m.deleted = '0'
+                    AND s.deleted = '0'
+            )
+        <if test="bo.campusId != null">
+            AND b.campus_id = #{bo.campusId}
+        </if>
+        <if test="bo.areaId != null">
+            AND b.area_id = #{bo.areaId}
+        </if>
+        <if test="bo.buildingName != null and bo.buildingName != ''">
+            AND b.building_name like concat('%', #{bo.buildingName}, '%')
+        </if>
+        <if test="bo.status != null and bo.status != ''">
+            AND b.status = #{bo.status}
+        </if>
+    </select>
+
+    <!-- 获取宿舍区管理员权限的宿舍楼信息 -->
+    <select id="selectBuildingsByAreaAdmin" resultMap="BuildingInfoMap">
+        SELECT
+            b.id,
+            b.building_name,
+            b.building_code,
+            b.campus_id,
+            c.campus_name,
+            b.area_id,
+            a.area_name,
+            b.floors,
+            b.remark,
+            b.create_by,
+            b.create_time,
+            b.update_by,
+            b.update_time
+        FROM
+            xg_dorm_building b
+        LEFT JOIN
+            xg_dorm_campus c ON b.campus_id = c.id
+        LEFT JOIN
+            xg_dorm_area a ON b.area_id = a.id
+        WHERE
+            b.deleted = '0'
+            AND b.area_id IN (
+                SELECT
+                    auth_source
+                FROM
+                    xg_dorm_manager m
+                JOIN
+                    xg_dorm_manager_source s ON m.id = s.manager_id
+                WHERE
+                    m.user_id = #{userId}
+                    AND m.manager_type = '3'
+                    AND m.deleted = '0'
+                    AND s.deleted = '0'
+            )
+        <if test="bo.campusId != null">
+            AND b.campus_id = #{bo.campusId}
+        </if>
+        <if test="bo.areaId != null">
+            AND b.area_id = #{bo.areaId}
+        </if>
+        <if test="bo.buildingName != null and bo.buildingName != ''">
+            AND b.building_name like concat('%', #{bo.buildingName}, '%')
+        </if>
+        <if test="bo.status != null and bo.status != ''">
+            AND b.status = #{bo.status}
+        </if>
+    </select>
+
+    <!-- 获取宿舍楼管理员权限的宿舍楼信息 -->
+    <select id="selectBuildingsByBuildingAdmin" resultMap="BuildingInfoMap">
+        SELECT
+            b.id,
+            b.building_name,
+            b.building_code,
+            b.campus_id,
+            c.campus_name,
+            b.area_id,
+            a.area_name,
+            b.floors,
+            b.remark,
+            b.create_by,
+            b.create_time,
+            b.update_by,
+            b.update_time
+        FROM
+            xg_dorm_building b
+        LEFT JOIN
+            xg_dorm_campus c ON b.campus_id = c.id
+        LEFT JOIN
+            xg_dorm_area a ON b.area_id = a.id
+        WHERE
+            b.deleted = '0'
+            AND b.id IN (
+                SELECT
+                    auth_source
+                FROM
+                    xg_dorm_manager m
+                JOIN
+                    xg_dorm_manager_source s ON m.id = s.manager_id
+                WHERE
+                    m.user_id = #{userId}
+                    AND m.manager_type = '4'
+                    AND m.deleted = '0'
+                    AND s.deleted = '0'
+            )
+        <if test="bo.campusId != null">
+            AND b.campus_id = #{bo.campusId}
+        </if>
+        <if test="bo.areaId != null">
+            AND b.area_id = #{bo.areaId}
+        </if>
+        <if test="bo.buildingName != null and bo.buildingName != ''">
+            AND b.building_name like concat('%', #{bo.buildingName}, '%')
+        </if>
+        <if test="bo.status != null and bo.status != ''">
+            AND b.status = #{bo.status}
+        </if>
+    </select>
+
+</mapper>

+ 67 - 46
docs/变更管理/code-adjust-record-2025-07-03-cursor.md

@@ -1,62 +1,83 @@
-# 宿舍楼房间管理功能开发记录
+# 宿舍楼树形结构API开发变更记录
 
 
-**日期:** 2025-07-03 14:30:25  
-**开发人员:** Cursor  
-**功能模块:** 学生宿舍管理系统 - 宿舍楼房间管理
+**日期**: 2025-07-03
+**作者**: cursor
+**模块**: 学生宿舍管理
 
 
 ## 变更内容
 ## 变更内容
 
 
-### 1. 功能概述
+### 1. 新增实体类
 
 
-开发了宿舍楼房间管理界面,实现了以下功能:
-- 左侧树形结构展示校区-宿舍区-宿舍楼的层级关系
-- 右侧按楼层展示房间信息,采用卡片式布局
-- 支持房间的添加、编辑、删除操作
-- 支持床位的添加、编辑、删除操作
-- 支持按房间号和状态进行筛选
+- 创建 `DormBuildingTreeVo.java`: 实现宿舍楼树形结构VO类,包含id、label、type、disabled、buildingFloors、children等字段
+- 创建 `DormBuildingInfoVo.java`: 实现宿舍楼信息VO类,用于数据库查询结果映射
+- 创建 `DormBuildingTreeBo.java`: 实现查询参数业务对象类,包含campusId、areaId、buildingName、status等字段
 
 
-### 2. 文件变更
+### 2. 新增Mapper接口和XML
 
 
-#### 新增文件
-- `web/src/views/xsssfjgl/index.vue` - 宿舍楼房间管理主界面
-- `web/src/views/xsssfjgl/components/RoomDialog.vue` - 房间编辑对话框组件
-- `web/src/views/xsssfjgl/components/BedDialog.vue` - 床位编辑对话框组件
-- `web/src/api/xsssfjgl/index.ts` - API接口实现
-- `web/src/api/xsssfjgl/types.ts` - API类型定义
+- 创建 `XgDormBuildingTreeMapper.java`: 包含获取校区、宿舍区、宿舍楼和检查用户权限等方法
+- 创建 `XgDormBuildingTreeMapper.xml`: 实现各种SQL查询,包括权限过滤逻辑
 
 
-### 3. 技术实现
+### 3. 新增服务接口和实现
 
 
-#### 3.1 树形结构设计
-- 采用Element Plus的Tree组件实现
-- 配置了disabled属性,使校区和宿舍区节点不可选
-- 只有宿舍楼节点可以被选中,并触发右侧数据加载
+- 创建 `IXgDormBuildingTreeService.java`: 定义获取宿舍楼树形结构的服务接口
+- 创建 `XgDormBuildingTreeServiceImpl.java`: 实现服务接口,包含按权限过滤和构建三级树形结构的逻辑
 
 
-#### 3.2 房间展示
-- 按楼层分组展示房间信息
-- 使用Grid布局实现自适应卡片排列
-- 每张卡片包含房间号、类型、床位使用情况和操作按钮
+### 4. 新增控制器
 
 
-#### 3.3 床位管理
-- 点击"床位管理"按钮弹出对话框
-- 表格展示该房间的所有床位信息
-- 支持床位的增删改操作
+- 创建 `XgDormBuildingTreeController.java`: 提供获取宿舍楼树形结构的REST接口
 
 
-#### 3.4 数据处理
-- 前期使用模拟数据进行界面开发
-- 预留了真实API接口,便于后期接入后端服务
-- 完整实现了增删改查的前端逻辑
+### 5. 新增API文档
 
 
-## 后续工作
+- 创建 `宿舍房间管理API.md`: 记录API接口的使用方法和参数说明
 
 
-1. 对接后端API,替换模拟数据
-2. 根据实际业务需求调整界面细节
-3. 增加权限控制逻辑
-4. 完善数据校验和错误处理
-5. 添加单元测试
+### 6. 代码优化与修复 (2025-07-03 16:25:30)
 
 
-## 注意事项
+- 修改 `XgDormBuildingTreeServiceImpl.java`: 优化宿舍楼查询逻辑,支持用户拥有多种角色权限的情况
+- 解决问题: 之前代码只会按优先级执行一种角色的查询,现在改为合并多种权限查询的结果
+- 实现思路:
+  - 保留全校管理员最高权限判断(可查看所有宿舍楼)
+  - 对于其他权限类型,分别查询并合并结果
+  - 使用HashSet确保宿舍楼不重复
+  - 修正了字段访问方法,使用getId()而不是getBuildingId()
 
 
-- 目前使用模拟数据,未与后端对接
-- 表单校验规则已基本实现,但可能需要根据业务规则调整
-- v-model:show-search 等指令存在linter错误,后续需要修复
-- 组件导入和类型引用存在linter错误,需要调整项目配置 
+### 7. API返回字段修复 (2025-07-23 10:30:15)
+
+- 修改 `XgDormBuildingMapper.xml`: 修复宿舍楼信息列表接口floors字段返回为null的问题
+- 解决问题: 宿舍楼信息查询接口未返回floors字段,导致前端显示为null
+- 修复详情:
+  - 在selectPageWithAreaAndCampusName方法的SELECT查询语句中添加了b.floors字段
+  - 确保与数据库表设计和实体类定义保持一致
+  - 完整路径: `/backend/ruoyi-modules/ruoyi-xg/src/main/resources/mapper/sslxx/XgDormBuildingMapper.xml`
+
+## 实现功能
+
+1. **三级树形结构**:
+   - 第一级:校区(不可点击)
+   - 第二级:宿舍区(不可点击)
+   - 第三级:宿舍楼(可点击)
+
+2. **多级数据权限**:
+   - 全校管理员(manager_type=1):可查看所有宿舍楼
+   - 校区管理员(manager_type=2):只能查看管理校区的宿舍楼
+   - 宿舍区管理员(manager_type=3):只能查看管理宿舍区的宿舍楼
+   - 宿舍楼管理员(manager_type=4):只能查看管理宿舍楼
+   - **新增:支持一个用户同时拥有多种管理员角色,数据权限取并集**
+
+3. **权限数据关联**:
+   - 通过 xg_dorm_manager 表获取用户权限类型
+   - 通过 xg_dorm_manager_source 表获取具体权限范围
+
+## API接口说明
+
+- **接口URL**: `/xgss/dormBuildingTree/list`
+- **请求方式**: GET
+- **权限要求**: `xgss:dormBuildingTree:list`
+- **可选参数**: campusId, areaId, buildingName, status
+- **返回格式**: 嵌套的树形结构JSON
+
+## 下一步计划
+
+1. 前端页面改造:将模拟数据替换为真实API调用
+2. 单元测试:编写测试用例验证API的功能和权限控制
+3. 集成测试:验证API在真实环境中的表现
+4. 完善文档:补充其他宿舍管理相关API的文档 

+ 10 - 1
docs/开发文档/API/API文档总览.md

@@ -9,7 +9,14 @@
 ## 学工管理模块
 ## 学工管理模块
 - [班干部管理API](班干部管理API.md)
 - [班干部管理API](班干部管理API.md)
 - [宿舍管理员授权API](宿舍管理员授权API.md)
 - [宿舍管理员授权API](宿舍管理员授权API.md)
-- [宿舍楼树形结构API](宿舍楼树形结构API.md) - 校区-宿舍区-宿舍楼三级树形结构数据
+- [宿舍楼树形结构API](宿舍楼树形结构API.md) - 校区-宿舍区-宿舍楼三级树形结构数据 (旧版API,路径: `/sslxx/dormBuilding/buildingTree`)
+
+## 宿舍管理相关API
+
+| API文档名称 | 说明 | 路径 |
+| ---------- | ---- | ---- |
+| [宿舍房间管理API](./宿舍房间管理API.md) | 提供宿舍楼树形结构API | `/xgss/dormBuildingTree/list` |
+| [宿舍房间管理API](./宿舍房间管理API.md) | 提供宿舍楼列表查询API | `/sslxx/dormBuilding/list` |
 
 
 ## 后勤管理
 ## 后勤管理
 
 
@@ -41,6 +48,8 @@
 
 
 ## 更新记录
 ## 更新记录
 
 
+- 2025-07-23:修复宿舍楼列表接口floors字段为null的问题,更新宿舍房间管理API文档
+- 2025-07-03:更新宿舍房间管理API,增强多角色权限支持
 - 2025-07-20:新增宿舍楼树形结构API文档
 - 2025-07-20:新增宿舍楼树形结构API文档
 - 2025-07-20:新增宿舍管理员授权API文档
 - 2025-07-20:新增宿舍管理员授权API文档
 - 2025-07-15:新增场地预约管理API文档
 - 2025-07-15:新增场地预约管理API文档

+ 187 - 413
docs/开发文档/API/宿舍房间管理API.md

@@ -1,79 +1,42 @@
 # 宿舍房间管理API文档
 # 宿舍房间管理API文档
 
 
-**版本:** 1.0.0  
-**作者:** Cursor  
-**更新日期:** 2025-07-03
-
 ## 目录
 ## 目录
 
 
-- [1. 概述](#1-概述)
-- [2. 接口基础信息](#2-接口基础信息)
-- [3. 宿舍楼树形结构接口](#3-宿舍楼树形结构接口)
-- [4. 房间管理接口](#4-房间管理接口)
-- [5. 床位管理接口](#5-床位管理接口)
-- [6. 数据字典](#6-数据字典)
-- [7. 错误码说明](#7-错误码说明)
-- [8. 移动端实现](#8-移动端实现)
-
-## 1. 概述
-
-本文档描述了宿舍楼房间管理模块的接口规范,包括宿舍楼树形结构查询、房间增删改查和床位管理等功能。
-
-### 1.1 应用场景
-
-- 学工处管理宿舍楼房间信息
-- 学生宿舍分配
-- 宿舍房间和床位状态维护
+- [1. 宿舍楼树形结构](#1-宿舍楼树形结构)
+  - [1.1 获取宿舍楼树形结构](#11-获取宿舍楼树形结构)
+- [2. 宿舍楼信息管理](#2-宿舍楼信息管理)
+  - [2.1 获取宿舍楼列表](#21-获取宿舍楼列表)
 
 
-### 1.2 功能列表
+## 1. 宿舍楼树形结构
 
 
-- 宿舍楼树形结构查询
-- 房间列表查询(支持分页和条件筛选)
-- 房间新增、修改、删除
-- 床位列表查询
-- 床位新增、修改、删除
+### 1.1 获取宿舍楼树形结构
 
 
-## 2. 接口基础信息
+#### 接口说明
 
 
-### 2.1 接口规范
+该接口用于获取宿舍楼的树形结构数据,按照校区-宿舍区-宿舍楼三级结构组织。校区和宿舍区节点不可点击,只有宿舍楼节点可以点击。
 
 
-- 接口采用RESTful风格
-- 请求和响应数据格式均为JSON
-- 所有接口均需要携带Token进行认证
-- 接口基础路径: `/xsssfjgl`
+#### 请求方式
 
 
-### 2.2 统一响应格式
-
-```json
-{
-  "code": 200,       // 响应状态码,200表示成功
-  "msg": "操作成功",  // 响应消息
-  "data": {}         // 响应数据,根据接口定义不同而不同
-}
 ```
 ```
-
-### 2.3 分页查询响应格式
-
-```json
-{
-  "code": 200,
-  "msg": "查询成功",
-  "rows": [],        // 数据列表
-  "total": 0         // 总记录数
-}
+GET /xgss/dormBuildingTree/list
 ```
 ```
 
 
-## 3. 宿舍楼树形结构接口
+#### 权限要求
 
 
-### 3.1 获取宿舍树形结构
+```
+xgss:dormBuildingTree:list
+```
 
 
-**接口说明:** 获取校区-宿舍区-宿舍楼的树形结构数据
+#### 请求参数
 
 
-- **请求方式:** GET
-- **请求路径:** `/xsssfjgl/tree`
-- **请求参数:** 无
+| 参数名        | 类型    | 必须 | 描述                 |
+| ------------- | ------- | ---- | -------------------- |
+| campusId      | Long    | 否   | 校区ID,用于筛选     |
+| areaId        | Long    | 否   | 宿舍区ID,用于筛选   |
+| buildingName  | String  | 否   | 宿舍楼名称,模糊查询 |
+| status        | String  | 否   | 宿舍楼状态           |
 
 
-**响应示例:**
+#### 返回结果
 
 
 ```json
 ```json
 {
 {
@@ -82,21 +45,44 @@
   "data": [
   "data": [
     {
     {
       "id": 1,
       "id": 1,
-      "label": "东校区",
+      "label": "主校区",
       "type": "campus",
       "type": "campus",
       "disabled": true,
       "disabled": true,
       "children": [
       "children": [
         {
         {
-          "id": 11,
+          "id": 101,
           "label": "东区宿舍",
           "label": "东区宿舍",
           "type": "area",
           "type": "area",
           "disabled": true,
           "disabled": true,
           "children": [
           "children": [
             {
             {
-              "id": 111,
-              "label": "东区1号楼",
+              "id": 1001,
+              "label": "1号楼",
               "type": "building",
               "type": "building",
+              "disabled": false,
               "buildingFloors": 6
               "buildingFloors": 6
+            },
+            {
+              "id": 1002,
+              "label": "2号楼",
+              "type": "building",
+              "disabled": false,
+              "buildingFloors": 5
+            }
+          ]
+        },
+        {
+          "id": 102,
+          "label": "西区宿舍",
+          "type": "area",
+          "disabled": true,
+          "children": [
+            {
+              "id": 1003,
+              "label": "3号楼",
+              "type": "building",
+              "disabled": false,
+              "buildingFloors": 7
             }
             }
           ]
           ]
         }
         }
@@ -106,384 +92,172 @@
 }
 }
 ```
 ```
 
 
-**字段说明:**
-
-| 字段名 | 类型 | 说明 |
-| ---- | ---- | ---- |
-| id | string/number | 节点ID |
-| label | string | 节点名称 |
-| type | string | 节点类型:campus(校区)、area(宿舍区)、building(宿舍楼) |
-| disabled | boolean | 是否禁用选择 |
-| children | array | 子节点 |
-| buildingFloors | number | 宿舍楼层数,仅type为building时有效 |
-
-## 4. 房间管理接口
-
-### 4.1 获取房间列表
-
-**接口说明:** 分页查询房间信息
-
-- **请求方式:** GET
-- **请求路径:** `/xsssfjgl/room/list`
-- **请求参数:**
-
-| 参数名 | 必填 | 类型 | 说明 |
-| ---- | ---- | ---- | ---- |
-| pageNum | 是 | number | 页码,从1开始 |
-| pageSize | 是 | number | 每页记录数 |
-| buildingId | 是 | string/number | 宿舍楼ID |
-| roomName | 否 | string | 房间名称,支持模糊查询 |
-| floorNumber | 否 | number | 楼层号 |
-| status | 否 | string | 房间状态:0-正常,1-维修中,2-停用 |
-
-**响应示例:**
-
-```json
-{
-  "code": 200,
-  "msg": "查询成功",
-  "rows": [
-    {
-      "roomId": "111101",
-      "roomName": "101",
-      "floorNumber": 1,
-      "buildingId": 111,
-      "capacity": 4,
-      "used": 2,
-      "roomType": "标准间",
-      "status": "0",
-      "remark": "",
-      "createBy": "admin",
-      "createTime": "2023-01-01 00:00:00",
-      "updateBy": "admin",
-      "updateTime": "2023-01-01 00:00:00"
+#### 返回参数说明
+
+| 参数名         | 类型    | 描述                                             |
+| -------------- | ------- | ------------------------------------------------ |
+| id             | Long    | 节点ID                                           |
+| label          | String  | 节点名称                                         |
+| type           | String  | 节点类型(campus:校区,area:宿舍区,building:宿舍楼) |
+| disabled       | Boolean | 是否禁用点击(校区和宿舍区为true,宿舍楼为false)     |
+| buildingFloors | Integer | 宿舍楼层数(只有宿舍楼节点有此字段)             |
+| children       | Array   | 子节点列表                                       |
+
+#### 数据权限说明
+
+接口会根据当前登录用户的权限进行数据过滤:
+
+1. 全校管理员(manager_type=1):可以查看所有校区、宿舍区和宿舍楼数据
+2. 校区管理员(manager_type=2):只能查看其管理的校区下的宿舍区和宿舍楼数据
+3. 宿舍区管理员(manager_type=3):只能查看其管理的宿舍区下的宿舍楼数据
+4. 宿舍楼管理员(manager_type=4):只能查看其管理的宿舍楼数据
+5. **多角色支持**:如果用户同时拥有多种管理员角色(如既是校区管理员又是宿舍楼管理员),将会合并所有权限范围内的数据。例如,一个用户同时是A校区管理员和B宿舍楼管理员,则可以看到A校区下的所有宿舍楼以及B宿舍楼。
+
+权限判断逻辑:
+- 通过 xg_dorm_manager 表的 user_id 与当前登录用户匹配,获取用户管理员类型
+- 根据 manager_type 确定权限级别
+- 通过 xg_dorm_manager_source 表的 auth_source 确定具体权限范围
+- **多角色权限合并**:合并不同角色对应的宿舍楼数据,确保不重复
+
+#### 错误码
+
+| 错误码 | 描述                 |
+| ------ | -------------------- |
+| 401    | 未授权,需要登录     |
+| 403    | 无权限访问该接口     |
+| 500    | 服务器内部错误       |
+
+#### 使用示例
+
+```javascript
+// 前端代码示例(使用axios)
+import axios from 'axios';
+
+// 获取宿舍楼树形结构
+async function getDormBuildingTree() {
+  try {
+    const response = await axios.get('/xgss/dormBuildingTree/list');
+    if (response.data.code === 200) {
+      return response.data.data;
     }
     }
-  ],
-  "total": 60
-}
-```
-
-### 4.2 获取房间详情
-
-**接口说明:** 根据房间ID获取详细信息
-
-- **请求方式:** GET
-- **请求路径:** `/xsssfjgl/room/{roomId}`
-- **请求参数:**
-
-| 参数名 | 必填 | 类型 | 说明 |
-| ---- | ---- | ---- | ---- |
-| roomId | 是 | string/number | 房间ID |
-
-**响应示例:**
-
-```json
-{
-  "code": 200,
-  "msg": "操作成功",
-  "data": {
-    "roomId": "111101",
-    "roomName": "101",
-    "floorNumber": 1,
-    "buildingId": 111,
-    "capacity": 4,
-    "used": 2,
-    "roomType": "标准间",
-    "status": "0",
-    "remark": "",
-    "createBy": "admin",
-    "createTime": "2023-01-01 00:00:00",
-    "updateBy": "admin",
-    "updateTime": "2023-01-01 00:00:00"
+  } catch (error) {
+    console.error('获取宿舍楼树失败:', error);
   }
   }
+  return [];
 }
 }
 ```
 ```
 
 
-### 4.3 新增房间
+## 2. 宿舍楼信息管理
 
 
-**接口说明:** 新增宿舍房间
+### 2.1 获取宿舍楼列表
 
 
-- **请求方式:** POST
-- **请求路径:** `/xsssfjgl/room`
-- **请求参数:**
+#### 接口说明
 
 
-```json
-{
-  "roomName": "101",
-  "floorNumber": 1,
-  "buildingId": 111,
-  "capacity": 4,
-  "roomType": "标准间",
-  "status": "0",
-  "remark": "新增房间"
-}
-```
+该接口用于获取宿舍楼信息的分页列表,包含宿舍楼基本信息以及关联的校区和宿舍区信息。
 
 
-**响应示例:**
+#### 请求方式
 
 
-```json
-{
-  "code": 200,
-  "msg": "操作成功"
-}
 ```
 ```
-
-### 4.4 修改房间
-
-**接口说明:** 修改宿舍房间信息
-
-- **请求方式:** PUT
-- **请求路径:** `/xsssfjgl/room`
-- **请求参数:**
-
-```json
-{
-  "roomId": "111101",
-  "roomName": "101",
-  "floorNumber": 1,
-  "buildingId": 111,
-  "capacity": 4,
-  "roomType": "标准间",
-  "status": "0",
-  "remark": "修改房间信息"
-}
+GET /sslxx/dormBuilding/list
 ```
 ```
 
 
-**响应示例:**
+#### 权限要求
 
 
-```json
-{
-  "code": 200,
-  "msg": "操作成功"
-}
 ```
 ```
-
-### 4.5 删除房间
-
-**接口说明:** 删除宿舍房间
-
-- **请求方式:** DELETE
-- **请求路径:** `/xsssfjgl/room/{roomIds}`
-- **请求参数:**
-
-| 参数名 | 必填 | 类型 | 说明 |
-| ---- | ---- | ---- | ---- |
-| roomIds | 是 | string | 房间ID,多个ID用逗号分隔 |
-
-**响应示例:**
-
-```json
-{
-  "code": 200,
-  "msg": "操作成功"
-}
+sslxx:dormBuilding:list
 ```
 ```
 
 
-## 5. 床位管理接口
-
-### 5.1 获取床位列表
-
-**接口说明:** 查询指定房间的床位列表
-
-- **请求方式:** GET
-- **请求路径:** `/xsssfjgl/bed/list`
-- **请求参数:**
+#### 请求参数
 
 
-| 参数名 | 必填 | 类型 | 说明 |
-| ---- | ---- | ---- | ---- |
-| roomId | 是 | string/number | 房间ID |
+| 参数名          | 类型    | 必须 | 描述                   |
+| --------------- | ------- | ---- | ---------------------- |
+| pageNum         | Integer | 是   | 当前页码,从1开始      |
+| pageSize        | Integer | 是   | 每页记录数             |
+| buildingCode    | String  | 否   | 宿舍楼编码,模糊查询   |
+| buildingName    | String  | 否   | 宿舍楼名称,模糊查询   |
+| areaId          | Long    | 否   | 宿舍区ID,精确查询     |
+| campusId        | Long    | 否   | 校区ID,精确查询       |
+| buildingType    | String  | 否   | 宿舍楼类型(1男生楼 2女生楼 3混合楼) |
 
 
-**响应示例:**
+#### 返回结果
 
 
 ```json
 ```json
 {
 {
-  "code": 200,
-  "msg": "操作成功",
-  "data": [
-    {
-      "bedId": "111101-1",
-      "bedName": "1号床",
-      "roomId": "111101",
-      "status": "0",
-      "studentId": null,
-      "studentName": null,
-      "remark": "",
-      "createBy": "admin",
-      "createTime": "2023-01-01 00:00:00",
-      "updateBy": "admin",
-      "updateTime": "2023-01-01 00:00:00"
-    },
+  "total": 1,
+  "rows": [
     {
     {
-      "bedId": "111101-2",
-      "bedName": "2号床",
-      "roomId": "111101",
-      "status": "1",
-      "studentId": 10001,
-      "studentName": "张三",
-      "remark": "",
-      "createBy": "admin",
-      "createTime": "2023-01-01 00:00:00",
-      "updateBy": "admin",
-      "updateTime": "2023-01-01 00:00:00"
+      "id": "1947459199879495681",
+      "buildingCode": "xixi-ssq01-ssl01",
+      "buildingName": "西溪校区-宿舍区01-宿舍楼01",
+      "areaId": "1946829650430935041",
+      "areaName": "西溪校区-宿舍区01",
+      "campusId": "1946815553291304962",
+      "campusName": "西溪校区",
+      "buildingType": "1",
+      "buildingDescription": "12312",
+      "sortOrder": 1,
+      "floors": 6,
+      "createBy": 1,
+      "createTime": "2025-07-22 08:50:30",
+      "updateBy": 1,
+      "updateTime": "2025-07-22 08:51:06"
     }
     }
-  ]
-}
-```
-
-### 5.2 新增床位
-
-**接口说明:** 新增床位
-
-- **请求方式:** POST
-- **请求路径:** `/xsssfjgl/bed`
-- **请求参数:**
-
-```json
-{
-  "bedName": "3号床",
-  "roomId": "111101",
-  "status": "0",
-  "remark": "新增床位"
-}
-```
-
-**响应示例:**
-
-```json
-{
-  "code": 200,
-  "msg": "操作成功"
-}
-```
-
-### 5.3 修改床位
-
-**接口说明:** 修改床位信息
-
-- **请求方式:** PUT
-- **请求路径:** `/xsssfjgl/bed`
-- **请求参数:**
-
-```json
-{
-  "bedId": "111101-3",
-  "bedName": "3号床",
-  "roomId": "111101",
-  "status": "1",
-  "remark": "修改床位信息"
-}
-```
-
-**响应示例:**
-
-```json
-{
-  "code": 200,
-  "msg": "操作成功"
-}
-```
-
-### 5.4 删除床位
-
-**接口说明:** 删除床位
-
-- **请求方式:** DELETE
-- **请求路径:** `/xsssfjgl/bed/{bedIds}`
-- **请求参数:**
-
-| 参数名 | 必填 | 类型 | 说明 |
-| ---- | ---- | ---- | ---- |
-| bedIds | 是 | string | 床位ID,多个ID用逗号分隔 |
-
-**响应示例:**
-
-```json
-{
+  ],
   "code": 200,
   "code": 200,
-  "msg": "操作成功"
+  "msg": "查询成功"
 }
 }
 ```
 ```
 
 
-## 6. 数据字典
-
-### 6.1 房间状态
-
-| 状态码 | 说明 |
-| ---- | ---- |
-| 0 | 正常 |
-| 1 | 维修中 |
-| 2 | 停用 |
-
-### 6.2 床位状态
-
-| 状态码 | 说明 |
-| ---- | ---- |
-| 0 | 空闲 |
-| 1 | 已分配 |
-| 2 | 维修中 |
-
-### 6.3 房间类型
-
-| 类型 | 说明 |
-| ---- | ---- |
-| 标准间 | 标准宿舍,通常4-6人 |
-| 单人间 | 单人宿舍 |
-| 套间 | 带独立卫浴的宿舍 |
-
-## 7. 错误码说明
-
-| 错误码 | 说明 |
-| ---- | ---- |
-| 200 | 操作成功 |
-| 400 | 请求参数错误 |
-| 401 | 未授权 |
-| 403 | 禁止访问 |
-| 404 | 资源不存在 |
-| 500 | 系统内部错误 |
-| 1001 | 房间名称已存在 |
-| 1002 | 房间包含已分配的床位,无法删除 |
-| 1003 | 床位已分配给学生,无法删除 |
-
-## 8. 移动端实现
-
-### 8.1 移动端适配说明
-
-移动端将实现以下功能:
-- 宿舍楼列表查看(无树形结构,改用列表+筛选)
-- 房间信息查看
-- 床位信息查看
-
-暂不支持在移动端进行房间和床位的增删改操作,仅支持查询功能。
-
-### 8.2 特殊API
-
-移动端将使用与PC端相同的API,但增加以下特殊接口:
-
-**获取宿舍楼列表:**
-
-- **请求方式:** GET
-- **请求路径:** `/xsssfjgl/mobile/buildings`
-- **请求参数:**
-
-| 参数名 | 必填 | 类型 | 说明 |
-| ---- | ---- | ---- | ---- |
-| campusId | 否 | string/number | 校区ID |
-| areaId | 否 | string/number | 宿舍区ID |
-
-**响应示例:**
-
-```json
-{
-  "code": 200,
-  "msg": "操作成功",
-  "data": [
-    {
-      "buildingId": 111,
-      "buildingName": "东区1号楼",
-      "campusName": "东校区",
-      "areaName": "东区宿舍",
-      "floors": 6
+#### 返回参数说明
+
+| 参数名             | 类型    | 描述                                     |
+| ------------------ | ------- | ---------------------------------------- |
+| id                 | Long    | 宿舍楼主键ID                             |
+| buildingCode       | String  | 宿舍楼编码                               |
+| buildingName       | String  | 宿舍楼名称                               |
+| areaId             | Long    | 所属宿舍区ID                             |
+| areaName           | String  | 所属宿舍区名称                           |
+| campusId           | Long    | 所属校区ID                               |
+| campusName         | String  | 所属校区名称                             |
+| buildingType       | String  | 宿舍楼类型(1男生楼 2女生楼 3混合楼)      |
+| buildingDescription | String  | 宿舍楼描述                               |
+| sortOrder          | Integer | 排序号                                   |
+| floors             | Integer | 总楼层数                                 |
+| createBy           | Long    | 创建者ID                                 |
+| createTime         | Date    | 创建时间                                 |
+| updateBy           | Long    | 更新者ID                                 |
+| updateTime         | Date    | 更新时间                                 |
+
+#### 错误码
+
+| 错误码 | 描述                 |
+| ------ | -------------------- |
+| 401    | 未授权,需要登录     |
+| 403    | 无权限访问该接口     |
+| 500    | 服务器内部错误       |
+
+#### 使用示例
+
+```javascript
+// 前端代码示例(使用axios)
+import axios from 'axios';
+
+// 获取宿舍楼列表
+async function getDormBuildingList(params) {
+  try {
+    const response = await axios.get('/sslxx/dormBuilding/list', { 
+      params: { 
+        pageNum: 1, 
+        pageSize: 10,
+        ...params 
+      } 
+    });
+    if (response.data.code === 200) {
+      return response.data;
     }
     }
-  ]
+  } catch (error) {
+    console.error('获取宿舍楼列表失败:', error);
+  }
+  return { total: 0, rows: [] };
 }
 }
 ``` 
 ``` 

+ 1 - 0
docs/设计文档/database/学工管理-宿舍管理/宿舍管理数据库建表脚本.sql

@@ -54,6 +54,7 @@ create table `xg_dorm_building` (
   `building_name` varchar(100) not null comment '宿舍楼名称',
   `building_name` varchar(100) not null comment '宿舍楼名称',
   `area_id` bigint(20) not null comment '所属宿舍区ID',
   `area_id` bigint(20) not null comment '所属宿舍区ID',
   `campus_id` bigint(20) not null comment '所属校区ID',
   `campus_id` bigint(20) not null comment '所属校区ID',
+  `floors` int(11) not null default '6'  comment '总楼层数',
   `building_type` char(1) default '1' comment '宿舍楼类型(1男生楼 2女生楼 3混合楼)',
   `building_type` char(1) default '1' comment '宿舍楼类型(1男生楼 2女生楼 3混合楼)',
   `building_description` varchar(500) default null comment '宿舍楼描述',
   `building_description` varchar(500) default null comment '宿舍楼描述',
   `sort_order` int(11) default '0' comment '排序号',
   `sort_order` int(11) default '0' comment '排序号',

+ 3 - 0
web/src/api/xgss/sslxx/dormBuilding/types.ts

@@ -14,6 +14,7 @@ export interface DormBuildingVO {
   remark: string;
   remark: string;
   areaName?: string;
   areaName?: string;
   campusName?: string;
   campusName?: string;
+  floors: number;
 }
 }
 
 
 export interface DormBuildingForm extends Omit<DormBuildingVO, 'createTime' | 'createBy' | 'updateTime' | 'updateBy' | 'areaName' | 'campusName'> {
 export interface DormBuildingForm extends Omit<DormBuildingVO, 'createTime' | 'createBy' | 'updateTime' | 'updateBy' | 'areaName' | 'campusName'> {
@@ -25,6 +26,7 @@ export interface DormBuildingQuery {
   areaId?: string | number;
   areaId?: string | number;
   campusId?: string | number;
   campusId?: string | number;
   buildingType?: string;
   buildingType?: string;
+  floors?: number;
   params?: Record<string, any>;
   params?: Record<string, any>;
 }
 }
 
 
@@ -40,6 +42,7 @@ export interface BuildingTreeSelectVo {
   createBy?: number;
   createBy?: number;
   createTime?: string;
   createTime?: string;
   updateBy?: number;
   updateBy?: number;
+  floors?: number;
   updateTime?: string;
   updateTime?: string;
 }
 }
 
 

+ 2 - 2
web/src/api/xgss/xsssfjgl/index.ts

@@ -5,11 +5,11 @@ import { DormQuery, RoomForm, BedForm, DormTreeNode, RoomInfo, BedInfo } from '.
 const baseUrl = '/xsssfjgl';
 const baseUrl = '/xsssfjgl';
 
 
 /**
 /**
- * 获取宿舍树形结构
+ * 获取宿舍楼树形结构
  */
  */
 export function getDormTree() {
 export function getDormTree() {
   return request({
   return request({
-    url: baseUrl + '/tree',
+    url: '/xgss/dormBuildingTree/list',
     method: 'get'
     method: 'get'
   });
   });
 }
 }

+ 18 - 2
web/src/views/xgss/sslxx/dormBuilding/index.vue

@@ -86,6 +86,7 @@
         <el-table-column label="宿舍楼名称" align="center" prop="buildingName" />
         <el-table-column label="宿舍楼名称" align="center" prop="buildingName" />
         <el-table-column label="所属校区" align="center" prop="campusName" />
         <el-table-column label="所属校区" align="center" prop="campusName" />
         <el-table-column label="所属宿舍区" align="center" prop="areaName" />
         <el-table-column label="所属宿舍区" align="center" prop="areaName" />
+        <el-table-column label="总楼层数" align="center" prop="floors" />
         <el-table-column label="宿舍楼类型" align="center" prop="buildingType">
         <el-table-column label="宿舍楼类型" align="center" prop="buildingType">
           <template #default="scope">
           <template #default="scope">
             <dict-tag :options="dorm_type" :value="scope.row.buildingType" />
             <dict-tag :options="dorm_type" :value="scope.row.buildingType" />
@@ -128,7 +129,18 @@
           <el-input v-model="form.buildingCode" placeholder="请输入宿舍楼编码" />
           <el-input v-model="form.buildingCode" placeholder="请输入宿舍楼编码" />
         </el-form-item>
         </el-form-item>
         <el-form-item label="宿舍楼名称" prop="buildingName">
         <el-form-item label="宿舍楼名称" prop="buildingName">
-          <el-input v-model="form.buildingName" placeholder="请输入宿舍楼名称" />
+          <el-input v-model="form.buildingName" placeholder="请输入宿舍楼名称" class="fixed-width-input" />
+        </el-form-item>
+        <el-form-item label="总楼层数" prop="floors">
+          <el-input-number
+            v-model="form.floors"
+            :min="1"
+            :max="99"
+            :step="1"
+            :default-value="6"
+            placeholder="请输入总楼层数"
+            class="fixed-width-input"
+          />
         </el-form-item>
         </el-form-item>
         <el-form-item label="宿舍楼类型" prop="buildingType">
         <el-form-item label="宿舍楼类型" prop="buildingType">
           <el-select v-model="form.buildingType" placeholder="请选择宿舍楼类型">
           <el-select v-model="form.buildingType" placeholder="请选择宿舍楼类型">
@@ -198,7 +210,8 @@ const initFormData: DormBuildingForm = {
   campusId: undefined,
   campusId: undefined,
   buildingType: undefined,
   buildingType: undefined,
   buildingDescription: undefined,
   buildingDescription: undefined,
-  sortOrder: undefined
+  sortOrder: undefined,
+  floors: 6 // 添加默认值为6
 };
 };
 const data = reactive<PageData<DormBuildingForm, DormBuildingQuery>>({
 const data = reactive<PageData<DormBuildingForm, DormBuildingQuery>>({
   form: { ...initFormData },
   form: { ...initFormData },
@@ -537,4 +550,7 @@ onMounted(() => {
     margin-bottom: 0 !important;
     margin-bottom: 0 !important;
   }
   }
 }
 }
+.fixed-width-input {
+  width: 100%;
+}
 </style>
 </style>

+ 56 - 36
web/src/views/xgss/xsssfjgl/index.vue

@@ -1,10 +1,18 @@
 <template>
 <template>
   <div class="p-2">
   <div class="p-2">
-    <el-row :gutter="20">
+    <div class="flex-layout">
       <!-- 宿舍树 -->
       <!-- 宿舍树 -->
-      <el-col :lg="4" :xs="24">
+      <div class="tree-sidebar">
         <el-card shadow="hover">
         <el-card shadow="hover">
-          <el-input v-model="buildingName" placeholder="请输入宿舍楼名称" prefix-icon="Search" clearable />
+          <el-input
+            v-model="buildingName"
+            prefix-icon="Search"
+            placeholder="请输入宿舍楼名称"
+            clearable
+            @clear="watchBuildingName"
+            @keyup.enter="watchBuildingName"
+          >
+          </el-input>
           <el-tree
           <el-tree
             ref="dormTreeRef"
             ref="dormTreeRef"
             class="mt-2"
             class="mt-2"
@@ -18,9 +26,9 @@
             @node-click="handleNodeClick"
             @node-click="handleNodeClick"
           />
           />
         </el-card>
         </el-card>
-      </el-col>
+      </div>
 
 
-      <el-col :lg="20" :xs="24">
+      <div class="content-area">
         <transition :enter-active-class="animate.searchAnimate.enter" :leave-active-class="animate.searchAnimate.leave">
         <transition :enter-active-class="animate.searchAnimate.enter" :leave-active-class="animate.searchAnimate.leave">
           <div v-show="showSearch" class="mb-[10px]">
           <div v-show="showSearch" class="mb-[10px]">
             <el-card shadow="hover">
             <el-card shadow="hover">
@@ -109,8 +117,8 @@
             </div>
             </div>
           </el-card>
           </el-card>
         </template>
         </template>
-      </el-col>
-    </el-row>
+      </div>
+    </div>
 
 
     <!-- 房间管理对话框 -->
     <!-- 房间管理对话框 -->
     <room-dialog
     <room-dialog
@@ -159,21 +167,11 @@
 </template>
 </template>
 
 
 <script setup name="DormRoomManagement" lang="ts">
 <script setup name="DormRoomManagement" lang="ts">
-import { ref, computed, reactive, onMounted, nextTick } from 'vue';
+import { ref, computed, reactive, onMounted, nextTick, watch } from 'vue';
 import { ElMessageBox, ElMessage } from 'element-plus';
 import { ElMessageBox, ElMessage } from 'element-plus';
-import { InfoFilled } from '@element-plus/icons-vue';
+import { InfoFilled, Search } from '@element-plus/icons-vue';
 import { DormTreeNode, RoomInfo, BedInfo, DormQuery } from '@/api/xgss/xsssfjgl/types';
 import { DormTreeNode, RoomInfo, BedInfo, DormQuery } from '@/api/xgss/xsssfjgl/types';
-import {
-  getDormTree,
-  listRooms,
-  delRoom,
-  listBeds,
-  delBed,
-  // 以下为模拟数据
-  getMockDormTree,
-  getMockRooms,
-  getMockBeds
-} from '@/api/xgss/xsssfjgl';
+import { getDormTree, listRooms, delRoom, listBeds, delBed } from '@/api/xgss/xsssfjgl';
 
 
 // 引入子组件
 // 引入子组件
 import RoomDialog from './components/RoomDialog.vue';
 import RoomDialog from './components/RoomDialog.vue';
@@ -242,7 +240,7 @@ const bedLoading = ref(false);
 /** 通过条件过滤节点 */
 /** 通过条件过滤节点 */
 const filterNode = (value: string, data: DormTreeNode) => {
 const filterNode = (value: string, data: DormTreeNode) => {
   if (!value) return true;
   if (!value) return true;
-  return data.label.indexOf(value) !== -1;
+  return data.label.toLowerCase().indexOf(value.toLowerCase()) !== -1;
 };
 };
 
 
 /** 监听宿舍楼名称变化,筛选树 */
 /** 监听宿舍楼名称变化,筛选树 */
@@ -250,12 +248,15 @@ const watchBuildingName = () => {
   dormTreeRef.value?.filter(buildingName.value);
   dormTreeRef.value?.filter(buildingName.value);
 };
 };
 
 
+// 监听buildingName变化,实时筛选宿舍楼
+watch(buildingName, () => {
+  watchBuildingName();
+});
+
 /** 获取宿舍树数据 */
 /** 获取宿舍树数据 */
 const getDormTreeData = async () => {
 const getDormTreeData = async () => {
   try {
   try {
-    // const res = await getDormTree();
-    // 使用模拟数据
-    const res = getMockDormTree();
+    const res = await getDormTree();
     dormOptions.value = res.data;
     dormOptions.value = res.data;
   } catch (error) {
   } catch (error) {
     console.error('获取宿舍树失败', error);
     console.error('获取宿舍树失败', error);
@@ -279,9 +280,7 @@ const loadRoomData = async () => {
   if (!queryParams.buildingId) return;
   if (!queryParams.buildingId) return;
 
 
   try {
   try {
-    // const res = await listRooms(queryParams);
-    // 使用模拟数据
-    const res = getMockRooms(queryParams.buildingId);
+    const res = await listRooms(queryParams);
     roomList.value = res.rows;
     roomList.value = res.rows;
   } catch (error) {
   } catch (error) {
     console.error('获取房间列表失败', error);
     console.error('获取房间列表失败', error);
@@ -366,9 +365,7 @@ const handleManageBeds = async (room: RoomInfo) => {
 const loadBedData = async (roomId: string | number) => {
 const loadBedData = async (roomId: string | number) => {
   bedLoading.value = true;
   bedLoading.value = true;
   try {
   try {
-    // const res = await listBeds(roomId);
-    // 使用模拟数据
-    const res = getMockBeds(roomId);
+    const res = await listBeds(roomId);
     bedList.value = res.data;
     bedList.value = res.data;
   } catch (error) {
   } catch (error) {
     console.error('获取床位列表失败', error);
     console.error('获取床位列表失败', error);
@@ -420,16 +417,39 @@ const handleBedSuccess = () => {
 
 
 onMounted(() => {
 onMounted(() => {
   getDormTreeData();
   getDormTreeData();
-
-  // 监听宿舍楼名称变化
-  nextTick(() => {
-    buildingName.value = '';
-    watchBuildingName();
-  });
 });
 });
+
+// 确保树加载后才能过滤
+watch(
+  dormOptions,
+  () => {
+    if (buildingName.value) {
+      nextTick(() => {
+        watchBuildingName();
+      });
+    }
+  },
+  { deep: true }
+);
 </script>
 </script>
 
 
 <style scoped>
 <style scoped>
+.flex-layout {
+  display: flex;
+  gap: 20px;
+}
+
+.tree-sidebar {
+  min-width: 320px;
+  max-width: 320px;
+  flex-shrink: 0;
+}
+
+.content-area {
+  flex: 1;
+  min-width: 0; /* 防止内容溢出 */
+}
+
 .room-container {
 .room-container {
   width: 100%;
   width: 100%;
 }
 }

+ 2 - 9
web/src/views/xgss/xsssgly/index.vue

@@ -418,15 +418,8 @@ function onScope(type: string, admin: any) {
   scopeDialogVisible.value = true;
   scopeDialogVisible.value = true;
 }
 }
 function onDialogSubmit(admin: any) {
 function onDialogSubmit(admin: any) {
-  // TODO: 新增/编辑时调用API,成功后刷新
-  const list = getListByType(activeTab.value);
-  if (dialogMode.value === 'add') {
-    admin.id = Date.now();
-    list.value.push(admin);
-  } else {
-    const idx = list.value.findIndex((a: any) => a.id === admin.id);
-    if (idx !== -1) list.value[idx] = { ...admin };
-  }
+  // 修改后立即刷新列表数据
+  fetchAdmins(activeTab.value);
   dialogVisible.value = false;
   dialogVisible.value = false;
 }
 }
 async function onScopeSubmit(scope: any) {
 async function onScopeSubmit(scope: any) {