优化分类树加载逻辑,新增批量查询子节点接口以减少数据库往返,提升性能。重构相关服务和控制器,确保系统的可维护性和扩展性。
This commit is contained in:
@@ -416,13 +416,7 @@ public class SysCategoryController {
|
||||
* 递归求子节点 同步加载用到
|
||||
*/
|
||||
private void loadAllCategoryChildren(List<TreeSelectModel> ls) {
|
||||
for (TreeSelectModel tsm : ls) {
|
||||
List<TreeSelectModel> temp = this.sysCategoryService.queryListByPid(tsm.getKey());
|
||||
if(temp!=null && temp.size()>0) {
|
||||
tsm.setChildren(temp);
|
||||
loadAllCategoryChildren(temp);
|
||||
}
|
||||
}
|
||||
this.sysCategoryService.fillCategoryChildrenBatch(ls);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -28,6 +28,11 @@ public interface SysCategoryMapper extends BaseMapper<SysCategory> {
|
||||
*/
|
||||
public List<TreeSelectModel> queryListByPid(@Param("pid") String pid,@Param("query") Map<String, String> query);
|
||||
|
||||
/**
|
||||
* 批量按父 id 查询子节点(树同步加载按层拉取,避免 N+1)
|
||||
*/
|
||||
List<TreeSelectModel> queryListByPidIn(@Param("pids") List<String> pids, @Param("query") Map<String, String> query);
|
||||
|
||||
/**
|
||||
* 通过code查询分类字典表
|
||||
* @param code
|
||||
|
||||
@@ -33,5 +33,36 @@
|
||||
</if>
|
||||
</select>
|
||||
|
||||
<select id="queryListByPidIn" resultType="org.jeecg.modules.system.model.TreeSelectModel">
|
||||
select code,
|
||||
name as "title",
|
||||
id as "key",
|
||||
(case when has_child = '1' then 0 else 1 end) as isLeaf,
|
||||
pid as parentId
|
||||
from sys_category
|
||||
where pid in
|
||||
<foreach collection="pids" item="item" open="(" separator="," close=")">
|
||||
#{item}
|
||||
</foreach>
|
||||
<if test="query!= null">
|
||||
<if test="query.code !=null and query.code != ''">
|
||||
and code = #{query.code}
|
||||
</if>
|
||||
<if test="query.name !=null and query.name != ''">
|
||||
and name = #{query.name}
|
||||
</if>
|
||||
<if test="query.id !=null and query.id != ''">
|
||||
and id = #{query.id}
|
||||
</if>
|
||||
<if test="query.createBy !=null and query.createBy != ''">
|
||||
and create_by = #{query.createBy}
|
||||
</if>
|
||||
<if test="query.sysOrgCode !=null and query.sysOrgCode != ''">
|
||||
and sys_org_code = #{query.sysOrgCode}
|
||||
</if>
|
||||
</if>
|
||||
order by code
|
||||
</select>
|
||||
|
||||
|
||||
</mapper>
|
||||
|
||||
@@ -98,4 +98,11 @@ public interface ISysCategoryService extends IService<SysCategory> {
|
||||
*/
|
||||
List<String> loadDictItemByNames(String names, boolean delNotExist);
|
||||
|
||||
/**
|
||||
* 按层批量补全子节点(替代逐节点递归 queryListByPid,显著减少数据库往返)
|
||||
*
|
||||
* @param nodes 首层节点列表(通常来自 {@link #queryListByCode})
|
||||
*/
|
||||
void fillCategoryChildrenBatch(List<TreeSelectModel> nodes);
|
||||
|
||||
}
|
||||
|
||||
@@ -126,6 +126,37 @@ public class SysCategoryServiceImpl extends ServiceImpl<SysCategoryMapper, SysCa
|
||||
return baseMapper.queryListByPid(pid,condition);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fillCategoryChildrenBatch(List<TreeSelectModel> nodes) {
|
||||
if (nodes == null || nodes.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
List<TreeSelectModel> frontier = new ArrayList<>(nodes);
|
||||
while (!frontier.isEmpty()) {
|
||||
List<String> pids = frontier.stream().map(TreeSelectModel::getKey).filter(Objects::nonNull).collect(Collectors.toList());
|
||||
if (pids.isEmpty()) {
|
||||
break;
|
||||
}
|
||||
List<TreeSelectModel> allChildren = baseMapper.queryListByPidIn(pids, null);
|
||||
if (allChildren == null || allChildren.isEmpty()) {
|
||||
break;
|
||||
}
|
||||
Map<String, List<TreeSelectModel>> byParent = allChildren.stream().collect(Collectors.groupingBy(TreeSelectModel::getParentId));
|
||||
List<TreeSelectModel> nextFrontier = new ArrayList<>();
|
||||
for (TreeSelectModel parent : frontier) {
|
||||
List<TreeSelectModel> 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);
|
||||
|
||||
@@ -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 已存在。');
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user