uview-pro 0.6.14 → 0.6.16

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.
Files changed (54) hide show
  1. package/changelog.md +32 -11
  2. package/components/u-action-sheet/u-action-sheet.vue +1 -0
  3. package/components/u-alert-tips/u-alert-tips.vue +1 -0
  4. package/components/u-avatar/u-avatar.vue +1 -0
  5. package/components/u-back-top/u-back-top.vue +1 -0
  6. package/components/u-calendar/u-calendar.vue +3 -0
  7. package/components/u-car-keyboard/u-car-keyboard.vue +1 -0
  8. package/components/u-cell-item/u-cell-item.vue +1 -0
  9. package/components/u-checkbox/u-checkbox.vue +1 -0
  10. package/components/u-city-select/u-city-select.vue +5 -0
  11. package/components/u-collapse-item/u-collapse-item.vue +1 -0
  12. package/components/u-column-notice/u-column-notice.vue +1 -0
  13. package/components/u-dropdown/u-dropdown.vue +1 -0
  14. package/components/u-dropdown-item/u-dropdown-item.vue +3 -0
  15. package/components/u-empty/u-empty.vue +1 -0
  16. package/components/u-fab/u-fab.vue +2 -0
  17. package/components/u-field/u-field.vue +1 -0
  18. package/components/u-form-item/u-form-item.vue +1 -0
  19. package/components/u-full-screen/u-full-screen.vue +1 -0
  20. package/components/u-image/u-image.vue +1 -0
  21. package/components/u-input/u-input.vue +1 -0
  22. package/components/u-keyboard/u-keyboard.vue +3 -0
  23. package/components/u-loading-popup/u-loading-popup.vue +1 -0
  24. package/components/u-loadmore/u-loadmore.vue +2 -0
  25. package/components/u-modal/u-modal.vue +2 -0
  26. package/components/u-navbar/u-navbar.vue +1 -0
  27. package/components/u-notice-bar/u-notice-bar.vue +2 -0
  28. package/components/u-number-box/u-number-box.vue +1 -0
  29. package/components/u-number-keyboard/u-number-keyboard.vue +1 -0
  30. package/components/u-pagination/u-pagination.vue +3 -0
  31. package/components/u-picker/u-picker.vue +1 -0
  32. package/components/u-popup/u-popup.vue +2 -0
  33. package/components/u-radio/u-radio.vue +1 -0
  34. package/components/u-rate/u-rate.vue +1 -0
  35. package/components/u-read-more/u-read-more.vue +1 -0
  36. package/components/u-row-notice/u-row-notice.vue +1 -0
  37. package/components/u-search/u-search.vue +297 -296
  38. package/components/u-section/u-section.vue +1 -0
  39. package/components/u-select/u-select.vue +1 -0
  40. package/components/u-step/u-step.vue +30 -2
  41. package/components/u-steps/u-steps.vue +14 -1
  42. package/components/u-switch/u-switch.vue +1 -0
  43. package/components/u-tabbar/u-tabbar.vue +3 -0
  44. package/components/u-tabs/u-tabs.vue +1 -0
  45. package/components/u-tabs-swiper/u-tabs-swiper.vue +1 -0
  46. package/components/u-tag/u-tag.vue +1 -0
  47. package/components/u-text/u-text.vue +2 -0
  48. package/components/u-textarea/u-textarea.vue +1 -0
  49. package/components/u-toast/u-toast.vue +3 -0
  50. package/components/u-upload/u-upload.vue +2 -0
  51. package/package.json +21 -2
  52. package/plugins/root/page.ts +77 -77
  53. package/plugins/root/root.ts +53 -53
  54. package/types/index.d.ts +15 -14
@@ -42,6 +42,14 @@
42
42
  <view class="u-steps__item__line" :class="['u-steps__item__line--' + mode]" v-if="showLine">
43
43
  <u-line :direction="direction" length="100%" :hair-line="false" :color="unActiveColor"></u-line>
44
44
  </view>
45
+ <!-- 横排模式下补左半连接线:节点宽度不一致时避免与上一个节点之间连线断开 -->
46
+ <view
47
+ class="u-steps__item__line"
48
+ :class="['u-steps__item__line--left--' + mode]"
49
+ v-if="direction === 'row' && childIndex > 0"
50
+ >
51
+ <u-line :direction="direction" length="100%" :hair-line="false" :color="unActiveColor"></u-line>
52
+ </view>
45
53
  </view>
46
54
  </template>
47
55
  <script lang="ts">
@@ -60,6 +68,8 @@ export default {
60
68
  import { computed } from 'vue';
61
69
  import { $u, useChildren } from '../..';
62
70
  import { StepProps } from './types';
71
+ import uIcon from '../u-icon/u-icon.vue';
72
+ import uLine from '../u-line/u-line.vue';
63
73
 
64
74
  const props = defineProps(StepProps);
65
75
 
@@ -154,6 +164,8 @@ $u-steps-item-dot-width: 20rpx;
154
164
  flex-direction: column;
155
165
 
156
166
  &--row {
167
+ // 步骤多时禁止收缩到内容宽度以下,超宽交给容器横向滚动,避免文字遮挡
168
+ flex: 1 0 auto;
157
169
  align-items: center;
158
170
  @include vue-flex;
159
171
  flex-direction: column;
@@ -162,17 +174,31 @@ $u-steps-item-dot-width: 20rpx;
162
174
  position: absolute;
163
175
  z-index: 0;
164
176
 
177
+ // 右半线:自本节点圆心向右伸至自身右边缘,与下一节点的左半线无缝衔接
165
178
  &--dot {
166
- width: calc(100% - #{$u-steps-item-dot-width});
179
+ width: calc(50% - #{$u-steps-item-dot-width} / 2);
167
180
  top: calc(#{$u-steps-item-dot-width} / 2);
168
181
  left: calc(#{$u-steps-item-dot-width} / 2 + 50%);
169
182
  }
170
183
 
184
+ // 左半线:自自身左边缘向左半圆心(不含圆心),补偿右半线在宽度不同时够不到下一节点圆心
185
+ &--left--dot {
186
+ width: calc(50% - #{$u-steps-item-dot-width} / 2);
187
+ top: calc(#{$u-steps-item-dot-width} / 2);
188
+ right: calc(#{$u-steps-item-dot-width} / 2 + 50%);
189
+ }
190
+
171
191
  &--number {
172
- width: calc(100% - $u-steps-item-number-width);
192
+ width: calc(50% - #{$u-steps-item-number-width} / 2);
173
193
  top: calc(#{$u-steps-item-number-width} / 2);
174
194
  left: calc(#{$u-steps-item-number-width} / 2 + 50%);
175
195
  }
196
+
197
+ &--left--number {
198
+ width: calc(50% - #{$u-steps-item-number-width} / 2);
199
+ top: calc(#{$u-steps-item-number-width} / 2);
200
+ right: calc(#{$u-steps-item-number-width} / 2 + 50%);
201
+ }
176
202
  }
177
203
  }
178
204
 
@@ -250,6 +276,8 @@ $u-steps-item-dot-width: 20rpx;
250
276
  }
251
277
 
252
278
  &__desc--row {
279
+ // 保持单行,超宽由容器横向滚动承载
280
+ white-space: nowrap;
253
281
  color: $u-type-info;
254
282
  font-size: 24rpx;
255
283
  }
@@ -55,6 +55,7 @@ export default {
55
55
  import { computed, getCurrentInstance } from 'vue';
56
56
  import { StepsProps } from './types';
57
57
  import { $u, useParent } from '../..';
58
+ import uStep from '../u-step/u-step.vue';
58
59
 
59
60
  /**
60
61
  * steps 步骤条
@@ -75,7 +76,19 @@ const props = defineProps(StepsProps);
75
76
 
76
77
  const { children } = useParent('u-steps');
77
78
  // 计算方向样式
78
- const directionStyle = computed(() => ({ flexDirection: props.direction as 'row' | 'column' }));
79
+ const directionStyle = computed(() => {
80
+ const isRow = props.direction === 'row';
81
+ return {
82
+ flexDirection: props.direction as 'row' | 'column',
83
+ ...(isRow
84
+ ? {
85
+ // 内容总宽超出一行时横向滚动,避免右侧节点被截断
86
+ overflowX: 'auto',
87
+ flexWrap: 'nowrap'
88
+ }
89
+ : {})
90
+ };
91
+ });
79
92
 
80
93
  defineExpose({
81
94
  props,
@@ -35,6 +35,7 @@ import { computed, nextTick } from 'vue';
35
35
  import { $u, useChildren } from '../..';
36
36
  import { SwitchProps } from './types';
37
37
  import type { SizeType } from '../../types/global';
38
+ import uLoading from '../u-loading/u-loading.vue';
38
39
 
39
40
  /**
40
41
  * switch 开关选择器
@@ -103,6 +103,9 @@ import { ref, computed, onMounted } from 'vue';
103
103
  import { $u } from '../..';
104
104
  import { TabbarProps } from './types';
105
105
  import type { TabbarItem } from '../../types/global';
106
+ import uBadge from '../u-badge/u-badge.vue';
107
+ import uGap from '../u-gap/u-gap.vue';
108
+ import uIcon from '../u-icon/u-icon.vue';
106
109
 
107
110
  /**
108
111
  * u-tabbar 底部导航栏
@@ -51,6 +51,7 @@ export default {
51
51
  import { ref, computed, watch, onMounted, nextTick, getCurrentInstance } from 'vue';
52
52
  import { $u } from '../..';
53
53
  import { TabsProps } from './types';
54
+ import uBadge from '../u-badge/u-badge.vue';
54
55
 
55
56
  /**
56
57
  * tabs 标签
@@ -44,6 +44,7 @@ import { ref, computed, watch, nextTick, onMounted, getCurrentInstance } from 'v
44
44
  import colorGradient from '../../libs/function/colorGradient';
45
45
  import { TabsSwiperProps } from './types';
46
46
  import { $u } from '../..';
47
+ import uBadge from '../u-badge/u-badge.vue';
47
48
 
48
49
  /**
49
50
  * tabsSwiper 全屏选项卡
@@ -46,6 +46,7 @@ export default {
46
46
  import { computed } from 'vue';
47
47
  import { TagProps } from './types';
48
48
  import { $u } from '../../';
49
+ import uIcon from '../u-icon/u-icon.vue';
49
50
 
50
51
  /**
51
52
  * tag 提示
@@ -85,6 +85,8 @@ export default {
85
85
  import { computed } from 'vue';
86
86
  import { TextProps } from './types';
87
87
  import { $u } from '../../';
88
+ import uIcon from '../u-icon/u-icon.vue';
89
+ import uLink from '../u-link/u-link.vue';
88
90
 
89
91
  /**
90
92
  * Text 文本
@@ -91,6 +91,7 @@ import { ref, computed, watch, nextTick } from 'vue';
91
91
  import { TextareaProps } from './types';
92
92
  import { $u, useChildren } from '../../';
93
93
  import type { SizeType } from '../../types/global';
94
+ import uIcon from '../u-icon/u-icon.vue';
94
95
 
95
96
  /**
96
97
  * Textarea 文本域
@@ -60,6 +60,9 @@ import {
60
60
  getEventWithCurrentPage,
61
61
  type ToastPayload
62
62
  } from './service';
63
+ import uIcon from '../u-icon/u-icon.vue';
64
+ import uLoading from '../u-loading/u-loading.vue';
65
+ import uMask from '../u-mask/u-mask.vue';
63
66
 
64
67
  /**
65
68
  * toast 消息提示
@@ -245,6 +245,8 @@ import { ref, watch, computed } from 'vue';
245
245
  import { $u, useLocale } from '../..';
246
246
  import { UploadProps } from './types';
247
247
  import type { UploadFileItem } from '../../types/global';
248
+ import uIcon from '../u-icon/u-icon.vue';
249
+ import uLineProgress from '../u-line-progress/u-line-progress.vue';
248
250
 
249
251
  /**
250
252
  * upload 文件上传
package/package.json CHANGED
@@ -2,12 +2,31 @@
2
2
  "id": "uview-pro",
3
3
  "name": "uview-pro",
4
4
  "displayName": "【支持鸿蒙】uView Pro|基于Vue3+TS的高质量UI组件库,支持多主题、暗黑模式、多语言",
5
- "version": "0.6.14",
5
+ "version": "0.6.16",
6
6
  "description": "uView Pro是基于Vue3+TS的多平台UI框架,提供80+高质量组件、便捷工具和常用模板,支持多主题、暗黑模式、多语言,支持H5/APP/鸿蒙/小程序多端开发。已在鸿蒙应用商店上架,欢迎体验!",
7
7
  "main": "index.ts",
8
8
  "module": "index.ts",
9
9
  "browser": "index.ts",
10
- "types": "index.ts",
10
+ "types": "index.d.ts",
11
+ "exports": {
12
+ ".": {
13
+ "types": "./index.d.ts",
14
+ "import": "./index.ts",
15
+ "require": "./index.ts",
16
+ "default": "./index.ts"
17
+ },
18
+ "./plugins": {
19
+ "types": "./plugins/index.ts",
20
+ "import": "./plugins/index.mjs",
21
+ "require": "./plugins/index.cjs",
22
+ "default": "./plugins/index.mjs"
23
+ },
24
+ "./types": "./types/index.d.ts",
25
+ "./types/*": "./types/*.d.ts",
26
+ "./components/*": "./components/*",
27
+ "./libs/*": "./libs/*",
28
+ "./*": "./*"
29
+ },
11
30
  "keywords": [
12
31
  "uview-pro",
13
32
  "vue3",
@@ -1,77 +1,77 @@
1
- import { parseSFC, findNode } from './utils';
2
-
3
- /**
4
- * 页面模板转换:将页面内容包裹在 <global-root-view> 中
5
- *
6
- * <global-root-view> 是 App.root.vue 注册的全局组件,
7
- * 其模板中包含 <slot />,页面内容通过插槽传入。
8
- *
9
- * 处理逻辑:
10
- * 1. 解析 SFC,定位 <template> 标签的起止位置
11
- * 2. 提取模板内容,查找 PageMeta 节点(如有则提取到包裹层外部)
12
- * 3. 将剩余内容包裹在 <global-root-view>...</global-root-view> 中
13
- *
14
- * 降级机制:当 vue/compiler-sfc 不可用(如 HBuilderX 项目)时,
15
- * 使用正则匹配 <page-meta> 标签替代 AST 解析。
16
- */
17
- export async function transformPage(code: string) {
18
- const sfc = await parseSFC(code);
19
-
20
- // 用正则定位 <template> 开头标签
21
- const openMatch = code.match(/<template\b[^>]*>/);
22
- if (!openMatch) return null;
23
-
24
- // 使用 lastIndexOf 定位最后一个 </template>,即根 <template> 的闭合标签
25
- // 避免匹配到模板内具名插槽 <template #slot> 的闭合标签
26
- const closeTagStart = code.lastIndexOf('</template>');
27
- if (closeTagStart === -1) return null;
28
-
29
- const openTagEnd = openMatch.index! + openMatch[0].length;
30
- const content = code.slice(openTagEnd, closeTagStart);
31
-
32
- let pageMetaSource = '';
33
- let newContent = content;
34
-
35
- if (sfc?.template) {
36
- // AST 模式:通过 vue/compiler-sfc 解析,精确定位 PageMeta 节点
37
- const pageMetaNode = findNode(sfc, 'PageMeta');
38
- if (pageMetaNode) {
39
- pageMetaSource = pageMetaNode.loc.source;
40
- const metaStart = pageMetaNode.loc.start.offset;
41
- const metaEnd = pageMetaNode.loc.end.offset;
42
-
43
- // pageMetaNode.loc 的 offset 是相对于整个文件的,转换为相对于 content 的位置
44
- const metaStartInContent = metaStart - openTagEnd;
45
- const metaEndInContent = metaEnd - openTagEnd;
46
-
47
- newContent = content.slice(0, metaStartInContent) + content.slice(metaEndInContent);
48
- }
49
- } else {
50
- // 降级模式:vue/compiler-sfc 不可用,用正则匹配 <page-meta> 标签
51
- const pageMetaMatch = content.match(/<page-meta\b[^>]*>[\s\S]*?<\/page-meta>/);
52
- if (pageMetaMatch) {
53
- pageMetaSource = pageMetaMatch[0];
54
- newContent = content.replace(pageMetaMatch[0], '');
55
- } else {
56
- // 也匹配自闭合的 <page-meta ... />
57
- const selfClosingMatch = content.match(/<page-meta\b[^>]*\/>/);
58
- if (selfClosingMatch) {
59
- pageMetaSource = selfClosingMatch[0];
60
- newContent = content.replace(selfClosingMatch[0], '');
61
- }
62
- }
63
- }
64
-
65
- // page-meta 放在包裹层外部,内容包裹在 <global-root-view> 中
66
- const wrappedContent = `\n${pageMetaSource}\n<global-root-view>${newContent}</global-root-view>\n`;
67
-
68
- return {
69
- code: code.slice(0, openTagEnd) + wrappedContent + code.slice(closeTagStart),
70
- map: {
71
- version: 3 as const,
72
- sources: [] as string[],
73
- names: [] as string[],
74
- mappings: ''
75
- }
76
- };
77
- }
1
+ import { parseSFC, findNode } from './utils';
2
+
3
+ /**
4
+ * 页面模板转换:将页面内容包裹在 <global-root-view> 中
5
+ *
6
+ * <global-root-view> 是 App.root.vue 注册的全局组件,
7
+ * 其模板中包含 <slot />,页面内容通过插槽传入。
8
+ *
9
+ * 处理逻辑:
10
+ * 1. 解析 SFC,定位 <template> 标签的起止位置
11
+ * 2. 提取模板内容,查找 PageMeta 节点(如有则提取到包裹层外部)
12
+ * 3. 将剩余内容包裹在 <global-root-view>...</global-root-view> 中
13
+ *
14
+ * 降级机制:当 vue/compiler-sfc 不可用(如 HBuilderX 项目)时,
15
+ * 使用正则匹配 <page-meta> 标签替代 AST 解析。
16
+ */
17
+ export async function transformPage(code: string) {
18
+ const sfc = await parseSFC(code);
19
+
20
+ // 用正则定位 <template> 开头标签
21
+ const openMatch = code.match(/<template\b[^>]*>/);
22
+ if (!openMatch) return null;
23
+
24
+ // 使用 lastIndexOf 定位最后一个 </template>,即根 <template> 的闭合标签
25
+ // 避免匹配到模板内具名插槽 <template #slot> 的闭合标签
26
+ const closeTagStart = code.lastIndexOf('</template>');
27
+ if (closeTagStart === -1) return null;
28
+
29
+ const openTagEnd = openMatch.index! + openMatch[0].length;
30
+ const content = code.slice(openTagEnd, closeTagStart);
31
+
32
+ let pageMetaSource = '';
33
+ let newContent = content;
34
+
35
+ if (sfc?.template) {
36
+ // AST 模式:通过 vue/compiler-sfc 解析,精确定位 PageMeta 节点
37
+ const pageMetaNode = findNode(sfc, 'PageMeta');
38
+ if (pageMetaNode) {
39
+ pageMetaSource = pageMetaNode.loc.source;
40
+ const metaStart = pageMetaNode.loc.start.offset;
41
+ const metaEnd = pageMetaNode.loc.end.offset;
42
+
43
+ // pageMetaNode.loc 的 offset 是相对于整个文件的,转换为相对于 content 的位置
44
+ const metaStartInContent = metaStart - openTagEnd;
45
+ const metaEndInContent = metaEnd - openTagEnd;
46
+
47
+ newContent = content.slice(0, metaStartInContent) + content.slice(metaEndInContent);
48
+ }
49
+ } else {
50
+ // 降级模式:vue/compiler-sfc 不可用,用正则匹配 <page-meta> 标签
51
+ const pageMetaMatch = content.match(/<page-meta\b[^>]*>[\s\S]*?<\/page-meta>/);
52
+ if (pageMetaMatch) {
53
+ pageMetaSource = pageMetaMatch[0];
54
+ newContent = content.replace(pageMetaMatch[0], '');
55
+ } else {
56
+ // 也匹配自闭合的 <page-meta ... />
57
+ const selfClosingMatch = content.match(/<page-meta\b[^>]*\/>/);
58
+ if (selfClosingMatch) {
59
+ pageMetaSource = selfClosingMatch[0];
60
+ newContent = content.replace(selfClosingMatch[0], '');
61
+ }
62
+ }
63
+ }
64
+
65
+ // page-meta 放在包裹层外部,内容包裹在 <global-root-view> 中
66
+ const wrappedContent = `\n${pageMetaSource}\n<global-root-view>${newContent}</global-root-view>\n`;
67
+
68
+ return {
69
+ code: code.slice(0, openTagEnd) + wrappedContent + code.slice(closeTagStart),
70
+ map: {
71
+ version: 3 as const,
72
+ sources: [] as string[],
73
+ names: [] as string[],
74
+ mappings: ''
75
+ }
76
+ };
77
+ }
@@ -1,53 +1,53 @@
1
- /**
2
- * 创建一个最小的 sourcemap,用于满足 Vite/Rollup 的 sourcemap 要求。
3
- *
4
- * 这是一个空映射的 sourcemap(mappings 为空字符串),不提供精确的源码映射,
5
- * 但可以避免 "Sourcemap is likely to be incorrect" 警告。
6
- * 调试器会回退到显示转换后的代码,不影响功能。
7
- *
8
- * 纯 JS 实现,无需第三方依赖。
9
- */
10
- function createEmptySourcemap() {
11
- return {
12
- version: 3 as const,
13
- sources: [] as string[],
14
- names: [] as string[],
15
- mappings: ''
16
- };
17
- }
18
-
19
- /**
20
- * 向 main.ts 注入 App.root.vue 的导入和全局注册
21
- *
22
- * 流程:
23
- * 1. 在文件顶部插入 `import GlobalRootView from "./App.root.vue"`
24
- * 2. 在 createSSRApp 之后插入 `app.component("global-root-view", GlobalRootView)`
25
- *
26
- * 注:GlobalRootView 仅为 main.ts 中的局部变量名,
27
- * 实际组件就是 App.root.vue,页面通过 <global-root-view> 标签使用。
28
- */
29
- export function registerRootApp(code: string, fileName: string = 'App.root') {
30
- const importCode = `import GlobalRootView from "./${fileName}.vue";`;
31
- const vueUseComponentCode = `app.component("global-root-view", GlobalRootView);`;
32
-
33
- let newCode = importCode + '\n' + code;
34
-
35
- // 在 createSSRApp 赋值语句之后插入组件注册代码
36
- const ssrAppMatch = newCode.match(/(const\s+app\s*=\s*createSSRApp\([^)]+\);)/);
37
- if (ssrAppMatch) {
38
- newCode = newCode.replace(/(const\s+app\s*=\s*createSSRApp\([^)]+\);)/, `$1\n ${vueUseComponentCode}`);
39
- } else {
40
- // 兜底:在 return { 之前插入
41
- newCode = newCode.replace(/(createApp[\s\S]*?)(return\s*\{)/, `$1${vueUseComponentCode}\n $2`);
42
- }
43
-
44
- return { code: newCode, map: createEmptySourcemap() };
45
- }
46
-
47
- /**
48
- * App.root.vue 模板中已使用 <slot /> 作为子内容插槽,
49
- * 无需替换,直接透传。
50
- */
51
- export function rebuildRootApp(code: string) {
52
- return { code, map: createEmptySourcemap() };
53
- }
1
+ /**
2
+ * 创建一个最小的 sourcemap,用于满足 Vite/Rollup 的 sourcemap 要求。
3
+ *
4
+ * 这是一个空映射的 sourcemap(mappings 为空字符串),不提供精确的源码映射,
5
+ * 但可以避免 "Sourcemap is likely to be incorrect" 警告。
6
+ * 调试器会回退到显示转换后的代码,不影响功能。
7
+ *
8
+ * 纯 JS 实现,无需第三方依赖。
9
+ */
10
+ function createEmptySourcemap() {
11
+ return {
12
+ version: 3 as const,
13
+ sources: [] as string[],
14
+ names: [] as string[],
15
+ mappings: ''
16
+ };
17
+ }
18
+
19
+ /**
20
+ * 向 main.ts 注入 App.root.vue 的导入和全局注册
21
+ *
22
+ * 流程:
23
+ * 1. 在文件顶部插入 `import GlobalRootView from "./App.root.vue"`
24
+ * 2. 在 createSSRApp 之后插入 `app.component("global-root-view", GlobalRootView)`
25
+ *
26
+ * 注:GlobalRootView 仅为 main.ts 中的局部变量名,
27
+ * 实际组件就是 App.root.vue,页面通过 <global-root-view> 标签使用。
28
+ */
29
+ export function registerRootApp(code: string, fileName: string = 'App.root') {
30
+ const importCode = `import GlobalRootView from "./${fileName}.vue";`;
31
+ const vueUseComponentCode = `app.component("global-root-view", GlobalRootView);`;
32
+
33
+ let newCode = importCode + '\n' + code;
34
+
35
+ // 在 createSSRApp 赋值语句之后插入组件注册代码
36
+ const ssrAppMatch = newCode.match(/(const\s+app\s*=\s*createSSRApp\([^)]+\);)/);
37
+ if (ssrAppMatch) {
38
+ newCode = newCode.replace(/(const\s+app\s*=\s*createSSRApp\([^)]+\);)/, `$1\n ${vueUseComponentCode}`);
39
+ } else {
40
+ // 兜底:在 return { 之前插入
41
+ newCode = newCode.replace(/(createApp[\s\S]*?)(return\s*\{)/, `$1${vueUseComponentCode}\n $2`);
42
+ }
43
+
44
+ return { code: newCode, map: createEmptySourcemap() };
45
+ }
46
+
47
+ /**
48
+ * App.root.vue 模板中已使用 <slot /> 作为子内容插槽,
49
+ * 无需替换,直接透传。
50
+ */
51
+ export function rebuildRootApp(code: string) {
52
+ return { code, map: createEmptySourcemap() };
53
+ }
package/types/index.d.ts CHANGED
@@ -1,14 +1,15 @@
1
- /// <reference path="./components.d.ts" />
2
- /// <reference path="./uni-app.d.ts" />
3
-
4
- export * from './global';
5
-
6
- declare global {
7
- interface Uni {
8
- $u: typeof import('../libs').$u;
9
- }
10
- }
11
-
12
- declare module 'uview-pro' {
13
- export function install(): void;
14
- }
1
+ /// <reference path="./components.d.ts" />
2
+ /// <reference path="./uni-app.d.ts" />
3
+
4
+ export * from './global';
5
+ export * from '../libs';
6
+
7
+ declare global {
8
+ interface Uni {
9
+ $u: typeof import('../libs').$u;
10
+ }
11
+ }
12
+
13
+ declare module 'uview-pro' {
14
+ export function install(app: any, options?: import('./global').UViewProOptions): void;
15
+ }