uview-pro 0.6.2 → 0.6.4
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 +34 -8
- package/components/u-dropdown/types.ts +25 -1
- package/components/u-dropdown/u-dropdown.vue +166 -71
- package/components/u-field/types.ts +2 -0
- package/components/u-field/u-field.vue +25 -6
- package/components/u-input/types.ts +5 -0
- package/components/u-input/u-input.vue +5 -2
- package/components/u-textarea/types.ts +2 -0
- package/components/u-textarea/u-textarea.vue +18 -2
- package/components/u-upload/u-upload.vue +17 -4
- package/libs/config/zIndex.ts +3 -1
- package/package.json +1 -1
package/changelog.md
CHANGED
|
@@ -1,18 +1,44 @@
|
|
|
1
|
-
## 0.6.
|
|
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))
|
|
1
|
+
## 0.6.4(2026-06-02)
|
|
7
2
|
|
|
8
3
|
### ✨ Features | 新功能
|
|
9
4
|
|
|
10
|
-
-
|
|
5
|
+
- **u-input:** 新增readonly输入属性,支持设置输入框只读状态,新增禁用与只读示例页面及配置项(#160) ([6a92373](https://github.com/anyup/uView-Pro/commit/6a92373a6c8a1c2875b93d6dbb3985df34887c4e))
|
|
6
|
+
- **u-textarea:** 新增click事件支持,在只读/非禁用状态下可触发点击回调,更新演示页面(#160) ([a79dc57](https://github.com/anyup/uView-Pro/commit/a79dc57262bfb3909d2f35bbf26589906e9a4c8d))
|
|
7
|
+
- **u-field:** 新增readonly属性支持,设置后可点击但无法输入,调整disabled和readonly状态的遮罩逻辑与样式(#160) ([708f13b](https://github.com/anyup/uView-Pro/commit/708f13bb3601c0c77a0a75f1b4d1c148f28c7229))
|
|
11
8
|
|
|
12
9
|
### 👥 Contributors
|
|
13
10
|
|
|
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>
|
|
11
|
+
<a href="https://github.com/anyup"><img src="https://github.com/anyup.png?size=40" width="40" height="40" alt="anyup" title="anyup"/></a>
|
|
15
12
|
|
|
13
|
+
## 0.6.3(2026-05-28)
|
|
14
|
+
|
|
15
|
+
### 🐛 Bug Fixes | Bug 修复
|
|
16
|
+
|
|
17
|
+
- **u-upload:** 修复进度条显示和上传终止的判断逻辑(#156) ([ad30563](https://github.com/anyup/uView-Pro/commit/ad305638b7e0977c60eda470a682ebb3ecf62c9e))
|
|
18
|
+
|
|
19
|
+
### ✨ Features | 新功能
|
|
20
|
+
|
|
21
|
+
- **u-dropdown:** 新增fixed定位选项,支持自动适配状态栏和导航栏高度,新增immersive沉浸式模式,增加offsetTop、navbarHeight、zIndex,增强灵活性 ([fc262bd](https://github.com/anyup/uView-Pro/commit/fc262bd5cc078fd3cbb825df2a9066427ccc9b69))
|
|
22
|
+
|
|
23
|
+
### 👥 Contributors
|
|
24
|
+
|
|
25
|
+
<a href="https://github.com/anyup"><img src="https://github.com/anyup.png?size=40" width="40" height="40" alt="anyup" title="anyup"/></a>
|
|
26
|
+
|
|
27
|
+
## 0.6.2(2026-05-15)
|
|
28
|
+
|
|
29
|
+
### 🐛 Bug Fixes | Bug 修复
|
|
30
|
+
|
|
31
|
+
- **u-checkbox:** 修复多选框在头条、抖音小程序图标偏移的问题 ([8ea1838](https://github.com/anyup/uView-Pro/commit/8ea18383b94b421cabea7d080a6867f4b6133ff5))
|
|
32
|
+
- **u-radio:** 修复单选框在头条、抖音小程序图标偏移的问题 ([dd7d6fe](https://github.com/anyup/uView-Pro/commit/dd7d6fee5a22bb39b3dcea9a24b9a06da40ee20e))
|
|
33
|
+
|
|
34
|
+
### ✨ Features | 新功能
|
|
35
|
+
|
|
36
|
+
- 添加 u-input 组件禁用状态样式 (#155) ([1145d99](https://github.com/anyup/uView-Pro/commit/1145d996ca111da769665ee5dca1bf07a0a1968d))
|
|
37
|
+
|
|
38
|
+
### 👥 Contributors
|
|
39
|
+
|
|
40
|
+
<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>
|
|
41
|
+
|
|
16
42
|
## 0.6.1(2026-05-13)
|
|
17
43
|
|
|
18
44
|
### ✨ 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"
|
|
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-
|
|
10
|
-
|
|
11
|
-
:
|
|
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
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
<
|
|
34
|
-
|
|
35
|
-
:
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
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
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
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,
|
|
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
|
-
|
|
120
|
-
//
|
|
121
|
-
const
|
|
122
|
-
|
|
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
|
-
|
|
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
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
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;
|
|
@@ -56,6 +56,8 @@ export const FieldProps = {
|
|
|
56
56
|
type: { type: String as PropType<InputType>, default: 'text' },
|
|
57
57
|
/** 是否不可输入(默认false) */
|
|
58
58
|
disabled: { type: Boolean, default: false },
|
|
59
|
+
/** 是否只读,禁止输入但可点击,样式不变,可触发click事件(默认false) */
|
|
60
|
+
readonly: { type: Boolean, default: false },
|
|
59
61
|
/** 最大输入长度,设置为 -1 的时候不限制最大长度(默认140) */
|
|
60
62
|
maxlength: { type: [Number, String] as PropType<string | number>, default: 140 },
|
|
61
63
|
/** 设置键盘右下角按钮的文字,仅在type="text"时生效(默认done) */
|
|
@@ -1,7 +1,14 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<view
|
|
3
3
|
class="u-field"
|
|
4
|
-
:class="[
|
|
4
|
+
:class="[
|
|
5
|
+
{
|
|
6
|
+
'u-border-top': props.borderTop,
|
|
7
|
+
'u-border-bottom': props.borderBottom,
|
|
8
|
+
'u-field--disabled': props.disabled
|
|
9
|
+
},
|
|
10
|
+
customClass
|
|
11
|
+
]"
|
|
5
12
|
:style="$u.toStyle(customStyle)"
|
|
6
13
|
>
|
|
7
14
|
<view
|
|
@@ -40,6 +47,7 @@
|
|
|
40
47
|
:placeholder="String(props.placeholder)"
|
|
41
48
|
:placeholderStyle="props.placeholderStyle"
|
|
42
49
|
:disabled="props.disabled"
|
|
50
|
+
:readonly="props.readonly"
|
|
43
51
|
:maxlength="inputMaxlength"
|
|
44
52
|
:focus="props.focus"
|
|
45
53
|
:autoHeight="props.autoHeight"
|
|
@@ -48,7 +56,6 @@
|
|
|
48
56
|
@blur="onBlur"
|
|
49
57
|
@focus="onFocus"
|
|
50
58
|
@confirm="onConfirm"
|
|
51
|
-
@tap="fieldClick"
|
|
52
59
|
/>
|
|
53
60
|
<!-- prettier-ignore -->
|
|
54
61
|
<input
|
|
@@ -61,6 +68,7 @@
|
|
|
61
68
|
:placeholder="String(props.placeholder)"
|
|
62
69
|
:placeholderStyle="props.placeholderStyle"
|
|
63
70
|
:disabled="props.disabled"
|
|
71
|
+
:readonly="props.readonly"
|
|
64
72
|
:maxlength="inputMaxlength"
|
|
65
73
|
:focus="props.focus"
|
|
66
74
|
:confirmType="props.confirmType"
|
|
@@ -68,10 +76,9 @@
|
|
|
68
76
|
@blur="onBlur"
|
|
69
77
|
@input="onInput"
|
|
70
78
|
@confirm="onConfirm"
|
|
71
|
-
@tap="fieldClick"
|
|
72
79
|
/>
|
|
73
|
-
<!--
|
|
74
|
-
<view v-if="props.
|
|
80
|
+
<!-- 透明遮罩,在disabled或readonly时显示,用于捕获点击事件(原生input设置disabled会阻止点击冒泡) -->
|
|
81
|
+
<view v-if="props.readonly" class="u-field__readonly-overlay" @tap.stop="fieldClick"></view>
|
|
75
82
|
</view>
|
|
76
83
|
<u-icon
|
|
77
84
|
v-if="props.clearable && inputValue !== '' && focused && !props.disabled"
|
|
@@ -256,6 +263,7 @@ function rightIconClick() {
|
|
|
256
263
|
}
|
|
257
264
|
|
|
258
265
|
function fieldClick() {
|
|
266
|
+
if (props.disabled) return;
|
|
259
267
|
emit('click');
|
|
260
268
|
}
|
|
261
269
|
</script>
|
|
@@ -366,7 +374,7 @@ function fieldClick() {
|
|
|
366
374
|
position: relative;
|
|
367
375
|
}
|
|
368
376
|
|
|
369
|
-
.u-
|
|
377
|
+
.u-field__readonly-overlay {
|
|
370
378
|
position: absolute;
|
|
371
379
|
top: 0;
|
|
372
380
|
left: 0;
|
|
@@ -375,4 +383,15 @@ function fieldClick() {
|
|
|
375
383
|
background-color: transparent;
|
|
376
384
|
z-index: 1;
|
|
377
385
|
}
|
|
386
|
+
|
|
387
|
+
.u-field--disabled {
|
|
388
|
+
background-color: $u-bg-gray-light;
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
.u-field--disabled .u-textarea-class,
|
|
392
|
+
.u-field--disabled .u-field__input-wrap {
|
|
393
|
+
background-color: transparent;
|
|
394
|
+
color: $u-light-color;
|
|
395
|
+
-webkit-text-fill-color: $u-light-color;
|
|
396
|
+
}
|
|
378
397
|
</style>
|
|
@@ -50,6 +50,11 @@ export const InputProps = {
|
|
|
50
50
|
type: Boolean,
|
|
51
51
|
default: false
|
|
52
52
|
},
|
|
53
|
+
/** 是否只读,禁止输入但可点击,样式不变,可触发click事件(默认false) */
|
|
54
|
+
readonly: {
|
|
55
|
+
type: Boolean,
|
|
56
|
+
default: false
|
|
57
|
+
},
|
|
53
58
|
/** 输入框的最大可输入长度(默认140) */
|
|
54
59
|
maxlength: {
|
|
55
60
|
type: [Number, String] as PropType<number | string>,
|
|
@@ -24,6 +24,7 @@
|
|
|
24
24
|
:placeholder="placeholder"
|
|
25
25
|
:placeholderStyle="getPlaceholderStyle"
|
|
26
26
|
:disabled="disabled"
|
|
27
|
+
:readonly="readonly"
|
|
27
28
|
:maxlength="inputMaxlength"
|
|
28
29
|
:fixed="fixed"
|
|
29
30
|
:focus="focus"
|
|
@@ -49,6 +50,7 @@
|
|
|
49
50
|
:placeholder="placeholder"
|
|
50
51
|
:placeholderStyle="getPlaceholderStyle"
|
|
51
52
|
:disabled="disabled || type === 'select'"
|
|
53
|
+
:readonly="readonly"
|
|
52
54
|
:maxlength="inputMaxlength"
|
|
53
55
|
:focus="focus"
|
|
54
56
|
:confirmType="confirmType"
|
|
@@ -62,7 +64,8 @@
|
|
|
62
64
|
@input="handleInput"
|
|
63
65
|
@confirm="onConfirm"
|
|
64
66
|
/>
|
|
65
|
-
|
|
67
|
+
<!-- 透明遮罩,在readonly时显示,用于捕获点击事件(原生input设置disabled会阻止点击冒泡) -->
|
|
68
|
+
<view v-if="readonly || type === 'select'" class="u-input__readonly-overlay" @tap.stop="inputClick"></view>
|
|
66
69
|
<view class="u-input__right-icon u-flex">
|
|
67
70
|
<view
|
|
68
71
|
class="u-input__right-icon__clear u-input__right-icon__item"
|
|
@@ -347,7 +350,7 @@ defineExpose({
|
|
|
347
350
|
@include vue-flex;
|
|
348
351
|
align-items: center;
|
|
349
352
|
|
|
350
|
-
&
|
|
353
|
+
&__readonly-overlay {
|
|
351
354
|
position: absolute;
|
|
352
355
|
inset: 0;
|
|
353
356
|
z-index: 1;
|
|
@@ -55,6 +55,8 @@ export const TextareaProps = {
|
|
|
55
55
|
confirmType: { type: String as PropType<string>, default: textarea.confirmType },
|
|
56
56
|
// 是否禁用
|
|
57
57
|
disabled: { type: Boolean as PropType<boolean>, default: textarea.disabled },
|
|
58
|
+
// 是否只读,禁止输入但可点击,样式不变,可触发click事件
|
|
59
|
+
readonly: { type: Boolean as PropType<boolean>, default: false },
|
|
58
60
|
// 是否显示统计字数
|
|
59
61
|
count: { type: Boolean as PropType<boolean>, default: textarea.count },
|
|
60
62
|
// 是否自动获取焦点,nvue不支持,H5取决于浏览器的实现
|
|
@@ -3,7 +3,8 @@
|
|
|
3
3
|
class="u-textarea"
|
|
4
4
|
:class="[
|
|
5
5
|
{
|
|
6
|
-
'u-textarea--error': validateState
|
|
6
|
+
'u-textarea--error': validateState,
|
|
7
|
+
'u-textarea--disabled': props.disabled
|
|
7
8
|
},
|
|
8
9
|
textareaClass,
|
|
9
10
|
customClass
|
|
@@ -19,6 +20,7 @@
|
|
|
19
20
|
:placeholder-style="getPlaceholderStyle"
|
|
20
21
|
:placeholder-class="props.placeholderClass"
|
|
21
22
|
:disabled="props.disabled"
|
|
23
|
+
:readonly="props.readonly"
|
|
22
24
|
:focus="props.focus"
|
|
23
25
|
:autoHeight="props.autoHeight"
|
|
24
26
|
:fixed="props.fixed"
|
|
@@ -51,6 +53,8 @@
|
|
|
51
53
|
{{ innerValue.length }}/{{ props.maxlength }}
|
|
52
54
|
</text>
|
|
53
55
|
|
|
56
|
+
<!-- 透明遮罩,在readonly时显示,用于捕获点击事件(原生textarea设置disabled会阻止点击冒泡) -->
|
|
57
|
+
<view v-if="props.readonly" class="u-textarea__readonly-overlay" @tap.stop="textareaClick"></view>
|
|
54
58
|
<view class="u-textarea__right-icon u-flex">
|
|
55
59
|
<view
|
|
56
60
|
class="u-textarea__right-icon__clear u-textarea__right-icon__item"
|
|
@@ -132,7 +136,8 @@ const emit = defineEmits([
|
|
|
132
136
|
'input',
|
|
133
137
|
'confirm',
|
|
134
138
|
'keyboardheightchange',
|
|
135
|
-
'change'
|
|
139
|
+
'change',
|
|
140
|
+
'click'
|
|
136
141
|
]);
|
|
137
142
|
|
|
138
143
|
const { emitToParent } = useChildren('u-textarea', 'u-form-item');
|
|
@@ -359,6 +364,11 @@ function onClear(event: any) {
|
|
|
359
364
|
valueChange();
|
|
360
365
|
}
|
|
361
366
|
|
|
367
|
+
function textareaClick() {
|
|
368
|
+
if (props.disabled) return;
|
|
369
|
+
emit('click');
|
|
370
|
+
}
|
|
371
|
+
|
|
362
372
|
defineExpose({
|
|
363
373
|
onFormItemError
|
|
364
374
|
});
|
|
@@ -374,6 +384,12 @@ defineExpose({
|
|
|
374
384
|
@include flex;
|
|
375
385
|
flex: 1;
|
|
376
386
|
|
|
387
|
+
&__readonly-overlay {
|
|
388
|
+
position: absolute;
|
|
389
|
+
inset: 0;
|
|
390
|
+
z-index: 1;
|
|
391
|
+
}
|
|
392
|
+
|
|
377
393
|
&--border {
|
|
378
394
|
border-radius: 4px;
|
|
379
395
|
border: 1px solid $u-border-color;
|
|
@@ -51,7 +51,13 @@
|
|
|
51
51
|
</text>
|
|
52
52
|
<!-- 进度条 -->
|
|
53
53
|
<view
|
|
54
|
-
v-if="
|
|
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="
|
|
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
|
-
|
|
1063
|
-
|
|
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);
|
package/libs/config/zIndex.ts
CHANGED
|
@@ -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.
|
|
5
|
+
"version": "0.6.4",
|
|
6
6
|
"description": "uView Pro是基于Vue3+TS的多平台UI框架,提供80+高质量组件、便捷工具和常用模板,支持多主题、暗黑模式、多语言,支持H5/APP/鸿蒙/小程序多端开发。已在鸿蒙应用商店上架,欢迎体验!",
|
|
7
7
|
"main": "index.ts",
|
|
8
8
|
"module": "index.ts",
|