# Coal Feeding Layout 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:** Replace the right-side `<table>` in `src/views/coalFeeding.vue` with a block-based unit-column layout while preserving the current row/column visual structure and existing interactions.

**Architecture:** Keep all business state and handlers in `src/views/coalFeeding.vue`, but reorganize the right-side rendering around a fixed parameter label column plus horizontally scrollable unit columns. Use small in-file render configurations for upper rows, lower rows, and fixed-height visual blocks so the new block layout stays aligned with the former table structure.

**Tech Stack:** Vue 3 `<script setup lang="ts">`, existing CSS utility classes, `@opentiny/vue`, Vite build verification

---

### Task 1: Prepare In-File Layout Metadata

**Files:**
- Modify: `D:\testProjects\yaodaoxiangmu\vite_vue3_tsproject_change\src\views\coalFeeding.vue`

- [ ] **Step 1: Add typed row metadata for the upper and lower time-setting blocks**

Insert these constants near the existing type declarations in `src/views/coalFeeding.vue` so the new template can loop over block rows instead of repeating hard-coded table rows:

```ts
type TimeFieldKey =
  | "tmyxsds"
  | "tmtzsds"
  | "tmljsds"
  | "blyxsds"
  | "tmyxsdx"
  | "tmtzsdx"
  | "tmljsdx"
  | "blyxsdx";

type DisplayFieldKey =
  | "tmljsjs"
  | "tmljsjx"
  | "tempera1"
  | "tempera2"
  | "carNumber";

type BlockRowConfig = {
  key: TimeFieldKey | DisplayFieldKey;
  label: string;
  kind: "time" | "display";
  idPrefix?: string;
};

const upperBlockRows: BlockRowConfig[] = [
  { key: "tmyxsds", label: "投煤运行时间设定", kind: "time", idPrefix: "tmyxsds" },
  { key: "tmtzsds", label: "投煤停止时间设定", kind: "time", idPrefix: "tmtzsds" },
  { key: "tmljsds", label: "投煤累积时间设定", kind: "time", idPrefix: "tmljsds" },
  { key: "blyxsds", label: "布料运行时间设定", kind: "time", idPrefix: "blyxsds" },
  { key: "tmljsjs", label: "投煤累积时间", kind: "display", idPrefix: "tmljsjs" },
];

const lowerBlockRows: BlockRowConfig[] = [
  { key: "tmyxsdx", label: "投煤运行时间设定", kind: "time", idPrefix: "tmyxsdx" },
  { key: "tmtzsdx", label: "投煤停止时间设定", kind: "time", idPrefix: "tmtzsdx" },
  { key: "tmljsdx", label: "投煤累积时间设定", kind: "time", idPrefix: "tmljsdx" },
  { key: "blyxsdx", label: "布料运行时间设定", kind: "time", idPrefix: "blyxsdx" },
  { key: "tmljsjx", label: "投煤累积时间", kind: "display", idPrefix: "tmljsjx" },
];
```

- [ ] **Step 2: Add typed helpers for rendering ids and editable values**

Add these helpers below the row metadata so the template can render the new block layout without string duplication:

```ts
const getCellId = (prefix: string | undefined, index: number) => {
  return prefix ? `${prefix}${index}` : undefined;
};

const getTempDropId = (side: "tempera1" | "tempera2", item: any, index: number) => {
  return `${side}_unit${item.unit}_${index + 1}`;
};

const isTimeRow = (row: BlockRowConfig) => row.kind === "time";
```

- [ ] **Step 3: Run a quick type sanity scan before touching the template**

Run: `rg -n "upperBlockRows|lowerBlockRows|getCellId|getTempDropId|isTimeRow" src\views\coalFeeding.vue`

Expected: five matches for the newly added metadata/helpers, all inside `src/views\coalFeeding.vue`

### Task 2: Replace the Table Template With a Column Layout

**Files:**
- Modify: `D:\testProjects\yaodaoxiangmu\vite_vue3_tsproject_change\src\views\coalFeeding.vue`

- [ ] **Step 1: Replace the `<table>` wrapper with a block-based layout shell**

Replace the current `<table>` section with this outer structure inside the existing right-side panel container:

```vue
<div class="control-panel">
  <div class="control-panel__labels">
    <div class="control-panel__corner"></div>
    <div class="control-panel__section">
      <div
        v-for="row in upperBlockRows"
        :key="`upper-label-${row.key}`"
        class="control-panel__label control-panel__label--row"
      >
        {{ row.label }}
      </div>
      <div class="control-panel__label control-panel__label--motor">中间侧</div>
    </div>
    <div class="control-panel__label control-panel__label--temp">2侧温度</div>
    <div class="control-panel__label control-panel__label--car">车位号</div>
    <div class="control-panel__label control-panel__label--temp">1侧温度</div>
    <div class="control-panel__section">
      <div
        v-for="row in lowerBlockRows"
        :key="`lower-label-${row.key}`"
        class="control-panel__label control-panel__label--row"
      >
        {{ row.label }}
      </div>
      <div class="control-panel__label control-panel__label--motor">回车侧</div>
    </div>
  </div>

  <div class="control-panel__columns">
    <!-- unit columns render here -->
  </div>
</div>
```

- [ ] **Step 2: Render each unit as one vertical column**

Inside `control-panel__columns`, render one column per `dataList` item using this structure:

```vue
<div
  v-for="(item, index) in dataList"
  :key="item.team"
  class="control-panel__column"
>
  <div class="control-panel__column-header">
    <span class="inline_flex items_center justify_center h1_25 min_w_6 px0_375 rounded bg_primary text_primary_color fontw700 text_11">
      {{ item.team }}
    </span>
  </div>

  <div class="control-panel__section">
    <!-- upper rows -->
  </div>

  <div
    :id="getTempDropId('tempera2', item, index)"
    class="control-panel__cell control-panel__cell--temp"
    @dragover="onDjDragOver"
    @drop="onDjDrop($event, item, getTempDropId('tempera2', item, index))"
  >
    <span class="text_xs fontw700 min_w_2_25 text_right text_red">{{ item.tempera2 }}</span>
    <span> °C</span>
  </div>

  <div class="control-panel__cell control-panel__cell--car">
    <span class="inline_flex items_center justify_center h1_25 min_w_1_75 px0_375 rounded_md bg_primary text_primary_color my0_3 fontw700 text_sm shadow_sm">
      {{ item.carNumber }}
    </span>
  </div>

  <div
    :id="getTempDropId('tempera1', item, index)"
    class="control-panel__cell control-panel__cell--temp"
    @dragover="onDjDragOver"
    @drop="onDjDrop($event, item, getTempDropId('tempera1', item, index))"
  >
    <span class="text_xs fontw700 min_w_2_25 text_right text_red">{{ item.tempera1 }}</span>
    <span> °C</span>
  </div>

  <div class="control-panel__section">
    <!-- lower rows -->
  </div>
</div>
```

- [ ] **Step 3: Render the upper and lower time/display rows from metadata**

Use this pattern in both the upper and lower sections so editable rows and display rows remain consistent:

```vue
<div
  v-for="row in upperBlockRows"
  :key="`upper-${item.team}-${row.key}`"
  :id="getCellId(row.idPrefix, index)"
  class="control-panel__cell control-panel__cell--row"
>
  <span v-if="!isTimeRow(row) || item.statusAuto" class="px0_25 py0_125 text_center text_xs color_base">
    {{ item[row.key] }}
  </span>
  <input
    v-else
    v-model="item[row.key]"
    class="px0_25 py0_125 text_center text_xs color_base control-panel__input"
  />
</div>
```

For the lower section, switch `upperBlockRows` to `lowerBlockRows` and keep the same markup.

- [ ] **Step 4: Move the middle-side and return-side motor rendering into the new sections**

Render the motor groups as fixed-height cells so the old `中间侧` and `回车侧` rows become block elements:

```vue
<div class="control-panel__cell control-panel__cell--motor">
  <div
    v-for="dj in item.dianji"
    :id="dj.id"
    :key="dj.id"
    class="flexs flex_col items_center gap0_25 text_center dianji_status"
    @dragover="onDjDragOver"
    @drop="onDjDrop($event, dj, 'id')"
  >
    <!-- preserve existing motor inner markup and click handlers -->
  </div>
</div>
```

For the lower section, keep the same structure but iterate `item.dianji2` and continue calling `toggleDjStop(dj, item.team, item.statusAuto, 'dianji2')`.

### Task 3: Rebuild Styling for Alignment and Visual Parity

**Files:**
- Modify: `D:\testProjects\yaodaoxiangmu\vite_vue3_tsproject_change\src\views\coalFeeding.vue`

- [ ] **Step 1: Add block-layout container styles**

Append styles like these near the existing `<style>` block:

```css
.control-panel {
  display: flex;
  align-items: flex-start;
  min-width: max-content;
}

.control-panel__labels {
  flex: 0 0 132px;
}

.control-panel__columns {
  display: flex;
  align-items: flex-start;
}

.control-panel__column {
  min-width: 96px;
  border-right: 1px solid rgba(148, 163, 184, 0.6);
}
```

- [ ] **Step 2: Add fixed row heights so labels and unit cells stay aligned**

Add shared row classes to replace the natural table sizing:

```css
.control-panel__corner,
.control-panel__column-header {
  height: 42px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-bottom: 1px solid rgba(148, 163, 184, 0.6);
}

.control-panel__label--row,
.control-panel__cell--row {
  height: 42px;
}

.control-panel__label--temp,
.control-panel__cell--temp,
.control-panel__label--car,
.control-panel__cell--car {
  height: 42px;
}

.control-panel__label--motor,
.control-panel__cell--motor {
  min-height: 120px;
}
```

- [ ] **Step 3: Restore row backgrounds and dense control-panel styling**

Add styling hooks so the new block elements preserve the current visual categories:

```css
.control-panel__label,
.control-panel__cell {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0.25rem;
  border-bottom: 1px solid rgba(148, 163, 184, 0.6);
  background: #ffffff;
}

.control-panel__label--temp,
.control-panel__cell--temp {
  background: #fff1e8;
}

.control-panel__label--car,
.control-panel__cell--car {
  background: #dbeafe;
}

.control-panel__label--motor,
.control-panel__cell--motor {
  background: #eff6ff;
}

.control-panel__input {
  width: 6rem;
}
```

- [ ] **Step 4: Run a targeted selector scan to make sure the old `<table>` layout is gone**

Run: `rg -n "<table|<thead|<tbody|<tr|<td|<th" src\views\coalFeeding.vue`

Expected: no matches

### Task 4: Verify Build and Behavior

**Files:**
- Modify: `D:\testProjects\yaodaoxiangmu\vite_vue3_tsproject_change\src\views\coalFeeding.vue`

- [ ] **Step 1: Run the production build**

Run: `npm run build`

Expected: Vite build completes successfully and outputs the `dist` bundle without Vue template or TypeScript errors.

- [ ] **Step 2: Manually verify the right panel structure in the app**

Open the page and confirm:

```text
1. The right panel no longer uses a table layout.
2. The left parameter column remains visually aligned with each unit column.
3. Each unit column shows:
   - upper block
   - 2侧温度
   - 车位号
   - 1侧温度
   - lower block
4. 中间侧 and 回车侧 motor areas still render with the expected controls.
```

- [ ] **Step 3: Manually verify preserved interactions**

Confirm these behaviors still work:

```text
1. Auto mode shows text; manual mode shows inputs.
2. Clicking a motor still toggles stop/run state as before.
3. Temperature targets still accept drag-and-drop point binding.
4. Bottom manual/auto switch panel still renders and responds.
```

- [ ] **Step 4: Record completion status instead of committing**

Because this workspace currently has no `.git` directory, do not run commit commands here.
Instead, record completion by listing the verified items in the final handoff:

```text
- build result
- layout conversion status
- interaction checks completed
```
