mirror of
https://github.com/veops/cmdb.git
synced 2025-08-08 16:17:56 +08:00
feat(ui): topology view (#525)
This commit is contained in:
@@ -2,11 +2,12 @@ import { axios } from '@/utils/request'
|
||||
|
||||
const urlPrefix = '/v0.1'
|
||||
|
||||
export function searchCI(params) {
|
||||
export function searchCI(params, isShowMessage = true) {
|
||||
return axios({
|
||||
url: urlPrefix + `/ci/s`,
|
||||
method: 'GET',
|
||||
params: params
|
||||
params: params,
|
||||
isShowMessage
|
||||
})
|
||||
}
|
||||
|
||||
|
110
cmdb-ui/src/modules/cmdb/api/topology.js
Normal file
110
cmdb-ui/src/modules/cmdb/api/topology.js
Normal file
@@ -0,0 +1,110 @@
|
||||
import { axios } from '@/utils/request'
|
||||
|
||||
const urlPrefix = '/v0.1'
|
||||
|
||||
export function getTopoGroups() {
|
||||
return axios({
|
||||
url: `${urlPrefix}/topology_views`,
|
||||
method: 'GET',
|
||||
})
|
||||
}
|
||||
|
||||
export function getTopoView(_id) {
|
||||
return axios({
|
||||
url: `${urlPrefix}/topology_views/${_id}`,
|
||||
method: 'GET',
|
||||
})
|
||||
}
|
||||
|
||||
export function postTopoGroup(data) {
|
||||
return axios({
|
||||
url: `${urlPrefix}/topology_views/groups`,
|
||||
method: 'POST',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
export function putTopoGroupByGId(gid, data) {
|
||||
return axios({
|
||||
url: `${urlPrefix}/topology_views/groups/${gid}`,
|
||||
method: 'PUT',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
export function putTopoGroupsOrder(data) {
|
||||
return axios({
|
||||
url: `${urlPrefix}/topology_views/groups/order`,
|
||||
method: 'PUT',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
export function deleteTopoGroup(gid, data) {
|
||||
return axios({
|
||||
url: `${urlPrefix}/topology_views/groups/${gid}`,
|
||||
method: 'DELETE',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
export function addTopoView(data) {
|
||||
return axios({
|
||||
url: `${urlPrefix}/topology_views`,
|
||||
method: 'POST',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
export function updateTopoView(_id, data) {
|
||||
return axios({
|
||||
url: `${urlPrefix}/topology_views/${_id}`,
|
||||
method: 'PUT',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
export function deleteTopoView(_id) {
|
||||
return axios({
|
||||
url: `${urlPrefix}/topology_views/${_id}`,
|
||||
method: 'DELETE',
|
||||
})
|
||||
}
|
||||
|
||||
export function getRelationsByTypeId(_id) {
|
||||
return axios({
|
||||
url: `${urlPrefix}/topology_views/relations/ci_types/${_id}`,
|
||||
method: 'GET',
|
||||
})
|
||||
}
|
||||
|
||||
export function previewTopoView(params) {
|
||||
return axios({
|
||||
url: `${urlPrefix}/topology_views/preview`,
|
||||
method: 'POST',
|
||||
data: params,
|
||||
})
|
||||
}
|
||||
|
||||
export function showTopoView(_id) {
|
||||
return axios({
|
||||
url: `${urlPrefix}/topology_views/${_id}/view`,
|
||||
method: 'GET',
|
||||
})
|
||||
}
|
||||
|
||||
export function grantTopologyView(viewId, rid, data) {
|
||||
return axios({
|
||||
url: `/v0.1/topology_views/${viewId}/roles/${rid}/grant`,
|
||||
method: 'POST',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
export function revokeTopologyView(viewId, rid, data) {
|
||||
return axios({
|
||||
url: `/v0.1/topology_views/${viewId}/roles/${rid}/revoke`,
|
||||
method: 'POST',
|
||||
data: data
|
||||
})
|
||||
}
|
@@ -57,6 +57,20 @@
|
||||
:addedRids="addedRids"
|
||||
/>
|
||||
</template>
|
||||
<template v-if="cmdbGrantType.includes('TopologyView')">
|
||||
<div class="cmdb-grant-title">{{ resourceTypeName }}{{ $t('cmdb.components.perm') }}</div>
|
||||
<TopologyViewGrant
|
||||
:resourceTypeName="resourceTypeName"
|
||||
:tableData="tableData"
|
||||
:viewId="CITypeId"
|
||||
grantType="TopologyView"
|
||||
@grantDepart="grantDepart"
|
||||
@grantRole="grantRole"
|
||||
@getTableData="getTableData"
|
||||
ref="grantTopologyView"
|
||||
:addedRids="addedRids"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<GrantModal ref="grantModal" @handleOk="handleOk" />
|
||||
<ReadGrantModal ref="readGrantModal" :CITypeId="CITypeId" @updateTableDataRead="updateTableDataRead" />
|
||||
@@ -72,11 +86,12 @@ import { getResourcePerms } from '@/modules/acl/api/permission'
|
||||
import GrantModal from './grantModal.vue'
|
||||
import ReadGrantModal from './readGrantModal'
|
||||
import RelationViewGrant from './relationViewGrant.vue'
|
||||
import TopologyViewGrant from './topologyViewGrant.vue'
|
||||
import { getCITypeGroupById, ciTypeFilterPermissions } from '../../api/CIType'
|
||||
|
||||
export default {
|
||||
name: 'GrantComp',
|
||||
components: { CiTypeGrant, TypeRelationGrant, RelationViewGrant, GrantModal, ReadGrantModal },
|
||||
components: { CiTypeGrant, TypeRelationGrant, RelationViewGrant, TopologyViewGrant, GrantModal, ReadGrantModal },
|
||||
props: {
|
||||
CITypeId: {
|
||||
type: Number,
|
||||
@@ -291,6 +306,20 @@ export default {
|
||||
})
|
||||
)
|
||||
}
|
||||
if (grantType === 'TopologyView') {
|
||||
this.tableData.unshift(
|
||||
...rids.map(({ rid, name }) => {
|
||||
return {
|
||||
rid,
|
||||
name,
|
||||
read: false,
|
||||
update: false,
|
||||
delete: false,
|
||||
grant: false,
|
||||
}
|
||||
})
|
||||
)
|
||||
}
|
||||
this.addedRids = rids
|
||||
this.$nextTick(() => {
|
||||
setTimeout(() => {
|
||||
|
@@ -0,0 +1,102 @@
|
||||
<template>
|
||||
<div class="topology-view-grant">
|
||||
<vxe-table
|
||||
ref="xTable"
|
||||
size="mini"
|
||||
stripe
|
||||
class="ops-stripe-table"
|
||||
:data="tableData"
|
||||
:max-height="`${tableHeight}px`"
|
||||
:scroll-y="{enabled: true}"
|
||||
:row-style="(params) => getCurrentRowStyle(params, addedRids)"
|
||||
>
|
||||
<vxe-column field="name"></vxe-column>
|
||||
<vxe-column v-for="col in columns" :key="col" :field="col" :title="permMap[col]">
|
||||
<template #default="{row}">
|
||||
<a-checkbox @change="(e) => handleChange(e, col, row)" v-model="row[col]"></a-checkbox>
|
||||
</template>
|
||||
</vxe-column>
|
||||
</vxe-table>
|
||||
<a-space>
|
||||
<span class="grant-button" @click="grantDepart">{{ $t('cmdb.components.grantUser') }}</span>
|
||||
<span class="grant-button" @click="grantRole">{{ $t('cmdb.components.grantRole') }}</span>
|
||||
</a-space>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { permMap } from './constants.js'
|
||||
import { grantTopologyView, revokeTopologyView } from '@/modules/cmdb/api/topology.js'
|
||||
import { getCurrentRowStyle } from './utils'
|
||||
export default {
|
||||
name: 'TopologyViewGrant',
|
||||
inject: ['loading', 'isModal'],
|
||||
props: {
|
||||
viewId: {
|
||||
type: Number,
|
||||
default: null,
|
||||
},
|
||||
resourceTypeName: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
tableData: {
|
||||
type: Array,
|
||||
default: () => [],
|
||||
},
|
||||
grantType: {
|
||||
type: String,
|
||||
default: 'relation_view',
|
||||
},
|
||||
addedRids: {
|
||||
type: Array,
|
||||
default: () => [],
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
columns: ['read', 'update', 'delete', 'grant'],
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
windowHeight() {
|
||||
return this.$store.state.windowHeight
|
||||
},
|
||||
tableHeight() {
|
||||
if (this.isModal) {
|
||||
return (this.windowHeight - 104) / 2
|
||||
}
|
||||
return (this.windowHeight - 104) / 2 - 116
|
||||
},
|
||||
permMap() {
|
||||
return permMap()
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
getCurrentRowStyle,
|
||||
grantDepart() {
|
||||
this.$emit('grantDepart', this.grantType)
|
||||
},
|
||||
grantRole() {
|
||||
this.$emit('grantRole', this.grantType)
|
||||
},
|
||||
handleChange(e, col, row) {
|
||||
if (e.target.checked) {
|
||||
grantTopologyView(this.viewId, row.rid, { perms: [col], name: this.resourceTypeName }).catch(() => {
|
||||
this.$emit('getTableData')
|
||||
})
|
||||
} else {
|
||||
revokeTopologyView(this.viewId, row.rid, { perms: [col], name: this.resourceTypeName }).catch(() => {
|
||||
this.$emit('getTableData')
|
||||
})
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.topology-view-grant {
|
||||
padding: 10px 0;
|
||||
}
|
||||
</style>
|
@@ -4,6 +4,7 @@ const cmdb_en = {
|
||||
configTable: 'Config Table',
|
||||
menu: {
|
||||
views: 'Views',
|
||||
topologyView: 'Topology Views',
|
||||
resources: 'Resources',
|
||||
config: 'Configuration',
|
||||
backend: 'Management',
|
||||
@@ -563,6 +564,30 @@ if __name__ == "__main__":
|
||||
tree: {
|
||||
tips1: 'Please go to Preference page first to complete your subscription!',
|
||||
subSettings: 'Settings',
|
||||
}
|
||||
},
|
||||
topo: {
|
||||
addTopoView: 'Add Topology View',
|
||||
editTopoView: 'Edit Topology View',
|
||||
addTopoViewInGroup: 'Define topology view under grouping',
|
||||
groupRequired: 'Please select a group first or create a group',
|
||||
viewName: 'Title',
|
||||
viewNamePlaceholder: 'Please enter a title for the topology view',
|
||||
inputNameTips: 'Title is required',
|
||||
centralNodeType: 'Central Node Model',
|
||||
filterInstances: 'Central Node Instances',
|
||||
typeRequired: 'Central Node Model is required',
|
||||
instancesRequired: 'instances are required',
|
||||
path: 'Path',
|
||||
aggregationCount: 'Aggregation Count',
|
||||
aggreationCountTip: 'When the number of child nodes > the number of aggregations, paging display',
|
||||
preview: 'Preivew',
|
||||
noData: 'No data',
|
||||
edit: 'Edit',
|
||||
delete: 'Delete',
|
||||
searchPlaceholder: 'Search topology view',
|
||||
confirmDeleteView: 'Are you sure you want to delete this view ?',
|
||||
noInstancePerm: 'You do not have read permissions for this instance',
|
||||
noPreferenceAttributes: 'This instance has no subscription attributes or no default displayed attributes',
|
||||
},
|
||||
}
|
||||
export default cmdb_en
|
||||
|
@@ -4,6 +4,7 @@ const cmdb_zh = {
|
||||
configTable: '配置表格',
|
||||
menu: {
|
||||
views: '视图',
|
||||
topologyView: '拓扑视图',
|
||||
resources: '资源',
|
||||
config: '配置',
|
||||
backend: '管理',
|
||||
@@ -563,6 +564,30 @@ if __name__ == "__main__":
|
||||
tree: {
|
||||
tips1: '请先到 我的订阅 页面完成订阅!',
|
||||
subSettings: '订阅设置',
|
||||
}
|
||||
},
|
||||
topo: {
|
||||
addTopoView: '新增拓扑视图',
|
||||
editTopoView: '编辑拓扑视图',
|
||||
addTopoViewInGroup: '在分组下定义拓扑视图',
|
||||
groupRequired: '请先选择分组或者创建分组',
|
||||
viewName: '标题',
|
||||
viewNamePlaceholder: '请输入拓扑视图的标题',
|
||||
inputNameTips: '必须输入标题',
|
||||
centralNodeType: '中心节点模型',
|
||||
filterInstances: '中心节点实例',
|
||||
typeRequired: '必须要选择中心节点模型',
|
||||
instancesRequired: '实例必须要选择',
|
||||
path: '路径选择',
|
||||
aggregationCount: '聚合数',
|
||||
aggreationCountTip: '当子节点数 > 聚合数 则进行分页展示',
|
||||
preview: '预览',
|
||||
noData: '没有数据',
|
||||
edit: '编辑',
|
||||
delete: '删除',
|
||||
searchPlaceholder: '搜索拓扑视图',
|
||||
confirmDeleteView: '您确定要删除该视图吗?',
|
||||
noInstancePerm: '您没有该实例的查看权限',
|
||||
noPreferenceAttributes: '该实例没有订阅属性或者没有默认展示的属性',
|
||||
},
|
||||
}
|
||||
export default cmdb_zh
|
||||
|
@@ -16,6 +16,12 @@ const genCmdbRoutes = async () => {
|
||||
meta: { title: 'dashboard', icon: 'ops-cmdb-dashboard', selectedIcon: 'ops-cmdb-dashboard', keepAlive: false },
|
||||
component: () => import('../views/dashboard/index_v2.vue')
|
||||
},
|
||||
{
|
||||
path: '/cmdb/topoviews',
|
||||
name: 'cmdb_topology_views',
|
||||
meta: { title: 'cmdb.menu.topologyView', appName: 'cmdb', icon: 'ops-topology_view', selectedIcon: 'ops-topology_view', keepAlive: false },
|
||||
component: () => import('../views/topology_view/index.vue')
|
||||
},
|
||||
{
|
||||
path: '/cmdb/disabled1',
|
||||
name: 'cmdb_disabled1',
|
||||
|
@@ -689,7 +689,7 @@ export default {
|
||||
content: that.$t('cmdb.ciType.confirmDeleteGroup', { groupName: `${g.name}` }),
|
||||
onOk() {
|
||||
deleteCITypeGroup(g.id).then((res) => {
|
||||
that.$message.info(that.$t('deleteSuccess'))
|
||||
that.$message.success(that.$t('deleteSuccess'))
|
||||
that.loadCITypes(true)
|
||||
})
|
||||
},
|
||||
|
@@ -274,8 +274,8 @@ export default {
|
||||
this.ciTypes = res.ci_types
|
||||
})
|
||||
},
|
||||
getCIType(typeId) {
|
||||
getCIType(typeId).then((res) => {
|
||||
async getCIType(typeId) {
|
||||
await getCIType(typeId).then((res) => {
|
||||
this.ciTypes = res.ci_types
|
||||
})
|
||||
},
|
||||
|
1150
cmdb-ui/src/modules/cmdb/views/topology_view/index.vue
Normal file
1150
cmdb-ui/src/modules/cmdb/views/topology_view/index.vue
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user