# 座位布局性能优化说明

## 问题描述

当座位布局节点数量很大时（例如 50x50 = 2500 个单元格），会出现明显的卡顿现象。主要原因是：

1. **大量 DOM 节点**：双重循环渲染所有单元格，创建大量 DOM 元素
2. **重复计算**：每次渲染时，`getCellClass`、`getCellText`、`shouldRenderCell` 等函数都会被调用，且内部包含循环遍历
3. **查找性能**：使用 `Array.find()` 查找单元格，时间复杂度为 O(n)
4. **事件处理**：鼠标移动事件触发频繁，没有有效节流

## 优化方案

### 1. 使用 Map 缓存单元格查找

**优化前：**
```typescript
const getCell = (col: number, row: number) => {
  return cells.value.find((c) => c.col === col && c.row === row);
};
```

**优化后：**
```typescript
// 单元格查找缓存 Map: key = "col,row", value = cell
const cellMapCache = ref<Map<string, ClassroomApi.ClassroomLayoutCell>>(new Map());

const getCell = (col: number, row: number) => {
  const key = `${col},${row}`;
  return cellMapCache.value.get(key);
};
```

**效果：** 查找时间复杂度从 O(n) 降低到 O(1)

### 2. 缓存合并单元格映射关系

**优化前：**
```typescript
// 每次都要遍历所有单元格检查是否被合并
for (const otherCell of cells.value) {
  // ... 检查逻辑
}
```

**优化后：**
```typescript
// 合并单元格主单元格映射: key = "col,row" (被合并的单元格), value = "col,row" (主单元格)
const mergeMasterMapCache = ref<Map<string, string>>(new Map());

// 使用缓存检查
const key = `${col},${row}`;
if (mergeMasterMapCache.value.has(key)) {
  return 'cell cell-merged';
}
```

**效果：** 避免了每次渲染时的 O(n²) 循环嵌套

### 3. 使用 shallowRef 优化响应式性能

**优化前：**
```typescript
const cells = ref<ClassroomApi.ClassroomLayoutCell[]>([]);
```

**优化后：**
```typescript
const cells = shallowRef<ClassroomApi.ClassroomLayoutCell[]>([]);
```

**效果：** 减少深度响应式监听，提升性能

### 4. 使用 requestAnimationFrame 优化鼠标移动事件

**优化前：**
```typescript
mouseEnterTimer = window.setTimeout(() => {
  // 填充逻辑
}, 16);
```

**优化后：**
```typescript
rafId = requestAnimationFrame(() => {
  // 填充逻辑
});
```

**效果：** 与浏览器渲染周期同步，更流畅

### 5. 使用 v-memo 指令缓存单元格渲染

**优化后：**
```vue
<div
  v-if="shouldRenderCell(col - 1, row - 1)"
  v-memo="[getCell(col - 1, row - 1)?.type, getCell(col - 1, row - 1)?.status, ...]"
  :class="getCellClass(col - 1, row - 1)"
  ...
>
```

**效果：** 只有当依赖项变化时才重新渲染，减少不必要的 DOM 更新

### 6. 统一更新缓存机制

在所有修改单元格的操作后，统一调用 `updateCellMapCache()` 更新缓存：

- `initLayout()` - 初始化布局
- `loadLayout()` - 加载布局
- `addColumnLeft/Right()` - 添加列
- `addRowTop/Bottom()` - 添加行
- `mergeCells()` - 合并单元格
- `unmergeCell()` - 取消合并
- `handleUndo()` - 撤销操作
- `handleCellMouseUp()` - 鼠标释放

## 性能提升

经过优化后，预期性能提升：

1. **单元格查找**：从 O(n) 降低到 O(1)，查找速度提升 100-1000 倍（取决于单元格数量）
2. **合并检查**：从 O(n²) 降低到 O(1)，检查速度提升 10000 倍以上
3. **渲染性能**：使用 v-memo 后，只有变化的单元格才会重新渲染
4. **鼠标交互**：使用 requestAnimationFrame 后，交互更流畅，帧率更稳定

## 注意事项

1. **缓存一致性**：所有修改单元格的操作都必须调用 `updateCellMapCache()` 保持缓存同步
2. **内存占用**：Map 缓存会占用额外内存，但对于性能提升是值得的
3. **兼容性**：`v-memo` 是 Vue 3.2+ 的特性，确保项目使用 Vue 3.2 或更高版本

## 后续优化建议

如果性能仍然不够理想，可以考虑：

1. **虚拟滚动**：只渲染可见区域的单元格（对 Grid 布局实现较复杂）
2. **Canvas 渲染**：使用 Canvas 替代 DOM 渲染（需要重写交互逻辑）
3. **Web Worker**：将复杂计算移到 Web Worker 中
4. **分块渲染**：将大布局分成多个块，按需加载

