|
@@ -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] || '未知风险';
|
|
|
+ }
|
|
|
}
|