uview-pro 0.2.1 → 0.2.3

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 (246) hide show
  1. package/changelog.md +522 -481
  2. package/components/common/props.ts +22 -22
  3. package/components/u-action-sheet/types.ts +35 -35
  4. package/components/u-action-sheet/u-action-sheet.vue +160 -160
  5. package/components/u-alert-tips/types.ts +39 -39
  6. package/components/u-alert-tips/u-alert-tips.vue +212 -212
  7. package/components/u-avatar/types.ts +34 -34
  8. package/components/u-avatar/u-avatar.vue +193 -193
  9. package/components/u-avatar-cropper/types.ts +23 -23
  10. package/components/u-avatar-cropper/u-avatar-cropper.vue +286 -286
  11. package/components/u-avatar-cropper/weCropper.d.ts +62 -62
  12. package/components/u-avatar-cropper/weCropper.js +1253 -1253
  13. package/components/u-avatar-cropper/weCropper.ts +1255 -1255
  14. package/components/u-back-top/types.ts +39 -39
  15. package/components/u-back-top/u-back-top.vue +125 -125
  16. package/components/u-badge/types.ts +36 -36
  17. package/components/u-badge/u-badge.vue +165 -165
  18. package/components/u-button/types.ts +66 -66
  19. package/components/u-button/u-button.vue +556 -556
  20. package/components/u-calendar/types.ts +73 -73
  21. package/components/u-calendar/u-calendar.vue +638 -638
  22. package/components/u-car-keyboard/types.ts +12 -12
  23. package/components/u-car-keyboard/u-car-keyboard.vue +234 -234
  24. package/components/u-card/types.ts +59 -59
  25. package/components/u-card/u-card.vue +194 -194
  26. package/components/u-cell-group/types.ts +17 -17
  27. package/components/u-cell-group/u-cell-group.vue +50 -50
  28. package/components/u-cell-item/types.ts +54 -54
  29. package/components/u-cell-item/u-cell-item.vue +202 -202
  30. package/components/u-checkbox/types.ts +31 -31
  31. package/components/u-checkbox/u-checkbox.vue +286 -267
  32. package/components/u-checkbox-group/types.ts +32 -32
  33. package/components/u-checkbox-group/u-checkbox-group.vue +130 -79
  34. package/components/u-circle-progress/types.ts +52 -52
  35. package/components/u-circle-progress/u-circle-progress.vue +187 -187
  36. package/components/u-city-select/types.ts +20 -20
  37. package/components/u-city-select/u-city-select.vue +236 -236
  38. package/components/u-col/types.ts +30 -30
  39. package/components/u-col/u-col.vue +123 -123
  40. package/components/u-collapse/types.ts +33 -33
  41. package/components/u-collapse/u-collapse.vue +195 -69
  42. package/components/u-collapse-item/types.ts +27 -27
  43. package/components/u-collapse-item/u-collapse-item.vue +311 -201
  44. package/components/u-column-notice/types.ts +48 -48
  45. package/components/u-column-notice/u-column-notice.vue +176 -176
  46. package/components/u-count-down/types.ts +42 -42
  47. package/components/u-count-down/u-count-down.vue +258 -258
  48. package/components/u-count-to/types.ts +32 -32
  49. package/components/u-count-to/u-count-to.vue +241 -241
  50. package/components/u-divider/types.ts +31 -31
  51. package/components/u-divider/u-divider.vue +121 -121
  52. package/components/u-dropdown/types.ts +32 -32
  53. package/components/u-dropdown/u-dropdown.vue +289 -289
  54. package/components/u-dropdown-item/types.ts +27 -27
  55. package/components/u-dropdown-item/u-dropdown-item.vue +123 -123
  56. package/components/u-empty/types.ts +36 -36
  57. package/components/u-empty/u-empty.vue +88 -88
  58. package/components/u-field/types.ts +69 -69
  59. package/components/u-field/u-field.vue +354 -354
  60. package/components/u-form/u-form.vue +132 -132
  61. package/components/u-form-item/u-form-item.vue +417 -417
  62. package/components/u-full-screen/types.ts +14 -14
  63. package/components/u-full-screen/u-full-screen.vue +82 -82
  64. package/components/u-gap/types.ts +18 -18
  65. package/components/u-gap/u-gap.vue +40 -40
  66. package/components/u-grid/types.ts +19 -19
  67. package/components/u-grid/u-grid.vue +93 -93
  68. package/components/u-grid-item/types.ts +16 -16
  69. package/components/u-grid-item/u-grid-item.vue +130 -130
  70. package/components/u-icon/types.ts +62 -62
  71. package/components/u-icon/u-icon.vue +281 -281
  72. package/components/u-image/types.ts +51 -51
  73. package/components/u-image/u-image.vue +222 -222
  74. package/components/u-index-anchor/types.ts +16 -16
  75. package/components/u-index-anchor/u-index-anchor.vue +86 -86
  76. package/components/u-index-list/types.ts +43 -43
  77. package/components/u-index-list/u-index-list.vue +355 -355
  78. package/components/u-input/types.ts +140 -140
  79. package/components/u-input/u-input.vue +264 -264
  80. package/components/u-keyboard/types.ts +40 -40
  81. package/components/u-keyboard/u-keyboard.vue +158 -158
  82. package/components/u-lazy-load/types.ts +37 -37
  83. package/components/u-lazy-load/u-lazy-load.vue +233 -233
  84. package/components/u-line/types.ts +44 -44
  85. package/components/u-line/u-line.vue +59 -59
  86. package/components/u-line-progress/types.ts +58 -58
  87. package/components/u-line-progress/u-line-progress.vue +109 -109
  88. package/components/u-link/types.ts +43 -43
  89. package/components/u-link/u-link.vue +75 -75
  90. package/components/u-loading/types.ts +35 -35
  91. package/components/u-loading/u-loading.vue +90 -90
  92. package/components/u-loading-popup/types.ts +26 -26
  93. package/components/u-loading-popup/u-loading-popup.vue +239 -239
  94. package/components/u-loadmore/types.ts +79 -79
  95. package/components/u-loadmore/u-loadmore.vue +140 -140
  96. package/components/u-mask/types.ts +43 -43
  97. package/components/u-mask/u-mask.vue +106 -106
  98. package/components/u-message-input/types.ts +74 -74
  99. package/components/u-message-input/u-message-input.vue +255 -255
  100. package/components/u-modal/types.ts +118 -118
  101. package/components/u-modal/u-modal.vue +204 -204
  102. package/components/u-navbar/types.ts +103 -103
  103. package/components/u-navbar/u-navbar.vue +226 -226
  104. package/components/u-no-network/image.ts +2 -2
  105. package/components/u-no-network/types.ts +28 -28
  106. package/components/u-no-network/u-no-network.vue +290 -290
  107. package/components/u-notice-bar/types.ts +111 -111
  108. package/components/u-notice-bar/u-notice-bar.vue +174 -174
  109. package/components/u-number-box/types.ts +42 -42
  110. package/components/u-number-box/u-number-box.vue +312 -312
  111. package/components/u-number-keyboard/types.ts +26 -26
  112. package/components/u-number-keyboard/u-number-keyboard.vue +166 -166
  113. package/components/u-picker/types.ts +123 -123
  114. package/components/u-picker/u-picker.vue +637 -637
  115. package/components/u-popup/types.ts +59 -59
  116. package/components/u-popup/u-popup.vue +359 -359
  117. package/components/u-radio/types.ts +25 -25
  118. package/components/u-radio/u-radio.vue +258 -258
  119. package/components/u-radio-group/types.ts +29 -29
  120. package/components/u-radio-group/u-radio-group.vue +98 -98
  121. package/components/u-rate/types.ts +40 -40
  122. package/components/u-rate/u-rate.vue +234 -234
  123. package/components/u-read-more/types.ts +35 -35
  124. package/components/u-read-more/u-read-more.vue +150 -150
  125. package/components/u-root-portal/u-root-portal.vue +54 -0
  126. package/components/u-row/types.ts +20 -20
  127. package/components/u-row/u-row.vue +87 -87
  128. package/components/u-row-notice/types.ts +39 -39
  129. package/components/u-row-notice/u-row-notice.vue +213 -213
  130. package/components/u-safe-bottom/u-safe-bottom.vue +46 -46
  131. package/components/u-search/types.ts +53 -53
  132. package/components/u-search/u-search.vue +256 -256
  133. package/components/u-section/types.ts +32 -32
  134. package/components/u-section/u-section.vue +125 -125
  135. package/components/u-select/types.ts +43 -43
  136. package/components/u-select/u-select.vue +361 -361
  137. package/components/u-skeleton/types.ts +20 -20
  138. package/components/u-skeleton/u-skeleton.vue +205 -205
  139. package/components/u-slider/types.ts +32 -32
  140. package/components/u-slider/u-slider.vue +238 -238
  141. package/components/u-status-bar/u-status-bar.vue +65 -65
  142. package/components/u-steps/types.ts +28 -28
  143. package/components/u-steps/u-steps.vue +160 -160
  144. package/components/u-sticky/types.ts +22 -22
  145. package/components/u-sticky/u-sticky.vue +159 -159
  146. package/components/u-subsection/types.ts +36 -36
  147. package/components/u-subsection/u-subsection.vue +328 -328
  148. package/components/u-swipe-action/types.ts +50 -50
  149. package/components/u-swipe-action/u-swipe-action.vue +253 -253
  150. package/components/u-swiper/types.ts +47 -47
  151. package/components/u-swiper/u-swiper.vue +266 -266
  152. package/components/u-switch/types.ts +28 -28
  153. package/components/u-switch/u-switch.vue +136 -136
  154. package/components/u-tabbar/types.ts +36 -36
  155. package/components/u-tabbar/u-tabbar.vue +280 -280
  156. package/components/u-table/types.ts +25 -25
  157. package/components/u-table/u-table.vue +55 -55
  158. package/components/u-tabs/types.ts +51 -51
  159. package/components/u-tabs/u-tabs.vue +284 -284
  160. package/components/u-tabs-swiper/types.ts +53 -53
  161. package/components/u-tabs-swiper/u-tabs-swiper.vue +379 -379
  162. package/components/u-tag/types.ts +37 -37
  163. package/components/u-tag/u-tag.vue +244 -244
  164. package/components/u-td/types.ts +12 -12
  165. package/components/u-td/u-td.vue +87 -87
  166. package/components/u-text/types.ts +69 -69
  167. package/components/u-text/u-text.vue +326 -326
  168. package/components/u-th/types.ts +12 -12
  169. package/components/u-th/u-th.vue +81 -81
  170. package/components/u-time-line/u-time-line.vue +39 -39
  171. package/components/u-time-line-item/types.ts +14 -14
  172. package/components/u-time-line-item/u-time-line-item.vue +78 -78
  173. package/components/u-toast/types.ts +36 -36
  174. package/components/u-toast/u-toast.vue +233 -233
  175. package/components/u-top-tips/types.ts +14 -14
  176. package/components/u-top-tips/u-top-tips.vue +113 -113
  177. package/components/u-tr/types.ts +8 -8
  178. package/components/u-tr/u-tr.vue +24 -24
  179. package/components/u-upload/types.ts +74 -74
  180. package/components/u-upload/u-upload.vue +545 -545
  181. package/components/u-verification-code/types.ts +22 -22
  182. package/components/u-verification-code/u-verification-code.vue +164 -164
  183. package/components/u-waterfall/types.ts +16 -16
  184. package/components/u-waterfall/u-waterfall.vue +175 -175
  185. package/iconfont.css +912 -912
  186. package/index.scss +25 -25
  187. package/index.ts +38 -29
  188. package/libs/config/config.ts +26 -26
  189. package/libs/config/zIndex.ts +37 -37
  190. package/libs/css/color.scss +155 -155
  191. package/libs/css/common.scss +178 -178
  192. package/libs/css/style.components.scss +16 -16
  193. package/libs/css/style.h5.scss +8 -8
  194. package/libs/css/style.mp.scss +72 -72
  195. package/libs/css/style.nvue.scss +15 -15
  196. package/libs/css/style.vue.scss +188 -188
  197. package/libs/function/$parent.ts +21 -21
  198. package/libs/function/addUnit.ts +13 -13
  199. package/libs/function/color.ts +37 -37
  200. package/libs/function/colorGradient.ts +125 -125
  201. package/libs/function/debounce.ts +28 -28
  202. package/libs/function/deepClone.ts +39 -39
  203. package/libs/function/deepMerge.ts +34 -34
  204. package/libs/function/getParent.ts +59 -59
  205. package/libs/function/getRect.ts +26 -26
  206. package/libs/function/guid.ts +42 -42
  207. package/libs/function/md5.ts +391 -391
  208. package/libs/function/parent.ts +21 -21
  209. package/libs/function/queryParams.ts +60 -60
  210. package/libs/function/random.ts +16 -16
  211. package/libs/function/randomArray.ts +11 -11
  212. package/libs/function/route.ts +118 -118
  213. package/libs/function/styleUtils.ts +83 -83
  214. package/libs/function/sys.ts +15 -15
  215. package/libs/function/test.ts +285 -285
  216. package/libs/function/throttle.ts +31 -31
  217. package/libs/function/timeFormat.ts +54 -54
  218. package/libs/function/timeFrom.ts +48 -48
  219. package/libs/function/toast.ts +14 -14
  220. package/libs/function/trim.ts +21 -21
  221. package/libs/function/type2icon.ts +36 -36
  222. package/libs/hooks/index.ts +3 -3
  223. package/libs/hooks/useComponent.ts +343 -0
  224. package/libs/hooks/useEmitter.ts +77 -77
  225. package/libs/hooks/useParent.ts +33 -31
  226. package/libs/hooks/useRect.ts +33 -33
  227. package/libs/index.ts +320 -291
  228. package/libs/request/auto-http.ts +76 -76
  229. package/libs/request/index.ts +223 -223
  230. package/libs/store/index.ts +88 -88
  231. package/libs/util/async-validator.d.ts +62 -62
  232. package/libs/util/async-validator.js +1 -1
  233. package/libs/util/calendar.d.ts +57 -57
  234. package/libs/util/emitter.ts +102 -102
  235. package/libs/util/eventBus.ts +86 -0
  236. package/libs/util/logger.ts +364 -0
  237. package/libs/util/mitt.ts +115 -115
  238. package/libs/util/parent.ts +20 -20
  239. package/package.json +1 -1
  240. package/readme.md +241 -237
  241. package/theme.scss +38 -38
  242. package/types/components.d.ts +97 -96
  243. package/types/global.d.ts +331 -295
  244. package/types/ignore-errors.d.ts +30 -30
  245. package/types/index.d.ts +19 -19
  246. package/types/uni-app.d.ts +63 -63
@@ -1,102 +1,102 @@
1
- import { getCurrentInstance, type ComponentInternalInstance } from 'vue';
2
-
3
- /**
4
- * 适用于 uni-app Vue3 的事件派发/广播工具
5
- * 用法:import { dispatch, broadcast } from './emitter'
6
- */
7
-
8
- /**
9
- * 向上查找父组件并派发事件
10
- * @param instance 当前组件实例(setup中可用getCurrentInstance())
11
- * @param componentName 目标组件名
12
- * @param eventName 事件名
13
- * @param params 参数
14
- */
15
-
16
- // 将事件名转换为驼峰格式
17
- // 例如:on-form-change -> onFormChange
18
- function formatToCamelCase(str: string): string {
19
- return str.replace(/-([a-z])/g, function (g) {
20
- return g[1].toUpperCase();
21
- });
22
- }
23
-
24
- /**
25
- * 向上查找父组件
26
- * @param instance 当前组件实例(setup中可用getCurrentInstance())
27
- * @param componentName 目标组件名
28
- * @returns 父组件实例
29
- */
30
- function parent(instance: ComponentInternalInstance | null | undefined = undefined, componentName: string = '') {
31
- if (!instance) {
32
- instance = getCurrentInstance();
33
- }
34
- let parent = instance && (instance.parent as ComponentInternalInstance | null | undefined);
35
-
36
- if (!componentName) return parent;
37
- while (parent) {
38
- const name = (parent.type as any)?.name as string | undefined;
39
- if (name === componentName) {
40
- return parent;
41
- }
42
- parent = parent.parent;
43
- }
44
- return null;
45
- }
46
-
47
- /** * 向上查找父组件并派发事件
48
- * @param instance 当前组件实例(setup中可用getCurrentInstance())
49
- * @param componentName 目标组件名
50
- * @param eventName 事件名
51
- * @param params 参数
52
- */
53
- function dispatch(instance: ComponentInternalInstance | null | undefined, componentName: string, eventName: string, ...params: any[]) {
54
- let parent = instance && (instance.parent as ComponentInternalInstance | null | undefined);
55
- while (parent) {
56
- const name = (parent.type as any)?.name as string | undefined;
57
- if (name === componentName) {
58
- // 找到目标组件,派发事件
59
- // Vue3未解决,目标组件事件监听失效,待优化,暂时使用下面的方式解决,如果你有好的方式也可以告诉我或者提PR
60
- parent.emit && parent.emit(eventName, ...params);
61
- // 如果有对应的方法,执行方法
62
- // 这里可以考虑将 eventName 转换为驼峰格式
63
- // 例如:on-form-change -> onFormChange
64
- parent.exposed?.[formatToCamelCase(eventName)] && parent.exposed[formatToCamelCase(eventName)](...params);
65
- break;
66
- }
67
- parent = parent.parent;
68
- }
69
- }
70
-
71
- /**
72
- * 向下递归查找子组件并广播事件
73
- * @param instance 当前组件实例(setup中可用getCurrentInstance())
74
- * @param componentName 目标组件名
75
- * @param eventName 事件名
76
- * @param params 参数
77
- */
78
- function broadcast(instance: ComponentInternalInstance | null | undefined, componentName: string, eventName: string, ...params: any[]) {
79
- if (!instance) return;
80
- const subTree = (instance.subTree as any)?.children || [];
81
- const children = Array.isArray(subTree) ? subTree : [subTree];
82
- children.forEach((vnode: any) => {
83
- const child = vnode.component as ComponentInternalInstance | undefined;
84
-
85
- if (child) {
86
- const name = (child.type as any)?.name as string | undefined;
87
- if (name === componentName) {
88
- // 找到目标组件,广播事件
89
- // Vue3未解决,目标组件事件监听失效,待优化,暂时使用下面的方式解决,如果你有好的方式也可以告诉我或者提PR
90
- child.emit && child.emit(eventName, ...params);
91
- // 如果有对应的方法,执行方法
92
- // 这里可以考虑将 eventName 转换为驼峰格式
93
- // 例如:on-form-change -> onFormChange
94
- child.exposed?.[formatToCamelCase(eventName)] && child.exposed[formatToCamelCase(eventName)](...params);
95
- } else {
96
- broadcast(child, componentName, eventName, ...params);
97
- }
98
- }
99
- });
100
- }
101
-
102
- export { dispatch, broadcast, parent };
1
+ import { getCurrentInstance, type ComponentInternalInstance } from 'vue';
2
+
3
+ /**
4
+ * 适用于 uni-app Vue3 的事件派发/广播工具
5
+ * 用法:import { dispatch, broadcast } from './emitter'
6
+ */
7
+
8
+ /**
9
+ * 向上查找父组件并派发事件
10
+ * @param instance 当前组件实例(setup中可用getCurrentInstance())
11
+ * @param componentName 目标组件名
12
+ * @param eventName 事件名
13
+ * @param params 参数
14
+ */
15
+
16
+ // 将事件名转换为驼峰格式
17
+ // 例如:on-form-change -> onFormChange
18
+ function formatToCamelCase(str: string): string {
19
+ return str.replace(/-([a-z])/g, function (g) {
20
+ return g[1].toUpperCase();
21
+ });
22
+ }
23
+
24
+ /**
25
+ * 向上查找父组件
26
+ * @param instance 当前组件实例(setup中可用getCurrentInstance())
27
+ * @param componentName 目标组件名
28
+ * @returns 父组件实例
29
+ */
30
+ function parent(instance: ComponentInternalInstance | null | undefined = undefined, componentName: string = '') {
31
+ if (!instance) {
32
+ instance = getCurrentInstance();
33
+ }
34
+ let parent = instance && (instance.parent as ComponentInternalInstance | null | undefined);
35
+
36
+ if (!componentName) return parent;
37
+ while (parent) {
38
+ const name = (parent.type as any)?.name as string | undefined;
39
+ if (name === componentName) {
40
+ return parent;
41
+ }
42
+ parent = parent.parent;
43
+ }
44
+ return null;
45
+ }
46
+
47
+ /** * 向上查找父组件并派发事件
48
+ * @param instance 当前组件实例(setup中可用getCurrentInstance())
49
+ * @param componentName 目标组件名
50
+ * @param eventName 事件名
51
+ * @param params 参数
52
+ */
53
+ function dispatch(instance: ComponentInternalInstance | null | undefined, componentName: string, eventName: string, ...params: any[]) {
54
+ let parent = instance && (instance.parent as ComponentInternalInstance | null | undefined);
55
+ while (parent) {
56
+ const name = (parent.type as any)?.name as string | undefined;
57
+ if (name === componentName) {
58
+ // 找到目标组件,派发事件
59
+ // Vue3未解决,目标组件事件监听失效,待优化,暂时使用下面的方式解决,如果你有好的方式也可以告诉我或者提PR
60
+ parent.emit && parent.emit(eventName, ...params);
61
+ // 如果有对应的方法,执行方法
62
+ // 这里可以考虑将 eventName 转换为驼峰格式
63
+ // 例如:on-form-change -> onFormChange
64
+ parent.exposed?.[formatToCamelCase(eventName)] && parent.exposed[formatToCamelCase(eventName)](...params);
65
+ break;
66
+ }
67
+ parent = parent.parent;
68
+ }
69
+ }
70
+
71
+ /**
72
+ * 向下递归查找子组件并广播事件
73
+ * @param instance 当前组件实例(setup中可用getCurrentInstance())
74
+ * @param componentName 目标组件名
75
+ * @param eventName 事件名
76
+ * @param params 参数
77
+ */
78
+ function broadcast(instance: ComponentInternalInstance | null | undefined, componentName: string, eventName: string, ...params: any[]) {
79
+ if (!instance) return;
80
+ const subTree = (instance.subTree as any)?.children || [];
81
+ const children = Array.isArray(subTree) ? subTree : [subTree];
82
+ children.forEach((vnode: any) => {
83
+ const child = vnode.component as ComponentInternalInstance | undefined;
84
+
85
+ if (child) {
86
+ const name = (child.type as any)?.name as string | undefined;
87
+ if (name === componentName) {
88
+ // 找到目标组件,广播事件
89
+ // Vue3未解决,目标组件事件监听失效,待优化,暂时使用下面的方式解决,如果你有好的方式也可以告诉我或者提PR
90
+ child.emit && child.emit(eventName, ...params);
91
+ // 如果有对应的方法,执行方法
92
+ // 这里可以考虑将 eventName 转换为驼峰格式
93
+ // 例如:on-form-change -> onFormChange
94
+ child.exposed?.[formatToCamelCase(eventName)] && child.exposed[formatToCamelCase(eventName)](...params);
95
+ } else {
96
+ broadcast(child, componentName, eventName, ...params);
97
+ }
98
+ }
99
+ });
100
+ }
101
+
102
+ export { dispatch, broadcast, parent };
@@ -0,0 +1,86 @@
1
+ // utils/eventBus.ts
2
+
3
+ // 更灵活的事件回调类型定义
4
+ type EventCallback = (data?: any, ...args: any[]) => void;
5
+
6
+ class EventBus {
7
+ private events: Map<string, EventCallback[]> = new Map();
8
+
9
+ /**
10
+ * 监听事件
11
+ */
12
+ on(event: string, callback: EventCallback): void {
13
+ if (!this.events.has(event)) {
14
+ this.events.set(event, []);
15
+ }
16
+ this.events.get(event)!.push(callback);
17
+ }
18
+
19
+ /**
20
+ * 一次性监听
21
+ */
22
+ once(event: string, callback: EventCallback): void {
23
+ const onceCallback: EventCallback = (data, ...args) => {
24
+ callback(data, ...args);
25
+ this.off(event, onceCallback);
26
+ };
27
+ this.on(event, onceCallback);
28
+ }
29
+
30
+ /**
31
+ * 触发事件
32
+ */
33
+ emit(event: string, data?: any, ...args: any[]): void {
34
+ if (this.events.has(event)) {
35
+ this.events.get(event)!.forEach(callback => {
36
+ try {
37
+ callback(data, ...args);
38
+ } catch (error) {
39
+ console.error(`EventBus error in ${event}:`, error);
40
+ }
41
+ });
42
+ }
43
+ }
44
+
45
+ /**
46
+ * 取消监听
47
+ */
48
+ off(event: string, callback?: EventCallback): void {
49
+ if (!this.events.has(event)) return;
50
+
51
+ if (callback) {
52
+ const callbacks = this.events.get(event)!;
53
+ const index = callbacks.indexOf(callback);
54
+ if (index > -1) {
55
+ callbacks.splice(index, 1);
56
+ }
57
+ } else {
58
+ this.events.delete(event);
59
+ }
60
+ }
61
+
62
+ /**
63
+ * 检查是否有监听器
64
+ */
65
+ has(event: string): boolean {
66
+ return this.events.has(event) && this.events.get(event)!.length > 0;
67
+ }
68
+
69
+ /**
70
+ * 清理所有事件
71
+ */
72
+ clear(): void {
73
+ this.events.clear();
74
+ }
75
+ }
76
+
77
+ // 创建全局实例
78
+ export const eventBus = new EventBus();
79
+
80
+ // 热更新处理
81
+ if (import.meta.hot) {
82
+ import.meta.hot.accept(() => {
83
+ // 热更新时不清理事件,保持事件监听
84
+ console.log('EventBus hot updated');
85
+ });
86
+ }
@@ -0,0 +1,364 @@
1
+ // utils/logger.ts
2
+
3
+ // 定义原始控制台方法的类型
4
+ interface ConsoleMethods {
5
+ log: typeof console.log;
6
+ info: typeof console.info;
7
+ warn: typeof console.warn;
8
+ error: typeof console.error;
9
+ debug?: typeof console.debug;
10
+ trace?: typeof console.trace;
11
+ table?: typeof console.table;
12
+ time?: typeof console.time;
13
+ timeEnd?: typeof console.timeEnd;
14
+ group?: typeof console.group;
15
+ groupEnd?: typeof console.groupEnd;
16
+ groupCollapsed?: typeof console.groupCollapsed;
17
+ assert?: typeof console.assert;
18
+ clear?: typeof console.clear;
19
+ count?: typeof console.count;
20
+ countReset?: typeof console.countReset;
21
+ }
22
+
23
+ // 安全地获取控制台方法
24
+ const originalConsole: ConsoleMethods = {
25
+ log: console.log,
26
+ info: console.info,
27
+ warn: console.warn,
28
+ error: console.error,
29
+ debug: console.debug,
30
+ trace: console.trace,
31
+ table: console.table,
32
+ time: console.time,
33
+ timeEnd: console.timeEnd,
34
+ group: console.group,
35
+ groupEnd: console.groupEnd,
36
+ groupCollapsed: console.groupCollapsed,
37
+ assert: console.assert,
38
+ clear: console.clear,
39
+ count: console.count,
40
+ countReset: console.countReset
41
+ };
42
+
43
+ // 检查并确保所有方法都存在,不存在的方法用空函数替代
44
+ Object.keys(originalConsole).forEach(key => {
45
+ const methodKey = key as keyof ConsoleMethods;
46
+ if (!originalConsole[methodKey]) {
47
+ (originalConsole[methodKey] as any) = () => {};
48
+ }
49
+ });
50
+
51
+ class Logger {
52
+ private debugMode: boolean = false;
53
+ private prefix: string = '[uViewPro]';
54
+ private showCallerInfo: boolean = true;
55
+
56
+ /**
57
+ * 设置调试模式
58
+ * @param enabled 是否启用调试模式
59
+ */
60
+ setDebugMode(enabled: boolean) {
61
+ this.debugMode = !!enabled;
62
+
63
+ if (this.debugMode) {
64
+ console.log('[uViewPro] Debug mode enabled');
65
+ } else {
66
+ console.log('[uViewPro] Debug mode disabled');
67
+ }
68
+ return this;
69
+ }
70
+
71
+ /**
72
+ * 设置是否显示调用者信息(文件名和行号)
73
+ * @param show 是否显示调用者信息
74
+ */
75
+ setShowCallerInfo(show: boolean) {
76
+ this.showCallerInfo = !!show;
77
+ return this;
78
+ }
79
+
80
+ /**
81
+ * 设置日志前缀
82
+ * @param prefix 日志前缀
83
+ */
84
+ setPrefix(prefix: string) {
85
+ if (prefix) this.prefix = prefix;
86
+ return this;
87
+ }
88
+
89
+ /**
90
+ * 获取当前调试模式状态
91
+ * @returns 当前调试模式状态
92
+ */
93
+ getDebugMode(): boolean {
94
+ return this.debugMode;
95
+ }
96
+
97
+ /**
98
+ * 从文件路径中提取纯净的文件名(去除查询参数和路径)
99
+ * @param filePath 文件路径
100
+ * @returns 纯净的文件名
101
+ */
102
+ private extractFileName(filePath: string): string {
103
+ if (!filePath) return '';
104
+
105
+ // 去除查询参数(?后面的内容)
106
+ const withoutQuery = filePath.split('?')[0];
107
+
108
+ // 使用正斜杠和反斜杠分割路径,取最后一部分
109
+ const parts = withoutQuery.split(/[/\\]/);
110
+ const fileNameWithExt = parts.pop() || '';
111
+
112
+ return fileNameWithExt;
113
+ }
114
+
115
+ /**
116
+ * 获取调用者信息(文件名和行号)
117
+ * @returns 调用者信息字符串
118
+ */
119
+ private getCallerInfo(): string {
120
+ if (!this.showCallerInfo) return '';
121
+
122
+ try {
123
+ // 创建一个 Error 对象来获取堆栈跟踪
124
+ const error = new Error();
125
+ const stack = error.stack;
126
+
127
+ if (!stack) return '';
128
+
129
+ // 解析堆栈跟踪,找到调用 logger 的文件和行号
130
+ const stackLines = stack.split('\n');
131
+
132
+ // 找到第一个不是 logger.ts 的堆栈行
133
+ for (let i = 3; i < stackLines.length; i++) {
134
+ const line = stackLines[i].trim();
135
+ if (line && !line.includes('logger.ts') && !line.includes('Logger.') && !line.includes('at Object.')) {
136
+ // 提取文件名和行号
137
+ const match = line.match(/\(?(.*):(\d+):(\d+)\)?/);
138
+ if (match) {
139
+ const filePath = match[1];
140
+ const lineNumber = match[2];
141
+ const fileName = this.extractFileName(filePath);
142
+ return `[${fileName}:${lineNumber}]`;
143
+ }
144
+ break;
145
+ }
146
+ }
147
+ } catch (e) {
148
+ // 如果获取调用者信息失败,静默处理
149
+ }
150
+
151
+ return '';
152
+ }
153
+
154
+ /**
155
+ * 通用日志输出方法
156
+ * @param level 日志级别
157
+ * @param args 日志参数
158
+ */
159
+ private output(level: keyof ConsoleMethods, ...args: any[]): void {
160
+ if (!this.debugMode || !originalConsole[level]) return;
161
+
162
+ const method = originalConsole[level] as Function;
163
+ const callerInfo = this.getCallerInfo();
164
+
165
+ if (this.prefix) {
166
+ if (callerInfo) {
167
+ method(`${this.prefix}${callerInfo}`, ...args);
168
+ } else {
169
+ method(this.prefix, ...args);
170
+ }
171
+ } else {
172
+ if (callerInfo) {
173
+ method(callerInfo, ...args);
174
+ } else {
175
+ method(...args);
176
+ }
177
+ }
178
+ }
179
+
180
+ /**
181
+ * 普通日志
182
+ * @param args 日志参数
183
+ */
184
+ log(...args: any[]): void {
185
+ this.output('log', ...args);
186
+ }
187
+
188
+ /**
189
+ * 信息日志
190
+ * @param args 日志参数
191
+ */
192
+ info(...args: any[]): void {
193
+ this.output('info', ...args);
194
+ }
195
+
196
+ /**
197
+ * 警告日志
198
+ * @param args 日志参数
199
+ */
200
+ warn(...args: any[]): void {
201
+ this.output('warn', ...args);
202
+ }
203
+
204
+ /**
205
+ * 错误日志
206
+ * @param args 日志参数
207
+ */
208
+ error(...args: any[]): void {
209
+ this.output('error', ...args);
210
+ }
211
+
212
+ /**
213
+ * 调试日志
214
+ * @param args 日志参数
215
+ */
216
+ debug(...args: any[]): void {
217
+ if (!originalConsole.debug) return;
218
+ this.output('debug', ...args);
219
+ }
220
+
221
+ /**
222
+ * 堆栈跟踪
223
+ * @param args 日志参数
224
+ */
225
+ trace(...args: any[]): void {
226
+ if (!originalConsole.trace) return;
227
+ this.output('trace', ...args);
228
+ }
229
+
230
+ /**
231
+ * 表格输出
232
+ * @param data 表格数据
233
+ * @param columns 列名(可选)
234
+ */
235
+ table(data: any, columns?: string[]): void {
236
+ if (!this.debugMode || !originalConsole.table) return;
237
+
238
+ if (this.prefix) {
239
+ originalConsole.log!(this.prefix);
240
+ }
241
+ originalConsole.table!(data, columns);
242
+ }
243
+
244
+ /**
245
+ * 开始计时
246
+ * @param label 计时器标签
247
+ */
248
+ time(label: string): void {
249
+ if (!this.debugMode || !originalConsole.time) return;
250
+
251
+ const fullLabel = this.prefix ? `${this.prefix} ${label}` : label;
252
+ originalConsole.time!(fullLabel);
253
+ }
254
+
255
+ /**
256
+ * 结束计时
257
+ * @param label 计时器标签
258
+ */
259
+ timeEnd(label: string): void {
260
+ if (!this.debugMode || !originalConsole.timeEnd) return;
261
+
262
+ const fullLabel = this.prefix ? `${this.prefix} ${label}` : label;
263
+ originalConsole.timeEnd!(fullLabel);
264
+ }
265
+
266
+ /**
267
+ * 分组日志
268
+ * @param label 分组标签
269
+ */
270
+ group(label: string): void {
271
+ if (!this.debugMode || !originalConsole.group) return;
272
+
273
+ const fullLabel = this.prefix ? `${this.prefix} ${label}` : label;
274
+ originalConsole.group!(fullLabel);
275
+ }
276
+
277
+ /**
278
+ * 结束分组
279
+ */
280
+ groupEnd(): void {
281
+ if (!this.debugMode || !originalConsole.groupEnd) return;
282
+ originalConsole.groupEnd!();
283
+ }
284
+
285
+ /**
286
+ * 分组日志(默认折叠)
287
+ * @param label 分组标签
288
+ */
289
+ groupCollapsed(label: string): void {
290
+ if (!this.debugMode || !originalConsole.groupCollapsed) return;
291
+
292
+ const fullLabel = this.prefix ? `${this.prefix} ${label}` : label;
293
+ originalConsole.groupCollapsed!(fullLabel);
294
+ }
295
+
296
+ /**
297
+ * 断言
298
+ * @param condition 条件
299
+ * @param message 错误消息
300
+ */
301
+ assert(condition: boolean, ...message: any[]): void {
302
+ if (!this.debugMode || !originalConsole.assert) return;
303
+
304
+ if (this.prefix) {
305
+ originalConsole.assert!(condition, this.prefix, ...message);
306
+ } else {
307
+ originalConsole.assert!(condition, ...message);
308
+ }
309
+ }
310
+
311
+ /**
312
+ * 清空控制台
313
+ */
314
+ clear(): void {
315
+ if (!this.debugMode || !originalConsole.clear) return;
316
+ originalConsole.clear!();
317
+ }
318
+
319
+ /**
320
+ * 计数器
321
+ * @param label 计数器标签
322
+ */
323
+ count(label?: string): void {
324
+ if (!this.debugMode || !originalConsole.count) return;
325
+
326
+ const fullLabel = this.prefix && label ? `${this.prefix} ${label}` : label || this.prefix;
327
+ originalConsole.count!(fullLabel);
328
+ }
329
+
330
+ /**
331
+ * 重置计数器
332
+ * @param label 计数器标签
333
+ */
334
+ countReset(label?: string): void {
335
+ if (!this.debugMode || !originalConsole.countReset) return;
336
+
337
+ const fullLabel = this.prefix && label ? `${this.prefix} ${label}` : label || this.prefix;
338
+ originalConsole.countReset!(fullLabel);
339
+ }
340
+
341
+ /**
342
+ * 带样式的日志
343
+ * @param style CSS样式
344
+ * @param message 消息内容
345
+ */
346
+ styled(style: string, message: string): void {
347
+ if (!this.debugMode) return;
348
+
349
+ const callerInfo = this.getCallerInfo();
350
+ const fullMessage = callerInfo ? `${message} ${callerInfo}` : message;
351
+
352
+ if (this.prefix) {
353
+ console.log(`%c${this.prefix} ${fullMessage}`, style);
354
+ } else {
355
+ console.log(`%c${fullMessage}`, style);
356
+ }
357
+ }
358
+ }
359
+
360
+ // 创建全局单例
361
+ const logger = new Logger();
362
+
363
+ // 导出单例和类
364
+ export { logger, Logger };