Files
rd_mes_uniapp/pages/wms/pdcIn/directRk.vue
2025-12-18 14:11:48 +08:00

565 lines
18 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<view>
<uni-collapse>
<uni-forms ref="form" :modelValue="formData" :rules="rules" label-align="right">
<uni-collapse-item title="直接入库单" :open="true">
<uni-forms-item label="工单" :labelWidth='80' name="workOrderCode">
<uni-easyinput suffixIcon="scan" @iconClick="scanWorkOrderCode" @change="handleChangeWorkOrderCode"
v-model="workOrderCode" type="text" />
</uni-forms-item>
<uni-forms-item label="产品入库任务单" :labelWidth='80' name="productInTaskCode">
<uni-combox :candidates="productInTaskCodeList" emptyTips="无" @input="fetchTaskInfo"
v-model="formData.productInTaskCode"></uni-combox>
</uni-forms-item>
<uni-forms-item label="上架员" :labelWidth='80' name="shelfPutBy">
<uni-easyinput suffixIcon="scan" @iconClick="scanPutBy" v-model="formData.shelfPutBy" type="text" />
<uni-data-picker popup-title="选择上架员" :localdata="dataTree" v-model="pickerData" @change="onchange"
@nodeclick="onnodeclick" @popupopened="onpopupopened" @popupclosed="onpopupclosed" placeholder="选择上架员"
class="putByPicker" :preload="true">
</uni-data-picker>
</uni-forms-item>
<uni-forms-item label="入库方式" :labelWidth='80'>
<uni-data-checkbox v-model="value" :localdata="pdcInTypeOptions" class="pdcInType" />
</uni-forms-item>
<span v-if="value=='扫物料标签' && formData.wmsProductInDetailList.length == 0" class="scanMatLabel">
<button size="mini" type="primary" class="scanMatLabelBtn" @click="show=!show">
添加物料标签
</button>
</span>
<u-modal :show="show" title="扫描物料标签编码" showCancelButton closeOnClickOverlay @cancel="cancelMaterialLabel"
@close="cancelMaterialLabel" :showConfirmButton="false">
<uni-easyinput suffixIcon="scan" @iconClick="scanBarMaterialLabel" v-model="materialLabel" type="text"
@confirm="confirmMaterialLabel" maxlength="-1" focus="true" />
</u-modal>
</uni-collapse-item>
<uni-collapse-item title="直接入库单明细" :open="true">
<uni-swipe-action>
<uni-swipe-action-item :rightOptions="rightOptions" :key="index"
v-for="(item, index) in formData.wmsProductInDetailList" @click="(data) => clickDetail(index,data)"
@change="swipChange">
<uni-badge :text="index+1" type="primary"></uni-badge>
<uni-forms-item label="物料编码" :labelWidth='90' :name="'wmsProductInDetailList.'+ index +'.materialCode'">
<uni-easyinput type="text" disabled v-model="item.materialCode"></uni-easyinput>
</uni-forms-item>
<uni-forms-item label="物料名称" :labelWidth='90' :name="'wmsProductInDetailList.'+ index +'.materialName'">
<uni-easyinput type="text" disabled v-model="item.materialName"></uni-easyinput>
</uni-forms-item>
<uni-forms-item label="物料批号" :labelWidth='90' name="'wmsProductInDetailList.'+ index +'.materialBatchNo'">
<uni-easyinput type="text" v-model="item.materialBatchNo" />
</uni-forms-item>
<uni-forms-item label="物料箱号" :labelWidth='90' name="'wmsProductInDetailList.'+ index +'.materialLotNo'">
<uni-easyinput disabled type="text" v-model="item.materialLotNo" />
</uni-forms-item>
<uni-forms-item label="类型" :labelWidth='90' name="'wmsProductInDetailList.'+ index +'.type'">
<uni-tag v-if="item.type == 1" text="合格" type="success"></uni-tag>
<uni-tag v-else-if="item.type == 2" text="不良" type="warning"></uni-tag>
<uni-tag v-else-if="item.type == 3" text="报废" type="error"></uni-tag>
</uni-forms-item>
<uni-forms-item label="推荐库位" :label-width="90" ref="myInput">
<uni-easyinput type="text" class="uni-mt-5" v-model="item.recommendLocation" disabled>
<template #right>
<uni-icons custom-prefix="iconfont" type="icon-fuzhi" size="40"
@click="clickCopy(index)"></uni-icons>
</template>
</uni-easyinput>
</uni-forms-item>
<uni-forms-item label="库位条码" :labelWidth='90'
name="'wmsProductInDetailList.'+ index +'.storageLocationBarcode'">
<uni-easyinput suffixIcon="scan" @iconClick="scanBarstorageLocationBarcode(index)" type="text"
v-model="item.storageLocationBarcode" />
</uni-forms-item>
<uni-forms-item label="上架数量" :labelWidth='90' name="'wmsProductInDetailList.'+ index +'number'">
<uni-easyinput disabled type="text" v-model="item.number" v-if="value == '扫物料标签'" />
<u-number-box inputWidth="120" button-size="36" v-model="item.number" :min="0" :max="item.notInNumber" v-else></u-number-box>
</uni-forms-item>
</uni-swipe-action-item>
</uni-swipe-action>
</uni-collapse-item>
</uni-forms>
</uni-collapse>
<view class="opt">
<button @click="clickCopy">一键复制</button>
<button type="primary" @click="submit">提交</button>
</view>
</view>
</template>
<script>
import {
addIn,
listTask,
getTask,
getReveive,
getDetails,
listReceiveDetail,
getDetail,
directProductInByTaskDetail,
getConnectLoc
} from "@/api/wms/pdcIn.js";
import { listDepartment } from "@/api/basic/department";
import { listEmployee } from "@/api/mes/jobIn.js";
import { listWarehouse } from "@/api/wms/warehouse";
import { listStock } from "@/api/wms/stock.js";
import { getConfigKey } from "@/api/system/config.js"
import { getMaterial_code } from "@/api/wms/purchase.js";
import { listLocation } from '@/api/basic/location';
export default {
mounted() {
// 获取任务单编码列表
listTask({
pageNum: 1,
pageSize: 25
}).then(res => {
this.productInTaskCodeList = res.rows.map(item => item.productInTaskCode);
});
// 获取部门列表
listDepartment().then((res) => {
this.dptList = res.rows
})
// 获取员工列表
listEmployee().then((res) => {
this.empList = res.rows
})
// 获取参数: 库位显示级数
getConfigKey('wms.location.size').then(res => {
this.locationSize = res.msg
})
},
data() {
return {
locationSize: null,
value: '正常',
show: false,
materialLabel: null,
workOrderCode: '',
productInTaskCodeList: [],
legalLocation: true,
dptList: [],
empList: [],
item: '',
dataTree: [],
pickerData: '',
formData: {
billType: '2',
status: '3',
productInTaskCode: '',
shelfPutBy: null,
wmsProductInDetailList: [],
},
//类型
pdcInTypeOptions: [
{ text: '正常', value: '正常' },
{ text: '扫物料标签', value: '扫物料标签' },
],
typeOptions: [{
value: 1,
label: "合格",
},
{
value: 2,
label: "不良",
},
{
value: 3,
label: "报废",
},
],
rightOptions: [{
text: '删除',
style: {
backgroundColor: '#ff2a17'
}
}, ],
rules: {
productInTaskCode: {
rules: [{
required: true,
errorMessage: '请输入产品入库任务单!'
}]
},
shelfPutBy: {
rules: [{
required: false,
errorMessage: '请输入上架员编码!'
}]
}
}
}
},
methods: {
// 工单改变
handleChangeWorkOrderCode() {
// 重置任务单列表
this.productInTaskCodeList = [];
// 重置任务单编码
this.formData.productInTaskCode = '';
// 重置明细
this.formData.wmsProductInDetailList = [];
// 获取任务单列表
this.fetchTaskList();
},
// 获取任务单列表
fetchTaskList() {
if (!this.workOrderCode) return;
listTask({
workOrderCode: this.workOrderCode
}).then(async res => {
this.productInTaskCodeList = res.rows.map(item => item.productInTaskCode);
}).catch(err => {
console.error(`获取工单号为${this.workOrderCode}的产品入库任务单列表失败,详情:${err}`);
});
},
// 扫描工单号
scanWorkOrderCode() {
const _this = this;
uni.scanCode({
scanType: ['barCode', 'qrCode'],
success: function(res) {
_this.workOrderCode = res.result;
_this.handleChangeWorkOrderCode();
}
});
},
onnodeclick(e) {
this.item = e
this.onchange(this.item)
},
onpopupopened(e) {
this.dataTree = []
this.empList.filter(item => item.deptId).forEach(item => {
item.departmentTitle = this.dptList.find(item2 => item2.id == item.deptId).departmentTitle
// 检查dataTree中是否已存在相同部门
let existingDept = this.dataTree.find(dept => dept.value === item.deptId);
if (existingDept) {
// 如果已存在相同部门则将员工信息push进该部门的children数组
existingDept.children.push({
text: item.name,
value: item.empCode
});
} else {
// 如果不存在相同部门则创建一个新部门对象包括children数组并将员工信息push进去
let newDept = {
text: item.departmentTitle,
value: item.deptId,
children: [{
text: item.name,
value: item.empCode
}]
};
this.dataTree.push(newDept);
}
})
},
onchange(e) {
this.formData.shelfPutBy = null
this.$set(this.formData, 'shelfPutBy', e.value.split('/')[0])
},
cancelMaterialLabel() {
this.materialLabel = null;
this.show = false;
},
confirmMaterialLabel(data) {
data = JSON.parse(data)
if (data) {
this.id = data.id
getDetail(data.id).then(res => {
if (res.data) {
this.formData.productInTaskCode = res.data.productInTaskCode;
let obj = {
materialCode: res.data.materialCode,
materialName: res.data.materialName,
materialBatchNo: res.data.materialBatchNo,
materialLotNo: res.data.materialLotNo,
type: res.data.type,
storageLocationBarcode: res.data.storageLocationBarcode,
number: res.data.number
}
this.formData.wmsProductInDetailList.push(obj)
this.materialLabel = null;
this.show = false;
} else {
this.$modal.msg("未查询到该条物料明细!")
}
})
}
},
scanBarMaterialLabel() {
const _this = this;
uni.scanCode({
scanType: ['barCode', 'qrCode'],
success: function(res) {
_this.materialLabel = res.result;
// console.log(materialLabel)
_this.confirmMaterialLabel(_this.materialLabel);
}
});
},
// 验证库位合法性
async validateLocation(item) {
const code = item.storageLocationBarcode
if (!code) return false
if (['2', '4'].includes(this.locationSize)) return true
let fullLocation = null
if (this.locationSize == '0') {
fullLocation = code
} else if (this.locationSize == '5') {
// 用两级库位查完整库位
const res = await listLocation({
storageShelvesCode: code.split('-')[0],
storageLocationCode: code.split('-').slice(1).join('-')
})
fullLocation = res.rows[0]?.storageLocationBarcode || null
}
const data = await getConnectLoc({ connectLoc: fullLocation })
if (data.data) {
item.whCode = fullLocation.split('-')[0] || null
item.areaCode = fullLocation.split('-')[1] || null
item.shelvesCode = fullLocation.split('-')[2] || null
item.storageLocationCode = fullLocation.split('-').slice(3).join('-') || null
} else {
this.$modal.msg("库位条码校验错误,请重新输入!")
}
return data.data
},
// 扫描库位编码
scanBarstorageLocationBarcode(i) {
const _this = this;
uni.scanCode({
scanType: ['barCode', 'qrCode'],
success: function(res) {
_this.$set(_this.formData.wmsProductInDetailList[i], "storageLocationBarcode", res.result);
}
});
},
selectTypeList() {
listTask({
pageNum: 1,
pageSize: 25
}).then(async res => {
for (var i in res.rows) {
this.productInTaskCodeList.push(res.rows[i].productInTaskCode);
}
});
},
// 依次获取推荐库位
async fetchLocation(taskDetail) {
const promises = taskDetail.map(async (item) => {
if (!item.materialCode) {
return {
...item,
recommend: null,
recommendLocation: null
}
}
const res = await getMaterial_code(item.materialCode);
// 提供默认值以防 res 为 null 或 undefined
const { data } = res || {};
const recommend = data || null;
const recommendLocation = data ? this.getRecommend(data) : null;
return { ...item, recommend, recommendLocation };
});
// 等待所有异步操作完成
const updatedList = await Promise.all(promises);
return updatedList;
},
async fetchTaskInfo() {
// 清空明细单列表
this.formData.wmsProductInDetailList = [];
if (!this.formData.productInTaskCode) return;
let taskId = null;
let taskDetail = [];
// 获取任务单 id
await listTask({
productInTaskCode: this.formData.productInTaskCode
}).then(res => {
taskId = res.rows[0].id
}).catch(err => {
console.error(`获取入库任务单号为${this.formData.productInTaskCode}的任务单 id 失败,详情:${err}`);
})
// 根据任务单 id 获取任务单明细
await getTask(taskId).then(res => {
taskDetail = res.data.wmsProductInTaskDetailList
}).catch(err => {
console.error(`获取入库任务单 id 为${taskId}的任务单明细失败,详情:${err}`);
})
if (taskDetail.length === 0) return
// 获取推荐库位
this.formData.wmsProductInDetailList = await this.fetchLocation(taskDetail)
console.log("明细单列表: ", this.formData.wmsProductInDetailList)
},
// 上架员
scanPutBy() {
const _this = this;
uni.scanCode({
scanType: ['qrCode', 'barCode'],
success: function(res) {
_this.formData.shelfPutBy = res.result;
}
});
},
// 拆解推荐库位
getRecommend(recommend) {
const { whCode, areaCode, shelvesCode, storageLocationCode } = recommend
if (!(whCode || areaCode || shelvesCode || storageLocationCode)) return null
switch (this.locationSize) {
case '0':
return [whCode, areaCode, shelvesCode, storageLocationCode].join('-')
case '2':
return areaCode
case '4':
return storageLocationCode
case '5':
return [shelvesCode, storageLocationCode].join('-')
}
},
// 校验明细单各项库位是否为空
checkLocation() {
this.formData.wmsProductInDetailList.forEach(item => {
if (!item.storageLocationBarcode) {
this.$modal.msg("库位条码不允许为空")
return false
}
})
return true
},
// 提交
async submit() {
const _this = this;
if (!this.checkLocation()) return
_this.$modal.loading('校验库位中')
await _this.formData.wmsProductInDetailList.forEach(async item => {
// 避免明细传递失败,删除明细 id
delete item.id;
if (!item.storageLocationBarcode) {
this.$modal.msg("库位条码不允许为空");
return;
}
const res = await _this.validateLocation(item)
if (!res) {
item.storageLocationBarcode = null
this.$modal.msg("库位条码校验错误,请重新输入!")
return
}
})
_this.$modal.closeLoading()
this.$refs.form.validate().then(res => {
uni.showModal({
title: '提示',
content: '您确定完成直接入库吗?',
success: function(res) {
if (res.confirm) {
if (_this.value == '扫物料标签') {
let obj = {
id: _this.id,
whCode: _this.formData.wmsProductInDetailList[0].whCode,
areaCode: _this.formData.wmsProductInDetailList[0]
.areaCode,
shelvesCode: _this.formData.wmsProductInDetailList[0]
.shelvesCode,
storageLocationCode: _this.formData.wmsProductInDetailList[
0].storageLocationCode
}
_this.$modal.loading('提交中')
directProductInByTaskDetail(obj).then(async res => {
_this.$modal.closeLoading();
_this.$modal.msgSuccess("入库成功!");
_this.$tab.switchTab('/pages/work/index');
});
} else {
if (_this.formData.productInTaskCode) {
_this.$modal.loading('提交中')
addIn(_this.formData).then(async res => {
_this.$modal.closeLoading();
_this.$modal.msgSuccess("入库成功!");
_this.$tab.switchTab('/pages/work/index');
});
}
}
} else if (res.cancel) {
console.log('用户点击取消');
}
}
});
});
},
// 复制库位
clickCopy(index) {
// 创建新数组避免引用问题
const newList = this.formData.wmsProductInDetailList.map(item => ({ ...item }));
if (typeof index === 'number') {
// 复制单个项
newList[index] = {
...newList[index],
storageLocationBarcode: newList[index].recommendLocation,
whCode: newList[index].recommend.whCode,
areaCode: newList[index].recommend.areaCode,
shelvesCode: newList[index].recommend.shelvesCode,
storageLocationCode: newList[index].recommend.storageLocationCode
};
} else {
// 复制所有项
newList.forEach(item => {
item.storageLocationBarcode = item.recommendLocation;
item.whCode = item.recommend.whCode;
item.areaCode = item.recommend.areaCode;
item.shelvesCode = item.recommend.shelvesCode;
item.storageLocationCode = item.recommend.storageLocationCode;
});
}
// 创建新对象确保响应式更新
this.formData = {
...this.formData,
wmsProductInDetailList: newList
};
}
}
}
</script>
<style lang="scss" scoped>
.putByPicker {
margin-top: 5px;
}
.pdcInType {
margin-top: 6px;
}
.scanMatLabel {
display: flex;
}
.scanMatLabel .scanMatLabelBtn {
justify-content: center;
font-size: 1.1rem;
}
.opt {
// position: fixed;
// bottom: 0;
width: 100%;
padding: 2vw 0;
display: flex;
justify-content: space-evenly;
}
.opt button {
flex: 1;
margin: 0 5px;
}
</style>