This commit is contained in:
zlwu committed 2026-05-24 10:21:14 +08:00
1 parent 9a93140391
commit 2eb1807fe6
7 files changed
+326 -76

No files matched your search

@@ -146,6 +146,7 @@
<el-select v-model="logSearchForm.changeType" placeholder="全部" clearable>
<el-option label="入库" value="in" />
<el-option label="出库" value="out" />
<el-option label="生产扣减" value="use" />
</el-select>
</el-form-item>
<el-form-item label="时间范围">
@@ -162,7 +163,7 @@
</el-form-item>
</div>
<div class="filter-actions-row">
<span class="filter-hint">按耗材、变动类型和时间范围查询变动记录。</span>
<span class="filter-hint">按耗材编码/名称、变动类型和时间范围查询变动记录。</span>
<div class="filter-actions-end">
<el-button class="btn-ghost" @click="handleLogReset"><el-icon><RefreshLeft /></el-icon>重置</el-button>
<el-button class="btn-main" type="primary" @click="handleLogSearch"><el-icon><Search /></el-icon>搜索</el-button>
@@ -178,6 +179,7 @@
v-loading="logLoading"
stripe
row-key="id"
@row-dblclick="handleLogView"
>
<el-table-column
type="index"
@@ -191,8 +193,8 @@
<el-table-column prop="materialName" label="耗材名称" min-width="140" align="center" header-align="center" />
<el-table-column label="变动类型" min-width="100" align="center" header-align="center">
<template #default="{ row }">
<el-tag :type="getChangeTypeTagType(row.changeType)" size="small">
{{ getChangeTypeLabel(row.changeType) }}
<el-tag :type="getChangeTypeTagType(row)" size="small">
{{ getChangeTypeLabel(row) }}
</el-tag>
</template>
</el-table-column>
@@ -205,6 +207,12 @@
</el-table-column>
<el-table-column prop="stockBefore" label="变动前库存" min-width="120" align="center" header-align="center" />
<el-table-column prop="stockAfter" label="变动后库存" min-width="120" align="center" header-align="center" />
<el-table-column label="工单号" min-width="140" align="center" header-align="center">
<template #default="{ row }">{{ row.taskNo || '-' }}</template>
</el-table-column>
<el-table-column label="步骤名称" min-width="140" align="center" header-align="center">
<template #default="{ row }">{{ row.stepName || '-' }}</template>
</el-table-column>
<el-table-column label="来源类型" min-width="120" align="center" header-align="center">
<template #default="{ row }">
<el-tag :type="getSourceTagType(row.sourceType)" size="small">
@@ -212,23 +220,27 @@
</el-tag>
</template>
</el-table-column>
<el-table-column label="工单号" min-width="140" align="center" header-align="center">
<template #default="{ row }">{{ row.taskNo || '-' }}</template>
</el-table-column>
<el-table-column label="步骤名称" min-width="140" align="center" header-align="center">
<template #default="{ row }">{{ row.stepName || '-' }}</template>
</el-table-column>
<el-table-column label="领用人" min-width="100" align="center" header-align="center">
<template #default="{ row }">{{ row.receiver || '-' }}</template>
<template #default="{ row }">{{ displayLogReceiver(row) }}</template>
</el-table-column>
<el-table-column label="用途" min-width="120" align="center" header-align="center" show-overflow-tooltip>
<template #default="{ row }">{{ row.purpose || '-' }}</template>
<template #default="{ row }">{{ displayLogPurpose(row) }}</template>
</el-table-column>
<el-table-column label="领用时间" min-width="170" align="center" header-align="center">
<template #default="{ row }">{{ displayLogUseTime(row) }}</template>
</el-table-column>
<el-table-column prop="remark" label="备注" min-width="140" align="center" header-align="center" show-overflow-tooltip />
<el-table-column label="操作人" min-width="100" align="center" header-align="center">
<template #default="{ row }">{{ row.createByName || row.createBy || '-' }}</template>
</el-table-column>
<el-table-column prop="createTime" label="变动时间" min-width="170" align="center" header-align="center" />
<el-table-column label="操作" min-width="160" fixed="right" align="center" header-align="center">
<template #default="{ row }">
<el-button class="btn-op-item" @click="handleLogView(row)">
<el-icon><View /></el-icon>查看
</el-button>
</template>
</el-table-column>
</el-table>
<div class="pagination list-pager-bar">
<el-pagination
@@ -770,8 +782,8 @@
/>
<el-table-column label="变动类型" min-width="100" align="center" header-align="center">
<template #default="{ row }">
<el-tag :type="getChangeTypeTagType(row.changeType)" size="small">
{{ getChangeTypeLabel(row.changeType) }}
<el-tag :type="getChangeTypeTagType(row)" size="small">
{{ getChangeTypeLabel(row) }}
</el-tag>
</template>
</el-table-column>
@@ -832,6 +844,15 @@
code-label="耗材编码"
:sections="viewSections"
/>
<!-- 变动记录查看弹窗 -->
<SystemViewDialog
v-model:visible="logViewVisible"
:title="logViewRow?.materialName || '变动记录详情'"
:icon="Document"
:meta="logViewRow?.createTime || ''"
:sections="logViewSections"
/>
</section>
</div>
</template>
@@ -1015,20 +1036,101 @@
const logTableData = ref<any[]>([])
const logLoading = ref(false)
const logPagination = reactive({ page: 1, pageSize: 10, total: 0 })
const logViewVisible = ref(false)
const logViewRow = ref<any>(null)
// 变动类型/来源映射
function getChangeTypeLabel(changeType: string) {
if (changeType === 'in') return '入库'
if (changeType === 'use') return '出库'
return changeType || '-'
function isManualOutLogRow(row: { changeType?: string; sourceType?: string }) {
return row.sourceType === 'manual_out'
}
function getChangeTypeTagType(changeType: string) {
if (changeType === 'in') return 'success'
if (changeType === 'use') return 'warning'
function isStepUseLogRow(row: { changeType?: string; sourceType?: string }) {
return row.changeType === 'use' && row.sourceType === 'step_save'
}
function getChangeTypeLabel(row: { changeType?: string; sourceType?: string }) {
if (row.changeType === 'in') return '入库'
if (isManualOutLogRow(row)) return '出库'
if (isStepUseLogRow(row)) return '生产扣减'
if (row.changeType === 'use') return '出库'
return row.changeType || '-'
}
function getChangeTypeTagType(row: { changeType?: string; sourceType?: string }) {
if (row.changeType === 'in') return 'success'
if (isManualOutLogRow(row)) return 'warning'
if (isStepUseLogRow(row)) return 'primary'
if (row.changeType === 'use') return 'warning'
return 'info'
}
function displayLogReceiver(row: any) {
if (!isManualOutLogRow(row)) return '-'
return (row.receiver || '').trim() || '-'
}
function displayLogPurpose(row: any) {
if (!isManualOutLogRow(row)) return '-'
return (row.purpose || '').trim() || '-'
}
function displayLogUseTime(row: any) {
if (!isManualOutLogRow(row)) return '-'
return (row.useTime || row.createTime || '').trim() || '-'
}
const logViewSections = computed(() => {
if (!logViewRow.value) return []
const row = logViewRow.value
return [
{
title: '变动信息',
fields: [
{ label: '耗材编码', value: row.materialCode },
{ label: '耗材名称', value: row.materialName },
{
label: '变动类型',
value: getChangeTypeLabel(row),
tagType: getChangeTypeTagType(row) as 'success' | 'warning' | 'primary' | 'info'
},
{
label: '变动数量',
value: row.changeQty < 0 ? String(row.changeQty) : `+${row.changeQty}`
},
{ label: '变动前库存', value: String(row.stockBefore ?? 0) },
{ label: '变动后库存', value: String(row.stockAfter ?? 0) },
{ label: '工单号', value: row.taskNo || '-' },
{ label: '步骤名称', value: row.stepName || '-' },
{
label: '来源类型',
value: getSourceLabel(row.sourceType),
tagType: getSourceTagType(row.sourceType) as 'success' | 'warning' | 'primary' | 'info'
},
{
label: '领用人',
value: displayLogReceiver(row) === '-' ? '—' : displayLogReceiver(row)
},
{
label: '用途',
value: displayLogPurpose(row) === '-' ? '—' : displayLogPurpose(row)
},
{
label: '领用时间',
value: displayLogUseTime(row) === '-' ? '—' : displayLogUseTime(row)
},
{ label: '备注', value: row.remark || '—', span: true },
{ label: '操作人', value: row.createByName || row.createBy || '-' },
{ label: '变动时间', value: row.createTime || '—' }
]
}
]
})
function handleLogView(row: any) {
logViewRow.value = row
logViewVisible.value = true
}
function getSourceLabel(sourceType: string) {
if (sourceType === 'manual_in') return '手动入库'
if (sourceType === 'manual_out') return '手动出库'
@@ -1540,9 +1642,27 @@
watch(activeTab, (val) => {
if (val === 'logs') {
logPagination.page = 1
loadLogData()
}
})
watchDebounced(
logSearchForm,
() => {
if (activeTab.value !== 'logs') return
logPagination.page = 1
loadLogData()
},
{ debounce: 300, deep: true }
)
watch(logDateRange, () => {
if (activeTab.value !== 'logs') return
logPagination.page = 1
loadLogData()
})
// 输入检索条件时自动搜索(防抖 300ms)
watchDebounced(
searchForm,
+175 -51
View File
@@ -219,8 +219,9 @@
</el-form-item>
<el-form-item label="变动类型">
<el-select v-model="allLogFilter.changeType" placeholder="全部" clearable>
<el-option label="入库" value="in" />
<el-option label="出库" value="out" />
<el-option label="入库" value="in" />
<el-option label="出库" value="out" />
<el-option label="生产扣减" value="use" />
</el-select>
</el-form-item>
<el-form-item label="时间范围">
@@ -231,12 +232,13 @@
start-placeholder="开始日期"
end-placeholder="结束日期"
value-format="YYYY-MM-DD"
clearable
style="width: 100%"
/>
</el-form-item>
</div>
<div class="filter-actions-row">
<span class="filter-hint">按试剂编码/名称、变动类型、时间范围筛选。</span>
<span class="filter-hint">按试剂编码/名称、变动类型和时间范围查询变动记录。</span>
<div class="filter-actions-end">
<el-button class="btn-ghost" @click="handleAllLogReset"
><el-icon><RefreshLeft /></el-icon>重置</el-button
@@ -255,6 +257,8 @@
:data="allLogData"
v-loading="allLogLoading"
stripe
row-key="id"
@row-dblclick="handleAllLogView"
>
<el-table-column
type="index"
@@ -280,95 +284,86 @@
/>
<el-table-column label="变动类型" min-width="100" align="center" header-align="center">
<template #default="{ row }">
<el-tag
:type="row.changeType === 'in' ? 'success' : 'warning'"
size="small"
>
{{ row.changeType === 'in' ? '入库' : '出库' }}
<el-tag :type="getChangeTypeTagType(row)" size="small">
{{ getChangeTypeLabel(row) }}
</el-tag>
</template>
</el-table-column>
<el-table-column label="变动数量" min-width="100" align="center" header-align="center">
<el-table-column label="变动数量" min-width="120" align="center" header-align="center">
<template #default="{ row }">
<span :style="{ color: row.changeQty >= 0 ? '#10b981' : '#ef4444' }">
{{ row.changeQty >= 0 ? '+' : '' }}{{ row.changeQty }}
<span :class="row.changeQty < 0 ? 'qty-negative' : 'qty-positive'">
{{ row.changeQty < 0 ? row.changeQty : `+${row.changeQty}` }}
</span>
</template>
</el-table-column>
<el-table-column
prop="stockBefore"
label="变动前库存"
min-width="110"
min-width="120"
align="center"
header-align="center"
/>
<el-table-column
prop="stockAfter"
label="变动后库存"
min-width="110"
min-width="120"
align="center"
header-align="center"
/>
<el-table-column label="来源" min-width="100" align="center" header-align="center">
<template #default="{ row }">
<el-tag
:type="sourceTypeTagType(row.sourceType)"
size="small"
>
{{ sourceTypeLabel(row.sourceType) }}
</el-tag>
</template>
</el-table-column>
<el-table-column label="工单号" min-width="140" align="center" header-align="center">
<template #default="{ row }">{{ row.taskNo || '-' }}</template>
</el-table-column>
<el-table-column label="步骤名称" min-width="140" align="center" header-align="center">
<template #default="{ row }">{{ row.stepName || '-' }}</template>
</el-table-column>
<el-table-column
prop="receiver"
label="领用人"
min-width="100"
align="center"
header-align="center"
/>
<el-table-column
prop="purpose"
label="用途"
min-width="120"
align="center"
header-align="center"
show-overflow-tooltip
/>
<el-table-column label="来源类型" min-width="120" align="center" header-align="center">
<template #default="{ row }">
<el-tag :type="sourceTypeTagType(row.sourceType)" size="small">
{{ sourceTypeLabel(row.sourceType) }}
</el-tag>
</template>
</el-table-column>
<el-table-column label="领用人" min-width="100" align="center" header-align="center">
<template #default="{ row }">{{ displayLogReceiver(row) }}</template>
</el-table-column>
<el-table-column label="用途" min-width="120" align="center" header-align="center" show-overflow-tooltip>
<template #default="{ row }">{{ displayLogPurpose(row) }}</template>
</el-table-column>
<el-table-column label="领用时间" min-width="170" align="center" header-align="center">
<template #default="{ row }">{{ displayLogUseTime(row) }}</template>
</el-table-column>
<el-table-column
prop="remark"
label="备注"
min-width="120"
min-width="140"
align="center"
header-align="center"
show-overflow-tooltip
/>
<el-table-column
prop="createByName"
label="操作人"
min-width="100"
align="center"
header-align="center"
/>
<el-table-column label="操作人" min-width="100" align="center" header-align="center">
<template #default="{ row }">{{ row.createByName || row.createBy || '-' }}</template>
</el-table-column>
<el-table-column
prop="createTime"
label="操作时间"
min-width="180"
label="变动时间"
min-width="170"
align="center"
header-align="center"
/>
<el-table-column label="操作" min-width="160" fixed="right" align="center" header-align="center">
<template #default="{ row }">
<el-button class="btn-op-item" @click="handleAllLogView(row)">
<el-icon><View /></el-icon>查看
</el-button>
</template>
</el-table-column>
</el-table>
<div class="pagination list-pager-bar">
<el-pagination
:current-page="allLogPagination.page"
:page-size="allLogPagination.pageSize"
:total="allLogPagination.total"
:page-sizes="[10, 20, 50]"
:page-sizes="[10, 20, 50, 100]"
layout="total, sizes, prev, pager, next"
@size-change="
(val) => ((allLogPagination.page = 1), (allLogPagination.pageSize = val), loadAllLogs())
@@ -1059,6 +1054,15 @@
code-label="试剂编码"
:sections="viewSections"
/>
<!-- 变动记录查看弹窗 -->
<SystemViewDialog
v-model:visible="allLogViewVisible"
:title="allLogViewRow?.materialName || '变动记录详情'"
:icon="Document"
:meta="allLogViewRow?.createTime || ''"
:sections="allLogViewSections"
/>
</section>
</div>
</template>
@@ -1120,9 +1124,48 @@
const map: Record<string, string> = {
manual_in: 'success',
manual_out: 'warning',
step_save: 'info'
step_save: 'primary'
}
return (map[sourceType] || 'info') as 'success' | 'warning' | 'info'
return (map[sourceType] || 'info') as 'success' | 'warning' | 'primary' | 'info'
}
function isManualOutLogRow(row: { changeType?: string; sourceType?: string }) {
return row.sourceType === 'manual_out'
}
function isStepUseLogRow(row: { changeType?: string; sourceType?: string }) {
return row.changeType === 'use' && row.sourceType === 'step_save'
}
function getChangeTypeLabel(row: { changeType?: string; sourceType?: string }) {
if (row.changeType === 'in') return '入库'
if (isManualOutLogRow(row)) return '出库'
if (isStepUseLogRow(row)) return '生产扣减'
if (row.changeType === 'use') return '出库'
return row.changeType || '-'
}
function getChangeTypeTagType(row: { changeType?: string; sourceType?: string }) {
if (row.changeType === 'in') return 'success'
if (isManualOutLogRow(row)) return 'warning'
if (isStepUseLogRow(row)) return 'primary'
if (row.changeType === 'use') return 'warning'
return 'info'
}
function displayLogReceiver(row: any) {
if (!isManualOutLogRow(row)) return '-'
return (row.receiver || '').trim() || '-'
}
function displayLogPurpose(row: any) {
if (!isManualOutLogRow(row)) return '-'
return (row.purpose || '').trim() || '-'
}
function displayLogUseTime(row: any) {
if (!isManualOutLogRow(row)) return '-'
return (row.useTime || row.createTime || '').trim() || '-'
}
const activeTab = ref('list')
@@ -1278,6 +1321,60 @@
const allLogFilter = reactive({ keyword: '', changeType: '' })
const allLogDateRange = ref<string[] | null>(null)
const allLogPagination = reactive({ page: 1, pageSize: 10, total: 0 })
const allLogViewVisible = ref(false)
const allLogViewRow = ref<any>(null)
const allLogViewSections = computed(() => {
if (!allLogViewRow.value) return []
const row = allLogViewRow.value
return [
{
title: '变动信息',
fields: [
{ label: '试剂编码', value: row.materialCode },
{ label: '试剂名称', value: row.materialName },
{
label: '变动类型',
value: getChangeTypeLabel(row),
tagType: getChangeTypeTagType(row) as 'success' | 'warning' | 'primary' | 'info'
},
{
label: '变动数量',
value: row.changeQty < 0 ? String(row.changeQty) : `+${row.changeQty}`
},
{ label: '变动前库存', value: String(row.stockBefore ?? 0) },
{ label: '变动后库存', value: String(row.stockAfter ?? 0) },
{ label: '工单号', value: row.taskNo || '-' },
{ label: '步骤名称', value: row.stepName || '-' },
{
label: '来源类型',
value: sourceTypeLabel(row.sourceType),
tagType: sourceTypeTagType(row.sourceType)
},
{
label: '领用人',
value: displayLogReceiver(row) === '-' ? '—' : displayLogReceiver(row)
},
{
label: '用途',
value: displayLogPurpose(row) === '-' ? '—' : displayLogPurpose(row)
},
{
label: '领用时间',
value: displayLogUseTime(row) === '-' ? '—' : displayLogUseTime(row)
},
{ label: '备注', value: row.remark || '—', span: true },
{ label: '操作人', value: row.createByName || row.createBy || '-' },
{ label: '变动时间', value: row.createTime || '—' }
]
}
]
})
function handleAllLogView(row: any) {
allLogViewRow.value = row
allLogViewVisible.value = true
}
const handleSelectionChange = (rows: any[]) => {
selectedRows.value = rows
@@ -1805,6 +1902,23 @@
loadAllLogs()
}
})
watchDebounced(
allLogFilter,
() => {
if (activeTab.value !== 'stockLogs') return
allLogPagination.page = 1
loadAllLogs()
},
{ debounce: 300, deep: true }
)
watch(allLogDateRange, () => {
if (activeTab.value !== 'stockLogs') return
allLogPagination.page = 1
loadAllLogs()
})
// 输入检索条件时自动搜索(防抖 300ms)
watchDebounced(
searchForm,
@@ -1829,6 +1943,16 @@
}
}
.qty-positive {
color: var(--el-color-success);
font-weight: 500;
}
.qty-negative {
color: var(--el-color-danger);
font-weight: 500;
}
.reagent-batch-stock-dialog {
.batch-stock-move-head {
margin-bottom: 16px;