功能更新

This commit is contained in:
李琦
2026-08-15 17:04:47 +08:00
parent d9475ac9da
commit b71b99a60d
49 changed files with 4976 additions and 438 deletions

View File

@@ -1,70 +1,68 @@
# nl-pms-api
code-countview 桌面端)的文件存储服务:客户端凭密钥上传图片,换取可公开访问的
http URL。管理员云端账号 id=1在 view 的「文件存储」配置里把存储方式设为
「服务器」并填入本服务地址与密钥后,内容图片(`imageMode=server`)与头像会上传到
这里Markdown / 头像直接引用返回的 URL —— 跨设备、跨团队都能访问,不再依赖本地路径。
code-countview 桌面端)的 **云同步 + 文件存储** HTTP 服务。桌面端不再直连 MySQL
登录一次拿到 JWT 后,同步、团队、文件上传共用同一 Bearer无需二次登录。
技术栈Go + gin + gormMySQL 与 view 同步服务共用 `code_count` 库(新表 `pms_files`
技术栈Go + gin + gorm。分层:`router → controller → service → commonservice → model`
MySQL 库 `code_count` 的 DDL 以本仓库 [`init.sql`](./init.sql) 为唯一来源。
## 接口
## 鉴权
| 方法 | 路径 | 鉴权 | 说明 |
|---|---|---|---|
| GET | `/healthz` | 无 | 健康检查view「测试连接」调用 |
| POST | `/api/v1/files` | `Authorization: Bearer <api_key>` | multipart 上传:`file` 必填,`kind`avatar\|content`userId``teamId` 可选;返回 `{id, name, url, size, mime, teamId}` |
| GET | `/api/v1/files` | 同上 | 素材库列表:`scope=mine\|team\|all` + `userId` + `teamId` + `page` + `pageSize`mine 看自己team 需为该团队 owner/adminall 仅超管userId=1返回 `{total, items}`(含上传者 `username` |
| DELETE | `/api/v1/files/:id` | 同上 | 删除素材(记录+磁盘文件):本人、超管 id=1、或该文件归属团队的 owner/admin |
| GET | `/files/*path` | 无 | 文件公开访问(路径含 128 位随机 hex不可枚举 |
| 方 | 说明 |
|---|---|
| 公开 | `GET /healthz``POST /api/v1/auth/register\|login\|refresh` |
| JWT | 其余 `/api/v1/*``Authorization: Bearer <accessToken>` |
| 刷新 | `POST /api/v1/auth/refresh` `refreshToken` 换新双令牌 |
上传约束:默认单文件 ≤ 20MB`max_upload_mb`);按内容嗅探只接受 jpeg/png/gif/webp
同一归属(`userId`+`teamId`)重复上传相同内容直接复用已有记录(秒传),
不同归属各自落盘,保证删除自己的素材不影响他人引用。
配置项:`jwt_secret`(必填)、`access_ttl_hours`(默认 2`refresh_ttl_days`(默认 30
身份模型:沿用 code-count 的内网信任模型 —— 客户端自报 `userId`/`teamId`
服务端按 code_count 库的 `team_members`/`users` 判定管理范围(防误操作,不防伪造)。
身份从 JWT claims 解析(`user_id` / `username`**不再信任客户端自报 userId**。
```bash
curl http://127.0.0.1:8788/healthz
curl -H "Authorization: Bearer change-me" -F "file=@a.png" -F "kind=content" \
http://127.0.0.1:8788/api/v1/files
```
## 主要接口
| 方法 | 路径 | 说明 |
|---|---|---|
| GET | `/healthz` | 健康检查 |
| POST | `/api/v1/auth/register` | 注册 `{username,password}` |
| POST | `/api/v1/auth/login` | 登录 → `{accessToken,refreshToken,userId,username}` |
| POST | `/api/v1/auth/refresh` | 刷新 `{refreshToken}` |
| POST | `/api/v1/auth/change-password` | 改密 `{oldPassword,newPassword}` |
| POST | `/api/v1/sync/push` | `{table,rows}` LWW 推送 |
| GET | `/api/v1/sync/pull` | `table` + `cursor` 增量拉取 |
| GET/PUT | `/api/v1/settings/:name` | 用户/全局设置 KV |
| GET | `/api/v1/settings?prefix=` | 按前缀批量(如 `fest_img:` |
| GET | `/api/v1/settings/global/:name` | 读管理员全局设置 |
| GET/PUT | `/api/v1/profile` | 公开资料 |
| GET | `/api/v1/notices` | 团队通知 `after=` |
| * | `/api/v1/teams...` | 团队/任务/日报/摘要 |
| POST/GET/DELETE | `/api/v1/files` | 图片上传/列表/删除JWT |
| GET | `/files/*path` | 文件公开访问(随机路径) |
上传约束:默认单文件 ≤ 20MB仅 jpeg/png/gif/webp同归属秒传去重。
## 配置
复制 `config.example.yaml``config.yaml` 后修改(启动可用 `-config` 指定路径)。
必填:`api_key`(客户端上传密钥)、`mysql.dsn``base_url` 建议填客户端可达地址
留空则按请求 Host 推断。
复制 `config.example.yaml``config.yaml` 后修改。必填:`jwt_secret``mysql.dsn`
`base_url` 建议填客户端可达地址(拼文件 URL
## 数据库迁移约定(重要)
## 数据库迁移约定
- **仅 dev 环境自动迁移**`config.yaml``env: dev` 时,启动执行 `AutoMigrate`
- **生产绝不迁移**`env: prod`(默认)启动只检查 `pms_files` 表是否存在,
缺表直接报错退出,不执行任何 DDL。部署 / 升级前先手工执行:
- **仅 dev**`env: dev`)启动 AutoMigrate。
- **生产绝不迁移**缺表直接退出。部署前:
```bash
mysql -u root -p < init.sql
```
`init.sql` 可重复执行(`CREATE TABLE IF NOT EXISTS`),索引名与 gorm 默认命名一致,
避免 dev / prod 两套 schema 漂移。
## 运行
```bash
# 开发(自动迁移)
go run . -config config.yaml # config.yaml 里 env: dev
# 生产(先执行 init.sql再构建部署
go build -o bin/nl-pms-api . # Windows 产出 bin/nl-pms-api.exe
go build -o bin/nl-pms-api .
./bin/nl-pms-api -config /etc/nl-pms-api/config.yaml
```
Windows 可用 nssm / 计划任务托管Linux 建议 systemd服务本身无状态
备份只需 `uploads/` 目录与 `pms_files` 表。
## 与桌面端的关系
## 安全权衡(内网定位)
- 上传密钥经 view 的 `sync_settings` 明文下发给所有登录客户端(与节日背景图同机制),
按内网工具定位设计;暴露公网需自行加 HTTPS 反代与更强的凭证体系。
- 图片 GET 公开:`<img>` 标签无法携带鉴权头,靠随机路径保证不可枚举。
view 打包配置 `build/sync.defaults.json``baseUrl` 指向本服务。
登录后本地存 `sync_access_token` / `sync_refresh_token`;文件存储「服务器」模式只需填本服务 `baseUrl`,鉴权用登录 JWT。