import { Component, Input, Output, EventEmitter, OnInit } from '@angular/core'; import { CommonModule } from '@angular/common'; import { FormsModule } from '@angular/forms'; import { FmodeObject, FmodeQuery, FmodeParse } from 'fmode-ng/parse'; import { WxworkCorp, WxworkSDK } from 'fmode-ng/core'; const Parse = FmodeParse.with('nova'); export interface ProjectMember { id: string; name: string; userid: string; avatar?: string; role: string; department?: string; isInGroupChat: boolean; isInProjectTeam: boolean; projectTeamId?: string; profileId?: string; } export interface GroupChatMember { userid: string; name: string; type: number; // 1: 内部成员 2: 外部联系人 avatar?: string; } @Component({ selector: 'app-project-members-modal', standalone: true, imports: [CommonModule, FormsModule], templateUrl: './project-members-modal.component.html', styleUrls: ['./project-members-modal.component.scss'] }) export class ProjectMembersModalComponent implements OnInit { @Input() project: FmodeObject | null = null; @Input() groupChat: FmodeObject | null = null; @Input() currentUser: FmodeObject | null = null; @Input() isVisible: boolean = false; @Input() cid: string = ''; @Output() close = new EventEmitter(); members: ProjectMember[] = []; loading: boolean = false; error: string | null = null; isWxworkEnvironment: boolean = false; // 统计信息 totalMembers: number = 0; groupChatMembers: number = 0; projectTeamMembers: number = 0; pendingAddMembers: number = 0; // 过滤和搜索 searchQuery: string = ''; memberFilter: 'all' | 'ingroup' | 'team' | 'pending' = 'all'; // 企业微信API private wecorp: WxworkCorp | null = null; private wwsdk: WxworkSDK | null = null; isWechat:boolean = false; constructor() { let ua = navigator.userAgent.toLowerCase(); this.isWechat = ua.indexOf('micromessenger') !== -1; this.checkWxworkEnvironment(); } ngOnInit(): void { if (this.isVisible && this.project) { this.loadMembers(); } } ngOnChanges(): void { if (this.isVisible && this.project) { this.loadMembers(); } } private checkWxworkEnvironment(): void { // 检查是否在企业微信环境中 this.wecorp = new WxworkCorp(this.cid); this.wwsdk = new WxworkSDK({cid:this.cid,appId:'crm'}); console.log('✅ 企业微信环境检测成功'); } async loadMembers(): Promise { if (!this.project) return; try { this.loading = true; this.error = null; // 1. 加载项目团队成员 const projectTeamMembers = await this.loadProjectTeamMembers(); // 2. 加载群聊成员 if(!this.groupChat?.id){ const gcQuery2 = new Parse.Query('GroupChat'); gcQuery2.equalTo('project', this.project?.id); this.groupChat = await gcQuery2.first(); } const groupChatMembers = await this.loadGroupChatMembers(); // 3. 合并成员数据 console.log("999",projectTeamMembers, groupChatMembers) this.mergeMembersData(projectTeamMembers, groupChatMembers); this.calculateStats(); console.log(`✅ 加载了 ${this.members.length} 个成员信息`); } catch (error) { console.error('❌ 加载成员失败:', error); this.error = error instanceof Error ? error.message : '加载成员失败'; } finally { this.loading = false; } } private async loadProjectTeamMembers(): Promise { try { const query = new FmodeQuery('ProjectTeam'); if (this.project) { query.equalTo('project', this.project.toPointer()); } query.include('profile','department','profile.department'); query.notEqualTo('isDeleted', true); return await query.find(); } catch (error) { console.error('加载项目团队成员失败:', error); return []; } } private async loadGroupChatMembers(): Promise { if (!this.groupChat) return []; try { const memberList = this.groupChat.get('member_list') || []; return memberList } catch (error) { console.error('加载群聊成员失败:', error); return []; } } private mergeMembersData(projectTeamMembers: FmodeObject[], groupChatMembers: GroupChatMember[]): void { const memberMap = new Map(); // 1. 添加项目团队成员 projectTeamMembers.forEach(team => { const profile = team.get('profile'); if (profile) { const member: ProjectMember = { id: profile.id, name: profile.get('name') || '未知', userid: profile.get('userid') || '', avatar: profile.get('data')?.avatar, role: profile.get('roleName') || '未知', department: profile.get('department')?.get('name'), isInGroupChat: false, isInProjectTeam: true, projectTeamId: team.id, profileId: profile.id }; memberMap.set(profile.id, member); } }); // 2. 添加群聊成员(包括外部联系人) groupChatMembers.forEach(groupMember => { // 查找是否已在项目团队中 const existingMember = Array.from(memberMap.values()).find( m => m.userid === groupMember.userid || m.name === groupMember.name ); if (existingMember) { existingMember.isInGroupChat = true; } else { // 添加仅存在于群聊中的成员 const member: ProjectMember = { id: groupMember.userid, name: groupMember.name, userid: groupMember.userid, avatar: groupMember.avatar, role: groupMember.type === 1 ? '外部联系人' : '内部成员', isInGroupChat: true, isInProjectTeam: false, projectTeamId: undefined, profileId: undefined }; memberMap.set(groupMember.userid, member); } }); this.members = Array.from(memberMap.values()); } calculateStats(): void { this.totalMembers = this.members.length; this.groupChatMembers = this.members.filter(m => m.isInGroupChat).length; this.projectTeamMembers = this.members.filter(m => m.isInProjectTeam).length; this.pendingAddMembers = this.members.filter(m => m.isInProjectTeam && !m.isInGroupChat).length; } onClose(): void { this.close.emit(); } onBackdropClick(event: MouseEvent): void { if (event.target === event.currentTarget) { this.onClose(); } } getFilteredMembers(): ProjectMember[] { let filtered = this.members; // 搜索过滤 if (this.searchQuery) { const query = this.searchQuery.toLowerCase(); filtered = filtered.filter(member => member.name.toLowerCase().includes(query) || member.role.toLowerCase().includes(query) || member.department?.toLowerCase().includes(query) ); } // 状态过滤 switch (this.memberFilter) { case 'ingroup': filtered = filtered.filter(m => m.isInGroupChat); break; case 'team': filtered = filtered.filter(m => m.isInProjectTeam); break; case 'pending': filtered = filtered.filter(m => m.isInProjectTeam && !m.isInGroupChat); break; } return filtered.sort((a, b) => { // 优先级:项目团队成员 > 仅群聊成员 if (a.isInProjectTeam && !b.isInProjectTeam) return -1; if (!a.isInProjectTeam && b.isInProjectTeam) return 1; // 按名称排序 return a.name.localeCompare(b.name, 'zh-CN'); }); } async addMemberToGroupChat(member: ProjectMember): Promise { if(!this.isWechat){ alert("请在企业微信客户端添加") } if (!member.userid) { alert('该成员没有用户ID,无法添加到群聊'); return; } try { const chatId = this.groupChat?.get('chat_id'); if (!chatId) { alert('群聊ID不存在'); return; } console.log(`🚀 开始添加成员 ${member.name} (${member.userid}) 到群聊 ${chatId}`); // TODO: 实现正确的企业微信API调用 let result = await this.wwsdk?.ww.updateEnterpriseChat({ chatId: chatId, userIdsToAdd: [member.userid] }); // 临时:直接更新本地状态用于演示 if(result){ member.isInGroupChat = true; this.calculateStats(); } alert(`✅ 已将 ${member.name} 添加到群聊`); console.log(`✅ 成功添加成员 ${member.name} 到群聊`); } catch (error) { console.error('❌ 添加成员到群聊失败:', error); alert(`添加失败: ${error instanceof Error ? error.message : '未知错误'}`); } } getRoleBadgeClass(role: string): string { switch (role) { case '客服': return 'role-customer-service'; case '组员': case '设计师': return 'role-designer'; case '组长': return 'role-team-leader'; case '管理员': return 'role-admin'; case '外部联系人': return 'role-external'; default: return 'role-default'; } } getMemberStatusClass(member: ProjectMember): string { if (member.isInProjectTeam && member.isInGroupChat) { return 'status-active'; } else if (member.isInProjectTeam) { return 'status-pending'; } else { return 'status-group-only'; } } getMemberStatusText(member: ProjectMember): string { if (member.isInProjectTeam && member.isInGroupChat) { return '已加入'; } else if (member.isInProjectTeam) { return '待加入'; } else { return '仅群聊'; } } }