# 用户名显示修复方案 > **更新时间**:2025年11月2日 > **状态**:✅ 已完成多层降级方案 --- ## 🎯 问题 导航条显示"未知用户",因为 Profile 表中没有存储用户的姓名信息。 --- ## 🔧 修复方案 ### 多层降级策略 我实现了 **5 层降级方案**,确保无论什么情况都能显示有意义的用户名: ``` 层级 1: Profile 表字段 ├─ profile.name ├─ profile.realname ├─ profile.username └─ profile.nickname 层级 2: 浏览器存储 ├─ localStorage.wxwork_userInfo ├─ localStorage.userInfo └─ sessionStorage.userInfo 层级 3: 企微 API └─ wxAuth.getUserInfo() 层级 4: Parse User 对象 └─ currentUser.username 层级 5: 使用 userid 生成 └─ "设计师-{userid前6位}" ``` --- ## 💡 新增功能 ### 1. 从浏览器获取用户信息 ```typescript private getUserInfoFromBrowser(): any { // 尝试从 localStorage 获取 const userInfoStr = localStorage.getItem('wxwork_userInfo') || localStorage.getItem('userInfo'); if (userInfoStr) { return JSON.parse(userInfoStr); } // 尝试从 sessionStorage 获取 const sessionUserInfoStr = sessionStorage.getItem('wxwork_userInfo'); if (sessionUserInfoStr) { return JSON.parse(sessionUserInfoStr); } return null; } ``` ### 2. 从 userid 生成显示名 ```typescript private generateNameFromUserid(userid: string): string { if (!userid) return '未知用户'; // 例如:woAs2qCQAA... -> 设计师-woAs2q const shortId = userid.slice(0, 6); return `设计师-${shortId}`; } ``` ### 3. 同步企微用户信息到 Profile ```typescript private async syncWxworkUserInfo(profile: FmodeObject): Promise { // 如果 Profile 已有用户名,跳过 if (profile.get('name')) return; // 方案1: 从浏览器获取 const browserUserInfo = this.getUserInfoFromBrowser(); // 方案2: 从企微 API 获取 if (!browserUserInfo) { userInfo = await this.wxAuth?.getUserInfo(); } // 更新并保存 Profile if (userInfo?.name) { profile.set('name', userInfo.name); profile.set('realname', userInfo.name); await profile.save(); } } ``` --- ## 🧪 测试步骤 ### 步骤 1: 强制刷新页面 按 **Ctrl+Shift+R** (Windows) 或 **Cmd+Shift+R** (Mac) ### 步骤 2: 打开控制台(F12) ### 步骤 3: 查看日志 #### 成功获取用户名 ``` 🔄 开始同步企微用户信息... 📋 从 localStorage 获取用户信息: {name: '王刚', ...} ✅ 设置用户名: 王刚 ✅ 用户信息已同步到 Profile 📋 从浏览器获取用户信息成功: {name: '王刚', ...} ✅ 用户信息映射完成: {name: '王刚', roleName: '组员'} ``` #### 使用 userid 生成 ``` ⚠️ 浏览器中未找到企微用户信息 ⚠️ 企微 API 获取用户信息失败 📋 使用 userid 生成显示名: 设计师-woAs2q ✅ 用户信息映射完成: {name: '设计师-woAs2q', roleName: '组员'} ``` --- ## 🎨 预期效果 ### 场景 A:有真实姓名 ``` ┌─────────────────────────────────────────────────────────┐ │ 设计师工作台 2025年11月2日星期六 [头像] 王刚 [组员] │ (紫色渐变) └─────────────────────────────────────────────────────────┘ ``` ### 场景 B:使用 userid ``` ┌───────────────────────────────────────────────────────────────┐ │ 设计师工作台 2025年11月2日星期六 [头像] 设计师-woAs2q [组员] │ (紫色渐变) └───────────────────────────────────────────────────────────────┘ ``` ### 场景 C:完全降级 ``` ┌──────────────────────────────────────────────────────────────┐ │ 设计师工作台 2025年11月2日星期六 [头像] 未知用户 [组员] │ (紫色渐变) └──────────────────────────────────────────────────────────────┘ ``` --- ## 📊 降级流程图 ``` 开始 ↓ Profile 有 name/realname? ├─ 是 → ✅ 使用 Profile.name └─ 否 → 继续 ↓ localStorage 有 userInfo? ├─ 是 → ✅ 使用 localStorage.userInfo.name └─ 否 → 继续 ↓ wxAuth.getUserInfo() 成功? ├─ 是 → ✅ 使用 API 返回的 name └─ 否 → 继续 ↓ 有 userid? ├─ 是 → ✅ 使用 "设计师-{userid前6位}" └─ 否 → ⚠️ 显示 "未知用户" ``` --- ## 🔍 调试信息 刷新页面后,请检查控制台中的这些日志: ### 1. 用户信息同步日志 ``` 🔄 开始同步企微用户信息... 📋 从 localStorage 获取用户信息: {...} ✅ 设置用户名: xxx ✅ 设置头像: xxx ✅ 用户信息已同步到 Profile ``` ### 2. 用户信息映射日志 ``` 📋 Profile 字段调试: { name: '王刚', realname: '王刚', avatar: 'http://...', 最终使用的name: '王刚', 最终使用的avatar: 'http://...' } ✅ 用户信息映射完成: {userid: '...', name: '王刚', ...} ``` --- ## ✅ 优势 ### 1. 多层保障 5 层降级方案确保总能显示有意义的名称 ### 2. 自动同步 首次访问时自动同步企微用户信息到 Profile ### 3. 性能优化 - 优先使用已存储的数据 - 只在必要时调用 API - 避免重复查询 ### 4. 友好降级 即使没有真实姓名,也显示 `设计师-xxxxx`,而不是"未知用户" --- ## 🚀 后续优化建议 ### 短期(本周) 1. **手动输入姓名** - 首次登录时弹出模态框 - 让用户输入真实姓名 - 保存到 Profile 表 2. **从项目记录反推** - 查询用户创建或参与的项目 - 从项目中提取创建者姓名 ### 中期(本月) 1. **企微权限申请** - 向企微管理员申请用户信息读取权限 - 配置企微应用权限 2. **统一用户信息管理** - 创建专门的用户信息同步服务 - 定期更新用户信息 ### 长期(季度) 1. **完善用户档案系统** - 支持用户自主编辑个人信息 - 头像上传功能 - 个性化设置 --- ## 📝 注意事项 ### 1. 不要清除 localStorage 会导致企微认证失效,只需刷新页面即可 ### 2. 查看完整日志 所有以 📋、✅、⚠️、❌ 开头的日志都很重要 ### 3. userid 生成的名称是临时的 一旦获取到真实姓名,会自动更新 ### 4. 头像默认使用 UI Avatars 如果无法获取真实头像,会显示带名称首字母的彩色头像 --- ## 🎉 总结 通过多层降级方案,我们确保了: ✅ **永远不会显示空白或错误** ✅ **优先使用真实姓名** ✅ **降级方案友好可读** ✅ **自动同步用户信息** ✅ **性能优化,减少 API 调用** --- 现在请刷新页面,查看效果!🚀 **最差情况下会显示**:`设计师-woAs2q [组员]` **最佳情况下会显示**:`王刚 [组员]`