Files
workutils/docs/superpowers/plans/2026-08-01-workutils-unified-ui-p2-core-plugins.md
T
2026-08-01 12:42:14 +08:00

14 KiB
Raw Blame History

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 PageHeader only when it adds a useful description.
  • Remove per-window Microsoft YaHei, arbitrary font sizes, background setStyle(...), and duplicated log/status styling from the touched windows.
  • Use only P0 AppIcon/IconFactory; no Emoji in visible controls.
  • Use LoadingButtonBinder and OperationStatusPane as 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.java
  • src/test/java/com/example/workutils/biz/mybatisgenerator/MyBatisGeneratorWindowArchitectureTest.java
  • src/main/java/com/example/workutils/biz/mybatisexport/MyBatisExportWindow.java
  • src/test/java/com/example/workutils/biz/mybatisexport/MyBatisExportHistoryMappingTest.java
  • src/main/java/com/example/workutils/biz/scanner/ScannerWindow.java
  • src/test/java/com/example/workutils/biz/scanner/ScannerHistoryMappingTest.java
  • src/main/java/com/example/workutils/biz/git/GitSyncWindow.java
  • src/main/java/com/example/workutils/biz/diff/DiffWindow.java
  • src/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-free OperationStatusPane.

  • 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.