Feat(页面):监听页面打开次数和页面停留时长逻辑初步实现

This commit is contained in:
lifizer
2024-05-16 17:23:07 +08:00
parent 2b3c0e4355
commit 84c5ede725
7 changed files with 167 additions and 79 deletions
+6
View File
@@ -0,0 +1,6 @@
export const pageToWatchData = {
'home_index': {
count: 0,
timer: 0
}
}
+3 -1
View File
@@ -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);
+33
View File
@@ -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)
}
}
}
}
+7 -4
View File
@@ -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
View File
@@ -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;
+2 -2
View File
@@ -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>
+35
View File
@@ -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++
}
}