hy-app 0.2.6 → 0.2.7
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/common/shakeService.ts +0 -2
- package/components/hy-address-picker/hy-address-picker.vue +75 -91
- package/components/hy-avatar/hy-avatar.vue +64 -73
- package/components/hy-button/hy-button.vue +2 -2
- package/components/hy-float-button/hy-float-button.vue +115 -37
- package/components/hy-float-button/props.ts +3 -3
- package/components/hy-float-button/typing.d.ts +20 -7
- package/components/hy-icon/hy-icon.vue +1 -1
- package/components/hy-image/hy-image.vue +69 -104
- package/components/hy-image/index.scss +21 -5
- package/components/hy-image/props.ts +11 -10
- package/components/hy-image/typing.d.ts +23 -19
- package/components/hy-modal/index.scss +1 -1
- package/components/hy-popover/hy-popover.vue +200 -0
- package/components/hy-popover/index.scss +83 -0
- package/components/hy-popover/props.ts +13 -0
- package/components/hy-popover/typing.d.ts +56 -0
- package/components/hy-qrcode/hy-qrcode.vue +44 -45
- package/components/hy-rate/props.ts +6 -6
- package/components/hy-transition/hy-transition.vue +64 -72
- package/components/hy-transition/typing.d.ts +10 -6
- package/composables/index.ts +4 -2
- package/composables/usePopover.ts +221 -0
- package/composables/useQueue.ts +52 -0
- package/libs/css/mixin.scss +88 -0
- package/package.json +2 -2
- package/utils/inside.ts +96 -108
|
@@ -75,7 +75,8 @@ import { computed, type CSSProperties, getCurrentInstance, onMounted, ref, toRef
|
|
|
75
75
|
import type IProps from './typing'
|
|
76
76
|
import type { MenusType } from './typing'
|
|
77
77
|
import defaultProps from './props'
|
|
78
|
-
import { addUnit, getPx, getRect,
|
|
78
|
+
import { addUnit, getPx, getRect, guid, isH5 } from '../../utils'
|
|
79
|
+
import { HyApp } from '../../typing/modules/common'
|
|
79
80
|
|
|
80
81
|
// 组件
|
|
81
82
|
import HyIcon from '../hy-icon/hy-icon.vue'
|
|
@@ -86,8 +87,6 @@ const {
|
|
|
86
87
|
menus,
|
|
87
88
|
customStyle,
|
|
88
89
|
gap,
|
|
89
|
-
left,
|
|
90
|
-
top,
|
|
91
90
|
zIndex,
|
|
92
91
|
bgColor,
|
|
93
92
|
text,
|
|
@@ -96,11 +95,12 @@ const {
|
|
|
96
95
|
fixed,
|
|
97
96
|
direction,
|
|
98
97
|
draggable,
|
|
98
|
+
position,
|
|
99
|
+
expandable,
|
|
99
100
|
} = toRefs(props)
|
|
100
101
|
const emit = defineEmits(['click', 'clickItem'])
|
|
101
102
|
|
|
102
103
|
const instance = getCurrentInstance()
|
|
103
|
-
const { windowWidth } = getWindowInfo()
|
|
104
104
|
const btnSize: AnyObject = {
|
|
105
105
|
small: '50px',
|
|
106
106
|
medium: '60px',
|
|
@@ -109,16 +109,94 @@ const btnSize: AnyObject = {
|
|
|
109
109
|
const open = ref(false)
|
|
110
110
|
const rotate = computed(() => (open.value && !text.value ? '45deg' : '0deg'))
|
|
111
111
|
const soleId = `hy-float-button__${guid()}`
|
|
112
|
-
const showLeft = ref(false)
|
|
113
112
|
const fabSize = reactive({ width: 0, height: 0 }) // 悬浮按钮大小
|
|
114
113
|
const screen = reactive({ width: 0, height: 0 })
|
|
115
114
|
const currentCoordinate = reactive({
|
|
116
|
-
top:
|
|
117
|
-
left:
|
|
115
|
+
top: 0,
|
|
116
|
+
left: 0,
|
|
118
117
|
})
|
|
119
118
|
// 按下时坐标相对于元素的偏移量
|
|
120
119
|
const touchOffset = reactive({ x: 0, y: 0 })
|
|
121
120
|
const attractTransition = ref<boolean>(false)
|
|
121
|
+
const fabDirection = ref<HyApp.LeftRightType>('left')
|
|
122
|
+
const fabDirection2 = ref<HyApp.TopBottomType>('top')
|
|
123
|
+
const bounding = reactive({
|
|
124
|
+
minLeft: 10,
|
|
125
|
+
minTop: 10,
|
|
126
|
+
maxLeft: 380,
|
|
127
|
+
maxTop: 680,
|
|
128
|
+
})
|
|
129
|
+
|
|
130
|
+
onMounted(async () => {
|
|
131
|
+
await getFatRect()
|
|
132
|
+
await getBounding()
|
|
133
|
+
initPosition()
|
|
134
|
+
})
|
|
135
|
+
|
|
136
|
+
watch(
|
|
137
|
+
() => position.value,
|
|
138
|
+
() => initPosition(),
|
|
139
|
+
)
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* @description 初始化距离
|
|
143
|
+
* */
|
|
144
|
+
const initPosition = () => {
|
|
145
|
+
const { minLeft, minTop, maxLeft, maxTop } = bounding
|
|
146
|
+
const centerY = (maxTop + minTop) / 2
|
|
147
|
+
const centerX = (maxLeft + minLeft) / 2
|
|
148
|
+
|
|
149
|
+
switch (position.value) {
|
|
150
|
+
case 'left-top':
|
|
151
|
+
currentCoordinate.top = minTop
|
|
152
|
+
currentCoordinate.left = minLeft
|
|
153
|
+
fabDirection.value = 'left'
|
|
154
|
+
fabDirection2.value = 'top'
|
|
155
|
+
break
|
|
156
|
+
case 'right-top':
|
|
157
|
+
currentCoordinate.top = minTop
|
|
158
|
+
currentCoordinate.left = maxLeft
|
|
159
|
+
fabDirection.value = 'right'
|
|
160
|
+
fabDirection2.value = 'top'
|
|
161
|
+
break
|
|
162
|
+
case 'left-bottom':
|
|
163
|
+
currentCoordinate.top = maxTop
|
|
164
|
+
currentCoordinate.left = minLeft
|
|
165
|
+
fabDirection.value = 'left'
|
|
166
|
+
fabDirection2.value = 'bottom'
|
|
167
|
+
break
|
|
168
|
+
case 'right-bottom':
|
|
169
|
+
currentCoordinate.top = maxTop
|
|
170
|
+
currentCoordinate.left = maxLeft
|
|
171
|
+
fabDirection.value = 'right'
|
|
172
|
+
fabDirection2.value = 'bottom'
|
|
173
|
+
break
|
|
174
|
+
case 'left-center':
|
|
175
|
+
currentCoordinate.top = centerY
|
|
176
|
+
currentCoordinate.left = minLeft
|
|
177
|
+
fabDirection.value = 'left'
|
|
178
|
+
fabDirection2.value = 'bottom'
|
|
179
|
+
break
|
|
180
|
+
case 'right-center':
|
|
181
|
+
currentCoordinate.top = centerY
|
|
182
|
+
currentCoordinate.left = maxLeft
|
|
183
|
+
fabDirection.value = 'right'
|
|
184
|
+
fabDirection2.value = 'bottom'
|
|
185
|
+
break
|
|
186
|
+
case 'top-center':
|
|
187
|
+
currentCoordinate.top = minTop
|
|
188
|
+
currentCoordinate.left = centerX
|
|
189
|
+
fabDirection.value = 'left'
|
|
190
|
+
fabDirection2.value = 'top'
|
|
191
|
+
break
|
|
192
|
+
case 'bottom-center':
|
|
193
|
+
currentCoordinate.top = maxTop
|
|
194
|
+
currentCoordinate.left = centerX
|
|
195
|
+
fabDirection.value = 'left'
|
|
196
|
+
fabDirection2.value = 'bottom'
|
|
197
|
+
break
|
|
198
|
+
}
|
|
199
|
+
}
|
|
122
200
|
|
|
123
201
|
/**
|
|
124
202
|
* @description 获取组件大小
|
|
@@ -136,8 +214,8 @@ const getFloatBtnSize = computed(() => {
|
|
|
136
214
|
* */
|
|
137
215
|
const FloatButtonStyle = computed(() => {
|
|
138
216
|
const style: CSSProperties = {
|
|
139
|
-
top:
|
|
140
|
-
left:
|
|
217
|
+
top: currentCoordinate.top + 'px',
|
|
218
|
+
left: currentCoordinate.left + 'px',
|
|
141
219
|
backgroundColor: bgColor.value,
|
|
142
220
|
zIndex: zIndex.value,
|
|
143
221
|
color: textColor.value,
|
|
@@ -156,7 +234,7 @@ const menusStyle = computed(() => {
|
|
|
156
234
|
|
|
157
235
|
// 判断横向展示还是纵向展示
|
|
158
236
|
if (direction.value === 'row') {
|
|
159
|
-
if (
|
|
237
|
+
if (fabDirection.value === 'right') {
|
|
160
238
|
style.transform = 'translateX(-100%)'
|
|
161
239
|
style.left = '100%'
|
|
162
240
|
style.paddingRight = getFloatBtnSize.value
|
|
@@ -171,33 +249,34 @@ const menusStyle = computed(() => {
|
|
|
171
249
|
? addUnit(getPx(getFloatBtnSize.value) * menus.value.length + getPx(getFloatBtnSize.value))
|
|
172
250
|
: 0
|
|
173
251
|
} else {
|
|
174
|
-
|
|
175
|
-
|
|
252
|
+
if (fabDirection2.value === 'top') {
|
|
253
|
+
style.transform = 'translateX(-100%)'
|
|
254
|
+
style.height = '100%'
|
|
255
|
+
style.left = getFloatBtnSize.value
|
|
256
|
+
style.top = '0px'
|
|
257
|
+
style.paddingTop = getFloatBtnSize.value
|
|
258
|
+
} else {
|
|
259
|
+
style.paddingBottom = getFloatBtnSize.value
|
|
260
|
+
style.bottom = 0
|
|
261
|
+
}
|
|
176
262
|
style.transition = 'height 0.5s ease'
|
|
177
263
|
style.width = getFloatBtnSize.value
|
|
178
264
|
style.height = open.value
|
|
179
265
|
? addUnit(getPx(getFloatBtnSize.value) * menus.value.length + getPx(getFloatBtnSize.value))
|
|
180
266
|
: 0
|
|
181
|
-
style.paddingBottom = getFloatBtnSize.value
|
|
182
267
|
}
|
|
183
268
|
return style
|
|
184
269
|
})
|
|
185
270
|
|
|
186
|
-
onMounted(async () => {
|
|
187
|
-
await getFatRect()
|
|
188
|
-
getBounding()
|
|
189
|
-
})
|
|
190
|
-
|
|
191
271
|
/**
|
|
192
272
|
* @description 获取悬浮按钮大小
|
|
193
273
|
* */
|
|
194
274
|
const getFatRect = () => {
|
|
195
275
|
return new Promise((resolve, reject) => {
|
|
196
276
|
getRect(`#${soleId}`, false, instance).then((rect) => {
|
|
197
|
-
const {
|
|
277
|
+
const { width, height } = rect as UniApp.NodeInfo
|
|
198
278
|
fabSize.width = width
|
|
199
279
|
fabSize.height = height
|
|
200
|
-
if (left && left > windowWidth / 2) showLeft.value = true
|
|
201
280
|
resolve(rect)
|
|
202
281
|
})
|
|
203
282
|
})
|
|
@@ -208,7 +287,9 @@ const getFatRect = () => {
|
|
|
208
287
|
* */
|
|
209
288
|
const handleClick = () => {
|
|
210
289
|
emit('click')
|
|
211
|
-
|
|
290
|
+
if (expandable.value) {
|
|
291
|
+
open.value = !open.value
|
|
292
|
+
}
|
|
212
293
|
}
|
|
213
294
|
|
|
214
295
|
/**
|
|
@@ -225,23 +306,20 @@ const handleMenuItemClick = (temp: MenusType, index: number) => {
|
|
|
225
306
|
}
|
|
226
307
|
|
|
227
308
|
const getBounding = () => {
|
|
228
|
-
|
|
309
|
+
return new Promise((resolve) => {
|
|
310
|
+
const sysInfo = uni.getSystemInfoSync()
|
|
229
311
|
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
312
|
+
const { top = 16, left = 16, right = 16, bottom = 16 } = gap.value
|
|
313
|
+
screen.width = sysInfo.windowWidth
|
|
314
|
+
screen.height = isH5 ? sysInfo.windowTop + sysInfo.windowHeight : sysInfo.windowHeight
|
|
315
|
+
bounding.minTop = isH5 ? sysInfo.windowTop + top : top
|
|
316
|
+
bounding.minLeft = left
|
|
317
|
+
bounding.maxLeft = screen.width - fabSize.width - right
|
|
318
|
+
bounding.maxTop = screen.height - fabSize.height - bottom
|
|
319
|
+
resolve(bounding)
|
|
320
|
+
})
|
|
237
321
|
}
|
|
238
322
|
|
|
239
|
-
const bounding = {
|
|
240
|
-
minLeft: 10,
|
|
241
|
-
minTop: 10,
|
|
242
|
-
maxLeft: 380,
|
|
243
|
-
maxTop: 680,
|
|
244
|
-
}
|
|
245
323
|
const handleTouchStart = (e: TouchEvent) => {
|
|
246
324
|
if (!draggable.value) return
|
|
247
325
|
|
|
@@ -277,10 +355,10 @@ function handleTouchEnd() {
|
|
|
277
355
|
attractTransition.value = true
|
|
278
356
|
if (fabCenterX < screenCenterX) {
|
|
279
357
|
currentCoordinate.left = bounding.minLeft
|
|
280
|
-
|
|
358
|
+
fabDirection.value = 'left'
|
|
281
359
|
} else {
|
|
282
360
|
currentCoordinate.left = bounding.maxLeft
|
|
283
|
-
|
|
361
|
+
fabDirection.value = 'right'
|
|
284
362
|
}
|
|
285
363
|
}
|
|
286
364
|
</script>
|
|
@@ -7,9 +7,7 @@ const defaultProps: IProps = {
|
|
|
7
7
|
icon: IconConfig.PLUS,
|
|
8
8
|
iconSize: '',
|
|
9
9
|
iconColor: '',
|
|
10
|
-
gap: { left: 16, right: 16 },
|
|
11
|
-
top: 80,
|
|
12
|
-
left: 20,
|
|
10
|
+
gap: { left: 16, right: 16, top: 16, bottom: 40 },
|
|
13
11
|
zIndex: 10086,
|
|
14
12
|
bgColor: '',
|
|
15
13
|
text: '',
|
|
@@ -22,6 +20,8 @@ const defaultProps: IProps = {
|
|
|
22
20
|
float: true,
|
|
23
21
|
fixed: true,
|
|
24
22
|
draggable: true,
|
|
23
|
+
position: 'right-bottom',
|
|
24
|
+
expandable: true,
|
|
25
25
|
}
|
|
26
26
|
|
|
27
27
|
export default defaultProps
|
|
@@ -19,6 +19,16 @@ export type IGap = {
|
|
|
19
19
|
bottom?: number
|
|
20
20
|
}
|
|
21
21
|
|
|
22
|
+
export type FloatPositionVo =
|
|
23
|
+
| 'left-top'
|
|
24
|
+
| 'left-bottom'
|
|
25
|
+
| 'right-top'
|
|
26
|
+
| 'right-bottom'
|
|
27
|
+
| 'left-center'
|
|
28
|
+
| 'right-center'
|
|
29
|
+
| 'top-center'
|
|
30
|
+
| 'bottom-center'
|
|
31
|
+
|
|
22
32
|
export default interface HyFloatButtonProps {
|
|
23
33
|
/**
|
|
24
34
|
* @description 菜单栏集合
|
|
@@ -40,15 +50,10 @@ export default interface HyFloatButtonProps {
|
|
|
40
50
|
* @description 按钮图标颜色
|
|
41
51
|
* */
|
|
42
52
|
iconColor?: string
|
|
43
|
-
gap?: IGap
|
|
44
53
|
/**
|
|
45
|
-
* @description
|
|
54
|
+
* @description 到边框最小距离
|
|
46
55
|
* */
|
|
47
|
-
|
|
48
|
-
/**
|
|
49
|
-
* @description 按钮距离左边的距离,默认单位为px
|
|
50
|
-
* */
|
|
51
|
-
left?: number | string
|
|
56
|
+
gap?: IGap
|
|
52
57
|
/**
|
|
53
58
|
* @description 层级(默认:10086)
|
|
54
59
|
* */
|
|
@@ -97,6 +102,14 @@ export default interface HyFloatButtonProps {
|
|
|
97
102
|
* @description 是否能拖动(默认:true)
|
|
98
103
|
* */
|
|
99
104
|
draggable?: boolean
|
|
105
|
+
/**
|
|
106
|
+
* @description 悬浮按钮位置 (默认:right-bottom)
|
|
107
|
+
* */
|
|
108
|
+
position?: FloatPositionVo
|
|
109
|
+
/**
|
|
110
|
+
* @description 禁用点击打开菜单栏
|
|
111
|
+
* */
|
|
112
|
+
expandable?: boolean
|
|
100
113
|
/**
|
|
101
114
|
* @description 定义需要用到的外部样式
|
|
102
115
|
* */
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
v-if="isImg"
|
|
6
6
|
:src="name"
|
|
7
7
|
:mode="imgMode"
|
|
8
|
-
:style="[imgStyle]"
|
|
8
|
+
:style="[imgStyle, customStyle]"
|
|
9
9
|
></image>
|
|
10
10
|
<text v-else class="hy-icon__icon" :class="uClasses" :style="[iconStyle, customStyle]"></text>
|
|
11
11
|
<!-- 这里进行空字符串判断,如果仅仅是v-if="label",可能会出现传递0的时候,结果也无法显示 -->
|
|
@@ -1,15 +1,6 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<HyTransition
|
|
3
|
-
|
|
4
|
-
:show="show"
|
|
5
|
-
:style="transStyle"
|
|
6
|
-
:duration="fade ? 1000 : 0"
|
|
7
|
-
>
|
|
8
|
-
<view
|
|
9
|
-
class="hy-image box-border"
|
|
10
|
-
@tap="clickHandler"
|
|
11
|
-
:style="[wrapStyle, backgroundStyle]"
|
|
12
|
-
>
|
|
2
|
+
<HyTransition mode="fade" :show="show" :style="transStyle" :duration="fade ? 1000 : 0">
|
|
3
|
+
<view class="hy-image box-border" @tap="clickHandler" :style="[wrapStyle, backgroundStyle]">
|
|
13
4
|
<image
|
|
14
5
|
v-if="!isError"
|
|
15
6
|
:src="src"
|
|
@@ -18,11 +9,11 @@
|
|
|
18
9
|
@load="onLoadHandler"
|
|
19
10
|
:show-menu-by-longpress="showMenuByLongPress"
|
|
20
11
|
:lazy-load="lazyLoad"
|
|
21
|
-
class="hy-
|
|
12
|
+
:class="['hy-image__url', indistinct && 'hy-image__indistinct']"
|
|
22
13
|
:style="{
|
|
23
14
|
width: addUnit(width),
|
|
24
15
|
height: addUnit(height),
|
|
25
|
-
borderRadius: shape == 'circle' ? '
|
|
16
|
+
borderRadius: shape == 'circle' ? '1000px' : addUnit(radius),
|
|
26
17
|
}"
|
|
27
18
|
></image>
|
|
28
19
|
<view
|
|
@@ -36,7 +27,7 @@
|
|
|
36
27
|
}"
|
|
37
28
|
>
|
|
38
29
|
<slot name="loading">
|
|
39
|
-
<
|
|
30
|
+
<HyLoading :name="loadingIcon"></HyLoading>
|
|
40
31
|
</slot>
|
|
41
32
|
</view>
|
|
42
33
|
<view
|
|
@@ -47,7 +38,7 @@
|
|
|
47
38
|
}"
|
|
48
39
|
>
|
|
49
40
|
<slot name="error">
|
|
50
|
-
<HyIcon :name="errorIcon"></HyIcon>
|
|
41
|
+
<HyIcon :name="errorIcon" size="30"></HyIcon>
|
|
51
42
|
</slot>
|
|
52
43
|
</view>
|
|
53
44
|
</view>
|
|
@@ -56,34 +47,27 @@
|
|
|
56
47
|
|
|
57
48
|
<script lang="ts">
|
|
58
49
|
export default {
|
|
59
|
-
name:
|
|
50
|
+
name: 'hy-image',
|
|
60
51
|
options: {
|
|
61
52
|
addGlobalClass: true,
|
|
62
53
|
virtualHost: true,
|
|
63
|
-
styleIsolation:
|
|
54
|
+
styleIsolation: 'shared',
|
|
64
55
|
},
|
|
65
|
-
}
|
|
56
|
+
}
|
|
66
57
|
</script>
|
|
67
58
|
|
|
68
59
|
<script setup lang="ts">
|
|
69
|
-
import {
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
ref,
|
|
74
|
-
toRefs,
|
|
75
|
-
watch,
|
|
76
|
-
} from "vue";
|
|
77
|
-
import defaultProps from "./props";
|
|
78
|
-
import type IProps from "./typing";
|
|
79
|
-
import { addUnit, getPx } from "../../utils";
|
|
60
|
+
import { computed, type CSSProperties, onMounted, ref, toRefs, watch } from 'vue'
|
|
61
|
+
import defaultProps from './props'
|
|
62
|
+
import type IProps from './typing'
|
|
63
|
+
import { addUnit, getPx } from '../../utils'
|
|
80
64
|
|
|
81
65
|
// 组件
|
|
66
|
+
import HyIcon from '../hy-icon/hy-icon.vue'
|
|
67
|
+
import HyTransition from '../hy-transition/hy-transition.vue'
|
|
68
|
+
import HyLoading from '../hy-loading/hy-loading.vue'
|
|
82
69
|
|
|
83
|
-
|
|
84
|
-
import HyIcon from "../hy-icon/hy-icon.vue";
|
|
85
|
-
|
|
86
|
-
const props = withDefaults(defineProps<IProps>(), defaultProps);
|
|
70
|
+
const props = withDefaults(defineProps<IProps>(), defaultProps)
|
|
87
71
|
const {
|
|
88
72
|
customStyle,
|
|
89
73
|
duration,
|
|
@@ -95,133 +79,114 @@ const {
|
|
|
95
79
|
radius,
|
|
96
80
|
bgColor,
|
|
97
81
|
previewImage,
|
|
98
|
-
|
|
99
|
-
|
|
82
|
+
indistinct,
|
|
83
|
+
} = toRefs(props)
|
|
84
|
+
const emit = defineEmits(['click', 'error', 'load'])
|
|
100
85
|
|
|
101
86
|
// 图片是否加载错误,如果是,则显示错误占位图
|
|
102
|
-
const isError = ref(false)
|
|
87
|
+
const isError = ref(false)
|
|
103
88
|
// 初始化组件时,默认为加载中状态
|
|
104
|
-
const loading = ref(true)
|
|
89
|
+
const loading = ref(true)
|
|
105
90
|
// 不透明度,为了实现淡入淡出的效果
|
|
106
|
-
const opacity = ref(1)
|
|
91
|
+
const opacity = ref(1)
|
|
107
92
|
// 过渡时间,因为props的值无法修改,故需要一个中间值
|
|
108
|
-
const durationTime = ref(duration.value)
|
|
93
|
+
const durationTime = ref(duration.value)
|
|
109
94
|
// 图片加载完成时,去掉背景颜色,因为如果是png图片,就会显示灰色的背景
|
|
110
|
-
const backgroundStyle = ref({})
|
|
95
|
+
const backgroundStyle = ref({})
|
|
111
96
|
// 用于fade模式的控制组件显示与否
|
|
112
|
-
const show = ref(false)
|
|
97
|
+
const show = ref(false)
|
|
113
98
|
|
|
114
99
|
watch(
|
|
115
100
|
() => src.value,
|
|
116
101
|
(newValue) => {
|
|
117
102
|
if (!newValue) {
|
|
118
103
|
// 如果传入null或者'',或者false,或者undefined,标记为错误状态
|
|
119
|
-
isError.value = true
|
|
104
|
+
isError.value = true
|
|
105
|
+
loading.value = false
|
|
120
106
|
} else {
|
|
121
|
-
isError.value = false
|
|
122
|
-
loading.value = true
|
|
107
|
+
isError.value = false
|
|
108
|
+
loading.value = true
|
|
123
109
|
}
|
|
124
110
|
},
|
|
125
111
|
{ immediate: true },
|
|
126
|
-
)
|
|
112
|
+
)
|
|
127
113
|
|
|
128
114
|
const transStyle = computed<CSSProperties>(() => {
|
|
129
|
-
const style: CSSProperties = {}
|
|
130
|
-
if (
|
|
131
|
-
|
|
132
|
-
isError.value ||
|
|
133
|
-
width.value == "100%" ||
|
|
134
|
-
mode.value != "heightFix"
|
|
135
|
-
) {
|
|
136
|
-
style.width = addUnit(width.value);
|
|
115
|
+
const style: CSSProperties = {}
|
|
116
|
+
if (loading.value || isError.value || width.value == '100%' || mode.value != 'heightFix') {
|
|
117
|
+
style.width = addUnit(width.value)
|
|
137
118
|
} else {
|
|
138
|
-
style.width =
|
|
119
|
+
style.width = 'fit-content'
|
|
139
120
|
}
|
|
140
|
-
if (
|
|
141
|
-
|
|
142
|
-
isError.value ||
|
|
143
|
-
height.value == "100%" ||
|
|
144
|
-
mode.value != "widthFix"
|
|
145
|
-
) {
|
|
146
|
-
style.height = addUnit(height.value);
|
|
121
|
+
if (loading.value || isError.value || height.value == '100%' || mode.value != 'widthFix') {
|
|
122
|
+
style.height = addUnit(height.value)
|
|
147
123
|
} else {
|
|
148
|
-
style.height =
|
|
124
|
+
style.height = 'fit-content'
|
|
149
125
|
}
|
|
150
|
-
return style
|
|
151
|
-
})
|
|
126
|
+
return style
|
|
127
|
+
})
|
|
152
128
|
|
|
153
129
|
const wrapStyle = computed(() => {
|
|
154
|
-
const style: CSSProperties = {}
|
|
155
|
-
if (
|
|
156
|
-
|
|
157
|
-
isError.value ||
|
|
158
|
-
width.value == "100%" ||
|
|
159
|
-
mode.value != "heightFix"
|
|
160
|
-
) {
|
|
161
|
-
style.width = addUnit(width.value);
|
|
130
|
+
const style: CSSProperties = {}
|
|
131
|
+
if (loading.value || isError.value || width.value == '100%' || mode.value != 'heightFix') {
|
|
132
|
+
style.width = addUnit(width.value)
|
|
162
133
|
} else {
|
|
163
|
-
style.width =
|
|
134
|
+
style.width = 'fit-content'
|
|
164
135
|
}
|
|
165
|
-
if (
|
|
166
|
-
|
|
167
|
-
isError.value ||
|
|
168
|
-
height.value == "100%" ||
|
|
169
|
-
mode.value != "widthFix"
|
|
170
|
-
) {
|
|
171
|
-
style.height = addUnit(height.value);
|
|
136
|
+
if (loading.value || isError.value || height.value == '100%' || mode.value != 'widthFix') {
|
|
137
|
+
style.height = addUnit(height.value)
|
|
172
138
|
} else {
|
|
173
|
-
style.height =
|
|
139
|
+
style.height = 'fit-content'
|
|
174
140
|
}
|
|
175
141
|
// 如果是显示圆形,设置一个很多的半径值即可
|
|
176
|
-
style.borderRadius =
|
|
177
|
-
shape.value == "circle" ? "10000px" : addUnit(radius.value);
|
|
142
|
+
style.borderRadius = shape.value == 'circle' ? '10000px' : addUnit(radius.value)
|
|
178
143
|
// 如果设置圆角,必须要有hidden,否则可能圆角无效
|
|
179
|
-
style.overflow = getPx(radius.value) > 0 ?
|
|
144
|
+
style.overflow = getPx(radius.value) > 0 ? 'hidden' : 'visible'
|
|
180
145
|
|
|
181
|
-
return Object.assign(style, customStyle.value)
|
|
182
|
-
})
|
|
146
|
+
return Object.assign(style, customStyle.value)
|
|
147
|
+
})
|
|
183
148
|
|
|
184
149
|
onMounted(() => {
|
|
185
|
-
show.value = true
|
|
186
|
-
})
|
|
150
|
+
show.value = true
|
|
151
|
+
})
|
|
187
152
|
|
|
188
153
|
const clickHandler = () => {
|
|
189
|
-
emit(
|
|
154
|
+
emit('click')
|
|
190
155
|
|
|
191
156
|
if (previewImage.value) {
|
|
192
157
|
uni.previewImage({
|
|
193
158
|
urls: [src.value],
|
|
194
|
-
})
|
|
159
|
+
})
|
|
195
160
|
}
|
|
196
|
-
}
|
|
161
|
+
}
|
|
197
162
|
|
|
198
163
|
/**
|
|
199
164
|
* @description 图片加载失败
|
|
200
165
|
* */
|
|
201
166
|
const onErrorHandler = (err: Event) => {
|
|
202
|
-
loading.value = false
|
|
203
|
-
isError.value = true
|
|
204
|
-
emit(
|
|
205
|
-
}
|
|
167
|
+
loading.value = false
|
|
168
|
+
isError.value = true
|
|
169
|
+
emit('error', err)
|
|
170
|
+
}
|
|
206
171
|
|
|
207
172
|
/**
|
|
208
173
|
* @description 图片加载成功
|
|
209
174
|
* */
|
|
210
175
|
const onLoadHandler = (e: Event) => {
|
|
211
|
-
loading.value = false
|
|
212
|
-
isError.value = false
|
|
213
|
-
emit(
|
|
214
|
-
removeBgColor()
|
|
215
|
-
}
|
|
176
|
+
loading.value = false
|
|
177
|
+
isError.value = false
|
|
178
|
+
emit('load', e)
|
|
179
|
+
removeBgColor()
|
|
180
|
+
}
|
|
216
181
|
|
|
217
182
|
const removeBgColor = () => {
|
|
218
183
|
// 淡入动画过渡完成后,将背景设置为透明色,否则png图片会看到灰色的背景
|
|
219
184
|
backgroundStyle.value = {
|
|
220
|
-
backgroundColor: bgColor.value ||
|
|
221
|
-
}
|
|
222
|
-
}
|
|
185
|
+
backgroundColor: bgColor.value || '',
|
|
186
|
+
}
|
|
187
|
+
}
|
|
223
188
|
</script>
|
|
224
189
|
|
|
225
190
|
<style scoped lang="scss">
|
|
226
|
-
@import
|
|
191
|
+
@import './index.scss';
|
|
227
192
|
</style>
|
|
@@ -4,14 +4,31 @@
|
|
|
4
4
|
@include b(image) {
|
|
5
5
|
position: relative;
|
|
6
6
|
transition: opacity 0.5s ease-in-out;
|
|
7
|
+
width: 250px;
|
|
8
|
+
height: 200px;
|
|
7
9
|
|
|
8
|
-
|
|
10
|
+
@include e(url) {
|
|
9
11
|
width: 100%;
|
|
10
12
|
height: 100%;
|
|
11
13
|
}
|
|
14
|
+
@include e(indistinct) {
|
|
15
|
+
position: relative;
|
|
16
|
+
@include pseudo(after) {
|
|
17
|
+
content: "";
|
|
18
|
+
position: absolute;
|
|
19
|
+
top: 0;
|
|
20
|
+
left: 0;
|
|
21
|
+
width: 100%;
|
|
22
|
+
height: 100%;
|
|
23
|
+
background: rgba(0, 0, 0, 0.2); /* 半透明背景 */
|
|
24
|
+
backdrop-filter: blur(6px); /* 磨砂效果 */
|
|
25
|
+
filter: blur(6px);
|
|
26
|
+
-webkit-filter: blur(6px); /* 兼容 iOS */
|
|
27
|
+
z-index: 999;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
12
30
|
|
|
13
|
-
|
|
14
|
-
&__error {
|
|
31
|
+
@include e(loading, error) {
|
|
15
32
|
position: absolute;
|
|
16
33
|
top: 0;
|
|
17
34
|
left: 0;
|
|
@@ -22,6 +39,5 @@
|
|
|
22
39
|
justify-content: center;
|
|
23
40
|
background-color: $hy-background--empty;
|
|
24
41
|
color: $hy-text-color--grey;
|
|
25
|
-
font-size: 46px;
|
|
26
42
|
}
|
|
27
|
-
}
|
|
43
|
+
}
|
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import type IProps from
|
|
2
|
-
import { IconConfig } from
|
|
1
|
+
import type IProps from './typing'
|
|
2
|
+
import { IconConfig } from '../../config'
|
|
3
3
|
|
|
4
4
|
const defaultProps: IProps = {
|
|
5
|
-
src:
|
|
6
|
-
mode:
|
|
7
|
-
width:
|
|
8
|
-
height:
|
|
9
|
-
shape:
|
|
5
|
+
src: '',
|
|
6
|
+
mode: 'aspectFill',
|
|
7
|
+
width: '',
|
|
8
|
+
height: '',
|
|
9
|
+
shape: 'square',
|
|
10
10
|
radius: 0,
|
|
11
11
|
lazyLoad: true,
|
|
12
12
|
showMenuByLongPress: true,
|
|
@@ -17,8 +17,9 @@ const defaultProps: IProps = {
|
|
|
17
17
|
fade: true,
|
|
18
18
|
webp: false,
|
|
19
19
|
duration: 500,
|
|
20
|
-
bgColor:
|
|
20
|
+
bgColor: '',
|
|
21
|
+
indistinct: false,
|
|
21
22
|
previewImage: false,
|
|
22
|
-
}
|
|
23
|
+
}
|
|
23
24
|
|
|
24
|
-
export default defaultProps
|
|
25
|
+
export default defaultProps
|