123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209 |
- <!-- 模态框背景 -->
- <div class="modal-overlay"
- *ngIf="isVisible"
- (click)="onBackdropClick($event)">
- <!-- 模态框内容 -->
- <div class="modal-container" (click)="$event.stopPropagation()">
- <!-- 模态框头部 -->
- <div class="modal-header">
- <div class="header-left">
- <h2 class="modal-title">
- <svg class="title-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
- <path d="M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2"></path>
- <circle cx="9" cy="7" r="4"></circle>
- <path d="M23 21v-2a4 4 0 0 0-3-3.87"></path>
- <path d="M16 3.13a4 4 0 0 1 0 7.75"></path>
- </svg>
- 项目成员
- </h2>
- <div class="member-stats">
- <span class="stat-item">
- <span class="stat-number">{{ totalMembers }}</span>
- <span class="stat-label">总成员</span>
- </span>
- <span class="stat-item">
- <span class="stat-number">{{ projectTeamMembers }}</span>
- <span class="stat-label">项目团队</span>
- </span>
- @if (pendingAddMembers > 0) {
- <span class="stat-item stat-pending">
- <span class="stat-number">{{ pendingAddMembers }}</span>
- <span class="stat-label">待加入群聊</span>
- </span>
- }
- </div>
- </div>
- <div class="header-right">
- <!-- 环境指示器 -->
- <div class="environment-indicator">
- @if (isWxworkEnvironment) {
- <span class="env-badge env-wxwork">
- <svg viewBox="0 0 24 24" fill="currentColor" width="16" height="16">
- <path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-1 17.88c0 .53-.21.9-.74.26-.18.07-.36.06-.51.14-.75.21-.13.18-.3.36-.3.75.06.39.12.69.12.75.21.37.12.69.12 1.06 0 .39-.13.7-.12.75-.06-.06-.18-.15-.51-.14-.75-.21-.53-.21-.9-.74-.26-.18-.07-.36-.06-.51-.14-.75-.21-.13-.18-.3-.36-.3-.75.06-.39.12-.69.12-.75-.21-.37-.12-.69-.12-1.06 0-.39.13-.7-.12-.75.06-.06.18-.15.51-.14-.75.21z"/>
- </svg>
- 企业微信环境
- </span>
- } @else {
- <span class="env-badge env-default">
- <svg viewBox="0 0 24 24" fill="currentColor" width="16" height="16">
- <path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 17.88c0 .53-.21.9-.74.26-.18.07-.36.06-.51.14-.75.21-.13.18-.3.36-.3.75.06.39.12.69.12.75.21.37.12.69.12 1.06 0 .39-.13.7-.12.75-.06-.06-.18-.15-.51-.14-.75-.21-.53-.21-.9-.74-.26-.18-.07-.36-.06-.51-.14-.75-.21-.13-.18-.3-.36-.3-.75.06-.39.12-.69.12-.75-.21-.37-.12-.69-.12-1.06 0-.39.13-.7-.12-.75.06-.06.18-.15.51-.14-.75.21z"/>
- </svg>
- 普通环境
- </span>
- }
- </div>
- <!-- 搜索框 -->
- <div class="search-box">
- <svg class="search-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
- <circle cx="11" cy="11" r="8"></circle>
- <path d="m21 21-4.35-4.35"></path>
- </svg>
- <input
- type="text"
- class="search-input"
- placeholder="搜索成员..."
- [(ngModel)]="searchQuery">
- </div>
- <!-- 过滤器 -->
- <select class="filter-select" [(ngModel)]="memberFilter">
- <option value="all">全部成员</option>
- <option value="team">项目团队</option>
- <option value="ingroup">已在群聊</option>
- <option value="pending">待加入群聊</option>
- </select>
- <!-- 关闭按钮 -->
- <button class="close-btn" (click)="onClose()">
- <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
- <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 class="modal-content">
- <!-- 加载状态 -->
- @if (loading) {
- <div class="loading-state">
- <div class="loading-spinner"></div>
- <p>加载成员信息...</p>
- </div>
- } @else if (error) {
- <!-- 错误状态 -->
- <div class="error-state">
- <svg class="error-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
- <circle cx="12" cy="12" r="10"></circle>
- <line x1="15" y1="9" x2="9" y2="15"></line>
- <line x1="9" y1="9" x2="15" y2="15"></line>
- </svg>
- <h3>加载失败</h3>
- <p>{{ error }}</p>
- <button class="retry-btn" (click)="loadMembers()">重试</button>
- </div>
- } @else if (getFilteredMembers().length === 0) {
- <!-- 空状态 -->
- <div class="empty-state">
- <svg class="empty-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
- <path d="M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2"></path>
- <circle cx="9" cy="7" r="4"></circle>
- <path d="M23 21v-2a4 4 0 0 0-3-3.87"></path>
- <path d="M16 3.13a4 4 0 0 1 0 7.75"></path>
- </svg>
- <h3>暂无成员</h3>
- <p>该项目还没有添加任何成员</p>
- </div>
- } @else {
- <!-- 成员列表 -->
- <div class="members-list">
- @for (member of getFilteredMembers(); track member.id) {
- <div class="member-card" [class]="getMemberStatusClass(member)">
- <!-- 成员头像 -->
- <div class="member-avatar">
- @if (member.avatar) {
- <img [src]="member.avatar" [alt]="member.name" class="avatar-image" />
- } @else {
- <div class="avatar-placeholder">
- {{ member.name.charAt(0).toUpperCase() }}
- </div>
- }
- </div>
- <!-- 成员信息 -->
- <div class="member-info">
- <h4 class="member-name">{{ member.name }}</h4>
- <div class="member-meta">
- <span class="member-role">
- <span class="role-badge" [class]="getRoleBadgeClass(member.role)">
- {{ member.role }}
- </span>
- </span>
- @if (member.department) {
- <span class="member-department">{{ member.department }}</span>
- }
- <span class="member-status" [class]="getMemberStatusClass(member)">
- {{ getMemberStatusText(member) }}
- </span>
- </div>
- @if (member.isInProjectTeam && !member.isInGroupChat && isWxworkEnvironment) {
- <div class="add-to-group-hint">
- <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
- <circle cx="12" cy="12" r="10"></circle>
- <line x1="12" y1="8" x2="12" y2="16"></line>
- <path d="M8 12h8"></path>
- </svg>
- <span>点击添加到群聊</span>
- </div>
- }
- </div>
- <!-- 操作按钮 -->
- <div class="member-actions">
- @if (member.isInProjectTeam && !member.isInGroupChat && isWxworkEnvironment) {
- <button
- class="action-btn add-btn"
- (click)="addMemberToGroupChat(member)"
- title="添加到群聊">
- <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
- <circle cx="12" cy="12" r="10"></circle>
- <line x1="12" y1="8" x2="12" y2="16"></line>
- <path d="M8 12h8"></path>
- </svg>
- <span>添加</span>
- </button>
- }
- <div class="status-indicator" [class]="getMemberStatusClass(member)">
- @if (member.isInProjectTeam && member.isInGroupChat) {
- <svg viewBox="0 0 24 24" fill="currentColor">
- <path d="M9 16.17L4.83 12l-1.42 1.41L9 19 21 7.41l-1.41-1.41z"/>
- </svg>
- }
- @else if (member.isInProjectTeam && !member.isInGroupChat) {
- <svg viewBox="0 0 24 24" fill="currentColor">
- <circle cx="12" cy="12" r="10" opacity="0.3"/>
- <path d="M12 8v8"/>
- <path d="M8 12h8"/>
- </svg>
- }
- @else {
- <svg viewBox="0 0 24 24" fill="currentColor">
- <path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15.88c0 .53-.21.9-.74.26-.18.07-.36.06-.51.14-.75.21-.13.18-.3.36-.3.75.06.39.12.69.12.75.21.37.12.69.12 1.06 0 .39-.13.7-.12.75-.06-.06-.18-.15-.51-.14-.75-.21-.53-.21-.9-.74-.26-.18-.07-.36-.06-.51-.14-.75-.21-.13-.18-.3-.36-.3-.75.06-.39.12-.69.12-.75-.21-.37-.12-.69-.12-1.06 0-.39.13-.7-.12-.75.06-.06.18-.15.51-.14-.75.21z"/>
- </svg>
- }
- </div>
- </div>
- </div>
- }
- </div>
- }
- </div>
- </div>
- </div>
|