feat: 新增文件压缩功能和通用确认弹窗

后端新增 POST api/files/compress 接口,使用 DotNetZip 将单个文件压缩为 ZIP,
密码固定为文件名去掉后缀,压缩前自动删除同名旧 ZIP。
前端新增 ConfirmModal 通用确认弹窗,替代所有 window.confirm/alert,
在文件列表中增加压缩按钮,压缩前显示确认弹窗。
This commit is contained in:
2026-07-10 10:35:32 +08:00
parent 60878f9b6e
commit 87f5c1ffb8
13 changed files with 686 additions and 8 deletions
@@ -2,6 +2,7 @@ using FileShare_Common.Core;
using FileShare_EFCore.Database;
using FileShare_EFCore.Models;
using FileShare_Services.Core;
using Ionic.Zip;
using Microsoft.EntityFrameworkCore;
using System.Text;
@@ -593,6 +594,36 @@ namespace FileShare_Services.Services.FileLibrary
await db.SaveChangesAsync(cancellationToken);
}
/// <inheritdoc />
public async Task CompressFileAsync(int id, CancellationToken cancellationToken = default)
{
var record = await db.ManagedFileRecords
.FirstOrDefaultAsync(f => f.Id == id && f.Exists, cancellationToken)
?? throw new InvalidOperationException("文件不存在。");
if (!File.Exists(record.AbsolutePath))
throw new FileNotFoundException("源文件不存在于磁盘。");
var dir = Path.GetDirectoryName(record.AbsolutePath)!;
var nameWithoutExt = Path.GetFileNameWithoutExtension(record.FileName);
var zipPath = Path.Combine(dir, nameWithoutExt + ".zip");
// 删除已存在的同名 ZIP
if (File.Exists(zipPath))
{
File.Delete(zipPath);
}
// 密码为文件名去掉后缀
var zipPassword = nameWithoutExt.ToLower();
// 创建 ZIP
using var zip = new Ionic.Zip.ZipFile();
zip.Password = zipPassword;
zip.AddFile(record.AbsolutePath, "");
zip.Save(zipPath);
}
/// <summary>
/// 深度优先遍历目录树,枚举所有被 <see cref="MediaFileTypes"/> 支持的媒体文件路径。
/// 遇到无权限的目录时跳过该分支继续遍历。