import { Component, OnInit, ViewChild, ElementRef, AfterViewChecked } from '@angular/core'; import { FormsModule } from '@angular/forms'; import { CommonModule } from '@angular/common'; import { TestCompletion, TestMessage,extractJSON} from '../../../../lib/cloud/comletion'; type SceneType = 'first-contact' | 'deep-talk'; type MessageRole = 'customer' | 'assistant'; interface StrategyAnalysis { aggressive: { title: string; highlight: string; applicable: string; advantage: string; successRate: string; }; neutral: { title: string; highlight: string; applicable: string; advantage: string; successRate: string; }; conservative: { title: string; highlight: string; applicable: string; advantage: string; successRate: string; }; } interface Message { role: MessageRole; content: string; time: string; } interface Tag { text: string; icon: string; background: string; color: string; } interface Strategy { type: string; title: string; icon: string; iconBg: string; iconColor: string; description: string; highlight: string; applicable: string; advantage: string; successRate: string; rating: string; isDefault: boolean; // 新增:标记是否为默认策略 } interface ChatRecord { id: string; scene: SceneType; messages: Message[]; tags: Tag[]; strategies: Strategy[]; timestamp: number; } @Component({ selector: 'app-page-crm-decision', standalone: true, imports: [CommonModule, FormsModule], templateUrl: './page-crm-decision.html', styleUrls: ['./page-crm-decision.scss'] }) export class PageCrmDecision implements OnInit, AfterViewChecked { @ViewChild('chatContainer') chatContainer!: ElementRef; @ViewChild('fileInput') fileInput!: ElementRef; private aiAssistant!: TestCompletion; private scenePrompts = { 'first-contact': `你是一名专业的酒店销售顾问,正在与一位潜在客户进行首次接触。 客户可能对酒店服务、房型、价格等方面有疑问。你的任务是: 1. 建立良好的沟通氛围 2. 了解客户基本需求 3. 介绍酒店核心优势 4. 避免过于强硬的推销语气 5. 为后续沟通留下空间`, 'deep-talk': `你是一名经验丰富的酒店销售顾问,正在与一位对酒店有一定兴趣的客户进行深度交流。 客户可能已经了解了基本信息,正在比较选择或寻求更详细的信息。你的任务是: 1. 深入挖掘客户具体需求和关注点 2. 提供针对性的解决方案和建议 3. 有效处理客户提出的异议和问题 4. 展示酒店差异化竞争优势 5. 推动客户向决策阶段发展` }; openHistory() { this.showHistoryModal = true; } selectedScene: SceneType = 'first-contact'; sceneTitle = '首次接触'; messages: Message[] = []; tags: Tag[] = [ { text: 'VIP客户', icon: 'fas fa-user', background: 'rgba(100, 160, 255, 0.15)', color: '#64a0ff' }, { text: '旺季时段', icon: 'fas fa-calendar', background: 'rgba(255, 212, 59, 0.15)', color: '#ffd43b' }, { text: '价格敏感', icon: 'fas fa-percent', background: 'rgba(156, 54, 181, 0.15)', color: '#9c36b5' } ]; currentRole: MessageRole = 'customer'; newMessage = ''; strategies: Strategy[] = [ { type: 'aggressive', title: '主动型策略', icon: 'fas fa-bolt', iconBg: 'var(--blue-light)', iconColor: 'var(--blue)', description: '直接强调酒店独特价值,制造紧迫感:', highlight: '', applicable: '客户表现出明确兴趣,决策周期短', advantage: '快速成交,提升单笔订单价值', successRate: '68%', rating: '⭐⭐⭐⭐', isDefault: true }, { type: 'neutral', title: '平衡型策略', icon: 'fas fa-balance-scale', iconBg: 'rgba(255, 212, 59, 0.15)', iconColor: 'var(--yellow)', description: '提供阶梯式优惠,引导客户选择:', highlight: '', applicable: '客户在多个选项间犹豫', advantage: '平衡双方利益,建立长期关系', successRate: '82%', rating: '⭐⭐⭐⭐⭐', isDefault: true }, { type: 'conservative', title: '保守型策略', icon: 'fas fa-shield-alt', iconBg: 'rgba(156, 54, 181, 0.15)', iconColor: 'var(--purple)', description: '提供灵活方案,降低决策风险:', highlight: '', applicable: '客户犹豫不决,决策周期长', advantage: '降低客户风险感知,提高转化率', successRate: '75%', rating: '⭐⭐⭐⭐', isDefault: true } ]; activeCardIndex = 0; isProcessing = false; showHistoryModal = false; chatRecords: ChatRecord[] = []; private strategiesContent: Record = { "first-contact": { aggressive: "主动介绍酒店特色和限时优惠,强调独特卖点", neutral: "提供套餐选择,引导客户了解不同房型", conservative: "邀请客户参观虚拟酒店,提供详细资料" }, "deep-talk": { aggressive: "深度挖掘客户需求,提供定制化解决方案", neutral: "建立信任关系,分享成功案例和客户评价", conservative: "提供专业建议,解答客户深层疑问" } }; ngOnInit() { this.loadRecords(); this.selectScene('first-contact'); } ngAfterViewChecked() { this.scrollToBottom(); } scrollToBottom(): void { try { if (this.chatContainer) { this.chatContainer.nativeElement.scrollTop = this.chatContainer.nativeElement.scrollHeight; } } catch (err) { console.error(err); } } onTextareaKeydown(event: KeyboardEvent): void { if (event.key === 'Enter' && !event.shiftKey) { event.preventDefault(); this.sendMessage(); } } // 只在初始化时设置默认策略 initializeDefaultStrategies(): void { const sceneStrategies = this.strategiesContent[this.selectedScene]; this.strategies[0] = { ...this.strategies[0], highlight: sceneStrategies.aggressive, isDefault: true }; this.strategies[1] = { ...this.strategies[1], highlight: sceneStrategies.neutral, isDefault: true }; this.strategies[2] = { ...this.strategies[2], highlight: sceneStrategies.conservative, isDefault: true }; } selectScene(scene: SceneType): void { this.selectedScene = scene; this.sceneTitle = scene === 'first-contact' ? '首次接触' : '深度交流'; // 初始化AI助手 this.messages = []; const systemPrompt = this.scenePrompts[scene]; this.aiAssistant = new TestCompletion([ { role: "system", content: systemPrompt }, { role: "assistant", content: scene === 'first-contact' ? "您好!我是九州宴会的销售顾问,很高兴认识您。请问您今天想了解哪方面的信息呢?" : "感谢您继续深入交流。基于我们之前的沟通,我整理了几个可能适合您的方案,您想先了解哪个方面?" } ]); // 添加初始问候语 this.addMessage('assistant', scene === 'first-contact' ? "您好!我是九州宴会的销售顾问,很高兴认识您。请问您今天想了解哪方面的信息呢?" : "感谢您继续深入交流。基于我们之前的沟通,我整理了几个可能适合您的方案,您想先了解哪个方面?" ); // 重置并初始化策略 this.resetStrategies(); this.initializeDefaultStrategies(); } // 重置策略内容(切换场景时调用) private resetStrategies() { this.strategies = [ { ...this.strategies[0], highlight: "", applicable: "客户表现出明确兴趣,决策周期短", advantage: "快速成交,提升单笔订单价值", successRate: "68%", isDefault: true }, { ...this.strategies[1], highlight: "", applicable: "客户在多个选项间犹豫", advantage: "平衡双方利益,建立长期关系", successRate: "82%", isDefault: true }, { ...this.strategies[2], highlight: "", applicable: "客户犹豫不决,决策周期长", advantage: "降低客户风险感知,提高转化率", successRate: "75%", isDefault: true } ]; } setRole(role: MessageRole): void { this.currentRole = role; } addTag(): void { const newTag: Tag = { text: '新标签', icon: 'fas fa-tag', background: 'rgba(100, 160, 255, 0.15)', color: '#64a0ff' }; this.tags.push(newTag); } removeTag(event: Event, tag: Tag): void { event.stopPropagation(); this.tags = this.tags.filter(t => t !== tag); } async sendMessage() { if (!this.newMessage.trim() || !this.selectedScene) return; this.isProcessing = true; // 添加用户消息 const now = new Date(); this.addMessage(this.currentRole, this.newMessage.trim()); this.newMessage = ''; // 如果是客户消息,更新策略分析 if (this.currentRole === 'customer') { try { // 显示加载状态 this.strategies.forEach(strategy => { strategy.highlight = "分析中..."; strategy.applicable = "生成最佳策略..."; strategy.successRate = "--"; strategy.isDefault = false; }); // 更新策略分析(基于最新客户消息) await this.updateStrategiesBasedOnMessage(this.messages[this.messages.length-1].content); } catch (error) { console.error('更新策略失败:', error); // 失败时使用关键词匹配生成动态内容 const fallbackStrategies = this.generateDynamicStrategies(this.messages[this.messages.length-1].content); this.updateStrategiesWithFallback(fallbackStrategies); } finally { this.isProcessing = false; } } else { this.isProcessing = false; } } private addMessage(role: MessageRole, content: string): void { const now = new Date(); this.messages.push({ role, content, time: `${now.getHours()}:${now.getMinutes().toString().padStart(2, '0')}` }); this.scrollToBottom(); } // 根据客户消息动态更新策略卡片内容 private async updateStrategiesBasedOnMessage(customerMessage: string) { try { // 调用AI分析客户消息,生成策略建议 const analysis = await this.analyzeCustomerMessage(customerMessage); // 更新策略卡片内容 this.strategies[0] = { ...this.strategies[0], highlight: analysis.aggressive.highlight, applicable: analysis.aggressive.applicable, advantage: analysis.aggressive.advantage, successRate: analysis.aggressive.successRate, isDefault: false }; this.strategies[1] = { ...this.strategies[1], highlight: analysis.neutral.highlight, applicable: analysis.neutral.applicable, advantage: analysis.neutral.advantage, successRate: analysis.neutral.successRate, isDefault: false }; this.strategies[2] = { ...this.strategies[2], highlight: analysis.conservative.highlight, applicable: analysis.conservative.applicable, advantage: analysis.conservative.advantage, successRate: analysis.conservative.successRate, isDefault: false }; // 根据消息内容选择最合适的策略 this.selectBestStrategy(customerMessage); } catch (error) { console.error('更新策略失败:', error); throw error; // 让调用者处理错误 } } // 使用备用策略更新(AI调用失败时) private updateStrategiesWithFallback(strategies: ReturnType) { this.strategies[0] = { ...this.strategies[0], highlight: strategies.aggressive.highlight, applicable: "客户表现出明确兴趣,决策周期短", successRate: "68%", isDefault: false }; this.strategies[1] = { ...this.strategies[1], highlight: strategies.neutral.highlight, applicable: "客户在多个选项间犹豫", successRate: "82%", isDefault: false }; this.strategies[2] = { ...this.strategies[2], highlight: strategies.conservative.highlight, applicable: "客户犹豫不决,决策周期长", successRate: "75%", isDefault: false }; // 仍然选择最佳策略 this.selectBestStrategy(this.messages[this.messages.length-1].content); } // 生成动态策略内容(关键词匹配) private generateDynamicStrategies(customerMessage: string) { // 关键词匹配,确保内容随客户消息变化 let focus = "酒店服务"; if (customerMessage.toLowerCase().includes("价格")) focus = "价格优势"; if (customerMessage.toLowerCase().includes("位置")) focus = "地理位置"; if (customerMessage.toLowerCase().includes("设施")) focus = "设施特色"; if (customerMessage.toLowerCase().includes("日期")) focus = "日期灵活性"; if (customerMessage.toLowerCase().includes("容量")) focus = "场地容量"; return { aggressive: { highlight: `立即强调${focus},提供专属限时优惠`, applicable: "客户表现出明确兴趣", advantage: "快速促成交易", successRate: "68%" }, neutral: { highlight: `提供${focus}的3种选择方案,满足不同需求`, applicable: "客户需要比较选择", advantage: "提高选择满意度", successRate: "82%" }, conservative: { highlight: `详细说明${focus}的优势,提供案例参考`, applicable: "客户需要更多决策信息", advantage: "降低决策阻力", successRate: "75%" } }; } activateCard(index: number): void { this.activeCardIndex = index; } getCardTransform(index: number): string { if (index === this.activeCardIndex) { return 'translateY(0) scale(1)'; } else if (Math.abs(index - this.activeCardIndex) === 1) { return `translateY(${20 * Math.abs(index - this.activeCardIndex)}px) scale(${1 - 0.05 * Math.abs(index - this.activeCardIndex)})`; } else { return `translateY(${40 * Math.abs(index - this.activeCardIndex)}px) scale(${1 - 0.1 * Math.abs(index - this.activeCardIndex)})`; } } getCardZIndex(index: number): string { if (index === this.activeCardIndex) { return '30'; } else if (Math.abs(index - this.activeCardIndex) === 1) { return '20'; } else { return '10'; } } // 文件上传处理 onFileSelected(event: Event) { const input = event.target as HTMLInputElement; if (!input.files || input.files.length === 0) return; const file = input.files[0]; if (file.type !== 'application/json' && !file.name.endsWith('.json')) { alert('请上传JSON格式的文件'); return; } const reader = new FileReader(); reader.onload = (e: ProgressEvent) => { try { const content = e.target?.result as string; const data = JSON.parse(content); if (Array.isArray(data) && data.every(item => item.role && item.content && item.time)) { this.messages = data as Message[]; this.updateStrategiesBasedOnMessages(); this.fileInput.nativeElement.value = ''; // 清空文件选择 } else { alert('文件格式不正确,请上传有效的聊天记录JSON文件'); } } catch (error) { console.error('文件解析错误:', error); alert('解析文件时出错'); } }; reader.readAsText(file); } // 根据完整对话更新策略 private updateStrategiesBasedOnMessages() { // 从对话中提取最后一条客户消息 const lastCustomerMessage = this.messages .filter(msg => msg.role === 'customer') .pop(); if (lastCustomerMessage) { this.updateStrategiesBasedOnMessage(lastCustomerMessage.content); } } // 保存记录 saveRecord() { if (!this.messages.length) { alert('没有可保存的对话记录'); return; } const record: ChatRecord = { id: Date.now().toString(), scene: this.selectedScene, messages: [...this.messages], tags: [...this.tags], strategies: [...this.strategies], timestamp: Date.now() }; this.chatRecords.unshift(record); // 添加到开头 this.saveRecords(); alert('记录已保存'); } // 加载记录 loadRecords() { const records = localStorage.getItem('chatRecords'); if (records) { this.chatRecords = JSON.parse(records); } } // 保存记录到本地存储 saveRecords() { localStorage.setItem('chatRecords', JSON.stringify(this.chatRecords)); } // 查看历史 viewHistory() { this.showHistoryModal = true; } // 选择历史记录 selectRecord(record: ChatRecord) { this.selectedScene = record.scene; this.sceneTitle = record.scene === 'first-contact' ? '首次接触' : '深度交流'; this.messages = [...record.messages]; this.tags = [...record.tags]; this.strategies = [...record.strategies]; // 初始化AI助手 const systemPrompt = this.scenePrompts[record.scene]; this.aiAssistant = new TestCompletion([ { role: "system", content: systemPrompt }, ...record.messages.map(msg => ({ role: msg.role === 'customer' ? 'user' : msg.role, content: msg.content })) ]); this.showHistoryModal = false; } // 删除历史记录 deleteRecord(record: ChatRecord) { if (confirm('确定要删除这条记录吗?')) { this.chatRecords = this.chatRecords.filter(r => r.id !== record.id); this.saveRecords(); } } // 格式化日期 formatDate(timestamp: number) { const date = new Date(timestamp); return `${date.getFullYear()}-${(date.getMonth()+1).toString().padStart(2, '0')}-${date.getDate().toString().padStart(2, '0')} ${date.getHours().toString().padStart(2, '0')}:${date.getMinutes().toString().padStart(2, '0')}`; } // 导出对话记录为JSON文件 exportChat() { if (!this.messages.length) { alert('没有可导出的对话记录'); return; } const jsonContent = JSON.stringify(this.messages, null, 2); const blob = new Blob([jsonContent], { type: 'application/json' }); const url = URL.createObjectURL(blob); const a = document.createElement('a'); a.href = url; a.download = `chat-record-${new Date().toISOString().slice(0,10)}.json`; document.body.appendChild(a); a.click(); document.body.removeChild(a); URL.revokeObjectURL(url); } // 生成AI回复 async generateAIResponse() { if (!this.messages.length || this.messages[this.messages.length - 1].role === 'assistant') { alert('请先发送客户消息'); return; } this.isProcessing = true; try { const aiReply = await this.aiAssistant.sendMessage( [...this.messages.map(msg => ({ role: msg.role === 'customer' ? 'user' : msg.role, content: msg.content }))], (partialContent) => { const lastMsg = this.messages[this.messages.length - 1]; if (lastMsg.role === 'assistant') { lastMsg.content = partialContent; } else { this.addMessage('assistant', partialContent); } } ); if (typeof aiReply === 'string') { this.addMessage('assistant', aiReply); // 基于最新客户消息更新策略 const lastCustomerMsg = this.messages .filter(msg => msg.role === 'customer') .pop(); if (lastCustomerMsg) { this.updateStrategiesBasedOnMessage(lastCustomerMsg.content); } } } catch (error) { console.error('AI交互错误:', error); this.addMessage('assistant', '抱歉,处理您的请求时出现了问题。'); } finally { this.isProcessing = false; } } // 调用AI分析客户消息并生成策略建议 private async analyzeCustomerMessage(customerMessage: string): Promise { // 构建提示词,引导AI生成三种策略 const prompt = ` 客户消息: "${customerMessage}" 请针对此客户消息,为酒店销售顾问生成三种应对策略: 1. 主动型策略: 直接、果断的销售方法 2. 平衡型策略: 中等强度的销售方法 3. 保守型策略: 温和、信息丰富的销售方法 请以JSON格式返回,包含以下字段: { "aggressive": { "title": "主动型策略标题", "highlight": "核心建议", "applicable": "适用场景", "advantage": "主要优势", "successRate": "成功率百分比" }, "neutral": { "title": "平衡型策略标题", "highlight": "核心建议", "applicable": "适用场景", "advantage": "主要优势", "successRate": "成功率百分比" }, "conservative": { "title": "保守型策略标题", "highlight": "核心建议", "applicable": "适用场景", "advantage": "主要优势", "successRate": "成功率百分比" } } `; // 使用TestCompletion调用AI const strategyAnalyzer = new TestCompletion([ { role: "system", content: "你是一位专业的酒店销售策略顾问,擅长根据客户消息生成针对性的销售策略。" }, { role: "user", content: prompt } ]); // 获取AI响应 const response = await strategyAnalyzer.sendMessage([ { role: "user", content: prompt } ],(content)=>{ this.aicontent = content }); // 解析JSON响应 try { let json = extractJSON(response) return json; } catch (parseError) { console.error('解析策略分析失败:', parseError); // 返回默认策略 return this.getDefaultStrategies(); } } aicontent:string = "" // 根据客户消息选择最合适的策略 private selectBestStrategy(customerMessage: string) { const lowerCaseMsg = customerMessage.toLowerCase(); if (lowerCaseMsg.includes('价格') || lowerCaseMsg.includes('优惠')) { this.activeCardIndex = 1; // 平衡型策略通常最适合价格讨论 } else if (lowerCaseMsg.includes('兴趣') || lowerCaseMsg.includes('考虑')) { this.activeCardIndex = 0; // 主动型策略适合有兴趣的客户 } else if (lowerCaseMsg.includes('犹豫') || lowerCaseMsg.includes('比较')) { this.activeCardIndex = 2; // 保守型策略适合犹豫的客户 } else { // 默认选择平衡型策略 this.activeCardIndex = 1; } } // 返回默认策略(当AI分析失败时使用) private getDefaultStrategies(): StrategyAnalysis { return { aggressive: { title: "主动型策略", highlight: "直接介绍酒店特色和限时优惠", applicable: "客户表现出明确兴趣,决策周期短", advantage: "快速成交,提升单笔订单价值", successRate: "68%" }, neutral: { title: "平衡型策略", highlight: "提供套餐选择,引导客户了解不同房型", applicable: "客户在多个选项间犹豫", advantage: "平衡双方利益,建立长期关系", successRate: "82%" }, conservative: { title: "保守型策略", highlight: "邀请客户参观虚拟酒店,提供详细资料", applicable: "客户犹豫不决,决策周期长", advantage: "降低客户风险感知,提高转化率", successRate: "75%" } }; } }