|
|
@@ -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">
|
|
|
+ <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="sourceTypeTagType(row.sourceType)"
|
|
|
- size="small"
|
|
|
- >
|
|
|
+ <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 label="领用人" min-width="100" align="center" header-align="center">
|
|
|
+ <template #default="{ row }">{{ displayLogReceiver(row) }}</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 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="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
|
|
|
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;
|