26.9:品牌统一(fileshare)+ 版本号改为日期式
- 数据库默认文件 filecodebox.db → fileshare.db(config.go 默认值与全部文档/编排同步)
- Go module filecodebox → fileshare(全部 import 同步,build/vet/test 全绿)
- 应用版本 APP_VERSION 2.5.6 → 26.9(health 接口已验证返回 26.9)
- deploy 编排统一:compose 项目名、Postgres 默认凭据、minio 桶名、env 注释
- JWT issuer、存储临时目录前缀、web 包名同步 fileshare
- CI:镜像 tag 以 APP_VERSION 为唯一版本源,main/tag 推送即发布
${VER} + latest;tag 触发时校验 tag 名与 APP_VERSION 一致,防错版
- 本地开发库文件已改名 fileshare.db(含 -shm/-wal 清理)
This commit is contained in:
@@ -3,7 +3,7 @@ name: Release 镜像
|
||||
on:
|
||||
push:
|
||||
branches: [main]
|
||||
tags: ["v*"]
|
||||
tags: ["v*", "26.*", "27.*"]
|
||||
workflow_dispatch:
|
||||
|
||||
env:
|
||||
@@ -57,20 +57,21 @@ jobs:
|
||||
- name: 安装 Docker CLI(挂宿主 daemon)
|
||||
run: apk add --no-cache docker-cli buildx >/dev/null
|
||||
|
||||
- name: 计算 tag 与平台
|
||||
- name: 计算 tag(以 APP_VERSION 为唯一版本源)
|
||||
id: meta
|
||||
env:
|
||||
REF: ${{ gitea.ref }}
|
||||
run: |
|
||||
case "$REF" in
|
||||
refs/tags/v*)
|
||||
VER="${REF#refs/tags/v}"
|
||||
echo "tags=${IMAGE}:${VER} ${IMAGE}:latest" >> "$GITHUB_OUTPUT"
|
||||
echo "发布 tag: ${VER} + latest" ;;
|
||||
*)
|
||||
echo "tags=${IMAGE}:latest" >> "$GITHUB_OUTPUT"
|
||||
echo "main 构建: latest" ;;
|
||||
esac
|
||||
VER=$(sed -n 's/.*APP_VERSION = "\(.*\)".*/\1/p' server/cmd/server/main.go | head -1)
|
||||
[ -n "$VER" ] || { echo "无法从 main.go 解析 APP_VERSION" >&2; exit 1; }
|
||||
echo "APP_VERSION=$VER"
|
||||
if [[ "$REF" == refs/tags/* ]]; then
|
||||
# tag 触发:要求 tag 名与 APP_VERSION 一致,防错版发布
|
||||
TAG_VER="${REF#refs/tags/}"
|
||||
TAG_VER="${TAG_VER#v}"
|
||||
[ "$TAG_VER" = "$VER" ] || { echo "tag($TAG_VER) != APP_VERSION($VER),拒绝发布" >&2; exit 1; }
|
||||
fi
|
||||
echo "tags=${IMAGE}:${VER} ${IMAGE}:latest" >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: 登录阿里云 ACR
|
||||
env:
|
||||
@@ -99,4 +100,8 @@ jobs:
|
||||
.
|
||||
|
||||
- name: 校验远程 manifest(双架构)
|
||||
run: docker buildx imagetools inspect "${IMAGE}:latest" | grep -E "linux/amd64|linux/arm64"
|
||||
env:
|
||||
VERSION: ${{ steps.meta.outputs.version }}
|
||||
run: |
|
||||
docker buildx imagetools inspect "${IMAGE}:${VERSION}" | grep -E "linux/amd64|linux/arm64"
|
||||
echo "推送完成: ${IMAGE}:${VERSION} + ${IMAGE}:latest"
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
文件快传
|
||||
|
||||
数据库**默认 SQLite 零依赖**(modernc.org/sqlite 纯 Go 驱动,数据文件 `./data/filecodebox.db`),
|
||||
数据库**默认 SQLite 零依赖**(modernc.org/sqlite 纯 Go 驱动,数据文件 `./data/fileshare.db`),
|
||||
可选切换 Postgres(`FCB_DB_DRIVER=postgres` + DSN);Redis 为**可选**增强(未配置时自动降级为进程内存缓存)。
|
||||
存储引擎支持 **本地 / S3 / WebDAV**(运行时热切换,健康检查通过才生效;WebDAV 重点优化:流式、Range、重试、连接复用)。
|
||||
|
||||
@@ -37,7 +37,7 @@ docker compose up -d --build
|
||||
```
|
||||
|
||||
- **数据库双路径**:默认 SQLite 零依赖——`docker compose up -d --build` 即可(无需 postgres profile,
|
||||
数据落 `serverdata` 卷 `/app/data/filecodebox.db`);Postgres 模式——`.env` 设
|
||||
数据落 `serverdata` 卷 `/app/data/fileshare.db`);Postgres 模式——`.env` 设
|
||||
`FCB_DB_DRIVER=postgres` 与 `FCB_DB_DSN` 后 `docker compose --profile postgres up -d --build`。
|
||||
- Redis 可选:`--profile redis` 并在 `.env` 设 `FCB_REDIS_ADDR=redis:6379`;未配置时自动降级为内存缓存。
|
||||
- 存储引擎切换:`.env` 改 `FCB_STORAGE_ENGINE=s3|webdav` 并带对应 profile 启动:
|
||||
@@ -51,7 +51,7 @@ docker compose up -d --build
|
||||
```bash
|
||||
# 1) 后端(:8466)——默认 SQLite 零依赖,无需任何数据库
|
||||
cd server
|
||||
go run ./cmd/server # 数据落 ./data/filecodebox.db;go test ./... 运行单测
|
||||
go run ./cmd/server # 数据落 ./data/fileshare.db;go test ./... 运行单测
|
||||
|
||||
# 2) 后端 Postgres 模式(可选)
|
||||
docker run -d --name fcb-pg -p 5432:5432 \
|
||||
@@ -89,7 +89,7 @@ npm run build # 产出 web/dist/,构建时按 deploy/Dockerfil
|
||||
| 变量 | 必需 | 默认 | 说明 |
|
||||
|---|---|---|---|
|
||||
| `FCB_DB_DRIVER` | ❌ | `sqlite` | 数据库驱动:`sqlite` \| `postgres`(v2 需求 ⑧) |
|
||||
| `FCB_DB_DSN` | 视驱动 | - | postgres:连接串(**必需**);sqlite:文件路径(可空,默认 `./data/filecodebox.db`) |
|
||||
| `FCB_DB_DSN` | 视驱动 | - | postgres:连接串(**必需**);sqlite:文件路径(可空,默认 `./data/fileshare.db`) |
|
||||
| `FCB_REDIS_ADDR` | ❌ | 空 | 为空时缓存降级为内存实现;支持 `redis://[:password@]host:port[/db]` / `rediss://` URL 形式 |
|
||||
| `FCB_REDIS_DB` | ❌ | `0` | Redis 逻辑库号 0-15(URL 显式 `/N` 时以 URL 为准) |
|
||||
| `FCB_LISTEN` | ❌ | `:8466` | 监听地址 |
|
||||
|
||||
+6
-6
@@ -5,17 +5,17 @@
|
||||
WEB_PORT=8466
|
||||
|
||||
# ---- 数据库(需求 ⑧)----
|
||||
# 默认 SQLite:零依赖,无需任何下方 Postgres 变量(数据落 serverdata 卷 /app/data/filecodebox.db)
|
||||
# 默认 SQLite:零依赖,无需任何下方 Postgres 变量(数据落 serverdata 卷 /app/data/fileshare.db)
|
||||
FCB_DB_DRIVER=sqlite
|
||||
FCB_DB_DSN=
|
||||
# Postgres 模式(可选):先 `docker compose --profile postgres up -d --build`,再改为:
|
||||
# FCB_DB_DRIVER=postgres
|
||||
# FCB_DB_DSN=postgres://filecodebox:filecodebox@postgres:5432/filecodebox?sslmode=disable
|
||||
# FCB_DB_DSN=postgres://fileshare:fileshare@postgres:5432/fileshare?sslmode=disable
|
||||
|
||||
# ---- Postgres(仅 --profile postgres 时使用;生产务必修改默认口令并启用 TLS)----
|
||||
POSTGRES_USER=filecodebox
|
||||
POSTGRES_PASSWORD=filecodebox
|
||||
POSTGRES_DB=filecodebox
|
||||
POSTGRES_USER=fileshare
|
||||
POSTGRES_PASSWORD=fileshare
|
||||
POSTGRES_DB=fileshare
|
||||
|
||||
# ---- 存储引擎切换:local | s3 | webdav ----
|
||||
FCB_STORAGE_ENGINE=local
|
||||
@@ -47,7 +47,7 @@ FCB_TRUSTED_PROXIES=
|
||||
# 注意:minioadmin/minioadmin 仅为本机冒烟默认值,对外部署必须修改
|
||||
# (并在 compose 中删除 minio 的 ports 发布或仅绑定 127.0.0.1)
|
||||
FCB_S3_ENDPOINT_URL=http://minio:9000
|
||||
FCB_S3_BUCKET_NAME=filecodebox
|
||||
FCB_S3_BUCKET_NAME=fileshare
|
||||
FCB_S3_ACCESS_KEY_ID=minioadmin
|
||||
FCB_S3_SECRET_ACCESS_KEY=minioadmin
|
||||
FCB_S3_REGION_NAME=us-east-1
|
||||
|
||||
+4
-4
@@ -30,7 +30,7 @@ docker compose up -d --build
|
||||
# 打开 http://localhost:8466(.env 可用 WEB_PORT 改端口)→ 自动跳转 /setup 完成初始化
|
||||
```
|
||||
|
||||
- 数据落 **`serverdata` 卷**:容器内 `/app/data/filecodebox.db`(WAL 模式,父目录自动创建)。
|
||||
- 数据落 **`serverdata` 卷**:容器内 `/app/data/fileshare.db`(WAL 模式,父目录自动创建)。
|
||||
- `.env` 中 Postgres 段变量(`POSTGRES_USER/PASSWORD/DB`)在此模式下不生效,无需修改。
|
||||
|
||||
### 路径 ②:Postgres 模式(可选)
|
||||
@@ -39,7 +39,7 @@ docker compose up -d --build
|
||||
|
||||
```dotenv
|
||||
FCB_DB_DRIVER=postgres
|
||||
FCB_DB_DSN=postgres://filecodebox:filecodebox@postgres:5432/filecodebox?sslmode=disable
|
||||
FCB_DB_DSN=postgres://fileshare:fileshare@postgres:5432/fileshare?sslmode=disable
|
||||
```
|
||||
|
||||
2. 带 postgres profile 启动(server 会等 postgres 健康检查通过后再启动):
|
||||
@@ -65,7 +65,7 @@ docker compose up -d --build
|
||||
```bash
|
||||
# S3 引擎(MinIO 冒烟)
|
||||
docker compose --profile minio up -d --build # .env: FCB_STORAGE_ENGINE=s3
|
||||
# minio-init 一次性任务自动建桶(mc mb filecodebox)
|
||||
# minio-init 一次性任务自动建桶(mc mb fileshare)
|
||||
|
||||
# WebDAV 引擎(dufs 冒烟,Basic 认证 admin/admin123@/:rw)
|
||||
docker compose --profile webdav up -d --build # .env: FCB_STORAGE_ENGINE=webdav
|
||||
@@ -125,7 +125,7 @@ curl -I http://localhost:8466/docs # 200(SPA 回退)
|
||||
或在 `.env` 设 `FCB_ADMIN_PASSWORD`(≥8 位)让服务启动即自动初始化,
|
||||
消除「公网上被抢先访问 /setup 接管」的窗口。初始化完成后建议从 `.env` 移除该变量。
|
||||
3. **修改组件默认凭据**:minio(`minioadmin/minioadmin`)、webdav(`admin/admin123`)、
|
||||
Postgres(`filecodebox/filecodebox`)默认凭据仅限本机冒烟;对外部署必须修改,
|
||||
Postgres(`fileshare/fileshare`)默认凭据仅限本机冒烟;对外部署必须修改,
|
||||
且不建议把 9000/9001/5005 端口发布到公网(compose 中删除对应 `ports` 或仅绑 127.0.0.1)。
|
||||
4. **Postgres 建议启用 TLS**:默认示例 DSN 为 `sslmode=disable`,生产请改为
|
||||
`sslmode=require` 及以上。
|
||||
|
||||
@@ -5,10 +5,10 @@
|
||||
# docker compose --profile minio up -d # 可选:S3 引擎冒烟(FCB_STORAGE_ENGINE=s3)
|
||||
# docker compose --profile webdav up -d # 可选:WebDAV 引擎冒烟(FCB_STORAGE_ENGINE=webdav)
|
||||
#
|
||||
# 数据库默认 SQLite(modernc.org/sqlite 纯 Go 驱动,数据落 serverdata 卷 /app/data/filecodebox.db);
|
||||
# 数据库默认 SQLite(modernc.org/sqlite 纯 Go 驱动,数据落 serverdata 卷 /app/data/fileshare.db);
|
||||
# postgres 为可选 profile 服务,启用时 server 经 FCB_DB_DRIVER/FCB_DB_DSN 自动接入;
|
||||
# Redis 同为可选,未配置时服务端内存降级。
|
||||
name: filecodebox
|
||||
name: fileshare
|
||||
|
||||
services:
|
||||
postgres:
|
||||
@@ -18,13 +18,13 @@ services:
|
||||
# 需要时 docker compose --profile postgres up -d --build
|
||||
profiles: ["postgres"]
|
||||
environment:
|
||||
POSTGRES_USER: ${POSTGRES_USER:-filecodebox}
|
||||
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-filecodebox}
|
||||
POSTGRES_DB: ${POSTGRES_DB:-filecodebox}
|
||||
POSTGRES_USER: ${POSTGRES_USER:-fileshare}
|
||||
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-fileshare}
|
||||
POSTGRES_DB: ${POSTGRES_DB:-fileshare}
|
||||
volumes:
|
||||
- pgdata:/var/lib/postgresql/data
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER:-filecodebox}"]
|
||||
test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER:-fileshare}"]
|
||||
interval: 5s
|
||||
timeout: 3s
|
||||
retries: 20
|
||||
@@ -52,7 +52,7 @@ services:
|
||||
start_period: 5s
|
||||
environment:
|
||||
# 需求 ⑧:数据库驱动 sqlite(默认,零依赖)| postgres(需 --profile postgres)
|
||||
# 默认 SQLite:DSN 留空 → 数据库文件落 /app/data/filecodebox.db(serverdata 卷)
|
||||
# 默认 SQLite:DSN 留空 → 数据库文件落 /app/data/fileshare.db(serverdata 卷)
|
||||
# postgres 模式:在 .env 设 FCB_DB_DRIVER=postgres 与 FCB_DB_DSN(模板见 deploy/.env.example)
|
||||
FCB_DB_DRIVER: ${FCB_DB_DRIVER:-sqlite}
|
||||
FCB_DB_DSN: ${FCB_DB_DSN:-}
|
||||
@@ -67,7 +67,7 @@ services:
|
||||
FCB_LOCAL_STORAGE_PATH: /app/data
|
||||
# S3 引擎(MinIO profile)
|
||||
FCB_S3_ENDPOINT_URL: ${FCB_S3_ENDPOINT_URL:-}
|
||||
FCB_S3_BUCKET_NAME: ${FCB_S3_BUCKET_NAME:-filecodebox}
|
||||
FCB_S3_BUCKET_NAME: ${FCB_S3_BUCKET_NAME:-fileshare}
|
||||
FCB_S3_ACCESS_KEY_ID: ${FCB_S3_ACCESS_KEY_ID:-minioadmin}
|
||||
FCB_S3_SECRET_ACCESS_KEY: ${FCB_S3_SECRET_ACCESS_KEY:-minioadmin}
|
||||
FCB_S3_REGION_NAME: ${FCB_S3_REGION_NAME:-us-east-1}
|
||||
@@ -122,7 +122,7 @@ services:
|
||||
entrypoint: >
|
||||
/bin/sh -c "
|
||||
mc alias set local http://minio:9000 ${FCB_S3_ACCESS_KEY_ID:-minioadmin} ${FCB_S3_SECRET_ACCESS_KEY:-minioadmin} &&
|
||||
mc mb --ignore-existing local/${FCB_S3_BUCKET_NAME:-filecodebox} &&
|
||||
mc mb --ignore-existing local/${FCB_S3_BUCKET_NAME:-fileshare} &&
|
||||
echo 'MinIO 桶已就绪'"
|
||||
|
||||
# WebDAV 冒烟服务器(dufs,简单读写 + Basic 认证)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# API 概述
|
||||
|
||||
文件快传 Go 版(v2.5.6)对外提供一套 REST API,覆盖文本/文件分享、分片上传、
|
||||
文件快传 Go 版(26.9)对外提供一套 REST API,覆盖文本/文件分享、分片上传、
|
||||
预签名直传、管理后台与审计日志查询。本文档与 `server/internal/api/` 实际实现逐一对齐,
|
||||
交互式规范见站内 `/openapi`(源文件 `docs/openapi.yaml`)。
|
||||
|
||||
|
||||
+1
-1
@@ -9,7 +9,7 @@
|
||||
|
||||
## 管理员令牌
|
||||
|
||||
- 由 `POST /admin/login` 用管理员密码换取,HS256 JWT,默认有效期 **7 天**(`adminSessionExpire`,1~365 整天,v2.5.6 起由 30 天缩短)。
|
||||
- 由 `POST /admin/login` 用管理员密码换取,HS256 JWT,默认有效期 **7 天**(`adminSessionExpire`,1~365 整天,26.9 起由 30 天缩短)。
|
||||
- 请求头格式:`Authorization: Bearer <token>`。
|
||||
- **改密/重置管理员密码会轮换 `jwt_secret`,所有已签发令牌立即失效**(401)。
|
||||
- 密码存储为 bcrypt(cost 12);历史 `sha256$`/明文格式在登录成功后自动升级重哈希,无需手动迁移。
|
||||
|
||||
@@ -52,7 +52,7 @@ curl -s -X POST http://localhost:8466/presign/upload/init \
|
||||
"code": 200, "msg": "ok",
|
||||
"data": {
|
||||
"upload_id": "6a1e…",
|
||||
"upload_url": "https://minio:9000/filecodebox/share/data/2025/06/01/6a1e…/backup.zip?X-Amz-…",
|
||||
"upload_url": "https://minio:9000/fileshare/share/data/2025/06/01/6a1e…/backup.zip?X-Amz-…",
|
||||
"mode": "direct",
|
||||
"expires_in": 900,
|
||||
"file_path": "share/data/2025/06/01/6a1e…"
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
| 客户端 | `ip` | 可信代理场景解析 XFF 后的真实 IP |
|
||||
| 终端信息 | `user_agent` | 原始 UA |
|
||||
| 设备解析 | `device_os` / `device_browser` / `device_type` | 由 UA 解析(如 Windows/Chrome/desktop) |
|
||||
| 动作 | `action` | `upload`(上传类) / `download`(取件/下载类) / `admin`(管理端敏感操作,v2.5.6 新增) |
|
||||
| 动作 | `action` | `upload`(上传类) / `download`(取件/下载类) / `admin`(管理端敏感操作,26.9 新增) |
|
||||
| 结果 | `result` | `success` / `denied`(拒绝:401/403/423/428)/ `failed`(失败:其余 4xx/5xx 或业务报错) |
|
||||
| 字节数 | `size_bytes` | 文件总大小;`transferred_bytes` 实际传输(**Range 下载只计实际区间字节**;下载由中间件自动统计,上传由各 handler 填充) |
|
||||
| 耗时 | `duration_ms` | 毫秒 |
|
||||
|
||||
@@ -2,14 +2,14 @@
|
||||
|
||||
配置分三层:**默认值 → `FCB_*` 环境变量 → 数据库 settings KV(管理端运行时修改)**。
|
||||
v2 起进程必需的环境变量为空集:数据库默认 **SQLite**(modernc.org/sqlite 纯 Go 驱动,零外部依赖,
|
||||
DSN 缺省落 `./data/filecodebox.db`);`FCB_DB_DRIVER=postgres` 时 `FCB_DB_DSN` 必需(需求 ⑧)。
|
||||
DSN 缺省落 `./data/fileshare.db`);`FCB_DB_DRIVER=postgres` 时 `FCB_DB_DSN` 必需(需求 ⑧)。
|
||||
|
||||
## 环境变量(进程级)
|
||||
|
||||
| 变量 | 必需 | 默认 | 说明 |
|
||||
|---|---|---|---|
|
||||
| `FCB_DB_DRIVER` | ❌ | `sqlite` | 数据库驱动:`sqlite` / `postgres`(需求 ⑧) |
|
||||
| `FCB_DB_DSN` | 视驱动 | `./data/filecodebox.db` | postgres:连接串(**必需**,如 `postgres://user:pass@host:5432/filecodebox?sslmode=disable`);sqlite:数据库文件路径(可空,父目录自动创建) |
|
||||
| `FCB_DB_DSN` | 视驱动 | `./data/fileshare.db` | postgres:连接串(**必需**,如 `postgres://user:pass@host:5432/filecodebox?sslmode=disable`);sqlite:数据库文件路径(可空,父目录自动创建) |
|
||||
| `FCB_REDIS_ADDR` | ❌ | 空 | Redis 地址(如 `redis:6379`),也支持 `redis://[:password@]host:port[/db]` / `rediss://`(TLS)URL 形式;**空则缓存降级为进程内存实现**(缓存故障时自动降级为进程内限流计数) |
|
||||
| `FCB_REDIS_DB` | ❌ | `0` | Redis 逻辑库号 0-15;URL 形式地址显式携带 `/N` 时以 URL 为准 |
|
||||
| `FCB_ADMIN_PASSWORD` | ❌ | 空 | 设置后服务首次启动即自动初始化管理员(≥8 位,不足告警跳过),消除 `/setup` 被抢占窗口;初始化完成后建议移除 |
|
||||
@@ -26,7 +26,7 @@ DSN 缺省落 `./data/filecodebox.db`);`FCB_DB_DRIVER=postgres` 时 `FCB_DB_
|
||||
`FCB_WEBDAV_URL`、`FCB_WEBDAV_USERNAME`、`FCB_WEBDAV_PASSWORD`、`FCB_WEBDAV_ROOT_PATH`。
|
||||
|
||||
部署用编排变量(`deploy/.env.example`):`WEB_PORT`(默认 8466)、
|
||||
`POSTGRES_USER` / `POSTGRES_PASSWORD` / `POSTGRES_DB`(默认 filecodebox,仅 `--profile postgres` 时使用)。
|
||||
`POSTGRES_USER` / `POSTGRES_PASSWORD` / `POSTGRES_DB`(默认 fileshare,仅 `--profile postgres` 时使用)。
|
||||
|
||||
## 配置项(settings KV,默认值对齐参考实现)
|
||||
|
||||
@@ -161,7 +161,7 @@ DSN 缺省落 `./data/filecodebox.db`);`FCB_DB_DRIVER=postgres` 时 `FCB_DB_
|
||||
"openUpload": true
|
||||
},
|
||||
"meta": {
|
||||
"version": "2.5.6",
|
||||
"version": "26.9",
|
||||
"features": { "chunkUpload": false, "guestUpload": true }
|
||||
}
|
||||
}
|
||||
@@ -182,7 +182,7 @@ curl -s http://localhost:8466/api/v1/health
|
||||
"code": 200, "msg": "ok",
|
||||
"data": {
|
||||
"status": "ok",
|
||||
"version": "2.5.6",
|
||||
"version": "26.9",
|
||||
"storage": "local",
|
||||
"time": "2025-06-01T12:00:00+08:00"
|
||||
}
|
||||
|
||||
+4
-4
@@ -27,7 +27,7 @@ server/
|
||||
| 变量 | 必需 | 默认 | 说明 |
|
||||
|---|---|---|---|
|
||||
| `FCB_DB_DRIVER` | ❌ | `sqlite` | 数据库驱动:`sqlite` \| `postgres`(需求 ⑧) |
|
||||
| `FCB_DB_DSN` | 视驱动 | `./data/filecodebox.db` | postgres:连接串(**必需**),如 `postgres://user:pass@host:5432/filecodebox?sslmode=disable`;sqlite:数据库文件路径(可空,自动创建 `data/` 目录) |
|
||||
| `FCB_DB_DSN` | 视驱动 | `./data/fileshare.db` | postgres:连接串(**必需**),如 `postgres://user:pass@host:5432/fileshare?sslmode=disable`;sqlite:数据库文件路径(可空,自动创建 `data/` 目录) |
|
||||
| `FCB_REDIS_ADDR` | ❌ | 空 | 为空时缓存降级为内存实现 |
|
||||
| `FCB_LISTEN` | ❌ | `:8466` | 监听地址 |
|
||||
| `FCB_STORAGE_ENGINE` | ❌ | `local` | `local` \| `s3` \| `webdav` |
|
||||
@@ -36,7 +36,7 @@ server/
|
||||
### 数据库模式(需求 ⑧)
|
||||
|
||||
- **SQLite(默认)**:`FCB_DB_DRIVER=sqlite`(或缺省)。零 DSN 零依赖启动,数据库文件
|
||||
默认 `./data/filecodebox.db`(`FCB_DB_DSN` 可覆盖路径;父目录自动创建)。
|
||||
默认 `./data/fileshare.db`(`FCB_DB_DSN` 可覆盖路径;父目录自动创建)。
|
||||
连接参数:`busy_timeout=10s` + `WAL` 日志模式 + `foreign_keys=1`(通过 DSN pragma 注入)。
|
||||
- **Postgres(可选)**:`FCB_DB_DRIVER=postgres` 且必须提供 `FCB_DB_DSN`,否则启动报错。
|
||||
连接池沿用 v1 参数(32/8、1h 轮换)。
|
||||
@@ -144,13 +144,13 @@ middleware.AuditRecordRequest(c, auditSvc, model.AuditResultSuccess, "")
|
||||
## 本地开发
|
||||
|
||||
```bash
|
||||
# 默认 SQLite 模式:零依赖,数据库落 ./data/filecodebox.db
|
||||
# 默认 SQLite 模式:零依赖,数据库落 ./data/fileshare.db
|
||||
go run ./cmd/server # 启动于 :8466
|
||||
curl localhost:8466/api/v1/health
|
||||
|
||||
# Postgres 模式(可选)
|
||||
export FCB_DB_DRIVER=postgres
|
||||
export FCB_DB_DSN='postgres://postgres:postgres@localhost:5432/filecodebox?sslmode=disable'
|
||||
export FCB_DB_DSN='postgres://postgres:postgres@localhost:5432/fileshare?sslmode=disable'
|
||||
go run ./cmd/server
|
||||
|
||||
# 双方言单测:sqlite 始终执行;postgres 需真实实例(FCB_TEST_PG_DSN 指向测试库)
|
||||
|
||||
+10
-10
@@ -15,19 +15,19 @@ import (
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"filecodebox/internal/api"
|
||||
"filecodebox/internal/audit"
|
||||
"filecodebox/internal/cache"
|
||||
"filecodebox/internal/config"
|
||||
"filecodebox/internal/database"
|
||||
"filecodebox/internal/janitor"
|
||||
"filecodebox/internal/middleware"
|
||||
"filecodebox/internal/settings"
|
||||
"filecodebox/internal/storage"
|
||||
"fileshare/internal/api"
|
||||
"fileshare/internal/audit"
|
||||
"fileshare/internal/cache"
|
||||
"fileshare/internal/config"
|
||||
"fileshare/internal/database"
|
||||
"fileshare/internal/janitor"
|
||||
"fileshare/internal/middleware"
|
||||
"fileshare/internal/settings"
|
||||
"fileshare/internal/storage"
|
||||
)
|
||||
|
||||
// APP_VERSION 版本号,对齐参考仓库 VERSION。
|
||||
const APP_VERSION = "2.5.6"
|
||||
const APP_VERSION = "26.9"
|
||||
|
||||
func main() {
|
||||
log.SetFlags(log.LstdFlags | log.Lshortfile)
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
module filecodebox
|
||||
module fileshare
|
||||
|
||||
go 1.27.1
|
||||
|
||||
|
||||
@@ -12,12 +12,12 @@ import (
|
||||
"github.com/gin-gonic/gin"
|
||||
"gorm.io/gorm"
|
||||
|
||||
"filecodebox/internal/config"
|
||||
"filecodebox/internal/middleware"
|
||||
"filecodebox/internal/model"
|
||||
"filecodebox/internal/response"
|
||||
"filecodebox/internal/settings"
|
||||
"filecodebox/internal/storage"
|
||||
"fileshare/internal/config"
|
||||
"fileshare/internal/middleware"
|
||||
"fileshare/internal/model"
|
||||
"fileshare/internal/response"
|
||||
"fileshare/internal/settings"
|
||||
"fileshare/internal/storage"
|
||||
)
|
||||
|
||||
// minutesDuration 分钟数转 Duration(0 回退 1 分钟,对齐 main.go 语义)。
|
||||
|
||||
@@ -16,10 +16,10 @@ import (
|
||||
"github.com/gin-gonic/gin"
|
||||
"gorm.io/gorm"
|
||||
|
||||
"filecodebox/internal/middleware"
|
||||
"filecodebox/internal/model"
|
||||
"filecodebox/internal/response"
|
||||
"filecodebox/internal/storage"
|
||||
"fileshare/internal/middleware"
|
||||
"fileshare/internal/model"
|
||||
"fileshare/internal/response"
|
||||
"fileshare/internal/storage"
|
||||
)
|
||||
|
||||
// chunkExpireTTL 分片会话保留时长(M5:预留窗口由 24h 缩短为 2h;
|
||||
|
||||
@@ -30,12 +30,12 @@ import (
|
||||
"github.com/gin-gonic/gin"
|
||||
"gorm.io/gorm"
|
||||
|
||||
"filecodebox/internal/audit"
|
||||
"filecodebox/internal/config"
|
||||
"filecodebox/internal/middleware"
|
||||
"filecodebox/internal/model"
|
||||
"filecodebox/internal/response"
|
||||
"filecodebox/internal/storage"
|
||||
"fileshare/internal/audit"
|
||||
"fileshare/internal/config"
|
||||
"fileshare/internal/middleware"
|
||||
"fileshare/internal/model"
|
||||
"fileshare/internal/response"
|
||||
"fileshare/internal/storage"
|
||||
)
|
||||
|
||||
// apiError 统一的业务错误:handler 返回该错误并由 respondError 映射 HTTP 状态。
|
||||
|
||||
@@ -6,8 +6,8 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"filecodebox/internal/config"
|
||||
"filecodebox/internal/storage"
|
||||
"fileshare/internal/config"
|
||||
"fileshare/internal/storage"
|
||||
)
|
||||
|
||||
// newTestConfig 构造测试配置(defaults 基线,无 KV 覆盖;需求 ⑧ 默认 sqlite,无需真实数据库)。
|
||||
|
||||
@@ -15,13 +15,13 @@ import (
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"filecodebox/internal/audit"
|
||||
"filecodebox/internal/cache"
|
||||
"filecodebox/internal/config"
|
||||
"filecodebox/internal/database"
|
||||
"filecodebox/internal/middleware"
|
||||
"filecodebox/internal/settings"
|
||||
"filecodebox/internal/storage"
|
||||
"fileshare/internal/audit"
|
||||
"fileshare/internal/cache"
|
||||
"fileshare/internal/config"
|
||||
"fileshare/internal/database"
|
||||
"fileshare/internal/middleware"
|
||||
"fileshare/internal/settings"
|
||||
"fileshare/internal/storage"
|
||||
)
|
||||
|
||||
// ============ 测试环境装配(真实 sqlite + 内存缓存 + 本地存储)============
|
||||
|
||||
@@ -9,10 +9,10 @@ import (
|
||||
"github.com/gin-gonic/gin"
|
||||
"gorm.io/gorm"
|
||||
|
||||
"filecodebox/internal/middleware"
|
||||
"filecodebox/internal/model"
|
||||
"filecodebox/internal/response"
|
||||
"filecodebox/internal/storage"
|
||||
"fileshare/internal/middleware"
|
||||
"fileshare/internal/model"
|
||||
"fileshare/internal/response"
|
||||
"fileshare/internal/storage"
|
||||
)
|
||||
|
||||
// presignSessionExpires 预签名会话有效期(对齐参考 PRESIGN_SESSION_EXPIRES=900 秒)。
|
||||
|
||||
@@ -6,12 +6,12 @@ import (
|
||||
"github.com/gin-gonic/gin"
|
||||
"gorm.io/gorm"
|
||||
|
||||
"filecodebox/internal/audit"
|
||||
"filecodebox/internal/config"
|
||||
"filecodebox/internal/middleware"
|
||||
"filecodebox/internal/response"
|
||||
"filecodebox/internal/settings"
|
||||
"filecodebox/internal/storage"
|
||||
"fileshare/internal/audit"
|
||||
"fileshare/internal/config"
|
||||
"fileshare/internal/middleware"
|
||||
"fileshare/internal/response"
|
||||
"fileshare/internal/settings"
|
||||
"fileshare/internal/storage"
|
||||
)
|
||||
|
||||
// Deps API 层共享依赖(main.go 装配后注入)。
|
||||
|
||||
@@ -15,8 +15,8 @@ import (
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"filecodebox/internal/model"
|
||||
"filecodebox/internal/settings"
|
||||
"fileshare/internal/model"
|
||||
"fileshare/internal/settings"
|
||||
)
|
||||
|
||||
// postJSON 以 JSON body 调用 POST 端点。
|
||||
|
||||
@@ -7,8 +7,8 @@ import (
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"filecodebox/internal/response"
|
||||
"filecodebox/internal/settings"
|
||||
"fileshare/internal/response"
|
||||
"fileshare/internal/settings"
|
||||
)
|
||||
|
||||
// fileSizeUnits 文件大小单位(对齐参考 FILE_SIZE_UNITS)。
|
||||
|
||||
@@ -12,11 +12,11 @@ import (
|
||||
"github.com/gin-gonic/gin"
|
||||
"gorm.io/gorm"
|
||||
|
||||
"filecodebox/internal/audit"
|
||||
"filecodebox/internal/middleware"
|
||||
"filecodebox/internal/model"
|
||||
"filecodebox/internal/response"
|
||||
"filecodebox/internal/storage"
|
||||
"fileshare/internal/audit"
|
||||
"fileshare/internal/middleware"
|
||||
"fileshare/internal/model"
|
||||
"fileshare/internal/response"
|
||||
"fileshare/internal/storage"
|
||||
)
|
||||
|
||||
// nowRFC3339 当前时间的 RFC3339 表示。
|
||||
|
||||
@@ -8,8 +8,8 @@ import (
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"filecodebox/internal/response"
|
||||
web "filecodebox/web"
|
||||
"fileshare/internal/response"
|
||||
web "fileshare/web"
|
||||
)
|
||||
|
||||
// registerWeb 注册前端静态资源与 SPA 回退(必须最后注册):
|
||||
|
||||
@@ -12,7 +12,7 @@ import (
|
||||
|
||||
"gorm.io/gorm"
|
||||
|
||||
"filecodebox/internal/model"
|
||||
"fileshare/internal/model"
|
||||
)
|
||||
|
||||
// Service 审计日志服务。
|
||||
|
||||
@@ -18,7 +18,7 @@ const (
|
||||
AdminSessionExpireMax = 365 * 24 * 60 * 60 // 最大 365 天
|
||||
|
||||
// DefaultSQLitePath SQLite 模式默认数据库文件路径(相对运行目录,自动创建 data/)。
|
||||
DefaultSQLitePath = "./data/filecodebox.db"
|
||||
DefaultSQLitePath = "./data/fileshare.db"
|
||||
)
|
||||
|
||||
// 数据库驱动常量(需求 ⑧:SQLite 默认、Postgres 可选)。
|
||||
|
||||
@@ -19,8 +19,8 @@ import (
|
||||
"gorm.io/gorm"
|
||||
"gorm.io/gorm/logger"
|
||||
|
||||
"filecodebox/internal/config"
|
||||
"filecodebox/internal/model"
|
||||
"fileshare/internal/config"
|
||||
"fileshare/internal/model"
|
||||
)
|
||||
|
||||
// Options 连接选项(main.go 从 config.Env 装配)。
|
||||
|
||||
@@ -18,8 +18,8 @@ import (
|
||||
|
||||
"gorm.io/gorm"
|
||||
|
||||
"filecodebox/internal/database"
|
||||
"filecodebox/internal/model"
|
||||
"fileshare/internal/database"
|
||||
"fileshare/internal/model"
|
||||
)
|
||||
|
||||
// pgTestDSN 返回 Postgres 测试连接串;未设置 FCB_TEST_PG_DSN 时返回空。
|
||||
|
||||
@@ -12,8 +12,8 @@ import (
|
||||
|
||||
"gorm.io/gorm"
|
||||
|
||||
"filecodebox/internal/model"
|
||||
"filecodebox/internal/storage"
|
||||
"fileshare/internal/model"
|
||||
"fileshare/internal/storage"
|
||||
)
|
||||
|
||||
// chunkSessionMaxAge 未完成分片会话的最大保留时长(预留 TTL 为 2h,
|
||||
|
||||
@@ -7,9 +7,9 @@ import (
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"filecodebox/internal/audit"
|
||||
"filecodebox/internal/model"
|
||||
"filecodebox/internal/response"
|
||||
"fileshare/internal/audit"
|
||||
"fileshare/internal/model"
|
||||
"fileshare/internal/response"
|
||||
)
|
||||
|
||||
// auditHooks 审计钩子:由 API 层在响应前后填充与落库。
|
||||
|
||||
@@ -10,8 +10,8 @@ import (
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"filecodebox/internal/audit"
|
||||
"filecodebox/internal/model"
|
||||
"fileshare/internal/audit"
|
||||
"fileshare/internal/model"
|
||||
)
|
||||
|
||||
type captureSink struct {
|
||||
|
||||
@@ -9,8 +9,8 @@ import (
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"filecodebox/internal/audit"
|
||||
"filecodebox/internal/model"
|
||||
"fileshare/internal/audit"
|
||||
"fileshare/internal/model"
|
||||
)
|
||||
|
||||
// memSink 测试用内存落库实现。
|
||||
|
||||
@@ -8,7 +8,7 @@ import (
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/golang-jwt/jwt/v5"
|
||||
|
||||
"filecodebox/internal/response"
|
||||
"fileshare/internal/response"
|
||||
)
|
||||
|
||||
// jwtClaims 自定义声明:对齐参考实现(payload 含 is_admin 与 exp)。
|
||||
@@ -36,7 +36,7 @@ func SignAdminToken(secret string, expires time.Duration) (string, time.Time, er
|
||||
RegisteredClaims: jwt.RegisteredClaims{
|
||||
ExpiresAt: jwt.NewNumericDate(expiresAt),
|
||||
IssuedAt: jwt.NewNumericDate(time.Now()),
|
||||
Issuer: "filecodebox",
|
||||
Issuer: "fileshare",
|
||||
},
|
||||
}
|
||||
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
|
||||
|
||||
@@ -8,7 +8,7 @@ import (
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"filecodebox/internal/response"
|
||||
"fileshare/internal/response"
|
||||
)
|
||||
|
||||
const testSecret = "unit-test-secret-0123456789abcdef"
|
||||
|
||||
@@ -11,8 +11,8 @@ import (
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"filecodebox/internal/cache"
|
||||
"filecodebox/internal/response"
|
||||
"fileshare/internal/cache"
|
||||
"fileshare/internal/response"
|
||||
)
|
||||
|
||||
// 限流类别(对齐参考 apps/base/utils.py 的 ip_limit)。
|
||||
|
||||
@@ -8,7 +8,7 @@ import (
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"filecodebox/internal/cache"
|
||||
"fileshare/internal/cache"
|
||||
)
|
||||
|
||||
// failingCache 模拟缓存故障(Get/Incr 均返回非 ErrNotFound 错误)。
|
||||
|
||||
@@ -8,7 +8,7 @@ import (
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"filecodebox/internal/cache"
|
||||
"fileshare/internal/cache"
|
||||
)
|
||||
|
||||
func rateLimitRouter(rl *RateLimiter, kind string) *gin.Engine {
|
||||
|
||||
@@ -10,9 +10,9 @@ import (
|
||||
|
||||
"gorm.io/gorm"
|
||||
|
||||
"filecodebox/internal/config"
|
||||
"filecodebox/internal/database"
|
||||
"filecodebox/internal/settings"
|
||||
"fileshare/internal/config"
|
||||
"fileshare/internal/database"
|
||||
"fileshare/internal/settings"
|
||||
)
|
||||
|
||||
// pgTestDSN 返回 Postgres 测试连接串;未设置 FCB_TEST_PG_DSN 时跳过。
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
// 4. schema 同步测试(config schema_test / settings schema_test)
|
||||
package settings
|
||||
|
||||
import "filecodebox/internal/config"
|
||||
import "fileshare/internal/config"
|
||||
|
||||
// —— 键名 re-export(与 config 包保持同一字符串,避免魔法值散落)——
|
||||
const (
|
||||
|
||||
@@ -12,8 +12,8 @@ import (
|
||||
|
||||
"gorm.io/gorm"
|
||||
|
||||
"filecodebox/internal/config"
|
||||
"filecodebox/internal/model"
|
||||
"fileshare/internal/config"
|
||||
"fileshare/internal/model"
|
||||
)
|
||||
|
||||
// settingsKey 数据库中的配置键(对齐参考实现)。
|
||||
|
||||
@@ -30,10 +30,10 @@ type LocalStorage struct {
|
||||
rootReal string
|
||||
}
|
||||
|
||||
// NewLocalStorage 构造本地引擎。root 为空时使用系统临时目录下的 filecodebox_storage。
|
||||
// NewLocalStorage 构造本地引擎。root 为空时使用系统临时目录下的 fileshare_storage。
|
||||
func NewLocalStorage(root string) (*LocalStorage, error) {
|
||||
if strings.TrimSpace(root) == "" {
|
||||
root = filepath.Join(os.TempDir(), "filecodebox_storage")
|
||||
root = filepath.Join(os.TempDir(), "fileshare_storage")
|
||||
}
|
||||
abs, err := filepath.Abs(root)
|
||||
if err != nil {
|
||||
|
||||
@@ -32,7 +32,7 @@ func sha256Hex(b []byte) string {
|
||||
func TestLocalSaveOpenRange(t *testing.T) {
|
||||
st := newTestLocal(t)
|
||||
ctx := context.Background()
|
||||
data := []byte("hello filecodebox 本地引擎 0123456789")
|
||||
data := []byte("hello fileshare 本地引擎 0123456789")
|
||||
|
||||
n, err := st.SaveFile(ctx, bytes.NewReader(data), "2025/08/测试文件.bin")
|
||||
if err != nil {
|
||||
|
||||
Vendored
+1
-1
@@ -1 +1 @@
|
||||
import{d as p,u as v,i as h,I as g,c as w,G as s,b as e,t as n,f as t,A as d,w as k,F as y,O as r,q as m,B as R,o as V}from"./index-DYsKpclu.js";import{_ as x}from"./SiteNav.vue_vue_type_script_setup_true_lang-CwaEJKIZ.js";import{u as A}from"./auth-B7MDTgxJ.js";import"./admin-DEOkRyTC.js";const B={class:"admin-shell"},C={class:"admin-aside"},b={class:"aside-title"},L=["aria-label"],N={class:"admin-main"},q=p({__name:"AdminLayout",setup(S){const{t:a}=v(),u=R(),o=A(),l=h();g(async()=>{o.isAuthed&&!o.checked&&await o.verify()});async function _(){await o.logout(),l.success(a("admin.nav.loggedOut")),u.replace({name:"admin-login"})}return(F,c)=>{const i=r("RouterLink"),f=r("RouterView");return V(),w(y,null,[s(x),e("div",B,[e("aside",C,[e("div",b,n(t(a)("admin.nav.title")),1),e("nav",{class:"aside-menu","aria-label":t(a)("admin.nav.menu")},[s(i,{to:{name:"admin-files"}},{default:d(()=>[m("📁 "+n(t(a)("admin.nav.files")),1)]),_:1}),s(i,{to:{name:"admin-audit"}},{default:d(()=>[m("🛡 "+n(t(a)("admin.nav.audit")),1)]),_:1}),s(i,{to:{name:"admin-settings"}},{default:d(()=>[m("⚙️ "+n(t(a)("admin.nav.settings")),1)]),_:1}),c[0]||(c[0]=e("div",{class:"aside-sep"},null,-1)),e("a",{href:"#",onClick:k(_,["prevent"])},"🚪 "+n(t(a)("admin.nav.logout")),1)],8,L)]),e("div",N,[s(f)])])],64)}}});export{q as default};
|
||||
import{d as p,u as v,i as h,I as g,c as w,G as s,b as e,t as n,f as t,A as d,w as k,F as y,O as r,q as m,B as R,o as V}from"./index-BKnWAKao.js";import{_ as x}from"./SiteNav.vue_vue_type_script_setup_true_lang-D3yLF4uh.js";import{u as A}from"./auth-Cp2GGuZy.js";import"./admin-KnbIpHLF.js";const B={class:"admin-shell"},C={class:"admin-aside"},b={class:"aside-title"},L=["aria-label"],N={class:"admin-main"},q=p({__name:"AdminLayout",setup(S){const{t:a}=v(),u=R(),o=A(),l=h();g(async()=>{o.isAuthed&&!o.checked&&await o.verify()});async function _(){await o.logout(),l.success(a("admin.nav.loggedOut")),u.replace({name:"admin-login"})}return(F,c)=>{const i=r("RouterLink"),f=r("RouterView");return V(),w(y,null,[s(x),e("div",B,[e("aside",C,[e("div",b,n(t(a)("admin.nav.title")),1),e("nav",{class:"aside-menu","aria-label":t(a)("admin.nav.menu")},[s(i,{to:{name:"admin-files"}},{default:d(()=>[m("📁 "+n(t(a)("admin.nav.files")),1)]),_:1}),s(i,{to:{name:"admin-audit"}},{default:d(()=>[m("🛡 "+n(t(a)("admin.nav.audit")),1)]),_:1}),s(i,{to:{name:"admin-settings"}},{default:d(()=>[m("⚙️ "+n(t(a)("admin.nav.settings")),1)]),_:1}),c[0]||(c[0]=e("div",{class:"aside-sep"},null,-1)),e("a",{href:"#",onClick:k(_,["prevent"])},"🚪 "+n(t(a)("admin.nav.logout")),1)],8,L)]),e("div",N,[s(f)])])],64)}}});export{q as default};
|
||||
Vendored
+1
-1
File diff suppressed because one or more lines are too long
+1
-1
File diff suppressed because one or more lines are too long
Vendored
+1
-1
File diff suppressed because one or more lines are too long
+1
-1
File diff suppressed because one or more lines are too long
Vendored
+1
-1
@@ -1 +1 @@
|
||||
import{d as w,u as b,a as y,z as x,A as k,b as e,f as t,t as a,w as V,C as B,D as C,c as m,g as _,q as N,j as r,N as S,B as q,o as d,H as L,_ as P}from"./index-DYsKpclu.js";import{P as A}from"./PageShell-D87JkPkG.js";import{u as D}from"./auth-B7MDTgxJ.js";import"./SiteNav.vue_vue_type_script_setup_true_lang-CwaEJKIZ.js";import"./admin-DEOkRyTC.js";const E={class:"card",style:{"max-width":"380px",margin:"8vh auto 0"}},I={class:"login-head"},M=["src"],R={class:"card-title"},T={class:"card-sub"},U={class:"field"},j={for:"admin-password"},z=["placeholder"],H={key:0,class:"hint",style:{color:"var(--c-danger)","margin-bottom":"12px"}},F=["disabled"],G={key:0,class:"spin","aria-hidden":"true"},J={class:"hint",style:{"margin-top":"16px"}},K=w({__name:"LoginView",setup(O){const{t:s}=b(),c=S(),g=q(),h=D(),u=y(),i=r(""),l=r(!1),n=r("");async function f(){if(!i.value){n.value=s("admin.login.required");return}l.value=!0,n.value="";try{await h.login(i.value);const o=typeof c.query.redirect=="string"?c.query.redirect:"/admin/files";g.replace(o)}catch(o){n.value=o instanceof L?o.code===401?s("admin.login.wrongPassword"):o.msg:s("admin.login.failed"),i.value=""}finally{l.value=!1}}return(o,p)=>(d(),x(A,null,{default:k(()=>[e("section",E,[e("div",I,[e("img",{src:t(u).displayLogoUrl,alt:"Logo",class:"login-logo"},null,8,M),e("h1",R,a(t(s)("admin.login.title")),1),e("p",T,a(t(s)("admin.login.subtitle",{name:t(u).displayName})),1)]),e("form",{onSubmit:V(f,["prevent"])},[e("div",U,[e("label",j,a(t(s)("admin.login.password")),1),B(e("input",{id:"admin-password","onUpdate:modelValue":p[0]||(p[0]=v=>i.value=v),class:"input",type:"password",placeholder:t(s)("admin.login.passwordPlaceholder"),autocomplete:"current-password",autofocus:""},null,8,z),[[C,i.value]])]),n.value?(d(),m("p",H,a(n.value),1)):_("",!0),e("button",{class:"btn btn-block",type:"submit",disabled:l.value},[l.value?(d(),m("span",G)):_("",!0),N(" "+a(t(s)("admin.login.submit")),1)],8,F)],32),e("p",J,a(t(s)("admin.login.hint")),1)])]),_:1}))}}),$=P(K,[["__scopeId","data-v-26e7f2a4"]]);export{$ as default};
|
||||
import{d as w,u as b,a as y,z as x,A as k,b as e,f as t,t as a,w as V,C as B,D as C,c as m,g as _,q as N,j as r,N as S,B as q,o as d,H as L,_ as P}from"./index-BKnWAKao.js";import{P as A}from"./PageShell-CBo29Oot.js";import{u as D}from"./auth-Cp2GGuZy.js";import"./SiteNav.vue_vue_type_script_setup_true_lang-D3yLF4uh.js";import"./admin-KnbIpHLF.js";const E={class:"card",style:{"max-width":"380px",margin:"8vh auto 0"}},I={class:"login-head"},M=["src"],R={class:"card-title"},T={class:"card-sub"},U={class:"field"},j={for:"admin-password"},z=["placeholder"],H={key:0,class:"hint",style:{color:"var(--c-danger)","margin-bottom":"12px"}},F=["disabled"],G={key:0,class:"spin","aria-hidden":"true"},J={class:"hint",style:{"margin-top":"16px"}},K=w({__name:"LoginView",setup(O){const{t:s}=b(),c=S(),g=q(),h=D(),u=y(),i=r(""),l=r(!1),n=r("");async function f(){if(!i.value){n.value=s("admin.login.required");return}l.value=!0,n.value="";try{await h.login(i.value);const o=typeof c.query.redirect=="string"?c.query.redirect:"/admin/files";g.replace(o)}catch(o){n.value=o instanceof L?o.code===401?s("admin.login.wrongPassword"):o.msg:s("admin.login.failed"),i.value=""}finally{l.value=!1}}return(o,p)=>(d(),x(A,null,{default:k(()=>[e("section",E,[e("div",I,[e("img",{src:t(u).displayLogoUrl,alt:"Logo",class:"login-logo"},null,8,M),e("h1",R,a(t(s)("admin.login.title")),1),e("p",T,a(t(s)("admin.login.subtitle",{name:t(u).displayName})),1)]),e("form",{onSubmit:V(f,["prevent"])},[e("div",U,[e("label",j,a(t(s)("admin.login.password")),1),B(e("input",{id:"admin-password","onUpdate:modelValue":p[0]||(p[0]=v=>i.value=v),class:"input",type:"password",placeholder:t(s)("admin.login.passwordPlaceholder"),autocomplete:"current-password",autofocus:""},null,8,z),[[C,i.value]])]),n.value?(d(),m("p",H,a(n.value),1)):_("",!0),e("button",{class:"btn btn-block",type:"submit",disabled:l.value},[l.value?(d(),m("span",G)):_("",!0),N(" "+a(t(s)("admin.login.submit")),1)],8,F)],32),e("p",J,a(t(s)("admin.login.hint")),1)])]),_:1}))}}),$=P(K,[["__scopeId","data-v-26e7f2a4"]]);export{$ as default};
|
||||
Vendored
+1
-1
@@ -1 +1 @@
|
||||
import{d as c,u as i,z as d,A as a,b as t,t as e,f as s,G as l,q as p,O as u,o as _}from"./index-DYsKpclu.js";import{P as m}from"./PageShell-D87JkPkG.js";import"./SiteNav.vue_vue_type_script_setup_true_lang-CwaEJKIZ.js";const f={class:"card empty",style:{"max-width":"480px",margin:"10vh auto 0"}},h={style:{"font-weight":"600",color:"var(--c-text)"}},x={class:"hint"},F=c({__name:"NotFoundView",setup(y){const{t:o}=i();return(g,n)=>{const r=u("RouterLink");return _(),d(m,null,{default:a(()=>[t("div",f,[n[0]||(n[0]=t("div",{class:"empty-icon"},"🧭",-1)),t("p",h,e(s(o)("notFound.title")),1),t("p",x,e(s(o)("notFound.desc")),1),l(r,{class:"btn",to:"/",style:{"margin-top":"10px"}},{default:a(()=>[p(e(s(o)("notFound.back")),1)]),_:1})])]),_:1})}}});export{F as default};
|
||||
import{d as c,u as i,z as d,A as a,b as t,t as e,f as s,G as l,q as p,O as u,o as _}from"./index-BKnWAKao.js";import{P as m}from"./PageShell-CBo29Oot.js";import"./SiteNav.vue_vue_type_script_setup_true_lang-D3yLF4uh.js";const f={class:"card empty",style:{"max-width":"480px",margin:"10vh auto 0"}},h={style:{"font-weight":"600",color:"var(--c-text)"}},x={class:"hint"},F=c({__name:"NotFoundView",setup(y){const{t:o}=i();return(g,n)=>{const r=u("RouterLink");return _(),d(m,null,{default:a(()=>[t("div",f,[n[0]||(n[0]=t("div",{class:"empty-icon"},"🧭",-1)),t("p",h,e(s(o)("notFound.title")),1),t("p",x,e(s(o)("notFound.desc")),1),l(r,{class:"btn",to:"/",style:{"margin-top":"10px"}},{default:a(()=>[p(e(s(o)("notFound.back")),1)]),_:1})])]),_:1})}}});export{F as default};
|
||||
Vendored
+1
-1
File diff suppressed because one or more lines are too long
Vendored
+1
-1
@@ -1 +1 @@
|
||||
import{d as h,u as g,a as k,c as n,G as i,b as t,Q as y,e as v,f as e,t as a,g as c,q as r,A as d,F as x,h as B,O as C,o as l,_ as b}from"./index-DYsKpclu.js";import{_ as w}from"./SiteNav.vue_vue_type_script_setup_true_lang-CwaEJKIZ.js";const N={class:"site-footer"},S={class:"footer-left"},F={key:0,class:"footer-text"},P={key:1,class:"footer-beian"},T={key:2},V=["aria-label"],$=h({__name:"PageShell",setup(D){const{t:s}=g(),o=k(),m=new Date().getFullYear(),u=B(()=>!!(o.footerText.trim()||o.footerBeian.trim()));return(p,_)=>{const f=C("RouterLink");return l(),n(x,null,[i(w),t("main",{class:v(["page",{"page-wide":p.$route.meta.wide}])},[y(p.$slots,"default",{},void 0,!0)],2),t("footer",N,[t("div",S,[e(o).footerText.trim()?(l(),n("span",F,a(e(o).footerText),1)):c("",!0),e(o).footerBeian.trim()?(l(),n("span",P,a(e(o).footerBeian),1)):c("",!0),u.value?c("",!0):(l(),n("span",T,a(e(s)("footer.copyright",{year:e(m),name:e(o).displayName})),1))]),_[0]||(_[0]=t("span",{class:"footer-powered"},[r(" Powered by "),t("a",{href:"https://skymirror.top",target:"_blank",rel:"noopener noreferrer"},"SKYMirror"),r(" 26.9 ")],-1)),t("nav",{"aria-label":e(s)("footer.linkNav")},[i(f,{to:"/docs"},{default:d(()=>[r(a(e(s)("footer.docs")),1)]),_:1}),i(f,{to:"/openapi"},{default:d(()=>[r(a(e(s)("footer.openapi")),1)]),_:1}),i(f,{to:"/admin/files"},{default:d(()=>[r(a(e(s)("footer.admin")),1)]),_:1})],8,V)])],64)}}}),R=b($,[["__scopeId","data-v-80685d6f"]]);export{R as P};
|
||||
import{d as h,u as g,a as k,c as n,G as i,b as t,Q as y,e as v,f as e,t as a,g as c,q as r,A as d,F as x,h as B,O as C,o as l,_ as b}from"./index-BKnWAKao.js";import{_ as w}from"./SiteNav.vue_vue_type_script_setup_true_lang-D3yLF4uh.js";const N={class:"site-footer"},S={class:"footer-left"},F={key:0,class:"footer-text"},P={key:1,class:"footer-beian"},T={key:2},V=["aria-label"],$=h({__name:"PageShell",setup(D){const{t:s}=g(),o=k(),m=new Date().getFullYear(),u=B(()=>!!(o.footerText.trim()||o.footerBeian.trim()));return(p,_)=>{const f=C("RouterLink");return l(),n(x,null,[i(w),t("main",{class:v(["page",{"page-wide":p.$route.meta.wide}])},[y(p.$slots,"default",{},void 0,!0)],2),t("footer",N,[t("div",S,[e(o).footerText.trim()?(l(),n("span",F,a(e(o).footerText),1)):c("",!0),e(o).footerBeian.trim()?(l(),n("span",P,a(e(o).footerBeian),1)):c("",!0),u.value?c("",!0):(l(),n("span",T,a(e(s)("footer.copyright",{year:e(m),name:e(o).displayName})),1))]),_[0]||(_[0]=t("span",{class:"footer-powered"},[r(" Powered by "),t("a",{href:"https://skymirror.top",target:"_blank",rel:"noopener noreferrer"},"SKYMirror"),r(" 26.9 ")],-1)),t("nav",{"aria-label":e(s)("footer.linkNav")},[i(f,{to:"/docs"},{default:d(()=>[r(a(e(s)("footer.docs")),1)]),_:1}),i(f,{to:"/openapi"},{default:d(()=>[r(a(e(s)("footer.openapi")),1)]),_:1}),i(f,{to:"/admin/files"},{default:d(()=>[r(a(e(s)("footer.admin")),1)]),_:1})],8,V)])],64)}}}),R=b($,[["__scopeId","data-v-80685d6f"]]);export{R as P};
|
||||
+1
-1
@@ -1 +1 @@
|
||||
import{d as b,u as p,c as r,b as o,t as i,f as c,h,o as f}from"./index-DYsKpclu.js";const v={class:"pager"},x={class:"pager-info"},k=["disabled"],M=["disabled"],y=b({__name:"Pager",props:{page:{},size:{},total:{}},emits:["change"],setup(t,{emit:m}){const a=t,d=m,{t:n}=p(),s=h(()=>Math.max(1,Math.ceil(a.total/a.size)));function g(l){const e=Math.min(Math.max(1,l),s.value);e!==a.page&&d("change",e,a.size)}return(l,e)=>(f(),r("div",v,[o("span",x,i(c(n)("common.pagerInfo",{total:t.total,page:t.page,pages:s.value})),1),o("button",{class:"btn btn-ghost btn-sm",type:"button",disabled:t.page<=1,onClick:e[0]||(e[0]=u=>g(t.page-1))},i(c(n)("common.previousPage")),9,k),o("button",{class:"btn btn-ghost btn-sm",type:"button",disabled:t.page>=s.value,onClick:e[1]||(e[1]=u=>g(t.page+1))},i(c(n)("common.nextPage")),9,M)]))}});export{y as _};
|
||||
import{d as b,u as p,c as r,b as o,t as i,f as c,h,o as f}from"./index-BKnWAKao.js";const v={class:"pager"},x={class:"pager-info"},k=["disabled"],M=["disabled"],y=b({__name:"Pager",props:{page:{},size:{},total:{}},emits:["change"],setup(t,{emit:m}){const a=t,d=m,{t:n}=p(),s=h(()=>Math.max(1,Math.ceil(a.total/a.size)));function g(l){const e=Math.min(Math.max(1,l),s.value);e!==a.page&&d("change",e,a.size)}return(l,e)=>(f(),r("div",v,[o("span",x,i(c(n)("common.pagerInfo",{total:t.total,page:t.page,pages:s.value})),1),o("button",{class:"btn btn-ghost btn-sm",type:"button",disabled:t.page<=1,onClick:e[0]||(e[0]=u=>g(t.page-1))},i(c(n)("common.previousPage")),9,k),o("button",{class:"btn btn-ghost btn-sm",type:"button",disabled:t.page>=s.value,onClick:e[1]||(e[1]=u=>g(t.page+1))},i(c(n)("common.nextPage")),9,M)]))}});export{y as _};
|
||||
Vendored
+1
-1
@@ -1 +1 @@
|
||||
import{d as N,u as U,i as q,I,J as b,z as L,A as R,H as C,h as T,j as p,b as t,c as u,q as z,t as s,f as n,w as E,C as H,D as $,F as y,s as _,g as w,K as j,L as J,n as K,M as B,k as W,N as G,B as O,o as l}from"./index-DYsKpclu.js";import{P as Q}from"./PageShell-D87JkPkG.js";import{g as X,p as Y,b as Z}from"./share-CqDDLJWI.js";import"./SiteNav.vue_vue_type_script_setup_true_lang-CwaEJKIZ.js";const ee={class:"card",style:{"max-width":"640px",margin:"12px auto 0"}},te={key:0,class:"loading-block"},ae={class:"empty"},oe={style:{"font-weight":"600",color:"var(--c-text)"}},ne={class:"hint"},se=["placeholder"],ie={class:"btn",type:"submit"},le={style:{display:"flex","align-items":"center",gap:"10px","flex-wrap":"wrap","margin-bottom":"4px"}},ue={class:"badge"},re={style:{"font-size":"16px","word-break":"break-all"}},ce={key:0,class:"hint",style:{margin:"0"}},pe={class:"hint",style:{"margin-bottom":"18px"}},de={key:0,class:"loading-block"},me={class:"text-view"},ve={style:{display:"flex",gap:"10px","margin-top":"14px","flex-wrap":"wrap"}},ye={class:"file-summary"},ke={style:{"font-weight":"600","word-break":"break-all"}},fe={class:"hint",style:{margin:"0"}},ge={key:0,style:{margin:"16px 0 6px"}},he={class:"progress"},xe={class:"hint"},_e=["disabled"],Be=N({__name:"PickupView",setup(we){const{t:e}=U(),D=G(),F=O(),k=q(),d=T(()=>String(D.params.code??"").trim().split(/\s+/)[0]),r=p("loading"),m=p(""),o=p(null),v=p(""),f=p(!1),c=p(null);async function g(){if(!d.value){r.value="error",m.value=e("pickup.emptyCode");return}r.value="loading",m.value="",o.value=null,v.value="";try{const a=await X(d.value);if(o.value=a,r.value="ready",a.isText){f.value=!0;try{v.value=await Y(d.value)}finally{f.value=!1}}}catch(a){r.value="error",m.value=a instanceof C?a.code===404?e("pickup.notFound"):a.code===423?e("home.rateLimited"):a.code===428?e("home.notInitialized"):a.msg:e("pickup.failedDefault")}}I(g),b(d,()=>{g()}),b(()=>e("pickup.emptyCode"),()=>{r.value==="error"&&m.value&&g()});async function A(){if(o.value){c.value=0;try{const{blob:a,filename:i}=await Z(d.value,x=>c.value=x);B(a,i||o.value.name||"download"),k.success(e("pickup.downloaded"))}catch(a){k.error(a instanceof C?a.msg:e("pickup.downloadFailed"))}finally{c.value=null}}}async function M(){await W(v.value)?k.success(e("pickup.copied")):k.error(e("common.copyFailed"))}function P(){if(!o.value)return;const a=new Blob([v.value],{type:"text/plain;charset=utf-8"}),i=o.value.name?.includes(".")?o.value.name:`${o.value.name||"text"}.txt`;B(a,i)}const h=p("");function S(){const a=h.value.trim();a&&F.push({name:"pickup",params:{code:a}})}const V=T(()=>{const a=o.value;return a?a.remainingDownloads===null||a.remainingDownloads===void 0||a.remainingDownloads<0?e("pickup.remainingUnlimited"):e("pickup.remainingCount",{n:a.remainingDownloads}):""});return(a,i)=>(l(),L(Q,null,{default:R(()=>[t("section",ee,[r.value==="loading"?(l(),u("div",te,[i[1]||(i[1]=t("span",{class:"spin","aria-hidden":"true"},null,-1)),z(" "+s(n(e)("pickup.querying",{code:d.value})),1)])):r.value==="error"?(l(),u(y,{key:1},[t("div",ae,[i[2]||(i[2]=t("div",{class:"empty-icon"},"📮",-1)),t("p",oe,s(m.value||n(e)("pickup.failed")),1),t("p",ne,s(n(e)("pickup.confirmHint")),1)]),t("form",{class:"quick-pickup",style:{"margin-top":"6px","max-width":"none"},onSubmit:E(S,["prevent"])},[H(t("input",{"onUpdate:modelValue":i[0]||(i[0]=x=>h.value=x),class:"input input-mono",placeholder:n(e)("pickup.retryPlaceholder"),maxlength:"32"},null,8,se),[[$,h.value]]),t("button",ie,s(n(e)("pickup.retryButton")),1)],32)],64)):o.value?(l(),u(y,{key:2},[t("div",le,[t("span",ue,s(o.value.isText?n(e)("common.text"):n(e)("common.file")),1),t("strong",re,s(o.value.name),1),o.value.isText?w("",!0):(l(),u("span",ce,s(n(_)(o.value.size)),1))]),t("p",pe,s(V.value)+" · "+s(n(e)("pickup.expireAt",{time:o.value.expiredAt?n(j)(o.value.expiredAt):n(e)("time.permanent")}))+" · "+s(n(J)(o.value.expiredAt)),1),o.value.isText?(l(),u(y,{key:0},[f.value?(l(),u("div",de,[i[3]||(i[3]=t("span",{class:"spin","aria-hidden":"true"},null,-1)),z(" "+s(n(e)("pickup.loadingText")),1)])):(l(),u(y,{key:1},[t("pre",me,s(v.value),1),t("div",ve,[t("button",{class:"btn",type:"button",onClick:M},s(n(e)("pickup.copyContent")),1),t("button",{class:"btn btn-ghost",type:"button",onClick:P},s(n(e)("pickup.downloadTxt")),1)])],64))],64)):(l(),u(y,{key:1},[t("div",ye,[i[4]||(i[4]=t("span",{style:{"font-size":"30px"},"aria-hidden":"true"},"📄",-1)),t("div",null,[t("div",ke,s(o.value.name),1),t("div",fe,s(n(e)("pickup.sizeUsed",{size:n(_)(o.value.size),n:o.value.usedCount})),1)])]),c.value!==null?(l(),u("div",ge,[t("div",he,[t("i",{style:K({width:`${c.value}%`})},null,4)]),t("p",xe,s(n(e)("pickup.downloading",{percent:c.value})),1)])):w("",!0),t("button",{class:"btn btn-block",type:"button",disabled:c.value!==null,onClick:A}," ⬇ "+s(n(e)("pickup.downloadFile",{size:n(_)(o.value.size)})),9,_e)],64))],64)):w("",!0)])]),_:1}))}});export{Be as default};
|
||||
import{d as N,u as U,i as q,I,J as b,z as L,A as R,H as C,h as T,j as p,b as t,c as u,q as z,t as s,f as n,w as E,C as H,D as $,F as y,s as _,g as w,K as j,L as J,n as K,M as B,k as W,N as G,B as O,o as l}from"./index-BKnWAKao.js";import{P as Q}from"./PageShell-CBo29Oot.js";import{g as X,p as Y,b as Z}from"./share-B-zR67vw.js";import"./SiteNav.vue_vue_type_script_setup_true_lang-D3yLF4uh.js";const ee={class:"card",style:{"max-width":"640px",margin:"12px auto 0"}},te={key:0,class:"loading-block"},ae={class:"empty"},oe={style:{"font-weight":"600",color:"var(--c-text)"}},ne={class:"hint"},se=["placeholder"],ie={class:"btn",type:"submit"},le={style:{display:"flex","align-items":"center",gap:"10px","flex-wrap":"wrap","margin-bottom":"4px"}},ue={class:"badge"},re={style:{"font-size":"16px","word-break":"break-all"}},ce={key:0,class:"hint",style:{margin:"0"}},pe={class:"hint",style:{"margin-bottom":"18px"}},de={key:0,class:"loading-block"},me={class:"text-view"},ve={style:{display:"flex",gap:"10px","margin-top":"14px","flex-wrap":"wrap"}},ye={class:"file-summary"},ke={style:{"font-weight":"600","word-break":"break-all"}},fe={class:"hint",style:{margin:"0"}},ge={key:0,style:{margin:"16px 0 6px"}},he={class:"progress"},xe={class:"hint"},_e=["disabled"],Be=N({__name:"PickupView",setup(we){const{t:e}=U(),D=G(),F=O(),k=q(),d=T(()=>String(D.params.code??"").trim().split(/\s+/)[0]),r=p("loading"),m=p(""),o=p(null),v=p(""),f=p(!1),c=p(null);async function g(){if(!d.value){r.value="error",m.value=e("pickup.emptyCode");return}r.value="loading",m.value="",o.value=null,v.value="";try{const a=await X(d.value);if(o.value=a,r.value="ready",a.isText){f.value=!0;try{v.value=await Y(d.value)}finally{f.value=!1}}}catch(a){r.value="error",m.value=a instanceof C?a.code===404?e("pickup.notFound"):a.code===423?e("home.rateLimited"):a.code===428?e("home.notInitialized"):a.msg:e("pickup.failedDefault")}}I(g),b(d,()=>{g()}),b(()=>e("pickup.emptyCode"),()=>{r.value==="error"&&m.value&&g()});async function A(){if(o.value){c.value=0;try{const{blob:a,filename:i}=await Z(d.value,x=>c.value=x);B(a,i||o.value.name||"download"),k.success(e("pickup.downloaded"))}catch(a){k.error(a instanceof C?a.msg:e("pickup.downloadFailed"))}finally{c.value=null}}}async function M(){await W(v.value)?k.success(e("pickup.copied")):k.error(e("common.copyFailed"))}function P(){if(!o.value)return;const a=new Blob([v.value],{type:"text/plain;charset=utf-8"}),i=o.value.name?.includes(".")?o.value.name:`${o.value.name||"text"}.txt`;B(a,i)}const h=p("");function S(){const a=h.value.trim();a&&F.push({name:"pickup",params:{code:a}})}const V=T(()=>{const a=o.value;return a?a.remainingDownloads===null||a.remainingDownloads===void 0||a.remainingDownloads<0?e("pickup.remainingUnlimited"):e("pickup.remainingCount",{n:a.remainingDownloads}):""});return(a,i)=>(l(),L(Q,null,{default:R(()=>[t("section",ee,[r.value==="loading"?(l(),u("div",te,[i[1]||(i[1]=t("span",{class:"spin","aria-hidden":"true"},null,-1)),z(" "+s(n(e)("pickup.querying",{code:d.value})),1)])):r.value==="error"?(l(),u(y,{key:1},[t("div",ae,[i[2]||(i[2]=t("div",{class:"empty-icon"},"📮",-1)),t("p",oe,s(m.value||n(e)("pickup.failed")),1),t("p",ne,s(n(e)("pickup.confirmHint")),1)]),t("form",{class:"quick-pickup",style:{"margin-top":"6px","max-width":"none"},onSubmit:E(S,["prevent"])},[H(t("input",{"onUpdate:modelValue":i[0]||(i[0]=x=>h.value=x),class:"input input-mono",placeholder:n(e)("pickup.retryPlaceholder"),maxlength:"32"},null,8,se),[[$,h.value]]),t("button",ie,s(n(e)("pickup.retryButton")),1)],32)],64)):o.value?(l(),u(y,{key:2},[t("div",le,[t("span",ue,s(o.value.isText?n(e)("common.text"):n(e)("common.file")),1),t("strong",re,s(o.value.name),1),o.value.isText?w("",!0):(l(),u("span",ce,s(n(_)(o.value.size)),1))]),t("p",pe,s(V.value)+" · "+s(n(e)("pickup.expireAt",{time:o.value.expiredAt?n(j)(o.value.expiredAt):n(e)("time.permanent")}))+" · "+s(n(J)(o.value.expiredAt)),1),o.value.isText?(l(),u(y,{key:0},[f.value?(l(),u("div",de,[i[3]||(i[3]=t("span",{class:"spin","aria-hidden":"true"},null,-1)),z(" "+s(n(e)("pickup.loadingText")),1)])):(l(),u(y,{key:1},[t("pre",me,s(v.value),1),t("div",ve,[t("button",{class:"btn",type:"button",onClick:M},s(n(e)("pickup.copyContent")),1),t("button",{class:"btn btn-ghost",type:"button",onClick:P},s(n(e)("pickup.downloadTxt")),1)])],64))],64)):(l(),u(y,{key:1},[t("div",ye,[i[4]||(i[4]=t("span",{style:{"font-size":"30px"},"aria-hidden":"true"},"📄",-1)),t("div",null,[t("div",ke,s(o.value.name),1),t("div",fe,s(n(e)("pickup.sizeUsed",{size:n(_)(o.value.size),n:o.value.usedCount})),1)])]),c.value!==null?(l(),u("div",ge,[t("div",he,[t("i",{style:K({width:`${c.value}%`})},null,4)]),t("p",xe,s(n(e)("pickup.downloading",{percent:c.value})),1)])):w("",!0),t("button",{class:"btn btn-block",type:"button",disabled:c.value!==null,onClick:A}," ⬇ "+s(n(e)("pickup.downloadFile",{size:n(_)(o.value.size)})),9,_e)],64))],64)):w("",!0)])]),_:1}))}});export{Be as default};
|
||||
Vendored
+1
-1
@@ -1,4 +1,4 @@
|
||||
import{a0 as ge,h as F,a1 as Ze,a2 as Me,a3 as Xe,a4 as Qe,a5 as Pe,a6 as et,o as w,a7 as ze,z as ce,c as y,F as G,b as e,a8 as We,a9 as tt,e as st,aa as nt,G as Fe,A as it,ab as ot,ac as at,j as V,ad as Ae,ae as K,J as lt,I as Ye,af as rt,P as dt,ag as ct,ah as ut,d as ve,ai as _t,aj as mt,ak as Ue,al as b,n as Re,am as Ge,an as ft,ao as ht,ap as pt,aq as I,ar as Ee,as as qe,at as Q,au as gt,u as vt,i as bt,a as wt,t as l,f as o,q as M,w as He,C as f,D as v,g as L,Z as _e,s as Oe,R as ke,S as p,H as re,B as yt,_ as xt}from"./index-DYsKpclu.js";import{f as kt,g as St,h as De,i as Ct}from"./admin-DEOkRyTC.js";import{u as Bt}from"./auth-B7MDTgxJ.js";function Vt(s={},t={defaultBordered:!0}){const d=ge(Me,null);return{inlineThemeDisabled:d?.inlineThemeDisabled,mergedRtlRef:d?.mergedRtlRef,mergedComponentPropsRef:d?.mergedComponentPropsRef,mergedBreakpointsRef:d?.mergedBreakpointsRef,mergedBorderedRef:F(()=>{const{bordered:u}=s;return u!==void 0?u:d?.mergedBorderedRef.value??t.defaultBordered??!0}),mergedClsPrefixRef:d?d.mergedClsPrefixRef:Ze("n"),namespaceRef:F(()=>d?.mergedNamespaceRef.value)}}function $t(s,t,d){if(!t)return;const u=Xe(),_=ge(Me,null),h=()=>{const x=d.value;t.mount({id:x===void 0?s:x+s,head:!0,anchorMetaName:Pe,props:{bPrefix:x?`.${x}-`:void 0},ssr:u,parent:_?.styleMountTarget}),_?.preflightStyleDisabled||et.mount({id:"n-global",head:!0,anchorMetaName:Pe,ssr:u,parent:_?.styleMountTarget})};u?h():Qe(h)}function z(s,t=1){let d=Fe,u=!1;return typeof s=="function"&&(u=!0,w(),d=ce,s=s()),ze(s)?u?ce(Ie(s)):Ie(s):Array.isArray(s)?u?y(G,null,s.map(_=>z(()=>_)),-2):e(G,null,s.slice()):s==null||typeof s=="boolean"?d(We):d(tt,null,String(s),t)}function Ie(s){return s.el===null&&s.patchFlag!==-1||s.memo?s:nt(s)}const Tt=s=>typeof s=="function"||Object.prototype.toString.call(s)==="[object Object]"&&!ze(s)?s:{default:it(()=>[z(()=>s)])},C=s=>st(s)||null;function j(s){return typeof s=="string"?s.endsWith("px")?Number(s.slice(0,s.length-2)):Number(s):s}function Se(s){if(s!=null)return typeof s=="number"?`${s}px`:s.endsWith("px")?s:`${s}px`}function Ut(s,t,d,u){d||ot("useThemeClass","cssVarsRef is not passed");const _=ge(Me,null),h=_?.mergedThemeHashRef,x=_?.styleMountTarget,B=V(""),a=Xe();let k;const $=`__${s}`,R=()=>{let m=$;const T=t?t.value:void 0,N=h?.value;N&&(m+=`-${N}`),T&&(m+=`-${T}`);const{themeOverrides:E,builtinThemeOverrides:q}=u;E&&(m+=`-${Ae(JSON.stringify(E))}`),q&&(m+=`-${Ae(JSON.stringify(q))}`),B.value=m,k=()=>{const te=d.value;let se="";for(const ne in te)se+=`${ne}: ${te[ne]};`;K(`.${m}`,se).mount({id:m,ssr:a,parent:x}),k=void 0}};return at(()=>{R()}),{themeClass:B,onRender:()=>{k?.()}}}function Rt(s,t){return lt(s,d=>{d!==void 0&&(t.value=d)}),F(()=>s.value===void 0?t.value:s.value)}function Mt(){const s=V(!1);return Ye(()=>{s.value=!0}),rt(s)}function he(s,...t){if(Array.isArray(s))s.forEach(d=>he(d,...t));else return s(...t)}function Ne(s){return s.some(t=>ze(t)?!(t.type===We||t.type===G&&!Ne(t.children)):!0)?s:null}function ee(s,t){return t(s&&Ne(s())||null)}function Ce(s){return!(s&&Ne(s()))}const Le=ct("n-form-item");function zt(s,{defaultSize:t="medium",mergedSize:d,mergedDisabled:u}={}){const _=ge(Le,null);ut(Le,null);const h=F(d?()=>d(_):()=>{const{size:a}=s;if(a)return a;if(_){const{mergedSize:k}=_;if(k.value!==void 0)return k.value}return t}),x=F(u?()=>u(_):()=>{const{disabled:a}=s;return a!==void 0?a:_?_.disabled.value:!1}),B=F(()=>{const{status:a}=s;return a||_?.mergedValidationStatus.value});return dt(()=>{_&&_.restoreValidation()}),{mergedSizeRef:h,mergedDisabledRef:x,mergedStatusRef:B,nTriggerFormBlur(){_&&_.handleContentBlur()},nTriggerFormChange(){_&&_.handleContentChange()},nTriggerFormFocus(){_&&_.handleContentFocus()},nTriggerFormInput(){_&&_.handleContentInput()}}}var Je=ve({name:"BaseIconSwitchTransition",setup(s,{slots:t}){const d=Mt();return()=>(w(),ce(_t,{name:"icon-switch-transition",appear:d.value},Tt(t),1032,["appear"]))}});const{cubicBezierEaseInOut:Ft}=mt;function pe({originalTransform:s="",left:t=0,top:d=0,transition:u=`all .3s ${Ft} !important`}={}){return[K("&.icon-switch-transition-enter-from, &.icon-switch-transition-leave-to",{transform:`${s} scale(0.75)`,left:t,top:d,opacity:0}),K("&.icon-switch-transition-enter-to, &.icon-switch-transition-leave-from",{transform:`scale(1) ${s}`,left:t,top:d,opacity:1}),K("&.icon-switch-transition-enter-active, &.icon-switch-transition-leave-active",{transformOrigin:"center",position:"absolute",left:t,top:d,transition:u})]}var Nt=K([K("@keyframes rotator",`
|
||||
import{a0 as ge,h as F,a1 as Ze,a2 as Me,a3 as Xe,a4 as Qe,a5 as Pe,a6 as et,o as w,a7 as ze,z as ce,c as y,F as G,b as e,a8 as We,a9 as tt,e as st,aa as nt,G as Fe,A as it,ab as ot,ac as at,j as V,ad as Ae,ae as K,J as lt,I as Ye,af as rt,P as dt,ag as ct,ah as ut,d as ve,ai as _t,aj as mt,ak as Ue,al as b,n as Re,am as Ge,an as ft,ao as ht,ap as pt,aq as I,ar as Ee,as as qe,at as Q,au as gt,u as vt,i as bt,a as wt,t as l,f as o,q as M,w as He,C as f,D as v,g as L,Z as _e,s as Oe,R as ke,S as p,H as re,B as yt,_ as xt}from"./index-BKnWAKao.js";import{f as kt,g as St,h as De,i as Ct}from"./admin-KnbIpHLF.js";import{u as Bt}from"./auth-Cp2GGuZy.js";function Vt(s={},t={defaultBordered:!0}){const d=ge(Me,null);return{inlineThemeDisabled:d?.inlineThemeDisabled,mergedRtlRef:d?.mergedRtlRef,mergedComponentPropsRef:d?.mergedComponentPropsRef,mergedBreakpointsRef:d?.mergedBreakpointsRef,mergedBorderedRef:F(()=>{const{bordered:u}=s;return u!==void 0?u:d?.mergedBorderedRef.value??t.defaultBordered??!0}),mergedClsPrefixRef:d?d.mergedClsPrefixRef:Ze("n"),namespaceRef:F(()=>d?.mergedNamespaceRef.value)}}function $t(s,t,d){if(!t)return;const u=Xe(),_=ge(Me,null),h=()=>{const x=d.value;t.mount({id:x===void 0?s:x+s,head:!0,anchorMetaName:Pe,props:{bPrefix:x?`.${x}-`:void 0},ssr:u,parent:_?.styleMountTarget}),_?.preflightStyleDisabled||et.mount({id:"n-global",head:!0,anchorMetaName:Pe,ssr:u,parent:_?.styleMountTarget})};u?h():Qe(h)}function z(s,t=1){let d=Fe,u=!1;return typeof s=="function"&&(u=!0,w(),d=ce,s=s()),ze(s)?u?ce(Ie(s)):Ie(s):Array.isArray(s)?u?y(G,null,s.map(_=>z(()=>_)),-2):e(G,null,s.slice()):s==null||typeof s=="boolean"?d(We):d(tt,null,String(s),t)}function Ie(s){return s.el===null&&s.patchFlag!==-1||s.memo?s:nt(s)}const Tt=s=>typeof s=="function"||Object.prototype.toString.call(s)==="[object Object]"&&!ze(s)?s:{default:it(()=>[z(()=>s)])},C=s=>st(s)||null;function j(s){return typeof s=="string"?s.endsWith("px")?Number(s.slice(0,s.length-2)):Number(s):s}function Se(s){if(s!=null)return typeof s=="number"?`${s}px`:s.endsWith("px")?s:`${s}px`}function Ut(s,t,d,u){d||ot("useThemeClass","cssVarsRef is not passed");const _=ge(Me,null),h=_?.mergedThemeHashRef,x=_?.styleMountTarget,B=V(""),a=Xe();let k;const $=`__${s}`,R=()=>{let m=$;const T=t?t.value:void 0,N=h?.value;N&&(m+=`-${N}`),T&&(m+=`-${T}`);const{themeOverrides:E,builtinThemeOverrides:q}=u;E&&(m+=`-${Ae(JSON.stringify(E))}`),q&&(m+=`-${Ae(JSON.stringify(q))}`),B.value=m,k=()=>{const te=d.value;let se="";for(const ne in te)se+=`${ne}: ${te[ne]};`;K(`.${m}`,se).mount({id:m,ssr:a,parent:x}),k=void 0}};return at(()=>{R()}),{themeClass:B,onRender:()=>{k?.()}}}function Rt(s,t){return lt(s,d=>{d!==void 0&&(t.value=d)}),F(()=>s.value===void 0?t.value:s.value)}function Mt(){const s=V(!1);return Ye(()=>{s.value=!0}),rt(s)}function he(s,...t){if(Array.isArray(s))s.forEach(d=>he(d,...t));else return s(...t)}function Ne(s){return s.some(t=>ze(t)?!(t.type===We||t.type===G&&!Ne(t.children)):!0)?s:null}function ee(s,t){return t(s&&Ne(s())||null)}function Ce(s){return!(s&&Ne(s()))}const Le=ct("n-form-item");function zt(s,{defaultSize:t="medium",mergedSize:d,mergedDisabled:u}={}){const _=ge(Le,null);ut(Le,null);const h=F(d?()=>d(_):()=>{const{size:a}=s;if(a)return a;if(_){const{mergedSize:k}=_;if(k.value!==void 0)return k.value}return t}),x=F(u?()=>u(_):()=>{const{disabled:a}=s;return a!==void 0?a:_?_.disabled.value:!1}),B=F(()=>{const{status:a}=s;return a||_?.mergedValidationStatus.value});return dt(()=>{_&&_.restoreValidation()}),{mergedSizeRef:h,mergedDisabledRef:x,mergedStatusRef:B,nTriggerFormBlur(){_&&_.handleContentBlur()},nTriggerFormChange(){_&&_.handleContentChange()},nTriggerFormFocus(){_&&_.handleContentFocus()},nTriggerFormInput(){_&&_.handleContentInput()}}}var Je=ve({name:"BaseIconSwitchTransition",setup(s,{slots:t}){const d=Mt();return()=>(w(),ce(_t,{name:"icon-switch-transition",appear:d.value},Tt(t),1032,["appear"]))}});const{cubicBezierEaseInOut:Ft}=mt;function pe({originalTransform:s="",left:t=0,top:d=0,transition:u=`all .3s ${Ft} !important`}={}){return[K("&.icon-switch-transition-enter-from, &.icon-switch-transition-leave-to",{transform:`${s} scale(0.75)`,left:t,top:d,opacity:0}),K("&.icon-switch-transition-enter-to, &.icon-switch-transition-leave-from",{transform:`scale(1) ${s}`,left:t,top:d,opacity:1}),K("&.icon-switch-transition-enter-active, &.icon-switch-transition-leave-active",{transformOrigin:"center",position:"absolute",left:t,top:d,transition:u})]}var Nt=K([K("@keyframes rotator",`
|
||||
0% {
|
||||
-webkit-transform: rotate(0deg);
|
||||
transform: rotate(0deg);
|
||||
+1
-1
@@ -1 +1 @@
|
||||
import{d as z,u as E,a as x,c as i,G as B,f as t,A as m,b as a,F as _,r as v,az as S,t as r,h as d,aA as p,aB as T,O as A,o,z as M,q as V,e as b,aC as w}from"./index-DYsKpclu.js";const D={class:"site-nav"},F=["src"],I={class:"brand-name"},O=["aria-label"],R={class:"nav-controls"},U=["aria-label"],q=["aria-checked","title","onClick"],G={class:"nav-control-icon","aria-hidden":"true"},H=["title"],K=z({__name:"SiteNav",setup($){const{t:s}=E(),c=x(),{mode:u,setMode:k}=w(),g=d(()=>[{to:"/",label:s("nav.home"),match:n=>n==="/"}]);function y(n){return n.match(location.pathname)}const C={light:"☀️",dark:"🌙",system:"💻"},f=d(()=>({light:s("theme.light"),dark:s("theme.dark"),system:s("theme.system")})),L=d(()=>p()==="zh-CN"?"中文":"English");function N(){const n=p()==="zh-CN"?"en-US":"zh-CN";T(n)}return(n,l)=>{const h=A("RouterLink");return o(),i("header",D,[B(h,{class:"brand",to:"/",title:t(s)("nav.homeTitle",{name:t(c).displayName})},{default:m(()=>[a("img",{src:t(c).displayLogoUrl,alt:"Logo",onError:l[0]||(l[0]=e=>e.target.style.visibility="hidden")},null,40,F),a("span",I,r(t(c).displayName),1)]),_:1},8,["title"]),a("nav",{class:"nav-links","aria-label":t(s)("nav.mainNav")},[(o(!0),i(_,null,v(g.value,e=>(o(),M(h,{key:e.to,to:e.to,class:b({"router-link-active":y(e)})},{default:m(()=>[V(r(e.label),1)]),_:2},1032,["to","class"]))),128))],8,O),a("div",R,[a("div",{class:"theme-seg",role:"radiogroup","aria-label":t(s)("theme.label")},[(o(!0),i(_,null,v(t(S),e=>(o(),i("button",{key:e,type:"button",role:"radio","aria-checked":t(u)===e,class:b({active:t(u)===e}),title:f.value[e],onClick:j=>t(k)(e)},[a("span",G,r(C[e]),1)],10,q))),128))],8,U),a("button",{class:"nav-control",type:"button",title:t(s)("lang.label"),onClick:N},[l[1]||(l[1]=a("span",{class:"nav-control-icon","aria-hidden":"true"},"🌐",-1)),a("span",null,r(L.value),1)],8,H)])])}}});export{K as _};
|
||||
import{d as z,u as E,a as x,c as i,G as B,f as t,A as m,b as a,F as _,r as v,az as S,t as r,h as d,aA as p,aB as T,O as A,o,z as M,q as V,e as b,aC as w}from"./index-BKnWAKao.js";const D={class:"site-nav"},F=["src"],I={class:"brand-name"},O=["aria-label"],R={class:"nav-controls"},U=["aria-label"],q=["aria-checked","title","onClick"],G={class:"nav-control-icon","aria-hidden":"true"},H=["title"],K=z({__name:"SiteNav",setup($){const{t:s}=E(),c=x(),{mode:u,setMode:k}=w(),g=d(()=>[{to:"/",label:s("nav.home"),match:n=>n==="/"}]);function y(n){return n.match(location.pathname)}const C={light:"☀️",dark:"🌙",system:"💻"},f=d(()=>({light:s("theme.light"),dark:s("theme.dark"),system:s("theme.system")})),L=d(()=>p()==="zh-CN"?"中文":"English");function N(){const n=p()==="zh-CN"?"en-US":"zh-CN";T(n)}return(n,l)=>{const h=A("RouterLink");return o(),i("header",D,[B(h,{class:"brand",to:"/",title:t(s)("nav.homeTitle",{name:t(c).displayName})},{default:m(()=>[a("img",{src:t(c).displayLogoUrl,alt:"Logo",onError:l[0]||(l[0]=e=>e.target.style.visibility="hidden")},null,40,F),a("span",I,r(t(c).displayName),1)]),_:1},8,["title"]),a("nav",{class:"nav-links","aria-label":t(s)("nav.mainNav")},[(o(!0),i(_,null,v(g.value,e=>(o(),M(h,{key:e.to,to:e.to,class:b({"router-link-active":y(e)})},{default:m(()=>[V(r(e.label),1)]),_:2},1032,["to","class"]))),128))],8,O),a("div",R,[a("div",{class:"theme-seg",role:"radiogroup","aria-label":t(s)("theme.label")},[(o(!0),i(_,null,v(t(S),e=>(o(),i("button",{key:e,type:"button",role:"radio","aria-checked":t(u)===e,class:b({active:t(u)===e}),title:f.value[e],onClick:j=>t(k)(e)},[a("span",G,r(C[e]),1)],10,q))),128))],8,U),a("button",{class:"nav-control",type:"button",title:t(s)("lang.label"),onClick:N},[l[1]||(l[1]=a("span",{class:"nav-control-icon","aria-hidden":"true"},"🌐",-1)),a("span",null,r(L.value),1)],8,H)])])}}});export{K as _};
|
||||
+1
-1
@@ -1 +1 @@
|
||||
import{v as n,S as e,x as s}from"./index-DYsKpclu.js";function u(t){return n(s.adminLogin,{method:"POST",json:{password:t}})}function m(){return n(s.adminVerify)}async function l(){await n(s.adminLogout,{method:"POST"})}async function g(t){const a=await n(s.adminFileList,{query:{page:t.page,size:t.size,keyword:t.keyword||void 0}}),o=e(a,["data","list","items","files"])??[],d=Number(e(a,["total","count"])??o.length);return{page:Number(e(a,["page"])??t.page),size:Number(e(a,["size"])??t.size),total:d,data:o.map(i=>({id:Number(e(i,["id"])??0),code:String(e(i,["code"])??""),name:String(e(i,["name"])??`${e(i,["prefix"])??""}${e(i,["suffix"])??""}`),suffix:String(e(i,["suffix"])??""),size:Number(e(i,["size"])??0),isText:!!(e(i,["isText","is_text"])??!1),expiredAt:e(i,["expiredAt","expired_at","expires_at"])??null,expiredCount:e(i,["expiredCount","expired_count"])??null,usedCount:Number(e(i,["usedCount","used_count"])??0),createdAt:e(i,["createdAt","created_at"])??null,isExpired:!!(e(i,["isExpired","is_expired"])??!1)}))}}async function p(t){await n(s.adminFileDelete,{method:"DELETE",json:{id:t}})}async function f(t){await n(s.adminFileBatchDelete,{method:"POST",json:{ids:t}})}async function y(t){await n(s.adminFileUpdate,{method:"PATCH",json:t})}async function w(){const t=await n(s.adminConfigGet);if(t&&typeof t=="object"&&!Array.isArray(t)){const a=t;return e(a,["config","data","settings"])??a}return{}}async function S(t){await n(s.adminConfigUpdate,{method:"PATCH",json:t})}async function _(t){const a=await n(s.adminStorageSwitch,{method:"POST",json:{engine:t}});return String(a?.engine??t)}async function x(t,a){await n(s.adminPasswordUpdate,{method:"PATCH",json:{old_password:t,new_password:a}})}async function b(t){const a=await n(s.adminAuditList,{query:{page:t.page,size:t.size,action:t.action||void 0,result:t.result||void 0,ip:t.ip||void 0,start_time:t.startTime||void 0,end_time:t.endTime||void 0}}),o=e(a,["data","list","items","logs"])??[],d=Number(e(a,["total","count"])??o.length);return{page:Number(e(a,["page"])??t.page),size:Number(e(a,["size"])??t.size),total:d,data:o.map((i,r)=>({id:Number(e(i,["id"])??r+1),action:String(e(i,["action"])??""),result:String(e(i,["result"])??""),fileCode:String(e(i,["file_code","fileCode","code"])??""),fileName:String(e(i,["file_name","fileName","name"])??""),sizeBytes:e(i,["size_bytes","sizeBytes","size"])??null,transferredBytes:e(i,["transferred_bytes","transferredBytes","bytes"])??null,ip:String(e(i,["ip","client_ip","clientIp"])??""),userAgent:String(e(i,["user_agent","userAgent"])??""),deviceOs:String(e(i,["device_os","deviceOs","os"])??""),deviceBrowser:String(e(i,["device_browser","deviceBrowser","browser"])??""),deviceType:String(e(i,["device_type","deviceType"])??""),actor:String(e(i,["actor"])??""),errorMsg:String(e(i,["error_msg","errorMsg","error"])??""),durationMs:e(i,["duration_ms","durationMs","duration"])??null,createdAt:e(i,["created_at","createdAt","time"])??null}))}}export{g as a,f as b,p as c,y as d,b as e,w as f,_ as g,S as h,x as i,l as j,m as k,u as l};
|
||||
import{v as n,S as e,x as s}from"./index-BKnWAKao.js";function u(t){return n(s.adminLogin,{method:"POST",json:{password:t}})}function m(){return n(s.adminVerify)}async function l(){await n(s.adminLogout,{method:"POST"})}async function g(t){const a=await n(s.adminFileList,{query:{page:t.page,size:t.size,keyword:t.keyword||void 0}}),o=e(a,["data","list","items","files"])??[],d=Number(e(a,["total","count"])??o.length);return{page:Number(e(a,["page"])??t.page),size:Number(e(a,["size"])??t.size),total:d,data:o.map(i=>({id:Number(e(i,["id"])??0),code:String(e(i,["code"])??""),name:String(e(i,["name"])??`${e(i,["prefix"])??""}${e(i,["suffix"])??""}`),suffix:String(e(i,["suffix"])??""),size:Number(e(i,["size"])??0),isText:!!(e(i,["isText","is_text"])??!1),expiredAt:e(i,["expiredAt","expired_at","expires_at"])??null,expiredCount:e(i,["expiredCount","expired_count"])??null,usedCount:Number(e(i,["usedCount","used_count"])??0),createdAt:e(i,["createdAt","created_at"])??null,isExpired:!!(e(i,["isExpired","is_expired"])??!1)}))}}async function p(t){await n(s.adminFileDelete,{method:"DELETE",json:{id:t}})}async function f(t){await n(s.adminFileBatchDelete,{method:"POST",json:{ids:t}})}async function y(t){await n(s.adminFileUpdate,{method:"PATCH",json:t})}async function w(){const t=await n(s.adminConfigGet);if(t&&typeof t=="object"&&!Array.isArray(t)){const a=t;return e(a,["config","data","settings"])??a}return{}}async function S(t){await n(s.adminConfigUpdate,{method:"PATCH",json:t})}async function _(t){const a=await n(s.adminStorageSwitch,{method:"POST",json:{engine:t}});return String(a?.engine??t)}async function x(t,a){await n(s.adminPasswordUpdate,{method:"PATCH",json:{old_password:t,new_password:a}})}async function b(t){const a=await n(s.adminAuditList,{query:{page:t.page,size:t.size,action:t.action||void 0,result:t.result||void 0,ip:t.ip||void 0,start_time:t.startTime||void 0,end_time:t.endTime||void 0}}),o=e(a,["data","list","items","logs"])??[],d=Number(e(a,["total","count"])??o.length);return{page:Number(e(a,["page"])??t.page),size:Number(e(a,["size"])??t.size),total:d,data:o.map((i,r)=>({id:Number(e(i,["id"])??r+1),action:String(e(i,["action"])??""),result:String(e(i,["result"])??""),fileCode:String(e(i,["file_code","fileCode","code"])??""),fileName:String(e(i,["file_name","fileName","name"])??""),sizeBytes:e(i,["size_bytes","sizeBytes","size"])??null,transferredBytes:e(i,["transferred_bytes","transferredBytes","bytes"])??null,ip:String(e(i,["ip","client_ip","clientIp"])??""),userAgent:String(e(i,["user_agent","userAgent"])??""),deviceOs:String(e(i,["device_os","deviceOs","os"])??""),deviceBrowser:String(e(i,["device_browser","deviceBrowser","browser"])??""),deviceType:String(e(i,["device_type","deviceType"])??""),actor:String(e(i,["actor"])??""),errorMsg:String(e(i,["error_msg","errorMsg","error"])??""),durationMs:e(i,["duration_ms","durationMs","duration"])??null,createdAt:e(i,["created_at","createdAt","time"])??null}))}}export{g as a,f as b,p as c,y as d,b as e,w as f,_ as g,S as h,x as i,l as j,m as k,u as l};
|
||||
+1
-1
@@ -1 +1 @@
|
||||
import{av as o,aw as a,W as r}from"./index-DYsKpclu.js";import{j as n,k as i,l as c}from"./admin-DEOkRyTC.js";const s="fcb_admin_flag",l=o("auth",{state:()=>({token:r(),checked:!1}),getters:{isAuthed:t=>!!t.token},actions:{async login(t){const e=(await c(t))?.token;if(!e)throw new Error("登录响应缺少 token");this.token=e,a(e);try{localStorage.setItem(s,"1")}catch{}this.checked=!0},async verify(){if(!this.token)return!1;try{return await i(),this.checked=!0,!0}catch{return this.reset(),!1}},async logout(){try{this.token&&await n()}catch{}this.reset()},reset(){this.token="",this.checked=!1,a("");try{localStorage.removeItem(s)}catch{}}}});export{l as u};
|
||||
import{av as o,aw as a,W as r}from"./index-BKnWAKao.js";import{j as n,k as i,l as c}from"./admin-KnbIpHLF.js";const s="fcb_admin_flag",l=o("auth",{state:()=>({token:r(),checked:!1}),getters:{isAuthed:t=>!!t.token},actions:{async login(t){const e=(await c(t))?.token;if(!e)throw new Error("登录响应缺少 token");this.token=e,a(e);try{localStorage.setItem(s,"1")}catch{}this.checked=!0},async verify(){if(!this.token)return!1;try{return await i(),this.checked=!0,!0}catch{return this.reset(),!1}},async logout(){try{this.token&&await n()}catch{}this.reset()},reset(){this.token="",this.checked=!1,a("");try{localStorage.removeItem(s)}catch{}}}});export{l as u};
|
||||
Vendored
+5
-5
File diff suppressed because one or more lines are too long
+2
-2
File diff suppressed because one or more lines are too long
+1
-1
@@ -1 +1 @@
|
||||
import{v as x,S as s,U as m,V as g,x as u,W as w,H as i,X as f,Y as h}from"./index-DYsKpclu.js";function T(n,t,r,a=""){return x(u.shareText,{method:"POST",form:{text:n,expire_value:String(t),expire_style:r,code:a}})}function y(n,t,r,a,o=""){const e=new FormData;return e.append("file",n),e.append("expire_value",String(t)),e.append("expire_style",r),o&&e.append("code",o),h(u.shareFile,e,a)}async function S(n){const t=await x(u.shareMetadata,{query:{code:n}}),r=!!(s(t,["is_text","isText"])??s(t,["type"])==="text");return{code:String(s(t,["code"])??n),name:String(s(t,["name"])??"未命名"),size:Number(s(t,["size"])??0),type:r?"text":"file",isText:r,createdAt:s(t,["created_at","createdAt"])??null,expiredAt:s(t,["expired_at","expires_at","expiredAt","expiresAt"])??null,expiredCount:s(t,["expired_count","expiredCount","remaining_downloads","remainingDownloads"])??null,usedCount:Number(s(t,["used_count","usedCount"])??0),remainingDownloads:s(t,["remaining_downloads","remainingDownloads","expired_count","expiredCount"])??null}}async function b(n){const{blob:t}=await m(u.shareSelect,{query:{code:n}});return t.text()}function A(n,t){return new Promise((r,a)=>{const o=new URL(g(u.shareSelect),location.origin);o.searchParams.set("code",n);const e=new XMLHttpRequest;e.open("GET",o.toString()),e.timeout=6e5,e.responseType="blob";const l=w();l&&e.setRequestHeader("Authorization",`Bearer ${l}`),e.onprogress=p=>{p.lengthComputable&&t&&t(Math.round(p.loaded/p.total*100))},e.onload=()=>{if((e.getResponseHeader("content-type")??"").includes("application/json")){const d=new FileReader;d.onload=()=>{try{const c=JSON.parse(String(d.result));a(new i(c.code??e.status,c.msg||"取件失败",e.status))}catch{a(new i(e.status,"取件失败",e.status))}},d.readAsText(e.response);return}e.status>=200&&e.status<300?r({blob:e.response,filename:f(e.getResponseHeader("content-disposition"))}):a(new i(e.status,`取件失败(HTTP ${e.status})`,e.status))},e.onerror=()=>a(new i(0,"网络异常,取件失败")),e.ontimeout=()=>a(new i(0,"下载超时,请重试")),e.send()})}export{y as a,A as b,S as g,b as p,T as s};
|
||||
import{v as x,S as s,U as m,V as g,x as u,W as w,H as i,X as f,Y as h}from"./index-BKnWAKao.js";function T(n,t,r,a=""){return x(u.shareText,{method:"POST",form:{text:n,expire_value:String(t),expire_style:r,code:a}})}function y(n,t,r,a,o=""){const e=new FormData;return e.append("file",n),e.append("expire_value",String(t)),e.append("expire_style",r),o&&e.append("code",o),h(u.shareFile,e,a)}async function S(n){const t=await x(u.shareMetadata,{query:{code:n}}),r=!!(s(t,["is_text","isText"])??s(t,["type"])==="text");return{code:String(s(t,["code"])??n),name:String(s(t,["name"])??"未命名"),size:Number(s(t,["size"])??0),type:r?"text":"file",isText:r,createdAt:s(t,["created_at","createdAt"])??null,expiredAt:s(t,["expired_at","expires_at","expiredAt","expiresAt"])??null,expiredCount:s(t,["expired_count","expiredCount","remaining_downloads","remainingDownloads"])??null,usedCount:Number(s(t,["used_count","usedCount"])??0),remainingDownloads:s(t,["remaining_downloads","remainingDownloads","expired_count","expiredCount"])??null}}async function b(n){const{blob:t}=await m(u.shareSelect,{query:{code:n}});return t.text()}function A(n,t){return new Promise((r,a)=>{const o=new URL(g(u.shareSelect),location.origin);o.searchParams.set("code",n);const e=new XMLHttpRequest;e.open("GET",o.toString()),e.timeout=6e5,e.responseType="blob";const l=w();l&&e.setRequestHeader("Authorization",`Bearer ${l}`),e.onprogress=p=>{p.lengthComputable&&t&&t(Math.round(p.loaded/p.total*100))},e.onload=()=>{if((e.getResponseHeader("content-type")??"").includes("application/json")){const d=new FileReader;d.onload=()=>{try{const c=JSON.parse(String(d.result));a(new i(c.code??e.status,c.msg||"取件失败",e.status))}catch{a(new i(e.status,"取件失败",e.status))}},d.readAsText(e.response);return}e.status>=200&&e.status<300?r({blob:e.response,filename:f(e.getResponseHeader("content-disposition"))}):a(new i(e.status,`取件失败(HTTP ${e.status})`,e.status))},e.onerror=()=>a(new i(0,"网络异常,取件失败")),e.ontimeout=()=>a(new i(0,"下载超时,请重试")),e.send()})}export{y as a,A as b,S as g,b as p,T as s};
|
||||
Vendored
+1
-1
@@ -27,7 +27,7 @@
|
||||
background: #0b0f1a;
|
||||
}
|
||||
</style>
|
||||
<script type="module" crossorigin src="/assets/index-DYsKpclu.js"></script>
|
||||
<script type="module" crossorigin src="/assets/index-BKnWAKao.js"></script>
|
||||
<link rel="stylesheet" crossorigin href="/assets/index-CtyCxWf5.css">
|
||||
</head>
|
||||
<body>
|
||||
|
||||
Generated
+5
-5
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "filecodebox-web",
|
||||
"version": "1.0.0",
|
||||
"name": "fileshare-web",
|
||||
"version": "26.9",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "filecodebox-web",
|
||||
"version": "1.0.0",
|
||||
"name": "fileshare-web",
|
||||
"version": "26.9",
|
||||
"dependencies": {
|
||||
"marked": "^16.3.0",
|
||||
"naive-ui": "^2.45.3",
|
||||
@@ -1957,4 +1957,4 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+2
-2
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "filecodebox-web",
|
||||
"name": "fileshare-web",
|
||||
"private": true,
|
||||
"version": "1.0.0",
|
||||
"version": "26.9",
|
||||
"type": "module",
|
||||
"description": "FileCodeBox Go 版前端:分享 / 取件 / 管理后台 / 审计日志 / 站内文档",
|
||||
"scripts": {
|
||||
|
||||
Reference in New Issue
Block a user