feat: 附件管理拆为独立tab + 员工端附件上传
管理端: - 花名册详情新增「附件资料」独立tab(人事信息分组下) - 从 BasicInfo 移除附件管理代码到独立 AttachmentsTab 组件 - shared.ts 添加 attachments tab 类型和计数映射 员工端: - 后端新增 GET/POST/DELETE /portal/attachments 接口 - 前端 api-services 添加 portalDelete + 附件 API 方法 - MyProfile 新增附件资料卡片,支持上传/查看/删除附件 - 附件类型:身份证/银行卡/学历证书/职业资格证书/合同/照片/其他
This commit is contained in:
@@ -563,52 +563,6 @@ export default function BasicInfo({ profile, employeeId, attachments }: { profil
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* 附件管理 */}
|
||||
<div className="mt-4 pt-4 border-t">
|
||||
<div className="flex items-center justify-between mb-3">
|
||||
<h3 className="text-xs font-medium text-gray-600">附件管理({attachments?.length || 0}个)</h3>
|
||||
{!editing && (
|
||||
<div className="flex gap-2 items-center">
|
||||
<Select value={fileType} onChange={(e) => setFileType(e.target.value as any)} className="text-xs !w-28">
|
||||
<option value="ID_CARD">身份证</option><option value="BANK_CARD">银行卡</option><option value="EDUCATION">学历证书</option><option value="CERTIFICATE">职业资格证书</option><option value="CONTRACT">合同扫描件</option><option value="PHOTO">员工照片</option><option value="OTHER">其他</option>
|
||||
</Select>
|
||||
<input ref={fileInputRef} type="file" className="hidden" onChange={handleFileUpload} />
|
||||
<Button size="sm" variant="secondary" onClick={() => fileInputRef.current?.click()} disabled={addAttachmentMutation.isPending} className="shrink-0 whitespace-nowrap">
|
||||
{addAttachmentMutation.isPending ? '上传中...' : '上传附件'}
|
||||
</Button>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
{!editing && attachments?.length ? (
|
||||
<div className="space-y-1.5">
|
||||
{attachments.map((att) => (
|
||||
<div key={att.id} className="flex items-center justify-between bg-gray-50 rounded p-2 text-xs hover:bg-gray-100">
|
||||
<div className="flex items-center gap-2 min-w-0">
|
||||
<Paperclip className="w-3.5 h-3.5 text-gray-400 shrink-0" />
|
||||
<div className="min-w-0">
|
||||
<div className="truncate font-medium text-gray-700">{att.fileName}</div>
|
||||
<div className="flex items-center gap-2 mt-0.5">
|
||||
<span className={`px-1.5 py-0.5 rounded text-xs ${fileTypeColors[att.fileType] || 'bg-gray-100 text-gray-500'}`}>{fileTypeLabels[att.fileType] || att.fileType}</span>
|
||||
<span className="text-gray-400">{formatSize(att.fileSize)}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex items-center gap-1.5 shrink-0 ml-2">
|
||||
<button onClick={() => window.open(att.fileUrl, '_blank')} className="text-gray-400 hover:text-blue-600" title="查看">
|
||||
<Eye className="w-3.5 h-3.5" />
|
||||
</button>
|
||||
<a href={att.fileUrl} download={att.fileName} className="text-gray-400 hover:text-blue-600" title="下载">
|
||||
<Download className="w-3.5 h-3.5" />
|
||||
</a>
|
||||
<button onClick={() => deleteAttachmentMutation.mutate(att.id)} className="text-gray-300 hover:text-danger" title="删除">
|
||||
<Trash2 className="w-3.5 h-3.5" />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
) : !editing ? <div className="text-gray-400 text-xs text-center py-3">暂无附件</div> : null}
|
||||
</div>
|
||||
</Card>
|
||||
)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user