designers.html 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226
  1. <div class="designers-page">
  2. <!-- 页面标题 -->
  3. <div class="page-header">
  4. <div class="header-left">
  5. <h2 class="page-title">设计师管理</h2>
  6. <p class="page-description">管理设计师团队,查看工作状态和绩效数据</p>
  7. </div>
  8. <div class="header-actions">
  9. <button class="btn btn-primary" (click)="addDesigner()">
  10. <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor">
  11. <line x1="12" y1="5" x2="12" y2="19"></line>
  12. <line x1="5" y1="12" x2="19" y2="12"></line>
  13. </svg>
  14. 添加设计师
  15. </button>
  16. <button class="btn btn-secondary" (click)="exportDesigners()">
  17. <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor">
  18. <path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"></path>
  19. <polyline points="7 10 12 15 17 10"></polyline>
  20. <line x1="12" y1="15" x2="12" y2="3"></line>
  21. </svg>
  22. 导出数据
  23. </button>
  24. </div>
  25. </div>
  26. <!-- 统计卡片 -->
  27. <div class="stats-overview">
  28. <div class="stat-card">
  29. <div class="stat-icon primary">
  30. <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor">
  31. <path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2"></path>
  32. <circle cx="12" cy="7" r="4"></circle>
  33. </svg>
  34. </div>
  35. <div class="stat-content">
  36. <div class="stat-value">{{ totalDesigners() }}</div>
  37. <div class="stat-label">设计师总数</div>
  38. </div>
  39. </div>
  40. <div class="stat-card">
  41. <div class="stat-icon success">
  42. <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor">
  43. <path d="M22 11.08V12a10 10 0 1 1-5.93-9.14"></path>
  44. <polyline points="22 4 12 14.01 9 11.01"></polyline>
  45. </svg>
  46. </div>
  47. <div class="stat-content">
  48. <div class="stat-value">{{ activeDesigners() }}</div>
  49. <div class="stat-label">在线设计师</div>
  50. </div>
  51. </div>
  52. <div class="stat-card">
  53. <div class="stat-icon warning">
  54. <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor">
  55. <circle cx="12" cy="12" r="10"></circle>
  56. <line x1="12" y1="8" x2="12" y2="12"></line>
  57. <line x1="12" y1="16" x2="12.01" y2="16"></line>
  58. </svg>
  59. </div>
  60. <div class="stat-content">
  61. <div class="stat-value">{{ busyDesigners() }}</div>
  62. <div class="stat-label">忙碌设计师</div>
  63. </div>
  64. </div>
  65. <div class="stat-card">
  66. <div class="stat-icon danger">
  67. <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor">
  68. <circle cx="12" cy="12" r="10"></circle>
  69. <line x1="15" y1="9" x2="9" y2="15"></line>
  70. <line x1="9" y1="9" x2="15" y2="15"></line>
  71. </svg>
  72. </div>
  73. <div class="stat-content">
  74. <div class="stat-value">{{ inactiveDesigners() }}</div>
  75. <div class="stat-label">离线设计师</div>
  76. </div>
  77. </div>
  78. </div>
  79. <!-- 筛选和搜索 -->
  80. <div class="filters-section">
  81. <div class="search-box">
  82. <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor">
  83. <circle cx="11" cy="11" r="8"></circle>
  84. <path d="M21 21l-4.35-4.35"></path>
  85. </svg>
  86. <input
  87. type="text"
  88. placeholder="搜索设计师姓名或邮箱..."
  89. [(ngModel)]="searchTerm"
  90. (input)="searchTerm.set($any($event.target).value)"
  91. >
  92. </div>
  93. <div class="filter-controls">
  94. <select [(ngModel)]="selectedDepartment" (change)="selectedDepartment.set($any($event.target).value)">
  95. <option value="all">全部部门</option>
  96. <option *ngFor="let dept of departments" [value]="dept">{{ dept }}</option>
  97. </select>
  98. <select [(ngModel)]="selectedLevel" (change)="selectedLevel.set($any($event.target).value)">
  99. <option value="all">全部等级</option>
  100. <option value="junior">初级</option>
  101. <option value="intermediate">中级</option>
  102. <option value="senior">高级</option>
  103. <option value="expert">专家</option>
  104. </select>
  105. <select [(ngModel)]="selectedStatus" (change)="selectedStatus.set($any($event.target).value)">
  106. <option value="all">全部状态</option>
  107. <option value="active">在线</option>
  108. <option value="busy">忙碌</option>
  109. <option value="inactive">离线</option>
  110. </select>
  111. <button class="btn btn-outline" (click)="resetFilters()">
  112. <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor">
  113. <polyline points="1 4 1 10 7 10"></polyline>
  114. <path d="M3.51 15a9 9 0 1 0 2.13-9.36L1 10"></path>
  115. </svg>
  116. 重置
  117. </button>
  118. </div>
  119. </div>
  120. <!-- 设计师列表 -->
  121. <div class="designers-grid">
  122. <div class="designer-card" *ngFor="let designer of filteredDesigners">
  123. <div class="designer-header">
  124. <div class="designer-avatar">
  125. <img [src]="designer.avatar" [alt]="designer.name">
  126. <div class="status-indicator" [class]="getStatusClass(designer.status)"></div>
  127. </div>
  128. <div class="designer-info">
  129. <h3 class="designer-name">{{ designer.name }}</h3>
  130. <p class="designer-department">{{ designer.department }}</p>
  131. <div class="designer-level">
  132. <span class="level-badge" [class]="'level-' + designer.level">
  133. {{ getLevelText(designer.level) }}
  134. </span>
  135. <span class="status-text" [class]="getStatusClass(designer.status)">
  136. {{ getStatusText(designer.status) }}
  137. </span>
  138. </div>
  139. </div>
  140. <div class="designer-actions">
  141. <button class="action-btn" (click)="viewDesigner(designer)" title="查看详情">
  142. <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor">
  143. <path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z"></path>
  144. <circle cx="12" cy="12" r="3"></circle>
  145. </svg>
  146. </button>
  147. <button class="action-btn" (click)="editDesigner(designer)" title="编辑">
  148. <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor">
  149. <path d="M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7"></path>
  150. <path d="M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z"></path>
  151. </svg>
  152. </button>
  153. <button class="action-btn danger" (click)="deleteDesigner(designer)" title="删除">
  154. <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor">
  155. <polyline points="3 6 5 6 21 6"></polyline>
  156. <path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"></path>
  157. </svg>
  158. </button>
  159. </div>
  160. </div>
  161. <div class="designer-stats">
  162. <div class="stat-item">
  163. <span class="stat-label">项目数量</span>
  164. <span class="stat-value">{{ designer.projectCount }}</span>
  165. </div>
  166. <div class="stat-item">
  167. <span class="stat-label">完成率</span>
  168. <span class="stat-value">{{ designer.completionRate }}%</span>
  169. </div>
  170. <div class="stat-item">
  171. <span class="stat-label">满意度</span>
  172. <span class="stat-value">{{ designer.satisfactionScore }}/5.0</span>
  173. </div>
  174. </div>
  175. <div class="designer-skills">
  176. <span class="skill-tag" *ngFor="let skill of designer.skills">{{ skill }}</span>
  177. </div>
  178. <div class="designer-contact">
  179. <div class="contact-item">
  180. <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor">
  181. <path d="M4 4h16c1.1 0 2 .9 2 2v12c0 1.1-.9 2-2 2H4c-1.1 0-2-.9-2-2V6c0-1.1.9-2 2-2z"></path>
  182. <polyline points="22 6 12 13 2 6"></polyline>
  183. </svg>
  184. <span>{{ designer.email }}</span>
  185. </div>
  186. <div class="contact-item">
  187. <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor">
  188. <path d="M22 16.92v3a2 2 0 0 1-2.18 2 19.79 19.79 0 0 1-8.63-3.07 19.5 19.5 0 0 1-6-6 19.79 19.79 0 0 1-3.07-8.67A2 2 0 0 1 4.11 2h3a2 2 0 0 1 2 1.72 12.84 12.84 0 0 0 .7 2.81 2 2 0 0 1-.45 2.11L8.09 9.91a16 16 0 0 0 6 6l1.27-1.27a2 2 0 0 1 2.11-.45 12.84 12.84 0 0 0 2.81.7A2 2 0 0 1 22 16.92z"></path>
  189. </svg>
  190. <span>{{ designer.phone }}</span>
  191. </div>
  192. </div>
  193. <div class="designer-footer">
  194. <span class="join-date">入职时间:{{ designer.joinDate | date:'yyyy-MM-dd' }}</span>
  195. <span class="last-active">最后活跃:{{ designer.lastActiveDate | date:'MM-dd HH:mm' }}</span>
  196. </div>
  197. </div>
  198. </div>
  199. <!-- 空状态 -->
  200. <div class="empty-state" *ngIf="filteredDesigners.length === 0">
  201. <svg width="64" height="64" viewBox="0 0 24 24" fill="none" stroke="currentColor">
  202. <path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2"></path>
  203. <circle cx="12" cy="7" r="4"></circle>
  204. </svg>
  205. <h3>暂无设计师数据</h3>
  206. <p>没有找到符合条件的设计师,请调整筛选条件或添加新的设计师。</p>
  207. <button class="btn btn-primary" (click)="addDesigner()">
  208. 添加设计师
  209. </button>
  210. </div>
  211. </div>