123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220 |
- <div class="project-list-container">
- <!-- 右侧主要内容 -->
- <div class="project-content">
- <!-- 页面标题和操作 -->
- <div class="page-header">
- <h2>项目列表</h2>
- <div class="header-actions">
- <div class="search-container">
- <div class="search-box">
- <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor">
- <circle cx="11" cy="11" r="8"></circle>
- <line x1="21" y1="21" x2="16.65" y2="16.65"></line>
- </svg>
- <input
- type="text"
- placeholder="搜索项目名称或客户..."
- [value]="searchTerm()"
- (input)="searchTerm.set($any($event.target).value)"
- (keyup.enter)="onSearch()"
- >
- <button class="search-btn" (click)="onSearch()">
- <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor">
- <line x1="5" y1="12" x2="19" y2="12"></line>
- <polyline points="12 5 19 12 12 19"></polyline>
- </svg>
- </button>
- </div>
- </div>
- </div>
- </div>
- <!-- 筛选和排序工具栏 -->
- <div class="filter-toolbar">
- <div class="filter-group">
- <label>状态筛选</label>
- <select (change)="onStatusChange($event)" [value]="statusFilter()">
- <option *ngFor="let option of statusOptions" [value]="option.value">
- {{ option.label }}
- </option>
- </select>
- </div>
-
- <div class="filter-group">
- <label>阶段筛选</label>
- <select (change)="onStageChange($event)" [value]="stageFilter()">
- <option *ngFor="let option of stageOptions" [value]="option.value">
- {{ option.label }}
- </option>
- </select>
- </div>
-
- <div class="filter-group">
- <label>排序方式</label>
- <select (change)="onSortChange($event)" [value]="sortBy()">
- <option *ngFor="let option of sortOptions" [value]="option.value">
- {{ option.label }}
- </option>
- </select>
- </div>
-
- <div class="filter-results">
- <span>共 {{ projects().length }} 个项目</span>
- </div>
- </div>
- <!-- 项目列表 -->
- <div class="project-grid">
- <div *ngFor="let project of paginatedProjects()" class="project-card">
- <div class="card-header">
- <div class="card-title-section">
- <h3 class="project-name">{{ project.name }}</h3>
- <span class="project-id">#{{ project.id }}</span>
- </div>
- <div class="card-tags">
- <span class="project-tag">{{ project.tagDisplayText }}</span>
- <span *ngIf="project.isUrgent" class="urgent-tag">紧急</span>
- </div>
- </div>
-
- <div class="card-content">
- <!-- 客户信息 -->
- <div class="info-item">
- <span class="info-label">客户</span>
- <span class="info-value">{{ project.customerName }}</span>
- </div>
-
- <!-- 设计师信息 -->
- <div class="info-item">
- <span class="info-label">设计师</span>
- <span class="info-value">{{ project.assigneeName }}</span>
- </div>
-
- <!-- 项目状态 -->
- <div class="info-item">
- <span class="info-label">状态</span>
- <span class="info-value status-badge" [class]="getStatusClass(project.status)">
- {{ project.status }}
- </span>
- </div>
-
- <!-- 当前阶段 -->
- <div class="info-item">
- <span class="info-label">阶段</span>
- <span class="info-value stage-badge" [class]="getStageClass(project.currentStage)">
- {{ project.currentStage }}
- </span>
- </div>
-
- <!-- 项目进度 -->
- <div class="progress-section">
- <div class="progress-header">
- <span class="progress-label">进度</span>
- <span class="progress-percentage">{{ project.progress }}%</span>
- </div>
- <div class="progress-bar">
- <div
- class="progress-fill"
- [style.width.percent]="project.progress"
- [style.backgroundColor]="project.status === '进行中' ? '#1976d2' : '#757575'"
- ></div>
- </div>
- </div>
-
- <!-- 时间信息 -->
- <div class="timeline-info">
- <div class="time-item">
- <span class="time-label">创建时间</span>
- <span class="time-value">{{ formatDate(project.createdAt) }}</span>
- </div>
- <div class="time-item">
- <span class="time-label">截止日期</span>
- <span
- class="time-value deadline"
- [class.overdue]="project.daysUntilDeadline < 0"
- [class.urgent]="project.isUrgent"
- >
- {{ formatDate(project.deadline) }} ({{ project.daysUntilDeadline >= 0 ? '还有' + project.daysUntilDeadline + '天' : '已逾期' + getAbsValue(project.daysUntilDeadline) + '天' }})
- </span>
- </div>
- </div>
-
- <!-- 高优先级需求 -->
- <div *ngIf="project.highPriorityNeeds && project.highPriorityNeeds.length > 0" class="needs-section">
- <span class="needs-label">高优先级需求:</span>
- <ul class="needs-list">
- <li *ngFor="let need of project.highPriorityNeeds">
- <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor">
- <circle cx="12" cy="12" r="10"></circle>
- <line x1="12" y1="8" x2="12" y2="12"></line>
- <line x1="12" y1="16" x2="12.01" y2="16"></line>
- </svg>
- {{ need }}
- </li>
- </ul>
- </div>
- </div>
-
- <div class="card-footer">
- <button class="secondary-btn card-action">
- <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor">
- <path d="M21 11.5a8.38 8.38 0 0 1-.9 3.8 8.5 8.5 0 0 1-7.6 4.7 8.38 8.38 0 0 1-3.8-.9L3 21l1.9-5.7a8.38 8.38 0 0 1-.9-3.8 8.5 8.5 0 0 1 4.7-7.6 8.38 8.38 0 0 1 3.8-.9h.5a8.48 8.48 0 0 1 8 8v.5z"></path>
- </svg>
- <span>联系</span>
- </button>
- <a [routerLink]="['/designer/project-detail', project.id]" class="primary-btn card-action">
- <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor">
- <path d="M21 11.5a8.38 8.38 0 0 1-.9 3.8 8.5 8.5 0 0 1-7.6 4.7 8.38 8.38 0 0 1-3.8-.9L3 21l1.9-5.7a8.38 8.38 0 0 1-.9-3.8 8.5 8.5 0 0 1 4.7-7.6 8.38 8.38 0 0 1 3.8-.9h.5a8.48 8.48 0 0 1 8 8v.5z"></path>
- </svg>
- <span>查看详情</span>
- </a>
- </div>
- </div>
- </div>
- <!-- 分页控件 -->
- <div class="pagination" *ngIf="totalPages() > 1">
- <button
- class="pagination-btn"
- (click)="prevPage()"
- [disabled]="currentPage() === 1"
- >
- <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor">
- <line x1="15" y1="18" x2="9" y2="12"></line>
- <line x1="9" y1="18" x2="15" y2="12"></line>
- </svg>
- </button>
-
- <button
- *ngFor="let page of pageNumbers()"
- class="pagination-btn"
- [class.active]="page === currentPage()"
- (click)="goToPage(page)"
- >
- {{ page }}
- </button>
-
- <!-- 省略号 -->
- <span *ngIf="totalPages() > 5" class="pagination-ellipsis">...</span>
-
- <button
- *ngIf="totalPages() > 5"
- class="pagination-btn"
- (click)="goToPage(totalPages())"
- >
- {{ totalPages() }}
- </button>
-
- <button
- class="pagination-btn"
- (click)="nextPage()"
- [disabled]="currentPage() === totalPages()"
- >
- <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor">
- <line x1="9" y1="18" x2="15" y2="12"></line>
- <line x1="15" y1="6" x2="9" y2="12"></line>
- </svg>
- </button>
- </div>
- </div>
- </div>
|