浏览代码

update:page-crm-data

0235664 14 小时之前
父节点
当前提交
986dd4b07c

+ 2 - 0
ai-assisant/src/index.html

@@ -8,6 +8,8 @@
   <link rel="icon" type="image/x-icon" href="favicon.ico">
 </head>
 <body>
+  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
+  <app-page-crm-data></app-page-crm-data>
   <app-root></app-root>
 </body>
 </html>

+ 2 - 1
ai-assisant/src/modules/crm/mobile/mobile.routes.ts

@@ -11,7 +11,8 @@ export const MOBILE_ROUTES: Routes = [
       },
       {
         path: 'data',
-        loadComponent: () => import('./page-crm-data/page-crm-data').then(m => m.PageCrmData)
+      // 修改为正确的组件类名
+        loadComponent: () => import('./page-crm-data/page-crm-data').then(m => m.PageCrmData)   
       },
        {
         path: 'image',

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

@@ -1 +1,200 @@
-<p>page-crm-data works!</p>
+<!-- page-crm-data.component.html -->
+<div class="container">
+  <div class="decor-circle circle-1"></div>
+  <div class="decor-circle circle-2"></div>
+  
+  <!-- 顶部导航 -->
+  <div class="header">
+    <button class="back-btn" aria-label="返回">
+        <i class="fas fa-arrow-left"></i>
+    </button>
+    <h1 class="title">数据训练中心</h1>
+  </div>
+  
+  <div class="page-header">
+    <h1 class="page-title">AI数据训练中心</h1>
+    <p class="page-subtitle">上传数据、训练模型、优化结果</p>
+  </div>
+  
+  <!-- 上传控制台 -->
+  <div class="card upload-console">
+    <div class="card-header">
+      <div>
+        <div class="card-title">上传控制台</div>
+        <div class="card-subtitle">选择数据类型和输入方式</div>
+      </div>
+    </div>
+    
+    <div class="source-tags">
+      <div *ngFor="let tag of sourceTags" 
+           class="source-tag" 
+           [class.active]="tag.active"
+           (click)="selectTag(tag)">
+        {{tag.name}}
+      </div>
+    </div>
+    
+    <div class="custom-tag-form">
+      <input type="text" class="custom-tag-input" 
+             [(ngModel)]="newTag" 
+             placeholder="输入新数据类型..."
+             (keyup.enter)="addTag()">
+      <button class="add-tag-btn" (click)="addTag()">
+        添加标签
+      </button>
+    </div>
+    
+    <div class="upload-method-selector">
+      <div class="method-title">选择输入方式</div>
+      <div class="method-options">
+        <div *ngFor="let method of uploadMethods" 
+             class="method-option" 
+             [class.active]="method.active"
+             (click)="selectMethod(method)">
+          <div class="method-icon">
+            <i class="fas fa-{{method.icon}}"></i>
+          </div>
+          <div>{{method.name}}</div>
+        </div>
+      </div>
+    </div>
+    
+    <div class="upload-action">
+      <button class="upload-button" (click)="uploadData()">
+        <i class="fas fa-cloud-upload-alt"></i> 上传数据
+      </button>
+    </div>
+    
+    <div class="upload-status" *ngIf="uploadStatus.visible" 
+         [class.error]="!uploadStatus.success">
+      <div [innerHTML]="uploadStatus.message"></div>
+      <div class="upload-progress">
+        <div class="progress-bar" [style.width]="uploadStatus.progress + '%'"></div>
+      </div>
+    </div>
+  </div>
+  
+  <!-- 数据看板 -->
+  <div class="card">
+    <div class="card-header">
+      <div>
+        <div class="card-title">数据看板</div>
+        <div class="card-subtitle">今日处理状态</div>
+      </div>
+      <div class="alert-badge">3</div>
+    </div>
+    
+    <div class="stats-container">
+      <div class="stat-item">
+        <div class="progress-ring">
+          <div class="progress-bg">
+            <div class="progress-inner">128</div>
+          </div>
+        </div>
+        <div class="stat-label">处理量</div>
+      </div>
+      
+      <div class="stat-item">
+        <div class="stat-value">85%</div>
+        <div class="stat-label">质量评分</div>
+        <div class="quality-bar">
+          <div class="quality-fill"></div>
+        </div>
+      </div>
+    </div>
+    
+    <!-- 每日数据记录 -->
+    <div class="data-record">
+      <div class="record-header">
+        <div class="card-title">每日数据记录</div>
+        <a class="view-all">
+          查看全部 <i class="fas fa-arrow-right"></i>
+        </a>
+      </div>
+      
+      <div class="record-list">
+        <div *ngFor="let stat of dashboardStats" class="record-item">
+          <div class="record-title">
+            <i class="fas fa-{{stat.icon}}"></i> {{stat.label}}
+          </div>
+          <div class="record-value">{{stat.value}}</div>
+          <div class="record-trend" [class.trend-up]="stat.trendUp" [class.trend-down]="!stat.trendUp">
+            <i class="fas fa-arrow-{{stat.trendUp ? 'up' : 'down'}} trend-icon"></i> {{stat.trend}}%
+          </div>
+        </div>
+      </div>
+    </div>
+  </div>
+  
+  <!-- 历史数据上传记录 -->
+  <div class="card">
+    <div class="card-header">
+      <div>
+        <div class="card-title">历史数据上传记录</div>
+        <div class="card-subtitle">最近上传的文件</div>
+      </div>
+    </div>
+    
+    <!-- 搜索区域 -->
+    <div class="search-container">
+      <div class="search-box">
+        <i class="fas fa-search"></i>
+        <input type="text" class="search-input" 
+               [(ngModel)]="searchTerm" 
+               (input)="filterHistory()"
+               placeholder="搜索文件名、类型或日期...">
+      </div>
+    </div>
+    
+    <div class="history-list">
+      <div *ngFor="let item of filteredHistory" class="history-item">
+        <div class="history-icon">
+          <i class="fas fa-file-{{item.type}}"></i>
+        </div>
+        <div class="history-content">
+          <div class="history-name">{{item.name}}</div>
+          <div class="history-meta">
+            <div class="history-size">
+              <i class="fas fa-database"></i> {{item.size}}MB
+            </div>
+            <div class="history-date">
+              <i class="far fa-calendar"></i> {{item.date}}
+            </div>
+          </div>
+        </div>
+      </div>
+    </div>
+  </div>
+  
+  <!-- 训练结果展示 -->
+  <div class="card">
+    <div class="card-header">
+      <div>
+        <div class="card-title">训练结果展示</div>
+        <div class="card-subtitle">模型训练状态与结果</div>
+      </div>
+    </div>
+    
+    <div class="training-results">
+      <div *ngFor="let result of trainingResults" class="result-item">
+        <div class="result-icon">
+          <i class="fas fa-{{result.icon}}"></i>
+        </div>
+        <div class="result-content">
+          <div class="result-title">{{result.title}}</div>
+          <div class="result-meta">
+            <div class="result-date">
+              <i class="far fa-clock"></i> 训练时间: {{result.time}}
+            </div>
+            <div class="result-status" [class]="'status-' + result.status">
+              {{ 
+                result.status === 'completed' ? '已完成' : 
+                result.status === 'training' ? '训练中' : '失败'
+              }}
+            </div>
+          </div>
+        </div>
+      </div>
+    </div>
+  </div>
+</div>

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

@@ -0,0 +1,730 @@
+/* page-crm-data.component.scss */
+:host {
+    display: block;
+    background-color: #f5f8ff;
+    background-image: linear-gradient(135deg, #f5f8ff 0%, #e8ecff 100%);
+    color: #333333;
+    line-height: 1.6;
+    padding: 16px;
+    max-width: 500px;
+    margin: 0 auto;
+    position: relative;
+    min-height: 100vh;
+    overflow-x: hidden;
+    font-family: 'Segoe UI', 'SF Pro Display', -apple-system, BlinkMacSystemFont, sans-serif;
+  }
+  
+  /* 变量定义 */
+  $primary: #4285f4;
+  $primary-light: rgba(66, 133, 244, 0.1);
+  $primary-dark: #3367d6;
+  $text-dark: #0a192f;
+  $text-medium: #333333;
+  $text-light: #8898aa;
+  $background: #ffffff;
+  $card-bg: #f8f9fa;
+  $border: #e6e9ed;
+  $success: #34a853;
+  $warning: #fbbc05;
+  $error: #ea4335;
+  $shadow: 0 8px 24px rgba(0, 0, 0, 0.05);
+  
+  * {
+    margin: 0;
+    padding: 0;
+    box-sizing: border-box;
+  }
+  
+  /* 头部导航 */
+  .header {
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+    padding: 16px 0;
+    margin-bottom: 20px;
+    position: sticky;
+    top: 0;
+    background: transparent;
+    z-index: 100;
+  }
+  
+  .back-btn {
+    width: 40px;
+    height: 40px;
+    border-radius: 50%;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    background: $background;
+    border: none;
+    color: $text-dark;
+    font-size: 18px;
+    cursor: pointer;
+    transition: all 0.3s ease;
+    box-shadow: $shadow;
+    
+    &:hover {
+      background: $primary-light;
+      color: $primary;
+    }
+  }
+  
+  .title {
+    font-size: 24px;
+    font-weight: 700;
+    color: $text-dark;
+    text-align: center;
+    flex-grow: 1;
+    text-shadow: 0 2px 4px rgba(0,0,0,0.05);
+  }
+  
+  /* 卡片样式 */
+  .card {
+    background: $background;
+    border-radius: 20px;
+    padding: 24px;
+    margin-bottom: 20px;
+    box-shadow: $shadow;
+    position: relative;
+    overflow: hidden;
+    border: 1px solid rgba(66, 133, 244, 0.1);
+    transition: transform 0.3s ease, box-shadow 0.3s ease;
+    
+    &:hover {
+      transform: translateY(-5px);
+      box-shadow: 0 12px 30px rgba(66, 133, 244, 0.15);
+    }
+  }
+  
+  .card-header {
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+    margin-bottom: 20px;
+  }
+  
+  .card-title {
+    font-size: 18px;
+    font-weight: 700;
+    color: $text-dark;
+  }
+  
+  .card-subtitle {
+    font-size: 14px;
+    color: $text-light;
+    margin-top: 4px;
+  }
+  
+  /* 上传控制台 */
+  .upload-console {
+    position: relative;
+    min-height: 220px;
+  }
+  
+  .source-tags {
+    display: flex;
+    gap: 10px;
+    margin-top: 20px;
+    flex-wrap: wrap;
+  }
+  
+  .source-tag {
+    background: #f0f4f8;
+    padding: 8px 16px;
+    border-radius: 20px;
+    font-size: 14px;
+    color: $text-dark;
+    transition: all 0.2s ease;
+    border: 1px solid transparent;
+    cursor: pointer;
+    box-shadow: 0 2px 5px rgba(0,0,0,0.05);
+    
+    &.active {
+      border-color: $primary;
+      box-shadow: 0 0 0 2px rgba(66, 133, 244, 0.3);
+      color: $primary;
+      font-weight: 600;
+      background: rgba(66, 133, 244, 0.08);
+    }
+  }
+  
+  /* 自定义标签区域 */
+  .custom-tag-form {
+    display: flex;
+    margin-top: 25px;
+    gap: 10px;
+    align-items: center;
+  }
+  
+  .custom-tag-input {
+    flex: 1;
+    padding: 12px 18px;
+    border-radius: 20px;
+    border: 1px solid $border;
+    outline: none;
+    font-size: 14px;
+    transition: border-color 0.3s;
+    background: $card-bg;
+    box-shadow: inset 0 2px 4px rgba(0,0,0,0.03);
+    
+    &:focus {
+      border-color: $primary;
+      box-shadow: 0 0 0 2px rgba(66, 133, 244, 0.2);
+    }
+  }
+  
+  .add-tag-btn {
+    background: $primary;
+    color: white;
+    border: none;
+    border-radius: 20px;
+    padding: 12px 24px;
+    font-size: 14px;
+    font-weight: 600;
+    cursor: pointer;
+    transition: background 0.3s;
+    display: flex;
+    align-items: center;
+    gap: 8px;
+    box-shadow: 0 4px 10px rgba(66, 133, 244, 0.3);
+    
+    &:hover {
+      background: $primary-dark;
+      transform: translateY(-2px);
+      box-shadow: 0 6px 15px rgba(66, 133, 244, 0.4);
+    }
+  }
+  
+  /* 数据看板 */
+  .stats-container {
+    display: flex;
+    justify-content: space-between;
+    gap: 15px;
+    margin-top: 15px;
+  }
+  
+  .stat-item {
+    flex: 1;
+    text-align: center;
+    padding: 15px;
+    border-radius: 16px;
+    background: $background;
+    position: relative;
+    box-shadow: 0 4px 10px rgba(0,0,0,0.03);
+    border: 1px solid rgba(66, 133, 244, 0.08);
+  }
+  
+  .stat-value {
+    font-size: 24px;
+    font-weight: 700;
+    color: $text-dark;
+    margin: 10px 0;
+  }
+  
+  .stat-label {
+    font-size: 13px;
+    color: $text-light;
+  }
+  
+  .progress-ring {
+    position: relative;
+    width: 80px;
+    height: 80px;
+    margin: 0 auto;
+  }
+  
+  .progress-bg {
+    width: 100%;
+    height: 100%;
+    border-radius: 50%;
+    background: conic-gradient($primary 0% 75%, $border 75% 100%);
+    display: flex;
+    align-items: center;
+    justify-content: center;
+  }
+  
+  .progress-inner {
+    width: 70px;
+    height: 70px;
+    border-radius: 50%;
+    background: $card-bg;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    font-size: 18px;
+    font-weight: 700;
+    color: $text-dark;
+  }
+  
+  .quality-bar {
+    height: 8px;
+    background: $border;
+    border-radius: 4px;
+    margin-top: 15px;
+    overflow: hidden;
+    position: relative;
+  }
+  
+  .quality-fill {
+    height: 100%;
+    width: 85%;
+    background: linear-gradient(90deg, $primary, $primary-dark);
+    border-radius: 4px;
+    position: relative;
+    
+    &::after {
+      content: '';
+      position: absolute;
+      top: 0;
+      left: 0;
+      right: 0;
+      bottom: 0;
+      background: linear-gradient(90deg, 
+        transparent, 
+        rgba(255, 255, 255, 0.5),
+        transparent);
+      animation: wave 2s linear infinite;
+    }
+  }
+  
+  @keyframes wave {
+    0% { transform: translateX(-100%); }
+    100% { transform: translateX(100%); }
+  }
+  
+  .alert-badge {
+    position: absolute;
+    top: -8px;
+    right: -8px;
+    width: 24px;
+    height: 24px;
+    border-radius: 50%;
+    background: $error;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    color: white;
+    font-size: 12px;
+    font-weight: bold;
+    animation: pulse 1.5s infinite;
+  }
+  
+  @keyframes pulse {
+    0% { box-shadow: 0 0 0 0 rgba(234, 67, 53, 0.7); }
+    70% { box-shadow: 0 0 0 8px rgba(234, 67, 53, 0); }
+    100% { box-shadow: 0 0 0 0 rgba(234, 67, 53, 0); }
+  }
+  
+  /* 训练结果展示 */
+  .training-results {
+    margin-top: 25px;
+  }
+  
+  .result-item {
+    display: flex;
+    align-items: center;
+    padding: 15px 0;
+    border-bottom: 1px solid $border;
+    transition: all 0.2s ease;
+    
+    &:hover {
+      background: rgba(66, 133, 244, 0.03);
+      border-radius: 12px;
+      padding: 15px;
+    }
+    
+    &:last-child {
+      border-bottom: none;
+    }
+  }
+  
+  .result-icon {
+    width: 40px;
+    height: 40px;
+    border-radius: 12px;
+    background: $primary-light;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    color: $primary;
+    margin-right: 15px;
+    font-size: 18px;
+  }
+  
+  .result-content {
+    flex: 1;
+  }
+  
+  .result-title {
+    font-weight: 600;
+    color: $text-dark;
+    margin-bottom: 4px;
+  }
+  
+  .result-meta {
+    display: flex;
+    font-size: 13px;
+    color: $text-light;
+    flex-wrap: wrap;
+    gap: 10px;
+  }
+  
+  .result-date {
+    display: flex;
+    align-items: center;
+    gap: 5px;
+  }
+  
+  .result-status {
+    padding: 4px 10px;
+    border-radius: 20px;
+    font-size: 12px;
+    font-weight: 600;
+    
+    &.status-completed {
+      background: rgba(52, 168, 83, 0.1);
+      color: $success;
+    }
+    
+    &.status-training {
+      background: rgba(251, 188, 5, 0.1);
+      color: $warning;
+    }
+    
+    &.status-error {
+      background: rgba(234, 67, 53, 0.1);
+      color: $error;
+    }
+  }
+  
+  /* 数据记录部分 */
+  .data-record {
+    margin-top: 25px;
+  }
+  
+  .record-header {
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+    margin-bottom: 15px;
+  }
+  
+  .view-all {
+    color: $primary;
+    font-size: 14px;
+    text-decoration: none;
+    cursor: pointer;
+    display: flex;
+    align-items: center;
+    gap: 5px;
+  }
+  
+  .record-list {
+    display: grid;
+    grid-template-columns: repeat(2, 1fr);
+    gap: 15px;
+  }
+  
+  .record-item {
+    background: $card-bg;
+    border-radius: 16px;
+    padding: 15px;
+    box-shadow: 0 4px 10px rgba(0, 0, 0, 0.03);
+    border: 1px solid rgba(66, 133, 244, 0.08);
+    transition: all 0.3s ease;
+    
+    &:hover {
+      transform: translateY(-3px);
+      box-shadow: 0 6px 15px rgba(66, 133, 244, 0.15);
+    }
+  }
+  
+  .record-title {
+    font-size: 14px;
+    font-weight: 600;
+    color: $text-dark;
+    margin-bottom: 10px;
+    display: flex;
+    align-items: center;
+    gap: 5px;
+  }
+  
+  .record-value {
+    font-size: 22px;
+    font-weight: 700;
+    color: $primary;
+  }
+  
+  .record-trend {
+    display: flex;
+    align-items: center;
+    font-size: 12px;
+    margin-top: 5px;
+    
+    &.trend-up {
+      color: $success;
+    }
+    
+    &.trend-down {
+      color: $error;
+    }
+  }
+  
+  .trend-icon {
+    margin-right: 4px;
+  }
+  
+  /* 历史数据记录 */
+  .history-list {
+    max-height: 200px;
+    overflow-y: auto;
+    padding-right: 8px;
+  }
+  
+  .history-item {
+    display: flex;
+    align-items: center;
+    padding: 12px 0;
+    border-bottom: 1px solid $border;
+    transition: all 0.2s ease;
+    
+    &:hover {
+      background: rgba(66, 133, 244, 0.03);
+      border-radius: 12px;
+      padding: 12px;
+    }
+  }
+  
+  .history-icon {
+    width: 36px;
+    height: 36px;
+    border-radius: 10px;
+    background: $primary-light;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    color: $primary;
+    margin-right: 12px;
+    font-size: 16px;
+  }
+  
+  .history-content {
+    flex: 1;
+  }
+  
+  .history-name {
+    font-weight: 500;
+    margin-bottom: 4px;
+  }
+  
+  .history-meta {
+    display: flex;
+    font-size: 12px;
+    color: $text-light;
+    gap: 15px;
+  }
+  
+  .history-size {
+    display: flex;
+    align-items: center;
+    gap: 3px;
+  }
+  
+  .history-date {
+    color: $text-medium;
+    display: flex;
+    align-items: center;
+    gap: 3px;
+  }
+  
+  /* 页面标题装饰 */
+  .page-header {
+    text-align: center;
+    margin-bottom: 25px;
+  }
+  
+  .page-title {
+    font-size: 28px;
+    font-weight: 800;
+    color: $text-dark;
+    margin-bottom: 8px;
+    background: linear-gradient(90deg, #3367d6, #4285f4);
+    -webkit-background-clip: text;
+    -webkit-text-fill-color: transparent;
+    position: relative;
+    display: inline-block;
+  }
+  
+  .page-subtitle {
+    color: $text-light;
+    font-size: 16px;
+    max-width: 300px;
+    margin: 0 auto;
+  }
+  
+  /* 装饰元素 */
+  .decor-circle {
+    position: absolute;
+    width: 200px;
+    height: 200px;
+    border-radius: 50%;
+    background: linear-gradient(135deg, rgba(66, 133, 244, 0.1) 0%, rgba(66, 133, 244, 0.05) 100%);
+    z-index: -1;
+  }
+  
+  .circle-1 {
+    top: 10%;
+    left: -50px;
+  }
+  
+  .circle-2 {
+    bottom: 10%;
+    right: -50px;
+  }
+  
+  /* 新增搜索框样式 */
+  .search-container {
+    margin-bottom: 20px;
+    position: relative;
+  }
+  
+  .search-box {
+    display: flex;
+    align-items: center;
+    background: $card-bg;
+    border-radius: 30px;
+    padding: 8px 16px;
+    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
+    border: 1px solid $border;
+    
+    i {
+      color: $text-light;
+      margin-right: 10px;
+      font-size: 18px;
+    }
+  }
+  
+  .search-input {
+    flex: 1;
+    border: none;
+    background: transparent;
+    padding: 10px 0;
+    font-size: 15px;
+    color: $text-dark;
+    outline: none;
+    
+    &::placeholder {
+      color: $text-light;
+    }
+  }
+  
+  /* 上传控制台新样式 */
+  .upload-method-selector {
+    margin: 25px 0;
+  }
+  
+  .method-title {
+    font-size: 16px;
+    font-weight: 600;
+    margin-bottom: 12px;
+    color: $text-dark;
+  }
+  
+  .method-options {
+    display: flex;
+    gap: 15px;
+    flex-wrap: wrap;
+  }
+  
+  .method-option {
+    flex: 1;
+    min-width: 100px;
+    padding: 15px;
+    background: $card-bg;
+    border-radius: 16px;
+    text-align: center;
+    cursor: pointer;
+    transition: all 0.3s ease;
+    border: 1px solid $border;
+    
+    &:hover {
+      transform: translateY(-3px);
+      box-shadow: 0 6px 15px rgba(66, 133, 244, 0.1);
+    }
+    
+    &.active {
+      border-color: $primary;
+      background: $primary-light;
+      color: $primary;
+      font-weight: 600;
+    }
+  }
+  
+  .method-icon {
+    font-size: 24px;
+    margin-bottom: 10px;
+    color: $primary;
+  }
+  
+  .upload-action {
+    display: flex;
+    justify-content: center;
+    margin-top: 15px;
+  }
+  
+  .upload-button {
+    background: $primary;
+    color: white;
+    border: none;
+    border-radius: 30px;
+    padding: 15px 40px;
+    font-size: 16px;
+    font-weight: 600;
+    cursor: pointer;
+    transition: all 0.3s ease;
+    display: flex;
+    align-items: center;
+    gap: 10px;
+    box-shadow: 0 6px 15px rgba(66, 133, 244, 0.3);
+    
+    &:hover {
+      background: $primary-dark;
+      transform: translateY(-2px);
+      box-shadow: 0 8px 20px rgba(66, 133, 244, 0.4);
+    }
+    
+    &:active {
+      transform: translateY(0);
+    }
+  }
+  
+  /* 上传状态指示器 */
+  .upload-status {
+    margin-top: 20px;
+    padding: 15px;
+    border-radius: 16px;
+    background: rgba(52, 168, 83, 0.1);
+    color: $success;
+    text-align: center;
+    
+    &.error {
+      background: rgba(234, 67, 53, 0.1);
+      color: $error;
+    }
+  }
+  
+  .upload-progress {
+    height: 6px;
+    background: $border;
+    border-radius: 3px;
+    margin-top: 10px;
+    overflow: hidden;
+  }
+  
+  .progress-bar {
+    height: 100%;
+    width: 0%;
+    background: linear-gradient(90deg, $primary, $primary-dark);
+    border-radius: 3px;
+    transition: width 0.3s ease;
+  }

+ 183 - 6
ai-assisant/src/modules/crm/mobile/page-crm-data/page-crm-data.ts

@@ -1,11 +1,188 @@
-import { Component } from '@angular/core';
+// page-crm-data.component.ts
+import { Component, ViewChild, ElementRef, AfterViewInit } from '@angular/core';
+import { CommonModule } from '@angular/common';
+import { FormsModule } from '@angular/forms';
 
 @Component({
   selector: 'app-page-crm-data',
-  imports: [],
-  templateUrl: './page-crm-data.html',
-  styleUrl: './page-crm-data.scss'
+  standalone: true,
+  imports: [CommonModule, FormsModule],
+  templateUrl: './page-crm-data.html', // 确保路径正确
+  styleUrls: ['./page-crm-data.scss']
 })
-export class PageCrmData {
 
-}
+export class PageCrmData implements AfterViewInit {
+  // 标签相关数据
+  sourceTags = [
+    { name: '会议记录', active: true },
+    { name: '客户合同', active: false },
+    { name: '反馈表', active: false },
+    { name: '培训资料', active: false }
+  ];
+  
+  newTag = '';
+  
+  // 上传方式
+  uploadMethods = [
+    { name: '拍照', icon: 'camera', active: false },
+    { name: '文件', icon: 'file', active: false },
+    { name: '录音', icon: 'microphone', active: false },
+    { name: '文本', icon: 'keyboard', active: false }
+  ];
+  
+  // 上传状态
+  uploadStatus = {
+    visible: false,
+    progress: 0,
+    message: '',
+    success: false
+  };
+  
+  // 历史记录
+  historyItems = [
+    { name: 'Q3销售报告.pdf', type: 'pdf', size: 4.2, date: '2023-10-15' },
+    { name: '客户数据.xlsx', type: 'excel', size: 3.1, date: '2023-10-14' },
+    { name: '会议纪要.docx', type: 'word', size: 1.7, date: '2023-10-13' },
+    { name: '用户反馈.csv', type: 'csv', size: 2.3, date: '2023-10-12' }
+  ];
+  
+  filteredHistory = [...this.historyItems];
+  searchTerm = '';
+  
+  // 训练结果
+  trainingResults = [
+    { title: '销售预测模型', time: '2.3小时', status: 'completed', icon: 'brain' },
+    { title: '情感分析模型', time: '1.5小时', status: 'training', icon: 'comments' },
+    { title: '趋势预测模型', time: '3.1小时', status: 'completed', icon: 'chart-line' },
+    { title: '客户服务模型', time: '4.2小时', status: 'error', icon: 'robot' }
+  ];
+  
+  // 数据看板
+  dashboardStats = [
+    { label: '新增数据', value: 42, trend: 12, trendUp: true, icon: 'file-medical' },
+    { label: '处理中', value: 18, trend: 5, trendUp: false, icon: 'cogs' },
+    { label: '训练时间', value: '1.8h', trend: 23, trendUp: true, icon: 'clock' },
+    { label: '完成率', value: '76%', trend: 8, trendUp: true, icon: 'check-circle' }
+  ];
+  
+  // 选择标签
+  selectTag(tag: any) {
+    this.sourceTags.forEach(t => t.active = false);
+    tag.active = true;
+  }
+  
+  // 添加新标签
+  addTag() {
+    if (this.newTag.trim()) {
+      this.sourceTags.push({ name: this.newTag.trim(), active: true });
+      this.selectTag(this.sourceTags[this.sourceTags.length - 1]);
+      this.newTag = '';
+    }
+  }
+  
+  // 选择上传方式
+  selectMethod(method: any) {
+    this.uploadMethods.forEach(m => m.active = false);
+    method.active = true;
+  }
+  
+  // 上传数据
+  uploadData() {
+    const selectedTag = this.sourceTags.find(t => t.active)?.name || '未知';
+    const selectedMethod = this.uploadMethods.find(m => m.active)?.name || '未选择';
+    
+    this.uploadStatus = {
+      visible: true,
+      progress: 0,
+      message: `正在上传: ${selectedTag} (方式: ${selectedMethod})`,
+      success: false
+    };
+    
+    // 模拟上传进度
+    const interval = setInterval(() => {
+      this.uploadStatus.progress += Math.floor(Math.random() * 10);
+      
+      if (this.uploadStatus.progress >= 100) {
+        this.uploadStatus.progress = 100;
+        clearInterval(interval);
+        
+        // 上传完成
+        setTimeout(() => {
+          this.uploadStatus.message = `<i class="fas fa-check-circle"></i> 上传成功: ${selectedTag} (方式: ${selectedMethod})`;
+          this.uploadStatus.success = true;
+          
+          // 添加新项目到历史记录
+          this.addHistoryItem(selectedTag, selectedMethod);
+          
+          // 3秒后隐藏状态
+          setTimeout(() => {
+            this.uploadStatus.visible = false;
+          }, 3000);
+        }, 500);
+      }
+    }, 200);
+  }
+  
+  // 添加历史记录
+  addHistoryItem(tagName: string, methodName: string) {
+    const fileType = this.getFileExtension(methodName);
+    
+    this.historyItems.unshift({
+      name: `${tagName}.${fileType}`,
+      type: fileType,
+      size: +(Math.random() * 5).toFixed(1),
+      date: this.getCurrentDate()
+    });
+    
+    this.filterHistory();
+  }
+  
+  // 获取文件扩展名
+  getFileExtension(method: string): string {
+    switch(method) {
+      case '拍照': return 'jpg';
+      case '文件': return 'pdf';
+      case '录音': return 'mp3';
+      case '文本': return 'txt';
+      default: return 'dat';
+    }
+  }
+  
+  // 获取当前日期
+  getCurrentDate(): string {
+    const now = new Date();
+    const year = now.getFullYear();
+    const month = String(now.getMonth() + 1).padStart(2, '0');
+    const day = String(now.getDate()).padStart(2, '0');
+    return `${year}-${month}-${day}`;
+  }
+  
+  // 搜索历史记录
+  filterHistory() {
+    if (!this.searchTerm.trim()) {
+      this.filteredHistory = [...this.historyItems];
+      return;
+    }
+    
+    const term = this.searchTerm.toLowerCase();
+    this.filteredHistory = this.historyItems.filter(item => 
+      item.name.toLowerCase().includes(term) || 
+      item.type.toLowerCase().includes(term) ||
+      item.date.includes(term)
+    );
+  }
+  
+  // 随机更新数据看板
+  ngAfterViewInit() {
+    setInterval(() => {
+      this.dashboardStats = this.dashboardStats.map(stat => {
+        if (typeof stat.value === 'number') {
+          const change = Math.floor(Math.random() * 5) - 2; // -2 到 2 之间的随机数
+          const newValue = Math.max(0, stat.value + change);
+          return { ...stat, value: newValue };
+        }
+        return stat;
+      });
+    }, 5000);
+  }
+}

+ 6 - 0
package-lock.json

@@ -0,0 +1,6 @@
+{
+  "name": "ai-salesperson-assistant",
+  "lockfileVersion": 3,
+  "requires": true,
+  "packages": {}
+}