update upload way

This commit is contained in:
xion 2025-03-31 21:18:39 +08:00
parent 0f03491a84
commit 122fbec7da
17 changed files with 188 additions and 18 deletions

3
.gitmodules vendored
View File

@ -22,3 +22,6 @@
[submodule "submodules/store"]
path = submodules/store
url = git@git.xiongxiao.me:kevisual/store.git
[submodule "submodules/query-upload"]
path = submodules/query-upload
url = git@git.xiongxiao.me:kevisual/kevisual-query-upload.git

@ -1 +1 @@
Subproject commit 62c5c2a82a2d346e27e064301a7c36c114f8512a
Subproject commit 0a8d7abf9a78bce528e31741d4643e017812616d

@ -1 +1 @@
Subproject commit 508ec960292ad5b009e594082a2e8945ab783d28
Subproject commit a99d9c2322df537d7ffaac09545e9b2e121511fa

View File

@ -20,6 +20,7 @@
"@emotion/react": "^11.14.0",
"@emotion/styled": "^11.14.0",
"@kevisual/components": "workspace:*",
"@kevisual/query-upload": "workspace:*",
"@kevisual/router": "^0.0.9",
"@kevisual/store": "^0.0.2",
"@mui/material": "^6.4.8",

View File

@ -5,3 +5,5 @@ export { iText } from './i-text/index.ts';
export { uploadFiles, uploadFileChunked, getDirectoryAndName, toFile, createDirectory } from './pages/upload/app';
export { DialogDirectory, DialogDeleteDirectory } from './pages/upload/DialogDirectory';
export { uploadChunkV2 } from './pages/upload/v2/upload-chunk';

View File

@ -5,6 +5,9 @@ import { FileText, CloudUpload as UploadIcon } from 'lucide-react';
import { uploadFileChunked } from './utils/upload-chunk';
import { filterFiles } from './utils/filter-files';
import { IconButton } from '@kevisual/components/button/index.tsx';
import { uploadChunkV2 } from './v2/upload-chunk';
import { uploadFilesV2 } from './v2/upload';
type UploadButtonProps = {
/**
*
@ -51,12 +54,10 @@ export const UploadButton = (props: UploadButtonProps) => {
console.log(acceptedFiles);
acceptedFiles = filterFiles(acceptedFiles);
if (acceptedFiles.length > 1) {
const res = await uploadFiles(acceptedFiles, { directory, appKey, version, username });
console.log('uploadFiles res', res);
const res = await uploadFilesV2(acceptedFiles, { directory, appKey, version, username });
props.onUpload?.(res);
} else if (acceptedFiles.length === 1) {
const res = await uploadFileChunked(acceptedFiles[0], { directory, appKey, version, username });
console.log('uploadFiles res', res);
const res = await uploadChunkV2(acceptedFiles[0], { directory, appKey, version, username });
props.onUpload?.(res);
}
};
@ -83,11 +84,9 @@ export const Upload = ({ uploadDirectory = false }: { uploadDirectory?: boolean
const onDrop = async (acceptedFiles) => {
acceptedFiles = filterFiles(acceptedFiles);
if (acceptedFiles.length > 1) {
const res = await uploadFiles(acceptedFiles, {});
console.log('uploadFiles res', res);
const res = await uploadFilesV2(acceptedFiles, {});
} else if (acceptedFiles.length === 1) {
const res = await uploadFileChunked(acceptedFiles[0], {});
console.log('uploadFiles res', res);
const res = await uploadChunkV2(acceptedFiles[0], {});
}
};

View File

@ -1,4 +1,4 @@
import { toTextFile } from '../app';
import { toTextFile } from '../tools/to-file';
import { ConvertOpts, uploadFileChunked } from './upload-chunk';
/**
* directory的路径进行解析

View File

@ -0,0 +1,55 @@
import NProgress from 'nprogress';
import 'nprogress/nprogress.css';
import { Id, toast } from 'react-toastify';
import { nanoid } from 'nanoid';
import { toastLogin } from '@kevisual/resources/pages/message/ToastLogin';
import { uploadFileChunked, UploadProgress } from '@kevisual/query-upload/query-upload';
export type ConvertOpts = {
appKey?: string;
version?: string;
username?: string;
directory?: string;
isPublic?: boolean;
filename?: string;
};
export const uploadChunkV2 = async (file: File, opts: ConvertOpts) => {
const filename = opts.filename || file.name;
const token = localStorage.getItem('token');
if (!token) {
console.log('uploadChunk token', token);
toastLogin();
return;
}
let loaded: Id;
const uploadProgress = new UploadProgress({
onStart: function () {
NProgress.start();
loaded = toast.loading(`${filename} 上传中...`);
},
onDone: () => {
NProgress.done();
toast.dismiss(loaded);
},
onProgress: (progress, data) => {
NProgress.set(progress);
console.log('uploadChunk progress', progress, data);
toast.update(loaded, {
render: `${filename} 上传中... ${progress.toFixed(2)}%`,
isLoading: true,
autoClose: false,
});
},
});
const result = await uploadFileChunked(file, opts, {
uploadProgress,
token,
createEventSource: (url: string, searchParams: URLSearchParams) => {
return new EventSource(url + '?' + searchParams.toString());
},
FormDataFn: FormData,
});
return result;
};

View File

@ -0,0 +1,70 @@
import NProgress from 'nprogress';
import 'nprogress/nprogress.css';
import { Id, toast } from 'react-toastify';
import { nanoid } from 'nanoid';
import { toastLogin } from '@kevisual/resources/pages/message/ToastLogin';
import { uploadFiles, UploadProgress } from '@kevisual/query-upload/query-upload';
export type ConvertOpts = {
appKey?: string;
version?: string;
username?: string;
directory?: string;
isPublic?: boolean;
maxSize?: number;
maxCount?: number;
};
export const uploadFilesV2 = async (files: File[], opts: ConvertOpts) => {
const token = localStorage.getItem('token');
if (!token) {
console.log('uploadChunk token', token);
toastLogin();
return;
}
const length = files.length;
const maxSize = opts.maxSize || 20 * 1024 * 1024; // 10MB
const totalSize = files.reduce((acc, file) => acc + file.size, 0);
if (totalSize > maxSize) {
toast.error('有文件大小不能超过20MB');
return;
}
const maxCount = opts.maxCount || 10;
if (length > maxCount) {
toast.error(`最多只能上传${maxCount}个文件`);
return;
}
toast.info(`上传中,共${length}个文件`);
let loaded: Id;
const uploadProgress = new UploadProgress({
onStart: function () {
NProgress.start();
loaded = toast.loading(`上传中...`);
},
onDone: () => {
NProgress.done();
toast.dismiss(loaded);
},
onProgress: (progress, data) => {
NProgress.set(progress);
console.log('uploadChunk progress', progress, data);
toast.update(loaded, {
render: `上传中... ${progress.toFixed(2)}%`,
isLoading: true,
autoClose: false,
});
},
});
const result = await uploadFiles(files, opts, {
uploadProgress,
token,
createEventSource: (url: string, searchParams: URLSearchParams) => {
return new EventSource(url + '?' + searchParams.toString());
},
FormDataFn: FormData,
});
return result;
};

31
pnpm-lock.yaml generated
View File

@ -481,6 +481,9 @@ importers:
'@kevisual/components':
specifier: workspace:*
version: link:../components
'@kevisual/query-upload':
specifier: workspace:*
version: link:../../submodules/query-upload
'@kevisual/router':
specifier: ^0.0.9
version: 0.0.9
@ -600,6 +603,18 @@ importers:
specifier: ^8.4.0
version: 8.4.0(@microsoft/api-extractor@7.52.2(@types/node@22.13.13))(jiti@2.4.2)(postcss@8.5.3)(typescript@5.8.2)(yaml@2.5.1)
submodules/query-upload:
devDependencies:
'@types/node':
specifier: ^22.13.14
version: 22.13.14
eventsource:
specifier: ^3.0.6
version: 3.0.6
tsup:
specifier: ^8.4.0
version: 8.4.0(@microsoft/api-extractor@7.52.2(@types/node@22.13.14))(jiti@2.4.2)(postcss@8.5.3)(typescript@5.8.2)(yaml@2.5.1)
submodules/store:
dependencies:
eventemitter3:
@ -3181,6 +3196,14 @@ packages:
eventemitter3@5.0.1:
resolution: {integrity: sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==}
eventsource-parser@3.0.1:
resolution: {integrity: sha512-VARTJ9CYeuQYb0pZEPbzi740OWFgpHe7AYJ2WFZVnUDUQp5Dk2yJUgF36YsZ81cOyxT0QxmXD2EQpapAouzWVA==}
engines: {node: '>=18.0.0'}
eventsource@3.0.6:
resolution: {integrity: sha512-l19WpE2m9hSuyP06+FbuUUf1G+R0SFLrtQfbRb9PRr+oimOfxQhgGCbVaXg5IvZyyTThJsxh6L/srkMiCeBPDA==}
engines: {node: '>=18.0.0'}
exsolve@1.0.4:
resolution: {integrity: sha512-xsZH6PXaER4XoV+NiT7JHp1bJodJVT+cxeSH1G0f0tlT0lJqYuHUP3bUx2HtfTDvOagMINYp8rsqusxud3RXhw==}
@ -6931,7 +6954,7 @@ snapshots:
'@types/qrcode@1.5.5':
dependencies:
'@types/node': 22.13.13
'@types/node': 22.13.14
'@types/react-dom@19.0.4(@types/react@19.0.12)':
dependencies:
@ -7812,6 +7835,12 @@ snapshots:
eventemitter3@5.0.1: {}
eventsource-parser@3.0.1: {}
eventsource@3.0.6:
dependencies:
eventsource-parser: 3.0.1
exsolve@1.0.4: {}
extend@3.0.2: {}

View File

@ -75,7 +75,7 @@ export const App = () => {
<Route path='/container/*' element={<ContainerApp />} />
<Route path='/map/*' element={<MapApp />} />
<Route path='/user/*' element={<UserApp />} />
<Route path='/user1/*' element={<UserApp />} />
<Route path='/user-center/*' element={<UserApp />} />
<Route path='/org/*' element={<OrgApp />} />
<Route path='/config/*' element={<ConfigApp />} />
<Route path='/app/*' element={<UserAppApp />} />

View File

@ -1,6 +1,7 @@
import { QueryClient } from '@kevisual/query';
import { QueryLoginBrowser } from '@kevisual/query-login';
import { toastLogin } from '@kevisual/resources/pages/message/ToastLogin.tsx';
import { toast } from 'react-toastify';
export const query = new QueryClient({
io: true,
});
@ -25,6 +26,15 @@ query.afterResponse = async (res, ctx) => {
afterAlso401: () => {
toastLogin();
},
afterCheck: (res) => {
if (res.code === 200) {
// console.log('afterCheck');
toast.success('刷新登陆信息');
setTimeout(() => {
window.location.reload();
}, 1000);
}
},
});
return newRes as any;

@ -1 +1 @@
Subproject commit 05f037383436cd0e30a6a12e7a4e08bf5b884ea8
Subproject commit 98c8a2ad86331566058ca7cc12df5ee2b406fa2f

@ -1 +1 @@
Subproject commit 39f0d7c566584811b73c027fb3eb43075d74ee1f
Subproject commit 757be9fc2fbfa2ac0af92a3002cccc9edba995ba

@ -0,0 +1 @@
Subproject commit a7faaca4188cae055deb1af1d1b758b6d5439f8d

@ -1 +1 @@
Subproject commit 415f008209c9579cccc5692bdc8a5f9f97b78d8c
Subproject commit 69784e8ed4f4546c91b2653adc75034e5946123c

View File

@ -7,8 +7,8 @@ const isDev = process.env.NODE_ENV === 'development';
const plugins: any[] = [basicSsl()];
plugins.push(tailwindcss());
const devBackend = 'https://kevisual.silkyai.cn';
// const meBackend = 'https://kevisual.xiongxiao.me';
const meBackend = 'https://kevisual.cn';
const meBackend = 'https://kevisual.xiongxiao.me';
// const meBackend = 'https://kevisual.cn';
// const backend = isDev ? devBackend : meBackend;
const backendWss = devBackend.replace(/^https:/, 'wss:');
const backend = meBackend;