| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195 |
- import { Component, Input, Output, EventEmitter, OnInit } from '@angular/core';
- import { CommonModule } from '@angular/common';
- import { FormsModule } from '@angular/forms';
- import { IonicModule } from '@ionic/angular';
- import { FmodeParse, FmodeObject } from 'fmode-ng/parse';
- import { WxworkCorp } from 'fmode-ng/core';
- import { CustomerProfileComponent } from '../../pages/contact/contact.component';
- const Parse: any = FmodeParse.with('nova');
- @Component({
- selector: 'app-contact-selector',
- standalone: true,
- imports: [CommonModule, FormsModule, IonicModule, CustomerProfileComponent],
- templateUrl: './contact-selector.component.html',
- styleUrls: ['./contact-selector.component.scss']
- })
- export class CustomerSelectorComponent implements OnInit {
- @Input() project: FmodeObject | null = null;
- @Input() groupChat: FmodeObject | null = null;
- @Input() currentUser: FmodeObject | null = null;
- @Input() placeholder: string = '请选择项目客户';
- @Input() disabled: boolean = false;
- @Input() showCreateButton: boolean = true;
- @Output() contactSelected = new EventEmitter<{ contact: FmodeObject; isNewCustomer: boolean; action: 'selected' | 'created' | 'updated' }>();
- loading: boolean = false;
- searchKeyword: string = '';
- currentCustomer: FmodeObject | null = null;
- availableCustomers: FmodeObject[] = [];
- externalMembers: Array<{ userid: string; name?: string }> = [];
- unbuiltExternalMembers: Array<{ userid: string; name?: string }> = [];
- showCustomerPanel: boolean = false;
- get canViewSensitiveInfo(): boolean {
- const role = this.currentUser?.get?.('roleName') || '';
- return ['客服', '组长', '管理员'].includes(role);
- }
- async ngOnInit() {
- await this.init();
- }
- private async init() {
- if (!this.project || !this.groupChat) return;
- try {
- this.loading = true;
- await this.checkProjectCustomer();
- await this.loadExternalMembers();
- await this.loadAvailableCustomers();
- this.computeUnbuiltMembers();
- } finally {
- this.loading = false;
- }
- }
- private async checkProjectCustomer() {
- const ptr = this.project!.get('contact');
- if (!ptr) { this.currentCustomer = null; return; }
- try {
- if (ptr.id && (ptr as any).get) {
- this.currentCustomer = ptr as any;
- } else if (ptr.id) {
- const query = new Parse.Query('ContactInfo');
- this.currentCustomer = await query.get(ptr.id);
- }
- } catch {
- this.currentCustomer = null;
- }
- }
- private async loadExternalMembers() {
- const list = this.groupChat!.get('member_list') || [];
- const external = Array.isArray(list) ? list.filter((m: any) => m && m.type === 2) : [];
- this.externalMembers = external.map((m: any) => ({ userid: m.userid, name: m.name }));
- }
- private async loadAvailableCustomers() {
- const companyId = this.project!.get('company')?.id || localStorage.getItem('company');
- if (!companyId) return;
- const extIds = this.externalMembers.map(m => m.userid);
- if (extIds.length === 0) { this.availableCustomers = []; return; }
- const query = new Parse.Query('ContactInfo');
- query.equalTo('company', companyId);
- query.containedIn('external_userid', extIds);
- query.notEqualTo('isDeleted', true);
- this.availableCustomers = await query.find();
- }
- private computeUnbuiltMembers() {
- const builtIds = new Set<string>(
- this.availableCustomers.map((c: any) => c.get('external_userid')).filter(Boolean)
- );
- this.unbuiltExternalMembers = this.externalMembers.filter(m => !builtIds.has(m.userid));
- }
- private getMemberInfo(userid: string): any {
- const list = this.groupChat!.get('member_list') || [];
- return (list || []).find((m: any) => m && m.userid === userid) || null;
- }
- get filteredCustomers(): FmodeObject[] {
- const kw = (this.searchKeyword || '').trim().toLowerCase();
- const base = this.availableCustomers;
- if (!kw) return base;
- return base.filter(c => {
- const name = (c.get('name') || c.get('data')?.name || '').toLowerCase();
- const mobile = (c.get('mobile') || '').toLowerCase();
- return name.includes(kw) || mobile.includes(kw);
- });
- }
- async selectExistingCustomer(contact: FmodeObject) {
- if (this.disabled || !this.project) return;
- const nameMissing = !contact.get('name') && !contact.get('data')?.name && !contact.get('data')?.external_contact?.name;
- const extid = contact.get('external_userid');
- if (nameMissing && extid) {
- await this.refreshContactInfo(contact);
- }
- this.project.set('contact', contact.toPointer());
- await this.project.save();
- this.currentCustomer = contact;
- this.contactSelected.emit({ contact, isNewCustomer: false, action: 'selected' });
- }
- switchToSelecting() {
- this.currentCustomer = null;
- this.searchKeyword = '';
- }
- async createFromMember(memberUserid: string) {
- if (this.disabled || !this.project) return;
- const companyId = this.project.get('company')?.id || localStorage.getItem('company');
- if (!companyId) throw new Error('无法获取企业信息');
- const query = new Parse.Query('ContactInfo');
- query.equalTo('external_userid', memberUserid);
- query.equalTo('company', companyId);
- let contactInfo = await query.first();
- if (!contactInfo) {
- const corp = new WxworkCorp(companyId);
- const extData = await corp.externalContact.get(memberUserid);
- const ext = (extData && extData.external_contact) ? extData.external_contact : {};
- const follow = (extData && extData.follow_user) ? extData.follow_user : [];
- const ContactInfo = Parse.Object.extend('ContactInfo');
- contactInfo = new ContactInfo();
- contactInfo.set('name', ext.name || this.getMemberInfo(memberUserid)?.name || '客户');
- contactInfo.set('external_userid', memberUserid);
- const company = new Parse.Object('Company');
- company.id = companyId;
- contactInfo.set('company', company.toPointer());
- const mapped = {
- external_contact: ext,
- follow_user: follow,
- member: this.getMemberInfo(memberUserid),
- name: ext.name || this.getMemberInfo(memberUserid)?.name,
- avatar: ext.avatar,
- gender: ext.gender,
- type: ext.type
- } as any;
- contactInfo.set('data', mapped);
- contactInfo = await contactInfo.save();
- await this.loadAvailableCustomers();
- this.computeUnbuiltMembers();
- }
- this.project.set('contact', contactInfo.toPointer());
- await this.project.save();
- this.currentCustomer = contactInfo;
- this.contactSelected.emit({ contact: contactInfo, isNewCustomer: true, action: 'created' });
- }
- async refreshContactInfo(contact: any) {
- const externalUserId = contact.get('external_userid');
- const companyId = this.project?.get('company')?.id || localStorage.getItem('company');
- if (!externalUserId || !companyId) return;
- const corp = new WxworkCorp(companyId);
- const extData = await corp.externalContact.get(externalUserId);
- const ext = (extData && extData.external_contact) ? extData.external_contact : {};
- const follow = (extData && extData.follow_user) ? extData.follow_user : [];
- if (ext.name) contact.set('name', ext.name);
- const mapped = {
- external_contact: ext,
- follow_user: follow,
- member: this.getMemberInfo(externalUserId),
- name: ext.name || this.getMemberInfo(externalUserId)?.name,
- avatar: ext.avatar,
- gender: ext.gender,
- type: ext.type
- } as any;
- contact.set('data', mapped);
- await contact.save();
- }
- viewCustomerDetail() { this.showCustomerPanel = true; }
- closeCustomerDetail() { this.showCustomerPanel = false; }
- }
|