Kaynağa Gözat

feat(项目详情): 添加项目状态显示功能并重构头部布局

添加获取项目状态文本、当前阶段文本和整体进度百分比的方法
将导航按钮移动到标题左侧并添加进度展示区域到头部右侧
移除旧的四大板块按钮组并优化响应式布局
0235711 6 saat önce
ebeveyn
işleme
73cd01e2b4

+ 1 - 7
.trae/rules/project_rules.md

@@ -3,10 +3,4 @@
 ========
 
 - 模板页面显示的条件和循环应统一使用控制流指令:@if 与 @for。
-=======
-
-# 项目规范
-
-模板页面显示的条件和循环采用控制流的@if和@for
->>>>>>> c955fbffd90c3e0d8285002bb4c199a356069c1a
->>>>>>> 60a6661d67681242039cf8f2e7002a1a80af63fe
+========

+ 19 - 22
src/app/pages/designer/project-detail/project-detail.html

@@ -14,17 +14,26 @@
       </div>
     </div>
     
+    <!-- 导航按钮区域 - 移动到标题左侧 -->
+    <div class="header-nav">
+      <app-vertical-nav 
+        [activeTab]="activeTab" 
+        (tabChange)="switchTab($event)"
+        class="header-nav-tabs">
+      </app-vertical-nav>
+    </div>
+
+    <!-- 进度展示区域 - 移动到右侧 -->
+    <div class="header-center">
+      <div class="progress-display">
+        <span class="progress-status">{{ getProjectStatusText() }}</span>
+        <span class="progress-stage">{{ getCurrentStageText() }}</span>
+        <span class="progress-percentage">({{ getOverallProgress() }}%)</span>
+      </div>
+    </div>
+    
     <div class="header-right">
       <div class="header-actions">
-        <!-- 导航条 - 移动到顶部与导出按钮水平对齐 -->
-        <div class="top-nav-container">
-          <app-vertical-nav 
-            [activeTab]="activeTab" 
-            (tabChange)="switchTab($event)"
-            class="top-nav">
-          </app-vertical-nav>
-        </div>
-        
         <!-- 导出阶段报告 -->
         <button (click)="exportProjectReport()" class="action-btn secondary-btn">
           <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
@@ -88,19 +97,7 @@
 
 </div>
 
-<!-- 四大板块按钮组 - 位于项目详情标题区域正下方 -->
-<div class="sections-toolbar-header">
-  @for (sec of sections; track sec.key) {
-    <button class="section-btn"
-            [class.completed]="getSectionStatus(sec.key) === 'completed'"
-            [class.active]="getSectionStatus(sec.key) === 'active'"
-            [class.pending]="getSectionStatus(sec.key) === 'pending'"
-            [class.current-order]="sec.key === 'order' && isCurrentOrderCreation()"
-            (click)="toggleSection(sec.key)">
-      <span class="section-label">{{ sec.label }}</span>
-    </button>
-  }
-</div>
+
 
 <!-- 图片预览模态框 -->
 @if (showImagePreview) {

+ 176 - 116
src/app/pages/designer/project-detail/project-detail.scss

@@ -11,73 +11,7 @@
   overflow-x: auto; // 允许水平滚动以防内容过宽
 }
 
-/* 四大板块按钮组 - 位于项目标题区域正下方 */
-.sections-toolbar-header {
-  display: flex;
-  gap: 1%; // 使用百分比间距
-  width: 100%;
-  margin: 1.5% 0 2% 0; // 使用百分比边距
-  padding: 0 2%; /* 与项目详情容器保持一致的左右边距 */
-  
-  .section-btn {
-    flex: 1;
-    appearance: none;
-    border: 1px solid $ios-border;
-    background: $ios-background;
-    color: $ios-text-primary;
-    padding: 0.9rem 1.2rem; // 使用rem单位
-    border-radius: $ios-radius-md;
-    font-size: 0.9rem; // 使用rem单位
-    font-weight: 500;
-    cursor: pointer;
-    transition: all 0.2s ease;
-    text-align: center;
-    min-height: 3rem; // 使用rem单位
-    display: flex;
-    align-items: center;
-    justify-content: center;
-    
-    .section-label {
-      white-space: nowrap;
-      overflow: hidden;
-      text-overflow: ellipsis;
-    }
-    
-    &:hover {
-      transform: translateY(-0.08rem); // 使用rem单位
-      box-shadow: 0 0.3rem 0.9rem rgba(0, 0, 0, 0.1);
-    }
-    
-    &.completed {
-      background: linear-gradient(135deg, #e6f7e6 0%, #d4edda 100%);
-      color: $ios-success;
-      border-color: $ios-success;
-      box-shadow: 0 0.15rem 0.6rem rgba(40, 167, 69, 0.15);
-    }
-    
-    &.active {
-      background: linear-gradient(135deg, #fff2f0 0%, #ffe6e6 100%);
-      color: #ff4d4f;
-      border-color: #ff4d4f;
-      box-shadow: 0 0.15rem 0.6rem rgba(255, 77, 79, 0.2);
-    }
-    
-    &.pending {
-      background: $ios-background;
-      color: $ios-text-secondary;
-      border-color: rgba(0, 0, 0, 0.1);
-    }
-    
-    // 订单创建按钮的红色高亮状态
-    &.current-order {
-      background: linear-gradient(135deg, #ffe6e6 0%, #ffcccc 100%);
-      color: #d32f2f;
-      border-color: #d32f2f;
-      box-shadow: 0 0.15rem 0.6rem rgba(211, 47, 47, 0.2);
-      font-weight: 600;
-    }
-  }
-}
+
 
 // 图片预览模态框样式
 .image-preview-modal {
@@ -1141,9 +1075,10 @@
   box-sizing: border-box;
   position: relative; // 确保下拉菜单正确定位
   box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
+  gap: $ios-spacing-lg; // 添加元素间距
   
   .header-left {
-    flex: 1;
+    flex: 0 0 auto; // 改为固定宽度,不拉伸
     
     .header-content {
       h1 {
@@ -1174,63 +1109,141 @@
       }
     }
   }
-  
-  .header-right {
-    .header-actions {
+
+  // 中央进度展示区域
+  .header-center {
+    display: flex;
+    align-items: center;
+    justify-content: center; // 改回居中对齐
+    flex: 1;
+    margin: 0 20px; // 左右各20px边距
+
+    .progress-display {
       display: flex;
       align-items: center;
-      gap: $ios-spacing-sm;
-      
-      // 顶部导航条容器样式
-      .top-nav-container {
-        display: flex;
-        align-items: center;
-        margin-right: $ios-spacing-md; // 与导出按钮保持间距
+      gap: 10px;
+      padding: 10px 18px; // 适度减少内边距
+      background: linear-gradient(135deg, #f8fafc 0%, #e2e8f0 100%); // 更柔和的灰色渐变
+      border: 1px solid #cbd5e1; // 更柔和的边框
+      border-radius: 8px; // 适中的圆角
+      font-size: 15px; // 适中的字体大小
+      box-shadow: 0 2px 8px rgba(148, 163, 184, 0.15), 0 0 0 1px rgba(148, 163, 184, 0.05); // 更柔和的阴影
+      transform: scale(1.05); // 适度放大
+      transition: all 0.3s ease-in-out; // 保持平滑过渡
+      position: relative;
+      overflow: hidden;
+
+      // 更柔和的闪烁效果
+      &::before {
+        content: '';
+        position: absolute;
+        top: 0;
+        left: -100%;
+        width: 100%;
+        height: 100%;
+        background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.4), transparent);
+        animation: shimmer 3s infinite; // 减慢动画速度
+      }
+
+      // 更柔和的悬停效果
+      &:hover {
+        transform: scale(1.08);
+        box-shadow: 0 4px 12px rgba(148, 163, 184, 0.2), 0 0 0 2px rgba(148, 163, 184, 0.1);
+      }
+
+      .progress-status {
+        font-weight: 600; // 减轻字体粗细
+        color: #1e40af; // 使用更协调的蓝色
+        text-shadow: none; // 移除文字阴影
+      }
+
+      .progress-stage {
+        color: #64748b; // 使用更协调的灰色
+        font-weight: 500;
+      }
+
+      .progress-percentage {
+        font-weight: 600; // 减轻字体粗细
+        color: #059669; // 使用更协调的绿色
+        text-shadow: none; // 移除文字阴影
+      }
+    }
+  }
+
+  // 添加闪烁动画
+  @keyframes shimmer {
+    0% {
+      left: -100%;
+    }
+    100% {
+      left: 100%;
+    }
+  }
+
+  // 导航按钮区域样式
+  .header-nav {
+    flex: 0 0 auto; // 改为固定宽度,不拉伸
+    display: flex;
+    justify-content: flex-start; // 保持左对齐
+    margin-left: 20px; // 距离标题20px
+    
+    .header-nav-tabs {
+      .horizontal-tab-nav {
+        background: rgba(0, 122, 255, 0.05);
+        border-radius: $ios-radius-md;
+        padding: 4px;
         
-        // 顶部导航条样式
-        .top-nav {
-          .vertical-nav {
+        .tab-container {
+          display: flex;
+          gap: 4px;
+          
+          .tab-item {
+            padding: 10px 20px;
+            border: none;
+            border-radius: $ios-radius-sm;
+            background: transparent;
+            color: $ios-text-primary;
+            font-size: $ios-font-size-sm;
+            font-weight: $ios-font-weight-medium;
+            cursor: pointer;
+            transition: all 0.2s ease;
+            white-space: nowrap;
+            min-height: 40px;
             display: flex;
-            flex-direction: row; // 水平排列
-            gap: 10px; // 导航按钮之间的间距
-            background: rgba(0, 122, 255, 0.05);
-            border-radius: 8px;
-            padding: 4px;
+            align-items: center;
+            justify-content: center;
             
-            .nav-item {
-              padding: 8px 16px;
-              border: none;
-              border-radius: 6px;
-              background: transparent;
-              color: $ios-text-primary;
-              font-size: 14px;
-              font-weight: 500;
-              cursor: pointer;
-              transition: all 0.2s ease;
-              white-space: nowrap;
-              min-height: 36px;
-              display: flex;
-              align-items: center;
-              justify-content: center;
-              
-              &:hover {
-                background: rgba(0, 122, 255, 0.1);
-                color: $ios-primary;
-              }
-              
-              &.active {
-                background: $ios-primary;
-                color: white;
-                font-weight: 600;
-              }
-              
-              .nav-text {
-                white-space: nowrap;
-              }
+            &:hover {
+              background: rgba(0, 122, 255, 0.1);
+              color: $ios-primary;
+            }
+            
+            &.active {
+              background: $ios-primary;
+              color: white;
+              font-weight: $ios-font-weight-semibold;
             }
           }
         }
+        
+        .tab-indicator {
+          background: $ios-primary;
+          border-radius: $ios-radius-sm;
+          box-shadow: 0 2px 8px rgba(0, 122, 255, 0.2);
+        }
       }
+    }
+  }
+  
+  .header-right {
+    flex: 0 0 auto; // 改为固定宽度,不拉伸
+    
+    .header-actions {
+      display: flex;
+      align-items: center;
+      gap: $ios-spacing-sm;
+      
+      // 原导航容器样式已移动到header-nav区域,此处保留空白以避免样式冲突
       
       .action-btn {
         padding: 10px 16px;
@@ -1412,7 +1425,34 @@
     align-items: stretch;
     gap: 16px;
     
+    .header-left {
+      order: 1;
+    }
+    
+    .header-nav {
+      order: 2;
+      justify-content: flex-start;
+      margin-left: 0; // 移动端取消左边距
+      margin-top: 8px; // 添加上边距
+      
+      .header-nav-tabs {
+        width: 100%;
+        
+        .horizontal-tab-nav {
+          .tab-container {
+            .tab-item {
+              padding: 8px 12px;
+              font-size: 13px;
+              min-height: 36px;
+            }
+          }
+        }
+      }
+    }
+    
     .header-right {
+      order: 3;
+      
       .header-actions {
         flex-wrap: wrap;
         justify-content: flex-end;
@@ -1428,6 +1468,26 @@
   }
 }
 
+@media (max-width: 480px) {
+  .project-header {
+    .header-nav {
+      .header-nav-tabs {
+        .horizontal-tab-nav {
+          .tab-container {
+            flex-direction: column;
+            gap: 2px;
+            
+            .tab-item {
+              width: 100%;
+              text-align: center;
+            }
+          }
+        }
+      }
+    }
+  }
+}
+
 /* 项目内容区域 */
 .project-content {
   .action-btn {

+ 55 - 0
src/app/pages/designer/project-detail/project-detail.ts

@@ -2088,6 +2088,61 @@ export class ProjectDetail implements OnInit, OnDestroy {
     }
   }
 
+  // 获取项目状态文本
+  getProjectStatusText(): string {
+    const current = (this.currentStage || this.project?.currentStage) as ProjectStage | undefined;
+    
+    if (!current || current === '订单创建') {
+      return '待开始';
+    }
+    
+    // 检查是否已完成所有阶段
+    const allStages: ProjectStage[] = ['订单创建', '需求沟通', '方案确认', '建模', '软装', '渲染', '后期', '尾款结算', '客户评价', '投诉处理'];
+    const currentIndex = allStages.indexOf(current);
+    
+    if (currentIndex === allStages.length - 1) {
+      return '已完成';
+    }
+    
+    return '进行中';
+  }
+
+  // 获取当前阶段文本
+  getCurrentStageText(): string {
+    const current = (this.currentStage || this.project?.currentStage) as ProjectStage | undefined;
+    
+    if (!current || current === '订单创建') {
+      return '订单创建阶段';
+    }
+    
+    return `${current}阶段`;
+  }
+
+  // 获取整体进度百分比
+  getOverallProgress(): number {
+    const current = (this.currentStage || this.project?.currentStage) as ProjectStage | undefined;
+    
+    if (!current) {
+      return 0;
+    }
+    
+    // 定义所有阶段及其权重
+    const stageWeights: Record<ProjectStage, number> = {
+      '订单创建': 5,
+      '需求沟通': 15,
+      '方案确认': 25,
+      '建模': 40,
+      '软装': 55,
+      '渲染': 70,
+      '后期': 85,
+      '尾款结算': 90,
+      '客户评价': 95,
+      '投诉处理': 100
+    };
+    
+    return stageWeights[current] || 0;
+  }
+
   // 获取必需阶段的完成进度百分比
   getRequiredStagesProgress(): number {
     let completedCount = 0;