feat: Vue Router 集成 + 压缩密码编码修复

前端:
- 引入 vue-router,HTML5 History 模式,干净 URL
- ClientPage.vue 拆分为 5 个独立路由视图组件
- 提取共享状态到 composables(useLibraryRoots/useMediaPlayer/useViewMode/useModals)
- 新增 DefaultLayout 统一布局
- 导航链接改为 router-link
- FileCard 网格视图修复删除/压缩按钮 hover 不显示问题

后端:
- 压缩密码编码修复:DotNetZip/SharpZipLib 不支持 UTF-8 密码
- 替换为 SharpZipLib + 中文字符替换为 # 的 ASCII 安全密码方案
This commit is contained in:
2026-07-10 15:22:09 +08:00
parent 87f5c1ffb8
commit 6bdcb48c97
22 changed files with 2001 additions and 935 deletions
@@ -2,7 +2,7 @@ using FileShare_Common.Core;
using FileShare_EFCore.Database;
using FileShare_EFCore.Models;
using FileShare_Services.Core;
using Ionic.Zip;
using ICSharpCode.SharpZipLib.Zip;
using Microsoft.EntityFrameworkCore;
using System.Text;
@@ -614,14 +614,25 @@ namespace FileShare_Services.Services.FileLibrary
File.Delete(zipPath);
}
// 密码为文件名去掉后缀
var zipPassword = nameWithoutExt.ToLower();
// 密码为文件名去掉后缀(中文转拼音,转小写)
var zipPassword = ConvertToAsciiPassword(nameWithoutExt);
// 创建 ZIP
using var zip = new Ionic.Zip.ZipFile();
zip.Password = zipPassword;
zip.AddFile(record.AbsolutePath, "");
zip.Save(zipPath);
// 使用 SharpZipLib 创建加密 ZIP(支持 UTF-8 密码)
using var outputStream = File.Create(zipPath);
using var zipStream = new ZipOutputStream(outputStream);
zipStream.Password = zipPassword;
zipStream.UseZip64 = UseZip64.Dynamic;
var entry = new ZipEntry(Path.GetFileName(record.AbsolutePath));
entry.DateTime = File.GetLastWriteTime(record.AbsolutePath);
zipStream.PutNextEntry(entry);
using (var fileStream = File.OpenRead(record.AbsolutePath))
{
await fileStream.CopyToAsync(zipStream, cancellationToken);
}
zipStream.CloseEntry();
}
/// <summary>
@@ -881,6 +892,22 @@ namespace FileShare_Services.Services.FileLibrary
|| sortDirection?.Trim().Equals("descending", StringComparison.OrdinalIgnoreCase) == true;
}
/// <summary>
/// 将文件名转换为 ASCII 安全的密码。中文字符替换为 #,其他字符保留原样。
/// </summary>
private static string ConvertToAsciiPassword(string fileName)
{
var sb = new StringBuilder(fileName.Length);
foreach (var ch in fileName)
{
if (ch >= 0x4E00 && ch <= 0x9FFF)
sb.Append('#');
else
sb.Append(ch);
}
return sb.ToString().ToLower();
}
/// <summary>
/// 安全获取驱动器属性值,驱动器未就绪或访问异常时返回 null。
/// </summary>