更新 FileList.vue、FileNavigator.vue 和 FileToolbar.vue 中 axios 属性的类型定义为 Function

This commit is contained in:
jxxghp
2025-06-30 19:39:02 +08:00
parent 60ea884fe2
commit 18cf1ea3d7
3 changed files with 193 additions and 187 deletions
+191 -185
View File
@@ -24,7 +24,7 @@ const inProps = defineProps({
storage: String, storage: String,
endpoints: Object as PropType<EndPoints>, endpoints: Object as PropType<EndPoints>,
axios: { axios: {
type: Object as PropType<any>, type: Function,
required: true, required: true,
}, },
refreshpending: Boolean, refreshpending: Boolean,
@@ -554,196 +554,202 @@ onMounted(() => {
</script> </script>
<template> <template>
<VCard class="d-flex flex-column w-full h-full rounded-t-0" :class="{ 'rounded-s-0': showTree }"> <div>
<div v-if="!loading" class="flex"> <VCard class="d-flex flex-column w-full h-full rounded-t-0" :class="{ 'rounded-s-0': showTree }">
<IconBtn v-if="display.mdAndUp.value"> <div v-if="!loading" class="flex">
<VIcon v-if="showTree" icon="mdi-file-tree" @click="switchFileTree(false)" /> <IconBtn v-if="display.mdAndUp.value">
<VIcon v-else icon="mdi-file-tree-outline" @click="switchFileTree(true)" /> <VIcon v-if="showTree" icon="mdi-file-tree" @click="switchFileTree(false)" />
</IconBtn> <VIcon v-else icon="mdi-file-tree-outline" @click="switchFileTree(true)" />
<VTextField
v-if="!isFile"
v-model="filter"
hide-details
flat
density="compact"
variant="plain"
:placeholder="t('common.search')"
prepend-inner-icon="mdi-filter-outline"
class="mx-2"
rounded
/>
<VSpacer v-if="isFile" />
<IconBtn v-if="!isFile" @click="changeSelectMode">
<VIcon color="primary" v-if="selectMode"> mdi-selection-remove </VIcon>
<VIcon color="primary" v-else>mdi-select</VIcon>
</IconBtn>
<IconBtn v-if="isFile" @click="recognize(inProps.item.path || '')">
<VIcon color="primary"> mdi-text-recognition </VIcon>
</IconBtn>
<IconBtn v-if="isFile && items.length > 0" @click="download(items[0])">
<VIcon color="primary"> mdi-download </VIcon>
</IconBtn>
<IconBtn v-if="!isFile" @click="list_files">
<VIcon color="primary"> mdi-refresh </VIcon>
</IconBtn>
<!-- 批量操作按钮 -->
<span v-if="selected.length > 0">
<IconBtn @click.stop="batchScrape">
<VIcon color="primary" icon="mdi-auto-fix" />
</IconBtn> </IconBtn>
<IconBtn @click.stop="showBatchTransfer"> <VTextField
<VIcon color="primary" icon="mdi-folder-arrow-right" /> v-if="!isFile"
v-model="filter"
hide-details
flat
density="compact"
variant="plain"
:placeholder="t('common.search')"
prepend-inner-icon="mdi-filter-outline"
class="mx-2"
rounded
/>
<VSpacer v-if="isFile" />
<IconBtn v-if="!isFile" @click="changeSelectMode">
<VIcon color="primary" v-if="selectMode"> mdi-selection-remove </VIcon>
<VIcon color="primary" v-else>mdi-select</VIcon>
</IconBtn> </IconBtn>
<IconBtn @click.stop="batchDelete"> <IconBtn v-if="isFile" @click="recognize(inProps.item.path || '')">
<VIcon icon="mdi-delete-outline" color="error" /> <VIcon color="primary"> mdi-text-recognition </VIcon>
</IconBtn> </IconBtn>
</span> <IconBtn v-if="isFile && items.length > 0" @click="download(items[0])">
</div> <VIcon color="primary"> mdi-download </VIcon>
<LoadingBanner v-if="loading" /> </IconBtn>
<!-- 文件详情 --> <IconBtn v-if="!isFile" @click="list_files">
<VCardText v-else-if="isFile && !isImage && items.length > 0" class="text-center break-all"> <VIcon color="primary"> mdi-refresh </VIcon>
<div v-if="items[0]?.thumbnail" class="flex justify-center"> </IconBtn>
<VImg max-width="15rem" cover :src="items[0]?.thumbnail" class="rounded border"> <!-- 批量操作按钮 -->
<template #placeholder> <span v-if="selected.length > 0">
<VSkeletonLoader class="object-cover w-full h-full" /> <IconBtn @click.stop="batchScrape">
</template> <VIcon color="primary" icon="mdi-auto-fix" />
</VImg> </IconBtn>
<IconBtn @click.stop="showBatchTransfer">
<VIcon color="primary" icon="mdi-folder-arrow-right" />
</IconBtn>
<IconBtn @click.stop="batchDelete">
<VIcon icon="mdi-delete-outline" color="error" />
</IconBtn>
</span>
</div> </div>
<div class="text-xl text-high-emphasis mt-3">{{ items[0]?.name }}</div> <LoadingBanner v-if="loading" />
<p class="mt-2" v-if="items[0]?.size && items[0].modify_time"> <!-- 文件详情 -->
{{ t('file.size') }}{{ formatBytes(items[0]?.size || 0) }}<br /> <VCardText v-else-if="isFile && !isImage && items.length > 0" class="text-center break-all">
{{ t('file.modifyTime') }}{{ formatTime(items[0]?.modify_time || 0) }} <div v-if="items[0]?.thumbnail" class="flex justify-center">
</p> <VImg max-width="15rem" cover :src="items[0]?.thumbnail" class="rounded border">
</VCardText> <template #placeholder>
<!-- 图片 --> <VSkeletonLoader class="object-cover w-full h-full" />
<VCardText v-else-if="isFile && isImage && items.length > 0" class="grow d-flex justify-center align-center"> </template>
<VImg :src="currentImgLink" max-width="100%" max-height="100%" /> </VImg>
</VCardText> </div>
<!-- 目录和文件列表 --> <div class="text-xl text-high-emphasis mt-3">{{ items[0]?.name }}</div>
<VCardText v-else-if="dirs.length || files.length" class="p-0"> <p class="mt-2" v-if="items[0]?.size && items[0].modify_time">
<VList class="text-high-emphasis"> {{ t('file.size') }}{{ formatBytes(items[0]?.size || 0) }}<br />
<VVirtualScroll :items="[...dirs, ...files]" :style="listStyle"> {{ t('file.modifyTime') }}{{ formatTime(items[0]?.modify_time || 0) }}
<template #default="{ item }"> </p>
<VHover> </VCardText>
<template #default="hover"> <!-- 图片 -->
<VListItem v-bind="hover.props" class="px-3 pe-1" @click="listItemClick(item)"> <VCardText v-else-if="isFile && isImage && items.length > 0" class="grow d-flex justify-center align-center">
<template #prepend> <VImg :src="currentImgLink" max-width="100%" max-height="100%" />
<VListItemAction v-if="selectMode"> </VCardText>
<VCheckbox v-model="selected" :value="item" /> <!-- 目录和文件列表 -->
</VListItemAction> <VCardText v-else-if="dirs.length || files.length" class="p-0">
<template v-else> <VList class="text-high-emphasis">
<VIcon <VVirtualScroll :items="[...dirs, ...files]" :style="listStyle">
v-if="inProps.icons && item.extension" <template #default="{ item }">
:icon="inProps.icons[item.extension.toLowerCase()] || inProps.icons?.other" <VHover>
/> <template #default="hover">
<VIcon v-else-if="item.type == 'dir'" icon="mdi-folder" /> <VListItem v-bind="hover.props" class="px-3 pe-1" @click="listItemClick(item)">
<VIcon v-else icon="mdi-file-outline" /> <template #prepend>
<VListItemAction v-if="selectMode">
<VCheckbox v-model="selected" :value="item" />
</VListItemAction>
<template v-else>
<VIcon
v-if="inProps.icons && item.extension"
:icon="inProps.icons[item.extension.toLowerCase()] || inProps.icons?.other"
/>
<VIcon v-else-if="item.type == 'dir'" icon="mdi-folder" />
<VIcon v-else icon="mdi-file-outline" />
</template>
</template> </template>
</template> <VListItemTitle v-text="item.name" />
<VListItemTitle v-text="item.name" /> <VListItemSubtitle v-if="item.size">
<VListItemSubtitle v-if="item.size"> {{ formatBytes(item.size) }}
{{ formatBytes(item.size) }} </VListItemSubtitle>
</VListItemSubtitle> <template #append>
<template #append> <IconBtn v-if="display.smAndDown.value && !selectMode">
<IconBtn v-if="display.smAndDown.value && !selectMode"> <VIcon icon="mdi-dots-vertical" />
<VIcon icon="mdi-dots-vertical" /> <VMenu activator="parent" close-on-content-click>
<VMenu activator="parent" close-on-content-click> <VList>
<VList> <template v-for="(menu, i) in dropdownItems" :key="i">
<template v-for="(menu, i) in dropdownItems" :key="i"> <VListItem
<VListItem v-if="menu.show" :base-color="menu.props.color" @click="menu.props.click(item)"> v-if="menu.show"
<template #prepend> :base-color="menu.props.color"
<VIcon :icon="menu.props.prependIcon" /> @click="menu.props.click(item)"
</template> >
<VListItemTitle v-text="menu.title" /> <template #prepend>
</VListItem> <VIcon :icon="menu.props.prependIcon" />
</template> </template>
</VList> <VListItemTitle v-text="menu.title" />
</VMenu> </VListItem>
</IconBtn> </template>
<span v-if="hover.isHovering && display.mdAndUp.value && !selectMode" class="flex"> </VList>
<IconBtn @click.stop="recognize(item.path)"> </VMenu>
<VIcon icon="mdi-text-recognition" />
</IconBtn> </IconBtn>
<IconBtn @click.stop="scrape(item)"> <span v-if="hover.isHovering && display.mdAndUp.value && !selectMode" class="flex">
<VIcon icon="mdi-auto-fix" /> <IconBtn @click.stop="recognize(item.path)">
</IconBtn> <VIcon icon="mdi-text-recognition" />
<IconBtn @click.stop="showRenmae(item)"> </IconBtn>
<VIcon icon="mdi-rename" /> <IconBtn @click.stop="scrape(item)">
</IconBtn> <VIcon icon="mdi-auto-fix" />
<IconBtn @click.stop="showTransfer(item)"> </IconBtn>
<VIcon icon="mdi-folder-arrow-right" /> <IconBtn @click.stop="showRenmae(item)">
</IconBtn> <VIcon icon="mdi-rename" />
<IconBtn @click.stop="deleteItem(item)"> </IconBtn>
<VIcon icon="mdi-delete-outline" color="error" /> <IconBtn @click.stop="showTransfer(item)">
</IconBtn> <VIcon icon="mdi-folder-arrow-right" />
</span> </IconBtn>
</template> <IconBtn @click.stop="deleteItem(item)">
</VListItem> <VIcon icon="mdi-delete-outline" color="error" />
</template> </IconBtn>
</VHover> </span>
</template> </template>
</VVirtualScroll> </VListItem>
</VList> </template>
</VCardText> </VHover>
<VCardText v-else-if="filter" class="grow d-flex justify-center align-center grey--text py-5"> </template>
{{ t('file.noFiles') }} </VVirtualScroll>
</VCardText> </VList>
<VCardText v-else-if="!loading" class="grow d-flex justify-center align-center grey--text py-5"> </VCardText>
{{ t('file.emptyDirectory') }} <VCardText v-else-if="filter" class="grow d-flex justify-center align-center grey--text py-5">
</VCardText> {{ t('file.noFiles') }}
</VCard> </VCardText>
<!-- 重命名弹窗 --> <VCardText v-else-if="!loading" class="grow d-flex justify-center align-center grey--text py-5">
<VDialog v-if="renamePopper" v-model="renamePopper" max-width="35rem"> {{ t('file.emptyDirectory') }}
<VCard>
<VCardItem>
<template #prepend>
<VIcon icon="mdi-pencil" class="me-2" />
</template>
<VCardTitle>{{ t('file.rename') }}</VCardTitle>
</VCardItem>
<VDialogCloseBtn @click="renamePopper = false" />
<VDivider />
<VCardText>
<VRow>
<VCol cols="12">
<VTextField
v-model="newName"
:label="t('file.newName')"
:loading="renameLoading"
prepend-inner-icon="mdi-format-text"
/>
</VCol>
<VCol cols="12" v-if="currentItem && currentItem.type == 'dir'">
<VSwitch v-model="renameAll" :label="t('file.includeSubfolders')" />
</VCol>
</VRow>
</VCardText> </VCardText>
<VCardActions>
<VBtn color="success" @click="get_recommend_name" prepend-icon="mdi-magic" class="px-5 me-3">
{{ t('file.autoRecognizeName') }}
</VBtn>
<VBtn :disabled="!newName" @click="rename" prepend-icon="mdi-check" class="px-5 me-3">
{{ t('common.confirm') }}
</VBtn>
</VCardActions>
</VCard> </VCard>
</VDialog> <!-- 重命名弹窗 -->
<!-- 文件整理弹窗 --> <VDialog v-if="renamePopper" v-model="renamePopper" max-width="35rem">
<ReorganizeDialog <VCard>
v-if="transferPopper" <VCardItem>
v-model="transferPopper" <template #prepend>
:items="transferItems" <VIcon icon="mdi-pencil" class="me-2" />
:target_storage="inProps.storage" </template>
@done="transferDone" <VCardTitle>{{ t('file.rename') }}</VCardTitle>
@close="transferPopper = false" </VCardItem>
/> <VDialogCloseBtn @click="renamePopper = false" />
<!-- 进度框 --> <VDivider />
<ProgressDialog v-if="progressDialog" v-model="progressDialog" :text="progressText" :value="progressValue" /> <VCardText>
<!-- 识别结果对话框 --> <VRow>
<MediaInfoDialog <VCol cols="12">
v-if="nameTestDialog" <VTextField
v-model="nameTestDialog" v-model="newName"
:context="nameTestResult" :label="t('file.newName')"
@close="nameTestDialog = false" :loading="renameLoading"
/> prepend-inner-icon="mdi-format-text"
/>
</VCol>
<VCol cols="12" v-if="currentItem && currentItem.type == 'dir'">
<VSwitch v-model="renameAll" :label="t('file.includeSubfolders')" />
</VCol>
</VRow>
</VCardText>
<VCardActions>
<VBtn color="success" @click="get_recommend_name" prepend-icon="mdi-magic" class="px-5 me-3">
{{ t('file.autoRecognizeName') }}
</VBtn>
<VBtn :disabled="!newName" @click="rename" prepend-icon="mdi-check" class="px-5 me-3">
{{ t('common.confirm') }}
</VBtn>
</VCardActions>
</VCard>
</VDialog>
<!-- 文件整理弹窗 -->
<ReorganizeDialog
v-if="transferPopper"
v-model="transferPopper"
:items="transferItems"
:target_storage="inProps.storage"
@done="transferDone"
@close="transferPopper = false"
/>
<!-- 进度框 -->
<ProgressDialog v-if="progressDialog" v-model="progressDialog" :text="progressText" :value="progressValue" />
<!-- 识别结果对话框 -->
<MediaInfoDialog
v-if="nameTestDialog"
v-model="nameTestDialog"
:context="nameTestResult"
@close="nameTestDialog = false"
/>
</div>
</template> </template>
+1 -1
View File
@@ -27,7 +27,7 @@ const props = defineProps({
}, },
endpoints: Object, endpoints: Object,
axios: { axios: {
type: Object as PropType<any>, type: Function,
required: true, required: true,
}, },
}) })
+1 -1
View File
@@ -24,7 +24,7 @@ const inProps = defineProps({
}, },
endpoints: Object as PropType<EndPoints>, endpoints: Object as PropType<EndPoints>,
axios: { axios: {
type: Object as PropType<any>, type: Function,
required: true, required: true,
}, },
}) })