| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531 |
- <template>
- <view
- :style="{opacity : pageStatus ? 1 : 0}"
- class="gui-sbody gui-flex gui-column"
- :class="[fullPage || refresh || loadmore ? 'gui-flex1' : '']">
- <!-- 自定义头部 -->
- <view
- class="gui-header gui-transition-all"
- :class="headerClass"
- v-if="customHeader"
- id="guiPageHeader"
- ref="guiPageHeader">
- <!-- 状态栏 -->
- <view
- class="gui-page-status-bar"
- :class="statusBarClass"
- :style="{height:statusBarHeight+'px'}">
- <slot name="gStatusBar"></slot>
- </view>
- <!-- 头部插槽 -->
- <view
- class="gui-flex gui-column gui-justify-content-center"
- @tap.stop.prevnet="headerTap">
- <slot name="gHeader"></slot>
- </view>
- </view>
- <!-- 自定义头部占位 -->
- <view
- v-if="customHeader && isHeaderSized"
- :style="{height:headerHeight+'px'}"></view>
-
-
- <!-- 页面主体 -->
- <view
- class="gui-flex gui-column gui-relative"
- v-if="!refresh && !loadmore"
- id="guiPageBody"
- :class="[fullPage ? 'gui-flex1' : '']"
- ref="guiPageBody">
- <slot name="gBody"></slot>
- </view>
-
-
- <!-- 刷新加载主体 非 nvue -->
- <!-- #ifndef APP-NVUE -->
- <view
- class="gui-flex1 gui-relative"
- v-if="refresh || loadmore"
- id="guiPageBody"
- ref="guiPageBody"
- :style="{marginTop:fixedTopMargin+'px'}">
- <scroll-view
- class="gui-absolute-full"
- :scroll-y="true"
- :show-scrollbar="false"
- @touchstart="touchstart"
- @touchmove="touchmove"
- @touchend="touchend"
- @scroll="scroll"
- :scroll-into-view="topTagID"
- :scroll-with-animation="false"
- @scrolltolower="loadmorefun">
- <view id="guiPageBodyTopTag">
- <gui-refresh
- ref="guiPageRefresh"
- @reload="reload"
- :refreshText="refreshText"
- :customClass="refreshClasses"
- :triggerHeight="reFreshTriggerHeight"
- :refreshFontSize="refreshFontSize"></gui-refresh>
- </view>
- <slot name="gBody"></slot>
- <view v-if="loadmore">
- <gui-loadmore
- ref="guipageloadmore"
- :status="loadMoreStatus"
- :loadMoreText="loadMoreText"
- :customClass="loadMoreClass"
- :loadMoreFontSize="loadMoreFontSize"></gui-loadmore>
- </view>
- </scroll-view>
- </view>
- <!-- #endif -->
-
- <!-- 刷新加载主体 nvue -->
- <!-- #ifdef APP-NVUE -->
- <view
- class="gui-flex gui-column gui-flex1"
- v-if="refresh || loadmore"
- id="guiPageBody"
- ref="guiPageBody"
- :style="{marginTop:fixedTopMargin+'px'}">
- <list
- :show-scrollbar="false"
- class="gui-flex1"
- @loadmore="loadmorefun"
- @scroll="scroll">
- <refresh
- v-if="refresh"
- :display="refreshing ? 'show' : 'hide'"
- @refresh="onrefresh"
- @pullingdown="onpullingdown"></refresh>
- <cell ref="guiPageBodyTopRef"></cell>
- <cell v-if="refresh">
- <gui-refresh
- ref="guiPageRefresh"
- :refreshText="refreshText"
- :customClass="refreshClasses"
- :triggerHeight="reFreshTriggerHeight"
- :refreshFontSize="refreshFontSize"></gui-refresh>
- </cell>
- <slot name="gBody"></slot>
- <cell
- v-if="loadmore"
- class="gui-page-loadmore">
- <gui-loadmore
- ref="guipageloadmore"
- :status="loadMoreStatus"
- :loadMoreText="loadMoreText"
- :customClass="loadMoreClass"
- :loadMoreFontSize="loadMoreFontSize"></gui-loadmore>
- </cell>
- </list>
- </view>
- <!-- #endif -->
-
- <!-- 页面底部 -->
- <!-- 底部占位 -->
- <view
- v-if="customFooter"
- :style="{height:footerHeight+'px'}"></view>
- <view
- v-if="customFooter"
- class="gui-page-footer gui-border-box"
- id="guiPageFooter"
- ref="guiPageFooter"
- :class="footerClass">
- <slot name="gFooter"></slot>
- <gui-iphone-bottom
- :need="!isSwitchPage"
- :customClass="footerSpaceClass"></gui-iphone-bottom>
- </view>
-
-
- <!-- 右下角悬浮挂件 -->
- <view
- class="gui-page-pendant" :class="pendantClass">
- <slot name="gPendant"></slot>
- </view>
-
-
- <!-- 吸顶元素 -->
- <view
- class="gui-page-fixed-top"
- ref="guiPageFixedTop"
- id="guiPageFixedTop"
- :style="{top:fixedTop+'px'}">
- <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 : {
- // #ifndef APP-NVUE
- fullPage : {type:Boolean, default:false},
- // #endif
- // #ifdef APP-NVUE
- fullPage : {type:Boolean, default:true},
- // #endif
-
- // 自定义头部
- customHeader : {type:Boolean, default:false},
- headerClass : {type:Array , default:function(){return [];}},
- isHeaderSized : {type:Boolean, default:true},
- statusBarClass : {type:Array , default:function(){return [];}},
-
- // 自定义底部
- customFooter : {type:Boolean, default:false},
- footerClass : {type:Array , default:function(){return [];}},
- footerSpaceClass : {type:Array, default:function(){return ['gui-bg-gray', 'gui-dark-bg-level-2'];}},
-
- // 挂件
- pendantClass : {type:Array , default:function(){return [];}},
-
- // 全屏加载状态
- isLoading : {type:Boolean, default:false},
- isSwitchPage : {type:Boolean, default:false},
-
- // 吸顶插槽样式
- fixedTopClass : {type:Array , default:function(){return [];}},
-
- /* 刷新 */
- refresh : {type:Boolean, default:false},
- refreshText : {type:Array, default:function () {
- return ['继续下拉刷新','松开手指开始刷新','数据刷新中','数据已刷新'];
- }},
- refreshClasses : {type:Array, default:function () {
- return [
- ['gui-color-gray'],
- ['gui-color-gray'],
- ['gui-primary-text'],
- ['gui-color-green']
- ];
- }},
- refreshFontSize : {type:Number, default:26},
- defaultHeight: {type:Number, default: 0},
- /* 加载更多 */
- loadmore : {type:Boolean, default:false},
- loadMoreText : {type:Array, default:function () {
- return ['','数据加载中', '已加载全部数据', '暂无数据'];
- }},
- loadMoreClass : {type:Array, default:function () {return ['gui-color-gray'];}},
- loadMoreFontSize : {type:String, default:'26rpx'},
- loadMoreStatus : {type:Number, default: 1},
- apiLoadingStatus : {type:Boolean, default:false},
- reFreshTriggerHeight : {type:Number, default:50}
- },
- data() {
- return {
- pageStatus : false,
- footerHeight : 50,
- statusBarHeight : 44,
- // #ifndef H5
- headerHeight : 72,
- // #endif
- // #ifdef H5
- headerHeight : 44,
- // #endif
- headerTapNumber : 0,
- fixedTop : 0,
- loadMoreTimer : null,
- fixedTopMargin : 0,
- scrollTop : 0,
- srcollTimer : null,
- refreshing : false,
- pullingdownVal : 0,
- topTagID : 'no'
- }
- },
- watch:{
- isLoading : function (val) {
- if(val){
- this.pageLoadingOpen();
- }else{
- this.pageLoadingClose();
- }
- }
- },
- mounted:function(){
- // 全屏 loading
- if(this.isLoading){
- this.pageLoadingOpen();
- }
-
- // 计算状态栏高度
- try {
- var system = uni.getSystemInfoSync();
- if(system.model){
- this.statusBarHeight = system.statusBarHeight;
- }
- // #ifdef APP-PLUS
- if(plus.navigator.isFullscreen()){
- this.statusBarHeight = 0;
- }
- // #endif
- } catch(e){return null;}
-
- // 获取自定义底部高度
- if(this.customFooter){
- setTimeout(()=>{
- this.getDomSize('guiPageFooter', (res)=>{
- this.footerHeight = res.height;
- }, 0);
- }, 200);
- }
-
- // 获取自定义头部高度
- if(this.customHeader){
- setTimeout(()=>{
- this.getDomSize('guiPageHeader', (res)=>{
- this.headerHeight = ~~this.defaultHeight ?? 0;
- // this.headerHeight = res.height;
- this.$nextTick(()=>{
- this.pageStatus = true;
- });
- }, 0);
- }, 200);
- }else{
- this.pageStatus = true;
- }
-
- // 吸顶 top
- // #ifdef H5
- if(this.customHeader){
- setTimeout(()=>{
- this.getDomSize('guiPageHeader', (res)=>{
- this.fixedTop = res.height;
- }, 0);
- }, 200);
- }else{
- this.fixedTop = 44;
- }
- // #endif
- // #ifndef H5
- if(this.customHeader){
- setTimeout(()=>{
- this.getDomSize('guiPageHeader', (res)=>{
- this.fixedTop = res.height;
- }, 0);
- }, 200);
- }
- // #endif
-
- // 全屏时适配吸顶插槽
- setTimeout(()=>{
- this.getDomSize('guiPageFixedTop', (res)=>{
- this.fixedTopMargin = res.height;
- }, 0);
- }, 200);
-
- },
- methods:{
- onpullingdown : function(e){
- if(this.apiLoadingStatus){return false;}
- e.changedTouches = [{pageY:e.pullingDistance}];
- this.$refs.guiPageRefresh.touchmove(e);
- },
- onrefresh : function(){
- if(this.apiLoadingStatus){return false;}
- this.refreshing = true;
- this.$refs.guiPageRefresh.refreshStatus = 2;
- setTimeout(()=>{
- this.$refs.guiPageRefresh.rotate360();
- }, 200);
- this.$emit('reload');
- },
- pageLoadingOpen : function(){
- this.getRefs('guipageloading',0,(ref)=>{
- ref.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(()=>{
- // #ifndef APP-NVUE
- this.$refs.guiPageRefresh.scroll(e);
- this.$emit('scroll', e);
- this.scrollTop = e.detail.scrollTop;
- // #endif
-
- // #ifdef APP-NVUE
- e.detail = {scrollTop : e.contentOffset.y * -1};
- this.$emit('scroll', e);
- this.scrollTop = e.detail.scrollTop;
- // #endif
- }, 500);
- },
- toTop : function (){
- // #ifndef APP-NVUE
- this.topTagID = 'guiPageBodyTopTag';
- setTimeout(()=>{
- this.topTagID = 'no';
- }, 500);
- // #endif
- // #ifdef APP-NVUE
- const el = this.$refs.guiPageBodyTopRef;
- dom.scrollToElement(el, {});
- // #endif
- },
- endReload : function(){
- this.$refs.guiPageRefresh.endReload();
- this.refreshing = false;
- },
- 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);
- return ;
- }else{
- if(res[0].height == undefined){
- count += 1;
- setTimeout(()=>{this.getDomSize(domIDOrRef, fun, count);}, 50);
- return ;
- }
- 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);
- return ;
- }else{
- if(res.size.height < 1){
- count += 1;
- setTimeout(()=>{this.getDomSize(domIDOrRef, fun, count);}, 50);
- return ;
- }
- 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){
- fun(refReturn);
- }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();
- },
- stoploadmore : function(){
- this.$refs.guipageloadmore.stoploadmore();
- },
- nomore : function () {
- this.$refs.guipageloadmore.nomore();
- },
- toast : function(msg){
- uni.showToast({
- title:msg,
- icon:"none"
- })
- },
- resetFooterHeight : function(){
- if(this.customFooter){
- setTimeout(()=>{
- this.getDomSize('guiPageFooter', (res)=>{
- this.footerHeight = res.height;
- }, 0);
- }, 500);
- }
- }
- },
- emits:['scroll', 'reload', 'loadmorefun', 'gotoTop']
- }
- </script>
- <style scoped>
- /* #ifdef APP-VUE */
- .gui-sbody{min-height:100vh;}
- /* #endif */
- /* #ifdef MP-ALIPAY */
- .gui-sbody{min-height:100vh;}
- /* #endif */
- </style>
|