Feat(页面):监听页面打开次数和页面停留时长逻辑初步实现
This commit is contained in:
@@ -0,0 +1,6 @@
|
||||
export const pageToWatchData = {
|
||||
'home_index': {
|
||||
count: 0,
|
||||
timer: 0
|
||||
}
|
||||
}
|
||||
@@ -16,6 +16,7 @@ import {
|
||||
} from "@/config";
|
||||
import uView from "uview-ui";
|
||||
import GooSkeleton from '@/components/GooSkeleton/index.vue'
|
||||
import { pageToWatchData } from '@/config/page'
|
||||
|
||||
Vue.use(uView)
|
||||
Vue.component('GooSkeleton', GooSkeleton)
|
||||
@@ -32,7 +33,8 @@ Vue.prototype.$VUE_APP_RESOURCES_URL = VUE_APP_RESOURCES_URL
|
||||
Vue.prototype.$STATIC_RESOURCE_URL = STATIC_RESOURCE_URL
|
||||
Vue.prototype.$VUE_APP_API_URL = VUE_APP_API_URL
|
||||
Vue.prototype.$WX_LIVE_APPID = WX_LIVE_APPID
|
||||
Vue.prototype.$global = global;
|
||||
Vue.prototype.$global = global
|
||||
Vue.prototype.$pageToWatchData = pageToWatchData
|
||||
|
||||
Vue.prototype.$validator = function (rule) {
|
||||
return new schema(rule);
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
import {
|
||||
pageToWatchShowCount,
|
||||
pageToWatchShowTimer
|
||||
} from '@/utils/util'
|
||||
export const pageListenMixins = {
|
||||
data(){
|
||||
return {
|
||||
pageTimer: null
|
||||
}
|
||||
},
|
||||
onShow() {
|
||||
this.pageToWatchShowCount(this.pageKeyId, this.pageShowTimerFn())
|
||||
},
|
||||
onHide() {
|
||||
this.clearPageTimerFn()
|
||||
},
|
||||
methods: {
|
||||
pageToWatchShowCount,
|
||||
pageToWatchShowTimer,
|
||||
pageShowTimerFn() {
|
||||
this.pageTimer = setInterval(() => {
|
||||
console.log('----页面监听----%s', this.pageKeyId)
|
||||
this.pageToWatchShowTimer(this.pageKeyId)
|
||||
}, 1000)
|
||||
},
|
||||
clearPageTimerFn() {
|
||||
if (this.pageTimer) {
|
||||
console.log('清除页面监听-----%s', this.pageKeyId)
|
||||
clearInterval(this.pageTimer)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -250,6 +250,8 @@ import {getProducts} from "@/api/store";
|
||||
import {sharpBannar} from "@/api/goods";
|
||||
import NP from "number-precision";
|
||||
|
||||
import { pageListenMixins } from '@/mixins/pageListenMixins'
|
||||
|
||||
var that;
|
||||
export default {
|
||||
name: 'Index',
|
||||
@@ -260,8 +262,7 @@ export default {
|
||||
CountDown,
|
||||
hxNavbar
|
||||
},
|
||||
computed: mapGetters(["userInfo", 'isLogin']),
|
||||
props: {},
|
||||
mixins: [pageListenMixins],
|
||||
data: function () {
|
||||
return {
|
||||
currentIndex: 0,
|
||||
@@ -378,9 +379,11 @@ export default {
|
||||
contentHomestay: {},
|
||||
contentFestival: {},
|
||||
countyFamous: {},
|
||||
seasonalFood: {}
|
||||
};
|
||||
seasonalFood: {},
|
||||
pageKeyId: Object.freeze('home_index')
|
||||
}
|
||||
},
|
||||
computed: mapGetters(["userInfo", 'isLogin']),
|
||||
onLoad: function (options) {
|
||||
that = this;
|
||||
this.init();
|
||||
|
||||
+81
-72
@@ -1,8 +1,87 @@
|
||||
<template>
|
||||
<view class="pkg-product-land-mark" v-if="mapData">
|
||||
<view class="top-box" :style="{'backgroundColor':topBoxBgColor}">
|
||||
<view class="view-box">
|
||||
<view class="search-box flex ai-center">
|
||||
<input
|
||||
v-model="keyword"
|
||||
type="text"
|
||||
placeholder="搜索商品"
|
||||
placeholder-style="color:#999"
|
||||
@confirm="search()"
|
||||
/>
|
||||
<image
|
||||
:src="webUrl+'/20231223183627184005.png'"
|
||||
mode="scaleToFill"
|
||||
style="width:30rpx;height:30rpx"
|
||||
@click="search()"
|
||||
/>
|
||||
</view>
|
||||
|
||||
<view class="map-box">
|
||||
<image class="img-map" :src="mapData.mapImage" mode="widthFix"/>
|
||||
|
||||
<view
|
||||
v-for="(item, index) in mapLocations"
|
||||
:key="index"
|
||||
class="item"
|
||||
:style="{'left':item.gx+'rpx','top':item.gy+'rpx'}"
|
||||
@click="$global.navToGoods(item.productId)"
|
||||
>
|
||||
<view class="round">
|
||||
<view class="line" :class="'line-'+directionClass[item.labelDirection]"></view>
|
||||
</view>
|
||||
<view class="label flex ai-end" :class="'label-'+directionClass[item.labelDirection]">
|
||||
<image class="cover flex-0" :src="item.mapImage" mode="scaleToFill" v-if="item.labelDirection===4"/>
|
||||
<view class="title flex ai-center">{{ item.mapTitle }}</view>
|
||||
<image class="cover flex-0" :src="item.mapImage" mode="scaleToFill" v-if="item.labelDirection!==4"/>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="nav flex">
|
||||
<view class="flex flex-0 ai-center" :class="{'active': navIndex===index}" v-for="(item,index) in navList"
|
||||
:key="index" @click="changeNav(index)">{{ item.provinceName }}
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="main-box" v-if="mapData.recommended.storeImage"
|
||||
@click="$global.navToGoods(mapData.recommended.productId)">
|
||||
<image class="bg-main" :src="mapData.recommended.storeImage" mode="scaleToFill"/>
|
||||
<view class="box-mask flex flex-col jc-end">
|
||||
<view class="one-t bold">{{ mapData.recommended.title }}</view>
|
||||
<view class="more-t">{{ mapData.recommended.description }}</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="list-box flex flex-wrap">
|
||||
<view class="item" v-for="item in goods" :key="item.id" @click="$global.navToGoods(item.productId)">
|
||||
<image :src="item.storeImage" mode="scaleToFill"/>
|
||||
<view class="content flex flex-col jc-between">
|
||||
<view class="more-t bold">{{ item.title }}</view>
|
||||
<view class="flex jc-between ai-center">
|
||||
<text class="price">¥{{ item.price }}</text>
|
||||
<image class="btn" :src="webUrl+'/20231114151028082368.png'" mode="scaleToFill"/>
|
||||
<!-- <view class="btn flex jc-center ai-center">立即购买</view>-->
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<image class="img-nodata" :src="webUrl+'/20231023131208675588.png'" mode="scaleToFill"
|
||||
v-if="goods.length===0"/>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {getProvince, getProvinceGoods, getProvinceList} from "@/api/product";
|
||||
import { pageListenMixins } from '@/mixins/pageListenMixins'
|
||||
|
||||
export default {
|
||||
name: "landMark",
|
||||
name: 'LandMarkPage',
|
||||
mixins: [pageListenMixins],
|
||||
data() {
|
||||
return {
|
||||
webUrl: this.$VUE_APP_RESOURCES_URL,
|
||||
@@ -14,6 +93,7 @@ export default {
|
||||
mapLocations: [],
|
||||
goods: [],
|
||||
directionClass: ['', 'up', 'right', 'down', 'left'],
|
||||
pageKeyId: Object.freeze('land_index')
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
@@ -84,77 +164,6 @@ export default {
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<view class="pkg-product-land-mark" v-if="mapData">
|
||||
<view class="top-box" :style="{'backgroundColor':topBoxBgColor}">
|
||||
<view class="view-box">
|
||||
<view class="search-box flex ai-center">
|
||||
<input
|
||||
v-model="keyword"
|
||||
type="text"
|
||||
placeholder="搜索商品"
|
||||
placeholder-style="color:#999"
|
||||
@confirm="search()"
|
||||
/>
|
||||
<image
|
||||
:src="webUrl+'/20231223183627184005.png'"
|
||||
mode="scaleToFill"
|
||||
style="width:30rpx;height:30rpx"
|
||||
@click="search()"
|
||||
/>
|
||||
</view>
|
||||
|
||||
<view class="map-box">
|
||||
<image class="img-map" :src="mapData.mapImage" mode="widthFix"/>
|
||||
|
||||
<view class="item" :style="{'left':item.gx+'rpx','top':item.gy+'rpx'}" v-for="item in mapLocations" @click="$global.navToGoods(item.productId)">
|
||||
<view class="round">
|
||||
<view class="line" :class="'line-'+directionClass[item.labelDirection]"></view>
|
||||
</view>
|
||||
<view class="label flex ai-end" :class="'label-'+directionClass[item.labelDirection]">
|
||||
<image class="cover flex-0" :src="item.mapImage" mode="scaleToFill" v-if="item.labelDirection===4"/>
|
||||
<view class="title flex ai-center">{{ item.mapTitle }}</view>
|
||||
<image class="cover flex-0" :src="item.mapImage" mode="scaleToFill" v-if="item.labelDirection!==4"/>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="nav flex">
|
||||
<view class="flex flex-0 ai-center" :class="{'active': navIndex===index}" v-for="(item,index) in navList"
|
||||
:key="index" @click="changeNav(index)">{{ item.provinceName }}
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="main-box" v-if="mapData.recommended.storeImage"
|
||||
@click="$global.navToGoods(mapData.recommended.productId)">
|
||||
<image class="bg-main" :src="mapData.recommended.storeImage" mode="scaleToFill"/>
|
||||
<view class="box-mask flex flex-col jc-end">
|
||||
<view class="one-t bold">{{ mapData.recommended.title }}</view>
|
||||
<view class="more-t">{{ mapData.recommended.description }}</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="list-box flex flex-wrap">
|
||||
<view class="item" v-for="item in goods" :key="item.id" @click="$global.navToGoods(item.productId)">
|
||||
<image :src="item.storeImage" mode="scaleToFill"/>
|
||||
<view class="content flex flex-col jc-between">
|
||||
<view class="more-t bold">{{ item.title }}</view>
|
||||
<view class="flex jc-between ai-center">
|
||||
<text class="price">¥{{ item.price }}</text>
|
||||
<image class="btn" :src="webUrl+'/20231114151028082368.png'" mode="scaleToFill"/>
|
||||
<!-- <view class="btn flex jc-center ai-center">立即购买</view>-->
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<image class="img-nodata" :src="webUrl+'/20231023131208675588.png'" mode="scaleToFill"
|
||||
v-if="goods.length===0"/>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<style scoped lang="less">
|
||||
.pkg-product-land-mark {
|
||||
background: #F7F3ED;
|
||||
|
||||
@@ -89,12 +89,12 @@
|
||||
<view v-if="list.length === 0" class="no-data">
|
||||
暂无数据
|
||||
</view>
|
||||
<u-loadmore
|
||||
<!-- <u-loadmore
|
||||
v-if="query.page >= totalPage && list.length > 0"
|
||||
:line="true"
|
||||
status="nomore"
|
||||
nomore-text="到底了"
|
||||
/>
|
||||
/> -->
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import Vue from 'vue'
|
||||
|
||||
// 日期格式化
|
||||
export function formatterDate(date, flag = '-', mode = 'date') {
|
||||
const year = new Date(date).getFullYear()
|
||||
@@ -22,3 +24,36 @@ export function formatContent(html) {
|
||||
contentData = contentData.replace(/\<img/gi, '<img style="max-width:100%;height:auto;display:block;margin:0 auto;"')
|
||||
return contentData
|
||||
}
|
||||
|
||||
/**
|
||||
* desc: 监听页面访问次数
|
||||
* auth: lifizer
|
||||
* date: 2024-05-16
|
||||
* @param key-页面唯一标识
|
||||
* @param cb-回调函数
|
||||
* @returns {null}
|
||||
*/
|
||||
export function pageToWatchShowCount(key, cb = '') {
|
||||
if (Vue.prototype.$pageToWatchData[key]) {
|
||||
Vue.prototype.$pageToWatchData[key].count++
|
||||
} else {
|
||||
Vue.prototype.$pageToWatchData[key] = {
|
||||
count: 1,
|
||||
timer: 0
|
||||
}
|
||||
}
|
||||
cb && cb()
|
||||
}
|
||||
|
||||
/**
|
||||
* desc: 监听页面访问时长
|
||||
* auth: lifizer
|
||||
* date: 2024-05-16
|
||||
* @param key-页面唯一标识
|
||||
* @returns {null}
|
||||
*/
|
||||
export function pageToWatchShowTimer(key) {
|
||||
if (Vue.prototype.$pageToWatchData[key]) {
|
||||
Vue.prototype.$pageToWatchData[key].timer++
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user