소스 검색

feat:上传问题解决

徐福静0235668 2 일 전
부모
커밋
0e46473137

+ 163 - 205
src/app/pages/customer-service/dashboard/dashboard.html

@@ -63,8 +63,8 @@
         </div>
       </div>
 
-      <!-- 异常项目 - 已隐藏 -->
-      <!-- <div class="stat-card" (click)="handleExceptionProjectsClick()" title="点击查看异常项目详情">
+      <!-- 异常项目 -->
+      <div class="stat-card" (click)="handleExceptionProjectsClick()" title="点击查看异常项目详情">
         <div class="stat-icon danger">
           <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor">
             <path d="M10.29 3.86L1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0z"></path>
@@ -76,10 +76,10 @@
           <div class="stat-value">{{ stats.exceptionProjects() }}</div>
           <div class="stat-label">异常项目</div>
         </div>
-      </div> -->
+      </div>
 
-      <!-- 售后服务 - 已隐藏 -->
-      <!-- <div class="stat-card" (click)="handleAfterSalesClick()" title="点击查看售后服务详情">
+      <!-- 售后服务 -->
+      <div class="stat-card" (click)="handleAfterSalesClick()" title="点击查看售后服务详情">
         <div class="stat-icon success">
           <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor">
             <path d="M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z"></path>
@@ -89,7 +89,7 @@
           <div class="stat-value">{{ stats.afterSalesCount() }}</div>
           <div class="stat-label">售后服务</div>
         </div>
-      </div> -->
+      </div>
 
     </div>
 </section>
@@ -249,30 +249,25 @@
   </div>
 </section>
 
-<!-- 🆕 待办任务双栏布局(待办问题 + 紧急事件) -->
-<section class="urgent-tasks-section">
-  <div class="section-header">
-    <h2>待办事项</h2>
-  </div>
-  
-  <!-- 🆕 双栏容器 -->
-  <div class="todo-dual-columns">
-    <!-- ========== 左栏:紧急事件 ========== -->
-    <div class="todo-column todo-column-urgent">
-      <div class="column-header">
-        <h3>
-          <svg viewBox="0 0 24 24" width="18" height="18" fill="currentColor">
-            <path d="M1 21h22L12 2 1 21zm12-3h-2v-2h2v2zm0-4h-2v-4h2v4z"/>
-          </svg>
-          紧急事件
-          @if (urgentEventsList().length > 0) {
-            <span class="task-count urgent">({{ urgentEventsList().length }})</span>
-          }
-        </h3>
-        <span class="column-subtitle">自动计算的截止事件</span>
+<!-- 紧急事件和待办任务流 -->
+<div class="content-grid">
+  <!-- 紧急事件列表(⭐ 使用可复用组件) -->
+  <section class="urgent-tasks-section">
+    <div class="section-header">
+      <h3>紧急事件</h3>
+      <div style="display: flex; gap: 12px; align-items: center;">
+        <button 
+          class="btn-primary"
+          (click)="showTaskForm()"
+          style="font-size: 14px; padding: 6px 16px;"
+        >
+          添加紧急事项
+        </button>
+        <a href="/customer-service/project-list" class="view-all-link">查看全部</a>
       </div>
-      
-      <!-- 加载状态 -->
+    </div>
+    
+    <div class="tasks-list">
       @if (loadingUrgentEvents()) {
         <div class="loading-state">
           <svg class="spinner" viewBox="0 0 50 50">
@@ -281,8 +276,6 @@
           <p>计算紧急事件中...</p>
         </div>
       }
-      
-      <!-- 空状态 -->
       @if (!loadingUrgentEvents() && urgentEventsList().length === 0) {
         <div class="empty-state">
           <svg viewBox="0 0 24 24" width="64" height="64" fill="#d1d5db">
@@ -292,18 +285,12 @@
           <p class="hint">所有项目时间节点正常 ✅</p>
         </div>
       }
-      
-      <!-- 紧急事件列表 -->
       @if (!loadingUrgentEvents() && urgentEventsList().length > 0) {
         <div class="todo-list-compact urgent-list">
           @for (event of urgentEventsList(); track event.id) {
             <div class="todo-item-compact urgent-item" [attr.data-urgency]="event.urgencyLevel">
-              <!-- 左侧紧急程度色条 -->
               <div class="urgency-indicator" [attr.data-urgency]="event.urgencyLevel"></div>
-              
-              <!-- 事件内容 -->
               <div class="task-content">
-                <!-- 标题行 -->
                 <div class="task-header">
                   <span class="task-title">{{ event.title }}</span>
                   <div class="task-badges">
@@ -319,13 +306,7 @@
                     </span>
                   </div>
                 </div>
-                
-                <!-- 描述 -->
-                <div class="task-description">
-                  {{ event.description }}
-                </div>
-                
-                <!-- 项目信息行 -->
+                <div class="task-description">{{ event.description }}</div>
                 <div class="task-meta">
                   <span class="project-info">
                     <svg viewBox="0 0 24 24" width="12" height="12" fill="currentColor">
@@ -342,25 +323,16 @@
                     </span>
                   }
                 </div>
-                
-                <!-- 底部信息行 -->
                 <div class="task-footer">
                   <span class="deadline-info" [class.overdue]="event.overdueDays && event.overdueDays > 0">
                     <svg viewBox="0 0 24 24" width="12" height="12" fill="currentColor">
                       <path d="M11.99 2C6.47 2 2 6.48 2 12s4.47 10 9.99 10C17.52 22 22 17.52 22 12S17.52 2 11.99 2zM12 20c-4.42 0-8-3.58-8-8s3.58-8 8-8 8 3.58 8 8-3.58 8-8 8zm.5-13H11v6l5.25 3.15.75-1.23-4.5-2.67z"/>
                     </svg>
                     截止: {{ event.deadline | date:'MM-dd HH:mm' }}
-                    @if (event.overdueDays && event.overdueDays > 0) {
-                      <span class="overdue-label">(逾期{{ event.overdueDays }}天)</span>
-                    }
-                    @else if (event.overdueDays && event.overdueDays < 0) {
-                      <span class="upcoming-label">(还剩{{ -event.overdueDays }}天)</span>
-                    }
-                    @else {
-                      <span class="today-label">(今天)</span>
-                    }
+                    @if (event.overdueDays && event.overdueDays > 0) { <span class="overdue-label">(逾期{{ event.overdueDays }}天)</span> }
+                    @else if (event.overdueDays && event.overdueDays < 0) { <span class="upcoming-label">(还剩{{ -event.overdueDays }}天)</span> }
+                    @else { <span class="today-label">(今天)</span> }
                   </span>
-                  
                   @if (event.completionRate !== undefined) {
                     <span class="completion-info">
                       <svg viewBox="0 0 24 24" width="12" height="12" fill="currentColor">
@@ -371,158 +343,15 @@
                   }
                 </div>
               </div>
-              
-              <!-- 右侧操作按钮 -->
-              <div class="task-actions">
-                <button 
-                  class="btn-action btn-view" 
-                  (click)="onUrgentEventViewProject(event.projectId)"
-                  title="查看项目">
-                  <svg viewBox="0 0 24 24" width="14" height="14" fill="currentColor">
-                    <path d="M12 4.5C7 4.5 2.73 7.61 1 12c1.73 4.39 6 7.5 11 7.5s9.27-3.11 11-7.5c-1.73-4.39-6-7.5-11-7.5zM12 17c-2.76 0-5-2.24-5-5s2.24-5 5-5 5 2.24 5 5-2.24 5-5 5zm0-8c-1.66 0-3 1.34-3 3s1.34 3 3 3 3-1.34 3-3-1.34-3-3-3z"/>
-                  </svg>
-                  查看项目
-                </button>
-              </div>
-            </div>
-          }
-        </div>
-      }
-    </div>
-    <!-- ========== 左栏结束 ========== -->
-    
-    <!-- ========== 右栏:待办任务 ========== -->
-    <div class="todo-column todo-column-issues">
-      <div class="column-header">
-        <h3>
-          <svg viewBox="0 0 24 24" width="18" height="18" fill="currentColor">
-            <path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-2h2v2zm0-4h-2V7h2v6z"/>
-          </svg>
-          待办任务
-          @if (todoTasksFromIssues().length > 0) {
-            <span class="task-count">({{ todoTasksFromIssues().length }})</span>
-          }
-        </h3>
-        <span class="column-subtitle">来自项目问题板块</span>
-      </div>
-      
-      <!-- 加载状态 -->
-      @if (loadingTodoTasks()) {
-        <div class="loading-state">
-          <svg class="spinner" viewBox="0 0 50 50">
-            <circle cx="25" cy="25" r="20" fill="none" stroke-width="4"></circle>
-          </svg>
-          <p>加载待办任务中...</p>
-        </div>
-      }
-      
-      <!-- 错误状态 -->
-      @if (!loadingTodoTasks() && todoTaskError()) {
-        <div class="error-state">
-          <svg viewBox="0 0 24 24" width="48" height="48" fill="#ef4444">
-            <path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-2h2v2zm0-4h-2V7h2v6z"/>
-          </svg>
-          <p>{{ todoTaskError() }}</p>
-          <button class="btn-retry" (click)="refreshTodoTasks()">重试</button>
-        </div>
-      }
-      
-      <!-- 空状态 -->
-      @if (!loadingTodoTasks() && !todoTaskError() && todoTasksFromIssues().length === 0) {
-        <div class="empty-state">
-          <svg viewBox="0 0 24 24" width="64" height="64" fill="#d1d5db">
-            <path d="M19 3h-4.18C14.4 1.84 13.3 1 12 1c-1.3 0-2.4.84-2.82 2H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-7 0c.55 0 1 .45 1 1s-.45 1-1 1-1-.45-1-1 .45-1 1-1zm2 14H7v-2h7v2zm3-4H7v-2h10v2zm0-4H7V7h10v2z"/>
-          </svg>
-          <p>暂无待办任务</p>
-          <p class="hint">所有项目问题都已处理完毕 🎉</p>
-        </div>
-      }
-      
-      <!-- 待办任务列表 -->
-      @if (!loadingTodoTasks() && !todoTaskError() && todoTasksFromIssues().length > 0) {
-        <div class="todo-list-compact">
-          @for (task of todoTasksFromIssues(); track task.id) {
-            <div class="todo-item-compact" [attr.data-priority]="task.priority">
-              <!-- 左侧优先级色条 -->
-              <div class="priority-indicator" [attr.data-priority]="task.priority"></div>
-              
-              <!-- 任务内容 -->
-              <div class="task-content">
-                <!-- 标题行 -->
-                <div class="task-header">
-                  <span class="task-title">{{ task.title }}</span>
-                  <div class="task-badges">
-                    <span class="badge badge-priority" [attr.data-priority]="task.priority">
-                      {{ getPriorityConfig(task.priority).label }}
-                    </span>
-                    <span class="badge badge-type">{{ getIssueTypeLabel(task.type) }}</span>
-                  </div>
-                </div>
-                
-                <!-- 项目信息行 -->
-                <div class="task-meta">
-                  <span class="project-info">
-                    <svg viewBox="0 0 24 24" width="12" height="12" fill="currentColor">
-                      <path d="M10 20v-6h4v6h5v-8h3L12 3 2 12h3v8z"/>
-                    </svg>
-                    项目: {{ task.projectName }}
-                    @if (task.relatedSpace) {
-                      | {{ task.relatedSpace }}
-                    }
-                    @if (task.relatedStage) {
-                      | {{ task.relatedStage }}
-                    }
-                  </span>
-                </div>
-                
-                <!-- 底部信息行 -->
-                <div class="task-footer">
-                  <span class="time-info" [title]="formatExactTime(task.createdAt)">
-                    <svg viewBox="0 0 24 24" width="12" height="12" fill="currentColor">
-                      <path d="M11.99 2C6.47 2 2 6.48 2 12s4.47 10 9.99 10C17.52 22 22 17.52 22 12S17.52 2 11.99 2zM12 20c-4.42 0-8-3.58-8-8s3.58-8 8-8 8 3.58 8 8-3.58 8-8 8zm.5-13H11v6l5.25 3.15.75-1.23-4.5-2.67z"/>
-                    </svg>
-                    创建于 {{ formatRelativeTime(task.createdAt) }}
-                  </span>
-                  
-                  <span class="assignee-info">
-                    <svg viewBox="0 0 24 24" width="12" height="12" fill="currentColor">
-                      <path d="M12 12c2.21 0 4-1.79 4-4s-1.79-4-4-4-4 1.79-4 4 1.79 4 4 4zm0 2c-2.67 0-8 1.34-8 4v2h16v-2c0-2.66-5.33-4-8-4z"/>
-                    </svg>
-                    指派给: {{ task.assigneeName }}
-                  </span>
-                </div>
-              </div>
-              
-              <!-- 右侧操作按钮 -->
               <div class="task-actions">
-                <button 
-                  class="btn-action btn-view" 
-                  (click)="navigateToIssue(task)"
-                  title="查看详情">
-                  <svg viewBox="0 0 24 24" width="14" height="14" fill="currentColor">
-                    <path d="M12 4.5C7 4.5 2.73 7.61 1 12c1.73 4.39 6 7.5 11 7.5s9.27-3.11 11-7.5c-1.73-4.39-6-7.5-11-7.5zM12 17c-2.76 0-5-2.24-5-5s2.24-5 5-5 5 2.24 5 5-2.24 5-5 5zm0-8c-1.66 0-3 1.34-3 3s1.34 3 3 3 3-1.34 3-3-1.34-3-3-3z"/>
-                  </svg>
-                  查看详情
-                </button>
-                <button 
-                  class="btn-action btn-mark-read" 
-                  (click)="onTodoTaskMarkAsRead(task)"
-                  title="标记已读">
-                  <svg viewBox="0 0 24 24" width="14" height="14" fill="currentColor">
-                    <path d="M9 16.2L4.8 12l-1.4 1.4L9 19 21 7l-1.4-1.4L9 16.2z"/>
-                  </svg>
-                  标记已读
-                </button>
+                <button class="btn-action btn-view" (click)="onUrgentEventViewProject(event.projectId)">查看项目</button>
               </div>
             </div>
           }
         </div>
       }
     </div>
-    <!-- ========== 右栏结束 ========== -->
-  </div>
-  <!-- ========== 双栏容器结束 ========== -->
-</section>
+  </section>
 
   <!-- iOS风格的添加紧急事项面板 -->
   @if (isTaskFormVisible()) {
@@ -751,10 +580,139 @@
   </div>
   }
 
-  <!-- 待办任务流(复用组长端设计) - 已隐藏 -->
-  <!-- <section class="project-updates-section todo-section-customer-service">
-    ... 已隐藏的待办任务流代码 ...
-  </section> -->
+  <!-- 待办任务流(复用组长端设计) -->
+  <section class="project-updates-section todo-section-customer-service">
+    <div class="section-header">
+      <h2>
+        待办任务
+        @if (todoTasksFromIssues().length > 0) {
+          <span class="task-count">({{ todoTasksFromIssues().length }})</span>
+        }
+      </h2>
+      <button 
+        class="btn-refresh" 
+        (click)="onRefreshTodoTasks()"
+        [disabled]="loadingTodoTasks()"
+        title="刷新待办任务">
+        <svg viewBox="0 0 24 24" width="16" height="16" [class.rotating]="loadingTodoTasks()">
+          <path fill="currentColor" d="M17.65 6.35A7.958 7.958 0 0 0 12 4c-4.42 0-7.99 3.58-7.99 8s3.57 8 7.99 8c3.73 0 6.84-2.55 7.73-6h-2.08A5.99 5.99 0 0 1 12 18c-3.31 0-6-2.69-6-6s2.69-6 6-6c1.66 0 3.14.69 4.22 1.78L13 11h7V4l-2.35 2.35z"/>
+        </svg>
+      </button>
+    </div>
+    
+    <!-- 加载状态 -->
+    @if (loadingTodoTasks()) {
+      <div class="loading-state">
+        <svg class="spinner" viewBox="0 0 50 50">
+          <circle cx="25" cy="25" r="20" fill="none" stroke-width="4"></circle>
+        </svg>
+        <p>加载待办任务中...</p>
+      </div>
+      }
+      
+    <!-- 错误状态 -->
+    @if (!loadingTodoTasks() && todoTaskError()) {
+      <div class="error-state">
+        <svg viewBox="0 0 24 24" width="48" height="48" fill="#ef4444">
+          <path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-2h2v2zm0-4h-2V7h2v6z"/>
+          </svg>
+        <p>{{ todoTaskError() }}</p>
+        <button class="btn-retry" (click)="onRefreshTodoTasks()">重试</button>
+          </div>
+          }
+    
+    <!-- 空状态 -->
+    @if (!loadingTodoTasks() && !todoTaskError() && todoTasksFromIssues().length === 0) {
+      <div class="empty-state">
+        <svg viewBox="0 0 24 24" width="64" height="64" fill="#d1d5db">
+          <path d="M19 3h-4.18C14.4 1.84 13.3 1 12 1c-1.3 0-2.4.84-2.82 2H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-7 0c.55 0 1 .45 1 1s-.45 1-1 1-1-.45-1-1 .45-1 1-1zm2 14H7v-2h7v2zm3-4H7v-2h10v2zm0-4H7V7h10v2z"/>
+        </svg>
+        <p>暂无待办任务</p>
+        <p class="hint">所有项目问题都已处理完毕 🎉</p>
+          </div>
+          }
+    
+    <!-- 待办任务列表 -->
+    @if (!loadingTodoTasks() && !todoTaskError() && todoTasksFromIssues().length > 0) {
+      <div class="todo-list-compact">
+        @for (task of todoTasksFromIssues(); track task.id) {
+          <div class="todo-item-compact" [attr.data-priority]="task.priority">
+            <!-- 左侧优先级色条 -->
+            <div class="priority-indicator" [attr.data-priority]="task.priority"></div>
+            
+            <!-- 任务内容 -->
+            <div class="task-content">
+              <!-- 标题行 -->
+              <div class="task-header">
+                <span class="task-title">{{ task.title }}</span>
+                <div class="task-badges">
+                  <span class="badge badge-priority" [attr.data-priority]="task.priority">
+                    {{ getPriorityConfig(task.priority).label }}
+                  </span>
+                  <span class="badge badge-type">{{ getIssueTypeLabel(task.type) }}</span>
+          </div>
+          </div>
+              
+              <!-- 项目信息行 -->
+              <div class="task-meta">
+                <span class="project-info">
+                  <svg viewBox="0 0 24 24" width="12" height="12" fill="currentColor">
+                    <path d="M10 20v-6h4v6h5v-8h3L12 3 2 12h3v8z"/>
+                  </svg>
+                  项目: {{ task.projectName }}
+                  @if (task.relatedSpace) {
+                    | {{ task.relatedSpace }}
+                  }
+                  @if (task.relatedStage) {
+                    | {{ task.relatedStage }}
+                  }
+                </span>
+              </div>
+              
+              <!-- 底部信息行 -->
+              <div class="task-footer">
+                <span class="time-info" [title]="formatExactTime(task.createdAt)">
+                  <svg viewBox="0 0 24 24" width="12" height="12" fill="currentColor">
+                    <path d="M11.99 2C6.47 2 2 6.48 2 12s4.47 10 9.99 10C17.52 22 22 17.52 22 12S17.52 2 11.99 2zM12 20c-4.42 0-8-3.58-8-8s3.58-8 8-8 8 3.58 8 8-3.58 8-8 8zm.5-13H11v6l5.25 3.15.75-1.23-4.5-2.67z"/>
+                  </svg>
+                  创建于 {{ formatRelativeTime(task.createdAt) }}
+                </span>
+                
+                <span class="assignee-info">
+                  <svg viewBox="0 0 24 24" width="12" height="12" fill="currentColor">
+                    <path d="M12 12c2.21 0 4-1.79 4-4s-1.79-4-4-4-4 1.79-4 4 1.79 4 4 4zm0 2c-2.67 0-8 1.34-8 4v2h16v-2c0-2.66-5.33-4-8-4z"/>
+                  </svg>
+                  指派给: {{ task.assigneeName }}
+            </span>
+          </div>
+        </div>
+            
+            <!-- 右侧操作按钮(⭐ 使用新的事件处理方法) -->
+            <div class="task-actions">
+              <button 
+                class="btn-action btn-view" 
+                (click)="onTodoTaskViewDetails(task)"
+                title="查看详情">
+                <svg viewBox="0 0 24 24" width="14" height="14" fill="currentColor">
+                  <path d="M12 4.5C7 4.5 2.73 7.61 1 12c1.73 4.39 6 7.5 11 7.5s9.27-3.11 11-7.5c-1.73-4.39-6-7.5-11-7.5zM12 17c-2.76 0-5-2.24-5-5s2.24-5 5-5 5 2.24 5 5-2.24 5-5 5zm0-8c-1.66 0-3 1.34-3 3s1.34 3 3 3 3-1.34 3-3-1.34-3-3-3z"/>
+                </svg>
+                查看详情
+              </button>
+              <button 
+                class="btn-action btn-mark-read" 
+                (click)="onTodoTaskMarkAsRead(task)"
+                title="标记已读">
+                <svg viewBox="0 0 24 24" width="14" height="14" fill="currentColor">
+                  <path d="M9 16.2L4.8 12l-1.4 1.4L9 19 21 7l-1.4-1.4L9 16.2z"/>
+                </svg>
+                标记已读
+              </button>
+            </div>
+      </div>
+      }
+    </div>
+    }
+  </section>
 
 <!-- 回到顶部按钮 -->
 <button class="back-to-top" (click)="scrollToTop()" [class.visible]="showBackToTop()">

+ 0 - 399
src/app/pages/customer-service/dashboard/dashboard.scss

@@ -3686,403 +3686,4 @@ input[type="datetime-local"]::-webkit-calendar-picker-indicator {
   .quick-actions {
     grid-template-columns: 1fr;
   }
-}
-
-// 🆕 待办事项双栏布局样式
-.urgent-tasks-section {
-  .section-header {
-    display: flex;
-    align-items: center;
-    justify-content: space-between;
-    padding: 16px 20px;
-    border-bottom: 1px solid #e5e7eb;
-    
-    h2 {
-      margin: 0;
-      font-size: 18px;
-      font-weight: 600;
-      color: #1c1c1e;
-    }
-  }
-
-  // 双栏容器
-  .todo-dual-columns {
-    display: grid;
-    grid-template-columns: 1fr 1fr;
-    gap: 20px;
-    padding: 20px;
-    
-    @media (max-width: 1200px) {
-      grid-template-columns: 1fr;
-      gap: 16px;
-    }
-  }
-
-  // 列样式
-  .todo-column {
-    display: flex;
-    flex-direction: column;
-    background: #ffffff;
-    border-radius: 12px;
-    border: 1px solid #e5e7eb;
-    overflow: hidden;
-    
-    .column-header {
-      padding: 16px;
-      background: linear-gradient(135deg, #6366f1 0%, #8b5cf6 100%);
-      color: white;
-      
-      h3 {
-        margin: 0;
-        font-size: 16px;
-        font-weight: 600;
-        display: flex;
-        align-items: center;
-        gap: 8px;
-        
-        .task-count {
-          margin-left: auto;
-          font-size: 14px;
-          font-weight: 500;
-          background: rgba(255, 255, 255, 0.2);
-          padding: 2px 8px;
-          border-radius: 12px;
-          
-          &.urgent {
-            background: rgba(239, 68, 68, 0.3);
-          }
-        }
-      }
-      
-      .column-subtitle {
-        font-size: 12px;
-        opacity: 0.8;
-        margin-top: 4px;
-        display: block;
-      }
-    }
-    
-    .loading-state,
-    .error-state,
-    .empty-state {
-      padding: 40px 20px;
-      text-align: center;
-      color: #6b7280;
-      
-      svg {
-        margin-bottom: 12px;
-      }
-      
-      p {
-        margin: 8px 0;
-        font-size: 14px;
-        
-        &.hint {
-          font-size: 12px;
-          color: #9ca3af;
-        }
-      }
-      
-      .btn-retry {
-        margin-top: 12px;
-        padding: 8px 16px;
-        background: #007aff;
-        color: white;
-        border: none;
-        border-radius: 6px;
-        cursor: pointer;
-        font-size: 14px;
-        
-        &:hover {
-          background: #0051a8;
-        }
-      }
-    }
-    
-    .todo-list-compact {
-      flex: 1;
-      overflow-y: auto;
-      max-height: 600px;
-      
-      .todo-item-compact {
-        display: flex;
-        gap: 12px;
-        padding: 12px;
-        border-bottom: 1px solid #f3f4f6;
-        transition: background-color 0.2s ease;
-        
-        &:hover {
-          background-color: #f9fafb;
-        }
-        
-        .priority-indicator {
-          width: 4px;
-          flex-shrink: 0;
-          border-radius: 2px;
-          
-          &[data-priority="urgent"],
-          &[data-priority="critical"] {
-            background: #dc2626;
-          }
-          
-          &[data-priority="high"] {
-            background: #f97316;
-          }
-          
-          &[data-priority="medium"] {
-            background: #f59e0b;
-          }
-          
-          &[data-priority="low"] {
-            background: #6b7280;
-          }
-        }
-        
-        .task-content {
-          flex: 1;
-          min-width: 0;
-          
-          .task-header {
-            display: flex;
-            align-items: center;
-            gap: 8px;
-            margin-bottom: 6px;
-            
-            .task-title {
-              font-size: 13px;
-              font-weight: 600;
-              color: #1c1c1e;
-              flex: 1;
-              white-space: nowrap;
-              overflow: hidden;
-              text-overflow: ellipsis;
-            }
-            
-            .task-badges {
-              display: flex;
-              gap: 6px;
-              flex-shrink: 0;
-              
-              .badge {
-                display: inline-block;
-                padding: 2px 8px;
-                border-radius: 4px;
-                font-size: 11px;
-                font-weight: 600;
-                white-space: nowrap;
-                
-                &.badge-priority {
-                  &[data-priority="urgent"],
-                  &[data-priority="critical"] {
-                    background: #fee2e2;
-                    color: #dc2626;
-                  }
-                  
-                  &[data-priority="high"] {
-                    background: #ffedd5;
-                    color: #f97316;
-                  }
-                  
-                  &[data-priority="medium"] {
-                    background: #fef3c7;
-                    color: #f59e0b;
-                  }
-                  
-                  &[data-priority="low"] {
-                    background: #f3f4f6;
-                    color: #6b7280;
-                  }
-                }
-                
-                &.badge-type {
-                  background: #dbeafe;
-                  color: #1e40af;
-                }
-              }
-            }
-          }
-          
-          .task-meta {
-            font-size: 12px;
-            color: #6b7280;
-            margin-bottom: 6px;
-            display: flex;
-            gap: 8px;
-            flex-wrap: wrap;
-            
-            .project-info,
-            .designer-info {
-              display: flex;
-              align-items: center;
-              gap: 4px;
-              white-space: nowrap;
-              overflow: hidden;
-              text-overflow: ellipsis;
-            }
-          }
-          
-          .task-footer {
-            font-size: 11px;
-            color: #9ca3af;
-            display: flex;
-            gap: 12px;
-            flex-wrap: wrap;
-            
-            .time-info,
-            .assignee-info {
-              display: flex;
-              align-items: center;
-              gap: 4px;
-              white-space: nowrap;
-            }
-          }
-        }
-        
-        .task-actions {
-          display: flex;
-          gap: 6px;
-          flex-shrink: 0;
-          
-          .btn-action {
-            padding: 6px 10px;
-            border: 1px solid #d1d5db;
-            background: white;
-            color: #6b7280;
-            border-radius: 6px;
-            cursor: pointer;
-            font-size: 12px;
-            display: flex;
-            align-items: center;
-            gap: 4px;
-            transition: all 0.2s ease;
-            white-space: nowrap;
-            
-            &:hover {
-              background: #f3f4f6;
-              color: #1c1c1e;
-              border-color: #9ca3af;
-            }
-            
-            &.btn-view {
-              color: #007aff;
-              border-color: #007aff;
-              
-              &:hover {
-                background: #f0f9ff;
-              }
-            }
-            
-            &.btn-mark-read {
-              color: #34c759;
-              border-color: #34c759;
-              
-              &:hover {
-                background: #f0fdf4;
-              }
-            }
-          }
-        }
-      }
-    }
-  }
-
-// 🆕 紧急事件样式(复用设计师组长端)
-  .todo-column-urgent {
-    .column-header {
-      background: linear-gradient(135deg, #f97316 0%, #dc2626 100%);
-    }
-    
-    // 紧急事件特定样式
-    .urgent-item {
-      background: #fff8f8;
-      border-left-width: 4px;
-      
-      &[data-urgency="critical"] {
-        border-left-color: #dc2626;
-        background: #fef2f2;
-      }
-      
-      &[data-urgency="high"] {
-        border-left-color: #f97316;
-        background: #fff7ed;
-      }
-      
-      &[data-urgency="medium"] {
-        border-left-color: #f59e0b;
-        background: #fffbeb;
-      }
-    }
-    
-    .urgency-indicator {
-      width: 4px;
-      
-      &[data-urgency="critical"] {
-        background: linear-gradient(180deg, #dc2626 0%, #b91c1c 100%);
-        box-shadow: 0 0 10px rgba(220, 38, 38, 0.5);
-      }
-      
-      &[data-urgency="high"] {
-        background: linear-gradient(180deg, #f97316 0%, #ea580c 100%);
-      }
-      
-      &[data-urgency="medium"] {
-        background: linear-gradient(180deg, #f59e0b 0%, #d97706 100%);
-      }
-    }
-    
-    .badge-urgency {
-      &[data-urgency="critical"] {
-        background: #fee2e2;
-        color: #dc2626;
-        font-weight: 700;
-      }
-      
-      &[data-urgency="high"] {
-        background: #ffedd5;
-        color: #f97316;
-      }
-      
-      &[data-urgency="medium"] {
-        background: #fef3c7;
-        color: #f59e0b;
-      }
-    }
-    
-    .badge-event-type {
-      background: #dbeafe;
-      color: #1e40af;
-    }
-    
-    .task-description {
-      font-size: 13px;
-      color: #6b7280;
-      margin: 8px 0;
-      line-height: 1.5;
-    }
-    
-    .deadline-info {
-      &.overdue {
-        color: #dc2626;
-        font-weight: 600;
-      }
-      
-      .overdue-label {
-        color: #dc2626;
-        font-weight: 600;
-      }
-      
-      .upcoming-label {
-        color: #f97316;
-      }
-      
-      .today-label {
-        color: #f59e0b;
-        font-weight: 600;
-      }
-    }
-    
-    .completion-info {
-      font-weight: 500;
-    }
-  }
 }

+ 14 - 16
src/app/pages/customer-service/dashboard/dashboard.ts

@@ -1918,22 +1918,6 @@ onSearchInput(event: Event): void {
     });
   }
   
-  /**
-   * ⭐ 从待办任务面板查看详情(跳转到项目并显示问题弹窗)
-   */
-  navigateToIssue(task: TodoTaskFromIssue): void {
-    console.log('🔍 [待办任务] 查看详情:', task.title);
-    // 跳转到项目详情页,并打开问题板块
-    const cid = localStorage.getItem('company') || 'cDL6R1hgSi';
-    this.router.navigate(['/wxwork', cid, 'project', task.projectId, 'order'], {
-      queryParams: {
-        openIssues: 'true',
-        highlightIssue: task.id,
-        roleName: 'customer-service'
-      }
-    });
-  }
-  
   /**
    * ⭐ 从待办任务面板查看详情
    */
@@ -2043,6 +2027,20 @@ onSearchInput(event: Event): void {
     return labels[status] || '待处理';
   }
   
+  /**
+   * 跳转到项目问题详情
+   */
+  navigateToIssue(task: TodoTaskFromIssue): void {
+    console.log(`📋 跳转到问题详情: ${task.id}, 项目ID: ${task.projectId}`);
+    
+    // 获取当前公司ID
+    const cid = localStorage.getItem('company') || 'cDL6R1hgSi';
+    
+    // 导航到wxwork模块的项目问题详情页
+    this.router.navigate(['/wxwork', cid, 'project', task.projectId, 'issues'], {
+      queryParams: { issueId: task.id }
+    });
+  }
 
   // 新增:一键发送大图
   sendLargeImages(projectId: string): void {

+ 2 - 2
src/app/pages/designer/project-detail/components/designer-team-assignment-modal/designer-team-assignment-modal.component.scss

@@ -593,9 +593,9 @@
           // ⭐ 修复:对图日期特别处理,最多显示2行
           white-space: normal;
           display: -webkit-box;
-          -webkit-line-clamp: 2;
-          line-clamp: 2;
           -webkit-box-orient: vertical;
+          -webkit-line-clamp: 2;
+          line-clamp: 2; // 标准属性,放在vendor前缀之后
           line-height: 1.4;
           
           .more-dates {