From f4b5ba168ac4facbdfd2a722cbcee35397547d3a Mon Sep 17 00:00:00 2001 From: lijiahang Date: Mon, 4 Dec 2023 14:35:18 +0800 Subject: [PATCH] =?UTF-8?q?refactor:=20=E4=BF=AE=E6=94=B9=E7=BC=93?= =?UTF-8?q?=E5=AD=98=E5=8A=A0=E8=BD=BD=E9=80=BB=E8=BE=91.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../log/core/annotation/OperatorLog.java | 2 +- .../core/generator/CodeGenerators.java | 17 +-- .../AssetAuthorizedDataServiceController.http | 4 +- .../AssetAuthorizedDataServiceController.java | 8 +- ...erVO.java => AuthorizedHostWrapperVO.java} | 7 +- .../asset/entity/vo/HostGroupTreeVO.java | 3 - .../service/AssetAuthorizedDataService.java | 6 +- .../impl/AssetAuthorizedDataServiceImpl.java | 121 ++++++++++++------ .../src/api/asset/asset-authorized-data.ts | 11 +- orion-ops-ui/src/api/asset/host-group.ts | 2 - orion-ops-ui/src/api/meta/tag.ts | 4 +- .../host-group/host-group-tree-selector.vue | 13 +- .../asset/host-group/host-group-tree.vue | 28 ++-- .../host-identity/host-identity-selector.vue | 12 +- .../asset/host-key/host-key-selector.vue | 12 +- .../meta/tag/tag-multi-selector.vue | 25 ++-- .../system/dict-key/dict-key-selector.vue | 23 ++-- .../system/menu/grant/menu-grant-table.vue | 4 +- .../menu/selector}/menu-tree-selector.vue | 36 +++--- orion-ops-ui/src/store/modules/cache/index.ts | 68 +++++++--- orion-ops-ui/src/store/modules/cache/types.ts | 2 - orion-ops-ui/src/types/form.ts | 5 + .../components/host-group-role-grant.vue | 2 +- .../components/host-group-user-grant.vue | 2 +- .../asset/grant/components/host-list.vue | 25 +--- .../src/views/asset/host-identity/index.vue | 28 +--- .../components/config/host-config-drawer.vue | 24 ---- .../components/group/host-transfer.vue | 38 ++---- .../host-list/components/host-card-list.vue | 1 - .../host-list/components/host-form-modal.vue | 1 - .../asset/host-list/components/host-table.vue | 1 - .../src/views/asset/host-list/index.vue | 25 +--- .../components/dict-value-form-modal.vue | 5 +- .../components/dict-value-table.vue | 1 + .../src/views/system/dict-value/index.vue | 24 +--- .../menu/components/menu-form-modal.vue | 5 +- .../system/menu/components/menu-table.vue | 1 - .../role/components/role-menu-grant-modal.vue | 11 +- .../views/user/role/types/table.columns.ts | 3 +- 39 files changed, 278 insertions(+), 332 deletions(-) rename orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/entity/vo/{AuthorizedHostGroupWrapperVO.java => AuthorizedHostWrapperVO.java} (77%) rename orion-ops-ui/src/{views/system/menu/components => components/system/menu/selector}/menu-tree-selector.vue (72%) diff --git a/orion-ops-framework/orion-ops-spring-boot-starter-biz-operator-log/src/main/java/com/orion/ops/framework/biz/operator/log/core/annotation/OperatorLog.java b/orion-ops-framework/orion-ops-spring-boot-starter-biz-operator-log/src/main/java/com/orion/ops/framework/biz/operator/log/core/annotation/OperatorLog.java index feea2bbe..0f463a45 100644 --- a/orion-ops-framework/orion-ops-spring-boot-starter-biz-operator-log/src/main/java/com/orion/ops/framework/biz/operator/log/core/annotation/OperatorLog.java +++ b/orion-ops-framework/orion-ops-spring-boot-starter-biz-operator-log/src/main/java/com/orion/ops/framework/biz/operator/log/core/annotation/OperatorLog.java @@ -30,7 +30,7 @@ public @interface OperatorLog { * - {@link org.springframework.web.bind.annotation.PathVariable} *

* 使用 @IgnoreParameter 可以忽略参数记录 {@link IgnoreParameter} - * 如果只需要忽略某个字段可以使用 @Desensitize(toEmpty = true) 标注 + * 如果只需要忽略某个字段可以使用 {@code @Desensitize(toEmpty = true)} 标注 */ boolean parameter() default true; diff --git a/orion-ops-framework/orion-ops-spring-boot-starter-mybatis/src/main/java/com/orion/ops/framework/mybatis/core/generator/CodeGenerators.java b/orion-ops-framework/orion-ops-spring-boot-starter-mybatis/src/main/java/com/orion/ops/framework/mybatis/core/generator/CodeGenerators.java index 9487af06..90d58988 100644 --- a/orion-ops-framework/orion-ops-spring-boot-starter-mybatis/src/main/java/com/orion/ops/framework/mybatis/core/generator/CodeGenerators.java +++ b/orion-ops-framework/orion-ops-spring-boot-starter-mybatis/src/main/java/com/orion/ops/framework/mybatis/core/generator/CodeGenerators.java @@ -45,23 +45,16 @@ public class CodeGenerators { // .color("blue", "gray", "red", "green", "white") // .valueUseFields() // .build(), - Template.create("code_snippet", "代码片段", "snippet") + Template.create("command_template", "命令模板", "command") .disableUnitTest() - .cache("code:snippet:{}", "代码片段") + .cache("command:template:list", "命令模板列表") .expire(1, TimeUnit.DAYS) .vue("asset", "snippet") - .enableCardView() .enableDrawerForm() - .dict("codeSnippetType", "type") - .comment("代码片段类型") - .fields("COMMAND", "TEMPLATE") - .labels("命令", "模板") - .extra("icon", "icon-code-block", "icon-code") - .valueUseFields() - .dict("codeSnippetRender", "prepare_render") + .dict("commandTemplateRender", "prepare_render") .comment("是否使用脚本渲染") - .fields("UN_RENDER", "RENDER") - .labels("不渲染", "渲染") + .fields("UNUSED", "USED") + .labels("不使用", "使用") .values(0, 1) .build(), }; diff --git a/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/controller/AssetAuthorizedDataServiceController.http b/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/controller/AssetAuthorizedDataServiceController.http index a5661043..577956c2 100644 --- a/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/controller/AssetAuthorizedDataServiceController.http +++ b/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/controller/AssetAuthorizedDataServiceController.http @@ -1,5 +1,5 @@ -### 查询当前用户已授权的主机分组及主机 -GET {{baseUrl}}/asset/authorized-data/current-host-group +### 查询当前用户已授权的主机 +GET {{baseUrl}}/asset/authorized-data/current-host Authorization: {{token}} ### 查询当前用户已授权的主机秘钥 diff --git a/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/controller/AssetAuthorizedDataServiceController.java b/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/controller/AssetAuthorizedDataServiceController.java index 635ba537..ee6c3f56 100644 --- a/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/controller/AssetAuthorizedDataServiceController.java +++ b/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/controller/AssetAuthorizedDataServiceController.java @@ -4,7 +4,7 @@ import com.orion.ops.framework.log.core.annotation.IgnoreLog; import com.orion.ops.framework.log.core.enums.IgnoreLogMode; import com.orion.ops.framework.security.core.utils.SecurityUtils; import com.orion.ops.framework.web.core.annotation.RestWrapper; -import com.orion.ops.module.asset.entity.vo.AuthorizedHostGroupWrapperVO; +import com.orion.ops.module.asset.entity.vo.AuthorizedHostWrapperVO; import com.orion.ops.module.asset.entity.vo.HostIdentityVO; import com.orion.ops.module.asset.entity.vo.HostKeyVO; import com.orion.ops.module.asset.service.AssetAuthorizedDataService; @@ -38,9 +38,9 @@ public class AssetAuthorizedDataServiceController { private AssetAuthorizedDataService assetAuthorizedDataService; @IgnoreLog(IgnoreLogMode.RET) - @GetMapping("/current-host-group") - @Operation(summary = "查询当前用户已授权的主机分组及主机") - public AuthorizedHostGroupWrapperVO getCurrentAuthorizedHostGroup() { + @GetMapping("/current-host") + @Operation(summary = "查询当前用户已授权的主机") + public AuthorizedHostWrapperVO getCurrentAuthorizedHostGroup() { return assetAuthorizedDataService.getUserAuthorizedHostGroup(SecurityUtils.getLoginUserId()); } diff --git a/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/entity/vo/AuthorizedHostGroupWrapperVO.java b/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/entity/vo/AuthorizedHostWrapperVO.java similarity index 77% rename from orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/entity/vo/AuthorizedHostGroupWrapperVO.java rename to orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/entity/vo/AuthorizedHostWrapperVO.java index 125da1e9..0162f8fb 100644 --- a/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/entity/vo/AuthorizedHostGroupWrapperVO.java +++ b/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/entity/vo/AuthorizedHostWrapperVO.java @@ -7,6 +7,8 @@ import lombok.Data; import lombok.NoArgsConstructor; import java.util.List; +import java.util.Map; +import java.util.Set; /** * 已授权的主机分组 视图响应对象 @@ -20,7 +22,7 @@ import java.util.List; @NoArgsConstructor @AllArgsConstructor @Schema(name = "AuthorizedHostGroupWrapperVO", description = "已授权的主机分组 视图响应对象") -public class AuthorizedHostGroupWrapperVO { +public class AuthorizedHostWrapperVO { @Schema(description = "授权的主机分组") private List groupTree; @@ -28,4 +30,7 @@ public class AuthorizedHostGroupWrapperVO { @Schema(description = "授权的主机列表") private List hostList; + @Schema(description = "分组树节点映射 'groupId':hostIdList") + private Map> treeNodes; + } diff --git a/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/entity/vo/HostGroupTreeVO.java b/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/entity/vo/HostGroupTreeVO.java index 4efee71b..001abaa9 100644 --- a/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/entity/vo/HostGroupTreeVO.java +++ b/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/entity/vo/HostGroupTreeVO.java @@ -44,7 +44,4 @@ public class HostGroupTreeVO implements TreeNode, Serializable @Schema(description = "子节点") private List children; - @Schema(description = "分组内主机") - private List hostList; - } diff --git a/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/service/AssetAuthorizedDataService.java b/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/service/AssetAuthorizedDataService.java index b713f12d..d81490f2 100644 --- a/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/service/AssetAuthorizedDataService.java +++ b/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/service/AssetAuthorizedDataService.java @@ -1,7 +1,7 @@ package com.orion.ops.module.asset.service; import com.orion.ops.module.asset.entity.request.asset.AssetAuthorizedDataQueryRequest; -import com.orion.ops.module.asset.entity.vo.AuthorizedHostGroupWrapperVO; +import com.orion.ops.module.asset.entity.vo.AuthorizedHostWrapperVO; import com.orion.ops.module.asset.entity.vo.HostIdentityVO; import com.orion.ops.module.asset.entity.vo.HostKeyVO; import com.orion.ops.module.infra.enums.DataPermissionTypeEnum; @@ -27,12 +27,12 @@ public interface AssetAuthorizedDataService { List getAuthorizedDataRelId(DataPermissionTypeEnum type, AssetAuthorizedDataQueryRequest request); /** - * 查询用户已授权的主机分组和主机 + * 查询用户已授权的主机主机 * * @param userId userId * @return group */ - AuthorizedHostGroupWrapperVO getUserAuthorizedHostGroup(Long userId); + AuthorizedHostWrapperVO getUserAuthorizedHostGroup(Long userId); /** * 查询用户已授权的主机秘钥 diff --git a/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/service/impl/AssetAuthorizedDataServiceImpl.java b/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/service/impl/AssetAuthorizedDataServiceImpl.java index 1a450c85..20074d0f 100644 --- a/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/service/impl/AssetAuthorizedDataServiceImpl.java +++ b/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/service/impl/AssetAuthorizedDataServiceImpl.java @@ -74,7 +74,7 @@ public class AssetAuthorizedDataServiceImpl implements AssetAuthorizedDataServic } @Override - public AuthorizedHostGroupWrapperVO getUserAuthorizedHostGroup(Long userId) { + public AuthorizedHostWrapperVO getUserAuthorizedHostGroup(Long userId) { if (systemUserApi.isAdminUser(userId)) { // 管理员查询所有 return this.buildUserAuthorizedHostGroup(null); @@ -83,7 +83,7 @@ public class AssetAuthorizedDataServiceImpl implements AssetAuthorizedDataServic List authorizedIdList = dataPermissionApi.getUserAuthorizedRelIdList(DataPermissionTypeEnum.HOST_GROUP, userId); if (authorizedIdList.isEmpty()) { // 无数据 - return AuthorizedHostGroupWrapperVO.builder() + return AuthorizedHostWrapperVO.builder() .groupTree(Lists.empty()) .hostList(Lists.empty()) .build(); @@ -142,60 +142,103 @@ public class AssetAuthorizedDataServiceImpl implements AssetAuthorizedDataServic * @param authorizedGroupIdList authorizedGroupIdList * @return tree */ - private AuthorizedHostGroupWrapperVO buildUserAuthorizedHostGroup(List authorizedGroupIdList) { + private AuthorizedHostWrapperVO buildUserAuthorizedHostGroup(List authorizedGroupIdList) { final boolean allData = Lists.isEmpty(authorizedGroupIdList); - AuthorizedHostGroupWrapperVO wrapper = new AuthorizedHostGroupWrapperVO(); - // 查询主机列表 - List hosts = hostService.getHostListByCache(); - Map hostMap = hosts.stream() - .collect(Collectors.toMap(HostVO::getId, Function.identity(), Functions.right())); - // 查询分组引用 - Map> groupRel = dataGroupRelApi.getGroupRelList(DataGroupTypeEnum.HOST); + AuthorizedHostWrapperVO wrapper = new AuthorizedHostWrapperVO(); + // TODO async get 最近连接 + // TODO async get 我的收藏 // 查询分组 List dataGroup = dataGroupApi.getDataGroupList(DataGroupTypeEnum.HOST); - // 过滤分组 + // 查询分组引用 + Map> dataGroupRel = dataGroupRelApi.getGroupRelList(DataGroupTypeEnum.HOST); + // 过滤已经授权的分组 if (!allData) { // 构建已授权的分组 List relNodes = new ArrayList<>(); TreeUtils.getAllNodes(dataGroup, authorizedGroupIdList, relNodes); dataGroup = new ArrayList<>(new HashSet<>(relNodes)); } - // 设置组内数据 + // 设置主机分组树 + wrapper.setGroupTree(this.getAuthorizedHostGroupTree(dataGroup)); + // 设置主机分组下的主机 + wrapper.setTreeNodes(this.getAuthorizedHostGroupNodes(allData, dataGroup, dataGroupRel, authorizedGroupIdList)); + // 设置已授权的所有主机 + wrapper.setHostList(this.getAuthorizedHostList(allData, dataGroup, dataGroupRel, authorizedGroupIdList)); + // TODO set 最近连接 + // TODO set 我的收藏 + + return wrapper; + } + + /** + * 构建主机分组树 + * + * @param dataGroup dataGroup + * @return tree + */ + private List getAuthorizedHostGroupTree(List dataGroup) { List groupList = HostGroupConvert.MAPPER.toList(dataGroup); - groupList.stream() - // 因为可能父菜单没有授权 这里需要判断组 - .filter(s -> allData || authorizedGroupIdList.contains(s.getId())) - .forEach(s -> { - List groupHosts = Lists.stream(groupRel.get(s.getId())) - .map(hostMap::get) - .filter(Objects::nonNull) - .collect(Collectors.toList()); - s.setHostList(groupHosts); - }); - // 构建主机树 HostGroupTreeVO rootNode = HostGroupTreeVO.builder() .id(Const.ROOT_PARENT_ID) .sort(Const.DEFAULT_SORT) .build(); TreeUtils.buildGroupTree(rootNode, groupList); - wrapper.setGroupTree(rootNode.getChildren()); - // 设置授权的主机 + return rootNode.getChildren(); + } + + /** + * 获取主机分组树 主机节点映射 + * + * @param allData allData + * @param dataGroup dataGroup + * @param dataGroupRel dataGroupRel + * @param authorizedGroupIdList authorizedGroupIdList + * @return hostGroupId:hostIdList + */ + private Map> getAuthorizedHostGroupNodes(boolean allData, + List dataGroup, + Map> dataGroupRel, + List authorizedGroupIdList) { + Map> result = new HashMap<>(); + dataGroup.stream() + .map(DataGroupDTO::getId) + // 因为可能父菜单没有授权 这里需要判断分组权限 + .filter(id -> allData || authorizedGroupIdList.contains(id)) + .forEach(s -> result.put(String.valueOf(s), dataGroupRel.get(s))); + return result; + } + + /** + * 查询已授权的所有主机 + * + * @param allData allData + * @param dataGroup dataGroup + * @param dataGroupRel dataGroupRel + * @param authorizedGroupIdList authorizedGroupIdList + * @return hosts + */ + private List getAuthorizedHostList(boolean allData, + List dataGroup, + Map> dataGroupRel, + List authorizedGroupIdList) { + // 查询主机列表 + List hosts = hostService.getHostListByCache(); + // 全部数据直接返回 if (allData) { - // 设置全部数据 - wrapper.setHostList(hosts); - } else { - // 仅设置已授权的数据 - List groupHosts = groupList.stream() - .filter(s -> authorizedGroupIdList.contains(s.getId())) - .map(s -> groupRel.get(s.getId())) - .filter(Lists::isNoneEmpty) - .flatMap(Collection::stream) - .map(hostMap::get) - .filter(Objects::nonNull) - .collect(Collectors.toList()); - wrapper.setHostList(groupHosts); + return hosts; } - return wrapper; + Map hostMap = hosts.stream() + .collect(Collectors.toMap(HostVO::getId, Function.identity(), Functions.right())); + // 仅设置已授权的数据 + return dataGroup.stream() + .map(DataGroupDTO::getId) + .filter(authorizedGroupIdList::contains) + .map(dataGroupRel::get) + .filter(Lists::isNoneEmpty) + .flatMap(Collection::stream) + .map(hostMap::get) + .filter(Objects::nonNull) + .collect(Collectors.toList()); } } diff --git a/orion-ops-ui/src/api/asset/asset-authorized-data.ts b/orion-ops-ui/src/api/asset/asset-authorized-data.ts index 7d7ef0f2..6b96bdc5 100644 --- a/orion-ops-ui/src/api/asset/asset-authorized-data.ts +++ b/orion-ops-ui/src/api/asset/asset-authorized-data.ts @@ -5,18 +5,19 @@ import type { HostIdentityQueryResponse } from './host-identity'; import axios from 'axios'; /** - * 已授权的主机分组 查询响应 + * 已授权的主机 查询响应 */ -export interface AuthorizedHostGroupQueryResponse { +export interface AuthorizedHostQueryResponse { groupTree: Array; hostList: Array; + treeNodes: Record>; } /** - * 查询当前用户已授权的主机分组 + * 查询当前用户已授权的主机 */ -export function getCurrentAuthorizedHostGroup() { - return axios.get('/asset/authorized-data/current-host-group'); +export function getCurrentAuthorizedHost() { + return axios.get('/asset/authorized-data/current-host'); } /** diff --git a/orion-ops-ui/src/api/asset/host-group.ts b/orion-ops-ui/src/api/asset/host-group.ts index d2ad3e50..075a18d3 100644 --- a/orion-ops-ui/src/api/asset/host-group.ts +++ b/orion-ops-ui/src/api/asset/host-group.ts @@ -1,4 +1,3 @@ -import type { HostQueryResponse } from './host'; import axios from 'axios'; /** @@ -34,7 +33,6 @@ export interface HostGroupQueryResponse { parentId: number; title: string; children: Array; - hostList: Array; } /** diff --git a/orion-ops-ui/src/api/meta/tag.ts b/orion-ops-ui/src/api/meta/tag.ts index 4fa5623e..2ace1b2f 100644 --- a/orion-ops-ui/src/api/meta/tag.ts +++ b/orion-ops-ui/src/api/meta/tag.ts @@ -1,6 +1,6 @@ import axios from 'axios'; -export type TagType = 'HOST' +export type TagType = 'HOST' | string /** * tag 创建对象 @@ -29,5 +29,5 @@ export function createTag(request: TagCreateRequest) { * 查询标签 */ export function getTagList(type: TagType) { - return axios.get('/infra/tag/list', { params: { type } }); + return axios.get>('/infra/tag/list', { params: { type } }); } diff --git a/orion-ops-ui/src/components/asset/host-group/host-group-tree-selector.vue b/orion-ops-ui/src/components/asset/host-group/host-group-tree-selector.vue index 62ad26f5..3b48995d 100644 --- a/orion-ops-ui/src/components/asset/host-group/host-group-tree-selector.vue +++ b/orion-ops-ui/src/components/asset/host-group/host-group-tree-selector.vue @@ -44,15 +44,10 @@ const treeData = ref>([]); // 初始化选项 - onBeforeMount(async () => { - if (cacheStore.hostGroups.length) { - treeData.value = cacheStore.hostGroups; - } else { - // 加载数据 - const { data } = await getHostGroupTree(); - treeData.value = data; - cacheStore.set('hostGroups', data); - } + onBeforeMount(() => { + cacheStore.loadHostGroups().then(s => { + treeData.value = s; + }); }); diff --git a/orion-ops-ui/src/components/asset/host-group/host-group-tree.vue b/orion-ops-ui/src/components/asset/host-group/host-group-tree.vue index 6b93e464..bca9d667 100644 --- a/orion-ops-ui/src/components/asset/host-group/host-group-tree.vue +++ b/orion-ops-ui/src/components/asset/host-group/host-group-tree.vue @@ -5,7 +5,7 @@ ref="tree" class="tree-container" :blockNode="true" - :draggable="draggable" + :draggable="editable" :data="treeData" :checkable="checkable" v-model:checked-keys="checkedKeys" @@ -20,7 +20,6 @@ v-model="currName" style="width: 138px;" placeholder="名称" - autofocus :max-length="32" :disabled="node.loading" @blur="() => saveNode(node.key)" @@ -77,7 +76,7 @@

暂无数据 - 点击上方 '' 添加一个分组吧~ + 点击上方 '' 添加一个分组吧~
@@ -99,7 +98,7 @@ const props = defineProps({ loading: Boolean, - draggable: { + editable: { type: Boolean, default: true }, @@ -313,20 +312,13 @@ // 加载数据 const fetchTreeData = async (force = false) => { - if (cacheStore.hostGroups.length && !force) { - // 缓存有数据并且非强制加载 直接从缓存中加载 - treeData.value = cacheStore.hostGroups; - } else { - // 无数据/强制加载 - try { - emits('loading', true); - const { data } = await getHostGroupTree(); - treeData.value = data; - cacheStore.hostGroups = data; - } catch (e) { - } finally { - emits('loading', false); - } + try { + const groups = await cacheStore.loadHostGroups(force); + emits('loading', true); + treeData.value = groups; + } catch (e) { + } finally { + emits('loading', false); } // 未选择则选择首个 if (!tree.value?.getSelectedNodes()?.length && treeData.value.length) { diff --git a/orion-ops-ui/src/components/asset/host-identity/host-identity-selector.vue b/orion-ops-ui/src/components/asset/host-identity/host-identity-selector.vue index bf0ce623..e1dd2832 100644 --- a/orion-ops-ui/src/components/asset/host-identity/host-identity-selector.vue +++ b/orion-ops-ui/src/components/asset/host-identity/host-identity-selector.vue @@ -40,11 +40,13 @@ // 初始化选项 onBeforeMount(() => { - optionData.value = cacheStore.hostIdentities.map(s => { - return { - label: `${s.name} (${s.username})`, - value: s.id, - }; + cacheStore.loadHostIdentities().then(hostIdentities => { + optionData.value = hostIdentities.map(s => { + return { + label: `${s.name} (${s.username})`, + value: s.id, + }; + }); }); }); diff --git a/orion-ops-ui/src/components/asset/host-key/host-key-selector.vue b/orion-ops-ui/src/components/asset/host-key/host-key-selector.vue index 75cb5c04..3d6ac95d 100644 --- a/orion-ops-ui/src/components/asset/host-key/host-key-selector.vue +++ b/orion-ops-ui/src/components/asset/host-key/host-key-selector.vue @@ -40,11 +40,13 @@ // 初始化选项 onBeforeMount(() => { - optionData.value = cacheStore.hostKeys.map(s => { - return { - label: s.name, - value: s.id, - }; + cacheStore.loadHostKeys().then(hostKeys => { + optionData.value = hostKeys.map(s => { + return { + label: s.name, + value: s.id, + }; + }); }); }); diff --git a/orion-ops-ui/src/components/meta/tag/tag-multi-selector.vue b/orion-ops-ui/src/components/meta/tag/tag-multi-selector.vue index 54e7b6e5..160435e4 100644 --- a/orion-ops-ui/src/components/meta/tag/tag-multi-selector.vue +++ b/orion-ops-ui/src/components/meta/tag/tag-multi-selector.vue @@ -2,6 +2,7 @@ >, @@ -31,11 +33,11 @@ limit: Number, type: String, allowCreate: Boolean, - tagType: String, }); const emits = defineEmits(['update:modelValue', 'onLimited']); + const { loading, setLoading } = useLoading(); const cacheStore = useCacheStore(); const value = computed>({ @@ -51,12 +53,13 @@ // 初始化选项 onBeforeMount(() => { - const tagCache = cacheStore[props.tagType as string] as Array; - optionData.value = tagCache.map(s => { - return { - label: s.name, - value: s.id, - }; + cacheStore.loadTags(props.type as string).then((tags) => { + optionData.value = tags.map(s => { + return { + label: s.name, + value: s.id, + }; + }); }); }); @@ -78,12 +81,16 @@ tags.splice(i, 1); return; } + // 不存在则创建 tag + setLoading(true); try { // 创建 tag tags[i] = await doCreateTag(tag); } catch (e) { // 失败删除 tags.splice(i, 1); + } finally { + setLoading(false); } } }; @@ -95,8 +102,8 @@ type: props.type } as unknown as TagCreateRequest); // 插入缓存 - const tagCache = cacheStore[props.tagType as string] as Array; - tagCache.push({ id, name }); + const tagCache = await cacheStore.loadTags(props.type as string); + tagCache && tagCache.push({ id, name }); // 插入 options optionData.value.push({ label: name, diff --git a/orion-ops-ui/src/components/system/dict-key/dict-key-selector.vue b/orion-ops-ui/src/components/system/dict-key/dict-key-selector.vue index b2a50010..0abea687 100644 --- a/orion-ops-ui/src/components/system/dict-key/dict-key-selector.vue +++ b/orion-ops-ui/src/components/system/dict-key/dict-key-selector.vue @@ -41,18 +41,18 @@ }, set(e) { if (typeof e === 'string') { - // 创建的值 - emits('update:modelValue', undefined); + // 创建的值 这里必须为 null, 否则 table 的重置不生效 + emits('update:modelValue', null); emits('change', { - id: undefined, + id: null, keyName: e }); } else { // 已有的值 emits('update:modelValue', e); - const find = cacheStore.dictKeys.find(s => s.id === e); + const find = optionData.value.find(s => s.value === e); if (find) { - emits('change', find); + emits('change', find.origin); } } } @@ -61,11 +61,14 @@ // 初始化选项 onBeforeMount(() => { - optionData.value = cacheStore.dictKeys.map(s => { - return { - label: `${s.keyName} - ${s.description || ''}`, - value: s.id, - }; + cacheStore.loadDictKeys().then(dictKeys => { + optionData.value = dictKeys.map(s => { + return { + label: `${s.keyName} - ${s.description || ''}`, + value: s.id, + origin: s + }; + }); }); }); diff --git a/orion-ops-ui/src/components/system/menu/grant/menu-grant-table.vue b/orion-ops-ui/src/components/system/menu/grant/menu-grant-table.vue index f5222315..d0596bcf 100644 --- a/orion-ops-ui/src/components/system/menu/grant/menu-grant-table.vue +++ b/orion-ops-ui/src/components/system/menu/grant/menu-grant-table.vue @@ -67,7 +67,9 @@ unTriggerChange.value = true; checkedKeys.value = keys; if (!menuData.value.length) { - menuData.value = [...cacheStore.menus]; + cacheStore.loadMenus().then(menus => { + menuData.value = [...menus]; + }); } }; diff --git a/orion-ops-ui/src/views/system/menu/components/menu-tree-selector.vue b/orion-ops-ui/src/components/system/menu/selector/menu-tree-selector.vue similarity index 72% rename from orion-ops-ui/src/views/system/menu/components/menu-tree-selector.vue rename to orion-ops-ui/src/components/system/menu/selector/menu-tree-selector.vue index 2c99d540..dc200da8 100644 --- a/orion-ops-ui/src/views/system/menu/components/menu-tree-selector.vue +++ b/orion-ops-ui/src/components/system/menu/selector/menu-tree-selector.vue @@ -1,9 +1,9 @@ @@ -16,8 +16,9 @@ diff --git a/orion-ops-ui/src/store/modules/cache/index.ts b/orion-ops-ui/src/store/modules/cache/index.ts index 5fda7f5b..840bf218 100644 --- a/orion-ops-ui/src/store/modules/cache/index.ts +++ b/orion-ops-ui/src/store/modules/cache/index.ts @@ -1,24 +1,23 @@ import type { CacheState } from './types'; import type { AxiosResponse } from 'axios'; +import type { TagType } from '@/api/meta/tag'; +import { getTagList } from '@/api/meta/tag'; import { defineStore } from 'pinia'; import { getUserList } from '@/api/user/user'; import { getRoleList } from '@/api/user/role'; +import { getDictKeyList } from '@/api/system/dict-key'; +import { getHostKeyList } from '@/api/asset/host-key'; +import { getHostIdentityList } from '@/api/asset/host-identity'; +import { getHostList } from '@/api/asset/host'; +import { getHostGroupTree } from '@/api/asset/host-group'; +import { getMenuList } from '@/api/system/menu'; export type CacheType = 'users' | 'menus' | 'roles' - | 'host' | 'hostGroups' | 'hostTags' | 'hostKeys' | 'hostIdentities' + | 'host' | 'hostGroups' | 'hostKeys' | 'hostIdentities' | 'dictKeys' | string export default defineStore('cache', { - state: (): CacheState => ({ - menus: [], - roles: [], - hosts: [], - hostGroups: [], - hostTags: [], - hostKeys: [], - hostIdentities: [], - dictKeys: [], - }), + state: (): CacheState => ({}), getters: {}, @@ -41,9 +40,9 @@ export default defineStore('cache', { }, // 加载数据 - async load(name: CacheType, loader: () => Promise>, onErrorValue = []) { + async load(name: CacheType, loader: () => Promise>, force = false, onErrorValue = []) { // 尝试直接从缓存中获取数据 - if (this[name]) { + if (this[name] && !force) { return this[name] as T; } // 加载数据 @@ -57,13 +56,48 @@ export default defineStore('cache', { }, // 获取用户列表 - async loadUsers() { - return await this.load('users', getUserList); + async loadUsers(force = false) { + return await this.load('users', getUserList, force); }, // 获取角色列表 - async loadRoles() { - return await this.load('roles', getRoleList); + async loadRoles(force = false) { + return await this.load('roles', getRoleList, force); + }, + + // 获取菜单列表 + async loadMenus(force = false) { + return await this.load('menus', () => getMenuList({}), force); + }, + + // 获取主机分组列表 + async loadHostGroups(force = false) { + return await this.load('hostGroups', getHostGroupTree, force); + }, + + // 获取主机列表 + async loadHosts(force = false) { + return await this.load('hosts', getHostList, force); + }, + + // 获取主机秘钥列表 + async loadHostKeys(force = false) { + return await this.load('hostKeys', getHostKeyList, force); + }, + + // 获取主机身份列表 + async loadHostIdentities(force = false) { + return await this.load('hostIdentities', getHostIdentityList, force); + }, + + // 获取字典配置项列表 + async loadDictKeys(force = false) { + return await this.load('dictKeys', getDictKeyList, force); + }, + + // 加载 tags + async loadTags(type: TagType, force = false) { + return await this.load(`${type}_Tags`, () => getTagList(type), force); }, } diff --git a/orion-ops-ui/src/store/modules/cache/types.ts b/orion-ops-ui/src/store/modules/cache/types.ts index 3a53c16c..3c4d8c22 100644 --- a/orion-ops-ui/src/store/modules/cache/types.ts +++ b/orion-ops-ui/src/store/modules/cache/types.ts @@ -1,7 +1,6 @@ import type { UserQueryResponse } from '@/api/user/user'; import type { MenuQueryResponse } from '@/api/system/menu'; import type { RoleQueryResponse } from '@/api/user/role'; -import type { TagQueryResponse } from '@/api/meta/tag'; import type { HostQueryResponse } from '@/api/asset/host'; import type { HostGroupQueryResponse } from '@/api/asset/host-group'; import type { HostKeyQueryResponse } from '@/api/asset/host-key'; @@ -12,7 +11,6 @@ export interface CacheState { users?: UserQueryResponse[]; menus?: MenuQueryResponse[]; roles?: RoleQueryResponse[]; - hostTags?: TagQueryResponse[]; hosts?: HostQueryResponse[]; hostGroups?: HostGroupQueryResponse[]; hostKeys?: HostKeyQueryResponse[]; diff --git a/orion-ops-ui/src/types/form.ts b/orion-ops-ui/src/types/form.ts index 336256de..04b3293e 100644 --- a/orion-ops-ui/src/types/form.ts +++ b/orion-ops-ui/src/types/form.ts @@ -2,3 +2,8 @@ export const labelFilter = (searchValue: string, option: { label: string; }) => { return option.label.toLowerCase().indexOf(searchValue.toLowerCase()) > -1; }; + +// 通过 title 进行过滤 +export const titleFilter = (searchValue: string, option: { title: string; }) => { + return option.title.toLowerCase().indexOf(searchValue.toLowerCase()) > -1; +}; diff --git a/orion-ops-ui/src/views/asset/grant/components/host-group-role-grant.vue b/orion-ops-ui/src/views/asset/grant/components/host-group-role-grant.vue index 78269ca1..28a20c5b 100644 --- a/orion-ops-ui/src/views/asset/grant/components/host-group-role-grant.vue +++ b/orion-ops-ui/src/views/asset/grant/components/host-group-role-grant.vue @@ -31,7 +31,7 @@ cacheStore.hosts.find(h => h.id === s) as HostQueryResponse) + const hosts = await cacheStore.loadHosts(); + selectedGroupHosts.value = data.map(s => hosts.find(h => h.id === s) as HostQueryResponse) .filter(Boolean); } catch (e) { } finally { @@ -72,24 +71,6 @@ } }); - // 加载主机列表 - const loadHostList = async () => { - try { - const { data } = await getHostList(); - // 设置到缓存 - cacheStore.set('hosts', data); - } catch (e) { - Message.error('主机列表加载失败'); - } - }; - - onBeforeMount(async () => { - if (!cacheStore.hosts.length) { - // 加载用户列表 - await loadHostList(); - } - }); -