14 KiB
WorkUtils Unified UI P2 Core Plugin Migration Implementation Plan
For agentic workers: REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (
- [ ]) syntax for tracking.
Goal: Migrate MyBatis reverse engineering, MyBatis SQL export, scanner, Git sync, and text diff to the P0 page skeleton and visual tokens without changing business behavior.
Architecture: Treat every plugin window as a thin view composer. Shared PageHeader, semantic CSS classes, LoadingButtonBinder, OperationStatusPane, ExportHistoryPane, and ResizableLogPane replace per-window font/style/layout code; application/use-case classes remain unchanged.
Tech Stack: Java 17, JavaFX 17.0.15, AtlantaFX 2.0.1, P0/P1 shared UI components, JUnit 5, Maven Wrapper.
Global Constraints
- Do not change request DTOs, use cases, generators, scanners, Git operations, diff algorithms, persistence formats, or output files.
- Do not add a second page title when the application header already names the active plugin; content uses
PageHeaderonly when it adds a useful description. - Remove per-window
Microsoft YaHei, arbitrary font sizes, backgroundsetStyle(...), and duplicated log/status styling from the touched windows. - Use only P0
AppIcon/IconFactory; no Emoji in visible controls. - Use
LoadingButtonBinderandOperationStatusPaneas the only asynchronous visual-state entry points. - Preserve true cancellation semantics: SQL export may cancel; scanner must not show a false cancel control.
- Each plugin migration is an independent commit with focused tests and a screenshot comparison.
File Structure
Create
src/test/java/com/example/workutils/system/ui/CorePluginVisualArchitectureTest.java— source-level guard for inline styles, arbitrary fonts, Emoji, and duplicate loading code.
Modify
src/main/java/com/example/workutils/biz/mybatisgenerator/MyBatisGeneratorWindow.javasrc/test/java/com/example/workutils/biz/mybatisgenerator/MyBatisGeneratorWindowArchitectureTest.javasrc/main/java/com/example/workutils/biz/mybatisexport/MyBatisExportWindow.javasrc/test/java/com/example/workutils/biz/mybatisexport/MyBatisExportHistoryMappingTest.javasrc/main/java/com/example/workutils/biz/scanner/ScannerWindow.javasrc/test/java/com/example/workutils/biz/scanner/ScannerHistoryMappingTest.javasrc/main/java/com/example/workutils/biz/git/GitSyncWindow.javasrc/main/java/com/example/workutils/biz/diff/DiffWindow.javasrc/main/resources/css/light-theme.css
Task 1: Establish migration guardrails
Files:
- Create:
src/test/java/com/example/workutils/system/ui/CorePluginVisualArchitectureTest.java
Interfaces:
-
Produces a test helper
source(String relativePath): String. Start the parameterized contract with the MyBatis generator only; add each remaining path in the task that migrates it so every commit finishes green. -
Step 1: Write the failing architecture test
private static String source(String relativePath) throws IOException {
return Files.readString(Path.of("src/main/java/com/example/workutils", relativePath));
}
@ParameterizedTest
@ValueSource(strings = {
"biz/mybatisgenerator/MyBatisGeneratorWindow.java"
})
void corePluginWindowsUseSharedVisualInfrastructure(String relativePath) throws IOException {
String source = source(relativePath);
assertFalse(source.contains("Font.font(\"Microsoft YaHei\""));
assertFalse(source.contains("-fx-background-color:"));
assertFalse(source.contains("new ProgressIndicator("));
assertTrue(source.contains("Theme.") || source.contains("PageHeader"));
}
- Step 2: Run and record expected failures
Run: .\mvnw.cmd -q -Dtest=CorePluginVisualArchitectureTest test
Expected: FAIL for the current MyBatis generator hardcoded fonts/backgrounds. Keep the failure output as the first migration checklist.
- Step 3: Add explicit exclusions for business-rendered content
The test scans only JavaFX window source. It must not scan generated HTML from ApiDocGenerator or diff HTML because those outputs have their own presentation contracts.
- Step 4: Commit the red test with the first migration task only
Do not commit a permanently red standalone changeset. Continue directly to Task 2, make the MyBatis generator case green, and commit the test plus that migration together.
Task 2: Migrate MyBatis reverse engineering
Files:
- Modify:
src/main/java/com/example/workutils/biz/mybatisgenerator/MyBatisGeneratorWindow.java - Modify:
src/test/java/com/example/workutils/biz/mybatisgenerator/MyBatisGeneratorWindowArchitectureTest.java - Modify:
src/main/resources/css/light-theme.css - Include:
src/test/java/com/example/workutils/system/ui/CorePluginVisualArchitectureTest.java
Interfaces:
-
Preserves:
QueryTablesUseCase,GenerateArtifactsUseCase, output planning, directory safety, and both operation controllers. -
Consumes:
PageHeader, tokenized controls,LoadingButtonBinder, and font-size-freeOperationStatusPane. -
Step 1: Add failing window structure assertions
assertTrue(source.contains("PageHeader"));
assertTrue(source.contains("LoadingButtonBinder.bind(queryBtn"));
assertTrue(source.contains("LoadingButtonBinder.bind(generateBtn"));
assertFalse(source.contains("Theme.heading(fsSection() + 4)"));
assertFalse(source.contains("Font.font(\"Consolas\""));
- Step 2: Run focused tests and verify failure
Run: .\mvnw.cmd -q -Dtest=MyBatisGeneratorWindowArchitectureTest,CorePluginVisualArchitectureTest test
Expected: FAIL on old title/font/inline styles.
- Step 3: Recompose the window
Use a compact data-source context row, two-column split for project tree and table/output form, semantic section headers, and the existing bottom generate action. Replace direct font/style calls with style classes. Keep current divider behavior and all event handlers.
- Step 4: Normalize the two operation rows
Query progress remains near table matching; generation progress remains with the final action bar. Do not merge the two controllers. Disable only controls that mutate each operation’s request.
- Step 5: Run all generator tests
Run: .\mvnw.cmd -q -Dtest=MyBatisGeneratorWindowArchitectureTest,GenerationPlannerTest,GeneratorRequestTest,GeneratorUseCaseTest,OutputLayoutPolicyTest,OutputSnapshotTest,DatasourceSummaryTest test
Expected: PASS.
- Step 6: Capture and compare
Capture the generator idle state and a controlled query-running state. Verify 20/15/14/13 typography, aligned directory rows, visible output controls, and no bottom clipping at 1024px width.
- Step 7: Commit
git add src/main/java/com/example/workutils/biz/mybatisgenerator/MyBatisGeneratorWindow.java src/test/java/com/example/workutils/biz/mybatisgenerator/MyBatisGeneratorWindowArchitectureTest.java src/test/java/com/example/workutils/system/ui/CorePluginVisualArchitectureTest.java src/main/resources/css/light-theme.css
git commit -m "统一 MyBatis 逆向工程界面"
Task 3: Migrate MyBatis SQL export and scanner
Files:
- Modify:
src/main/java/com/example/workutils/biz/mybatisexport/MyBatisExportWindow.java - Modify:
src/main/java/com/example/workutils/biz/scanner/ScannerWindow.java - Modify:
src/test/java/com/example/workutils/biz/mybatisexport/MyBatisExportHistoryMappingTest.java - Modify:
src/test/java/com/example/workutils/biz/scanner/ScannerHistoryMappingTest.java - Modify:
src/test/java/com/example/workutils/system/ui/CorePluginVisualArchitectureTest.java
Interfaces:
-
Preserves:
SqlExportRequest,RunSqlExportUseCase,ScanRequest,RunScanUseCase, and history mappings. -
Consumes: shared page/form classes and
ResizableLogPane. -
Step 1: Add failing cancellation and structure assertions
First extend @ValueSource with MyBatisExportWindow.java and ScannerWindow.java, then add:
assertTrue(sqlSource.contains("new OperationStatusPane(exportOperation, true)"));
assertTrue(scannerSource.contains("new OperationStatusPane(scanOperation, false)"));
assertFalse(scannerSource.contains("停止当前任务"));
assertFalse(sqlSource.contains("logArea.setStyle("));
- Step 2: Run focused tests and verify failure
Run: .\mvnw.cmd -q -Dtest=CorePluginVisualArchitectureTest,RunSqlExportCancellationTest,ScanProgressTest test
Expected: FAIL on old constructors/styles; cancellation domain tests remain green.
- Step 3: Migrate SQL export
Lay out filter controls as one semantic form row, keep export action/progress together, use ResizableLogPane for current-run output, and retain ExportHistoryPane below. Keep the real SQL-export cancel control.
- Step 4: Migrate scanner
Lay out scan type and pattern as a compact configuration section, keep the non-cancellable status pane, and use shared history/log visuals. Do not add a stop button.
- Step 5: Run focused tests
Run: .\mvnw.cmd -q -Dtest=SqlExportRequestTest,SqlExportProgressTest,RunSqlExportCancellationTest,MyBatisExportHistoryMappingTest,ScanRequestTest,ScanProgressTest,ScannerHistoryMappingTest,CorePluginVisualArchitectureTest test
Expected: PASS.
- Step 6: Capture and compare both pages
Use idle/synthetic running states. Confirm SQL export exposes cancel while scanner does not, histories remain usable, and controls do not jump when loading begins.
- Step 7: Commit
git add src/main/java/com/example/workutils/biz/mybatisexport/MyBatisExportWindow.java src/main/java/com/example/workutils/biz/scanner/ScannerWindow.java src/test/java/com/example/workutils/biz/mybatisexport src/test/java/com/example/workutils/biz/scanner src/test/java/com/example/workutils/system/ui/CorePluginVisualArchitectureTest.java
git commit -m "统一导出与扫描插件界面"
Task 4: Migrate Git sync without touching Git behavior
Files:
- Modify:
src/main/java/com/example/workutils/biz/git/GitSyncWindow.java - Modify:
src/test/java/com/example/workutils/system/ui/CorePluginVisualArchitectureTest.java
Interfaces:
-
Preserves all tabs,
RunGitSyncUseCase,GitSyncRequest, filters, remote URL presentation, damaged repository actions, and confirmation flow. -
Consumes shared tabs, table, form, log, loading, and status styles.
-
Step 1: Add failing Git window assertions
First extend @ValueSource with GitSyncWindow.java, then add:
assertTrue(source.contains("new Tab(\"项目列表\")"));
assertTrue(source.contains("new Tab(\"同步执行\")"));
assertTrue(source.contains("new Tab(\"损坏仓库处理\")"));
assertFalse(source.contains("btn.setStyle("));
assertFalse(source.contains("projectTable.setStyle("));
- Step 2: Run tests and verify failure
Run: .\mvnw.cmd -q -Dtest=CorePluginVisualArchitectureTest,RunGitSyncUseCaseTest,ProjectFilterTest,RemoteUrlDisplayTest test
Expected: FAIL only on visual architecture assertions.
- Step 3: Migrate each existing tab in place
Use global tab styles, tokenized toolbar/form spacing, shared table/log styles, and semantic warning button classes. Do not rename or reorder tabs. Preserve destructive confirmation text and never invoke the destructive action during visual verification.
- Step 4: Run focused tests and capture
Run: .\mvnw.cmd -q -Dtest=CorePluginVisualArchitectureTest,RunGitSyncUseCaseTest,ProjectFilterTest,RemoteUrlDisplayTest test
Expected: PASS. Capture all three tabs read-only and verify row height, URL truncation, and warning action hierarchy.
- Step 5: Commit
git add src/main/java/com/example/workutils/biz/git/GitSyncWindow.java src/test/java/com/example/workutils/system/ui/CorePluginVisualArchitectureTest.java src/main/resources/css/light-theme.css
git commit -m "统一 Git 同步插件界面"
Task 5: Migrate text diff while preserving the renderer
Files:
- Modify:
src/main/java/com/example/workutils/biz/diff/DiffWindow.java - Modify:
src/test/java/com/example/workutils/system/ui/CorePluginVisualArchitectureTest.java
Interfaces:
-
Preserves:
DiffEngine, input actions, navigation between differences, copy/save actions, and WebView result rendering. -
Consumes shared input, split-pane, action-bar, status, and focus styles.
-
Step 1: Add failing diff visual assertions
First extend @ValueSource with DiffWindow.java, then add:
assertTrue(source.contains("LoadingButtonBinder.bind(compareBtn"));
assertFalse(source.contains("\"▶ 开始对比\""));
assertFalse(source.contains("webView.setStyle("));
assertFalse(source.contains("statusLabel.setStyle("));
- Step 2: Run and verify failure
Run: .\mvnw.cmd -q -Dtest=CorePluginVisualArchitectureTest,DiffEngineLineTest,DiffEngineCharacterTest test
Expected: FAIL on Emoji/inline styles; engine tests remain green.
- Step 3: Migrate the JavaFX chrome only
Replace the play-character button text with visible “开始对比” plus AppIcon.DIFF; apply shared split-pane, input, result header, WebView border, and status classes. Do not alter HTML generation or diff algorithms.
- Step 4: Run tests and capture
Run: .\mvnw.cmd -q -Dtest=CorePluginVisualArchitectureTest,DiffEngineLineTest,DiffEngineCharacterTest test
Expected: PASS. Capture empty, compared, and difference-navigation states using non-sensitive sample text.
- Step 5: Commit
git add src/main/java/com/example/workutils/biz/diff/DiffWindow.java src/test/java/com/example/workutils/system/ui/CorePluginVisualArchitectureTest.java src/main/resources/css/light-theme.css
git commit -m "统一文本对比插件界面"
P2 Completion Gate
Run: .\mvnw.cmd -q test
Run: .\mvnw.cmd -q -DskipTests compile
Run: git diff --check
Expected: all exit 0. Review the five plugin screenshot sets at 1440px and 1024px before P3. No test or visual check may perform Git synchronization, export files, generation, or scanning against user projects.