post.ts 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. import { createRoute, OpenAPIHono } from '@hono/zod-openapi';
  2. import { z } from '@hono/zod-openapi';
  3. import { MiniAuthService } from '../../../modules/auth/mini-auth.service';
  4. import { AppDataSource } from '../../../data-source';
  5. import { ErrorSchema } from '../../../utils/errorHandler';
  6. import { UserEntity } from '../../../modules/users/user.entity';
  7. import { UserResponseSchema } from '../../../modules/users/user.schema';
  8. import { parseWithAwait } from '../../../utils/parseWithAwait';
  9. const MiniLoginSchema = z.object({
  10. code: z.string().openapi({
  11. example: '08123456789012345678901234567890',
  12. description: '小程序登录code'
  13. }),
  14. userInfo: z.object({
  15. nickName: z.string().optional(),
  16. avatarUrl: z.string().optional()
  17. }).optional()
  18. });
  19. const MiniLoginResponseSchema = z.object({
  20. token: z.string().openapi({
  21. example: 'jwt.token.here',
  22. description: 'JWT Token'
  23. }),
  24. user: UserResponseSchema,
  25. isNewUser: z.boolean().openapi({
  26. example: true,
  27. description: '是否为新注册用户'
  28. })
  29. });
  30. const miniLoginRoute = createRoute({
  31. method: 'post',
  32. path: '/mini-login',
  33. request: {
  34. body: {
  35. content: {
  36. 'application/json': {
  37. schema: MiniLoginSchema
  38. }
  39. }
  40. }
  41. },
  42. responses: {
  43. 200: {
  44. description: '小程序登录成功',
  45. content: {
  46. 'application/json': {
  47. schema: MiniLoginResponseSchema
  48. }
  49. }
  50. },
  51. 400: {
  52. description: '参数错误',
  53. content: {
  54. 'application/json': {
  55. schema: ErrorSchema
  56. }
  57. }
  58. },
  59. 500: {
  60. description: '服务器错误',
  61. content: {
  62. 'application/json': {
  63. schema: ErrorSchema
  64. }
  65. }
  66. }
  67. }
  68. });
  69. const miniAuthService = new MiniAuthService(AppDataSource);
  70. const app = new OpenAPIHono().openapi(miniLoginRoute, async (c) => {
  71. try {
  72. const { code, userInfo } = c.req.valid('json');
  73. const result = await miniAuthService.miniLogin(code);
  74. // 如果有用户信息,更新用户资料
  75. if (userInfo) {
  76. await miniAuthService.updateUserProfile(result.user.id, {
  77. nickname: userInfo.nickName,
  78. avatarUrl: userInfo.avatarUrl
  79. });
  80. // 重新获取更新后的用户信息
  81. const updatedUser = await AppDataSource.getRepository(UserEntity).findOne({
  82. where: { id: result.user.id },
  83. relations: ['avatarFile']
  84. });
  85. if (updatedUser) {
  86. result.user = updatedUser;
  87. }
  88. }
  89. // 获取完整的用户信息(包含所有字段)
  90. const fullUser = await AppDataSource.getRepository(UserEntity).findOne({
  91. where: { id: result.user.id },
  92. relations: ['avatarFile', 'roles']
  93. });
  94. if (!fullUser) {
  95. return c.json({ code: 500, message: '用户信息获取失败' }, 500);
  96. }
  97. // 构建用户响应数据
  98. const userResponseData = {
  99. token: result.token,
  100. user: fullUser,
  101. isNewUser: result.isNewUser
  102. };
  103. // 使用parseWithAwait处理异步字段
  104. const validatedResponse = await parseWithAwait(MiniLoginResponseSchema, userResponseData);
  105. return c.json(validatedResponse, 200);
  106. } catch (error) {
  107. const { code = 500, message = '登录失败' } = error as Error & { code?: number };
  108. return c.json({ code, message }, 500);
  109. }
  110. });
  111. export default app;