--- 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 `` ### 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"` - **图标**: `` -> `` 或对应 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 自带显示控制) - `` 必须有单个根元素:添加 `
` 包裹所有 slot 默认内容 - `
` -> `