整体链接
Change-Id: Id3379c6188613acdc95548964f19e317eda8dc4f
diff --git a/src/api/comment.ts b/src/api/comment.ts
index 1809ad2..6531eea 100644
--- a/src/api/comment.ts
+++ b/src/api/comment.ts
@@ -1 +1,2 @@
-export const getPostComments = '/api/comments/post'
\ No newline at end of file
+export const getPostComments = '/api/comments/post'
+export const postPostComments = '/api/comments'
\ No newline at end of file
diff --git a/src/components/corner/corner.tsx b/src/components/corner/corner.tsx
index ad80476..7f8d900 100644
--- a/src/components/corner/corner.tsx
+++ b/src/components/corner/corner.tsx
@@ -1,15 +1,30 @@
-// src/components/BottomRightUpload.tsx
-import React, { use } from 'react';
+
+import React, { useState, useCallback, useEffect } from 'react';
import styles from './corner.module.css';
import { useNavigate } from 'react-router';
import { useSearchParams } from 'react-router-dom';
-const BottomRightUpload: React.FC = () => {
+import { MainTag, MainPostTag } from '@/types/common';
+import { Button, Checkbox, Row, Col } from 'antd';
+import { getTagsByMainTag } from '@/utils/common';
+interface CornerProp {
+
+ setTagIds: (tagIds: number[]) => void;
+}
+
+const BottomRightUpload: React.FC<CornerProp> = (props:CornerProp) => {
const [searchParams] = useSearchParams();
+ const [tags, setTags] = useState<Map<string, number>>(new Map);
+ const [selectdTags, setSelectedTags] = useState<number[]>([])
+ const setTagIds = props.setTagIds;
const navigate = useNavigate();
const type = searchParams.get('type');
+
const handleUploadClick = () => {
navigate('/createPost', { state: { isNewPost: true, type} });
};
+ useEffect(()=>{
+ setTags(getTagsByMainTag(type as string))
+ },[])
return (
<div className={styles.container}>
@@ -18,17 +33,6 @@
</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>
@@ -40,8 +44,41 @@
<div className={styles.filterItem}>
<label htmlFor="tag">标签:</label>
- <input type="text" id="tag" placeholder="输入标签关键词" />
+ <Checkbox.Group
+ value={selectdTags}
+ onChange={(checkedValues) =>{
+ setSelectedTags([...checkedValues])
+ }}
+ >
+ <Row gutter={[12, 12]}>
+ {[...tags.entries()].map(([name, id]) => (
+ <Col key={id} xs={12} sm={12} md={8} lg={6}>
+ <Checkbox value={id}>{name}</Checkbox>
+ </Col>
+ ))}
+ </Row>
+ </Checkbox.Group>
</div>
+
+ <Button
+ color='primary'
+ variant='outlined'
+ onClick={()=>{
+ console.log(selectdTags)
+ setTagIds([...selectdTags])
+
+ }}
+ > 筛选 </Button>
+
+ <Button
+ color='danger'
+ variant='outlined'
+ onClick={()=>{
+ setTagIds([])
+ setSelectedTags([])
+ }}
+ >清空筛选
+ </Button>
</div>
);
};
diff --git a/src/components/navbar/navbar.tsx b/src/components/navbar/navbar.tsx
index e246ed6..3f26b6b 100644
--- a/src/components/navbar/navbar.tsx
+++ b/src/components/navbar/navbar.tsx
@@ -95,7 +95,7 @@
key: 'game',
icon: <GameIcon />,
label: (
- <a href={'/posts?type=game'}>
+ <a href={'/posts?type=Game'}>
游戏
</a>
),
diff --git a/src/components/postsPanel/postsPanel.module.css b/src/components/postsPanel/postsPanel.module.css
index b4b75ce..f639c77 100644
--- a/src/components/postsPanel/postsPanel.module.css
+++ b/src/components/postsPanel/postsPanel.module.css
@@ -4,7 +4,9 @@
width:100%;
padding:0px 5px;
}
-
+span {
+ color:var(--text-color)
+}
.header{
border-bottom:1px solid var(--border-color);
box-shadow: 1px;
diff --git a/src/components/postsPanel/postsPanel.tsx b/src/components/postsPanel/postsPanel.tsx
index 2916753..c99e40e 100644
--- a/src/components/postsPanel/postsPanel.tsx
+++ b/src/components/postsPanel/postsPanel.tsx
@@ -1,5 +1,5 @@
import { useApi } from '@/hooks/request';
-import React, { useCallback } from 'react';
+import React, { useCallback, useEffect, useState } from 'react';
import request from '@/utils/request'
import style from './postsPanel.module.css'
import { useNavigate } from 'react-router';
@@ -18,6 +18,14 @@
const handlePostCheck =(postId:string) =>{
nav('/postDetail?postId=' + postId);
}
+
+ useEffect(()=>{
+ if(data){
+ console.log("data!!!")
+ console.log(data)
+ }
+ }, [data])
+
return (
<div className={style.panel}>
<div className={style.header}>
@@ -25,11 +33,11 @@
<span className={style.more}>更多</span>
</div>
<div className={style.content} >
- {data && data.length > 0 ?
- data?.map((item: {postId:string, postTitle: string; createdAt: string }, index: number) => (
+ {data && data.records && data.records.length > 0 ?
+ data.records.map((item: {postId:string, postTitle: string; createdAt: string }, index: number) => (
<div key={index} className={style.item} onClick={()=> handlePostCheck(item.postId)} >
<span className={style.text}>{item.postTitle}</span>
- <span>{item.createdAt}</span>
+ <span>{new Date(item.createdAt).toLocaleString()}</span>
</div>
)) :(
<div>未查询到相关记录</div>
diff --git a/src/components/selfStatus/selfStatus.tsx b/src/components/selfStatus/selfStatus.tsx
index 24028ad..1fa812a 100644
--- a/src/components/selfStatus/selfStatus.tsx
+++ b/src/components/selfStatus/selfStatus.tsx
@@ -5,8 +5,9 @@
import request from "@/utils/request";
import { getUserInfo } from "@/api/user";
import { useAppDispatch } from "@/hooks/store";
-
+import type { MenuProps } from 'antd';
import { useNavigate } from "react-router";
+import { Dropdown } from "antd";
interface SelfStatusProps {
@@ -32,29 +33,37 @@
dispatch({ type: "user/getUserInfo", payload: data.userInfo });
}
}
+
+ const logOut = () =>{
+ dispatch({type:"user/logout"})
+ nav('/')
+ }
+
+ const menu: MenuProps['items'] =[
+ {
+ key:'1',
+ label:(<span onClick={logOut}>登出</span>)
+ }
+]
useEffect(() => {
fenchData();
}, [ dispatch]);
- function handleAvatarClick(){
- nav('/homepage')
- }
-
return (
<div className={style.container}>
- <div className={style.left}>
+ <div className={style.left}
+
+ >
{avatar && avatar.length > 0 ? (
- <img className={style.avatar} src={avatar} alt="User Avatar" />):null}
+ <img className={style.avatar} onClick={() => nav('/homepage')} style={{ cursor: 'pointer'}} src={avatar} alt="User Avatar" />):null}
</div>
<div className={style.right}>
<div className={style.info}>
- <p className={style.userName}>{userName}</p>
- <p
- className={style.role}
- onClick={() => nav('/homepage')}
- style={{ cursor: 'pointer', textDecoration: 'underline' }}>
- 用户组: {role && role.trim().length? role:'N/A'}</p>
+ <Dropdown menu={{ items: menu }}>
+ <p className={style.userName}>{userName}</p>
+ </Dropdown>
+ <p className={style.role}>用户组: {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/selfStatus/style.module.css b/src/components/selfStatus/style.module.css
index 858e88a..da68ee3 100644
--- a/src/components/selfStatus/style.module.css
+++ b/src/components/selfStatus/style.module.css
@@ -13,7 +13,6 @@
}
.left {
- border:1px solid #ccc;
display: flex;
flex-direction: column;
align-items: center;
@@ -29,7 +28,6 @@
margin-bottom: 10px;
}
.right {
- border:1px solid #aaa;
display: flex;
flex-direction: column;
justify-content: flex-start;
diff --git a/src/index.tsx b/src/index.tsx
index 494de3e..3e51093 100644
--- a/src/index.tsx
+++ b/src/index.tsx
@@ -5,8 +5,6 @@
import store from "./store/index";
import { RouterProvider } from "react-router";
import './global.css';
-import { useEffect } from "react";
-import { checkAndRefreshToken } from "./utils/jwt";
if(localStorage.getItem("theme") === null) {
localStorage.setItem("theme", "light");
diff --git a/src/route/privateRoute.tsx b/src/route/privateRoute.tsx
index 992f372..2a1441a 100644
--- a/src/route/privateRoute.tsx
+++ b/src/route/privateRoute.tsx
@@ -1,6 +1,10 @@
import { Navigate, Outlet } from 'react-router-dom'
-import React from 'react'
+import React, { useEffect, useState } from 'react'
import { useSelector } from 'react-redux'
+import { useApi } from '@/hooks/request'
+import request from '@/utils/request'
+import { getUserInfo } from '@/api/user'
+import { useAppDispatch } from '@/hooks/store'
interface PrivateRouteProps {
role: number
@@ -15,6 +19,30 @@
}: PrivateRouteProps) => {
const isLogin = useSelector((state: any) => state.user.isLogin)
const userRole = useSelector((state: any) => state.user.role)
+ const userId = useSelector((state: any) => state.user.userId)
+ const dispatch = useAppDispatch()
+ const [hasFetchedUser, setHasFetchedUser] = useState(false) // 防止重复请求
+ const { refresh: getUserInfoRefresh } = useApi(
+ () => request.get(getUserInfo),
+ false
+ )
+
+ useEffect(() => {
+ if (isLogin && !userId && !hasFetchedUser) {
+ const fetchUserInfo = async () => {
+ try {
+ const userInfo = await getUserInfoRefresh()
+ if (userInfo && !(userInfo as any).error) {
+ dispatch({ type: 'user/getUserInfo', payload: userInfo.userInfo })
+ setHasFetchedUser(true) // 标记已请求
+ }
+ } catch (error) {
+ console.error('获取用户信息失败:', error)
+ }
+ }
+ fetchUserInfo()
+ }
+ }, [isLogin, userId, hasFetchedUser, dispatch, getUserInfoRefresh])
if (!isLogin) {
return <Navigate to={redirectPath} replace />
@@ -24,12 +52,7 @@
return <Navigate to={redirectPath} replace />
}
- return children ? (
- <>{children}</>
- ) : (
- <Outlet />
- )
-
+ return children ? <>{children}</> : <Outlet />
}
export default PrivateRoute
\ No newline at end of file
diff --git a/src/utils/axios.ts b/src/utils/axios.ts
index bb44c82..c13c516 100644
--- a/src/utils/axios.ts
+++ b/src/utils/axios.ts
@@ -28,11 +28,15 @@
// 响应拦截器
instance.interceptors.response.use(
(response) => {
- // 统一处理响应数据格式
- if (response.status === 200) {
- return response.data.data
+ if(response.headers['content-type']!=='application/x-bittorrent')
+ {
+ if (response.status === 200) {
+ return response.data.data
+ }
+ return Promise.reject(response.data)
+ }else {
+ return response
}
- return Promise.reject(response.data)
},
(error) => {
if(error.status===401){
diff --git a/src/views/login/login.module.css b/src/views/login/login.module.css
index a7fc6f4..8866d78 100644
--- a/src/views/login/login.module.css
+++ b/src/views/login/login.module.css
@@ -3,7 +3,7 @@
flex-direction: column;
align-items: center; /* Center items horizontally */
justify-content: center; /* Center items vertically */
- height: 40%; /* Occupy 40% of the viewport height */
+ height: 50%; /* Occupy 40% of the viewport height */
width:25%;
background-color: #f0f8ff; /* Light blue background */
box-shadow: 3px 3px 5px 6px #ccc;
diff --git a/src/views/login/login.tsx b/src/views/login/login.tsx
index 70b5573..1bc18c2 100644
--- a/src/views/login/login.tsx
+++ b/src/views/login/login.tsx
@@ -21,6 +21,7 @@
const [codeBtnDisabled, setCodeBtnDisabled] = useState(false);
const [codeBtnText, setCodeBtnText] = useState('发送验证码');
const [codeTimer, setCodeTimer] = useState<NodeJS.Timeout | null>(null);
+ const [userName, setUserName] = useState('');
const dispatch = useAppDispatch();
const [messageApi, contextHolder] = message.useMessage();
@@ -141,6 +142,13 @@
) : (
<>
<input
+ type='text'
+ value={userName}
+ onChange={(e)=>setUserName(e.target.value)}
+ className={style.invite}
+ placeholder="用户名"
+ />
+ <input
type="text"
value={inviteCode}
onChange={(e) => setInviteCode(e.target.value)}
diff --git a/src/views/postDetail/postDetail.tsx b/src/views/postDetail/postDetail.tsx
index 202907b..591d9f1 100644
--- a/src/views/postDetail/postDetail.tsx
+++ b/src/views/postDetail/postDetail.tsx
@@ -1,13 +1,16 @@
-import React, { useEffect, useState } from 'react';
+import React, { useCallback, useEffect, useState } from 'react';
import styles from './PostDetail.module.css';
-import { Card, List, Typography, Button, Input, Spin, Empty, Divider } from 'antd';
+import { Card, List, Typography, Button, Input, Spin, Empty, Divider, message } from 'antd';
import { getPostDetail } from '@/api/post';
-import { getPostComments } from '@/api/comment';
+import { getPostComments, postPostComments } from '@/api/comment';
import { useSearchParams } from 'react-router-dom';
import request from '@/utils/request';
import { useApi } from '@/hooks/request';
import Navbar from '@/components/navbar/navbar';
-import { DownloadOutlined, LikeOutlined, LikeFilled } from '@ant-design/icons';
+import { DownloadOutlined, LikeOutlined, LikeFilled, PayCircleOutlined } from '@ant-design/icons';
+import instance from '@/utils/axios';
+import { useAppSelector } from '@/hooks/store';
+
const { Title, Text, Paragraph } = Typography;
const { TextArea } = Input;
@@ -41,6 +44,7 @@
}
const PostDetail: React.FC = () => {
+ const [messageApi, placeholder] = message.useMessage();
const [searchParams] = useSearchParams();
const postId = searchParams.get('postId');
const { refresh: getPostDetailRefresh } = useApi(() => request.get(getPostDetail + `/${postId}`), false);
@@ -50,6 +54,36 @@
const [newComment, setNewComment] = useState<string>('');
const [loading, setLoading] = useState<boolean>(true);
const [liked, setLiked] = useState(false);
+ const userId = useAppSelector((state)=> state.user.userId)
+
+ const {refresh:postComment} = useApi((payload)=>request.post(postPostComments, payload), false)
+
+ const handleDownload = async (torrentId: string, torrentName:string) => {
+ console.log(torrentId)
+ try {
+ const token = localStorage.getItem('token'); // 或从状态管理中获取
+ const response = await instance.get(`/torrent/download/${torrentId}`, {
+ responseType: 'blob',
+ headers: {
+ Authorization: `Bearer ${token}`,
+ },
+ });
+ console.log(response)
+ const blob = new Blob([response.data], { type: response.headers['content-type'] });
+ const downloadUrl = URL.createObjectURL(blob);
+
+ const a = document.createElement('a');
+ a.href = downloadUrl;
+ a.download = `资源_${torrentName}.torrent`;
+ document.body.appendChild(a);
+ a.click();
+ document.body.removeChild(a);
+ URL.revokeObjectURL(downloadUrl);
+ } catch (error) {
+ console.error('下载失败', error);
+ alert('下载失败,请检查网络或登录状态');
+ }
+ };
useEffect(() => {
if (!postId) return;
@@ -65,37 +99,41 @@
const commentsRes = await getPostCommentsRefresh();
setComments(commentsRes as CommentResponse[]);
setLoading(false);
- console.log("postRes:", postRes);
- console.log("commentsRes:", commentsRes);
};
fetchData();
}, [postId]);
+ const refreshComment = useCallback(async ()=>{
+ if(!postId) return;
+ const commentsRes = await getPostCommentsRefresh();
+ setComments(commentsRes as CommentResponse[]);
+ },[postId, setComments])
+
if (loading) return <div className={styles.center}><Spin /></div>;
if (!post) return <div className={styles.center}><Empty description="未找到帖子" /></div>;
return (
<div className={styles.container}>
- {/* 固定导航栏 */}
+ {placeholder}
<div className={styles.nav}>
<Navbar current={post.postType} />
</div>
- {/* 内容区域 */}
+
<div className={styles.contentArea}>
+ {/**帖子信息 */}
<Card
title={<Title level={3} style={{ margin: 0 }}>{post.postTitle || "帖子标题"}</Title>}
className={styles.card}
- bordered={false}
style={{ marginBottom: 24, boxShadow: '0 4px 24px rgba(0,0,0,0.08)' }}
extra={
<div style={{ display: 'flex', gap: 16 }}>
<Button
type="primary"
icon={<DownloadOutlined />}
- onClick={() => {
- // 下载逻辑
- window.open(`/api/download/post/${post.postId}`, '_blank');
- }}
+ onClick={() =>
+ post.torrentId && post.postTitle
+ ? handleDownload(post.torrentId, post.postTitle)
+ : undefined}
>
下载
</Button>
@@ -115,9 +153,6 @@
<Text type="secondary">作者ID: {post.userId}</Text>
<Text type="secondary">发布时间: {post.createdAt ? new Date(post.createdAt).toLocaleString() : "未知"}</Text>
<Text type="secondary">浏览量: {post.viewCount}</Text>
- <Text type="secondary">类型: {post.postType}</Text>
- <Text type="secondary">热度: {post.hotScore}</Text>
- <Text type="secondary">最后计算: {post.lastCalculated ? new Date(post.lastCalculated).toLocaleString() : "无"}</Text>
</div>
{post.isLocked && (
<div className={styles.locked}>
@@ -144,7 +179,22 @@
<Button
type="primary"
style={{ marginTop: 12, float: 'right' }}
- onClick={() => setNewComment('')}
+ onClick={async() => {
+ try{
+ await postComment({
+ postId,
+ userId,
+ content:newComment,
+ parentCommentId:''
+ })
+ setNewComment('')
+ refreshComment();
+ messageApi.success('发布成功');
+ }catch(err){
+ messageApi.error((err as Error).message);
+ }
+
+ }}
disabled={!newComment.trim()}
>
评论
@@ -152,12 +202,14 @@
<div style={{ clear: 'both' }} />
</Card>
+ {/* 评论区 */}
<Card
className={styles.commentListCard}
title={<Title level={4} style={{ margin: 0 }}>评论区</Title>}
- bodyStyle={{ padding: 0 }}
>
- <List
+ {
+ comments && comments.length &&
+ <List
className={styles.commentList}
dataSource={comments}
locale={{ emptyText: <Empty description="暂无评论" /> }}
@@ -199,6 +251,8 @@
</List.Item>
)}
/>
+ }
+
</Card>
</div>
</div>
diff --git a/src/views/postList/postList.tsx b/src/views/postList/postList.tsx
index 28a660d..2312361 100644
--- a/src/views/postList/postList.tsx
+++ b/src/views/postList/postList.tsx
@@ -1,15 +1,11 @@
-import React from "react";
+import React ,{useCallback, useState}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";
-import { Form } from "antd"
import { useApi } from "@/hooks/request";
import request from "@/utils/request";
-import { Pagination, PaginationProps } from "antd";
-import { set } from "lodash";
import { useEffect } from "react";
import { useNavigate, useSearchParams } from "react-router";
import { MainPostTag } from "@/types/common";
@@ -20,27 +16,26 @@
const type = searchParams.get("type") || "";
const nav = useNavigate();
- if(type in ['video', 'music', 'game', 'software']) {
+ if(type in ['video', 'music', 'Game', 'software']) {
nav('/')
}
-
- const {data:postList, refresh:getPostList} = useApi(() => request.get(getPosts + `?tags=${[MainPostTag[type as keyof typeof MainPostTag]]}&page=${currentPage}&pageSize=${pageSize}`), false);
- const [currentPage, setCurrentPage] = React.useState(1);
- const [pageSize, setPageSize] = React.useState(10);
- const handlePageChange = (page:number, size?:number) => {
- setCurrentPage(page);
- if(size) setPageSize(size);
- console.log(page, size);
- };
+ const {data:postList, refresh:getPostList} = useApi((tags) => request.get(getPosts + `?keyword&tags=${tags.join(',')}&author`), false);
+ const [currentPage, setCurrentPage] = useState(1);
+ const [pageSize, setPageSize] = useState(10);
+ const [tagIds, setTagIds] = useState<Array<number>>([]);
const handlePostClick = (postId:number) => {
nav(`/postsDetail?postId=${postId}`);
}
useEffect(() => {
- getPostList();
+ getPostList([MainPostTag[type as keyof typeof MainPostTag]]);
},[currentPage, pageSize]);
+ useEffect(()=>{
+ console.log(tagIds)
+ getPostList([...tagIds, MainPostTag[type as keyof typeof MainPostTag]])
+ },[tagIds])
return (
<div className={style.container}>
<div className={style.left}>
@@ -53,7 +48,7 @@
<div key={post.postId} className={style.contentItem} onClick={() => handlePostClick(post.postId)}>
<h3>{post.postTitle}</h3>
<p>{post.postContent.substring(0, 20)}</p>
- <p className={style.createDate}>{post.createdAt}</p>
+ <p className={style.createDate}>{new Date(post.createdAt).toLocaleString()}</p>
</div>
))
) : (
@@ -67,7 +62,7 @@
<SelfStatus/>
</div>
<div className={style.filter}>
- <Corner />
+ <Corner setTagIds={setTagIds}/>
</div>
</div>
</div>
diff --git a/src/views/upload/upload.tsx b/src/views/upload/upload.tsx
index 19e1197..7ec8850 100644
--- a/src/views/upload/upload.tsx
+++ b/src/views/upload/upload.tsx
@@ -5,11 +5,13 @@
import { useLocation, useNavigate } from 'react-router-dom'; // 用于跳转
import { getTagsByMainTag } from '@/utils/common';
import { Checkbox, Row, Col } from 'antd'; // 使用 antd 的 Checkbox 组件
-import { MainTag } from '@/types/common';
+import { MainTag, MainPostTag } from '@/types/common';
import { Select } from 'antd';
import { UploadOutlined } from '@ant-design/icons';
import type { UploadProps } from 'antd';
import { Button, message, Upload as UploadArea } from 'antd';
+import request from '@/utils/request';
+import {useApi} from '@/hooks/request';
const CreatePost = () => {
@@ -22,27 +24,41 @@
const [postType, setPostType] = useState<string>(type || ''); // 初始化 postType
const navigate = useNavigate();
const [tags, setTags] = useState<Map<string, number>>(new Map());
+ const [torrentId, setTorrentId] = useState<number>(0); // 用于存储上传的种子 ID
+ const [messageApi, contextHolder] = message.useMessage();
+
+ const {refresh} = useApi((payload)=> request.post('/post', payload), false)
const props: UploadProps = {
name: 'file',
- action: process.env.REACT_APP_BASE_URL + postTorrentUpload, // 替换为实际的上传接口地址
+ action: process.env.API_BASE_URL + postTorrentUpload, // 替换为实际的上传接口地址
headers: {
- authorization: 'authorization-text',
+ authorization: `Bearer ${localStorage.getItem('token')}`, // 使用本地存储的 token
},
onChange(info) {
- if (info.file.status !== 'uploading') {
- console.log(info.file, info.fileList);
- }
+
if (info.file.status === 'done') {
- message.success(`${info.file.name} file uploaded successfully`);
+ const response = info.file.response;
+ if(response && response.code !== 200) {
+ messageApi.error(response.message || '上传失败');
+ return;
+ }
+ else {
+ console.log('上传成功:', response);
+ messageApi.success('上传成功')
+ console.log(response.data.torrentId);
+ setTorrentId(response.data.torrentId); // 假设返回的数据中有 torrentId
+ }
} else if (info.file.status === 'error') {
- message.error(`${info.file.name} file upload failed.`);
+ messageApi.error(`${info.file.name} 文件上传失败`);
}
},
+
};
const handleSubmit = async () => {
+ console.log(torrentId)
if (!postTitle.trim() || !postType || !postContent.trim()) {
alert('请填写完整内容(资源名、类型、内容介绍)');
return;
@@ -55,33 +71,23 @@
const payload = {
post: {
- postId: 0,
- userId: 0,
postTitle,
postContent,
- createdAt: Date.now(),
- postType,
- viewCount: 0,
- hotScore: 5,
- lastCalculated: Date.now()
+ torrentId,
+ postType:'resource'
},
- tagIds: [0]
+ tagIds: new Array(...tagIds, MainPostTag[postType as keyof typeof MainPostTag]), // 确保 tagIds 是一个数组
};
-
- try {
- const res = await instance.post(Upload, payload);
-
- console.log('后端返回内容:', res.code);
-
- // 判断返回内容是否成功(根据你 mock 接口返回的 code 字段)
- if (res.code !== 0) throw new Error('发布失败');
-
- alert('发布成功!');
- navigate(-1); // 返回上一页(homepage)
- } catch (error) {
- alert('发布失败,请稍后重试');
- console.error(error);
+ try{
+ const res = await refresh(payload)
+ messageApi.success('发布成功', 3).then(()=>{
+ navigate('/')
+ });
+ ; // 发布成功后跳转到首页
+ } catch (err){
+ messageApi.error((err as Error).message || '发布失败,请稍后再试');
}
+
};
useEffect(() => {
@@ -97,6 +103,7 @@
return (
<div className={styles.container}>
+ {contextHolder}
<div className={styles.formGroup}>
<label>资源名:</label>
<input