统计工作时长

统计工作时长

方案1

是的,你可以利用 requestIdleCallback 实现一个工作时长统计功能,记录用户在页面上的活动时间。requestIdleCallback 可以在浏览器空闲时执行任务,因此非常适合用于记录用户在页面上的活动时间。


实现思路

  1. 记录开始时间

    • 当用户进入页面时,记录当前时间作为开始时间。
  2. 使用 requestIdleCallback

    • 在浏览器空闲时更新工作时长。
  3. 计算工作时长

    • 每次更新时,计算当前时间与开始时间的差值,并显示为小时和分钟。
  4. 重新安排任务

    • 在回调函数中重新调用 requestIdleCallback,确保任务能够持续执行。

实现代码

示例:

let startTime = Date.now(); // 记录开始时间
let lastUpdateTime = Date.now(); // 记录上一次更新的时间

function updateWorkDuration(deadline) {
    const currentTime = Date.now();
    const elapsedTime = currentTime - startTime; // 计算总工作时长
    const elapsedMinutes = Math.floor(elapsedTime / (1000 * 60)); // 转换为分钟
    const hours = Math.floor(elapsedMinutes / 60); // 计算小时
    const minutes = elapsedMinutes % 60; // 计算分钟

    // 更新 UI
    document.getElementById('workDuration').textContent = `你已工作了 ${hours} 小时 ${minutes} 分钟`;

    // 重新安排下一次更新
    requestIdleCallback(updateWorkDuration);
}

// 注册空闲任务
requestIdleCallback(updateWorkDuration);

HTML:

<div id="workDuration">你已工作了 0 小时 0 分钟</div>

解释

1. startTime

  • 记录用户进入页面时的当前时间。

2. lastUpdateTime

  • 记录上一次更新的时间,用于控制更新的频率。

3. elapsedTime

  • 计算当前时间与开始时间的差值,表示总工作时长(以毫秒为单位)。

4. elapsedMinutes

  • 将总工作时长转换为分钟。

5. hours minutes

  • 将总工作时长转换为小时和分钟,并显示在页面上。

6. 重新安排任务

  • 在回调函数末尾,重新调用 requestIdleCallback(updateWorkDuration),确保任务能够持续执行。

示例效果

  • 当用户进入页面时,开始记录工作时长。
  • 在浏览器空闲时,更新页面上的工作时长显示。
  • 显示格式为:你已工作了 xx 小时 xx 分钟

优化:控制更新频率

如果需要控制更新的频率,可以在回调函数中添加条件判断。

示例:

let startTime = Date.now(); // 记录开始时间
let lastUpdateTime = Date.now(); // 记录上一次更新的时间
const updateInterval = 1000; // 更新间隔为 1000ms(1秒)

function updateWorkDuration(deadline) {
    const currentTime = Date.now();
    const elapsedTime = currentTime - startTime; // 计算总工作时长
    const elapsedMinutes = Math.floor(elapsedTime / (1000 * 60)); // 转换为分钟
    const hours = Math.floor(elapsedMinutes / 60); // 计算小时
    const minutes = elapsedMinutes % 60; // 计算分钟

    // 更新 UI
    document.getElementById('workDuration').textContent = `你已工作了 ${hours} 小时 ${minutes} 分钟`;

    // 如果距离上一次更新时间超过 updateInterval,重新安排下一次更新
    if (currentTime - lastUpdateTime >= updateInterval) {
        lastUpdateTime = currentTime; // 更新上一次更新的时间
        requestIdleCallback(updateWorkDuration);
    } else {
        // 如果未达到更新间隔,使用 setTimeout 安排下一次更新
        setTimeout(updateWorkDuration, updateInterval - (currentTime - lastUpdateTime));
    }
}

// 注册空闲任务
requestIdleCallback(updateWorkDuration);

解释:

  1. updateInterval

    • 指定更新的时间间隔(例如 1000ms)。
  2. 条件判断

    • 如果距离上一次更新时间超过 updateInterval,重新调用 requestIdleCallback
    • 如果未达到更新间隔,使用 setTimeout 安排下一次更新。

总结

方案 适用场景 优点 缺点
requestIdleCallback 工作时长统计,空闲时更新 在空闲时执行任务,节省资源 无法保证固定的更新频率,更新可能延迟
requestIdleCallback + setTimeout 优化工作时长统计,结合两者的优点 在空闲时使用requestIdleCallback,繁忙时使用 setTimeout 实现稍微复杂,需要手动管理时间间隔

推荐:

  • 工作时长统计:推荐使用 requestIdleCallback
  • 需要更精确的控制:推荐结合 requestIdleCallbacksetTimeout

结论

  • 你可以使用 requestIdleCallback 实现一个工作时长统计功能。
  • 通过记录开始时间和当前时间,计算总工作时长,并显示为小时和分钟。
  • 如果需要更精确的控制,可以结合 setTimeout 来优化实现。

方案2

你提出的问题非常合理!浏览器空闲时并不代表用户未在工作,因为用户可能在浏览其他页面、切换标签页、甚至离开电脑。为了更精准地统计实际工作时长,我们需要考虑以下几个方面:


1. 问题分析

  • 浏览器空闲时

    • requestIdleCallback 只会在浏览器主线程空闲时触发。
    • 如果用户在浏览其他页面或切换标签页,浏览器主线程可能不会空闲,但用户实际上并未在工作。
  • 用户实际工作

    • 用户的工作行为可能包括:鼠标点击、键盘输入、页面滚动等。
    • 我们需要通过检测这些用户行为来判断用户是否在工作。

2. 解决方案

(1) 监听用户交互事件

  • 通过监听用户的交互事件(如 mousemovekeydownscroll 等),判断用户是否在工作。
  • 如果用户有交互行为,则认为用户在工作;否则,认为用户不在工作。

(2) 记录工作时间

  • 使用一个变量记录用户的工作时间。
  • 每次用户有交互行为时,更新工作时间。

(3) 显示工作时长

  • 在页面上实时显示用户的工作时长。

3. 实现代码

示例:

let startTime = Date.now(); // 记录开始时间
let workDuration = 0; // 记录工作时长
let lastInteractionTime = Date.now(); // 记录上一次交互的时间

// 监听用户交互事件
document.addEventListener('mousemove', updateInteractionTime);
document.addEventListener('keydown', updateInteractionTime);
document.addEventListener('scroll', updateInteractionTime);

function updateInteractionTime() {
    const currentTime = Date.now();
    const elapsedTime = currentTime - lastInteractionTime; // 计算距离上一次交互的时间

    // 如果距离上一次交互的时间小于 5 秒,则认为是工作时间
    if (elapsedTime < 5000) {
        workDuration += elapsedTime; // 累加工作时间
    }

    lastInteractionTime = currentTime; // 更新上一次交互的时间

    // 更新 UI
    updateWorkDuration();
}

function updateWorkDuration() {
    const elapsedMinutes = Math.floor(workDuration / (1000 * 60)); // 转换为分钟
    const hours = Math.floor(elapsedMinutes / 60); // 计算小时
    const minutes = elapsedMinutes % 60; // 计算分钟

    // 更新 UI
    document.getElementById('workDuration').textContent = `你已工作了 ${hours} 小时 ${minutes} 分钟`;
}

// 页面加载完成后初始化
window.addEventListener('load', () => {
    lastInteractionTime = Date.now(); // 初始化上一次交互的时间
    updateWorkDuration(); // 初始化显示
});

HTML:

<div id="workDuration">你已工作了 0 小时 0 分钟</div>

4. 解释

(1) 监听用户交互事件

  • 监听 mousemovekeydownscroll 事件,判断用户是否在工作。
  • 每次用户有交互行为时,调用 updateInteractionTime 函数。

(2) updateInteractionTime 函数

  • 计算当前时间与上一次交互时间的差值。
  • 如果差值小于 5 秒,则认为是工作时间,累加到 workDuration 中。
  • 更新 lastInteractionTime 为当前时间。

(3) updateWorkDuration 函数

  • workDuration 转换为小时和分钟,并显示在页面上。

(4) 初始化

  • 在页面加载完成后,初始化 lastInteractionTime 和显示。

5. 优化

(1) 忽略短暂的交互

  • 如果用户只是短暂地移动鼠标或按下键盘,可能并不代表实际工作。
  • 可以通过设置一个时间阈值(例如 5 秒),忽略短暂的交互。

(2) 考虑用户离开页面

  • 如果用户离开页面(例如切换标签页或关闭浏览器),可以停止计数。
  • 可以通过 visibilitychange 事件来检测页面是否可见。

示例:

document.addEventListener('visibilitychange', () => {
    if (document.visibilityState === 'hidden') {
        // 用户离开页面,停止计数
        console.log('User left the page');
    } else {
        // 用户回到页面,继续计数
        console.log('User returned to the page');
        lastInteractionTime = Date.now(); // 更新上一次交互的时间
    }
});

6. 总结

方案 适用场景 优点 缺点
监听用户交互事件 精准统计工作时长 通过用户行为判断工作状态,更准确 需要监听多个事件,可能会有性能开销
requestIdleCallback 轻量级任务,空闲时执行 代码简单,适合空闲时执行任务 无法判断用户是否实际在工作

推荐:

  • 精准统计工作时长:推荐使用监听用户交互事件的方案。
  • 轻量级任务:可以使用 requestIdleCallback,但需要结合用户交互事件来判断工作状态。

7. 结论

  • 为了更精准地统计实际工作时长,建议通过监听用户的交互事件(如 mousemovekeydownscroll 等)来判断用户是否在工作。
  • 通过记录用户的工作时间,并实时显示在页面上,可以实现更精准的工作时长统计。
  • 如果需要进一步优化,可以结合 visibilitychange 事件来检测用户是否离开页面。

image.png

留下你的脚步
推荐阅读