19 KiB
name, overview, todos, isProject
| name | overview | todos | isProject | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| MOM-UI Tech Stack Migration | 将 mom-backend-ui 从 Vue CLI + Vue 2 + Element UI 渐进式升级到 Vite + Vue 3 + Element Plus,与 erp-frontend-vue 技术栈保持一致,方便后续合并。 |
|
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/ 根目录创建 vite.config.js,参考 erp-frontend-vue/vite.config.ts 的结构:
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 移到项目根目录,移除 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-vuevite-plugin-svg-icons+fast-glob(替代 svg-sprite-loader)sass-embedded(替代 sass + sass-loader)
移除:
@vue/cli-service,@vue/cli-plugin-babel,@vue/cli-plugin-eslintvue-template-compilerwebpack相关:compression-webpack-plugin,script-ext-html-webpack-plugin,svg-sprite-loader,sass-loader,less-loaderbabel-eslint,babel-plugin-dynamic-import-node,cross-envcore-js
1.5 配置 @vue/compat
在 vite.config.js 中配置别名,让 vue 指向兼容构建:
resolve: {
alias: {
'@': path.resolve(__dirname, './src'),
'vue': '@vue/compat'
}
}
同时需要配置 @vitejs/plugin-vue 的 compat 编译器选项:
vue({
template: {
compilerOptions: {
compatConfig: { MODE: 2 }
}
}
})
Phase 2: 更新入口文件和核心模块
2.1 更新 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.xxxVue.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 中的 require.context 替换为 Vite 的 import.meta.glob:
import 'virtual:svg-icons-register'
// SvgIcon 组件需要在 main.js 中用 app.component 注册
2.3 升级 Vue Router 3 -> 4
修改 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:
router.addRoutes(accessRoutes)改为循环调用router.addRoute(route)Message从 Element Plus 导入
2.4 升级 Vuex 3 -> 4
修改 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,改用 Element Plus 主题配置
3a.2 更新 main.js 中的 Element 导入
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(面包屑)
- SvgIcon(SVG 图标,已迁移)
- 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/ 下的 SCSS 文件中引用 Element UI 类名的部分
- Element Plus 的 CSS 变量命名有差异(如
--el-color-primary等) el-icon-loadingspinner 等全局引用需更新
验收标准: 全站所有页面功能正常,无 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实际操作验证,确认无功能回退再进入下一步