honors.vue 10.9 KB
<!--
 * @Date: 2024-10-17 11:13:44
 * @LastEditors: hookehuyr hookehuyr@gmail.com
 * @LastEditTime: 2024-10-24 16:21:41
 * @FilePath: /hager/src/views/about/honors.vue
 * @Description: 关于海格-荣誉展示
-->
<template>
  <div class="hager-about-honors-page">
    <hager-box>
      <div style="margin-top: 1.5rem;">
        <el-breadcrumb separator="/">
          <el-breadcrumb-item>关于海格</el-breadcrumb-item>
          <el-breadcrumb-item>{{ $route.name }}</el-breadcrumb-item>
        </el-breadcrumb>
      </div>
    </hager-box>
    <div :class="['top-img', is_xs ? 'xs' : '']"></div>
    <hager-box v-if="!is_xs">
      <div class="select-btn-box">
        <div
          v-for="(item, index) in button_list" :key="index"
          :class="['btn', active_idx === index ? 'active' : 'normal']"
          @click="onClickBtn(index)">
          {{ item.category_name }}
        </div>
      </div>
    </hager-box>
    <div v-else class="select-btn-box" style="padding: 1rem;">
      <el-row :gutter="10">
        <el-col :span="8" v-for="(item, index) in button_list" :key="index">
          <div @click="onClickBtn(index)" :class="['btn xs', active_idx === index ? 'active' : 'normal']">{{ item.category_name }}</div>
        </el-col>
      </el-row>
    </div>
    <hager-box v-if="!is_xs" v-for="(item, index) in honors_cate_list" :key="index">
      <p class="list-title">{{ item.category_name }}</p>
      <div class="list-wrapper">
        <div class="card" v-for="(x, idx) in item.list" :key="idx">
          <div class="card-image-box">
            <div class="card-image" :style="{ backgroundImage: `url(${x.cover})` }"></div>
          </div>
          <div ref="contentDiv" :class="['card-content', active_idx === 0 ? 'a' : '', active_idx === 1 ? 'b' : '', active_idx === 2 ? 'c' : '', ]">
            <h3>{{ x.post_title }}</h3>
            <p v-if="x.post_content" v-html="x.post_content"></p>
          </div>
        </div>
      </div>
    </hager-box>
    <div v-if="is_xs" v-for="(item, index) in honors_cate_list" :key="index" style="padding: 1rem;">
      <p class="list-title">{{ item.category_name }}</p>
      <swiper class="swiper"
        :ref="'mySwiper' + item.id"
        :options="swiperOption"
        @slideChange="onSlideChange(item)"
      >
        <swiper-slide v-for="(x, idx) in item.list" :key="idx">
          <div class="list-wrapper-mini">
            <div class="card">
              <div class="card-image-box">
                <div class="card-image xs" :style="{ backgroundImage: `url(${x.cover})` }"></div>
              </div>
              <div class="card-content xs">
                <h3>{{ x.post_title }}</h3>
                <p v-if="x.post_content" class="content" v-html="x.post_content"></p>
              </div>
            </div>
          </div>
        </swiper-slide>
      </swiper>
      <div v-if="item.list.length > item.slidesPerView || is_xs" class="xs-control">
        <div>
          <i :class="['el-icon-arrow-left', item.activeIndex === 0 ? 'disabled' : '']" @click="prevBtn(item)"></i>&nbsp;
          <i :class="['el-icon-arrow-right', item.reach_end ? 'disabled' : '']" @click="nextBtn(item)"></i>
        </div>
      </div>
    </div>
    <!-- <hager-box>
      <hager-load-more></hager-load-more>
    </hager-box> -->
  </div>
</template>

<script>
import mixin from 'common/mixin';
import hagerBox from '@/components/common/hagerBox';
import hagerLoadMore from '@/components/hagerLoadMore.vue';
import { honorAPI } from "@/api/hager.js";

export default {
  components: { hagerBox, hagerLoadMore },
  mixins: [mixin.init],
  data () {
    return {
      active_idx: 0,
      button_list: [],
      all_honors_list: [],
      honors_cate_list: [],
      swiperOption: {
        slidesPerView: 2,
        spaceBetween: 20,
        preventClicks : true,
        slideToClickedSlide: false,
        touchRatio: 0,
        breakpoints: {
          1480: {
            slidesPerView: 5,
            spaceBetween: 30
          },
          1024: {
            slidesPerView: 5,
            spaceBetween: 30
          },
          768: {
            slidesPerView: 3,
            spaceBetween: 20
          },
          640: {
            slidesPerView: 2,
            spaceBetween: 10
          },
          320: {
            slidesPerView: 1,
            spaceBetween: 10
          },
          160: {
            slidesPerView: 1,
            spaceBetween: 0
          }
        }
      },
    }
  },
  async mounted () {
    const { code, data } = await honorAPI();
    if (code) {
      this.all_honors_list = data; // 所有荣誉集合
      // 荣誉分类列表
      this.button_list = data.map(item => {
        return {
          id: item.id,
          category_name: item.category_name
        }
      });
      this.honors_cate_list = this.all_honors_list[0]['children']; // 默认第一个
      this.honors_cate_list.forEach((item) => {
        this.$nextTick(() => {
          const swiperRef = this.$refs[`mySwiper${item.id}`];
          if (swiperRef && swiperRef[0].$swiper) {
            swiperRef[0].$swiper.on('breakpoint', (swiper) => {
              // breakpoint时 显示的条数
              item.slidesPerView = swiper.slidesPerView;
            });
          }
          this.checkOverflow();
        });
      });
      // 监听窗口的 resize 事件
      window.addEventListener('resize', this.checkOverflow);
    }
  },
  beforeDestroy() {
    // 在组件销毁前移除监听器,防止内存泄漏
    window.removeEventListener('resize', this.checkOverflow);
  },
  methods: {
    onClickBtn (idx) {
      this.active_idx = idx;
      this.honors_cate_list = this.all_honors_list[idx]['children'];
    },
    prevBtn (item) {
      this.$nextTick(() => {
        const swiperRef = this.$refs[`mySwiper${item.id}`];
        if (swiperRef && swiperRef[0].$swiper) {
          swiperRef[0].$swiper.slidePrev();
        }
      });
    },
    nextBtn (item) {
      this.$nextTick(() => {
        const swiperRef = this.$refs[`mySwiper${item.id}`];
        if (swiperRef && swiperRef[0].$swiper) {
          swiperRef[0].$swiper.slideNext();
        }
      });
    },
    onSlideChange (item) {
      item.activeIndex = this.$refs[`mySwiper${item.id}`][0].$swiper.activeIndex;
      const isEnd = this.$refs[`mySwiper${item.id}`][0].$swiper.isEnd;

      if (isEnd) {
        item.reach_end = true;
      } else {
        item.reach_end = false;
      }
    },
    checkOverflow () { // 检测内容是否超出,避免overflow IE显示问题
      this.$refs.contentDiv.forEach(div => {
        // 判断内容是否超出 div 的高度
        if (div.scrollHeight > div.clientHeight) {
          div.style.overflow = 'scroll';
        } else {
          div.style.overflow = 'visible';
        }
      });
    }
  }
}
</script>

<style lang="less" scoped>
  .hager-about-honors-page {
    .top-img {
      height: 22rem;
      background-image: url(https://cdn.ipadbiz.cn/hager/img/about/g21@2x.png);
      background-size: cover;
      background-position: center;
      background-repeat: no-repeat;
      margin: 2rem 0;
      &.xs {
        height: 12rem;
      }
    }

    .select-btn-box {
      margin-bottom: 2rem;
      &.xs {
        margin-bottom: 0;
      }
      .btn {
        width: 8rem;
        height: 2rem;
        line-height: 2rem;
        text-align: center;
        display: inline-block;
        padding: 0.5rem 0;
        margin-right: 1rem;
        &.xs {
          width: 100%;
        }
        &.active {
          background-color: @primary-color;
          color: #fff;
          font-weight: bold;
        }
        &.normal {
          background-color: #F3F3F3;
          color: @text-color;
          font-weight: none;
        }
        &:hover {
          cursor: pointer;
        }
      }
    }

    .list-title {
      font-size: 1.75rem;
      font-weight: bold;
      margin-bottom: 1rem;
      color: @secondary-color;
    }

    .list-wrapper {
      margin-bottom: 1rem;
      .card-image-box {
        padding: 0.5rem;
        background-color: #E3F1F7;
      }
      .card-image {
        width: 100%;
        height: 17rem;
        background-size: cover;
        background-position: center;
        background-repeat: no-repeat;
      }
      .card-content {
        background-color: #F7F7F7;
        padding: 2rem 1.5rem;
        padding-bottom: 0.5rem;
        overflow: scroll;
        &.a {
          height: 10rem;
        }
        &.b {
          height: 4rem;
        }
        &.c {
          height: 4rem;
        }
        h3 {
          color: @secondary-color;
          font-size: 1rem;
          margin: 0;
          height: 2rem;
          line-height: 1.5;
        }
        p {
          font-size: 0.95rem;
          line-height: 1.8;
          // height: 3rem;
          margin-bottom: 0.5rem;
          overflow: scroll;
        }
      }
    }

    .list-wrapper {
      display: flex;
      flex-wrap: wrap;
      justify-content: flex-start; /* 保证剩余元素靠左对齐 */
      align-items: stretch; /* 让所有子元素的高度保持一致 */
    }

    .card {
      flex: 0 0 32.33%; /* 设置宽度为 1/3 */
      margin-bottom: 1rem;
      margin-right: 1.5%; /* 每个项目之间的右侧留空 */
      box-sizing: border-box; /* 保证 padding 和 margin 不影响宽度计算 */
    }

    /* 确保每行的第三个元素没有右边距 */
    .card:nth-child(3n) {
      margin-right: 0;
    }

    /* 伪元素填充最后一行的剩余空间,确保它靠左对齐 */
    .list-wrapper::after {
      content: "";
      flex: auto;
    }

    /* 针对IE的处理 */
    @media all and (-ms-high-contrast: none), (-ms-high-contrast: active) {
      .card {
        width: 32.33%; /* 使用百分比宽度替代 flex-basis 以支持 IE */
        margin-right: 1.5%;
      }

      .card:nth-child(3n) {
        margin-right: 0;
      }
    }

    .list-wrapper-mini {
      margin-bottom: 1rem;
      .card-image-box {
        padding: 1rem;
        background-color: #E3F1F7;
      }
      .card-image {
        // width: 100%;
        height: 17rem;
        background-size: cover;
        background-position: center;
        background-repeat: no-repeat;
        &.xs {
          height: 15rem;
        }
      }
      .card-content {
        background-color: #F7F7F7;
        padding: 2rem 1.5rem;
        &.xs {
          // height: 2rem;
          padding-bottom: 0.5rem;
        }
        h3 {
          color: @secondary-color;
          font-size: 1rem;
          margin: 0;
          margin-bottom: 0.5rem;
          height: 3rem;
        }
        p {
          font-size: 0.95rem;
          line-height: 1.8;
          height: 8rem;
          overflow: scroll;
        }
      }
    }

    .xs-control {
      display: flex;
      justify-content: flex-end;
      margin-top: 1rem;
      i {
        font-size: 1.35rem;
        color: #EE6D10;
        &:hover {
          cursor: pointer;
        }
        &.disabled {
          color: #ccc;
        }
      }
    }
  }
</style>