blob: 493cdcec3f33f63bd264dafe01fee4d296ad13ce [file] [log] [blame]
import React, { useState } from 'react';
import {
Box, Container, Typography, Paper,
TextField, Button, Stack
} from '@mui/material';
import CloudUploadIcon from '@mui/icons-material/CloudUpload';
// Assuming your base.css is in a relative path like src/styles/base/base.css
// If your component is in src/components/Upload.js, this path would be ../styles/base/base.css
// Adjust if your project structure is different.
// For this example, I'll assume it's correctly linked.
// import '../styles/base/base.css';
function Upload() {
const [title, setTitle] = useState('');
const [file, setFile] = useState(null);
const handleUpload = () => {
const formData = new FormData();
if (file) {
formData.append('file', file);
}
formData.append('title', title);
// Replace with your actual API endpoint and error handling
fetch('/api/torrents/upload', {
method: 'POST',
body: formData
})
.then(response => {
if (response.ok) {
// Use a more modern way to show messages, e.g., a Snackbar
console.log('上传成功');
alert('上传成功 (建议使用Snackbar等UI组件替代alert)');
} else {
console.error('上传失败');
alert('上传失败 (建议使用Snackbar等UI组件替代alert)');
}
})
.catch(error => {
console.error('上传出错:', error);
alert('上传出错 (建议使用Snackbar等UI组件替代alert)');
});
};
return (
<Box sx={{ minHeight: '100vh', py: 4, background: 'linear-gradient(135deg, #2c3e50, #4ca1af)', color: 'white' }}> {/* Moved body styles here for self-containment */}
<Container maxWidth="sm" sx={{ position: 'relative', zIndex: 10 }}>
<Typography variant="h4" sx={{ textAlign: 'center', mb: 3, fontWeight: 'bold' }}> {/* Replaced className with sx */}
⬆️ 上传种子 · Mini-Tracker
</Typography>
<Paper sx={{ position: 'relative', zIndex: 20, padding: '2rem', backgroundColor: 'rgba(30, 30, 30, 0.9)' }}> {/* Replaced className with sx */}
<Stack spacing={3}> {/* Increased spacing a bit */}
<TextField
label="资源名称"
variant="outlined"
fullWidth
value={title}
onChange={e => setTitle(e.target.value)}
placeholder="请输入资源名称"
InputLabelProps={{
sx: {
color: '#ccc',
'&.Mui-focused': { // Ensure label color remains consistent when focused
color: '#ccc',
}
}
}}
sx={{
// Root element of the TextField
backgroundColor: 'transparent',
// Styles for the HTML input element itself
'& .MuiInputBase-input': {
color: 'white', // Text color
backgroundColor: 'transparent', // **** THIS IS THE FIX **** Ensure input background is transparent
caretColor: 'white', // Cursor color
'&::placeholder': {
color: '#bbb',
opacity: 1,
},
},
// Styles for the outlined border
'& .MuiOutlinedInput-root': {
'& fieldset': {
borderColor: '#888', // Default border color
},
'&:hover fieldset': {
borderColor: '#aaa', // Border color on hover
},
'&.Mui-focused fieldset': {
borderColor: '#fff', // Border color when focused
},
},
}}
/>
<Button
variant="contained"
component="label" // Allows the button to act as a label for a hidden input
startIcon={<CloudUploadIcon />}
sx={{ backgroundColor: '#00bcd4', color: 'white', '&:hover': { backgroundColor: '#0097a7' } }} // Replaced className with sx
>
选择种子文件
<input
hidden
type="file"
accept=".torrent"
onChange={e => {
if (e.target.files && e.target.files[0]) {
setFile(e.target.files[0]);
}
}}
/>
</Button>
{file && (
<Typography variant="body2" sx={{ color: '#eee', textAlign: 'center' }}>
已选择文件: {file.name}
</Typography>
)}
<Button
variant="outlined"
onClick={handleUpload}
disabled={!file || !title}
sx={{ borderColor: 'white', color: 'white', '&:hover': { borderColor: '#ddd', backgroundColor: 'rgba(255,255,255,0.1)'}, '&.Mui-disabled': { borderColor: '#777', color: '#777' } }} // Replaced className with sx
>
提交上传
</Button>
</Stack>
</Paper>
</Container>
{/* Background bubbles animation - assuming CSS for .bubbles and .bubble is globally available or defined in an imported CSS file */}
{/* For self-containment, these styles would ideally be JSS or defined in a <style> tag if not using styled-components or similar */}
<Box className="bubbles" sx={{
pointerEvents: 'none',
position: 'fixed',
top: 0,
left: 0,
width: '100%',
height: '100%',
overflow: 'hidden',
zIndex: 1, // Ensure it's behind the content paper but above the main background
}}>
{[...Array(40)].map((_, i) => (
<Box
key={i}
className="bubble" // Assuming .bubble and @keyframes rise are defined in your CSS
sx={{
position: 'absolute',
bottom: '-100px',
background: 'rgba(255, 255, 255, 0.15)',
borderRadius: '50%',
animation: 'rise 20s infinite ease-in', // Make sure @keyframes rise is defined
width: `${Math.random() * 20 + 10}px`,
height: `${Math.random() * 20 + 10}px`,
left: `${Math.random() * 100}%`,
animationDuration: `${10 + Math.random() * 20}s`,
animationDelay: `${Math.random() * 5}s`
}}
/>
))}
</Box>
{/* Define keyframes if not in external CSS */}
<style>
{`
@keyframes rise {
0% {
transform: translateY(0) scale(1);
opacity: 0.5;
}
50% {
opacity: 1;
}
100% {
transform: translateY(-120vh) scale(0.5);
opacity: 0;
}
}
body { /* Basic reset if base.css is not loaded */
margin: 0;
font-family: 'Roboto', sans-serif;
}
`}
</style>
</Box>
);
}
export default Upload;