https://huodong.fanli.com/h5/jdsellactivity.html
html
<?php
$title = '京东11.11全球热爱季';
$cssList = array(implode(",", array(
'//static2.51fanli.net/static/?f=webapp/css/base.css',
'common/libs/vant/index.css',
'huodong/jdsellactivity/css/index.css'
))
);
$jsList = array(implode(",", array(
'//static2.51fanli.net/static/?f=webapp/js/base.js',
'common/js/fanli/trace/ubt.js',
'common/libs/fmu/js/core/fmu.js',
'common/libs/fmu/js/core/widget.js',
'common/libs/fmu/js/extend/jquery.extend.js',
'webapp/js/common/hybridapi/nativefunction_v2.js',
'common/libs/vue/vue-lazyload.js',
'common/libs/fmu/js/vendors/vue/vue-2.6.14.js',
'common/libs/vant/index.js',
'huodong/jdsellactivity/js/index.js'
))
);
?>
<include file="$header" remwidth="750" remswitch="1" />
<div id="app">
<template>
<div v-if="topCfg" class="top-pic">
<img class="top-pic-bg" :src="topCfg.bg_img" alt="">
<div class="rule-btn" @click="showRuleDialog"></div>
<div
v-for="(item, index) of topCfg.hotAreaList"
:key="index" class="hot-area"
:style="{ width: (item.w)/100+'rem', height: (item.h)/100+'rem', left: (item.x)/100+'rem', top: (item.y)/100+'rem'}"
@click="topPicHotLinkJump(item.link)"
></div>
</div>
<div class="huichang-pic">
<img class="huichang-pic-bg" :src="huichangCfg.bg_img" alt="">
<div
v-for="(item, index) of huichangCfg.hotAreaList"
:key="index"
class="hot-area"
:style="{ width: (item.w)/100+'rem', height: (item.h)/100+'rem', left: (item.x)/100+'rem', top: (item.y)/100+'rem'}"
@click="huichangHotLinkJump(item.link,index)"
></div>
</div>
<van-dialog
class="dialog-box"
v-model="showDialog"
title="活动规则"
>
<div class="dialog-content" v-if="gaeaCfg">
<div v-for="(item, index) of gaeaCfg.rule[0].data1.split('\n')" v-html="item"></div>
</div>
<van-icon name="close" class="dialog-close-btn" @click="closeRuleDialog"/>
</van-dialog>
<div v-if="navCfg">
<!-- 导航 -->
<van-tabs
:v-model="0"
:color="navCfg.backcolor"
:background="navCfg.backcolor"
:title-active-color="navCfg.selected_color"
:title-inactive-color="navCfg.no_select_color"
:ellipsis="false"
sticky
@click="changeNavTab"
>
<van-tab v-for="(nav, navIndex) of navTitleArr" :key="navIndex" :title="nav">
<div class="container">
<van-list
v-model="loading"
:finished="finished"
finished-text="没有更多了"
:immediate-check="false"
@load="loadingMore"
>
<div v-if="listData.length>0">
<div class="pro-item-box" v-for="(item, index) of listData" :key="index" @click="goShop(item.skuId, item.popup_link)">
<div class="pro-item-left">
<img class="pic-img" :src="item.imgUrl" alt="">
</div>
<div class="pro-item-right">
<div class="item-title">{{ item.skuName }}</div>
<div class="quan-box">
<span class="cut-price" v-if="item.preAmountDeposit">付定金减{{ item.preAmountDeposit }}元</span>
<span class="quan" v-if="item.coupon_amount!=0">{{ item.coupon_amount }}元券</span>
</div>
<div class="price-box">
<span class="text" v-if="item.earnest">预售价</span>
<span class="text" v-else>到手价</span>
<span class="yuan">¥</span>
<span class="pre-num-one" v-if="item.prePrice && !item.prePrice.split('.')[1]" style="margin-right: 0.1rem;">{{ item.prePrice.split('.')[0] }}</span>
<span class="pre-num-one" v-if="item.prePrice && item.prePrice.split('.')[1]">{{ item.prePrice.split('.')[0] }}.</span>
<span class="pre-num-two" v-if="item.prePrice && item.prePrice.split('.')[1]">{{ item.prePrice.split('.')[1] }}</span>
<span class="old-price" v-if="item.prePrice<item.price">¥{{ item.price }}</span>
</div>
<div class="dj-btn" v-if="item.earnest">立即付{{ item.earnest }}元定金</div>
<div class="dj-btn" v-else>立即购买</div>
</div>
</div>
</div>
<div v-else style="height: 50vh;"></div>
</van-list>
</div>
</van-tab>
</van-tabs>
</div>
<!-- 可拖拽的浮标 -->
<img
v-if="gaeaCfg"
:src="gaeaCfg.float[0].img"
class="moveable-float-window"
@touchstart="wtouchstart"
@touchmove="wtouchmove"
@touchend="wtouchend"
@mousedown="wonmousedown"
@mousemove="wonmousemove"
@mouseup="wonmouseup"
@click="floatWinJump"
/>
</template>
</div>
<input id="J_bg_color" type="text" value="{$gaea['background'][0].data1}" hidden>
<include file="$footer"/>
less:
// out: ../css/
html, body, div, span, img {
box-sizing: border-box;
}
html, body {
width: 100%;
overflow-x: hidden;
}
#app{width: 100%;height: 100%;position: relative;}
.van-tabs__nav--line.van-tabs__nav--complete {
display: flex;
align-items: center;
}
.van-tab--active {
width: auto;
}
.van-tab--active > span {
display: inline-block;
width: auto;
height: .6rem;
text-align: center;
border-radius: .1rem;
padding: .05rem .3rem;
font-size: .26rem;
display: flex;
align-items: center;
background-color: #1f8bf9;
white-space: nowrap;
}
.van-tab__text {
font-size: 0.26rem;
}
.van-dialog {
overflow: visible;
}
.van-dialog__header {
padding: .2rem 0 0.1rem;
}
.van-dialog__footer {
display: none;
}
.container {
width: 7.1rem;
margin: 0 auto;
padding-bottom: 0.3rem;
}
.top-pic {
width: 7.5rem;
height: auto;
position: relative;
.top-pic-bg {
width: 7.5rem;
height: auto;
}
.rule-btn {
width: 1.2rem;
height: .4rem;
border-radius: 0.2rem 0 0 0.2rem;
position: absolute;
top: .1rem;
right: 0;
}
.hot-area {
position: absolute;
z-index: 100;
}
}
.huichang-pic {
width: 7.5rem;
height: auto;
position: relative;
.huichang-pic-bg {
width: 7.5rem;
height: auto;
}
.hot-area {
position: absolute;
z-index: 100;
}
}
.dialog-box {
width: 5.4rem;
position: fixed;
z-index: 1002;
background-color: #fff;
border-radius: 0.2rem;
.dialog-content {
max-height: 9rem;
overflow-y: auto;
border-radius: .2rem;
padding: 0.14rem 0.28rem 0.22rem;
color: #555;
font-size: 0.25rem;
word-break: break-all;
position: relative;
}
.dialog-close-btn {
font-size: .6rem;
color: #fff;
position: absolute;
top: -0.74rem;
right: 0;
}
}
.pro-item-box {
width: 7.1rem;
height: 2.98rem;
background: #FFFFFF;
border-radius: 0.1rem;
display: flex;
justify-content: space-between;
align-items: center;
padding: 0.2rem 0.22rem;
margin: 0.2rem auto;
.pro-item-left {
width: 2.6rem;
height: 2.6rem;
overflow: hidden;
.pic-img {
width: 2.6rem;
height: 2.6rem;
}
}
.pro-item-right {
width: 3.97rem;
height: 2.6rem;
position: relative;
.item-title {
width: 3.97rem;
height: 0.71rem;
line-height: 0.36rem;
font-size: 0.28rem;
font-weight: bold;
color: #111111;
margin-bottom: 0.14rem;
word-break: break-all;
text-overflow: -o-ellipsis-lastline;
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 2;
line-clamp: 2;
-webkit-box-orient: vertical;
}
.quan-box {
display: flex;
justify-content: flex-start;
align-items: flex-end;
span {
display: inline-block;
width: auto;
height: .3rem;
line-height: .3rem;
font-size: .22rem;
border-radius: .05rem;
margin-right: .16rem;
color: #fff;
padding: 0.04rem 0.08rem;
display: flex;
align-items: center;
}
.cut-price {
background: #3BB3F0;
}
.quan {
background: #F1450C;
}
}
.price-box {
font-size: 0.24rem;
color: #F10C10;
display: flex;
height: 0.56rem;
align-items: flex-end;
span {
display: inline-flex;
height: 0.56rem;
align-items: flex-end;
}
.text {
white-space: nowrap;
position: relative;
top: 0.03rem;
}
.yuan {
font-weight: bold;
margin: 0 0.02rem;
}
.pre-num-one {
font-size: 0.4rem;
font-weight: bold;
position: relative;
top: 0.04rem;
}
.pre-num-two {
font-weight: bold;
margin-right: 0.1rem;
}
.old-price {
color: #8A8A8A;
text-decoration: line-through;
}
}
.dj-btn {
width: 3.97rem;
height: 0.6rem;
line-height: 0.6rem;
text-align: center;
background-image: linear-gradient(-89deg, #F15665 0%, #EF4361 100%);
border-radius: 0.3rem;
color: #fff;
font-size: 0.28rem;
position: absolute;
right: 0;
bottom: 0;
display: flex;
justify-content: center;
align-items: center;
}
}
}
.moveable-float-window {
width: 0.9rem;
height: 0.9rem;
position: fixed;
right: 0rem;
top: 70%;
z-index: 500;
}
js:
;
(function(){
document.body.style.backgroundColor = $('#J_bg_color').val()
var baseUrl = 'https://huodong.fanli.com/h5/jdsellactivity';
Vue.use(VueLazyload, {
preLoad: 4,
loading: '//static2.51fanli.net/common/images/loading/spacer.png'
});
new Vue({
el: '#app',
data: {
showDialog: false,
gaeaCfg: '',
topCfg: '',
huichangCfg: '',
navCfg: '',
navTitleArr: [ '实时热销', '品质家电', '全球热卖', '商超好货' ],
navName: '',
pageNum: 0,
pageSize: 5,
listData: [],
loading: false,
finished: false,
ubtNavIndex: 1,
bgColor: '', // 页面背景色
mouseStartX: 0,
mouseStartY: 0,
currX: 0,
currY: 0,
pcDownFlag: false
},
mounted () {
UBT.track("page_name.h5.pty-homepv~std-84961")
this.initPage()
this.changeNavTab(0)
},
methods: {
initPage: function() {
var that = this;
$.getJSON(baseUrl + "/gaeaCfg", function(res) {
if(res.code === 1) {
that.gaeaCfg = res.data.gaeaCfg
that.topCfg = res.data.top
that.huichangCfg = res.data.huichang
that.navCfg= res.data.tab_style
}
})
},
showRuleDialog: function () {
UBT.track("page_name.h5.pty-rule~std-84961")
this.showDialog = true
},
closeRuleDialog: function () {
this.showDialog = false
},
loadingMore: function () {
var that = this;
that.pageNum++
$.getJSON(baseUrl + "/productList", {
name: that.navName,
page: that.pageNum,
size: that.pageSize
}, function(res) {
if(res.code === 1) {
for (var i = 0; i < res.list_data.length; i++) {
that.listData.push(res.list_data[i])
}
that.loading = false;
if (res.list_data.length === 0) {
that.finished = true;
}
}
})
},
changeNavTab: function (index) {
this.ubtNavIndex = index + 1
UBT.track("spm=page_name.h5.pty-tabdj~tab-"+ this.ubtNavIndex +"~std-84961")
if (index == 0) {
this.navName = 'ssrx'
} else if (index == 1) {
this.navName = 'pzjd'
} else if (index == 2) {
this.navName = 'qqrm'
} else {
this.navName = 'schh'
}
this.pageNum = 0
this.listData = []
this.loading = true
this.finished = false
this.loadingMore()
},
topPicHotLinkJump: function (link) {
window.location.href = link
},
huichangHotLinkJump: function (link, index) {
var ubtIndex = index + 1
UBT.track("page_name.h5.pty-addj~data-" + ubtIndex + "~std-84961")
window.location.href = link
},
floatWinJump: function () {
window.location.href = this.gaeaCfg.float[0].link
},
goShop: function (id, link) {
UBT.track("page_name.h5.pty-plist~tab-" + this.ubtNavIndex + "~pid-" + id + "~std-84961")
window.location.href = link
},
// 移动端事件 touch start
wtouchstart(e){
// 相对于父元素的右上角座标为 x=0,y=0
this.mouseStartX = e.changedTouches[0].pageX //获取鼠标点击的X坐标
this.mouseStartY = e.changedTouches[0].pageY //获取鼠标点击的Y坐标
this.currX = e.changedTouches[0].target.offsetLeft //相对于当前窗口X轴的偏移量
this.currY = e.changedTouches[0].target.offsetTop //相对于当前窗口Y轴的偏移量
},
// 移动端事件 touch move
wtouchmove(e){
var currDom = e.changedTouches[0].target
e.preventDefault();
moveX=e.changedTouches[0].pageX;//移动过程中X轴的坐标
moveY=e.changedTouches[0].pageY;//移动过程中Y轴的坐标
var leftX = this.mouseStartX-this.currX //鼠标所能移动的最左端是当前鼠标距div左边距的位置
var rightX = currDom.parentNode.clientWidth-currDom.clientWidth+leftX //鼠标所能移动的最右端是当前窗口距离减去鼠标距div最右端位置
var topY = this.mouseStartY-this.currY //鼠标所能移动最上端是当前鼠标距div上边距的位置
var bottomY = currDom.parentNode.clientHeight-currDom.clientHeight+topY //鼠标所能移动最下端是当前窗口距离减去鼠标距div最下端位置
// console.log(bottomY)
if(moveX<leftX){moveX=leftX;}
if(moveX>rightX){moveX=rightX;}
if(moveY<topY){moveY=topY;}
if(moveY>bottomY){moveY=bottomY;}
currDom.style.left = (moveX+ this.currX-this.mouseStartX) + 'px'
currDom.style.top = (moveY+this.currY-this.mouseStartY) + 'px'
},
// 移动端事件 touch end
wtouchend(e){
const currDom = e.changedTouches[0].target
e.preventDefault();
moveX=e.changedTouches[0].pageX;//移动过程中X轴的坐标
moveY=e.changedTouches[0].pageY;//移动过程中Y轴的坐标
if (currDom.offsetTop >= window.screen.height - 200) {
currDom.style.top = (window.screen.height - 200) + 'px'
}
if(this.currX == currDom.offsetLeft && this.currY == currDom.offsetTop){
// div座标未移动,认为它是点击事件
window.location.href = this.gaeaCfg.float[0].link
}else{
var left = moveX+ this.currX-this.mouseStartX
// 以下是左右吸边计算
var subX = currDom.parentNode.clientWidth - currDom.clientWidth
if(left >= subX/2){
currDom.style.left = subX + 'px'
}else{
currDom.style.left = 0 + 'px'
}
}
},
// 电脑端 onmouse down
wonmousedown (e){
// 相对于父元素的右上角座标为 x=0,y=0
this.mouseStartX = e.pageX //获取鼠标点击的X坐标
this.mouseStartY = e.pageY //获取鼠标点击的Y坐标
this.currX = e.target.offsetLeft //相对于当前窗口X轴的偏移量
this.currY = e.target.offsetTop //相对于当前窗口Y轴的偏移量
this.pcDownFlag = true
},
// 电脑端 onmouse move
wonmousemove(e){
if(!this.pcDownFlag){ //这是移动端touch和mouse方法唯一的区别了,试着可以注释掉,就知道原因了
return
}
var currDom = e.target
e.preventDefault();
moveX=e.pageX;//移动过程中X轴的坐标
moveY=e.pageY;//移动过程中Y轴的坐标
var leftX = this.mouseStartX-this.currX //鼠标所能移动的最左端是当前鼠标距div左边距的位置
var rightX = currDom.parentNode.clientWidth-currDom.clientWidth+leftX //鼠标所能移动的最右端是当前窗口距离减去鼠标距div最右端位置
var topY = this.mouseStartY-this.currY //鼠标所能移动最上端是当前鼠标距div上边距的位置
var bottomY = currDom.parentNode.clientHeight-currDom.clientHeight+topY //鼠标所能移动最下端是当前窗口距离减去鼠标距div最下端位置
if(moveX<leftX){moveX=leftX;}
if(moveX>rightX){moveX=rightX;}
if(moveY<topY){moveY=topY;}
if(moveY>bottomY){moveY=bottomY;}
currDom.style.left = (moveX+ this.currX-this.mouseStartX) + 'px'
currDom.style.top = (moveY+this.currY-this.mouseStartY) + 'px'
},
// 电脑端 onmouse up
wonmouseup(e){
this.pcDownFlag = false
const currDom = e.target
e.preventDefault();
moveX=e.pageX;//移动过程中X轴的坐标
moveY=e.pageY;//移动过程中Y轴的坐标
if(this.currX == currDom.offsetLeft && this.currY == currDom.offsetTop){
// div座标未移动,认为它是点击事件
console.log('点击事件');
}else{
var left = moveX+ this.currX-this.mouseStartX
// 以下是左右吸边计算
var subX = currDom.parentNode.clientWidth - currDom.clientWidth
if(left >= subX/2){
currDom.style.left = subX + 'px'
}else{
currDom.style.left = 0 + 'px'
}
}
}
}
})
})();