ui框架-文件列表展示

ui框架-文件列表展示

介紹

UI框架的文件列表展示組件,可以展示文件夾,支持列表展示和圖標展示模式。組件提供了豐富的功能和可配置選項,適用于文件管理、文件上傳等場景。

功能特性

  • 支持列表模式和網格模式的切換展示
  • 支持文件和文件夾的層級展示
  • 支持文件選擇和文件夾選擇
  • 支持拖拽上傳文件
  • 支持多選/單選模式
  • 支持文件類型過濾
  • 支持文件大小限制
  • 支持圖片文件預覽
  • 支持返回上級目錄
  • 顯示文件大小和最后修改時間

安裝

npm install bbyh-ui-file-list-diaplay

使用示例

<template><FileListDisplaydefaultViewMode="grid":defaultFiles="files":acceptedTypes="['jpg', 'png', 'pdf']":maxFileSize="50":multiple="true":showFileSize="true":enableDrop="true"@select="handleSelect"@file-error="handleError"/>
</template><script setup>
import FileListDisplay from "bbyh-ui-file-list-diaplay";
import { ref } from 'vue';const files = ref([]);const handleSelect = (selectedFiles) => {console.log('Selected files:', selectedFiles);
};const handleError = (error) => {console.error('File error:', error);
};
</script>

Props 配置

屬性名類型默認值說明
defaultViewModeString‘list’默認視圖模式,可選值:‘list’/‘grid’
defaultFilesArray[]默認顯示的文件列表
multipleBooleantrue是否允許多選
acceptedTypesArray[]允許的文件類型,空數組表示允許所有類型
maxFileSizeNumber100最大文件大小(MB)
showFileSizeBooleantrue是否顯示文件大小
enableDropBooleantrue是否允許拖拽上傳
showToolbarBooleantrue是否顯示工具欄
showBackButtonBooleantrue是否顯示返回上級目錄按鈕

事件

事件名參數說明
selectselectedFiles選擇文件時觸發
enter-directorydirectory進入文件夾時觸發
file-error{file, error}文件驗證失敗時觸發
dropfiles拖拽文件時觸發
view-mode-changemode視圖模式改變時觸發

支持的文件類型圖標

  • 常見文檔:txt, doc, docx, xls, xlsx, ppt, pptx, pdf
  • 圖片:jpg, jpeg, png, gif, bmp, webp
  • 開發相關:js, java, c, cpp, py, css, html, json
  • 其他:exe, zip, rar 等

瀏覽器兼容性

  • Chrome >= 80
  • Firefox >= 75
  • Safari >= 13
  • Edge >= 80

開發說明

  1. 安裝依賴
npm install
  1. 啟動開發服務器
npm run serve
  1. 構建生產版本
npm run build

源碼下載

ui框架-文件列表展示

npm倉庫

ui框架-文件列表展示

核心代碼

code/src/components/FileListDisplay.vue

<template><div class="file-list-display"><!-- 工具欄 --><div class="toolbar"><div class="view-mode"><span:class="['mode-item', { active: viewMode === 'list' }]"@click="viewMode = 'list'">列表模式</span><span:class="['mode-item', { active: viewMode === 'grid' }]"@click="viewMode = 'grid'">圖標模式</span></div><div class="operations"><inputtype="file"ref="fileInput"@change="handleFileSelect"multiplestyle="display: none"><inputtype="file"ref="folderInput"@change="handleFolderSelect"webkitdirectorystyle="display: none"><button @click="selectFiles">選擇文件</button><button @click="selectFolder">選擇文件夾</button></div></div><!-- 文件列表區域 --><divclass="file-container":class="viewMode"@dragover.prevent@drop.prevent="handleDrop"><template v-if="currentDirectory.children.length"><!-- 顯示返回上級目錄按鈕 --><divv-if="currentDirectory.parent"class="file-item"@click="navigateToParent"><div class="file-icon"><img :src="getFileIcon({type: 'back'})" alt="back"></div><div class="file-info"><div class="file-name">..</div></div></div><!-- 顯示文件和文件夾 --><divv-for="item in currentDirectory.children":key="item.path"class="file-item":class="{ selected: selectedFiles.includes(item) }"@click="handleItemClick(item)"@dblclick="handleItemDoubleClick(item)"><div class="file-icon"><!-- 如果是圖片文件則顯示預覽 --><imgv-if="isImageFile(item)":src="getImagePreview(item)":alt="item.name"class="image-preview"@error="handleImageError(item)"><!-- 非圖片文件顯示默認圖標 --><img v-else :src="getFileIcon(item)" :alt="item.name" class="not-image-preview"></div><div class="file-info"><div class="file-name">{{ item.name }}</div><div class="file-size">{{formatFileSize(item.isDirectory ? calculateDirectorySize(item) : item.size)}}</div></div></div></template><div v-else class="empty-tip">當前文件夾為空</div></div></div>
</template><script setup>
import {onMounted, onUnmounted, ref, watch} from 'vue';
import {getFileIcon} from './fileIcons';
import {buildFileTree, calculateDirectorySize} from './fileUtils';// Props 定義
const props = defineProps({// 默認視圖模式defaultViewMode: {type: String,default: 'list',validator: (value) => ['list', 'grid'].includes(value)},// 默認文件列表defaultFiles: {type: Array,default: () => []},// 是否允許多選multiple: {type: Boolean,default: true},// 允許的文件類型acceptedTypes: {type: Array,default: () => []},// 最大文件大小(MB)maxFileSize: {type: Number,default: 100},// 是否顯示文件大小showFileSize: {type: Boolean,default: true},// 是否允許拖拽上傳enableDrop: {type: Boolean,default: true},// 是否顯示工具欄showToolbar: {type: Boolean,default: true},// 是否顯示返回上級目錄按鈕showBackButton: {type: Boolean,default: true}
});// Emits 定義
const emit = defineEmits(['select',           // 選擇文件時觸發'enter-directory',  // 進入文件夾時觸發'file-error',      // 文件驗證失敗時觸發'drop',            // 拖拽文件時觸發'view-mode-change' // 視圖模式改變時觸發
]);// 視圖模式
const viewMode = ref(props.defaultViewMode);// 文件輸入引用
const fileInput = ref();
const folderInput = ref();// 選擇文件
const selectFiles = () => {fileInput.value.click();
};// 選擇文件夾
const selectFolder = () => {folderInput.value.click();
};// 格式化文件大小
const formatFileSize = (size) => {if (size < 1024) return size + ' B';if (size < 1024 * 1024) return (size / 1024).toFixed(2) + ' KB';if (size < 1024 * 1024 * 1024) return (size / (1024 * 1024)).toFixed(2) + ' MB';return (size / (1024 * 1024 * 1024)).toFixed(2) + ' GB';
};// 文件樹根節點
const root = ref(buildFileTree([]));
// 當前顯示的目錄
const currentDirectory = ref(root.value);
// 選中的文件
const selectedFiles = ref([]);// 返回上級目錄
const navigateToParent = () => {if (currentDirectory.value.parent) {currentDirectory.value = currentDirectory.value.parent;selectedFiles.value = [];}
};// 監聽視圖模式變化
watch(viewMode, (newMode) => {emit('view-mode-change', newMode);
});// 初始化默認文件
onMounted(() => {if (props.defaultFiles.length) {root.value = buildFileTree(props.defaultFiles);currentDirectory.value = root.value;}
});// 驗證文件
const validateFile = (file) => {// 驗證文件類型if (props.acceptedTypes.length) {const fileType = file.name.split('.').pop()?.toLowerCase();if (!props.acceptedTypes.includes(fileType)) {emit('file-error', {file,error: 'file-type-not-allowed'});return false;}}// 驗證文件大小if (props.maxFileSize && file.size > props.maxFileSize * 1024 * 1024) {emit('file-error', {file,error: 'file-too-large'});return false;}return true;
};// 修改文件選擇處理函數
const handleFileSelect = (event) => {const newFiles = Array.from(event.target.files).filter(validateFile);if (newFiles.length) {root.value = buildFileTree([...root.value.children.map(node => node.file), ...newFiles]);currentDirectory.value = root.value;emit('select', newFiles);}event.target.value = '';
};// 修改文件夾選擇處理函數
const handleFolderSelect = (event) => {const newFiles = Array.from(event.target.files).filter(validateFile);if (newFiles.length) {root.value = buildFileTree([...root.value.children.map(node => node.file), ...newFiles]);currentDirectory.value = root.value;emit('select', newFiles);}event.target.value = '';
};// 修改拖拽處理函數
const handleDrop = (event) => {if (!props.enableDrop) return;const newFiles = Array.from(event.dataTransfer.files).filter(validateFile);if (newFiles.length) {root.value = buildFileTree([...root.value.children.map(node => node.file), ...newFiles]);currentDirectory.value = root.value;emit('drop', newFiles);}
};// 修改文件點擊處理函數
const handleItemClick = (item) => {if (!props.multiple) {selectedFiles.value = [item];} else {const index = selectedFiles.value.indexOf(item);if (index === -1) {selectedFiles.value.push(item);} else {selectedFiles.value.splice(index, 1);}}emit('select', selectedFiles.value);
};// 修改雙擊處理函數
const handleItemDoubleClick = (item) => {if (item.isDirectory) {currentDirectory.value = item;selectedFiles.value = [];emit('enter-directory', item);}
};// 判斷是否為圖片文件
const isImageFile = (file) => {const imageTypes = ['jpg', 'jpeg', 'png', 'gif', 'bmp', 'webp'];const extension = file.name.split('.').pop()?.toLowerCase();return imageTypes.includes(extension);
};// 獲取圖片預覽URL
const getImagePreview = (file) => {if (!file.file) return '';return URL.createObjectURL(file.file);
};// 處理圖片加載錯誤
const handleImageError = (item) => {console.warn(`Failed to load preview for ${item.name}`);// 圖片加載失敗時使用默認圖標return getFileIcon(item);
};// 在組件卸載時清理創建的URL
onUnmounted(() => {currentDirectory.value.children.forEach(item => {if (isImageFile(item)) {URL.revokeObjectURL(getImagePreview(item));}});
});
</script><style scoped>
.file-list-display {width: 100%;height: 100%;border: 1px solid #ddd;border-radius: 4px;
}.toolbar {padding: 10px;border-bottom: 1px solid #ddd;display: flex;justify-content: space-between;align-items: center;
}.view-mode .mode-item {padding: 5px 10px;cursor: pointer;margin-right: 10px;
}.view-mode .mode-item.active {background: #e6f7ff;color: #1890ff;border-radius: 4px;
}.operations button {margin-left: 10px;padding: 5px 15px;background-color: #67c23a;color: white;border: none;border-radius: 4px;cursor: pointer;
}.operations button:hover {background-color: #85ce61;
}.file-container {padding: 20px;min-height: 200px;
}.file-container.list .file-item {display: flex;align-items: center;padding: 10px;border-bottom: 1px solid #eee;
}.file-container.grid {display: grid;grid-template-columns: repeat(auto-fill, minmax(120px, 1fr));gap: 20px;
}.file-container.grid .file-item {text-align: center;padding: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;
}.file-item {cursor: pointer;transition: background-color 0.2s;
}.file-item:hover {background-color: #f5f5f5;
}.file-item.selected {background-color: #e6f7ff;
}.file-icon {width: 60px;height: 60px;padding: 10px 0;display: flex;justify-content: center;align-items: center;
}/* 列表模式下的圖片預覽 */
.file-container.list .file-icon {width: 40px;height: 40px;padding: 2px;margin-right: 10px;
}.file-container.list .image-preview {width: 36px;height: 36px;object-fit: cover;border-radius: 4px;
}.file-container.list .not-image-preview {width: 36px;height: 36px;object-fit: cover;border-radius: 4px;
}/* 網格模式下的圖片預覽 */
.file-container.grid .file-icon {width: 100px;height: 100px;padding: 5px;
}.file-container.grid .image-preview {width: 90px;height: 90px;object-fit: cover;border-radius: 8px;
}.file-container.grid .not-image-preview {width: 90px;height: 90px;object-fit: cover;border-radius: 8px;
}.image-preview {box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);transition: transform 0.2s;
}.image-preview:hover {transform: scale(1.05);
}.file-info {flex: 1;
}.file-name {font-size: 14px;margin-bottom: 4px;word-break: break-all;
}.file-size {font-size: 12px;color: #999;
}.empty-tip {text-align: center;color: #999;padding: 40px 0;
}
</style>

code/src/components/fileIcons.js

const fileIcons = {// 文本文件txt: `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24"><path fill="#4A90E2" d="M14 2H6C4.89 2 4 2.89 4 4V20C4 21.11 4.89 22 6 22H18C19.11 22 20 21.11 20 20V8L14 2ZM16 18H8V16H16V18ZM16 14H8V12H16V14ZM13 9V3.5L18.5 9H13Z"/></svg>`,// 添加新的文件類型圖標exe: `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path fill="#F44336" d="M12,2A10,10 0 0,1 22,12A10,10 0 0,1 12,22A10,10 0 0,1 2,12A10,10 0 0,1 12,2M12,4A8,8 0 0,0 4,12A8,8 0 0,0 12,20A8,8 0 0,0 20,12A8,8 0 0,0 12,4M12,6A6,6 0 0,1 18,12A6,6 0 0,1 12,18A6,6 0 0,1 6,12A6,6 0 0,1 12,6M12,8A4,4 0 0,0 8,12A4,4 0 0,0 12,16A4,4 0 0,0 16,12A4,4 0 0,0 12,8Z"/></svg>`,js: `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path fill="#FFD600" d="M3,3H21V21H3V3M7.73,18.04C8.13,18.89 8.92,19.59 10.27,19.59C11.77,19.59 12.8,18.79 12.8,17.04V11.26H11.1V17C11.1,17.86 10.75,18.08 10.2,18.08C9.62,18.08 9.38,17.68 9.11,17.21L7.73,18.04M13.71,17.86C14.21,18.84 15.22,19.59 16.8,19.59C18.4,19.59 19.6,18.76 19.6,17.23C19.6,15.82 18.79,15.19 17.35,14.57L16.93,14.39C16.2,14.08 15.89,13.87 15.89,13.37C15.89,12.96 16.2,12.64 16.7,12.64C17.18,12.64 17.5,12.85 17.79,13.37L19.1,12.5C18.55,11.54 17.77,11.17 16.7,11.17C15.19,11.17 14.22,12.13 14.22,13.4C14.22,14.78 15.03,15.43 16.25,15.95L16.67,16.13C17.45,16.47 17.91,16.68 17.91,17.26C17.91,17.74 17.46,18.09 16.76,18.09C15.93,18.09 15.45,17.66 15.09,17.06L13.71,17.86Z"/></svg>`,java: `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path fill="#E65100" d="M9.37,17.51C3.4,18.15 3.4,15.82 5,15.82C5,15.82 4.79,15.91 4.79,15.91C4.79,15.91 3,16.12 6.16,17.1C6.16,17.1 9.42,17.58 11.5,16.85C11.5,16.85 11.9,16.65 12.25,16.36C10.45,16.54 9.37,17.51 9.37,17.51M16.21,18.69C16.21,18.69 17.5,19.08 17.5,19.08C17.5,19.08 13.89,19.03 9.29,18.25C9.29,18.25 8.11,17.91 7.25,17.71C7.25,17.71 9.29,18.86 16.21,18.69M11.56,14.3C11.56,14.3 12,14.94 12,14.94C12,14.94 8.4,14.75 5.36,15.61C5.36,15.61 4,16.06 4,16.06C4,16.06 7.09,14.21 11.56,14.3M12.89,11.93C12.89,11.93 13.24,12.32 13.24,12.32C13.24,12.32 9.79,12.23 7.2,13.04C7.2,13.04 5.92,13.45 5.92,13.45C5.92,13.45 8.86,11.85 12.89,11.93M13.5,9.33C13.5,9.33 13.96,9.74 13.96,9.74C13.96,9.74 10.33,9.7 7.85,10.43C7.85,10.43 6.5,10.86 6.5,10.86C6.5,10.86 9.68,9.29 13.5,9.33M14,6.45C14,6.45 14.32,6.85 14.32,6.85C14.32,6.85 10.57,7.04 8.18,7.73C8.18,7.73 6.84,8.15 6.84,8.15C6.84,8.15 10.24,6.62 14,6.45M5.95,10.2L6.31,10.03C6.31,10.03 4.92,10.84 4.92,10.84C4.92,10.84 7.05,9.37 14.14,9.55C14.14,9.55 14.39,9.92 14.39,9.92C14.39,9.92 8.07,9.85 5.95,10.2M5.95,12.66L6.31,12.5C6.31,12.5 4.92,13.3 4.92,13.3C4.92,13.3 7.05,11.83 14.14,12.01C14.14,12.01 14.39,12.38 14.39,12.38C14.39,12.38 8.07,12.31 5.95,12.66M5.95,15.29L6.31,15.12C6.31,15.12 4.92,15.93 4.92,15.93C4.92,15.93 7.05,14.46 14.14,14.64C14.14,14.64 14.39,15.01 14.39,15.01C14.39,15.01 8.07,14.95 5.95,15.29Z"/></svg>`,c: `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path fill="#0277BD" d="M16,2V4H14V2H10V4H8V2H4V22H8V20H10V22H14V20H16V22H20V2H16M18,20H16V18H14V20H10V18H8V20H6V4H8V6H10V4H14V6H16V4H18V20M16,10V8H8V10H16M16,16V14H8V16H16Z"/></svg>`,py: `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path fill="#FFC107" d="M19.14,7.5A2.86,2.86 0 0,1 22,10.36V14.14A2.86,2.86 0 0,1 19.14,17H12C12,17.39 12.32,17.96 12.71,17.96H17V19.64A2.86,2.86 0 0,1 14.14,22.5H9.86A2.86,2.86 0 0,1 7,19.64V15.89C7,14.31 8.28,13.04 9.86,13.04H15.11C16.69,13.04 17.96,11.76 17.96,10.18V7.5H19.14M14.86,19.29C14.46,19.29 14.14,19.59 14.14,20.18C14.14,20.77 14.46,20.89 14.86,20.89A0.71,0.71 0 0,0 15.57,20.18C15.57,19.59 15.25,19.29 14.86,19.29M4.86,17.5C3.28,17.5 2,16.22 2,14.64V10.86C2,9.28 3.28,8 4.86,8H12C12,7.61 11.68,7.04 11.29,7.04H7V5.36C7,3.78 8.28,2.5 9.86,2.5H14.14C15.72,2.5 17,3.78 17,5.36V9.11C17,10.69 15.72,11.96 14.14,11.96H8.89C7.31,11.96 6.04,13.24 6.04,14.82V17.5H4.86M9.14,5.71C9.54,5.71 9.86,5.41 9.86,4.82C9.86,4.23 9.54,4.11 9.14,4.11C8.75,4.11 8.43,4.23 8.43,4.82C8.43,5.41 8.75,5.71 9.14,5.71Z"/></svg>`,cpp: `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path fill="#00897B" d="M10.5,15.97L10.91,18.41C10.65,18.55 10.23,18.68 9.67,18.8C9.1,18.93 8.48,19 7.81,19C6.94,19 6.21,18.84 5.61,18.5C5,18.16 4.53,17.69 4.18,17.07C3.84,16.45 3.67,15.72 3.67,14.88L3.67,14.88V13.69C3.67,12.82 3.85,12.07 4.19,11.45C4.54,10.82 5,10.35 5.59,10.05C6.18,9.75 6.87,9.6 7.65,9.6C8.77,9.6 9.6,9.79 10.13,10.17C10.66,10.55 11,11.11 11.15,11.86L9.97,12.12C9.87,11.69 9.68,11.37 9.39,11.17C9.1,10.97 8.67,10.87 8.11,10.87C7.31,10.87 6.69,11.14 6.27,11.68C5.84,12.22 5.63,12.97 5.63,13.94L5.63,13.94V14.72C5.63,15.71 5.86,16.47 6.32,17.01C6.79,17.55 7.42,17.82 8.21,17.82C8.74,17.82 9.19,17.75 9.57,17.61L9.57,16.47H7.81V15.31H10.5V15.97M20,4C21.1,4 22,4.9 22,6V18C22,19.1 21.1,20 20,20H4C2.9,20 2,19.1 2,18V6C2,4.9 2.9,4 4,4H20M12.63,11.59H14.12V10.09H15.62V11.59H17.12V13.09H15.62V14.59H14.12V13.09H12.63V11.59M16.12,11.59H17.62V10.09H19.12V11.59H20.62V13.09H19.12V14.59H17.62V13.09H16.12V11.59Z"/></svg>`,css: `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path fill="#42A5F5" d="M5,3L4.35,6.34H17.94L17.5,8.5H3.92L3.26,11.83H16.85L16.09,15.64L10.61,17.45L5.86,15.64L6.19,14H2.85L2.06,18L9.91,21L18.96,18L20.16,11.97L20.4,10.76L21.94,3H5Z"/></svg>`,html: `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path fill="#E44D26" d="M12,17.56L16.07,16.43L16.62,10.33H9.38L9.2,8.3H16.8L17,6.31H7L7.56,12.32H14.45L14.22,14.9L12,15.5L9.78,14.9L9.64,13.24H7.64L7.93,16.43L12,17.56M4.07,3H19.93L18.5,19.2L12,21L5.5,19.2L4.07,3Z"/></svg>`,json: `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path fill="#FBC02D" d="M5,3H7V5H5V10A2,2 0 0,1 3,12A2,2 0 0,1 5,14V19H7V21H5C3.93,20.73 3,20.1 3,19V15A2,2 0 0,0 1,13H0V11H1A2,2 0 0,0 3,9V5A2,2 0 0,1 5,3M19,3A2,2 0 0,1 21,5V9A2,2 0 0,0 23,11H24V13H23A2,2 0 0,0 21,15V19A2,2 0 0,1 19,21H17V19H19V14A2,2 0 0,1 21,12A2,2 0 0,1 19,10V5H17V3H19M12,15A1,1 0 0,1 13,16A1,1 0 0,1 12,17A1,1 0 0,1 11,16A1,1 0 0,1 12,15M8,15A1,1 0 0,1 9,16A1,1 0 0,1 8,17A1,1 0 0,1 7,16A1,1 0 0,1 8,15M16,15A1,1 0 0,1 17,16A1,1 0 0,1 16,17A1,1 0 0,1 15,16A1,1 0 0,1 16,15Z"/></svg>`,// Markdown文件md: `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24"><path fill="#7C4DFF" d="M20.56 18H3.44C2.65 18 2 17.37 2 16.59V7.41C2 6.63 2.65 6 3.44 6H20.56C21.35 6 22 6.63 22 7.41V16.59C22 17.37 21.35 18 20.56 18ZM6 12H8V16H10V12H12L9 9L6 12ZM14 16H16V12H18L15 9L12 12H14V16Z"/></svg>`,// PDF文件pdf: `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24"><path fill="#FF5252" d="M14,2L20,8V20A2,2 0 0,1 18,22H6A2,2 0 0,1 4,20V4A2,2 0 0,1 6,2H14M18,20V9H13V4H6V20H18M10.92,12.31C10.68,11.54 10.15,9.08 11.55,9.04C12.95,9 12.03,12.16 12.03,12.16C12.42,13.65 14.05,14.72 14.05,14.72C14.55,14.57 17.4,14.24 17,15.72C16.57,17.2 13.5,15.81 13.5,15.81C11.55,15.95 10.09,16.47 10.09,16.47C8.96,18.58 7.64,19.5 7.1,18.61C6.43,17.5 9.23,16.07 9.23,16.07C10.68,13.72 10.92,12.31 10.92,12.31M11.57,13.15C11.17,14.45 10.37,15.84 10.37,15.84C11.22,15.5 13.08,15.11 13.08,15.11C11.94,14.11 11.57,13.15 11.57,13.15M13.81,15.1C14.05,15.23 15.03,15.63 15.35,15.4C15.67,15.17 14.3,14.96 13.81,15.1M11.33,9.93C10.67,9.89 10.65,10.86 10.76,11.45C10.87,12.04 11.16,11.76 11.16,11.76C11.16,11.76 11.64,9.97 11.33,9.93M9.94,16.61C9.94,16.61 8.7,17.45 8.7,17.71C8.7,17.97 9.45,17.15 9.94,16.61Z"/></svg>`,// 圖片文件png: `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24"><path fill="#4CAF50" d="M19,19H5V5H19M19,3H5A2,2 0 0,0 3,5V19A2,2 0 0,0 5,21H19A2,2 0 0,0 21,19V5A2,2 0 0,0 19,3M13.96,12.29L11.21,15.83L9.25,13.47L6.5,17H17.5L13.96,12.29Z"/></svg>`,jpeg: `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24"><path fill="#FF9800" d="M19,19H5V5H19M19,3H5A2,2 0 0,0 3,5V19A2,2 0 0,0 5,21H19A2,2 0 0,0 21,19V5A2,2 0 0,0 19,3M13.96,12.29L11.21,15.83L9.25,13.47L6.5,17H17.5L13.96,12.29Z"/></svg>`,// Excel文件xlsx: `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24"><path fill="#2E7D32" d="M14,2H6A2,2 0 0,0 4,4V20A2,2 0 0,0 6,22H18A2,2 0 0,0 20,20V8L14,2M15.8,20H14L12,16.6L10,20H8.2L11.1,15.5L8.2,11H10L12,14.4L14,11H15.8L12.9,15.5L15.8,20M13,9V3.5L18.5,9H13Z"/></svg>`,// Word文件docx: `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24"><path fill="#1976D2" d="M14,2H6A2,2 0 0,0 4,4V20A2,2 0 0,0 6,22H18A2,2 0 0,0 20,20V8L14,2M15.2,20H13.8L12,13.2L10.2,20H8.8L6.6,11H8.1L9.5,17.8L11.3,11H12.6L14.4,17.8L15.8,11H17.3L15.2,20M13,9V3.5L18.5,9H13Z"/></svg>`,// 文件夾folder: `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24"><path fill="#FFA000" d="M10,4H4C2.89,4 2,4.89 2,6V18A2,2 0 0,0 4,20H20A2,2 0 0,0 22,18V8C22,6.89 21.1,6 20,6H12L10,4Z"/></svg>`,// 在 fileIcons 對象中添加back: `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24"><path fill="#666666" d="M20,11V13H8L13.5,18.5L12.08,19.92L4.16,12L12.08,4.08L13.5,5.5L8,11H20Z"/></svg>`,// 默認文件圖標default: `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24"><path fill="#757575" d="M14,2H6A2,2 0 0,0 4,4V20A2,2 0 0,0 6,22H18A2,2 0 0,0 20,20V8L14,2M18,20H6V4H13V9H18V20Z"/></svg>`
};// 獲取文件圖標的函數
export function getFileIcon(file) {// 如果是文件夾if (file.type === 'directory') {return `data:image/svg+xml;base64,${btoa(fileIcons.folder)}`;}if (file.type === 'back') {return `data:image/svg+xml;base64,${btoa(fileIcons.back)}`;}// 獲取文件擴展名const extension = file.name.split('.').pop()?.toLowerCase();// 根據文件擴展名返回對應的圖標const iconSvg = fileIcons[extension] || fileIcons.default;return `data:image/svg+xml;base64,${btoa(iconSvg)}`;
}

code/src/components/fileUtils.js

// 文件節點類型
export class FileNode {constructor(file, parent = null) {this.name = file.name;this.size = file.size;this.type = file.type;this.lastModified = file.lastModified;this.isDirectory = file.type === 'directory';this.parent = parent;this.children = [];this.path = file.webkitRelativePath || file.name;this.file = file; // 保存原始文件對象}
}// 構建文件樹
export function buildFileTree(files) {const root = {children: [],isDirectory: true,name: 'root'};for (const file of files) {const paths = file.webkitRelativePath ? file.webkitRelativePath.split('/') : [file.name];let currentNode = root;// 如果是來自文件夾選擇的文件if (paths.length > 1) {// 遍歷路徑創建目錄結構for (let i = 0; i < paths.length - 1; i++) {const dirName = paths[i];let dir = currentNode.children.find(child => child.name === dirName);if (!dir) {dir = new FileNode({name: dirName,type: 'directory',size: 0,lastModified: file.lastModified}, currentNode);currentNode.children.push(dir);}currentNode = dir;}}// 添加文件節點const fileNode = new FileNode(file, currentNode);currentNode.children.push(fileNode);}return root;
}// 計算文件夾大小
export function calculateDirectorySize(node) {if (!node.isDirectory) {return node.size;}return node.children.reduce((total, child) => {return total + calculateDirectorySize(child);}, 0);
}

效果展示

示例頁面
在這里插入圖片描述

圖標模式
在這里插入圖片描述

列表模式
在這里插入圖片描述

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/83277.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/83277.shtml
英文地址,請注明出處:http://en.pswp.cn/web/83277.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

使用QMediaPlayer開發音樂播放器

編譯完成的程序下載:【免費】使用QMediaPlayer開發音樂播放器資源-CSDN文庫 完整源碼:使用QMediaPlayer開發音樂播放器源碼資源-CSDN文庫 需求分析: 1.本地音樂播放器 核心播放功能 支持常見音頻格式本地播放MP3、WAV、FLAC 等 2.播放控制:播放 / 暫停 / 停止 / 上一曲…

Linux-07 ubuntu 的 chrome 啟動不了

文章目錄 問題原因解決步驟一、卸載舊版chrome二、重新安裝chorme三、啟動不了&#xff0c;報錯如下四、啟動不了&#xff0c;解決如下 總結 問題原因 在應用中可以看到chrome&#xff0c;但是打不開(說明&#xff1a;原來的ubuntu系統出問題了&#xff0c;這個是備用的硬盤&a…

【Redis】緩存雪崩、緩存擊穿、緩存穿透

目錄 1、緩存雪崩【1】定義【2】原因【3】解決方案[1]差異化過期時間[2]多級緩存[3]熔斷降級[4]緩存永不過期異步更新 2、緩存擊穿【1】定義【2】原因【3】解決方案[1]互斥鎖[2]邏輯過期[3]熱點數據加載 3、緩存穿透【1】定義【2】原因【3】解決方案[1]緩存空對象[2]布隆過濾器…

【論文閱讀筆記】萬花筒:用于異構多智能體強化學習的可學習掩碼

摘要 在多智能體強化學習&#xff08;MARL&#xff09;中&#xff0c;通常采用參數共享來提高樣本效率。然而&#xff0c;全參數共享的流行方法通常會導致智能體之間的策略同質&#xff0c;這可能會限制從策略多樣性中獲得的性能優勢。為了解決這一關鍵限制&#xff0c;我們提出…

vue2 , el-select 多選樹結構,可重名

人家antd都支持&#xff0c;elementplus 也支持&#xff0c;vue2的沒有&#xff0c;很煩。 網上其實可以搜到各種的&#xff0c;不過大部分不支持重名&#xff0c;在刪除的時候可能會刪錯&#xff0c;比如樹結構1F的1樓啊&#xff0c;2F的1樓啊這種同時勾選的情況。。 可以全…

golang循環變量捕獲問題??

在 Go 語言中&#xff0c;當在循環中啟動協程&#xff08;goroutine&#xff09;時&#xff0c;如果在協程閉包中直接引用循環變量&#xff0c;可能會遇到一個常見的陷阱 - ??循環變量捕獲問題??。讓我詳細解釋一下&#xff1a; 問題背景 看這個代碼片段&#xff1a; fo…

【一文看懂Spring循環依賴】Spring循環依賴:從陷阱破局到架構涅槃

&#x1f32a;? Spring Boot循環依賴&#xff1a;從陷阱破局到架構涅槃 循環依賴如同莫比烏斯環上的螞蟻&#xff0c;看似前進卻永遠困在閉環中。本文將帶你拆解Spring中這一經典難題&#xff0c;從臨時救火到根治重構&#xff0c;構建無懈可擊的依賴體系。 &#x1f525; 一、…

el-table封裝自動滾動表格(適用大屏)

表格功能&#xff1a;自動滾動&#xff0c;鼠標移入停止滾動&#xff0c;移出繼續滾動。如果想加觸底加載新數據可以判斷 scrollWrap.scrollTop和maxScrollTop大小來加載數據&#xff0c;另寫邏輯。 <template><el-table ref"eltable" :data"tableDa…

Eureka REST 相關接口

可供非 Java 應用程序使用的 Eureka REST 操作。 appID 是應用程序的名稱&#xff0c;instanceID 是與實例關聯的唯一標識符。在 AWS 云中&#xff0c;instanceID 是實例的實例 ID&#xff1b;在其他數據中心&#xff0c;它是實例的主機名。 對于 XML/JSON&#xff0c;HTTP 的…

DSP——時鐘樹講解

配置任何外設的第一步都要看一下時鐘樹,下圖是DSP28377的時鐘樹: 由圖所示DSP28377由4個時鐘源,分別是INTOSC1、INTOSC2、XTAL、AUXCL INTOSC1:0M內部系統時鐘,備用時鐘,檢測到系統時鐘缺失自動連接到備用時鐘,也作為看門狗時鐘使用; INTOSC2:10M內部系統時鐘,復位…

少量數據達到更好效果

九坤團隊新作&#xff01;一條數據訓練AI超越上萬條數據 一 僅需一條無標簽數據和10步優化 九坤團隊訓練了13,440個大模型&#xff0c;發現熵最小化 (EM) 僅需一條無標簽數據和10步優化&#xff0c;就能實現與強化學習中使用成千上萬條數據和精心設計的獎勵機制所取得的性能提…

html - <mark>標簽

<mark> 標簽在HTML中用于高亮顯示文本&#xff0c;通常用于突出顯示某些重要的部分。它的默認樣式通常是背景色為黃色&#xff0c;但你可以通過CSS自定義其外觀。 1. 基本用法 <mark> 標簽用于標記文本的高亮顯示。它常用于搜索結果中&#xff0c;突出顯示匹配的…

YOLOv8+ByteTrack:高精度人車過線統計系統搭建指南

文章目錄 1. 引言2. YOLOv8簡介3. 過線統計原理4. 代碼實現4.1 環境準備4.2 基礎檢測代碼4.3 過線統計實現4.4 完整代碼示例5. 性能優化與改進5.1 多線程處理5.2 區域檢測優化5.3 使用ByteTrack改進跟蹤6. 實際應用中的挑戰與解決方案7. 總結與展望1. 引言 目標檢測是計算機視…

20、React常用API和Hook索引

這一小節中只給出一些API和Hook的索引&#xff0c;需要用到的時候可以去官網查詢&#xff0c;如無必要此處不列出詳細用法。React v1.19.1。 對Components的支持 以下是開發時通用的一些功能組件 APIdescription<Fragment>通常使用 <>…</> 代替&#xff0…

Python爬蟲實戰:研究feedparser庫相關技術

1. 引言 1.1 研究背景與意義 在當今信息爆炸的時代,互聯網上存在著海量的信息資源。RSS(Really Simple Syndication)作為一種標準化的信息聚合技術,被廣泛用于網站內容的發布和訂閱。通過 RSS,用戶可以方便地獲取網站更新的內容,而無需頻繁訪問各個網站。 然而,互聯網…

HTML實現的2048游戲

以下是一個純HTML實現的2048游戲代碼&#xff0c;包含CSS和JavaScript&#xff1a; <!DOCTYPE html> <html> <head><meta charset"utf-8"><title>2048 Game</title><style>body {font-family: Arial, sans-serif;text-a…

使用Python 構建支持主流大模型與 Ollama 的統一接口平臺

?? 背景概述 近年來,隨著大語言模型(LLM)的蓬勃發展,OpenAI 的 GPT 系列、Google 的 Gemini、Anthropic 的 Claude、以及開源的 Ollama 本地模型等,逐漸成為自然語言處理、智能問答、AI 助手等應用的基礎組件。 開發者在使用這些模型時常面臨如下問題: 各模型接口不統…

計算機系統概述(4)

計算機系統層次結構&#xff1a;硬件層、系統層、應用層。 計算機的基本硬件系統由運算器、控制器、存儲器、輸入設備和輸出設備5大部件組成。 運算器、控制器等部件被集成在一起統稱為中央處理單元CPU。 存儲器是計算機系統中的記憶設備&#xff0c;分為內部存儲器和外部存…

Linux 下的COW機制(copy-on-write)

Linux通過MMU進行虛擬地址到物理地址的轉換&#xff0c;當進程執行fork()后&#xff0c;會把頁中的權限設置為RD-ONLY&#xff08;只讀&#xff09;。 MMU&#xff08;內存管理單元&#xff09; MMU本質是一個集成在CPU核心的硬件電路模塊&#xff0c;其核心任務是實現…

客戶案例 | 短視頻點播企業海外視頻加速與成本優化:MediaPackage+Cloudfront 技術重構實踐

01技術背景與業務挑戰 某短視頻點播企業深耕國內用戶市場&#xff0c;但其后臺應用系統部署于東南亞印尼 IDC 機房。 隨著業務規模擴大&#xff0c;傳統架構已較難滿足當前企業發展的需求&#xff0c;企業面臨著三重挑戰&#xff1a; ① 業務&#xff1a;國內用戶訪問海外服…