chore:优化文件管理分页

This commit is contained in:
秋帆
2024-05-19 22:42:51 +08:00
parent f703854037
commit 00da9acdd0
3 changed files with 51 additions and 113 deletions

View File

@@ -3,11 +3,12 @@ import { useBreakpoint } from '@/hooks'
type Callback = () => void type Callback = () => void
type Options = { export type Options = {
defaultPageSize: number defaultPageSize: number
defaultSizeOptions: number[]
} }
export function usePagination(callback: Callback, options: Options = { defaultPageSize: 10 }) { export function usePagination(callback: Callback, options: Options = { defaultPageSize: 10, defaultSizeOptions: [10, 20, 30, 40, 50] }) {
const { breakpoint } = useBreakpoint() const { breakpoint } = useBreakpoint()
const pagination = reactive({ const pagination = reactive({
@@ -15,6 +16,7 @@ export function usePagination(callback: Callback, options: Options = { defaultPa
showTotal: true, showTotal: true,
current: 1, current: 1,
pageSize: options.defaultPageSize, pageSize: options.defaultPageSize,
pageSizeOptions: options.defaultSizeOptions,
total: 0, total: 0,
simple: false, simple: false,
onChange: (size: number) => { onChange: (size: number) => {

View File

@@ -1,5 +1,6 @@
import type { TableData, TableInstance } from '@arco-design/web-vue' import type { TableData, TableInstance } from '@arco-design/web-vue'
import { Message, Modal } from '@arco-design/web-vue' import { Message, Modal } from '@arco-design/web-vue'
import type { Options as paginationOptions } from './usePagination'
import { usePagination } from '@/hooks' import { usePagination } from '@/hooks'
interface Options<T> { interface Options<T> {
@@ -7,6 +8,7 @@ interface Options<T> {
onSuccess?: () => void onSuccess?: () => void
immediate?: boolean immediate?: boolean
rowKey?: keyof T rowKey?: keyof T
paginationOption: paginationOptions
} }
type PaginationParams = { page: number, size: number } type PaginationParams = { page: number, size: number }
@@ -14,7 +16,7 @@ type Api<T> = (params: PaginationParams) => Promise<ApiRes<PageRes<T[]>>> | Prom
export function useTable<T>(api: Api<T>, options?: Options<T>) { export function useTable<T>(api: Api<T>, options?: Options<T>) {
const { formatResult, onSuccess, immediate, rowKey } = options || {} const { formatResult, onSuccess, immediate, rowKey } = options || {}
const { pagination, setTotal } = usePagination(() => getTableData()) const { pagination, setTotal } = usePagination(() => getTableData(), options?.paginationOption)
const loading = ref(false) const loading = ref(false)
const tableData = ref<T[]>([]) const tableData = ref<T[]>([])

View File

@@ -17,13 +17,7 @@
</a-dropdown> </a-dropdown>
<a-input-group> <a-input-group>
<a-input <a-input v-model="queryForm.name" placeholder="请输入文件名" allow-clear style="width: 200px" @change="search" />
v-model="queryForm.name"
placeholder="请输入文件名"
allow-clear
style="width: 200px"
@change="search"
/>
<a-button type="primary" @click="search"> <a-button type="primary" @click="search">
<template #icon> <template #icon>
<icon-search /> <icon-search />
@@ -35,13 +29,8 @@
<!-- 右侧区域 --> <!-- 右侧区域 -->
<a-space wrap> <a-space wrap>
<a-button <a-button v-if="isBatchMode" :disabled="!selectedFileIds.length" type="primary" status="danger"
v-if="isBatchMode" @click="handleMulDelete">
:disabled="!selectedFileIds.length"
type="primary"
status="danger"
@click="handleMulDelete"
>
<template #icon> <template #icon>
<icon-delete /> <icon-delete />
</template> </template>
@@ -67,29 +56,20 @@
<!-- 文件列表-宫格模式 --> <!-- 文件列表-宫格模式 -->
<a-spin id="fileMain" class="file-main__list" :loading="loading" @scroll="handleScroll"> <a-spin id="fileMain" class="file-main__list" :loading="loading" @scroll="handleScroll">
<FileGrid <FileGrid v-show="fileList.length && mode === 'grid'" :data="fileList" :is-batch-mode="isBatchMode"
v-show="fileList.length && mode === 'grid'" :selected-file-ids="selectedFileIds" @click="handleClickFile" @select="handleSelectFile"
:data="fileList" @right-menu-click="handleRightMenuClick"></FileGrid>
:is-batch-mode="isBatchMode"
:selected-file-ids="selectedFileIds"
@click="handleClickFile"
@select="handleSelectFile"
@right-menu-click="handleRightMenuClick"
></FileGrid>
<!-- 文件列表-列表模式 --> <!-- 文件列表-列表模式 -->
<FileList <FileList v-show="fileList.length && mode === 'list'" :data="fileList" :is-batch-mode="isBatchMode"
v-show="fileList.length && mode === 'list'" :selected-file-ids="selectedFileIds" @click="handleClickFile" @select="handleSelectFile"
:data="fileList" @right-menu-click="handleRightMenuClick"></FileList>
:is-batch-mode="isBatchMode"
:selected-file-ids="selectedFileIds"
@click="handleClickFile"
@select="handleSelectFile"
@right-menu-click="handleRightMenuClick"
></FileList>
<a-empty v-show="!fileList.length"></a-empty> <a-empty v-show="!fileList.length"></a-empty>
</a-spin> </a-spin>
<div class="pagination">
<a-pagination v-bind="pagination" />
</div>
</div> </div>
</template> </template>
@@ -104,6 +84,7 @@ import {
} from '../../components/index' } from '../../components/index'
import FileGrid from './FileGrid.vue' import FileGrid from './FileGrid.vue'
import useFileManage from './useFileManage' import useFileManage from './useFileManage'
import { useTable } from '@/hooks'
import { type FileItem, type FilePageQuery, type FileQuery, deleteFile, listFile, uploadFile } from '@/apis' import { type FileItem, type FilePageQuery, type FileQuery, deleteFile, listFile, uploadFile } from '@/apis'
import { ImageTypes } from '@/constant/file' import { ImageTypes } from '@/constant/file'
import 'viewerjs/dist/viewer.css' import 'viewerjs/dist/viewer.css'
@@ -118,48 +99,17 @@ const queryForm = reactive<FileQuery>({
type: route.query.type?.toString() || undefined, type: route.query.type?.toString() || undefined,
sort: ['updateTime,desc'] sort: ['updateTime,desc']
}) })
const pagination = reactive({ const paginationOption = reactive({
page: 1, defaultPageSize: 30,
size: 30 defaultSizeOptions: [30, 40, 50, 100, 120]
}) })
const fileList = ref<FileItem[]>([])
const isBatchMode = ref(false) const isBatchMode = ref(false)
const loading = ref(false) const {
const timer = ref<any>() tableData: fileList,
// 查询文件列表 loading,
const getFileList = async (query: FilePageQuery = { ...queryForm, page: pagination.page, size: pagination.size }) => { pagination,
try { search
loading.value = true } = useTable((page) => listFile({ ...queryForm, ...page }), { immediate: false, paginationOption })
isBatchMode.value = false
query.type = query.type === '0' ? undefined : query.type
const res = await listFile(query)
if (res.data.list) {
if (query.page === 1) {
fileList.value = res.data.list
timer.value = setTimeout(() => {
clearTimeout(timer.value)
timer.value = null
}, 1000)
} else {
fileList.value = [...fileList.value, ...res.data.list]
}
} else {
--pagination.page
}
} catch (error) {
--pagination.page
return error
} finally {
loading.value = false
}
}
// 查询
const search = () => {
pagination.page = 1
getFileList()
}
// 点击文件 // 点击文件
const handleClickFile = (item: FileItem) => { const handleClickFile = (item: FileItem) => {
@@ -236,20 +186,20 @@ const handleMulDelete = () => {
// 上传 // 上传
const handleUpload = (options: RequestOption) => { const handleUpload = (options: RequestOption) => {
const controller = new AbortController() const controller = new AbortController()
;(async function requestWrap() { ; (async function requestWrap() {
const { onProgress, onError, onSuccess, fileItem, name = 'file' } = options const { onProgress, onError, onSuccess, fileItem, name = 'file' } = options
onProgress(20) onProgress(20)
const formData = new FormData() const formData = new FormData()
formData.append(name as string, fileItem.file as Blob) formData.append(name as string, fileItem.file as Blob)
try { try {
const res = await uploadFile(formData) const res = await uploadFile(formData)
Message.success('上传成功') Message.success('上传成功')
onSuccess(res) onSuccess(res)
search() search()
} catch (error) { } catch (error) {
onError(error) onError(error)
} }
})() })()
return { return {
abort() { abort() {
controller.abort() controller.abort()
@@ -257,30 +207,6 @@ const handleUpload = (options: RequestOption) => {
} }
} }
const handleScroll = (event) => {
const { clientHeight, scrollHeight, scrollTop } = event.target
const scrollLinerHeight = (clientHeight / scrollHeight) * scrollHeight
if (!timer.value) {
timer.value = setTimeout(() => {
if ((scrollTop + scrollLinerHeight) / scrollHeight >= 0.9 && !loading.value) {
++pagination.page
getFileList()
}
timer.value = null
}, 1000)
}
}
onMounted(() => {
const fileMainDom = document.getElementById('fileMain')
fileMainDom.addEventListener('scrool', handleScroll)
})
onUnmounted(() => {
// 移除事件监听
const fileMainDom = document.getElementById('fileMain')
fileMainDom.removeEventListener('scroll', handleScroll)
})
onBeforeRouteUpdate((to) => { onBeforeRouteUpdate((to) => {
if (!to.query.type) return if (!to.query.type) return
queryForm.type = to.query.type?.toString() queryForm.type = to.query.type?.toString()
@@ -315,5 +241,13 @@ onMounted(() => {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
} }
.pagination {
margin: 10px 0;
:deep(.arco-pagination) {
justify-content: end;
}
}
} }
</style> </style>