From ffc390f3de20cfe2d40896377d6e2b48a448bcf9 Mon Sep 17 00:00:00 2001 From: geht <2947093423@qq.com> Date: Fri, 15 May 2026 09:58:30 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96=E5=88=86=E7=B1=BB=E6=A0=91?= =?UTF-8?q?=E5=8A=A0=E8=BD=BD=E9=80=BB=E8=BE=91=EF=BC=8C=E6=96=B0=E5=A2=9E?= =?UTF-8?q?=E6=89=B9=E9=87=8F=E6=9F=A5=E8=AF=A2=E5=AD=90=E8=8A=82=E7=82=B9?= =?UTF-8?q?=E6=8E=A5=E5=8F=A3=E4=BB=A5=E5=87=8F=E5=B0=91=E6=95=B0=E6=8D=AE?= =?UTF-8?q?=E5=BA=93=E5=BE=80=E8=BF=94=EF=BC=8C=E6=8F=90=E5=8D=87=E6=80=A7?= =?UTF-8?q?=E8=83=BD=E3=80=82=E9=87=8D=E6=9E=84=E7=9B=B8=E5=85=B3=E6=9C=8D?= =?UTF-8?q?=E5=8A=A1=E5=92=8C=E6=8E=A7=E5=88=B6=E5=99=A8=EF=BC=8C=E7=A1=AE?= =?UTF-8?q?=E4=BF=9D=E7=B3=BB=E7=BB=9F=E7=9A=84=E5=8F=AF=E7=BB=B4=E6=8A=A4?= =?UTF-8?q?=E6=80=A7=E5=92=8C=E6=89=A9=E5=B1=95=E6=80=A7=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/SysCategoryController.java | 8 +---- .../system/mapper/SysCategoryMapper.java | 5 +++ .../system/mapper/xml/SysCategoryMapper.xml | 31 +++++++++++++++++++ .../system/service/ISysCategoryService.java | 7 +++++ .../service/impl/SysCategoryServiceImpl.java | 31 +++++++++++++++++++ .../mes/material/MesMixerMaterialList.vue | 5 +-- .../xslmes/mesXslUnit/MesXslUnitList.vue | 6 ++-- .../mesXslWarehouse/MesXslWarehouseList.vue | 5 +-- 8 files changed, 85 insertions(+), 13 deletions(-) diff --git a/jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/controller/SysCategoryController.java b/jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/controller/SysCategoryController.java index c93e5b2..5961764 100644 --- a/jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/controller/SysCategoryController.java +++ b/jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/controller/SysCategoryController.java @@ -416,13 +416,7 @@ public class SysCategoryController { * 递归求子节点 同步加载用到 */ private void loadAllCategoryChildren(List ls) { - for (TreeSelectModel tsm : ls) { - List temp = this.sysCategoryService.queryListByPid(tsm.getKey()); - if(temp!=null && temp.size()>0) { - tsm.setChildren(temp); - loadAllCategoryChildren(temp); - } - } + this.sysCategoryService.fillCategoryChildrenBatch(ls); } /** diff --git a/jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/mapper/SysCategoryMapper.java b/jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/mapper/SysCategoryMapper.java index 208ba7e..c676b39 100644 --- a/jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/mapper/SysCategoryMapper.java +++ b/jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/mapper/SysCategoryMapper.java @@ -28,6 +28,11 @@ public interface SysCategoryMapper extends BaseMapper { */ public List queryListByPid(@Param("pid") String pid,@Param("query") Map query); + /** + * 批量按父 id 查询子节点(树同步加载按层拉取,避免 N+1) + */ + List queryListByPidIn(@Param("pids") List pids, @Param("query") Map query); + /** * 通过code查询分类字典表 * @param code diff --git a/jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/mapper/xml/SysCategoryMapper.xml b/jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/mapper/xml/SysCategoryMapper.xml index 741670c..6c32069 100644 --- a/jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/mapper/xml/SysCategoryMapper.xml +++ b/jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/mapper/xml/SysCategoryMapper.xml @@ -33,5 +33,36 @@ + + diff --git a/jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/service/ISysCategoryService.java b/jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/service/ISysCategoryService.java index 607d2c5..652f672 100644 --- a/jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/service/ISysCategoryService.java +++ b/jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/service/ISysCategoryService.java @@ -98,4 +98,11 @@ public interface ISysCategoryService extends IService { */ List loadDictItemByNames(String names, boolean delNotExist); + /** + * 按层批量补全子节点(替代逐节点递归 queryListByPid,显著减少数据库往返) + * + * @param nodes 首层节点列表(通常来自 {@link #queryListByCode}) + */ + void fillCategoryChildrenBatch(List nodes); + } diff --git a/jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/service/impl/SysCategoryServiceImpl.java b/jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/service/impl/SysCategoryServiceImpl.java index cff09f8..5410273 100644 --- a/jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/service/impl/SysCategoryServiceImpl.java +++ b/jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/service/impl/SysCategoryServiceImpl.java @@ -126,6 +126,37 @@ public class SysCategoryServiceImpl extends ServiceImpl nodes) { + if (nodes == null || nodes.isEmpty()) { + return; + } + List frontier = new ArrayList<>(nodes); + while (!frontier.isEmpty()) { + List pids = frontier.stream().map(TreeSelectModel::getKey).filter(Objects::nonNull).collect(Collectors.toList()); + if (pids.isEmpty()) { + break; + } + List allChildren = baseMapper.queryListByPidIn(pids, null); + if (allChildren == null || allChildren.isEmpty()) { + break; + } + Map> byParent = allChildren.stream().collect(Collectors.groupingBy(TreeSelectModel::getParentId)); + List nextFrontier = new ArrayList<>(); + for (TreeSelectModel parent : frontier) { + List ch = byParent.get(parent.getKey()); + if (ch != null && !ch.isEmpty()) { + parent.setChildren(ch); + nextFrontier.addAll(ch); + } + } + if (nextFrontier.isEmpty()) { + break; + } + frontier = nextFrontier; + } + } + @Override public String queryIdByCode(String code) { return baseMapper.queryIdByCode(code); diff --git a/jeecgboot-vue3/src/views/mes/material/MesMixerMaterialList.vue b/jeecgboot-vue3/src/views/mes/material/MesMixerMaterialList.vue index 26edd29..06bb3b0 100644 --- a/jeecgboot-vue3/src/views/mes/material/MesMixerMaterialList.vue +++ b/jeecgboot-vue3/src/views/mes/material/MesMixerMaterialList.vue @@ -114,6 +114,8 @@ const { tableContext, onExportXls, onImportXls } = useListPage({ title: '密炼物料信息', api: list, columns, + // 避免:表格默认 immediate 请求一次 + onMounted 末尾 reload 再请求一次(进入页列表闪两次) + immediate: false, canResize: true, formConfig: { labelWidth: 120, schemas: searchFormSchema, autoSubmitOnEnter: true, showAdvancedButton: true }, actionColumn: { width: 120 }, @@ -227,9 +229,8 @@ function findNodeByKey(nodes: Recordable[], key: string): Recordable | null { async function loadCategoryTree() { treeLoading.value = true; try { - const root = await fetchMaterialCategoryRoot(); + const [root, res] = await Promise.all([fetchMaterialCategoryRoot(), loadCategoryTreeRoot({ async: false, pcode: 'XSLMES_MATERIAL' })]); materialCategoryRootId.value = root?.id != null ? String(root.id) : ''; - const res = await loadCategoryTreeRoot({ async: false, pcode: 'XSLMES_MATERIAL' }); rawCategoryTree.value = Array.isArray(res) ? res : []; if (!materialCategoryRootId.value || !rawCategoryTree.value.length) { createMessage.warning('未加载到物料分类树,请确认分类字典根编码 XSLMES_MATERIAL 已存在。'); diff --git a/jeecgboot-vue3/src/views/xslmes/mesXslUnit/MesXslUnitList.vue b/jeecgboot-vue3/src/views/xslmes/mesXslUnit/MesXslUnitList.vue index 47fcfff..a37b367 100644 --- a/jeecgboot-vue3/src/views/xslmes/mesXslUnit/MesXslUnitList.vue +++ b/jeecgboot-vue3/src/views/xslmes/mesXslUnit/MesXslUnitList.vue @@ -271,9 +271,9 @@ async function loadCategoryTree() { treeLoading.value = true; try { - const root = await fetchUnitCategoryRoot(); + // 根节点查询与整棵树接口并行,减少串行等待;后端已改为按层批量查子节点,降低 DB 往返 + const [root, res] = await Promise.all([fetchUnitCategoryRoot(), loadUnitCategoryTreeRoot({ async: false, pcode: 'XSLMES_UNIT' })]); unitCategoryRootId.value = root?.id != null ? String(root.id) : ''; - const res = await loadUnitCategoryTreeRoot({ async: false, pcode: 'XSLMES_UNIT' }); rawUnitCategoryTree.value = Array.isArray(res) ? res : []; if (!unitCategoryRootId.value || !rawUnitCategoryTree.value.length) { createMessage.warning('未加载到单位分类树,请确认已执行库脚本且分类字典根编码为 XSLMES_UNIT。'); @@ -295,6 +295,8 @@ title: '单位管理', api: list, columns, + // 避免:表格默认 immediate 请求一次 + onMounted 末尾 reload 再请求一次(进入页列表闪两次) + immediate: false, canResize: true, formConfig: { schemas: searchFormSchema, diff --git a/jeecgboot-vue3/src/views/xslmes/mesXslWarehouse/MesXslWarehouseList.vue b/jeecgboot-vue3/src/views/xslmes/mesXslWarehouse/MesXslWarehouseList.vue index ab7e221..43db4f3 100644 --- a/jeecgboot-vue3/src/views/xslmes/mesXslWarehouse/MesXslWarehouseList.vue +++ b/jeecgboot-vue3/src/views/xslmes/mesXslWarehouse/MesXslWarehouseList.vue @@ -294,9 +294,8 @@ async function loadCategoryTree() { treeLoading.value = true; try { - const root = await fetchWarehouseCategoryRoot(); + const [root, res] = await Promise.all([fetchWarehouseCategoryRoot(), loadCategoryTreeRoot({ async: false, pcode: 'XSLMES_WH' })]); warehouseCategoryRootId.value = root?.id != null ? String(root.id) : ''; - const res = await loadCategoryTreeRoot({ async: false, pcode: 'XSLMES_WH' }); rawWarehouseCategoryTree.value = Array.isArray(res) ? res : []; if (!warehouseCategoryRootId.value || !rawWarehouseCategoryTree.value.length) { createMessage.warning('未加载到仓库分类树,请确认已执行库脚本并已在「分类字典」中维护根节点 XSLMES_WH。'); @@ -385,6 +384,8 @@ title: '仓库管理', api: list, columns, + // 避免:表格默认 immediate 请求一次 + onMounted 末尾 reload 再请求一次(进入页列表闪两次) + immediate: false, canResize: true, formConfig: { schemas: searchFormSchema,