155 lines
6.3 KiB
TypeScript
155 lines
6.3 KiB
TypeScript
import React, { useState } from 'react';
|
||
import { invoke } from '@tauri-apps/api/core';
|
||
import { Database, RefreshCw, AlertTriangle, CheckCircle, XCircle } from 'lucide-react';
|
||
|
||
/**
|
||
* 数据库调试面板组件
|
||
* 用于诊断和解决数据库连接问题
|
||
*/
|
||
export const DatabaseDebugPanel: React.FC = () => {
|
||
const [connectionStatus, setConnectionStatus] = useState<string>('');
|
||
const [isChecking, setIsChecking] = useState(false);
|
||
const [isReleasing, setIsReleasing] = useState(false);
|
||
const [lastCheckTime, setLastCheckTime] = useState<string>('');
|
||
|
||
// 检查数据库连接状态
|
||
const checkConnection = async () => {
|
||
setIsChecking(true);
|
||
try {
|
||
const status = await invoke<string>('check_database_connection');
|
||
setConnectionStatus(status);
|
||
setLastCheckTime(new Date().toLocaleTimeString());
|
||
} catch (error) {
|
||
setConnectionStatus(`检查失败: ${error}`);
|
||
} finally {
|
||
setIsChecking(false);
|
||
}
|
||
};
|
||
|
||
// 强制释放数据库连接
|
||
const forceReleaseConnection = async () => {
|
||
setIsReleasing(true);
|
||
try {
|
||
const result = await invoke<string>('force_release_database_connection');
|
||
setConnectionStatus(result);
|
||
setLastCheckTime(new Date().toLocaleTimeString());
|
||
} catch (error) {
|
||
setConnectionStatus(`释放失败: ${error}`);
|
||
} finally {
|
||
setIsReleasing(false);
|
||
}
|
||
};
|
||
|
||
// 获取状态图标
|
||
const getStatusIcon = () => {
|
||
if (connectionStatus.includes('可用')) {
|
||
return <CheckCircle className="w-5 h-5 text-green-500" />;
|
||
} else if (connectionStatus.includes('被占用')) {
|
||
return <AlertTriangle className="w-5 h-5 text-yellow-500" />;
|
||
} else if (connectionStatus.includes('损坏') || connectionStatus.includes('失败')) {
|
||
return <XCircle className="w-5 h-5 text-red-500" />;
|
||
}
|
||
return <Database className="w-5 h-5 text-gray-500" />;
|
||
};
|
||
|
||
// 获取状态颜色
|
||
const getStatusColor = () => {
|
||
if (connectionStatus.includes('可用')) {
|
||
return 'text-green-700 bg-green-50 border-green-200';
|
||
} else if (connectionStatus.includes('被占用')) {
|
||
return 'text-yellow-700 bg-yellow-50 border-yellow-200';
|
||
} else if (connectionStatus.includes('损坏') || connectionStatus.includes('失败')) {
|
||
return 'text-red-700 bg-red-50 border-red-200';
|
||
}
|
||
return 'text-gray-700 bg-gray-50 border-gray-200';
|
||
};
|
||
|
||
return (
|
||
<div className="p-6 bg-white rounded-lg shadow-sm border border-gray-200">
|
||
<div className="flex items-center space-x-3 mb-6">
|
||
<Database className="w-6 h-6 text-blue-600" />
|
||
<h3 className="text-lg font-semibold text-gray-900">数据库连接诊断</h3>
|
||
</div>
|
||
|
||
{/* 连接状态显示 */}
|
||
<div className="mb-6">
|
||
<div className="flex items-center justify-between mb-3">
|
||
<span className="text-sm font-medium text-gray-700">连接状态</span>
|
||
{lastCheckTime && (
|
||
<span className="text-xs text-gray-500">
|
||
最后检查: {lastCheckTime}
|
||
</span>
|
||
)}
|
||
</div>
|
||
|
||
{connectionStatus ? (
|
||
<div className={`flex items-center space-x-3 p-3 rounded-lg border ${getStatusColor()}`}>
|
||
{getStatusIcon()}
|
||
<span className="text-sm font-medium">{connectionStatus}</span>
|
||
</div>
|
||
) : (
|
||
<div className="flex items-center space-x-3 p-3 rounded-lg border border-gray-200 bg-gray-50">
|
||
<Database className="w-5 h-5 text-gray-400" />
|
||
<span className="text-sm text-gray-600">点击检查按钮获取连接状态</span>
|
||
</div>
|
||
)}
|
||
</div>
|
||
|
||
{/* 操作按钮 */}
|
||
<div className="space-y-3">
|
||
<button
|
||
onClick={checkConnection}
|
||
disabled={isChecking}
|
||
className="w-full flex items-center justify-center space-x-2 px-4 py-2 bg-blue-600 text-white rounded-lg hover:bg-blue-700 disabled:opacity-50 disabled:cursor-not-allowed transition-colors"
|
||
>
|
||
<RefreshCw className={`w-4 h-4 ${isChecking ? 'animate-spin' : ''}`} />
|
||
<span>{isChecking ? '检查中...' : '检查连接状态'}</span>
|
||
</button>
|
||
|
||
<button
|
||
onClick={forceReleaseConnection}
|
||
disabled={isReleasing}
|
||
className="w-full flex items-center justify-center space-x-2 px-4 py-2 bg-red-600 text-white rounded-lg hover:bg-red-700 disabled:opacity-50 disabled:cursor-not-allowed transition-colors"
|
||
>
|
||
<XCircle className={`w-4 h-4 ${isReleasing ? 'animate-spin' : ''}`} />
|
||
<span>{isReleasing ? '释放中...' : '强制释放连接'}</span>
|
||
</button>
|
||
</div>
|
||
|
||
{/* 使用说明 */}
|
||
<div className="mt-6 p-4 bg-blue-50 border border-blue-200 rounded-lg">
|
||
<h4 className="text-sm font-medium text-blue-900 mb-2">使用说明</h4>
|
||
<ul className="text-xs text-blue-800 space-y-1">
|
||
<li>• <strong>连接可用</strong>: 数据库连接正常,可以执行操作</li>
|
||
<li>• <strong>连接被占用</strong>: 其他操作正在使用连接,请稍等</li>
|
||
<li>• <strong>连接已损坏</strong>: 连接出现问题,需要强制释放</li>
|
||
<li>• <strong>强制释放</strong>: 紧急情况下使用,可能导致数据不一致</li>
|
||
</ul>
|
||
</div>
|
||
|
||
{/* 故障排除建议 */}
|
||
{connectionStatus.includes('被占用') && (
|
||
<div className="mt-4 p-4 bg-yellow-50 border border-yellow-200 rounded-lg">
|
||
<h4 className="text-sm font-medium text-yellow-900 mb-2">故障排除建议</h4>
|
||
<ul className="text-xs text-yellow-800 space-y-1">
|
||
<li>1. 等待当前操作完成(通常几秒钟)</li>
|
||
<li>2. 检查是否有长时间运行的导入或分析任务</li>
|
||
<li>3. 如果问题持续,可以尝试强制释放连接</li>
|
||
</ul>
|
||
</div>
|
||
)}
|
||
|
||
{connectionStatus.includes('损坏') && (
|
||
<div className="mt-4 p-4 bg-red-50 border border-red-200 rounded-lg">
|
||
<h4 className="text-sm font-medium text-red-900 mb-2">紧急处理</h4>
|
||
<ul className="text-xs text-red-800 space-y-1">
|
||
<li>1. 立即点击"强制释放连接"按钮</li>
|
||
<li>2. 重新启动应用程序</li>
|
||
<li>3. 如果问题持续,请联系技术支持</li>
|
||
</ul>
|
||
</div>
|
||
)}
|
||
</div>
|
||
);
|
||
};
|