重新提交
Change-Id: I41d894c30f6945402022f7309d52d9dfc0ff4c79
diff --git a/nginx.conf b/nginx.conf
index d96b07b..76a4aae 100644
--- a/nginx.conf
+++ b/nginx.conf
@@ -1,17 +1,15 @@
server {
listen 80; # 代理默认端口,可改
- server_name localhost;
+ server_name team2.10813352.xyz;
root /var/www/html;
index index.html;
- location / {
- try_files $uri $uri/ /index.html;
- }
+
# 代理 /api/v1/ 到后端服务
location /api/v1/ {
- proxy_pass http://team2.10813352.xyz:8088; # 你的后端暴露位置
+ proxy_pass http://localhost:8088; # 你的后端暴露位置
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
@@ -19,8 +17,8 @@
proxy_cache_bypass $http_upgrade;
}
- location = /favicon.ico { log_not_found off; access_log off; }
- location = /robots.txt { log_not_found off; access_log off; allow all; }
+ location = /favicon.ico { log_not_found off}; access_log off; }
+ location = /robots.txt { log_not_found off}; access_log off; allow all; }
location ~* \.(css|gif|ico|jpeg|jpg|js|png)$ {
expires max;
log_not_found off;
diff --git a/src/api/administer.js b/src/api/administer.js
index 5f28e45..d90bffa 100644
--- a/src/api/administer.js
+++ b/src/api/administer.js
@@ -1,10 +1,10 @@
import axios from 'axios';
-const API_BASE_URL = 'http://localhost:8088'; // 替换为你的后端API基础URL
+// const API_BASE_URL = 'http://team2.10813352.xyz:8088'; // 替换为你的后端API基础URL
export const getAllUsers = async () => {
try {
- const response = await axios.get(`${API_BASE_URL}/user/allUser`, {
+ const response = await axios.get(`/user/allUser`, {
headers: {
Authorization: localStorage.getItem('token')
}
@@ -27,7 +27,7 @@
export const searchUsers = async (key) => {
try {
- const response = await axios.get(`${API_BASE_URL}/user/searchUser`, {
+ const response = await axios.get(`/user/searchUser`, {
params: { key },
headers: {
Authorization: localStorage.getItem('token')
@@ -50,7 +50,7 @@
// 修改用户权限
export const updateUserAuthority = async (username, authority) => {
try {
- const response = await axios.put(`${API_BASE_URL}/user/changeAuthority`,
+ const response = await axios.put(`/user/changeAuthority`,
{
changeUsername: username,
authority: authority
@@ -113,7 +113,7 @@
// 修改 getAllDiscounts 和 getCurrentDiscount 方法
export const getAllDiscounts = async () => {
try {
- const response = await axios.get(`${API_BASE_URL}/discount/all`, {
+ const response = await axios.get(`/discount/all`, {
headers: {
Authorization: localStorage.getItem('token')
}
@@ -133,7 +133,7 @@
export const getCurrentDiscount = async () => {
try {
- const response = await axios.get(`${API_BASE_URL}/discount/current`, {
+ const response = await axios.get(`/discount/current`, {
headers: {
Authorization: localStorage.getItem('token')
}
@@ -156,7 +156,7 @@
// 添加折扣
export const addDiscount = async (discountData) => {
try {
- const response = await axios.post(`${API_BASE_URL}/discount/add`, discountData, {
+ const response = await axios.post(`/discount/add`, discountData, {
headers: {
Authorization: localStorage.getItem('token')
}
@@ -176,7 +176,7 @@
// 删除折扣
export const deleteDiscount = async (id) => {
try {
- const response = await axios.delete(`${API_BASE_URL}/discount/delete/${id}`, {
+ const response = await axios.delete(`/discount/delete/${id}`, {
headers: {
Authorization: localStorage.getItem('token')
}
diff --git a/src/api/administer.test.js b/src/api/administer.test.js
index beb1e11..e5e785e 100644
--- a/src/api/administer.test.js
+++ b/src/api/administer.test.js
@@ -37,7 +37,7 @@
}
];
- mock.onGet('http://localhost:8088/user/allUser').reply(200, {
+ mock.onGet('/user/allUser').reply(200, {
code: 200,
data: { data: mockUsers }
});
@@ -47,7 +47,7 @@
});
it('should return empty array when no users', async () => {
- mock.onGet('http://localhost:8088/user/allUser').reply(200, {
+ mock.onGet('/user/allUser').reply(200, {
code: 200,
data: { data: [] }
});
@@ -57,7 +57,7 @@
});
it('should handle error when fetching users', async () => {
- mock.onGet('http://localhost:8088/user/allUser').reply(500, {
+ mock.onGet('/user/allUser').reply(500, {
message: 'Request failed with status code 500'
});
@@ -74,7 +74,7 @@
}
];
- mock.onGet('http://localhost:8088/user/searchUser', { params: { key: 'user' } })
+ mock.onGet('/user/searchUser', { params: { key: 'user' } })
.reply(200, {
code: 200,
data: { data: mockUsers }
@@ -92,7 +92,7 @@
}
];
- mock.onGet('http://localhost:8088/user/searchUser', { params: { key: '' } })
+ mock.onGet('/user/searchUser', { params: { key: '' } })
.reply(200, {
code: 200,
data: { data: mockUsers }
@@ -108,7 +108,7 @@
const username = 'user1';
const authority = 'ADMIN';
- mock.onPut('http://localhost:8088/user/changeAuthority', {
+ mock.onPut('/user/changeAuthority', {
changeUsername: username,
authority: authority
}).reply(200, {
@@ -133,7 +133,7 @@
}
];
- mock.onGet('http://localhost:8088/discount/all').reply(200, {
+ mock.onGet('/discount/all').reply(200, {
code: 200,
data: { data: mockDiscounts }
});
@@ -153,7 +153,7 @@
endTime: '2023-05-07T23:59:59'
};
- mock.onGet('http://localhost:8088/discount/current').reply(200, {
+ mock.onGet('/discount/current').reply(200, {
code: 200,
data: { data: mockDiscount }
});
@@ -163,7 +163,7 @@
});
it('should return null when no current discount', async () => {
- mock.onGet('http://localhost:8088/discount/current').reply(200, {
+ mock.onGet('/discount/current').reply(200, {
code: 200,
message: '目前没有进行中的折扣',
data: null
@@ -174,7 +174,7 @@
});
it('should handle error when fetching current discount', async () => {
- mock.onGet('http://localhost:8088/discount/current').reply(500);
+ mock.onGet('/discount/current').reply(500);
await expect(getCurrentDiscount()).rejects.toThrow();
});
@@ -189,7 +189,7 @@
endTime: '2023-06-07T23:59:59'
};
- mock.onPost('http://localhost:8088/discount/add', newDiscount).reply(200, {
+ mock.onPost('/discount/add', newDiscount).reply(200, {
code: 200,
data: { data: { id: 2, ...newDiscount } }
});
@@ -203,7 +203,7 @@
it('should delete discount successfully', async () => {
const discountId = 1;
- mock.onDelete(`http://localhost:8088/discount/delete/${discountId}`).reply(200, {
+ mock.onDelete(`/discount/delete/${discountId}`).reply(200, {
code: 200,
message: '删除成功'
});
diff --git a/src/api/auth.js b/src/api/auth.js
index c094a44..a779af2 100644
--- a/src/api/auth.js
+++ b/src/api/auth.js
@@ -3,7 +3,7 @@
// 创建并导出 axios 实例
export const api = axios.create({
- baseURL: 'http://localhost:8088',
+ baseURL: 'http://team2.10813352.xyz:8088',
timeout: 5000,
});
diff --git a/src/api/recommend.js b/src/api/recommend.js
new file mode 100644
index 0000000..13c9f94
--- /dev/null
+++ b/src/api/recommend.js
@@ -0,0 +1,30 @@
+// src/api/recommend.js
+import { api } from './auth';
+
+export const getRecommendations = async (limit = 5) => {
+ try {
+ const response = await api.get('/recommend/for-user', {
+ params: { limit }
+ });
+ return response.data;
+ } catch (error) {
+ console.error('获取推荐失败:', error);
+ throw error;
+ }
+};
+
+export const markRecommendationShown = async (torrentId) => {
+ try {
+ await api.post(`/recommend/mark-shown/${torrentId}`);
+ } catch (error) {
+ console.error('标记推荐为已显示失败:', error);
+ }
+};
+
+export const markRecommendationClicked = async (torrentId) => {
+ try {
+ await api.post(`/recommend/mark-clicked/${torrentId}`);
+ } catch (error) {
+ console.error('标记推荐为已点击失败:', error);
+ }
+};
\ No newline at end of file
diff --git a/src/components/Administer.test.jsx b/src/components/Administer.test.jsx
index 7f446ed..598ed4e 100644
--- a/src/components/Administer.test.jsx
+++ b/src/components/Administer.test.jsx
@@ -23,7 +23,7 @@
});
test('renders user management tab by default', async () => {
- mock.onGet('http://localhost:8088/user/allUser').reply(200, {
+ mock.onGet('/user/allUser').reply(200, {
code: 200,
data: { data: [] }
});
@@ -53,7 +53,7 @@
}
];
- mock.onGet('http://localhost:8088/user/allUser').reply(200, {
+ mock.onGet('/user/allUser').reply(200, {
code: 200,
data: { data: mockUsers }
});
@@ -77,7 +77,7 @@
}
];
- mock.onGet('http://localhost:8088/user/searchUser').reply(200, {
+ mock.onGet('/user/searchUser').reply(200, {
code: 200,
data: { data: mockUsers }
});
@@ -99,12 +99,12 @@
});
test('switches between tabs', async () => {
- mock.onGet('http://localhost:8088/user/allUser').reply(200, {
+ mock.onGet('/user/allUser').reply(200, {
code: 200,
data: { data: [] }
});
- mock.onGet('http://localhost:8088/discount/all').reply(200, {
+ mock.onGet('/discount/all').reply(200, {
code: 200,
data: { data: [] }
});
diff --git a/src/components/Dashboard.jsx b/src/components/Dashboard.jsx
index 40bd19d..61111f3 100644
--- a/src/components/Dashboard.jsx
+++ b/src/components/Dashboard.jsx
@@ -7,8 +7,10 @@
import { message } from 'antd'; // 用于显示提示消息
import { getAnnouncements,getLatestAnnouncements,getAnnouncementDetail } from '../api/announcement';
import { getAllDiscounts } from '../api/administer';
- import { getUserInfo, isAdmin } from '../api/auth';
+import { getUserInfo, isAdmin } from '../api/auth';
import { api } from '../api/auth';
+import { getRecommendations, markRecommendationShown, markRecommendationClicked } from '../api/recommend';
+
const Dashboard = ({onLogout}) => {
@@ -67,6 +69,10 @@
const [shareSearch, setShareSearch] = useState('');
const [requestSearch, setRequestSearch] = useState('');
const [helpSearch, setHelpSearch] = useState('');
+ const [recommendations, setRecommendations] = useState([]);
+ const [recommendLoading, setRecommendLoading] = useState(false);
+ const [recommendError, setRecommendError] = useState(null);
+
const activeTab = tab || 'announcement'; // 如果没有tab参数,则默认为announcement
@@ -99,6 +105,7 @@
if (activeTab === 'announcement') {
fetchAnnouncements();
fetchDiscountsForCarousel();
+ fetchRecommendations();
}
}, [activeTab]);
@@ -143,6 +150,23 @@
}
};
+ const handleRecommendClick = async (torrent) => {
+ try {
+ // 标记为已点击
+ await markRecommendationClicked(torrent.id);
+
+ // 导航到种子详情页
+ navigate(`/torrent/${torrent.id}`, {
+ state: {
+ fromTab: 'announcement',
+ scrollPosition: window.scrollY
+ }
+ });
+ } catch (error) {
+ console.error('标记推荐点击失败:', error);
+ }
+ };
+
// 公告区搜索处理
const handleSearchAnnouncement = (e) => {
@@ -515,7 +539,7 @@
const response = (shareSearch && !isReset)
? await searchTorrents(shareSearch, page)
- : await api.get('http://localhost:8088/torrent', { params });
+ : await api.get('/torrent', { params });
if (response.data.code === 200) {
setTorrentPosts(response.data.data.records);
@@ -614,7 +638,26 @@
} finally {
setHelpLoading(false);
}
- };
+ };
+
+ const fetchRecommendations = async () => {
+ try {
+ setRecommendLoading(true);
+ const response = await getRecommendations(5);
+ if (response.code === 200) {
+ setRecommendations(response.data || []);
+
+ // 标记这些推荐为已显示
+ response.data.forEach(torrent => {
+ markRecommendationShown(torrent.id);
+ });
+ }
+ } catch (error) {
+ setRecommendError(error.message || '获取推荐失败');
+ } finally {
+ setRecommendLoading(false);
+ }
+ };
useEffect(() => {
@@ -719,7 +762,7 @@
}
// 调用API获取筛选结果
- const response = await api.get('http://localhost:8088/torrent', { params });
+ const response = await api.get('/torrent', { params });
if (response.data.code === 200) {
setTorrentPosts(response.data.data.records);
@@ -857,6 +900,45 @@
</div>
))}
</div>
+ {/* 新增的为你推荐区域 */}
+ <div className="recommend-section">
+ <h2 className="section-title">为你推荐</h2>
+
+ {recommendLoading && <div className="loading">加载推荐中...</div>}
+ {recommendError && <div className="error">{recommendError}</div>}
+
+ <div className="recommend-grid">
+ {recommendations.map(torrent => (
+ <div
+ key={torrent.id}
+ className="recommend-card"
+ onClick={() => handleRecommendClick(torrent)}
+ >
+ <div className="card-poster">
+ <div className="poster-image gray-bg">
+ {torrent.torrentName.charAt(0)}
+ </div>
+ </div>
+ <div className="card-info">
+ <h3 className="card-title">{torrent.torrentName}</h3>
+ <p className="card-meta">
+ {torrent.resolution} | {torrent.region} | {torrent.category}
+ </p>
+ <p className="card-subtitle">字幕: {torrent.subtitle}</p>
+ </div>
+ <div className="card-stats">
+ <span className="stat">👍 {torrent.likeCount || 0}</span>
+ </div>
+ </div>
+ ))}
+
+ {!recommendLoading && recommendations.length === 0 && (
+ <div className="no-recommendations">
+ 暂无推荐,请先下载一些资源以获取个性化推荐
+ </div>
+ )}
+ </div>
+ </div>
</div>
);
case 'share':
diff --git a/src/config/config.js b/src/config/config.js
index 365cc9e..1da40df 100644
--- a/src/config/config.js
+++ b/src/config/config.js
@@ -2,6 +2,6 @@
//serverIP后端服务器地址
- serverIP:'http://team2.10813352.xyz:8088'
+ serverIP:'http://team2.10813352.xyz:8088',
}
\ No newline at end of file
diff --git "a/\345\255\230\345\234\250\347\232\204\351\227\256\351\242\230.txt" "b/\345\255\230\345\234\250\347\232\204\351\227\256\351\242\230.txt"
index 335c27b..4a0acb5 100644
--- "a/\345\255\230\345\234\250\347\232\204\351\227\256\351\242\230.txt"
+++ "b/\345\255\230\345\234\250\347\232\204\351\227\256\351\242\230.txt"
@@ -4,10 +4,9 @@
4.个人中心添加一个下载进度展示的条,可能每十秒请求一次数据ok
5.公告区前后端ok
6.个人中心新增的魔力值兑换量之类的接口都接好ok
-7.求种区,前后端
-8.下载进度条合上之后才能测试
+7.求种区,前后端,完成
+8.下载进度条合上之后才能测试(未完成)
9。管理员区里的发布公告,新开一个公告管理,完成
10.轮播图实现折扣展示ok
11.图片展示固定比例,(暂时解决,未找到其他bug,已修复主评论不能上传图片bug)
12.看不到其他人上传的图片(需要云服务器),暂且搁置
-a
\ No newline at end of file