import { FC, useState, useEffect } from 'react'; import { X, Lock, Globe, Users, FileText, } from 'lucide-react'; import { DeliverableItem } from '../../types/workbench'; import { RoleDefinition, DocVisibilityRule, VisibilityMode } from '../../types/rbac'; export interface DocVisibilityModalProps { isOpen: boolean; onClose: () => void; doc: DeliverableItem | null; roles: RoleDefinition[]; currentUserName: string; onSaveRule: (docId: string, rule: DocVisibilityRule | undefined) => void; } export const DocVisibilityModal: FC = ({ isOpen, onClose, doc, roles, currentUserName, onSaveRule, }) => { const [mode, setMode] = useState('inherit'); const [selectedRoleIds, setSelectedRoleIds] = useState([]); const [overrideReason, setOverrideReason] = useState(''); // 初始化已有规则 useEffect(() => { if (doc?.visibilityRule) { setMode(doc.visibilityRule.mode); setSelectedRoleIds(doc.visibilityRule.allowedRoleIds || []); setOverrideReason(doc.visibilityRule.overrideReason || ''); } else { setMode('inherit'); setSelectedRoleIds([]); setOverrideReason(''); } }, [doc, isOpen]); useEffect(() => { const handleKeyDown = (e: KeyboardEvent) => { if (e.key === 'Escape' && isOpen) { onClose(); } }; window.addEventListener('keydown', handleKeyDown); return () => window.removeEventListener('keydown', handleKeyDown); }, [isOpen, onClose]); if (!isOpen || !doc) return null; const handleToggleRole = (roleId: string) => { setSelectedRoleIds((prev) => prev.includes(roleId) ? prev.filter((id) => id !== roleId) : [...prev, roleId] ); }; const handleSave = () => { if (mode === 'inherit') { onSaveRule(doc.docId, undefined); onClose(); return; } const rule: DocVisibilityRule = { mode, allowedRoleIds: mode === 'role_whitelist' ? selectedRoleIds : undefined, overrideReason: overrideReason.trim() || '业务主管根据合规与保密要求设置覆盖策略', configuredBy: currentUserName, configuredAt: new Date().toLocaleString(), }; onSaveRule(doc.docId, rule); onClose(); }; const handleResetToInherit = () => { onSaveRule(doc.docId, undefined); onClose(); }; return (
{ if (e.target === e.currentTarget) onClose(); }} >
{/* 顶部标题栏 */}
单文档可见性覆盖策略 (Doc Visibility Override)
设置后将优先于工作流默认可见性规则生效
{/* 主体表单 */}
{/* 目标文档信息卡 */}
{doc.title}
所属阶段: {doc.stage} 编制: {doc.author} 审核: {doc.reviewer} 批准: {doc.approver}
{/* 覆盖模式选择 */}
选择可见性覆盖策略: {/* 模式 1: 继承工作流默认 */} {/* 模式 2: 仅三权责任人可见 */} {/* 模式 3: 指定全局角色白名单 */} {/* 模式 4: 全员公开 */}
{/* 覆盖原因留痕输入 */} {mode !== 'inherit' && (
覆盖原因与合规留痕说明: setOverrideReason(e.target.value)} style={{ padding: '8px 10px', fontSize: '12px', borderRadius: '6px', border: '1px solid var(--border)', backgroundColor: 'var(--bg-panel)', color: 'var(--text-strong)', }} />
)}
{/* 底部操作栏 */}
{doc.visibilityRule && doc.visibilityRule.mode !== 'inherit' ? ( ) : ( 当前状态:继承工作流默认可见性 )}
); };