|
|
|
@ -9,9 +9,9 @@
|
|
|
|
|
<div class="seckill">
|
|
|
|
|
<div v-show="isSticky" class="seckill-header-sticky">
|
|
|
|
|
<TabBar
|
|
|
|
|
v-model="query.activityTimeId"
|
|
|
|
|
:tab-id="query.activityTimeId"
|
|
|
|
|
:list="tabList"
|
|
|
|
|
@tab-click="getGoodsList"
|
|
|
|
|
@tab-change="handleTabChange"
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
<!-- 秒杀时间段 -->
|
|
|
|
@ -21,13 +21,17 @@
|
|
|
|
|
>
|
|
|
|
|
<div class="seckill-header-tabbar">
|
|
|
|
|
<TabBar
|
|
|
|
|
v-model="query.activityTimeId"
|
|
|
|
|
:tab-id="query.activityTimeId"
|
|
|
|
|
:list="tabList"
|
|
|
|
|
@tab-click="getGoodsList"
|
|
|
|
|
@tab-change="handleTabChange"
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="seckill-bar flex flex-middle flex-center">
|
|
|
|
|
<!-- 倒计时展示 -->
|
|
|
|
|
<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>
|
|
|
|
@ -81,16 +85,23 @@
|
|
|
|
|
</el-pagination>
|
|
|
|
|
<el-button class="btn-confirm">确定</el-button>
|
|
|
|
|
</div>
|
|
|
|
|
<DialogEnd :visible="seckillEndVisible" @close="handleClose" />
|
|
|
|
|
</div>
|
|
|
|
|
</template>
|
|
|
|
|
<script>
|
|
|
|
|
import { ApiGetSeckillTimes, ApiGetSeckillGoods } from "@/plugins/api/seckill";
|
|
|
|
|
import { FormatDate } from "@/plugins/utils";
|
|
|
|
|
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 },
|
|
|
|
|
components: { TabBar, DialogEnd },
|
|
|
|
|
data() {
|
|
|
|
|
return {
|
|
|
|
|
bkgSckill: require("~/assets/img/sckill/bkg-large.png"),
|
|
|
|
@ -101,38 +112,49 @@ export default {
|
|
|
|
|
loading: false,
|
|
|
|
|
query: {
|
|
|
|
|
pageIndex: 1,
|
|
|
|
|
length: 16,
|
|
|
|
|
activityTimeId: 1,
|
|
|
|
|
length: PAGE_SIZE,
|
|
|
|
|
activityTimeId: 0,
|
|
|
|
|
},
|
|
|
|
|
ticking: false,
|
|
|
|
|
isSticky: false,
|
|
|
|
|
timeInterval: null, // 倒计时定时器
|
|
|
|
|
seckillTip: "", // 秒杀提示文案
|
|
|
|
|
seckillTime: 0, // 秒杀时间
|
|
|
|
|
seckillEndVisible: false, //秒杀结束弹窗
|
|
|
|
|
seckillStatus: SECKILL_STATUS.NOT_START, // 当前秒杀时间段状态
|
|
|
|
|
};
|
|
|
|
|
},
|
|
|
|
|
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: "01",
|
|
|
|
|
minute: "32",
|
|
|
|
|
second: "09",
|
|
|
|
|
hour: hour < 10 ? `0${hour}` : `${hour}`,
|
|
|
|
|
minute: minute < 10 ? `0${minute}` : `${minute}`,
|
|
|
|
|
second: second < 10 ? `0${second}` : `${second}`,
|
|
|
|
|
};
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
// 当前选中时间段
|
|
|
|
|
currentTabItem() {
|
|
|
|
|
const tabItem = this.tabList.find(
|
|
|
|
|
(item) => item.id === this.query.activityTimeId
|
|
|
|
|
);
|
|
|
|
|
return tabItem || null;
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
// 当前时间段秒杀文案
|
|
|
|
|
seckillTip() {
|
|
|
|
|
if (this.currentTabItem) {
|
|
|
|
|
return this.currentTabItem.isInProgress
|
|
|
|
|
? "本场正在秒杀中,好物转瞬即逝,不要错过哦~距结束仅剩"
|
|
|
|
|
: "本场秒杀即将开抢,距开始还剩";
|
|
|
|
|
}
|
|
|
|
|
return "";
|
|
|
|
|
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,
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
@ -145,6 +167,7 @@ export default {
|
|
|
|
|
},
|
|
|
|
|
destroyed() {
|
|
|
|
|
window.removeEventListener("scroll", this.scrollEventMethod);
|
|
|
|
|
clearInterval(this.timeInterval);
|
|
|
|
|
},
|
|
|
|
|
methods: {
|
|
|
|
|
scrollEventMethod() {
|
|
|
|
@ -177,6 +200,64 @@ export default {
|
|
|
|
|
this.goodsList = result.records;
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
// 设置定时器
|
|
|
|
|
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;
|
|
|
|
|
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) {
|
|
|
|
|
this.$router.push(`/goods/detail/${id}`);
|
|
|
|
|
},
|
|
|
|
@ -188,12 +269,15 @@ export default {
|
|
|
|
|
this.query.pageIndex = page;
|
|
|
|
|
this.getGoodsList();
|
|
|
|
|
},
|
|
|
|
|
handleTabSelect(id) {
|
|
|
|
|
handleTabChange(id) {
|
|
|
|
|
this.query.activityTimeId = id;
|
|
|
|
|
Object.assign(this.query, {
|
|
|
|
|
pageIndex: 1,
|
|
|
|
|
length: 16,
|
|
|
|
|
});
|
|
|
|
|
this.queryDataReset();
|
|
|
|
|
this.getGoodsList();
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
// 离开活动页面
|
|
|
|
|
handleClose() {
|
|
|
|
|
this.$router.push("/");
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
};
|
|
|
|
@ -256,7 +340,7 @@ export default {
|
|
|
|
|
.seckill-products-wrap {
|
|
|
|
|
width: 24%;
|
|
|
|
|
background: #ffffff;
|
|
|
|
|
margin: 15px 0 60px 0;
|
|
|
|
|
margin-bottom: 16px;
|
|
|
|
|
cursor: pointer;
|
|
|
|
|
&:not(:nth-child(4n)) {
|
|
|
|
|
margin-right: calc(4% / 3);
|
|
|
|
|