Browse Source

build: 降级Angular动画和CDK依赖版本

将@angular/animations从^20.3.1降级到20.1.0,@angular/cdk从^20.2.4降级到20.2.2以解决兼容性问题
0235711 5 hours ago
parent
commit
e6f9d78819

File diff suppressed because it is too large
+ 281 - 221
package-lock.json


+ 2 - 2
package.json

@@ -21,8 +21,8 @@
   },
   "private": true,
   "dependencies": {
-    "@angular/animations": "^20.3.1",
-    "@angular/cdk": "^20.2.4",
+    "@angular/animations": "20.1.0",
+    "@angular/cdk": "20.2.2",
     "@angular/common": "^20.1.0",
     "@angular/compiler": "^20.1.0",
     "@angular/core": "^20.1.0",

+ 1 - 1
src/app/pages/designer/project-detail/project-detail.html

@@ -1,4 +1,4 @@
-<!-- 只展示修改处,未变更部分用占位注释表示 -->
+<!-- 只展示修改处,未变更部分用占位注释表示 -->
 <div class="project-detail-container designer-page">
   <!-- 项目标题栏 -->
   <div class="project-header card">

+ 929 - 0
src/app/pages/designer/project-detail/project-detail.html.bak

@@ -0,0 +1,929 @@
+<!-- 鍙睍绀轰慨鏀瑰锛屾湭鍙樻洿閮ㄥ垎鐢ㄥ崰浣嶆敞閲婅〃绀?-->
+<div class="project-detail-container designer-page">
+  <!-- 椤圭洰鏍囬鏍?-->
+  <div class="project-header card">
+    <div class="header-content">
+      <h1>椤圭洰璇︽儏</h1>
+      <div class="project-meta">
+        <span class="project-id">椤圭洰ID: {{ projectId }}</span>
+        @if (project) { <span class="project-status">{{ project.status }}</span> }
+        <!-- 绱ф€ヤ笌寮傚父寰芥爣锛堜娇鐢ㄦ帶鍒舵祦鎸囦护锛?-->
+        <!-- 淇濇寔宸叉湁@if 寰jit爣閫昏緫涓嶅彉 -->
+      </div>
+    </div>
+    <div class="header-actions">
+      <!-- 杩斿洖宸ヤ綔鍙版寜閽?-->
+      <button (click)="backToWorkbench()" class="back-btn">杩斿洖宸ヤ綔鍙?/button>
+      
+      <!-- 鍒囨崲椤圭洰涓嬫媺鑿滃崟 -->
+      <div class="project-switcher">
+        <button (click)="showDropdown = !showDropdown" class="switch-btn">鍒囨崲椤圭洰</button>
+        @if (showDropdown) {
+          <div class="switch-dropdown" (click)="$event.stopPropagation()">
+            @for (p of projects; track p.id) {
+              <div (click)="switchProject(p.id); showDropdown = false" 
+                   [class.active]="p.id === projectId" 
+                   class="project-item">
+                <span class="project-name">{{ p.name }}</span>
+                <span class="project-status-badge" 
+                      [class.ongoing]="p.status === '杩涜涓?" 
+                      [class.completed]="p.status === '宸插畬鎴?" 
+                      [class.pending]="p.status === '寰呭鐞?">
+                  {{ p.status }}
+                </span>
+              </div>
+            }
+          </div>
+        }
+      </div>
+
+      <!-- 瀵煎嚭闃舵鎶ュ憡 -->
+      <button (click)="exportProjectReport()" class="secondary-btn">瀵煎嚭闃舵鎶ュ憡</button>
+      
+      <button (click)="generateReminderMessage()" class="stagnation-btn">璁剧疆鍋滄粸</button>
+    </div>
+  </div>
+
+  <!-- 鎻愰啋娑堟伅寮圭獥 -->
+  @if (reminderMessage) {
+    <div class="reminder-popup">
+      {{ reminderMessage }}
+    </div>
+  }
+
+  <!-- 鏍囧噯闃舵杩涘害锛?闃舵锛?-->
+  <!-- 宸查噰鐢ˊfor锛屼笉鍙?-->
+
+  <!-- 椤堕儴瀵艰埅鏍囩椤?-->
+  <!-- 鍘熸湁浠g爜淇濈暀 -->
+
+  <div class="tab-content">
+    <!-- 椤圭洰杩涘害鏍囩椤?-->
+    @if (isActiveTab('progress')) {
+      <div class="progress-tab-content">
+        <div class="main-content-layout">
+          <!-- 宸︿晶淇濈暀 -->
+          <div class="left-column">
+            <div class="project-info-card card">
+              <h2>瀹㈡埛淇℃伅</h2>
+              @if (project) {
+                <div class="info-grid">
+                  <div class="info-item key-info"><label>瀹㈡埛濮撳悕</label><span>{{ project.customerName }}</span></div>
+                  <div class="info-item key-info"><label>椤圭洰璐熻矗浜?/label><span>{{ project.assigneeName }}</span></div>
+                  <div class="info-item"><label>椤圭洰鍒涘缓</label><span>{{ formatDate(project.createdAt) }}</span></div>
+                  <div class="info-item"><label>鎴鏃ユ湡</label><span>{{ formatDate(project.deadline) }}</span></div>
+                </div>
+                <div class="tags-container" style="margin-top: 12px;">
+                  <div class="tag-section">
+                    <h3>瀹㈡埛鏍囩</h3>
+                    <div class="tags">
+                      @for (tag of project.customerTags; track $index) {
+                        <span class="tag">{{ tag.source }} 路 {{ tag.needType }} 路 {{ tag.preference }} 路 {{ tag.colorAtmosphere }}</span>
+                      }
+                      @if (project.customerTags.length === 0) { <span class="desc">鏆傛棤鏍囩</span> }
+                    </div>
+                  </div>
+                  <div class="tag-section">
+                    <h3>楂樹紭鍏堢骇闇€姹?/h3>
+                    <ul class="need-list">
+                      @for (need of project.highPriorityNeeds; track $index) {
+                        <li>{{ need }}</li>
+                      }
+                      @if (project.highPriorityNeeds.length === 0) { <li class="desc">鏃?/li> }
+                    </ul>
+                  </div>
+                </div>
+              } @else {
+                <div class="loading-state">
+                  <div class="loading-spinner"></div>
+                  <div>姝e湪鍔犺浇瀹㈡埛淇℃伅...</div>
+                </div>
+              }
+            </div>
+          </div>
+
+          <!-- 鍙充晶涓夊垎涔嬩簩 - 鍒朵綔娴佺▼杩涘害 -->
+          <div class="right-column">
+            <div class="process-card card">
+              <h2>鍒朵綔娴佺▼杩涘害</h2>
+
+              <!-- 鏂板锛氬洓澶ф澘鍧楃煩褰㈡寜閽?-->
+              <div class="sections-toolbar">
+                @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'"
+                          (click)="toggleSection(sec.key)">
+                    <span class="section-label">{{ sec.label }}</span>
+                  </button>
+                }
+              </div>
+
+              <!-- 涓插紡娴佺▼锛?0涓樁娈垫í鍚戞帓鍒楋紙淇濇寔锛?-->
+              <div class="stage-progress-container">
+                @for (stage of stages; track stage) {
+                  @if (stage === '璁㈠崟鍒涘缓') {
+                    <app-consultation-order></app-consultation-order>
+                  }
+                  <div class="delivery-col" [class.active]="getStageStatus(stage) === 'active'">
+                    <div class="delivery-stage-header">
+                      <span class="dot" [class.completed]="getStageStatus(stage) === 'completed'" [class.active]="getStageStatus(stage) === 'active'"></span>
+                      <h3>{{ stage }}</h3>
+                    </div>
+                    <!-- 鐩存帴澶嶇敤鍘熼樁娈靛唴瀹瑰崱鐗囷細鎸塻tage鍖归厤鏄剧ず -->
+                    <div class="delivery-stage-body">
+                      @if (stage === '寤烘ā') { <!-- 寮曠敤鍘熷缓妯″潡 -->
+                        <div class="model-check-section">
+                          <h4>妯″瀷璇樊妫€鏌ユ竻鍗?/h4>
+                          <div class="checklist">
+                            @for (item of modelCheckItems; track item.id) {
+                              <div class="checklist-item">
+                                <label class="checklist-label">
+                                  <input type="checkbox" class="custom-checkbox" [checked]="item.isPassed" (change)="updateModelCheckItem(item.id, $any($event.target).checked)" [disabled]="!isDesignerView()">
+                                  <span class="checklist-text">{{ item.name }}</span>
+                                </label>
+                                <span class="check-status">{{ item.isPassed ? '宸查€氳繃' : '寰呭鐞? }}</span>
+                              </div>
+                            }
+                          </div>
+                        </div>
+                      }
+
+                      @if (stage === '杞') { <!-- 寮曠敤鍘熻蒋瑁呭潡 -->
+                        <div class="softdecor-section">
+                          <h4>杞琛ュ厖璧勬枡</h4>
+                          <div class="upload-section">
+                            <div class="upload-header">
+                              <h4>涓婁紶杞灏忓浘</h4>
+                              <span class="hint">寤鸿 鈮?1MB 鐨?JPG/PNG 灏忓浘</span>
+                            </div>
+                            <div class="upload-actions">
+                              @if (isDesignerView()) {
+                                <label class="secondary-btn">
+                                  閫夋嫨鍥剧墖
+                                  <input type="file" accept="{{allowedImageTypes}}" multiple (change)="onSoftDecorSmallPicsSelected($event)" style="display:none" />
+                                </label>
+                                <button class="primary-btn" [disabled]="softDecorImages.length===0" (click)="confirmSoftDecorUpload()">纭涓婁紶</button>
+                              }
+                              @if (isTeamLeaderView()) { <button class="secondary-btn" (click)="syncUploadedImages('soft')">鍚屾鍥剧墖淇℃伅</button> }
+                              @if (isCustomerServiceView()) { <span class="desc">鍙</span> }
+                            </div>
+                            @if (softDecorImages.length > 0) {
+                              <div class="thumb-list">
+                                @for (img of softDecorImages; track img.id) {
+                                  <div class="thumb-item">
+                                    <img [src]="img.url" [alt]="img.name" />
+                                    <div class="thumb-meta">
+                                      <span class="name" [title]="img.name">{{ img.name }}</span>
+                                      <span class="size">{{ img.size }}</span>
+                                    </div>
+                                    <div class="review-meta" style="display:flex;gap:8px;align-items:center;">
+                                      <span class="status-badge">{{ getImageReviewStatusText(img) }}</span>
+                                      @if (isTeamLeaderView()) {
+                                        <button class="link success" (click)="reviewImage(img.id, 'soft', 'approved')">閫氳繃</button>
+                                        <button class="link warning" (click)="reviewImage(img.id, 'soft', 'rejected')">椹冲洖</button>
+                                      }
+                                    </div>
+                                    @if (isDesignerView()) { <button class="link danger" (click)="removeSoftDecorImage(img.id)">绉婚櫎</button> }
+                                  </div>
+                                }
+                              </div>
+                            }
+                          </div>
+                        </div>
+                      }
+
+                      @if (stage === '渲染') { <!-- 寮曠敤鍘熸覆鏌撳潡 -->
+                        <div class="render-progress-section">
+                          @if (isLoadingRenderProgress) {
+                            <div class="loading-state">
+                              <div class="loading-spinner"></div>
+                              <div>姝e湪鍔犺浇渲染杩涘害...</div>
+                            </div>
+                          }
+                          @if (errorLoadingRenderProgress) {
+                            <div class="error-state">
+                              <div>渲染杩涘害鍔犺浇澶辫触</div>
+                              <button class="secondary-btn" (click)="retryLoadRenderProgress()">重试</button>
+                            </div>
+                          }
+                          @if (!isLoadingRenderProgress && !errorLoadingRenderProgress && renderProgress) {
+                            <div class="progress-info" style="display:flex;gap:16px;align-items:center;margin:12px 0;">
+                              <span>鐘舵€侊細{{ renderProgress.status }}</span>
+                              <span>瀹屾垚搴︼細{{ renderProgress.completionRate }}%</span>
+                              <span>预计剩余:{{ renderProgress.estimatedTimeRemaining }} 小时</span>
+                            </div>
+                          }
+                          <div class="upload-section">
+                            <div class="upload-header">
+                              <h4>涓婁紶渲染澶у浘</h4>
+                              <span class="hint">闇€婊¤冻4K鏍囧噯锛堟渶澶ц竟鈮?000px锛?/span>
+                            </div>
+                            <div class="upload-actions" style="display:flex;gap:12px;align-items:center;">
+                              @if (isDesignerView()) { <button class="primary-btn" (click)="openRenderUploadModal()">閫夋嫨骞朵笂浼?/button> }
+                              @if (isTeamLeaderView()) { <button class="secondary-btn" (click)="syncUploadedImages('render')">鍚屾鍥剧墖淇℃伅</button> }
+                              @if (renderLargeImages.length>0) { <span class="desc">宸蹭笂浼?{{renderLargeImages.length}} 寮?/span> }
+                            </div>
+                            @if (renderLargeImages.length > 0) {
+                              <div class="thumb-list">
+                                @for (img of renderLargeImages; track img.id) {
+                                  <div class="thumb-item">
+                                    <img [src]="img.url" [alt]="img.name" />
+                                    <div class="thumb-meta">
+                                      <span class="name" [title]="img.name">{{ img.name }}</span>
+                                      <span class="size">{{ img.size }}</span>
+                                    </div>
+                                    <div class="review-meta" style="display:flex;gap:8px;align-items:center;">
+                                      <span class="status-badge">{{ getImageReviewStatusText(img) }}</span>
+                                      @if (isTeamLeaderView()) {
+                                        <button class="link success" (click)="reviewImage(img.id, 'render', 'approved')">閫氳繃</button>
+                                        <button class="link warning" (click)="reviewImage(img.id, 'render', 'rejected')">椹冲洖</button>
+                                      }
+                                    </div>
+                                    @if (isDesignerView()) { <button class="link danger" (click)="removeRenderLargeImage(img.id)">绉婚櫎</button> }
+                                  </div>
+                                }
+                              </div>
+                            }
+                          </div>
+                        </div>
+                      }
+                    </div>
+                  </div>
+                }
+              </div>
+
+              <!-- 淇濈暀鍘熶笅鏂规寜褰撳墠婵€娲婚樁娈垫樉绀虹殑鏃ц鎯呯綉鏍硷紙鍙€愭娣樻卑锛?-->
+                                }
+                              </div>
+                            </div>
+                          }
+                        </div>
+                      }
+                                  <div class="empty">姝ゅ鍙墿灞曟姇璇夊鐞嗘祦绋?璁板綍</div>
+                                }
+                              </div>
+                            </div>
+                          }
+                        </div>
+                      }
+                                  <div class="empty">姝ゅ鍙墿灞曟姇璇夊鐞嗗唴瀹?/div>
+                                }
+                              </div>
+                            </div>
+                          }
+                        </div>
+                      }
+                    </div>
+                  }
+                }
+              </div>
+
+              <!-- 淇濈暀鍘熶笅鏂规寜褰撳墠婵€娲婚樁娈垫樉绀虹殑鏃ц鎯呯綉鏍硷紙鍙€愭娣樻卑锛?-->
+              <div class="sections-content">
+                @for (sec of sections; track sec.key) {
+                  @if (expandedSection === sec.key) {
+                    <div class="section-panel" [attr.data-key]="sec.key">
+                      <!-- 浜や粯鎵ц锛氫笁闃舵妯悜鎺掑垪銆佸唴瀹圭珫鍚戝睍寮€銆佺┖闂村钩鍒?-->
+                      @if (sec.key === 'delivery') {
+                        <div class="delivery-grid">
+                          @for (stage of sec.stages; track stage) {
+                            <div class="delivery-col" [class.active]="getStageStatus(stage) === 'active'">
+                              <div class="delivery-stage-header">
+                                <span class="dot" [class.completed]="getStageStatus(stage) === 'completed'" [class.active]="getStageStatus(stage) === 'active'"></span>
+                                <h3>{{ stage }}</h3>
+                              </div>
+                              <!-- 鐩存帴澶嶇敤鍘熼樁娈靛唴瀹瑰崱鐗囷細鎸塻tage鍖归厤鏄剧ず -->
+                              <div class="delivery-stage-body">
+                                @if (stage === '寤烘ā') { <!-- 寮曠敤鍘熷缓妯″潡 -->
+                                  <!-- BEGIN: reuse 寤烘ā闃舵鍐呭 -->
+                                  @if (shouldShowCard('modelCheck')) {
+                                    <div class="model-check-section">
+                                      <h4>妯″瀷璇樊妫€鏌ユ竻鍗?/h4>
+                                      <div class="checklist">
+                                        @for (item of modelCheckItems; track item.id) {
+                                          <div class="checklist-item">
+                                            <label class="checklist-label">
+                                              <input type="checkbox" class="custom-checkbox" [checked]="item.isPassed" (change)="updateModelCheckItem(item.id, $any($event.target).checked)" [disabled]="!isDesignerView()">
+                                              <span class="checklist-text">{{ item.name }}</span>
+                                            </label>
+                                            <span class="check-status">{{ item.isPassed ? '宸查€氳繃' : '寰呭鐞? }}</span>
+                                          </div>
+                                        }
+                                      </div>
+                                    </div>
+                                  }
+                                  <div class="upload-section">
+                                    <div class="upload-header">
+                                      <h4>涓婁紶鐧芥ā鍥剧墖</h4>
+                                      <span class="hint">鏀寔锛欽PG/PNG锛涗笉寮哄埗4K</span>
+                                    </div>
+                                    <div class="upload-actions">
+                                      @if (isDesignerView()) {
+                                        <label class="secondary-btn">
+                                          閫夋嫨鍥剧墖
+                                          <input type="file" accept="{{allowedImageTypes}}" multiple (change)="onWhiteModelSelected($event)" style="display:none" />
+                                        </label>
+                                        <button class="primary-btn" [disabled]="whiteModelImages.length===0" (click)="confirmWhiteModelUpload()">纭涓婁紶</button>
+                                      }
+                                      @if (isTeamLeaderView()) { <button class="secondary-btn" (click)="syncUploadedImages('white')">鍚屾鍥剧墖淇℃伅</button> }
+                                      @if (isCustomerServiceView()) { <span class="desc">鍙</span> }
+                                    </div>
+                                    @if (whiteModelImages.length > 0) {
+                                      <div class="thumb-list">
+                                        @for (img of whiteModelImages; track img.id) {
+                                          <div class="thumb-item">
+                                            <img [src]="img.url" [alt]="img.name" />
+                                            <div class="thumb-meta">
+                                              <span class="name" [title]="img.name">{{ img.name }}</span>
+                                              <span class="size">{{ img.size }}</span>
+                                            </div>
+                                            <div class="review-meta" style="display:flex;gap:8px;align-items:center;">
+                                              <span class="status-badge">{{ getImageReviewStatusText(img) }}</span>
+                                              @if (isTeamLeaderView()) {
+                                                <button class="link success" (click)="reviewImage(img.id, 'white', 'approved')">閫氳繃</button>
+                                                <button class="link warning" (click)="reviewImage(img.id, 'white', 'rejected')">椹冲洖</button>
+                                              }
+                                            </div>
+                                            @if (isDesignerView()) { <button class="link danger" (click)="removeWhiteModelImage(img.id)">绉婚櫎</button> }
+                                          </div>
+                                        }
+                                      </div>
+                                    }
+                                  </div>
+                                  <!-- END: reuse 寤烘ā闃舵鍐呭 -->
+                                }
+
+                                @if (stage === '杞') { <!-- 寮曠敤鍘熻蒋瑁呭潡 -->
+                                  <!-- BEGIN: reuse 杞闃舵鍐呭 -->
+                                  <div class="softdecor-section">
+                                    <h4>杞琛ュ厖璧勬枡</h4>
+                                    <div class="upload-section">
+                                      <div class="upload-header">
+                                        <h4>涓婁紶杞灏忓浘</h4>
+                                        <span class="hint">寤鸿 鈮?1MB 鐨?JPG/PNG 灏忓浘</span>
+                                      </div>
+                                      <div class="upload-actions">
+                                        @if (isDesignerView()) {
+                                          <label class="secondary-btn">
+                                            閫夋嫨鍥剧墖
+                                            <input type="file" accept="{{allowedImageTypes}}" multiple (change)="onSoftDecorSmallPicsSelected($event)" style="display:none" />
+                                          </label>
+                                          <button class="primary-btn" [disabled]="softDecorImages.length===0" (click)="confirmSoftDecorUpload()">纭涓婁紶</button>
+                                        }
+                                        @if (isTeamLeaderView()) { <button class="secondary-btn" (click)="syncUploadedImages('soft')">鍚屾鍥剧墖淇℃伅</button> }
+                                        @if (isCustomerServiceView()) { <span class="desc">鍙</span> }
+                                      </div>
+                                      @if (softDecorImages.length > 0) {
+                                        <div class="thumb-list">
+                                          @for (img of softDecorImages; track img.id) {
+                                            <div class="thumb-item">
+                                              <img [src]="img.url" [alt]="img.name" />
+                                              <div class="thumb-meta">
+                                                <span class="name" [title]="img.name">{{ img.name }}</span>
+                                                <span class="size">{{ img.size }}</span>
+                                              </div>
+                                              <div class="review-meta" style="display:flex;gap:8px;align-items:center;">
+                                                <span class="status-badge">{{ getImageReviewStatusText(img) }}</span>
+                                                @if (isTeamLeaderView()) {
+                                                  <button class="link success" (click)="reviewImage(img.id, 'soft', 'approved')">閫氳繃</button>
+                                                  <button class="link warning" (click)="reviewImage(img.id, 'soft', 'rejected')">椹冲洖</button>
+                                                }
+                                              </div>
+                                              @if (isDesignerView()) { <button class="link danger" (click)="removeSoftDecorImage(img.id)">绉婚櫎</button> }
+                                            </div>
+                                          }
+                                        </div>
+                                      }
+                                    </div>
+                                  </div>
+                                  <!-- END: reuse 杞闃舵鍐呭 -->
+                                }
+
+                                @if (stage === '渲染') { <!-- 寮曠敤鍘熸覆鏌撳潡 -->
+                                  <!-- BEGIN: reuse 渲染闃舵鍐呭锛堢畝鍖栧鍣級 -->
+                                  <div class="render-progress-section">
+                                    @if (isLoadingRenderProgress) {
+                                      <div class="loading-state">
+                                        <div class="loading-spinner"></div>
+                                        <div>姝e湪鍔犺浇渲染杩涘害...</div>
+                                      </div>
+                                    }
+                                    @if (errorLoadingRenderProgress) {
+                                      <div class="error-state">
+                                        <div>渲染杩涘害鍔犺浇澶辫触</div>
+                                        <button class="secondary-btn" (click)="retryLoadRenderProgress()">重试</button>
+                                      </div>
+                                    }
+                                    @if (!isLoadingRenderProgress && !errorLoadingRenderProgress && renderProgress) {
+                                      <div class="progress-info" style="display:flex;gap:16px;align-items:center;margin:12px 0;">
+                                        <span>鐘舵€侊細{{ renderProgress.status }}</span>
+                                        <span>瀹屾垚搴︼細{{ renderProgress.completionRate }}%</span>
+                                        <span>预计剩余:{{ renderProgress.estimatedTimeRemaining }} 小时</span>
+                                      </div>
+                                    }
+                                    <div class="upload-section">
+                                      <div class="upload-header">
+                                        <h4>涓婁紶渲染澶у浘</h4>
+                                        <span class="hint">闇€婊¤冻4K鏍囧噯锛堟渶澶ц竟鈮?000px锛?/span>
+                                      </div>
+                                      <div class="upload-actions" style="display:flex;gap:12px;align-items:center;">
+                                        @if (isDesignerView()) { <button class="primary-btn" (click)="openRenderUploadModal()">閫夋嫨骞朵笂浼?/button> }
+                                        @if (isTeamLeaderView()) { <button class="secondary-btn" (click)="syncUploadedImages('render')">鍚屾鍥剧墖淇℃伅</button> }
+                                        @if (renderLargeImages.length>0) { <span class="desc">宸蹭笂浼?{{renderLargeImages.length}} 寮?/span> }
+                                      </div>
+                                      @if (renderLargeImages.length > 0) {
+                                        <div class="thumb-list">
+                                          @for (img of renderLargeImages; track img.id) {
+                                            <div class="thumb-item">
+                                              <img [src]="img.url" [alt]="img.name" />
+                                              <div class="thumb-meta">
+                                                <span class="name" [title]="img.name">{{ img.name }}</span>
+                                                <span class="size">{{ img.size }}</span>
+                                              </div>
+                                              <div class="review-meta" style="display:flex;gap:8px;align-items:center;">
+                                                <span class="status-badge">{{ getImageReviewStatusText(img) }}</span>
+                                                @if (isTeamLeaderView()) {
+                                                  <button class="link success" (click)="reviewImage(img.id, 'render', 'approved')">閫氳繃</button>
+                                                  <button class="link warning" (click)="reviewImage(img.id, 'render', 'rejected')">椹冲洖</button>
+                                                }
+                                              </div>
+                                              @if (isDesignerView()) { <button class="link danger" (click)="removeRenderLargeImage(img.id)">绉婚櫎</button> }
+                                            </div>
+                                          }
+                                        </div>
+                                      }
+                                    </div>
+                                  </div>
+                                </div>
+                              </div>
+                            </div>
+                          }
+                        </div>
+                      }
+                                  <div class="empty">姝ゅ鍙墿灞曟姇璇夊鐞嗘祦绋?璁板綍</div>
+                                }
+                              </div>
+                            </div>
+                          }
+                        </div>
+                      }
+                                  <div class="empty">姝ゅ鍙墿灞曟姇璇夊鐞嗗唴瀹?/div>
+                                }
+                              </div>
+                            </div>
+                          }
+                        </div>
+                      }
+                    </div>
+                  }
+                }
+              </div>
+
+              <!-- 淇濈暀鍘熶笅鏂规寜褰撳墠婵€娲婚樁娈垫樉绀虹殑鏃ц鎯呯綉鏍硷紙鍙€愭娣樻卑锛?-->
+              <div class="sections-content">
+                @for (sec of sections; track sec.key) {
+                  @if (expandedSection === sec.key) {
+                    <div class="section-panel" [attr.data-key]="sec.key">
+                      <!-- 浜や粯鎵ц锛氫笁闃舵妯悜鎺掑垪銆佸唴瀹圭珫鍚戝睍寮€銆佺┖闂村钩鍒?-->
+                      @if (sec.key === 'delivery') {
+                        <div class="delivery-grid">
+                          @for (stage of sec.stages; track stage) {
+                            <div class="delivery-col" [class.active]="getStageStatus(stage) === 'active'">
+                              <div class="delivery-stage-header">
+                                <span class="dot" [class.completed]="getStageStatus(stage) === 'completed'" [class.active]="getStageStatus(stage) === 'active'"></span>
+                                <h3>{{ stage }}</h3>
+                              </div>
+                              <!-- 鐩存帴澶嶇敤鍘熼樁娈靛唴瀹瑰崱鐗囷細鎸塻tage鍖归厤鏄剧ず -->
+                              <div class="delivery-stage-body">
+                                @if (stage === '寤烘ā') { <!-- 寮曠敤鍘熷缓妯″潡 -->
+                                  <!-- BEGIN: reuse 寤烘ā闃舵鍐呭 -->
+                                  @if (shouldShowCard('modelCheck')) {
+                                    <div class="model-check-section">
+                                      <h4>妯″瀷璇樊妫€鏌ユ竻鍗?/h4>
+                                      <div class="checklist">
+                                        @for (item of modelCheckItems; track item.id) {
+                                          <div class="checklist-item">
+                                            <label class="checklist-label">
+                                              <input type="checkbox" class="custom-checkbox" [checked]="item.isPassed" (change)="updateModelCheckItem(item.id, $any($event.target).checked)" [disabled]="!isDesignerView()">
+                                              <span class="checklist-text">{{ item.name }}</span>
+                                            </label>
+                                            <span class="check-status">{{ item.isPassed ? '宸查€氳繃' : '寰呭鐞? }}</span>
+                                          </div>
+                                        }
+                                      </div>
+                                    </div>
+                                  }
+                                  <div class="upload-section">
+                                    <div class="upload-header">
+                                      <h4>涓婁紶鐧芥ā鍥剧墖</h4>
+                                      <span class="hint">鏀寔锛欽PG/PNG锛涗笉寮哄埗4K</span>
+                                    </div>
+                                    <div class="upload-actions">
+                                      @if (isDesignerView()) {
+                                        <label class="secondary-btn">
+                                          閫夋嫨鍥剧墖
+                                          <input type="file" accept="{{allowedImageTypes}}" multiple (change)="onWhiteModelSelected($event)" style="display:none" />
+                                        </label>
+                                        <button class="primary-btn" [disabled]="whiteModelImages.length===0" (click)="confirmWhiteModelUpload()">纭涓婁紶</button>
+                                      }
+                                      @if (isTeamLeaderView()) { <button class="secondary-btn" (click)="syncUploadedImages('white')">鍚屾鍥剧墖淇℃伅</button> }
+                                      @if (isCustomerServiceView()) { <span class="desc">鍙</span> }
+                                    </div>
+                                    @if (whiteModelImages.length > 0) {
+                                      <div class="thumb-list">
+                                        @for (img of whiteModelImages; track img.id) {
+                                          <div class="thumb-item">
+                                            <img [src]="img.url" [alt]="img.name" />
+                                            <div class="thumb-meta">
+                                              <span class="name" [title]="img.name">{{ img.name }}</span>
+                                              <span class="size">{{ img.size }}</span>
+                                            </div>
+                                            <div class="review-meta" style="display:flex;gap:8px;align-items:center;">
+                                              <span class="status-badge">{{ getImageReviewStatusText(img) }}</span>
+                                              @if (isTeamLeaderView()) {
+                                                <button class="link success" (click)="reviewImage(img.id, 'white', 'approved')">閫氳繃</button>
+                                                <button class="link warning" (click)="reviewImage(img.id, 'white', 'rejected')">椹冲洖</button>
+                                              }
+                                            </div>
+                                            @if (isDesignerView()) { <button class="link danger" (click)="removeWhiteModelImage(img.id)">绉婚櫎</button> }
+                                          </div>
+                                        }
+                                      </div>
+                                    }
+                                  </div>
+                                  <!-- END: reuse 寤烘ā闃舵鍐呭 -->
+                                }
+
+                                @if (stage === '杞') { <!-- 寮曠敤鍘熻蒋瑁呭潡 -->
+                                  <!-- BEGIN: reuse 杞闃舵鍐呭 -->
+                                  <div class="softdecor-section">
+                                    <h4>杞琛ュ厖璧勬枡</h4>
+                                    <div class="upload-section">
+                                      <div class="upload-header">
+                                        <h4>涓婁紶杞灏忓浘</h4>
+                                        <span class="hint">寤鸿 鈮?1MB 鐨?JPG/PNG 灏忓浘</span>
+                                      </div>
+                                      <div class="upload-actions">
+                                        @if (isDesignerView()) {
+                                          <label class="secondary-btn">
+                                            閫夋嫨鍥剧墖
+                                            <input type="file" accept="{{allowedImageTypes}}" multiple (change)="onSoftDecorSmallPicsSelected($event)" style="display:none" />
+                                          </label>
+                                          <button class="primary-btn" [disabled]="softDecorImages.length===0" (click)="confirmSoftDecorUpload()">纭涓婁紶</button>
+                                        }
+                                        @if (isTeamLeaderView()) { <button class="secondary-btn" (click)="syncUploadedImages('soft')">鍚屾鍥剧墖淇℃伅</button> }
+                                        @if (isCustomerServiceView()) { <span class="desc">鍙</span> }
+                                      </div>
+                                      @if (softDecorImages.length > 0) {
+                                        <div class="thumb-list">
+                                          @for (img of softDecorImages; track img.id) {
+                                            <div class="thumb-item">
+                                              <img [src]="img.url" [alt]="img.name" />
+                                              <div class="thumb-meta">
+                                                <span class="name" [title]="img.name">{{ img.name }}</span>
+                                                <span class="size">{{ img.size }}</span>
+                                              </div>
+                                              <div class="review-meta" style="display:flex;gap:8px;align-items:center;">
+                                                <span class="status-badge">{{ getImageReviewStatusText(img) }}</span>
+                                                @if (isTeamLeaderView()) {
+                                                  <button class="link success" (click)="reviewImage(img.id, 'soft', 'approved')">閫氳繃</button>
+                                                  <button class="link warning" (click)="reviewImage(img.id, 'soft', 'rejected')">椹冲洖</button>
+                                                }
+                                              </div>
+                                              @if (isDesignerView()) { <button class="link danger" (click)="removeSoftDecorImage(img.id)">绉婚櫎</button> }
+                                            </div>
+                                          }
+                                        </div>
+                                      }
+                                    </div>
+                                  </div>
+                                  <!-- END: reuse 杞闃舵鍐呭 -->
+                                }
+
+                                @if (stage === '渲染') { <!-- 寮曠敤鍘熸覆鏌撳潡 -->
+                                  <!-- BEGIN: reuse 渲染闃舵鍐呭锛堢畝鍖栧鍣級 -->
+                                  <div class="render-progress-section">
+                                    @if (isLoadingRenderProgress) {
+                                      <div class="loading-state">
+                                        <div class="loading-spinner"></div>
+                                        <div>姝e湪鍔犺浇渲染杩涘害...</div>
+                                      </div>
+                                    }
+                                    @if (errorLoadingRenderProgress) {
+                                      <div class="error-state">
+                                        <div>渲染杩涘害鍔犺浇澶辫触</div>
+                                        <button class="secondary-btn" (click)="retryLoadRenderProgress()">重试</button>
+                                      </div>
+                                    }
+                                    @if (!isLoadingRenderProgress && !errorLoadingRenderProgress && renderProgress) {
+                                      <div class="progress-info" style="display:flex;gap:16px;align-items:center;margin:12px 0;">
+                                        <span>鐘舵€侊細{{ renderProgress.status }}</span>
+                                        <span>瀹屾垚搴︼細{{ renderProgress.completionRate }}%</span>
+                                        <span>预计剩余:{{ renderProgress.estimatedTimeRemaining }} 小时</span>
+                                      </div>
+                                    }
+                                    <div class="upload-section">
+                                      <div class="upload-header">
+                                        <h4>涓婁紶渲染澶у浘</h4>
+                                        <span class="hint">闇€婊¤冻4K鏍囧噯锛堟渶澶ц竟鈮?000px锛?/span>
+                                      </div>
+                                      <div class="upload-actions" style="display:flex;gap:12px;align-items:center;">
+                                        @if (isDesignerView()) { <button class="primary-btn" (click)="openRenderUploadModal()">閫夋嫨骞朵笂浼?/button> }
+                                        @if (isTeamLeaderView()) { <button class="secondary-btn" (click)="syncUploadedImages('render')">鍚屾鍥剧墖淇℃伅</button> }
+                                        @if (renderLargeImages.length>0) { <span class="desc">宸蹭笂浼?{{renderLargeImages.length}} 寮?/span> }
+                                      </div>
+                                      @if (renderLargeImages.length > 0) {
+                                        <div class="thumb-list">
+                                          @for (img of renderLargeImages; track img.id) {
+                                            <div class="thumb-item">
+                                              <img [src]="img.url" [alt]="img.name" />
+                                              <div class="thumb-meta">
+                                                <span class="name" [title]="img.name">{{ img.name }}</span>
+                                                <span class="size">{{ img.size }}</span>
+                                              </div>
+                                              <div class="review-meta" style="display:flex;gap:8px;align-items:center;">
+                                                <span class="status-badge">{{ getImageReviewStatusText(img) }}</span>
+                                                @if (isTeamLeaderView()) {
+                                                  <button class="link success" (click)="reviewImage(img.id, 'render', 'approved')">閫氳繃</button>
+                                                  <button class="link warning" (click)="reviewImage(img.id, 'render', 'rejected')">椹冲洖</button>
+                                                }
+                                              </div>
+                                              @if (isDesignerView()) { <button class="link danger" (click)="removeRenderLargeImage(img.id)">绉婚櫎</button> }
+                                            </div>
+                                          }
+                                        </div>
+                                      }
+                                    </div>
+                                  </div>
+                                </div>
+                              </div>
+                            </div>
+                          }
+                        </div>
+                      }
+                                  <div class="empty">姝ゅ鍙墿灞曟姇璇夊鐞嗗唴瀹?/div>
+                                }
+                              </div>
+                            </div>
+                          }
+                        </div>
+                      }
+                                  <div class="empty">姝ゅ鍙墿灞曟姇璇夊鐞嗗唴瀹?/div>
+                                }
+                              </div>
+                            </div>
+                          }
+                        </div>
+                      }
+                    </div>
+                  }
+                }
+              </div>
+
+              <!-- 淇濈暀鍘熶笅鏂规寜褰撳墠婵€娲婚樁娈垫樉绀虹殑鏃ц鎯呯綉鏍硷紙鍙€愭娣樻卑锛?-->
+              <div class="sections-content">
+                @for (sec of sections; track sec.key) {
+                  @if (expandedSection === sec.key) {
+                    <div class="section-panel" [attr.data-key]="sec.key">
+                      <!-- 浜や粯鎵ц锛氫笁闃舵妯悜鎺掑垪銆佸唴瀹圭珫鍚戝睍寮€銆佺┖闂村钩鍒?-->
+                      @if (sec.key === 'delivery') {
+                        <div class="delivery-grid">
+                          @for (stage of sec.stages; track stage) {
+                            <div class="delivery-col" [class.active]="getStageStatus(stage) === 'active'">
+                              <div class="delivery-stage-header">
+                                <span class="dot" [class.completed]="getStageStatus(stage) === 'completed'" [class.active]="getStageStatus(stage) === 'active'"></span>
+                                <h3>{{ stage }}</h3>
+                              </div>
+                              <!-- 鐩存帴澶嶇敤鍘熼樁娈靛唴瀹瑰崱鐗囷細鎸塻tage鍖归厤鏄剧ず -->
+                              <div class="delivery-stage-body">
+                                @if (stage === '寤烘ā') { <!-- 寮曠敤鍘熷缓妯″潡 -->
+                                  <!-- BEGIN: reuse 寤烘ā闃舵鍐呭 -->
+                                  @if (shouldShowCard('modelCheck')) {
+                                    <div class="model-check-section">
+                                      <h4>妯″瀷璇樊妫€鏌ユ竻鍗?/h4>
+                                      <div class="checklist">
+                                        @for (item of modelCheckItems; track item.id) {
+                                          <div class="checklist-item">
+                                            <label class="checklist-label">
+                                              <input type="checkbox" class="custom-checkbox" [checked]="item.isPassed" (change)="updateModelCheckItem(item.id, $any($event.target).checked)" [disabled]="!isDesignerView()">
+                                              <span class="checklist-text">{{ item.name }}</span>
+                                            </label>
+                                            <span class="check-status">{{ item.isPassed ? '宸查€氳繃' : '寰呭鐞? }}</span>
+                                          </div>
+                                        }
+                                      </div>
+                                    </div>
+                                  }
+                                  <div class="upload-section">
+                                    <div class="upload-header">
+                                      <h4>涓婁紶鐧芥ā鍥剧墖</h4>
+                                      <span class="hint">鏀寔锛欽PG/PNG锛涗笉寮哄埗4K</span>
+                                    </div>
+                                    <div class="upload-actions">
+                                      @if (isDesignerView()) {
+                                        <label class="secondary-btn">
+                                          閫夋嫨鍥剧墖
+                                          <input type="file" accept="{{allowedImageTypes}}" multiple (change)="onWhiteModelSelected($event)" style="display:none" />
+                                        </label>
+                                        <button class="primary-btn" [disabled]="whiteModelImages.length===0" (click)="confirmWhiteModelUpload()">纭涓婁紶</button>
+                                      }
+                                      @if (isTeamLeaderView()) { <button class="secondary-btn" (click)="syncUploadedImages('white')">鍚屾鍥剧墖淇℃伅</button> }
+                                      @if (isCustomerServiceView()) { <span class="desc">鍙</span> }
+                                    </div>
+                                    @if (whiteModelImages.length > 0) {
+                                      <div class="thumb-list">
+                                        @for (img of whiteModelImages; track img.id) {
+                                          <div class="thumb-item">
+                                            <img [src]="img.url" [alt]="img.name" />
+                                            <div class="thumb-meta">
+                                              <span class="name" [title]="img.name">{{ img.name }}</span>
+                                              <span class="size">{{ img.size }}</span>
+                                            </div>
+                                            <div class="review-meta" style="display:flex;gap:8px;align-items:center;">
+                                              <span class="status-badge">{{ getImageReviewStatusText(img) }}</span>
+                                              @if (isTeamLeaderView()) {
+                                                <button class="link success" (click)="reviewImage(img.id, 'white', 'approved')">閫氳繃</button>
+                                                <button class="link warning" (click)="reviewImage(img.id, 'white', 'rejected')">椹冲洖</button>
+                                              }
+                                            </div>
+                                            @if (isDesignerView()) { <button class="link danger" (click)="removeWhiteModelImage(img.id)">绉婚櫎</button> }
+                                          </div>
+                                        }
+                                      </div>
+                                    }
+                                  </div>
+                                  <!-- END: reuse 寤烘ā闃舵鍐呭 -->
+                                }
+
+                                @if (stage === '杞') { <!-- 寮曠敤鍘熻蒋瑁呭潡 -->
+                                  <!-- BEGIN: reuse 杞闃舵鍐呭 -->
+                                  <div class="softdecor-section">
+                                    <h4>杞琛ュ厖璧勬枡</h4>
+                                    <div class="upload-section">
+                                      <div class="upload-header">
+                                        <h4>涓婁紶杞灏忓浘</h4>
+                                        <span class="hint">寤鸿 鈮?1MB 鐨?JPG/PNG 灏忓浘</span>
+                                      </div>
+                                      <div class="upload-actions">
+                                        @if (isDesignerView()) {
+                                          <label class="secondary-btn">
+                                            閫夋嫨鍥剧墖
+                                            <input type="file" accept="{{allowedImageTypes}}" multiple (change)="onSoftDecorSmallPicsSelected($event)" style="display:none" />
+                                          </label>
+                                          <button class="primary-btn" [disabled]="softDecorImages.length===0" (click)="confirmSoftDecorUpload()">纭涓婁紶</button>
+                                        }
+                                        @if (isTeamLeaderView()) { <button class="secondary-btn" (click)="syncUploadedImages('soft')">鍚屾鍥剧墖淇℃伅</button> }
+                                        @if (isCustomerServiceView()) { <span class="desc">鍙</span> }
+                                      </div>
+                                      @if (softDecorImages.length > 0) {
+                                        <div class="thumb-list">
+                                          @for (img of softDecorImages; track img.id) {
+                                            <div class="thumb-item">
+                                              <img [src]="img.url" [alt]="img.name" />
+                                              <div class="thumb-meta">
+                                                <span class="name" [title]="img.name">{{ img.name }}</span>
+                                                <span class="size">{{ img.size }}</span>
+                                              </div>
+                                              <div class="review-meta" style="display:flex;gap:8px;align-items:center;">
+                                                <span class="status-badge">{{ getImageReviewStatusText(img) }}</span>
+                                                @if (isTeamLeaderView()) {
+                                                  <button class="link success" (click)="reviewImage(img.id, 'soft', 'approved')">閫氳繃</button>
+                                                  <button class="link warning" (click)="reviewImage(img.id, 'soft', 'rejected')">椹冲洖</button>
+                                                }
+                                              </div>
+                                              @if (isDesignerView()) { <button class="link danger" (click)="removeSoftDecorImage(img.id)">绉婚櫎</button> }
+                                            </div>
+                                          }
+                                        </div>
+                                      }
+                                    </div>
+                                  </div>
+                                  <!-- END: reuse 杞闃舵鍐呭 -->
+                                }
+
+                                @if (stage === '渲染') { <!-- 寮曠敤鍘熸覆鏌撳潡 -->
+                                  <!-- BEGIN: reuse 渲染闃舵鍐呭锛堢畝鍖栧鍣級 -->
+                                  <div class="render-progress-section">
+                                    @if (isLoadingRenderProgress) {
+                                      <div class="loading-state">
+                                        <div class="loading-spinner"></div>
+                                        <div>姝e湪鍔犺浇渲染杩涘害...</div>
+                                      </div>
+                                    }
+                                    @if (errorLoadingRenderProgress) {
+                                      <div class="error-state">
+                                        <div>渲染杩涘害鍔犺浇澶辫触</div>
+                                        <button class="secondary-btn" (click)="retryLoadRenderProgress()">重试</button>
+                                      </div>
+                                    }
+                                    @if (!isLoadingRenderProgress && !errorLoadingRenderProgress && renderProgress) {
+                                      <div class="progress-info" style="display:flex;gap:16px;align-items:center;margin:12px 0;">
+                                        <span>鐘舵€侊細{{ renderProgress.status }}</span>
+                                        <span>瀹屾垚搴︼細{{ renderProgress.completionRate }}%</span>
+                                        <span>预计剩余:{{ renderProgress.estimatedTimeRemaining }} 小时</span>
+                                      </div>
+                                    }
+                                    <div class="upload-section">
+                                      <div class="upload-header">
+                                        <h4>涓婁紶渲染澶у浘</h4>
+                                        <span class="hint">闇€婊¤冻4K鏍囧噯锛堟渶澶ц竟鈮?000px锛?/span>
+                                      </div>
+                                      <div class="upload-actions" style="display:flex;gap:12px;align-items:center;">
+                                        @if (isDesignerView()) { <button class="primary-btn" (click)="openRenderUploadModal()">閫夋嫨骞朵笂浼?/button> }
+                                        @if (isTeamLeaderView()) { <button class="secondary-btn" (click)="syncUploadedImages('render')">鍚屾鍥剧墖淇℃伅</button> }
+                                        @if (renderLargeImages.length>0) { <span class="desc">宸蹭笂浼?{{renderLargeImages.length}} 寮?/span> }
+                                      </div>
+                                      @if (renderLargeImages.length > 0) {
+                                        <div class="thumb-list">
+                                          @for (img of renderLargeImages; track img.id) {
+                                            <div class="thumb-item">
+                                              <img [src]="img.url" [alt]="img.name" />
+                                              <div class="thumb-meta">
+                                                <span class="name" [title]="img.name">{{ img.name }}</span>
+                                                <span class="size">{{ img.size }}</span>
+                                              </div>
+                                              <div class="review-meta" style="display:flex;gap:8px;align-items:center;">
+                                                <span class="status-badge">{{ getImageReviewStatusText(img) }}</span>
+                                                @if (isTeamLeaderView()) {
+                                                  <button class="link success" (click)="reviewImage(img.id, 'render', 'approved')">閫氳繃</button>
+                                                  <button class="link warning" (click)="reviewImage(img.id, 'render', 'rejected')">椹冲洖</button>
+                                                }
+                                              </div>
+                                              @if (isDesignerView()) { <button class="link danger" (click)="removeRenderLargeImage(img.id)">绉婚櫎</button> }
+                                            </div>
+                                          }
+                                        </div>
+                                      }
+                                    </div>
+                                  </div>
+                                </div>
+                              </div>
+                            </div>
+                          }
+                        </div>
+                      }
+                                  <div class="empty">姝ゅ鍙墿灞曟姇璇夊鐞嗘祦绋?璁板綍</div>
+                                }
+                              </div>
+                            </div>
+                          }
+                        </div>
+                      }
+                                  <div class="empty">姝ゅ鍙墿灞曟姇璇夊鐞嗗唴瀹?/div>
+                                }
+                              </div>
+                            </div>
+                          }
+                        </div>
+                      }
+                    </div>
+                  }
+                }
+              </div>
+
+              <!-- 淇濈暀鍘熶笅鏂规寜褰撳墠婵€娲婚樁娈垫樉绀虹殑鏃ц鎯呯綉鏍硷紙鍙€愭娣樻卑锛?-->
+              <div class="sections-content">
+                @for (sec of sections; track sec.key) {
+                  @if (expandedSection === sec.key) {
+                    <div class="section-panel" [attr.data-key]="sec.key">
+                      <!-- 浜や粯鎵ц锛氫笁闃舵妯悜鎺掑垪銆佸唴瀹圭珫鍚戝睍寮€銆佺┖闂村钩鍒?-->
+                      @if (sec.key === 'delivery') {
+                        <div class="delivery-grid">
+                          @for (stage of sec.stages; track stage) {
+                            <div class="delivery-col" [class.active]="getStageStatus(stage) === 'active'">
+                              <div class="delivery-stage-header">
+                                <span class="dot" [class.completed]="getStageStatus(stage) === 'completed'" [class.active]="getStageStatus(stage) === 'active'"></span>
+                                <h3>{{ stage }}</h3>
+                              </div>
+                              <!-- 鐩存帴澶嶇敤鍘熼樁娈靛唴瀹瑰崱鐗囷細鎸塻tage鍖归厤鏄剧ず -->
+                              <div class="delivery-stage-body">
+                                @if (stage === '寤烘ā') { <!-- 寮曠敤鍘熷缓妯″潡 -->
+                                  <!-- BEGIN: reuse 寤烘ā闃舵鍐呭 -->
+                                  @if (shouldShowCard('modelCheck')) {
+                                    <div class="model-check-section">
+                                      <h4>妯″瀷璇樊妫€鏌ユ竻鍗?/h4>
+                                      <div class="checklist">
+                                        @for (item of modelCheckItems; track item.id) {
+                                          <div class="checklist-item">
+                                            <label class="checklist-label">
+                                              <input type="checkbox" class="custom-checkbox" [checked]="item.isPassed" (change)="updateModelCheckItem(item.id, $any($event.target).checked)" [disabled]="!isDesignerView()">
+                                              <span class="checklist-text">{{ item.name }}</span>
+                                            </label>
+                                            <span class="check-status">{{ item.isPassed ? '宸查€氳繃' : '寰呭鐞? }}</span>
+                                          </div>
+                                        }
+                                      </div>
+                                    </div>
+                                  }
+                                  <div class="upload-section">
+                                    <div class="upload-header">
+                                      <h4>涓婁紶鐧芥ā鍥剧墖</h4>
+                                      <span class="hint">鏀寔锛欽PG/PNG锛涗笉寮哄埗4K</span>
+                                    </div>
+                                    <div class="upload-actions">
+                                      @if (isDesignerView()) {
+                                        <label class="secondary-btn">
+                                          閫夋嫨鍥剧墖
+                                          <input type="file" accept="{{allowedImageTypes}}" multiple (change)="onWhiteModelSelected($

Some files were not shown because too many files changed in this diff