rht
This commit is contained in:
parent
6985ee863f
commit
0dad0e18ec
|
@ -27,7 +27,7 @@
|
|||
"@nestjs/jwt": "^10.2.0",
|
||||
"@nestjs/platform-express": "^10.0.0",
|
||||
"@nestjs/platform-socket.io": "^10.3.10",
|
||||
"@nestjs/schedule": "^4.1.0",
|
||||
"@nestjs/schedule": "^4.1.2",
|
||||
"@nestjs/websockets": "^10.3.10",
|
||||
"@nice/common": "workspace:*",
|
||||
"@nice/tus": "workspace:*",
|
||||
|
|
|
@ -3,6 +3,9 @@ import { customAlphabet } from 'nanoid-cjs';
|
|||
import { db } from '@nice/common';
|
||||
import { Cron, CronExpression } from '@nestjs/schedule';
|
||||
import { ResourceService } from '@server/models/resource/resource.service';
|
||||
import * as fs from 'fs'
|
||||
import * as path from 'path'
|
||||
|
||||
|
||||
export interface ShareCode {
|
||||
id: string;
|
||||
|
@ -44,7 +47,7 @@ export class ShareCodeService {
|
|||
const resource = await this.resourceService.findUnique({
|
||||
where: { fileId },
|
||||
});
|
||||
console.log('完整 fileId:', fileId); // 确保与前端一致
|
||||
this.logger.log('完整 fileId:', fileId); // 确保与前端一致
|
||||
|
||||
if (!resource) {
|
||||
throw new NotFoundException('文件不存在');
|
||||
|
@ -53,7 +56,7 @@ export class ShareCodeService {
|
|||
// 生成分享码
|
||||
const code = this.generateCode();
|
||||
const expiresAt = new Date(Date.now() + 24 * 60 * 60 * 1000); // 24小时后过期
|
||||
|
||||
//const expiresAt = new Date(Date.now() + 10 * 1000); // 24小时后过期
|
||||
// 查找是否已有分享码记录
|
||||
const existingShareCode = await db.shareCode.findUnique({
|
||||
where: { fileId },
|
||||
|
@ -96,7 +99,7 @@ export class ShareCodeService {
|
|||
|
||||
async validateAndUseCode(code: string): Promise<ShareCode | null> {
|
||||
try {
|
||||
console.log(`尝试验证分享码: ${code}`);
|
||||
this.logger.log(`尝试验证分享码: ${code}`);
|
||||
|
||||
// 查找有效的分享码
|
||||
const shareCode = await db.shareCode.findFirst({
|
||||
|
@ -107,10 +110,10 @@ export class ShareCodeService {
|
|||
},
|
||||
});
|
||||
|
||||
console.log('查询结果:', shareCode);
|
||||
this.logger.log('查询结果:', shareCode);
|
||||
|
||||
if (!shareCode) {
|
||||
console.log('分享码无效或已过期');
|
||||
this.logger.log('分享码无效或已过期');
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -132,21 +135,74 @@ export class ShareCodeService {
|
|||
}
|
||||
|
||||
// 每天清理过期的分享码
|
||||
//@Cron('*/30 * * * * *')
|
||||
@Cron(CronExpression.EVERY_DAY_AT_MIDNIGHT)
|
||||
async cleanupExpiredShareCodes() {
|
||||
try {
|
||||
const result = await db.shareCode.deleteMany({
|
||||
const shareCodes = await db.shareCode.findMany({
|
||||
where: {
|
||||
OR: [{ expiresAt: { lt: new Date() } }, { isUsed: true }],
|
||||
}
|
||||
})
|
||||
this.logger.log('需要清理的分享码:', shareCodes);
|
||||
shareCodes.forEach(code => {
|
||||
this.cleanupUploadFolder(code.fileId);
|
||||
})
|
||||
const result = await db.shareCode.deleteMany({
|
||||
where: {
|
||||
fileId: {
|
||||
in: shareCodes.map(code => code.fileId)
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
this.logger.log(`Cleaned up ${result.count} expired share codes`);
|
||||
const deleteResource = await this.resourceService.deleteMany({
|
||||
where: {
|
||||
fileId: {
|
||||
in: shareCodes.map(code => code.fileId)
|
||||
}
|
||||
}
|
||||
})
|
||||
this.logger.log(`Cleaned up ${result.count} ${deleteResource.count} expired share codes`);
|
||||
} catch (error) {
|
||||
this.logger.error('Failed to cleanup expired share codes', error);
|
||||
}
|
||||
}
|
||||
|
||||
async cleanupUploadFolder(file?: string) {
|
||||
//const uploadDir = path.join(__dirname, '../../../uploads');
|
||||
const uploadDir = path.join('/data/uploads/', file || '');
|
||||
this.logger.log('uploadDir:', uploadDir);
|
||||
try {
|
||||
if (!fs.existsSync(uploadDir)) {
|
||||
this.logger.warn(`Upload directory does not exist: ${uploadDir}`);
|
||||
return;
|
||||
}
|
||||
// 递归删除文件夹及其内容
|
||||
this.deleteFolderRecursive(uploadDir);
|
||||
this.logger.log(`Cleaned up upload folder: ${uploadDir}`);
|
||||
} catch (error) {
|
||||
this.logger.error('读取上传目录失败:', error);
|
||||
return;
|
||||
}
|
||||
}
|
||||
private deleteFolderRecursive(dirPath: string) {
|
||||
if (fs.existsSync(dirPath)) {
|
||||
fs.readdirSync(dirPath).forEach((file) => {
|
||||
const filePath = path.join(dirPath, file);
|
||||
if (fs.statSync(filePath).isDirectory()) {
|
||||
// 递归删除子目录
|
||||
this.deleteFolderRecursive(filePath);
|
||||
} else {
|
||||
// 删除文件
|
||||
fs.unlinkSync(filePath);
|
||||
this.logger.log(`Deleted file: ${filePath}`);
|
||||
}
|
||||
});
|
||||
// 删除空文件夹
|
||||
fs.rmdirSync(dirPath);
|
||||
this.logger.log(`Deleted folder: ${dirPath}`);
|
||||
}
|
||||
}
|
||||
// 获取分享码信息
|
||||
async getShareCodeInfo(code: string): Promise<ShareCode | null> {
|
||||
try {
|
||||
|
@ -192,10 +248,10 @@ export class ShareCodeService {
|
|||
|
||||
// 根据分享码获取文件
|
||||
async getFileByShareCode(code: string) {
|
||||
console.log('收到验证分享码请求,code:', code);
|
||||
this.logger.log('收到验证分享码请求,code:', code);
|
||||
|
||||
const shareCode = await this.validateAndUseCode(code);
|
||||
console.log('验证分享码结果:', shareCode);
|
||||
this.logger.log('验证分享码结果:', shareCode);
|
||||
|
||||
if (!shareCode) {
|
||||
throw new NotFoundException('分享码无效或已过期');
|
||||
|
@ -205,8 +261,9 @@ export class ShareCodeService {
|
|||
const resource = await this.resourceService.findUnique({
|
||||
where: { fileId: shareCode.fileId },
|
||||
});
|
||||
console.log('获取到的资源信息:', resource);
|
||||
this.logger.log('获取到的资源信息:', resource);
|
||||
const { filename } = resource.meta as any as ResourceMeta
|
||||
const fileUrl = resource?.url
|
||||
if (!resource) {
|
||||
throw new NotFoundException('文件不存在');
|
||||
}
|
||||
|
@ -216,22 +273,23 @@ export class ShareCodeService {
|
|||
fileId: shareCode.fileId,
|
||||
fileName: filename || 'downloaded_file',
|
||||
code: shareCode.code,
|
||||
expiresAt: shareCode.expiresAt
|
||||
expiresAt: shareCode.expiresAt,
|
||||
url: fileUrl,
|
||||
};
|
||||
|
||||
console.log('返回给前端的数据:', response); // 添加日志
|
||||
this.logger.log('返回给前端的数据:', response); // 添加日志
|
||||
return response;
|
||||
}
|
||||
|
||||
// 根据文件ID生成分享码
|
||||
async generateShareCodeByFileId(fileId: string) {
|
||||
try {
|
||||
console.log('收到生成分享码请求,fileId:', fileId);
|
||||
this.logger.log('收到生成分享码请求,fileId:', fileId);
|
||||
const result = await this.generateShareCode(fileId);
|
||||
console.log('生成分享码结果:', result);
|
||||
this.logger.log('生成分享码结果:', result);
|
||||
return result;
|
||||
} catch (error) {
|
||||
console.error('生成分享码错误:', error);
|
||||
this.logger.error('生成分享码错误:', error);
|
||||
return error
|
||||
}
|
||||
|
||||
|
|
|
@ -1,233 +1,95 @@
|
|||
import { useTusUpload } from "@web/src/hooks/useTusUpload";
|
||||
|
||||
import { ShareCodeGenerator } from "../sharecode/sharecodegenerator";
|
||||
import { ShareCodeValidator } from "../sharecode/sharecodevalidator";
|
||||
import { useState, useRef, useCallback, useEffect } from "react";
|
||||
import { message, Progress, Button, Tabs, DatePicker, Form } from "antd";
|
||||
import { UploadOutlined, DeleteOutlined, InboxOutlined } from "@ant-design/icons";
|
||||
import { message, Tabs, Form, Spin } from "antd";
|
||||
import { env } from '../../../env'
|
||||
import { TusUploader } from "@web/src/components/common/uploader/TusUploader";
|
||||
import { useState } from "react";
|
||||
const { TabPane } = Tabs;
|
||||
|
||||
export default function DeptSettingPage() {
|
||||
const [uploadedFileId, setUploadedFileId] = useState<string>('');
|
||||
const [uploadedFileName, setUploadedFileName] = useState<string>('');
|
||||
const [fileNameMap, setFileNameMap] = useState<Record<string, string>>({});
|
||||
const [uploadedFiles, setUploadedFiles] = useState<{ id: string, name: string }[]>([]);
|
||||
const [isDragging, setIsDragging] = useState(false);
|
||||
const [expireTime, setExpireTime] = useState<Date | null>(null);
|
||||
const dropRef = useRef<HTMLDivElement>(null);
|
||||
const [form] = Form.useForm();
|
||||
const [currentFile, setCurrentFile] = useState<string[]>([])
|
||||
const uploadFileId = Form.useWatch(["file"], form)?.[0]
|
||||
// 使用您的 useTusUpload hook
|
||||
const { uploadProgress, isUploading, uploadError, handleFileUpload } = useTusUpload();
|
||||
|
||||
// 清除已上传文件
|
||||
const handleClearFile = () => {
|
||||
setUploadedFileId('');
|
||||
setUploadedFileName('');
|
||||
setUploadedFiles([]);
|
||||
setFileNameMap({});
|
||||
};
|
||||
|
||||
// 处理文件上传
|
||||
const handleFileSelect = async (file: File) => {
|
||||
// 限制:如果已有上传文件,则提示用户
|
||||
if (uploadedFiles.length > 0) {
|
||||
message.warning('只能上传一个文件,请先删除已上传的文件');
|
||||
return;
|
||||
}
|
||||
|
||||
const fileKey = `file-${Date.now()}`; // 生成唯一的文件标识
|
||||
|
||||
handleFileUpload(
|
||||
file,
|
||||
async (result) => {
|
||||
setUploadedFileId(result.fileId);
|
||||
setUploadedFileName(result.fileName);
|
||||
|
||||
// 添加到已上传文件列表
|
||||
setUploadedFiles([{ id: result.fileId, name: file.name }]);
|
||||
|
||||
// 在前端保存文件名映射(用于当前会话)
|
||||
setFileNameMap({
|
||||
[result.fileId]: file.name
|
||||
});
|
||||
|
||||
// 上传成功后保存原始文件名到数据库
|
||||
try {
|
||||
console.log('正在保存文件名到数据库:', result.fileName, '对应文件ID:', result.fileId);
|
||||
|
||||
const response = await fetch(`http://${env.SERVER_IP}:${env.SERVER_PORT}/upload/filename`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify({
|
||||
fileId: result.fileId,
|
||||
fileName: file.name
|
||||
}),
|
||||
});
|
||||
|
||||
const responseText = await response.text();
|
||||
console.log('保存文件名响应:', response.status, responseText);
|
||||
|
||||
if (!response.ok) {
|
||||
console.error('保存文件名失败:', responseText);
|
||||
message.warning('文件名保存失败,下载时可能无法显示原始文件名');
|
||||
} else {
|
||||
console.log('文件名保存成功:', file.name);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('保存文件名请求失败:', error);
|
||||
message.warning('文件名保存失败,下载时可能无法显示原始文件名');
|
||||
}
|
||||
|
||||
message.success('文件上传成功');
|
||||
},
|
||||
(error) => {
|
||||
message.error('上传失败:' + error.message);
|
||||
},
|
||||
fileKey
|
||||
);
|
||||
};
|
||||
|
||||
// 处理多个文件上传 - 已移除
|
||||
// const handleFilesUpload = (file: File) => {
|
||||
// handleFileSelect(file);
|
||||
// };
|
||||
|
||||
// 处理文件删除
|
||||
const handleDeleteFile = async (fileId: string) => {
|
||||
try {
|
||||
// 可以添加删除文件的API调用
|
||||
// const response = await fetch(`http://${env.SERVER_IP}:${env.SERVER_PORT}/upload/delete/${fileId}`, {
|
||||
// method: 'DELETE'
|
||||
// });
|
||||
|
||||
// if (!response.ok) {
|
||||
// throw new Error('删除文件失败');
|
||||
// }
|
||||
|
||||
// 无论服务器删除是否成功,前端都需要更新状态
|
||||
setUploadedFiles([]);
|
||||
setUploadedFileId('');
|
||||
setUploadedFileName('');
|
||||
setFileNameMap({});
|
||||
|
||||
message.success('文件已删除');
|
||||
} catch (error) {
|
||||
console.error('删除文件错误:', error);
|
||||
message.error('删除文件失败');
|
||||
}
|
||||
};
|
||||
|
||||
// 拖拽相关处理函数
|
||||
const handleDragEnter = useCallback((e: React.DragEvent<HTMLDivElement>) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
setIsDragging(true);
|
||||
}, []);
|
||||
|
||||
const handleDragLeave = useCallback((e: React.DragEvent<HTMLDivElement>) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
setIsDragging(false);
|
||||
}, []);
|
||||
|
||||
const handleDragOver = useCallback((e: React.DragEvent<HTMLDivElement>) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
setIsDragging(true);
|
||||
}, []);
|
||||
|
||||
const handleDrop = useCallback((e: React.DragEvent<HTMLDivElement>) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
setIsDragging(false);
|
||||
|
||||
handleFileSelect(e.dataTransfer.files[0]);
|
||||
}, []);
|
||||
|
||||
|
||||
const [isGetingFileId, setIsGetingFileId] = useState(false);
|
||||
// 处理分享码生成成功
|
||||
const handleShareSuccess = (code: string) => {
|
||||
message.success('分享码生成成功:' + code);
|
||||
// 可以在这里添加其他逻辑,比如保存到历史记录
|
||||
};
|
||||
|
||||
}
|
||||
// 处理分享码验证成功
|
||||
const handleValidSuccess = async (fileId: string, fileName: string) => {
|
||||
const handleValidSuccess = async (fileUrl: string, fileName: string) => {
|
||||
setIsGetingFileId(true);
|
||||
try {
|
||||
// 构建下载URL(包含文件名参数)
|
||||
const downloadUrl = `/upload/download/${fileId}?fileName=${encodeURIComponent(fileName)}`;
|
||||
const response = await fetch(downloadUrl);
|
||||
if (!response.ok) {
|
||||
throw new Error('文件下载失败');
|
||||
}
|
||||
|
||||
// 创建下载链接
|
||||
const blob = await response.blob();
|
||||
const url = window.URL.createObjectURL(blob);
|
||||
console.log('文件url:', fileUrl);
|
||||
const downloadUrl = `http://${env.SERVER_IP}:${env.FILE_PORT}/uploads/${fileUrl}`;
|
||||
console.log('下载URL:', downloadUrl);
|
||||
const link = document.createElement('a');
|
||||
link.href = url;
|
||||
link.href = downloadUrl;
|
||||
|
||||
// 直接使用传入的 fileName
|
||||
link.download = fileName;
|
||||
|
||||
link.target = '_blank'; // 在新标签页中打开
|
||||
// 触发下载
|
||||
document.body.appendChild(link);
|
||||
link.click();
|
||||
document.body.removeChild(link);
|
||||
window.URL.revokeObjectURL(url);
|
||||
|
||||
message.success('文件下载开始');
|
||||
} catch (error) {
|
||||
console.error('下载失败:', error);
|
||||
message.error('文件下载失败');
|
||||
} finally {
|
||||
setIsGetingFileId(false);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
return (
|
||||
<div style={{ maxWidth: '800px', margin: '0 auto', padding: '20px' }}>
|
||||
<span className="text-2xl py-4">文件分享中心</span>
|
||||
<Tabs defaultActiveKey="upload">
|
||||
<TabPane tab="上传分享" key="upload">
|
||||
{/* 文件上传区域 */}
|
||||
<div style={{ marginBottom: '40px' }}>
|
||||
<span className="text-lg block text-zinc-700 py-2">第一步:上传文件</span>
|
||||
{/* 如果没有已上传文件,显示上传区域 */}
|
||||
<Form form={form}>
|
||||
<Form.Item name="file">
|
||||
<TusUploader
|
||||
multiple={false}
|
||||
style={"w-full py-4"}
|
||||
></TusUploader>
|
||||
</Form.Item>
|
||||
</Form>
|
||||
</div>
|
||||
<>
|
||||
{
|
||||
isGetingFileId ?
|
||||
(<Spin spinning={isGetingFileId} fullscreen />) :
|
||||
(<div style={{ maxWidth: '800px', margin: '0 auto', padding: '20px' }}>
|
||||
<span className="text-2xl py-4">文件分享中心</span>
|
||||
<Tabs defaultActiveKey="upload">
|
||||
<TabPane tab="上传分享" key="upload">
|
||||
{/* 文件上传区域 */}
|
||||
<div style={{ marginBottom: '40px' }}>
|
||||
<span className="text-lg block text-zinc-700 py-2">第一步:上传文件</span>
|
||||
{/* 如果没有已上传文件,显示上传区域 */}
|
||||
<Form form={form}>
|
||||
<Form.Item name="file">
|
||||
<TusUploader
|
||||
multiple={false}
|
||||
style={"w-full py-4"}
|
||||
></TusUploader>
|
||||
</Form.Item>
|
||||
</Form>
|
||||
</div>
|
||||
|
||||
{/* 生成分享码区域 */}
|
||||
<div style={{ marginBottom: '40px' }}>
|
||||
<span className="text-lg block text-zinc-700 py-4">第二步:生成分享码</span>
|
||||
<ShareCodeGenerator
|
||||
fileId={uploadFileId}
|
||||
onSuccess={handleShareSuccess}
|
||||
/>
|
||||
</div>
|
||||
</TabPane>
|
||||
{/* 生成分享码区域 */}
|
||||
<div style={{ marginBottom: '40px' }}>
|
||||
<span className="text-lg block text-zinc-700 py-4">第二步:生成分享码</span>
|
||||
<ShareCodeGenerator
|
||||
fileId={uploadFileId}
|
||||
onSuccess={handleShareSuccess}
|
||||
/>
|
||||
</div>
|
||||
</TabPane>
|
||||
|
||||
{/* 使用分享码区域 */}
|
||||
<TabPane tab="下载文件" key="download">
|
||||
<div>
|
||||
<span className="text-lg block text-zinc-700 py-4">使用分享码下载文件</span>
|
||||
<ShareCodeValidator
|
||||
onValidSuccess={handleValidSuccess}
|
||||
/>
|
||||
</div>
|
||||
</TabPane>
|
||||
</Tabs>
|
||||
</div>)
|
||||
}
|
||||
</>
|
||||
)
|
||||
|
||||
{/* 使用分享码区域 */}
|
||||
<TabPane tab="下载文件" key="download">
|
||||
<div>
|
||||
<span className="text-lg block text-zinc-700 py-4">使用分享码下载文件</span>
|
||||
<ShareCodeValidator
|
||||
onValidSuccess={handleValidSuccess}
|
||||
/>
|
||||
</div>
|
||||
</TabPane>
|
||||
</Tabs>
|
||||
</div>
|
||||
);
|
||||
}
|
|
@ -14,7 +14,7 @@ interface ShareCodeGeneratorProps {
|
|||
interface ShareCodeResponse {
|
||||
code?: string;
|
||||
expiresAt?: Date;
|
||||
}
|
||||
}
|
||||
export const ShareCodeGenerator: React.FC<ShareCodeGeneratorProps> = ({
|
||||
fileId,
|
||||
onSuccess,
|
||||
|
@ -39,6 +39,10 @@ export const ShareCodeGenerator: React.FC<ShareCodeGeneratorProps> = ({
|
|||
setCurrentFileId(fileId);
|
||||
}, [fileId])
|
||||
const generateCode = async () => {
|
||||
if (!fileId) {
|
||||
message.error('请先上传文件');
|
||||
return;
|
||||
}
|
||||
setLoading(true);
|
||||
console.log('开始生成分享码,fileId:', fileId, 'fileName:', fileName);
|
||||
try {
|
||||
|
@ -48,7 +52,7 @@ export const ShareCodeGenerator: React.FC<ShareCodeGeneratorProps> = ({
|
|||
setIsGenerate(true);
|
||||
setExpiresAt(data.expiresAt ? new Date(data.expiresAt) : null);
|
||||
onSuccess?.(data.code);
|
||||
message.success('分享码生成成功');
|
||||
//message.success('分享码生成成功');
|
||||
} catch (error) {
|
||||
console.error('生成分享码错误:', error);
|
||||
message.error('生成分享码失败: ' + (error instanceof Error ? error.message : '未知错误'));
|
||||
|
@ -56,6 +60,26 @@ export const ShareCodeGenerator: React.FC<ShareCodeGeneratorProps> = ({
|
|||
setLoading(false);
|
||||
}
|
||||
};
|
||||
function copyToClipboard(text) {
|
||||
if (navigator.clipboard) {
|
||||
return navigator.clipboard.writeText(text);
|
||||
} else {
|
||||
const textarea = document.createElement('textarea');
|
||||
textarea.value = text;
|
||||
document.body.appendChild(textarea);
|
||||
textarea.select();
|
||||
document.execCommand('copy');
|
||||
document.body.removeChild(textarea);
|
||||
return Promise.resolve();
|
||||
}
|
||||
}
|
||||
|
||||
// 组件使用
|
||||
const handleCopy = (code) => {
|
||||
copyToClipboard(code)
|
||||
.then(() => console.log('复制成功'))
|
||||
.catch(() => console.error('复制失败'));
|
||||
};
|
||||
|
||||
return (
|
||||
<div style={{ padding: '20px', backgroundColor: '#f8f9fa', borderRadius: '8px' }}>
|
||||
|
@ -96,7 +120,8 @@ export const ShareCodeGenerator: React.FC<ShareCodeGeneratorProps> = ({
|
|||
<Button
|
||||
icon={<CopyOutlined />}
|
||||
onClick={() => {
|
||||
navigator.clipboard.writeText(shareCode);
|
||||
handleCopy(shareCode)
|
||||
//navigator.clipboard.writeText(shareCode);
|
||||
message.success('分享码已复制');
|
||||
}}
|
||||
/>
|
||||
|
|
|
@ -22,23 +22,23 @@ export const ShareCodeValidator: React.FC<ShareCodeValidatorProps> = ({
|
|||
|
||||
|
||||
const validateCode = useCallback(() => {
|
||||
|
||||
if (!code.trim()) {
|
||||
message.warning('请输入分享码');
|
||||
message.warning('请输入正确的分享码');
|
||||
return;
|
||||
}
|
||||
|
||||
setLoading(true);
|
||||
try {
|
||||
console.log('验证分享码返回数据:', result);
|
||||
onValidSuccess(result.fileId, result.fileName);
|
||||
message.success(`验证成功,文件名:${result.fileName}`);
|
||||
onValidSuccess(result.url, result.fileName);
|
||||
message.success(`验证成功,文件名:${result.fileName},请等待下载...`);
|
||||
} catch (error) {
|
||||
console.error('验证分享码失败:', error);
|
||||
message.error('分享码无效或已过期');
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
},[result])
|
||||
},[result,code, onValidSuccess])
|
||||
|
||||
return (
|
||||
<div className={styles.container}>
|
||||
|
|
|
@ -32,7 +32,7 @@ importers:
|
|||
specifier: ^10.3.10
|
||||
version: 10.4.15(@nestjs/common@10.4.15(reflect-metadata@0.2.2)(rxjs@7.8.1))(@nestjs/websockets@10.4.15)(rxjs@7.8.1)
|
||||
'@nestjs/schedule':
|
||||
specifier: ^4.1.0
|
||||
specifier: ^4.1.2
|
||||
version: 4.1.2(@nestjs/common@10.4.15(reflect-metadata@0.2.2)(rxjs@7.8.1))(@nestjs/core@10.4.15)
|
||||
'@nestjs/websockets':
|
||||
specifier: ^10.3.10
|
||||
|
|
Binary file not shown.
Loading…
Reference in New Issue