WxworkAuthGuard
是一个用于企业微信页面的路由守卫,提供以下核心功能:
_User
账号user
字段到 Profile/UserSocial守卫会自动为通过企微认证的用户创建 Parse _User
账号:
userid
(企业员工)或 external_userid
(外部用户)user
字段到 Profile/UserSocial守卫中的自动登录逻辑位于:
fmode-ng/src/lib/social/wxwork/wxwork-auth.guard.ts
autoLogin()
函数import { WxworkAuthGuard } from 'fmode-ng';
export const routes: Routes = [
{
path: ":cid/auth/user-confirm",
canActivate: [WxworkAuthGuard],
loadComponent: () => import("./page-user-confirm.component")
.then((m) => m.PageUserConfirmComponent)
}
];
守卫会自动从路由中提取以下参数:
支持的参数来源:
route.paramMap.get("cid")
- 路径参数route.queryParamMap.get("cid")
- 查询参数// 带 cid 和 appId 的路由
{
path: ":cid/auth/:appId/user-confirm",
canActivate: [WxworkAuthGuard],
loadComponent: () => ...
}
// 仅带 cid 的路由(appId 默认为 "crm")
{
path: ":cid/auth/user-confirm",
canActivate: [WxworkAuthGuard],
loadComponent: () => ...
}
// 查询参数方式
// 访问: /some-page?cid=E4KpGvTEto
{
path: "some-page",
canActivate: [WxworkAuthGuard],
loadComponent: () => ...
}
import { WxworkSDK } from 'fmode-ng/core';
// 在组件中初始化
this.wxwork = new WxworkSDK({
cid: this.cid, // 公司帐套ID
appId: this.appId // 应用ID,默认 "crm"
});
最简单的方式获取当前用户信息
// 获取当前用户的 Profile 或 UserSocial
const currentUser = await this.wxwork.getCurrentUser();
if (currentUser) {
console.log("用户类型:", currentUser.className); // "Profile" 或 "UserSocial"
console.log("用户ID:", currentUser.id);
console.log("用户名:", currentUser.get("name"));
console.log("手机号:", currentUser.get("mobile"));
// Profile 特有字段
if (currentUser.className === "Profile") {
console.log("员工ID:", currentUser.get("userid"));
console.log("部门:", currentUser.get("department"));
console.log("职位:", currentUser.get("position"));
}
// UserSocial 特有字段
if (currentUser.className === "UserSocial") {
console.log("外部用户ID:", currentUser.get("data").external_userid);
console.log("外部用户类型:", currentUser.get("type"));
}
}
// 从 localStorage 获取 USERINFO
const userInfo = await this.wxwork.getUserinfo();
console.log(userInfo.userid); // 企业员工ID
console.log(userInfo.external_userid); // 外部用户ID
console.log(userInfo.mobile); // 手机号
console.log(userInfo.name); // 姓名
console.log(userInfo.avatar); // 头像
存储位置: localStorage[${cid}/USERINFO]
const userInfo = await this.wxwork.getUserinfo();
const profileOrSocial = await this.wxwork.getContactOrProfile(userInfo);
console.log(profileOrSocial.className); // "Profile" 或 "UserSocial"
console.log(profileOrSocial.id);
由于守卫自动登录,任何挂载守卫的页面都可以直接使用:
import { FmodeParse } from 'fmode-ng/parse';
const Parse = FmodeParse.with("nova");
// 获取当前登录的 _User
const currentUser = Parse.User.current();
if (currentUser) {
console.log("用户名:", currentUser.get("username")); // userid 或 external_userid
console.log("手机号:", currentUser.get("mobilePhoneNumber"));
console.log("邮箱:", currentUser.get("email"));
// 获取关联的 Profile/UserSocial
const wxwork = new WxworkSDK({ cid: this.cid, appId: "crm" });
const profileOrSocial = await wxwork.getCurrentUser();
console.log("关联用户:", profileOrSocial.get("name"));
}
export class MyPageComponent implements OnInit {
cid: string = '';
appId: string = '';
wxwork: WxworkSDK;
currentUser: FmodeObject | null = null;
constructor(private route: ActivatedRoute) {}
async ngOnInit() {
this.route.paramMap.subscribe(async params => {
this.cid = params.get('cid') || '';
this.appId = params.get('appId') || 'crm';
// ⭐ 最简单的方式:直接获取当前用户
this.wxwork = new WxworkSDK({ cid: this.cid, appId: this.appId });
this.currentUser = await this.wxwork.getCurrentUser();
if (this.currentUser) {
console.log("用户类型:", this.currentUser.className);
console.log("用户姓名:", this.currentUser.get("name"));
// 直接使用用户信息
this.loadUserData();
}
});
}
async loadUserData() {
// 使用 this.currentUser 进行业务逻辑
if (this.currentUser.className === "Profile") {
// 企业员工逻辑
} else {
// 外部用户逻辑
}
}
}
// ❌ 不推荐:手动查询(代码冗长)
async loadUserInfo() {
const userInfo = await this.wxwork.getUserinfo();
if (userInfo.userid) {
const query = new Parse.Query('Profile');
query.equalTo('userid', userInfo.userid);
const profile = await query.first();
// ... 处理 Profile
} else if (userInfo.external_userid) {
const query = new Parse.Query('UserSocial');
query.equalTo('data.external_userid', userInfo.external_userid);
const userSocial = await query.first();
// ... 处理 UserSocial
}
}
// ✅ 推荐:使用 getCurrentUser()(简洁高效)
async loadUserInfo() {
const currentUser = await this.wxwork.getCurrentUser();
// 直接使用 currentUser,无需判断类型
}
字段 | 类型 | 说明 |
---|---|---|
userid | String | 企业员工微信ID |
company | Pointer | 所属企业 |
user | Pointer<_User> | 关联的 Parse 用户 |
name | String | 姓名 |
avatar | String | 头像URL |
mobile | String | 手机号 |
String | 邮箱 | |
department | String | 部门 |
position | String | 职位 |
corp_name | String | 企业名称 |
isVerified | Boolean | 身份确认状态 |
字段 | 类型 | 说明 |
---|---|---|
data.external_userid | String | 外部用户微信ID |
company | Pointer | 所属企业 |
user | Pointer<_User> | 关联的 Parse 用户 |
name | String | 姓名 |
avatar | String | 头像URL |
mobile | String | 手机号 |
type | String | 外部用户类型 |
corp_name | String | 企业名称 |
isVerified | Boolean | 身份确认状态 |
字段 | 类型 | 说明 |
---|---|---|
username | String | userid 或 external_userid |
password | String | userid/external_userid 后6位 |
mobilePhoneNumber | String | 手机号(同步自企微) |
String | 邮箱(同步自企微) |
用户访问页面
↓
检测到微信环境
↓
OAuth 跳转授权
↓
回调获取 code
↓
调用 getUserinfo(code)
↓
同步用户信息到 Profile/UserSocial
↓
自动登录/注册 _User
↓
同步 user 指针
↓
进入页面
用户访问页面
↓
弹出企微扫码登录
↓
扫码成功获取 code
↓
调用 getUserinfo(code)
↓
同步用户信息到 Profile/UserSocial
↓
自动登录/注册 _User
↓
同步 user 指针
↓
进入页面
用户访问页面
↓
从 localStorage 读取 USERINFO
↓
验证用户信息有效
↓
同步用户信息到 Profile/UserSocial
↓
自动登录(如未登录)
↓
同步 user 指针
↓
直接进入页面(无需重新授权)
async showUserInfo() {
const currentUser = await this.wxwork.getCurrentUser();
if (currentUser) {
const name = currentUser.get("name");
const avatar = currentUser.get("avatar");
const mobile = currentUser.get("mobile");
console.log(`用户: ${name}, 手机: ${mobile}`);
}
}
async checkUserType() {
const currentUser = await this.wxwork.getCurrentUser();
if (currentUser.className === "Profile") {
console.log("这是企业员工");
const userid = currentUser.get("userid");
// 执行员工相关逻辑
} else if (currentUser.className === "UserSocial") {
console.log("这是外部用户");
const externalUserId = currentUser.get("data").external_userid;
// 执行外部用户相关逻辑
}
}
async accessParseUser() {
// 方式1:通过 Parse.User.current()
const parseUser = Parse.User.current();
console.log("Parse 用户名:", parseUser.get("username"));
// 方式2:通过 Profile/UserSocial 的 user 指针
const currentUser = await this.wxwork.getCurrentUser();
const userPointer = currentUser.get("user");
if (userPointer) {
const user = await new Parse.Query("_User").get(userPointer.id);
console.log("关联的 Parse 用户:", user.get("username"));
}
}
async updateUserInfo() {
const currentUser = await this.wxwork.getCurrentUser();
if (currentUser) {
currentUser.set("name", "新名字");
currentUser.set("mobile", "13800138000");
await currentUser.save();
console.log("用户信息更新成功");
}
}
async checkVerified() {
const currentUser = await this.wxwork.getCurrentUser();
if (currentUser.get("isVerified")) {
console.log("用户已确认身份");
// 允许访问完整功能
} else {
console.log("用户未确认身份");
// 跳转到身份确认页面
this.router.navigate([`/auth/${this.cid}/user-confirm`]);
}
}
// ✅ 正确:路径中包含 cid
{ path: ":cid/my-page", canActivate: [WxworkAuthGuard], ... }
// ✅ 正确:查询参数中包含 cid
// 访问: /my-page?cid=E4KpGvTEto
{ path: "my-page", canActivate: [WxworkAuthGuard], ... }
// ❌ 错误:缺少 cid 参数
{ path: "my-page", canActivate: [WxworkAuthGuard], ... }
// ✅ 正确
this.wxwork = new WxworkSDK({ cid: this.cid, appId: this.appId });
// ❌ 错误:缺少 cid
this.wxwork = new WxworkSDK({ appId: this.appId });
// getCurrentUser() 会读取守卫写入的 localStorage
// 必须在守卫执行后调用
async ngOnInit() {
// 守卫已执行,localStorage 中有 USERINFO
const currentUser = await this.wxwork.getCurrentUser();
}
// 只有在守卫执行后,Parse.User.current() 才会有值
const currentUser = Parse.User.current();
if (currentUser) {
// 用户已自动登录
} else {
// 用户未登录(不应该出现在守卫保护的页面)
}
守卫会自动同步 user
字段,但如果需要手动同步:
async syncUserPointer() {
const parseUser = Parse.User.current();
const currentUser = await this.wxwork.getCurrentUser();
if (parseUser && currentUser && !currentUser.get("user")) {
currentUser.set("user", parseUser.toPointer());
await currentUser.save();
}
}
const userInfoStr = localStorage.getItem(`${this.cid}/USERINFO`);
const userInfo = JSON.parse(userInfoStr);
console.log("缓存的用户信息:", userInfo);
const currentUser = Parse.User.current();
console.log("Parse User:", currentUser?.toJSON());
const currentUser = await this.wxwork.getCurrentUser();
console.log("Profile/UserSocial:", currentUser?.toJSON());
// 清除用户信息缓存
localStorage.removeItem(`${this.cid}/USERINFO`);
// 退出登录
await Parse.User.logOut();
// 刷新页面重新授权
location.reload();
ZhangSan123456
→ 密码: 123456
wmABCDEF123456
→ 密码: 123456
autoLogin()
函数的密码生成逻辑使用 WxworkAuthGuard
和 WxworkSDK.getCurrentUser()
可以极大简化企微页面开发:
✅ 一行代码获取用户 - await this.wxwork.getCurrentUser()
✅ 自动登录 - 无需手动处理 Parse 用户登录
✅ 统一接口 - Profile 和 UserSocial 统一处理
✅ 用户指针同步 - 自动关联 Parse _User
✅ Parse.User.current() 可用 - 方便其他模块使用
开发企微功能页面时,只需配置守卫,然后使用 getCurrentUser()
即可快速开始业务逻辑开发!