更新下载次数记录和更新次数记录等

This commit is contained in:
rucky
2026-04-07 18:30:49 +08:00
parent f459cc9ad0
commit 9dc6c0dcce
18 changed files with 665 additions and 591 deletions

689
API.md
View File

@@ -1,75 +1,23 @@
# Nanami Web API 文档
# Nanami 启动器 API 文档
Base URL: `https://nui.rucky.cn`
> Base URL: `https://nanami.rucky.cn`(或对应部署地址)
>
> 标注说明:🆕 新增 | ✏️ 有变动 | 无标注为原有不变
---
## 目录
## 1. 检查更新 ✏️
- [公开接口](#公开接口)
- [服务器时间](#服务器时间)
- [检查更新](#检查更新)
- [启动器最新版本](#启动器最新版本)
- [软件版本下载](#软件版本下载)
- [插件列表](#插件列表)
- [插件详情](#插件详情)
- [插件版本下载](#插件版本下载)
- [Banner 列表](#banner-列表)
- [画廊图片列表](#画廊图片列表)
- [管理接口(需认证)](#管理接口需认证)
- [软件管理](#软件管理)
- [软件版本管理](#软件版本管理)
- [插件管理](#插件管理)
- [插件版本发布](#插件版本发布)
- [Banner 管理](#banner-管理)
- [画廊管理](#画廊管理)
- [文件上传](#文件上传)
- [修改密码](#修改密码)
---
## 公开接口
### 服务器时间
获取服务器当前时间。
```
GET /api/server-time
```
**响应示例:**
```json
{
"timestamp": 1710748800000,
"iso": "2026-03-18T08:00:00.000Z",
"timezone": "Asia/Shanghai"
}
```
| 字段 | 类型 | 说明 |
|------|------|------|
| `timestamp` | `number` | Unix 毫秒时间戳 |
| `iso` | `string` | ISO 8601 格式时间 |
| `timezone` | `string` | 服务器时区 |
---
### 检查更新
客户端检查软件是否有新版本可用。
检查指定软件是否有新版本。
```
GET /api/software/check-update?slug={slug}&versionCode={versionCode}
```
**查询参数:**
| 参数 | 必填 | 说明 |
|------|------|------|
| `slug` | 是 | 软件标识符,如 `nanami-launcher` |
| `versionCode` | 否 | 当前客户端版本号(整数),默认 `0` |
| 参数 | 类型 | 必填 | 说明 |
|------|------|------|------|
| slug | string | | 软件标识,如 `nanami-launcher``nanami-launcher-patch` |
| versionCode | number | 否 | 当前客户端版本号(整数),不传默认为 0 |
**响应示例:**
@@ -78,564 +26,177 @@ GET /api/software/check-update?slug={slug}&versionCode={versionCode}
"hasUpdate": true,
"forceUpdate": false,
"latest": {
"version": "0.8.15",
"versionCode": 815,
"changelog": "修复了若干问题...",
"downloadUrl": "https://cdn.example.com/launcher-setup.exe",
"version": "1.3.0",
"versionCode": 130,
"changelog": "- 修复xxx\n- 新增xxx",
"downloadUrl": "https://nanami.rucky.cn/api/software/download/clxxx?source=launcher",
"fileSize": 52428800,
"minVersion": "0.7.0",
"createdAt": "2026-03-15T10:00:00.000Z"
"minVersion": "1.0.0",
"createdAt": "2026-03-25T10:00:00.000Z"
}
}
```
| 字段 | 类型 | 说明 |
|------|------|------|
| `hasUpdate` | `boolean` | 是否有新版本 |
| `forceUpdate` | `boolean` | 是否需要强制更新 |
| `latest.version` | `string` | 最新版本号 |
| `latest.versionCode` | `number` | 最新版本编码 |
| `latest.changelog` | `string` | 更新日志 |
| `latest.downloadUrl` | `string` | 下载地址 |
| `latest.fileSize` | `number` | 文件大小(字节) |
| `latest.minVersion` | `string\|null` | 最低兼容版本 |
| `latest.createdAt` | `string` | 发布时间 |
**✏️ 变动说明**:返回的 `downloadUrl` 现在自动附带 `?source=launcher` 参数,启动器直接使用该 URL 下载即可,下载量会被单独统计为「客户端更新下载」,与网页端下载区分。启动器无需做任何额外处理。
---
### 启动器最新版本
## 2. 下载文件 ✏️
获取启动器最新版本信息或直接下载
#### 获取信息
根据版本 ID 下载文件。通常不需要手动拼接,直接使用 check-update 返回的 `downloadUrl` 即可
```
GET /api/software/latest?info=1
GET /api/software/download/{versionId}?source={source}
```
添加 `&track=1` 可同时记录一次下载计数。
| 参数 | 类型 | 必填 | 说明 |
|------|------|------|------|
| versionId | string | 是 | 路径参数,版本记录 ID |
| source | string | 否 | 下载来源标识,传 `launcher` 表示客户端更新下载 |
**响应示例:**
**响应**
- 本地文件:直接返回二进制流(`Content-Type: application/octet-stream`
- 外链文件302 重定向到外部 URL
**✏️ 变动说明**:新增 `source` 查询参数。当 `source=launcher`下载量会同时计入总下载量和启动器更新下载量两个计数器。check-update 返回的 URL 已自动包含此参数,启动器无需手动处理。
---
## 3. 获取最新版本信息(网页用)
获取 nanami-launcher 的最新版本信息或直接下载,主要给网页端使用。
```
GET /api/software/latest?info=1&track=1
```
| 参数 | 类型 | 必填 | 说明 |
|------|------|------|------|
| info | string | 否 | 传 `1` 返回 JSON 元数据;不传则直接下载文件 |
| track | string | 否 | 仅在 `info=1` 时生效,传 `1` 同时计数下载量 |
**响应示例info=1**
```json
{
"available": true,
"version": "0.8.15",
"versionCode": 815,
"changelog": "更新内容...",
"version": "1.3.0",
"versionCode": 130,
"changelog": "...",
"fileSize": 52428800,
"createdAt": "2026-03-15T10:00:00.000Z",
"downloadUrl": "https://cdn.example.com/launcher-setup.exe",
"downloadType": "url"
"createdAt": "2026-03-25T10:00:00.000Z",
"downloadUrl": "/api/software/download/clxxx",
"downloadType": "local"
}
```
当无可用版本时返回:
```json
{ "available": false }
```
#### 直接下载
```
GET /api/software/latest
```
- 外部链接类型302 重定向到外部 URL
- 本地文件类型:返回文件流
- 自动记录下载次数
> 此接口固定查询 slug 为 `nanami-launcher` 的软件,启动器通常使用 check-update 接口而非此接口。
---
### 软件版本下载
## 4. 上报心跳(在线状态) 🆕
按版本 ID 下载特定版本
启动器定期调用此接口上报在线状态,建议每 **60 秒** 调用一次。超过 3 分钟无心跳视为离线
```
GET /api/software/download/{id}
```
**路径参数:**
| 参数 | 说明 |
|------|------|
| `id` | 软件版本 ID |
- 外部链接类型302 重定向
- 本地文件类型:返回文件流(`application/octet-stream`
- 自动记录下载次数
**错误响应:**
| 状态码 | 说明 |
|--------|------|
| `404` | 版本不存在或文件不存在 |
---
### 插件列表
获取已发布的插件列表。
```
GET /api/addons
```
**查询参数:**
| 参数 | 必填 | 说明 |
|------|------|------|
| `category` | 否 | 按分类筛选 |
| `search` | 否 | 按名称/简介搜索(模糊匹配) |
| `published` | 否 | 默认 `true`,设为 `false` 查询所有 |
**响应示例:**
```json
[
{
"id": "clxx...",
"name": "插件名",
"slug": "addon-slug",
"summary": "插件简介",
"description": "详细描述...",
"iconUrl": "/uploads/icon.png",
"category": "ui",
"published": true,
"totalDownloads": 1024,
"createdAt": "2026-01-01T00:00:00.000Z",
"updatedAt": "2026-03-01T00:00:00.000Z",
"releases": [{ "...最新版本..." }],
"_count": { "releases": 5 }
}
]
```
---
### 插件详情
获取单个插件详细信息,包含所有版本和截图。
```
GET /api/addons/{id}
```
**路径参数:** `id` 可以是插件 ID 或 slug。
**响应:** 插件完整信息,含 `releases`(按时间倒序)和 `screenshots`(按排序序号)。
---
### 插件版本下载
```
GET /api/download/{id}
```
**路径参数:**
| 参数 | 说明 |
|------|------|
| `id` | Release 版本 ID |
- 自动增加 Release 和 Addon 的下载计数
- 外部链接类型302 重定向
- 本地文件类型:返回文件流
---
### Banner 列表
```
GET /api/banners
```
**查询参数:**
| 参数 | 说明 |
|------|------|
| `enabled` | 设为 `1` 仅返回已启用的 Banner |
**响应示例:**
```json
[
{
"id": "clxx...",
"imageUrl": "/banners/banner_1.png",
"sortOrder": 0,
"enabled": true,
"createdAt": "2026-01-01T00:00:00.000Z"
}
]
```
---
### 画廊图片列表
```
GET /api/gallery
```
**查询参数:**
| 参数 | 说明 |
|------|------|
| `enabled` | 设为 `1` 仅返回已启用的图片 |
**响应示例:**
```json
[
{
"id": "clxx...",
"imageUrl": "/views/view_1.png",
"title": "主界面",
"sortOrder": 0,
"enabled": true,
"createdAt": "2026-01-01T00:00:00.000Z"
}
]
```
---
## 管理接口(需认证)
以下接口需要管理员登录后的 Session 认证。未认证请求返回 `401 Unauthorized`
### 软件管理
#### 获取软件列表
```
GET /api/software
```
返回所有软件及其最新版本和版本数量。
#### 创建软件
```
POST /api/software
POST /api/launcher/heartbeat
Content-Type: application/json
```
**请求体:**
```json
{
"name": "Nanami Launcher",
"slug": "nanami-launcher",
"description": "启动器描述"
"deviceId": "unique-machine-id",
"os": "Windows",
"osVersion": "10.0.19045",
"appVersion": "1.3.0"
}
```
| 字段 | 必填 | 说明 |
|------|------|------|
| `name` | 是 | 软件名称 |
| `slug` | 是 | 唯一标识符 |
| `description` | 否 | 描述 |
#### 获取软件详情
```
GET /api/software/{id}
```
`id` 可以是软件 ID 或 slug返回软件信息及所有版本。
#### 更新软件
```
PUT /api/software/{id}
Content-Type: application/json
{
"name": "新名称",
"slug": "new-slug",
"description": "新描述"
}
```
#### 删除软件
```
DELETE /api/software/{id}
```
---
### 软件版本管理
#### 创建新版本
```
POST /api/software/{id}/versions
Content-Type: application/json
{
"version": "1.0.0",
"versionCode": 100,
"changelog": "首次发布",
"downloadType": "url",
"externalUrl": "https://cdn.example.com/file.exe",
"fileSize": 52428800,
"forceUpdate": false,
"minVersion": null
}
```
| 字段 | 必填 | 类型 | 说明 |
| 字段 | 类型 | 必填 | 说明 |
|------|------|------|------|
| `version` | 是 | `string` | 版本号 |
| `versionCode` | | `number` | 版本编码(用于比较) |
| `changelog` | 否 | `string` | 更新日志 |
| `downloadType` | 否 | `string` | `"local"``"url"`,默认 `"local"` |
| `filePath` | 否 | `string` | 本地文件路径 |
| `externalUrl` | 否 | `string` | 外部下载链接 |
| `fileSize` | 否 | `number` | 文件大小(字节) |
| `forceUpdate` | 否 | `boolean` | 是否强制更新 |
| `minVersion` | 否 | `string` | 最低兼容版本 |
| deviceId | string | **是** | 设备唯一标识,建议使用机器码或 UUID 持久化存储 |
| os | string | | 操作系统名称,如 `Windows``macOS``Linux` |
| osVersion | string | 否 | 系统版本号,如 `10.0.19045``14.3` |
| appVersion | string | 否 | 启动器版本号,如 `1.3.0` |
新版本自动设为 `isLatest: true`,之前的最新版本会被取消。
**响应:**
#### 更新版本
```
PUT /api/software/versions/{versionId}
Content-Type: application/json
{
"version": "1.0.1",
"changelog": "修复问题",
"isLatest": true
}
```json
{ "ok": true }
```
所有字段均为可选,仅更新传入的字段。设置 `isLatest: true` 时自动取消其他版本的最新标记。
#### 删除版本
```
DELETE /api/software/versions/{versionId}
```
**实现建议**
- 启动器启动时立即发送一次心跳,之后每 60 秒发送一次
- `deviceId` 需要在客户端持久化保存,确保同一台机器始终使用相同 ID
- IP 地址由服务端自动获取,无需客户端上报
- 网络失败时静默忽略即可,不影响启动器正常功能
---
### 插件管理
## 5. 历史更新日志 🆕
#### 创建插件
查询指定软件的所有版本历史和更新日志,按版本号倒序排列。
```
POST /api/addons
Content-Type: application/json
{
"name": "插件名",
"slug": "addon-slug",
"summary": "简介",
"description": "详细描述",
"iconUrl": "/uploads/icon.png",
"category": "ui"
}
GET /api/software/changelog?slug={slug}
```
| 字段 | 必填 | 说明 |
|------|------|------|
| `name` | 是 | 插件名称 |
| `slug` | 是 | 唯一标识符 |
| `summary` | 是 | 简短描述 |
| `description` | 否 | 详细描述 |
| `iconUrl` | 否 | 图标 URL |
| `category` | 否 | 分类,默认 `"general"` |
#### 更新插件
```
PUT /api/addons/{id}
Content-Type: application/json
{
"name": "新名称",
"published": true
}
```
#### 删除插件
```
DELETE /api/addons/{id}
```
---
### 插件版本发布
```
POST /api/releases
Content-Type: application/json
{
"addonId": "插件ID",
"version": "1.0.0",
"changelog": "首次发布",
"downloadType": "url",
"externalUrl": "https://cdn.example.com/addon.zip",
"gameVersion": "11.1.0"
}
```
| 字段 | 必填 | 说明 |
|------|------|------|
| `addonId` | 是 | 所属插件 ID |
| `version` | 是 | 版本号 |
| `changelog` | 否 | 更新日志 |
| `downloadType` | 否 | `"local"``"url"` |
| `filePath` | 否 | 本地文件路径 |
| `externalUrl` | 否 | 外部链接(`downloadType``"url"` 时必填) |
| `gameVersion` | 否 | 适配的游戏版本 |
#### 获取版本列表
```
GET /api/releases?addonId={addonId}
```
---
### Banner 管理
#### 创建 Banner
```
POST /api/banners
Content-Type: application/json
{
"imageUrl": "/uploads/banner.png",
"sortOrder": 0,
"enabled": true
}
```
#### 更新 Banner
```
PUT /api/banners/{id}
Content-Type: application/json
{
"sortOrder": 1,
"enabled": false
}
```
#### 删除 Banner
```
DELETE /api/banners/{id}
```
---
### 画廊管理
#### 创建画廊图片
```
POST /api/gallery
Content-Type: application/json
{
"imageUrl": "/uploads/screenshot.png",
"title": "主界面截图",
"sortOrder": 0,
"enabled": true
}
```
#### 更新画廊图片
```
PUT /api/gallery/{id}
Content-Type: application/json
{
"title": "新标题",
"sortOrder": 2,
"enabled": true
}
```
#### 删除画廊图片
```
DELETE /api/gallery/{id}
```
---
### 文件上传
上传文件到服务器。
```
POST /api/upload
Content-Type: multipart/form-data
file: (二进制文件)
```
| 参数 | 类型 | 必填 | 说明 |
|------|------|------|------|
| slug | string | 是 | 软件标识,如 `nanami-launcher``nanami-launcher-patch` |
**响应示例:**
```json
{
"filePath": "/uploads/1710748800000-image.png",
"originalName": "image.png",
"size": 204800
"name": "Nanami 启动器(全量包)",
"slug": "nanami-launcher",
"versions": [
{
"version": "1.3.0",
"versionCode": 130,
"changelog": "- 新增xxx\n- 修复xxx",
"fileSize": 52428800,
"isLatest": true,
"forceUpdate": false,
"createdAt": "2026-03-25T10:00:00.000Z"
},
{
"version": "1.2.0",
"versionCode": 120,
"changelog": "- 优化xxx",
"fileSize": 50331648,
"isLatest": false,
"forceUpdate": false,
"createdAt": "2026-03-10T08:00:00.000Z"
}
]
}
```
返回的 `filePath` 可用于其他接口的 `imageUrl``filePath` 等字段。
**响应字段说明:**
| 字段 | 类型 | 说明 |
|------|------|------|
| versions[].version | string | 版本号 |
| versions[].versionCode | number | 版本号(整数),用于比较大小 |
| versions[].changelog | string | 更新日志内容 |
| versions[].fileSize | number | 文件大小(字节) |
| versions[].isLatest | boolean | 是否为当前最新版本 |
| versions[].forceUpdate | boolean | 是否为强制更新版本 |
| versions[].createdAt | string | 发布时间ISO 8601 |
---
### 修改密码
## 接口一览
```
POST /api/admin/change-password
Content-Type: application/json
{
"currentPassword": "当前密码",
"newPassword": "新密码≥6位"
}
```
**错误响应:**
| 状态码 | 说明 |
|--------|------|
| `400` | 参数缺失或新密码过短 |
| `403` | 当前密码错误 |
| `404` | 用户不存在 |
---
## 通用错误格式
所有 API 错误均以 JSON 格式返回:
```json
{
"error": "错误描述信息"
}
```
| 状态码 | 说明 |
|--------|------|
| `400` | 请求参数错误 |
| `401` | 未认证 |
| `404` | 资源不存在 |
| `409` | 资源冲突(如 slug 重复) |
| `500` | 服务器内部错误 |
| 方法 | 路径 | 状态 | 用途 |
|------|------|------|------|
| GET | `/api/software/check-update` | ✏️ 变动 | 检查更新downloadUrl 已含 source 标记 |
| GET | `/api/software/download/{id}` | ✏️ 变动 | 下载文件,支持 source 参数区分来源 |
| GET | `/api/software/latest` | 无变动 | 获取最新版信息/下载(网页用) |
| GET | `/api/software/changelog` | 🆕 新增 | 查询历史更新日志 |
| POST | `/api/launcher/heartbeat` | 🆕 新增 | 上报在线状态 |