133 lines
4.4 KiB
TypeScript
133 lines
4.4 KiB
TypeScript
import React from 'react'
|
|
import type { DebugInfo } from '../types'
|
|
|
|
interface DebugDialogProps {
|
|
isOpen: boolean
|
|
debugInfo: DebugInfo | null
|
|
onClose: () => void
|
|
}
|
|
|
|
export const DebugDialog: React.FC<DebugDialogProps> = ({
|
|
isOpen,
|
|
debugInfo,
|
|
onClose
|
|
}) => {
|
|
if (!isOpen || !debugInfo) return null
|
|
|
|
return (
|
|
<div
|
|
className="fixed inset-0 bg-black/50 flex items-center justify-center z-50"
|
|
onClick={onClose}
|
|
>
|
|
<div
|
|
className="bg-white dark:bg-gray-800 rounded-lg shadow-xl max-w-3xl w-full mx-4 max-h-[85vh] overflow-hidden"
|
|
onClick={e => e.stopPropagation()}
|
|
>
|
|
<div className="flex items-center justify-between px-4 py-3 border-b border-gray-200 dark:border-gray-700">
|
|
<h2 className="text-lg font-medium text-gray-800 dark:text-gray-200">调试信息</h2>
|
|
<button
|
|
onClick={onClose}
|
|
className="p-1 hover:bg-gray-200 dark:hover:bg-gray-700 rounded transition-colors text-gray-500"
|
|
>
|
|
✕
|
|
</button>
|
|
</div>
|
|
<div className="p-4 overflow-y-auto max-h-[calc(85vh-60px)]">
|
|
{debugInfo.error ? (
|
|
<div className="text-red-500">{debugInfo.error}</div>
|
|
) : (
|
|
<div className="space-y-4 text-sm">
|
|
<InfoGrid debugInfo={debugInfo} />
|
|
<ImagePreview debugInfo={debugInfo} />
|
|
<TocInfo toc={debugInfo.toc} />
|
|
<UrlInfo url={debugInfo.url} />
|
|
<DomInfo domInfo={debugInfo.domInfo} />
|
|
</div>
|
|
)}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
)
|
|
}
|
|
|
|
const InfoGrid: React.FC<{ debugInfo: DebugInfo }> = ({ debugInfo }) => (
|
|
<div className="grid grid-cols-2 gap-4">
|
|
<InfoItem label="书名" value={debugInfo.bookTitle} />
|
|
<InfoItem label="作者" value={debugInfo.author} />
|
|
<InfoItem label="章节标题" value={debugInfo.chapterTitle} />
|
|
<InfoItem label="书籍状态" value={debugInfo.bookStatus} />
|
|
<InfoItem label="阅读时间" value={debugInfo.readingTime} />
|
|
<InfoItem label="评分" value={debugInfo.rating} />
|
|
<InfoItem label="当前页面" value={debugInfo.currentPage} isSmall />
|
|
<InfoItem label="选中文字" value={debugInfo.selectedText} />
|
|
</div>
|
|
)
|
|
|
|
const InfoItem: React.FC<{
|
|
label: string
|
|
value: string | null
|
|
isSmall?: boolean
|
|
}> = ({ label, value, isSmall }) => (
|
|
<div>
|
|
<div className="font-medium text-gray-700 dark:text-gray-300 mb-1">{label}</div>
|
|
<div className={`bg-gray-100 dark:bg-gray-900 p-2 rounded text-gray-800 dark:text-gray-200 ${isSmall ? 'text-xs' : ''}`}>
|
|
{value || '(未检测到)'}
|
|
</div>
|
|
</div>
|
|
)
|
|
|
|
const ImagePreview: React.FC<{ debugInfo: DebugInfo }> = ({ debugInfo }) => {
|
|
if (!debugInfo.bookCover && !debugInfo.userAvatar) return null
|
|
|
|
return (
|
|
<div>
|
|
<div className="font-medium text-gray-700 dark:text-gray-300 mb-2">图片</div>
|
|
<div className="flex gap-4">
|
|
{debugInfo.bookCover && (
|
|
<div>
|
|
<div className="text-xs text-gray-500 mb-1">书籍封面</div>
|
|
<img src={debugInfo.bookCover} alt="cover" className="w-16 h-20 object-cover rounded" />
|
|
</div>
|
|
)}
|
|
{debugInfo.userAvatar && (
|
|
<div>
|
|
<div className="text-xs text-gray-500 mb-1">用户头像</div>
|
|
<img src={debugInfo.userAvatar} alt="avatar" className="w-12 h-12 rounded-full" />
|
|
</div>
|
|
)}
|
|
</div>
|
|
</div>
|
|
)
|
|
}
|
|
|
|
const TocInfo: React.FC<{ toc: string | null }> = ({ toc }) => {
|
|
if (!toc) return null
|
|
|
|
return (
|
|
<div>
|
|
<div className="font-medium text-gray-700 dark:text-gray-300 mb-1">目录信息</div>
|
|
<pre className="bg-gray-100 dark:bg-gray-900 p-2 rounded text-gray-800 dark:text-gray-200 overflow-x-auto text-xs max-h-48">
|
|
{toc}
|
|
</pre>
|
|
</div>
|
|
)
|
|
}
|
|
|
|
const UrlInfo: React.FC<{ url: string }> = ({ url }) => (
|
|
<div>
|
|
<div className="font-medium text-gray-700 dark:text-gray-300 mb-1">当前 URL</div>
|
|
<div className="bg-gray-100 dark:bg-gray-900 p-2 rounded text-gray-800 dark:text-gray-200 break-all text-xs">
|
|
{url || '(空)'}
|
|
</div>
|
|
</div>
|
|
)
|
|
|
|
const DomInfo: React.FC<{ domInfo: string | null }> = ({ domInfo }) => (
|
|
<div>
|
|
<div className="font-medium text-gray-700 dark:text-gray-300 mb-1">DOM 结构信息</div>
|
|
<pre className="bg-gray-100 dark:bg-gray-900 p-2 rounded text-gray-800 dark:text-gray-200 overflow-x-auto text-xs max-h-96">
|
|
{domInfo}
|
|
</pre>
|
|
</div>
|
|
)
|