# 空间批量操作问题修复规格说明书

**文档版本**: v1.0  
**创建日期**: 2026-02-23  
**文档类型**: Bug修复规格说明书

---

## 一、问题描述

用户报告了8个问题，需要逐一分析和修复：

### 问题列表

| 序号 | 问题描述 | 状态 |
|------|---------|------|
| 1 | 批量操作点进去的生成类型不用显示了，隐藏即可 | ✅ 已隐藏 |
| 2 | 批量生成房间保存，提示失败 | ⚠️ 需排查 |
| 3 | 批量生成车位后缀应为空 | ✅ 已设置 |
| 4 | 批量生成车位设置的3位数序号，但生成的是1位数，且自动带上了后缀号车位 | ⚠️ 需排查 |
| 5 | 批量操作不再限定必须选中楼栋或车位才能添加对应批量信息 | ⚠️ 需修改 |
| 6 | 停车区域的子项里显示的车位列表设置成支持分页，每页20个 | ✅ 已支持 |
| 7 | 新增的批量楼栋依然没有生成地址 | ⚠️ 需修改 |
| 8 | 项目查看详情，统计数据里，显示总户数8户，但是我增加了12户。面积为空 | ⚠️ 需排查 |

---

## 二、问题分析

### 2.1 问题1：生成类型隐藏

**文件**: `ether-ui-admin/src/views/mdm/project/components/BatchGenerateModal.vue`

**当前状态**: 第21行已使用 `v-show="false"` 隐藏

```vue
<a-form-item label="生成类型" name="generateType" v-show="false">
```

**结论**: ✅ 已正确隐藏，无需修改

---

### 2.2 问题2：批量生成房间保存失败

**相关文件**:
- 前端: `BatchGenerateModal.vue` 第451-477行
- 后端: `SpaceNodeServiceImpl.java` 第932-994行

**前端代码分析**:
```typescript
const generateRooms = async () => {
  if (!formState.value.buildingIds || formState.value.buildingIds.length === 0) {
    throw new Error("请选择所属楼栋");
  }
  // ... 调用 API
};
```

**后端代码分析**:
```java
public List<SpaceNodeResponse> batchGenerateRooms(BatchGenerateRoomsRequest request) {
    // 检查楼栋是否存在
    SpaceNode building = spaceNodeRepository.findById(buildingId)
            .orElseThrow(() -> new BusinessException("楼栋不存在: " + buildingId));
    // ...
}
```

**可能原因**:
1. 前端传递的 `buildingIds` 可能是空数组
2. 后端 `findById` 可能找不到楼栋（项目隔离问题）
3. 编码冲突导致失败

**需要检查**:
- API 路径是否正确
- 项目上下文是否正确传递
- 后端日志输出

---

### 2.3 问题3：车位后缀应为空

**前端代码**: `BatchGenerateModal.vue` 第490行

```typescript
await spaceNodeApi.batchGenerateParkingSpaces({
  // ...
  suffix: "",  // ✅ 已设置为空字符串
});
```

**结论**: ✅ 已正确设置，无需修改

---

### 2.4 问题4：车位序号位数和名称问题

**后端代码**: `SpaceNodeServiceImpl.java` 第1057-1070行

```java
int digitCount = request.getDigitCount() != null ? request.getDigitCount() : 3;

for (int i = 0; i < request.getCount(); i++) {
    int number = request.getStartNumber() + i;
    String code = (request.getPrefix() != null ? request.getPrefix() : "") 
            + String.format("%0" + digitCount + "d", number);  // ✅ 正确使用位数
    
    // ...
    parkingSpace.setName(code);  // ✅ 名称只使用编码，没有添加"车位"后缀
}
```

**前端代码**: `BatchGenerateModal.vue` 第369-385行

```typescript
const generateParkingCodePreview = () => {
  const { codePrefix, digitCount, startNumber, parkingCount } = formState.value;
  // ...
  const code = `${codePrefix}${String(num).padStart(digitCount, '0')}`;  // ✅ 正确使用位数
};
```

**结论**: 后端代码逻辑正确。需要检查：
1. 前端是否正确传递 `digitCount` 参数
2. 后端是否正确接收 `digitCount` 参数

---

### 2.5 问题5：批量操作限制

**前端代码**: `SpaceManagement.vue` 第613-621行

```typescript
// 计算是否可以批量生成房间（需要选中楼栋）
const canBatchGenerateRoom = computed(() => {
  return selectedNode.value?.nodeType === SpaceNodeType.BUILDING;
});

// 计算是否可以批量生成车位（需要选中停车区域）
const canBatchGenerateParking = computed(() => {
  return selectedNode.value?.nodeType === SpaceNodeType.GARAGE || 
         selectedNode.value?.nodeType === SpaceNodeType.PARKING_AREA;
});
```

**问题**: 这些计算属性已定义但未使用来限制批量生成操作

**需要修改**: 移除限制，允许直接从菜单选择批量生成类型

---

### 2.6 问题6：车位列表分页

**前端代码**: `SpaceManagement.vue` 第225-229行

```vue
<a-table
  :pagination="{
    pageSize: 20,
    showSizeChanger: false,
    showTotal: (total: number) => `共 ${total} 条`
  }"
>
```

**结论**: ✅ 已支持分页，每页20条

---

### 2.7 问题7：批量楼栋地址生成

**后端代码**: `SpaceNodeServiceImpl.java` 第902-911行

```java
if (parentNode != null) {
    building.setTreePath(parentTreePath + "." + buildingId);
    building.setLevel(baseLevel);
    String parentAddress = parentNode.getAddress() != null ? parentNode.getAddress() : parentNode.getName();
    building.setAddress(parentAddress + " " + name);
} else {
    building.setTreePath(buildingId.toString());
    building.setLevel(0);
    building.setAddress(name);  // ⚠️ 没有父节点时，地址只设置为名称
}
```

**问题**: 当没有父节点时，地址只设置为 `name`（如 "B001号楼"），而不是完整地址

**需要修改**: 应该使用项目地址作为基础地址

---

### 2.8 问题8：项目统计数据不正确

**相关文件**:
- 前端: `project/detail.vue` 第458-471行
- 后端: `ProjectServiceImpl.java`

**前端代码**:
```typescript
try {
  statistics.value = await projectApi.getProjectStatistics(projectId);
} catch {
  // 统计接口可能不存在，使用默认值
  statistics.value = {
    totalBuildings: project.value?.totalBuildings ?? 0,
    totalUnits: project.value?.totalUnits ?? 0,
    // ...
  };
}
```

**问题**: 统计数据可能来自项目表的缓存字段，而不是实时计算

**需要检查**:
1. 后端统计接口是否实时计算
2. 项目表的 `totalBuildings`, `totalUnits` 等字段是否正确更新

---

## 三、修复方案

### 3.1 问题2修复：批量生成房间

**需要检查**:
1. 确保前端正确传递项目ID
2. 确保后端使用项目上下文查询楼栋

### 3.2 问题4修复：车位序号位数

**需要验证**:
1. 前端传递的 `digitCount` 参数是否正确
2. 后端接收参数是否正确

### 3.3 问题5修复：移除批量操作限制

**修改文件**: `SpaceManagement.vue`

**修改内容**: 移除 `canBatchGenerateRoom` 和 `canBatchGenerateParking` 的限制检查

### 3.4 问题7修复：楼栋地址生成

**修改文件**: `SpaceNodeServiceImpl.java`

**修改内容**: 当没有父节点时，使用项目地址作为基础地址

### 3.5 问题8修复：项目统计数据

**需要检查**:
1. 后端统计接口实现
2. 空间节点变更时是否更新项目统计字段

---

## 四、测试验证

### 4.1 测试环境

- 前端: http://localhost:5175
- 后端: http://localhost:8080

### 4.2 测试用例

| 序号 | 测试项 | 预期结果 |
|------|--------|---------|
| 1 | 打开批量生成弹窗，确认生成类型已隐藏 | 不显示生成类型选择 |
| 2 | 批量生成房间 | 保存成功 |
| 3 | 批量生成车位，设置3位数序号 | 生成如 001, 002, 003 格式 |
| 4 | 批量生成车位，名称不带"车位"后缀 | 名称与编码一致 |
| 5 | 不选中任何节点，点击批量生成楼栋/房间/车位 | 弹窗正常打开 |
| 6 | 停车区域子项列表 | 支持分页，每页20条 |
| 7 | 批量生成楼栋，查看地址 | 地址包含项目地址 |
| 8 | 项目详情统计数据 | 显示正确的户数和面积 |

---

## 五、风险评估

| 风险项 | 影响 | 缓解措施 |
|--------|------|---------|
| 修改后端地址生成逻辑 | 可能影响现有数据 | 仅影响新生成的楼栋 |
| 移除批量操作限制 | 用户可能误操作 | 在弹窗中提示用户选择正确的父节点 |
| 统计数据修复 | 可能需要数据迁移 | 提供统计刷新接口 |

---

**下一步**: 创建任务清单并开始修复
