layout-header.vue 3.59 KB
<template>
  <div class="layout-header-wrap" v-if="!hide" :class="{[`theme-${theme}`]: theme}" :style="statusBarHeight">
    <div class="layout-header">
      <div class="back flex hover-opacity" @touchend.stop.prevent="onBack">
        <slot name="back" v-if="back && canShowBack">
          <i class="iconfont icon-left"></i>
        </slot>
      </div>
      <div class="title flex" :style="{opacity}">
        <slot>
          <span class="title-inner">{{title}}</span>
        </slot>
      </div>
      <div class="opts flex" :style="{opacity}">
        <slot name="opts"></slot>
      </div>
    </div>
    <div class="suction-top-block">
      <slot name="suctionTop"></slot>
    </div>
  </div>
</template>

<script>
import {mapState} from 'vuex';

export default {
  name: 'LayoutHeader',
  props: {
    title: String,
    theme: String,
    fixed: Boolean,
    back: {
      type: Boolean,
      default: true
    },
    transparentSeek: Number,
    opacity: {
      type: Number,
      default: 1
    },
    hide: Boolean
  },
  title(setTitle) {
    if (!setTitle) {
      return this.title;
    }
    if (this.title) {
      setTitle(this.title);
    }
    this.setTitle = setTitle;
  },
  computed: {
    ...mapState(['yoho']),
    canShowBack() {
      return !this.yoho.context.env.isChat;
    },
    statusBarHeight() {
      if (this.yoho.window && this.yoho.window.statusBarStatus && this.yoho.window.statusBarHeight) {
        return {paddingTop: this.yoho.window.statusBarHeight + 'px'};
      }

      return {};
    }
  },
  watch: {
    transparentSeek(value) {
      this.animeEl && this.animeEl.seek(this.animeEl.duration * value);
    },
    title(val) {
      if (val) {
        this.setTitle && this.setTitle(val);
      }
    }
  },
  mounted() {
    if (this.transparentSeek >= 0) {
      import('animejs').then(({default: anime}) => {
        this.animeEl = anime({
          targets: this.$el,
          backgroundColor: '#222',
          easing: 'easeInOutQuad',
          autoplay: false
        });
      });
    }
  },
  methods: {
    onBack() {
      if (this.yoho.homePage) {
        this.$bus.$emit('beforeFinishPage');
        this.$yoho.safetyInterface(() => {
          this.$yoho.finishPage({});
        });
      } else {
        this.$router.go(-1);
      }
    }
  }
};
</script>

<style lang="scss" scoped>
.layout-header-wrap {
  width: 100%;
  background-color: #444;
  color: #fff;

  &.theme-white {
    background-color: #fff;
    color: #222;

    .layout-header {
      border-bottom: solid 1px #efefef;
    }
  }

  &.theme-transparent {
    background-color: initial;
    color: #fff;
  }
}

.layout-header {
  width: 100%;
  height: 44PX;
  overflow: hidden;
  display: flex;
  align-items: stretch;
  box-sizing: border-box;

  > * {
    position: relative;
  }

  .flex {
    display: flex;
    align-items: center;
  }

  .iconfont {
    height: 100%;
    font-size: 20PX;
    display: flex;
    align-items: center;
    justify-content: center;
    padding-left: 10PX;
    padding-right: 10PX;
  }

  .back {
    width: 160px;
    padding-left: 5px;
  }

  .title {
    flex: 1;
    justify-content: center;
    font-size: 18PX;
    letter-spacing: 0.09PX;
    overflow: hidden;
    z-index: 1;

    .title-inner {
      max-width: 90%;
      line-height: 1.4;
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
      display: inline-block;
    }
  }

  .opts {
    width: 160px;
    height: inherit;
    justify-content: flex-end;
    padding-right: 5px;

    .iconfont {
      font-size: 23PX;
    }
  }
}

.suction-top-block {
  width: 100%;
  position: absolute;
}
</style>