123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192 |
- import { Component, Input, Output, EventEmitter, OnInit, OnDestroy, ChangeDetectionStrategy, HostListener } from '@angular/core';
- import { CommonModule } from '@angular/common';
- import { ColorAnalysisService, AnalysisProgress } from '../../services/color-analysis.service';
- 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 ColorAnalysisResult {
- colors: Array<{ hex: string; rgb: { r: number; g: number; b: number }; percentage: number }>;
- reportUrl?: string;
- mosaicUrl?: 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;
- @Output() closeModal = new EventEmitter<void>();
- @Output() analyzeColors = new EventEmitter<UploadedFile[]>();
- @Output() viewReport = new EventEmitter<ColorAnalysisResult>();
- // 颜色分析状态
- isAnalyzing = false;
- analysisProgress: AnalysisProgress | null = null;
- analysisError: string | null = null;
-
- // 响应式状态
- isMobile = false;
- isTablet = false;
-
- // 动画状态
- animationState = 'idle';
- buttonHoverState = 'normal';
- private progressSubscription?: Subscription;
- private resizeSubscription?: Subscription;
- constructor(private colorAnalysisService: ColorAnalysisService) {}
- 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.isAnalyzing = true;
- this.analysisError = null;
- try {
- // 发射分析事件给父组件处理
- this.analyzeColors.emit(this.uploadedFiles);
-
- // 模拟分析过程(实际应该由父组件处理并返回结果)
- await this.simulateAnalysis();
-
- } catch (error) {
- this.analysisError = '颜色分析失败,请重试';
- console.error('Color analysis error:', error);
- } finally {
- this.isAnalyzing = false;
- }
- }
- // 模拟分析过程
- private async simulateAnalysis(): Promise<void> {
- 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 }
- ],
- reportUrl: '/assets/reports/color-analysis-report.html',
- mosaicUrl: '/assets/reports/mosaic-image.png'
- };
- resolve();
- }, 2000);
- });
- }
- // 事件处理方法
- 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) {
- 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/'));
- }
- private checkScreenSize() {
- const width = window.innerWidth;
- this.isMobile = width < 768;
- this.isTablet = width >= 768 && width < 1024;
- }
- private setupResizeListener() {
- // 可以添加更复杂的响应式逻辑
- }
- }
|