This commit is contained in:
zlwu committed 2026-06-16 15:17:32 +08:00
1 parent 4f24d3b687
commit 1ff73b9a74
202 files changed
+11989 -10045

No files matched your search

@@ -429,116 +429,195 @@
<el-dialog
v-model="occupancyDialogVisible"
:title="occupancyDialogTitle"
width="920px"
top="5vh"
class="dialog-form-layout"
width="1280px"
class="dialog-form-layout storage-occupancy-dialog"
align-center
append-to-body
modal-class="protocol-dialog-mask"
destroy-on-close
>
<el-tabs v-model="occupancyActiveTab">
<el-tabs v-model="occupancyActiveTab" class="storage-occupancy-tabs">
<el-tab-pane label="在库物品" name="stored">
<div class="occupancy-toolbar">
<el-button
v-if="occupancyTotal === 0"
type="primary"
size="small"
@click="handleOpenStoreDialog"
>
入库
</el-button>
<span v-else class="occupancy-full-tip">该储物格已有物品在库,一格只能存放一个物品</span>
<div class="list-toolbar occupancy-list-toolbar">
<div class="list-toolbar-row">
<el-button
v-if="occupancyTotal === 0"
class="btn-main"
type="primary"
@click="handleOpenStoreDialog"
>
<el-icon><Plus /></el-icon>
入库
</el-button>
<span v-else class="occupancy-full-tip">该储物格已有物品在库,一格只能存放一个物品</span>
</div>
</div>
<el-table
:data="occupancyList"
v-loading="occupancyLoading"
size="small"
max-height="360"
>
<el-table-column type="index" label="序号" min-width="60" />
<el-table-column label="物品类型" min-width="120">
<template #default="{ row }">
<el-tag :type="row.itemType === 'cell_product' ? 'primary' : 'info'" size="small">
{{ row.itemType === 'cell_product' ? '细胞产品' : '其他' }}
</el-tag>
</template>
</el-table-column>
<el-table-column prop="itemCode" label="物品编码" min-width="140" />
<el-table-column prop="itemName" label="物品名称" min-width="140" />
<el-table-column label="来源" min-width="120">
<template #default="{ row }">
{{
{ production: '生产入库', manual: '手动入库', transfer: '转移' }[
row.itemSource
] || row.itemSource
}}
</template>
</el-table-column>
<el-table-column prop="storedAt" label="入库时间" min-width="170" />
<el-table-column label="操作" min-width="80" fixed="right">
<template #default="{ row }">
<el-button type="danger" link size="small" @click="handleRemoveOccupancy(row)">
出库
</el-button>
</template>
</el-table-column>
</el-table>
<div v-if="occupancyTotal > occupancyPageSize" class="occupancy-pagination">
<el-pagination
small
layout="total, prev, pager, next"
:total="occupancyTotal"
:page-size="occupancyPageSize"
v-model:current-page="occupancyPage"
@current-change="loadOccupancies"
/>
<div class="list-body list-wrap view-inner-table-wrap">
<el-table
class="list-table inner-table"
:data="occupancyList"
v-loading="occupancyLoading"
stripe
row-key="id"
empty-text="暂无在库物品"
>
<el-table-column
type="index"
label="序号"
min-width="68"
align="center"
header-align="center"
:index="(index) => (occupancyPage - 1) * occupancyPageSize + index + 1"
/>
<el-table-column label="物品类型" min-width="120" align="center" header-align="center">
<template #default="{ row }">
<el-tag :type="row.itemType === 'cell_product' ? 'primary' : 'info'" size="small">
{{ row.itemType === 'cell_product' ? '细胞产品' : '其他' }}
</el-tag>
</template>
</el-table-column>
<el-table-column
prop="itemCode"
label="物品编码"
min-width="140"
align="center"
header-align="center"
/>
<el-table-column
prop="itemName"
label="物品名称"
min-width="140"
align="center"
header-align="center"
show-overflow-tooltip
/>
<el-table-column label="来源" min-width="120" align="center" header-align="center">
<template #default="{ row }">
{{
{ production: '生产入库', manual: '手动入库', transfer: '转移' }[
row.itemSource
] || row.itemSource
}}
</template>
</el-table-column>
<el-table-column
prop="storedAt"
label="入库时间"
min-width="170"
align="center"
header-align="center"
/>
<el-table-column
label="操作"
min-width="120"
fixed="right"
align="center"
header-align="center"
>
<template #default="{ row }">
<div style="display: flex; justify-content: center; gap: 8px">
<el-button class="btn-op-item" @click="handleRemoveOccupancy(row)">
<el-icon><Top /></el-icon>出库
</el-button>
</div>
</template>
</el-table-column>
</el-table>
<div class="pagination list-pager-bar">
<el-pagination
:current-page="occupancyPage"
:page-size="occupancyPageSize"
:total="occupancyTotal"
layout="total, prev, pager, next"
@current-change="(val) => ((occupancyPage = val), loadOccupancies())"
/>
</div>
</div>
</el-tab-pane>
<el-tab-pane label="出入库历史" name="history">
<el-table :data="historyList" v-loading="historyLoading" size="small" max-height="400">
<el-table-column type="index" label="序号" min-width="60" />
<el-table-column label="物品类型" min-width="120">
<template #default="{ row }">
<el-tag :type="row.itemType === 'cell_product' ? 'primary' : 'info'" size="small">
{{ row.itemType === 'cell_product' ? '细胞产品' : '其他' }}
</el-tag>
</template>
</el-table-column>
<el-table-column prop="itemCode" label="物品编码" min-width="120" />
<el-table-column prop="itemName" label="物品名称" min-width="120" />
<el-table-column label="来源" min-width="100">
<template #default="{ row }">
{{
{ production: '生产入库', manual: '手动入库', transfer: '转移' }[
row.itemSource
] || row.itemSource
}}
</template>
</el-table-column>
<el-table-column prop="storedAt" label="入库时间" min-width="170" />
<el-table-column prop="removedAt" label="出库时间" min-width="170" />
<el-table-column label="状态" min-width="100">
<template #default="{ row }">
<el-tag
:type="row.occupancyStatus === 'stored' ? 'success' : 'warning'"
size="small"
>
{{ row.occupancyStatus === 'stored' ? '在库' : '已出库' }}
</el-tag>
</template>
</el-table-column>
</el-table>
<div v-if="historyTotal > historyPageSize" class="occupancy-pagination">
<el-pagination
small
layout="total, prev, pager, next"
:total="historyTotal"
:page-size="historyPageSize"
v-model:current-page="historyPage"
@current-change="loadHistory"
/>
<div class="list-body list-wrap view-inner-table-wrap">
<el-table
class="list-table inner-table"
:data="historyList"
v-loading="historyLoading"
stripe
row-key="id"
empty-text="暂无出入库历史"
>
<el-table-column
type="index"
label="序号"
min-width="68"
align="center"
header-align="center"
:index="(index) => (historyPage - 1) * historyPageSize + index + 1"
/>
<el-table-column label="物品类型" min-width="120" align="center" header-align="center">
<template #default="{ row }">
<el-tag :type="row.itemType === 'cell_product' ? 'primary' : 'info'" size="small">
{{ row.itemType === 'cell_product' ? '细胞产品' : '其他' }}
</el-tag>
</template>
</el-table-column>
<el-table-column
prop="itemCode"
label="物品编码"
min-width="140"
align="center"
header-align="center"
/>
<el-table-column
prop="itemName"
label="物品名称"
min-width="140"
align="center"
header-align="center"
show-overflow-tooltip
/>
<el-table-column label="来源" min-width="120" align="center" header-align="center">
<template #default="{ row }">
{{
{ production: '生产入库', manual: '手动入库', transfer: '转移' }[
row.itemSource
] || row.itemSource
}}
</template>
</el-table-column>
<el-table-column
prop="storedAt"
label="入库时间"
min-width="170"
align="center"
header-align="center"
/>
<el-table-column
prop="removedAt"
label="出库时间"
min-width="170"
align="center"
header-align="center"
/>
<el-table-column label="状态" min-width="100" align="center" header-align="center">
<template #default="{ row }">
<el-tag
:type="row.occupancyStatus === 'stored' ? 'success' : 'warning'"
size="small"
>
{{ row.occupancyStatus === 'stored' ? '在库' : '已出库' }}
</el-tag>
</template>
</el-table-column>
</el-table>
<div class="pagination list-pager-bar">
<el-pagination
:current-page="historyPage"
:page-size="historyPageSize"
:total="historyTotal"
layout="total, prev, pager, next"
@current-change="(val) => ((historyPage = val), loadHistory())"
/>
</div>
</div>
</el-tab-pane>
@@ -576,11 +655,12 @@
</el-form>
<div class="occupancy-slot-save-bar">
<el-button
class="btn-main"
type="primary"
size="small"
:loading="occupancySlotSaving"
@click="handleOccupancySlotSave"
>
<el-icon><Check /></el-icon>
保存
</el-button>
</div>
@@ -635,7 +715,7 @@
<script setup lang="ts">
import { ElMessage, ElMessageBox } from 'element-plus'
import { Plus, Close, Check } from '@element-plus/icons-vue'
import { Plus, Close, Check, Top } from '@element-plus/icons-vue'
import {
fetchStorageFacilityList,
fetchCreateStorageFacility,
@@ -1678,14 +1758,14 @@
}
.shelf-label {
width: 28px;
width: 36px;
flex-shrink: 0;
background: #ea580c;
color: #fff;
display: flex;
align-items: center;
justify-content: center;
font-size: 12px;
font-size: 14px;
font-weight: 600;
border-radius: 4px 0 0 4px;
}
@@ -1693,12 +1773,12 @@
.shelf-cells {
display: flex;
flex-wrap: wrap;
gap: 4px;
gap: 6px;
}
.shelf-cell {
width: 40px;
height: 40px;
width: 80px;
height: 80px;
border: 1px solid #fed7aa;
display: flex;
flex-direction: column;
@@ -1739,7 +1819,7 @@
}
.add-icon {
font-size: 20px;
font-size: 32px;
color: #fb923c;
line-height: 1;
}
@@ -1754,14 +1834,14 @@
position: absolute;
top: 0;
right: 0;
width: 14px;
height: 14px;
width: 22px;
height: 22px;
border: none;
border-radius: 0 4px 0 4px;
background: rgba(245, 108, 108, 0.85);
color: #fff;
font-size: 10px;
line-height: 14px;
font-size: 14px;
line-height: 22px;
text-align: center;
cursor: pointer;
padding: 0;
@@ -1779,24 +1859,25 @@
}
.cell-code {
font-size: 10px;
font-size: 12px;
font-weight: 600;
color: #303133;
text-align: center;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
max-width: 34px;
max-width: 72px;
padding: 0 4px;
}
.cell-badge {
position: absolute;
top: 2px;
right: 2px;
min-width: 16px;
height: 16px;
line-height: 16px;
font-size: 10px;
top: 4px;
right: 4px;
min-width: 20px;
height: 20px;
line-height: 20px;
font-size: 11px;
text-align: center;
color: #fff;
background: #f56c6c;
@@ -1804,8 +1885,10 @@
padding: 0 4px;
}
.occupancy-toolbar {
.occupancy-list-toolbar {
margin-bottom: 12px;
padding-bottom: 0;
border-bottom: none;
}
.occupancy-full-tip {
@@ -1813,15 +1896,59 @@
color: var(--mint-text-muted, #64748b);
}
.occupancy-pagination {
margin-top: 12px;
display: flex;
justify-content: flex-end;
:deep(.el-dialog.storage-occupancy-dialog) {
min-height: min(720px, calc(100vh - 100px));
}
.storage-occupancy-tabs {
:deep(.el-tabs__content) {
min-height: 520px;
}
}
.view-inner-table-wrap.list-body.list-wrap {
margin-top: 0;
border: 1px solid var(--mint-border, #e2e8f0);
border-radius: var(--mint-radius, 10px);
overflow: hidden;
background: #fff;
:deep(.el-table) {
--el-table-header-bg-color: var(--mint-table-head, #f8fafc);
--el-table-border-color: var(--mint-border, #e2e8f0);
--el-table-row-hover-bg-color: var(--mint-row-hover, #f0fdf4);
--el-table-text-color: var(--mint-text, #0f172a);
--el-table-header-text-color: var(--mint-text-muted, #64748b);
font-size: 14px;
}
:deep(.el-table th.el-table__cell) {
font-size: 12px;
font-weight: 600;
color: var(--mint-text-muted, #64748b);
}
:deep(.el-table td.el-table__cell) {
font-size: 14px;
font-weight: 500;
color: var(--mint-text, #0f172a);
}
:deep(.el-empty) {
padding: 24px 0;
}
.pagination.list-pager-bar {
display: flex;
justify-content: flex-end;
}
}
.occupancy-slot-save-bar {
margin-top: 24px;
padding-top: 16px;
border-top: 1px solid var(--el-border-color-lighter);
display: flex;
justify-content: flex-end;
}
</style>