Browse Source

✨ feat(auth): add user information update feature

- add PUT /me API endpoint for updating user information
- implement user update mutation with error handling and toast notifications
- add input validation and response schemas for user update API
- update auth context to include async updateUser method using mutation
- add success/error feedback for user update operations

♻️ refactor(auth): improve user state management

- replace simple updateUser function with useMutation hook
- add storage synchronization when user data updates
- implement proper error handling for user update operations
yourname 4 tháng trước cách đây
mục cha
commit
eeda21bcd7
3 tập tin đã thay đổi với 127 bổ sung6 xóa
  1. 27 6
      mini/src/utils/auth.tsx
  2. 2 0
      src/server/api/auth/index.ts
  3. 98 0
      src/server/api/auth/me/put.ts

+ 27 - 6
mini/src/utils/auth.tsx

@@ -125,13 +125,34 @@ export const AuthProvider: React.FC<PropsWithChildren> = ({ children }) => {
     },
   })
 
-  const updateUser = (userData: Partial<User>) => {
-    if (user) {
-      const updatedUser = { ...user, ...userData }
-      queryClient.setQueryData(['currentUser'], updatedUser)
+  const updateUserMutation = useMutation<User, Error, Partial<User>>({
+    mutationFn: async (userData) => {
+      const response = await authClient.me.$put({ json: userData })
+      if (response.status !== 200) {
+        throw new Error('更新用户信息失败')
+      }
+      const updatedUser = await response.json()
       Taro.setStorageSync('userInfo', JSON.stringify(updatedUser))
-    }
-  }
+      return updatedUser
+    },
+    onSuccess: (updatedUser) => {
+      queryClient.setQueryData(['currentUser'], updatedUser)
+      Taro.showToast({
+        title: '更新成功',
+        icon: 'success',
+        duration: 2000,
+      })
+    },
+    onError: (error) => {
+      Taro.showToast({
+        title: error.message || '更新失败,请重试',
+        icon: 'none',
+        duration: 2000,
+      })
+    },
+  })
+
+  const updateUser = updateUserMutation.mutateAsync
 
   const value = {
     user: user || null,

+ 2 - 0
src/server/api/auth/index.ts

@@ -2,6 +2,7 @@ import { OpenAPIHono } from '@hono/zod-openapi';
 import loginRoute from './login/post';
 import logoutRoute from './logout';
 import meRoute from './me/get';
+import putMeRoute from './me/put';
 import registerRoute from './register/create';
 import ssoVerify from './sso-verify';
 
@@ -9,6 +10,7 @@ const app = new OpenAPIHono()
   .route('/', loginRoute)
   .route('/', logoutRoute)
   .route('/', meRoute)
+  .route('/', putMeRoute)
   .route('/', registerRoute)
   .route('/', ssoVerify);
 

+ 98 - 0
src/server/api/auth/me/put.ts

@@ -0,0 +1,98 @@
+import { createRoute, OpenAPIHono } from '@hono/zod-openapi'
+import { ErrorSchema } from '@/server/utils/errorHandler'
+import { authMiddleware } from '@/server/middleware/auth.middleware'
+import { AuthContext } from '@/server/types/context'
+import { UserSchema , UpdateUserDto} from '@/server/modules/users/user.schema'
+import { UserService } from '@/server/modules/users/user.service'
+import { AppDataSource } from '@/server/data-source'
+import { parseWithAwait } from '@/server/utils/parseWithAwait'
+
+// 定义响应schema,排除密码
+const UserResponseSchema = UserSchema.omit({
+  password: true
+})
+
+const routeDef = createRoute({
+  method: 'put',
+  path: '/me',
+  middleware: [authMiddleware],
+  request: {
+    body: {
+      content: {
+        'application/json': {
+          schema: UpdateUserDto
+        }
+      }
+    }
+  },
+  responses: {
+    200: {
+      description: '用户信息更新成功',
+      content: {
+        'application/json': {
+          schema: UserResponseSchema
+        }
+      }
+    },
+    400: {
+      description: '请求参数错误',
+      content: {
+        'application/json': {
+          schema: ErrorSchema
+        }
+      }
+    },
+    401: {
+      description: '未授权',
+      content: {
+        'application/json': {
+          schema: ErrorSchema
+        }
+      }
+    },
+    404: {
+      description: '用户不存在',
+      content: {
+        'application/json': {
+          schema: ErrorSchema
+        }
+      }
+    },
+    500: {
+      description: '服务器错误',
+      content: {
+        'application/json': {
+          schema: ErrorSchema
+        }
+      }
+    }
+  }
+})
+
+const app = new OpenAPIHono<AuthContext>().openapi(routeDef, async (c) => {
+  try {
+    const user = c.get('user')
+    const updateData = c.req.valid('json')
+    
+    const userService = new UserService(AppDataSource)
+    
+    // 更新用户信息
+    const updatedUser = await userService.updateUser(user.id, updateData)
+    
+    if (!updatedUser) {
+      return c.json({ code: 404, message: '用户不存在' }, 404)
+    }
+    
+    // 返回更新后的用户信息(不包含密码)
+    return c.json(await parseWithAwait(UserResponseSchema, updatedUser), 200)
+    
+  } catch (error) {
+    console.error('更新用户信息失败:', error)
+    return c.json({ 
+      code: 500, 
+      message: error instanceof Error ? error.message : '更新用户信息失败' 
+    }, 500)
+  }
+})
+
+export default app