| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533 |
- import { Component, OnInit } from '@angular/core';
- import { CommonModule } from '@angular/common';
- import { Router, ActivatedRoute } from '@angular/router';
- import { WxworkAuth } from 'fmode-ng/core';
- /**
- * 企业微信身份激活测试组件
- * 用于调试身份激活 + 问卷整合流程
- */
- @Component({
- selector: 'app-wxwork-activation-test',
- standalone: true,
- imports: [CommonModule],
- host: {
- 'class': 'full-page-component'
- },
- template: `
- <div class="test-wrapper">
- <div class="test-container">
- <h1>🧪 企业微信身份激活测试</h1>
-
- <div class="test-section">
- <h2>测试步骤:</h2>
- <ol>
- <li [class.active]="currentStep >= 1">初始化企微认证</li>
- <li [class.active]="currentStep >= 2">执行身份激活</li>
- <li [class.active]="currentStep >= 3">检查问卷状态</li>
- <li [class.active]="currentStep >= 4">跳转到相应页面</li>
- </ol>
- </div>
- <div class="test-section" *ngIf="logs.length > 0">
- <h2>执行日志:</h2>
- <div class="log-container">
- <div *ngFor="let log of logs" [class]="'log-' + log.type">
- <span class="log-time">{{ log.time }}</span>
- <span class="log-message">{{ log.message }}</span>
- </div>
- </div>
- </div>
- <div class="test-section" *ngIf="profileInfo">
- <h2>员工信息:</h2>
- <table>
- <tr>
- <td>员工ID:</td>
- <td>{{ profileInfo.id }}</td>
- </tr>
- <tr>
- <td>姓名:</td>
- <td>{{ profileInfo.realname }}</td>
- </tr>
- <tr>
- <td>角色:</td>
- <td>{{ profileInfo.roleName }}</td>
- </tr>
- <tr>
- <td>问卷状态:</td>
- <td>
- <span [class]="profileInfo.surveyCompleted ? 'status-completed' : 'status-pending'">
- {{ profileInfo.surveyCompleted ? '✅ 已完成' : '❌ 未完成' }}
- </span>
- </td>
- </tr>
- </table>
- </div>
- <div class="test-section">
- <h2>测试操作:</h2>
- <button (click)="startTest()" [disabled]="testing">
- {{ testing ? '测试中...' : '开始测试' }}
- </button>
- <button (click)="resetSurvey()" [disabled]="!profileInfo">
- 重置问卷状态
- </button>
- <button (click)="goToSurvey()" [disabled]="!profileInfo">
- 前往问卷页面
- </button>
- <button (click)="goToDashboard()" [disabled]="!profileInfo">
- 前往工作台
- </button>
- </div>
- <div class="test-section" *ngIf="error">
- <h2 style="color: red;">❌ 错误信息:</h2>
- <pre>{{ error }}</pre>
- </div>
- </div>
- </div>
- `,
- styles: [`
- /* 强制突破父容器限制 */
- :host {
- display: block;
- position: fixed !important;
- top: 0 !important;
- left: 0 !important;
- right: 0 !important;
- bottom: 0 !important;
- width: 100vw !important;
- height: 100vh !important;
- overflow-y: auto !important;
- overflow-x: hidden !important;
- z-index: 1;
- background: #f5f5f5;
- -webkit-overflow-scrolling: touch;
- }
- .test-wrapper {
- min-height: 100vh;
- width: 100%;
- overflow-y: auto;
- overflow-x: hidden;
- }
- .test-container {
- max-width: 900px;
- margin: 40px auto;
- padding: 20px 20px 60px;
- font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
- }
- h1 {
- color: #333;
- margin-bottom: 30px;
- font-size: 28px;
- }
- .test-section {
- background: white;
- border-radius: 12px;
- padding: 24px;
- margin-bottom: 20px;
- box-shadow: 0 2px 8px rgba(0,0,0,0.1);
- }
- h2 {
- color: #555;
- font-size: 18px;
- margin: 0 0 16px 0;
- }
- ol {
- margin: 0;
- padding-left: 24px;
- }
- li {
- padding: 8px 0;
- color: #999;
- transition: all 0.3s;
- }
- li.active {
- color: #007aff;
- font-weight: 500;
- }
- .log-container {
- background: #f5f5f5;
- border-radius: 8px;
- padding: 16px;
- max-height: 400px;
- height: 400px;
- overflow-y: auto;
- overflow-x: hidden;
- font-family: 'Courier New', monospace;
- font-size: 13px;
- -webkit-overflow-scrolling: touch;
- }
- .log-container > div {
- padding: 4px 0;
- display: flex;
- gap: 12px;
- }
- .log-time {
- color: #999;
- min-width: 80px;
- }
- .log-info { color: #007aff; }
- .log-success { color: #34c759; }
- .log-warning { color: #ff9500; }
- .log-error { color: #ff3b30; }
- table {
- width: 100%;
- border-collapse: collapse;
- }
- td {
- padding: 12px;
- border-bottom: 1px solid #eee;
- }
- td:first-child {
- font-weight: 500;
- color: #666;
- width: 120px;
- }
- .status-completed {
- color: #34c759;
- font-weight: 500;
- }
- .status-pending {
- color: #ff9500;
- font-weight: 500;
- }
- button {
- padding: 12px 24px;
- margin-right: 12px;
- border: none;
- border-radius: 8px;
- background: #007aff;
- color: white;
- font-size: 14px;
- font-weight: 500;
- cursor: pointer;
- transition: all 0.2s;
- }
- button:hover:not(:disabled) {
- background: #0051d5;
- transform: translateY(-1px);
- }
- button:disabled {
- background: #ccc;
- cursor: not-allowed;
- transform: none;
- }
- pre {
- background: #f5f5f5;
- padding: 16px;
- border-radius: 8px;
- overflow-x: auto;
- white-space: pre-wrap;
- word-wrap: break-word;
- }
- /* 确保移动端也能滚动 */
- @media (max-width: 768px) {
- .test-container {
- margin: 20px auto;
- padding: 16px 16px 40px;
- }
- .log-container {
- height: 300px;
- max-height: 300px;
- }
- button {
- width: 100%;
- margin-right: 0;
- margin-bottom: 8px;
- }
- }
- `]
- })
- export class WxworkActivationTestComponent implements OnInit {
- cid: string = '';
- currentStep: number = 0;
- testing: boolean = false;
- logs: Array<{ time: string; message: string; type: string }> = [];
- profileInfo: any = null;
- error: string = '';
-
- private wxAuth: WxworkAuth | null = null;
- constructor(
- private router: Router,
- private route: ActivatedRoute
- ) {}
- ngOnInit() {
- // 从URL获取cid(同步处理)
- const snapshot = this.route.snapshot;
- this.cid = snapshot.paramMap.get('cid') || 'test';
- this.addLog('获取公司ID: ' + this.cid, 'info');
-
- // 设置localStorage用于测试模式
- if (this.cid === 'test' || this.cid === 'demo') {
- localStorage.setItem('company', this.cid);
- this.addLog('🧪 测试模式已启用', 'info');
- }
- }
- /**
- * 开始测试
- */
- async startTest() {
- this.testing = true;
- this.error = '';
- this.logs = [];
- this.currentStep = 0;
- try {
- // 检查cid
- if (!this.cid) {
- throw new Error('公司ID未设置,请刷新页面重试');
- }
-
- // Step 1: 初始化企微认证(仅非测试模式)
- this.currentStep = 1;
- if (this.cid !== 'test' && this.cid !== 'demo') {
- this.addLog('初始化企微认证...', 'info');
- await this.initAuth();
- } else {
- this.addLog('🧪 测试模式,跳过企微认证初始化', 'info');
- }
-
- // Step 2: 执行身份激活
- this.currentStep = 2;
- this.addLog('执行身份激活...', 'info');
- await this.activate();
-
- // Step 3: 检查问卷状态
- this.currentStep = 3;
- this.addLog('检查问卷状态...', 'info');
- await this.checkSurvey();
-
- // Step 4: 决定跳转
- this.currentStep = 4;
- this.addLog('测试完成!', 'success');
-
- if (!this.profileInfo.surveyCompleted) {
- this.addLog('检测到问卷未完成,可以点击"前往问卷页面"按钮测试', 'warning');
- } else {
- this.addLog('问卷已完成,可以点击"前往工作台"按钮测试', 'success');
- }
-
- } catch (err: any) {
- this.error = err.message || String(err);
- this.addLog('测试失败: ' + this.error, 'error');
- } finally {
- this.testing = false;
- }
- }
- /**
- * 初始化认证
- */
- private async initAuth() {
- try {
- // 检查cid是否有效
- if (!this.cid) {
- throw new Error('公司ID(cid)未设置');
- }
-
- this.wxAuth = new WxworkAuth({ cid: this.cid, appId: 'crm' });
- this.addLog('✅ 企微认证初始化成功', 'success');
- } catch (error) {
- throw new Error('企微认证初始化失败: ' + error);
- }
- }
- /**
- * 执行激活
- */
- private async activate() {
- try {
- // 测试模式:使用模拟数据
- if (this.cid === 'test' || this.cid === 'demo') {
- this.addLog('🧪 使用测试模式,创建模拟Profile', 'warning');
- await this.createTestProfile();
- return;
- }
-
- // 真实模式:执行企微认证
- const { user, profile } = await this.wxAuth!.authenticateAndLogin();
-
- if (!profile) {
- throw new Error('未能获取Profile信息');
- }
-
- this.profileInfo = {
- id: profile.id,
- realname: profile.get('realname') || profile.get('name'),
- roleName: profile.get('roleName'),
- surveyCompleted: profile.get('surveyCompleted') || false
- };
-
- this.addLog(`✅ 身份激活成功: ${this.profileInfo.realname}`, 'success');
- this.addLog(` 角色: ${this.profileInfo.roleName}`, 'info');
-
- } catch (error) {
- throw new Error('身份激活失败: ' + error);
- }
- }
-
- /**
- * 创建测试Profile
- */
- private async createTestProfile() {
- const Parse = await import('fmode-ng/parse').then(m => m.FmodeParse.with('nova'));
-
- try {
- // 尝试查找现有的测试Profile
- const query = new Parse.Query('Profile');
- query.equalTo('name', '测试员工');
- query.limit(1);
-
- let profile = await query.first();
-
- // 如果不存在,创建新的
- if (!profile) {
- const Profile = Parse.Object.extend('Profile');
- profile = new Profile();
-
- profile.set('name', '测试员工');
- profile.set('realname', '王刚');
- profile.set('roleName', '组员');
- profile.set('surveyCompleted', false);
-
- profile = await profile.save();
- this.addLog('✅ 已创建新的测试Profile', 'success');
- } else {
- this.addLog('✅ 找到现有测试Profile', 'success');
- }
-
- // 保存Profile信息
- this.profileInfo = {
- id: profile.id,
- realname: profile.get('realname') || profile.get('name'),
- roleName: profile.get('roleName'),
- surveyCompleted: profile.get('surveyCompleted') || false
- };
-
- // 缓存Profile ID
- localStorage.setItem('Parse/ProfileId', profile.id);
-
- this.addLog(` 员工姓名: ${this.profileInfo.realname}`, 'info');
- this.addLog(` 员工角色: ${this.profileInfo.roleName}`, 'info');
-
- } catch (error) {
- throw new Error('创建测试Profile失败: ' + error);
- }
- }
- /**
- * 检查问卷状态
- */
- private async checkSurvey() {
- const Parse = await import('fmode-ng/parse').then(m => m.FmodeParse.with('nova'));
-
- try {
- const query = new Parse.Query('Profile');
- const profile = await query.get(this.profileInfo.id);
-
- const surveyCompleted = profile.get('surveyCompleted') || false;
- this.profileInfo.surveyCompleted = surveyCompleted;
-
- if (surveyCompleted) {
- this.addLog('✅ 问卷已完成', 'success');
- } else {
- this.addLog('⚠️ 问卷未完成', 'warning');
- }
-
- } catch (error) {
- this.addLog('⚠️ 无法查询问卷状态: ' + error, 'warning');
- }
- }
- /**
- * 重置问卷状态
- */
- async resetSurvey() {
- if (!this.profileInfo) return;
-
- const Parse = await import('fmode-ng/parse').then(m => m.FmodeParse.with('nova'));
-
- try {
- this.addLog('重置问卷状态...', 'info');
-
- const query = new Parse.Query('Profile');
- const profile = await query.get(this.profileInfo.id);
-
- profile.set('surveyCompleted', false);
- profile.unset('surveyCompletedAt');
- profile.unset('surveyLogId');
-
- await profile.save();
-
- this.profileInfo.surveyCompleted = false;
- this.addLog('✅ 问卷状态已重置', 'success');
-
- } catch (error) {
- this.addLog('❌ 重置失败: ' + error, 'error');
- }
- }
- /**
- * 前往问卷页面
- */
- goToSurvey() {
- this.addLog('跳转到问卷页面...', 'info');
- this.router.navigate(['/wxwork', this.cid, 'survey', 'profile']);
- }
- /**
- * 前往工作台
- */
- goToDashboard() {
- this.addLog('跳转到工作台...', 'info');
- this.router.navigate(['/wxwork', this.cid, 'designer', 'dashboard']);
- }
- /**
- * 添加日志
- */
- private addLog(message: string, type: 'info' | 'success' | 'warning' | 'error') {
- const time = new Date().toLocaleTimeString();
- this.logs.push({ time, message, type });
-
- // 自动滚动到底部
- setTimeout(() => {
- const container = document.querySelector('.log-container');
- if (container) {
- container.scrollTop = container.scrollHeight;
- }
- }, 100);
- }
- }
|