<!--
 * @Author: ch
 * @Date: 2022-05-04 17:25:41
 * @LastEditors: ch
 * @LastEditTime: 2022-05-04 17:26:08
 * @Description: file content
-->
<template>
  <div class="seckill">
    <div v-show="isSticky" class="seckill-header-sticky">
      <TabBar
        :tab-id="query.activityTimeId"
        :list="tabList"
        @tab-change="handleTabChange"
      />
    </div>
    <!-- 秒杀时间段 -->
    <div
      class="seckill-header"
      :style="{ backgroundImage: `url(${bkgSckill})` }"
    >
      <div class="seckill-header-tabbar">
        <TabBar
          :tab-id="query.activityTimeId"
          :list="tabList"
          @tab-change="handleTabChange"
        />
      </div>
    </div>
    <!-- 倒计时展示 -->
    <div
      v-if="tabList.length > 0"
      class="seckill-bar flex flex-middle flex-center"
    >
      <p>{{ seckillTip }}</p>
      <div class="seckill-bar-countdown flex flex-middle">
        <div class="seckill-bar-countdown__time">{{ countdown.hour }}</div>
        <span class="seckill-bar-countdown--mark">:</span>
        <div class="seckill-bar-countdown__time">{{ countdown.minute }}</div>
        <span class="seckill-bar-countdown--mark">:</span>
        <div class="seckill-bar-countdown__time">{{ countdown.second }}</div>
      </div>
    </div>
    <!-- 秒杀商品列表 -->
    <div v-loading="loading">
      <div class="seckill-products flex flex-wrap">
        <div
          v-for="item in goodsList"
          :key="item.productId"
          @click="onJumpGoodsDetail(item.productId)"
          class="seckill-products-wrap"
        >
          <div class="seckill-products-wrap__cover">
            <img :src="item.productMainPicture" />
            <div
              v-if="item.percentage === 100"
              class="products-wrap-cover__sold flex flex-middle flex-center"
            >
              已售罄
            </div>
          </div>
          <div class="seckill-products-wrap__content">
            <p class="products-wrap-content__title">{{ item.productName }}</p>
            <div class="products-wrap-content__price">
              <strong>￥{{ item.activityPrice }}</strong>
              <del>￥{{ item.originalPrice }}</del>
            </div>
            <div
              class="products-wrap-content__footer flex flex-middle flex-between"
            >
              <div class="wrap-content-footer__stock">
                <el-progress
                  :percentage="item.percentage"
                  :show-text="false"
                ></el-progress>
                <p>仅剩{{ item.stock }}件</p>
              </div>
              <div
                v-if="item.percentage === 100"
                class="wrap-content-footer__btn wrap-content-footer__btn--gray"
              >
                已售罄
              </div>
              <div v-else class="wrap-content-footer__btn">
                {{ goodsBtnText }}
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>
    <!-- 分页 -->
    <div class="seckill-pagination flex flex-right">
      <UiPagination
        :current-page="currentPage"
        :page-size="query.length"
        :total="total"
        @current-change="handleCurrentChange"
      >
        <el-button class="btn-confirm">确定</el-button>
      </UiPagination>
    </div>
    <DialogEnd :visible="seckillEndVisible" @close="handleClose" />
  </div>
</template>
<script>
import UiPagination from "@/components/UiPagination.vue";
import {
  ApiGetSeckillTimes,
  ApiGetSeckillGoods,
  ApiGetCurrentTime,
} from "@/plugins/api/seckill";
import { SECKILL_STATUS } from "@/constants";
import TabBar from "./module/TabBar.vue";
import DialogEnd from "./module/DialogEnd.vue";
const PAGE_SIZE = 16;

export default {
  name: "Sckill",
  components: { TabBar, DialogEnd, UiPagination },
  data() {
    return {
      bkgSckill: require("~/assets/img/sckill/bkg-large.png"),
      tabList: [], // 秒杀时间段
      goodsList: [], // 商品列表
      total: 0,
      currentPage: 0,
      loading: false,
      query: {
        pageIndex: 1,
        length: PAGE_SIZE,
        activityTimeId: 0,
      },
      ticking: false,
      isSticky: false,
      timeInterval: null, // 倒计时定时器
      seckillTip: "", // 秒杀提示文案
      seckillTime: 0, // 秒杀时间
      seckillEndVisible: false, //秒杀结束弹窗
      seckillStatus: SECKILL_STATUS.NOT_START, // 当前秒杀时间段状态
      inProgressId: 0, // 秒杀中的活动id
    };
  },
  computed: {
    countdown() {
      const data = parseInt(this.seckillTime / 1e3);
      const hour = Math.floor(data / 60 / 60);
      const minute = Math.floor((data / 60) % 60);
      const second = Math.floor(data % 60);
      return {
        hour: hour < 10 ? `0${hour}` : `${hour}`,
        minute: minute < 10 ? `0${minute}` : `${minute}`,
        second: second < 10 ? `0${second}` : `${second}`,
      };
    },
    goodsBtnText() {
      return this.query.activityTimeId === this.inProgressId
        ? "立即开抢"
        : "即将开抢";
    },
  },
  watch: {
    // 切换秒杀时间段
    "query.activityTimeId": {
      immediate: true,
      handler(val) {
        if (val === 0) {
          return;
        }
        clearImmediate(this.timeInterval);
        const tabItem = this.tabList.find((item) => item.id === val);
        if (tabItem) {
          const { activityStartTime, activityEndTime } = tabItem;
          this.setTimerInterval({
            startTime: activityStartTime,
            endTime: activityEndTime,
          });
        }
      },
    },
  },

  created() {
    this.getSeckillTimes();
  },
  mounted() {
    // 监听滚动事件
    window.addEventListener("scroll", this.scrollEventMethod);
  },
  destroyed() {
    window.removeEventListener("scroll", this.scrollEventMethod);
    clearInterval(this.timeInterval);
  },
  methods: {
    scrollEventMethod() {
      const that = this;
      // 节流
      if (!that.ticking) {
        window.requestAnimationFrame(function () {
          that.ticking = false;
          that.isSticky = window.scrollY > 400;
        });
        that.ticking = true;
      }
    },
    async getSeckillTimes() {
      const { result } = await ApiGetSeckillTimes();
      if (result && result.length > 0) {
        this.tabList = result;
        const inProgressItem = result.find((item) => item.isInProgress);
        if (inProgressItem) {
          this.inProgressId = inProgressItem.id;
          this.query.activityTimeId = inProgressItem.id;
        } else {
          this.query.activityTimeId = result[0].id;
        }
        this.getGoodsList();
        return;
      }
      this.seckillEndVisible = true;
    },
    async getGoodsList() {
      this.loading = true;
      const { result } = await ApiGetSeckillGoods({ ...this.query });
      this.loading = false;
      if (result) {
        this.total = result.total;
        this.goodsList = result.records.map((item) => {
          // 售出数量
          const saleNumber = item.number - item.stock;
          return {
            ...item,
            percentage:
              saleNumber === 0
                ? 0
                : (saleNumber / item.number).toFixed(2) * 100,
          };
        });
      }
    },

    // 设置定时器
    async setTimerInterval({ startTime, endTime }) {
      clearInterval(this.timeInterval);

      // 获取服务器当前时间
      const { result } = await ApiGetCurrentTime();
      const current = result || Date.now();

      startTime = new Date(startTime).getTime();
      endTime = new Date(endTime).getTime();
      if (current > endTime) {
        // 秒杀结束
        this.getSeckillTimes();
        this.queryDataReset();
        return;
      }
      if (startTime < current && endTime > current) {
        // 秒杀进行中
        this.seckillTime = endTime - current;
        this.seckillTip = "本场正在秒杀中，好物转瞬即逝，不要错过哦~距结束仅剩";
        this.seckillStatus = SECKILL_STATUS.GOING;
      } else {
        // 秒杀未开始
        this.seckillTime = startTime - current;
        this.seckillTip = "本场秒杀即将开抢，距开始还剩";
        this.seckillStatus = SECKILL_STATUS.NOT_START;
      }

      this.timeInterval = setInterval(() => {
        if (this.seckillTime <= 0) {
          clearInterval(this.timeInterval);

          // 仅有一个进行中的秒杀时间段，倒计时完成展示结束弹窗
          if (
            this.tabList.length === 1 &&
            this.seckillStatus === SECKILL_STATUS.GOING
          ) {
            this.seckillEndVisible = true;
            this.$store.commit("setSeckillTabVisible", false);
            return;
          }

          // 秒杀开始，activityTimeId重置，触发watch
          this.query.activityTimeId = 0;
          this.getSeckillTimes();
          return;
        }
        this.seckillTime -= 1e3;
      }, 1e3);
    },

    // 重置分页等数据
    queryDataReset() {
      Object.assign(this.query, {
        pageIndex: 1,
        length: PAGE_SIZE,
      });
    },
    onJumpGoodsDetail(id) {
      window.open(`${location.origin}/goods/detail/${id}`);
    },
    handleCurrentChange(page) {
      this.query.pageIndex = page;
      this.getGoodsList();
    },
    handleTabChange(id) {
      this.query.activityTimeId = id;
      this.queryDataReset();
      this.getGoodsList();
    },

    // 离开活动页面
    handleClose() {
      this.$router.push("/");
    },
  },
};
</script>
<style lang="scss" scoped>
.seckill {
  background: #f8f8f8;
  padding-bottom: 60px;
  .seckill-header-sticky {
    position: fixed;
    left: 50%;
    transform: translate(-50%);
    top: 50px;
    z-index: 1;
    @include layout-box;
  }
  .seckill-header {
    position: relative;
    width: 100%;
    height: 156px;
    background-size: 100% 100%;
    .seckill-header-tabbar {
      @include layout-box;
      position: absolute;
      left: 50%;
      bottom: 0;
      transform: translate(-50%);
    }
  }
  .seckill-bar {
    height: 60px;
    line-height: 60px;
    text-align: center;
    font-size: 14px;
    color: #666666;
    .seckill-bar-countdown {
      margin-left: 25px;
      font-weight: bold;
      &__time {
        width: 22px;
        height: 22px;
        line-height: 22px;
        text-align: center;
        font-size: 14px;
        color: #ffffff;
        background: #2f3430;
      }
      &--mark {
        display: block;
        margin: 0 7px;
        color: #2f3430;
      }
    }
  }
  .seckill-products,
  .seckill-pagination {
    @include layout-box;
  }
  .seckill-products {
    .seckill-products-wrap {
      width: 24%;
      background: #ffffff;
      margin-bottom: 16px;
      cursor: pointer;
      &:not(:nth-child(4n)) {
        margin-right: calc(4% / 3);
      }
      &:hover {
        box-shadow: 0px 0px 10px 1px rgba(0, 0, 0, 0.1);
      }
      .seckill-products-wrap__cover {
        position: relative;
        width: 100%;
        height: 288px;
        img {
          width: 100%;
          height: 100%;
        }
        .products-wrap-cover__sold {
          position: absolute;
          width: 110px;
          height: 110px;
          left: 50%;
          top: 50%;
          transform: translate(-50%, -50%);
          background: rgba(0, 0, 0, 0.5);
          font-size: 24px;
          color: #ffffff;
          border-radius: 50%;
        }
      }
      .seckill-products-wrap__content {
        padding: 20px 16px;
        .products-wrap-content__title {
          @include ellipsis;
          color: #333333;
          font-size: 16px;
          margin-bottom: 10px;
        }
        .products-wrap-content__price {
          font-size: 12px;
          color: #999999;
          margin-bottom: 7px;
          strong {
            font-size: 18px;
            color: #ff512b;
            margin-right: 14px;
          }
        }
        .products-wrap-content__footer {
          .wrap-content-footer__stock {
            font-size: 12px;
            color: #666666;
            /deep/.el-progress {
              width: 100px;
              height: 6px;
              background: #dddddd;
              border-radius: 4px;
              margin-bottom: 8px;
            }
          }
          .wrap-content-footer__btn {
            width: 100px;
            height: 36px;
            line-height: 36px;
            text-align: center;
            background: #ff512b;
            font-size: 14px;
            color: #ffffff;
            &--gray {
              color: #999999;
              background: #eeeeee;
            }
          }
        }
      }
    }
  }
  .seckill-pagination {
    .btn-confirm {
      width: 81px;
      height: 32px;
      border-radius: 2px;
      margin-left: 14px;
    }
  }
}
</style>
