9.7 KiB
Warehouse Paper Form Unification Phase 1 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: Make warehouse operation documents use one cohesive paper-form visual language, starting with the production-ledger controlled inbound forms that currently mix modern web controls into the paper sheet.
Architecture: Keep all business state, computed values, validation, and submit payloads in InventoryLedgerView.vue unchanged. Introduce paper-specific wrappers/classes around the existing controls so selectors, selected-lot tables, live summaries, remarks, and settle controls visually belong to the same document grid as the approved “客料入库单”. Avoid global restyling of .form-field, .double-field, .table-wrap, or shared controls used outside paper documents.
Tech Stack: Vue 3 SFC, Vite, project CSS in frontend/src/styles/main.css, Node built-in test runner.
File Structure
- Modify
frontend/src/views/InventoryLedgerView.vue: convert the generic warehouse drawer’s production-ledger controlled inbound branch to paper-specific markup while preserving existing bindings and branch conditions. - Modify
frontend/src/styles/main.css: add reusable paper document classes for control grids, inline summary rows, source-lot selector/table panels, and settle confirmation rows. - Modify
frontend/src/views/InventoryLedgerView.test.js: add regression coverage that production surplus/scrap inbound forms use the paper-specific classes and that the old naked modern classes are not the only visual contract.
Design Direction
- Aesthetic: “工业纸质单据”.
- Purpose: Support fast warehouse entry while making each operation feel like a formal business document, not a demo web form.
- Differentiation anchor: Thick ledger grid lines, label/value cells, stamped meta strips, and paper-native control panels.
- DFII: 13. Impact 4, fit 5, feasibility 5, performance 4, consistency risk 5. This is strong because it reuses the approved客料入库 visual system, but must be scoped to avoid touching unrelated app forms.
Task 1: Lock The Regression Tests
Files:
-
Modify:
frontend/src/views/InventoryLedgerView.test.js -
Read:
frontend/src/views/InventoryLedgerView.vue -
Read:
frontend/src/styles/main.css -
Step 1: Add paper-form assertions for production-ledger controlled inbound
Add a test that checks the generic drawer contains production-ledger paper classes and keeps the old branch visually wrapped:
it("wraps production-ledger controlled inbound forms in the shared paper control language", () => {
assert.match(source, /warehouse-paper-control-grid/);
assert.match(source, /warehouse-paper-source-lot-panel/);
assert.match(source, /warehouse-paper-source-lot-table/);
assert.match(source, /warehouse-paper-inline-summary/);
assert.match(source, /warehouse-paper-settle-panel/);
assert.match(source, /warehouse-paper-settle-toggle/);
assert.match(source, /warehouse-paper-settle-grid/);
assert.match(source, /warehouse-paper-settle-remark/);
assert.match(mainCss, /\.warehouse-document-section-grid > \.warehouse-paper-control-grid\s*\{[\s\S]*grid-column: 1 \/ -1;/);
assert.match(mainCss, /\.warehouse-paper-control-grid\s*\{[\s\S]*grid-template-columns: repeat\(4, minmax\(0, 1fr\)\);/);
assert.match(mainCss, /\.warehouse-paper-source-lot-table/);
assert.match(mainCss, /\.warehouse-paper-settle-toggle/);
});
- Step 2: Run the test and confirm it fails before implementation
Run:
cd frontend
node --test src/views/InventoryLedgerView.test.js
Expected before implementation: failure mentioning one or more missing warehouse-paper-* classes.
Task 2: Convert Production Controlled Inbound Markup
Files:
-
Modify:
frontend/src/views/InventoryLedgerView.vue -
Step 1: Replace the naked production work-order block
Replace the isProductionWorkOrderControlledInbound stack-form block with paper-grid fields:
<div v-if="isProductionWorkOrderControlledInbound" class="warehouse-paper-control-grid warehouse-paper-control-grid-compact">
<label class="warehouse-paper-field warehouse-paper-field-wide">
<span>{{ isReworkScrapInbound ? "返工工单" : "生产台账" }}</span>
<select v-model.number="genericForm.work_order_id" required @change="applyGenericWorkOrder">
<option disabled value="">{{ isReworkScrapInbound ? "请选择返工工单" : "请选择生产台账" }}</option>
<option v-for="workOrder in genericWorkOrderOptions" :key="workOrder.work_order_id" :value="workOrder.work_order_id">
{{ formatWorkOrderLedgerOption(workOrder, activeOperation?.bizType) }}
</option>
</select>
</label>
<template v-if="selectedGenericWorkOrder">
<article class="warehouse-paper-summary-card warehouse-paper-summary-card-wide">
<span>产品</span>
<strong>{{ selectedGenericWorkOrder.product_code }} · {{ selectedGenericWorkOrder.product_name }}</strong>
</article>
<article class="warehouse-paper-summary-card">
<span>材料库存批次号</span>
<strong>{{ selectedGenericWorkOrder.source_lot_summary || selectedGenericWorkOrder.material_lot_no || "-" }}</strong>
</article>
<article v-if="isProductionScrapInbound" class="warehouse-paper-summary-card">
<span>库外未闭环重量</span>
<strong>{{ formatWeight(selectedGenericWorkOrder.outside_weight_kg || selectedGenericWorkOrder.limits?.max_scrap_inbound_weight_kg) }}</strong>
</article>
<article v-if="isProductionSurplusInbound" class="warehouse-paper-summary-card">
<span>库外未闭环重量</span>
<strong>{{ formatWeight(selectedGenericWorkOrder.outside_weight_kg || selectedGenericWorkOrder.limits?.max_surplus_inbound_weight_kg) }}</strong>
</article>
</template>
</div>
- Step 2: Convert the core fields to a paper grid
Replace the main double-field and triple-field groups in the generic drawer with warehouse-paper-control-grid, using the existing exact conditions and v-models. Keep field order: item, warehouse, location, measure basis, weight, quantity, unit cost.
- Step 3: Wrap source-lot selector and tables in paper panels
Keep StockLotTagSelect unchanged, but place it inside:
<div v-if="usesGenericSourceLotSelector" class="warehouse-paper-source-lot-panel">
<div class="warehouse-paper-source-lot-heading">
<span>来源库存批次号</span>
<strong>{{ genericSourceLotSelectPlaceholder }}</strong>
</div>
<StockLotTagSelect ... />
</div>
For selected lot tables, keep the same columns and inputs but add warehouse-paper-source-lot-table to the wrapping table container so CSS can remove the ordinary web-card feel.
- Step 4: Convert summaries and settle controls
Replace inventory-live-summary display with warehouse-paper-inline-summary, and replace work-order-settle-panel / work-order-settle-toggle with paper-specific classes. Keep genericForm.settle_work_order, deviation values, and genericForm.settle_remark unchanged.
Task 3: Add Paper-Specific CSS
Files:
-
Modify:
frontend/src/styles/main.css -
Step 1: Add grid spanning rules
Add the new paper containers beside existing .warehouse-paper-grid rules:
.warehouse-document-section-grid > .warehouse-paper-control-grid,
.warehouse-document-section-grid > .warehouse-paper-source-lot-panel,
.warehouse-document-section-grid > .warehouse-paper-source-lot-table,
.warehouse-document-section-grid > .warehouse-paper-inline-summary,
.warehouse-document-section-grid > .warehouse-paper-settle-panel {
grid-column: 1 / -1;
}
- Step 2: Reuse approved paper field and summary cells
Make .warehouse-paper-control-grid visually match .warehouse-paper-grid, with four columns on desktop, two on tablet, and one on mobile. Make .warehouse-paper-control-grid-compact allow summary cards to live in the same grid.
- Step 3: Style selector/table/settle panels as document rows
Style:
.warehouse-paper-source-lot-panel
.warehouse-paper-source-lot-heading
.warehouse-paper-source-lot-table
.warehouse-paper-inline-summary
.warehouse-paper-settle-panel
.warehouse-paper-settle-toggle
.warehouse-paper-settle-grid
.warehouse-paper-settle-remark
They should use document borders, paper backgrounds, Songti/Simsun value text where appropriate, and no floating modern-card shadows.
Task 4: Verify
Files:
-
Test:
frontend/src/views/InventoryLedgerView.test.js -
Build:
frontend/package.json -
Step 1: Run focused view tests
Run:
cd frontend
node --test src/views/InventoryLedgerView.test.js
Expected: all tests pass.
- Step 2: Run production build
Run:
cd frontend
npm run build
Expected: Vite build succeeds. Existing chunk-size warning is acceptable if it remains the same non-blocking warning.
- Step 3: Browser verification
Open http://localhost:5173/inventory-ledger, then inspect:
- 原材料库 · 客料入库 remains unchanged and approved.
- 原材料库 · 生产余料入库 uses the same paper-grid visual language.
- The source-lot multi-select, selected-lot table, remark field, and “该批材料余料结单” no longer look like separate modern web cards pasted onto paper.
- Existing submit button and drawer behavior still work.
Self-Review
- Spec coverage: covers the user’s requested recommended approach by converting the most visible mixed-UI warehouse document first and creating reusable paper classes for subsequent warehouse forms.
- Placeholder scan: no TBD/TODO/implement-later placeholders.
- Type consistency: class names in tests, markup, and CSS use the same
warehouse-paper-*prefix.