gracePage.vue 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367
  1. <template>
  2. <view class="grace-sbody">
  3. <!-- 头部导航 -->
  4. <view v-if="customHeader">
  5. <view class="grace-page-header" :style="{
  6. 'z-index':headerIndex, background:headerBG,
  7. borderBottomWidth:borderWidth, borderBottomColor:borderColor}">
  8. <!-- 沉浸式状态栏 -->
  9. <view class="grace-page-status-bar" :style="{height:statusBarHeight+'px', background:statusBarBG}"></view>
  10. <!-- 头部核心 -->
  11. <view class="grace-page-header-nav" id="gracePageHeader" :style="{minHeight:headerHeight+'px', height:headerHeight+'px', overflow:'hidden'}">
  12. <view class="grace-header-main">
  13. <slot name="gHeader"></slot>
  14. </view>
  15. <view :style="{width:BoundingWidth, flexShrink:'0'}" v-if="bounding"></view>
  16. </view>
  17. </view>
  18. <!-- 占位 view -->
  19. <view :style="{width:'100%', height:(headerHeight+statusBarHeight) + 'px'}"></view>
  20. </view>
  21. <!-- 页面主体 -->
  22. <view class="grace-page-body">
  23. <slot name="gBody"></slot>
  24. </view>
  25. <!-- #ifndef APP-PLUS -->
  26. <view v-if="!isSwitchPage" :style="{width:'100%', height:iphoneXButtomHeight+'px'}"></view>
  27. <!-- #endif -->
  28. <!-- 页面底部 -->
  29. <view class="grace-page-footer" :style="{'z-index':footerIndex, background:footerBg}">
  30. <slot name="gFooter"></slot>
  31. <!-- iphoneX 占位 view -->
  32. <!-- #ifndef APP-PLUS -->
  33. <view v-if="!isSwitchPage" :style="{width:'100%', height:iphoneXButtomHeight+'px'}"></view>
  34. <!-- #endif -->
  35. </view>
  36. <!-- 右下角悬浮按钮 -->
  37. <view class="gui-page-rb-area" :style="{right:rbRight+'rpx', bottom:rbBottom+'rpx', width:rbWidth+'rpx', zIndex:rbIndex}">
  38. <slot name="gRTArea"></slot>
  39. </view>
  40. <!-- 吸顶元素 -->
  41. <view class="grace-page-fixed-top" :style="{top:fixedTop+'px'}">
  42. <slot name="gFixedTop"></slot>
  43. </view>
  44. <!-- 全屏 loading -->
  45. <view class="grace-page-loading" @tap.stop="stopfun" @touchmove.stop.prevent="stopfun" :style="{background:loadingBG}"
  46. v-if="isLoading">
  47. <view class="grace-page-loading-point">
  48. <view class="grace-page-loading-points animate1" :style="{background:loadingPointBg}"></view>
  49. <view class="grace-page-loading-points animate2" :style="{background:loadingPointBg}"></view>
  50. <view class="grace-page-loading-points animate3" :style="{background:loadingPointBg}"></view>
  51. </view>
  52. </view>
  53. </view>
  54. </template>
  55. <script>
  56. export default {
  57. props: {
  58. customHeader: {
  59. type: Boolean,
  60. default: true
  61. },
  62. headerHeight: {
  63. type: Number,
  64. default: 44
  65. },
  66. headerIndex: {
  67. type: Number,
  68. default: 98
  69. },
  70. headerBG: {
  71. type: String,
  72. default: 'none'
  73. },
  74. statusBarBG: {
  75. type: String,
  76. default: 'none'
  77. },
  78. footerIndex: {
  79. type: Number,
  80. default: 98
  81. },
  82. footerBg: {
  83. type: String,
  84. default: ''
  85. },
  86. isSwitchPage: {
  87. type: Boolean,
  88. default: false
  89. },
  90. rbWidth: {
  91. type: Number,
  92. default: 100
  93. },
  94. rbBottom: {
  95. type: Number,
  96. default: 100
  97. },
  98. rbRight: {
  99. type: Number,
  100. default: 20
  101. },
  102. rbIndex: {
  103. type: Number,
  104. default: 1
  105. },
  106. borderWidth: {
  107. type: String,
  108. default: '0px'
  109. },
  110. borderColor: {
  111. type: String,
  112. default: '#D1D1D1'
  113. },
  114. loadingBG: {
  115. type: String,
  116. default: 'rgba(255,255,255, 0.1)'
  117. },
  118. isLoading: {
  119. type: Boolean,
  120. default: false
  121. },
  122. loadingPointBg: {
  123. type: String,
  124. default: '#3688FF'
  125. },
  126. bounding: {
  127. type: Boolean,
  128. default: true
  129. }
  130. },
  131. data() {
  132. return {
  133. statusBarHeight: 44,
  134. iphoneXButtomHeight: 0,
  135. BoundingWidth: '0px',
  136. fixedTop: 0
  137. }
  138. },
  139. created: function() {
  140. // #ifdef H5
  141. if (this.customHeader) {
  142. this.fixedTop = this.headerHeight;
  143. } else {
  144. this.fixedTop = 44;
  145. }
  146. // #endif
  147. try {
  148. var system = uni.getSystemInfoSync();
  149. system.model = system.model.replace(' ', '');
  150. system.model = system.model.toLowerCase();
  151. if (system.model.indexOf('iphonex') != -1 || system.model.indexOf('iphone1') != -1) {
  152. this.iphoneXButtomHeight = uni.upx2px(50);
  153. }
  154. // #ifndef H5
  155. if (this.customHeader) {
  156. this.fixedTop = this.headerHeight + system.statusBarHeight;
  157. } else {
  158. this.fixedTop = 0;
  159. }
  160. // #endif
  161. if (!this.customHeader) {
  162. return;
  163. }
  164. this.statusBarHeight = system.statusBarHeight;
  165. // #ifdef MP-ALIPAY
  166. this.statusBarHeight = 0;
  167. // #endif
  168. // #ifndef MP-ALIPAY
  169. // #ifdef MP-WEIXIN
  170. // 小程序胶囊按钮
  171. var bounding = uni.getMenuButtonBoundingClientRect();
  172. this.BoundingWidth = (bounding.width + system.windowWidth - bounding.right + 10) + 'px';
  173. // #endif
  174. // #endif
  175. } catch (e) {
  176. return null;
  177. }
  178. },
  179. methods: {
  180. getHeaderHeight: function() {
  181. return this.headerHeight + this.statusBarHeight;
  182. },
  183. stopfun: function() {}
  184. }
  185. }
  186. </script>
  187. <style>
  188. /* #ifndef MP */
  189. page {
  190. width: 100%;
  191. min-height: 100%;
  192. display: flex;
  193. flex-direction: column;
  194. flex: 1;
  195. }
  196. /* #endif */
  197. .grace-sbody {
  198. display: flex;
  199. flex-direction: column;
  200. width: 100%;
  201. min-height: 100%;
  202. flex: 1;
  203. }
  204. /* #ifdef MP */
  205. .grace-sbody {
  206. min-height: 100vh;
  207. }
  208. /* #endif */
  209. .grace-page-header {
  210. width: 100%;
  211. position: fixed;
  212. left: 0;
  213. top: 0;
  214. z-index: 99;
  215. border-bottom: 0px solid #FFFFFF;
  216. }
  217. .grace-page-status-bar {
  218. width: 100%;
  219. height: 0;
  220. }
  221. .grace-page-header-nav {
  222. width: 100%;
  223. display: flex;
  224. flex-direction: row;
  225. flex-wrap: nowrap;
  226. align-items: center;
  227. }
  228. .grace-header-main {
  229. width: 300rpx;
  230. flex: auto;
  231. overflow: hidden;
  232. min-height: 44px;
  233. }
  234. .grace-page-body {
  235. width: 100%;
  236. flex: 1;
  237. display: flex;
  238. flex-direction: column;
  239. }
  240. .grace-page-footer {
  241. width: 100%;
  242. position: fixed;
  243. left: 0;
  244. bottom: var(--window-bottom);
  245. z-index: 99;
  246. }
  247. .gui-page-rb-area {
  248. width: 100rpx;
  249. position: fixed;
  250. right: 20rpx;
  251. bottom: 100rpx;
  252. z-index: 1;
  253. }
  254. .grace-page-loading {
  255. width: 100%;
  256. height: 100%;
  257. background: rgba(255, 255, 255, 0.1);
  258. position: fixed;
  259. z-index: 9999;
  260. left: 0;
  261. top: 0;
  262. bottom: 0;
  263. display: flex;
  264. flex-direction: column;
  265. justify-content: center;
  266. align-items: center;
  267. }
  268. .grace-page-loading-point {
  269. display: flex;
  270. flex-direction: row;
  271. flex-wrap: nowrap;
  272. justify-content: center;
  273. }
  274. .grace-page-loading-points {
  275. width: 20rpx;
  276. height: 20rpx;
  277. background-color: #3688FF;
  278. border-radius: 50rpx;
  279. margin: 10rpx;
  280. opacity: 0.5;
  281. }
  282. @keyframes pageLoading1 {
  283. 0% {
  284. opacity: 0.5;
  285. transform: scale(1);
  286. }
  287. 40% {
  288. opacity: 1;
  289. transform: scale(1.5);
  290. }
  291. 60% {
  292. opacity: 0.5;
  293. transform: scale(1);
  294. }
  295. }
  296. @keyframes pageLoading2 {
  297. 20% {
  298. opacity: 0.5;
  299. transform: scale(1);
  300. }
  301. 60% {
  302. opacity: 1;
  303. transform: scale(1.5);
  304. }
  305. 80% {
  306. opacity: 0.5;
  307. transform: scale(1);
  308. }
  309. }
  310. @keyframes pageLoading3 {
  311. 40% {
  312. opacity: 0.5;
  313. transform: scale(1);
  314. }
  315. 80% {
  316. opacity: 1;
  317. transform: scale(1.5);
  318. }
  319. 100% {
  320. opacity: 0.5;
  321. transform: scale(1);
  322. }
  323. }
  324. .animate1 {
  325. animation: pageLoading1 1.2s infinite linear;
  326. }
  327. .animate2 {
  328. animation: pageLoading2 1.2s infinite linear;
  329. }
  330. .animate3 {
  331. animation: pageLoading3 1.2s infinite linear;
  332. }
  333. .grace-page-fixed-top {
  334. position: fixed;
  335. top: 44px;
  336. left: 0px;
  337. width: 750rpx;
  338. z-index: 99998;
  339. }
  340. </style>