feat:添加链接QR支持,删除无用文件

This commit is contained in:
MatrixSeven
2025-08-05 18:02:00 +08:00
parent 6cc66435f6
commit 3f3b7d8f18
8 changed files with 369 additions and 262 deletions

View File

@@ -50,19 +50,21 @@ export default function HomePage() {
</TabsTrigger>
<TabsTrigger
value="text"
className="flex items-center justify-center space-x-2 px-4 py-3 text-sm font-medium rounded-lg transition-all duration-200 hover:bg-slate-50 data-[state=active]:bg-emerald-500 data-[state=active]:text-white data-[state=active]:shadow-md data-[state=active]:hover:bg-emerald-600"
className="flex items-center justify-center space-x-2 px-4 py-3 text-sm font-medium rounded-lg transition-all duration-200 hover:bg-slate-50 data-[state=active]:bg-emerald-500 data-[state=active]:text-white data-[state=active]:shadow-md data-[state=active]:hover:bg-emerald-600 relative"
>
<MessageSquare className="w-4 h-4" />
<span className="hidden sm:inline"></span>
<span className="sm:hidden"></span>
<span className="text-xs bg-orange-100 text-orange-600 px-1.5 py-0.5 rounded ml-1 absolute -top-1 -right-1"></span>
</TabsTrigger>
<TabsTrigger
value="desktop"
className="flex items-center justify-center space-x-2 px-4 py-3 text-sm font-medium rounded-lg transition-all duration-200 hover:bg-slate-50 data-[state=active]:bg-purple-500 data-[state=active]:text-white data-[state=active]:shadow-md data-[state=active]:hover:bg-purple-600"
className="flex items-center justify-center space-x-2 px-4 py-3 text-sm font-medium rounded-lg transition-all duration-200 hover:bg-slate-50 data-[state=active]:bg-purple-500 data-[state=active]:text-white data-[state=active]:shadow-md data-[state=active]:hover:bg-purple-600 relative"
>
<Monitor className="w-4 h-4" />
<span className="hidden sm:inline"></span>
<span className="sm:hidden"></span>
<span className="text-xs bg-orange-100 text-orange-600 px-1.5 py-0.5 rounded ml-1 absolute -top-1 -right-1"></span>
</TabsTrigger>
</TabsList>
</div>
@@ -74,49 +76,43 @@ export default function HomePage() {
</TabsContent>
<TabsContent value="text" className="mt-0 animate-fade-in-up">
<TextTransfer
onSendText={async (text: string) => {
try {
const response = await fetch('/api/create-text-room', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ text }),
});
const data = await response.json();
if (!response.ok) {
throw new Error(data.error || '创建文本房间失败');
}
return data.code;
} catch (error) {
console.error('创建文本房间失败:', error);
throw error;
}
}}
onReceiveText={async (code: string) => {
try {
const response = await fetch(`/api/get-text-content?code=${code}`);
const data = await response.json();
if (!response.ok) {
throw new Error(data.error || '获取文本内容失败');
}
return data.text;
} catch (error) {
console.error('获取文本内容失败:', error);
throw error;
}
}}
/>
<div className="max-w-md mx-auto p-8 bg-white/90 backdrop-blur-sm rounded-2xl shadow-lg border border-slate-200">
<div className="text-center">
<div className="w-16 h-16 mx-auto mb-4 bg-gradient-to-br from-emerald-100 to-emerald-200 rounded-full flex items-center justify-center">
<MessageSquare className="w-8 h-8 text-emerald-600" />
</div>
<h3 className="text-xl font-semibold text-slate-800 mb-2"></h3>
<p className="text-slate-600 mb-4">...</p>
<div className="bg-emerald-50 border border-emerald-200 rounded-lg p-4">
<p className="text-sm text-emerald-700">
🚧 便
</p>
</div>
<p className="text-xs text-slate-500 mt-4">
使
</p>
</div>
</div>
</TabsContent>
<TabsContent value="desktop" className="mt-0 animate-fade-in-up">
<DesktopShare />
<div className="max-w-md mx-auto p-8 bg-white/90 backdrop-blur-sm rounded-2xl shadow-lg border border-slate-200">
<div className="text-center">
<div className="w-16 h-16 mx-auto mb-4 bg-gradient-to-br from-purple-100 to-purple-200 rounded-full flex items-center justify-center">
<Monitor className="w-8 h-8 text-purple-600" />
</div>
<h3 className="text-xl font-semibold text-slate-800 mb-2"></h3>
<p className="text-slate-600 mb-4">...</p>
<div className="bg-purple-50 border border-purple-200 rounded-lg p-4">
<p className="text-sm text-purple-700">
🚧
</p>
</div>
<p className="text-xs text-slate-500 mt-4">
使
</p>
</div>
</div>
</TabsContent>
</div>
</Tabs>

View File

@@ -7,6 +7,13 @@ export async function GET(request: NextRequest) {
const { searchParams } = new URL(request.url);
const code = searchParams.get('code');
if (!code) {
return NextResponse.json(
{ error: 'Missing code parameter' },
{ status: 400 }
);
}
console.log('API Route: Getting room info, proxying to:', `${GO_BACKEND_URL}/api/room-info?code=${code}`);
const response = await fetch(`${GO_BACKEND_URL}/api/room-info?code=${code}`, {

View File

@@ -0,0 +1,68 @@
"use client";
import React, { useEffect, useRef, useState } from 'react';
import QRCode from 'qrcode';
interface QRCodeDisplayProps {
value: string;
size?: number;
className?: string;
title?: string;
}
export default function QRCodeDisplay({
value,
size = 200,
className = "",
title = "扫码传输"
}: QRCodeDisplayProps) {
const canvasRef = useRef<HTMLCanvasElement>(null);
const [error, setError] = useState<string>('');
useEffect(() => {
const generateQR = async () => {
try {
if (canvasRef.current && value) {
await QRCode.toCanvas(canvasRef.current, value, {
width: size,
margin: 2,
color: {
dark: '#1e293b', // slate-800
light: '#ffffff'
}
});
setError('');
}
} catch (err) {
console.error('生成二维码失败:', err);
setError('生成二维码失败');
}
};
generateQR();
}, [value, size]);
if (error) {
return (
<div className={`flex items-center justify-center bg-slate-100 rounded-lg ${className}`}
style={{ width: size, height: size }}>
<p className="text-sm text-slate-500">{error}</p>
</div>
);
}
return (
<div className={className}>
{title && (
<h3 className="text-sm font-medium text-slate-700 text-center mb-3">{title}</h3>
)}
<div className="flex justify-center">
<canvas
ref={canvasRef}
className="rounded-lg"
style={{ maxWidth: '100%', height: 'auto' }}
/>
</div>
</div>
);
}

View File

@@ -4,6 +4,7 @@ import React, { useState, useRef, useCallback } from 'react';
import { Button } from '@/components/ui/button';
import { useToast } from '@/components/ui/toast-simple';
import { Upload, FileText, Image, Video, Music, Archive, X } from 'lucide-react';
import QRCodeDisplay from '@/components/QRCodeDisplay';
interface FileInfo {
id: string;
@@ -398,62 +399,77 @@ export function WebRTCFileUpload({
{/* 取件码展示 */}
{pickupCode && (
<div className="border-t border-slate-200 pt-6">
<div className="text-center mb-4 sm:mb-6">
<div className="w-12 h-12 sm:w-16 sm:h-16 mx-auto mb-4 bg-gradient-to-br from-emerald-500 to-teal-500 rounded-2xl flex items-center justify-center animate-float">
<FileText className="w-6 h-6 sm:w-8 sm:h-8 text-white" />
</div>
<h3 className="text-xl sm:text-2xl font-bold bg-gradient-to-r from-emerald-600 to-teal-600 bg-clip-text text-transparent mb-2">
</h3>
<p className="text-sm sm:text-base text-slate-600"></p>
</div>
<div className="space-y-4 sm:space-y-6">
{/* 取件码 */}
<div>
<label className="block text-sm font-medium text-slate-700 mb-3"></label>
<div className="flex flex-col sm:flex-row gap-3">
<div className="flex-1 code-display rounded-xl p-4 sm:p-6 text-center">
<div className="text-2xl sm:text-3xl font-bold font-mono bg-gradient-to-r from-emerald-600 to-teal-600 bg-clip-text text-transparent tracking-wider">
{pickupCode}
</div>
</div>
<Button
onClick={onCopyCode}
className="px-4 sm:px-6 py-3 bg-emerald-500 hover:bg-emerald-600 text-white rounded-xl font-medium shadow-lg transition-all duration-200 hover:shadow-xl w-full sm:w-auto"
>
</Button>
{/* 左上角状态提示 - 类似已选择文件的风格 */}
<div className="flex items-center mb-6">
<div className="flex items-center space-x-3">
<div className="w-10 h-10 bg-gradient-to-br from-emerald-500 to-teal-500 rounded-xl flex items-center justify-center">
<FileText className="w-5 h-5 text-white" />
</div>
<div>
<h3 className="text-lg font-semibold text-slate-800"></h3>
<p className="text-sm text-slate-600"></p>
</div>
</div>
</div>
{/* 取件链接 */}
{/* 中间区域:取件码 + 分隔线 + 二维码 */}
<div className="flex flex-col lg:flex-row lg:items-start gap-6 lg:gap-8 mb-8">
{/* 左侧:取件码 */}
<div className="flex-1">
<label className="block text-sm font-medium text-slate-700 mb-3"></label>
<div className="flex flex-col items-center rounded-xl border border-slate-200 p-6 h-40 justify-center bg-slate-50">
<div className="text-2xl font-bold font-mono bg-gradient-to-r from-emerald-600 to-teal-600 bg-clip-text text-transparent tracking-wider">
{pickupCode}
</div>
</div>
<Button
onClick={onCopyCode}
className="w-full px-4 py-2.5 bg-emerald-500 hover:bg-emerald-600 text-white rounded-lg font-medium shadow transition-all duration-200 mt-3"
>
</Button>
</div>
{/* 分隔线 - 大屏幕显示竖线,移动端隐藏 */}
<div className="hidden lg:block w-px bg-slate-200 h-64 mt-6"></div>
{/* 右侧:二维码 */}
{pickupLink && (
<div>
<label className="block text-sm font-medium text-slate-700 mb-3"></label>
<div className="flex flex-col sm:flex-row gap-3">
<div className="flex-1 code-display rounded-xl p-3 sm:p-4">
<div className="text-xs sm:text-sm text-slate-700 break-all font-mono">
{pickupLink}
</div>
</div>
<Button
onClick={onCopyLink}
className="px-4 sm:px-6 py-3 bg-blue-500 hover:bg-blue-600 text-white rounded-xl font-medium shadow-lg transition-all duration-200 hover:shadow-xl w-full sm:w-auto"
>
</Button>
<div className="flex-1">
<label className="block text-sm font-medium text-slate-700 mb-3"></label>
<div className="flex flex-col items-center rounded-xl border border-slate-200 p-6 h-40 justify-center bg-slate-50">
<QRCodeDisplay
value={pickupLink}
size={120}
title=""
className="w-auto"
/>
</div>
<div className="w-full px-4 py-2.5 bg-blue-500 text-white rounded-lg font-medium shadow transition-all duration-200 mt-3 text-center">
使访
</div>
</div>
)}
</div>
{/* 使用提示 */}
<div className="mt-4 sm:mt-6 p-3 sm:p-4 bg-gradient-to-r from-blue-50 to-indigo-50 rounded-xl border border-blue-200">
<p className="text-xs sm:text-sm text-slate-600 text-center">
💡 <span className="font-medium">使</span>访
</p>
</div>
{/* 底部:取件链接 */}
{pickupLink && (
<div className="space-y-3">
<div className="flex gap-3">
<div className="flex-1 code-display rounded-lg p-3 bg-slate-50 border border-slate-200">
<div className="text-sm text-slate-700 break-all font-mono leading-relaxed">
{pickupLink}
</div>
</div>
<Button
onClick={onCopyLink}
className="px-4 py-2.5 bg-blue-500 hover:bg-blue-600 text-white rounded-lg font-medium shadow transition-all duration-200 shrink-0"
>
</Button>
</div>
</div>
)}
</div>
)}
</div>

View File

@@ -75,10 +75,10 @@ export const useTabManager = (isConnected: boolean, pickupCode: string, isConnec
currentMode = '文件传输';
break;
case 'text':
currentMode = '文字传输';
currentMode = '文字传输(开发中)';
break;
case 'desktop':
currentMode = '桌面共享';
currentMode = '桌面共享(开发中)';
break;
}
@@ -87,10 +87,10 @@ export const useTabManager = (isConnected: boolean, pickupCode: string, isConnec
targetMode = '文件传输';
break;
case 'text':
targetMode = '文字传输';
targetMode = '文字传输(开发中)';
break;
case 'desktop':
targetMode = '桌面共享';
targetMode = '桌面共享(开发中)';
break;
}