| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115 |
- 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<void>();
- @Output() toggleFavorite = new EventEmitter<Case>();
- @Output() share = new EventEmitter<Case>();
- /**
- * 统一计算封面图:
- * 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);
- }
- }
|