import React, { useState } from 'react'; import { X, Users, UserPlus, Shield, UserMinus, RotateCcw, LogOut } from 'lucide-react'; import { ProjectInfo, ProjectMember, ProjectMemberRole } from '../../types/workbench'; import { UserProfile } from '../../types/docgov'; interface ProjectMembersModalProps { isOpen: boolean; onClose: () => void; project: ProjectInfo | undefined; currentUser: UserProfile; availableUsers: UserProfile[]; onAddMember: (member: Omit) => void; onUpdateMemberRole: (userId: number, role: ProjectMemberRole) => void; onRemoveMember: (userId: number) => void; // 移出/置为已退出 onRestoreMember: (userId: number) => void; // 重新激活 } export const ProjectMembersModal: React.FC = ({ isOpen, onClose, project, currentUser, availableUsers, onAddMember, onUpdateMemberRole, onRemoveMember, onRestoreMember, }) => { const [showAddForm, setShowAddForm] = useState(false); const [selectedUserId, setSelectedUserId] = useState(''); const [selectedRole, setSelectedRole] = useState('viewer'); if (!isOpen || !project) return null; const isCreator = currentUser.id === project.creatorId; const isAdmin = currentUser.roleId === 'role-admin'; const canManage = isCreator || isAdmin; // 筛选尚未加入该项目的人员 const existingMemberIds = new Set(project.members.map((m) => m.userId)); const unjoinedUsers = availableUsers.filter((u) => !existingMemberIds.has(u.id)); const handleAddSubmit = (e: React.FormEvent) => { e.preventDefault(); if (!selectedUserId) return; const targetUser = availableUsers.find((u) => u.id === selectedUserId); if (!targetUser) return; onAddMember({ userId: targetUser.id, userName: targetUser.name, department: targetUser.department, position: targetUser.position, role: selectedRole, }); setSelectedUserId(''); setSelectedRole('viewer'); setShowAddForm(false); }; const getRoleBadge = (role: ProjectMemberRole) => { switch (role) { case 'creator': return { label: '项目创建人', bg: 'rgba(79, 107, 255, 0.12)', color: '#4f6bff' }; case 'author': return { label: '编制人 (Author)', bg: 'rgba(59, 130, 246, 0.12)', color: '#2563eb' }; case 'reviewer': return { label: '审核人 (Reviewer)', bg: 'rgba(217, 119, 6, 0.12)', color: '#d97706' }; case 'approver': return { label: '批准人 (Approver)', bg: 'rgba(16, 185, 129, 0.12)', color: '#059669' }; default: return { label: '查阅者 (Viewer)', bg: 'rgba(100, 116, 139, 0.12)', color: '#64748b' }; } }; return (
e.stopPropagation()} > {/* 头部 */}

项目成员与职责权限管理

{project.members.filter((m) => m.status === 'active').length} 位在职成员

当前项目:{project.title} (创建人: {project.creatorName})

{/* 主体列表 */}
{/* 管理员/创建者操作提示 */}
{canManage ? '您是该项目的创建人/管理员,有权添加新成员、调整法定职责或移出成员。' : '您是该项目的协同成员,仅可查阅成员名单与职责分配。'}
{canManage && !showAddForm && unjoinedUsers.length > 0 && ( )}
{/* 添加新成员表单 */} {showAddForm && (
)} {/* 成员列表 */}
{project.members.map((member) => { const badge = getRoleBadge(member.role); const isExited = member.status === 'exited'; const isMemberCreator = member.role === 'creator' || member.userId === project.creatorId; return (
{/* 左侧成员信息 */}
{member.userName} {/* 角色徽章 */} {badge.label} {/* 状态标签 */} {isExited ? ( 已退出 ({member.exitedAt || '历史记录留痕'}) ) : ( 在职成员 )}
{member.department || '研发中心'} · {member.position || '研发岗位'} · 加入时间: {member.joinedAt}
{/* 右侧管理操作 */}
{canManage && !isMemberCreator && ( <> {!isExited ? ( <> {/* 修改职责 */} {/* 移出项目 */} ) : ( /* 重新激活恢复 */ )} )} {/* 普通在职成员自主退出项目 */} {!canManage && member.userId === currentUser.id && !isExited && ( )}
); })}
{/* 底部 */}
💡 退出项目说明:退出成员将保留已有聊天记录供审计留痕,但无法再发送对话或查阅受控交付物。
); };