8.2 KiB
Dense Cargo Space Plan 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: Display warehouse 03 as a floor-selectable 13排 × 25列 dense-storage map matching the supplied layout while preserving the existing heatmap for every other warehouse.
Architecture: Add a dedicated read-only KPI endpoint for dense-layout coordinates so the legacy /kpi/cargoSpacePlan response remains unchanged. The Vue page branches only when warehouseId === '03', rendering a focused dense-map component with exact coordinate placement, floor controls, special-node colors, and per-floor counts; all other warehouses continue through the current roadway/platoon/ECharts path.
Tech Stack: Java 17, Spring Boot, Mockito/JUnit 5, Vue 2, Element UI, ECharts 5, SCSS, Playwright.
Task 1: Add a dense-plan KPI response
Files:
-
Modify:
ruoyi-admin/src/main/java/com/ruoyi/kpi/controller/KpiController.java -
Modify:
ruoyi-admin/src/main/java/com/ruoyi/kpi/service/KpiService.java -
Modify:
ruoyi-admin/src/main/java/com/ruoyi/kpi/service/impl/KpiServiceImpl.java -
Test:
ruoyi-admin/src/test/java/com/ruoyi/kpi/service/impl/KpiServiceImplTest.java -
Step 1: Write the failing service test
Add a test that returns two warehouse-03 BasCargoSpace records on different floors and asserts that getDenseCargoSpacePlanData("03") returns sorted floors plus location maps containing cargoSpaceId, thePlatoon, theColumn, theFloor, status, groupCoding, and thisCargoArea.
Map<String, Object> result = service.getDenseCargoSpacePlanData("03");
assertThat(result.get("floors")).isEqualTo(List.of(1L, 2L));
assertThat(result.get("locations")).asList().hasSize(2);
- Step 2: Run the test and verify the missing-method failure
Run: D:/BDevTools/maven/apache-maven-3.9.11/bin/mvn.cmd -pl ruoyi-admin -am -Dtest=KpiServiceImplTest -Dsurefire.failIfNoSpecifiedTests=false test
Expected: compilation fails because getDenseCargoSpacePlanData does not exist.
- Step 3: Implement the service and endpoint
Add GET /kpi/denseCargoSpacePlan?warehouseId=03 protected by kpi:cargo:space:plan. Query BasCargoSpaceMapper by warehouse, derive sorted floors, and return plain location maps without JSON-string encoding.
@GetMapping("/denseCargoSpacePlan")
@PreAuthorize("@ss.hasPermi('kpi:cargo:space:plan')")
public AjaxResult getDenseCargoSpacePlan(String warehouseId) {
return AjaxResult.success(kpiService.getDenseCargoSpacePlanData(warehouseId));
}
- Step 4: Run the focused backend test
Run: D:/BDevTools/maven/apache-maven-3.9.11/bin/mvn.cmd -pl ruoyi-admin -am -Dtest=KpiServiceImplTest -Dsurefire.failIfNoSpecifiedTests=false test
Expected: all KpiServiceImplTest tests pass.
Task 2: Build the floor-selectable dense map
Files:
-
Create:
ruoyi-ui/src/views/kpi/plan/components/DenseCargoSpaceMap.vue -
Modify:
ruoyi-ui/src/api/kpi/kpi.js -
Modify:
ruoyi-ui/src/views/kpi/plan/index.vue -
Step 1: Add the dense-plan API client
export function getDenseChartData(query) {
return request({
url: '/kpi/denseCargoSpacePlan',
method: 'get',
params: query
})
}
- Step 2: Create the coordinate-grid component
Render a top axis row, 25 descending 列 rows, 13 ascending 排 columns, and a bottom axis row. Place each location with gridColumn = thePlatoon + 1 and gridRow = 27 - theColumn; use status 7 brown, status 8 yellow, status 9 green, and show the eight-digit cargo-space ID inside every real node.
cellStyle(location) {
return {
gridColumn: String(Number(location.thePlatoon) + 1),
gridRow: String(27 - Number(location.theColumn))
}
}
- Step 3: Branch warehouse 03 without changing legacy behavior
Keep the warehouse selector for all warehouses. For warehouse 03, hide roadway/platoon filters, call the dense endpoint, and show floor buttons 1-5. For any other warehouse, retain the existing roadway/platoon calls and ECharts heatmap code.
isDenseWarehouse() {
return String(this.queryParams.warehouseId) === '03'
}
- Step 4: Build the production frontend
Run: npm run build:prod from ruoyi-ui.
Expected: Vue production build succeeds with no compile errors.
Task 3: Verify behavior and visual fidelity
Files:
-
Create:
scripts/verify_dense_cargo_space_plan.py -
Verify:
ruoyi-ui/src/views/kpi/plan/index.vue -
Verify:
ruoyi-ui/src/views/kpi/plan/components/DenseCargoSpaceMap.vue -
Step 1: Start the backend and frontend with the webapp-testing helper
Run python C:/Users/13623/.agents/skills/webapp-testing/scripts/with_server.py --help first, then start the Spring Boot backend and Vue dev server through the helper.
- Step 2: Verify warehouse 03 in Chromium
Open the KPI cargo-space plan, select warehouse 03, wait for network idle, and verify floor controls, 259 current-floor nodes, the green 王-shaped mother channel, two brown lifts, two yellow conveyors, axis labels, and no console errors.
- Step 3: Verify a legacy warehouse
Switch to warehouse 01 and verify roadway/platoon controls and the existing ECharts heatmap remain visible.
- Step 4: Commit
git add docs/superpowers/plans/2026-07-14-dense-cargo-space-plan.md scripts/verify_dense_cargo_space_plan.py ruoyi-admin/src/main/java/com/ruoyi/kpi/controller/KpiController.java ruoyi-admin/src/main/java/com/ruoyi/kpi/service/KpiService.java ruoyi-admin/src/main/java/com/ruoyi/kpi/service/impl/KpiServiceImpl.java ruoyi-admin/src/test/java/com/ruoyi/kpi/service/impl/KpiServiceImplTest.java ruoyi-ui/src/api/kpi/kpi.js ruoyi-ui/src/views/kpi/plan/index.vue ruoyi-ui/src/views/kpi/plan/components/DenseCargoSpaceMap.vue
git commit -m "feat: add dense warehouse floor plan"
Only perform this step when the user explicitly requests a Git commit.
Task 4: Make the dense map viewport adaptive
Files:
-
Modify:
ruoyi-ui/src/views/kpi/plan/index.vue -
Modify:
ruoyi-ui/src/views/kpi/plan/components/DenseCargoSpaceMap.vue -
Modify:
scripts/verify_dense_cargo_space_plan.py -
Step 1: Move floor actions into the existing search form
For warehouse 03, render el-radio-group floor buttons and a refresh button after the warehouse selector. Remove the dense-mode explanatory sentence. Pass only the selected floor and locations into the map component.
<template v-if="isDenseWarehouse">
<el-form-item label="层">
<el-radio-group v-model="selectedDenseFloor" size="small">
<el-radio-button v-for="floor in denseFloors" :key="floor" :label="floor">{{ floor }}层</el-radio-button>
</el-radio-group>
</el-form-item>
<el-form-item>
<el-button icon="el-icon-refresh" @click="loadDenseChartData">刷新</el-button>
</el-form-item>
</template>
- Step 2: Remove the map header and column 25
Delete the warehouse eyebrow, title, subtitle, internal floor switch, and internal refresh action. Generate column labels from 24 down to 1, place data rows with gridRow = 26 - theColumn, and move the bottom 排 axis to row 26.
columnLabels() {
return Array.from({ length: 24 }, (_, index) => 24 - index)
}
- Step 3: Fit the full grid without internal scrolling
Use a fixed 13-column fraction grid and 24 adaptive rows. Set the viewport to overflow: hidden; compute the map row height from available viewport height with CSS clamp(), reduce summary/legend/footer vertical space, and allow cargo IDs to scale with clamp().
.dense-map__viewport { overflow: hidden; }
.dense-grid {
grid-template-columns: 36px repeat(13, minmax(0, 1fr));
grid-template-rows: 24px repeat(24, minmax(18px, 1fr)) 28px;
width: 100%;
min-width: 0;
}
- Step 4: Rebuild and verify responsive behavior
Run npm run build:prod, then run python scripts/verify_dense_cargo_space_plan.py. Assert column 25 is absent, floor controls are in .search-box, the dense map has 259 nodes, and both .dense-map__viewport and .dense-grid have scrollWidth <= clientWidth and scrollHeight <= clientHeight at 1500×1050 and 1280×800 viewports.