uview-pro 0.6.2 → 0.6.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.
package/changelog.md CHANGED
@@ -1,18 +1,32 @@
1
- ## 0.6.2(2026-05-15
2
-
3
- ### 🐛 Bug Fixes | Bug 修复
4
-
5
- - **u-checkbox:** 修复多选框在头条、抖音小程序图标偏移的问题 ([8ea1838](https://github.com/anyup/uView-Pro/commit/8ea18383b94b421cabea7d080a6867f4b6133ff5))
6
- - **u-radio:** 修复单选框在头条、抖音小程序图标偏移的问题 ([dd7d6fe](https://github.com/anyup/uView-Pro/commit/dd7d6fee5a22bb39b3dcea9a24b9a06da40ee20e))
7
-
8
- ### ✨ Features | 新功能
9
-
10
- - 添加 u-input 组件禁用状态样式 (#155) ([1145d99](https://github.com/anyup/uView-Pro/commit/1145d996ca111da769665ee5dca1bf07a0a1968d))
11
-
12
- ### 👥 Contributors
13
-
14
- <a href="https://github.com/anyup"><img src="https://github.com/anyup.png?size=40" width="40" height="40" alt="anyup" title="anyup"/></a> <a href="https://github.com/1361176289"><img src="https://github.com/1361176289.png?size=40" width="40" height="40" alt="小陆同学" title="小陆同学"/></a>
15
-
1
+ ## 0.6.3(2026-05-28
2
+
3
+ ### 🐛 Bug Fixes | Bug 修复
4
+
5
+ - **u-upload:** 修复进度条显示和上传终止的判断逻辑(#156) ([ad30563](https://github.com/anyup/uView-Pro/commit/ad305638b7e0977c60eda470a682ebb3ecf62c9e))
6
+
7
+ ### ✨ Features | 新功能
8
+
9
+ - **u-dropdown:** 新增fixed定位选项,支持自动适配状态栏和导航栏高度,新增immersive沉浸式模式,增加offsetTop、navbarHeight、zIndex,增强灵活性 ([fc262bd](https://github.com/anyup/uView-Pro/commit/fc262bd5cc078fd3cbb825df2a9066427ccc9b69))
10
+
11
+ ### 👥 Contributors
12
+
13
+ <a href="https://github.com/anyup"><img src="https://github.com/anyup.png?size=40" width="40" height="40" alt="anyup" title="anyup"/></a>
14
+
15
+ ## 0.6.2(2026-05-15)
16
+
17
+ ### 🐛 Bug Fixes | Bug 修复
18
+
19
+ - **u-checkbox:** 修复多选框在头条、抖音小程序图标偏移的问题 ([8ea1838](https://github.com/anyup/uView-Pro/commit/8ea18383b94b421cabea7d080a6867f4b6133ff5))
20
+ - **u-radio:** 修复单选框在头条、抖音小程序图标偏移的问题 ([dd7d6fe](https://github.com/anyup/uView-Pro/commit/dd7d6fee5a22bb39b3dcea9a24b9a06da40ee20e))
21
+
22
+ ### ✨ Features | 新功能
23
+
24
+ - 添加 u-input 组件禁用状态样式 (#155) ([1145d99](https://github.com/anyup/uView-Pro/commit/1145d996ca111da769665ee5dca1bf07a0a1968d))
25
+
26
+ ### 👥 Contributors
27
+
28
+ <a href="https://github.com/anyup"><img src="https://github.com/anyup.png?size=40" width="40" height="40" alt="anyup" title="anyup"/></a> <a href="https://github.com/1361176289"><img src="https://github.com/1361176289.png?size=40" width="40" height="40" alt="小陆同学" title="小陆同学"/></a>
29
+
16
30
  ## 0.6.1(2026-05-13)
17
31
 
18
32
  ### ✨ Features | 新功能
@@ -1,5 +1,6 @@
1
1
  import type { ExtractPropTypes, PropType } from 'vue';
2
2
  import { getColor } from '../../';
3
+ import zIndex from '../../libs/config/zIndex';
3
4
 
4
5
  /**
5
6
  * u-dropdown 下拉菜单 Props
@@ -37,7 +38,30 @@ export const DropdownProps = {
37
38
  /** 菜单右侧的icon图标 */
38
39
  menuIcon: { type: String, default: 'arrow-down' },
39
40
  /** 菜单右侧图标的大小 */
40
- menuIconSize: { type: [Number, String] as PropType<number | string>, default: 26 }
41
+ menuIconSize: { type: [Number, String] as PropType<number | string>, default: 26 },
42
+ /**
43
+ * 是否使用fixed定位,开启后下拉菜单固定在顶部,
44
+ * 自动适配状态栏和导航栏高度,并生成占位区域防止页面塌陷
45
+ */
46
+ fixed: { type: Boolean, default: false },
47
+ /**
48
+ * fixed定位时,在自动计算的偏移量基础上的额外顶部偏移量(px),用于用户微调位置。
49
+ * 实际top = statusBarHeight + navbarHeight + offsetTop
50
+ */
51
+ offsetTop: { type: [Number, String] as PropType<number | string>, default: 0 },
52
+ /**
53
+ * fixed定位时,状态栏和导航栏所占的总高度(px)。
54
+ * 默认不设置(空字符串),组件会自动获取系统状态栏高度 + 默认导航栏高度(44px)。
55
+ * 设置任意数值(包括0)则使用用户指定值,不再自动计算。
56
+ */
57
+ navbarHeight: { type: [Number, String] as PropType<number | string>, default: '' },
58
+ /**
59
+ * 沉浸式模式,仅在fixed下生效。
60
+ * 开启后不生成占位区域,允许页面内容延伸到dropdown下方(类似沉浸式导航栏)
61
+ */
62
+ immersive: { type: Boolean, default: false },
63
+ /** fixed定位时的z-index值 */
64
+ zIndex: { type: [Number, String] as PropType<number | string>, default: zIndex.dropdown }
41
65
  };
42
66
 
43
67
  export type DropdownProps = ExtractPropTypes<typeof DropdownProps>;
@@ -1,63 +1,73 @@
1
1
  <template>
2
- <view class="u-dropdown" :style="$u.toStyle(styles, customStyle)" :class="customClass">
3
- <view
4
- class="u-dropdown__menu"
5
- :style="{ height: $u.addUnit(height) }"
6
- :class="{ 'u-border-bottom': borderBottom }"
7
- >
2
+ <view class="u-dropdown-wrapper">
3
+ <view class="u-dropdown" :style="dropdownRootStyle" :class="[{ 'u-dropdown__fixed': fixed }, customClass]">
8
4
  <view
9
- class="u-dropdown__menu__item"
10
- v-for="(item, index) in menuList"
11
- :key="index"
12
- @tap.stop="menuClick(index)"
5
+ class="u-dropdown__menu"
6
+ :style="{ height: $u.addUnit(height) }"
7
+ :class="{ 'u-border-bottom': borderBottom }"
13
8
  >
14
- <view class="u-flex">
15
- <text
16
- class="u-dropdown__menu__item__text"
17
- :style="{
18
- color: item.disabled
19
- ? 'var(--u-light-color)'
20
- : index === current || highlightIndex == index
21
- ? activeColor
22
- : inactiveColor,
23
- fontSize: $u.addUnit(titleSize)
24
- }"
25
- >{{ item.title }}</text
26
- >
27
- <view
28
- class="u-dropdown__menu__item__arrow"
29
- :class="{
30
- 'u-dropdown__menu__item__arrow--rotate': index === current
31
- }"
32
- >
33
- <u-icon
34
- :custom-style="{ display: 'flex' }"
35
- :name="menuIcon"
36
- :size="$u.addUnit(menuIconSize)"
37
- :color="index === current || highlightIndex == index ? activeColor : 'var(--u-light-color)'"
38
- ></u-icon>
9
+ <view
10
+ class="u-dropdown__menu__item"
11
+ v-for="(item, index) in menuList"
12
+ :key="index"
13
+ @tap.stop="menuClick(index)"
14
+ >
15
+ <view class="u-flex">
16
+ <text
17
+ class="u-dropdown__menu__item__text"
18
+ :style="{
19
+ color: item.disabled
20
+ ? 'var(--u-light-color)'
21
+ : index === current || highlightIndex == index
22
+ ? activeColor
23
+ : inactiveColor,
24
+ fontSize: $u.addUnit(titleSize)
25
+ }"
26
+ >{{ item.title }}</text
27
+ >
28
+ <view
29
+ class="u-dropdown__menu__item__arrow"
30
+ :class="{
31
+ 'u-dropdown__menu__item__arrow--rotate': index === current
32
+ }"
33
+ >
34
+ <u-icon
35
+ :custom-style="{ display: 'flex' }"
36
+ :name="menuIcon"
37
+ :size="$u.addUnit(menuIconSize)"
38
+ :color="
39
+ index === current || highlightIndex == index ? activeColor : 'var(--u-light-color)'
40
+ "
41
+ ></u-icon>
42
+ </view>
39
43
  </view>
40
44
  </view>
41
45
  </view>
42
- </view>
43
- <view
44
- class="u-dropdown__content"
45
- :style="[
46
- contentStyle,
47
- {
48
- transition: `opacity ${Number(duration) / 1000}s linear`,
49
- top: $u.addUnit(height),
50
- height: contentHeight + 'px'
51
- }
52
- ]"
53
- @tap="maskClick"
54
- @touchmove.stop.prevent
55
- >
56
- <view @tap.stop.prevent class="u-dropdown__content__popup" :style="[popupStyle]">
57
- <slot></slot>
46
+ <view
47
+ class="u-dropdown__content"
48
+ :style="[
49
+ contentStyle,
50
+ {
51
+ transition: `opacity ${Number(duration) / 1000}s linear`,
52
+ top: $u.addUnit(height),
53
+ height: contentHeight + 'px'
54
+ }
55
+ ]"
56
+ @tap="maskClick"
57
+ @touchmove.stop.prevent
58
+ >
59
+ <view @tap.stop.prevent class="u-dropdown__content__popup" :style="[popupStyle]">
60
+ <slot></slot>
61
+ </view>
62
+ <view class="u-dropdown__content__mask"></view>
58
63
  </view>
59
- <view class="u-dropdown__content__mask"></view>
60
64
  </view>
65
+ <!-- fixed定位时的占位区域,防止页面内容塌陷 -->
66
+ <view
67
+ v-if="fixed && !immersive"
68
+ class="u-dropdown__placeholder"
69
+ :style="{ height: dropdownPlaceholderHeight + 'px' }"
70
+ ></view>
61
71
  </view>
62
72
  </template>
63
73
 
@@ -75,13 +85,14 @@ export default {
75
85
  </script>
76
86
 
77
87
  <script setup lang="ts">
78
- import { ref, computed, onMounted, getCurrentInstance, nextTick } from 'vue';
88
+ import { ref, computed, onMounted, nextTick } from 'vue';
79
89
  import { $u, useParent } from '../..';
80
90
  import { DropdownProps } from './types';
81
91
 
82
92
  /**
83
93
  * dropdown 下拉菜单
84
- * @description 该组件一般用于向下展开菜单,同时可切换多个选项卡的场景
94
+ * @description 该组件一般用于向下展开菜单,同时可切换多个选项卡的场景。
95
+ * 支持fixed定位,自动适配状态栏和导航栏高度,并提供占位区域防止页面塌陷。
85
96
  * @tutorial https://uviewpro.cn/zh/components/dropdown.html
86
97
  * @property {String} active-color 标题和选项卡选中的颜色(默认主题色primary)
87
98
  * @property {String} inactive-color 标题和选项卡未选中的颜色(默认var(--u-content-color))
@@ -92,9 +103,14 @@ import { DropdownProps } from './types';
92
103
  * @property {String | Number} border-radius 菜单展开内容下方的圆角值,单位任意(默认0)
93
104
  * @property {Boolean} border-bottom 标题菜单是否显示下边框(默认false)
94
105
  * @property {String | Number} title-size 标题的字体大小,单位任意,数值默认为rpx单位(默认28)
106
+ * @property {Boolean} fixed 是否使用fixed定位固定在顶部,自动适配状态栏和导航栏高度(默认false)
107
+ * @property {String | Number} offset-top fixed定位时,在自动计算的偏移量基础上的额外顶部偏移量,单位px(默认0)
108
+ * @property {String | Number} navbar-height fixed定位时,状态栏+导航栏的总高度(px)。不设置则自动获取,设置任意数值(包括0)则使用指定值
109
+ * @property {Boolean} immersive 沉浸式模式,仅在fixed下生效,开启后不生成占位区域(默认false)
110
+ * @property {String | Number} z-index fixed定位时的z-index值(默认985)
95
111
  * @event {Function} open 下拉菜单被打开时触发
96
112
  * @event {Function} close 下拉菜单被关闭时触发
97
- * @example <u-dropdown></u-dropdown>
113
+ * @example <u-dropdown :fixed="true"></u-dropdown>
98
114
  */
99
115
 
100
116
  const props = defineProps(DropdownProps);
@@ -115,14 +131,74 @@ const contentStyle = ref<any>({ zIndex: -1, opacity: 0 });
115
131
  const highlightIndex = ref<number>(99999);
116
132
  // 下拉内容高度
117
133
  const contentHeight = ref<number>(0);
118
- // 子组件引用
119
- const instance = getCurrentInstance();
120
- // 兼容头条样式
121
- const styles = computed(() => {
122
- const style: any = {};
134
+
135
+ // ==================== fixed定位相关 ====================
136
+ // 获取系统状态栏高度
137
+ const systemInfo = uni.getSystemInfoSync();
138
+ const statusBarHeight = ref(0);
139
+ // #ifdef APP-HARMONY || MP-WEIXIN
140
+ const windowInfo = uni.getWindowInfo();
141
+ statusBarHeight.value = windowInfo.statusBarHeight || 0;
142
+ // #endif
143
+ // #ifndef APP-HARMONY || MP-WEIXIN
144
+ statusBarHeight.value = systemInfo.statusBarHeight || 0;
145
+ // #endif
146
+
147
+ // 默认导航栏高度(与 u-navbar 保持一致)
148
+ const defaultNavbarHeight = computed(() => {
149
+ // #ifdef APP || H5
150
+ return 44;
151
+ // #endif
152
+ // #ifdef MP
153
+ return systemInfo.platform === 'ios' ? 44 : 48;
154
+ // #endif
155
+ });
156
+
157
+ /**
158
+ * 计算 fixed 定位时的总偏移高度(px)
159
+ * - 若用户通过 navbarHeight 指定了任意数值(包括0),则使用用户指定值
160
+ * - 否则(空字符串)自动计算:状态栏高度 + 默认导航栏高度
161
+ * - 最后加上 offsetTop 作为额外偏移
162
+ */
163
+ const dropdownOffsetHeight = computed(() => {
164
+ let baseHeight: number;
165
+ if (props.navbarHeight !== '' && props.navbarHeight !== undefined && props.navbarHeight !== null) {
166
+ // 用户手动指定了 navbar 高度(包括0),直接使用
167
+ baseHeight = Number(props.navbarHeight);
168
+ } else {
169
+ // 自动计算:状态栏高度 + 默认导航栏高度
170
+ baseHeight = statusBarHeight.value + defaultNavbarHeight.value;
171
+ }
172
+ // 加上用户设置的额外 offsetTop 偏移
173
+ return baseHeight + Number(props.offsetTop);
174
+ });
175
+
176
+ /**
177
+ * 占位区域高度 = dropdown菜单栏自身高度(px)
178
+ * 不包含状态栏+导航栏偏移,因为页面上已有 navbar 等元素占据该空间
179
+ */
180
+ const dropdownPlaceholderHeight = computed(() => {
181
+ return uni.upx2px(Number(props.height));
182
+ });
183
+
184
+ /**
185
+ * dropdown 根节点样式
186
+ * fixed 时设置 top 和 z-index
187
+ */
188
+ const dropdownRootStyle = computed(() => {
189
+ const style: Record<string, any> = {};
190
+
191
+ // 兼容头条小程序
123
192
  // #ifdef MP-TOUTIAO
124
193
  style.width = '100vw';
125
194
  // #endif
195
+
196
+ // fixed 定位时,计算顶部偏移和 z-index
197
+ if (props.fixed) {
198
+ style.top = dropdownOffsetHeight.value + 'px';
199
+ style.zIndex = props.zIndex ? Number(props.zIndex) : $u.zIndex.dropdown;
200
+ }
201
+
126
202
  return style;
127
203
  });
128
204
 
@@ -193,7 +269,7 @@ function open(index: number) {
193
269
  // 重置高亮索引,否则会造成多个菜单同时高亮
194
270
  // highlightIndex.value = 9999;
195
271
  // 展开时,设置下拉内容的样式
196
- contentStyle.value = { zIndex: 11 };
272
+ contentStyle.value = { zIndex: 11, display: 'block' };
197
273
  // 标记展开状态以及当前展开项的索引
198
274
  active.value = true;
199
275
  current.value = index;
@@ -214,8 +290,12 @@ function close() {
214
290
  // 设置为收起状态,同时current归位,设置为空字符串
215
291
  active.value = false;
216
292
  current.value = 99999;
217
- // 下拉内容的样式进行调整,不透明度设置为0
218
- contentStyle.value = { zIndex: -1, opacity: 0 };
293
+ // 下拉内容的样式进行调整,不透明度设置为0,fixed模式下隐藏display避免遮挡页面元素
294
+ if (props.fixed) {
295
+ contentStyle.value = { zIndex: -1, opacity: 0, display: 'none' };
296
+ } else {
297
+ contentStyle.value = { zIndex: -1, opacity: 0 };
298
+ }
219
299
  }
220
300
 
221
301
  /**
@@ -243,14 +323,15 @@ function highlight(index?: number) {
243
323
  */
244
324
  function getContentHeight() {
245
325
  const windowHeight = $u.sys().windowHeight;
326
+ contentHeight.value = windowHeight;
246
327
 
247
- $u.getRect('.u-dropdown__menu', instance).then((res: any) => {
248
- // 这里获取的是dropdown的尺寸,在H5上,uniapp获取尺寸是有bug的(以前提出修复过,后来又出现了此bug,目前hx2.8.11版本)
249
- // H5端bug表现为元素尺寸的top值为导航栏底部到到元素的上边沿的距离,但是元素的bottom值确是导航栏顶部到元素底部的距离
250
- // 二者是互相矛盾的,本质原因是H5端导航栏非原生,uni的开发者大意造成
251
- // 这里取菜单栏的botton值合理的,不能用res.top,否则页面会造成滚动
252
- contentHeight.value = windowHeight - res.bottom;
253
- });
328
+ // $u.getRect('.u-dropdown__menu', instance).then((res: any) => {
329
+ // // 这里获取的是dropdown的尺寸,在H5上,uniapp获取尺寸是有bug的(以前提出修复过,后来又出现了此bug,目前hx2.8.11版本)
330
+ // // H5端bug表现为元素尺寸的top值为导航栏底部到到元素的上边沿的距离,但是元素的bottom值确是导航栏顶部到元素底部的距离
331
+ // // 二者是互相矛盾的,本质原因是H5端导航栏非原生,uni的开发者大意造成
332
+ // // 这里取菜单栏的botton值合理的,不能用res.top,否则页面会造成滚动
333
+ // contentHeight.value = windowHeight - res.bottom;
334
+ // });
254
335
  }
255
336
 
256
337
  onMounted(() => {
@@ -275,11 +356,26 @@ defineExpose({
275
356
  <style scoped lang="scss">
276
357
  @import '../../libs/css/style.components.scss';
277
358
 
359
+ .u-dropdown-wrapper {
360
+ width: 100%;
361
+ }
362
+
278
363
  .u-dropdown {
279
364
  flex: 1;
280
365
  width: 100%;
281
366
  position: relative;
282
367
 
368
+ &__fixed {
369
+ position: fixed;
370
+ left: 0;
371
+ right: 0;
372
+ background-color: #fff;
373
+ }
374
+
375
+ &__placeholder {
376
+ width: 100%;
377
+ }
378
+
283
379
  &__menu {
284
380
  @include vue-flex;
285
381
  position: relative;
@@ -312,7 +408,6 @@ defineExpose({
312
408
 
313
409
  &__content {
314
410
  position: absolute;
315
- z-index: 8;
316
411
  width: 100%;
317
412
  left: 0px;
318
413
  bottom: 0;
@@ -51,7 +51,13 @@
51
51
  </text>
52
52
  <!-- 进度条 -->
53
53
  <view
54
- v-if="showProgress && item.progress > 0 && item.progress < 100 && !item.error"
54
+ v-if="
55
+ showProgress &&
56
+ item.progress !== undefined &&
57
+ item.progress > 0 &&
58
+ item.progress < 100 &&
59
+ !item.error
60
+ "
55
61
  class="u-upload-list__progress"
56
62
  >
57
63
  <u-line-progress
@@ -129,7 +135,13 @@
129
135
  </view>
130
136
  <view class="u-upload-grid__progress">
131
137
  <u-line-progress
132
- v-if="showProgress && item.progress > 0 && item.progress !== 100 && !item.error"
138
+ v-if="
139
+ showProgress &&
140
+ item.progress !== undefined &&
141
+ item.progress > 0 &&
142
+ item.progress !== 100 &&
143
+ !item.error
144
+ "
133
145
  :show-percent="false"
134
146
  height="16"
135
147
  :percent="item.progress"
@@ -1059,8 +1071,9 @@ async function executeBeforeRemove(index: number) {
1059
1071
  */
1060
1072
  function handlerDeleteItem(index: number) {
1061
1073
  // 如果文件正在上传中,终止上传任务
1062
- if (lists.value[index].progress < 100 && lists.value[index].progress > 0) {
1063
- typeof lists.value[index].uploadTask != 'undefined' && lists.value[index].uploadTask?.abort?.();
1074
+ const item = lists.value[index];
1075
+ if (item && item.progress !== undefined && item.progress < 100 && item.progress > 0) {
1076
+ typeof item.uploadTask != 'undefined' && item.uploadTask?.abort?.();
1064
1077
  }
1065
1078
  lists.value.splice(index, 1);
1066
1079
  emit('on-remove', index, lists.value, props.index);
@@ -12,6 +12,7 @@ export interface ZIndexConfig {
12
12
  sticky: number;
13
13
  indexListSticky: number;
14
14
  tabbar: number;
15
+ dropdown: number;
15
16
  }
16
17
 
17
18
  const zIndex: ZIndexConfig = {
@@ -24,7 +25,8 @@ const zIndex: ZIndexConfig = {
24
25
  topTips: 975,
25
26
  sticky: 970,
26
27
  indexListSticky: 965,
27
- tabbar: 998
28
+ tabbar: 998,
29
+ dropdown: 985
28
30
  };
29
31
 
30
32
  export default zIndex;
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "id": "uview-pro",
3
3
  "name": "uview-pro",
4
4
  "displayName": "【支持鸿蒙】uView Pro|基于Vue3+TS的高质量UI组件库,支持多主题、暗黑模式、多语言",
5
- "version": "0.6.2",
5
+ "version": "0.6.3",
6
6
  "description": "uView Pro是基于Vue3+TS的多平台UI框架,提供80+高质量组件、便捷工具和常用模板,支持多主题、暗黑模式、多语言,支持H5/APP/鸿蒙/小程序多端开发。已在鸿蒙应用商店上架,欢迎体验!",
7
7
  "main": "index.ts",
8
8
  "module": "index.ts",