'use client'; import { Button } from '@/components/ui/button'; import { Checkbox } from '@/components/ui/checkbox'; import { Table, TableBody, TableCaption, TableCell, TableHead, TableHeader, TableRow } from '@/components/ui/table'; import { Delete, Download, RefreshCcw, Upload } from 'lucide-react'; import { useEffect, useMemo, useState } from 'react'; import { toast } from 'sonner'; import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger, } from "@/components/ui/dropdown-menu" import { UploadManager } from './components/UploadManager'; import { OssObjectItem, OssObjectList, OssStore } from '@/lib/oss/OssStore'; import { useOssStore } from '@/hooks/admin/web/blog/use-oss-store'; import OSS from 'ali-oss'; const formatSizeNumber = (n: number) => { const unit = ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB']; for (const [i] of unit.entries()) { if (n < 1024 ** (i + 1)) { if (i <= 0) { return `${(n)}${unit[i]}`; } else { return `${(n / 1024 ** i).toFixed(2)}${unit[i]}`; } } } } const ossStore = new OssStore(); export default function Page() { const [objectList, setObjectList] = useState(null) ossStore.setSetObjectList(setObjectList); const storeMeta = useOssStore(); useEffect(() => { const data = storeMeta.stsTokenData; if (!data) return; const store = new OSS({ region: 'oss-cn-chengdu', bucket: 'tone-personal', accessKeyId: data.AccessKeyId, accessKeySecret: data.AccessKeySecret, stsToken: data.SecurityToken, refreshSTSToken: async () => { await storeMeta.refresh(); if (!storeMeta.stsTokenData) throw new Error(); const { AccessKeyId, AccessKeySecret, SecurityToken } = storeMeta.stsTokenData; return { accessKeyId: AccessKeyId, accessKeySecret: AccessKeySecret, stsToken: SecurityToken, }; }, }) ossStore.setStore(store); ossStore.setWorkDir(`tone-page/${data.userId}`) ossStore.loadObjectList(); // eslint-disable-next-line react-hooks/exhaustive-deps -- storeMeta引用会导致无限循环,依赖stsTokenData即可 }, [storeMeta.stsTokenData]); const handleRefreshFileList = async () => ossStore.loadObjectList().catch(e => toast.error(e.message)); const handleCheckboxChange = ossStore.handleObjectCheckedStateChanged.bind(ossStore); const checkedFileIds = useMemo(() => { return (objectList || []).filter(i => i.isChecked).map(i => i.id); }, [objectList]) const handleDeleteObject = async (objectItem: OssObjectItem) => { await ossStore.deleteObject(objectItem) .then(() => ossStore.loadObjectList()) .catch(e => toast.error(`${e.message}`)) } const handleDeleteCheckedFiles = async () => { if (!objectList) return; const checkedObjects = objectList.filter(o => o.isChecked); const res = await ossStore.deleteCheckedObjects(checkedObjects); if (res.failed > 0) { toast.warning(`删除完成,共有${res.failed}个文件删除失败`) } else { toast.success(`${res.all}个文件删除完成`) } handleRefreshFileList(); } const handleDownloadObject = async (objectItem: OssObjectItem) => { ossStore.downloadObject(objectItem).catch(e => toast.error(`${e.message}`)); } return (
{objectList &&
共有 {objectList.length} 个文件,目前最大支持100个文件
}
{objectList === null &&
加载中...
} {/* {error &&
{`${error}`}
} */} {objectList && objectList.length === 0 &&
暂无文件
}
文件名 文件大小 上次修改时间 { objectList && objectList.map(d => ( handleCheckboxChange(d.id, Boolean(v))} /> {d.name} handleDownloadObject(d)}>下载 {/* 编辑 */} handleDeleteObject(d)}>删除 {formatSizeNumber(d.size)} {d.lastModified.toLocaleString()} )) }
) }