refactor(system/file): 重构文件管理相关代码

This commit is contained in:
2025-05-15 23:18:02 +08:00
parent dc66e9e62c
commit b680ee3fac
11 changed files with 55 additions and 62 deletions

View File

@@ -32,5 +32,5 @@ export function checkFile(sha256: string) {
/** @desc 创建文件夹 */
export function createDir(path: string, name: string) {
return http.post<T.FileItem>(`${BASE_URL}/createDir`, { parentPath: path, name })
return http.post<T.FileItem>(`${BASE_URL}/dir`, { path, originalName: name })
}

View File

@@ -202,24 +202,25 @@ export interface NoticePageQuery extends NoticeQuery, PageQuery {
export interface FileItem {
id: string
name: string
originalName: string
size: number
url: string
parentPath: string
absPath: string
metadata: string
path: string
sha256: string
contentType: string
metadata: string
thumbnailSize: number
thumbnailUrl: string
thumbnailName: string
thumbnailMetadata: string
thumbnailUrl: string
extension: string
type: number
storageId: string
storageName: string
createUserString: string
createTime: string
updateUserString: string
updateTime: string
updateUserString?: string
updateTime?: string
}
/** 文件资源统计信息 */
export interface FileStatisticsResp {
@@ -230,9 +231,9 @@ export interface FileStatisticsResp {
data: Array<FileStatisticsResp>
}
export interface FileQuery {
name?: string
originalName?: string
type?: string
absPath?: string
path?: string
sort: Array<string>
}
export interface FilePageQuery extends FileQuery, PageQuery {

View File

@@ -101,7 +101,7 @@ const columns: ColumnItem[] = reactive([
field: 'domain',
type: 'input',
span: 24,
required: true,
required: false,
show: () => form.type === 2,
},
{

View File

@@ -5,7 +5,7 @@
<div ref="audioHeadRef" class="audio-box__header">
<div class="audio-name">
<icon-music :size="16" spin />
<span>{{ props.data?.name }}.{{ props.data?.extension }}</span>
<span>{{ props.data?.originalName }}</span>
</div>
<div class="close-icon" @click="close">
<icon-close :size="12" />

View File

@@ -9,14 +9,19 @@
<a-descriptions-item label="名称">
<a-typography-paragraph copyable :copy-text="data.url">
<template #copy-tooltip>复制链接</template>
{{ getFileName(data) }}
{{ data.originalName }}
</a-typography-paragraph>
</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="SHA256">{{ data.sha256 }}</a-descriptions-item>
<a-descriptions-item label="路径">{{ `${data.path === '/' ? '' : data.path}/${data.name}` }}</a-descriptions-item>
<a-descriptions-item v-if="data.sha256" label="SHA256">
<a-typography-paragraph copyable :copy-text="data.sha256">
<template #copy-tooltip>复制</template>
{{ data.sha256 }}
</a-typography-paragraph>
</a-descriptions-item>
<a-descriptions-item label="上传时间">{{ data.createTime }}</a-descriptions-item>
<a-descriptions-item label="修改时间">{{ data.updateTime }}</a-descriptions-item>
<a-descriptions-item v-if="data?.updateTime" label="修改时间">{{ data?.updateTime }}</a-descriptions-item>
<a-descriptions-item label="存储名称">{{ data.storageName }}</a-descriptions-item>
</a-descriptions>
</a-row>
@@ -32,11 +37,6 @@ interface Props {
}
withDefaults(defineProps<Props>(), {})
// 文件名称带后缀
const getFileName = (item: FileItem) => {
return `${item.name}${item.extension ? `.${item.extension}` : ''}`
}
</script>
<style lang="less" scoped>

View File

@@ -3,11 +3,11 @@
<a-form ref="formRef" :model="form" auto-label-width class="w-full">
<a-form-item
label="文件名称"
field="name"
field="originalName"
:rules="[{ required: true, message: '请输入文件名称' }]"
style="margin-bottom: 0"
>
<a-input v-model="form.name" placeholder="请输入文件名称" allow-clear />
<a-input v-model="form.originalName" placeholder="请输入文件名称" allow-clear />
</a-form-item>
</a-form>
</a-row>
@@ -24,7 +24,7 @@ const props = withDefaults(defineProps<Props>(), {})
const formRef = ref<FormInstance>()
const form = reactive({
name: props.data?.name || '',
originalName: props.data?.originalName || '',
})
defineExpose({ formRef })

View File

@@ -21,7 +21,7 @@ export function openFileRenameModal(data: FileItem, callback?: () => void) {
const isInvalid = await ModalContentRef.value?.formRef?.validate()
const modelParams = ModalContentRef.value?.formRef?.model
if (isInvalid) return false
await updateFile({ name: modelParams?.name }, data.id)
await updateFile({ originalName: modelParams?.originalName }, data.id)
Message.success('重命名成功')
if (callback) {
callback()

View File

@@ -16,9 +16,9 @@
<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>
<FileImage :data="item" :title="item.originalName"></FileImage>
</div>
<p class="gi_line_1 file-name">{{ getFileName(item) }}</p>
<p class="gi_line_1 file-name">{{ item.originalName }}</p>
</section>
<!-- 勾选模式 -->
<section
@@ -64,11 +64,6 @@ interface Props {
isBatchMode?: boolean
}
// 文件名称带后缀
const getFileName = (item: FileItem) => {
return `${item.name}${item.extension ? `.${item.extension}` : ''}`
}
// 点击事件
const handleClickFile = (item: FileItem) => {
emit('click', item)

View File

@@ -15,13 +15,17 @@ const props = withDefaults(defineProps<Props>(), {})
// 是否是图片类型文件
const isImage = computed(() => {
const extension = props.data.extension.toLowerCase()
const extension = props.data.extension?.toLowerCase()
return ImageTypes.includes(extension)
})
// 获取文件图标,如果是图片就显示图片
const getFileImg = computed<string>(() => {
const extension = props.data.extension.toLowerCase()
// 文件夹
if (props.data.type === 0) {
return FileIcon.dir
}
const extension = props.data.extension?.toLowerCase()
if (ImageTypes.includes(extension)) {
return props.data.url || ''
}

View File

@@ -30,7 +30,7 @@
</div>
<a-typography-paragraph copyable :copy-text="record.url">
<template #copy-tooltip>复制链接</template>
{{ getFileName(record) }}
{{ record.originalName }}
</a-typography-paragraph>
</section>
<template #content>
@@ -90,11 +90,6 @@ interface Props {
isBatchMode?: boolean
}
// 文件名称带后缀
const getFileName = (item: FileItem) => {
return `${item.name}${item.extension ? `.${item.extension}` : ''}`
}
const rowSelection: TableRowSelection = reactive({
type: 'checkbox',
showCheckedAll: true,

View File

@@ -38,7 +38,7 @@
<icon-delete />
</template>
</a-button>
<a-button type="primary" :disabled="!queryForm.absPath" @click="createDirModalVisible = !createDirModalVisible">
<a-button type="primary" :disabled="!queryForm.path" @click="createDirModalVisible = !createDirModalVisible">
<template #icon>
<icon-folder />
</template>
@@ -105,7 +105,7 @@ import FileGrid from './FileGrid.vue'
import useFileManage from './useFileManage'
import { useTable } from '@/hooks'
import { type FileItem, type FileQuery, createDir, deleteFile, listFile, uploadFile } from '@/apis'
import { DirTypes, ImageTypes, OfficeTypes } from '@/constant/file'
import { ImageTypes, OfficeTypes } from '@/constant/file'
import 'viewerjs/dist/viewer.css'
import { downloadByUrl } from '@/utils/downloadFile'
import mittBus from '@/utils/mitt'
@@ -119,12 +119,12 @@ const { mode, selectedFileIds, toggleMode, addSelectedFileItem } = useFileManage
const queryTypeOption = [{
label: '文件名',
value: 'name',
value: 'originalName',
}, {
label: '路径',
value: 'absPath',
value: 'path',
}]
const queryType = ref<string>('name')
const queryType = ref<string>('originalName')
// 新建文件夹弹窗显示
const createDirModalVisible = ref<boolean>(false)
@@ -132,15 +132,15 @@ const createDirModalVisible = ref<boolean>(false)
const newDirName = ref()
const queryForm = reactive<FileQuery>({
name: undefined,
absPath: '/',
type: route.query.type?.toString() !== '0' ? route.query.type?.toString() : undefined,
sort: ['updateTime,desc'],
originalName: undefined,
path: (!route.query.type || route.query.type?.toString() === '0') ? '/' : undefined,
type: route.query.type?.toString() && route.query.type?.toString() !== '0' ? route.query.type?.toString() : undefined,
sort: ['type,asc', 'updateTime,desc'],
})
const reset = () => {
queryForm.name = undefined
queryForm.absPath = undefined
queryForm.originalName = undefined
queryForm.path = undefined
}
const paginationOption = reactive({
@@ -186,7 +186,7 @@ const handleClickFile = (item: FileItem) => {
},
}
filePreviewRef.value.onPreview({
fileInfo: { data: item.url, fileName: item.name, fileType: item.extension },
fileInfo: { data: item.url, fileName: item.originalName, fileType: item.extension },
excelConfig,
})
}
@@ -200,12 +200,8 @@ const handleClickFile = (item: FileItem) => {
// 双击文件
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}`
}
if (item.type === 0) {
queryForm.path = `${item.path === '/' ? '' : item.path}/${item.name}`
search()
}
}
@@ -215,7 +211,7 @@ const onDownload = async (fileInfo: FileItem) => {
const res = await downloadByUrl({
url: fileInfo.url,
target: '_self',
fileName: `${fileInfo.name}.${fileInfo.extension}`,
fileName: fileInfo.originalName,
})
res ? Message.success('下载成功') : Message.error('下载失败')
search()
@@ -226,7 +222,7 @@ const handleRightMenuClick = async (mode: string, fileInfo: FileItem) => {
if (mode === 'delete') {
Modal.warning({
title: '提示',
content: `是否确定删除文件${fileInfo.name}」?`,
content: `是否确定删除${fileInfo.type === 0 ? '文件夹' : '文件'}${fileInfo.originalName}」?`,
hideCancel: false,
okButtonProps: { status: 'danger' },
onOk: async () => {
@@ -273,7 +269,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('path', queryForm.path ?? '/')
formData.append(name as string, fileItem.file as Blob)
try {
const res = await uploadFile(formData)
@@ -295,10 +291,12 @@ const handleUpload = (options: RequestOption) => {
onBeforeRouteUpdate((to) => {
if (!to.query.type) return
if (to.query.type === '0') {
if (to.query.type === '0' || !to.query.type) {
queryForm.type = undefined
queryForm.path = '/'
} else {
queryForm.type = to.query.type?.toString()
queryForm.path = undefined
}
search()
@@ -312,7 +310,7 @@ const handleCancel = () => {
// 新建文件夹弹窗窗口确认事件
const handleCreateDir = async () => {
await createDir(queryForm.absPath ?? '/', newDirName.value)
await createDir(queryForm.path ?? '/', newDirName.value)
newDirName.value = undefined
createDirModalVisible.value = false
search()