review code.
This commit is contained in:
@@ -21,7 +21,7 @@ export interface AssetAuthorizedDataQueryRequest {
|
||||
* 主机分组授权
|
||||
*/
|
||||
export function grantHostGroup(request: AssetDataGrantRequest) {
|
||||
return axios.put('/asset/host-group/grant-host-group', request);
|
||||
return axios.put('/asset/data-grant/grant-host-group', request);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -4,12 +4,10 @@
|
||||
<div class="tab-bar-box">
|
||||
<div class="tab-bar-scroll">
|
||||
<div class="tags-wrap">
|
||||
<TabItem
|
||||
v-for="(tag, index) in tagList"
|
||||
:key="tag.fullPath"
|
||||
:index="index"
|
||||
:item-data="tag"
|
||||
/>
|
||||
<TabItem v-for="(tag, index) in tagList"
|
||||
:key="tag.fullPath"
|
||||
:index="index"
|
||||
:item-data="tag" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="tag-bar-operation"></div>
|
||||
@@ -48,7 +46,7 @@
|
||||
listenerRouteChange((route: RouteLocationNormalized) => {
|
||||
if (
|
||||
!route.meta.noAffix &&
|
||||
!tagList.value.some((tag) => tag.fullPath === route.fullPath)
|
||||
!tagList.value.some((tag) => tag.path === route.path)
|
||||
) {
|
||||
// 固定并且没有此 tab 则添加
|
||||
tabBarStore.addTab(routerToTag(route), route.meta?.ignoreCache as unknown as boolean);
|
||||
|
||||
@@ -1,18 +1,15 @@
|
||||
<template>
|
||||
<a-dropdown
|
||||
trigger="contextMenu"
|
||||
:popup-max-height="false"
|
||||
@select="actionSelect">
|
||||
<span
|
||||
class="arco-tag arco-tag-size-medium arco-tag-checked"
|
||||
:class="{ 'link-activated': itemData?.fullPath === $route.fullPath }"
|
||||
@click="goto(itemData as TagProps)">
|
||||
<a-dropdown trigger="contextMenu"
|
||||
:popup-max-height="false"
|
||||
@select="actionSelect">
|
||||
<span class="arco-tag arco-tag-size-medium arco-tag-checked"
|
||||
:class="{ 'link-activated': itemData?.path === $route.path }"
|
||||
@click="goto(itemData as TagProps)">
|
||||
<span class="tag-link">
|
||||
{{ itemData.title }}
|
||||
</span>
|
||||
<span
|
||||
class="arco-icon-hover arco-tag-icon-hover arco-icon-hover-size-medium arco-tag-close-btn"
|
||||
@click.stop="tagClose(itemData as TagProps, index)">
|
||||
<span class="arco-icon-hover arco-tag-icon-hover arco-icon-hover-size-medium arco-tag-close-btn"
|
||||
@click.stop="tagClose(itemData as TagProps, index)">
|
||||
<icon-close />
|
||||
</span>
|
||||
</span>
|
||||
@@ -91,7 +88,7 @@
|
||||
});
|
||||
|
||||
const disabledReload = computed(() => {
|
||||
return props.itemData.fullPath !== route.fullPath;
|
||||
return props.itemData.path !== route.path;
|
||||
});
|
||||
|
||||
const disabledCurrent = computed(() => {
|
||||
@@ -106,22 +103,22 @@
|
||||
return props.index === tagList.value.length - 1;
|
||||
});
|
||||
|
||||
/**
|
||||
* 关闭 tag
|
||||
*/
|
||||
// 关闭 tag
|
||||
const tagClose = (tag: TagProps, idx: number) => {
|
||||
tabBarStore.deleteTab(idx, tag);
|
||||
if (props.itemData.fullPath === route.fullPath) {
|
||||
if (props.itemData.path === route.path) {
|
||||
// 获取队列的前一个 tab
|
||||
const latest = tagList.value[idx - 1];
|
||||
router.push({ name: latest.name });
|
||||
}
|
||||
};
|
||||
|
||||
// 获取当前路由索引
|
||||
const findCurrentRouteIndex = () => {
|
||||
return tagList.value.findIndex((el) => el.fullPath === route.fullPath);
|
||||
return tagList.value.findIndex((el) => el.path === route.path);
|
||||
};
|
||||
|
||||
// 选择操作
|
||||
const actionSelect = async (value: any) => {
|
||||
const { itemData, index } = props;
|
||||
const copyTagList = [...tagList.value];
|
||||
|
||||
@@ -2,11 +2,9 @@
|
||||
<router-view v-slot="{ Component, route }">
|
||||
<transition name="fade" mode="out-in" appear>
|
||||
<!-- 渲染组件 -->
|
||||
<component
|
||||
:is="Component"
|
||||
v-if="route.meta.ignoreCache"
|
||||
:key="route.fullPath"
|
||||
/>
|
||||
<component :is="Component"
|
||||
v-if="route.meta.ignoreCache"
|
||||
:key="route.fullPath" />
|
||||
<!-- 渲染缓存组件 -->
|
||||
<keep-alive v-else :include="cacheList">
|
||||
<component :is="Component" :key="route.fullPath" />
|
||||
|
||||
@@ -35,6 +35,7 @@ export const STATUS_ROUTER_LIST = [
|
||||
export const DEFAULT_TAB = {
|
||||
title: '工作台',
|
||||
name: DEFAULT_ROUTE_NAME,
|
||||
path: DEFAULT_ROUTE_FULL_PATH,
|
||||
fullPath: DEFAULT_ROUTE_FULL_PATH,
|
||||
};
|
||||
|
||||
@@ -42,10 +43,11 @@ export const DEFAULT_TAB = {
|
||||
* router 转 tag
|
||||
*/
|
||||
export const routerToTag = (route: RouteLocationNormalized): TagProps => {
|
||||
const { name, meta, fullPath, query } = route;
|
||||
const { name, meta, path, fullPath, query } = route;
|
||||
return {
|
||||
title: meta.locale || '',
|
||||
name: String(name),
|
||||
path,
|
||||
fullPath,
|
||||
query,
|
||||
ignoreCache: meta.ignoreCache,
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
export interface TagProps {
|
||||
title: string;
|
||||
name: string;
|
||||
path: string;
|
||||
fullPath: string;
|
||||
query?: any;
|
||||
ignoreCache?: boolean;
|
||||
|
||||
@@ -6,3 +6,9 @@ export const TablePageSizeOptions = [10, 20, 30, 50, 100];
|
||||
|
||||
// 卡片视图分页数配置
|
||||
export const CardPageSizeOptions = [12, 18, 36, 48, 96];
|
||||
|
||||
// 通用启用状态
|
||||
export const EnabledStatus = {
|
||||
DISABLED: 0,
|
||||
ENABLED: 1
|
||||
};
|
||||
|
||||
@@ -1,14 +1,16 @@
|
||||
<template>
|
||||
<a-spin :loading="loading" class="grant-container">
|
||||
<!-- 角色列表 -->
|
||||
<router-roles v-model="roleId" @change="fetchAuthorizedGroup" />
|
||||
<router-roles outer-class="roles-router-wrapper"
|
||||
v-model="roleId"
|
||||
@change="fetchAuthorizedGroup" />
|
||||
<!-- 分组列表 -->
|
||||
<div class="group-container">
|
||||
<!-- 顶部 -->
|
||||
<div class="group-header">
|
||||
<!-- 提示信息 -->
|
||||
<a-alert class="alert-wrapper" :show-icon="false">
|
||||
<span v-if="currentRole">
|
||||
<span v-if="currentRole" class="alert-message">
|
||||
当前选择的角色为 <span class="span-blue mr4">{{ currentRole?.text }}</span>
|
||||
<span class="span-blue ml4" v-if="currentRole.code === AdminRoleCode">管理员拥有全部权限, 无需配置</span>
|
||||
</span>
|
||||
@@ -112,6 +114,12 @@
|
||||
height: 100%;
|
||||
display: flex;
|
||||
padding: 0 12px 12px 0;
|
||||
position: absolute;
|
||||
|
||||
.roles-router-wrapper {
|
||||
margin-right: 16px;
|
||||
border-right: 1px var(--color-neutral-3) solid;
|
||||
}
|
||||
|
||||
.group-container {
|
||||
position: relative;
|
||||
@@ -126,6 +134,11 @@
|
||||
|
||||
.alert-wrapper {
|
||||
padding: 4px 16px;
|
||||
|
||||
.alert-message {
|
||||
display: block;
|
||||
height: 22px;
|
||||
}
|
||||
}
|
||||
|
||||
.grant-button {
|
||||
|
||||
@@ -1,14 +1,16 @@
|
||||
<template>
|
||||
<a-spin :loading="loading" class="grant-container">
|
||||
<!-- 用户列表 -->
|
||||
<router-users v-model="userId" @change="fetchAuthorizedGroup" />
|
||||
<router-users outer-class="users-router-wrapper"
|
||||
v-model="userId"
|
||||
@change="fetchAuthorizedGroup" />
|
||||
<!-- 分组列表 -->
|
||||
<div class="group-container">
|
||||
<!-- 顶部 -->
|
||||
<div class="group-header">
|
||||
<!-- 提示信息 -->
|
||||
<a-alert class="alert-wrapper" :show-icon="false">
|
||||
<span v-if="currentUser">
|
||||
<span v-if="currentUser" class="alert-message">
|
||||
当前选择的用户为 <span class="span-blue mr4">{{ currentUser?.text }}</span>
|
||||
<span class="ml4">若当前选择的用户角色包含管理员则无需配置 (管理员拥有全部权限)</span>
|
||||
</span>
|
||||
@@ -110,6 +112,12 @@
|
||||
height: 100%;
|
||||
display: flex;
|
||||
padding: 0 12px 12px 0;
|
||||
position: absolute;
|
||||
|
||||
.users-router-wrapper {
|
||||
margin-right: 16px;
|
||||
border-right: 1px var(--color-neutral-3) solid;
|
||||
}
|
||||
|
||||
.group-container {
|
||||
position: relative;
|
||||
@@ -124,6 +132,11 @@
|
||||
|
||||
.alert-wrapper {
|
||||
padding: 4px 16px;
|
||||
|
||||
.alert-message {
|
||||
display: block;
|
||||
height: 22px;
|
||||
}
|
||||
}
|
||||
|
||||
.grant-button {
|
||||
|
||||
@@ -66,13 +66,6 @@
|
||||
const { data } = await getHostGroupRelList(groupId as number);
|
||||
selectedGroupHosts.value = data.map(s => cacheStore.hosts.find(h => h.id === s) as HostQueryResponse)
|
||||
.filter(Boolean);
|
||||
for (let i = 1800; i < 2000; i++) {
|
||||
selectedGroupHosts.value.push({
|
||||
id: i,
|
||||
name: i + '',
|
||||
code: i + '',
|
||||
} as any);
|
||||
}
|
||||
} catch (e) {
|
||||
} finally {
|
||||
setLoading(false);
|
||||
|
||||
@@ -1,18 +1,24 @@
|
||||
<template>
|
||||
<div class="role-container">
|
||||
<!-- 角色列表 -->
|
||||
<tab-router v-if="rolesRouter.length"
|
||||
class="role-router"
|
||||
v-model="value"
|
||||
:items="rolesRouter"
|
||||
@change="(key, item) => emits('change', key, item)" />
|
||||
<!-- 暂无数据 -->
|
||||
<a-empty v-else class="role-empty">
|
||||
<div slot="description">
|
||||
暂无角色数据
|
||||
</div>
|
||||
</a-empty>
|
||||
</div>
|
||||
<a-scrollbar>
|
||||
<div class="role-container">
|
||||
<!-- 角色列表 -->
|
||||
<tab-router v-if="rolesRouter.length"
|
||||
class="role-router"
|
||||
v-model="value"
|
||||
:items="rolesRouter"
|
||||
@change="(key, item) => emits('change', key, item)" />
|
||||
<!-- 加载中 -->
|
||||
<a-skeleton v-else-if="loading" class="skeleton-wrapper">
|
||||
<a-skeleton-line :rows="4" />
|
||||
</a-skeleton>
|
||||
<!-- 暂无数据 -->
|
||||
<a-empty v-else class="role-empty">
|
||||
<div slot="description">
|
||||
暂无角色数据
|
||||
</div>
|
||||
</a-empty>
|
||||
</div>
|
||||
</a-scrollbar>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
@@ -27,6 +33,7 @@
|
||||
import { useCacheStore } from '@/store';
|
||||
import { getRoleList } from '@/api/user/role';
|
||||
import { Message } from '@arco-design/web-vue';
|
||||
import useLoading from '@/hooks/loading';
|
||||
|
||||
const props = defineProps({
|
||||
modelValue: Number
|
||||
@@ -34,6 +41,7 @@
|
||||
|
||||
const emits = defineEmits(['update:modelValue', 'change']);
|
||||
|
||||
const { loading, setLoading } = useLoading();
|
||||
const cacheStore = useCacheStore();
|
||||
|
||||
const rolesRouter = ref<Array<TabRouterItem>>([]);
|
||||
@@ -49,12 +57,15 @@
|
||||
|
||||
// 加载角色列表
|
||||
const loadRoleList = async () => {
|
||||
setLoading(true);
|
||||
try {
|
||||
const { data } = await getRoleList();
|
||||
// 设置到缓存
|
||||
cacheStore.set('roles', data);
|
||||
} catch (e) {
|
||||
Message.error('角色列表加载失败');
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -75,17 +86,27 @@
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
@width: 198px;
|
||||
@height: 198px;
|
||||
|
||||
:deep(.arco-scrollbar-container) {
|
||||
height: 100%;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.role-container {
|
||||
margin-right: 16px;
|
||||
overflow: hidden;
|
||||
|
||||
.role-router {
|
||||
height: 100%;
|
||||
min-width: max-content;
|
||||
border-right: 1px var(--color-neutral-3) solid;
|
||||
min-width: @width;
|
||||
width: max-content;
|
||||
}
|
||||
|
||||
.role-empty {
|
||||
width: 198px;
|
||||
.skeleton-wrapper, .role-empty {
|
||||
width: @width;
|
||||
height: 200px;
|
||||
padding: 8px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,18 +1,24 @@
|
||||
<template>
|
||||
<div class="user-container">
|
||||
<!-- 用户列表 -->
|
||||
<tab-router v-if="usersRouter.length"
|
||||
class="user-router"
|
||||
v-model="value"
|
||||
:items="usersRouter"
|
||||
@change="(key, item) => emits('change', key, item)" />
|
||||
<!-- 暂无数据 -->
|
||||
<a-empty v-else class="user-empty">
|
||||
<div slot="description">
|
||||
暂无用户数据
|
||||
</div>
|
||||
</a-empty>
|
||||
</div>
|
||||
<a-scrollbar>
|
||||
<div class="user-container">
|
||||
<!-- 用户列表 -->
|
||||
<tab-router v-if="usersRouter.length"
|
||||
class="user-router"
|
||||
v-model="value"
|
||||
:items="usersRouter"
|
||||
@change="(key, item) => emits('change', key, item)" />
|
||||
<!-- 加载中 -->
|
||||
<a-skeleton v-else-if="loading" class="skeleton-wrapper">
|
||||
<a-skeleton-line :rows="4" />
|
||||
</a-skeleton>
|
||||
<!-- 暂无数据 -->
|
||||
<a-empty v-else class="user-empty">
|
||||
<div slot="description">
|
||||
暂无用户数据
|
||||
</div>
|
||||
</a-empty>
|
||||
</div>
|
||||
</a-scrollbar>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
@@ -27,6 +33,7 @@
|
||||
import { useCacheStore } from '@/store';
|
||||
import { getUserList } from '@/api/user/user';
|
||||
import { Message } from '@arco-design/web-vue';
|
||||
import useLoading from '@/hooks/loading';
|
||||
|
||||
const props = defineProps({
|
||||
modelValue: Number
|
||||
@@ -34,6 +41,7 @@
|
||||
|
||||
const emits = defineEmits(['update:modelValue', 'change']);
|
||||
|
||||
const { loading, setLoading } = useLoading();
|
||||
const cacheStore = useCacheStore();
|
||||
|
||||
const usersRouter = ref<Array<TabRouterItem>>([]);
|
||||
@@ -49,12 +57,15 @@
|
||||
|
||||
// 加载用户列表
|
||||
const loadUserList = async () => {
|
||||
setLoading(true);
|
||||
try {
|
||||
const { data } = await getUserList();
|
||||
// 设置到缓存
|
||||
cacheStore.set('users', data);
|
||||
} catch (e) {
|
||||
Message.error('用户列表加载失败');
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -74,17 +85,27 @@
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
@width: 198px;
|
||||
@height: 198px;
|
||||
|
||||
:deep(.arco-scrollbar-container) {
|
||||
height: 100%;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.user-container {
|
||||
margin-right: 16px;
|
||||
overflow: hidden;
|
||||
|
||||
.user-router {
|
||||
height: 100%;
|
||||
min-width: max-content;
|
||||
border-right: 1px var(--color-neutral-3) solid;
|
||||
min-width: @width;
|
||||
width: max-content;
|
||||
}
|
||||
|
||||
.user-empty {
|
||||
width: 198px;
|
||||
.skeleton-wrapper, .user-empty {
|
||||
width: @width;
|
||||
height: @height;
|
||||
padding: 8px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
<template>
|
||||
<div class="view-container">
|
||||
<a-tabs class="tabs-container simple-card"
|
||||
<a-tabs v-model:active-key="activeKey"
|
||||
class="tabs-container simple-card"
|
||||
size="large"
|
||||
:destroy-on-hide="true"
|
||||
:justify="true"
|
||||
:lazy-load="true">
|
||||
<!-- 主机分组授权(角色) -->
|
||||
<a-tab-pane :key="1"
|
||||
<a-tab-pane :key="GrantKey.HOST_GROUP_ROLE"
|
||||
v-permission="['asset:host-group:grant']"
|
||||
title="主机分组授权(角色)">
|
||||
<host-group-role-grant />
|
||||
</a-tab-pane>
|
||||
<!-- 主机分组授权(用户) -->
|
||||
<a-tab-pane :key="2"
|
||||
<a-tab-pane :key="GrantKey.HOST_GROUP_USER"
|
||||
v-permission="['asset:host-group:grant']"
|
||||
title="主机分组授权(用户)">
|
||||
<host-group-user-grant />
|
||||
@@ -28,33 +28,31 @@
|
||||
</script>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref, onBeforeMount, onUnmounted } from 'vue';
|
||||
import { onBeforeMount, onUnmounted, ref } from 'vue';
|
||||
import { useCacheStore } from '@/store';
|
||||
import { Message } from '@arco-design/web-vue';
|
||||
import { getUserList } from '@/api/user/user';
|
||||
import { getRoleList } from '@/api/user/role';
|
||||
import HostGroupRoleGrant from './components/host-group-role-grant.vue';
|
||||
import HostGroupUserGrant from './components/host-group-user-grant.vue';
|
||||
import { GrantKey } from './types/const';
|
||||
import { useRoute } from 'vue-router';
|
||||
|
||||
const render = ref(false);
|
||||
const route = useRoute();
|
||||
const cacheStore = useCacheStore();
|
||||
|
||||
// 加载用户列表
|
||||
const loadUserList = async () => {
|
||||
try {
|
||||
const { data } = await getUserList();
|
||||
// 设置到缓存
|
||||
cacheStore.set('users', data);
|
||||
} catch (e) {
|
||||
Message.error('用户列表加载失败');
|
||||
}
|
||||
};
|
||||
const activeKey = ref();
|
||||
|
||||
// 卸载时清除 cache
|
||||
onUnmounted(() => {
|
||||
cacheStore.reset('users', 'roles', 'hosts', 'hostGroups');
|
||||
});
|
||||
|
||||
// 跳转到指定页
|
||||
onBeforeMount(() => {
|
||||
const key = route.query.key;
|
||||
if (key) {
|
||||
activeKey.value = Number(key);
|
||||
}
|
||||
});
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
@@ -71,6 +69,12 @@
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
:deep(.arco-tabs-pane) {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
:deep(.arco-tabs-tab-title) {
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,10 @@
|
||||
// 创建前缀
|
||||
export const createGroupGroupPrefix = 'create-';
|
||||
// 路由
|
||||
export const GrantRouteName = 'assetGrant';
|
||||
|
||||
// 根id
|
||||
export const rootId = 0;
|
||||
// 授权 key
|
||||
export const GrantKey = {
|
||||
// 主机分组-角色
|
||||
HOST_GROUP_ROLE: 1,
|
||||
// 主机分组-用户
|
||||
HOST_GROUP_USER: 2
|
||||
};
|
||||
|
||||
@@ -35,9 +35,10 @@
|
||||
import useLoading from '@/hooks/loading';
|
||||
import { Message } from '@arco-design/web-vue';
|
||||
import { getHostConfigAll } from '@/api/asset/host';
|
||||
import { useCacheStore } from '@/store';
|
||||
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';
|
||||
|
||||
const { visible, setVisible } = useVisible();
|
||||
@@ -95,6 +96,9 @@
|
||||
};
|
||||
|
||||
onBeforeMount(async () => {
|
||||
// 加载字典值
|
||||
const dictStore = useDictStore();
|
||||
await dictStore.loadKeys([...sshDictKeys]);
|
||||
// 加载主机秘钥
|
||||
await fetchHostKeys();
|
||||
// 加载主机身份
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<a-card class="general-card"
|
||||
:body-style="{ padding: config.status === 1 ? '' : '0' }">
|
||||
:body-style="{ padding: config.status === EnabledStatus.ENABLED ? '' : '0' }">
|
||||
<!-- 标题 -->
|
||||
<template #title>
|
||||
<div class="config-title-wrapper">
|
||||
@@ -140,7 +140,7 @@
|
||||
<script lang="ts" setup>
|
||||
import type { FieldRule } from '@arco-design/web-vue';
|
||||
import type { HostSshConfig } from './types/const';
|
||||
import { ref, watch } from 'vue';
|
||||
import { reactive, ref, watch } from 'vue';
|
||||
import { updateHostConfigStatus, updateHostConfig } from '@/api/asset/host';
|
||||
import { authTypeKey, AuthType } from './types/const';
|
||||
import rules from './types/form.rules';
|
||||
@@ -149,6 +149,7 @@
|
||||
import { useDictStore } from '@/store';
|
||||
import HostKeySelector from '@/components/asset/host-key/host-key-selector.vue';
|
||||
import HostIdentitySelector from '@/components/asset/host-identity/host-identity-selector.vue';
|
||||
import { EnabledStatus } from '@/types/const';
|
||||
|
||||
const { loading, setLoading } = useLoading();
|
||||
const { toOptions } = useDictStore();
|
||||
@@ -159,7 +160,7 @@
|
||||
|
||||
const emits = defineEmits(['submitted']);
|
||||
|
||||
const config = ref({
|
||||
const config = reactive({
|
||||
status: undefined,
|
||||
version: undefined,
|
||||
});
|
||||
@@ -182,8 +183,8 @@
|
||||
|
||||
// 监听数据变化
|
||||
watch(() => props.content, (v: any) => {
|
||||
config.value.status = v?.status;
|
||||
config.value.version = v?.version;
|
||||
config.status = v?.status;
|
||||
config.version = v?.version;
|
||||
resetConfig();
|
||||
});
|
||||
|
||||
@@ -221,9 +222,9 @@
|
||||
return updateHostConfigStatus({
|
||||
id: props?.content?.id,
|
||||
status: e,
|
||||
version: config.value.version
|
||||
version: config.version
|
||||
}).then(({ data }) => {
|
||||
config.value.version = data;
|
||||
config.version = data;
|
||||
setLoading(false);
|
||||
return true;
|
||||
}).catch(() => {
|
||||
@@ -250,10 +251,10 @@
|
||||
setLoading(true);
|
||||
const { data } = await updateHostConfig({
|
||||
id: props?.content?.id,
|
||||
version: config.value.version,
|
||||
version: config.version,
|
||||
config: JSON.stringify(formModel.value)
|
||||
});
|
||||
config.value.version = data;
|
||||
config.version = data;
|
||||
setLoading(false);
|
||||
Message.success('修改成功');
|
||||
// 回调 props
|
||||
|
||||
@@ -26,3 +26,6 @@ export const AuthType = {
|
||||
|
||||
// 主机验证方式 字典项
|
||||
export const authTypeKey = 'hostAuthTypeType';
|
||||
|
||||
// 加载的字典值
|
||||
export const dictKeys = ['hostAuthTypeType'];
|
||||
|
||||
@@ -8,7 +8,8 @@
|
||||
:pagination="pagination"
|
||||
:card-layout-cols="cardColLayout"
|
||||
:filter-count="filterCount"
|
||||
:handle-visible="{ disableAdd: true }"
|
||||
:add-permission="['asset:host:create']"
|
||||
@add="emits('openAdd')"
|
||||
@reset="reset"
|
||||
@search="fetchCardData"
|
||||
@page-change="fetchCardData">
|
||||
@@ -16,22 +17,31 @@
|
||||
<template #leftHandle>
|
||||
<!-- 主机分组 -->
|
||||
<a-button v-permission="['asset:host-group:update']"
|
||||
class="click-icon-wrapper card-header-icon-wrapper"
|
||||
type="primary"
|
||||
title="分组配置"
|
||||
class="card-header-icon-wrapper"
|
||||
@click="emits('openHostGroup')">
|
||||
主机分组
|
||||
<template #icon>
|
||||
<icon-layers />
|
||||
</template>
|
||||
</a-button>
|
||||
<!-- 创建 -->
|
||||
<div v-permission="['asset:host:create']"
|
||||
class="click-icon-wrapper card-header-icon-wrapper"
|
||||
title="创建"
|
||||
@click="emits('openAdd')">
|
||||
<icon-plus />
|
||||
</div>
|
||||
<!-- 角色授权 -->
|
||||
<a-button v-permission="['asset:host-group:grant']"
|
||||
class="card-header-icon-wrapper"
|
||||
@click="$router.push({ name: GrantRouteName, query: { key: GrantKey.HOST_GROUP_ROLE }})">
|
||||
角色授权
|
||||
<template #icon>
|
||||
<icon-user-group />
|
||||
</template>
|
||||
</a-button>
|
||||
<!-- 用户授权 -->
|
||||
<a-button v-permission="['asset:host-group:grant']"
|
||||
class="card-header-icon-wrapper"
|
||||
@click="$router.push({ name: GrantRouteName, query: { key: GrantKey.HOST_GROUP_USER }})">
|
||||
用户授权
|
||||
<template #icon>
|
||||
<icon-user />
|
||||
</template>
|
||||
</a-button>
|
||||
</template>
|
||||
<!-- 过滤条件 -->
|
||||
<template #filterContent>
|
||||
@@ -173,6 +183,7 @@
|
||||
import { tagColor } from '../types/const';
|
||||
import TagMultiSelector from '@/components/meta/tag/tag-multi-selector.vue';
|
||||
import useCopy from '@/hooks/copy';
|
||||
import { GrantKey, GrantRouteName } from '@/views/asset/grant/types/const';
|
||||
|
||||
const emits = defineEmits(['openAdd', 'openUpdate', 'openUpdateConfig', 'openHostGroup']);
|
||||
|
||||
|
||||
@@ -71,6 +71,24 @@
|
||||
<icon-layers />
|
||||
</template>
|
||||
</a-button>
|
||||
<!-- 角色授权 -->
|
||||
<a-button type="primary"
|
||||
v-permission="['asset:host-group:grant']"
|
||||
@click="$router.push({ name: GrantRouteName, query: { key: GrantKey.HOST_GROUP_ROLE }})">
|
||||
角色授权
|
||||
<template #icon>
|
||||
<icon-user-group />
|
||||
</template>
|
||||
</a-button>
|
||||
<!-- 用户授权 -->
|
||||
<a-button type="primary"
|
||||
v-permission="['asset:host-group:grant']"
|
||||
@click="$router.push({ name: GrantRouteName, query: { key: GrantKey.HOST_GROUP_USER }})">
|
||||
用户授权
|
||||
<template #icon>
|
||||
<icon-user />
|
||||
</template>
|
||||
</a-button>
|
||||
<!-- 新增 -->
|
||||
<a-button type="primary"
|
||||
v-permission="['asset:host:create']"
|
||||
@@ -183,6 +201,7 @@
|
||||
import useFavorite from '@/hooks/favorite';
|
||||
import { dataColor } from '@/utils';
|
||||
import TagMultiSelector from '@/components/meta/tag/tag-multi-selector.vue';
|
||||
import { GrantKey, GrantRouteName } from '@/views/asset/grant/types/const';
|
||||
|
||||
const tagSelector = ref();
|
||||
const tableRenderData = ref<HostQueryResponse[]>([]);
|
||||
|
||||
@@ -33,9 +33,8 @@
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { computed, ref, onBeforeMount, onUnmounted } from 'vue';
|
||||
import { useAppStore, useCacheStore, useDictStore } from '@/store';
|
||||
import { useAppStore, useCacheStore } from '@/store';
|
||||
import { getTagList } from '@/api/meta/tag';
|
||||
import { dictKeys } from './types/const';
|
||||
import { Message } from '@arco-design/web-vue';
|
||||
import HostTable from './components/host-table.vue';
|
||||
import HostCardList from './components/host-card-list.vue';
|
||||
@@ -87,9 +86,6 @@
|
||||
onBeforeMount(async () => {
|
||||
// 加载 tags
|
||||
await loadTags();
|
||||
// 加载字典值
|
||||
const dictStore = useDictStore();
|
||||
await dictStore.loadKeys(dictKeys);
|
||||
render.value = true;
|
||||
});
|
||||
|
||||
|
||||
@@ -15,6 +15,3 @@ export const tagColor = [
|
||||
'pinkpurple',
|
||||
'magenta'
|
||||
];
|
||||
|
||||
// 加载的字典值
|
||||
export const dictKeys = ['hostAuthTypeType'];
|
||||
|
||||
Reference in New Issue
Block a user