2025-04-02 21:59:19 +08:00
|
|
|
|
import React, { useEffect, useState } from 'react';
|
2025-04-08 09:29:14 +08:00
|
|
|
|
import { Button, DatePicker, Form, message, Select } from 'antd';
|
2025-04-02 16:14:30 +08:00
|
|
|
|
import { CopyOutlined } from '@ant-design/icons';
|
2025-04-02 21:59:19 +08:00
|
|
|
|
import { useQueryClient } from '@tanstack/react-query';
|
|
|
|
|
import { getQueryKey } from '@trpc/react-query';
|
|
|
|
|
import { api } from '@nice/client';
|
2025-04-08 09:29:14 +08:00
|
|
|
|
import dayjs from 'dayjs';
|
|
|
|
|
import utc from 'dayjs/plugin/utc';
|
|
|
|
|
import timezone from 'dayjs/plugin/timezone';
|
2025-04-09 17:01:21 +08:00
|
|
|
|
import { ShareCodeResponse, useQuickFileContext } from '../quick-file/quickFileContext';
|
2025-04-08 09:29:14 +08:00
|
|
|
|
dayjs.extend(utc);
|
|
|
|
|
dayjs.extend(timezone);
|
2025-04-02 16:14:30 +08:00
|
|
|
|
interface ShareCodeGeneratorProps {
|
|
|
|
|
fileId: string;
|
|
|
|
|
onSuccess?: (code: string) => void;
|
|
|
|
|
fileName?: string;
|
|
|
|
|
}
|
2025-04-09 17:01:21 +08:00
|
|
|
|
|
2025-04-08 13:06:40 +08:00
|
|
|
|
|
|
|
|
|
export 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();
|
|
|
|
|
}
|
|
|
|
|
}
|
2025-04-02 16:14:30 +08:00
|
|
|
|
export const ShareCodeGenerator: React.FC<ShareCodeGeneratorProps> = ({
|
|
|
|
|
fileId,
|
|
|
|
|
fileName,
|
|
|
|
|
}) => {
|
|
|
|
|
const [loading, setLoading] = useState(false);
|
|
|
|
|
const [shareCode, setShareCode] = useState<string>('');
|
2025-04-08 10:39:48 +08:00
|
|
|
|
const [expiresAt, setExpiresAt] = useState<string | null>(null);
|
2025-04-08 09:29:14 +08:00
|
|
|
|
const [canUseTimes, setCanUseTimes] = useState<number>(null);
|
2025-04-02 21:59:19 +08:00
|
|
|
|
const queryClient = useQueryClient();
|
2025-04-10 11:10:33 +08:00
|
|
|
|
const queryKey = getQueryKey(api.shareCode);
|
2025-04-02 21:59:19 +08:00
|
|
|
|
const [isGenerate, setIsGenerate] = useState(false);
|
|
|
|
|
const [currentFileId, setCurrentFileId] = useState<string>('');
|
2025-04-08 09:29:14 +08:00
|
|
|
|
const [form] = Form.useForm();
|
2025-04-09 17:01:21 +08:00
|
|
|
|
const { saveCodeRecord } = useQuickFileContext();
|
2025-04-02 21:59:19 +08:00
|
|
|
|
const generateShareCode = api.shareCode.generateShareCodeByFileId.useMutation({
|
|
|
|
|
onSuccess: (data) => {
|
|
|
|
|
queryClient.invalidateQueries({ queryKey });
|
|
|
|
|
},
|
|
|
|
|
});
|
|
|
|
|
useEffect(() => {
|
|
|
|
|
if (fileId !== currentFileId || !fileId) {
|
|
|
|
|
setIsGenerate(false);
|
|
|
|
|
}
|
|
|
|
|
setCurrentFileId(fileId);
|
|
|
|
|
}, [fileId])
|
2025-04-02 16:14:30 +08:00
|
|
|
|
const generateCode = async () => {
|
2025-04-03 13:27:58 +08:00
|
|
|
|
if (!fileId) {
|
|
|
|
|
message.error('请先上传文件');
|
|
|
|
|
return;
|
|
|
|
|
}
|
2025-04-02 16:14:30 +08:00
|
|
|
|
setLoading(true);
|
|
|
|
|
console.log('开始生成分享码,fileId:', fileId, 'fileName:', fileName);
|
|
|
|
|
try {
|
2025-04-08 09:29:14 +08:00
|
|
|
|
const data: ShareCodeResponse = await generateShareCode.mutateAsync({
|
|
|
|
|
fileId,
|
2025-04-08 10:24:14 +08:00
|
|
|
|
expiresAt: form.getFieldsValue()?.expiresAt ? form.getFieldsValue().expiresAt.tz('Asia/Shanghai').toDate() : dayjs().add(1, 'day').tz('Asia/Shanghai').toDate(),
|
2025-04-08 09:29:14 +08:00
|
|
|
|
canUseTimes: form.getFieldsValue()?.canUseTimes ? form.getFieldsValue().canUseTimes : 10,
|
|
|
|
|
});
|
2025-04-08 10:24:14 +08:00
|
|
|
|
console.log('data', data)
|
2025-04-02 16:14:30 +08:00
|
|
|
|
setShareCode(data.code);
|
2025-04-02 21:59:19 +08:00
|
|
|
|
setIsGenerate(true);
|
2025-04-08 10:39:48 +08:00
|
|
|
|
setExpiresAt(dayjs(data.expiresAt).format('YYYY-MM-DD HH:mm:ss'));
|
2025-04-08 09:29:14 +08:00
|
|
|
|
setCanUseTimes(data.canUseTimes);
|
2025-04-09 17:01:21 +08:00
|
|
|
|
saveCodeRecord(data,'shareCodeGeneratorRecords');
|
|
|
|
|
message.success('分享码生成成功'+data.code);
|
2025-04-02 16:14:30 +08:00
|
|
|
|
} catch (error) {
|
|
|
|
|
console.error('生成分享码错误:', error);
|
|
|
|
|
message.error('生成分享码失败: ' + (error instanceof Error ? error.message : '未知错误'));
|
|
|
|
|
} finally {
|
|
|
|
|
setLoading(false);
|
|
|
|
|
}
|
|
|
|
|
};
|
2025-04-08 13:06:40 +08:00
|
|
|
|
|
2025-04-03 13:27:58 +08:00
|
|
|
|
const handleCopy = (code) => {
|
|
|
|
|
copyToClipboard(code)
|
|
|
|
|
.then(() => console.log('复制成功'))
|
|
|
|
|
.catch(() => console.error('复制失败'));
|
|
|
|
|
};
|
2025-04-08 09:29:14 +08:00
|
|
|
|
useEffect(() => {
|
|
|
|
|
const date = dayjs().add(1, 'day').tz('Asia/Shanghai');
|
|
|
|
|
form.setFieldsValue({
|
|
|
|
|
expiresAt: date,
|
|
|
|
|
canUseTimes: 10
|
|
|
|
|
});
|
|
|
|
|
}, [form]);
|
2025-04-02 16:14:30 +08:00
|
|
|
|
|
2025-04-08 10:24:14 +08:00
|
|
|
|
useEffect(() => {
|
2025-04-08 09:29:14 +08:00
|
|
|
|
if (fileId) {
|
|
|
|
|
generateCode()
|
|
|
|
|
}
|
|
|
|
|
}, [fileId])
|
2025-04-02 16:14:30 +08:00
|
|
|
|
return (
|
|
|
|
|
<div style={{ padding: '20px', backgroundColor: '#f8f9fa', borderRadius: '8px' }}>
|
2025-04-08 09:29:14 +08:00
|
|
|
|
<div style={{ marginBottom: '3px' }}>
|
|
|
|
|
<small style={{ color: '#666' }}>文件ID: {fileId ? fileId : '暂未上传文件'}</small>
|
2025-04-02 16:14:30 +08:00
|
|
|
|
</div>
|
2025-04-02 21:59:19 +08:00
|
|
|
|
{!isGenerate ? (
|
2025-04-08 09:29:14 +08:00
|
|
|
|
<>
|
|
|
|
|
<Form form={form}>
|
|
|
|
|
<div className='w-4/5 h-16 flex flex-row justify-between items-center'>
|
|
|
|
|
<small style={{ color: '#666' }}>
|
|
|
|
|
{"分享码的有效期"}
|
|
|
|
|
</small>
|
|
|
|
|
<Form.Item name="expiresAt" className='mt-5'>
|
|
|
|
|
<DatePicker
|
|
|
|
|
showTime
|
2025-04-08 10:24:14 +08:00
|
|
|
|
disabledDate={(current) => current && current < dayjs().startOf('day')}
|
|
|
|
|
disabledTime={(current) => {
|
|
|
|
|
if (current && current.isSame(dayjs(), 'day')) {
|
|
|
|
|
return {
|
|
|
|
|
disabledHours: () => [...Array(dayjs().hour() + 1).keys()],
|
|
|
|
|
disabledMinutes: (selectedHour) => {
|
|
|
|
|
if (selectedHour === dayjs().hour()) {
|
|
|
|
|
return [...Array(dayjs().minute() + 1).keys()];
|
|
|
|
|
}
|
|
|
|
|
return [];
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
return {};
|
|
|
|
|
}}
|
2025-04-08 09:29:14 +08:00
|
|
|
|
/>
|
|
|
|
|
</Form.Item>
|
|
|
|
|
<small style={{ color: '#666' }}>
|
|
|
|
|
{"分享码的使用次数"}
|
|
|
|
|
</small>
|
|
|
|
|
<Form.Item name="canUseTimes" className='mt-5'>
|
|
|
|
|
<Select
|
|
|
|
|
style={{ width: 120 }}
|
|
|
|
|
//onChange={handleChange}
|
|
|
|
|
options={[
|
|
|
|
|
{ value: 10, label: '10' },
|
|
|
|
|
{ value: 20, label: '20' },
|
|
|
|
|
{ value: 30, label: '30' },
|
|
|
|
|
{ value: 40, label: '40' },
|
|
|
|
|
{ value: 50, label: '50' },
|
|
|
|
|
]}
|
|
|
|
|
/>
|
|
|
|
|
</Form.Item>
|
|
|
|
|
</div>
|
|
|
|
|
</Form>
|
|
|
|
|
</>
|
|
|
|
|
|
2025-04-02 16:14:30 +08:00
|
|
|
|
) : (
|
|
|
|
|
<div style={{ textAlign: 'center' }}>
|
2025-04-02 21:59:19 +08:00
|
|
|
|
<div style={{
|
2025-04-02 16:14:30 +08:00
|
|
|
|
display: 'flex',
|
|
|
|
|
alignItems: 'center',
|
|
|
|
|
justifyContent: 'center',
|
|
|
|
|
gap: '12px',
|
|
|
|
|
margin: '16px 0'
|
|
|
|
|
}}>
|
|
|
|
|
<span style={{
|
|
|
|
|
fontSize: '24px',
|
|
|
|
|
fontWeight: 'bold',
|
|
|
|
|
letterSpacing: '2px',
|
|
|
|
|
color: '#1890ff',
|
|
|
|
|
padding: '8px 16px',
|
|
|
|
|
backgroundColor: '#e6f7ff',
|
|
|
|
|
borderRadius: '4px'
|
|
|
|
|
}}>
|
|
|
|
|
{shareCode}
|
|
|
|
|
</span>
|
|
|
|
|
<Button
|
|
|
|
|
icon={<CopyOutlined />}
|
|
|
|
|
onClick={() => {
|
2025-04-03 13:27:58 +08:00
|
|
|
|
handleCopy(shareCode)
|
|
|
|
|
//navigator.clipboard.writeText(shareCode);
|
2025-04-02 16:14:30 +08:00
|
|
|
|
message.success('分享码已复制');
|
|
|
|
|
}}
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
2025-04-08 09:29:14 +08:00
|
|
|
|
{isGenerate && expiresAt ? (
|
2025-04-02 16:14:30 +08:00
|
|
|
|
<div style={{ color: '#666' }}>
|
2025-04-08 10:39:48 +08:00
|
|
|
|
有效期至: {expiresAt} 可使用次数: {canUseTimes}
|
2025-04-02 16:14:30 +08:00
|
|
|
|
</div>
|
|
|
|
|
) : (
|
|
|
|
|
<div style={{ color: 'red' }}>
|
|
|
|
|
未获取到有效期信息
|
|
|
|
|
</div>
|
|
|
|
|
)}
|
|
|
|
|
</div>
|
|
|
|
|
)}
|
|
|
|
|
</div>
|
|
|
|
|
);
|
|
|
|
|
};
|