本方案实现了自定义企微身份激活页面,整合了员工问卷功能,用户体验流畅。
fmode-ng 默认的身份确认界面src/
├── modules/profile/pages/profile-activation/
│ ├── profile-activation.component.ts # 激活组件逻辑
│ ├── profile-activation.component.html # 激活页面模板
│ └── profile-activation.component.scss # 激活页面样式
├── app/
│ ├── app.routes.ts # 路由配置(新增激活路由)
│ └── custom-wxwork-auth-guard.ts # 自定义认证守卫
1. 用户首次访问企微应用
↓
2. CustomWxworkAuthGuard 检测未激活
↓
3. 重定向到 /wxwork/:cid/activation
↓
4. ProfileActivationComponent 显示身份确认界面
- 显示用户信息
- [确认身份] 按钮
↓
5. 用户点击确认
↓
6. 激活成功,显示问卷引导
- [开始填写问卷] 按钮
- [稍后填写,先进入工作台] 按钮
↓
7a. 用户点击"开始填写问卷"
↓
跳转到 /wxwork/:cid/survey/profile
↓
完成问卷
↓
返回激活页面,点击"刷新状态"
↓
显示"查看问卷结果"按钮
↓
查看完整答案
↓
[进入工作台]
7b. 用户点击"稍后填写"
↓
直接进入工作台
Profile {
userid: String, // 企微用户ID
name: String, // 姓名
realname: String, // 真实姓名
avatar: String, // 头像
roleName: String, // 角色(组员/组长/管理员)
// 新增字段
isActivated: Boolean, // 是否已激活
activatedAt: Date, // 激活时间
surveyCompleted: Boolean, // 问卷是否完成
surveyCompletedAt: Date, // 问卷完成时间
surveyLogId: String // SurveyLog ID
}
SurveyLog {
type: 'survey-profile', // 问卷类型
profile: Pointer, // 关联的 Profile
answers: Array<{ // 问卷答案
questionId: String,
question: String,
type: String, // 'single' | 'multiple' | 'scale' | 'text'
answer: Any
}>,
completedAt: Date // 完成时间
}
#667eea → #764ba2#66bb6a#ffa726访问: https://your-domain.com/wxwork/[公司ID]/designer/dashboard
(任意受保护的路由)
流程:
1. 自动重定向到 /wxwork/[公司ID]/activation
2. 显示身份确认界面
3. 点击"确认身份"
4. 显示问卷按钮
# 启动开发服务器
npm run dev
# 访问测试URL(模拟企微环境)
http://localhost:4200/wxwork/test/activation
// 在浏览器控制台执行,模拟问卷完成
// 1. 获取当前 Profile
const Parse = FmodeParse.with('nova');
const query = new Parse.Query('Profile');
query.equalTo('userid', 'test_user_id');
const profile = await query.first();
// 2. 标记问卷已完成
profile.set('surveyCompleted', true);
profile.set('surveyCompletedAt', new Date());
await profile.save();
// 3. 刷新页面,点击"刷新状态"
1. 在激活页面点击"已完成?刷新状态"
2. 自动检测到问卷已完成
3. 显示"查看问卷结果"按钮
4. 点击查看完整答案
// src/app/app.routes.ts
// 1. 激活页面路由(不受守卫保护)
{
path: 'wxwork/:cid/activation',
loadComponent: () => import('...ProfileActivationComponent'),
title: '身份激活'
}
// 2. 受保护的路由(需要激活)
{
path: 'wxwork/:cid',
canActivate: [CustomWxworkAuthGuard],
children: [...]
}
// src/app/custom-wxwork-auth-guard.ts
export const CustomWxworkAuthGuard: CanActivateFn = async (route, state) => {
// 1. 获取用户信息
const userInfo = await wxAuth.getUserInfo();
// 2. 检查激活状态
const profile = await wxAuth.currentProfile();
// 3. 未激活 → 跳转到激活页面
if (!profile?.get('isActivated')) {
router.navigate(['/wxwork', cid, 'activation']);
return false;
}
// 4. 已激活 → 允许访问
return true;
};
原因: Profile 的 isActivated 字段未设置
解决:
// 在 ProfileActivationComponent.confirmActivation() 中
profile.set('isActivated', true);
profile.set('activatedAt', new Date());
await profile.save();
原因: SurveyLog 查询条件不匹配
检查:
// 确保 SurveyLog 有正确的字段
const query = new Parse.Query('SurveyLog');
query.equalTo('type', 'survey-profile');
query.equalTo('profile', profile.toPointer());
const surveyLog = await query.first();
方法: 手动设置 Profile 为已激活
const profile = await wxAuth.currentProfile();
profile.set('isActivated', true);
await profile.save();
const Parse = FmodeParse.with('nova');
const query = new Parse.Query('Profile');
query.equalTo('isActivated', true);
const profiles = await query.find();
console.log('已激活用户数:', profiles.length);
const totalQuery = new Parse.Query('Profile');
const total = await totalQuery.count();
const completedQuery = new Parse.Query('Profile');
completedQuery.equalTo('surveyCompleted', true);
const completed = await completedQuery.count();
console.log(`问卷完成率: ${(completed / total * 100).toFixed(2)}%`);
在企业微信管理后台 → 应用管理 → 自建应用 → 网页:
应用主页:
https://your-domain.com/wxwork/[公司ID]/designer/dashboard
说明:
- 首次访问会自动跳转到激活页面
- 激活后直接进入工作台
可信域名:
your-domain.com
说明:
- 用于企微OAuth授权
- 必须与应用主页域名一致
✅ 实现的功能:
✅ 技术亮点:
✅ 用户体验: