Files
FTC25009/docs/superpowers/plans/2026-07-14-dense-cargo-space-plan.md

182 lines
8.2 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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`
- [x] **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`.
```java
Map<String, Object> result = service.getDenseCargoSpacePlanData("03");
assertThat(result.get("floors")).isEqualTo(List.of(1L, 2L));
assertThat(result.get("locations")).asList().hasSize(2);
```
- [x] **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.
- [x] **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.
```java
@GetMapping("/denseCargoSpacePlan")
@PreAuthorize("@ss.hasPermi('kpi:cargo:space:plan')")
public AjaxResult getDenseCargoSpacePlan(String warehouseId) {
return AjaxResult.success(kpiService.getDenseCargoSpacePlanData(warehouseId));
}
```
- [x] **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`
- [x] **Step 1: Add the dense-plan API client**
```javascript
export function getDenseChartData(query) {
return request({
url: '/kpi/denseCargoSpacePlan',
method: 'get',
params: query
})
}
```
- [x] **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.
```javascript
cellStyle(location) {
return {
gridColumn: String(Number(location.thePlatoon) + 1),
gridRow: String(27 - Number(location.theColumn))
}
}
```
- [x] **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.
```javascript
isDenseWarehouse() {
return String(this.queryParams.warehouseId) === '03'
}
```
- [x] **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`
- [x] **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.
- [x] **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.
- [x] **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**
```bash
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`
- [x] **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.
```vue
<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>
```
- [x] **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.
```javascript
columnLabels() {
return Array.from({ length: 24 }, (_, index) => 24 - index)
}
```
- [x] **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()`.
```scss
.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;
}
```
- [x] **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.