Files
yidaima/RuoYi-Vue/docs/superpowers/plans/2026-07-06-admin-home-dashboard-metrics.md

15 KiB
Raw Permalink Blame History

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:

@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:

mvn -pl ruoyi-generator -Dtest=ChartDatasetValidatorTest#chartValidationAcceptsDashboardSpans test

Expected: FAIL because span 3 is rejected.

  • Step 3: Implement span support

Change ChartDatasetValidator.SPANS to:

private static final Set<Integer> SPANS =
        new HashSet<Integer>(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<E3><80>?<3F><>?<3F><>?<3F><>?.

  • Step 4: Add template test and implementation

Add assertions to QingTemplateSupportTest.businessBlockPageTemplateUsesLocalizedPolishedEmptyState():

assertTrue(content.contains("business-block-page__item--span-3"));
assertTrue(content.contains("business-block-page__item--span-8"));

Run:

mvn -pl ruoyi-generator -Dtest=QingTemplateSupportTest#businessBlockPageTemplateUsesLocalizedPolishedEmptyState test

Expected: FAIL until business-block-page.vue.vm contains:

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

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():

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:

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:

public class AdminHomeDashboardDesign {
    private String title;
    private String description;
    private List<AdminHomeMetricDesign> metrics = new ArrayList<AdminHomeMetricDesign>();
    private List<AdminHomeChartDesign> charts = new ArrayList<AdminHomeChartDesign>();
}
public class AdminHomeMetricDesign {
    private String code;
    private String title;
    private String tableName;
    private String aggregate;
    private String field;
    private List<ChartFilterConfig> filters = new ArrayList<ChartFilterConfig>();
    private ChartDateRangeConfig dateRange;
    private String semantic;
    private String unit;
    private String prefix;
    private String suffix;
    private Integer precision;
}
public class AdminHomeChartDesign {
    private String code;
    private String title;
    private String type;
    private String tableName;
    private ChartDimensionConfig dimension;
    private List<ChartMetricConfig> metrics = new ArrayList<ChartMetricConfig>();
    private List<ChartFilterConfig> filters = new ArrayList<ChartFilterConfig>();
    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:

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:

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:

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:

mvn -pl ruoyi-generator -Dtest=AdminHomeDashboardComposerTest#composeUsesBlueprintMetricsAndCharts test

Expected: FAIL because the class does not exist.

  • Step 3: Implement composer core

Implement:

public boolean compose(FrontProjectPageDesign homeDesign, AppBlueprintDesign blueprint,
        Collection<FrontProjectTable> sourceTables, BusinessLoopPlan loopPlan)

Key helpers:

  • metricBlock(AdminHomeMetricDesign metric, int index)
  • chartBlock(AdminHomeChartDesign chart, int index)
  • validate(BusinessBlockInstance instance, List<GenTable> 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:

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:

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:

mvn -pl ruoyi-generator -Dtest=FrontendPageDesignServiceTest#initializeAdminHomeComposesDashboardFromBlueprint test

Expected: FAIL because the service does not call the composer.

  • Step 3: Wire composer

Add:

@Autowired
private AdminHomeDashboardComposer adminHomeDashboardComposer;

Add a lazy fallback method like existing homeBusinessBlockComposer(). In initializeAdminPageDesigns, after getOrCreateHomeDesign, call:

if (adminHomeDashboardComposer().compose(homeDesign, blueprint, frontTables(tablesByName), loopPlan))
{
    pageDesignMapper.updateFrontProjectPageDesign(homeDesign);
}
  • Step 4: Verify task

Run:

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:

"display":{"title":"Order Count","semantic":"order","icon":"el-icon-s-order","theme":"green","unit":"<22><>?}

Assert generated component contains:

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:

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: <i :class="display.icon || 'el-icon-data-line'"></i>

  • title and optional subtitle

  • formatted value with prefix, suffix, unit, and precision

  • themeClass computed from display.theme

  • Step 4: Verify task

Run:

mvn -pl ruoyi-generator -Dtest=BusinessBlockGenerationServiceTest test

Expected: PASS.

Task 6: Final Verification

Files:

  • All touched files.

  • Step 1: Run focused tests

Run:

mvn -pl ruoyi-generator -Dtest=AdminHomeDashboardComposerTest,FrontendPageDesignServiceTest,ChartDatasetValidatorTest,BusinessBlockGenerationServiceTest,QingTemplateSupportTest,AiGenerateServiceImplTest test

Expected: PASS.

  • Step 2: Run compile

Run:

mvn -pl ruoyi-generator -am -DskipTests compile

Expected: PASS.

  • Step 3: Review diffs

Run:

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.