| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155 |
- <div class="project-loader">
- <!-- 头部 -->
- <div class="header">
- <h1 class="title">项目管理</h1>
- </div>
- <!-- 加载中状态 -->
- @if (loading) {
- <div class="loading-container">
- <div class="skeleton-loader">
- <!-- 骨架屏动画 -->
- <div class="skeleton-header"></div>
- <div class="skeleton-card"></div>
- <div class="skeleton-card"></div>
- <div class="skeleton-buttons">
- <div></div>
- <div></div>
- </div>
- </div>
- <div class="spinner">
- <div class="spinner-circle"></div>
- </div>
- <p class="loading-message">{{ loadingMessage }}</p>
- </div>
- }
- <!-- 错误状态 -->
- @if (error && !loading) {
- <div class="error-container">
- <div class="error-icon">
- <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512">
- <path d="M256 48C141.31 48 48 141.31 48 256s93.31 208 208 208 208-93.31 208-208S370.69 48 256 48zm0 319.91a20 20 0 1120-20 20 20 0 01-20 20zm21.72-201.15l-5.74 122a16 16 0 01-32 0l-5.74-121.94v-.05a21.74 21.74 0 1143.44 0z"/>
- </svg>
- </div>
- <h2 class="error-title">加载失败</h2>
- <p class="error-message">{{ error }}</p>
- <button class="btn btn-primary" (click)="reload()">
- <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512">
- <path d="M320 146s24.36-12-64-12a160 160 0 10160 160" fill="none" stroke="currentColor" stroke-linecap="round" stroke-miterlimit="10" stroke-width="32"/>
- <path fill="currentColor" d="M256 58l80 80-80 80"/>
- </svg>
- 重新加载
- </button>
- </div>
- }
- <!-- 创建项目引导 -->
- @if (showCreateGuide && !loading && !error) {
- <div class="create-guide-container">
- <!-- 群聊信息卡片 -->
- <div class="card group-info-card">
- <div class="card-header">
- <h3 class="card-title">{{ groupChat?.get('name') }}</h3>
- <p class="card-subtitle">当前群聊暂无关联项目</p>
- </div>
- <div class="card-content">
- <p>您可以为该群聊创建新项目,或选择已有项目关联。</p>
- </div>
- </div>
- <!-- 创建新项目 -->
- <div class="card create-project-card">
- <div class="card-header">
- <h3 class="card-title">
- <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512">
- <path d="M448 256c0-106-86-192-192-192S64 150 64 256s86 192 192 192 192-86 192-192z" fill="none" stroke="currentColor" stroke-miterlimit="10" stroke-width="32"/>
- <path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="32" d="M256 176v160M336 256H176"/>
- </svg>
- 创建新项目
- </h3>
- </div>
- <div class="card-content">
- <div class="form-group">
- <label for="projectName">项目名称</label>
- <input
- id="projectName"
- type="text"
- class="form-input"
- [(ngModel)]="projectName"
- placeholder="输入项目名称"
- [disabled]="creating">
- </div>
- <button
- class="btn btn-primary btn-block"
- (click)="createProject()"
- [disabled]="creating || !projectName.trim()">
- @if (creating) {
- <div class="btn-spinner"></div>
- <span>创建中...</span>
- } @else {
- <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512">
- <path d="M461.81 53.81a4.47 4.47 0 00-3.3-3.39c-54.38-13.3-180 34.09-248.13 102.17a294.9 294.9 0 00-33.09 39.08c-21-1.9-42-.3-59.88 7.5-50.49 22.2-65.18 80.18-69.28 105.07a9 9 0 009.8 10.4l81.07-8.9a180.29 180.29 0 001.1 18.3 18.15 18.15 0 005.3 11.09l31.39 31.39a18.15 18.15 0 0011.1 5.3 179.91 179.91 0 0018.19 1.1l-8.89 81a9 9 0 0010.39 9.79c24.9-4 83-18.69 105.07-69.17 7.8-17.9 9.4-38.79 7.6-59.69a293.91 293.91 0 0039.19-33.09c68.38-68 115.47-190.86 102.37-247.95zM298.66 213.67a42.7 42.7 0 1160.38 0 42.65 42.65 0 01-60.38 0z"/>
- <path d="M109.64 352a45.06 45.06 0 00-26.35 12.84C65.67 382.52 64 448 64 448s65.52-1.67 83.15-19.31A44.73 44.73 0 00160 402.32"/>
- </svg>
- 创建项目
- }
- </button>
- </div>
- </div>
- <!-- 历史项目列表 -->
- @if (historyProjects.length > 0) {
- <div class="card history-projects-card">
- <div class="card-header">
- <h3 class="card-title">
- <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512">
- <path d="M256 64C150 64 64 150 64 256s86 192 192 192 192-86 192-192S362 64 256 64z" fill="none" stroke="currentColor" stroke-miterlimit="10" stroke-width="32"/>
- <path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="32" d="M256 128v144h96"/>
- </svg>
- 群聊相关的历史项目
- </h3>
- <p class="card-subtitle">点击关联到当前群聊</p>
- </div>
- <div class="card-content">
- <div class="list">
- @for (proj of historyProjects; track proj.id) {
- <div class="list-item" (click)="selectHistoryProject(proj)">
- <div class="list-item-content">
- <h4 class="list-item-title">{{ proj.get('title') }}</h4>
- <div class="list-item-meta">
- <span class="badge" [ngClass]="getProjectStatusClass(proj.get('status'))">
- {{ proj.get('status') }}
- </span>
- <span class="list-item-stage">{{ proj.get('currentStage') }}</span>
- </div>
- <p class="list-item-date">
- 创建时间: {{ formatDate(proj.get('createdAt')) }}
- </p>
- </div>
- <div class="list-item-arrow">
- <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512">
- <path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="48" d="M184 112l144 144-144 144"/>
- </svg>
- </div>
- </div>
- }
- </div>
- </div>
- </div>
- }
- <!-- 用户信息底部 -->
- @if (currentUser) {
- <div class="user-info-footer">
- <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512">
- <path d="M258.9 48C141.92 46.42 46.42 141.92 48 258.9c1.56 112.19 92.91 203.54 205.1 205.1 117 1.6 212.48-93.9 210.88-210.88C462.44 140.91 371.09 49.56 258.9 48zM385.32 375.25a4 4 0 01-6.14-.32 124.27 124.27 0 00-32.35-29.59C321.37 329 289.11 320 256 320s-65.37 9-90.83 25.34a124.24 124.24 0 00-32.35 29.58 4 4 0 01-6.14.32A175.32 175.32 0 0180 259c-1.63-97.31 78.22-178.76 175.57-179S432 158.81 432 256a175.32 175.32 0 01-46.68 119.25z"/>
- <path d="M256 144c-19.72 0-37.55 7.39-50.22 20.82s-19 32-17.57 51.93C191.11 256 221.52 288 256 288s64.83-32 67.79-71.24c1.48-19.74-4.8-38.14-17.68-51.82C293.39 151.44 275.59 144 256 144z"/>
- </svg>
- <span>当前用户: {{ getCurrentUserName() }} ({{ getCurrentUserRole() }})</span>
- </div>
- }
- </div>
- }
- </div>
|