diff --git a/web-admin/src/views/production/cell-product/index.vue b/web-admin/src/views/production/cell-product/index.vue
index 62406a9f..7a5d9589 100644
--- a/web-admin/src/views/production/cell-product/index.vue
+++ b/web-admin/src/views/production/cell-product/index.vue
@@ -471,6 +471,16 @@
入库明细
{{ productLinesHint }}
+
+
+
+ 复制首行属性
+
+
+
+ 批量填储物格
+
+
+
+
([createEmptyProductLine()])
+ const batchSlotFillVisible = ref(false)
+
+ const emptyStorageSlotLineCount = computed(
+ () => productLines.value.filter((l) => !String(l.storageSlotId || '').trim()).length
+ )
+
+ const formUsedStorageSlotIds = computed(() =>
+ productLines.value.map((l) => l.storageSlotId).filter((id) => String(id || '').trim())
+ )
+
+ function handleCopyFirstLineAttrs() {
+ const r = copyFirstProductLineAttrs(productLines.value)
+ if (!r.ok) {
+ ElMessage.warning(r.message)
+ return
+ }
+ ElMessage.success(`已将首行属性复制到其余 ${r.filledCount} 行`)
+ }
+
+ function openBatchSlotFill() {
+ if (emptyStorageSlotLineCount.value <= 0) {
+ ElMessage.warning('没有可填充的空行')
+ return
+ }
+ batchSlotFillVisible.value = true
+ }
+
+ function onBatchSlotFilled(payload: {
+ slotIds: string[]
+ options: Array<{ id: string; name: string; facilityNodeId?: string }>
+ }) {
+ const n = applySlotIdsToEmptyLines(productLines.value, payload.slotIds)
+ storageSlotOptions.value = ensureStorageSlotsInOptions(
+ storageSlotOptions.value,
+ payload.options
+ )
+ ElMessage.success(`已为 ${n} 行填充储物格`)
+ }
const formRules = {
productCode: [{ required: true, message: '请输入产品编码', trigger: 'blur' }],
@@ -1874,7 +1936,7 @@
.product-lines-head {
display: flex;
- align-items: baseline;
+ align-items: center;
flex-wrap: wrap;
gap: 8px;
margin-bottom: 10px;
@@ -1886,6 +1948,13 @@
color: var(--mint-text, #334155);
}
+ .product-lines-actions {
+ display: flex;
+ flex-wrap: wrap;
+ gap: 8px;
+ margin-left: auto;
+ }
+
.product-lines-table {
width: 100%;
}