Browse Source

update:page-crm-data

0235664 1 day ago
parent
commit
4b5651f204

+ 62 - 1
ai-assisant/src/modules/crm/mobile/page-crm-data/page-crm-data.html

@@ -418,7 +418,9 @@
     </div>
     
     <div class="training-results">
-      <div *ngFor="let result of trainingResults" class="result-item">
+      <div *ngFor="let result of trainingResults" 
+      class="result-item"
+      (click)="onResultClick(result)"> 
         <div class="result-icon">
           <i class="fas fa-{{result.icon}}"></i>
         </div>
@@ -439,4 +441,63 @@
       </div>
     </div>
   </div>
+  <!-- 在训练结果展示卡片后面添加这个模态框 -->
+<!-- AI对话模态框 -->
+<div class="ai-dialog-overlay" *ngIf="showAIDialog" (click)="closeAIDialog()">
+  <div class="ai-dialog-container" (click)="$event.stopPropagation()">
+    <div class="ai-dialog-header">
+      <h3>{{ currentAIModel?.title }} - AI智能助手</h3>
+      <button class="ai-dialog-close" (click)="closeAIDialog()">
+        <i class="fas fa-times"></i>
+      </button>
+    </div>
+    
+    <div class="ai-dialog-content">
+      <div class="ai-messages" #messageContainer>
+        <div *ngFor="let message of aiMessages" class="message" [class.user]="message.role === 'user'">
+          <div class="message-avatar">
+            <i *ngIf="message.role === 'assistant'" class="fas fa-robot"></i>
+            <i *ngIf="message.role === 'user'" class="fas fa-user"></i>
+          </div>
+          <div class="message-content">
+            <div class="message-text" [innerHTML]="message.content"></div>
+            <div class="message-time">{{ message.time | date:'HH:mm' }}</div>
+          </div>
+        </div>
+        
+        <div *ngIf="isAIThinking" class="ai-thinking">
+          <div class="typing-indicator">
+            <span></span>
+            <span></span>
+            <span></span>
+          </div>
+        </div>
+      </div>
+      
+      <div class="ai-input-container">
+        <textarea 
+          [(ngModel)]="userMessage" 
+          (keydown.enter)="sendMessage($event)"
+          placeholder="输入您的问题..."
+          class="ai-input"
+          rows="1"
+          #messageInput
+        ></textarea>
+        <button class="ai-send-btn" (click)="sendMessage()" [disabled]="!userMessage.trim()">
+          <i class="fas fa-paper-plane"></i>
+        </button>
+      </div>
+    </div>
+    
+    <div class="ai-dialog-footer">
+      <div class="ai-suggestions">
+        <span>快捷提问:</span>
+        <button *ngFor="let suggestion of aiSuggestions" 
+                (click)="selectSuggestion(suggestion)">
+          {{ suggestion }}
+        </button>
+      </div>
+    </div>
+  </div>
+</div>
 

+ 411 - 0
ai-assisant/src/modules/crm/mobile/page-crm-data/page-crm-data.scss

@@ -1691,7 +1691,418 @@ label:not(.sr-only):not(.file-upload-label) {
 }
 
 //7.3
+/* AI对话模态框样式 */
+.ai-dialog-overlay {
+  position: fixed;
+  top: 0;
+  left: 0;
+  right: 0;
+  bottom: 0;
+  background-color: rgba(0, 0, 0, 0.7);
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  z-index: 1100;
+  backdrop-filter: blur(5px);
+}
+
+.ai-dialog-container {
+  width: 90%;
+  max-width: 600px;
+  height: 80vh;
+  background-color: white;
+  border-radius: 12px;
+  box-shadow: 0 10px 30px rgba(0, 0, 0, 0.3);
+  display: flex;
+  flex-direction: column;
+  overflow: hidden;
+}
+
+.ai-dialog-header {
+  padding: 16px 24px;
+  background: linear-gradient(135deg, #4285f4, #3367d6);
+  color: white;
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  
+  h3 {
+    margin: 0;
+    font-size: 18px;
+    font-weight: 600;
+  }
+}
+
+.ai-dialog-close {
+  background: rgba(255, 255, 255, 0.2);
+  border: none;
+  width: 32px;
+  height: 32px;
+  border-radius: 50%;
+  color: white;
+  font-size: 16px;
+  cursor: pointer;
+  transition: all 0.2s;
+  
+  &:hover {
+    background: rgba(255, 255, 255, 0.3);
+    transform: rotate(90deg);
+  }
+}
+
+.ai-dialog-content {
+  flex: 1;
+  display: flex;
+  flex-direction: column;
+  padding: 0;
+  min-height: 0;  // 新增这行
+  overflow: hidden;  // 修改为hidden
+  background-color: #f5f7fa;
+}
+
+.ai-messages {
+  min-height: 0;  // 新增这行
+  flex: 1;
+  padding: 16px;
+  overflow-y: auto;
+  scroll-behavior: smooth;
+  
+  /* 自定义滚动条 */
+  &::-webkit-scrollbar {
+    width: 8px;
+  }
+  
+  &::-webkit-scrollbar-track {
+    background: #f1f1f1;
+    border-radius: 4px;
+  }
+  
+  &::-webkit-scrollbar-thumb {
+    background: #c1c1c1;
+    border-radius: 4px;
+    
+    &:hover {
+      background: #a8a8a8;
+    }
+  }
+}
+
+.message {
+  display: flex;
+  margin-bottom: 20px;
+  animation: fadeIn 0.3s ease;
+  max-width: 100%;
+  box-sizing: border-box;
+  
+  &.user {
+    flex-direction: row-reverse;
+    
+    .message-content {
+      align-items: flex-end;
+    }
+    
+    .message-text {
+      background: linear-gradient(135deg, #4285f4, #3367d6);
+      color: white;
+      border-radius: 18px 18px 0 18px;
+    }
+  }
+}
+
+@keyframes fadeIn { 
+  from { opacity: 0; transform: translateY(10px); }
+  to { opacity: 1; transform: translateY(0); }
+}
+
+.message-avatar {
+  width: 40px;
+  height: 40px;
+  border-radius: 50%;
+  background-color: #e0e0e0;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  margin: 0 12px;
+  flex-shrink: 0;
+  
+  i {
+    color: #666;
+    font-size: 18px;
+  }
+}
+
+.message-content {
+  display: flex;
+  flex-direction: column;
+  max-width: 75%;
+}
+
+.message-text {
+  padding: 12px 16px;
+  background-color: white;
+  border-radius: 18px 18px 18px 0;
+  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
+  margin-bottom: 6px;
+  line-height: 1.5;
+  font-size: 15px;
+  
+  a {
+    color: #4285f4;
+    text-decoration: none;
+    
+    &:hover {
+      text-decoration: underline;
+    }
+  }
+}
+
+.message-time {
+  font-size: 12px;
+  color: #888;
+}
+
+.ai-thinking {
+  display: flex;
+  justify-content: center;
+  padding: 16px;
+}
+
+.typing-indicator {
+  display: flex;
+  align-items: center;
+  background-color: white;
+  padding: 12px 16px;
+  border-radius: 18px;
+  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
+  
+  span {
+    width: 8px;
+    height: 8px;
+    margin: 0 3px;
+    background-color: #4285f4;
+    border-radius: 50%;
+    display: inline-block;
+    animation: typing 1s infinite ease-in-out;
+    
+    &:nth-child(1) {
+      animation-delay: 0s;
+    }
+    
+    &:nth-child(2) {
+      animation-delay: 0.2s;
+    }
+    
+    &:nth-child(3) {
+      animation-delay: 0.4s;
+    }
+  }
+}
+
+@keyframes typing {
+  0%, 100% {
+    transform: translateY(0);
+    opacity: 0.6;
+  }
+  50% {
+    transform: translateY(-5px);
+    opacity: 1;
+  }
+}
 
+.ai-input-container {
+  display: flex;
+  padding: 16px;
+  border-top: 1px solid #e0e0e0;
+  background-color: white;
+  align-items: flex-end;
+}
+
+.ai-input {
+  flex: 1;
+  padding: 12px 16px;
+  border: 1px solid #ddd;
+  border-radius: 24px;
+  outline: none;
+  font-size: 15px;
+  resize: none;
+  max-height: 120px;
+  line-height: 1.5;
+  transition: all 0.2s;
+  
+  &:focus {
+    border-color: #4285f4;
+    box-shadow: 0 0 0 2px rgba(66, 133, 244, 0.2);
+  }
+}
 
+.ai-send-btn {
+  width: 48px;
+  height: 48px;
+  border-radius: 50%;
+  background: linear-gradient(135deg, #4285f4, #3367d6);
+  color: white;
+  border: none;
+  margin-left: 12px;
+  cursor: pointer;
+  transition: all 0.2s;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  
+  &:hover:not(:disabled) {
+    transform: translateY(-2px);
+    box-shadow: 0 4px 12px rgba(66, 133, 244, 0.3);
+  }
+  
+  &:disabled {
+    background: #ddd;
+    cursor: not-allowed;
+  }
+  
+  i {
+    font-size: 18px;
+  }
+}
+
+.ai-dialog-footer {
+  padding: 12px 16px;
+  border-top: 1px solid #e0e0e0;
+  background-color: #f9f9f9;
+}
+
+.ai-suggestions {
+  display: flex;
+  flex-wrap: wrap;
+  gap: 8px;
+  align-items: center;
+  
+  span {
+    font-size: 13px;
+    color: #666;
+    margin-right: 8px;
+  }
+  
+  button {
+    padding: 6px 12px;
+    background-color: #e8f0fe;
+    border: none;
+    border-radius: 16px;
+    font-size: 13px;
+    color: #4285f4;
+    cursor: pointer;
+    transition: all 0.2s;
+    white-space: nowrap;
+    
+    &:hover {
+      background-color: #d2e3fc;
+      transform: translateY(-1px);
+    }
+  }
+}
+
+/* 修改训练结果项样式 */
+.result-item {
+  cursor: pointer;
+  transition: all 0.2s;
+  
+  &:hover {
+    transform: translateY(-2px);
+    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
+  }
+  
+  &[class*="status-completed"] {
+    &:hover {
+      background-color: rgba(52, 168, 83, 0.05);
+    }
+  }
+}
+
+/* 新增:自动调整输入框高度 */
+.ai-input {
+  min-height: 48px;
+  max-height: 120px;
+  overflow-y: auto;
+}
+
+/* 新增:响应式调整 */
+@media (max-width: 480px) {
+  .ai-dialog-container {
+    width: 95%;
+    height: 85vh;
+  }
+  
+  .message-content {
+    max-width: 85%;
+  }
+  
+  .message-avatar {
+    width: 32px;
+    height: 32px;
+    margin: 0 8px;
+    
+    i {
+      font-size: 16px;
+    }
+  }
+  
+  .message-text {
+    padding: 10px 14px;
+    font-size: 14px;
+  }
+  
+  .ai-input-container {
+    padding: 12px;
+  }
+  
+  .ai-send-btn {
+    width: 42px;
+    height: 42px;
+  }
+}
+.ai-dialog-overlay {
+  position: fixed;
+  top: 0;
+  left: 0;
+  right: 0;
+  bottom: 0;
+  background-color: rgba(0, 0, 0, 0.7);
+  z-index: 9999; /* 临时设置为极高的值 */
+  /* 其他样式 */
+}
+.ai-messages {
+  flex: 1;
+  padding: 16px;
+  overflow-y: auto;  // 启用垂直滚动
+  scroll-behavior: smooth;  // 平滑滚动
+  
+  /* 自定义滚动条样式 */
+  &::-webkit-scrollbar {
+    width: 8px;  // 滚动条宽度
+  }
+  
+  &::-webkit-scrollbar-track {
+    background: #f1f1f1;  // 轨道颜色
+    border-radius: 4px;
+  }
+  
+  &::-webkit-scrollbar-thumb {
+    background: #c1c1c1;  // 滑块颜色
+    border-radius: 4px;
+    
+    &:hover {
+      background: #a8a8a8;  // 悬停颜色
+    }
+  }
+  
+  /* 确保消息不会超出容器 */
+  .message {
+    max-width: 100%;
+    box-sizing: border-box;
+  }
+  
+  /* 滚轮滚动支持 */
+  overscroll-behavior-y: contain;
+  -webkit-overflow-scrolling: touch;  // iOS平滑滚动
+}
 
 //

+ 188 - 1
ai-assisant/src/modules/crm/mobile/page-crm-data/page-crm-data.ts

@@ -3,6 +3,7 @@ import { Component, ViewChild, ElementRef, AfterViewInit } from '@angular/core';
 import { CommonModule } from '@angular/common';
 import { FormsModule } from '@angular/forms';
 import { CloudObject, CloudQuery } from '../../../../lib/cloud/ncloud';
+import { HostListener } from '@angular/core';
 
 @Component({
   selector: 'app-page-crm-data',
@@ -14,6 +15,11 @@ import { CloudObject, CloudQuery } from '../../../../lib/cloud/ncloud';
 
 export class PageCrmData implements AfterViewInit {
   // 标签相关数据
+
+  //7.3
+  @ViewChild('messageInput') messageInput!: ElementRef<HTMLTextAreaElement>;
+  @ViewChild('messageContainer') messageContainer!: ElementRef<HTMLDivElement>;
+  //
   // 标签相关数据
 sourceTags = [
   { 
@@ -563,4 +569,185 @@ getTypeIcon(type: string): string {
       });
     }, 5000);
   }
-}
+
+
+
+  //7.2
+
+  // AI对话相关属性
+  showAIDialog = false;
+  currentAIModel: any = null;
+  userMessage = '';
+  aiMessages: any[] = [];
+  isAIThinking = false;
+  aiSuggestions = [
+    '这个模型的具体功能是什么?',
+    '模型使用了哪些训练数据?',
+    '模型的准确率和性能指标如何?',
+    '如何在实际业务中使用这个模型?'
+  ];
+
+  // 知识库 - 模拟真实AI回答
+  private knowledgeBase: { [key: string]: any } = {
+    '销售预测模型': {
+      description: '该模型基于历史销售数据和市场趋势,能够预测未来3-6个月的销售情况,准确率达到87.5%。',
+      dataUsed: '使用了2019-2023年的销售记录、客户购买行为数据和市场调研报告。',
+      accuracy: '测试集准确率87.5%,召回率82.3%,F1分数84.8%。',
+      usage: '通过API集成到CRM系统,每日自动生成销售预测报告。'
+    },
+    '情感分析模型': {
+      description: '分析客户反馈、评论和社交媒体中的情感倾向,识别正面、负面和中性情绪。',
+      dataUsed: '10万条客户评论、5万条客服对话记录和社交媒体数据。',
+      accuracy: '情感分类准确率92.1%,支持中文、英文和西班牙语。',
+      usage: '实时分析客户反馈,自动触发满意度低的客户跟进流程。'
+    },
+    '趋势预测模型': {
+      description: '识别产品需求变化和市场趋势,帮助调整库存和营销策略。',
+      dataUsed: '行业报告、搜索引擎趋势和产品销售数据。',
+      accuracy: '趋势预测准确率79.3%,提前3个月预警市场变化。',
+      usage: '每周生成趋势报告,指导产品开发和营销活动。'
+    }
+  };
+
+  // 打开AI对话框
+  openAIDialog(model: any) {
+    if (model.status !== 'completed') return;
+    
+    this.currentAIModel = model;
+    this.showAIDialog = true;
+    this.userMessage = '';
+    
+    // 初始化AI欢迎消息
+    this.aiMessages = [{
+      role: 'assistant',
+      content: `您好!我是${model.title} AI助手,专为销售团队设计。我可以回答关于这个模型的各种问题,包括:<br>
+      • 模型功能和应用场景<br>
+      • 训练数据和性能指标<br>
+      • 实际使用方法和集成方式<br><br>
+      请问您想了解什么?`,
+      time: new Date()
+    }];
+    
+    // 自动聚焦输入框
+    setTimeout(() => {
+      this.messageInput.nativeElement.focus();
+      this.scrollToBottom();
+    }, 100);
+  }
+
+  // 关闭AI对话框
+  closeAIDialog() {
+    this.showAIDialog = false;
+    this.currentAIModel = null;
+    this.userMessage = '';
+    this.aiMessages = [];
+  }
+
+  // 发送消息
+  sendMessage(event?: Event) {
+    if (event) event.preventDefault();
+    if (!this.userMessage.trim()) return;
+    
+    const question = this.userMessage.trim();
+    
+    // 添加用户消息
+    this.aiMessages.push({
+      role: 'user',
+      content: question,
+      time: new Date()
+    });
+    
+    this.userMessage = '';
+    this.isAIThinking = true;
+    this.scrollToBottom();
+    
+    // 获取AI响应
+    setTimeout(() => {
+      const response = this.generateAIResponse(question);
+      this.aiMessages.push({
+        role: 'assistant',
+        content: response,
+        time: new Date()
+      });
+      this.isAIThinking = false;
+      this.scrollToBottom();
+    }, 800); // 模拟网络延迟
+  }
+
+  // 生成AI响应
+  private generateAIResponse(question: string): string {
+    const model = this.currentAIModel.title;
+    const knowledge = this.knowledgeBase[model] || {};
+    
+    // 问题分类和回答
+    if (question.includes('功能') || question.includes('做什么') || question.includes('用途')) {
+      return `关于<strong>${model}</strong>的功能:<br><br>${knowledge.description || 
+        '该模型主要用于销售场景的数据分析和决策支持,具体功能包括预测分析、趋势识别和客户行为分析等。'}`;
+    }
+    else if (question.includes('数据') || question.includes('训练') || question.includes('样本')) {
+      return `关于<strong>${model}</strong>的训练数据:<br><br>${knowledge.dataUsed || 
+        '模型使用了公司多年的销售数据、客户互动记录和市场调研数据,经过严格的数据清洗和特征工程处理。'}`;
+    }
+    else if (question.includes('准确') || question.includes('性能') || question.includes('指标')) {
+      return `关于<strong>${model}</strong>的性能指标:<br><br>${knowledge.accuracy || 
+        '模型在测试集上表现良好,准确率和召回率均超过80%,具体指标会根据不同业务场景有所变化。'}`;
+    }
+    else if (question.includes('使用') || question.includes('怎么用') || question.includes('集成')) {
+      return `关于<strong>${model}</strong>的使用方法:<br><br>${knowledge.usage || 
+        '可以通过我们的API接口集成到现有系统中,也支持导出分析报告。详细技术文档请联系技术团队获取。'}`;
+    }
+    else {
+      return `感谢您的提问。关于"${question}",${model}可以提供专业分析:<br><br>
+      1. 该问题涉及${model}的${question.includes('客户') ? '客户分析' : '预测'}功能<br>
+      2. 我们建议${question.includes('销售') ? '结合历史销售数据' : '参考模型输出'}进行决策<br>
+      3. 如需更详细分析,可以提供具体数据样本<br><br>
+      您是否需要更具体的信息?`;
+    }
+  }
+
+  // 选择建议问题
+  selectSuggestion(suggestion: string) {
+    this.userMessage = suggestion;
+    this.sendMessage();
+  }
+
+  
+
+  // 修改训练结果项的点击处理
+  onResultClick(result: any) {
+    if (result.status === 'completed') {
+      this.openAIDialog(result);
+    }
+  }
+  // 监听滚轮事件
+  @HostListener('wheel', ['$event'])
+  onWheel(event: WheelEvent) {
+    // 防止页面整体滚动
+    if (this.showAIDialog) {
+      const container = this.messageContainer?.nativeElement;
+      if (container && container.contains(event.target as Node)) {
+        event.preventDefault();
+        container.scrollTop += event.deltaY;
+      }
+    }
+  }
+  
+  // 确保每次新消息都滚动到底部
+  ngAfterViewChecked() {
+    this.scrollToBottom();
+  }
+  
+  private scrollToBottom(): void {
+    if (this.messageContainer) {
+      try {
+        const container = this.messageContainer.nativeElement;
+        container.scrollTop = container.scrollHeight;
+      } catch (err) {
+        console.error('滚动错误:', err);
+      }
+    }
+  }
+}
+
+
+  //