rrj-astra-ui 1.0.2
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.en.md +36 -0
- package/README.md +37 -0
- package/components/AuiBadge.vue +50 -0
- package/components/AuiBlockBox.vue +85 -0
- package/components/AuiButton.vue +210 -0
- package/components/AuiCustomerForm.vue +304 -0
- package/components/AuiDivider.vue +66 -0
- package/components/AuiFold.vue +40 -0
- package/components/AuiFoldItem.vue +173 -0
- package/components/AuiForm.vue +76 -0
- package/components/AuiFormItem.vue +88 -0
- package/components/AuiGrid.vue +26 -0
- package/components/AuiGridItem.vue +20 -0
- package/components/AuiIcon.vue +145 -0
- package/components/AuiImage.vue +152 -0
- package/components/AuiInput.vue +176 -0
- package/components/AuiLamp.vue +254 -0
- package/components/AuiLineProgress.vue +169 -0
- package/components/AuiList.vue +18 -0
- package/components/AuiListItem.vue +142 -0
- package/components/AuiMultiSelect.vue +303 -0
- package/components/AuiNoticeBar.vue +62 -0
- package/components/AuiNumberBox.vue +282 -0
- package/components/AuiPicker.vue +619 -0
- package/components/AuiPopup.vue +57 -0
- package/components/AuiSelectGroup.vue +312 -0
- package/components/AuiTab.vue +173 -0
- package/components/AuiTabItem.vue +43 -0
- package/components/AuiTable.vue +357 -0
- package/components/AuiTag.vue +112 -0
- package/components/AuiText.vue +81 -0
- package/components/AuiTextarea.vue +203 -0
- package/components/AuiToast.vue +96 -0
- package/components/AuiUpdate.vue +271 -0
- package/components/AuiUpload.vue +524 -0
- package/index.js +93 -0
- package/package.json +36 -0
- package/style.scss +30 -0
|
@@ -0,0 +1,619 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="aui-picker" :class="{'aui-picker--disabled': disabled}">
|
|
3
|
+
<div class="aui-picker__header" @click="togglePicker">
|
|
4
|
+
<span class="aui-picker__title">{{ title || '请选择' }}</span>
|
|
5
|
+
<span
|
|
6
|
+
class="aui-picker__value"
|
|
7
|
+
:class="{ 'aui-picker__value--selected': hasSelectedValue }"
|
|
8
|
+
>
|
|
9
|
+
{{ displayValue || (title || '请选择') }}
|
|
10
|
+
</span>
|
|
11
|
+
<i class="aui-picker__icon" :class="{'aui-picker__icon--up': isOpen}"></i>
|
|
12
|
+
</div>
|
|
13
|
+
<transition name="aui-picker-transition">
|
|
14
|
+
<div class="aui-picker__content" v-show="isOpen">
|
|
15
|
+
<div class="aui-picker__mask" @click="closePicker"></div>
|
|
16
|
+
<div class="aui-picker__panel">
|
|
17
|
+
<div class="aui-picker__toolbar">
|
|
18
|
+
<view class="aui-picker__cancel" @click="closePicker">取消</view>
|
|
19
|
+
<view class="aui-picker__confirm" @click="confirmSelection">确定</view>
|
|
20
|
+
</div>
|
|
21
|
+
<div class="aui-picker__columns">
|
|
22
|
+
<div class="aui-picker__column" v-for="(column, index) in columns" :key="index">
|
|
23
|
+
<div
|
|
24
|
+
class="aui-picker__wheel"
|
|
25
|
+
ref="wheels[index]"
|
|
26
|
+
@touchstart="onTouchStart(index, $event)"
|
|
27
|
+
@touchmove="onTouchMove(index, $event, true)"
|
|
28
|
+
@touchend="onTouchEnd(index, $event)"
|
|
29
|
+
@touchcancel="onTouchEnd(index, $event)"
|
|
30
|
+
@mousedown="onMouseDown(index, $event)"
|
|
31
|
+
@mousemove="onMouseMove(index, $event, false)"
|
|
32
|
+
@mouseup="onMouseUp(index, $event)"
|
|
33
|
+
@mouseleave="onMouseUp(index, $event)"
|
|
34
|
+
>
|
|
35
|
+
<div class="aui-picker__indicator"></div>
|
|
36
|
+
<div class="aui-picker__frame" :style="{ transform: wheelTransforms[index] }">
|
|
37
|
+
<!-- 顶部虚拟空间 -->
|
|
38
|
+
<div class="aui-picker__dummy-item" :style="{ height: dummyHeight + 'px' }"></div>
|
|
39
|
+
|
|
40
|
+
<!-- 实际选项 -->
|
|
41
|
+
<div class="aui-picker__item"
|
|
42
|
+
v-for="(item, itemIndex) in column.values"
|
|
43
|
+
:key="itemIndex"
|
|
44
|
+
:class="{'aui-picker__item--selected': isSelected(index, itemIndex)}"
|
|
45
|
+
@click="selectItem(index, itemIndex)">
|
|
46
|
+
{{ item.label || item }}
|
|
47
|
+
</div>
|
|
48
|
+
|
|
49
|
+
<!-- 底部虚拟空间 -->
|
|
50
|
+
<div class="aui-picker__dummy-item" :style="{ height: dummyHeight + 'px' }"></div>
|
|
51
|
+
</div>
|
|
52
|
+
</div>
|
|
53
|
+
</div>
|
|
54
|
+
</div>
|
|
55
|
+
</div>
|
|
56
|
+
</div>
|
|
57
|
+
</transition>
|
|
58
|
+
</div>
|
|
59
|
+
</template>
|
|
60
|
+
|
|
61
|
+
<script setup>
|
|
62
|
+
import { ref, computed, onMounted, nextTick, watch } from 'vue';
|
|
63
|
+
|
|
64
|
+
const _name = "AuiPicker";
|
|
65
|
+
defineOptions({ name: _name });
|
|
66
|
+
const props = defineProps({
|
|
67
|
+
columns: {
|
|
68
|
+
type: Array,
|
|
69
|
+
required: true,
|
|
70
|
+
default: () => []
|
|
71
|
+
},
|
|
72
|
+
value: {
|
|
73
|
+
type: Array,
|
|
74
|
+
default: () => []
|
|
75
|
+
},
|
|
76
|
+
title: {
|
|
77
|
+
type: String,
|
|
78
|
+
default: '请选择'
|
|
79
|
+
},
|
|
80
|
+
disabled: {
|
|
81
|
+
type: Boolean,
|
|
82
|
+
default: false
|
|
83
|
+
}
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
const emits = defineEmits(['update:value', 'change', 'confirm', 'cancel']);
|
|
87
|
+
|
|
88
|
+
const isOpen = ref(false);
|
|
89
|
+
const wheels = ref([]);
|
|
90
|
+
const selectedValues = ref([...props.value]);
|
|
91
|
+
const wheelTransforms = ref([]);
|
|
92
|
+
const startY = ref(0);
|
|
93
|
+
const currentY = ref(0);
|
|
94
|
+
const isDragging = ref(false);
|
|
95
|
+
const activeWheelIndex = ref(-1);
|
|
96
|
+
const itemHeight = 44;
|
|
97
|
+
const dummyHeight = itemHeight * 2;
|
|
98
|
+
|
|
99
|
+
// 检测鸿蒙系统
|
|
100
|
+
const isHarmonyOS = () => {
|
|
101
|
+
const ua = navigator.userAgent.toLowerCase();
|
|
102
|
+
return ua.includes('harmonyos') || ua.includes('huawei') || ua.includes('harmony');
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
// 判断是否有选中值
|
|
106
|
+
const hasSelectedValue = computed(() => {
|
|
107
|
+
return selectedValues.value.length > 0 &&
|
|
108
|
+
selectedValues.value.every(val => val !== undefined && val !== null);
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
// 计算显示值
|
|
112
|
+
const displayValue = computed(() => {
|
|
113
|
+
if (!selectedValues.value.length) return '';
|
|
114
|
+
|
|
115
|
+
return selectedValues.value.map((val, index) => {
|
|
116
|
+
const column = props.columns[index];
|
|
117
|
+
const item = column.values.find(item => item.value === val) || column.values[0];
|
|
118
|
+
return item.label || item;
|
|
119
|
+
}).join(' / ');
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
// 检查选项是否被选中
|
|
123
|
+
const isSelected = (columnIndex, itemIndex) => {
|
|
124
|
+
const column = props.columns[columnIndex];
|
|
125
|
+
const selectedVal = selectedValues.value[columnIndex];
|
|
126
|
+
return column.values[itemIndex].value === selectedVal;
|
|
127
|
+
};
|
|
128
|
+
|
|
129
|
+
// 切换选择器显示状态
|
|
130
|
+
const togglePicker = () => {
|
|
131
|
+
if (props.disabled) return;
|
|
132
|
+
isOpen.value = !isOpen.value;
|
|
133
|
+
if (isOpen.value) {
|
|
134
|
+
nextTick(() => {
|
|
135
|
+
updateWheelPositions();
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
};
|
|
139
|
+
|
|
140
|
+
// 关闭选择器
|
|
141
|
+
const closePicker = () => {
|
|
142
|
+
isOpen.value = false;
|
|
143
|
+
emits('cancel');
|
|
144
|
+
};
|
|
145
|
+
|
|
146
|
+
// 确认选择
|
|
147
|
+
const confirmSelection = () => {
|
|
148
|
+
emits('update:value', [...selectedValues.value]);
|
|
149
|
+
emits('confirm', [...selectedValues.value]);
|
|
150
|
+
isOpen.value = false;
|
|
151
|
+
};
|
|
152
|
+
|
|
153
|
+
// 选择项目
|
|
154
|
+
const selectItem = (columnIndex, itemIndex) => {
|
|
155
|
+
const column = props.columns[columnIndex];
|
|
156
|
+
selectedValues.value[columnIndex] = column.values[itemIndex].value;
|
|
157
|
+
emits('change', [...selectedValues.value]);
|
|
158
|
+
updateWheelPosition(columnIndex);
|
|
159
|
+
};
|
|
160
|
+
|
|
161
|
+
// 更新滚轮位置
|
|
162
|
+
const updateWheelPositions = () => {
|
|
163
|
+
wheels.value.forEach((wheel, index) => {
|
|
164
|
+
updateWheelPosition(index);
|
|
165
|
+
});
|
|
166
|
+
};
|
|
167
|
+
|
|
168
|
+
// 更新单个滚轮位置
|
|
169
|
+
const updateWheelPosition = (columnIndex) => {
|
|
170
|
+
const column = props.columns[columnIndex];
|
|
171
|
+
const selectedVal = selectedValues.value[columnIndex];
|
|
172
|
+
const selectedIndex = column.values.findIndex(item => item.value === selectedVal);
|
|
173
|
+
|
|
174
|
+
if (selectedIndex !== -1) {
|
|
175
|
+
const indicatorTop = 83;
|
|
176
|
+
const offset = selectedIndex * itemHeight + dummyHeight - indicatorTop;
|
|
177
|
+
wheelTransforms.value[columnIndex] = `translate3d(0, ${-offset}px, 0)`;
|
|
178
|
+
}
|
|
179
|
+
};
|
|
180
|
+
|
|
181
|
+
// 获取指示器位置
|
|
182
|
+
const getIndicatorPosition = (wheel) => {
|
|
183
|
+
const indicator = wheel.querySelector('.aui-picker__indicator');
|
|
184
|
+
const rect = indicator.getBoundingClientRect();
|
|
185
|
+
return {
|
|
186
|
+
top: rect.top,
|
|
187
|
+
height: rect.height,
|
|
188
|
+
center: rect.top + rect.height / 2
|
|
189
|
+
};
|
|
190
|
+
};
|
|
191
|
+
|
|
192
|
+
// 触摸/鼠标事件处理
|
|
193
|
+
const onTouchStart = (index, event) => {
|
|
194
|
+
event.preventDefault();
|
|
195
|
+
event.stopPropagation();
|
|
196
|
+
|
|
197
|
+
if (isHarmonyOS()) {
|
|
198
|
+
event.stopImmediatePropagation();
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
startDrag(index, event.touches[0].clientY, true);
|
|
202
|
+
};
|
|
203
|
+
|
|
204
|
+
const onTouchMove = (index, event, isTouch) => {
|
|
205
|
+
if (index !== activeWheelIndex.value || !isDragging.value) return;
|
|
206
|
+
|
|
207
|
+
if (isTouch && isHarmonyOS()) {
|
|
208
|
+
event.preventDefault();
|
|
209
|
+
event.stopPropagation();
|
|
210
|
+
event.stopImmediatePropagation();
|
|
211
|
+
|
|
212
|
+
const touch = event.touches[0];
|
|
213
|
+
drag(index, touch.clientY);
|
|
214
|
+
return;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
event.preventDefault();
|
|
218
|
+
event.stopPropagation();
|
|
219
|
+
drag(index, isTouch ? event.touches[0].clientY : event.clientY);
|
|
220
|
+
};
|
|
221
|
+
|
|
222
|
+
const onTouchEnd = (index, event) => {
|
|
223
|
+
if (index !== activeWheelIndex.value || !isDragging.value) return;
|
|
224
|
+
event.stopPropagation();
|
|
225
|
+
endDrag(index);
|
|
226
|
+
};
|
|
227
|
+
|
|
228
|
+
const onMouseDown = (index, event) => {
|
|
229
|
+
if (event.button !== 0) return;
|
|
230
|
+
event.preventDefault();
|
|
231
|
+
event.stopPropagation();
|
|
232
|
+
startDrag(index, event.clientY, false);
|
|
233
|
+
};
|
|
234
|
+
|
|
235
|
+
const onMouseMove = (index, event, isTouch) => {
|
|
236
|
+
if (index !== activeWheelIndex.value || !isDragging.value || !isTouch) return;
|
|
237
|
+
event.preventDefault();
|
|
238
|
+
event.stopPropagation();
|
|
239
|
+
drag(index, event.clientY);
|
|
240
|
+
};
|
|
241
|
+
|
|
242
|
+
const onMouseUp = (index, event) => {
|
|
243
|
+
if (index !== activeWheelIndex.value || !isDragging.value) return;
|
|
244
|
+
event.preventDefault();
|
|
245
|
+
event.stopPropagation();
|
|
246
|
+
endDrag(index);
|
|
247
|
+
};
|
|
248
|
+
|
|
249
|
+
// 开始拖拽
|
|
250
|
+
const startDrag = (index, y, isTouch) => {
|
|
251
|
+
if (props.disabled) return;
|
|
252
|
+
|
|
253
|
+
activeWheelIndex.value = index;
|
|
254
|
+
startY.value = y;
|
|
255
|
+
currentY.value = 0;
|
|
256
|
+
isDragging.value = true;
|
|
257
|
+
|
|
258
|
+
const wheel = wheels.value[index];
|
|
259
|
+
const frame = wheel.querySelector('.aui-picker__frame');
|
|
260
|
+
|
|
261
|
+
const transform = window.getComputedStyle(frame).transform;
|
|
262
|
+
const matrix = new DOMMatrix(transform);
|
|
263
|
+
const startOffset = matrix.m42;
|
|
264
|
+
|
|
265
|
+
wheel._startOffset = startOffset;
|
|
266
|
+
wheel._startTime = Date.now();
|
|
267
|
+
wheel._lastY = y;
|
|
268
|
+
wheel._lastTime = Date.now();
|
|
269
|
+
wheel._velocity = 0;
|
|
270
|
+
wheel._isDragging = true;
|
|
271
|
+
wheel._isTouch = isTouch;
|
|
272
|
+
|
|
273
|
+
wheel._indicatorPos = getIndicatorPosition(wheel);
|
|
274
|
+
|
|
275
|
+
frame.style.transition = 'none';
|
|
276
|
+
|
|
277
|
+
document.body.style.overflow = 'hidden';
|
|
278
|
+
|
|
279
|
+
if (isTouch && isHarmonyOS()) {
|
|
280
|
+
wheel._rafId = requestAnimationFrame(() => {
|
|
281
|
+
if (wheel._isDragging) {
|
|
282
|
+
// 鸿蒙系统特殊处理
|
|
283
|
+
}
|
|
284
|
+
});
|
|
285
|
+
}
|
|
286
|
+
};
|
|
287
|
+
|
|
288
|
+
// 拖拽过程
|
|
289
|
+
const drag = (index, y) => {
|
|
290
|
+
if (!isDragging.value) return;
|
|
291
|
+
|
|
292
|
+
const deltaY = y - startY.value;
|
|
293
|
+
currentY.value = deltaY;
|
|
294
|
+
|
|
295
|
+
const wheel = wheels.value[index];
|
|
296
|
+
const startOffset = wheel._startOffset;
|
|
297
|
+
let newOffset = startOffset + deltaY;
|
|
298
|
+
|
|
299
|
+
const column = props.columns[index];
|
|
300
|
+
const totalItems = column.values.length;
|
|
301
|
+
const maxOffset = 0;
|
|
302
|
+
const minOffset = -((totalItems - 1) * itemHeight + dummyHeight * 2 - 83);
|
|
303
|
+
|
|
304
|
+
newOffset = Math.min(Math.max(newOffset, minOffset), maxOffset);
|
|
305
|
+
|
|
306
|
+
const frame = wheel.querySelector('.aui-picker__frame');
|
|
307
|
+
wheelTransforms.value[index] = `translate3d(0, ${newOffset}px, 0)`;
|
|
308
|
+
|
|
309
|
+
const now = Date.now();
|
|
310
|
+
const timeDelta = now - wheel._lastTime;
|
|
311
|
+
if (timeDelta > 0) {
|
|
312
|
+
wheel._velocity = (y - wheel._lastY) / timeDelta;
|
|
313
|
+
wheel._lastY = y;
|
|
314
|
+
wheel._lastTime = now;
|
|
315
|
+
}
|
|
316
|
+
};
|
|
317
|
+
|
|
318
|
+
// 结束拖拽
|
|
319
|
+
const endDrag = (index) => {
|
|
320
|
+
if (!isDragging.value) return;
|
|
321
|
+
|
|
322
|
+
isDragging.value = false;
|
|
323
|
+
activeWheelIndex.value = -1;
|
|
324
|
+
|
|
325
|
+
const wheel = wheels.value[index];
|
|
326
|
+
wheel._isDragging = false;
|
|
327
|
+
|
|
328
|
+
if (wheel._rafId) {
|
|
329
|
+
cancelAnimationFrame(wheel._rafId);
|
|
330
|
+
wheel._rafId = null;
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
document.body.style.overflow = '';
|
|
334
|
+
|
|
335
|
+
const frame = wheel.querySelector('.aui-picker__frame');
|
|
336
|
+
const column = props.columns[index];
|
|
337
|
+
|
|
338
|
+
frame.style.transition = 'transform 0.3s cubic-bezier(0.25, 0.1, 0.25, 1)';
|
|
339
|
+
|
|
340
|
+
const transform = window.getComputedStyle(frame).transform;
|
|
341
|
+
const matrix = new DOMMatrix(transform);
|
|
342
|
+
let currentOffset = matrix.m42;
|
|
343
|
+
|
|
344
|
+
const totalItems = column.values.length;
|
|
345
|
+
const maxOffset = 0;
|
|
346
|
+
const minOffset = -((totalItems - 1) * itemHeight + dummyHeight * 2 - 83);
|
|
347
|
+
|
|
348
|
+
const velocity = wheel._velocity;
|
|
349
|
+
const inertiaDistance = Math.sign(velocity) * Math.min(Math.abs(velocity) * 80, 300);
|
|
350
|
+
let targetOffset = currentOffset + inertiaDistance;
|
|
351
|
+
|
|
352
|
+
targetOffset = Math.min(Math.max(targetOffset, minOffset), maxOffset);
|
|
353
|
+
|
|
354
|
+
const indicator = wheel.querySelector('.aui-picker__indicator');
|
|
355
|
+
const rect = indicator.getBoundingClientRect();
|
|
356
|
+
const wheelRect = wheel.getBoundingClientRect();
|
|
357
|
+
const indicatorRelativeTop = rect.top - wheelRect.top;
|
|
358
|
+
const indicatorCenter = indicatorRelativeTop + rect.height / 2;
|
|
359
|
+
|
|
360
|
+
const contentOffset = Math.abs(targetOffset);
|
|
361
|
+
const adjustedOffset = contentOffset - dummyHeight + indicatorRelativeTop;
|
|
362
|
+
const closestIndex = Math.round(adjustedOffset / itemHeight);
|
|
363
|
+
|
|
364
|
+
const clampedIndex = Math.max(0, Math.min(closestIndex, totalItems - 1));
|
|
365
|
+
|
|
366
|
+
const finalOffset = -(clampedIndex * itemHeight + dummyHeight - indicatorRelativeTop);
|
|
367
|
+
|
|
368
|
+
wheelTransforms.value[index] = `translate3d(0, ${finalOffset}px, 0)`;
|
|
369
|
+
|
|
370
|
+
selectedValues.value[index] = column.values[clampedIndex].value;
|
|
371
|
+
emits('change', [...selectedValues.value]);
|
|
372
|
+
};
|
|
373
|
+
|
|
374
|
+
// 监听props.value变化
|
|
375
|
+
watch(() => props.value, (newVal) => {
|
|
376
|
+
selectedValues.value = [...newVal];
|
|
377
|
+
if (isOpen.value) {
|
|
378
|
+
nextTick(() => {
|
|
379
|
+
updateWheelPositions();
|
|
380
|
+
});
|
|
381
|
+
}
|
|
382
|
+
});
|
|
383
|
+
|
|
384
|
+
// 初始化
|
|
385
|
+
onMounted(() => {
|
|
386
|
+
wheels.value = Array.from(document.querySelectorAll('.aui-picker__wheel'));
|
|
387
|
+
wheelTransforms.value = wheels.value.map(() => 'translate3d(0, 0, 0)');
|
|
388
|
+
|
|
389
|
+
nextTick(() => {
|
|
390
|
+
updateWheelPositions();
|
|
391
|
+
|
|
392
|
+
wheels.value.forEach((wheel, index) => {
|
|
393
|
+
const column = props.columns[index];
|
|
394
|
+
const selectedVal = selectedValues.value[index];
|
|
395
|
+
const selectedIndex = column.values.findIndex(item => item.value === selectedVal);
|
|
396
|
+
|
|
397
|
+
if (selectedIndex !== -1) {
|
|
398
|
+
const frame = wheel.querySelector('.aui-picker__frame');
|
|
399
|
+
const transform = window.getComputedStyle(frame).transform;
|
|
400
|
+
const matrix = new DOMMatrix(transform);
|
|
401
|
+
const currentOffset = matrix.m42;
|
|
402
|
+
const indicatorTop = 83;
|
|
403
|
+
const expectedOffset = -(selectedIndex * itemHeight + dummyHeight - indicatorTop);
|
|
404
|
+
|
|
405
|
+
if (Math.abs(currentOffset - expectedOffset) > 1) {
|
|
406
|
+
wheelTransforms.value[index] = `translate3d(0, ${expectedOffset}px, 0)`;
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
});
|
|
410
|
+
|
|
411
|
+
if (isHarmonyOS()) {
|
|
412
|
+
console.log('初始化鸿蒙系统兼容性优化');
|
|
413
|
+
}
|
|
414
|
+
});
|
|
415
|
+
});
|
|
416
|
+
</script>
|
|
417
|
+
|
|
418
|
+
<style scoped>
|
|
419
|
+
.aui-picker {
|
|
420
|
+
position: relative;
|
|
421
|
+
width: 100%;
|
|
422
|
+
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
.aui-picker--disabled {
|
|
426
|
+
opacity: 0.5;
|
|
427
|
+
cursor: not-allowed;
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
.aui-picker__header {
|
|
431
|
+
display: flex;
|
|
432
|
+
align-items: center;
|
|
433
|
+
justify-content: space-between;
|
|
434
|
+
height: 44px;
|
|
435
|
+
padding: 0 15px;
|
|
436
|
+
border: 1px solid #e5e5e5;
|
|
437
|
+
border-radius: 4px;
|
|
438
|
+
background-color: #fff;
|
|
439
|
+
cursor: pointer;
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
.aui-picker__title {
|
|
443
|
+
font-size: 14px;
|
|
444
|
+
color: #333;
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
.aui-picker__value {
|
|
448
|
+
flex: 1;
|
|
449
|
+
margin-left: 10px;
|
|
450
|
+
font-size: 14px;
|
|
451
|
+
color: #666; /* 默认灰色 */
|
|
452
|
+
text-align: right;
|
|
453
|
+
overflow: hidden;
|
|
454
|
+
text-overflow: ellipsis;
|
|
455
|
+
white-space: nowrap;
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
/* 选中后的文本颜色 */
|
|
459
|
+
.aui-picker__value--selected {
|
|
460
|
+
color: #333; /* 选中后黑色 */
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
.aui-picker__icon {
|
|
464
|
+
display: inline-block;
|
|
465
|
+
width: 12px;
|
|
466
|
+
height: 12px;
|
|
467
|
+
margin-left: 8px;
|
|
468
|
+
border-right: 1px solid #999;
|
|
469
|
+
border-bottom: 1px solid #999;
|
|
470
|
+
transform: rotate(45deg);
|
|
471
|
+
transition: transform 0.3s ease;
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
.aui-picker__icon--up {
|
|
475
|
+
transform: rotate(225deg);
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
.aui-picker__content {
|
|
479
|
+
position: fixed;
|
|
480
|
+
top: 0;
|
|
481
|
+
left: 0;
|
|
482
|
+
width: 100%;
|
|
483
|
+
height: 100%;
|
|
484
|
+
z-index: 1000;
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
.aui-picker__mask {
|
|
488
|
+
position: absolute;
|
|
489
|
+
top: 0;
|
|
490
|
+
left: 0;
|
|
491
|
+
width: 100%;
|
|
492
|
+
height: 100%;
|
|
493
|
+
background-color: rgba(0, 0, 0, 0.5);
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
.aui-picker__panel {
|
|
497
|
+
position: absolute;
|
|
498
|
+
bottom: 0;
|
|
499
|
+
left: 0;
|
|
500
|
+
width: 100%;
|
|
501
|
+
background-color: #fff;
|
|
502
|
+
transform: translateY(0);
|
|
503
|
+
transition: transform 0.3s ease;
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
.aui-picker__toolbar {
|
|
507
|
+
display: flex;
|
|
508
|
+
justify-content: space-between;
|
|
509
|
+
align-items: center;
|
|
510
|
+
height: 44px;
|
|
511
|
+
padding: 0 15px;
|
|
512
|
+
border-bottom: 1px solid #e5e5e5;
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
.aui-picker__cancel,
|
|
516
|
+
.aui-picker__confirm {
|
|
517
|
+
font-size: 16px;
|
|
518
|
+
color: #007aff;
|
|
519
|
+
background-color: transparent;
|
|
520
|
+
border: none;
|
|
521
|
+
outline: none;
|
|
522
|
+
cursor: pointer;
|
|
523
|
+
}
|
|
524
|
+
|
|
525
|
+
.aui-picker__columns {
|
|
526
|
+
display: flex;
|
|
527
|
+
height: 300px;
|
|
528
|
+
overflow: hidden;
|
|
529
|
+
}
|
|
530
|
+
|
|
531
|
+
.aui-picker__column {
|
|
532
|
+
flex: 1;
|
|
533
|
+
position: relative;
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
.aui-picker__wheel {
|
|
537
|
+
position: relative;
|
|
538
|
+
height: 100%;
|
|
539
|
+
overflow: hidden;
|
|
540
|
+
-webkit-overflow-scrolling: touch;
|
|
541
|
+
overflow-scrolling: touch;
|
|
542
|
+
touch-action: pan-y;
|
|
543
|
+
}
|
|
544
|
+
|
|
545
|
+
.aui-picker__indicator {
|
|
546
|
+
position: absolute;
|
|
547
|
+
top: 83px;
|
|
548
|
+
left: 0;
|
|
549
|
+
width: 100%;
|
|
550
|
+
height: 44px;
|
|
551
|
+
border-top: 1px solid #e5e5e5;
|
|
552
|
+
border-bottom: 1px solid #e5e5e5;
|
|
553
|
+
pointer-events: none;
|
|
554
|
+
}
|
|
555
|
+
|
|
556
|
+
.aui-picker__frame {
|
|
557
|
+
position: relative;
|
|
558
|
+
transition: transform 0.1s ease-out;
|
|
559
|
+
will-change: transform;
|
|
560
|
+
transform: translateZ(0);
|
|
561
|
+
}
|
|
562
|
+
|
|
563
|
+
.aui-picker__item {
|
|
564
|
+
height: 44px;
|
|
565
|
+
line-height: 44px;
|
|
566
|
+
text-align: center;
|
|
567
|
+
font-size: 18px;
|
|
568
|
+
color: #333;
|
|
569
|
+
overflow: hidden;
|
|
570
|
+
text-overflow: ellipsis;
|
|
571
|
+
white-space: nowrap;
|
|
572
|
+
}
|
|
573
|
+
|
|
574
|
+
.aui-picker__item--selected {
|
|
575
|
+
font-weight: 500;
|
|
576
|
+
color: #000;
|
|
577
|
+
}
|
|
578
|
+
|
|
579
|
+
.aui-picker__dummy-item {
|
|
580
|
+
height: 88px;
|
|
581
|
+
visibility: hidden;
|
|
582
|
+
pointer-events: none;
|
|
583
|
+
}
|
|
584
|
+
|
|
585
|
+
.aui-picker-transition-enter-active,
|
|
586
|
+
.aui-picker-transition-leave-active {
|
|
587
|
+
transition: opacity 0.3s ease;
|
|
588
|
+
}
|
|
589
|
+
|
|
590
|
+
.aui-picker-transition-enter-from,
|
|
591
|
+
.aui-picker-transition-leave-to {
|
|
592
|
+
opacity: 0;
|
|
593
|
+
}
|
|
594
|
+
|
|
595
|
+
/* 针对鸿蒙系统的特殊样式 */
|
|
596
|
+
@media screen and (max-device-width: 768px) and (hover: none) {
|
|
597
|
+
.aui-picker__wheel {
|
|
598
|
+
-ms-touch-action: pan-y;
|
|
599
|
+
touch-action: pan-y;
|
|
600
|
+
overflow: hidden !important;
|
|
601
|
+
position: relative;
|
|
602
|
+
}
|
|
603
|
+
|
|
604
|
+
.aui-picker__frame {
|
|
605
|
+
will-change: transform;
|
|
606
|
+
transform: translateZ(0);
|
|
607
|
+
backface-visibility: hidden;
|
|
608
|
+
}
|
|
609
|
+
|
|
610
|
+
.aui-picker__columns {
|
|
611
|
+
-webkit-transform: translateZ(0);
|
|
612
|
+
transform: translateZ(0);
|
|
613
|
+
}
|
|
614
|
+
|
|
615
|
+
.aui-picker__panel {
|
|
616
|
+
transform: translate3d(0, 0, 0);
|
|
617
|
+
}
|
|
618
|
+
}
|
|
619
|
+
</style>
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<view class="aui-popup" v-show="visible" :style="`z-index:${zIndex}`">
|
|
3
|
+
<view class="aui-popup-mask">
|
|
4
|
+
<view class="aui-popup-content">
|
|
5
|
+
<slot></slot>
|
|
6
|
+
</view>
|
|
7
|
+
</view>
|
|
8
|
+
</view>
|
|
9
|
+
</template>
|
|
10
|
+
|
|
11
|
+
<script setup>
|
|
12
|
+
import { ref, computed, watch, onMounted, onUnmounted } from 'vue';
|
|
13
|
+
|
|
14
|
+
const _name="AuiPopup";
|
|
15
|
+
defineOptions({name:_name})
|
|
16
|
+
const props = defineProps({
|
|
17
|
+
visible: {
|
|
18
|
+
type: Boolean,
|
|
19
|
+
default: false
|
|
20
|
+
},
|
|
21
|
+
zIndex: {
|
|
22
|
+
type: Number,
|
|
23
|
+
default: 999
|
|
24
|
+
}
|
|
25
|
+
})
|
|
26
|
+
</script>
|
|
27
|
+
|
|
28
|
+
<style lang="scss" scoped>
|
|
29
|
+
.aui-popup{
|
|
30
|
+
position: fixed;
|
|
31
|
+
top: 0;
|
|
32
|
+
left: 0;
|
|
33
|
+
width: 100%;
|
|
34
|
+
height: 100%;
|
|
35
|
+
}
|
|
36
|
+
.aui-popup-mask{
|
|
37
|
+
position: absolute;
|
|
38
|
+
top: 0;
|
|
39
|
+
left: 0;
|
|
40
|
+
width: 100%;
|
|
41
|
+
height: 100%;
|
|
42
|
+
background-color: rgba(0,0,0,0.5);
|
|
43
|
+
}
|
|
44
|
+
.aui-popup-content{
|
|
45
|
+
background-color: #FFFFFF;
|
|
46
|
+
border-top-right-radius: 8px;
|
|
47
|
+
border-top-left-radius: 8px;
|
|
48
|
+
padding: 16px;
|
|
49
|
+
position: absolute;
|
|
50
|
+
bottom:0px;
|
|
51
|
+
left: 0px;
|
|
52
|
+
width: 100% ;
|
|
53
|
+
box-sizing: border-box;
|
|
54
|
+
max-height: 100%;
|
|
55
|
+
overflow-y: auto;
|
|
56
|
+
}
|
|
57
|
+
</style>
|