Browse Source

fix: requirements with ai analysis

ryanemax 1 day ago
parent
commit
4d22bb42db

+ 364 - 15
src/modules/project/pages/project-detail/stages/stage-requirements.component.html

@@ -18,11 +18,11 @@
           @for (product of projectProducts; track product.id) {
             <button
               class="space-tab"
-              [class.active]="activeProductId === product.id"
+              [class.active]="activeProductId == product.id"
               (click)="selectProduct(product.id)">
               <span class="space-icon">{{ getSpaceIcon(product.type) }}</span>
               <span>{{ getProductDisplayName(product) }}</span>
-              <span class="progress-indicator" [style.width.%]="calculateProductCompletion(product.id)"></span>
+              <span class="progress-indicator" [style.width]="calculateProductCompletion(product.id) + '%'"></span>
             </button>
           }
         </div>
@@ -34,20 +34,20 @@
       <div class="segment-buttons">
         <button
           class="segment-btn"
-          [class.active]="requirementsSegment === 'global'"
+          [class.active]="requirementsSegment == 'global'"
           (click)="selectRequirementsSegment('global')">
           全局需求
         </button>
         @if (isMultiProductProject) {
           <button
             class="segment-btn"
-            [class.active]="requirementsSegment === 'spaces'"
+            [class.active]="requirementsSegment == 'spaces'"
             (click)="selectRequirementsSegment('spaces')">
             产品需求
           </button>
           <button
             class="segment-btn"
-            [class.active]="requirementsSegment === 'cross-space'"
+            [class.active]="requirementsSegment == 'cross-space'"
             (click)="selectRequirementsSegment('cross-space')">
             跨产品协调
           </button>
@@ -56,7 +56,7 @@
     </div>
 
     <!-- 全局需求 -->
-    @if (requirementsSegment === 'global') {
+    @if (requirementsSegment == 'global') {
       <div class="global-requirements">
         <!-- 参考图片 -->
         <div class="card reference-images-card">
@@ -66,8 +66,91 @@
               参考图片
             </h3>
             <p class="card-subtitle">上传风格、空间或材质参考图</p>
+            <div class="ai-analysis-actions">
+              @if (referenceImages.length > 0 && canEdit) {
+                <button
+                  class="btn btn-sm btn-primary"
+                  (click)="analyzeReferenceImages()"
+                  [disabled]="aiAnalyzingImages">
+                  @if (aiAnalyzingImages) {
+                    <div class="spinner-small">
+                      <div class="spinner-circle"></div>
+                    </div>
+                    AI分析中...
+                  } @else {
+                    <ion-icon name="sparkles"></ion-icon>
+                    AI分析图片
+                  }
+                </button>
+              }
+            </div>
           </div>
           <div class="card-content">
+            <!-- AI图片分析结果 -->
+            @if (aiAnalysisResults.imageAnalysis && aiAnalysisResults.imageAnalysis.length > 0) {
+              <div class="ai-analysis-results">
+                <div class="analysis-header">
+                  <span class="badge badge-success">
+                    <ion-icon name="checkmark-circle"></ion-icon>
+                    AI分析完成
+                  </span>
+                </div>
+                <div class="analysis-grid">
+                  @for (analysis of aiAnalysisResults.imageAnalysis; track analysis.imageId) {
+                    
+                    @if (analysisImageMap[analysis.imageId]) {
+                      <div class="analysis-item">
+                        <div class="analysis-image">
+                          <img [src]="analysisImageMap[analysis.imageId]?.url" [alt]="analysisImageMap[analysis.imageId]?.name" />
+                          <div class="confidence-badge">
+                            <span>AI识别置信度: {{ (analysis.confidence * 100).toFixed(1) }}%</span>
+                          </div>
+                        </div>
+                        <div class="analysis-content">
+                          <div class="analysis-section">
+                            <h5>风格元素</h5>
+                            <div class="tags">
+                              @for (element of analysis.styleElements; track $index) {
+                                <span class="badge badge-secondary">{{ element }}</span>
+                              }
+                            </div>
+                          </div>
+                          <div class="analysis-section">
+                            <h5>色彩搭配</h5>
+                            <div class="color-palette">
+                              @for (color of analysis.colorPalette; track $index) {
+                                <div class="color-swatch" [style.background-color]="color" [title]="color"></div>
+                              }
+                            </div>
+                          </div>
+                          <div class="analysis-section">
+                            <h5>材质分析</h5>
+                            <div class="tags">
+                              @for (material of analysis.materialAnalysis; track $index) {
+                                <span class="badge badge-tertiary">{{ material }}</span>
+                              }
+                            </div>
+                          </div>
+                          <div class="analysis-section">
+                            <h5>布局特征</h5>
+                            <div class="tags">
+                              @for (feature of analysis.layoutFeatures; track $index) {
+                                <span class="badge badge-outline">{{ feature }}</span>
+                              }
+                            </div>
+                          </div>
+                          <div class="analysis-section">
+                            <h5>空间氛围</h5>
+                            <p>{{ analysis.mood }}</p>
+                          </div>
+                        </div>
+                      </div>
+                    }
+                  }
+                </div>
+              </div>
+            }
+
             <div class="images-grid">
               @for (image of getFilteredReferenceImages(); track image.id) {
                 <div class="image-item">
@@ -79,6 +162,12 @@
                     @if (image.spaceId) {
                       <span class="badge badge-outline">{{ getProductDisplayNameById(image.spaceId || '') }}</span>
                     }
+                    @if (aiAnalysisResults.imageAnalysis?.find(a => a.imageId == image.id)) {
+                      <span class="badge badge-success">
+                        <ion-icon name="sparkles"></ion-icon>
+                        已分析
+                      </span>
+                    }
                     @if (canEdit) {
                       <button
                         class="btn-icon btn-danger"
@@ -121,9 +210,107 @@
               CAD文件
             </h3>
             <p class="card-subtitle">上传户型图或施工图纸</p>
+            <div class="ai-analysis-actions">
+              @if (cadFiles.length > 0 && canEdit) {
+                <button
+                  class="btn btn-sm btn-primary"
+                  (click)="analyzeCADFiles()"
+                  [disabled]="aiAnalyzingCAD">
+                  @if (aiAnalyzingCAD) {
+                    <div class="spinner-small">
+                      <div class="spinner-circle"></div>
+                    </div>
+                    AI分析中...
+                  } @else {
+                    <ion-icon name="sparkles"></ion-icon>
+                    AI分析CAD
+                  }
+                </button>
+              }
+            </div>
           </div>
           <div class="card-content">
-            @if (getFilteredCADFiles().length === 0) {
+            <!-- AI CAD分析结果 -->
+            @if (aiAnalysisResults.cadAnalysis && aiAnalysisResults.cadAnalysis.length > 0) {
+              <div class="ai-analysis-results">
+                <div class="analysis-header">
+                  <span class="badge badge-success">
+                    <ion-icon name="checkmark-circle"></ion-icon>
+                    CAD分析完成
+                  </span>
+                </div>
+                <div class="cad-analysis-grid">
+                  @for (analysis of aiAnalysisResults.cadAnalysis; track analysis.fileId) {
+
+                    @if (analysisFileMap[analysis.fileId]) {
+                      <div class="cad-analysis-item">
+                        <div class="cad-file-info">
+                          <ion-icon name="document-text" class="file-icon"></ion-icon>
+                          <div class="file-details">
+                            <h4>{{ analysisFileMap[analysis.fileId]?.name }}</h4>
+                            <p>{{ formatFileSize(analysisFileMap[analysis.fileId]?.size || 0) }}</p>
+                          </div>
+                        </div>
+                        <div class="cad-analysis-content">
+                          <div class="analysis-section">
+                            <h5>空间结构</h5>
+                            <div class="structure-info">
+                              <div class="info-item">
+                                <span class="label">总面积:</span>
+                                <span class="value">{{ analysis.spaceStructure.totalArea }}</span>
+                              </div>
+                              <div class="info-item">
+                                <span class="label">房间数量:</span>
+                                <span class="value">{{ analysis.spaceStructure.roomCount }}</span>
+                              </div>
+                              <div class="info-item">
+                                <span class="label">布局类型:</span>
+                                <span class="value">{{ analysis.spaceStructure.layoutType }}</span>
+                              </div>
+                            </div>
+                          </div>
+                          <div class="analysis-section">
+                            <h5>尺寸信息</h5>
+                            <div class="dimensions-info">
+                              <div class="info-item">
+                                <span class="label">长度:</span>
+                                <span class="value">{{ analysis.dimensions.length }}</span>
+                              </div>
+                              <div class="info-item">
+                                <span class="label">宽度:</span>
+                                <span class="value">{{ analysis.dimensions.width }}</span>
+                              </div>
+                              <div class="info-item">
+                                <span class="label">层高:</span>
+                                <span class="value">{{ analysis.dimensions.height }}</span>
+                              </div>
+                            </div>
+                          </div>
+                          <div class="analysis-section">
+                            <h5>限制因素</h5>
+                            <div class="tags">
+                              @for (constraint of analysis.constraints; track $index) {
+                                <span class="badge badge-warning">{{ constraint }}</span>
+                              }
+                            </div>
+                          </div>
+                          <div class="analysis-section">
+                            <h5>优化机会</h5>
+                            <div class="tags">
+                              @for (opportunity of analysis.opportunities; track $index) {
+                                <span class="badge badge-success">{{ opportunity }}</span>
+                              }
+                            </div>
+                          </div>
+                        </div>
+                      </div>
+                    }
+                  }
+                </div>
+              </div>
+            }
+
+            @if (getFilteredCADFiles().length == 0) {
               <div class="empty-state">
                 <ion-icon name="document-outline" class="icon-large"></ion-icon>
                 <p>暂无CAD文件</p>
@@ -139,6 +326,12 @@
                       @if (file.spaceId) {
                         <span class="badge badge-outline">{{ getProductDisplayNameById(file.spaceId || '') }}</span>
                       }
+                      @if (aiAnalysisResults.cadAnalysis?.find(a => a.fileId == file.id)) {
+                        <span class="badge badge-success">
+                          <ion-icon name="sparkles"></ion-icon>
+                          已分析
+                        </span>
+                      }
                     </div>
                     @if (canEdit) {
                       <button
@@ -314,10 +507,10 @@
     }
 
     <!-- 空间需求 -->
-    @if (requirementsSegment === 'spaces' && isMultiProductProject) {
+    @if (requirementsSegment == 'spaces' && isMultiProductProject) {
       <div class="space-requirements">
         @for (space of projectProducts; track space.id) {
-          <div class="card space-requirement-card" [class.active]="activeProductId === space.id">
+          <div class="card space-requirement-card" [class.active]="activeProductId == space.id">
             <div class="card-header">
               <h3 class="card-title">
                 <span class="space-icon">{{ getSpaceIcon(space.type) }}</span>
@@ -383,7 +576,7 @@
     }
 
     <!-- 跨空间协调需求 -->
-    @if (requirementsSegment === 'cross-space' && isMultiProductProject) {
+    @if (requirementsSegment == 'cross-space' && isMultiProductProject) {
       <div class="cross-space-requirements">
         <div class="card">
           <div class="card-header">
@@ -397,7 +590,7 @@
             </button>
           </div>
           <div class="card-content">
-            @if (crossSpaceRequirements.length === 0) {
+            @if (crossSpaceRequirements.length == 0) {
               <div class="empty-state">
                 <ion-icon name="links-outline" class="icon-large"></ion-icon>
                 <p>暂无跨空间协调需求</p>
@@ -434,6 +627,97 @@
       </div>
     }
 
+    <!-- 综合AI分析 -->
+    @if (aiAnalysisResults.comprehensiveAnalysis) {
+      <div class="card comprehensive-analysis-card">
+        <div class="card-header">
+          <h3 class="card-title">
+            <ion-icon name="analytics"></ion-icon>
+            综合AI分析
+          </h3>
+          <span class="badge badge-success">
+            <ion-icon name="checkmark-circle"></ion-icon>
+            分析完成
+          </span>
+        </div>
+        <div class="card-content">
+          <div class="comprehensive-analysis-content">
+            <!-- 整体风格 -->
+            <div class="analysis-section">
+              <h4>整体风格定位</h4>
+              <p>{{ aiAnalysisResults.comprehensiveAnalysis.overallStyle }}</p>
+            </div>
+
+            <!-- AI推荐色彩方案 -->
+            <div class="analysis-section">
+              <h4>AI推荐色彩方案</h4>
+              <div class="ai-color-scheme">
+                <div class="color-item">
+                  <div class="color-swatch" [style.background-color]="aiAnalysisResults.comprehensiveAnalysis.colorScheme.primary" [title]="aiAnalysisResults.comprehensiveAnalysis.colorScheme.primary"></div>
+                  <span class="color-label">主色调</span>
+                </div>
+                <div class="color-item">
+                  <div class="color-swatch" [style.background-color]="aiAnalysisResults.comprehensiveAnalysis.colorScheme.secondary" [title]="aiAnalysisResults.comprehensiveAnalysis.colorScheme.secondary"></div>
+                  <span class="color-label">副色调</span>
+                </div>
+                <div class="color-item">
+                  <div class="color-swatch" [style.background-color]="aiAnalysisResults.comprehensiveAnalysis.colorScheme.accent" [title]="aiAnalysisResults.comprehensiveAnalysis.colorScheme.accent"></div>
+                  <span class="color-label">点缀色</span>
+                </div>
+              </div>
+            </div>
+
+            <!-- 材质推荐 -->
+            <div class="analysis-section">
+              <h4>AI材质推荐</h4>
+              <div class="tags">
+                @for (material of aiAnalysisResults.comprehensiveAnalysis.materialRecommendations; track $index) {
+                  <span class="badge badge-tertiary">{{ material }}</span>
+                }
+              </div>
+            </div>
+
+            <!-- 布局优化建议 -->
+            <div class="analysis-section">
+              <h4>布局优化建议</h4>
+              <ul class="optimization-list">
+                @for (optimization of aiAnalysisResults.comprehensiveAnalysis.layoutOptimization; track $index) {
+                  <li>{{ optimization }}</li>
+                }
+              </ul>
+            </div>
+
+            <!-- AI预算评估 -->
+            <div class="analysis-section">
+              <h4>AI预算评估</h4>
+              <div class="budget-assessment">
+                <div class="budget-range">
+                  <span class="label">预估范围:</span>
+                  <span class="value">¥{{ aiAnalysisResults.comprehensiveAnalysis.budgetAssessment.estimatedMin?.toLocaleString() }} - ¥{{ aiAnalysisResults.comprehensiveAnalysis.budgetAssessment.estimatedMax?.toLocaleString() }}</span>
+                </div>
+                <div class="risk-level">
+                  <span class="label">风险等级:</span>
+                  <span class="badge" [class]="getRiskLevelClass(aiAnalysisResults.comprehensiveAnalysis.budgetAssessment.riskLevel)">
+                    {{ getRiskLevelName(aiAnalysisResults.comprehensiveAnalysis.budgetAssessment.riskLevel) }}
+                  </span>
+                </div>
+              </div>
+            </div>
+
+            <!-- 风险因素 -->
+            <div class="analysis-section">
+              <h4>潜在风险因素</h4>
+              <div class="tags">
+                @for (risk of aiAnalysisResults.comprehensiveAnalysis.riskFactors; track $index) {
+                  <span class="badge badge-warning">{{ risk }}</span>
+                }
+              </div>
+            </div>
+          </div>
+        </div>
+      </div>
+    }
+
     <!-- AI生成方案 -->
     <div class="card ai-solution-card">
       <div class="card-header">
@@ -444,7 +728,7 @@
         <div class="completion-indicator">
           <span class="label">需求完成度</span>
           <div class="progress-bar">
-            <div class="progress-fill" [style.width.%]="calculateRequirementsCompleteness()"></div>
+            <div class="progress-fill" [style.width]="calculateRequirementsCompleteness() + '%'"></div>
           </div>
           <span class="progress-text">{{ calculateRequirementsCompleteness() }}%</span>
         </div>
@@ -458,8 +742,8 @@
               <button
                 class="btn btn-primary"
                 (click)="generateAISolution()"
-                [disabled]="generating">
-                @if (generating) {
+                [disabled]="generating || aiGeneratingComprehensive">
+                @if (generating || aiGeneratingComprehensive) {
                   <div class="spinner-small">
                     <div class="spinner-circle"></div>
                   </div>
@@ -482,7 +766,7 @@
                 <button
                   class="btn btn-outline btn-sm"
                   (click)="generateAISolution()"
-                  [disabled]="generating">
+                  [disabled]="generating || aiGeneratingComprehensive">
                   <ion-icon name="refresh"></ion-icon>
                   重新生成
                 </button>
@@ -598,6 +882,71 @@
       </div>
     </div>
 
+    <!-- AI聊天助手 -->
+    <div class="card ai-chat-card">
+      <div class="card-header">
+        <h3 class="card-title">
+          <ion-icon name="chatbubbles"></ion-icon>
+          AI设计助手
+        </h3>
+        <button
+          class="btn btn-sm btn-outline"
+          (click)="toggleAIChat()">
+          <ion-icon [name]="showAIChat ? 'chevron-up' : 'chevron-down'"></ion-icon>
+          {{ showAIChat ? '收起' : '展开' }}
+        </button>
+      </div>
+      @if (showAIChat) {
+        <div class="card-content">
+          <div class="ai-chat-container">
+            <!-- 聊天消息列表 -->
+            <div class="chat-messages" #chatMessages>
+              @for (message of aiChatMessages; track message.id) {
+                <div class="message" [class.user-message]="message.role == 'user'" [class.ai-message]="message.role == 'assistant'">
+                  <div class="message-avatar">
+                    @if (message.role == 'user') {
+                      <ion-icon name="person-circle"></ion-icon>
+                    } @else {
+                      <ion-icon name="sparkles"></ion-icon>
+                    }
+                  </div>
+                  <div class="message-content">
+                    <div class="message-text">{{ message.content }}</div>
+                    <div class="message-time">{{ message.timestamp | date:'HH:mm' }}</div>
+                  </div>
+                </div>
+              }
+              @if (aiChatMessages.length == 0) {
+                <div class="empty-chat">
+                  <ion-icon name="chatbubble-ellipses-outline" class="icon-large"></ion-icon>
+                  <p>向AI设计助手咨询任何家装问题</p>
+                </div>
+              }
+            </div>
+
+            <!-- 输入区域 -->
+            <div class="chat-input">
+              <div class="input-group">
+                <input
+                  type="text"
+                  class="form-input"
+                  [(ngModel)]="aiChatInput"
+                  (keydown.enter)="sendAIChatMessage()"
+                  placeholder="询问家装设计相关问题..."
+                  [disabled]="aiAnalyzing" />
+                <button
+                  class="btn btn-primary"
+                  (click)="sendAIChatMessage()"
+                  [disabled]="!aiChatInput.trim() || aiAnalyzing">
+                  <ion-icon name="send"></ion-icon>
+                </button>
+              </div>
+            </div>
+          </div>
+        </div>
+      }
+    </div>
+
     <!-- 操作按钮 -->
     @if (canEdit) {
       <div class="action-buttons">

+ 540 - 0
src/modules/project/pages/project-detail/stages/stage-requirements.component.scss

@@ -291,6 +291,546 @@
     }
   }
 
+  // AI分析操作区域
+  .ai-analysis-actions {
+    display: flex;
+    gap: 8px;
+    align-items: center;
+
+    .btn {
+      .spinner-small {
+        margin-right: 4px;
+      }
+    }
+  }
+
+  // AI分析结果
+  .ai-analysis-results {
+    margin-bottom: 20px;
+
+    .analysis-header {
+      display: flex;
+      justify-content: space-between;
+      align-items: center;
+      margin-bottom: 16px;
+      padding-bottom: 8px;
+      border-bottom: 1px solid var(--light-shade);
+
+      .badge {
+        display: flex;
+        align-items: center;
+        gap: 4px;
+        font-size: 12px;
+        padding: 6px 12px;
+
+        .icon, .space-icon {
+          font-size: 14px;
+        }
+      }
+    }
+
+    .analysis-grid {
+      display: grid;
+      gap: 16px;
+
+      .analysis-item {
+        display: grid;
+        grid-template-columns: 200px 1fr;
+        gap: 16px;
+        padding: 16px;
+        background: linear-gradient(135deg, rgba(var(--primary-rgb), 0.03), rgba(12, 209, 232, 0.03));
+        border-radius: 12px;
+        border: 1px solid rgba(var(--primary-rgb), 0.1);
+
+        .analysis-image {
+          position: relative;
+          border-radius: 8px;
+          overflow: hidden;
+          box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
+
+          img {
+            width: 100%;
+            height: 150px;
+            object-fit: cover;
+          }
+
+          .confidence-badge {
+            position: absolute;
+            top: 8px;
+            right: 8px;
+            background: rgba(0, 0, 0, 0.8);
+            color: white;
+            padding: 4px 8px;
+            border-radius: 12px;
+            font-size: 10px;
+            font-weight: 600;
+          }
+        }
+
+        .analysis-content {
+          display: flex;
+          flex-direction: column;
+          gap: 12px;
+
+          .analysis-section {
+            h5 {
+              margin: 0 0 8px;
+              font-size: 13px;
+              font-weight: 600;
+              color: var(--dark-color);
+              display: flex;
+              align-items: center;
+              gap: 6px;
+
+              &::before {
+                content: '';
+                width: 3px;
+                height: 14px;
+                background: var(--primary-color);
+                border-radius: 2px;
+              }
+            }
+
+            p {
+              margin: 0;
+              font-size: 12px;
+              line-height: 1.5;
+              color: var(--medium-color);
+            }
+
+            .color-palette {
+              display: flex;
+              gap: 6px;
+              flex-wrap: wrap;
+
+              .color-swatch {
+                width: 24px;
+                height: 24px;
+                border-radius: 4px;
+                border: 1px solid rgba(0, 0, 0, 0.1);
+                box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
+                cursor: pointer;
+                transition: transform 0.2s;
+
+                &:hover {
+                  transform: scale(1.1);
+                }
+              }
+            }
+
+            .tags {
+              display: flex;
+              flex-wrap: wrap;
+              gap: 6px;
+
+              .badge {
+                font-size: 10px;
+                padding: 3px 8px;
+              }
+            }
+          }
+        }
+      }
+    }
+
+    .cad-analysis-grid {
+      display: grid;
+      gap: 16px;
+
+      .cad-analysis-item {
+        padding: 16px;
+        background: linear-gradient(135deg, rgba(var(--tertiary-rgb), 0.03), rgba(45, 211, 111, 0.03));
+        border-radius: 12px;
+        border: 1px solid rgba(var(--tertiary-rgb), 0.1);
+
+        .cad-file-info {
+          display: flex;
+          align-items: center;
+          gap: 12px;
+          margin-bottom: 16px;
+          padding-bottom: 12px;
+          border-bottom: 1px solid var(--light-shade);
+
+          .file-icon {
+            font-size: 32px;
+            color: var(--tertiary-color);
+          }
+
+          .file-details {
+            flex: 1;
+
+            h4 {
+              margin: 0 0 4px;
+              font-size: 15px;
+              font-weight: 600;
+              color: var(--dark-color);
+            }
+
+            p {
+              margin: 0;
+              font-size: 12px;
+              color: var(--medium-color);
+            }
+          }
+        }
+
+        .cad-analysis-content {
+          display: grid;
+          gap: 16px;
+
+          .analysis-section {
+            h5 {
+              margin: 0 0 8px;
+              font-size: 13px;
+              font-weight: 600;
+              color: var(--dark-color);
+              display: flex;
+              align-items: center;
+              gap: 6px;
+
+              &::before {
+                content: '';
+                width: 3px;
+                height: 14px;
+                background: var(--tertiary-color);
+                border-radius: 2px;
+              }
+            }
+
+            .structure-info,
+            .dimensions-info {
+              display: grid;
+              grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
+              gap: 8px;
+
+              .info-item {
+                display: flex;
+                align-items: center;
+                gap: 8px;
+
+                .label {
+                  font-size: 12px;
+                  color: var(--medium-color);
+                  font-weight: 500;
+                }
+
+                .value {
+                  font-size: 13px;
+                  color: var(--dark-color);
+                  font-weight: 600;
+                }
+              }
+            }
+
+            .tags {
+              display: flex;
+              flex-wrap: wrap;
+              gap: 6px;
+
+              .badge {
+                font-size: 10px;
+                padding: 3px 8px;
+              }
+            }
+          }
+        }
+      }
+    }
+  }
+
+  // 综合AI分析卡片
+  .comprehensive-analysis-card {
+    border: 2px solid rgba(var(--success-rgb), 0.2);
+    box-shadow: 0 4px 16px rgba(45, 211, 111, 0.1);
+
+    .comprehensive-analysis-content {
+      .analysis-section {
+        margin-bottom: 20px;
+        padding-bottom: 16px;
+        border-bottom: 1px solid var(--light-shade);
+
+        &:last-child {
+          margin-bottom: 0;
+          padding-bottom: 0;
+          border-bottom: none;
+        }
+
+        h4 {
+          margin: 0 0 12px;
+          font-size: 15px;
+          font-weight: 600;
+          color: var(--dark-color);
+          display: flex;
+          align-items: center;
+          gap: 8px;
+
+          &::before {
+            content: '';
+            width: 4px;
+            height: 16px;
+            background: var(--success-color);
+            border-radius: 2px;
+          }
+        }
+
+        p {
+          margin: 0;
+          font-size: 14px;
+          line-height: 1.6;
+          color: var(--dark-color);
+        }
+
+        .ai-color-scheme {
+          display: flex;
+          gap: 16px;
+          align-items: center;
+          padding: 12px;
+          background: linear-gradient(135deg, rgba(var(--success-rgb), 0.05), rgba(112, 68, 255, 0.05));
+          border-radius: 8px;
+
+          .color-item {
+            display: flex;
+            flex-direction: column;
+            align-items: center;
+            gap: 8px;
+
+            .color-swatch {
+              width: 48px;
+              height: 48px;
+              border-radius: 8px;
+              border: 2px solid white;
+              box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
+              cursor: pointer;
+              transition: transform 0.2s;
+
+              &:hover {
+                transform: scale(1.05);
+              }
+            }
+
+            .color-label {
+              font-size: 11px;
+              color: var(--medium-color);
+              font-weight: 500;
+            }
+          }
+        }
+
+        .optimization-list {
+          margin: 0;
+          padding-left: 20px;
+
+          li {
+            margin-bottom: 6px;
+            font-size: 13px;
+            line-height: 1.5;
+            color: var(--dark-color);
+
+            &:last-child {
+              margin-bottom: 0;
+            }
+
+            &::marker {
+              color: var(--success-color);
+            }
+          }
+        }
+
+        .budget-assessment {
+          display: grid;
+          grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
+          gap: 16px;
+
+          .budget-range,
+          .risk-level {
+            display: flex;
+            align-items: center;
+            gap: 8px;
+
+            .label {
+              font-size: 12px;
+              color: var(--medium-color);
+              font-weight: 500;
+            }
+
+            .value {
+              font-size: 14px;
+              color: var(--dark-color);
+              font-weight: 600;
+            }
+
+            .badge {
+              font-size: 10px;
+              padding: 4px 8px;
+            }
+          }
+        }
+      }
+    }
+  }
+
+  // AI聊天卡片
+  .ai-chat-card {
+    .ai-chat-container {
+      display: flex;
+      flex-direction: column;
+      height: 400px;
+
+      .chat-messages {
+        flex: 1;
+        overflow-y: auto;
+        padding: 16px;
+        background: var(--light-color);
+        border-radius: 8px;
+        margin-bottom: 12px;
+
+        &::-webkit-scrollbar {
+          width: 4px;
+        }
+
+        &::-webkit-scrollbar-track {
+          background: transparent;
+        }
+
+        &::-webkit-scrollbar-thumb {
+          background: var(--medium-color);
+          border-radius: 2px;
+        }
+
+        .message {
+          display: flex;
+          gap: 12px;
+          margin-bottom: 16px;
+
+          &:last-child {
+            margin-bottom: 0;
+          }
+
+          &.user-message {
+            flex-direction: row-reverse;
+
+            .message-avatar {
+              .icon, .space-icon {
+                color: var(--primary-color);
+              }
+            }
+
+            .message-content {
+              background: var(--primary-color);
+              color: white;
+            }
+          }
+
+          &.ai-message {
+            .message-avatar {
+              .icon, .space-icon {
+                color: var(--success-color);
+              }
+            }
+
+            .message-content {
+              background: white;
+              color: var(--dark-color);
+              border: 1px solid var(--light-shade);
+            }
+          }
+
+          .message-avatar {
+            flex-shrink: 0;
+            width: 32px;
+            height: 32px;
+            display: flex;
+            align-items: center;
+            justify-content: center;
+
+            .icon, .space-icon {
+              font-size: 24px;
+            }
+          }
+
+          .message-content {
+            flex: 1;
+            max-width: 70%;
+            padding: 12px 16px;
+            border-radius: 16px;
+            word-wrap: break-word;
+
+            .message-text {
+              font-size: 13px;
+              line-height: 1.5;
+              margin-bottom: 4px;
+            }
+
+            .message-time {
+              font-size: 10px;
+              opacity: 0.7;
+            }
+          }
+        }
+
+        .empty-chat {
+          display: flex;
+          flex-direction: column;
+          align-items: center;
+          justify-content: center;
+          height: 100%;
+          text-align: center;
+
+          .icon-large {
+            font-size: 48px;
+            color: var(--medium-color);
+            margin-bottom: 12px;
+            opacity: 0.5;
+          }
+
+          p {
+            color: var(--medium-color);
+            margin: 0;
+            font-size: 13px;
+          }
+        }
+      }
+
+      .chat-input {
+        .input-group {
+          display: flex;
+          gap: 8px;
+
+          .form-input {
+            flex: 1;
+            padding: 12px 16px;
+            border: 1px solid var(--light-shade);
+            border-radius: 24px;
+            font-size: 13px;
+            background: white;
+
+            &:focus {
+              outline: none;
+              border-color: var(--primary-color);
+              box-shadow: 0 0 0 3px rgba(var(--primary-rgb), 0.1);
+            }
+
+            &::placeholder {
+              color: var(--medium-color);
+            }
+          }
+
+          .btn {
+            width: 48px;
+            height: 48px;
+            border-radius: 50%;
+            padding: 0;
+            flex-shrink: 0;
+
+            .icon, .space-icon {
+              font-size: 20px;
+            }
+          }
+        }
+      }
+    }
+  }
+
   // 参考图片卡片
   .reference-images-card {
     .images-grid {

+ 553 - 37
src/modules/project/pages/project-detail/stages/stage-requirements.component.ts

@@ -1,9 +1,10 @@
-import { Component, OnInit, Input, ChangeDetectionStrategy, ChangeDetectorRef } from '@angular/core';
+import { Component, OnInit, Input, ChangeDetectionStrategy, ChangeDetectorRef, ViewChild, ElementRef } from '@angular/core';
 import { CommonModule } from '@angular/common';
 import { FormsModule, ReactiveFormsModule } from '@angular/forms';
 import { ActivatedRoute } from '@angular/router';
 import { IonIcon } from '@ionic/angular/standalone';
 import { ProductSpaceService, Project } from '../../../services/product-space.service';
+import { completionJSON } from 'fmode-ng';
 
 /**
  * 确认需求阶段组件 - Product表统一空间管理
@@ -120,12 +121,64 @@ export class StageRequirementsComponent implements OnInit {
     };
   } | null = null;
 
+  // AI分析相关数据
+  aiAnalysisResults: {
+    imageAnalysis?: Array<{
+      imageId: string;
+      styleElements: string[];
+      colorPalette: string[];
+      materialAnalysis: string[];
+      layoutFeatures: string[];
+      mood: string;
+      confidence: number;
+    }>;
+    cadAnalysis?: Array<{
+      fileId: string;
+      spaceStructure: any;
+      dimensions: any;
+      constraints: string[];
+      opportunities: string[];
+    }>;
+    comprehensiveAnalysis?: {
+      overallStyle: string;
+      colorScheme: any;
+      materialRecommendations: string[];
+      layoutOptimization: string[];
+      budgetAssessment: any;
+      timeline: string;
+      riskFactors: string[];
+    };
+  } = {};
+
+  // AI聊天相关
+  aiChatMessages: Array<{
+    id: string;
+    role: 'user' | 'assistant';
+    content: string;
+    timestamp: Date;
+    analysisType?: string;
+  }> = [];
+
+  // AI分析状态
+  aiAnalyzing: boolean = false;
+  aiAnalyzingImages: boolean = false;
+  aiAnalyzingCAD: boolean = false;
+  aiGeneratingComprehensive: boolean = false;
+  showAIChat: boolean = false;
+  aiChatInput: string = '';
+
+  // AI分析配置
+  private readonly AI_MODEL = 'fmode-1.6-cn';
+
   // 加载状态
   loading: boolean = true;
   uploading: boolean = false;
   generating: boolean = false;
   saving: boolean = false;
 
+  // 模板引用变量
+  @ViewChild('chatMessages') chatMessagesContainer!: ElementRef;
+
   constructor(
     private route: ActivatedRoute,
     private cdr: ChangeDetectorRef,
@@ -277,6 +330,7 @@ export class StageRequirementsComponent implements OnInit {
         };
 
         // 添加到参考图片列表
+        this.analysisImageMap[uploadedFile?.id] = uploadedFile
         this.referenceImages.push(uploadedFile);
       }
 
@@ -289,6 +343,7 @@ export class StageRequirementsComponent implements OnInit {
     }
   }
 
+  analysisImageMap:any = {}
   /**
    * 删除参考图片
    */
@@ -376,24 +431,17 @@ export class StageRequirementsComponent implements OnInit {
     try {
       this.generating = true;
 
-      // 模拟AI方案生成
+      // 先进行AI分析,再生成方案
+      await this.performComprehensiveAIAnalysis();
+
+      // 基于AI分析结果生成方案
       this.aiSolution = {
         generated: true,
-        content: `基于您的${this.globalRequirements.stylePreference}风格需求,我们为您设计了以下方案...`,
-        spaces: this.projectProducts.map(product => ({
-          id: product.id,
-          name: product.name,
-          type: product.type,
-          styleDescription: `${this.globalRequirements.stylePreference}风格${product.name}设计`,
-          colorPalette: [this.globalRequirements.colorScheme.primary, this.globalRequirements.colorScheme.secondary, this.globalRequirements.colorScheme.accent],
-          materials: ['实木', '大理石', '布艺'],
-          furnitureRecommendations: this.getFurnitureRecommendations(product.type),
-          estimatedCost: this.calculateProductEstimatedCost(product),
-          timeline: this.calculateProductTimeline(product)
-        })),
-        estimatedCost: this.globalRequirements.overallBudget.max || this.calculateTotalEstimatedCost(),
-        timeline: this.calculateTotalTimeline(),
-        crossSpaceCoordination: this.generateCrossSpaceCoordination()
+        content: this.generateSolutionContent(),
+        spaces: this.generateSpaceSolutions(),
+        estimatedCost: this.calculateAIEnhancedEstimatedCost(),
+        timeline: this.calculateAIEnhancedTimeline(),
+        crossSpaceCoordination: this.generateAICrossSpaceCoordination()
       };
 
       this.cdr.markForCheck();
@@ -405,6 +453,453 @@ export class StageRequirementsComponent implements OnInit {
     }
   }
 
+  /**
+   * AI分析参考图片
+   */
+  async analyzeReferenceImages(): Promise<void> {
+    if (this.referenceImages.length === 0) return;
+
+    try {
+      this.aiAnalyzingImages = true;
+      this.aiAnalysisResults.imageAnalysis = [];
+
+      for (const image of this.referenceImages) {
+        const analysisResult = await this.analyzeImage(image);
+        this.aiAnalysisResults.imageAnalysis.push(analysisResult);
+      }
+
+      this.cdr.markForCheck();
+    } catch (error) {
+      console.error('图片分析失败:', error);
+    } finally {
+      this.aiAnalyzingImages = false;
+    }
+  }
+
+  /**
+   * 分析单张图片
+   */
+  private async analyzeImage(image: any): Promise<any> {
+    try {
+      const prompt = `分析这张家装参考图片,提取以下设计信息:
+{
+  "styleElements": ["风格元素1", "风格元素2"],
+  "colorPalette": ["#主色调", "#副色调", "#点缀色"],
+  "materialAnalysis": ["材质1", "材质2"],
+  "layoutFeatures": ["布局特征1", "布局特征2"],
+  "mood": "空间氛围描述",
+  "confidence": 0.95
+}
+
+要求:
+1. 准确识别图片中的设计风格(如现代简约、北欧、轻奢等)
+2. 提取主要色彩搭配(HEX格式)
+3. 识别使用的材质(如实木、大理石、布艺等)
+4. 分析空间布局特点
+5. 描述整体氛围感受`;
+
+      const output = `{
+  "styleElements": ["现代简约", "线条流畅", "留白设计"],
+  "colorPalette": ["#FFFFFF", "#F5F5F5", "#3880FF"],
+  "materialAnalysis": ["实木地板", "布艺沙发", "金属装饰"],
+  "layoutFeatures": ["开放式布局", "功能分区明确", "采光良好"],
+  "mood": "简洁明亮,温馨舒适",
+  "confidence": 0.92
+}`;
+
+      // 转换图片为Base64(实际项目中应该使用已上传的Base64数据)
+      const imageBase64 = await this.convertImageToBase64(image.url);
+
+      const result = await completionJSON(
+        prompt,
+        output,
+        (_content) => {
+          // 进度回调
+        },
+        2,
+        {
+          model: this.AI_MODEL,
+          vision: true,
+          images: [imageBase64]
+        }
+      );
+
+      return {
+        imageId: image.id,
+        ...result
+      };
+
+    } catch (error) {
+      console.error('图片分析失败:', error);
+      return {
+        imageId: image.id,
+        styleElements: [],
+        colorPalette: [],
+        materialAnalysis: [],
+        layoutFeatures: [],
+        mood: '',
+        confidence: 0
+      };
+    }
+  }
+
+  /**
+   * AI分析CAD文件
+   */
+  async analyzeCADFiles(): Promise<void> {
+    if (this.cadFiles.length === 0) return;
+
+    try {
+      this.aiAnalyzingCAD = true;
+      this.aiAnalysisResults.cadAnalysis = [];
+
+      for (const cadFile of this.cadFiles) {
+        const analysisResult = await this.analyzeCADFile(cadFile);
+        this.analysisFileMap[analysisResult?.fileId] = analysisResult;
+        this.aiAnalysisResults.cadAnalysis.push(analysisResult);
+      }
+
+      this.cdr.markForCheck();
+    } catch (error) {
+      console.error('CAD分析失败:', error);
+    } finally {
+      this.aiAnalyzingCAD = false;
+    }
+  }
+  analysisFileMap:any = {}
+
+  /**
+   * 分析单个CAD文件
+   */
+  private async analyzeCADFile(cadFile: any): Promise<any> {
+    try {
+      const prompt = `分析这个CAD户型文件,提取空间结构信息:
+{
+  "spaceStructure": {
+    "totalArea": "总面积",
+    "roomCount": "房间数量",
+    "layoutType": "布局类型"
+  },
+  "dimensions": {
+    "length": "长度",
+    "width": "宽度",
+    "height": "层高"
+  },
+  "constraints": ["限制因素1", "限制因素2"],
+  "opportunities": ["优化机会1", "优化机会2"]
+}
+
+要求:
+1. 识别空间结构和尺寸
+2. 分析承重墙、管道等限制因素
+3. 提供布局优化建议`;
+
+      const output = `{
+  "spaceStructure": {
+    "totalArea": "120㎡",
+    "roomCount": "3室2厅",
+    "layoutType": "南北通透"
+  },
+  "dimensions": {
+    "length": "12m",
+    "width": "10m",
+    "height": "2.8m"
+  },
+  "constraints": ["承重墙不可拆改", "主管道位置固定"],
+  "opportunities": ["客厅阳台可打通", "厨房可做开放式设计"]
+}`;
+
+      // 模拟CAD分析(实际需要CAD解析库)
+      const result = await completionJSON(
+        prompt,
+        output,
+        (_content) => {
+          // 进度回调
+        },
+        2,
+        {
+          model: this.AI_MODEL
+        }
+      );
+
+      return {
+        fileId: cadFile.id,
+        ...result
+      };
+
+    } catch (error) {
+      console.error('CAD文件分析失败:', error);
+      return {
+        fileId: cadFile.id,
+        spaceStructure: {},
+        dimensions: {},
+        constraints: [],
+        opportunities: []
+      };
+    }
+  }
+
+  /**
+   * 执行综合AI分析
+   */
+  async performComprehensiveAIAnalysis(): Promise<void> {
+    try {
+      this.aiGeneratingComprehensive = true;
+
+      // 并行执行图片和CAD分析
+      await Promise.all([
+        this.analyzeReferenceImages(),
+        this.analyzeCADFiles()
+      ]);
+
+      // 生成综合分析
+      await this.generateComprehensiveAnalysis();
+
+      this.cdr.markForCheck();
+    } catch (error) {
+      console.error('综合分析失败:', error);
+    } finally {
+      this.aiGeneratingComprehensive = false;
+    }
+  }
+
+  /**
+   * 生成综合分析
+   */
+  private async generateComprehensiveAnalysis(): Promise<void> {
+    try {
+      const prompt = `基于以下信息,生成综合设计方案分析:
+
+参考图片分析:${JSON.stringify(this.aiAnalysisResults.imageAnalysis, null, 2)}
+CAD文件分析:${JSON.stringify(this.aiAnalysisResults.cadAnalysis, null, 2)}
+用户需求:${JSON.stringify(this.globalRequirements, null, 2)}
+产品信息:${JSON.stringify(this.projectProducts.map(p => ({
+  name: p.name,
+  type: p.type,
+  area: p.area
+    })), null, 2)}
+
+请生成以下格式的综合分析:
+{
+  "overallStyle": "整体风格定位",
+  "colorScheme": {
+    "primary": "主色调",
+    "secondary": "副色调",
+    "accent": "点缀色"
+  },
+  "materialRecommendations": ["材质1", "材质2"],
+  "layoutOptimization": ["布局优化建议1", "布局优化建议2"],
+  "budgetAssessment": {
+    "estimatedMin": 最低预算,
+    "estimatedMax": 最高预算,
+    "riskLevel": "风险等级"
+  },
+  "timeline": "预计工期",
+  "riskFactors": ["风险因素1", "风险因素2"]
+}`;
+
+      const output = `{
+  "overallStyle": "现代简约风格,注重功能性和舒适性",
+  "colorScheme": {
+    "primary": "#FFFFFF",
+    "secondary": "#F5F5F5",
+    "accent": "#3880FF"
+  },
+  "materialRecommendations": ["实木复合地板", "环保乳胶漆", "布艺沙发"],
+  "layoutOptimization": ["打通客厅阳台,增加空间感", "厨房做开放式设计,提升互动性"],
+  "budgetAssessment": {
+    "estimatedMin": 150000,
+    "estimatedMax": 250000,
+    "riskLevel": "中等"
+  },
+  "timeline": "60-75个工作日",
+  "riskFactors": ["工期可能受天气影响", "材料价格波动风险"]
+}`;
+
+      const result = await completionJSON(
+        prompt,
+        output,
+        (_content) => {
+          // 进度回调
+        },
+        2,
+        {
+          model: this.AI_MODEL
+        }
+      );
+
+      this.aiAnalysisResults.comprehensiveAnalysis = result;
+
+    } catch (error) {
+      console.error('综合分析生成失败:', error);
+    }
+  }
+
+  /**
+   * AI聊天助手
+   */
+  async sendAIChatMessage(): Promise<void> {
+    if (!this.aiChatInput.trim()) return;
+
+    try {
+      const userMessage = {
+        id: `msg_${Date.now()}`,
+        role: 'user' as const,
+        content: this.aiChatInput,
+        timestamp: new Date()
+      };
+
+      this.aiChatMessages.push(userMessage);
+      this.aiChatInput = '';
+      this.cdr.markForCheck();
+
+      // 生成AI回复
+      const aiResponse = await this.generateAIChatResponse(userMessage.content);
+
+      this.aiChatMessages.push({
+        id: `msg_${Date.now() + 1}`,
+        role: 'assistant',
+        content: aiResponse,
+        timestamp: new Date()
+      });
+
+      this.cdr.markForCheck();
+
+    } catch (error) {
+      console.error('AI聊天失败:', error);
+    }
+  }
+
+  /**
+   * 生成AI聊天回复
+   */
+  private async generateAIChatResponse(userMessage: string): Promise<string> {
+    try {
+      const context = `
+项目背景:${JSON.stringify(this.globalRequirements, null, 2)}
+AI分析结果:${JSON.stringify(this.aiAnalysisResults, null, 2)}
+产品信息:${JSON.stringify(this.projectProducts.map(p => ({
+    name: p.name,
+    type: p.type,
+    area: p.area
+  })), null, 2)}`;
+
+      const prompt = `作为专业的家装设计AI助手,基于以下项目信息回答用户问题:
+
+${context}
+
+用户问题:${userMessage}
+
+请提供专业、实用的建议,回答要简洁明了,字数控制在200字以内。`;
+
+      const result = await completionJSON(
+        prompt,
+        '{"response": "专业的家装设计建议"}',
+        (content) => {
+          // 流式输出回调
+        },
+        2,
+        {
+          model: this.AI_MODEL
+        }
+      );
+
+      return result.response || '抱歉,我暂时无法回答这个问题。';
+
+    } catch (error) {
+      console.error('AI回复生成失败:', error);
+      return '抱歉,服务暂时不可用,请稍后再试。';
+    }
+  }
+
+  /**
+   * 转换图片为Base64
+   */
+  private async convertImageToBase64(_imageUrl: string): Promise<string> {
+    // 实际项目中,图片上传时应该已经保存了Base64格式
+    // 这里返回一个模拟的Base64字符串
+    return 'data:image/jpeg;base64,/9j/4AAQSkZJRgABAQEAYABgAAD/2wBDAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQH/2wBDAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQH/wAARCAABAAEDASIAAhEBAxEB/8QAFQABAQAAAAAAAAAAAAAAAAAAAAv/xAAUEAEAAAAAAAAAAAAAAAAAAAAA/8QAFQEBAQAAAAAAAAAAAAAAAAAAAAX/xAAUEQEAAAAAAAAAAAAAAAAAAAAA/9oADAMBAAIRAxEAPwA/wA==';
+  }
+
+  /**
+   * 生成方案内容
+   */
+  private generateSolutionContent(): string {
+    const analysis = this.aiAnalysisResults.comprehensiveAnalysis;
+    if (analysis) {
+      return `基于AI分析结果,我们为您推荐${analysis.overallStyle},通过${analysis.colorScheme.primary}、${analysis.colorScheme.secondary}、${analysis.colorScheme.accent}的色彩搭配,营造${this.globalRequirements.colorScheme.atmosphere}的居住氛围。`;
+    }
+    return `基于您的${this.globalRequirements.stylePreference}风格需求,我们为您设计了以下方案...`;
+  }
+
+  /**
+   * 生成空间方案
+   */
+  private generateSpaceSolutions(): any[] {
+    return this.projectProducts.map(product => {
+      const analysis = this.aiAnalysisResults.comprehensiveAnalysis;
+      return {
+        id: product.id,
+        name: product.name,
+        type: product.type,
+        styleDescription: `${analysis?.overallStyle || this.globalRequirements.stylePreference}风格${product.name}设计`,
+        colorPalette: analysis ? [analysis.colorScheme.primary, analysis.colorScheme.secondary, analysis.colorScheme.accent] : [this.globalRequirements.colorScheme.primary, this.globalRequirements.colorScheme.secondary, this.globalRequirements.colorScheme.accent],
+        materials: analysis?.materialRecommendations || ['实木', '大理石', '布艺'],
+        furnitureRecommendations: this.getFurnitureRecommendations(product.type),
+        estimatedCost: this.calculateProductEstimatedCost(product),
+        timeline: this.calculateProductTimeline(product)
+      };
+    });
+  }
+
+  /**
+   * 计算AI增强的估算成本
+   */
+  private calculateAIEnhancedEstimatedCost(): number {
+    const analysis = this.aiAnalysisResults.comprehensiveAnalysis;
+    if (analysis?.budgetAssessment) {
+      return analysis.budgetAssessment.estimatedMax || this.calculateTotalEstimatedCost();
+    }
+    return this.globalRequirements.overallBudget.max || this.calculateTotalEstimatedCost();
+  }
+
+  /**
+   * 计算AI增强的工期
+   */
+  private calculateAIEnhancedTimeline(): string {
+    const analysis = this.aiAnalysisResults.comprehensiveAnalysis;
+    return analysis?.timeline || this.calculateTotalTimeline();
+  }
+
+  /**
+   * 生成AI跨空间协调方案
+   */
+  private generateAICrossSpaceCoordination(): any {
+    const analysis = this.aiAnalysisResults.comprehensiveAnalysis;
+    return {
+      styleConsistency: {
+        description: analysis ? `确保${analysis.overallStyle}风格在各空间的统一体现` : '确保各空间风格统一协调',
+        keyElements: ['色彩搭配', '材质选择', '设计元素']
+      },
+      functionalFlow: {
+        description: analysis ? `基于${analysis.layoutOptimization?.join('、') || '空间规划'}优化功能流线` : '优化空间之间的功能流线',
+        considerations: ['动线规划', '采光通风', '噪音控制']
+      },
+      timelineCoordination: {
+        description: '协调各空间施工时间',
+        strategy: '并行施工,关键节点协调'
+      }
+    };
+  }
+
+  /**
+   * 切换AI聊天显示
+   */
+  toggleAIChat(): void {
+    this.showAIChat = !this.showAIChat;
+    this.cdr.markForCheck();
+  }
+
   /**
    * 获取家具推荐
    */
@@ -483,26 +978,7 @@ export class StageRequirementsComponent implements OnInit {
     return `预计${Math.ceil(totalDays * 0.7)}-${totalDays}个工作日(考虑并行施工)`;
   }
 
-  /**
-   * 生成跨空间协调方案
-   */
-  private generateCrossSpaceCoordination(): any {
-    return {
-      styleConsistency: {
-        description: '确保各空间风格统一协调',
-        keyElements: ['色彩搭配', '材质选择', '设计元素']
-      },
-      functionalFlow: {
-        description: '优化空间之间的功能流线',
-        considerations: ['动线规划', '采光通风', '噪音控制']
-      },
-      timelineCoordination: {
-        description: '协调各空间施工时间',
-        strategy: '并行施工,关键节点协调'
-      }
-    };
-  }
-
+  
   /**
    * 保存草稿
    */
@@ -857,4 +1333,44 @@ export class StageRequirementsComponent implements OnInit {
       element.click();
     }
   }
+
+  // ===== AI分析辅助方法 =====
+
+  /**
+   * 获取分析对应的图片
+   */
+  getAnalysisImage(imageId: string): any {
+    return this.referenceImages.find(img => img.id === imageId);
+  }
+
+  /**
+   * 获取分析对应的CAD文件
+   */
+  getAnalysisFile(fileId: string): any {
+    return this.cadFiles.find(file => file.id === fileId);
+  }
+
+  /**
+   * 获取风险等级样式类名
+   */
+  getRiskLevelClass(riskLevel: string): string {
+    const classMap: Record<string, string> = {
+      'low': 'badge-success',
+      'medium': 'badge-warning',
+      'high': 'badge-danger'
+    };
+    return classMap[riskLevel] || 'badge-secondary';
+  }
+
+  /**
+   * 获取风险等级名称
+   */
+  getRiskLevelName(riskLevel: string): string {
+    const nameMap: Record<string, string> = {
+      'low': '低风险',
+      'medium': '中等风险',
+      'high': '高风险'
+    };
+    return nameMap[riskLevel] || '未知风险';
+  }
 }