Explorar el Código

fix(auth): 使用RPC类型推断替代手动类型定义,确保前后端数据结构一致

类型安全改进:
- 使用 `InferResponseType` 自动推断类型,替代手动定义 `TalentUserInfo` 接口
- 移除所有手动数据转换逻辑,直接使用 `response` 和 `response.user`
- 修复字段映射错误: `user.id` 不是 `userId`,`personInfo.id` 不是 `personInfo.personId`
- 参考用人方小程序实现,确保类型与后端API完全一致

具体修复:
- useAuth.tsx: `export interface TalentUserInfo` → `export type TalentUserInfo = InferResponseType<...>`
- useQuery: 直接使用 `response` 而非手动转换
- loginMutation: 直接使用 `response.user` 而非手动映射

影响: 现在登录后数据结构与后端完全一致,支持 `gender`、`disabilityLevel` 等所有字段

🤖 Generated with [Claude Code](https://claude.com/claude-code)
via [Happy](https://happy.engineering)

Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Happy <yesreply@happy.engineering>
yourname hace 3 semanas
padre
commit
9b75b392ec

+ 11 - 2
docs/stories/017.011.story.md

@@ -222,12 +222,21 @@ claude-sonnet-4-5-20251101 (James - Dev Agent)
    - 修复内容: `talentAuthClient.login.$post({ body: {...} })` → `talentAuthClient.login.$post({ json: {...} })`
    - 影响范围: 此bug导致账号密码无法正确传递到后端,返回 "data and hash arguments required" 错误
 
-6. **用户体验**: 手机号放在第一位,符合主流APP登录习惯
+6. **任务6完成**: 使用RPC类型推断替代手动类型定义
+   - 发现问题: useAuth.tsx中手动定义了 `TalentUserInfo` 接口,与后端Schema不一致
+   - 字段映射错误: 手动映射 `userId` ← `user.id`,`personInfo.personId` ← `personInfo.id`
+   - 参考实现: 用人方小程序使用 `InferResponseType` 自动推断类型
+   - 修复内容:
+     - `export interface TalentUserInfo {...}` → `export type TalentUserInfo = InferResponseType<typeof talentAuthClient.me.$get, 200>`
+     - 移除所有手动数据转换逻辑,直接使用 `response` 和 `response.user`
+   - 影响范围: 类型安全,自动与后端API保持同步
+
+7. **用户体验**: 手机号放在第一位,符合主流APP登录习惯
 
 ### File List
 
 | 文件路径 | 操作 | 说明 |
 |---------|------|------|
 | `mini-ui-packages/rencai-auth-ui/src/pages/LoginPage/LoginPage.tsx` | 修改 | 更新4处UI文案 |
-| `mini-ui-packages/rencai-auth-ui/src/hooks/useAuth.tsx` | 修改 | 更新错误提示文案 + 修复API调用bug |
+| `mini-ui-packages/rencai-auth-ui/src/hooks/useAuth.tsx` | 修改 | 更新错误提示文案 + 修复API调用bug + 使用RPC类型推断 |
 | `mini-ui-packages/rencai-auth-ui/src/api/talentAuthClient.ts` | 修改 | 添加登录方式说明注释 |

+ 6 - 69
mini-ui-packages/rencai-auth-ui/src/hooks/useAuth.tsx

@@ -4,29 +4,8 @@ import { QueryClient, useQuery, useMutation, useQueryClient } from '@tanstack/re
 import { talentAuthClient } from '../api'
 import type { InferResponseType } from 'hono'
 
-export interface TalentUserInfo {
-  userId: number
-  username: string
-  userType: 'talent'
-  personId?: number
-  phone?: string | null
-  nickname?: string | null
-  name?: string | null
-  // 从 disabled_person 表获取的人才详情
-  personInfo?: {
-    personId: number
-    name: string
-    disabilityType: string
-    idCard: string
-    disabilityId: string
-    phone: string
-    province: string
-    city: string
-    district?: string | null
-    detailedAddress?: string | null
-    jobStatus: number
-  }
-}
+// 使用RPC类型推断,确保类型与后端API完全一致
+export type TalentUserInfo = InferResponseType<typeof talentAuthClient.me.$get, 200>
 
 export interface AuthContextType {
   isLoggedIn: boolean
@@ -68,29 +47,8 @@ export const AuthProvider: React.FC<{ children: ReactNode }> = ({ children }) =>
           throw new Error('获取用户信息失败')
         }
 
-        // 转换API响应为UserInfo格式
-        const userInfo: TalentUserInfo = {
-          userId: response.id,
-          username: response.username,
-          userType: 'talent',
-          personId: response.personId || undefined,
-          phone: response.phone,
-          nickname: response.nickname,
-          name: response.name,
-          personInfo: response.personInfo ? {
-            personId: response.personInfo.id,
-            name: response.personInfo.name,
-            disabilityType: response.personInfo.disabilityType,
-            idCard: response.personInfo.idCard,
-            disabilityId: response.personInfo.disabilityId,
-            phone: response.personInfo.phone,
-            province: response.personInfo.province,
-            city: response.personInfo.city,
-            district: response.personInfo.district,
-            detailedAddress: response.personInfo.detailedAddress,
-            jobStatus: response.personInfo.jobStatus,
-          } : undefined
-        }
+        // 直接使用响应数据,类型已通过RPC推断保证一致
+        const userInfo = response
 
         // 缓存到本地存储
         Taro.setStorageSync(USER_KEY, userInfo)
@@ -127,29 +85,8 @@ export const AuthProvider: React.FC<{ children: ReactNode }> = ({ children }) =>
         throw new Error('登录失败')
       }
 
-      // 转换API响应为UserInfo格式
-      const userInfo: TalentUserInfo = {
-        userId: response.user.id,
-        username: response.user.username,
-        userType: 'talent',
-        personId: response.user.personId || undefined,
-        phone: response.user.phone,
-        nickname: response.user.nickname,
-        name: response.user.name,
-        personInfo: response.user.personInfo ? {
-          personId: response.user.personInfo.id,
-          name: response.user.personInfo.name,
-          disabilityType: response.user.personInfo.disabilityType,
-          idCard: response.user.personInfo.idCard,
-          disabilityId: response.user.personInfo.disabilityId,
-          phone: response.user.personInfo.phone,
-          province: response.user.personInfo.province,
-          city: response.user.personInfo.city,
-          district: response.user.personInfo.district,
-          detailedAddress: response.user.personInfo.detailedAddress,
-          jobStatus: response.user.personInfo.jobStatus,
-        } : undefined
-      }
+      // 直接使用响应数据,类型已通过RPC推断保证一致
+      const userInfo = response.user
 
       // 保存到本地存储
       Taro.setStorageSync(TOKEN_KEY, response.token)

+ 3 - 0
pnpm-lock.yaml

@@ -6977,6 +6977,9 @@ importers:
       '@d8d/allin-company-management-ui':
         specifier: workspace:*
         version: link:../../allin-packages/company-management-ui
+      '@d8d/allin-disability-person-management-ui':
+        specifier: workspace:*
+        version: link:../../allin-packages/disability-person-management-ui
       '@d8d/shared-types':
         specifier: workspace:*
         version: link:../shared-types