import { Component, Input, Output, EventEmitter } from '@angular/core'; import { CommonModule } from '@angular/common'; export interface Case { id: string; name: string; coverImage: string; images?: string[]; projectType: '工装' | '家装' | string; spaceType: '平层' | '复式' | '别墅' | '自建房' | string; roomType?: string; // 户型 renderingLevel: '高端' | '中端' | '低端' | string; designer: string; designerId?: string; team: string; teamId?: string; area: number; totalPrice?: number; // 项目总额 completionDate?: Date | string; // 完成时间 tag?: string[]; // 标签数组(替代styleTags) styleTags?: string[]; // 兼容旧字段 customerReview?: string; viewCount?: number; shareCount?: number; favoriteCount?: number; isFavorite?: boolean; isExcellent?: boolean; isPublished?: boolean; createdAt: Date | string; updatedAt?: Date | string; projectId?: string; data?: any; info?: { area?: number; projectType?: '工装' | '家装'; roomType?: string; spaceType?: string; renderingLevel?: string; }; } @Component({ selector: 'app-case-detail-panel', standalone: true, imports: [CommonModule], templateUrl: './case-detail-panel.component.html', styleUrls: ['./case-detail-panel.component.scss'] }) export class CaseDetailPanelComponent { @Input() case!: Case; @Input() isInternalUser: boolean = false; @Output() close = new EventEmitter(); @Output() toggleFavorite = new EventEmitter(); @Output() share = new EventEmitter(); /** * 统一计算封面图: * 1) 优先交付执行阶段上传的真实图片(来自 images 数组) * 2) 再看 coverImage 是否为真实上传 * 3) 否则回退到本地默认图 * 同时过滤需求阶段(stage/requirements)和占位/默认图。 */ coverImageOf(c: Case | null | undefined): string { if (!c) return '/assets/presets/家装图片.jpg'; const images = (c as any)?.images || []; const uploadedImage = images.find((img: string) => img && img.startsWith('http') && !img.includes('placeholder') && !img.includes('unsplash.com') && !img.endsWith('.svg') && !img.includes('/stage/requirements/') && (img.includes('file-cloud.fmode.cn') || img.includes('storage')) ); if (uploadedImage) return uploadedImage; const coverUrl: string = c.coverImage || ''; const isRealUpload = !!( coverUrl && coverUrl.startsWith('http') && !coverUrl.includes('placeholder') && !coverUrl.includes('unsplash.com') && !coverUrl.endsWith('.svg') && !coverUrl.includes('/stage/requirements/') && (coverUrl.includes('file-cloud.fmode.cn') || coverUrl.includes('storage')) ); if (isRealUpload) return coverUrl; return '/assets/presets/家装图片.jpg'; } closePanel() { this.close.emit(); } onToggleFavorite() { this.toggleFavorite.emit(this.case); } onShare() { this.share.emit(this.case); } getFormattedDate(date: Date | string): string { const dateObj = typeof date === 'string' ? new Date(date) : date; return new Intl.DateTimeFormat('zh-CN', { year: 'numeric', month: 'long', day: 'numeric' }).format(dateObj); } }