| | |
| | | .over-limit #selectedTotal { |
| | | color: #FF5722 !important; /* 红色警告 */ |
| | | } |
| | | |
| | | /* 订单完成状态 */ |
| | | .order-completed { |
| | | background: #5FB878 !important; |
| | | } |
| | | </style> |
| | | </head> |
| | | <body> |
| | |
| | | <input class="layui-input" type="text" name="batch" placeholder="批号" autocomplete="off"> |
| | | </div> |
| | | </div> |
| | | <div class="layui-inline"> |
| | | <div class="layui-input-inline"> |
| | | <input class="layui-input" type="text" name="brand" placeholder="生产线" autocomplete="off"> |
| | | </div> |
| | | </div> |
| | | <div class="layui-inline"> |
| | | <div class="layui-input-inline"> |
| | | <input class="layui-input" type="text" name="sku" placeholder="等级" autocomplete="off"> |
| | | <div class="layui-input-inline" style="margin-right: 100px;"> |
| | | <div id="condition" name="condition"> |
| | | |
| | | </div> |
| | | </div> |
| | | <!-- 日期范围 --> |
| | |
| | | |
| | | <script type="text/html" id="toolbar"> |
| | | <div class="layui-btn-container"> |
| | | <button class="layui-btn" id="btn-auto-select" lay-event="autoSelect">自动勾选</button> |
| | | <button class="layui-btn" id="btn-confirm" lay-event="confirm" style="">提取</button> |
| | | </div> |
| | | </script> |
| | |
| | | </div> |
| | | </script> |
| | | |
| | | <!-- 批量选择出库站弹窗模板 --> |
| | | <script type="text/html" id="staBatchSelectDialog"> |
| | | <div style="padding: 20px;"> |
| | | <form class="layui-form" id="batchSelectStaBox"> |
| | | <!-- 下拉框将通过Handlebars模板动态渲染 --> |
| | | </form> |
| | | <div style="text-align: center; margin-top: 20px;"> |
| | | <button class="layui-btn layui-btn-sm" lay-submit lay-filter="staBatchSelectConfirm">确认</button> |
| | | </div> |
| | | </div> |
| | | </script> |
| | | |
| | | <!-- 批量选择出库站下拉框模板 --> |
| | | <script type="text/html" id="batchStaSelectTpl"> |
| | | <div class="layui-form-item"> |
| | | <label class="layui-form-label">出库站</label> |
| | | <div class="layui-input-block"> |
| | | <select name="batchSta" lay-filter="batchSta" lay-search> |
| | | {{#each list}} |
| | | <option value="{{this}}">{{this}}</option> |
| | | {{/each}} |
| | | </select> |
| | | </div> |
| | | </div> |
| | | </script> |
| | | |
| | | <script type="text/html" id="tbBasicTbStaNos"> |
| | | <div class="ew-select-fixed"> |
| | | <select class="order-sta-select" lay-filter="tbBasicTbStaNos"> |
| | |
| | | </script> |
| | | |
| | | <script> |
| | | var conditionXmSelect; |
| | | function getCol() { |
| | | var cols = [ |
| | | {type: 'checkbox', merge: ['locNo']} |
| | | {type: 'checkbox'} |
| | | , {field: 'locNo', align: 'center', title: '库位号', merge: true, style: 'font-weight: bold'} |
| | | // ,{field: 'locNo$', align: 'center',title: '库位号'} |
| | | ]; |
| | |
| | | }).extend({ |
| | | notice: 'notice/notice', |
| | | }) |
| | | .use(['table', 'notice', 'laydate', 'form', 'admin', 'tableMerge'], function () { |
| | | .use(['table', 'notice', 'laydate', 'form', 'admin', 'tableMerge','xmSelect'], function () { |
| | | var table = layui.table; |
| | | var $ = layui.jquery; |
| | | var layer = layui.layer; |
| | |
| | | var admin = layui.admin; |
| | | var tableMerge = layui.tableMerge; |
| | | var notice = layui.notice; |
| | | var xmSelect = layui.xmSelect; |
| | | |
| | | $('#matnr').val(parent.matnR); |
| | | $('#anfme').val(parent.anfme); |
| | |
| | | url: baseUrl + '/stock/out/list/auth', |
| | | where: {matnr: parent.matnR[0]}, |
| | | page: true, |
| | | limits: [16, 30, 50, 100, 200, 500], |
| | | limits: [50, 100, 200, 500], |
| | | limit: 16, |
| | | even: true, |
| | | toolbar: '#toolbar', |
| | |
| | | // 初始化选中数量 |
| | | selectedTotal = 0; |
| | | updateSelectedTotal(); |
| | | |
| | | // 从后端获取数据后,默认自动勾选数据,勾选到和订单数量一致 |
| | | if (res.data.length > 0 && orderTotal > 0) { |
| | | // 延迟执行,确保表格渲染完成 |
| | | setTimeout(function() { |
| | | autoSelectItems(); |
| | | }, 100); |
| | | } |
| | | } |
| | | }); |
| | | |
| | |
| | | var data = obj.data; |
| | | var checked = obj.checked; |
| | | var type = obj.type; |
| | | |
| | | console.log("data"+data.batch) |
| | | if (type === 'one') { |
| | | // 单个选择 |
| | | if (checked) { |
| | |
| | | // 监听头工具栏事件 |
| | | table.on('toolbar(stockOut)', function (obj) { |
| | | var checkStatus = table.checkStatus(obj.config.id); |
| | | var data = checkStatus.data; |
| | | var data = checkStatus.data; // 这里只获取实际勾选的数据 |
| | | switch (obj.event) { |
| | | case 'autoSelect': |
| | | // 自动勾选功能 |
| | | autoSelectItems(); |
| | | break; |
| | | case 'confirm': |
| | | // 只使用界面上实际勾选的数据,不再额外整合window.autoSelectedData |
| | | // 检查是否有数据可提取 |
| | | if (data.length === 0) { |
| | | layer.msg("请选择数据"); |
| | | return; |
| | | } |
| | | |
| | | // 检查选中的数量是否超过订单数量 |
| | | if (selectedTotal > orderTotal) { |
| | | layer.confirm('选中的数量已超过订单数量,是否继续?', { |
| | |
| | | break; |
| | | } |
| | | }); |
| | | |
| | | // 自动勾选函数 - 勾选库存明细,数量累加不超过订单数量 |
| | | function autoSelectItems() { |
| | | // 获取当前页所有数据 |
| | | var allData = table.cache.stockOut; |
| | | if (!allData || allData.length === 0) { |
| | | layer.msg("没有可勾选的数据", {icon: 2}); |
| | | return; |
| | | } |
| | | |
| | | // 如果订单数量为0,不需要勾选 |
| | | if (orderTotal <= 0) { |
| | | layer.msg("订单数量为0,无需勾选", {icon: 2}); |
| | | return; |
| | | } |
| | | |
| | | // 先取消所有已选中的项 |
| | | for (var i = 0; i < allData.length; i++) { |
| | | allData[i].LAY_CHECKED = false; |
| | | } |
| | | |
| | | // 重置选中数量 |
| | | selectedTotal = 0; |
| | | // 初始化自动选中数据 |
| | | window.autoSelectedData = []; |
| | | |
| | | // 按顺序勾选库存明细,直到累计数量达到订单数量 |
| | | var remaining = orderTotal; |
| | | var selectedCount = 0; |
| | | |
| | | // 对库位数据进行排序,优先选择相同库位的库存 |
| | | // allData.sort(function(a, b) { |
| | | // // 先按库位号排序 |
| | | // if (a.locNo !== b.locNo) { |
| | | // return a.locNo.localeCompare(b.locNo); |
| | | // } |
| | | // // 再按批次排序 |
| | | // return a.batch.localeCompare(b.batch); |
| | | // }); |
| | | |
| | | for (var i = 0; i < allData.length; i++) { |
| | | var item = allData[i]; |
| | | var itemAnfme = parseFloat(item.anfme || 0); |
| | | |
| | | if (itemAnfme <= 0) { |
| | | continue; // 跳过数量为0的记录 |
| | | } |
| | | |
| | | // 如果剩余数量大于等于当前项的数量,全部勾选 |
| | | if (remaining >= itemAnfme) { |
| | | allData[i].LAY_CHECKED = true; |
| | | selectedTotal += itemAnfme; |
| | | remaining -= itemAnfme; |
| | | selectedCount++; |
| | | window.autoSelectedData.push(item); |
| | | } |
| | | // 否则只勾选剩余部分(实际操作中,整个记录都会被勾选,但会在提交时处理数量) |
| | | else if (remaining > 0) { |
| | | allData[i].LAY_CHECKED = true; |
| | | selectedTotal += itemAnfme; |
| | | // 这里不修改item.anfme,因为这是表格显示的数据 |
| | | remaining = 0; |
| | | selectedCount++; |
| | | window.autoSelectedData.push(item); |
| | | } else { |
| | | break; // 已满足订单数量,停止勾选 |
| | | } |
| | | |
| | | // 如果已经满足订单数量,停止勾选 |
| | | if (remaining <= 0) { |
| | | break; |
| | | } |
| | | } |
| | | |
| | | // 不重新加载表格,直接更新表格的勾选状态 |
| | | var checkStatus = table.checkStatus('stockOut'); |
| | | // 遍历表格行并设置勾选状态 |
| | | $('.layui-table-box tr').each(function(index, tr) { |
| | | var rowIndex = $(tr).data('index'); |
| | | if (rowIndex !== undefined && allData[rowIndex]) { |
| | | var checkbox = $(tr).find('input[type="checkbox"]'); |
| | | checkbox.prop('checked', allData[rowIndex].LAY_CHECKED); |
| | | // 同步layui的勾选状态样式 |
| | | if (allData[rowIndex].LAY_CHECKED) { |
| | | $(tr).addClass('layui-table-click'); |
| | | checkbox.next().addClass('layui-form-checked'); |
| | | } else { |
| | | $(tr).removeClass('layui-table-click'); |
| | | checkbox.next().removeClass('layui-form-checked'); |
| | | } |
| | | } |
| | | }); |
| | | // 同步全选框状态 |
| | | var headerCheckbox = $('.layui-table-header input[type="checkbox"]'); |
| | | var allChecked = allData.length > 0; |
| | | for (var i = 0; i < allData.length; i++) { |
| | | if (!allData[i].LAY_CHECKED) { |
| | | allChecked = false; |
| | | break; |
| | | } |
| | | } |
| | | headerCheckbox.prop('checked', allChecked); |
| | | if (allChecked) { |
| | | headerCheckbox.next().addClass('layui-form-checked'); |
| | | } else { |
| | | headerCheckbox.next().removeClass('layui-form-checked'); |
| | | } |
| | | |
| | | // 更新显示选中的数量 |
| | | updateSelectedTotal(); |
| | | |
| | | // 如果没有勾选足够的数据,给出提示 |
| | | if (selectedTotal < orderTotal && selectedCount > 0) { |
| | | layer.msg('已选择全部可用库存,但仍未满足订单数量!', {icon: 2, time: 3000}); |
| | | } else if (selectedCount === 0) { |
| | | layer.msg('没有可勾选的数据,请检查库存!', {icon: 2, time: 3000}); |
| | | } else { |
| | | layer.msg('自动勾选完成,已勾选 ' + selectedCount + ' 条记录!', {icon: 1, time: 2000}); |
| | | } |
| | | } |
| | | conditionXmSelect = xmSelect.render({ |
| | | el: '#condition', |
| | | style: { |
| | | width: '200px', |
| | | }, |
| | | autoRow: true, |
| | | toolbar: {show: true}, |
| | | filterable: true, |
| | | data: [ |
| | | { |
| | | name: '成品智能立库', |
| | | value: '成品智能立库' |
| | | }, |
| | | { |
| | | name: '特采智能立库', |
| | | value: '特采智能立库' |
| | | } |
| | | ] |
| | | }) |
| | | |
| | | // 搜索栏搜索事件 |
| | | form.on('submit(search)', function (data) { |
| | |
| | | } |
| | | |
| | | function pakoutPreview(id, data) { |
| | | // 确保传入的数据有效 |
| | | if (!data || data.length === 0) { |
| | | layer.msg("请选择数据"); |
| | | return; |
| | | } |
| | | |
| | | // 存储实际勾选的数据到全局变量,用于出库操作 |
| | | window.selectedDataForPakout = data; |
| | | |
| | | console.log("id=" + id) |
| | | let loadIndex = layer.load(2); |
| | | var da = { |
| | | "id": JSON.stringify(id), |
| | | "list": data |
| | | "list": data // 只使用实际勾选的数据 |
| | | } |
| | | $.ajax({ |
| | | url: baseUrl + "/out/pakout/preview/auth1", |
| | |
| | | , moveType: 1 //拖拽模式,0或者1 |
| | | , content: $('#pakoutPreviewBox').html() |
| | | , success: function (layero, index) { |
| | | res.data.forEach((item, index) => { |
| | | console.log(`项 ${index + 1}:`, item); |
| | | }); |
| | | stoPreTabIdx = table.render({ |
| | | elem: '#stoPreTab1', |
| | | data: res.data, |
| | |
| | | page: false, |
| | | limit: Number.MAX_VALUE, |
| | | cellMinWidth: 100, |
| | | // cols必须使用二维数组格式,这是layui table的标准配置 |
| | | cols: [[ |
| | | // {type: 'checkbox', merge: ['orderNo']}, |
| | | // 将复选框列放在第一列,便于用户操作和tableMerge处理 |
| | | |
| | | {field: 'orderNo', title: '单据编号', merge: true, align: 'center'}, |
| | | {field: 'title', title: '商品', merge: true, align: 'center', width: 350}, |
| | | {field: 'batch', title: '批号', align: 'center'}, |
| | |
| | | title: '货位', |
| | | align: 'center', |
| | | width: 100, |
| | | merge: ['locNo'], |
| | | templet: '#locNoTpl' |
| | | }, |
| | | { |
| | |
| | | merge: ['locNo'], |
| | | templet: '#tbBasicTbStaNos' |
| | | }, |
| | | {type: 'checkbox', merge: ['locNo']}, |
| | | {type: 'checkbox'} |
| | | ]], |
| | | done: function (res) { |
| | | tableMerge.render(this); |
| | |
| | | }); |
| | | // 批量修改出库站 |
| | | form.on('submit(batchModifySta)', function () { |
| | | let stoPreTabData = layui.table.checkStatus('stoPreTab1').data; |
| | | // 获取选中的数据,兼容合并行的情况 |
| | | let checkStatus = table.checkStatus('stoPreTab1'); |
| | | let stoPreTabData = checkStatus.data; |
| | | |
| | | // 如果checkStatus返回的数据为空,尝试从tableCache中获取 |
| | | if (stoPreTabData.length === 0) { |
| | | // 遍历tableCache,找出所有选中的行及其合并行 |
| | | let checkedLocNos = []; |
| | | // 首先找出所有被选中的行的locNo |
| | | tableCache.forEach(function(item) { |
| | | if (item.LAY_CHECKED === true) { |
| | | checkedLocNos.push(item.locNo); |
| | | } |
| | | }); |
| | | |
| | | // 去重 |
| | | checkedLocNos = [...new Set(checkedLocNos)]; |
| | | |
| | | // 根据locNo过滤出所有相关的行 |
| | | stoPreTabData = tableCache.filter(function(item) { |
| | | return checkedLocNos.includes(item.locNo); |
| | | }); |
| | | } |
| | | |
| | | if (stoPreTabData.length < 1) { |
| | | layer.msg("请至少选择一条以上合并数据", {icon: 7}); |
| | | return false; |
| | |
| | | } |
| | | } |
| | | } |
| | | |
| | | // 添加调试信息 |
| | | console.log('staBatchSelectVal:', staBatchSelectVal); |
| | | console.log('staBatchSelectVal类型:', Array.isArray(staBatchSelectVal) ? '数组' : '非数组'); |
| | | console.log('staBatchSelectVal长度:', staBatchSelectVal.length); |
| | | if (staBatchSelectVal.length === 0) { |
| | | layer.msg("出库站没有交集,无法批量修改", {icon: 2}); |
| | | return; |
| | |
| | | title: '请选择站点', |
| | | content: $('#staBatchSelectDialog').html(), |
| | | success: function (layero, ddIndex) { |
| | | // 渲染下拉框 |
| | | let template = Handlebars.compile($('#batchStaSelectTpl').html()); |
| | | $('#batchSelectStaBox').html(template({list: staBatchSelectVal})); |
| | | // 直接使用原生方式创建select元素,不依赖Handlebars模板 |
| | | let selectHtml = '<div class="layui-form-item">'; |
| | | selectHtml += '<label class="layui-form-label">出库站</label>'; |
| | | selectHtml += '<div class="layui-input-block">'; |
| | | selectHtml += '<select name="batchSta" lay-filter="batchSta" lay-search>'; |
| | | |
| | | // 手动遍历数组创建option |
| | | staBatchSelectVal.forEach(function(staNo) { |
| | | selectHtml += '<option value="' + staNo + '">' + staNo + '</option>'; |
| | | }); |
| | | |
| | | selectHtml += '</select>'; |
| | | selectHtml += '</div>'; |
| | | selectHtml += '</div>'; |
| | | |
| | | // 直接插入HTML |
| | | $(layero).find('#batchSelectStaBox').html(selectHtml); |
| | | |
| | | // 渲染表单 |
| | | layui.form.render('select'); |
| | | |
| | | // 确认 |
| | | form.on('submit(staBatchSelectConfirm)', function (obj) { |
| | | let loadIdx = layer.load(2); |
| | | let batchSta = Number(obj.field.batchSta); |
| | | // 直接从DOM中获取选中的站点值,确保能正确获取到 |
| | | let batchSta = $(layero).find('select[name="batchSta"]').val(); |
| | | console.log('批量修改的站点值:', batchSta); |
| | | let arr = []; |
| | | for (let j = 0; j < stoPreTabData.length; j++) { |
| | | |
| | | // 简化更新逻辑,直接更新所有选中的数据 |
| | | stoPreTabData.forEach(function(preItem) { |
| | | for (let i = 0; i < tableCache.length; i++) { |
| | | if (tableCache[i].orderNo === stoPreTabData[j].orderNo |
| | | && tableCache[i].matnr === stoPreTabData[j].matnr |
| | | && tableCache[i].locNo === stoPreTabData[j].locNo) { |
| | | // 只根据locNo进行匹配,因为表格中locNo是合并单元格的关键字段 |
| | | if (tableCache[i].locNo === preItem.locNo) { |
| | | tableCache[i]['staNo'] = batchSta; |
| | | arr.push(i); |
| | | console.log('更新了数据索引:', i, '站点值:', batchSta); |
| | | } |
| | | } |
| | | }); |
| | | |
| | | // 如果没有找到匹配项,尝试直接更新选中的数据 |
| | | if (arr.length === 0) { |
| | | console.log('未找到匹配项,尝试直接更新'); |
| | | // 直接遍历tableCache,更新所有LAY_CHECKED为true的项 |
| | | for (let i = 0; i < tableCache.length; i++) { |
| | | if (tableCache[i].LAY_CHECKED === true) { |
| | | tableCache[i]['staNo'] = batchSta; |
| | | arr.push(i); |
| | | console.log('直接更新了选中的数据索引:', i); |
| | | } |
| | | } |
| | | } |
| | |
| | | }); |
| | | // 弹窗不出现滚动条 |
| | | $(layero).children('.layui-layer-content').css('overflow', 'visible'); |
| | | layui.form.render('select'); |
| | | }, |
| | | }) |
| | | } |
| | |
| | | } |
| | | , yes: function (index, layero) { |
| | | //按钮【立即出库】的回调 |
| | | pakout(tableCache, index); |
| | | // 不再传递tableCache,pakout函数将使用window.selectedDataForPakout |
| | | pakout(index); |
| | | } |
| | | , btn2: function (index, layero) { |
| | | //按钮【稍后处理】的回调 |
| | | layer.close(index) |
| | | // 清理全局变量 |
| | | window.selectedDataForPakout = null; |
| | | //return false 开启该代码可禁止点击该按钮关闭 |
| | | } |
| | | }); |
| | |
| | | }) |
| | | } |
| | | |
| | | function pakout(tableCache, layerIndex) { |
| | | function pakout(layerIndex) { |
| | | // 获取存储的实际勾选数据 |
| | | var tableCache = window.selectedDataForPakout; |
| | | |
| | | // 确保传入的数据有效 |
| | | if (!tableCache || tableCache.length === 0) { |
| | | layer.msg("没有有效的数据可处理", {icon: 2}); |
| | | return; |
| | | } |
| | | |
| | | // 重置自动选中的数据,避免数据残留 |
| | | window.autoSelectedData = []; |
| | | |
| | | // let loadIndex = layer.load(2); |
| | | notice.msg('正在生成出库任务......', {icon: 4}); |
| | | $.ajax({ |
| | |
| | | } else { |
| | | layer.msg(res.msg, {icon: 2}) |
| | | } |
| | | }, |
| | | error: function () { |
| | | notice.destroy(); |
| | | layer.msg('网络错误,请稍后重试', {icon: 2}); |
| | | } |
| | | }); |
| | | |
| | | // 清理全局变量 |
| | | window.selectedDataForPakout = null; |
| | | } |
| | | |
| | | window.pakoutPreview = pakoutPreview; |
| | | // 初始化自动选中数据变量,确保页面加载时被正确初始化 |
| | | window.autoSelectedData = null; |
| | | }) |
| | | </script> |
| | | </html> |