宠物界面

Change-Id: I2dd7341009685f4daac87fa0a848032b1d0c1e42
diff --git a/src/views/forum/index.tsx b/src/views/forum/index.tsx
index 13c369f..d2e7c5a 100644
--- a/src/views/forum/index.tsx
+++ b/src/views/forum/index.tsx
@@ -12,7 +12,12 @@
 import ad2 from '&/assets/ad2.png'
 import { useEffect } from "react";
 
+
+
 export default function Forum() {
+
+
+    
     useEffect(() => {
         // 禁止滚动
         document.body.style.overflow = 'hidden';
diff --git a/src/views/homepage/homepage.module.css b/src/views/homepage/homepage.module.css
index fdcc060..cd57580 100644
--- a/src/views/homepage/homepage.module.css
+++ b/src/views/homepage/homepage.module.css
@@ -1,25 +1,9 @@
-/* 主题色变量 */
-/* :root {
-    --primary-color: #3498db; 
-    --primary-hover: #2980b9;
-    --secondary-color: #f1c40f; 
-    --dark-color: #2c3e50; 
-    --light-color: #ecf0f1;
-    --text-color: #333;
-    --text-secondary: #7f8c8d;
-    --border-color: #ddd;
-  } */
-  
-    /* --bg-color: #2b2b2b;
-    --text-color: #f1f1f1;
-    --card-bg: #1e1e1e;
-    --border-color: #444444; */
-
   .container {
     min-height: 100vh;
     background-color: var(--bg-color);
     color: var(--text-color);
     font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
+    overflow: hidden;
   }
   
   /* 顶部导航栏 */
@@ -157,8 +141,14 @@
   /* 作品区 */
   .worksSection {
     margin-top: 30px;
+    max-height: 450px;
+    overflow-y: auto;
   }
-  
+
+  .worksSection::-webkit-scrollbar {
+    width: 6px;
+  }
+
   .sectionTitle {
     margin: 0 0 20px 0;
     color: var(--dark-color);
diff --git a/src/views/homepage/homepage.tsx b/src/views/homepage/homepage.tsx
index ec74187..dab0c0f 100644
--- a/src/views/homepage/homepage.tsx
+++ b/src/views/homepage/homepage.tsx
@@ -1,10 +1,10 @@
 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 { useAppSelector } from '@/hooks/store';
 import { RootState } from '@/store';
 import { useNavigate } from 'react-router';
-import logo from '&/assets/logo.png';
+import  Logo  from '&/assets/logo.png';
 import { getUserMessage } from '@/api/homepage'
 import { getUserDetail } from '@/api/homepage'
 import request from '@/utils/request'
@@ -12,6 +12,14 @@
 import { postUserLogin } from '@/api/auth';
 import { debounce } from 'lodash';
 import { Q } from 'react-router/dist/development/fog-of-war-CGNKxM4z';
+import head from '&/assets/head.jpg'
+import lv_one from '&/assets/pet/lv_one.png'
+import lv_two from '&/assets/pet/lv_two.png'
+import lv_three from '&/assets/pet/lv_three.png'
+import lv_four from '&/assets/pet/lv_four.png'
+import lv_five from '&/assets/pet/lv_five.png'
+import PetGame from '@/components/pet'
+
 
 interface WorkItem {  
   postId: number,
@@ -46,25 +54,47 @@
   const [works, setWorks] = useState<WorkItem[]>([]);
   const worksRef = useRef<WorkItem[]>([]);
 
-
   const navigate = useNavigate();
-  const userInfo = useSelector((state: RootState) => state.user);
+  const userInfo = useAppSelector((state: RootState) => state.user);
   const userId = userInfo.userId; // 从Redux获取当前用户ID
 
+  const levelImages: { [key: string]: string } = {
+    'lv1': lv_one,
+    'lv2': lv_two,
+    'lv3': lv_three,
+    'lv4': lv_four,
+    'lv5': lv_five
+  };
+
   const { data:userdata, loading:userloading, error:usererror, refresh: getUserDetailRefresh } = useApi(
-    () => request.get(getUserDetail, {params: {userId}}).then(res => res.data.data),
+    () => request.get(getUserDetail, {params: {userId}}),
+    false
   );
 
-  const { data:workdata, loading:workloading, error:workerror, refresh: getUserMessageRefresh } = useApi(
-    () => request.get(getUserMessage, { params: { userId } }).then(res => res.data.data),
+  const { data: workdata, loading: workloading, error: workerror, refresh: getUserMessageRefresh } = useApi(
+    () => request.get(`${getUserMessage}/${userId}`), // 注意这里拼接了 userId
     false
   );
 
   const getUserDetails = debounce(async () => {
     try{
-      const res = await  getUserDetailRefresh({userId});
-      console.log("res", res);
-      setUserStats(res);
+      // const res = await  getUserDetailRefresh({userId});
+      const res = await  getUserDetailRefresh();
+      const data_1 = res?.userInfo;
+      const data_2 = res?.statistics;
+      console.log('data', data_1)
+      const formatted: UserStats = {
+        username: data_1.userName,
+        uploadAmount: data_1.uploadAmount,
+        level: data_1.userLevel,
+        likes: data_2.likes,
+        following: data_2.followingCount,
+        followers: data_2.followersCount,
+        mutualFollows: data_2.mutualFollows
+      };
+
+      setUserStats(formatted);
+      console.log('formatted:',formatted)
     }catch(error){
       console.error('获取用户信息错误', error);
     }
@@ -72,15 +102,21 @@
 
 
   const getUserPost = debounce(async () => {
-    try{
-      const res = await getUserMessageRefresh({userId});
+    try {
+      const url = `${getUserMessage}/${userId}`; // ✅ 正确的 URL 拼接方式
+      console.log("请求发送:", url);
+
+      // 不需要传 userId 参数了,因为 URL 已包含它
+      const res = await getUserMessageRefresh();
       console.log("res", res);
+
       worksRef.current = res;
       setWorks(res);
-    }catch(error) {
+    } catch (error) {
       console.error('获取帖子列表错误', error);
     }
-  },1000) as () => void;
+  }, 1000) as () => void;
+
 
   useEffect(() => {
     if (!userId) {
@@ -105,13 +141,13 @@
         <div className={styles.userProfile}>
           <div className={styles.userHeader}>
             <img 
-              src={userInfo.avatar || '/default-avatar.png'} 
+              src={head} 
               alt="用户头像" 
               className={styles.userAvatar}
             />
             <div className={styles.userInfo}>
-              <h2 className={styles.username}>阳菜,放睛!</h2>
-              <div className={styles.inviteCode}>邀请码:1314520</div>
+              <h2 className={styles.username}>{userStats?.username}</h2>
+              <div className={styles.inviteCode}>邀请码:123456</div>
               <button className={styles.editButton}>编辑主页</button>
             </div>
           </div>
@@ -129,10 +165,10 @@
               <div className={styles.statNumber}>{userStats?.followers ?? '--'}</div>
               <div className={styles.statLabel}>粉丝</div>
             </div>
-            <div className={styles.statItem}>
+            {/* <div className={styles.statItem}>
               <div className={styles.statNumber}>{userStats?.mutualFollows ?? '--'}</div>
               <div className={styles.statLabel}>互关</div>
-            </div>
+            </div> */}
           </div>
 
           <div className={styles.userData}>
@@ -168,14 +204,15 @@
           <div className={styles.petSection}>
             <h3 className={styles.sectionTitle}>宠物图</h3>
             <div className={styles.petContainer}>
-              <img 
-                src="/assets/pet-blue-star.png" 
-                alt="蓝色星星宠物" 
-                className={styles.petImage}
-              />
+            <img 
+              src={levelImages[userStats?.level || 'lv5']} // 默认用 '1' 级
+              alt={`等级${userStats?.level}宠物`} 
+              className={styles.petImage}
+            />
             </div>
+            <PetGame/>
           </div>
-
+            
         </div>
       </div>
     </div>
diff --git a/src/views/login/login.tsx b/src/views/login/login.tsx
index fef6e32..70b5573 100644
--- a/src/views/login/login.tsx
+++ b/src/views/login/login.tsx
@@ -48,7 +48,16 @@
             if (userInfo == null || (userInfo as any).error) {
                 throw new Error('获取用户信息失败');
             }
-            dispatch({ type: "user/getUserInfo", payload: userInfo });
+
+            dispatch({ type: "user/getUserInfo", payload: userInfo.userInfo });
+
+            //设置宠物初始化参数
+            localStorage.setItem('petState', JSON.stringify({
+            mood: 30,
+            hunger: 50,
+            timestamp: Date.now()
+            }));
+
             nav('/');
         } catch (error) {
             showErrorMessage('登录失败,请检查您的用户名和密码');
diff --git a/src/views/postDetail/postDetail.tsx b/src/views/postDetail/postDetail.tsx
index d6029a8..202907b 100644
--- a/src/views/postDetail/postDetail.tsx
+++ b/src/views/postDetail/postDetail.tsx
@@ -65,6 +65,8 @@
       const commentsRes = await getPostCommentsRefresh();
       setComments(commentsRes as CommentResponse[]);
       setLoading(false);
+      console.log("postRes:", postRes);
+      console.log("commentsRes:", commentsRes);
     };
     fetchData();
   }, [postId]);
diff --git a/src/views/search/search.module.css b/src/views/search/search.module.css
index 2e1f40a..4475d20 100644
--- a/src/views/search/search.module.css
+++ b/src/views/search/search.module.css
@@ -130,3 +130,28 @@
   display: flex;
   justify-content: flex-end;
 }
+
+
+.secondaryHeader {
+  display: flex;
+  justify-content: space-between;
+  align-items: flex-start;
+  padding: 16px;
+  border-bottom: 1px solid var(--primary-color);
+  background-color: var(--light-color);
+}
+
+.results {
+  margin-top: 20px;
+  padding: 20px;
+}
+
+.resultList {
+  list-style: none;
+  padding: 0;
+}
+
+.resultItem {
+  border-bottom: 1px solid var(--primary-color);
+  padding: 12px 0;
+}
diff --git a/src/views/search/search.tsx b/src/views/search/search.tsx
index 6dba69c..bf252c5 100644
--- a/src/views/search/search.tsx
+++ b/src/views/search/search.tsx
@@ -2,6 +2,7 @@
 import React, { useState, useEffect } from 'react';
 import styles from './search.module.css';
 import { useLocation } from "react-router-dom";
+import { getSearch } from '@/api/search'
 
 interface PostItem {
   postId: number;
@@ -32,19 +33,49 @@
     11: "table",
   },
   video: {
-    20: "视频标签1",
-    21: "视频标签2",
-    22: "视频标签3",
+    20: "chinese",
+    21: "America",
+    22: "Japan",
+    23: "Koera",
+    24: "Europe",
+    25: "other",
+    26: "Short",
+    27: "plot",
+    28: "comedy",
+    29: "love",
+    30: "action",
+    31: "terror",
+    32: "science fiction",
+    33: "commit a crime",
+    34: "Thriller",
   },
   music: {
-    40: "音乐标签1",
-    41: "音乐标签2",
-    42: "音乐标签3",
+    40: "chinese",
+    41: "America",
+    42: "Japan",
+    43: "Korea",
+    44: "Europe",
+    45: "other",
+    46: "rap",
+    47: "Electric sound",
+    48: "Guofeng",
+    49: "motion",
+    50: "ballad",
+    51: "Rock and roll",
+    52: "classical",
   },
   software: {
-    60: "软件标签1",
-    61: "软件标签2",
-    62: "软件标签3",
+    60: "android",
+    61: "mac",
+    62: "pc",
+    63: "ios",
+    64: "other",
+    65: "life",
+    66: "shopping",
+    67: "video",
+    68: "music",
+    69: "read",
+    70: "system",
   },
 };
 
@@ -64,13 +95,34 @@
   };
 
   useEffect(() => {
-    fetch('/api/posts')
-      .then((res) => res.json())
-      .then((data) => {
+    if (!keyword) return;
+
+    const requestBody = {
+      keyword,
+      tags: [] // 可以为空
+    };
+
+  console.log("请求发送:", getSearch, requestBody);
+
+
+    fetch(getSearch, {
+      method: 'Get',
+      headers: {
+        'Content-Type': 'application/json'
+      },
+      body: JSON.stringify(requestBody)
+    })
+      .then(res => res.json())
+      .then((res) => {
+        const data: PostItem[] = res.data;
         setPosts(data);
         setFilteredPosts(data);
+      })
+      .catch((error) => {
+        console.error('搜索请求失败:', error);
       });
-  }, []);
+  }, [keyword]);
+
 
   const applyFilters = () => {
     let filtered = posts;
@@ -94,6 +146,7 @@
   };
 
   return (
+    <div>
     <div className={styles.secondaryHeader}>
     <div className={styles.leftSection}>
         <select
@@ -154,6 +207,26 @@
     </div>
     </div>
 
+    <div className={styles.results}>
+      {filteredPosts.length === 0 ? (
+        <p>暂无搜索结果</p>
+      ) : (
+        <ul className={styles.resultList}>
+          {filteredPosts.map((post) => (
+            <li key={post.postId} className={styles.resultItem}>
+              <h3>{post.postTitle || '无标题'}</h3>
+              <p>{post.postContent || '无内容'}</p>
+              <p>类型:{post.postType || '未知'} | 热度评分:{post.hotScore}</p>
+            </li>
+          ))}
+        </ul>
+      )}
+    </div>
+
+  </div>
+
+        
+
   );
 };
 
diff --git a/src/views/upload/upload.tsx b/src/views/upload/upload.tsx
index 1bf096a..19e1197 100644
--- a/src/views/upload/upload.tsx
+++ b/src/views/upload/upload.tsx
@@ -71,7 +71,7 @@
     try {
       const res = await instance.post(Upload, payload);
 
-      console.log('mock返回内容:', res.code);
+      console.log('后端返回内容:', res.code);
 
       // 判断返回内容是否成功(根据你 mock 接口返回的 code 字段)
       if (res.code !== 0) throw new Error('发布失败');