import { useState, useRef } from 'react' import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query' import { toast } from 'sonner' import { Building2, Upload, Trash2, FileText, AlertCircle, Calendar } from 'lucide-react' import { companyFilesApi } from '../lib/api-services' import Card from '../components/ui/Card' import Button from '../components/ui/Button' import { Input, Label, Select } from '../components/ui/Input' import EmptyState from '../components/ui/EmptyState' import PageGuide from '../components/ui/PageGuide' const FILE_TYPES = [ { value: 'BUSINESS_LICENSE', label: '营业执照' }, { value: 'WORK_HOURS', label: '工时备案' }, { value: 'HR_POLICY', label: '制度文件' }, { value: 'LABOR_CONTRACT_TEMPLATE', label: '合同模板' }, { value: 'OTHER', label: '其他' }, ] const fileTypeLabels: Record = Object.fromEntries(FILE_TYPES.map(t => [t.value, t.label])) export default function CompanyFiles() { const queryClient = useQueryClient() const fileInputRef = useRef(null) const [fileType, setFileType] = useState('BUSINESS_LICENSE') const [remark, setRemark] = useState('') const [expiryDate, setExpiryDate] = useState('') const [filterType, setFilterType] = useState('') const { data: files, isLoading } = useQuery({ queryKey: ['company-files', filterType], queryFn: async () => { return await companyFilesApi.list(filterType ? { fileType: filterType } : {}) }, }) const addMutation = useMutation({ mutationFn: (data: any) => companyFilesApi.add(data), onSuccess: () => { queryClient.invalidateQueries({ queryKey: ['company-files'] }) toast.success('文件上传成功') setRemark('') setExpiryDate('') }, onError: () => toast.error('上传失败'), }) const deleteMutation = useMutation({ mutationFn: (id: string) => companyFilesApi.remove(id), onSuccess: () => { queryClient.invalidateQueries({ queryKey: ['company-files'] }) toast.success('已删除') }, }) const handleFileUpload = (e: React.ChangeEvent) => { const file = e.target.files?.[0] if (!file) return if (file.size > 10 * 1024 * 1024) { toast.error('文件不能超过 10MB') return } const reader = new FileReader() reader.onload = () => { addMutation.mutate({ fileName: file.name, fileType, fileUrl: reader.result as string, fileSize: file.size, remark: remark || undefined, expiryDate: expiryDate || undefined, }) } reader.readAsDataURL(file) e.target.value = '' } const fmtSize = (bytes: number) => { if (bytes < 1024) return `${bytes}B` if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)}KB` return `${(bytes / 1024 / 1024).toFixed(1)}MB` } return (
公司文件管理,集中存储和管理公司制度、合同模板、政策文件等。支持分类管理、在线预览、权限控制。关联:员工可在员工端查看已授权的公司文件。

公司备用文件

上传营业执照、工时备案文件、公司制度文件、合同模板等公司级文件
setRemark(e.target.value)} placeholder="如:2024年营业执照" className="w-48" />
setExpiryDate(e.target.value)} className="w-40" />

文件列表

{isLoading ? (
加载中...
) : !files || files.length === 0 ? ( ) : (
{files.map((f: any) => { const isExpired = f.expiryDate && new Date(f.expiryDate) < new Date() const isExpiringSoon = f.expiryDate && !isExpired && (new Date(f.expiryDate).getTime() - new Date().getTime()) < 30 * 24 * 60 * 60 * 1000 return (
{f.fileName} {fileTypeLabels[f.fileType] || f.fileType} {isExpired && 已过期} {isExpiringSoon && 即将到期}
{fmtSize(f.fileSize)} {f.remark && · {f.remark}} {f.expiryDate && · 有效期至 {f.expiryDate.slice(0, 10)}} · {new Date(f.createdAt).toLocaleDateString('zh-CN')}
下载
) })}
)}
) }