Browse Source

feat 广告位对接

pull/3/head
Wangwei 2 years ago
parent
commit
f749e99fb7
  1. 3
      package.json
  2. 541
      src/components/banner.vue
  3. 6
      src/router.js
  4. 151
      src/utils/advertisementSDK.js
  5. 19
      src/views/studypath/finebi.vue
  6. 21
      src/views/studypath/finereportStudyPath2023.vue
  7. 19
      src/views/studypath/jiandaoyun.vue
  8. 3
      src/views/video/indexVideo.vue

3
package.json

@ -54,7 +54,8 @@
"parser": "babel-eslint"
},
"rules": {
"no-undef": "off"
"no-undef": "off",
"no-unused-vars": "off"
}
},
"browserslist": [

541
src/components/banner.vue

@ -1,25 +1,24 @@
<template>
<div class="mbg idBanner" >
<div class="mbg idBanner">
<div class="nav">
<div class="left-nav">
<ul class="left-wrapper">
<li v-for="(item,i) in menuList.slice(0,6)" :key="i">
<router-link @mouseenter="gethot(item.id)" class="c1a flex-3 flex-1" :to="'/video?class1='+item.id"
target="_blank">
<span>{{item.it618_classname}}</span>
<li v-for="(item, i) in menuList.slice(0, 6)" :key="i">
<router-link @mouseenter="gethot(item.id)" class="c1a flex-3 flex-1" :to="'/video?class1=' + item.id" target="_blank">
<span>{{ item.it618_classname }}</span>
<i class="arrow el-icon-arrow-right"></i>
</router-link>
<div class="child-nav">
<div class="child-wrapper">
<ul>
<li class="child-item" v-for="(child,j) in item.class2" :key="j">
<router-link class="c2a" :to="'/video?class1='+item.id+'&class2='+child.id" target="_blank">
{{child.it618_classname}}
<li class="child-item" v-for="(child, j) in item.class2" :key="j">
<router-link class="c2a" :to="'/video?class1=' + item.id + '&class2=' + child.id" target="_blank">
{{ child.it618_classname }}
</router-link>
</li>
<div class="amore">
<router-link class="mra flex-1" :to="'/video?class1='+item.id" target="_blank">
<span>查看{{item.it618_classname}}全部课程</span>
<router-link class="mra flex-1" :to="'/video?class1=' + item.id" target="_blank">
<span>查看{{ item.it618_classname }}全部课程</span>
<i class="arrow el-icon-arrow-right"></i>
</router-link>
</div>
@ -29,23 +28,21 @@
<h2 class="col617">热门推荐</h2>
<ul>
<li v-for="(item, i) in item.hotdata" :key="i">
<router-link class="lk hide-txt" :to="'/video/'+item.id" target="_blank">
{{item.title}}
<router-link class="lk hide-txt" :to="'/video/' + item.id" target="_blank">
{{ item.title }}
</router-link>
<p>
<span>{{item.class_hour}}</span>
<em>{{item.number_people}}</em>
<span>{{ item.class_hour }}</span>
<em>{{ item.number_people }}</em>
</p>
</li>
</ul>
</div>
</div>
</div>
</li>
<li>
<!-- <a href="/video?class1=37&class2=0" class="c1a flex-3 flex-1">
<span>FineDataLink</span>
<i class="arrow el-icon-arrow-right"></i>
@ -69,28 +66,16 @@
</router-link>
</div>
</ul>
</div>
</div>
</li>
</ul>
</div>
<div class="right-box flex-3">
<div class="ad">
<a :href="cover.click_url" target="_blank">
<!-- <img :src="cover.imgurl" width="1000" height="420"> -->
<el-image :src="cover.img_url" style=" width: 1000px; height: 375px; position: static">
<template #error>
<div style="width: 800px; height: 100%;" class="flex-5">
<i class="el-icon-loading f24 colb3c"></i>
</div>
</template>
</el-image>
</a>
<div id="AD-1d4b2f969fcd43a99205e88c53b05d8d"></div>
</div>
<div class="menu">
<ul>
<a href="https://bbs.fanruan.com/course/report/standard?sqtjBI" target="_blank">
<li>
@ -121,16 +106,11 @@
<i class="arrow el-icon-arrow-right"></i>
</a>
</ul>
</div>
</div>
</div>
</div>
<div class="mbg ad-m dn">
<a :href="cover.click_url" target="_blank">
<el-image :src="cover.img_url" style=" width: 100%; position: static">
@ -142,315 +122,308 @@
</el-image>
</a>
</div>
</template>
<script>
import { getCategories } from "@/api/video";
import { getcateHot, getCover } from "@/api/index";
import { toRefs, reactive } from 'vue';
export default {
setup() {
const state = reactive({
menuList: [],
listhot: [],
cover: {},
isloadHot: [],
});
const fetchMenuList = async () => {
const res = await getCategories();
if (res.code === 200) {
state.menuList = res.data;
}
};
fetchMenuList();
const fetchgetCover = async () => {
const res = await getCover();
if (res.code === 200) {
state.cover = res.data[0];
}
};
fetchgetCover();
const fetchgetcateHot = async (class1) => {
const res = await getcateHot(class1);
if (res.code === 200) {
state.listhot = res.data;
state.isloadHot.push(class1);
state.menuList.forEach((item, index) => {
if (item.id === class1) {
state.menuList[index]['hotdata'] = res.data;
}
});
}
};
import { getCategories } from "@/api/video";
import { getcateHot } from "@/api/index";
import { toRefs, reactive } from "vue";
export default {
setup() {
const state = reactive({
menuList: [],
listhot: [],
cover: {},
isloadHot: [],
});
const fetchMenuList = async () => {
const res = await getCategories();
if (res.code === 200) {
state.menuList = res.data;
}
};
fetchMenuList();
// banner cid广
// const fetchgetCover = async () => {
// const res = await getCover();
// if (res.code === 200) {
// state.cover = res.data[0];
// }
// };
// fetchgetCover();
// banner 广
window.fineAd.getAdvertisement({ adId: "1d4b2f969fcd43a99205e88c53b05d8d" });
const fetchgetcateHot = async (class1) => {
const res = await getcateHot(class1);
if (res.code === 200) {
state.listhot = res.data;
state.isloadHot.push(class1);
const gethot = (class1) => {
//
state.menuList.forEach((item, index) => {
if (item.id === class1) {
if (!state.menuList[index]['hotdata']) {
fetchgetcateHot(class1);
}
state.menuList[index]["hotdata"] = res.data;
}
});
}
return {
...toRefs(state),
gethot,
};
},
};
};
const gethot = (class1) => {
//
state.menuList.forEach((item, index) => {
if (item.id === class1) {
if (!state.menuList[index]["hotdata"]) {
fetchgetcateHot(class1);
}
}
});
};
return {
...toRefs(state),
gethot,
};
},
};
</script>
<style lang="scss" scoped>
.mbg {
background: #F3F8FF;
padding: 34px 0 0;
}
.nav {
position: relative;
width: 1200px;
height: 375px;
margin: auto;
display: flex;
justify-content: space-between;
color: #fff;
border-radius: 8px;
overflow: hidden;
box-shadow: 0px 2px 16px 0px rgba(12, 40, 131, 0.1);
}
.left-nav {
display: flex;
width: 200px;
background-color: #fff;
}
.left-nav .left-wrapper {
width: 100%;
.mbg {
background: #f3f8ff;
padding: 34px 0 0;
}
.nav {
position: relative;
width: 1200px;
height: 375px;
margin: auto;
display: flex;
justify-content: space-between;
color: #fff;
border-radius: 8px;
overflow: hidden;
box-shadow: 0px 2px 16px 0px rgba(12, 40, 131, 0.1);
}
.left-nav {
display: flex;
width: 200px;
background-color: #fff;
}
.left-nav .left-wrapper {
width: 100%;
}
.left-nav .left-wrapper > li {
display: block;
box-sizing: border-box;
white-space: nowrap;
text-overflow: ellipsis;
.c1a {
font-size: 16px;
padding: 16px 24px;
}
}
.left-nav .left-wrapper>li {
display: block;
box-sizing: border-box;
white-space: nowrap;
text-overflow: ellipsis;
.left-nav .left-wrapper > li:hover {
color: #0082fc;
background: #eef3fa;
}
.c1a {
font-size: 16px;
padding: 16px 24px;
}
}
.left-nav .left-wrapper li:hover .child-nav {
display: block;
}
.left-nav .left-wrapper>li:hover {
color: #0082FC;
background: #EEF3FA;
}
.nav .right-box {
background-color: #eef3fa;
border: none;
width: 1000px;
.left-nav .left-wrapper li:hover .child-nav {
display: block;
.ad {
width: 800px;
}
.nav .right-box {
background-color: #EEF3FA;
border: none;
width: 1000px;
.menu {
width: 200px;
position: relative;
.ad {
width: 800px;
ul {
width: 216px;
height: 100%;
position: absolute;
right: -16px;
}
.menu {
width: 200px;
a {
display: flex;
align-items: center;
color: #fff;
height: 25%;
padding: 0 16px;
background-color: rgb(0, 0, 0, 0.19);
transition: all 0.3s;
position: relative;
ul {
width: 216px;
height: 100%;
position: absolute;
right: -16px;
h5 {
font-size: 16px;
padding-bottom: 2px;
}
a {
display: flex;
align-items: center;
color: #fff;
height: 25%;
padding: 0 16px;
background-color: rgb(0, 0, 0, 0.19);
transition: all .3s;
position: relative;
span {
font-size: 14px;
}
h5 {
font-size: 16px;
padding-bottom: 2px;
}
i {
transition: all 0.3s;
opacity: 0;
margin-left: 0;
}
span {
font-size: 14px;
}
&:hover {
margin-left: -16px;
i {
transition: all .3s;
opacity: 0;
margin-left: 0;
}
&:hover {
margin-left: -16px;
i {
opacity: 1;
margin-left: 26px;
}
opacity: 1;
margin-left: 26px;
}
}
&::after {
content: "";
position: absolute;
left: 16px;
right: 34px;
bottom: 0;
height: 1px;
background-color: rgba(255, 255, 255, 0.2);
}
&::after {
content: "";
position: absolute;
left: 16px;
right: 34px;
bottom: 0;
height: 1px;
background-color: rgba(255, 255, 255, 0.2);
}
}
}
.child-nav {
display: none;
}
.child-nav {
display: none;
position: absolute;
top: 0;
left: 200px;
height: 100%;
}
.child-nav .child-wrapper {
display: flex;
justify-content: space-between;
height: 100%;
}
.child-wrapper > ul {
position: relative;
display: flex;
justify-content: space-around;
align-content: flex-start;
flex-wrap: wrap;
width: 320px;
height: 100%;
padding-top: 20px;
background-color: #eef3fa;
padding: 20px 10px 0 10px;
.amore {
position: absolute;
top: 0;
left: 200px;
height: 100%;
}
.child-nav .child-wrapper {
display: flex;
justify-content: space-between;
height: 100%;
}
bottom: 0;
left: 0;
width: 100%;
.child-wrapper>ul {
position: relative;
display: flex;
justify-content: space-around;
align-content: flex-start;
flex-wrap: wrap;
width: 320px;
height: 100%;
padding-top: 20px;
background-color: #EEF3FA;
padding: 20px 10px 0 10px;
.amore {
position: absolute;
bottom: 0;
left: 0;
width: 100%;
.mra {
padding: 20px 0 20px 32px;
border-top: 1px solid #CEDDF2;
color: #0082FC;
font-size: 14px;
.mra {
padding: 20px 0 20px 32px;
border-top: 1px solid #ceddf2;
color: #0082fc;
font-size: 14px;
span {
padding-right: 12px;
}
span {
padding-right: 12px;
}
}
}
&:after {
content: ' ';
width: 42%;
}
&:after {
content: " ";
width: 42%;
}
}
.child-wrapper .child-item {
width: 42%;
border-radius: 20px;
text-align: center;
margin-bottom: 16px;
.child-wrapper .child-item {
width: 42%;
border-radius: 20px;
.c2a {
width: 100%;
display: inline-block;
background-color: #fff;
border-radius: 24px;
text-align: center;
margin-bottom: 16px;
.c2a {
width: 100%;
display: inline-block;
background-color: #fff;
border-radius: 24px;
text-align: center;
padding: 4px 0;
font-size: 14px;
}
padding: 4px 0;
font-size: 14px;
}
}
.child-wrapper .child-item:hover {
color: rgb(61, 185, 255);
}
.child-wrapper .child-item:hover {
color: rgb(61, 185, 255);
}
.child-wrapper .child-item:last-child:nth-child(2n - 1) {
margin-right: calc(40% + 9%);
}
.child-wrapper .child-item:last-child:nth-child(2n - 1) {
margin-right: calc(40% + 9%);
.left-wrapper .hot {
border-left: 1px solid #ceddf2;
width: 240px;
background-color: #eef3fa;
padding: 24px;
h2 {
font-size: 14px;
padding-bottom: 18px;
}
.left-wrapper .hot {
border-left: 1px solid #CEDDF2;
width: 240px;
background-color: #EEF3FA;
padding: 24px;
li {
padding-bottom: 24px;
h2 {
.lk {
font-size: 14px;
padding-bottom: 18px;
}
li {
padding-bottom: 24px;
.lk {
font-size: 14px;
}
p {
font-size: 12px;
color: #617288;
p {
font-size: 12px;
color: #617288;
span {
padding-right: 16px;
}
span {
padding-right: 16px;
}
}
}
}
</style>
<style lang="scss" scoped>
.ad-m {
width: 100%;
min-height: 100px;
padding: 18px 20px 0 20px;
overflow: hidden;
::v-deep .el-image__inner {
border-radius: 8px;
max-width: 1000px;
margin: 0 auto;
display: block;
}
.ad-m {
width: 100%;
min-height: 100px;
padding: 18px 20px 0 20px;
overflow: hidden;
::v-deep .el-image__inner {
border-radius: 8px;
max-width: 1000px;
margin: 0 auto;
display: block;
}
</style>
}
</style>

6
src/router.js

@ -2,7 +2,7 @@ import { createRouter, createWebHistory } from 'vue-router';
import Layout from '@/layout/index.vue';
import store from '@/store';
import { refreshToken } from '@/api/auth';
// import '@/utils/fineClubSDK';
import '@/utils/advertisementSDK';
import { getUid, getExpiresTime } from '@/utils/cookie';
import { delUrlParams } from '@/utils/urlQuery';
@ -350,6 +350,10 @@ const router = createRouter({
},
});
// 接入广告配置
let getAdEnv = process.env.VUE_APP_ENV == 'dist' ? false : true;
window.fineAd.config({debug:getAdEnv,dev:getAdEnv});
// 通过导航守卫 判断并刷新token
let accessToken = store.getters.get_token;
let expires = getExpiresTime();

151
src/utils/advertisementSDK.js

@ -0,0 +1,151 @@
/**
* 广告调用SDK
* 2023-04-11 by Wangwei
*/
import axios from "axios";
const fineAd = (window.fineAd = window.fineAd || {});
fineAd.options = fineAd.options || {};
/**
* 初始化SDK配置
* @param debug
* @param dev
* @param adApiUrl
*/
const config = ({ debug = false, dev = false, adApiUrl }) => {
fineAd.options = {
...fineAd.options,
debug,
dev,
adApiUrl: dev ? 'https://testjdy.fanruan.com/fcoin' : 'https://home.fanruan.com/fcoin',
};
if(debug){
console.log('adApiUrl', fineAd.config.adApiUrl);
}
};
/**
* 获取并展示指定广告id的广告位
* @param adId 广告位id
* @param adId2 如果adId没有匹配到则显示第二个广告位
* @param top 顶边距
* @param bottom 底边距
*/
const getAdvertisement = async ({adId, adId2, top, bottom}) => {
const { debug, dev } = fineAd.options;
const dataPath = dev ? 'test' : 'prod';
await axios.get("https://shequ-oss.obs.cn-east-2.myhuaweicloud.com/digit/ad/data/" + dataPath + "/advertisement.json?v=" + Date.now())
.then(function (res) {
var isAdId = false;
res.data.forEach((item) => {
if(item.adId === adId){
isAdId = true;
let getSize = splitPicSize(item.picSize);
if(debug){
console.group("advertisement " + adId);
console.log('item',item);
console.log('picSize',getSize);
console.log('top',top);
console.log('bottom',bottom);
console.groupEnd();
}
let adDomId = document.getElementById('AD-' + adId);
adDomId.innerHTML='';
window.fineAd.adMargin({ adId:adId, top:top });
// 无链接图片广告
if(!item.adLink && item.type===1){
adDomId.innerHTML+=`<img width="${getSize.w}" height="${getSize.h}" src="${item.picUrl}">`;
}
// 有链接图片广告
if(item.adLink && item.type===1){
adDomId.innerHTML+=`<a onClick="window.fineAd.advertisementHits('${adId}');" href="${item.adLink}" target="_blank"><img width="${getSize.w}" height="${getSize.h}" src="${item.picUrl}"></a>`;
}
// 有链接文本广告
if(item.adLink && item.type===2){
adDomId.innerHTML+=`<a onClick="window.fineAd.advertisementHits('${adId}');" href="${item.adLink}" target="_blank">${item.adText}</a>`;
}
window.fineAd.adMargin({ adId:adId, bottom:bottom });
}
});
// 找第二个广告位
if(adId2 && !isAdId){
res.data.forEach((item) => {
if(item.adId === adId2){
console.log('isAdId',isAdId);
let getSize = splitPicSize(item.picSize);
if(debug){
console.group("advertisement " + adId2);
console.log('item',item);
console.log('picSize',getSize);
console.log('top',top);
console.log('bottom',bottom);
console.groupEnd();
}
let adDomId = document.getElementById('AD-' + adId2);
adDomId.innerHTML='';
window.fineAd.adMargin({ adId:adId2, top:top });
// 有链接图片广告
if(item.adLink && item.type===1){
adDomId.innerHTML=`<a onClick="window.fineAd.advertisementHits('${adId2}');" href="${item.adLink}" target="_blank"><img width="${getSize.w}" height="${getSize.h}" src="${item.picUrl}"></a>`;
}
// 有链接文本广告
if(item.adLink && item.type===2){
adDomId.innerHTML=`<a onClick="window.fineAd.advertisementHits('${adId2}');" href="${item.adLink}" target="_blank">${item.adText}</a>`;
}
window.fineAd.adMargin({ adId:adId2, bottom:bottom });
}
});
}
})
.catch(function (error) {
console.log('ad error',error);
});
};
/**
* 广告边距
* @param top 顶边距
* @param bottom 底边距
*/
const adMargin = ({ adId, top = 0, bottom = 0 }) => {
let adDomId = document.getElementById('AD-' + adId);
if(top > 0){
adDomId.innerHTML+=`<div style="height:${top}px;"></div>`;
}else if(bottom > 0){
adDomId.innerHTML+=`<div style="height:${bottom}px;"></div>`;
}
}
/**
* 拆分广告位尺寸
* @param adSize 广告位尺寸
* @return Array[w,h] 宽和高
*/
const splitPicSize = (adSize) =>{
let {w,h} = {w:'',h:''};
if(adSize){
let {[0]:w,[1]:h} = adSize.replace(/\s/g,"").split('*');
return {w,h};
}else{
return {w,h};
}
}
/**
* 广告位埋点
* @param adId 广告位id
*/
const advertisementHits = (adId) =>{
const { adApiUrl } = fineAd.options;
axios.get(adApiUrl + "/api/advertisement/hits/" + adId);
}
fineAd.config = config;
fineAd.adMargin = adMargin;
fineAd.getAdvertisement = getAdvertisement;
fineAd.advertisementHits = advertisementHits;

19
src/views/studypath/finebi.vue

@ -216,11 +216,7 @@
</div>
</el-scrollbar>
<div style="display:float;width: 100%;height:80px;overflow: hidden;margin:20px 0;" class="m-dn" v-if="is_ad">
<a :href="ad_clickurl" target="_blank">
<img :src="ad_imgurl" alt="BI学习路径banner" />
</a>
</div>
<div id="AD-83346c28538542f6b678220a47e6fee3" class="m-dn"></div>
</div>
</div>
@ -807,7 +803,6 @@
import { reactive, toRefs } from "vue";
import { studentCount } from "@/api/guide";
import { getCourseNum } from "@/api/study";
import { adurl } from "@/api/ad";
import downMenu from "@/views/studypath/downMenu";
import pathMenu from "@/views/studypath/pathMenu";
export default {
@ -860,17 +855,7 @@ export default {
resgetNode();
// 广
const adgetNode = async () => {
const res = await adurl(31);
if (res.code === 200) {
if (res.data.img_url != null) {
state.ad_imgurl = res.data.img_url;
state.ad_clickurl = res.data.click_url;
state.is_ad = true;
}
}
};
adgetNode();
window.fineAd.getAdvertisement({ adId: "83346c28538542f6b678220a47e6fee3", top: 24 });
//
const resCourseNum = async (pid, tmp) => {

21
src/views/studypath/finereportStudyPath2023.vue

@ -198,12 +198,7 @@
</div>
</div>
</el-scrollbar>
<div style="display:float;width: 100%;height:80px;overflow: hidden;margin:20px 0;" class="m-dn" v-if="is_ad">
<a :href="ad_clickurl" target="_blank">
<img :src="ad_imgurl" alt="FR学习路径banner" />
</a>
</div>
<div id="AD-bfb30c067e5e449aac8ea667205fcfc3" class="m-dn"></div>
</div>
</div>
@ -654,7 +649,6 @@
<script>
import { reactive, toRefs } from "vue";
import { getCourseNum } from "@/api/study";
import { adurl } from "@/api/ad";
import downMenu from "@/views/studypath/downMenu";
import { scrollToElementAnchor } from "@/utils/scrollTo";
import pathMenu from "@/views/studypath/pathMenu";
@ -691,18 +685,7 @@ export default {
cate_list: [],
});
// 广
const adgetNode = async () => {
const res = await adurl(30);
if (res.code === 200) {
if (res.data.img_url != null) {
state.ad_imgurl = res.data.img_url;
state.ad_clickurl = res.data.click_url;
state.is_ad = true;
}
}
};
adgetNode();
window.fineAd.getAdvertisement({ adId: "bfb30c067e5e449aac8ea667205fcfc3", top: 24 });
//
const resCourseNum = async () => {

19
src/views/studypath/jiandaoyun.vue

@ -203,11 +203,7 @@
</div>
</el-scrollbar>
<div style="display:float;width: 100%;height:80px;overflow: hidden;margin:20px 0;" class="m-dn" v-if="is_ad">
<a :href="ad_clickurl" target="_blank">
<img :src="ad_imgurl" alt="简道云学习路径banner" />
</a>
</div>
<div id="AD-ec2bf821df994fa5aa3cc950377a812e" class="m-dn"></div>
</div>
</div>
@ -679,7 +675,6 @@
import { reactive, toRefs } from "vue";
import { studentCount } from "@/api/guide";
import { getCourseNum } from "@/api/study";
import { adurl } from "@/api/ad";
import downMenu from "@/views/studypath/downMenu";
import pathMenu from "@/views/studypath/pathMenu";
export default {
@ -726,17 +721,7 @@ export default {
resgetNode();
// 广
const adgetNode = async () => {
const res = await adurl(32);
if (res.code === 200) {
if (res.data.img_url != null) {
state.ad_imgurl = res.data.img_url;
state.ad_clickurl = res.data.click_url;
state.is_ad = true;
}
}
};
adgetNode();
window.fineAd.getAdvertisement({ adId: "ec2bf821df994fa5aa3cc950377a812e", top: 24 });
//
const resCourseNum = async () => {

3
src/views/video/indexVideo.vue

@ -294,12 +294,11 @@
{ id: 6, name: "300元以上" },
],
sortList: [
{ id: 0, name: "默认排序", label: "按课程id从高到低", icon: "" },
{ id: 0, name: "最近更新", label: "发布时间倒序", icon: "" },
{ id: 1, name: "学习人数", label: "学习人数从高到底", icon: "el-icon-caret-bottom" },
{ id: 2, name: "销量", label: "销量从高到低", icon: "el-icon-caret-bottom" },
{ id: 3, name: "价格", label: "价格从高到低", icon: "el-icon-caret-bottom" },
{ id: 4, name: "价格", label: "价格从低到高", icon: "el-icon-caret-top" },
{ id: 5, name: "更新时间", label: "发布日期倒序", icon: "el-icon-caret-bottom" },
],
priceRangeList: [],
videoList: [],

Loading…
Cancel
Save