Bladeren bron

Merge branch 'master' of http://git.fmode.cn:3000/nkkj/yss-project

徐福静0235668 1 dag geleden
bovenliggende
commit
c955fbffd9

+ 31 - 28
src/app/pages/team-leader/dashboard/dashboard.html

@@ -61,37 +61,40 @@
     
     <!-- 项目看板 - 横向展开10个项目阶段 -->
     <div class="project-kanban">
-      <!-- 阶段标题 -->
-      <div class="kanban-header">
-        <div class="kanban-column-header" *ngFor="let stage of projectStages">
-          <h3>{{ stage.name }}</h3>
-          <span class="stage-count">{{ getProjectCountByStage(stage.id) }}</span>
+      <!-- 新增:公共横向滚动容器,保证表头与表体同步滚动 -->
+      <div class="kanban-scroll">
+        <!-- 阶段标题 -->
+        <div class="kanban-header">
+          <div class="kanban-column-header" *ngFor="let stage of projectStages">
+            <h3>{{ stage.name }}</h3>
+            <span class="stage-count">{{ getProjectCountByStage(stage.id) }}</span>
+          </div>
         </div>
-      </div>
-      <!-- 项目卡片 -->
-      <div class="kanban-body">
-        <div class="kanban-column" *ngFor="let stage of projectStages">
-          <div *ngFor="let project of getProjectsByStage(stage.id)" 
-               class="project-card" 
-               [class.overdue]="project.isOverdue" 
-               [class.high-urgency]="project.urgency === 'high'">
-            <div class="project-card-header">
-              <h4 [routerLink]="['/team-leader/project-review', project.id]">{{ project.name }}</h4>
-              <span class="project-urgency" [class]="'urgency-' + project.urgency">{{ getUrgencyLabel(project.urgency) }}</span>
+        <!-- 项目卡片 -->
+        <div class="kanban-body">
+          <div class="kanban-column" *ngFor="let stage of projectStages">
+            <div *ngFor="let project of getProjectsByStage(stage.id)" 
+                 class="project-card" 
+                 [class.overdue]="project.isOverdue" 
+                 [class.high-urgency]="project.urgency === 'high'">
+              <div class="project-card-header">
+                <h4 [routerLink]="['/team-leader/project-review', project.id]">{{ project.name }}</h4>
+                <span class="project-urgency" [class]="'urgency-' + project.urgency">{{ getUrgencyLabel(project.urgency) }}</span>
+              </div>
+              <div class="project-card-content">
+                <p>负责人: {{ project.designerName }}</p>
+                <p class="deadline">{{ project.isOverdue ? '超期' + project.overdueDays + '天' : '截止: ' + (project.expectedEndDate | date:'MM-dd') }}</p>
+              </div>
+              <div class="project-card-footer">
+                <button (click)="viewProjectDetails(project.id)" class="btn-view">查看详情</button>
+                <button (click)="quickAssignProject(project.id)" *ngIf="stage.id === 'pendingAssignment'" class="btn-assign">分配</button>
+              </div>
             </div>
-            <div class="project-card-content">
-              <p>负责人: {{ project.designerName }}</p>
-              <p class="deadline">{{ project.isOverdue ? '超期' + project.overdueDays + '天' : '截止: ' + (project.expectedEndDate | date:'MM-dd') }}</p>
+            <!-- 空状态 -->
+            <div *ngIf="getProjectsByStage(stage.id).length === 0" class="empty-column">
+              <span class="empty-icon">📦</span>
+              <p>暂无项目</p>
             </div>
-            <div class="project-card-footer">
-              <button (click)="viewProjectDetails(project.id)" class="btn-view">查看详情</button>
-              <button (click)="quickAssignProject(project.id)" *ngIf="stage.id === 'pendingAssignment'" class="btn-assign">分配</button>
-            </div>
-          </div>
-          <!-- 空状态 -->
-          <div *ngIf="getProjectsByStage(stage.id).length === 0" class="empty-column">
-            <span class="empty-icon">📦</span>
-            <p>暂无项目</p>
           </div>
         </div>
       </div>

+ 68 - 22
src/app/pages/team-leader/dashboard/dashboard.scss

@@ -84,6 +84,33 @@
   }
 }
 
+/* 极窄屏样式优化:减小列间距与列宽,保证可视密度 */
+@media (max-width: 640px) {
+  .project-kanban {
+    .kanban-header {
+      gap: $ios-spacing-sm;
+    }
+    .kanban-body {
+      gap: $ios-spacing-sm;
+      .kanban-column {
+        min-width: 160px;
+        max-width: 160px;
+      }
+    }
+  }
+}
+
+@media (max-width: 480px) {
+  .project-kanban {
+    .kanban-body {
+      .kanban-column {
+        min-width: 150px;
+        max-width: 150px;
+      }
+    }
+  }
+}
+
 .dashboard-main {
   max-width: 1400px;
   margin: 0 auto;
@@ -161,15 +188,54 @@
   position: relative;
   z-index: 1;
   
+  // 新增:公共横向滚动容器,保持表头与表体同步滚动
+  .kanban-scroll {
+    overflow-x: auto;
+    padding-bottom: $ios-spacing-md; // 与原来kanban-body一致的底部留白
+    -webkit-overflow-scrolling: touch; // 触屏设备启用惯性滚动
+
+    // 滚动条样式沿用原有
+    &::-webkit-scrollbar {
+      height: 6px;
+    }
+    
+    &::-webkit-scrollbar-track {
+      background: $ios-background;
+      border-radius: $ios-radius-full;
+    }
+    
+    &::-webkit-scrollbar-thumb {
+      background: $ios-border;
+      border-radius: $ios-radius-full;
+    }
+    
+    &::-webkit-scrollbar-thumb:hover {
+      background: $ios-text-tertiary;
+    }
+
+    // 让表头和表体在同一行内布局,从而一起横向滚动
+    .kanban-header,
+    .kanban-body {
+      width: max-content; // 根据列数量自适应宽度
+    }
+  }
+  
   // 看板标题行
   .kanban-header {
+    position: sticky;
+    top: 0; // 如需避开全局固定导航,可改为具体偏移值
+    z-index: 2; // 位于列内容之上
+    background: $ios-card-background; // 与父容器一致,防止滚动时透底
+    border-bottom: 1px solid $ios-border; // 细分隔线,避免视觉抖动
     display: flex;
     gap: $ios-spacing-md;
     margin-bottom: $ios-spacing-md;
     
     .kanban-column-header {
-      flex: 1;
+      // 固定列宽,确保与内容列完美对齐
+      flex: 0 0 180px;
       min-width: 180px;
+      max-width: 180px;
       display: flex;
       justify-content: space-between;
       align-items: center;
@@ -200,27 +266,6 @@
   .kanban-body {
     display: flex;
     gap: $ios-spacing-md;
-    overflow-x: auto;
-    padding-bottom: $ios-spacing-md;
-    
-    // 滚动条样式
-    &::-webkit-scrollbar {
-      height: 6px;
-    }
-    
-    &::-webkit-scrollbar-track {
-      background: $ios-background;
-      border-radius: $ios-radius-full;
-    }
-    
-    &::-webkit-scrollbar-thumb {
-      background: $ios-border;
-      border-radius: $ios-radius-full;
-    }
-    
-    &::-webkit-scrollbar-thumb:hover {
-      background: $ios-text-tertiary;
-    }
     
     // 看板列
     .kanban-column {
@@ -233,6 +278,7 @@
       border: 1px solid $ios-border;
       padding: $ios-spacing-sm;
       overflow-y: auto;
+      -webkit-overflow-scrolling: touch; // 移动端列内纵向惯性滚动
       
       // 滚动条样式
       &::-webkit-scrollbar {

+ 46 - 0
src/app/pages/team-leader/dashboard/dashboard.ts

@@ -196,6 +196,52 @@ export class Dashboard implements OnInit {
       }
     ];
 
+    // ===== 追加生成示例数据:保证总量达到100条 =====
+    const stageIds = this.projectStages.map(s => s.id);
+    const designers = ['张三','李四','王五','赵六','钱七','孙八','周九','吴十','郑一','冯二','陈三','褚四'];
+    const statusMap: Record<string, string> = {
+      pendingApproval: '待确认',
+      pendingAssignment: '待分配',
+      requirement: '进行中',
+      planning: '进行中',
+      modeling: '进行中',
+      rendering: '进行中',
+      postProduction: '进行中',
+      review: '进行中',
+      revision: '进行中',
+      delivery: '已完成'
+    };
+
+    for (let i = 8; i <= 100; i++) {
+      const stageIndex = (i - 1) % stageIds.length;
+      const currentStage = stageIds[stageIndex];
+      const type: 'soft' | 'hard' = i % 2 === 0 ? 'soft' : 'hard';
+      const urgency: 'high' | 'medium' | 'low' = i % 5 === 0 ? 'high' : (i % 3 === 0 ? 'medium' : 'low');
+      const isOverdue = ['planning','modeling','rendering','postProduction','review','revision','delivery'].includes(currentStage) ? i % 7 === 0 : false;
+      const overdueDays = isOverdue ? (i % 10) + 1 : 0;
+      const hasDesigner = !['pendingApproval', 'pendingAssignment'].includes(currentStage);
+      const designerName = hasDesigner ? designers[i % designers.length] : '';
+      const status = statusMap[currentStage] || '进行中';
+      const expectedEndDate = new Date();
+      const daysOffset = isOverdue ? - (overdueDays + (i % 5)) : ((i % 20) + 3);
+      expectedEndDate.setDate(expectedEndDate.getDate() + daysOffset);
+
+      this.projects.push({
+        id: `proj-${String(i).padStart(3, '0')}`,
+        name: `${type === 'soft' ? '软装' : '硬装'}示例项目 ${i}`,
+        type,
+        designerName,
+        status,
+        expectedEndDate,
+        isOverdue,
+        overdueDays,
+        urgency,
+        currentStage,
+        phases: []
+      });
+    }
+    // ===== 示例数据生成结束 =====
+
     // 筛选超期项目
     this.overdueProjects = this.projects.filter(project => project.isOverdue);
     this.filteredProjects = [...this.projects];