2025-01-18 20:08:14 +08:00
|
|
|
<template>
|
2025-01-19 10:30:37 +08:00
|
|
|
<div class="ad" v-show="ads.length && isShow">
|
2025-01-18 20:08:14 +08:00
|
|
|
<div class="header">
|
2025-01-19 12:12:51 +08:00
|
|
|
<div class="title">Recommend</div>
|
|
|
|
<div class="line"></div>
|
2025-01-19 10:30:37 +08:00
|
|
|
<div class="close" @click="onClose" :title="closeTitle">
|
2025-01-19 13:22:26 +08:00
|
|
|
<div class="icon">x</div>
|
2025-01-18 20:08:14 +08:00
|
|
|
</div>
|
|
|
|
</div>
|
2025-01-19 10:30:37 +08:00
|
|
|
<div class="body" @mouseenter="onMouseEnter" @mouseleave="onMouseLeave">
|
2025-01-18 20:08:14 +08:00
|
|
|
<div class="left slide" @click="onClickBtnLeft">
|
2025-01-19 13:22:26 +08:00
|
|
|
<div class="arrow"><</div>
|
2025-01-18 20:08:14 +08:00
|
|
|
</div>
|
|
|
|
<div class="list" ref="elAd" @wheel="onWheel">
|
|
|
|
<Banner v-for="(item, index) in ads" :data="item" :key="index"></Banner>
|
|
|
|
</div>
|
|
|
|
<div class="right slide" @click="onClickBtnRight">
|
2025-01-19 13:22:26 +08:00
|
|
|
<div class="arrow">></div>
|
2025-01-18 20:08:14 +08:00
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</template>
|
|
|
|
<script lang="ts">
|
2025-01-19 10:30:37 +08:00
|
|
|
import { defineComponent, onMounted, onUnmounted, ref, toRaw } from "vue";
|
|
|
|
import { GA_EventName } from "../../ga/type";
|
2025-01-18 20:08:14 +08:00
|
|
|
import Banner from "./banner.vue";
|
|
|
|
import { emitter, Msg } from "./const";
|
|
|
|
import { AdItem, getAdData } from "./loader";
|
2025-01-18 21:57:27 +08:00
|
|
|
import { ga } from "./util";
|
2025-01-18 20:08:14 +08:00
|
|
|
export default defineComponent({
|
|
|
|
name: "ad",
|
|
|
|
components: { Banner },
|
|
|
|
setup() {
|
|
|
|
let ads = ref<AdItem[]>([]);
|
|
|
|
let stopAutoScroll = false;
|
2025-01-19 10:30:37 +08:00
|
|
|
const key = "close-time";
|
|
|
|
let timer = null;
|
|
|
|
const closeTitle = ref("");
|
2025-01-18 20:08:14 +08:00
|
|
|
onMounted(async () => {
|
|
|
|
const data = await getAdData();
|
|
|
|
if (!data) {
|
|
|
|
console.log(`get ad failed`);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (!data.valid) {
|
|
|
|
console.log(`set ad forbidden`);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (!data.data.length) {
|
|
|
|
console.log(`not find any ad`);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
ads.value = data.data;
|
|
|
|
console.log("get ads ", toRaw(ads.value));
|
2025-01-19 10:30:37 +08:00
|
|
|
closeTitle.value = `display again in ${data.showDuration} minute`;
|
2025-01-18 20:08:14 +08:00
|
|
|
|
2025-01-19 10:30:37 +08:00
|
|
|
visibleAd(data.showDuration);
|
|
|
|
adScroll(data.scrollDuration);
|
|
|
|
});
|
|
|
|
function adScroll(scrollDuration: number) {
|
|
|
|
timer = setInterval(() => {
|
2025-01-18 22:07:44 +08:00
|
|
|
// return;
|
2025-01-18 20:08:14 +08:00
|
|
|
if (stopAutoScroll) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (elAd.value) {
|
|
|
|
const el = elAd.value as HTMLElement;
|
|
|
|
|
|
|
|
let left = el.scrollLeft + adWidth;
|
2025-01-18 22:07:44 +08:00
|
|
|
if (el.scrollLeft + el.clientWidth >= el.scrollWidth) {
|
2025-01-18 20:08:14 +08:00
|
|
|
left = 0;
|
|
|
|
}
|
|
|
|
el.scrollTo({ left, behavior: "smooth" });
|
|
|
|
}
|
2025-01-19 10:30:37 +08:00
|
|
|
}, scrollDuration * 1000);
|
|
|
|
}
|
|
|
|
function visibleAd(showDuration: number) {
|
|
|
|
const time = Number(localStorage.getItem(key) || "0");
|
|
|
|
if (time) {
|
|
|
|
// 单位分钟
|
|
|
|
const diff = (Date.now() - time) / 1000 / 60;
|
|
|
|
isShow.value = diff >= showDuration;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
onUnmounted(() => {
|
|
|
|
clearInterval(timer);
|
2025-01-18 20:08:14 +08:00
|
|
|
});
|
|
|
|
function testBanner() {
|
|
|
|
const data = new AdItem();
|
|
|
|
data.name = "ad test 11111111111 11111111111 44444444444444 5555555555555 111111111111111111 2222222222222222 33333333333333 444444444444444";
|
|
|
|
data.store = "http://www.baidu.com";
|
|
|
|
emitter.emit(Msg.ChangeAd, data);
|
|
|
|
}
|
|
|
|
const elAd = ref<HTMLElement>(null);
|
|
|
|
const adWidth = 300;
|
|
|
|
const isShow = ref(true);
|
|
|
|
return {
|
2025-01-19 10:30:37 +08:00
|
|
|
closeTitle,
|
2025-01-18 20:08:14 +08:00
|
|
|
isShow,
|
|
|
|
elAd,
|
|
|
|
ads,
|
|
|
|
onClose() {
|
|
|
|
isShow.value = false;
|
2025-01-19 10:30:37 +08:00
|
|
|
localStorage.setItem(key, Date.now().toString());
|
2025-01-18 21:57:27 +08:00
|
|
|
ga(GA_EventName.CloseAd);
|
2025-01-18 20:08:14 +08:00
|
|
|
},
|
|
|
|
onMouseEnter() {
|
|
|
|
stopAutoScroll = true;
|
|
|
|
},
|
|
|
|
onMouseLeave() {
|
|
|
|
stopAutoScroll = false;
|
|
|
|
},
|
|
|
|
onWheel(event: WheelEvent) {
|
|
|
|
if (!elAd.value) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
event.preventDefault();
|
|
|
|
const div = elAd.value as HTMLElement;
|
|
|
|
if (event.deltaY > 0) {
|
|
|
|
div.scrollTo({ left: div.scrollLeft + adWidth, behavior: "smooth" });
|
|
|
|
} else {
|
|
|
|
div.scrollTo({ left: div.scrollLeft - adWidth, behavior: "smooth" });
|
|
|
|
}
|
|
|
|
},
|
|
|
|
async onClickBtnLeft() {
|
|
|
|
if (elAd.value) {
|
|
|
|
const el = elAd.value as HTMLElement;
|
|
|
|
el.scrollTo({ left: el.scrollLeft - adWidth, behavior: "smooth" });
|
|
|
|
}
|
|
|
|
},
|
|
|
|
async onClickBtnRight() {
|
|
|
|
if (elAd.value) {
|
|
|
|
const el = elAd.value as HTMLElement;
|
|
|
|
el.scrollTo({ left: el.scrollLeft + adWidth, behavior: "smooth" });
|
|
|
|
}
|
|
|
|
},
|
|
|
|
};
|
|
|
|
},
|
|
|
|
});
|
|
|
|
</script>
|
|
|
|
|
|
|
|
<style scoped lang="less">
|
|
|
|
@color-bg: #8d8d8da6;
|
2025-01-19 13:22:26 +08:00
|
|
|
@color-hover: #f9c04e;
|
2025-01-18 20:08:14 +08:00
|
|
|
@color-active: #ffaa00;
|
|
|
|
.ad {
|
|
|
|
position: absolute;
|
|
|
|
bottom: 0;
|
|
|
|
left: 0;
|
|
|
|
right: 0;
|
|
|
|
display: flex;
|
|
|
|
flex-direction: column;
|
2025-01-19 12:12:51 +08:00
|
|
|
//overflow: hidden;
|
2025-01-18 20:08:14 +08:00
|
|
|
|
|
|
|
.header {
|
|
|
|
display: flex;
|
|
|
|
align-items: flex-end;
|
|
|
|
.title {
|
2025-01-19 12:12:51 +08:00
|
|
|
box-shadow: 0px 0px 2px 0px;
|
2025-01-18 20:08:14 +08:00
|
|
|
font-size: 12px;
|
|
|
|
user-select: none;
|
|
|
|
background-color: white;
|
|
|
|
// border-top-left-radius: 5px;
|
|
|
|
border-top-right-radius: 5px;
|
|
|
|
padding: 3px 9px;
|
|
|
|
}
|
2025-01-19 12:12:51 +08:00
|
|
|
.line {
|
|
|
|
height: 1px;
|
|
|
|
flex: 1;
|
|
|
|
box-shadow: 0px 0px 2px 0px;
|
|
|
|
}
|
2025-01-18 20:08:14 +08:00
|
|
|
.close {
|
2025-01-19 12:12:51 +08:00
|
|
|
box-shadow: 0px 0px 3px 0px;
|
2025-01-18 20:08:14 +08:00
|
|
|
background-color: white;
|
|
|
|
border-top-left-radius: 10px;
|
|
|
|
cursor: pointer;
|
|
|
|
color: rgb(138, 138, 138);
|
|
|
|
width: 20px;
|
|
|
|
height: 20px;
|
|
|
|
display: flex;
|
|
|
|
justify-content: center;
|
|
|
|
align-items: center;
|
|
|
|
.icon {
|
2025-01-19 13:22:26 +08:00
|
|
|
user-select: none;
|
|
|
|
font-size: 14px;
|
2025-01-18 20:08:14 +08:00
|
|
|
&:hover {
|
|
|
|
color: black;
|
|
|
|
}
|
|
|
|
&:active {
|
|
|
|
color: #ffaa00;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
.body {
|
|
|
|
display: flex;
|
|
|
|
position: relative;
|
|
|
|
.list {
|
|
|
|
flex: 1;
|
|
|
|
display: flex;
|
|
|
|
flex-direction: row;
|
|
|
|
overflow: hidden;
|
|
|
|
}
|
|
|
|
.left {
|
|
|
|
left: 0;
|
|
|
|
background-image: linear-gradient(to left, rgba(0, 0, 0, 0), @color-bg);
|
|
|
|
&:hover {
|
|
|
|
background-image: linear-gradient(to left, rgba(0, 0, 0, 0), @color-hover);
|
|
|
|
}
|
|
|
|
&:active {
|
|
|
|
background-image: linear-gradient(to left, rgba(0, 0, 0, 0), @color-active);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
.right {
|
|
|
|
right: 0px;
|
|
|
|
background-image: linear-gradient(to right, rgba(0, 0, 0, 0), @color-bg);
|
|
|
|
&:hover {
|
|
|
|
background-image: linear-gradient(to right, rgba(0, 0, 0, 0), @color-hover);
|
|
|
|
}
|
|
|
|
&:active {
|
|
|
|
background-image: linear-gradient(to right, rgba(0, 0, 0, 0), @color-active);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
.slide {
|
|
|
|
display: flex;
|
|
|
|
height: 100%;
|
|
|
|
width: 20px;
|
|
|
|
cursor: pointer;
|
|
|
|
flex-direction: row;
|
|
|
|
align-items: center;
|
|
|
|
position: absolute;
|
2025-01-19 13:22:26 +08:00
|
|
|
justify-content: center;
|
2025-01-18 20:08:14 +08:00
|
|
|
|
|
|
|
.arrow {
|
2025-01-19 13:22:26 +08:00
|
|
|
user-select: none;
|
2025-01-18 20:08:14 +08:00
|
|
|
font-size: 22px;
|
2025-01-19 13:22:26 +08:00
|
|
|
font-weight: bold;
|
|
|
|
|
|
|
|
color: rgb(133, 133, 133);
|
2025-01-18 20:08:14 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
</style>
|