| import React from 'react'; |
| import { cn } from '@/lib/utils'; |
| import { AlertTriangle, Info, XCircle } from 'lucide-react'; |
|
|
| |
| |
| |
| |
|
|
| export type IssueSeverity = 'error' | 'warning' | 'info'; |
|
|
| export interface Issue { |
| |
| id: string; |
| |
| severity: IssueSeverity; |
| |
| message: string; |
| |
| source?: string; |
| } |
|
|
| interface IssueListProps { |
| |
| issues: Issue[]; |
| |
| emptyText?: string; |
| |
| className?: string; |
| |
| onIssueClick?: (issue: Issue) => void; |
| } |
|
|
| |
| const severityIcons: Record<IssueSeverity, React.ReactNode> = { |
| error: <XCircle className="w-3.5 h-3.5 text-console-status-error" />, |
| warning: <AlertTriangle className="w-3.5 h-3.5 text-console-status-warning" />, |
| info: <Info className="w-3.5 h-3.5 text-console-status-info" />, |
| }; |
|
|
| |
| const severityBg: Record<IssueSeverity, string> = { |
| error: 'bg-console-status-error-bg', |
| warning: 'bg-console-status-warning-bg', |
| info: 'bg-console-status-info-bg', |
| }; |
|
|
| |
| |
| |
| |
| export function IssueList({ |
| issues, |
| emptyText = '暂无问题', |
| className, |
| onIssueClick, |
| }: IssueListProps) { |
| if (issues.length === 0) { |
| return ( |
| <div className={cn('py-4 text-center text-xs text-console-text-muted', className)}> |
| {emptyText} |
| </div> |
| ); |
| } |
|
|
| return ( |
| <ul className={cn('space-y-1', className)} role="list"> |
| {issues.map((issue) => ( |
| <li |
| key={issue.id} |
| className={cn( |
| 'flex items-start gap-2 px-2 py-1.5 rounded-console-sm text-xs', |
| severityBg[issue.severity], |
| onIssueClick && 'cursor-pointer hover:opacity-80' |
| )} |
| onClick={() => onIssueClick?.(issue)} |
| role={onIssueClick ? 'button' : undefined} |
| tabIndex={onIssueClick ? 0 : undefined} |
| > |
| {/* 图标 */} |
| <span className="mt-0.5 shrink-0" aria-hidden="true"> |
| {severityIcons[issue.severity]} |
| </span> |
| |
| {/* 内容 */} |
| <div className="flex-1 min-w-0"> |
| <span className="text-console-text-primary">{issue.message}</span> |
| {issue.source && ( |
| <span className="ml-1 text-console-text-muted"> |
| ({issue.source}) |
| </span> |
| )} |
| </div> |
| </li> |
| ))} |
| </ul> |
| ); |
| } |
|
|