给发布服务添加统计访问量及网站运行时间

给发布服务添加统计访问量及网站运行时间

see https://ld246.com/article/1744513615105

// 统计网站访问量和运行时间
(async ()=>{
    // api地址,最后不要加 /
    const apiUrl = 'http://127.0.0.1:6806';
  
    // api token 在设置->关于中查看
    const apiToken = '';

    // 初始化数据
    const initData = {
        // 网站总访问量
        total: 0,
        // 网站运行初始日期
        startDay: '2025-04-13'
    };

    // 定义统计信息显示模板
    const tongjiTpl = `总访问量:{total}  网站运行:{runningDays}天`;

    // 已统计的跳过
    if(document.querySelector('#status .site__tongji')) return;
  
    // 获取置顶数据,格式 {"total":0, "startDay":''}
    let data = await getFile('/data/storage/site_tongji.json');
    data = JSON.parse(data||'{}');
    if(data.code && data.code !== 0) data = {};
    data = {...initData, ...data};

    // 仅发布服务器才统计
    if(siyuan.config.readonly) {
        // 网站访问+1
        data.total++;
  
        // 存储网站访问数据
        putFile('/data/storage/site_tongji.json', JSON.stringify(data, null, 4));
    }

    // 获取网站运行时间
    const runningDays = calculateRunningDays(data);

    // 状态栏显示统计信息
    showStatusMsg(tongjiTpl.replace('{total}', data.total).replace('{runningDays}', runningDays));

    // 计算网站运行时间(单位:天)
    function calculateRunningDays(data) {
        // 获取当前日期并重置时间为 00:00:00
        const currentDate = new Date();
        resetTime(currentDate);
  
        // 解析初始日期并重置时间为 00:00:00
        const startDate = new Date(data.startDay);
        if (isNaN(startDate.getTime())) {
            return 1;
        }
        resetTime(startDate);
  
        // 计算时间差(毫秒)
        const timeDifference = currentDate - startDate;
  
        // 转换为天数
        const daysDifference = Math.floor(timeDifference / (1000 * 60 * 60 * 24));
  
        return daysDifference + 1;
    }

    function resetTime(date) {
        date.setHours(0, 0, 0, 0); // 设置时间为 00:00:00.000
        return date;
    }

    // 状态栏输出
    function showStatusMsg(html) {
        const statusMsg = document.querySelector('#status .status__msg');
        if(!statusMsg) return;
        const tongji = document.querySelector('#status .site__tongji');
        if(tongji) tongji.remove();
        const style = `
            color: var(--b3-theme-on-surface);
            white-space: nowrap;
            text-overflow: ellipsis;
            overflow: hidden;
            padding-left: 5px;
            font-size: 12px;
        `;
        html = `<div class="site__tongji" style="${style}">${html}</div>`;
        statusMsg.insertAdjacentHTML('beforebegin', html);
    }
  
    // 获取文件
    async function getFile(path) {
        return fetch("/api/file/getFile", {
            method: "POST",
            headers: {
                "Content-Type": "application/json",
            },
            body: JSON.stringify({
                path,
            }),
        }).then((response) => {
            if (response.ok) {
                return response.text();
            } else {
                throw new Error("Failed to get file content");
            }
        }).catch((error) => {
            console.error(error);
        });
    }

    // 存储文件,支持创建文件夹,当isDir true时创建文件夹,忽略文件
     async function putFile(path, content = '', isDir = false) {
        const formData = new FormData();
        formData.append("path", path);
        formData.append("isDir", isDir)
        formData.append("file", new Blob([content]));
        const result = await fetch(apiUrl+"/api/file/putFile", { // 写入js到本地
            method: "POST",
            headers: {
                "Authorization": "token " + apiToken // 添加 Authorization 头
            },
            body: formData,
        });
        const json = await result.json();
        return json;
    }
})();
image.png

留下你的脚步
推荐阅读