为身份激活页面添加可编辑表单功能,在保留企微自动获取信息的基础上,允许用户修改和完善个人信息,实现"自动获取 + 可编辑"的最佳用户体验。
2025年11月3日
| 字段名 | 类型 | 必填 | 说明 |
|---|---|---|---|
| 真实姓名 | 文本输入 | ✅ | 从企微获取,可修改 |
| 所属部门 | 下拉选择 | ✅ | 7个预设部门可选 |
| 职位角色 | 下拉选择 | ✅ | 4个角色级别可选 |
| 手机号 | 电话输入 | ❌ | 从企微获取,可修改 |
| 员工ID | 只读显示 | - | 企微userid,不可编辑 |
profile-activation.component.tsimport { FormsModule } from '@angular/forms';
表单数据模型(第52-58行):
formData = {
realname: '',
department: '',
roleName: '组员',
mobile: ''
};
部门列表(第60-69行):
departmentList = [
'设计部',
'建模部',
'渲染部',
'软装部',
'后期部',
'综合部',
'管理部'
];
角色列表(第71-77行):
roleList = [
'组员',
'组长',
'主管',
'经理'
];
populateFormData()(第160-189行):
智能处理部门信息的多种格式(数组、对象、字符串)
private populateFormData(): void {
// 优先从Profile获取,其次从企微userInfo获取
this.formData.realname = this.profile?.get('realname') ||
this.profile?.get('name') ||
this.userInfo?.name || '';
this.formData.mobile = this.profile?.get('mobile') ||
this.userInfo?.mobile || '';
this.formData.roleName = this.profile?.get('roleName') || '组员';
// 处理部门信息(支持多种格式)
// ... 详细逻辑见代码
}
initAuth()(第122、138行):
populateFormData()confirmActivation()(第234-248行):
confirmActivation()(第257-271行):
name 和 realname 字段同时更新 department 和 departmentName 字段
// 保存用户编辑的信息
this.profile.set('realname', this.formData.realname);
this.profile.set('name', this.formData.realname);
this.profile.set('department', this.formData.department);
this.profile.set('departmentName', this.formData.department);
this.profile.set('roleName', this.formData.roleName);
this.profile.set('mobile', this.formData.mobile);
profile-activation.component.html替换原来的只读信息列表为可编辑表单:
<div class="form-container">
<!-- 真实姓名 -->
<div class="form-group">
<label class="form-label">
<span class="label-text">真实姓名</span>
<span class="required">*</span>
</label>
<input
type="text"
class="form-input"
[(ngModel)]="formData.realname"
placeholder="请输入您的真实姓名"
required />
</div>
<!-- 所属部门 -->
<div class="form-group">
<label class="form-label">
<span class="label-text">所属部门</span>
<span class="required">*</span>
</label>
<select
class="form-select"
[(ngModel)]="formData.department"
required>
<option value="">请选择部门</option>
@for (dept of departmentList; track dept) {
<option [value]="dept">{{ dept }}</option>
}
</select>
</div>
<!-- 职位角色 -->
<div class="form-group">
<label class="form-label">
<span class="label-text">职位角色</span>
<span class="required">*</span>
</label>
<select
class="form-select"
[(ngModel)]="formData.roleName"
required>
@for (role of roleList; track role) {
<option [value]="role">{{ role }}</option>
}
</select>
</div>
<!-- 手机号 -->
<div class="form-group">
<label class="form-label">
<span class="label-text">手机号</span>
</label>
<input
type="tel"
class="form-input"
[(ngModel)]="formData.mobile"
placeholder="请输入手机号" />
</div>
<!-- 员工ID(只读) -->
<div class="form-group readonly">
<label class="form-label">
<span class="label-text">员工ID</span>
</label>
<div class="readonly-value">{{ getUserId() }}</div>
</div>
</div>
用户名显示(第41行):
<h2 class="user-name">{{ formData.realname || '请填写姓名' }}</h2>
角色显示(第42行):
<p class="user-role">{{ formData.roleName }}</p>
profile-activation.component.scss表单容器:
.form-container {
padding: 24px 0;
.form-group {
margin-bottom: 20px;
}
}
表单标签:
.form-label {
display: flex;
align-items: center;
margin-bottom: 8px;
font-size: 14px;
font-weight: 500;
color: #333;
.required {
color: #f56c6c; // 红色必填标记
margin-left: 4px;
}
}
输入框和下拉框:
.form-input,
.form-select {
width: 100%;
padding: 12px 16px;
border: 1px solid #e0e0e0;
border-radius: 8px;
transition: all 0.3s ease;
&:focus {
border-color: #667eea;
box-shadow: 0 0 0 3px rgba(102, 126, 234, 0.1);
}
}
下拉框箭头图标:
.form-select {
appearance: none;
background-image: url("data:image/svg+xml,.."); // SVG箭头
background-repeat: no-repeat;
background-position: right 12px center;
padding-right: 36px;
cursor: pointer;
}
只读字段:
&.readonly {
.readonly-value {
padding: 12px 16px;
background: #f5f5f5;
border-radius: 8px;
color: #666;
}
}
@media (max-width: 640px) {
.form-container {
.form-input,
.form-select {
font-size: 16px; // 防止iOS自动缩放
}
}
}
用户访问页面
↓
initAuth() - 初始化企微认证
↓
获取企微用户信息 (userInfo)
↓
checkActivationStatus() - 检查Profile
↓
populateFormData() - 自动填充表单
↓
显示可编辑表单
用户编辑表单
↓
点击"确认身份"按钮
↓
表单验证(必填字段)
↓
confirmActivation()
↓
创建/更新 Profile 记录
↓
保存 formData 到 Profile
↓
设置 isActivated = true
↓
跳转到激活成功页面
当前支持的部门:
如需修改部门列表:编辑 profile-activation.component.ts 第60-69行的 departmentList 数组。
当前支持的角色:
如需修改角色列表:编辑 profile-activation.component.ts 第71-77行的 roleList 数组。
验证失败时弹出 alert 提示用户:
* 标记/wxwork/test/activation)| 表单字段 | Profile字段1 | Profile字段2 | 说明 |
|---|---|---|---|
| realname | realname |
name |
真实姓名,同时更新两个字段 |
| department | department |
departmentName |
部门,同时更新两个字段 |
| roleName | roleName |
- | 角色/职位 |
| mobile | mobile |
- | 手机号 |
async loadDepartments() {
const Parse = FmodeParse.with('nova');
const query = new Parse.Query('Department');
const departments = await query.find();
this.departmentList = departments.map(d => d.get('name'));
}
validateMobile(mobile: string): boolean {
return /^1[3-9]\d{9}$/.test(mobile);
}
<div class="form-group">
<label>头像</label>
<input type="file" accept="image/*" (change)="onAvatarChange($event)" />
</div>
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
this.activationForm = this.fb.group({
realname: ['', Validators.required],
department: ['', Validators.required],
roleName: ['组员', Validators.required],
mobile: ['', Validators.pattern(/^1[3-9]\d{9}$/)]
});
<button class="btn-reset" (click)="resetForm()">
重置为企微信息
</button>
使用 [(ngModel)] 实现表单和数据的双向同步:
<input [(ngModel)]="formData.realname" />
处理企微部门信息的多种数据格式:
// 支持数组、对象、字符串三种格式
if (Array.isArray(userDept)) { ... }
else if (typeof userDept === 'object') { ... }
else if (typeof userDept === 'string') { ... }
使用 SVG data URI 实现自定义下拉箭头:
background-image: url("data:image/svg+xml,...");
CSS实现输入框聚焦时的视觉反馈:
&:focus {
border-color: #667eea;
box-shadow: 0 0 0 3px rgba(102, 126, 234, 0.1);
}
此功能完美结合了自动化和灵活性:
通过这次更新,身份激活流程更加人性化和专业化,为整个系统的用户体验奠定了良好基础。