feat: 新增托盘库存网格(任务6)
This commit is contained in:
@@ -0,0 +1,168 @@
|
||||
<script lang="ts" setup>
|
||||
import type { LmsStockingIvtApi } from '#/api/lms/stockingivt';
|
||||
|
||||
import { computed, ref } from 'vue';
|
||||
|
||||
import { useVbenModal } from '@vben/common-ui';
|
||||
|
||||
import { Spin, Tooltip } from 'antdv-next';
|
||||
|
||||
import { getPaperVehicleInventory } from '#/api/lms/stockingivt';
|
||||
|
||||
interface PalletCell {
|
||||
colNum: number;
|
||||
inventory?: LmsStockingIvtApi.PaperVehicleInventory;
|
||||
rowNum: number;
|
||||
}
|
||||
|
||||
const vehicleCode = ref('');
|
||||
const inventoryList = ref<LmsStockingIvtApi.PaperVehicleInventory[]>([]);
|
||||
const loading = ref(false);
|
||||
|
||||
const modalTitle = computed(() => `托盘 ${vehicleCode.value} 的库存`);
|
||||
const occupiedCount = computed(() => inventoryList.value.length);
|
||||
const cells = computed<PalletCell[]>(() => {
|
||||
const inventoryMap = new Map(
|
||||
inventoryList.value.map((item) => [`${item.rowNum}:${item.colNum}`, item]),
|
||||
);
|
||||
return Array.from({ length: 25 }, (_, index) => {
|
||||
const rowNum = Math.floor(index / 5) + 1;
|
||||
const colNum = (index % 5) + 1;
|
||||
return {
|
||||
colNum,
|
||||
inventory: inventoryMap.get(`${rowNum}:${colNum}`),
|
||||
rowNum,
|
||||
};
|
||||
});
|
||||
});
|
||||
|
||||
const [Modal, modalApi] = useVbenModal({
|
||||
footer: false,
|
||||
async onOpenChange(isOpen) {
|
||||
if (!isOpen) {
|
||||
vehicleCode.value = '';
|
||||
inventoryList.value = [];
|
||||
return;
|
||||
}
|
||||
const data = modalApi.getData<{ vehicleCode: string }>();
|
||||
if (!data?.vehicleCode) return;
|
||||
vehicleCode.value = data.vehicleCode;
|
||||
loading.value = true;
|
||||
try {
|
||||
inventoryList.value = await getPaperVehicleInventory(data.vehicleCode);
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Modal class="w-[900px] max-w-[96vw]" :title="modalTitle">
|
||||
<Spin :spinning="loading">
|
||||
<div class="px-3 pb-4">
|
||||
<div class="mb-4 flex justify-end gap-6 text-sm">
|
||||
<span>已占用 {{ occupiedCount }} / 25</span>
|
||||
<span>空位 {{ 25 - occupiedCount }}</span>
|
||||
</div>
|
||||
<div class="pallet-grid">
|
||||
<div></div>
|
||||
<div v-for="col in 5" :key="`header-${col}`" class="axis-label">
|
||||
列 {{ col }}
|
||||
</div>
|
||||
<template v-for="row in 5" :key="`row-${row}`">
|
||||
<div class="axis-label">行 {{ row }}</div>
|
||||
<Tooltip
|
||||
v-for="cell in cells.slice((row - 1) * 5, row * 5)"
|
||||
:key="`${cell.rowNum}-${cell.colNum}`"
|
||||
>
|
||||
<template #title>
|
||||
<div>位置:第 {{ cell.rowNum }} 行,第 {{ cell.colNum }} 列</div>
|
||||
<template v-if="cell.inventory">
|
||||
<div>物料编码:{{ cell.inventory.materialCode }}</div>
|
||||
<div>物料名称:{{ cell.inventory.materialName }}</div>
|
||||
<div>数量:{{ cell.inventory.qty }}</div>
|
||||
</template>
|
||||
<div v-else>空位</div>
|
||||
</template>
|
||||
<div :class="['pallet-cell', { occupied: cell.inventory }]">
|
||||
<template v-if="cell.inventory">
|
||||
<strong>{{ cell.inventory.materialCode }}</strong>
|
||||
<span>{{ cell.inventory.materialName }}</span>
|
||||
</template>
|
||||
<span v-else>空</span>
|
||||
</div>
|
||||
</Tooltip>
|
||||
</template>
|
||||
</div>
|
||||
<div class="mt-4 flex gap-6 text-sm text-gray-500">
|
||||
<span class="legend"><i class="legend-block occupied"></i>有物料(1 根)</span>
|
||||
<span class="legend"><i class="legend-block"></i>空位</span>
|
||||
</div>
|
||||
</div>
|
||||
</Spin>
|
||||
</Modal>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.pallet-grid {
|
||||
display: grid;
|
||||
grid-template-columns: 48px repeat(5, minmax(100px, 1fr));
|
||||
gap: 8px;
|
||||
align-items: stretch;
|
||||
}
|
||||
|
||||
.axis-label {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.pallet-cell {
|
||||
display: flex;
|
||||
min-height: 72px;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
overflow: hidden;
|
||||
padding: 8px;
|
||||
color: #999;
|
||||
text-align: center;
|
||||
border: 1px dashed #d9d9d9;
|
||||
border-radius: 6px;
|
||||
background: #fafafa;
|
||||
}
|
||||
|
||||
.pallet-cell.occupied {
|
||||
color: #1f1f1f;
|
||||
border: 1px solid #91caff;
|
||||
background: #e6f4ff;
|
||||
}
|
||||
|
||||
.pallet-cell span {
|
||||
max-width: 100%;
|
||||
overflow: hidden;
|
||||
font-size: 12px;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.legend {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.legend-block {
|
||||
width: 13px;
|
||||
height: 13px;
|
||||
margin-right: 6px;
|
||||
border: 1px dashed #d9d9d9;
|
||||
background: #fafafa;
|
||||
}
|
||||
|
||||
.legend-block.occupied {
|
||||
border: 1px solid #91caff;
|
||||
background: #e6f4ff;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user