logo
2
1
WeChat Login

Open Kounter

Open Kounter 是一个基于 EdgeOne Pages Functions 和 Blob 存储的无服务器计数器服务,旨在替代 LeanCloud 为静态网站(如 Hexo)提供 PV/UV 统计功能。它包含一个完整的管理后台,支持数据管理、导入导出、域名白名单、旧版 KV 一键迁移、Passkey 无密码登录和 OIDC 单点登录。

Open Kounter Demo

更详细的介绍和部署指南请参考:

EdgeOne Pages 上部署

你可以通过 EdgeOne Pages 一键部署或手动配置构建:

一键部署:

使用 EdgeOne Pages 部署

注意:点击上方按钮前,建议先 Fork 本仓库,并在跳转后的页面中确认仓库地址为你 Fork 后的地址。

手动部署配置:

  • 框架预设:Node.js(或留空,EdgeOne 会识别 edgeone.json
  • 构建命令:npm run build
  • 输出目录:dist
  • Node 版本:22

更多 EdgeOne Pages文档:https://pages.edgeone.ai/zh/document/product-introduction

为什么从 KV 切换到 Blob

Open Kounter 早期使用 EdgeOne Pages KV 保存计数器、配置和认证信息,但 KV 的全球同步是最终一致模型,在多节点场景下会有明显同步延迟。

  • 计数器刚写入后,后台列表或下一次读取可能短时间内看不到最新值。
  • 域名白名单、Token、Passkey 相关状态在边缘节点之间同步时,也可能出现短暂不一致。
  • 对于计数器这类“写完就要立刻读到最新结果”的场景,KV 的全球同步延迟会直接影响可用性。

现在主存储已经切换为 Blob,并在核心读取路径中使用强一致读取。这样做的目标很明确:解决 KV 全球同步存在延迟的问题,让计数、配置和认证状态在写入后能更快、更稳定地读到最新值。

配置 Blob 存储(必需)

本项目使用 Blob 作为主存储,部署后会在 cloud-functions 中自动创建并使用名为 open-kounter 的 Blob Store。

  1. 开启 Blob 能力
  • 在 EdgeOne Pages 控制台进入项目设置 > 存储
  • 确认项目已开通 Blob 能力
  1. 首次访问自动创建 Store
  • 默认会使用 open-kounter 作为 Blob Store 名称
  • 如需自定义名称,可设置环境变量 OPEN_KOUNTER_BLOB_STORE
  1. Passkey 域名配置(可选)
  • Passkey 默认会使用当前页面 Origin 的 hostname 作为 RP ID
  • 如需固定 RP ID 或跨环境统一配置,可设置环境变量 PASSKEY_RP_ID
  • 如需自定义显示名称,可设置环境变量 PASSKEY_RP_NAME
  1. OIDC 单点登录配置(可选)
  • 如需启用 OIDC 登录,需设置以下环境变量:
    • OIDC_ISSUER:OIDC 提供商的 Issuer URL(如 https://auth.example.com/realms/master
    • OIDC_CLIENT_ID:客户端 ID
    • OIDC_CLIENT_SECRET:客户端密钥
    • OIDC_REDIRECT_URI:回调地址(如 https://your-domain.com/api/oidc/callback
  • 配置完成后,管理员需先使用 Token 登录,在控制面板中绑定 OIDC 账号,之后即可使用 OIDC 登录
  • 登录页会自动检测 OIDC 配置状态,仅在配置完整且已绑定时显示 OIDC 登录按钮
  1. 重新部署项目
  • 启用 Blob 或调整环境变量后建议重新部署

旧版 KV 迁移(可选)

如果你是从旧版 KV 存储迁移,请额外绑定旧 KV 命名空间,变量名仍为:OPEN_KOUNTER

  • 新部署且没有历史数据时,不需要绑定 KV。
  • 已有旧 KV 数据时,可在登录页或后台“数据备份”面板中点击“旧 KV 迁移到 Blob”。

初始化

部署并配置完成后,访问你的项目网址,首次访问将引导你设置管理员 Token。

目录结构与文件说明

.
├── client/
│   └── adapter.js          # 客户端适配器,模拟 LeanCloud 行为
├── cloud-functions/        # 主后端逻辑 (Blob API)
│   └── api/
│       ├── auth.js         # 认证逻辑
│       ├── counter.js      # 核心计数器逻辑
│       ├── init.js         # 初始化与迁移接口
│       ├── passkey.js      # Passkey 相关逻辑
│       └── oidc/           # OIDC 单点登录
│           ├── login.js    # OIDC 登录发起
│           ├── callback.js # OIDC 回调处理
│           └── status.js   # OIDC 绑定状态查询
├── edge-functions/         # 兼容旧版 KV 的迁移出口
│   └── legacy-api/
│       └── migrate.js      # 导出旧 KV 数据供 Blob 导入
├── src/                    # 前端管理后台 (Vue 3 + Vite)
│   ├── components/
│   │   ├── dashboard/
│   │   │   ├── CounterList.vue          # 计数器列表
│   │   │   ├── DataBackup.vue           # 数据备份与恢复
│   │   │   ├── DomainConfig.vue         # 域名白名单配置
│   │   │   ├── OidcManager.vue          # OIDC 绑定管理
│   │   │   ├── PasskeyManager.vue       # Passkey 管理
│   │   │   ├── SingleCounterManager.vue # 单个计数器管理
│   │   │   └── TotalStats.vue           # 统计概览
│   │   ├── Dashboard.vue   # 仪表盘主组件
│   │   └── Login.vue       # 登录组件
│   ├── utils/              # 工具函数
│   ├── App.vue             # 主应用组件
│   ├── main.js             # 入口文件
│   └── style.css           # 全局样式
├── edgeone.json            # EdgeOne 配置文件
├── index.html              # HTML 入口
├── package.json            # 项目依赖
├── tailwind.config.js      # Tailwind 配置
└── vite.config.js          # Vite 配置

API 接口文档

所有 API 的基础路径为 /api

公开接口 (无需认证)

1. 获取计数

  • URL: GET /api/counter
  • 参数: target (必填,计数器的 Key,如 site-pv)
  • 响应:
    {
      "code": 0,
      "data": {
        "time": 100,
        "target": "site-pv",
        "created_at": 1700000000000,
        "updated_at": 1700000000000
      }
    }
    

2. 增加计数 (自增)

  • URL: POST /api/counter
  • Body:
    {
      "action": "inc",
      "target": "site-pv"
    }
    
  • 说明: 受域名白名单限制。

3. 批量增加计数

  • URL: POST /api/counter
  • Body:
    {
      "action": "batch_inc",
      "requests": [
        { "target": "site-pv" },
        { "target": "/posts/hello-world/" }
      ]
    }
    
  • 说明: 常用于同时更新站点总 PV 和单页 PV。受域名白名单限制。

管理接口 (需要认证)

需要在 Header 中携带 Authorization: Bearer <YOUR_TOKEN>

1. 设置计数器值

  • URL: POST /api/counter
  • Body:
    {
      "action": "set",
      "target": "site-pv",
      "value": 1000
    }
    

2. 删除计数器

  • URL: POST /api/counter
  • Body:
    {
      "action": "delete",
      "target": "site-pv"
    }
    

3. 获取计数器列表

  • URL: POST /api/counter
  • Body:
    {
      "action": "list",
      "page": 1,
      "pageSize": 20
    }
    

4. 导出所有数据

  • URL: POST /api/counter
  • Body: { "action": "export_all" }
  • 响应: 包含所有计数器数据和配置的 JSON 对象。

5. 导入数据

  • URL: POST /api/counter
  • Body:
    {
      "action": "import_all",
      "data": { ... } // 导出的 JSON 数据
    }
    

6. 配置域名白名单

  • URL: POST /api/counter
  • Body:
    {
      "action": "set_config",
      "allowedDomains": ["example.com", "*.example.com"]
    }
    

环境变量一览

变量名必需说明
OPEN_KOUNTER_BLOB_STORE自定义 Blob Store 名称,默认 open-kounter
ADMIN_TOKEN预设管理员 Token(优先级高于 Blob 中存储的 Token)
PASSKEY_RP_IDPasskey RP ID,默认使用当前域名
PASSKEY_RP_NAMEPasskey 显示名称,默认 Open Kounter
OIDC_ISSUEROIDC Issuer URL
OIDC_CLIENT_IDOIDC 客户端 ID
OIDC_CLIENT_SECRETOIDC 客户端密钥
OIDC_REDIRECT_URIOIDC 回调地址

登录方式

Open Kounter 支持三种登录方式,登录页会自动检测可用的登录方式并渐进式展示:

  1. Token 登录(始终可用):使用管理员 Token 直接登录
  2. Passkey 登录(按需展示):在后台绑定 Passkey 后,登录页自动显示 Passkey 登录按钮
  3. OIDC 登录(按需展示):配置 OIDC 环境变量并在后台绑定 OIDC 账号后,登录页自动显示 OIDC 登录按钮

登录页加载时会先进行环境检测(显示加载动画),检测完成后仅展示已配置/已绑定的登录方式,保持界面简洁。

许可证

本项目基于 MIT License 开源。

About

A lightweight visitor counter based on KV, an alternative to LeanCloud.

1.64 MiB
2 forks1 stars2 branches0 TagREADMEMIT license
Language
Vue55.3%
JavaScript44.2%
CSS0.3%
HTML0.2%