好 👌
下面这份 **`README.md`** 是**直接可用、偏工程文档级别**的，既能给自己看，也能给同事 / 代码评审看，一看就懂你为什么要这么拆 ✨

你可以 **原封不动保存为 `README.md`**。

---


# Device Layer Panel 组件说明文档

## 📌 背景说明

在现有设备图层面板中，原有 `LayerItem` 采用**纵向列表 + 左右结构**的展示方式。
随着业务扩展，新增了一种 **横向卡片式图层面板** 的需求：

- LayerItem **横向排列**
- 超出容器宽度后 **自动换行**
- Item 内部结构从 **左右布局 → 上下布局**
- 整体视觉更偏向「卡片 / 模块化」

由于 **布局模型与 DOM 结构差异较大**，继续通过 `props` 控制样式会显著降低可维护性，因此采用 **多组件 + 单出口** 的架构设计。

---

## 🧠 设计原则

### 1️⃣ 结构差异优先于样式复用

- 不强行在同一个组件中通过 `props` 控制完全不同的 DOM 结构
- 每种展示形态拥有独立组件，降低复杂度

### 2️⃣ API 统一，表现分离

- 对外只暴露一个 `DeviceLayerPanel`
- 内部根据 `mode` 切换不同实现
- 调用方无感知

### 3️⃣ 易扩展、易维护

- 未来新增 `grid / compact / map-overlay` 模式时
- 只需新增组件，不影响已有逻辑

---

## 📁 目录结构

```text
device-layer-panel/
├─ DeviceLayerPanel.vue        # 统一出口（模式切换）
├─ LayerPanelVertical.vue      # 纵向面板
├─ LayerPanelHorizontal.vue    # 横向面板（flex-wrap）
├─ LayerItemVertical.vue       # 纵向 item（左右结构）
├─ LayerItemHorizontal.vue     # 横向 item（上下结构）
````

---

## 🧩 核心组件说明

### DeviceLayerPanel.vue（入口组件）

**职责：**

* 接收 `layers` 数据
* 根据 `mode` 决定渲染哪种面板
* 向外统一抛出事件（如 `select`）

```vue
<DeviceLayerPanel
  mode="horizontal"
  :layers="layers"
  @select="onSelect"
/>
```

**支持的 mode：**

| mode 值       | 说明         |
| ------------ | ---------- |
| `vertical`   | 纵向列表（默认）   |
| `horizontal` | 横向卡片（自动换行） |

---

### LayerPanelVertical.vue

* 纵向列表容器
* 内部使用 `LayerItemVertical`
* 保持原有展示逻辑与交互习惯

适合：

* 图层管理
* 信息密度较高的场景

---

### LayerPanelHorizontal.vue

* `flex + flex-wrap` 布局
* 子项自动换行
* 内部使用 `LayerItemHorizontal`

适合：

* 设备选择
* 图层快速开关
* 卡片式交互场景

---

## 🎴 LayerItem 组件拆分说明

### 为什么不复用一个 LayerItem？

| 对比项     | Vertical | Horizontal |
| ------- | -------- | ---------- |
| Item 排列 | 纵向       | 横向换行       |
| 内部结构    | 左右       | 上下         |
| 视觉风格    | 列表       | 卡片         |
| DOM 结构  | 不一致      | 不一致        |

👉 **属于结构级差异，而非样式差异**

因此采用：

* `LayerItemVertical.vue`
* `LayerItemHorizontal.vue`

但两者保持：

* 相同 props 结构
* 相同业务语义
* 相同事件行为

---

## 🔄 数据结构约定

```js
{
  id: Number | String,
  name: String,      // 图层名称
  desc: String,      // 图层描述
  visible: Boolean   // 是否可见
}
```

---

## 📈 扩展建议

未来如需新增展示模式：

```text
LayerPanelGrid.vue
LayerItemGrid.vue
```

只需在 `DeviceLayerPanel.vue` 中增加分支即可：

```vue
<LayerPanelGrid v-if="mode === 'grid'" />
```

无需改动已有组件。

---

## ✅ 总结

* 本方案 **避免了 props 控制复杂布局**
* 提高了组件可读性与长期可维护性
* 结构清晰，职责单一，符合工程实践

> 当 UI 结构开始“明显分叉”时，
> **拆组件不是浪费代码，而是减少未来成本。**
