mirror of
https://github.com/continew-org/continew-admin-ui.git
synced 2025-09-08 22:57:11 +08:00
feat: 文件管理呈目录形式展示 (#60)
This commit is contained in:
@@ -24,3 +24,13 @@ export function deleteFile(id: string) {
|
||||
export function getFileStatistics() {
|
||||
return http.get<T.FileStatisticsResp>(`${BASE_URL}/statistics`)
|
||||
}
|
||||
|
||||
/** @desc 根据sha256检测文件是否已经在服务器存在 */
|
||||
export function checkFile(sha256: string) {
|
||||
return http.get<T.FileItem>(`${BASE_URL}/check`, { fileHash: sha256 })
|
||||
}
|
||||
|
||||
/** @desc 创建文件夹 */
|
||||
export function createDir(path: string, name: string) {
|
||||
return http.post<T.FileItem>(`${BASE_URL}/createDir`, { parentPath: path, name })
|
||||
}
|
||||
|
@@ -207,7 +207,7 @@ export interface FileItem {
|
||||
parentPath: string
|
||||
absPath: string
|
||||
metadata: string
|
||||
md5: string
|
||||
sha256: string
|
||||
contentType: string
|
||||
thumbnailSize: number
|
||||
thumbnailUrl: string
|
||||
|
@@ -46,3 +46,5 @@ export const OfficeTypes = ['ppt', 'pptx', 'doc', 'docx', 'xls', 'xlsx', 'pdf']
|
||||
export const WordTypes = ['doc', 'docx']
|
||||
|
||||
export const ExcelTypes = ['xls', 'xlsx']
|
||||
|
||||
export const DirTypes = ['dir']
|
||||
|
@@ -14,7 +14,7 @@
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="大小">{{ formatFileSize(data.size) }}</a-descriptions-item>
|
||||
<a-descriptions-item label="路径">{{ data.absPath + getFileName(data) }}</a-descriptions-item>
|
||||
<a-descriptions-item label="MD5">{{ data.md5 }}</a-descriptions-item>
|
||||
<a-descriptions-item label="SHA256">{{ data.sha256 }}</a-descriptions-item>
|
||||
<a-descriptions-item label="上传时间">{{ data.createTime }}</a-descriptions-item>
|
||||
<a-descriptions-item label="修改时间">{{ data.updateTime }}</a-descriptions-item>
|
||||
<a-descriptions-item label="存储名称">{{ data.storageName }}</a-descriptions-item>
|
||||
|
@@ -13,7 +13,7 @@
|
||||
scroll-to-close
|
||||
>
|
||||
<a-grid-item>
|
||||
<div class="file-grid-item" @click.stop="handleClickFile(item)">
|
||||
<div class="file-grid-item" @click.stop="handleClickFile(item)" @dblclick="handleDblclickFile(item)">
|
||||
<section class="file-grid-item__wrapper">
|
||||
<div class="file-icon">
|
||||
<FileImage :data="item" :title="item.name"></FileImage>
|
||||
@@ -51,6 +51,7 @@ const props = withDefaults(defineProps<Props>(), {
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: 'click', record: FileItem): void
|
||||
(e: 'dblclick', record: FileItem): void
|
||||
(e: 'select', record: FileItem): void
|
||||
(e: 'right-menu-click', mode: string, item: FileItem): void
|
||||
}>()
|
||||
@@ -73,6 +74,11 @@ const handleClickFile = (item: FileItem) => {
|
||||
emit('click', item)
|
||||
}
|
||||
|
||||
// 双击事件
|
||||
const handleDblclickFile = (item: FileItem) => {
|
||||
emit('dblclick', item)
|
||||
}
|
||||
|
||||
// 选中事件
|
||||
const handleCheckFile = (item: FileItem) => {
|
||||
emit('select', item)
|
||||
|
@@ -34,7 +34,7 @@
|
||||
</a-typography-paragraph>
|
||||
</section>
|
||||
<template #content>
|
||||
<FileRightMenu :data="record" @click="handleRightMenuClick($event, record)"></FileRightMenu>
|
||||
<FileRightMenu :data="record" @click="handleRightMenuClick($event, record)" @dblclick="handleDblclickFile(record)"></FileRightMenu>
|
||||
</template>
|
||||
</a-trigger>
|
||||
</template>
|
||||
@@ -77,6 +77,7 @@ const props = withDefaults(defineProps<Props>(), {
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: 'click', record: FileItem): void
|
||||
(e: 'dblclick', record: FileItem): void
|
||||
(e: 'select', record: FileItem): void
|
||||
(e: 'right-menu-click', mode: string, item: FileItem): void
|
||||
}>()
|
||||
@@ -109,6 +110,11 @@ const handleRowClick: TableInstance['onRowClick'] = (record) => {
|
||||
emit('click', record as unknown as FileItem)
|
||||
}
|
||||
|
||||
// 双击事件
|
||||
const handleDblclickFile = (item: FileItem) => {
|
||||
emit('dblclick', item)
|
||||
}
|
||||
|
||||
// 右键菜单点击事件
|
||||
const handleRightMenuClick = (mode: string, item: FileItem) => {
|
||||
emit('right-menu-click', mode, item)
|
||||
|
@@ -38,6 +38,12 @@
|
||||
<icon-delete />
|
||||
</template>
|
||||
</a-button>
|
||||
<a-button type="primary" :disabled="!queryForm.absPath" @click="createDirModalVisible = !createDirModalVisible">
|
||||
<template #icon>
|
||||
<icon-folder />
|
||||
</template>
|
||||
<template #default>新建文件夹</template>
|
||||
</a-button>
|
||||
<a-button type="primary" @click="isBatchMode = !isBatchMode">
|
||||
<template #icon>
|
||||
<icon-select-all />
|
||||
@@ -62,14 +68,14 @@
|
||||
<FileGrid
|
||||
v-show="fileList.length && mode === 'grid'" :data="fileList" :is-batch-mode="isBatchMode"
|
||||
:selected-file-ids="selectedFileIds" @click="handleClickFile" @select="handleSelectFile"
|
||||
@right-menu-click="handleRightMenuClick"
|
||||
@right-menu-click="handleRightMenuClick" @dblclick="handleDblclickFile"
|
||||
></FileGrid>
|
||||
|
||||
<!-- 文件列表-列表模式 -->
|
||||
<FileList
|
||||
v-show="fileList.length && mode === 'list'" :data="fileList" :is-batch-mode="isBatchMode"
|
||||
:selected-file-ids="selectedFileIds" @click="handleClickFile" @select="handleSelectFile"
|
||||
@right-menu-click="handleRightMenuClick"
|
||||
@right-menu-click="handleRightMenuClick" @dblclick="handleDblclickFile"
|
||||
></FileList>
|
||||
|
||||
<a-empty v-if="!fileList.length" />
|
||||
@@ -78,6 +84,11 @@
|
||||
<div class="pagination">
|
||||
<a-pagination v-bind="pagination" />
|
||||
</div>
|
||||
|
||||
<!-- 弹出新建窗口 -->
|
||||
<a-modal v-model:visible="createDirModalVisible" title="新建文件夹" @ok="handleCreateDir" @cancel="handleCancel">
|
||||
<a-input v-model="newDirName" placeholder="请输入文件夹名称" size="large" allow-clear />
|
||||
</a-modal>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -93,8 +104,8 @@ import {
|
||||
import FileGrid from './FileGrid.vue'
|
||||
import useFileManage from './useFileManage'
|
||||
import { useTable } from '@/hooks'
|
||||
import { type FileItem, type FileQuery, deleteFile, listFile, uploadFile } from '@/apis'
|
||||
import { ImageTypes, OfficeTypes } from '@/constant/file'
|
||||
import { type FileItem, type FileQuery, checkFile, createDir, deleteFile, listFile, uploadFile } from '@/apis'
|
||||
import { DirTypes, ImageTypes, OfficeTypes } from '@/constant/file'
|
||||
import 'viewerjs/dist/viewer.css'
|
||||
import { downloadByUrl } from '@/utils/downloadFile'
|
||||
import mittBus from '@/utils/mitt'
|
||||
@@ -114,9 +125,15 @@ const queryTypeOption = [{
|
||||
value: 'absPath',
|
||||
}]
|
||||
const queryType = ref<string>('name')
|
||||
|
||||
// 新建文件夹弹窗显示
|
||||
const createDirModalVisible = ref<boolean>(false)
|
||||
// 新文件名称
|
||||
const newDirName = ref()
|
||||
|
||||
const queryForm = reactive<FileQuery>({
|
||||
name: undefined,
|
||||
absPath: undefined,
|
||||
absPath: '/',
|
||||
type: route.query.type?.toString() !== '0' ? route.query.type?.toString() : undefined,
|
||||
sort: ['updateTime,desc'],
|
||||
})
|
||||
@@ -180,6 +197,19 @@ const handleClickFile = (item: FileItem) => {
|
||||
previewFileAudioModal(item)
|
||||
}
|
||||
}
|
||||
|
||||
// 双击文件
|
||||
const handleDblclickFile = (item: FileItem) => {
|
||||
if (DirTypes.includes(item.extension)) {
|
||||
if (item.absPath.endsWith('/')) {
|
||||
queryForm.absPath = item.absPath + item.name
|
||||
} else {
|
||||
queryForm.absPath = `${item.absPath}/${item.name}`
|
||||
}
|
||||
search()
|
||||
}
|
||||
}
|
||||
|
||||
// 下载文件
|
||||
const onDownload = async (fileInfo: FileItem) => {
|
||||
const res = await downloadByUrl({
|
||||
@@ -242,6 +272,7 @@ const handleUpload = (options: RequestOption) => {
|
||||
const { onProgress, onError, onSuccess, fileItem, name = 'file' } = options
|
||||
onProgress(20)
|
||||
const formData = new FormData()
|
||||
formData.append('path', queryForm.absPath ?? '/')
|
||||
formData.append(name as string, fileItem.file as Blob)
|
||||
try {
|
||||
const res = await uploadFile(formData)
|
||||
@@ -272,6 +303,20 @@ onBeforeRouteUpdate((to) => {
|
||||
search()
|
||||
})
|
||||
|
||||
// 新建文件夹弹窗窗口取消事件
|
||||
const handleCancel = () => {
|
||||
newDirName.value = undefined
|
||||
createDirModalVisible.value = false
|
||||
}
|
||||
|
||||
// 新建文件夹弹窗窗口确认事件
|
||||
const handleCreateDir = async () => {
|
||||
const res = await createDir(queryForm.absPath ?? '/', newDirName.value)
|
||||
newDirName.value = undefined
|
||||
createDirModalVisible.value = false
|
||||
search()
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
search()
|
||||
})
|
||||
|
Reference in New Issue
Block a user