Procházet zdrojové kódy

feat(项目流程): 添加后期阶段到项目工作流

在项目流程中添加新的后期阶段,包括:
1. 在ProjectStage类型定义中添加后期阶段
2. 在各页面组件中添加后期阶段相关逻辑
3. 在项目详情页添加后期阶段UI和功能
4. 更新阶段顺序和进度配置
5. 实现后期图片上传和确认功能
0235711 před 18 hodinami
rodič
revize
379ca46c47

+ 1 - 1
src/app/models/project.model.ts

@@ -49,7 +49,7 @@ export interface CustomerTag {
 export type ProjectStatus = '进行中' | '已完成' | '已暂停' | '已延期';
 
 // 项目阶段
-export type ProjectStage = '订单创建' | '需求沟通' | '方案确认' | '建模' | '软装' | '渲染' | '尾款结算' | '客户评价' | '投诉处理';
+export type ProjectStage = '订单创建' | '需求沟通' | '方案确认' | '建模' | '软装' | '渲染' | '后期' | '尾款结算' | '客户评价' | '投诉处理';
 
 // 任务模型
 // 修复 Task 接口,将 completedAt 改为 completedDate(与实际代码保持一致)

+ 1 - 0
src/app/pages/customer-service/project-list/project-list.ts

@@ -243,6 +243,7 @@ export class ProjectList implements OnInit, OnDestroy {
         '建模': 40,
         '软装': 60,
         '渲染': 80,
+        '后期': 85,
         '尾款结算': 90,
         '投诉处理': 100,
         订单创建: 0,

+ 1 - 0
src/app/pages/designer/personal-board/personal-board.ts

@@ -322,6 +322,7 @@ export class PersonalBoard implements OnInit, AfterViewInit {
       '建模': 30,
       '软装': 0,
       '渲染': 50,
+      '后期': 0,
       '尾款结算': 0,
       '客户评价': 0,
       '投诉处理': 0

+ 62 - 2
src/app/pages/designer/project-detail/project-detail.html

@@ -744,14 +744,15 @@
                             <div class="empty-tip" style="color:#888;">暂无色彩分析结果</div>
                           }
                         </div>
-                      } @else if (stage === '建模' || stage === '软装' || stage === '渲染') {
+                      } @else if (stage === '建模' || stage === '软装' || stage === '渲染' || stage === '后期') {
                         <!-- 横向折叠面板布局 -->
                         <div class="delivery-execution-panel">
                           <div class="delivery-processes-container">
                             @for (process of deliveryProcesses; track process.name) {
                               @if ((stage === '建模' && process.type === 'modeling') || 
                                    (stage === '软装' && process.type === 'softDecor') || 
-                                   (stage === '渲染' && process.type === 'rendering')) {
+                                   (stage === '渲染' && process.type === 'rendering') ||
+                                   (stage === '后期' && process.type === 'postProcess')) {
                                 <div class="delivery-process-card" [class.expanded]="process.isExpanded">
                                   <!-- 流程标题 -->
                                   <div class="process-header" (click)="toggleProcess(process.id)">
@@ -1020,6 +1021,65 @@
                                                   </div>
                                                 }
                                               </div>
+                                            } @else if (process.type === 'postProcess') {
+                                              <!-- 后期内容 -->
+                                              <div class="postprocess-content">
+                                                <div class="upload-section">
+                                                  <div class="upload-header">
+                                                    <h6>上传后期图片</h6>
+                                                    <span class="hint">建议 ≥4K 分辨率的 JPG/PNG 图片</span>
+                                                  </div>
+                                                  @if (canEditSection('delivery')) {
+                                                    <div class="upload-dropzone" 
+                                                         (click)="!process.content[space.id]?.images || process.content[space.id].images.length === 0 ? triggerSpaceFileInput(process.id, space.id) : null"
+                                                         [class.has-images]="(process.content[space.id]?.images?.length || 0) > 0">
+                                                      @if (!process.content[space.id]?.images || process.content[space.id].images.length === 0) {
+                                                        <div class="upload-icon"></div>
+                                                        <div class="upload-text">点击此处上传后期图片</div>
+                                                        <div class="upload-hint">支持 JPG、PNG 格式,建议 4K 分辨率</div>
+                                                      } @else {
+                                                        <div class="uploaded-images-grid">
+                                                          @for (img of process.content[space.id].images; track img.id) {
+                                                            <div class="uploaded-image-item" (click)="previewImage(img)">
+                                                              <img [src]="img.url" [alt]="img.name" />
+                                                              <div class="image-overlay">
+                                                                <div class="image-name">{{ img.name }}</div>
+                                                                <div class="image-actions">
+                                                                  <button class="preview-btn" (click)="$event.stopPropagation(); previewImage(img)">
+                                                                    <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor">
+                                                                      <path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z"></path>
+                                                                      <circle cx="12" cy="12" r="3"></circle>
+                                                                    </svg>
+                                                                  </button>
+                                                                  <button class="remove-btn" (click)="$event.stopPropagation(); removeSpaceImage(process.id, space.id, img.id)">
+                                                                    <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor">
+                                                                      <line x1="18" y1="6" x2="6" y2="18"></line>
+                                                                      <line x1="6" y1="6" x2="18" y2="18"></line>
+                                                                    </svg>
+                                                                  </button>
+                                                                </div>
+                                                              </div>
+                                                            </div>
+                                                          }
+                                                          <div class="add-more-btn" (click)="triggerSpaceFileInput(process.id, space.id)">
+                                                            <div class="add-icon">+</div>
+                                                            <div class="add-text">添加更多</div>
+                                                          </div>
+                                                        </div>
+                                                      }
+                                                    </div>
+                                                  }
+                                                </div>
+                                                
+                                                <!-- 后期阶段确认上传按钮 -->
+                                                @if (canEditSection('delivery') && (process.content[space.id]?.images?.length || 0) > 0) {
+                                                  <div class="upload-actions">
+                                                    <button class="primary-btn" (click)="confirmPostProcessUpload()">
+                                                      确认上传
+                                                    </button>
+                                                  </div>
+                                                }
+                                              </div>
                                             }
                                           </div>
                                         }

+ 29 - 8
src/app/pages/designer/project-detail/project-detail.ts

@@ -194,8 +194,8 @@ interface DeliverySpace {
 
 interface DeliveryProcess {
   id: string;
-  name: string; // 流程名称:建模、软装、渲染
-  type: 'modeling' | 'softDecor' | 'rendering';
+  name: string; // 流程名称:建模、软装、渲染、后期
+  type: 'modeling' | 'softDecor' | 'rendering' | 'postProcess';
   spaces: DeliverySpace[]; // 该流程下的空间列表
   isExpanded: boolean; // 是否展开
   content: {
@@ -253,8 +253,8 @@ export class ProjectDetail implements OnInit, OnDestroy {
   referenceImages: any[] = [];
   cadFiles: any[] = [];
   
-  // 新增:9阶段顺序(串式流程)- 删除后期阶段
-  stageOrder: ProjectStage[] = ['订单创建', '需求沟通', '方案确认', '建模', '软装', '渲染', '尾款结算', '客户评价', '投诉处理'];
+  // 新增:9阶段顺序(串式流程)- 包含后期阶段
+  stageOrder: ProjectStage[] = ['订单创建', '需求沟通', '方案确认', '建模', '软装', '渲染', '后期', '尾款结算', '客户评价', '投诉处理'];
   // 新增:阶段展开状态(默认全部收起,当前阶段在数据加载后自动展开)
   expandedStages: Partial<Record<ProjectStage, boolean>> = {
     '订单创建': false,
@@ -263,6 +263,7 @@ export class ProjectDetail implements OnInit, OnDestroy {
     '建模': false,
     '软装': false,
     '渲染': false,
+    '后期': false,
     '尾款结算': false,
     '客户评价': false,
     '投诉处理': false,
@@ -272,7 +273,7 @@ export class ProjectDetail implements OnInit, OnDestroy {
   sections: Array<{ key: SectionKey; label: string; stages: ProjectStage[] }> = [
     { key: 'order', label: '订单创建', stages: ['订单创建'] },
     { key: 'requirements', label: '确认需求', stages: ['需求沟通', '方案确认'] },
-    { key: 'delivery', label: '交付执行', stages: ['建模', '软装', '渲染'] },
+    { key: 'delivery', label: '交付执行', stages: ['建模', '软装', '渲染', '后期'] },
     { key: 'aftercare', label: '售后', stages: ['尾款结算', '客户评价', '投诉处理'] }
   ];
   expandedSection: SectionKey | null = null;
@@ -374,6 +375,22 @@ export class ProjectDetail implements OnInit, OnDestroy {
         'living': { images: [], progress: 0, status: 'pending', notes: '', lastUpdated: new Date() },
         'kitchen': { images: [], progress: 0, status: 'pending', notes: '', lastUpdated: new Date() }
       }
+    },
+    {
+      id: 'postProcess',
+      name: '后期',
+      type: 'postProcess',
+      isExpanded: false,
+      spaces: [
+        { id: 'bedroom', name: '卧室', isExpanded: false, order: 1 },
+        { id: 'living', name: '客厅', isExpanded: false, order: 2 },
+        { id: 'kitchen', name: '厨房', isExpanded: false, order: 3 }
+      ],
+      content: {
+        'bedroom': { images: [], progress: 0, status: 'pending', notes: '', lastUpdated: new Date() },
+        'living': { images: [], progress: 0, status: 'pending', notes: '', lastUpdated: new Date() },
+        'kitchen': { images: [], progress: 0, status: 'pending', notes: '', lastUpdated: new Date() }
+      }
     }
   ];
 
@@ -1230,6 +1247,7 @@ export class ProjectDetail implements OnInit, OnDestroy {
       '建模': '项目执行',
       '软装': '项目执行',
       '渲染': '项目执行',
+      '后期': '项目执行',
       '尾款结算': '收尾验收',
       '客户评价': '收尾验收',
       '投诉处理': '收尾验收'
@@ -1788,10 +1806,10 @@ export class ProjectDetail implements OnInit, OnDestroy {
     this.postProcessImages = this.postProcessImages.filter(i => i.id !== id);
   }
 
-  // 新增:后期阶段确认上传并自动进入下一阶段(已删除后期阶段,此方法保留但不会被调用
+  // 新增:后期阶段 确认上传并自动进入下一阶段(尾款结算
   confirmPostProcessUpload(): void {
-    // 由于删除了后期阶段,此方法不再使用
-    console.log('后期阶段已删除,此方法不再使用');
+    if (this.postProcessImages.length === 0) return;
+    this.advanceToNextStage('后期');
   }
 
   // 新增:尾款结算阶段确认并自动进入下一阶段(客户评价)
@@ -1896,6 +1914,7 @@ export class ProjectDetail implements OnInit, OnDestroy {
       case '建模':
       case '软装':
       case '渲染':
+      case '后期':
         return 'delivery';
       case '尾款结算':
       case '客户评价':
@@ -1957,6 +1976,7 @@ export class ProjectDetail implements OnInit, OnDestroy {
       '建模': 'modeling',
       '软装': 'softdecor',
       '渲染': 'render',
+      '后期': 'postprocess',
       '尾款结算': 'settlement',
       '客户评价': 'customer-review',
       '投诉处理': 'complaint'
@@ -2476,6 +2496,7 @@ export class ProjectDetail implements OnInit, OnDestroy {
       '建模': 40,
       '软装': 55,
       '渲染': 70,
+      '后期': 80,
       '尾款结算': 90,
       '客户评价': 95,
       '投诉处理': 100