提交房间分配给二级学院的业务代码
This commit is contained in:
1 parent
7593904a79
commit
b5e6ca3cce
27 files changed
+2727
-55
No files matched your search
+105
@@ -0,0 +1,105 @@
|
||||
package org.dromara.xg.controller;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import jakarta.validation.constraints.*;
|
||||
import cn.dev33.satoken.annotation.SaCheckPermission;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.dromara.common.idempotent.annotation.RepeatSubmit;
|
||||
import org.dromara.common.log.annotation.Log;
|
||||
import org.dromara.common.web.core.BaseController;
|
||||
import org.dromara.common.mybatis.core.page.PageQuery;
|
||||
import org.dromara.common.core.domain.R;
|
||||
import org.dromara.common.core.validate.AddGroup;
|
||||
import org.dromara.common.core.validate.EditGroup;
|
||||
import org.dromara.common.log.enums.BusinessType;
|
||||
import org.dromara.common.excel.utils.ExcelUtil;
|
||||
import org.dromara.xg.domain.vo.XgDormBedVo;
|
||||
import org.dromara.xg.domain.bo.XgDormBedBo;
|
||||
import org.dromara.xg.service.IXgDormBedService;
|
||||
import org.dromara.common.mybatis.core.page.TableDataInfo;
|
||||
|
||||
/**
|
||||
* 宿舍床位信息
|
||||
*
|
||||
* @author zlwu
|
||||
* @date 2025-07-22
|
||||
*/
|
||||
@Validated
|
||||
@RequiredArgsConstructor
|
||||
@RestController
|
||||
@RequestMapping("/dormbed/dormBed")
|
||||
public class XgDormBedController extends BaseController {
|
||||
|
||||
private final IXgDormBedService xgDormBedService;
|
||||
|
||||
/**
|
||||
* 查询宿舍床位信息列表
|
||||
*/
|
||||
@SaCheckPermission("dormbed:dormBed:list")
|
||||
@GetMapping("/list")
|
||||
public TableDataInfo<XgDormBedVo> list(XgDormBedBo bo, PageQuery pageQuery) {
|
||||
return xgDormBedService.queryPageList(bo, pageQuery);
|
||||
}
|
||||
|
||||
/**
|
||||
* 导出宿舍床位信息列表
|
||||
*/
|
||||
@SaCheckPermission("dormbed:dormBed:export")
|
||||
@Log(title = "宿舍床位信息", businessType = BusinessType.EXPORT)
|
||||
@PostMapping("/export")
|
||||
public void export(XgDormBedBo bo, HttpServletResponse response) {
|
||||
List<XgDormBedVo> list = xgDormBedService.queryList(bo);
|
||||
ExcelUtil.exportExcel(list, "宿舍床位信息", XgDormBedVo.class, response);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取宿舍床位信息详细信息
|
||||
*
|
||||
* @param id 主键
|
||||
*/
|
||||
@SaCheckPermission("dormbed:dormBed:query")
|
||||
@GetMapping("/{id}")
|
||||
public R<XgDormBedVo> getInfo(@NotNull(message = "主键不能为空")
|
||||
@PathVariable Long id) {
|
||||
return R.ok(xgDormBedService.queryById(id));
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增宿舍床位信息
|
||||
*/
|
||||
@SaCheckPermission("dormbed:dormBed:add")
|
||||
@Log(title = "宿舍床位信息", businessType = BusinessType.INSERT)
|
||||
@RepeatSubmit()
|
||||
@PostMapping()
|
||||
public R<Void> add(@Validated(AddGroup.class) @RequestBody XgDormBedBo bo) {
|
||||
return toAjax(xgDormBedService.insertByBo(bo));
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改宿舍床位信息
|
||||
*/
|
||||
@SaCheckPermission("dormbed:dormBed:edit")
|
||||
@Log(title = "宿舍床位信息", businessType = BusinessType.UPDATE)
|
||||
@RepeatSubmit()
|
||||
@PutMapping()
|
||||
public R<Void> edit(@Validated(EditGroup.class) @RequestBody XgDormBedBo bo) {
|
||||
return toAjax(xgDormBedService.updateByBo(bo));
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除宿舍床位信息
|
||||
*
|
||||
* @param ids 主键串
|
||||
*/
|
||||
@SaCheckPermission("dormbed:dormBed:remove")
|
||||
@Log(title = "宿舍床位信息", businessType = BusinessType.DELETE)
|
||||
@DeleteMapping("/{ids}")
|
||||
public R<Void> remove(@NotEmpty(message = "主键不能为空")
|
||||
@PathVariable Long[] ids) {
|
||||
return toAjax(xgDormBedService.deleteWithValidByIds(List.of(ids), true));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
package org.dromara.xg.domain;
|
||||
|
||||
import org.dromara.common.tenant.core.TenantEntity;
|
||||
import com.baomidou.mybatisplus.annotation.*;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
import java.io.Serial;
|
||||
|
||||
/**
|
||||
* 宿舍床位信息对象 xg_dorm_bed
|
||||
*
|
||||
* @author zlwu
|
||||
* @date 2025-07-22
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@TableName("xg_dorm_bed")
|
||||
public class XgDormBed extends TenantEntity {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 主键ID
|
||||
*/
|
||||
@TableId(value = "id")
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 床位编号
|
||||
*/
|
||||
private String bedCode;
|
||||
|
||||
/**
|
||||
* 床位名称
|
||||
*/
|
||||
private String bedName;
|
||||
|
||||
/**
|
||||
* 所属房间ID
|
||||
*/
|
||||
private Long roomId;
|
||||
|
||||
/**
|
||||
* 床位类型(1下铺 2上铺 3中铺 4独立床)
|
||||
*/
|
||||
private String bedType;
|
||||
|
||||
/**
|
||||
* 床位状态(0空闲 1已分配 2维修中)
|
||||
*/
|
||||
private String bedStatus;
|
||||
|
||||
/**
|
||||
* 删除标志(0代表存在 1代表删除)
|
||||
*/
|
||||
@TableLogic(value = "0", delval = "1")
|
||||
private String deleted;
|
||||
|
||||
/**
|
||||
* 备注
|
||||
*/
|
||||
private String remark;
|
||||
|
||||
}
|
||||
+68
@@ -0,0 +1,68 @@
|
||||
package org.dromara.xg.domain.bo;
|
||||
|
||||
import org.dromara.xg.domain.XgDormBed;
|
||||
import org.dromara.common.mybatis.core.domain.BaseEntity;
|
||||
import org.dromara.common.core.validate.AddGroup;
|
||||
import org.dromara.common.core.validate.EditGroup;
|
||||
import io.github.linpeilie.annotations.AutoMapper;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import jakarta.validation.constraints.*;
|
||||
|
||||
/**
|
||||
* 宿舍床位信息业务对象 xg_dorm_bed
|
||||
*
|
||||
* @author zlwu
|
||||
* @date 2025-07-22
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@AutoMapper(target = XgDormBed.class, reverseConvertGenerate = false)
|
||||
public class XgDormBedBo extends BaseEntity {
|
||||
|
||||
/**
|
||||
* 主键ID
|
||||
*/
|
||||
@NotNull(message = "主键ID不能为空", groups = { EditGroup.class })
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 床位编号
|
||||
*/
|
||||
@NotBlank(message = "床位编号不能为空", groups = { AddGroup.class, EditGroup.class })
|
||||
private String bedCode;
|
||||
|
||||
/**
|
||||
* 床位名称
|
||||
*/
|
||||
@NotBlank(message = "床位名称不能为空", groups = { AddGroup.class, EditGroup.class })
|
||||
private String bedName;
|
||||
|
||||
/**
|
||||
* 所属房间ID
|
||||
*/
|
||||
@NotNull(message = "所属房间ID不能为空", groups = { AddGroup.class, EditGroup.class })
|
||||
private Long roomId;
|
||||
|
||||
/**
|
||||
* 床位类型(1下铺 2上铺 3中铺 4独立床)
|
||||
*/
|
||||
private String bedType;
|
||||
|
||||
/**
|
||||
* 床位状态(0空闲 1已分配 2维修中)
|
||||
*/
|
||||
private String bedStatus;
|
||||
|
||||
/**
|
||||
* 删除标志(0代表存在 1代表删除)
|
||||
*/
|
||||
private String deleted;
|
||||
|
||||
/**
|
||||
* 备注
|
||||
*/
|
||||
private String remark;
|
||||
|
||||
|
||||
}
|
||||
+5
@@ -102,4 +102,9 @@ public class DormBuildingInfoVo implements Serializable {
|
||||
*/
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private Date updateTime;
|
||||
|
||||
/**
|
||||
* 宿舍楼类型(1男生楼 2女生楼 3混合楼)(仅宿舍楼节点有此字段)
|
||||
*/
|
||||
private String buildingType;
|
||||
}
|
||||
+5
@@ -41,6 +41,11 @@ public class DormBuildingTreeVo implements Serializable {
|
||||
*/
|
||||
private Integer buildingFloors;
|
||||
|
||||
/**
|
||||
* 宿舍楼类型(1男生楼 2女生楼 3混合楼)(仅宿舍楼节点有此字段)
|
||||
*/
|
||||
private String buildingType;
|
||||
|
||||
/**
|
||||
* 子节点
|
||||
*/
|
||||
|
||||
+80
@@ -0,0 +1,80 @@
|
||||
package org.dromara.xg.domain.vo;
|
||||
|
||||
import org.dromara.xg.domain.XgDormBed;
|
||||
import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
|
||||
import cn.idev.excel.annotation.ExcelProperty;
|
||||
import org.dromara.common.excel.annotation.ExcelDictFormat;
|
||||
import org.dromara.common.excel.convert.ExcelDictConvert;
|
||||
import io.github.linpeilie.annotations.AutoMapper;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 宿舍床位信息视图对象 xg_dorm_bed
|
||||
*
|
||||
* @author zlwu
|
||||
* @date 2025-07-22
|
||||
*/
|
||||
@Data
|
||||
@ExcelIgnoreUnannotated
|
||||
@AutoMapper(target = XgDormBed.class)
|
||||
public class XgDormBedVo implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 主键ID
|
||||
*/
|
||||
@ExcelProperty(value = "主键ID")
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 床位编号
|
||||
*/
|
||||
@ExcelProperty(value = "床位编号")
|
||||
private String bedCode;
|
||||
|
||||
/**
|
||||
* 床位名称
|
||||
*/
|
||||
@ExcelProperty(value = "床位名称")
|
||||
private String bedName;
|
||||
|
||||
/**
|
||||
* 所属房间ID
|
||||
*/
|
||||
@ExcelProperty(value = "所属房间ID")
|
||||
private Long roomId;
|
||||
|
||||
/**
|
||||
* 床位类型(1下铺 2上铺 3中铺 4独立床)
|
||||
*/
|
||||
@ExcelProperty(value = "床位类型(1下铺 2上铺 3中铺 4独立床)")
|
||||
private String bedType;
|
||||
|
||||
/**
|
||||
* 床位状态(0空闲 1已分配 2维修中)
|
||||
*/
|
||||
@ExcelProperty(value = "床位状态(0空闲 1已分配 2维修中)")
|
||||
private String bedStatus;
|
||||
|
||||
/**
|
||||
* 删除标志(0代表存在 1代表删除)
|
||||
*/
|
||||
@ExcelProperty(value = "删除标志(0代表存在 1代表删除)")
|
||||
private String deleted;
|
||||
|
||||
/**
|
||||
* 备注
|
||||
*/
|
||||
@ExcelProperty(value = "备注")
|
||||
private String remark;
|
||||
|
||||
|
||||
}
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
package org.dromara.xg.mapper;
|
||||
|
||||
import org.dromara.xg.domain.XgDormBed;
|
||||
import org.dromara.xg.domain.vo.XgDormBedVo;
|
||||
import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
|
||||
|
||||
/**
|
||||
* 宿舍床位信息Mapper接口
|
||||
*
|
||||
* @author zlwu
|
||||
* @date 2025-07-22
|
||||
*/
|
||||
public interface XgDormBedMapper extends BaseMapperPlus<XgDormBed, XgDormBedVo> {
|
||||
|
||||
}
|
||||
+68
@@ -0,0 +1,68 @@
|
||||
package org.dromara.xg.service;
|
||||
|
||||
import org.dromara.xg.domain.vo.XgDormBedVo;
|
||||
import org.dromara.xg.domain.bo.XgDormBedBo;
|
||||
import org.dromara.common.mybatis.core.page.TableDataInfo;
|
||||
import org.dromara.common.mybatis.core.page.PageQuery;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 宿舍床位信息Service接口
|
||||
*
|
||||
* @author zlwu
|
||||
* @date 2025-07-22
|
||||
*/
|
||||
public interface IXgDormBedService {
|
||||
|
||||
/**
|
||||
* 查询宿舍床位信息
|
||||
*
|
||||
* @param id 主键
|
||||
* @return 宿舍床位信息
|
||||
*/
|
||||
XgDormBedVo queryById(Long id);
|
||||
|
||||
/**
|
||||
* 分页查询宿舍床位信息列表
|
||||
*
|
||||
* @param bo 查询条件
|
||||
* @param pageQuery 分页参数
|
||||
* @return 宿舍床位信息分页列表
|
||||
*/
|
||||
TableDataInfo<XgDormBedVo> queryPageList(XgDormBedBo bo, PageQuery pageQuery);
|
||||
|
||||
/**
|
||||
* 查询符合条件的宿舍床位信息列表
|
||||
*
|
||||
* @param bo 查询条件
|
||||
* @return 宿舍床位信息列表
|
||||
*/
|
||||
List<XgDormBedVo> queryList(XgDormBedBo bo);
|
||||
|
||||
/**
|
||||
* 新增宿舍床位信息
|
||||
*
|
||||
* @param bo 宿舍床位信息
|
||||
* @return 是否新增成功
|
||||
*/
|
||||
Boolean insertByBo(XgDormBedBo bo);
|
||||
|
||||
/**
|
||||
* 修改宿舍床位信息
|
||||
*
|
||||
* @param bo 宿舍床位信息
|
||||
* @return 是否修改成功
|
||||
*/
|
||||
Boolean updateByBo(XgDormBedBo bo);
|
||||
|
||||
/**
|
||||
* 校验并批量删除宿舍床位信息信息
|
||||
*
|
||||
* @param ids 待删除的主键集合
|
||||
* @param isValid 是否进行有效性校验
|
||||
* @return 是否删除成功
|
||||
*/
|
||||
Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
|
||||
}
|
||||
+137
@@ -0,0 +1,137 @@
|
||||
package org.dromara.xg.service.impl;
|
||||
|
||||
import org.dromara.common.core.utils.MapstructUtils;
|
||||
import org.dromara.common.core.utils.StringUtils;
|
||||
import org.dromara.common.mybatis.core.page.TableDataInfo;
|
||||
import org.dromara.common.mybatis.core.page.PageQuery;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.dromara.xg.domain.bo.XgDormBedBo;
|
||||
import org.dromara.xg.domain.vo.XgDormBedVo;
|
||||
import org.dromara.xg.domain.XgDormBed;
|
||||
import org.dromara.xg.mapper.XgDormBedMapper;
|
||||
import org.dromara.xg.service.IXgDormBedService;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
* 宿舍床位信息Service业务层处理
|
||||
*
|
||||
* @author zlwu
|
||||
* @date 2025-07-22
|
||||
*/
|
||||
@Slf4j
|
||||
@RequiredArgsConstructor
|
||||
@Service
|
||||
public class XgDormBedServiceImpl implements IXgDormBedService {
|
||||
|
||||
private final XgDormBedMapper baseMapper;
|
||||
|
||||
/**
|
||||
* 查询宿舍床位信息
|
||||
*
|
||||
* @param id 主键
|
||||
* @return 宿舍床位信息
|
||||
*/
|
||||
@Override
|
||||
public XgDormBedVo queryById(Long id){
|
||||
return baseMapper.selectVoById(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* 分页查询宿舍床位信息列表
|
||||
*
|
||||
* @param bo 查询条件
|
||||
* @param pageQuery 分页参数
|
||||
* @return 宿舍床位信息分页列表
|
||||
*/
|
||||
@Override
|
||||
public TableDataInfo<XgDormBedVo> queryPageList(XgDormBedBo bo, PageQuery pageQuery) {
|
||||
LambdaQueryWrapper<XgDormBed> lqw = buildQueryWrapper(bo);
|
||||
Page<XgDormBedVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
|
||||
return TableDataInfo.build(result);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询符合条件的宿舍床位信息列表
|
||||
*
|
||||
* @param bo 查询条件
|
||||
* @return 宿舍床位信息列表
|
||||
*/
|
||||
@Override
|
||||
public List<XgDormBedVo> queryList(XgDormBedBo bo) {
|
||||
LambdaQueryWrapper<XgDormBed> lqw = buildQueryWrapper(bo);
|
||||
return baseMapper.selectVoList(lqw);
|
||||
}
|
||||
|
||||
private LambdaQueryWrapper<XgDormBed> buildQueryWrapper(XgDormBedBo bo) {
|
||||
Map<String, Object> params = bo.getParams();
|
||||
LambdaQueryWrapper<XgDormBed> lqw = Wrappers.lambdaQuery();
|
||||
lqw.orderByAsc(XgDormBed::getId);
|
||||
lqw.like(StringUtils.isNotBlank(bo.getBedCode()), XgDormBed::getBedCode, bo.getBedCode());
|
||||
lqw.like(StringUtils.isNotBlank(bo.getBedName()), XgDormBed::getBedName, bo.getBedName());
|
||||
lqw.eq(bo.getRoomId() != null, XgDormBed::getRoomId, bo.getRoomId());
|
||||
lqw.eq(StringUtils.isNotBlank(bo.getBedType()), XgDormBed::getBedType, bo.getBedType());
|
||||
lqw.eq(StringUtils.isNotBlank(bo.getBedStatus()), XgDormBed::getBedStatus, bo.getBedStatus());
|
||||
lqw.eq(StringUtils.isNotBlank(bo.getDeleted()), XgDormBed::getDeleted, bo.getDeleted());
|
||||
return lqw;
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增宿舍床位信息
|
||||
*
|
||||
* @param bo 宿舍床位信息
|
||||
* @return 是否新增成功
|
||||
*/
|
||||
@Override
|
||||
public Boolean insertByBo(XgDormBedBo bo) {
|
||||
XgDormBed add = MapstructUtils.convert(bo, XgDormBed.class);
|
||||
validEntityBeforeSave(add);
|
||||
boolean flag = baseMapper.insert(add) > 0;
|
||||
if (flag) {
|
||||
bo.setId(add.getId());
|
||||
}
|
||||
return flag;
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改宿舍床位信息
|
||||
*
|
||||
* @param bo 宿舍床位信息
|
||||
* @return 是否修改成功
|
||||
*/
|
||||
@Override
|
||||
public Boolean updateByBo(XgDormBedBo bo) {
|
||||
XgDormBed update = MapstructUtils.convert(bo, XgDormBed.class);
|
||||
validEntityBeforeSave(update);
|
||||
return baseMapper.updateById(update) > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存前的数据校验
|
||||
*/
|
||||
private void validEntityBeforeSave(XgDormBed entity){
|
||||
//TODO 做一些数据校验,如唯一约束
|
||||
}
|
||||
|
||||
/**
|
||||
* 校验并批量删除宿舍床位信息信息
|
||||
*
|
||||
* @param ids 待删除的主键集合
|
||||
* @param isValid 是否进行有效性校验
|
||||
* @return 是否删除成功
|
||||
*/
|
||||
@Override
|
||||
public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
|
||||
if(isValid){
|
||||
//TODO 做一些业务上的校验,判断是否需要校验
|
||||
}
|
||||
return baseMapper.deleteByIds(ids) > 0;
|
||||
}
|
||||
}
|
||||
+1
@@ -141,6 +141,7 @@ public class XgDormBuildingTreeServiceImpl implements IXgDormBuildingTreeService
|
||||
buildingNode.setType("building");
|
||||
buildingNode.setDisabled(false); // 宿舍楼节点可点击
|
||||
buildingNode.setBuildingFloors(building.getFloors());
|
||||
buildingNode.setBuildingType(building.getBuildingType());
|
||||
|
||||
// 将宿舍楼节点添加到对应的宿舍区节点下
|
||||
DormBuildingTreeVo areaNode = areaMap.get(building.getAreaId());
|
||||
|
||||
+7
-6
@@ -40,7 +40,7 @@ public class XgDormRoomServiceImpl implements IXgDormRoomService {
|
||||
* @return 宿舍房间信息
|
||||
*/
|
||||
@Override
|
||||
public XgDormRoomVo queryById(Long id){
|
||||
public XgDormRoomVo queryById(Long id) {
|
||||
return baseMapper.selectVoById(id);
|
||||
}
|
||||
|
||||
@@ -73,7 +73,8 @@ public class XgDormRoomServiceImpl implements IXgDormRoomService {
|
||||
private LambdaQueryWrapper<XgDormRoom> buildQueryWrapper(XgDormRoomBo bo) {
|
||||
Map<String, Object> params = bo.getParams();
|
||||
LambdaQueryWrapper<XgDormRoom> lqw = Wrappers.lambdaQuery();
|
||||
lqw.orderByAsc(XgDormRoom::getId);
|
||||
lqw.orderByAsc(XgDormRoom::getFloorNum); // 优先按楼层排序
|
||||
lqw.orderByAsc(XgDormRoom::getRoomName); // 其次按房间名称排序
|
||||
lqw.like(StringUtils.isNotBlank(bo.getRoomCode()), XgDormRoom::getRoomCode, bo.getRoomCode());
|
||||
lqw.like(StringUtils.isNotBlank(bo.getRoomName()), XgDormRoom::getRoomName, bo.getRoomName());
|
||||
lqw.eq(bo.getBuildingId() != null, XgDormRoom::getBuildingId, bo.getBuildingId());
|
||||
@@ -119,8 +120,8 @@ public class XgDormRoomServiceImpl implements IXgDormRoomService {
|
||||
/**
|
||||
* 保存前的数据校验
|
||||
*/
|
||||
private void validEntityBeforeSave(XgDormRoom entity){
|
||||
//TODO 做一些数据校验,如唯一约束
|
||||
private void validEntityBeforeSave(XgDormRoom entity) {
|
||||
// TODO 做一些数据校验,如唯一约束
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -132,8 +133,8 @@ public class XgDormRoomServiceImpl implements IXgDormRoomService {
|
||||
*/
|
||||
@Override
|
||||
public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
|
||||
if(isValid){
|
||||
//TODO 做一些业务上的校验,判断是否需要校验
|
||||
if (isValid) {
|
||||
// TODO 做一些业务上的校验,判断是否需要校验
|
||||
}
|
||||
return baseMapper.deleteByIds(ids) > 0;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
<?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.XgDormBedMapper">
|
||||
|
||||
</mapper>
|
||||
+6
@@ -8,6 +8,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
<id property="id" column="id"/>
|
||||
<result property="buildingName" column="building_name"/>
|
||||
<result property="buildingCode" column="building_code"/>
|
||||
<result property="buildingType" column="building_type"/>
|
||||
<result property="campusId" column="campus_id"/>
|
||||
<result property="campusName" column="campus_name"/>
|
||||
<result property="areaId" column="area_id"/>
|
||||
@@ -55,6 +56,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
b.building_name,
|
||||
b.building_code,
|
||||
b.campus_id,
|
||||
b.building_type,
|
||||
c.campus_name,
|
||||
b.area_id,
|
||||
a.area_name,
|
||||
@@ -103,6 +105,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
b.id,
|
||||
b.building_name,
|
||||
b.building_code,
|
||||
b.building_type,
|
||||
b.campus_id,
|
||||
c.campus_name,
|
||||
b.area_id,
|
||||
@@ -148,6 +151,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
b.building_name,
|
||||
b.building_code,
|
||||
b.campus_id,
|
||||
b.building_type,
|
||||
c.campus_name,
|
||||
b.area_id,
|
||||
a.area_name,
|
||||
@@ -201,6 +205,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
b.campus_id,
|
||||
c.campus_name,
|
||||
b.area_id,
|
||||
b.building_type,
|
||||
a.area_name,
|
||||
b.floors,
|
||||
b.remark,
|
||||
@@ -249,6 +254,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
b.id,
|
||||
b.building_name,
|
||||
b.building_code,
|
||||
b.building_type,
|
||||
b.campus_id,
|
||||
c.campus_name,
|
||||
b.area_id,
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
# 代码调整记录 - 2025-07-22
|
||||
|
||||
## 宿舍房间查询排序优化
|
||||
|
||||
### 变更时间
|
||||
2025-07-22 10:35:26
|
||||
|
||||
### 变更类型
|
||||
接口优化 - 数据排序调整
|
||||
|
||||
### 变更描述
|
||||
修改了宿舍房间列表查询接口的排序逻辑,调整为优先按楼层(floorNum)排序,然后按房间名称(roomName)排序,确保宿舍房间按照楼层顺序输出。
|
||||
|
||||
### 变更文件
|
||||
- `backend/ruoyi-modules/ruoyi-xg/src/main/java/org/dromara/xg/service/impl/XgDormRoomServiceImpl.java`
|
||||
|
||||
### 变更详情
|
||||
原先的排序逻辑:
|
||||
```java
|
||||
lqw.orderByAsc(XgDormRoom::getId);
|
||||
lqw.orderByAsc(XgDormRoom::getFloorNum); // 按楼层排序
|
||||
```
|
||||
|
||||
修改后的排序逻辑:
|
||||
```java
|
||||
lqw.orderByAsc(XgDormRoom::getFloorNum); // 优先按楼层排序
|
||||
lqw.orderByAsc(XgDormRoom::getRoomName); // 其次按房间名称排序
|
||||
```
|
||||
|
||||
### 原因
|
||||
前端展示宿舍房间列表时,需要按照楼层顺序进行排列,但原有排序逻辑中先按ID排序,导致楼层排序不能正确生效。
|
||||
|
||||
### 影响范围
|
||||
- 宿舍分配二级学院页面(xsssfpejxy)中的房间列表显示顺序
|
||||
- 其他调用宿舍房间查询接口的功能
|
||||
|
||||
### 测试验证
|
||||
- 验证宿舍楼下的房间是否按楼层升序排列
|
||||
- 验证相同楼层的房间是否按房间名称排序
|
||||
|
||||
# 宿舍管理功能变更记录
|
||||
|
||||
## 宿舍树性别标识功能添加
|
||||
|
||||
**时间**:2025-07-22 15:30:00
|
||||
|
||||
**变更内容**:
|
||||
1. 在宿舍树显示中,为宿舍楼名称前添加性别标识
|
||||
- 男生楼:添加"(男)"前缀,显示蓝色
|
||||
- 女生楼:添加"(女)"前缀,显示粉色
|
||||
2. 修改前端数据模型
|
||||
- 在`DormTreeNode`接口中添加`gender`字段,用于标识宿舍楼性别(1-男生楼,2-女生楼)
|
||||
3. 修改模拟数据
|
||||
- 为模拟数据中的宿舍楼添加性别标识
|
||||
4. 适配逻辑处理
|
||||
- 对于后端返回的没有性别标识的数据,前端会进行随机分配(临时措施)
|
||||
|
||||
**相关文件**:
|
||||
- `/web/src/views/xgss/xsssfjgl/index.vue`:修改宿舍树节点显示,添加性别标识和样式
|
||||
- `/web/src/api/xgss/xsssfjgl/types.ts`:在`DormTreeNode`接口中添加性别字段
|
||||
- `/web/src/api/xgss/xsssfjgl/index.ts`:修改模拟数据,添加性别标识
|
||||
|
||||
**后续优化建议**:
|
||||
1. 后端需要确保返回的宿舍楼数据中包含性别信息
|
||||
2. 宿舍楼管理功能中应添加性别设置选项
|
||||
3. 考虑在宿舍树过滤功能中添加按性别筛选功能
|
||||
|
||||
**相关SQL变更**:无(本次只涉及前端显示变更)
|
||||
+150
-4
@@ -6,6 +6,8 @@
|
||||
- [1.1 获取宿舍楼树形结构](#11-获取宿舍楼树形结构)
|
||||
- [2. 宿舍楼信息管理](#2-宿舍楼信息管理)
|
||||
- [2.1 获取宿舍楼列表](#21-获取宿舍楼列表)
|
||||
- [3. 宿舍房间管理](#3-宿舍房间管理)
|
||||
- [3.1 获取宿舍房间列表](#31-获取宿舍房间列表)
|
||||
|
||||
## 1. 宿舍楼树形结构
|
||||
|
||||
@@ -60,14 +62,16 @@ xgss:dormBuildingTree:list
|
||||
"label": "1号楼",
|
||||
"type": "building",
|
||||
"disabled": false,
|
||||
"buildingFloors": 6
|
||||
"buildingFloors": 6,
|
||||
"gender": "male"
|
||||
},
|
||||
{
|
||||
"id": 1002,
|
||||
"label": "2号楼",
|
||||
"type": "building",
|
||||
"disabled": false,
|
||||
"buildingFloors": 5
|
||||
"buildingFloors": 5,
|
||||
"gender": "female"
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -97,10 +101,11 @@ xgss:dormBuildingTree:list
|
||||
| 参数名 | 类型 | 描述 |
|
||||
| -------------- | ------- | ------------------------------------------------ |
|
||||
| id | Long | 节点ID |
|
||||
| label | String | 节点名称 |
|
||||
| type | String | 节点类型(campus:校区,area:宿舍区,building:宿舍楼) |
|
||||
| label | String | 节点显示名称 |
|
||||
| type | String | 节点类型(campus:校区、area:宿舍区、building:宿舍楼) |
|
||||
| disabled | Boolean | 是否禁用点击(校区和宿舍区为true,宿舍楼为false) |
|
||||
| buildingFloors | Integer | 宿舍楼层数(只有宿舍楼节点有此字段) |
|
||||
| gender | String | 宿舍楼性别(只有宿舍楼节点有此字段) |
|
||||
| children | Array | 子节点列表 |
|
||||
|
||||
#### 数据权限说明
|
||||
@@ -260,4 +265,145 @@ async function getDormBuildingList(params) {
|
||||
}
|
||||
return { total: 0, rows: [] };
|
||||
}
|
||||
```
|
||||
|
||||
## 3. 宿舍房间管理
|
||||
|
||||
### 3.1 获取宿舍房间列表
|
||||
|
||||
#### 接口说明
|
||||
|
||||
该接口用于获取宿舍房间信息的列表,包含房间基本信息。列表按照楼层升序、房间名称升序排列。
|
||||
|
||||
#### 请求方式
|
||||
|
||||
```
|
||||
GET /xgss/dormRoom/list
|
||||
```
|
||||
|
||||
#### 权限要求
|
||||
|
||||
```
|
||||
xgss:dormRoom:list
|
||||
```
|
||||
|
||||
#### 请求参数
|
||||
|
||||
| 参数名 | 类型 | 必须 | 描述 |
|
||||
| ---------- | ------- | ---- | ---------------------- |
|
||||
| pageNum | Integer | 是 | 当前页码,从1开始 |
|
||||
| pageSize | Integer | 是 | 每页记录数 |
|
||||
| buildingId | Long | 否 | 宿舍楼ID,精确查询 |
|
||||
| roomName | String | 否 | 房间名称,模糊查询 |
|
||||
| floorNum | Integer | 否 | 楼层号,精确查询 |
|
||||
| roomType | String | 否 | 房间类型(1标准间 2单人间 3套间) |
|
||||
| roomStatus | String | 否 | 房间状态(0正常 1维修中 2停用) |
|
||||
|
||||
#### 返回结果
|
||||
|
||||
```json
|
||||
{
|
||||
"total": 2,
|
||||
"rows": [
|
||||
{
|
||||
"id": "1947459199879495682",
|
||||
"roomCode": "room-101",
|
||||
"roomName": "101",
|
||||
"buildingId": "1947459199879495681",
|
||||
"floorNum": 1,
|
||||
"roomType": "1",
|
||||
"standardBeds": 4,
|
||||
"actualBeds": 4,
|
||||
"roomArea": 20.5,
|
||||
"roomStatus": "0",
|
||||
"remark": "标准四人间",
|
||||
"createBy": 1,
|
||||
"createTime": "2025-07-22 09:15:30",
|
||||
"updateBy": 1,
|
||||
"updateTime": "2025-07-22 09:15:30"
|
||||
},
|
||||
{
|
||||
"id": "1947459199879495683",
|
||||
"roomCode": "room-201",
|
||||
"roomName": "201",
|
||||
"buildingId": "1947459199879495681",
|
||||
"floorNum": 2,
|
||||
"roomType": "1",
|
||||
"standardBeds": 4,
|
||||
"actualBeds": 4,
|
||||
"roomArea": 20.5,
|
||||
"roomStatus": "0",
|
||||
"remark": "标准四人间",
|
||||
"createBy": 1,
|
||||
"createTime": "2025-07-22 09:15:30",
|
||||
"updateBy": 1,
|
||||
"updateTime": "2025-07-22 09:15:30"
|
||||
}
|
||||
],
|
||||
"code": 200,
|
||||
"msg": "查询成功"
|
||||
}
|
||||
```
|
||||
|
||||
#### 返回参数说明
|
||||
|
||||
| 参数名 | 类型 | 描述 |
|
||||
| ------------ | ------- | --------------------------------------- |
|
||||
| id | Long | 房间主键ID |
|
||||
| roomCode | String | 房间编码 |
|
||||
| roomName | String | 房间名称 |
|
||||
| buildingId | Long | 所属宿舍楼ID |
|
||||
| floorNum | Integer | 楼层号 |
|
||||
| roomType | String | 房间类型(1标准间 2单人间 3套间) |
|
||||
| standardBeds | Integer | 标准床位数 |
|
||||
| actualBeds | Integer | 实际床位数 |
|
||||
| roomArea | Double | 房间面积(平方米) |
|
||||
| roomStatus | String | 房间状态(0正常 1维修中 2停用) |
|
||||
| remark | String | 备注 |
|
||||
| createBy | Long | 创建者ID |
|
||||
| createTime | Date | 创建时间 |
|
||||
| updateBy | Long | 更新者ID |
|
||||
| updateTime | Date | 更新时间 |
|
||||
|
||||
#### 排序规则
|
||||
|
||||
房间列表按照以下顺序排序:
|
||||
1. 优先按楼层号(floorNum)升序排列
|
||||
2. 其次按房间名称(roomName)升序排列
|
||||
|
||||
这确保了在宿舍管理系统中房间按照从低楼层到高楼层的顺序展示,相同楼层的房间按照名称顺序排列,提供更直观的浏览体验。
|
||||
|
||||
#### 错误码
|
||||
|
||||
| 错误码 | 描述 |
|
||||
| ------ | -------------------- |
|
||||
| 401 | 未授权,需要登录 |
|
||||
| 403 | 无权限访问该接口 |
|
||||
| 500 | 服务器内部错误 |
|
||||
|
||||
#### 使用示例
|
||||
|
||||
```javascript
|
||||
// 前端代码示例(使用axios)
|
||||
import axios from 'axios';
|
||||
|
||||
// 获取宿舍房间列表
|
||||
async function getDormRoomList(params) {
|
||||
try {
|
||||
const response = await axios.get('/xgss/dormRoom/list', {
|
||||
params: {
|
||||
pageNum: 1,
|
||||
pageSize: 100,
|
||||
buildingId: buildingId,
|
||||
...params
|
||||
}
|
||||
});
|
||||
if (response.data.code === 200) {
|
||||
return response.data;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('获取宿舍房间列表失败:', error);
|
||||
}
|
||||
return { total: 0, rows: [] };
|
||||
}
|
||||
```
|
||||
@@ -109,6 +109,7 @@ create table `xg_dorm_bed` (
|
||||
`bed_status` char(1) default '0' comment '床位状态(0空闲 1已分配 2维修中)',
|
||||
`deleted` char(1) default '0' comment '删除标志(0代表存在 1代表删除)',
|
||||
`tenant_id` bigint(20) default '0' comment '租户编号',
|
||||
`create_dept` bigint(20) DEFAULT NULL COMMENT '创建部门',
|
||||
`create_by` bigint(20) default null comment '创建者',
|
||||
`create_time` datetime default null comment '创建时间',
|
||||
`update_by` bigint(20) default null comment '更新者',
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
import request from '@/utils/request';
|
||||
import { AxiosPromise } from 'axios';
|
||||
import { DormBedVO, DormBedForm, DormBedQuery } from '@/api/xgss/dormBed/types';
|
||||
|
||||
/**
|
||||
* 查询宿舍床位信息列表
|
||||
* @param query
|
||||
* @returns {*}
|
||||
*/
|
||||
|
||||
export const listDormBed = (query?: DormBedQuery): AxiosPromise<DormBedVO[]> => {
|
||||
return request({
|
||||
url: '/dormbed/dormBed/list',
|
||||
method: 'get',
|
||||
params: query
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 查询宿舍床位信息详细
|
||||
* @param id
|
||||
*/
|
||||
export const getDormBed = (id: string | number): AxiosPromise<DormBedVO> => {
|
||||
return request({
|
||||
url: '/dormbed/dormBed/' + id,
|
||||
method: 'get'
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 新增宿舍床位信息
|
||||
* @param data
|
||||
*/
|
||||
export const addDormBed = (data: DormBedForm) => {
|
||||
return request({
|
||||
url: '/dormbed/dormBed',
|
||||
method: 'post',
|
||||
data: data
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 修改宿舍床位信息
|
||||
* @param data
|
||||
*/
|
||||
export const updateDormBed = (data: DormBedForm) => {
|
||||
return request({
|
||||
url: '/dormbed/dormBed',
|
||||
method: 'put',
|
||||
data: data
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 删除宿舍床位信息
|
||||
* @param id
|
||||
*/
|
||||
export const delDormBed = (id: string | number | Array<string | number>) => {
|
||||
return request({
|
||||
url: '/dormbed/dormBed/' + id,
|
||||
method: 'delete'
|
||||
});
|
||||
};
|
||||
@@ -0,0 +1,66 @@
|
||||
/**
|
||||
* 宿舍床位信息查询参数
|
||||
*/
|
||||
export interface DormBedQuery {
|
||||
/** 床位编号 */
|
||||
bedCode?: string;
|
||||
/** 床位名称 */
|
||||
bedName?: string;
|
||||
/** 所属房间ID */
|
||||
roomId?: string | number;
|
||||
/** 床位状态(0=空闲,1=已分配,2=维修中) */
|
||||
bedStatus?: string;
|
||||
/** 床位类型(1=下铺,2=上铺,3=中铺,4=独立床) */
|
||||
bedType?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* 宿舍床位信息对象
|
||||
*/
|
||||
export interface DormBedVO {
|
||||
/** 床位ID */
|
||||
id: string | number;
|
||||
/** 床位编号 */
|
||||
bedCode: string;
|
||||
/** 床位名称 */
|
||||
bedName: string;
|
||||
/** 所属房间ID */
|
||||
roomId: string | number;
|
||||
/** 床位状态(0=空闲,1=已分配,2=维修中) */
|
||||
bedStatus: string;
|
||||
/** 床位类型(1=下铺,2=上铺,3=中铺,4=独立床) */
|
||||
bedType: string;
|
||||
/** 备注 */
|
||||
remark?: string;
|
||||
/** 创建者 */
|
||||
createBy: number;
|
||||
/** 创建时间 */
|
||||
createTime: Date;
|
||||
/** 更新者 */
|
||||
updateBy: number;
|
||||
/** 更新时间 */
|
||||
updateTime: Date;
|
||||
}
|
||||
|
||||
/**
|
||||
* 宿舍床位信息表单对象
|
||||
*/
|
||||
export interface DormBedForm {
|
||||
/** 床位ID */
|
||||
id: string | number;
|
||||
/** 床位编号 */
|
||||
bedCode: string;
|
||||
/** 床位名称 */
|
||||
bedName: string;
|
||||
/** 所属房间ID */
|
||||
roomId: string | number;
|
||||
/** 床位状态(0=空闲,1=已分配,2=维修中) */
|
||||
bedStatus: string;
|
||||
/** 床位类型(1=下铺,2=上铺,3=中铺,4=独立床) */
|
||||
bedType: string;
|
||||
/** 备注 */
|
||||
remark?: string;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
import request from '@/utils/request';
|
||||
import { AxiosPromise } from 'axios';
|
||||
import { DormRoomVO, DormRoomForm, DormRoomQuery } from '@/api/xgss/dormRoom/types';
|
||||
|
||||
/**
|
||||
* 查询宿舍房间信息列表
|
||||
* @param query
|
||||
* @returns {*}
|
||||
*/
|
||||
|
||||
export const listDormRoom = (query?: DormRoomQuery): AxiosPromise<DormRoomVO[]> => {
|
||||
return request({
|
||||
url: '/xgss/dormRoom/list',
|
||||
method: 'get',
|
||||
params: query
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 查询宿舍房间信息详细
|
||||
* @param id
|
||||
*/
|
||||
export const getDormRoom = (id: string | number): AxiosPromise<DormRoomVO> => {
|
||||
return request({
|
||||
url: '/xgss/dormRoom/' + id,
|
||||
method: 'get'
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 新增宿舍房间信息
|
||||
* @param data
|
||||
*/
|
||||
export const addDormRoom = (data: DormRoomForm) => {
|
||||
return request({
|
||||
url: '/xgss/dormRoom',
|
||||
method: 'post',
|
||||
data: data
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 修改宿舍房间信息
|
||||
* @param data
|
||||
*/
|
||||
export const updateDormRoom = (data: DormRoomForm) => {
|
||||
return request({
|
||||
url: '/xgss/dormRoom',
|
||||
method: 'put',
|
||||
data: data
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 删除宿舍房间信息
|
||||
* @param id
|
||||
*/
|
||||
export const delDormRoom = (id: string | number | Array<string | number>) => {
|
||||
return request({
|
||||
url: '/xgss/dormRoom/' + id,
|
||||
method: 'delete'
|
||||
});
|
||||
};
|
||||
@@ -0,0 +1,176 @@
|
||||
export interface DormRoomVO {
|
||||
/**
|
||||
* 主键ID
|
||||
*/
|
||||
id: string | number;
|
||||
|
||||
/**
|
||||
* 房间编号
|
||||
*/
|
||||
roomCode: string;
|
||||
|
||||
/**
|
||||
* 房间名称
|
||||
*/
|
||||
roomName: string;
|
||||
|
||||
/**
|
||||
* 所属宿舍楼ID
|
||||
*/
|
||||
buildingId: string | number;
|
||||
|
||||
/**
|
||||
* 楼层
|
||||
*/
|
||||
floorNum: number;
|
||||
|
||||
/**
|
||||
* 房间类型(1标准间 2 单人间 3 套间)
|
||||
*/
|
||||
roomType: string;
|
||||
|
||||
/**
|
||||
* 实际床位数
|
||||
*/
|
||||
actualBeds: number;
|
||||
|
||||
/**
|
||||
* 当前床位数
|
||||
*/
|
||||
currentBeds?: number;
|
||||
|
||||
/**
|
||||
* 房间面积(平方米)
|
||||
*/
|
||||
roomArea: number;
|
||||
|
||||
/**
|
||||
* 房间状态(0可用 1维修中 2停用)
|
||||
*/
|
||||
roomStatus: string;
|
||||
|
||||
/**
|
||||
* 删除标志(0代表存在 1代表删除)
|
||||
*/
|
||||
deleted: string;
|
||||
|
||||
/**
|
||||
* 备注
|
||||
*/
|
||||
remark: string;
|
||||
|
||||
}
|
||||
|
||||
export interface DormRoomForm extends BaseEntity {
|
||||
/**
|
||||
* 主键ID
|
||||
*/
|
||||
id?: string | number;
|
||||
|
||||
/**
|
||||
* 房间编号
|
||||
*/
|
||||
roomCode?: string;
|
||||
|
||||
/**
|
||||
* 房间名称
|
||||
*/
|
||||
roomName?: string;
|
||||
|
||||
/**
|
||||
* 所属宿舍楼ID
|
||||
*/
|
||||
buildingId?: string | number;
|
||||
|
||||
/**
|
||||
* 楼层
|
||||
*/
|
||||
floorNum?: number;
|
||||
|
||||
/**
|
||||
* 房间类型(1标准间 2 单人间 3 套间)
|
||||
*/
|
||||
roomType?: string;
|
||||
|
||||
/**
|
||||
* 实际床位数
|
||||
*/
|
||||
actualBeds?: number;
|
||||
|
||||
/**
|
||||
* 房间面积(平方米)
|
||||
*/
|
||||
roomArea?: number;
|
||||
|
||||
/**
|
||||
* 房间状态(0可用 1维修中 2停用)
|
||||
*/
|
||||
roomStatus?: string;
|
||||
|
||||
/**
|
||||
* 删除标志(0代表存在 1代表删除)
|
||||
*/
|
||||
deleted?: string;
|
||||
|
||||
/**
|
||||
* 备注
|
||||
*/
|
||||
remark?: string;
|
||||
|
||||
}
|
||||
|
||||
export interface DormRoomQuery extends PageQuery {
|
||||
|
||||
/**
|
||||
* 房间编号
|
||||
*/
|
||||
roomCode?: string;
|
||||
|
||||
/**
|
||||
* 房间名称
|
||||
*/
|
||||
roomName?: string;
|
||||
|
||||
/**
|
||||
* 所属宿舍楼ID
|
||||
*/
|
||||
buildingId?: string | number;
|
||||
|
||||
/**
|
||||
* 楼层
|
||||
*/
|
||||
floorNum?: number;
|
||||
|
||||
/**
|
||||
* 房间类型(1标准间 2 单人间 3 套间)
|
||||
*/
|
||||
roomType?: string;
|
||||
|
||||
/**
|
||||
* 实际床位数
|
||||
*/
|
||||
actualBeds?: number;
|
||||
|
||||
/**
|
||||
* 房间面积(平方米)
|
||||
*/
|
||||
roomArea?: number;
|
||||
|
||||
/**
|
||||
* 房间状态(0可用 1维修中 2停用)
|
||||
*/
|
||||
roomStatus?: string;
|
||||
|
||||
/**
|
||||
* 删除标志(0代表存在 1代表删除)
|
||||
*/
|
||||
deleted?: string;
|
||||
|
||||
/**
|
||||
* 日期范围参数
|
||||
*/
|
||||
params?: any;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -148,13 +148,15 @@ export function getMockDormTree(): { data: DormTreeNode[] } {
|
||||
id: 111,
|
||||
label: '东区1号楼',
|
||||
type: 'building',
|
||||
buildingFloors: 6
|
||||
buildingFloors: 6,
|
||||
gender: '1' // 男生楼
|
||||
},
|
||||
{
|
||||
id: 112,
|
||||
label: '东区2号楼',
|
||||
type: 'building',
|
||||
buildingFloors: 8
|
||||
buildingFloors: 8,
|
||||
gender: '2' // 女生楼
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -176,13 +178,15 @@ export function getMockDormTree(): { data: DormTreeNode[] } {
|
||||
id: 211,
|
||||
label: '西区1号楼',
|
||||
type: 'building',
|
||||
buildingFloors: 7
|
||||
buildingFloors: 7,
|
||||
gender: '2' // 女生楼
|
||||
},
|
||||
{
|
||||
id: 212,
|
||||
label: '西区2号楼',
|
||||
type: 'building',
|
||||
buildingFloors: 5
|
||||
buildingFloors: 5,
|
||||
gender: '1' // 男生楼
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@ export interface DormTreeNode {
|
||||
type: 'campus' | 'area' | 'building'; // 节点类型:校区、宿舍区、宿舍楼
|
||||
disabled?: boolean; // 是否禁用选择
|
||||
buildingFloors?: number; // 宿舍楼层数
|
||||
gender?: string; // 宿舍楼性别: 1-男生楼, 2-女生楼
|
||||
}
|
||||
|
||||
// 房间信息
|
||||
@@ -72,9 +73,12 @@ export interface RoomForm {
|
||||
|
||||
// 床位表单
|
||||
export interface BedForm {
|
||||
id?: string | number;
|
||||
bedId?: string | number;
|
||||
bedCode: string;
|
||||
bedName: string;
|
||||
roomId: string | number;
|
||||
status: string;
|
||||
bedType: string;
|
||||
bedStatus: string;
|
||||
remark?: string;
|
||||
}
|
||||
@@ -1,16 +1,27 @@
|
||||
<template>
|
||||
<el-dialog v-model="visible" :title="title" width="500px" append-to-body @close="closeDialog">
|
||||
<el-form ref="formRef" :model="form" :rules="rules" label-width="80px">
|
||||
<el-form-item label="床位编号" prop="bedCode">
|
||||
<el-input v-model="form.bedCode" placeholder="请输入床位编号" maxlength="20" />
|
||||
</el-form-item>
|
||||
<el-form-item label="床位名称" prop="bedName">
|
||||
<el-input v-model="form.bedName" placeholder="请输入床位名称" maxlength="20" />
|
||||
</el-form-item>
|
||||
<el-form-item label="床位状态" prop="status">
|
||||
<el-radio-group v-model="form.status">
|
||||
<el-form-item label="床位状态" prop="bedStatus">
|
||||
<el-radio-group v-model="form.bedStatus">
|
||||
<el-radio label="0">空闲</el-radio>
|
||||
<el-radio label="1">已分配</el-radio>
|
||||
<el-radio label="1" disabled>已分配</el-radio>
|
||||
<el-radio label="2">维修中</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item label="床位类型" prop="bedType">
|
||||
<el-radio-group v-model="form.bedType">
|
||||
<el-radio label="1">下铺</el-radio>
|
||||
<el-radio label="2">上铺</el-radio>
|
||||
<el-radio label="3">中铺</el-radio>
|
||||
<el-radio label="4">独立床</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item label="备注" prop="remark">
|
||||
<el-input v-model="form.remark" type="textarea" placeholder="请输入备注内容" />
|
||||
</el-form-item>
|
||||
@@ -27,8 +38,8 @@
|
||||
<script setup lang="ts">
|
||||
import { ref, reactive, watch } from 'vue';
|
||||
import type { FormInstance, FormRules } from 'element-plus';
|
||||
import { BedForm } from '@/api/xgss/xsssfjgl/types';
|
||||
import { addBed, updateBed } from '@/api/xgss/xsssfjgl';
|
||||
import { DormBedForm } from '@/api/xgss/dormBed/types';
|
||||
import { addDormBed, updateDormBed, getDormBed } from '@/api/xgss/dormBed';
|
||||
|
||||
const props = defineProps<{
|
||||
modelValue: boolean;
|
||||
@@ -43,19 +54,24 @@ const formRef = ref<FormInstance>();
|
||||
const visible = ref(false);
|
||||
|
||||
// 表单数据
|
||||
const initFormData: BedForm = {
|
||||
const initFormData: DormBedForm = {
|
||||
id: '',
|
||||
bedCode: '',
|
||||
bedName: '',
|
||||
roomId: '',
|
||||
status: '0',
|
||||
bedStatus: '0',
|
||||
bedType: '4',
|
||||
remark: ''
|
||||
};
|
||||
|
||||
const form = reactive<BedForm>({ ...initFormData });
|
||||
const form = reactive<DormBedForm>({ ...initFormData });
|
||||
|
||||
// 表单校验规则
|
||||
const rules = reactive<FormRules>({
|
||||
bedCode: [{ required: true, message: '床位编号不能为空', trigger: 'blur' }],
|
||||
bedName: [{ required: true, message: '床位名称不能为空', trigger: 'blur' }],
|
||||
status: [{ required: true, message: '床位状态不能为空', trigger: 'change' }]
|
||||
bedStatus: [{ required: true, message: '床位状态不能为空', trigger: 'change' }],
|
||||
bedType: [{ required: true, message: '床位类型不能为空', trigger: 'change' }]
|
||||
});
|
||||
|
||||
// 监听visible属性变化
|
||||
@@ -67,6 +83,20 @@ watch(
|
||||
resetForm();
|
||||
// 设置表单初始值
|
||||
form.roomId = props.roomId;
|
||||
// 编辑模式,获取床位详情
|
||||
if (props.bedId) {
|
||||
console.log('开始获取床位详情, bedId:', props.bedId);
|
||||
getDormBed(props.bedId)
|
||||
.then((res) => {
|
||||
console.log('获取床位详情成功:', res.data);
|
||||
if (res.data) {
|
||||
Object.assign(form, res.data);
|
||||
}
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error('获取床位详情失败', error);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
@@ -98,11 +128,11 @@ const submitForm = () => {
|
||||
try {
|
||||
if (props.bedId) {
|
||||
// 修改
|
||||
form.bedId = props.bedId;
|
||||
await updateBed(form);
|
||||
form.id = props.bedId;
|
||||
await updateDormBed(form);
|
||||
} else {
|
||||
// 新增
|
||||
await addBed(form);
|
||||
await addDormBed(form);
|
||||
}
|
||||
closeDialog();
|
||||
emit('success');
|
||||
|
||||
@@ -13,18 +13,34 @@
|
||||
@keyup.enter="watchBuildingName"
|
||||
>
|
||||
</el-input>
|
||||
<el-tree
|
||||
ref="dormTreeRef"
|
||||
class="mt-2"
|
||||
node-key="id"
|
||||
:data="dormOptions"
|
||||
:props="{ label: 'label', children: 'children', disabled: 'disabled' }"
|
||||
:expand-on-click-node="false"
|
||||
:filter-node-method="filterNode"
|
||||
highlight-current
|
||||
default-expand-all
|
||||
@node-click="handleNodeClick"
|
||||
/>
|
||||
<div class="tree-container">
|
||||
<el-tree
|
||||
ref="dormTreeRef"
|
||||
class="mt-2"
|
||||
node-key="id"
|
||||
:data="dormOptions"
|
||||
:props="{ label: 'label', children: 'children', disabled: 'disabled' }"
|
||||
:expand-on-click-node="false"
|
||||
:filter-node-method="filterNode"
|
||||
highlight-current
|
||||
default-expand-all
|
||||
@node-click="handleNodeClick"
|
||||
>
|
||||
<template #default="{ node, data }">
|
||||
<div class="custom-tree-node">
|
||||
<el-tooltip v-if="data.disabled" effect="dark" content="此节点不可选择,请选择具体的宿舍楼" placement="right">
|
||||
<span :class="{ 'disabled-node': data.disabled }">{{ node.label }}</span>
|
||||
</el-tooltip>
|
||||
<span v-else>
|
||||
<span v-if="data.type === 'building'" :class="data.buildingType === '1' ? 'male-building' : 'female-building'">
|
||||
{{ data.buildingType === '1' ? '(男)' : '(女)' }}
|
||||
</span>
|
||||
{{ node.label }}
|
||||
</span>
|
||||
</div>
|
||||
</template>
|
||||
</el-tree>
|
||||
</div>
|
||||
</el-card>
|
||||
</div>
|
||||
|
||||
@@ -106,7 +122,7 @@
|
||||
<div class="mb-2">
|
||||
<span class="text-gray-500">类型:</span>{{ room.roomType === '1' ? '标准间' : room.roomType === '2' ? '单人间' : '套间' }}
|
||||
</div>
|
||||
<div class="mb-2"><span class="text-gray-500">床位:</span>0/{{ room.actualBeds }}</div>
|
||||
<div class="mb-2"><span class="text-gray-500">床位:</span>{{ room.currentBeds || 0 }}/{{ room.actualBeds }}</div>
|
||||
<div class="flex justify-between mt-4">
|
||||
<div>
|
||||
<el-button type="primary" link size="small" @click="handleManageBeds(room)">床位管理</el-button>
|
||||
@@ -140,18 +156,30 @@
|
||||
<!-- 床位管理对话框 -->
|
||||
<el-dialog v-model="bedManageDialog.visible" :title="`${bedManageDialog.roomName} - 床位管理`" width="800px">
|
||||
<div class="mb-4 text-right">
|
||||
<el-button type="primary" icon="Plus" @click="handleAddBed">添加床位</el-button>
|
||||
<el-button v-if="!isBedLimitReached" type="primary" icon="Plus" size="small" @click="handleAddBed">添加床位</el-button>
|
||||
<el-tag v-else type="info">已达到床位上限 ({{ bedList.length }}/{{ bedManageDialog.maxBeds }})</el-tag>
|
||||
<!-- <el-button type="success" icon="Check" size="small" @click="handleSaveBeds">保存</el-button> -->
|
||||
</div>
|
||||
<el-table v-loading="bedLoading" :data="bedList" border>
|
||||
<el-table-column label="床位编号" prop="bedCode" />
|
||||
<el-table-column label="床位名称" prop="bedName" />
|
||||
<el-table-column label="状态" align="center">
|
||||
<template #default="scope">
|
||||
<el-tag v-if="scope.row.status === '0'" type="success">空闲</el-tag>
|
||||
<el-tag v-else-if="scope.row.status === '1'" type="warning">已分配</el-tag>
|
||||
<el-tag v-if="scope.row.bedStatus === '0'" type="success">空闲</el-tag>
|
||||
<el-tag v-else-if="scope.row.bedStatus === '1'" type="warning">已分配</el-tag>
|
||||
<el-tag v-else type="danger">维修中</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="学生" prop="studentName" />
|
||||
<!-- 在这里增加床位类型-->
|
||||
<el-table-column label="床位类型" prop="bedType">
|
||||
<template #default="scope">
|
||||
<el-tag v-if="scope.row.bedType === '1'" type="success">下铺</el-tag>
|
||||
<el-tag v-else-if="scope.row.bedType === '2'" type="warning">上铺</el-tag>
|
||||
<el-tag v-else-if="scope.row.bedType === '3'" type="danger">中铺</el-tag>
|
||||
<el-tag v-else type="info">独立床</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<!-- <el-table-column label="学生" prop="studentName" /> -->
|
||||
<el-table-column label="备注" prop="remark" :show-overflow-tooltip="true" />
|
||||
<el-table-column label="操作" width="180" align="center">
|
||||
<template #default="scope">
|
||||
@@ -179,7 +207,9 @@ import { ElMessage, ElMessageBox } from 'element-plus';
|
||||
import { InfoFilled, Search } from '@element-plus/icons-vue';
|
||||
import { DormTreeNode, BedInfo, DormQuery } from '@/api/xgss/xsssfjgl/types';
|
||||
import { DormRoomVO, DormRoomQuery } from '@/api/xgss/dormRoom/types';
|
||||
import { getDormTree, listBeds, delBed } from '@/api/xgss/xsssfjgl';
|
||||
import { getDormTree } from '@/api/xgss/xsssfjgl';
|
||||
import { listDormBed, delDormBed } from '@/api/xgss/dormBed';
|
||||
import type { DormBedQuery } from '@/api/xgss/dormBed/types';
|
||||
import { listDormRoom, delDormRoom } from '@/api/xgss/dormRoom';
|
||||
|
||||
// 引入子组件
|
||||
@@ -198,6 +228,11 @@ const animate = reactive({
|
||||
}
|
||||
});
|
||||
|
||||
// 判断床位是否已达到上限的计算属性
|
||||
const isBedLimitReached = computed(() => {
|
||||
return bedList.value.length >= bedManageDialog.maxBeds;
|
||||
});
|
||||
|
||||
// 宿舍树数据
|
||||
const dormOptions = ref<DormTreeNode[]>([]);
|
||||
const selectedBuilding = ref<DormTreeNode>();
|
||||
@@ -232,7 +267,8 @@ const roomDialog = reactive({
|
||||
const bedManageDialog = reactive({
|
||||
visible: false,
|
||||
roomId: '' as string | number,
|
||||
roomName: ''
|
||||
roomName: '',
|
||||
maxBeds: 0 // 预设的最大床位数
|
||||
});
|
||||
|
||||
// 床位表单对话框
|
||||
@@ -267,7 +303,29 @@ watch(buildingName, () => {
|
||||
const getDormTreeData = async () => {
|
||||
try {
|
||||
const res = await getDormTree();
|
||||
dormOptions.value = res.data;
|
||||
// 处理树节点,标记非宿舍楼节点为禁用
|
||||
const processTreeNodes = (nodes: DormTreeNode[]) => {
|
||||
return nodes.map((node) => {
|
||||
// 如果不是宿舍楼类型,则禁用该节点
|
||||
if (node.type !== 'building') {
|
||||
node.disabled = true;
|
||||
}
|
||||
|
||||
// 如果是宿舍楼但没有性别信息,随机分配性别(实际项目中应该由后端提供)
|
||||
if (node.type === 'building' && !node.gender) {
|
||||
// 这里使用随机分配,实际项目中应该从后端获取
|
||||
node.gender = Math.random() > 0.5 ? '1' : '2';
|
||||
}
|
||||
|
||||
// 递归处理子节点
|
||||
if (node.children && node.children.length > 0) {
|
||||
node.children = processTreeNodes(node.children);
|
||||
}
|
||||
return node;
|
||||
});
|
||||
};
|
||||
|
||||
dormOptions.value = processTreeNodes(res.data);
|
||||
} catch (error) {
|
||||
console.error('获取宿舍树失败', error);
|
||||
}
|
||||
@@ -292,6 +350,20 @@ const loadRoomData = async () => {
|
||||
try {
|
||||
const res = await listDormRoom(queryParams);
|
||||
roomList.value = res?.rows;
|
||||
|
||||
// 加载每个房间的当前床位数量
|
||||
await Promise.all(
|
||||
roomList.value.map(async (room) => {
|
||||
try {
|
||||
const bedQuery: DormBedQuery = { roomId: room.id };
|
||||
const bedRes = await listDormBed(bedQuery);
|
||||
room.currentBeds = bedRes?.rows?.length || 0;
|
||||
} catch (error) {
|
||||
console.error('获取床位数量失败', error);
|
||||
room.currentBeds = 0;
|
||||
}
|
||||
})
|
||||
);
|
||||
} catch (error) {
|
||||
console.error('获取房间列表失败', error);
|
||||
}
|
||||
@@ -373,6 +445,7 @@ const handleRoomSuccess = () => {
|
||||
const handleManageBeds = async (room: DormRoomVO) => {
|
||||
bedManageDialog.roomId = room.id;
|
||||
bedManageDialog.roomName = room.roomName;
|
||||
bedManageDialog.maxBeds = room.actualBeds || 0; // 保存预设的床位数
|
||||
bedManageDialog.visible = true;
|
||||
|
||||
await loadBedData(room.id);
|
||||
@@ -382,8 +455,13 @@ const handleManageBeds = async (room: DormRoomVO) => {
|
||||
const loadBedData = async (roomId: string | number) => {
|
||||
bedLoading.value = true;
|
||||
try {
|
||||
const res = await listBeds(roomId);
|
||||
bedList.value = res.data;
|
||||
const query: DormBedQuery = {
|
||||
roomId,
|
||||
pageNum: 1,
|
||||
pageSize: 100
|
||||
};
|
||||
const res = await listDormBed(query);
|
||||
bedList.value = res?.rows || [];
|
||||
} catch (error) {
|
||||
console.error('获取床位列表失败', error);
|
||||
} finally {
|
||||
@@ -402,7 +480,7 @@ const handleAddBed = () => {
|
||||
/** 编辑床位 */
|
||||
const handleEditBed = (bed: BedInfo) => {
|
||||
bedDialog.title = '编辑床位';
|
||||
bedDialog.bedId = bed.bedId;
|
||||
bedDialog.bedId = bed.id;
|
||||
bedDialog.roomId = bed.roomId;
|
||||
bedDialog.visible = true;
|
||||
};
|
||||
@@ -416,10 +494,13 @@ const handleDeleteBed = (row: BedInfo) => {
|
||||
})
|
||||
.then(async () => {
|
||||
try {
|
||||
// await delBed(row.bedId);
|
||||
// 模拟删除成功
|
||||
await delDormBed(row.id);
|
||||
ElMessage.success('删除成功');
|
||||
loadBedData(bedManageDialog.roomId);
|
||||
await loadBedData(bedManageDialog.roomId);
|
||||
// 更新房间的当前床位数
|
||||
if (selectedBuilding.value) {
|
||||
loadRoomData();
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('删除床位失败', error);
|
||||
}
|
||||
@@ -428,8 +509,23 @@ const handleDeleteBed = (row: BedInfo) => {
|
||||
};
|
||||
|
||||
/** 床位操作成功回调 */
|
||||
const handleBedSuccess = () => {
|
||||
loadBedData(bedManageDialog.roomId);
|
||||
const handleBedSuccess = async () => {
|
||||
await loadBedData(bedManageDialog.roomId);
|
||||
// 更新房间的当前床位数
|
||||
if (selectedBuilding.value) {
|
||||
loadRoomData();
|
||||
}
|
||||
};
|
||||
|
||||
/** 保存床位信息 */
|
||||
const handleSaveBeds = async () => {
|
||||
try {
|
||||
ElMessage.success('床位信息保存成功');
|
||||
await loadBedData(bedManageDialog.roomId);
|
||||
} catch (error) {
|
||||
console.error('保存床位信息失败', error);
|
||||
ElMessage.error('保存失败,请重试');
|
||||
}
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
@@ -460,6 +556,23 @@ watch(
|
||||
min-width: 320px;
|
||||
max-width: 320px;
|
||||
flex-shrink: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: calc(100vh - 120px); /* 调整高度以适应页面 */
|
||||
}
|
||||
|
||||
.tree-sidebar .el-card {
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.tree-sidebar .el-card__body {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding: 15px;
|
||||
overflow: hidden; /* 防止卡片内容溢出 */
|
||||
}
|
||||
|
||||
.content-area {
|
||||
@@ -498,4 +611,68 @@ watch(
|
||||
.empty-tip {
|
||||
min-height: 400px;
|
||||
}
|
||||
|
||||
.custom-tree-node {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding-right: 8px;
|
||||
white-space: nowrap; /* 防止节点内容换行 */
|
||||
overflow: visible; /* 确保长内容可见 */
|
||||
min-width: 200px; /* 设置最小宽度 */
|
||||
}
|
||||
|
||||
.disabled-node {
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
.male-building {
|
||||
color: var(--el-color-primary);
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.female-building {
|
||||
color: #ff69b4; /* 粉色 */
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.tree-container {
|
||||
overflow-y: auto; /* 纵向滚动条 */
|
||||
overflow-x: auto; /* 横向滚动条 */
|
||||
max-height: unset; /* 取消最大高度限制 */
|
||||
min-height: 0; /* 允许容器收缩 */
|
||||
height: 100%; /* 填满父容器 */
|
||||
flex: 1; /* 占用剩余空间 */
|
||||
border: 1px solid #ebeef5;
|
||||
border-radius: 4px;
|
||||
padding: 5px;
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.tree-container::-webkit-scrollbar {
|
||||
width: 6px;
|
||||
height: 6px;
|
||||
}
|
||||
|
||||
.tree-container::-webkit-scrollbar-thumb {
|
||||
background-color: #c0c4cc;
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
.tree-container::-webkit-scrollbar-track {
|
||||
background-color: #f5f7fa;
|
||||
}
|
||||
|
||||
/* 当宿舍树节点太长时,确保有足够空间显示完整内容 */
|
||||
.tree-container .el-tree-node__content {
|
||||
min-width: fit-content;
|
||||
height: auto;
|
||||
min-height: 26px;
|
||||
padding: 4px 0;
|
||||
}
|
||||
|
||||
.tree-container .el-tree {
|
||||
min-width: 100%; /* 确保树至少占满容器宽度 */
|
||||
width: max-content; /* 允许内容扩展 */
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,150 @@
|
||||
<template>
|
||||
<el-dialog v-model="visible" :title="title" width="500px" append-to-body @close="closeDialog">
|
||||
<el-form ref="formRef" :model="form" :rules="rules" label-width="80px">
|
||||
<el-form-item label="床位编号" prop="bedCode">
|
||||
<el-input v-model="form.bedCode" placeholder="请输入床位编号" maxlength="20" />
|
||||
</el-form-item>
|
||||
<el-form-item label="床位名称" prop="bedName">
|
||||
<el-input v-model="form.bedName" placeholder="请输入床位名称" maxlength="20" />
|
||||
</el-form-item>
|
||||
<el-form-item label="床位状态" prop="bedStatus">
|
||||
<el-radio-group v-model="form.bedStatus">
|
||||
<el-radio label="0">空闲</el-radio>
|
||||
<el-radio label="1" disabled>已分配</el-radio>
|
||||
<el-radio label="2">维修中</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item label="床位类型" prop="bedType">
|
||||
<el-radio-group v-model="form.bedType">
|
||||
<el-radio label="1">下铺</el-radio>
|
||||
<el-radio label="2">上铺</el-radio>
|
||||
<el-radio label="3">中铺</el-radio>
|
||||
<el-radio label="4">独立床</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item label="备注" prop="remark">
|
||||
<el-input v-model="form.remark" type="textarea" placeholder="请输入备注内容" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<div class="dialog-footer">
|
||||
<el-button type="primary" @click="submitForm">确 定</el-button>
|
||||
<el-button @click="visible = false">取 消</el-button>
|
||||
</div>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, reactive, watch } from 'vue';
|
||||
import type { FormInstance, FormRules } from 'element-plus';
|
||||
import { DormBedForm } from '@/api/xgss/dormBed/types';
|
||||
import { addDormBed, updateDormBed, getDormBed } from '@/api/xgss/dormBed';
|
||||
|
||||
const props = defineProps<{
|
||||
modelValue: boolean;
|
||||
title: string;
|
||||
bedId?: string | number;
|
||||
roomId: string | number;
|
||||
}>();
|
||||
|
||||
const emit = defineEmits(['update:modelValue', 'success']);
|
||||
|
||||
const formRef = ref<FormInstance>();
|
||||
const visible = ref(false);
|
||||
|
||||
// 表单数据
|
||||
const initFormData: DormBedForm = {
|
||||
id: '',
|
||||
bedCode: '',
|
||||
bedName: '',
|
||||
roomId: '',
|
||||
bedStatus: '0',
|
||||
bedType: '4',
|
||||
remark: ''
|
||||
};
|
||||
|
||||
const form = reactive<DormBedForm>({ ...initFormData });
|
||||
|
||||
// 表单校验规则
|
||||
const rules = reactive<FormRules>({
|
||||
bedCode: [{ required: true, message: '床位编号不能为空', trigger: 'blur' }],
|
||||
bedName: [{ required: true, message: '床位名称不能为空', trigger: 'blur' }],
|
||||
bedStatus: [{ required: true, message: '床位状态不能为空', trigger: 'change' }],
|
||||
bedType: [{ required: true, message: '床位类型不能为空', trigger: 'change' }]
|
||||
});
|
||||
|
||||
// 监听visible属性变化
|
||||
watch(
|
||||
() => props.modelValue,
|
||||
(val) => {
|
||||
visible.value = val;
|
||||
if (val) {
|
||||
resetForm();
|
||||
// 设置表单初始值
|
||||
form.roomId = props.roomId;
|
||||
// 编辑模式,获取床位详情
|
||||
if (props.bedId) {
|
||||
console.log('开始获取床位详情, bedId:', props.bedId);
|
||||
getDormBed(props.bedId)
|
||||
.then((res) => {
|
||||
console.log('获取床位详情成功:', res.data);
|
||||
if (res.data) {
|
||||
Object.assign(form, res.data);
|
||||
}
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error('获取床位详情失败', error);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
// 监听visible变化,同步回父组件
|
||||
watch(
|
||||
() => visible.value,
|
||||
(val) => {
|
||||
emit('update:modelValue', val);
|
||||
}
|
||||
);
|
||||
|
||||
// 关闭对话框
|
||||
const closeDialog = () => {
|
||||
visible.value = false;
|
||||
resetForm();
|
||||
};
|
||||
|
||||
// 重置表单
|
||||
const resetForm = () => {
|
||||
Object.assign(form, { ...initFormData });
|
||||
formRef.value?.resetFields();
|
||||
};
|
||||
|
||||
// 提交表单
|
||||
const submitForm = () => {
|
||||
formRef.value?.validate(async (valid) => {
|
||||
if (valid) {
|
||||
try {
|
||||
if (props.bedId) {
|
||||
// 修改
|
||||
form.id = props.bedId;
|
||||
await updateDormBed(form);
|
||||
} else {
|
||||
// 新增
|
||||
await addDormBed(form);
|
||||
}
|
||||
closeDialog();
|
||||
emit('success');
|
||||
} catch (error) {
|
||||
console.error('操作失败', error);
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
// 添加默认导出以支持导入
|
||||
defineOptions({
|
||||
name: 'BedDialog'
|
||||
});
|
||||
</script>
|
||||
@@ -0,0 +1,171 @@
|
||||
<template>
|
||||
<el-dialog v-model="visible" :title="title" width="500px" append-to-body @close="closeDialog">
|
||||
<el-form ref="formRef" :model="form" :rules="rules" label-width="80px">
|
||||
<el-form-item label="楼层" prop="floorNum">
|
||||
<el-input v-model="form.floorNum" placeholder="请输入楼层" :disabled="true" />
|
||||
</el-form-item>
|
||||
<el-form-item label="房间编号" prop="roomCode">
|
||||
<el-input v-model="form.roomCode" placeholder="请输入房间编号" maxlength="20" />
|
||||
</el-form-item>
|
||||
<el-form-item label="房间名称" prop="roomName">
|
||||
<el-input v-model="form.roomName" placeholder="请输入房间名称" maxlength="20" />
|
||||
</el-form-item>
|
||||
<el-form-item label="房间类型" prop="roomType">
|
||||
<el-select v-model="form.roomType" placeholder="请选择房间类型" clearable style="width: 100%">
|
||||
<el-option label="标准间" value="1" />
|
||||
<el-option label="单人间" value="2" />
|
||||
<el-option label="套间" value="3" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="床位数量" prop="actualBeds">
|
||||
<el-input-number v-model="form.actualBeds" :min="1" :max="8" controls-position="right" style="width: 100%" />
|
||||
</el-form-item>
|
||||
<el-form-item label="房间面积" prop="roomArea">
|
||||
<el-input v-model="form.roomArea" placeholder="请输入房间面积" maxlength="20">
|
||||
<template #append>
|
||||
<span style="color: #000; background: transparent">平方米</span>
|
||||
</template>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="房间状态" prop="roomStatus">
|
||||
<el-radio-group v-model="form.roomStatus">
|
||||
<el-radio label="0">正常</el-radio>
|
||||
<el-radio label="1">维修中</el-radio>
|
||||
<el-radio label="2">停用</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item label="备注" prop="remark">
|
||||
<el-input v-model="form.remark" type="textarea" placeholder="请输入备注内容" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<div class="dialog-footer">
|
||||
<el-button type="primary" @click="submitForm">确 定</el-button>
|
||||
<el-button @click="visible = false">取 消</el-button>
|
||||
</div>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, reactive, watch } from 'vue';
|
||||
import type { FormInstance, FormRules } from 'element-plus';
|
||||
import { DormRoomForm, DormRoomVO } from '@/api/xgss/dormRoom/types';
|
||||
import { addDormRoom, updateDormRoom } from '@/api/xgss/dormRoom';
|
||||
|
||||
const props = defineProps<{
|
||||
modelValue: boolean;
|
||||
title: string;
|
||||
roomId?: string | number;
|
||||
floorNum: number;
|
||||
buildingId: string | number;
|
||||
room?: DormRoomVO;
|
||||
}>();
|
||||
|
||||
const emit = defineEmits(['update:modelValue', 'success']);
|
||||
|
||||
const formRef = ref<FormInstance>();
|
||||
const visible = ref(false);
|
||||
|
||||
// 表单数据
|
||||
const initFormData: DormRoomForm = {
|
||||
id: undefined,
|
||||
roomCode: '',
|
||||
roomName: '',
|
||||
floorNum: 1,
|
||||
buildingId: '',
|
||||
actualBeds: 4,
|
||||
roomArea: 0,
|
||||
roomType: '1',
|
||||
roomStatus: '0',
|
||||
remark: ''
|
||||
};
|
||||
|
||||
const form = reactive<DormRoomForm>({ ...initFormData });
|
||||
|
||||
// 表单校验规则
|
||||
const rules = reactive<FormRules>({
|
||||
roomCode: [{ required: true, message: '房间编号不能为空', trigger: 'blur' }],
|
||||
roomName: [{ required: true, message: '房间名称不能为空', trigger: 'blur' }],
|
||||
floorNum: [{ required: true, message: '楼层不能为空', trigger: 'blur' }],
|
||||
actualBeds: [{ required: true, message: '床位数量不能为空', trigger: 'change' }],
|
||||
roomType: [{ required: true, message: '房间类型不能为空', trigger: 'change' }],
|
||||
roomStatus: [{ required: true, message: '房间状态不能为空', trigger: 'change' }]
|
||||
});
|
||||
|
||||
// 监听visible属性变化
|
||||
watch(
|
||||
() => props.modelValue,
|
||||
(val) => {
|
||||
visible.value = val;
|
||||
if (val) {
|
||||
// 完全重置表单,确保没有残留数据
|
||||
resetForm();
|
||||
|
||||
// 重新设置基本参数
|
||||
form.floorNum = props.floorNum;
|
||||
form.buildingId = props.buildingId;
|
||||
|
||||
// 如果是编辑模式且有room数据,填充表单数据
|
||||
if (props.room) {
|
||||
Object.keys(form).forEach((key) => {
|
||||
if (key in props.room) {
|
||||
form[key] = props.room[key];
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
// 监听visible变化,同步回父组件
|
||||
watch(
|
||||
() => visible.value,
|
||||
(val) => {
|
||||
emit('update:modelValue', val);
|
||||
}
|
||||
);
|
||||
|
||||
// 关闭对话框
|
||||
const closeDialog = () => {
|
||||
visible.value = false;
|
||||
resetForm();
|
||||
};
|
||||
|
||||
// 重置表单
|
||||
const resetForm = () => {
|
||||
// 使用深拷贝确保完全重置
|
||||
Object.keys(form).forEach((key) => {
|
||||
form[key] = initFormData[key];
|
||||
});
|
||||
formRef.value?.resetFields();
|
||||
};
|
||||
|
||||
// 提交表单
|
||||
const submitForm = () => {
|
||||
formRef.value?.validate(async (valid) => {
|
||||
if (valid) {
|
||||
try {
|
||||
console.log(props.roomId);
|
||||
if (props.roomId) {
|
||||
// 修改
|
||||
form.id = props.roomId;
|
||||
await updateDormRoom(form);
|
||||
} else {
|
||||
// 新增
|
||||
await addDormRoom(form);
|
||||
}
|
||||
closeDialog();
|
||||
emit('success');
|
||||
} catch (error) {
|
||||
console.error('操作失败', error);
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
// 添加默认导出以支持导入
|
||||
defineOptions({
|
||||
name: 'RoomDialog'
|
||||
});
|
||||
</script>
|
||||
@@ -0,0 +1,989 @@
|
||||
<template>
|
||||
<div class="p-2">
|
||||
<div class="flex-layout">
|
||||
<!-- 宿舍树 -->
|
||||
<div class="tree-sidebar">
|
||||
<!-- 宿舍楼树 -->
|
||||
<el-card shadow="hover" class="tree-card">
|
||||
<div class="card-header-title">宿舍楼</div>
|
||||
<el-input
|
||||
v-model="buildingName"
|
||||
prefix-icon="Search"
|
||||
placeholder="请输入宿舍楼名称"
|
||||
clearable
|
||||
@clear="watchBuildingName"
|
||||
@keyup.enter="watchBuildingName"
|
||||
>
|
||||
</el-input>
|
||||
<el-tree
|
||||
ref="dormTreeRef"
|
||||
class="mt-2"
|
||||
node-key="id"
|
||||
:data="dormOptions"
|
||||
:props="{ label: 'label', children: 'children', disabled: 'disabled' }"
|
||||
:expand-on-click-node="false"
|
||||
:filter-node-method="filterNode"
|
||||
highlight-current
|
||||
default-expand-all
|
||||
@node-click="handleNodeClick"
|
||||
>
|
||||
<template #default="{ node, data }">
|
||||
<div class="custom-tree-node">
|
||||
<el-tooltip v-if="data.disabled" effect="dark" content="此节点不可选择,请选择具体的宿舍楼" placement="right">
|
||||
<span :class="{ 'disabled-node': data.disabled }">{{ node.label }}</span>
|
||||
</el-tooltip>
|
||||
<span v-else>
|
||||
<span v-if="data.type === 'building'" :class="data.buildingType === '1' ? 'male-building' : 'female-building'">
|
||||
{{ data.buildingType === '1' ? '(男)' : '(女)' }}
|
||||
</span>
|
||||
{{ node.label }}
|
||||
</span>
|
||||
<span v-if="data.type === 'college' || data.type === 'class'" class="bed-count">
|
||||
<el-tag size="small" type="success" class="ml-2">男:{{ data.maleAssigned }}/{{ data.maleTotal }}</el-tag>
|
||||
<el-tag size="small" type="danger" class="ml-2">女:{{ data.femaleAssigned }}/{{ data.femaleTotal }}</el-tag>
|
||||
</span>
|
||||
</div>
|
||||
</template>
|
||||
</el-tree>
|
||||
</el-card>
|
||||
|
||||
<!-- 学生树 -->
|
||||
<el-card shadow="hover" class="tree-card mt-4">
|
||||
<div class="card-header-title">学生信息</div>
|
||||
<el-input
|
||||
v-model="studentSearchKey"
|
||||
prefix-icon="Search"
|
||||
placeholder="请输入关键词搜索"
|
||||
clearable
|
||||
@clear="watchStudentSearch"
|
||||
@keyup.enter="watchStudentSearch"
|
||||
>
|
||||
</el-input>
|
||||
<el-tree
|
||||
ref="studentTreeRef"
|
||||
class="mt-2"
|
||||
node-key="id"
|
||||
:data="studentTreeData"
|
||||
:props="{ label: (data) => data.label, children: 'children' }"
|
||||
:expand-on-click-node="false"
|
||||
:filter-node-method="filterStudentNode"
|
||||
highlight-current
|
||||
default-expand-all
|
||||
@node-click="handleStudentNodeClick"
|
||||
>
|
||||
<template #default="{ node, data }">
|
||||
<span class="custom-tree-node">
|
||||
<span>{{ node.label }}</span>
|
||||
<span v-if="data.type === 'college' || data.type === 'class'" class="bed-count">
|
||||
<el-tag size="small" type="success" class="ml-2">男:{{ data.maleAssigned }}/{{ data.maleTotal }}</el-tag>
|
||||
<el-tag size="small" type="danger" class="ml-2">女:{{ data.femaleAssigned }}/{{ data.femaleTotal }}</el-tag>
|
||||
</span>
|
||||
</span>
|
||||
</template>
|
||||
</el-tree>
|
||||
</el-card>
|
||||
</div>
|
||||
|
||||
<div class="content-area">
|
||||
<transition :enter-active-class="animate.searchAnimate.enter" :leave-active-class="animate.searchAnimate.leave">
|
||||
<div v-show="showSearch" class="mb-[10px]">
|
||||
<el-card shadow="hover">
|
||||
<el-form ref="queryFormRef" :model="queryParams" inline>
|
||||
<el-form-item label="房间号" prop="roomName">
|
||||
<el-input v-model="queryParams.roomName" placeholder="请输入房间号" clearable @keyup.enter="handleQuery" />
|
||||
</el-form-item>
|
||||
<el-form-item label="状态" prop="roomStatus">
|
||||
<el-select v-model="queryParams.roomStatus" placeholder="房间状态" clearable>
|
||||
<el-option label="正常" value="0" />
|
||||
<el-option label="维修中" value="1" />
|
||||
<el-option label="停用" value="2" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
|
||||
<el-button icon="Refresh" @click="resetQuery">重置</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-card>
|
||||
</div>
|
||||
</transition>
|
||||
|
||||
<el-card v-if="!selectedBuilding" shadow="hover" class="empty-tip">
|
||||
<div class="flex flex-col items-center justify-center h-[400px]">
|
||||
<el-icon class="text-gray-400 text-5xl mb-4"><InfoFilled /></el-icon>
|
||||
<p class="text-gray-500 text-lg">请在左侧选择宿舍楼</p>
|
||||
</div>
|
||||
</el-card>
|
||||
|
||||
<template v-else>
|
||||
<el-card shadow="hover" class="mb-4">
|
||||
<template #header>
|
||||
<el-row>
|
||||
<el-col :span="12">
|
||||
<el-button type="primary" icon="check" size="small" @click="handleAddRoom">分配给二级学院</el-button>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</template>
|
||||
|
||||
<!-- 操作按钮 -->
|
||||
<div class="mb-4">
|
||||
<el-row>
|
||||
<el-col :span="12">
|
||||
<span class="font-bold">{{ selectedBuilding?.label }} - 房间管理</span>
|
||||
<span class="ml-4 text-blue-500">已选择: {{ selectedRoomCount }}个房间 / {{ selectedBedCount }}个床位</span>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<!-- <el-button type="primary" icon="Plus" @click="handleAddRoom">添加房间</el-button> -->
|
||||
</div>
|
||||
|
||||
<!-- 房间及床位树形表格 -->
|
||||
<el-table
|
||||
ref="tableRef"
|
||||
v-loading="loading"
|
||||
:data="roomList"
|
||||
row-key="id"
|
||||
border
|
||||
:expand-row-keys="expandedRowKeys"
|
||||
@expand-change="handleExpandChange"
|
||||
:tree-props="{ children: 'children', hasChildren: 'hasChildren' }"
|
||||
style="width: 100%"
|
||||
@selection-change="handleSelectionChange"
|
||||
>
|
||||
<el-table-column type="selection" width="55" :selectable="checkSelectable" />
|
||||
<el-table-column prop="roomName" label="房间/宿舍名称" min-width="180">
|
||||
<template #default="scope">
|
||||
<span v-if="!scope.row.isBed">{{ scope.row.roomName }} (房间)</span>
|
||||
<span v-else>{{ scope.row.bedName }} (床位)</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="floorNum" label="楼层" width="80" align="center">
|
||||
<template #default="scope">
|
||||
<span v-if="!scope.row.isBed">{{ scope.row.floorNum }}</span>
|
||||
<span v-else>-</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="类型" width="120" align="center">
|
||||
<template #default="scope">
|
||||
<template v-if="!scope.row.isBed">
|
||||
<span>{{ scope.row.roomType === '1' ? '标准间' : scope.row.roomType === '2' ? '单人间' : '套间' }}</span>
|
||||
</template>
|
||||
<template v-else>
|
||||
<el-tag v-if="scope.row.bedType === '1'" type="success" size="small">下铺</el-tag>
|
||||
<el-tag v-else-if="scope.row.bedType === '2'" type="warning" size="small">上铺</el-tag>
|
||||
<el-tag v-else-if="scope.row.bedType === '3'" type="danger" size="small">中铺</el-tag>
|
||||
<el-tag v-else type="info" size="small">独立床</el-tag>
|
||||
</template>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="状态" width="100" align="center">
|
||||
<template #default="scope">
|
||||
<template v-if="!scope.row.isBed">
|
||||
<el-tag v-if="scope.row.roomStatus === '0'" type="success">正常</el-tag>
|
||||
<el-tag v-else-if="scope.row.roomStatus === '1'" type="warning">维修中</el-tag>
|
||||
<el-tag v-else type="danger">停用</el-tag>
|
||||
</template>
|
||||
<template v-else>
|
||||
<el-tag v-if="scope.row.bedStatus === '0'" type="success">空闲</el-tag>
|
||||
<el-tag v-else-if="scope.row.bedStatus === '1'" type="warning">已分配</el-tag>
|
||||
<el-tag v-else type="danger">维修中</el-tag>
|
||||
</template>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="remark" label="备注" min-width="150" :show-overflow-tooltip="true">
|
||||
<template #default="scope">
|
||||
{{ scope.row.remark }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="180" align="center">
|
||||
<template #default="scope">
|
||||
<template v-if="!scope.row.isBed">
|
||||
<!-- <el-button type="primary" link icon="Plus" @click="handleAddBed(scope.row)" /> -->
|
||||
<el-button type="primary" link icon="Edit" @click="handleEditRoom(scope.row)" />
|
||||
<el-button type="danger" link icon="Delete" @click="handleDeleteRoom(scope.row)" />
|
||||
</template>
|
||||
<template v-else>
|
||||
<el-button type="primary" link icon="Edit" @click="handleEditBed(scope.row)" />
|
||||
<el-button type="danger" link icon="Delete" @click="handleDeleteBed(scope.row)" />
|
||||
</template>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</el-card>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 房间管理对话框 -->
|
||||
<room-dialog
|
||||
v-model="roomDialog.visible"
|
||||
:title="roomDialog.title"
|
||||
:room-id="roomDialog.roomId"
|
||||
:floor-num="roomDialog.floorNum"
|
||||
:building-id="roomDialog.buildingId"
|
||||
:room="roomDialog.room"
|
||||
@success="handleRoomSuccess"
|
||||
/>
|
||||
|
||||
<!-- 床位表单对话框 -->
|
||||
<bed-dialog
|
||||
v-model="bedDialog.visible"
|
||||
:title="bedDialog.title"
|
||||
:bed-id="bedDialog.bedId"
|
||||
:room-id="bedDialog.roomId"
|
||||
@success="handleBedSuccess"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup name="DormRoomTreeManagement" lang="ts">
|
||||
import { ref, computed, reactive, onMounted, nextTick, watch, getCurrentInstance } from 'vue';
|
||||
import { InfoFilled } from '@element-plus/icons-vue';
|
||||
import type { DormTreeNode, BedInfo } from '@/api/xgss/xsssfjgl/types';
|
||||
import type { DormRoomVO } from '@/api/xgss/dormRoom/types';
|
||||
import { getDormTree } from '@/api/xgss/xsssfjgl';
|
||||
import { listDormBed, delDormBed, getDormBed } from '@/api/xgss/dormBed';
|
||||
import { listDormRoom, delDormRoom } from '@/api/xgss/dormRoom';
|
||||
|
||||
// 引入子组件
|
||||
import RoomDialog from './components/RoomDialog.vue';
|
||||
import BedDialog from './components/BedDialog.vue';
|
||||
|
||||
const { proxy } = getCurrentInstance();
|
||||
|
||||
// 组件状态
|
||||
const dormTreeRef = ref();
|
||||
const queryFormRef = ref();
|
||||
const tableRef = ref();
|
||||
const buildingName = ref('');
|
||||
const showSearch = ref(true);
|
||||
const loading = ref(false);
|
||||
const expandedRowKeys = ref<string[]>([]);
|
||||
|
||||
// 选择状态
|
||||
const selectedRows = ref<any[]>([]);
|
||||
const selectedRoomCount = ref(0);
|
||||
const selectedBedCount = ref(0);
|
||||
|
||||
const animate = reactive({
|
||||
searchAnimate: {
|
||||
enter: 'animate__animated animate__fadeInDown',
|
||||
leave: 'animate__animated animate__fadeOutUp'
|
||||
}
|
||||
});
|
||||
|
||||
// 宿舍树数据
|
||||
const dormOptions = ref<DormTreeNode[]>([]);
|
||||
const selectedBuilding = ref<DormTreeNode>();
|
||||
|
||||
// 房间和床位数据(合并展示)
|
||||
const roomList = ref<any[]>([]);
|
||||
|
||||
// 查询参数
|
||||
const queryParams = reactive({
|
||||
pageNum: 1,
|
||||
pageSize: 10000,
|
||||
buildingId: undefined as string | number | undefined,
|
||||
roomName: '',
|
||||
roomStatus: undefined as string | undefined
|
||||
});
|
||||
|
||||
// 房间对话框
|
||||
const roomDialog = reactive({
|
||||
visible: false,
|
||||
title: '',
|
||||
roomId: undefined as string | number | undefined,
|
||||
floorNum: 1,
|
||||
buildingId: '' as string | number,
|
||||
room: undefined as DormRoomVO | undefined
|
||||
});
|
||||
|
||||
// 床位表单对话框
|
||||
const bedDialog = reactive({
|
||||
visible: false,
|
||||
title: '',
|
||||
bedId: undefined as string | number | undefined,
|
||||
roomId: '' as string | number
|
||||
});
|
||||
|
||||
// 学生树相关数据
|
||||
const studentTreeRef = ref();
|
||||
const studentSearchKey = ref('');
|
||||
const studentTreeData = ref<any[]>([
|
||||
{
|
||||
id: 'grade-2025',
|
||||
label: '2025级',
|
||||
type: 'grade',
|
||||
children: [
|
||||
{
|
||||
id: 'college-cs-2025',
|
||||
label: '计算机学院',
|
||||
type: 'college',
|
||||
maleAssigned: 45,
|
||||
maleTotal: 120,
|
||||
femaleAssigned: 25,
|
||||
femaleTotal: 60,
|
||||
children: [
|
||||
{
|
||||
id: 'class-cs-1-2025',
|
||||
label: '计算机科学与技术1班',
|
||||
type: 'class',
|
||||
maleAssigned: 20,
|
||||
maleTotal: 40,
|
||||
femaleAssigned: 10,
|
||||
femaleTotal: 15
|
||||
},
|
||||
{
|
||||
id: 'class-cs-2-2025',
|
||||
label: '计算机科学与技术2班',
|
||||
type: 'class',
|
||||
maleAssigned: 25,
|
||||
maleTotal: 40,
|
||||
femaleAssigned: 15,
|
||||
femaleTotal: 20
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
id: 'college-ee-2025',
|
||||
label: '电子工程学院',
|
||||
type: 'college',
|
||||
maleAssigned: 55,
|
||||
maleTotal: 100,
|
||||
femaleAssigned: 35,
|
||||
femaleTotal: 50,
|
||||
children: [
|
||||
{
|
||||
id: 'class-ee-1-2025',
|
||||
label: '电子信息工程1班',
|
||||
type: 'class',
|
||||
maleAssigned: 30,
|
||||
maleTotal: 50,
|
||||
femaleAssigned: 20,
|
||||
femaleTotal: 25
|
||||
},
|
||||
{
|
||||
id: 'class-ee-2-2025',
|
||||
label: '电子信息工程2班',
|
||||
type: 'class',
|
||||
maleAssigned: 25,
|
||||
maleTotal: 50,
|
||||
femaleAssigned: 15,
|
||||
femaleTotal: 25
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
id: 'grade-2024',
|
||||
label: '2024级',
|
||||
type: 'grade',
|
||||
children: [
|
||||
{
|
||||
id: 'college-cs-2024',
|
||||
label: '计算机学院',
|
||||
type: 'college',
|
||||
maleAssigned: 110,
|
||||
maleTotal: 120,
|
||||
femaleAssigned: 58,
|
||||
femaleTotal: 60,
|
||||
children: [
|
||||
{
|
||||
id: 'class-cs-1-2024',
|
||||
label: '计算机科学与技术1班',
|
||||
type: 'class',
|
||||
maleAssigned: 38,
|
||||
maleTotal: 40,
|
||||
femaleAssigned: 14,
|
||||
femaleTotal: 15
|
||||
},
|
||||
{
|
||||
id: 'class-cs-2-2024',
|
||||
label: '计算机科学与技术2班',
|
||||
type: 'class',
|
||||
maleAssigned: 37,
|
||||
maleTotal: 40,
|
||||
femaleAssigned: 18,
|
||||
femaleTotal: 20
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
id: 'grade-2024',
|
||||
label: '2024级',
|
||||
type: 'grade',
|
||||
children: [
|
||||
{
|
||||
id: 'college-cs-2024',
|
||||
label: '计算机学院',
|
||||
type: 'college',
|
||||
maleAssigned: 110,
|
||||
maleTotal: 120,
|
||||
femaleAssigned: 58,
|
||||
femaleTotal: 60,
|
||||
children: [
|
||||
{
|
||||
id: 'class-cs-1-2024',
|
||||
label: '计算机科学与技术1班',
|
||||
type: 'class',
|
||||
maleAssigned: 38,
|
||||
maleTotal: 40,
|
||||
femaleAssigned: 14,
|
||||
femaleTotal: 15
|
||||
},
|
||||
{
|
||||
id: 'class-cs-2-2024',
|
||||
label: '计算机科学与技术2班',
|
||||
type: 'class',
|
||||
maleAssigned: 37,
|
||||
maleTotal: 40,
|
||||
femaleAssigned: 18,
|
||||
femaleTotal: 20
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
id: 'grade-2024',
|
||||
label: '2024级',
|
||||
type: 'grade',
|
||||
children: [
|
||||
{
|
||||
id: 'college-cs-2024',
|
||||
label: '计算机学院',
|
||||
type: 'college',
|
||||
maleAssigned: 110,
|
||||
maleTotal: 120,
|
||||
femaleAssigned: 58,
|
||||
femaleTotal: 60,
|
||||
children: [
|
||||
{
|
||||
id: 'class-cs-1-2024',
|
||||
label: '计算机科学与技术1班',
|
||||
type: 'class',
|
||||
maleAssigned: 38,
|
||||
maleTotal: 40,
|
||||
femaleAssigned: 14,
|
||||
femaleTotal: 15
|
||||
},
|
||||
{
|
||||
id: 'class-cs-2-2024',
|
||||
label: '计算机科学与技术2班',
|
||||
type: 'class',
|
||||
maleAssigned: 37,
|
||||
maleTotal: 40,
|
||||
femaleAssigned: 18,
|
||||
femaleTotal: 20
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]);
|
||||
|
||||
/** 通过条件过滤节点 */
|
||||
const filterNode = (value: string, data: DormTreeNode) => {
|
||||
if (!value) return true;
|
||||
return data.label.toLowerCase().indexOf(value.toLowerCase()) !== -1;
|
||||
};
|
||||
|
||||
/** 通过条件过滤学生节点 */
|
||||
const filterStudentNode = (value: string, data: any) => {
|
||||
if (!value) return true;
|
||||
return data.label.toLowerCase().indexOf(value.toLowerCase()) !== -1;
|
||||
};
|
||||
|
||||
/** 监听宿舍楼名称变化,筛选树 */
|
||||
const watchBuildingName = () => {
|
||||
dormTreeRef.value?.filter(buildingName.value);
|
||||
};
|
||||
|
||||
/** 监听学生树搜索输入变化 */
|
||||
const watchStudentSearch = () => {
|
||||
studentTreeRef.value?.filter(studentSearchKey.value);
|
||||
};
|
||||
|
||||
// 监听buildingName变化,实时筛选宿舍楼
|
||||
watch(buildingName, () => {
|
||||
watchBuildingName();
|
||||
});
|
||||
|
||||
/** 获取宿舍树数据 */
|
||||
const getDormTreeData = async () => {
|
||||
try {
|
||||
const res = await getDormTree();
|
||||
|
||||
// 处理树节点,标记非宿舍楼节点为禁用
|
||||
const processTreeNodes = (nodes: DormTreeNode[]) => {
|
||||
return nodes.map((node) => {
|
||||
// 如果不是宿舍楼类型,则禁用该节点
|
||||
if (node.type !== 'building') {
|
||||
node.disabled = true;
|
||||
}
|
||||
|
||||
// 如果是宿舍楼但没有性别信息,添加宿舍楼性别类型
|
||||
if (node.type === 'building' && !node.buildingType) {
|
||||
// 实际项目中应该从后端获取,这里先用随机分配,后续可以修改为从后端获取
|
||||
node.buildingType = Math.random() > 0.5 ? '1' : '2';
|
||||
}
|
||||
|
||||
// 递归处理子节点
|
||||
if (node.children && node.children.length > 0) {
|
||||
node.children = processTreeNodes(node.children);
|
||||
}
|
||||
return node;
|
||||
});
|
||||
};
|
||||
|
||||
dormOptions.value = processTreeNodes(res.data);
|
||||
} catch (error) {
|
||||
console.error('获取宿舍树失败', error);
|
||||
}
|
||||
};
|
||||
|
||||
/** 处理节点单击事件 */
|
||||
const handleNodeClick = (data: DormTreeNode) => {
|
||||
if (data.type !== 'building') {
|
||||
// 如果不是宿舍楼,不进行操作
|
||||
return;
|
||||
}
|
||||
|
||||
// 设置选中的宿舍楼
|
||||
selectedBuilding.value = data;
|
||||
// 更新查询参数
|
||||
queryParams.buildingId = data.id;
|
||||
// 加载房间数据
|
||||
handleQuery();
|
||||
};
|
||||
|
||||
/** 学生树节点点击处理 */
|
||||
const handleStudentNodeClick = (data: any) => {
|
||||
console.log('学生树节点点击:', data);
|
||||
// 这里可以实现学生节点点击后的相关功能
|
||||
};
|
||||
|
||||
/** 查询房间数据 */
|
||||
const handleQuery = () => {
|
||||
loadRoomData();
|
||||
};
|
||||
|
||||
/** 重置查询条件 */
|
||||
const resetQuery = () => {
|
||||
queryFormRef.value?.resetFields();
|
||||
if (selectedBuilding.value) {
|
||||
queryParams.buildingId = selectedBuilding.value.id;
|
||||
}
|
||||
handleQuery();
|
||||
};
|
||||
|
||||
/** 加载房间数据 */
|
||||
const loadRoomData = async () => {
|
||||
if (!queryParams.buildingId) return;
|
||||
|
||||
loading.value = true;
|
||||
try {
|
||||
// 获取房间列表
|
||||
const res = await listDormRoom(queryParams);
|
||||
const rooms = res.rows || [];
|
||||
|
||||
// 存储临时结果
|
||||
const tempList: any[] = [];
|
||||
|
||||
// 处理每个房间
|
||||
for (const room of rooms) {
|
||||
// 添加房间记录
|
||||
const roomRecord = {
|
||||
...room,
|
||||
isBed: false,
|
||||
children: []
|
||||
};
|
||||
|
||||
// 获取房间的床位信息
|
||||
try {
|
||||
const bedRes = await listDormBed({ roomId: room.id });
|
||||
const beds = bedRes.rows || [];
|
||||
|
||||
// 将床位信息添加为房间的子项
|
||||
if (beds.length > 0) {
|
||||
roomRecord.children = beds.map((bed: any) => ({
|
||||
...bed,
|
||||
isBed: true,
|
||||
roomName: room.roomName // 保留房间名称,方便展示
|
||||
}));
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(`获取房间 ${room.id} 的床位信息失败`, error);
|
||||
}
|
||||
|
||||
tempList.push(roomRecord);
|
||||
}
|
||||
|
||||
roomList.value = tempList;
|
||||
|
||||
// 重置选择状态
|
||||
selectedRows.value = [];
|
||||
selectedRoomCount.value = 0;
|
||||
selectedBedCount.value = 0;
|
||||
} catch (error) {
|
||||
console.error('加载房间数据失败', error);
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
/** 添加房间 */
|
||||
const handleAddRoom = () => {
|
||||
if (!selectedBuilding.value) {
|
||||
// 使用全局自动导入的 ElMessage
|
||||
proxy.$modal.msgWarning('请先选择宿舍楼');
|
||||
return;
|
||||
}
|
||||
roomDialog.title = '添加房间';
|
||||
roomDialog.roomId = undefined;
|
||||
roomDialog.floorNum = 1;
|
||||
roomDialog.buildingId = selectedBuilding.value.id;
|
||||
roomDialog.room = undefined;
|
||||
roomDialog.visible = true;
|
||||
};
|
||||
|
||||
/** 编辑房间 */
|
||||
const handleEditRoom = (row: any) => {
|
||||
roomDialog.title = '编辑房间';
|
||||
roomDialog.roomId = row.id;
|
||||
roomDialog.floorNum = row.floorNum;
|
||||
roomDialog.buildingId = row.buildingId;
|
||||
roomDialog.room = { ...row };
|
||||
roomDialog.visible = true;
|
||||
};
|
||||
|
||||
/** 删除房间 */
|
||||
const handleDeleteRoom = (row: any) => {
|
||||
proxy.$modal
|
||||
.confirm(`确定删除房间 ${row.roomName} 吗?`, '警告', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
})
|
||||
.then(async () => {
|
||||
try {
|
||||
await delDormRoom(row.id);
|
||||
proxy.$modal.msgSuccess('删除成功');
|
||||
loadRoomData(); // 刷新数据
|
||||
} catch (error) {
|
||||
console.error('删除房间失败', error);
|
||||
}
|
||||
})
|
||||
.catch(() => {});
|
||||
};
|
||||
|
||||
/** 房间操作成功回调 */
|
||||
const handleRoomSuccess = () => {
|
||||
loadRoomData();
|
||||
};
|
||||
|
||||
/** 添加床位 */
|
||||
const handleAddBed = (row: any) => {
|
||||
bedDialog.title = '添加床位';
|
||||
bedDialog.bedId = undefined;
|
||||
bedDialog.roomId = row.roomId;
|
||||
bedDialog.visible = true;
|
||||
};
|
||||
|
||||
/** 编辑床位 */
|
||||
const handleEditBed = (row: any) => {
|
||||
bedDialog.title = '编辑床位';
|
||||
bedDialog.bedId = row.id;
|
||||
bedDialog.roomId = row.roomId;
|
||||
bedDialog.visible = true;
|
||||
};
|
||||
|
||||
/** 删除床位 */
|
||||
const handleDeleteBed = (row: any) => {
|
||||
proxy.$modal
|
||||
.confirm(`确定删除床位 ${row.bedName} 吗?`, '警告', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
})
|
||||
.then(async () => {
|
||||
try {
|
||||
await delDormBed(row.id);
|
||||
proxy.$modal.msgSuccess('删除成功');
|
||||
loadRoomData(); // 刷新数据
|
||||
} catch (error) {
|
||||
console.error('删除床位失败', error);
|
||||
}
|
||||
})
|
||||
.catch(() => {});
|
||||
};
|
||||
|
||||
/** 床位操作成功回调 */
|
||||
const handleBedSuccess = () => {
|
||||
loadRoomData();
|
||||
};
|
||||
|
||||
/** 处理行的展开/收起 */
|
||||
const handleExpandChange = (row: any, expanded: boolean) => {
|
||||
const rowId = String(row.roomId);
|
||||
if (expanded) {
|
||||
// 添加到已展开行数组
|
||||
expandedRowKeys.value.push(rowId);
|
||||
} else {
|
||||
// 从已展开行数组中移除
|
||||
const index = expandedRowKeys.value.findIndex((key) => key === rowId);
|
||||
if (index !== -1) {
|
||||
expandedRowKeys.value.splice(index, 1);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/** 检查行是否可选中(只有正常状态的房间和空闲状态的床位可选) */
|
||||
const checkSelectable = (row: any) => {
|
||||
if (row.isBed) {
|
||||
// 床位:只有空闲状态(0)可选
|
||||
return row.bedStatus === '0';
|
||||
} else {
|
||||
// 房间:只有正常状态(0)可选
|
||||
return row.roomStatus === '0';
|
||||
}
|
||||
};
|
||||
|
||||
/** 处理选择变更 */
|
||||
const handleSelectionChange = (rows: any[]) => {
|
||||
// 更新选中行数组
|
||||
selectedRows.value = rows;
|
||||
|
||||
// 计算选中的房间和床位数量
|
||||
const rooms = rows.filter((row) => !row.isBed);
|
||||
const beds = rows.filter((row) => row.isBed);
|
||||
|
||||
selectedRoomCount.value = rooms.length;
|
||||
selectedBedCount.value = beds.length;
|
||||
};
|
||||
|
||||
/** 当选择房间时,自动选择其下所有空闲床位 */
|
||||
const toggleRoomSelection = async (room: any, isSelected: boolean) => {
|
||||
if (!room || !room.children || room.children.length === 0) return;
|
||||
|
||||
// 获取该房间下所有空闲状态的床位
|
||||
const availableBeds = room.children.filter((bed: any) => bed.bedStatus === '0');
|
||||
|
||||
// 根据房间选择状态,选中或取消选中所有空闲床位
|
||||
availableBeds.forEach((bed: any) => {
|
||||
tableRef.value?.toggleRowSelection(bed, isSelected);
|
||||
});
|
||||
};
|
||||
|
||||
// 监听房间选择变化
|
||||
watch(
|
||||
selectedRows,
|
||||
(newRows, oldRows) => {
|
||||
// 找出新增的房间和移除的房间
|
||||
const oldRooms = oldRows.filter((row) => !row.isBed);
|
||||
const newRooms = newRows.filter((row) => !row.isBed);
|
||||
|
||||
// 找出新增选中的房间
|
||||
const addedRooms = newRooms.filter((newRoom) => !oldRooms.some((oldRoom) => oldRoom.id === newRoom.id));
|
||||
|
||||
// 找出取消选中的房间
|
||||
const removedRooms = oldRooms.filter((oldRoom) => !newRooms.some((newRoom) => newRoom.id === oldRoom.id));
|
||||
|
||||
// 为新增选中的房间选中所有空闲床位
|
||||
addedRooms.forEach((room) => {
|
||||
toggleRoomSelection(room, true);
|
||||
});
|
||||
|
||||
// 为取消选中的房间取消选中所有床位
|
||||
removedRooms.forEach((room) => {
|
||||
toggleRoomSelection(room, false);
|
||||
});
|
||||
},
|
||||
{ deep: true }
|
||||
);
|
||||
|
||||
// 组件挂载时获取宿舍树数据
|
||||
onMounted(() => {
|
||||
getDormTreeData();
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.flex-layout {
|
||||
display: flex;
|
||||
gap: 16px;
|
||||
}
|
||||
|
||||
.tree-sidebar {
|
||||
width: 300px;
|
||||
flex-shrink: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.tree-card {
|
||||
flex: 1;
|
||||
max-height: calc(50vh - 24px);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.tree-card :deep(.el-card__body) {
|
||||
flex: 1;
|
||||
overflow-y: auto;
|
||||
overflow-x: auto; /* 添加横向滚动 */
|
||||
padding-top: 10px;
|
||||
}
|
||||
|
||||
.content-area {
|
||||
flex-grow: 1;
|
||||
overflow: hidden; /* 防止溢出 */
|
||||
}
|
||||
|
||||
.room-container {
|
||||
margin-top: 16px;
|
||||
}
|
||||
|
||||
.empty-tip {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
/* 添加表格横向滚动样式 */
|
||||
.el-card :deep(.el-table) {
|
||||
width: 100%;
|
||||
overflow-x: auto;
|
||||
}
|
||||
|
||||
.el-card :deep(.el-table__body-wrapper),
|
||||
.el-card :deep(.el-table__header-wrapper) {
|
||||
overflow-x: auto !important;
|
||||
}
|
||||
|
||||
.el-card :deep(.el-table__body),
|
||||
.el-card :deep(.el-table__header) {
|
||||
min-width: 100%;
|
||||
}
|
||||
|
||||
/* 学生树自定义样式 */
|
||||
.card-header-title {
|
||||
font-weight: bold;
|
||||
margin-bottom: 10px;
|
||||
font-size: 16px;
|
||||
color: var(--el-color-primary);
|
||||
}
|
||||
|
||||
.custom-tree-node {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
width: 100%;
|
||||
align-items: center;
|
||||
min-width: max-content; /* 确保内容不被压缩 */
|
||||
}
|
||||
|
||||
.bed-count {
|
||||
font-size: 12px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
/* 学生树横向和纵向滚动样式 - 修复版 */
|
||||
.tree-card.mt-4 {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
/* 学生树卡片内容区域的滚动行为 - 使用嵌套滚动容器解决滚动条问题 */
|
||||
.tree-card.mt-4 :deep(.el-card__body) {
|
||||
position: relative;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding: 10px !important;
|
||||
max-height: calc(50vh - 24px); /* 设置最大高度 */
|
||||
overflow: hidden; /* 避免双重滚动条 */
|
||||
}
|
||||
|
||||
/* 创建一个包装容器进行纵向滚动 */
|
||||
.tree-card.mt-4 :deep(.el-input) {
|
||||
flex-shrink: 0; /* 防止搜索框被压缩 */
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
/* 添加自定义滚动容器 */
|
||||
.tree-card.mt-4 :deep(.el-tree) {
|
||||
overflow-y: auto; /* 纵向滚动 */
|
||||
overflow-x: auto; /* 横向滚动 */
|
||||
max-width: 100%; /* 确保不超出父容器 */
|
||||
min-width: 100%; /* 确保至少占满容器宽度 */
|
||||
padding-bottom: 10px; /* 为横向滚动条留出空间 */
|
||||
display: inline-block; /* 使容器能够根据内容扩展 */
|
||||
width: max-content; /* 允许根据内容扩展宽度 */
|
||||
}
|
||||
|
||||
/* 确保学生树节点内容完整显示 */
|
||||
.tree-card.mt-4 :deep(.el-tree-node) {
|
||||
min-width: max-content;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.tree-card.mt-4 :deep(.el-tree-node__content) {
|
||||
min-width: max-content;
|
||||
width: auto !important;
|
||||
}
|
||||
|
||||
.disabled-node {
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
.male-building {
|
||||
color: var(--el-color-primary);
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.female-building {
|
||||
color: #ff69b4; /* 粉色 */
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
/* 宿舍树横向和纵向滚动样式 - 修复版 */
|
||||
.tree-card:first-child {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
/* 宿舍树卡片内容区域的滚动行为 - 使用嵌套滚动容器解决滚动条问题 */
|
||||
.tree-card:first-child :deep(.el-card__body) {
|
||||
position: relative;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding: 10px !important;
|
||||
max-height: calc(50vh - 24px); /* 设置最大高度 */
|
||||
overflow: hidden; /* 避免双重滚动条 */
|
||||
}
|
||||
|
||||
/* 创建一个包装容器进行纵向滚动 */
|
||||
.tree-card:first-child :deep(.el-input) {
|
||||
flex-shrink: 0; /* 防止搜索框被压缩 */
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
/* 添加自定义滚动容器 */
|
||||
.tree-card:first-child :deep(.el-tree) {
|
||||
overflow-y: auto; /* 纵向滚动 */
|
||||
overflow-x: auto; /* 横向滚动 */
|
||||
max-width: 100%; /* 确保不超出父容器 */
|
||||
min-width: 100%; /* 确保至少占满容器宽度 */
|
||||
padding-bottom: 10px; /* 为横向滚动条留出空间 */
|
||||
display: inline-block; /* 使容器能够根据内容扩展 */
|
||||
width: max-content; /* 允许根据内容扩展宽度 */
|
||||
}
|
||||
|
||||
/* 确保宿舍树节点内容完整显示 */
|
||||
.tree-card:first-child :deep(.el-tree-node) {
|
||||
min-width: max-content;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.tree-card:first-child :deep(.el-tree-node__content) {
|
||||
min-width: max-content;
|
||||
width: auto !important;
|
||||
}
|
||||
</style>
|
||||
Reference in new issue
Block a user