Record ALL input orders in history, including resolution failures (not_found)
and ERP query misses (erp_not_found). Add ProductionId column to track original
总排号 input. Add 总排号 column and new status styles to the history UI. Fix
empty result caching that prevented retry on transient query failures.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Fix colSpan mismatch: material detail row now correctly spans 9 columns
- Use lazy state initialization for Set/Map useState to avoid re-creation
- Remove data-duplicating refs (batchExecutionsRef, batchOrdersRef, orderMaterialsRef)
and replace with lightweight tracking refs (detailsLoadedRef, loadedMaterialsRef)
- Extract per-batch rendering into BatchItem with React.memo to prevent
sibling re-renders when expanding/collapsing one batch
- Reduce parent component state from 13 to 5 variables
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Backend changes:
- SQL Server dialect: GETDATE() → SYSUTCDATETIME()
- MySQL dialect: NOW() → UTC_TIMESTAMP()
- Ensures OperationTime and EndTime use consistent UTC timezone
Frontend changes:
- formatDateTime: display UTC timestamps in user's local timezone
- Uses getFullYear/getMonth/getDate/getHours (local) instead of UTC methods
Data migration:
- Executed migration script to fix historical OperationTime records
- All existing records now have correct UTC timestamps
- Execution duration now accurate (minutes, not hours)
Impact:
- New executions store UTC timestamps correctly
- UI displays times in user's local timezone (UTC+8 for CN users)
- Historical data corrected via migration
- Time difference between OperationTime and EndTime now accurate
- Add 'Retry' column to order history table
- Show retry count badge with refresh icon
- Display retry success/failure status with visual indicators
- Purple badge for retry count, green/red for success/failure
Remove ReportViewerDialog and ReportAnalysisDialog lazy imports, state
variables, Suspense wrappers, and the "查看报告" toolbar button. These
components were for the old Markdown file-based report viewer which has
been replaced by database-backed operation history.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
When CleanerService hits a fatal error (browser crash, timeout), the
outer catch now sets result.crashed=true. CleanerApplicationService
detects this, closes the dead browser session, re-logs into ERP, and
re-runs all orders once. An execution ID (CLN-yyyyMMddHHmmss-XXXX)
generated at startup ensures report files are deduplicated across
retries. Reports now display execution ID and app version.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Admin can now pass selectedManagers to getCleanerData so material codes
are queried from MaterialsToBeDeleted by ManagerName IN (selectedManagers).
When no managers are selected, fallback to DiscreteMaterialPlanData by
orderNumbers. User behavior is unchanged. Includes updated tests and
role-based flow documentation.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add React ErrorBoundary component that captures rendering errors with
full component stack and logs them to main process via IPC. Wrap all
three App branches (PlaywrightDownload, UnauthenticatedApp,
AuthenticatedApp) with scoped boundaries.
Replace 13 console.* calls across renderer with structured logger:
- useDialogFocus: 10 calls (focus management diagnostics)
- PlaywrightDownloadDialog: 1 call (download cancellation error)
- useReportData: 1 call (report fetch failure)
- parser: 1 call (execution time extraction warning)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace console.error with structured useLogger calls in 5 key renderer
files (Cleaner, LoginDialog, Extractor, OperationHistory, MaterialType)
to enable persistent log capture for frontend error diagnosis.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1. Extract shared module: consolidate getLogDir() and isProduction()
into shared.ts, eliminate duplication across logger modules
2. Make retention config effective: delay file transport creation
until config is loaded, apply appRetention/auditRetention from config.yaml
3. Add before-quit log flush: close logger and audit logger on
app exit to prevent log loss
4. Unify logError entry point: remove duplicate logError from index.ts,
re-export from error-utils.ts with richer error context
5. Renderer log level filtering: add client-side level check in preload
to skip IPC for filtered-out messages
6. Child logger cache + audit cleanup: cache child loggers in IPC
handler for performance, remove redundant timestamp format in audit logger
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
When Admin switches user and the switched user logs out, instead of
showing the login dialog, re-run silent login to detect if the
computer belongs to an Admin user and show user selection dialog.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add Admin-only delete button in operation history modal
- Replace dropdown with multi-select chip filters for Admin users
- Support filtering by multiple usernames using IN clause
- Fix user state propagation by passing currentUser via props
- Change GetBatchesOptions.username to usernames (array)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The database stores time in UTC format, and the UI should display UTC
time without timezone conversion. Use getUTCXxx() methods instead of
getHours() to avoid adding 8-hour timezone offset.
Also extract common datetime formatting logic to reduce code duplication.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add copy buttons in table headers for "总排号" and "订单号" columns
- Copy all non-empty values as newline-separated text
- Show toast notification with copied data count
- Handle clipboard errors gracefully
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
MySQL binary protocol prepared statements (connection.execute()) do not
support ? placeholders in LIMIT/OFFSET clauses, causing "Incorrect
arguments to mysqld_stmt_execute". Embed validated integer values directly
for MySQL while keeping parameterized queries for SQL Server.
Also apply React best practices to ExtractorOperationHistoryModal:
- Hoist formatDateTime to module level
- Wrap async handlers with useCallback for stable effect dependencies
- Import shared types instead of duplicating definitions
- Use ternary for conditional rendering
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add a new operation history feature for the extractor module that tracks
all extraction operations with persistent database storage.
Features:
- Records extraction operations with batch tracking (UUID-based)
- Preserves production ID to order number mapping
- Shows batch statistics (orders, records, success/failure counts)
- Expandable details for each batch showing individual order records
- User-based permission: Admin sees all records, User sees own records only
- Delete functionality with permission validation
Database:
- New ExtractorOperationHistory table schema
- Supports both SQL Server and MySQL
- Indexed on BatchId, UserId, and OperationTime
Files:
- Add DAO class for history operations
- Add IPC handler with permission checks
- Add preload API wrapper
- Add React modal component with expandable batch details
- Integrate history recording into extractor handler
- Add operation history button to ExtractorPage
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Remove all references to 'Guest' user type from the codebase, simplifying the role system to only support 'Admin' and 'User' roles.
Changes:
- Update type definitions to exclude 'Guest' from UserType
- Remove isGuest() method from SessionManager
- Remove Guest-specific logic from update services
- Update all type assertions from 'Admin | User | Guest' to 'Admin | User'
- Remove Guest UI styling from UserSelectionDialog
- Replace Guest fallback with ValidationError in settings handler
Error handling:
- Zod schema now rejects 'Guest' as invalid user type
- TypeScript will fail compilation if 'Guest' is referenced
- Runtime errors occur if database contains Guest users
No database migration needed (confirmed: no Guest users exist)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Break down 948-line monolithic component into 11 focused modules following
Vercel React best practices:
**Module Structure:**
- types.ts: Centralized type definitions and constants
- hooks/: Custom hooks for data management (useReportData, useChartData, useReportFilters)
- components/: Reusable UI components (MetricSelector, ViewModeToggle, UserFilter, ReportChart, Tooltips)
- utils/: Parser and aggregator utility functions
**Key Improvements:**
- Reduced main component from 948 to ~200 lines (79% reduction)
- Separated concerns: data fetching, state management, and UI rendering
- Enhanced reusability and testability of individual components
- Maintained backward compatibility with existing imports
**Additional Fixes:**
- Fixed tooltip displaying duplicate average time values
- Formatted time values to 1 decimal place in both views
- Removed redundant time display from tooltip footer
**Performance Optimizations Applied:**
- Moved tooltip components outside parent component (rerender-no-inline-components)
- Hoisted regex pattern creation outside loops (js-hoist-regexp)
- Used functional setState updates (rerender-functional-setState)
- Memoized expensive computations and callbacks
All changes maintain existing functionality while improving code quality
and maintainability.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Restrict metric selection to single choice in user comparison view
- Auto-keep first selected metric when switching to comparison mode
- Update UI label to show "单选" or "多选" based on view mode
- Improve chart readability by preventing metric overload in comparison mode
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Fix bug where chart displayed accumulated total execution time instead of per-order average. The executionTimeSecs field now correctly shows average time per order (total time / total orders) for proper performance metrics.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Enhanced value extraction with multi-pattern regex approach to handle various markdown table formats. Improved parseDurationToSeconds error handling for edge cases. Added debug logging for failed extractions.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Added a new ReportAnalysisDialog component, accessible from the ReportViewerDialog, strictly for Admin users. It parses execution reports, extracts markdown metrics like processed orders, skipped materials, errors, and execution time, and presents them in an interactive recharts line chart aggregated by day.
Co-authored-by: luwamgere15-crypto <255338376+luwamgere15-crypto@users.noreply.github.com>
Replace native select dropdown with Headless UI Combobox component to enable:
- Search/filter functionality for reports
- Better UX with keyboard navigation
- Improved visual feedback for selected items
- Empty state handling for no matches
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Added a new "View Reports" button to the CleanerPage which opens a new ReportViewerDialog. This dialog lists all available execution reports stored in S3 for the current user, or for all users if the current user is an admin.
The reports are downloaded as Markdown and rendered using react-markdown.
Added three new IPC channels to fetch and download reports using the existing RustfsService and S3Client.
Co-authored-by: luwamgere15-crypto <255338376+luwamgere15-crypto@users.noreply.github.com>
- Add disableBackdropClick prop to Modal component
- Prevent closing ExecutionReportDialog by clicking backdrop during execution
- Complements existing disableEscapeKey behavior for ongoing operations
This prevents users from accidentally interrupting long-running operations by clicking outside the dialog.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Remove setStartTime(null) from finally block to preserve start time for result display
- Add resetStartTime function to useCleaner hook
- Call resetStartTime when execution report dialog closes
- Add useEffect to update timer when execution completes
Now the total elapsed time (总耗时) will be shown in the result dialog after execution completes.
- CleanerPage now uses updateProcessConcurrency instead of setProcessConcurrency
- This ensures slider changes are persisted to config.yaml via IPC
- Remove unused queryBatchSize and setProcessConcurrency from destructuring
- Add *.yaml text eol=lf rule to .gitattributes for consistent line endings
- Format cleaner.ts with Prettier (parameter and chain formatting)
- Format CleanerPage.tsx (JSX formatting)
- Format cleaner.test.ts (array formatting)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Replace local message state with global showSuccess/showError
- Remove inline message display component from SettingsPage
- Center toast notifications for better visibility
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>