@proteus-vue/component-ir 0.1.0 → 0.2.0-beta.1
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/LICENSE +218 -0
- package/README.md +1 -1
- package/dist/audit.d.ts +22 -0
- package/dist/conformance.d.ts +12 -3
- package/dist/degradation.d.ts +115 -0
- package/dist/index.d.ts +8 -3
- package/dist/index.js +1316 -85
- package/dist/map.d.ts +1 -1
- package/dist/mp-spec-coverage.d.ts +106 -0
- package/dist/primitives.d.ts +2 -2
- package/dist/schema.d.ts +43 -2
- package/package.json +5 -5
package/dist/index.js
CHANGED
|
@@ -17,6 +17,9 @@ var SEMANTIC_ENUM = [
|
|
|
17
17
|
"layout.split",
|
|
18
18
|
"layout.safe",
|
|
19
19
|
"layout.sidebar",
|
|
20
|
+
// ★#405 语义登记批:组件库扩展组件(Fluid S1-S4 + 工程兜底,语义层待 L2 落地——G-31.4 降级 planned)
|
|
21
|
+
"layout.aspect",
|
|
22
|
+
"layout.zone",
|
|
20
23
|
// —— 基础 UI 原语(G-32 ② UI 18 + 既有按钮)——
|
|
21
24
|
"ui.text",
|
|
22
25
|
"ui.heading",
|
|
@@ -41,6 +44,17 @@ var SEMANTIC_ENUM = [
|
|
|
41
44
|
// ★G-31 B4:既有组件对齐(p-list-view/p-nav-bar)
|
|
42
45
|
"ui.list",
|
|
43
46
|
"ui.nav",
|
|
47
|
+
// ★#405 语义登记批:反馈/状态类组件
|
|
48
|
+
"ui.loading",
|
|
49
|
+
"ui.scale",
|
|
50
|
+
"ui.skeleton",
|
|
51
|
+
// ★能力颗粒度对齐 C2:进度条 / 表单标签(对齐小程序 <progress> / <label>)
|
|
52
|
+
"ui.progress",
|
|
53
|
+
"ui.label",
|
|
54
|
+
// ★权威标尺批 H:局部文本选区(对齐小程序 <selection>)
|
|
55
|
+
"ui.selection",
|
|
56
|
+
// ★权威标尺批 I:相机(对齐小程序 <camera>)
|
|
57
|
+
"ui.camera",
|
|
44
58
|
// —— 容器/导航原语(G-32 ③ Shell 10)——
|
|
45
59
|
"shell.page",
|
|
46
60
|
"shell.nav",
|
|
@@ -51,17 +65,35 @@ var SEMANTIC_ENUM = [
|
|
|
51
65
|
"shell.popover",
|
|
52
66
|
"shell.toast",
|
|
53
67
|
"shell.action-sheet",
|
|
68
|
+
// ★#405 语义登记批:弹层/工具栏组件
|
|
69
|
+
"shell.mask",
|
|
70
|
+
"shell.popup",
|
|
71
|
+
"shell.toolbar",
|
|
72
|
+
// ★能力颗粒度对齐 C2:页面容器(对齐小程序 <page-container>)
|
|
73
|
+
"shell.page-container",
|
|
74
|
+
// ★权威标尺批 H:键盘上方工具栏(对齐小程序 <keyboard-accessory>)
|
|
75
|
+
"shell.keyboard-accessory",
|
|
76
|
+
// ★权威标尺批 J:内嵌网页 / 广告位(对齐小程序 <web-view>/<ad>)
|
|
77
|
+
"shell.webview",
|
|
78
|
+
"shell.ad",
|
|
79
|
+
// ★权威标尺批 J:地图(对齐小程序 <map>)
|
|
80
|
+
"ui.map",
|
|
54
81
|
// —— 交互/手势原语(G-32 ④ Gesture——组件形态 2 个;v-gesture: 指令归绑定层不产生 C-IR 节点)——
|
|
55
82
|
"gesture.draggable",
|
|
56
83
|
"gesture.scrollable",
|
|
57
|
-
// —— 工程原语(G-32 ⑥ Engineering——组件形态 3
|
|
84
|
+
// —— 工程原语(G-32 ⑥ Engineering——组件形态 3 个 + ★#405 错误兑底;Hook/路由方法归 API 层不产生 C-IR 节点)——
|
|
58
85
|
"engineering.router-link",
|
|
59
86
|
"engineering.transition",
|
|
60
87
|
"engineering.animate",
|
|
88
|
+
"engineering.error-boundary",
|
|
89
|
+
"engineering.share-element",
|
|
61
90
|
// —— 能力入口(G-28 组件化:p-* 能力入口组件;useXxx Hook 归 API 层不产生 C-IR 节点)——
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
91
|
+
// ★2026-09-18 语义去重:原列 'capability.scan-qr' / 'capability.pick-photo' 为**重复名**,
|
|
92
|
+
// 已退役改为真实能力(组件的实现分别调用 useQRCode() / useCamera(),即 C42 / C1)——
|
|
93
|
+
// 本枚举收录的是「能作为 C-IR 节点出现的语义」,故此处列真实能力名(E8 双形态先例同源)。
|
|
94
|
+
"capability.location",
|
|
95
|
+
"capability.qr-code",
|
|
96
|
+
"capability.camera"
|
|
65
97
|
];
|
|
66
98
|
var COMPONENT_IR_SCHEMA = {
|
|
67
99
|
$schema: "https://json-schema.org/draft/2020-12/schema",
|
|
@@ -84,7 +116,7 @@ var TAG_SEMANTIC_MAP = {
|
|
|
84
116
|
"p-inline": "layout.inline",
|
|
85
117
|
"p-stack": "layout.stack",
|
|
86
118
|
"p-grid": "layout.grid",
|
|
87
|
-
|
|
119
|
+
// ★Skyline 线收口:'p-fluid' 移除——layout.fluid 是 v-p-fluid **指令**语义(非标签),登记为标签会让 <p-fluid> 静默不渲染
|
|
88
120
|
"p-adaptive": "layout.adaptive",
|
|
89
121
|
"p-fit": "layout.fit",
|
|
90
122
|
"p-spacer": "layout.spacer",
|
|
@@ -133,11 +165,17 @@ var TAG_SEMANTIC_MAP = {
|
|
|
133
165
|
// ★E18 组件形态(p- 前缀产 C-IR)
|
|
134
166
|
"router-link": "engineering.router-link",
|
|
135
167
|
// ★兼容别名(Vue Router 风格 <router-link> 标签;非 catalog 条目——p-view 先例 G-31 B4)
|
|
168
|
+
"p-share-element": "engineering.share-element",
|
|
169
|
+
// ★批次 8:页面间共享元素转场(≠ p-transition 页内过渡)
|
|
136
170
|
"p-transition": "engineering.transition",
|
|
137
171
|
"p-animate": "engineering.animate",
|
|
138
172
|
// G-31 能力入口
|
|
139
|
-
|
|
140
|
-
|
|
173
|
+
// ★2026-09-18 语义去重:原 capability.scan-qr / capability.pick-photo 是**重复名**——
|
|
174
|
+
// 两个组件的实现分别调用 useQRCode() / useCamera(),对应真实能力即 C42 capability.qr-code /
|
|
175
|
+
// C1 capability.camera(其 mpEquiv 与 hook 完全一致)。故**退役重复名、重指向真实能力**,
|
|
176
|
+
// 并按 E8 双形态在两行补 tag(而非新建语义)。
|
|
177
|
+
"p-scan-qr": "capability.qr-code",
|
|
178
|
+
"p-pick-photo": "capability.camera",
|
|
141
179
|
"p-location": "capability.location",
|
|
142
180
|
// ★G-31 B4 现有组件对齐(src/components 实际标签 → L1 语义)
|
|
143
181
|
"p-view": "layout.box",
|
|
@@ -146,7 +184,54 @@ var TAG_SEMANTIC_MAP = {
|
|
|
146
184
|
"p-nav-bar": "ui.nav",
|
|
147
185
|
// ★G-31 B4 Fluid 体系扩展语义(有明确系统原生对应——原则 #10.8)
|
|
148
186
|
"p-safe": "layout.safe",
|
|
149
|
-
"p-sidebar": "layout.sidebar"
|
|
187
|
+
"p-sidebar": "layout.sidebar",
|
|
188
|
+
// ★#405 语义登记批:剩余 10 组件全量入图(EXTRA_KIND 文档兑底退役)——
|
|
189
|
+
// 9 个新语义(catalog planned L2:语义层待多端映射)+ p-scroll-view 复用 layout.scroll
|
|
190
|
+
// (★2026-09-18 修正原文「p-view 先例」:显式 multi-tag 别名先例是上一行的 `router-link`
|
|
191
|
+
// ——同一语义由两个标签提供;本条与 p-view 是并列的别名情形,非「先例」关系)
|
|
192
|
+
"p-aspect": "layout.aspect",
|
|
193
|
+
"p-zone": "layout.zone",
|
|
194
|
+
"p-loading": "ui.loading",
|
|
195
|
+
"p-scale": "ui.scale",
|
|
196
|
+
"p-skeleton": "ui.skeleton",
|
|
197
|
+
"p-mask": "shell.mask",
|
|
198
|
+
"p-popup": "shell.popup",
|
|
199
|
+
"p-toolbar": "shell.toolbar",
|
|
200
|
+
"p-scroll-view": "layout.scroll",
|
|
201
|
+
// 滚动容器 = p-scroll 角色
|
|
202
|
+
"p-error-boundary": "engineering.error-boundary",
|
|
203
|
+
// E8 原语组件形态(useErrorBoundary API 形态并存)
|
|
204
|
+
// ★能力颗粒度对齐 C2:新增真实组件
|
|
205
|
+
"p-progress": "ui.progress",
|
|
206
|
+
"p-label": "ui.label",
|
|
207
|
+
"p-page-container": "shell.page-container",
|
|
208
|
+
// ★权威标尺批 H:选区 / 键盘工具栏
|
|
209
|
+
"p-selection": "ui.selection",
|
|
210
|
+
"p-keyboard-accessory": "shell.keyboard-accessory",
|
|
211
|
+
// ★权威标尺批 I:相机
|
|
212
|
+
"p-camera": "ui.camera",
|
|
213
|
+
// ★权威标尺批 J:内嵌网页 / 广告位
|
|
214
|
+
"p-webview": "shell.webview",
|
|
215
|
+
"p-ad": "shell.ad",
|
|
216
|
+
"p-map": "ui.map"
|
|
217
|
+
};
|
|
218
|
+
var FRAMEWORK_INTERNAL_TAGS = /* @__PURE__ */ new Set(["p-svg-canvas"]);
|
|
219
|
+
var TAG_SEMANTIC_ALIASES = {
|
|
220
|
+
"layout.box": {
|
|
221
|
+
canonical: "p-view",
|
|
222
|
+
aliases: ["p-box"],
|
|
223
|
+
reason: "p-view \u4E3A\u7AEF\u5BF9\u9F50\u4EA7\u7269\uFF08\u5BF9\u9F50\u5B98\u65B9 <view> \u6309\u538B\u53CD\u9988 4 \u5C5E\u6027\u3001\u6A21\u677F\u7528 <view> \u8D70 Web \u6A21\u62DF\u5C42\uFF09\u4E14\u5B9E\u9645\u88AB\u5F15\u7528\uFF1Bp-box \u4E3A G-32 L1 \u8840\u7EDF\uFF08aspectRatio/overflow \u4E24\u4E2A\u8BED\u4E49\u5C5E\u6027\uFF0C\u5F53\u524D\u96F6\u6E90\u7801\u5F15\u7528\uFF09\u2014\u2014\u4FDD\u7559\u4E3A\u517C\u5BB9\u522B\u540D\u4E0D\u5220\u3002\u2605\u6CE8\uFF1Acatalog L1 \u884C\u7684 props \u662F\u4E24\u8005\u7684\u5E76\u96C6\uFF0C\u5C5E\u300C\u610F\u56FE\u58F0\u660E\u300D\uFF0C\u4E0E\u4E24\u5B9E\u73B0\u5747\u4E0D\u5B8C\u5168\u4E00\u81F4\uFF08\u89C1 audit C8 \u62AB\u9732\uFF09\u3002"
|
|
224
|
+
},
|
|
225
|
+
"layout.scroll": {
|
|
226
|
+
canonical: "p-scroll-view",
|
|
227
|
+
aliases: ["p-scroll"],
|
|
228
|
+
reason: "p-scroll-view \u4E3A\u7AEF\u5BF9\u9F50\u4EA7\u7269\uFF08\u900F\u4F20\u5B98\u65B9 <scroll-view> \u5168\u91CF\u5C5E\u6027\uFF1Ascroll-into-view/upper-threshold/refresher \u5168\u5BB6\u6876/enhanced \u7B49\uFF09\uFF1Bp-scroll \u4E3A G-32 L10 \u8840\u7EDF\uFF08axis/paging/refresh/indicator \u8BED\u4E49\u5C5E\u6027\uFF09\u3002\u2605\u6CE8\uFF1Acatalog L10 \u884C props \u540C\u4E3A\u4E24\u8005\u5E76\u96C6\u3002"
|
|
229
|
+
},
|
|
230
|
+
"engineering.router-link": {
|
|
231
|
+
canonical: "p-router-link",
|
|
232
|
+
aliases: ["router-link"],
|
|
233
|
+
reason: "router-link \u662F Vue Router \u98CE\u683C\u6807\u7B7E\u517C\u5BB9\u522B\u540D\uFF08framework \u4FDD\u7559\u5B57\uFF0C\u975E catalog \u6761\u76EE\uFF09\u3002"
|
|
234
|
+
}
|
|
150
235
|
};
|
|
151
236
|
|
|
152
237
|
// src/validate.ts
|
|
@@ -247,7 +332,7 @@ var SEMANTIC_BACKEND_MAP = {
|
|
|
247
332
|
},
|
|
248
333
|
"layout.fluid": {
|
|
249
334
|
"vue-dom": "div.proteus-fluid",
|
|
250
|
-
"native-ios": "
|
|
335
|
+
"native-ios": "UIView.fluid",
|
|
251
336
|
"native-android": "ConstraintLayout",
|
|
252
337
|
"native-harmony": "Flex.fluid",
|
|
253
338
|
skyline: "view.fluid",
|
|
@@ -266,7 +351,7 @@ var SEMANTIC_BACKEND_MAP = {
|
|
|
266
351
|
},
|
|
267
352
|
"layout.fit": {
|
|
268
353
|
"vue-dom": "div.proteus-fit",
|
|
269
|
-
"native-ios": "
|
|
354
|
+
"native-ios": "UIView.fit",
|
|
270
355
|
"native-android": "wrapContent",
|
|
271
356
|
"native-harmony": "fitContent",
|
|
272
357
|
skyline: "view.fit",
|
|
@@ -357,7 +442,9 @@ var SEMANTIC_BACKEND_MAP = {
|
|
|
357
442
|
headless: "nav"
|
|
358
443
|
},
|
|
359
444
|
// —— 能力入口(G-28 组件化)——
|
|
360
|
-
|
|
445
|
+
// ★2026-09-18 语义去重:原键 capability.scan-qr 为重复名(组件的实现调用 useQRCode(),
|
|
446
|
+
// 真实能力即 C42 capability.qr-code)——键已迁移,7 端渲染映射原样保留。
|
|
447
|
+
"capability.qr-code": {
|
|
361
448
|
"vue-dom": "button.proteus-scan-qr",
|
|
362
449
|
"native-ios": "AVCaptureSession",
|
|
363
450
|
"native-android": "CameraX",
|
|
@@ -366,7 +453,9 @@ var SEMANTIC_BACKEND_MAP = {
|
|
|
366
453
|
flutter: "scanQR",
|
|
367
454
|
headless: "scan-qr"
|
|
368
455
|
},
|
|
369
|
-
|
|
456
|
+
// ★2026-09-18 语义去重:原键 capability.pick-photo 为重复名(组件实现调用 useCamera(),
|
|
457
|
+
// 真实能力即 C1 capability.camera)——键已迁移,映射原样保留。
|
|
458
|
+
"capability.camera": {
|
|
370
459
|
"vue-dom": "input.proteus-pick-photo",
|
|
371
460
|
"native-ios": "UIImagePicker",
|
|
372
461
|
"native-android": "PhotoPicker",
|
|
@@ -670,6 +759,44 @@ var SEMANTIC_BACKEND_MAP = {
|
|
|
670
759
|
headless: "form"
|
|
671
760
|
},
|
|
672
761
|
// ★G-32 B4 ④ Gesture 组件形态(drag/scrollable——指令/useGesture 属绑定层不产渲染节点)
|
|
762
|
+
// ★2026-09-18:tap / longpress 补映射——`v-gesture:tap|longpress` 已有**双端原生对等**
|
|
763
|
+
// (MP 映射 bindtap/bindlongpress;Web 走 Pointer 识别器),故由 planned 转 implemented。
|
|
764
|
+
// ★其余手势(swipe/pan/pinch/rotate/press)**刻意不补**:MP 端无事件对等
|
|
765
|
+
// (官方用 worklet 手势处理器<组件>,框架未生成)→ 保持 planned(诚实边界,不凑端数)。
|
|
766
|
+
"gesture.tap": {
|
|
767
|
+
"vue-dom": "v-gesture:tap\uFF08Pointer \u8BC6\u522B\u5668\uFF09",
|
|
768
|
+
"native-ios": "UITapGestureRecognizer",
|
|
769
|
+
"native-android": "GestureDetector.onSingleTapUp",
|
|
770
|
+
"native-harmony": "TapGesture",
|
|
771
|
+
skyline: "bindtap",
|
|
772
|
+
// MP 原生事件(编译器 v-gesture:tap → bindtap,2026-09-18)
|
|
773
|
+
flutter: "GestureDetector.onTap",
|
|
774
|
+
headless: "tap"
|
|
775
|
+
},
|
|
776
|
+
"gesture.longpress": {
|
|
777
|
+
"vue-dom": "v-gesture:longpress\uFF08Pointer \u8BC6\u522B\u5668\uFF09",
|
|
778
|
+
"native-ios": "UILongPressGestureRecognizer",
|
|
779
|
+
"native-android": "GestureDetector.onLongPress",
|
|
780
|
+
"native-harmony": "LongPressGesture",
|
|
781
|
+
skyline: "bindlongpress",
|
|
782
|
+
// MP 原生事件(编译器 v-gesture:longpress → bindlongpress,2026-09-18)
|
|
783
|
+
flutter: "GestureDetector.onLongPress",
|
|
784
|
+
headless: "longpress"
|
|
785
|
+
},
|
|
786
|
+
// ★批次 8:共享元素转场(页面间)——各端系统级转场能力
|
|
787
|
+
"engineering.share-element": {
|
|
788
|
+
"vue-dom": "div.proteus-share-element",
|
|
789
|
+
// Web 无宿主共享元素转场 → 普通容器(降级,不飞)
|
|
790
|
+
"native-ios": "UIView.matchedTransition",
|
|
791
|
+
"native-android": "SharedElementTransition",
|
|
792
|
+
"native-harmony": "geometryTransition",
|
|
793
|
+
// ArkUI 几何过渡
|
|
794
|
+
skyline: "share-element",
|
|
795
|
+
// 微信原生(宿主跨页飞行)
|
|
796
|
+
flutter: "Hero",
|
|
797
|
+
// Flutter Hero 动画即共享元素
|
|
798
|
+
headless: "share-element"
|
|
799
|
+
},
|
|
673
800
|
"gesture.draggable": {
|
|
674
801
|
"vue-dom": "div.proteus-draggable",
|
|
675
802
|
"native-ios": "UIPanGestureRecognizer",
|
|
@@ -727,6 +854,105 @@ var SEMANTIC_BACKEND_MAP = {
|
|
|
727
854
|
// Skyline animation CSS
|
|
728
855
|
flutter: "AnimationController",
|
|
729
856
|
headless: "animate"
|
|
857
|
+
},
|
|
858
|
+
// ★能力颗粒度对齐 C2:进度条 / 表单标签 / 页面容器(对齐小程序 <progress>/<label>/<page-container>)
|
|
859
|
+
"ui.progress": {
|
|
860
|
+
"vue-dom": "div.proteus-progress",
|
|
861
|
+
"native-ios": "UIProgressView",
|
|
862
|
+
"native-android": "ProgressBar",
|
|
863
|
+
"native-harmony": "Progress",
|
|
864
|
+
skyline: "progress",
|
|
865
|
+
// 微信原生 <progress>
|
|
866
|
+
flutter: "LinearProgressIndicator",
|
|
867
|
+
headless: "progress"
|
|
868
|
+
},
|
|
869
|
+
"ui.label": {
|
|
870
|
+
"vue-dom": "label",
|
|
871
|
+
"native-ios": "UILabel.label",
|
|
872
|
+
"native-android": "TextView.label",
|
|
873
|
+
"native-harmony": "Text.label",
|
|
874
|
+
skyline: "label",
|
|
875
|
+
// 微信原生 <label>(for 关联控件)
|
|
876
|
+
flutter: "Text.label",
|
|
877
|
+
headless: "label"
|
|
878
|
+
},
|
|
879
|
+
"shell.page-container": {
|
|
880
|
+
"vue-dom": "div.proteus-page-container",
|
|
881
|
+
"native-ios": "UIPresentationController",
|
|
882
|
+
"native-android": "BottomSheetDialog",
|
|
883
|
+
"native-harmony": "bindSheet",
|
|
884
|
+
skyline: "page-container",
|
|
885
|
+
// 微信原生 <page-container>
|
|
886
|
+
flutter: "showModalBottomSheet",
|
|
887
|
+
headless: "page-container"
|
|
888
|
+
},
|
|
889
|
+
// ★权威标尺批 H:局部文本选区 / 键盘上方工具栏(对齐小程序 <selection>/<keyboard-accessory>)
|
|
890
|
+
"ui.selection": {
|
|
891
|
+
"vue-dom": "div.proteus-selection",
|
|
892
|
+
"native-ios": "UITextView.selection",
|
|
893
|
+
"native-android": "TextView.selection",
|
|
894
|
+
"native-harmony": "Text.selection",
|
|
895
|
+
skyline: "selection",
|
|
896
|
+
// 微信原生 <selection>
|
|
897
|
+
flutter: "SelectableText",
|
|
898
|
+
headless: "selection"
|
|
899
|
+
},
|
|
900
|
+
"shell.keyboard-accessory": {
|
|
901
|
+
"vue-dom": "div.proteus-keyboard-accessory",
|
|
902
|
+
"native-ios": "UIInputView",
|
|
903
|
+
"native-android": "InputMethodService.accessory",
|
|
904
|
+
"native-harmony": "KeyboardAccessory",
|
|
905
|
+
skyline: "keyboard-accessory",
|
|
906
|
+
// 微信原生 <keyboard-accessory>
|
|
907
|
+
flutter: "KeyboardAccessoryView",
|
|
908
|
+
headless: "keyboard-accessory"
|
|
909
|
+
},
|
|
910
|
+
// ★权威标尺批 I:相机(对齐小程序 <camera>)
|
|
911
|
+
"ui.camera": {
|
|
912
|
+
"vue-dom": "video.proteus-camera",
|
|
913
|
+
// Web getUserMedia + <video> 预览
|
|
914
|
+
"native-ios": "AVCaptureVideoPreviewLayer",
|
|
915
|
+
"native-android": "CameraX.PreviewView",
|
|
916
|
+
"native-harmony": "XComponent.camera",
|
|
917
|
+
skyline: "camera",
|
|
918
|
+
// 微信原生 <camera>
|
|
919
|
+
flutter: "CameraPreview",
|
|
920
|
+
headless: "camera"
|
|
921
|
+
},
|
|
922
|
+
// ★权威标尺批 J:内嵌网页 / 广告位(对齐小程序 <web-view>/<ad>)
|
|
923
|
+
"shell.webview": {
|
|
924
|
+
"vue-dom": "div.proteus-webview",
|
|
925
|
+
// Web iframe 运行时注入
|
|
926
|
+
"native-ios": "WKWebView",
|
|
927
|
+
"native-android": "WebView",
|
|
928
|
+
"native-harmony": "Web",
|
|
929
|
+
skyline: "web-view",
|
|
930
|
+
// 微信原生 <web-view>
|
|
931
|
+
flutter: "WebView",
|
|
932
|
+
headless: "webview"
|
|
933
|
+
},
|
|
934
|
+
"shell.ad": {
|
|
935
|
+
"vue-dom": "div.proteus-ad",
|
|
936
|
+
// Web 占位容器(无广告联盟标准)
|
|
937
|
+
"native-ios": "UIView.ad",
|
|
938
|
+
"native-android": "View.ad",
|
|
939
|
+
"native-harmony": "AdSlot",
|
|
940
|
+
skyline: "ad",
|
|
941
|
+
// 微信原生 <ad>
|
|
942
|
+
flutter: "AdWidget",
|
|
943
|
+
headless: "ad"
|
|
944
|
+
},
|
|
945
|
+
// ★权威标尺批 J:地图(对齐小程序 <map>)
|
|
946
|
+
"ui.map": {
|
|
947
|
+
"vue-dom": "div.proteus-map",
|
|
948
|
+
// Web 宿主槽位(接入高德/Google/Mapbox)
|
|
949
|
+
"native-ios": "MKMapView",
|
|
950
|
+
"native-android": "MapView",
|
|
951
|
+
"native-harmony": "MapComponent",
|
|
952
|
+
skyline: "map",
|
|
953
|
+
// 微信原生 <map>
|
|
954
|
+
flutter: "GoogleMap",
|
|
955
|
+
headless: "map"
|
|
730
956
|
}
|
|
731
957
|
};
|
|
732
958
|
function mapSemanticToBackend(semantic, backendId) {
|
|
@@ -753,28 +979,35 @@ function toComponentTree(tag, props = {}, children = []) {
|
|
|
753
979
|
|
|
754
980
|
// src/primitives.ts
|
|
755
981
|
var LAYOUT = [
|
|
756
|
-
{ id: "L1", kind: "layout", semantic: "layout.box", tag: "p-box", props: ["aspectRatio", "overflow"], mpEquiv: "<view>", tier: "L1", status: "implemented" },
|
|
982
|
+
{ id: "L1", kind: "layout", semantic: "layout.box", tag: "p-box", props: ["aspectRatio", "overflow", "hoverClass", "hoverStopPropagation", "hoverStartTime", "hoverStayTime"], mpEquiv: "<view>", tier: "L1", status: "implemented" },
|
|
757
983
|
{ id: "L2", kind: "layout", semantic: "layout.inline", tag: "p-inline", props: ["wrap"], mpEquiv: "<text> \u5185\u8054", tier: "L1", status: "implemented" },
|
|
758
984
|
{ id: "L3", kind: "layout", semantic: "layout.stack", tag: "p-stack", props: ["direction", "gap", "align", "wrap", "snap", "loop"], mpEquiv: "flex + scroll-view + swiper", tier: "L1", status: "implemented" },
|
|
759
985
|
{ id: "L4", kind: "layout", semantic: "layout.grid", tag: "p-grid", props: ["minColWidth", "maxCols", "gap", "autoFlow"], mpEquiv: "<view> + CSS Grid", tier: "L1", status: "implemented" },
|
|
760
|
-
|
|
986
|
+
// ★Skyline 线收口:layout.fluid 由 v-p-fluid **指令**承载(非标签)——无 tag,避免 <p-fluid> 幽灵
|
|
987
|
+
{ id: "L5", kind: "layout", semantic: "layout.fluid", props: ["breakpoints", "minItemWidth"], mpEquiv: "\u54CD\u5E94\u5F0F CSS\uFF08v-p-fluid \u6307\u4EE4\uFF09", tier: "L1", status: "implemented" },
|
|
761
988
|
{ id: "L6", kind: "layout", semantic: "layout.adaptive", tag: "p-adaptive", props: ["sheet", "dialog", "popover", "drawer"], mpEquiv: "\u65E0\uFF08\u5BB9\u5668\u5BBD\u5EA6\u8BED\u4E49\u65AD\u70B9\uFF09", tier: "L1", status: "implemented" },
|
|
762
989
|
{ id: "L7", kind: "layout", semantic: "layout.fit", tag: "p-fit", props: ["mode"], mpEquiv: "fit-content", tier: "L1", status: "implemented" },
|
|
763
990
|
{ id: "L8", kind: "layout", semantic: "layout.spacer", tag: "p-spacer", props: ["grow", "shrink"], mpEquiv: "flex:1", tier: "L1", status: "implemented" },
|
|
764
991
|
{ id: "L9", kind: "layout", semantic: "layout.divider", tag: "p-divider", props: ["orientation", "inset"], mpEquiv: "<view> + border", tier: "L1", status: "implemented" },
|
|
765
|
-
{ id: "L10", kind: "layout", semantic: "layout.scroll", tag: "p-scroll", props: ["axis", "paging", "refresh", "indicator"], mpEquiv: "<scroll-view>", tier: "L1", status: "implemented" },
|
|
992
|
+
{ id: "L10", kind: "layout", semantic: "layout.scroll", tag: "p-scroll", props: ["axis", "paging", "refresh", "indicator", "upperThreshold", "lowerThreshold", "scrollIntoView", "scrollWithAnimation", "enableBackToTop", "enablePassive", "refresherEnabled", "refresherTriggered", "enhanced", "bounces", "scrollAnchoring", "padding"], mpEquiv: "<scroll-view>", tier: "L1", status: "implemented" },
|
|
766
993
|
{ id: "L11", kind: "layout", semantic: "layout.virtual-list", tag: "p-virtual-list", props: ["itemSize", "buffer", "direction"], mpEquiv: "<scroll-view> + \u624B\u52A8\u56DE\u6536", tier: "L1", status: "implemented" },
|
|
767
|
-
{ id: "L12", kind: "layout", semantic: "layout.masonry", tag: "p-masonry", props: ["colCount", "gap"], mpEquiv: "\u7B2C\u4E09\u65B9\u7011\u5E03\u6D41", tier: "L1", status: "implemented" }
|
|
994
|
+
{ id: "L12", kind: "layout", semantic: "layout.masonry", tag: "p-masonry", props: ["colCount", "gap"], mpEquiv: "\u7B2C\u4E09\u65B9\u7011\u5E03\u6D41", tier: "L1", status: "implemented" },
|
|
995
|
+
// ★#405 语义登记批:Fluid 体系剩余组件(语义层待多端映射 → planned L2——G-31.4 不足 3 端降级)
|
|
996
|
+
{ id: "L13", kind: "layout", semantic: "layout.aspect", tag: "p-aspect", props: ["ratio", "maxWidth"], mpEquiv: "\u65E0\uFF08\u7EB5\u6A2A\u6BD4\u5BB9\u5668\uFF09", tier: "L2", status: "planned" },
|
|
997
|
+
{ id: "L14", kind: "layout", semantic: "layout.zone", tag: "p-zone", props: ["designWidth"], mpEquiv: "\u65E0\uFF08\u5BB9\u5668\u65AD\u70B9\u5206\u533A\uFF09", tier: "L2", status: "planned" },
|
|
998
|
+
// ★批次 7(2026-09-18)未登记组件补登记:安全区(刘海/折叠屏/降级)+ 侧边导航容器
|
|
999
|
+
{ id: "L15", kind: "layout", semantic: "layout.safe", tag: "p-safe", props: ["area", "fold", "fallback"], mpEquiv: "\u65E0\uFF08\u5B89\u5168\u533A\u8BED\u4E49\u5BB9\u5668\uFF09", tier: "L1", status: "implemented" },
|
|
1000
|
+
{ id: "L16", kind: "layout", semantic: "layout.sidebar", tag: "p-sidebar", props: ["minSidebarWidth", "navWidth", "designWidth", "toggleLabel"], mpEquiv: "\u65E0\uFF08\u5BB9\u5668\u65AD\u70B9\u4FA7\u680F\uFF09", tier: "L1", status: "implemented" }
|
|
768
1001
|
];
|
|
769
1002
|
var UI = [
|
|
770
|
-
{ id: "U1", kind: "ui", semantic: "ui.text", tag: "p-text", props: ["content", "selectable", "truncate", "align"], mpEquiv: "<text>", tier: "L1", status: "implemented" },
|
|
1003
|
+
{ id: "U1", kind: "ui", semantic: "ui.text", tag: "p-text", props: ["content", "selectable", "truncate", "align", "userSelect", "overflow", "maxLines", "selectOnGesture", "space", "decode"], mpEquiv: "<text>", tier: "L1", status: "implemented" },
|
|
771
1004
|
{ id: "U2", kind: "ui", semantic: "ui.heading", tag: "p-heading", props: ["level"], mpEquiv: "<h1>-<h6>", tier: "L1", status: "implemented" },
|
|
772
|
-
{ id: "U3", kind: "ui", semantic: "ui.rich-text", tag: "p-rich-text", props: ["
|
|
773
|
-
{ id: "U4", kind: "ui", semantic: "ui.icon", tag: "p-icon", props: ["name", "size", "color", "spin"], mpEquiv: "<icon>", tier: "L1", status: "implemented" },
|
|
774
|
-
{ id: "U5", kind: "ui", semantic: "ui.image", tag: "p-image", props: ["src", "fit", "placeholder", "lazy"], mpEquiv: "<image>", tier: "L1", status: "implemented" },
|
|
1005
|
+
{ id: "U3", kind: "ui", semantic: "ui.rich-text", tag: "p-rich-text", props: ["nodes", "space", "userSelect", "mode", "source"], mpEquiv: "<rich-text>", tier: "L1", status: "implemented" },
|
|
1006
|
+
{ id: "U4", kind: "ui", semantic: "ui.icon", tag: "p-icon", props: ["name", "type", "size", "color", "spin"], mpEquiv: "<icon>", tier: "L1", status: "implemented" },
|
|
1007
|
+
{ id: "U5", kind: "ui", semantic: "ui.image", tag: "p-image", props: ["src", "fit", "placeholder", "lazy", "showMenuByLongpress", "fadeIn", "preload", "webp", "referrerPolicy"], mpEquiv: "<image>", tier: "L1", status: "implemented" },
|
|
775
1008
|
{ id: "U6", kind: "ui", semantic: "ui.avatar", tag: "p-avatar", props: ["src", "shape", "size", "fallback"], mpEquiv: "\u7EC4\u5408", tier: "L1", status: "implemented" },
|
|
776
|
-
{ id: "U7", kind: "ui", semantic: "ui.media", tag: "p-media", props: ["kind", "controls", "autoplay", "poster", "
|
|
777
|
-
{ id: "U8", kind: "ui", semantic: "ui.canvas", tag: "p-canvas", props: ["engine", "resolution"], mpEquiv: "<canvas>", tier: "L1", status: "implemented" },
|
|
1009
|
+
{ id: "U7", kind: "ui", semantic: "ui.media", tag: "p-media", props: ["kind", "src", "duration", "controls", "autoplay", "loop", "muted", "initialTime", "poster", "objectFit", "title", "playBtnPosition", "direction", "showProgress", "showFullscreenBtn", "showPlayBtn", "showCenterPlayBtn", "showMuteBtn", "showBottomProgress", "enableProgressGesture", "enablePlayGesture", "pageGesture", "vslideGesture", "vslideGestureInFullscreen", "autoPauseIfNavigate", "autoPauseIfOpenNative", "danmuList", "danmuBtn", "enableDanmu", "pictureInPicture"], mpEquiv: "<video>+<audio>", tier: "L1", status: "implemented" },
|
|
1010
|
+
{ id: "U8", kind: "ui", semantic: "ui.canvas", tag: "p-canvas", props: ["engine", "canvasId", "disableScroll", "resolution"], mpEquiv: "<canvas>", tier: "L1", status: "implemented" },
|
|
778
1011
|
{ id: "U9", kind: "ui", semantic: "ui.svg", tag: "p-svg", props: ["path", "viewbox"], mpEquiv: "\u65E0", tier: "L1", status: "implemented" },
|
|
779
1012
|
{ id: "U10", kind: "ui", semantic: "ui.input", tag: "p-input", props: ["type", "mask", "validation", "clearable"], mpEquiv: "<input>", tier: "L1", status: "implemented" },
|
|
780
1013
|
{ id: "U11", kind: "ui", semantic: "ui.textarea", tag: "p-textarea", props: ["autosize", "maxLength", "count"], mpEquiv: "<textarea>", tier: "L1", status: "implemented" },
|
|
@@ -783,12 +1016,32 @@ var UI = [
|
|
|
783
1016
|
{ id: "U14", kind: "ui", semantic: "ui.radio", tag: "p-radio", props: ["value", "group"], mpEquiv: "<radio>", tier: "L1", status: "implemented" },
|
|
784
1017
|
{ id: "U15", kind: "ui", semantic: "ui.switch", tag: "p-switch", props: ["checked", "loading"], mpEquiv: "<switch>", tier: "L1", status: "implemented" },
|
|
785
1018
|
{ id: "U16", kind: "ui", semantic: "ui.slider", tag: "p-slider", props: ["min", "max", "step", "range"], mpEquiv: "<slider>", tier: "L1", status: "implemented" },
|
|
786
|
-
{ id: "U17", kind: "ui", semantic: "ui.picker", tag: "p-picker", props: ["mode", "start", "end"], mpEquiv: "<picker>", tier: "L1", status: "implemented" },
|
|
787
|
-
{ id: "U18", kind: "ui", semantic: "ui.form", tag: "p-form", props: ["model", "rules", "layout"], mpEquiv: "\u7EC4\u5408", tier: "L1", status: "implemented" }
|
|
1019
|
+
{ id: "U17", kind: "ui", semantic: "ui.picker", tag: "p-picker", props: ["mode", "start", "end", "indicatorStyle", "indicatorClass", "maskClass", "maskStyle", "immediateChange"], mpEquiv: "<picker>", tier: "L1", status: "implemented" },
|
|
1020
|
+
{ id: "U18", kind: "ui", semantic: "ui.form", tag: "p-form", props: ["model", "rules", "layout"], mpEquiv: "\u7EC4\u5408", tier: "L1", status: "implemented" },
|
|
1021
|
+
// ★#405 语义登记批:反馈/状态类组件
|
|
1022
|
+
{ id: "U19", kind: "ui", semantic: "ui.loading", tag: "p-loading", props: ["size", "text"], mpEquiv: "wx.showLoading \u90E8\u5206", tier: "L2", status: "planned" },
|
|
1023
|
+
{ id: "U20", kind: "ui", semantic: "ui.scale", tag: "p-scale", props: ["level", "density", "baseSize"], mpEquiv: "\u65E0\uFF08\u65E0\u969C\u788D\u6863\u4F4D\uFF09", tier: "L2", status: "planned" },
|
|
1024
|
+
{ id: "U21", kind: "ui", semantic: "ui.skeleton", tag: "p-skeleton", props: ["rows", "avatar", "animated"], mpEquiv: "\u65E0", tier: "L2", status: "planned" },
|
|
1025
|
+
// ★能力颗粒度对齐 C2:进度条 / 表单标签
|
|
1026
|
+
{ id: "U22", kind: "ui", semantic: "ui.progress", tag: "p-progress", props: ["percent", "status", "type", "strokeWidth", "showInfo"], mpEquiv: "<progress>", tier: "L1", status: "implemented" },
|
|
1027
|
+
{ id: "U23", kind: "ui", semantic: "ui.label", tag: "p-label", props: ["for", "block"], mpEquiv: "<label>", tier: "L1", status: "implemented" },
|
|
1028
|
+
// ★权威标尺批 H:局部文本选区
|
|
1029
|
+
{ id: "U24", kind: "ui", semantic: "ui.selection", tag: "p-selection", props: ["disableContextMenu", "selectable"], mpEquiv: "<selection>", tier: "L1", status: "implemented" },
|
|
1030
|
+
// ★权威标尺批 I:相机
|
|
1031
|
+
{ id: "U25", kind: "ui", semantic: "ui.camera", tag: "p-camera", props: ["mode", "resolution", "devicePosition", "flash", "frameSize", "aspectRatio"], mpEquiv: "<camera>", tier: "L1", status: "implemented" },
|
|
1032
|
+
// ★权威标尺批 J:地图
|
|
1033
|
+
{ id: "U26", kind: "ui", semantic: "ui.map", tag: "p-map", props: ["latitude", "longitude", "scale", "minScale", "maxScale", "markers", "polyline", "circles", "polygons", "includePoints", "showLocation", "layerStyle", "rotate", "skew", "showCompass", "showScale", "enableZoom", "enableScroll", "enableRotate", "enableSatellite", "enableTraffic", "enablePoi", "enableBuilding", "enableOverlooking", "setting"], mpEquiv: "<map>", tier: "L1", status: "implemented" },
|
|
1034
|
+
// ★批次 7(2026-09-18)未登记组件补登记:这 3 个组件此前**只存在于 TAG_SEMANTIC_MAP**(编译器能解析、
|
|
1035
|
+
// 组件能渲染),但不在 SSOT catalog → C1 不变量(catalog tag ↔ TAG_SEMANTIC_MAP 双向)单向成立、
|
|
1036
|
+
// catalog 查询类 API(primitiveByTag / componentPrimitives)查不到它们。
|
|
1037
|
+
// ★p-button 尤其反讽:它是**端对齐全流程的参考实现**(21/21、SOP v2 范式),却不在语义清单里。
|
|
1038
|
+
{ id: "U27", kind: "ui", semantic: "ui.button", tag: "p-button", props: ["disabled", "loading", "throttle", "size", "type", "plain", "formType", "openType", "hoverClass", "theme", "hoverStopPropagation", "hoverStartTime", "hoverStayTime", "lang", "sessionFrom", "sendMessageTitle", "sendMessagePath", "sendMessageImg", "appParameter", "showMessageCard", "phoneNumberNoQuotaToast", "needShowEntrance", "entrancePath"], mpEquiv: "<button>", tier: "L1", status: "implemented" },
|
|
1039
|
+
{ id: "U28", kind: "ui", semantic: "ui.list", tag: "p-list-view", props: ["items", "itemHeight", "height", "bufferSize", "virtual", "lazy", "padding"], mpEquiv: "<list-view>\uFF08\u865A\u62DF\u6EDA\u52A8\uFF09", tier: "L1", status: "implemented" },
|
|
1040
|
+
{ id: "U29", kind: "ui", semantic: "ui.nav", tag: "p-nav-bar", props: ["title", "back", "fixed", "loading", "frontColor", "backgroundColor", "colorAnimationDuration", "colorAnimationTimingFunc"], mpEquiv: "<navigation-bar>\uFF08\u81EA\u7ED8\uFF09", tier: "L1", status: "implemented" }
|
|
788
1041
|
];
|
|
789
1042
|
var SHELL = [
|
|
790
1043
|
{ id: "S1", kind: "shell", semantic: "shell.page", tag: "p-page", props: ["title", "statusBar", "pullRefresh"], mpEquiv: "<page>", tier: "L1", status: "implemented" },
|
|
791
|
-
{ id: "S2", kind: "shell", semantic: "shell.nav", tag: "p-nav", props: ["title", "transparent"], mpEquiv: "\u5BFC\u822A\u680F\u914D\u7F6E", tier: "L1", status: "implemented" },
|
|
1044
|
+
{ id: "S2", kind: "shell", semantic: "shell.nav", tag: "p-nav", props: ["title", "transparent", "loading", "frontColor", "backgroundColor", "colorAnimationDuration", "colorAnimationTimingFunc"], mpEquiv: "\u5BFC\u822A\u680F\u914D\u7F6E", tier: "L1", status: "implemented" },
|
|
792
1045
|
{ id: "S3", kind: "shell", semantic: "shell.tabbar", tag: "p-tabbar", props: ["tabs", "active", "badge"], mpEquiv: "<tabbar>", tier: "L1", status: "implemented" },
|
|
793
1046
|
{ id: "S4", kind: "shell", semantic: "shell.segment", tag: "p-segment", props: ["options", "active"], mpEquiv: "<segment>", tier: "L1", status: "implemented" },
|
|
794
1047
|
{ id: "S5", kind: "shell", semantic: "shell.drawer", tag: "p-drawer", props: ["side", "width", "overlay"], mpEquiv: "\u7EC4\u5408", tier: "L1", status: "implemented" },
|
|
@@ -796,18 +1049,33 @@ var SHELL = [
|
|
|
796
1049
|
{ id: "S7", kind: "shell", semantic: "shell.popover", tag: "p-popover", props: ["trigger", "placement"], mpEquiv: "\u7EC4\u5408", tier: "L1", status: "implemented" },
|
|
797
1050
|
{ id: "S8", kind: "shell", semantic: "shell.toast", tag: "p-toast", props: ["message", "duration", "type"], mpEquiv: "wx.showToast", tier: "L1", status: "planned" },
|
|
798
1051
|
{ id: "S9", kind: "shell", semantic: "shell.action-sheet", tag: "p-action-sheet", props: ["actions", "cancel"], mpEquiv: "wx.showActionSheet", tier: "L1", status: "implemented" },
|
|
799
|
-
{ id: "S10", kind: "shell", semantic: "layout.split", tag: "p-split", props: ["breakpoint", "ratio", "collapse"], mpEquiv: "\u65E0\uFF08\u5206\u680F\u5E03\u5C40\uFF09", tier: "L1", status: "implemented" }
|
|
1052
|
+
{ id: "S10", kind: "shell", semantic: "layout.split", tag: "p-split", props: ["breakpoint", "ratio", "collapse"], mpEquiv: "\u65E0\uFF08\u5206\u680F\u5E03\u5C40\uFF09", tier: "L1", status: "implemented" },
|
|
800
1053
|
// ★已落地绑定:分栏语义由 layout.split 承载(G-32 文档为 shell.split——机器事实以实现为准)
|
|
1054
|
+
// ★#405 语义登记批:弹层/工具栏组件
|
|
1055
|
+
{ id: "S11", kind: "shell", semantic: "shell.mask", tag: "p-mask", props: ["visible", "transparent"], mpEquiv: "\u7EC4\u5408\uFF08\u906E\u7F69\u5C42\uFF09", tier: "L2", status: "planned" },
|
|
1056
|
+
{ id: "S12", kind: "shell", semantic: "shell.popup", tag: "p-popup", props: ["position", "round", "overlay"], mpEquiv: "\u7EC4\u5408\uFF08\u5F39\u5C42\uFF09", tier: "L2", status: "planned" },
|
|
1057
|
+
{ id: "S13", kind: "shell", semantic: "shell.toolbar", tag: "p-toolbar", props: ["items", "itemWidth", "moreWidth"], mpEquiv: "\u65E0\uFF08\u6EA2\u51FA\u6298\u53E0\uFF09", tier: "L2", status: "planned" },
|
|
1058
|
+
// ★能力颗粒度对齐 C2:页面容器(对齐小程序 <page-container>)
|
|
1059
|
+
{ id: "S14", kind: "shell", semantic: "shell.page-container", tag: "p-page-container", props: ["show", "position", "overlay", "closeOnClickOverlay", "duration", "zIndex", "closeOnSlideDown", "overlayStyle", "customStyle"], mpEquiv: "<page-container>", tier: "L1", status: "implemented" },
|
|
1060
|
+
// ★权威标尺批 H:键盘上方工具栏
|
|
1061
|
+
{ id: "S15", kind: "shell", semantic: "shell.keyboard-accessory", tag: "p-keyboard-accessory", props: ["visible", "maxHeight", "background"], mpEquiv: "<keyboard-accessory>", tier: "L1", status: "implemented" },
|
|
1062
|
+
// ★权威标尺批 J:内嵌网页 / 广告位
|
|
1063
|
+
{ id: "S16", kind: "shell", semantic: "shell.webview", tag: "p-webview", props: ["src", "height", "sandbox"], mpEquiv: "<web-view>", tier: "L1", status: "implemented" },
|
|
1064
|
+
{ id: "S17", kind: "shell", semantic: "shell.ad", tag: "p-ad", props: ["unitId", "adIntervals", "adType", "adTheme", "height"], mpEquiv: "<ad>", tier: "L1", status: "implemented" }
|
|
801
1065
|
];
|
|
802
1066
|
var GESTURE = [
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
{ id: "
|
|
808
|
-
{ id: "
|
|
809
|
-
{ id: "
|
|
810
|
-
{ id: "
|
|
1067
|
+
// ★2026-09-18:G1/G2 由 planned → implemented——`v-gesture:tap|longpress` 已双端落地
|
|
1068
|
+
// (编译器新增 `directive/v-gesture` 规则:MP 映射 bindtap/bindlongpress;Web 走 Pointer 识别器)。
|
|
1069
|
+
// ★G3–G7 **保持 planned**:MP 端无事件对等(官方用 worklet 手势处理器<组件>,框架未生成),
|
|
1070
|
+
// mpEquiv 已改为**如实描述**(原值 bindswipe/bindtouchmove/组合/3D Touch 多为不准确表述)。
|
|
1071
|
+
{ id: "G1", kind: "gesture", semantic: "gesture.tap", api: "v-gesture:tap", props: ["count"], mpEquiv: "bindtap\uFF08\u539F\u751F\u4E8B\u4EF6\u2014\u2014\u7F16\u8BD1\u5668\u76F4\u6620\u5C04\uFF09", tier: "L1", status: "implemented" },
|
|
1072
|
+
{ id: "G2", kind: "gesture", semantic: "gesture.longpress", api: "v-gesture:longpress", props: ["duration", "onEnd"], mpEquiv: "bindlongpress\uFF08\u539F\u751F\u4E8B\u4EF6\u2014\u2014\u7F16\u8BD1\u5668\u76F4\u6620\u5C04\uFF09", tier: "L1", status: "implemented" },
|
|
1073
|
+
{ id: "G3", kind: "gesture", semantic: "gesture.swipe", api: "v-gesture:swipe", props: ["direction", "threshold"], mpEquiv: "\u65E0\u539F\u751F\u4E8B\u4EF6\u2014\u2014\u9700 @touchstart/@touchend \u81EA\u884C\u5224\u5B9A\u65B9\u5411", tier: "L1", status: "planned" },
|
|
1074
|
+
{ id: "G4", kind: "gesture", semantic: "gesture.pan", api: "v-gesture:pan", props: ["axis", "bounds"], mpEquiv: "\u65E0\u539F\u751F\u4E8B\u4EF6\u2014\u2014\u5B98\u65B9 <pan-gesture-handler>\uFF08worklet\uFF09\u6216 touch \u65CF\u81EA\u884C\u5224\u5B9A", tier: "L1", status: "planned" },
|
|
1075
|
+
{ id: "G5", kind: "gesture", semantic: "gesture.pinch", api: "v-gesture:pinch", props: ["scale", "onChange"], mpEquiv: "\u65E0\u539F\u751F\u4E8B\u4EF6\u2014\u2014\u5B98\u65B9 <scale-gesture-handler>\uFF08worklet\uFF09", tier: "L1", status: "planned" },
|
|
1076
|
+
{ id: "G6", kind: "gesture", semantic: "gesture.rotate", api: "v-gesture:rotate", props: ["angle"], mpEquiv: "\u65E0\u539F\u751F\u4E8B\u4EF6\uFF08MP \u65E0 rotate \u624B\u52BF\u5904\u7406\u5668\uFF09", tier: "L1", status: "planned" },
|
|
1077
|
+
{ id: "G7", kind: "gesture", semantic: "gesture.press", api: "v-gesture:press", props: ["force"], mpEquiv: "\u65E0\u539F\u751F\u4E8B\u4EF6\u2014\u2014\u5B98\u65B9 <force-press-gesture-handler>\uFF08worklet\uFF0C\u9700 3D Touch \u8BBE\u5907\uFF09", tier: "L1", status: "planned" },
|
|
1078
|
+
{ id: "G8", kind: "gesture", semantic: "gesture.draggable", tag: "p-draggable", props: ["direction", "inertia", "outOfBounds", "x", "y", "damping", "friction", "disabled", "scaleEnabled", "scaleMin", "scaleMax", "scaleValue", "animation", "scaleArea", "ghost", "snapToGrid", "onDrop"], mpEquiv: "movable-view", tier: "L1", status: "implemented" },
|
|
811
1079
|
{ id: "G9", kind: "gesture", semantic: "gesture.scrollable", tag: "p-scrollable", props: ["bounce", "refresh", "loadMore"], mpEquiv: "<scroll-view>", tier: "L1", status: "implemented" },
|
|
812
1080
|
{ id: "G10", kind: "gesture", semantic: "gesture.use-gesture", api: "useGesture()", props: ["recognizers", "simultaneous"], mpEquiv: "\u65E0", tier: "L1", status: "planned" }
|
|
813
1081
|
];
|
|
@@ -816,9 +1084,10 @@ function cap(id, name, api, mpEquiv, returnType) {
|
|
|
816
1084
|
}
|
|
817
1085
|
var CAPABILITY = [
|
|
818
1086
|
// 7.1 设备/硬件(15)
|
|
819
|
-
|
|
1087
|
+
// ★2026-09-18 双形态(E8 先例):能力入口组件 p-pick-photo 即 useCamera() 的声明式入口
|
|
1088
|
+
{ id: "C1", kind: "capability", semantic: "capability.camera", api: "useCamera()", tag: "p-pick-photo", props: ["Result<Media>"], mpEquiv: "wx.createCameraContext", tier: "L1", status: "implemented" },
|
|
820
1089
|
cap("C2", "microphone", "useMicrophone()", "RecorderManager", "Result<AudioBuffer>"),
|
|
821
|
-
{ id: "C3", kind: "capability", semantic: "capability.location", api: "useLocation()", props: ["Result<Coords>"], mpEquiv: "wx.getLocation", tier: "L1", status: "implemented" },
|
|
1090
|
+
{ id: "C3", kind: "capability", semantic: "capability.location", api: "useLocation()", tag: "p-location", props: ["Result<Coords>"], mpEquiv: "wx.getLocation", tier: "L1", status: "implemented" },
|
|
822
1091
|
cap("C4", "map", "useMap()", "wx.createMapContext", "MapController"),
|
|
823
1092
|
cap("C5", "sensor", "useSensor()", "onAccelerometer/onCompass/onGyroscope", "SensorStream"),
|
|
824
1093
|
cap("C6", "vibrate", "useVibrate()", "wx.vibrateShort/Long", "void"),
|
|
@@ -860,7 +1129,8 @@ var CAPABILITY = [
|
|
|
860
1129
|
cap("C39", "face-id", "useFaceID()", "\u7EC4\u5408", "Result<boolean>"),
|
|
861
1130
|
cap("C40", "payment", "usePayment()", "wx.requestPayment", "Result<PayResult>"),
|
|
862
1131
|
cap("C41", "login", "useLogin()", "wx.login", "Result<Token>"),
|
|
863
|
-
|
|
1132
|
+
// ★2026-09-18 双形态(E8 先例):能力入口组件 p-scan-qr 即 useQRCode() 的声明式入口
|
|
1133
|
+
{ id: "C42", kind: "capability", semantic: "capability.qr-code", api: "useQRCode()", tag: "p-scan-qr", props: ["Result<string>"], mpEquiv: "wx.scanCode + canvas", tier: "L1", status: "implemented" },
|
|
864
1134
|
cap("C43", "file-system", "useFileSystem()", "wx.getFileSystemManager", "FSAdapter"),
|
|
865
1135
|
cap("C44", "archive", "useArchive()", "wx.compressFile", "Result<void>"),
|
|
866
1136
|
cap("C45", "shortcut", "useShortcut()", "wx.addToDesktop", "Result<void>"),
|
|
@@ -869,7 +1139,49 @@ var CAPABILITY = [
|
|
|
869
1139
|
{ id: "C47", kind: "capability", semantic: "capability.mini-program", api: "useMiniProgram()", props: ["MPContext"], mpEquiv: "wx.navigateToMiniProgram", tier: "L1", status: "planned" },
|
|
870
1140
|
{ id: "C48", kind: "capability", semantic: "capability.embedded", api: "useEmbedded()", props: ["HostContext"], mpEquiv: "\u65E0\uFF08\u88AB\u5BBF\u4E3B\u5D4C\u5165\uFF09", tier: "L1", status: "planned" },
|
|
871
1141
|
{ id: "C49", kind: "capability", semantic: "capability.live", api: "useLive()", props: ["LiveRoom"], mpEquiv: "wx...\uFF08\u76F4\u64AD\u7EC4\u4EF6\uFF09", tier: "L1", status: "planned" },
|
|
872
|
-
{ id: "C50", kind: "capability", semantic: "capability.extension", api: "useExtension()", props: ["ExtensionAPI"], mpEquiv: "\u65E0\uFF08\u63D2\u4EF6/\u6269\u5C55\u70B9 G-21\uFF09", tier: "L1", status: "planned" }
|
|
1142
|
+
{ id: "C50", kind: "capability", semantic: "capability.extension", api: "useExtension()", props: ["ExtensionAPI"], mpEquiv: "\u65E0\uFF08\u63D2\u4EF6/\u6269\u5C55\u70B9 G-21\uFF09", tier: "L1", status: "planned" },
|
|
1143
|
+
// ★颗粒度对齐 C(2026-09-11):C51 小程序热更新(wx.getUpdateManager)
|
|
1144
|
+
{ id: "C51", kind: "capability", semantic: "capability.update", api: "useUpdate()", props: ["UpdateManagerAPI"], mpEquiv: "wx.getUpdateManager", tier: "L1", status: "planned" },
|
|
1145
|
+
// ★颗粒度对齐 C3(2026-09-11):相册 / Worker(对齐小程序媒体与多线程 API——纯 Hook,无 C-IR 节点 → planned)
|
|
1146
|
+
{ id: "C52", kind: "capability", semantic: "capability.album", api: "useAlbum()", props: ["AlbumAPI"], mpEquiv: "wx.chooseMedia/saveImageToPhotosAlbum/previewMedia", tier: "L1", status: "planned" },
|
|
1147
|
+
{ id: "C53", kind: "capability", semantic: "capability.worker", api: "useWorker()", props: ["WorkerHandle"], mpEquiv: "wx.createWorker", tier: "L1", status: "planned" },
|
|
1148
|
+
// ★颗粒度对齐 C3 批 2:收货地址 / WiFi / 微信运动(对齐小程序系统 API——纯 Hook → planned)
|
|
1149
|
+
{ id: "C54", kind: "capability", semantic: "capability.address", api: "useAddress()", props: ["ShippingAddress"], mpEquiv: "wx.chooseAddress", tier: "L1", status: "planned" },
|
|
1150
|
+
{ id: "C55", kind: "capability", semantic: "capability.wifi", api: "useWifi()", props: ["WifiAPI"], mpEquiv: "wx.getConnectedWifi/getWifiList/connectWifi", tier: "L1", status: "planned" },
|
|
1151
|
+
{ id: "C56", kind: "capability", semantic: "capability.we-run", api: "useWeRun()", props: ["WeRunData"], mpEquiv: "wx.getWeRunData", tier: "L1", status: "planned" },
|
|
1152
|
+
// ★组件实例 API 对齐(2026-09-12):画布组件实例(wx.createCanvasContext/SelectorQuery node/canvasToTempFilePath/OffscreenCanvas;纯 Hook → planned)
|
|
1153
|
+
{ id: "C57", kind: "capability", semantic: "capability.canvas", api: "useCanvas()", props: ["CanvasController"], mpEquiv: "wx.createCanvasContext/canvasToTempFilePath/createOffscreenCanvas", tier: "L1", status: "planned" },
|
|
1154
|
+
// ★组件实例 API 对齐(2026-09-12):元素查询 / 交叉观察 / 媒体查询(wx SelectorQuery/IntersectionObserver/MediaQueryObserver)
|
|
1155
|
+
{ id: "C58", kind: "capability", semantic: "capability.element-query", api: "useElement()", props: ["ElementQuery"], mpEquiv: "wx.createSelectorQuery", tier: "L1", status: "planned" },
|
|
1156
|
+
{ id: "C59", kind: "capability", semantic: "capability.intersection", api: "useIntersection()", props: ["IntersectionHandle"], mpEquiv: "wx.createIntersectionObserver", tier: "L1", status: "planned" },
|
|
1157
|
+
{ id: "C60", kind: "capability", semantic: "capability.media-query", api: "useMediaQuery()", props: ["MediaQueryObserver"], mpEquiv: "wx.createMediaQueryObserver", tier: "L1", status: "planned" },
|
|
1158
|
+
// ★组件实例 API 对齐(2026-09-12):媒体组件实例 + 广告(wx VideoContext/InnerAudioContext/LivePusherContext + 广告联盟)
|
|
1159
|
+
{ id: "C61", kind: "capability", semantic: "capability.video", api: "useVideo()", props: ["VideoController"], mpEquiv: "wx.createVideoContext", tier: "L1", status: "planned" },
|
|
1160
|
+
{ id: "C62", kind: "capability", semantic: "capability.audio", api: "useAudio()", props: ["AudioController"], mpEquiv: "wx.createInnerAudioContext", tier: "L1", status: "planned" },
|
|
1161
|
+
{ id: "C63", kind: "capability", semantic: "capability.live-pusher", api: "useLivePusher()", props: ["LivePusherController"], mpEquiv: "wx.createLivePusherContext", tier: "L1", status: "planned" },
|
|
1162
|
+
{ id: "C64", kind: "capability", semantic: "capability.ad", api: "useAd()", props: ["AdAPI"], mpEquiv: "wx.createRewardedVideoAd/createInterstitialAd/createBannerAd", tier: "L1", status: "planned" },
|
|
1163
|
+
// ★权威标尺缺口补齐(2026-09-12):隐私协议(wx.getPrivacySetting/openPrivacyContract/requirePrivacyAuthorize——合规刚需)
|
|
1164
|
+
{ id: "C65", kind: "capability", semantic: "capability.privacy", api: "usePrivacy()", props: ["PrivacyAPI"], mpEquiv: "wx.getPrivacySetting/openPrivacyContract/requirePrivacyAuthorize", tier: "L1", status: "planned" },
|
|
1165
|
+
// ★权威标尺缺口补齐批 D(2026-09-12):性能 / 预加载 / 图像编辑(通用能力,无资质门槛)
|
|
1166
|
+
{ id: "C66", kind: "capability", semantic: "capability.performance", api: "usePerformance()", props: ["PerformanceAPI"], mpEquiv: "wx.getPerformance/reportPerformance", tier: "L1", status: "planned" },
|
|
1167
|
+
{ id: "C67", kind: "capability", semantic: "capability.preload", api: "usePreload()", props: ["PreloadAPI"], mpEquiv: "wx.preloadAssets/preloadSkylineView/preloadWebview/preDownloadSubpackage", tier: "L1", status: "planned" },
|
|
1168
|
+
{ id: "C68", kind: "capability", semantic: "capability.image-edit", api: "useImageEdit()", props: ["ImageEditAPI"], mpEquiv: "wx.cropImage/editImage", tier: "L1", status: "planned" },
|
|
1169
|
+
// ★权威标尺缺口补齐批 E(2026-09-12):网络底层 / 媒体高级
|
|
1170
|
+
{ id: "C69", kind: "capability", semantic: "capability.socket", api: "useSocket()", props: ["UDPSocketHandle / TCPSocketHandle"], mpEquiv: "wx.createUDPSocket/createTCPSocket", tier: "L1", status: "planned" },
|
|
1171
|
+
{ id: "C70", kind: "capability", semantic: "capability.media-processing", api: "useMediaProcessing()", props: ["MediaProcessingAPI"], mpEquiv: "wx.createMediaContainer/createVideoDecoder/createMediaAudioPlayer", tier: "L1", status: "planned" },
|
|
1172
|
+
// ★权威标尺缺口补齐批 F(2026-09-12):录屏/缓存/空闲/窗口/导航拦截
|
|
1173
|
+
{ id: "C71", kind: "capability", semantic: "capability.screen-capture", api: "useScreenCapture()", props: ["ScreenCaptureAPI"], mpEquiv: "wx.getScreenRecordingState/onScreenRecordingStateChanged/onUserCaptureScreen/checkIsPictureInPictureActive", tier: "L1", status: "planned" },
|
|
1174
|
+
{ id: "C72", kind: "capability", semantic: "capability.cache-manager", api: "useCacheManager()", props: ["CacheManagerHandle"], mpEquiv: "wx.createCacheManager", tier: "L1", status: "planned" },
|
|
1175
|
+
{ id: "C73", kind: "capability", semantic: "capability.idle", api: "useIdle()", props: ["IdleAPI"], mpEquiv: "wx.requestIdleCallback/cancelIdleCallback", tier: "L1", status: "planned" },
|
|
1176
|
+
{ id: "C74", kind: "capability", semantic: "capability.window", api: "useWindow()", props: ["WindowAPI"], mpEquiv: "wx.setWindowSize", tier: "L1", status: "planned" },
|
|
1177
|
+
{ id: "C75", kind: "capability", semantic: "capability.navigation-guard", api: "useNavigationGuard()", props: ["NavigationGuardAPI"], mpEquiv: "wx.enableAlertBeforeUnload/disableAlertBeforeUnload", tier: "L1", status: "planned" },
|
|
1178
|
+
// ★权威标尺缺口补齐批 G(2026-09-12):AR/XR / iBeacon / 局域网 / 翻译 / 海报 / 设备探测
|
|
1179
|
+
{ id: "C76", kind: "capability", semantic: "capability.ar", api: "useAR()", props: ["ARAPI"], mpEquiv: "wx.createVKSession/isVKSupport", tier: "L1", status: "planned" },
|
|
1180
|
+
{ id: "C77", kind: "capability", semantic: "capability.beacon", api: "useBeacon()", props: ["BeaconAPI"], mpEquiv: "wx.onBeaconServiceChange/onBeaconUpdate", tier: "L1", status: "planned" },
|
|
1181
|
+
{ id: "C78", kind: "capability", semantic: "capability.local-service", api: "useLocalService()", props: ["LocalServiceAPI"], mpEquiv: "wx.onLocalServiceFound/Lost/ResolveFail/DiscoveryStop", tier: "L1", status: "planned" },
|
|
1182
|
+
{ id: "C79", kind: "capability", semantic: "capability.translation", api: "useTranslation()", props: ["TranslationAPI"], mpEquiv: "wx.onUserTriggerTranslation/onUserOffTranslation", tier: "L1", status: "planned" },
|
|
1183
|
+
{ id: "C80", kind: "capability", semantic: "capability.poster", api: "usePoster()", props: ["PosterAPI"], mpEquiv: "wx.onGeneratePoster", tier: "L1", status: "planned" },
|
|
1184
|
+
{ id: "C81", kind: "capability", semantic: "capability.device-capability", api: "useDeviceCapability()", props: ["DeviceCapabilityAPI"], mpEquiv: "wx.checkDeviceSupportHevc", tier: "L1", status: "planned" }
|
|
873
1185
|
];
|
|
874
1186
|
var ENGINEERING = [
|
|
875
1187
|
{ id: "E1", kind: "engineering", semantic: "engineering.state", api: "useState()", mpEquiv: "data", tier: "L1", status: "planned" },
|
|
@@ -879,7 +1191,8 @@ var ENGINEERING = [
|
|
|
879
1191
|
{ id: "E5", kind: "engineering", semantic: "engineering.provide-inject", api: "useProvide()/useInject()", mpEquiv: "\u65E0", tier: "L1", status: "planned" },
|
|
880
1192
|
{ id: "E6", kind: "engineering", semantic: "engineering.lifecycle", api: "useLifecycle()", mpEquiv: "onLoad/onShow/onHide/onUnload", tier: "L1", status: "planned" },
|
|
881
1193
|
{ id: "E7", kind: "engineering", semantic: "engineering.ready", api: "useReady()", mpEquiv: "onReady", tier: "L1", status: "planned" },
|
|
882
|
-
{ id: "E8", kind: "engineering", semantic: "engineering.error-boundary", api: "useErrorBoundary()", mpEquiv: "onError", tier: "L1", status: "planned" },
|
|
1194
|
+
{ id: "E8", kind: "engineering", semantic: "engineering.error-boundary", api: "useErrorBoundary()", tag: "p-error-boundary", mpEquiv: "onError", tier: "L1", status: "planned" },
|
|
1195
|
+
// ★#405:组件形态补登(双形态:Hook + p- 标签)
|
|
883
1196
|
{ id: "E9", kind: "engineering", semantic: "engineering.page-param", api: "usePageParam()", mpEquiv: "onLoad(options)", tier: "L1", status: "planned" },
|
|
884
1197
|
{ id: "E10", kind: "engineering", semantic: "engineering.route", api: "useRoute()", mpEquiv: "getCurrentPages()", tier: "L1", status: "planned" },
|
|
885
1198
|
{ id: "E11", kind: "engineering", semantic: "engineering.router-push", api: "router.push()", mpEquiv: "wx.navigateTo", tier: "L1", status: "planned" },
|
|
@@ -889,7 +1202,7 @@ var ENGINEERING = [
|
|
|
889
1202
|
{ id: "E15", kind: "engineering", semantic: "engineering.router-relaunch", api: "router.reLaunch()", mpEquiv: "wx.reLaunch", tier: "L1", status: "planned" },
|
|
890
1203
|
{ id: "E16", kind: "engineering", semantic: "engineering.router-before-each", api: "router.beforeEach()", mpEquiv: "onLaunch \u624B\u52A8", tier: "L1", status: "planned" },
|
|
891
1204
|
{ id: "E17", kind: "engineering", semantic: "engineering.router-after-each", api: "router.afterEach()", mpEquiv: "\u65E0", tier: "L1", status: "planned" },
|
|
892
|
-
{ id: "E18", kind: "engineering", semantic: "engineering.router-link", tag: "p-router-link", props: ["to", "replace", "switchTab"], mpEquiv: "<navigator>", tier: "L1", status: "implemented" },
|
|
1205
|
+
{ id: "E18", kind: "engineering", semantic: "engineering.router-link", tag: "p-router-link", props: ["to", "replace", "switchTab", "target", "url", "openType", "delta", "appId", "path", "extraData", "version", "shortLink", "hoverClass", "hoverStopPropagation", "hoverStartTime", "hoverStayTime"], mpEquiv: "<navigator>", tier: "L1", status: "implemented" },
|
|
893
1206
|
{ id: "E19", kind: "engineering", semantic: "engineering.transition", tag: "p-transition", props: ["name", "mode"], mpEquiv: "transition CSS", tier: "L1", status: "implemented" },
|
|
894
1207
|
{ id: "E20", kind: "engineering", semantic: "engineering.animate", tag: "p-animate", props: ["keyframes", "duration"], mpEquiv: "animation CSS", tier: "L1", status: "implemented" },
|
|
895
1208
|
{ id: "E21", kind: "engineering", semantic: "engineering.animation", api: "useAnimation()", mpEquiv: "wx.createAnimation", tier: "L1", status: "planned" },
|
|
@@ -899,7 +1212,18 @@ var ENGINEERING = [
|
|
|
899
1212
|
{ id: "E25", kind: "engineering", semantic: "engineering.inspector", api: "useInspector()", mpEquiv: "\u65E0", tier: "L1", status: "planned" },
|
|
900
1213
|
{ id: "E26", kind: "engineering", semantic: "engineering.performance", api: "usePerformance()", mpEquiv: "wx.reportPerformance", tier: "L1", status: "planned" },
|
|
901
1214
|
{ id: "E27", kind: "engineering", semantic: "engineering.define-component", api: "defineComponent()", mpEquiv: "Component()", tier: "L1", status: "planned" },
|
|
902
|
-
{ id: "E28", kind: "engineering", semantic: "engineering.define-capability", api: "defineCapability()", mpEquiv: "\u65E0", tier: "L1", status: "planned" }
|
|
1215
|
+
{ id: "E28", kind: "engineering", semantic: "engineering.define-capability", api: "defineCapability()", mpEquiv: "\u65E0", tier: "L1", status: "planned" },
|
|
1216
|
+
// ★批次 8(2026-09-18):共享元素转场(官方 <share-element> 对齐)——能力由宿主提供,框架只声明语义
|
|
1217
|
+
{ id: "E29", kind: "engineering", semantic: "engineering.share-element", tag: "p-share-element", props: ["shuttleKey", "animate", "duration", "easingFunction", "transitionOnGesture", "shuttleOnPush", "shuttleOnPop", "rectTweenType"], mpEquiv: "<share-element>\uFF08\u5BBF\u4E3B\u8DE8\u9875\u98DE\u884C\u52A8\u753B\uFF09", tier: "L1", status: "implemented" },
|
|
1218
|
+
// ★E30(2026-09-19):WebMCP 接入——把**能力面**暴露为浏览器内 agent 可调用工具。
|
|
1219
|
+
// 规范面:`document.modelContext.registerTool(...)`(★非 navigator)+ signal 注销(规范无 unregisterTool);
|
|
1220
|
+
// 灵感来自 VueUse v15 `useWebMCP`(document 命名空间 / signal 注销 / 方法可调用探测 / 三元组返回)。
|
|
1221
|
+
// 框架差异化:能力面统一 `CapResult<T>` 契约(G-32.4)→ 能力可**自动**派生为工具、响应归一不必逐个手写。
|
|
1222
|
+
// ★状态口径(与 E1-E28 / C15 / C26 等同款,非本轮新引入):hook 形态原语无**渲染后端映射**,
|
|
1223
|
+
// 故按 catalog 既有约定记 `planned`——该字段反映「已在 SEMANTIC_BACKEND_MAP 登记 ≥3 端」,
|
|
1224
|
+
// 不等于「代码未实现」(本原语已实现于 `packages/api/src/mcp.ts`)。
|
|
1225
|
+
// `mpEquiv: 无`:WebMCP 是浏览器侧 agent 通道,小程序无 `document.modelContext` → 如实降级(isSupported=false)。
|
|
1226
|
+
{ id: "E30", kind: "engineering", semantic: "engineering.mcp", api: "useMCP()", props: ["tools", "capabilities", "prefix"], mpEquiv: "\u65E0\uFF08\u6D4F\u89C8\u5668\u4FA7 agent \u901A\u9053\uFF1BMP \u7AEF isSupported=false \u8BDA\u5B9E\u964D\u7EA7\uFF09", tier: "L1", status: "planned" }
|
|
903
1227
|
];
|
|
904
1228
|
var PRIMITIVE_CATALOG = [...LAYOUT, ...UI, ...SHELL, ...GESTURE, ...CAPABILITY, ...ENGINEERING];
|
|
905
1229
|
function componentPrimitives(kinds = ["layout", "ui", "shell", "gesture", "engineering"]) {
|
|
@@ -919,7 +1243,7 @@ function primitiveByTag(tag) {
|
|
|
919
1243
|
}
|
|
920
1244
|
function checkPrimitiveCatalog() {
|
|
921
1245
|
const errors = [];
|
|
922
|
-
if (PRIMITIVE_CATALOG.length
|
|
1246
|
+
if (PRIMITIVE_CATALOG.length === 0) errors.push("\u6E05\u5355\u4E3A\u7A7A");
|
|
923
1247
|
const ids = new Set(PRIMITIVE_CATALOG.map((p) => p.id));
|
|
924
1248
|
if (ids.size !== PRIMITIVE_CATALOG.length) errors.push("id \u91CD\u590D");
|
|
925
1249
|
const sems = new Set(PRIMITIVE_CATALOG.map((p) => p.semantic));
|
|
@@ -979,10 +1303,10 @@ var MP_COMPONENTS = [
|
|
|
979
1303
|
{ mp: "<swiper-item>", proteus: "layout.stack \u5B50\u9879", status: "ok", group: "component" },
|
|
980
1304
|
{ mp: "<movable-area>", proteus: "gesture.scrollable \u5BB9\u5668", status: "ok", group: "component" },
|
|
981
1305
|
{ mp: "<movable-view>", proteus: "gesture.draggable", status: "ok", group: "component" },
|
|
982
|
-
{ mp: "<cover-view>", proteus: "
|
|
983
|
-
{ mp: "<cover-image>", proteus: "
|
|
1306
|
+
{ mp: "<cover-view>", proteus: "layout.box\uFF08Skyline \u540C\u5C42\u6E32\u67D3\u540E view \u5373\u53EF\u8986\u76D6\u2014\u2014\u5B98\u65B9\u5EFA\u8BAE\u66FF\u4EE3\uFF09", status: "ok", group: "component" },
|
|
1307
|
+
{ mp: "<cover-image>", proteus: "ui.image\uFF08\u540C\u5C42\u6E32\u67D3\u540E image \u5373\u53EF\u8986\u76D6\uFF09", status: "ok", group: "component" },
|
|
984
1308
|
{ mp: "<icon>", proteus: "ui.icon", status: "ok", group: "component" },
|
|
985
|
-
{ mp: "<progress>", proteus: "
|
|
1309
|
+
{ mp: "<progress>", proteus: "ui.progress", status: "ok", group: "component" },
|
|
986
1310
|
{ mp: "<rich-text>", proteus: "ui.rich-text", status: "ok", group: "component" },
|
|
987
1311
|
{ mp: "<button>", proteus: "ui.button", status: "ok", group: "component" },
|
|
988
1312
|
{ mp: "<form>", proteus: "ui.form", status: "ok", group: "component" },
|
|
@@ -994,56 +1318,103 @@ var MP_COMPONENTS = [
|
|
|
994
1318
|
{ mp: "<picker-view>", proteus: "ui.picker mode=wheel", status: "ok", group: "component" },
|
|
995
1319
|
{ mp: "<slider>", proteus: "ui.slider", status: "ok", group: "component" },
|
|
996
1320
|
{ mp: "<switch>", proteus: "ui.switch", status: "ok", group: "component" },
|
|
997
|
-
{ mp: "<label>", proteus: "
|
|
1321
|
+
{ mp: "<label>", proteus: "ui.label", status: "ok", group: "component" },
|
|
998
1322
|
{ mp: "<navigator>", proteus: "engineering.router-link / router.*", status: "ok", group: "component" },
|
|
999
1323
|
{ mp: "<audio>", proteus: "ui.media kind=audio\uFF08\u6D88\u706D\u4E3A\u5C5E\u6027\uFF09", status: "ok", group: "component" },
|
|
1000
1324
|
{ mp: "<video>", proteus: "ui.media kind=video\uFF08\u6D88\u706D\u4E3A\u5C5E\u6027\uFF09", status: "ok", group: "component" },
|
|
1001
|
-
{ mp: "<camera>", proteus: "
|
|
1325
|
+
{ mp: "<camera>", proteus: "ui.camera\uFF08p-camera\uFF09+ useCamera", status: "ok", group: "component" },
|
|
1002
1326
|
{ mp: "<live-player>", proteus: "ui.media kind=live\uFF08\u6D88\u706D\u4E3A\u5C5E\u6027\uFF09", status: "ok", group: "component" },
|
|
1003
1327
|
{ mp: "<live-pusher>", proteus: "ui.media kind=live mode=push", status: "ok", group: "component" },
|
|
1004
1328
|
{ mp: "<canvas>", proteus: "ui.canvas", status: "ok", group: "component" },
|
|
1005
|
-
{ mp: "<map>", proteus: "
|
|
1006
|
-
{ mp: "<web-view>", proteus: "
|
|
1329
|
+
{ mp: "<map>", proteus: "ui.map\uFF08p-map\uFF09+ useMap", status: "ok", group: "component" },
|
|
1330
|
+
{ mp: "<web-view>", proteus: "shell.webview\uFF08p-webview\uFF09+ \u5BBF\u4E3B\u6865", status: "ok", group: "component" },
|
|
1007
1331
|
{ mp: "<editor>", proteus: "ui.rich-text editable", status: "ok", group: "component" },
|
|
1008
|
-
{ mp: "<ad>", proteus: "
|
|
1009
|
-
{ mp: "<official-account>", proteus: "
|
|
1010
|
-
{ mp: "<open-data>", proteus: "
|
|
1011
|
-
{ mp: "<share-element>", proteus: "
|
|
1012
|
-
{ mp: "<aria-component>", proteus: "
|
|
1013
|
-
{ mp: "<page-container>", proteus: "
|
|
1014
|
-
{ mp: "<voip-room>", proteus: "
|
|
1015
|
-
{ mp: "<guild-room>", proteus: "
|
|
1332
|
+
{ mp: "<ad>", proteus: "shell.ad\uFF08p-ad\uFF09", status: "ok", group: "component" },
|
|
1333
|
+
{ mp: "<official-account>", proteus: "useMiniProgram\uFF08\u5FAE\u4FE1\u79C1\u6709\uFF09", status: "private", group: "component" },
|
|
1334
|
+
{ mp: "<open-data>", proteus: "useMiniProgram\uFF08\u5FAE\u4FE1\u79C1\u6709\uFF09", status: "private", group: "component" },
|
|
1335
|
+
{ mp: "<share-element>", proteus: "engineering.share-element\uFF08p-share-element\uFF09", status: "ok", group: "component" },
|
|
1336
|
+
{ mp: "<aria-component>", proteus: "aria-* \u5C5E\u6027\uFF08\u5404\u7EC4\u4EF6 ariaLabel\uFF1B\u4E24\u7AEF\u539F\u751F\u652F\u6301\uFF09", status: "ok", group: "component" },
|
|
1337
|
+
{ mp: "<page-container>", proteus: "shell.page-container", status: "ok", group: "component" },
|
|
1338
|
+
{ mp: "<voip-room>", proteus: "useMiniProgram\uFF08\u5FAE\u4FE1 VOIP\uFF09", status: "private", group: "component" },
|
|
1339
|
+
{ mp: "<guild-room>", proteus: "useMiniProgram\uFF08\u5FAE\u4FE1\u6E38\u620F\uFF09", status: "private", group: "component" },
|
|
1340
|
+
// ★2026-09-11 补齐:此前矩阵漏列的真实微信内置组件(Skyline 族为主)——有等价能力标 ok/compat,无则 missing
|
|
1341
|
+
{ mp: "<match-media>", proteus: "p-adaptive / p-zone\uFF08\u5BB9\u5668\u65AD\u70B9\u66FF\u4EE3\uFF09", status: "ok", group: "component" },
|
|
1342
|
+
{ mp: "<navigation-bar>", proteus: "shell.nav\uFF08p-nav-bar \u81EA\u7ED8\uFF09", status: "ok", group: "component" },
|
|
1343
|
+
{ mp: "<keyframe-animation>", proteus: "engineering.animate / engineering.transition", status: "ok", group: "component" },
|
|
1344
|
+
{ mp: "<list-view>", proteus: "layout.virtual-list\uFF08p-list-view \u56DE\u6536\uFF09", status: "ok", group: "component" },
|
|
1345
|
+
{ mp: "<grid-view>", proteus: "layout.grid / layout.virtual-list", status: "ok", group: "component" },
|
|
1346
|
+
{ mp: "<snapshot>", proteus: "ui.canvas\uFF08\u622A\u56FE\u7ECF OffscreenCanvas\uFF09", status: "compat", group: "component" },
|
|
1347
|
+
{ mp: "<page-meta>", proteus: "shell.page\uFF08\u9875\u9762\u914D\u7F6E\u5C5E\u6027\uFF09", status: "compat", group: "component" },
|
|
1348
|
+
{ mp: "<root-portal>", proteus: "engineering.transition\uFF08teleport\u2192root-portal \u7F16\u8BD1\u671F\uFF09", status: "ok", group: "component" },
|
|
1349
|
+
{ mp: "<sticky-header>", proteus: "layout.scroll + sticky\uFF08CSS\uFF09", status: "compat", group: "component" },
|
|
1350
|
+
{ mp: "<sticky-section>", proteus: "layout.scroll + sticky\uFF08CSS\uFF09", status: "compat", group: "component" },
|
|
1351
|
+
{ mp: "<double-tap-gesture>", proteus: "gesture.draggable\uFF08p-draggable \u624B\u52BF\u8BC6\u522B\u5668\uFF09", status: "ok", group: "component" },
|
|
1352
|
+
{ mp: "<functional-page-navigator>", proteus: "\u2014\uFF08\u5FAE\u4FE1\u63D2\u4EF6\u9875\u4E13\u5C5E\uFF0C\u975E\u76EE\u6807\uFF09", status: "private", group: "component" },
|
|
1353
|
+
{ mp: "<open-container>", proteus: "\u2014\uFF08\u5FAE\u4FE1\u5F00\u5C4F\u5BB9\u5668\uFF0C\u79C1\u6709\uFF09", status: "private", group: "component" },
|
|
1354
|
+
// ★权威标尺批 H:局部文本选区 / 键盘上方工具栏(全端真实落地)
|
|
1355
|
+
{ mp: "<selection>", proteus: "ui.selection\uFF08p-selection\uFF09", status: "ok", group: "component" },
|
|
1356
|
+
{ mp: "<keyboard-accessory>", proteus: "shell.keyboard-accessory\uFF08p-keyboard-accessory\uFF09", status: "ok", group: "component" }
|
|
1016
1357
|
];
|
|
1017
1358
|
var MP_API_GROUPS = [
|
|
1018
|
-
{ mp: "wx.request/upload/download/websocket\uFF08\u7F51\u7EDC\uFF09", proteus: "
|
|
1019
|
-
{ mp: "wx.requestPayment", proteus: "
|
|
1020
|
-
{ mp: "wx.chooseImage/chooseMedia/previewImage\uFF08\u5A92\u4F53\uFF09", proteus: "
|
|
1021
|
-
{ mp: "wx.startRecord/RecorderManager\uFF08\u5F55\u97F3\uFF09", proteus: "
|
|
1022
|
-
{ mp: "wx.createVideoContext/CameraContext", proteus: "
|
|
1023
|
-
{ mp: "wx.scanCode", proteus: "
|
|
1024
|
-
{ mp: "wx.saveImageToPhotosAlbum", proteus: "
|
|
1025
|
-
{ mp: "wx.
|
|
1026
|
-
{ mp: "wx.
|
|
1027
|
-
{ mp: "wx.
|
|
1028
|
-
{ mp: "wx.
|
|
1029
|
-
|
|
1030
|
-
{ mp: "wx.
|
|
1031
|
-
{ mp: "wx.
|
|
1032
|
-
{ mp: "wx.
|
|
1033
|
-
{ mp: "wx.
|
|
1034
|
-
{ mp: "wx.
|
|
1359
|
+
{ mp: "wx.request/upload/download/websocket\uFF08\u7F51\u7EDC\uFF09", proteus: "useFetch / useUpload / useDownload / useWebSocket / useSocketTask", status: "ok", group: "api" },
|
|
1360
|
+
{ mp: "wx.requestPayment", proteus: "usePayment", status: "ok", group: "api" },
|
|
1361
|
+
{ mp: "wx.chooseImage/chooseMedia/previewImage\uFF08\u5A92\u4F53\uFF09", proteus: "useAlbum / useCamera + ui.image", status: "ok", group: "api" },
|
|
1362
|
+
{ mp: "wx.startRecord/RecorderManager\uFF08\u5F55\u97F3\uFF09", proteus: "useMicrophone / useRecorder", status: "ok", group: "api" },
|
|
1363
|
+
{ mp: "wx.createVideoContext/CameraContext", proteus: "ui.media + createCameraContext\uFF08ui.canvas \u627F\u63A5\uFF09", status: "ok", group: "api" },
|
|
1364
|
+
{ mp: "wx.scanCode", proteus: "useQRCode / p-scan-qr", status: "ok", group: "api" },
|
|
1365
|
+
{ mp: "wx.saveImageToPhotosAlbum/saveVideoToPhotosAlbum", proteus: "useAlbum\uFF08saveImage/saveVideo\uFF09", status: "ok", group: "api" },
|
|
1366
|
+
{ mp: "wx.createWorker\uFF08\u591A\u7EBF\u7A0B\uFF09", proteus: "useWorker", status: "ok", group: "api" },
|
|
1367
|
+
{ mp: "wx.chooseAddress\uFF08\u6536\u8D27\u5730\u5740\uFF09", proteus: "useAddress", status: "ok", group: "api" },
|
|
1368
|
+
{ mp: "wx.getConnectedWifi/getWifiList/connectWifi\uFF08WiFi\uFF09", proteus: "useWifi", status: "ok", group: "api" },
|
|
1369
|
+
{ mp: "wx.getWeRunData\uFF08\u5FAE\u4FE1\u8FD0\u52A8\uFF09", proteus: "useWeRun", status: "ok", group: "api" },
|
|
1370
|
+
// ★组件实例 API 对齐(2026-09-12):Canvas/查询/媒体组件实例(此前矩阵误标 useElement/useIntersection/useMedia——均为幽灵引用)
|
|
1371
|
+
{ mp: "wx.createCanvasContext / canvasToTempFilePath / createOffscreenCanvas\uFF08Canvas \u7EC4\u4EF6\u5B9E\u4F8B\uFF09", proteus: "useCanvas", status: "ok", group: "api" },
|
|
1372
|
+
{ mp: "wx.createSelectorQuery\uFF08\u5143\u7D20\u51E0\u4F55\u67E5\u8BE2\uFF09", proteus: "useElement", status: "ok", group: "api" },
|
|
1373
|
+
{ mp: "wx.createIntersectionObserver\uFF08\u4EA4\u53C9\u89C2\u5BDF\uFF09", proteus: "useIntersection", status: "ok", group: "api" },
|
|
1374
|
+
{ mp: "wx.createMediaQueryObserver\uFF08\u5A92\u4F53\u67E5\u8BE2\uFF09", proteus: "useMediaQuery", status: "ok", group: "api" },
|
|
1375
|
+
{ mp: "wx.createVideoContext\uFF08\u89C6\u9891\u7EC4\u4EF6\u5B9E\u4F8B\uFF09", proteus: "useVideo", status: "ok", group: "api" },
|
|
1376
|
+
{ mp: "wx.createInnerAudioContext\uFF08\u97F3\u9891\u5B9E\u4F8B\uFF09", proteus: "useAudio", status: "ok", group: "api" },
|
|
1377
|
+
{ mp: "wx.createLivePusherContext\uFF08\u76F4\u64AD\u63A8\u6D41\u5B9E\u4F8B\uFF09", proteus: "useLivePusher", status: "ok", group: "api" },
|
|
1378
|
+
{ mp: "wx.createRewardedVideoAd/createInterstitialAd/createBannerAd\uFF08\u5E7F\u544A\uFF09", proteus: "useAd", status: "ok", group: "api" },
|
|
1379
|
+
{ mp: "wx.getPrivacySetting/openPrivacyContract/requirePrivacyAuthorize\uFF08\u9690\u79C1\u534F\u8BAE\uFF09", proteus: "usePrivacy", status: "ok", group: "api" },
|
|
1380
|
+
{ mp: "wx.getPerformance/reportPerformance\uFF08\u6027\u80FD\uFF09", proteus: "usePerformance", status: "ok", group: "api" },
|
|
1381
|
+
{ mp: "wx.preloadAssets/preloadSkylineView/preloadWebview/preDownloadSubpackage\uFF08\u9884\u52A0\u8F7D\uFF09", proteus: "usePreload", status: "ok", group: "api" },
|
|
1382
|
+
{ mp: "wx.cropImage/editImage\uFF08\u56FE\u50CF\u7F16\u8F91\uFF09", proteus: "useImageEdit", status: "ok", group: "api" },
|
|
1383
|
+
{ mp: "wx.createUDPSocket/createTCPSocket\uFF08\u7F51\u7EDC\u5E95\u5C42 Socket\uFF09", proteus: "useSocket", status: "ok", group: "api" },
|
|
1384
|
+
{ mp: "wx.createMediaContainer/createVideoDecoder/createMediaAudioPlayer\uFF08\u5A92\u4F53\u9AD8\u7EA7\uFF09", proteus: "useMediaProcessing", status: "ok", group: "api" },
|
|
1385
|
+
{ mp: "wx.getScreenRecordingState/onScreenRecordingStateChanged/onUserCaptureScreen/checkIsPictureInPictureActive\uFF08\u5F55\u5C4F/\u622A\u5C4F\uFF09", proteus: "useScreenCapture", status: "ok", group: "api" },
|
|
1386
|
+
{ mp: "wx.createCacheManager\uFF08\u8BF7\u6C42\u7F13\u5B58\u7BA1\u7406\uFF09", proteus: "useCacheManager", status: "ok", group: "api" },
|
|
1387
|
+
{ mp: "wx.requestIdleCallback/cancelIdleCallback\uFF08\u7A7A\u95F2\u8C03\u5EA6\uFF09", proteus: "useIdle", status: "ok", group: "api" },
|
|
1388
|
+
{ mp: "wx.setWindowSize\uFF08PC \u7A97\u53E3\uFF09", proteus: "useWindow", status: "ok", group: "api" },
|
|
1389
|
+
{ mp: "wx.enableAlertBeforeUnload/disableAlertBeforeUnload\uFF08\u5378\u8F7D\u62E6\u622A\uFF09", proteus: "useNavigationGuard", status: "ok", group: "api" },
|
|
1390
|
+
{ mp: "wx.createVKSession/isVKSupport\uFF08AR/XR \u89C6\u89C9\u7B97\u6CD5\uFF09", proteus: "useAR", status: "ok", group: "api" },
|
|
1391
|
+
{ mp: "wx.onBeaconServiceChange/onBeaconUpdate\uFF08iBeacon\uFF09", proteus: "useBeacon", status: "ok", group: "api" },
|
|
1392
|
+
{ mp: "wx.onLocalServiceFound/Lost/ResolveFail/DiscoveryStop\uFF08\u5C40\u57DF\u7F51 mDNS\uFF09", proteus: "useLocalService", status: "ok", group: "api" },
|
|
1393
|
+
{ mp: "wx.onUserTriggerTranslation/onUserOffTranslation\uFF08\u7FFB\u8BD1\uFF09", proteus: "useTranslation", status: "ok", group: "api" },
|
|
1394
|
+
{ mp: "wx.onGeneratePoster\uFF08\u5206\u4EAB\u6D77\u62A5\uFF09", proteus: "usePoster", status: "ok", group: "api" },
|
|
1395
|
+
{ mp: "wx.checkDeviceSupportHevc\uFF08\u8BBE\u5907\u80FD\u529B\u63A2\u6D4B\uFF09", proteus: "useDeviceCapability", status: "ok", group: "api" },
|
|
1396
|
+
{ mp: "wx.getFileSystemManager/*\uFF08\u6587\u4EF6 30+\uFF09", proteus: "useFileSystem", status: "ok", group: "api" },
|
|
1397
|
+
{ mp: "wx.compressFile/unzip", proteus: "useArchive", status: "ok", group: "api" },
|
|
1398
|
+
{ mp: "wx.set/get/remove/clearStorage(+Sync)", proteus: "useStorage", status: "ok", group: "api" },
|
|
1399
|
+
{ mp: "wx.getLocation/chooseLocation/openLocation", proteus: "useLocation / p-location", status: "ok", group: "api" },
|
|
1400
|
+
{ mp: "wx.createMapContext", proteus: "useMap", status: "ok", group: "api" },
|
|
1401
|
+
{ mp: "wx.getSystemInfo\uFF08\u8BBE\u5907/\u5C4F\u5E55/\u7F51\u7EDC/\u7535\u91CF/\u4EAE\u5EA6/\u65B9\u5411/\u9707\u52A8/\u4F20\u611F\u5668/\u526A\u8D34\u677F/\u7535\u8BDD\uFF09", proteus: "useDevice / useScreen / useNetwork / useBattery / useBrightness / useOrientation / useVibrate / useSensor / useClipboard / usePhoneCall", status: "ok", group: "api" },
|
|
1402
|
+
{ mp: "wx.openBluetoothAdapter\uFF08\u84DD\u7259 20+\uFF09", proteus: "useBluetooth", status: "ok", group: "api" },
|
|
1403
|
+
{ mp: "wx.getHCEState\uFF08NFC\uFF09", proteus: "useNFC", status: "ok", group: "api" },
|
|
1404
|
+
{ mp: "wx.checkIsSupportFingerPrint/FaceID", proteus: "useBiometric / useFaceID", status: "ok", group: "api" },
|
|
1405
|
+
{ mp: "wx.showToast/showLoading/showModal/showActionSheet", proteus: "shell.toast + ui.loading + shell.modal + shell.action-sheet", status: "ok", group: "api" },
|
|
1035
1406
|
{ mp: "wx.setNavigationBarTitle/Color", proteus: "shell.nav", status: "ok", group: "api" },
|
|
1036
1407
|
{ mp: "wx.setTabBarItem/Style/hide/show", proteus: "shell.tabbar", status: "ok", group: "api" },
|
|
1037
|
-
{ mp: "wx.pageScrollTo", proteus: "
|
|
1038
|
-
{ mp: "wx.createAnimation", proteus: "engineering.
|
|
1039
|
-
{ mp: "wx.createSelectorQuery/IntersectionObserver", proteus: "
|
|
1040
|
-
{ mp: "wx.navigateTo/redirectTo/navigateBack/switchTab/reLaunch", proteus: "engineering.router-
|
|
1041
|
-
{ mp: "wx.getCurrentPages", proteus: "engineering.
|
|
1042
|
-
{ mp: "App()/Page() \u751F\u547D\u5468\u671F/getApp()", proteus: "
|
|
1043
|
-
{ mp: "wx.shareAppMessage/requestSubscribeMessage", proteus: "
|
|
1044
|
-
{ mp: "wx.login/checkSession/getUserInfo/authorize", proteus: "
|
|
1045
|
-
{ mp: "wx.getUpdateManager", proteus: "
|
|
1046
|
-
{ mp: "wx.requestWeChatPay/navigateToMiniProgram/\u6A21\u677F\u6D88\u606F/\u5BA2\u670D\uFF08\u5FAE\u4FE1\u79C1\u6709\uFF09", proteus: "
|
|
1408
|
+
{ mp: "wx.pageScrollTo", proteus: "layout.scroll\uFF08p-scroll-view\uFF09", status: "ok", group: "api" },
|
|
1409
|
+
{ mp: "wx.createAnimation", proteus: "engineering.animate / engineering.transition", status: "ok", group: "api" },
|
|
1410
|
+
{ mp: "wx.createSelectorQuery/IntersectionObserver", proteus: "engineering.router-link + layout.scroll\uFF08\u5B9E\u6D4B\u80FD\u529B\uFF09", status: "ok", group: "api" },
|
|
1411
|
+
{ mp: "wx.navigateTo/redirectTo/navigateBack/switchTab/reLaunch", proteus: "engineering.router-link + router.* API", status: "ok", group: "api" },
|
|
1412
|
+
{ mp: "wx.getCurrentPages", proteus: "engineering.router-link + shared adapter", status: "ok", group: "api" },
|
|
1413
|
+
{ mp: "App()/Page() \u751F\u547D\u5468\u671F/getApp()", proteus: "useAppLifecycle / usePageLifecycle", status: "ok", group: "api" },
|
|
1414
|
+
{ mp: "wx.shareAppMessage/requestSubscribeMessage", proteus: "useShare / useNotification", status: "ok", group: "api" },
|
|
1415
|
+
{ mp: "wx.login/checkSession/getUserInfo/authorize", proteus: "useLogin / useAuth / usePermission", status: "ok", group: "api" },
|
|
1416
|
+
{ mp: "wx.getUpdateManager", proteus: "useUpdate", status: "ok", group: "api" },
|
|
1417
|
+
{ mp: "wx.requestWeChatPay/navigateToMiniProgram/\u6A21\u677F\u6D88\u606F/\u5BA2\u670D\uFF08\u5FAE\u4FE1\u79C1\u6709\uFF09", proteus: "useMiniProgram", status: "private", group: "api" }
|
|
1047
1418
|
];
|
|
1048
1419
|
var MP_MAPPING_MATRIX = [...MP_COMPONENTS, ...MP_API_GROUPS];
|
|
1049
1420
|
function auditMiniprogramCoverage(matrix = MP_MAPPING_MATRIX) {
|
|
@@ -1052,6 +1423,7 @@ function auditMiniprogramCoverage(matrix = MP_MAPPING_MATRIX) {
|
|
|
1052
1423
|
const ok = matrix.filter((i) => i.status === "ok").length;
|
|
1053
1424
|
const compat = matrix.filter((i) => i.status === "compat").length;
|
|
1054
1425
|
const priv = matrix.filter((i) => i.status === "private").length;
|
|
1426
|
+
const planned = matrix.filter((i) => i.planned === true).length;
|
|
1055
1427
|
const total = matrix.length;
|
|
1056
1428
|
return {
|
|
1057
1429
|
total,
|
|
@@ -1059,11 +1431,40 @@ function auditMiniprogramCoverage(matrix = MP_MAPPING_MATRIX) {
|
|
|
1059
1431
|
compat,
|
|
1060
1432
|
private: priv,
|
|
1061
1433
|
missing: missingItems.length,
|
|
1434
|
+
planned,
|
|
1435
|
+
landed: total - priv - missingItems.length - planned,
|
|
1062
1436
|
percent: total === 0 ? 0 : Math.round((total - missingItems.length) / total * 100),
|
|
1063
1437
|
pass: missingItems.length === 0,
|
|
1064
1438
|
missingItems
|
|
1065
1439
|
};
|
|
1066
1440
|
}
|
|
1441
|
+
function auditMatrixReferences(matrix = MP_MAPPING_MATRIX, knownHooks = /* @__PURE__ */ new Set()) {
|
|
1442
|
+
const issues = [];
|
|
1443
|
+
const tags = new Set(Object.keys(TAG_SEMANTIC_MAP));
|
|
1444
|
+
const semantics = new Set(SEMANTIC_ENUM);
|
|
1445
|
+
let plannedRefs = 0;
|
|
1446
|
+
for (const it of matrix) {
|
|
1447
|
+
if (it.status === "missing") continue;
|
|
1448
|
+
for (const m of it.proteus.matchAll(/\bp-[a-z][\w-]*/g)) {
|
|
1449
|
+
if (tags.has(m[0])) continue;
|
|
1450
|
+
if (it.planned) {
|
|
1451
|
+
plannedRefs++;
|
|
1452
|
+
continue;
|
|
1453
|
+
}
|
|
1454
|
+
issues.push({ mp: it.mp, ref: m[0], kind: "component" });
|
|
1455
|
+
}
|
|
1456
|
+
for (const m of it.proteus.matchAll(/\b(?:layout|ui|shell|gesture|capability|engineering)\.[a-z][\w-]*/g)) {
|
|
1457
|
+
if (semantics.has(m[0])) continue;
|
|
1458
|
+
issues.push({ mp: it.mp, ref: m[0], kind: "semantic" });
|
|
1459
|
+
}
|
|
1460
|
+
if (knownHooks.size) {
|
|
1461
|
+
for (const m of it.proteus.matchAll(/\buse[A-Z]\w*/g)) {
|
|
1462
|
+
if (!knownHooks.has(m[0])) issues.push({ mp: it.mp, ref: m[0], kind: "hook" });
|
|
1463
|
+
}
|
|
1464
|
+
}
|
|
1465
|
+
}
|
|
1466
|
+
return { issues, plannedRefs };
|
|
1467
|
+
}
|
|
1067
1468
|
function auditCatalogConsistency() {
|
|
1068
1469
|
const issues = [];
|
|
1069
1470
|
const enumSet = new Set(SEMANTIC_ENUM);
|
|
@@ -1097,12 +1498,52 @@ function auditCatalogConsistency() {
|
|
|
1097
1498
|
}
|
|
1098
1499
|
}
|
|
1099
1500
|
}
|
|
1501
|
+
{
|
|
1502
|
+
const bySemantic = /* @__PURE__ */ new Map();
|
|
1503
|
+
for (const [tag, sem] of Object.entries(TAG_SEMANTIC_MAP)) {
|
|
1504
|
+
const list = bySemantic.get(sem) ?? [];
|
|
1505
|
+
list.push(tag);
|
|
1506
|
+
bySemantic.set(sem, list);
|
|
1507
|
+
}
|
|
1508
|
+
const aliasKeys = Object.keys(TAG_SEMANTIC_ALIASES);
|
|
1509
|
+
for (const [sem, tags] of bySemantic) {
|
|
1510
|
+
if (tags.length <= 1) continue;
|
|
1511
|
+
const decl = TAG_SEMANTIC_ALIASES[sem];
|
|
1512
|
+
if (!decl) {
|
|
1513
|
+
issues.push({
|
|
1514
|
+
rule: "C6",
|
|
1515
|
+
detail: `\u8BED\u4E49 ${sem} \u88AB ${tags.length} \u4E2A\u6807\u7B7E\u5171\u4EAB\uFF08${tags.join(", ")}\uFF09\u4F46\u672A\u5728 TAG_SEMANTIC_ALIASES \u767B\u8BB0\uFF08\u987B\u7ED9\u7406\u7531 + \u6307\u660E\u89C4\u8303\u6807\u7B7E\uFF09`
|
|
1516
|
+
});
|
|
1517
|
+
continue;
|
|
1518
|
+
}
|
|
1519
|
+
const declared = /* @__PURE__ */ new Set([decl.canonical, ...decl.aliases]);
|
|
1520
|
+
const undeclared = tags.filter((t) => !declared.has(t));
|
|
1521
|
+
if (undeclared.length) {
|
|
1522
|
+
issues.push({ rule: "C6", detail: `${sem} \u7684\u5171\u4EAB\u6807\u7B7E ${undeclared.join(", ")} \u672A\u5728 TAG_SEMANTIC_ALIASES \u4E2D\u58F0\u660E` });
|
|
1523
|
+
}
|
|
1524
|
+
if (!tags.includes(decl.canonical)) {
|
|
1525
|
+
issues.push({ rule: "C6", detail: `${sem} \u7684 canonical\u300C${decl.canonical}\u300D\u4E0D\u5728\u5B9E\u9645\u5171\u4EAB\u6807\u7B7E\u4E2D` });
|
|
1526
|
+
}
|
|
1527
|
+
if (!decl.reason?.trim()) issues.push({ rule: "C6", detail: `${sem} \u7684\u522B\u540D\u767B\u8BB0\u7F3A\u7406\u7531` });
|
|
1528
|
+
}
|
|
1529
|
+
for (const sem of aliasKeys) {
|
|
1530
|
+
if ((bySemantic.get(sem)?.length ?? 0) <= 1) {
|
|
1531
|
+
issues.push({ rule: "C6", detail: `TAG_SEMANTIC_ALIASES \u767B\u8BB0\u4E86 ${sem}\uFF0C\u4F46\u5B83\u5E76\u672A\u88AB\u591A\u6807\u7B7E\u5171\u4EAB\uFF08\u9648\u65E7\u767B\u8BB0\uFF09` });
|
|
1532
|
+
}
|
|
1533
|
+
}
|
|
1534
|
+
}
|
|
1535
|
+
for (const sem of Object.keys(SEMANTIC_BACKEND_MAP)) {
|
|
1536
|
+
if (!PRIMITIVE_CATALOG.some((p) => p.semantic === sem)) {
|
|
1537
|
+
issues.push({ rule: "C7", detail: `${sem} \u5728 SEMANTIC_BACKEND_MAP \u4F46 catalog \u65E0\u627F\u63A5\u884C\uFF08\u5B64\u513F\u8BED\u4E49\uFF09` });
|
|
1538
|
+
}
|
|
1539
|
+
}
|
|
1100
1540
|
return issues;
|
|
1101
1541
|
}
|
|
1102
1542
|
function formatCoverageReport(report) {
|
|
1103
1543
|
const lines = [
|
|
1104
1544
|
`G-32.1 \u5C0F\u7A0B\u5E8F\u80FD\u529B\u8986\u76D6\u5BA1\u8BA1\uFF1A`,
|
|
1105
|
-
` \u603B\u8BA1 ${report.total} \xB7 \u2705
|
|
1545
|
+
` \u603B\u8BA1 ${report.total} \xB7 \u2705 \u6709\u7B49\u4EF7 ${report.total - report.missing}\uFF08L1 \u539F\u8BED ${report.ok} + \u517C\u5BB9\u7B49\u4EF7 ${report.compat - report.planned}\uFF09\xB7 \u2B1B \u79C1\u6709 ${report.private} \xB7 \u274C \u7F3A\u5931 ${report.missing}`,
|
|
1546
|
+
` \u2605\u771F\xB7\u5DF2\u843D\u5730 ${report.landed} \xB7 \u{1F4CB} L2 \u89C4\u5212\u5F85\u843D\u5730 ${report.planned}\uFF08\u8BA1\u4F5C\u8986\u76D6\uFF0C\u975E\u5DF2\u5B9E\u73B0\u2014\u2014\u8BDA\u5B9E\u8FB9\u754C\uFF09`,
|
|
1106
1547
|
` \u8986\u76D6\u7387 ${report.percent}% ${report.pass ? "\u2705 \u8FBE\u6807\uFF080 \u7F3A\u5931\uFF09" : "\u274C \u672A\u8FBE\u6807\uFF08CI \u7EA2\uFF09"}`
|
|
1107
1548
|
];
|
|
1108
1549
|
if (report.missingItems.length) {
|
|
@@ -1111,22 +1552,812 @@ function formatCoverageReport(report) {
|
|
|
1111
1552
|
}
|
|
1112
1553
|
return lines.join("\n");
|
|
1113
1554
|
}
|
|
1555
|
+
|
|
1556
|
+
// src/mp-spec-coverage.ts
|
|
1557
|
+
var SPEC_COVERED = {
|
|
1558
|
+
// 网络(既有 Hook 承接)
|
|
1559
|
+
onSocketOpen: "useSocketTask/useWebSocket",
|
|
1560
|
+
onSocketClose: "useSocketTask/useWebSocket",
|
|
1561
|
+
onSocketError: "useSocketTask/useWebSocket",
|
|
1562
|
+
onSocketMessage: "useSocketTask/useWebSocket",
|
|
1563
|
+
offSocketOpen: "useSocketTask/useWebSocket",
|
|
1564
|
+
offSocketClose: "useSocketTask/useWebSocket",
|
|
1565
|
+
offSocketError: "useSocketTask/useWebSocket",
|
|
1566
|
+
offSocketMessage: "useSocketTask/useWebSocket",
|
|
1567
|
+
// 存储(同步/批量)
|
|
1568
|
+
batchGetStorageSync: "useStorage",
|
|
1569
|
+
batchSetStorageSync: "useStorage",
|
|
1570
|
+
removeStorageSync: "useStorage",
|
|
1571
|
+
// 设备/系统信息(新版拆分)
|
|
1572
|
+
getAccountInfoSync: "useDevice",
|
|
1573
|
+
getAppBaseInfo: "useDevice",
|
|
1574
|
+
getDeviceInfo: "useDevice",
|
|
1575
|
+
getWindowInfo: "useScreen",
|
|
1576
|
+
getSystemSetting: "usePermission",
|
|
1577
|
+
getAppAuthorizeSetting: "usePermission",
|
|
1578
|
+
getBatteryInfoSync: "useBattery",
|
|
1579
|
+
getRendererUserAgent: "useDevice",
|
|
1580
|
+
getSkylineInfo: "useDevice",
|
|
1581
|
+
getSkylineInfoSync: "useDevice",
|
|
1582
|
+
getDeviceBenchmarkInfo: "useDevice",
|
|
1583
|
+
canIUse: "useDevice",
|
|
1584
|
+
getApiCategory: "useDevice",
|
|
1585
|
+
getFuzzyLocation: "useLocation",
|
|
1586
|
+
// 应用/页面生命周期
|
|
1587
|
+
onAppHide: "useAppLifecycle",
|
|
1588
|
+
onAppShow: "useAppLifecycle",
|
|
1589
|
+
offAppHide: "useAppLifecycle",
|
|
1590
|
+
offAppShow: "useAppLifecycle",
|
|
1591
|
+
onMemoryWarning: "useAppLifecycle",
|
|
1592
|
+
offMemoryWarning: "useAppLifecycle",
|
|
1593
|
+
onThemeChange: "useAppLifecycle",
|
|
1594
|
+
offThemeChange: "useAppLifecycle",
|
|
1595
|
+
onUnhandledRejection: "useAppLifecycle",
|
|
1596
|
+
offUnhandledRejection: "useAppLifecycle",
|
|
1597
|
+
onPageNotFound: "usePageLifecycle",
|
|
1598
|
+
offPageNotFound: "usePageLifecycle",
|
|
1599
|
+
onBeforePageLoad: "usePageLifecycle",
|
|
1600
|
+
onAfterPageLoad: "usePageLifecycle",
|
|
1601
|
+
onBeforePageUnload: "usePageLifecycle",
|
|
1602
|
+
onAfterPageUnload: "usePageLifecycle",
|
|
1603
|
+
onLazyLoadError: "usePageLifecycle",
|
|
1604
|
+
offLazyLoadError: "usePageLifecycle",
|
|
1605
|
+
// 位置 / 网络 / 键盘 / WiFi / 蓝牙 / 传感器 事件
|
|
1606
|
+
onLocationChange: "useLocation.watch",
|
|
1607
|
+
offLocationChange: "useLocation.watch",
|
|
1608
|
+
onLocationChangeError: "useLocation.watch",
|
|
1609
|
+
offLocationChangeError: "useLocation.watch",
|
|
1610
|
+
onNetworkStatusChange: "useNetwork",
|
|
1611
|
+
offNetworkStatusChange: "useNetwork",
|
|
1612
|
+
onNetworkWeakChange: "useNetwork",
|
|
1613
|
+
offNetworkWeakChange: "useNetwork",
|
|
1614
|
+
onKeyboardHeightChange: "useKeyboard",
|
|
1615
|
+
offKeyboardHeightChange: "useKeyboard",
|
|
1616
|
+
onKeyDown: "useKeyboard",
|
|
1617
|
+
offKeyDown: "useKeyboard",
|
|
1618
|
+
onKeyUp: "useKeyboard",
|
|
1619
|
+
offKeyUp: "useKeyboard",
|
|
1620
|
+
onWifiConnected: "useWifi",
|
|
1621
|
+
offWifiConnected: "useWifi",
|
|
1622
|
+
onWifiConnectedWithPartialInfo: "useWifi",
|
|
1623
|
+
offWifiConnectedWithPartialInfo: "useWifi",
|
|
1624
|
+
onGetWifiList: "useWifi",
|
|
1625
|
+
offGetWifiList: "useWifi",
|
|
1626
|
+
onBluetoothAdapterStateChange: "useBluetooth",
|
|
1627
|
+
offBluetoothAdapterStateChange: "useBluetooth",
|
|
1628
|
+
onBluetoothDeviceFound: "useBluetooth",
|
|
1629
|
+
offBluetoothDeviceFound: "useBluetooth",
|
|
1630
|
+
onBLEConnectionStateChange: "useBluetooth",
|
|
1631
|
+
offBLEConnectionStateChange: "useBluetooth",
|
|
1632
|
+
onBLECharacteristicValueChange: "useBluetooth",
|
|
1633
|
+
offBLECharacteristicValueChange: "useBluetooth",
|
|
1634
|
+
onBLEMTUChange: "useBluetooth",
|
|
1635
|
+
offBLEMTUChange: "useBluetooth",
|
|
1636
|
+
onBatteryInfoChange: "useBattery",
|
|
1637
|
+
offBatteryInfoChange: "useBattery",
|
|
1638
|
+
onCompassChange: "useSensor",
|
|
1639
|
+
offCompassChange: "useSensor",
|
|
1640
|
+
onAccelerometerChange: "useSensor",
|
|
1641
|
+
offAccelerometerChange: "useSensor",
|
|
1642
|
+
onGyroscopeChange: "useSensor",
|
|
1643
|
+
offGyroscopeChange: "useSensor",
|
|
1644
|
+
onDeviceMotionChange: "useSensor",
|
|
1645
|
+
offDeviceMotionChange: "useSensor",
|
|
1646
|
+
onDeviceOrientationChange: "useOrientation",
|
|
1647
|
+
// 日志 / 埋点 / 通知 / 日历
|
|
1648
|
+
getLogManager: "useLog",
|
|
1649
|
+
getRealtimeLogManager: "useLog",
|
|
1650
|
+
reportAnalytics: "useAnalytics",
|
|
1651
|
+
reportEvent: "useAnalytics",
|
|
1652
|
+
reportMonitor: "useLog",
|
|
1653
|
+
sendSms: "useSMS",
|
|
1654
|
+
addPhoneCalendar: "useCalendarAPI",
|
|
1655
|
+
removePhoneCalendar: "useCalendarAPI",
|
|
1656
|
+
openCustomerServiceChat: "useCustomerService",
|
|
1657
|
+
requestSubscribeDeviceMessage: "useDeviceNotification",
|
|
1658
|
+
// 媒体组件实例(本轮 C4)
|
|
1659
|
+
createVideoContext: "useVideo",
|
|
1660
|
+
createInnerAudioContext: "useAudio",
|
|
1661
|
+
createLivePusherContext: "useLivePusher",
|
|
1662
|
+
createMediaRecorder: "useRecorder",
|
|
1663
|
+
createWebAudioContext: "useAudio",
|
|
1664
|
+
// 画布 / 查询(本轮 C4)
|
|
1665
|
+
createCanvasContext: "useCanvas",
|
|
1666
|
+
createOffscreenCanvas: "useCanvas",
|
|
1667
|
+
createSelectorQuery: "useElement",
|
|
1668
|
+
createIntersectionObserver: "useIntersection",
|
|
1669
|
+
createMediaQueryObserver: "useMediaQuery",
|
|
1670
|
+
// 广告(本轮 C4)
|
|
1671
|
+
createRewardedVideoAd: "useAd",
|
|
1672
|
+
createInterstitialAd: "useAd",
|
|
1673
|
+
createBannerAd: "useAd",
|
|
1674
|
+
// 大文件工具(useFileSystem 承接)
|
|
1675
|
+
arrayBufferToBase64: "useFileSystem",
|
|
1676
|
+
base64ToArrayBuffer: "useFileSystem",
|
|
1677
|
+
createBufferURL: "useFileSystem",
|
|
1678
|
+
revokeBufferURL: "useFileSystem",
|
|
1679
|
+
getFileSystemManager: "useFileSystem",
|
|
1680
|
+
saveFileToDisk: "useFileSystem",
|
|
1681
|
+
// 网络(改名承接)
|
|
1682
|
+
connectSocket: "useWebSocket",
|
|
1683
|
+
uploadFile: "useUpload",
|
|
1684
|
+
downloadFile: "useDownload",
|
|
1685
|
+
// 组件实例(改名承接)
|
|
1686
|
+
createCameraContext: "useCameraContext",
|
|
1687
|
+
createMapContext: "useMap",
|
|
1688
|
+
createWorker: "useWorker",
|
|
1689
|
+
createAnimation: "useAnimation",
|
|
1690
|
+
createLivePlayerContext: "useLive",
|
|
1691
|
+
createNFCAdapter: "useNFC",
|
|
1692
|
+
getNFCAdapter: "useNFC",
|
|
1693
|
+
getRecorderManager: "useRecorder",
|
|
1694
|
+
// 存储(同步/old)
|
|
1695
|
+
clearStorageSync: "useStorage",
|
|
1696
|
+
getStorageInfoSync: "useStorage.info",
|
|
1697
|
+
// 系统信息旧版(new 拆分版承接)
|
|
1698
|
+
getSystemInfoSync: "useDevice",
|
|
1699
|
+
getLaunchOptionsSync: "useMiniProgram",
|
|
1700
|
+
getEnterOptionsSync: "useMiniProgram",
|
|
1701
|
+
// 生命周期事件(旧名承接)
|
|
1702
|
+
onError: "useAppLifecycle",
|
|
1703
|
+
offError: "useAppLifecycle",
|
|
1704
|
+
onWindowResize: "useOrientation",
|
|
1705
|
+
offWindowResize: "useOrientation",
|
|
1706
|
+
onHCEMessage: "useNFC",
|
|
1707
|
+
offHCEMessage: "useNFC",
|
|
1708
|
+
offAfterPageLoad: "usePageLifecycle",
|
|
1709
|
+
offAfterPageUnload: "usePageLifecycle",
|
|
1710
|
+
offBeforePageLoad: "usePageLifecycle",
|
|
1711
|
+
offBeforePageUnload: "usePageLifecycle",
|
|
1712
|
+
// 热更新 / 联系人 / 剪贴板
|
|
1713
|
+
getUpdateManager: "useUpdate",
|
|
1714
|
+
chooseContact: "useContact",
|
|
1715
|
+
getMenuButtonBoundingClientRect: "useElement.boundingClientRect",
|
|
1716
|
+
getLocalIPAddress: "useNetwork",
|
|
1717
|
+
// 隐私协议(C65——合规刚需,2026-09-12 补齐)
|
|
1718
|
+
getPrivacySetting: "usePrivacy",
|
|
1719
|
+
openPrivacyContract: "usePrivacy",
|
|
1720
|
+
requirePrivacyAuthorize: "usePrivacy",
|
|
1721
|
+
onNeedPrivacyAuthorization: "usePrivacy",
|
|
1722
|
+
offNeedPrivacyAuthorization: "usePrivacy",
|
|
1723
|
+
// 性能 / 预加载 / 图像编辑(C66-C68——批 D 补齐,2026-09-12)
|
|
1724
|
+
getPerformance: "usePerformance",
|
|
1725
|
+
reportPerformance: "usePerformance",
|
|
1726
|
+
preloadAssets: "usePreload",
|
|
1727
|
+
preloadSkylineView: "usePreload",
|
|
1728
|
+
preloadWebview: "usePreload",
|
|
1729
|
+
preDownloadSubpackage: "usePreload",
|
|
1730
|
+
cropImage: "useImageEdit",
|
|
1731
|
+
editImage: "useImageEdit",
|
|
1732
|
+
// 网络底层 / 媒体高级(C69-C70——批 E 补齐,2026-09-12)
|
|
1733
|
+
createUDPSocket: "useSocket.udp",
|
|
1734
|
+
createTCPSocket: "useSocket.tcp",
|
|
1735
|
+
createMediaContainer: "useMediaProcessing.container",
|
|
1736
|
+
createVideoDecoder: "useMediaProcessing.videoDecoder",
|
|
1737
|
+
createMediaAudioPlayer: "useMediaProcessing.audioPlayer",
|
|
1738
|
+
// 录屏/缓存/空闲/窗口/导航拦截(C71-C75——批 F 补齐,2026-09-12)
|
|
1739
|
+
getScreenRecordingState: "useScreenCapture",
|
|
1740
|
+
onScreenRecordingStateChanged: "useScreenCapture",
|
|
1741
|
+
offScreenRecordingStateChanged: "useScreenCapture",
|
|
1742
|
+
onUserCaptureScreen: "useScreenCapture",
|
|
1743
|
+
offUserCaptureScreen: "useScreenCapture",
|
|
1744
|
+
checkIsPictureInPictureActive: "useScreenCapture",
|
|
1745
|
+
createCacheManager: "useCacheManager",
|
|
1746
|
+
requestIdleCallback: "useIdle",
|
|
1747
|
+
cancelIdleCallback: "useIdle",
|
|
1748
|
+
setWindowSize: "useWindow",
|
|
1749
|
+
enableAlertBeforeUnload: "useNavigationGuard",
|
|
1750
|
+
disableAlertBeforeUnload: "useNavigationGuard",
|
|
1751
|
+
// AR/XR / iBeacon / 局域网 / 翻译 / 海报 / 设备探测(C76-C81——批 G 补齐,2026-09-12)
|
|
1752
|
+
createVKSession: "useAR",
|
|
1753
|
+
isVKSupport: "useAR",
|
|
1754
|
+
checkDeviceSupportHevc: "useDeviceCapability",
|
|
1755
|
+
onUserTriggerTranslation: "useTranslation",
|
|
1756
|
+
offUserTriggerTranslation: "useTranslation",
|
|
1757
|
+
onUserOffTranslation: "useTranslation",
|
|
1758
|
+
offUserOffTranslation: "useTranslation",
|
|
1759
|
+
onGeneratePoster: "usePoster",
|
|
1760
|
+
offGeneratePoster: "usePoster"
|
|
1761
|
+
};
|
|
1762
|
+
var SPEC_PRIVATE = /* @__PURE__ */ new Set([
|
|
1763
|
+
// 支付 / 交通卡 / 离线支付
|
|
1764
|
+
"addPaymentPassFinish",
|
|
1765
|
+
"addPaymentPassGetCertificateData",
|
|
1766
|
+
"canAddSecureElementPass",
|
|
1767
|
+
"getSecureElementPasses",
|
|
1768
|
+
"removeSecureElementPass",
|
|
1769
|
+
"checkTransitCardSupport",
|
|
1770
|
+
"getTransitCardCPLC",
|
|
1771
|
+
"getTransitCardInfo",
|
|
1772
|
+
"getTransitCardList",
|
|
1773
|
+
"issueTransitCard",
|
|
1774
|
+
"rechargeTransitCard",
|
|
1775
|
+
"deleteTransitCard",
|
|
1776
|
+
"createGlobalPayment",
|
|
1777
|
+
"requestCommonPayment",
|
|
1778
|
+
"requestVirtualPayment",
|
|
1779
|
+
"requestPluginPayment",
|
|
1780
|
+
"requestAppleSubscribeSign",
|
|
1781
|
+
"jumpToOfflinePay",
|
|
1782
|
+
"openHKOfflinePayView",
|
|
1783
|
+
"requestMerchantTransfer",
|
|
1784
|
+
"openInquiriesTopic",
|
|
1785
|
+
"openHKOfflinePayView",
|
|
1786
|
+
// 视频号 / 直播频道
|
|
1787
|
+
"getChannelsLiveInfo",
|
|
1788
|
+
"getChannelsLiveNoticeInfo",
|
|
1789
|
+
"getChannelsShareKey",
|
|
1790
|
+
"openChannelsActivity",
|
|
1791
|
+
"openChannelsEvent",
|
|
1792
|
+
"openChannelsLive",
|
|
1793
|
+
"openChannelsLiveNoticeInfo",
|
|
1794
|
+
"openChannelsUserProfile",
|
|
1795
|
+
"reserveChannelsLive",
|
|
1796
|
+
// VoIP / 客服会话
|
|
1797
|
+
"getDeviceVoIPList",
|
|
1798
|
+
"requestDeviceVoIP",
|
|
1799
|
+
"joinVoIPChat",
|
|
1800
|
+
"setEnable1v1Chat",
|
|
1801
|
+
"join1v1Chat",
|
|
1802
|
+
"enterChatToolMode",
|
|
1803
|
+
"onVoIPChatInterrupted",
|
|
1804
|
+
"offVoIPChatInterrupted",
|
|
1805
|
+
"onVoIPChatMembersChanged",
|
|
1806
|
+
"offVoIPChatMembersChanged",
|
|
1807
|
+
"onVoIPChatSpeakersChanged",
|
|
1808
|
+
"offVoIPChatSpeakersChanged",
|
|
1809
|
+
"onVoIPChatStateChanged",
|
|
1810
|
+
"offVoIPChatStateChanged",
|
|
1811
|
+
"onVoIPVideoMembersChanged",
|
|
1812
|
+
"offVoIPVideoMembersChanged",
|
|
1813
|
+
// 人脸核身 / 类目资质
|
|
1814
|
+
"startFacialRecognitionVerify",
|
|
1815
|
+
"checkIsSupportFacialRecognition",
|
|
1816
|
+
"requestFacialVerify",
|
|
1817
|
+
"faceDetect",
|
|
1818
|
+
"initFaceDetect",
|
|
1819
|
+
"stopFaceDetect",
|
|
1820
|
+
"setVisualEffectOnCapture",
|
|
1821
|
+
// AI 推理(类目)
|
|
1822
|
+
"createInferenceSession",
|
|
1823
|
+
"getInferenceEnvInfo",
|
|
1824
|
+
// 企业 / 员工关系
|
|
1825
|
+
"bindEmployeeRelation",
|
|
1826
|
+
"checkEmployeeRelation",
|
|
1827
|
+
"requestSubscribeEmployeeMessage",
|
|
1828
|
+
"authPrivateMessage",
|
|
1829
|
+
// 插件
|
|
1830
|
+
"pluginLogin",
|
|
1831
|
+
"getPluginUpdateManager",
|
|
1832
|
+
"authorizeForMiniProgram",
|
|
1833
|
+
// 营销 / 门店 / 贴纸 / 公众号
|
|
1834
|
+
"openDesignerProfile",
|
|
1835
|
+
"openOfficialAccountArticle",
|
|
1836
|
+
"openOfficialAccountChat",
|
|
1837
|
+
"openOfficialAccountProfile",
|
|
1838
|
+
"shareToOfficialAccount",
|
|
1839
|
+
"postMessageToReferrerMiniProgram",
|
|
1840
|
+
"postMessageToReferrerPage",
|
|
1841
|
+
"openSingleStickerView",
|
|
1842
|
+
"openStickerIPView",
|
|
1843
|
+
"openStickerSetView",
|
|
1844
|
+
"openStoreCouponDetail",
|
|
1845
|
+
"openStoreOrderDetail",
|
|
1846
|
+
"openVideoEditor",
|
|
1847
|
+
// 加密 / 群入口 / 扩展配置
|
|
1848
|
+
"getUserCryptoManager",
|
|
1849
|
+
"getGroupEnterInfo",
|
|
1850
|
+
"getExtConfigSync",
|
|
1851
|
+
"getCommonConfig",
|
|
1852
|
+
"getExptInfoSync",
|
|
1853
|
+
// 后台音频(旧)/ 小程序互跳 / 路由重写
|
|
1854
|
+
"getBackgroundAudioManager",
|
|
1855
|
+
"onBackgroundAudioPause",
|
|
1856
|
+
"onBackgroundAudioPlay",
|
|
1857
|
+
"onBackgroundAudioStop",
|
|
1858
|
+
"openEmbeddedMiniProgram",
|
|
1859
|
+
"exitMiniProgram",
|
|
1860
|
+
"restartMiniProgram",
|
|
1861
|
+
"rewriteRoute",
|
|
1862
|
+
"onEmbeddedMiniProgramHeightChange",
|
|
1863
|
+
"offEmbeddedMiniProgramHeightChange",
|
|
1864
|
+
"openData",
|
|
1865
|
+
// 小程序归属 / 开屏广告 / XR 系统(微信私有)
|
|
1866
|
+
"checkIsAddedToMyMiniProgram",
|
|
1867
|
+
"getShowSplashAdStatus",
|
|
1868
|
+
"getXrFrameSystem"
|
|
1869
|
+
]);
|
|
1870
|
+
var SPEC_NA = /* @__PURE__ */ new Set([
|
|
1871
|
+
// 废弃路由事件(wx.router 前身)
|
|
1872
|
+
"onAppRoute",
|
|
1873
|
+
"offAppRoute",
|
|
1874
|
+
"onAppRouteDone",
|
|
1875
|
+
"offAppRouteDone",
|
|
1876
|
+
"onBeforeAppRoute",
|
|
1877
|
+
"offBeforeAppRoute",
|
|
1878
|
+
// 废弃音频(→ createWebAudioContext)
|
|
1879
|
+
"createAudioContext",
|
|
1880
|
+
// 构建期动态路径(编译期解析,无运行期 API)
|
|
1881
|
+
"resolve",
|
|
1882
|
+
// 内置字体(宿主排版层)
|
|
1883
|
+
"loadBuiltInFontFace",
|
|
1884
|
+
// 并行状态(试验特性,已废弃)
|
|
1885
|
+
"onParallelStateChange",
|
|
1886
|
+
"offParallelStateChange",
|
|
1887
|
+
// 系统信息旧版(新工程用 getWindowInfo/getDeviceInfo/getAppBaseInfo)
|
|
1888
|
+
"getSystemInfoAsync",
|
|
1889
|
+
// 调度原语(Vue nextTick / 渲染器调度等价,非平台能力)
|
|
1890
|
+
"nextTick"
|
|
1891
|
+
]);
|
|
1892
|
+
var SPEC_PLANNED = {
|
|
1893
|
+
// 网络底层(已由 C69 useSocket 覆盖——见 SPEC_COVERED)
|
|
1894
|
+
// 媒体高级(已由 C70 useMediaProcessing 覆盖——见 SPEC_COVERED)
|
|
1895
|
+
// 图像编辑(已由 C68 useImageEdit 覆盖——见 SPEC_COVERED)
|
|
1896
|
+
// 性能(已由 C66 usePerformance 覆盖——见 SPEC_COVERED)
|
|
1897
|
+
// 录屏 / 画中画(已由 C71 useScreenCapture 覆盖——见 SPEC_COVERED + EVENT_BASE covered)
|
|
1898
|
+
// 预加载 / 分包(已由 C67 usePreload 覆盖——见 SPEC_COVERED)
|
|
1899
|
+
// AR / XR(已由 C76 useAR 覆盖——见 SPEC_COVERED)
|
|
1900
|
+
// 缓存管理 / 窗口 / 卸载拦截(已由 C72/C74/C75 覆盖——见 SPEC_COVERED)
|
|
1901
|
+
// 调度(已由 C73 useIdle 覆盖——见 SPEC_COVERED)
|
|
1902
|
+
// 设备能力探测(已由 C81 useDeviceCapability 覆盖——见 SPEC_COVERED)
|
|
1903
|
+
};
|
|
1904
|
+
var EVENT_BASE = {
|
|
1905
|
+
// 映射既有 Hook(covered)
|
|
1906
|
+
onCopyUrl: { status: "covered", proteus: "useClipboard" },
|
|
1907
|
+
offCopyUrl: { status: "covered", proteus: "useClipboard" },
|
|
1908
|
+
onAudioInterruptionBegin: { status: "covered", proteus: "useBackground" },
|
|
1909
|
+
offAudioInterruptionBegin: { status: "covered", proteus: "useBackground" },
|
|
1910
|
+
onAudioInterruptionEnd: { status: "covered", proteus: "useBackground" },
|
|
1911
|
+
offAudioInterruptionEnd: { status: "covered", proteus: "useBackground" },
|
|
1912
|
+
onBackgroundFetchData: { status: "covered", proteus: "useBackground" },
|
|
1913
|
+
offBackgroundFetchData: { status: "covered", proteus: "useBackground" },
|
|
1914
|
+
onMenuButtonBoundingClientRectWeightChange: { status: "covered", proteus: "useElement" },
|
|
1915
|
+
offMenuButtonBoundingClientRectWeightChange: { status: "covered", proteus: "useElement" },
|
|
1916
|
+
onApiCategoryChange: { status: "covered", proteus: "useDevice" },
|
|
1917
|
+
offApiCategoryChange: { status: "covered", proteus: "useDevice" },
|
|
1918
|
+
onWindowStateChange: { status: "covered", proteus: "useAppLifecycle" },
|
|
1919
|
+
offWindowStateChange: { status: "covered", proteus: "useAppLifecycle" },
|
|
1920
|
+
onBLEPeripheralConnectionStateChanged: { status: "covered", proteus: "useBluetooth" },
|
|
1921
|
+
offBLEPeripheralConnectionStateChanged: { status: "covered", proteus: "useBluetooth" },
|
|
1922
|
+
// 批 G:iBeacon / 局域网 mDNS(covered——C77/C78)
|
|
1923
|
+
onBeaconServiceChange: { status: "covered", proteus: "useBeacon" },
|
|
1924
|
+
offBeaconServiceChange: { status: "covered", proteus: "useBeacon" },
|
|
1925
|
+
onBeaconUpdate: { status: "covered", proteus: "useBeacon" },
|
|
1926
|
+
offBeaconUpdate: { status: "covered", proteus: "useBeacon" },
|
|
1927
|
+
onLocalServiceFound: { status: "covered", proteus: "useLocalService" },
|
|
1928
|
+
offLocalServiceFound: { status: "covered", proteus: "useLocalService" },
|
|
1929
|
+
onLocalServiceLost: { status: "covered", proteus: "useLocalService" },
|
|
1930
|
+
offLocalServiceLost: { status: "covered", proteus: "useLocalService" },
|
|
1931
|
+
onLocalServiceResolveFail: { status: "covered", proteus: "useLocalService" },
|
|
1932
|
+
offLocalServiceResolveFail: { status: "covered", proteus: "useLocalService" },
|
|
1933
|
+
onLocalServiceDiscoveryStop: { status: "covered", proteus: "useLocalService" },
|
|
1934
|
+
offLocalServiceDiscoveryStop: { status: "covered", proteus: "useLocalService" },
|
|
1935
|
+
// 批 G:录屏(covered——C71)/ 翻译(covered——C79)/ 海报(covered——C80)
|
|
1936
|
+
onScreenRecordingStateChanged: { status: "covered", proteus: "useScreenCapture" },
|
|
1937
|
+
offScreenRecordingStateChanged: { status: "covered", proteus: "useScreenCapture" },
|
|
1938
|
+
onUserCaptureScreen: { status: "covered", proteus: "useScreenCapture" },
|
|
1939
|
+
offUserCaptureScreen: { status: "covered", proteus: "useScreenCapture" },
|
|
1940
|
+
onUserTriggerTranslation: { status: "covered", proteus: "useTranslation" },
|
|
1941
|
+
offUserTriggerTranslation: { status: "covered", proteus: "useTranslation" },
|
|
1942
|
+
onUserOffTranslation: { status: "covered", proteus: "useTranslation" },
|
|
1943
|
+
offUserOffTranslation: { status: "covered", proteus: "useTranslation" },
|
|
1944
|
+
onGeneratePoster: { status: "covered", proteus: "usePoster" },
|
|
1945
|
+
offGeneratePoster: { status: "covered", proteus: "usePoster" }
|
|
1946
|
+
};
|
|
1947
|
+
function classifySpecApi(name) {
|
|
1948
|
+
if (name in SPEC_COVERED) return { status: "covered", proteus: SPEC_COVERED[name] };
|
|
1949
|
+
if (SPEC_PRIVATE.has(name)) return { status: "private" };
|
|
1950
|
+
if (SPEC_NA.has(name)) return { status: "na" };
|
|
1951
|
+
if (name in SPEC_PLANNED) return { status: "planned", proteus: SPEC_PLANNED[name] };
|
|
1952
|
+
if (name in EVENT_BASE) return EVENT_BASE[name];
|
|
1953
|
+
return { status: "gap" };
|
|
1954
|
+
}
|
|
1955
|
+
function classifySpecComponent(tag, matrix) {
|
|
1956
|
+
if (tag in SPEC_COMPONENT_OVERRIDE) return SPEC_COMPONENT_OVERRIDE[tag];
|
|
1957
|
+
const row = matrix.find((r) => r.mp === `<${tag}>`);
|
|
1958
|
+
if (!row) return { status: "gap" };
|
|
1959
|
+
if (row.planned) return { status: "planned" };
|
|
1960
|
+
if (row.status === "private") return { status: "private" };
|
|
1961
|
+
if (row.status === "missing") return { status: "gap" };
|
|
1962
|
+
return { status: "covered" };
|
|
1963
|
+
}
|
|
1964
|
+
var SPEC_COMPONENT_OVERRIDE = {
|
|
1965
|
+
// 语义消灭为子项/属性(表单分组、多列选择)
|
|
1966
|
+
"checkbox-group": { status: "na", proteus: "p-checkbox \u5206\u7EC4\uFF08\u6D88\u706D\u4E3A\u5B50\u9879\uFF09" },
|
|
1967
|
+
"radio-group": { status: "na", proteus: "p-radio \u5206\u7EC4\uFF08\u6D88\u706D\u4E3A\u5B50\u9879\uFF09" },
|
|
1968
|
+
"picker-view-column": { status: "na", proteus: "p-picker \u591A\u5217\uFF08\u6D88\u706D\u4E3A\u5C5E\u6027\uFF09" },
|
|
1969
|
+
// Skyline 手势处理器 → 手势原语(gesture.* / v-gesture)
|
|
1970
|
+
// ★2026-09-18 诚实性修正:以下 5 条原标 covered,但其指向的 gesture 原语在 PRIMITIVE_CATALOG 中
|
|
1971
|
+
// 为 **planned**(`gesture.long-press` 更是拼写错误——实际名为 `gesture.longpress`)。
|
|
1972
|
+
// covered 的定义是「有可运行等价」,而统一手势 API(`v-gesture:*`)尚未落地 →
|
|
1973
|
+
// 按实测状态改标 planned(与 2026-09-16 属性标尺虚高同类修正:数字不粉饰)。
|
|
1974
|
+
// ★2026-09-18 复评:tap/longpress **已据实转 covered**(编译器新增 directive/v-gesture 规则,
|
|
1975
|
+
// 双端原生事件对等:MP bindtap/bindlongpress、Web Pointer 识别器);pan/pinch/press 仍 planned
|
|
1976
|
+
// (MP 无事件对等——官方是 worklet 手势处理器<组件>,非事件属性)。
|
|
1977
|
+
// ★同时新增 auditSpecOverrideRefs 门禁——此前 override 表**完全不在引用校验范围内**,
|
|
1978
|
+
// 故这 5 条虚高 + 1 处悬空引用长期未被发现。
|
|
1979
|
+
"tap-gesture-handler": { status: "covered", proteus: "gesture.tap\uFF08\u26052026-09-18 \u843D\u5730\uFF1A\u7F16\u8BD1\u5668 v-gesture:tap \u2192 bindtap\u2014\u2014MP \u539F\u751F\u4E8B\u4EF6\u5BF9\u7B49\uFF09" },
|
|
1980
|
+
// ★2026-09-19 诚实性修正(与本文件 `gesture.long-press` 拼写错误同类):本节原标 `covered`
|
|
1981
|
+
// 且引用 `gesture.draggable`(**拖拽**语义)——两处都不成立:
|
|
1982
|
+
// ① 引用错位:双击识别在 `gesture.tap` 的 `count`/`dblTapWindow`(recognizers.ts:229),
|
|
1983
|
+
// 与 draggable(G8 = movable-view 拖拽)无关;
|
|
1984
|
+
// ② MP 无对等:`v-gesture:tap` 在 MP 只映射 bindtap(原生事件不带 count),编译器亦无 count
|
|
1985
|
+
// 处理 → 双击语义仅 Web 成立。
|
|
1986
|
+
// ⇒ 按 pan/scale/force-press 同一标准(MP 无原生对等即 planned)据实改标 `planned`。
|
|
1987
|
+
// ★该错位长期漏网,因 auditSpecOverrideRefs 当时只校验「引用存在且已落地」——
|
|
1988
|
+
// 本轮补 GESTURE_HANDLER_EXPECTED 语义配对门禁(同类错位今后必红)。
|
|
1989
|
+
"double-tap-gesture-handler": { status: "planned", proteus: "gesture.tap \u7684 count \u53D8\u4F53\uFF08Web \u8BC6\u522B\u5668\u652F\u6301\u53CC\u51FB\uFF1BMP \u539F\u751F bindtap \u4E0D\u5E26 count\uFF0C\u65E0\u5BF9\u7B49\uFF09" },
|
|
1990
|
+
"long-press-gesture-handler": { status: "covered", proteus: "gesture.longpress\uFF08\u26052026-09-18 \u843D\u5730\uFF1A\u7F16\u8BD1\u5668 v-gesture:longpress \u2192 bindlongpress\u2014\u2014MP \u539F\u751F\u4E8B\u4EF6\u5BF9\u7B49\uFF09" },
|
|
1991
|
+
"pan-gesture-handler": { status: "planned", proteus: "gesture.pan\uFF08v-gesture:pan \u89C4\u5212\u4E2D\uFF09" },
|
|
1992
|
+
"scale-gesture-handler": { status: "planned", proteus: "gesture.pinch\uFF08v-gesture:pinch \u89C4\u5212\u4E2D\uFF09" },
|
|
1993
|
+
"force-press-gesture-handler": { status: "planned", proteus: "gesture.press\uFF08v-gesture:press \u89C4\u5212\u4E2D\uFF09" },
|
|
1994
|
+
"horizontal-drag-gesture-handler": { status: "covered", proteus: "gesture.draggable" },
|
|
1995
|
+
"vertical-drag-gesture-handler": { status: "covered", proteus: "gesture.draggable" },
|
|
1996
|
+
// Skyline 布局构建器 → 布局语义
|
|
1997
|
+
"grid-builder": { status: "covered", proteus: "layout.grid" },
|
|
1998
|
+
"list-builder": { status: "covered", proteus: "layout.virtual-list" },
|
|
1999
|
+
"nested-scroll-body": { status: "covered", proteus: "layout.scroll\uFF08\u5D4C\u5957\u6EDA\u52A8\uFF09" },
|
|
2000
|
+
"nested-scroll-header": { status: "covered", proteus: "layout.scroll\uFF08\u5D4C\u5957\u6EDA\u52A8\uFF09" },
|
|
2001
|
+
"draggable-sheet": { status: "covered", proteus: "shell.page-container\uFF08\u534A\u5C4F\u53EF\u62D6\uFF09" },
|
|
2002
|
+
// aria-component 是 ARIA 属性文档页(非组件标签)——ARIA 属性两端原生支持(aria-label/aria-role)
|
|
2003
|
+
"aria-component": { status: "na", proteus: "\u2014\uFF08ARIA \u5C5E\u6027\u6587\u6863\u9875\uFF1Baria-* \u4E24\u7AEF\u539F\u751F\u652F\u6301\uFF0C\u7EC4\u4EF6\u5DF2\u5E26 ariaLabel\uFF09" },
|
|
2004
|
+
// Skyline 同层渲染后冗余(官方:建议用 view 替代 cover-view/cover-image)
|
|
2005
|
+
"cover-view": { status: "na", proteus: "\u2014\uFF08\u540C\u5C42\u6E32\u67D3\u540E\u5197\u4F59\uFF0C\u7528 layout.box \u66FF\u4EE3\uFF09" },
|
|
2006
|
+
"cover-image": { status: "na", proteus: "\u2014\uFF08\u540C\u5C42\u6E32\u67D3\u540E\u5197\u4F59\uFF0C\u7528 ui.image \u66FF\u4EE3\uFF09" },
|
|
2007
|
+
// 表单/富文本/文本片段 → 语义承接(★批 H:keyboard-accessory/selection 已全端真实落地)
|
|
2008
|
+
"keyboard-accessory": { status: "covered", proteus: "shell.keyboard-accessory\uFF08p-keyboard-accessory\uFF09" },
|
|
2009
|
+
selection: { status: "covered", proteus: "ui.selection\uFF08p-selection\uFF09" },
|
|
2010
|
+
span: { status: "na", proteus: "ui.text \u5185\u8054\uFF08\u6D88\u706D\u4E3A\u5B50\u5143\u7D20\uFF09" },
|
|
2011
|
+
"editor-portal": { status: "na", proteus: "ui.rich-text \u5185\u8054\uFF08\u6D88\u706D\u4E3A\u5B50\u5143\u7D20\uFF09" },
|
|
2012
|
+
"native-component": { status: "private", proteus: "\uFF08\u5FAE\u4FE1\u539F\u751F\u7EC4\u4EF6\u6269\u5C55\u70B9\uFF0C\u975E\u76EE\u6807\uFF09" },
|
|
2013
|
+
"official-account-publish": { status: "private", proteus: "\uFF08\u5FAE\u4FE1\u516C\u4F17\u53F7\u53D1\u5E03\uFF0C\u79C1\u6709\uFF09" },
|
|
2014
|
+
"open-data-item": { status: "private", proteus: "\uFF08\u5FAE\u4FE1\u5F00\u653E\u6570\u636E\u9879\uFF0C\u79C1\u6709\uFF09" },
|
|
2015
|
+
"open-data-list": { status: "private", proteus: "\uFF08\u5FAE\u4FE1\u5F00\u653E\u6570\u636E\u5217\u8868\uFF0C\u79C1\u6709\uFF09" },
|
|
2016
|
+
// 视频号 / 营销(类目资质)
|
|
2017
|
+
"channel-live": { status: "private", proteus: "\uFF08\u89C6\u9891\u53F7\u76F4\u64AD\uFF0C\u79C1\u6709\uFF09" },
|
|
2018
|
+
"channel-video": { status: "private", proteus: "\uFF08\u89C6\u9891\u53F7\u89C6\u9891\uFF0C\u79C1\u6709\uFF09" },
|
|
2019
|
+
"ad-custom": { status: "private", proteus: "\uFF08\u5FAE\u4FE1\u81EA\u5B9A\u4E49\u5E7F\u544A\uFF0C\u79C1\u6709\uFF09" },
|
|
2020
|
+
reward: { status: "private", proteus: "\uFF08\u5FAE\u4FE1\u6FC0\u52B1\u5956\u52B1\u7EC4\u4EF6\uFF0C\u79C1\u6709\uFF09" },
|
|
2021
|
+
"store-coupon": { status: "private", proteus: "\uFF08\u5FAE\u4FE1\u5C0F\u5E97\u4F18\u60E0\u5238\uFF0C\u79C1\u6709\uFF09" },
|
|
2022
|
+
"store-gift": { status: "private", proteus: "\uFF08\u5FAE\u4FE1\u5C0F\u5E97\u793C\u54C1\uFF0C\u79C1\u6709\uFF09" },
|
|
2023
|
+
"store-home": { status: "private", proteus: "\uFF08\u5FAE\u4FE1\u5C0F\u5E97\u4E3B\u9875\uFF0C\u79C1\u6709\uFF09" },
|
|
2024
|
+
"store-product": { status: "private", proteus: "\uFF08\u5FAE\u4FE1\u5C0F\u5E97\u5546\u54C1\uFF0C\u79C1\u6709\uFF09" }
|
|
2025
|
+
};
|
|
2026
|
+
var GESTURE_HANDLER_EXPECTED = {
|
|
2027
|
+
"tap-gesture-handler": "gesture.tap",
|
|
2028
|
+
"double-tap-gesture-handler": "gesture.tap",
|
|
2029
|
+
// 语义上属 tap 的 count 变体(当前 planned——MP 无对等)
|
|
2030
|
+
"long-press-gesture-handler": "gesture.longpress",
|
|
2031
|
+
"pan-gesture-handler": "gesture.pan",
|
|
2032
|
+
"scale-gesture-handler": "gesture.pinch",
|
|
2033
|
+
"force-press-gesture-handler": "gesture.press",
|
|
2034
|
+
"horizontal-drag-gesture-handler": "gesture.draggable",
|
|
2035
|
+
"vertical-drag-gesture-handler": "gesture.draggable"
|
|
2036
|
+
};
|
|
2037
|
+
function auditSpecOverrideRefs(catalog, overrideTable = SPEC_COMPONENT_OVERRIDE) {
|
|
2038
|
+
const bySemantic = new Map(catalog.map((p) => [p.semantic, p]));
|
|
2039
|
+
const byTag = new Map(catalog.filter((p) => p.tag).map((p) => [p.tag, p]));
|
|
2040
|
+
const issues = [];
|
|
2041
|
+
let coveredRefs = 0;
|
|
2042
|
+
for (const [tag, cls] of Object.entries(overrideTable)) {
|
|
2043
|
+
if (cls.status !== "covered") continue;
|
|
2044
|
+
const text = cls.proteus ?? "";
|
|
2045
|
+
const expected = GESTURE_HANDLER_EXPECTED[tag];
|
|
2046
|
+
if (expected) {
|
|
2047
|
+
const gestureRefs = [...text.matchAll(/\bgesture\.[a-z][\w-]*/g)].map((m) => m[0]).filter((r) => bySemantic.has(r));
|
|
2048
|
+
if (gestureRefs.length > 0 && !gestureRefs.includes(expected)) {
|
|
2049
|
+
issues.push({ mp: tag, ref: expected, kind: "mismatched" });
|
|
2050
|
+
}
|
|
2051
|
+
}
|
|
2052
|
+
for (const m of text.matchAll(/\b(?:layout|ui|shell|gesture|capability|engineering)\.[a-z][\w-]*/g)) {
|
|
2053
|
+
coveredRefs++;
|
|
2054
|
+
const p = bySemantic.get(m[0]);
|
|
2055
|
+
if (!p) issues.push({ mp: tag, ref: m[0], kind: "semantic" });
|
|
2056
|
+
else if (p.status === "planned") issues.push({ mp: tag, ref: m[0], kind: "unimplemented" });
|
|
2057
|
+
}
|
|
2058
|
+
for (const m of text.matchAll(/\bp-[a-z][\w-]*/g)) {
|
|
2059
|
+
coveredRefs++;
|
|
2060
|
+
const p = byTag.get(m[0]);
|
|
2061
|
+
if (!p) issues.push({ mp: tag, ref: m[0], kind: "component" });
|
|
2062
|
+
else if (p.status === "planned") issues.push({ mp: tag, ref: m[0], kind: "unimplemented" });
|
|
2063
|
+
}
|
|
2064
|
+
}
|
|
2065
|
+
return { issues, coveredRefs };
|
|
2066
|
+
}
|
|
2067
|
+
function auditSpecCoverage(spec, matrix) {
|
|
2068
|
+
const counts = { covered: 0, planned: 0, private: 0, na: 0, gap: 0 };
|
|
2069
|
+
const gaps = [];
|
|
2070
|
+
const plannedItems = [];
|
|
2071
|
+
for (const tag of spec.components) {
|
|
2072
|
+
const c = classifySpecComponent(tag, matrix);
|
|
2073
|
+
counts[c.status]++;
|
|
2074
|
+
if (c.status === "gap") gaps.push({ kind: "component", name: tag });
|
|
2075
|
+
if (c.status === "planned") plannedItems.push({ kind: "component", name: tag, proteus: c.proteus });
|
|
2076
|
+
}
|
|
2077
|
+
for (const api of spec.apis) {
|
|
2078
|
+
const c = classifySpecApi(api);
|
|
2079
|
+
counts[c.status]++;
|
|
2080
|
+
if (c.status === "gap") gaps.push({ kind: "api", name: api });
|
|
2081
|
+
if (c.status === "planned") plannedItems.push({ kind: "api", name: api, proteus: c.proteus });
|
|
2082
|
+
}
|
|
2083
|
+
const total = spec.components.length + spec.apis.length;
|
|
2084
|
+
const actionable = counts.covered + counts.planned;
|
|
2085
|
+
return {
|
|
2086
|
+
total,
|
|
2087
|
+
covered: counts.covered,
|
|
2088
|
+
planned: counts.planned,
|
|
2089
|
+
private: counts.private,
|
|
2090
|
+
na: counts.na,
|
|
2091
|
+
gap: counts.gap,
|
|
2092
|
+
accounted: total - counts.gap,
|
|
2093
|
+
classifiedPercent: total === 0 ? 0 : Math.round((total - counts.gap) / total * 100),
|
|
2094
|
+
actionable,
|
|
2095
|
+
landedPercent: actionable === 0 ? 100 : Math.floor(counts.covered / actionable * 100),
|
|
2096
|
+
// ★floor(永不夸大——99.6% 显示 99 而非 100)
|
|
2097
|
+
gaps,
|
|
2098
|
+
plannedItems
|
|
2099
|
+
};
|
|
2100
|
+
}
|
|
2101
|
+
var SPEC_RATCHET = {
|
|
2102
|
+
// ★2026-09-18 水位修正(非回退):255 → 250(含 5 条手势虚高);同日后又 **250 → 252**
|
|
2103
|
+
// (其中 tap/longpress 经编译器落地,见下)。原 255 基线**含 5 条虚高**
|
|
2104
|
+
// (tap/long-press/pan/scale/force-press-gesture-handler 标 covered,但其手势原语为 planned)。
|
|
2105
|
+
// 修正后实测 covered 250 / planned 6(share-element + 5 手势)/ private 106 / na 20 / gap 0。
|
|
2106
|
+
// 这与 2026-09-16「属性总数 793→771」属同类修正——**修的是标尺,不是能力**:
|
|
2107
|
+
// 真实可运行的等价物一件没少,只是不再把「规划中」记成「已落地」。
|
|
2108
|
+
// ★今后此值只增不减;若因**同类诚实性修正**需下调,必须在本注释写明被修正的具体条目。
|
|
2109
|
+
// ★2026-09-18 上调 250 → 252:tap/longpress 手势**真实落地**(编译器 directive/v-gesture 规则
|
|
2110
|
+
// → MP bindtap/bindlongpress + Web Pointer 识别器),spec 分类据实由 planned 转 covered。
|
|
2111
|
+
// 与上次的「下调」性质相反——这次是**能力真实增长**(真·落地率 97%→98%)。
|
|
2112
|
+
// ★2026-09-19 诚实性修正(下行 253→252,属「修标尺不是修能力」):`double-tap-gesture-handler`
|
|
2113
|
+
// 原标 covered 且引用 `gesture.draggable`(拖拽)——引用错位 + MP 无对等(bindtap 不带 count)
|
|
2114
|
+
// ⇒ 据实转 planned。**真实可运行的等价物一件没少**,只是不再把「仅 Web 成立」记成「两端已落地」。
|
|
2115
|
+
// 该条即上次注释要求「因诚实性修正需下调时,必须写明被修正的具体条目」所指的条目。
|
|
2116
|
+
coveredMin: 252,
|
|
2117
|
+
// 2026-09-18 上行基线(250 修正基线 + tap/longpress 落地);2026-09-19 因 double-tap 修正后实测亦为 252
|
|
2118
|
+
gapMax: 0
|
|
2119
|
+
// 全部官方项必须归类
|
|
2120
|
+
};
|
|
2121
|
+
|
|
2122
|
+
// src/degradation.ts
|
|
2123
|
+
var PRIVATE_WEB_FALLBACK = {
|
|
2124
|
+
openType: "Web \u89E6\u53D1\u540C\u540D\u4E8B\u4EF6\uFF08\u5982 @contact\uFF09+ console \u63D0\u793A\u81EA\u5B9A\u4E49\u5BF9\u5E94\u4EA4\u4E92\uFF08\u53C2\u8003 Web p-button open-type\uFF09",
|
|
2125
|
+
appId: "Web \u65E0\u8DE8\u5E94\u7528\u8DF3\u8F6C\u80FD\u529B\uFF0C\u4EC5\u56DE\u663E\u53C2\u6570\u5E76\u63D0\u793A",
|
|
2126
|
+
shortLink: "Web \u65E0\u77ED\u94FE\u8DF3\u8F6C\u80FD\u529B\uFF0C\u4EC5\u56DE\u663E\u53C2\u6570\u5E76\u63D0\u793A",
|
|
2127
|
+
unitId: "Web \u65E0\u5BBF\u4E3B\u5E7F\u544A\u4F4D\uFF0C\u6E32\u67D3\u5360\u4F4D\u5E76\u63D0\u793A\uFF08\u4E0D\u9759\u9ED8\uFF09",
|
|
2128
|
+
adType: "Web \u65E0\u5BBF\u4E3B\u5E7F\u544A\u7C7B\u578B\uFF0C\u5FFD\u7565\u5E76\u63D0\u793A",
|
|
2129
|
+
adTheme: "Web \u65E0\u5BBF\u4E3B\u5E7F\u544A\u4E3B\u9898\uFF0C\u5FFD\u7565\u5E76\u63D0\u793A",
|
|
2130
|
+
adIntervals: "Web \u65E0\u5BBF\u4E3B\u5E7F\u544A\u81EA\u52A8\u5237\u65B0\uFF0C\u5FFD\u7565\u5E76\u63D0\u793A"
|
|
2131
|
+
};
|
|
2132
|
+
var STYLE_WEB_FALLBACK = {
|
|
2133
|
+
hoverClass: "\u6620\u5C04 CSS :active/:hover \u7C7B\uFF08\u6846\u67B6\u9ED8\u8BA4\u7C7B\u6052\u5728\uFF0C\u81EA\u5B9A\u4E49\u7C7B\u4F5C\u9644\u52A0\u2014\u2014T3\uFF09",
|
|
2134
|
+
hoverStartTime: "Web \u7528 CSS transition-delay \u8FD1\u4F3C\u6309\u538B\u8D77\u59CB\u5EF6\u65F6",
|
|
2135
|
+
hoverStayTime: "Web \u7528 CSS transition-duration \u8FD1\u4F3C\u6309\u538B\u505C\u7559\u65F6\u957F",
|
|
2136
|
+
hoverStopPropagation: "Web \u7528 CSS pointer-events \u963B\u65AD\u5B50\u7EA7\u53CD\u9988\u8FD1\u4F3C"
|
|
2137
|
+
};
|
|
2138
|
+
var MP_HOST_WEB_FALLBACK = {
|
|
2139
|
+
alwaysEmbed: "Web \u65E0\u540C\u5C42/\u975E\u540C\u5C42\u5207\u6362\u6982\u5FF5\uFF08input \u59CB\u7EC8\u5728\u6587\u6863\u6D41\uFF09\uFF0C\u5FFD\u7565\u5E76\u63D0\u793A",
|
|
2140
|
+
confirmHold: "Web \u65E0\u6CD5\u63A7\u5236\u8F6F\u952E\u76D8\u6536\u8D77\u65F6\u673A\uFF08\u7531\u6D4F\u89C8\u5668/\u7CFB\u7EDF\u51B3\u5B9A\uFF09\uFF0C\u5FFD\u7565\u5E76\u63D0\u793A",
|
|
2141
|
+
adjustPosition: "Web \u7531\u6D4F\u89C8\u5668\u81EA\u8EAB\u5904\u7406\u952E\u76D8\u5F39\u8D77\u65F6\u7684\u89C6\u53E3\u6EDA\u52A8\uFF0C\u5FFD\u7565\u5E76\u63D0\u793A",
|
|
2142
|
+
holdKeyboard: "Web \u65E0\u6CD5\u5728\u5931\u7126\u70B9\u51FB\u65F6\u4FDD\u6301\u952E\u76D8\uFF08\u6D4F\u89C8\u5668\u884C\u4E3A\uFF09\uFF0C\u5FFD\u7565\u5E76\u63D0\u793A",
|
|
2143
|
+
cursorColor: "Web \u8FD1\u4F3C\uFF1ACSS caret-color\uFF08\u5F53\u524D\u672A\u63A5\u7EBF\uFF0C\u5FFD\u7565\u5E76\u63D0\u793A\uFF09",
|
|
2144
|
+
selectionStart: "Web \u8FD1\u4F3C\uFF1AsetSelectionRange\uFF08\u5F53\u524D\u672A\u63A5\u7EBF\uFF0C\u5FFD\u7565\u5E76\u63D0\u793A\uFF09",
|
|
2145
|
+
selectionEnd: "Web \u8FD1\u4F3C\uFF1AsetSelectionRange\uFF08\u5F53\u524D\u672A\u63A5\u7EBF\uFF0C\u5FFD\u7565\u5E76\u63D0\u793A\uFF09",
|
|
2146
|
+
placeholderClass: "Web \u65E0\u300C\u5360\u4F4D\u7B26\u4E13\u7528\u7C7B\u540D\u300D\u901A\u9053\uFF08::placeholder \u4E0D\u53EF\u627F\u63A5\u4EFB\u610F\u7C7B\uFF09\uFF0C\u5FFD\u7565\u5E76\u63D0\u793A",
|
|
2147
|
+
safePasswordCertPath: "Web \u65E0\u5C0F\u7A0B\u5E8F\u5B89\u5168\u952E\u76D8\uFF08\u5BBF\u4E3B\u7EA7\u52A0\u5BC6\u952E\u76D8\uFF09\uFF0C\u5FFD\u7565\u5E76\u63D0\u793A",
|
|
2148
|
+
safePasswordLength: "Web \u65E0\u5C0F\u7A0B\u5E8F\u5B89\u5168\u952E\u76D8\uFF0C\u5FFD\u7565\u5E76\u63D0\u793A",
|
|
2149
|
+
safePasswordTimeStamp: "Web \u65E0\u5C0F\u7A0B\u5E8F\u5B89\u5168\u952E\u76D8\uFF0C\u5FFD\u7565\u5E76\u63D0\u793A",
|
|
2150
|
+
safePasswordNonce: "Web \u65E0\u5C0F\u7A0B\u5E8F\u5B89\u5168\u952E\u76D8\uFF0C\u5FFD\u7565\u5E76\u63D0\u793A",
|
|
2151
|
+
safePasswordSalt: "Web \u65E0\u5C0F\u7A0B\u5E8F\u5B89\u5168\u952E\u76D8\uFF0C\u5FFD\u7565\u5E76\u63D0\u793A",
|
|
2152
|
+
safePasswordCustomHash: "Web \u65E0\u5C0F\u7A0B\u5E8F\u5B89\u5168\u952E\u76D8\uFF0C\u5FFD\u7565\u5E76\u63D0\u793A",
|
|
2153
|
+
reportSubmit: "formId \u662F\u5C0F\u7A0B\u5E8F\u6A21\u677F\u6D88\u606F\u5BBF\u4E3B\u80FD\u529B\uFF0CWeb \u65E0\u5BF9\u5E94 \u2192 \u5FFD\u7565\u5E76\u63D0\u793A",
|
|
2154
|
+
reportSubmitTimeout: "formId \u662F\u5C0F\u7A0B\u5E8F\u6A21\u677F\u6D88\u606F\u5BBF\u4E3B\u80FD\u529B\uFF0CWeb \u65E0\u5BF9\u5E94 \u2192 \u5FFD\u7565\u5E76\u63D0\u793A"
|
|
2155
|
+
};
|
|
2156
|
+
var HOST_TAGS = {
|
|
2157
|
+
"p-map": "Web \u6A21\u62DF\u5C42\u6E32\u67D3\u9759\u6001\u5360\u4F4D\u5BB9\u5668\uFF0C\u5FFD\u7565\u8BE5\u5730\u56FE\u663E\u793A\u53C2\u6570\u5E76\u63D0\u793A",
|
|
2158
|
+
"p-media": "Web \u7528\u539F\u751F <video>\uFF0C\u5FFD\u7565\u8BE5\u64AD\u653E\u5668\u5916\u89C2/\u4E13\u6709\u53C2\u6570\u5E76\u63D0\u793A",
|
|
2159
|
+
"p-camera": "Web \u65E0\u6444\u50CF\u5934\u5BBF\u4E3B\uFF0C\u5FFD\u7565\u8BE5\u91C7\u96C6\u53C2\u6570\u5E76\u63D0\u793A\uFF08\u53EF\u9000\u5316 getUserMedia \u65F6\u53E6\u884C\u5B9E\u73B0\uFF09",
|
|
2160
|
+
"p-ad": "Web \u65E0\u5BBF\u4E3B\u5E7F\u544A\uFF0C\u5FFD\u7565\u8BE5\u5E7F\u544A\u53C2\u6570\u5E76\u63D0\u793A",
|
|
2161
|
+
"p-canvas": "Web \u7528 HTMLCanvasElement\uFF0C\u5FFD\u7565\u8BE5\u5C0F\u7A0B\u5E8F\u6E32\u67D3\u4E0A\u4E0B\u6587\u4E13\u6709\u53C2\u6570\u5E76\u63D0\u793A",
|
|
2162
|
+
"p-webview": "Web \u7528 <iframe>\uFF0C\u5FFD\u7565\u8BE5\u5C0F\u7A0B\u5E8F web-view \u4E13\u6709\u53C2\u6570\u5E76\u63D0\u793A"
|
|
2163
|
+
};
|
|
2164
|
+
var WEB_EXTENSION_MP_FALLBACK = {
|
|
2165
|
+
density: "\u5C0F\u7A0B\u5E8F\u65E0 DPI \u5BC6\u5EA6\u6982\u5FF5\uFF0C\u5FFD\u7565\u5E76\u63D0\u793A\uFF08rpx \u5DF2\u6309\u8BBE\u8BA1\u7A3F\u5BBD\u5EA6\u6362\u7B97\uFF09",
|
|
2166
|
+
designWidth: "\u5C0F\u7A0B\u5E8F\u7528 rpx \u57FA\u51C6\uFF08750\uFF09\uFF0C\u8BE5 Web \u4E13\u7528\u57FA\u51C6\u5FFD\u7565\u5E76\u63D0\u793A",
|
|
2167
|
+
searchable: "\u5C0F\u7A0B\u5E8F\u65E0\u5185\u5EFA\u641C\u7D22\u8BED\u4E49\uFF0C\u5FFD\u7565\u5E76\u63D0\u793A\uFF08\u7531\u4E1A\u52A1\u4FA7\u81EA\u7ED8\uFF09"
|
|
2168
|
+
};
|
|
2169
|
+
var TAG_PROP_MP_FALLBACK = {
|
|
2170
|
+
"p-stack": {
|
|
2171
|
+
snap: "\u5C0F\u7A0B\u5E8F view \u4E0D\u6EDA\u52A8\uFF08Skyline \u65E0 CSS overflow \u6EDA\u52A8\uFF0CS14 \u5B9E\u6D4B\uFF09\u2192 \u5438\u9644\u65E0\u8F7D\u4F53\uFF0C\u964D\u7EA7\u4E3A\u666E\u901A\u6392\u5217 + \u53EF\u89C2\u5BDF\u63D0\u793A\uFF1B\u9700\u7FFB\u9875\u8BF7\u7528 p-scroll-view \u7684 paging-enabled",
|
|
2172
|
+
loop: "\u56DE\u73AF\u4F9D\u8D56\u5438\u9644\u5BB9\u5668\uFF0C\u800C\u5C0F\u7A0B\u5E8F view \u4E0D\u6EDA\u52A8\uFF08S14\uFF09\u2192 \u4E00\u5E76\u964D\u7EA7\u4E3A\u666E\u901A\u6392\u5217 + \u53EF\u89C2\u5BDF\u63D0\u793A"
|
|
2173
|
+
}
|
|
2174
|
+
};
|
|
2175
|
+
var RULE_REGISTERED_PROPS = [
|
|
2176
|
+
...Object.keys(PRIVATE_WEB_FALLBACK),
|
|
2177
|
+
...Object.keys(STYLE_WEB_FALLBACK),
|
|
2178
|
+
...Object.keys(WEB_EXTENSION_MP_FALLBACK),
|
|
2179
|
+
...Object.keys(MP_HOST_WEB_FALLBACK),
|
|
2180
|
+
...Object.values(TAG_PROP_MP_FALLBACK).flatMap((m) => Object.keys(m))
|
|
2181
|
+
];
|
|
2182
|
+
var HOST_FALLBACK_TAGS = Object.keys(HOST_TAGS);
|
|
2183
|
+
function degradeProp(tag, prop) {
|
|
2184
|
+
const style = STYLE_WEB_FALLBACK[prop];
|
|
2185
|
+
if (style) return { mp: "supported", web: "fallback", behavior: style };
|
|
2186
|
+
const priv = PRIVATE_WEB_FALLBACK[prop];
|
|
2187
|
+
if (priv) return { mp: "supported", web: "fallback", behavior: priv };
|
|
2188
|
+
const mpHost = MP_HOST_WEB_FALLBACK[prop];
|
|
2189
|
+
if (mpHost) return { mp: "supported", web: "fallback", behavior: mpHost };
|
|
2190
|
+
if (tag && HOST_TAGS[tag]) {
|
|
2191
|
+
return { mp: "supported", web: "fallback", behavior: HOST_TAGS[tag] };
|
|
2192
|
+
}
|
|
2193
|
+
const tagProp = tag ? TAG_PROP_MP_FALLBACK[tag] : void 0;
|
|
2194
|
+
const tagPropBehavior = tagProp ? tagProp[prop] : void 0;
|
|
2195
|
+
if (tagPropBehavior) return { mp: "fallback", web: "supported", behavior: tagPropBehavior };
|
|
2196
|
+
const webExt = WEB_EXTENSION_MP_FALLBACK[prop];
|
|
2197
|
+
if (webExt) return { mp: "fallback", web: "supported", behavior: webExt };
|
|
2198
|
+
return { mp: "supported", web: "supported" };
|
|
2199
|
+
}
|
|
2200
|
+
function degradationOf(prim) {
|
|
2201
|
+
const out = {};
|
|
2202
|
+
for (const p of prim.props ?? []) out[p] = degradeProp(prim.tag, p);
|
|
2203
|
+
return out;
|
|
2204
|
+
}
|
|
2205
|
+
var DEGRADATION_TABLE = (() => {
|
|
2206
|
+
const out = {};
|
|
2207
|
+
for (const prim of PRIMITIVE_CATALOG) {
|
|
2208
|
+
if (!prim.tag) continue;
|
|
2209
|
+
out[prim.tag] = degradationOf(prim);
|
|
2210
|
+
}
|
|
2211
|
+
return out;
|
|
2212
|
+
})();
|
|
2213
|
+
var MP_UNSUPPORTED_PROPS = (() => {
|
|
2214
|
+
const kebab = (s) => s.replace(/([a-z0-9])([A-Z])/g, "$1-$2").toLowerCase();
|
|
2215
|
+
const out = {};
|
|
2216
|
+
for (const [tag, table] of Object.entries(DEGRADATION_TABLE)) {
|
|
2217
|
+
const set = /* @__PURE__ */ new Set();
|
|
2218
|
+
for (const [prop, entry] of Object.entries(table)) {
|
|
2219
|
+
if (entry.mp === "unsupported") set.add(kebab(prop));
|
|
2220
|
+
}
|
|
2221
|
+
if (set.size) out[tag] = set;
|
|
2222
|
+
}
|
|
2223
|
+
return out;
|
|
2224
|
+
})();
|
|
2225
|
+
function auditDegradation(extraSpecs) {
|
|
2226
|
+
const issues = [];
|
|
2227
|
+
const counts = {
|
|
2228
|
+
mp: { supported: 0, fallback: 0, unsupported: 0 },
|
|
2229
|
+
web: { supported: 0, fallback: 0, unsupported: 0 }
|
|
2230
|
+
};
|
|
2231
|
+
let props = 0;
|
|
2232
|
+
let components = 0;
|
|
2233
|
+
let behaviorDeclared = 0;
|
|
2234
|
+
let behaviorNeeded = 0;
|
|
2235
|
+
const specs = [];
|
|
2236
|
+
const sourceByTag = new Map((extraSpecs ?? []).map((s) => [s.tag, s.props]));
|
|
2237
|
+
const emitted = /* @__PURE__ */ new Set();
|
|
2238
|
+
for (const prim of PRIMITIVE_CATALOG) {
|
|
2239
|
+
if (!prim.tag) continue;
|
|
2240
|
+
specs.push({ tag: prim.tag, props: sourceByTag.get(prim.tag) ?? prim.props ?? [] });
|
|
2241
|
+
emitted.add(prim.tag);
|
|
2242
|
+
}
|
|
2243
|
+
for (const s of extraSpecs ?? []) {
|
|
2244
|
+
if (emitted.has(s.tag)) continue;
|
|
2245
|
+
specs.push({ tag: s.tag, props: s.props });
|
|
2246
|
+
emitted.add(s.tag);
|
|
2247
|
+
}
|
|
2248
|
+
for (const { tag, props: propList } of specs) {
|
|
2249
|
+
components++;
|
|
2250
|
+
for (const p of propList) {
|
|
2251
|
+
props++;
|
|
2252
|
+
const entry = degradeProp(tag, p);
|
|
2253
|
+
counts.mp[entry.mp]++;
|
|
2254
|
+
counts.web[entry.web]++;
|
|
2255
|
+
const needsBehavior = entry.mp !== "supported" || entry.web !== "supported";
|
|
2256
|
+
if (needsBehavior) {
|
|
2257
|
+
behaviorNeeded++;
|
|
2258
|
+
if (entry.behavior && entry.behavior.trim().length > 0) behaviorDeclared++;
|
|
2259
|
+
else {
|
|
2260
|
+
issues.push({
|
|
2261
|
+
tag,
|
|
2262
|
+
prop: p,
|
|
2263
|
+
kind: "behavior-gap",
|
|
2264
|
+
detail: `\u58F0\u660E\u4E86 ${entry.mp === "supported" ? "" : `mp:${entry.mp} `}${entry.web === "supported" ? "" : `web:${entry.web}`} \u4F46\u65E0 behavior\uFF08\u964D\u7EA7\u987B\u53EF\u89C2\u5BDF\uFF0C\xA74 \u53CD\u9ED1\u76D2\uFF09`
|
|
2265
|
+
});
|
|
2266
|
+
}
|
|
2267
|
+
}
|
|
2268
|
+
}
|
|
2269
|
+
}
|
|
2270
|
+
for (const [tag, table] of Object.entries(DEGRADATION_TABLE)) {
|
|
2271
|
+
for (const [prop, entry] of Object.entries(table)) {
|
|
2272
|
+
const fresh = degradeProp(tag, prop);
|
|
2273
|
+
if (fresh.mp !== entry.mp || fresh.web !== entry.web) {
|
|
2274
|
+
issues.push({
|
|
2275
|
+
tag,
|
|
2276
|
+
prop,
|
|
2277
|
+
kind: "table-divergence",
|
|
2278
|
+
detail: `DEGRADATION_TABLE=${entry.mp}/${entry.web} \u4E0E\u89C4\u5219\u5224\u5B9A=${fresh.mp}/${fresh.web} \u4E0D\u4E00\u81F4\uFF08\u8868\u987B\u7531\u89C4\u5219\u6784\u5EFA\uFF09`
|
|
2279
|
+
});
|
|
2280
|
+
}
|
|
2281
|
+
}
|
|
2282
|
+
}
|
|
2283
|
+
return { components, props, counts, behaviorDeclared, behaviorNeeded, issues, ok: issues.length === 0 };
|
|
2284
|
+
}
|
|
2285
|
+
function formatDegradationReport(r) {
|
|
2286
|
+
const lines = [
|
|
2287
|
+
`\u964D\u7EA7\u58F0\u660E\u8986\u76D6\uFF1A${r.components} \u7EC4\u4EF6 / ${r.props} \u5C5E\u6027`,
|
|
2288
|
+
` mp \u7AEF\uFF1Asupported ${r.counts.mp.supported} \xB7 fallback ${r.counts.mp.fallback} \xB7 unsupported ${r.counts.mp.unsupported}`,
|
|
2289
|
+
` web \u7AEF\uFF1Asupported ${r.counts.web.supported} \xB7 fallback ${r.counts.web.fallback} \xB7 unsupported ${r.counts.web.unsupported}`,
|
|
2290
|
+
` fallback \u53EF\u89C2\u5BDF\u884C\u4E3A\uFF1A${r.behaviorDeclared}/${r.behaviorNeeded}`
|
|
2291
|
+
];
|
|
2292
|
+
if (r.issues.length) {
|
|
2293
|
+
lines.push(` \u274C ${r.issues.length} \u9879\u95EE\u9898\uFF1A`);
|
|
2294
|
+
for (const i of r.issues.slice(0, 20)) lines.push(` - [${i.tag}] ${i.prop}\uFF1A${i.detail}`);
|
|
2295
|
+
if (r.issues.length > 20) lines.push(` \u2026\u53E6\u6709 ${r.issues.length - 20} \u9879`);
|
|
2296
|
+
}
|
|
2297
|
+
return lines.join("\n");
|
|
2298
|
+
}
|
|
2299
|
+
var PROP_NO_DEGRADATION = "PROP_NO_DEGRADATION";
|
|
2300
|
+
function checkPropDegradation(tag, prop, end, table = DEGRADATION_TABLE) {
|
|
2301
|
+
const entry = table[tag]?.[prop];
|
|
2302
|
+
if (!entry) return null;
|
|
2303
|
+
if (entry[end] !== "unsupported") return null;
|
|
2304
|
+
return {
|
|
2305
|
+
code: PROP_NO_DEGRADATION,
|
|
2306
|
+
tag,
|
|
2307
|
+
prop,
|
|
2308
|
+
end,
|
|
2309
|
+
message: `[${PROP_NO_DEGRADATION}] <${tag}> \u7684\u5C5E\u6027 "${prop}" \u5728 ${end} \u7AEF\u4E3A unsupported\uFF08\u672C\u7AEF\u65E0\u6CD5\u5B9E\u73B0\uFF09\u2014\u2014\u7EE7\u7EED\u4F7F\u7528\u4F1A\u9759\u9ED8\u5931\u8D25\uFF08\u8FDD\u53CD G-31.2\uFF09\u3002\u8BF7\u6539\u7528 @conditional \u663E\u5F0F\u5206\u652F\u6216\u79FB\u9664\u8BE5\u5C5E\u6027\u3002`
|
|
2310
|
+
};
|
|
2311
|
+
}
|
|
2312
|
+
function collectPropDiagnostics(tag, props, end, table = DEGRADATION_TABLE) {
|
|
2313
|
+
const out = [];
|
|
2314
|
+
for (const p of props) {
|
|
2315
|
+
const d = checkPropDegradation(tag, p, end, table);
|
|
2316
|
+
if (d) out.push(d);
|
|
2317
|
+
}
|
|
2318
|
+
return out;
|
|
2319
|
+
}
|
|
1114
2320
|
export {
|
|
1115
2321
|
COMPONENT_IR_SCHEMA,
|
|
1116
2322
|
DEFAULT_DESIGN_WIDTH,
|
|
2323
|
+
DEGRADATION_TABLE,
|
|
2324
|
+
FRAMEWORK_INTERNAL_TAGS,
|
|
2325
|
+
GESTURE_HANDLER_EXPECTED,
|
|
2326
|
+
HOST_FALLBACK_TAGS,
|
|
1117
2327
|
MP_MAPPING_MATRIX,
|
|
2328
|
+
MP_UNSUPPORTED_PROPS,
|
|
1118
2329
|
PRIMITIVE_CATALOG,
|
|
2330
|
+
PROP_NO_DEGRADATION,
|
|
2331
|
+
RULE_REGISTERED_PROPS,
|
|
1119
2332
|
SEMANTIC_BACKEND_MAP,
|
|
1120
2333
|
SEMANTIC_ENUM,
|
|
2334
|
+
SPEC_COMPONENT_OVERRIDE,
|
|
2335
|
+
SPEC_COVERED,
|
|
2336
|
+
SPEC_NA,
|
|
2337
|
+
SPEC_PLANNED,
|
|
2338
|
+
SPEC_PRIVATE,
|
|
2339
|
+
SPEC_RATCHET,
|
|
2340
|
+
TAG_SEMANTIC_ALIASES,
|
|
1121
2341
|
TAG_SEMANTIC_MAP,
|
|
1122
2342
|
auditCatalogConsistency,
|
|
2343
|
+
auditDegradation,
|
|
2344
|
+
auditMatrixReferences,
|
|
1123
2345
|
auditMiniprogramCoverage,
|
|
2346
|
+
auditSpecCoverage,
|
|
2347
|
+
auditSpecOverrideRefs,
|
|
1124
2348
|
checkComponentSnapshot,
|
|
1125
2349
|
checkPrimitiveCatalog,
|
|
2350
|
+
checkPropDegradation,
|
|
1126
2351
|
checkSemanticCoverage,
|
|
2352
|
+
classifySpecApi,
|
|
2353
|
+
classifySpecComponent,
|
|
2354
|
+
collectPropDiagnostics,
|
|
1127
2355
|
componentPrimitives,
|
|
2356
|
+
degradationOf,
|
|
2357
|
+
degradeProp,
|
|
1128
2358
|
extractSemanticTree,
|
|
1129
2359
|
formatCoverageReport,
|
|
2360
|
+
formatDegradationReport,
|
|
1130
2361
|
implementedPrimitives,
|
|
1131
2362
|
mapSemanticToBackend,
|
|
1132
2363
|
primitiveById,
|