Loading... # 前端效果示例: ![](https://cdn.gta5pdx.cn/usr/uploads/2024/04/918668714.png) ![](https://cdn.gta5pdx.cn/usr/uploads/2024/04/4010448633.jpg) # 后端搭建: ## 第一步:安装Docker **进入命令行页面安装Dockers** * Debian:apt install docker* -y * Centos:yum install docker* -y ![](https://cdn.gta5pdx.cn/usr/uploads/2024/04/2025832286.png) **在目录下新建 docker-compose.yml文件:** * vim docker-compose.yml **将下面内容放入docker-compose.yml文件中。** ``` --- version: '3' services: umami: image: docker.umami.dev/umami-software/umami:postgresql-latest ports: - "3000:3000" environment: DATABASE_URL: postgresql://umami:umami@db:5432/umami DATABASE_TYPE: postgresql APP_SECRET: replace-me-with-a-random-string TRACKER_SCRIPT_NAME: random-string.js depends_on: - db restart: always db: image: postgres:15-alpine environment: POSTGRES_DB: umami POSTGRES_USER: umami POSTGRES_PASSWORD: umami volumes: - ./sql/schema.postgresql.sql:/docker-entrypoint-initdb.d/schema.postgresql.sql:ro - umami-db-data:/var/lib/postgresql/data restart: always volumes: umami-db-data: ``` * 输入:wq保存 ## 第二步:启用放有Umami镜像的Docker 容器: * docker compose up -d *注意端口是否占用。如果端口被占用,则提示bind:address already in use* ![](https://cdn.gta5pdx.cn/usr/uploads/2024/04/1987603236.png) <div class="panel panel-default collapse-panel box-shadow-wrap-lg"><div class="panel-heading panel-collapse" data-toggle="collapse" data-target="#collapse-c581e785dfbf5c915d7fdd55891aa85173" aria-expanded="true"><div class="accordion-toggle"><span style="">解决方法:</span> <i class="pull-right fontello icon-fw fontello-angle-right"></i> </div> </div> <div class="panel-body collapse-panel-body"> <div id="collapse-c581e785dfbf5c915d7fdd55891aa85173" class="collapse collapse-content"><p></p> **把 `ports`中冒号前的3000改为其他的** ![](https://cdn.gta5pdx.cn/usr/uploads/2024/04/1877035076.png) **修改完重新再执行一次** * docker compose up -d <p></p></div></div></div> ![](https://cdn.gta5pdx.cn/usr/uploads/2024/04/3102673001.png) **提示running和started即可** * 输入搭建机子的ip加端口号即可访问 ![](https://cdn.gta5pdx.cn/usr/uploads/2024/04/119073829.png) * 默认账号:admin * 默认密码:umami * 点击上方的地球图标可以修改为中文 ![](https://cdn.gta5pdx.cn/usr/uploads/2024/04/3068220036.png) ## 第三步:后端统计功能代码实现 ![](https://cdn.gta5pdx.cn/usr/uploads/2024/04/2414136452.png) **添加网站,输入名字和域名,比如我要统计`test123.com`的访问量,名字自定义,域名输入`test123.com`** ![](https://cdn.gta5pdx.cn/usr/uploads/2024/04/847177139.png) **点击编辑,将统计代码插入到需要放置的网站上** ![](https://cdn.gta5pdx.cn/usr/uploads/2024/04/2347989028.png) ![](https://cdn.gta5pdx.cn/usr/uploads/2024/04/2648421260.png) ![](https://cdn.gta5pdx.cn/usr/uploads/2024/04/3882611740.png) **想看访问量可以点击网站,点击对应的域名查看今天访问数据** ![](https://cdn.gta5pdx.cn/usr/uploads/2024/04/2072159096.png) ## 如何在前端插入展示多少访问量,请往下看 * 获取用户的 API Token **我们可以通过以下方式获取 API Token:** * 点击退出登录 * F12打开开发者控制台的network后重新登录页面 ![](https://cdn.gta5pdx.cn/usr/uploads/2024/04/2451588498.png) * 如果成功,你应该会得到以下的结果: * 抓取login里面的包 ```json { "token": "9aNPclUzR2h/XGTN1oTu9oesujLS3avZS7RThTsdqQlTtlP3t8gnRDSApZqIyp5iKII5AuNFR28ujpWJy6A4rD1CtPVneo/0hH/Ms7dYI3ycbSgFrTgJPpy48c7R/q9/Eyw2LshA7OEjq1vtThqtvhQpwwkQ4blXq570S3QZAq/EoHqLse3PQstgFYHKeldqEzXAgPFdNJmH+Qsd/sWOKgLkNQSxN7iGZXSvJbX3w5bUF0WnDu3tYRZfadWDQfC66EZ11j3FAhPhkBZYZZTrvaxQQ34Cq5Xfw/msw8T8DJ0zCNuoBpQCNYtARYOB6bPti5OxtruTIV3WFx0FvjKf/60dpvXt8zbriA==", "user": { "id": "41e2b680-648e-4b09-bcd7-3e2b10c06264", "username": "admin", "role": "admin", "createdAt": "2024-04-21T14:21:58.820Z", "isAdmin": true } } ``` * 有两个必填的查询参数:`startAt` 和 `endAt`,都是 Unix 毫秒时间戳,表示开始时间和结束时间 * `websiteId` 和 `startAt` 需要我们自己获取 * websiteId 可以在 Dashboard -> 点击你网站的 View details -> 浏览器栏的地址 https://example.com/websites/{websiteId} 中找到 {websiteId} * 例如test123.com的websiteld为:eca83b28-ca7c-4de2-be92-dfe262a4adcb ![](https://cdn.gta5pdx.cn/usr/uploads/2024/04/699123100.png) * startAt则是上文的 `token` "9aNPclUzR2h/XGTN1oTu9oesujLS3avZS7RThTsdqQlTtlP3t8gnRDSApZqIyp5iKII5AuNFR28ujpWJy6A4rD1CtPVneo/0hH/Ms7dYI3ycbSgFrTgJPpy48c7R/q9/Eyw2LshA7OEjq1vtThqtvhQpwwkQ4blXq570S3QZAq/EoHqLse3PQstgFYHKeldqEzXAgPFdNJmH+Qsd/sWOKgLkNQSxN7iGZXSvJbX3w5bUF0WnDu3tYRZfadWDQfC66EZ11j3FAhPhkBZYZZTrvaxQQ34Cq5Xfw/msw8T8DJ0zCNuoBpQCNYtARYOB6bPti5OxtruTIV3WFx0FvjKf/60dpvXt8zbriA==", # 前端代码(将下面这个代码插入到你想要展示的位置): ```html <div style="text-align:center;"> <span>总访问量 <span id="umami-site-pv"></span> 次</span> <span>总访客数 <span id="umami-site-uv"></span> 人</span> </div> <script> // 从配置文件中获取 umami 的配置,例如上文提取到的website_id:eca83b28-ca7c-4de2-be92-dfe262a4adcb const website_id = 'xxx'; // 拼接请求地址,例如http://172.18.38.228:3002 这个就是umami的部署ip const request_url = 'https://xxx.com' + '/api/websites/' + website_id + '/stats'; const start_time = new Date('2024-01-01').getTime(); const end_time = new Date().getTime(); // token填写上文获取到的token const token = 'xxxxxx'; // 检查配置是否为空 if (!website_id) { throw new Error("Umami website_id is empty"); } if (!request_url) { throw new Error("Umami request_url is empty"); } if (!start_time) { throw new Error("Umami start_time is empty"); } if (!token) { throw new Error("Umami token is empty"); } const params = new URLSearchParams({ startAt: start_time, endAt: end_time, }); const request_header = { method: "GET", headers: { "Content-Type": "application/json", "Authorization": "Bearer " + token, }, }; async function allStats() { try { const response = await fetch(`${request_url}?${params}`, request_header); const data = await response.json(); const uniqueVisitors = data.visitors?.value; // 获取独立访客数 const pageViews = data.pageviews?.value; // 获取页面浏览量 let ele1 = document.querySelector("#umami-site-pv"); if (ele1) { ele1.textContent = pageViews; // 设置页面浏览量 } let ele2 = document.querySelector("#umami-site-uv"); if (ele2) { ele2.textContent = uniqueVisitors; } console.log(uniqueVisitors, pageViews); console.log(data); } catch (error) { console.error(error); return "-1"; } } allStats(); </script> //跟踪代码 <script defer src="http://172.18.38.228:3002/random-string.js" data-website-id="eca83b28-ca7c-4de2-be92-dfe262a4adcb"></script> ``` **至此,前端也可以展示访问量,后端也可以查看详细** ![](https://cdn.gta5pdx.cn/usr/uploads/2024/04/3472265630.png) # 前端优化: * 分两个文件 * 可以将JavaScript代码从HTML中提取到一个单独的 `.js`文件中。以下是将JavaScript代码从HTML中移至一个 `umamiStats.js`文件的示例: **umamiStats.js:** ```javascript // 从配置文件中获取 umami 的配置 const website_id = 'eca83b28-ca7c-4de2-be92-dfe262a4adcb'; // 拼接请求地址 const request_url = 'http://172.18.38.228:3002' + '/api/websites/' + website_id + '/stats'; const start_time = new Date('2024-01-01').getTime(); const end_time = new Date().getTime(); const token = '9aNPclUzR2h/XGTN1oTu9oesujLS3avZS7RThTsdqQlTtlP3t8gnRDSApZqIyp5iKII5AuNFR28ujpWJy6A4rD1CtPVneo/0hH/Ms7dYI3ycbSgFrTgJPpy48c7R/q9/Eyw2LshA7OEjq1vtThqtvhQpwwkQ4blXq570S3QZAq/EoHqLse3PQstgFYHKeldqEzXAgPFdNJmH+Qsd/sWOKgLkNQSxN7iGZXSvJbX3w5bUF0WnDu3tYRZfadWDQfC66EZ11j3FAhPhkBZYZZTrvaxQQ34Cq5Xfw/msw8T8DJ0zCNuoBpQCNYtARYOB6bPti5OxtruTIV3WFx0FvjKf/60dpvXt8zbriA=='; // 检查配置是否为空 if (!website_id) { throw new Error("Umami website_id is empty"); } if (!request_url) { throw new Error("Umami request_url is empty"); } if (!start_time) { throw new Error("Umami start_time is empty"); } if (!token) { throw new Error("Umami token is empty"); } const params = new URLSearchParams({ startAt: start_time, endAt: end_time, }); const request_header = { method: "GET", headers: { "Content-Type": "application/json", "Authorization": "Bearer " + token, }, }; async function allStats() { try { const response = await fetch(`${request_url}?${params}`, request_header); const data = await response.json(); const uniqueVisitors = data.visitors?.value; // 获取独立访客数 const pageViews = data.pageviews?.value; // 获取页面浏览量 let ele1 = document.querySelector("#umami-site-pv"); if (ele1) { ele1.textContent = pageViews; // 设置页面浏览量 } let ele2 = document.querySelector("#umami-site-uv"); if (ele2) { ele2.textContent = uniqueVisitors; } console.log(uniqueVisitors, pageViews); console.log(data); } catch (error) { console.error(error); return "-1"; } } allStats(); ``` **index.html:** ```html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> </head> <body> <div style="text-align:center;"> <h1>Umami 网站统计</h1> <span>总访问量 <span id="umami-site-pv"></span> 次</span> <span>总访客数 <span id="umami-site-uv"></span> 人</span> </div> <script src="umamiStats.js"></script> </body> </html> ``` * 在这个示例中,创建了一个名为 `umamiStats.js`的JavaScript文件,并在HTML文件中使用 `<script>`标签引用它。这样可以使代码更加清晰和模块化。 最后修改:2024 年 04 月 22 日 © 允许规范转载 赞 如果觉得我的文章对你有用,请随意赞赏