Files
timi-server/src/pages/file/fileExplorer.shared.ts
2026-04-13 14:55:50 +08:00

124 lines
2.7 KiB
TypeScript

import type { ServerFile } from "@/types/File";
export type DisplayMode = "list" | "grid";
export type FileItemType = "dir" | "file";
export interface ExplorerItem {
name: string;
type: FileItemType;
extension?: string;
size?: string;
updatedAt: string;
icon: string;
path: string;
rawType?: string;
}
const fileIconMap: Record<string, string> = {
TXT: "file-text",
CODE: "code",
SCRIPT: "code",
ZIP: "file-zip",
MICROSOFT: "file-excel",
JAVA: "logo-android",
VIDEO: "video",
FONT: "font-size",
AUDIO: "music",
IMAGE: "image",
SYSTEM: "setting",
FILE: "file"
};
const dateTimeFormatter = new Intl.DateTimeFormat("zh-CN", {
year: "numeric",
month: "2-digit",
day: "2-digit",
hour: "2-digit",
minute: "2-digit",
hour12: false
});
export function mapServerFileToExplorerItem(file: ServerFile): ExplorerItem {
const isDirectory = file.isDirectory || file.type === "DIRECTORY";
const rawPath = typeof file.absolutePath === "string" ? file.absolutePath.trim() : "";
return {
name: file.name || "未命名",
type: isDirectory ? "dir" : "file",
extension: file.extension,
size: isDirectory ? undefined : formatFileSize(file.size),
updatedAt: formatModifiedAt(file.modifiedAt),
icon: resolveFileIcon(file, isDirectory),
path: rawPath || file.name || "",
rawType: file.type
};
}
export function sortExplorerItems(items: ExplorerItem[]): ExplorerItem[] {
return [...items].sort((left, right) => {
if (left.type !== right.type) {
return left.type === "dir" ? -1 : 1;
}
return left.name.localeCompare(right.name, "zh-CN");
});
}
export function formatItemDesc(item: ExplorerItem): string {
if (item.type === "dir") {
return `文件夹 | ${item.updatedAt}`;
}
return `${item.size || "--"} | ${item.updatedAt}`;
}
function resolveFileIcon(file: ServerFile, isDirectory: boolean): string {
if (isDirectory) {
return "folder";
}
const rawType = typeof file.type === "string" ? file.type.toUpperCase() : "FILE";
return fileIconMap[rawType] || "file";
}
function formatModifiedAt(modifiedAt?: number): string {
if (!modifiedAt) {
return "未知时间";
}
return dateTimeFormatter.format(modifiedAt);
}
function formatFileSize(size?: number): string {
if (typeof size !== "number" || Number.isNaN(size) || size < 0) {
return "--";
}
if (size < 1024) {
return `${size} B`;
}
const units = ["KB", "MB", "GB", "TB"];
let nextSize = size / 1024;
let unitIndex = 0;
while (1024 <= nextSize && unitIndex < units.length - 1) {
nextSize /= 1024;
unitIndex += 1;
}
return `${trimDecimal(nextSize)} ${units[unitIndex]}`;
}
function trimDecimal(value: number): string {
if (10 <= value || Number.isInteger(value)) {
return value.toFixed(0);
}
if (1 <= value) {
return value.toFixed(1);
}
return value.toFixed(2);
}