956303669 | a32fc2c | 2025-06-02 19:45:53 +0800 | [diff] [blame] | 1 | import React from "react"; |
ssq | 5067cb9 | 2025-06-05 11:44:23 +0000 | [diff] [blame] | 2 | import { BrowserRouter as Router, Routes, Route, useNavigate, Link, Navigate } from "react-router-dom"; |
956303669 | a32fc2c | 2025-06-02 19:45:53 +0800 | [diff] [blame] | 3 | import MovieIcon from "@mui/icons-material/Movie"; |
| 4 | import EmailIcon from "@mui/icons-material/Email"; |
| 5 | import MusicNoteIcon from "@mui/icons-material/MusicNote"; |
| 6 | import EmojiPeopleIcon from "@mui/icons-material/EmojiPeople"; |
| 7 | import SportsEsportsIcon from "@mui/icons-material/SportsEsports"; |
| 8 | import SportsMartialArtsIcon from "@mui/icons-material/SportsMartialArts"; |
| 9 | import PersonIcon from "@mui/icons-material/Person"; |
| 10 | import AccountCircleIcon from "@mui/icons-material/AccountCircle"; |
wht | 6a1b678 | 2025-06-06 19:14:59 +0800 | [diff] [blame] | 11 | import ForumIcon from "@mui/icons-material/Forum"; |
956303669 | a32fc2c | 2025-06-02 19:45:53 +0800 | [diff] [blame] | 12 | import "./App.css"; |
| 13 | import MoviePage from "./MoviePage"; |
| 14 | import TVPage from "./TVPage"; |
| 15 | import MusicPage from "./MusicPage"; |
| 16 | import AnimePage from "./AnimePage"; |
| 17 | import GamePage from "./GamePage"; |
| 18 | import SportPage from "./SportPage"; |
| 19 | import InfoPage from "./InfoPage"; |
| 20 | import UserProfile from "./UserProfile"; |
956303669 | 9e95ae3 | 2025-06-02 21:42:11 +0800 | [diff] [blame] | 21 | import PublishPage from "./PublishPage"; |
| 22 | import TorrentDetailPage from './TorrentDetailPage'; |
wht | 6a1b678 | 2025-06-06 19:14:59 +0800 | [diff] [blame] | 23 | import ForumPage from "./ForumPage"; |
| 24 | import PostDetailPage from "./PostDetailPage"; |
ssq | 5067cb9 | 2025-06-05 11:44:23 +0000 | [diff] [blame] | 25 | import LoginPage from './LoginPage'; |
| 26 | import RegisterPage from './RegisterPage'; |
22301133 | 38fd388 | 2025-06-06 23:33:57 +0800 | [diff] [blame^] | 27 | import RequireAuth from './RequireAuth'; |
wht | 6a1b678 | 2025-06-06 19:14:59 +0800 | [diff] [blame] | 28 | |
956303669 | a32fc2c | 2025-06-02 19:45:53 +0800 | [diff] [blame] | 29 | const navItems = [ |
| 30 | { label: "电影", icon: <MovieIcon />, path: "/movie" }, |
| 31 | { label: "剧集", icon: <EmailIcon />, path: "/tv" }, |
| 32 | { label: "音乐", icon: <MusicNoteIcon />, path: "/music" }, |
| 33 | { label: "动漫", icon: <EmojiPeopleIcon />, path: "/anime" }, |
| 34 | { label: "游戏", icon: <SportsEsportsIcon />, path: "/game" }, |
| 35 | { label: "体育", icon: <SportsMartialArtsIcon />, path: "/sport" }, |
| 36 | { label: "资料", icon: <PersonIcon />, path: "/info" }, |
wht | 6a1b678 | 2025-06-06 19:14:59 +0800 | [diff] [blame] | 37 | { label: "论坛", icon: <ForumIcon />, path: "/forum" }, |
| 38 | { label: "发布", icon: <AccountCircleIcon />, path: "/publish" }, |
956303669 | a32fc2c | 2025-06-02 19:45:53 +0800 | [diff] [blame] | 39 | ]; |
| 40 | |
| 41 | function Home() { |
| 42 | const navigate = useNavigate(); |
| 43 | return ( |
| 44 | <div className="container"> |
| 45 | {/* 顶部空白与电影界面一致 */} |
| 46 | <div style={{ height: 80 }} /> |
| 47 | {/* 用户栏 */} |
| 48 | <div className="user-bar" style={{ position: 'fixed', top: 18, right: 42, zIndex: 100, display: 'flex', alignItems: 'center', background: '#e0f3ff', borderRadius: 12, padding: '6px 18px', boxShadow: '0 2px 8px #b2d8ea', minWidth: 320, minHeight: 48, width: 420 }}> |
| 49 | <div style={{ cursor: 'pointer', marginRight: 16 }} onClick={() => navigate('/user')}> |
| 50 | <AccountCircleIcon style={{ fontSize: 38, color: '#1a237e', background: '#e0f3ff', borderRadius: '50%' }} /> |
| 51 | </div> |
| 52 | <div style={{ color: '#222', fontWeight: 500, marginRight: 24 }}>用户栏</div> |
| 53 | <div style={{ display: 'flex', gap: 28, flex: 1, justifyContent: 'flex-end', alignItems: 'center' }}> |
| 54 | <span style={{ color: '#1976d2', fontWeight: 500 }}>魔力值: <b>12345</b></span> |
| 55 | <span style={{ color: '#1976d2', fontWeight: 500 }}>分享率: <b>2.56</b></span> |
| 56 | <span style={{ color: '#1976d2', fontWeight: 500 }}>上传量: <b>100GB</b></span> |
| 57 | <span style={{ color: '#1976d2', fontWeight: 500 }}>下载量: <b>50GB</b></span> |
| 58 | </div> |
| 59 | </div> |
956303669 | a32fc2c | 2025-06-02 19:45:53 +0800 | [diff] [blame] | 60 | <div style={{ height: 32 }} /> |
| 61 | <nav className="nav-bar card"> |
| 62 | {navItems.map((item) => ( |
| 63 | <div |
| 64 | key={item.label} |
| 65 | className={"nav-item"} |
| 66 | onClick={() => navigate(item.path)} |
| 67 | > |
| 68 | {item.icon} |
| 69 | <span>{item.label}</span> |
| 70 | </div> |
| 71 | ))} |
| 72 | </nav> |
| 73 | <div className="search-section card"> |
| 74 | <input className="search-input" placeholder="输入搜索关键词" /> |
| 75 | <button className="search-btn"> |
| 76 | <span role="img" aria-label="search">🔍</span> |
| 77 | </button> |
| 78 | </div> |
956303669 | a32fc2c | 2025-06-02 19:45:53 +0800 | [diff] [blame] | 79 | <div className="table-section card"> |
| 80 | <table className="movie-table"> |
| 81 | <thead> |
| 82 | <tr> |
| 83 | <th>类型</th> |
| 84 | <th>标题</th> |
| 85 | <th>发布者</th> |
| 86 | </tr> |
| 87 | </thead> |
| 88 | <tbody> |
| 89 | <tr> |
| 90 | <td>电影</td> |
| 91 | <td></td> |
| 92 | <td></td> |
| 93 | </tr> |
| 94 | <tr> |
| 95 | <td>剧集</td> |
| 96 | <td></td> |
| 97 | <td></td> |
| 98 | </tr> |
| 99 | <tr> |
| 100 | <td>音乐</td> |
| 101 | <td></td> |
| 102 | <td></td> |
| 103 | </tr> |
| 104 | <tr> |
| 105 | <td>动漫</td> |
| 106 | <td></td> |
| 107 | <td></td> |
| 108 | </tr> |
| 109 | <tr> |
| 110 | <td>游戏</td> |
| 111 | <td></td> |
| 112 | <td></td> |
| 113 | </tr> |
| 114 | </tbody> |
| 115 | </table> |
| 116 | </div> |
| 117 | <div style={{ height: 32 }} /> |
| 118 | <Pagination /> |
| 119 | </div> |
| 120 | ); |
| 121 | } |
| 122 | |
| 123 | function Pagination() { |
| 124 | const [page, setPage] = React.useState(3); |
| 125 | const total = 5; |
| 126 | return ( |
| 127 | <div className="pagination"> |
| 128 | <button onClick={() => setPage(p => Math.max(1, p - 1))} disabled={page === 1}>上一页</button> |
| 129 | <span className="page-num">{page}/{total}</span> |
| 130 | <button onClick={() => setPage(p => Math.min(total, p + 1))} disabled={page === total}>下一页</button> |
| 131 | <span className="page-info">第 <b>{page}</b> 页</span> |
| 132 | </div> |
| 133 | ); |
| 134 | } |
| 135 | |
| 136 | function Page({ label }) { |
| 137 | return ( |
| 138 | <div style={{ padding: 40, fontSize: 32 }}> |
| 139 | {label} 页面(可自定义内容) |
| 140 | <br /> |
| 141 | <Link to="/">返回首页</Link> |
| 142 | </div> |
| 143 | ); |
| 144 | } |
| 145 | |
| 146 | export default function App() { |
| 147 | return ( |
| 148 | <Router> |
| 149 | <Routes> |
ssq | 5067cb9 | 2025-06-05 11:44:23 +0000 | [diff] [blame] | 150 | <Route path="/login" element={<LoginPage />} /> |
| 151 | <Route path="/register" element={<RegisterPage />} /> |
| 152 | <Route path="/" element={<Navigate to="/login" replace />} /> |
22301133 | 38fd388 | 2025-06-06 23:33:57 +0800 | [diff] [blame^] | 153 | {/* Protected routes */} |
| 154 | <Route element={<RequireAuth />}> |
| 155 | <Route path="/movie" element={<MoviePage />} /> |
| 156 | <Route path="/tv" element={<TVPage />} /> |
| 157 | <Route path="/music" element={<MusicPage />} /> |
| 158 | <Route path="/anime" element={<AnimePage />} /> |
| 159 | <Route path="/game" element={<GamePage />} /> |
| 160 | <Route path="/sport" element={<SportPage />} /> |
| 161 | <Route path="/forum" element={<ForumPage />} /> |
| 162 | <Route path="/forum/:postId" element={<PostDetailPage />} /> |
| 163 | <Route path="/info" element={<InfoPage />} /> |
| 164 | <Route path="/user" element={<UserProfile />} /> |
| 165 | <Route path="/publish" element={<PublishPage />} /> |
| 166 | <Route path="/torrent/:torrentId" element={<TorrentDetailPage />} /> |
| 167 | </Route> |
956303669 | a32fc2c | 2025-06-02 19:45:53 +0800 | [diff] [blame] | 168 | </Routes> |
| 169 | </Router> |
| 170 | ); |
| 171 | } |