lj-win-common.vue 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295
  1. <!--最基础的页面组件,管理app bar 页脚等基础布局-->
  2. <!--methods-->
  3. <!--打开右侧抽屉openRightDrawer()-->
  4. <!--关闭右侧抽屉closeRightDrawer()-->
  5. <!--slots-->
  6. <!--header_left:app bar左侧,通常为图标按钮-->
  7. <!--header:app bar中间,默认为标题-->
  8. <!--header_right:appbar 右侧,通常为图标按钮-->
  9. <!--header_sub: appbar下方子标题,固定在顶部-->
  10. <!--body:中间内容-->
  11. <!--footer:底部,固定,为兼容iPhone X以后的home indicator安全区域,不能过度使用div作辅助tag,slot声明尽量直接声明在实体tag中,或者用template代替div进行算法辅助-->
  12. <!--drawer_right:右侧抽屉-->
  13. <template>
  14. <div ref="baseDiv">
  15. <div class="background-color" :class="bgClass">
  16. <mu-appbar v-show="!hideAppBar" class="header" ref="headerDom" :color="headerBg" :textColor="headerTextColor">
  17. <div slot="left" style="position: absolute; z-index: 99; top: 0; left: 0;" ref="headerLeft">
  18. <slot name="header_left">
  19. <!-- 默认icon -->
  20. <mu-button icon v-if="showBack" @click="closeWin()">
  21. <i class="iconfont icon-left"></i>
  22. </mu-button>
  23. </slot>
  24. </div>
  25. <slot name="header">
  26. <div style="text-align: center;">
  27. <slot name="header_title">
  28. {{title}}
  29. </slot>
  30. </div>
  31. </slot>
  32. <div slot="right" style="position: absolute; z-index: 99; top: 0; right: 0;" ref="headerRight">
  33. <slot name="header_right">
  34. </slot>
  35. </div>
  36. </mu-appbar>
  37. <div id="headerSub" v-if="!hideHeaderSub" class="header-sub" v-bind:style="headerSubStyle">
  38. <slot name="header_sub"></slot>
  39. </div>
  40. <div class="content" v-bind:style="contentStyle" v-bind:class="bodyClass" ref="content">
  41. <template v-if="pullRefresh">
  42. <van-pull-refresh v-model="isLoading" @refresh="onRefresh">
  43. <slot name="body">
  44. </slot>
  45. </van-pull-refresh>
  46. </template>
  47. <template v-else>
  48. <slot name="body">
  49. </slot>
  50. </template>
  51. <!--<slot name="header_sub"></slot>-->
  52. <!--<sticky :offset="stickyOffset">-->
  53. <!--<slot name="header_sub"></slot>-->
  54. <!--</sticky>-->
  55. </div>
  56. <template v-if="simplefooter">
  57. <div class="footer">
  58. <slot name="footer" ref="footerInside">
  59. </slot>
  60. </div>
  61. </template>
  62. <mu-paper v-else class="footer" ref="footerDom" :zDepth="6">
  63. <slot name="footer" ref="footerInside">
  64. </slot>
  65. </mu-paper>
  66. </div>
  67. <mu-drawer :docked='false' right :open="rightDrawerOpen" @close="closeRightDrawer">
  68. <div class="drawer-content" :style="drawerStyle">
  69. <slot name="drawer_right">
  70. </slot>
  71. </div>
  72. </mu-drawer>
  73. </div>
  74. </template>
  75. <script>
  76. import {Sticky} from 'vux'
  77. export default {
  78. name: "lj-win-common",
  79. components: {
  80. "sticky": Sticky
  81. },
  82. props: {
  83. // 标题名称
  84. title: {
  85. type: String,
  86. default: "龙嘉软件"
  87. },
  88. // 背景div的css类
  89. bgClass: {
  90. type: [String, Array, Object]
  91. },
  92. // 内容div的css类
  93. bodyClass: {
  94. type: [String, Array, Object]
  95. },
  96. // 右侧抽屉标题
  97. rightDrawerTitle: {
  98. type: String,
  99. default: ""
  100. },
  101. // 右侧抽屉初始时是否打开
  102. rightDrawerInitOpen: {
  103. type: Boolean,
  104. default: false
  105. },
  106. // 是否显示返回按钮
  107. showBack: {
  108. type: Boolean,
  109. default: true
  110. },
  111. hideAppBar: {
  112. type: Boolean,
  113. default: false
  114. },
  115. closeWinHandler: {
  116. type: Function,
  117. },
  118. hideHeaderSub: {
  119. type: Boolean,
  120. default: false
  121. },
  122. headerBg: {
  123. type: String,
  124. default: "#fff"
  125. },
  126. headerTextColor: {
  127. type: String,
  128. default: "#000"
  129. },
  130. bodyClass: {
  131. type: String,
  132. default: ""
  133. },
  134. pullRefresh: {
  135. type: Boolean,
  136. default: false
  137. },
  138. simplefooter: {
  139. type: Boolean,
  140. default: false
  141. }
  142. },
  143. data() {
  144. return {
  145. rightDrawerOpen: false,
  146. contentStyle: {
  147. //变量名不能改,继承会引用到
  148. marginTop: "0px",
  149. marginBottom: "0px"
  150. },
  151. headerSubStyle: {
  152. top: "0"
  153. },
  154. drawerStyle: {},
  155. stickyOffset: 40,
  156. isLoading: false
  157. }
  158. },
  159. created() {
  160. this.rightDrawerOpen = this.rightDrawerInitOpen;
  161. },
  162. mounted() {
  163. this.initStyle();
  164. },
  165. updated() {
  166. this.initStyle();
  167. },
  168. methods: {
  169. onRefresh() {
  170. this.$emit("onRefresh", () => {
  171. this.isLoading = false;
  172. });
  173. },
  174. initStyle() {
  175. let appBarHeight = 0;
  176. // 兼容刘海屏
  177. $lj.fixStatusBar(this.$refs.headerDom.$el);
  178. $lj.fixStatusBar(this.$refs.headerLeft);
  179. $lj.fixStatusBar(this.$refs.headerRight);
  180. appBarHeight = $lj.getAppBarHeight();
  181. this.$refs.headerDom.$el.style.height = appBarHeight + "px";
  182. // 兼容iPhone X底部Home Indicator
  183. if (api.systemType === "ios") {
  184. if (this.$slots.footer) {
  185. let footerObj;
  186. for (let item of this.$slots.footer.reverse()) {
  187. if (item.tag) {
  188. footerObj = item;
  189. break;
  190. }
  191. }
  192. if (footerObj) {
  193. $lj.fixTabBar(footerObj.elm);
  194. }
  195. }
  196. }
  197. let footerHeight = 0;
  198. let headerSubHeight = 0;
  199. if (this.$refs.headerDom.$el) {
  200. appBarHeight = this.$refs.headerDom.$el.offsetHeight;
  201. }
  202. if (document.getElementById("headerSub")) {
  203. headerSubHeight = document.getElementById("headerSub").offsetHeight;
  204. }
  205. this.stickyOffset = appBarHeight;
  206. // if (this.$refs.footerDom.$el) {
  207. // footerHeight = this.$refs.footerDom.$el.offsetHeight;
  208. // } else {
  209. // footerHeight = this.$refs.footerDom.offsetHeight;
  210. // }
  211. if (this.$slots.footer) {
  212. let heightArr = [];
  213. this.$slots.footer.forEach(item => {
  214. if (item.elm.offsetHeight) {
  215. heightArr.push(item.elm.offsetHeight);
  216. }
  217. });
  218. footerHeight = Math.max.apply(null, heightArr);
  219. }
  220. // footerHeight += api.safeArea.bottom;
  221. let winHeight = 80;
  222. if (window.api) {
  223. winHeight = api.winHeight;
  224. }
  225. this.headerSubStyle.top = appBarHeight + "px";
  226. this.contentStyle.minHeight = (winHeight - appBarHeight - footerHeight - headerSubHeight) + "px";
  227. this.contentStyle.marginTop = appBarHeight + headerSubHeight + "px";
  228. this.contentStyle.marginBottom = footerHeight + "px";
  229. // console.log(' this.contentStyle :>>>>>>>>>>>>>>>>>>>>>!!!!!!!!!!!!!!!!!____________________________', JSON.stringify(this.contentStyle));
  230. this.$nextTick(() => {
  231. this.$emit('fix-body',this.contentStyle);
  232. });
  233. // 右侧抽屉
  234. // this.drawerStyle.minHeight = this.contentStyle.minHeight;
  235. // this.drawerStyle.marginTop = this.contentStyle.marginTop;
  236. },
  237. openRightDrawer() {
  238. this.rightDrawerOpen = true;
  239. },
  240. closeRightDrawer() {
  241. this.rightDrawerOpen = false;
  242. },
  243. closeWin() {
  244. if (this.closeWinHandler){
  245. this.closeWinHandler();
  246. } else {
  247. $lj.closeWin();
  248. }
  249. }
  250. }
  251. }
  252. </script>
  253. <style scoped lang="less">
  254. @import "~assets/css/lj-base.less";
  255. .header {
  256. width: 100%;
  257. position: fixed;
  258. top: 0;
  259. background-color: @appBarBackgroundColor;
  260. z-index: 999;
  261. }
  262. .content {
  263. width: 100%;
  264. margin: 0 auto;
  265. }
  266. .background-color {
  267. background-color: @winBackgroundColor;
  268. }
  269. .drawer-content {
  270. padding: 2rem;
  271. }
  272. .footer {
  273. position: fixed;
  274. bottom: 0;
  275. width: 100%;
  276. z-index: 99;
  277. }
  278. .header-sub {
  279. position: fixed;
  280. width: 100%;
  281. height: auto;
  282. background: white;
  283. z-index: 100;
  284. }
  285. </style>