Files
my-mom-system/.cursor/plans/mom-ui_tech_stack_migration_ddb51afc.plan.md

447 lines
19 KiB
Markdown
Raw Permalink Normal View History

2026-03-06 02:02:59 +08:00
---
name: MOM-UI Tech Stack Migration
overview: 将 mom-backend-ui 从 Vue CLI + Vue 2 + Element UI 渐进式升级到 Vite + Vue 3 + Element Plus与 erp-frontend-vue 技术栈保持一致,方便后续合并。
todos:
- id: phase1-vite-setup
content: "Phase 1: 创建 vite.config.js移动 index.html 到根目录,更新 package.json scripts安装 Vite + Vue 3 + @vue/compat 依赖,移除 Vue CLI/Webpack 依赖"
status: completed
- id: phase2-core-modules
content: "Phase 2: 更新 main.js (createApp),升级 Vue Router 4升级 Vuex 4替换 SVG 图标系统 (vite-plugin-svg-icons),修改 permission.js"
status: completed
- id: phase3a-element-plus-deps
content: "Phase 3a: 替换 Element Plus 依赖 + 更新 main.js 导入 + 迁移公共组件 (31 个 dialog 组件) + 迁移采购入库页面 (4 个 Vue 文件) 作为验证试点"
status: in_progress
- id: phase3a-2-layout-components
content: "Phase 3a-2: 迁移 src/layout/ + src/components/ 中非 dialog 组件 (~38 个 Vue 文件),确保公共组件完全脱离 Element UI"
status: completed
- id: phase3b-wm-module
content: "Phase 3b: 迁移仓库管理模块其余页面 (wm, 64 个 Vue 文件),验证整个模块功能正常"
status: pending
- id: phase3c-remaining-pages
content: "Phase 3c: 迁移其余所有页面 (MES 其他 98 + system 19 + monitor 8 + tool 12 + print 6 + 其他 5 = ~148 个 Vue 文件) + 全局样式修正"
status: pending
- id: phase4-third-party
content: "Phase 4: 更新第三方依赖为 Vue 3 兼容版本 (vuedraggable, vue-cropper, echarts, quill, axios 等)"
status: completed
- id: phase5-cleanup
content: "Phase 5: 删除旧配置文件,迁移环境变量 (VUE_APP_ -> VITE_),移除 @vue/compat,最终清理"
status: pending
isProject: false
---
# mom-backend-ui 技术栈升级计划
## 当前差异对比
| 维度 | mom-backend-ui (当前) | erp-frontend-vue (目标) |
| ------ | ----------------------------------- | -------------------------------- |
| 构建工具 | Vue CLI 4 (Webpack) | Vite 7 |
| 框架 | Vue 2.6 | Vue 3.5 |
| UI 库 | Element UI 2.15 | Element Plus 2.x |
| 路由 | Vue Router 3.4 | Vue Router 4.6 |
| 状态管理 | Vuex 3.6 | 自定义 reactive store |
| 语言 | JavaScript | TypeScript (暂保留 JS) |
| 组件风格 | Options API | Composition API `<script setup>` |
| SVG 图标 | svg-sprite-loader + require.context | @element-plus/icons-vue |
## 核心挑战
项目有 **305 个 Vue 文件 + 225 个 JS 文件**,无法一步到位。采用 **Vue 3 兼容模式 (`@vue/compat`)** 进行渐进式迁移,确保大部分 Vue 2 代码可以在 Vue 3 下运行,然后逐步修复。
---
## Phase 1: Vite 构建工具替换 + Vue 3 兼容模式
### 1.1 创建 Vite 配置
在 [mom-backend-ui/](mom-backend-ui/) 根目录创建 `vite.config.js`,参考 [erp-frontend-vue/vite.config.ts](erp-frontend-vue/vite.config.ts) 的结构:
```javascript
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import path from 'path'
import { createSvgIconsPlugin } from 'vite-plugin-svg-icons'
export default defineConfig({
plugins: [
vue(),
createSvgIconsPlugin({
iconDirs: [path.resolve(__dirname, 'src/assets/icons/svg')],
symbolId: 'icon-[name]'
})
],
resolve: {
alias: { '@': path.resolve(__dirname, './src') },
// Vue 3 compat mode
dedupe: ['vue']
},
server: {
port: 80,
proxy: {
'/dev-api': {
target: 'http://localhost:8080',
changeOrigin: true,
rewrite: (path) => path.replace(/^\/dev-api/, '')
},
'/ureport': {
target: 'http://localhost:8080',
changeOrigin: true
}
}
},
css: {
preprocessorOptions: {
scss: { api: 'modern-compiler' }
}
}
})
```
### 1.2 移动并更新 index.html
将 [mom-backend-ui/public/index.html](mom-backend-ui/public/index.html) 移到项目根目录,移除 Webpack 模板语法:
- `<%= BASE_URL %>` 改为 `/`
- `<%= webpackConfig.name %>` 改为固定标题
- 添加 `<script type="module" src="/src/main.js"></script>`
### 1.3 更新 package.json
- 添加 `"type": "module"`
- 更新 scripts
- `"dev": "vite"`
- `"build": "vite build"`
- `"preview": "vite preview"`
### 1.4 安装新依赖,移除旧依赖
**安装:**
- `vue@^3.5` + `@vue/compat@^3.5`(兼容模式)
- `vite` + `@vitejs/plugin-vue`
- `vite-plugin-svg-icons` + `fast-glob`(替代 svg-sprite-loader
- `sass-embedded`(替代 sass + sass-loader
**移除:**
- `@vue/cli-service`, `@vue/cli-plugin-babel`, `@vue/cli-plugin-eslint`
- `vue-template-compiler`
- `webpack` 相关: `compression-webpack-plugin`, `script-ext-html-webpack-plugin`, `svg-sprite-loader`, `sass-loader`, `less-loader`
- `babel-eslint`, `babel-plugin-dynamic-import-node`, `cross-env`
- `core-js`
### 1.5 配置 @vue/compat
`vite.config.js` 中配置别名,让 `vue` 指向兼容构建:
```javascript
resolve: {
alias: {
'@': path.resolve(__dirname, './src'),
'vue': '@vue/compat'
}
}
```
同时需要配置 `@vitejs/plugin-vue` 的 compat 编译器选项:
```javascript
vue({
template: {
compilerOptions: {
compatConfig: { MODE: 2 }
}
}
})
```
---
## Phase 2: 更新入口文件和核心模块
### 2.1 更新 main.js
将 [mom-backend-ui/src/main.js](mom-backend-ui/src/main.js) 从 `new Vue()` 改为 `createApp()`
- `import { createApp } from 'vue'` 替代 `import Vue from 'vue'`
- `const app = createApp(App)` 替代 `new Vue({...})`
- `Vue.prototype.xxx` 改为 `app.config.globalProperties.xxx`
- `Vue.component(...)` 改为 `app.component(...)`
- `Vue.use(...)` 改为 `app.use(...)`
- `app.use(store).use(router).mount('#app')`
### 2.2 更新 SVG 图标系统
将 [mom-backend-ui/src/assets/icons/index.js](mom-backend-ui/src/assets/icons/index.js) 中的 `require.context` 替换为 Vite 的 `import.meta.glob`
```javascript
import 'virtual:svg-icons-register'
// SvgIcon 组件需要在 main.js 中用 app.component 注册
```
### 2.3 升级 Vue Router 3 -> 4
修改 [mom-backend-ui/src/router/index.js](mom-backend-ui/src/router/index.js)
- `import { createRouter, createWebHistory } from 'vue-router'`
- `new Router({mode: 'history', ...})` 改为 `createRouter({ history: createWebHistory(), ... })`
- 移除 `Vue.use(Router)`
- `scrollBehavior: () => ({ y: 0 })` 改为 `scrollBehavior: () => ({ top: 0 })`
修改 [mom-backend-ui/src/permission.js](mom-backend-ui/src/permission.js)
- `router.addRoutes(accessRoutes)` 改为循环调用 `router.addRoute(route)`
- `Message` 从 Element Plus 导入
### 2.4 升级 Vuex 3 -> 4
修改 [mom-backend-ui/src/store/index.js](mom-backend-ui/src/store/index.js)
- `import { createStore } from 'vuex'`
- `new Vuex.Store({...})` 改为 `createStore({...})`
- 移除 `Vue.use(Vuex)`
- 各 modules 文件暂时不动Vuex 4 向后兼容 module 写法)
---
## Phase 3: Element UI -> Element Plus 迁移(分步进行)
这是工作量最大的部分,影响所有 306 个 Vue 文件。为保证项目平稳升级,拆分为 **3a → 3b → 3c** 三步,先拿采购入库页面做试点验证,确认方案可行后再逐步扩展到全模块。
### Element UI -> Element Plus 通用变更清单
以下变更适用于所有步骤,每步迁移页面时需逐项检查:
- **size 属性**: `size="mini"` -> `size="small"`, `size="medium"` -> `size="default"`
- **图标**: `<i class="el-icon-xxx">` -> `<el-icon><Xxx /></el-icon>` 或对应 Element Plus 图标组件
- **v-model 变更**: `.sync` 修饰符移除,改用 `v-model:propName`
- `:visible.sync` -> `v-model`Dialog
- `:current-page.sync` -> `v-model:current-page`Pagination
- `:page-size.sync` -> `v-model:page-size`Pagination
- **事件名变更**: `@current-change` 等部分组件事件保持不变;`.native` 修饰符移除
- **Slot 变更**: 部分具名插槽名称变化
- **移除的属性**: `el-button``type="text"` 改为 `link``text` 属性
- **DatePicker**: `value-format` 格式字符串变更 (如 `yyyy-MM-dd` -> `YYYY-MM-DD`)
---
### Phase 3a: 替换依赖 + 迁移公共组件 + 采购入库页面试点
**目标**: 完成 Element Plus 基础切换,优先迁移 `src/components` 中的公共组件(避免页面迁移时遇到依赖问题),再以采购入库页面(`itemrecpt`)作为验证试点。
#### 3a.1 替换依赖
- 卸载 `element-ui`
- 安装 `element-plus` + `@element-plus/icons-vue`
- 删除 [mom-backend-ui/src/assets/styles/element-variables.scss](mom-backend-ui/src/assets/styles/element-variables.scss),改用 Element Plus 主题配置
#### 3a.2 更新 main.js 中的 Element 导入
```javascript
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'
import zhCn from 'element-plus/dist/locale/zh-cn.mjs'
import * as ElementPlusIconsVue from '@element-plus/icons-vue'
// 注册图标
for (const [key, component] of Object.entries(ElementPlusIconsVue)) {
app.component(key, component)
}
app.use(ElementPlus, { locale: zhCn, size: 'default' })
```
#### 3a.3 更新 plugins/modal.js 中的 Element 导入
`import { Message, MessageBox, Notification, Loading } from 'element-ui'` 改为 `import { ElMessage, ElMessageBox, ElNotification, ElLoading } from 'element-plus'`,并更新对应的 API 调用。
同时更新 `permission.js` 中的 `Message` 导入。
#### 3a.4 迁移公共组件31 个包含 Dialog 的组件,优先处理)
**目标**: 修复所有 `src/components` 中使用 `:visible.sync` 的组件,避免页面迁移时遇到 `[ElOnlyChild]` 错误。
需要迁移的组件列表(按目录分组):
| 组件分类 | 文件路径 | 数量 |
| --------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --- |
| Select 组件 | vendorSelect, iqcSelect, noticeSelect, itemSelect, clientSelect, batchSelect, userSelect, stockSelect, machinerySelect, warehouseSelect, workstationSelect, workorderSelect, procardSelect, qcindexSelect, reportSelect, TaskSelect, defectSelect, dvsubjectSelect, calTeamSelect, oqcSelect, itemBomSelect, dvplanSelect, stocktakingplanSelect, package | 31 |
| 其他 | DictSelect, ImageUpload | 2 |
**关键变更点**(适用所有组件):
- `:visible.sync="showFlag"` -> `v-model="showFlag"`
- 移除 `v-if="showFlag"`Element Plus dialog 自带显示控制)
- `<el-dialog>` 必须有单个根元素:添加 `<div class="dialog-content-wrapper">` 包裹所有 slot 默认内容
- `<div slot="footer">` -> `<template #footer>`
**当前进度**(已完成部分):
- ✅ vendorSelect/single.vue
- ✅ iqcSelect/single.vue
- ✅ noticeSelect/single.vue
- ⏳ noticeSelect/lineSingle.vue (进行中)
- ⏳ itemSelect/single.vue (进行中)
- 🔲 其余 26 个组件待迁移
#### 3a.5 迁移采购入库页面(试点验证)
逐一修改以下 4 个文件,按照通用变更清单做 Element Plus 适配:
| 文件 | 说明 |
| --------------------------------------- | ------- |
| `src/views/mes/wm/itemrecpt/index.vue` | 采购入库列表页 |
| `src/views/mes/wm/itemrecpt/form.vue` | 采购入库表单页 |
| `src/views/mes/wm/itemrecpt/line.vue` | 采购入库明细行 |
| `src/views/mes/wm/itemrecpt/detail.vue` | 采购入库详情页 |
**验收标准**: 启动 `vite dev`,能正常访问采购入库列表、新增、编辑、查看详情,无控制台报错。
---
### Phase 3a-2: 迁移公共布局和非 Dialog 组件(~38 个 Vue 文件)
**目标**: 完成 `src/layout/``src/components/` 中剩余的非 dialog 组件迁移,确保所有公共组件脱离 Element UI。
#### 需要迁移的文件类型
**Layout 组件** (`src/layout/`):
- Layout 主布局组件
- Navbar, Sidebar, TagsView 等导航组件
- AppMain, Settings 等布局子组件
- 约 10-15 个文件
**非 Dialog 公共组件** (`src/components/`):
- Pagination分页组件
- FileUpload文件上传
- Editor富文本编辑器可能使用 Element UI 依赖)
- Breadcrumb面包屑
- SvgIconSVG 图标,已迁移)
- Dict 相关组件(数据字典)
- TreeSelect, Cascader 等表单组件
- 其他工具类组件(约 20-25 个文件)
**迁移要点**:
- 替换所有 Element UI 组件为 Element Plus
- 更新 `size="mini"` -> `size="small"`
- 移除 `.native` 修饰符
- 更新图标引用方式
- 检查并修复任何使用 `$message`, `$alert` 等全局方法的调用
**验收标准**: 所有 `src/components/``src/layout/` 文件中不再有 `element-ui` 导入,项目启动无 Element UI 相关警告。
---
### Phase 3b: 仓库管理模块其余页面64 个 Vue 文件)
**目标**: 确认试点方案可行后,将整个仓库管理模块(`views/mes/wm/`)全部迁移完成。
需要迁移的子模块(按业务分组):
| 分组 | 子模块 | 文件数 |
| --- | -------------------------------------------------------------------------------------------------------- | --- |
| 入库 | arrivalnotice (到货通知), itemrecpt (采购入库✅已完成), outsourcerecpt (委外入库), productrecpt (产品入库), miscrecpt (其他入库) | ~15 |
| 出库 | issue (生产领料), productsales (销售出库), outsourceissue (委外出库), miscissue (其他出库), itemconsume (物料消耗) | ~15 |
| 退料 | rtissue (生产退料), rtsales (销售退货), rtvendor (供应商退货) | ~9 |
| 库存 | wmstock (库存查询), stocktaking (盘点), stocktakingplan (盘点计划), transfer (调拨) | ~10 |
| 基础 | warehouse (仓库), location (库区), area (库位), barcode (条码), batch (批次), sn (序列号), package (包装) | ~13 |
| 通知 | salesnotice (销售通知), mrnotice (物料需求通知) | ~5 |
**验收标准**: 仓库管理菜单下所有页面(列表/表单/详情)均可正常操作,无控制台 Element 组件报错。
---
### Phase 3c: 其余所有页面(~148 个 Vue 文件)+ 全局样式修正
**目标**: 完成所有剩余页面的迁移,项目彻底脱离 Element UI。
| 分组 | 范围 | 文件数 |
| ------ | ------------------------------------------------------------ | --- |
| MES 其他 | `views/mes/` 除 wm 外 (md, pro, dv, qc, report 等) | ~98 |
| 系统管理 | `views/system/` (user, role, menu, dept, dict 等) | ~19 |
| 监控 | `views/monitor/` (online, job, server, cache 等) | ~8 |
| 工具 | `views/tool/` (gen, build 等) | ~12 |
| 打印 | `views/print/` | ~6 |
| 其他 | `views/login.vue`, `views/register.vue`, `views/index.vue` 等 | ~5 |
#### 3c.1 全局样式文件更新
- 更新 [mom-backend-ui/src/assets/styles/](mom-backend-ui/src/assets/styles/) 下的 SCSS 文件中引用 Element UI 类名的部分
- Element Plus 的 CSS 变量命名有差异(如 `--el-color-primary` 等)
- `el-icon-loading` spinner 等全局引用需更新
**验收标准**: 全站所有页面功能正常,无 Element UI 残留引用,`vite build` 成功。
---
## Phase 4: 更新第三方依赖
以下 Vue 2 专属库需要更新为 Vue 3 兼容版本:
| 当前依赖 | 操作 |
| ------------------------- | ------------------------------------------------- |
| `vue-meta` 2.x | 移除,改用 `@unhead/vue``document.title` |
| `vuedraggable` 2.x | 升级到 `vuedraggable@next` (4.x) |
| `vue-cropper` 0.5 | 升级到 `vue-cropper@next` |
| `@riophae/vue-treeselect` | 替换为 `vue3-treeselect` 或 Element Plus 的 TreeSelect |
| `vue-count-to` | 替换为 Vue 3 兼容版本或自行实现 |
| `vue-plugin-hiprint` | 确认 Vue 3 兼容性,可能需要替换 |
| `echarts` 4.9 | 升级到 5.x |
| `@dhtmlx/trial-vue-gantt` | 确认 Vue 3 兼容版本 |
| `quill` | 替换为 `@vueup/vue-quill` |
| `axios` 0.24 | 升级到 1.x |
---
## Phase 5: 清理和收尾
### 5.1 移除旧配置文件
- 删除 `vue.config.js`
- 删除 `babel.config.js`
- 删除 `.eslintrc.js`(后续可按需重新配置 ESLint flat config
- 删除 `build/` 目录preview 脚本)
### 5.2 移除 @vue/compat
当所有组件和功能正常运行后:
-`vite.config.js` 中移除 `'vue': '@vue/compat'` 别名
- 移除 `compatConfig` 编译器选项
- 卸载 `@vue/compat`
- 修复剩余的 Vue 2 兼容性警告
### 5.3 环境变量迁移
- `VUE_APP_*` 环境变量需改为 `VITE_*` 前缀
- `process.env.VUE_APP_*` 改为 `import.meta.env.VITE_*`
- 创建 `.env.development``.env.production` 文件
---
## 执行建议
- **Phase 1-2** 是基础,已完成,项目可用 `vite` 启动和构建
- **Phase 3a** 先做依赖切换 + 采购入库试点,验证迁移方案的完整流程和模式
- **Phase 3b** 试点通过后,在仓库管理模块内推广,以模块为单位验证
- **Phase 3c** 最后全面铺开,涵盖剩余 layout/components/views
- **Phase 4** 可以与 Phase 3 并行,按需处理
- **Phase 5** 在所有功能验证通过后进行
- 整个过程中暂保留 JavaScript不转 TypeScript后续按需迁移
- 每步完成后都应启动 `vite dev` 实际操作验证,确认无功能回退再进入下一步