# Vue 2 + Element UI → Vue 3 + Element Plus 迁移规则

适用于 `pc-v3/src/` 下的 `.vue` 文件。逐文件应用以下机械转换。

## 1. 模板（template）转换

### 1.1 组件改名
- `<el-submenu>` → `<el-sub-menu>`（开闭标签都要改）

### 1.2 `.sync` 修饰符
- `:visible.sync="x"` → `v-model="x"`
- `:any-prop.sync="x"` → `v-model:any-prop="x"`

### 1.3 `.native` 修饰符（Vue 3 已移除）
- `@click.native` → `@click`
- `@keyup.enter.native` → `@keyup.enter`
- `@submit.native.prevent` → `@submit.prevent`
- 其它一切 `.native` 全部删除该修饰符

### 1.4 slot 语法
- `slot-scope="scope"` → 改成 `<template #default="scope">` 包装（如果原本已在 `<template>` 上则直接换属性）
- 子元素上的 `slot="header"` → 抽出来包成 `<template #header>...</template>`
- 子元素上的 `slot="reference"` → 包成 `<template #reference>...</template>`
- 子元素上的 `slot="dropdown"` → 包成 `<template #dropdown>...</template>`
- 子元素上的 `slot="prefix"` / `slot="suffix"` / `slot="append"` / `slot="prepend"` → 同上

举例：
```vue
<!-- 旧 -->
<el-popover ...>
  <div>内容</div>
  <el-button slot="reference">触发</el-button>
</el-popover>

<!-- 新 -->
<el-popover ...>
  <div>内容</div>
  <template #reference>
    <el-button>触发</el-button>
  </template>
</el-popover>
```

```vue
<!-- 旧 -->
<el-table-column>
  <template slot-scope="scope">
    <span>{{ scope.row.name }}</span>
  </template>
</el-table-column>

<!-- 新 -->
<el-table-column>
  <template #default="scope">
    <span>{{ scope.row.name }}</span>
  </template>
</el-table-column>
```

### 1.5 尺寸 size
- `size="mini"` → `size="small"`
- `size="medium"` → 删除该属性（用默认）

### 1.6 图标（核心规则！）

主入口 `main.js` 已经把 `@element-plus/icons-vue` 的所有图标**全局注册**，所以模板里直接用组件名即可，**不需要在每个文件 import**。

#### 1.6.1 `<i class="el-icon-xxx"></i>` → `<el-icon><Xxx /></el-icon>`

按下表对应替换。原 `<i>` 标签上的 class（除 el-icon-xxx 外的）、`@click`、`style` 等属性，全部搬到 `<el-icon>` 上：

| 旧 class | 新组件名 |
|---|---|
| el-icon-monitor | Monitor |
| el-icon-setting | Setting |
| el-icon-s-tools | Tools |
| el-icon-s-fold | Fold |
| el-icon-s-unfold | Expand |
| el-icon-arrow-down | ArrowDown |
| el-icon-arrow-left | ArrowLeft |
| el-icon-arrow-right | ArrowRight |
| el-icon-user | User |
| el-icon-user-solid | UserFilled |
| el-icon-lock | Lock |
| el-icon-plus | Plus |
| el-icon-edit | Edit |
| el-icon-edit-outline | EditPen |
| el-icon-delete | Delete |
| el-icon-view | View |
| el-icon-check | Check |
| el-icon-close | Close |
| el-icon-circle-close | CircleClose |
| el-icon-circle-plus-outline | CirclePlus |
| el-icon-bank-card | CreditCard |
| el-icon-goods | Goods |
| el-icon-collection-tag | CollectionTag |
| el-icon-copy-document | CopyDocument |
| el-icon-data-board | DataBoard |
| el-icon-document | Document |
| el-icon-document-copy | DocumentCopy |
| el-icon-download | Download |
| el-icon-files | Files |
| el-icon-finished | Finished |
| el-icon-folder-opened | FolderOpened |
| el-icon-info | InfoFilled |
| el-icon-link | Link |
| el-icon-message | Message |
| el-icon-more | More |
| el-icon-notebook-2 | Notebook |
| el-icon-picture | Picture |
| el-icon-picture-outline | PictureRounded |
| el-icon-postcard | Postcard |
| el-icon-present | Present |
| el-icon-question | QuestionFilled |
| el-icon-s-data | DataAnalysis |
| el-icon-s-finance | Money |
| el-icon-s-grid | Grid |
| el-icon-s-order | List |
| el-icon-set-up | SetUp |
| el-icon-sort | Sort |
| el-icon-thumb | Pointer |
| el-icon-upload | Upload |
| el-icon-video-play | VideoPlay |

举例：
```vue
<!-- 旧 -->
<i class="el-icon-plus"></i>
<i class="el-icon-edit" style="color:red" @click="x"></i>

<!-- 新 -->
<el-icon><Plus /></el-icon>
<el-icon style="color:red" @click="x"><Edit /></el-icon>
```

#### 1.6.2 组件属性形式 `icon="el-icon-xxx"` / `prefix-icon="el-icon-xxx"`

用 `#prefix`/`#suffix` 等 slot 替代（保持模板内一致，不需要 import）：

```vue
<!-- 旧 -->
<el-button type="primary" icon="el-icon-plus">添加</el-button>
<el-input prefix-icon="el-icon-user" v-model="x" />

<!-- 新 -->
<el-button type="primary">
  <el-icon><Plus /></el-icon>添加
</el-button>
<el-input v-model="x">
  <template #prefix><el-icon><User /></el-icon></template>
</el-input>
```

对于 `<el-button type="text" icon="el-icon-more">`（按钮内只有图标，无文字）也按上面处理：
```vue
<el-button type="text">
  <el-icon><More /></el-icon>
</el-button>
```

### 1.7 el-button text 类型
- `type="text"` 在 Element Plus 仍然支持但已 deprecated，**保持不变**（不要主动改成 link，免得动到样式）

## 2. script 部分转换

### 2.1 全局消息
- `this.$message(...)` 或 `this.$message.success/info/warning/error(...)`
- → 顶部加 `import { ElMessage } from 'element-plus'`，调用 `ElMessage(...)` / `ElMessage.success(...)`

- `this.$confirm(...)` → `ElMessageBox.confirm(...)`
- `this.$alert(...)` → `ElMessageBox.alert(...)`
- `this.$prompt(...)` → `ElMessageBox.prompt(...)`
- → 顶部加 `import { ElMessageBox } from 'element-plus'`

如果同一个文件同时用到 message + messagebox，合并成一个 import：
```js
import { ElMessage, ElMessageBox } from 'element-plus'
```

### 2.2 ref 名称
- 如果 `ref="form"` 且 script 里 `this.$refs.form.validate(...)`，建议保留原 ref 名以减少 diff（无需统一改名为 formRef）

### 2.3 Popover doClose
- `this.$refs.xxx.doClose()` → `this.$refs.xxx.hide()`（Element Plus ElPopover 暴露 hide 方法）
- 如果是数组 ref（`:ref="`pop-${i}`"`），`Array.isArray(ref) ? ref[0] : ref` 写法保留，只把末尾 `.doClose()` 换成 `.hide()`

### 2.4 emit 声明
- Vue 3 推荐在组件里声明 emits，但**为了减少改动，本次不强制要求加**，子组件用 `this.$emit('update:visible', false)` 之类继续工作

### 2.5 富文本（vue-quill-editor → @vueup/vue-quill）
- 移除 `import { quillEditor } from 'vue-quill-editor'`，移除 `components: { quillEditor }`
- 模板里 `<quill-editor v-model="x" :options="..." />` → `<quill-editor v-model:content="x" content-type="html" :options="quillOptions" />`
- `QuillEditor` 已在 `main.js` 全局注册（kebab-case：`<quill-editor>`），不必逐文件 import

## 3. 其它

- 顶部 `import` 的 `'element-ui'` 全部替换成 `'element-plus'`
- `'element-ui/lib/...'` 之类的 CSS / 子模块 import 全部删除（main.js 统一处理了）
- `slot=` 在 template 标签上的写法（如 `<template slot="header">`）改成 `<template #header>`
- 文件中可能存在 `Vue.set` / `Vue.delete` —— 模板里不会有，script 里如有出现，改成直接赋值 / `delete obj.key`

## 4. 验证

迁移完成后，对每个文件用以下 grep 自查（应该全部为空）：

```bash
grep -E '\.sync=|\.native|<el-submenu|</el-submenu|slot=|slot-scope|el-icon-|this\.\$message|this\.\$confirm|this\.\$alert|this\.\$prompt|element-ui|vue-quill-editor|Vue\.set|Vue\.delete|size="mini"|size="medium"|\.doClose\(' <file>
```
