employee-activation-debug.md 8.1 KB

员工激活状态诊断指南

问题描述

员工ID: woAs2qCQAAGQckyg7AQBxhMEoSwnlTvg 已经激活身份,但访问项目管理时显示"企业微信认证失败"。

诊断步骤

1. 检查Profile记录

在Parse Dashboard中执行以下查询:

// 查询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字段类型

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

解决方案:

profile.set('isActivated', true);
profile.set('activatedAt', new Date());
await profile.save(null, { useMasterKey: true });

问题2: isActivated为false

症状: profile.get('isActivated') 返回 false

解决方案:

profile.set('isActivated', true);
profile.set('activatedAt', new Date());
await profile.save(null, { useMasterKey: true });

问题3: isActivated为字符串"true"

症状: profile.get('isActivated') 返回 "true" (字符串)

解决方案:

profile.set('isActivated', true); // 转换为布尔值
await profile.save(null, { useMasterKey: true });

问题4: isDeleted或isDisabled为true

症状: 员工被标记为删除或禁用

解决方案:

profile.unset('isDeleted');
profile.unset('isDisabled');
await profile.save(null, { useMasterKey: true });

4. 批量修复脚本

如果有多个员工遇到同样问题,使用以下脚本批量修复:

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() 方法正确设置:

profile.set('isActivated', true);
profile.set('activatedAt', new Date());
await profile.save();

7.2 数据同步时自动激活

在企微数据同步时,自动设置 isActivated=true

// 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: 云函数修复

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
});

调用:

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. 增强激活页面错误处理

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. 定期数据审计

每周运行脚本,检查异常状态的员工:

  • isActivatedundefined
  • isActivated 为字符串
  • isActivatedfalseactivatedAt 存在

4. 监控告警

设置告警规则:

  • 激活失败率超过5%
  • 单个员工激活失败超过3次
  • 企微认证失败率异常

联系支持

如果以上方法都无法解决问题,请联系技术支持,并提供:

  1. 员工userid
  2. 浏览器控制台完整日志
  3. Parse Dashboard中的Profile记录截图
  4. 问题发生的时间和频率