You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
332 lines
15 KiB
332 lines
15 KiB
|
3 years ago
|
<!DOCTYPE html>
|
||
|
|
<html xmlns:th="http://www.w3.org/1999/xhtml">
|
||
|
|
<html xmlns:th="http://www.thymeleaf.org">
|
||
|
|
<head>
|
||
|
|
<meta charset="utf-8">
|
||
|
|
<title>扫码</title>
|
||
|
|
<link rel="stylesheet" href="/static/lib/layui-v2.6.3/css/layui.css" media="all">
|
||
|
|
<link rel="stylesheet" href="/static/css/layuimini.css?v=2.0.4.2" media="all">
|
||
|
|
<link rel="stylesheet" href="/static/css/themes/default.css" media="all">
|
||
|
|
<link rel="stylesheet" href="/static/lib/font-awesome-4.7.0/css/font-awesome.min.css" media="all">
|
||
|
|
<!--[if lt IE 9]>
|
||
|
|
<script src="/static/js/html5.min.js"></script>
|
||
|
|
<script src="/static/js/respond.min.js"></script>
|
||
|
|
<![endif]-->
|
||
|
|
<!-- vue相关-->
|
||
|
|
<script src="../static/js/vue/vue.js"></script>
|
||
|
|
<script src="../static/js/vue/vue-router.js"></script>
|
||
|
|
<script src="../static/lib/http-vue-loader/src/httpVueLoader.js"></script>
|
||
|
|
<script src="../static/js/VueQrcodeReader.umd.min.js"></script>
|
||
|
|
<style>
|
||
|
|
.validation-success,
|
||
|
|
.validation-failure,
|
||
|
|
.validation-pending {
|
||
|
|
position: absolute;
|
||
|
|
width: 100%;
|
||
|
|
height: 100%;
|
||
|
|
|
||
|
|
background-color: rgba(255, 255, 255, .8);
|
||
|
|
text-align: center;
|
||
|
|
font-weight: bold;
|
||
|
|
font-size: 1.4rem;
|
||
|
|
padding: 10px;
|
||
|
|
|
||
|
|
display: flex;
|
||
|
|
flex-flow: column nowrap;
|
||
|
|
justify-content: center;
|
||
|
|
}
|
||
|
|
|
||
|
|
.validation-success {
|
||
|
|
color: green;
|
||
|
|
}
|
||
|
|
|
||
|
|
.validation-failure {
|
||
|
|
color: red;
|
||
|
|
}
|
||
|
|
</style>
|
||
|
|
</head>
|
||
|
|
<body>
|
||
|
|
<div id="app">
|
||
|
|
<input id="id" style="display: none" th:value="${record.getId()}">
|
||
|
|
<input id="mcode" style="display: none" th:value="${materialById.getCode()}">
|
||
|
|
<input id="depositoryId" style="display: none" th:value="${record.getDepositoryId()}">
|
||
|
|
<input id="quantity" style="display: none" th:value="${record.getQuantity()}">
|
||
|
|
<qrcode-stream :camera="camera" @decode="onDecode" @init="onInit" :track="paintBoundingBox">
|
||
|
|
<div v-if="validationPending" class="validation-pending">
|
||
|
|
Long validation in progress...
|
||
|
|
</div>
|
||
|
|
</qrcode-stream>
|
||
|
|
</div>
|
||
|
|
<script src="/static/lib/layui-v2.6.3/layui.js" charset="utf-8"></script>
|
||
|
|
<script>
|
||
|
|
Vue.use(httpVueLoader);
|
||
|
|
let id = layui.$("#id").val();
|
||
|
|
let mcode = layui.$("#mcode").val();
|
||
|
|
let depositoryId = layui.$("#depositoryId").val();
|
||
|
|
let quantity = layui.$("#quantity").val();
|
||
|
|
var vue = new Vue({
|
||
|
|
data() {
|
||
|
|
return {
|
||
|
|
isValid: undefined,
|
||
|
|
camera: 'auto',
|
||
|
|
result: '',
|
||
|
|
error: '',
|
||
|
|
material: null,
|
||
|
|
depository: null,
|
||
|
|
place: null
|
||
|
|
|
||
|
|
}
|
||
|
|
},
|
||
|
|
computed: {
|
||
|
|
validationPending() {
|
||
|
|
return this.isValid === undefined
|
||
|
|
&& this.camera === 'off'
|
||
|
|
},
|
||
|
|
},
|
||
|
|
methods: {
|
||
|
|
onDecode(result) {
|
||
|
|
let params = {}; // 用于暂存扫描结果
|
||
|
|
this.result = result;
|
||
|
|
let parse = JSON.parse(result);
|
||
|
|
vue.turnCameraOff(); // 暂停扫描
|
||
|
|
if (parse.did !== undefined) {
|
||
|
|
//如果扫描的为仓库
|
||
|
|
this.depository = parse;// 将扫描结果保存到vue中
|
||
|
|
if(this.material == null){
|
||
|
|
// 如果还没有扫描物料
|
||
|
|
layer.confirm("请扫描物料", {
|
||
|
|
btn:["扫描","取消"]
|
||
|
|
},function () { // 继续
|
||
|
|
vue.turnCameraOn(); // 继续扫描
|
||
|
|
layer.close(layer.index); // 关闭弹窗
|
||
|
|
},function () { // 取消
|
||
|
|
// 将vue中暂存的数据置为空
|
||
|
|
this.depository = null;
|
||
|
|
this.place = null;
|
||
|
|
this.material = null;
|
||
|
|
})
|
||
|
|
}
|
||
|
|
else{
|
||
|
|
// 如果已经扫描物料
|
||
|
|
if(depositoryId !== parse.did && Number(depositoryId) !== parse.did && depositoryId !== parse.did.toString()){
|
||
|
|
// 如果当前仓库不是订单对应仓库
|
||
|
|
this.depository = null;
|
||
|
|
this.place = null;
|
||
|
|
layer.msg("出库仓库不正确,请重新扫描");
|
||
|
|
this.turnCameraOn()
|
||
|
|
}else{
|
||
|
|
var req = {};
|
||
|
|
req.id = id;
|
||
|
|
vue.isOutTrue(req);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else if (parse.pid !== undefined){
|
||
|
|
// 如果扫描的为库位
|
||
|
|
this.place = parse;// 将扫描结果保存到vue中
|
||
|
|
if(this.material == null){
|
||
|
|
// 如果还没有扫描物料
|
||
|
|
layer.confirm("请扫描物料", {
|
||
|
|
btn:["扫描","取消"]
|
||
|
|
},function () { // 继续
|
||
|
|
vue.turnCameraOn(); // 继续扫描
|
||
|
|
layer.close(layer.index); // 关闭弹窗
|
||
|
|
},function () { // 取消
|
||
|
|
// 将vue中暂存的库位置为空
|
||
|
|
this.place = null;
|
||
|
|
})
|
||
|
|
}else{
|
||
|
|
if(depositoryId !== parse.depositoryId && Number(depositoryId) !== parse.depositoryId && depositoryId !== parse.depositoryId.toString()){
|
||
|
|
// 如果当前仓库不是订单对应仓库
|
||
|
|
this.depository = null;
|
||
|
|
this.place = null;
|
||
|
|
layer.msg("出库库位所在仓库不正确,请重新扫描");
|
||
|
|
this.turnCameraOn()
|
||
|
|
}else if(parse.mcodeList.indexOf(mcode) === -1){
|
||
|
|
// 如果当前库位不存在该物料
|
||
|
|
this.depository = null;
|
||
|
|
this.place = null;
|
||
|
|
layer.msg("出库库位不含该物料,请重新扫描");
|
||
|
|
this.turnCameraOn()
|
||
|
|
}
|
||
|
|
else{
|
||
|
|
var req = {};
|
||
|
|
req.placeId= this.place.pid;
|
||
|
|
req.id = id;
|
||
|
|
vue.isOutTrue(req);
|
||
|
|
}
|
||
|
|
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else if (parse.mid !== undefined){
|
||
|
|
// 如果扫描的为物料
|
||
|
|
this.material = parse;// 将扫描结果保存到vue中
|
||
|
|
if(mcode !== this.material.code && Number(mcode) !== this.material.code && mcode !== this.material.code.toString()){
|
||
|
|
this.material = null;
|
||
|
|
layer.msg("出库物料不正确,请重新扫描");
|
||
|
|
this.turnCameraOn()
|
||
|
|
}
|
||
|
|
else {
|
||
|
|
if (this.depository !== null) { // 如果已经扫描仓库
|
||
|
|
let depository = this.depository;
|
||
|
|
if (depositoryId !== depository.did && Number(depositoryId) !== depository.did && depositoryId !== depository.did.toString()) {
|
||
|
|
// 如果扫描的仓库不是订单要求的仓库
|
||
|
|
layer.confirm("当前仓库不符合要求,请移步至正确仓库", {
|
||
|
|
btn: ["确定"]
|
||
|
|
}, function () {
|
||
|
|
// 将vue中仓库设为空
|
||
|
|
vue.depository = null;
|
||
|
|
layer.close(layer.index); // 关闭弹窗
|
||
|
|
})
|
||
|
|
} else {
|
||
|
|
// 如果是出库位置为默认库位
|
||
|
|
var req = {};
|
||
|
|
req.id = id;
|
||
|
|
// 弹出确定框
|
||
|
|
vue.isOutTrue(req);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else if(this.place != null){
|
||
|
|
// 如果已经扫描库位
|
||
|
|
if(depositoryId !== this.place.depositoryId && Number(depositoryId) !== this.place.depositoryId && depositoryId !== this.place.depositoryId.toString()){
|
||
|
|
// 如果当前仓库不是订单对应仓库
|
||
|
|
this.depository = null;
|
||
|
|
this.place = null;
|
||
|
|
layer.msg("出库库位所在仓库不正确,请重新扫描");
|
||
|
|
this.turnCameraOn()
|
||
|
|
}else if(this.place.mcodeList.indexOf(mcode) === -1){
|
||
|
|
// 如果当前库位不存在该物料
|
||
|
|
this.depository = null;
|
||
|
|
this.place = null;
|
||
|
|
layer.msg("出库库位不含该物料,请重新扫描");
|
||
|
|
this.turnCameraOn()
|
||
|
|
}
|
||
|
|
else{
|
||
|
|
var req = {};
|
||
|
|
req.id = id;
|
||
|
|
req.placeId= this.place.pid;
|
||
|
|
// 弹出确定框
|
||
|
|
vue.isOutTrue(req);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else {
|
||
|
|
layer.confirm("请扫描仓库或库位", {
|
||
|
|
btn: ["扫描", "取消"]
|
||
|
|
}, function () { // 继续
|
||
|
|
vue.turnCameraOn(); // 继续扫描
|
||
|
|
layer.close(layer.index); // 关闭弹窗
|
||
|
|
}, function () { // 取消
|
||
|
|
// 将vue中暂存的库位置为空
|
||
|
|
this.material = null;
|
||
|
|
})
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
},
|
||
|
|
async onInit(promise) {
|
||
|
|
try {
|
||
|
|
await promise.then(this.resetValidationState)
|
||
|
|
} catch (error) {
|
||
|
|
if (error.name === 'NotAllowedError') {
|
||
|
|
this.error = "ERROR: you need to grant camera access permission"
|
||
|
|
} else if (error.name === 'NotFoundError') {
|
||
|
|
this.error = "ERROR: no camera on this device"
|
||
|
|
} else if (error.name === 'NotSupportedError') {
|
||
|
|
this.error = "ERROR: secure context required (HTTPS, localhost)"
|
||
|
|
} else if (error.name === 'NotReadableError') {
|
||
|
|
this.error = "ERROR: is the camera already in use?"
|
||
|
|
} else if (error.name === 'OverconstrainedError') {
|
||
|
|
this.error = "ERROR: installed cameras are not suitable"
|
||
|
|
} else if (error.name === 'StreamApiNotSupportedError') {
|
||
|
|
this.error = "ERROR: Stream API is not supported in this browser"
|
||
|
|
} else if (error.name === 'InsecureContextError') {
|
||
|
|
this.error = 'ERROR: Camera access is only permitted in secure context. Use HTTPS or localhost rather than HTTP.';
|
||
|
|
} else {
|
||
|
|
this.error = `ERROR: Camera error (${error.name})`
|
||
|
|
}
|
||
|
|
console.log(this.error)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
,
|
||
|
|
resetValidationState() {
|
||
|
|
this.isValid = undefined
|
||
|
|
}
|
||
|
|
,
|
||
|
|
// 绘制二维码跟踪框
|
||
|
|
paintBoundingBox(detectedCodes, ctx) {
|
||
|
|
for (const detectedCode of detectedCodes) {
|
||
|
|
const {boundingBox: {x, y, width, height}} = detectedCode;
|
||
|
|
ctx.lineWidth = 2;
|
||
|
|
ctx.strokeStyle = '#007bff';
|
||
|
|
ctx.strokeRect(x, y, width, height)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
,
|
||
|
|
// 打开相机
|
||
|
|
turnCameraOn() {
|
||
|
|
this.camera = 'auto'
|
||
|
|
}
|
||
|
|
,
|
||
|
|
// 关闭相机
|
||
|
|
turnCameraOff() {
|
||
|
|
this.camera = 'off'
|
||
|
|
},
|
||
|
|
// 将扫描到的数据暂存到redis
|
||
|
|
temporaryScanValue(params) {
|
||
|
|
layui.$.ajax({
|
||
|
|
url: "/material/temporaryValue",
|
||
|
|
type: 'post',
|
||
|
|
dataType: 'json',
|
||
|
|
contentType: "application/json;charset=utf-8",
|
||
|
|
data: JSON.stringify(params)
|
||
|
|
});
|
||
|
|
},
|
||
|
|
// 弹出出库确定弹出框
|
||
|
|
isOutTrue(req){
|
||
|
|
layer.confirm("确定出库?", {
|
||
|
|
btn: ["确定", "取消"]
|
||
|
|
}, function () { // 如果确定出库
|
||
|
|
|
||
|
|
layui.$.ajax({
|
||
|
|
url: "/depositoryRecord/isCheckOut",
|
||
|
|
type: "post",
|
||
|
|
dataType: 'json',
|
||
|
|
data: JSON.stringify(req),
|
||
|
|
contentType: "application/json;charset=utf-8",
|
||
|
|
success: function (res) {
|
||
|
|
if (res.status === 200) {
|
||
|
|
// 如果出库成功
|
||
|
|
layer.msg("出库成功",
|
||
|
|
{icon:6,
|
||
|
|
time:500
|
||
|
|
}
|
||
|
|
, function () {
|
||
|
|
layer.close(layer.index);
|
||
|
|
});
|
||
|
|
layer.close(layer.index)
|
||
|
|
|
||
|
|
} else {
|
||
|
|
// 如果出库失败
|
||
|
|
layer.msg(res.statusInfo.message+",请重试");
|
||
|
|
vue.depository = null;
|
||
|
|
vue.material = null;
|
||
|
|
vue.place = null;
|
||
|
|
// 继续扫描
|
||
|
|
vue.turnCameraOn();
|
||
|
|
return
|
||
|
|
}
|
||
|
|
}
|
||
|
|
})
|
||
|
|
}, function () {
|
||
|
|
// 如果取消
|
||
|
|
vue.depository = null;
|
||
|
|
vue.material = null;
|
||
|
|
vue.place = null;
|
||
|
|
})
|
||
|
|
}
|
||
|
|
|
||
|
|
}
|
||
|
|
}).$mount('#app')
|
||
|
|
</script>
|
||
|
|
</body>
|
||
|
|
</html>
|