258 lines
7.0 KiB
TypeScript
258 lines
7.0 KiB
TypeScript
import { Hono } from "hono";
|
|
import debug from "debug";
|
|
import type {
|
|
FileLibrary,
|
|
} from "../client/share/types.ts";
|
|
|
|
import {
|
|
DeleteStatus,
|
|
EnableStatus,
|
|
} from "../client/share/types.ts";
|
|
|
|
import type { Variables, WithAuth } from "./middlewares.ts";
|
|
|
|
const log = {
|
|
api: debug("api:sys"),
|
|
};
|
|
|
|
// 创建文件上传路由
|
|
export function createFileUploadRoutes(withAuth: WithAuth) {
|
|
const fileUploadRoutes = new Hono<{ Variables: Variables }>();
|
|
|
|
// 获取 MinIO 上传策略
|
|
fileUploadRoutes.get("/policy", withAuth, async (c) => {
|
|
try {
|
|
const prefix = c.req.query("prefix") || "uploads/";
|
|
const filename = c.req.query("filename");
|
|
const maxSize = Number(c.req.query("maxSize")) || 10 * 1024 * 1024; // 默认10MB
|
|
|
|
if (!filename) {
|
|
return c.json({ error: "文件名不能为空" }, 400);
|
|
}
|
|
|
|
const apiClient = c.get('apiClient');
|
|
const policy = await apiClient.storage.getUploadPolicy(
|
|
prefix,
|
|
filename,
|
|
maxSize
|
|
);
|
|
|
|
return c.json({
|
|
message: "获取上传策略成功",
|
|
data: policy,
|
|
});
|
|
} catch (error) {
|
|
log.api("获取上传策略失败:", error);
|
|
return c.json({ error: "获取上传策略失败" }, 500);
|
|
}
|
|
});
|
|
|
|
// 保存文件信息到文件库
|
|
fileUploadRoutes.post("/save", withAuth, async (c) => {
|
|
try {
|
|
const fileData = (await c.req.json()) as Partial<FileLibrary>;
|
|
const user = c.get("user");
|
|
|
|
// 验证必填字段
|
|
if (!fileData.file_name || !fileData.file_path || !fileData.file_type) {
|
|
return c.json({ error: "文件名、路径和类型不能为空" }, 400);
|
|
}
|
|
|
|
const apiClient = c.get('apiClient');
|
|
|
|
// 设置上传者信息
|
|
if (user) {
|
|
fileData.uploader_id = user.id;
|
|
fileData.uploader_name = user.nickname || user.username;
|
|
}
|
|
|
|
// 插入文件库记录
|
|
const [id] = await apiClient.database.table("file_library").insert({
|
|
...fileData,
|
|
download_count: 0,
|
|
is_disabled: EnableStatus.ENABLED,
|
|
is_deleted: DeleteStatus.NOT_DELETED,
|
|
created_at: apiClient.database.fn.now(),
|
|
updated_at: apiClient.database.fn.now(),
|
|
});
|
|
|
|
// 获取插入的数据
|
|
const [insertedFile] = await apiClient.database
|
|
.table("file_library")
|
|
.where("id", id);
|
|
|
|
return c.json({
|
|
message: "文件信息保存成功",
|
|
data: insertedFile,
|
|
});
|
|
} catch (error) {
|
|
log.api("保存文件信息失败:", error);
|
|
return c.json({ error: "保存文件信息失败" }, 500);
|
|
}
|
|
});
|
|
|
|
// 获取文件列表
|
|
fileUploadRoutes.get("/list", withAuth, async (c) => {
|
|
try {
|
|
const page = Number(c.req.query("page")) || 1;
|
|
const pageSize = Number(c.req.query("pageSize")) || 10;
|
|
const category_id = c.req.query("category_id");
|
|
const fileType = c.req.query("fileType");
|
|
const keyword = c.req.query("keyword");
|
|
|
|
const apiClient = c.get('apiClient');
|
|
let query = apiClient.database
|
|
.table("file_library")
|
|
.where("is_deleted", DeleteStatus.NOT_DELETED)
|
|
.orderBy("created_at", "desc");
|
|
|
|
// 应用过滤条件
|
|
if (category_id) {
|
|
query = query.where("category_id", category_id);
|
|
}
|
|
|
|
if (fileType) {
|
|
query = query.where("file_type", fileType);
|
|
}
|
|
|
|
if (keyword) {
|
|
query = query.where((builder) => {
|
|
builder
|
|
.where("file_name", "like", `%${keyword}%`)
|
|
.orWhere("description", "like", `%${keyword}%`)
|
|
.orWhere("tags", "like", `%${keyword}%`);
|
|
});
|
|
}
|
|
|
|
// 获取总数
|
|
const total = await query.clone().count();
|
|
|
|
// 分页查询
|
|
const files = await query.limit(pageSize).offset((page - 1) * pageSize);
|
|
|
|
return c.json({
|
|
message: "获取文件列表成功",
|
|
data: {
|
|
list: files,
|
|
pagination: {
|
|
current: page,
|
|
pageSize,
|
|
total: Number(total),
|
|
},
|
|
},
|
|
});
|
|
} catch (error) {
|
|
log.api("获取文件列表失败:", error);
|
|
return c.json({ error: "获取文件列表失败" }, 500);
|
|
}
|
|
});
|
|
|
|
// 获取单个文件信息
|
|
fileUploadRoutes.get("/:id", withAuth, async (c) => {
|
|
try {
|
|
const id = Number(c.req.param("id"));
|
|
|
|
if (!id || isNaN(id)) {
|
|
return c.json({ error: "无效的文件ID" }, 400);
|
|
}
|
|
|
|
const apiClient = c.get('apiClient');
|
|
const file = await apiClient.database
|
|
.table("file_library")
|
|
.where("id", id)
|
|
.where("is_deleted", DeleteStatus.NOT_DELETED)
|
|
.first();
|
|
|
|
if (!file) {
|
|
return c.json({ error: "文件不存在" }, 404);
|
|
}
|
|
|
|
return c.json({
|
|
message: "获取文件信息成功",
|
|
data: file,
|
|
});
|
|
} catch (error) {
|
|
log.api("获取文件信息失败:", error);
|
|
return c.json({ error: "获取文件信息失败" }, 500);
|
|
}
|
|
});
|
|
|
|
// 增加文件下载计数
|
|
fileUploadRoutes.post("/:id/download", withAuth, async (c) => {
|
|
try {
|
|
const id = Number(c.req.param("id"));
|
|
|
|
if (!id || isNaN(id)) {
|
|
return c.json({ error: "无效的文件ID" }, 400);
|
|
}
|
|
|
|
const apiClient = c.get('apiClient');
|
|
|
|
// 查询文件是否存在
|
|
const file = await apiClient.database
|
|
.table("file_library")
|
|
.where("id", id)
|
|
.where("is_deleted", DeleteStatus.NOT_DELETED)
|
|
.first();
|
|
|
|
if (!file) {
|
|
return c.json({ error: "文件不存在" }, 404);
|
|
}
|
|
|
|
// 增加下载计数
|
|
await apiClient.database
|
|
.table("file_library")
|
|
.where("id", id)
|
|
.update({
|
|
download_count: apiClient.database.raw("download_count + 1"),
|
|
updated_at: apiClient.database.fn.now(),
|
|
});
|
|
|
|
return c.json({
|
|
message: "更新下载计数成功",
|
|
});
|
|
} catch (error) {
|
|
log.api("更新下载计数失败:", error);
|
|
return c.json({ error: "更新下载计数失败" }, 500);
|
|
}
|
|
});
|
|
|
|
// 删除文件
|
|
fileUploadRoutes.delete("/:id", withAuth, async (c) => {
|
|
try {
|
|
const id = Number(c.req.param("id"));
|
|
|
|
if (!id || isNaN(id)) {
|
|
return c.json({ error: "无效的文件ID" }, 400);
|
|
}
|
|
|
|
const apiClient = c.get('apiClient');
|
|
|
|
// 查询文件是否存在
|
|
const file = await apiClient.database
|
|
.table("file_library")
|
|
.where("id", id)
|
|
.where("is_deleted", DeleteStatus.NOT_DELETED)
|
|
.first();
|
|
|
|
if (!file) {
|
|
return c.json({ error: "文件不存在" }, 404);
|
|
}
|
|
|
|
// 软删除文件
|
|
await apiClient.database.table("file_library").where("id", id).update({
|
|
is_deleted: DeleteStatus.DELETED,
|
|
updated_at: apiClient.database.fn.now(),
|
|
});
|
|
|
|
return c.json({
|
|
message: "文件删除成功",
|
|
});
|
|
} catch (error) {
|
|
log.api("删除文件失败:", error);
|
|
return c.json({ error: "删除文件失败" }, 500);
|
|
}
|
|
});
|
|
|
|
return fileUploadRoutes;
|
|
} |