import { useEffect, useState } from 'react'; import { motion, AnimatePresence } from 'motion/react'; import { X, MailOpen, Loader2, ArrowLeft } from 'lucide-react'; import { fetchJson } from '../auth/api-client'; interface FeedbackItem { id: number; type: 'dimension' | 'bug' | 'ux' | 'other'; module: string | null; content: string; contact: string | null; screenshots: string[] | string | null; status: 'open' | 'in_progress' | 'done' | 'rejected'; reply_content: string | null; reply_user: string | null; reply_at: string | null; created_at: string; } const TYPE_LABEL: Record = { dimension: '💡 新维度', bug: '🐛 Bug', ux: '🎨 体验', other: '📝 其他', }; const STATUS_LABEL: Record = { open: '待处理', in_progress: '处理中', done: '已完成', rejected: '已忽略', }; const STATUS_STYLE: Record = { open: 'bg-slate-100 text-slate-500', in_progress: 'bg-amber-100 text-amber-600', done: 'bg-emerald-100 text-emerald-600', rejected: 'bg-rose-100 text-rose-500', }; interface Props { open: boolean; onClose: () => void; onBack?: () => void; } function parseScreenshots(s: FeedbackItem['screenshots']): string[] { if (!s) return []; if (Array.isArray(s)) return s; try { return JSON.parse(String(s)); } catch { return []; } } export default function FeedbackHistoryDrawer({ open, onClose, onBack }: Props) { const [items, setItems] = useState(null); const [error, setError] = useState(null); useEffect(() => { if (!open) return; setItems(null); setError(null); fetchJson<{ items: FeedbackItem[] }>('/api/feedback/mine') .then(d => setItems(d.items)) .catch(e => setError(e instanceof Error ? e.message : String(e))); }, [open]); return ( {open && ( e.stopPropagation()} >
{onBack && ( )}
我的反馈
查看进展与回复
{error ? (
{error}
) : items === null ? (
加载中…
) : items.length === 0 ? (
还没有提过反馈
) : (
{items.map(it => { const shots = parseScreenshots(it.screenshots); return (
{TYPE_LABEL[it.type] || it.type} {STATUS_LABEL[it.status]} {(it.created_at || '').replace('T', ' ').slice(0, 16)}
{it.content}
{shots.length > 0 && (
{shots.map((url, i) => ( ))}
)} {it.reply_content && (
{it.reply_user || '产品同学'} 回复 {it.reply_at && {(it.reply_at || '').replace('T', ' ').slice(0, 16)}}
{it.reply_content}
)}
); })}
)}
)} ); }