Bläddra i källkod

✨ feat(user): 优化用户资料页面性能和数据获取逻辑

- 客户端:移除多个独立API调用,统一从用户资料接口获取关注状态和数量
- 服务端:为用户实体添加isFollowing属性,根据当前用户动态计算关注状态
- 服务端:优化getUserById方法,支持传入currentUserId参数获取关注状态
- 服务端:批量处理用户列表的关注状态查询,减少数据库请求次数
- 客户端:修复错误日志级别,将error改为普通log以避免监控误报

✨ feat(user): 扩展用户数据模型

- 为UserEntity添加isFollowing计算属性
- 在UserSchema中添加isFollowing字段的API文档定义
- 为用户列表查询添加currentUserId参数支持

♻️ refactor(user): 优化用户服务查询逻辑

- 重构getUserById方法,支持动态添加关注状态
- 改进用户列表查询,批量处理关注状态以提升性能
- 在UserService中注入FollowService依赖以获取关注关系数据
yourname 5 månader sedan
förälder
incheckning
adf0365a3c

+ 5 - 22
src/client/home/pages/UserProfilePage.tsx

@@ -35,32 +35,15 @@ const UserProfilePage: React.FC = () => {
       const userData = await response.json();
       setUser(userData);
       
-      // 获取关注状态
+      // 从用户资料中获取关注状态和数量
       if (currentUser && currentUser.id !== Number(id)) {
-        rpcLogger('Checking follow status from user %s to user %s', currentUser.id, id);
-        const followStatus = await userClient[':id'].following['$get']({
-          param: { id },
-          query: { page: 1}
-        });
-        setIsFollowing(followStatus.ok);
+        setIsFollowing(userData.isFollowing || false);
       }
       
-      // 获取关注数量
-      rpcLogger('Fetching followers count for user: %s', id);
-      const followers = await userClient[':id'].followers['$get']({ 
-        param: { id },
-        query: { pageSize: 1 } 
-      });
-      rpcLogger('Fetching following count for user: %s', id);
-      const following = await userClient[':id'].following['$get']({ 
-        param: { id },
-        query: { pageSize: 1 } 
-      });
-      
-      setFollowerCount(await followers.json().then(data => data.pagination.total));
-      setFollowingCount(await following.json().then(data => data.pagination.total));
+      setFollowerCount(userData.followerCount || 0);
+      setFollowingCount(userData.followingCount || 0);
     } catch (error) {
-      rpcLogger.error('Error fetching user profile:', error);
+      rpcLogger('Error fetching user profile:', error);
     } finally {
       setLoading(false);
     }

+ 9 - 1
src/server/modules/users/user.entity.ts

@@ -65,6 +65,10 @@ export class UserEntity {
     Object.assign(this, partial);
   }
 
+  get isFollowing(): boolean {
+    return false;
+  }
+
   get followerCount(): number {
     return this.followers?.length || 0;
   }
@@ -138,6 +142,10 @@ export const UserSchema = z.object({
     description: '关注的用户数量',
     example: 50
   }),
+  isFollowing: z.boolean().openapi({
+    description: '当前用户是否关注该用户',
+    example: false
+  }),
   createdAt: z.date().openapi({ description: '创建时间' }),
-  updatedAt: z.date().openapi({ description: '更新时间' })
+  updatedAt: z.date().openapi({ description: '更新时间' }),
 });

+ 41 - 3
src/server/modules/users/user.service.ts

@@ -6,15 +6,19 @@ import { Role } from './role.entity';
 
 const SALT_ROUNDS = 10;
 
+import { FollowService } from '../follows/follow.service';
+
 export class UserService {
   private userRepository: Repository<User>;
   private roleRepository: Repository<Role>;
+  private followService: FollowService;
   private readonly dataSource: DataSource;
 
   constructor(dataSource: DataSource) {
     this.dataSource = dataSource;
     this.userRepository = this.dataSource.getRepository(User);
     this.roleRepository = this.dataSource.getRepository(Role);
+    this.followService = new FollowService(dataSource);
   }
 
   async createUser(userData: Partial<User>): Promise<User> {
@@ -30,12 +34,19 @@ export class UserService {
     }
   }
 
-  async getUserById(id: number): Promise<User | null> {
+  async getUserById(id: number, currentUserId?: number): Promise<User | null> {
     try {
-      return await this.userRepository.findOne({ 
+      const user = await this.userRepository.findOne({
         where: { id },
         relations: ['roles']
       });
+      
+      if (user && currentUserId && currentUserId !== id) {
+        const isFollowing = await this.followService.isFollowing(currentUserId, id);
+        return { ...user, isFollowing } as User;
+      }
+      
+      return user ? { ...user, isFollowing: false } as User : null;
     } catch (error) {
       console.error('Error getting user:', error);
       throw new Error('Failed to get user');
@@ -92,6 +103,7 @@ export class UserService {
     page: number;
     pageSize: number;
     keyword?: string;
+    currentUserId?: number;
   }): Promise<[User[], number]> {
     try {
       const { page, pageSize, keyword } = params;
@@ -110,7 +122,33 @@ export class UserService {
         );
       }
 
-      return await queryBuilder.getManyAndCount();
+      const [users, total] = await queryBuilder.getManyAndCount();
+      
+      // 如果提供了当前用户ID,添加关注状态
+      const { currentUserId } = params;
+      if (currentUserId) {
+        const usersWithFollowStatus = await Promise.all(
+          users.map(async (user) => {
+            if (user.id === currentUserId) {
+              return { ...user, isFollowing: false };
+            }
+            const isFollowing = await this.followService.isFollowing(
+              currentUserId,
+              user.id
+            );
+            return { ...user, isFollowing };
+          })
+        ) as User[];
+        return [usersWithFollowStatus, total];
+      }
+      
+      // 默认添加isFollowing: false
+      const usersWithFollowStatus = users.map(user => ({
+        ...user,
+        isFollowing: false
+      })) as User[];
+      
+      return [usersWithFollowStatus, total];
     } catch (error) {
       console.error('Error getting users with pagination:', error);
       throw new Error('Failed to get users');