@ecolovo/uniapp-components 2.0.4 → 2.0.5

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.
Files changed (199) hide show
  1. package/components/badge/badge.vue +22 -11
  2. package/components/badge/types.d.ts +6 -0
  3. package/components/badge/types.js +4 -0
  4. package/components/badge/types.ts +10 -0
  5. package/components/button/button.vue +77 -48
  6. package/components/button/types.d.ts +20 -0
  7. package/components/button/types.js +4 -0
  8. package/components/button/types.ts +24 -0
  9. package/components/checkbox/checkbox.scss +1 -1
  10. package/components/checkbox/checkbox.vue +2 -0
  11. package/components/checkbox/types.d.ts +10 -0
  12. package/components/checkbox/types.js +4 -0
  13. package/components/checkbox/types.ts +16 -0
  14. package/components/checkbox-group/checkbox-group.vue +2 -0
  15. package/components/checkbox-group/types.d.ts +10 -0
  16. package/components/checkbox-group/types.js +8 -0
  17. package/components/checkbox-group/types.ts +20 -0
  18. package/components/checkbox-group2/checkbox-group2.vue +2 -0
  19. package/components/data-list/data-list.vue +13 -7
  20. package/components/date-picker/date-picker.vue +2 -0
  21. package/components/date-picker/types.d.ts +12 -0
  22. package/components/date-picker/types.js +4 -0
  23. package/components/date-picker/types.ts +18 -0
  24. package/components/dialog/dialog-content.vue +61 -46
  25. package/components/dialog/dialog.vue +55 -29
  26. package/components/dialog/types.d.ts +20 -0
  27. package/components/dialog/types.js +4 -0
  28. package/components/dialog/types.ts +24 -0
  29. package/components/dropdown/dropdown.vue +2 -0
  30. package/components/dropdown/types.d.ts +10 -0
  31. package/components/dropdown/types.js +4 -0
  32. package/components/dropdown/types.ts +16 -0
  33. package/components/empty/empty.vue +37 -20
  34. package/components/empty/types.d.ts +12 -0
  35. package/components/empty/types.js +9 -0
  36. package/components/empty/types.ts +21 -0
  37. package/components/flex/flex.vue +2 -0
  38. package/components/flex/types.d.ts +12 -0
  39. package/components/flex/types.js +4 -0
  40. package/components/flex/types.ts +22 -0
  41. package/components/form/form.vue +2 -0
  42. package/components/form/types.d.ts +6 -0
  43. package/components/form/types.js +4 -0
  44. package/components/form/types.ts +10 -0
  45. package/components/form-item/form-item.scss +6 -0
  46. package/components/form-item/form-item.vue +9 -3
  47. package/components/form-item/types.d.ts +6 -0
  48. package/components/form-item/types.js +4 -0
  49. package/components/form-item/types.ts +12 -0
  50. package/components/image/image.vue +28 -21
  51. package/components/image/types.d.ts +18 -0
  52. package/components/image/types.js +4 -0
  53. package/components/image/types.ts +23 -0
  54. package/components/index.d.ts +1 -0
  55. package/components/index.js +1 -0
  56. package/components/index.ts +1 -0
  57. package/components/input/input.scss +9 -0
  58. package/components/input/input.vue +11 -4
  59. package/components/input/password-input.vue +3 -1
  60. package/components/input/types.d.ts +20 -0
  61. package/components/input/types.js +8 -0
  62. package/components/input/types.ts +31 -0
  63. package/components/list-page/list-page.vue +21 -24
  64. package/components/list-page/types.d.ts +6 -0
  65. package/components/list-page/types.js +4 -0
  66. package/components/list-page/types.ts +12 -0
  67. package/components/load-more/load-more.scss +1 -0
  68. package/components/load-more/load-more.vue +66 -6
  69. package/components/load-more/types.d.ts +6 -0
  70. package/components/load-more/types.js +4 -0
  71. package/components/load-more/types.ts +12 -0
  72. package/components/loading/loading.vue +2 -0
  73. package/components/loading/types.d.ts +6 -0
  74. package/components/loading/types.js +4 -0
  75. package/components/loading/types.ts +12 -0
  76. package/components/message-box/message-box.d.ts +14 -16
  77. package/components/message-box/message-box.ts +0 -2
  78. package/components/message-box/message-box.vue +18 -43
  79. package/components/message-box/types.d.ts +16 -0
  80. package/components/message-box/types.js +4 -0
  81. package/components/message-box/types.ts +22 -0
  82. package/components/number-dialog/number-dialog.vue +5 -3
  83. package/components/number-dialog/types.d.ts +18 -0
  84. package/components/number-dialog/types.js +4 -0
  85. package/components/number-dialog/types.ts +24 -0
  86. package/components/number-input/number-input.scss +1 -1
  87. package/components/number-input/number-input.vue +5 -3
  88. package/components/number-input/types.d.ts +20 -0
  89. package/components/number-input/types.js +4 -0
  90. package/components/number-input/types.ts +26 -0
  91. package/components/numpad/numpad.vue +2 -0
  92. package/components/numpad/types.d.ts +10 -0
  93. package/components/numpad/types.js +4 -0
  94. package/components/numpad/types.ts +14 -0
  95. package/components/page/page-body.scss +1 -1
  96. package/components/page/page-footer.vue +2 -3
  97. package/components/page/page-header.vue +19 -9
  98. package/components/page/page.vue +45 -14
  99. package/components/page/types.d.ts +16 -0
  100. package/components/page/types.js +8 -0
  101. package/components/page/types.ts +27 -0
  102. package/components/picker/picker-popup.vue +10 -6
  103. package/components/picker/picker.vue +8 -0
  104. package/components/picker/types.d.ts +14 -0
  105. package/components/picker/types.js +4 -0
  106. package/components/picker/types.ts +18 -0
  107. package/components/popover/popover-content.vue +10 -1
  108. package/components/popover/popover-mask.vue +5 -5
  109. package/components/popover/popover.vue +34 -29
  110. package/components/popover/types.d.ts +10 -0
  111. package/components/popover/types.js +4 -0
  112. package/components/popover/types.ts +16 -0
  113. package/components/popup/popup-content.vue +61 -43
  114. package/components/popup/popup.vue +34 -28
  115. package/components/popup/types.d.ts +20 -0
  116. package/components/popup/types.js +4 -0
  117. package/components/popup/types.ts +24 -0
  118. package/components/price/price.scss +7 -3
  119. package/components/price/price.vue +6 -0
  120. package/components/price/types.d.ts +10 -0
  121. package/components/price/types.js +4 -0
  122. package/components/price/types.ts +14 -0
  123. package/components/search/search.vue +2 -0
  124. package/components/search/types.d.ts +14 -0
  125. package/components/search/types.js +4 -0
  126. package/components/search/types.ts +18 -0
  127. package/components/searching/searching.vue +2 -0
  128. package/components/searching/types.d.ts +8 -0
  129. package/components/searching/types.js +4 -0
  130. package/components/searching/types.ts +14 -0
  131. package/components/switch/switch.vue +5 -8
  132. package/components/switch/types.d.ts +8 -0
  133. package/components/switch/types.js +4 -0
  134. package/components/switch/types.ts +12 -0
  135. package/components/tab/tab.vue +2 -0
  136. package/components/tab/types.d.ts +8 -0
  137. package/components/tab/types.js +4 -0
  138. package/components/tab/types.ts +12 -0
  139. package/components/textarea/textarea.scss +10 -0
  140. package/components/textarea/textarea.vue +17 -9
  141. package/components/textarea/types.d.ts +12 -0
  142. package/components/textarea/types.js +4 -0
  143. package/components/textarea/types.ts +18 -0
  144. package/components/upload/composable.d.ts +24 -0
  145. package/components/upload/composable.js +173 -0
  146. package/components/upload/composable.ts +228 -0
  147. package/components/upload/media-upload.scss +12 -0
  148. package/components/upload/media-upload.vue +250 -0
  149. package/components/upload/types.d.ts +29 -0
  150. package/components/upload/types.js +4 -0
  151. package/components/upload/types.ts +38 -0
  152. package/composable/component-name.d.ts +8 -0
  153. package/composable/component-name.js +11 -4
  154. package/composable/component-name.ts +8 -0
  155. package/composable/dialog.d.ts +40 -0
  156. package/composable/dialog.js +96 -0
  157. package/composable/dialog.ts +113 -0
  158. package/composable/index.d.ts +5 -0
  159. package/composable/index.js +5 -0
  160. package/composable/index.ts +5 -0
  161. package/composable/message-box.d.ts +45 -28
  162. package/composable/message-box.js +68 -53
  163. package/composable/message-box.ts +101 -36
  164. package/composable/model.d.ts +8 -0
  165. package/composable/model.js +23 -0
  166. package/composable/model.ts +27 -0
  167. package/composable/page.d.ts +41 -0
  168. package/composable/page.js +25 -0
  169. package/composable/page.ts +34 -0
  170. package/configs/index.d.ts +24 -19
  171. package/configs/index.js +38 -35
  172. package/configs/index.ts +19 -0
  173. package/easyCom.d.ts +6 -6
  174. package/easyCom.js +19 -31
  175. package/easyCom.ts +4 -4
  176. package/globals.d.ts +93 -33
  177. package/globals.js +1 -0
  178. package/globals.ts +118 -0
  179. package/index.d.ts +3 -2
  180. package/index.js +2 -2
  181. package/index.ts +3 -2
  182. package/init.d.ts +11 -6
  183. package/init.js +84 -14
  184. package/init.ts +86 -1
  185. package/package.json +9 -9
  186. package/styles/var/component.scss +1 -0
  187. package/utils/date.d.ts +14 -19
  188. package/utils/date.js +77 -87
  189. package/utils/freezeDeep.js +7 -7
  190. package/utils/price.d.ts +15 -18
  191. package/utils/price.js +36 -37
  192. package/utils/upload.d.ts +1 -0
  193. package/utils/upload.js +8 -0
  194. package/utils/upload.ts +12 -0
  195. package/utils/windowInfo.d.ts +1 -9
  196. package/utils/windowInfo.js +10 -17
  197. package/utils/round.d.ts +0 -2
  198. package/utils/round.js +0 -13
  199. 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: #999;
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
- margin-top: 20rpx;
123
- margin-bottom: 12rpx;
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,6 @@
1
+ export type ConfigurableFormItemProps = {
2
+ /** 表单显示类型 */
3
+ type?: 'line' | 'next' | 'block';
4
+ };
5
+ export declare let formItemProps: ConfigurableFormItemProps;
6
+ export declare const setDefaultFormItemProps: (props?: ConfigurableFormItemProps) => void;
@@ -0,0 +1,4 @@
1
+ export let formItemProps = {};
2
+ export const setDefaultFormItemProps = (props = {}) => {
3
+ formItemProps = props;
4
+ };
@@ -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
- :preview-list="previewList"
4
+ :show-menu-by-longpress="showMenuByLongpress"
5
+ :webp="webp"
6
+ :lazy-load="lazyLoad"
5
7
  :class="[...classNames]"
6
8
  :mode="mode"
7
- @click="preview"
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
- previewList?: string[];
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
- previewList: () => [],
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 preview = () => {
49
+ const previewList = computed(() => {
46
50
  if (!props.preview) {
47
- emit('click');
48
- return;
51
+ return [];
49
52
  }
53
+ if (props.preview === true) {
54
+ return [props.src];
55
+ }
56
+ return props.preview;
57
+ });
50
58
 
51
- if (props.previewList.length > 0) {
52
- uni.previewImage({
53
- current: props.src,
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: [props.src],
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,4 @@
1
+ export let imageProps = {};
2
+ export const setDefaultImageProps = (props = {}) => {
3
+ imageProps = props;
4
+ };
@@ -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
+ };
@@ -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';
@@ -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';
@@ -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';
@@ -0,0 +1,9 @@
1
+ @use 'sass:map';
2
+ @use '../../styles/utils' as *;
3
+
4
+ // 可配置的变量
5
+ $input: () !default;
6
+ $input-default: (
7
+ height: null,
8
+ );
9
+ $input: map.merge($input-default, $input);
@@ -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
- width: 100%;
118
- height: 100%;
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: 140,
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,8 @@
1
+ export let inputProps = {};
2
+ export const setDefaultInputProps = (props = {}) => {
3
+ inputProps = props;
4
+ };
5
+ export let passwordInputProps = {};
6
+ export const setDefaultPasswordInputProps = (props = {}) => {
7
+ passwordInputProps = props;
8
+ };
@@ -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 v-if="hasFooter" #footer>
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?: UniApp.PromiseResolvers<unknown>): void;
84
- (e: 'reach-bottom', payload?: UniApp.PromiseResolvers<unknown>): void;
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
- // const { promise, resolve, reject } = Promise.withResolvers();
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
- // const { promise, resolve, reject } = Promise.withResolvers();
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,6 @@
1
+ export type ConfigurableListPageProps = {
2
+ /** 页面头部样式,主要用于控制导航栏字体颜色 */
3
+ theme?: 'light' | 'dark';
4
+ };
5
+ export declare let listPageProps: ConfigurableListPageProps;
6
+ export declare const setDefaultListPageProps: (props?: ConfigurableListPageProps) => void;
@@ -0,0 +1,4 @@
1
+ export let listPageProps = {};
2
+ export const setDefaultListPageProps = (props = {}) => {
3
+ listPageProps = props;
4
+ };
@@ -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
+ };
@@ -8,5 +8,6 @@ $load-more-default: (
8
8
  space: 40rpx,
9
9
  color: #ccc,
10
10
  font-size: UTILS__GLOBAL_VAR(font-size, normal),
11
+ observer-height: 50vh,
11
12
  );
12
13
  $load-more: map.merge($load-more-default, $load-more);
@@ -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']">{{ endTitle }}</view>
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,6 @@
1
+ export type ConfigurableLoadMoreProps = {
2
+ /** 到最后一页时文本 */
3
+ endTitle?: string;
4
+ };
5
+ export declare let loadMoreProps: ConfigurableLoadMoreProps;
6
+ export declare const setDefaultLoadMoreProps: (props?: ConfigurableLoadMoreProps) => void;
@@ -0,0 +1,4 @@
1
+ export let loadMoreProps = {};
2
+ export const setDefaultLoadMoreProps = (props = {}) => {
3
+ loadMoreProps = props;
4
+ };
@@ -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
+ };