Commit Graph

98 Commits

Author SHA1 Message Date
Misaka_Company
e1d55b8b39 feat(cleaner): add outer-level retry on fatal crash with execution ID
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>
2026-04-13 10:07:29 +08:00
Misaka
8b173890fa feat(cleaner): add multi-signal deletion verification with material-level retry
Replace fragile single-signal (row change only) deletion verification
with a robust multi-signal approach using row change + material count +
ERP message detection. Add material-level retry (up to 3 attempts) for
transient failures, with detailed tracking of failed/uncertain deletions.

- Add DeletionOutcome/DeletionErrorCategory enums and FailedMaterial type
- Add deleteWithVerification() core method with retry logic
- Add evaluateDeletionSignals() pure logic (unit tested, 9 cases)
- Add helper methods: readMaterialCount, checkErpMessages, handleConfirmDialog
- Extend CleanerResult/OrderCleanDetail with failed/uncertain tracking
- Update report generator with failed materials detail section
- Update ExecutionReportDialog to display failed/uncertain stats

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-07 21:55:47 +08:00
Misaka
3be7959067 feat(cleaner): support selectedManagers filtering for admin cleaner execution
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>
2026-04-06 19:20:22 +08:00
Misaka
3d5adb74d8 feat(logging-p0): add ErrorBoundary and replace remaining console.* with logger
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>
2026-04-04 17:11:59 +08:00
Misaka
219d8ab752 feat(logging-p0): add useLogger to renderer critical path components
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>
2026-04-04 12:46:41 +08:00
Misaka
883f98065a refactor(logger): optimize logging architecture with 6 improvements
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>
2026-04-03 20:53:53 +08:00
Misaka_Company
020bbcdccc fix(auth): retry silent login after logout to show user selection for Admin
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>
2026-04-01 16:28:26 +08:00
Misaka_Company
c8ab58d390 feat(history): add Admin-only delete button and multi-user filter with chips
- 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>
2026-04-01 15:17:20 +08:00
Misaka_Company
348b02600d fix(time): use UTC methods for operation history display
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>
2026-04-01 13:54:26 +08:00
Misaka_Company
d004f8e9f8 feat(history): add one-click copy for production IDs and order numbers
- 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>
2026-04-01 10:00:31 +08:00
Misaka
17fbd7d251 fix(extractor): resolve MySQL LIMIT placeholder error in operation history query
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>
2026-03-31 19:42:44 +08:00
Misaka_Company
557ed174c3 feat(extractor): add operation history tracking
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>
2026-03-31 15:22:53 +08:00
Misaka_Company
491f2afe3f refactor(auth): remove Guest role from user type system
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>
2026-03-26 12:50:18 +08:00
Misaka_Company
4a1a78ee14 refactor(ui): restructure ReportAnalysisDialog into modular architecture
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>
2026-03-26 12:14:35 +08:00
Misaka_Company
43e6d1f4b4 feat(ui): add single-select mode for metrics in comparison view
- 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>
2026-03-26 10:35:35 +08:00
Misaka_Company
5ff5e5d18b fix(ui): correct per-order execution time calculation in report analysis
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>
2026-03-26 10:32:41 +08:00
Misaka_Company
18a81ae030 fix(ui): improve execution time extraction in report analysis dialog
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>
2026-03-26 09:47:25 +08:00
google-labs-jules[bot]
5178a2425a feat(ui): add report analysis feature for admin
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>
2026-03-25 10:47:32 +00:00
Misaka_Company
2adfc77a58 fix: correct progress speed and ETA display logic 2026-03-24 17:26:18 +08:00
Misaka_Company
2343fb2188 fix: re-trigger authentication after Playwright download completes 2026-03-24 17:16:04 +08:00
Misaka_Company
fbd62fe390 feat: integrate Playwright download dialog into startup flow 2026-03-24 16:02:31 +08:00
Misaka_Company
a711781f21 feat: add Playwright browser download progress dialog component 2026-03-24 15:48:07 +08:00
Misaka
c09e0eb4e7 test: cover renderer state helpers 2026-03-21 19:45:19 +08:00
Misaka
86614efa22 refactor: lazy load renderer dialogs 2026-03-21 19:32:03 +08:00
Misaka
16ac892c93 refactor: isolate extractor and update dialog state 2026-03-21 19:28:01 +08:00
Misaka
1fc2eab816 refactor: split cleaner page layout 2026-03-21 19:15:35 +08:00
Misaka
2baf55bd2e refactor: split app bootstrap and shell 2026-03-21 19:05:10 +08:00
Misaka
9a1f5a483e fix: harden startup flow and auth re-entry 2026-03-21 11:02:17 +08:00
Misaka
2b4a09dabe fix: resolve lint and typecheck issues 2026-03-21 09:33:07 +08:00
Misaka
7b57545127 refactor: extract cleaner hook helpers and api 2026-03-21 09:02:45 +08:00
Misaka
7d73592d41 Merge remote-tracking branch 'origin/dev' into dev 2026-03-20 23:25:32 +08:00
Misaka
6ad9463e73 feat: rebuild portable auto-update flow 2026-03-20 21:20:28 +08:00
Misaka_Company
7644b8d4ea feat(report-viewer): add searchable combobox for report selection
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>
2026-03-19 17:33:16 +08:00
test
5e50a8fbcf feat(report-viewer): add syntax highlighting and GitHub-style markdown rendering
Add rehype plugins for enhanced markdown rendering:
- rehype-highlight: syntax highlighting for code blocks
- rehype-slug: generates heading IDs for anchoring
- rehype-autolink-headings: auto-links headings
- github-markdown-css: GitHub-flavored markdown styling

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-18 20:13:40 +08:00
google-labs-jules[bot]
a020ee537d feat: Add Report Viewer Dialog to Cleaner Page
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>
2026-03-17 23:03:13 +00:00
test
b94640ca81 fix(modal): prevent accidental closure during execution
- 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>
2026-03-17 22:02:00 +08:00
Misaka_Company
defeb01808 fix: show elapsed time in execution result dialog
- 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.
2026-03-17 14:50:57 +08:00
Misaka_Company
b289fb9624 fix: use updateProcessConcurrency to persist slider changes to config.yaml
- 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
2026-03-17 10:57:24 +08:00
test
103effcfca ♻️ style: format code with Prettier and fix .gitattributes
- 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>
2026-03-16 22:42:16 +08:00
test
6a2fba0e57 refactor(cleaner): batch query and controlled parallel order processing 2026-03-16 21:47:13 +08:00
Misaka_Company
9248be6310 ♻️ refactor(ui): use global toast system in SettingsPage
- 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>
2026-03-16 16:16:06 +08:00
Misaka_Company
cccc4e4c8c feat(ui): display version and git hash in header
Add version info display below "ERP Auto" logo showing format:
${version}(${git-hash})

- Inject __APP_VERSION__ and __GIT_HASH__ via vite define
- Add TypeScript declarations for global constants
- Simplify portable artifact name (remove version)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-16 15:00:38 +08:00
Misaka_Company
715dfb4d71 feat(cleaner): add automatic retry mechanism for failed orders
- Add retry logic with max 2 attempts per failed order
- Track retry statistics (retriedOrders, successfulRetries)
- Generate detailed retry report section in execution reports
- Display retry metrics in ExecutionReportDialog UI

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 15:59:10 +08:00
test
77fabf2018 fix(shared-state): clear shared Production IDs when input is cleared
Fixes a bug where clearing the order number input in the extraction page
did not clear the shared Production IDs in the main process. This caused
the data cleanup page to continue using stale data when filtering by
Production ID.

Changes:
- Add VALIDATION_CLEAR_SHARED_PRODUCTION_IDS IPC channel
- Register handler to clear shared Production IDs by sender ID
- Expose clearSharedProductionIds API in preload script
- Update ExtractorPage to call clear when order numbers are empty

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-03-08 21:58:56 +08:00
test
33b17e278d refactor(ui): replace native alerts with toast notifications and confirm dialogs
This commit refactors all native browser alert() and confirm() dialogs to use
the app's custom UI components for consistent user experience.

**Changes:**
- Add ConfirmDialog component with danger/warning/info variants
- Add useConfirmDialog hook for promise-based dialog API
- Add formatListMessage utility for truncating long lists
- Replace 18 alert() calls with toast notifications in useCleaner.ts
- Replace 7 alert()/confirm() calls in MaterialTypeManagementDialog.tsx
- Render Toast component in App.tsx for global notifications
- Add keyboard shortcuts (Enter to confirm, Escape to cancel)

**Benefits:**
- Consistent UI design across all notifications
- Non-blocking notifications for better UX
- Better accessibility with proper ARIA roles and focus management
- Multi-line message support with truncation for long lists

**Files Modified:**
- src/renderer/src/components/ui/ConfirmDialog.tsx (new)
- src/renderer/src/stores/useAppStore.ts (add formatListMessage)
- src/renderer/src/hooks/useCleaner.ts (refactor error handling)
- src/renderer/src/components/MaterialTypeManagementDialog.tsx (refactor dialogs)
- src/renderer/src/pages/CleanerPage.tsx (add ConfirmDialog)
- src/renderer/src/App.tsx (render Toast component)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-03-08 19:13:25 +08:00
test
bcfe0eecca fix(a11y): improve focus restoration with timing fixes, validation, and error handling
Core improvements:
- Fix focus restoration timing by using queueMicrotask only (removed double-layer async)
- Add comprehensive error handling with dev-mode logging for all failure scenarios
- Validate element visibility (display: none, visibility: hidden) before restoring focus
- Check disabled state and implement fallback to nearest focusable ancestor
- Add findNearestFocusableElement() helper for robust fallback strategy
- Add tabindex="-1" to focusable selectors for better focus management
- Use preventScroll option when calling focus() to prevent scroll jumps

Additional fixes:
- Remove unnecessary type conversion in Modal.tsx
- Fix TypeScript unused variable errors in main process
- Clean up unused imports in bip-users-dao.ts
- Add ARIA attributes and focus management to LoginDialog
- Add triggerRef support to UserSelectionDialog and ExecutionReportDialog
- Refactor ExecutionReportDialog to use Modal component
- Improve MaterialTypeManagementDialog with focus management

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-03-08 18:29:39 +08:00
test
9a640b96e6 test(e2e): improve dialog focus tests and code quality
Test improvements:
- Add error handling for Electron app launch in headless environments
- Update dialog selectors to use ARIA attributes for better reliability
- Implement actual test logic (previously skipped placeholders)
- Add screenshot capture evidence for test results
- Update test descriptions to match actual dialog types

Code quality improvements:
- Change 'let' to 'const' for variables that are not reassigned
- Improves code clarity and follows best practices

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-03-08 17:59:35 +08:00
test
5b4d7fab49 refactor(a11y): optimize dialog focus management with centralized Escape handling
Enhanced the useDialogFocus hook to support conditional Escape key handling,
removing redundant Escape key listeners from individual dialog components.

Changes:
- Added shouldCloseOnEscape option to useDialogFocus (boolean or function callback)
- Removed redundant Escape key handlers from Modal, ExecutionReportDialog, and LoginDialog
- ExecutionReportDialog now uses shouldCloseOnEscape: () => !isExecuting to prevent
  closing during execution
- LoginDialog no longer has manual focus effect (handled by initialFocusSelector)
- Fixed React hooks order violations in ExecutionReportDialog
- Added proper TypeScript return types throughout

Benefits:
- Centralized Escape key logic in one place
- Consistent behavior across all dialogs
- Reduced code duplication (~50 lines removed)
- Easier to maintain and extend

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-03-08 17:58:16 +08:00
test
72d8d981b1 feat(a11y): add focus management to UserSelectionDialog and ExecutionReportDialog
UserSelectionDialog:
- Add ARIA attributes (role, aria-modal, aria-labelledby)
- Integrate useDialogFocus hook with FocusLock
- Add Escape key handling (was missing)
- Initial focus on first user card

ExecutionReportDialog:
- Add ARIA attributes with dynamic aria-labelledby
- Add aria-live for progress updates
- Integrate useDialogFocus hook with FocusLock
- Escape key only closes when not executing
2026-03-08 17:16:53 +08:00
test
d1f2f40123 feat(a11y): add focus management to LoginDialog
- Add role="dialog", aria-modal="true", aria-labelledby
- Add aria-live="polite" and role="alert" on error messages
- Integrate useDialogFocus hook with FocusLock
- Maintain initial focus on username input
- Maintain Enter key submit and Escape key close
- Refactor error handling with internal state
2026-03-08 17:09:37 +08:00