fix: 统一按钮样式

This commit is contained in:
imeepos
2025-07-14 22:12:39 +08:00
parent 2d88274c3a
commit 49c5b1a033
6 changed files with 142 additions and 136 deletions

View File

@@ -2,7 +2,6 @@ import React, { useState } from 'react';
import { X, FolderOpen, AlertCircle, CheckCircle, Settings } from 'lucide-react';
import { BatchImportRequest } from '../../types/template';
import { CustomSelect } from '../CustomSelect';
import { useProjectStore } from '../../store/projectStore';
import { invoke } from '@tauri-apps/api/core';
interface BatchImportModalProps {
@@ -26,8 +25,6 @@ export const BatchImportModal: React.FC<BatchImportModalProps> = ({
const [errors, setErrors] = useState<Record<string, string>>({});
const [showAdvanced, setShowAdvanced] = useState(false);
const { projects } = useProjectStore();
// 处理文件夹选择
const handleFolderSelect = async () => {
try {
@@ -77,13 +74,6 @@ export const BatchImportModal: React.FC<BatchImportModalProps> = ({
}
};
const projectOptions = [
{ value: '', label: '不关联项目' },
...projects.map(project => ({
value: project.id,
label: project.name,
})),
];
const concurrentOptions = [
{ value: `1`, label: '1 个(慢速)' },
@@ -164,20 +154,6 @@ export const BatchImportModal: React.FC<BatchImportModalProps> = ({
)}
</div>
{/* 关联项目 */}
<div className="mb-6">
<label className="block text-sm font-medium text-gray-700 mb-2">
</label>
<CustomSelect
value={formData.project_id || ''}
onChange={(value) => setFormData(prev => ({ ...prev, project_id: value }))}
options={projectOptions}
placeholder="选择项目(可选)"
className="w-full"
/>
</div>
{/* 自动上传选项 */}
<div className="mb-6">
<label className="flex items-center">

View File

@@ -16,6 +16,7 @@ export const ImportProgressModal: React.FC<ImportProgressModalProps> = ({
}) => {
const [progress, setProgress] = useState<ImportProgress | null>(null);
const [lastValidProgress, setLastValidProgress] = useState<ImportProgress | null>(null);
const [hasCompleted, setHasCompleted] = useState(false);
const { getImportProgress } = useTemplateStore();
useEffect(() => {
@@ -35,10 +36,17 @@ export const ImportProgressModal: React.FC<ImportProgressModalProps> = ({
setLastValidProgress(progressData);
}
// 如果进度数据为空(已被清除),说明导入完成,停止轮询
if (!progressData) {
// 使用最后一次有效的进度数据,但更新状态为完成
if (lastValidProgress) {
// 检查是否导入完成
const isCompleted = !progressData ||
progressData.status === ImportStatus.Completed ||
progressData.status === ImportStatus.Failed;
if (isCompleted && !hasCompleted) {
// 标记为已完成,避免重复处理
setHasCompleted(true);
// 如果进度数据为空但有最后有效进度,使用它
if (!progressData && lastValidProgress) {
const completedProgress: ImportProgress = {
...lastValidProgress,
status: ImportStatus.Completed,
@@ -54,36 +62,20 @@ export const ImportProgressModal: React.FC<ImportProgressModalProps> = ({
interval = null;
}
// 触发完成回调
if (onComplete) {
// 立即触发完成回调,然后延迟关闭弹窗
if (onComplete && (progressData?.status === ImportStatus.Completed || !progressData)) {
// 立即刷新列表
onComplete();
// 延迟关闭弹窗,让用户看到完成状态
setTimeout(() => {
if (isMounted) {
onComplete();
onClose();
}
}, 2000); // 2秒后自动关闭
}, 2000);
}
return;
}
// 如果进度状态为完成或失败,也停止轮询
if (progressData.status === ImportStatus.Completed ||
progressData.status === ImportStatus.Failed) {
// 清除轮询
if (interval) {
clearInterval(interval);
interval = null;
}
if (progressData.status === ImportStatus.Completed && onComplete) {
setTimeout(() => {
if (isMounted) {
onComplete();
}
}, 2000); // 2秒后自动关闭
}
return; // 重要:完成后直接返回,不再继续轮询
}
} catch (error) {
console.error('获取导入进度失败:', error);
// 如果出错,也停止轮询

View File

@@ -1,9 +1,7 @@
import React, { useState } from 'react';
import { X, Upload, File, AlertCircle, CheckCircle } from 'lucide-react';
import { X, Upload, AlertCircle, CheckCircle } from 'lucide-react';
import { invoke } from '@tauri-apps/api/core';
import { ImportTemplateRequest } from '../../types/template';
import { CustomSelect } from '../CustomSelect';
import { useProjectStore } from '../../store/projectStore';
interface ImportTemplateModalProps {
onClose: () => void;
@@ -26,7 +24,6 @@ export const ImportTemplateModal: React.FC<ImportTemplateModalProps> = ({
const [selectedFile, setSelectedFile] = useState<string>('');
const [errors, setErrors] = useState<Record<string, string>>({});
const { projects } = useProjectStore();
// 处理文件选择
const handleFileSelect = async () => {
@@ -114,14 +111,6 @@ export const ImportTemplateModal: React.FC<ImportTemplateModalProps> = ({
}
};
const projectOptions = [
{ value: '', label: '不关联项目' },
...projects.map(project => ({
value: project.id,
label: project.name,
})),
];
return (
<div className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50">
<div className="bg-white rounded-lg shadow-xl w-full max-w-md mx-4">
@@ -155,6 +144,7 @@ export const ImportTemplateModal: React.FC<ImportTemplateModalProps> = ({
onDragOver={handleDragOver}
onDragLeave={handleDragLeave}
onDrop={handleDrop}
onClick={handleFileSelect}
>
{selectedFile ? (
<div className="flex items-center justify-center">
@@ -179,15 +169,6 @@ export const ImportTemplateModal: React.FC<ImportTemplateModalProps> = ({
</div>
</>
)}
<button
type="button"
onClick={handleFileSelect}
className="inline-flex items-center px-4 py-2 border border-gray-300 rounded-md text-sm font-medium text-gray-700 bg-white hover:bg-gray-50 transition-colors"
>
<File className="w-4 h-4 mr-2" />
</button>
</div>
{errors.file_path && (
@@ -220,20 +201,6 @@ export const ImportTemplateModal: React.FC<ImportTemplateModalProps> = ({
)}
</div>
{/* 关联项目 */}
<div className="mb-6">
<label className="block text-sm font-medium text-gray-700 mb-2">
</label>
<CustomSelect
value={formData.project_id || ''}
onChange={(value) => setFormData(prev => ({ ...prev, project_id: value }))}
options={projectOptions}
placeholder="选择项目(可选)"
className="w-full"
/>
</div>
{/* 自动上传选项 */}
<div className="mb-6">
<label className="flex items-center">

View File

@@ -1,6 +1,7 @@
import React, { useState, useEffect } from 'react';
import { Activity, Database, Clock, TrendingUp, RefreshCw, Trash2 } from 'lucide-react';
import { invoke } from '@tauri-apps/api/core';
import { DeleteConfirmDialog } from '../DeleteConfirmDialog';
interface PerformanceStats {
template_import?: {
@@ -42,6 +43,8 @@ export const PerformanceMonitor: React.FC<PerformanceMonitorProps> = ({ onClose
const [performanceStats, setPerformanceStats] = useState<PerformanceStats>({});
const [cacheStats, setCacheStats] = useState<CacheStats | null>(null);
const [loading, setLoading] = useState(true);
const [showDeleteConfirm, setShowDeleteConfirm] = useState(false);
const [deleting, setDeleting] = useState(false);
const [refreshing, setRefreshing] = useState(false);
// 加载性能数据
@@ -66,17 +69,29 @@ export const PerformanceMonitor: React.FC<PerformanceMonitorProps> = ({ onClose
};
// 清理性能数据
const handleCleanupData = async () => {
if (window.confirm('确定要清理7天前的性能数据吗')) {
try {
await invoke('cleanup_template_performance_data', { olderThanHours: 24 * 7 });
await loadPerformanceData();
} catch (error) {
console.error('清理性能数据失败:', error);
}
const handleCleanupData = () => {
setShowDeleteConfirm(true);
};
// 确认清理性能数据
const confirmCleanupData = async () => {
try {
setDeleting(true);
await invoke('cleanup_template_performance_data', { olderThanHours: 24 * 7 });
await loadPerformanceData();
setShowDeleteConfirm(false);
} catch (error) {
console.error('清理性能数据失败:', error);
} finally {
setDeleting(false);
}
};
// 取消清理
const cancelCleanupData = () => {
setShowDeleteConfirm(false);
};
// 预热缓存
const handleWarmCache = async () => {
try {
@@ -346,6 +361,15 @@ export const PerformanceMonitor: React.FC<PerformanceMonitorProps> = ({ onClose
)}
</div>
</div>
<DeleteConfirmDialog
isOpen={showDeleteConfirm}
title="清理性能数据"
message="确定要清理7天前的性能数据吗此操作不可撤销。"
deleting={deleting}
onConfirm={confirmCleanupData}
onCancel={cancelCleanupData}
/>
</div>
);
};