@ecolovo/uniapp-components 1.0.10 → 2.0.1

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 (130) hide show
  1. package/README.md +202 -66
  2. package/components/aspect/aspect.vue +24 -15
  3. package/components/badge/badge.scss +20 -0
  4. package/components/badge/badge.vue +49 -40
  5. package/components/button/button.scss +15 -0
  6. package/components/button/button.vue +121 -177
  7. package/components/checkbox/checkbox.scss +10 -0
  8. package/components/checkbox/checkbox.vue +118 -146
  9. package/components/checkbox-group/checkbox-group.vue +79 -85
  10. package/components/checkbox-group2/checkbox-group2.vue +111 -107
  11. package/components/checkbox-group2/checkbox2.vue +104 -0
  12. package/components/data-list/data-list.scss +9 -0
  13. package/components/data-list/data-list.vue +70 -79
  14. package/components/date-picker/date-picker-view.vue +125 -124
  15. package/components/date-picker/date-picker.vue +145 -146
  16. package/components/dialog/dialog-content.vue +39 -47
  17. package/components/dialog/dialog.scss +11 -0
  18. package/components/dialog/dialog.vue +125 -138
  19. package/components/dropdown/dropdown.scss +11 -0
  20. package/components/dropdown/dropdown.vue +55 -97
  21. package/components/empty/empty.scss +14 -0
  22. package/components/empty/empty.vue +42 -41
  23. package/components/flex/flex.vue +45 -54
  24. package/components/form/form.vue +29 -24
  25. package/components/form-item/form-item.scss +11 -0
  26. package/components/form-item/form-item.vue +43 -40
  27. package/components/icon/icon.vue +70 -85
  28. package/components/image/image.vue +35 -38
  29. package/components/input/input.vue +65 -79
  30. package/components/input/password-input.vue +34 -42
  31. package/components/list-page/list-page.vue +73 -99
  32. package/components/load-more/load-more.scss +12 -0
  33. package/components/load-more/load-more.vue +29 -29
  34. package/components/loading/animations/loading-animation1.vue +8 -8
  35. package/components/loading/animations/loading-animation2.vue +8 -9
  36. package/components/loading/animations/loading-animation3.vue +11 -11
  37. package/components/loading/animations/loading-animation4.vue +8 -8
  38. package/components/loading/loading.vue +19 -20
  39. package/components/message-box/message-box.vue +59 -41
  40. package/components/number-dialog/number-dialog.scss +9 -0
  41. package/components/number-dialog/number-dialog.vue +209 -204
  42. package/components/number-input/number-input.scss +9 -0
  43. package/components/number-input/number-input.vue +233 -232
  44. package/components/numpad/numpad.scss +9 -0
  45. package/components/numpad/numpad.vue +133 -150
  46. package/components/page/page-body.scss +15 -0
  47. package/components/page/page-body.vue +137 -119
  48. package/components/page/page-footer.scss +13 -0
  49. package/components/page/page-footer.vue +31 -33
  50. package/components/page/page-header.scss +17 -0
  51. package/components/page/page-header.vue +89 -94
  52. package/components/page/page.scss +9 -0
  53. package/components/page/page.vue +105 -81
  54. package/components/picker/picker-popup.vue +218 -209
  55. package/components/picker/picker.vue +99 -104
  56. package/components/popover/popover-content.vue +54 -63
  57. package/components/popover/popover-mask.vue +63 -63
  58. package/components/popover/popover.scss +28 -0
  59. package/components/popover/popover.vue +49 -47
  60. package/components/popup/popup-content.vue +49 -53
  61. package/components/popup/popup.scss +11 -0
  62. package/components/popup/popup.vue +117 -132
  63. package/components/price/price.scss +20 -0
  64. package/components/price/price.vue +31 -42
  65. package/components/search/search.scss +12 -0
  66. package/components/search/search.vue +93 -117
  67. package/components/searching/searching.vue +33 -40
  68. package/components/selector/selector.vue +43 -48
  69. package/components/switch/switch.scss +12 -0
  70. package/components/switch/switch.vue +99 -96
  71. package/components/tab/tab.scss +19 -0
  72. package/components/tab/tab.vue +151 -145
  73. package/components/textarea/textarea.vue +104 -101
  74. package/composable/component-name.d.ts +2 -0
  75. package/composable/component-name.js +8 -0
  76. package/composable/component-name.ts +10 -0
  77. package/configs/index.d.ts +25 -10
  78. package/configs/index.js +14 -23
  79. package/configs/index.ts +82 -0
  80. package/easyCom.d.ts +9 -0
  81. package/easyCom.js +1 -2
  82. package/easyCom.ts +31 -0
  83. package/index.d.ts +1 -0
  84. package/index.js +1 -0
  85. package/index.ts +1 -0
  86. package/init.d.ts +4 -7
  87. package/init.js +5 -4
  88. package/init.ts +34 -0
  89. package/package.json +14 -4
  90. package/styles/utils/css-var.scss +12 -15
  91. package/styles/utils/ellipsis.scss +0 -7
  92. package/styles/utils/z-index.scss +1 -1
  93. package/styles/var/component.scss +21 -245
  94. package/utils/date.d.ts +47 -0
  95. package/utils/date.js +23 -43
  96. package/utils/date.ts +153 -0
  97. package/utils/freezeDeep.d.ts +1 -0
  98. package/utils/freezeDeep.js +4 -14
  99. package/utils/freezeDeep.ts +9 -0
  100. package/utils/price.d.ts +24 -0
  101. package/utils/price.js +14 -8
  102. package/utils/price.ts +57 -0
  103. package/utils/round.d.ts +2 -0
  104. package/utils/round.js +2 -14
  105. package/utils/round.ts +11 -0
  106. package/utils/windowInfo.d.ts +24 -0
  107. package/utils/windowInfo.js +8 -36
  108. package/utils/windowInfo.ts +50 -0
  109. package/components/checkbox-group2/checkbox.vue +0 -109
  110. package/components/datetime-picker/datetime-picker-view.vue +0 -209
  111. package/components/datetime-picker/datetime-picker.vue +0 -235
  112. package/components/form/mixin.js +0 -13
  113. package/components/list-page/list-page.js +0 -10
  114. package/components/table/table.vue +0 -112
  115. package/components/time-picker/time-picker-view.vue +0 -127
  116. package/components/time-picker/time-picker.vue +0 -140
  117. package/components/uploader/download.js +0 -81
  118. package/components/uploader/file-uploader.vue +0 -52
  119. package/components/uploader/files.js +0 -225
  120. package/components/uploader/media-uploader.vue +0 -189
  121. package/components/uploader/mixin.js +0 -171
  122. package/components/uploader/uni.js +0 -38
  123. package/components/uploader/upload-button.vue +0 -29
  124. package/components/uploader/uploader copy.vue +0 -547
  125. package/components/uploader/uploader.vue +0 -117
  126. package/mixins/componentName.js +0 -32
  127. package/mixins/listPage.js +0 -1
  128. package/mixins/windowInfo.js +0 -1
  129. package/utils/fileSize.js +0 -39
  130. package/utils/floor.js +0 -20
@@ -1,56 +1,54 @@
1
1
  <template>
2
- <view :class="componentClassNames" :style="styleStr" @touchmove.stop.prevent="doNothing">
2
+ <view :class="[...classNames, $style['PageFooter']]" :style="inlineStyle" @touchmove.stop.prevent="doNothing">
3
3
  <view :class="$style['PageFooter--content']">
4
4
  <slot></slot>
5
5
  </view>
6
6
  </view>
7
7
  </template>
8
8
 
9
- <script>
9
+ <script lang="ts" setup>
10
10
  /**
11
11
  * 页面页脚部分容器组件,不单独使用,通过 page 组件间接引入
12
12
  */
13
+ import { computed } from 'vue';
14
+ import useClassNames from '../../composable/component-name';
15
+ import { safeAreaInsetBottom } from '../../utils/windowInfo';
13
16
 
14
- import componentName from '../../mixins/componentName';
15
- import windowInfoMixin from '../../mixins/windowInfo';
16
-
17
- export default {
18
- name: 'PageFooter',
17
+ defineOptions({
19
18
  options: {
20
- virtualHost: true,
21
19
  styleIsolation: 'shared',
20
+ virtualHost: true,
22
21
  },
23
- mixins: [componentName, windowInfoMixin],
24
- props: {
25
- /** 是否是 tab 页 */
26
- isTabPage: {
27
- type: Boolean,
28
- default: false,
29
- },
30
- },
31
- computed: {
32
- styleStr() {
33
- return `--safe-area-bottom: ${(this.isTabPage ? 0 : this.safeAreaInsetBottom) + 'px'};`;
34
- },
35
- },
36
- methods: {
37
- doNothing() {},
38
- },
22
+ });
23
+
24
+ const classNames = useClassNames('page-footer');
25
+
26
+ type _Props = {
27
+ /** 是否是 tab 页 */
28
+ isTabPage?: boolean;
39
29
  };
30
+
31
+ withDefaults(defineProps<_Props>(), {
32
+ isTabPage: false,
33
+ });
34
+
35
+ const inlineStyle = computed(() => {
36
+ return [
37
+ // 底部安全区高度
38
+ `--safe-area-bottom: ${safeAreaInsetBottom}px;`,
39
+ ].join('');
40
+ });
41
+
42
+ const doNothing = () => {};
40
43
  </script>
41
44
 
42
45
  <style lang="scss" module>
43
- @use '../../styles/index' as *;
46
+ @use '../../styles/utils' as *;
47
+ @use './page-footer' as *;
44
48
 
45
49
  // 定义外部变量
46
- $component-name: 'page-footer';
47
- $component-vars: $page-footer;
48
50
  %external-vars {
49
- @include UTILS__DEFINE_COMPONENT_VARS();
50
- }
51
-
52
- :host {
53
- display: block;
51
+ @include UTILS__DEFINE_COMPONENT_VARS($page-footer, 'page-footer');
54
52
  }
55
53
 
56
54
  .PageFooter {
@@ -62,7 +60,7 @@ $component-vars: $page-footer;
62
60
  background: UTILS__LOCAL_VAR(background);
63
61
  padding-bottom: var(--safe-area-bottom);
64
62
  box-sizing: border-box;
65
- z-index: UTILS__z-index();
63
+ z-index: UTILS__z-index('page-footer');
66
64
  box-shadow: 0 -4rpx 4rpx 4rpx #ccc;
67
65
  }
68
66
 
@@ -0,0 +1,17 @@
1
+ @use 'sass:map';
2
+
3
+ // 可配置的变量
4
+ $page-header: () !default;
5
+ $page-header-default: (
6
+ // 背景色
7
+ background: #fff,
8
+ // 字体大小
9
+ font-size: 28rpx,
10
+ // 标题栏下的额外内容高度,有内容时需设置次值
11
+ extra-height: 0px,
12
+ // 亮色主题下的文本颜色
13
+ color-light: #000,
14
+ // 暗色主题下的文本颜色
15
+ color-dark: #fff
16
+ );
17
+ $page-header: map.merge($page-header-default, $page-header);
@@ -1,7 +1,11 @@
1
1
  <template>
2
2
  <view
3
- :class="[componentClassNames, theme === 'dark' ? $style['PageHeader--dark'] : $style['PageHeader--light']]"
4
- :style="styleStr"
3
+ :class="[
4
+ ...classNames,
5
+ $style['PageHeader'],
6
+ theme === 'dark' ? $style['PageHeader--dark'] : $style['PageHeader--light'],
7
+ ]"
8
+ :style="inlineCssVar"
5
9
  >
6
10
  <!-- 标题栏 -->
7
11
  <view
@@ -24,7 +28,7 @@
24
28
  </navigator>
25
29
  <navigator
26
30
  v-if="hasHome"
27
- :url="homePageUrl"
31
+ :url="homePath"
28
32
  open-type="reLaunch"
29
33
  :class="$style['PageHeader--home-icon']"
30
34
  hover-class="none"
@@ -36,7 +40,7 @@
36
40
  :class="[
37
41
  $style['PageHeader--title'],
38
42
  $style['PageHeader--title-ellipsis'],
39
- { 'PageHeader--title-center': center },
43
+ { [$style['PageHeader--title-center']]: center },
40
44
  ]"
41
45
  >
42
46
  <slot>{{ title }}</slot>
@@ -49,103 +53,94 @@
49
53
  </view>
50
54
  </template>
51
55
 
52
- <script>
56
+ <script lang="ts" setup>
53
57
  /**
54
58
  * 页面头部部分容器组件,不单独使用,通过 page 组件间接引入
55
59
  */
56
-
57
- import componentName from '../../mixins/componentName';
58
- import windowInfoMixin from '../../mixins/windowInfo';
59
- import IconCpn from '../icon/icon.vue';
60
+ import { computed } from 'vue';
61
+ import useClassNames from '../../composable/component-name';
60
62
  import { homePath } from '../../configs';
63
+ import { navBarHeight, navBarTopOffset, menuButtonWidthInCss } from '../../utils/windowInfo';
64
+ import IconCpn from '../icon/icon.vue';
61
65
 
62
- export default {
63
- name: 'PageHeader',
66
+ defineOptions({
64
67
  options: {
65
- virtualHost: true,
66
68
  styleIsolation: 'shared',
69
+ virtualHost: true,
67
70
  },
68
- components: { IconCpn },
69
- mixins: [componentName, windowInfoMixin],
70
- props: {
71
- /** 导航栏标题 */
72
- title: {
73
- type: String,
74
- default: '',
75
- },
76
- /** 导航栏标题是否居中显示 */
77
- center: {
78
- type: Boolean,
79
- default: false,
80
- },
81
- /** 主题,只能是 'light' 和 'dark' 中的一个 */
82
- theme: {
83
- type: String,
84
- default: 'light',
85
- },
86
- /** 导航按钮类型: 0 = 不显示,1 = 返回,2 = 首页,3 = 返回|首页 */
87
- navType: {
88
- type: [Number, null],
89
- default: null,
90
- },
91
- },
92
- computed: {
93
- /** 首页路径 */
94
- homePageUrl() {
95
- return homePath;
96
- },
97
- /** 是否显示返回按钮 */
98
- hasBack() {
99
- // 如果指定了导航按钮类型,则根据类型判断
100
- if (this.navType !== null) return !!(this.navType & 1);
101
- const pages = getCurrentPages();
102
- // 在首页不显示返回按钮
103
- if (this.homePageUrl === '/' + pages[0].route) return false;
104
- // 页面栈只有一个时不显示返回按钮
105
- if (pages.length === 1) return false;
106
- // 其他情况均显示返回按钮
107
- return true;
108
- },
109
- /** 是否显示首页按钮 */
110
- hasHome() {
111
- // 如果指定了导航按钮类型,则根据类型判断
112
- if (this.navType !== null) return !!(this.navType & 2);
113
- const pages = getCurrentPages();
114
- // 在首页不显示返回首页按钮
115
- if (this.homePageUrl === '/' + pages[0].route) return false;
116
- // 页面栈只有一个时显示返回按钮
117
- if (pages.length === 1) return true;
118
- // 其他情况均不显示返回按钮
119
- return false;
120
- },
121
- /** 导航按钮个数 */
122
- iconCount() {
123
- return (this.hasBack ? 1 : 0) + (this.hasHome ? 1 : 0);
124
- },
125
- styleStr() {
126
- return [
127
- `--title-bar-top: ${this.navBarTopOffset}px;`,
128
- `--title-bar-height: ${this.navBarHeight}px;`,
129
- `--title-bar-bottom: ${this.navBarBottomOffset}px;`,
130
- `--menu-button-width: ${this.menuButtonWidth};`,
131
- ].join(' ');
132
- },
133
- },
71
+ });
72
+
73
+ const classNames = useClassNames('page-header');
74
+
75
+ type _Props = {
76
+ /** 图标名 */
77
+ title?: string;
78
+ /** 图标名 */
79
+ center?: boolean;
80
+ /** 图标名 */
81
+ theme?: string;
82
+ /** 图标名 */
83
+ navType?: 0 | 1 | 2 | 3;
134
84
  };
85
+
86
+ const props = withDefaults(defineProps<_Props>(), {
87
+ title: '',
88
+ center: false,
89
+ theme: '',
90
+ navType: undefined,
91
+ });
92
+
93
+ defineEmits<{
94
+ (event: 'click'): void;
95
+ }>();
96
+
97
+ /** 是否显示返回按钮 */
98
+ const hasBack = computed(() => {
99
+ // 如果指定了导航按钮类型,则根据类型判断
100
+ if (props.navType !== undefined) return !!(props.navType & 1);
101
+ const pages = getCurrentPages();
102
+ // 在首页不显示返回按钮
103
+ if (homePath === '/' + pages[0]!.route) return false;
104
+ // 页面栈只有一个时不显示返回按钮
105
+ if (pages.length === 1) return false;
106
+ // 其他情况均显示返回按钮
107
+ return true;
108
+ });
109
+ /** 是否显示首页按钮 */
110
+ const hasHome = computed(() => {
111
+ // 如果指定了导航按钮类型,则根据类型判断
112
+ if (props.navType !== undefined) return !!(props.navType & 2);
113
+ const pages = getCurrentPages();
114
+ // 在首页不显示返回首页按钮
115
+ if (homePath === '/' + pages[0]!.route) return false;
116
+ // 页面栈只有一个时显示返回按钮
117
+ if (pages.length === 1) return true;
118
+ // 其他情况均不显示返回按钮
119
+ return false;
120
+ });
121
+ /** 导航按钮个数 */
122
+ const iconCount = computed(() => {
123
+ return (hasBack.value ? 1 : 0) + (hasHome.value ? 1 : 0);
124
+ });
125
+ const inlineCssVar = computed(() => {
126
+ return [
127
+ // 页面头部上边缘相较于顶部的距离
128
+ `--page-header-top: ${navBarTopOffset}px;`,
129
+ // 页面头部高度
130
+ `--page-header-height: ${navBarHeight}px;`,
131
+ // 小程序胶囊按钮宽度(实际为胶囊按钮最左侧到页面右边的距离)
132
+ `--menu-button-width: ${menuButtonWidthInCss};`,
133
+ ].join(' ');
134
+ });
135
135
  </script>
136
136
 
137
137
  <style lang="scss" module>
138
- @use '../../styles/index' as *;
138
+ @use '../../styles/utils' as *;
139
+ @use './page-header' as *;
139
140
 
140
141
  // 定义外部变量
141
- $component-name: 'page-header';
142
- $component-vars: $page-header;
143
142
  %external-vars {
144
- @include UTILS__DEFINE_COMPONENT_VARS();
145
- }
146
-
147
- :host {
148
- display: block;
143
+ @include UTILS__DEFINE_COMPONENT_VARS($page-header, 'page-header');
149
144
  }
150
145
 
151
146
  .PageHeader {
@@ -156,7 +151,7 @@ $component-vars: $page-header;
156
151
  width: 100%;
157
152
  overflow: hidden; // BFC
158
153
  background: UTILS__LOCAL_VAR(background);
159
- z-index: UTILS__z-index();
154
+ z-index: UTILS__z-index('page-header');
160
155
  }
161
156
 
162
157
  // 亮色主题对应样式
@@ -173,10 +168,10 @@ $component-vars: $page-header;
173
168
  position: relative;
174
169
  font-size: UTILS__LOCAL_VAR(font-size);
175
170
  font-weight: 600;
176
- margin-top: var(--title-bar-top);
171
+ margin-top: var(--page-header-top);
177
172
  width: 100%;
178
- height: var(--title-bar-height);
179
- line-height: var(--title-bar-height);
173
+ height: var(--page-header-height);
174
+ line-height: var(--page-header-height);
180
175
  overflow: hidden;
181
176
  }
182
177
  // 标题栏中的返回按钮
@@ -187,8 +182,8 @@ $component-vars: $page-header;
187
182
  }
188
183
  .PageHeader--back-icon,
189
184
  .PageHeader--home-icon {
190
- width: var(--title-bar-height);
191
- height: var(--title-bar-height);
185
+ width: var(--page-header-height);
186
+ height: var(--page-header-height);
192
187
  display: inline-flex;
193
188
  justify-content: center;
194
189
  align-items: center;
@@ -219,10 +214,10 @@ $component-vars: $page-header;
219
214
  text-overflow: ellipsis;
220
215
  }
221
216
  .PageHeader--title-icon-1 & {
222
- --title-bar-left-padding: calc(var(--title-bar-height) + 20rpx);
217
+ --title-bar-left-padding: calc(var(--page-header-height) + 20rpx);
223
218
  }
224
219
  .PageHeader--title-icon-2 & {
225
- --title-bar-left-padding: calc(var(--title-bar-height) * 2 + 20rpx);
220
+ --title-bar-left-padding: calc(var(--page-header-height) * 2 + 20rpx);
226
221
  }
227
222
  &.PageHeader--title-center {
228
223
  text-align: center;
@@ -0,0 +1,9 @@
1
+ @use 'sass:map';
2
+
3
+ // 可配置的变量
4
+ $page: () !default;
5
+ $page-default: (
6
+ // 页面背景
7
+ background: transparent
8
+ );
9
+ $page: map.merge($page-default, $page);
@@ -1,15 +1,17 @@
1
1
  <template>
2
- <view :class="componentClassNames">
3
- <page-header-cpn v-if="custom" :theme="theme" :title="title">
4
- <template #extra>
5
- <slot name="header-extra"></slot>
6
- </template>
7
- </page-header-cpn>
2
+ <view :class="[...classNames, $style['Page']]" :style="inlineStyle">
3
+ <slot name="header">
4
+ <page-header-cpn v-if="hasHeader" :theme="theme" :title="title">
5
+ <template #extra>
6
+ <slot name="header-extra"></slot>
7
+ </template>
8
+ </page-header-cpn>
9
+ </slot>
8
10
 
9
11
  <page-body-cpn
10
12
  ref="body"
11
- :has-custom-nav="custom"
12
- :has-footer="hasFooter && $slots.footer"
13
+ :has-header="hasHeader"
14
+ :has-footer="hasFooter && !!$slots.footer"
13
15
  :use-scroll="useScroll"
14
16
  :is-tab-page="tabbar"
15
17
  :enable-refresh="enableRefresh"
@@ -29,93 +31,115 @@
29
31
  </view>
30
32
  </template>
31
33
 
32
- <script>
33
- import componentName from '../../mixins/componentName';
34
+ <script lang="ts" setup>
35
+ import { computed } from 'vue';
36
+ import useClassNames from '../../composable/component-name';
34
37
  import LoadingCpn from '../loading/loading.vue';
35
38
  import PageBodyCpn from './page-body.vue';
36
39
  import PageFooterCpn from './page-footer.vue';
37
40
  import PageHeaderCpn from './page-header.vue';
41
+ import {
42
+ menuButtonWidthInCss,
43
+ navBarBottomOffset,
44
+ navBarHeight,
45
+ navBarTopOffset,
46
+ safeAreaInsetBottom,
47
+ } from '../../utils/windowInfo';
38
48
 
39
- export default {
40
- name: 'Page',
49
+ defineOptions({
41
50
  options: {
42
- virtualHost: true,
43
51
  styleIsolation: 'shared',
52
+ virtualHost: true,
44
53
  },
45
- components: { LoadingCpn, PageBodyCpn, PageFooterCpn, PageHeaderCpn },
46
- mixins: [componentName],
47
- props: {
48
- /** 页面标题 */
49
- title: {
50
- type: String,
51
- default: '',
52
- },
53
- /** 是否使用自定义导航栏 */
54
- custom: {
55
- type: Boolean,
56
- default: true,
57
- },
58
- /** 是否使用底部操作栏 */
59
- hasFooter: {
60
- type: Boolean,
61
- default: true,
62
- },
63
- /** 是否使用scroll-view */
64
- useScroll: {
65
- type: Boolean,
66
- default: true,
67
- },
68
- /** 是否启用下拉刷新,仅 useScroll 为 true 时有效 */
69
- enableRefresh: {
70
- type: Boolean,
71
- default: false,
72
- },
73
- /** 是否触发下拉刷新,仅 useScroll 为 true 时有效 */
74
- refreshing: {
75
- type: [Boolean, null],
76
- default: null,
77
- },
78
- /** 页面加载 */
79
- loading: {
80
- type: [Boolean, String],
81
- default: false,
82
- },
83
- /** 分页大小 */
84
- pageSize: {
85
- type: [Number, String],
86
- default: 0,
87
- },
88
- /** 是否显示加载更多 */
89
- showLoadMore: {
90
- type: Boolean,
91
- default: true,
92
- },
93
- /** 页面头部样式,主要用于控制导航栏字体颜色 */
94
- theme: {
95
- type: String,
96
- default: 'light',
97
- },
98
- /** 是否是 tabbar 页面,且 tabbar 未隐藏 */
99
- tabbar: {
100
- type: Boolean,
101
- default: false,
102
- },
103
- },
54
+ });
55
+
56
+ const classNames = useClassNames('page');
57
+
58
+ type _Props = {
59
+ /** 页面标题 */
60
+ title?: string;
61
+ /** 页面是否有导航栏,当为 true 时,页面主体部分会为导航栏留出空间;否则内容部分会显示在屏幕顶部 */
62
+ hasHeader?: boolean;
63
+ /**
64
+ * 是否显示底部操作栏,通常情况下使用 footer 插槽时就会显示,未使用时则没有。
65
+ *
66
+ * 但因 uniapp 的一些限制,动态的控制插槽的显隐存在一些问题,故使用此属性来进行动态控制。
67
+ */
68
+ hasFooter?: boolean;
69
+ /** 是否使用scroll-view */
70
+ useScroll?: boolean;
71
+ /** 是否启用下拉刷新,仅 useScroll 为 true 时有效 */
72
+ enableRefresh?: boolean;
73
+ /** 是否触发下拉刷新,仅 useScroll 为 true 时有效 */
74
+ refreshing?: boolean;
75
+ /** 页面加载 */
76
+ loading?: boolean | string;
77
+ /** 分页大小 */
78
+ pageSize?: number;
79
+ /** 是否显示加载更多 */
80
+ showLoadMore?: boolean;
81
+ /** 页面头部样式,主要用于控制导航栏字体颜色 */
82
+ theme?: 'light' | 'dark';
83
+ /** 是否是 tabbar 页面,且 tabbar 未隐藏 */
84
+ tabbar?: boolean;
85
+ };
86
+
87
+ withDefaults(defineProps<_Props>(), {
88
+ title: '',
89
+ hasHeader: true,
90
+ hasFooter: true,
91
+ useScroll: true,
92
+ enableRefresh: false,
93
+ refreshing: undefined,
94
+ loading: false,
95
+ pageSize: 0,
96
+ showLoadMore: true,
97
+ theme: 'light',
98
+ tabbar: false,
99
+ });
100
+
101
+ type ScrollEvent = {
102
+ detail: {
103
+ scrollLeft: number;
104
+ scrollTop: number;
105
+ scrollHeight: number;
106
+ scrollWidth: number;
107
+ deltaX: number;
108
+ deltaY: number;
109
+ };
104
110
  };
111
+
112
+ defineEmits<{
113
+ (event: 'scroll', value: ScrollEvent): void;
114
+ (event: 'refresh'): void;
115
+ (event: 'reach-bottom'): void;
116
+ }>();
117
+
118
+ const inlineStyle = computed(() => {
119
+ return [
120
+ // 顶部安全区高度
121
+ `--safe-area-top: ${navBarTopOffset}px;`,
122
+ // 底部安全区高度
123
+ `--safe-area-bottom: ${safeAreaInsetBottom}px;`,
124
+ // 页面头部上边缘相较于顶部的距离,原则上等于 `--safe-area-top`
125
+ `--page-header-top: ${navBarTopOffset}px;`,
126
+ // 页面头部高度
127
+ `--page-header-height: ${navBarHeight}px;`,
128
+ // 页面头部下边缘相较于顶部的距离
129
+ `--page-header-bottom: ${navBarBottomOffset}px;`,
130
+ // 小程序胶囊按钮宽度(实际为胶囊按钮最左侧到页面右边的距离)
131
+ `--menu-button-width: ${menuButtonWidthInCss};`,
132
+ ].join('');
133
+ });
105
134
  </script>
106
135
 
107
136
  <style lang="scss" module>
108
- @use '../../styles/index' as *;
137
+ @use '../../styles/utils' as *;
138
+ @use './page' as *;
109
139
 
110
140
  // 定义外部变量
111
- $component-name: 'page';
112
- $component-vars: $page;
113
141
  %external-vars {
114
- @include UTILS__DEFINE_COMPONENT_VARS();
115
- }
116
-
117
- :host {
118
- display: block;
142
+ @include UTILS__DEFINE_COMPONENT_VARS($page, 'page');
119
143
  }
120
144
 
121
145
  .Page {
@@ -123,6 +147,6 @@ $component-vars: $page;
123
147
 
124
148
  width: 100vw;
125
149
  position: relative;
126
- background: var(--background);
150
+ background: UTILS__LOCAL_VAR(background);
127
151
  }
128
152
  </style>