diff --git a/RuoYi-App-master/App.vue b/RuoYi-App-master/App.vue index 797f513..94d0026 100644 --- a/RuoYi-App-master/App.vue +++ b/RuoYi-App-master/App.vue @@ -7,6 +7,10 @@ onLaunch: function() { this.initApp() }, + onShow: function() { + // 检查应用状态,确保从后台恢复时状态一致 + this.checkAppState() + }, methods: { // 初始化应用 initApp() { @@ -24,7 +28,30 @@ if (!getToken()) { this.$tab.reLaunch('/pages/login') } - } + }, + checkAppState() { + + + // 检查Token状态和页面导航栈状态 + console.log('应用从后台切换到前台,检查应用状态') + // 检查Token状态 + if (!getToken()) { + console.log('Token不存在,提示并跳转到登录页') + uni.showToast({ + icon: 'none', + title: '登录已过期,请重新登录' + }) + setTimeout(() => { + uni.reLaunch({ url: loginPage }) + }, 1500) + } else { + console.log('Token存在,不做操作') + } + + // 注意:应用从后台切换到前台的逻辑已在permission.js中处理 + // 这里不需要重复处理,保留此方法以便未来扩展 + } + } } diff --git a/RuoYi-App-master/locales/en-US.json b/RuoYi-App-master/locales/en-US.json index 249a9d9..fe9119d 100644 --- a/RuoYi-App-master/locales/en-US.json +++ b/RuoYi-App-master/locales/en-US.json @@ -345,6 +345,7 @@ "scanShelfCode": "Please scan shelf code", "unknownMaterial": "Unknown Material", "noCode": "No Code", + "noQuantity": "No Quantity", "submit": "Submit", "pleaseSelectMaterial": "Please select materials to bind first", "pleaseScanShelfCode": "Please scan shelf code first", diff --git a/RuoYi-App-master/locales/zh-CN.json b/RuoYi-App-master/locales/zh-CN.json index 36e5896..f12c4a1 100644 --- a/RuoYi-App-master/locales/zh-CN.json +++ b/RuoYi-App-master/locales/zh-CN.json @@ -346,6 +346,7 @@ "scanShelfCode": "请扫描料架条码", "unknownMaterial": "未知物料", "noCode": "无编码", + "noQuantity": "无数量", "submit": "提交", "pleaseSelectMaterial": "请先选择需要绑定的物料", "pleaseScanShelfCode": "请先扫描料架条码", diff --git a/RuoYi-App-master/pages/out/bindShell.vue b/RuoYi-App-master/pages/out/bindShell.vue index 5108bac..9874337 100644 --- a/RuoYi-App-master/pages/out/bindShell.vue +++ b/RuoYi-App-master/pages/out/bindShell.vue @@ -88,6 +88,7 @@ {{ item.productName || $t('outbound.bindShelf.unknownMaterial') }} {{ item.productId || $t('outbound.bindShelf.noCode') }} + {{ item.quantity || $t('outbound.bindShelf.noQuantity') }} @@ -244,7 +245,7 @@ export default { this.materialList = (response.rows || []).map(item => ({ ...item, selected: false, - bindQuantity: item.quantit + bindQuantity: item.quantity })) } else { uni.showToast({ @@ -299,6 +300,19 @@ export default { return } + // 检查绑定数量是否为0或空 + const invalidQuantityItem = selectedItems.find(item => { + return !item.bindQuantity || item.bindQuantity === 0 + }) + + if (invalidQuantityItem) { + uni.showToast({ + title: '绑定数量不能为0或空', + icon: 'none' + }) + return + } + this.$refs.bindShelfPopup.open() }, // 关闭绑定料架弹窗 @@ -375,6 +389,19 @@ export default { return } + // 检查绑定数量是否为0或空 + const invalidQuantityItem = selectedItems.find(item => { + return !item.bindQuantity || item.bindQuantity === 0 + }) + + if (invalidQuantityItem) { + uni.showToast({ + title: '绑定数量不能为0或空', + icon: 'none' + }) + return + } + // 这里可以根据实际需求调用相应的API进行提交 // 示例:构建提交数据 const submitData = { diff --git a/RuoYi-App-master/pages/out/errorout.vue b/RuoYi-App-master/pages/out/errorout.vue index 8019ccb..ad963eb 100644 --- a/RuoYi-App-master/pages/out/errorout.vue +++ b/RuoYi-App-master/pages/out/errorout.vue @@ -31,9 +31,9 @@ {{ item.outQuantity }} - {{ $t('outbound.exception.pickQuantity') }}: - {{ item.pickQuantity }} - + {{ $t('outbound.exception.pickQuantity') }}: + + @@ -68,7 +68,13 @@ export default { try { const response = await getTaskDetail({trayCode: value,inOut:'2'}) if (response.code === 200) { - this.materialList = response.data || [] + // 设置materialList并初始化pickQuantity为outQuantity的值 + this.materialList = (response.data || []).map(item => { + return { + ...item, + pickQuantity: item.outQuantity + } + }) } else { uni.showToast({ title: response.msg || this.$t('common.noData'), @@ -88,6 +94,37 @@ export default { handleClear() { this.materialList = [] }, + // 验证拣货数量不超过出库数量且不为负数 + validatePickQuantity(item) { + // 转换为数字 + let pickQty = Number(item.pickQuantity) + let outQty = Number(item.outQuantity) + + // 检查是否为有效数字 + if (isNaN(pickQty) || pickQty === '') { + item.pickQuantity = outQty + return + } + + // 检查是否为负数 + if (pickQty < 0) { + uni.showToast({ + title: this.$t('outbound.exception.pickQuantityNegative'), + icon: 'none' + }) + item.pickQuantity = 0 + return + } + + // 检查是否超过出库数量 + if (pickQty > outQty) { + uni.showToast({ + title: this.$t('outbound.exception.pickQuantityExceed'), + icon: 'none' + }) + item.pickQuantity = outQty + } + }, // 处理扫码事件 handleScan() { uni.scanCode({ @@ -106,10 +143,62 @@ export default { }) return } + + // 提交前再次验证所有物料的pickQuantity + let isValid = true + this.materialList.forEach(item => { + // 转换为数字 + let pickQty = Number(item.pickQuantity) + let outQty = Number(item.outQuantity) + + // 检查是否为有效数字 + if (isNaN(pickQty) || pickQty === '') { + isValid = false + uni.showToast({ + title: this.$t('outbound.exception.invalidPickQuantity'), + icon: 'none' + }) + item.pickQuantity = outQty + return + } + + // 检查是否为负数 + if (pickQty < 0) { + isValid = false + uni.showToast({ + title: this.$t('outbound.exception.pickQuantityNegative'), + icon: 'none' + }) + item.pickQuantity = 0 + return + } + + // 检查是否超过出库数量 + if (pickQty > outQty) { + isValid = false + uni.showToast({ + title: this.$t('outbound.exception.pickQuantityExceed'), + icon: 'none' + }) + item.pickQuantity = outQty + } + }) + + if (!isValid) return + + // 准备提交数据,包含所有物料编码和pickQuantity + const materialDetails = this.materialList.map(item => { + return { + jobDetailId: item.jobDetailId, + productId: item.productId, + pickQuantity: item.pickQuantity + } + }) + try { const response = await submitError({ - trayCode: this.trayCode - + trayCode: this.trayCode, + materialDetails: materialDetails }) if (response.code === 200) { uni.showToast({ diff --git a/RuoYi-App-master/permission.js b/RuoYi-App-master/permission.js index b9dc0ec..0ad5d0c 100644 --- a/RuoYi-App-master/permission.js +++ b/RuoYi-App-master/permission.js @@ -3,6 +3,9 @@ import { getToken } from '@/utils/auth' // 登录页面 const loginPage = "/pages/login" +// 首页 +const indexPage = "/pages/index" + // 标记是否由navigateBack触发的reLaunch let isNavigateBackTriggered = false @@ -10,6 +13,8 @@ let isNavigateBackTriggered = false function getCurrentPageUrl() { const pages = getCurrentPages() const currentPage = pages[pages.length - 1] + console.log("当前页面",currentPage.route) + console.log("上一层页面", pages[pages.length - 2].route) return currentPage ? currentPage.route : '' } @@ -26,6 +31,8 @@ function checkWhite(url) { return whiteList.indexOf(path) !== -1 } + + // 页面跳转验证拦截器 let list = ["navigateTo", "redirectTo", "reLaunch", "switchTab"] list.forEach(item => { @@ -77,6 +84,45 @@ uni.addInterceptor('navigateBack', { console.log('navigateBack 拦截器被触发', e) console.log('当前 Token 状态:', getToken() ? '存在' : '不存在') + // 获取当前页面栈 + const pages = getCurrentPages() + + // 检查页面导航栈是否为空 + if (pages.length <= 1) { + console.log('页面导航栈为空或只有一个页面,无法正常返回') + + // 检查Token状态 + if (getToken()) { + console.log('Token存在,跳转到首页') + // 设置标志,表明当前的reLaunch是由navigateBack触发的 + isNavigateBackTriggered = true + uni.reLaunch({ url: indexPage }) + // 重置标志 + setTimeout(() => { + isNavigateBackTriggered = false + }, 100) + } else { + console.log('Token不存在,跳转到登录页') + uni.showToast({ + icon: 'none', + title: '登录已过期,请重新登录' + }) + + // 设置标志,表明当前的reLaunch是由navigateBack触发的 + isNavigateBackTriggered = true + setTimeout(() => { + console.log('执行跳转到登录页') + uni.reLaunch({ url: loginPage }) + // 重置标志 + setTimeout(() => { + isNavigateBackTriggered = false + }, 100) + }, 1500) + } + return false + } + + // 页面导航栈不为空,检查Token状态 if (!getToken()) { const currentPage = getCurrentPageUrl() console.log('当前页面路径:', currentPage) @@ -87,26 +133,32 @@ uni.addInterceptor('navigateBack', { return true } - console.log('Token 不存在且页面不在白名单中,准备跳转到登录页') + console.log('Token不存在且页面不在白名单中,准备跳转到登录页') uni.showToast({ icon: 'none', title: '登录已过期,请重新登录' }) // 设置标志,表明当前的reLaunch是由navigateBack触发的 - isNavigateBackTriggered = true; + isNavigateBackTriggered = true setTimeout(() => { console.log('执行跳转到登录页') uni.reLaunch({ url: loginPage }) // 重置标志 setTimeout(() => { - isNavigateBackTriggered = false; - }, 100); + isNavigateBackTriggered = false + }, 100) }, 1500) return false } - console.log('Token 存在,允许正常返回') + // Token存在且页面导航栈不为空,允许正常返回 + const currentPage = pages[pages.length - 1] + console.log("当前页面:", currentPage.route) + if (pages.length > 1) { + console.log("上一层页面:", pages[pages.length - 2].route) + } + console.log('Token存在,允许正常返回') return true }, fail(err) { diff --git a/ruoyi-admin/src/main/java/com/ruoyi/pda/controller/PdaController.java b/ruoyi-admin/src/main/java/com/ruoyi/pda/controller/PdaController.java index 7aa91ff..fe320fd 100644 --- a/ruoyi-admin/src/main/java/com/ruoyi/pda/controller/PdaController.java +++ b/ruoyi-admin/src/main/java/com/ruoyi/pda/controller/PdaController.java @@ -330,7 +330,7 @@ public class PdaController extends BaseController { if("1".equals(basWarehouse.getWarehouseType())){ MydoJob mydoJob = new MydoJob(); mydoJob.setWarehouseId(basWarehouse.getWarehouseId()); - mydoJob.setCargoSpaceId(trayCodeMsg.getTrayCode()); + mydoJob.setTrayCode(trayCodeMsg.getTrayCode()); mydoJob.setInOut(trayCodeMsg.getInOut()); // if("1".equals(trayCodeMsg.getInOut())){ mydoJob.setStatus("1"); @@ -351,7 +351,7 @@ public class PdaController extends BaseController { mydoJob.setInOutIds(list); } mydoJob.setWarehouseId(basWarehouse.getWarehouseId()); - mydoJob.setCargoSpaceId(trayCodeMsg.getTrayCode()); + mydoJob.setTrayCode(trayCodeMsg.getTrayCode()); mydoJob.setStatus("3"); List mydoJobs2 = mydoJobService.selectMydoJobList(mydoJob); mydoJobArrayList.addAll(mydoJobs2); diff --git a/ruoyi-admin/src/main/java/com/ruoyi/pda/service/PdaServiceImp.java b/ruoyi-admin/src/main/java/com/ruoyi/pda/service/PdaServiceImp.java index a014242..9c9965a 100644 --- a/ruoyi-admin/src/main/java/com/ruoyi/pda/service/PdaServiceImp.java +++ b/ruoyi-admin/src/main/java/com/ruoyi/pda/service/PdaServiceImp.java @@ -56,6 +56,7 @@ import com.ruoyi.stock.stock.domain.BasStock; import com.ruoyi.stock.stock.service.IBasStockService; import com.ruoyi.system.service.ISysRoleService; import lombok.extern.slf4j.Slf4j; +import org.jetbrains.annotations.NotNull; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -668,11 +669,17 @@ public class PdaServiceImp implements PdaService { String startPoint = basContainer1.getPortName(); //todo 调用agv搬运接口 //使用HttpUtil post请求,参数为startPoint,endPoint,和containerCode + return agvRequest(basContainer.getContainerId(), startPoint, endPoint); + + + } + + private @NotNull AjaxResult agvRequest(String containerId, String startPoint, String endPoint) { String taskNo = IdUtil.fastSimpleUUID(); AgvMoveParam agvMoveParam =new AgvMoveParam(); agvMoveParam.setStartPoint(startPoint); agvMoveParam.setEndPoint(endPoint); - agvMoveParam.setContainerCode(basContainer1.getContainerId()); + agvMoveParam.setContainerCode(containerId); agvMoveParam.setTaskNo(taskNo); String result = HttpUtil.post("http://192.168.1.100:8080/agv/api/receiveAgvMoveJob", JSONUtil.toJsonStr( agvMoveParam)); //接口的返回结果为AjaxResult,从result中获取code @@ -680,7 +687,7 @@ public class PdaServiceImp implements PdaService { int code = JSONObject.parseObject(result).getIntValue("code"); if (code == 200) { AgvContainerTask agvContainerTask = new AgvContainerTask(); - agvContainerTask.setContainer(basContainer.getContainerId()); + agvContainerTask.setContainer(containerId); agvContainerTask.setStartPoint(startPoint); agvContainerTask.setEndPoint(endPoint); agvContainerTask.setStatus("0"); @@ -691,8 +698,6 @@ public class PdaServiceImp implements PdaService { } else { return AjaxResult.warn(JSONObject.parseObject(result).getString("msg")); } - - } @@ -867,17 +872,19 @@ public class PdaServiceImp implements PdaService { return AjaxResult.error(MessageUtils.message("error.message31")); } BasContainerDetails basContainer = basContainerDetails1.get(0); + return agvRequest(basContainer.getContainerId(), startPoint, endPoint); - String result = HttpUtil.post("http://192.168.1.100:8080/agv/api/receiveAgvMoveJob", "startPoint=" + startPoint + "&endPoint=" + endPoint + "&containerCode=" + basContainer.getContainerId()); - //接口的返回结果为AjaxResult,从result中获取code - - //获取code - int code = JSONObject.parseObject(result).getIntValue("code"); - if (code == 200) { - return AjaxResult.success(result); - } else { - return AjaxResult.warn(JSONObject.parseObject(result).getString("msg")); - } +// +// String result = HttpUtil.post("http://192.168.1.100:8080/agv/api/receiveAgvMoveJob", "startPoint=" + startPoint + "&endPoint=" + endPoint + "&containerCode=" + basContainer.getContainerId()); +// //接口的返回结果为AjaxResult,从result中获取code +// +// //获取code +// int code = JSONObject.parseObject(result).getIntValue("code"); +// if (code == 200) { +// return AjaxResult.success(result); +// } else { +// return AjaxResult.warn(JSONObject.parseObject(result).getString("msg")); +// } }