@epxing/cli 0.5.0-beta.12 → 0.5.0-beta.13

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.12`。导出名、子路径和签名从当前源码、package.json 与类型声明生成。
5
+ 本页对应包版本 `0.5.0-beta.13`。导出名、子路径和签名从当前源码、package.json 与类型声明生成。
6
6
 
7
7
  ## 安装与使用
8
8
 
9
9
 
10
10
  ```sh
11
- npm install -g @epxing/cli@0.5.0-beta.12
11
+ npm install -g @epxing/cli@0.5.0-beta.13
12
12
  ```
13
13
 
14
14
 
package/README.md CHANGED
@@ -4,7 +4,9 @@
4
4
 
5
5
  独立的工程开发工具,包含交互菜单、开发服务、产品库构建、创建、Vue3 迁移、静态检查和升级技能安装。创建和升级默认使用 `@epxing/*` 独立包,版本留空时查询最新 `beta` 并固定到具体版本,没有 `beta` 时使用 `latest`;可用 `--packages-version` 指定版本或标签。CLI 使用自己的版本号。创建和升级会生成产品使用说明;`@epxing/cli/vite` 提供产品构建插件,不依赖聚合包中的构建工具。
6
6
 
7
- 本批测试版本:`@epxing/cli@0.5.0-beta.12`,平台包 `5.3.0-beta.5`,均使用 npm 公网 `beta` 标签。CLI 与平台独立版本,本次不升级平台包。完整流程见文档站“CLI 创建、升级与产品使用”;各包公开 API 随安装包的 `API.md` 提供。
7
+ 本批测试版本:`@epxing/cli@0.5.0-beta.13`,平台包 `5.3.0-beta.5`,均使用 npm 公网 `beta` 标签。CLI 与平台独立版本,本次不升级平台包。完整流程见文档站“CLI 创建、升级与产品使用”;各包公开 API 随安装包的 `API.md` 提供。
8
+
9
+ `0.5.0-beta.13` 根据考核迁移报告补充插槽作用域、响应式状态、树刷新、异步依赖与移动布局复核。列表只读扫描新增同层插槽参数条件检测,覆盖解构、别名和局部变量遮蔽;模板解析失败非零退出,不自动改写业务条件。新增 F32–F34,明确历史报告对账和未定位问题的验收边界。
8
10
 
9
11
  `0.5.0-beta.12` 合并考核升级经验,随技能交付跨产品复核清单及列表插槽、拖拽、图标三个只读扫描脚本。模型与样式按组件复核,覆盖模板、JSX/render、包装与继承链;扫描零命中不能替代未覆盖场景验收。CLI 更新不会覆盖已有产品技能,更新前须比较并保留自定义内容;新建目录可运行 epxing skill install 安装完整技能。
10
12
 
@@ -31,6 +31,8 @@ Claude Code 项目技能放在 `.claude/skills/epxing-frontend-vue3-migrate/`,
31
31
 
32
32
  ## 共性问题复核入口
33
33
 
34
+ 重复故障优先检查 F32–F34:同层插槽条件读取局部参数、树刷新后的旧引用、响应式业务状态误迁、异步依赖未就绪及移动滚动。对状态查询验证不同返回顺序和失败反馈;对报告区分历史扫描候选、已修未验和已验,未定位的业务症状不得归入“已修复”。
35
+
34
36
  每次升级先读 [跨产品升级复核](references/upgrade-review.md),在迁移前、源码转换后和交付前执行其中的复核。模型协议与样式是每个组件的必检项,覆盖模板、JSX/render、包装组件及继承链;沿用 E2 台账记录实际协议、来源、结论和证据。修复一处后检查同类结构,不能只修用户点出的页面。只读扫描不覆盖的模型、动态样式和运行分支必须另行核实,构建成功或扫描零命中不能关闭这些检查。
35
37
 
36
38
  ## 先判断升级类型
@@ -748,6 +748,28 @@ vuedraggable 等第三方库升级 major 后,核对模板与 JSX 的实际插
748
748
 
749
749
  有升级前 Git 基线时,运行 `node <本技能目录>/scripts/check-icon-migration.cjs <前端工程根目录> <升级前Git引用>`。脚本只读比较模板图标的顺序、指令和参数,接受事件移动到祖先按钮;无法对齐的结构变化列为人工项,不自动恢复旧代码。结果只覆盖模板静态图标,JSX、动态图标、普通属性与 CSS 仍需复核。按原始图标类和按钮状态检查最终选择器,避免图标换成 SVG 后 hover/隐藏样式失效。回归点击入口本身,验证实际打开、选中回显、关闭、原记录 ID、上下文参数及事件冒泡;仅测试方法存在不足以发现失接线。
750
750
 
751
+ ### F32. 同层插槽条件访问尚未声明的局部参数
752
+
753
+ `<template #default="scope" v-if="scope.row.data">` 中,外层条件不能使用该插槽才声明的参数;`#cell="{ row: item }"` 配合 `v-if="item.data"` 同样需要检查,不能只搜索 scope。将依赖局部参数的判断放入插槽内部,保留父行/叶子行、编辑/查看及相邻 if/else-if/else 的完整语义。外层条件只引用组件状态时可以保留,不全局移动所有带插槽的条件。
754
+
755
+ 运行 `scripts/check-list-slots.cjs` 检查模板 AST 中同层条件与绑定参数的引用关系。脚本只读,解析不确定项报告复核,不自动改写条件链。修复一处后扫描全部模板,沿同基类和复制组件扩查;验收应从真实表格验证父行、叶子行、空值、编辑模型与原记录 ID,不能加空 scope 或删除业务条件来隐藏错误。
756
+
757
+ 命中同名引用仍是候选:若组件外层确有同名状态,先确认条件究竟读取它还是误用了插槽局部参数,不能机械移动后改变条件含义。
758
+
759
+ ### F33. 响应式状态、树刷新与异步依赖未形成完整闭环
760
+
761
+ 按 F24 区分组件旧 filters 选项和 data.filters 等业务状态;实例所读写的状态须在 data/props/computed 等公开响应式入口声明,不能将数组或对象误迁到 methods。模式切换后清理旧显示分支,按当前模式消费响应;请求可能交错返回时,验证旧请求不会覆盖新上下文,不把所有 watcher 扩大为无差别深度监听。
762
+
763
+ 树数据整体刷新后,旧节点引用不再代表新数据。按稳定业务 ID 在新树中恢复有效选中;选中项消失或树为空时,清除关联列表、指标、详情和依赖旧节点的操作入口。核对 rowKey 的真实唯一性、展开/收起和选择回写,不用名称去重或字符串缩进冒充真实树关系。
764
+
765
+ 对依赖多次异步初始化的状态查询,列清每个必需参数的来源及就绪条件,分别验证 A 先返回、B 先返回、空结果、失败与上下文切换。失败不能继续展示初始成功/已提交值,也不能强制设为未提交来显示按钮;按实际协议区分未加载、加载成功和加载失败,保留权限及业务筛选。具体业务接口的参数名不可推广成所有请求都必传。
766
+
767
+ ### F34. 移动布局与报告结论必须按实际场景验收
768
+
769
+ 按 F15/F30 检查继承及 render/插槽链的实际根和 scopeId;移动页尤其核对 flex 收缩、min-width/min-height、横纵滚动、底栏自然高度与安全区。抽屉内部避免用 100vw 假定其等于容器宽度;宽表、长名称与按钮换行应按真实容器验证。只在确认当前作用域失配后修复,保留专属命名空间和外部隔离,不套用其他产品的固定高度、像素或整块删除 scoped。
770
+
771
+ 源码、组件/浏览器夹具、最终制品及目标宿主分别记结果。工具初始报告中的未勾选项须与后续修复和验证逐项对账,不能直接把历史清单当作当前缺陷,也不能因本地构建成功整体勾选。报告乱码、缺失请求或未复现入口不构成根因证据;待定位问题保留症状、已知证据、缺少条件与下一步,不能变成共性自动修法。
772
+
751
773
  ## G. 产品升级的跨会话缺陷回归
752
774
 
753
775
  本节从近期产品故障的提交及交接记录提炼检查场景,补充 E2 的逐组件主题验收。历史记录证明曾出现过这些问题,不证明当前目标环境已发布修复;其中只有临时浏览器实验、单测或尚待现场验证的结论,不能提升为已部署通过。具体来源及证据层次保留在平台仓 `docs/handoff/tasks/` 的原任务中,技能只保留可复用检查方法。
@@ -21,6 +21,8 @@
21
21
 
22
22
  ## 模型与样式的逐组件必检项
23
23
 
24
+ 新增重点:按 [F32](../pitfalls.md#f32-同层插槽条件访问尚未声明的局部参数) 检查插槽参数与条件的词法作用域;按 F33 验证树刷新后的选中引用、业务响应式状态及依赖请求的不同返回顺序;按 F34 对账历史报告与实际证据,并检查移动滚动和底栏。以上是共性检查,不复制具体产品的参数、状态默认值或布局尺寸。
25
+
24
26
  以下项目并入现有 E2 台账,不另建一份互相脱节的清单。没有发现问题也须留下检查依据;确实没有模型或样式的组件注明原因,不靠组件名称或继承关系免检。
25
27
 
26
28
  | 复核项 | 必须追踪的链路 | 关闭条件 |
@@ -73,7 +75,7 @@ node <技能目录>/scripts/check-icon-migration.cjs <前端工程根目录> <
73
75
 
74
76
  | 脚本 | 覆盖 | 退出码与边界 |
75
77
  | --- | --- | --- |
76
- | check-list-slots | render 方法中的旧 scopedSlots、列渲染函数属性展开(含条件)、表格旧 props 包装、模板/JSX 静态绑定到本组件方法的样式回调字符串返回 | 0:无此类候选;1:有候选。不能覆盖全部模板插槽、对象属性函数、动态别名、h 第三参或运行时元数据 |
78
+ | check-list-slots | 同层 v-slot 与 if/else-if 对插槽参数的引用(含解构和别名);render 旧 scopedSlots、列渲染函数展开、表格旧 props 包装及静态绑定的表格样式回调字符串返回 | 0:无此类候选;1:有候选或插槽表达式需复核。不自动改条件链;对象属性函数、动态别名、h 第三参及运行时元数据继续审阅 |
77
79
  | check-draggable-slots | 模板 vuedraggable 导入别名、直接 item 插槽、item-key;纯 JSX 标为复核 | 0:已扫描项无候选;1:明确缺项;2:需人工复核。JSX 和动态插槽继续验证 |
78
80
  | check-icon-migration | 对比升级前模板的静态图标顺序、事件/参数/修饰符和条件,接受事件移动到祖先按钮 | 0:未发现保留差异;1:候选或无法对齐。新增图标、结构调整需要人工判断;普通属性、CSS、JSX 另查 |
79
81
 
@@ -22,9 +22,31 @@ function hasRenderer(node) {
22
22
  }
23
23
  for (const file of walk(path.join(root, 'src')).filter(f => /\.(vue|[cm]?[jt]sx?)$/.test(f))) {
24
24
  const source = fs.readFileSync(file, 'utf8')
25
- const descriptor = file.endsWith('.vue') ? parse(source).descriptor : null
25
+ const parsed = file.endsWith('.vue') ? parse(source) : null
26
+ if (parsed?.errors.length) throw new Error(file + ':Vue 文件解析失败:' + parsed.errors.map(error => error.message || error).join('; '))
27
+ const descriptor = parsed?.descriptor || null
26
28
  const styleCallbacks = new Set()
27
29
  function templateBindings(node) {
30
+ if (node.type === 1) {
31
+ const slot = node.props.find(p => p.type === 7 && p.name === 'slot' && p.exp)
32
+ const condition = node.props.find(p => p.type === 7 && ['if', 'else-if'].includes(p.name) && p.exp)
33
+ if (slot && condition) {
34
+ const location = { file: path.relative(root, file), line: condition.loc.start.line }
35
+ try {
36
+ const options = { configFile: false, babelrc: false, parserOpts: { plugins: ['typescript'] } }
37
+ const parameters = babel.parseSync(`(${slot.exp.content}) => 0`, options).program.body[0].expression.params
38
+ const names = new Set(parameters.flatMap(param => Object.keys(t.getBindingIdentifiers(param))))
39
+ const expression = babel.parseSync(`(${condition.exp.content})`, options)
40
+ const referenced = new Set()
41
+ babel.traverse(expression, { ReferencedIdentifier(p) {
42
+ if (names.has(p.node.name) && !p.scope.hasBinding(p.node.name)) referenced.add(p.node.name)
43
+ } })
44
+ if (referenced.size) findings.push({ ...location, reason: '同层插槽条件与局部参数同名引用:' + [...referenced].join(', ') + ';核对外层同名状态,若依赖插槽参数则将条件移入内部并保留完整 else 链' })
45
+ } catch (error) {
46
+ findings.push({ ...location, reason: '插槽参数或条件无法静态解析,需复核作用域:' + error.message })
47
+ }
48
+ }
49
+ }
28
50
  if (node.type === 1 && node.tag === 'el-table') for (const p of node.props) {
29
51
  if (p.type === 7 && p.name === 'bind' && tableStyles.has(p.arg?.content) && /^[\w$]+$/.test(p.exp?.content || '')) styleCallbacks.add(p.exp.content)
30
52
  }
@@ -69,5 +91,5 @@ for (const file of walk(path.join(root, 'src')).filter(f => /\.(vue|[cm]?[jt]sx?
69
91
  })
70
92
  }
71
93
  }
72
- console.log(JSON.stringify({ files, columns, findings, scope: 'script slots/props and statically bound table-style callbacks; aliases, h() consumers and runtime metadata require review' }, null, 2))
94
+ console.log(JSON.stringify({ files, columns, findings, scope: '同层插槽参数条件、script 插槽/props、静态绑定的表格样式回调;别名、h() 消费方与运行时元数据仍需复核' }, null, 2))
73
95
  process.exitCode = findings.length ? 1 : 0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@epxing/cli",
3
- "version": "0.5.0-beta.12",
3
+ "version": "0.5.0-beta.13",
4
4
  "description": "EPX 交互式工程开发、服务启动、构建、Vue3 迁移及技能安装工具",
5
5
  "type": "module",
6
6
  "bin": {