@ecolovo/uniapp-components 2.0.4 → 2.0.6
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/components/badge/badge.vue +22 -11
- package/components/badge/types.d.ts +6 -0
- package/components/badge/types.js +4 -0
- package/components/badge/types.ts +10 -0
- package/components/button/button.vue +77 -48
- package/components/button/types.d.ts +20 -0
- package/components/button/types.js +4 -0
- package/components/button/types.ts +24 -0
- package/components/checkbox/checkbox.scss +1 -1
- package/components/checkbox/checkbox.vue +2 -0
- package/components/checkbox/types.d.ts +10 -0
- package/components/checkbox/types.js +4 -0
- package/components/checkbox/types.ts +16 -0
- package/components/checkbox-group/checkbox-group.vue +2 -0
- package/components/checkbox-group/types.d.ts +10 -0
- package/components/checkbox-group/types.js +8 -0
- package/components/checkbox-group/types.ts +20 -0
- package/components/checkbox-group2/checkbox-group2.vue +2 -0
- package/components/data-list/data-list.vue +13 -7
- package/components/date-picker/date-picker.vue +2 -0
- package/components/date-picker/types.d.ts +12 -0
- package/components/date-picker/types.js +4 -0
- package/components/date-picker/types.ts +18 -0
- package/components/dialog/dialog-content.vue +61 -46
- package/components/dialog/dialog.vue +55 -29
- package/components/dialog/types.d.ts +20 -0
- package/components/dialog/types.js +4 -0
- package/components/dialog/types.ts +24 -0
- package/components/dropdown/dropdown.vue +2 -0
- package/components/dropdown/types.d.ts +10 -0
- package/components/dropdown/types.js +4 -0
- package/components/dropdown/types.ts +16 -0
- package/components/empty/empty.vue +37 -20
- package/components/empty/types.d.ts +12 -0
- package/components/empty/types.js +9 -0
- package/components/empty/types.ts +21 -0
- package/components/flex/flex.vue +2 -0
- package/components/flex/types.d.ts +12 -0
- package/components/flex/types.js +4 -0
- package/components/flex/types.ts +22 -0
- package/components/form/form.vue +2 -0
- package/components/form/types.d.ts +6 -0
- package/components/form/types.js +4 -0
- package/components/form/types.ts +10 -0
- package/components/form-item/form-item.scss +6 -0
- package/components/form-item/form-item.vue +9 -3
- package/components/form-item/types.d.ts +6 -0
- package/components/form-item/types.js +4 -0
- package/components/form-item/types.ts +12 -0
- package/components/image/image.vue +28 -21
- package/components/image/types.d.ts +18 -0
- package/components/image/types.js +4 -0
- package/components/image/types.ts +23 -0
- package/components/index.d.ts +1 -0
- package/components/index.js +1 -0
- package/components/index.ts +1 -0
- package/components/input/input.scss +9 -0
- package/components/input/input.vue +11 -4
- package/components/input/password-input.vue +3 -1
- package/components/input/types.d.ts +20 -0
- package/components/input/types.js +8 -0
- package/components/input/types.ts +31 -0
- package/components/list-page/list-page.vue +21 -24
- package/components/list-page/types.d.ts +6 -0
- package/components/list-page/types.js +4 -0
- package/components/list-page/types.ts +12 -0
- package/components/load-more/load-more.scss +1 -0
- package/components/load-more/load-more.vue +66 -6
- package/components/load-more/types.d.ts +6 -0
- package/components/load-more/types.js +4 -0
- package/components/load-more/types.ts +12 -0
- package/components/loading/loading.vue +2 -0
- package/components/loading/types.d.ts +6 -0
- package/components/loading/types.js +4 -0
- package/components/loading/types.ts +12 -0
- package/components/message-box/message-box.d.ts +14 -16
- package/components/message-box/message-box.ts +0 -2
- package/components/message-box/message-box.vue +18 -43
- package/components/message-box/types.d.ts +16 -0
- package/components/message-box/types.js +4 -0
- package/components/message-box/types.ts +22 -0
- package/components/number-dialog/number-dialog.vue +5 -3
- package/components/number-dialog/types.d.ts +18 -0
- package/components/number-dialog/types.js +4 -0
- package/components/number-dialog/types.ts +24 -0
- package/components/number-input/number-input.scss +1 -1
- package/components/number-input/number-input.vue +6 -4
- package/components/number-input/types.d.ts +20 -0
- package/components/number-input/types.js +4 -0
- package/components/number-input/types.ts +26 -0
- package/components/numpad/numpad.vue +2 -0
- package/components/numpad/types.d.ts +10 -0
- package/components/numpad/types.js +4 -0
- package/components/numpad/types.ts +14 -0
- package/components/page/page-body.scss +1 -1
- package/components/page/page-footer.vue +2 -3
- package/components/page/page-header.vue +19 -9
- package/components/page/page.vue +45 -14
- package/components/page/types.d.ts +16 -0
- package/components/page/types.js +8 -0
- package/components/page/types.ts +27 -0
- package/components/picker/picker-popup.vue +10 -6
- package/components/picker/picker.vue +8 -0
- package/components/picker/types.d.ts +14 -0
- package/components/picker/types.js +4 -0
- package/components/picker/types.ts +18 -0
- package/components/popover/popover-content.vue +10 -1
- package/components/popover/popover-mask.vue +5 -5
- package/components/popover/popover.vue +34 -29
- package/components/popover/types.d.ts +10 -0
- package/components/popover/types.js +4 -0
- package/components/popover/types.ts +16 -0
- package/components/popup/popup-content.vue +61 -43
- package/components/popup/popup.vue +34 -28
- package/components/popup/types.d.ts +20 -0
- package/components/popup/types.js +4 -0
- package/components/popup/types.ts +24 -0
- package/components/price/price.scss +7 -3
- package/components/price/price.vue +6 -0
- package/components/price/types.d.ts +10 -0
- package/components/price/types.js +4 -0
- package/components/price/types.ts +14 -0
- package/components/search/search.vue +4 -2
- package/components/search/types.d.ts +14 -0
- package/components/search/types.js +4 -0
- package/components/search/types.ts +18 -0
- package/components/searching/searching.vue +2 -0
- package/components/searching/types.d.ts +8 -0
- package/components/searching/types.js +4 -0
- package/components/searching/types.ts +14 -0
- package/components/switch/switch.vue +5 -8
- package/components/switch/types.d.ts +8 -0
- package/components/switch/types.js +4 -0
- package/components/switch/types.ts +12 -0
- package/components/tab/tab.vue +2 -0
- package/components/tab/types.d.ts +8 -0
- package/components/tab/types.js +4 -0
- package/components/tab/types.ts +12 -0
- package/components/textarea/textarea.scss +10 -0
- package/components/textarea/textarea.vue +17 -9
- package/components/textarea/types.d.ts +12 -0
- package/components/textarea/types.js +4 -0
- package/components/textarea/types.ts +18 -0
- package/components/upload/composable.d.ts +24 -0
- package/components/upload/composable.js +173 -0
- package/components/upload/composable.ts +228 -0
- package/components/upload/media-upload.scss +12 -0
- package/components/upload/media-upload.vue +250 -0
- package/components/upload/types.d.ts +29 -0
- package/components/upload/types.js +4 -0
- package/components/upload/types.ts +38 -0
- package/composable/component-name.d.ts +8 -0
- package/composable/component-name.js +11 -4
- package/composable/component-name.ts +8 -0
- package/composable/dialog.d.ts +40 -0
- package/composable/dialog.js +96 -0
- package/composable/dialog.ts +113 -0
- package/composable/index.d.ts +5 -0
- package/composable/index.js +5 -0
- package/composable/index.ts +5 -0
- package/composable/message-box.d.ts +45 -28
- package/composable/message-box.js +68 -53
- package/composable/message-box.ts +101 -36
- package/composable/model.d.ts +8 -0
- package/composable/model.js +23 -0
- package/composable/model.ts +27 -0
- package/composable/page.d.ts +72 -0
- package/composable/page.js +25 -0
- package/composable/page.ts +34 -0
- package/configs/index.d.ts +24 -19
- package/configs/index.js +38 -35
- package/configs/index.ts +19 -0
- package/easyCom.d.ts +6 -6
- package/easyCom.js +19 -31
- package/easyCom.ts +4 -4
- package/globals.d.ts +93 -33
- package/globals.js +1 -0
- package/globals.ts +118 -0
- package/index.d.ts +3 -2
- package/index.js +2 -2
- package/index.ts +3 -2
- package/init.d.ts +11 -6
- package/init.js +84 -14
- package/init.ts +86 -1
- package/package.json +15 -12
- package/styles/var/component.scss +1 -0
- package/utils/date.d.ts +14 -19
- package/utils/date.js +77 -87
- package/utils/freezeDeep.js +7 -7
- package/utils/price.d.ts +15 -18
- package/utils/price.js +36 -37
- package/utils/upload.d.ts +1 -0
- package/utils/upload.js +8 -0
- package/utils/upload.ts +12 -0
- package/utils/windowInfo.d.ts +1 -9
- package/utils/windowInfo.js +10 -17
- package/utils/round.d.ts +0 -2
- package/utils/round.js +0 -13
- package/utils/round.ts +0 -14
|
@@ -31,6 +31,7 @@
|
|
|
31
31
|
import { computed, inject } from 'vue';
|
|
32
32
|
import type { ComputedRef } from 'vue';
|
|
33
33
|
import useClassNames from '../../composable/component-name';
|
|
34
|
+
import { formItemProps } from './types';
|
|
34
35
|
|
|
35
36
|
defineOptions({
|
|
36
37
|
options: {
|
|
@@ -57,6 +58,7 @@ const props = withDefaults(defineProps<_Props>(), {
|
|
|
57
58
|
subLabel: '',
|
|
58
59
|
required: false,
|
|
59
60
|
type: undefined,
|
|
61
|
+
...formItemProps,
|
|
60
62
|
});
|
|
61
63
|
|
|
62
64
|
/** 表单是否只读 */
|
|
@@ -94,7 +96,9 @@ const usingType = computed(() => props.type || formType.value);
|
|
|
94
96
|
}
|
|
95
97
|
|
|
96
98
|
.FormItem--label {
|
|
97
|
-
color:
|
|
99
|
+
color: UTILS__LOCAL_VAR(label-color);
|
|
100
|
+
font-size: UTILS__LOCAL_VAR(label-font-size);
|
|
101
|
+
font-weight: UTILS__LOCAL_VAR(label-font-weight);
|
|
98
102
|
}
|
|
99
103
|
|
|
100
104
|
&.FormItem--line {
|
|
@@ -119,8 +123,8 @@ const usingType = computed(() => props.type || formType.value);
|
|
|
119
123
|
|
|
120
124
|
&.FormItem--next {
|
|
121
125
|
.FormItem--label {
|
|
122
|
-
|
|
123
|
-
|
|
126
|
+
padding-top: 20rpx;
|
|
127
|
+
padding-bottom: 12rpx;
|
|
124
128
|
}
|
|
125
129
|
.FormItem--sub-label {
|
|
126
130
|
margin-left: 30rpx;
|
|
@@ -147,6 +151,8 @@ const usingType = computed(() => props.type || formType.value);
|
|
|
147
151
|
background: UTILS__GLOBAL_VAR(color, background);
|
|
148
152
|
border-radius: 12rpx;
|
|
149
153
|
height: 104rpx;
|
|
154
|
+
|
|
155
|
+
@include UTILS__SET_VAR(input, height, 100%);
|
|
150
156
|
}
|
|
151
157
|
}
|
|
152
158
|
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export type ConfigurableFormItemProps = {
|
|
2
|
+
/** 表单显示类型 */
|
|
3
|
+
type?: 'line' | 'next' | 'block';
|
|
4
|
+
};
|
|
5
|
+
|
|
6
|
+
export let formItemProps: ConfigurableFormItemProps = {};
|
|
7
|
+
|
|
8
|
+
export const setDefaultFormItemProps = (
|
|
9
|
+
props: ConfigurableFormItemProps = {}
|
|
10
|
+
) => {
|
|
11
|
+
formItemProps = props;
|
|
12
|
+
};
|
|
@@ -1,15 +1,19 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<image
|
|
3
3
|
:src="src || ''"
|
|
4
|
-
:
|
|
4
|
+
:show-menu-by-longpress="showMenuByLongpress"
|
|
5
|
+
:webp="webp"
|
|
6
|
+
:lazy-load="lazyLoad"
|
|
5
7
|
:class="[...classNames]"
|
|
6
8
|
:mode="mode"
|
|
7
|
-
@click="
|
|
9
|
+
@click="handlePreview"
|
|
8
10
|
></image>
|
|
9
11
|
</template>
|
|
10
12
|
|
|
11
13
|
<script lang="ts" setup>
|
|
14
|
+
import { computed } from 'vue';
|
|
12
15
|
import useClassNames from '../../composable/component-name';
|
|
16
|
+
import { imageProps, type ImageProps } from './types';
|
|
13
17
|
|
|
14
18
|
defineOptions({
|
|
15
19
|
options: {
|
|
@@ -20,44 +24,47 @@ defineOptions({
|
|
|
20
24
|
|
|
21
25
|
const classNames = useClassNames('image');
|
|
22
26
|
|
|
23
|
-
type _Props = {
|
|
24
|
-
/** 图片地址 */
|
|
25
|
-
src?: string;
|
|
26
|
-
/** 图片显示模式 */
|
|
27
|
-
mode?: string;
|
|
27
|
+
type _Props = ImageProps & {
|
|
28
28
|
/** 是否开启预览 */
|
|
29
|
-
preview?: boolean;
|
|
29
|
+
preview?: boolean | string[];
|
|
30
30
|
/** 预览列表 */
|
|
31
|
-
|
|
31
|
+
previewIndex?: number;
|
|
32
32
|
};
|
|
33
33
|
|
|
34
34
|
const props = withDefaults(defineProps<_Props>(), {
|
|
35
35
|
src: '',
|
|
36
|
-
mode: '',
|
|
36
|
+
mode: 'scaleToFill',
|
|
37
|
+
showMenuByLongpress: false,
|
|
38
|
+
webp: false,
|
|
39
|
+
lazyLoad: false,
|
|
37
40
|
preview: false,
|
|
38
|
-
|
|
41
|
+
previewIndex: undefined,
|
|
42
|
+
...imageProps,
|
|
39
43
|
});
|
|
40
44
|
|
|
41
45
|
const emit = defineEmits<{
|
|
42
46
|
(e: 'click'): void;
|
|
43
47
|
}>();
|
|
44
48
|
|
|
45
|
-
const
|
|
49
|
+
const previewList = computed(() => {
|
|
46
50
|
if (!props.preview) {
|
|
47
|
-
|
|
48
|
-
return;
|
|
51
|
+
return [];
|
|
49
52
|
}
|
|
53
|
+
if (props.preview === true) {
|
|
54
|
+
return [props.src];
|
|
55
|
+
}
|
|
56
|
+
return props.preview;
|
|
57
|
+
});
|
|
50
58
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
urls: props.previewList,
|
|
55
|
-
});
|
|
59
|
+
const handlePreview = () => {
|
|
60
|
+
if (!props.preview) {
|
|
61
|
+
emit('click');
|
|
56
62
|
return;
|
|
57
63
|
}
|
|
64
|
+
|
|
58
65
|
uni.previewImage({
|
|
59
|
-
current: props.src,
|
|
60
|
-
urls:
|
|
66
|
+
current: props.previewIndex ?? props.src,
|
|
67
|
+
urls: previewList.value,
|
|
61
68
|
});
|
|
62
69
|
};
|
|
63
70
|
</script>
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export interface ImageProps {
|
|
2
|
+
/** 图片地址 */
|
|
3
|
+
src?: string;
|
|
4
|
+
/** 图片显示模式 */
|
|
5
|
+
mode?: UniApp.ImageMode;
|
|
6
|
+
/** 长按图片显示发送给朋友、收藏、保存图片、搜一搜、打开名片/前往群聊/打开小程序(若图片中包含对应二维码或小程序码)的菜单。 */
|
|
7
|
+
showMenuByLongpress?: boolean;
|
|
8
|
+
/** 默认不解析 webP 格式,只支持网络资源 */
|
|
9
|
+
webp?: boolean;
|
|
10
|
+
/** 是否开启懒加载 */
|
|
11
|
+
lazyLoad?: boolean;
|
|
12
|
+
}
|
|
13
|
+
export type ConfigurableImageProps = {
|
|
14
|
+
/** 图片显示模式 */
|
|
15
|
+
mode?: UniApp.ImageMode;
|
|
16
|
+
};
|
|
17
|
+
export declare let imageProps: ConfigurableImageProps;
|
|
18
|
+
export declare const setDefaultImageProps: (props?: ConfigurableImageProps) => void;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export interface ImageProps {
|
|
2
|
+
/** 图片地址 */
|
|
3
|
+
src?: string;
|
|
4
|
+
/** 图片显示模式 */
|
|
5
|
+
mode?: UniApp.ImageMode;
|
|
6
|
+
/** 长按图片显示发送给朋友、收藏、保存图片、搜一搜、打开名片/前往群聊/打开小程序(若图片中包含对应二维码或小程序码)的菜单。 */
|
|
7
|
+
showMenuByLongpress?: boolean;
|
|
8
|
+
/** 默认不解析 webP 格式,只支持网络资源 */
|
|
9
|
+
webp?: boolean;
|
|
10
|
+
/** 是否开启懒加载 */
|
|
11
|
+
lazyLoad?: boolean;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export type ConfigurableImageProps = {
|
|
15
|
+
/** 图片显示模式 */
|
|
16
|
+
mode?: UniApp.ImageMode;
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
export let imageProps: ConfigurableImageProps = {};
|
|
20
|
+
|
|
21
|
+
export const setDefaultImageProps = (props: ConfigurableImageProps = {}) => {
|
|
22
|
+
imageProps = props;
|
|
23
|
+
};
|
package/components/index.d.ts
CHANGED
|
@@ -48,3 +48,4 @@ export { default as Selector } from './selector/selector.vue';
|
|
|
48
48
|
export { default as Switch } from './switch/switch.vue';
|
|
49
49
|
export { default as Tab } from './tab/tab.vue';
|
|
50
50
|
export { default as Textarea } from './textarea/textarea.vue';
|
|
51
|
+
export { default as MediaUpload } from './upload/media-upload.vue';
|
package/components/index.js
CHANGED
|
@@ -48,3 +48,4 @@ export { default as Selector } from './selector/selector.vue';
|
|
|
48
48
|
export { default as Switch } from './switch/switch.vue';
|
|
49
49
|
export { default as Tab } from './tab/tab.vue';
|
|
50
50
|
export { default as Textarea } from './textarea/textarea.vue';
|
|
51
|
+
export { default as MediaUpload } from './upload/media-upload.vue';
|
package/components/index.ts
CHANGED
|
@@ -48,3 +48,4 @@ export { default as Selector } from './selector/selector.vue';
|
|
|
48
48
|
export { default as Switch } from './switch/switch.vue';
|
|
49
49
|
export { default as Tab } from './tab/tab.vue';
|
|
50
50
|
export { default as Textarea } from './textarea/textarea.vue';
|
|
51
|
+
export { default as MediaUpload } from './upload/media-upload.vue';
|
|
@@ -39,6 +39,7 @@
|
|
|
39
39
|
import { computed, inject, ref } from 'vue';
|
|
40
40
|
import useClassNames from '../../composable/component-name';
|
|
41
41
|
import IconCpn from '../icon/icon.vue';
|
|
42
|
+
import { inputProps } from './types';
|
|
42
43
|
|
|
43
44
|
defineOptions({
|
|
44
45
|
options: {
|
|
@@ -87,6 +88,7 @@ const props = withDefaults(defineProps<_Props>(), {
|
|
|
87
88
|
maxlength: 140,
|
|
88
89
|
placeholder: '请输入',
|
|
89
90
|
useText: false,
|
|
91
|
+
...inputProps,
|
|
90
92
|
});
|
|
91
93
|
|
|
92
94
|
defineEmits<{
|
|
@@ -112,16 +114,22 @@ const setFocus = () => {
|
|
|
112
114
|
|
|
113
115
|
<style lang="scss" module>
|
|
114
116
|
@use '../../styles/utils' as *;
|
|
117
|
+
@use './input' as *;
|
|
118
|
+
|
|
119
|
+
// 定义外部变量
|
|
120
|
+
%external-vars {
|
|
121
|
+
@include UTILS__DEFINE_COMPONENT_VARS('input', $input);
|
|
122
|
+
}
|
|
115
123
|
|
|
116
124
|
.Input {
|
|
117
|
-
|
|
118
|
-
|
|
125
|
+
@extend %external-vars;
|
|
126
|
+
|
|
127
|
+
height: var(--height);
|
|
119
128
|
display: flex;
|
|
120
129
|
align-items: center;
|
|
121
130
|
|
|
122
131
|
.Input--text {
|
|
123
132
|
flex: 1;
|
|
124
|
-
width: 100%;
|
|
125
133
|
pointer-events: none;
|
|
126
134
|
}
|
|
127
135
|
.Input--ellipsis {
|
|
@@ -131,7 +139,6 @@ const setFocus = () => {
|
|
|
131
139
|
}
|
|
132
140
|
.Input--input {
|
|
133
141
|
flex: 1;
|
|
134
|
-
width: 100%;
|
|
135
142
|
height: 100%;
|
|
136
143
|
min-height: 1em;
|
|
137
144
|
padding: 0;
|
|
@@ -24,6 +24,7 @@
|
|
|
24
24
|
import { ref } from 'vue';
|
|
25
25
|
import useClassNames from '../../composable/component-name';
|
|
26
26
|
import IconCpn from '../icon/icon.vue';
|
|
27
|
+
import { passwordInputProps } from './types';
|
|
27
28
|
|
|
28
29
|
defineOptions({
|
|
29
30
|
options: {
|
|
@@ -48,8 +49,9 @@ type _Props = {
|
|
|
48
49
|
withDefaults(defineProps<_Props>(), {
|
|
49
50
|
modelValue: '',
|
|
50
51
|
disabled: false,
|
|
51
|
-
maxlength:
|
|
52
|
+
maxlength: 20,
|
|
52
53
|
placeholder: '请输入密码',
|
|
54
|
+
...passwordInputProps,
|
|
53
55
|
});
|
|
54
56
|
|
|
55
57
|
defineEmits<{
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export type ConfigurableInputProps = {
|
|
2
|
+
/** 文本超长时是否省略 */
|
|
3
|
+
ellipsis?: boolean;
|
|
4
|
+
/** 最大输入长度 */
|
|
5
|
+
maxlength?: number;
|
|
6
|
+
/** 占位文本 */
|
|
7
|
+
placeholder?: string;
|
|
8
|
+
/** 当不聚焦时是否使用文本替换 input */
|
|
9
|
+
useText?: boolean;
|
|
10
|
+
};
|
|
11
|
+
export declare let inputProps: ConfigurableInputProps;
|
|
12
|
+
export declare const setDefaultInputProps: (props?: ConfigurableInputProps) => void;
|
|
13
|
+
export type ConfigurablePasswordInputProps = {
|
|
14
|
+
/** 最大输入长度 */
|
|
15
|
+
maxlength?: number;
|
|
16
|
+
/** 占位文本 */
|
|
17
|
+
placeholder?: string;
|
|
18
|
+
};
|
|
19
|
+
export declare let passwordInputProps: ConfigurablePasswordInputProps;
|
|
20
|
+
export declare const setDefaultPasswordInputProps: (props?: ConfigurablePasswordInputProps) => void;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
export type ConfigurableInputProps = {
|
|
2
|
+
/** 文本超长时是否省略 */
|
|
3
|
+
ellipsis?: boolean;
|
|
4
|
+
/** 最大输入长度 */
|
|
5
|
+
maxlength?: number;
|
|
6
|
+
/** 占位文本 */
|
|
7
|
+
placeholder?: string;
|
|
8
|
+
/** 当不聚焦时是否使用文本替换 input */
|
|
9
|
+
useText?: boolean;
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
export let inputProps: ConfigurableInputProps = {};
|
|
13
|
+
|
|
14
|
+
export const setDefaultInputProps = (props: ConfigurableInputProps = {}) => {
|
|
15
|
+
inputProps = props;
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
export type ConfigurablePasswordInputProps = {
|
|
19
|
+
/** 最大输入长度 */
|
|
20
|
+
maxlength?: number;
|
|
21
|
+
/** 占位文本 */
|
|
22
|
+
placeholder?: string;
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
export let passwordInputProps: ConfigurablePasswordInputProps = {};
|
|
26
|
+
|
|
27
|
+
export const setDefaultPasswordInputProps = (
|
|
28
|
+
props: ConfigurablePasswordInputProps = {}
|
|
29
|
+
) => {
|
|
30
|
+
passwordInputProps = props;
|
|
31
|
+
};
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<page-cpn
|
|
3
|
-
:custom="custom"
|
|
4
3
|
:title="title"
|
|
5
4
|
:theme="theme"
|
|
6
5
|
:has-footer="hasFooter"
|
|
@@ -26,19 +25,18 @@
|
|
|
26
25
|
:class="$style['ListPage--empty']"
|
|
27
26
|
></empty-cpn>
|
|
28
27
|
|
|
29
|
-
<template
|
|
30
|
-
<slot name="footer"></slot>
|
|
31
|
-
</template>
|
|
28
|
+
<template #[footerSlot]><slot name="footer" /></template>
|
|
32
29
|
</page-cpn>
|
|
33
30
|
</template>
|
|
34
31
|
|
|
35
32
|
<script lang="ts" setup>
|
|
36
|
-
import { ref } from 'vue';
|
|
33
|
+
import { ref, useSlots } from 'vue';
|
|
37
34
|
import type { PagingData } from '@ecolovo/utils';
|
|
38
35
|
import useClassNames from '../../composable/component-name';
|
|
39
36
|
import DataListCpn from '../data-list/data-list.vue';
|
|
40
37
|
import EmptyCpn from '../empty/empty.vue';
|
|
41
38
|
import PageCpn from '../page/page.vue';
|
|
39
|
+
import { listPageProps } from './types';
|
|
42
40
|
|
|
43
41
|
defineOptions({
|
|
44
42
|
options: {
|
|
@@ -49,9 +47,17 @@ defineOptions({
|
|
|
49
47
|
|
|
50
48
|
const classNames = useClassNames('list-page');
|
|
51
49
|
|
|
50
|
+
type _Slots = {
|
|
51
|
+
default: () => void;
|
|
52
|
+
footer: () => void;
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
defineSlots<_Slots>();
|
|
56
|
+
|
|
57
|
+
const $slots = useSlots();
|
|
58
|
+
const footerSlot = $slots.footer ? 'footer' : 'unused_slot';
|
|
59
|
+
|
|
52
60
|
type _Props = {
|
|
53
|
-
/** 是否使用自定义导航栏 */
|
|
54
|
-
custom?: boolean;
|
|
55
61
|
/** 页面标题 */
|
|
56
62
|
title?: string;
|
|
57
63
|
/** 页面头部样式,主要用于控制导航栏字体颜色 */
|
|
@@ -69,7 +75,6 @@ type _Props = {
|
|
|
69
75
|
};
|
|
70
76
|
|
|
71
77
|
const props = withDefaults(defineProps<_Props>(), {
|
|
72
|
-
custom: true,
|
|
73
78
|
title: '',
|
|
74
79
|
theme: 'light',
|
|
75
80
|
hasFooter: false,
|
|
@@ -77,11 +82,15 @@ const props = withDefaults(defineProps<_Props>(), {
|
|
|
77
82
|
pagingData: null,
|
|
78
83
|
showLoadMore: true,
|
|
79
84
|
loading: false,
|
|
85
|
+
...listPageProps,
|
|
80
86
|
});
|
|
81
87
|
|
|
82
88
|
const emit = defineEmits<{
|
|
83
|
-
(e: 'refresh', payload?:
|
|
84
|
-
(
|
|
89
|
+
(e: 'refresh', payload?: PromiseResolvers<unknown> | VoidFunction): void;
|
|
90
|
+
(
|
|
91
|
+
e: 'reach-bottom',
|
|
92
|
+
payload?: PromiseResolvers<unknown> | VoidFunction
|
|
93
|
+
): void;
|
|
85
94
|
}>();
|
|
86
95
|
|
|
87
96
|
/** 是否正在刷新中 */
|
|
@@ -95,13 +104,7 @@ const onRefresh = () => {
|
|
|
95
104
|
|
|
96
105
|
isRefreshing.value = true;
|
|
97
106
|
|
|
98
|
-
|
|
99
|
-
let resolve: UniApp.PromiseResolver<unknown>,
|
|
100
|
-
reject: UniApp.PromiseRejector<unknown>;
|
|
101
|
-
const promise = new Promise((res, rej) => {
|
|
102
|
-
resolve = res;
|
|
103
|
-
reject = rej;
|
|
104
|
-
});
|
|
107
|
+
const { promise, resolve, reject } = Promise.withResolvers();
|
|
105
108
|
|
|
106
109
|
promise.finally(() => {
|
|
107
110
|
isRefreshing.value = false;
|
|
@@ -116,13 +119,7 @@ const onLoadMore = () => {
|
|
|
116
119
|
if (!props.pagingData?.hasMore) return;
|
|
117
120
|
|
|
118
121
|
isLoadingMore.value = true;
|
|
119
|
-
|
|
120
|
-
let resolve: UniApp.PromiseResolver<unknown>,
|
|
121
|
-
reject: UniApp.PromiseRejector<unknown>;
|
|
122
|
-
const promise = new Promise((res, rej) => {
|
|
123
|
-
resolve = res;
|
|
124
|
-
reject = rej;
|
|
125
|
-
});
|
|
122
|
+
const { promise, resolve, reject } = Promise.withResolvers();
|
|
126
123
|
|
|
127
124
|
promise.finally(() => {
|
|
128
125
|
isLoadingMore.value = false;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export type ConfigurableListPageProps = {
|
|
2
|
+
/** 页面头部样式,主要用于控制导航栏字体颜色 */
|
|
3
|
+
theme?: 'light' | 'dark';
|
|
4
|
+
};
|
|
5
|
+
|
|
6
|
+
export let listPageProps: ConfigurableListPageProps = {};
|
|
7
|
+
|
|
8
|
+
export const setDefaultListPageProps = (
|
|
9
|
+
props: ConfigurableListPageProps = {}
|
|
10
|
+
) => {
|
|
11
|
+
listPageProps = props;
|
|
12
|
+
};
|
|
@@ -1,24 +1,35 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<view :class="[...classNames, $style['LoadMore']]">
|
|
3
3
|
<template v-if="end">
|
|
4
|
-
<view :class="$style['LoadMore--content']">
|
|
4
|
+
<view :class="$style['LoadMore--content']">
|
|
5
|
+
<text>{{ endTitle }}</text>
|
|
6
|
+
</view>
|
|
5
7
|
</template>
|
|
6
8
|
<view v-else-if="loading" :class="$style['LoadMore--content']">
|
|
7
|
-
<icon-cpn icon="loading-dot-spinner"></icon-cpn>
|
|
8
|
-
|
|
9
|
+
<icon-cpn icon="loading-dot-spinner" spinning></icon-cpn>
|
|
10
|
+
<text>加载中...</text>
|
|
9
11
|
</view>
|
|
10
12
|
<view
|
|
11
13
|
v-else
|
|
12
14
|
:class="$style['LoadMore--content']"
|
|
13
15
|
@click="$emit('load-more')"
|
|
14
|
-
>上滑或点击加载更多</view
|
|
15
16
|
>
|
|
17
|
+
<text>上滑或点击加载更多</text>
|
|
18
|
+
</view>
|
|
19
|
+
<view v-if="observe" :class="$style['LoadMore--observe-view']"></view>
|
|
16
20
|
</view>
|
|
17
21
|
</template>
|
|
18
22
|
|
|
19
23
|
<script lang="ts" setup>
|
|
24
|
+
import {
|
|
25
|
+
getCurrentInstance,
|
|
26
|
+
onBeforeUnmount,
|
|
27
|
+
onMounted,
|
|
28
|
+
useCssModule,
|
|
29
|
+
} from 'vue';
|
|
20
30
|
import useClassNames from '../../composable/component-name';
|
|
21
31
|
import IconCpn from '../icon/icon.vue';
|
|
32
|
+
import { loadMoreProps } from './types';
|
|
22
33
|
|
|
23
34
|
defineOptions({
|
|
24
35
|
options: {
|
|
@@ -28,6 +39,7 @@ defineOptions({
|
|
|
28
39
|
});
|
|
29
40
|
|
|
30
41
|
const classNames = useClassNames('load-more');
|
|
42
|
+
const $style = useCssModule();
|
|
31
43
|
|
|
32
44
|
type _Props = {
|
|
33
45
|
/** 是否加载中 */
|
|
@@ -36,17 +48,54 @@ type _Props = {
|
|
|
36
48
|
end?: boolean;
|
|
37
49
|
/** 到最后一页时文本 */
|
|
38
50
|
endTitle?: string;
|
|
51
|
+
/** 是否开启观察 */
|
|
52
|
+
observe?: boolean;
|
|
39
53
|
};
|
|
40
54
|
|
|
41
|
-
withDefaults(defineProps<_Props>(), {
|
|
55
|
+
const props = withDefaults(defineProps<_Props>(), {
|
|
42
56
|
loading: false,
|
|
43
57
|
end: false,
|
|
44
58
|
endTitle: '没有更多了',
|
|
59
|
+
observe: true,
|
|
60
|
+
...loadMoreProps,
|
|
45
61
|
});
|
|
46
62
|
|
|
47
|
-
defineEmits<{
|
|
63
|
+
const emit = defineEmits<{
|
|
48
64
|
(event: 'load-more'): void;
|
|
49
65
|
}>();
|
|
66
|
+
|
|
67
|
+
let _observer: UniApp.IntersectionObserver | null = null;
|
|
68
|
+
|
|
69
|
+
const vm = getCurrentInstance();
|
|
70
|
+
|
|
71
|
+
const startObserver = () => {
|
|
72
|
+
stopObserver();
|
|
73
|
+
|
|
74
|
+
_observer = uni
|
|
75
|
+
.createIntersectionObserver(vm, {
|
|
76
|
+
nativeMode: true,
|
|
77
|
+
} as UniApp.CreateIntersectionObserverOptions)
|
|
78
|
+
.relativeToViewport({
|
|
79
|
+
bottom: 0,
|
|
80
|
+
});
|
|
81
|
+
_observer.observe('.' + $style['LoadMore--observe-view'], (res) => {
|
|
82
|
+
if (res.intersectionRatio === 0) return;
|
|
83
|
+
if (props.end || props.loading) return;
|
|
84
|
+
emit('load-more');
|
|
85
|
+
});
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
const stopObserver = () => {
|
|
89
|
+
_observer?.disconnect();
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
onMounted(() => {
|
|
93
|
+
startObserver();
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
onBeforeUnmount(() => {
|
|
97
|
+
stopObserver();
|
|
98
|
+
});
|
|
50
99
|
</script>
|
|
51
100
|
|
|
52
101
|
<style lang="scss" module>
|
|
@@ -66,6 +115,8 @@ defineEmits<{
|
|
|
66
115
|
text-align: center;
|
|
67
116
|
padding-top: UTILS__LOCAL_VAR(space);
|
|
68
117
|
font-size: UTILS__GLOBAL_VAR(font-size, normal);
|
|
118
|
+
position: relative;
|
|
119
|
+
z-index: 0;
|
|
69
120
|
}
|
|
70
121
|
.LoadMore--content {
|
|
71
122
|
box-sizing: border-box;
|
|
@@ -99,4 +150,13 @@ defineEmits<{
|
|
|
99
150
|
background: linear-gradient(to left, transparent, #ccc 75%);
|
|
100
151
|
}
|
|
101
152
|
}
|
|
153
|
+
.LoadMore--observe-view {
|
|
154
|
+
position: absolute;
|
|
155
|
+
z-index: -1;
|
|
156
|
+
left: 0;
|
|
157
|
+
bottom: 0;
|
|
158
|
+
width: 100%;
|
|
159
|
+
height: UTILS__LOCAL_VAR(observer-height);
|
|
160
|
+
pointer-events: none;
|
|
161
|
+
}
|
|
102
162
|
</style>
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export type ConfigurableLoadMoreProps = {
|
|
2
|
+
/** 到最后一页时文本 */
|
|
3
|
+
endTitle?: string;
|
|
4
|
+
};
|
|
5
|
+
|
|
6
|
+
export let loadMoreProps: ConfigurableLoadMoreProps = {};
|
|
7
|
+
|
|
8
|
+
export const setDefaultLoadMoreProps = (
|
|
9
|
+
props: ConfigurableLoadMoreProps = {}
|
|
10
|
+
) => {
|
|
11
|
+
loadMoreProps = props;
|
|
12
|
+
};
|