<template>
|
<div class="scan-container">
|
<el-card class="scan-card">
|
<div slot="header" class="clearfix">
|
<span>灯光扫描入库</span>
|
</div>
|
<el-row>
|
<el-col :span="12">
|
<el-form ref="form" :model="formData" label-width="120px" class="scan-form">
|
<el-form-item label="预到货单号">
|
<el-input ref="orderCode" v-model="formData.orderCode" class="input-300" autofocus @keyup.native.enter.stop="getData"></el-input>
|
<span class="sub-item">
|
<span class="sub-label">物料校验:</span>
|
<el-switch v-model="formData.isValidateProductCode" @change="onIsValidateProductCodeChange"></el-switch>
|
</span>
|
</el-form-item>
|
<el-form-item label="上架货位">
|
<el-input ref="positionName" v-model="formData.positionName" class="input-300" @keyup.native.enter.stop="positionNameEnter"></el-input>
|
<span class="sub-item">
|
<span class="sub-label">直接上架:</span>
|
<el-switch v-model="formData.isOnShelve" @change="onIsOnShelveChange"></el-switch>
|
</span>
|
</el-form-item>
|
<el-form-item label="物料条码">
|
<el-input ref="productModel" v-model="formData.productModel" :disabled="!formData.isValidateProductCode" class="w-250" @keyup.native.enter.stop="checkPackingBarcode"></el-input>
|
<span class="sub-item">
|
<span class="sub-label">扫描数量:</span>
|
<!-- :min="1" -->
|
<el-input-number ref="scanQty" v-model="formData.scanQty" :min="1" :disabled="!formData.isValidateProductCode" class="input-100" controls-position="right" @change="changeScanQty"></el-input-number>
|
</span>
|
</el-form-item>
|
<el-form-item>
|
<el-button type="primary" @click="lightLabel">点亮标签</el-button>
|
<el-button type="primary" @click="saveCheck">确认入库</el-button>
|
<el-button @click="onReset">重置</el-button>
|
</el-form-item>
|
</el-form>
|
</el-col>
|
<el-col :span="12">
|
<el-form ref="form" :model="formData" label-width="120px" class="scan-form">
|
<el-form-item label="灯光服务器地址">
|
<el-input v-model="serverIP" class="w-300" @keyup.native.enter.stop="getWayBillPrinter"></el-input>
|
</el-form-item>
|
<el-form-item>
|
<el-button type="primary" @click="connectSocketServer('showMsg')">连接服务器</el-button>
|
<el-tag :type="serverStatus==='已连接服务器'?'success':'danger'">{{ serverStatus }}</el-tag>
|
</el-form-item>
|
</el-form>
|
</el-col>
|
</el-row>
|
</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="['unFinishedQuantity','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" :max="scope.row['quantity']" 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="'rowStatus'.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-tag v-if="scope.row.rowStatus==='已确认'" type="success" effect="dark">
|
{{ scope.row.rowStatus }}
|
</el-tag>
|
<el-tag v-else type="warning">
|
{{ scope.row.rowStatus }}
|
</el-tag>
|
</template>
|
</template>
|
</el-table-column>
|
</template>
|
<template v-else-if="'positionName,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-if="'produceDate,limitDate'.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-date-picker v-model="scope.row[item.prop]" size="mini" type="date" placeholder="选择日期" class="w-110" value-format="yyyy-MM-dd">
|
</el-date-picker>
|
</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: "inbound-scan-order-light",
|
components: {
|
ScanSettingDialog
|
},
|
mixins: [YrtScanMixins],
|
data() {
|
return {
|
formData: {
|
orderCode: null,
|
// 是否校验物料
|
isValidateProductCode: true,
|
// 自动生成上架单
|
isOnShelve: false,
|
positionName: null,
|
productModel: null,
|
scanQty: null
|
},
|
// 明细数据
|
tableData: [],
|
// 仓库ID
|
storage_Id: 0,
|
// 当前正在扫描的数据 {}
|
currentRow: null,
|
// 已经找到的数据
|
existRows: [],
|
// 装箱方式:0:常规扫描,1:一品一箱,2:多品一箱
|
caseMode: 0,
|
// 一次扫描的数量
|
scanCount: 1,
|
// 装箱新增行
|
caseNewRows: [],
|
// 配置参数
|
config: {
|
// 自动生成上架单
|
in_generateShelve: true,
|
// 是否启用装箱操作
|
in_caseNumber: false,
|
// 支持一品多码
|
sku_productToMultiBarcode: true
|
},
|
/** ***********************
|
* websockect
|
* *********************** */
|
// 服务器IP
|
serverIP: null,
|
ws: null,
|
// 服务器状态
|
serverStatus: "未连接",
|
// 扫描列设置对话框参数
|
setting: {
|
visible: false,
|
name: "inbound-scan-order-light",
|
fields: [
|
{
|
prop: "productModel",
|
label: "条形码",
|
visible: true,
|
width: 130,
|
order: 1
|
},
|
{
|
prop: "quantity",
|
label: "清单数量",
|
visible: true,
|
width: 80,
|
order: 2
|
},
|
{
|
prop: "enterQuantity",
|
label: "已入库数量",
|
visible: true,
|
width: 90,
|
order: 3
|
},
|
{
|
prop: "finishedQuantity",
|
label: "已扫描数量",
|
visible: true,
|
width: 90,
|
order: 4
|
},
|
{
|
prop: "unFinishedQuantity",
|
label: "未扫描数量",
|
visible: true,
|
width: 90,
|
order: 5
|
},
|
{
|
prop: "productCode",
|
label: "物料编号",
|
visible: false,
|
width: 130,
|
order: 6
|
},
|
{
|
prop: "smallUnit",
|
label: "单位",
|
visible: true,
|
width: 50,
|
order: 7
|
},
|
{
|
prop: "positionName",
|
label: "上架货位",
|
visible: true,
|
width: 120,
|
order: 8
|
},
|
{
|
prop: "rowStatus",
|
label: "上架状态",
|
visible: true,
|
width: 300,
|
order: 8
|
},
|
{
|
prop: "produceDate",
|
label: "生产日期",
|
visible: true,
|
width: 130,
|
order: 9
|
},
|
{
|
prop: "limitDate",
|
label: "到期日期",
|
visible: false,
|
width: 130,
|
order: 10
|
},
|
{
|
prop: "purchasePrice",
|
label: "单价",
|
visible: false,
|
width: 80,
|
order: 11
|
},
|
{
|
prop: "productSpec",
|
label: "物料规格",
|
visible: true,
|
width: 80,
|
order: 12
|
},
|
{
|
prop: "weight",
|
label: "单位毛重",
|
visible: false,
|
width: 80,
|
order: 13
|
},
|
{
|
prop: "sumTotalWeight",
|
label: "合计重量",
|
visible: false,
|
width: 80,
|
order: 14
|
},
|
{
|
prop: "scanWeight",
|
label: "已扫重量",
|
visible: false,
|
width: 80,
|
order: 15
|
},
|
{
|
prop: "productName",
|
label: "物料名称",
|
visible: true,
|
width: null,
|
order: 16
|
}
|
]
|
}
|
};
|
},
|
computed: {
|
// 服务器地址
|
serverDomain: function() {
|
return "ws://" + this.serverIP + ":2888/";
|
}
|
},
|
// 监听数据
|
watch: {
|
// 当前行扫描数据改变后,将扫描数量也改变
|
currentRow: {
|
handler: function(rowData) {
|
if (rowData) {
|
this.formData.scanQty = rowData.finishedQuantity;
|
}
|
},
|
deep: true
|
}
|
},
|
mounted() {
|
this.serverIP = localStorage.getItem("serverIP");
|
// 连接灯光系统
|
this.connectSocketServer();
|
setInterval(() => {
|
if (!this.ws || this.ws.readyState === 2 || this.ws.readyState === 3) {
|
this.connectSocketServer();
|
}
|
}, 20 * 1000);
|
|
// 字段设置
|
const setting = localStorage[this.setting.name + "-setting"];
|
if (setting) {
|
this.setting.fields = JSON.parse(setting);
|
}
|
const isOnShelve = localStorage["isOnShelve"];
|
if (isOnShelve) {
|
this.formData.isOnShelve = isOnShelve === "true";
|
}
|
const isValidateProductCode = localStorage["isValidateProductCode"];
|
if (isOnShelve) {
|
this.formData.isValidateProductCode = isValidateProductCode === "true";
|
}
|
},
|
methods: {
|
// 连接服务器
|
connectSocketServer(type) {
|
const userInfo = this.common.getUserInfo();
|
const support = "MozWebSocket" in window ? "MozWebSocket" : "WebSocket" in window ? "WebSocket" : null;
|
localStorage.setItem("serverIP", this.serverIP);
|
|
if (support == null) {
|
alert("Your browser cannot support WebSocket!");
|
return;
|
}
|
|
if (this.ws) {
|
this.ws.close();
|
}
|
|
// 0 (CONNECTING), 1 (OPEN), 2 (CLOSING),3 (CLOSED)
|
if (!this.ws || this.ws.readyState === 2 || this.ws.readyState === 3) {
|
this.ws = new window[support](this.serverDomain);
|
} else {
|
this.$message.warning("已连接,无需重复连接");
|
}
|
|
this.ws.onerror = function(e) {
|
// console.log(e);
|
};
|
|
this.ws.onmessage = evt => {
|
var data = JSON.parse(evt.data);
|
if (data.action === "CloseLabelLight") {
|
this.tableData.forEach(item => {
|
if (item.orderList_Id === data.rowId) {
|
item.rowStatus = "已确认";
|
}
|
});
|
}
|
};
|
|
// when the connection is established, this method is called
|
this.ws.onopen = () => {
|
var msg = {};
|
msg.action = "SetOnline";
|
msg.fromMobile = userInfo.mobile;
|
this.ws.send(JSON.stringify(msg));
|
this.serverStatus = "已连接服务器";
|
if (type === "showMsg") {
|
if (this.serverStatus === "已连接服务器") {
|
this.$message.success(this.serverStatus);
|
} else {
|
this.$message.error(this.serverStatus);
|
}
|
}
|
};
|
|
// when the connection is closed, this method is called
|
this.ws.onclose = () => {
|
this.serverStatus = "未连接服务器";
|
};
|
},
|
// 点亮标签
|
lightLabel() {
|
const dataList = this.tableData
|
.filter(item => {
|
return item.finishedQuantity > 0 && item.rowStatus !== "已确认";
|
})
|
.map(item => {
|
return {
|
rowId: item.orderList_Id,
|
positionName: item.positionName,
|
qty: item.finishedQuantity,
|
status: "未点亮"
|
};
|
});
|
if (!dataList.length) {
|
this.$message.error("没有可提交的数据");
|
return;
|
}
|
if (!this.ws || this.ws.readyState === 2 || this.ws.readyState === 3) {
|
this.$message.warning("未连接灯光系统,无法点亮");
|
return;
|
}
|
|
const dataInfo = {
|
action: "SendCode",
|
dataList: dataList
|
};
|
this.ws.send(JSON.stringify(dataInfo));
|
},
|
// 直接上架设置
|
onIsValidateProductCodeChange() {
|
localStorage["isValidateProductCode"] = this.formData.isValidateProductCode;
|
},
|
// 直接上架设置
|
onIsOnShelveChange() {
|
localStorage["isOnShelve"] = this.formData.isOnShelve;
|
},
|
// 获得明细数据
|
getData() {
|
var orderCode = this.formData.orderCode;
|
if (!orderCode) {
|
this.$message.error("预到货单号不能为空");
|
return;
|
}
|
const url = "/api/inbound/inScan/getData";
|
const params = {
|
openNodeApi: true,
|
orderCode: orderCode,
|
isOnShelve: this.formData.isOnShelve
|
};
|
var callback = res => {
|
this.common.showMsg(res);
|
if (res.result) {
|
// 构建数据
|
this.currentRow = null;
|
this.formData.positionName = null;
|
this.formData.productModel = null;
|
this.formData.scanQty = null;
|
this.tableData = res.data.map(row => {
|
row.unFinishedQuantity = row.quantity - row.enterQuantity;
|
row.finishedQuantity = 0;
|
row.sortIndex = 0;
|
row.scanWeight = 0;
|
row.rowStatus = "未确认";
|
return row;
|
});
|
if (!this.formData.isValidateProductCode) {
|
this.tableData.forEach(row => {
|
row.finishedQuantity = row.unFinishedQuantity;
|
row.unFinishedQuantity = 0;
|
});
|
}
|
// 获取货位
|
this.storage_Id = parseInt(res.stateCode);
|
this.$refs.positionName.select();
|
this.$refs.positionName.focus();
|
}
|
};
|
this.common.ajax(url, params, callback, true);
|
},
|
// 货位回车
|
positionNameEnter() {
|
this.$refs.productModel.select();
|
this.$refs.productModel.focus();
|
},
|
// 判断扫描包装条码
|
checkPackingBarcode(evt) {
|
this.checkPackingProductModel(this.tableData, () => {
|
this.currentRow.positionName = this.formData.positionName;
|
});
|
},
|
// 扫描数量手工改变
|
changeScanQty() {
|
this.setScanQty();
|
},
|
// 行数据改变
|
rowChangeQty(prop, row) {
|
if (prop === "finishedQuantity") {
|
row.unFinishedQuantity = row.quantity - row.finishedQuantity;
|
} else if (prop === "unFinishedQuantity") {
|
row.finishedQuantity = row.quantity - row.unFinishedQuantity;
|
}
|
},
|
// 重置onReset
|
onReset() {
|
this.formData = {
|
orderCode: null,
|
isValidateProductCode: true, // 是否校验物料
|
positionName: null,
|
productModel: null,
|
scanQty: 0
|
};
|
this.tableData = [];
|
this.focus("orderCode");
|
},
|
|
// 入库时保质期如果超过一定时长(可设定)需要预警提示是否入库
|
saveCheck() {
|
if (!this.formData.positionName && this.formData.isValidateProductCode) {
|
// 常规入库
|
this.$message.error("请扫描收货位!");
|
this.$refs.positionName.focus();
|
this.$refs.sound_error.play(); // 播放声音
|
return;
|
}
|
if (!this.formData.orderCode) {
|
this.$message.error("请扫描预到货单号!");
|
this.$refs.orderCode.focus();
|
this.$refs.sound_error.play(); // 播放声音
|
return;
|
}
|
|
var existRows = this.tableData.some(item => {
|
return item.rowStatus === "未确认" && item.finishedQuantity > 0;
|
});
|
|
// 执行上架操作
|
const doWork = noTip => {
|
var dataList = [];
|
// 不校验物料
|
if (this.formData.isValidateProductCode === false) {
|
this.tableData.forEach(rowData => {
|
var orderList_Id = rowData.orderList_Id;
|
var finishedQuantity = rowData.unFinishedQuantity;
|
if (finishedQuantity <= 0) return;
|
|
dataList.push({
|
orderList_Id: orderList_Id,
|
finishedQuantity: finishedQuantity,
|
PlateCode: null
|
});
|
});
|
} else {
|
// 校验物料
|
var code = this.formData.productModel;
|
this.tableData.forEach(rowData => {
|
if (rowData.productModel === code) {
|
var orderList_Id = rowData.orderList_Id;
|
var finishedQuantity = rowData.finishedQuantity;
|
var PlateCode = rowData.productModel;
|
if (finishedQuantity <= 0) return;
|
|
dataList.push({
|
orderList_Id: orderList_Id,
|
finishedQuantity: finishedQuantity,
|
PlateCode: PlateCode
|
});
|
}
|
});
|
if (!dataList.length) {
|
this.$message.error("没有扫描可用的数据!");
|
return;
|
}
|
}
|
|
if (!noTip && !window.confirm("当前扫描要确认入库吗?")) return;
|
var url = "/api/inbound/inScan/saveCheck";
|
var params = {
|
openNodeApi: true,
|
orderCode: this.formData.orderCode,
|
positionName: this.formData.positionName,
|
dataList: dataList
|
};
|
this.common.ajax(
|
url,
|
params,
|
res => {
|
if (res.result) {
|
// 强制关闭所有灯光
|
const userInfo = this.common.getUserInfo();
|
if (this.ws && this.ws.readyState === 1) {
|
const msg = {};
|
msg.action = "CloseLabelLight";
|
msg.fromMobile = userInfo.mobile;
|
this.ws.send(JSON.stringify(msg));
|
}
|
|
if (this.config.in_generateShelve) {
|
this.saveAndShelve();
|
} else {
|
this.save();
|
}
|
} else {
|
this.modify(res.msg);
|
}
|
},
|
this.$refs.form
|
);
|
};
|
if (existRows) {
|
this.$confirm("已扫描上架的物料未确认上架,是否强制上架?", "提示", {
|
confirmButtonText: "确定",
|
cancelButtonText: "取消",
|
type: "warning"
|
})
|
.then(() => {
|
doWork(true);
|
})
|
.catch(() => {
|
this.$message({
|
type: "info",
|
message: "已取消"
|
});
|
});
|
} else {
|
doWork();
|
}
|
},
|
// 入库保质期超期,强行收货
|
modify(msg) {
|
this.$confirm(msg, "提示", {
|
confirmButtonText: "确定",
|
cancelButtonText: "取消",
|
type: "warning"
|
})
|
.then(() => {
|
if (this.config.in_generateShelve) {
|
this.saveAndShelve();
|
} else {
|
this.save();
|
}
|
})
|
.catch(() => {
|
this.$message.info("已取消");
|
});
|
},
|
// 确认入库
|
save() {
|
if (!this.formData.positionName && this.formData.isValidateProductCode) {
|
// 常规入库
|
this.$message.error("请扫描收货位!");
|
this.$refs.positionName.focus();
|
this.$refs.sound_error.play(); // 播放声音
|
return;
|
}
|
if (!this.formData.orderCode) {
|
this.$message.error("请扫描预到货单号!");
|
this.$refs.orderCode.focus();
|
this.$refs.sound_error.play(); // 播放声音
|
return;
|
}
|
|
var emptyPositionName = this.tableData
|
.filter(item => {
|
return !item.positionName && item.finishedQuantity > 0;
|
})
|
.map(item => {
|
return item.productModel;
|
});
|
if (emptyPositionName.length) {
|
this.$message.error("条形码[" + emptyPositionName.join(",") + "]货位不能为空!");
|
this.$refs.sound_error.play(); // 播放声音
|
return;
|
}
|
|
var dataList = [];
|
this.tableData.forEach(rowData => {
|
if (!rowData.finishedQuantity <= 0) return;
|
|
dataList.push({
|
orderList_Id: rowData.orderList_Id,
|
finishedQuantity: rowData.finishedQuantity,
|
positionName: rowData.positionName,
|
produceDate: rowData.produceDate,
|
limitDate: rowData.limitDate,
|
PlateCode: rowData.PlateCode
|
});
|
});
|
|
var url = "/api/inbound/inScan/save";
|
var params = {
|
openNodeApi: true,
|
orderCode: this.formData.orderCode,
|
positionName: this.formData.positionName,
|
lightSortInfo_Id: null,
|
dataList: dataList
|
};
|
this.common.ajax(
|
url,
|
params,
|
function(res) {
|
this.common.showMsg(res);
|
if (res.result) {
|
this.onReset();
|
this.$refs.sound_correct.play(); // 播放声音
|
} else {
|
this.$refs.sound_error.play(); // 播放声音
|
}
|
},
|
this.$refs.form
|
);
|
},
|
// 确认入库并自动生成上架单
|
saveAndShelve() {
|
if (!this.formData.positionName && this.formData.isValidateProductCode) {
|
// 常规入库
|
this.$message.error("请扫描收货位!");
|
this.$refs.sound_error.play(); // 播放声音
|
this.focus("positionName");
|
return;
|
}
|
if (!this.formData.orderCode) {
|
this.$message.error("请扫描预到货单号!");
|
this.$refs.sound_error.play(); // 播放声音
|
this.focus("orderCode");
|
return;
|
}
|
|
var emptyPositionName = this.tableData
|
.filter(item => {
|
return !item.positionName;
|
})
|
.map(item => {
|
return item.productModel;
|
});
|
if (emptyPositionName.length) {
|
this.$message.error("条形码[" + emptyPositionName.join(",") + "]货位不能为空!");
|
this.$refs.sound_error.play(); // 播放声音
|
return;
|
}
|
|
var dataList = this.tableData.filter(item => item.finishedQuantity > 0);
|
|
var url = "/api/inbound/inScan/saveAndShelve";
|
var params = {
|
orderCode: this.formData.orderCode,
|
positionName: this.formData.positionName,
|
dataList: dataList
|
};
|
this.common.ajax(
|
url,
|
params,
|
res => {
|
this.common.showMsg(res);
|
if (res.result) {
|
this.onReset();
|
this.$refs.sound_correct.play(); // 播放声音
|
} else {
|
this.$refs.sound_error.play(); // 播放声音
|
}
|
},
|
this.$refs.form
|
);
|
},
|
// 收货位
|
positionNameClick(item) {
|
const positionName = item.Name;
|
this.tableData.forEach(rowData => {
|
rowData.positionName = positionName;
|
});
|
}
|
}
|
};
|
</script>
|
|
<style lang="scss" scoped>
|
@import "../../../styles/scan.scss";
|
</style>
|