diff --git a/cmdb-ui/public/iconfont/demo_index.html b/cmdb-ui/public/iconfont/demo_index.html index b0f71f1..ea98011 100644 --- a/cmdb-ui/public/iconfont/demo_index.html +++ b/cmdb-ui/public/iconfont/demo_index.html @@ -54,6 +54,108 @@
+ +
+ + + {{ $t('cmdb.components.default') }} + + + +
+
+ +
+
+ {{ $t(item.title) }} +
+
+ {{ item.name }} +
+
+
@@ -95,6 +161,7 @@ import _ from 'lodash' import draggable from 'vuedraggable' import { ops_move_icon as OpsMoveIcon } from '@/core/icons' +import { CI_DEFAULT_ATTR } from '@/modules/cmdb/utils/const.js' export default { name: 'AttributesTransfer', @@ -130,10 +197,41 @@ export default { type: Number, default: 400, }, + showDefaultAttr: { + type: Boolean, + default: false, + } }, data() { return { selectedKeys: [], + defaultAttrList: [ + { + title: 'cmdb.components.updater', + name: 'updater', + key: CI_DEFAULT_ATTR.UPDATE_USER + }, + { + title: 'cmdb.components.updateTime', + name: 'update time', + key: CI_DEFAULT_ATTR.UPDATE_TIME + } + ] + } + }, + computed: { + rightDefaultAttrList() { + if (!this.showDefaultAttr) { + return [] + } + return this.defaultAttrList.filter((item) => this.targetKeys.includes(item.key)) + }, + + leftDefaultAttrList() { + if (!this.showDefaultAttr) { + return [] + } + return this.defaultAttrList.filter((item) => !this.targetKeys.includes(item.key)) } }, methods: { @@ -216,6 +314,10 @@ export default { } this.$emit('setFixedList', _fixedList) }, + + filterDefaultAttr(list) { + return this.showDefaultAttr ? list.filter((item) => ![CI_DEFAULT_ATTR.UPDATE_USER, CI_DEFAULT_ATTR.UPDATE_TIME].includes(item.key)) : list + } }, } @@ -296,5 +398,67 @@ export default { } } } + + .default-attr { + .ant-divider { + margin: 7px 0; + padding: 0 15px; + + .ant-divider-inner-text { + padding: 0 6px; + } + } + + &-divider { + font-size: 12px; + color: #86909C; + } + + &-title { + font-size: 14px; + line-height: 14px; + font-weight: 400; + } + + &-name { + font-size: 11px; + line-height: 12px; + color: rgb(163, 163, 163); + } + + &-arrow { + position: absolute; + top: 9px; + display: none; + cursor: pointer; + font-size: 12px; + background-color: #fff; + color: @primary-color; + border-radius: 4px; + width: 12px; + } + + &-item { + padding-left: 34px; + padding-top: 4px; + padding-bottom: 4px; + position: relative; + border-left: solid 2px transparent; + margin-bottom: 6px; + + &-selected { + background-color: #f0f5ff; + border-color: #2f54eb; + } + + &:hover { + background-color: #f0f5ff; + + .default-attr-arrow { + display: inline; + } + } + } + } } diff --git a/cmdb-ui/src/modules/cmdb/components/searchForm/SearchForm.vue b/cmdb-ui/src/modules/cmdb/components/searchForm/SearchForm.vue index bba43a1..afad4bd 100644 --- a/cmdb-ui/src/modules/cmdb/components/searchForm/SearchForm.vue +++ b/cmdb-ui/src/modules/cmdb/components/searchForm/SearchForm.vue @@ -129,6 +129,8 @@ import Treeselect from '@riophae/vue-treeselect' import MetadataDrawer from '../../views/ci/modules/MetadataDrawer.vue' import FilterComp from '@/components/CMDBFilterComp' import { getCITypeGroups } from '../../api/ciTypeGroup' +import { CI_DEFAULT_ATTR } from '@/modules/cmdb/utils/const.js' + export default { name: 'SearchForm', components: { MetadataDrawer, FilterComp, Treeselect }, @@ -176,7 +178,9 @@ export default { return '200px' }, canSearchPreferenceAttrList() { - return this.preferenceAttrList.filter((item) => item.value_type !== '6') + return this.preferenceAttrList.filter((item) => { + return item.value_type !== '6' && ![CI_DEFAULT_ATTR.UPDATE_USER, CI_DEFAULT_ATTR.UPDATE_TIME].includes(item.name) + }) }, }, watch: { diff --git a/cmdb-ui/src/modules/cmdb/components/subscribeSetting/subscribeSetting.vue b/cmdb-ui/src/modules/cmdb/components/subscribeSetting/subscribeSetting.vue index fb5c54a..49a2792 100644 --- a/cmdb-ui/src/modules/cmdb/components/subscribeSetting/subscribeSetting.vue +++ b/cmdb-ui/src/modules/cmdb/components/subscribeSetting/subscribeSetting.vue @@ -29,6 +29,7 @@ :fixedList="fixedList" @setFixedList="setFixedList" :height="windowHeight - 170" + :showDefaultAttr="true" />
{{ $t('cmdb.preference.sub') }} @@ -64,7 +65,7 @@
-
+
{{ attr.title }}
@@ -90,6 +91,8 @@ import { } from '@/modules/cmdb/api/preference' import { getCITypeAttributesByName } from '@/modules/cmdb/api/CITypeAttr' import AttributesTransfer from '../attributesTransfer' +import { CI_DEFAULT_ATTR } from '@/modules/cmdb/utils/const.js' + export default { name: 'SubscribeSetting', components: { AttributesTransfer }, @@ -110,16 +113,32 @@ export default { ...mapState({ windowHeight: (state) => state.windowHeight, }), + treeViewAttrList() { + return this.attrList.filter((item) => ![CI_DEFAULT_ATTR.UPDATE_USER, CI_DEFAULT_ATTR.UPDATE_TIME].includes(item.name)) + } }, methods: { open(ciType = {}, activeKey = '1') { this.ciType = ciType this.activeKey = activeKey + const updatedByKey = CI_DEFAULT_ATTR.UPDATE_USER + const updatedAtKey = CI_DEFAULT_ATTR.UPDATE_TIME + getCITypeAttributesByName(ciType.type_id).then((res) => { - const attributes = res.attributes + const attributes = res.attributes.filter((item) => ![updatedByKey, updatedAtKey].includes(item.name)) + + ;[updatedByKey, updatedAtKey].map((key) => { + attributes.push({ + alias: key, + name: key, + id: key + }) + }) + getSubscribeAttributes(ciType.type_id).then((_res) => { this.instanceSubscribed = _res.is_subscribed const selectedAttrList = _res.attributes.map((item) => item.id.toString()) + const attrList = attributes.map((item) => { return { key: item.id.toString(), @@ -188,9 +207,20 @@ export default { }) }, subInstanceSubmit() { + const customAttr = [] + const defaultAttr = [] + this.selectedAttrList.map((attr) => { + if ([CI_DEFAULT_ATTR.UPDATE_USER, CI_DEFAULT_ATTR.UPDATE_TIME].includes(attr)) { + defaultAttr.push(attr) + } else { + customAttr.push(attr) + } + }) + const selectedAttrList = [...customAttr, ...defaultAttr] + subscribeCIType( this.ciType.type_id, - this.selectedAttrList.map((item) => { + selectedAttrList.map((item) => { return [item, !!this.fixedList.includes(item)] }) ).then((res) => { diff --git a/cmdb-ui/src/modules/cmdb/lang/en.js b/cmdb-ui/src/modules/cmdb/lang/en.js index fc13d7d..9ceb9fb 100644 --- a/cmdb-ui/src/modules/cmdb/lang/en.js +++ b/cmdb-ui/src/modules/cmdb/lang/en.js @@ -24,7 +24,8 @@ const cmdb_en = { operationHistory: 'Operation Audit', relationType: 'Relation Type', ad: 'AutoDiscovery', - cidetail: 'CI Detail' + cidetail: 'CI Detail', + scene: 'Scene' }, ciType: { ciType: 'CIType', @@ -377,6 +378,9 @@ const cmdb_en = { param: 'Parameter{param}', value: 'Value{value}', clear: 'Clear', + updater: 'Update User', + updateTime: 'Update Time', + default: 'Default' }, batch: { downloadFailed: 'Download failed', @@ -757,6 +761,83 @@ if __name__ == "__main__": conditionName: 'Condition Name', path: 'Path', expandCondition: 'Expand Condition', + }, + ipam: { + overview: 'Overview', + addressAssign: 'Address Assign', + ipSearch: 'IP Search', + subnetList: 'Subnet List', + history: 'History Log', + ticket: 'Related Tickets', + addSubnet: 'Add Subnet', + editSubnet: 'Edit Subnet', + addCatalog: 'Add Catalog', + editCatalog: 'Edit Catalog', + catalogName: 'Catalog Name', + editName: 'Edit Name', + editNode: 'Edit Node', + deleteNode: 'Delete Node', + basicInfo: 'Basic Info', + scanRule: 'Scan Rule', + adExecTarget: 'Execute targets', + masterMachineTip: 'The machine where OneMaster is installed', + oneagentIdTips: 'Please enter the hexadecimal OneAgent ID starting with 0x ID', + selectFromCMDBTips: 'Select from CMDB', + adInterval: 'Collection frequency', + cronTips: 'The format is the same as crontab, for example: 0 15 * * 1-5', + masterMachine: 'Master machine', + specifyMachine: 'Specify machine', + specifyMachineTips: 'Please fill in the specify machine!', + cronRequiredTip: 'Acquisition frequency cannot be null', + addressNullTip: ' Please select the leaf node of the left subnet tree first', + addressNullTip2: 'Subnet prefix length must be >= 16', + assignedOnline: 'Assigned Online', + assignedOffline: 'Assigned Offline', + unassignedOnline: 'Unassigned Online', + unused: 'Unused', + allStatus: 'All Status', + editAssignAddress: 'Edit Assign Address', + assign: 'Assign', + recycle: 'Recycle', + assignStatus: 'Assign Status', + reserved: 'Reserved', + assigned: 'Assigned', + recycleTip: 'Confirmed for recycle? After recycling, the status of the segment will be changed to unassigned.', + recycleSuccess: '{ip} Recycled successfully, status changed to: unassigned.', + operationLog: 'Operation Log', + scanLog: 'Scan Log', + updateCatalog: 'Update Catalog', + deleteCatalog: 'Delete Catalog', + updateSubnet: 'Update Subnet', + deleteSubnet: 'Delete Subnet', + revokeAddress: 'Revoke Address', + operateTime: 'Operate Time', + operateUser: 'Operate User', + operateType: 'Operate Type', + subnet: 'Subnet', + description: 'Description', + ipNumber: 'Number of online IP', + startTime: 'Start Time', + endTime: 'End Time', + scanningTime: 'Scanning Time', + viewResult: 'View Result', + scannedIP: 'Scanned IP', + subnetStats: 'Subnet Stats', + addressStats: 'Address Stats', + onlineStats: 'Online Stats', + assignStats: 'Assign Stats', + total: 'Total', + free: 'Free', + unassigned: 'Unassigned', + online: 'Online', + offline: 'Offline', + onlineUsageStats: 'Subnet Online Stats', + subnetName: 'Subnet Name', + addressCount: 'Address Count', + onlineRatio: 'Online Ratio', + scanEnable: 'Scan Enable', + lastScanTime: 'Last Scan Time', + isSuccess: 'Is Success' } } export default cmdb_en diff --git a/cmdb-ui/src/modules/cmdb/lang/zh.js b/cmdb-ui/src/modules/cmdb/lang/zh.js index d65642c..66aaba6 100644 --- a/cmdb-ui/src/modules/cmdb/lang/zh.js +++ b/cmdb-ui/src/modules/cmdb/lang/zh.js @@ -24,7 +24,8 @@ const cmdb_zh = { operationHistory: '操作审计', relationType: '关系类型', ad: '自动发现', - cidetail: 'CI 详情' + cidetail: 'CI 详情', + scene: '场景' }, ciType: { ciType: '模型', @@ -377,6 +378,9 @@ const cmdb_zh = { param: '参数{param}', value: '值{value}', clear: '清空', + updater: '更新人', + updateTime: '更新时间', + default: '默认' }, batch: { downloadFailed: '失败下载', @@ -756,6 +760,83 @@ if __name__ == "__main__": conditionName: '条件命名', path: '路径', expandCondition: '展开条件', + }, + ipam: { + overview: '概览', + addressAssign: '地址分配', + ipSearch: 'IP查询', + subnetList: '子网列表', + history: '历史记录', + ticket: '关联工单', + addSubnet: '新增子网', + editSubnet: '编辑子网', + addCatalog: '新增目录', + editCatalog: '修改目录', + catalogName: '目录名称', + editName: '修改名称', + editNode: '修改节点', + deleteNode: '删除节点', + basicInfo: '基本信息', + scanRule: '扫描规则', + adExecTarget: '执行机器', + masterMachineTip: '安装OneMaster的所在机器', + oneagentIdTips: '请输入以0x开头的16进制OneAgent ID', + selectFromCMDBTips: '从CMDB中选择', + adInterval: '采集频率', + cronTips: '格式同crontab, 例如:0 15 * * 1-5', + masterMachine: 'Master机器', + specifyMachine: '指定机器', + specifyMachineTips: '请填写指定机器!', + cronRequiredTip: '采集频率不能为空', + addressNullTip: '请先选择左侧子网树的叶子节点', + addressNullTip2: '子网前缀长度必须 >= 16', + assignedOnline: '已分配在线', + assignedOffline: '已分配离线', + unassignedOnline: '未分配在线', + unused: '空闲', + allStatus: '全部状态', + editAssignAddress: '编辑分配地址', + assign: '分配', + recycle: '回收', + assignStatus: '分配状态', + reserved: '预留', + assigned: '已分配', + recycleTip: '确认要回收吗?回收后该网段状态变更为:未分配', + recycleSuccess: '{ip} 回收成功,状态变更为: 未分配', + operationLog: '操作记录', + scanLog: '扫描记录', + updateCatalog: '更新目录', + deleteCatalog: '删除目录', + updateSubnet: '修改子网', + deleteSubnet: '删除子网', + revokeAddress: '地址回收', + operateTime: '操作时间', + operateUser: '操作人', + operateType: '操作类型', + subnet: '子网', + description: '描述', + ipNumber: '在线IP地址数', + startTime: '开始时间', + endTime: '结束时间', + scanningTime: '扫描耗时', + viewResult: '查看结果', + scannedIP: '已扫描的IP', + subnetStats: '子网统计', + addressStats: '地址数统计', + onlineStats: '在线统计', + assignStats: '分配统计', + total: '总数', + free: '空闲', + unassigned: '未分配', + online: '在线', + offline: '离线', + onlineUsageStats: '子网在线统计', + subnetName: '子网名称', + addressCount: '地址数', + onlineRatio: '在线率', + scanEnable: '是否扫描', + lastScanTime: '最后扫描时间', + isSuccess: '是否成功' } } export default cmdb_zh diff --git a/cmdb-ui/src/modules/cmdb/router/index.js b/cmdb-ui/src/modules/cmdb/router/index.js index 3ff5a87..d2bc284 100644 --- a/cmdb-ui/src/modules/cmdb/router/index.js +++ b/cmdb-ui/src/modules/cmdb/router/index.js @@ -70,6 +70,17 @@ const genCmdbRoutes = async () => { meta: { title: 'cmdb.menu.cidetail', keepAlive: false }, component: () => import('../views/ci/ciDetailPage.vue') }, + { + path: '/cmdb/disabled4', + name: 'cmdb_disabled4', + meta: { title: 'cmdb.menu.scene', appName: 'cmdb', disabled: true, permission: ['admin', 'cmdb_admin'] }, + }, + { + path: '/cmdb/ipam', + component: () => import('../views/ipam'), + name: 'cmdb_ipam', + meta: { title: 'IPAM', appName: 'cmdb', icon: 'veops-ipam', selectedIcon: 'veops-ipam', keepAlive: false, permission: ['admin', 'cmdb_admin'] } + }, { path: '/cmdb/disabled2', name: 'cmdb_disabled2', diff --git a/cmdb-ui/src/modules/cmdb/utils/const.js b/cmdb-ui/src/modules/cmdb/utils/const.js index 65b1701..9354957 100644 --- a/cmdb-ui/src/modules/cmdb/utils/const.js +++ b/cmdb-ui/src/modules/cmdb/utils/const.js @@ -33,3 +33,8 @@ export const defautValueColor = [ ] export const defaultBGColors = ['#ffccc7', '#ffd8bf', '#ffe7ba', '#fff1b8', '#d9f7be', '#b5f5ec', '#bae7ff', '#d6e4ff', '#efdbff', '#ffd6e7'] + +export const CI_DEFAULT_ATTR = { + UPDATE_USER: '_updated_by', + UPDATE_TIME: '_updated_at' +} diff --git a/cmdb-ui/src/modules/cmdb/utils/helper.js b/cmdb-ui/src/modules/cmdb/utils/helper.js index a6ae527..6892533 100644 --- a/cmdb-ui/src/modules/cmdb/utils/helper.js +++ b/cmdb-ui/src/modules/cmdb/utils/helper.js @@ -2,6 +2,9 @@ import _ from 'lodash' import XLSX from 'xlsx' import XLSXS from 'xlsx-js-style' +import { CI_DEFAULT_ATTR } from './const.js' +import i18n from '@/lang' + export function sum(arr) { if (!arr.length) { return 0 @@ -49,7 +52,10 @@ export function getCITableColumns(data, attrList, width = 1600, height) { const _attrList = _.orderBy(attrList, ['is_fixed'], ['desc']) const columns = [] for (let attr of _attrList) { - const editRender = { name: 'input' } + const editRender = { + name: 'input', + enabled: !attr.is_computed && !attr.sys_computed + } switch (attr.value_type) { case '0': editRender['props'] = { 'type': 'float' } @@ -83,13 +89,35 @@ export function getCITableColumns(data, attrList, width = 1600, height) { delete editRender.props } + + let title = attr.alias || attr.name + let sortable = !!attr.is_sortable + let attr_id = attr.id + + if ([CI_DEFAULT_ATTR.UPDATE_TIME, CI_DEFAULT_ATTR.UPDATE_USER].includes(attr.name)) { + editRender.enabled = false + attr_id = attr.name + + switch (attr.name) { + case CI_DEFAULT_ATTR.UPDATE_USER: + title = i18n.t('cmdb.components.updater') + break; + case CI_DEFAULT_ATTR.UPDATE_TIME: + title = i18n.t('cmdb.components.updateTime') + sortable = true + break; + default: + break; + } + } + columns.push({ - attr_id: attr.id, + attr_id, editRender, - title: attr.alias || attr.name, + title, field: attr.name, value_type: attr.value_type, - sortable: !!attr.is_sortable, + sortable, filters: attr.is_choice ? attr.choice_value : null, choice_builtin: null, width: Math.min(Math.max(100, ...data.map(item => strLength(item[attr.name]))), 350), diff --git a/cmdb-ui/src/modules/cmdb/views/ci/modules/CreateInstanceForm.vue b/cmdb-ui/src/modules/cmdb/views/ci/modules/CreateInstanceForm.vue index 4d2603d..0fad2eb 100644 --- a/cmdb-ui/src/modules/cmdb/views/ci/modules/CreateInstanceForm.vue +++ b/cmdb-ui/src/modules/cmdb/views/ci/modules/CreateInstanceForm.vue @@ -259,7 +259,7 @@ export default { this.attributeList = _attrList.sort((x, y) => y.is_required - x.is_required) await getCITypeGroupById(this.typeId).then((res1) => { const _attributesByGroup = res1.map((g) => { - g.attributes = g.attributes.filter((attr) => !attr.is_computed) + g.attributes = g.attributes.filter((attr) => !attr.is_computed && !attr.sys_computed) return g }) const attrHasGroupIds = [] @@ -268,7 +268,7 @@ export default { attrHasGroupIds.push(...id) }) const otherGroupAttr = this.attributeList.filter( - (attr) => !attrHasGroupIds.includes(attr.id) && !attr.is_computed + (attr) => !attrHasGroupIds.includes(attr.id) && !attr.is_computed && !attr.sys_computed ) if (otherGroupAttr.length) { _attributesByGroup.push({ id: -1, name: this.$t('other'), attributes: otherGroupAttr }) diff --git a/cmdb-ui/src/modules/cmdb/views/ci/modules/ciDetailAttrContent.vue b/cmdb-ui/src/modules/cmdb/views/ci/modules/ciDetailAttrContent.vue index 29d7c7e..b292f27 100644 --- a/cmdb-ui/src/modules/cmdb/views/ci/modules/ciDetailAttrContent.vue +++ b/cmdb-ui/src/modules/cmdb/views/ci/modules/ciDetailAttrContent.vue @@ -178,7 +178,7 @@ - + @@ -267,7 +267,7 @@ export default { async handleCloseEdit() { const newData = this.form.getFieldValue(this.attr.name) if (!_.isEqual(this.ci[this.attr.name], newData)) { - await updateCI(this.ci._id, { [`${this.attr.name}`]: newData }) + await updateCI(this.ci._id, { [`${this.attr.name}`]: newData ?? null }) .then(() => { this.$message.success(this.$t('updateSuccess')) this.$emit('updateCIByself', { [`${this.attr.name}`]: newData }, this.attr.name) diff --git a/cmdb-ui/src/modules/cmdb/views/ci/modules/ciDetailRelation.vue b/cmdb-ui/src/modules/cmdb/views/ci/modules/ciDetailRelation.vue index dbe659c..26280bd 100644 --- a/cmdb-ui/src/modules/cmdb/views/ci/modules/ciDetailRelation.vue +++ b/cmdb-ui/src/modules/cmdb/views/ci/modules/ciDetailRelation.vue @@ -18,7 +18,7 @@ :disabled="!canEdit[parent.id]" @click=" () => { - $refs.addTableModal.openModal({ [`${ci.unique}`]: ci[ci.unique] }, ci._id, parent.id, 'parents') + $refs.addTableModal.openModal({ [`${ci.unique}`]: ci[ci.unique] }, ci._id, parent, 'parents') } " > { const sourceNode = data?.id || null if (type === 'custom:clickLeft') { - searchCIRelation(`root_id=${Number(sourceNode)}&level=1&reverse=1&count=10000`).then((res) => { - this.redrawData(res, sourceNode, 'left') - }) + this.debounceClick(sourceNode, 1) } if (type === 'custom:clickRight') { - searchCIRelation(`root_id=${Number(sourceNode)}&level=1&reverse=0&count=10000`).then((res) => { - this.redrawData(res, sourceNode, 'right') - }) + this.debounceClick(sourceNode, 0) } }) }, + + debounceClick: _.debounce(function(sourceNode, reverse) { + searchCIRelation(`root_id=${Number(sourceNode)}&level=1&reverse=${reverse}&count=10000`).then((res) => { + this.redrawData(res, sourceNode, reverse === 1 ? 'left' : 'right') + }) + }, 300), + setTopoData(data) { const root = document.getElementById('ci-detail-relation-topo') if (root && root?.innerHTML) { diff --git a/cmdb-ui/src/modules/cmdb/views/ci/modules/editAttrsPopover.vue b/cmdb-ui/src/modules/cmdb/views/ci/modules/editAttrsPopover.vue index 9255db8..0a2a7bc 100644 --- a/cmdb-ui/src/modules/cmdb/views/ci/modules/editAttrsPopover.vue +++ b/cmdb-ui/src/modules/cmdb/views/ci/modules/editAttrsPopover.vue @@ -4,6 +4,7 @@ { - const attributes = res.attributes + const attributes = res.attributes.filter((item) => ![updatedByKey, updatedAtKey].includes(item.name)) + ;[updatedByKey, updatedAtKey].map((key) => { + attributes.push({ + alias: key, + name: key, + id: key + }) + }) + getSubscribeAttributes(this.typeId).then((_res) => { const selectedAttrList = _res.attributes.map((item) => item.id.toString()) @@ -71,12 +85,23 @@ export default { handleSubmit() { if (this.selectedAttrList.length) { + const customAttr = [] + const defaultAttr = [] + this.selectedAttrList.map((attr) => { + if ([CI_DEFAULT_ATTR.UPDATE_USER, CI_DEFAULT_ATTR.UPDATE_TIME].includes(attr)) { + defaultAttr.push(attr) + } else { + customAttr.push(attr) + } + }) + const selectedAttrList = [...customAttr, ...defaultAttr] + subscribeCIType( this.typeId, - this.selectedAttrList.map((item) => { + selectedAttrList.map((item) => { return [item, !!this.fixedList.includes(item)] }) - ).then((res) => { + ).then(() => { this.$message.success(this.$t('cmdb.components.subSuccess')) this.visible = false this.$emit('refresh') diff --git a/cmdb-ui/src/modules/cmdb/views/ipam/components/catalogForm.vue b/cmdb-ui/src/modules/cmdb/views/ipam/components/catalogForm.vue new file mode 100644 index 0000000..d3df1c5 --- /dev/null +++ b/cmdb-ui/src/modules/cmdb/views/ipam/components/catalogForm.vue @@ -0,0 +1,99 @@ + + + + + diff --git a/cmdb-ui/src/modules/cmdb/views/ipam/components/ipamTree.vue b/cmdb-ui/src/modules/cmdb/views/ipam/components/ipamTree.vue new file mode 100644 index 0000000..d5bfdf1 --- /dev/null +++ b/cmdb-ui/src/modules/cmdb/views/ipam/components/ipamTree.vue @@ -0,0 +1,317 @@ + + + + + diff --git a/cmdb-ui/src/modules/cmdb/views/ipam/components/subnetForm.vue b/cmdb-ui/src/modules/cmdb/views/ipam/components/subnetForm.vue new file mode 100644 index 0000000..94192a6 --- /dev/null +++ b/cmdb-ui/src/modules/cmdb/views/ipam/components/subnetForm.vue @@ -0,0 +1,445 @@ + + + + + diff --git a/cmdb-ui/src/modules/cmdb/views/ipam/constants.js b/cmdb-ui/src/modules/cmdb/views/ipam/constants.js new file mode 100644 index 0000000..f887e1c --- /dev/null +++ b/cmdb-ui/src/modules/cmdb/views/ipam/constants.js @@ -0,0 +1,3 @@ +export const SUB_NET_CITYPE_NAME = 'ipam_subnet' +export const SCOPE_CITYPE_NAME = 'ipam_scope' +export const ADDRESS_CITYPE_NAME = 'ipam_address' diff --git a/cmdb-ui/src/modules/cmdb/views/ipam/index.vue b/cmdb-ui/src/modules/cmdb/views/ipam/index.vue new file mode 100644 index 0000000..fc75476 --- /dev/null +++ b/cmdb-ui/src/modules/cmdb/views/ipam/index.vue @@ -0,0 +1,296 @@ + + + + + diff --git a/cmdb-ui/src/modules/cmdb/views/ipam/modules/address/assignForm.vue b/cmdb-ui/src/modules/cmdb/views/ipam/modules/address/assignForm.vue new file mode 100644 index 0000000..45ce276 --- /dev/null +++ b/cmdb-ui/src/modules/cmdb/views/ipam/modules/address/assignForm.vue @@ -0,0 +1,284 @@ + + + + + diff --git a/cmdb-ui/src/modules/cmdb/views/ipam/modules/address/constants.js b/cmdb-ui/src/modules/cmdb/views/ipam/modules/address/constants.js new file mode 100644 index 0000000..31dacce --- /dev/null +++ b/cmdb-ui/src/modules/cmdb/views/ipam/modules/address/constants.js @@ -0,0 +1,39 @@ +export const ADDRESS_STATUS = { + ONLINE_ASSIGNED: '0', + ONLINE_UNASSIGNED: '1', + OFFLINE_ASSIGNED: '2', + OFFLINE_UNASSIGNED: '3', +} + +export const STATUS_COLOR = { + [ADDRESS_STATUS.ONLINE_ASSIGNED]: '#00B42A', + [ADDRESS_STATUS.ONLINE_UNASSIGNED]: '#FF7D00', + [ADDRESS_STATUS.OFFLINE_ASSIGNED]: '#2F54EB', + [ADDRESS_STATUS.OFFLINE_UNASSIGNED]: '#A5A9BC' +} + +export const STATUS_LABEL = { + [ADDRESS_STATUS.ONLINE_ASSIGNED]: 'cmdb.ipam.assignedOnline', + [ADDRESS_STATUS.ONLINE_UNASSIGNED]: 'cmdb.ipam.unassignedOnline', + [ADDRESS_STATUS.OFFLINE_ASSIGNED]: 'cmdb.ipam.assignedOffline', + [ADDRESS_STATUS.OFFLINE_UNASSIGNED]: 'cmdb.ipam.unused' +} + +export const STATUS_OPTION = [ + { + value: ADDRESS_STATUS.ONLINE_ASSIGNED, + label: STATUS_LABEL[ADDRESS_STATUS.ONLINE_ASSIGNED], + }, + { + value: ADDRESS_STATUS.ONLINE_UNASSIGNED, + label: STATUS_LABEL[ADDRESS_STATUS.ONLINE_UNASSIGNED], + }, + { + value: ADDRESS_STATUS.OFFLINE_ASSIGNED, + label: STATUS_LABEL[ADDRESS_STATUS.OFFLINE_ASSIGNED], + }, + { + value: ADDRESS_STATUS.OFFLINE_UNASSIGNED, + label: STATUS_LABEL[ADDRESS_STATUS.OFFLINE_UNASSIGNED], + } +] diff --git a/cmdb-ui/src/modules/cmdb/views/ipam/modules/address/gridIP.vue b/cmdb-ui/src/modules/cmdb/views/ipam/modules/address/gridIP.vue new file mode 100644 index 0000000..e327a1c --- /dev/null +++ b/cmdb-ui/src/modules/cmdb/views/ipam/modules/address/gridIP.vue @@ -0,0 +1,399 @@ + + + + + diff --git a/cmdb-ui/src/modules/cmdb/views/ipam/modules/address/index.vue b/cmdb-ui/src/modules/cmdb/views/ipam/modules/address/index.vue new file mode 100644 index 0000000..2413575 --- /dev/null +++ b/cmdb-ui/src/modules/cmdb/views/ipam/modules/address/index.vue @@ -0,0 +1,721 @@ + + + + + diff --git a/cmdb-ui/src/modules/cmdb/views/ipam/modules/address/tableIP.vue b/cmdb-ui/src/modules/cmdb/views/ipam/modules/address/tableIP.vue new file mode 100644 index 0000000..062eb01 --- /dev/null +++ b/cmdb-ui/src/modules/cmdb/views/ipam/modules/address/tableIP.vue @@ -0,0 +1,346 @@ + + + + + diff --git a/cmdb-ui/src/modules/cmdb/views/ipam/modules/history/index.vue b/cmdb-ui/src/modules/cmdb/views/ipam/modules/history/index.vue new file mode 100644 index 0000000..9d3324b --- /dev/null +++ b/cmdb-ui/src/modules/cmdb/views/ipam/modules/history/index.vue @@ -0,0 +1,96 @@ + + + + + diff --git a/cmdb-ui/src/modules/cmdb/views/ipam/modules/history/operation/constants.js b/cmdb-ui/src/modules/cmdb/views/ipam/modules/history/operation/constants.js new file mode 100644 index 0000000..d681084 --- /dev/null +++ b/cmdb-ui/src/modules/cmdb/views/ipam/modules/history/operation/constants.js @@ -0,0 +1,56 @@ +export const OPERATE_TYPE = { + ADD_SCOPE: '0', + UPDATE_SCOPE: '1', + DELETE_SCOPE: '2', + ADD_SUBNET: '3', + UPDATE_SUBNET: '4', + DELETE_SUBNET: '5', + ASSIGN_ADDRESS: '6', + REVOKE_ADDRESS: '7', +} + +export const OPERATE_TYPE_TEXT = { + [OPERATE_TYPE.ADD_SCOPE]: 'cmdb.ipam.addCatalog', + [OPERATE_TYPE.UPDATE_SCOPE]: 'cmdb.ipam.updateCatalog', + [OPERATE_TYPE.DELETE_SCOPE]: 'cmdb.ipam.deleteCatalog', + [OPERATE_TYPE.ADD_SUBNET]: 'cmdb.ipam.addSubnet', + [OPERATE_TYPE.UPDATE_SUBNET]: 'cmdb.ipam.updateSubnet', + [OPERATE_TYPE.DELETE_SUBNET]: 'cmdb.ipam.deleteSubnet', + [OPERATE_TYPE.ASSIGN_ADDRESS]: 'cmdb.ipam.addressAssign', + [OPERATE_TYPE.REVOKE_ADDRESS]: 'cmdb.ipam.revokeAddress', +} + +export const OPERATE_TYPE_COLOR = { + [OPERATE_TYPE.ADD_SCOPE]: { + color: '#2F54EB', + backgroundColor: '#DCF5FF' + }, + [OPERATE_TYPE.UPDATE_SCOPE]: { + color: '#FF7D00', + backgroundColor: '#FFECCF' + }, + [OPERATE_TYPE.DELETE_SCOPE]: { + color: '#FD4C6A', + backgroundColor: '#FFECE8' + }, + [OPERATE_TYPE.ADD_SUBNET]: { + color: '#2F54EB', + backgroundColor: '#DCF5FF' + }, + [OPERATE_TYPE.UPDATE_SUBNET]: { + color: '#FF7D00', + backgroundColor: '#FFECCF' + }, + [OPERATE_TYPE.DELETE_SUBNET]: { + color: '#FD4C6A', + backgroundColor: '#FFECE8' + }, + [OPERATE_TYPE.ASSIGN_ADDRESS]: { + color: '#00B42A', + backgroundColor: '#F6FFED' + }, + [OPERATE_TYPE.REVOKE_ADDRESS]: { + color: '#0AA5A8', + backgroundColor: '#E8FFFB' + }, +} diff --git a/cmdb-ui/src/modules/cmdb/views/ipam/modules/history/operation/index.vue b/cmdb-ui/src/modules/cmdb/views/ipam/modules/history/operation/index.vue new file mode 100644 index 0000000..bbf7a3d --- /dev/null +++ b/cmdb-ui/src/modules/cmdb/views/ipam/modules/history/operation/index.vue @@ -0,0 +1,240 @@ + + + + + diff --git a/cmdb-ui/src/modules/cmdb/views/ipam/modules/history/scan/index.vue b/cmdb-ui/src/modules/cmdb/views/ipam/modules/history/scan/index.vue new file mode 100644 index 0000000..a541e47 --- /dev/null +++ b/cmdb-ui/src/modules/cmdb/views/ipam/modules/history/scan/index.vue @@ -0,0 +1,286 @@ + + + + + diff --git a/cmdb-ui/src/modules/cmdb/views/ipam/modules/ipSearch/index.vue b/cmdb-ui/src/modules/cmdb/views/ipam/modules/ipSearch/index.vue new file mode 100644 index 0000000..fe71354 --- /dev/null +++ b/cmdb-ui/src/modules/cmdb/views/ipam/modules/ipSearch/index.vue @@ -0,0 +1,385 @@ + + + + + diff --git a/cmdb-ui/src/modules/cmdb/views/ipam/modules/overview/index.vue b/cmdb-ui/src/modules/cmdb/views/ipam/modules/overview/index.vue new file mode 100644 index 0000000..5b8086c --- /dev/null +++ b/cmdb-ui/src/modules/cmdb/views/ipam/modules/overview/index.vue @@ -0,0 +1,65 @@ + + + + + diff --git a/cmdb-ui/src/modules/cmdb/views/ipam/modules/overview/stats.vue b/cmdb-ui/src/modules/cmdb/views/ipam/modules/overview/stats.vue new file mode 100644 index 0000000..463199c --- /dev/null +++ b/cmdb-ui/src/modules/cmdb/views/ipam/modules/overview/stats.vue @@ -0,0 +1,212 @@ + + + + + diff --git a/cmdb-ui/src/modules/cmdb/views/ipam/modules/overview/statsChart.vue b/cmdb-ui/src/modules/cmdb/views/ipam/modules/overview/statsChart.vue new file mode 100644 index 0000000..85f06c3 --- /dev/null +++ b/cmdb-ui/src/modules/cmdb/views/ipam/modules/overview/statsChart.vue @@ -0,0 +1,105 @@ + + + + + diff --git a/cmdb-ui/src/modules/cmdb/views/ipam/modules/overview/subnetTable.vue b/cmdb-ui/src/modules/cmdb/views/ipam/modules/overview/subnetTable.vue new file mode 100644 index 0000000..d4eecfc --- /dev/null +++ b/cmdb-ui/src/modules/cmdb/views/ipam/modules/overview/subnetTable.vue @@ -0,0 +1,207 @@ + + + + + diff --git a/cmdb-ui/src/modules/cmdb/views/ipam/modules/subnetList/index.vue b/cmdb-ui/src/modules/cmdb/views/ipam/modules/subnetList/index.vue new file mode 100644 index 0000000..fd89ae4 --- /dev/null +++ b/cmdb-ui/src/modules/cmdb/views/ipam/modules/subnetList/index.vue @@ -0,0 +1,387 @@ + + + + + diff --git a/cmdb-ui/src/modules/cmdb/views/preference/index.vue b/cmdb-ui/src/modules/cmdb/views/preference/index.vue index 494c785..324e997 100644 --- a/cmdb-ui/src/modules/cmdb/views/preference/index.vue +++ b/cmdb-ui/src/modules/cmdb/views/preference/index.vue @@ -233,6 +233,7 @@ import CollapseTransition from '@/components/CollapseTransition' import SubscribeSetting from '../../components/subscribeSetting/subscribeSetting' import { getCIAdcStatistics } from '../../api/ci' import { ops_move_icon as OpsMoveIcon } from '@/core/icons' +import { SUB_NET_CITYPE_NAME, SCOPE_CITYPE_NAME, ADDRESS_CITYPE_NAME } from '../ipam/constants.js' export default { name: 'Preference', @@ -282,8 +283,16 @@ export default { getPreference2(true, true), getCIAdcStatistics(), ]) + + const IPAM_CI = [ + SUB_NET_CITYPE_NAME, + SCOPE_CITYPE_NAME, + ADDRESS_CITYPE_NAME + ] + ciTypeGroup.forEach((group) => { if (group.ci_types && group.ci_types.length) { + group.ci_types = group.ci_types.filter((type) => !IPAM_CI.includes(type.name)) group.ci_types.forEach((type) => { const idx = pref.type_ids.findIndex((p) => p === type.id) if (idx > -1) { @@ -304,10 +313,17 @@ export default { const { self, type_id2users } = pref2 this.self = self this.type_id2users = type_id2users + + const prefGroupTypes = pref.group_types.filter((group) => { + group.ci_types = group?.ci_types?.filter((type) => !IPAM_CI.includes(type?.name)) || [] + return group?.ci_types?.length + }) + const prefTreeTypes = pref?.tree_types?.filter((type) => !IPAM_CI.includes(type?.name)) || [] + const _myPreferences = [ { name: this.$t('cmdb.menu.ciTable'), - groups: pref.group_types, + groups: prefGroupTypes, icon: 'cmdb-ci', type: 'ci', }, @@ -315,7 +331,7 @@ export default { name: this.$t('cmdb.menu.ciTree'), groups: [ { - ci_types: pref.tree_types, + ci_types: prefTreeTypes, name: null, } ], @@ -382,11 +398,13 @@ export default { }) }, resetRoute() { - resetRouter() const roles = store.getters.roles store.dispatch('GenerateRoutes', { roles }, { root: true }).then(() => { - router.addRoutes(store.getters.appRoutes) - this.getCITypes() + resetRouter() + this.$nextTick(() => { + router.addRoutes(store.getters.appRoutes) + this.getCITypes() + }) }) }, diff --git a/cmdb-ui/src/modules/cmdb/views/relation_views/index.vue b/cmdb-ui/src/modules/cmdb/views/relation_views/index.vue index 9ac9359..8e7199b 100644 --- a/cmdb-ui/src/modules/cmdb/views/relation_views/index.vue +++ b/cmdb-ui/src/modules/cmdb/views/relation_views/index.vue @@ -984,7 +984,28 @@ export default { this.batchTreeKey = [] } else { const childTypeId = menuKey - this.$refs.addTableModal.openModal(firstCIObj, firstCIId, childTypeId, 'children', ancestor_ids) + + let typeName = '' + if (this?.relationViews?.id2type?.[childTypeId]) { + typeName = this.relationViews.id2type[childTypeId]?.name || '' + } else { + const node2show_types = this?.relationViews?.views?.[this.viewName]?.node2show_types + const typeId = _tempTree?.[1] + if (node2show_types?.[typeId]?.length) { + const findType = node2show_types[typeId].find((item) => item.id === childTypeId) + typeName = findType?.name || '' + } + } + this.$refs.addTableModal.openModal( + firstCIObj, + firstCIId, + { + id: childTypeId, + name: typeName + }, + 'children', + ancestor_ids + ) } } }, diff --git a/cmdb-ui/src/modules/cmdb/views/relation_views/modules/AddTableModal.vue b/cmdb-ui/src/modules/cmdb/views/relation_views/modules/AddTableModal.vue index 6bc79d2..f9f3234 100644 --- a/cmdb-ui/src/modules/cmdb/views/relation_views/modules/AddTableModal.vue +++ b/cmdb-ui/src/modules/cmdb/views/relation_views/modules/AddTableModal.vue @@ -18,6 +18,7 @@ @refresh="handleSearch" > import _ from 'lodash' -import moment from 'moment' import { mapState } from 'vuex' import ExcelJS from 'exceljs' import FileSaver from 'file-saver' @@ -266,8 +268,7 @@ export default { ciTypeName: this.tabActive || '', }) }, - batchDownload({ checkedKeys }) { - const excel_name = `cmdb-${this.tabActive}-${moment().format('YYYYMMDDHHmmss')}.xlsx` + batchDownload({ checkedKeys, filename }) { const wb = new ExcelJS.Workbook() const tableRef = this.$refs.xTable.getVxetableRef() @@ -341,12 +342,16 @@ export default { const file = new Blob([buffer], { type: 'application/octet-stream', }) - FileSaver.saveAs(file, excel_name) + FileSaver.saveAs(file, `${filename}.xlsx`) }) this.$refs.xTable.getVxetableRef().clearCheckboxRow() this.$refs.xTable.getVxetableRef().clearCheckboxReserve() - } + }, + + onSelectChange() { + console.log('onSelectChange') + }, } }