blob: e75abb0b2a25c59653c936361c6816743b3446ee [file] [log] [blame]
95630366980c1f272025-06-20 14:08:54 +08001// 搜索推荐算法相关的API接口
22301008ba662fe2025-06-20 18:10:20 +08002// 仅首页推荐和搜索使用 JWLLL 后端服务
3// 其他功能使用对应的后端服务
95630366980c1f272025-06-20 14:08:54 +08004
22301008ba662fe2025-06-20 18:10:20 +08005// JWLLL 后端服务 - 仅用于推荐和搜索
6const JWLLL_BASE_URL = 'http://10.126.59.25:5717'
7// WZY 后端服务 - 用于帖子详情、点赞、评论等
22301008e25b4b02025-06-20 22:15:31 +08008const WZY_BASE_URL = 'http://192.168.5.235:5714'
95630366980c1f272025-06-20 14:08:54 +08009
10// 通用请求函数
11const request = async (url, options = {}) => {
12 try {
13 const response = await fetch(url, {
14 headers: {
15 'Content-Type': 'application/json',
16 ...options.headers
17 },
18 ...options
19 })
22301008e4acb922025-06-24 23:50:35 +080020
21 // 检查响应状态码
22 if (!response.ok) {
23 let errorData
24 try {
25 errorData = await response.json()
26 } catch {
27 errorData = { error: `HTTP ${response.status}` }
28 }
29 throw new Error(errorData.error || `HTTP ${response.status}`)
30 }
31
32 // 处理空响应(如204 No Content)
33 const contentType = response.headers.get('content-type')
34 if (contentType && contentType.includes('application/json')) {
35 return await response.json()
36 } else {
37 return {} // 返回空对象而不是尝试解析JSON
38 }
95630366980c1f272025-06-20 14:08:54 +080039 } catch (error) {
40 console.error('API请求错误:', error)
41 throw error
42 }
43}
44
22301008ba662fe2025-06-20 18:10:20 +080045// 搜索推荐API
95630366980c1f272025-06-20 14:08:54 +080046export const searchAPI = {
22301008ba662fe2025-06-20 18:10:20 +080047 // ===== 推荐和搜索功能 - 使用 JWLLL 服务 =====
48
95630366980c1f272025-06-20 14:08:54 +080049 // 搜索内容
50 search: async (keyword, category = undefined) => {
22301008ba662fe2025-06-20 18:10:20 +080051 return await request(`${JWLLL_BASE_URL}/search`, {
95630366980c1f272025-06-20 14:08:54 +080052 method: 'POST',
53 body: JSON.stringify({ keyword, category })
54 })
55 },
56
57 // 获取用户标签
58 getUserTags: async (userId) => {
22301008ba662fe2025-06-20 18:10:20 +080059 return await request(`${JWLLL_BASE_URL}/user_tags?user_id=${userId}`)
95630366980c1f272025-06-20 14:08:54 +080060 },
61
62 // 标签推荐
63 recommendByTags: async (userId, tags) => {
22301008ba662fe2025-06-20 18:10:20 +080064 return await request(`${JWLLL_BASE_URL}/recommend_tags`, {
95630366980c1f272025-06-20 14:08:54 +080065 method: 'POST',
66 body: JSON.stringify({ user_id: userId, tags })
67 })
68 },
69
70 // 协同过滤推荐
71 userBasedRecommend: async (userId, topN = 20) => {
22301008ba662fe2025-06-20 18:10:20 +080072 return await request(`${JWLLL_BASE_URL}/user_based_recommend`, {
95630366980c1f272025-06-20 14:08:54 +080073 method: 'POST',
74 body: JSON.stringify({ user_id: userId, top_n: topN })
75 })
76 },
77
22301008ba662fe2025-06-20 18:10:20 +080078 // ===== 其他功能 - 使用 WZY 服务 =====
79
95630366980c1f272025-06-20 14:08:54 +080080 // 获取帖子详情
81 getPostDetail: async (postId) => {
22301008ba662fe2025-06-20 18:10:20 +080082 return await request(`${WZY_BASE_URL}/posts/${postId}`)
22301008e4acb922025-06-24 23:50:35 +080083 }, // 点赞帖子
95630366980c1f272025-06-20 14:08:54 +080084 likePost: async (postId, userId) => {
22301008ba662fe2025-06-20 18:10:20 +080085 return await request(`${WZY_BASE_URL}/posts/${postId}/like`, {
95630366980c1f272025-06-20 14:08:54 +080086 method: 'POST',
22301008ba662fe2025-06-20 18:10:20 +080087 body: JSON.stringify({ user_id: userId })
95630366980c1f272025-06-20 14:08:54 +080088 })
89 },
90
91 // 取消点赞
92 unlikePost: async (postId, userId) => {
22301008ba662fe2025-06-20 18:10:20 +080093 return await request(`${WZY_BASE_URL}/posts/${postId}/like`, {
94 method: 'DELETE',
95 body: JSON.stringify({ user_id: userId })
95630366980c1f272025-06-20 14:08:54 +080096 })
97 },
wu5a4acf72025-06-24 15:38:29 +080098 // 查看是否点赞
99 hasLiked: async (postId, userId) => {
100 const res = await request(
22301008e4acb922025-06-24 23:50:35 +0800101 `${WZY_BASE_URL}/posts/${postId}/like/status?user_id=${userId}`,
wu5a4acf72025-06-24 15:38:29 +0800102 {
103 method: 'GET'
104 }
105 )
106 return res.liked
107 },
108
95630366980c1f272025-06-20 14:08:54 +0800109 // 添加评论
110 addComment: async (postId, userId, content) => {
22301008ba662fe2025-06-20 18:10:20 +0800111 return await request(`${WZY_BASE_URL}/posts/${postId}/comments`, {
95630366980c1f272025-06-20 14:08:54 +0800112 method: 'POST',
22301008ba662fe2025-06-20 18:10:20 +0800113 body: JSON.stringify({ user_id: userId, content })
95630366980c1f272025-06-20 14:08:54 +0800114 })
22301008ba662fe2025-06-20 18:10:20 +0800115 }, // 获取评论
95630366980c1f272025-06-20 14:08:54 +0800116 getComments: async (postId) => {
22301008ba662fe2025-06-20 18:10:20 +0800117 const comments = await request(`${WZY_BASE_URL}/posts/${postId}/comments`)
118 // 适配数据格式,WZY服务返回数组,而前端期望 {comments: [...]}
119 // 同时转换字段名以适配前端期望的格式
120 const adaptedComments = Array.isArray(comments) ? comments.map(comment => ({
121 ...comment,
122 user_name: comment.user_name || `用户${comment.user_id}`, // 如果没有用户名,使用用户ID生成
123 create_time: comment.created_at // 将 created_at 映射为 create_time
124 })) : []
125 return { comments: adaptedComments }
95630366980c1f272025-06-20 14:08:54 +0800126 },
95630366980c1f272025-06-20 14:08:54 +0800127 // 上传帖子
128 uploadPost: async (postData) => {
22301008ba662fe2025-06-20 18:10:20 +0800129 // 转换数据格式以适配 WZY 服务
130 const payload = {
131 user_id: postData.user_id || 1, // 默认用户ID
132 title: postData.title,
133 content: postData.content,
134 type: postData.type || 'text', // 默认为文本类型
135 media_urls: postData.media_files || [],
136 status: 'published' // 直接发布,不需要审核
137 }
138
139 const result = await request(`${WZY_BASE_URL}/posts`, {
95630366980c1f272025-06-20 14:08:54 +0800140 method: 'POST',
22301008ba662fe2025-06-20 18:10:20 +0800141 body: JSON.stringify(payload)
95630366980c1f272025-06-20 14:08:54 +0800142 })
22301008ba662fe2025-06-20 18:10:20 +0800143
144 // 注意:WZY 服务目前不支持标签功能,tags 会被忽略
145 // 如果需要标签功能,需要额外的API调用或使用支持标签的服务
146
147 return result
95630366980c1f272025-06-20 14:08:54 +0800148 }
149}
150
151export default searchAPI