|
|
<template> <div class="pda-container"> <!-- 头部栏 --> <div class="header-bar"> <div class="header-left" @click="$router.back()"> <i class="el-icon-arrow-left"></i> <span>生产待入库</span> </div> <div class="header-right" @click="$router.push({ path: '/' })"> 首页 </div> </div>
<!-- 搜索框 --> <div class="search-container"> <el-input clearable v-model="searchCode" placeholder="请扫描入库单或关联单号" prefix-icon="el-icon-search" @keyup.enter.native="handleSearch" ref="searchInput" /> </div>
<!-- 入库单列表 --> <div class="inbound-list"> <!-- 当没有选中入库单时,显示所有入库单 --> <template v-if="!selectedInbound"> <div v-for="(item, index) in qualifiedList" :key="index" class="inbound-card" @click="selectInbound(item)" > <div class="card-title"> <span class="title-label">入库单号:{{ item.inboundNo }}</span> </div>
<div class="card-details"> <div class="detail-item"> <div class="detail-label">标签张数</div> <div class="detail-value"> <span class="qualified">{{ item.labelinCount }}</span><span class="total">{{ item.totalLabels }}</span> </div> </div> <div class="detail-item"> <div class="detail-label">物料总数</div> <div class="detail-value"> <span class="qualified">{{ item.totalinLabels }}</span><span class="total">{{ item.labelCount }}</span> </div> </div> <div class="detail-item"> <div class="detail-label">批次号</div> <div class="detail-value">{{ item.batchNo }}</div> </div> <div class="detail-item"> <div class="detail-label">创建日期</div> <div class="detail-value">{{ formatDate(item.inspectionDate) }}</div> </div> </div> </div>
<!-- 空状态 --> <div v-if="qualifiedList.length === 0 && !loading" class="empty-state"> <i class="el-icon-box"></i> <p>暂无生产待入库物料</p> </div>
<!-- 加载状态 --> <div v-if="loading" class="loading-state"> <i class="el-icon-loading"></i> <p>加载中...</p> </div> </template>
<!-- 当选中入库单时,只显示选中的入库单 --> <div v-else class="inbound-card selected" @click="deselectInbound" > <div class="card-title"> <span class="title-label">入库单号:{{ selectedInbound.inboundNo }}</span> <i class="el-icon-arrow-left back-icon" title="返回列表"></i> </div>
<div class="card-details"> <div class="detail-item"> <div class="detail-label">标签张数</div> <div class="detail-value"> <span class="qualified">{{ selectedInbound.labelinCount }}</span><span class="total">{{ selectedInbound.totalLabels }}</span> </div> </div> <div class="detail-item"> <div class="detail-label">物料总数</div> <div class="detail-value"> <span class="qualified">{{ selectedInbound.totalinLabels }}</span><span class="total">{{ selectedInbound.labelCount }}</span> </div> </div> <div class="detail-item"> <div class="detail-label">批次号</div> <div class="detail-value">{{ selectedInbound.batchNo }}</div> </div> <div class="detail-item"> <div class="detail-label">创建日期</div> <div class="detail-value">{{ formatDate(selectedInbound.inspectionDate) }}</div> </div> </div> </div> </div>
<!-- 物料详情列表(小卡片) --> <div class="content-area" v-if="selectedInbound && detailList.length > 0" > <div v-for="(detail, index) in detailList" :key="index" class="detail-card" @click="selectDetail(detail)" > <!-- 第一行:关联单号(左)| 需求数量(右) --> <div class="card-row"> <span class="field-item"> <span class="field-label">关联单号:</span> <span class="field-value">{{ detail.relatedOrderNo }}</span> </span> <span class="field-item"> <span class="field-label">需求数量:</span> <span class="field-value">{{ detail.requiredQty || 0 }}</span> </span> </div>
<!-- 第二行:物料编码(左)| 单位(右) --> <div class="card-row"> <span class="field-item"> <span class="field-label">物料编码:</span> <span class="field-value">{{ detail.partNo }}</span> </span> <span class="field-item"> <span class="field-label">单位:</span> <span class="field-value">{{ detail.umName }}</span> </span> </div>
<!-- 第三行:物料名称(全宽) --> <div class="card-row-full"> <span class="field-label">物料名称:</span> <span class="field-value">{{ detail.partDesc }}</span> </div>
<!-- 第四行:订单数量(全宽) --> <div class="card-row-full"> <span class="field-label">订单数量:</span> <span class="field-value">{{ detail.orderQty || 0 }}</span> </div> </div> </div>
<!-- 物料详情加载状态 --> <div v-if="selectedInbound && detailListLoading" class="loading-state"> <i class="el-icon-loading"></i> <p>加载物料详情中...</p> </div>
<!-- 物料详情空状态 --> <div v-if="selectedInbound && !detailListLoading && detailList.length === 0" class="empty-state"> <i class="el-icon-document"></i> <p>暂无物料详情</p> </div> </div></template>
<script>import { getQualifiedInboundList, getInboundNotificationDetails } from "@/api/production/production-inbound.js";import { getCurrentWarehouse } from '@/utils'import moment from 'moment';
export default { data() { return { searchCode: '', qualifiedList: [], loading: false, selectedInbound: null, detailList: [], detailListLoading: false }; }, methods: { formatDate(date) { return date ? moment(date).format('YYYY-MM-DD') : ''; },
// 处理搜索
handleSearch() { if (this.searchCode.trim()) { this.searchQualifiedList(this.searchCode.trim()); } else { this.loadQualifiedList(); } },
// 加载生产待入库列表
loadQualifiedList() { const currentWarehouse = getCurrentWarehouse(); if (!currentWarehouse) { this.$message.error('请先选择仓库'); return; }
this.loading = true; const params = { warehouseId: currentWarehouse, site:localStorage.getItem('site'), status: '待入库',// 待入库状态
};
getQualifiedInboundList(params).then(({ data }) => { this.loading = false; if (data && data.code === 0) { this.qualifiedList = data.data || []; } else { this.$message.error(data.msg || '获取数据失败'); } }).catch(error => { this.loading = false; console.error('获取生产待入库列表失败:', error); this.$message.error('获取数据失败'); }); },
// 搜索特定入库单
searchQualifiedList(searchCode) { const currentWarehouse = getCurrentWarehouse(); if (!currentWarehouse) { this.$message.error('请先选择仓库'); return; }
this.loading = true; const params = { warehouseId: currentWarehouse, searchCode: searchCode, site:localStorage.getItem('site'), status: '待入库' };
getQualifiedInboundList(params).then(({ data }) => { this.loading = false; if (data && data.code === 0) { if (data.data.length === 0) { this.$message.warning('未找到匹配的入库单'); } this.qualifiedList = data.data || []; } else { this.$message.error(data.msg || '查询失败'); } }).catch(error => { this.loading = false; console.error('搜索失败:', error); this.$message.error('查询失败'); }); },
// 选择入库单
selectInbound(item) { this.selectedInbound = item; this.loadDetailList(item); },
// 取消选择入库单
deselectInbound() { this.selectedInbound = null; this.detailList = []; },
// 加载物料详情列表(小卡片)
loadDetailList(item) { this.detailListLoading = true;
const params = { site: localStorage.getItem('site'), buNo: item.buNo, orderNo: item.inboundNo };
getInboundNotificationDetails(params).then(({ data }) => { this.detailListLoading = false; if (data && data.code === 0) { this.detailList = (data.data || []).map((detail) => ({ ...detail, // 映射后端字段到前端字段
orderNo: detail.orderNo, orderQty: detail.orderQty, requiredQty: detail.requiredQty, partNo: detail.partNo, partDesc: detail.partDesc, umName: detail.umName, relatedOrderNo: detail.relatedOrderNo, relatedOrderLineNo: detail.relatedOrderLineNo })); } else { this.$message.error(data.msg || '获取物料明细失败'); this.detailList = []; } }).catch(error => { this.detailListLoading = false; console.error('获取物料明细失败:', error); this.$message.error('获取物料明细失败'); this.detailList = []; }); },
// 选择物料详情,跳转到入库页面
selectDetail(detail) { this.$router.push({ name: 'productionInboundStorage', params: { buNo: this.selectedInbound.buNo, inboundNo: this.selectedInbound.inboundNo, relatedOrderNo: detail.relatedOrderNo, relatedOrderLineNo: detail.relatedOrderLineNo, partNo: detail.partNo, partDesc: detail.partDesc } }); } },
mounted() { // 聚焦搜索框
this.$nextTick(() => { if (this.$refs.searchInput) { this.$refs.searchInput.focus(); } });
// 加载数据
this.loadQualifiedList(); }};</script>
<style scoped>.pda-container { width: 100vw; height: 100vh; display: flex; flex-direction: column; background: #f5f5f5;}
/* 头部栏 */.header-bar { display: flex; justify-content: space-between; align-items: center; padding: 8px 16px; background: #17B3A3; color: white; height: 40px; min-height: 40px;}
.header-left { display: flex; align-items: center; cursor: pointer; font-size: 16px; font-weight: 500;}
.header-left i { margin-right: 8px; font-size: 18px;}
.header-right { cursor: pointer; font-size: 16px; font-weight: 500;}
/* 搜索容器 */.search-container { padding: 12px 16px; background: white;}
/* 入库单列表 */.inbound-list { overflow-y: auto; padding: 12px 16px;}
/* 内容区域(物料详情列表) */.content-area { flex: 1; overflow-y: auto; padding: 8px 0 12px 0; background: #f8f9fa; margin: 0 16px 12px 16px; border-radius: 0 0 8px 8px;}
/* 入库卡片 */.inbound-card { background: white; border-radius: 8px; margin-bottom: 12px; padding: 16px; box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); cursor: pointer; transition: all 0.2s ease; border: 2px solid transparent;}
.inbound-card:hover { box-shadow: 0 4px 8px rgba(0, 0, 0, 0.15); transform: translateY(-1px);}
.inbound-card.selected { border-color: #17B3A3; background: #f0fffe;}
.inbound-card:active { transform: translateY(0);}
/* 物料详情卡片(小卡片) */.detail-card { background: white; border-radius: 6px; margin-bottom: 8px; margin-left: 20px; margin-right: 16px; padding: 12px; box-shadow: 0 1px 3px rgba(0, 0, 0, 0.08); cursor: pointer; transition: all 0.2s ease; border: 1px solid #e8f4f3; position: relative;}
.detail-card::before { content: ''; position: absolute; left: -12px; top: 50%; transform: translateY(-50%); width: 4px; height: 20px; background: #17B3A3; border-radius: 2px;}
.detail-card:hover { box-shadow: 0 2px 6px rgba(0, 0, 0, 0.12); transform: translateY(-1px); border-color: #17B3A3;}
.detail-card:active { transform: translateY(0);}
/* 卡片标题 */.card-title { margin-bottom: 12px; position: relative;}
.title-label { font-size: 12px; color: #666; display: block; margin-bottom: 4px;}
.title-value { font-size: 16px; font-weight: bold; color: #333; margin-left: 16px;}
.back-icon { position: absolute; right: 16px; top: 50%; transform: translateY(-50%); font-size: 18px; color: #17B3A3; cursor: pointer; transition: color 0.2s ease;}
.back-icon:hover { color: #0d8f7f;}
/* 物料详情卡片内的字段行样式 */.detail-card .card-row { display: flex; justify-content: space-between; align-items: center; margin-bottom: 6px; gap: 8px;}
.detail-card .card-row-full { margin-bottom: 6px; display: flex; align-items: center;}
.detail-card .field-item { display: flex; align-items: center; flex: 1; min-width: 0;}
.detail-card .field-label { font-size: 11px; color: #666; white-space: nowrap; margin-right: 4px;}
.detail-card .field-value { font-size: 12px; color: #333; font-weight: 500; word-break: break-all; flex: 1;}
/* 卡片详情 */.card-details { display: flex; justify-content: space-between; align-items: flex-start; gap: 4px;}
.detail-item { flex: 1; text-align: center; min-width: 60px; max-width: 60px;}
.detail-label { font-size: 11px; color: #666; margin-bottom: 4px; line-height: 1.2; margin-left: -12px;}
.detail-value { font-size: 13px; color: #333; line-height: 1.2; margin-left: -12px;}
.detail-value .qualified { color: #17B3A3; font-weight: 500;}
.detail-value .total { color: #333; font-weight: 500;}
.detail-value .total::before { content: '/'; color: #333;}
/* 空状态 */.empty-state { display: flex; flex-direction: column; align-items: center; justify-content: center; padding: 60px 20px; color: #999;}
.empty-state i { font-size: 48px; margin-bottom: 16px;}
.empty-state p { font-size: 14px; margin: 0;}
/* 加载状态 */.loading-state { display: flex; flex-direction: column; align-items: center; justify-content: center; padding: 60px 20px; color: #17B3A3;}
.loading-state i { font-size: 24px; margin-bottom: 12px; animation: spin 1s linear infinite;}
@keyframes spin { from { transform: rotate(0deg); } to { transform: rotate(360deg); }}
.loading-state p { font-size: 14px; margin: 0;}
/* 响应式设计 */@media (max-width: 360px) { .header-bar { padding: 8px 12px; }
.search-container { padding: 8px 12px; }
.inbound-list { padding: 8px 12px; }
.content-area { padding: 8px 12px; margin: 0 12px 8px 12px; }
.inbound-card { padding: 12px; }
.detail-card { margin-left: 16px; margin-right: 12px; }
.card-details { flex-wrap: wrap; gap: 6px; }
.detail-item { flex: 0 0 48%; margin-bottom: 6px; min-width: 50px; }
.detail-card .field-item { flex: 0 0 45%; min-width: 40px; }}</style>
|