index.vue 11.5 KB
<!--
 * @Date: 2024-09-27 16:53:09
 * @LastEditors: hookehuyr hookehuyr@gmail.com
 * @LastEditTime: 2024-11-11 09:28:03
 * @FilePath: /hager/src/views/product/index.vue
 * @Description: 文件描述
-->
<template>
  <div class="product-index">
    <hager-box v-if="!is_search">
      <div style="margin-top: 1.5rem;">
        <el-breadcrumb v-if="!is_all_cate" separator="/">
          <el-breadcrumb-item :to="{ path: allPath }">所有产品</el-breadcrumb-item>
          <el-breadcrumb-item v-if="parent_name" :to="{ path: productPath }">{{ parent_name }}</el-breadcrumb-item>
          <el-breadcrumb-item>{{ category_name }}</el-breadcrumb-item>
        </el-breadcrumb>
        <el-breadcrumb v-else separator="/">
          <el-breadcrumb-item>所有产品</el-breadcrumb-item>
        </el-breadcrumb>
      </div>
    </hager-box>
    <hager-box v-if="!is_xs && !is_search" :class="['top-img', is_xs ? 'xs' : '']" :style="{ backgroundImage: `url('https://cdn.ipadbiz.cn/hager/img/product/banner-l@2x.png'), url(${banner})`, marginTop: '1rem' }">
      <div class="banner-text-wrapper" style="margin-top: 5%;">
        <div class="text">
          <p class="title" style="margin-bottom: 0; color: white; font-size: 2.2vw;">{{ category_name }}</p>
          <p class="sub" style="color: white; font-size: 2.2vw;">{{ category_name_en }}</p>
          <div style="margin-top: 1rem; font-weight: normal; font-size: 1.15vw; color: white; width: 50%;">
            <p v-html="category_description"></p>
          </div>
        </div>
      </div>
    </hager-box>
    <hager-box>
      <div v-if="!is_xs">
        <hager-h1 v-if="is_search" :title="'与“' + keyword + '”相关的搜索结果'" :sub="''" style="margin: 2rem 0;"></hager-h1>
      </div>
      <div v-else>
        <hager-h1 v-if="!is_search" :title="category_name" :sub="category_name_en" style="margin: 2rem 0;"></hager-h1>
        <hager-h1 v-else :title="'与“' + keyword + '”相关的搜索结果'" :sub="''" style="margin: 2rem 0;"></hager-h1>
      </div>
    </hager-box>
    <hager-box>
      <el-row v-if="!is_xs" :gutter="0" style="margin: 1rem 0;">
        <el-col :span="6">
          <div class="product-nav-wrapper">
            <div class="product-nav-title">按产品类别查找</div>
            <el-input style="margin-bottom: 0.5rem;" placeholder="请输入产品" prefix-icon="el-icon-search" v-model="search_keyword" @change="goToSearch"></el-input>
            <!-- <el-collapse v-if="!is_all_cate" v-model="activeNames" @change="handleChange">
              <el-collapse-item v-for="(item, index) in cate_list" :key="index" :title="item.category_name" :name="item.category_name">
                <div @click="goToDetail(c)" v-for="(c, idx) in item.list" :key="idx" class="p-item">{{ c.product_name }}</div>
              </el-collapse-item>
            </el-collapse> -->
            <Accordion v-if="!is_all_cate" :items="cate_list" />
            <Accordion v-else :items="all_cate_list" />
          </div>
        </el-col>
        <el-col :span="18">
          <div class="product-list">
            <div class="product-item" v-for="(item, index) in product_list" :key="index">
              <div class="product-item-img" @click="goToDetail(item)">
                <img style="width: 100%; height: auto;" :src="item.cover">
              </div>
              <p @click="goToDetail(item)" class="product-item-title">{{ item.product_name }}</p>
            </div>
          </div>
          <div style="height: 5rem;"></div>
        </el-col>
      </el-row>
      <div v-else class="product-list">
        <div class="product-item xs" v-for="(item, index) in product_list" :key="index">
          <div @click="goToDetail(item)" class="product-item-img xs">
            <img style="width: 35vw; height: auto;" :src="item.cover">
          </div>
          <p @click="goToDetail(item)" class="product-item-title">{{ item.product_name }}</p>
        </div>
      </div>
      <div style="height: 5rem;"></div>
    </hager-box>
  </div>
</template>

<script>
import mixin from 'common/mixin';
import hagerBox from '@/components/common/hagerBox';
import hagerH1 from '@/components/common/hagerH1.vue';
import Accordion from '@/components/accordion/Accordion.vue';
import { getProductCateAPI, getProductSearchAPI } from "@/api/hager.js";
import $ from 'jquery';

export default {
  components: { hagerBox, hagerH1, Accordion },
  mixins: [mixin.init],
  data () {
    return {
      search_keyword: '',
      keyword: '',
      activeNames: [],
      cate_id: '',
      parent_name: '',
      category_name: '所有产品',
      category_name_en: 'All Products',
      category_description: '',
      banner: '',
      cate_list: [],
      product_list: [],
      no_product_img: 'https://cdn.ipadbiz.cn/hager/img/no-product-img.png',
      is_search: false,
      all_cate_list: [],
    }
  },
  async mounted () {
    if (!this.is_all_cate) {
      this.getMain();
    } else { // 没有ID显示所有产品
      this.getAllMain();
    }
    window.addEventListener('resize', this.changeImgHeight);
  },
  beforeDestroy() {
    // 在组件销毁前移除监听器,防止内存泄漏
    window.removeEventListener('resize', this.handleHeightResize);
  },
  computed: {
    allPath () {
      return `/product/index?timestamp=${Date.now()}`;
    },
    productPath () {
      return `/product/index?id=${this.cate_id}&timestamp=${Date.now()}`;
    },
    is_all_cate () {
      return this.$route.query.id === undefined;
    }
  },
  watch: {
    // 监听路由参数变化时,更新输入框的值
    '$route.query.id' (val, old) {
      if (val) {
        if (old !== val) {
          this.is_search = false;
          this.getMain();
        }
      } else {
        // 所有产品
        this.getAllMain();
      }
    },
    '$route.query.timestamp' (val, old) {
      this.is_search = false;
      if (!this.is_all_cate) {
        this.getMain();
      } else {
        // 所有产品
        this.getAllMain();
      }
    },
  },
  methods: {
    changeImgHeight () {
      this.$nextTick(() => {
        // 动态计算图片高度
        let img_width = $('.product-item-img img').outerWidth();
        $('.product-item-img img').css('height', img_width * 1 + 'px');
        let banner_width = $('.top-img').outerWidth();
        $('.top-img').css('height', banner_width * 0.21 + 'px');
      })
    },
    handleChange(val) {
    },
    goToDetail (v) { // 跳转产品详情
      this.$router.push({
        path: '/product/detail',
        query: {
          id: v.id,
          category_id: this.$route.query.id
        }
      });
    },
    async getAllMain () { // 查询所有产品列表数据
      this.getCurrentCate();
      const { code, data } = await getProductCateAPI({ cid: 0 });
      if (code) {
        let info = data[0];
        this.category_name = '所有产品';
        this.category_name_en = 'All Products';
        this.category_description = '';
        this.banner = 'https://cdn.ipadbiz.cn/hager/img/product/banner-r@2x.png';
        this.product_list = info.list;

        this.search_keyword = '';
        // 设置页面标题
        document.title = '所有产品 | Hager China';
        // 动态计算图片高度
        this.changeImgHeight();
      }
    },
    async getMain () {
      const { code, data } = await getProductCateAPI({cid: this.$route.query.id });
      if (code) {
        let info = data[0];
        this.parent_name = info.parent_name;
        this.category_name = info.category_name;
        this.category_name_en = info.category_name_en;
        this.category_description = info.category_description;
        this.banner = info.banner;
        this.product_list = info.list;

        this.search_keyword = '';
        // 获取当前类别的内容
        this.cate_id = info.category_parent ? info.category_parent : info.id; // 同一个值,在不同层级下名字不一样
        this.getCurrentCate(this.cate_id);
        // 设置页面标题
        document.title = this.category_name + '  | Hager China';
        // 动态计算图片高度
        this.changeImgHeight();
      }
    },
    async getCurrentCate (cate_id) {
      const { code, data } = await getProductCateAPI();
      if (code) {
        if (cate_id) {
          data.forEach((item) => {
            if (item.id === cate_id) {
              this.cate_list = item.children;
              // 重构数据结构配合组件
              this.cate_list.forEach((c) => {
                c.children = c.list;
                c.style = {fontWeight: 'normal', height: '2.5rem'}
                c.children.forEach((d) => {
                  d.category_name = d.product_name
                })
              })
            }
          });
        } else {
          // 所有分类列表
          this.all_cate_list = data;
          // 重构数据结构配合组件
          this.all_cate_list.forEach((item) => {
            item.children.forEach((c) => {
              c.children = c.list;
              c.style = {fontWeight: 'normal', height: '2.5rem'}
              c.children.forEach((d) => {
                d.category_name = d.product_name
              })
            })
          })
        }
      }
    },
    async goToSearch () {
      if (this.search_keyword) { // 产品有值时操作
        const { code, data } = await getProductSearchAPI({ keyword: this.search_keyword });
        if (code) {
          this.product_list = data;
          this.is_search = true;
          this.keyword = this.search_keyword;
        }
      } else { // 清空搜索值,还原
        if (!this.is_all_cate) {
          this.getMain();
        } else {
          // 所有产品
          this.getAllMain();
        }
        this.is_search = false;
        this.keyword = '';
      }
    },
  }
}
</script>

<style lang="less">
  .product-index {
    .product-nav-wrapper {
      border: 1px solid #eee;
      border-radius: 5px;
      padding: 1.5rem;
      margin-right: 1rem;
      .product-nav-title {
        color: @secondary-color;
        font-weight: bold;
        font-size: 1.15rem;
        margin-bottom: 0.5rem;
      }
    }

    .top-img {
      background-size: 50% 100%; /* 每张背景图各占 50% 的宽度,100% 的高度 */
      background-position: left, right; /* 第一张图在左侧,第二张图在右侧 */
      background-repeat: no-repeat; /* 避免背景图重复 */
      position: relative;
      width: 100%;
      height: 25rem; /* 或根据需要指定高度 */
      &.xs {
        height: 12rem;
      }
      .top-center {
        position: absolute;
        transform: translateY(50%); /* 垂直与水平居中 */
      }
    }

    .product-list {
      display: flex;
      flex-wrap: wrap;
    }
    .product-item {
      width: calc(33.33% - 1rem);
      margin-bottom: 1rem;
      margin-right: 1rem;
      &.xs {
        width: calc(50% - 1rem);
      }
    }
    .product-item-img {
      background-color: #fff;
      display: flex;
      align-items: center;
      justify-content: center;
      height: 18rem;
      padding: 2vw;
      box-sizing: border-box;
      border-radius: 8px;
      border: 1px solid #eee;
      overflow: hidden;
      &:hover {
        cursor: pointer;
      }
    }
    .product-item-title {
      // text-align: center;
      margin-top: 0.75rem;
      color: @text-color;
      font-weight: bold;
      padding-left: 1rem;
      &:hover {
        cursor: pointer;
        text-decoration: underline;
      }
    }
  }

  .el-collapse {
    border-top: 0;
  }
  .el-collapse-item {
    .el-collapse-item__header {
      font-size: 0.9rem;
    }
    .p-item {
      &:hover {
        cursor: pointer;
        text-decoration: underline;
      }
    }
  }
</style>