182 lines
8.2 KiB
Markdown
182 lines
8.2 KiB
Markdown
# 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.
|