@epxing/cli 0.5.0-beta.3 → 0.5.0-beta.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/API.md CHANGED
@@ -2,13 +2,13 @@
2
2
 
3
3
  独立工程命令行工具,终端命令名为 epxing。/vite 提供产品构建插件,根入口不提供业务运行时。
4
4
 
5
- 本页对应包版本 `0.5.0-beta.3`。导出名、子路径和签名从当前源码、package.json 与类型声明生成。
5
+ 本页对应包版本 `0.5.0-beta.4`。导出名、子路径和签名从当前源码、package.json 与类型声明生成。
6
6
 
7
7
  ## 安装与使用
8
8
 
9
9
 
10
10
  ```sh
11
- npm install -g @epxing/cli@0.5.0-beta.3
11
+ npm install -g @epxing/cli@0.5.0-beta.4
12
12
  ```
13
13
 
14
14
 
package/README.md CHANGED
@@ -4,7 +4,7 @@
4
4
 
5
5
  独立的工程开发工具,包含交互菜单、开发服务、产品库构建、创建、Vue3 迁移、静态检查和升级技能安装。创建和升级默认使用 `@epxing/*` 独立包,版本留空时查询最新 `beta` 并固定到具体版本,没有 `beta` 时使用 `latest`;可用 `--packages-version` 指定版本或标签。CLI 使用自己的版本号。创建和升级会生成产品使用说明;`@epxing/cli/vite` 提供产品构建插件,不依赖聚合包中的构建工具。
6
6
 
7
- 本批测试版本:`@epxing/cli@0.5.0-beta.3`,平台包 `5.3.0-beta.2`,均使用 npm 公网 `beta` 标签。完整流程见文档站“CLI 创建、升级与产品使用”;各包公开 API 随安装包的 `API.md` 提供。
7
+ 本批测试版本:`@epxing/cli@0.5.0-beta.4`,平台包 `5.3.0-beta.2`,均使用 npm 公网 `beta` 标签。完整流程见文档站“CLI 创建、升级与产品使用”;各包公开 API 随安装包的 `API.md` 提供。
8
8
 
9
9
  平台包从 `5.3.0-beta.2` 起自动加载自身样式,产品无需手动引入各包的 `style.css`。创建和迁移使用此版本时,CLI 不再添加这些导入;指定旧版本时仍保留显式样式以兼容旧包。标签会先解析成具体版本再选择模板。已有显式导入可以保留,产品覆盖样式放在框架导入之后。
10
10
 
@@ -26,6 +26,14 @@ epxing skill install --dir E:/products/my-product
26
26
 
27
27
  从 0.4.0 起终端命令为 `epxing`,可与旧聚合 CLI 的 `epx` 共存。新产品直接依赖 `@epxing/core`、`@epxing/components`、`@epxing/utils` 等包。创建后进入目录安装依赖,再运行 `npm run dev`;默认端口 8080。工具安装阶段不会运行迁移或改产品文件。
28
28
 
29
+ 新建产品的 `src/main.js` 使用 `createApp({ router: createFrameRouter() })`,安装 Components、Business 和产品插件,默认运行平台登录、菜单与系统首页。先在 `.env.development.local` 配置实际后端和应用参数。产品组件放入自动收集目录,`src/index.js` 仍是独立产品库入口,不包含本地应用启动代码。
30
+
31
+ 从 `0.5.0-beta.4` 起,旧 CLI 生成的计数欢迎页在 main.js 与 App.vue 都保持原始模板时可由 upgrade 自动修复;自定义入口不覆盖。`epxing scan` 的 R4 提示尚未修复的原始欢迎页。升级技能区分 Vue2/webpack、Vue3 聚合包及已有独立包工程,报告补充平台启动验收。
32
+
33
+ 组件校验 `epxing verify` 优先读取 lib 的清单或产物,无产物时按产品收集入口列源码候选,支持常规静态 glob 与 require.context;无法确定的动态规则要求先构建。源码候选不能代替产物及真实平台验收。
34
+
35
+ 升级 CLI 后可用 `epxing skill install --dir <产品目录>` 安装新版升级技能。已有技能会受保护而退出;确认并保留产品自定义内容后,才使用 `--force` 替换。技能和命令随同一 CLI 版本交付。
36
+
29
37
  `--epx-frame <版本或spec>` 仅用于显式选择旧聚合产品模式,与 `--packages-version` 互斥。普通命令与无参数交互引导均默认使用独立包,版本输入可直接回车。显式数字版本不查询网络;默认版本与标签需查询 npm,查询失败会退出,可通过固定版本离线生成。迁移遇到动态旧接口等无法确定的内容时返回 2,报告人工清单并保留原包模式;不会只切换一半导入。已有业务路由、store 和 install 注册代码保留;已有自定义 `PRODUCT-GUIDE.md` 会保留,另写 `EPXING-PACKAGES-GUIDE.md`。
30
38
 
31
39
  ```js
package/dist/cli.mjs CHANGED
@@ -76,7 +76,7 @@ async function interactive (cwd, action) {
76
76
  if (!action) {
77
77
  action = await prompts.select('选择操作', choices([
78
78
  ['dev 启动开发服务', 'dev'], ['build 工程打包', 'build'], ['lib 产品库 / 平台组件库打包', 'lib'],
79
- ['preview 预览构建结果', 'preview'], ['create 创建产品 / 项目', 'create'], ['migrate 升级到 Vue 3', 'migrate'],
79
+ ['preview 预览构建结果', 'preview'], ['create 创建产品 / 项目', 'create'], ['migrate 产品升级 / Vue 3 迁移', 'migrate'],
80
80
  ['skill 安装升级技能', 'skill'], ['check 风险扫描 / 组件校验 / 代码检查', 'check'],
81
81
  ['advanced 平台独立包 / 远程模块构建', 'advanced'], ['help 查看命令帮助', 'help'], ['exit 退出', 'exit']
82
82
  ]))
@@ -193,6 +193,8 @@ create、migrate 默认使用 @epxing/core、@epxing/components 等独立包。
193
193
  版本留空时查询最新 beta 并固定具体版本;没有 beta 时使用 latest。可用 --packages-version 固定版本或指定标签。
194
194
  --epx-frame <版本或spec> 保留旧聚合模式,与 --packages-version 互斥。
195
195
  创建和升级自动写入 runtime: "vue3"。迁移默认 dry-run,--apply 才落盘。
196
+ create 默认启动平台系统;upgrade 可修复原始计数欢迎页入口,自定义入口保留。
197
+ Vue 3 工程通常无需 --transform-vue;升级后验证平台登录、菜单、首页和产品组件,再交付 lib/。
196
198
  工具不会自动安装平台依赖;.vue 转换工具仅在执行 --apply --transform-vue 时下载并缓存。`)
197
199
  return 0
198
200
  }
@@ -3,14 +3,34 @@ name: epxing-frontend-vue3-migrate
3
3
  description: epx 产品/项目远程库 Vue2/webpack → Vue3/Vite 升级 + 按需打包(lazy/chunks 形态)的完整流程、判据与踩坑清单;也用于排查远程库「构建绿、控制台干净、组件却静默失效」——不渲染 / 注册名错 / 有组件没样式 / 登录拉整包 / 弹窗标题空 / 图表画不出 / 卡片 scoped 样式丢。含 epx-migrate CLI(migrate 迁移、detect-vue3-risks 发布前静态扫风险、verify-components 组件清单对齐)与三方对比环境搭法(本地 dist + 工装 + Web Worker 定时器垫片 + 运行时实证)。触发:产品升级 / Vue3 迁移 / 迁移包对比测试 / 升级后静默失效排查。
4
4
  ---
5
5
 
6
- # 升级产品远程库(Vue3 + Vite + 按需打包)
6
+ # 产品升级与迁移(独立包 + Vue3 + Vite)
7
7
 
8
8
  ## 这是什么
9
9
 
10
10
  epx 的产品/项目远程库(`window.library.<pkg>`,由 `FM_SYSTEM_WEBPACK` 配 url、运行时加载)
11
11
  从 Vue2/webpack 迁到 Vue3/Vite,并可选切到「清单 + 组件按需加载」形态的完整流程与踩坑清单。
12
12
 
13
- 独立 CLI 从 `@epxing/cli@0.4.0` 起使用 `epxing` 命令(包名不变,平台依赖仍为 `epx-frame`)。例如 `epxing migrate <产品目录> --epx-frame <目标版本> --apply`;同时执行日期格式和主题样式迁移。已升级工程可用 `epxing theme <目录> --apply` 单独补修。仓库原有 `pnpm epx` 是本地脚本,不等同于全局命令。
13
+ 独立 CLI 使用 `epxing` 命令,产品默认依赖 `@epxing/core`、`@epxing/components`、`@epxing/business` 等独立包。`upgrade` 是 `migrate` 的别名;版本留空查询最新 beta(无 beta 时回退 latest),并固定具体版本。`--epx-frame` 仅显式保留旧聚合模式。仓库原有 `pnpm epx` 是本地脚本,不等同于已安装的 CLI。
14
+
15
+ ## 先判断升级类型
16
+
17
+ | 当前工程 | 操作 |
18
+ | --- | --- |
19
+ | Vue2 / webpack 产品 | 先预览 `epxing upgrade . --transform-vue --to-vite`,审阅人工项后同命令加 `--apply` |
20
+ | Vue3 聚合包产品 | `epxing upgrade .` 预览独立包切换;仅仍用 webpack 时追加 `--to-vite` |
21
+ | 已使用独立包的 Vue3 产品 | `epxing upgrade .` 更新包版本与确定的补修,不重复执行 Vue2 转换 |
22
+
23
+ 默认预览只读;`--apply` 要求目标 Git 工作树干净。需要复现指定版本时传 `--packages-version <版本>`。CLI 不自动安装平台依赖、构建、提交、部署或发布产品,按当前任务授权执行后续步骤。日期和主题的静态补修随迁移执行;动态来源仍需复核。
24
+
25
+ ## 平台启动入口
26
+
27
+ 新建平台产品默认使用 `createApp({ router: createFrameRouter() })`,依次安装 Components、Business 和产品插件后 mount。core 提供最外层路由根组件;Business 注册系统 App,在应用配置就绪后读取 FIRST_PAGE / MOBILE_FIRST_PAGE。不要把 business 的系统视图直接挂成最外层根组件。components 提供 AppIndex、登录和基础组件。
28
+
29
+ 旧 CLI 的计数欢迎页仅在 main.js 与 App.vue 都保持原始模板时自动修复;自定义根组件、路由、store、HTTP 客户端保留,先确认它是平台产品还是完全自建应用,再按实际用途调整。`epxing scan .` 的 R4 提示尚未修复的原始欢迎页,不据此覆盖自定义内容。
30
+
31
+ `src/main.js` 负责本地开发启动;`src/index.js` 负责产品组件库安装和导出,库入口中不再次 createApp 或 mount。组件目录以收集入口为准,不固定为 hr;无构建产物时 `epxing verify .` 仅列源码候选,不能当作产物校验或运行验收通过。
32
+
33
+ 启动前确认后端地址、客户端、系统和应用配置;验收登录、角色、菜单、PC/移动端首页,再验产品组件、路由与状态。入口、依赖及迁移规则以当前 CLI 创建模板、迁移器和组件校验器为依据,参见 [A5](pitfalls.md#a5-独立包升级后仍显示欢迎页或平台入口空白)。
14
34
 
15
35
  **核心判断:这条链上的失败几乎全是静默的。** 构建绿、控制台干净、组件就是不出来。
16
36
  所以每一步都要有**判据**,别靠"看着没报错"。
@@ -27,11 +47,11 @@ epx 的产品/项目远程库(`window.library.<pkg>`,由 `FM_SYSTEM_WEBPACK`
27
47
  ## 顺序(别调换)
28
48
 
29
49
  ```
30
- ① 依赖 + codemod pnpm epx migrate --apply → 出 MIGRATION-REPORT.md
50
+ ① 预览并应用升级 epxing upgrade . → 审阅计划后追加 --apply
31
51
  ② .vue 转换 (同上,gogocode) → 逐个修构建报错
32
52
  ③ 切 Vite 换 vite.config.mjs → require.context → import.meta.glob
33
53
  ④ 跑起来 dev 壳验证 → 组件真渲染出来才算过
34
- ⑤ 开按需(可选) npm run build:lib:lazy → 验清单 + 真机验渲染
54
+ ⑤ 验产品库形态 epxing lib / lib --full → 按需 / 完整库,验清单和真实平台渲染
35
55
  ```
36
56
 
37
57
  **②→③ 之间必须先让 `build:lib` 绿**。没绿就切按需,等于同时改两个变量,出问题分不清是谁的。
@@ -41,10 +61,10 @@ epx 的产品/项目远程库(`window.library.<pkg>`,由 `FM_SYSTEM_WEBPACK`
41
61
  | 步骤 | 判据(不是"没报错") |
42
62
  |---|---|
43
63
  | ① 依赖迁移 | `MIGRATION-REPORT.md` 的人工清单**逐条看过**——里面写着的坑会真的咬人 |
44
- | ② .vue 转换 | `npx eslint src --ext .js,.jsx,.vue` 能跑(迁移会删掉 eslint 生态,先修工具链) |
64
+ | ② .vue 转换 | 使用工程本地 ESLint 校验改动源码;工具链缺失则先恢复并明确未验证项,不临时拉全局 ESLint |
45
65
  | ③ 切 Vite | `npm run build:lib` exit 0 **且** `lib/` 里有 `index.js`/`index.css`/`index.deps.json` |
46
- | ④ dev 壳 | 浏览器里 `#app.__vue_app__._context.components` 能数到你的组件个数;对自定义页、继承组件和多分支 render,核对实际 DOM 与 CSS 选择器是否匹配。样式隔离变更还须用最终产物通过 F15 的组件内、组件外及跨页面检查 |
47
- | ⑤ 按需 | `index.manifest.json` 组件数 == `.vue` 文件数,**且路径兜底名 0 个** |
66
+ | ④ dev 壳 | 平台登录、角色、菜单与配置首页可用,产品组件确实显示;核对真实 DOM 和 CSS,不能仅凭注册数量判通过。样式隔离变更还须用最终产物通过 F15 的组件内、组件外及跨页面检查 |
67
+ | ⑤ 按需 | `index.manifest.json` 与入口实际收集的组件集合对齐,复核路径兜底名;源码候选、产物清单和线上参考分别记录 |
48
68
 
49
69
  第⑤条那个"路径兜底名"是最容易漏的:注册名抽不到就退成 `hrcomponentsSearch` 这种,
50
70
  **dev 壳看不出来**(dev 读运行时 `comp.name`),只在按需形态下炸。
@@ -121,7 +141,7 @@ epx 的产品/项目远程库(`window.library.<pkg>`,由 `FM_SYSTEM_WEBPACK`
121
141
  真正的大头是平台重建(旧平台 20–59 s → 新平台 11 s)。
122
142
 
123
143
  所以按需的价值是**防止劣化**(库继续长大时首屏不跟着涨),不是当下提速。
124
- 库还不到 1MB 就别开。
144
+ 当前 CLI 的 `epxing lib` 默认按需构建;小型产品或无需分片时可使用 `epxing lib --full`。选择依据是实际宿主、请求数与渲染测试,不用旧案例中的体积阈值作为统一开关。
125
145
 
126
146
  ## 部署前必查
127
147
 
@@ -49,6 +49,14 @@ gogocode 按它自己的约定把函数体改成 `window.$vueApp.*`,而**平
49
49
 
50
50
  ---
51
51
 
52
+ ### A5. 独立包升级后仍显示欢迎页或平台入口空白
53
+
54
+ **区分根组件与系统视图**:core 的 createApp 提供路由根组件;createFrameRouter 提供平台路由和守卫;Business 注册的系统 App 依赖已加载的应用配置,再选择 FIRST_PAGE / MOBILE_FIRST_PAGE。只挂计数欢迎页不会进入系统;直接把系统 App 当根组件则绕过配置加载链。
55
+
56
+ **修复边界**:新版 upgrade 只自动修复 main.js 和 App.vue 均为原始计数模板的工程。自定义页面和入口保留,按用途核对路由及插件,不全量覆盖为平台模板。scan 的 R4 能提示原始欢迎页;构建、静态检查和模拟 DOM 通过都不能替代真实后端的登录、角色、菜单、首页及产品组件验收。
57
+
58
+ **远程交付**:产品库入口保留组件安装/导出和 runtime 标识,不把本地 main.js 的 createApp/mount 打入远程库。组件校验优先读取产物;无产物时按入口目录列源码候选,动态收集规则先构建再校验,不把空集合误判为缺失全部业务组件。
59
+
52
60
  ## B. Vite 化阶段
53
61
 
54
62
  ### B1. `recorder-core` 引擎与核心之间**没有模块图边**
@@ -0,0 +1,227 @@
1
+ import{a as o}from"./OVN5O3EZ.mjs";function c(i="5.3.0-beta.2"){let n=i.match(/^[~^]?(\d+)\.(\d+)\.(\d+)(?:-([\w.-]+))?$/);if(!n)return!1;let[,p,t,e,s]=n,r=Number(p)*1e6+Number(t)*1e3+Number(e);return r!==5003e3?r>5003e3:!s||/^beta\.(\d+)$/.test(s)&&Number(s.slice(5))>=2}o(c,"usesAutomaticStyles");var a=["@epxing/core/style.css","@epxing/components/style.css","@epxing/business/style.css"],m={main:`import { createApp } from '@epxing/core'
2
+ import Components from '@epxing/components'
3
+ import Business from '@epxing/business'
4
+ import '@epxing/theme'
5
+ import App from './App.vue'
6
+ import product from './index'
7
+
8
+ const app = createApp({ rootComponent: App })
9
+ app.use(Components)
10
+ app.use(Business)
11
+ app.use(product)
12
+ app.mount('#app')
13
+ `,app:`<script setup>
14
+ import { ref } from 'vue'
15
+ const count = ref(0)
16
+ </script>
17
+
18
+ <template>
19
+ <main class="product-start">
20
+ <h1>__NAME__</h1>
21
+ <p>\u4EA7\u54C1\u5DF2\u542F\u52A8\uFF0C\u53EF\u4EE5\u5F00\u59CB\u5F00\u53D1\u3002</p>
22
+ <button @click="count++">\u70B9\u51FB {{ count }} \u6B21</button>
23
+ </main>
24
+ </template>
25
+
26
+ <style scoped>
27
+ .product-start { padding: var(--epx-space-4, 24px); color: var(--epx-text); }
28
+ </style>
29
+ `};function l(i,n,p){let t=o(s=>(s||"").replaceAll(`\r
30
+ `,`
31
+ `).trim(),"normalize"),e=t(i);for(let s of a)e=e.replace(`import '${s}'
32
+ `,"");return e===t(m.main)&&t(n)===t(m.app.replaceAll("__NAME__",p))}o(l,"isLegacyWelcomeProduct");function d(i,n){let p={...i,"package.json":JSON.stringify({name:"__NAME__",version:"0.1.0",private:!0,runtime:"vue3",type:"module",scripts:{dev:"vite","build:lib":"vite build","build:lib:lazy":"cross-env LAZY_LIB=true vite build","build:app":"vite build --mode app",preview:"vite preview"},dependencies:{"@epxing/core":"__PACKAGES_VERSION__","@epxing/components":"__PACKAGES_VERSION__","@epxing/utils":"__PACKAGES_VERSION__","@epxing/business":"__PACKAGES_VERSION__","@epxing/theme":"__PACKAGES_VERSION__",vue:"3.5.39","vue-router":"4.6.4",vuex:"4.1.0","element-plus":"2.14.3"},devDependencies:{"@epxing/cli":"__CLI_VERSION__","@epxing/icons":"__PACKAGES_VERSION__",vite:"^6.0.0","@vitejs/plugin-vue":"^5.2.1","@vitejs/plugin-vue-jsx":"^4.1.1",sass:"^1.83.3","cross-env":"^7.0.3"}},null,2)+`
33
+ `,"vite.config.mjs":`import path from 'node:path'
34
+ import { fileURLToPath } from 'node:url'
35
+ import { createRequire } from 'node:module'
36
+ import { defineConfig, loadEnv } from 'vite'
37
+ import vue from '@vitejs/plugin-vue'
38
+ import vueJsx from '@vitejs/plugin-vue-jsx'
39
+ import { frameDeps, epxShared, lazyLib } from '@epxing/cli/vite'
40
+ import epxIcons from '@epxing/icons'
41
+ import pkg from './package.json' with { type: 'json' }
42
+
43
+ const root = path.dirname(fileURLToPath(import.meta.url))
44
+ const require = createRequire(import.meta.url)
45
+ const CONFIG_KEYS = ['IP', 'BASE_URL', 'BASE_PROJECT_NAME', 'BASE_AUTH_NAME', 'BASE_CLIENT_ID', 'BASE_SYSTEM_ID', 'BASE_APP_ID', 'ROUTER_MODE', 'MINIO_FILE_URL', 'WITH_CREDENTIALS']
46
+
47
+ export default defineConfig(({ command, mode }) => {
48
+ const env = loadEnv(mode, root, '')
49
+ const library = command === 'build' && mode !== 'app'
50
+ return {
51
+ resolve: { alias: { '@': path.resolve(root, 'src') }, dedupe: ['vue', 'vuex', 'vue-router'] },
52
+ server: { port: 8080 },
53
+ plugins: [
54
+ vue(), vueJsx(), epxIcons(),
55
+ ...(library ? [
56
+ frameDeps(), epxShared(),
57
+ lazyLib({ root, enabled: process.env.LAZY_LIB === 'true', glob: './__DIRNAME__/**/*.vue', pkgName: pkg.name })
58
+ ] : []),
59
+ {
60
+ name: 'product-runtime-config',
61
+ transformIndexHtml () {
62
+ const lines = CONFIG_KEYS.map(key => key === 'WITH_CREDENTIALS'
63
+ ? 'window.' + key + ' = ' + JSON.stringify(env[key] === 'true')
64
+ : 'window.' + key + ' = ' + JSON.stringify(env[key] || ''))
65
+ lines.push('window.MINIO_IP = window.IP || window.location.origin + "/"')
66
+ return [{ tag: 'script', children: lines.join('\\n'), injectTo: 'head-prepend' }]
67
+ }
68
+ }
69
+ ],
70
+ css: { preprocessorOptions: { scss: {
71
+ additionalData: '@import "' + require.resolve('@epxing/theme/src/theme/utils/mixins.scss').replace(/\\\\/g, '/') + '";',
72
+ quietDeps: true, silenceDeprecations: ['import', 'legacy-js-api', 'global-builtin']
73
+ } } },
74
+ build: library ? {
75
+ outDir: 'lib',
76
+ lib: { entry: path.resolve(root, 'src/index.js'), name: 'library.' + pkg.name, formats: ['umd'], fileName: () => 'index.js' },
77
+ rollupOptions: { output: { exports: 'default', assetFileNames: asset =>
78
+ (asset.names || [asset.name]).some(name => String(name).endsWith('.css')) ? 'index.css' : 'assets/[name]-[hash][extname]' } }
79
+ } : { outDir: 'dist' }
80
+ }
81
+ })
82
+ `,"src/main.js":`import { createApp, createFrameRouter } from '@epxing/core'
83
+ import Components from '@epxing/components'
84
+ import Business from '@epxing/business'
85
+ import '@epxing/theme'
86
+ import product from './index'
87
+
88
+ // \u5E73\u53F0\u8DEF\u7531\u8D1F\u8D23\u767B\u5F55\u3001\u5E94\u7528\u914D\u7F6E\u548C\u7CFB\u7EDF\u9996\u9875\uFF0CBusiness \u63D0\u4F9B\u5176\u4E2D\u7684\u7CFB\u7EDF\u89C6\u56FE\u3002
89
+ const app = createApp({ router: createFrameRouter() })
90
+ app.use(Components)
91
+ app.use(Business)
92
+ app.use(product)
93
+ app.mount('#app')
94
+ `,"src/__DIRNAME__/DemoList.vue":`<script>
95
+ import { EntityList } from '@epxing/components'
96
+ export default {
97
+ name: 'epx-__NAME__-demo-list',
98
+ extends: EntityList
99
+ // \u914D\u7F6E\u771F\u5B9E metaId\u3001listFields\u3001operates \u540E\uFF0C\u5728\u4EA7\u54C1\u9875\u9762\u4E2D\u4F7F\u7528\u3002
100
+ }
101
+ </script>
102
+ <style lang="scss" scoped>
103
+ .epx-__NAME__-demo-card {
104
+ @include epx-card;
105
+ font-size: var(--epx-font-size-base, 14px);
106
+ }
107
+ </style>
108
+ `,"README.md":`# __NAME__
109
+
110
+ \u57FA\u4E8E @epxing/* \u72EC\u7ACB\u5305\u7684 Vue 3 \u4EA7\u54C1\u3002\u8BE6\u7EC6\u8BF4\u660E\u89C1 [\u4EA7\u54C1\u4F7F\u7528\u6587\u6863](./PRODUCT-GUIDE.md)\u3002
111
+
112
+ \`\`\`sh
113
+ npm install --registry https://registry.npmjs.org/
114
+ npm run dev
115
+ npx epxing lib
116
+ npx epxing lib --full
117
+ npm run build:app
118
+ \`\`\`
119
+
120
+ \u672C\u5730\u9884\u89C8\u9ED8\u8BA4\u7AEF\u53E3 8080\uFF0C\u9ED8\u8BA4\u6253\u5F00\u5E73\u53F0\u7CFB\u7EDF\u3002\u542F\u52A8\u524D\u5728 .env.development.local \u914D\u7F6E\u540E\u7AEF\u53CA\u5BA2\u6237\u7AEF\u3001\u7CFB\u7EDF\u3001\u5E94\u7528\u53C2\u6570\uFF1B\u767B\u5F55\u3001\u83DC\u5355\u548C\u9996\u9875\u4F7F\u7528\u5E73\u53F0\u914D\u7F6E\u3002
121
+ `,"PRODUCT-GUIDE.md":u};if(!c(n)){let t=a.map(e=>`import '${e}'`).join(`
122
+ `);for(let e of["src/main.js","PRODUCT-GUIDE.md"])p[e]=p[e].replace("import '@epxing/theme'",`import '@epxing/theme'
123
+ `+t)}return p}o(d,"createPackageTemplates");var u=`# \u4EA7\u54C1\u5F00\u53D1\u4E0E\u5347\u7EA7\u4F7F\u7528\u8BF4\u660E
124
+
125
+ <!-- epxing-generated-product-guide -->
126
+
127
+ \u5E73\u53F0\u5305\u7248\u672C\uFF1A\`__PACKAGES_VERSION__\`\uFF1BCLI \u7248\u672C\uFF1A\`__CLI_VERSION__\`\u3002CLI \u4E0E\u5E73\u53F0\u5305\u5206\u522B\u5347\u7EA7\u3002
128
+
129
+ \u521B\u5EFA\u6216\u5347\u7EA7\u65F6\u4E0D\u586B\u7248\u672C\uFF0CCLI \u81EA\u52A8\u9009\u62E9\u6700\u65B0 beta\uFF08\u6CA1\u6709 beta \u65F6\u4F7F\u7528 latest\uFF09\uFF0C\u5E76\u5C06\u5177\u4F53\u7248\u672C\u5199\u5165\u4F9D\u8D56\u3002\u9700\u8981\u590D\u73B0\u6307\u5B9A\u7248\u672C\u65F6\u4F7F\u7528 --packages-version\uFF1B\u57FA\u7840\u7EC4\u4EF6\u7EDF\u4E00\u4ECE @epxing/components \u5BFC\u5165\u3002
130
+
131
+ ## \u5B89\u88C5\u4E0E\u542F\u52A8
132
+
133
+ \`\`\`sh
134
+ npm install --registry https://registry.npmjs.org/
135
+ npm run dev
136
+ \`\`\`
137
+
138
+ \u672C\u5730\u9ED8\u8BA4 \`http://localhost:8080\`\uFF0C\u6253\u5F00\u7684\u662F\u5E73\u53F0\u7CFB\u7EDF\u3002\u5148\u5728 \`.env.development.local\` \u914D\u7F6E IP\u3001BASE_PROJECT_NAME\u3001BASE_AUTH_NAME\u3001BASE_CLIENT_ID\u3001BASE_SYSTEM_ID\u3001BASE_APP_ID\uFF0C\u6307\u5411\u5B9E\u9645\u540E\u7AEF\u548C\u5E94\u7528\u3002\u767B\u5F55\u3001\u83DC\u5355\u3001\u6743\u9650\u3001\u9996\u9875\u5747\u7531\u5E73\u53F0\u63D0\u4F9B\uFF0C\u9700\u8981\u53EF\u7528\u540E\u7AEF\u3002
139
+
140
+ ## \u5E94\u7528\u5165\u53E3
141
+
142
+ \`\`\`js
143
+ import { createApp, createFrameRouter } from '@epxing/core'
144
+ import Components from '@epxing/components'
145
+ import Business from '@epxing/business'
146
+ import '@epxing/theme'
147
+ import product from './index'
148
+
149
+ const app = createApp({ router: createFrameRouter() })
150
+ app.use(Components)
151
+ app.use(Business)
152
+ app.use(product)
153
+ app.mount('#app')
154
+ \`\`\`
155
+
156
+ createApp \u8FD4\u56DE Vue App\uFF0C\u9ED8\u8BA4\u521B\u5EFA\u72EC\u7ACB store\u3001hash router \u548C HTTP \u5BA2\u6237\u7AEF\u3002\u9700\u8981\u81EA\u5B9A\u4E49\u65F6\u4F20\u5165 \`{ rootComponent, store, router, http: productHttp }\`\u3002\u4EA7\u54C1 HTTP \u5BA2\u6237\u7AEF\u9700\u5B9E\u73B0\u9875\u9762\u5B9E\u9645\u8C03\u7528\u7684 find/get/list/save \u7B49\u534F\u8BAE\u3002
157
+
158
+ \u4ECE\u5E73\u53F0\u5305 5.3.0-beta.2 \u8D77\uFF0Ccore\u3001component/components\u3001business\u3001designer\u3001dashboard \u7684 JS \u5165\u53E3\u81EA\u52A8\u52A0\u8F7D\u672C\u5305\u805A\u5408\u6837\u5F0F\uFF0C\u6839\u5BFC\u5165\u548C\u7EC4\u4EF6\u5B50\u8DEF\u5F84\u90FD\u65E0\u9700\u624B\u52A8 import style.css\u3002utils \u548C icons \u5DE5\u5177\u4E0D\u52A0\u8F7D UI \u6837\u5F0F\uFF1Btheme \u4ECD\u662F\u663E\u5F0F\u4F7F\u7528\u7684 SCSS \u6E90\u7801\u5305\u3002\u81EA\u52A8\u52A0\u8F7D\u6309\u5305\u805A\u5408\uFF0C\u4E0D\u662F\u5355\u4E2A\u7EC4\u4EF6\u7684 CSS \u88C1\u526A\u3002
159
+
160
+ \u4FDD\u7559 style.css \u5165\u53E3\u4EE5\u517C\u5BB9\u65E7\u4EE3\u7801\uFF1B\u5DF2\u6709\u624B\u52A8\u5BFC\u5165\u53EF\u4EE5\u5220\u9664\u3002\u4EA7\u54C1\u8986\u76D6\u6837\u5F0F\u653E\u5728\u6846\u67B6\u5BFC\u5165\u4E4B\u540E\u3002CLI \u6307\u5B9A\u65E7\u7248\u672C\u6216\u65E0\u6CD5\u786E\u5B9A\u7248\u672C\u4E0B\u9650\u7684\u6807\u7B7E\u65F6\uFF0C\u4F1A\u4FDD\u5B88\u4FDD\u7559\u663E\u5F0F CSS \u5BFC\u5165\u3002
161
+
162
+ \u9ED8\u8BA4\u6839\u7EC4\u4EF6\u7531 core \u63D0\u4F9B\uFF0C\u8D1F\u8D23\u8DEF\u7531\u51FA\u53E3\u3001\u8DEF\u7531\u5237\u65B0\u7B56\u7565\u548C\u4E3B\u9898\u521D\u59CB\u5316\uFF1BcreateFrameRouter \u63D0\u4F9B\u5E73\u53F0\u8DEF\u7531\u548C\u767B\u5F55\u5B88\u536B\u3002Business \u6CE8\u518C\u7684 App\uFF08views/App.vue\uFF09\u5728\u5E94\u7528\u914D\u7F6E\u52A0\u8F7D\u540E\u8BFB\u53D6 FIRST_PAGE / MOBILE_FIRST_PAGE\uFF0C\u8FDB\u5165\u7CFB\u7EDF\u9996\u9875\uFF0C\u4E0D\u5E94\u76F4\u63A5\u66FF\u6362\u6700\u5916\u5C42\u8DEF\u7531\u6839\u7EC4\u4EF6\u3002components \u63D0\u4F9B AppIndex\u3001\u767B\u5F55\u548C\u57FA\u7840\u7EC4\u4EF6\uFF0C\u4EA7\u54C1\u901A\u8FC7 app.use(product) \u6CE8\u518C\u81EA\u5DF1\u7684\u7EC4\u4EF6\u3002
163
+
164
+ \u9700\u8981\u5B8C\u5168\u81EA\u5EFA\u5E94\u7528\u65F6\uFF0C\u624D\u4F20\u5165\u81EA\u5DF1\u7684 rootComponent\u3001router \u6216 routes\u3002\u4EA7\u54C1\u7EC4\u4EF6\u653E\u5728 src/__DIRNAME__/\uFF0C\u901A\u8FC7\u5E73\u53F0\u9875\u9762\u7EC4\u4EF6\u914D\u7F6E\u4F7F\u7528\uFF1B\u5F00\u53D1\u5165\u53E3 src/main.js \u4E0D\u8FDB\u5165\u8FDC\u7A0B\u4EA7\u54C1\u5E93\uFF0C\u5E93\u6784\u5EFA\u53EA\u8BFB\u53D6 src/index.js\u3002
165
+
166
+ ## \u7EC4\u4EF6\u4E0E\u5DE5\u5177
167
+
168
+ \`\`\`js
169
+ import { EntityList, AddForm, AddFormItem } from '@epxing/components'
170
+ import { UserFind, EntityTreeManage } from '@epxing/business'
171
+ import { mixins, getSystemMeta, getFileUrl, http, createFieldFactory } from '@epxing/core'
172
+ import { cloneDeep, moment, resolvePlaceholders, storage } from '@epxing/utils'
173
+
174
+ export default {
175
+ name: 'epx-__NAME__-employee-list',
176
+ extends: EntityList,
177
+ metaId: '\u4EA7\u54C1\u5B9E\u9645\u5143\u6570\u636EID',
178
+ pageSize: 20
179
+ }
180
+ \`\`\`
181
+
182
+ \u914D\u7F6E\u9A71\u52A8\u7EC4\u4EF6\u7ECF $configs \u8BFB\u53D6\u5408\u6210\u914D\u7F6E\u3002ComponentMixin/mixins.component \u63D0\u4F9B\u9875\u9762\u4E0A\u4E0B\u6587\uFF1B\u666E\u901A Vue props \u4E0E\u914D\u7F6E\u9879\u8BF7\u6309\u5404\u7EC4\u4EF6 API \u4F7F\u7528\u3002\`runExpByScope.call(vm, scopes, data)\` \u4FDD\u7559\u7EC4\u4EF6\u4E0A\u4E0B\u6587\u3002\u9ED8\u8BA4\u5DE5\u5177\u5BF9\u8C61\u4E0E\u5177\u540D API \u4EE5\u5BF9\u5E94\u5305 API.md \u4E3A\u51C6\u3002
183
+
184
+ \u9700\u8981\u8BBE\u8BA1\u5668/\u770B\u677F\u65F6\uFF0C\u5B89\u88C5\u540C\u7248\u672C \`@epxing/designer\` / \`@epxing/dashboard\`\uFF0C\u5728\u672C\u5730\u5E94\u7528\u5BFC\u5165\u5E76\u5B89\u88C5\u63D2\u4EF6\uFF0C\u6837\u5F0F\u81EA\u52A8\u52A0\u8F7D\u3002\u8FDC\u7A0B\u4EA7\u54C1\u4F7F\u7528\u516C\u5F00\u7EC4\u4EF6\uFF0C\u5BBF\u4E3B\u8D1F\u8D23\u5B89\u88C5\u8BBE\u8BA1/\u4E1A\u52A1\u63D2\u4EF6\u53CA\u52A0\u8F7D\u5176\u6837\u5F0F\u3002
185
+
186
+ \u5404\u5305 API.md \u968F\u5B89\u88C5\u5305\u63D0\u4F9B\uFF0C\u53EF\u5728 node_modules/@epxing/<\u5305\u540D>/API.md \u67E5\u770B\u3002\u57FA\u7840\u7EC4\u4EF6\u7EDF\u4E00\u4F7F\u7528 @epxing/components\uFF0C\u65B0\u4EE3\u7801\u4F7F\u7528\u6839\u5BFC\u51FA\u53CA\u7A33\u5B9A\u5B50\u8DEF\u5F84\u3002
187
+
188
+ ## \u72EC\u7ACB\u5E94\u7528\u4E0E\u8FDC\u7A0B\u4EA7\u54C1\u5E93
189
+
190
+ \`\`\`sh
191
+ npm run build:app # dist/\uFF1A\u72EC\u7ACB\u5E94\u7528\uFF0C\u4F7F\u7528 npm \u5305
192
+ npx epxing lib # lib/\uFF1A\u9ED8\u8BA4\u6309\u9700\u4EA7\u54C1\u5E93
193
+ npx epxing lib --full # lib/\uFF1A\u5B8C\u6574\u4EA7\u54C1\u5E93
194
+ npm run build:lib # \u76F4\u63A5 Vite \u5B8C\u6574\u5E93\u6784\u5EFA
195
+ npm run build:lib:lazy # \u663E\u5F0F\u6309\u9700\u5E93\u6784\u5EFA
196
+ \`\`\`
197
+
198
+ vite.config.mjs \u53EA\u5728\u8FDC\u7A0B\u5E93\u6784\u5EFA\u542F\u7528 epxShared\u3002\u5B83\u5C06\u516C\u5F00 core/component/utils/business/designer \u548C Vue \u5BFC\u5165\u8FDE\u63A5\u5230\u5BBF\u4E3B\u5171\u4EAB\u547D\u540D\u7A7A\u95F4\uFF0C\u907F\u514D\u91CD\u590D\u6253\u5305\u8FD0\u884C\u65F6\uFF1B\u4E0D\u652F\u6301\u7684\u6DF1\u8DEF\u5F84\u4F1A\u5728\u6784\u5EFA\u65F6\u62A5\u9519\u3002\u5BBF\u4E3B\u5FC5\u987B\u5B89\u88C5\u76F8\u540C\u7248\u672C\u7684\u5E73\u53F0\u5305\uFF0C\u5E76\u5148\u5B8C\u6210\u5BF9\u5E94\u7EC4\u4EF6\u7EC4\u7684\u52A0\u8F7D\u3002\u770B\u677F\u8FDC\u7A0B\u5171\u4EAB\u5165\u53E3\u5C1A\u672A\u63D0\u4F9B\uFF0C\u4F7F\u7528\u770B\u677F\u7684\u8FDC\u7A0B\u4EA7\u54C1\u5E94\u7531\u5BBF\u4E3B\u63D0\u4F9B\u6CE8\u518C\u7EC4\u4EF6\u5E76\u6838\u5BF9\u6784\u5EFA\u4F9D\u8D56\u3002
199
+
200
+ \u5E93\u5165\u53E3\u4FDD\u7559\u7EC4\u4EF6\u6536\u96C6\u3001install \u5E42\u7B49\u548C runtime: vue3\u3002\u65B0\u589E\u7EC4\u4EF6\u653E\u5165 src/__DIRNAME__/ \u5373\u81EA\u52A8\u6536\u96C6\uFF1B\u4EA7\u54C1\u81EA\u6709\u8DEF\u7531\u548C store \u6A21\u5757\u5E94\u5728 install(app) \u4E2D\u6CE8\u518C\uFF0C\u5E76\u786E\u4FDD\u91CD\u590D\u5B89\u88C5\u5B89\u5168\u3002
201
+
202
+ \u6309\u9700\u4EA7\u7269\u5FC5\u987B\u4E0A\u4F20\u6574\u4E2A lib/ \u76EE\u5F55\uFF0C\u5305\u62EC chunks\u3001shims\u3001index.manifest.json\u3001index.full.js \u548C\u6837\u5F0F\u3002\u5E73\u53F0 FM_SYSTEM_WEBPACK \u4ECD\u914D\u7F6E index.js / index.css URL\uFF0Cindex.deps.json \u4E0E\u5165\u53E3\u540C\u76EE\u5F55\u90E8\u7F72\u3002\u72EC\u7ACB\u5E94\u7528\u90E8\u7F72 dist/\u3002
203
+
204
+ ## \u5B58\u91CF\u4EA7\u54C1\u5347\u7EA7
205
+
206
+ \`\`\`sh
207
+ epxing migrate .
208
+ epxing migrate . --apply
209
+ epxing migrate . --transform-vue --to-vite --apply
210
+ # \u56FA\u5B9A\u5230\u5F53\u524D\u7248\u672C\uFF1Aepxing migrate . --packages-version __PACKAGES_VERSION__
211
+ \`\`\`
212
+
213
+ \u9ED8\u8BA4\u53EA\u8BFB\u9884\u89C8\uFF1B--apply \u8981\u6C42 Git \u5DE5\u4F5C\u6811\u5E72\u51C0\u3002\u5347\u7EA7\u4FDD\u7559\u4E1A\u52A1\u7EC4\u4EF6\u3001\u8DEF\u7531\u3001store \u548C\u81EA\u5B9A\u4E49\u914D\u7F6E\uFF0C\u53EA\u81EA\u52A8\u6539\u5199\u786E\u5B9A\u7684\u5BFC\u5165\u53CA\u5165\u53E3\u3002\u52A8\u6001\u53D6\u503C\u3001\u672A\u77E5\u65E7\u63A5\u53E3\u3001\u672A\u652F\u6301\u7684\u6E90\u7801\u8DEF\u5F84\u8FDB\u5165 MIGRATION-REPORT.md \u4EBA\u5DE5\u6E05\u5355\uFF1B\u5B58\u5728\u65E0\u6CD5\u5B8C\u6574\u5207\u6362\u7684\u65E7\u5165\u53E3\u65F6\uFF0C\u4E0D\u6DF7\u88C5\u4E24\u5957\u8FD0\u884C\u65F6\uFF0C\u5148\u4FDD\u7559\u65E7\u6A21\u5F0F\u5E76\u5B8C\u6210\u6E05\u5355\u518D\u5347\u7EA7\u3002
214
+
215
+ \u65E7 CLI \u751F\u6210\u7684\u8BA1\u6570\u6B22\u8FCE\u9875\uFF0C\u4EC5\u5728 src/main.js \u4E0E src/App.vue \u5747\u4FDD\u6301\u539F\u6837\u65F6\u81EA\u52A8\u4FEE\u590D\u4E3A\u5E73\u53F0\u8DEF\u7531\u5165\u53E3\u3002\u81EA\u5B9A\u4E49\u5165\u53E3\u4E0D\u8986\u76D6\uFF0C\u53EF\u6309\u4E0A\u9762\u7684\u5E94\u7528\u5165\u53E3\u793A\u4F8B\u624B\u52A8\u8C03\u6574\uFF1B\u65E7 App.vue \u4FDD\u7559\u4F46\u4E0D\u518D\u4F5C\u4E3A\u542F\u52A8\u5165\u53E3\u3002
216
+
217
+ Vue 2 \u8BED\u6CD5\u8F6C\u6362\u3001\u7B2C\u4E09\u65B9\u7EC4\u4EF6\u66FF\u6362\u3001\u65E5\u671F\u53C2\u6570\u3001\u4E3B\u9898\u548C\u6837\u5F0F\u9694\u79BB\u9700\u7ED3\u5408\u62A5\u544A\u590D\u6838\u3002\u6784\u5EFA\u901A\u8FC7\u540E\u4ECD\u9700\u5728\u771F\u5B9E\u540E\u7AEF\u9A8C\u6536\u767B\u5F55\u3001\u6743\u9650\u3001\u5217\u8868\u3001\u8868\u5355\u3001\u5F39\u5C42\u53CA\u5173\u952E\u6D41\u7A0B\u3002
218
+
219
+ ## \u66F4\u65B0\u7248\u672C
220
+
221
+ \`\`\`sh
222
+ npm install -g @epxing/cli@beta --registry https://registry.npmjs.org/
223
+ epxing --version
224
+ \`\`\`
225
+
226
+ \u6D4B\u8BD5\u7248\u4F7F\u7528 beta \u6807\u7B7E\uFF1B\u4EA7\u54C1\u5C06 @epxing \u5E73\u53F0\u5305\u56FA\u5B9A\u5728\u540C\u4E00\u5DF2\u9A8C\u8BC1\u7248\u672C\u3002CLI \u66F4\u65B0\u4E0D\u4F1A\u81EA\u52A8\u6539\u4EA7\u54C1\u4F9D\u8D56\uFF0C\u6309 migrate \u9884\u89C8\u3001\u5BA1\u9605\u3001\u5E94\u7528\u3001\u5B89\u88C5\u3001\u6784\u5EFA\u548C\u9A8C\u6536\u7684\u987A\u5E8F\u66F4\u65B0\u3002
227
+ `;export{c as a,a as b,l as c,d};