refactor: 修改缓存加载逻辑.
This commit is contained in:
@@ -30,7 +30,7 @@ public @interface OperatorLog {
|
||||
* - {@link org.springframework.web.bind.annotation.PathVariable}
|
||||
* <p>
|
||||
* 使用 @IgnoreParameter 可以忽略参数记录 {@link IgnoreParameter}
|
||||
* 如果只需要忽略某个字段可以使用 @Desensitize(toEmpty = true) 标注
|
||||
* 如果只需要忽略某个字段可以使用 {@code @Desensitize(toEmpty = true)} 标注
|
||||
*/
|
||||
boolean parameter() default true;
|
||||
|
||||
|
||||
@@ -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(),
|
||||
};
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
### 查询当前用户已授权的主机分组及主机
|
||||
GET {{baseUrl}}/asset/authorized-data/current-host-group
|
||||
### 查询当前用户已授权的主机
|
||||
GET {{baseUrl}}/asset/authorized-data/current-host
|
||||
Authorization: {{token}}
|
||||
|
||||
### 查询当前用户已授权的主机秘钥
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
|
||||
@@ -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<HostGroupTreeVO> groupTree;
|
||||
@@ -28,4 +30,7 @@ public class AuthorizedHostGroupWrapperVO {
|
||||
@Schema(description = "授权的主机列表")
|
||||
private List<HostVO> hostList;
|
||||
|
||||
@Schema(description = "分组树节点映射 'groupId':hostIdList")
|
||||
private Map<String, Set<Long>> treeNodes;
|
||||
|
||||
}
|
||||
@@ -44,7 +44,4 @@ public class HostGroupTreeVO implements TreeNode<HostGroupTreeVO>, Serializable
|
||||
@Schema(description = "子节点")
|
||||
private List<HostGroupTreeVO> children;
|
||||
|
||||
@Schema(description = "分组内主机")
|
||||
private List<HostVO> hostList;
|
||||
|
||||
}
|
||||
|
||||
@@ -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<Long> getAuthorizedDataRelId(DataPermissionTypeEnum type, AssetAuthorizedDataQueryRequest request);
|
||||
|
||||
/**
|
||||
* 查询用户已授权的主机分组和主机
|
||||
* 查询用户已授权的主机主机
|
||||
*
|
||||
* @param userId userId
|
||||
* @return group
|
||||
*/
|
||||
AuthorizedHostGroupWrapperVO getUserAuthorizedHostGroup(Long userId);
|
||||
AuthorizedHostWrapperVO getUserAuthorizedHostGroup(Long userId);
|
||||
|
||||
/**
|
||||
* 查询用户已授权的主机秘钥
|
||||
|
||||
@@ -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<Long> 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<Long> authorizedGroupIdList) {
|
||||
private AuthorizedHostWrapperVO buildUserAuthorizedHostGroup(List<Long> authorizedGroupIdList) {
|
||||
final boolean allData = Lists.isEmpty(authorizedGroupIdList);
|
||||
AuthorizedHostGroupWrapperVO wrapper = new AuthorizedHostGroupWrapperVO();
|
||||
// 查询主机列表
|
||||
List<HostVO> hosts = hostService.getHostListByCache();
|
||||
Map<Long, HostVO> hostMap = hosts.stream()
|
||||
.collect(Collectors.toMap(HostVO::getId, Function.identity(), Functions.right()));
|
||||
// 查询分组引用
|
||||
Map<Long, Set<Long>> groupRel = dataGroupRelApi.getGroupRelList(DataGroupTypeEnum.HOST);
|
||||
AuthorizedHostWrapperVO wrapper = new AuthorizedHostWrapperVO();
|
||||
// TODO async get 最近连接
|
||||
// TODO async get 我的收藏
|
||||
// 查询分组
|
||||
List<DataGroupDTO> dataGroup = dataGroupApi.getDataGroupList(DataGroupTypeEnum.HOST);
|
||||
// 过滤分组
|
||||
// 查询分组引用
|
||||
Map<Long, Set<Long>> dataGroupRel = dataGroupRelApi.getGroupRelList(DataGroupTypeEnum.HOST);
|
||||
// 过滤已经授权的分组
|
||||
if (!allData) {
|
||||
// 构建已授权的分组
|
||||
List<DataGroupDTO> 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<HostGroupTreeVO> getAuthorizedHostGroupTree(List<DataGroupDTO> dataGroup) {
|
||||
List<HostGroupTreeVO> groupList = HostGroupConvert.MAPPER.toList(dataGroup);
|
||||
groupList.stream()
|
||||
// 因为可能父菜单没有授权 这里需要判断组
|
||||
.filter(s -> allData || authorizedGroupIdList.contains(s.getId()))
|
||||
.forEach(s -> {
|
||||
List<HostVO> 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<String, Set<Long>> getAuthorizedHostGroupNodes(boolean allData,
|
||||
List<DataGroupDTO> dataGroup,
|
||||
Map<Long, Set<Long>> dataGroupRel,
|
||||
List<Long> authorizedGroupIdList) {
|
||||
Map<String, Set<Long>> 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<HostVO> getAuthorizedHostList(boolean allData,
|
||||
List<DataGroupDTO> dataGroup,
|
||||
Map<Long, Set<Long>> dataGroupRel,
|
||||
List<Long> authorizedGroupIdList) {
|
||||
// 查询主机列表
|
||||
List<HostVO> hosts = hostService.getHostListByCache();
|
||||
// 全部数据直接返回
|
||||
if (allData) {
|
||||
// 设置全部数据
|
||||
wrapper.setHostList(hosts);
|
||||
} else {
|
||||
// 仅设置已授权的数据
|
||||
List<HostVO> 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<Long, HostVO> 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());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -5,18 +5,19 @@ import type { HostIdentityQueryResponse } from './host-identity';
|
||||
import axios from 'axios';
|
||||
|
||||
/**
|
||||
* 已授权的主机分组 查询响应
|
||||
* 已授权的主机 查询响应
|
||||
*/
|
||||
export interface AuthorizedHostGroupQueryResponse {
|
||||
export interface AuthorizedHostQueryResponse {
|
||||
groupTree: Array<HostGroupQueryResponse>;
|
||||
hostList: Array<HostQueryResponse>;
|
||||
treeNodes: Record<string, Array<number>>;
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询当前用户已授权的主机分组
|
||||
* 查询当前用户已授权的主机
|
||||
*/
|
||||
export function getCurrentAuthorizedHostGroup() {
|
||||
return axios.get<AuthorizedHostGroupQueryResponse>('/asset/authorized-data/current-host-group');
|
||||
export function getCurrentAuthorizedHost() {
|
||||
return axios.get<AuthorizedHostQueryResponse>('/asset/authorized-data/current-host');
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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<HostGroupQueryResponse>;
|
||||
hostList: Array<HostQueryResponse>;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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<TagQueryResponse>('/infra/tag/list', { params: { type } });
|
||||
return axios.get<Array<TagQueryResponse>>('/infra/tag/list', { params: { type } });
|
||||
}
|
||||
|
||||
@@ -44,15 +44,10 @@
|
||||
const treeData = ref<Array<TreeNodeData>>([]);
|
||||
|
||||
// 初始化选项
|
||||
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;
|
||||
});
|
||||
});
|
||||
|
||||
</script>
|
||||
|
||||
@@ -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 @@
|
||||
<!-- 无数据 -->
|
||||
<div v-else-if="!loading" class="empty-container">
|
||||
<span>暂无数据</span>
|
||||
<span>点击上方 '<icon-plus />' 添加一个分组吧~</span>
|
||||
<span v-if="editable">点击上方 '<icon-plus />' 添加一个分组吧~</span>
|
||||
</div>
|
||||
</a-scrollbar>
|
||||
</template>
|
||||
@@ -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) {
|
||||
|
||||
@@ -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,
|
||||
};
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -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,
|
||||
};
|
||||
});
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
<a-select v-model:model-value="value"
|
||||
:placeholder="placeholder"
|
||||
:options="optionData"
|
||||
:loading="loading"
|
||||
:limit="limit as number"
|
||||
:allow-create="allowCreate"
|
||||
@exceed-limit="() => { emits('onLimited', limit, `最多选择${limit}个tag`) }"
|
||||
@@ -24,6 +25,7 @@
|
||||
import { useCacheStore } from '@/store';
|
||||
import { Message } from '@arco-design/web-vue';
|
||||
import { createTag } from '@/api/meta/tag';
|
||||
import useLoading from '@/hooks/loading';
|
||||
|
||||
const props = defineProps({
|
||||
modelValue: Array as PropType<Array<number>>,
|
||||
@@ -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<Array<number>>({
|
||||
@@ -51,12 +53,13 @@
|
||||
|
||||
// 初始化选项
|
||||
onBeforeMount(() => {
|
||||
const tagCache = cacheStore[props.tagType as string] as Array<any>;
|
||||
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<any>;
|
||||
tagCache.push({ id, name });
|
||||
const tagCache = await cacheStore.loadTags(props.type as string);
|
||||
tagCache && tagCache.push({ id, name });
|
||||
// 插入 options
|
||||
optionData.value.push({
|
||||
label: name,
|
||||
|
||||
@@ -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
|
||||
};
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -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];
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
<template>
|
||||
<a-tree-select v-model:model-value="value"
|
||||
:data="treeData()"
|
||||
:data="treeData"
|
||||
:disabled="disabled"
|
||||
:allow-search="true"
|
||||
:filter-tree-node="filterTreeNode"
|
||||
:filter-tree-node="titleFilter"
|
||||
placeholder="请选择菜单" />
|
||||
</template>
|
||||
|
||||
@@ -16,8 +16,9 @@
|
||||
<script lang="ts" setup>
|
||||
import type { TreeNodeData } from '@arco-design/web-vue';
|
||||
import { useCacheStore } from '@/store';
|
||||
import { computed } from 'vue';
|
||||
import { MenuType } from '../types/const';
|
||||
import { computed, onBeforeMount, ref } from 'vue';
|
||||
import { MenuType } from '@/views/system/menu/types/const';
|
||||
import { titleFilter } from '@/types/form';
|
||||
|
||||
const props = defineProps({
|
||||
modelValue: Number,
|
||||
@@ -26,6 +27,10 @@
|
||||
|
||||
const emits = defineEmits(['update:modelValue']);
|
||||
|
||||
const cacheStore = useCacheStore();
|
||||
|
||||
const treeData = ref<Array<TreeNodeData>>([]);
|
||||
|
||||
const value = computed({
|
||||
get() {
|
||||
return props.modelValue;
|
||||
@@ -35,9 +40,7 @@
|
||||
}
|
||||
});
|
||||
|
||||
// 树数据
|
||||
const cacheStore = useCacheStore();
|
||||
const treeData = (): TreeNodeData[] => {
|
||||
onBeforeMount(() => {
|
||||
let render = (arr: any[]): TreeNodeData[] => {
|
||||
return arr.map((s) => {
|
||||
// 为 function 返回空
|
||||
@@ -57,17 +60,14 @@
|
||||
return node;
|
||||
}).filter(Boolean);
|
||||
};
|
||||
return [{
|
||||
key: 0,
|
||||
title: '根目录',
|
||||
children: render([...cacheStore.menus])
|
||||
}];
|
||||
};
|
||||
|
||||
// 搜索
|
||||
const filterTreeNode = (searchValue: string, nodeData: { title: string; }) => {
|
||||
return nodeData.title.toLowerCase().indexOf(searchValue.toLowerCase()) > -1;
|
||||
};
|
||||
cacheStore.loadMenus().then(menus => {
|
||||
treeData.value = [{
|
||||
key: 0,
|
||||
title: '根目录',
|
||||
children: render([...menus])
|
||||
}];
|
||||
});
|
||||
});
|
||||
|
||||
</script>
|
||||
|
||||
68
orion-ops-ui/src/store/modules/cache/index.ts
vendored
68
orion-ops-ui/src/store/modules/cache/index.ts
vendored
@@ -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<T>(name: CacheType, loader: () => Promise<AxiosResponse<T>>, onErrorValue = []) {
|
||||
async load<T>(name: CacheType, loader: () => Promise<AxiosResponse<T>>, 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);
|
||||
},
|
||||
|
||||
}
|
||||
|
||||
@@ -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[];
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
<host-group-tree outer-class="group-main-tree"
|
||||
:checkable="true"
|
||||
:checked-keys="checkedGroups"
|
||||
:draggable="false"
|
||||
:editable="false"
|
||||
:loading="loading"
|
||||
@loading="setLoading"
|
||||
@select-node="e => selectedGroup = e"
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
<!-- 分组 -->
|
||||
<host-group-tree outer-class="group-main-tree"
|
||||
:checked-keys="checkedGroups"
|
||||
:draggable="false"
|
||||
:editable="false"
|
||||
:loading="loading"
|
||||
@loading="setLoading"
|
||||
@select-node="e => selectedGroup = e"
|
||||
|
||||
@@ -36,10 +36,8 @@
|
||||
import type { PropType } from 'vue';
|
||||
import useLoading from '@/hooks/loading';
|
||||
import { useCacheStore } from '@/store';
|
||||
import { onBeforeMount, ref, watch } from 'vue';
|
||||
import { ref, watch } from 'vue';
|
||||
import { getHostGroupRelList } from '@/api/asset/host-group';
|
||||
import { getHostList } from '@/api/asset/host';
|
||||
import { Message } from '@arco-design/web-vue';
|
||||
|
||||
const props = defineProps({
|
||||
group: {
|
||||
@@ -64,7 +62,8 @@
|
||||
try {
|
||||
setLoading(true);
|
||||
const { data } = await getHostGroupRelList(groupId as number);
|
||||
selectedGroupHosts.value = data.map(s => 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();
|
||||
}
|
||||
});
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<div class="layout-container" v-if="render">
|
||||
<div class="layout-container">
|
||||
<!-- 列表-表格 -->
|
||||
<host-identity-table v-if="renderTable"
|
||||
ref="table"
|
||||
@@ -16,7 +16,7 @@
|
||||
<host-identity-form-modal ref="modal"
|
||||
@added="modalAddCallback"
|
||||
@updated="modalUpdateCallback" />
|
||||
<!-- 添加修改模态框 -->
|
||||
<!-- 主机秘钥抽屉 -->
|
||||
<host-key-form-drawer ref="keyDrawer" />
|
||||
</div>
|
||||
</template>
|
||||
@@ -28,17 +28,13 @@
|
||||
</script>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref, computed, onUnmounted } from 'vue';
|
||||
import { useAppStore, useCacheStore } from '@/store';
|
||||
import HostIdentityCardList from './components/host-identity-card-list.vue';
|
||||
import HostIdentityTable from './components/host-identity-table.vue';
|
||||
import HostIdentityFormModal from './components/host-identity-form-modal.vue';
|
||||
import HostKeyFormDrawer from '../host-key/components/host-key-form-drawer.vue';
|
||||
import { getHostKeyList } from '@/api/asset/host-key';
|
||||
|
||||
import { ref, computed, onBeforeMount, onUnmounted } from 'vue';
|
||||
import { useAppStore, useCacheStore } from '@/store';
|
||||
import { Message } from '@arco-design/web-vue';
|
||||
|
||||
const render = ref(false);
|
||||
const table = ref();
|
||||
const card = ref();
|
||||
const modal = ref();
|
||||
@@ -66,22 +62,6 @@
|
||||
}
|
||||
};
|
||||
|
||||
// 获取主机秘钥列表
|
||||
const fetchHostKeyList = async () => {
|
||||
try {
|
||||
const { data } = await getHostKeyList();
|
||||
cacheStore.set('hostKeys', data);
|
||||
} catch (e) {
|
||||
Message.error('主机秘钥加载失败');
|
||||
}
|
||||
};
|
||||
|
||||
onBeforeMount(async () => {
|
||||
// 加载主机秘钥
|
||||
await fetchHostKeyList();
|
||||
render.value = true;
|
||||
});
|
||||
|
||||
// 卸载时清除 cache
|
||||
onUnmounted(() => {
|
||||
const cacheStore = useCacheStore();
|
||||
|
||||
@@ -36,8 +36,6 @@
|
||||
import { Message } from '@arco-design/web-vue';
|
||||
import { getHostConfigAll } from '@/api/asset/host';
|
||||
import { useCacheStore, useDictStore } from '@/store';
|
||||
import { getHostKeyList } from '@/api/asset/host-key';
|
||||
import { getHostIdentityList } from '@/api/asset/host-identity';
|
||||
import { dictKeys as sshDictKeys } from './ssh/types/const';
|
||||
import SshConfigForm from './ssh/ssh-config-form.vue';
|
||||
|
||||
@@ -77,32 +75,10 @@
|
||||
|
||||
defineExpose({ open });
|
||||
|
||||
// 加载主机秘钥
|
||||
const fetchHostKeys = async () => {
|
||||
try {
|
||||
const { data } = await getHostKeyList();
|
||||
cacheStore.set('hostKeys', data);
|
||||
} catch (e) {
|
||||
}
|
||||
};
|
||||
|
||||
// 加载主机身份
|
||||
const fetchHostIdentities = async () => {
|
||||
try {
|
||||
const { data } = await getHostIdentityList();
|
||||
cacheStore.set('hostIdentities', data);
|
||||
} catch (e) {
|
||||
}
|
||||
};
|
||||
|
||||
onBeforeMount(async () => {
|
||||
// 加载字典值
|
||||
const dictStore = useDictStore();
|
||||
await dictStore.loadKeys([...sshDictKeys]);
|
||||
// 加载主机秘钥
|
||||
await fetchHostKeys();
|
||||
// 加载主机身份
|
||||
await fetchHostIdentities();
|
||||
});
|
||||
|
||||
</script>
|
||||
|
||||
@@ -52,9 +52,7 @@
|
||||
import type { PropType } from 'vue';
|
||||
import { onMounted, ref, watch, computed } from 'vue';
|
||||
import { useCacheStore } from '@/store';
|
||||
import { getHostGroupRelList, updateHostGroupRel } from '@/api/asset/host-group';
|
||||
import { Message } from '@arco-design/web-vue';
|
||||
import { getHostList } from '@/api/asset/host';
|
||||
import { getHostGroupRelList } from '@/api/asset/host-group';
|
||||
|
||||
const props = defineProps({
|
||||
modelValue: {
|
||||
@@ -114,31 +112,15 @@
|
||||
}
|
||||
});
|
||||
|
||||
// 加载主机列表
|
||||
const loadHostList = async () => {
|
||||
emits('loading', true);
|
||||
try {
|
||||
const { data } = await getHostList();
|
||||
// 设置到缓存
|
||||
cacheStore.set('hosts', data);
|
||||
} catch (e) {
|
||||
Message.error('主机列表加载失败');
|
||||
} finally {
|
||||
emits('loading', false);
|
||||
}
|
||||
};
|
||||
|
||||
onMounted(async () => {
|
||||
if (!cacheStore.hosts.length) {
|
||||
// 加载主机列表
|
||||
await loadHostList();
|
||||
}
|
||||
data.value = cacheStore.hosts.map(s => {
|
||||
return {
|
||||
value: String(s.id),
|
||||
label: `${s.name}(${s.code})-${s.address}`,
|
||||
disabled: false
|
||||
};
|
||||
onMounted(() => {
|
||||
cacheStore.loadHosts().then(hosts => {
|
||||
data.value = hosts.map(s => {
|
||||
return {
|
||||
value: String(s.id),
|
||||
label: `${s.name}(${s.code})-${s.address}`,
|
||||
disabled: false
|
||||
};
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -78,7 +78,6 @@
|
||||
:allowCreate="false"
|
||||
:limit="0"
|
||||
type="HOST"
|
||||
tag-type="hostTags"
|
||||
placeholder="请选择主机标签" />
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
|
||||
@@ -43,7 +43,6 @@
|
||||
:allowCreate="true"
|
||||
:limit="5"
|
||||
type="HOST"
|
||||
tag-type="hostTags"
|
||||
placeholder="请选择主机标签"
|
||||
@onLimited="onLimitedTag" />
|
||||
</a-form-item>
|
||||
|
||||
@@ -32,7 +32,6 @@
|
||||
:allowCreate="false"
|
||||
:limit="0"
|
||||
type="HOST"
|
||||
tag-type="hostTags"
|
||||
placeholder="请选择主机标签" />
|
||||
</a-form-item>
|
||||
</a-query-header>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<div class="layout-container" v-if="render">
|
||||
<div class="layout-container">
|
||||
<!-- 列表-表格 -->
|
||||
<host-table v-if="renderTable"
|
||||
ref="table"
|
||||
@@ -32,10 +32,8 @@
|
||||
</script>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { computed, ref, onBeforeMount, onUnmounted } from 'vue';
|
||||
import { computed, ref, onUnmounted } from 'vue';
|
||||
import { useAppStore, useCacheStore } from '@/store';
|
||||
import { getTagList } from '@/api/meta/tag';
|
||||
import { Message } from '@arco-design/web-vue';
|
||||
import HostTable from './components/host-table.vue';
|
||||
import HostCardList from './components/host-card-list.vue';
|
||||
import HostFormModal from './components/host-form-modal.vue';
|
||||
@@ -72,26 +70,9 @@
|
||||
}
|
||||
};
|
||||
|
||||
// 加载 tags
|
||||
const loadTags = async () => {
|
||||
try {
|
||||
const { data } = await getTagList('HOST');
|
||||
// 设置到缓存
|
||||
cacheStore.set('hostTags', data);
|
||||
} catch (e) {
|
||||
Message.error('tag加载失败');
|
||||
}
|
||||
};
|
||||
|
||||
onBeforeMount(async () => {
|
||||
// 加载 tags
|
||||
await loadTags();
|
||||
render.value = true;
|
||||
});
|
||||
|
||||
// 卸载时清除 cache
|
||||
onUnmounted(() => {
|
||||
cacheStore.reset('hosts', 'hostTags', 'hostKeys', 'hostIdentities', 'hostGroups');
|
||||
cacheStore.reset('hosts', 'hostKeys', 'hostIdentities', 'hostGroups', 'HOST_Tags');
|
||||
});
|
||||
|
||||
</script>
|
||||
|
||||
@@ -139,10 +139,11 @@
|
||||
};
|
||||
|
||||
// 渲染表单
|
||||
const renderForm = (record: any) => {
|
||||
const renderForm = async (record: any) => {
|
||||
formModel.value = Object.assign({}, record);
|
||||
// schema
|
||||
const find = record.keyId && cacheStore.dictKeys.find((item) => item.id === record.keyId);
|
||||
const dictKeys = await cacheStore.loadDictKeys();
|
||||
const find = record.keyId && dictKeys.find((item) => item.id === record.keyId);
|
||||
keyExtraSchemas.value = (find && find.extraSchema && JSON.parse(find.extraSchema)) || [];
|
||||
// 额外参数
|
||||
extraValue.value = (formModel.value.extra && JSON.parse(formModel.value.extra)) || {};
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
<a-form-item field="keyId" label="配置项" label-col-flex="50px">
|
||||
<dict-key-selector v-model="formModel.keyId"
|
||||
@change="changeKey"
|
||||
allow-create
|
||||
allow-clear />
|
||||
</a-form-item>
|
||||
<!-- 配置值 -->
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<div class="layout-container" v-if="render">
|
||||
<div class="layout-container">
|
||||
<!-- 列表-表格 -->
|
||||
<dict-value-table ref="table"
|
||||
@openAdd="() => modal.openAdd()"
|
||||
@@ -27,14 +27,11 @@
|
||||
import DictValueTable from './components/dict-value-table.vue';
|
||||
import DictValueFormModal from './components/dict-value-form-modal.vue';
|
||||
import HistoryValueModal from '@/components/meta/history/history-value-modal.vue';
|
||||
import { ref, onBeforeMount, onUnmounted } from 'vue';
|
||||
import { ref, onUnmounted } from 'vue';
|
||||
import { historyType } from './types/const';
|
||||
import { useCacheStore } from '@/store';
|
||||
import { getDictKeyList } from '@/api/system/dict-key';
|
||||
import { Message } from '@arco-design/web-vue';
|
||||
import { rollbackDictValue } from '@/api/system/dict-value';
|
||||
|
||||
const render = ref(false);
|
||||
const table = ref();
|
||||
const modal = ref();
|
||||
const history = ref();
|
||||
@@ -55,23 +52,6 @@
|
||||
await rollbackDictValue({ id, valueId });
|
||||
};
|
||||
|
||||
// 加载字典配置项
|
||||
const loadDictKeys = async () => {
|
||||
try {
|
||||
const { data } = await getDictKeyList();
|
||||
// 设置到缓存
|
||||
cacheStore.set('dictKeys', data);
|
||||
} catch (e) {
|
||||
Message.error('配置项加载失败');
|
||||
}
|
||||
};
|
||||
|
||||
onBeforeMount(async () => {
|
||||
// 加载字典值
|
||||
await loadDictKeys();
|
||||
render.value = true;
|
||||
});
|
||||
|
||||
// 卸载时清除 cache
|
||||
onUnmounted(() => {
|
||||
cacheStore.reset('dictKeys');
|
||||
|
||||
@@ -125,12 +125,11 @@
|
||||
import formRules from '../types/form.rules';
|
||||
import { menuCacheKey, sortStep } from '../types/const';
|
||||
import { menuVisibleKey, menuTypeKey, MenuType, MenuVisible, MenuCache } from '../types/const';
|
||||
|
||||
import IconPicker from '@sanqi377/arco-vue-icon-picker';
|
||||
import MenuTreeSelector from './menu-tree-selector.vue';
|
||||
import { createMenu, updateMenu } from '@/api/system/menu';
|
||||
import { Message } from '@arco-design/web-vue';
|
||||
import { useDictStore } from '@/store';
|
||||
import IconPicker from '@sanqi377/arco-vue-icon-picker';
|
||||
import MenuTreeSelector from '@/components/system/menu/selector/menu-tree-selector.vue';
|
||||
|
||||
const { visible, setVisible } = useVisible();
|
||||
const { loading, setLoading } = useLoading();
|
||||
|
||||
@@ -263,7 +263,6 @@
|
||||
setFetchLoading(true);
|
||||
const { data } = await getMenuList(formModel);
|
||||
tableRenderData.value = data as MenuQueryResponse[];
|
||||
cacheStore.set('menus', tableRenderData.value);
|
||||
} catch (e) {
|
||||
} finally {
|
||||
setFetchLoading(false);
|
||||
|
||||
@@ -57,10 +57,8 @@
|
||||
import useVisible from '@/hooks/visible';
|
||||
import { getRoleMenuId, grantRoleMenu } from '@/api/user/role';
|
||||
import { Message } from '@arco-design/web-vue';
|
||||
import { useCacheStore } from '@/store';
|
||||
import { getMenuList } from '@/api/system/menu';
|
||||
import MenuGrantTable from '@/components/system/menu/grant/menu-grant-table.vue';
|
||||
import { quickGrantMenuOperator } from '../types/const';
|
||||
import MenuGrantTable from '@/components/system/menu/grant/menu-grant-table.vue';
|
||||
|
||||
const { visible, setVisible } = useVisible();
|
||||
const { loading, setLoading } = useLoading();
|
||||
@@ -74,13 +72,6 @@
|
||||
setVisible(true);
|
||||
try {
|
||||
setLoading(true);
|
||||
// 获取菜单列表
|
||||
const cacheStore = useCacheStore();
|
||||
if (!cacheStore.menus?.length) {
|
||||
// 加载菜单
|
||||
const { data: menuData } = await getMenuList({});
|
||||
cacheStore.set('menus', menuData);
|
||||
}
|
||||
// 获取角色菜单
|
||||
const { data: roleMenuIdList } = await getRoleMenuId(record.id);
|
||||
table.value.init(roleMenuIdList);
|
||||
|
||||
@@ -18,10 +18,11 @@ const columns = [
|
||||
dataIndex: 'code',
|
||||
slotName: 'code',
|
||||
}, {
|
||||
title: '角色状态',
|
||||
title: '状态',
|
||||
dataIndex: 'status',
|
||||
slotName: 'status',
|
||||
align: 'center',
|
||||
width: 84,
|
||||
}, {
|
||||
title: '创建时间',
|
||||
dataIndex: 'createTime',
|
||||
|
||||
Reference in New Issue
Block a user