diff --git a/web/src/assets/icons/files/archive.svg b/web/src/assets/icons/files/archive.svg
new file mode 100644
index 00000000..c6a9fe7c
--- /dev/null
+++ b/web/src/assets/icons/files/archive.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/web/src/assets/icons/files/audio.svg b/web/src/assets/icons/files/audio.svg
new file mode 100644
index 00000000..7864d428
--- /dev/null
+++ b/web/src/assets/icons/files/audio.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/web/src/assets/icons/files/cad.svg b/web/src/assets/icons/files/cad.svg
new file mode 100644
index 00000000..cf4eb8f2
--- /dev/null
+++ b/web/src/assets/icons/files/cad.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/web/src/assets/icons/files/code.svg b/web/src/assets/icons/files/code.svg
new file mode 100644
index 00000000..5a05b781
--- /dev/null
+++ b/web/src/assets/icons/files/code.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/web/src/assets/icons/files/file.svg b/web/src/assets/icons/files/file.svg
new file mode 100644
index 00000000..6fa6b1a4
--- /dev/null
+++ b/web/src/assets/icons/files/file.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/web/src/assets/icons/files/folder-enterprise.svg b/web/src/assets/icons/files/folder-enterprise.svg
new file mode 100644
index 00000000..e42e4403
--- /dev/null
+++ b/web/src/assets/icons/files/folder-enterprise.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/web/src/assets/icons/files/folder-favorite.svg b/web/src/assets/icons/files/folder-favorite.svg
new file mode 100644
index 00000000..1cfaec4d
--- /dev/null
+++ b/web/src/assets/icons/files/folder-favorite.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/web/src/assets/icons/files/folder-personal.svg b/web/src/assets/icons/files/folder-personal.svg
new file mode 100644
index 00000000..6f971a61
--- /dev/null
+++ b/web/src/assets/icons/files/folder-personal.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/web/src/assets/icons/files/folder-trash.svg b/web/src/assets/icons/files/folder-trash.svg
new file mode 100644
index 00000000..6bf61555
--- /dev/null
+++ b/web/src/assets/icons/files/folder-trash.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/web/src/assets/icons/files/folder.svg b/web/src/assets/icons/files/folder.svg
new file mode 100644
index 00000000..e5f52911
--- /dev/null
+++ b/web/src/assets/icons/files/folder.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/web/src/assets/icons/files/image.svg b/web/src/assets/icons/files/image.svg
new file mode 100644
index 00000000..5c298d1d
--- /dev/null
+++ b/web/src/assets/icons/files/image.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/web/src/assets/icons/files/markdown.svg b/web/src/assets/icons/files/markdown.svg
new file mode 100644
index 00000000..6582fef0
--- /dev/null
+++ b/web/src/assets/icons/files/markdown.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/web/src/assets/icons/files/pdf.svg b/web/src/assets/icons/files/pdf.svg
new file mode 100644
index 00000000..d2c71780
--- /dev/null
+++ b/web/src/assets/icons/files/pdf.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/web/src/assets/icons/files/ppt.svg b/web/src/assets/icons/files/ppt.svg
new file mode 100644
index 00000000..71917a76
--- /dev/null
+++ b/web/src/assets/icons/files/ppt.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/web/src/assets/icons/files/psd.svg b/web/src/assets/icons/files/psd.svg
new file mode 100644
index 00000000..1ec920ee
--- /dev/null
+++ b/web/src/assets/icons/files/psd.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/web/src/assets/icons/files/python.svg b/web/src/assets/icons/files/python.svg
new file mode 100644
index 00000000..c7a8c355
--- /dev/null
+++ b/web/src/assets/icons/files/python.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/web/src/assets/icons/files/spreadsheet.svg b/web/src/assets/icons/files/spreadsheet.svg
new file mode 100644
index 00000000..ab411e40
--- /dev/null
+++ b/web/src/assets/icons/files/spreadsheet.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/web/src/assets/icons/files/text.svg b/web/src/assets/icons/files/text.svg
new file mode 100644
index 00000000..552438af
--- /dev/null
+++ b/web/src/assets/icons/files/text.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/web/src/assets/icons/files/video.svg b/web/src/assets/icons/files/video.svg
new file mode 100644
index 00000000..2412825e
--- /dev/null
+++ b/web/src/assets/icons/files/video.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/web/src/assets/icons/files/web.svg b/web/src/assets/icons/files/web.svg
new file mode 100644
index 00000000..6bdc0ee1
--- /dev/null
+++ b/web/src/assets/icons/files/web.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/web/src/assets/icons/files/word.svg b/web/src/assets/icons/files/word.svg
new file mode 100644
index 00000000..b8a180f6
--- /dev/null
+++ b/web/src/assets/icons/files/word.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/web/src/components/common/FileTypeIcon.vue b/web/src/components/common/FileTypeIcon.vue
new file mode 100644
index 00000000..7a0bdba9
--- /dev/null
+++ b/web/src/components/common/FileTypeIcon.vue
@@ -0,0 +1,36 @@
+
+
+
+
+
+
+
diff --git a/web/src/utils/file_icon.js b/web/src/utils/file_icon.js
new file mode 100644
index 00000000..0ce6f7bf
--- /dev/null
+++ b/web/src/utils/file_icon.js
@@ -0,0 +1,142 @@
+// 文件 / 文件夹类型图标(彩色 SVG),用于在文件路径前渲染。
+// 注意:仅用于「渲染文件/文件夹名称前的类型图标」,按钮图标请勿使用此处的资源。
+import archiveIcon from '@/assets/icons/files/archive.svg?url'
+import audioIcon from '@/assets/icons/files/audio.svg?url'
+import cadIcon from '@/assets/icons/files/cad.svg?url'
+import codeIcon from '@/assets/icons/files/code.svg?url'
+import fileIcon from '@/assets/icons/files/file.svg?url'
+import imageIcon from '@/assets/icons/files/image.svg?url'
+import markdownIcon from '@/assets/icons/files/markdown.svg?url'
+import pdfIcon from '@/assets/icons/files/pdf.svg?url'
+import pptIcon from '@/assets/icons/files/ppt.svg?url'
+import psdIcon from '@/assets/icons/files/psd.svg?url'
+import pythonIcon from '@/assets/icons/files/python.svg?url'
+import spreadsheetIcon from '@/assets/icons/files/spreadsheet.svg?url'
+import textIcon from '@/assets/icons/files/text.svg?url'
+import videoIcon from '@/assets/icons/files/video.svg?url'
+import webIcon from '@/assets/icons/files/web.svg?url'
+import wordIcon from '@/assets/icons/files/word.svg?url'
+import folderIcon from '@/assets/icons/files/folder.svg?url'
+import folderEnterpriseIcon from '@/assets/icons/files/folder-enterprise.svg?url'
+import folderFavoriteIcon from '@/assets/icons/files/folder-favorite.svg?url'
+import folderPersonalIcon from '@/assets/icons/files/folder-personal.svg?url'
+import folderTrashIcon from '@/assets/icons/files/folder-trash.svg?url'
+
+export const FOLDER_ICONS = {
+ default: folderIcon,
+ enterprise: folderEnterpriseIcon,
+ favorite: folderFavoriteIcon,
+ personal: folderPersonalIcon,
+ trash: folderTrashIcon
+}
+
+const EXTENSION_ICONS = {
+ // 文档
+ pdf: pdfIcon,
+ doc: wordIcon,
+ docx: wordIcon,
+ rtf: wordIcon,
+ ppt: pptIcon,
+ pptx: pptIcon,
+ xls: spreadsheetIcon,
+ xlsx: spreadsheetIcon,
+ csv: spreadsheetIcon,
+ // 文本 / Markdown
+ txt: textIcon,
+ text: textIcon,
+ log: textIcon,
+ md: markdownIcon,
+ markdown: markdownIcon,
+ mdx: markdownIcon,
+ // 代码
+ py: pythonIcon,
+ js: codeIcon,
+ mjs: codeIcon,
+ cjs: codeIcon,
+ jsx: codeIcon,
+ ts: codeIcon,
+ tsx: codeIcon,
+ vue: codeIcon,
+ json: codeIcon,
+ yaml: codeIcon,
+ yml: codeIcon,
+ toml: codeIcon,
+ ini: codeIcon,
+ conf: codeIcon,
+ env: codeIcon,
+ sh: codeIcon,
+ bash: codeIcon,
+ bat: codeIcon,
+ go: codeIcon,
+ rs: codeIcon,
+ c: codeIcon,
+ h: codeIcon,
+ cpp: codeIcon,
+ java: codeIcon,
+ css: codeIcon,
+ less: codeIcon,
+ scss: codeIcon,
+ sql: codeIcon,
+ xml: codeIcon,
+ // 网页
+ html: webIcon,
+ htm: webIcon,
+ // 图片
+ png: imageIcon,
+ jpg: imageIcon,
+ jpeg: imageIcon,
+ gif: imageIcon,
+ bmp: imageIcon,
+ webp: imageIcon,
+ svg: imageIcon,
+ apng: imageIcon,
+ avif: imageIcon,
+ ico: imageIcon,
+ // 设计 / 工程
+ psd: psdIcon,
+ dwg: cadIcon,
+ dxf: cadIcon,
+ // 音视频
+ mp3: audioIcon,
+ wav: audioIcon,
+ flac: audioIcon,
+ aac: audioIcon,
+ ogg: audioIcon,
+ m4a: audioIcon,
+ mp4: videoIcon,
+ mov: videoIcon,
+ avi: videoIcon,
+ mkv: videoIcon,
+ webm: videoIcon,
+ flv: videoIcon,
+ // 压缩包
+ zip: archiveIcon,
+ rar: archiveIcon,
+ '7z': archiveIcon,
+ tar: archiveIcon,
+ gz: archiveIcon
+}
+
+const getExtension = (name) => {
+ const cleanName = String(name || '')
+ .trim()
+ .toLowerCase()
+ .split(/[?#]/)[0]
+ const fileName = cleanName.split('/').pop() || ''
+ const dotIndex = fileName.lastIndexOf('.')
+ if (dotIndex <= 0) return ''
+ return fileName.slice(dotIndex + 1)
+}
+
+/**
+ * 解析文件 / 文件夹对应的彩色图标 URL。
+ * @param {string} name 文件名或路径(目录可以 `/` 结尾)
+ * @param {object} [options]
+ * @param {boolean} [options.isDir] 是否为目录
+ * @param {string} [options.folderVariant] 文件夹图标变体:default | enterprise | favorite | personal | trash
+ */
+export const resolveFileIconUrl = (name, { isDir = false, folderVariant = 'default' } = {}) => {
+ const isDirectory = isDir || String(name || '').endsWith('/')
+ if (isDirectory) return FOLDER_ICONS[folderVariant] || FOLDER_ICONS.default
+ return EXTENSION_ICONS[getExtension(name)] || fileIcon
+}