product_control_client/docs/superpowers/plans/2026-03-27-coal-feeding-mot...

7.8 KiB

Coal Feeding Motor Grid Alignment 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: Update the motor sections in src/views/coalFeeding.vue so both 中间侧 and 回车侧 render motors two per row, with odd counts left-aligned, while keeping the left labels height-aligned with the right motor sections.

Architecture: Keep the existing block-based control-panel layout as the baseline. Add small computed helpers in coalFeeding.vue to calculate a shared minimum height for the middle and return motor sections, then apply that shared height to both the left labels and right motor containers. Replace the motor-item vertical stack with a two-column CSS grid wrapper while preserving all existing motor card interactions.

Tech Stack: Vue 3 <script setup lang="ts">, existing coalFeeding.vue local state, scoped CSS, Vite build verification


Task 1: Add Shared Motor Height Helpers

Files:

  • Modify: D:\testProjects\yaodaoxiangmu\vite_vue3_tsproject_change\src\views\coalFeeding.vue

  • Step 1: Add height constants near the existing control-panel helper functions

Insert these constants near getCellId, getTempDropId, and isTimeRow so the motor section height calculation is explicit and easy to tune:

const MOTOR_GRID_COLUMNS = 2;
const MOTOR_SECTION_MIN_HEIGHT = 120;
const MOTOR_CARD_HEIGHT = 92;
const MOTOR_SECTION_VERTICAL_PADDING = 8;
const MOTOR_GRID_ROW_GAP = 8;
  • Step 2: Add helpers to calculate motor row counts and shared heights

Add these helpers below the constants so both left labels and right sections can consume the same height values:

const getMotorRowCount = (count: number) => {
  return Math.max(1, Math.ceil(count / MOTOR_GRID_COLUMNS));
};

const getMotorSectionHeight = (count: number) => {
  const rows = getMotorRowCount(count);
  const computedHeight =
    MOTOR_SECTION_VERTICAL_PADDING * 2 +
    rows * MOTOR_CARD_HEIGHT +
    (rows - 1) * MOTOR_GRID_ROW_GAP;

  return `${Math.max(MOTOR_SECTION_MIN_HEIGHT, computedHeight)}px`;
};

const middleMotorHeight = computed(() => {
  const maxCount = dataList.reduce((max, item) => Math.max(max, item.dianji.length), 0);
  return getMotorSectionHeight(maxCount);
});

const returnMotorHeight = computed(() => {
  const maxCount = dataList.reduce((max, item) => Math.max(max, item.dianji2.length), 0);
  return getMotorSectionHeight(maxCount);
});
  • Step 3: Import the missing Vue utility for computed values

Update the top Vue import so the new computed helpers are available:

import { computed, onMounted, onUnmounted, reactive, ref } from "vue";
  • Step 4: Run a quick search to confirm the new helper symbols exist once

Run: rg -n "MOTOR_GRID_COLUMNS|getMotorRowCount|middleMotorHeight|returnMotorHeight|computed" src\views\coalFeeding.vue

Expected: matches for the new constants/helpers and the updated Vue import in src\views\coalFeeding.vue

Task 2: Apply Shared Heights to Labels and Motor Sections

Files:

  • Modify: D:\testProjects\yaodaoxiangmu\vite_vue3_tsproject_change\src\views\coalFeeding.vue

  • Step 1: Bind the left motor labels to the shared section heights

Update the two left-side labels so they use the same computed heights as the corresponding right-side sections:

<div class="control-panel__label control-panel__label--motor" :style="{ minHeight: middleMotorHeight }">
  中间侧
</div>
<div class="control-panel__label control-panel__label--motor" :style="{ minHeight: returnMotorHeight }">
  回车侧
</div>
  • Step 2: Bind the right-side upper motor section to the middle motor height

Update the 中间侧 motor wrapper from a plain section cell into a shared-height container:

<div class="control-panel__cell control-panel__cell--motor" :style="{ minHeight: middleMotorHeight }">
  <div class="control-panel__motor-grid">
    <!-- existing dianji cards stay here -->
  </div>
</div>
  • Step 3: Bind the right-side lower motor section to the return motor height

Update the 回车侧 motor wrapper the same way:

<div class="control-panel__cell control-panel__cell--motor" :style="{ minHeight: returnMotorHeight }">
  <div class="control-panel__motor-grid">
    <!-- existing dianji2 cards stay here -->
  </div>
</div>

Task 3: Convert Motor Items to Two-Column Grid Layout

Files:

  • Modify: D:\testProjects\yaodaoxiangmu\vite_vue3_tsproject_change\src\views\coalFeeding.vue

  • Step 1: Wrap the upper motor cards in a dedicated grid container

Move the existing item.dianji loop inside a grid wrapper without changing the motor card internals:

<div class="control-panel__motor-grid">
  <div
    v-for="dj in item.dianji"
    :key="dj.id"
    :id="dj.id"
    class="control-panel__motor-card flexs flex_col items_center gap0_25 text_center dianji_status"
    @dragover="onDjDragOver"
    @drop="onDjDrop($event, dj, 'id')"
  >
    <!-- keep existing motor content and click handlers -->
  </div>
</div>
  • Step 2: Wrap the lower motor cards in the same grid container pattern

Apply the same grid wrapper to item.dianji2, keeping the existing click handler with the dianji2 motor key:

<div class="control-panel__motor-grid">
  <div
    v-for="dj in item.dianji2"
    :key="dj.id"
    class="control-panel__motor-card flexs flex_col items_center gap0_25 text_center dianji_status"
    @dragover="onDjDragOver"
    @drop="onDjDrop($event, dj, 'id')"
  >
    <!-- keep existing motor content and click handlers -->
  </div>
</div>
  • Step 3: Add the motor grid styles so cards render two per row

Append these scoped styles near the current control-panel CSS:

.control-panel__motor-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 8px;
  align-items: start;
  width: 100%;
}

.control-panel__motor-card {
  width: 100%;
  min-height: 92px;
}

This keeps odd counts left-aligned automatically because the final odd card occupies the first cell of the last grid row.

  • Step 4: Update the motor container styles to support top-aligned grid content

Refine the existing motor container style so the new grid aligns correctly:

.control-panel__cell--motor {
  min-height: 120px;
  background: #eff6ff;
  align-items: flex-start;
  justify-content: flex-start;
  padding: 8px;
}

Task 4: Verify Layout and Build

Files:

  • Modify: D:\testProjects\yaodaoxiangmu\vite_vue3_tsproject_change\src\views\coalFeeding.vue

  • Step 1: Run a selector scan to confirm the new motor-grid classes are present

Run: rg -n "control-panel__motor-grid|control-panel__motor-card|middleMotorHeight|returnMotorHeight" src\views\coalFeeding.vue

Expected: matches for the new template bindings, helper logic, and styles inside src\views\coalFeeding.vue

  • Step 2: Run the production build

Run: npm run build

Expected: Vite finishes successfully with no Vue template or TypeScript errors.

  • Step 3: Manually verify the refined motor layout

Open the page and confirm:

1. 中间侧 motors render two per row.
2. 回车侧 motors render two per row.
3. If a section has an odd motor count, the last motor stays on the left side of the final row.
4. The left labels for 中间侧 and 回车侧 stay height-aligned with the right motor blocks.
5. Existing motor click and drag behavior still works.
  • Step 4: Record completion status instead of committing

Because this workspace has no .git directory, do not run commit commands here. In the final handoff, report:

- build result
- motor grid conversion status
- left/right height alignment status
- interaction checks completed