From a48ea6f110795b4f8aee85abc6d6b16864f9e9dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=B5=B5=E6=AD=A3=E6=98=93?= Date: Fri, 22 Aug 2025 18:28:25 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=96=B0=E5=A2=9E=E7=89=A9=E6=96=99?= =?UTF-8?q?=E5=9B=BE=E6=A0=87=E5=92=8C=E4=BC=98=E5=8C=96UI=E7=BB=84?= =?UTF-8?q?=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit fix(入库页面): 修复重复箱检测和批次检查逻辑 refactor(请求模块): 优化错误处理和防抖机制 style(全局字体): 更改默认字体为数黑体 perf(扫码组件): 添加防抖处理避免重复提交 feat(卡片组件): 增加删除功能并优化样式 docs(工具函数): 添加入库工具函数文档 chore: 更新依赖和配置文件 --- components/package-card/package-card.vue | 130 +- components/pda-scan-input/index.vue | 260 ++-- pages.json | 5 - pages/inWarehouse/inWarehouse.vue | 393 ++--- pages/inWarehouse/utils.js | 118 ++ .../MaterialProductionInput.vue | 17 +- .../materialManagement/materialManagement.vue | 195 ++- pages/outWarehouse/components/CustomList.vue | 32 + .../components/CustomListItem.vue | 36 + pages/outWarehouse/components/CustomPopup.vue | 126 ++ pages/outWarehouse/outWarehouse.vue | 1327 ++++++++++------- pages/relocation/relocation.vue | 55 +- pages/returnWarehouse/returnWarehouse.vue | 76 +- pages/scan/scan.vue | 3 +- .../warehoseActionList/warehoseActionList.vue | 1 + static/font/global-font.css | 12 +- static/images/material-icons/.gitkeep | 0 static/images/material-icons/coupon-fill.svg | 4 + .../images/material-icons/file-text-fill.svg | 4 + static/images/material-icons/file-text.svg | 4 + static/images/material-icons/gift.svg | 5 + .../material-icons/shopping-cart-fill.svg | 4 + static/images/material-icons/仓库配料.svg | 1 + static/images/material-icons/全点位移动.svg | 1 + static/images/material-icons/成品入库.svg | 1 + static/images/material-icons/车间叫料.svg | 1 + static/images/material-icons/车间进料.svg | 1 + static/images/material-icons/进箱.svg | 1 + utils/request.js | 85 +- 29 files changed, 1830 insertions(+), 1068 deletions(-) create mode 100644 pages/inWarehouse/utils.js create mode 100644 pages/outWarehouse/components/CustomList.vue create mode 100644 pages/outWarehouse/components/CustomListItem.vue create mode 100644 pages/outWarehouse/components/CustomPopup.vue create mode 100644 static/images/material-icons/.gitkeep create mode 100644 static/images/material-icons/coupon-fill.svg create mode 100644 static/images/material-icons/file-text-fill.svg create mode 100644 static/images/material-icons/file-text.svg create mode 100644 static/images/material-icons/gift.svg create mode 100644 static/images/material-icons/shopping-cart-fill.svg create mode 100644 static/images/material-icons/仓库配料.svg create mode 100644 static/images/material-icons/全点位移动.svg create mode 100644 static/images/material-icons/成品入库.svg create mode 100644 static/images/material-icons/车间叫料.svg create mode 100644 static/images/material-icons/车间进料.svg create mode 100644 static/images/material-icons/进箱.svg diff --git a/components/package-card/package-card.vue b/components/package-card/package-card.vue index b083825..3e833b6 100644 --- a/components/package-card/package-card.vue +++ b/components/package-card/package-card.vue @@ -2,6 +2,7 @@ 工单号:{{ packageInfo.workoderID }} + × @@ -11,8 +12,8 @@ 数量:{{ packageInfo.quantity }} - 生产日期 - {{ packageInfo.productionTime }} + 生产批次 + {{ packageInfo.productionTime }} @@ -24,7 +25,8 @@ export default { name: 'package-card', props: { packageInfo: { - default: { + type: Object, + default: () => ({ id:-1, // 工单号 workoderID:'', @@ -40,63 +42,85 @@ export default { quantity: 0, // 货物内部编号 originalCode:'' - } + }) } }, data() { return {}; + }, + methods: { + handleDelete() { + this.$emit('delete', this.packageInfo); + } } }; diff --git a/components/pda-scan-input/index.vue b/components/pda-scan-input/index.vue index af4ad9e..9b03657 100644 --- a/components/pda-scan-input/index.vue +++ b/components/pda-scan-input/index.vue @@ -29,7 +29,8 @@ isFocus: true, // search: 'A1-01', search: '', - time: null + time: null, + debounceTimer: null }; }, watch: { @@ -70,23 +71,27 @@ } }, // 获取扫码信息 - async getInfo(e) { - const text = e.target.value; - const type = this.type; - if (type === 1) { - await this.handleScanWareHouseCode(text); - } else if (type === 2) { - await this.handleScanGoodsCode(text); - } else if (type === 3) { - await this.handleScanDeliveryOrderCode(text); - } else if (type === 4) { - await this.handleScanStockReturnCode(text); + getInfo(e) { + // 防抖处理 + if (this.debounceTimer) { + clearTimeout(this.debounceTimer); } - setTimeout(() => { + this.debounceTimer = setTimeout(async () => { + const text = e.target.value; + const type = this.type; + if (type === 1) { + await this.handleScanWareHouseCode(text); + } else if (type === 2) { + await this.handleScanGoodsCode(text); + } else if (type === 3) { + await this.handleScanDeliveryOrderCode(text); + } else if (type === 4) { + await this.handleScanStockReturnCode(text); + } this.$nextTick(function() { this.search = ''; }); - }, 300); + }, 300); // 300ms防抖延迟 }, // type = 1 入库扫仓库编码 async handleScanWareHouseCode(text) { @@ -94,35 +99,48 @@ const locationCheckData = { production_location_code: text }; - const checkRes = await WarehoseApi.isProductionLocation(locationCheckData); - if (checkRes.code !== 200 || !checkRes.data) { + try { + const checkRes = await WarehoseApi.isProductionLocation(locationCheckData); + if (checkRes.code !== 200 || !checkRes.data) { + uni.showModal({ + title: '提示', + content: '仓库编号异常!', + showCancel: false, + confirmText: '确定' + }); + this.search = ''; + return; + } + const getProductLocationData = { + locationcode: locationCheckData.production_location_code, + warehouse_num: 1 + }; + const WarehoseRes = await WarehoseApi.getProductLocationInfo(getProductLocationData); + if (WarehoseRes.code !== 200 || !WarehoseRes.data) { + uni.showModal({ + title: '提示', + content: '获取仓库信息异常!', + showCancel: false, + confirmText: '确定' + }); + this.search = ''; + return; + } + // 待返回的结果数据 + let emitData = { + warehoseInfo: WarehoseRes.data + }; + this.emitInputChange(emitData, 1); + } catch (error) { uni.showModal({ title: '提示', - content: '仓库编号异常!', + content: '仓库扫码解析异常!', showCancel: false, confirmText: '确定' }); + this.search = ''; return; } - const getProductLocationData = { - locationcode: locationCheckData.production_location_code, - warehouse_num: 1 - }; - const WarehoseRes = await WarehoseApi.getProductLocationInfo(getProductLocationData); - if (WarehoseRes.code !== 200 || !WarehoseRes.data) { - uni.showModal({ - title: '提示', - content: '获取仓库信息异常!', - showCancel: false, - confirmText: '确定' - }); - return; - } - // 待返回的结果数据 - let emitData = { - warehoseInfo: WarehoseRes.data - }; - this.emitInputChange(emitData, 1); }, // type = 2 入库扫货物编码 async handleScanGoodsCode(text) { @@ -130,87 +148,83 @@ let resolutionData = { code: package_code }; - const emitRes = await WarehoseApi.resolutionPackage(resolutionData); - if (emitRes.code !== 200 || emitRes.data === null) { - uni.showModal({ - title: '提示', - content: '该箱号数据解析异常!', - showCancel: false, - confirmText: '确定' - }); + try { + const emitRes = await WarehoseApi.resolutionPackage(resolutionData); + if (emitRes.code !== 200 || emitRes.data === null) { + uni.showModal({ + title: '提示', + content: '该箱号数据解析异常!', + showCancel: false, + confirmText: '确定' + }); + this.search = ''; + return; + } + this.emitInputChange(emitRes.data, 2); + } catch (error) { return; } - this.emitInputChange(emitRes.data, 2); return; - // 临时库处理 - // let _warehouseInfo = this.warehouseInfo; - // if (_warehouseInfo != null && _warehouseInfo != undefined) { - // if (_warehouseInfo.remark === '临时' || _warehouseInfo.locaiton === 'LS1-01') { - // let resolutionData = { - // code: package_code - // }; - // const emitRes = await WarehoseApi.resolutionPackage(resolutionData); - // if (emitRes.code !== 200 || emitRes.data === null) { - // uni.showModal({ - // title: '提示', - // content: '该箱号数据解析异常!', - // showCancel: false, - // confirmText: '确定' - // }); - // return; - // } - // this.emitInputChange(emitRes.data, 2); - // return; - // } - // } - // 成品库处理 - // 成品满箱扫码 - let locationCheckData = { - package_code - }; - // 判断是否是箱号 - const checkRes = await WarehoseApi.isProductionPackage(locationCheckData); - console.log(checkRes); - if (checkRes.code !== 200) { + }, + // type = 3 扫出货单 + async handleScanDeliveryOrderCode(text) { + let id = text; + try { + const getWmOutOrderRes = await WarehoseApi.getWmOutOrder(id); + if (getWmOutOrderRes.code != 200) { uni.showModal({ title: '提示', - content: '成品箱号异常!', + content: '出库单号异常!', showCancel: false, confirmText: '确定' }); + this.search = ''; return; } - if (checkRes.data === 0) { + this.emitInputChange(getWmOutOrderRes.data, 3); + } catch (error) { + uni.showModal({ + title: '提示', + content: '出库单号解析异常!', + showCancel: false, + confirmText: '确定' + }); + this.search = ''; + return; + } + }, + // type = 4 退货扫货物编码 + async handleScanStockReturnCode(text) { + const checkData = { + originalCode: text + }; + // 判断是否仓库中有记录 + try { + const checkRes = await WarehoseApi.isExistedWarehouse(checkData); + if (!checkRes.data) { + uni.showModal({ + title: '提示', + content: '该编码不在仓库记录中:' + checkRes.msg, + showCancel: false, + confirmText: '确定' + }); + this.search = ''; + return; + } + } catch (error) { uni.showModal({ title: '提示', - content: checkRes.msg, + content: '仓库记录查询异常!', showCancel: false, confirmText: '确定' }); + this.search = ''; return; - } else if (checkRes.data === 2) { - uni.showModal({ - title: '提示', - content: checkRes.msg, - showCancel: false, - confirmText: '确定' - }); - return; - } else if (checkRes.data === 1) { - // 判断是否为满箱 - // const isFullRes = await WarehoseApi.isFullPackage(locationCheckData); - // if (isFullRes.code !== 200 || !isFullRes.data) { - // uni.showModal({ - // title: '提示', - // content: '该标签不为满箱标签!', - // showCancel: false, - // confirmText: '确定' - // }); - // return; - // } - let resolutionData = { - code: package_code - }; + } + const resolutionData = { + code: text + }; + try { const emitRes = await WarehoseApi.resolutionPackage(resolutionData); if (emitRes.code !== 200 || emitRes.data === null) { uni.showModal({ @@ -221,54 +235,16 @@ }); return; } - this.emitInputChange(emitRes.data, 2); - } - }, - // type = 3 扫出货单 - async handleScanDeliveryOrderCode(text) { - let id = text; - const getWmOutOrderRes = await WarehoseApi.getWmOutOrder(id); - if (getWmOutOrderRes.code != 200) { + this.emitInputChange(emitRes.data, 4); + } catch (error) { uni.showModal({ title: '提示', - content: '出库单号异常!', + content: '外箱标签解析异常!', showCancel: false, confirmText: '确定' }); return; } - this.emitInputChange(getWmOutOrderRes.data, 3); - }, - // type = 4 退货扫货物编码 - async handleScanStockReturnCode(text) { - const checkData = { - originalCode: text - }; - // 判断是否仓库中有记录 - const checkRes = await WarehoseApi.isExistedWarehouse(checkData); - if (!checkRes.data) { - uni.showModal({ - title: '提示', - content: '该编码不在仓库记录中:' + checkRes.msg, - showCancel: false, - confirmText: '确定' - }); - return; - } - const resolutionData = { - code: text - }; - const emitRes = await WarehoseApi.resolutionPackage(resolutionData); - if (emitRes.code !== 200 || emitRes.data === null) { - uni.showModal({ - title: '提示', - content: '该箱号数据解析异常!', - showCancel: false, - confirmText: '确定' - }); - return; - } - this.emitInputChange(emitRes.data, 4); } } }; diff --git a/pages.json b/pages.json index 3b73bbd..d381e93 100644 --- a/pages.json +++ b/pages.json @@ -40,14 +40,12 @@ "path": "pages/index/index", "style": { "navigationBarTitleText": "DOAN" - // "navigationStyle": "custom" } }, { "path": "pages/inWarehouse/inWarehouse", "style": { "navigationBarTitleText": "入库", - // "navigationStyle": "custom", "enablePullDownRefresh": false } }, @@ -55,7 +53,6 @@ "path": "pages/outWarehouse/outWarehouse", "style": { "navigationBarTitleText": "出库", - // "navigationStyle": "custom", "enablePullDownRefresh": false } }, @@ -63,7 +60,6 @@ "path": "pages/stocktake/stocktake", "style": { "navigationBarTitleText": "盘点", - // "navigationStyle": "custom", "enablePullDownRefresh": false } }, @@ -71,7 +67,6 @@ "path": "pages/relocation/relocation", "style": { "navigationBarTitleText": "移库", - // "navigationStyle": "custom", "enablePullDownRefresh": false } }, diff --git a/pages/inWarehouse/inWarehouse.vue b/pages/inWarehouse/inWarehouse.vue index a477caa..4eea65a 100644 --- a/pages/inWarehouse/inWarehouse.vue +++ b/pages/inWarehouse/inWarehouse.vue @@ -20,22 +20,33 @@ 请扫箱码 - + + + + + 上次批次号:{{ + newMaterialList[newMaterialList.length - 2].patchCode }} + 上次批次号: + {{ this.isStrict ? '' : '无校验' }}入库清单 - 上次批次号:{{ newMaterialList[newMaterialList.length - 2].patchCode }} - 上次批次号: - + + + + - 全部重置 - 入库 + 全部重置 + 入库 @@ -44,6 +55,7 @@ import materialItem from '@/components/material-item/material-item.vue'; import packageCard from '@/components/package-card/package-card.vue'; import * as WarehoseApi from '@/api/warehouse/warehose.js'; +import { showOperationConfirm, isRepeatPackage, isChangeBatch, clearRepeatPackages, debounce } from './utils.js'; // 入库 export default { components: { @@ -55,8 +67,6 @@ export default { // 入库模式(true严格追溯 false不严格不追溯) isStrict: false, loading: false, - // 双击判定 - touchNum: 0, clearData: {}, // 仓库信息 warehouseInfo: { @@ -121,10 +131,21 @@ export default { this.searchType = 1; }, clear() { - this.warehouseInfo = JSON.parse(JSON.stringify(this.clearData.warehouseInfo)); - this.oldMaterialList = JSON.parse(JSON.stringify(this.clearData.oldMaterialList)); - this.newMaterialList = JSON.parse(JSON.stringify(this.clearData.newMaterialList)); - this.searchType = 1; + uni.showModal({ + title: '确认重置', + content: '确定要重置所有数据吗?', + showCancel: true, + cancelText: '取消', + confirmText: '确认', + success: (res) => { + if (res.confirm) { + this.warehouseInfo = JSON.parse(JSON.stringify(this.clearData.warehouseInfo)); + this.oldMaterialList = JSON.parse(JSON.stringify(this.clearData.oldMaterialList)); + this.newMaterialList = JSON.parse(JSON.stringify(this.clearData.newMaterialList)); + this.searchType = 1; + } + } + }); }, handleGetInfo(data, type) { if (type === 1) { @@ -134,37 +155,24 @@ export default { this.newMaterialList = []; this.loading = false; } else if (type === 2) { - if (this.loading) { - uni.showModal({ - title: '提示', - content: '请等待加载完成!', - showCancel: false, - confirmText: '确定' - }); + if (this.loading) { + showOperationConfirm('提示', '请等待加载完成!', false); + return; } // 此时扫描的是箱号 // 当前录入的箱号是否在同一批次录入过 // 曾经是否扫过 if (this.newMaterialList.length > 0) { - for (let item of this.newMaterialList) { - if (item.patchCode === data.patchCode) { - uni.showModal({ - title: '提示', - content: '此货物已录入过!', - showCancel: false, - confirmText: '确定' - }); - this.loading = false; - return; - } + // 检查是否为重复箱 + if (isRepeatPackage(this.newMaterialList, data.patchCode)) { + showOperationConfirm('提示', '此货物已录入过!', false); + this.loading = false; + return; } - if (this.newMaterialList[this.newMaterialList.length - 1].workoderID !== data.workoderID) { - uni.showModal({ - title: '提示', - content: '已更换入库批次!', - showCancel: false, - confirmText: '确定' - }); + + // 检查是否更换了批次 + if (isChangeBatch(this.newMaterialList, data.workoderID)) { + showOperationConfirm('提示', '已更换入库批次!', false); } } const checkData = { @@ -174,139 +182,143 @@ export default { isStrict: this.isStrict }; this.loading = true; - setTimeout(() => { - this.loading = false; - }, 10000); - WarehoseApi.checkWarehousing(checkData).then((res) => { - if (res.code === 200 && res.data) { - this.newMaterialList.push(data); - this.loading = false; - } else { - uni.showModal({ - title: '提示', - content: '不可入库:' + res.msg, - showCancel: false, - confirmText: '确定' - }); - this.loading = false; - } + // 使用Promise包装API调用,避免setTimeout可能带来的问题 + const checkWarehousingPromise = WarehoseApi.checkWarehousing(checkData); + const timeoutPromise = new Promise((resolve, reject) => { + setTimeout(() => reject(new Error('timeout')), 10000); }); + Promise.race([checkWarehousingPromise, timeoutPromise]) + .then((res) => { + if (res.code === 200 && res.data) { + this.newMaterialList.push(data); + } else { + uni.showModal({ + title: '提示', + content: '不可入库:' + res.msg, + showCancel: false, + confirmText: '确定' + }); + } + }) + .catch((error) => { + if (error.message === 'timeout') { + uni.showModal({ + title: '提示', + content: '请求超时,请重试!', + showCancel: false, + confirmText: '确定' + }); + } else { + uni.showModal({ + title: '提示', + content: '请求异常,请重试!', + showCancel: false, + confirmText: '确定' + }); + } + }) + .finally(() => { + this.loading = false; + }); } }, - // 长按弹出删除 - handleDeleteItem(item, index) { - // 双击判定 - this.touchNum++; - setTimeout(() => { - if (this.touchNum >= 2) { - uni.showModal({ - title: '删除提示', - content: '是否从列表中删除此货物?', - showCancel: true, - cancelText: '取消', - confirmText: '删除', - success: (res) => { - if (res.confirm) { - this.newMaterialList.splice(index, 1); - } - } - }); - } - this.touchNum = 0; - }, 250); - }, - // 入库提交 - handlerSubmit() { - if (this.newMaterialList.length === 0) { - uni.showModal({ - title: '提示', - content: '无入库货物!', - showCancel: false, - confirmText: '确定' - }); - return; - } - // 箱重复提醒 this.isPackageRepeat() - if (this.isPackageRepeat()) { - uni.showModal({ - title: '重复箱校验', - content: '检测到存在重复箱,是否自动清除?', - showCancel: true, - cancelText: '取消', - confirmText: '确认清除', - success: (res) => { - if (res.confirm) { - this.clearRepeatPackage(); - } - } - }); - return; - } - this.loading = true; - setTimeout(() => { - this.loading = false; - }, 30000); - uni.showModal({ - title: '入库操作', - content: '是否确认入库?', - showCancel: true, - cancelText: '取消', - confirmText: '确认入库', - success: (res) => { - if (res.confirm) { - let list = []; - for (let item of this.newMaterialList) { - list.push(item.originalCode); - } - const data = { - location: this.warehouseInfo.location, - packagelist: list - }; - uni.$u.throttle(() => { - WarehoseApi.handlerIntoProductWarehouse(data).then((res) => { - if (res.code === 200) { - if (res.data === 0 || !res.data) { - uni.showModal({ - title: '提示', - content: '入库失败:' + res.msg, - showCancel: false, - confirmText: '确定' - }); - this.loading = false; - return; - } - uni.showToast({ - icon: 'none', - title: '入库成功!' + res.msg - }); - this.loading = false; - this.oldMaterialList = JSON.parse(JSON.stringify(this.clearData.oldMaterialList)); - this.newMaterialList = JSON.parse(JSON.stringify(this.clearData.newMaterialList)); - // this.clear(); - } else { - uni.showToast({ - icon: 'error', - title: '入库失败!' - }); - this.loading = false; - } - }); - }, 5000); - } else { - this.loading = false; + // 删除货物项 + handleDeleteItem(item) { + showOperationConfirm('删除提示', '是否从列表中删除此货物?', true).then((res) => { + if (res.confirm) { + const index = this.newMaterialList.findIndex(i => i.originalCode === item.originalCode); + if (index > -1) { + this.newMaterialList.splice(index, 1); } } }); }, + // 入库提交 + handlerSubmit() { + if (this.newMaterialList.length === 0) { + showOperationConfirm('提示', '无入库货物!', false); + return; + } + // 箱重复提醒 this.isPackageRepeat() + if (this.isPackageRepeat()) { + showOperationConfirm('重复箱校验', '检测到存在重复箱,是否自动清除?', true).then((res) => { + if (res.confirm) { + this.clearRepeatPackage(); + } + }); + return; + } + + showOperationConfirm('入库操作', '是否确认入库?', true).then((res) => { + if (res.confirm) { + this.loading = true; + let list = []; + for (let item of this.newMaterialList) { + list.push(item.originalCode); + } + const data = { + location: this.warehouseInfo.location, + packagelist: list + }; + // 优化防抖处理机制,使用更可靠的防抖函数 + const debouncedSubmit = (() => { + let timeoutId; + return () => { + // 清除之前的定时器 + if (timeoutId) { + clearTimeout(timeoutId); + } + + // 设置新的定时器执行入库操作 + timeoutId = setTimeout(() => { + WarehoseApi.handlerIntoProductWarehouse(data).then((res) => { + if (res.code === 200) { + if (res.data === 0 || !res.data) { + showOperationConfirm('提示', '入库失败:' + res.msg, false); + this.loading = false; + return; + } + uni.showToast({ + icon: 'none', + title: '入库成功!' + res.msg + }); + this.loading = false; + this.oldMaterialList = JSON.parse(JSON.stringify(this.clearData.oldMaterialList)); + this.newMaterialList = JSON.parse(JSON.stringify(this.clearData.newMaterialList)); + } else { + showOperationConfirm('提示', '入库失败!', false); + this.loading = false; + } + }).catch((error) => { + // 处理请求失败的情况,确保loading状态被重置 + console.error('入库请求失败:', error); + showOperationConfirm('提示', '请求失败,请重试!', false); + this.loading = false; + }); + }, 1000); // 1秒防抖延迟 + }; + })(); + + // 调用防抖函数 + debouncedSubmit(); + } else { + this.loading = false; + } + }); + }, // 入库箱去重校验,数据是否有重复 + // 统一重复检查逻辑,使用Map提高查找效率 isPackageRepeat() { let oldList = this.newMaterialList; - let newlist = []; + let seen = new Map(); for (let item of oldList) { - newlist.push(item.originalCode); + if (seen.has(item.originalCode)) { + return true; + } + seen.set(item.originalCode, true); } - return new Set(newlist).size !== oldList.length; + return false; }, // 自动清除重复箱 clearRepeatPackage() { @@ -315,31 +327,32 @@ export default { let seen = new Map(); let repeatPackage = []; oldArray.forEach((item) => { - let itemStr = JSON.stringify(item); - if (!seen.has(itemStr)) { - seen.set(itemStr, true); + // 统一重复检查逻辑,使用originalCode作为唯一标识 + if (!seen.has(item.originalCode)) { + seen.set(item.originalCode, true); newArray.push(item); } else { repeatPackage.push(item.patchCode); } }); this.newMaterialList = newArray; - uni.showModal({ - title: '提示', - content: '清除成功,原箱数' + oldArray.length + '现箱数:' + newArray.length + '重复箱:' + repeatPackage.join(','), - showCancel: false, - confirmText: '确定' - }); + // 增强用户交互提示信息 + showOperationConfirm('重复箱清除', `检测到${repeatPackage.length}个重复箱,已自动清除。原箱数:${oldArray.length} 现箱数:${newArray.length} 重复箱:${repeatPackage.join(', ')}`, false); } } }; diff --git a/pages/inWarehouse/utils.js b/pages/inWarehouse/utils.js new file mode 100644 index 0000000..fe59f5f --- /dev/null +++ b/pages/inWarehouse/utils.js @@ -0,0 +1,118 @@ +/** + * 入库通用工具方法 + */ + +/** + * 显示操作确认模态框 + * @param {string} title - 标题 + * @param {string} content - 内容 + * @param {boolean} showCancel - 是否显示取消按钮 + * @returns {Promise} Promise对象 + */ +export function showOperationConfirm(title, content, showCancel = true) { + return new Promise((resolve) => { + uni.showModal({ + title: title || '提示', + content: content || '', + showCancel: showCancel, + cancelText: '取消', + confirmText: '确定', + success: function(res) { + resolve(res); + } + }); + }); +} + +/** + * 检查是否为重复箱 + * @param {Array} list - 箱子列表 + * @param {string} patchCode - 批次号 + * @returns {boolean} 是否重复 + */ +export function isRepeatPackage(list, patchCode) { + if (!list || list.length === 0) return false; + + for (let item of list) { + if (item.patchCode === patchCode) { + return true; + } + } + return false; +} + +/** + * 检查是否更换了批次 + * @param {Array} list - 箱子列表 + * @param {string} workoderID - 工单号 + * @returns {boolean} 是否更换批次 + */ +export function isChangeBatch(list, workoderID) { + if (!list || list.length === 0) return false; + + const lastItem = list[list.length - 1]; + return lastItem.workoderID !== workoderID; +} + +/** + * 检查是否为重复箱(基于originalCode) + * @param {Array} list - 箱子列表 + * @param {string} originalCode - 原始编码 + * @returns {boolean} 是否重复 + */ +export function isRepeatPackageByCode(list, originalCode) { + if (!list || list.length === 0) return false; + + for (let item of list) { + if (item.originalCode === originalCode) { + return true; + } + } + return false; +} + +/** + * 清除重复箱 + * @param {Array} list - 箱子列表 + * @returns {Array} 清除重复后的列表和重复箱信息 + */ +export function clearRepeatPackages(list) { + let newArray = []; + let seen = new Map(); + let repeatPackage = []; + + list.forEach((item) => { + if (!seen.has(item.originalCode)) { + seen.set(item.originalCode, true); + newArray.push(item); + } else { + repeatPackage.push(item.patchCode); + } + }); + + return { + clearedList: newArray, + repeatPackages: repeatPackage + }; +} + +/** + * 防抖函数 + * @param {Function} func - 要防抖的函数 + * @param {number} delay - 延迟时间(ms) + * @returns {Function} 防抖后的函数 + */ +export function debounce(func, delay) { + let timeoutId; + return function (...args) { + // 清除之前的定时器 + if (timeoutId) { + clearTimeout(timeoutId); + } + + // 设置新的定时器 + timeoutId = setTimeout(() => { + func.apply(this, args); + }, delay); + }; +} \ No newline at end of file diff --git a/pages/materialManagement/MaterialProductionInput/MaterialProductionInput.vue b/pages/materialManagement/MaterialProductionInput/MaterialProductionInput.vue index 3899471..b3f2e14 100644 --- a/pages/materialManagement/MaterialProductionInput/MaterialProductionInput.vue +++ b/pages/materialManagement/MaterialProductionInput/MaterialProductionInput.vue @@ -4,13 +4,11 @@ - + @@ -18,11 +16,10 @@ - - + + - + - + @@ -191,7 +188,7 @@ export default { // 计算上海时区的时间 let shanghaiTime = new Date(date.getTime() + offset * 60 * 1000); - console.log("shanghaiTime",shanghaiTime); + console.log('shanghaiTime', shanghaiTime); const query = { datetimespan: shanghaiTime, pageNum: this.page.pageNum, diff --git a/pages/materialManagement/materialManagement.vue b/pages/materialManagement/materialManagement.vue index 6ac48fe..32d4507 100644 --- a/pages/materialManagement/materialManagement.vue +++ b/pages/materialManagement/materialManagement.vue @@ -1,35 +1,33 @@ \ No newline at end of file diff --git a/pages/outWarehouse/components/CustomList.vue b/pages/outWarehouse/components/CustomList.vue new file mode 100644 index 0000000..3ccc1d6 --- /dev/null +++ b/pages/outWarehouse/components/CustomList.vue @@ -0,0 +1,32 @@ + + + + + \ No newline at end of file diff --git a/pages/outWarehouse/components/CustomListItem.vue b/pages/outWarehouse/components/CustomListItem.vue new file mode 100644 index 0000000..fd261b4 --- /dev/null +++ b/pages/outWarehouse/components/CustomListItem.vue @@ -0,0 +1,36 @@ + + + + + \ No newline at end of file diff --git a/pages/outWarehouse/components/CustomPopup.vue b/pages/outWarehouse/components/CustomPopup.vue new file mode 100644 index 0000000..9559600 --- /dev/null +++ b/pages/outWarehouse/components/CustomPopup.vue @@ -0,0 +1,126 @@ + + + + + \ No newline at end of file diff --git a/pages/outWarehouse/outWarehouse.vue b/pages/outWarehouse/outWarehouse.vue index 66e5f6a..339e624 100644 --- a/pages/outWarehouse/outWarehouse.vue +++ b/pages/outWarehouse/outWarehouse.vue @@ -15,8 +15,8 @@ - + - + - + - - - - - - + + + {{ item }} + + - + 出库计划查看 - + - - - - - - - - - - - - - - - + + + 出库计划未生成,请先生成出库计划 + + + + + + {{ item.outOrder }} 计划批次号: {{ item.packageCode + }} + + + 异常 + 已完成 + 未完成 + - - - - - - - - + + 物料号: {{ item.partnumber }} + 仓库编号: {{ item.warehouseCode }} + 描述: {{ item.description }} + 计划需求零件数: {{ item.requireNum }} + 库存现有箱数: {{ item.packageNum }} 库存现有零件数: {{ item.partnumberNum + }} + 计划出库箱数: {{ item.packagePlanNum }} 计划出库零件数: {{ + item.partnumberPlanNum + }} + 该批次已出箱数: {{ item.outPackageNum }} 该批次已出零件数: {{ + item.outPartnumberNum + }} - - - + + + - + @@ -137,537 +137,774 @@ \ No newline at end of file diff --git a/pages/relocation/relocation.vue b/pages/relocation/relocation.vue index efca215..91b3b78 100644 --- a/pages/relocation/relocation.vue +++ b/pages/relocation/relocation.vue @@ -184,6 +184,7 @@ export default { }, // 移库提交 handlerSubmit() { + this.loading = true; if (this.newMaterialList.length === 0) { uni.showModal({ title: '提示', @@ -191,6 +192,7 @@ export default { showCancel: false, confirmText: '确定' }); + this.loading = false; return; } uni.showModal({ @@ -201,24 +203,47 @@ export default { confirmText: '确认移库', success: (res) => { if (res.confirm) { - let data = { - id: this.packageInfo.id, - locationCode: this.warehouseInfo.location - }; - GoodsNowApi.updateWmGoodsNowProduction(data).then((res) => { - if (res.code === 200) { - uni.showToast({ - icon: 'success', - title: '移库成功!' - }); - this.clear(); - } else { + // 使用防抖函数避免重复提交,并确保5秒后loading状态重置 + const debouncedSubmit = uni.$u.debounce(() => { + let data = { + id: this.packageInfo.id, + locationCode: this.warehouseInfo.location + }; + GoodsNowApi.updateWmGoodsNowProduction(data).then((res) => { + if (res.code === 200) { + uni.showToast({ + icon: 'success', + title: '移库成功!' + }); + this.clear(); + this.loading = false; + } else { + uni.showToast({ + icon: 'error', + title: '移库失败!' + }); + this.loading = false; + } + }).catch((error) => { + // 处理请求失败的情况,确保loading状态被重置 + console.error('移库请求失败:', error); uni.showToast({ icon: 'error', - title: '移库失败!' + title: '请求失败,请重试!' }); - } - }); + this.loading = false; + }); + }, 1000); + + // 调用防抖函数 + debouncedSubmit(); + + // 确保5秒后loading状态重置 + setTimeout(() => { + this.loading = false; + }, 5000); + } else { + this.loading = false; } } }); diff --git a/pages/returnWarehouse/returnWarehouse.vue b/pages/returnWarehouse/returnWarehouse.vue index 1aaac99..e6d6457 100644 --- a/pages/returnWarehouse/returnWarehouse.vue +++ b/pages/returnWarehouse/returnWarehouse.vue @@ -133,6 +133,7 @@ }, // 退库提交 handlerSubmit() { + this.loading = true; if (this.newMaterialList.length === 0) { uni.showModal({ title: '提示', @@ -140,6 +141,7 @@ showCancel: false, confirmText: '确定' }); + this.loading = false; return; } uni.showModal({ @@ -150,36 +152,60 @@ confirmText: '确认退库', success: (res) => { if (res.confirm) { - let list = []; - for (let item of this.newMaterialList) { - list.push(item.originalCode); - } - const data = { - originalCode: list[0] - }; - WarehoseApi.handlErexitwarehouse(data).then((res) => { - if (res.code === 200) { - if (!res.data) { - uni.showModal({ - title: '提示', - content: '退库异常:' + res.msg, - showCancel: false, - confirmText: '确定' + // 使用防抖函数避免重复提交,并确保5秒后loading状态重置 + const debouncedSubmit = uni.$u.debounce(() => { + let list = []; + for (let item of this.newMaterialList) { + list.push(item.originalCode); + } + const data = { + originalCode: list[0] + }; + WarehoseApi.handlErexitwarehouse(data).then((res) => { + if (res.code === 200) { + if (!res.data) { + uni.showModal({ + title: '提示', + content: '退库异常:' + res.msg, + showCancel: false, + confirmText: '确定' + }); + this.loading = false; + return; + } + uni.showToast({ + icon: 'success', + title: '退库成功!' }); - return; + this.clear(); + this.loading = false; + } else { + uni.showToast({ + icon: 'error', + title: '退库失败!' + }); + this.loading = false; } - uni.showToast({ - icon: 'success', - title: '退库成功!' - }); - this.clear(); - } else { + }).catch((error) => { + // 处理请求失败的情况,确保loading状态被重置 + console.error('退库请求失败:', error); uni.showToast({ icon: 'error', - title: '退库失败!' + title: '请求失败,请重试!' }); - } - }); + this.loading = false; + }); + }, 1000); + + // 调用防抖函数 + debouncedSubmit(); + + // 确保5秒后loading状态重置 + setTimeout(() => { + this.loading = false; + }, 5000); + } else { + this.loading = false; } } }); diff --git a/pages/scan/scan.vue b/pages/scan/scan.vue index 458bffc..0fa671f 100644 --- a/pages/scan/scan.vue +++ b/pages/scan/scan.vue @@ -2,7 +2,7 @@ - @@ -70,6 +70,7 @@ showCancel: false, confirmText: '确定' }); + this.formData.query = ""; return; } setTimeout(() => { diff --git a/pages/warehoseActionList/warehoseActionList.vue b/pages/warehoseActionList/warehoseActionList.vue index 62b07c2..6142aa5 100644 --- a/pages/warehoseActionList/warehoseActionList.vue +++ b/pages/warehoseActionList/warehoseActionList.vue @@ -234,6 +234,7 @@ showCancel: false, confirmText: '确定' }); + this.queryForm.description = ""; return; } setTimeout(() => { diff --git a/static/font/global-font.css b/static/font/global-font.css index d6fa3f3..8ebe78e 100644 --- a/static/font/global-font.css +++ b/static/font/global-font.css @@ -1,18 +1,18 @@ @font-face { - font-family: '东方大楷'; - src: url('@/static/font/东方大楷/AlimamaDongFangDaKai-Regular.ttf') format('truetype'), - url('@/static/font/东方大楷/AlimamaDongFangDaKai-Regular.woff') format('woff'), - url('@/static/font/东方大楷/AlimamaDongFangDaKai-Regular.woff2') format('woff2'); + font-family: '数黑体'; + src: url('@/static/font/数黑体/AlimamaShuHeiTi-Bold.ttf') format('truetype'), + url('@/static/font/数黑体/AlimamaShuHeiTi-Bold.woff') format('woff'), + url('@/static/font/数黑体/AlimamaShuHeiTi-Bold.woff2') format('woff2'); font-weight: normal; font-style: normal; } /* 设置全局默认字体 */ body, page { - font-family: '东方大楷', -apple-system, BlinkMacSystemFont, 'Segoe UI', 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', 'Helvetica Neue', Helvetica, Arial, sans-serif; + font-family: '数黑体', -apple-system, BlinkMacSystemFont, 'Segoe UI', 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', 'Helvetica Neue', Helvetica, Arial, sans-serif; } /* 为所有元素设置默认字体 */ * { - font-family: '东方大楷', -apple-system, BlinkMacSystemFont, 'Segoe UI', 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', 'Helvetica Neue', Helvetica, Arial, sans-serif; + font-family: '数黑体', -apple-system, BlinkMacSystemFont, 'Segoe UI', 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', 'Helvetica Neue', Helvetica, Arial, sans-serif; } \ No newline at end of file diff --git a/static/images/material-icons/.gitkeep b/static/images/material-icons/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/static/images/material-icons/coupon-fill.svg b/static/images/material-icons/coupon-fill.svg new file mode 100644 index 0000000..955994d --- /dev/null +++ b/static/images/material-icons/coupon-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/static/images/material-icons/file-text-fill.svg b/static/images/material-icons/file-text-fill.svg new file mode 100644 index 0000000..a31e493 --- /dev/null +++ b/static/images/material-icons/file-text-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/static/images/material-icons/file-text.svg b/static/images/material-icons/file-text.svg new file mode 100644 index 0000000..a31e493 --- /dev/null +++ b/static/images/material-icons/file-text.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/static/images/material-icons/gift.svg b/static/images/material-icons/gift.svg new file mode 100644 index 0000000..2c23148 --- /dev/null +++ b/static/images/material-icons/gift.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/static/images/material-icons/shopping-cart-fill.svg b/static/images/material-icons/shopping-cart-fill.svg new file mode 100644 index 0000000..ee80341 --- /dev/null +++ b/static/images/material-icons/shopping-cart-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/static/images/material-icons/仓库配料.svg b/static/images/material-icons/仓库配料.svg new file mode 100644 index 0000000..01b24d9 --- /dev/null +++ b/static/images/material-icons/仓库配料.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/static/images/material-icons/全点位移动.svg b/static/images/material-icons/全点位移动.svg new file mode 100644 index 0000000..91d6008 --- /dev/null +++ b/static/images/material-icons/全点位移动.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/static/images/material-icons/成品入库.svg b/static/images/material-icons/成品入库.svg new file mode 100644 index 0000000..7efdf1f --- /dev/null +++ b/static/images/material-icons/成品入库.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/static/images/material-icons/车间叫料.svg b/static/images/material-icons/车间叫料.svg new file mode 100644 index 0000000..d0ab78b --- /dev/null +++ b/static/images/material-icons/车间叫料.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/static/images/material-icons/车间进料.svg b/static/images/material-icons/车间进料.svg new file mode 100644 index 0000000..77ab11a --- /dev/null +++ b/static/images/material-icons/车间进料.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/static/images/material-icons/进箱.svg b/static/images/material-icons/进箱.svg new file mode 100644 index 0000000..896374a --- /dev/null +++ b/static/images/material-icons/进箱.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/utils/request.js b/utils/request.js index dd67b2a..36a49af 100644 --- a/utils/request.js +++ b/utils/request.js @@ -26,9 +26,9 @@ const request = config => { config.header = config.header || {} // 假设你使用的是PHP作为你的后端语言 - config.header['Access-Control-Allow-Origin']= '*'; // 允许任何源访问 - config.header['Access-Control-Allow-Methods']='GET, POST, OPTIONS'; // 允许的HTTP方法 - config.header['Access-Control-Allow-Headers']= 'X-Requested-With'; // 允许的HTTP头 + config.header['Access-Control-Allow-Origin'] = '*'; // 允许任何源访问 + config.header['Access-Control-Allow-Methods'] = 'GET, POST, OPTIONS'; // 允许的HTTP方法 + config.header['Access-Control-Allow-Headers'] = 'X-Requested-With'; // 允许的HTTP头 if (getToken() && !isToken) { config.header['Authorization'] = 'Bearer ' + getToken() config.header['userName'] = encodeURIComponent(store.getters.nickName ?? "未知用户") @@ -42,46 +42,49 @@ const request = config => { return new Promise((resolve, reject) => { uni.request({ - method: config.method || 'get', - timeout: config.timeout || timeout, - url: config.baseUrl || (storageBaseUrl + config.url), - data: config.data, - header: config.header, - dataType: 'json' - }).then(response => { - let [error, res] = response - //console.log('token:','Bearer ' + getToAccess-Control-Allow-Originken()); - //console.log('request:',storageBaseUrl + config.url,response); - if (error) { - showConfirm(error) - // toast('后端接口连接异常') - reject('后端接口连接异常') - return + method: config.method || 'get', + timeout: config.timeout || timeout, + url: config.baseUrl || (storageBaseUrl + config.url), + data: config.data, + header: config.header, + dataType: 'json' + }).then(response => { + let [error, res] = response + //console.log('token:','Bearer ' + getToAccess-Control-Allow-Originken()); + //console.log('request:',storageBaseUrl + config.url,response); + if (error) { + if (error.errMsg.includes('Failed to connect')) { + toast('后台地址连接失败,请检查:' + (config.baseUrl || (storageBaseUrl + config.url))) + } else { + toast('后端接口连接异常') } - const code = res.data.code || 200 - const msg = errorCode[code] || res.data.msg || errorCode['default'] - if (code === 401) { - showConfirm('登录状态已过期,您可以继续留在该页面,或者重新登录?').then(res => { - if (res.confirm) { - store.dispatch('LogOut').then(res => { - uni.reLaunch({ - url: '/pages/login' - }) + reject('后端接口连接异常') + return + } + const code = res.data.code || 200 + const msg = errorCode[code] || res.data.msg || errorCode['default'] + if (code === 401) { + showConfirm('登录状态已过期,您可以继续留在该页面,或者重新登录?').then(res => { + if (res.confirm) { + store.dispatch('LogOut').then(res => { + uni.reLaunch({ + url: '/pages/login' }) - } - }) - reject('无效的会话,或者会话已过期,请重新登录。') - } else if (code === 500) { - // toast(msg) - showConfirm(msg) - reject('500') - } else if (code !== 200) { - // toast(msg) - showConfirm(msg) - reject(code) - } - resolve(res.data) - }) + }) + } + }) + reject('无效的会话,或者会话已过期,请重新登录。') + } else if (code === 500) { + // toast(msg) + showConfirm(msg) + reject('500') + } else if (code !== 200) { + // toast(msg) + showConfirm(msg) + reject(code) + } + resolve(res.data) + }) .catch(error => { let { message