import { Component, Input, Output, EventEmitter, OnInit, OnDestroy, ChangeDetectionStrategy, HostListener } from '@angular/core'; import { CommonModule } from '@angular/common'; import { ColorAnalysisService, AnalysisProgress, ColorAnalysisResult } from '../../services/color-analysis.service'; import { FormAnalysisService } from '../../services/form-analysis.service'; import { TextureAnalysisService } from '../../services/texture-analysis.service'; import { PatternAnalysisService } from '../../services/pattern-analysis.service'; import { LightingAnalysisService } from '../../services/lighting-analysis.service'; import { RequirementMappingService } from '../../../services/requirement-mapping.service'; import { AtmospherePreviewService } from '../../../services/atmosphere-preview.service'; import { RequirementMapping, SceneTemplate } from '../../../models/requirement-mapping.interface'; import { Subscription } from 'rxjs'; import { modalAnimations } from './upload-success-modal.animations'; export interface UploadedFile { id: string; name: string; url: string; size?: number; type?: 'image' | 'cad' | 'text'; preview?: string; } export interface ColorInfo { hex: string; rgb: { r: number; g: number; b: number }; percentage: number; name?: string; // 颜色名称,如"深蓝色"、"暖白色"等 } @Component({ selector: 'app-upload-success-modal', standalone: true, imports: [CommonModule], templateUrl: './upload-success-modal.component.html', styleUrls: ['./upload-success-modal.component.scss'], changeDetection: ChangeDetectionStrategy.OnPush, animations: modalAnimations }) export class UploadSuccessModalComponent implements OnInit, OnDestroy { @Input() isVisible: boolean = false; @Input() uploadedFiles: UploadedFile[] = []; @Input() uploadType: 'image' | 'document' | 'mixed' = 'image'; @Input() analysisResult?: ColorAnalysisResult; @Input() isAnalyzing: boolean = false; // 新增:从父组件接收分析状态 @Output() closeModal = new EventEmitter(); @Output() analyzeColors = new EventEmitter(); @Output() viewReport = new EventEmitter(); @Output() generateRequirementMapping = new EventEmitter(); // 新增:需求映射生成事件 // 移除本地的isAnalyzing属性,使用@Input()的isAnalyzing // isAnalyzing = false; // 已移除,现在从父组件接收 analysisProgress: AnalysisProgress | null = null; analysisError: string | null = null; // 需求映射相关状态 requirementMapping: RequirementMapping | null = null; isGeneratingMapping = false; mappingError: string | null = null; // 增强分析标签页状态 activeTab: 'color' | 'form' | 'texture' | 'pattern' | 'lighting' | 'mapping' = 'color'; // 响应式状态 isMobile = false; isTablet = false; // 动画状态 animationState = 'idle'; buttonHoverState = 'normal'; copySuccess = false; // 复制成功状态 private progressSubscription?: Subscription; private resizeSubscription?: Subscription; constructor( private colorAnalysisService: ColorAnalysisService, private formAnalysisService: FormAnalysisService, private textureAnalysisService: TextureAnalysisService, private patternAnalysisService: PatternAnalysisService, private lightingAnalysisService: LightingAnalysisService, private requirementMappingService: RequirementMappingService, private atmospherePreviewService: AtmospherePreviewService ) {} ngOnInit() { this.checkScreenSize(); this.setupResizeListener(); } ngOnDestroy() { this.progressSubscription?.unsubscribe(); this.resizeSubscription?.unsubscribe(); } // 响应式布局检测 @HostListener('window:resize', ['$event']) onResize(event: any) { this.checkScreenSize(); } @HostListener('document:keydown', ['$event']) onKeyDown(event: KeyboardEvent) { if (event.key === 'Escape' && this.isVisible) { this.onClose(); } } // 开始颜色分析 async startColorAnalysis() { if (this.uploadedFiles.length === 0 || this.uploadType !== 'image') { return; } this.analysisError = null; try { // 发射分析事件给父组件处理 this.analyzeColors.emit(this.uploadedFiles); // 注意:不再调用本地的simulateAnalysis,而是等待父组件传递分析结果 // 父组件会通过@Input() analysisResult传递分析结果 // 父组件也会通过@Input() isAnalyzing控制分析状态 } catch (error) { this.analysisError = '颜色分析失败,请重试'; console.error('Color analysis error:', error); } } // 模拟分析过程 private async simulateAnalysis(): Promise { return new Promise((resolve) => { setTimeout(() => { // 模拟分析结果 this.analysisResult = { colors: [ { hex: '#8B4513', rgb: { r: 139, g: 69, b: 19 }, percentage: 35.2 }, { hex: '#A0522D', rgb: { r: 160, g: 82, b: 45 }, percentage: 27.1 }, { hex: '#D2B48C', rgb: { r: 210, g: 180, b: 140 }, percentage: 22.4 }, { hex: '#DEB887', rgb: { r: 222, g: 184, b: 135 }, percentage: 12.5 }, { hex: '#F5F5DC', rgb: { r: 245, g: 245, b: 220 }, percentage: 2.8 } ], originalImage: this.uploadedFiles[0]?.url || '', mosaicImage: '/assets/images/mock-mosaic.jpg', reportPath: '/reports/color-analysis-' + Date.now() + '.html', enhancedAnalysis: { colorWheel: { dominantHue: 45, saturationRange: { min: 20, max: 80 }, brightnessRange: { min: 40, max: 90 }, colorDistribution: [ { hue: 45, saturation: 65, brightness: 75, percentage: 62.3 }, { hue: 30, saturation: 45, brightness: 85, percentage: 22.4 }, { hue: 40, saturation: 55, brightness: 70, percentage: 12.5 } ] }, colorHarmony: { harmonyType: 'analogous', harmonyScore: 78, suggestions: ['保持温暖色调的统一性', '可适当增加对比色作为点缀'], relationships: [ { color1: '#8B4513', color2: '#D2B48C', relationship: '相似色', strength: 85 } ] }, colorTemperature: { averageTemperature: 3200, temperatureRange: { min: 2800, max: 3600 }, warmCoolBalance: 65, temperatureDescription: '温暖色调,适合营造舒适氛围', lightingRecommendations: ['适合使用暖白光照明(2700K-3000K)', '营造温馨舒适的氛围'] }, colorPsychology: { mood: '温馨', atmosphere: '舒适', suitableSpaces: ['客厅', '卧室', '餐厅'], psychologicalEffects: ['放松身心', '增强温暖感', '促进交流'], emotionalImpact: { energy: 45, warmth: 85, sophistication: 60, comfort: 90 } } }, // 模拟其他分析结果 formAnalysis: { lineAnalysis: { dominantLines: ['直线', '曲线'], dominantLineType: '直线', visualFlow: '流畅' }, overallAssessment: { complexity: 65, visualImpact: 78 } }, textureAnalysis: { surfaceProperties: { roughness: { level: 'moderate', value: 50, description: '中等粗糙度' }, glossiness: { level: 'satin', value: 40, reflectivity: 35 }, transparency: { level: 'opaque', value: 10, description: '基本不透明' }, reflectivity: { level: 'low', value: 25, description: '低反射' } }, materialClassification: { primaryMaterials: ['木材', '织物'], secondaryMaterials: ['金属', '玻璃'] } }, patternAnalysis: { patternRecognition: { primaryPatterns: [{ type: 'geometric', confidence: 80, coverage: 60, characteristics: ['规则', '对称'] }], patternComplexity: { level: 'moderate', value: 60, description: '中等复杂度' } }, visualRhythm: { rhythmType: { primary: 'regular', secondary: 'flowing' }, movement: { direction: 'horizontal', intensity: 65 } } }, lightingAnalysis: { lightSourceIdentification: { primarySources: ['自然光', '人工光'], lightingSetup: '混合照明' }, ambientAnalysis: { ambientLight: '柔和', lightingMood: '温馨' } } }; // 添加调试输出 console.log('=== 分析结果数据结构调试 ==='); console.log('完整分析结果:', this.analysisResult); console.log('形体分析:', this.analysisResult.formAnalysis); console.log('质感分析:', this.analysisResult.textureAnalysis); console.log('纹理分析:', this.analysisResult.patternAnalysis); console.log('灯光分析:', this.analysisResult.lightingAnalysis); console.log('色彩分析:', this.analysisResult.enhancedAnalysis); console.log('主要光源:', this.analysisResult.lightingAnalysis.lightSourceIdentification.primarySources); console.log('材质分类:', this.analysisResult.textureAnalysis.materialClassification); console.log('视觉节奏:', this.analysisResult.patternAnalysis.visualRhythm); // 生成需求映射 this.generateRequirementMappingFromAnalysis(); resolve(); }, 2000); }); } // 根据分析结果生成需求映射 private generateRequirementMappingFromAnalysis(): void { if (!this.analysisResult) { return; } try { this.isGeneratingMapping = true; this.mappingError = null; // 使用需求映射服务生成映射 this.requirementMappingService.generateRequirementMapping(this.analysisResult).subscribe({ next: (mapping) => { this.requirementMapping = mapping; console.log('=== 需求映射生成成功 ==='); console.log('需求映射结果:', this.requirementMapping); // 发出需求映射生成事件 this.generateRequirementMapping.emit(this.requirementMapping); }, error: (error) => { console.error('需求映射生成失败:', error); this.mappingError = '需求映射生成失败,请稍后重试'; }, complete: () => { this.isGeneratingMapping = false; } }); } catch (error) { console.error('需求映射初始化失败:', error); this.mappingError = '需求映射初始化失败,请稍后重试'; this.isGeneratingMapping = false; } } // 手动重新生成需求映射 regenerateRequirementMapping(): void { if (!this.analysisResult) { return; } this.generateRequirementMappingFromAnalysis(); } // 事件处理方法 onClose() { this.closeModal.emit(); } onBackdropClick(event: Event) { // 点击背景遮罩关闭弹窗 this.onClose(); } onAnalyzeColorsClick() { if (this.isAnalyzing || this.uploadedFiles.length === 0) { return; } this.animationState = 'loading'; this.analyzeColors.emit(this.uploadedFiles); } onViewReportClick() { if (this.analysisResult) { // 创建一个新的窗口来显示完整报告 const reportWindow = window.open('', '_blank', 'width=1200,height=800,scrollbars=yes,resizable=yes'); if (reportWindow) { // 生成完整的HTML报告内容 const reportHtml = this.generateFullReport(); reportWindow.document.write(reportHtml); reportWindow.document.close(); reportWindow.focus(); } else { // 如果弹窗被阻止,则下载报告文件 this.downloadReport(); } // 触发事件给父组件 this.viewReport.emit(this.analysisResult); } } // 工具方法 shouldShowColorAnalysis(): boolean { return this.uploadType === 'image' || this.hasImageFiles(); } formatFileSize(bytes: number): string { if (bytes === 0) return '0 Bytes'; const k = 1024; const sizes = ['Bytes', 'KB', 'MB', 'GB']; const i = Math.floor(Math.log(bytes) / Math.log(k)); return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i]; } getFileTypeIcon(file: UploadedFile): string { if (file.type?.startsWith('image/')) { return 'image'; } else if (file.type?.includes('pdf')) { return 'pdf'; } else if (file.type?.includes('word') || file.type?.includes('doc')) { return 'document'; } else { return 'file'; } } hasImageFiles(): boolean { return this.uploadedFiles.some(file => file.type?.startsWith('image/')); } // 生成颜色描述文字 generateColorDescription(): string { if (!this.analysisResult || !this.analysisResult.colors.length) { return ''; } const colorDescriptions = this.analysisResult.colors.map(color => { const colorName = color.name || this.getColorName(color.hex); return `${colorName}(${color.hex}) ${color.percentage}%`; }); return `主要色彩:${colorDescriptions.join('、')}`; } // 根据色值获取颜色名称 private getColorName(hex: string): string { const colorMap: { [key: string]: string } = { '#FFFFFF': '纯白色', '#F5F5F5': '白烟', '#E5E5E5': '浅灰色', '#CCCCCC': '中灰色', '#999999': '深灰色', '#666666': '暗灰色', '#333333': '深暗灰', '#000000': '纯黑色', '#FF0000': '红色', '#00FF00': '酸橙色', '#0000FF': '蓝色', '#FFFF00': '黄色', '#FF00FF': '品红色', '#00FFFF': '青色', '#FFA500': '橙色', '#800080': '紫色', '#008000': '绿色', '#000080': '海军蓝', '#800000': '栗色', '#808000': '橄榄色', '#008080': '水鸭色', '#C0C0C0': '银色', '#808080': '灰色', '#FFE4E1': '雾玫瑰', '#F0F8FF': '爱丽丝蓝', '#FAEBD7': '古董白', '#F5F5DC': '米色', '#DEB887': '硬木色', '#A52A2A': '棕色', '#D2691E': '巧克力色', '#FF7F50': '珊瑚色', '#6495ED': '矢车菊蓝', '#DC143C': '深红色', '#00008B': '深蓝色', '#B8860B': '深金色', '#A9A9A9': '深灰色', '#006400': '深绿色', '#BDB76B': '深卡其色', '#8B008B': '深品红', '#556B2F': '深橄榄绿', '#FF8C00': '深橙色', '#9932CC': '深兰花紫', '#8B0000': '深红色2', '#E9967A': '深鲑鱼色', '#8FBC8F': '深海绿', '#483D8B': '深石板蓝', '#2F4F4F': '深石板灰', '#00CED1': '深绿松石', '#9400D3': '深紫罗兰', '#FF1493': '深粉红', '#00BFFF': '深天蓝', '#696969': '暗灰色2', '#1E90FF': '道奇蓝', '#B22222': '火砖色', '#FFFAF0': '花白色', '#228B22': '森林绿', '#DCDCDC': '淡灰色', '#F8F8FF': '幽灵白', '#FFD700': '金色', '#DAA520': '金麒麟色', '#ADFF2F': '绿黄色', '#F0FFF0': '蜜瓜色', '#FF69B4': '热粉红', '#CD5C5C': '印度红', '#4B0082': '靛青色', '#FFFFF0': '象牙色', '#F0E68C': '卡其色', '#E6E6FA': '薰衣草色', '#FFF0F5': '薰衣草红', '#7CFC00': '草坪绿', '#FFFACD': '柠檬绸', '#ADD8E6': '浅蓝色', '#F08080': '浅珊瑚色', '#E0FFFF': '浅青色', '#FAFAD2': '浅金菊黄', '#D3D3D3': '浅灰色2', '#90EE90': '浅绿色', '#FFB6C1': '浅粉红', '#FFA07A': '浅鲑鱼色', '#20B2AA': '浅海绿', '#87CEFA': '浅天蓝', '#778899': '浅石板灰', '#B0C4DE': '浅钢蓝', '#FFFFE0': '浅黄色', '#32CD32': '酸橙绿', '#FAF0E6': '亚麻色', '#66CDAA': '中海绿', '#0000CD': '中蓝色', '#BA55D3': '中兰花紫', '#9370DB': '中紫色', '#3CB371': '中海春绿', '#7B68EE': '中石板蓝', '#00FA9A': '中春绿', '#48D1CC': '中绿松石', '#C71585': '中紫罗兰红', '#191970': '午夜蓝', '#F5FFFA': '薄荷奶油', '#FFDEAD': '那瓦霍白', '#FDF5E6': '老花边', '#6B8E23': '橄榄褐色', '#FF4500': '橙红色', '#DA70D6': '兰花紫', '#EEE8AA': '灰秋麒麟', '#98FB98': '灰绿色', '#AFEEEE': '灰绿松石', '#DB7093': '灰紫罗兰红', '#FFEFD5': '番木瓜鞭', '#FFDAB9': '桃扑', '#CD853F': '秘鲁色', '#FFC0CB': '粉红色', '#DDA0DD': '洋李色', '#B0E0E6': '粉蓝色', '#BC8F8F': '玫瑰棕色', '#4169E1': '皇家蓝', '#8B4513': '马鞍棕色', '#FA8072': '鲑鱼色', '#F4A460': '沙棕色', '#2E8B57': '海绿色', '#FFF5EE': '海贝色', '#A0522D': '赭色', '#87CEEB': '天蓝色', '#6A5ACD': '石板蓝', '#708090': '石板灰', '#FFFAFA': '雪色', '#00FF7F': '春绿色', '#4682B4': '钢蓝色', '#D2B48C': '棕褐色', '#D8BFD8': '蓟色', '#FF6347': '番茄色', '#40E0D0': '绿松石', '#EE82EE': '紫罗兰', '#F5DEB3': '小麦色', '#9ACD32': '黄绿色' }; // 如果找到精确匹配,返回对应名称 if (colorMap[hex.toUpperCase()]) { return colorMap[hex.toUpperCase()]; } // 否则根据RGB值判断颜色类型 const rgb = this.hexToRgb(hex); if (!rgb) return '未知颜色'; const { r, g, b } = rgb; const brightness = (r * 299 + g * 587 + b * 114) / 1000; // 判断是否为灰色系 const isGray = Math.abs(r - g) < 30 && Math.abs(g - b) < 30 && Math.abs(r - b) < 30; if (isGray) { if (brightness > 240) return '浅灰白'; if (brightness > 200) return '浅灰色'; if (brightness > 160) return '中灰色'; if (brightness > 120) return '深灰色'; if (brightness > 80) return '暗灰色'; return '深暗灰'; } // 判断主要颜色倾向 const max = Math.max(r, g, b); const min = Math.min(r, g, b); const saturation = max === 0 ? 0 : (max - min) / max; if (saturation < 0.2) { // 低饱和度,偏向灰色 if (brightness > 200) return '浅灰色'; if (brightness > 100) return '中灰色'; return '深灰色'; } // 高饱和度,判断色相 let colorName = ''; if (r >= g && r >= b) { if (g > b) { colorName = brightness > 150 ? '浅橙色' : '橙色'; } else { colorName = brightness > 150 ? '浅红色' : '红色'; } } else if (g >= r && g >= b) { if (r > b) { colorName = brightness > 150 ? '浅黄绿' : '黄绿色'; } else { colorName = brightness > 150 ? '浅绿色' : '绿色'; } } else { if (r > g) { colorName = brightness > 150 ? '浅紫色' : '紫色'; } else { colorName = brightness > 150 ? '浅蓝色' : '蓝色'; } } return colorName; } // 将十六进制颜色转换为RGB private hexToRgb(hex: string): { r: number; g: number; b: number } | null { const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex); return result ? { r: parseInt(result[1], 16), g: parseInt(result[2], 16), b: parseInt(result[3], 16) } : null; } // 复制颜色描述到剪贴板 async copyColorDescription(): Promise { const description = this.generateColorDescription(); if (!description) return; try { await navigator.clipboard.writeText(description); this.copySuccess = true; console.log('颜色描述已复制到剪贴板'); // 2秒后重置复制状态 setTimeout(() => { this.copySuccess = false; }, 2000); } catch (err) { console.error('复制失败:', err); // 降级方案:使用传统方法 this.fallbackCopyTextToClipboard(description); } } // 降级复制方案 private fallbackCopyTextToClipboard(text: string): void { const textArea = document.createElement('textarea'); textArea.value = text; textArea.style.top = '0'; textArea.style.left = '0'; textArea.style.position = 'fixed'; textArea.style.opacity = '0'; document.body.appendChild(textArea); textArea.focus(); textArea.select(); try { const successful = document.execCommand('copy'); if (successful) { this.copySuccess = true; console.log('颜色描述已复制到剪贴板(降级方案)'); // 2秒后重置复制状态 setTimeout(() => { this.copySuccess = false; }, 2000); } } catch (err) { console.error('降级复制方案也失败了:', err); } document.body.removeChild(textArea); } // 生成完整的HTML报告 private generateFullReport(): string { if (!this.analysisResult) return ''; const colors = this.analysisResult.colors; const colorDescription = this.generateColorDescription(); return ` 图片颜色分析完整报告

图片颜色分析报告

基于AI智能分析生成的详细颜色报告

颜色分析结果

${colors.map(color => `
${this.getColorName(color.hex)}
${color.hex}
${color.percentage}%
`).join('')}
${colors.length}
主要颜色数量
${colors[0]?.percentage || 0}%
主色占比
${colors.reduce((sum, c) => sum + c.percentage, 0).toFixed(1)}%
总覆盖率
${this.analysisResult.enhancedAnalysis ? `

增强色彩分析

色轮分析

色相分布

主色调: ${this.analysisResult.enhancedAnalysis.colorWheel.dominantHue}°
饱和度范围: ${this.analysisResult.enhancedAnalysis.colorWheel.saturationRange.min}% - ${this.analysisResult.enhancedAnalysis.colorWheel.saturationRange.max}%

色彩心理学

情绪: ${this.analysisResult.enhancedAnalysis.colorPsychology.mood}
氛围: ${this.analysisResult.enhancedAnalysis.colorPsychology.atmosphere}
${this.analysisResult.enhancedAnalysis.colorPsychology.suitableSpaces.map(space => `${space}`).join('')}
` : ''} ${this.analysisResult.formAnalysis ? `

形体分析

线条分析

主导线条: ${this.analysisResult.formAnalysis.lineAnalysis.dominantLineType}
视觉流动: ${this.analysisResult.formAnalysis.lineAnalysis.visualFlow}

整体评估

复杂度: ${this.analysisResult.formAnalysis.overallAssessment.complexity}%
视觉冲击: ${this.analysisResult.formAnalysis.overallAssessment.visualImpact}%
` : ''} ${this.analysisResult.textureAnalysis ? `

质感分析

表面属性

粗糙度: ${this.analysisResult.textureAnalysis.surfaceProperties.roughness}%
光泽度: ${this.analysisResult.textureAnalysis.surfaceProperties.glossiness}%

材质分类

主要材质:
${this.analysisResult.textureAnalysis.materialClassification.primaryMaterials.map((material: string) => `${material}`).join('')}
次要材质:
${this.analysisResult.textureAnalysis.materialClassification.secondaryMaterials.map((material: string) => `${material}`).join('')}
` : ''} ${this.analysisResult.patternAnalysis ? `

纹理分析

图案识别

主要图案: ${this.analysisResult.patternAnalysis.patternRecognition.primaryPatterns[0]?.type || '无'}
复杂度: ${this.analysisResult.patternAnalysis.patternRecognition.complexity}

视觉节奏

节奏类型: ${this.analysisResult.patternAnalysis.visualRhythm.rhythmType}
运动感: ${this.analysisResult.patternAnalysis.visualRhythm.movement}
` : ''} ${this.analysisResult.lightingAnalysis ? `

灯光分析

光源识别

interface RequirementMapping { sceneGeneration: { baseScene: string; // 固定场景模板 parameters: SceneParams; // 场景参数 atmospherePreview: string; // 氛围感预览图 }; parameterMapping: { colorParams: ColorMappingParams; spaceParams: SpaceMappingParams; materialParams: MaterialMappingParams; }; }interface RequirementMapping { sceneGeneration: { baseScene: string; // 固定场景模板 parameters: SceneParams; // 场景参数 atmospherePreview: string; // 氛围感预览图 }; parameterMapping: { colorParams: ColorMappingParams; spaceParams: SpaceMappingParams; materialParams: MaterialMappingParams; }; }interface RequirementMapping { sceneGeneration: { baseScene: string; // 固定场景模板 parameters: SceneParams; // 场景参数 atmospherePreview: string; // 氛围感预览图 }; parameterMapping: { colorParams: ColorMappingParams; spaceParams: SpaceMappingParams; materialParams: MaterialMappingParams; }; } 主要光源: ${this.analysisResult.lightingAnalysis.lightSourceIdentification.primarySources[0]?.type || '无'} - ${this.analysisResult.lightingAnalysis.lightSourceIdentification.primarySources[0]?.subtype || ''}
灯光复杂度: ${this.analysisResult.lightingAnalysis.lightSourceIdentification.lightingSetup.complexity}
灯光风格: ${this.analysisResult.lightingAnalysis.lightSourceIdentification.lightingSetup.lightingStyle}

环境分析

环境光强度: ${this.analysisResult.lightingAnalysis.ambientAnalysis.ambientLevel.strength}%
灯光情绪: ${this.analysisResult.lightingAnalysis.ambientAnalysis.lightingMood.primary}
情绪强度: ${this.analysisResult.lightingAnalysis.ambientAnalysis.lightingMood.intensity}%
` : ''}

颜色描述文字

${colorDescription}
`; } // 下载报告文件 private downloadReport(): void { if (!this.analysisResult) return; const reportHtml = this.generateFullReport(); const blob = new Blob([reportHtml], { type: 'text/html;charset=utf-8' }); const url = URL.createObjectURL(blob); const link = document.createElement('a'); link.href = url; link.download = `颜色分析报告_${new Date().toISOString().slice(0, 10)}.html`; document.body.appendChild(link); link.click(); document.body.removeChild(link); URL.revokeObjectURL(url); } private checkScreenSize(): void { const width = window.innerWidth; this.isMobile = width < 768; this.isTablet = width >= 768 && width < 1024; } private setupResizeListener(): void { // 可以添加更复杂的响应式逻辑 } // 获取质感分析属性数组,用于模板中的循环显示 getTextureProperties(): Array<{name: string, value: number}> { if (!this.analysisResult?.textureAnalysis?.surfaceProperties) { return []; } const properties = this.analysisResult.textureAnalysis.surfaceProperties; return [ { name: '粗糙度', value: properties.roughness?.value || 0 }, { name: '光泽度', value: properties.glossiness?.value || 0 }, { name: '透明度', value: properties.transparency?.value || 0 }, { name: '反射率', value: properties.reflectivity?.value || 0 } ]; } }