import { CommonModule } from '@angular/common'; import { ChangeDetectionStrategy, Component, inject, OnDestroy, OnInit, signal } from '@angular/core'; import { FormsModule } from '@angular/forms'; import { ActivatedRoute } from '@angular/router'; import { firstValueFrom } from 'rxjs'; import { ApiService } from '../../core/api.service'; import { SessionService } from '../../core/session.service'; import { buildFormSubmission } from '../../core/form-payload'; import { PAGE_BY_PATH } from '../../core/page-catalog'; import { DropdownDirective } from '../../shared/dropdown.directive'; interface Reply {id:string;title:string;content:string;kind:string;submittedAt:string;status:string;response:string;handledAt:string;unread:boolean;readAt:string;} interface Inbox {items:Reply[];total:number;unread:number;} @Component({selector:'app-support-center',standalone:true,imports:[CommonModule,FormsModule,DropdownDirective],templateUrl:'./support-center.component.html',styleUrl:'./support-center.component.scss',changeDetection:ChangeDetectionStrategy.OnPush}) export class SupportCenterComponent implements OnInit,OnDestroy { private readonly api=inject(ApiService); private readonly session=inject(SessionService); readonly history=signal(inject(ActivatedRoute).snapshot.queryParamMap.get('view')==='history'); readonly inbox=signal(null); readonly loading=signal(false);readonly sending=signal(false);readonly error=signal('');readonly submitError=signal('');readonly message=signal('');readonly readError=signal('');readonly reading=signal('');readonly expanded=signal(''); name='';content='';requestType='feedback';page=1;readonly pageSize=10;readonly Math=Math; private revision=0;private timer?: ReturnType; private readonly refresh=()=>{if(document.visibilityState==='visible'&&!this.reading()&&!this.sending())void this.load(false);}; ngOnInit():void {this.name=this.session.user()?.honeyName||this.session.user()?.userName||'';void this.load();this.timer=setInterval(this.refresh,30000);window.addEventListener('focus',this.refresh);document.addEventListener('visibilitychange',this.refresh);} ngOnDestroy():void {this.revision++;clearInterval(this.timer);window.removeEventListener('focus',this.refresh);document.removeEventListener('visibilitychange',this.refresh);} statusLabel(status:string):string{return ({pending:'待处理',processed:'已处理',approved:'已同意休假',rejected:'未同意休假'} as Record)[status]||'待处理';} async load(foreground=true):Promise{ const revision=++this.revision,token=this.session.token(); if(foreground)this.loading.set(true); try{const {result}=await firstValueFrom(this.api.post('app_support_requests_list',{page:this.page,pageSize:this.pageSize}));if(revision!==this.revision||token!==this.session.token())return;this.inbox.set(result);this.error.set('');} catch(e){if(revision===this.revision&&token===this.session.token())this.error.set(e instanceof Error?e.message:'回复暂时无法加载,请重试');} finally{if(revision===this.revision)this.loading.set(false);} } showHistory():void{this.history.set(true);void this.load();} changePage(page:number):void{this.page=page;this.expanded.set('');void this.load();} async submit():Promise{ if(this.sending())return; if(!this.name.trim()||!this.content.trim()){this.submitError.set('请填写姓名和内容');return;} const payload=buildFormSubmission(PAGE_BY_PATH.get('pages/member/feedback')!,{name:this.name,content:this.content.trim(),requestType:this.requestType},{uid:this.session.user()?.userId})!; this.sending.set(true);this.submitError.set('');this.message.set(''); try{await firstValueFrom(this.api.post(payload.action,payload.payload));this.content='';this.message.set('提交成功,管理员处理后会在这里回复。');this.history.set(true);this.page=1;await this.load();} catch(e){this.submitError.set(e instanceof Error?e.message:'提交失败,请重试');}finally{this.sending.set(false);} } async viewReply(row:Reply):Promise{ this.expanded.set(row.id);this.readError.set('');if(!row.unread||this.reading())return; this.revision++;this.loading.set(false);this.reading.set(row.id);const token=this.session.token(); try{await firstValueFrom(this.api.post('app_support_request_read',{id:row.id}));if(token!==this.session.token())return;this.inbox.update(d=>d?{...d,unread:Math.max(0,d.unread-(d.items.some(r=>r.id===row.id&&r.unread)?1:0)),items:d.items.map(r=>r.id===row.id?{...r,unread:false}:r)}:d);} catch(e){this.readError.set(e instanceof Error?e.message:'已读状态未保存,可重试');}finally{this.reading.set('');} } }