import { useState } from 'react' import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query' import { toast } from 'sonner' import { FileText, Plus, ChevronRight, CheckCircle, Clock, X } from 'lucide-react' import api from '../lib/api' import Card from '../components/ui/Card' import Button from '../components/ui/Button' import EmptyState from '../components/ui/EmptyState' const STEP_LABELS: Record = { DRAFTING: '起草', DISCUSSION: '讨论', CONSULTATION: '协商', PUBLICATION: '公示', } const STEP_ORDER = ['DRAFTING', 'DISCUSSION', 'CONSULTATION', 'PUBLICATION'] /** * 规章制度民主程序管理页面 */ export default function Policies() { const queryClient = useQueryClient() const [showCreate, setShowCreate] = useState(false) const [selectedPolicy, setSelectedPolicy] = useState(null) const { data: list, isLoading } = useQuery({ queryKey: ['policies'], queryFn: async () => { const res = await api.get('/policies') as any return res.data }, }) const advanceMutation = useMutation({ mutationFn: ({ id, step, note }: { id: string; step: number; note?: string }) => api.post(`/policies/${id}/advance-step`, { step, note }), onSuccess: () => { toast.success('流程步骤已推进') queryClient.invalidateQueries({ queryKey: ['policies'] }) // 刷新选中制度详情 if (selectedPolicy) { api.get(`/policies/${selectedPolicy.id}`).then((res: any) => setSelectedPolicy(res.data)) } }, onError: (err: any) => toast.error(err?.response?.data?.error?.message || '操作失败'), }) return (

规章制度管理

民主程序四步法:起草 → 讨论 → 协商 → 公示

{isLoading ? (
加载中...
) : !list || list.length === 0 ? ( ) : (
{list.map((p: any) => (
setSelectedPolicy(p)}>
{p.title} {p.status === 'PUBLISHED' ? ( 已生效 ) : ( {STEP_LABELS[STEP_ORDER[(p.democracyProgress?.currentStep || 1) - 1]] || '起草中'} )}
{p.content?.slice(0, 80) || '暂无内容'}
{STEP_ORDER.map((step, i) => { const currentStep = p.democracyProgress?.currentStep || 1 const isDone = i < currentStep - 1 || p.status === 'PUBLISHED' const isCurrent = i === currentStep - 1 && p.status !== 'PUBLISHED' return (
{isDone ? : } {STEP_LABELS[step]}
{i < STEP_ORDER.length - 1 && }
) })}
{p.status === 'PUBLISHED' && p.totalEmployees > 0 && (
员工签收:
0 ? Math.round((p.readCount / p.totalEmployees) * 100) : 0}%` }} />
{p.readCount}/{p.totalEmployees}
)}
))}
)} {/* 详情弹窗 */} {selectedPolicy && (
setSelectedPolicy(null)}>
e.stopPropagation()}>

{selectedPolicy.title}

{selectedPolicy.content || '暂无内容'}
民主程序进度
{(selectedPolicy.democracyProgress?.steps || []).map((s: any, i: number) => { const isDone = s.status === 'COMPLETED' || (selectedPolicy.status === 'PUBLISHED') const isCurrent = s.status === 'IN_PROGRESS' && selectedPolicy.status !== 'PUBLISHED' return (
{isDone ? : } {s.name} · {s.description} {isCurrent && ( )}
{s.date && (
{s.status === 'COMPLETED' ? '完成时间' : '开始时间'}:{s.date} {s.note && 备注:{s.note}}
)}
) })}
{/* 阅读签收统计(仅已公示制度显示) */} {selectedPolicy.status === 'PUBLISHED' && ( )}
)} {/* 新建弹窗 */} {showCreate && ( setShowCreate(false)} onSuccess={() => { setShowCreate(false); queryClient.invalidateQueries({ queryKey: ['policies'] }) }} /> )}
) } function CreatePolicyModal({ onClose, onSuccess }: { onClose: () => void; onSuccess: () => void }) { const [title, setTitle] = useState('') const [content, setContent] = useState('') const [type, setType] = useState('RULES') const createMutation = useMutation({ mutationFn: () => api.post('/policies', { title, content, type }), onSuccess: () => { toast.success('制度已创建'); onSuccess() }, onError: (err: any) => toast.error(err?.response?.data?.error?.message || '创建失败'), }) return (
e.stopPropagation()}>

新建规章制度

setTitle(e.target.value)} className="w-full mt-1 px-3 py-2 text-sm border rounded-lg focus:outline-none focus:ring-2 focus:ring-primary" placeholder="如:考勤管理制度" />