uview-plus 3.8.127 → 3.8.129
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/README.md +13 -0
- package/changelog.md +38 -0
- package/components/u-barcode/u-barcode.vue +1 -1
- package/components/u-calendar/month.vue +71 -35
- package/components/u-calendar/u-calendar.vue +67 -31
- package/components/u-car-keyboard/u-car-keyboard.vue +21 -8
- package/components/u-cate-tab/u-cate-tab.vue +56 -11
- package/components/u-cell/u-cell.vue +20 -16
- package/components/u-collapse-item/u-collapse-item.vue +34 -11
- package/components/u-datetime-picker/u-datetime-picker.vue +16 -0
- package/components/u-dropdown/u-dropdown.vue +15 -0
- package/components/u-grid/u-grid.vue +9 -0
- package/components/u-grid-item/u-grid-item.vue +8 -0
- package/components/u-icon/util.js +16 -1
- package/components/u-list/u-list.vue +59 -8
- package/components/u-list-item/u-list-item.vue +9 -3
- package/components/u-navbar/navbar.js +2 -1
- package/components/u-navbar/props.js +6 -1
- package/components/u-navbar/u-navbar.vue +20 -3
- package/components/u-number-keyboard/u-number-keyboard.vue +18 -6
- package/components/u-parse/parser.js +4 -3
- package/components/u-picker/u-picker.vue +6 -3
- package/components/u-search/u-search.vue +15 -5
- package/components/u-select/u-select.vue +206 -31
- package/components/u-slider/u-slider.vue +21 -12
- package/components/u-tabs/u-tabs.vue +5 -1
- package/components/u-text/u-text.vue +34 -32
- package/components/u-textarea/props.js +5 -0
- package/components/u-textarea/textarea.js +4 -1
- package/components/u-textarea/u-textarea.vue +3 -1
- package/components/u-upload/u-upload.vue +15 -4
- package/components/u-upload/utils.js +4 -1
- package/components/u-video/danmaku.js +97 -0
- package/components/u-video/props.js +205 -0
- package/components/u-video/u-video.vue +1427 -0
- package/components/u-video/video-danmaku.vue +273 -0
- package/components/u-video/video-slider.vue +179 -0
- package/components/u-video/video-utils.js +98 -0
- package/components/u-video/video.js +72 -0
- package/libs/config/props.js +2 -1
- package/libs/function/test.js +2 -0
- package/libs/i18n/locales/de.js +14 -1
- package/libs/i18n/locales/en.js +14 -1
- package/libs/i18n/locales/es.js +14 -1
- package/libs/i18n/locales/fr.js +14 -1
- package/libs/i18n/locales/ja.js +14 -1
- package/libs/i18n/locales/ko.js +14 -1
- package/libs/i18n/locales/ru.js +14 -1
- package/libs/i18n/locales/th.js +14 -1
- package/libs/i18n/locales/zh-Hans.js +14 -1
- package/libs/i18n/locales/zh-Hant.js +14 -1
- package/libs/mixin/mixin.js +11 -6
- package/package.json +1 -1
- package/skills/README.md +66 -0
- package/skills/uview-plus/SKILL.md +95 -0
- package/skills/uview-plus/references/api.md +105 -0
- package/skills/uview-plus/references/components.md +156 -0
- package/skills/uview-plus/references/icons.md +223 -0
- package/skills/uview-plus/references/pitfalls.md +77 -0
- package/skills/uview-plus/references/setup.md +168 -0
- package/types/comps/form.d.ts +44 -8
- package/types/comps/list.d.ts +1 -1
- package/types/comps/listItem.d.ts +1 -1
- package/types/comps/navbar.d.ts +6 -0
- package/types/comps/numberBox.d.ts +85 -21
- package/types/comps/pagination.d.ts +96 -0
- package/types/comps/swipeActionItem.d.ts +3 -4
- package/types/comps/textarea.d.ts +9 -3
- package/types/comps.d.ts +1 -0
- package/types/index.d.ts +5 -0
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
<view :class="['u-select__content', disabled && 'disabled']">
|
|
4
4
|
<view :class="['u-select__label', border && 'u-select__label--border']" :style="selectLabelStyle" @click="labelClick">
|
|
5
5
|
<slot name="text" :currentLabel="currentLabel">
|
|
6
|
-
<text class="u-select__text" :style="{ color: resolvedTextColor }" v-if="showOptionsLabel">
|
|
6
|
+
<text class="u-select__text" :style="{ color: resolvedTextColor }" v-if="showOptionsLabel && currentLabel">
|
|
7
7
|
{{ currentLabel }}
|
|
8
8
|
</text>
|
|
9
9
|
<text class="u-select__text" :style="{ color: resolvedTextColor }" v-else>
|
|
@@ -16,17 +16,25 @@
|
|
|
16
16
|
</view>
|
|
17
17
|
<up-overlay :show="isOpen" @click="overlayClick" v-if="overlay" :zIndex="zIndex" :duration="duration + 50"
|
|
18
18
|
:customStyle="overlayStyle" :opacity="overlayOpacity" @touchmove.stop.prevent="noop"></up-overlay>
|
|
19
|
+
<view class="u-select__arrow" :class="'u-select__arrow--' + optionsPlacement" :style="arrowStyle"
|
|
20
|
+
v-if="isOpen && arrow">
|
|
21
|
+
<view class="u-select__arrow__outer"></view>
|
|
22
|
+
<view class="u-select__arrow__inner"></view>
|
|
23
|
+
</view>
|
|
19
24
|
<view class="u-select__options__wrap" :style="optionsWrapStyle">
|
|
20
25
|
<view class="u-select__options" :style="optionsStyle" v-if="isOpen">
|
|
21
26
|
<slot name="options">
|
|
22
|
-
<view class="u-select__options_item" :class="
|
|
23
|
-
:style="{ color:
|
|
27
|
+
<view class="u-select__options_item" :class="isSelected(item) ? 'active': ''"
|
|
28
|
+
:style="{ color: itemTextColor(item) }"
|
|
24
29
|
:key="index" v-for="(item, index) in options" @click="selectItem(item)">
|
|
25
|
-
<
|
|
26
|
-
<
|
|
27
|
-
{
|
|
28
|
-
|
|
29
|
-
|
|
30
|
+
<view class="u-select__options_item__body">
|
|
31
|
+
<slot name="optionItem" :item="item" :selected="isSelected(item)">
|
|
32
|
+
<text class="u-select__item_text" :style="{color: itemTextColor(item)}">
|
|
33
|
+
{{item[labelName]}}
|
|
34
|
+
</text>
|
|
35
|
+
</slot>
|
|
36
|
+
</view>
|
|
37
|
+
<up-icon v-if="isSelected(item)" name="checkbox-mark" size="15px" :color="resolvedActiveColor"></up-icon>
|
|
30
38
|
</view>
|
|
31
39
|
</slot>
|
|
32
40
|
</view>
|
|
@@ -99,8 +107,9 @@
|
|
|
99
107
|
type: Boolean,
|
|
100
108
|
default: false
|
|
101
109
|
},
|
|
110
|
+
// 当前选中值,multiple 时传数组
|
|
102
111
|
current: {
|
|
103
|
-
type: [String, Number],
|
|
112
|
+
type: [String, Number, Array],
|
|
104
113
|
default: ''
|
|
105
114
|
},
|
|
106
115
|
zIndex: {
|
|
@@ -133,19 +142,45 @@
|
|
|
133
142
|
optionsWidth: {
|
|
134
143
|
type: [String, Number],
|
|
135
144
|
default: ''
|
|
145
|
+
},
|
|
146
|
+
// 下拉面板展开方向:auto 按上下剩余空间自动选择,bottom 固定向下,top 固定向上
|
|
147
|
+
placement: {
|
|
148
|
+
type: String,
|
|
149
|
+
default: 'auto'
|
|
150
|
+
},
|
|
151
|
+
// 是否显示下拉面板指向触发区的三角形指示器
|
|
152
|
+
arrow: {
|
|
153
|
+
type: Boolean,
|
|
154
|
+
default: true
|
|
155
|
+
},
|
|
156
|
+
// 是否多选,多选时 current 为数组且选中后面板不关闭
|
|
157
|
+
multiple: {
|
|
158
|
+
type: Boolean,
|
|
159
|
+
default: false
|
|
160
|
+
},
|
|
161
|
+
// 选中项的文字与勾选图标颜色,默认取主题主色
|
|
162
|
+
activeColor: {
|
|
163
|
+
type: String,
|
|
164
|
+
default: ''
|
|
136
165
|
}
|
|
137
166
|
},
|
|
138
167
|
data() {
|
|
139
168
|
return {
|
|
140
169
|
isOpen: false,
|
|
141
170
|
optionsWrapLeft: 'auto',
|
|
142
|
-
optionsWrapRight: 'auto'
|
|
171
|
+
optionsWrapRight: 'auto',
|
|
172
|
+
// 展开方向与空间不足时的限高,都在打开时按剩余空间重新计算
|
|
173
|
+
optionsPlacement: 'bottom',
|
|
174
|
+
optionsWrapMaxHeight: ''
|
|
143
175
|
}
|
|
144
176
|
},
|
|
145
177
|
computed: {
|
|
146
178
|
resolvedItemColor() {
|
|
147
179
|
return this.itemColor || this.upThemeVar('--up-main-color', '#303133');
|
|
148
180
|
},
|
|
181
|
+
resolvedActiveColor() {
|
|
182
|
+
return this.activeColor || this.upThemeVar('--up-primary', '#3c9cff');
|
|
183
|
+
},
|
|
149
184
|
resolvedTextColor() {
|
|
150
185
|
return this.upThemeVar('--up-main-color', '#303133');
|
|
151
186
|
},
|
|
@@ -174,14 +209,25 @@
|
|
|
174
209
|
}
|
|
175
210
|
return style;
|
|
176
211
|
},
|
|
212
|
+
panelGap() {
|
|
213
|
+
// 显示指示器时把间距留成三角形的高度,让它正好顶住面板边框
|
|
214
|
+
return this.arrow ? 6 : 4;
|
|
215
|
+
},
|
|
177
216
|
optionsWrapStyle() {
|
|
178
217
|
const style = {
|
|
179
218
|
overflowY: 'auto',
|
|
180
219
|
zIndex: this.zIndex + 1,
|
|
181
220
|
left: this.optionsWrapLeft,
|
|
182
221
|
right: this.optionsWrapRight,
|
|
183
|
-
maxHeight: this.maxHeight
|
|
222
|
+
maxHeight: this.optionsWrapMaxHeight || this.maxHeight
|
|
184
223
|
};
|
|
224
|
+
if (this.optionsPlacement === 'top') {
|
|
225
|
+
style.top = 'auto';
|
|
226
|
+
style.bottom = `calc(100% + ${this.panelGap}px)`;
|
|
227
|
+
} else {
|
|
228
|
+
style.top = `calc(100% + ${this.panelGap}px)`;
|
|
229
|
+
style.bottom = 'auto';
|
|
230
|
+
}
|
|
185
231
|
if (this.normalizedOptionsWidth) {
|
|
186
232
|
style.width = this.normalizedOptionsWidth;
|
|
187
233
|
}
|
|
@@ -195,15 +241,36 @@
|
|
|
195
241
|
}
|
|
196
242
|
return style;
|
|
197
243
|
},
|
|
244
|
+
arrowStyle() {
|
|
245
|
+
// 指示器画在滚动容器外面,否则会被面板自身的 overflow 裁掉
|
|
246
|
+
const style = {
|
|
247
|
+
zIndex: this.zIndex + 2,
|
|
248
|
+
left: this.optionsWrapLeft === 'auto' ? 'auto' : '12px',
|
|
249
|
+
right: this.optionsWrapLeft === 'auto' ? '12px' : 'auto'
|
|
250
|
+
};
|
|
251
|
+
if (this.optionsPlacement === 'top') {
|
|
252
|
+
style.top = 'auto';
|
|
253
|
+
style.bottom = '100%';
|
|
254
|
+
} else {
|
|
255
|
+
style.top = '100%';
|
|
256
|
+
style.bottom = 'auto';
|
|
257
|
+
}
|
|
258
|
+
return style;
|
|
259
|
+
},
|
|
260
|
+
currentList() {
|
|
261
|
+
if (Array.isArray(this.current)) return this.current;
|
|
262
|
+
if (this.current === '' || this.current === null || typeof this.current === 'undefined') return [];
|
|
263
|
+
return [this.current];
|
|
264
|
+
},
|
|
198
265
|
currentLabel() {
|
|
199
|
-
|
|
266
|
+
const names = [];
|
|
200
267
|
this.options.forEach((ele) => {
|
|
201
|
-
if (
|
|
202
|
-
|
|
203
|
-
}
|
|
204
|
-
});
|
|
205
|
-
return
|
|
206
|
-
}
|
|
268
|
+
if (this.isSelected(ele)) {
|
|
269
|
+
names.push(ele[this.labelName]);
|
|
270
|
+
}
|
|
271
|
+
});
|
|
272
|
+
return names.join('、');
|
|
273
|
+
}
|
|
207
274
|
},
|
|
208
275
|
methods: {
|
|
209
276
|
labelClick() {
|
|
@@ -230,24 +297,76 @@
|
|
|
230
297
|
if (!this.closeOnClickOverlay) return;
|
|
231
298
|
this.closeSelect();
|
|
232
299
|
},
|
|
300
|
+
isSelected(item) {
|
|
301
|
+
const value = item[this.keyName];
|
|
302
|
+
if (this.multiple) {
|
|
303
|
+
return this.currentList.some((ele) => ele == value);
|
|
304
|
+
}
|
|
305
|
+
// 没有选中值时不能走宽松比较,否则 0 == '' 会把 key 为 0 的项误标成选中
|
|
306
|
+
if (this.current === '' || this.current === null || typeof this.current === 'undefined') {
|
|
307
|
+
return false;
|
|
308
|
+
}
|
|
309
|
+
return this.current == value;
|
|
310
|
+
},
|
|
311
|
+
itemTextColor(item) {
|
|
312
|
+
// 选项颜色是行内绑定的,选中态必须走同一个绑定,否则会被行内样式盖掉
|
|
313
|
+
return this.isSelected(item) ? this.resolvedActiveColor : this.resolvedItemColor;
|
|
314
|
+
},
|
|
233
315
|
selectItem(item) {
|
|
316
|
+
const value = item[this.keyName];
|
|
317
|
+
if (this.multiple) {
|
|
318
|
+
// 多选时保持面板展开,方便连续勾选
|
|
319
|
+
const list = this.currentList.slice();
|
|
320
|
+
const index = list.findIndex((ele) => ele == value);
|
|
321
|
+
if (index > -1) {
|
|
322
|
+
list.splice(index, 1);
|
|
323
|
+
} else {
|
|
324
|
+
list.push(value);
|
|
325
|
+
}
|
|
326
|
+
this.$emit('update:current', list);
|
|
327
|
+
this.$emit('select', item, list);
|
|
328
|
+
return;
|
|
329
|
+
}
|
|
234
330
|
this.isOpen = false;
|
|
235
|
-
this.$emit('update:current',
|
|
331
|
+
this.$emit('update:current', value);
|
|
236
332
|
this.$emit('select', item);
|
|
237
333
|
},
|
|
238
334
|
adjustOptionsWrapPosition() {
|
|
335
|
+
// 每次打开都从"左对齐、向下、不限高"重新算,避免上一次的结果影响这次的测量
|
|
239
336
|
this.optionsWrapLeft = '0px';
|
|
240
337
|
this.optionsWrapRight = 'auto';
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
this.$
|
|
244
|
-
if (
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
338
|
+
this.optionsWrapMaxHeight = '';
|
|
339
|
+
this.optionsPlacement = this.placement === 'top' ? 'top' : 'bottom';
|
|
340
|
+
this.$nextTick(() => {
|
|
341
|
+
if (!this.isOpen) return;
|
|
342
|
+
let wi = getWindowInfo();
|
|
343
|
+
let windowWidth = wi.windowWidth;
|
|
344
|
+
let windowHeight = wi.windowHeight;
|
|
345
|
+
Promise.all([
|
|
346
|
+
this.$uGetRect('.u-select__label'),
|
|
347
|
+
this.$uGetRect('.u-select__options__wrap')
|
|
348
|
+
]).then(([labelRect, wrapRect]) => {
|
|
349
|
+
if (!this.isOpen || !labelRect || !wrapRect) return;
|
|
350
|
+
if (wrapRect.left + wrapRect.width > windowWidth) {
|
|
351
|
+
// 如果右侧被遮挡,则调整到左侧
|
|
352
|
+
this.optionsWrapLeft = 'auto';
|
|
353
|
+
this.optionsWrapRight = `0px`;
|
|
354
|
+
}
|
|
355
|
+
// boundingClientRect 的坐标以窗口可用区域为原点,直接和 windowHeight 比即可
|
|
356
|
+
const spaceBelow = windowHeight - labelRect.bottom - this.panelGap;
|
|
357
|
+
const spaceAbove = labelRect.top - this.panelGap;
|
|
358
|
+
if (this.placement === 'auto' && wrapRect.height > spaceBelow && spaceAbove > spaceBelow) {
|
|
359
|
+
// 下方放不下且上方更宽裕时翻到触发区上方
|
|
360
|
+
this.optionsPlacement = 'top';
|
|
361
|
+
}
|
|
362
|
+
// 选定方向后仍放不下就限高滚动,否则面板会溢出窗口,并把页面撑高
|
|
363
|
+
const space = this.optionsPlacement === 'top' ? spaceAbove : spaceBelow;
|
|
364
|
+
if (space > 0 && wrapRect.height > space) {
|
|
365
|
+
this.optionsWrapMaxHeight = `${Math.floor(space)}px`;
|
|
366
|
+
}
|
|
367
|
+
});
|
|
368
|
+
});
|
|
369
|
+
}
|
|
251
370
|
}
|
|
252
371
|
}
|
|
253
372
|
</script>
|
|
@@ -287,10 +406,56 @@
|
|
|
287
406
|
pointer-events: none;
|
|
288
407
|
}
|
|
289
408
|
|
|
409
|
+
.u-select__arrow {
|
|
410
|
+
position: absolute;
|
|
411
|
+
width: 0;
|
|
412
|
+
height: 0;
|
|
413
|
+
pointer-events: none;
|
|
414
|
+
|
|
415
|
+
.u-select__arrow__outer,
|
|
416
|
+
.u-select__arrow__inner {
|
|
417
|
+
position: absolute;
|
|
418
|
+
left: 0;
|
|
419
|
+
/* 三角形以锚点为中心,左右对齐时都不会贴到面板边角 */
|
|
420
|
+
margin-left: -6px;
|
|
421
|
+
width: 0;
|
|
422
|
+
height: 0;
|
|
423
|
+
border-style: solid;
|
|
424
|
+
border-color: transparent;
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
&--bottom {
|
|
428
|
+
.u-select__arrow__outer {
|
|
429
|
+
top: 0;
|
|
430
|
+
border-width: 0 6px 6px 6px;
|
|
431
|
+
border-bottom-color: var(--up-border-color, #f1f1f1);
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
.u-select__arrow__inner {
|
|
435
|
+
// 往面板里挪 1px,盖掉面板自身的边框,拼出缺口效果
|
|
436
|
+
top: 1px;
|
|
437
|
+
border-width: 0 6px 6px 6px;
|
|
438
|
+
border-bottom-color: var(--up-card-bg-color, #fff);
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
&--top {
|
|
443
|
+
.u-select__arrow__outer {
|
|
444
|
+
bottom: 0;
|
|
445
|
+
border-width: 6px 6px 0 6px;
|
|
446
|
+
border-top-color: var(--up-border-color, #f1f1f1);
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
.u-select__arrow__inner {
|
|
450
|
+
bottom: 1px;
|
|
451
|
+
border-width: 6px 6px 0 6px;
|
|
452
|
+
border-top-color: var(--up-card-bg-color, #fff);
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
}
|
|
456
|
+
|
|
290
457
|
.u-select__options__wrap {
|
|
291
|
-
margin-bottom: 46px;
|
|
292
458
|
position: absolute;
|
|
293
|
-
top: calc(100% + 4px);
|
|
294
459
|
left: 0;
|
|
295
460
|
}
|
|
296
461
|
|
|
@@ -303,6 +468,8 @@
|
|
|
303
468
|
|
|
304
469
|
.u-select__options_item {
|
|
305
470
|
padding: 10px 12px;
|
|
471
|
+
display: flex;
|
|
472
|
+
align-items: center;
|
|
306
473
|
box-sizing: border-box;
|
|
307
474
|
width: 100%;
|
|
308
475
|
height: 100%;
|
|
@@ -310,6 +477,14 @@
|
|
|
310
477
|
&:hover {
|
|
311
478
|
background-color: var(--up-bg-color, #f7f7f7);
|
|
312
479
|
}
|
|
480
|
+
|
|
481
|
+
&.active {
|
|
482
|
+
background-color: var(--up-primary-light, #ecf5ff);
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
.u-select__options_item__body {
|
|
486
|
+
flex: 1;
|
|
487
|
+
}
|
|
313
488
|
|
|
314
489
|
/* #ifdef H5 */
|
|
315
490
|
&:hover {
|
|
@@ -21,7 +21,6 @@
|
|
|
21
21
|
>
|
|
22
22
|
</view>
|
|
23
23
|
<view
|
|
24
|
-
@click="onClick"
|
|
25
24
|
class="u-slider__gap"
|
|
26
25
|
:style="[
|
|
27
26
|
barStyle,
|
|
@@ -52,7 +51,7 @@
|
|
|
52
51
|
<template v-if="isRange">
|
|
53
52
|
<view class="u-slider__button-wrap u-slider__button-wrap-0" @touchstart="onTouchStart($event, 0)"
|
|
54
53
|
@touchmove="onTouchMove($event, 0)" @touchend="onTouchEnd($event, 0)"
|
|
55
|
-
@touchcancel="onTouchEnd($event, 0)" :style="touchButtonStyle(barStyle0)">
|
|
54
|
+
@touchcancel="onTouchEnd($event, 0)" @click.stop="() => {}" :style="touchButtonStyle(barStyle0)">
|
|
56
55
|
<slot name="min" v-if="$slots.min || $slots.$min"/>
|
|
57
56
|
<view v-else class="u-slider__button" :style="[blockStyle, {
|
|
58
57
|
height: getPx(blockSize, true),
|
|
@@ -63,7 +62,7 @@
|
|
|
63
62
|
</template>
|
|
64
63
|
<view class="u-slider__button-wrap" @touchstart="onTouchStart"
|
|
65
64
|
@touchmove="onTouchMove" @touchend="onTouchEnd"
|
|
66
|
-
@touchcancel="onTouchEnd" :style="touchButtonStyle(barStyle)">
|
|
65
|
+
@touchcancel="onTouchEnd" @click.stop="() => {}" :style="touchButtonStyle(barStyle)">
|
|
67
66
|
<slot name="max" v-if="isRange && ($slots.max || $slots.$max)"/>
|
|
68
67
|
<slot v-else-if="$slots.default || $slots.$default"/>
|
|
69
68
|
<view v-else class="u-slider__button" :style="[blockStyle, {
|
|
@@ -153,8 +152,7 @@
|
|
|
153
152
|
modelValue(n) {
|
|
154
153
|
// 只有在非滑动状态时,才可以通过value更新滑块值,这里监听,是为了让用户触发
|
|
155
154
|
if (this.status == 'end') {
|
|
156
|
-
|
|
157
|
-
this.$emit('change', $crtFmtValue);
|
|
155
|
+
this.updateValue(this.modelValue, false);
|
|
158
156
|
}
|
|
159
157
|
},
|
|
160
158
|
// #endif
|
|
@@ -162,8 +160,7 @@
|
|
|
162
160
|
value(n) {
|
|
163
161
|
// 只有在非滑动状态时,才可以通过value更新滑块值,这里监听,是为了让用户触发
|
|
164
162
|
if (this.status == 'end') {
|
|
165
|
-
|
|
166
|
-
this.$emit('change', $crtFmtValue);
|
|
163
|
+
this.updateValue(this.value, false);
|
|
167
164
|
}
|
|
168
165
|
},
|
|
169
166
|
// #endif
|
|
@@ -172,7 +169,6 @@
|
|
|
172
169
|
if (this.status == 'end') {
|
|
173
170
|
this.updateValue(this.rangeValue[0], false, 0);
|
|
174
171
|
this.updateValue(this.rangeValue[1], false, 1);
|
|
175
|
-
this.$emit('change', this.rangeValue);
|
|
176
172
|
}
|
|
177
173
|
},
|
|
178
174
|
deep:true
|
|
@@ -414,16 +410,24 @@
|
|
|
414
410
|
// nvue下暂时无法获取坐标
|
|
415
411
|
const min = this.toSliderNumber(this.min)
|
|
416
412
|
const max = this.toSliderNumber(this.max, 100)
|
|
413
|
+
const detail = event && event.detail ? event.detail : {}
|
|
414
|
+
const position = Number(this.vertical ? detail.y : detail.x)
|
|
415
|
+
const sliderSize = this.vertical ? this.sliderRect.height : this.sliderRect.width
|
|
416
|
+
// 少数端的tap没有坐标,滑块在弹窗里未显示时也量不到长度,
|
|
417
|
+
// 这两种情况下算出来的只会是min,别当成用户点了min发出去
|
|
418
|
+
if (!Number.isFinite(position) || !sliderSize) return
|
|
417
419
|
if (this.vertical) {
|
|
418
|
-
let clientY =
|
|
420
|
+
let clientY = position - this.sliderRect.top
|
|
419
421
|
// console.log(this.sliderRect.top, event.detail.y)
|
|
420
422
|
this.newValue = ((clientY / this.sliderRect.height) * (max - min)) + min
|
|
421
|
-
this.updateValue(this.newValue, false, 1)
|
|
422
423
|
} else {
|
|
423
|
-
let clientX =
|
|
424
|
+
let clientX = position - this.sliderRect.left
|
|
424
425
|
this.newValue = ((clientX / this.sliderRect.width) * (max - min)) + min
|
|
425
|
-
this.updateValue(this.newValue, false, 1)
|
|
426
426
|
}
|
|
427
|
+
// 点击等同于一次完整的取值,需要和拖动结束一样对外发出change,
|
|
428
|
+
// 否则单向绑定(:modelValue)时外部拿不到点击后的值
|
|
429
|
+
const $crtFmtValue = this.updateValue(this.newValue, false, 1)
|
|
430
|
+
this.$emit('change', $crtFmtValue)
|
|
427
431
|
// #endif
|
|
428
432
|
},
|
|
429
433
|
updateValue(value, drag, index = 1) {
|
|
@@ -572,6 +576,11 @@
|
|
|
572
576
|
flex-direction: column;
|
|
573
577
|
position: relative;
|
|
574
578
|
border-radius: 999px;
|
|
579
|
+
/* #ifndef APP-NVUE */
|
|
580
|
+
// 高度按 blockSize 内联下发,须以内容盒为基准;否则应用层的
|
|
581
|
+
// view { box-sizing: border-box } 会把上下 padding 从内容高度中扣掉,滑块与滑道错位
|
|
582
|
+
box-sizing: content-box;
|
|
583
|
+
/* #endif */
|
|
575
584
|
padding: 10px 18px;
|
|
576
585
|
justify-content: center;
|
|
577
586
|
}
|
|
@@ -405,7 +405,11 @@
|
|
|
405
405
|
}
|
|
406
406
|
|
|
407
407
|
&__scroll-view {
|
|
408
|
-
|
|
408
|
+
// 这里不能声明 display: flex:各端 scroll-view 都把内容包在内层容器里,flex 作用不到内容上,
|
|
409
|
+
// 反而会让微信小程序告警「设置 enable-flex 属性以使 flexbox 布局生效」(issue #650)
|
|
410
|
+
/* #ifdef APP-NVUE */
|
|
411
|
+
flex-direction: row;
|
|
412
|
+
/* #endif */
|
|
409
413
|
flex: 1;
|
|
410
414
|
}
|
|
411
415
|
|
|
@@ -44,6 +44,7 @@
|
|
|
44
44
|
:send-message-img="sendMessageImg"
|
|
45
45
|
:show-message-card="showMessageCard"
|
|
46
46
|
:app-parameter="appParameter"
|
|
47
|
+
v-bind="$attrs"
|
|
47
48
|
>
|
|
48
49
|
{{ value }}
|
|
49
50
|
</button>
|
|
@@ -73,22 +74,22 @@ import value from './value.js'
|
|
|
73
74
|
import { mpMixin } from '../../libs/mixin/mpMixin';
|
|
74
75
|
import { mixin } from '../../libs/mixin/mixin';
|
|
75
76
|
import { buttonMixin } from '../../libs/mixin/button';
|
|
76
|
-
import { openType } from '../../libs/mixin/openType';
|
|
77
|
-
import { addStyle, addUnit, deepMerge } from '../../libs/function/index';
|
|
78
|
-
|
|
79
|
-
function normalizeLineHeight(value) {
|
|
80
|
-
const valueString = String(value).trim()
|
|
81
|
-
const numericValue = Number(valueString)
|
|
82
|
-
const isUnitless =
|
|
83
|
-
/^[+-]?(?:\d+\.?\d*|\.\d+)$/.test(valueString) &&
|
|
84
|
-
numericValue > 0 &&
|
|
85
|
-
numericValue < 10
|
|
86
|
-
|
|
87
|
-
return isUnitless ? valueString : addUnit(value)
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
/**
|
|
91
|
-
* Text 文本
|
|
77
|
+
import { openType } from '../../libs/mixin/openType';
|
|
78
|
+
import { addStyle, addUnit, deepMerge } from '../../libs/function/index';
|
|
79
|
+
|
|
80
|
+
function normalizeLineHeight(value) {
|
|
81
|
+
const valueString = String(value).trim()
|
|
82
|
+
const numericValue = Number(valueString)
|
|
83
|
+
const isUnitless =
|
|
84
|
+
/^[+-]?(?:\d+\.?\d*|\.\d+)$/.test(valueString) &&
|
|
85
|
+
numericValue > 0 &&
|
|
86
|
+
numericValue < 10
|
|
87
|
+
|
|
88
|
+
return isUnitless ? valueString : addUnit(value)
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Text 文本
|
|
92
93
|
* @description 此组件集成了文本类在项目中的常用功能,包括状态,拨打电话,格式化日期,*替换,超链接...等功能。 您大可不必在使用特殊文本时自己定义,text组件几乎涵盖您能使用的大部分场景。
|
|
93
94
|
* @tutorial https://uview-plus.jiangruyi.com/components/loading.html
|
|
94
95
|
* @property {String} type 主题颜色
|
|
@@ -109,7 +110,7 @@ function normalizeLineHeight(value) {
|
|
|
109
110
|
* @property {Object | String} iconStyle 图标的样式 (默认 {fontSize: '15px'} )
|
|
110
111
|
* @property {String} decoration 文字装饰,下划线,中划线等,可选值 none|underline|line-through(默认 'none' )
|
|
111
112
|
* @property {Object | String | Number} margin 外边距,对象、字符串,数值形式均可(默认 0 )
|
|
112
|
-
* @property {String | Number} lineHeight 文本行高,支持带单位值或无单位倍数(如 1.2)
|
|
113
|
+
* @property {String | Number} lineHeight 文本行高,支持带单位值或无单位倍数(如 1.2)
|
|
113
114
|
* @property {String} align 文本对齐方式,可选值left|center|right(默认 'left' )
|
|
114
115
|
* @property {String} wordWrap 文字换行,可选值break-word|normal|anywhere(默认 'normal' )
|
|
115
116
|
* @event {Function} click 点击触发事件
|
|
@@ -123,6 +124,7 @@ export default {
|
|
|
123
124
|
// #ifndef MP
|
|
124
125
|
mixins: [mpMixin, mixin, value, props],
|
|
125
126
|
// #endif
|
|
127
|
+
inheritAttrs: false,
|
|
126
128
|
emits: ['click'],
|
|
127
129
|
computed: {
|
|
128
130
|
wrapStyle() {
|
|
@@ -139,21 +141,21 @@ export default {
|
|
|
139
141
|
}
|
|
140
142
|
return style;
|
|
141
143
|
},
|
|
142
|
-
valueStyle() {
|
|
143
|
-
const style = {
|
|
144
|
-
textDecoration: this.decoration,
|
|
145
|
-
fontWeight: this.bold ? 'bold' : 'normal',
|
|
146
|
-
wordWrap: this.wordWrap,
|
|
147
|
-
fontSize: addUnit(this.size)
|
|
148
|
-
}
|
|
149
|
-
if (!this.type) {
|
|
150
|
-
style.color = this.color || this.upThemeVar('--up-content-color', this.$u?.color?.contentColor || '#606266')
|
|
151
|
-
}
|
|
152
|
-
this.isNvue && this.lines && (style.lines = this.lines)
|
|
153
|
-
this.lineHeight &&
|
|
154
|
-
(style.lineHeight = normalizeLineHeight(this.lineHeight))
|
|
155
|
-
!this.isNvue && this.block && (style.display = 'block')
|
|
156
|
-
return deepMerge(style, addStyle(this.customStyle))
|
|
144
|
+
valueStyle() {
|
|
145
|
+
const style = {
|
|
146
|
+
textDecoration: this.decoration,
|
|
147
|
+
fontWeight: this.bold ? 'bold' : 'normal',
|
|
148
|
+
wordWrap: this.wordWrap,
|
|
149
|
+
fontSize: addUnit(this.size)
|
|
150
|
+
}
|
|
151
|
+
if (!this.type) {
|
|
152
|
+
style.color = this.color || this.upThemeVar('--up-content-color', this.$u?.color?.contentColor || '#606266')
|
|
153
|
+
}
|
|
154
|
+
this.isNvue && this.lines && (style.lines = this.lines)
|
|
155
|
+
this.lineHeight &&
|
|
156
|
+
(style.lineHeight = normalizeLineHeight(this.lineHeight))
|
|
157
|
+
!this.isNvue && this.block && (style.display = 'block')
|
|
158
|
+
return deepMerge(style, addStyle(this.customStyle))
|
|
157
159
|
},
|
|
158
160
|
isNvue() {
|
|
159
161
|
let nvue = false
|
|
@@ -40,6 +40,11 @@ export const props = defineMixin({
|
|
|
40
40
|
type: String,
|
|
41
41
|
default: () => defProps.textarea.confirmType
|
|
42
42
|
},
|
|
43
|
+
// 点击键盘右下角按钮时是否保持键盘不收起,confirmType 非 return 时有效
|
|
44
|
+
confirmHold: {
|
|
45
|
+
type: Boolean,
|
|
46
|
+
default: () => defProps.textarea.confirmHold
|
|
47
|
+
},
|
|
43
48
|
// 是否禁用
|
|
44
49
|
disabled: {
|
|
45
50
|
type: Boolean,
|
|
@@ -15,7 +15,10 @@ export default {
|
|
|
15
15
|
placeholderClass: 'textarea-placeholder',
|
|
16
16
|
placeholderStyle: '',
|
|
17
17
|
height: 70,
|
|
18
|
-
|
|
18
|
+
// 与 uni-app textarea 原生默认值保持一致:return 表示回车换行;
|
|
19
|
+
// 取 done/go/next/search/send 时回车会触发 confirm 且不换行
|
|
20
|
+
confirmType: 'return',
|
|
21
|
+
confirmHold: false,
|
|
19
22
|
disabled: false,
|
|
20
23
|
count: false,
|
|
21
24
|
focus: false,
|
|
@@ -21,6 +21,7 @@
|
|
|
21
21
|
:holdKeyboard="holdKeyboard"
|
|
22
22
|
:maxlength="maxlength"
|
|
23
23
|
:confirm-type="confirmType"
|
|
24
|
+
:confirm-hold="confirmHold"
|
|
24
25
|
:ignoreCompositionEvent="ignoreCompositionEvent"
|
|
25
26
|
@focus="onFocus"
|
|
26
27
|
@blur="onBlur"
|
|
@@ -55,7 +56,8 @@ import { addStyle, addUnit, deepMerge, formValidate, os } from '../../libs/funct
|
|
|
55
56
|
* @property {String} placeholderClass 指定placeholder的样式类,注意页面或组件的style中写了scoped时,需要在类名前写/deep/ ( 默认 'input-placeholder' )
|
|
56
57
|
* @property {String | Object} placeholderStyle 指定placeholder的样式,字符串/对象形式,如"color: red;"
|
|
57
58
|
* @property {String | Number} height 输入框高度(默认 70 )
|
|
58
|
-
* @property {String} confirmType 设置键盘右下角按钮的文字,仅微信小程序,App-vue和H5
|
|
59
|
+
* @property {String} confirmType 设置键盘右下角按钮的文字,仅微信小程序,App-vue和H5有效。为 'return' 时回车换行,取 'done'、'go'、'next'、'search'、'send' 时回车触发 confirm 且不换行(默认 'return' )
|
|
60
|
+
* @property {Boolean} confirmHold 点击键盘右下角按钮时是否保持键盘不收起,confirmType 非 'return' 时有效(默认 false )
|
|
59
61
|
* @property {Boolean} disabled 是否禁用(默认 false )
|
|
60
62
|
* @property {Boolean} count 是否显示统计字数(默认 false )
|
|
61
63
|
* @property {Boolean} focus 是否自动获取焦点,nvue不支持,H5取决于浏览器的实现(默认 false )
|
|
@@ -441,6 +441,19 @@
|
|
|
441
441
|
index: index == null ? this.fileList.length : index,
|
|
442
442
|
};
|
|
443
443
|
},
|
|
444
|
+
// 组装uni.uploadFile的文件参数。
|
|
445
|
+
// H5下选择结果里带的是真实File对象,直接交给uni.uploadFile;否则它只能拿blob:
|
|
446
|
+
// 地址再读回二进制,而部分webview(如微信内置浏览器)读blob:会拿到空内容,
|
|
447
|
+
// 上传就会失败(uploadFile:fail file error)。#801
|
|
448
|
+
uploadFileParams(item, name = 'file') {
|
|
449
|
+
// #ifdef H5
|
|
450
|
+
const raw = item.file || item.tempFile
|
|
451
|
+
if (typeof Blob !== 'undefined' && raw instanceof Blob) {
|
|
452
|
+
return { name, files: [{ name, file: raw }] }
|
|
453
|
+
}
|
|
454
|
+
// #endif
|
|
455
|
+
return { name, filePath: item.url }
|
|
456
|
+
},
|
|
444
457
|
async onAfterRead(file) {
|
|
445
458
|
const {
|
|
446
459
|
maxSize,
|
|
@@ -511,8 +524,7 @@
|
|
|
511
524
|
}
|
|
512
525
|
var uploadTask = uni.uploadFile({
|
|
513
526
|
url: res0.data.params.host,
|
|
514
|
-
|
|
515
|
-
name: 'file',
|
|
527
|
+
...this.uploadFileParams(lists[j]),
|
|
516
528
|
// fileType: 'video', // 仅支付宝小程序,且必填。
|
|
517
529
|
// header: header,
|
|
518
530
|
formData: formData,
|
|
@@ -556,8 +568,7 @@
|
|
|
556
568
|
// 服务器本机上传
|
|
557
569
|
var uploadTask = uni.uploadFile({
|
|
558
570
|
url: this.autoUploadApi,
|
|
559
|
-
|
|
560
|
-
name: 'file',
|
|
571
|
+
...this.uploadFileParams(lists[j]),
|
|
561
572
|
// fileType: 'video', // 仅支付宝小程序,且必填。
|
|
562
573
|
header: this.autoUploadHeader,
|
|
563
574
|
success: (uploadFileRes) => {
|
|
@@ -42,7 +42,10 @@ function formatVideo(res) {
|
|
|
42
42
|
height: res.height || 0, // APP 2.1.0+、H5、微信小程序、京东小程序
|
|
43
43
|
// #ifdef H5
|
|
44
44
|
name: res.name,
|
|
45
|
-
|
|
45
|
+
// chooseVideo 在H5已经返回了真实的File对象(res.tempFile),必须把它透出来,
|
|
46
|
+
// 和formatImage/formatMedia/formatFile保持一致。否则调用方只剩blob:地址可用,
|
|
47
|
+
// 而部分webview(如微信内置浏览器)读blob:会拿到空内容,视频就传不上去。#801
|
|
48
|
+
file: res.tempFile || res
|
|
46
49
|
// #endif
|
|
47
50
|
// #ifndef H5
|
|
48
51
|
name: res.tempFilePath.split('/').pop() + '.mp4',
|