You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
430 lines
13 KiB
430 lines
13 KiB
<template>
|
|
<view :class="[
|
|
'gui-flex', 'gui-columns', 'gui-sbody',
|
|
fullPage ? 'gui-flex1':'' ,
|
|
refresh || loadmore ? 'gui-flex1' : ''
|
|
]">
|
|
<!-- 自定义头部 -->
|
|
<view
|
|
class="gui-header gui-transition-all"
|
|
v-if="customHeader"
|
|
id="guiPageHeader"
|
|
ref="guiPageHeader"
|
|
:style="'height:'
|
|
+(headerSets.height+statusBarHeight)+'px; z-index:'
|
|
+headerSets.zIndex+';'+headerStyle">
|
|
<!-- 状态栏 -->
|
|
<view
|
|
class="gui-page-status-bar"
|
|
:style="'height:'+statusBarHeight+'px;'+statusBarStyle"></view>
|
|
<!-- 头部插槽 -->
|
|
<view
|
|
class="gui-flex gui-columns gui-justify-content-center"
|
|
@tap.stop.prevnet="headerTap"
|
|
:style="{height:headerSets.height+'px'}">
|
|
<slot name="gHeader"></slot>
|
|
</view>
|
|
</view>
|
|
<!-- 自定义头部占位 -->
|
|
<view
|
|
v-if="customHeader && isHeaderSized"
|
|
:style="'height:'+(headerSets.height+statusBarHeight)+'px; '+ headerSizedStyle + ';'"></view>
|
|
<!-- 页面主体 -->
|
|
<view
|
|
class="gui-flex gui-columns"
|
|
v-if="!refresh && !loadmore"
|
|
id="guiPageBody"
|
|
ref="guiPageBody"
|
|
:class="[fullPage?'gui-flex1':'']">
|
|
<slot name="gBody"></slot>
|
|
</view>
|
|
<!-- 刷新加载主体 -->
|
|
<view class="gui-flex gui-columns gui-flex1"
|
|
v-if="refresh || loadmore"
|
|
id="guiPageBody"
|
|
ref="guiPageBody"
|
|
:style="{
|
|
marginTop:fixedTopMargin+'px',
|
|
height:refreshBodyHeight+'px'
|
|
}">
|
|
<scroll-view
|
|
class="gui-relative"
|
|
:scroll-y="true"
|
|
:show-scrollbar="false"
|
|
:style="{
|
|
height:refreshBodyHeight+'px',
|
|
opacity:refreshBodyHeight < 1 ? 0 : 1
|
|
}"
|
|
@touchstart="touchstart"
|
|
@touchmove="touchmove"
|
|
@touchend="touchend"
|
|
@scroll="scroll"
|
|
:scroll-top="scrollTop"
|
|
@scrolltolower="loadmorefun">
|
|
<view>
|
|
<gui-refresh
|
|
ref="guiPageRefresh"
|
|
@reload="reload"
|
|
:refreshText="refreshText"
|
|
:refreshBgColor="refreshBgColor"
|
|
:refreshColor="refreshColor"
|
|
:refreshFontSize="refreshFontSize"></gui-refresh>
|
|
</view>
|
|
<slot name="gBody"></slot>
|
|
<view
|
|
v-if="loadmore"
|
|
class="gui-page-loadmore">
|
|
<gui-loadmore
|
|
ref="guipageloadmore"
|
|
:status="loadMoreStatus"
|
|
:loadMoreText="loadMoreText"
|
|
:loadMoreColor="loadMoreColor"
|
|
:loadMoreFontSize="loadMoreFontSize"></gui-loadmore>
|
|
</view>
|
|
</scroll-view>
|
|
</view>
|
|
<!-- 页面底部 -->
|
|
<!-- 底部占位 -->
|
|
<view v-if="customFooter"
|
|
:style="{height:footerHeight}"></view>
|
|
<view class="gui-page-footer gui-border-box"
|
|
:class="[isSwitchPage?'gui-switch-page-footer':'']"
|
|
v-if="customFooter"
|
|
id="guiPageFooter"
|
|
ref="guiPageFooter"
|
|
:style="{
|
|
height:footerHeight,
|
|
'background-image':footerSets.bg,
|
|
'z-index':footerSets.zIndex
|
|
}">
|
|
<view>
|
|
<slot name="gFooter"></slot>
|
|
</view>
|
|
<view
|
|
:style="'height:'+iphoneXButtomHeight+'; '+ iphoneXButtomStyle"></view>
|
|
</view>
|
|
<!-- 右下角悬浮挂件 -->
|
|
<view
|
|
class="gui-page-pendant"
|
|
:style="{
|
|
right:pendantSets.right, bottom:pendantSets.bottom,
|
|
width:pendantSets.width, zIndex:pendantSets.zIndex}">
|
|
<slot name="gPendant"></slot>
|
|
</view>
|
|
<!-- 吸顶元素 -->
|
|
<view
|
|
class="gui-page-fixed-top"
|
|
ref="guiPageFixedTop"
|
|
id="guiPageFixedTop"
|
|
:style="{
|
|
top:fixedTop+'px',
|
|
zIndex:fixedTopZIndex
|
|
}">
|
|
<slot name="gFixedTop"></slot>
|
|
</view>
|
|
<!-- 全屏 loading -->
|
|
<gui-page-loading ref="guipageloading"></gui-page-loading>
|
|
</view>
|
|
</template>
|
|
<script>
|
|
// #ifdef APP-NVUE
|
|
const dom = weex.requireModule('dom');
|
|
// #endif
|
|
export default{
|
|
name : 'gui-page',
|
|
props : {
|
|
fullPage : {type:Boolean, default:false},
|
|
customHeader : {type:Boolean, default:false},
|
|
headerSets : {type:Object , default:function(){return {height:44, zIndex:100}}},
|
|
headerStyle : {type:String , default:'background-color:#FFFFFF;'},
|
|
isHeaderSized : {type:Boolean, default:true},
|
|
statusBarStyle : {type:String , default:'background-color:#FFFFFF;'},
|
|
customFooter : {type:Boolean, default:false},
|
|
footerSets : {type:Object , default:function(){return {height:100, zIndex:100, bg:'linear-gradient(to bottom, #FFFFFF,#FFFFFF)'}}},
|
|
pendantSets : {type:Object , default:function(){return {width:'100rpx', right:'25rpx', bottom:'100rpx', zIndex:100};}},
|
|
isLoading : {type:Boolean, default:false},
|
|
isSwitchPage : {type:Boolean, default:false},
|
|
iphoneXButtomStyle : {type:String, default:''},
|
|
headerSizedStyle : {type:String, default:''},
|
|
fixedTopZIndex : {type:Number, default:2},
|
|
/* 刷新 */
|
|
refresh : {type:Boolean, default:false},
|
|
refreshText : {type:Array, default:function () {
|
|
return ['继续下拉刷新','松开手指开始刷新','数据刷新中','数据已刷新'];
|
|
}},
|
|
refreshBgColor : {type:Array, default:function () {
|
|
return ['#FFFFFF','#FFFFFF','#FFFFFF','#63D2BC'];
|
|
}},
|
|
refreshColor : {type:Array, default:function () {
|
|
return ['rgba(69, 90, 100, 0.6)','rgba(69, 90, 100, 0.6)','#63D2BC','#FFFFFF'];
|
|
}},
|
|
refreshFontSize : {type:String, default:'26rpx'},
|
|
|
|
/* 加载更多 */
|
|
loadmore : {type:Boolean, default:false},
|
|
loadMoreText : {type:Array, default:function () {
|
|
return ['','数据加载中', '已加载全部数据', '暂无数据'];
|
|
}},
|
|
loadMoreColor : {type:Array, default:function () {
|
|
return ['rgba(69, 90, 100, 0.6)', 'rgba(69, 90, 100, 0.6)', 'rgba(69, 90, 100, 0.8)', 'rgba(69, 90, 100, 0.8)'];
|
|
}},
|
|
loadMoreStatus : {type:Number, defalut:0},
|
|
loadMoreFontSize : {type:String, default:'26rpx'},
|
|
apiLoadingStatus : {type:Boolean, default:false}
|
|
},
|
|
data() {
|
|
return {
|
|
footerHeight : '100rpx',
|
|
iphoneXButtomHeight : '0rpx',
|
|
statusBarHeight : 0,
|
|
// #ifdef APP-NVUE
|
|
animateCount : 0,
|
|
// #endif
|
|
headerTapNumber : 0,
|
|
fixedTop : 0,
|
|
refreshBodyHeight : 0,
|
|
loadMoreTimer : null,
|
|
fixedTopMargin : 0,
|
|
scrollTop : 0,
|
|
srcollTimer : null
|
|
}
|
|
},
|
|
|
|
mounted:function(){
|
|
if(this.isLoading){
|
|
this.pageLoadingOpen();
|
|
}
|
|
// 刷新相关
|
|
setTimeout(()=>{
|
|
if(this.refresh || this.loadmore){
|
|
this.getDomSize('guiPageBody', (res)=>{
|
|
this.refreshBodyHeight = res.height;
|
|
this.getDomSize('guiPageFixedTop', (res)=>{
|
|
if(res.height){
|
|
this.refreshBodyHeight -= res.height;
|
|
this.fixedTopMargin = res.height;
|
|
}
|
|
})
|
|
});
|
|
}
|
|
},200);
|
|
},
|
|
watch:{
|
|
isLoading : function (val) {
|
|
if(val){
|
|
this.pageLoadingOpen();
|
|
}else{
|
|
this.pageLoadingClose();
|
|
}
|
|
}
|
|
},
|
|
created:function(){
|
|
this.footerHeight = this.footerSets.height + 'rpx';
|
|
// #ifdef H5
|
|
if(this.customHeader){
|
|
this.fixedTop = this.headerSets.height;
|
|
}else{
|
|
this.fixedTop = 44;
|
|
}
|
|
// #endif
|
|
try {
|
|
var system = uni.getSystemInfoSync();
|
|
if(system.model){
|
|
system.model = system.model.replace(' ', '');
|
|
system.model = system.model.toLowerCase();
|
|
this.statusBarHeight = system.statusBarHeight;
|
|
var res1 = system.model.indexOf('iphonex');
|
|
if(res1 > 5){res1 = -1;}
|
|
var res2 = system.model.indexOf('iphone1');
|
|
if(res2 > 5){res2 = -1;}
|
|
if(res1 != -1 || res2 != -1){
|
|
this.iphoneXButtomHeight = '50rpx';
|
|
this.footerHeight = (this.footerSets.height + 50 ) + 'rpx';
|
|
}
|
|
}
|
|
// #ifdef MP-ALIPAY
|
|
this.statusBarHeight = 0;
|
|
// #endif
|
|
// #ifdef APP-PLUS
|
|
this.iphoneXButtomHeight = '0rpx';
|
|
this.footerHeight = this.footerSets.height + 'rpx';
|
|
if(plus.navigator.isFullscreen()){
|
|
this.statusBarHeight = 0;
|
|
}
|
|
// #endif
|
|
if(this.isSwitchPage){
|
|
this.iphoneXButtomHeight = '0rpx';
|
|
this.footerHeight = this.footerSets.height + 'rpx';
|
|
}
|
|
// #ifndef H5
|
|
if(this.customHeader){
|
|
this.fixedTop = this.headerSets.height + this.statusBarHeight;
|
|
}else{
|
|
this.fixedTop = 0;
|
|
}
|
|
// #endif
|
|
} catch (e){return null;}
|
|
},
|
|
methods:{
|
|
pageLoadingOpen : function(){
|
|
this.getRefs('guipageloading',0,(ref)=>{
|
|
this.$refs.guipageloading.open();
|
|
});
|
|
},
|
|
pageLoadingClose : function(){
|
|
this.getRefs('guipageloading',0,(ref)=>{
|
|
ref.close();
|
|
});
|
|
},
|
|
// 下拉刷新相关
|
|
touchstart : function (e){
|
|
if(!this.refresh){return false;}
|
|
if(this.apiLoadingStatus){return false;}
|
|
this.$refs.guiPageRefresh.touchstart(e);
|
|
},
|
|
touchmove : function(e){
|
|
if(!this.refresh){return false;}
|
|
if(this.apiLoadingStatus){return false;}
|
|
this.$refs.guiPageRefresh.touchmove(e);
|
|
},
|
|
touchend : function (e) {
|
|
if(!this.refresh){return false;}
|
|
if(this.apiLoadingStatus){return false;}
|
|
this.$refs.guiPageRefresh.touchend(e);
|
|
},
|
|
scroll:function(e){
|
|
if(this.srcollTimer != null){
|
|
clearTimeout(this.srcollTimer);
|
|
}
|
|
this.srcollTimer = setTimeout(()=>{
|
|
this.$refs.guiPageRefresh.scroll(e);
|
|
this.$emit('scroll', e);
|
|
this.scrollTop = e.detail.scrollTop;
|
|
}, 100);
|
|
},
|
|
setScrollTop : function (scrollTop){
|
|
this.scrollTop = scrollTop;
|
|
},
|
|
endReload : function(){
|
|
this.$refs.guiPageRefresh.endReload();
|
|
},
|
|
reload : function(){
|
|
if(this.apiLoadingStatus){return false;}
|
|
this.$emit('reload');
|
|
if(this.loadmore){this.$refs.guipageloadmore.stoploadmore();}
|
|
},
|
|
// 获取元素尺寸
|
|
getDomSize : function(domIDOrRef, fun, count){
|
|
if(!count){count = 1;}
|
|
if(count >= 50){
|
|
fun({width:0, height:0});
|
|
return false;
|
|
}
|
|
// #ifndef APP-NVUE
|
|
uni.createSelectorQuery().in(this).select('#'+domIDOrRef).boundingClientRect().exec((res)=>{
|
|
if(res[0] == null){
|
|
count += 1;
|
|
setTimeout(()=>{this.getDomSize(domIDOrRef, fun, count);}, 50);
|
|
}else{
|
|
fun(res[0]);
|
|
return ;
|
|
}
|
|
});
|
|
// #endif
|
|
// #ifdef APP-NVUE
|
|
var el = this.$refs[domIDOrRef];
|
|
dom.getComponentRect(el, (res) => {
|
|
if(res.result == false){
|
|
count += 1;
|
|
setTimeout(()=>{this.getDomSize(domIDOrRef, fun, count);}, 50);
|
|
}else{
|
|
fun(res.size);
|
|
return ;
|
|
}
|
|
});
|
|
// #endif
|
|
|
|
},
|
|
stopfun : function(e){e.stopPropagation(); return null;},
|
|
headerTap : function(){
|
|
this.headerTapNumber ++;
|
|
if(this.headerTapNumber >= 2){
|
|
this.$emit('gotoTop');
|
|
this.headerTapNumber = 0;
|
|
}else{
|
|
setTimeout(()=>{this.headerTapNumber = 0;}, 1000);
|
|
}
|
|
},
|
|
getRefs : function(ref, count, fun){
|
|
if(count >= 50){
|
|
fun(this.$refs[ref]);
|
|
return false;
|
|
}
|
|
var refReturn = this.$refs[ref];
|
|
if(refReturn){
|
|
// #ifdef APP-NVUE
|
|
fun(refReturn);
|
|
return;
|
|
// #endif
|
|
// #ifndef APP-NVUE
|
|
if(refReturn._data){
|
|
fun(refReturn);
|
|
return;
|
|
}
|
|
// #endif
|
|
}else{
|
|
count++;
|
|
setTimeout(()=>{
|
|
this.getRefs(ref, count, fun);
|
|
}, 100);
|
|
}
|
|
},
|
|
loadmorefun : function () {
|
|
if(!this.loadmore){return false;}
|
|
if(this.apiLoadingStatus){return false;}
|
|
// 获取加载组件状态看一下是否还能继续加载
|
|
// 保证触底只执行一次加载
|
|
if(this.loadMoreTimer != null){clearTimeout(this.loadMoreTimer);}
|
|
this.loadMoreTimer = setTimeout(() => {
|
|
var status = this.$refs.guipageloadmore.loadMoreStatus;
|
|
if(status != 0){return null;}
|
|
this.$refs.guipageloadmore.loading();
|
|
this.$emit('loadmorefun');
|
|
}, 80);
|
|
},
|
|
stoploadmore : function(){
|
|
this.$refs.guipageloadmore.stoploadmore();
|
|
},
|
|
nomore : function () {
|
|
this.$refs.guipageloadmore.nomore();
|
|
},
|
|
loadEmpty : function(){
|
|
this.$refs.guipageloadmore.empty();
|
|
}
|
|
}
|
|
}
|
|
</script>
|
|
<style scoped>
|
|
/* .gui-sbody{width:750rpx;} */
|
|
.gui-page-loading{width:750rpx; position:fixed; left:0; top:0; bottom:0; flex:1; z-index:99999;}
|
|
.gui-page-loading-points{width:20rpx; height:20rpx; border-radius:50rpx; margin:10rpx;}
|
|
/* #ifndef APP-NVUE */
|
|
.gui-sbody{min-height:calc(100vh - var(--window-top) - var(--window-bottom));}
|
|
@keyframes pageLoading1{0% {opacity:0.5; transform:scale(1);} 40% {opacity:1; transform:scale(1.5);} 60%{opacity:0.5; transform:scale(1);}}
|
|
@keyframes pageLoading2{20% {opacity:0.5; transform:scale(1);} 60% {opacity:1; transform:scale(1.5);} 80% {opacity:0.5; transform:scale(1);}}
|
|
@keyframes pageLoading3{40% {opacity:0.5; transform:scale(1);} 80% {opacity:1; transform:scale(1.5);} 100% {opacity:0.5; transform:scale(1);}}
|
|
.animate1{animation:pageLoading1 1.2s infinite linear;}
|
|
.animate2{animation:pageLoading2 1.2s infinite linear;}
|
|
.animate3{animation:pageLoading3 1.2s infinite linear;}
|
|
/* #endif */
|
|
.gui-header{width:750rpx; position:fixed; left:0; top:0;}
|
|
.gui-page-footer{width:750rpx; position:fixed; left:0; bottom:0;}
|
|
/* #ifdef H5 */
|
|
.gui-switch-page-footer{bottom:50px;}
|
|
/* #endif */
|
|
.gui-page-status-bar{width:750rpx;}
|
|
.gui-page-pendant{position:fixed;}
|
|
|
|
.gui-page-fixed-top{position:fixed; top:44px; left:0px; width:750rpx; z-index:99998; overflow:hidden;}
|
|
.gui-page-loadmore{padding-bottom:30rpx;}
|
|
</style>
|