惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

D
Docker
Simon Willison's Weblog
Simon Willison's Weblog
H
Help Net Security
F
Fortinet All Blogs
H
Heimdal Security Blog
S
Schneier on Security
L
LangChain Blog
博客园 - Franky
酷 壳 – CoolShell
酷 壳 – CoolShell
NISL@THU
NISL@THU
P
Palo Alto Networks Blog
J
Java Code Geeks
博客园 - 【当耐特】
The Last Watchdog
The Last Watchdog
W
WeLiveSecurity
www.infosecurity-magazine.com
www.infosecurity-magazine.com
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
V
Vulnerabilities – Threatpost
I
InfoQ
Recorded Future
Recorded Future
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
C
CERT Recently Published Vulnerability Notes
T
Tenable Blog
腾讯CDC
C
Check Point Blog
量子位
M
MIT News - Artificial intelligence
GbyAI
GbyAI
罗磊的独立博客
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
B
Blog
小众软件
小众软件
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
C
CXSECURITY Database RSS Feed - CXSecurity.com
Stack Overflow Blog
Stack Overflow Blog
P
Proofpoint News Feed
P
Privacy & Cybersecurity Law Blog
V2EX - 技术
V2EX - 技术
T
Threatpost
Engineering at Meta
Engineering at Meta
Attack and Defense Labs
Attack and Defense Labs
T
Tailwind CSS Blog
S
Securelist
The Cloudflare Blog
博客园 - 叶小钗
L
LINUX DO - 最新话题
T
Troy Hunt's Blog
C
Cyber Attacks, Cyber Crime and Cyber Security
爱范儿
爱范儿

博客园 - ^Mao^

不同缩放下适配 vxe-table 3D饼图 openlayer实现给线的附近添加点,点支持移动 element-plus el-select html导出pdf openlayers增加移动功能 适配 openlayers基本使用(街景+标注+绘制) 使用openlayer绘制街景地图 正则表达式--取对应表达式的值 vue2实现el-table-column多级效果 echarts-雷达图 echarts--地图 散点图效果 echarts散点图区域设置 vant 的vant-uploader组件问题 Threejs学习 Echarts-普通地图和3D地图实现 test
部分页面统计用户访问时长
^Mao^ · 2025-11-06 · via 博客园 - ^Mao^

方式1

import { createApp } from "vue";
import { createPinia } from "pinia";

import App from "./App.vue";
import router from "./router";

const app = createApp(App);

app.use(createPinia());
app.use(router);

// 初始化变量
let startTime = 0; // 开始计时时间
let totalDuration = 0; // 总浏览时长(秒)
let isActive = false; // 页面是否活跃

// 页面加载时开始计时
window.addEventListener("load", () => {
  console.log("页面加载完毕");
  startTime = Date.now();
  isActive = true;
});

// 监听页面可见性变化(切换标签页、最小化窗口)
document.addEventListener("visibilitychange", () => {
  // console.log("visibilitychange");
  if (document.hidden) {
    // 页面隐藏:停止计时,累加时长
    if (isActive) {
      totalDuration += Math.floor((Date.now() - startTime) / 1000);
      isActive = false;
    }
  } else {
    // 页面显示:重新开始计时
    startTime = Date.now();
    isActive = true;
  }
});

// 监听窗口焦点变化(切换到其他应用时)
window.addEventListener("blur", () => {
  console.log("blur");
  if (isActive) {
    totalDuration += Math.floor((Date.now() - startTime) / 1000);
    isActive = false;
  }
});

window.addEventListener("focus", () => {
  console.log("focus");
  startTime = Date.now();
  isActive = true;
});

// 页面卸载时处理时长(上报或存储)
window.addEventListener("beforeunload", (event) => {
  // 累加最后一次活跃时长
  if (isActive) {
    totalDuration += Math.floor((Date.now() - startTime) / 1000);
  }

  // 1. 存储到本地 localStorage(刷新后仍可获取)
  localStorage.setItem("pageBrowseDuration", totalDuration);

  // 2. 上报到服务器(示例:通过接口提交)
  // fetch('/api/report-duration', {
  //   method: 'POST',
  //   headers: { 'Content-Type': 'application/json' },
  //   body: JSON.stringify({ duration: totalDuration, url: window.location.href })
  // });

  console.log("当前页面浏览时长:", totalDuration, "秒");
});

app.mount("#app");

方式2

// src/main.js

import { createApp } from "vue";
import { createPinia } from "pinia";

import App from "./App.vue";
import router from "./router";

const app = createApp(App);

app.use(createPinia());
app.use(router);

let pageTimers = {}; // 存储各个页面的计时信息

// 路由前置守卫
router.beforeEach((to, from, next) => {
  const now = Date.now();

  // 如果有正在计时的页面,则结束它的计时并保存
  if (from.meta.trackTime) {
    if (pageTimers[from.path]) {
      pageTimers[from.path].duration += Math.floor((now - pageTimers[from.path].start) / 1000);
      delete pageTimers[from.path];
    }
  }

  // 如果即将进入需要追踪的页面,则开始新的计时
  if (to.meta.trackTime) {
    pageTimers[to.path] = {
      start: now,
      duration: 0
    };
  }

  next();
});

// 页面卸载前上报数据
window.addEventListener("beforeunload", () => {
  const now = Date.now();
  
  // 结束所有正在进行的计时
  for (let path in pageTimers) {
    pageTimers[path].duration += Math.floor((now - pageTimers[path].start) / 1000);
    
    // 可以在这里发送每个页面的数据到服务器或本地存储
    console.log(`页面 ${path} 浏览时长:`, pageTimers[path].duration, "秒");
    
    // 示例:存储到 localStorage 或发送至服务端
    localStorage.setItem(`pageDuration_${path}`, pageTimers[path].duration);
  }
});

app.mount("#app");