@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.
- package/README.md +202 -66
- package/components/aspect/aspect.vue +24 -15
- package/components/badge/badge.scss +20 -0
- package/components/badge/badge.vue +49 -40
- package/components/button/button.scss +15 -0
- package/components/button/button.vue +121 -177
- package/components/checkbox/checkbox.scss +10 -0
- package/components/checkbox/checkbox.vue +118 -146
- package/components/checkbox-group/checkbox-group.vue +79 -85
- package/components/checkbox-group2/checkbox-group2.vue +111 -107
- package/components/checkbox-group2/checkbox2.vue +104 -0
- package/components/data-list/data-list.scss +9 -0
- package/components/data-list/data-list.vue +70 -79
- package/components/date-picker/date-picker-view.vue +125 -124
- package/components/date-picker/date-picker.vue +145 -146
- package/components/dialog/dialog-content.vue +39 -47
- package/components/dialog/dialog.scss +11 -0
- package/components/dialog/dialog.vue +125 -138
- package/components/dropdown/dropdown.scss +11 -0
- package/components/dropdown/dropdown.vue +55 -97
- package/components/empty/empty.scss +14 -0
- package/components/empty/empty.vue +42 -41
- package/components/flex/flex.vue +45 -54
- package/components/form/form.vue +29 -24
- package/components/form-item/form-item.scss +11 -0
- package/components/form-item/form-item.vue +43 -40
- package/components/icon/icon.vue +70 -85
- package/components/image/image.vue +35 -38
- package/components/input/input.vue +65 -79
- package/components/input/password-input.vue +34 -42
- package/components/list-page/list-page.vue +73 -99
- package/components/load-more/load-more.scss +12 -0
- package/components/load-more/load-more.vue +29 -29
- package/components/loading/animations/loading-animation1.vue +8 -8
- package/components/loading/animations/loading-animation2.vue +8 -9
- package/components/loading/animations/loading-animation3.vue +11 -11
- package/components/loading/animations/loading-animation4.vue +8 -8
- package/components/loading/loading.vue +19 -20
- package/components/message-box/message-box.vue +59 -41
- package/components/number-dialog/number-dialog.scss +9 -0
- package/components/number-dialog/number-dialog.vue +209 -204
- package/components/number-input/number-input.scss +9 -0
- package/components/number-input/number-input.vue +233 -232
- package/components/numpad/numpad.scss +9 -0
- package/components/numpad/numpad.vue +133 -150
- package/components/page/page-body.scss +15 -0
- package/components/page/page-body.vue +137 -119
- package/components/page/page-footer.scss +13 -0
- package/components/page/page-footer.vue +31 -33
- package/components/page/page-header.scss +17 -0
- package/components/page/page-header.vue +89 -94
- package/components/page/page.scss +9 -0
- package/components/page/page.vue +105 -81
- package/components/picker/picker-popup.vue +218 -209
- package/components/picker/picker.vue +99 -104
- package/components/popover/popover-content.vue +54 -63
- package/components/popover/popover-mask.vue +63 -63
- package/components/popover/popover.scss +28 -0
- package/components/popover/popover.vue +49 -47
- package/components/popup/popup-content.vue +49 -53
- package/components/popup/popup.scss +11 -0
- package/components/popup/popup.vue +117 -132
- package/components/price/price.scss +20 -0
- package/components/price/price.vue +31 -42
- package/components/search/search.scss +12 -0
- package/components/search/search.vue +93 -117
- package/components/searching/searching.vue +33 -40
- package/components/selector/selector.vue +43 -48
- package/components/switch/switch.scss +12 -0
- package/components/switch/switch.vue +99 -96
- package/components/tab/tab.scss +19 -0
- package/components/tab/tab.vue +151 -145
- package/components/textarea/textarea.vue +104 -101
- package/composable/component-name.d.ts +2 -0
- package/composable/component-name.js +8 -0
- package/composable/component-name.ts +10 -0
- package/configs/index.d.ts +25 -10
- package/configs/index.js +14 -23
- package/configs/index.ts +82 -0
- package/easyCom.d.ts +9 -0
- package/easyCom.js +1 -2
- package/easyCom.ts +31 -0
- package/index.d.ts +1 -0
- package/index.js +1 -0
- package/index.ts +1 -0
- package/init.d.ts +4 -7
- package/init.js +5 -4
- package/init.ts +34 -0
- package/package.json +14 -4
- package/styles/utils/css-var.scss +12 -15
- package/styles/utils/ellipsis.scss +0 -7
- package/styles/utils/z-index.scss +1 -1
- package/styles/var/component.scss +21 -245
- package/utils/date.d.ts +47 -0
- package/utils/date.js +23 -43
- package/utils/date.ts +153 -0
- package/utils/freezeDeep.d.ts +1 -0
- package/utils/freezeDeep.js +4 -14
- package/utils/freezeDeep.ts +9 -0
- package/utils/price.d.ts +24 -0
- package/utils/price.js +14 -8
- package/utils/price.ts +57 -0
- package/utils/round.d.ts +2 -0
- package/utils/round.js +2 -14
- package/utils/round.ts +11 -0
- package/utils/windowInfo.d.ts +24 -0
- package/utils/windowInfo.js +8 -36
- package/utils/windowInfo.ts +50 -0
- package/components/checkbox-group2/checkbox.vue +0 -109
- package/components/datetime-picker/datetime-picker-view.vue +0 -209
- package/components/datetime-picker/datetime-picker.vue +0 -235
- package/components/form/mixin.js +0 -13
- package/components/list-page/list-page.js +0 -10
- package/components/table/table.vue +0 -112
- package/components/time-picker/time-picker-view.vue +0 -127
- package/components/time-picker/time-picker.vue +0 -140
- package/components/uploader/download.js +0 -81
- package/components/uploader/file-uploader.vue +0 -52
- package/components/uploader/files.js +0 -225
- package/components/uploader/media-uploader.vue +0 -189
- package/components/uploader/mixin.js +0 -171
- package/components/uploader/uni.js +0 -38
- package/components/uploader/upload-button.vue +0 -29
- package/components/uploader/uploader copy.vue +0 -547
- package/components/uploader/uploader.vue +0 -117
- package/mixins/componentName.js +0 -32
- package/mixins/listPage.js +0 -1
- package/mixins/windowInfo.js +0 -1
- package/utils/fileSize.js +0 -39
- package/utils/floor.js +0 -20
|
@@ -1,56 +1,54 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<view :class="
|
|
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
|
-
|
|
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
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
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/
|
|
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="[
|
|
4
|
-
|
|
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="
|
|
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
|
|
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
|
-
|
|
63
|
-
name: 'PageHeader',
|
|
66
|
+
defineOptions({
|
|
64
67
|
options: {
|
|
65
|
-
virtualHost: true,
|
|
66
68
|
styleIsolation: 'shared',
|
|
69
|
+
virtualHost: true,
|
|
67
70
|
},
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
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/
|
|
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(--
|
|
171
|
+
margin-top: var(--page-header-top);
|
|
177
172
|
width: 100%;
|
|
178
|
-
height: var(--
|
|
179
|
-
line-height: var(--
|
|
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(--
|
|
191
|
-
height: var(--
|
|
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(--
|
|
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(--
|
|
220
|
+
--title-bar-left-padding: calc(var(--page-header-height) * 2 + 20rpx);
|
|
226
221
|
}
|
|
227
222
|
&.PageHeader--title-center {
|
|
228
223
|
text-align: center;
|
package/components/page/page.vue
CHANGED
|
@@ -1,15 +1,17 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<view :class="
|
|
3
|
-
<
|
|
4
|
-
<
|
|
5
|
-
<
|
|
6
|
-
|
|
7
|
-
|
|
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-
|
|
12
|
-
:has-footer="hasFooter &&
|
|
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
|
|
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
|
-
|
|
40
|
-
name: 'Page',
|
|
49
|
+
defineOptions({
|
|
41
50
|
options: {
|
|
42
|
-
virtualHost: true,
|
|
43
51
|
styleIsolation: 'shared',
|
|
52
|
+
virtualHost: true,
|
|
44
53
|
},
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
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/
|
|
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:
|
|
150
|
+
background: UTILS__LOCAL_VAR(background);
|
|
127
151
|
}
|
|
128
152
|
</style>
|