<template>
|
<div class="scan-container">
|
<el-card class="scan-card">
|
<div slot="header" class="clearfix">
|
<span>无单扫描出库(支持无出库单,物料条码扫描直接出库)</span>
|
</div>
|
<el-form ref="form" :model="formData" label-width="120px" class="scan-form">
|
<el-form-item label="货主名称">
|
<el-select v-model="formData.consignor_Id" placeholder="请选择" @change="currentConsignorNames">
|
<el-option v-for="item in consignorNames" :key="item.consignor_Id" :label="item.consignorName" :value="item.consignor_Id">
|
</el-option>
|
</el-select>
|
</el-form-item>
|
<el-form-item label="所属仓库">
|
<el-select v-model="formData.storage_Id" placeholder="请选择" @change="currentStorageName">
|
<el-option v-for="item in storageNames" :key="item.storage_Id" :label="item.storageName" :value="item.storage_Id">
|
</el-option>
|
</el-select>
|
</el-form-item>
|
|
<el-form-item label="出库货位">
|
<el-input ref="positionName" v-model="formData.positionName" class="input-300" @keyup.enter.native="focus('productModel')"></el-input>
|
</el-form-item>
|
<el-form-item label="物料条码">
|
<el-input ref="productModel" v-model="formData.productModel" class="input-300" @keyup.native.enter.stop="checkPackingBarcode"></el-input>
|
<span class="sub-item">
|
<span class="sub-label">扫描数量:</span>
|
<!-- :min="1" -->
|
<el-input-number v-model="formData.scanQty" class="input-100" controls-position="right" @change="setScanQty"></el-input-number>
|
</span>
|
</el-form-item>
|
<el-form-item>
|
<el-button type="primary" @click="save">确认出库</el-button>
|
<el-button @click="onReset">重置</el-button>
|
</el-form-item>
|
</el-form>
|
</el-card>
|
<el-card class="scan-card body-no-padding">
|
<div slot="header" class="clearfix">
|
<span class="padding-top-10">扫描结果</span>
|
<el-button type="text" class="floatRight" @click="setting.visible=true">字段设置</el-button>
|
</div>
|
<el-table ref="scan-table" :data="tableData" :row-class-name="rowClass" stripe style="width: 100%" class="scan-table" @row-dblclick="setCurrent">
|
<template v-for="(item, index) in setting.fields">
|
<template v-if="['finishedQuantity'].indexOf(item.prop)>=0">
|
<el-table-column v-if="item.visible" :key="index" :prop="item.prop" :label="item.label" :width="item.width">
|
<template slot-scope="scope">
|
<template v-if="!formData.isValidateProductCode">
|
<el-input-number v-model="scope.row[item.prop]" :min="0" size="mini" class="w-100pc" controls-position="right" @change="rowChangeQty(item.prop, scope.row)"></el-input-number>
|
</template>
|
<template v-else>
|
{{ scope.row[item.prop] }}
|
</template>
|
</template>
|
</el-table-column>
|
</template>
|
<template v-else-if="'scanWeight'.indexOf(item.prop)>=0">
|
<el-table-column v-if="item.visible" :key="index" :prop="item.prop" :label="item.label" :width="item.width">
|
<template slot-scope="scope">
|
<template>
|
<el-input v-model="scope.row[item.prop]" size="mini" class="w-100pc"></el-input>
|
</template>
|
</template>
|
</el-table-column>
|
</template>
|
<template v-else>
|
<el-table-column v-if="item.visible" :key="index" :prop="item.prop" :label="item.label" :width="item.width">
|
</el-table-column>
|
</template>
|
</template>
|
</el-table>
|
</el-card>
|
|
<scan-setting-dialog ref="setting-dialog" :visible.sync="setting.visible" :fields="setting.fields" :name="setting.name">
|
</scan-setting-dialog>
|
<!--声音文件-->
|
<audio ref="sound_error" controls="controls" style="display:none;">
|
<source src="@/assets/sounds/error2.mp3" type="audio/mpeg" />
|
</audio>
|
<audio ref="sound_correct" controls="controls" style="display:none;">
|
<source src="@/assets/sounds/feixin.mp3" type="audio/mpeg" />
|
</audio>
|
<audio controls="controls" style="display:none;">
|
<source ref="sound_scan" src="@/assets/sounds/saomiao.wav" type="audio/mpeg" />
|
</audio>
|
|
</div>
|
</template>
|
|
<script>
|
import YrtScanMixins from "@/components/common/yrtScanMixins.vue";
|
import ScanSettingDialog from "@/components/common/components/scanSettingDialog.vue";
|
export default {
|
name: "scan-purchase-order",
|
components: {
|
ScanSettingDialog
|
},
|
mixins: [YrtScanMixins],
|
data() {
|
return {
|
formData: {
|
orderCode: null,
|
positionName: null,
|
productModel: null,
|
scanQty: null,
|
consignor_Id: null,
|
consignorCode: null,
|
consignorName: null,
|
storage_Id: null, // 仓库id
|
storageName: null // 仓库名称
|
},
|
// 货主
|
consignorNames: [],
|
// 仓库
|
storageNames: [],
|
// 明细数据
|
tableData: [],
|
// 仓库ID
|
storage_Id: 0,
|
// 仓库信息
|
storageInfo: {},
|
// 当前正在扫描的数据 {}
|
currentRow: null,
|
// 已经找到的数据
|
existRows: [],
|
// 装箱方式:0:常规扫描,1:一品一箱,2:多品一箱
|
caseMode: 0,
|
// 一次扫描的数量
|
scanCount: 1,
|
// 装箱新增行
|
caseNewRows: [],
|
// 扫描列设置对话框参数
|
setting: {
|
visible: false,
|
name: "scan-purchase-order",
|
fields: [
|
{
|
prop: "productModel",
|
label: "条形码",
|
visible: true,
|
width: 130,
|
order: 1
|
},
|
{
|
prop: "validQty",
|
label: "有效库存量",
|
visible: true,
|
width: 90,
|
order: 2
|
},
|
{
|
prop: "finishedQuantity",
|
label: "已扫描数量",
|
visible: true,
|
width: 90,
|
order: 3
|
},
|
{
|
prop: "productCode",
|
label: "物料编号",
|
visible: false,
|
width: 130,
|
order: 4
|
},
|
{
|
prop: "positionName",
|
label: "出库货位",
|
visible: true,
|
width: 120,
|
order: 5
|
},
|
{
|
prop: "produceDate",
|
label: "生产日期",
|
visible: true,
|
width: 130,
|
order: 6
|
},
|
|
{
|
prop: "salePrice",
|
label: "销售价",
|
visible: true,
|
width: 110,
|
order: 7
|
},
|
{
|
prop: "batchNumber",
|
label: "批次号",
|
visible: false,
|
width: 120,
|
order: 8
|
},
|
{
|
prop: "productSpec",
|
label: "物料规格",
|
visible: true,
|
width: 110,
|
order: 9
|
},
|
{
|
prop: "weight",
|
label: "单位毛重",
|
visible: false,
|
width: 80,
|
order: 10
|
},
|
{
|
prop: "scanWeight",
|
label: "已扫重量",
|
visible: false,
|
width: 80,
|
order: 11
|
},
|
{
|
prop: "productName",
|
label: "物料名称",
|
visible: true,
|
width: null,
|
order: 16
|
}
|
]
|
},
|
// 配置参数
|
config: {
|
// 自动生成上架单
|
in_generateShelve: true,
|
// 是否启用装箱操作
|
in_caseNumber: false,
|
// 支持一品多码
|
sku_productToMultiBarcode: true
|
}
|
};
|
},
|
mounted() {
|
this.getStorageList();
|
this.getConsignorList();
|
// 字段设置
|
const setting = localStorage[this.setting.name + "-setting"];
|
if (setting) {
|
this.setting.fields = JSON.parse(setting);
|
}
|
},
|
methods: {
|
// 获取仓库
|
getStorageList() {
|
const url = "api/basicInfo/base/storage/getList";
|
const params = {
|
openNodeApi: true
|
};
|
var callback = res => {
|
if (res.result) {
|
this.storageNames = res.data;
|
}
|
};
|
this.common.ajax(url, params, callback, true);
|
},
|
// 获取货主名称下拉框
|
getConsignorList() {
|
const url = "api/basicInfo/base/consignor/getList";
|
const params = {
|
openNodeApi: true
|
};
|
var callback = res => {
|
if (res.result) {
|
this.consignorNames = res.data;
|
}
|
};
|
this.common.ajax(url, params, callback, true);
|
},
|
|
// 判断扫描包装条码
|
checkPackingBarcode(evt) {
|
this.checkPackingProductModel(this.tableData, null, this.getProductInfo);
|
},
|
// 获取物料信息
|
getProductInfo() {
|
if (!this.formData.storage_Id) {
|
this.$message({
|
message: "仓库不能为空!",
|
type: "warning"
|
});
|
return;
|
}
|
if (!this.formData.consignor_Id) {
|
this.$message({
|
message: "货主不能为空!",
|
type: "warning"
|
});
|
return;
|
}
|
if (!this.formData.positionName) {
|
this.$message({
|
message: "货位不能为空!",
|
type: "warning"
|
});
|
return;
|
}
|
if (!this.formData.productModel) {
|
this.$message({
|
message: "条码不能为空!",
|
type: "warning"
|
});
|
return;
|
}
|
const url = "/api/outbound/noBillScan/getProductInfoOut";
|
const params = {
|
storage_Id: this.formData.storage_Id,
|
positionName: this.formData.positionName,
|
productModel: this.formData.productModel,
|
consignor_Id: this.formData.consignor_Id
|
};
|
var callback = res => {
|
this.common.showMsg(res);
|
if (res.result) {
|
// 构建数据
|
this.tableData = res.data.map(row => {
|
row.positionName = this.formData.positionName;
|
row.finishedQuantity = 0;
|
row.unFinishedQuantity = row.validQty;
|
return row;
|
});
|
}
|
this.focus("productModel");
|
};
|
this.common.ajax(url, params, callback, this.$refs["form"]);
|
},
|
// 选择货主之后找值
|
currentConsignorNames(value) {
|
this.consignorNames.forEach(item => {
|
if (item.consignor_Id === value) {
|
this.formData.consignorCode = item.consignorCode;
|
this.formData.consignorName = item.consignorName;
|
}
|
});
|
},
|
// 选择仓库之后找值
|
currentStorageName(value) {
|
this.storageNames.forEach(item => {
|
if (item.storage_Id === value) {
|
this.formData.storageName = item.storageName;
|
}
|
});
|
},
|
// 确认出库
|
save() {
|
var storage_Id = this.formData.storage_Id;
|
var consignor_Id = this.formData.consignor_Id;
|
if (!consignor_Id) {
|
this.$message.error("请选择货主!");
|
return false;
|
}
|
if (!storage_Id) {
|
this.$message.error("请选择仓库!");
|
return false;
|
}
|
this.tableData.forEach(item => {
|
item.storage_Id = this.formData.storage_Id;
|
item.storageName = this.formData.storageName;
|
item.totalWeight = item.scanWeight;
|
});
|
const dataList = this.tableData.filter(item => item.finishedQuantity > 0);
|
var emptyPositionName = dataList
|
.filter(item => {
|
return !item.positionName;
|
})
|
.map(item => {
|
return item.productModel;
|
})
|
.join(",");
|
|
if (emptyPositionName) {
|
this.$message.error("条形码[" + emptyPositionName + "]货位不能为空!");
|
return;
|
}
|
if (!dataList.length) {
|
this.$message.error("请扫描需要出库的物料!");
|
return;
|
}
|
var url = "/api/outbound/noBillScan/saleOuterNoBillSaveByConsignor";
|
var params = {
|
positionName: this.formData.positionName,
|
dataList: dataList
|
};
|
var callback = res => {
|
this.common.showMsg(res);
|
if (res.result) {
|
this.onReset();
|
}
|
};
|
this.common.ajax(url, params, callback, true);
|
},
|
// 重置onReset
|
onReset() {
|
this.formData = {
|
orderCode: null,
|
positionName: null,
|
productModel: null,
|
scanQty: null,
|
consignor_Id: null,
|
consignorCode: null,
|
consignorName: null,
|
storage_Id: null, // 仓库id
|
storageName: null // 仓库名称
|
};
|
this.tableData = [];
|
}
|
}
|
};
|
</script>
|
|
<style lang="scss" scoped>
|
@import "../../../styles/scan.scss";
|
</style>
|