上传种子部分
Change-Id: I6657a3a9e57fbbab330e0844ff0b04b78fa3f2dd
diff --git a/src/api/homepage.ts b/src/api/homepage.ts
index 697d0d0..917eaa3 100644
--- a/src/api/homepage.ts
+++ b/src/api/homepage.ts
@@ -1 +1,5 @@
-export const getUserMessage="/user/message"
\ No newline at end of file
+export const getUserMessage="/post/getByUserId"
+export const getUserDetail="/user/detail"
+
+
+// export const getUserMessage = (userId: number) => `/user/message?userId=${userId}`;
\ No newline at end of file
diff --git a/src/components/corner/corner.module.css b/src/components/corner/corner.module.css
new file mode 100644
index 0000000..8b51c33
--- /dev/null
+++ b/src/components/corner/corner.module.css
@@ -0,0 +1,49 @@
+.container {
+ display: flex;
+ flex-direction: column; /* 纵向排列 */
+ align-items: stretch;
+ justify-content: flex-start;
+ padding: 20px;
+ border-radius: 10px;
+ background-color: var(--card-bg);
+ width: 100%;
+ height: 100%;
+ box-sizing: border-box;
+ overflow: hidden;
+}
+
+.uploadButton {
+ padding: 10px 20px;
+ font-size: 14px;
+ background-color: var(--primary-color);
+ color: var(--text-color);
+ border: none;
+ border-radius: 5px;
+ cursor: pointer;
+ margin-bottom: 20px;
+}
+
+.uploadButton:hover {
+ background-color: var(--primary-hover);
+}
+
+.filterItem {
+ display: flex;
+ flex-direction: column;
+ margin-bottom: 15px;
+ color: var(--text-color);
+}
+
+.filterItem label {
+ margin-bottom: 5px;
+ font-size: 14px;
+}
+
+.filterItem select,
+.filterItem input {
+ padding: 6px 10px;
+ border-radius: 4px;
+ border: 1px solid #ccc;
+ background-color: var(--light-color);
+ color: var(--text-color);
+}
diff --git a/src/components/corner/corner.tsx b/src/components/corner/corner.tsx
new file mode 100644
index 0000000..71dd772
--- /dev/null
+++ b/src/components/corner/corner.tsx
@@ -0,0 +1,48 @@
+// src/components/BottomRightUpload.tsx
+import React from 'react';
+import styles from './corner.module.css';
+import { useNavigate } from 'react-router';
+
+const BottomRightUpload: React.FC = () => {
+ const navigate = useNavigate();
+
+ const handleUploadClick = () => {
+ navigate('/postDetails', { state: { isNewPost: true } });
+ };
+
+ return (
+ <div className={styles.container}>
+ <button className={styles.uploadButton} onClick={handleUploadClick}>
+ 发布种子
+ </button>
+
+ <div className={styles.filterItem}>
+ <label htmlFor="category">分区:</label>
+ <select id="category">
+ <option value="all">全部</option>
+ <option value="video">视频</option>
+ <option value="music">音乐</option>
+ <option value="game">游戏</option>
+ <option value="software">软件</option>
+ </select>
+ </div>
+
+ <div className={styles.filterItem}>
+ <label htmlFor="rating">评分:</label>
+ <select id="rating">
+ <option value="all">全部</option>
+ <option value="high">高评分</option>
+ <option value="medium">中评分</option>
+ <option value="low">低评分</option>
+ </select>
+ </div>
+
+ <div className={styles.filterItem}>
+ <label htmlFor="tag">标签:</label>
+ <input type="text" id="tag" placeholder="输入标签关键词" />
+ </div>
+ </div>
+ );
+};
+
+export default BottomRightUpload;
diff --git a/src/components/selfStatus/selfStatus.tsx b/src/components/selfStatus/selfStatus.tsx
index c7ea79d..fb25c75 100644
--- a/src/components/selfStatus/selfStatus.tsx
+++ b/src/components/selfStatus/selfStatus.tsx
@@ -45,7 +45,11 @@
<div className={style.right}>
<div className={style.info}>
<p className={style.userName}>{userName}</p>
- <p className={style.role}>用户组: {role && role.trim().length? role:'N/A'}</p>
+ <p
+ className={style.role}
+ onClick={() => nav('/homepage')}
+ style={{ cursor: 'pointer', textDecoration: 'underline' }}>
+ 用户组: {role && role.trim().length? role:'N/A'}</p>
<p className={style.uploadTraffic}>上传量: {uploadTraffic ? uploadTraffic : 0}</p>
<p className={style.downloadTraffic}>下载量: {downloadTraffic ? downloadTraffic : 0}</p>
diff --git a/src/components/upload/upload.module.css b/src/components/upload/upload.module.css
deleted file mode 100644
index 2fb6278..0000000
--- a/src/components/upload/upload.module.css
+++ /dev/null
@@ -1,39 +0,0 @@
-.uploadContainer {
- display: flex;
- flex-direction: column;
- align-items: center;
- justify-content: center;
- border: 2px dashed #1890ff;
- padding: 40px;
- border-radius: 8px;
- background-color: #f0f5ff;
- transition: border-color 0.3s;
-}
-
-.uploadContainer:hover {
- border-color: #40a9ff;
-}
-
-.uploadLabel {
- font-size: 16px;
- margin-bottom: 10px;
- color: #333;
-}
-
-.uploadInput {
- display: none;
-}
-
-.uploadButton {
- padding: 8px 16px;
- background-color: #1890ff;
- color: white;
- border: none;
- border-radius: 4px;
- cursor: pointer;
- font-size: 14px;
-}
-
-.uploadButton:hover {
- background-color: #40a9ff;
-}
diff --git a/src/components/upload/upload.tsx b/src/components/upload/upload.tsx
deleted file mode 100644
index 708e9d1..0000000
--- a/src/components/upload/upload.tsx
+++ /dev/null
@@ -1,44 +0,0 @@
-// src/component/upload/upload.tsx
-import React, { useState } from 'react'
-import './upload.css'
-
-const UploadComponent: React.FC = () => {
- const [selectedFile, setSelectedFile] = useState<File | null>(null)
-
- const handleFileChange = (e: React.ChangeEvent<HTMLInputElement>) => {
- if (e.target.files && e.target.files.length > 0) {
- setSelectedFile(e.target.files[0])
- }
- }
-
- const handleUpload = () => {
- if (selectedFile) {
- console.log('上传文件:', selectedFile)
- // 此处可以添加实际上传逻辑
- }
- }
-
- return (
- <div className="uploadContainer">
- <label className="uploadLabel" htmlFor="upload-input">请选择文件上传:</label>
- <input
- type="file"
- id="upload-input"
- className="uploadInput"
- data-testid="upload-input"
- onChange={handleFileChange}
- />
- <label htmlFor="upload-input">
- <div
- className="uploadButton"
- data-testid="upload-button"
- onClick={handleUpload}
- >
- 点击上传
- </div>
- </label>
- </div>
- )
-}
-
-export default UploadComponent
diff --git a/src/views/forum/index.tsx b/src/views/forum/index.tsx
index 83d791f..13c369f 100644
--- a/src/views/forum/index.tsx
+++ b/src/views/forum/index.tsx
@@ -1,6 +1,7 @@
import React from "react";
import { Navigate } from "react-router";
import SelfStatus from "@/components/selfStatus/selfStatus";
+import Corner from "@/components/corner/corner";
import style from "./index.module.css";
import Navbar from "@/components/navbar/navbar";
diff --git a/src/views/homepage/homepage.tsx b/src/views/homepage/homepage.tsx
index 58c910f..ec74187 100644
--- a/src/views/homepage/homepage.tsx
+++ b/src/views/homepage/homepage.tsx
@@ -1,14 +1,17 @@
-import React, { useCallback, useEffect } from 'react';
+import React, { useCallback, useEffect,useState,useRef } from 'react';
import styles from './homepage.module.css';
import { useApi } from '@/hooks/request';
import { useSelector } from 'react-redux';
import { RootState } from '@/store';
import { useNavigate } from 'react-router';
import logo from '&/assets/logo.png';
-import { getUserMessage } from '@/api/homepage';
+import { getUserMessage } from '@/api/homepage'
+import { getUserDetail } from '@/api/homepage'
import request from '@/utils/request'
-import { hotPosts } from '@/api/post';
+// import { hotPosts } from '@/api/post';
import { postUserLogin } from '@/api/auth';
+import { debounce } from 'lodash';
+import { Q } from 'react-router/dist/development/fog-of-war-CGNKxM4z';
interface WorkItem {
postId: number,
@@ -17,54 +20,80 @@
postContent: string,
createdAt: number,
postType: string,
+ isLocked: boolean,
+ lockedReason: string,
+ lockedAt: string,
+ lockedBy: number,
viewCount: number,
hotScore: number,
lastCalculated: number
-
}
interface UserStats {
+ username: string;
+ uploadAmount: number;
+ level: string;
likes: number;
following: number;
followers: number;
mutualFollows: number;
}
-interface UserResponse {
- username: string;
- inviteCode: string;
- stats: UserStats;
- upload: string;
- level: string;
- works: WorkItem[];
- petImage: string;
- trafficImage: string;
-}
-
const Homepage: React.FC =() => {
+ const [userStats, setUserStats] = useState<UserStats | null>(null);
+
+ const [works, setWorks] = useState<WorkItem[]>([]);
+ const worksRef = useRef<WorkItem[]>([]);
+
+
const navigate = useNavigate();
const userInfo = useSelector((state: RootState) => state.user);
-
- // 获取用户作品数据
- // const {data: response, loading, error, refresh} =useApi(()=>request.get(getUserMessage), false);
- const { data: response, loading, error, refresh } = useApi<UserResponse>(() => request.get(getUserMessage), false);
+ const userId = userInfo.userId; // 从Redux获取当前用户ID
+
+ const { data:userdata, loading:userloading, error:usererror, refresh: getUserDetailRefresh } = useApi(
+ () => request.get(getUserDetail, {params: {userId}}).then(res => res.data.data),
+ );
+
+ const { data:workdata, loading:workloading, error:workerror, refresh: getUserMessageRefresh } = useApi(
+ () => request.get(getUserMessage, { params: { userId } }).then(res => res.data.data),
+ false
+ );
+
+ const getUserDetails = debounce(async () => {
+ try{
+ const res = await getUserDetailRefresh({userId});
+ console.log("res", res);
+ setUserStats(res);
+ }catch(error){
+ console.error('获取用户信息错误', error);
+ }
+ },1000) as () => void;
+
+
+ const getUserPost = debounce(async () => {
+ try{
+ const res = await getUserMessageRefresh({userId});
+ console.log("res", res);
+ worksRef.current = res;
+ setWorks(res);
+ }catch(error) {
+ console.error('获取帖子列表错误', error);
+ }
+ },1000) as () => void;
+
useEffect(() => {
- refresh(); // 页面首次加载时触发请求
- }, []);
- // 用户统计数据
- const userStats = {
- likes: response?.stats?.likes ?? 0,
- following: response?.stats?.following ?? 0,
- followers: response?.stats?.followers ?? 0,
- mutualFollows: response?.stats?.mutualFollows ?? 0,
- uploadAmount: response?.upload ?? '--',
- level: response?.level ?? '--'
- };
-
- const handleLogoClick = () => {
- navigate('/');
- };
+ if (!userId) {
+ navigate('/login');
+ }
+ else {
+ getUserDetails();
+ getUserPost();
+ }
+ }, [userId]);
+
+ if (!userId) return null;
+
return (
<div className={styles.container}>
@@ -84,32 +113,24 @@
<h2 className={styles.username}>阳菜,放睛!</h2>
<div className={styles.inviteCode}>邀请码:1314520</div>
<button className={styles.editButton}>编辑主页</button>
- <button
- className={styles.editButton}
- onClick={() => navigate('/postDetails', {
- state: { isNewPost: true }
- })}
- >
- 发布种子
- </button>
</div>
</div>
<div className={styles.userStats}>
<div className={styles.statItem}>
- <div className={styles.statNumber}>{userStats.likes}</div>
+ <div className={styles.statNumber}>{userStats?.likes ?? '--'}</div>
<div className={styles.statLabel}>获赞</div>
</div>
<div className={styles.statItem}>
- <div className={styles.statNumber}>{userStats.following}</div>
+ <div className={styles.statNumber}>{userStats?.following ?? '--'}</div>
<div className={styles.statLabel}>关注</div>
</div>
<div className={styles.statItem}>
- <div className={styles.statNumber}>{userStats.followers}</div>
+ <div className={styles.statNumber}>{userStats?.followers ?? '--'}</div>
<div className={styles.statLabel}>粉丝</div>
</div>
<div className={styles.statItem}>
- <div className={styles.statNumber}>{userStats.mutualFollows}</div>
+ <div className={styles.statNumber}>{userStats?.mutualFollows ?? '--'}</div>
<div className={styles.statLabel}>互关</div>
</div>
</div>
@@ -117,20 +138,20 @@
<div className={styles.userData}>
<div className={styles.dataItem}>
<span>您的总上传量为:</span>
- <strong>{userStats.uploadAmount}</strong>
+ <strong>{userStats?.uploadAmount ?? '--'}</strong>
</div>
<div className={styles.dataItem}>
<span>您的用户等级为:</span>
- <strong>{userStats.level}</strong>
+ <strong>{userStats?.level ?? '--'}</strong>
</div>
</div>
<div className={styles.worksSection}>
<h3 className={styles.sectionTitle}>我的作品</h3>
- {loading && <div className={styles.loading}>加载中...</div>}
- {error && <div className={styles.error}>{error.message}</div>}
+ {workloading && <div className={styles.loading}>加载中...</div>}
+ {workerror && <div className={styles.error}>{workerror.message}</div>}
- {response && response.works.map(work => (
+ {works.map(work => (
<div key={work.postId} className={styles.workItem}>
<h4 className={styles.workTitle}>{work.postTitle}</h4>
<div className={styles.workMeta}>
diff --git a/src/views/postList/postList.tsx b/src/views/postList/postList.tsx
index 69388d8..28a660d 100644
--- a/src/views/postList/postList.tsx
+++ b/src/views/postList/postList.tsx
@@ -1,6 +1,7 @@
import React from "react";
import style from "./postList.module.css";
import SelfStatus from "@/components/selfStatus/selfStatus";
+import Corner from "@/components/corner/corner"
import Navbar from "@/components/navbar/navbar";
import PostsPanel from "@/components/postsPanel/postsPanel";
import { getPosts, unknownAPI } from "@/api/post";
@@ -66,7 +67,7 @@
<SelfStatus/>
</div>
<div className={style.filter}>
-
+ <Corner />
</div>
</div>
</div>
diff --git a/src/views/search/search.tsx b/src/views/search/search.tsx
index cd9db91..6dba69c 100644
--- a/src/views/search/search.tsx
+++ b/src/views/search/search.tsx
@@ -16,12 +16,36 @@
tags?: number[];
}
-const tagMap: Record<number, string> = {
- 1: "搞笑",
- 2: "悬疑",
- 3: "教育",
- 4: "动作",
- 5: "剧情"
+const tagMap: Record<string, Record<number, string>> = {
+ Game: {
+ 0: "android",
+ 1: "mac",
+ 2: "pc",
+ 3: "ios",
+ 4: "other",
+ 5: "action",
+ 6: "adventure",
+ 7: "leisure",
+ 8: "riddle",
+ 9: "sport",
+ 10: "strategy",
+ 11: "table",
+ },
+ video: {
+ 20: "视频标签1",
+ 21: "视频标签2",
+ 22: "视频标签3",
+ },
+ music: {
+ 40: "音乐标签1",
+ 41: "音乐标签2",
+ 42: "音乐标签3",
+ },
+ software: {
+ 60: "软件标签1",
+ 61: "软件标签2",
+ 62: "软件标签3",
+ },
};
const SearchPage: React.FC = () => {
@@ -35,6 +59,10 @@
const params = new URLSearchParams(location.search);
const keyword = params.get("keyword");
+ const getTagsForPostType = (postType: string) => {
+ return tagMap[postType] || {};
+ };
+
useEffect(() => {
fetch('/api/posts')
.then((res) => res.json())
@@ -62,6 +90,7 @@
}
setFilteredPosts(filtered);
+
};
return (
@@ -73,10 +102,10 @@
className={styles.selectBox}
>
<option value="all">所有分区</option>
- <option value="影视">影视</option>
- <option value="音乐">音乐</option>
- <option value="游戏">游戏</option>
- <option value="软件">软件</option>
+ <option value="video">影视</option>
+ <option value="music">音乐</option>
+ <option value="Game">游戏</option>
+ <option value="software">软件</option>
</select>
<select
@@ -97,7 +126,7 @@
<div className={styles.centerSection}>
<div className={styles.tagFilters}>
- {Object.entries(tagMap).map(([tagId, tagName]) => (
+ {Object.entries(getTagsForPostType(selectedPostType)).map(([tagId, tagName]) => (
<label key={tagId}>
<input
type="checkbox"