import { Component, OnInit } from '@angular/core'; import { CommonModule } from '@angular/common'; import { Router, ActivatedRoute } from '@angular/router'; import { FormsModule } from '@angular/forms'; import { IonicModule } from '@ionic/angular'; import { WxworkSDK, WxworkCorp, WxworkCurrentChat } from 'fmode-ng/core'; import { FmodeParse, FmodeObject } from 'fmode-ng/parse'; import { wxdebug } from 'fmode-ng'; import { addIcons } from 'ionicons'; import { rocketOutline, addCircleOutline, timeOutline, personCircleOutline, alertCircleOutline, refreshOutline, chevronForwardOutline } from 'ionicons/icons'; const Parse = FmodeParse.with('nova'); /** * 项目预加载页面 * * 功能: * 1. 从企微会话获取上下文(群聊或联系人) * 2. 获取当前登录用户(Profile) * 3. 根据场景跳转到对应页面 * - 群聊 → 项目详情 或 创建项目引导 * - 联系人 → 客户画像 * * 路由:/wxwork/:cid/project-loader * * 参考实现:nova-admin/projects/nova-crm/src/modules/chat/page-chat-context */ @Component({ selector: 'app-project-loader', standalone: true, imports: [CommonModule, FormsModule, IonicModule], templateUrl: './project-loader.component.html', styleUrls: ['./project-loader.component.scss'] }) export class ProjectLoaderComponent implements OnInit { // 基础数据 cid: string = ''; appId: string = 'crm'; // 加载状态 loading: boolean = true; loadingMessage: string = '正在加载...'; error: string | null = null; // 企微SDK wxwork: WxworkSDK | null = null; wecorp: WxworkCorp | null = null; // 上下文数据 currentUser: FmodeObject | null = null; // Profile 或 UserSocial currentChat: WxworkCurrentChat | null = null; chatType: 'group' | 'contact' | 'none' = 'none'; groupChat: FmodeObject | null = null; // GroupChat contact: FmodeObject | null = null; // ContactInfo project: FmodeObject | null = null; // Project // 创建项目引导 showCreateGuide: boolean = false; defaultProjectName: string = ''; projectName: string = ''; creating: boolean = false; // 历史项目(当前群聊无项目时展示) historyProjects: FmodeObject[] = []; constructor( private router: Router, private route: ActivatedRoute ) { addIcons({ rocketOutline, addCircleOutline, timeOutline, personCircleOutline, alertCircleOutline, refreshOutline, chevronForwardOutline }); } async ngOnInit() { // 获取路由参数 this.route.paramMap.subscribe(async params => { this.cid = params.get('cid') || ''; this.appId = params.get('appId') || 'crm'; if (!this.cid) { this.error = '缺少企业ID参数'; this.loading = false; return; } await this.loadData(); }); } /** * 加载数据主流程(参考 page-chat-context 实现) */ async loadData() { try { this.loading = true; this.loadingMessage = '初始化企微SDK...'; // 1️⃣ 初始化 SDK this.wxwork = new WxworkSDK({ cid: this.cid, appId: this.appId }); this.wecorp = new WxworkCorp(this.cid); wxdebug('1. SDK初始化完成', { cid: this.cid, appId: this.appId }); // 2️⃣ 加载当前登录员工信息(由 WxworkAuthGuard 自动登录) this.loadingMessage = '获取用户信息...'; try { this.currentUser = await this.wxwork.getCurrentUser(); wxdebug('2. 获取当前用户成功', this.currentUser?.toJSON()); } catch (err) { console.error('获取当前用户失败:', err); wxdebug('2. 获取当前用户失败', err); throw new Error('获取用户信息失败,请重试'); } // 3️⃣ 加载当前聊天上下文 this.loadingMessage = '获取会话信息...'; try { this.currentChat = await this.wxwork.getCurrentChat(); wxdebug('3. getCurrentChat返回', this.currentChat); } catch (err) { console.error('getCurrentChat失败:', err); wxdebug('3. getCurrentChat失败', err); } // 4️⃣ 根据场景同步数据 if (this.currentChat?.type === "chatId" && this.currentChat?.group) { // 群聊场景 wxdebug('4. 检测到群聊场景', this.currentChat.group); this.loadingMessage = '同步群聊信息...'; try { this.chatType = 'group'; this.groupChat = await this.wxwork.syncGroupChat(this.currentChat.group); wxdebug('5. 群聊同步完成', this.groupChat?.toJSON()); // 处理群聊场景 await this.handleGroupChatScene(); } catch (err) { console.error('群聊同步失败:', err); wxdebug('5. 群聊同步失败', err); throw new Error('群聊信息同步失败'); } } else if (this.currentChat?.type === "userId" && this.currentChat?.id) { // 联系人场景 wxdebug('4. 检测到联系人场景', { id: this.currentChat.id }); this.loadingMessage = '同步联系人信息...'; try { this.chatType = 'contact'; // 获取完整联系人信息 const contactInfo = await this.wecorp!.externalContact.get(this.currentChat.id); wxdebug('5. 获取完整联系人信息', contactInfo); this.contact = await this.wxwork.syncContact(contactInfo); wxdebug('6. 联系人同步完成', this.contact?.toJSON()); // 处理联系人场景 await this.handleContactScene(); } catch (err) { console.error('联系人同步失败:', err); wxdebug('联系人同步失败', err); throw new Error('联系人信息同步失败'); } } else { // 未检测到有效场景 wxdebug('4. 未检测到有效场景', { currentChat: this.currentChat, type: this.currentChat?.type, hasGroup: !!this.currentChat?.group, hasContact: !!this.currentChat?.contact, hasId: !!this.currentChat?.id }); throw new Error('无法识别当前会话类型,请在群聊或联系人会话中打开'); } wxdebug('加载完成', { chatType: this.chatType, hasGroupChat: !!this.groupChat, hasContact: !!this.contact, hasCurrentUser: !!this.currentUser }); } catch (err: any) { console.error('加载失败:', err); this.error = err.message || '加载失败,请重试'; } finally { this.loading = false; } } /** * 处理群聊场景 */ async handleGroupChatScene() { this.loadingMessage = '查询项目信息...'; // 查询群聊关联的项目 const projectPointer = this.groupChat!.get('project'); if (projectPointer) { // 有项目,加载项目详情 try { const query = new Parse.Query('Project'); query.include('customer', 'assignee'); this.project = await query.get(projectPointer.id); wxdebug('找到项目', this.project.toJSON()); // 跳转项目详情 await this.navigateToProjectDetail(); } catch (err) { console.error('加载项目失败:', err); wxdebug('加载项目失败', err); this.error = '项目已删除或无权访问'; } } else { // 无项目,查询历史项目并显示创建引导 await this.loadHistoryProjects(); this.showCreateProjectGuide(); } } /** * 处理联系人场景 */ async handleContactScene() { wxdebug('联系人场景,跳转客户画像', { contactId: this.contact!.id, contactName: this.contact!.get('name') }); // 跳转客户画像页面 await this.router.navigate(['/wxwork', this.cid, 'contact', this.contact!.id], { queryParams: { profileId: this.currentUser!.id } }); } /** * 加载历史项目(当前群聊相关的其他项目) */ async loadHistoryProjects() { try { // 通过 ProjectGroup 查询该群聊的所有项目 const pgQuery = new Parse.Query('ProjectGroup'); pgQuery.equalTo('groupChat', this.groupChat!.toPointer()); pgQuery.include('project'); pgQuery.descending('createdAt'); const projectGroups = await pgQuery.find(); this.historyProjects = projectGroups .map(pg => pg.get('project')) .filter(p => p && !p.get('isDeleted')); wxdebug('找到历史项目', { count: this.historyProjects.length }); } catch (err) { console.error('加载历史项目失败:', err); wxdebug('加载历史项目失败', err); } } /** * 显示创建项目引导 */ showCreateProjectGuide() { this.showCreateGuide = true; this.defaultProjectName = this.groupChat!.get('name') || '新项目'; this.projectName = this.defaultProjectName; wxdebug('显示创建项目引导', { groupName: this.groupChat!.get('name'), historyProjectsCount: this.historyProjects.length }); } /** * 创建项目 */ async createProject() { if (!this.projectName.trim()) { alert('请输入项目名称'); return; } // 权限检查 const role = this.currentUser!.get('role'); if (!['客服', '组长', '管理员'].includes(role)) { alert('您没有权限创建项目'); return; } try { this.creating = true; wxdebug('开始创建项目', { projectName: this.projectName, groupChatId: this.groupChat!.id, currentUserId: this.currentUser!.id, role: role }); // 1. 创建项目 const Project = Parse.Object.extend('Project'); const project = new Project(); project.set('title', this.projectName.trim()); project.set('company', this.currentUser!.get('company')); project.set('status', '待分配'); project.set('currentStage', '订单分配'); project.set('data', { createdBy: this.currentUser!.id, createdFrom: 'wxwork_groupchat', groupChatId: this.groupChat!.id }); await project.save(); wxdebug('项目创建成功', { projectId: project.id }); // 2. 关联群聊 this.groupChat!.set('project', project.toPointer()); await this.groupChat!.save(); wxdebug('群聊关联项目成功'); // 3. 创建 ProjectGroup 关联(支持多项目多群) const ProjectGroup = Parse.Object.extend('ProjectGroup'); const pg = new ProjectGroup(); pg.set('project', project.toPointer()); pg.set('groupChat', this.groupChat!.toPointer()); pg.set('isPrimary', true); pg.set('company', this.currentUser!.get('company')); await pg.save(); wxdebug('ProjectGroup关联创建成功'); // 4. 跳转项目详情 this.project = project; await this.navigateToProjectDetail(); } catch (err: any) { console.error('创建项目失败:', err); wxdebug('创建项目失败', err); alert('创建失败: ' + (err.message || '未知错误')); } finally { this.creating = false; } } /** * 选择历史项目 */ async selectHistoryProject(project: FmodeObject) { try { wxdebug('选择历史项目', { projectId: project.id, projectTitle: project.get('title') }); // 更新群聊的当前项目 this.groupChat!.set('project', project.toPointer()); await this.groupChat!.save(); // 跳转项目详情 this.project = project; await this.navigateToProjectDetail(); } catch (err: any) { console.error('关联项目失败:', err); alert('关联失败: ' + (err.message || '未知错误')); } } /** * 跳转项目详情 */ async navigateToProjectDetail() { wxdebug('跳转项目详情', { projectId: this.project!.id, cid: this.cid, groupChatId: this.groupChat?.id }); await this.router.navigate(['/wxwork', this.cid, 'project', this.project!.id], { queryParams: { groupId: this.groupChat?.id, profileId: this.currentUser!.id } }); } /** * 重新加载 */ async reload() { this.error = null; this.showCreateGuide = false; this.historyProjects = []; this.chatType = 'none'; await this.loadData(); } /** * 获取当前员工姓名 */ getCurrentUserName(): string { if (!this.currentUser) return '未知'; return this.currentUser.get('name') || this.currentUser.get('userid') || '未知'; } /** * 获取当前员工角色 */ getCurrentUserRole(): string { if (!this.currentUser) return '未知'; return this.currentUser.get('role') || '未知'; } /** * 获取项目状态的显示样式类 */ getProjectStatusClass(status: string): string { const classMap: any = { '待分配': 'status-pending', '进行中': 'status-active', '已完成': 'status-completed', '已暂停': 'status-paused', '已取消': 'status-cancelled' }; return classMap[status] || 'status-default'; } /** * 格式化日期 */ formatDate(date: Date): string { if (!date) return ''; const d = new Date(date); return `${d.getFullYear()}/${d.getMonth() + 1}/${d.getDate()}`; } }