重构:Wails v3 迁移 + 前端目录规范化 + Sidebar滚动优化

- web/ → frontend/ 目录重命名(Wails v3 标准结构)
- main.go: Middleware 修复 custom.js 404 + DevTools 延迟启动
- Sidebar: 收藏夹内部独立滚动 + 帮助区块固定底部
- useFavorites.ts: longPressTimer const→let 修复 TypeError
- App.vue: Arco Tabs padding-top 覆盖
- build: config.yml / Taskfile.yml 对齐官方模板,devtools build tag
- 新增 v3 bindings、vite.config.js、跨平台构建配置

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
lxy
2026-05-01 11:03:53 +08:00
co-authored by Claude Opus 4.7
parent 44847e0d40
commit f54bf1c28d
185 changed files with 7768 additions and 914 deletions
+119
View File
@@ -0,0 +1,119 @@
/**
* Wails Transport — 本地文件操作(通过 Wails v3 IPC)
*/
import type { FsTransport, FileItem, FileOperationResult, DetectTypeResult } from './transport'
import {
ListDir, GetFileInfo, ReadFile, WriteFile, SaveBase64File,
CreateFile, CreateDir, DeletePath, RenamePath,
ListZipContents, ExtractFileFromZip, ExtractFileFromZipToTemp, GetZipFileInfo,
OpenPath, GetFileServerURL, ResolveShortcut, DetectFileTypeByContent,
GetCommonPaths, GetRecycleBinEntries, RestoreFromRecycleBin,
DeletePermanently, EmptyRecycleBin
} from '../wailsjs/v3-bindings/u-desk/app'
function transformFile(file: any): FileItem {
return { ...file, is_dir: file.is_dir, mod_time: file.mod_time }
}
function transformFileList(files: any[]): FileItem[] {
return files.map(transformFile)
}
export class WailsTransport implements FsTransport {
async listDir(path: string): Promise<FileItem[]> {
return transformFileList(await ListDir(path))
}
async getFileInfo(path: string): Promise<Record<string, any>> {
return GetFileInfo(path)
}
async readFile(path: string): Promise<string> {
return ReadFile(path)
}
async writeFile(path: string, content: string): Promise<void> {
await WriteFile({ path: String(path), content: String(content) })
}
async saveBase64File(path: string, content: string): Promise<void> {
if (!content) throw new Error('无效的 base64 内容')
await SaveBase64File({ path: String(path), content })
}
async createFile(dirPath: string, filename: string): Promise<FileOperationResult> {
const fullPath = dirPath.replace(/\/$/, '') + '/' + filename
return CreateFile(fullPath)
}
async createDir(parentPath: string, dirname: string): Promise<FileOperationResult> {
const fullPath = parentPath.replace(/\/$/, '') + '/' + dirname
return CreateDir(fullPath)
}
async deletePath(path: string): Promise<FileOperationResult> {
return DeletePath(path)
}
async renamePath(oldPath: string, newPath: string): Promise<FileOperationResult> {
return RenamePath({ oldPath: String(oldPath), newPath: String(newPath) })
}
async listZipContents(zipPath: string): Promise<FileItem[]> {
return transformFileList(await ListZipContents(zipPath))
}
async extractFileFromZip(zipPath: string, filePath: string): Promise<string> {
return ExtractFileFromZip(zipPath, filePath)
}
async extractFileFromZipToTemp(zipPath: string, filePath: string): Promise<string> {
return ExtractFileFromZipToTemp(zipPath, filePath)
}
async getZipFileInfo(zipPath: string, filePath: string): Promise<FileItem> {
return transform(await GetZipFileInfo(zipPath, filePath))
}
async openPath(path: string): Promise<void> {
await OpenPath(path)
}
async getFileServerURL(): Promise<string> {
return GetFileServerURL()
}
getPreviewToken(): string {
return '' // 本地模式无需 token
}
async resolveShortcut(lnkPath: string): Promise<any> {
return ResolveShortcut(lnkPath)
}
async detectFileTypeByContent(path: string): Promise<DetectTypeResult> {
const result = await DetectFileTypeByContent(path)
return result as unknown as DetectTypeResult
}
async getCommonPaths(): Promise<Record<string, string>> {
return GetCommonPaths()
}
async getRecycleBinEntries(): Promise<any[]> {
return GetRecycleBinEntries()
}
async restoreFromRecycleBin(path: string): Promise<void> {
await RestoreFromRecycleBin(path)
}
async deletePermanently(path: string): Promise<void> {
await DeletePermanently(path)
}
async emptyRecycleBin(): Promise<void> {
await EmptyRecycleBin()
}
}