From 32d9e60fe1562b5784d6f1b9cd5efa33ff0fe879 Mon Sep 17 00:00:00 2001 From: xuyuxiang Date: Fri, 27 Feb 2026 16:56:51 +0800 Subject: [PATCH] =?UTF-8?q?=E3=80=90=E6=9B=B4=E6=96=B0=E3=80=91=E6=9C=BA?= =?UTF-8?q?=E6=9E=84=E5=A4=A7=E6=95=B0=E6=8D=AE=E4=BC=98=E5=8C=96=EF=BC=88?= =?UTF-8?q?=E5=BE=85=E5=AE=8C=E5=96=84=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- snowy-admin-web/src/views/biz/org/form.vue | 5 +++ snowy-admin-web/src/views/biz/org/index.vue | 1 + .../src/views/biz/position/index.vue | 1 + snowy-admin-web/src/views/biz/user/form.vue | 15 +++---- snowy-admin-web/src/views/biz/user/index.vue | 1 + snowy-admin-web/src/views/sys/org/form.vue | 5 +++ snowy-admin-web/src/views/sys/org/index.vue | 1 + .../src/views/sys/position/index.vue | 1 + snowy-admin-web/src/views/sys/role/index.vue | 1 + snowy-admin-web/src/views/sys/user/form.vue | 13 +++--- snowy-admin-web/src/views/sys/user/index.vue | 1 + .../core/listener/BizDataChangeListener.java | 6 +++ .../org/service/impl/BizOrgServiceImpl.java | 41 +++++++++---------- .../core/listener/SysDataChangeListener.java | 34 ++++++++++++--- .../org/service/impl/SysOrgServiceImpl.java | 19 +++------ 15 files changed, 88 insertions(+), 57 deletions(-) diff --git a/snowy-admin-web/src/views/biz/org/form.vue b/snowy-admin-web/src/views/biz/org/form.vue index 93b4297b..e2dbc08f 100644 --- a/snowy-admin-web/src/views/biz/org/form.vue +++ b/snowy-admin-web/src/views/biz/org/form.vue @@ -192,6 +192,11 @@ } // 传递设计器需要的API const selectorApiFunction = { + orgTreeApi: (param) => { + return bizOrgApi.orgTreeLazySelector(param).then((data) => { + return Promise.resolve(data) + }) + }, orgTreeLazyApi: (param) => { return bizOrgApi.orgTreeLazySelector(param).then((data) => { return Promise.resolve(data) diff --git a/snowy-admin-web/src/views/biz/org/index.vue b/snowy-admin-web/src/views/biz/org/index.vue index dd1ac278..992897ca 100644 --- a/snowy-admin-web/src/views/biz/org/index.vue +++ b/snowy-admin-web/src/views/biz/org/index.vue @@ -15,6 +15,7 @@ @@ -131,12 +128,12 @@ :dropdown-style="{ maxHeight: '400px', overflow: 'auto' }" placeholder="请选择机构" allow-clear - tree-default-expand-all + tree-line :tree-data="treeData" :tree-default-expanded-keys="treeDefaultExpandedKeys" - :field-names="{ children: 'children', label: 'name', value: 'id' }" + :field-names="treeFieldNames" :load-data="onLoadData" - @select="childOrgSelect(positionInfo, 0, index)" + @change="childOrgSelect(positionInfo, 0, index)" /> @@ -320,7 +317,7 @@ const xnChildUserPageSelectRef = ref() // 表单数据 const formData = ref({}) - const treeFieldNames = { children: 'children', title: 'dictLabel', key: 'id' } + const treeFieldNames = { children: 'children', label: 'name', key: 'id', value: 'id' } // 在树中递归查找节点 const findNodeInTree = (nodes, id) => { diff --git a/snowy-admin-web/src/views/biz/user/index.vue b/snowy-admin-web/src/views/biz/user/index.vue index a81a12e5..1eb93fd2 100644 --- a/snowy-admin-web/src/views/biz/user/index.vue +++ b/snowy-admin-web/src/views/biz/user/index.vue @@ -15,6 +15,7 @@ { + return orgApi.orgOrgTreeLazySelector(param).then((data) => { + return Promise.resolve(data) + }) + }, orgTreeLazyApi: (param) => { return orgApi.orgOrgTreeLazySelector(param).then((data) => { return Promise.resolve(data) diff --git a/snowy-admin-web/src/views/sys/org/index.vue b/snowy-admin-web/src/views/sys/org/index.vue index 9b01f983..c7eae3d6 100644 --- a/snowy-admin-web/src/views/sys/org/index.vue +++ b/snowy-admin-web/src/views/sys/org/index.vue @@ -15,6 +15,7 @@ @@ -131,12 +128,12 @@ :dropdown-style="{ maxHeight: '400px', overflow: 'auto' }" placeholder="请选择组织" allow-clear - tree-default-expand-all + tree-line :tree-data="treeData" :tree-default-expanded-keys="treeDefaultExpandedKeys" :field-names="treeFieldNames" :load-data="onLoadData" - @select="childOrgSelect(positionInfo, 0, index)" + @change="childOrgSelect(positionInfo, 0, index)" /> @@ -320,7 +317,7 @@ const xnChildUserPageSelectRef = ref() // 表单数据 const formData = ref({}) - const treeFieldNames = { children: 'children', title: 'name', key: 'id' } + const treeFieldNames = { children: 'children', label: 'name', key: 'id', value: 'id' } // 在树中递归查找节点 const findNodeInTree = (nodes, id) => { diff --git a/snowy-admin-web/src/views/sys/user/index.vue b/snowy-admin-web/src/views/sys/user/index.vue index bea18174..5bbbafad 100644 --- a/snowy-admin-web/src/views/sys/user/index.vue +++ b/snowy-admin-web/src/views/sys/user/index.vue @@ -15,6 +15,7 @@ impleme private static final String ORG_ALL_LIST_CACHE_KEY = "biz-org:all-list"; + /** 本地内存缓存,避免每次从Redis取出后JSON反序列化大量记录(与SysOrg对齐) */ + private volatile List localOrgListCache; + /** 机构数据版本号缓存key,机构增删改时递增,用于使 visibleOrgIds 缓存自动失效 */ private static final String ORG_CACHE_VERSION_KEY = "biz-org:cache-version"; @@ -246,11 +249,8 @@ public class BizOrgServiceImpl extends ServiceImpl impleme this.save(bizOrg); // 插入扩展信息 bizOrgExtService.createExtInfo(bizOrg.getId(), sourceFromType); - // 发布增加事件 + // 发布增加事件(BizDataChangeListener 和 SysDataChangeListener 监听后自动清缓存) CommonDataChangeEventCenter.doAddWithData(BizDataTypeEnum.ORG.getValue(), JSONUtil.createArray().put(bizOrg)); - // 清除缓存 - this.invalidateOrgCaches(); - sysOrgApi.clearOrgCache(); } @Transactional(rollbackFor = Exception.class) @@ -285,11 +285,8 @@ public class BizOrgServiceImpl extends ServiceImpl impleme } // 更新机构 this.updateById(bizOrg); - // 发布更新事件 + // 发布更新事件(BizDataChangeListener 和 SysDataChangeListener 监听后自动清缓存) CommonDataChangeEventCenter.doUpdateWithData(BizDataTypeEnum.ORG.getValue(), JSONUtil.createArray().put(bizOrg)); - // 清除缓存 - this.invalidateOrgCaches(); - sysOrgApi.clearOrgCache(); } @Transactional(rollbackFor = Exception.class) @@ -342,11 +339,8 @@ public class BizOrgServiceImpl extends ServiceImpl impleme // 执行删除 this.removeByIds(toDeleteOrgIdList); - // 发布删除事件 + // 发布删除事件(BizDataChangeListener 和 SysDataChangeListener 监听后自动清缓存) CommonDataChangeEventCenter.doDeleteWithDataIdList(BizDataTypeEnum.ORG.getValue(), toDeleteOrgIdList); - // 清除缓存 - this.invalidateOrgCaches(); - sysOrgApi.clearOrgCache(); } } @@ -366,12 +360,22 @@ public class BizOrgServiceImpl extends ServiceImpl impleme @Override public List getAllOrgList() { + // 优先从本地内存缓存获取,避免每次JSON反序列化 + List localCache = localOrgListCache; + if (localCache != null) { + return localCache; + } + // 其次从Redis缓存获取 Object cached = commonCacheOperator.get(ORG_ALL_LIST_CACHE_KEY); if (cached != null) { - return JSONUtil.toList(JSONUtil.parseArray(cached), BizOrg.class); + List list = JSONUtil.toList(JSONUtil.parseArray(cached), BizOrg.class); + localOrgListCache = list; + return list; } + // 最后从数据库查询 List list = this.list(new LambdaQueryWrapper().orderByAsc(BizOrg::getSortCode)); commonCacheOperator.put(ORG_ALL_LIST_CACHE_KEY, list); + localOrgListCache = list; return list; } @@ -380,6 +384,7 @@ public class BizOrgServiceImpl extends ServiceImpl impleme * 机构增删改时调用,visibleOrgIds 缓存通过版本号自动失效,旧条目由 TTL 自动清理 */ private void invalidateOrgCaches() { + localOrgListCache = null; commonCacheOperator.remove(ORG_ALL_LIST_CACHE_KEY); commonCacheOperator.put(ORG_CACHE_VERSION_KEY, String.valueOf(System.currentTimeMillis())); } @@ -483,11 +488,8 @@ public class BizOrgServiceImpl extends ServiceImpl impleme bizOrg.setCategory("0".equals(parentId)?BizOrgCategoryEnum.COMPANY.getValue():BizOrgCategoryEnum.DEPT.getValue()); bizOrg.setSortCode(99); this.save(bizOrg); - // 发布增加事件 + // 发布增加事件(BizDataChangeListener 和 SysDataChangeListener 监听后自动清缓存) CommonDataChangeEventCenter.doAddWithData(BizDataTypeEnum.ORG.getValue(), JSONUtil.createArray().put(bizOrg)); - // 清除缓存 - this.invalidateOrgCaches(); - sysOrgApi.clearOrgCache(); return bizOrg.getId(); } @@ -625,14 +627,11 @@ public class BizOrgServiceImpl extends ServiceImpl impleme this.save(copyBizOrg); // 插入扩展信息 bizOrgExtService.createExtInfo(copyBizOrg.getId(), BizOrgSourceFromTypeEnum.SYSTEM_ADD.getValue()); - // 发布增加事件 + // 发布增加事件(BizDataChangeListener 和 SysDataChangeListener 监听后自动清缓存) CommonDataChangeEventCenter.doAddWithData(BizDataTypeEnum.ORG.getValue(), JSONUtil.createArray().put(copyBizOrg)); } } }); - // 清除缓存 - this.invalidateOrgCaches(); - sysOrgApi.clearOrgCache(); } } diff --git a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/core/listener/SysDataChangeListener.java b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/core/listener/SysDataChangeListener.java index d29c57ea..7c8330d8 100644 --- a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/core/listener/SysDataChangeListener.java +++ b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/core/listener/SysDataChangeListener.java @@ -21,8 +21,10 @@ import vip.xiaonuo.auth.core.pojo.SaBaseLoginUser; import vip.xiaonuo.auth.core.util.StpLoginUserUtil; import vip.xiaonuo.common.listener.CommonDataChangeListener; import vip.xiaonuo.sys.core.enums.SysDataTypeEnum; +import vip.xiaonuo.sys.modular.org.service.SysOrgService; import vip.xiaonuo.sys.modular.org.service.SysUserDataScopeService; +import java.util.Collections; import java.util.List; /** @@ -34,18 +36,35 @@ import java.util.List; @Component public class SysDataChangeListener implements CommonDataChangeListener { + @Resource + private SysOrgService sysOrgService; + @Resource private SysUserDataScopeService sysUserDataScopeService; @Override public void doAddWithDataId(String dataType, String dataId) { - // 此处可做额外处理 + if(dataType.equals(SysDataTypeEnum.ORG.getValue())) { + List dataIdList = Collections.singletonList(dataId); + // 清除机构缓存 + sysOrgService.clearOrgCache(); + // 将新机构加入到当前登录用户的数据范围缓存 + SaBaseLoginUser saBaseLoginUser = StpLoginUserUtil.getLoginUser(); + saBaseLoginUser.getDataScopeList().forEach(dataScope -> dataScope.getDataScope().addAll(dataIdList)); + saBaseLoginUser.setDataScopeList(saBaseLoginUser.getDataScopeList()); + // 重新缓存当前登录用户信息 + StpUtil.getTokenSession().set("loginUser", saBaseLoginUser); + // 同步更新预计算表:为当前用户的所有API追加新机构 + sysUserDataScopeService.appendOrgIdsForUser(saBaseLoginUser.getId(), dataIdList); + } } @Override public void doAddWithDataIdList(String dataType, List dataIdList) { - // 如果检测到机构增加,则将该机构加入到当前登录用户的数据范围缓存 if(dataType.equals(SysDataTypeEnum.ORG.getValue())) { + // 清除机构缓存 + sysOrgService.clearOrgCache(); + // 将新机构加入到当前登录用户的数据范围缓存 SaBaseLoginUser saBaseLoginUser = StpLoginUserUtil.getLoginUser(); saBaseLoginUser.getDataScopeList().forEach(dataScope -> dataScope.getDataScope().addAll(dataIdList)); saBaseLoginUser.setDataScopeList(saBaseLoginUser.getDataScopeList()); @@ -68,12 +87,16 @@ public class SysDataChangeListener implements CommonDataChangeListener { @Override public void doUpdateWithDataId(String dataType, String dataId) { - // 此处可做额外处理 + if(dataType.equals(SysDataTypeEnum.ORG.getValue())) { + sysOrgService.clearOrgCache(); + } } @Override public void doUpdateWithDataIdList(String dataType, List dataIdList) { - // 此处可做额外处理 + if(dataType.equals(SysDataTypeEnum.ORG.getValue())) { + sysOrgService.clearOrgCache(); + } } @Override @@ -93,8 +116,9 @@ public class SysDataChangeListener implements CommonDataChangeListener { @Override public void doDeleteWithDataIdList(String dataType, List dataIdList) { - // 组织删除时,精准删除预计算表中对应的机构记录 if(dataType.equals(SysDataTypeEnum.ORG.getValue())) { + sysOrgService.clearOrgCache(); + // 精准删除预计算表中对应的机构记录 sysUserDataScopeService.deleteByOrgIds(dataIdList); } } diff --git a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/org/service/impl/SysOrgServiceImpl.java b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/org/service/impl/SysOrgServiceImpl.java index d9ef5c36..f55c3eb7 100644 --- a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/org/service/impl/SysOrgServiceImpl.java +++ b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/org/service/impl/SysOrgServiceImpl.java @@ -182,10 +182,8 @@ public class SysOrgServiceImpl extends ServiceImpl impleme this.save(sysOrg); // 插入扩展信息 sysOrgExtService.createExtInfo(sysOrg.getId(), sourceFromType); - // 发布增加事件 + // 发布增加事件(SysDataChangeListener 和 BizDataChangeListener 监听后自动清缓存) CommonDataChangeEventCenter.doAddWithData(SysDataTypeEnum.ORG.getValue(), JSONUtil.createArray().put(sysOrg)); - // 清除缓存 - clearOrgCache(); } @Transactional(rollbackFor = Exception.class) @@ -207,10 +205,8 @@ public class SysOrgServiceImpl extends ServiceImpl impleme } // 更新组织 this.updateById(sysOrg); - // 发布更新事件 + // 发布更新事件(SysDataChangeListener 和 BizDataChangeListener 监听后自动清缓存) CommonDataChangeEventCenter.doUpdateWithData(SysDataTypeEnum.ORG.getValue(), JSONUtil.createArray().put(sysOrg)); - // 清除缓存 - clearOrgCache(); } @Transactional(rollbackFor = Exception.class) @@ -254,10 +250,8 @@ public class SysOrgServiceImpl extends ServiceImpl impleme // 执行删除 this.removeByIds(toDeleteOrgIdList); - // 发布删除事件 + // 发布删除事件(SysDataChangeListener 和 BizDataChangeListener 监听后自动清缓存) CommonDataChangeEventCenter.doDeleteWithDataIdList(SysDataTypeEnum.ORG.getValue(), toDeleteOrgIdList); - // 清除缓存 - clearOrgCache(); } } @@ -302,12 +296,11 @@ public class SysOrgServiceImpl extends ServiceImpl impleme // 插入扩展信息 sysOrgExtService.createExtInfo(copySysOrg.getId(), SysOrgSourceFromTypeEnum.SYSTEM_ADD.getValue()); // 发布增加事件 + // 发布增加事件(SysDataChangeListener 和 BizDataChangeListener 监听后自动清缓存) CommonDataChangeEventCenter.doAddWithData(SysDataTypeEnum.ORG.getValue(), JSONUtil.createArray().put(copySysOrg)); } } }); - // 清除缓存 - clearOrgCache(); } } @@ -429,10 +422,8 @@ public class SysOrgServiceImpl extends ServiceImpl impleme this.save(sysOrg); // 插入扩展信息 sysOrgExtService.createExtInfo(sysOrg.getId(), SysOrgSourceFromTypeEnum.SYSTEM_ADD.getValue()); - // 发布增加事件 + // 发布增加事件(SysDataChangeListener 和 BizDataChangeListener 监听后自动清缓存) CommonDataChangeEventCenter.doAddWithData(SysDataTypeEnum.ORG.getValue(), JSONUtil.createArray().put(sysOrg)); - // 清除缓存 - clearOrgCache(); return sysOrg.getId(); }