export class util {
    /**
     * 检测是否为移动端(触摸屏或小屏幕)
     */
    static isMobile(): boolean {
        return window.matchMedia('(max-width: 768px)').matches;
    }

    /**
     * 返回当前系统配色对应的 Monaco 主题名
     */
    static monacoTheme(): 'vs-dark' | 'vs' {
        return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'vs-dark' : 'vs';
    }

    /**
     * 更新容器内的所有时间标签
     * @param container - 要搜索的容器(默认为 document)
     */
    static updateTimeTags(container: Document | HTMLElement = document): void {
        const timeTags = container.querySelectorAll('time');
        for (const time of timeTags) {
            const datetime = time.getAttribute('datetime');
            if (datetime && !time.dataset.processed) {
                const date = new Date(datetime);
                const now = new Date();
                // seconds
                const diff = (now.getTime() - date.getTime()) / 1000;

                let timeString = '';
                if (diff < 60) {
                    timeString = '刚刚';
                } else if (diff < 3600) {
                    timeString = `${Math.floor(diff / 60)}分钟前`;
                } else if (diff < 86400) {
                    timeString = `${Math.floor(diff / 3600)}小时前`;
                }
                // 30 天内
                else if (diff < 2592000) {
                    timeString = `${Math.floor(diff / 86400)}天前`;
                }
                // 365 天内
                else if (diff < 31536000) {
                    timeString = `${Math.floor(diff / 2592000)}个月前`;
                } else {
                    timeString = `${Math.floor(diff / 31536000)}年前`;
                }

                time.textContent = timeString;

                // 设置 title 属性,以便全局 tooltip 处理器在悬停时显示
                if (!time.hasAttribute('title') && !time.hasAttribute('data-original-title')) {
                    time.setAttribute('title', datetime);
                }

                // 标记为已处理,避免重复渲染
                time.dataset.processed = 'true';
            }
        }
    }
}
⚠⚠    以下内容为AI分析的结果,请根据实际情况进行判断。

这是一个名为 util 的工具类,包含三个静态方法,用于处理前端开发中的常见需求。让我逐一解释每个方法的功能:

1. isMobile() 方法

static isMobile(): boolean {
    return window.matchMedia('(max-width: 768px)').matches;
}

功能:检测当前设备是否为移动端

  • 使用 CSS 媒体查询 (max-width: 768px) 来判断屏幕宽度
  • 当屏幕宽度小于等于 768px 时返回 true,否则返回 false
  • 768px 是一个常见的移动端断点

2. monacoTheme() 方法

static monacoTheme(): 'vs-dark' | 'vs' {
    return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'vs-dark' : 'vs';
}

功能:根据系统配色方案返回对应的 Monaco 编辑器主题

  • 检测系统是否启用了深色模式 (prefers-color-scheme: dark)
  • 深色模式时返回 'vs-dark',浅色模式时返回 'vs'
  • Monaco Editor 是 VS Code 使用的代码编辑器组件

3. updateTimeTags() 方法

static updateTimeTags(container: Document | HTMLElement = document): void

功能:将页面中的时间标签转换为相对时间显示(如"3分钟前")

主要逻辑

  1. 查找时间标签:在指定容器中查找所有 <time> 元素
  2. 获取时间数据:从 datetime 属性获取原始时间
  3. 计算时间差:计算当前时间与目标时间的差值(秒)
  4. 格式化显示:根据时间差显示不同格式:
    • < 60秒:显示"刚刚"
    • < 1小时:显示"X分钟前"
    • < 1天:显示"X小时前"
    • < 30天:显示"X天前"
    • < 1年:显示"X个月前"
    • ≥ 1年:显示"X年前"

附加功能

  • 设置 title 属性显示原始时间,便于悬停查看详细时间
  • 使用 data-processed 标记避免重复处理
  • 支持自定义容器范围,默认处理整个文档

使用场景

这个工具类适用于:

  • 响应式网站的移动端适配
  • 代码编辑器的主题切换
  • 社交媒体、博客、论坛等需要显示相对时间的场景
评论加载中...