first commit
This commit is contained in:
1246
src/views/mes/quality/productquality/components/QualityDialog.vue
Normal file
1246
src/views/mes/quality/productquality/components/QualityDialog.vue
Normal file
File diff suppressed because it is too large
Load Diff
898
src/views/mes/quality/productquality/index.vue
Normal file
898
src/views/mes/quality/productquality/index.vue
Normal file
@@ -0,0 +1,898 @@
|
||||
<template>
|
||||
<ContentWrap>
|
||||
<!-- 搜索表单 -->
|
||||
<el-form
|
||||
ref="searchFormRef"
|
||||
:model="searchForm"
|
||||
:inline="true"
|
||||
label-width="68px"
|
||||
class="-mb-15px"
|
||||
>
|
||||
<el-form-item label="产品名称" prop="productName">
|
||||
<el-input
|
||||
v-model="searchForm.productName"
|
||||
placeholder="请输入产品名称"
|
||||
clearable
|
||||
class="!w-240px"
|
||||
@keyup.enter="handleQuery"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="批次编号" prop="workOrderCode">
|
||||
<el-input
|
||||
v-model="searchForm.workOrderCode"
|
||||
placeholder="请输入批次编号"
|
||||
clearable
|
||||
class="!w-240px"
|
||||
@keyup.enter="handleQuery"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="质检状态" prop="status">
|
||||
<el-select
|
||||
v-model="searchForm.status"
|
||||
placeholder="请选择质检状态"
|
||||
clearable
|
||||
class="!w-240px"
|
||||
>
|
||||
<el-option label="待检" :value="0" />
|
||||
<el-option label="检验中" :value="1" />
|
||||
<el-option label="已完成" :value="2" />
|
||||
<el-option label="已入库" :value="3" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="是否合格" prop="qualified">
|
||||
<el-select
|
||||
v-model="searchForm.qualified"
|
||||
placeholder="请选择是否合格"
|
||||
clearable
|
||||
class="!w-240px"
|
||||
>
|
||||
<el-option label="合格" :value="1" />
|
||||
<el-option label="不合格" :value="0" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="质检时间" prop="inspectionTime">
|
||||
<el-date-picker
|
||||
v-model="searchForm.inspectionTime"
|
||||
type="daterange"
|
||||
range-separator="至"
|
||||
start-placeholder="开始日期"
|
||||
end-placeholder="结束日期"
|
||||
value-format="YYYY-MM-DD"
|
||||
class="!w-420px"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button @click="handleQuery">
|
||||
<Icon icon="ep:search" class="mr-[5px]" /> 搜索
|
||||
</el-button>
|
||||
<el-button @click="resetQuery">
|
||||
<Icon icon="ep:refresh" class="mr-[5px]" /> 重置
|
||||
</el-button>
|
||||
<el-button
|
||||
type="primary"
|
||||
plain
|
||||
@click="openDialog('create')"
|
||||
v-hasPermi="['mes:finished-product-quality:create']"
|
||||
>
|
||||
<Icon icon="ep:plus" class="mr-[5px]" /> 新增
|
||||
</el-button>
|
||||
<el-button
|
||||
type="success"
|
||||
plain
|
||||
@click="handleExport"
|
||||
v-hasPermi="['mes:finished-product-quality:query']"
|
||||
>
|
||||
<Icon icon="ep:download" class="mr-[5px]" /> 导出
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</ContentWrap>
|
||||
|
||||
<!-- 数据表格 -->
|
||||
<ContentWrap>
|
||||
<el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true" @row-click="handleRowClick">
|
||||
<el-table-column type="selection" width="50" align="center" />
|
||||
<el-table-column label="质检编号" align="center" prop="code" />
|
||||
<el-table-column label="批次编号" align="center" prop="workOrderCode" />
|
||||
<!-- 合并产品名称与产品编号为一列 -->
|
||||
<el-table-column label="产品信息" align="center">
|
||||
<template #default="scope">
|
||||
<div>{{ scope.row.productName }}</div>
|
||||
<div style="color: #909399; font-size: 12px; margin-top: 2px">{{
|
||||
scope.row.productCode
|
||||
}}</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<!-- 合并质检状态与是否合格为一列 -->
|
||||
<el-table-column label="质检状态/合格" align="center">
|
||||
<template #default="scope">
|
||||
<el-tag
|
||||
:type="scope.row.status === 0 ? 'info' : scope.row.status === 1 ? 'warning' : 'success'"
|
||||
>
|
||||
{{
|
||||
scope.row.status === 0
|
||||
? '待检'
|
||||
: scope.row.status === 1
|
||||
? '检验中'
|
||||
: scope.row.status === 2
|
||||
? '已完成'
|
||||
: '已入库'
|
||||
}}
|
||||
</el-tag>
|
||||
<div v-if="scope.row.status === 2" style="margin-top: 6px">
|
||||
<el-tag :type="scope.row.qualified ? 'success' : 'danger'">
|
||||
{{ scope.row.qualified ? '合格' : '不合格' }}
|
||||
</el-tag>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<!-- 合并质检数量、合格数量、不合格数量为一列 -->
|
||||
<el-table-column label="重量(kg)" align="center">
|
||||
<template #default="scope">
|
||||
<div
|
||||
>合格重量:{{
|
||||
scope.row.status === 2 || scope.row.status === 3 ? (scope.row.weight ?? '-') : '-'
|
||||
}}</div
|
||||
>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="质检员" align="center" prop="inspectorName" />
|
||||
<el-table-column label="质检时间" align="center" prop="inspectionTime" width="180" sortable/>
|
||||
<el-table-column label="操作" align="center" width="260">
|
||||
<template #default="scope">
|
||||
<el-button
|
||||
v-if="scope.row.status !== 0"
|
||||
type="primary"
|
||||
link @click.stop="openDetail(scope.row)"
|
||||
>
|
||||
查看 </el-button>
|
||||
<el-button
|
||||
v-if="scope.row.status !== 2 && scope.row.status !== 3"
|
||||
type="success"
|
||||
link
|
||||
@click.stop="openDialog('edit', scope.row)"
|
||||
v-hasPermi="['mes:finished-product-quality:update']"
|
||||
>
|
||||
编辑
|
||||
</el-button>
|
||||
<el-button
|
||||
v-if="scope.row.status === 0 || scope.row.status === 1"
|
||||
type="warning"
|
||||
link
|
||||
@click.stop="handleApprove(scope.row)"
|
||||
v-hasPermi="['mes:finished-product-quality:update']"
|
||||
>
|
||||
审核
|
||||
</el-button>
|
||||
<el-button
|
||||
v-if="scope.row.status !== 2 && scope.row.status !== 3"
|
||||
type="danger"
|
||||
link
|
||||
@click.stop="handleDelete(scope.row)"
|
||||
v-hasPermi="['mes:finished-product-quality:delete']"
|
||||
>
|
||||
删除
|
||||
</el-button>
|
||||
<el-button
|
||||
v-if="scope.row.status === 2"
|
||||
type="success"
|
||||
link
|
||||
@click.stop="handleOpenInbound(scope.row)"
|
||||
v-hasPermi="['mes:finished-product-quality:update']"
|
||||
>
|
||||
入库
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<!-- 分页组件 -->
|
||||
<Pagination
|
||||
v-model:page="queryParams.pageNo"
|
||||
v-model:limit="queryParams.pageSize"
|
||||
:total="total"
|
||||
@pagination="getList"
|
||||
/>
|
||||
</ContentWrap>
|
||||
|
||||
<!-- 引入弹窗组件 -->
|
||||
<QualityDialog
|
||||
v-model:visible="dialog.visible"
|
||||
:type="dialog.type"
|
||||
:title="dialog.title"
|
||||
:data="currentRow"
|
||||
@submit="handleDialogSubmit"
|
||||
/>
|
||||
|
||||
<!-- 查看抽屉:左侧工单生产信息,右侧质检信息 -->
|
||||
<el-drawer v-model="detail.visible" size="80%" :with-header="true" title="查看详情">
|
||||
<el-row :gutter="16">
|
||||
<!-- 左侧:批次生产信息 -->
|
||||
<el-col :span="12">
|
||||
<el-card shadow="never" header="批次生产信息" v-loading="detail.loadingWorkOrder">
|
||||
<el-empty v-if="!detail.workOrder && !detail.loadingWorkOrder" description="无工单数据" />
|
||||
<template v-else>
|
||||
<el-descriptions :column="1" border>
|
||||
<el-descriptions-item label="工单编号">{{
|
||||
detail.workOrder?.code || '-'
|
||||
}}</el-descriptions-item>
|
||||
<el-descriptions-item label="产品名称">{{
|
||||
detail.workOrder?.productName || '-'
|
||||
}}</el-descriptions-item>
|
||||
<el-descriptions-item label="产品编号">{{
|
||||
detail.workOrder?.productCode || '-'
|
||||
}}</el-descriptions-item>
|
||||
<el-descriptions-item label="工序路线">{{
|
||||
detail.workOrder?.routeName || '-'
|
||||
}}</el-descriptions-item>
|
||||
<el-descriptions-item label="实际生产数量">{{
|
||||
detail.workOrder?.producedQuantity ?? '-'
|
||||
}}</el-descriptions-item>
|
||||
<el-descriptions-item label="优先级">{{
|
||||
detail.workOrder?.priority ?? '-'
|
||||
}}</el-descriptions-item>
|
||||
<el-descriptions-item label="合格数量">{{
|
||||
detail.workOrder?.qualifiedQuantity ?? '-'
|
||||
}}</el-descriptions-item>
|
||||
<el-descriptions-item label="不合格数量">{{
|
||||
detail.workOrder?.unqualifiedQuantity ?? '-'
|
||||
}}</el-descriptions-item>
|
||||
<el-descriptions-item label="合格率">{{
|
||||
formatPercent(
|
||||
detail.workOrder?.qualifiedQuantity,
|
||||
detail.workOrder?.producedQuantity
|
||||
)
|
||||
}}</el-descriptions-item>
|
||||
<el-descriptions-item label="状态">{{
|
||||
workOrderStatusText(detail.workOrder?.status)
|
||||
}}</el-descriptions-item>
|
||||
<el-descriptions-item label="实际开始时间">{{
|
||||
formatDateTime(detail.workOrder?.actualStartTime)
|
||||
}}</el-descriptions-item>
|
||||
<el-descriptions-item label="实际结束时间">{{
|
||||
formatDateTime(detail.workOrder?.actualEndTime)
|
||||
}}</el-descriptions-item>
|
||||
<el-descriptions-item label="创建时间">{{
|
||||
formatDateTime(detail.workOrder?.createTime)
|
||||
}}</el-descriptions-item>
|
||||
<el-descriptions-item label="备注">{{
|
||||
detail.workOrder?.remark || '-'
|
||||
}}</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
<el-divider>工序信息</el-divider>
|
||||
<el-table
|
||||
:data="detail.workOrder?.operations || []"
|
||||
border
|
||||
size="small"
|
||||
max-height="280"
|
||||
>
|
||||
<el-table-column type="index" label="#" width="50" align="center" />
|
||||
<el-table-column prop="operationCode" label="工序编码" min-width="120" />
|
||||
<el-table-column prop="operationName" label="工序名称" min-width="140" />
|
||||
<el-table-column prop="sequence" label="顺序" width="80" align="center" />
|
||||
<el-table-column prop="completedQuantity" label="完成数" width="100" align="center" />
|
||||
<el-table-column prop="qualifiedQuantity" label="合格数" width="100" align="center" />
|
||||
<el-table-column
|
||||
prop="unqualifiedQuantity"
|
||||
label="不合格数"
|
||||
width="110"
|
||||
align="center"
|
||||
/>
|
||||
<el-table-column label="完成时间" min-width="160">
|
||||
<template #default="{ row }">{{ formatDateTime(row.actualEndTime) }}</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</template>
|
||||
</el-card>
|
||||
</el-col>
|
||||
<!-- 右侧:质检信息 -->
|
||||
<el-col :span="12">
|
||||
<el-card shadow="never" header="质检信息">
|
||||
<el-descriptions :column="2" border>
|
||||
<el-descriptions-item label="质检编号">{{
|
||||
detail.row?.code || '-'
|
||||
}}</el-descriptions-item>
|
||||
<el-descriptions-item label="批次编号">{{
|
||||
detail.row?.workOrderCode || '-'
|
||||
}}</el-descriptions-item>
|
||||
<el-descriptions-item label="产品名称">{{
|
||||
detail.row?.productName || '-'
|
||||
}}</el-descriptions-item>
|
||||
<el-descriptions-item label="产品编号">{{
|
||||
detail.row?.productCode || '-'
|
||||
}}</el-descriptions-item>
|
||||
<el-descriptions-item label="质检状态">{{
|
||||
detail.row?.status === 0
|
||||
? '待检'
|
||||
: detail.row?.status === 1
|
||||
? '检验中'
|
||||
: detail.row?.status === 2
|
||||
? '已完成'
|
||||
: '已入库'
|
||||
}}</el-descriptions-item>
|
||||
<el-descriptions-item label="是否合格">{{
|
||||
detail.row?.qualified ? '合格' : '不合格'
|
||||
}}</el-descriptions-item>
|
||||
<el-descriptions-item label="质检员">{{
|
||||
detail.row?.inspectorName || '-'
|
||||
}}</el-descriptions-item>
|
||||
<el-descriptions-item label="质检时间">{{
|
||||
detail.row?.inspectionTime || '-'
|
||||
}}</el-descriptions-item>
|
||||
<el-descriptions-item label="备注" :span="2">{{
|
||||
detail.row?.remark || '-'
|
||||
}}</el-descriptions-item>
|
||||
<el-descriptions-item label="不合格原因" :span="2" v-if="detail.row?.unqualifiedReason">{{
|
||||
detail.row?.unqualifiedReason || '-'
|
||||
}}</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
<template v-if="isTomato(detail.row?.workOrderCode)">
|
||||
<el-divider>番茄酱(番茄)附加检验</el-divider>
|
||||
<el-descriptions :column="2" border>
|
||||
<el-descriptions-item label="工艺">{{
|
||||
detail.row?.tomatoProcess ?? '-'
|
||||
}}</el-descriptions-item>
|
||||
<el-descriptions-item label="浓度(%)">{{
|
||||
detail.row?.tomatoConcentration ?? '-'
|
||||
}}</el-descriptions-item>
|
||||
<el-descriptions-item label="数量">{{
|
||||
detail.row?.tomatoQuantity ?? '-'
|
||||
}}</el-descriptions-item>
|
||||
<el-descriptions-item label="重量(kg)">{{
|
||||
detail.row?.weight ?? '-'
|
||||
}}</el-descriptions-item>
|
||||
<el-descriptions-item label="可溶性固形物(%)">{{
|
||||
detail.row?.tomatoSolubleSolidsPercent ?? '-'
|
||||
}}</el-descriptions-item>
|
||||
<el-descriptions-item label="粘稠度(cm/30s)">{{
|
||||
detail.row?.tomatoViscosityCmPer ?? '-'
|
||||
}}</el-descriptions-item>
|
||||
<el-descriptions-item label="番茄红素(mg/100g)">{{
|
||||
detail.row?.tomatoLycopeneMgPer ?? '-'
|
||||
}}</el-descriptions-item>
|
||||
<el-descriptions-item label="总酸(%)">{{
|
||||
detail.row?.tomatoTotalAcidPercent ?? '-'
|
||||
}}</el-descriptions-item>
|
||||
<el-descriptions-item label="PH 值">{{
|
||||
detail.row?.tomatoPhValue ?? '-'
|
||||
}}</el-descriptions-item>
|
||||
<el-descriptions-item label="色差 a/b">{{
|
||||
detail.row?.tomatoColorDifference ?? '-'
|
||||
}}</el-descriptions-item>
|
||||
<el-descriptions-item label="霉菌(%)">{{
|
||||
detail.row?.tomatoMouldPositivePercent ?? '-'
|
||||
}}</el-descriptions-item>
|
||||
<el-descriptions-item label="评定">{{
|
||||
detail.row?.tomatoAssessConformance === 1
|
||||
? '品质符合'
|
||||
: detail.row?.tomatoAssessConformance === 0
|
||||
? '品质不符合'
|
||||
: '-'
|
||||
}}</el-descriptions-item>
|
||||
<el-descriptions-item label="评定说明" :span="2">{{
|
||||
detail.row?.tomatoAssessRemark || '-'
|
||||
}}</el-descriptions-item>
|
||||
<el-descriptions-item label="感官" :span="2">{{
|
||||
detail.row?.tomatoSensory || '-'
|
||||
}}</el-descriptions-item>
|
||||
<el-descriptions-item label="番茄备注" :span="2">{{
|
||||
detail.row?.remark || '-'
|
||||
}}</el-descriptions-item>
|
||||
<el-descriptions-item label="附件" :span="2">
|
||||
<template v-if="detail.row?.attachmentUrls">
|
||||
<el-link type="primary" :href="detail.row.attachmentUrls" target="_blank">查看附件</el-link>
|
||||
</template>
|
||||
<template v-else>-</template>
|
||||
</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
</template>
|
||||
<template v-else-if="isStevia(detail.row?.workOrderCode)">
|
||||
<el-divider>甜菊糖(甜叶菊)附加检验</el-divider>
|
||||
<el-descriptions :column="2" border>
|
||||
<el-descriptions-item label="标签" :span="2">{{
|
||||
detail.row?.steviaLabel || '-'
|
||||
}}</el-descriptions-item>
|
||||
<!-- <el-descriptions-item label="色泽">{{-->
|
||||
<!-- detail.row?.steviaColor || '-'-->
|
||||
<!-- }}</el-descriptions-item>-->
|
||||
<!-- <el-descriptions-item label="色泽合格">{{-->
|
||||
<!-- detail.row?.steviaColorOk ? '✓' : '-'-->
|
||||
<!-- }}</el-descriptions-item>-->
|
||||
<!-- <el-descriptions-item label="状态">{{-->
|
||||
<!-- detail.row?.steviaState || '-'-->
|
||||
<!-- }}</el-descriptions-item>-->
|
||||
<!-- <el-descriptions-item label="状态合格">{{-->
|
||||
<!-- detail.row?.steviaStateOk ? '✓' : '-'-->
|
||||
<!-- }}</el-descriptions-item>-->
|
||||
<el-descriptions-item label="甜菊糖苷含量(%)">{{
|
||||
detail.row?.steviaGlycosidesPercent ?? '-'
|
||||
}}</el-descriptions-item>
|
||||
<el-descriptions-item label="灰分(%)">{{
|
||||
detail.row?.steviaAshPercent ?? '-'
|
||||
}}</el-descriptions-item>
|
||||
<!-- <el-descriptions-item label="干燥减重(%)">{{-->
|
||||
<!-- detail.row?.steviaLossOnDryingPercent ?? '-'-->
|
||||
<!-- }}</el-descriptions-item>-->
|
||||
<!-- <el-descriptions-item label="甲醇(mg/kg)">{{-->
|
||||
<!-- detail.row?.steviaMethanolMgPerKg ?? '-'-->
|
||||
<!-- }}</el-descriptions-item>-->
|
||||
<!-- <el-descriptions-item label="乙醇(mg/kg)">{{-->
|
||||
<!-- detail.row?.steviaEthanolMgPerKg ?? '-'-->
|
||||
<!-- }}</el-descriptions-item>-->
|
||||
<!-- <el-descriptions-item label="铅(mg/kg)">{{-->
|
||||
<!-- detail.row?.steviaLeadMgPerKg ?? '-'-->
|
||||
<!-- }}</el-descriptions-item>-->
|
||||
<!-- <el-descriptions-item label="总砷(mg/kg)">{{-->
|
||||
<!-- detail.row?.steviaTotalArsenicMgPerKg ?? '-'-->
|
||||
<!-- }}</el-descriptions-item>-->
|
||||
<el-descriptions-item label="PH 值">{{
|
||||
detail.row?.steviaPhValue ?? '-'
|
||||
}}</el-descriptions-item>
|
||||
<el-descriptions-item label="RD">{{
|
||||
detail.row?.steviaRd ?? '-'
|
||||
}}</el-descriptions-item>
|
||||
<el-descriptions-item label="RA">{{
|
||||
detail.row?.steviaRa ?? '-'
|
||||
}}</el-descriptions-item>
|
||||
<el-descriptions-item label="STV">{{
|
||||
detail.row?.steviaStv ?? '-'
|
||||
}}</el-descriptions-item>
|
||||
<el-descriptions-item label="RF">{{
|
||||
detail.row?.steviaRf ?? '-'
|
||||
}}</el-descriptions-item>
|
||||
<el-descriptions-item label="RC">{{
|
||||
detail.row?.steviaRc ?? '-'
|
||||
}}</el-descriptions-item>
|
||||
<el-descriptions-item label="DA">{{
|
||||
detail.row?.steviaDa ?? '-'
|
||||
}}</el-descriptions-item>
|
||||
<el-descriptions-item label="RV">{{
|
||||
detail.row?.steviaRv ?? '-'
|
||||
}}</el-descriptions-item>
|
||||
<el-descriptions-item label="RB">{{
|
||||
detail.row?.steviaRb ?? '-'
|
||||
}}</el-descriptions-item>
|
||||
<el-descriptions-item label="SB">{{
|
||||
detail.row?.steviaSb ?? '-'
|
||||
}}</el-descriptions-item>
|
||||
<el-descriptions-item label="水分(%)">{{
|
||||
detail.row?.steviaMoisture ?? '-'
|
||||
}}</el-descriptions-item>
|
||||
<el-descriptions-item label="比吸光">{{
|
||||
detail.row?.steviaSpecificAbsorbance ?? '-'
|
||||
}}</el-descriptions-item>
|
||||
<el-descriptions-item label="透光率(%)">{{
|
||||
detail.row?.steviaTransmittance ?? '-'
|
||||
}}</el-descriptions-item>
|
||||
<!-- <el-descriptions-item label="产量(kg)">{{-->
|
||||
<!-- detail.row?.steviaYield ?? '-'-->
|
||||
<!-- }}</el-descriptions-item>-->
|
||||
<el-descriptions-item label="甜菊糖备注" :span="2">{{
|
||||
detail.row?.steviaRemark || '-'
|
||||
}}</el-descriptions-item>
|
||||
<el-descriptions-item label="附件" :span="2">
|
||||
<template v-if="detail.row?.attachmentUrls">
|
||||
<el-link type="primary" :href="detail.row.attachmentUrls" target="_blank">查看附件</el-link>
|
||||
</template>
|
||||
<template v-else>-</template>
|
||||
</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
</template>
|
||||
</el-card>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-drawer>
|
||||
|
||||
<!-- 成品质检入库弹窗 -->
|
||||
<el-dialog v-model="inboundDialogVisible" title="生产入库" width="520px" append-to-body>
|
||||
<el-form label-width="120px">
|
||||
<el-form-item label="选择仓库">
|
||||
<el-select
|
||||
v-model="selectedWarehouseId"
|
||||
placeholder="请选择或输入仓库编号"
|
||||
filterable
|
||||
allow-create
|
||||
default-first-option
|
||||
clearable
|
||||
class="!w-320px"
|
||||
>
|
||||
<el-option
|
||||
v-for="w in warehouseOptions"
|
||||
:key="w.id"
|
||||
:label="w.name + '(' + w.id + ')'"
|
||||
:value="w.id"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="产品条码">
|
||||
<span>{{
|
||||
(currentInboundRow &&
|
||||
(currentInboundRow.productCode ||
|
||||
currentInboundRow.productBarCode ||
|
||||
currentInboundRow.barCode)) ||
|
||||
'-'
|
||||
}}</span>
|
||||
</el-form-item>
|
||||
<el-form-item label="入库重量(kg)">
|
||||
<span>{{ (currentInboundRow && currentInboundRow.weight) || 0 }}</span>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<span class="dialog-footer">
|
||||
<el-button @click="inboundDialogVisible = false">取消</el-button>
|
||||
<el-button type="primary" :loading="inboundSubmitting" @click="confirmInbound"
|
||||
>确定</el-button
|
||||
>
|
||||
</span>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, reactive, onMounted } from 'vue'
|
||||
import { ElMessage, ElMessageBox } from 'element-plus'
|
||||
import QualityDialog from './components/QualityDialog.vue'
|
||||
import {
|
||||
getFinishedProductQualityPage,
|
||||
deleteFinishedProductQuality,
|
||||
approveFinishedProductQuality
|
||||
} from '@/api/mes/quality/productquality/index'
|
||||
import { YVHgetWorkOrder, YVHgetWorkOrderSimpleList } from '@/api/mes/production/workorder'
|
||||
import { WarehouseApi } from '@/api/erp/stock/warehouse'
|
||||
import request from '@/config/axios'
|
||||
|
||||
// 查询参数
|
||||
const queryParams = reactive({
|
||||
pageNo: 1,
|
||||
pageSize: 10
|
||||
})
|
||||
|
||||
// 搜索表单
|
||||
const searchForm = reactive({
|
||||
productName: '',
|
||||
workOrderCode: '',
|
||||
status: undefined,
|
||||
qualified: undefined,
|
||||
inspectionTime: [] as string[]
|
||||
})
|
||||
|
||||
// 弹窗控制
|
||||
const dialog = reactive({
|
||||
visible: false,
|
||||
title: '',
|
||||
type: ''
|
||||
})
|
||||
|
||||
// 当前选中的行数据
|
||||
const currentRow = ref<any>({})
|
||||
|
||||
// 列表数据
|
||||
const list = ref<any[]>([])
|
||||
const loading = ref(false)
|
||||
const total = ref(0)
|
||||
|
||||
// 详情抽屉状态
|
||||
const detail = reactive<any>({
|
||||
visible: false,
|
||||
row: null,
|
||||
loadingWorkOrder: false,
|
||||
workOrder: null
|
||||
})
|
||||
|
||||
const isTomato = (code?: string) => {
|
||||
const c = (code || '').toUpperCase()
|
||||
return c.startsWith('X8')
|
||||
}
|
||||
const isStevia = (code?: string) => {
|
||||
const c = (code || '').toUpperCase()
|
||||
return c.startsWith('X') && !c.startsWith('X8')
|
||||
}
|
||||
|
||||
// 工具:时间与百分比格式化
|
||||
const pad2 = (n: number) => String(n).padStart(2, '0')
|
||||
const formatDateTime = (v: any) => {
|
||||
if (v == null || v === '') return '-'
|
||||
try {
|
||||
let d: Date
|
||||
if (typeof v === 'number') {
|
||||
// 兼容秒/毫秒
|
||||
d = new Date(v > 1e12 ? v : v * 1000)
|
||||
} else if (typeof v === 'string') {
|
||||
d = new Date(v)
|
||||
} else if (v instanceof Date) {
|
||||
d = v
|
||||
} else {
|
||||
return String(v)
|
||||
}
|
||||
const Y = d.getFullYear()
|
||||
const M = pad2(d.getMonth() + 1)
|
||||
const D = pad2(d.getDate())
|
||||
const h = pad2(d.getHours())
|
||||
const m = pad2(d.getMinutes())
|
||||
const s = pad2(d.getSeconds())
|
||||
return `${Y}-${M}-${D} ${h}:${m}:${s}`
|
||||
} catch {
|
||||
return String(v)
|
||||
}
|
||||
}
|
||||
const formatPercent = (num?: number, denom?: number) => {
|
||||
if (!denom || denom <= 0 || num == null) return '-'
|
||||
return `${((num / denom) * 100).toFixed(2)}%`
|
||||
}
|
||||
const workOrderStatusText = (s?: number) => {
|
||||
switch (s) {
|
||||
case 7:
|
||||
return '已入库'
|
||||
case 4:
|
||||
return '已完成'
|
||||
case 3:
|
||||
return '生产中'
|
||||
case 2:
|
||||
return '已审核'
|
||||
case 1:
|
||||
return '待审核'
|
||||
case 0:
|
||||
return '草稿'
|
||||
default:
|
||||
return '已入库'
|
||||
}
|
||||
}
|
||||
|
||||
// 入库弹窗状态
|
||||
const inboundDialogVisible = ref(false)
|
||||
const inboundSubmitting = ref(false)
|
||||
const warehouseOptions = ref<Array<{ id: number; name: string }>>([])
|
||||
const selectedWarehouseId = ref<string | number | undefined>(undefined)
|
||||
const currentInboundRow = ref<any>(null)
|
||||
// 不再使用工单ID入库,改为传质检单ID
|
||||
|
||||
// 打开入库
|
||||
const handleOpenInbound = async (row: any) => {
|
||||
currentInboundRow.value = row
|
||||
selectedWarehouseId.value = undefined
|
||||
try {
|
||||
// 加载仓库选项
|
||||
const list = await WarehouseApi.getWarehouseSimpleList()
|
||||
warehouseOptions.value = Array.isArray(list) ? list : list?.data || []
|
||||
if (warehouseOptions.value.length > 0) {
|
||||
selectedWarehouseId.value = warehouseOptions.value[0].id
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('加载仓库列表失败:', error)
|
||||
}
|
||||
|
||||
inboundDialogVisible.value = true
|
||||
}
|
||||
|
||||
// 确认入库
|
||||
const confirmInbound = async () => {
|
||||
if (!currentInboundRow.value) return
|
||||
const chosenId = selectedWarehouseId.value
|
||||
const warehouseId = Number(chosenId)
|
||||
if (!Number.isInteger(warehouseId) || warehouseId <= 0) {
|
||||
ElMessage.error('请选择或输入合法的仓库编号')
|
||||
return
|
||||
}
|
||||
const barCode =
|
||||
currentInboundRow.value.productCode ||
|
||||
currentInboundRow.value.productBarCode ||
|
||||
currentInboundRow.value.barCode
|
||||
if (!barCode) {
|
||||
ElMessage.error('缺少产品条码,无法入库')
|
||||
return
|
||||
}
|
||||
const count = Number(currentInboundRow.value.weight) || 0
|
||||
if (!count || count <= 0) {
|
||||
ElMessage.error('合格重量为 0,无法入库')
|
||||
return
|
||||
}
|
||||
// 确保有工单ID
|
||||
let workOrderId = currentInboundRow.value?.workOrderId
|
||||
if (!workOrderId && currentInboundRow.value?.workOrderCode) {
|
||||
try {
|
||||
const list: any = await YVHgetWorkOrderSimpleList({
|
||||
code: currentInboundRow.value.workOrderCode
|
||||
} as any)
|
||||
const target = Array.isArray(list)
|
||||
? list.find((it: any) => it.code === currentInboundRow.value.workOrderCode)
|
||||
: null
|
||||
workOrderId = target?.id
|
||||
} catch (e) {}
|
||||
}
|
||||
|
||||
inboundSubmitting.value = true
|
||||
try {
|
||||
await request.post({
|
||||
url: '/mes/stock/inbound',
|
||||
data: {
|
||||
barCode,
|
||||
warehouseId,
|
||||
count,
|
||||
finishedProductQualityId: currentInboundRow.value.id
|
||||
}
|
||||
})
|
||||
ElMessage.success('入库成功')
|
||||
inboundDialogVisible.value = false
|
||||
} catch (error) {
|
||||
console.error('入库失败:', error)
|
||||
ElMessage.error('入库失败')
|
||||
} finally {
|
||||
inboundSubmitting.value = false
|
||||
}
|
||||
}
|
||||
|
||||
// 获取列表数据
|
||||
const getList = async () => {
|
||||
loading.value = true
|
||||
try {
|
||||
// 构建查询参数
|
||||
const params: any = {
|
||||
...queryParams,
|
||||
productName: searchForm.productName || undefined,
|
||||
workOrderCode: searchForm.workOrderCode || undefined,
|
||||
status: searchForm.status,
|
||||
qualified:
|
||||
searchForm.qualified === true
|
||||
? 1
|
||||
: searchForm.qualified === false
|
||||
? 0
|
||||
: searchForm.qualified
|
||||
}
|
||||
|
||||
// 处理日期范围
|
||||
if (searchForm.inspectionTime && searchForm.inspectionTime.length === 2) {
|
||||
params.inspectionTime = [
|
||||
searchForm.inspectionTime[0] + ' 00:00:00',
|
||||
searchForm.inspectionTime[1] + ' 23:59:59'
|
||||
]
|
||||
}
|
||||
|
||||
const res = await getFinishedProductQualityPage(params)
|
||||
if (res.list && Array.isArray(res.list)) {
|
||||
list.value = res.list
|
||||
total.value = res.total || 0
|
||||
} else if (res.code === 0 && res.data) {
|
||||
// 处理标准响应格式
|
||||
list.value = res.data.list || []
|
||||
total.value = res.data.total || 0
|
||||
} else {
|
||||
ElMessage.error('获取列表失败')
|
||||
list.value = []
|
||||
total.value = 0
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('获取成品质检列表失败', error)
|
||||
list.value = []
|
||||
total.value = 0
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
// 查询操作
|
||||
const handleQuery = () => {
|
||||
queryParams.pageNo = 1
|
||||
getList()
|
||||
}
|
||||
|
||||
// 重置查询
|
||||
const resetQuery = () => {
|
||||
searchForm.productName = ''
|
||||
searchForm.workOrderCode = ''
|
||||
searchForm.status = undefined
|
||||
searchForm.qualified = undefined
|
||||
searchForm.inspectionTime = []
|
||||
handleQuery()
|
||||
}
|
||||
|
||||
// 打开弹窗
|
||||
const openDialog = (type: string, row?: any) => {
|
||||
dialog.type = type
|
||||
dialog.title =
|
||||
{
|
||||
create: '新增报工与质检',
|
||||
edit: '编辑报工与质检',
|
||||
view: '查看报工与质检'
|
||||
}[type] || ''
|
||||
|
||||
dialog.visible = true
|
||||
currentRow.value = row || {}
|
||||
}
|
||||
|
||||
// 打开详情抽屉
|
||||
const openDetail = async (row: any) => {
|
||||
detail.visible = true
|
||||
detail.row = row
|
||||
|
||||
// 加载工单基础信息
|
||||
detail.loadingWorkOrder = true
|
||||
try {
|
||||
let workOrderId = row?.workOrderId
|
||||
if (!workOrderId && row?.workOrderCode) {
|
||||
// 通过 code 查找 id(兜底方案)
|
||||
const list = await YVHgetWorkOrderSimpleList({ code: row.workOrderCode } as any)
|
||||
const target = Array.isArray(list)
|
||||
? list.find((it: any) => it.code === row.workOrderCode)
|
||||
: null
|
||||
workOrderId = target?.id
|
||||
}
|
||||
if (workOrderId) {
|
||||
const res = await YVHgetWorkOrder(workOrderId)
|
||||
detail.workOrder = res
|
||||
} else {
|
||||
detail.workOrder = null
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('加载工单详情失败', e)
|
||||
detail.workOrder = null
|
||||
} finally {
|
||||
detail.loadingWorkOrder = false
|
||||
}
|
||||
}
|
||||
|
||||
// 处理弹窗提交
|
||||
const handleDialogSubmit = () => {
|
||||
// 直接刷新列表,不显示提示信息
|
||||
getList()
|
||||
}
|
||||
|
||||
// 审核记录
|
||||
const handleApprove = (row: any) => {
|
||||
ElMessageBox.confirm('确认要审核该成品质检记录吗?审核后状态将变更为已完成。', '审核确认', {
|
||||
type: 'warning'
|
||||
})
|
||||
.then(async () => {
|
||||
try {
|
||||
await approveFinishedProductQuality(row.id)
|
||||
ElMessage.success('审核成功')
|
||||
getList()
|
||||
} catch (error: any) {
|
||||
console.error('审核失败:', error)
|
||||
ElMessage.error(error.message || '审核失败')
|
||||
}
|
||||
})
|
||||
.catch(() => {})
|
||||
}
|
||||
|
||||
// 删除记录
|
||||
const handleDelete = (row: any) => {
|
||||
ElMessageBox.confirm('确认要删除该成品质检记录吗?', '警告', {
|
||||
type: 'warning'
|
||||
})
|
||||
.then(async () => {
|
||||
try {
|
||||
const res = await deleteFinishedProductQuality(row.id)
|
||||
if (res) {
|
||||
ElMessage.success('删除成功')
|
||||
getList()
|
||||
} else {
|
||||
ElMessage.error(res.msg || '删除失败')
|
||||
}
|
||||
} catch (error: any) {
|
||||
ElMessage.error(error.message || '删除失败')
|
||||
}
|
||||
})
|
||||
.catch(() => {})
|
||||
}
|
||||
|
||||
// 处理行点击事件
|
||||
const handleRowClick = (row: any) => {
|
||||
// 状态为待检(0)或检验中(1)时,打开编辑页面
|
||||
if (row.status === 0 || row.status === 1) {
|
||||
openDialog('edit', row)
|
||||
}
|
||||
// 状态为已完成(2)或已入库(3)时,打开详情页面
|
||||
else if (row.status === 2 || row.status === 3) {
|
||||
openDetail(row)
|
||||
}
|
||||
}
|
||||
|
||||
// 导出数据
|
||||
const handleExport = () => {
|
||||
ElMessage.success('导出成功')
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
getList()
|
||||
})
|
||||
</script>
|
||||
Reference in New Issue
Block a user