Files
mom-web/src/views/mes/production/material-requisition/MaterialRequisitionView.vue

458 lines
16 KiB
Vue
Raw Normal View History

2026-03-05 16:52:12 +08:00
<template>
<el-drawer
v-model="dialogVisible"
title="查看领料单"
direction="rtl"
size="100%"
:close-on-press-escape="true"
:destroy-on-close="true"
:append-to-body="true"
class="mobile-form-drawer"
>
<div class="mobile-form">
<!-- 基本信息 -->
<div class="mobile-form__section">
<div class="mobile-form__section-title">基本信息</div>
<div class="mobile-info-list">
<div class="mobile-info-row" v-for="item in schema" :key="item.field">
<span class="mobile-info-row__label">{{ item.label }}</span>
<span class="mobile-info-row__value">
{{ item.formatter ? item.formatter(detailData[item.field]) : (detailData[item.field] || '-') }}
</span>
</div>
</div>
</div>
2026-03-05 16:52:12 +08:00
<!-- 领料明细 -->
<div class="mobile-form__section">
<div class="mobile-form__section-title">领料明细</div>
<div class="mobile-item-list">
<div
v-for="(row, index) in detailData.items"
:key="index"
class="mobile-item-card"
>
<div class="mobile-item-card__header">
<span class="mobile-item-card__index">#{{ index + 1 }}</span>
<span class="mobile-item-card__name">{{ row.materialName || '未知物料' }}</span>
</div>
<div class="mobile-item-card__body">
<div class="mobile-item-card__info-row">
<span class="mobile-item-card__info-label">物料编码</span>
<span class="mobile-item-card__info-value">{{ row.materialCode || '-' }}</span>
</div>
<div class="mobile-item-card__info-row">
<span class="mobile-item-card__info-label">单位</span>
<span class="mobile-item-card__info-value">{{ row.unit || '-' }}</span>
</div>
<div class="mobile-item-card__info-row">
<span class="mobile-item-card__info-label">计划数量</span>
<span class="mobile-item-card__info-value">{{ row.planQuantity }}</span>
</div>
<div class="mobile-item-card__info-row">
<span class="mobile-item-card__info-label">实际数量</span>
<span class="mobile-item-card__info-value">{{ row.actualQuantity || '-' }}</span>
</div>
<div class="mobile-item-card__info-row">
<span class="mobile-item-card__info-label">仓库</span>
<span class="mobile-item-card__info-value">{{ row.warehouseName || '-' }}</span>
</div>
<div class="mobile-item-card__info-row">
<span class="mobile-item-card__info-label">过磅单号</span>
<span class="mobile-item-card__info-value">{{ row.no || '-' }}</span>
</div>
<div class="mobile-item-card__info-row" v-if="row.remark">
<span class="mobile-item-card__info-label">备注</span>
<span class="mobile-item-card__info-value">{{ row.remark }}</span>
</div>
</div>
<div class="mobile-item-card__footer" v-if="row.purchaseId">
<el-button size="small" @click="openWeighDetail(row.purchaseId)">查看过磅详情</el-button>
</div>
</div>
<div v-if="detailData.items.length === 0" class="mobile-empty-tip">
暂无领料明细
</div>
</div>
</div>
2026-03-05 16:52:12 +08:00
<!-- 底部操作按钮 -->
<div class="mobile-form__footer">
<el-button @click="dialogVisible = false"> </el-button>
</div>
</div>
</el-drawer>
2026-03-05 16:52:12 +08:00
<!-- 过磅单详情弹窗 -->
<el-drawer
v-model="weighDialogVisible"
title="过磅单详情"
direction="rtl"
size="100%"
:close-on-press-escape="true"
:destroy-on-close="true"
:append-to-body="true"
class="mobile-form-drawer"
>
<div class="mobile-form">
<!-- 基本信息 -->
<div class="mobile-form__section">
<div class="mobile-form__section-title">基本信息</div>
<div class="mobile-info-list">
<div class="mobile-info-row">
<span class="mobile-info-row__label">过磅单号</span>
<span class="mobile-info-row__value">{{ weighDetail?.no || '-' }}</span>
</div>
<div class="mobile-info-row">
<span class="mobile-info-row__label">入库状态</span>
<span class="mobile-info-row__value">
<el-tag :type="weighDetail?.inStatus === 1 ? 'success' : 'warning'" size="small">
{{ weighDetail?.inStatus === 1 ? '已入库' : '未入库' }}
</el-tag>
</span>
</div>
<div class="mobile-info-row">
<span class="mobile-info-row__label">产品</span>
<span class="mobile-info-row__value">{{ weighDetail?.productName || '-' }}</span>
</div>
<div class="mobile-info-row">
<span class="mobile-info-row__label">车牌</span>
<span class="mobile-info-row__value">{{ weighDetail?.vehicleNumber || '-' }}</span>
</div>
<div class="mobile-info-row">
<span class="mobile-info-row__label">毛重</span>
<span class="mobile-info-row__value">{{ weighDetail?.grossWeight != null ? weighDetail.grossWeight + ' kg' : '-' }}</span>
</div>
<div class="mobile-info-row">
<span class="mobile-info-row__label">皮重</span>
<span class="mobile-info-row__value">{{ weighDetail?.tareWeight != null ? weighDetail.tareWeight + ' kg' : '-' }}</span>
</div>
<div class="mobile-info-row">
<span class="mobile-info-row__label">净重</span>
<span class="mobile-info-row__value">{{ weighDetail?.netWeight != null ? weighDetail.netWeight + ' kg' : '-' }}</span>
</div>
<div class="mobile-info-row">
<span class="mobile-info-row__label">计划重量</span>
<span class="mobile-info-row__value">{{ weighDetail?.plannedWeight != null ? weighDetail.plannedWeight + ' kg' : '-' }}</span>
</div>
<div class="mobile-info-row">
<span class="mobile-info-row__label">杂质率</span>
<span class="mobile-info-row__value">{{ weighDetail?.impurityRate != null ? (weighDetail.impurityRate * 100).toFixed(2) + '%' : '-' }}</span>
</div>
<div class="mobile-info-row">
<span class="mobile-info-row__label">供应商</span>
<span class="mobile-info-row__value">{{ weighDetail?.supplierName || '-' }}</span>
</div>
<div class="mobile-info-row">
<span class="mobile-info-row__label">司机</span>
<span class="mobile-info-row__value">{{ weighDetail?.driver || '-' }}</span>
</div>
<div class="mobile-info-row">
<span class="mobile-info-row__label">管理员</span>
<span class="mobile-info-row__value">{{ weighDetail?.administrator || '-' }}</span>
</div>
<div class="mobile-info-row">
<span class="mobile-info-row__label">过磅员</span>
<span class="mobile-info-row__value">{{ weighDetail?.weigher || '-' }}</span>
</div>
<div class="mobile-info-row" v-if="weighDetail?.fileUrl">
<span class="mobile-info-row__label">附件</span>
<span class="mobile-info-row__value"><a :href="weighDetail.fileUrl" target="_blank">查看附件</a></span>
</div>
<div class="mobile-info-row" v-if="weighDetail?.remark">
<span class="mobile-info-row__label">备注</span>
<span class="mobile-info-row__value">{{ weighDetail.remark }}</span>
</div>
<div class="mobile-info-row">
<span class="mobile-info-row__label">创建时间</span>
<span class="mobile-info-row__value">{{ weighDetail?.createTime ? formatDate(weighDetail.createTime) : '-' }}</span>
</div>
</div>
</div>
2026-03-05 16:52:12 +08:00
<!-- 检验信息部分 - 仅当有检验数据时显示 -->
<div class="mobile-form__section" v-if="hasInspectionData">
<div class="mobile-form__section-title">检验信息</div>
<div class="mobile-info-list">
<div class="mobile-info-row">
<span class="mobile-info-row__label">取样日期</span>
<span class="mobile-info-row__value">{{ weighDetail?.sampleDate ? formatDate(weighDetail.sampleDate) : '-' }}</span>
</div>
<div class="mobile-info-row">
<span class="mobile-info-row__label">取样地点</span>
<span class="mobile-info-row__value">{{ weighDetail?.sampleLocation || '-' }}</span>
</div>
<div class="mobile-info-row">
<span class="mobile-info-row__label">代表重量</span>
<span class="mobile-info-row__value">{{ weighDetail?.representativeWeight != null ? weighDetail.representativeWeight + ' kg' : '-' }}</span>
</div>
<div class="mobile-info-row">
<span class="mobile-info-row__label">样品重量</span>
<span class="mobile-info-row__value">{{ weighDetail?.sampleWeight != null ? weighDetail.sampleWeight + ' kg' : '-' }}</span>
</div>
<div class="mobile-info-row">
<span class="mobile-info-row__label">杂质重量</span>
<span class="mobile-info-row__value">{{ weighDetail?.impurityWeight != null ? weighDetail.impurityWeight + ' kg' : '-' }}</span>
</div>
<div class="mobile-info-row">
<span class="mobile-info-row__label">沙土重量</span>
<span class="mobile-info-row__value">{{ weighDetail?.sandWeight != null ? weighDetail.sandWeight + ' kg' : '-' }}</span>
</div>
<div class="mobile-info-row">
<span class="mobile-info-row__label">感官</span>
<span class="mobile-info-row__value">{{ weighDetail?.sensoryEvaluation || '-' }}</span>
</div>
<div class="mobile-info-row">
<span class="mobile-info-row__label">合格率</span>
<span class="mobile-info-row__value">{{ weighDetail?.qualificationRate ? weighDetail.qualificationRate + '%' : '-' }}</span>
</div>
<div class="mobile-info-row">
<span class="mobile-info-row__label">水分</span>
<span class="mobile-info-row__value">{{ weighDetail?.moistureContent ? weighDetail.moistureContent + '%' : '-' }}</span>
</div>
<div class="mobile-info-row">
<span class="mobile-info-row__label">含糖</span>
<span class="mobile-info-row__value">{{ weighDetail?.sugarContent ? weighDetail.sugarContent + '%' : '-' }}</span>
</div>
<div class="mobile-info-row">
<span class="mobile-info-row__label">RA值</span>
<span class="mobile-info-row__value">{{ weighDetail?.raValue || '-' }}</span>
</div>
<div class="mobile-info-row">
<span class="mobile-info-row__label">STV值</span>
<span class="mobile-info-row__value">{{ weighDetail?.stvValue || '-' }}</span>
</div>
<div class="mobile-info-row">
<span class="mobile-info-row__label">化验员</span>
<span class="mobile-info-row__value">{{ weighDetail?.labTechnician || '-' }}</span>
</div>
<div class="mobile-info-row" v-if="weighDetail?.inspectionRemark">
<span class="mobile-info-row__label">检验备注</span>
<span class="mobile-info-row__value">{{ weighDetail.inspectionRemark }}</span>
</div>
</div>
</div>
<div class="mobile-form__footer">
<el-button @click="weighDialogVisible = false" style="width: 100%"> </el-button>
</div>
</div>
</el-drawer>
2026-03-05 16:52:12 +08:00
</template>
<script setup lang="ts">
import { ref, computed } from 'vue'
import { getMaterialRequisition } from '@/api/mes/production/material-requisition'
import { formatDate } from '@/utils/formatTime'
import { Icon } from '@/components/Icon'
import { WeighApi } from '@/api/erp/purchase/weigh'
const dialogVisible = ref(false)
const detailData = ref<any>({
items: []
})
const weighDialogVisible = ref(false)
const weighDetail = ref<any>(null)
// 判断是否有检验数据
const hasInspectionData = computed(() => {
if (!weighDetail.value) return false
return !!(
weighDetail.value.sampleDate ||
weighDetail.value.sampleLocation ||
weighDetail.value.representativeWeight ||
weighDetail.value.sampleWeight ||
weighDetail.value.impurityWeight ||
weighDetail.value.sandWeight ||
weighDetail.value.sensoryEvaluation ||
weighDetail.value.qualificationRate ||
weighDetail.value.moistureContent ||
weighDetail.value.sugarContent ||
weighDetail.value.raValue ||
weighDetail.value.stvValue ||
weighDetail.value.labTechnician ||
weighDetail.value.inspectionRemark
)
})
const schema = [
{
label: '领料单号',
field: 'code'
},
{
label: '工单编号',
field: 'orderCode'
},
{
label: '领料时间',
field: 'requisitionTime',
formatter: (val: string) => (val ? formatDate(val) : '')
},
{
label: '状态',
field: 'status',
formatter: (val: number) => {
const statusMap: Record<number, string> = {
0: '草稿',
1: '待审核',
2: '已审核',
3: '已领料',
4: '已取消'
}
return statusMap[val] || '未知'
}
},
{
label: '申请人',
field: 'applicantName'
},
{
label: '审批人',
field: 'approverName'
},
{
label: '备注',
field: 'remark'
},
{
label: '创建时间',
field: 'createTime',
formatter: (val: string) => (val ? formatDate(val) : '')
}
]
const open = async (id: number) => {
dialogVisible.value = true
const res = await getMaterialRequisition(id)
detailData.value = res
}
const openWeighDetail = async (purchaseId: number) => {
try {
const res: any = await WeighApi.getWeigh(purchaseId)
weighDetail.value = res?.data || res
weighDialogVisible.value = true
} catch (e) {
console.error('获取过磅单详情失败', e)
}
}
defineExpose({
open
})
</script>
<style lang="scss" scoped>
.mobile-form {
padding: 0 4px;
}
.mobile-form__section {
background: #fff;
border-radius: 10px;
padding: 14px;
margin-bottom: 12px;
box-shadow: 0 1px 4px rgba(0, 0, 0, 0.06);
}
.mobile-form__section-title {
font-size: 15px;
font-weight: 600;
color: #303133;
margin-bottom: 12px;
padding-bottom: 8px;
border-bottom: 1px solid #f0f0f0;
}
.mobile-form__footer {
position: sticky;
bottom: 0;
background: #fff;
padding: 12px 16px;
padding-bottom: calc(12px + constant(safe-area-inset-bottom));
padding-bottom: calc(12px + env(safe-area-inset-bottom));
border-top: 1px solid #eee;
display: flex;
justify-content: center;
z-index: 10;
margin: 0 -4px;
.el-button {
width: 100%;
height: 40px;
font-size: 15px;
}
}
.mobile-info-list {
font-size: 13px;
}
.mobile-info-row {
display: flex;
justify-content: space-between;
padding: 6px 0;
border-bottom: 1px solid #f5f5f5;
&:last-child { border-bottom: none; }
&__label { color: #909399; flex-shrink: 0; margin-right: 12px; }
&__value { color: #303133; text-align: right; }
}
.mobile-item-list {
display: flex;
flex-direction: column;
gap: 10px;
}
.mobile-item-card {
background: #f9f9fb;
border-radius: 8px;
padding: 12px;
border: 1px solid #ebeef5;
&__header {
display: flex;
align-items: center;
gap: 8px;
margin-bottom: 10px;
padding-bottom: 8px;
border-bottom: 1px solid #f0f0f0;
}
&__index {
font-size: 12px;
color: #909399;
font-weight: 600;
}
&__name {
flex: 1;
font-size: 14px;
font-weight: 600;
color: #303133;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
&__body {
font-size: 13px;
}
&__info-row {
display: flex;
justify-content: space-between;
padding: 4px 0;
}
&__info-label {
color: #909399;
flex-shrink: 0;
}
&__info-value {
color: #606266;
text-align: right;
}
&__footer {
margin-top: 10px;
padding-top: 10px;
border-top: 1px solid #f0f0f0;
}
}
.mobile-empty-tip {
text-align: center;
color: #909399;
padding: 20px 0;
font-size: 14px;
}
</style>