diff --git a/src/renderer/src/components/ExtractorOperationHistoryModal.tsx b/src/renderer/src/components/ExtractorOperationHistoryModal.tsx index 22cea3c..6884f8d 100644 --- a/src/renderer/src/components/ExtractorOperationHistoryModal.tsx +++ b/src/renderer/src/components/ExtractorOperationHistoryModal.tsx @@ -7,6 +7,7 @@ import React, { useState, useEffect, useCallback } from 'react' import { Modal } from './ui/Modal' +import { useLogger } from '../hooks/useLogger' import { RefreshCw, Trash2, @@ -82,6 +83,7 @@ export const ExtractorOperationHistoryModal: React.FC>(new Set()) const [allUsers, setAllUsers] = useState([]) const [selectedUsers, setSelectedUsers] = useState([]) + const logger = useLogger('OperationHistory') const isAdmin = user?.userType === 'Admin' @@ -116,9 +118,11 @@ export const ExtractorOperationHistoryModal: React.FC { @@ -133,10 +137,13 @@ export const ExtractorOperationHistoryModal: React.FC new Map(prev).set(batchId, result.data!)) } } catch (err) { - console.error('Failed to fetch batch details:', err) + logger.error('Failed to fetch batch details', { + error: err instanceof Error ? err.message : String(err), + batchId + }) } }, - [batchDetails] + [batchDetails, logger] ) // Fetch batches when modal opens diff --git a/src/renderer/src/components/LoginDialog.tsx b/src/renderer/src/components/LoginDialog.tsx index 7ce74d6..e01a343 100644 --- a/src/renderer/src/components/LoginDialog.tsx +++ b/src/renderer/src/components/LoginDialog.tsx @@ -9,6 +9,7 @@ import React, { useState, useRef } from 'react' import { Modal } from './ui/Modal' +import { useLogger } from '../hooks/useLogger' interface LoginDialogProps { isOpen: boolean @@ -31,6 +32,7 @@ export const LoginDialog: React.FC = ({ const [errorMessage, setErrorMessage] = useState('') const usernameInputRef = useRef(null) const errorRef = useRef(null) + const logger = useLogger('LoginDialog') // Display error message with aria-live const showError = (message: string): void => { @@ -42,12 +44,14 @@ export const LoginDialog: React.FC = ({ setErrorMessage('') if (!username.trim()) { + logger.warn('Login validation: empty username') showError('请输入用户名') usernameInputRef.current?.focus() return } if (!password.trim()) { + logger.warn('Login validation: empty password') showError('请输入密码') return } @@ -57,8 +61,8 @@ export const LoginDialog: React.FC = ({ setIsLoggingIn(false) if (!success) { + logger.error('Login failed: invalid credentials', { username: username.trim(), computerName }) showError('用户名或密码错误') - setPassword('') } } diff --git a/src/renderer/src/components/MaterialTypeManagementDialog.tsx b/src/renderer/src/components/MaterialTypeManagementDialog.tsx index b2ebafb..2e649b1 100644 --- a/src/renderer/src/components/MaterialTypeManagementDialog.tsx +++ b/src/renderer/src/components/MaterialTypeManagementDialog.tsx @@ -12,6 +12,7 @@ import { Modal } from './ui/Modal' import { showSuccess, showError, showInfo } from '../stores/useAppStore' import { ConfirmDialog } from './ui/ConfirmDialog' import { useConfirmDialog } from './ui/useConfirmDialog' +import { useLogger } from '../hooks/useLogger' interface MaterialTypeRecord { id?: number @@ -48,6 +49,7 @@ export const MaterialTypeManagementDialog: React.FC(null) const [editValue, setEditValue] = useState('') const [selectedRowIndex, setSelectedRowIndex] = useState(null) + const logger = useLogger('MaterialType') const tableRef = useRef(null) const inputRef = useRef(null) @@ -96,11 +98,15 @@ export const MaterialTypeManagementDialog: React.FC { @@ -286,6 +292,12 @@ export const MaterialTypeManagementDialog: React.FC('') @@ -108,11 +111,13 @@ export function useCleaner() { setSelectedManagers(new Set([result.currentUsername])) } } catch (err) { - console.error('Initialization failed:', err) + logger.error('Cleaner page initialization failed', { + error: err instanceof Error ? err.message : String(err) + }) } } initializePage() - }, []) + }, [logger]) // Subscribe to cleaner progress events useEffect(() => { @@ -135,11 +140,13 @@ export function useCleaner() { setProcessConcurrency(result.processConcurrency) } } catch (err) { - console.error('Failed to load cleaner config:', err) + logger.error('Failed to load cleaner config', { + error: err instanceof Error ? err.message : String(err) + }) } } loadCleanerConfig() - }, []) + }, [logger]) useEffect(() => { sessionStorage.setItem('cleaner_dryRun', dryRun.toString()) @@ -155,7 +162,10 @@ export function useCleaner() { try { await window.electron.config.updateCleaner({ processConcurrency: clamped }) } catch (err) { - console.error('Failed to update cleaner config:', err) + logger.error('Failed to update process concurrency', { + error: err instanceof Error ? err.message : String(err), + value: clamped + }) } } diff --git a/src/renderer/src/hooks/useExtractor.ts b/src/renderer/src/hooks/useExtractor.ts index 0389936..a0d93f4 100644 --- a/src/renderer/src/hooks/useExtractor.ts +++ b/src/renderer/src/hooks/useExtractor.ts @@ -1,12 +1,15 @@ import { useEffect } from 'react' import type { LogLevel } from '../stores/extractorStore' import { useExtractorStore } from '../stores/extractorStore' +import { useLogger } from './useLogger' function isLogLevel(value: string): value is LogLevel { return ['info', 'success', 'warning', 'error', 'system'].includes(value) } export function useExtractor() { + const logger = useLogger('Extractor') + const { isRunning, isComplete, @@ -73,6 +76,11 @@ export function useExtractor() { 'success', `提取完成:下载 ${data.downloadedFiles.length} 个文件,共 ${data.recordCount} 条记录` ) + logger.info('Extraction completed', { + downloadedFiles: data.downloadedFiles.length, + recordCount: data.recordCount, + errorCount: data.errors.length + }) if (data.errors.length > 0) { addLog('warning', `存在 ${data.errors.length} 个错误`) // Log each error detail for debugging @@ -83,11 +91,13 @@ export function useExtractor() { } else { setError(response.error || '提取失败') addLog('error', response.error || '提取失败') + logger.error('Extraction failed', { error: response.error }) } } catch (err) { const errMsg = err instanceof Error ? err.message : '发生未知错误' setError(errMsg) addLog('error', errMsg) + logger.error('Extraction exception', { error: errMsg }) } finally { setRunning(false) setProgress(null)