前端调用Umami API数据并渲染展示 [复制链接]

帖子链接已复制到剪贴板
懋和道人 (UID: 1319) 4月前
帖子已经有人评论啦,不支持删除!

315 2

image.png

Umami是一个高颜值可自部署的统计应用。小道也自豪的采用Umami进行的来访统计,较为真实、连贯,也比较能看得懂。为了更好的让用户访问数据能够较为完善的展现出来,小道也设计了一个“统计”页面,下面我来分享前端调用Umami API数据并渲染展示的全过程。

第一步、获取Token

小道是使用下列工具获取Token的

https://hoppscotch.io/

image.png

主要的是选择post,然后点击到body,然后的然后是Content Type选择application/json输入

{
"username": "Umami管理账号",
"password": "Umami管理密码"
}

单后点击Send,就会得到JSON的token。

第二步、获取 websiteId

在Umami的“设置”>“网站”选择需要统计渲染的站点,复制“网站ID”。

image.png

第三步、前端调用全站数据

PHP部分,用于存储umami_cache.json,作前端数据动态化调用。

<?php
header('Content-Type: application/json');
header("Access-Control-Allow-Origin: *");

// 配置 Umami API 的凭据
$apiBaseUrl = '已部署Umami统计站点';
$token = '第一步获得的Umamitoken';
$websiteId = '需要获取的网站ID'; // 在这里定义 websiteId
$cacheFile = 'umami_cache.json'; // 保存的json即使更新数据
$cacheTime = 600; // 缓存时间为10分钟(600秒)

// 获取当前时间戳(毫秒级)
$currentTimestamp = time() * 1000;

// Umami API 的起始时间戳(毫秒级)
$startTimestampToday = strtotime("today") * 1000;
$startTimestampYesterday = strtotime("yesterday") * 1000;

// 获取上个月的时间范围
$startTimestampLastMonth = strtotime("first day of last month") * 1000;
$endTimestampLastMonth = strtotime("last day of last month 23:59:59") * 1000;

// 获取去年全年的时间范围
$startTimestampLastYear = strtotime("first day of January last year") * 1000;
$endTimestampLastYear = strtotime("last day of December last year 23:59:59") * 1000;

// 定义 Umami API 请求函数
function fetchUmamiData($apiBaseUrl, $websiteId, $startAt, $endAt, $token) {
    $url = "$apiBaseUrl/api/websites/$websiteId/stats?" . http_build_query([
        'startAt' => $startAt,
        'endAt' => $endAt
    ]);

    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_HTTPHEADER, [
        "Authorization: Bearer $token",
        "Content-Type: application/json"
    ]);
    $response = curl_exec($ch);

    if (curl_errno($ch)) {
        echo 'Curl error: ' . curl_error($ch);
        curl_close($ch);
        return null;
    }

    $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    if ($httpCode != 200) {
        echo "HTTP error code: $httpCode\n";
        curl_close($ch);
        return null;
    }

    curl_close($ch);
    return json_decode($response, true);
}

// 检查缓存文件是否存在且未过期
if (file_exists($cacheFile) && (time() - filemtime($cacheFile) < $cacheTime)) {
    // 读取缓存文件
    $cachedData = file_get_contents($cacheFile);
    echo $cachedData;
} else {
    // 获取统计数据
    $todayData = fetchUmamiData($apiBaseUrl, $websiteId, $startTimestampToday, $currentTimestamp, $token);
    $yesterdayData = fetchUmamiData($apiBaseUrl, $websiteId, $startTimestampYesterday, $startTimestampToday, $token);
    $lastMonthData = fetchUmamiData($apiBaseUrl, $websiteId, $startTimestampLastMonth, $endTimestampLastMonth, $token);
    $lastYearData = fetchUmamiData($apiBaseUrl, $websiteId, $startTimestampLastYear, $endTimestampLastYear, $token);

    // 如果请求失败,返回错误信息
    if ($todayData === null || $yesterdayData === null || $lastMonthData === null || $lastYearData === null) {
        echo json_encode(["error" => "Failed to fetch data from Umami API"]);
        exit;
    }

    // 组装返回的 JSON 数据
    $responseData = [
        "today_uv" => $todayData['visitors']['value'] ?? null,
        "today_pv" => $todayData['pageviews']['value'] ?? null,
        "yesterday_uv" => $yesterdayData['visitors']['value'] ?? null,
        "yesterday_pv" => $yesterdayData['pageviews']['value'] ?? null,
        "last_month_pv" => $lastMonthData['pageviews']['value'] ?? null,
        "last_month_uv" => $lastMonthData['visitors']['value'] ?? null,
        "last_year_pv" => $lastYearData['pageviews']['value'] ?? null,
        "last_year_uv" => $lastYearData['visitors']['value'] ?? null
    ];

    // 将数据写入缓存文件
    file_put_contents($cacheFile, json_encode($responseData));

    // 输出 JSON 数据
    echo json_encode($responseData);
}
?>

上述几部,大功告成,我会先保存一个json数据组,然后再调用。然后在前端所想要展示的地方加一个<div id="main"></div>,使用Javascript来做数据组化,调用的所保存的json的数据。

Javascript部分,作前端div及数据渲染组合。

async function loadAndDisplayData() {  
  try {  
      const response = await fetch('./umami_cache.json');  
      if (!response.ok) throw new Error('Network response was not ok');  
      const data = await response.json();  

      // 获取主容器  
      const mainContainer = document.getElementById('main');  

      // 清除主容器中的现有内容  
      mainContainer.innerHTML = '';  

      // 定义一个函数来创建包含UV和PV的div对  
      function createStatsPair(uvLabel, uvValue, pvLabel, pvValue) {  
const pairContainer = document.createElement('div');  
  pairContainer.className = 'tongji'; // 使用CSS类来设置样式

          const uvDiv = document.createElement('div');  
          uvDiv.className = 'uvDiv sidecmtcon'; // 设置UV的div类名  
          uvDiv.textContent = `${uvLabel}: ${uvValue}`;  

          const pvDiv = document.createElement('div');  
          pvDiv.className = 'pvDiv sidecmtcon'; // 设置PV的div类名  
          pvDiv.textContent = `${pvLabel}: ${pvValue}`;  

          pairContainer.appendChild(uvDiv);  
          pairContainer.appendChild(pvDiv);  

          return pairContainer;  
      }  

      // 创建UV和PV的div对并添加到主容器中  
      const statsPairs = [  
          { uvLabel: '今日(UV)', uv: data.today_uv, pvLabel: '今日(PV)', pv: data.today_pv },  
          { uvLabel: '昨日(UV)', uv: data.yesterday_uv, pvLabel: '昨日(PV)', pv: data.yesterday_pv },  
          { uvLabel: '本月(UV)', uv: data.last_month_uv, pvLabel: '本月(PV)', pv: data.last_month_pv }
//          { uvLabel: '今年(UV)', uv: data.last_year_uv, pvLabel: '今年(PV)', pv: data.last_year_pv }  
      ];  

      statsPairs.forEach(pair => {  
          const pairDiv = createStatsPair(pair.uvLabel, pair.uv, pair.pvLabel, pair.pv);  
          mainContainer.appendChild(pairDiv);  
      });  

  } catch (error) {  
      console.error('Error loading or parsing data:', error);  
      // 显示错误消息  
      document.getElementById('main').textContent = 'Error loading data';  
  }  
}  

// 调用函数加载并显示数据  
loadAndDisplayData();

好了,小道语言组织能力差,基本上按照上面我写的内容,基本上就基本上的大功告成了,下面请欣赏:

https://www.dao.js.cn/tongji

米表,www.dao.js.cn/mi
已有评论 (2)
提示:您必须 登录 才能查看此内容。
创建新帖
广告推广点击空位自助购买