@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
@@ -4,12 +4,12 @@
4
4
  <page-header-cpn
5
5
  v-if="hasHeader"
6
6
  fixed
7
+ :center="centerTitle"
7
8
  :theme="theme"
8
9
  :title="title"
10
+ :nav-type="isTabbar ? 0 : undefined"
9
11
  >
10
- <template #extra>
11
- <slot name="header-extra"></slot>
12
- </template>
12
+ <template #[extraSlot]><slot name="header-extra" /></template>
13
13
  </page-header-cpn>
14
14
  </slot>
15
15
 
@@ -19,7 +19,7 @@
19
19
  :has-header="hasHeader"
20
20
  :has-footer="hasFooter && !!$slots.footer"
21
21
  :use-scroll="useScroll"
22
- :is-tab-page="tabbar"
22
+ :is-tab-page="isTabbar"
23
23
  :enable-refresh="enableRefresh"
24
24
  :refreshing="refreshing"
25
25
  @scroll="$emit('scroll', $event)"
@@ -35,12 +35,12 @@
35
35
 
36
36
  <page-footer-cpn
37
37
  v-if="hasFooter && $slots.footer"
38
- :is-tab-page="tabbar"
38
+ :is-tab-page="isTabbar"
39
39
  >
40
40
  <slot name="footer"></slot>
41
41
  </page-footer-cpn>
42
42
 
43
- <message-box-cpn ref="pageMessageBoxRef" />
43
+ <message-box-cpn ref="messageBoxRef" />
44
44
 
45
45
  <loading-cpn
46
46
  v-if="loading"
@@ -50,7 +50,7 @@
50
50
  </template>
51
51
 
52
52
  <script lang="ts" setup>
53
- import { computed, provide, ref } from 'vue';
53
+ import { computed, provide, ref, useSlots } from 'vue';
54
54
  import useClassNames from '../../composable/component-name';
55
55
  import LoadingCpn from '../loading/loading.vue';
56
56
  import MessageBoxCpn from '../message-box/message-box.vue';
@@ -64,7 +64,9 @@ import {
64
64
  navBarTopOffset,
65
65
  safeAreaInsetBottom,
66
66
  } from '../../utils/windowInfo';
67
- import { useMessageBox } from '../../composable/message-box';
67
+ import { useMessageBoxComponent } from '../../composable/message-box';
68
+ import { pageProps } from './types';
69
+ import { useCurrentPageRoute } from '../../composable/page';
68
70
 
69
71
  defineOptions({
70
72
  options: {
@@ -75,9 +77,33 @@ defineOptions({
75
77
 
76
78
  const classNames = useClassNames('page');
77
79
 
80
+ type _Slots = {
81
+ default: () => void;
82
+ /** 导航栏 */
83
+ header: () => void;
84
+ /** 导航栏额外内容 */
85
+ 'header-extra': () => void;
86
+ /** 页面主体 */
87
+ body: () => void;
88
+ /** 固定布局内容插槽 */
89
+ fixed: () => void;
90
+ /** 底部操作栏 */
91
+ footer: () => void;
92
+ };
93
+
94
+ defineSlots<_Slots>();
95
+
96
+ // 这些值用于插槽的透传
97
+ // 注意:小程序无法实现动态插槽,组件在初始化时就确定了哪些插槽在用,哪些没用使用
98
+ // 后续无论如何更新都无法改变这个行为,但插槽的内容可以动态更新
99
+ const $slots = useSlots();
100
+ const extraSlot = $slots['header-extra'] ? 'extra' : 'unused_slot';
101
+
78
102
  type _Props = {
79
103
  /** 页面标题 */
80
104
  title?: string;
105
+ /** 导航栏标题是否居中显示 */
106
+ centerTitle?: boolean;
81
107
  /** 页面是否有导航栏,当为 true 时,页面主体部分会为导航栏留出空间;否则内容部分会显示在屏幕顶部 */
82
108
  hasHeader?: boolean;
83
109
  /**
@@ -104,8 +130,9 @@ type _Props = {
104
130
  tabbar?: boolean;
105
131
  };
106
132
 
107
- withDefaults(defineProps<_Props>(), {
133
+ const props = withDefaults(defineProps<_Props>(), {
108
134
  title: '',
135
+ centerTitle: undefined,
109
136
  hasHeader: true,
110
137
  hasFooter: true,
111
138
  useScroll: true,
@@ -115,9 +142,14 @@ withDefaults(defineProps<_Props>(), {
115
142
  pageSize: 0,
116
143
  showLoadMore: true,
117
144
  theme: 'light',
118
- tabbar: false,
145
+ tabbar: undefined,
146
+ ...pageProps,
119
147
  });
120
148
 
149
+ const { isTabbarPage } = useCurrentPageRoute();
150
+
151
+ const isTabbar = computed(() => props.tabbar ?? isTabbarPage.value);
152
+
121
153
  defineEmits<{
122
154
  (event: 'scroll', value: ScrollEvent): void;
123
155
  (event: 'refresh'): void;
@@ -125,8 +157,9 @@ defineEmits<{
125
157
  }>();
126
158
 
127
159
  const pageBodyRef = ref<InstanceType<typeof PageBodyCpn>>();
128
- const pageMessageBoxRef = ref<InstanceType<typeof MessageBoxCpn>>();
129
- provide('ecolovo/page/messageBoxRef', pageMessageBoxRef);
160
+ const { messageBoxRef, show, showConfirm, showMessageBox } =
161
+ useMessageBoxComponent();
162
+ provide('ecolovo/page/messageBoxRef', messageBoxRef);
130
163
 
131
164
  /**
132
165
  * 滚动到顶部
@@ -146,8 +179,6 @@ const scrollIntoView = (viewId: string, animation = true) => {
146
179
  pageBodyRef.value?.scrollIntoView(viewId, animation);
147
180
  };
148
181
 
149
- const { show, showConfirm, showMessageBox } = useMessageBox(pageMessageBoxRef);
150
-
151
182
  const inlineStyle = computed(() => {
152
183
  return [
153
184
  // 顶部安全区高度
@@ -0,0 +1,16 @@
1
+ export type ConfigurablePageProps = {
2
+ /** 是否使用scroll-view */
3
+ useScroll?: boolean;
4
+ /** 页面头部样式,主要用于控制导航栏字体颜色 */
5
+ theme?: 'light' | 'dark';
6
+ };
7
+ export declare let pageProps: ConfigurablePageProps;
8
+ export declare const setDefaultPageProps: (props?: ConfigurablePageProps) => void;
9
+ export type ConfigurablePageHeaderProps = {
10
+ /** 导航栏标题是否居中显示 */
11
+ center?: boolean;
12
+ /** 页面头部样式,主要用于控制导航栏字体颜色 */
13
+ theme?: 'light' | 'dark';
14
+ };
15
+ export declare let pageHeaderProps: ConfigurablePageHeaderProps;
16
+ export declare const setDefaultPageHeaderProps: (props?: ConfigurablePageHeaderProps) => void;
@@ -0,0 +1,8 @@
1
+ export let pageProps = {};
2
+ export const setDefaultPageProps = (props = {}) => {
3
+ pageProps = props;
4
+ };
5
+ export let pageHeaderProps = {};
6
+ export const setDefaultPageHeaderProps = (props = {}) => {
7
+ pageHeaderProps = props;
8
+ };
@@ -0,0 +1,27 @@
1
+ export type ConfigurablePageProps = {
2
+ /** 是否使用scroll-view */
3
+ useScroll?: boolean;
4
+ /** 页面头部样式,主要用于控制导航栏字体颜色 */
5
+ theme?: 'light' | 'dark';
6
+ };
7
+
8
+ export let pageProps: ConfigurablePageProps = {};
9
+
10
+ export const setDefaultPageProps = (props: ConfigurablePageProps = {}) => {
11
+ pageProps = props;
12
+ };
13
+
14
+ export type ConfigurablePageHeaderProps = {
15
+ /** 导航栏标题是否居中显示 */
16
+ center?: boolean;
17
+ /** 页面头部样式,主要用于控制导航栏字体颜色 */
18
+ theme?: 'light' | 'dark';
19
+ };
20
+
21
+ export let pageHeaderProps: ConfigurablePageHeaderProps = {};
22
+
23
+ export const setDefaultPageHeaderProps = (
24
+ props: ConfigurablePageHeaderProps = {}
25
+ ) => {
26
+ pageHeaderProps = props;
27
+ };
@@ -1,9 +1,8 @@
1
1
  <template>
2
2
  <popup-cpn
3
3
  ref="popupRef"
4
- :model-value="modelValue"
4
+ v-model="isShow"
5
5
  :class="[...classNames, $style['PickerPopup']]"
6
- @update:model-value="emit('update:modelValue', $event)"
7
6
  >
8
7
  <template #content>
9
8
  <popup-content-cpn
@@ -112,11 +111,18 @@ defineOptions({
112
111
 
113
112
  const classNames = useClassNames('picker-popup');
114
113
 
114
+ type _Slots = {
115
+ title: () => void;
116
+ };
117
+
118
+ defineSlots<_Slots>();
119
+
120
+ /** 是否可见 */
121
+ const isShow = defineModel<boolean>();
122
+
115
123
  type _Option = Record<string, string | number>;
116
124
 
117
125
  type _Props = {
118
- /** 是否可见 */
119
- modelValue?: boolean;
120
126
  /** 标题 */
121
127
  title?: string;
122
128
  /** 副标题 */
@@ -142,7 +148,6 @@ type _Props = {
142
148
  };
143
149
 
144
150
  const props = withDefaults(defineProps<_Props>(), {
145
- modelValue: false,
146
151
  title: '',
147
152
  subTitle: '',
148
153
  searchable: false,
@@ -157,7 +162,6 @@ const props = withDefaults(defineProps<_Props>(), {
157
162
  });
158
163
 
159
164
  const emit = defineEmits<{
160
- (e: 'update:modelValue', val: boolean): void;
161
165
  (e: 'confirm', val: _Option | _Option[]): void;
162
166
  (e: 'search', text: string): void;
163
167
  (e: 'load-more'): void;
@@ -30,6 +30,7 @@ import { computed, inject, ref } from 'vue';
30
30
  import useClassNames from '../../composable/component-name';
31
31
  import SelectorCpn from '../selector/selector.vue';
32
32
  import PickerPopupCpn from './picker-popup.vue';
33
+ import { pickerProps } from './types';
33
34
 
34
35
  defineOptions({
35
36
  options: {
@@ -40,6 +41,12 @@ defineOptions({
40
41
 
41
42
  const classNames = useClassNames('picker');
42
43
 
44
+ type _Slots = {
45
+ popup: () => void;
46
+ };
47
+
48
+ defineSlots<_Slots>();
49
+
43
50
  type _Option = Record<string, string | number>;
44
51
  type _Value = string | number | boolean | Record<string, unknown>;
45
52
 
@@ -80,6 +87,7 @@ const props = withDefaults(defineProps<_Props>(), {
80
87
  options: () => [],
81
88
  multiple: false,
82
89
  joinText: '、',
90
+ ...pickerProps,
83
91
  });
84
92
 
85
93
  const emit = defineEmits<{
@@ -0,0 +1,14 @@
1
+ export type ConfigurablePickerProps = {
2
+ /** 选项唯一标识 */
3
+ valueKey?: string;
4
+ /** 选项标签字段 */
5
+ labelKey?: string;
6
+ /** 占位文本 */
7
+ placeholder?: string;
8
+ /** 弹出框标题 */
9
+ popupTitle?: string;
10
+ /** 多选时选项拼接的分隔符 */
11
+ joinText?: string;
12
+ };
13
+ export declare let pickerProps: ConfigurablePickerProps;
14
+ export declare const setDefaultPickerProps: (props?: ConfigurablePickerProps) => void;
@@ -0,0 +1,4 @@
1
+ export let pickerProps = {};
2
+ export const setDefaultPickerProps = (props = {}) => {
3
+ pickerProps = props;
4
+ };
@@ -0,0 +1,18 @@
1
+ export type ConfigurablePickerProps = {
2
+ /** 选项唯一标识 */
3
+ valueKey?: string;
4
+ /** 选项标签字段 */
5
+ labelKey?: string;
6
+ /** 占位文本 */
7
+ placeholder?: string;
8
+ /** 弹出框标题 */
9
+ popupTitle?: string;
10
+ /** 多选时选项拼接的分隔符 */
11
+ joinText?: string;
12
+ };
13
+
14
+ export let pickerProps: ConfigurablePickerProps = {};
15
+
16
+ export const setDefaultPickerProps = (props: ConfigurablePickerProps = {}) => {
17
+ pickerProps = props;
18
+ };
@@ -34,7 +34,7 @@
34
34
 
35
35
  <!-- loading 动画 -->
36
36
  <view v-if="loading" :class="$style['PopoverContent--loading']">
37
- <icon-cpn icon="loading-dot-spinner"></icon-cpn>
37
+ <icon-cpn icon="loading-dot-spinner" spinning></icon-cpn>
38
38
  </view>
39
39
  </view>
40
40
  </template>
@@ -57,6 +57,15 @@ defineOptions({
57
57
 
58
58
  const classNames = useClassNames('popover-content');
59
59
 
60
+ type _Slots = {
61
+ custom: () => void;
62
+ header: () => void;
63
+ default: () => void;
64
+ footer: () => void;
65
+ };
66
+
67
+ defineSlots<_Slots>();
68
+
60
69
  type _Props = {
61
70
  /** 弹出框位置,可选值为 top、bottom、left、right、center */
62
71
  position?: 'top' | 'bottom' | 'left' | 'right' | 'center';
@@ -33,20 +33,19 @@ defineOptions({
33
33
 
34
34
  const classNames = useClassNames('popover-mask');
35
35
 
36
+ const isShow = defineModel<boolean>({ required: true });
37
+
36
38
  type _Props = {
37
- /** v-model 绑定值,控制弹出框是否可见 */
38
- modelValue?: boolean;
39
39
  /** 是否模态弹出框 */
40
40
  modal?: boolean;
41
41
  };
42
42
 
43
43
  const props = withDefaults(defineProps<_Props>(), {
44
- modelValue: false,
45
44
  modal: false,
46
45
  });
47
46
 
48
47
  const emit = defineEmits<{
49
- (e: 'update:modelValue', val: boolean): void;
48
+ (e: 'mask'): void;
50
49
  (e: 'close'): void;
51
50
  (e: 'closed'): void;
52
51
  }>();
@@ -70,7 +69,7 @@ const close = (onClosed?: VoidFunction) => {
70
69
 
71
70
  setTimeout(() => {
72
71
  onClosed?.();
73
- emit('update:modelValue', false);
72
+ isShow.value = false;
74
73
  emit('closed');
75
74
  }, 300);
76
75
  };
@@ -78,6 +77,7 @@ const close = (onClosed?: VoidFunction) => {
78
77
  /** 点击遮罩层 */
79
78
  const onMask = () => {
80
79
  if (props.modal) return;
80
+ emit('mask');
81
81
  close();
82
82
  };
83
83
 
@@ -1,49 +1,34 @@
1
1
  <template>
2
- <view :class="[...classNames, $style['Popover']]">
2
+ <view v-if="isShow" :class="[...classNames, $style['Popover']]">
3
3
  <popover-mask-cpn
4
- v-if="modelValue"
5
4
  ref="maskRef"
6
- :model-value="modelValue"
5
+ v-model="isShow"
7
6
  :modal="modal || loading"
8
- @update:model-value="$emit('update:modelValue', $event)"
7
+ @mask="onConfirm()"
9
8
  @close="$emit('close')"
10
9
  @closed="$emit('closed')"
11
10
  >
12
11
  <popover-content-cpn
13
- v-if="$slots.custom"
14
12
  :position="position"
15
13
  :fullscreen="fullscreen"
16
14
  :loading="loading"
17
15
  >
18
- <template #custom>
19
- <slot name="custom"></slot>
20
- </template>
21
- </popover-content-cpn>
22
- <popover-content-cpn
23
- v-else
24
- :position="position"
25
- :fullscreen="fullscreen"
26
- :loading="loading"
27
- >
28
- <template v-if="$slots.header" #header>
29
- <slot name="header"></slot>
30
- </template>
31
-
16
+ <template #[customSlot]><slot name="custom" /></template>
17
+ <template #[headerSlot]><slot name="header" /></template>
32
18
  <slot></slot>
33
-
34
- <template v-if="$slots.footer" #footer>
35
- <slot name="footer"></slot>
36
- </template>
19
+ <template #[footerSlot]><slot name="footer" /></template>
37
20
  </popover-content-cpn>
38
21
  </popover-mask-cpn>
39
22
  </view>
40
23
  </template>
41
24
 
42
25
  <script lang="ts" setup>
43
- import { ref } from 'vue';
26
+ import { ref, useSlots } from 'vue';
44
27
  import useClassNames from '../../composable/component-name';
45
28
  import PopoverContentCpn from './popover-content.vue';
46
29
  import PopoverMaskCpn from './popover-mask.vue';
30
+ import { popoverProps } from './types';
31
+ import { useAwaitableDialog, useModelValue } from '../../composable';
47
32
 
48
33
  defineOptions({
49
34
  options: {
@@ -54,9 +39,30 @@ defineOptions({
54
39
 
55
40
  const classNames = useClassNames('popover');
56
41
 
42
+ type _Slots = {
43
+ custom: () => void;
44
+ header: () => void;
45
+ default: () => void;
46
+ footer: () => void;
47
+ };
48
+
49
+ defineSlots<_Slots>();
50
+
51
+ // 这些值用于插槽的透传
52
+ // 注意:小程序无法实现动态插槽,组件在初始化时就确定了哪些插槽在用,哪些没用使用
53
+ // 后续无论如何更新都无法改变这个行为,但插槽的内容可以动态更新
54
+ const $slots = useSlots();
55
+ const customSlot = $slots.custom ? 'custom' : 'unused_slot';
56
+ const headerSlot = $slots.header ? 'header' : 'unused_slot';
57
+ const footerSlot = $slots.footer ? 'footer' : 'unused_slot';
58
+
59
+ const isShow_ = defineModel<boolean>();
60
+ /** 是否可见 */
61
+ const isShow = useModelValue(isShow_);
62
+
63
+ const { show, onConfirm } = useAwaitableDialog(isShow);
64
+
57
65
  type _Props = {
58
- /** v-model 绑定值,控制弹出框是否可见 */
59
- modelValue?: boolean;
60
66
  /** 弹出框位置,可选值为 top、bottom、left、right、center */
61
67
  position?: 'top' | 'bottom' | 'left' | 'right' | 'center';
62
68
  /** 是否占满屏幕 */
@@ -68,15 +74,14 @@ type _Props = {
68
74
  };
69
75
 
70
76
  withDefaults(defineProps<_Props>(), {
71
- modelValue: false,
72
77
  position: 'bottom',
73
78
  fullscreen: false,
74
79
  modal: false,
75
80
  loading: false,
81
+ ...popoverProps,
76
82
  });
77
83
 
78
84
  defineEmits<{
79
- (e: 'update:modelValue', val: boolean): void;
80
85
  (e: 'close'): void;
81
86
  (e: 'closed'): void;
82
87
  }>();
@@ -88,7 +93,7 @@ const close = (onClosed?: VoidFunction) => {
88
93
  maskRef.value?.close(onClosed);
89
94
  };
90
95
 
91
- defineExpose({ close });
96
+ defineExpose({ show, close });
92
97
  </script>
93
98
 
94
99
  <style lang="scss" module>
@@ -0,0 +1,10 @@
1
+ export type ConfigurablePopoverProps = {
2
+ /** 弹出框位置,可选值为 top、bottom、left、right、center */
3
+ position?: 'top' | 'bottom' | 'left' | 'right' | 'center';
4
+ /** 是否占满屏幕 */
5
+ fullscreen?: boolean;
6
+ /** 是否模态弹出框 */
7
+ modal?: boolean;
8
+ };
9
+ export declare let popoverProps: ConfigurablePopoverProps;
10
+ export declare const setDefaultPopoverProps: (props?: ConfigurablePopoverProps) => void;
@@ -0,0 +1,4 @@
1
+ export let popoverProps = {};
2
+ export const setDefaultPopoverProps = (props = {}) => {
3
+ popoverProps = props;
4
+ };
@@ -0,0 +1,16 @@
1
+ export type ConfigurablePopoverProps = {
2
+ /** 弹出框位置,可选值为 top、bottom、left、right、center */
3
+ position?: 'top' | 'bottom' | 'left' | 'right' | 'center';
4
+ /** 是否占满屏幕 */
5
+ fullscreen?: boolean;
6
+ /** 是否模态弹出框 */
7
+ modal?: boolean;
8
+ };
9
+
10
+ export let popoverProps: ConfigurablePopoverProps = {};
11
+
12
+ export const setDefaultPopoverProps = (
13
+ props: ConfigurablePopoverProps = {}
14
+ ) => {
15
+ popoverProps = props;
16
+ };
@@ -3,32 +3,33 @@
3
3
  <popover-content-cpn position="bottom" :loading="loading">
4
4
  <!-- 内容上方标题 -->
5
5
  <template #header>
6
- <slot v-if="$slots.header" name="header"></slot>
7
- <view
8
- v-else-if="title || showClose"
9
- :class="$style['PopupContent--header']"
10
- >
6
+ <slot name="header">
11
7
  <view
12
- :class="[
13
- $style['PopupContent--title'],
14
- {
15
- [$style['PopupContent--title-center']]:
16
- centerTitle,
17
- },
18
- ]"
8
+ v-if="title || showClose"
9
+ :class="$style['PopupContent--header']"
19
10
  >
20
- <slot name="title">
21
- <text>{{ title }}</text>
22
- </slot>
11
+ <view
12
+ :class="[
13
+ $style['PopupContent--title'],
14
+ {
15
+ [$style['PopupContent--title-center']]:
16
+ centerTitle,
17
+ },
18
+ ]"
19
+ >
20
+ <slot name="title">
21
+ <text>{{ title }}</text>
22
+ </slot>
23
+ </view>
24
+ <view
25
+ v-if="showClose"
26
+ :class="$style['PopupContent--close']"
27
+ @click="$emit('close')"
28
+ >
29
+ <icon-cpn icon="close" tap-size="80rpx" />
30
+ </view>
23
31
  </view>
24
- <view
25
- v-if="showClose"
26
- :class="$style['PopupContent--close']"
27
- @click="$emit('close')"
28
- >
29
- <icon-cpn icon="close" tap-size="80rpx" />
30
- </view>
31
- </view>
32
+ </slot>
32
33
  </template>
33
34
 
34
35
  <!-- 内容区域 -->
@@ -36,29 +37,35 @@
36
37
 
37
38
  <!-- 内容下方操作按钮 -->
38
39
  <template #footer>
39
- <slot v-if="$slots.footer" name="footer"></slot>
40
- <view
41
- v-else-if="cancel || confirm"
42
- :class="$style['PopupContent--footer']"
43
- >
44
- <view v-if="cancel" :class="$style['PopupContent--button']">
45
- <slot name="cancel">
46
- <button-cpn plain @click="$emit('cancel')">
47
- {{ cancel }}
48
- </button-cpn>
49
- </slot>
50
- </view>
40
+ <slot name="footer">
51
41
  <view
52
- v-if="confirm"
53
- :class="$style['PopupContent--button']"
42
+ v-if="
43
+ cancel || confirm || $slots.cancel || $slots.confirm
44
+ "
45
+ :class="$style['PopupContent--footer']"
54
46
  >
55
- <slot name="confirm">
56
- <button-cpn @click="$emit('confirm')">
57
- {{ confirm }}
58
- </button-cpn>
59
- </slot>
47
+ <view
48
+ v-if="cancel || $slots.cancel"
49
+ :class="$style['PopupContent--button']"
50
+ >
51
+ <slot name="cancel">
52
+ <button-cpn plain @click="$emit('cancel')">
53
+ {{ cancel }}
54
+ </button-cpn>
55
+ </slot>
56
+ </view>
57
+ <view
58
+ v-if="confirm || $slots.confirm"
59
+ :class="$style['PopupContent--button']"
60
+ >
61
+ <slot name="confirm">
62
+ <button-cpn @click="$emit('confirm')">
63
+ {{ confirm }}
64
+ </button-cpn>
65
+ </slot>
66
+ </view>
60
67
  </view>
61
- </view>
68
+ </slot>
62
69
  </template>
63
70
  </popover-content-cpn>
64
71
  </view>
@@ -79,6 +86,17 @@ defineOptions({
79
86
 
80
87
  const classNames = useClassNames('popup-content');
81
88
 
89
+ type _Slots = {
90
+ header: () => void;
91
+ title: () => void;
92
+ default: () => void;
93
+ footer: () => void;
94
+ cancel: () => void;
95
+ confirm: () => void;
96
+ };
97
+
98
+ defineSlots<_Slots>();
99
+
82
100
  type _Props = {
83
101
  /** 是否显示 loading 动画 */
84
102
  loading?: boolean;