mirror of
https://github.com/continew-org/continew-admin-ui.git
synced 2025-09-09 20:57:17 +08:00
refactor(system/file): 重构文件管理相关代码
This commit is contained in:
@@ -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 })
|
||||
}
|
||||
|
@@ -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 {
|
||||
|
@@ -101,7 +101,7 @@ const columns: ColumnItem[] = reactive([
|
||||
field: 'domain',
|
||||
type: 'input',
|
||||
span: 24,
|
||||
required: true,
|
||||
required: false,
|
||||
show: () => form.type === 2,
|
||||
},
|
||||
{
|
||||
|
@@ -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" />
|
||||
|
@@ -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>
|
||||
|
@@ -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 })
|
||||
|
@@ -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()
|
||||
|
@@ -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)
|
||||
|
@@ -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 || ''
|
||||
}
|
||||
|
@@ -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,
|
||||
|
@@ -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()
|
||||
|
Reference in New Issue
Block a user