# Admin Home Dashboard Metrics 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:** Generate an admin home dashboard with metric cards, semantic icons, and chart blocks from `AppBlueprintDesign.adminHomeDashboard`, falling back to the main business table when needed. **Architecture:** Add dashboard DTOs to the app blueprint, a focused `AdminHomeDashboardComposer` that converts blueprint/fallback intent into existing `business-blocks-v1` chart block instances, and wire it into admin page initialization. Reuse `BusinessBlockRegistryService`, `ChartDatasetValidator`, existing chart business block definitions, and existing Velocity chart generation templates. **Tech Stack:** Java 8, JUnit 4, Mockito, Fastjson2, Jackson, RuoYi generator services, Velocity templates, Vue 2/Element UI. --- ## File Structure - Create `ruoyi-generator/src/main/java/com/ruoyi/generator/domain/front/dto/AdminHomeDashboardDesign.java`: top-level dashboard blueprint model. - Create `ruoyi-generator/src/main/java/com/ruoyi/generator/domain/front/dto/AdminHomeMetricDesign.java`: metric card blueprint model. - Create `ruoyi-generator/src/main/java/com/ruoyi/generator/domain/front/dto/AdminHomeChartDesign.java`: chart blueprint model. - Modify `ruoyi-generator/src/main/java/com/ruoyi/generator/domain/front/dto/AppBlueprintDesign.java`: add `adminHomeDashboard`. - Create `ruoyi-generator/src/main/java/com/ruoyi/generator/service/front/AdminHomeDashboardComposer.java`: compose dashboard layout from blueprint and table metadata. - Modify `ruoyi-generator/src/main/java/com/ruoyi/generator/service/front/FrontendPageDesignService.java`: call composer for `admin_home`. - Modify `ruoyi-generator/src/main/java/com/ruoyi/generator/service/front/ChartDatasetValidator.java`: allow spans `3` and `8`. - Modify `ruoyi-generator/src/main/java/com/ruoyi/generator/service/front/AiGenerateServiceImpl.java`: prompt AI to return `adminHomeDashboard`. - Modify `ruoyi-generator/src/main/resources/business-blocks/page/business-block-page.vue.vm`: add grid classes for `span=3` and `span=8`. - Modify `ruoyi-generator/src/main/resources/business-blocks/chart/templates/frontend/AdminChartBlock.vue.vm`: render metric blocks as polished indicator cards with icon/theme/unit support. - Test `ruoyi-generator/src/test/java/com/ruoyi/generator/service/front/AdminHomeDashboardComposerTest.java`. - Modify tests in `ChartDatasetValidatorTest`, `FrontendPageDesignServiceTest`, `AiGenerateServiceImplTest`, `QingTemplateSupportTest`, and `BusinessBlockGenerationServiceTest`. ## Task 1: Allow Dashboard Grid Spans **Files:** - Modify: `ruoyi-generator/src/main/java/com/ruoyi/generator/service/front/ChartDatasetValidator.java` - Modify: `ruoyi-generator/src/test/java/com/ruoyi/generator/service/front/ChartDatasetValidatorTest.java` - Modify: `ruoyi-generator/src/main/resources/business-blocks/page/business-block-page.vue.vm` - Modify: `ruoyi-generator/src/test/java/com/ruoyi/generator/util/QingTemplateSupportTest.java` - [ ] **Step 1: Write failing validator test** Add this test to `ChartDatasetValidatorTest`: ```java @Test public void chartValidationAcceptsDashboardSpans() { BusinessBlockInstance metric = validLineChartInstance(); metric.setSpan(Integer.valueOf(3)); validator.validate(lineChartDefinition(), metric, chartTables()); BusinessBlockInstance wide = validLineChartInstance(); wide.setSpan(Integer.valueOf(8)); validator.validate(lineChartDefinition(), wide, chartTables()); } ``` - [ ] **Step 2: Run failing validator test** Run: ```bash mvn -pl ruoyi-generator -Dtest=ChartDatasetValidatorTest#chartValidationAcceptsDashboardSpans test ``` Expected: FAIL because span `3` is rejected. - [ ] **Step 3: Implement span support** Change `ChartDatasetValidator.SPANS` to: ```java private static final Set SPANS = new HashSet(Arrays.asList(Integer.valueOf(12), Integer.valueOf(8), Integer.valueOf(6), Integer.valueOf(4), Integer.valueOf(3))); ``` Update the span error message to mention `12????`. - [ ] **Step 4: Add template test and implementation** Add assertions to `QingTemplateSupportTest.businessBlockPageTemplateUsesLocalizedPolishedEmptyState()`: ```java assertTrue(content.contains("business-block-page__item--span-3")); assertTrue(content.contains("business-block-page__item--span-8")); ``` Run: ```bash mvn -pl ruoyi-generator -Dtest=QingTemplateSupportTest#businessBlockPageTemplateUsesLocalizedPolishedEmptyState test ``` Expected: FAIL until `business-block-page.vue.vm` contains: ```css .business-block-page__item--span-8 { grid-column: span 8; } .business-block-page__item--span-3 { grid-column: span 3; } ``` - [ ] **Step 5: Verify task** Run: ```bash mvn -pl ruoyi-generator -Dtest=ChartDatasetValidatorTest,QingTemplateSupportTest test ``` Expected: PASS for touched tests. ## Task 2: Add Dashboard Blueprint DTOs and AI Prompt **Files:** - Create: `ruoyi-generator/src/main/java/com/ruoyi/generator/domain/front/dto/AdminHomeDashboardDesign.java` - Create: `ruoyi-generator/src/main/java/com/ruoyi/generator/domain/front/dto/AdminHomeMetricDesign.java` - Create: `ruoyi-generator/src/main/java/com/ruoyi/generator/domain/front/dto/AdminHomeChartDesign.java` - Modify: `ruoyi-generator/src/main/java/com/ruoyi/generator/domain/front/dto/AppBlueprintDesign.java` - Modify: `ruoyi-generator/src/main/java/com/ruoyi/generator/service/front/AiGenerateServiceImpl.java` - Modify: `ruoyi-generator/src/test/java/com/ruoyi/generator/service/front/AiGenerateServiceImplTest.java` - [ ] **Step 1: Write failing AI blueprint test** Extend `generateAppBlueprintNormalizesAndPersistsStaticMenus()`: ```java assertTrue(promptCaptor.getValue().contains("adminHomeDashboard")); assertEquals("运营总览", blueprint.getAdminHomeDashboard().getTitle()); assertEquals("order_count", blueprint.getAdminHomeDashboard().getMetrics().get(0).getCode()); assertEquals("sales_trend", blueprint.getAdminHomeDashboard().getCharts().get(0).getCode()); assertTrue(projectCaptor.getValue().getAppBlueprint().contains("adminHomeDashboard")); ``` Extend `appBlueprintResponse()` with a valid `adminHomeDashboard` object that contains one metric and one chart. - [ ] **Step 2: Run failing AI test** Run: ```bash mvn -pl ruoyi-generator -Dtest=AiGenerateServiceImplTest#generateAppBlueprintNormalizesAndPersistsStaticMenus test ``` Expected: FAIL because `AppBlueprintDesign` has no dashboard property or the prompt does not mention it. - [ ] **Step 3: Add DTOs** Use these public fields through getters/setters: ```java public class AdminHomeDashboardDesign { private String title; private String description; private List metrics = new ArrayList(); private List charts = new ArrayList(); } ``` ```java public class AdminHomeMetricDesign { private String code; private String title; private String tableName; private String aggregate; private String field; private List filters = new ArrayList(); private ChartDateRangeConfig dateRange; private String semantic; private String unit; private String prefix; private String suffix; private Integer precision; } ``` ```java public class AdminHomeChartDesign { private String code; private String title; private String type; private String tableName; private ChartDimensionConfig dimension; private List metrics = new ArrayList(); private List filters = new ArrayList(); private ChartDateRangeConfig dateRange; private ChartSortConfig sort; private Integer limit; private String semantic; } ``` Add `private AdminHomeDashboardDesign adminHomeDashboard;` to `AppBlueprintDesign`. - [ ] **Step 4: Update prompt** In `buildAppBlueprintPrompt`, include `adminHomeDashboard` in the JSON shape and add constraints: ```java prompt.append("Also return adminHomeDashboard for the generated backend home page. "); prompt.append("It must include 4 business metrics when possible and at least 2 charts: one trend line/bar chart and one distribution pie/bar chart. "); prompt.append("Use semantic values only for dashboard icons: money, order, user, task, warning, inventory, content, default. Do not output Element UI icon class names.\\n"); ``` - [ ] **Step 5: Verify task** Run: ```bash mvn -pl ruoyi-generator -Dtest=AiGenerateServiceImplTest#generateAppBlueprintNormalizesAndPersistsStaticMenus test ``` Expected: PASS. ## Task 3: Compose Dashboard Layout From Blueprint **Files:** - Create: `ruoyi-generator/src/main/java/com/ruoyi/generator/service/front/AdminHomeDashboardComposer.java` - Create: `ruoyi-generator/src/test/java/com/ruoyi/generator/service/front/AdminHomeDashboardComposerTest.java` - [ ] **Step 1: Write failing composer test for complete blueprint** Test should create an `admin_home` design, an app blueprint with 4 metrics and 2 charts, and a `shop_order` table with id, amount, status, and create time columns. Assert that: ```java assertTrue(composer.compose(homeDesign, blueprint, tables(), null)); assertTrue(homeDesign.getLayoutJson().contains("\"dashboard\"")); assertTrue(homeDesign.getLayoutJson().contains("\"blockCode\":\"admin_metric_chart\"")); assertTrue(homeDesign.getLayoutJson().contains("\"span\":3")); assertTrue(homeDesign.getLayoutJson().contains("\"blockCode\":\"admin_line_chart\"")); assertTrue(homeDesign.getLayoutJson().contains("\"span\":8")); assertTrue(homeDesign.getLayoutJson().contains("\"icon\":\"el-icon-s-order\"")); ``` - [ ] **Step 2: Run failing composer test** Run: ```bash mvn -pl ruoyi-generator -Dtest=AdminHomeDashboardComposerTest#composeUsesBlueprintMetricsAndCharts test ``` Expected: FAIL because the class does not exist. - [ ] **Step 3: Implement composer core** Implement: ```java public boolean compose(FrontProjectPageDesign homeDesign, AppBlueprintDesign blueprint, Collection sourceTables, BusinessLoopPlan loopPlan) ``` Key helpers: - `metricBlock(AdminHomeMetricDesign metric, int index)` - `chartBlock(AdminHomeChartDesign chart, int index)` - `validate(BusinessBlockInstance instance, List genTables)` - `display(String title, String semantic, AdminHomeMetricDesign metric)` - `iconFor(String semantic)` and `themeFor(String semantic)` - `safeCode(String value, String fallback)` Use block codes `admin_metric_chart`, `admin_line_chart`, `admin_bar_chart`, `admin_pie_chart` and IDs with `auto_admin_metric_` or `auto_admin_chart_` prefixes. - [ ] **Step 4: Add failing fallback test** Test no dashboard blueprint and a single `shop_order` table. Assert composer still produces total records, today added, pending, abnormal, trend, and distribution blocks. - [ ] **Step 5: Implement fallback** Select the main table, find primary key/id field, date field, status field, and amount field. Build: - `total_count` - `today_created` - `pending_count` - `abnormal_count` - `created_trend` - `status_distribution` - [ ] **Step 6: Verify task** Run: ```bash mvn -pl ruoyi-generator -Dtest=AdminHomeDashboardComposerTest test ``` Expected: PASS. ## Task 4: Wire Composer Into Admin Page Initialization **Files:** - Modify: `ruoyi-generator/src/main/java/com/ruoyi/generator/service/front/FrontendPageDesignService.java` - Modify: `ruoyi-generator/src/test/java/com/ruoyi/generator/service/front/FrontendPageDesignServiceTest.java` - [ ] **Step 1: Write failing service test** Add a test that initializes admin page designs with `projectWithAdminDashboard()` and `orderTable()`. Assert: ```java FrontendPageDesignInitResponse response = service.initializePageDesigns(7L, 10L, "admin"); assertEquals("admin_home", response.getDesigns().get(0).getPageCode()); assertTrue(response.getDesigns().get(0).getLayoutJson().contains("admin_metric_chart")); assertTrue(response.getDesigns().get(0).getLayoutJson().contains("admin_line_chart")); verify(pageDesignMapper, times(2)).insertFrontProjectPageDesign(any(FrontProjectPageDesign.class)); verify(pageDesignMapper).updateFrontProjectPageDesign(any(FrontProjectPageDesign.class)); ``` - [ ] **Step 2: Run failing service test** Run: ```bash mvn -pl ruoyi-generator -Dtest=FrontendPageDesignServiceTest#initializeAdminHomeComposesDashboardFromBlueprint test ``` Expected: FAIL because the service does not call the composer. - [ ] **Step 3: Wire composer** Add: ```java @Autowired private AdminHomeDashboardComposer adminHomeDashboardComposer; ``` Add a lazy fallback method like existing `homeBusinessBlockComposer()`. In `initializeAdminPageDesigns`, after `getOrCreateHomeDesign`, call: ```java if (adminHomeDashboardComposer().compose(homeDesign, blueprint, frontTables(tablesByName), loopPlan)) { pageDesignMapper.updateFrontProjectPageDesign(homeDesign); } ``` - [ ] **Step 4: Verify task** Run: ```bash mvn -pl ruoyi-generator -Dtest=FrontendPageDesignServiceTest#initializeAdminHomeComposesDashboardFromBlueprint test ``` Expected: PASS. ## Task 5: Render Metric Cards With Icons and Theme **Files:** - Modify: `ruoyi-generator/src/main/resources/business-blocks/chart/templates/frontend/AdminChartBlock.vue.vm` - Modify: `ruoyi-generator/src/test/java/com/ruoyi/generator/service/BusinessBlockGenerationServiceTest.java` - [ ] **Step 1: Write failing template generation test** Extend the existing chart component generation test or add one using an `admin_metric_chart` instance with: ```json "display":{"title":"Order Count","semantic":"order","icon":"el-icon-s-order","theme":"green","unit":"?} ``` Assert generated component contains: ```java assertTrue(component.contains("admin-chart-block--metric")); assertTrue(component.contains("display.icon")); assertTrue(component.contains("metricUnit")); assertTrue(component.contains("themeClass")); ``` - [ ] **Step 2: Run failing generation test** Run: ```bash mvn -pl ruoyi-generator -Dtest=BusinessBlockGenerationServiceTest test ``` Expected: FAIL until the template includes metric card markup/helpers. - [ ] **Step 3: Update template** For `chartType === "metric"`, render a dedicated metric card with: - icon square: `` - title and optional subtitle - formatted value with `prefix`, `suffix`, `unit`, and `precision` - `themeClass` computed from `display.theme` - [ ] **Step 4: Verify task** Run: ```bash mvn -pl ruoyi-generator -Dtest=BusinessBlockGenerationServiceTest test ``` Expected: PASS. ## Task 6: Final Verification **Files:** - All touched files. - [ ] **Step 1: Run focused tests** Run: ```bash mvn -pl ruoyi-generator -Dtest=AdminHomeDashboardComposerTest,FrontendPageDesignServiceTest,ChartDatasetValidatorTest,BusinessBlockGenerationServiceTest,QingTemplateSupportTest,AiGenerateServiceImplTest test ``` Expected: PASS. - [ ] **Step 2: Run compile** Run: ```bash mvn -pl ruoyi-generator -am -DskipTests compile ``` Expected: PASS. - [ ] **Step 3: Review diffs** Run: ```bash git diff -- RuoYi-Vue/ruoyi-generator RuoYi-Vue/docs/superpowers/plans/2026-07-06-admin-home-dashboard-metrics.md ``` Expected: Only dashboard implementation, tests, templates, and plan changes.