From 1c7f790142f80a5ce66383177aee071ebe2ae04b Mon Sep 17 00:00:00 2001 From: hayu <1604366271@qq.com> Date: Tue, 6 Jan 2026 15:05:02 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=89=E5=85=A8=E5=B7=A5=E5=99=A8=E5=85=B7?= =?UTF-8?q?=E5=8F=B0=E8=B4=A6=E5=8F=8A=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- js/aq_demand_plan/child/send_out_detail.js | 12 +- js/aq_demand_plan/child/send_out_edit_form.js | 65 +- js/aq_demand_plan/child/send_out_form.js | 70 +- .../child/send_out_pro_detail.js | 3 + .../child/send_out_supplement.js | 693 ++++++++++++++++++ js/aq_inventory/safety_tools_ledger.js | 228 ++++-- .../child/send_out_edit_form.html | 8 +- page/aq_demand_plan/child/send_out_form.html | 4 +- .../child/send_out_supplemen.html | 189 +++++ .../child/send_out_unplanned_form.html | 2 +- page/aq_inventory/safety_tools_ledger.html | 10 +- 11 files changed, 1189 insertions(+), 95 deletions(-) create mode 100644 js/aq_demand_plan/child/send_out_supplement.js create mode 100644 page/aq_demand_plan/child/send_out_supplemen.html diff --git a/js/aq_demand_plan/child/send_out_detail.js b/js/aq_demand_plan/child/send_out_detail.js index 3029612..77ae94e 100644 --- a/js/aq_demand_plan/child/send_out_detail.js +++ b/js/aq_demand_plan/child/send_out_detail.js @@ -40,7 +40,7 @@ function getPurchaseDetails() { function setTableData(obj) { $('#planCode').html(obj.planCode); $('#cgNum').html(obj.cgNum); - $('#money').html('¥ ' + obj.money); + $('#money').html(formatMoney(obj.money)); $('#lkNum').html(obj.lkNum); $('#fhDay').html(obj.fhDay); $('#jbUser').html(obj.jbUser); @@ -53,6 +53,16 @@ function getPurchaseDetails() { } } +function formatMoney(value) { + // 第一步:处理空值/异常值,转为0 + let num = 0; + if (value !== null && value !== undefined && value !== '' && !isNaN(Number(value))) { + num = Number(value); + } + // 第二步:保留2位小数,返回带¥的格式化字符串 + return '¥ ' + num.toFixed(2); +} + // 采购发货明细 function getPurchaseDetailsList() { let params = { diff --git a/js/aq_demand_plan/child/send_out_edit_form.js b/js/aq_demand_plan/child/send_out_edit_form.js index f5e9e08..8e3fdba 100644 --- a/js/aq_demand_plan/child/send_out_edit_form.js +++ b/js/aq_demand_plan/child/send_out_edit_form.js @@ -205,43 +205,58 @@ function saveData2() { // 提交前确认 function beforeSubmitApply() { - // 校验附件证明是否上传 - let length = $('.file-iteme').length; - if (length === 0) { - return layer.msg('请上传附件证明', { icon: 7 }); - } let dataList = getBaseTableData(); - // 校验 发货明细数据 + let hasError = false; + let targetData = null; // 存储需要提交的目标数据 + let confirmIndex = -1; // 存储需要确认的行索引 + + // 第一步:先完成所有校验,不执行异步操作 for (let i = 0; i < dataList.length; i++) { + if (hasError) break; let o = dataList[i]; let list = o.supList; - let cgNum = 0,lkNum = 0; // 采购量、利库量 + let cgNum = 0,lkNum = 0; for (let j = 0; j < list.length; j++) { let l = list[j]; cgNum += (l.cgNum ? parseInt(l.cgNum) : 0); lkNum += (l.lkNum ? parseInt(l.lkNum) : 0); - if (!l.supId && cgNum > 0) { - // 采购才需要填写供应商 - return layer.msg('序号为' + (i + 1) + '的数据,未选择供应商', { icon: 7 }); - } - if (!l.ccDay) { - return layer.msg('序号为' + (i + 1) + '的数据,未选择出厂日期', { icon: 7 }); - } - if (!l.jyDay) { - return layer.msg('序号为' + (i + 1) + '的数据,未选择检验日期', { icon: 7 }); + let thisCgNum= (l.cgNum ? parseInt(l.cgNum) : 0); + if (!l.supId && thisCgNum > 0) { + layer.msg('序号为' + (i + 1) + '的数据,未选择供应商', { icon: 7 }); + hasError = true; + break; } } - - if (parseInt(o.needNum) < (cgNum + lkNum)) { // 采购量 大于需求量 - layer.confirm('序号为' + (i + 1) + '的数据,采购量和利库量大于需要量是否确认?', { - btn: ['确定', '关闭'] //按钮 - }, function(){ - openIframeByParamObj("quickAddForm", "采购发货确认", "./send_out_confirm.html", "92%", "92%", dataList); - }, function(){ - - }); + if (hasError) break; + if (cgNum + lkNum<=0) { + layer.msg('请填写采购量或利库量', { icon: 7 }); + hasError = true; + break; } + o.cgTotal = cgNum; // 存储总采购量 + o.lkTotal = lkNum; // 存储总利库量 + if (parseInt(o.needNum) < (cgNum + lkNum)) { + confirmIndex = i; + targetData = dataList; + break; // 先记录需要确认的行,终止循环 + } else { + targetData = dataList; + } + } + // 第二步:校验通过后,处理异步确认或直接打开弹窗 + if (hasError) return; + + if (confirmIndex > -1) { + // 有需要确认的行 + layer.confirm('序号为' + (confirmIndex + 1) + '的数据,采购量和利库量大于需要量是否确认?', { + btn: ['确定', '关闭'] + }, function(){ + openIframeByParamObj("quickAddForm", "采购发货确认", "./send_out_confirm.html", "92%", "92%", targetData); + }); + } else { + // 无需确认,直接打开 + openIframeByParamObj("quickAddForm", "采购发货确认", "./send_out_confirm.html", "92%", "92%", targetData); } } diff --git a/js/aq_demand_plan/child/send_out_form.js b/js/aq_demand_plan/child/send_out_form.js index 8fbf9d7..bf6465e 100644 --- a/js/aq_demand_plan/child/send_out_form.js +++ b/js/aq_demand_plan/child/send_out_form.js @@ -139,32 +139,74 @@ function saveData2() { // 提交前确认 function beforeSubmitApply() { - // 校验发货附件是否上传 - /* if (fileList.length === 0) { - return layer.msg('请上传发货附件', { icon: 7 }); - }*/ + // 校验发货附件是否上传(注释保留,可按需启用) + /* if (fileList.length === 0) { + layer.msg('请上传发货附件', { icon: 7 }); + return; // 这里直接return有效,因为不在嵌套循环内 + }*/ let dataList = getBaseTableData(); + // 1. 定义错误标记,用于终止多层循环和函数 + let hasError = false; + // 2. 定义变量存储需要确认的行索引(用于弹窗提示) + let needConfirmIndex = -1; + // 校验 发货明细数据 for (let i = 0; i < dataList.length; i++) { + if (hasError) break; // 已发现错误,直接终止外层循环 let o = dataList[i]; let list = o.supList; - let cgNum = 0,lkNum = 0; // 采购量、利库量 + let cgNum = 0, lkNum = 0; // 采购量、利库量 for (let j = 0; j < list.length; j++) { + if (hasError) break; // 已发现错误,终止内层循环 let l = list[j]; + // 累加采购量和利库量 cgNum += (l.cgNum ? parseInt(l.cgNum) : 0); lkNum += (l.lkNum ? parseInt(l.lkNum) : 0); - if (cgNum > 0 || lkNum > 0) { - // 如果没有选择供应商且 cgNum 大于 0,显示警告 - if (!l.supId && cgNum > 0) { - return layer.msg('序号为' + (i + 1) + '的数据,未选择供应商', { icon: 7 }); - } - } else { - // 如果 cgNum 和 lkNum 都不大于 0,弹出提示 - return layer.msg('序号为' + (i + 1) + '的数据,采购量 或 利库量 必须大于 0', { icon: 7 }); + let thisCgNum = (l.cgNum ? parseInt(l.cgNum) : 0); + + // 校验供应商是否选择(采购量大于0时必填) + if (!l.supId && thisCgNum > 0) { + layer.msg('序号为' + (i + 1) + '的数据,未选择供应商', { icon: 7 }); + hasError = true; // 标记错误状态 + break; // 终止内层循环 } } + if (hasError) break; // 再次判断,确保外层循环终止 + + // 校验采购量或利库量是否填写 + if (cgNum + lkNum <= 0) { + layer.msg('请填写采购量或利库量', { icon: 7 }); + hasError = true; + break; // 终止外层循环 + } + + // 校验:采购量+利库量 是否大于 需要量,记录需要确认的行索引 + if (parseInt(o.needNum) < (cgNum + lkNum)) { + needConfirmIndex = i; // 存储当前需要确认的行号 + break; // 发现需要确认的行,先终止循环(避免多笔数据重复弹窗) + } + } + + // 若存在错误,直接退出函数,不执行后续操作 + if (hasError) { + return; + } + + // 3. 处理 layer.confirm 确认提示逻辑 + if (needConfirmIndex > -1) { + // 有数据需要确认,弹出确认弹窗 + layer.confirm('序号为' + (needConfirmIndex + 1) + '的数据,采购量和利库量大于需要量是否确认?', { + btn: ['确定', '关闭'] // 弹窗按钮 + }, function(){ + // 用户点击“确定”,执行打开iframe操作 + openIframeByParamObj("quickAddForm", "采购发货确认", "./send_out_confirm.html", "92%", "92%", dataList); + }, function(){ + // 用户点击“关闭”,不执行任何操作(弹窗关闭) + }); + } else { + // 无需确认(采购量+利库量 ≤ 需要量),直接打开iframe + openIframeByParamObj("quickAddForm", "采购发货确认", "./send_out_confirm.html", "92%", "92%", dataList); } - openIframeByParamObj("quickAddForm", "采购发货确认", "./send_out_confirm.html", "92%", "92%", dataList); } // 提交 diff --git a/js/aq_demand_plan/child/send_out_pro_detail.js b/js/aq_demand_plan/child/send_out_pro_detail.js index 0491196..29d7740 100644 --- a/js/aq_demand_plan/child/send_out_pro_detail.js +++ b/js/aq_demand_plan/child/send_out_pro_detail.js @@ -265,6 +265,7 @@ function initTable() { html += "详情"; html += "
|
修改发货"; html += "
|
二维码下载"; + html += "
|
补发货"; html += "
|
撤销"; } @@ -321,6 +322,8 @@ function sendOutForm(obj, type) { let content = '../aq_demand_plan/child/send_out_form.html'; if (type === 2) { content = '../aq_demand_plan/child/send_out_edit_form.html'; + } else if (type === 3) { + content = '../aq_demand_plan/child/send_out_supplemen.html'; } openIframeByParamObj2("sendOutForm", "采购发货", content, "92%", "95%", obj); } diff --git a/js/aq_demand_plan/child/send_out_supplement.js b/js/aq_demand_plan/child/send_out_supplement.js new file mode 100644 index 0000000..5867d55 --- /dev/null +++ b/js/aq_demand_plan/child/send_out_supplement.js @@ -0,0 +1,693 @@ +// 全局变量定义 +let objParam, dataObj, fileList = new Array(), imgListUp = new Array(), delImgIdList = []; +let form, laydate, layer, upload, table, util; +let pageNum = 1, tableIns; +let supplierList = []; +let delSupIdArr = []; +// 存储原始采购量/利库量(用于灵活校验,独立于DOM元素) +let originalCgLkMap = new Map(); // key: modelId_index, value: {originalCgNum: 0, originalLkNum: 0} + +// 设置参数初始化 +function setParams(obj) { + objParam = JSON.parse(obj); + console.error(objParam); + $('#proName').html(objParam.proName); + $('#companyName').val((objParam.companyName !== null && objParam.companyName !== '') ? objParam.companyName : '/'); + layui.use(['form', 'layer', 'laydate', 'upload', 'table'], function () { + form = layui.form; + layer = layui.layer; + laydate = layui.laydate; + upload = layui.upload; + table = layui.table; + util = layui.util; + + // 渲染日期选择器(只读状态,不可修改) + laydate.render({ + elem: '#fhDay', + trigger: 'none' // 禁止触发日期选择 + }); + laydate.render({ + elem: '.cjDate', + trigger: 'none' + }); + laydate.render({ + elem: '.jyDate', + trigger: 'none' + }); + + form.verify(); + // 表单提交监听 + form.on('submit(formData)', function (data) { + beforeSubmitApply(data); + }); + + // 文件上传配置(仅可新增,不可删除原有附件) + let uploadObj = upload.render({ + elem: '#test2', + multiple: true, + dataType: "json", + exts: 'jpg|png|jpeg|doc|docx|pdf|xlsx|xls', + acceptMime: 'image/jpg,image/png,image/jpeg,application/pdf,application/msword,application/vnd.openxmlformats-officedocument.wordprocessingml.document,application/vnd.ms-excel,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', + number: 5, //最大上传数量 + size: 1024 * 10, //最大文件大小,单位k + auto: false, //是否自动上传 + bindAction: '#hideUpload', //绑定的按钮 + choose: function (obj) { + let length = $('.file-iteme').length; + if (length >= 5) { + return layer.msg('最多上传5个发货附件', { icon: 7 }); + } + uploadObj.config.elem.next()[0].value = ''; + let num = 0; + obj.preview(function (index, file, result) { + num++; + if (num <= (5 - length)) { + $('#uploader-list').append( + '
' + + '' + // 隐藏删除按钮 + handleFileType(index, file, result) + + '
' + ); + let map = new Map(); + map.index = index; + map.file = file; + fileList.push(map); + } + }); + } + }); + }); + // 先获取供应商,再加载其他数据,解决异步加载问题 + getSupplierList(function() { + getPurchaseDetails(); + getPurchaseDetailsList(); + }); +} + +// 获取采购详情(回填只读数据) +function getPurchaseDetails() { + let params = { + encryptedData: JSON.stringify({ + 'id': objParam.id + }) + }; + let url = dataUrl + 'backstage/purchase/getPurchaseDetails'; + ajaxRequest(url, "POST", params, true, function () { + }, function (result) { + console.error(result); + if (result.code === 200) { + dataObj = result.data; + setFormData(result.data); + } else { + } + }, function (xhr, status, error) { + errorFn(xhr, status, error) + }, null); + + function setFormData(obj) { + $('#code').html(obj.planCode); + // 表单赋值(全部只读) + form.val('formInfo', obj); + let fileList = obj.fileList, html = ''; + for (let i = 0; i < fileList.length; i++) { + let path = fileUrl + fileList[i].fileUrl + '?token=' + sessionStorage.getItem("gz-token"); + let file = { name: fileList[i].fileName, id: fileList[i].id }; + html += '
' + + '' + // 隐藏删除按钮,不可删除原有附件 + handleFileType(i, file, path) + + '
' + } + $('#uploader-list').append(html); + } +} + +// 获取发货明细列表 +function getPurchaseDetailsList() { + let params = { + encryptedData: JSON.stringify({ + 'id': objParam.id + }) + }; + let url = dataUrl + 'backstage/purchase/getPurchaseDetailsList'; + ajaxRequest(url, "POST", params, true, function () { + }, function (result) { + console.error(result); + if (result.code === 200) { + // 先存储原始采购量/利库量到全局Map(强制确保键值正确) + saveOriginalCgLkNum(result.data); + // 渲染表格 + setBaseTable(result.data); + } + }, function (xhr, status, error) { + errorFn(xhr, status, error) + }, null); +} + +// 存储原始采购量/利库量(核心:修复键值生成逻辑,确保唯一性和一致性) +function saveOriginalCgLkNum(data) { + if (!data || data.length === 0) return; + originalCgLkMap.clear(); + for (let i = 0; i < data.length; i++) { + let item = data[i]; + let modelId = item.modelId || 'default_' + i; // 兜底:防止modelId为空 + if (item.supList && item.supList.length > 0) { + for (let j = 0; j < item.supList.length; j++) { + let supItem = item.supList[j]; + let key = modelId + '_' + j; // 明确:modelId + 索引j,与提交校验时一致 + originalCgLkMap.set(key, { + originalCgNum: parseInt(supItem.cgNum || 0), + originalLkNum: parseInt(supItem.lkNum || 0) + }); + // 控制台打印:方便调试查看原始值存储情况 + console.log('原始值存储 - 键:', key, ' 采购量:', parseInt(supItem.cgNum || 0), ' 利库量:', parseInt(supItem.lkNum || 0)); + } + } + } +} + +// 设置文件类型渲染 +function handleFileType(index, file, result) { + let html = '', img = ''; + if (file.ext) { + file.ext = file.ext.toLowerCase(); + } + if (file.name) { + file.name = file.name.toLowerCase(); + } + if (file.ext === 'doc' || file.ext === 'docx' || file.name.indexOf('doc') > -1 || file.name.indexOf('docx') > -1) { + img = '../../../images/docx.png'; + } else if (file.ext === 'xls' || file.ext === 'xlsx' || file.name.indexOf('xls') > -1 || file.name.indexOf('xlsx') > -1) { + img = '../../../images/xlsx.png'; + } else if (file.ext === 'pdf' || file.name.indexOf('pdf') > -1) { + img = '../../../images/pdf.png'; + } else { + return ''; + } + html += '
' + + '' + + '

' + file.name + '

' + + '
'; + return html; +} + +// 隐藏删除按钮,禁止删除文件(补充模式下仅可新增附件) +$(document).on("click", ".file-iteme .handle", function (event) { + layer.msg('补充模式下不可删除附件,仅可新增', { icon: 7 }); + return false; +}); + +// 触发表单提交 +function saveData2() { + $('#formSubmit').trigger('click') +} + +// 提交前确认与灵活校验(核心修复:供应商回显+采购量>0时必填供应商) +function beforeSubmitApply() { + let dataList = getBaseTableData(); + let hasError = false; + let targetData = null; + let confirmIndex = -1; + + // 第一步:优先校验采购量/利库量是否小于原始值(最高优先级,发现错误立即阻断) + for (let i = 0; i < dataList.length; i++) { + if (hasError) break; + let o = dataList[i]; + let modelId = o.modelId || 'default_' + i; // 与存储时兜底逻辑一致 + let list = o.supList; + let cgNum = 0, lkNum = 0; + + for (let j = 0; j < list.length; j++) { + let l = list[j]; + let currentCgNum = parseInt(l.cgNum || 0); + let currentLkNum = parseInt(l.lkNum || 0); + cgNum += currentCgNum; + lkNum += currentLkNum; + + // 关键修复:使用与存储时完全一致的键值,获取原始值 + let key = modelId + '_' + j; + let originalData = originalCgLkMap.get(key); + + // 兜底:防止原始值未获取到 + if (!originalData) { + layer.msg('序号为' + (i + 1) + '的数据,未获取到原始数据,请刷新页面重试', { icon: 7 }); + hasError = true; + break; + } + + // 强制校验:采购量不可小于原始值 + if (currentCgNum < originalData.originalCgNum) { + layer.msg('序号为' + (i + 1) + '的数据,采购量不可小于原始值:' + originalData.originalCgNum + '(当前值:' + currentCgNum + ')', { icon: 7 }); + hasError = true; + break; + } + // 强制校验:利库量不可小于原始值(修复第二条数据不提示问题) + if (currentLkNum < originalData.originalLkNum) { + layer.msg('序号为' + (i + 1) + '的数据,利库量不可小于原始值:' + originalData.originalLkNum + '(当前值:' + currentLkNum + ')', { icon: 7 }); + hasError = true; + break; + } + + // 新增校验:采购量>0时,供应商为必填项 + if (currentCgNum > 0 && (!l.supId || l.supId === '')) { + layer.msg('序号为' + (i + 1) + '的数据,采购量大于0时必须选择供应商', { icon: 7 }); + hasError = true; + break; + } + + } + + if (hasError) break; + + // 第二步:校验采购量+利库量不可全部为0 + if (cgNum + lkNum <= 0) { + layer.msg('序号为' + (i + 1) + '的数据,请填写采购量或利库量(不可全部为0)', { icon: 7 }); + hasError = true; + break; + } + + o.cgTotal = cgNum; + o.lkTotal = lkNum; + + // 第三步:校验采购量+利库量是否大于需用量(仅当前面无错误时执行) + let needNumInt = parseInt(o.needNum || 0); + if (cgNum + lkNum > needNumInt) { + confirmIndex = i; + targetData = dataList; + // 不break,继续校验其他数据是否有原始值违规 + } else { + if (!targetData) { + targetData = dataList; + } + } + } + + // 若存在错误,直接返回,不执行后续逻辑 + if (hasError) return; + + // 第四步:仅当无任何错误时,才判断是否需要弹出总量超需用量的确认框 + if (confirmIndex > -1) { + layer.confirm('序号为' + (confirmIndex + 1) + '的数据,采购量+利库量总和大于需要量,是否确认提交?', { + btn: ['确定', '关闭'] + }, function () { + openIframeByParamObj("quickAddForm", "采购发货补充确认", "./send_out_confirm.html", "92%", "92%", targetData); + }); + } else { + openIframeByParamObj("quickAddForm", "采购发货补充确认", "./send_out_confirm.html", "92%", "92%", targetData); + } +} + +// 提交数据到后台 +function submitApply() { + // 补充模式下,清空供应商删除ID,禁止删除供应商 + delSupIdArr = []; + + let data = form.val('formInfo'); + let dataList = getBaseTableData(); + data.id = dataObj.id; + data.detailsList = dataList; + data.planId = objParam.id; + data.proId = objParam.proId; + + // 补充模式下,禁止删除原有文件,清空删除文件ID + delImgIdList = []; + let delFileId = '', delSupId = ''; + if (delImgIdList && delImgIdList.length > 0) { + for (let i = 0; i < delImgIdList.length; i++) { + if (i === delImgIdList.length - 1) { + delFileId += delImgIdList[i]; + } else { + delFileId += delImgIdList[i] + '@'; + } + } + } + if (delSupIdArr && delSupIdArr.length > 0) { + for (let i = 0; i < delSupIdArr.length; i++) { + if (i === delSupIdArr.length - 1) { + delSupId += delSupIdArr[i]; + } else { + delSupId += delSupIdArr[i] + '@'; + } + } + } + data.delFileId = delFileId; + data.delSupId = delSupId; + let formData = new FormData(); + for (let i = 0; i < fileList.length; i++) { + formData.append("file[]", fileList[i].file) + } + console.log(data); + formData.append('params', JSON.stringify(data)); + let loadingMsg = layer.msg('正在提交补充,请稍等...', { icon: 16, shade: 0.01, time: '0' }); + let url = dataUrl + 'backstage/purchase/updatePurchaseData'; + ajaxRequestByUploadFile(url, formData, function () { + $('.save').addClass("layui-btn-disabled").attr("disabled", true); + $('.cancel').addClass("layui-btn-disabled").attr("disabled", true); + }, function (result) { + layer.close(loadingMsg); + $('.save').removeClass("layui-btn-disabled").attr("disabled", false); + $('.cancel').removeClass("layui-btn-disabled").attr("disabled", false); + if (result.code === 200) { + parent.layer.msg(result.msg, { icon: 1 }); + closePage(result.data); + } else { + layer.msg(result.msg, { icon: 2 }); + } + }, function (xhr, status, error) { + layer.close(loadingMsg); + layer.msg('服务异常,请稍后重试', { icon: 16, scrollbar: false, time: 2000 }); + $('.save').removeClass("layui-btn-disabled").attr("disabled", false); + $('.cancel').removeClass("layui-btn-disabled").attr("disabled", false); + errorFn(xhr, status, error) + }, null); +} + +// 获取供应商下拉选列表(新增回调,确保先加载供应商再渲染表格) +function getSupplierList(callback) { + supplierList.splice(0, supplierList.length); + let encryptedData = {}; + let url = dataUrl + 'backstage/sup/getSelected?encryptedData=' + encodeURIComponent(JSON.stringify(encryptedData)); + ajaxRequest(url, "GET", null, false, function () { + }, function (result) { + if (result.code === 200) { + supplierList = result.data; + // 执行回调函数 + if (typeof callback === 'function') { + callback(); + } + } + }, function (xhr, status, error) { + errorFn(xhr, status, error); + // 即使获取失败,也执行回调,避免页面阻塞 + if (typeof callback === 'function') { + callback(); + } + }, null); +} + +// 厂家校验(禁用,仅保留兼容,不限制供应商) +function supCheck(modelId, contractId, value) { + return true; // 直接返回通过,不做校验 +} + +// 库存数量校验(保留,不影响核心逻辑) +function maTypeCheck(modelId) { + let num = 0; + let params = { + encryptedData: JSON.stringify({ + 'modelId': modelId + }) + }; + let url = dataUrl + 'backstage/maType/maTypeCheck'; + ajaxRequest(url, "POST", params, false, function () { + }, function (result) { + if (result.code === 200) { + num = result.data; + } + }, function (xhr, status, error) { + errorFn(xhr, status, error) + }, null); + return num; +} + +// 获取发货明细表格数据(确保modelId和索引j正确传递) +function getBaseTableData() { + let dataList = []; + $('#baseTable tbody tr.mainTr').each(function (trIndex) { + let obj = {}; + let modelId = $(this).attr('id') || 'default_' + trIndex; // 与存储时兜底逻辑一致 + let detailId = $(this).attr('detailId'); + let type = $(this).find('td').eq(2).html(); + let name = $(this).find('td').eq(3).html(); + let model = $(this).find('td').eq(4).html(); + let unit = $(this).find('td').eq(5).html(); + let needNum = $(this).find('td').eq(6).html(); + let formList = []; + let idx = $('.model' + modelId).length; + + for (let i = 0; i < idx; i++) { + let formObj = {}; + let dataId = $('.model' + modelId).eq(i).attr('dataId'); + let num = $('.num' + modelId).eq(i).val(); + let lkNum = $('.lkNum' + modelId).eq(i).val(); + let supplier = $('.supplier' + modelId).eq(i).val(); + let supplierName = $('.supplier' + modelId).eq(i).find('option:checked').text(); + let contractId = ''; + if (supplier) { + let item = JSON.parse($('.supplier' + modelId).eq(i).find('option:checked').attr('item')); + contractId = item.contractId; + } + let cjDate = $('.cjDate' + modelId).eq(i).val(); + let jyDate = $('.jyDate' + modelId).eq(i).val(); + let remark = $('.remark' + modelId).eq(i).val(); + formObj.cgNum = num; + formObj.lkNum = lkNum; + formObj.supId = supplier; + formObj.supName = supplierName; + formObj.ccDay = cjDate; + formObj.jyDay = jyDate; + formObj.remark = remark; + formObj.modelId = modelId; // 确保modelId正确赋值 + formObj.contractId = contractId; + formObj.id = dataId; + formList.push(formObj); + } + + obj.modelId = modelId; + obj.id = detailId; + obj.type = type; + obj.name = name; + obj.model = model; + obj.unit = unit; + obj.needNum = needNum; + obj.supList = formList; + dataList.push(obj); + }) + return dataList; +} + +// 关闭当前页面(iframe) +function closePage(data) { + let index = parent.layer.getFrameIndex(window.name); + if (data) { + let obj = { + resultData: data.resultData, + resultData2: data.resultData2, + id: data.planId + }; + let frameId = parent.document.getElementById('sendOutProDetail').getElementsByTagName("iframe")[0]; + frameId.contentWindow.sendOutSuccess(JSON.stringify(obj)); + } + parent.layer.close(index); +} + +// 监听采购量输入框(增强提示:实时+失焦双重提示,确保用户感知) +// 修复:选择器匹配修改后的输入框类名,确保监听生效 +$(document).on('input blur', '.num, .num' + objParam.modelId, function () { + let $this = $(this); + let modelId = $this.attr('modelId') || $this.closest('tr').attr('id') || $this.closest('tr').attr('class').match(/model(\S+)/)[1] || 'default_0'; + let index = $this.attr('index') || $this.closest('td').index() - 7 || 0; + let currentVal = parseInt($this.val() || 0); + let key = modelId + '_' + index; + let originalData = originalCgLkMap.get(key); + + if (!originalData) return; + + // 实时提示:采购量不可小于原始值 + if (currentVal < originalData.originalCgNum) { + layer.tips('采购量不可小于原始值:' + originalData.originalCgNum + '(当前值:' + currentVal + ')', $this, { + tips: [1, '#f56c6c'], + time: 3000 + }); + } + + // 实时提示:采购量>0时需要选择供应商 + if (currentVal > 0) { + let $supplier = $('.supplier' + modelId).eq(index); + if (!$supplier.val() || $supplier.val() === '') { + layer.tips('采购量大于0时必须选择供应商', $supplier, { + tips: [1, '#f56c6c'], + time: 3000 + }); + } + } +}); + +// 监听利库量输入框(增强提示:实时+失焦双重提示,确保用户感知) +// 修复:选择器匹配修改后的输入框类名,确保监听生效 +$(document).on('input blur', '.lkNum, .lkNum' + objParam.modelId, function () { + let $this = $(this); + let modelId = $this.attr('modelId') || $this.closest('tr').attr('id') || $this.closest('tr').attr('class').match(/model(\S+)/)[1] || 'default_0'; + let index = $this.attr('index') || $this.closest('td').index() - 7 || 0; + let currentVal = parseInt($this.val() || 0); + let key = modelId + '_' + index; + let originalData = originalCgLkMap.get(key); + + if (!originalData) return; + + // 实时提示:输入时就给出反馈,修复第二条数据不提示问题 + if (currentVal < originalData.originalLkNum) { + layer.tips('利库量不可小于原始值:' + originalData.originalLkNum + '(当前值:' + currentVal + ')', $this, { + tips: [1, '#f56c6c'], + time: 3000 + }); + } +}); + +// 空值处理函数(对齐参考文件) +function setNullValue(val) { + return val === undefined || val === null || val === '' ? '' : val; +} + +// 构建下拉选数据(对齐参考文件逻辑,核心修复供应商回显) +function setSelectData(modelId, value) { + let html = ""; + if (!supplierList || supplierList.length === 0) { + return html; + } + $.each(supplierList, function (index, item) { + // 统一转为字符串,解决类型不匹配问题 + let targetValue = (value || '').toString().trim(); + let supIdStr = (item.supId || item.id).toString().trim(); + let selected = ''; + if (targetValue === supIdStr) { + selected = 'selected'; + } + // 转义JSON中的双引号,避免HTML渲染异常 + let itemJson = JSON.stringify(item).replace(/"/g, '"'); + html += ""; + }); + return html; +} + +// 构建表单输入项(核心修复:出厂日期/检验日期/备注添加readonly属性,禁用编辑) +function setFormInput(value, type, id) { + let html = '
'; + let safeValue = setNullValue(value); + + if (type === 1) { // 采购量 + html += ''; + } else if (type === 2) { // 利库量 + let oldValue = safeValue || 0; + html += ''; + } else if (type === 3) { // 供应商(核心:调用setSelectData构建下拉选) + html += ''; + } else if (type === 4) { // 出厂日期:添加readonly属性,禁用编辑 + html += ''; + } else if (type === 5) { // 检验日期:添加readonly属性,禁用编辑 + html += ''; + } else if (type === 6) { // 备注:添加readonly属性,禁用编辑 + html += ''; + } + html += '
'; + return html; +} + +// 完整setBaseTable函数(完全对齐参考文件结构,保留索引属性确保提示生效) +function setBaseTable(data) { + let html = ""; + if (data && data.length > 0) { + for (var i = 0; i < data.length; i++) { + var l = data[i]; + let list = l.supList || []; + // 对齐参考文件,遍历supList渲染主行和子行 + $.each(list, function (index, item) { + // 给每个输入框绑定index属性,确保提示功能能获取到正确索引 + let itemIndex = index; + if (index === 0) { + // 主行:带rowspan合并单元格 + html += ""; + html += ''; + html += "" + (i + 1) + ""; + html += "" + (l.type || '') + ""; + html += "" + (l.name || '') + ""; + html += "" + (l.model || '') + ""; + html += "" + (l.unit || '') + ""; + html += "" + (l.needNum || 0) + ""; + // 采购量:添加index属性 + html += "" + setFormInput(item.cgNum, 1, l.modelId).replace('"; + // 利库量:添加index属性 + html += "" + setFormInput(item.lkNum, 2, l.modelId).replace('"; + html += "" + setFormInput(item.supId, 3, l.modelId) + ""; + // 出厂日期:已通过setFormInput添加readonly + html += "" + setFormInput(item.ccDay, 4, l.modelId) + ""; + // 检验日期:已通过setFormInput添加readonly + html += "" + setFormInput(item.jyDay, 5, l.modelId) + ""; + // 备注:已通过setFormInput添加readonly + html += "" + setFormInput(item.remark, 6, l.modelId) + ""; + html += ""; + } else { + // 子行:不合并单元格 + html += ""; + // 采购量:添加index属性 + html += "" + setFormInput(item.cgNum, 1, l.modelId).replace('"; + // 利库量:添加index属性 + html += "" + setFormInput(item.lkNum, 2, l.modelId).replace('"; + html += "" + setFormInput(item.supId, 3, l.modelId) + ""; + // 出厂日期:已通过setFormInput添加readonly + html += "" + setFormInput(item.ccDay, 4, l.modelId) + ""; + // 检验日期:已通过setFormInput添加readonly + html += "" + setFormInput(item.jyDay, 5, l.modelId) + ""; + // 备注:已通过setFormInput添加readonly + html += "" + setFormInput(item.remark, 6, l.modelId) + ""; + html += ""; + } + }); + } + } else { + html += "没有相关数据"; + } + $("#baseTable tbody").empty().append(html); + // 重新渲染日期选择器 + laydate.render({ + elem: '.cjDate', + trigger: 'none' // 再次确认日期选择器不可触发 + }); + laydate.render({ + elem: '.jyDate', + trigger: 'none' // 再次确认日期选择器不可触发 + }); + // 强制渲染layui表单,确保供应商下拉选生效 + layui.form.render(); +} + +// 校验数据(保留原有逻辑,确保失焦时校验提示生效) +function checkValue(that, type) { + let value = $(that).val().trim(); + // 统一处理前置0(保留纯0的情况) + let processedValue = value.replace(/^0+(?=\d)/, ''); + if (processedValue === '') { + processedValue = '0'; // 输入全是0的情况(如0000)转为0 + } + // 先更新输入框值为处理后的值 + $(that).val(processedValue); + value = processedValue; // 后续校验使用处理后的值 + + if (type === 1) { // 采购量 + const regex = /^(0|[1-9]\d{0,6})$/; + if (!regex.test(value) && value) { + $(that).val(0); + return layer.msg('采购量输入有误,请重新输入!', { icon: 5 }) + } + } else if (type === 2) { // 利库量 + const regex = /^(0|[1-9]\d{0,6})$/; + if (!regex.test(value) && value) { + $(that).val(0); + return layer.msg('利库量输入有误,请重新输入!', { icon: 5 }) + } + if (value) { + // 新的利库量与库存量校验 + let modelId = $(that).attr('modelId'); + let oldValue = $(that).attr('oldValue'); + let num = maTypeCheck(modelId); + let newValue = parseInt(value) - parseInt(oldValue); + if (newValue > 0) { + if (newValue > num) { + $(that).val(oldValue); + return layer.msg('利库量不能大于库存量,请重新输入!', { icon: 5 }) + } + } + } + } +} \ No newline at end of file diff --git a/js/aq_inventory/safety_tools_ledger.js b/js/aq_inventory/safety_tools_ledger.js index 72d0c45..2b63350 100644 --- a/js/aq_inventory/safety_tools_ledger.js +++ b/js/aq_inventory/safety_tools_ledger.js @@ -1,13 +1,60 @@ let form, table; let tableIns; let pageNum = 1; // 定义分页 +let proListData = []; // 存储工程列表数据(新增) + layui.use(["form", "table"], function () { form = layui.form; table = layui.table; + getProList(); // 新增:加载工程下拉数据 initTable(); getStatistics(); }); +// 新增:获取工程列表数据 +function getProList() { + let url = dataUrl + 'backstage/planApply/getProSelectAndCompanyName'; + ajaxRequest(url, "POST", null, false, function () { + console.log("开始获取工程列表..."); + }, function (result) { + console.log("获取工程列表结果:", result); + if (result.code === 200) { + if (result.data && result.data.length > 0) { + console.log("工程数据:", result.data); + proListData = result.data; + setSelectProData(result.data); // 渲染工程下拉选 + } else { + console.warn("工程列表为空"); + setSelectProData([]); + } + } else { + console.error("获取工程列表失败:", result.msg); + } + }, function (xhr, status, error) { + console.error("获取工程列表异常:", error); + errorFn(xhr, status, error) + }, null); +} + +// 新增:渲染工程下拉选 +function setSelectProData(proList) { + let html = ''; + $.each(proList || [], function (index, item) { + // 拼接工程名称和公司名称(如果有) + let proText = item.name || item.proName || ''; + if (item.companyName) { + proText += ' - ' + item.companyName; + } + html += ''; + }); + + $('#projectId').empty().append(html); + + // 重新渲染Layui表单 + if (layui && layui.form) { + layui.form.render('select'); + } +} // 数据概览 function getStatistics() { @@ -51,6 +98,7 @@ function queryTable(type) { $('#keyWord').val(''); $('#useUnit').val(''); $('#isShortage').val(''); + $('#projectId').val(''); // 新增:重置工程下拉选 layui.form.render(); reloadTable(1); } @@ -62,20 +110,23 @@ function reloadData() { getStatistics(); } -// 重载表格 +// 重载表格 - 修改:添加工程筛选条件 function reloadTable(pageNum) { table.reload("currentTableId", { - where: { - encryptedData: JSON.stringify({ - 'keyWord': $('#keyWord').val(), - 'isShortage': $('#isShortage').val() - }), + page: { + curr: pageNum ? pageNum : 1, + }, + where: { + encryptedData: JSON.stringify({ + 'keyWord': $('#keyWord').val(), + 'proId': $('#projectId').val() // 新增:工程ID筛选条件 + }), + }, }, - }, ); } -// 初始化表格 +// 初始化表格 - 修改:添加工程筛选条件 function initTable() { tableIns = table.render({ elem: "#currentTableId", @@ -87,7 +138,8 @@ function initTable() { url: dataUrl + "backstage/inventoryCount/getSafetyToolsLedger", where: { encryptedData: JSON.stringify({ - 'keyWord': $('#keyWord').val() + 'keyWord': $('#keyWord').val(), + 'proId': $('#projectId').val() }), }, request: { @@ -116,61 +168,150 @@ function initTable() { }, }, { - field: "type", + field: "proName", width: '15%', - title: "物资类型", + title: "工程名称", unresize: true, align: "center", }, { field: "name", - width: '15%', + width: '8%', title: "物资名称", unresize: true, align: "center", }, { field: "model", - width: '18%', + width: '8%', title: "规格型号", unresize: true, align: "center", }, { - field: "storageNum", - width: '16%', - title: "库存量", + field: "unit", + width: '5%', + title: "单位", unresize: true, align: "center", - sort: true, }, { - field: "totalCk", - width: '16%', - title: "出库总量", + field: "planApplyCode", + width: '10%', + title: "计划编号", + unresize: true, + align: "center", + }, + { + field: "needNum", + width: '7%', + title: "总需用量", unresize: true, align: "center", - sort: true, templet: function (d) { - return d.totalCk || 0; + return d.needNum || 0; }, }, { - field: "totalBack", + field: "price", + width: '8%', + title: "单价", + unresize: true, + align: "center", + }, + { + field: "totalPrice", + width: '8%', + title: "总价", + unresize: true, + align: "center", + templet: function (d) { + // 转换为数字,空值默认0,避免NaN + const price = Number(d.price || 0); + const needNum = Number(d.needNum || 0); + // 计算总价并保留2位小数(金额常用格式) + const totalPrice = (price * needNum).toFixed(2); + return totalPrice; + }, + }, + { + field: "outInfo", + width: '14.5%', + title: "发货时间", + unresize: true, + align: "center", + }, + { + field: "outAddress", width: '15%', - title: "退还数量", + title: "发货地址", unresize: true, align: "center", - sort: true, - templet: function (d) { - return d.totalBack || 0; - }, }, + { + field: "supName", + width: '10%', + title: "供应商", + unresize: true, + align: "center", + }, + { + field: "backNum", + width: '8%', + title: "退还数量", + align: "center", + templet: function (d) { + return Number(d.backNum ?? 0); + } + }, + { + field: "backTime", + width: '15.5%', + title: "退还时间", + align: "center", + }, + { + title: "差缺", + width: '8%', + align: "center", + templet: function (d) { + let needNum = Number(d.needNum ?? 0); + let backNum = Number(d.backNum ?? 0); + + let diff = needNum - backNum; // 允许为负数 + return diff; + } + }, + { + title: "差缺总价", + width: '8%', + align: "center", + templet: function (d) { + // 转换为数字,空值默认0,避免NaN + let needNum = Number(d.needNum ?? 0); + let backNum = Number(d.backNum ?? 0); + let price = Number(d.price || 0); + + // 计算差缺数量 + let diff = needNum - backNum; + // 计算差缺总价 = 差缺数量 × 单价,保留2位小数 + let diffTotalPrice = (diff * price).toFixed(2); + + return diffTotalPrice; + } + }, + { + field: "remark", + width: '6%', + title: "备注", + align: "center", + }, + ], ], limits: [10, 20, 30, 50, 100], - limit: 50, - page: false, + limit: 10, + page: true, done: function (res, curr, count) { pageNum = tableIns.config.page.curr; table.resize("currentTableId"); @@ -178,32 +319,25 @@ function initTable() { }); } -// 查看详情 -function viewDetail(id) { - layer.msg('查看工程物料详情功能待开发', { icon: 1 }); - // 这里可以添加查看详情的逻辑,比如打开新窗口或弹窗显示详细信息 - // openIframe('工程物料详情', 'page/aq_inventory/project_material_detail.html?id=' + id); -} - -// 导出Excel +// 导出Excel - 修改:添加工程筛选条件 function exportExcel() { let keyWord = $('#keyWord').val(); - let isShortage = $('#isShortage').val(); - + let projectId = $('#projectId').val(); + let params = { 'keyWord': keyWord, - 'isShortage': isShortage + 'proId': projectId // 新增:工程ID筛选条件 }; - + let encryptedData = JSON.stringify(params); - let url = dataUrl + 'backstage/inventoryCount/exportLedgerListByProjectAndModel?encryptedData=' + encodeURIComponent(encryptedData); - + let url = dataUrl + 'backstage/inventoryCount/exportLedgerList?encryptedData=' + encodeURIComponent(encryptedData); + // 创建隐藏的下载链接 let link = document.createElement('a'); link.href = url; - link.download = '工程物料统计_' + new Date().getTime() + '.xlsx'; + link.download = '安全用品发放台账_' + new Date().getTime() + '.xlsx'; link.style.display = 'none'; - + // 添加授权头并下载 fetch(url, { method: 'GET', @@ -226,4 +360,4 @@ function exportExcel() { }).catch(error => { layer.msg('导出失败:' + error.message, { icon: 2 }); }); -} \ No newline at end of file +} \ No newline at end of file diff --git a/page/aq_demand_plan/child/send_out_edit_form.html b/page/aq_demand_plan/child/send_out_edit_form.html index 29633c6..5488aba 100644 --- a/page/aq_demand_plan/child/send_out_edit_form.html +++ b/page/aq_demand_plan/child/send_out_edit_form.html @@ -78,7 +78,7 @@
-

发货附件*

+

发货附件

@@ -155,9 +155,9 @@ 需要量 *采购量 *利库量 - *供应商 - *出厂日期 - *检验日期 + 供应商 + 出厂日期 + 检验日期 备注 diff --git a/page/aq_demand_plan/child/send_out_form.html b/page/aq_demand_plan/child/send_out_form.html index 1f05f9c..77ea07d 100644 --- a/page/aq_demand_plan/child/send_out_form.html +++ b/page/aq_demand_plan/child/send_out_form.html @@ -84,7 +84,7 @@
-

必传项:请上传出门条

+

请上传出门条

可选项: 领料单、装卸货照片、车牌号

@@ -155,7 +155,7 @@ 需要量 *采购量 *利库量 - *供应商 + 供应商 出厂日期 检验日期 备注 diff --git a/page/aq_demand_plan/child/send_out_supplemen.html b/page/aq_demand_plan/child/send_out_supplemen.html new file mode 100644 index 0000000..a19c776 --- /dev/null +++ b/page/aq_demand_plan/child/send_out_supplemen.html @@ -0,0 +1,189 @@ + + + + + + + 采购发货-补充 + + + + + + + + +
+
+
+ +
+

+

+
+
+
+
+
+ +

采购发货资料填写

+
+
+
+ +
+ +
+
+
+ +
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+
+ +
+ +
+
+
+ +
+ +
+
+ +
+
+
+

发货附件

+
+
+ +
+
+

提示:最多上传5个附件

+

支持格式:jpg、png、jpeg

+

doc、docx、pdf、xlsx、xls

+
+
+
+
+ +

发货明细(仅可增加采购量/利库量)

+
+
+ 搜索信息 +
+
+
+
+
+ +
+
+
+
+ +
+
+
+ + +
+
+
+
+ +

拆分

+
+

(一条物品采购多家时,请勾选后点击拆分)

+

取消拆分

+
+
+
+
+
+ +

快捷录入

+
+

(点击一键录入全部信息)

+
+
+
+
+
+
+
+ + + + + + + + + + + + + + + + + + + +
+ + 序号类型名称规格单位需要量*采购量*利库量供应商出厂日期检验日期备注
+
+
+
+ + +
+
+ + + + + + + + + + \ No newline at end of file diff --git a/page/aq_demand_plan/child/send_out_unplanned_form.html b/page/aq_demand_plan/child/send_out_unplanned_form.html index db0bec4..657fa44 100644 --- a/page/aq_demand_plan/child/send_out_unplanned_form.html +++ b/page/aq_demand_plan/child/send_out_unplanned_form.html @@ -84,7 +84,7 @@
-

必传项:请上传出门条

+

请上传出门条

可选项: 领料单、装卸货照片、车牌号

diff --git a/page/aq_inventory/safety_tools_ledger.html b/page/aq_inventory/safety_tools_ledger.html index ea564f1..32b8d26 100644 --- a/page/aq_inventory/safety_tools_ledger.html +++ b/page/aq_inventory/safety_tools_ledger.html @@ -37,10 +37,18 @@
+
+ +
+ +
+
+ class="layui-input" lay-affix="clear" placeholder="输入关键字" maxlength="30">