379 lines
12 KiB
Vue
379 lines
12 KiB
Vue
|
|
<template>
|
||
|
|
<el-config-provider :locale="zhCn">
|
||
|
|
<el-container class="content">
|
||
|
|
<div class="work-area">
|
||
|
|
<fieldset class="main-area">
|
||
|
|
<legend>物料查询</legend>
|
||
|
|
<el-form ref="queryFormRef" :model="queryForm" label-width="70px" :label-position="labelPosition">
|
||
|
|
<el-row :gutter="5" class="form-row">
|
||
|
|
<el-col :xs="24" :sm="4" :md="4" :lg="4">
|
||
|
|
<el-form-item label="内部编号">
|
||
|
|
<el-input v-model="queryForm.neibubianhao" clearable class="custom-input" />
|
||
|
|
</el-form-item>
|
||
|
|
</el-col>
|
||
|
|
<el-col :xs="24" :sm="4" :md="4" :lg="4">
|
||
|
|
<el-form-item label="规格">
|
||
|
|
<el-input v-model="queryForm.goodsType" clearable class="custom-input" />
|
||
|
|
</el-form-item>
|
||
|
|
</el-col>
|
||
|
|
<el-col :xs="24" :sm="4" :md="4" :lg="4">
|
||
|
|
<el-form-item label="销售单号">
|
||
|
|
<el-input v-model="queryForm.xsfbillno" clearable class="custom-input" />
|
||
|
|
</el-form-item>
|
||
|
|
</el-col>
|
||
|
|
<el-col :xs="24" :sm="4" :md="4" :lg="4" class="btn-col">
|
||
|
|
<el-button type="primary" @click="queryGoods">查询</el-button>
|
||
|
|
<el-button type="info" @click="resetQueryForm">重置</el-button>
|
||
|
|
</el-col>
|
||
|
|
</el-row>
|
||
|
|
</el-form>
|
||
|
|
</fieldset>
|
||
|
|
|
||
|
|
<fieldset v-if="tableData.length > 0" class="main-area">
|
||
|
|
<legend>查询结果</legend>
|
||
|
|
<div v-for="(locationItem, locationIndex) in tableData" :key="locationIndex" class="location-group">
|
||
|
|
<div class="location-header">
|
||
|
|
<h3>库位: {{ locationItem.location }} | 托盘号: {{ locationItem.vehicleNo }}</h3>
|
||
|
|
</div>
|
||
|
|
<el-table
|
||
|
|
:data="locationItem.goodsDetail"
|
||
|
|
border
|
||
|
|
stripe
|
||
|
|
style="width: 100%"
|
||
|
|
@selection-change="(selection) => handleSelectionChange(selection, locationItem.vehicleNo)"
|
||
|
|
:ref="`table_${locationIndex}`">
|
||
|
|
<el-table-column type="selection" width="55" />
|
||
|
|
<el-table-column prop="goodsId" label="物料编号" />
|
||
|
|
<el-table-column prop="goodsName" label="物料名称" />
|
||
|
|
<el-table-column prop="goodsType" label="规格" />
|
||
|
|
<el-table-column prop="specification" label="说明" />
|
||
|
|
<el-table-column prop="quantity" label="数量" />
|
||
|
|
<el-table-column prop="neibubianhao" label="内部编号" />
|
||
|
|
<el-table-column prop="xsfbillno" label="销售单号" />
|
||
|
|
<el-table-column prop="xsfseq" label="行号" />
|
||
|
|
<el-table-column prop="storeTime" label="入库时间">
|
||
|
|
<template #default="scope">
|
||
|
|
{{ scope.row.storeTime ? scope.row.storeTime.split('T')[0] + ' ' + scope.row.storeTime.split('T')[1] : '' }}
|
||
|
|
</template>
|
||
|
|
</el-table-column>
|
||
|
|
</el-table>
|
||
|
|
</div>
|
||
|
|
<div class="batch-action-bar">
|
||
|
|
<el-button type="danger" @click="batchOut" :disabled="getTotalSelectedCount() === 0">出库</el-button>
|
||
|
|
<span class="selection-info">已选择 {{ getTotalSelectedCount() }} 项</span>
|
||
|
|
</div>
|
||
|
|
</fieldset>
|
||
|
|
|
||
|
|
<el-dialog v-model="responseDialogVisible" title="请求结果" width="500px">
|
||
|
|
<pre>{{ responseResult }}</pre>
|
||
|
|
<template #footer>
|
||
|
|
<span class="dialog-footer">
|
||
|
|
<el-button type="primary" @click="responseDialogVisible = false">确定</el-button>
|
||
|
|
</span>
|
||
|
|
</template>
|
||
|
|
</el-dialog>
|
||
|
|
</div>
|
||
|
|
</el-container>
|
||
|
|
</el-config-provider>
|
||
|
|
</template>
|
||
|
|
|
||
|
|
<script setup>
|
||
|
|
import { reactive, ref, onMounted, nextTick, onBeforeUnmount } from 'vue'
|
||
|
|
import { ElMessage } from 'element-plus'
|
||
|
|
import zhCn from 'element-plus/dist/locale/zh-cn.mjs'
|
||
|
|
import { loading } from '@/utils/loading.js'
|
||
|
|
import { errorBox } from '@/utils/myMessageBox.js'
|
||
|
|
import { labelPosition } from '@/constant/form'
|
||
|
|
import { submitOrderOutForm, localQuery } from '@/api/orderOut.js'
|
||
|
|
|
||
|
|
// 生成订单号方法
|
||
|
|
const generateOrderId = () => {
|
||
|
|
const now = new Date()
|
||
|
|
const year = now.getFullYear()
|
||
|
|
const month = String(now.getMonth() + 1).padStart(2, '0')
|
||
|
|
const day = String(now.getDate()).padStart(2, '0')
|
||
|
|
const hours = String(now.getHours()).padStart(2, '0')
|
||
|
|
const minutes = String(now.getMinutes()).padStart(2, '0')
|
||
|
|
const seconds = String(now.getSeconds()).padStart(2, '0')
|
||
|
|
const milliseconds = String(now.getMilliseconds()).padStart(3, '0')
|
||
|
|
return `baokai${year}${month}${day}${hours}${minutes}${seconds}${milliseconds}`
|
||
|
|
}
|
||
|
|
|
||
|
|
// 表单数据
|
||
|
|
const orderOutFormRef = ref()
|
||
|
|
const orderOutForm = reactive({
|
||
|
|
orderId: generateOrderId(),
|
||
|
|
neibubianhao: '',
|
||
|
|
xsfbillno: '',
|
||
|
|
goodsType: '',
|
||
|
|
clientId: "WMS"
|
||
|
|
})
|
||
|
|
|
||
|
|
// 查询表单数据
|
||
|
|
const queryFormRef = ref()
|
||
|
|
const queryForm = reactive({
|
||
|
|
neibubianhao: '',
|
||
|
|
goodsType: '',
|
||
|
|
xsfbillno: ''
|
||
|
|
})
|
||
|
|
|
||
|
|
// 表格数据
|
||
|
|
const tableData = ref([])
|
||
|
|
const selectedItemsMap = ref(new Map()) // 用Map存储每个载具对应的选中物料
|
||
|
|
|
||
|
|
// 表单规则
|
||
|
|
const rules = reactive({
|
||
|
|
neibubianhao: [{ required: true, message: '请输入内部编号', trigger: 'blur' }],
|
||
|
|
xsfbillno: [{ required: true, message: '请输入销售单号', trigger: 'blur' }],
|
||
|
|
goodsType: [{ required: true, message: '请输入规格', trigger: 'blur' }]
|
||
|
|
})
|
||
|
|
|
||
|
|
// 引用DOM元素
|
||
|
|
const neibubianhaoRef = ref()
|
||
|
|
const xsfbillnoRef = ref()
|
||
|
|
const goodsTypeRef = ref()
|
||
|
|
|
||
|
|
// 响应结果对话框
|
||
|
|
const responseDialogVisible = ref(false)
|
||
|
|
const responseResult = ref({})
|
||
|
|
|
||
|
|
// 初始化时聚焦第一个输入框
|
||
|
|
onMounted(() => {
|
||
|
|
nextTick(() => {
|
||
|
|
neibubianhaoRef.value.focus()
|
||
|
|
window.addEventListener('resize', resizeHeight)
|
||
|
|
})
|
||
|
|
})
|
||
|
|
|
||
|
|
onBeforeUnmount(() => {
|
||
|
|
window.removeEventListener('resize', resizeHeight)
|
||
|
|
})
|
||
|
|
|
||
|
|
// 调整高度
|
||
|
|
const resizeHeight = () => {
|
||
|
|
// 如果需要可以在这里添加高度调整逻辑
|
||
|
|
}
|
||
|
|
|
||
|
|
// 处理回车事件
|
||
|
|
const handleEnter = (nextField) => {
|
||
|
|
const refMap = {
|
||
|
|
'neibubianhao': neibubianhaoRef,
|
||
|
|
'xsfbillno': xsfbillnoRef,
|
||
|
|
'goodsType': goodsTypeRef
|
||
|
|
}
|
||
|
|
|
||
|
|
if (refMap[nextField]) {
|
||
|
|
refMap[nextField].value.focus()
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// 重置表单
|
||
|
|
const resetForm = () => {
|
||
|
|
orderOutFormRef.value.resetFields()
|
||
|
|
// 重新生成订单号
|
||
|
|
orderOutForm.orderId = generateOrderId()
|
||
|
|
nextTick(() => {
|
||
|
|
neibubianhaoRef.value.focus()
|
||
|
|
})
|
||
|
|
}
|
||
|
|
|
||
|
|
// 重置查询表单
|
||
|
|
const resetQueryForm = () => {
|
||
|
|
queryFormRef.value.resetFields()
|
||
|
|
tableData.value = []
|
||
|
|
selectedItemsMap.value.clear()
|
||
|
|
}
|
||
|
|
|
||
|
|
// 查询物料
|
||
|
|
const queryGoods = () => {
|
||
|
|
loading.open()
|
||
|
|
localQuery(queryForm)
|
||
|
|
.then(res => {
|
||
|
|
if (res.data.code === 0) {
|
||
|
|
tableData.value = res.data.returnData || []
|
||
|
|
selectedItemsMap.value.clear() // 清空之前的选择
|
||
|
|
if (tableData.value.length === 0) {
|
||
|
|
ElMessage.info('未查询到相关物料信息')
|
||
|
|
}
|
||
|
|
} else {
|
||
|
|
errorBox(`查询失败: ${res.data.message}`)
|
||
|
|
}
|
||
|
|
})
|
||
|
|
.catch(err => {
|
||
|
|
console.error(err)
|
||
|
|
errorBox('查询物料时发生错误')
|
||
|
|
})
|
||
|
|
.finally(() => {
|
||
|
|
loading.close()
|
||
|
|
})
|
||
|
|
}
|
||
|
|
|
||
|
|
// 处理表格选择变化
|
||
|
|
const handleSelectionChange = (selection, vehicleNo) => {
|
||
|
|
// 为每个载具单独存储选中的物料
|
||
|
|
if (selection.length > 0) {
|
||
|
|
selectedItemsMap.value.set(vehicleNo, selection)
|
||
|
|
} else {
|
||
|
|
selectedItemsMap.value.delete(vehicleNo)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// 获取总选择项数
|
||
|
|
const getTotalSelectedCount = () => {
|
||
|
|
let count = 0
|
||
|
|
selectedItemsMap.value.forEach(items => {
|
||
|
|
count += items.length
|
||
|
|
})
|
||
|
|
return count
|
||
|
|
}
|
||
|
|
|
||
|
|
// 批量出库
|
||
|
|
const batchOut = () => {
|
||
|
|
if (getTotalSelectedCount() === 0) {
|
||
|
|
ElMessage.warning('请至少选择一项物料')
|
||
|
|
return
|
||
|
|
}
|
||
|
|
|
||
|
|
// 根据选中的物料生成载具号列表
|
||
|
|
const selectedVehicleNos = []
|
||
|
|
|
||
|
|
selectedItemsMap.value.forEach((selectedItems, vehicleNo) => {
|
||
|
|
// 为每个选中的物料项添加一个载具号
|
||
|
|
selectedItems.forEach(item => {
|
||
|
|
selectedVehicleNos.push(vehicleNo)
|
||
|
|
})
|
||
|
|
})
|
||
|
|
|
||
|
|
console.log('选中的载具号列表:', selectedVehicleNos)
|
||
|
|
|
||
|
|
if (selectedVehicleNos.length === 0) {
|
||
|
|
ElMessage.warning('无法获取选中物料的载具号')
|
||
|
|
return
|
||
|
|
}
|
||
|
|
|
||
|
|
loading.open()
|
||
|
|
submitOrderOutForm(selectedVehicleNos)
|
||
|
|
.then(res => {
|
||
|
|
responseResult.value = res.data
|
||
|
|
responseDialogVisible.value = true
|
||
|
|
|
||
|
|
if (res.data.code === 0) {
|
||
|
|
ElMessage.success(`出库成功,共处理 ${selectedVehicleNos.length} 项物料`)
|
||
|
|
// 刷新查询结果
|
||
|
|
queryGoods()
|
||
|
|
} else {
|
||
|
|
errorBox(`出库失败: ${res.data.message}`)
|
||
|
|
}
|
||
|
|
})
|
||
|
|
.catch(err => {
|
||
|
|
console.error(err)
|
||
|
|
errorBox('出库时发生错误')
|
||
|
|
})
|
||
|
|
.finally(() => {
|
||
|
|
loading.close()
|
||
|
|
})
|
||
|
|
}
|
||
|
|
</script>
|
||
|
|
|
||
|
|
<style scoped>
|
||
|
|
.content {
|
||
|
|
display: flex;
|
||
|
|
width: 100%;
|
||
|
|
overflow-x: hidden;
|
||
|
|
}
|
||
|
|
|
||
|
|
.work-area {
|
||
|
|
width: 100%;
|
||
|
|
height: calc(100vh - 160px);
|
||
|
|
padding: 15px;
|
||
|
|
overflow-y: auto;
|
||
|
|
overflow-x: hidden;
|
||
|
|
box-sizing: border-box;
|
||
|
|
}
|
||
|
|
|
||
|
|
.main-area {
|
||
|
|
width: 100%;
|
||
|
|
margin-bottom: 20px;
|
||
|
|
padding: 15px;
|
||
|
|
border: 1px solid #dcdfe6;
|
||
|
|
border-radius: 4px;
|
||
|
|
box-sizing: border-box;
|
||
|
|
}
|
||
|
|
|
||
|
|
legend {
|
||
|
|
padding: 0 10px;
|
||
|
|
font-weight: bold;
|
||
|
|
}
|
||
|
|
|
||
|
|
pre {
|
||
|
|
white-space: pre-wrap;
|
||
|
|
word-wrap: break-word;
|
||
|
|
background-color: #f8f8f8;
|
||
|
|
padding: 15px;
|
||
|
|
border-radius: 4px;
|
||
|
|
max-height: 300px;
|
||
|
|
overflow-y: auto;
|
||
|
|
}
|
||
|
|
|
||
|
|
:deep(.el-input),
|
||
|
|
:deep(.el-input-number) {
|
||
|
|
width: 100%;
|
||
|
|
}
|
||
|
|
|
||
|
|
.form-row {
|
||
|
|
display: flex;
|
||
|
|
align-items: center;
|
||
|
|
}
|
||
|
|
|
||
|
|
:deep(.custom-input) {
|
||
|
|
width: 100%;
|
||
|
|
}
|
||
|
|
|
||
|
|
:deep(.custom-input .el-input__inner),
|
||
|
|
:deep(.custom-input .el-input-number__decrease),
|
||
|
|
:deep(.custom-input .el-input-number__increase),
|
||
|
|
:deep(.custom-input .el-input-number__inner) {
|
||
|
|
height: 40px;
|
||
|
|
line-height: 40px;
|
||
|
|
}
|
||
|
|
|
||
|
|
.btn-col {
|
||
|
|
display: flex;
|
||
|
|
align-items: center;
|
||
|
|
justify-content: space-around;
|
||
|
|
}
|
||
|
|
|
||
|
|
.btn-col .el-button {
|
||
|
|
margin-left: 0;
|
||
|
|
height: 40px;
|
||
|
|
}
|
||
|
|
|
||
|
|
.location-group {
|
||
|
|
margin-bottom: 20px;
|
||
|
|
}
|
||
|
|
|
||
|
|
.location-header {
|
||
|
|
background-color: #f5f7fa;
|
||
|
|
padding: 8px 15px;
|
||
|
|
border-radius: 4px 4px 0 0;
|
||
|
|
margin-bottom: 5px;
|
||
|
|
}
|
||
|
|
|
||
|
|
.location-header h3 {
|
||
|
|
margin: 0;
|
||
|
|
font-size: 14px;
|
||
|
|
color: #606266;
|
||
|
|
}
|
||
|
|
|
||
|
|
.batch-action-bar {
|
||
|
|
margin-top: 15px;
|
||
|
|
display: flex;
|
||
|
|
align-items: center;
|
||
|
|
}
|
||
|
|
|
||
|
|
.selection-info {
|
||
|
|
margin-left: 15px;
|
||
|
|
color: #606266;
|
||
|
|
font-size: 14px;
|
||
|
|
}
|
||
|
|
</style>
|