collect-system/apps/web/src/app/admin/sharecode/sharecodegenerator.tsx

198 lines
6.7 KiB
TypeScript
Raw Normal View History

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>
);
};