# 员工激活状态诊断指南 ## 问题描述 员工ID: `woAs2qCQAAGQckyg7AQBxhMEoSwnlTvg` 已经激活身份,但访问项目管理时显示"企业微信认证失败"。 ## 诊断步骤 ### 1. 检查Profile记录 在Parse Dashboard中执行以下查询: ```javascript // 查询Profile表 const query = new Parse.Query('Profile'); query.equalTo('userid', 'woAs2qCQAAGQckyg7AQBxhMEoSwnlTvg'); const profile = await query.first({ useMasterKey: true }); if (profile) { console.log('Profile记录:', { objectId: profile.id, userid: profile.get('userid'), name: profile.get('name'), realname: profile.get('realname'), isActivated: profile.get('isActivated'), activatedAt: profile.get('activatedAt'), isDeleted: profile.get('isDeleted'), isDisabled: profile.get('isDisabled'), roleName: profile.get('roleName'), departmentName: profile.get('departmentName'), createdAt: profile.get('createdAt'), updatedAt: profile.get('updatedAt') }); } else { console.log('❌ 未找到Profile记录'); } ``` ### 2. 检查isActivated字段类型 ```javascript const isActivated = profile.get('isActivated'); console.log('isActivated值:', isActivated); console.log('isActivated类型:', typeof isActivated); console.log('isActivated === true:', isActivated === true); console.log('isActivated == true:', isActivated == true); console.log('!!isActivated:', !!isActivated); ``` ### 3. 常见问题 #### 问题1: isActivated字段不存在 **症状**: `profile.get('isActivated')` 返回 `undefined` **解决方案**: ```javascript profile.set('isActivated', true); profile.set('activatedAt', new Date()); await profile.save(null, { useMasterKey: true }); ``` #### 问题2: isActivated为false **症状**: `profile.get('isActivated')` 返回 `false` **解决方案**: ```javascript profile.set('isActivated', true); profile.set('activatedAt', new Date()); await profile.save(null, { useMasterKey: true }); ``` #### 问题3: isActivated为字符串"true" **症状**: `profile.get('isActivated')` 返回 `"true"` (字符串) **解决方案**: ```javascript profile.set('isActivated', true); // 转换为布尔值 await profile.save(null, { useMasterKey: true }); ``` #### 问题4: isDeleted或isDisabled为true **症状**: 员工被标记为删除或禁用 **解决方案**: ```javascript profile.unset('isDeleted'); profile.unset('isDisabled'); await profile.save(null, { useMasterKey: true }); ``` ### 4. 批量修复脚本 如果有多个员工遇到同样问题,使用以下脚本批量修复: ```javascript const Parse = require('parse/node'); Parse.initialize('your-app-id', 'your-js-key', 'your-master-key'); Parse.serverURL = 'https://your-server-url/parse'; async function fixActivationStatus() { const query = new Parse.Query('Profile'); // 查询所有未激活的员工 query.notEqualTo('isActivated', true); query.notEqualTo('isDeleted', true); query.notEqualTo('isDisabled', true); query.limit(1000); const profiles = await query.find({ useMasterKey: true }); console.log(`找到 ${profiles.length} 个未激活的员工`); for (const profile of profiles) { const userid = profile.get('userid'); const name = profile.get('name') || profile.get('realname'); console.log(`修复员工: ${name} (${userid})`); profile.set('isActivated', true); if (!profile.get('activatedAt')) { profile.set('activatedAt', new Date()); } await profile.save(null, { useMasterKey: true }); } console.log('✅ 批量修复完成'); } fixActivationStatus(); ``` ### 5. 前端调试 在浏览器控制台查看详细日志: ``` 🔐 CustomWxworkAuthGuard 执行,当前路由: /wxwork/xxx/project/xxx ✅ 获取用户信息成功: { name: "xxx", userid: "woAs2qCQAAGQckyg7AQBxhMEoSwnlTvg" } 🔎 currentProfile 查询结果: { isActivated: false } 🔎 回退 Profile 查询结果: { isActivated: false } ❌ Profile存在但未激活 ⚠️ 用户未激活,跳转到激活页面 ``` ### 6. 验证修复 修复后,让员工重新登录: 1. 清除浏览器缓存 2. 退出企业微信应用 3. 重新进入应用 4. 检查是否能正常访问项目管理页面 ### 7. 预防措施 #### 7.1 激活页面自动设置isActivated 确保 `profile-activation.component.ts` 中的 `confirmActivation()` 方法正确设置: ```typescript profile.set('isActivated', true); profile.set('activatedAt', new Date()); await profile.save(); ``` #### 7.2 数据同步时自动激活 在企微数据同步时,自动设置 `isActivated=true`: ```typescript // wxwork-auth.ts 或数据同步脚本 if (profile && !profile.get('isActivated')) { profile.set('isActivated', true); profile.set('activatedAt', new Date()); await profile.save(); } ``` #### 7.3 定期检查 使用管理工具定期扫描未激活员工: 访问: `/admin/employee-activation-fix` ## 针对当前问题的快速修复 ### 方法1: Parse Dashboard手动修复 1. 登录Parse Dashboard 2. 进入Profile表 3. 搜索 `userid = woAs2qCQAAGQckyg7AQBxhMEoSwnlTvg` 4. 编辑记录,设置: - `isActivated` = `true` (Boolean类型) - `activatedAt` = 当前时间 5. 保存 6. 让员工重新登录 ### 方法2: 使用修复工具 1. 访问: `https://app.fmode.cn/dev/yss/admin/employee-activation-fix` 2. 点击"扫描所有员工" 3. 找到该员工,点击"修复" 4. 让员工重新登录 ### 方法3: 云函数修复 ```javascript Parse.Cloud.define('fixEmployeeActivation', async (request) => { const { userid } = request.params; const query = new Parse.Query('Profile'); query.equalTo('userid', userid); const profile = await query.first({ useMasterKey: true }); if (!profile) { throw new Error('未找到员工记录'); } profile.set('isActivated', true); profile.set('activatedAt', new Date()); await profile.save(null, { useMasterKey: true }); return { success: true, message: '激活状态已修复', profile: { id: profile.id, name: profile.get('name'), isActivated: profile.get('isActivated') } }; }, { requireMaster: true }); ``` 调用: ```javascript Parse.Cloud.run('fixEmployeeActivation', { userid: 'woAs2qCQAAGQckyg7AQBxhMEoSwnlTvg' }, { useMasterKey: true }); ``` ## 根本原因分析 ### 可能原因1: 激活流程未完成 员工点击了"确认身份"按钮,但: - 网络中断导致保存失败 - 前端代码执行异常 - 后端保存时出错 ### 可能原因2: 数据同步覆盖 企微数据同步时,覆盖了 `isActivated` 字段: - 同步脚本未保留 `isActivated` 字段 - 同步时使用了错误的数据源 ### 可能原因3: 字段类型错误 `isActivated` 被设置为字符串而不是布尔值: - `"true"` (字符串) vs `true` (布尔值) - JavaScript的 `if (profile.get('isActivated'))` 会通过 - 但 `profile.get('isActivated') === true` 会失败 ### 可能原因4: 缓存问题 前端或Parse缓存了旧数据: - `currentProfile()` 返回缓存的未激活状态 - 需要强制从服务器获取最新数据 ## 长期解决方案 ### 1. 增强激活页面错误处理 ```typescript async confirmActivation() { try { // ... 激活逻辑 profile.set('isActivated', true); profile.set('activatedAt', new Date()); await profile.save(); // 验证保存成功 await profile.fetch(); if (profile.get('isActivated') !== true) { throw new Error('激活状态保存失败'); } console.log('✅ 激活成功并验证'); } catch (error) { console.error('❌ 激活失败:', error); alert('激活失败,请重试或联系管理员'); } } ``` ### 2. 守卫增强日志 已在 `CustomWxworkAuthGuard` 中添加详细日志(第120-177行) ### 3. 定期数据审计 每周运行脚本,检查异常状态的员工: - `isActivated` 为 `undefined` - `isActivated` 为字符串 - `isActivated` 为 `false` 但 `activatedAt` 存在 ### 4. 监控告警 设置告警规则: - 激活失败率超过5% - 单个员工激活失败超过3次 - 企微认证失败率异常 ## 联系支持 如果以上方法都无法解决问题,请联系技术支持,并提供: 1. 员工userid 2. 浏览器控制台完整日志 3. Parse Dashboard中的Profile记录截图 4. 问题发生的时间和频率