宠物部分

Change-Id: Ie34c359924afc8a1a7634d0ce47030e6071f67de
diff --git a/git-filter-repo.exe b/git-filter-repo.exe
new file mode 100644
index 0000000..8537307
--- /dev/null
+++ b/git-filter-repo.exe
@@ -0,0 +1 @@
+Not Found
\ No newline at end of file
diff --git a/src/components/pet/index.tsx b/src/components/pet/index.tsx
index c859b68..51871bc 100644
--- a/src/components/pet/index.tsx
+++ b/src/components/pet/index.tsx
@@ -1,91 +1,109 @@
-import React, { useState, useEffect } from 'react';
+import React, { useEffect, useRef, useState } from 'react';
+import styles from './pet.module.css'; // 确保这个路径对
 
-const petList = [
-  {
-    id: 'cat01',
-    name: '喵喵',
-    image: '/pets/cat.png',
-    mood: '开心',
-    hunger: 50,
-  },
-  {
-    id: 'dog01',
-    name: '汪汪',
-    image: '/pets/dog.png',
-    mood: '饥饿',
-    hunger: 70,
-  }
-];
+const PetGame: React.FC = () => {
+  const petRef = useRef<HTMLDivElement>(null);
+  const [mood, setMood] = useState(50);
+  const [hunger, setHunger] = useState(50);
 
-const PetGame = () => {
-  const [selectedPetIndex, setSelectedPetIndex] = useState(0);
-  const [petStates, setPetStates] = useState(petList);
-
-  // 定时每 5 秒减少一点饥饿值
+  // 从 localStorage 恢复状态
   useEffect(() => {
-    const timer = setInterval(() => {
-      setPetStates(prev =>
-        prev.map((pet, index) =>
-          index === selectedPetIndex
-            ? {
-                ...pet,
-                hunger: Math.min(100, pet.hunger + 2),
-                mood: pet.hunger > 80 ? '生气' : pet.mood
-              }
-            : pet
-        )
-      );
-    }, 5000);
-    return () => clearInterval(timer);
-  }, [selectedPetIndex]);
+    const saved = localStorage.getItem('petState');
+    if (saved) {
+      const { mood: savedMood, hunger: savedHunger } = JSON.parse(saved);
+      setMood(savedMood);
+      setHunger(savedHunger);
+    }
+  }, []);
 
+  // 每分钟更新状态并保存
+  useEffect(() => {
+    const interval = setInterval(() => {
+      setMood(prev => {
+        const newMood = Math.min(prev + 1, 100);
+        savePetState(newMood, hunger);
+        return newMood;
+      });
+      setHunger(prev => {
+        const newHunger = Math.max(prev - 1, 0);
+        savePetState(mood, newHunger);
+        return newHunger;
+      });
+    }, 60000); // 每分钟一次
+
+    return () => clearInterval(interval);
+  }, [mood, hunger]);
+
+  // 保存状态到 localStorage
+  const savePetState = (newMood: number, newHunger: number) => {
+    localStorage.setItem('petState', JSON.stringify({ mood: newMood, hunger: newHunger }));
+  };
+
+  // 拖动功能(保留)
+  useEffect(() => {
+    const pet = petRef.current;
+    if (!pet) return;
+
+    let offsetX = 0;
+    let offsetY = 0;
+    let isDragging = false;
+
+    const handleMouseDown = (e: MouseEvent) => {
+      isDragging = true;
+      const rect = pet.getBoundingClientRect();
+      offsetX = e.clientX - rect.left;
+      offsetY = e.clientY - rect.top;
+    };
+
+    const handleMouseMove = (e: MouseEvent) => {
+      if (isDragging && pet) {
+        pet.style.left = `${e.clientX - offsetX}px`;
+        pet.style.top = `${e.clientY - offsetY}px`;
+      }
+    };
+
+    const handleMouseUp = () => {
+      isDragging = false;
+    };
+
+    pet.addEventListener('mousedown', handleMouseDown);
+    document.addEventListener('mousemove', handleMouseMove);
+    document.addEventListener('mouseup', handleMouseUp);
+
+    return () => {
+      pet.removeEventListener('mousedown', handleMouseDown);
+      document.removeEventListener('mousemove', handleMouseMove);
+      document.removeEventListener('mouseup', handleMouseUp);
+    };
+  }, []);
+
+  // 喂食按钮逻辑
   const handleFeed = () => {
-    setPetStates(prev =>
-      prev.map((pet, index) =>
-        index === selectedPetIndex
-          ? {
-              ...pet,
-              hunger: Math.max(0, pet.hunger - 20),
-              mood: '开心'
-            }
-          : pet
-      )
-    );
+    const newHunger = Math.min(hunger + 10, 100);
+    setHunger(newHunger);
+    savePetState(mood, newHunger);
   };
 
-  const handlePet = () => {
-    setPetStates(prev =>
-      prev.map((pet, index) =>
-        index === selectedPetIndex
-          ? { ...pet, mood: '超级开心' }
-          : pet
-      )
-    );
+  // 互动按钮逻辑
+  const handleInteract = () => {
+    const newMood = Math.min(mood + 10, 100);
+    setMood(newMood);
+    savePetState(newMood, hunger);
   };
 
-  const currentPet = petStates[selectedPetIndex];
-
   return (
-    <div style={{ textAlign: 'center', padding: 20 }}>
-      <h2>当前宠物:{currentPet.name}</h2>
-      <img
-        src={currentPet.image}
-        alt={currentPet.name}
-        style={{ width: 200, height: 200, cursor: 'pointer' }}
-        onClick={handlePet}
-      />
-      <p>情绪:{currentPet.mood}</p>
-      <p>饥饿值:{currentPet.hunger}/100</p>
+    <div className={styles.cardContainer}>
+      <div className={styles.card}>
+        <p className={styles.text}>情绪:{mood}</p>
+        <p className={styles.text}>饥饿值:{hunger}/100</p>
 
-      <button onClick={handleFeed}>🍖 喂食</button>
+        <button className={styles.feedButton} onClick={handleFeed}>
+          🍖 喂食
+        </button>
 
-      <div style={{ marginTop: 20 }}>
-        <h4>切换宠物:</h4>
-        {petStates.map((pet, index) => (
-          <button key={pet.id} onClick={() => setSelectedPetIndex(index)} style={{ marginRight: 8 }}>
-            {pet.name}
-          </button>
-        ))}
+        <button className={styles.feedButton} onClick={handleInteract}>
+          🐾 摸摸头 / 玩游戏
+        </button>
       </div>
     </div>
   );
diff --git a/src/components/pet/pet.module.css b/src/components/pet/pet.module.css
new file mode 100644
index 0000000..833729a
--- /dev/null
+++ b/src/components/pet/pet.module.css
@@ -0,0 +1,71 @@
+/* 外部容器:左右布局 */
+.wrapper {
+    background:none;
+    border:none;
+    box-shadow: none;
+  display: flex;
+  align-items: flex-start;
+  justify-content: center;
+  padding: 40px;
+  gap: 60px;
+}
+
+/* 宠物区域 */
+.petSection {
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+}
+
+.petImage {
+  width: 200px;
+  height: 200px;
+  object-fit: cover;
+  cursor: pointer;
+  margin-bottom: 12px;
+}
+
+/* 卡片区域:紧跟宠物图下方,模拟右下角 */
+.cardContainer {
+  align-self: flex-end; /* 让它贴底部对齐 */
+  width: 280px;
+}
+
+.card {
+
+  border-radius: 16px;
+
+  padding: 20px;
+}
+
+.text {
+  font-size: 16px;
+  margin: 12px 0;
+  color: #333;
+}
+
+.feedButton {
+  width: 100%;
+  padding: 12px;
+  font-size: 16px;
+  background-color: #ff9800;
+  color: white;
+  border: none;
+  border-radius: 10px;
+  cursor: pointer;
+  margin: 16px 0;
+  transition: background-color 0.2s;
+}
+
+.feedButton:hover {
+  background-color: #fb8c00;
+}
+
+.switchSection {
+  margin-top: 20px;
+}
+
+.switchTitle {
+  font-weight: 600;
+  font-size: 14px;
+}
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 697ed8f..dab0c0f 100644
--- a/src/views/homepage/homepage.tsx
+++ b/src/views/homepage/homepage.tsx
@@ -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,
@@ -50,6 +58,13 @@
   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}}),
@@ -126,7 +141,7 @@
         <div className={styles.userProfile}>
           <div className={styles.userHeader}>
             <img 
-              src={userInfo.avatar || '/default-avatar.png'} 
+              src={head} 
               alt="用户头像" 
               className={styles.userAvatar}
             />
@@ -150,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}>
@@ -189,14 +204,15 @@
           <div className={styles.petSection}>
             <h3 className={styles.sectionTitle}>宠物图</h3>
             <div className={styles.petContainer}>
-              <img 
-                src={Logo}
-                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 d3414ec..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.userInfo });
+
+            //设置宠物初始化参数
+            localStorage.setItem('petState', JSON.stringify({
+            mood: 30,
+            hunger: 50,
+            timestamp: Date.now()
+            }));
+
             nav('/');
         } catch (error) {
             showErrorMessage('登录失败,请检查您的用户名和密码');