新手小白记一次 WMS系统优化:绕过后端慢 SQL 实现秒开弹窗 + 跨 Iframe 暴力传值
0x01 背景
最近用着公司的的一个老WMS管理系统,有个业务场景是:在“库存调整单”主页点击按钮,弹出 Layer 子页面选条码,进行库存调整。
原代码逻辑:
SELECT
bs.barcode_no AS "barcodeNo",
bs.item_no AS "itemNo",
p.item_name AS "itemName",
p.item_spec AS "itemSpec",
bs.ent AS "ent",
bs.site AS "site",
bs.warehouse_no AS "warehouseNo",
bs.warehouse_no_id AS "warehouseNoId",
bs.lot_no AS "lotNo",
bs.product_code AS "productCode",
bs.stock_code AS "stockCode",
p.unit_no AS "unitNo",
bs.cur_stor_num AS "curStorNum",
IFNULL(p.reference_unit, ' ') AS "referenceUnitNo",
p.is_to_erp AS "isToErp"
FROM
srm_bar_store_change_head ch,
srm_barcode_store bs
INNER JOIN srm_barcode_no_prop p ON p.item_no = bs.item_no
WHERE
ch.ent = bs.ent
AND ch.site = bs.site
AND ch.doc_no = '调整单单号'
AND bs.warehouse_no in
(
'101'
-
, '901'
)
ORDER BY bs.update_date DESC limit 30
系统的弹窗逻辑,在初始化(Init)时会执行一段非常臃肿的 SQL(如上所示)而且这个表的数据比较多大概两百多万条,
但是调整单的单号也就是doc_no,严重怀疑当时开发建表的时候咋想的,并不在srm_barcode_detail表中。
母页面把单据号(docNo)直接拼在 URL 后面传给子页面。后端一拿到单号就触发全表关联查询和权限校验。
点击条码编号后,由于慢 SQL 拖累,弹窗白屏 40 秒才能出来,
0x02 踩坑经历(错误示范)
由于楼主是个水货,所以决定对前端尝试看看能不能有什么突破。
- 直接删参数: 既然 URL 带了调整单单号就慢,我不带不就秒开了吗?结果页面是秒开了,但子页面里的查询按钮废了——因为没单号,后端直接拦截了请求。
- 闭包地狱: 想在控制台临时改个变量传过去,结果发现变量全被裹在
$(function(){...}) 里,外面根本访问不到,全是 Uncaught ReferenceError。
- 低级错误: 甚至想过在 HTML 属性里写逻辑:
<input value="$('#docNo').val(parent.xxx)"/>。后来猛然醒悟:value 只是个存字符串的盒子,它没脑子,不会执行代码。
0x03 最终方案:全局挂载 + 异步抓取
既然 SQL 改不动,咱们就换个思路:先骗过后端加载页面(不带单号实现秒开),等页面加载完,再由前端补齐参数。
1. 母页面:强行提升变量作用域
别管什么闭包了,直接把变量挂在浏览器的全局 window 对象上。
`javascript
<script type="text/javascript">
window.my_docNo = "${barStoreChangeBody.docNo}";
$(function () {
$("#barcodeNo").click(function () {
layer.open({
content: '${ctx}/wms/barcode/iframe?docNo=&site=' + window.my_site,
area: ['1050px', '400px'],
// ... 其他配置
});
});
});
</script>
-
子页面(Iframe):反向“偷”值
子页面秒开之后,在点击查询按钮的一瞬间,回头去 parent 那里抓取单号。
JavaScript
// 子页面 iframeBarcodeNoN.jsp
$(function () {
$("#btnSearch").click(function() {
// parent 才是真神,直接去母页面的全局 window 里拿
var realDocNo = parent.window.my_docNo;
if (realDocNo) {
// 拿到值后,动态填入子页面的隐藏域
$("#docNo").val(realDocNo);
// 此时再提交,后端校验就能通过了
$("#searchForm").submit();
} else {
top.$.jBox.tip("未抓取到母页面单号,查询中止", 'error');
}
});
});
0x04 经验小结
思路转变: 遇到慢 SQL 导致的加载卡顿,可以尝试“空 URL 加载页面 + 前端异步补参数”的方案。
跨页面传值: 遇到闭包变量拿不到的情况,window.xxx 挂载 + parent.window.xxx 调用是 Iframe 通讯的暴力美学,简单有效。
防坑指南: 再次提醒,HTML 标签的 value 属性不具备代码执行能力,JS 逻辑必须老老实实写在script里。
折腾了一晚上,终于把响应速度从 40 秒优化到了 1 秒内。这个老系统的坑是真的多,希望这个思路能帮到正在改老系统的老哥们
第一次写类似的文章,觉得有用点个赞,求个加分!