import { ChangeDetectionStrategy, Component, OnInit, inject, signal } from '@angular/core'; import { CommonModule } from '@angular/common'; import { FormsModule } from '@angular/forms'; import { ActivatedRoute, Router, RouterLink } from '@angular/router'; import { RUNTIME_CONFIG } from '../../../../app/core/config/runtime-config'; import { PageHeaderComponent } from '../../../shared/components/page-header/page-header.component'; import { SummaryMetricCardComponent } from '../../../shared/components/summary-metric-card/summary-metric-card.component'; import { ContentCardComponent } from '../../../shared/components/content-card/content-card.component'; import { ListingAiApiService } from '../../services/listing-ai-api.service'; import { ListingAiWorkbenchStore } from '../../services/listing-ai-workbench.store'; @Component({selector:'app-listing-ai-workbench',standalone:true,imports:[CommonModule,FormsModule,RouterLink,PageHeaderComponent,SummaryMetricCardComponent,ContentCardComponent],providers:[ListingAiWorkbenchStore],changeDetection:ChangeDetectionStrategy.OnPush,templateUrl:'./listing-ai-workbench.component.html',styleUrl:'../../listing-ai.shared.scss'}) export class ListingAiWorkbenchComponent implements OnInit{ readonly store=inject(ListingAiWorkbenchStore);private readonly api=inject(ListingAiApiService);private readonly route=inject(ActivatedRoute);private readonly router=inject(Router);readonly workspaceId=RUNTIME_CONFIG.domesticWorkspaceId; search='';scoreStatus='';coverageStatus='';sort='productId';readonly creating=signal(false);readonly actionError=signal('');readonly selected=new Set(); ngOnInit():void{const query=this.route.snapshot.queryParamMap;this.search=query.get('search')??'';this.scoreStatus=query.get('scoreStatus')??'';this.coverageStatus=query.get('coverageStatus')??'';this.sort=query.get('sort')??'productId';this.apply(false);} apply(updateUrl=true):void{this.store.patchFilters({search:this.search,scoreStatus:this.scoreStatus||undefined,coverageStatus:this.coverageStatus||undefined,sort:this.sort});if(updateUrl)void this.router.navigate([],{relativeTo:this.route,queryParams:{search:this.search||null,scoreStatus:this.scoreStatus||null,coverageStatus:this.coverageStatus||null,sort:this.sort==='productId'?null:this.sort},queryParamsHandling:'merge',replaceUrl:true});this.store.load(this.workspaceId);} toggle(id:string,checked:boolean):void{checked?this.selected.add(id):this.selected.delete(id);} runAiScore():void{ if(!this.selected.size)return; if(this.selected.size>10){this.actionError.set('本轮 Listing AI 评分最多支持 10 个商品,请减少选择数量。');return;} this.creating.set(true); this.actionError.set(''); const scope={mode:'selected' as const,productIds:[...this.selected]}; this.api.createScoreJob(this.workspaceId,scope,'ai').subscribe({ next:({job})=>void this.router.navigate(['/listing-ai/tasks',job.id]), error:(error)=>{ this.creating.set(false); const code=error?.error?.error; this.actionError.set(code==='listing_ai_budget_exceeded'?'本轮 Listing AI 评分最多支持 10 个商品。':code||'任务创建失败'); }, complete:()=>this.creating.set(false), }); } score(value:number|null):string{return value===null?'—':String(value);} scoreSource(score:{scoreKind?:string;rubricVersion:string}|null):string{return score?.scoreKind==='hybrid_ai'||score?.rubricVersion.startsWith('listing-jd-ai-')?'AI评分':'规则评分';} }