mirror of https://github.com/veops/cmdb.git
feat(cmdb-ui):i18n
This commit is contained in:
parent
3401cf4a1e
commit
420106ae65
Binary file not shown.
Before Width: | Height: | Size: 85 KiB After Width: | Height: | Size: 30 KiB |
Binary file not shown.
Before Width: | Height: | Size: 9.0 KiB After Width: | Height: | Size: 143 KiB |
|
@ -63,7 +63,7 @@ export default {
|
||||||
updateCI(this.row.ci_id || this.row._id, {
|
updateCI(this.row.ci_id || this.row._id, {
|
||||||
[`${this.column.property}`]: this.default_value_json_right ? this.jsonData : {},
|
[`${this.column.property}`]: this.default_value_json_right ? this.jsonData : {},
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
this.$message.success('保存成功!')
|
this.$message.success(this.$t('saveSuccess'))
|
||||||
this.handleCancel()
|
this.handleCancel()
|
||||||
this.$emit('jsonEditorOk', this.row, this.column, this.default_value_json_right ? this.jsonData : {})
|
this.$emit('jsonEditorOk', this.row, this.column, this.default_value_json_right ? this.jsonData : {})
|
||||||
})
|
})
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
width: '200px',
|
width: '200px',
|
||||||
height: `${height}px`,
|
height: `${height}px`,
|
||||||
}"
|
}"
|
||||||
:titles="['未选属性', '已选属性']"
|
:titles="[$t('cmdb.components.unselectAttributes'), $t('cmdb.components.selectAttributes')]"
|
||||||
:render="(item) => item.title"
|
:render="(item) => item.title"
|
||||||
:targetKeys="targetKeys"
|
:targetKeys="targetKeys"
|
||||||
@change="handleChange"
|
@change="handleChange"
|
||||||
|
@ -16,7 +16,7 @@
|
||||||
:filterOption="filterOption"
|
:filterOption="filterOption"
|
||||||
class="cmdb-transfer"
|
class="cmdb-transfer"
|
||||||
>
|
>
|
||||||
<span slot="notFoundContent">暂无数据</span>
|
<span slot="notFoundContent">{{ $t('noData') }}</span>
|
||||||
<template slot="children" slot-scope="{ props: { direction, filteredItems } }">
|
<template slot="children" slot-scope="{ props: { direction, filteredItems } }">
|
||||||
<div class="ant-transfer-list-content" v-if="direction === 'right'">
|
<div class="ant-transfer-list-content" v-if="direction === 'right'">
|
||||||
<draggable :value="targetKeys" animation="300" @end="dragEnd" :disabled="!isSortable">
|
<draggable :value="targetKeys" animation="300" @end="dragEnd" :disabled="!isSortable">
|
||||||
|
@ -27,10 +27,11 @@
|
||||||
:style="{ height: '38px' }"
|
:style="{ height: '38px' }"
|
||||||
>
|
>
|
||||||
<li
|
<li
|
||||||
:class="{
|
:class="
|
||||||
'ant-transfer-list-content-item': true,
|
`ant-transfer-list-content-item ${
|
||||||
'ant-transfer-list-content-item-selected': selectedKeys.includes(item.key),
|
selectedKeys.includes(item.key) ? 'ant-transfer-list-content-item-selected' : ''
|
||||||
}"
|
}`
|
||||||
|
"
|
||||||
@click="setSelectedKeys(item)"
|
@click="setSelectedKeys(item)"
|
||||||
>
|
>
|
||||||
<OpsMoveIcon class="move-icon" />
|
<OpsMoveIcon class="move-icon" />
|
||||||
|
@ -62,9 +63,11 @@
|
||||||
:style="{ height: '38px' }"
|
:style="{ height: '38px' }"
|
||||||
>
|
>
|
||||||
<li
|
<li
|
||||||
:class="`ant-transfer-list-content-item ${
|
:class="
|
||||||
selectedKeys.includes(item.key) ? 'ant-transfer-list-content-item-selected' : ''
|
`ant-transfer-list-content-item ${
|
||||||
}`"
|
selectedKeys.includes(item.key) ? 'ant-transfer-list-content-item-selected' : ''
|
||||||
|
}`
|
||||||
|
"
|
||||||
@click="setSelectedKeys(item)"
|
@click="setSelectedKeys(item)"
|
||||||
>
|
>
|
||||||
<div class="ant-transfer-list-content-item-text" style="display: inline">
|
<div class="ant-transfer-list-content-item-text" style="display: inline">
|
||||||
|
@ -83,7 +86,7 @@
|
||||||
</template>
|
</template>
|
||||||
</a-transfer>
|
</a-transfer>
|
||||||
<div v-if="hasFooter" :style="{ marginTop: '5px', height: '20px' }">
|
<div v-if="hasFooter" :style="{ marginTop: '5px', height: '20px' }">
|
||||||
<a-button :style="{ float: 'right' }" size="small" @click="handleSubmit" type="primary">确定</a-button>
|
<a-button :style="{ float: 'right' }" size="small" @click="handleSubmit" type="primary">{{ $t('confirm') }}</a-button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
@ -110,12 +113,12 @@ export default {
|
||||||
default: true,
|
default: true,
|
||||||
},
|
},
|
||||||
isSortable: {
|
isSortable: {
|
||||||
// 右侧是否可排序
|
// Is the right side sortable?
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: true,
|
default: true,
|
||||||
},
|
},
|
||||||
isFixable: {
|
isFixable: {
|
||||||
// 右侧是否可固定
|
// Can the right side be fixed?
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: true,
|
default: true,
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,21 +1,30 @@
|
||||||
<template>
|
<template>
|
||||||
<a-modal :visible="visible" title="导出数据" @cancel="handleCancel" okText="导出" @ok="handleOk">
|
<a-modal
|
||||||
|
:visible="visible"
|
||||||
|
:title="$t('cmdb.components.downloadCI')"
|
||||||
|
@cancel="handleCancel"
|
||||||
|
@ok="handleOk"
|
||||||
|
width="700px"
|
||||||
|
>
|
||||||
<a-form :form="form" :label-col="{ span: 6 }" :wrapper-col="{ span: 15 }">
|
<a-form :form="form" :label-col="{ span: 6 }" :wrapper-col="{ span: 15 }">
|
||||||
<a-form-item label="文件名">
|
<a-form-item :label="$t('cmdb.components.filename')">
|
||||||
<a-input
|
<a-input
|
||||||
placeholder="请输入文件名"
|
:placeholder="$t('cmdb.components.filenameInputTips')"
|
||||||
v-decorator="['filename', { rules: [{ required: true, message: '请输入文件名' }] }]"
|
v-decorator="['filename', { rules: [{ required: true, message: $t('cmdb.components.filenameInputTips') }] }]"
|
||||||
/>
|
/>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-form-item label="保存类型">
|
<a-form-item :label="$t('cmdb.components.saveType')">
|
||||||
<a-select
|
<a-select
|
||||||
placeholder="请选择保存类型"
|
:placeholder="$t('cmdb.components.saveTypeTips')"
|
||||||
v-decorator="['type', { rules: [{ required: true, message: '请选择保存类型' }], initialValue: 'xlsx' }]"
|
v-decorator="[
|
||||||
|
'type',
|
||||||
|
{ rules: [{ required: true, message: $t('cmdb.components.saveTypeTips') }], initialValue: 'xlsx' },
|
||||||
|
]"
|
||||||
>
|
>
|
||||||
<a-select-option v-for="item in typeList" :key="item.id" :values="item.id">{{ item.label }}</a-select-option>
|
<a-select-option v-for="item in typeList" :key="item.id" :values="item.id">{{ item.label }}</a-select-option>
|
||||||
</a-select>
|
</a-select>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-form-item label="选择字段">
|
<a-form-item :label="$t('cmdb.ciType.selectAttributes')">
|
||||||
<div
|
<div
|
||||||
:style="{
|
:style="{
|
||||||
paddingLeft: '26px',
|
paddingLeft: '26px',
|
||||||
|
@ -29,7 +38,7 @@
|
||||||
:checked="checkAll"
|
:checked="checkAll"
|
||||||
@change="onCheckAllChange"
|
@change="onCheckAllChange"
|
||||||
:style="{ marginRight: '10px' }"
|
:style="{ marginRight: '10px' }"
|
||||||
/>全选
|
/>{{ $t('checkAll') }}
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
:style="{
|
:style="{
|
||||||
|
@ -76,30 +85,7 @@ export default {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
const typeList = [
|
|
||||||
{
|
|
||||||
id: 'xlsx',
|
|
||||||
label: 'Excel工作簿(*.xlsx)',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'csv',
|
|
||||||
label: 'CSV(逗号分隔)(*.csv)',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'html',
|
|
||||||
label: '网页(*.html)',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'xml',
|
|
||||||
label: 'XML数据(*.xml)',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'txt',
|
|
||||||
label: '文本文件(制表符分隔)(*.txt)',
|
|
||||||
},
|
|
||||||
]
|
|
||||||
return {
|
return {
|
||||||
typeList,
|
|
||||||
visible: false,
|
visible: false,
|
||||||
form: this.$form.createForm(this),
|
form: this.$form.createForm(this),
|
||||||
preferenceAttrList: [],
|
preferenceAttrList: [],
|
||||||
|
@ -109,6 +95,32 @@ export default {
|
||||||
defaultChecked: [],
|
defaultChecked: [],
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
computed: {
|
||||||
|
typeList() {
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
id: 'xlsx',
|
||||||
|
label: this.$t('cmdb.components.xlsx'),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'csv',
|
||||||
|
label: this.$t('cmdb.components.csv'),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'html',
|
||||||
|
label: this.$t('cmdb.components.html'),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'xml',
|
||||||
|
label: this.$t('cmdb.components.xml'),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'txt',
|
||||||
|
label: this.$t('cmdb.components.txt'),
|
||||||
|
},
|
||||||
|
]
|
||||||
|
},
|
||||||
|
},
|
||||||
methods: {
|
methods: {
|
||||||
...mapMutations('cmdbStore', ['SET_IS_TABLE_LOADING']),
|
...mapMutations('cmdbStore', ['SET_IS_TABLE_LOADING']),
|
||||||
open({ preferenceAttrList, ciTypeName = undefined }) {
|
open({ preferenceAttrList, ciTypeName = undefined }) {
|
||||||
|
|
|
@ -25,17 +25,17 @@
|
||||||
</vxe-column>
|
</vxe-column>
|
||||||
<template #empty>
|
<template #empty>
|
||||||
<div v-if="loading()" style="height: 200px; line-height: 200px;color:#2F54EB">
|
<div v-if="loading()" style="height: 200px; line-height: 200px;color:#2F54EB">
|
||||||
<a-icon type="loading" /> 加载中...
|
<a-icon type="loading" /> {{ $t('loading') }}
|
||||||
</div>
|
</div>
|
||||||
<div v-else>
|
<div v-else>
|
||||||
<img :style="{ width: '100px' }" :src="require('@/assets/data_empty.png')" />
|
<img :style="{ width: '100px' }" :src="require('@/assets/data_empty.png')" />
|
||||||
<div>暂无数据</div>
|
<div>{{ $t('noData') }}</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</vxe-table>
|
</vxe-table>
|
||||||
<a-space>
|
<a-space>
|
||||||
<span class="grant-button" @click="grantDepart">授权用户/部门</span>
|
<span class="grant-button" @click="grantDepart">{{ $t('cmdb.components.grantUser') }}</span>
|
||||||
<span class="grant-button" @click="grantRole">授权角色</span>
|
<span class="grant-button" @click="grantRole">{{ $t('cmdb.components.grantRole') }}</span>
|
||||||
</a-space>
|
</a-space>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
@ -95,10 +95,8 @@ export default {
|
||||||
}
|
}
|
||||||
return (this.windowHeight - 104) / 2 - 116
|
return (this.windowHeight - 104) / 2 - 116
|
||||||
},
|
},
|
||||||
},
|
permMap() {
|
||||||
data() {
|
return permMap()
|
||||||
return {
|
|
||||||
permMap,
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
@ -131,8 +129,8 @@ export default {
|
||||||
} else {
|
} else {
|
||||||
const that = this
|
const that = this
|
||||||
this.$confirm({
|
this.$confirm({
|
||||||
title: '警告',
|
title: that.$t('warning'),
|
||||||
content: `确认删除 【${row.name}】 的 【授权】 权限?`,
|
content: that.$t('cmdb.components.confirmRevoke', { name: `${row.name}` }),
|
||||||
onOk() {
|
onOk() {
|
||||||
that.handleChange({ target: { checked: false } }, col, row)
|
that.handleChange({ target: { checked: false } }, col, row)
|
||||||
const _idx = that.tableData.findIndex((item) => item.rid === row.rid)
|
const _idx = that.tableData.findIndex((item) => item.rid === row.rid)
|
||||||
|
|
|
@ -1,11 +1,15 @@
|
||||||
export const permMap = {
|
import i18n from '@/lang'
|
||||||
read: '查看',
|
|
||||||
add: '新增',
|
export const permMap = () => {
|
||||||
create: '新增',
|
return {
|
||||||
update: '修改',
|
read: i18n.t('view'),
|
||||||
delete: '删除',
|
add: i18n.t('new'),
|
||||||
config: '配置',
|
create: i18n.t('new'),
|
||||||
grant: '授权',
|
update: i18n.t('update'),
|
||||||
'read_attr': '查看字段',
|
delete: i18n.t('delete'),
|
||||||
'read_ci': '查看实例'
|
config: i18n.t('cmdb.components.config'),
|
||||||
|
grant: i18n.t('grant'),
|
||||||
|
'read_attr': i18n.t('cmdb.components.readAttribute'),
|
||||||
|
'read_ci': i18n.t('cmdb.components.readCI')
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="cmdb-grant" :style="{ maxHeight: `${windowHeight - 104}px` }">
|
<div class="cmdb-grant" :style="{ maxHeight: `${windowHeight - 104}px` }">
|
||||||
<template v-if="cmdbGrantType.includes('ci_type')">
|
<template v-if="cmdbGrantType.includes('ci_type')">
|
||||||
<div class="cmdb-grant-title">模型权限</div>
|
<div class="cmdb-grant-title">{{ $t('cmdb.components.ciTypeGrant') }}</div>
|
||||||
<CiTypeGrant
|
<CiTypeGrant
|
||||||
:CITypeId="CITypeId"
|
:CITypeId="CITypeId"
|
||||||
:tableData="tableData"
|
:tableData="tableData"
|
||||||
|
@ -18,7 +18,7 @@
|
||||||
cmdbGrantType.includes('ci_type,ci') || (cmdbGrantType.includes('ci') && !cmdbGrantType.includes('ci_type'))
|
cmdbGrantType.includes('ci_type,ci') || (cmdbGrantType.includes('ci') && !cmdbGrantType.includes('ci_type'))
|
||||||
"
|
"
|
||||||
>
|
>
|
||||||
<div class="cmdb-grant-title">实例权限</div>
|
<div class="cmdb-grant-title">{{ $t('cmdb.components.ciGrant') }}</div>
|
||||||
<CiTypeGrant
|
<CiTypeGrant
|
||||||
:CITypeId="CITypeId"
|
:CITypeId="CITypeId"
|
||||||
:tableData="tableData"
|
:tableData="tableData"
|
||||||
|
@ -32,7 +32,7 @@
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
<template v-if="cmdbGrantType.includes('type_relation')">
|
<template v-if="cmdbGrantType.includes('type_relation')">
|
||||||
<div class="cmdb-grant-title">关系权限</div>
|
<div class="cmdb-grant-title">{{ $t('cmdb.components.relationGrant') }}</div>
|
||||||
<TypeRelationGrant
|
<TypeRelationGrant
|
||||||
:typeRelationIds="typeRelationIds"
|
:typeRelationIds="typeRelationIds"
|
||||||
:tableData="tableData"
|
:tableData="tableData"
|
||||||
|
@ -45,7 +45,7 @@
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
<template v-if="cmdbGrantType.includes('relation_view')">
|
<template v-if="cmdbGrantType.includes('relation_view')">
|
||||||
<div class="cmdb-grant-title">{{ resourceTypeName }}权限</div>
|
<div class="cmdb-grant-title">{{ resourceTypeName }}{{ $t('cmdb.components.perm') }}</div>
|
||||||
<RelationViewGrant
|
<RelationViewGrant
|
||||||
:resourceTypeName="resourceTypeName"
|
:resourceTypeName="resourceTypeName"
|
||||||
:tableData="tableData"
|
:tableData="tableData"
|
||||||
|
@ -116,7 +116,7 @@ export default {
|
||||||
attrGroup: [],
|
attrGroup: [],
|
||||||
filerPerimissions: {},
|
filerPerimissions: {},
|
||||||
loading: false,
|
loading: false,
|
||||||
addedRids: [], // 本次新增的rid
|
addedRids: [], // added rid this time
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
@ -203,12 +203,12 @@ export default {
|
||||||
this.tableData = perms
|
this.tableData = perms
|
||||||
this.loading = false
|
this.loading = false
|
||||||
},
|
},
|
||||||
// 授权common-setting中的部门 从中拿到roleid
|
// Grant the department in common-setting and get the roleid from it
|
||||||
grantDepart(grantType) {
|
grantDepart(grantType) {
|
||||||
this.$refs.grantModal.open('depart')
|
this.$refs.grantModal.open('depart')
|
||||||
this.grantType = grantType
|
this.grantType = grantType
|
||||||
},
|
},
|
||||||
// 授权最古老的角色权限
|
// Grant the oldest role permissions
|
||||||
grantRole(grantType) {
|
grantRole(grantType) {
|
||||||
this.$refs.grantModal.open('role')
|
this.$refs.grantModal.open('role')
|
||||||
this.grantType = grantType
|
this.grantType = grantType
|
||||||
|
|
|
@ -26,9 +26,9 @@ export default {
|
||||||
computed: {
|
computed: {
|
||||||
title() {
|
title() {
|
||||||
if (this.type === 'depart') {
|
if (this.type === 'depart') {
|
||||||
return '授权用户/部门'
|
return this.$t('cmdb.components.grantUser')
|
||||||
}
|
}
|
||||||
return '授权角色'
|
return this.$t('cmdb.components.grantRole')
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
|
|
@ -2,9 +2,9 @@
|
||||||
<a-modal :width="680" :title="title" :visible="visible" @ok="handleOk" @cancel="handleCancel">
|
<a-modal :width="680" :title="title" :visible="visible" @ok="handleOk" @cancel="handleCancel">
|
||||||
<CustomRadio
|
<CustomRadio
|
||||||
:radioList="[
|
:radioList="[
|
||||||
{ value: 1, label: '全部' },
|
{ value: 1, label: $t('cmdb.components.all') },
|
||||||
{ value: 2, label: '自定义', layout: 'vertical' },
|
{ value: 2, label: $t('cmdb.components.customize'), layout: 'vertical' },
|
||||||
{ value: 3, label: '无' },
|
{ value: 3, label: $t('cmdb.components.none') },
|
||||||
]"
|
]"
|
||||||
v-model="radioValue"
|
v-model="radioValue"
|
||||||
>
|
>
|
||||||
|
@ -16,7 +16,7 @@
|
||||||
:clearable="true"
|
:clearable="true"
|
||||||
searchable
|
searchable
|
||||||
:options="attrGroup"
|
:options="attrGroup"
|
||||||
placeholder="请选择属性字段"
|
:placeholder="$t('cmdb.ciType.selectAttributes')"
|
||||||
value-consists-of="LEAF_PRIORITY"
|
value-consists-of="LEAF_PRIORITY"
|
||||||
:limit="10"
|
:limit="10"
|
||||||
:limitText="(count) => `+ ${count}`"
|
:limitText="(count) => `+ ${count}`"
|
||||||
|
@ -24,8 +24,8 @@
|
||||||
(node) => {
|
(node) => {
|
||||||
return {
|
return {
|
||||||
id: node.name || -1,
|
id: node.name || -1,
|
||||||
label: node.alias || node.name || '其他',
|
label: node.alias || node.name || $t('other'),
|
||||||
title: node.alias || node.name || '其他',
|
title: node.alias || node.name || $t('other'),
|
||||||
children: node.attributes,
|
children: node.attributes,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -42,7 +42,7 @@
|
||||||
:wrapperCol="{ span: 10 }"
|
:wrapperCol="{ span: 10 }"
|
||||||
ref="form"
|
ref="form"
|
||||||
>
|
>
|
||||||
<a-form-model-item label="名称" prop="name">
|
<a-form-model-item :label="$t('name')" prop="name">
|
||||||
<a-input v-model="form.name" />
|
<a-input v-model="form.name" />
|
||||||
</a-form-model-item>
|
</a-form-model-item>
|
||||||
<FilterComp
|
<FilterComp
|
||||||
|
@ -99,16 +99,16 @@ export default {
|
||||||
name: '',
|
name: '',
|
||||||
},
|
},
|
||||||
rules: {
|
rules: {
|
||||||
name: [{ required: true, message: '请输入自定义筛选条件名' }],
|
name: [{ required: true, message: this.$t('cmdb.components.customizeFilterName') }],
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
title() {
|
title() {
|
||||||
if (this.colType === 'read_attr') {
|
if (this.colType === 'read_attr') {
|
||||||
return '字段权限'
|
return this.$t('cmdb.components.attributeGrant')
|
||||||
}
|
}
|
||||||
return '实例权限'
|
return this.$t('cmdb.components.ciGrant')
|
||||||
},
|
},
|
||||||
attrGroup() {
|
attrGroup() {
|
||||||
return this.provide_attrGroup()
|
return this.provide_attrGroup()
|
||||||
|
|
|
@ -17,8 +17,8 @@
|
||||||
</vxe-column>
|
</vxe-column>
|
||||||
</vxe-table>
|
</vxe-table>
|
||||||
<a-space>
|
<a-space>
|
||||||
<span class="grant-button" @click="grantDepart">授权用户/部门</span>
|
<span class="grant-button" @click="grantDepart">{{ $t('cmdb.components.grantUser') }}</span>
|
||||||
<span class="grant-button" @click="grantRole">授权角色</span>
|
<span class="grant-button" @click="grantRole">{{ $t('cmdb.components.grantRole') }}</span>
|
||||||
</a-space>
|
</a-space>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
@ -51,7 +51,6 @@ export default {
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
permMap,
|
|
||||||
columns: ['read', 'grant'],
|
columns: ['read', 'grant'],
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -65,6 +64,9 @@ export default {
|
||||||
}
|
}
|
||||||
return (this.windowHeight - 104) / 2 - 116
|
return (this.windowHeight - 104) / 2 - 116
|
||||||
},
|
},
|
||||||
|
permMap() {
|
||||||
|
return permMap()
|
||||||
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
getCurrentRowStyle,
|
getCurrentRowStyle,
|
||||||
|
|
|
@ -17,8 +17,8 @@
|
||||||
</vxe-column>
|
</vxe-column>
|
||||||
</vxe-table>
|
</vxe-table>
|
||||||
<a-space>
|
<a-space>
|
||||||
<span class="grant-button" @click="grantDepart">授权用户/部门</span>
|
<span class="grant-button" @click="grantDepart">{{ $t('cmdb.components.grantUser') }}</span>
|
||||||
<span class="grant-button" @click="grantRole">授权角色</span>
|
<span class="grant-button" @click="grantRole">{{ $t('cmdb.components.grantRole') }}</span>
|
||||||
</a-space>
|
</a-space>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
@ -51,7 +51,6 @@ export default {
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
permMap,
|
|
||||||
columns: ['create', 'grant', 'delete'],
|
columns: ['create', 'grant', 'delete'],
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -65,6 +64,9 @@ export default {
|
||||||
}
|
}
|
||||||
return (this.windowHeight - 104) / 2 - 116
|
return (this.windowHeight - 104) / 2 - 116
|
||||||
},
|
},
|
||||||
|
permMap() {
|
||||||
|
return permMap()
|
||||||
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
getCurrentRowStyle,
|
getCurrentRowStyle,
|
||||||
|
|
|
@ -132,7 +132,7 @@ export default {
|
||||||
} else if (color.indexOf('rgb') !== -1) {
|
} else if (color.indexOf('rgb') !== -1) {
|
||||||
hsvObj = this.rgbToHSV(color)
|
hsvObj = this.rgbToHSV(color)
|
||||||
} else {
|
} else {
|
||||||
throw new Error('初始化颜色格式错误,使用#fff或rgb格式')
|
throw new Error(this.$t('cmdb.components.colorPickerError'))
|
||||||
// this.$message.error('颜色格式错误,使用16进制格式')
|
// this.$message.error('颜色格式错误,使用16进制格式')
|
||||||
}
|
}
|
||||||
if (hsvObj) {
|
if (hsvObj) {
|
||||||
|
|
|
@ -15,19 +15,19 @@
|
||||||
:edit-config="isEdit ? { trigger: 'click', mode: 'cell' } : {}"
|
:edit-config="isEdit ? { trigger: 'click', mode: 'cell' } : {}"
|
||||||
>
|
>
|
||||||
<template v-if="isEdit">
|
<template v-if="isEdit">
|
||||||
<vxe-colgroup title="自动发现">
|
<vxe-colgroup :title="$t('cmdb.ciType.autoDiscovery')">
|
||||||
<vxe-column field="name" title="名称" width="100"> </vxe-column>
|
<vxe-column field="name" :title="$t('name')" width="100"> </vxe-column>
|
||||||
<vxe-column field="type" title="类型" width="80"> </vxe-column>
|
<vxe-column field="type" :title="$t('type')" width="80"> </vxe-column>
|
||||||
<vxe-column field="example" title="示例值">
|
<vxe-column field="example" :title="$t('cmdb.components.example')">
|
||||||
<template #default="{row}">
|
<template #default="{row}">
|
||||||
<span v-if="row.type === 'json'">{{ JSON.stringify(row.example) }}</span>
|
<span v-if="row.type === 'json'">{{ JSON.stringify(row.example) }}</span>
|
||||||
<span v-else>{{ row.example }}</span>
|
<span v-else>{{ row.example }}</span>
|
||||||
</template>
|
</template>
|
||||||
</vxe-column>
|
</vxe-column>
|
||||||
<vxe-column field="desc" title="描述"> </vxe-column>
|
<vxe-column field="desc" :title="$t('desc')"> </vxe-column>
|
||||||
</vxe-colgroup>
|
</vxe-colgroup>
|
||||||
<vxe-colgroup title="模型属性">
|
<vxe-colgroup :title="$t('cmdb.ciType.attributes')">
|
||||||
<vxe-column field="attr" title="名称" :edit-render="{}">
|
<vxe-column field="attr" :title="$t('name')" :edit-render="{}">
|
||||||
<template #default="{row}">
|
<template #default="{row}">
|
||||||
{{ row.attr }}
|
{{ row.attr }}
|
||||||
</template>
|
</template>
|
||||||
|
@ -45,15 +45,15 @@
|
||||||
</vxe-colgroup>
|
</vxe-colgroup>
|
||||||
</template>
|
</template>
|
||||||
<template v-else>
|
<template v-else>
|
||||||
<vxe-column field="name" title="名称" width="100"> </vxe-column>
|
<vxe-column field="name" :title="$t('name')" width="100"> </vxe-column>
|
||||||
<vxe-column field="type" title="类型" width="80"> </vxe-column>
|
<vxe-column field="type" :title="$t('type')" width="80"> </vxe-column>
|
||||||
<vxe-column field="example" title="示例值">
|
<vxe-column field="example" :title="$t('cmdb.components.example')">
|
||||||
<template #default="{row}">
|
<template #default="{row}">
|
||||||
<span v-if="row.type === 'object'">{{ JSON.stringify(row.example) }}</span>
|
<span v-if="row.type === 'object'">{{ JSON.stringify(row.example) }}</span>
|
||||||
<span v-else>{{ row.example }}</span>
|
<span v-else>{{ row.example }}</span>
|
||||||
</template>
|
</template>
|
||||||
</vxe-column>
|
</vxe-column>
|
||||||
<vxe-column field="desc" title="描述"> </vxe-column>
|
<vxe-column field="desc" :title="$t('desc')"> </vxe-column>
|
||||||
</template>
|
</template>
|
||||||
</vxe-table>
|
</vxe-table>
|
||||||
</div>
|
</div>
|
||||||
|
@ -61,12 +61,6 @@
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { getHttpCategories, getHttpAttributes, getSnmpAttributes } from '../../api/discovery'
|
import { getHttpCategories, getHttpAttributes, getSnmpAttributes } from '../../api/discovery'
|
||||||
const httpMap = {
|
|
||||||
阿里云: { name: 'aliyun' },
|
|
||||||
腾讯云: { name: 'tencentcloud' },
|
|
||||||
华为云: { name: 'huaweicloud' },
|
|
||||||
AWS: { name: 'aws' },
|
|
||||||
}
|
|
||||||
export default {
|
export default {
|
||||||
name: 'HttpSnmpAD',
|
name: 'HttpSnmpAD',
|
||||||
props: {
|
props: {
|
||||||
|
@ -107,13 +101,21 @@ export default {
|
||||||
const { ruleType, ruleName } = this
|
const { ruleType, ruleName } = this
|
||||||
return { ruleType, ruleName }
|
return { ruleType, ruleName }
|
||||||
},
|
},
|
||||||
|
httpMap() {
|
||||||
|
return {
|
||||||
|
[this.$t('cmdb.components.aliyun')]: { name: 'aliyun' },
|
||||||
|
[this.$t('cmdb.components.tencentcloud')]: { name: 'tencentcloud' },
|
||||||
|
[this.$t('cmdb.components.huaweicloud')]: { name: 'huaweicloud' },
|
||||||
|
AWS: { name: 'aws' },
|
||||||
|
}
|
||||||
|
},
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
currentCate: {
|
currentCate: {
|
||||||
immediate: true,
|
immediate: true,
|
||||||
handler(newVal) {
|
handler(newVal) {
|
||||||
if (newVal) {
|
if (newVal) {
|
||||||
getHttpAttributes(httpMap[`${this.ruleName}`].name, { category: newVal }).then((res) => {
|
getHttpAttributes(this.httpMap[`${this.ruleName}`].name, { category: newVal }).then((res) => {
|
||||||
if (this.isEdit) {
|
if (this.isEdit) {
|
||||||
this.formatTableData(res)
|
this.formatTableData(res)
|
||||||
} else {
|
} else {
|
||||||
|
@ -139,7 +141,7 @@ export default {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
if (ruleType === 'http' && ruleName) {
|
if (ruleType === 'http' && ruleName) {
|
||||||
getHttpCategories(httpMap[`${this.ruleName}`].name).then((res) => {
|
getHttpCategories(this.httpMap[`${this.ruleName}`].name).then((res) => {
|
||||||
this.categories = res
|
this.categories = res
|
||||||
if (res && res.length) {
|
if (res && res.length) {
|
||||||
this.currentCate = res[0]
|
this.currentCate = res[0]
|
||||||
|
|
|
@ -1,199 +1,199 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="notice-content">
|
<div class="notice-content">
|
||||||
<div class="notice-content-main">
|
<div class="notice-content-main">
|
||||||
<Toolbar
|
<Toolbar
|
||||||
:editor="editor"
|
:editor="editor"
|
||||||
:defaultConfig="{
|
:defaultConfig="{
|
||||||
excludeKeys: [
|
excludeKeys: [
|
||||||
'emotion',
|
'emotion',
|
||||||
'group-image',
|
'group-image',
|
||||||
'group-video',
|
'group-video',
|
||||||
'insertTable',
|
'insertTable',
|
||||||
'codeBlock',
|
'codeBlock',
|
||||||
'blockquote',
|
'blockquote',
|
||||||
'fullScreen',
|
'fullScreen',
|
||||||
],
|
],
|
||||||
}"
|
}"
|
||||||
mode="default"
|
mode="default"
|
||||||
/>
|
/>
|
||||||
<Editor class="notice-content-editor" :defaultConfig="editorConfig" mode="simple" @onCreated="onCreated" />
|
<Editor class="notice-content-editor" :defaultConfig="editorConfig" mode="simple" @onCreated="onCreated" />
|
||||||
<div class="notice-content-sidebar">
|
<div class="notice-content-sidebar">
|
||||||
<template v-if="needOld">
|
<template v-if="needOld">
|
||||||
<div class="notice-content-sidebar-divider">变更前</div>
|
<div class="notice-content-sidebar-divider">{{ $t('cmdb.components.beforeChange') }}</div>
|
||||||
<div
|
<div
|
||||||
@dblclick="dblclickSidebar(`old_${attr.name}`, attr.alias || attr.name)"
|
@dblclick="dblclickSidebar(`old_${attr.name}`, attr.alias || attr.name)"
|
||||||
class="notice-content-sidebar-item"
|
class="notice-content-sidebar-item"
|
||||||
v-for="attr in attrList"
|
v-for="attr in attrList"
|
||||||
:key="`old_${attr.id}`"
|
:key="`old_${attr.id}`"
|
||||||
:title="attr.alias || attr.name"
|
:title="attr.alias || attr.name"
|
||||||
>
|
>
|
||||||
{{ attr.alias || attr.name }}
|
{{ attr.alias || attr.name }}
|
||||||
</div>
|
</div>
|
||||||
<div class="notice-content-sidebar-divider">变更后</div>
|
<div class="notice-content-sidebar-divider">{{ $t('cmdb.components.afterChange') }}</div>
|
||||||
</template>
|
</template>
|
||||||
<div
|
<div
|
||||||
@dblclick="dblclickSidebar(attr.name, attr.alias || attr.name)"
|
@dblclick="dblclickSidebar(attr.name, attr.alias || attr.name)"
|
||||||
class="notice-content-sidebar-item"
|
class="notice-content-sidebar-item"
|
||||||
v-for="attr in attrList"
|
v-for="attr in attrList"
|
||||||
:key="attr.id"
|
:key="attr.id"
|
||||||
:title="attr.alias || attr.name"
|
:title="attr.alias || attr.name"
|
||||||
>
|
>
|
||||||
{{ attr.alias || attr.name }}
|
{{ attr.alias || attr.name }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import _ from 'lodash'
|
import _ from 'lodash'
|
||||||
import '@wangeditor/editor/dist/css/style.css'
|
import '@wangeditor/editor/dist/css/style.css'
|
||||||
import { Editor, Toolbar } from '@wangeditor/editor-for-vue'
|
import { Editor, Toolbar } from '@wangeditor/editor-for-vue'
|
||||||
export default {
|
export default {
|
||||||
name: 'NoticeContent',
|
name: 'NoticeContent',
|
||||||
components: { Editor, Toolbar },
|
components: { Editor, Toolbar },
|
||||||
props: {
|
props: {
|
||||||
attrList: {
|
attrList: {
|
||||||
type: Array,
|
type: Array,
|
||||||
default: () => [],
|
default: () => [],
|
||||||
},
|
},
|
||||||
needOld: {
|
needOld: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: false,
|
default: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
editor: null,
|
editor: null,
|
||||||
editorConfig: { placeholder: '请输入通知内容', readOnly: this.readOnly },
|
editorConfig: { placeholder: this.$t('cmdb.components.noticeContentTips'), readOnly: this.readOnly },
|
||||||
content: '',
|
content: '',
|
||||||
defaultParams: [],
|
defaultParams: [],
|
||||||
value2LabelMap: {},
|
value2LabelMap: {},
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
beforeDestroy() {
|
beforeDestroy() {
|
||||||
const editor = this.editor
|
const editor = this.editor
|
||||||
if (editor == null) return
|
if (editor == null) return
|
||||||
editor.destroy() // 组件销毁时,及时销毁编辑器
|
editor.destroy() // When the component is destroyed, destroy the editor in time
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
onCreated(editor) {
|
onCreated(editor) {
|
||||||
this.editor = Object.seal(editor) // 一定要用 Object.seal() ,否则会报错
|
this.editor = Object.seal(editor) // Be sure to use Object.seal(), otherwise an error will be reported
|
||||||
},
|
},
|
||||||
getContent() {
|
getContent() {
|
||||||
const html = _.cloneDeep(this.editor.getHtml())
|
const html = _.cloneDeep(this.editor.getHtml())
|
||||||
const _html = html.replace(
|
const _html = html.replace(
|
||||||
/<span data-w-e-type="attachment" (data-w-e-is-void|data-w-e-is-void="") (data-w-e-is-inline|data-w-e-is-inline="").*?<\/span>/gm,
|
/<span data-w-e-type="attachment" (data-w-e-is-void|data-w-e-is-void="") (data-w-e-is-inline|data-w-e-is-inline="").*?<\/span>/gm,
|
||||||
(value) => {
|
(value) => {
|
||||||
const _match = value.match(/(?<=data-attachment(V|v)alue=").*?(?=")/)
|
const _match = value.match(/(?<=data-attachment(V|v)alue=").*?(?=")/)
|
||||||
return `{{${_match[0]}}}`
|
return `{{${_match[0]}}}`
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
return { body_html: html, body: _html }
|
return { body_html: html, body: _html }
|
||||||
},
|
},
|
||||||
setContent(html) {
|
setContent(html) {
|
||||||
this.editor.setHtml(html)
|
this.editor.setHtml(html)
|
||||||
},
|
},
|
||||||
dblclickSidebar(value, label) {
|
dblclickSidebar(value, label) {
|
||||||
if (!this.readOnly) {
|
if (!this.readOnly) {
|
||||||
this.editor.restoreSelection()
|
this.editor.restoreSelection()
|
||||||
|
|
||||||
const node = {
|
const node = {
|
||||||
type: 'attachment',
|
type: 'attachment',
|
||||||
attachmentValue: value,
|
attachmentValue: value,
|
||||||
attachmentLabel: `${label}`,
|
attachmentLabel: `${label}`,
|
||||||
children: [{ text: '' }],
|
children: [{ text: '' }],
|
||||||
}
|
}
|
||||||
this.editor.insertNode(node)
|
this.editor.insertNode(node)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="less" scoped>
|
<style lang="less" scoped>
|
||||||
@import '~@/style/static.less';
|
@import '~@/style/static.less';
|
||||||
.notice-content {
|
.notice-content {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
& &-main {
|
& &-main {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
align-items: flex-end;
|
align-items: flex-end;
|
||||||
position: relative;
|
position: relative;
|
||||||
.notice-content-editor {
|
.notice-content-editor {
|
||||||
height: 300px;
|
height: 300px;
|
||||||
width: 75%;
|
width: 75%;
|
||||||
border: 1px solid #e4e7ed;
|
border: 1px solid #e4e7ed;
|
||||||
border-top: none;
|
border-top: none;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
.notice-content-sidebar {
|
.notice-content-sidebar {
|
||||||
width: 25%;
|
width: 25%;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
height: 300px;
|
height: 300px;
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
left: 0;
|
left: 0;
|
||||||
border: 1px solid #e4e7ed;
|
border: 1px solid #e4e7ed;
|
||||||
border-top: none;
|
border-top: none;
|
||||||
border-right: none;
|
border-right: none;
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
.notice-content-sidebar-divider {
|
.notice-content-sidebar-divider {
|
||||||
position: sticky;
|
position: sticky;
|
||||||
top: 0;
|
top: 0;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
color: #afafaf;
|
color: #afafaf;
|
||||||
background-color: #fff;
|
background-color: #fff;
|
||||||
line-height: 20px;
|
line-height: 20px;
|
||||||
padding-left: 12px;
|
padding-left: 12px;
|
||||||
&::before,
|
&::before,
|
||||||
&::after {
|
&::after {
|
||||||
content: '';
|
content: '';
|
||||||
position: absolute;
|
position: absolute;
|
||||||
border-top: 1px solid #d1d1d1;
|
border-top: 1px solid #d1d1d1;
|
||||||
top: 50%;
|
top: 50%;
|
||||||
transition: translateY(-50%);
|
transition: translateY(-50%);
|
||||||
}
|
}
|
||||||
&::before {
|
&::before {
|
||||||
left: 3px;
|
left: 3px;
|
||||||
width: 5px;
|
width: 5px;
|
||||||
}
|
}
|
||||||
&::after {
|
&::after {
|
||||||
right: 3px;
|
right: 3px;
|
||||||
width: 78px;
|
width: 78px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.notice-content-sidebar-item:first-child {
|
.notice-content-sidebar-item:first-child {
|
||||||
margin-top: 10px;
|
margin-top: 10px;
|
||||||
}
|
}
|
||||||
.notice-content-sidebar-item {
|
.notice-content-sidebar-item {
|
||||||
line-height: 1.5;
|
line-height: 1.5;
|
||||||
padding: 4px 12px;
|
padding: 4px 12px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
user-select: none;
|
user-select: none;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
&:hover {
|
&:hover {
|
||||||
background-color: #custom_colors[color_2];
|
background-color: #custom_colors[color_2];
|
||||||
color: #custom_colors[color_1];
|
color: #custom_colors[color_1];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<style lang="less">
|
<style lang="less">
|
||||||
@import '~@/style/static.less';
|
@import '~@/style/static.less';
|
||||||
|
|
||||||
.notice-content {
|
.notice-content {
|
||||||
.w-e-bar {
|
.w-e-bar {
|
||||||
background-color: #custom_colors[color_2];
|
background-color: #custom_colors[color_2];
|
||||||
}
|
}
|
||||||
.w-e-text-placeholder {
|
.w-e-text-placeholder {
|
||||||
line-height: 1.5;
|
line-height: 1.5;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
@blur="handleInputConfirm"
|
@blur="handleInputConfirm"
|
||||||
@keyup.enter="handleInputConfirm"
|
@keyup.enter="handleInputConfirm"
|
||||||
/>
|
/>
|
||||||
<a-button v-else type="primary" size="small" ghost @click="showInput">保存筛选条件</a-button>
|
<a-button v-else type="primary" size="small" ghost @click="showInput">{{ $t('cmdb.components.saveQuery') }}</a-button>
|
||||||
</span>
|
</span>
|
||||||
<template v-for="(item, index) in preferenceSearchList.slice(0, 3)">
|
<template v-for="(item, index) in preferenceSearchList.slice(0, 3)">
|
||||||
<span
|
<span
|
||||||
|
@ -26,7 +26,7 @@
|
||||||
<a-tooltip :title="item.name">
|
<a-tooltip :title="item.name">
|
||||||
<span @click="clickPreferenceSearch(item)">{{ `${item.name.slice(0, 6)}...` }}</span>
|
<span @click="clickPreferenceSearch(item)">{{ `${item.name.slice(0, 6)}...` }}</span>
|
||||||
</a-tooltip>
|
</a-tooltip>
|
||||||
<a-popconfirm title="确认删除?" @confirm="deletePreferenceSearch(item)">
|
<a-popconfirm :title="$t('cmdb.ciType.confirmDelete2')" @confirm="deletePreferenceSearch(item)">
|
||||||
<a-icon type="close" />
|
<a-icon type="close" />
|
||||||
</a-popconfirm>
|
</a-popconfirm>
|
||||||
</span>
|
</span>
|
||||||
|
@ -40,7 +40,7 @@
|
||||||
}"
|
}"
|
||||||
>
|
>
|
||||||
<span @click="clickPreferenceSearch(item)">{{ item.name }}</span>
|
<span @click="clickPreferenceSearch(item)">{{ item.name }}</span>
|
||||||
<a-popconfirm title="确认删除?" @confirm="deletePreferenceSearch(item)">
|
<a-popconfirm :title="$t('cmdb.ciType.confirmDelete2')" @confirm="deletePreferenceSearch(item)">
|
||||||
<a-icon type="close" />
|
<a-icon type="close" />
|
||||||
</a-popconfirm>
|
</a-popconfirm>
|
||||||
</span>
|
</span>
|
||||||
|
@ -73,7 +73,7 @@
|
||||||
{{ item.name }}
|
{{ item.name }}
|
||||||
</div>
|
</div>
|
||||||
<a-popconfirm
|
<a-popconfirm
|
||||||
title="确认删除?"
|
:title="$t('cmdb.ciType.confirmDelete2')"
|
||||||
:getPopupContainer="(trigger) => trigger.parentElement"
|
:getPopupContainer="(trigger) => trigger.parentElement"
|
||||||
placement="left"
|
placement="left"
|
||||||
@confirm="
|
@confirm="
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
:limit="1"
|
:limit="1"
|
||||||
:limitText="(count) => `+ ${count}`"
|
:limitText="(count) => `+ ${count}`"
|
||||||
value-consists-of="LEAF_PRIORITY"
|
value-consists-of="LEAF_PRIORITY"
|
||||||
placeholder="模型"
|
:placeholder="$t('cmdb.ciType.ciType')"
|
||||||
@close="closeCiTypeGroup"
|
@close="closeCiTypeGroup"
|
||||||
@open="openCiTypeGroup"
|
@open="openCiTypeGroup"
|
||||||
@input="inputCiTypeGroup"
|
@input="inputCiTypeGroup"
|
||||||
|
@ -23,8 +23,8 @@
|
||||||
(node) => {
|
(node) => {
|
||||||
return {
|
return {
|
||||||
id: node.id || -1,
|
id: node.id || -1,
|
||||||
label: node.alias || node.name || '其他',
|
label: node.alias || node.name || $t('other'),
|
||||||
title: node.alias || node.name || '其他',
|
title: node.alias || node.name || $t('other'),
|
||||||
children: node.ci_types,
|
children: node.ci_types,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -42,7 +42,7 @@
|
||||||
<a-input
|
<a-input
|
||||||
v-model="fuzzySearch"
|
v-model="fuzzySearch"
|
||||||
:style="{ display: 'inline-block', width: '244px' }"
|
:style="{ display: 'inline-block', width: '244px' }"
|
||||||
placeholder="请查找"
|
:placeholder="$t('cmdb.components.pleaseSearch')"
|
||||||
@pressEnter="emitRefresh"
|
@pressEnter="emitRefresh"
|
||||||
class="ops-input ops-input-radius"
|
class="ops-input ops-input-radius"
|
||||||
>
|
>
|
||||||
|
@ -54,7 +54,7 @@
|
||||||
/>
|
/>
|
||||||
<a-tooltip slot="prefix" placement="bottom" :overlayStyle="{ maxWidth: '550px' }">
|
<a-tooltip slot="prefix" placement="bottom" :overlayStyle="{ maxWidth: '550px' }">
|
||||||
<template slot="title">
|
<template slot="title">
|
||||||
1、json属性不能搜索<br />2、搜索内容包括逗号,则需转义 \,<br />3、只搜索索引属性,非索引属性使用条件过滤
|
{{ $t('cmdb.components.ciSearchTips') }}
|
||||||
</template>
|
</template>
|
||||||
<a><a-icon type="question-circle"/></a>
|
<a><a-icon type="question-circle"/></a>
|
||||||
</a-tooltip>
|
</a-tooltip>
|
||||||
|
@ -68,7 +68,7 @@
|
||||||
>
|
>
|
||||||
<div slot="popover_item" class="search-form-bar-filter">
|
<div slot="popover_item" class="search-form-bar-filter">
|
||||||
<a-icon class="search-form-bar-filter-icon" type="filter" />
|
<a-icon class="search-form-bar-filter-icon" type="filter" />
|
||||||
条件过滤
|
{{ $t('cmdb.components.conditionFilter') }}
|
||||||
<a-icon class="search-form-bar-filter-icon" type="down" />
|
<a-icon class="search-form-bar-filter-icon" type="down" />
|
||||||
</div>
|
</div>
|
||||||
</FilterComp>
|
</FilterComp>
|
||||||
|
@ -97,8 +97,8 @@
|
||||||
</a-space>
|
</a-space>
|
||||||
</div>
|
</div>
|
||||||
<a-space>
|
<a-space>
|
||||||
<a-button @click="reset" size="small">重置</a-button>
|
<a-button @click="reset" size="small">{{ $t('reset') }}</a-button>
|
||||||
<a-tooltip title="属性说明" v-if="type === 'relationView'">
|
<a-tooltip :title="$t('cmdb.components.attributeDesc')" v-if="type === 'relationView'">
|
||||||
<a
|
<a
|
||||||
@click="
|
@click="
|
||||||
() => {
|
() => {
|
||||||
|
@ -149,7 +149,7 @@ export default {
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
// 高级搜索 展开/关闭
|
// Advanced Search Expand/Close
|
||||||
advanced: false,
|
advanced: false,
|
||||||
queryParam: {},
|
queryParam: {},
|
||||||
isFocusExpression: false,
|
isFocusExpression: false,
|
||||||
|
@ -163,7 +163,7 @@ export default {
|
||||||
|
|
||||||
computed: {
|
computed: {
|
||||||
placeholder() {
|
placeholder() {
|
||||||
return this.isFocusExpression ? '例:q=hostname:*0.0.0.0*' : '表达式'
|
return this.isFocusExpression ? this.$t('cmdb.components.ciSearchTips2') : this.$t('cmdb.ciType.expr')
|
||||||
},
|
},
|
||||||
width() {
|
width() {
|
||||||
return '200px'
|
return '200px'
|
||||||
|
|
|
@ -11,13 +11,13 @@
|
||||||
>
|
>
|
||||||
<a-tabs v-model="activeKey">
|
<a-tabs v-model="activeKey">
|
||||||
<a-tab-pane key="1">
|
<a-tab-pane key="1">
|
||||||
<span slot="tab"><ops-icon type="cmdb-ci" />资源数据</span>
|
<span slot="tab"><ops-icon type="cmdb-ci" />{{ $t('cmdb.menu.ciTable') }}</span>
|
||||||
<div class="cmdb-subscribe-drawer-container" :style="{ height: `${windowHeight - 60}px` }">
|
<div class="cmdb-subscribe-drawer-container" :style="{ height: `${windowHeight - 60}px` }">
|
||||||
<div class="cmdb-subscribe-drawer-container-title">
|
<div class="cmdb-subscribe-drawer-container-title">
|
||||||
<span>订阅模型:{{ ciType.alias || ciType.name }}</span>
|
<span>{{ $t('cmdb.components.subCIType') }}: {{ ciType.alias || ciType.name }}</span>
|
||||||
<span :style="{ fontWeight: 500, color: instanceSubscribed ? 'green' : 'red' }">{{
|
<span :style="{ fontWeight: 500, color: instanceSubscribed ? 'green' : 'red' }">{{
|
||||||
`(${instanceSubscribed ? '已' : '未'}订阅)`
|
`(${instanceSubscribed ? $t('cmdb.components.already') : $t('cmdb.components.not')}`
|
||||||
}}</span>
|
}}{{ $t('cmdb.components.sub') }})</span>
|
||||||
</div>
|
</div>
|
||||||
<template>
|
<template>
|
||||||
<AttributesTransfer
|
<AttributesTransfer
|
||||||
|
@ -31,22 +31,22 @@
|
||||||
:height="windowHeight - 170"
|
:height="windowHeight - 170"
|
||||||
/>
|
/>
|
||||||
<div class="custom-drawer-bottom-action">
|
<div class="custom-drawer-bottom-action">
|
||||||
<a-button @click="subInstanceSubmit" type="primary">订阅</a-button>
|
<a-button @click="subInstanceSubmit" type="primary">{{ $t('cmdb.preference.sub') }}</a-button>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</div>
|
</div>
|
||||||
</a-tab-pane>
|
</a-tab-pane>
|
||||||
<a-tab-pane key="2" force-render>
|
<a-tab-pane key="2" force-render>
|
||||||
<span slot="tab"><ops-icon type="cmdb-tree" />资源层级</span>
|
<span slot="tab"><ops-icon type="cmdb-tree" />{{ $t('cmdb.menu.ciTree') }}</span>
|
||||||
<div class="cmdb-subscribe-drawer-container" :style="{ height: `${windowHeight - 60}px` }">
|
<div class="cmdb-subscribe-drawer-container" :style="{ height: `${windowHeight - 60}px` }">
|
||||||
<div class="cmdb-subscribe-drawer-container-title">
|
<div class="cmdb-subscribe-drawer-container-title">
|
||||||
<span>订阅模型:{{ ciType.alias || ciType.name }}</span>
|
<span>{{ $t('cmdb.components.subCIType') }}: {{ ciType.alias || ciType.name }}</span>
|
||||||
<span :style="{ fontWeight: 500, color: treeSubscribed ? 'green' : 'red' }">{{
|
<span :style="{ fontWeight: 500, color: treeSubscribed ? 'green' : 'red' }">{{
|
||||||
`(${treeSubscribed ? '已' : '未'}订阅)`
|
`(${treeSubscribed ? $t('cmdb.components.already') : $t('cmdb.components.not')}`
|
||||||
}}</span>
|
}}{{ $t('cmdb.components.sub') }})</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="cmdb-subscribe-drawer-tree-header" :style="{ maxHeight: `${(windowHeight - 170) / 3 - 20}px` }">
|
<div class="cmdb-subscribe-drawer-tree-header" :style="{ maxHeight: `${(windowHeight - 170) / 3 - 20}px` }">
|
||||||
<span v-if="!treeViews.length">请在下方进行选择</span>
|
<span v-if="!treeViews.length">{{ $t('cmdb.components.selectBelow') }}</span>
|
||||||
<div
|
<div
|
||||||
class="cmdb-subscribe-drawer-tree-header-selected"
|
class="cmdb-subscribe-drawer-tree-header-selected"
|
||||||
:style="{ marginLeft: `${18 * index}px` }"
|
:style="{ marginLeft: `${18 * index}px` }"
|
||||||
|
@ -70,7 +70,7 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="custom-drawer-bottom-action">
|
<div class="custom-drawer-bottom-action">
|
||||||
<a-button @click="subTreeSubmit" type="primary">订阅</a-button>
|
<a-button @click="subTreeSubmit" type="primary">{{ $t('cmdb.preference.sub') }}</a-button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</a-tab-pane>
|
</a-tab-pane>
|
||||||
|
@ -179,7 +179,7 @@ export default {
|
||||||
},
|
},
|
||||||
subTreeSubmit() {
|
subTreeSubmit() {
|
||||||
subscribeTreeView(this.ciType.type_id, this.treeViews).then((res) => {
|
subscribeTreeView(this.ciType.type_id, this.treeViews).then((res) => {
|
||||||
this.$message.success('订阅成功')
|
this.$message.success(this.$t('cmdb.components.subSuccess'))
|
||||||
if (this.treeViews.length > 0) {
|
if (this.treeViews.length > 0) {
|
||||||
this.treeSubscribed = true
|
this.treeSubscribed = true
|
||||||
} else {
|
} else {
|
||||||
|
@ -194,7 +194,7 @@ export default {
|
||||||
return [item, !!this.fixedList.includes(item)]
|
return [item, !!this.fixedList.includes(item)]
|
||||||
})
|
})
|
||||||
).then((res) => {
|
).then((res) => {
|
||||||
this.$message.success('订阅成功')
|
this.$message.success(this.$t('cmdb.components.subSuccess'))
|
||||||
this.resetRoute()
|
this.resetRoute()
|
||||||
if (this.selectedAttrList.length > 0) {
|
if (this.selectedAttrList.length > 0) {
|
||||||
this.instanceSubscribed = true
|
this.instanceSubscribed = true
|
||||||
|
|
|
@ -1,144 +1,144 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="authorization-wrapper">
|
<div class="authorization-wrapper">
|
||||||
<div class="authorization-header">
|
<div class="authorization-header">
|
||||||
<a-space>
|
<a-space>
|
||||||
<span>Authorization Type</span>
|
<span>Authorization Type</span>
|
||||||
<a-select size="small" v-model="authorizationType" style="width: 200px" :showSearch="true">
|
<a-select size="small" v-model="authorizationType" style="width: 200px" :showSearch="true">
|
||||||
<a-select-option value="none">
|
<a-select-option value="none">
|
||||||
None
|
None
|
||||||
</a-select-option>
|
</a-select-option>
|
||||||
<a-select-option value="BasicAuth">
|
<a-select-option value="BasicAuth">
|
||||||
Basic Auth
|
Basic Auth
|
||||||
</a-select-option>
|
</a-select-option>
|
||||||
<a-select-option value="Bearer">
|
<a-select-option value="Bearer">
|
||||||
Bearer
|
Bearer
|
||||||
</a-select-option>
|
</a-select-option>
|
||||||
<a-select-option value="APIKey">
|
<a-select-option value="APIKey">
|
||||||
APIKey
|
APIKey
|
||||||
</a-select-option>
|
</a-select-option>
|
||||||
<a-select-option value="OAuth2.0">
|
<a-select-option value="OAuth2.0">
|
||||||
OAuth2.0
|
OAuth2.0
|
||||||
</a-select-option>
|
</a-select-option>
|
||||||
</a-select>
|
</a-select>
|
||||||
</a-space>
|
</a-space>
|
||||||
</div>
|
</div>
|
||||||
<div style="margin-top:10px">
|
<div style="margin-top:10px">
|
||||||
<table v-if="authorizationType === 'BasicAuth'">
|
<table v-if="authorizationType === 'BasicAuth'">
|
||||||
<tr>
|
<tr>
|
||||||
<td><a-input class="authorization-input" v-model="BasicAuth.username" placeholder="用户名" /></td>
|
<td><a-input class="authorization-input" v-model="BasicAuth.username" :placeholder="$t('cmdb.ciType.username')" /></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td><a-input class="authorization-input" v-model="BasicAuth.password" placeholder="密码" /></td>
|
<td><a-input class="authorization-input" v-model="BasicAuth.password" :placeholder="$t('cmdb.ciType.password')" /></td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
<table v-else-if="authorizationType === 'Bearer'">
|
<table v-else-if="authorizationType === 'Bearer'">
|
||||||
<tr>
|
<tr>
|
||||||
<td><a-input class="authorization-input" v-model="Bearer.token" placeholder="token" /></td>
|
<td><a-input class="authorization-input" v-model="Bearer.token" placeholder="token" /></td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
<table v-else-if="authorizationType === 'APIKey'">
|
<table v-else-if="authorizationType === 'APIKey'">
|
||||||
<tr>
|
<tr>
|
||||||
<td><a-input class="authorization-input" v-model="APIKey.key" placeholder="key" /></td>
|
<td><a-input class="authorization-input" v-model="APIKey.key" placeholder="key" /></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td><a-input class="authorization-input" v-model="APIKey.value" placeholder="value" /></td>
|
<td><a-input class="authorization-input" v-model="APIKey.value" placeholder="value" /></td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
<table v-else-if="authorizationType === 'OAuth2.0'">
|
<table v-else-if="authorizationType === 'OAuth2.0'">
|
||||||
<tr>
|
<tr>
|
||||||
<td><a-input class="authorization-input" v-model="OAuth2.client_id" placeholder="client_id" /></td>
|
<td><a-input class="authorization-input" v-model="OAuth2.client_id" placeholder="client_id" /></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
<a-input class="authorization-input" v-model="OAuth2.client_secret" placeholder="client_secret" />
|
<a-input class="authorization-input" v-model="OAuth2.client_secret" placeholder="client_secret" />
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
<a-input
|
<a-input
|
||||||
class="authorization-input"
|
class="authorization-input"
|
||||||
v-model="OAuth2.authorization_base_url"
|
v-model="OAuth2.authorization_base_url"
|
||||||
placeholder="authorization_base_url"
|
placeholder="authorization_base_url"
|
||||||
/>
|
/>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
<a-input class="authorization-input" v-model="OAuth2.token_url" placeholder="token_url" />
|
<a-input class="authorization-input" v-model="OAuth2.token_url" placeholder="token_url" />
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td><a-input class="authorization-input" v-model="OAuth2.redirect_url" placeholder="redirect_url" /></td>
|
<td><a-input class="authorization-input" v-model="OAuth2.redirect_url" placeholder="redirect_url" /></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
<a-input class="authorization-input" v-model="OAuth2.scope" placeholder="scope" />
|
<a-input class="authorization-input" v-model="OAuth2.scope" placeholder="scope" />
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
<a-empty
|
<a-empty
|
||||||
v-else
|
v-else
|
||||||
:image-style="{
|
:image-style="{
|
||||||
height: '60px',
|
height: '60px',
|
||||||
}"
|
}"
|
||||||
>
|
>
|
||||||
<img slot="image" :src="require('@/assets/data_empty.png')" />
|
<img slot="image" :src="require('@/assets/data_empty.png')" />
|
||||||
<span slot="description"> 暂无请求认证 </span>
|
<span slot="description"> {{ $t('cmdb.components.noAuthRequest') }} </span>
|
||||||
</a-empty>
|
</a-empty>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
export default {
|
export default {
|
||||||
name: 'Authorization',
|
name: 'Authorization',
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
authorizationType: 'none',
|
authorizationType: 'none',
|
||||||
BasicAuth: {
|
BasicAuth: {
|
||||||
username: '',
|
username: '',
|
||||||
password: '',
|
password: '',
|
||||||
},
|
},
|
||||||
Bearer: {
|
Bearer: {
|
||||||
token: '',
|
token: '',
|
||||||
},
|
},
|
||||||
APIKey: {
|
APIKey: {
|
||||||
key: '',
|
key: '',
|
||||||
value: '',
|
value: '',
|
||||||
},
|
},
|
||||||
OAuth2: {
|
OAuth2: {
|
||||||
client_id: '',
|
client_id: '',
|
||||||
client_secret: '',
|
client_secret: '',
|
||||||
authorization_base_url: '',
|
authorization_base_url: '',
|
||||||
token_url: '',
|
token_url: '',
|
||||||
redirect_url: '',
|
redirect_url: '',
|
||||||
scope: '',
|
scope: '',
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="less" scoped>
|
<style lang="less" scoped>
|
||||||
.authorization-wrapper {
|
.authorization-wrapper {
|
||||||
table {
|
table {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
border-collapse: collapse;
|
border-collapse: collapse;
|
||||||
}
|
}
|
||||||
table,
|
table,
|
||||||
td,
|
td,
|
||||||
th {
|
th {
|
||||||
border: 1px solid #f3f4f6;
|
border: 1px solid #f3f4f6;
|
||||||
}
|
}
|
||||||
.authorization-input {
|
.authorization-input {
|
||||||
border: none;
|
border: none;
|
||||||
&:focus {
|
&:focus {
|
||||||
box-shadow: none;
|
box-shadow: none;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -1,101 +1,101 @@
|
||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<div class="headers-header">
|
<div class="headers-header">
|
||||||
<span>请求参数</span>
|
<span>{{ $t('cmdb.components.requestParam') }}</span>
|
||||||
<a-space>
|
<a-space>
|
||||||
<a-tooltip title="清空">
|
<a-tooltip :title="$t('cmdb.components.clear')">
|
||||||
<ops-icon
|
<ops-icon
|
||||||
type="icon-xianxing-delete"
|
type="icon-xianxing-delete"
|
||||||
@click="
|
@click="
|
||||||
() => {
|
() => {
|
||||||
headers = [
|
headers = [
|
||||||
{
|
{
|
||||||
id: uuidv4(),
|
id: uuidv4(),
|
||||||
key: '',
|
key: '',
|
||||||
value: '',
|
value: '',
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
"
|
"
|
||||||
/>
|
/>
|
||||||
</a-tooltip>
|
</a-tooltip>
|
||||||
<a-tooltip title="新增">
|
<a-tooltip :title="$t('new')">
|
||||||
<a-icon type="plus" @click="add" />
|
<a-icon type="plus" @click="add" />
|
||||||
</a-tooltip>
|
</a-tooltip>
|
||||||
</a-space>
|
</a-space>
|
||||||
</div>
|
</div>
|
||||||
<div class="headers-box">
|
<div class="headers-box">
|
||||||
<table>
|
<table>
|
||||||
<tr v-for="(item, index) in headers" :key="item.id">
|
<tr v-for="(item, index) in headers" :key="item.id">
|
||||||
<td><a-input class="headers-input" v-model="item.key" :placeholder="`参数${index + 1}`" /></td>
|
<td><a-input class="headers-input" v-model="item.key" :placeholder="$t('cmdb.components.param', { param: `${index + 1}` })" /></td>
|
||||||
<td><a-input class="headers-input" v-model="item.value" :placeholder="`值${index + 1}`" /></td>
|
<td><a-input class="headers-input" v-model="item.value" :placeholder="$t('cmdb.components.value', { value: `${index + 1}` })" /></td>
|
||||||
<td>
|
<td>
|
||||||
<a style="color:red">
|
<a style="color:red">
|
||||||
<ops-icon type="icon-xianxing-delete" @click="deleteParam(index)" />
|
<ops-icon type="icon-xianxing-delete" @click="deleteParam(index)" />
|
||||||
</a>
|
</a>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { v4 as uuidv4 } from 'uuid'
|
import { v4 as uuidv4 } from 'uuid'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'Header',
|
name: 'Header',
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
headers: [
|
headers: [
|
||||||
{
|
{
|
||||||
id: uuidv4(),
|
id: uuidv4(),
|
||||||
key: '',
|
key: '',
|
||||||
value: '',
|
value: '',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
uuidv4,
|
uuidv4,
|
||||||
add() {
|
add() {
|
||||||
this.headers.push({
|
this.headers.push({
|
||||||
id: uuidv4(),
|
id: uuidv4(),
|
||||||
key: '',
|
key: '',
|
||||||
value: '',
|
value: '',
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
deleteParam(index) {
|
deleteParam(index) {
|
||||||
this.headers.splice(index, 1)
|
this.headers.splice(index, 1)
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="less" scoped>
|
<style lang="less" scoped>
|
||||||
.headers-header {
|
.headers-header {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
i {
|
i {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.headers-box {
|
.headers-box {
|
||||||
table {
|
table {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
border-collapse: collapse;
|
border-collapse: collapse;
|
||||||
}
|
}
|
||||||
table,
|
table,
|
||||||
td,
|
td,
|
||||||
th {
|
th {
|
||||||
border: 1px solid #f3f4f6;
|
border: 1px solid #f3f4f6;
|
||||||
}
|
}
|
||||||
.headers-input {
|
.headers-input {
|
||||||
border: none;
|
border: none;
|
||||||
&:focus {
|
&:focus {
|
||||||
box-shadow: none;
|
box-shadow: none;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -1,147 +1,147 @@
|
||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<a-input-group compact>
|
<a-input-group compact>
|
||||||
<treeselect
|
<treeselect
|
||||||
:disable-branch-nodes="true"
|
:disable-branch-nodes="true"
|
||||||
class="custom-treeselect custom-treeselect-bgcAndBorder"
|
class="custom-treeselect custom-treeselect-bgcAndBorder"
|
||||||
:style="{
|
:style="{
|
||||||
'--custom-height': '30px',
|
'--custom-height': '30px',
|
||||||
lineHeight: '30px',
|
lineHeight: '30px',
|
||||||
'--custom-bg-color': '#fff',
|
'--custom-bg-color': '#fff',
|
||||||
'--custom-border': '1px solid #d9d9d9',
|
'--custom-border': '1px solid #d9d9d9',
|
||||||
display: 'inline-block',
|
display: 'inline-block',
|
||||||
width: '100px',
|
width: '100px',
|
||||||
}"
|
}"
|
||||||
v-model="method"
|
v-model="method"
|
||||||
:multiple="false"
|
:multiple="false"
|
||||||
:clearable="false"
|
:clearable="false"
|
||||||
searchable
|
searchable
|
||||||
:options="methodList"
|
:options="methodList"
|
||||||
value-consists-of="LEAF_PRIORITY"
|
value-consists-of="LEAF_PRIORITY"
|
||||||
placeholder="请选择方式"
|
:placeholder="$t('cmdb.components.selectMethods')"
|
||||||
>
|
>
|
||||||
</treeselect>
|
</treeselect>
|
||||||
<a-input :style="{ display: 'inline-block', width: 'calc(100% - 100px)' }" v-model="url" />
|
<a-input :style="{ display: 'inline-block', width: 'calc(100% - 100px)' }" v-model="url" />
|
||||||
</a-input-group>
|
</a-input-group>
|
||||||
<a-tabs>
|
<a-tabs>
|
||||||
<a-tab-pane key="Parameters" tab="Parameters">
|
<a-tab-pane key="Parameters" tab="Parameters">
|
||||||
<Parameters ref="Parameters" />
|
<Parameters ref="Parameters" />
|
||||||
</a-tab-pane>
|
</a-tab-pane>
|
||||||
<a-tab-pane key="Body" tab="Body" force-render>
|
<a-tab-pane key="Body" tab="Body" force-render>
|
||||||
<Body ref="Body" />
|
<Body ref="Body" />
|
||||||
</a-tab-pane>
|
</a-tab-pane>
|
||||||
<a-tab-pane key="Headers" tab="Headers" force-render>
|
<a-tab-pane key="Headers" tab="Headers" force-render>
|
||||||
<Header ref="Header" />
|
<Header ref="Header" />
|
||||||
</a-tab-pane>
|
</a-tab-pane>
|
||||||
<a-tab-pane key="Authorization" tab="Authorization" force-render>
|
<a-tab-pane key="Authorization" tab="Authorization" force-render>
|
||||||
<Authorization ref="Authorization" />
|
<Authorization ref="Authorization" />
|
||||||
</a-tab-pane>
|
</a-tab-pane>
|
||||||
</a-tabs>
|
</a-tabs>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import _ from 'lodash'
|
import _ from 'lodash'
|
||||||
import { v4 as uuidv4 } from 'uuid'
|
import { v4 as uuidv4 } from 'uuid'
|
||||||
import Parameters from './paramaters.vue'
|
import Parameters from './paramaters.vue'
|
||||||
import Body from './body.vue'
|
import Body from './body.vue'
|
||||||
import Header from './header.vue'
|
import Header from './header.vue'
|
||||||
import Authorization from './authorization.vue'
|
import Authorization from './authorization.vue'
|
||||||
export default {
|
export default {
|
||||||
name: 'Webhook',
|
name: 'Webhook',
|
||||||
components: { Parameters, Body, Header, Authorization },
|
components: { Parameters, Body, Header, Authorization },
|
||||||
data() {
|
data() {
|
||||||
const methodList = [
|
const methodList = [
|
||||||
{
|
{
|
||||||
id: 'GET',
|
id: 'GET',
|
||||||
label: 'GET',
|
label: 'GET',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'POST',
|
id: 'POST',
|
||||||
label: 'POST',
|
label: 'POST',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'PUT',
|
id: 'PUT',
|
||||||
label: 'PUT',
|
label: 'PUT',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'DELETE',
|
id: 'DELETE',
|
||||||
label: 'DELETE',
|
label: 'DELETE',
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
return {
|
return {
|
||||||
methodList,
|
methodList,
|
||||||
method: 'GET',
|
method: 'GET',
|
||||||
url: '',
|
url: '',
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
getParams() {
|
getParams() {
|
||||||
const parameters = {}
|
const parameters = {}
|
||||||
this.$refs.Parameters.parameters.forEach((item) => {
|
this.$refs.Parameters.parameters.forEach((item) => {
|
||||||
parameters[item.key] = item.value
|
parameters[item.key] = item.value
|
||||||
})
|
})
|
||||||
let body = this.$refs.Body.jsonData
|
let body = this.$refs.Body.jsonData
|
||||||
try {
|
try {
|
||||||
JSON.parse(body)
|
JSON.parse(body)
|
||||||
body = JSON.parse(body)
|
body = JSON.parse(body)
|
||||||
} catch {}
|
} catch {}
|
||||||
const headers = {}
|
const headers = {}
|
||||||
this.$refs.Header.headers.forEach((item) => {
|
this.$refs.Header.headers.forEach((item) => {
|
||||||
headers[item.key] = item.value
|
headers[item.key] = item.value
|
||||||
})
|
})
|
||||||
let authorization = {}
|
let authorization = {}
|
||||||
const type = this.$refs.Authorization.authorizationType
|
const type = this.$refs.Authorization.authorizationType
|
||||||
if (type !== 'none') {
|
if (type !== 'none') {
|
||||||
if (type === 'OAuth2.0') {
|
if (type === 'OAuth2.0') {
|
||||||
authorization = { ...this.$refs.Authorization['OAuth2'], type }
|
authorization = { ...this.$refs.Authorization['OAuth2'], type }
|
||||||
} else {
|
} else {
|
||||||
authorization = { ...this.$refs.Authorization[type], type }
|
authorization = { ...this.$refs.Authorization[type], type }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const { method, url } = this
|
const { method, url } = this
|
||||||
return { method, url, parameters, body, headers, authorization }
|
return { method, url, parameters, body, headers, authorization }
|
||||||
},
|
},
|
||||||
setParams(params) {
|
setParams(params) {
|
||||||
const { method, url, parameters, body, headers, authorization = {} } = params ?? {}
|
const { method, url, parameters, body, headers, authorization = {} } = params ?? {}
|
||||||
this.method = method
|
this.method = method
|
||||||
this.url = url
|
this.url = url
|
||||||
this.$refs.Parameters.parameters =
|
this.$refs.Parameters.parameters =
|
||||||
Object.keys(parameters).map((key) => {
|
Object.keys(parameters).map((key) => {
|
||||||
return {
|
return {
|
||||||
id: uuidv4(),
|
id: uuidv4(),
|
||||||
key: key,
|
key: key,
|
||||||
value: parameters[key],
|
value: parameters[key],
|
||||||
}
|
}
|
||||||
}) || []
|
}) || []
|
||||||
if (body && Object.prototype.toString.call(body) === '[object Object]') {
|
if (body && Object.prototype.toString.call(body) === '[object Object]') {
|
||||||
this.$refs.Body.jsonData = JSON.stringify(body)
|
this.$refs.Body.jsonData = JSON.stringify(body)
|
||||||
} else {
|
} else {
|
||||||
this.$refs.Body.jsonData = body
|
this.$refs.Body.jsonData = body
|
||||||
}
|
}
|
||||||
this.$refs.Header.headers =
|
this.$refs.Header.headers =
|
||||||
Object.keys(headers).map((key) => {
|
Object.keys(headers).map((key) => {
|
||||||
return {
|
return {
|
||||||
id: uuidv4(),
|
id: uuidv4(),
|
||||||
key: key,
|
key: key,
|
||||||
value: headers[key],
|
value: headers[key],
|
||||||
}
|
}
|
||||||
}) || []
|
}) || []
|
||||||
const { type = 'none' } = authorization
|
const { type = 'none' } = authorization
|
||||||
console.log(type)
|
console.log(type)
|
||||||
this.$refs.Authorization.authorizationType = type
|
this.$refs.Authorization.authorizationType = type
|
||||||
if (type !== 'none') {
|
if (type !== 'none') {
|
||||||
const _authorization = _.cloneDeep(authorization)
|
const _authorization = _.cloneDeep(authorization)
|
||||||
delete _authorization.type
|
delete _authorization.type
|
||||||
if (type === 'OAuth2.0') {
|
if (type === 'OAuth2.0') {
|
||||||
this.$refs.Authorization.OAuth2 = _authorization
|
this.$refs.Authorization.OAuth2 = _authorization
|
||||||
} else {
|
} else {
|
||||||
this.$refs.Authorization[type] = _authorization
|
this.$refs.Authorization[type] = _authorization
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style></style>
|
<style></style>
|
||||||
|
|
|
@ -1,100 +1,100 @@
|
||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<div class="parameters-header">
|
<div class="parameters-header">
|
||||||
<span>请求参数</span>
|
<span>{{ $t('cmdb.components.requestParam') }}</span>
|
||||||
<a-space>
|
<a-space>
|
||||||
<a-tooltip title="清空">
|
<a-tooltip :title="$t('cmdb.components.clear')">
|
||||||
<ops-icon
|
<ops-icon
|
||||||
type="icon-xianxing-delete"
|
type="icon-xianxing-delete"
|
||||||
@click="
|
@click="
|
||||||
() => {
|
() => {
|
||||||
parameters = []
|
parameters = []
|
||||||
}
|
}
|
||||||
"
|
"
|
||||||
/>
|
/>
|
||||||
</a-tooltip>
|
</a-tooltip>
|
||||||
<a-tooltip title="新增">
|
<a-tooltip :title="$t('new')">
|
||||||
<a-icon type="plus" @click="add" />
|
<a-icon type="plus" @click="add" />
|
||||||
</a-tooltip>
|
</a-tooltip>
|
||||||
</a-space>
|
</a-space>
|
||||||
</div>
|
</div>
|
||||||
<div class="parameters-box" v-if="parameters && parameters.length">
|
<div class="parameters-box" v-if="parameters && parameters.length">
|
||||||
<table>
|
<table>
|
||||||
<tr v-for="(item, index) in parameters" :key="item.id">
|
<tr v-for="(item, index) in parameters" :key="item.id">
|
||||||
<td><a-input class="parameters-input" v-model="item.key" :placeholder="`参数${index + 1}`" /></td>
|
<td><a-input class="parameters-input" v-model="item.key" :placeholder="$t('cmdb.components.param', { param: `${index + 1}` })" /></td>
|
||||||
<td><a-input class="parameters-input" v-model="item.value" :placeholder="`值${index + 1}`" /></td>
|
<td><a-input class="parameters-input" v-model="item.value" :placeholder="$t('cmdb.components.value', { value: `${index + 1}` })" /></td>
|
||||||
<td>
|
<td>
|
||||||
<a style="color:red">
|
<a style="color:red">
|
||||||
<ops-icon type="icon-xianxing-delete" @click="deleteParam(index)" />
|
<ops-icon type="icon-xianxing-delete" @click="deleteParam(index)" />
|
||||||
</a>
|
</a>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
<a-empty
|
<a-empty
|
||||||
v-else
|
v-else
|
||||||
:image-style="{
|
:image-style="{
|
||||||
height: '60px',
|
height: '60px',
|
||||||
}"
|
}"
|
||||||
>
|
>
|
||||||
<img slot="image" :src="require('@/assets/data_empty.png')" />
|
<img slot="image" :src="require('@/assets/data_empty.png')" />
|
||||||
<span slot="description"> 暂无请求参数 </span>
|
<span slot="description"> {{ $t('cmdb.components.noParamRequest') }} </span>
|
||||||
<a-button @click="add" type="primary" size="small" icon="plus" class="ops-button-primary">
|
<a-button @click="add" type="primary" size="small" icon="plus" class="ops-button-primary">
|
||||||
添加
|
{{ $t('add') }}
|
||||||
</a-button>
|
</a-button>
|
||||||
</a-empty>
|
</a-empty>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { v4 as uuidv4 } from 'uuid'
|
import { v4 as uuidv4 } from 'uuid'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'Parameters',
|
name: 'Parameters',
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
parameters: [],
|
parameters: [],
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
add() {
|
add() {
|
||||||
this.parameters.push({
|
this.parameters.push({
|
||||||
id: uuidv4(),
|
id: uuidv4(),
|
||||||
key: '',
|
key: '',
|
||||||
value: '',
|
value: '',
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
deleteParam(index) {
|
deleteParam(index) {
|
||||||
this.parameters.splice(index, 1)
|
this.parameters.splice(index, 1)
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="less" scoped>
|
<style lang="less" scoped>
|
||||||
.parameters-header {
|
.parameters-header {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
i {
|
i {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.parameters-box {
|
.parameters-box {
|
||||||
table {
|
table {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
border-collapse: collapse;
|
border-collapse: collapse;
|
||||||
}
|
}
|
||||||
table,
|
table,
|
||||||
td,
|
td,
|
||||||
th {
|
th {
|
||||||
border: 1px solid #f3f4f6;
|
border: 1px solid #f3f4f6;
|
||||||
}
|
}
|
||||||
.parameters-input {
|
.parameters-input {
|
||||||
border: none;
|
border: none;
|
||||||
&:focus {
|
&:focus {
|
||||||
box-shadow: none;
|
box-shadow: none;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -0,0 +1,483 @@
|
||||||
|
const cmdb_en = {
|
||||||
|
relation: 'Relation',
|
||||||
|
attribute: 'Attributes',
|
||||||
|
menu: {
|
||||||
|
views: 'Views',
|
||||||
|
config: 'Configuration',
|
||||||
|
backend: 'Management',
|
||||||
|
ciTable: 'Resource Views',
|
||||||
|
ciTree: 'Tree Views',
|
||||||
|
ciSearch: 'Search',
|
||||||
|
adCIs: 'AutoDiscovery Pool',
|
||||||
|
preference: 'Preference',
|
||||||
|
batchUpload: 'Batch Import',
|
||||||
|
citypeManage: 'Modeling',
|
||||||
|
backendManage: 'Backend',
|
||||||
|
customDashboard: 'Custom Dashboard',
|
||||||
|
serviceTreeDefine: 'Service Tree',
|
||||||
|
citypeRelation: 'CIType Relation',
|
||||||
|
operationHistory: 'Operation Audit',
|
||||||
|
relationType: 'Relation Type',
|
||||||
|
ad: 'AutoDiscovery',
|
||||||
|
},
|
||||||
|
ciType: {
|
||||||
|
ciType: 'CIType',
|
||||||
|
attributes: 'Attributes',
|
||||||
|
relation: 'Relation',
|
||||||
|
trigger: 'Triggers',
|
||||||
|
attributeAD: 'Attributes AutoDiscovery',
|
||||||
|
relationAD: 'Relation AutoDiscovery',
|
||||||
|
grant: 'Grant',
|
||||||
|
addGroup: 'New Group',
|
||||||
|
editGroup: 'Edit Group',
|
||||||
|
group: 'Group',
|
||||||
|
attributeLibray: 'Attribute Library',
|
||||||
|
addCITypeInGroup: 'Add a new CIType to the group',
|
||||||
|
addCIType: 'Add CIType',
|
||||||
|
editGroupName: 'Edit group name',
|
||||||
|
deleteGroup: 'Delete this group',
|
||||||
|
CITypeName: 'Name(English)',
|
||||||
|
English: 'English',
|
||||||
|
inputAttributeName: 'Please enter the attribute name',
|
||||||
|
attributeNameTips: 'It cannot start with a number, it can be English numbers and underscores (_)',
|
||||||
|
editCIType: 'Edit CIType',
|
||||||
|
defaultSort: 'Default sort',
|
||||||
|
selectDefaultOrderAttr: 'Select default sorting attributes',
|
||||||
|
asec: 'Forward order',
|
||||||
|
desc: 'Reverse order',
|
||||||
|
uniqueKey: 'Uniquely Identifies',
|
||||||
|
uniqueKeySelect: 'Please select a unique identifier',
|
||||||
|
notfound: 'Can\'t find what you want?',
|
||||||
|
cannotDeleteGroupTips: 'There is data under this group and cannot be deleted!',
|
||||||
|
confirmDeleteGroup: 'Are you sure you want to delete group [{groupName}]?',
|
||||||
|
confirmDeleteCIType: 'Are you sure you want to delete model [{typeName}]?',
|
||||||
|
uploading: 'Uploading',
|
||||||
|
uploadFailed: 'Upload failed, please try again later',
|
||||||
|
addPlugin: 'New plugin',
|
||||||
|
deletePlugin: 'Delete plugin',
|
||||||
|
confirmDeleteADT: 'Do you confirm to delete [{pluginName}]',
|
||||||
|
attributeMap: 'Attribute mapping',
|
||||||
|
autoDiscovery: 'AutoDiscovery',
|
||||||
|
node: 'Node',
|
||||||
|
adExecConfig: 'Execute configuration',
|
||||||
|
adExecTarget: 'Execute targets',
|
||||||
|
oneagentIdTips: 'Please enter the hexadecimal OneAgent ID starting with 0x',
|
||||||
|
selectFromCMDBTips: 'Select from CMDB ',
|
||||||
|
adAutoInLib: 'Save as CI auto',
|
||||||
|
adInterval: 'Collection frequency',
|
||||||
|
byInterval: 'by interval',
|
||||||
|
allNodes: 'All nodes',
|
||||||
|
specifyNodes: 'Specify Node',
|
||||||
|
specifyNodesTips: 'Please fill in the specify node!',
|
||||||
|
username: 'Username',
|
||||||
|
password: 'Password',
|
||||||
|
link: 'Link',
|
||||||
|
list: 'List',
|
||||||
|
listTips: 'The value of the field is one or more, and the type of the value returned by the interface is list.',
|
||||||
|
computeForAllCITips: 'All CI trigger computes',
|
||||||
|
confirmcomputeForAllCITips: 'Confirm triggering computes for all CIs?',
|
||||||
|
isUnique: 'Is it unique',
|
||||||
|
unique: 'Unique',
|
||||||
|
isChoice: 'Choiced',
|
||||||
|
defaultShow: 'Default Display',
|
||||||
|
defaultShowTips: 'The CI instance table displays this field by default',
|
||||||
|
isSortable: 'Sortable',
|
||||||
|
isIndex: 'Indexed',
|
||||||
|
index: 'Index',
|
||||||
|
indexTips: 'Fields can be used for retrieval to speed up queries',
|
||||||
|
confirmDelete: 'Confirm to delete [{name}]?',
|
||||||
|
confirmDelete2: 'Confirm to delete?',
|
||||||
|
computeSuccess: 'Triggered successfully!',
|
||||||
|
basicConfig: 'Basic Settings',
|
||||||
|
AttributeName: 'Name(English)',
|
||||||
|
DataType: 'Data Type',
|
||||||
|
defaultValue: 'Default value',
|
||||||
|
autoIncID: 'Auto-increment ID',
|
||||||
|
customTime: 'Custom time',
|
||||||
|
advancedSettings: 'Advanced Settings',
|
||||||
|
font: 'Font',
|
||||||
|
color: 'Color',
|
||||||
|
choiceValue: 'Predefined value',
|
||||||
|
computedAttribute: 'Computed Attribute',
|
||||||
|
computedAttributeTips: 'The value of this attribute is calculated through an expression constructed from other attributes of the CIType or by executing a piece of code. The reference method of the attribute is: {{ attribute name }}',
|
||||||
|
addAttribute: 'New attribute',
|
||||||
|
existedAttributes: 'Already have attributes',
|
||||||
|
editAttribute: 'Edit attribute',
|
||||||
|
addAttributeTips1: 'If sorting is selected, it must also be selected!',
|
||||||
|
uniqueConstraint: 'Unique Constraint',
|
||||||
|
up: 'Move up',
|
||||||
|
down: 'Move down',
|
||||||
|
selectAttribute: 'Select Attribute',
|
||||||
|
groupExisted: 'Group name already exists',
|
||||||
|
attributeSortedTips: 'Attributes in other groups cannot be sorted. If you need to sort, please drag them to a custom group first!',
|
||||||
|
buildinAttribute: 'built-in attributes',
|
||||||
|
expr: 'Expression',
|
||||||
|
code: 'Code',
|
||||||
|
apply: 'apply',
|
||||||
|
continueAdd: 'Keep adding',
|
||||||
|
filter: 'Filter',
|
||||||
|
choiceOther: 'Other CIType Attributes',
|
||||||
|
choiceWebhookTips: 'The returned results are filtered by fields, and the hierarchical nesting is separated by ##, such as k1##k2. The web request returns {k1: [{k2: 1}, {k2: 2}]}, and the parsing result is [1, 2 ]',
|
||||||
|
selectCIType: 'Please select a CMDB CIType',
|
||||||
|
selectCITypeAttributes: 'Please select CIType attributes',
|
||||||
|
selectAttributes: 'Please select attributes',
|
||||||
|
choiceScriptDemo: 'class ChoiceValue(object):\n @staticmethod\n def values():\n """\n Execution entry, returns predefined value\n :return: Returns a list, the type of the value is the same as the type of the attribute\n For example:\n return ["online", "offline"]\n """\n return []',
|
||||||
|
valueExisted: 'The current value already exists!',
|
||||||
|
addRelation: 'Add Relation',
|
||||||
|
sourceCIType: 'Source CIType',
|
||||||
|
sourceCITypeTips: 'Please select Source CIType',
|
||||||
|
dstCIType: 'Target CIType',
|
||||||
|
dstCITypeTips: 'Please select target CIType',
|
||||||
|
relationType: 'Relation Type',
|
||||||
|
relationTypeTips: 'Please select relation type',
|
||||||
|
isParent: 'is parent',
|
||||||
|
relationConstraint: 'Constraints',
|
||||||
|
relationConstraintTips: 'please select a relationship constraint',
|
||||||
|
one2Many: 'One to Many',
|
||||||
|
one2One: 'One to One',
|
||||||
|
many2Many: 'Many to Many',
|
||||||
|
basicInfo: 'Basic Information',
|
||||||
|
nameInputTips: 'Please enter name',
|
||||||
|
triggerDataChange: 'Data changes',
|
||||||
|
triggerDate: 'Date attribute',
|
||||||
|
triggerEnable: 'Turn on',
|
||||||
|
descInput: 'Please enter remarks',
|
||||||
|
triggerCondition: 'Triggering conditions',
|
||||||
|
addInstance: 'Add new instance',
|
||||||
|
deleteInstance: 'Delete instance',
|
||||||
|
changeInstance: 'Instance changes',
|
||||||
|
selectMutipleAttributes: 'Please select attributes (multiple selections)',
|
||||||
|
selectSingleAttribute: 'Please select an attribute (single choice)',
|
||||||
|
beforeDays: 'ahead of time',
|
||||||
|
days: 'Days',
|
||||||
|
notifyAt: 'Send time',
|
||||||
|
notify: 'Notify',
|
||||||
|
triggerAction: 'Trigger action',
|
||||||
|
receivers: 'Recipients',
|
||||||
|
emailTips: 'Please enter your email address, separate multiple email addresses with ;',
|
||||||
|
customEmail: 'Custom recipients',
|
||||||
|
notifySubject: 'Notification title',
|
||||||
|
notifySubjectTips: 'Please enter notification title',
|
||||||
|
notifyContent: 'Content',
|
||||||
|
notifyMethod: 'Notify methods',
|
||||||
|
botSelect: 'Please select a robot',
|
||||||
|
refAttributeTips: 'The title and content can reference the attribute value of the CIType. The reference method is: {{ attr_name }}',
|
||||||
|
webhookRefAttributeTips: 'Request parameters can reference the attribute value of the model. The reference method is: {{ attr_name }}',
|
||||||
|
newTrigger: 'Add trigger',
|
||||||
|
editTriggerTitle: 'Edit trigger {name}',
|
||||||
|
newTriggerTitle: 'Add trigger {name}',
|
||||||
|
confirmDeleteTrigger: 'Are you sure to delete this trigger?',
|
||||||
|
int: 'Integer',
|
||||||
|
float: 'Float',
|
||||||
|
text: 'Text',
|
||||||
|
datetime: 'DateTime',
|
||||||
|
date: 'Date',
|
||||||
|
time: 'Time',
|
||||||
|
json: 'JSON',
|
||||||
|
event: 'Event'
|
||||||
|
},
|
||||||
|
components: {
|
||||||
|
unselectAttributes: 'Unselected',
|
||||||
|
selectAttributes: 'Selected',
|
||||||
|
downloadCI: 'Export data',
|
||||||
|
filename: 'Filename',
|
||||||
|
filenameInputTips: 'Please enter filename',
|
||||||
|
saveType: 'Save type',
|
||||||
|
saveTypeTips: 'Please select save type',
|
||||||
|
xlsx: 'Excel workbook (*.xlsx)',
|
||||||
|
csv: 'CSV (comma separated) (*.csv)',
|
||||||
|
html: 'Web page (*.html)',
|
||||||
|
xml: 'XML data (*.xml)',
|
||||||
|
txt: 'Text file (tab delimited) (*.txt)',
|
||||||
|
grantUser: 'Grant User/Department',
|
||||||
|
grantRole: 'Grant Role',
|
||||||
|
confirmRevoke: 'Confirm to delete the [Authorization] permission of [{name}]?',
|
||||||
|
readAttribute: 'View Attributes',
|
||||||
|
readCI: 'View CIs',
|
||||||
|
config: 'Configuration',
|
||||||
|
ciTypeGrant: 'Grant CIType',
|
||||||
|
ciGrant: 'Grant CI',
|
||||||
|
attributeGrant: 'Grant Attribute',
|
||||||
|
relationGrant: 'Grant Relation',
|
||||||
|
perm: 'Permissions',
|
||||||
|
all: 'All',
|
||||||
|
customize: 'Customize',
|
||||||
|
none: 'None',
|
||||||
|
customizeFilterName: 'Please enter a custom filter name',
|
||||||
|
colorPickerError: 'Initialization color format error, use #fff or rgb format',
|
||||||
|
example: 'Example value',
|
||||||
|
aliyun: 'aliyun',
|
||||||
|
tencentcloud: 'Tencent Cloud',
|
||||||
|
huaweicloud: 'Huawei Cloud',
|
||||||
|
beforeChange: 'Before change',
|
||||||
|
afterChange: 'After change',
|
||||||
|
noticeContentTips: 'Please enter notification content',
|
||||||
|
saveQuery: 'Save Filters',
|
||||||
|
pleaseSearch: 'Please search',
|
||||||
|
conditionFilter: 'Conditional filtering',
|
||||||
|
attributeDesc: 'Attribute Description',
|
||||||
|
ciSearchTips: '1. JSON attributes cannot be searched<br />2. If the search content includes commas, they need to be escaped,<br />3. Only index attributes are searched, non-index attributes use conditional filtering',
|
||||||
|
ciSearchTips2: 'For example: q=hostname:*0.0.0.0*',
|
||||||
|
subCIType: 'Subscription CIType',
|
||||||
|
already: 'already',
|
||||||
|
not: 'not',
|
||||||
|
sub: 'subscription',
|
||||||
|
selectBelow: 'Please select below',
|
||||||
|
subSuccess: 'Subscription successful',
|
||||||
|
selectMethods: 'Please select a method',
|
||||||
|
noAuthRequest: 'No certification requested yet',
|
||||||
|
noParamRequest: 'No parameter certification yet',
|
||||||
|
requestParam: 'Request parameters',
|
||||||
|
param: 'Parameter{param}',
|
||||||
|
value: 'Value{value}',
|
||||||
|
clear: 'Clear',
|
||||||
|
},
|
||||||
|
batch: {
|
||||||
|
downloadFailed: 'Download failed',
|
||||||
|
unselectCIType: 'No CIType selected yet',
|
||||||
|
pleaseUploadFile: 'Please upload files',
|
||||||
|
batchUploadCanceled: 'Batch upload canceled',
|
||||||
|
selectCITypeTips: 'Please select CIType',
|
||||||
|
downloadTemplate: 'Download Template',
|
||||||
|
drawTips: 'Click or drag files here to upload!',
|
||||||
|
supportFileTypes: 'Supported file types: xls, xlsx',
|
||||||
|
uploadResult: 'Upload results',
|
||||||
|
total: 'total',
|
||||||
|
successItems: 'items, succeeded',
|
||||||
|
failedItems: 'items, failed',
|
||||||
|
items: 'items',
|
||||||
|
errorTips: 'Error message',
|
||||||
|
requestFailedTips: 'An error occurred with the request, please try again later',
|
||||||
|
requestSuccessTips: 'Upload completed',
|
||||||
|
},
|
||||||
|
preference: {
|
||||||
|
mySub: 'My Subscription',
|
||||||
|
sub: 'Subscribe',
|
||||||
|
cancelSub: 'Unsubscribe',
|
||||||
|
editSub: 'Edit subscription',
|
||||||
|
peopleSub: ' people subscribed',
|
||||||
|
noSub: 'No subscribed',
|
||||||
|
cancelSubSuccess: 'Unsubscribe successfully',
|
||||||
|
confirmcancelSub: 'Are you sure to cancel your subscription?',
|
||||||
|
confirmcancelSub2: 'Are you sure you want to unsubscribe {name}?',
|
||||||
|
of: 'of',
|
||||||
|
hoursAgo: 'hours ago',
|
||||||
|
daysAgo: 'days ago',
|
||||||
|
monthsAgo: 'month ago',
|
||||||
|
yearsAgo: 'years ago',
|
||||||
|
just: 'just now',
|
||||||
|
},
|
||||||
|
custom_dashboard: {
|
||||||
|
charts: 'Chart',
|
||||||
|
newChart: 'Add Chart',
|
||||||
|
editChart: 'Edit Chart',
|
||||||
|
title: 'Title',
|
||||||
|
titleTips: 'Please enter a chart title',
|
||||||
|
calcIndicators: 'Counter',
|
||||||
|
dimensions: 'Dimensions',
|
||||||
|
selectDimensions: 'Please select a dimension',
|
||||||
|
quantity: 'Quantity',
|
||||||
|
childCIType: 'Relational CIType',
|
||||||
|
level: 'Level',
|
||||||
|
levelTips: 'Please enter the relationship level',
|
||||||
|
preview: 'Preview',
|
||||||
|
showIcon: 'Display icon',
|
||||||
|
chartType: 'Chart Type',
|
||||||
|
dataFilter: 'Data Filtering',
|
||||||
|
format: 'Formats',
|
||||||
|
fontColor: 'Font Color',
|
||||||
|
backgroundColor: 'Background',
|
||||||
|
chartColor: 'Chart Color',
|
||||||
|
chartLength: 'Length',
|
||||||
|
barType: 'Bar Type',
|
||||||
|
stackedBar: 'Stacked Bar',
|
||||||
|
multipleSeriesBar: 'Multiple Series Bar ',
|
||||||
|
axis: 'Axis',
|
||||||
|
direction: 'Direction',
|
||||||
|
lowerShadow: 'Lower Shadow',
|
||||||
|
count: 'Indicator',
|
||||||
|
bar: 'Bar',
|
||||||
|
line: 'Line',
|
||||||
|
pie: 'Pie',
|
||||||
|
table: 'Table',
|
||||||
|
default: 'default',
|
||||||
|
relation: 'Relation',
|
||||||
|
noCustomDashboard: 'The administrator has not customized the dashboard yet',
|
||||||
|
},
|
||||||
|
preference_relation: {
|
||||||
|
newServiceTree: 'Add ServiceTree',
|
||||||
|
serviceTreeName: 'Name',
|
||||||
|
public: 'Public',
|
||||||
|
saveLayout: 'Save Layout',
|
||||||
|
childNodesNotFound: 'There are no child nodes and no business relationship can be formed. Please select again!',
|
||||||
|
tips1: 'Cannot form a view with the currently selected node, please select again!',
|
||||||
|
tips2: 'Please enter the new serviceTree name!',
|
||||||
|
tips3: 'Please select at least two nodes!',
|
||||||
|
},
|
||||||
|
history: {
|
||||||
|
ciChange: 'CI',
|
||||||
|
relationChange: 'Relation',
|
||||||
|
ciTypeChange: 'CIType',
|
||||||
|
triggerHistory: 'Triggers',
|
||||||
|
opreateTime: 'Operate Time',
|
||||||
|
user: 'User',
|
||||||
|
userTips: 'Enter filter username',
|
||||||
|
filter: 'Search',
|
||||||
|
filterOperate: 'fitler operation',
|
||||||
|
attribute: 'Attribute',
|
||||||
|
old: 'Old',
|
||||||
|
new: 'New',
|
||||||
|
noUpdate: 'No update',
|
||||||
|
itemsPerPage: '/page',
|
||||||
|
triggerName: 'Name',
|
||||||
|
event: 'Event',
|
||||||
|
action: 'Actoin',
|
||||||
|
status: 'Status',
|
||||||
|
done: 'Done',
|
||||||
|
undone: 'Undone',
|
||||||
|
triggerTime: 'Trigger Time',
|
||||||
|
totalItems: '{total} records in total',
|
||||||
|
pleaseSelect: 'Please select',
|
||||||
|
startTime: 'Start Time',
|
||||||
|
endTime: 'End Time',
|
||||||
|
deleteCIType: 'Delete CIType',
|
||||||
|
addCIType: 'Add CIType',
|
||||||
|
updateCIType: 'Update CIType',
|
||||||
|
addAttribute: 'Add Attribute',
|
||||||
|
updateAttribute: 'Update Attribute',
|
||||||
|
deleteAttribute: 'Delete Attribute',
|
||||||
|
addTrigger: 'Add Trigger',
|
||||||
|
updateTrigger: 'Update Trigger',
|
||||||
|
deleteTrigger: 'Delete Trigger',
|
||||||
|
addUniqueConstraint: 'Add Unique Constraint',
|
||||||
|
updateUniqueConstraint: 'Update Unique Constraint',
|
||||||
|
deleteUniqueConstraint: 'Delete Unique Constraint',
|
||||||
|
addRelation: 'Add Relation',
|
||||||
|
deleteRelation: 'Delete Relation',
|
||||||
|
noModifications: 'No Modifications',
|
||||||
|
attr: 'attribute',
|
||||||
|
attrId: 'attribute id',
|
||||||
|
changeDescription: 'attribute id: {attr_id}, {before_days} day(s) in advance, Subject: {subject}\nContent: {body}\nNotify At: {notify_at}'
|
||||||
|
},
|
||||||
|
relation_type: {
|
||||||
|
addRelationType: 'New',
|
||||||
|
nameTips: 'Please enter a type name',
|
||||||
|
},
|
||||||
|
ad: {
|
||||||
|
upload: 'Import',
|
||||||
|
download: 'Export',
|
||||||
|
accpet: 'Accept',
|
||||||
|
accpetBy: 'Accept By',
|
||||||
|
acceptTime: 'Accept Time',
|
||||||
|
confirmAccept: 'Confirm Accept?',
|
||||||
|
accpetSuccess: 'Accept successfully',
|
||||||
|
isAccpet: 'Is accept',
|
||||||
|
deleteADC: 'Confirm to delete this data?',
|
||||||
|
batchDelete: 'Confirm to delete this data?',
|
||||||
|
agent: 'Built-in & Plug-ins',
|
||||||
|
snmp: 'Network Devices',
|
||||||
|
http: 'Public Clouds',
|
||||||
|
rule: 'AutoDiscovery Rules',
|
||||||
|
timeout: 'Timeout error',
|
||||||
|
mode: 'Mode',
|
||||||
|
collectSettings: 'Collection Settings',
|
||||||
|
updateFields: 'Update Field',
|
||||||
|
pluginScript: `# -*- coding:utf-8 -*-
|
||||||
|
|
||||||
|
import json
|
||||||
|
|
||||||
|
|
||||||
|
class AutoDiscovery(object):
|
||||||
|
|
||||||
|
@property
|
||||||
|
def unique_key(self):
|
||||||
|
"""
|
||||||
|
|
||||||
|
:return: Returns the name of a unique attribute
|
||||||
|
"""
|
||||||
|
return
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def attributes():
|
||||||
|
"""
|
||||||
|
Define attribute fields
|
||||||
|
:return: Returns a list of attribute fields. The list items are (name, type, description). The name must be in English.
|
||||||
|
type: String Integer Float Date DateTime Time JSON
|
||||||
|
For example:
|
||||||
|
return [
|
||||||
|
("ci_type", "String", "CIType name"),
|
||||||
|
("private_ip", "String", "Internal IP, multiple values separated by commas")
|
||||||
|
]
|
||||||
|
"""
|
||||||
|
return []
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def run():
|
||||||
|
"""
|
||||||
|
Execution entry, returns collected attribute values
|
||||||
|
:return:
|
||||||
|
Returns a list, the list item is a dictionary, the dictionary key is the attribute name, and the value is the attribute value
|
||||||
|
For example:
|
||||||
|
return [dict(ci_type="server", private_ip="192.168.1.1")]
|
||||||
|
"""
|
||||||
|
return []
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
result = AutoDiscovery().run()
|
||||||
|
if isinstance(result, list):
|
||||||
|
print("AutoDiscovery::Result::{}".format(json.dumps(result)))
|
||||||
|
else:
|
||||||
|
print("ERROR: The collection return must be a list")
|
||||||
|
`,
|
||||||
|
server: 'Server',
|
||||||
|
vserver: 'VServer',
|
||||||
|
nic: 'NIC',
|
||||||
|
disk: 'harddisk',
|
||||||
|
},
|
||||||
|
ci: {
|
||||||
|
attributeDesc: 'Attribute Description',
|
||||||
|
selectRows: 'Select: {rows} items',
|
||||||
|
addRelation: 'Add Relation',
|
||||||
|
all: 'All',
|
||||||
|
batchUpdate: 'Batch Update',
|
||||||
|
batchUpdateConfirm: 'Are you sure you want to make batch updates?',
|
||||||
|
batchUpdateInProgress: 'Currently being updated in batches',
|
||||||
|
batchUpdateInProgress2: 'Updating in batches, {total} in total, {successNum} successful, {errorNum} failed',
|
||||||
|
batchDeleting: 'Deleting...',
|
||||||
|
batchDeleting2: 'Deleting {total} items in total, {successNum} items successful, {errorNum} items failed',
|
||||||
|
copyFailed: 'Copy failed',
|
||||||
|
noLevel: 'No hierarchical relationship!',
|
||||||
|
batchAddRelation: 'Batch Add Relation',
|
||||||
|
history: 'History',
|
||||||
|
topo: 'Topology',
|
||||||
|
table: 'Table',
|
||||||
|
m2mTips: 'The current CIType relationship is many-to-many, please go to the SerivceTree(relation view) to add or delete',
|
||||||
|
confirmDeleteRelation: 'Confirm to delete the relationship?',
|
||||||
|
tips1: 'Use commas to separate multiple values',
|
||||||
|
tips2: 'The field can be modified as needed. When the value is empty, the field will be left empty.',
|
||||||
|
tips3: 'Please select the fields that need to be modified',
|
||||||
|
tips4: 'At least one field must be selected',
|
||||||
|
tips5: 'Search name | alias',
|
||||||
|
tips6: 'Speed up retrieval, full-text search possible, no need to use conditional filtering\n\n json currently does not support indexing \n\nText characters longer than 190 cannot be indexed',
|
||||||
|
tips7: 'The form of expression is a drop-down box, and the value must be in the predefined value',
|
||||||
|
tips8: 'Multiple values, such as intranet IP',
|
||||||
|
tips9: 'For front-end only',
|
||||||
|
tips10: 'Other attributes of the CIType are computed using expressions\n\nA code snippet computes the returned value.',
|
||||||
|
newUpdateField: 'Add a Attribute',
|
||||||
|
attributeSettings: 'Attribute Settings',
|
||||||
|
},
|
||||||
|
serviceTree: {
|
||||||
|
deleteNode: 'Delete Node',
|
||||||
|
tips1: 'For example: q=os_version:centos&sort=os_version',
|
||||||
|
tips2: 'Expression search',
|
||||||
|
alert1: 'The administrator has not configured the ServiceTree(relation view), or you do not have permission to access it!',
|
||||||
|
copyFailed: 'Copy failed',
|
||||||
|
deleteRelationConfirm: 'Confirm to remove selected {name} from current relationship?',
|
||||||
|
},
|
||||||
|
tree: {
|
||||||
|
tips1: 'Please go to Preference page first to complete your subscription!',
|
||||||
|
subSettings: 'Settings',
|
||||||
|
}
|
||||||
|
}
|
||||||
|
export default cmdb_en
|
|
@ -0,0 +1,482 @@
|
||||||
|
const cmdb_zh = {
|
||||||
|
relation: '关系',
|
||||||
|
attribute: '属性',
|
||||||
|
menu: {
|
||||||
|
views: '视图',
|
||||||
|
config: '配置',
|
||||||
|
backend: '管理端',
|
||||||
|
ciTable: '资源数据',
|
||||||
|
ciTree: '资源层级',
|
||||||
|
ciSearch: '资源搜索',
|
||||||
|
adCIs: '自动发现池',
|
||||||
|
preference: '我的订阅',
|
||||||
|
batchUpload: '批量导入',
|
||||||
|
citypeManage: '模型配置',
|
||||||
|
backendManage: '后台管理',
|
||||||
|
customDashboard: '定制仪表盘',
|
||||||
|
serviceTreeDefine: '服务树定义',
|
||||||
|
citypeRelation: '模型关系',
|
||||||
|
operationHistory: '操作审计',
|
||||||
|
relationType: '关系类型',
|
||||||
|
ad: '自动发现',
|
||||||
|
},
|
||||||
|
ciType: {
|
||||||
|
ciType: '模型',
|
||||||
|
attributes: '模型属性',
|
||||||
|
relation: '模型关联',
|
||||||
|
trigger: '触发器',
|
||||||
|
attributeAD: '属性自动发现',
|
||||||
|
relationAD: '关系自动发现',
|
||||||
|
grant: '权限配置',
|
||||||
|
addGroup: '新增分组',
|
||||||
|
editGroup: '修改分组',
|
||||||
|
group: '分组',
|
||||||
|
attributeLibray: '属性库',
|
||||||
|
addCITypeInGroup: '在该组中新增CI模型',
|
||||||
|
addCIType: '新增CI模型',
|
||||||
|
editGroupName: '编辑组名称',
|
||||||
|
deleteGroup: '删除该组',
|
||||||
|
CITypeName: '模型名(英文)',
|
||||||
|
English: '英文',
|
||||||
|
inputAttributeName: '请输入属性名',
|
||||||
|
attributeNameTips: '不能以数字开头,可以是英文 数字以及下划线 (_)',
|
||||||
|
editCIType: '编辑模型',
|
||||||
|
defaultSort: '默认排序',
|
||||||
|
selectDefaultOrderAttr: '选择默认排序属性',
|
||||||
|
asec: '正序',
|
||||||
|
desc: '倒序',
|
||||||
|
uniqueKey: '唯一标识',
|
||||||
|
uniqueKeySelect: '请选择唯一标识',
|
||||||
|
notfound: '找不到想要的?',
|
||||||
|
cannotDeleteGroupTips: '该分组下有数据, 不能删除!',
|
||||||
|
confirmDeleteGroup: '确定要删除分组 【{groupName}】 吗?',
|
||||||
|
confirmDeleteCIType: '确定要删除模型 【{typeName}】 吗?',
|
||||||
|
uploading: '正在导入中',
|
||||||
|
uploadFailed: '导入失败,请稍后重试',
|
||||||
|
addPlugin: '新建plugin',
|
||||||
|
deletePlugin: '删除plugin',
|
||||||
|
confirmDeleteADT: '确认删除 【{pluginName}】',
|
||||||
|
attributeMap: '字段映射',
|
||||||
|
autoDiscovery: '自动发现',
|
||||||
|
node: '节点',
|
||||||
|
adExecConfig: '执行配置',
|
||||||
|
adExecTarget: '执行机器',
|
||||||
|
oneagentIdTips: '请输入以0x开头的16进制OneAgent ID',
|
||||||
|
selectFromCMDBTips: '从CMDB中选择 ',
|
||||||
|
adAutoInLib: '自动入库',
|
||||||
|
adInterval: '采集频率',
|
||||||
|
byInterval: '按间隔',
|
||||||
|
allNodes: '所有节点',
|
||||||
|
specifyNodes: '指定节点',
|
||||||
|
specifyNodesTips: '请填写指定节点!',
|
||||||
|
username: '用户名',
|
||||||
|
password: '密码',
|
||||||
|
link: '链接',
|
||||||
|
list: '多值',
|
||||||
|
listTips: '字段的值是1个或者多个,接口返回的值的类型是list',
|
||||||
|
computeForAllCITips: '所有CI触发计算',
|
||||||
|
confirmcomputeForAllCITips: '确认触发所有CI的计算?',
|
||||||
|
isUnique: '是否唯一',
|
||||||
|
unique: '唯一',
|
||||||
|
isChoice: '是否选择',
|
||||||
|
defaultShow: '默认显示',
|
||||||
|
defaultShowTips: 'CI实例表格默认展示该字段',
|
||||||
|
isSortable: '可排序',
|
||||||
|
isIndex: '是否索引',
|
||||||
|
index: '索引',
|
||||||
|
indexTips: '字段可被用于检索,加速查询',
|
||||||
|
confirmDelete: '确认删除【{name}】?',
|
||||||
|
confirmDelete2: '确认删除?',
|
||||||
|
computeSuccess: '触发成功!',
|
||||||
|
basicConfig: '基础设置',
|
||||||
|
AttributeName: '属性名(英文)',
|
||||||
|
DataType: '数据类型',
|
||||||
|
defaultValue: '默认值',
|
||||||
|
autoIncID: '自增ID',
|
||||||
|
customTime: '自定义时间',
|
||||||
|
advancedSettings: '高级设置',
|
||||||
|
font: '字体',
|
||||||
|
color: '颜色',
|
||||||
|
choiceValue: '预定义值',
|
||||||
|
computedAttribute: '计算属性',
|
||||||
|
computedAttributeTips: '该属性的值是通过模型的其它属性构建的表达式或者执行一段代码的方式计算而来,属性的引用方法为: {{ 属性名 }}',
|
||||||
|
addAttribute: '新增属性',
|
||||||
|
existedAttributes: '已有属性',
|
||||||
|
editAttribute: '编辑属性',
|
||||||
|
addAttributeTips1: '选中排序,则必须也要选中!',
|
||||||
|
uniqueConstraint: '唯一校验',
|
||||||
|
up: '上移',
|
||||||
|
down: '下移',
|
||||||
|
selectAttribute: '添加属性',
|
||||||
|
groupExisted: '分组名称已存在',
|
||||||
|
attributeSortedTips: '其他分组中的属性不能进行排序,如需排序请先拖至自定义的分组!',
|
||||||
|
buildinAttribute: '内置字段',
|
||||||
|
expr: '表达式',
|
||||||
|
code: '代码',
|
||||||
|
apply: '应用',
|
||||||
|
continueAdd: '继续添加',
|
||||||
|
filter: '过滤',
|
||||||
|
choiceOther: '其他模型属性',
|
||||||
|
choiceWebhookTips: '返回的结果按字段来过滤,层级嵌套用##分隔,比如k1##k2,web请求返回{k1: [{k2: 1}, {k2: 2}]}, 解析结果为[1, 2]',
|
||||||
|
selectCIType: '请选择CMDB模型',
|
||||||
|
selectCITypeAttributes: '请选择模型属性',
|
||||||
|
selectAttributes: '请选择属性',
|
||||||
|
choiceScriptDemo: 'class ChoiceValue(object):\n @staticmethod\n def values():\n """\n 执行入口, 返回预定义值\n :return: 返回一个列表, 值的类型同属性的类型\n 例如:\n return ["在线", "下线"]\n """\n return []',
|
||||||
|
valueExisted: '当前值已存在!',
|
||||||
|
addRelation: '新增关系',
|
||||||
|
sourceCIType: '源模型',
|
||||||
|
sourceCITypeTips: '请选择源模型',
|
||||||
|
dstCIType: '目标模型名',
|
||||||
|
dstCITypeTips: '请选择目标模型',
|
||||||
|
relationType: '关联类型',
|
||||||
|
relationTypeTips: '请选择关联类型',
|
||||||
|
isParent: '被',
|
||||||
|
relationConstraint: '关系约束',
|
||||||
|
relationConstraintTips: '请选择关系约束',
|
||||||
|
one2Many: '一对多',
|
||||||
|
one2One: '一对一',
|
||||||
|
many2Many: '多对多',
|
||||||
|
basicInfo: '基本信息',
|
||||||
|
nameInputTips: '请输入名称',
|
||||||
|
triggerDataChange: '数据变更',
|
||||||
|
triggerDate: '日期属性',
|
||||||
|
triggerEnable: '开启',
|
||||||
|
descInput: '请输入备注',
|
||||||
|
triggerCondition: '触发条件',
|
||||||
|
addInstance: '新增实例',
|
||||||
|
deleteInstance: '删除实例',
|
||||||
|
changeInstance: '实例变更',
|
||||||
|
selectMutipleAttributes: '请选择属性(多选)',
|
||||||
|
selectSingleAttribute: '请选择属性(单选)',
|
||||||
|
beforeDays: '提前',
|
||||||
|
days: '天',
|
||||||
|
notifyAt: '发送时间',
|
||||||
|
notify: '通知',
|
||||||
|
triggerAction: '触发动作',
|
||||||
|
receivers: '收件人',
|
||||||
|
emailTips: '请输入邮箱,多个邮箱用;分隔',
|
||||||
|
customEmail: '自定义收件人',
|
||||||
|
notifySubject: '通知标题',
|
||||||
|
notifySubjectTips: '请输入通知标题',
|
||||||
|
notifyContent: '内容',
|
||||||
|
notifyMethod: '通知方式',
|
||||||
|
botSelect: '请选择机器人',
|
||||||
|
refAttributeTips: '标题、内容可以引用该模型的属性值,引用方法为: {{ attr_name }}',
|
||||||
|
webhookRefAttributeTips: '请求参数可以引用该模型的属性值,引用方法为: {{ attr_name }}',
|
||||||
|
newTrigger: '新增触发器',
|
||||||
|
editTriggerTitle: '编辑触发器 {name}',
|
||||||
|
newTriggerTitle: '新增触发器 {name}',
|
||||||
|
confirmDeleteTrigger: '确认删除该触发器吗?',
|
||||||
|
int: '整数',
|
||||||
|
float: '浮点数',
|
||||||
|
text: '文本',
|
||||||
|
datetime: '日期时间',
|
||||||
|
date: '日期',
|
||||||
|
time: '时间',
|
||||||
|
json: 'JSON',
|
||||||
|
event: '事件'
|
||||||
|
},
|
||||||
|
components: {
|
||||||
|
unselectAttributes: '未选属性',
|
||||||
|
selectAttributes: '已选属性',
|
||||||
|
downloadCI: '导出数据',
|
||||||
|
filename: '文件名',
|
||||||
|
filenameInputTips: '请输入文件名',
|
||||||
|
saveType: '保存类型',
|
||||||
|
saveTypeTips: '请选择保存类型',
|
||||||
|
xlsx: 'Excel工作簿(*.xlsx)',
|
||||||
|
csv: 'CSV(逗号分隔)(*.csv)',
|
||||||
|
html: '网页(*.html)',
|
||||||
|
xml: 'XML数据(*.xml)',
|
||||||
|
txt: '文本文件(制表符分隔)(*.txt)',
|
||||||
|
grantUser: '授权用户/部门',
|
||||||
|
grantRole: '授权角色',
|
||||||
|
confirmRevoke: '确认删除 【{name}】 的 【授权】 权限?',
|
||||||
|
readAttribute: '查看字段',
|
||||||
|
readCI: '查看实例',
|
||||||
|
config: '配置',
|
||||||
|
ciTypeGrant: '模型权限',
|
||||||
|
ciGrant: '实例权限',
|
||||||
|
attributeGrant: '字段权限',
|
||||||
|
relationGrant: '关系权限',
|
||||||
|
perm: '权限',
|
||||||
|
all: '全部',
|
||||||
|
customize: '自定义',
|
||||||
|
none: '无',
|
||||||
|
customizeFilterName: '请输入自定义筛选条件名',
|
||||||
|
colorPickerError: '初始化颜色格式错误,使用#fff或rgb格式',
|
||||||
|
example: '示例值',
|
||||||
|
aliyun: '阿里云',
|
||||||
|
tencentcloud: '腾讯云',
|
||||||
|
huaweicloud: '华为云',
|
||||||
|
beforeChange: '变更前',
|
||||||
|
afterChange: '变更后',
|
||||||
|
noticeContentTips: '请输入通知内容',
|
||||||
|
saveQuery: '保存筛选条件',
|
||||||
|
pleaseSearch: '请查找',
|
||||||
|
conditionFilter: '条件过滤',
|
||||||
|
attributeDesc: '属性说明',
|
||||||
|
ciSearchTips: '1. json属性不能搜索<br />2. 搜索内容包括逗号, 则需转义 ,<br />3. 只搜索索引属性, 非索引属性使用条件过滤',
|
||||||
|
ciSearchTips2: '例: q=hostname:*0.0.0.0*',
|
||||||
|
subCIType: '订阅模型',
|
||||||
|
already: '已',
|
||||||
|
not: '未',
|
||||||
|
sub: '订阅',
|
||||||
|
selectBelow: '请在下方进行选择',
|
||||||
|
subSuccess: '订阅成功',
|
||||||
|
selectMethods: '请选择方式',
|
||||||
|
noAuthRequest: '暂无请求认证',
|
||||||
|
noParamRequest: '暂无参数认证',
|
||||||
|
requestParam: '请求参数',
|
||||||
|
param: '参数{param}',
|
||||||
|
value: '值{value}',
|
||||||
|
clear: '清空',
|
||||||
|
},
|
||||||
|
batch: {
|
||||||
|
downloadFailed: '失败下载',
|
||||||
|
unselectCIType: '尚未选择模板类型',
|
||||||
|
pleaseUploadFile: '请上传文件',
|
||||||
|
batchUploadCanceled: '批量上传已取消',
|
||||||
|
selectCITypeTips: '请选择模板类型',
|
||||||
|
downloadTemplate: '下载模板',
|
||||||
|
drawTips: '点击或拖拽文件至此上传!',
|
||||||
|
supportFileTypes: '支持文件类型:xls,xlsx',
|
||||||
|
uploadResult: '上传结果',
|
||||||
|
total: '共',
|
||||||
|
successItems: '条,已成功',
|
||||||
|
failedItems: '条,失败',
|
||||||
|
items: '条',
|
||||||
|
errorTips: '错误信息',
|
||||||
|
requestFailedTips: '请求出现错误,请稍后再试',
|
||||||
|
requestSuccessTips: '批量上传已完成',
|
||||||
|
},
|
||||||
|
preference: {
|
||||||
|
mySub: '我的订阅',
|
||||||
|
sub: '订阅',
|
||||||
|
cancelSub: '取消订阅',
|
||||||
|
editSub: '编辑订阅',
|
||||||
|
peopleSub: '位同事已订阅',
|
||||||
|
noSub: '暂无同事订阅',
|
||||||
|
cancelSubSuccess: '取消订阅成功',
|
||||||
|
confirmcancelSub: '确认取消订阅',
|
||||||
|
confirmcancelSub2: '确认取消订阅 {name} 吗?',
|
||||||
|
of: '的',
|
||||||
|
hoursAgo: '小时前',
|
||||||
|
daysAgo: '天前',
|
||||||
|
monthsAgo: '月前',
|
||||||
|
yearsAgo: '年前',
|
||||||
|
just: '刚刚',
|
||||||
|
},
|
||||||
|
custom_dashboard: {
|
||||||
|
charts: '图表',
|
||||||
|
newChart: '新增图表',
|
||||||
|
editChart: '编辑图表',
|
||||||
|
title: '标题',
|
||||||
|
titleTips: '请输入图表标题',
|
||||||
|
calcIndicators: '计算指标',
|
||||||
|
dimensions: '维度',
|
||||||
|
selectDimensions: '请选择维度',
|
||||||
|
quantity: '数量',
|
||||||
|
childCIType: '关系模型',
|
||||||
|
level: '层级',
|
||||||
|
levelTips: '请输入关系层级',
|
||||||
|
preview: '预览',
|
||||||
|
showIcon: '是否显示icon',
|
||||||
|
chartType: '图表类型',
|
||||||
|
dataFilter: '数据筛选',
|
||||||
|
format: '格式',
|
||||||
|
fontColor: '字体颜色',
|
||||||
|
backgroundColor: '背景颜色',
|
||||||
|
chartColor: '图表颜色',
|
||||||
|
chartLength: '图表长度',
|
||||||
|
barType: '柱状图类型',
|
||||||
|
stackedBar: '堆积柱状图',
|
||||||
|
multipleSeriesBar: '多系列柱状图',
|
||||||
|
axis: '轴',
|
||||||
|
direction: '方向',
|
||||||
|
lowerShadow: '下方阴影',
|
||||||
|
count: '指标',
|
||||||
|
bar: '柱状图',
|
||||||
|
line: '折线图',
|
||||||
|
pie: '饼状图',
|
||||||
|
table: '表格',
|
||||||
|
default: '默认',
|
||||||
|
relation: '关系',
|
||||||
|
noCustomDashboard: '管理员暂未定制仪表盘',
|
||||||
|
},
|
||||||
|
preference_relation: {
|
||||||
|
newServiceTree: '新增服务树',
|
||||||
|
serviceTreeName: '服务树名',
|
||||||
|
public: '公开',
|
||||||
|
saveLayout: '保存布局',
|
||||||
|
childNodesNotFound: '不存在子节点,不能形成业务关系,请重新选择!',
|
||||||
|
tips1: '不能与当前选中节点形成视图,请重新选择!',
|
||||||
|
tips2: '请输入新增服务树名!',
|
||||||
|
tips3: '请选择至少两个节点!',
|
||||||
|
},
|
||||||
|
history: {
|
||||||
|
ciChange: 'CI变更',
|
||||||
|
relationChange: '关系变更',
|
||||||
|
ciTypeChange: '模型变更',
|
||||||
|
triggerHistory: '触发历史',
|
||||||
|
opreateTime: '操作时间',
|
||||||
|
user: '用户',
|
||||||
|
userTips: '输入筛选用户名',
|
||||||
|
filter: '筛选',
|
||||||
|
filterOperate: '筛选操作',
|
||||||
|
attribute: '属性',
|
||||||
|
old: '旧',
|
||||||
|
new: '新',
|
||||||
|
noUpdate: '没有修改',
|
||||||
|
itemsPerPage: '/页',
|
||||||
|
triggerName: '触发器名称',
|
||||||
|
event: '事件',
|
||||||
|
action: '动作',
|
||||||
|
status: '状态',
|
||||||
|
done: '已完成',
|
||||||
|
undone: '未完成',
|
||||||
|
triggerTime: '触发时间',
|
||||||
|
totalItems: '共 {total} 条记录',
|
||||||
|
pleaseSelect: '请选择',
|
||||||
|
startTime: '开始时间',
|
||||||
|
endTime: '结束时间',
|
||||||
|
deleteCIType: '删除模型',
|
||||||
|
addCIType: '新增模型',
|
||||||
|
updateCIType: '修改模型',
|
||||||
|
addAttribute: '新增属性',
|
||||||
|
updateAttribute: '修改属性',
|
||||||
|
deleteAttribute: '删除属性',
|
||||||
|
addTrigger: '新增触发器',
|
||||||
|
updateTrigger: '修改触发器',
|
||||||
|
deleteTrigger: '删除触发器',
|
||||||
|
addUniqueConstraint: '新增联合唯一',
|
||||||
|
updateUniqueConstraint: '修改联合唯一',
|
||||||
|
deleteUniqueConstraint: '删除联合唯一',
|
||||||
|
addRelation: '新增关系',
|
||||||
|
deleteRelation: '删除关系',
|
||||||
|
noModifications: '没有修改',
|
||||||
|
attr: '属性名',
|
||||||
|
attrId: '属性ID',
|
||||||
|
changeDescription: '属性ID:{attr_id},提前:{before_days}天,主题:{subject}\n内容:{body}\n通知时间:{notify_at}'
|
||||||
|
},
|
||||||
|
relation_type: {
|
||||||
|
addRelationType: '新增关系类型',
|
||||||
|
nameTips: '请输入类型名',
|
||||||
|
},
|
||||||
|
ad: {
|
||||||
|
upload: '规则导入',
|
||||||
|
download: '规则导出',
|
||||||
|
accpet: '入库',
|
||||||
|
accpetBy: '入库人',
|
||||||
|
acceptTime: '入库时间',
|
||||||
|
confirmAccept: '确认入库?',
|
||||||
|
accpetSuccess: '入库成功',
|
||||||
|
isAccpet: '是否入库',
|
||||||
|
deleteADC: '确认删除该条数据?',
|
||||||
|
batchDelete: '确认删除这些数据?',
|
||||||
|
agent: '内置 & 插件',
|
||||||
|
snmp: '网络设备',
|
||||||
|
http: '公有云资源',
|
||||||
|
rule: '自动发现规则',
|
||||||
|
timeout: '超时错误',
|
||||||
|
mode: '模式',
|
||||||
|
collectSettings: '采集设置',
|
||||||
|
updateFields: '更新字段',
|
||||||
|
pluginScript: `# -*- coding:utf-8 -*-
|
||||||
|
|
||||||
|
import json
|
||||||
|
|
||||||
|
|
||||||
|
class AutoDiscovery(object):
|
||||||
|
|
||||||
|
@property
|
||||||
|
def unique_key(self):
|
||||||
|
"""
|
||||||
|
|
||||||
|
:return: 返回唯一属性的名字
|
||||||
|
"""
|
||||||
|
return
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def attributes():
|
||||||
|
"""
|
||||||
|
定义属性字段
|
||||||
|
:return: 返回属性字段列表, 列表项是(名称, 类型, 描述), 名称必须是英文
|
||||||
|
类型: String Integer Float Date DateTime Time JSON
|
||||||
|
例如:
|
||||||
|
return [
|
||||||
|
("ci_type", "String", "模型名称"),
|
||||||
|
("private_ip", "String", "内网IP, 多值逗号分隔")
|
||||||
|
]
|
||||||
|
"""
|
||||||
|
return []
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def run():
|
||||||
|
"""
|
||||||
|
执行入口, 返回采集的属性值
|
||||||
|
:return: 返回一个列表, 列表项是字典, 字典key是属性名称, value是属性值
|
||||||
|
例如:
|
||||||
|
return [dict(ci_type="server", private_ip="192.168.1.1")]
|
||||||
|
"""
|
||||||
|
return []
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
result = AutoDiscovery().run()
|
||||||
|
if isinstance(result, list):
|
||||||
|
print("AutoDiscovery::Result::{}".format(json.dumps(result)))
|
||||||
|
else:
|
||||||
|
print("ERROR: 采集返回必须是列表")
|
||||||
|
`,
|
||||||
|
server: '物理机',
|
||||||
|
vserver: '虚拟机',
|
||||||
|
nic: '网卡',
|
||||||
|
disk: '硬盘',
|
||||||
|
},
|
||||||
|
ci: {
|
||||||
|
attributeDesc: '属性说明',
|
||||||
|
selectRows: '选取:{rows} 项',
|
||||||
|
addRelation: '添加关系',
|
||||||
|
all: '全部',
|
||||||
|
batchUpdate: '批量修改',
|
||||||
|
batchUpdateConfirm: '确认要批量修改吗?',
|
||||||
|
batchUpdateInProgress: '正在批量修改',
|
||||||
|
batchUpdateInProgress2: '正在批量修改,共{total}个,成功{successNum}个,失败{errorNum}个',
|
||||||
|
batchDeleting: '正在删除...',
|
||||||
|
batchDeleting2: '正在删除,共{total}个,成功{successNum}个,失败{errorNum}个',
|
||||||
|
copyFailed: '复制失败!',
|
||||||
|
noLevel: '无层级关系!',
|
||||||
|
batchAddRelation: '批量添加关系',
|
||||||
|
history: '操作历史',
|
||||||
|
topo: '拓扑',
|
||||||
|
table: '表格',
|
||||||
|
m2mTips: '当前模型关系为多对多,请前往关系视图进行增删操作',
|
||||||
|
confirmDeleteRelation: '确认删除关系?',
|
||||||
|
tips1: '多个值使用,分割',
|
||||||
|
tips2: '可根据需要修改字段,当值为 空 时,则该字段 置空',
|
||||||
|
tips3: '请选择需要修改的字段',
|
||||||
|
tips4: '必须至少选择一个字段',
|
||||||
|
tips5: '搜索 名称 | 别名',
|
||||||
|
tips6: '加快检索, 可以全文搜索, 无需使用条件过滤\n\n json目前不支持建索引 \n\n文本字符长度超过190不能建索引',
|
||||||
|
tips7: '表现形式是下拉框, 值必须在预定义值里',
|
||||||
|
tips8: '多值, 比如内网IP',
|
||||||
|
tips9: '仅针对前端',
|
||||||
|
tips10: '模型的其他属性通过表达式的方式计算出来\n\n一个代码片段计算返回的值',
|
||||||
|
newUpdateField: '新增修改字段',
|
||||||
|
attributeSettings: '字段设置',
|
||||||
|
},
|
||||||
|
serviceTree: {
|
||||||
|
deleteNode: '删除节点',
|
||||||
|
tips1: '例:q=os_version:centos&sort=os_version',
|
||||||
|
tips2: '表达式搜索',
|
||||||
|
alert1: '管理员 还未配置业务关系, 或者你无权限访问!',
|
||||||
|
copyFailed: '复制失败',
|
||||||
|
deleteRelationConfirm: '确认将选中的 {name} 从当前关系中删除?',
|
||||||
|
},
|
||||||
|
tree: {
|
||||||
|
tips1: '请先到 我的订阅 页面完成订阅!',
|
||||||
|
subSettings: '订阅设置',
|
||||||
|
}
|
||||||
|
}
|
||||||
|
export default cmdb_zh
|
|
@ -13,19 +13,19 @@ const genCmdbRoutes = async () => {
|
||||||
{
|
{
|
||||||
path: '/cmdb/dashboard',
|
path: '/cmdb/dashboard',
|
||||||
name: 'cmdb_dashboard',
|
name: 'cmdb_dashboard',
|
||||||
meta: { title: '仪表盘', icon: 'ops-cmdb-dashboard', selectedIcon: 'ops-cmdb-dashboard-selected', keepAlive: false },
|
meta: { title: 'dashboard', icon: 'ops-cmdb-dashboard', selectedIcon: 'ops-cmdb-dashboard-selected', keepAlive: false },
|
||||||
component: () => import('../views/dashboard/index_v2.vue')
|
component: () => import('../views/dashboard/index_v2.vue')
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/cmdb/disabled1',
|
path: '/cmdb/disabled1',
|
||||||
name: 'cmdb_disabled1',
|
name: 'cmdb_disabled1',
|
||||||
meta: { title: '视图', disabled: true },
|
meta: { title: 'cmdb.menu.views', disabled: true },
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/cmdb/resourceviews',
|
path: '/cmdb/resourceviews',
|
||||||
name: 'cmdb_resource_views',
|
name: 'cmdb_resource_views',
|
||||||
component: RouteView,
|
component: RouteView,
|
||||||
meta: { title: '资源数据', icon: 'ops-cmdb-resource', selectedIcon: 'ops-cmdb-resource-selected', keepAlive: true },
|
meta: { title: 'cmdb.menu.ciTable', icon: 'ops-cmdb-resource', selectedIcon: 'ops-cmdb-resource-selected', keepAlive: true },
|
||||||
hideChildrenInMenu: false,
|
hideChildrenInMenu: false,
|
||||||
children: []
|
children: []
|
||||||
},
|
},
|
||||||
|
@ -33,108 +33,108 @@ const genCmdbRoutes = async () => {
|
||||||
path: '/cmdb/tree_views',
|
path: '/cmdb/tree_views',
|
||||||
component: () => import('../views/tree_views'),
|
component: () => import('../views/tree_views'),
|
||||||
name: 'cmdb_tree_views',
|
name: 'cmdb_tree_views',
|
||||||
meta: { title: '资源层级', icon: 'ops-cmdb-tree', selectedIcon: 'ops-cmdb-tree-selected', keepAlive: false },
|
meta: { title: 'cmdb.menu.ciTree', icon: 'ops-cmdb-tree', selectedIcon: 'ops-cmdb-tree-selected', keepAlive: false },
|
||||||
hideChildrenInMenu: true,
|
hideChildrenInMenu: true,
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
path: '/cmdb/tree_views/:typeId',
|
path: '/cmdb/tree_views/:typeId',
|
||||||
name: 'cmdb_tree_views_item',
|
name: 'cmdb_tree_views_item',
|
||||||
component: () => import('../views/tree_views'),
|
component: () => import('../views/tree_views'),
|
||||||
meta: { title: '资源层级', keepAlive: false },
|
meta: { title: 'cmdb.menu.ciTree', keepAlive: false },
|
||||||
hidden: true
|
hidden: true
|
||||||
}]
|
}]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/cmdb/resourcesearch',
|
path: '/cmdb/resourcesearch',
|
||||||
name: 'cmdb_resource_search',
|
name: 'cmdb_resource_search',
|
||||||
meta: { title: '资源搜索', icon: 'ops-cmdb-search', selectedIcon: 'ops-cmdb-search-selected', keepAlive: false },
|
meta: { title: 'cmdb.menu.ciSearch', icon: 'ops-cmdb-search', selectedIcon: 'ops-cmdb-search-selected', keepAlive: false },
|
||||||
component: () => import('../views/resource_search/index.vue')
|
component: () => import('../views/resource_search/index.vue')
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/cmdb/adc',
|
path: '/cmdb/adc',
|
||||||
name: 'cmdb_auto_discovery_ci',
|
name: 'cmdb_auto_discovery_ci',
|
||||||
meta: { title: '自动发现池', icon: 'ops-cmdb-adc', selectedIcon: 'ops-cmdb-adc-selected', keepAlive: false },
|
meta: { title: 'cmdb.menu.adCIs', icon: 'ops-cmdb-adc', selectedIcon: 'ops-cmdb-adc-selected', keepAlive: false },
|
||||||
component: () => import('../views/discoveryCI/index.vue')
|
component: () => import('../views/discoveryCI/index.vue')
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/cmdb/disabled2',
|
path: '/cmdb/disabled2',
|
||||||
name: 'cmdb_disabled2',
|
name: 'cmdb_disabled2',
|
||||||
meta: { title: '配置', disabled: true, },
|
meta: { title: 'cmdb.menu.config', disabled: true, },
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/cmdb/preference',
|
path: '/cmdb/preference',
|
||||||
component: () => import('../views/preference/index'),
|
component: () => import('../views/preference/index'),
|
||||||
name: 'cmdb_preference',
|
name: 'cmdb_preference',
|
||||||
meta: { title: '我的订阅', icon: 'ops-cmdb-preference', selectedIcon: 'ops-cmdb-preference-selected', keepAlive: false }
|
meta: { title: 'cmdb.menu.preference', icon: 'ops-cmdb-preference', selectedIcon: 'ops-cmdb-preference-selected', keepAlive: false }
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/cmdb/batch',
|
path: '/cmdb/batch',
|
||||||
component: () => import('../views/batch'),
|
component: () => import('../views/batch'),
|
||||||
name: 'cmdb_batch',
|
name: 'cmdb_batch',
|
||||||
meta: { 'title': '批量导入', icon: 'ops-cmdb-batch', selectedIcon: 'ops-cmdb-batch-selected', keepAlive: false }
|
meta: { 'title': 'cmdb.menu.batchUpload', icon: 'ops-cmdb-batch', selectedIcon: 'ops-cmdb-batch-selected', keepAlive: false }
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/cmdb/ci_types',
|
path: '/cmdb/ci_types',
|
||||||
name: 'ci_type',
|
name: 'ci_type',
|
||||||
component: () => import('../views/ci_types/index'),
|
component: () => import('../views/ci_types/index'),
|
||||||
meta: { title: '模型配置', icon: 'ops-cmdb-citype', selectedIcon: 'ops-cmdb-citype-selected', keepAlive: false, permission: ['cmdb_admin', 'admin'] }
|
meta: { title: 'cmdb.menu.citypeManage', icon: 'ops-cmdb-citype', selectedIcon: 'ops-cmdb-citype-selected', keepAlive: false, permission: ['cmdb_admin', 'admin'] }
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/cmdb/disabled3',
|
path: '/cmdb/disabled3',
|
||||||
name: 'cmdb_disabled3',
|
name: 'cmdb_disabled3',
|
||||||
meta: { title: '管理端', disabled: true, permission: ['cmdb_admin', 'OneOPS_Application_Admin', 'admin'], },
|
meta: { title: 'cmdb.menu.backend', disabled: true, permission: ['cmdb_admin', 'OneOPS_Application_Admin', 'admin'], },
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/cmdb/citypes',
|
path: '/cmdb/citypes',
|
||||||
name: 'cmdb_ci_type',
|
name: 'cmdb_ci_type',
|
||||||
component: RouteView,
|
component: RouteView,
|
||||||
redirect: '/cmdb/ci_type',
|
redirect: '/cmdb/ci_type',
|
||||||
meta: { title: '后台管理', icon: 'setting', permission: ['cmdb_admin', 'OneOPS_Application_Admin', 'admin'], },
|
meta: { title: 'cmdb.menu.backendManage', icon: 'setting', permission: ['cmdb_admin', 'OneOPS_Application_Admin', 'admin'], },
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
path: '/cmdb/customdashboard',
|
path: '/cmdb/customdashboard',
|
||||||
name: 'cmdb_custom_dashboard',
|
name: 'cmdb_custom_dashboard',
|
||||||
component: () => import('../views/custom_dashboard/index'),
|
component: () => import('../views/custom_dashboard/index'),
|
||||||
meta: { title: '定制仪表盘', keepAlive: false, icon: 'ops-cmdb-customdashboard', selectedIcon: 'ops-cmdb-customdashboard-selected' }
|
meta: { title: 'cmdb.menu.customDashboard', keepAlive: false, icon: 'ops-cmdb-customdashboard', selectedIcon: 'ops-cmdb-customdashboard-selected' }
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/cmdb/preferencerelation',
|
path: '/cmdb/preferencerelation',
|
||||||
name: 'preference_relation',
|
name: 'preference_relation',
|
||||||
component: () => import('../views/preference_relation/index'),
|
component: () => import('../views/preference_relation/index'),
|
||||||
meta: { title: '业务关系定义', keepAlive: false, icon: 'ops-cmdb-preferencerelation', selectedIcon: 'ops-cmdb-preferencerelation-selected' }
|
meta: { title: 'cmdb.menu.serviceTreeDefine', keepAlive: false, icon: 'ops-cmdb-preferencerelation', selectedIcon: 'ops-cmdb-preferencerelation-selected' }
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/cmdb/modelrelation',
|
path: '/cmdb/modelrelation',
|
||||||
name: 'model_relation',
|
name: 'model_relation',
|
||||||
hideChildrenInMenu: true,
|
hideChildrenInMenu: true,
|
||||||
component: () => import('../views/model_relation/index'),
|
component: () => import('../views/model_relation/index'),
|
||||||
meta: { title: '模型关系', keepAlive: false, icon: 'ops-cmdb-modelrelation', selectedIcon: 'ops-cmdb-modelrelation-selected' }
|
meta: { title: 'cmdb.menu.citypeRelation', keepAlive: false, icon: 'ops-cmdb-modelrelation', selectedIcon: 'ops-cmdb-modelrelation-selected' }
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/cmdb/operationhistory',
|
path: '/cmdb/operationhistory',
|
||||||
name: 'operation_history',
|
name: 'operation_history',
|
||||||
hideChildrenInMenu: true,
|
hideChildrenInMenu: true,
|
||||||
component: () => import('../views/operation_history/index'),
|
component: () => import('../views/operation_history/index'),
|
||||||
meta: { title: '操作审计', keepAlive: false, icon: 'ops-cmdb-operation', selectedIcon: 'ops-cmdb-operation-selected' }
|
meta: { title: 'cmdb.menu.operationHistory', keepAlive: false, icon: 'ops-cmdb-operation', selectedIcon: 'ops-cmdb-operation-selected' }
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/cmdb/relationtype',
|
path: '/cmdb/relationtype',
|
||||||
name: 'relation_type',
|
name: 'relation_type',
|
||||||
hideChildrenInMenu: true,
|
hideChildrenInMenu: true,
|
||||||
component: () => import('../views/relation_type/index'),
|
component: () => import('../views/relation_type/index'),
|
||||||
meta: { title: '关系类型', keepAlive: false, icon: 'ops-cmdb-relationtype', selectedIcon: 'ops-cmdb-relationtype-selected' }
|
meta: { title: 'cmdb.menu.relationType', keepAlive: false, icon: 'ops-cmdb-relationtype', selectedIcon: 'ops-cmdb-relationtype-selected' }
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/cmdb/discovery',
|
path: '/cmdb/discovery',
|
||||||
name: 'discovery',
|
name: 'discovery',
|
||||||
component: () => import('../views/discovery/index'),
|
component: () => import('../views/discovery/index'),
|
||||||
meta: { title: '自动发现', keepAlive: false, icon: 'ops-cmdb-adr', selectedIcon: 'ops-cmdb-adr-selected' }
|
meta: { title: 'cmdb.menu.ad', keepAlive: false, icon: 'ops-cmdb-adr', selectedIcon: 'ops-cmdb-adr-selected' }
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
// 动态添加订阅的条目及业务关系
|
// Dynamically add subscription items and business relationships
|
||||||
const [preference, relation] = await Promise.all([getPreference(), getRelationView()])
|
const [preference, relation] = await Promise.all([getPreference(), getRelationView()])
|
||||||
|
|
||||||
preference.forEach(item => {
|
preference.forEach(item => {
|
||||||
|
@ -143,7 +143,7 @@ const genCmdbRoutes = async () => {
|
||||||
component: () => import(`../views/ci/index`),
|
component: () => import(`../views/ci/index`),
|
||||||
name: `cmdb_${item.id}`,
|
name: `cmdb_${item.id}`,
|
||||||
meta: { title: item.alias, keepAlive: false, typeId: item.id, name: item.name, customIcon: item.icon },
|
meta: { title: item.alias, keepAlive: false, typeId: item.id, name: item.name, customIcon: item.icon },
|
||||||
// hideChildrenInMenu: true // 强制显示 MenuItem 而不是 SubMenu
|
// hideChildrenInMenu: true // Force display of MenuItem instead of SubMenu
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
const lastTypeId = window.localStorage.getItem('ops_ci_typeid') || undefined
|
const lastTypeId = window.localStorage.getItem('ops_ci_typeid') || undefined
|
||||||
|
|
|
@ -1,28 +1,32 @@
|
||||||
export const valueTypeMap = {
|
import i18n from '@/lang'
|
||||||
'0': '整数',
|
|
||||||
'1': '浮点数',
|
export const valueTypeMap = () => {
|
||||||
'2': '文本',
|
return {
|
||||||
'3': '日期时间',
|
'0': i18n.t('cmdb.ciType.int'),
|
||||||
'4': '日期',
|
'1': i18n.t('cmdb.ciType.float'),
|
||||||
'5': '时间',
|
'2': i18n.t('cmdb.ciType.text'),
|
||||||
'6': 'JSON',
|
'3': i18n.t('cmdb.ciType.datetime'),
|
||||||
'7': '密码',
|
'4': i18n.t('cmdb.ciType.date'),
|
||||||
'8': '链接'
|
'5': i18n.t('cmdb.ciType.time'),
|
||||||
}
|
'6': 'JSON',
|
||||||
|
'7': i18n.t('cmdb.ciType.password'),
|
||||||
export const defautValueColor = [
|
'8': i18n.t('cmdb.ciType.link')
|
||||||
{ value: '#d9d9d9' },
|
}
|
||||||
{ value: '#ffccc7' },
|
}
|
||||||
{ value: '#ffd8bf' },
|
|
||||||
{ value: '#ffe7ba' },
|
export const defautValueColor = [
|
||||||
{ value: '#fff1b8' },
|
{ value: '#d9d9d9' },
|
||||||
{ value: '#f4ffb8' },
|
{ value: '#ffccc7' },
|
||||||
{ value: '#d9f7be' },
|
{ value: '#ffd8bf' },
|
||||||
{ value: '#b5f5ec' },
|
{ value: '#ffe7ba' },
|
||||||
{ value: '#bae7ff' },
|
{ value: '#fff1b8' },
|
||||||
{ value: '#d6e4ff' },
|
{ value: '#f4ffb8' },
|
||||||
{ value: '#efdbff' },
|
{ value: '#d9f7be' },
|
||||||
{ value: '#ffd6e7' },
|
{ value: '#b5f5ec' },
|
||||||
]
|
{ value: '#bae7ff' },
|
||||||
|
{ value: '#d6e4ff' },
|
||||||
export const defaultBGColors = ['#ffccc7', '#ffd8bf', '#ffe7ba', '#fff1b8', '#d9f7be', '#b5f5ec', '#bae7ff', '#d6e4ff', '#efdbff', '#ffd6e7']
|
{ value: '#efdbff' },
|
||||||
|
{ value: '#ffd6e7' },
|
||||||
|
]
|
||||||
|
|
||||||
|
export const defaultBGColors = ['#ffccc7', '#ffd8bf', '#ffe7ba', '#fff1b8', '#d9f7be', '#b5f5ec', '#bae7ff', '#d6e4ff', '#efdbff', '#ffd6e7']
|
||||||
|
|
|
@ -16,9 +16,9 @@
|
||||||
<CiUploadTable :ciTypeAttrs="ciTypeAttrs" ref="ciUploadTable" :uploadData="uploadData"></CiUploadTable>
|
<CiUploadTable :ciTypeAttrs="ciTypeAttrs" ref="ciUploadTable" :uploadData="uploadData"></CiUploadTable>
|
||||||
<div class="cmdb-batch-upload-action">
|
<div class="cmdb-batch-upload-action">
|
||||||
<a-space size="large">
|
<a-space size="large">
|
||||||
<a-button type="primary" ghost @click="handleCancel">取消</a-button>
|
<a-button type="primary" ghost @click="handleCancel">{{ $t('cancel') }}</a-button>
|
||||||
<a-button @click="handleUpload" type="primary">上传</a-button>
|
<a-button @click="handleUpload" type="primary">{{ $t('upload') }}</a-button>
|
||||||
<a-button v-if="hasError && !isUploading" @click="downloadError" type="primary">失败下载</a-button>
|
<a-button v-if="hasError && !isUploading" @click="downloadError" type="primary">{{ $t('cmdb.batch.downloadFailed') }}</a-button>
|
||||||
</a-space>
|
</a-space>
|
||||||
</div>
|
</div>
|
||||||
</a-col>
|
</a-col>
|
||||||
|
@ -109,7 +109,7 @@ export default {
|
||||||
},
|
},
|
||||||
handleUpload() {
|
handleUpload() {
|
||||||
if (!this.ciType) {
|
if (!this.ciType) {
|
||||||
this.$message.error('尚未选择模板类型')
|
this.$message.error(this.$t('cmdb.batch.unselectCIType'))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if (this.uploadData && this.uploadData.length > 0) {
|
if (this.uploadData && this.uploadData.length > 0) {
|
||||||
|
@ -118,7 +118,7 @@ export default {
|
||||||
this.$refs.uploadResult.upload2Server()
|
this.$refs.uploadResult.upload2Server()
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
this.$message.error('请上传文件')
|
this.$message.error(this.$t('cmdb.batch.pleaseUploadFile'))
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
handleCancel() {
|
handleCancel() {
|
||||||
|
@ -127,7 +127,7 @@ export default {
|
||||||
this.$refs.ciTypeChoice.selectNum = null
|
this.$refs.ciTypeChoice.selectNum = null
|
||||||
this.hasError = false
|
this.hasError = false
|
||||||
} else {
|
} else {
|
||||||
this.$message.warning('批量上传已取消')
|
this.$message.warning(this.$t('cmdb.batch.batchUploadCanceled'))
|
||||||
this.isUploading = false
|
this.isUploading = false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
<template>
|
<template>
|
||||||
<a-space>
|
<a-space>
|
||||||
<span>模板类型:</span>
|
<span>{{ $t('cmdb.ciType.ciType') }}: </span>
|
||||||
<a-select
|
<a-select
|
||||||
showSearch
|
showSearch
|
||||||
placeholder="请选择模板类型"
|
:placeholder="$t('cmdb.batch.selectCITypeTips')"
|
||||||
@change="selectCiType"
|
@change="selectCiType"
|
||||||
:style="{ width: '300px' }"
|
:style="{ width: '300px' }"
|
||||||
class="ops-select"
|
class="ops-select"
|
||||||
|
@ -20,7 +20,7 @@
|
||||||
type="primary"
|
type="primary"
|
||||||
class="ops-button-primary"
|
class="ops-button-primary"
|
||||||
icon="download"
|
icon="download"
|
||||||
>下载模板</a-button
|
>{{ $t('cmdb.batch.downloadTemplate') }}</a-button
|
||||||
>
|
>
|
||||||
<a-modal
|
<a-modal
|
||||||
:bodyStyle="{ paddingTop: 0 }"
|
:bodyStyle="{ paddingTop: 0 }"
|
||||||
|
@ -31,14 +31,14 @@
|
||||||
@ok="handleOk"
|
@ok="handleOk"
|
||||||
wrapClassName="ci-type-choice-modal"
|
wrapClassName="ci-type-choice-modal"
|
||||||
>
|
>
|
||||||
<a-divider orientation="left">模型属性</a-divider>
|
<a-divider orientation="left">{{ $t('cmdb.ciType.attributes') }}</a-divider>
|
||||||
<a-checkbox
|
<a-checkbox
|
||||||
@change="changeCheckAll"
|
@change="changeCheckAll"
|
||||||
:style="{ marginBottom: '20px' }"
|
:style="{ marginBottom: '20px' }"
|
||||||
:indeterminate="indeterminate"
|
:indeterminate="indeterminate"
|
||||||
:checked="checkAll"
|
:checked="checkAll"
|
||||||
>
|
>
|
||||||
全选
|
{{ $t('checkAll') }}
|
||||||
</a-checkbox>
|
</a-checkbox>
|
||||||
<br />
|
<br />
|
||||||
<a-checkbox-group style="width:100%" v-model="checkedAttrs">
|
<a-checkbox-group style="width:100%" v-model="checkedAttrs">
|
||||||
|
@ -52,7 +52,7 @@
|
||||||
</a-row>
|
</a-row>
|
||||||
</a-checkbox-group>
|
</a-checkbox-group>
|
||||||
<template v-if="parentsType && parentsType.length">
|
<template v-if="parentsType && parentsType.length">
|
||||||
<a-divider orientation="left">模型关联</a-divider>
|
<a-divider orientation="left">{{ $t('cmdb.ciType.relation') }}</a-divider>
|
||||||
<a-row :gutter="[24, 24]" align="top" type="flex">
|
<a-row :gutter="[24, 24]" align="top" type="flex">
|
||||||
<a-col :style="{ display: 'inline-flex' }" :span="12" v-for="item in parentsType" :key="item.id">
|
<a-col :style="{ display: 'inline-flex' }" :span="12" v-for="item in parentsType" :key="item.id">
|
||||||
<a-checkbox @click="clickParent(item)" :checked="checkedParents.includes(item.alias || item.name)">
|
<a-checkbox @click="clickParent(item)" :checked="checkedParents.includes(item.alias || item.name)">
|
||||||
|
@ -150,7 +150,7 @@ export default {
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
selectCiType(el) {
|
selectCiType(el) {
|
||||||
// 当选择好模板类型时的回调函数
|
// Callback function when a template type is selected
|
||||||
getCITypeAttributesById(el).then((res) => {
|
getCITypeAttributesById(el).then((res) => {
|
||||||
this.$emit('getCiTypeAttr', res)
|
this.$emit('getCiTypeAttr', res)
|
||||||
this.selectCiTypeAttrList = res
|
this.selectCiTypeAttrList = res
|
||||||
|
|
|
@ -10,8 +10,8 @@
|
||||||
:disabled="!ciType || isUploading"
|
:disabled="!ciType || isUploading"
|
||||||
>
|
>
|
||||||
<img :style="{ width: '80px', height: '80px' }" src="@/assets/file_upload.png" />
|
<img :style="{ width: '80px', height: '80px' }" src="@/assets/file_upload.png" />
|
||||||
<p class="ant-upload-text">点击或拖拽文件至此上传!</p>
|
<p class="ant-upload-text">{{ $t('cmdb.batch.drawTips') }}</p>
|
||||||
<p class="ant-upload-hint">支持文件类型:xls,xlsx</p>
|
<p class="ant-upload-hint">{{ $t('cmdb.batch.supportFileTypes') }}</p>
|
||||||
</a-upload-dragger>
|
</a-upload-dragger>
|
||||||
<div v-for="item in fileList" :key="item.name" class="cmdb-batch-upload-dragger-file">
|
<div v-for="item in fileList" :key="item.name" class="cmdb-batch-upload-dragger-file">
|
||||||
<span><a-icon type="file" :style="{ color: '#2F54EB', marginRight: '5px' }" />{{ item.name }}</span>
|
<span><a-icon type="file" :style="{ color: '#2F54EB', marginRight: '5px' }" />{{ item.name }}</span>
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="cmdb-batch-upload-result" v-if="visible">
|
<div class="cmdb-batch-upload-result" v-if="visible">
|
||||||
<h3 class="cmdb-batch-upload-result-title">上传结果</h3>
|
<h3 class="cmdb-batch-upload-result-title">{{ $t('cmdb.batch.uploadResult') }}</h3>
|
||||||
<div class="cmdb-batch-upload-result-content">
|
<div class="cmdb-batch-upload-result-content">
|
||||||
<h4>
|
<h4>
|
||||||
共 <span style="color: blue">{{ total }}</span> 条,已成功
|
{{ $t('cmdb.batch.total') }} <span style="color: blue">{{ total }}</span> {{ $t('cmdb.batch.successItems') }}
|
||||||
<span style="color: lightgreen">{{ success }}</span> 条,失败 <span style="color: red">{{ errorNum }} </span>条
|
<span style="color: lightgreen">{{ success }}</span> {{ $t('cmdb.batch.failedItems') }} <span style="color: red">{{ errorNum }} </span>{{ $t('cmdb.batch.items') }}
|
||||||
</h4>
|
</h4>
|
||||||
<div>
|
<div>
|
||||||
<span>错误信息:</span>
|
<span>{{ $t('cmdb.batch.errorTips') }}: </span>
|
||||||
<ol>
|
<ol>
|
||||||
<li :key="item + index" v-for="(item, index) in errorItems">{{ item }}</li>
|
<li :key="item + index" v-for="(item, index) in errorItems">{{ item }}</li>
|
||||||
</ol>
|
</ol>
|
||||||
|
@ -71,7 +71,7 @@ export default {
|
||||||
if (r.status === 'fulfilled') {
|
if (r.status === 'fulfilled') {
|
||||||
this.success += 1
|
this.success += 1
|
||||||
} else {
|
} else {
|
||||||
this.errorItems.push(r?.reason?.response?.data.message ?? '请求出现错误,请稍后再试')
|
this.errorItems.push(r?.reason?.response?.data.message ?? this.$t('cmdb.batch.requestFailedTips'))
|
||||||
this.errorNum += 1
|
this.errorNum += 1
|
||||||
this.$emit('uploadResultError', 6 * i + j)
|
this.$emit('uploadResultError', 6 * i + j)
|
||||||
}
|
}
|
||||||
|
@ -86,7 +86,7 @@ export default {
|
||||||
}
|
}
|
||||||
if (this.isUploading) {
|
if (this.isUploading) {
|
||||||
this.$emit('uploadResultDone')
|
this.$emit('uploadResultDone')
|
||||||
this.$message.success('批量上传已完成')
|
this.$message.success(this.$t('cmdb.batch.requestSuccessTips'))
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,6 +1,6 @@
|
||||||
<template>
|
<template>
|
||||||
<a-drawer
|
<a-drawer
|
||||||
title="批量添加关系"
|
:title="$t('cmdb.ci.batchAddRelation')"
|
||||||
width="50%"
|
width="50%"
|
||||||
@close="() => { visible = false; $emit('refresh', true) }"
|
@close="() => { visible = false; $emit('refresh', true) }"
|
||||||
:visible="visible"
|
:visible="visible"
|
||||||
|
|
|
@ -1,342 +1,344 @@
|
||||||
<template>
|
<template>
|
||||||
<CustomDrawer
|
<CustomDrawer
|
||||||
width="80%"
|
width="80%"
|
||||||
placement="left"
|
placement="left"
|
||||||
@close="
|
@close="
|
||||||
() => {
|
() => {
|
||||||
visible = false
|
visible = false
|
||||||
}
|
}
|
||||||
"
|
"
|
||||||
:visible="visible"
|
:visible="visible"
|
||||||
:hasTitle="false"
|
:hasTitle="false"
|
||||||
:hasFooter="false"
|
:hasFooter="false"
|
||||||
:bodyStyle="{ padding: 0, height: '100vh' }"
|
:bodyStyle="{ padding: 0, height: '100vh' }"
|
||||||
wrapClassName="ci-detail"
|
wrapClassName="ci-detail"
|
||||||
destroyOnClose
|
destroyOnClose
|
||||||
>
|
>
|
||||||
<a-tabs v-model="activeTabKey" @change="changeTab">
|
<a-tabs v-model="activeTabKey" @change="changeTab">
|
||||||
<a-tab-pane key="tab_1">
|
<a-tab-pane key="tab_1">
|
||||||
<span slot="tab"><a-icon type="book" />属性</span>
|
<span slot="tab"><a-icon type="book" />{{ $t('cmdb.attribute') }}</span>
|
||||||
<div :style="{ maxHeight: `${windowHeight - 44}px`, overflow: 'auto', padding: '24px' }" class="ci-detail-attr">
|
<div :style="{ maxHeight: `${windowHeight - 44}px`, overflow: 'auto', padding: '24px' }" class="ci-detail-attr">
|
||||||
<el-descriptions
|
<el-descriptions
|
||||||
:title="group.name || '其他'"
|
:title="group.name || $t('other')"
|
||||||
:key="group.name"
|
:key="group.name"
|
||||||
v-for="group in attributeGroups"
|
v-for="group in attributeGroups"
|
||||||
border
|
border
|
||||||
:column="3"
|
:column="3"
|
||||||
>
|
>
|
||||||
<el-descriptions-item
|
<el-descriptions-item
|
||||||
:label="`${attr.alias || attr.name}`"
|
:label="`${attr.alias || attr.name}`"
|
||||||
:key="attr.name"
|
:key="attr.name"
|
||||||
v-for="attr in group.attributes"
|
v-for="attr in group.attributes"
|
||||||
>
|
>
|
||||||
<CiDetailAttrContent :ci="ci" :attr="attr" @refresh="refresh" @updateCIByself="updateCIByself" />
|
<CiDetailAttrContent :ci="ci" :attr="attr" @refresh="refresh" @updateCIByself="updateCIByself" />
|
||||||
</el-descriptions-item>
|
</el-descriptions-item>
|
||||||
</el-descriptions>
|
</el-descriptions>
|
||||||
</div>
|
</div>
|
||||||
</a-tab-pane>
|
</a-tab-pane>
|
||||||
<a-tab-pane key="tab_2">
|
<a-tab-pane key="tab_2">
|
||||||
<span slot="tab"><a-icon type="branches" />关系</span>
|
<span slot="tab"><a-icon type="branches" />{{ $t('cmdb.relation') }}</span>
|
||||||
<div :style="{ padding: '24px' }">
|
<div :style="{ padding: '24px' }">
|
||||||
<CiDetailRelation ref="ciDetailRelation" :ciId="ciId" :typeId="typeId" :ci="ci" />
|
<CiDetailRelation ref="ciDetailRelation" :ciId="ciId" :typeId="typeId" :ci="ci" />
|
||||||
</div>
|
</div>
|
||||||
</a-tab-pane>
|
</a-tab-pane>
|
||||||
<a-tab-pane key="tab_3">
|
<a-tab-pane key="tab_3">
|
||||||
<span slot="tab"><a-icon type="clock-circle" />操作历史</span>
|
<span slot="tab"><a-icon type="clock-circle" />{{ $t('cmdb.ci.history') }}</span>
|
||||||
<div :style="{ padding: '24px', height: 'calc(100vh - 44px)' }">
|
<div :style="{ padding: '24px', height: 'calc(100vh - 44px)' }">
|
||||||
<vxe-table
|
<vxe-table
|
||||||
ref="xTable"
|
ref="xTable"
|
||||||
:data="ciHistory"
|
:data="ciHistory"
|
||||||
size="small"
|
size="small"
|
||||||
:max-height="`${windowHeight - 94}px`"
|
:max-height="`${windowHeight - 94}px`"
|
||||||
:span-method="mergeRowMethod"
|
:span-method="mergeRowMethod"
|
||||||
border
|
border
|
||||||
:scroll-y="{ enabled: false }"
|
:scroll-y="{ enabled: false }"
|
||||||
class="ops-stripe-table"
|
class="ops-stripe-table"
|
||||||
>
|
>
|
||||||
<vxe-table-column sortable field="created_at" title="时间"></vxe-table-column>
|
<vxe-table-column sortable field="created_at" :title="$t('created_at')"></vxe-table-column>
|
||||||
<vxe-table-column
|
<vxe-table-column
|
||||||
field="username"
|
field="username"
|
||||||
title="用户"
|
:title="$t('user')"
|
||||||
:filters="[]"
|
:filters="[]"
|
||||||
:filter-method="filterUsernameMethod"
|
:filter-method="filterUsernameMethod"
|
||||||
></vxe-table-column>
|
></vxe-table-column>
|
||||||
<vxe-table-column
|
<vxe-table-column
|
||||||
field="operate_type"
|
field="operate_type"
|
||||||
:filters="[
|
:filters="[
|
||||||
{ value: 0, label: '新增' },
|
{ value: 0, label: $t('new') },
|
||||||
{ value: 1, label: '删除' },
|
{ value: 1, label: $t('delete') },
|
||||||
{ value: 3, label: '修改' },
|
{ value: 3, label: $t('update') },
|
||||||
]"
|
]"
|
||||||
:filter-method="filterOperateMethod"
|
:filter-method="filterOperateMethod"
|
||||||
title="操作"
|
:title="$t('operation')"
|
||||||
>
|
>
|
||||||
<template #default="{ row }">
|
<template #default="{ row }">
|
||||||
{{ operateTypeMap[row.operate_type] }}
|
{{ operateTypeMap[row.operate_type] }}
|
||||||
</template>
|
</template>
|
||||||
</vxe-table-column>
|
</vxe-table-column>
|
||||||
<vxe-table-column
|
<vxe-table-column
|
||||||
field="attr_alias"
|
field="attr_alias"
|
||||||
title="属性"
|
:title="$t('cmdb.attribute')"
|
||||||
:filters="[]"
|
:filters="[]"
|
||||||
:filter-method="filterAttrMethod"
|
:filter-method="filterAttrMethod"
|
||||||
></vxe-table-column>
|
></vxe-table-column>
|
||||||
<vxe-table-column field="old" title="旧"></vxe-table-column>
|
<vxe-table-column field="old" :title="$t('cmdb.history.old')"></vxe-table-column>
|
||||||
<vxe-table-column field="new" title="新"></vxe-table-column>
|
<vxe-table-column field="new" :title="$t('cmdb.history.new')"></vxe-table-column>
|
||||||
</vxe-table>
|
</vxe-table>
|
||||||
</div>
|
</div>
|
||||||
</a-tab-pane>
|
</a-tab-pane>
|
||||||
<a-tab-pane key="tab_4">
|
<a-tab-pane key="tab_4">
|
||||||
<span slot="tab"><ops-icon type="itsm_auto_trigger" />触发历史</span>
|
<span slot="tab"><ops-icon type="itsm_auto_trigger" />{{ $t('cmdb.history.triggerHistory') }}</span>
|
||||||
<div :style="{ padding: '24px', height: 'calc(100vh - 44px)' }">
|
<div :style="{ padding: '24px', height: 'calc(100vh - 44px)' }">
|
||||||
<TriggerTable :ci_id="ci._id" />
|
<TriggerTable :ci_id="ci._id" />
|
||||||
</div>
|
</div>
|
||||||
</a-tab-pane>
|
</a-tab-pane>
|
||||||
</a-tabs>
|
</a-tabs>
|
||||||
</CustomDrawer>
|
</CustomDrawer>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import _ from 'lodash'
|
import _ from 'lodash'
|
||||||
import { Descriptions, DescriptionsItem } from 'element-ui'
|
import { Descriptions, DescriptionsItem } from 'element-ui'
|
||||||
import { getCITypeGroupById, getCITypes } from '@/modules/cmdb/api/CIType'
|
import { getCITypeGroupById, getCITypes } from '@/modules/cmdb/api/CIType'
|
||||||
import { getCIHistory } from '@/modules/cmdb/api/history'
|
import { getCIHistory } from '@/modules/cmdb/api/history'
|
||||||
import { getCIById } from '@/modules/cmdb/api/ci'
|
import { getCIById } from '@/modules/cmdb/api/ci'
|
||||||
import CiDetailAttrContent from './ciDetailAttrContent.vue'
|
import CiDetailAttrContent from './ciDetailAttrContent.vue'
|
||||||
import CiDetailRelation from './ciDetailRelation.vue'
|
import CiDetailRelation from './ciDetailRelation.vue'
|
||||||
import TriggerTable from '../../operation_history/modules/triggerTable.vue'
|
import TriggerTable from '../../operation_history/modules/triggerTable.vue'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
ElDescriptions: Descriptions,
|
ElDescriptions: Descriptions,
|
||||||
ElDescriptionsItem: DescriptionsItem,
|
ElDescriptionsItem: DescriptionsItem,
|
||||||
CiDetailAttrContent,
|
CiDetailAttrContent,
|
||||||
CiDetailRelation,
|
CiDetailRelation,
|
||||||
TriggerTable,
|
TriggerTable,
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
typeId: {
|
typeId: {
|
||||||
type: Number,
|
type: Number,
|
||||||
required: true,
|
required: true,
|
||||||
},
|
},
|
||||||
treeViewsLevels: {
|
treeViewsLevels: {
|
||||||
type: Array,
|
type: Array,
|
||||||
default: () => [],
|
default: () => [],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
const operateTypeMap = {
|
return {
|
||||||
0: '新增',
|
visible: false,
|
||||||
1: '删除',
|
ci: {},
|
||||||
2: '修改',
|
attributeGroups: [],
|
||||||
}
|
activeTabKey: 'tab_1',
|
||||||
return {
|
rowSpanMap: {},
|
||||||
operateTypeMap,
|
ciHistory: [],
|
||||||
visible: false,
|
ciId: null,
|
||||||
ci: {},
|
ci_types: [],
|
||||||
attributeGroups: [],
|
}
|
||||||
activeTabKey: 'tab_1',
|
},
|
||||||
rowSpanMap: {},
|
computed: {
|
||||||
ciHistory: [],
|
windowHeight() {
|
||||||
ciId: null,
|
return this.$store.state.windowHeight
|
||||||
ci_types: [],
|
},
|
||||||
}
|
|
||||||
},
|
operateTypeMap() {
|
||||||
computed: {
|
return {
|
||||||
windowHeight() {
|
0: this.$t('new'),
|
||||||
return this.$store.state.windowHeight
|
1: this.$t('delete'),
|
||||||
},
|
2: this.$t('update'),
|
||||||
},
|
}
|
||||||
provide() {
|
},
|
||||||
return {
|
},
|
||||||
ci_types: () => {
|
provide() {
|
||||||
return this.ci_types
|
return {
|
||||||
},
|
ci_types: () => {
|
||||||
}
|
return this.ci_types
|
||||||
},
|
},
|
||||||
inject: ['reload', 'handleSearch', 'attrList'],
|
}
|
||||||
methods: {
|
},
|
||||||
create(ciId, activeTabKey = 'tab_1', ciDetailRelationKey = '1') {
|
inject: ['reload', 'handleSearch', 'attrList'],
|
||||||
this.visible = true
|
methods: {
|
||||||
this.activeTabKey = activeTabKey
|
create(ciId, activeTabKey = 'tab_1', ciDetailRelationKey = '1') {
|
||||||
if (activeTabKey === 'tab_2') {
|
this.visible = true
|
||||||
this.$nextTick(() => {
|
this.activeTabKey = activeTabKey
|
||||||
this.$refs.ciDetailRelation.activeKey = ciDetailRelationKey
|
if (activeTabKey === 'tab_2') {
|
||||||
})
|
this.$nextTick(() => {
|
||||||
}
|
this.$refs.ciDetailRelation.activeKey = ciDetailRelationKey
|
||||||
this.ciId = ciId
|
})
|
||||||
this.getAttributes()
|
}
|
||||||
this.getCI()
|
this.ciId = ciId
|
||||||
this.getCIHistory()
|
this.getAttributes()
|
||||||
getCITypes().then((res) => {
|
this.getCI()
|
||||||
this.ci_types = res.ci_types
|
this.getCIHistory()
|
||||||
})
|
getCITypes().then((res) => {
|
||||||
},
|
this.ci_types = res.ci_types
|
||||||
getAttributes() {
|
})
|
||||||
getCITypeGroupById(this.typeId, { need_other: 1 })
|
},
|
||||||
.then((res) => {
|
getAttributes() {
|
||||||
this.attributeGroups = res
|
getCITypeGroupById(this.typeId, { need_other: 1 })
|
||||||
})
|
.then((res) => {
|
||||||
.catch((e) => {})
|
this.attributeGroups = res
|
||||||
},
|
})
|
||||||
getCI() {
|
.catch((e) => {})
|
||||||
getCIById(this.ciId)
|
},
|
||||||
.then((res) => {
|
getCI() {
|
||||||
// this.ci = res.ci
|
getCIById(this.ciId)
|
||||||
this.ci = res.result[0]
|
.then((res) => {
|
||||||
})
|
// this.ci = res.ci
|
||||||
.catch((e) => {})
|
this.ci = res.result[0]
|
||||||
},
|
})
|
||||||
|
.catch((e) => {})
|
||||||
getCIHistory() {
|
},
|
||||||
getCIHistory(this.ciId)
|
|
||||||
.then((res) => {
|
getCIHistory() {
|
||||||
this.ciHistory = res
|
getCIHistory(this.ciId)
|
||||||
|
.then((res) => {
|
||||||
const rowSpanMap = {}
|
this.ciHistory = res
|
||||||
let startIndex = 0
|
|
||||||
let startCount = 1
|
const rowSpanMap = {}
|
||||||
res.forEach((item, index) => {
|
let startIndex = 0
|
||||||
if (index === 0) {
|
let startCount = 1
|
||||||
return
|
res.forEach((item, index) => {
|
||||||
}
|
if (index === 0) {
|
||||||
if (res[index].record_id === res[startIndex].record_id) {
|
return
|
||||||
startCount += 1
|
}
|
||||||
rowSpanMap[index] = 0
|
if (res[index].record_id === res[startIndex].record_id) {
|
||||||
if (index === res.length - 1) {
|
startCount += 1
|
||||||
rowSpanMap[startIndex] = startCount
|
rowSpanMap[index] = 0
|
||||||
}
|
if (index === res.length - 1) {
|
||||||
} else {
|
rowSpanMap[startIndex] = startCount
|
||||||
rowSpanMap[startIndex] = startCount
|
}
|
||||||
startIndex = index
|
} else {
|
||||||
startCount = 1
|
rowSpanMap[startIndex] = startCount
|
||||||
if (index === res.length - 1) {
|
startIndex = index
|
||||||
rowSpanMap[index] = 1
|
startCount = 1
|
||||||
}
|
if (index === res.length - 1) {
|
||||||
}
|
rowSpanMap[index] = 1
|
||||||
})
|
}
|
||||||
this.rowSpanMap = rowSpanMap
|
}
|
||||||
})
|
})
|
||||||
.catch((e) => {
|
this.rowSpanMap = rowSpanMap
|
||||||
console.log(e)
|
})
|
||||||
})
|
.catch((e) => {
|
||||||
},
|
console.log(e)
|
||||||
changeTab(key) {
|
})
|
||||||
this.activeTabKey = key
|
},
|
||||||
if (key === 'tab_3') {
|
changeTab(key) {
|
||||||
this.$nextTick(() => {
|
this.activeTabKey = key
|
||||||
const $table = this.$refs.xTable
|
if (key === 'tab_3') {
|
||||||
if ($table) {
|
this.$nextTick(() => {
|
||||||
const usernameColumn = $table.getColumnByField('username')
|
const $table = this.$refs.xTable
|
||||||
const attrColumn = $table.getColumnByField('attr_alias')
|
if ($table) {
|
||||||
if (usernameColumn) {
|
const usernameColumn = $table.getColumnByField('username')
|
||||||
const usernameList = [...new Set(this.ciHistory.map((item) => item.username))]
|
const attrColumn = $table.getColumnByField('attr_alias')
|
||||||
$table.setFilter(
|
if (usernameColumn) {
|
||||||
usernameColumn,
|
const usernameList = [...new Set(this.ciHistory.map((item) => item.username))]
|
||||||
usernameList.map((item) => {
|
$table.setFilter(
|
||||||
return {
|
usernameColumn,
|
||||||
value: item,
|
usernameList.map((item) => {
|
||||||
label: item,
|
return {
|
||||||
}
|
value: item,
|
||||||
})
|
label: item,
|
||||||
)
|
}
|
||||||
}
|
})
|
||||||
if (attrColumn) {
|
)
|
||||||
$table.setFilter(
|
}
|
||||||
attrColumn,
|
if (attrColumn) {
|
||||||
this.attrList().map((attr) => {
|
$table.setFilter(
|
||||||
return { value: attr.alias || attr.name, label: attr.alias || attr.name }
|
attrColumn,
|
||||||
})
|
this.attrList().map((attr) => {
|
||||||
)
|
return { value: attr.alias || attr.name, label: attr.alias || attr.name }
|
||||||
}
|
})
|
||||||
}
|
)
|
||||||
})
|
}
|
||||||
}
|
}
|
||||||
},
|
})
|
||||||
filterUsernameMethod({ value, row, column }) {
|
}
|
||||||
return row.username === value
|
},
|
||||||
},
|
filterUsernameMethod({ value, row, column }) {
|
||||||
filterOperateMethod({ value, row, column }) {
|
return row.username === value
|
||||||
return Number(row.operate_type) === Number(value)
|
},
|
||||||
},
|
filterOperateMethod({ value, row, column }) {
|
||||||
filterAttrMethod({ value, row, column }) {
|
return Number(row.operate_type) === Number(value)
|
||||||
return row.attr_alias === value
|
},
|
||||||
},
|
filterAttrMethod({ value, row, column }) {
|
||||||
refresh(editAttrName) {
|
return row.attr_alias === value
|
||||||
this.getCI()
|
},
|
||||||
const _find = this.treeViewsLevels.find((level) => level.name === editAttrName)
|
refresh(editAttrName) {
|
||||||
// 修改的字段为树形视图订阅的字段 则全部reload
|
this.getCI()
|
||||||
setTimeout(() => {
|
const _find = this.treeViewsLevels.find((level) => level.name === editAttrName)
|
||||||
if (_find) {
|
// 修改的字段为树形视图订阅的字段 则全部reload
|
||||||
this.reload()
|
setTimeout(() => {
|
||||||
} else {
|
if (_find) {
|
||||||
this.handleSearch()
|
this.reload()
|
||||||
}
|
} else {
|
||||||
}, 500)
|
this.handleSearch()
|
||||||
},
|
}
|
||||||
mergeRowMethod({ row, _rowIndex, column, visibleData }) {
|
}, 500)
|
||||||
const fields = ['created_at', 'username']
|
},
|
||||||
const cellValue1 = row['created_at']
|
mergeRowMethod({ row, _rowIndex, column, visibleData }) {
|
||||||
const cellValue2 = row['username']
|
const fields = ['created_at', 'username']
|
||||||
if (cellValue1 && cellValue2 && fields.includes(column.property)) {
|
const cellValue1 = row['created_at']
|
||||||
const prevRow = visibleData[_rowIndex - 1]
|
const cellValue2 = row['username']
|
||||||
let nextRow = visibleData[_rowIndex + 1]
|
if (cellValue1 && cellValue2 && fields.includes(column.property)) {
|
||||||
if (prevRow && prevRow['created_at'] === cellValue1 && prevRow['username'] === cellValue2) {
|
const prevRow = visibleData[_rowIndex - 1]
|
||||||
return { rowspan: 0, colspan: 0 }
|
let nextRow = visibleData[_rowIndex + 1]
|
||||||
} else {
|
if (prevRow && prevRow['created_at'] === cellValue1 && prevRow['username'] === cellValue2) {
|
||||||
let countRowspan = 1
|
return { rowspan: 0, colspan: 0 }
|
||||||
while (nextRow && nextRow['created_at'] === cellValue1 && nextRow['username'] === cellValue2) {
|
} else {
|
||||||
nextRow = visibleData[++countRowspan + _rowIndex]
|
let countRowspan = 1
|
||||||
}
|
while (nextRow && nextRow['created_at'] === cellValue1 && nextRow['username'] === cellValue2) {
|
||||||
if (countRowspan > 1) {
|
nextRow = visibleData[++countRowspan + _rowIndex]
|
||||||
return { rowspan: countRowspan, colspan: 1 }
|
}
|
||||||
}
|
if (countRowspan > 1) {
|
||||||
}
|
return { rowspan: countRowspan, colspan: 1 }
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
updateCIByself(params, editAttrName) {
|
}
|
||||||
const _ci = { ..._.cloneDeep(this.ci), ...params }
|
},
|
||||||
this.ci = _ci
|
updateCIByself(params, editAttrName) {
|
||||||
const _find = this.treeViewsLevels.find((level) => level.name === editAttrName)
|
const _ci = { ..._.cloneDeep(this.ci), ...params }
|
||||||
// 修改的字段为树形视图订阅的字段 则全部reload
|
this.ci = _ci
|
||||||
setTimeout(() => {
|
const _find = this.treeViewsLevels.find((level) => level.name === editAttrName)
|
||||||
if (_find) {
|
// 修改的字段为树形视图订阅的字段 则全部reload
|
||||||
this.reload()
|
setTimeout(() => {
|
||||||
} else {
|
if (_find) {
|
||||||
this.handleSearch()
|
this.reload()
|
||||||
}
|
} else {
|
||||||
}, 500)
|
this.handleSearch()
|
||||||
},
|
}
|
||||||
},
|
}, 500)
|
||||||
}
|
},
|
||||||
</script>
|
},
|
||||||
|
}
|
||||||
<style lang="less" scoped></style>
|
</script>
|
||||||
<style lang="less">
|
|
||||||
.ci-detail {
|
<style lang="less" scoped></style>
|
||||||
.ant-tabs-bar {
|
<style lang="less">
|
||||||
margin: 0;
|
.ci-detail {
|
||||||
}
|
.ant-tabs-bar {
|
||||||
.ci-detail-attr {
|
margin: 0;
|
||||||
.el-descriptions-item__content {
|
}
|
||||||
cursor: default;
|
.ci-detail-attr {
|
||||||
&:hover a {
|
.el-descriptions-item__content {
|
||||||
opacity: 1 !important;
|
cursor: default;
|
||||||
}
|
&:hover a {
|
||||||
}
|
opacity: 1 !important;
|
||||||
.el-descriptions:first-child > .el-descriptions__header {
|
}
|
||||||
margin-top: 0;
|
}
|
||||||
}
|
.el-descriptions:first-child > .el-descriptions__header {
|
||||||
.el-descriptions__header {
|
margin-top: 0;
|
||||||
margin-bottom: 5px;
|
}
|
||||||
margin-top: 20px;
|
.el-descriptions__header {
|
||||||
}
|
margin-bottom: 5px;
|
||||||
.ant-form-item {
|
margin-top: 20px;
|
||||||
margin-bottom: 0;
|
}
|
||||||
}
|
.ant-form-item {
|
||||||
.ant-form-item-control {
|
margin-bottom: 0;
|
||||||
line-height: 19px;
|
}
|
||||||
}
|
.ant-form-item-control {
|
||||||
}
|
line-height: 19px;
|
||||||
}
|
}
|
||||||
</style>
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
|
@ -1,386 +1,388 @@
|
||||||
<template>
|
<template>
|
||||||
<CustomDrawer
|
<CustomDrawer
|
||||||
:title="title + CIType.alias"
|
:title="title + CIType.alias"
|
||||||
width="800"
|
width="800"
|
||||||
@close="handleClose"
|
@close="handleClose"
|
||||||
:maskClosable="false"
|
:maskClosable="false"
|
||||||
:visible="visible"
|
:visible="visible"
|
||||||
wrapClassName="create-instance-form"
|
wrapClassName="create-instance-form"
|
||||||
:bodyStyle="{ paddingTop: 0 }"
|
:bodyStyle="{ paddingTop: 0 }"
|
||||||
:headerStyle="{ borderBottom: 'none' }"
|
:headerStyle="{ borderBottom: 'none' }"
|
||||||
>
|
>
|
||||||
<div class="custom-drawer-bottom-action">
|
<div class="custom-drawer-bottom-action">
|
||||||
<a-button @click="handleClose">取消</a-button>
|
<a-button @click="handleClose">{{ $t('cancel') }}</a-button>
|
||||||
<a-button type="primary" @click="createInstance">提交</a-button>
|
<a-button type="primary" @click="createInstance">{{ $t('submit') }}</a-button>
|
||||||
</div>
|
</div>
|
||||||
<template v-if="action === 'create'">
|
<template v-if="action === 'create'">
|
||||||
<template v-for="group in attributesByGroup">
|
<template v-for="group in attributesByGroup">
|
||||||
<CreateInstanceFormByGroup
|
<CreateInstanceFormByGroup
|
||||||
:ref="`createInstanceFormByGroup_${group.id}`"
|
:ref="`createInstanceFormByGroup_${group.id}`"
|
||||||
:key="group.id || group.name"
|
:key="group.id || group.name"
|
||||||
:group="group"
|
:group="group"
|
||||||
@handleFocusInput="handleFocusInput"
|
@handleFocusInput="handleFocusInput"
|
||||||
:attributeList="attributeList"
|
:attributeList="attributeList"
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
<template v-if="parentsType && parentsType.length">
|
<template v-if="parentsType && parentsType.length">
|
||||||
<a-divider style="font-size:14px;margin:14px 0;font-weight:700;">模型关系</a-divider>
|
<a-divider style="font-size:14px;margin:14px 0;font-weight:700;">{{ $t('cmdb.menu.citypeRelation') }}</a-divider>
|
||||||
<a-form>
|
<a-form>
|
||||||
<a-row :gutter="24" align="top" type="flex">
|
<a-row :gutter="24" align="top" type="flex">
|
||||||
<a-col :span="12" v-for="item in parentsType" :key="item.id">
|
<a-col :span="12" v-for="item in parentsType" :key="item.id">
|
||||||
<a-form-item :label="item.alias || item.name" :colon="false">
|
<a-form-item :label="item.alias || item.name" :colon="false">
|
||||||
<a-input-group compact style="width: 100%">
|
<a-input-group compact style="width: 100%">
|
||||||
<a-select v-model="parentsForm[item.name].attr">
|
<a-select v-model="parentsForm[item.name].attr">
|
||||||
<a-select-option
|
<a-select-option
|
||||||
:title="attr.alias || attr.name"
|
:title="attr.alias || attr.name"
|
||||||
v-for="attr in item.attributes"
|
v-for="attr in item.attributes"
|
||||||
:key="attr.name"
|
:key="attr.name"
|
||||||
:value="attr.name"
|
:value="attr.name"
|
||||||
>
|
>
|
||||||
{{ attr.alias || attr.name }}
|
{{ attr.alias || attr.name }}
|
||||||
</a-select-option>
|
</a-select-option>
|
||||||
</a-select>
|
</a-select>
|
||||||
<a-input placeholder="多个值使用,分割" v-model="parentsForm[item.name].value" style="width: 50%" />
|
<a-input :placeholder="$t('cmdb.ci.tips1')" v-model="parentsForm[item.name].value" style="width: 50%" />
|
||||||
</a-input-group>
|
</a-input-group>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
</a-col>
|
</a-col>
|
||||||
</a-row>
|
</a-row>
|
||||||
</a-form>
|
</a-form>
|
||||||
</template>
|
</template>
|
||||||
</template>
|
</template>
|
||||||
<template v-if="action === 'update'">
|
<template v-if="action === 'update'">
|
||||||
<a-form :form="form">
|
<a-form :form="form">
|
||||||
<p>可根据需要修改字段,当值为<strong>空</strong>时,则该字段<strong>置空</strong></p>
|
<p>{{ $t('cmdb.ci.tips2') }}</p>
|
||||||
<a-row :gutter="24" v-for="list in batchUpdateLists" :key="list.name">
|
<a-row :gutter="24" v-for="list in batchUpdateLists" :key="list.name">
|
||||||
<a-col :span="11">
|
<a-col :span="11">
|
||||||
<a-form-item>
|
<a-form-item>
|
||||||
<el-select showSearch size="small" filterable v-model="list.name" placeholder="请选择需要修改的字段">
|
<el-select showSearch size="small" filterable v-model="list.name" :placeholder="$t('cmdb.ci.tips3')">
|
||||||
<el-option
|
<el-option
|
||||||
v-for="attr in attributeList"
|
v-for="attr in attributeList"
|
||||||
:key="attr.name"
|
:key="attr.name"
|
||||||
:value="attr.name"
|
:value="attr.name"
|
||||||
:disabled="batchUpdateLists.findIndex((item) => item.name === attr.name) > -1"
|
:disabled="batchUpdateLists.findIndex((item) => item.name === attr.name) > -1"
|
||||||
:label="attr.alias || attr.name"
|
:label="attr.alias || attr.name"
|
||||||
>
|
>
|
||||||
</el-option>
|
</el-option>
|
||||||
</el-select>
|
</el-select>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
</a-col>
|
</a-col>
|
||||||
<a-col :span="11">
|
<a-col :span="11">
|
||||||
<a-form-item>
|
<a-form-item>
|
||||||
<a-select
|
<a-select
|
||||||
:style="{ width: '100%' }"
|
:style="{ width: '100%' }"
|
||||||
v-decorator="[list.name, { rules: [{ required: false }] }]"
|
v-decorator="[list.name, { rules: [{ required: false }] }]"
|
||||||
placeholder="请选择"
|
:placeholder="$t('placeholder2')"
|
||||||
v-if="getFieldType(list.name).split('%%')[0] === 'select'"
|
v-if="getFieldType(list.name).split('%%')[0] === 'select'"
|
||||||
:mode="getFieldType(list.name).split('%%')[1] === 'multiple' ? 'multiple' : 'default'"
|
:mode="getFieldType(list.name).split('%%')[1] === 'multiple' ? 'multiple' : 'default'"
|
||||||
showSearch
|
showSearch
|
||||||
allowClear
|
allowClear
|
||||||
>
|
>
|
||||||
<a-select-option
|
<a-select-option
|
||||||
:value="choice[0]"
|
:value="choice[0]"
|
||||||
:key="'New_' + choice + choice_idx"
|
:key="'New_' + choice + choice_idx"
|
||||||
v-for="(choice, choice_idx) in getSelectFieldOptions(list.name)"
|
v-for="(choice, choice_idx) in getSelectFieldOptions(list.name)"
|
||||||
>
|
>
|
||||||
<span :style="choice[1] ? choice[1].style || {} : {}">
|
<span :style="choice[1] ? choice[1].style || {} : {}">
|
||||||
<ops-icon
|
<ops-icon
|
||||||
:style="{ color: choice[1].icon.color }"
|
:style="{ color: choice[1].icon.color }"
|
||||||
v-if="choice[1] && choice[1].icon && choice[1].icon.name"
|
v-if="choice[1] && choice[1].icon && choice[1].icon.name"
|
||||||
:type="choice[1].icon.name"
|
:type="choice[1].icon.name"
|
||||||
/>
|
/>
|
||||||
{{ choice[0] }}
|
{{ choice[0] }}
|
||||||
</span>
|
</span>
|
||||||
</a-select-option>
|
</a-select-option>
|
||||||
</a-select>
|
</a-select>
|
||||||
<a-input-number
|
<a-input-number
|
||||||
v-decorator="[list.name, { rules: [{ required: false }] }]"
|
v-decorator="[list.name, { rules: [{ required: false }] }]"
|
||||||
style="width: 100%"
|
style="width: 100%"
|
||||||
v-if="getFieldType(list.name) === 'input_number'"
|
v-if="getFieldType(list.name) === 'input_number'"
|
||||||
/>
|
/>
|
||||||
<a-date-picker
|
<a-date-picker
|
||||||
v-decorator="[list.name, { rules: [{ required: false }] }]"
|
v-decorator="[list.name, { rules: [{ required: false }] }]"
|
||||||
style="width: 100%"
|
style="width: 100%"
|
||||||
:format="getFieldType(list.name) == 'date' ? 'YYYY-MM-DD' : 'YYYY-MM-DD HH:mm:ss'"
|
:format="getFieldType(list.name) == 'date' ? 'YYYY-MM-DD' : 'YYYY-MM-DD HH:mm:ss'"
|
||||||
v-if="getFieldType(list.name) === 'date' || getFieldType(list.name) === 'datetime'"
|
v-if="getFieldType(list.name) === 'date' || getFieldType(list.name) === 'datetime'"
|
||||||
:showTime="getFieldType(list.name) === 'date' ? false : { format: 'HH:mm:ss' }"
|
:showTime="getFieldType(list.name) === 'date' ? false : { format: 'HH:mm:ss' }"
|
||||||
/>
|
/>
|
||||||
<a-input
|
<a-input
|
||||||
v-if="getFieldType(list.name) === 'input'"
|
v-if="getFieldType(list.name) === 'input'"
|
||||||
@focus="(e) => handleFocusInput(e, list)"
|
@focus="(e) => handleFocusInput(e, list)"
|
||||||
v-decorator="[list.name, { rules: [{ required: false }] }]"
|
v-decorator="[list.name, { rules: [{ required: false }] }]"
|
||||||
/>
|
/>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
</a-col>
|
</a-col>
|
||||||
<a-col :span="2">
|
<a-col :span="2">
|
||||||
<a-form-item>
|
<a-form-item>
|
||||||
<a :style="{ color: 'red', marginTop: '2px' }" @click="handleDelete(list.name)">
|
<a :style="{ color: 'red', marginTop: '2px' }" @click="handleDelete(list.name)">
|
||||||
<a-icon type="delete" />
|
<a-icon type="delete" />
|
||||||
</a>
|
</a>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
</a-col>
|
</a-col>
|
||||||
</a-row>
|
</a-row>
|
||||||
<a-button type="primary" ghost icon="plus" @click="handleAdd">新增修改字段</a-button>
|
<a-button type="primary" ghost icon="plus" @click="handleAdd">{{ $t('cmdb.ci.newUpdateField') }}</a-button>
|
||||||
</a-form>
|
</a-form>
|
||||||
</template>
|
</template>
|
||||||
<JsonEditor ref="jsonEditor" @jsonEditorOk="jsonEditorOk" />
|
<JsonEditor ref="jsonEditor" @jsonEditorOk="jsonEditorOk" />
|
||||||
</CustomDrawer>
|
</CustomDrawer>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import _ from 'lodash'
|
import _ from 'lodash'
|
||||||
import moment from 'moment'
|
import moment from 'moment'
|
||||||
import { Select, Option } from 'element-ui'
|
import { Select, Option } from 'element-ui'
|
||||||
import { getCIType, getCITypeGroupById } from '@/modules/cmdb/api/CIType'
|
import { getCIType, getCITypeGroupById } from '@/modules/cmdb/api/CIType'
|
||||||
import { addCI } from '@/modules/cmdb/api/ci'
|
import { addCI } from '@/modules/cmdb/api/ci'
|
||||||
import JsonEditor from '../../../components/JsonEditor/jsonEditor.vue'
|
import JsonEditor from '../../../components/JsonEditor/jsonEditor.vue'
|
||||||
import { valueTypeMap } from '../../../utils/const'
|
import { valueTypeMap } from '../../../utils/const'
|
||||||
import CreateInstanceFormByGroup from './createInstanceFormByGroup.vue'
|
import CreateInstanceFormByGroup from './createInstanceFormByGroup.vue'
|
||||||
import { getCITypeParent, getCanEditByParentIdChildId } from '@/modules/cmdb/api/CITypeRelation'
|
import { getCITypeParent, getCanEditByParentIdChildId } from '@/modules/cmdb/api/CITypeRelation'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'CreateInstanceForm',
|
name: 'CreateInstanceForm',
|
||||||
components: {
|
components: {
|
||||||
ElSelect: Select,
|
ElSelect: Select,
|
||||||
ElOption: Option,
|
ElOption: Option,
|
||||||
JsonEditor,
|
JsonEditor,
|
||||||
CreateInstanceFormByGroup,
|
CreateInstanceFormByGroup,
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
typeIdFromRelation: {
|
typeIdFromRelation: {
|
||||||
type: Number,
|
type: Number,
|
||||||
default: 0,
|
default: 0,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
valueTypeMap,
|
action: '',
|
||||||
action: '',
|
form: this.$form.createForm(this),
|
||||||
form: this.$form.createForm(this),
|
visible: false,
|
||||||
visible: false,
|
attributeList: [],
|
||||||
attributeList: [],
|
|
||||||
|
CIType: {},
|
||||||
CIType: {},
|
|
||||||
|
batchUpdateLists: [],
|
||||||
batchUpdateLists: [],
|
editAttr: null,
|
||||||
editAttr: null,
|
attributesByGroup: [],
|
||||||
attributesByGroup: [],
|
parentsType: [],
|
||||||
parentsType: [],
|
parentsForm: {},
|
||||||
parentsForm: {},
|
canEdit: {},
|
||||||
canEdit: {},
|
}
|
||||||
}
|
},
|
||||||
},
|
computed: {
|
||||||
computed: {
|
title() {
|
||||||
title() {
|
return this.action === 'create' ? this.$t('create') + ' ' : this.$t('cmdb.ci.batchUpdate') + ' '
|
||||||
return this.action === 'create' ? '创建 ' : '批量修改 '
|
},
|
||||||
},
|
typeId() {
|
||||||
typeId() {
|
if (this.typeIdFromRelation) {
|
||||||
if (this.typeIdFromRelation) {
|
return this.typeIdFromRelation
|
||||||
return this.typeIdFromRelation
|
}
|
||||||
}
|
return this.$router.currentRoute.meta.typeId
|
||||||
return this.$router.currentRoute.meta.typeId
|
},
|
||||||
},
|
valueTypeMap() {
|
||||||
},
|
return valueTypeMap()
|
||||||
provide() {
|
},
|
||||||
return {
|
},
|
||||||
getFieldType: this.getFieldType,
|
provide() {
|
||||||
}
|
return {
|
||||||
},
|
getFieldType: this.getFieldType,
|
||||||
inject: ['attrList'],
|
}
|
||||||
methods: {
|
},
|
||||||
moment,
|
inject: ['attrList'],
|
||||||
async getCIType() {
|
methods: {
|
||||||
await getCIType(this.typeId).then((res) => {
|
moment,
|
||||||
this.CIType = res.ci_types[0]
|
async getCIType() {
|
||||||
})
|
await getCIType(this.typeId).then((res) => {
|
||||||
},
|
this.CIType = res.ci_types[0]
|
||||||
async getAttributeList() {
|
})
|
||||||
const _attrList = this.attrList()
|
},
|
||||||
this.attributeList = _attrList.sort((x, y) => y.is_required - x.is_required)
|
async getAttributeList() {
|
||||||
await getCITypeGroupById(this.typeId).then((res1) => {
|
const _attrList = this.attrList()
|
||||||
const _attributesByGroup = res1.map((g) => {
|
this.attributeList = _attrList.sort((x, y) => y.is_required - x.is_required)
|
||||||
g.attributes = g.attributes.filter((attr) => !attr.is_computed)
|
await getCITypeGroupById(this.typeId).then((res1) => {
|
||||||
return g
|
const _attributesByGroup = res1.map((g) => {
|
||||||
})
|
g.attributes = g.attributes.filter((attr) => !attr.is_computed)
|
||||||
const attrHasGroupIds = []
|
return g
|
||||||
res1.forEach((g) => {
|
})
|
||||||
const id = g.attributes.map((attr) => attr.id)
|
const attrHasGroupIds = []
|
||||||
attrHasGroupIds.push(...id)
|
res1.forEach((g) => {
|
||||||
})
|
const id = g.attributes.map((attr) => attr.id)
|
||||||
const otherGroupAttr = this.attributeList.filter(
|
attrHasGroupIds.push(...id)
|
||||||
(attr) => !attrHasGroupIds.includes(attr.id) && !attr.is_computed
|
})
|
||||||
)
|
const otherGroupAttr = this.attributeList.filter(
|
||||||
if (otherGroupAttr.length) {
|
(attr) => !attrHasGroupIds.includes(attr.id) && !attr.is_computed
|
||||||
_attributesByGroup.push({ id: -1, name: '其他', attributes: otherGroupAttr })
|
)
|
||||||
}
|
if (otherGroupAttr.length) {
|
||||||
this.attributesByGroup = _attributesByGroup
|
_attributesByGroup.push({ id: -1, name: this.$t('other'), attributes: otherGroupAttr })
|
||||||
})
|
}
|
||||||
},
|
this.attributesByGroup = _attributesByGroup
|
||||||
createInstance() {
|
})
|
||||||
const _this = this
|
},
|
||||||
if (_this.action === 'update') {
|
createInstance() {
|
||||||
this.form.validateFields((err, values) => {
|
const _this = this
|
||||||
if (err) {
|
if (_this.action === 'update') {
|
||||||
return
|
this.form.validateFields((err, values) => {
|
||||||
}
|
if (err) {
|
||||||
Object.keys(values).forEach((k) => {
|
return
|
||||||
const _tempFind = this.attributeList.find((item) => item.name === k)
|
}
|
||||||
if (
|
Object.keys(values).forEach((k) => {
|
||||||
_tempFind.value_type === '3' &&
|
const _tempFind = this.attributeList.find((item) => item.name === k)
|
||||||
values[k] &&
|
if (
|
||||||
Object.prototype.toString.call(values[k]) === '[object Object]'
|
_tempFind.value_type === '3' &&
|
||||||
) {
|
values[k] &&
|
||||||
values[k] = values[k].format('YYYY-MM-DD HH:mm:ss')
|
Object.prototype.toString.call(values[k]) === '[object Object]'
|
||||||
}
|
) {
|
||||||
if (
|
values[k] = values[k].format('YYYY-MM-DD HH:mm:ss')
|
||||||
_tempFind.value_type === '4' &&
|
}
|
||||||
values[k] &&
|
if (
|
||||||
Object.prototype.toString.call(values[k]) === '[object Object]'
|
_tempFind.value_type === '4' &&
|
||||||
) {
|
values[k] &&
|
||||||
values[k] = values[k].format('YYYY-MM-DD')
|
Object.prototype.toString.call(values[k]) === '[object Object]'
|
||||||
}
|
) {
|
||||||
if (_tempFind.value_type === '6') {
|
values[k] = values[k].format('YYYY-MM-DD')
|
||||||
values[k] = values[k] ? JSON.parse(values[k]) : undefined
|
}
|
||||||
}
|
if (_tempFind.value_type === '6') {
|
||||||
})
|
values[k] = values[k] ? JSON.parse(values[k]) : undefined
|
||||||
|
}
|
||||||
_this.$emit('submit', values)
|
})
|
||||||
})
|
|
||||||
} else {
|
_this.$emit('submit', values)
|
||||||
let values = {}
|
})
|
||||||
for (let i = 0; i < this.attributesByGroup.length; i++) {
|
} else {
|
||||||
const data = this.$refs[`createInstanceFormByGroup_${this.attributesByGroup[i].id}`][0].getData()
|
let values = {}
|
||||||
if (data === 'error') {
|
for (let i = 0; i < this.attributesByGroup.length; i++) {
|
||||||
return
|
const data = this.$refs[`createInstanceFormByGroup_${this.attributesByGroup[i].id}`][0].getData()
|
||||||
}
|
if (data === 'error') {
|
||||||
values = { ...values, ...data }
|
return
|
||||||
}
|
}
|
||||||
|
values = { ...values, ...data }
|
||||||
Object.keys(values).forEach((k) => {
|
}
|
||||||
const _tempFind = this.attributeList.find((item) => item.name === k)
|
|
||||||
if (
|
Object.keys(values).forEach((k) => {
|
||||||
_tempFind.value_type === '3' &&
|
const _tempFind = this.attributeList.find((item) => item.name === k)
|
||||||
values[k] &&
|
if (
|
||||||
Object.prototype.toString.call(values[k]) === '[object Object]'
|
_tempFind.value_type === '3' &&
|
||||||
) {
|
values[k] &&
|
||||||
values[k] = values[k].format('YYYY-MM-DD HH:mm:ss')
|
Object.prototype.toString.call(values[k]) === '[object Object]'
|
||||||
}
|
) {
|
||||||
if (
|
values[k] = values[k].format('YYYY-MM-DD HH:mm:ss')
|
||||||
_tempFind.value_type === '4' &&
|
}
|
||||||
values[k] &&
|
if (
|
||||||
Object.prototype.toString.call(values[k]) === '[object Object]'
|
_tempFind.value_type === '4' &&
|
||||||
) {
|
values[k] &&
|
||||||
values[k] = values[k].format('YYYY-MM-DD')
|
Object.prototype.toString.call(values[k]) === '[object Object]'
|
||||||
}
|
) {
|
||||||
if (_tempFind.value_type === '6') {
|
values[k] = values[k].format('YYYY-MM-DD')
|
||||||
values[k] = values[k] ? JSON.parse(values[k]) : undefined
|
}
|
||||||
}
|
if (_tempFind.value_type === '6') {
|
||||||
})
|
values[k] = values[k] ? JSON.parse(values[k]) : undefined
|
||||||
values.ci_type = _this.typeId
|
}
|
||||||
console.log(this.parentsForm)
|
})
|
||||||
Object.keys(this.parentsForm).forEach((type) => {
|
values.ci_type = _this.typeId
|
||||||
if (this.parentsForm[type].value) {
|
console.log(this.parentsForm)
|
||||||
values[`$${type}.${this.parentsForm[type].attr}`] = this.parentsForm[type].value
|
Object.keys(this.parentsForm).forEach((type) => {
|
||||||
}
|
if (this.parentsForm[type].value) {
|
||||||
})
|
values[`$${type}.${this.parentsForm[type].attr}`] = this.parentsForm[type].value
|
||||||
addCI(values).then((res) => {
|
}
|
||||||
_this.$message.success('新增成功!')
|
})
|
||||||
_this.visible = false
|
addCI(values).then((res) => {
|
||||||
_this.$emit('reload', { ci_id: res.ci_id })
|
_this.$message.success(this.$t('addSuccess'))
|
||||||
})
|
_this.visible = false
|
||||||
}
|
_this.$emit('reload', { ci_id: res.ci_id })
|
||||||
},
|
})
|
||||||
handleClose() {
|
}
|
||||||
this.visible = false
|
},
|
||||||
},
|
handleClose() {
|
||||||
handleOpen(visible, action) {
|
this.visible = false
|
||||||
this.visible = visible
|
},
|
||||||
this.action = action
|
handleOpen(visible, action) {
|
||||||
this.$nextTick(() => {
|
this.visible = visible
|
||||||
this.form.resetFields()
|
this.action = action
|
||||||
Promise.all([this.getCIType(), this.getAttributeList()]).then(() => {
|
this.$nextTick(() => {
|
||||||
this.batchUpdateLists = [{ name: this.attributeList[0].name }]
|
this.form.resetFields()
|
||||||
})
|
Promise.all([this.getCIType(), this.getAttributeList()]).then(() => {
|
||||||
if (action === 'create') {
|
this.batchUpdateLists = [{ name: this.attributeList[0].name }]
|
||||||
getCITypeParent(this.typeId).then(async (res) => {
|
})
|
||||||
for (let i = 0; i < res.parents.length; i++) {
|
if (action === 'create') {
|
||||||
await getCanEditByParentIdChildId(res.parents[i].id, this.typeId).then((p_res) => {
|
getCITypeParent(this.typeId).then(async (res) => {
|
||||||
this.canEdit = {
|
for (let i = 0; i < res.parents.length; i++) {
|
||||||
..._.cloneDeep(this.canEdit),
|
await getCanEditByParentIdChildId(res.parents[i].id, this.typeId).then((p_res) => {
|
||||||
[res.parents[i].id]: p_res.result,
|
this.canEdit = {
|
||||||
}
|
..._.cloneDeep(this.canEdit),
|
||||||
})
|
[res.parents[i].id]: p_res.result,
|
||||||
}
|
}
|
||||||
this.parentsType = res.parents.filter((parent) => this.canEdit[parent.id])
|
})
|
||||||
const _parentsForm = {}
|
}
|
||||||
res.parents.forEach((item) => {
|
this.parentsType = res.parents.filter((parent) => this.canEdit[parent.id])
|
||||||
const _find = item.attributes.find((attr) => attr.id === item.unique_id)
|
const _parentsForm = {}
|
||||||
_parentsForm[item.name] = { attr: _find.name, value: '' }
|
res.parents.forEach((item) => {
|
||||||
})
|
const _find = item.attributes.find((attr) => attr.id === item.unique_id)
|
||||||
this.parentsForm = _parentsForm
|
_parentsForm[item.name] = { attr: _find.name, value: '' }
|
||||||
})
|
})
|
||||||
}
|
this.parentsForm = _parentsForm
|
||||||
})
|
})
|
||||||
},
|
}
|
||||||
getFieldType(name) {
|
})
|
||||||
const _find = this.attributeList.find((item) => item.name === name)
|
},
|
||||||
if (_find) {
|
getFieldType(name) {
|
||||||
if (_find.is_choice) {
|
const _find = this.attributeList.find((item) => item.name === name)
|
||||||
if (_find.is_list) {
|
if (_find) {
|
||||||
return 'select%%multiple'
|
if (_find.is_choice) {
|
||||||
}
|
if (_find.is_list) {
|
||||||
return 'select'
|
return 'select%%multiple'
|
||||||
} else if (_find.value_type === '0' || _find.value_type === '1') {
|
}
|
||||||
return 'input_number'
|
return 'select'
|
||||||
} else if (_find.value_type === '4' || _find.value_type === '3') {
|
} else if (_find.value_type === '0' || _find.value_type === '1') {
|
||||||
return valueTypeMap[_find.value_type]
|
return 'input_number'
|
||||||
} else {
|
} else if (_find.value_type === '4' || _find.value_type === '3') {
|
||||||
return 'input'
|
return this.valueTypeMap[_find.value_type]
|
||||||
}
|
} else {
|
||||||
}
|
return 'input'
|
||||||
return 'input'
|
}
|
||||||
},
|
}
|
||||||
getSelectFieldOptions(name) {
|
return 'input'
|
||||||
const _find = this.attributeList.find((item) => item.name === name)
|
},
|
||||||
if (_find) {
|
getSelectFieldOptions(name) {
|
||||||
return _find.choice_value
|
const _find = this.attributeList.find((item) => item.name === name)
|
||||||
}
|
if (_find) {
|
||||||
return []
|
return _find.choice_value
|
||||||
},
|
}
|
||||||
handleAdd() {
|
return []
|
||||||
this.batchUpdateLists.push({ name: undefined })
|
},
|
||||||
},
|
handleAdd() {
|
||||||
handleDelete(name) {
|
this.batchUpdateLists.push({ name: undefined })
|
||||||
const _idx = this.batchUpdateLists.findIndex((item) => item.name === name)
|
},
|
||||||
if (_idx > -1) {
|
handleDelete(name) {
|
||||||
this.batchUpdateLists.splice(_idx, 1)
|
const _idx = this.batchUpdateLists.findIndex((item) => item.name === name)
|
||||||
}
|
if (_idx > -1) {
|
||||||
},
|
this.batchUpdateLists.splice(_idx, 1)
|
||||||
handleFocusInput(e, attr) {
|
}
|
||||||
console.log(attr)
|
},
|
||||||
const _tempFind = this.attributeList.find((item) => item.name === attr.name)
|
handleFocusInput(e, attr) {
|
||||||
if (_tempFind.value_type === '6') {
|
console.log(attr)
|
||||||
this.editAttr = attr
|
const _tempFind = this.attributeList.find((item) => item.name === attr.name)
|
||||||
e.srcElement.blur()
|
if (_tempFind.value_type === '6') {
|
||||||
const jsonData = this.form.getFieldValue(attr.name)
|
this.editAttr = attr
|
||||||
this.$refs.jsonEditor.open(null, null, jsonData ? JSON.parse(jsonData) : {})
|
e.srcElement.blur()
|
||||||
} else {
|
const jsonData = this.form.getFieldValue(attr.name)
|
||||||
this.editAttr = null
|
this.$refs.jsonEditor.open(null, null, jsonData ? JSON.parse(jsonData) : {})
|
||||||
}
|
} else {
|
||||||
},
|
this.editAttr = null
|
||||||
jsonEditorOk(jsonData) {
|
}
|
||||||
this.form.setFieldsValue({ [this.editAttr.name]: JSON.stringify(jsonData) })
|
},
|
||||||
},
|
jsonEditorOk(jsonData) {
|
||||||
},
|
this.form.setFieldsValue({ [this.editAttr.name]: JSON.stringify(jsonData) })
|
||||||
}
|
},
|
||||||
</script>
|
},
|
||||||
<style lang="less">
|
}
|
||||||
.create-instance-form {
|
</script>
|
||||||
.ant-form-item {
|
<style lang="less">
|
||||||
margin-bottom: 5px;
|
.create-instance-form {
|
||||||
}
|
.ant-form-item {
|
||||||
.ant-drawer-body {
|
margin-bottom: 5px;
|
||||||
overflow-y: auto;
|
}
|
||||||
max-height: calc(100vh - 110px);
|
.ant-drawer-body {
|
||||||
}
|
overflow-y: auto;
|
||||||
}
|
max-height: calc(100vh - 110px);
|
||||||
</style>
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
|
@ -1,225 +1,228 @@
|
||||||
<template>
|
<template>
|
||||||
<CustomDrawer
|
<CustomDrawer
|
||||||
:visible="visible"
|
:visible="visible"
|
||||||
:hasFooter="false"
|
:hasFooter="false"
|
||||||
@close="
|
@close="
|
||||||
() => {
|
() => {
|
||||||
visible = false
|
visible = false
|
||||||
}
|
}
|
||||||
"
|
"
|
||||||
title="属性说明"
|
:title="$t('cmdb.ci.attributeDesc')"
|
||||||
width="72%"
|
width="72%"
|
||||||
:bodyStyle="{ height: '100vh' }"
|
:bodyStyle="{ height: '100vh' }"
|
||||||
>
|
>
|
||||||
<vxe-toolbar>
|
<vxe-toolbar>
|
||||||
<template #buttons>
|
<template #buttons>
|
||||||
<a-input
|
<a-input
|
||||||
v-model="searchKey"
|
v-model="searchKey"
|
||||||
:style="{ display: 'inline-block', width: '244px' }"
|
:style="{ display: 'inline-block', width: '244px' }"
|
||||||
class="ops-input ops-input-radius"
|
class="ops-input ops-input-radius"
|
||||||
type="search"
|
type="search"
|
||||||
placeholder="搜索 名称 | 别名"
|
:placeholder="$t('cmdb.ci.tips5')"
|
||||||
@keyup="searchAttributes"
|
@keyup="searchAttributes"
|
||||||
>
|
>
|
||||||
<a-icon type="search" slot="suffix" />
|
<a-icon type="search" slot="suffix" />
|
||||||
</a-input>
|
</a-input>
|
||||||
</template>
|
</template>
|
||||||
</vxe-toolbar>
|
</vxe-toolbar>
|
||||||
|
|
||||||
<a-spin :spinning="loading">
|
<a-spin :spinning="loading">
|
||||||
<vxe-table
|
<vxe-table
|
||||||
resizable
|
resizable
|
||||||
border
|
border
|
||||||
size="mini"
|
size="mini"
|
||||||
:height="windowHeight - 160"
|
:height="windowHeight - 160"
|
||||||
:data="list"
|
:data="list"
|
||||||
:scroll-x="{ enabled: true, gt: 0 }"
|
:scroll-x="{ enabled: true, gt: 0 }"
|
||||||
show-overflow
|
show-overflow
|
||||||
show-header-overflow
|
show-header-overflow
|
||||||
align="center"
|
align="center"
|
||||||
highlight-hover-row
|
highlight-hover-row
|
||||||
class="ops-stripe-table"
|
class="ops-stripe-table"
|
||||||
>
|
>
|
||||||
<vxe-column
|
<vxe-column
|
||||||
v-for="(column, index) in columns"
|
v-for="(column, index) in columns"
|
||||||
:field="column.field"
|
:field="column.field"
|
||||||
:title="column.title"
|
:title="column.title"
|
||||||
:min-width="column.width"
|
:min-width="column.width"
|
||||||
:align="column.align"
|
:align="column.align"
|
||||||
:key="column.field"
|
:key="column.field"
|
||||||
:fixed="index < 3 ? 'left' : ''"
|
:fixed="index < 3 ? 'left' : ''"
|
||||||
:sortable="index < 3 ? true : false"
|
:sortable="index < 3 ? true : false"
|
||||||
:title-help="column.help !== null ? { message: column.help } : null"
|
:title-help="column.help !== null ? { message: column.help } : null"
|
||||||
:filters="
|
:filters="
|
||||||
index < 2
|
index < 2
|
||||||
? null
|
? null
|
||||||
: index === 2
|
: index === 2
|
||||||
? valueTypeFilters
|
? valueTypeFilters
|
||||||
: [
|
: [
|
||||||
{ label: '是', value: true },
|
{ label: $t('yes'), value: true },
|
||||||
{ label: '否', value: false },
|
{ label: $t('no'), value: false },
|
||||||
]
|
]
|
||||||
"
|
"
|
||||||
type="html"
|
type="html"
|
||||||
>
|
>
|
||||||
<template #default="{ row }">
|
<template #default="{ row }">
|
||||||
<span v-if="column.field !== 'name' && column.field !== 'alias' && column.field !== 'value_type'">
|
<span v-if="column.field !== 'name' && column.field !== 'alias' && column.field !== 'value_type'">
|
||||||
<a-icon :style="{ color: '#1fb51f' }" type="check" v-if="row[column.field]" />
|
<a-icon :style="{ color: '#1fb51f' }" type="check" v-if="row[column.field]" />
|
||||||
</span>
|
</span>
|
||||||
<span v-else-if="column.field === 'value_type'" v-html="valueTypeMap[row.value_type]"> </span>
|
<span v-else-if="column.field === 'value_type'" v-html="valueTypeMap[row.value_type]"> </span>
|
||||||
<span v-else v-html="row[column.field]"> </span>
|
<span v-else v-html="row[column.field]"> </span>
|
||||||
</template>
|
</template>
|
||||||
</vxe-column>
|
</vxe-column>
|
||||||
</vxe-table>
|
</vxe-table>
|
||||||
</a-spin>
|
</a-spin>
|
||||||
</CustomDrawer>
|
</CustomDrawer>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import XEUtils from 'xe-utils'
|
import XEUtils from 'xe-utils'
|
||||||
import { getCITypeAttributesByName } from '@/modules/cmdb/api/CITypeAttr'
|
import { getCITypeAttributesByName } from '@/modules/cmdb/api/CITypeAttr'
|
||||||
import { valueTypeMap } from '@/modules/cmdb/utils/const'
|
import { valueTypeMap } from '@/modules/cmdb/utils/const'
|
||||||
export default {
|
export default {
|
||||||
name: 'MetadataDrawer',
|
name: 'MetadataDrawer',
|
||||||
data() {
|
data() {
|
||||||
const columns = [
|
return {
|
||||||
{
|
visible: false,
|
||||||
field: 'name',
|
list: [],
|
||||||
title: '名称',
|
tableData: [],
|
||||||
width: 150,
|
loading: false,
|
||||||
align: 'left',
|
valueTypeFilters: [],
|
||||||
help: null,
|
searchKey: '',
|
||||||
},
|
}
|
||||||
{
|
},
|
||||||
field: 'alias',
|
computed: {
|
||||||
title: '别名',
|
windowHeight() {
|
||||||
width: 150,
|
return this.$store.state.windowHeight
|
||||||
align: 'left',
|
},
|
||||||
help: null,
|
valueTypeMap() {
|
||||||
},
|
return valueTypeMap()
|
||||||
{
|
},
|
||||||
field: 'value_type',
|
columns() {
|
||||||
title: '类型',
|
return [
|
||||||
width: 100,
|
{
|
||||||
align: 'left',
|
field: 'name',
|
||||||
help: null,
|
title: this.$t('name'),
|
||||||
},
|
width: 150,
|
||||||
{
|
align: 'left',
|
||||||
field: 'is_index',
|
help: null,
|
||||||
title: '是否索引',
|
},
|
||||||
width: 110,
|
{
|
||||||
help: '加快检索, 可以全文搜索, 无需使用条件过滤\n\n json目前不支持建索引 \n\n文本字符长度超过190不能建索引',
|
field: 'alias',
|
||||||
},
|
title: this.$t('alias'),
|
||||||
{
|
width: 150,
|
||||||
field: 'default_show',
|
align: 'left',
|
||||||
title: '默认显示',
|
help: null,
|
||||||
width: 110,
|
},
|
||||||
help: '订阅CI,默认显示在table里的属性',
|
{
|
||||||
},
|
field: 'value_type',
|
||||||
{
|
title: this.$t('type'),
|
||||||
field: 'is_unique',
|
width: 100,
|
||||||
title: '是否唯一',
|
align: 'left',
|
||||||
width: 110,
|
help: null,
|
||||||
help: null,
|
},
|
||||||
},
|
{
|
||||||
{
|
field: 'is_index',
|
||||||
field: 'is_choice',
|
title: this.$t('cmdb.ciType.isIndex'),
|
||||||
title: '是否选择',
|
width: 110,
|
||||||
width: 110,
|
help: this.$t('cmdb.ci.tips6'),
|
||||||
help: '表现形式是下拉框, 值必须在预定义值里',
|
},
|
||||||
},
|
{
|
||||||
{
|
field: 'default_show',
|
||||||
field: 'is_list',
|
title: this.$t('cmdb.ciType.defaultShow'),
|
||||||
title: '是否列表',
|
width: 110,
|
||||||
width: 110,
|
help: this.$t('cmdb.ciType.defaultShowTips'),
|
||||||
help: '多值, 比如内网IP',
|
},
|
||||||
},
|
{
|
||||||
{
|
field: 'is_unique',
|
||||||
field: 'is_sortable',
|
title: this.$t('cmdb.ciType.isUnique'),
|
||||||
title: '可排序',
|
width: 110,
|
||||||
width: 100,
|
help: null,
|
||||||
help: '仅针对前端',
|
},
|
||||||
},
|
{
|
||||||
{
|
field: 'is_choice',
|
||||||
field: 'is_computed',
|
title: this.$t('cmdb.ciType.isChoice'),
|
||||||
title: '计算属性',
|
width: 110,
|
||||||
width: 110,
|
help: this.$t('cmdb.ci.tips7'),
|
||||||
help: '模型的其他属性通过表达式的方式计算出来\n\n一个代码片段计算返回的值',
|
},
|
||||||
},
|
{
|
||||||
]
|
field: 'is_list',
|
||||||
return {
|
title: this.$t('cmdb.ciType.list'),
|
||||||
columns,
|
width: 110,
|
||||||
visible: false,
|
help: this.$t('cmdb.ci.tips8'),
|
||||||
list: [],
|
},
|
||||||
tableData: [],
|
{
|
||||||
loading: false,
|
field: 'is_sortable',
|
||||||
valueTypeMap,
|
title: this.$t('cmdb.ciType.isSortable'),
|
||||||
valueTypeFilters: [],
|
width: 100,
|
||||||
searchKey: '',
|
help: this.$t('cmdb.ci.tips9'),
|
||||||
}
|
},
|
||||||
},
|
{
|
||||||
computed: {
|
field: 'is_computed',
|
||||||
windowHeight() {
|
title: this.$t('cmdb.ciType.computedAttribute'),
|
||||||
return this.$store.state.windowHeight
|
width: 110,
|
||||||
},
|
help: this.$t('cmdb.ci.tips10'),
|
||||||
},
|
},
|
||||||
created: function() {
|
]
|
||||||
this.valueTypeFilters = Object.keys(this.valueTypeMap).map((key) => {
|
},
|
||||||
return { label: this.valueTypeMap[key], value: key }
|
},
|
||||||
})
|
created: function() {
|
||||||
},
|
this.valueTypeFilters = Object.keys(this.valueTypeMap).map((key) => {
|
||||||
methods: {
|
return { label: this.valueTypeMap[key], value: key }
|
||||||
open(typeId) {
|
})
|
||||||
this.visible = true
|
},
|
||||||
this.typeId = typeId
|
methods: {
|
||||||
this.getAttrs()
|
open(typeId) {
|
||||||
},
|
this.visible = true
|
||||||
async getAttrs() {
|
this.typeId = typeId
|
||||||
this.loading = true
|
this.getAttrs()
|
||||||
const { attributes = [] } = await getCITypeAttributesByName(this.typeId)
|
},
|
||||||
this.tableData = attributes.map((attr) => {
|
async getAttrs() {
|
||||||
if (attr.is_password) {
|
this.loading = true
|
||||||
attr.value_type = '7'
|
const { attributes = [] } = await getCITypeAttributesByName(this.typeId)
|
||||||
}
|
this.tableData = attributes.map((attr) => {
|
||||||
if (attr.is_link) {
|
if (attr.is_password) {
|
||||||
attr.value_type = '8'
|
attr.value_type = '7'
|
||||||
}
|
}
|
||||||
return attr
|
if (attr.is_link) {
|
||||||
})
|
attr.value_type = '8'
|
||||||
this.loading = false
|
}
|
||||||
this.searchAttributes()
|
return attr
|
||||||
},
|
})
|
||||||
searchAttributes() {
|
this.loading = false
|
||||||
const filterName = XEUtils.toValueString(this.searchKey)
|
this.searchAttributes()
|
||||||
.trim()
|
},
|
||||||
.toLowerCase()
|
searchAttributes() {
|
||||||
if (filterName) {
|
const filterName = XEUtils.toValueString(this.searchKey)
|
||||||
const filterRE = new RegExp(filterName, 'gi')
|
.trim()
|
||||||
const searchProps = ['name', 'alias', 'value_type']
|
.toLowerCase()
|
||||||
const rest = this.tableData.filter((item) =>
|
if (filterName) {
|
||||||
searchProps.some(
|
const filterRE = new RegExp(filterName, 'gi')
|
||||||
(key) =>
|
const searchProps = ['name', 'alias', 'value_type']
|
||||||
XEUtils.toValueString(item[key])
|
const rest = this.tableData.filter((item) =>
|
||||||
.toLowerCase()
|
searchProps.some(
|
||||||
.indexOf(filterName) > -1
|
(key) =>
|
||||||
)
|
XEUtils.toValueString(item[key])
|
||||||
)
|
.toLowerCase()
|
||||||
this.list = rest.map((row) => {
|
.indexOf(filterName) > -1
|
||||||
const item = Object.assign({}, row)
|
)
|
||||||
searchProps.forEach((key) => {
|
)
|
||||||
item[key] = XEUtils.toValueString(item[key]).replace(
|
this.list = rest.map((row) => {
|
||||||
filterRE,
|
const item = Object.assign({}, row)
|
||||||
(match) => `<span style='background: yellow'>${match}</span>`
|
searchProps.forEach((key) => {
|
||||||
)
|
item[key] = XEUtils.toValueString(item[key]).replace(
|
||||||
})
|
filterRE,
|
||||||
return item
|
(match) => `<span style='background: yellow'>${match}</span>`
|
||||||
})
|
)
|
||||||
} else {
|
})
|
||||||
this.list = this.tableData
|
return item
|
||||||
}
|
})
|
||||||
},
|
} else {
|
||||||
},
|
this.list = this.tableData
|
||||||
}
|
}
|
||||||
</script>
|
},
|
||||||
|
},
|
||||||
<style></style>
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style></style>
|
||||||
|
|
|
@ -1,318 +1,318 @@
|
||||||
<template>
|
<template>
|
||||||
<span :id="`ci-detail-attr-${attr.name}`">
|
<span :id="`ci-detail-attr-${attr.name}`">
|
||||||
<span v-if="!isEdit || attr.value_type === '6'">
|
<span v-if="!isEdit || attr.value_type === '6'">
|
||||||
<PasswordField
|
<PasswordField
|
||||||
:style="{ display: 'inline-block' }"
|
:style="{ display: 'inline-block' }"
|
||||||
v-if="attr.is_password && ci[attr.name]"
|
v-if="attr.is_password && ci[attr.name]"
|
||||||
:ci_id="ci._id"
|
:ci_id="ci._id"
|
||||||
:attr_id="attr.id"
|
:attr_id="attr.id"
|
||||||
></PasswordField>
|
></PasswordField>
|
||||||
<template v-else-if="attr.value_type === '6'">{{ JSON.stringify(ci[attr.name] || {}) }}</template>
|
<template v-else-if="attr.value_type === '6'">{{ JSON.stringify(ci[attr.name] || {}) }}</template>
|
||||||
<template v-else-if="attr.is_choice">
|
<template v-else-if="attr.is_choice">
|
||||||
<template v-if="attr.is_list">
|
<template v-if="attr.is_list">
|
||||||
<span
|
<span
|
||||||
v-for="value in ci[attr.name]"
|
v-for="value in ci[attr.name]"
|
||||||
:key="value"
|
:key="value"
|
||||||
:style="{
|
:style="{
|
||||||
borderRadius: '4px',
|
borderRadius: '4px',
|
||||||
padding: '1px 5px',
|
padding: '1px 5px',
|
||||||
margin: '2px',
|
margin: '2px',
|
||||||
...getChoiceValueStyle(attr, value),
|
...getChoiceValueStyle(attr, value),
|
||||||
display: 'inline-flex',
|
display: 'inline-flex',
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
}"
|
}"
|
||||||
>
|
>
|
||||||
<img
|
<img
|
||||||
v-if="getChoiceValueIcon(attr, value).id && getChoiceValueIcon(attr, value).url"
|
v-if="getChoiceValueIcon(attr, value).id && getChoiceValueIcon(attr, value).url"
|
||||||
:src="`/api/common-setting/v1/file/${getChoiceValueIcon(attr, value).url}`"
|
:src="`/api/common-setting/v1/file/${getChoiceValueIcon(attr, value).url}`"
|
||||||
:style="{ maxHeight: '13px', maxWidth: '13px', marginRight: '5px' }"
|
:style="{ maxHeight: '13px', maxWidth: '13px', marginRight: '5px' }"
|
||||||
/>
|
/>
|
||||||
<ops-icon
|
<ops-icon
|
||||||
v-else
|
v-else
|
||||||
:style="{ color: getChoiceValueIcon(attr, value).color, marginRight: '5px' }"
|
:style="{ color: getChoiceValueIcon(attr, value).color, marginRight: '5px' }"
|
||||||
:type="getChoiceValueIcon(attr, value).name"
|
:type="getChoiceValueIcon(attr, value).name"
|
||||||
/>
|
/>
|
||||||
{{ value }}</span
|
{{ value }}</span
|
||||||
>
|
>
|
||||||
</template>
|
</template>
|
||||||
<span
|
<span
|
||||||
v-else
|
v-else
|
||||||
:style="{
|
:style="{
|
||||||
borderRadius: '4px',
|
borderRadius: '4px',
|
||||||
padding: '1px 5px',
|
padding: '1px 5px',
|
||||||
margin: '2px 0',
|
margin: '2px 0',
|
||||||
...getChoiceValueStyle(attr, ci[attr.name]),
|
...getChoiceValueStyle(attr, ci[attr.name]),
|
||||||
display: 'inline-flex',
|
display: 'inline-flex',
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
}"
|
}"
|
||||||
>
|
>
|
||||||
<img
|
<img
|
||||||
v-if="getChoiceValueIcon(attr, ci[attr.name]).id && getChoiceValueIcon(attr, ci[attr.name]).url"
|
v-if="getChoiceValueIcon(attr, ci[attr.name]).id && getChoiceValueIcon(attr, ci[attr.name]).url"
|
||||||
:src="`/api/common-setting/v1/file/${getChoiceValueIcon(attr, ci[attr.name]).url}`"
|
:src="`/api/common-setting/v1/file/${getChoiceValueIcon(attr, ci[attr.name]).url}`"
|
||||||
:style="{ maxHeight: '13px', maxWidth: '13px', marginRight: '5px' }"
|
:style="{ maxHeight: '13px', maxWidth: '13px', marginRight: '5px' }"
|
||||||
/>
|
/>
|
||||||
<ops-icon
|
<ops-icon
|
||||||
v-else
|
v-else
|
||||||
:style="{ color: getChoiceValueIcon(attr, ci[attr.name]).color, marginRight: '5px' }"
|
:style="{ color: getChoiceValueIcon(attr, ci[attr.name]).color, marginRight: '5px' }"
|
||||||
:type="getChoiceValueIcon(attr, ci[attr.name]).name"
|
:type="getChoiceValueIcon(attr, ci[attr.name]).name"
|
||||||
/>
|
/>
|
||||||
{{ ci[attr.name] }}
|
{{ ci[attr.name] }}
|
||||||
</span>
|
</span>
|
||||||
</template>
|
</template>
|
||||||
<template v-else-if="attr.is_list">
|
<template v-else-if="attr.is_list">
|
||||||
<span> {{ ci[attr.name].join(',') }}</span>
|
<span> {{ ci[attr.name].join(',') }}</span>
|
||||||
</template>
|
</template>
|
||||||
<template v-else>{{ getName(ci[attr.name]) }}</template>
|
<template v-else>{{ getName(ci[attr.name]) }}</template>
|
||||||
</span>
|
</span>
|
||||||
<template v-else>
|
<template v-else>
|
||||||
<a-form :form="form">
|
<a-form :form="form">
|
||||||
<a-form-item label="" :colon="false">
|
<a-form-item label="" :colon="false">
|
||||||
<a-select
|
<a-select
|
||||||
:style="{ width: '100%' }"
|
:style="{ width: '100%' }"
|
||||||
v-decorator="[
|
v-decorator="[
|
||||||
attr.name,
|
attr.name,
|
||||||
{
|
{
|
||||||
rules: [{ required: attr.is_required }],
|
rules: [{ required: attr.is_required }],
|
||||||
},
|
},
|
||||||
]"
|
]"
|
||||||
placeholder="请选择"
|
:placeholder="$t('placeholder2')"
|
||||||
v-if="attr.is_choice"
|
v-if="attr.is_choice"
|
||||||
:mode="attr.is_list ? 'multiple' : 'default'"
|
:mode="attr.is_list ? 'multiple' : 'default'"
|
||||||
showSearch
|
showSearch
|
||||||
allowClear
|
allowClear
|
||||||
size="small"
|
size="small"
|
||||||
:getPopupContainer="(trigger) => trigger.parentElement"
|
:getPopupContainer="(trigger) => trigger.parentElement"
|
||||||
>
|
>
|
||||||
<a-select-option
|
<a-select-option
|
||||||
:value="choice[0]"
|
:value="choice[0]"
|
||||||
:key="'New_' + attr.name + choice_idx"
|
:key="'New_' + attr.name + choice_idx"
|
||||||
v-for="(choice, choice_idx) in attr.choice_value"
|
v-for="(choice, choice_idx) in attr.choice_value"
|
||||||
>
|
>
|
||||||
<span :style="{ ...(choice[1] ? choice[1].style : {}), display: 'inline-flex', alignItems: 'center' }">
|
<span :style="{ ...(choice[1] ? choice[1].style : {}), display: 'inline-flex', alignItems: 'center' }">
|
||||||
<template v-if="choice[1] && choice[1].icon && choice[1].icon.name">
|
<template v-if="choice[1] && choice[1].icon && choice[1].icon.name">
|
||||||
<img
|
<img
|
||||||
v-if="choice[1].icon.id && choice[1].icon.url"
|
v-if="choice[1].icon.id && choice[1].icon.url"
|
||||||
:src="`/api/common-setting/v1/file/${choice[1].icon.url}`"
|
:src="`/api/common-setting/v1/file/${choice[1].icon.url}`"
|
||||||
:style="{ maxHeight: '13px', maxWidth: '13px', marginRight: '5px' }"
|
:style="{ maxHeight: '13px', maxWidth: '13px', marginRight: '5px' }"
|
||||||
/>
|
/>
|
||||||
<ops-icon
|
<ops-icon
|
||||||
v-else
|
v-else
|
||||||
:style="{ color: choice[1].icon.color, marginRight: '5px' }"
|
:style="{ color: choice[1].icon.color, marginRight: '5px' }"
|
||||||
:type="choice[1].icon.name"
|
:type="choice[1].icon.name"
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
{{ choice[0] }}
|
{{ choice[0] }}
|
||||||
</span>
|
</span>
|
||||||
</a-select-option>
|
</a-select-option>
|
||||||
</a-select>
|
</a-select>
|
||||||
<a-select
|
<a-select
|
||||||
:style="{ width: '100%' }"
|
:style="{ width: '100%' }"
|
||||||
v-decorator="[
|
v-decorator="[
|
||||||
attr.name,
|
attr.name,
|
||||||
{
|
{
|
||||||
rules: [{ required: attr.is_required }],
|
rules: [{ required: attr.is_required }],
|
||||||
},
|
},
|
||||||
]"
|
]"
|
||||||
placeholder="请选择"
|
:placeholder="$t('placeholder2')"
|
||||||
v-else-if="attr.is_list"
|
v-else-if="attr.is_list"
|
||||||
mode="tags"
|
mode="tags"
|
||||||
showSearch
|
showSearch
|
||||||
allowClear
|
allowClear
|
||||||
size="small"
|
size="small"
|
||||||
:getPopupContainer="(trigger) => trigger.parentElement"
|
:getPopupContainer="(trigger) => trigger.parentElement"
|
||||||
>
|
>
|
||||||
</a-select>
|
</a-select>
|
||||||
<a-input-number
|
<a-input-number
|
||||||
size="small"
|
size="small"
|
||||||
v-decorator="[
|
v-decorator="[
|
||||||
attr.name,
|
attr.name,
|
||||||
{
|
{
|
||||||
rules: [{ required: attr.is_required }],
|
rules: [{ required: attr.is_required }],
|
||||||
},
|
},
|
||||||
]"
|
]"
|
||||||
style="width: 100%"
|
style="width: 100%"
|
||||||
v-else-if="attr.value_type === '0' || attr.value_type === '1'"
|
v-else-if="attr.value_type === '0' || attr.value_type === '1'"
|
||||||
/>
|
/>
|
||||||
<a-date-picker
|
<a-date-picker
|
||||||
size="small"
|
size="small"
|
||||||
v-decorator="[
|
v-decorator="[
|
||||||
attr.name,
|
attr.name,
|
||||||
{
|
{
|
||||||
rules: [{ required: attr.is_required }],
|
rules: [{ required: attr.is_required }],
|
||||||
},
|
},
|
||||||
]"
|
]"
|
||||||
style="width: 100%"
|
style="width: 100%"
|
||||||
:format="attr.value_type === '4' ? 'YYYY-MM-DD' : 'YYYY-MM-DD HH:mm:ss'"
|
:format="attr.value_type === '4' ? 'YYYY-MM-DD' : 'YYYY-MM-DD HH:mm:ss'"
|
||||||
:valueFormat="attr.value_type === '4' ? 'YYYY-MM-DD' : 'YYYY-MM-DD HH:mm:ss'"
|
:valueFormat="attr.value_type === '4' ? 'YYYY-MM-DD' : 'YYYY-MM-DD HH:mm:ss'"
|
||||||
v-else-if="attr.value_type === '4' || attr.value_type === '3'"
|
v-else-if="attr.value_type === '4' || attr.value_type === '3'"
|
||||||
:showTime="attr.value_type === '4' ? false : { format: 'HH:mm:ss' }"
|
:showTime="attr.value_type === '4' ? false : { format: 'HH:mm:ss' }"
|
||||||
/>
|
/>
|
||||||
<!-- <a-input
|
<!-- <a-input
|
||||||
size="small"
|
size="small"
|
||||||
@focus="(e) => handleFocusInput(e, attr)"
|
@focus="(e) => handleFocusInput(e, attr)"
|
||||||
v-decorator="[
|
v-decorator="[
|
||||||
attr.name,
|
attr.name,
|
||||||
{
|
{
|
||||||
validateTrigger: ['submit'],
|
validateTrigger: ['submit'],
|
||||||
rules: [{ required: attr.is_required }],
|
rules: [{ required: attr.is_required }],
|
||||||
},
|
},
|
||||||
]"
|
]"
|
||||||
style="width: 100%"
|
style="width: 100%"
|
||||||
v-else-if="attr.value_type === '6'"
|
v-else-if="attr.value_type === '6'"
|
||||||
/> -->
|
/> -->
|
||||||
<a-input
|
<a-input
|
||||||
size="small"
|
size="small"
|
||||||
v-decorator="[
|
v-decorator="[
|
||||||
attr.name,
|
attr.name,
|
||||||
{
|
{
|
||||||
validateTrigger: ['submit'],
|
validateTrigger: ['submit'],
|
||||||
rules: [{ required: attr.is_required }],
|
rules: [{ required: attr.is_required }],
|
||||||
},
|
},
|
||||||
]"
|
]"
|
||||||
style="width: 100%"
|
style="width: 100%"
|
||||||
v-else
|
v-else
|
||||||
/>
|
/>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
</a-form>
|
</a-form>
|
||||||
</template>
|
</template>
|
||||||
<a v-if="!isEdit && !attr.is_computed" @click="handleEdit" :style="{ opacity: 0 }"><a-icon type="edit"/></a>
|
<a v-if="!isEdit && !attr.is_computed" @click="handleEdit" :style="{ opacity: 0 }"><a-icon type="edit"/></a>
|
||||||
<JsonEditor ref="jsonEditor" @jsonEditorOk="jsonEditorOk" />
|
<JsonEditor ref="jsonEditor" @jsonEditorOk="jsonEditorOk" />
|
||||||
</span>
|
</span>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import _ from 'lodash'
|
import _ from 'lodash'
|
||||||
import moment from 'moment'
|
import moment from 'moment'
|
||||||
import { updateCI } from '@/modules/cmdb/api/ci'
|
import { updateCI } from '@/modules/cmdb/api/ci'
|
||||||
import JsonEditor from '../../../components/JsonEditor/jsonEditor.vue'
|
import JsonEditor from '../../../components/JsonEditor/jsonEditor.vue'
|
||||||
import PasswordField from '../../../components/passwordField/index.vue'
|
import PasswordField from '../../../components/passwordField/index.vue'
|
||||||
import { getAttrPassword } from '../../../api/CITypeAttr'
|
import { getAttrPassword } from '../../../api/CITypeAttr'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'CiDetailAttrContent',
|
name: 'CiDetailAttrContent',
|
||||||
components: { JsonEditor, PasswordField },
|
components: { JsonEditor, PasswordField },
|
||||||
props: {
|
props: {
|
||||||
ci: {
|
ci: {
|
||||||
type: Object,
|
type: Object,
|
||||||
default: () => {},
|
default: () => {},
|
||||||
},
|
},
|
||||||
attr: {
|
attr: {
|
||||||
type: Object,
|
type: Object,
|
||||||
default: () => {},
|
default: () => {},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
isEdit: false,
|
isEdit: false,
|
||||||
form: this.$form.createForm(this, this.attr.name),
|
form: this.$form.createForm(this, this.attr.name),
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
document.addEventListener('click', this.eventListener)
|
document.addEventListener('click', this.eventListener)
|
||||||
},
|
},
|
||||||
beforeDestroy() {
|
beforeDestroy() {
|
||||||
document.removeEventListener('click', this.eventListener)
|
document.removeEventListener('click', this.eventListener)
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
moment,
|
moment,
|
||||||
eventListener(e) {
|
eventListener(e) {
|
||||||
const datePickerContainer = document.getElementsByClassName('ant-calendar-picker-container')
|
const datePickerContainer = document.getElementsByClassName('ant-calendar-picker-container')
|
||||||
if (this.isEdit && !datePickerContainer.length) {
|
if (this.isEdit && !datePickerContainer.length) {
|
||||||
const dom = document.getElementById(`ci-detail-attr-${this.attr.name}`)
|
const dom = document.getElementById(`ci-detail-attr-${this.attr.name}`)
|
||||||
e.stopPropagation()
|
e.stopPropagation()
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
if (dom) {
|
if (dom) {
|
||||||
const isSelf = dom.contains(e.target)
|
const isSelf = dom.contains(e.target)
|
||||||
if (!isSelf) {
|
if (!isSelf) {
|
||||||
this.handleCloseEdit()
|
this.handleCloseEdit()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
handleEdit(e) {
|
handleEdit(e) {
|
||||||
e.stopPropagation()
|
e.stopPropagation()
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
if (this.attr.value_type === '6') {
|
if (this.attr.value_type === '6') {
|
||||||
const jsonData = this.ci[this.attr.name]
|
const jsonData = this.ci[this.attr.name]
|
||||||
this.$refs.jsonEditor.open(null, null, jsonData || {})
|
this.$refs.jsonEditor.open(null, null, jsonData || {})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
this.isEdit = true
|
this.isEdit = true
|
||||||
this.$nextTick(async () => {
|
this.$nextTick(async () => {
|
||||||
if (this.attr.is_list && !this.attr.is_choice) {
|
if (this.attr.is_list && !this.attr.is_choice) {
|
||||||
this.form.setFieldsValue({
|
this.form.setFieldsValue({
|
||||||
[`${this.attr.name}`]: this.ci[this.attr.name] || null,
|
[`${this.attr.name}`]: this.ci[this.attr.name] || null,
|
||||||
})
|
})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if (this.attr.is_password) {
|
if (this.attr.is_password) {
|
||||||
await getAttrPassword(this.ci._id, this.attr.id).then((res) => {
|
await getAttrPassword(this.ci._id, this.attr.id).then((res) => {
|
||||||
this.form.setFieldsValue({
|
this.form.setFieldsValue({
|
||||||
[`${this.attr.name}`]: res.value ?? null,
|
[`${this.attr.name}`]: res.value ?? null,
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
this.form.setFieldsValue({
|
this.form.setFieldsValue({
|
||||||
[`${this.attr.name}`]: this.ci[this.attr.name] ?? null,
|
[`${this.attr.name}`]: this.ci[this.attr.name] ?? null,
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
async handleCloseEdit() {
|
async handleCloseEdit() {
|
||||||
const newData = this.form.getFieldValue(this.attr.name)
|
const newData = this.form.getFieldValue(this.attr.name)
|
||||||
if (!_.isEqual(this.ci[this.attr.name], newData)) {
|
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 })
|
||||||
.then(() => {
|
.then(() => {
|
||||||
this.$message.success('更新成功!')
|
this.$message.success(this.$t('updateSuccess'))
|
||||||
this.$emit('updateCIByself', { [`${this.attr.name}`]: newData }, this.attr.name)
|
this.$emit('updateCIByself', { [`${this.attr.name}`]: newData }, this.attr.name)
|
||||||
})
|
})
|
||||||
.catch(() => {
|
.catch(() => {
|
||||||
this.$emit('refresh', this.attr.name)
|
this.$emit('refresh', this.attr.name)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
this.isEdit = false
|
this.isEdit = false
|
||||||
},
|
},
|
||||||
// handleFocusInput(e, attr) {
|
// handleFocusInput(e, attr) {
|
||||||
// console.log('focus')
|
// console.log('focus')
|
||||||
// if (this.attr.value_type === '6') {
|
// if (this.attr.value_type === '6') {
|
||||||
// e.preventDefault()
|
// e.preventDefault()
|
||||||
// e.stopPropagation()
|
// e.stopPropagation()
|
||||||
// // e.srcElement.blur()
|
// // e.srcElement.blur()
|
||||||
// const jsonData = this.form.getFieldValue(attr.name)
|
// const jsonData = this.form.getFieldValue(attr.name)
|
||||||
// this.$refs.jsonEditor.open(null, null, jsonData ? JSON.parse(jsonData) : {})
|
// this.$refs.jsonEditor.open(null, null, jsonData ? JSON.parse(jsonData) : {})
|
||||||
// }
|
// }
|
||||||
// },
|
// },
|
||||||
jsonEditorOk(jsonData) {
|
jsonEditorOk(jsonData) {
|
||||||
if (!_.isEqual(this.ci[this.attr.name], jsonData)) {
|
if (!_.isEqual(this.ci[this.attr.name], jsonData)) {
|
||||||
updateCI(this.ci._id, { [`${this.attr.name}`]: jsonData })
|
updateCI(this.ci._id, { [`${this.attr.name}`]: jsonData })
|
||||||
.then(() => {
|
.then(() => {
|
||||||
this.$message.success('更新成功!')
|
this.$message.success(this.$t('updateSuccess'))
|
||||||
this.$emit('updateCIByself', { [`${this.attr.name}`]: jsonData }, this.attr.name)
|
this.$emit('updateCIByself', { [`${this.attr.name}`]: jsonData }, this.attr.name)
|
||||||
})
|
})
|
||||||
.catch(() => {
|
.catch(() => {
|
||||||
this.$emit('refresh', this.attr.name)
|
this.$emit('refresh', this.attr.name)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
getChoiceValueStyle(col, colValue) {
|
getChoiceValueStyle(col, colValue) {
|
||||||
const _find = col.choice_value.find((item) => String(item[0]) === String(colValue))
|
const _find = col.choice_value.find((item) => String(item[0]) === String(colValue))
|
||||||
if (_find) {
|
if (_find) {
|
||||||
return _find[1]?.style || {}
|
return _find[1]?.style || {}
|
||||||
}
|
}
|
||||||
return {}
|
return {}
|
||||||
},
|
},
|
||||||
getChoiceValueIcon(col, colValue) {
|
getChoiceValueIcon(col, colValue) {
|
||||||
const _find = col.choice_value.find((item) => String(item[0]) === String(colValue))
|
const _find = col.choice_value.find((item) => String(item[0]) === String(colValue))
|
||||||
if (_find) {
|
if (_find) {
|
||||||
return _find[1]?.icon || {}
|
return _find[1]?.icon || {}
|
||||||
}
|
}
|
||||||
return {}
|
return {}
|
||||||
},
|
},
|
||||||
getName(name) {
|
getName(name) {
|
||||||
return name ?? ''
|
return name ?? ''
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style></style>
|
<style></style>
|
||||||
|
|
|
@ -2,10 +2,10 @@
|
||||||
<div class="ci-detail-relation">
|
<div class="ci-detail-relation">
|
||||||
<a-radio-group v-model="activeKey" size="small" @change="handleChangeActiveKey">
|
<a-radio-group v-model="activeKey" size="small" @change="handleChangeActiveKey">
|
||||||
<a-radio-button value="1">
|
<a-radio-button value="1">
|
||||||
拓扑
|
{{ $t('cmdb.ci.topo') }}
|
||||||
</a-radio-button>
|
</a-radio-button>
|
||||||
<a-radio-button value="2">
|
<a-radio-button value="2">
|
||||||
表格
|
{{ $t('cmdb.ci.table') }}
|
||||||
</a-radio-button>
|
</a-radio-button>
|
||||||
</a-radio-group>
|
</a-radio-group>
|
||||||
<CiDetailRelationTopo ref="ciDetailRelationTopo" v-if="activeKey === '1'" />
|
<CiDetailRelationTopo ref="ciDetailRelationTopo" v-if="activeKey === '1'" />
|
||||||
|
@ -24,7 +24,7 @@
|
||||||
><a-icon
|
><a-icon
|
||||||
type="plus-square"
|
type="plus-square"
|
||||||
/></a>
|
/></a>
|
||||||
<span v-if="!canEdit[parent.id]">(当前模型关系为多对多,请前往关系视图进行增删操作)</span>
|
<span v-if="!canEdit[parent.id]">({{ $t('cmdb.ci.m2mTips') }})</span>
|
||||||
</div>
|
</div>
|
||||||
<vxe-grid
|
<vxe-grid
|
||||||
v-if="firstCIs[parent.name]"
|
v-if="firstCIs[parent.name]"
|
||||||
|
@ -39,7 +39,7 @@
|
||||||
class="ops-stripe-table"
|
class="ops-stripe-table"
|
||||||
>
|
>
|
||||||
<template #operation_default="{ row }">
|
<template #operation_default="{ row }">
|
||||||
<a-popconfirm arrowPointAtCenter title="确认删除关系?" @confirm="deleteRelation(row._id, ciId)">
|
<a-popconfirm arrowPointAtCenter :title="$t('cmdb.ci.confirmDeleteRelation')" @confirm="deleteRelation(row._id, ciId)">
|
||||||
<a
|
<a
|
||||||
:disabled="!canEdit[parent.id]"
|
:disabled="!canEdit[parent.id]"
|
||||||
:style="{
|
:style="{
|
||||||
|
@ -68,7 +68,7 @@
|
||||||
><a-icon
|
><a-icon
|
||||||
type="plus-square"
|
type="plus-square"
|
||||||
/></a>
|
/></a>
|
||||||
<span v-if="!canEdit[child.id]">(当前模型关系为多对多,请前往关系视图进行增删操作)</span>
|
<span v-if="!canEdit[child.id]">({{ $t('cmdb.ci.m2mTips') }})</span>
|
||||||
</div>
|
</div>
|
||||||
<vxe-grid
|
<vxe-grid
|
||||||
v-if="secondCIs[child.name]"
|
v-if="secondCIs[child.name]"
|
||||||
|
@ -82,7 +82,7 @@
|
||||||
class="ops-stripe-table"
|
class="ops-stripe-table"
|
||||||
>
|
>
|
||||||
<template #operation_default="{ row }">
|
<template #operation_default="{ row }">
|
||||||
<a-popconfirm arrowPointAtCenter title="确认删除关系?" @confirm="deleteRelation(ciId, row._id)">
|
<a-popconfirm arrowPointAtCenter :title="$t('cmdb.ci.confirmDeleteRelation')" @confirm="deleteRelation(ciId, row._id)">
|
||||||
<a
|
<a
|
||||||
:disabled="!canEdit[child.id]"
|
:disabled="!canEdit[child.id]"
|
||||||
:style="{
|
:style="{
|
||||||
|
@ -338,7 +338,7 @@ export default {
|
||||||
firstCIColumns[item.id].push({
|
firstCIColumns[item.id].push({
|
||||||
key: 'p_operation',
|
key: 'p_operation',
|
||||||
field: 'operation',
|
field: 'operation',
|
||||||
title: '操作',
|
title: this.$t('operation'),
|
||||||
width: '60px',
|
width: '60px',
|
||||||
fixed: 'right',
|
fixed: 'right',
|
||||||
slots: {
|
slots: {
|
||||||
|
@ -379,7 +379,7 @@ export default {
|
||||||
secondCIColumns[item.id].push({
|
secondCIColumns[item.id].push({
|
||||||
key: 'c_operation',
|
key: 'c_operation',
|
||||||
field: 'operation',
|
field: 'operation',
|
||||||
title: '操作',
|
title: this.$t('operation'),
|
||||||
width: '60px',
|
width: '60px',
|
||||||
fixed: 'right',
|
fixed: 'right',
|
||||||
slots: {
|
slots: {
|
||||||
|
|
|
@ -1,168 +1,168 @@
|
||||||
<template>
|
<template>
|
||||||
<div
|
<div
|
||||||
id="ci-detail-relation-topo"
|
id="ci-detail-relation-topo"
|
||||||
class="ci-detail-relation-topo"
|
class="ci-detail-relation-topo"
|
||||||
:style="{ width: '100%', marginTop: '20px', height: 'calc(100vh - 136px)' }"
|
:style="{ width: '100%', marginTop: '20px', height: 'calc(100vh - 136px)' }"
|
||||||
></div>
|
></div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import _ from 'lodash'
|
import _ from 'lodash'
|
||||||
import { TreeCanvas } from 'butterfly-dag'
|
import { TreeCanvas } from 'butterfly-dag'
|
||||||
import { searchCIRelation } from '@/modules/cmdb/api/CIRelation'
|
import { searchCIRelation } from '@/modules/cmdb/api/CIRelation'
|
||||||
import Node from './node.js'
|
import Node from './node.js'
|
||||||
|
|
||||||
import 'butterfly-dag/dist/index.css'
|
import 'butterfly-dag/dist/index.css'
|
||||||
import './index.less'
|
import './index.less'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'CiDetailRelationTopo',
|
name: 'CiDetailRelationTopo',
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
topoData: {},
|
topoData: {},
|
||||||
exsited_ci: [],
|
exsited_ci: [],
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
inject: ['ci_types'],
|
inject: ['ci_types'],
|
||||||
mounted() {},
|
mounted() {},
|
||||||
methods: {
|
methods: {
|
||||||
init() {
|
init() {
|
||||||
const root = document.getElementById('ci-detail-relation-topo')
|
const root = document.getElementById('ci-detail-relation-topo')
|
||||||
this.canvas = new TreeCanvas({
|
this.canvas = new TreeCanvas({
|
||||||
root: root,
|
root: root,
|
||||||
disLinkable: false, // 可删除连线
|
disLinkable: false, // 可删除连线
|
||||||
linkable: false, // 可连线
|
linkable: false, // 可连线
|
||||||
draggable: true, // 可拖动
|
draggable: true, // 可拖动
|
||||||
zoomable: true, // 可放大
|
zoomable: true, // 可放大
|
||||||
moveable: true, // 可平移
|
moveable: true, // 可平移
|
||||||
theme: {
|
theme: {
|
||||||
edge: {
|
edge: {
|
||||||
shapeType: 'AdvancedBezier',
|
shapeType: 'AdvancedBezier',
|
||||||
arrow: true,
|
arrow: true,
|
||||||
arrowPosition: 1,
|
arrowPosition: 1,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
layout: {
|
layout: {
|
||||||
type: 'mindmap',
|
type: 'mindmap',
|
||||||
options: {
|
options: {
|
||||||
direction: 'H',
|
direction: 'H',
|
||||||
getSide(d) {
|
getSide(d) {
|
||||||
return d.data.side || 'right'
|
return d.data.side || 'right'
|
||||||
},
|
},
|
||||||
getHeight(d) {
|
getHeight(d) {
|
||||||
return 10
|
return 10
|
||||||
},
|
},
|
||||||
getWidth(d) {
|
getWidth(d) {
|
||||||
return 40
|
return 40
|
||||||
},
|
},
|
||||||
getHGap(d) {
|
getHGap(d) {
|
||||||
return 80
|
return 80
|
||||||
},
|
},
|
||||||
getVGap(d) {
|
getVGap(d) {
|
||||||
return 40
|
return 40
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
this.canvas.setZoomable(true, true)
|
this.canvas.setZoomable(true, true)
|
||||||
this.canvas.on('events', ({ type, data }) => {
|
this.canvas.on('events', ({ type, data }) => {
|
||||||
const sourceNode = data?.id || null
|
const sourceNode = data?.id || null
|
||||||
if (type === 'custom:clickLeft') {
|
if (type === 'custom:clickLeft') {
|
||||||
searchCIRelation(`root_id=${Number(sourceNode)}&&level=1&&reverse=1&&count=10000`).then((res) => {
|
searchCIRelation(`root_id=${Number(sourceNode)}&&level=1&&reverse=1&&count=10000`).then((res) => {
|
||||||
this.redrawData(res, sourceNode, 'left')
|
this.redrawData(res, sourceNode, 'left')
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
if (type === 'custom:clickRight') {
|
if (type === 'custom:clickRight') {
|
||||||
searchCIRelation(`root_id=${Number(sourceNode)}&&level=1&&reverse=0&&count=10000`).then((res) => {
|
searchCIRelation(`root_id=${Number(sourceNode)}&&level=1&&reverse=0&&count=10000`).then((res) => {
|
||||||
this.redrawData(res, sourceNode, 'right')
|
this.redrawData(res, sourceNode, 'right')
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
setTopoData(data) {
|
setTopoData(data) {
|
||||||
this.canvas = null
|
this.canvas = null
|
||||||
this.init()
|
this.init()
|
||||||
this.topoData = _.cloneDeep(data)
|
this.topoData = _.cloneDeep(data)
|
||||||
this.canvas.draw(data, {}, () => {
|
this.canvas.draw(data, {}, () => {
|
||||||
this.canvas.focusCenterWithAnimate()
|
this.canvas.focusCenterWithAnimate()
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
redrawData(res, sourceNode, side) {
|
redrawData(res, sourceNode, side) {
|
||||||
const newNodes = []
|
const newNodes = []
|
||||||
const newEdges = []
|
const newEdges = []
|
||||||
if (!res.result.length) {
|
if (!res.result.length) {
|
||||||
this.$message.info('无层级关系!')
|
this.$message.info(this.$t('cmdb.ci.noLevel'))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
const ci_types_list = this.ci_types()
|
const ci_types_list = this.ci_types()
|
||||||
res.result.forEach((r) => {
|
res.result.forEach((r) => {
|
||||||
if (!this.exsited_ci.includes(r._id)) {
|
if (!this.exsited_ci.includes(r._id)) {
|
||||||
const _findCiType = ci_types_list.find((item) => item.id === r._type)
|
const _findCiType = ci_types_list.find((item) => item.id === r._type)
|
||||||
newNodes.push({
|
newNodes.push({
|
||||||
id: `${r._id}`,
|
id: `${r._id}`,
|
||||||
Class: Node,
|
Class: Node,
|
||||||
title: r.ci_type_alias || r.ci_type,
|
title: r.ci_type_alias || r.ci_type,
|
||||||
name: r.ci_type,
|
name: r.ci_type,
|
||||||
side: side,
|
side: side,
|
||||||
unique_alias: r.unique_alias,
|
unique_alias: r.unique_alias,
|
||||||
unique_name: r.unique,
|
unique_name: r.unique,
|
||||||
unique_value: r[r.unique],
|
unique_value: r[r.unique],
|
||||||
children: [],
|
children: [],
|
||||||
icon: _findCiType?.icon || '',
|
icon: _findCiType?.icon || '',
|
||||||
endpoints: [
|
endpoints: [
|
||||||
{
|
{
|
||||||
id: 'left',
|
id: 'left',
|
||||||
orientation: [-1, 0],
|
orientation: [-1, 0],
|
||||||
pos: [0, 0.5],
|
pos: [0, 0.5],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'right',
|
id: 'right',
|
||||||
orientation: [1, 0],
|
orientation: [1, 0],
|
||||||
pos: [0, 0.5],
|
pos: [0, 0.5],
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
newEdges.push({
|
newEdges.push({
|
||||||
id: `${r._id}`,
|
id: `${r._id}`,
|
||||||
source: 'right',
|
source: 'right',
|
||||||
target: 'left',
|
target: 'left',
|
||||||
sourceNode: side === 'right' ? sourceNode : `${r._id}`,
|
sourceNode: side === 'right' ? sourceNode : `${r._id}`,
|
||||||
targetNode: side === 'right' ? `${r._id}` : sourceNode,
|
targetNode: side === 'right' ? `${r._id}` : sourceNode,
|
||||||
type: 'endpoint',
|
type: 'endpoint',
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
const { nodes, edges } = this.canvas.getDataMap()
|
const { nodes, edges } = this.canvas.getDataMap()
|
||||||
// 删除原节点和边
|
// 删除原节点和边
|
||||||
this.canvas.removeNodes(nodes.map((node) => node.id))
|
this.canvas.removeNodes(nodes.map((node) => node.id))
|
||||||
this.canvas.removeEdges(edges)
|
this.canvas.removeEdges(edges)
|
||||||
|
|
||||||
const _topoData = _.cloneDeep(this.topoData)
|
const _topoData = _.cloneDeep(this.topoData)
|
||||||
_topoData.edges.push(...newEdges)
|
_topoData.edges.push(...newEdges)
|
||||||
let result
|
let result
|
||||||
const getTreeItem = (data, id) => {
|
const getTreeItem = (data, id) => {
|
||||||
for (let i = 0; i < data.length; i++) {
|
for (let i = 0; i < data.length; i++) {
|
||||||
if (data[i].id === id) {
|
if (data[i].id === id) {
|
||||||
result = data[i] // 结果赋值
|
result = data[i] // 结果赋值
|
||||||
result.edges = _topoData.edges
|
result.edges = _topoData.edges
|
||||||
break
|
break
|
||||||
} else {
|
} else {
|
||||||
if (data[i].children && data[i].children.length) {
|
if (data[i].children && data[i].children.length) {
|
||||||
getTreeItem(data[i].children, id)
|
getTreeItem(data[i].children, id)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
getTreeItem(_topoData.nodes.children, sourceNode)
|
getTreeItem(_topoData.nodes.children, sourceNode)
|
||||||
result.children.push(...newNodes)
|
result.children.push(...newNodes)
|
||||||
|
|
||||||
this.topoData = _topoData
|
this.topoData = _topoData
|
||||||
this.canvas.draw(_topoData, {}, () => {})
|
this.canvas.draw(_topoData, {}, () => {})
|
||||||
this.exsited_ci = [...new Set([...this.exsited_ci, ...res.result.map((r) => r._id)])]
|
this.exsited_ci = [...new Set([...this.exsited_ci, ...res.result.map((r) => r._id)])]
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style></style>
|
<style></style>
|
||||||
|
|
|
@ -1,56 +1,57 @@
|
||||||
/* eslint-disable no-useless-constructor */
|
/* eslint-disable no-useless-constructor */
|
||||||
import { TreeNode } from 'butterfly-dag'
|
import { TreeNode } from 'butterfly-dag'
|
||||||
|
import i18n from '@/lang'
|
||||||
import $ from 'jquery'
|
|
||||||
|
import $ from 'jquery'
|
||||||
class BaseNode extends TreeNode {
|
|
||||||
constructor(opts) {
|
class BaseNode extends TreeNode {
|
||||||
super(opts)
|
constructor(opts) {
|
||||||
}
|
super(opts)
|
||||||
|
}
|
||||||
draw = (opts) => {
|
|
||||||
const container = $(`<div class="${opts.id.startsWith('Root') ? 'root' : ''} ci-detail-relation-topo-node"></div>`)
|
draw = (opts) => {
|
||||||
.css('top', opts.top)
|
const container = $(`<div class="${opts.id.startsWith('Root') ? 'root' : ''} ci-detail-relation-topo-node"></div>`)
|
||||||
.css('left', opts.left)
|
.css('top', opts.top)
|
||||||
.attr('id', opts.id)
|
.css('left', opts.left)
|
||||||
let icon
|
.attr('id', opts.id)
|
||||||
if (opts.options.icon) {
|
let icon
|
||||||
if (opts.options.icon.split('$$')[2]) {
|
if (opts.options.icon) {
|
||||||
icon = $(`<img style="max-width:16px;max-height:16px;" src="/api/common-setting/v1/file/${opts.options.icon.split('$$')[3]}" />`)
|
if (opts.options.icon.split('$$')[2]) {
|
||||||
} else {
|
icon = $(`<img style="max-width:16px;max-height:16px;" src="/api/common-setting/v1/file/${opts.options.icon.split('$$')[3]}" />`)
|
||||||
icon = $(`<svg class="icon" style="color:${opts.options.icon.split('$$')[1]}" width="1em" height="1em" fill="currentColor" aria-hidden="true" focusable="false" class=""><use data-v-5bd421da="" xlink:href="#${opts.options.icon.split('$$')[0]}"></use></svg>`)
|
} else {
|
||||||
}
|
icon = $(`<svg class="icon" style="color:${opts.options.icon.split('$$')[1]}" width="1em" height="1em" fill="currentColor" aria-hidden="true" focusable="false" class=""><use data-v-5bd421da="" xlink:href="#${opts.options.icon.split('$$')[0]}"></use></svg>`)
|
||||||
} else {
|
}
|
||||||
icon = $(`<span class="icon icon-default">${opts.options.name[0].toUpperCase()}</span>`)
|
} else {
|
||||||
}
|
icon = $(`<span class="icon icon-default">${opts.options.name[0].toUpperCase()}</span>`)
|
||||||
|
}
|
||||||
const titleContent = $(`<div title=${opts.options.title} class="title">${opts.options.title}</div>`)
|
|
||||||
const uniqueDom = $(`<div class="unique">${opts.options.unique_alias || opts.options.unique_name}:${opts.options.unique_value}<div>`)
|
const titleContent = $(`<div title=${opts.options.title} class="title">${opts.options.title}</div>`)
|
||||||
container.append(icon)
|
const uniqueDom = $(`<div class="unique">${opts.options.unique_alias || opts.options.unique_name}:${opts.options.unique_value}<div>`)
|
||||||
container.append(titleContent)
|
container.append(icon)
|
||||||
container.append(uniqueDom)
|
container.append(titleContent)
|
||||||
|
container.append(uniqueDom)
|
||||||
if (opts.options.side && (!opts.options.children.length && !(opts.options.edges && opts.options.edges.length && opts.options.edges.find(e => e.source === opts.options.side && e.sourceNode === opts.options.id)))) {
|
|
||||||
const addIcon = $(`<i aria-label="图标: plus-square" class="anticon anticon-plus-square add-icon-${opts.options.side}"><svg viewBox="64 64 896 896" data-icon="plus-square" width="1em" height="1em" fill="currentColor" aria-hidden="true" focusable="false" class=""><path d="M328 544h152v152c0 4.4 3.6 8 8 8h48c4.4 0 8-3.6 8-8V544h152c4.4 0 8-3.6 8-8v-48c0-4.4-3.6-8-8-8H544V328c0-4.4-3.6-8-8-8h-48c-4.4 0-8 3.6-8 8v152H328c-4.4 0-8 3.6-8 8v48c0 4.4 3.6 8 8 8z"></path><path d="M880 112H144c-17.7 0-32 14.3-32 32v736c0 17.7 14.3 32 32 32h736c17.7 0 32-14.3 32-32V144c0-17.7-14.3-32-32-32zm-40 728H184V184h656v656z"></path></svg></i>`)
|
if (opts.options.side && (!opts.options.children.length && !(opts.options.edges && opts.options.edges.length && opts.options.edges.find(e => e.source === opts.options.side && e.sourceNode === opts.options.id)))) {
|
||||||
container.append(addIcon)
|
const addIcon = $(`<i aria-label="${i18n.t('icon')}: plus-square" class="anticon anticon-plus-square add-icon-${opts.options.side}"><svg viewBox="64 64 896 896" data-icon="plus-square" width="1em" height="1em" fill="currentColor" aria-hidden="true" focusable="false" class=""><path d="M328 544h152v152c0 4.4 3.6 8 8 8h48c4.4 0 8-3.6 8-8V544h152c4.4 0 8-3.6 8-8v-48c0-4.4-3.6-8-8-8H544V328c0-4.4-3.6-8-8-8h-48c-4.4 0-8 3.6-8 8v152H328c-4.4 0-8 3.6-8 8v48c0 4.4 3.6 8 8 8z"></path><path d="M880 112H144c-17.7 0-32 14.3-32 32v736c0 17.7 14.3 32 32 32h736c17.7 0 32-14.3 32-32V144c0-17.7-14.3-32-32-32zm-40 728H184V184h656v656z"></path></svg></i>`)
|
||||||
addIcon.on('click', () => {
|
container.append(addIcon)
|
||||||
if (opts.options.side === 'left') {
|
addIcon.on('click', () => {
|
||||||
this.emit('events', {
|
if (opts.options.side === 'left') {
|
||||||
type: 'custom:clickLeft',
|
this.emit('events', {
|
||||||
data: { ...this }
|
type: 'custom:clickLeft',
|
||||||
})
|
data: { ...this }
|
||||||
}
|
})
|
||||||
if (opts.options.side === 'right') {
|
}
|
||||||
this.emit('events', {
|
if (opts.options.side === 'right') {
|
||||||
type: 'custom:clickRight',
|
this.emit('events', {
|
||||||
data: { ...this }
|
type: 'custom:clickRight',
|
||||||
})
|
data: { ...this }
|
||||||
}
|
})
|
||||||
})
|
}
|
||||||
}
|
})
|
||||||
|
}
|
||||||
return container[0]
|
|
||||||
}
|
return container[0]
|
||||||
}
|
}
|
||||||
|
}
|
||||||
export default BaseNode
|
|
||||||
|
export default BaseNode
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
<template>
|
<template>
|
||||||
<a-form :form="form">
|
<a-form :form="form">
|
||||||
<a-divider style="font-size: 14px; margin: 14px 0; font-weight: 700">{{ group.name || '其他' }}</a-divider>
|
<a-divider style="font-size:14px;margin:14px 0;font-weight:700;">{{ group.name || $t('other') }}</a-divider>
|
||||||
<a-row :gutter="24" align="top" type="flex">
|
<a-row :gutter="24" align="top" type="flex">
|
||||||
<a-col
|
<a-col
|
||||||
:span="12"
|
:span="12"
|
||||||
|
@ -21,11 +21,11 @@
|
||||||
v-decorator="[
|
v-decorator="[
|
||||||
attr.name,
|
attr.name,
|
||||||
{
|
{
|
||||||
rules: [{ required: attr.is_required, message: `请选择${attr.alias || attr.name}` }],
|
rules: [{ required: attr.is_required, message: $t('placeholder2') + `${attr.alias || attr.name}` }],
|
||||||
initialValue: attr.default && attr.default.default ? attr.default.default : attr.is_list ? [] : null,
|
initialValue: attr.default && attr.default.default ? attr.default.default : attr.is_list ? [] : null,
|
||||||
},
|
},
|
||||||
]"
|
]"
|
||||||
placeholder="请选择"
|
:placeholder="$t('placeholder2')"
|
||||||
v-if="attr.is_choice"
|
v-if="attr.is_choice"
|
||||||
:mode="attr.is_list ? 'multiple' : 'default'"
|
:mode="attr.is_list ? 'multiple' : 'default'"
|
||||||
showSearch
|
showSearch
|
||||||
|
@ -60,7 +60,7 @@
|
||||||
v-decorator="[
|
v-decorator="[
|
||||||
attr.name,
|
attr.name,
|
||||||
{
|
{
|
||||||
rules: [{ required: attr.is_required, message: `请选择${attr.alias || attr.name}` }],
|
rules: [{ required: attr.is_required, message: $t('placeholder2') + `${attr.alias || attr.name}` }],
|
||||||
initialValue: attr.default && attr.default.default ? attr.default.default : attr.is_list ? [] : null,
|
initialValue: attr.default && attr.default.default ? attr.default.default : attr.is_list ? [] : null,
|
||||||
},
|
},
|
||||||
]"
|
]"
|
||||||
|
@ -70,7 +70,7 @@
|
||||||
v-decorator="[
|
v-decorator="[
|
||||||
attr.name,
|
attr.name,
|
||||||
{
|
{
|
||||||
rules: [{ required: attr.is_required, message: `请输入${attr.alias || attr.name}` }],
|
rules: [{ required: attr.is_required, message: $t('placeholder1') + `${attr.alias || attr.name}` }],
|
||||||
initialValue: attr.default && attr.default.default ? attr.default.default : null,
|
initialValue: attr.default && attr.default.default ? attr.default.default : null,
|
||||||
},
|
},
|
||||||
]"
|
]"
|
||||||
|
@ -81,7 +81,7 @@
|
||||||
v-decorator="[
|
v-decorator="[
|
||||||
attr.name,
|
attr.name,
|
||||||
{
|
{
|
||||||
rules: [{ required: attr.is_required, message: `请选择${attr.alias || attr.name}` }],
|
rules: [{ required: attr.is_required, message: $t('placeholder2') + `${attr.alias || attr.name}` }],
|
||||||
initialValue: attr.default && attr.default.default ? moment(attr.default.default) : null,
|
initialValue: attr.default && attr.default.default ? moment(attr.default.default) : null,
|
||||||
},
|
},
|
||||||
]"
|
]"
|
||||||
|
@ -96,7 +96,7 @@
|
||||||
attr.name,
|
attr.name,
|
||||||
{
|
{
|
||||||
validateTrigger: ['submit'],
|
validateTrigger: ['submit'],
|
||||||
rules: [{ required: attr.is_required, message: `请输入${attr.alias || attr.name}` }],
|
rules: [{ required: attr.is_required, message: $t('placeholder1') + `${attr.alias || attr.name}` }],
|
||||||
initialValue: attr.default && attr.default.default ? JSON.stringify(attr.default.default) : '',
|
initialValue: attr.default && attr.default.default ? JSON.stringify(attr.default.default) : '',
|
||||||
},
|
},
|
||||||
]"
|
]"
|
||||||
|
@ -109,7 +109,7 @@
|
||||||
attr.name,
|
attr.name,
|
||||||
{
|
{
|
||||||
validateTrigger: ['submit'],
|
validateTrigger: ['submit'],
|
||||||
rules: [{ required: attr.is_required, message: `请输入${attr.alias || attr.name}` }],
|
rules: [{ required: attr.is_required, message: $t('placeholder1') + `${attr.alias || attr.name}` }],
|
||||||
initialValue: attr.default && attr.default.default ? attr.default.default : null,
|
initialValue: attr.default && attr.default.default ? attr.default.default : null,
|
||||||
},
|
},
|
||||||
]"
|
]"
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
visible = false
|
visible = false
|
||||||
}
|
}
|
||||||
"
|
"
|
||||||
title="字段设置"
|
:title="$t('cmdb.ci.attributeSettings')"
|
||||||
>
|
>
|
||||||
<CustomTransfer
|
<CustomTransfer
|
||||||
ref="customTransfer"
|
ref="customTransfer"
|
||||||
|
@ -17,16 +17,16 @@
|
||||||
width: '230px',
|
width: '230px',
|
||||||
height: '500px',
|
height: '500px',
|
||||||
}"
|
}"
|
||||||
:titles="['未选属性', '已选属性']"
|
:titles="[$t('cmdb.components.unselectAttributes'), $t('cmdb.components.selectAttributes')]"
|
||||||
:render="item => item.title"
|
:render="item => item.title"
|
||||||
:targetKeys="selectedAttrList"
|
:targetKeys="selectedAttrList"
|
||||||
@change="handleChange"
|
@change="handleChange"
|
||||||
@selectChange="selectChange"
|
@selectChange="selectChange"
|
||||||
>
|
>
|
||||||
<span slot="notFoundContent">没数据</span>
|
<span slot="notFoundContent">{{ $t('noData') }}</span>
|
||||||
</CustomTransfer>
|
</CustomTransfer>
|
||||||
<div class="custom-drawer-bottom-action">
|
<div class="custom-drawer-bottom-action">
|
||||||
<a-button @click="handleSubmit" type="primary">确定</a-button>
|
<a-button @click="handleSubmit" type="primary">{{ $t('confirm') }}</a-button>
|
||||||
</div>
|
</div>
|
||||||
</CustomDrawer>
|
</CustomDrawer>
|
||||||
</template>
|
</template>
|
||||||
|
@ -79,16 +79,17 @@ export default {
|
||||||
this.selectedAttrList = targetKeys
|
this.selectedAttrList = targetKeys
|
||||||
},
|
},
|
||||||
handleSubmit() {
|
handleSubmit() {
|
||||||
|
const that = this
|
||||||
if (this.selectedAttrList.length) {
|
if (this.selectedAttrList.length) {
|
||||||
subscribeCIType(this.typeId, this.selectedAttrList).then(res => {
|
subscribeCIType(this.typeId, this.selectedAttrList).then(res => {
|
||||||
this.$message.success('订阅成功!')
|
this.$message.success(this.$t('cmdb.components.subSuccess'))
|
||||||
this.visible = false
|
this.visible = false
|
||||||
this.$emit('refresh')
|
this.$emit('refresh')
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
this.$confirm({
|
this.$confirm({
|
||||||
title: '警告',
|
title: that.$t('warning'),
|
||||||
content: '必须至少选择一个字段',
|
content: that.$t('cmdb.ci.tips4'),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
@ -75,12 +75,12 @@ export default {
|
||||||
return [item, !!this.fixedList.includes(item)]
|
return [item, !!this.fixedList.includes(item)]
|
||||||
})
|
})
|
||||||
).then((res) => {
|
).then((res) => {
|
||||||
this.$message.success('订阅成功!')
|
this.$message.success(this.$t('cmdb.components.subSuccess'))
|
||||||
this.visible = false
|
this.visible = false
|
||||||
this.$emit('refresh')
|
this.$emit('refresh')
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
this.$message.error('请至少选择一个字段!')
|
this.$message.error(this.$t('cmdb.ci.tips4'))
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
setTargetKeys(targetKeys) {
|
setTargetKeys(targetKeys) {
|
||||||
|
|
|
@ -3,9 +3,9 @@
|
||||||
<Discovery :isSelected="true" :style="{ maxHeight: '75vh', overflow: 'auto' }" />
|
<Discovery :isSelected="true" :style="{ maxHeight: '75vh', overflow: 'auto' }" />
|
||||||
<template #footer>
|
<template #footer>
|
||||||
<a-space>
|
<a-space>
|
||||||
<a-button @click="handleCancel">取消</a-button>
|
<a-button @click="handleCancel">{{ $t('cancel') }}</a-button>
|
||||||
<a-button type="primary" @click="handleOK">确认</a-button>
|
<a-button type="primary" @click="handleOK">{{ $t('confirm') }}</a-button>
|
||||||
<a-button type="primary" @click="addPlugin">新建plugin</a-button>
|
<a-button type="primary" @click="addPlugin">{{ $t('cmdb.ciType.addPlugin') }}</a-button>
|
||||||
</a-space>
|
</a-space>
|
||||||
</template>
|
</template>
|
||||||
</a-modal>
|
</a-modal>
|
||||||
|
@ -55,7 +55,7 @@ export default {
|
||||||
await Promise.all(promises)
|
await Promise.all(promises)
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
this.getCITypeDiscovery(res[0].id)
|
this.getCITypeDiscovery(res[0].id)
|
||||||
this.$message.success('添加成功')
|
this.$message.success(this.$t('addSuccess'))
|
||||||
})
|
})
|
||||||
.catch(() => {
|
.catch(() => {
|
||||||
this.getCITypeDiscovery()
|
this.getCITypeDiscovery()
|
||||||
|
|
|
@ -29,7 +29,7 @@
|
||||||
slot="tabBarExtraContent"
|
slot="tabBarExtraContent"
|
||||||
:style="{ cursor: 'pointer' }"
|
:style="{ cursor: 'pointer' }"
|
||||||
>
|
>
|
||||||
<ops-icon type="icon-xianxing-tianjia" :style="{ color: '#2F54EB' }" /><a>添加</a>
|
<ops-icon type="icon-xianxing-tianjia" :style="{ color: '#2F54EB' }" /><a>{{ $t('add') }}</a>
|
||||||
</a-space>
|
</a-space>
|
||||||
</a-tabs>
|
</a-tabs>
|
||||||
</div>
|
</div>
|
||||||
|
@ -40,7 +40,7 @@
|
||||||
}"
|
}"
|
||||||
>
|
>
|
||||||
<img slot="image" :src="require('@/assets/data_empty.png')" />
|
<img slot="image" :src="require('@/assets/data_empty.png')" />
|
||||||
<span slot="description"> 暂无数据 </span>
|
<span slot="description"> {{ $t('noData') }} </span>
|
||||||
<a-button
|
<a-button
|
||||||
@click="
|
@click="
|
||||||
() => {
|
() => {
|
||||||
|
@ -52,7 +52,7 @@
|
||||||
icon="plus"
|
icon="plus"
|
||||||
class="ops-button-primary"
|
class="ops-button-primary"
|
||||||
>
|
>
|
||||||
添加
|
{{ $t('add') }}
|
||||||
</a-button>
|
</a-button>
|
||||||
</a-empty>
|
</a-empty>
|
||||||
<ADModal ref="adModal" :CITypeId="CITypeId" @addPlugin="openEditDrawer(null, 'add', 'agent')" />
|
<ADModal ref="adModal" :CITypeId="CITypeId" @addPlugin="openEditDrawer(null, 'add', 'agent')" />
|
||||||
|
@ -158,10 +158,10 @@ export default {
|
||||||
e.stopPropagation()
|
e.stopPropagation()
|
||||||
const that = this
|
const that = this
|
||||||
this.$confirm({
|
this.$confirm({
|
||||||
title: `确认删除 【${item?.extra_option?.alias || this.getADCITypeParam(item.adr_id)}】`,
|
title: that.$t('cmdb.ciType.confirmDeleteADT', { pluginName: `${item?.extra_option?.alias || this.getADCITypeParam(item.adr_id)}` }),
|
||||||
content: (h) => (
|
content: (h) => (
|
||||||
<div>
|
<div>
|
||||||
<a-checkbox v-model={that.deletePlugin}>删除插件</a-checkbox>
|
<a-checkbox v-model={that.deletePlugin}>{that.$t('cmdb.ciType.deletePlugin')}</a-checkbox>
|
||||||
</div>
|
</div>
|
||||||
),
|
),
|
||||||
onOk() {
|
onOk() {
|
||||||
|
@ -169,7 +169,7 @@ export default {
|
||||||
if (that.currentTab === item.id) {
|
if (that.currentTab === item.id) {
|
||||||
that.currentTab = ''
|
that.currentTab = ''
|
||||||
}
|
}
|
||||||
that.$message.success('删除成功!')
|
that.$message.success(that.$t('deleteSuccess'))
|
||||||
that.getCITypeDiscovery()
|
that.getCITypeDiscovery()
|
||||||
if (that.deletePlugin) {
|
if (that.deletePlugin) {
|
||||||
await deleteDiscovery(item.adr_id).finally(() => {
|
await deleteDiscovery(item.adr_id).finally(() => {
|
||||||
|
|
|
@ -1,396 +1,398 @@
|
||||||
<template>
|
<template>
|
||||||
<div :style="{ height: `${windowHeight - 156}px`, overflow: 'auto', position: 'relative' }">
|
<div :style="{ height: `${windowHeight - 156}px`, overflow: 'auto', position: 'relative' }">
|
||||||
<a
|
<a
|
||||||
v-if="!adrIsInner"
|
v-if="!adrIsInner"
|
||||||
:style="{ position: 'absolute', right: 0, top: 0 }"
|
:style="{ position: 'absolute', right: 0, top: 0 }"
|
||||||
@click="
|
@click="
|
||||||
() => {
|
() => {
|
||||||
$emit('openEditDrawer', currentAdr, 'edit', 'agent')
|
$emit('openEditDrawer', currentAdr, 'edit', 'agent')
|
||||||
}
|
}
|
||||||
"
|
"
|
||||||
>
|
>
|
||||||
<a-space>
|
<a-space>
|
||||||
<ops-icon type="icon-xianxing-edit" />
|
<ops-icon type="icon-xianxing-edit" />
|
||||||
<span>编辑</span>
|
<span>{{ $t('edit') }}</span>
|
||||||
</a-space>
|
</a-space>
|
||||||
</a>
|
</a>
|
||||||
<div>别名:<a-input v-model="alias" style="width:200px;" /></div>
|
<div>{{ $t('alias') }}:<a-input v-model="alias" style="width:200px;" /></div>
|
||||||
<div class="attr-ad-header">字段映射</div>
|
<div class="attr-ad-header">{{ $t('cmdb.ciType.attributeMap') }}</div>
|
||||||
<vxe-table
|
<vxe-table
|
||||||
v-if="adrType === 'agent'"
|
v-if="adrType === 'agent'"
|
||||||
ref="xTable"
|
ref="xTable"
|
||||||
:edit-config="{ trigger: 'click', mode: 'cell' }"
|
:edit-config="{ trigger: 'click', mode: 'cell' }"
|
||||||
size="mini"
|
size="mini"
|
||||||
stripe
|
stripe
|
||||||
class="ops-stripe-table"
|
class="ops-stripe-table"
|
||||||
:data="tableData"
|
:data="tableData"
|
||||||
:style="{ width: '700px', marginBottom: '20px' }"
|
:style="{ width: '700px', marginBottom: '20px' }"
|
||||||
>
|
>
|
||||||
<vxe-colgroup title="自动发现">
|
<vxe-colgroup :title="$t('cmdb.ciType.autoDiscovery')">
|
||||||
<vxe-column field="name" title="名称"> </vxe-column>
|
<vxe-column field="name" :title="$t('name')"> </vxe-column>
|
||||||
<vxe-column field="type" title="类型"> </vxe-column>
|
<vxe-column field="type" :title="$t('type')"> </vxe-column>
|
||||||
<vxe-column field="desc" title="描述"> </vxe-column>
|
<vxe-column field="desc" :title="$t('desc')"> </vxe-column>
|
||||||
</vxe-colgroup>
|
</vxe-colgroup>
|
||||||
<vxe-colgroup title="模型属性">
|
<vxe-colgroup :title="$t('cmdb.ciType.attributes')">
|
||||||
<vxe-column field="attr" title="名称" :edit-render="{}">
|
<vxe-column field="attr" :title="$t('name')" :edit-render="{}">
|
||||||
<template #default="{row}">
|
<template #default="{row}">
|
||||||
{{ row.attr }}
|
{{ row.attr }}
|
||||||
</template>
|
</template>
|
||||||
<template #edit="{ row }">
|
<template #edit="{ row }">
|
||||||
<vxe-select
|
<vxe-select
|
||||||
filterable
|
filterable
|
||||||
clearable
|
clearable
|
||||||
v-model="row.attr"
|
v-model="row.attr"
|
||||||
type="text"
|
type="text"
|
||||||
:options="ciTypeAttributes"
|
:options="ciTypeAttributes"
|
||||||
transfer
|
transfer
|
||||||
></vxe-select>
|
></vxe-select>
|
||||||
</template>
|
</template>
|
||||||
</vxe-column>
|
</vxe-column>
|
||||||
</vxe-colgroup>
|
</vxe-colgroup>
|
||||||
</vxe-table>
|
</vxe-table>
|
||||||
<HttpSnmpAD
|
<HttpSnmpAD
|
||||||
v-else
|
v-else
|
||||||
:isEdit="true"
|
:isEdit="true"
|
||||||
ref="httpSnmpAd"
|
ref="httpSnmpAd"
|
||||||
:ruleType="adrType"
|
:ruleType="adrType"
|
||||||
:ruleName="adrName"
|
:ruleName="adrName"
|
||||||
:ciTypeAttributes="ciTypeAttributes"
|
:ciTypeAttributes="ciTypeAttributes"
|
||||||
:adCITypeList="adCITypeList"
|
:adCITypeList="adCITypeList"
|
||||||
:currentTab="adr_id"
|
:currentTab="adr_id"
|
||||||
:style="{ marginBottom: '20px' }"
|
:style="{ marginBottom: '20px' }"
|
||||||
/>
|
/>
|
||||||
<a-form-model
|
<a-form-model
|
||||||
v-if="adrType === 'http'"
|
v-if="adrType === 'http'"
|
||||||
:model="form2"
|
:model="form2"
|
||||||
:labelCol="{ span: 2 }"
|
:labelCol="{ span: 2 }"
|
||||||
:wrapperCol="{ span: 8 }"
|
:wrapperCol="{ span: 8 }"
|
||||||
:style="{ margin: '20px 0' }"
|
:style="{ margin: '20px 0' }"
|
||||||
>
|
>
|
||||||
<a-form-model-item label="key">
|
<a-form-model-item label="key">
|
||||||
<a-input-password v-model="form2.key" />
|
<a-input-password v-model="form2.key" />
|
||||||
</a-form-model-item>
|
</a-form-model-item>
|
||||||
<a-form-model-item label="secret">
|
<a-form-model-item label="secret">
|
||||||
<a-input-password v-model="form2.secret" />
|
<a-input-password v-model="form2.secret" />
|
||||||
</a-form-model-item>
|
</a-form-model-item>
|
||||||
</a-form-model>
|
</a-form-model>
|
||||||
<a-form :form="form3" v-if="adrType === 'snmp'" class="attr-ad-snmp-form">
|
<a-form :form="form3" v-if="adrType === 'snmp'" class="attr-ad-snmp-form">
|
||||||
<a-col :span="24">
|
<a-col :span="24">
|
||||||
<a-form-item label="节点" :labelCol="{ span: 2 }" :wrapperCol="{ span: 20 }">
|
<a-form-item :label="$t('cmdb.ciType.node')" :labelCol="{ span: 2 }" :wrapperCol="{ span: 20 }">
|
||||||
<MonitorNodeSetting ref="monitorNodeSetting" :initNodes="nodes" :form="form3" />
|
<MonitorNodeSetting ref="monitorNodeSetting" :initNodes="nodes" :form="form3" />
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
</a-col>
|
</a-col>
|
||||||
</a-form>
|
</a-form>
|
||||||
<div class="attr-ad-header">执行配置</div>
|
<div class="attr-ad-header">{{ $t('cmdb.ciType.adExecConfig') }}</div>
|
||||||
<a-form-model :model="form" :labelCol="{ span: 2 }" :wrapperCol="{ span: 20 }">
|
<a-form-model :model="form" :labelCol="{ span: 2 }" :wrapperCol="{ span: 20 }">
|
||||||
<a-form-model-item label="执行机器">
|
<a-form-model-item :label="$t('cmdb.ciType.adExecTarget')">
|
||||||
<CustomRadio v-model="agent_type" :radioList="agentTypeRadioList">
|
<CustomRadio v-model="agent_type" :radioList="agentTypeRadioList">
|
||||||
<a-input
|
<a-input
|
||||||
:style="{ width: '300px' }"
|
:style="{ width: '300px' }"
|
||||||
placeholder="请输入以0x开头的16进制OneAgent ID"
|
:placeholder="$t('cmdb.ciType.oneagentIdTips')"
|
||||||
v-show="agent_type === 'agent_id'"
|
v-show="agent_type === 'agent_id'"
|
||||||
slot="extra_agent_id"
|
slot="extra_agent_id"
|
||||||
v-model="form.agent_id"
|
v-model="form.agent_id"
|
||||||
/>
|
/>
|
||||||
<a-input
|
<a-input
|
||||||
:style="{ width: '300px' }"
|
:style="{ width: '300px' }"
|
||||||
v-show="agent_type === 'query_expr'"
|
v-show="agent_type === 'query_expr'"
|
||||||
slot="extra_query_expr"
|
slot="extra_query_expr"
|
||||||
placeholder="从CMDB选择"
|
:placeholder="$t('cmdb.ciType.selectFromCMDBTips')"
|
||||||
v-model="form.query_expr"
|
v-model="form.query_expr"
|
||||||
>
|
>
|
||||||
<a @click="handleOpenCmdb" slot="suffix"><a-icon type="menu"/></a>
|
<a @click="handleOpenCmdb" slot="suffix"><a-icon type="menu"/></a>
|
||||||
</a-input>
|
</a-input>
|
||||||
</CustomRadio>
|
</CustomRadio>
|
||||||
</a-form-model-item>
|
</a-form-model-item>
|
||||||
<a-form-model-item label="自动入库">
|
<a-form-model-item :label="$t('cmdb.ciType.adAutoInLib')">
|
||||||
<a-switch v-model="form.auto_accept" />
|
<a-switch v-model="form.auto_accept" />
|
||||||
</a-form-model-item>
|
</a-form-model-item>
|
||||||
</a-form-model>
|
</a-form-model>
|
||||||
<div class="attr-ad-header">采集频率</div>
|
<div class="attr-ad-header">{{ $t('cmdb.ciType.adInterval') }}</div>
|
||||||
<CustomRadio :radioList="radioList" v-model="interval">
|
<CustomRadio :radioList="radioList" v-model="interval">
|
||||||
<span v-show="interval === 'interval'" slot="extra_interval">
|
<span v-show="interval === 'interval'" slot="extra_interval">
|
||||||
<a-input-number v-model="intervalValue" :min="1" /> 秒
|
<a-input-number v-model="intervalValue" :min="1" /> {{ $t('seconds') }}
|
||||||
</span>
|
</span>
|
||||||
</CustomRadio>
|
</CustomRadio>
|
||||||
|
|
||||||
<div class="attr-ad-footer">
|
<div class="attr-ad-footer">
|
||||||
<a-button type="primary" @click="handleSave">保存</a-button>
|
<a-button type="primary" @click="handleSave">{{ $t('save') }}</a-button>
|
||||||
</div>
|
</div>
|
||||||
<CMDBExprDrawer ref="cmdbDrawer" @copySuccess="copySuccess" />
|
<CMDBExprDrawer ref="cmdbDrawer" @copySuccess="copySuccess" />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { v4 as uuidv4 } from 'uuid'
|
import { v4 as uuidv4 } from 'uuid'
|
||||||
import { mapState } from 'vuex'
|
import { mapState } from 'vuex'
|
||||||
import Vcrontab from '@/components/Crontab'
|
import Vcrontab from '@/components/Crontab'
|
||||||
import { putCITypeDiscovery } from '../../api/discovery'
|
import { putCITypeDiscovery } from '../../api/discovery'
|
||||||
import HttpSnmpAD from '../../components/httpSnmpAD'
|
import HttpSnmpAD from '../../components/httpSnmpAD'
|
||||||
import CMDBExprDrawer from '@/components/CMDBExprDrawer'
|
import CMDBExprDrawer from '@/components/CMDBExprDrawer'
|
||||||
import MonitorNodeSetting from '@/components/MonitorNodeSetting'
|
import MonitorNodeSetting from '@/components/MonitorNodeSetting'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'AttrADTabpane',
|
name: 'AttrADTabpane',
|
||||||
components: { Vcrontab, HttpSnmpAD, CMDBExprDrawer, MonitorNodeSetting },
|
components: { Vcrontab, HttpSnmpAD, CMDBExprDrawer, MonitorNodeSetting },
|
||||||
props: {
|
props: {
|
||||||
adr_id: {
|
adr_id: {
|
||||||
type: Number,
|
type: Number,
|
||||||
default: 0,
|
default: 0,
|
||||||
},
|
},
|
||||||
adrList: {
|
adrList: {
|
||||||
type: Array,
|
type: Array,
|
||||||
default: () => {},
|
default: () => {},
|
||||||
},
|
},
|
||||||
adCITypeList: {
|
adCITypeList: {
|
||||||
type: Array,
|
type: Array,
|
||||||
default: () => {},
|
default: () => {},
|
||||||
},
|
},
|
||||||
currentAdt: {
|
currentAdt: {
|
||||||
type: Object,
|
type: Object,
|
||||||
default: () => {},
|
default: () => {},
|
||||||
},
|
},
|
||||||
currentAdr: {
|
currentAdr: {
|
||||||
type: Object,
|
type: Object,
|
||||||
default: () => {},
|
default: () => {},
|
||||||
},
|
},
|
||||||
ciTypeAttributes: {
|
ciTypeAttributes: {
|
||||||
type: Array,
|
type: Array,
|
||||||
default: () => [],
|
default: () => [],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
const radioList = [
|
return {
|
||||||
{ value: 'interval', label: '按间隔' },
|
tableData: [],
|
||||||
]
|
form: {
|
||||||
return {
|
agent_id: '',
|
||||||
radioList,
|
auto_accept: false,
|
||||||
tableData: [],
|
query_expr: '',
|
||||||
form: {
|
},
|
||||||
agent_id: '',
|
form2: {
|
||||||
auto_accept: false,
|
key: '',
|
||||||
query_expr: '',
|
secret: '',
|
||||||
},
|
},
|
||||||
form2: {
|
interval: 'interval', // interval cron
|
||||||
key: '',
|
cron: '',
|
||||||
secret: '',
|
intervalValue: 3,
|
||||||
},
|
agent_type: 'agent_id',
|
||||||
interval: 'interval', // interval cron
|
nodes: [
|
||||||
cron: '',
|
{
|
||||||
intervalValue: 3,
|
id: uuidv4(),
|
||||||
agent_type: 'agent_id',
|
ip: '',
|
||||||
nodes: [
|
community: '',
|
||||||
{
|
version: '',
|
||||||
id: uuidv4(),
|
},
|
||||||
ip: '',
|
],
|
||||||
community: '',
|
form3: this.$form.createForm(this, { name: 'snmp_form' }),
|
||||||
version: '',
|
alias: '',
|
||||||
},
|
}
|
||||||
],
|
},
|
||||||
form3: this.$form.createForm(this, { name: 'snmp_form' }),
|
computed: {
|
||||||
alias: '',
|
...mapState({
|
||||||
}
|
windowHeight: (state) => state.windowHeight,
|
||||||
},
|
userRoles: (state) => state.user.roles,
|
||||||
computed: {
|
}),
|
||||||
...mapState({
|
adrType() {
|
||||||
windowHeight: (state) => state.windowHeight,
|
return this.currentAdr.type
|
||||||
userRoles: (state) => state.user.roles,
|
},
|
||||||
}),
|
adrName() {
|
||||||
adrType() {
|
return this.currentAdr.name
|
||||||
return this.currentAdr.type
|
},
|
||||||
},
|
adrIsInner() {
|
||||||
adrName() {
|
return this.currentAdr.is_inner
|
||||||
return this.currentAdr.name
|
},
|
||||||
},
|
agentTypeRadioList() {
|
||||||
adrIsInner() {
|
const { permissions = [] } = this.userRoles
|
||||||
return this.currentAdr.is_inner
|
if ((permissions.includes('cmdb_admin') || permissions.includes('admin')) && this.adrType !== 'http') {
|
||||||
},
|
return [
|
||||||
agentTypeRadioList() {
|
{ value: 'all', label: this.$t('cmdb.ciType.allNodes') },
|
||||||
const { permissions = [] } = this.userRoles
|
{ value: 'agent_id', label: this.$t('cmdb.ciType.specifyNodes') },
|
||||||
if ((permissions.includes('cmdb_admin') || permissions.includes('admin')) && this.adrType !== 'http') {
|
{ value: 'query_expr', label: this.$t('cmdb.ciType.selectFromCMDBTips') },
|
||||||
return [
|
]
|
||||||
{ value: 'all', label: '所有节点' },
|
}
|
||||||
{ value: 'agent_id', label: '指定节点' },
|
return [
|
||||||
{ value: 'query_expr', label: '从CMDB中选择 ' },
|
{ value: 'agent_id', label: this.$t('cmdb.ciType.specifyNodes') },
|
||||||
]
|
{ value: 'query_expr', label: this.$t('cmdb.ciType.selectFromCMDBTips') },
|
||||||
}
|
]
|
||||||
return [
|
},
|
||||||
{ value: 'agent_id', label: '指定节点' },
|
radioList() {
|
||||||
{ value: 'query_expr', label: '从CMDB中选择 ' },
|
return [
|
||||||
]
|
{ value: 'interval', label: this.$t('cmdb.ciType.byInterval') },
|
||||||
},
|
// { value: 'cron', label: '按cron', layout: 'vertical' },
|
||||||
},
|
]
|
||||||
mounted() {},
|
},
|
||||||
methods: {
|
},
|
||||||
init() {
|
mounted() {},
|
||||||
const _find = this.adrList.find((item) => Number(item.id) === Number(this.adr_id))
|
methods: {
|
||||||
const _findADT = this.adCITypeList.find((item) => Number(item.id) === Number(this.currentAdt.id))
|
init() {
|
||||||
this.alias = _findADT?.extra_option?.alias ?? ''
|
const _find = this.adrList.find((item) => Number(item.id) === Number(this.adr_id))
|
||||||
if (this.adrType === 'http') {
|
const _findADT = this.adCITypeList.find((item) => Number(item.id) === Number(this.currentAdt.id))
|
||||||
const { category = undefined, key = '', secret = '' } = _findADT?.extra_option ?? {}
|
this.alias = _findADT?.extra_option?.alias ?? ''
|
||||||
this.form2 = {
|
if (this.adrType === 'http') {
|
||||||
key,
|
const { category = undefined, key = '', secret = '' } = _findADT?.extra_option ?? {}
|
||||||
secret,
|
this.form2 = {
|
||||||
}
|
key,
|
||||||
this.$refs.httpSnmpAd.setCurrentCate(category)
|
secret,
|
||||||
}
|
}
|
||||||
if (this.adrType === 'snmp') {
|
this.$refs.httpSnmpAd.setCurrentCate(category)
|
||||||
this.nodes = _findADT?.extra_option?.nodes ?? [
|
}
|
||||||
{
|
if (this.adrType === 'snmp') {
|
||||||
id: uuidv4(),
|
this.nodes = _findADT?.extra_option?.nodes ?? [
|
||||||
ip: '',
|
{
|
||||||
community: '',
|
id: uuidv4(),
|
||||||
version: '',
|
ip: '',
|
||||||
},
|
community: '',
|
||||||
]
|
version: '',
|
||||||
this.$nextTick(() => {
|
},
|
||||||
this.$refs.monitorNodeSetting.initNodesFunc()
|
]
|
||||||
this.$nextTick(() => {
|
this.$nextTick(() => {
|
||||||
this.$refs.monitorNodeSetting.setNodeField()
|
this.$refs.monitorNodeSetting.initNodesFunc()
|
||||||
})
|
this.$nextTick(() => {
|
||||||
})
|
this.$refs.monitorNodeSetting.setNodeField()
|
||||||
}
|
})
|
||||||
if (this.adrType === 'agent') {
|
})
|
||||||
this.tableData = (_find?.attributes || []).map((item) => {
|
}
|
||||||
if (_findADT.attributes) {
|
if (this.adrType === 'agent') {
|
||||||
return {
|
this.tableData = (_find?.attributes || []).map((item) => {
|
||||||
...item,
|
if (_findADT.attributes) {
|
||||||
attr: _findADT.attributes[`${item.name}`],
|
return {
|
||||||
}
|
...item,
|
||||||
} else {
|
attr: _findADT.attributes[`${item.name}`],
|
||||||
const _find = this.ciTypeAttributes.find((ele) => ele.name === item.name)
|
}
|
||||||
if (_find) {
|
} else {
|
||||||
return {
|
const _find = this.ciTypeAttributes.find((ele) => ele.name === item.name)
|
||||||
...item,
|
if (_find) {
|
||||||
attr: _find.name,
|
return {
|
||||||
}
|
...item,
|
||||||
}
|
attr: _find.name,
|
||||||
return item
|
}
|
||||||
}
|
}
|
||||||
})
|
return item
|
||||||
}
|
}
|
||||||
this.form = {
|
})
|
||||||
auto_accept: _findADT?.auto_accept || false,
|
}
|
||||||
agent_id: _findADT.agent_id || '',
|
this.form = {
|
||||||
query_expr: _findADT.query_expr || '',
|
auto_accept: _findADT?.auto_accept || false,
|
||||||
}
|
agent_id: _findADT.agent_id || '',
|
||||||
if (_findADT.query_expr) {
|
query_expr: _findADT.query_expr || '',
|
||||||
this.agent_type = 'query_expr'
|
}
|
||||||
} else if (_findADT.agent_id) {
|
if (_findADT.query_expr) {
|
||||||
this.agent_type = 'agent_id'
|
this.agent_type = 'query_expr'
|
||||||
} else {
|
} else if (_findADT.agent_id) {
|
||||||
this.agent_type = this.agentTypeRadioList[0].value
|
this.agent_type = 'agent_id'
|
||||||
}
|
} else {
|
||||||
if (_findADT.interval || (!_findADT.interval && !_findADT.cron)) {
|
this.agent_type = this.agentTypeRadioList[0].value
|
||||||
this.interval = 'interval'
|
}
|
||||||
this.intervalValue = _findADT.interval || ''
|
if (_findADT.interval || (!_findADT.interval && !_findADT.cron)) {
|
||||||
} else {
|
this.interval = 'interval'
|
||||||
this.interval = 'cron'
|
this.intervalValue = _findADT.interval || ''
|
||||||
this.cron = `0 ${_findADT.cron}`
|
} else {
|
||||||
}
|
this.interval = 'cron'
|
||||||
},
|
this.cron = `0 ${_findADT.cron}`
|
||||||
getAttrNameByAttrName(attrName) {
|
}
|
||||||
const _find = this.ciTypeAttributes.find((item) => item.name === attrName)
|
},
|
||||||
return _find?.alias || _find?.name || ''
|
getAttrNameByAttrName(attrName) {
|
||||||
},
|
const _find = this.ciTypeAttributes.find((item) => item.name === attrName)
|
||||||
crontabFill(cron) {
|
return _find?.alias || _find?.name || ''
|
||||||
this.cron = cron
|
},
|
||||||
},
|
crontabFill(cron) {
|
||||||
handleSave() {
|
this.cron = cron
|
||||||
const { currentAdt, alias } = this
|
},
|
||||||
let params
|
handleSave() {
|
||||||
if (this.adrType === 'http') {
|
const { currentAdt, alias } = this
|
||||||
params = {
|
let params
|
||||||
extra_option: {
|
if (this.adrType === 'http') {
|
||||||
...this.form2,
|
params = {
|
||||||
category: this.$refs.httpSnmpAd.currentCate,
|
extra_option: {
|
||||||
},
|
...this.form2,
|
||||||
}
|
category: this.$refs.httpSnmpAd.currentCate,
|
||||||
}
|
},
|
||||||
if (this.adrType === 'snmp') {
|
}
|
||||||
params = {
|
}
|
||||||
extra_option: { nodes: this.$refs.monitorNodeSetting?.getNodeValue() ?? [] },
|
if (this.adrType === 'snmp') {
|
||||||
}
|
params = {
|
||||||
}
|
extra_option: { nodes: this.$refs.monitorNodeSetting?.getNodeValue() ?? [] },
|
||||||
if (this.adrType === 'agent') {
|
}
|
||||||
const $table = this.$refs.xTable
|
}
|
||||||
const { fullData: _tableData } = $table.getTableData()
|
if (this.adrType === 'agent') {
|
||||||
const attributes = {}
|
const $table = this.$refs.xTable
|
||||||
_tableData.forEach((td) => {
|
const { fullData: _tableData } = $table.getTableData()
|
||||||
if (td.attr) {
|
const attributes = {}
|
||||||
attributes[`${td.name}`] = td.attr
|
_tableData.forEach((td) => {
|
||||||
}
|
if (td.attr) {
|
||||||
})
|
attributes[`${td.name}`] = td.attr
|
||||||
params = {
|
}
|
||||||
...params,
|
})
|
||||||
attributes,
|
params = {
|
||||||
}
|
...params,
|
||||||
} else {
|
attributes,
|
||||||
const _tableData = this.$refs.httpSnmpAd.getTableData()
|
}
|
||||||
const attributes = {}
|
} else {
|
||||||
_tableData.forEach((td) => {
|
const _tableData = this.$refs.httpSnmpAd.getTableData()
|
||||||
if (td.attr) {
|
const attributes = {}
|
||||||
attributes[`${td.name}`] = td.attr
|
_tableData.forEach((td) => {
|
||||||
}
|
if (td.attr) {
|
||||||
})
|
attributes[`${td.name}`] = td.attr
|
||||||
params = {
|
}
|
||||||
...params,
|
})
|
||||||
attributes,
|
params = {
|
||||||
}
|
...params,
|
||||||
}
|
attributes,
|
||||||
if (this.interval === 'cron') {
|
}
|
||||||
this.$refs.cronTab.submitFill()
|
}
|
||||||
}
|
if (this.interval === 'cron') {
|
||||||
params = {
|
this.$refs.cronTab.submitFill()
|
||||||
...params,
|
}
|
||||||
...this.form,
|
params = {
|
||||||
type_id: this.CITypeId,
|
...params,
|
||||||
adr_id: currentAdt.adr_id,
|
...this.form,
|
||||||
interval: this.interval === 'interval' ? this.intervalValue : null,
|
type_id: this.CITypeId,
|
||||||
cron: this.interval === 'cron' ? this.cron : null,
|
adr_id: currentAdt.adr_id,
|
||||||
}
|
interval: this.interval === 'interval' ? this.intervalValue : null,
|
||||||
if (this.agent_type === 'agent_id' || this.agent_type === 'all') {
|
cron: this.interval === 'cron' ? this.cron : null,
|
||||||
params.query_expr = ''
|
}
|
||||||
if (this.agent_type === 'agent_id' && !params.agent_id) {
|
if (this.agent_type === 'agent_id' || this.agent_type === 'all') {
|
||||||
this.$message.error('请填写指定节点!')
|
params.query_expr = ''
|
||||||
return
|
if (this.agent_type === 'agent_id' && !params.agent_id) {
|
||||||
}
|
this.$message.error(this.$t('cmdb.ciType.specifyNodesTips'))
|
||||||
}
|
return
|
||||||
if (this.agent_type === 'query_expr' || this.agent_type === 'all') {
|
}
|
||||||
params.agent_id = ''
|
}
|
||||||
if (this.agent_type === 'query_expr' && !params.query_expr) {
|
if (this.agent_type === 'query_expr' || this.agent_type === 'all') {
|
||||||
this.$message.error('请从cmdb中选择!')
|
params.agent_id = ''
|
||||||
return
|
if (this.agent_type === 'query_expr' && !params.query_expr) {
|
||||||
}
|
this.$message.error(this.$t('cmdb.ciType.selectFromCMDBTips'))
|
||||||
}
|
return
|
||||||
if (params.extra_option) {
|
}
|
||||||
params.extra_option.alias = alias
|
}
|
||||||
} else {
|
if (params.extra_option) {
|
||||||
params.extra_option = {}
|
params.extra_option.alias = alias
|
||||||
params.extra_option.alias = alias
|
} else {
|
||||||
}
|
params.extra_option = {}
|
||||||
putCITypeDiscovery(currentAdt.id, params).then((res) => {
|
params.extra_option.alias = alias
|
||||||
this.$message.success('保存成功')
|
}
|
||||||
this.$emit('handleSave')
|
putCITypeDiscovery(currentAdt.id, params).then((res) => {
|
||||||
})
|
this.$message.success(this.$t('saveSuccess'))
|
||||||
},
|
this.$emit('handleSave')
|
||||||
handleOpenCmdb() {
|
})
|
||||||
this.$refs.cmdbDrawer.open()
|
},
|
||||||
},
|
handleOpenCmdb() {
|
||||||
copySuccess(text) {
|
this.$refs.cmdbDrawer.open()
|
||||||
this.form = {
|
},
|
||||||
...this.form,
|
copySuccess(text) {
|
||||||
query_expr: `${text}`,
|
this.form = {
|
||||||
}
|
...this.form,
|
||||||
},
|
query_expr: `${text}`,
|
||||||
},
|
}
|
||||||
}
|
},
|
||||||
</script>
|
},
|
||||||
|
}
|
||||||
<style lang="less">
|
</script>
|
||||||
.attr-ad-snmp-form {
|
|
||||||
.ant-form-item {
|
<style lang="less">
|
||||||
margin-bottom: 0;
|
.attr-ad-snmp-form {
|
||||||
}
|
.ant-form-item {
|
||||||
}
|
margin-bottom: 0;
|
||||||
</style>
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
|
@ -1,278 +1,282 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="attribute-card">
|
<div class="attribute-card">
|
||||||
<div class="attribute-card-content">
|
<div class="attribute-card-content">
|
||||||
<div class="attribute-card-value-type-icon handle" :style="{ ...getPropertyStyle(property) }">
|
<div class="attribute-card-value-type-icon handle" :style="{ ...getPropertyStyle(property) }">
|
||||||
<ValueTypeIcon :attr="property" />
|
<ValueTypeIcon :attr="property" />
|
||||||
</div>
|
</div>
|
||||||
<div :class="{ 'attribute-card-content-inner': true, 'attribute-card-name-required': property.is_required }">
|
<div :class="{ 'attribute-card-content-inner': true, 'attribute-card-name-required': property.is_required }">
|
||||||
<div :class="{ 'attribute-card-name': true, 'attribute-card-name-default-show': property.default_show }">
|
<div :class="{ 'attribute-card-name': true, 'attribute-card-name-default-show': property.default_show }">
|
||||||
{{ property.alias || property.name }}
|
{{ property.alias || property.name }}
|
||||||
</div>
|
</div>
|
||||||
<div v-if="property.is_password" class="attribute-card_value-type">密码</div>
|
<div v-if="property.is_password" class="attribute-card_value-type">{{ $t('cmdb.ciType.password') }}</div>
|
||||||
<div v-else-if="property.is_link" class="attribute-card_value-type">链接</div>
|
<div v-else-if="property.is_link" class="attribute-card_value-type">{{ $t('cmdb.ciType.link') }}</div>
|
||||||
<div v-else class="attribute-card_value-type">{{ valueTypeMap[property.value_type] }}</div>
|
<div v-else class="attribute-card_value-type">{{ valueTypeMap[property.value_type] }}</div>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
class="attribute-card-trigger"
|
class="attribute-card-trigger"
|
||||||
v-if="(property.value_type === '3' || property.value_type === '4') && !isStore"
|
v-if="(property.value_type === '3' || property.value_type === '4') && !isStore"
|
||||||
>
|
>
|
||||||
<a @click="openTrigger"><ops-icon type="ops-trigger"/></a>
|
<a @click="openTrigger"><ops-icon type="ops-trigger"/></a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="attribute-card-footer">
|
<div class="attribute-card-footer">
|
||||||
<a-popover
|
<a-popover
|
||||||
trigger="click"
|
trigger="click"
|
||||||
:arrowPointAtCenter="true"
|
:arrowPointAtCenter="true"
|
||||||
placement="bottom"
|
placement="bottom"
|
||||||
overlayClassName="attribute-card-footer-popover"
|
overlayClassName="attribute-card-footer-popover"
|
||||||
>
|
>
|
||||||
<div slot="content">
|
<div slot="content">
|
||||||
<h3 :style="{ textAlign: 'center', paddingTop: '0.5em' }">
|
<h3 :style="{ textAlign: 'center', paddingTop: '0.5em' }">
|
||||||
<span>{{ property.alias }}({{ property.name }})</span>
|
<span>{{ property.alias }}({{ property.name }})</span>
|
||||||
</h3>
|
</h3>
|
||||||
<a-descriptions layout="horizontal" bordered size="small" :column="2">
|
<a-descriptions layout="horizontal" bordered size="small" :column="2">
|
||||||
<a-descriptions-item v-for="item in propertyList" :key="item.property" :label="item.label">
|
<a-descriptions-item v-for="item in propertyList" :key="item.property" :label="item.label">
|
||||||
<components
|
<components
|
||||||
:is="`ops_${item.property}`"
|
:is="`ops_${item.property}`"
|
||||||
v-if="property[item.property]"
|
v-if="property[item.property]"
|
||||||
:style="{ width: '1em', height: '1em' }"
|
:style="{ width: '1em', height: '1em' }"
|
||||||
/>
|
/>
|
||||||
<ops-icon v-else :type="`ops-${item.property}-disabled`" />
|
<ops-icon v-else :type="`ops-${item.property}-disabled`" />
|
||||||
</a-descriptions-item>
|
</a-descriptions-item>
|
||||||
<a-descriptions-item label></a-descriptions-item>
|
<a-descriptions-item label></a-descriptions-item>
|
||||||
</a-descriptions>
|
</a-descriptions>
|
||||||
</div>
|
</div>
|
||||||
<a-space :style="{ cursor: 'pointer' }">
|
<a-space :style="{ cursor: 'pointer' }">
|
||||||
<components
|
<components
|
||||||
v-for="item in propertyList.filter((p) => property[p.property])"
|
v-for="item in propertyList.filter((p) => property[p.property])"
|
||||||
:key="item.property"
|
:key="item.property"
|
||||||
:is="`ops_${item.property}`"
|
:is="`ops_${item.property}`"
|
||||||
/>
|
/>
|
||||||
</a-space>
|
</a-space>
|
||||||
</a-popover>
|
</a-popover>
|
||||||
|
|
||||||
<a-space class="attribute-card-operation">
|
<a-space class="attribute-card-operation">
|
||||||
<a v-if="!isStore"><a-icon type="edit" @click="handleEdit"/></a>
|
<a v-if="!isStore"><a-icon type="edit" @click="handleEdit"/></a>
|
||||||
<a-tooltip title="所有CI触发计算">
|
<a-tooltip :title="$t('cmdb.ciType.computeForAllCITips')">
|
||||||
<a v-if="!isStore && property.is_computed"><a-icon type="redo" @click="handleCalcComputed"/></a>
|
<a v-if="!isStore && property.is_computed"><a-icon type="redo" @click="handleCalcComputed"/></a>
|
||||||
</a-tooltip>
|
</a-tooltip>
|
||||||
<a style="color:red;"><a-icon type="delete" @click="handleDelete"/></a>
|
<a style="color:red;"><a-icon type="delete" @click="handleDelete"/></a>
|
||||||
</a-space>
|
</a-space>
|
||||||
</div>
|
</div>
|
||||||
<TriggerForm ref="triggerForm" :CITypeId="CITypeId" />
|
<TriggerForm ref="triggerForm" :CITypeId="CITypeId" />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { deleteCITypeAttributesById, deleteAttributesById, calcComputedAttribute } from '@/modules/cmdb/api/CITypeAttr'
|
import { deleteCITypeAttributesById, deleteAttributesById, calcComputedAttribute } from '@/modules/cmdb/api/CITypeAttr'
|
||||||
import ValueTypeIcon from '@/components/CMDBValueTypeMapIcon'
|
import ValueTypeIcon from '@/components/CMDBValueTypeMapIcon'
|
||||||
import {
|
import {
|
||||||
ops_default_show,
|
ops_default_show,
|
||||||
ops_is_choice,
|
ops_is_choice,
|
||||||
ops_is_index,
|
ops_is_index,
|
||||||
ops_is_link,
|
ops_is_link,
|
||||||
ops_is_password,
|
ops_is_password,
|
||||||
ops_is_sortable,
|
ops_is_sortable,
|
||||||
ops_is_unique,
|
ops_is_unique,
|
||||||
} from '@/core/icons'
|
} from '@/core/icons'
|
||||||
import { valueTypeMap } from '../../utils/const'
|
import { valueTypeMap } from '../../utils/const'
|
||||||
import { getPropertyStyle } from '../../utils/helper'
|
import { getPropertyStyle } from '../../utils/helper'
|
||||||
import TriggerForm from './triggerForm.vue'
|
import TriggerForm from './triggerForm.vue'
|
||||||
export default {
|
export default {
|
||||||
name: 'AttributeCard',
|
name: 'AttributeCard',
|
||||||
components: {
|
components: {
|
||||||
ValueTypeIcon,
|
ValueTypeIcon,
|
||||||
TriggerForm,
|
TriggerForm,
|
||||||
ops_default_show,
|
ops_default_show,
|
||||||
ops_is_choice,
|
ops_is_choice,
|
||||||
ops_is_index,
|
ops_is_index,
|
||||||
ops_is_link,
|
ops_is_link,
|
||||||
ops_is_password,
|
ops_is_password,
|
||||||
ops_is_sortable,
|
ops_is_sortable,
|
||||||
ops_is_unique,
|
ops_is_unique,
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
property: {
|
property: {
|
||||||
type: Object,
|
type: Object,
|
||||||
default: () => {},
|
default: () => {},
|
||||||
},
|
},
|
||||||
CITypeId: {
|
CITypeId: {
|
||||||
type: Number,
|
type: Number,
|
||||||
default: null,
|
default: null,
|
||||||
},
|
},
|
||||||
isStore: {
|
isStore: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: false,
|
default: false,
|
||||||
},
|
},
|
||||||
attributes: {
|
attributes: {
|
||||||
type: Array,
|
type: Array,
|
||||||
default: () => []
|
default: () => [],
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
const propertyList = [
|
return {}
|
||||||
{
|
},
|
||||||
label: '是否唯一',
|
computed: {
|
||||||
property: 'is_unique',
|
valueTypeMap() {
|
||||||
},
|
return valueTypeMap()
|
||||||
{
|
},
|
||||||
label: '是否选择',
|
propertyList() {
|
||||||
property: 'is_choice',
|
return [
|
||||||
},
|
{
|
||||||
{
|
label: this.$t('cmdb.ciType.isUnique'),
|
||||||
label: '默认显示',
|
property: 'is_unique',
|
||||||
property: 'default_show',
|
},
|
||||||
},
|
{
|
||||||
{
|
label: this.$t('cmdb.ciType.isChoice'),
|
||||||
label: '可排序',
|
property: 'is_choice',
|
||||||
property: 'is_sortable',
|
},
|
||||||
},
|
{
|
||||||
{
|
label: this.$t('cmdb.ciType.defaultShow'),
|
||||||
label: '是否索引',
|
property: 'default_show',
|
||||||
property: 'is_index',
|
},
|
||||||
},
|
{
|
||||||
]
|
label: this.$t('cmdb.ciType.isSortable'),
|
||||||
return {
|
property: 'is_sortable',
|
||||||
valueTypeMap,
|
},
|
||||||
propertyList,
|
{
|
||||||
}
|
label: this.$t('cmdb.ciType.isIndex'),
|
||||||
},
|
property: 'is_index',
|
||||||
methods: {
|
},
|
||||||
getPropertyStyle,
|
]
|
||||||
handleEdit() {
|
},
|
||||||
this.$emit('edit')
|
},
|
||||||
},
|
methods: {
|
||||||
handleDelete() {
|
getPropertyStyle,
|
||||||
const that = this
|
handleEdit() {
|
||||||
this.$confirm({
|
this.$emit('edit')
|
||||||
title: '警告',
|
},
|
||||||
content: `确认删除 【${that.property.alias || that.property.name}】?`,
|
handleDelete() {
|
||||||
onOk() {
|
const that = this
|
||||||
if (that.isStore) {
|
this.$confirm({
|
||||||
deleteAttributesById(that.property.id).then(() => {
|
title: that.$t('warning'),
|
||||||
that.$message.success('删除成功!')
|
content: that.$t('cmdb.ciType.confirmDelete', { name: `${that.property.alias || that.property.name}` }),
|
||||||
that.$emit('ok')
|
onOk() {
|
||||||
})
|
if (that.isStore) {
|
||||||
} else {
|
deleteAttributesById(that.property.id).then(() => {
|
||||||
deleteCITypeAttributesById(that.CITypeId, { attr_id: [that.property.id] }).then(() => {
|
that.$message.success(that.$t('deleteSuccess'))
|
||||||
that.$message.success('删除成功!')
|
that.$emit('ok')
|
||||||
that.$emit('ok')
|
})
|
||||||
})
|
} else {
|
||||||
}
|
deleteCITypeAttributesById(that.CITypeId, { attr_id: [that.property.id] }).then(() => {
|
||||||
},
|
that.$message.success(that.$t('deleteSuccess'))
|
||||||
onCancel() {},
|
that.$emit('ok')
|
||||||
})
|
})
|
||||||
},
|
}
|
||||||
openTrigger() {
|
},
|
||||||
this.$refs.triggerForm.open(this.property, this.attributes)
|
onCancel() {},
|
||||||
},
|
})
|
||||||
handleCalcComputed() {
|
},
|
||||||
const that = this
|
openTrigger() {
|
||||||
this.$confirm({
|
this.$refs.triggerForm.open(this.property, this.attributes)
|
||||||
title: '警告',
|
},
|
||||||
content: `确认触发所有CI的计算?`,
|
handleCalcComputed() {
|
||||||
onOk() {
|
const that = this
|
||||||
calcComputedAttribute(that.property.id).then(() => {
|
this.$confirm({
|
||||||
that.$message.success('触发成功!')
|
title: that.$t('warning'),
|
||||||
})
|
content: that.$t('cmdb.ciType.confirmcomputeForAllCITips'),
|
||||||
},
|
onOk() {
|
||||||
})
|
calcComputedAttribute(that.property.id).then(() => {
|
||||||
},
|
that.$message.success(that.$t('cmdb.ciType.computeSuccess'))
|
||||||
},
|
})
|
||||||
}
|
},
|
||||||
</script>
|
})
|
||||||
|
},
|
||||||
<style lang="less" scoped>
|
},
|
||||||
.attribute-card {
|
}
|
||||||
width: 182px;
|
</script>
|
||||||
height: 80px;
|
|
||||||
background: #f8faff;
|
<style lang="less" scoped>
|
||||||
border-radius: 5px;
|
.attribute-card {
|
||||||
position: relative;
|
width: 182px;
|
||||||
margin-bottom: 16px;
|
height: 80px;
|
||||||
transition: all 0.3s;
|
background: #f8faff;
|
||||||
&:hover {
|
border-radius: 5px;
|
||||||
box-shadow: 0 4px 12px #4e5ea066;
|
position: relative;
|
||||||
.attribute-card-operation {
|
margin-bottom: 16px;
|
||||||
visibility: visible !important;
|
transition: all 0.3s;
|
||||||
}
|
&:hover {
|
||||||
}
|
box-shadow: 0 4px 12px #4e5ea066;
|
||||||
.attribute-card-content {
|
.attribute-card-operation {
|
||||||
height: 50px;
|
visibility: visible !important;
|
||||||
display: inline-flex;
|
}
|
||||||
align-items: center;
|
}
|
||||||
padding: 8px;
|
.attribute-card-content {
|
||||||
width: 100%;
|
height: 50px;
|
||||||
.attribute-card-value-type-icon {
|
display: inline-flex;
|
||||||
width: 32px;
|
align-items: center;
|
||||||
height: 32px;
|
padding: 8px;
|
||||||
font-size: 12px;
|
width: 100%;
|
||||||
cursor: move;
|
.attribute-card-value-type-icon {
|
||||||
background: #ffffff !important;
|
width: 32px;
|
||||||
box-shadow: 0px 1px 2px rgba(47, 84, 235, 0.2);
|
height: 32px;
|
||||||
border-radius: 2px;
|
font-size: 12px;
|
||||||
text-align: center;
|
cursor: move;
|
||||||
line-height: 32px;
|
background: #ffffff !important;
|
||||||
}
|
box-shadow: 0px 1px 2px rgba(47, 84, 235, 0.2);
|
||||||
.attribute-card-content-inner {
|
border-radius: 2px;
|
||||||
padding-left: 12px;
|
text-align: center;
|
||||||
font-weight: 400;
|
line-height: 32px;
|
||||||
font-size: 12px;
|
}
|
||||||
width: 120px;
|
.attribute-card-content-inner {
|
||||||
position: relative;
|
padding-left: 12px;
|
||||||
.attribute-card-name {
|
font-weight: 400;
|
||||||
width: 100%;
|
font-size: 12px;
|
||||||
color: rgba(0, 0, 0, 0.8);
|
width: 120px;
|
||||||
overflow: hidden;
|
position: relative;
|
||||||
text-overflow: ellipsis;
|
.attribute-card-name {
|
||||||
white-space: nowrap;
|
width: 100%;
|
||||||
}
|
color: rgba(0, 0, 0, 0.8);
|
||||||
.attribute-card-name-default-show {
|
overflow: hidden;
|
||||||
color: #2f54eb;
|
text-overflow: ellipsis;
|
||||||
}
|
white-space: nowrap;
|
||||||
.attribute-card_value-type {
|
}
|
||||||
font-size: 10px;
|
.attribute-card-name-default-show {
|
||||||
color: rgba(0, 0, 0, 0.35);
|
color: #2f54eb;
|
||||||
}
|
}
|
||||||
}
|
.attribute-card_value-type {
|
||||||
.attribute-card-name-required::before {
|
font-size: 10px;
|
||||||
content: '*';
|
color: rgba(0, 0, 0, 0.35);
|
||||||
width: 5px;
|
}
|
||||||
color: red;
|
}
|
||||||
position: absolute;
|
.attribute-card-name-required::before {
|
||||||
left: 3px;
|
content: '*';
|
||||||
}
|
width: 5px;
|
||||||
.attribute-card-trigger {
|
color: red;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
right: 8px;
|
left: 3px;
|
||||||
top: 8px;
|
}
|
||||||
}
|
.attribute-card-trigger {
|
||||||
}
|
position: absolute;
|
||||||
.attribute-card-footer {
|
right: 8px;
|
||||||
width: 182px;
|
top: 8px;
|
||||||
height: 30px;
|
}
|
||||||
padding: 0 8px;
|
}
|
||||||
position: absolute;
|
.attribute-card-footer {
|
||||||
bottom: 0;
|
width: 182px;
|
||||||
left: 0;
|
height: 30px;
|
||||||
background: linear-gradient(180deg, #96abd6 0%, #ecf2ff 0.01%, #ffffff 143.33%);
|
padding: 0 8px;
|
||||||
border-radius: 0px 0px 5px 5px;
|
position: absolute;
|
||||||
display: inline-flex;
|
bottom: 0;
|
||||||
align-items: center;
|
left: 0;
|
||||||
justify-content: space-between;
|
background: linear-gradient(180deg, #96abd6 0%, #ecf2ff 0.01%, #ffffff 143.33%);
|
||||||
.attribute-card-operation {
|
border-radius: 0px 0px 5px 5px;
|
||||||
visibility: hidden;
|
display: inline-flex;
|
||||||
}
|
align-items: center;
|
||||||
}
|
justify-content: space-between;
|
||||||
}
|
.attribute-card-operation {
|
||||||
</style>
|
visibility: hidden;
|
||||||
<style lang="less">
|
}
|
||||||
.attribute-card-footer-popover {
|
}
|
||||||
.ant-popover-inner-content {
|
}
|
||||||
padding: 0;
|
</style>
|
||||||
}
|
<style lang="less">
|
||||||
.ant-descriptions-bordered .ant-descriptions-item-label {
|
.attribute-card-footer-popover {
|
||||||
background-color: #f8faff;
|
.ant-popover-inner-content {
|
||||||
}
|
padding: 0;
|
||||||
}
|
}
|
||||||
</style>
|
.ant-descriptions-bordered .ant-descriptions-item-label {
|
||||||
|
background-color: #f8faff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -2,15 +2,15 @@
|
||||||
<a-modal wrapClassName="attrbute-store-wrapper" width="80%" :visible="visible" @cancel="handleCancel">
|
<a-modal wrapClassName="attrbute-store-wrapper" width="80%" :visible="visible" @cancel="handleCancel">
|
||||||
<template slot="title">
|
<template slot="title">
|
||||||
<div class="attrbute-store-header">
|
<div class="attrbute-store-header">
|
||||||
<span>属性库</span>
|
<span>{{ $t('cmdb.ciType.attributeLibray') }}</span>
|
||||||
<div class="attrbute-store-search">
|
<div class="attrbute-store-search">
|
||||||
<a-input-group compact>
|
<a-input-group compact>
|
||||||
<a-select class="attrbute-store-search-select" v-model="searchKey">
|
<a-select class="attrbute-store-search-select" v-model="searchKey">
|
||||||
<a-select-option value="alias">
|
<a-select-option value="alias">
|
||||||
别名
|
{{ $t('alias') }}
|
||||||
</a-select-option>
|
</a-select-option>
|
||||||
<a-select-option value="name">
|
<a-select-option value="name">
|
||||||
名称
|
{{ $t('name') }}
|
||||||
</a-select-option>
|
</a-select-option>
|
||||||
</a-select>
|
</a-select>
|
||||||
<a-input
|
<a-input
|
||||||
|
@ -53,7 +53,7 @@
|
||||||
</a-row>
|
</a-row>
|
||||||
<a-empty v-else>
|
<a-empty v-else>
|
||||||
<img slot="image" :src="require('@/assets/data_empty.png')" />
|
<img slot="image" :src="require('@/assets/data_empty.png')" />
|
||||||
<span slot="description"> 暂无数据 </span>
|
<span slot="description"> {{ $t('noData') }} </span>
|
||||||
</a-empty>
|
</a-empty>
|
||||||
</a-spin>
|
</a-spin>
|
||||||
<template slot="footer">
|
<template slot="footer">
|
||||||
|
@ -63,7 +63,7 @@
|
||||||
show-quick-jumper
|
show-quick-jumper
|
||||||
:current="tablePage.currentPage"
|
:current="tablePage.currentPage"
|
||||||
:total="tablePage.totalResult"
|
:total="tablePage.totalResult"
|
||||||
:show-total="(total, range) => `当前展示 ${range[0]}-${range[1]} 条数据, 共 ${total} 条`"
|
:show-total="(total, range) => $t('pagination.total', { total: total, range0: range[0], range1: range[1] })"
|
||||||
:page-size="tablePage.pageSize"
|
:page-size="tablePage.pageSize"
|
||||||
:default-current="1"
|
:default-current="1"
|
||||||
@change="pageOrSizeChange"
|
@change="pageOrSizeChange"
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -1,22 +1,22 @@
|
||||||
<template>
|
<template>
|
||||||
<a-card :bordered="false" :bodyStyle="{ padding: '0' }">
|
<a-card :bordered="false" :bodyStyle="{ padding: '0' }">
|
||||||
<a-tabs :activeKey="activeKey" @change="changeTab" class="ops-tab" type="card">
|
<a-tabs :activeKey="activeKey" @change="changeTab" class="ops-tab" type="card">
|
||||||
<a-tab-pane key="1" tab="模型属性">
|
<a-tab-pane key="1" :tab="$t('cmdb.ciType.attributes')">
|
||||||
<AttributesTable ref="attributesTable" :CITypeId="CITypeId" :CITypeName="CITypeName"></AttributesTable>
|
<AttributesTable ref="attributesTable" :CITypeId="CITypeId" :CITypeName="CITypeName"></AttributesTable>
|
||||||
</a-tab-pane>
|
</a-tab-pane>
|
||||||
<a-tab-pane forceRender key="2" tab="模型关联">
|
<a-tab-pane forceRender key="2" :tab="$t('cmdb.ciType.relation')">
|
||||||
<RelationTable :CITypeId="CITypeId" :CITypeName="CITypeName"></RelationTable>
|
<RelationTable :CITypeId="CITypeId" :CITypeName="CITypeName"></RelationTable>
|
||||||
</a-tab-pane>
|
</a-tab-pane>
|
||||||
<a-tab-pane key="3" tab="触发器">
|
<a-tab-pane key="3" :tab="$t('cmdb.ciType.trigger')">
|
||||||
<TriggerTable ref="triggerTable" :CITypeId="CITypeId"></TriggerTable>
|
<TriggerTable ref="triggerTable" :CITypeId="CITypeId"></TriggerTable>
|
||||||
</a-tab-pane>
|
</a-tab-pane>
|
||||||
<a-tab-pane key="4" tab="属性自动发现">
|
<a-tab-pane key="4" :tab="$t('cmdb.ciType.attributeAD')">
|
||||||
<AttrAD :CITypeId="CITypeId"></AttrAD>
|
<AttrAD :CITypeId="CITypeId"></AttrAD>
|
||||||
</a-tab-pane>
|
</a-tab-pane>
|
||||||
<a-tab-pane key="5" tab="关系自动发现">
|
<a-tab-pane key="5" :tab="$t('cmdb.ciType.relationAD')">
|
||||||
<RelationAD :CITypeId="CITypeId"></RelationAD>
|
<RelationAD :CITypeId="CITypeId"></RelationAD>
|
||||||
</a-tab-pane>
|
</a-tab-pane>
|
||||||
<a-tab-pane key="6" tab="权限设置">
|
<a-tab-pane key="6" :tab="$t('cmdb.ciType.grant')">
|
||||||
<GrantComp :CITypeId="CITypeId" resourceType="CIType" :resourceTypeName="CITypeName"></GrantComp>
|
<GrantComp :CITypeId="CITypeId" resourceType="CIType" :resourceTypeName="CITypeName"></GrantComp>
|
||||||
</a-tab-pane>
|
</a-tab-pane>
|
||||||
</a-tabs>
|
</a-tabs>
|
||||||
|
|
|
@ -1,90 +1,90 @@
|
||||||
<template>
|
<template>
|
||||||
<a-tabs v-model="activeKey" size="small" :tabBarStyle="{ borderBottom: 'none' }">
|
<a-tabs v-model="activeKey" size="small" :tabBarStyle="{ borderBottom: 'none' }">
|
||||||
<a-tab-pane key="expr" :disabled="!canDefineComputed">
|
<a-tab-pane key="expr" :disabled="!canDefineComputed">
|
||||||
<span style="font-size:12px;" slot="tab">表达式</span>
|
<span style="font-size:12px;" slot="tab">{{ $t('cmdb.ciType.expr') }}</span>
|
||||||
<a-textarea v-model="compute_expr" :placeholder="`{{a}}+{{b}}`" :rows="2" :disabled="!canDefineComputed" />
|
<a-textarea v-model="compute_expr" :placeholder="`{{a}}+{{b}}`" :rows="2" :disabled="!canDefineComputed" />
|
||||||
</a-tab-pane>
|
</a-tab-pane>
|
||||||
<a-tab-pane key="script" :disabled="!canDefineComputed">
|
<a-tab-pane key="script" :disabled="!canDefineComputed">
|
||||||
<span style="font-size:12px;" slot="tab">代码</span>
|
<span style="font-size:12px;" slot="tab">{{ $t('cmdb.ciType.code') }}</span>
|
||||||
<codemirror style="z-index: 9999" :options="cmOptions" v-model="compute_script"></codemirror>
|
<codemirror style="z-index: 9999" :options="cmOptions" v-model="compute_script"></codemirror>
|
||||||
</a-tab-pane>
|
</a-tab-pane>
|
||||||
<template slot="tabBarExtraContent" v-if="showCalcComputed">
|
<template slot="tabBarExtraContent" v-if="showCalcComputed">
|
||||||
<a-button type="primary" size="small" @click="handleCalcComputed">
|
<a-button type="primary" size="small" @click="handleCalcComputed">
|
||||||
应用
|
{{ $t('cmdb.ciType.apply') }}
|
||||||
</a-button>
|
</a-button>
|
||||||
<a-tooltip title="所有CI触发计算">
|
<a-tooltip :title="$t('cmdb.ciType.computeForAllCITips')">
|
||||||
<a-icon type="question-circle" style="margin-left:5px" />
|
<a-icon type="question-circle" style="margin-left:5px" />
|
||||||
</a-tooltip>
|
</a-tooltip>
|
||||||
</template>
|
</template>
|
||||||
</a-tabs>
|
</a-tabs>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { codemirror } from 'vue-codemirror'
|
import { codemirror } from 'vue-codemirror'
|
||||||
import 'codemirror/lib/codemirror.css'
|
import 'codemirror/lib/codemirror.css'
|
||||||
import 'codemirror/theme/monokai.css'
|
import 'codemirror/theme/monokai.css'
|
||||||
|
|
||||||
require('codemirror/mode/python/python.js')
|
require('codemirror/mode/python/python.js')
|
||||||
export default {
|
export default {
|
||||||
name: 'ComputedArea',
|
name: 'ComputedArea',
|
||||||
components: { codemirror },
|
components: { codemirror },
|
||||||
props: {
|
props: {
|
||||||
canDefineComputed: {
|
canDefineComputed: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: true,
|
default: true,
|
||||||
},
|
},
|
||||||
showCalcComputed: {
|
showCalcComputed: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: false,
|
default: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
activeKey: 'expr', // expr script
|
activeKey: 'expr', // expr script
|
||||||
compute_expr: '',
|
compute_expr: '',
|
||||||
compute_script: 'def computed(): \n return',
|
compute_script: 'def computed(): \n return',
|
||||||
cmOptions: {
|
cmOptions: {
|
||||||
lineNumbers: true,
|
lineNumbers: true,
|
||||||
mode: 'python',
|
mode: 'python',
|
||||||
height: '200px',
|
height: '200px',
|
||||||
theme: 'monokai',
|
theme: 'monokai',
|
||||||
tabSize: 4,
|
tabSize: 4,
|
||||||
lineWrapping: true,
|
lineWrapping: true,
|
||||||
readOnly: !this.canDefineComputed,
|
readOnly: !this.canDefineComputed,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
getData() {
|
getData() {
|
||||||
const { activeKey, compute_expr, compute_script } = this
|
const { activeKey, compute_expr, compute_script } = this
|
||||||
if (activeKey === 'expr') {
|
if (activeKey === 'expr') {
|
||||||
return { compute_expr, compute_script: null }
|
return { compute_expr, compute_script: null }
|
||||||
} else if (activeKey === 'script') {
|
} else if (activeKey === 'script') {
|
||||||
return { compute_script, compute_expr: null }
|
return { compute_script, compute_expr: null }
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
setData(data) {
|
setData(data) {
|
||||||
const { compute_expr, compute_script } = data
|
const { compute_expr, compute_script } = data
|
||||||
this.compute_expr = compute_expr
|
this.compute_expr = compute_expr
|
||||||
this.compute_script = compute_script || 'def computed(): \n return'
|
this.compute_script = compute_script || 'def computed(): \n return'
|
||||||
if (compute_script) {
|
if (compute_script) {
|
||||||
this.activeKey = 'script'
|
this.activeKey = 'script'
|
||||||
} else {
|
} else {
|
||||||
this.activeKey = 'expr'
|
this.activeKey = 'expr'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
handleCalcComputed() {
|
handleCalcComputed() {
|
||||||
const that = this
|
const that = this
|
||||||
this.$confirm({
|
this.$confirm({
|
||||||
title: '警告',
|
title: this.$t('warning'),
|
||||||
content: `确认触发将保存当前配置及触发所有CI的计算?`,
|
content: this.$t('cmdb.ciType.confirmcomputeForAllCITips'),
|
||||||
onOk() {
|
onOk() {
|
||||||
that.$emit('handleCalcComputed')
|
that.$emit('handleCalcComputed')
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style></style>
|
<style></style>
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -18,18 +18,18 @@
|
||||||
visible = false
|
visible = false
|
||||||
}
|
}
|
||||||
"
|
"
|
||||||
>取消</a-button
|
>{{ $t('cancel') }}</a-button
|
||||||
>
|
>
|
||||||
<a-button :loading="confirmLoading" @click="handleSubmit(false)" type="primary">继续添加</a-button>
|
<a-button :loading="confirmLoading" @click="handleSubmit(false)" type="primary">{{ $t('cmdb.ciType.continueAdd') }}</a-button>
|
||||||
<a-button :loading="confirmLoading" type="primary" @click="handleSubmit">确定</a-button>
|
<a-button :loading="confirmLoading" type="primary" @click="handleSubmit">{{ $t('confirm') }}</a-button>
|
||||||
</template>
|
</template>
|
||||||
<a-tabs v-model="activeKey">
|
<a-tabs v-model="activeKey">
|
||||||
<a-tab-pane key="1" tab="新建属性">
|
<a-tab-pane key="1" :tab="$t('cmdb.ciType.addAttribute')">
|
||||||
<div :style="{ overflow: 'auto', maxHeight: '480px' }">
|
<div :style="{ overflow: 'auto', maxHeight: '480px' }">
|
||||||
<create-new-attribute ref="createNewAttribute" :hasFooter="false" @done="handleAddNewAttr" />
|
<create-new-attribute ref="createNewAttribute" :hasFooter="false" @done="handleAddNewAttr" />
|
||||||
</div>
|
</div>
|
||||||
</a-tab-pane>
|
</a-tab-pane>
|
||||||
<a-tab-pane key="2" tab="已有属性" force-render>
|
<a-tab-pane key="2" :tab="$t('cmdb.ciType.existedAttributes')" force-render>
|
||||||
<AttributesTransfer
|
<AttributesTransfer
|
||||||
:dataSource="unLinkdAttrs"
|
:dataSource="unLinkdAttrs"
|
||||||
:targetKeys="targetKeys"
|
:targetKeys="targetKeys"
|
||||||
|
@ -67,7 +67,6 @@ export default {
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
valueTypeMap,
|
|
||||||
activeKey: '1',
|
activeKey: '1',
|
||||||
visible: false,
|
visible: false,
|
||||||
attributes: [],
|
attributes: [],
|
||||||
|
@ -78,6 +77,9 @@ export default {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
valueTypeMap() {
|
||||||
|
return valueTypeMap()
|
||||||
|
},
|
||||||
windowHeight() {
|
windowHeight() {
|
||||||
return this.$store.state.windowHeight
|
return this.$store.state.windowHeight
|
||||||
},
|
},
|
||||||
|
@ -154,7 +156,7 @@ export default {
|
||||||
},
|
},
|
||||||
handleClose(isCloseModal = true) {
|
handleClose(isCloseModal = true) {
|
||||||
this.$emit('ok')
|
this.$emit('ok')
|
||||||
this.$message.success('添加成功!')
|
this.$message.success(this.$t('addSuccess'))
|
||||||
if (isCloseModal) {
|
if (isCloseModal) {
|
||||||
this.visible = false
|
this.visible = false
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,422 +1,422 @@
|
||||||
<template>
|
<template>
|
||||||
<a-tabs
|
<a-tabs
|
||||||
id="preValueArea"
|
id="preValueArea"
|
||||||
v-model="activeKey"
|
v-model="activeKey"
|
||||||
@change="changeActiveKey"
|
@change="changeActiveKey"
|
||||||
size="small"
|
size="small"
|
||||||
:tabBarStyle="{ borderBottom: 'none' }"
|
:tabBarStyle="{ borderBottom: 'none' }"
|
||||||
>
|
>
|
||||||
<a-tab-pane key="define" :disabled="disabled">
|
<a-tab-pane key="define" :disabled="disabled">
|
||||||
<span style="font-size:12px;" slot="tab">定义</span>
|
<span style="font-size:12px;" slot="tab">{{ $t('define') }}</span>
|
||||||
<PreValueTag type="add" :item="[]" @add="addNewValue" :disabled="disabled">
|
<PreValueTag type="add" :item="[]" @add="addNewValue" :disabled="disabled">
|
||||||
<template #default>
|
<template #default>
|
||||||
<a-button
|
<a-button
|
||||||
:style="{ marginBottom: '10px', fontSize: '12px', padding: '1px 7px' }"
|
:style="{ marginBottom: '10px', fontSize: '12px', padding: '1px 7px' }"
|
||||||
type="primary"
|
type="primary"
|
||||||
ghost
|
ghost
|
||||||
:disabled="disabled"
|
:disabled="disabled"
|
||||||
size="small"
|
size="small"
|
||||||
>
|
>
|
||||||
<a-icon type="plus" />添加</a-button
|
<a-icon type="plus" />{{ $t('add') }}</a-button
|
||||||
>
|
>
|
||||||
</template>
|
</template>
|
||||||
</PreValueTag>
|
</PreValueTag>
|
||||||
<draggable :list="valueList" handle=".handle" :disabled="disabled">
|
<draggable :list="valueList" handle=".handle" :disabled="disabled">
|
||||||
<PreValueTag
|
<PreValueTag
|
||||||
:disabled="disabled"
|
:disabled="disabled"
|
||||||
v-for="(item, index) in valueList"
|
v-for="(item, index) in valueList"
|
||||||
:key="`${item[0]}_${index}`"
|
:key="`${item[0]}_${index}`"
|
||||||
:item="item"
|
:item="item"
|
||||||
@deleteValue="deleteValue"
|
@deleteValue="deleteValue"
|
||||||
@editValue="editValue"
|
@editValue="editValue"
|
||||||
/>
|
/>
|
||||||
</draggable>
|
</draggable>
|
||||||
</a-tab-pane>
|
</a-tab-pane>
|
||||||
<a-tab-pane key="webhook" :disabled="disabled">
|
<a-tab-pane key="webhook" :disabled="disabled">
|
||||||
<span style="font-size:12px;" slot="tab">Webhook</span>
|
<span style="font-size:12px;" slot="tab">Webhook</span>
|
||||||
<Webhook ref="webhook" style="margin-top:10px" />
|
<Webhook ref="webhook" style="margin-top:10px" />
|
||||||
<a-form-model :model="form">
|
<a-form-model :model="form">
|
||||||
<a-col :span="24">
|
<a-col :span="24">
|
||||||
<a-form-model-item prop="ret_key" :labelCol="{ span: 3 }" :wrapperCol="{ span: 18 }">
|
<a-form-model-item prop="ret_key" :labelCol="{ span: 3 }" :wrapperCol="{ span: 18 }">
|
||||||
<template slot="label">
|
<template slot="label">
|
||||||
<span
|
<span
|
||||||
style="position:relative;white-space:pre;"
|
style="position:relative;white-space:pre;"
|
||||||
>{{ `过滤` }}
|
>{{ $t('cmdb.ciType.filter') }}
|
||||||
<a-tooltip
|
<a-tooltip
|
||||||
title="返回的结果按字段来过滤,层级嵌套用##分隔,比如k1##k2,web请求返回{k1: [{k2: 1}, {k2: 2}]}, 解析结果为[1, 2]"
|
:title="$t('cmdb.ciType.choiceWebhookTips')"
|
||||||
>
|
>
|
||||||
<a-icon
|
<a-icon
|
||||||
style="position:absolute;top:3px;left:-17px;color:#2f54eb;"
|
style="position:absolute;top:3px;left:-17px;color:#2f54eb;"
|
||||||
type="question-circle"
|
type="question-circle"
|
||||||
theme="filled"
|
theme="filled"
|
||||||
/>
|
/>
|
||||||
</a-tooltip>
|
</a-tooltip>
|
||||||
</span>
|
</span>
|
||||||
</template>
|
</template>
|
||||||
<a-input style="width:150px;" v-model="form.ret_key" placeholder="k1##k2" :disabled="disabled" />
|
<a-input style="width:150px;" v-model="form.ret_key" placeholder="k1##k2" :disabled="disabled" />
|
||||||
</a-form-model-item>
|
</a-form-model-item>
|
||||||
</a-col>
|
</a-col>
|
||||||
</a-form-model>
|
</a-form-model>
|
||||||
</a-tab-pane>
|
</a-tab-pane>
|
||||||
<a-tab-pane key="choice_other" :disabled="disabled">
|
<a-tab-pane key="choice_other" :disabled="disabled">
|
||||||
<span style="font-size:12px;" slot="tab">其他模型属性</span>
|
<span style="font-size:12px;" slot="tab">{{ $t('cmdb.ciType.choiceOther') }}</span>
|
||||||
<a-row :gutter="[24, 24]">
|
<a-row :gutter="[24, 24]">
|
||||||
<a-col :span="12">
|
<a-col :span="12">
|
||||||
<a-form-item
|
<a-form-item
|
||||||
:style="{ lineHeight: '24px', marginBottom: '5px' }"
|
:style="{ lineHeight: '24px', marginBottom: '5px' }"
|
||||||
label="模型"
|
:label="$t('cmdb.ciType.ciType')"
|
||||||
:label-col="{ span: 4 }"
|
:label-col="{ span: 4 }"
|
||||||
:wrapper-col="{ span: 20 }"
|
:wrapper-col="{ span: 20 }"
|
||||||
>
|
>
|
||||||
<treeselect
|
<treeselect
|
||||||
:disable-branch-nodes="true"
|
:disable-branch-nodes="true"
|
||||||
:class="{
|
:class="{
|
||||||
'custom-treeselect': true,
|
'custom-treeselect': true,
|
||||||
'custom-treeselect-bgcAndBorder': true,
|
'custom-treeselect-bgcAndBorder': true,
|
||||||
}"
|
}"
|
||||||
:style="{
|
:style="{
|
||||||
'--custom-height': '32px',
|
'--custom-height': '32px',
|
||||||
lineHeight: '32px',
|
lineHeight: '32px',
|
||||||
'--custom-bg-color': '#fff',
|
'--custom-bg-color': '#fff',
|
||||||
'--custom-border': '1px solid #d9d9d9',
|
'--custom-border': '1px solid #d9d9d9',
|
||||||
'--custom-multiple-lineHeight': '14px',
|
'--custom-multiple-lineHeight': '14px',
|
||||||
}"
|
}"
|
||||||
v-model="choice_other.type_ids"
|
v-model="choice_other.type_ids"
|
||||||
:multiple="true"
|
:multiple="true"
|
||||||
:clearable="true"
|
:clearable="true"
|
||||||
searchable
|
searchable
|
||||||
:options="ciTypeGroup"
|
:options="ciTypeGroup"
|
||||||
value-consists-of="LEAF_PRIORITY"
|
value-consists-of="LEAF_PRIORITY"
|
||||||
placeholder="请选择CMDB模型"
|
:placeholder="$t('cmdb.ciType.selectCIType')"
|
||||||
:normalizer="
|
:normalizer="
|
||||||
(node) => {
|
(node) => {
|
||||||
return {
|
return {
|
||||||
id: node.id || -1,
|
id: node.id || -1,
|
||||||
label: node.alias || node.name || '其他',
|
label: node.alias || node.name || $t('other'),
|
||||||
title: node.alias || node.name || '其他',
|
title: node.alias || node.name || $t('other'),
|
||||||
children: node.ci_types,
|
children: node.ci_types,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
"
|
"
|
||||||
appendToBody
|
appendToBody
|
||||||
:zIndex="1050"
|
:zIndex="1050"
|
||||||
@select="
|
@select="
|
||||||
() => {
|
() => {
|
||||||
choice_other.attr_id = undefined
|
choice_other.attr_id = undefined
|
||||||
}
|
}
|
||||||
"
|
"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
:title="node.label"
|
:title="node.label"
|
||||||
slot="option-label"
|
slot="option-label"
|
||||||
slot-scope="{ node }"
|
slot-scope="{ node }"
|
||||||
:style="{ width: '100%', whiteSpace: 'nowrap', textOverflow: 'ellipsis', overflow: 'hidden' }"
|
:style="{ width: '100%', whiteSpace: 'nowrap', textOverflow: 'ellipsis', overflow: 'hidden' }"
|
||||||
>
|
>
|
||||||
{{ node.label }}
|
{{ node.label }}
|
||||||
</div>
|
</div>
|
||||||
</treeselect>
|
</treeselect>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
</a-col>
|
</a-col>
|
||||||
<a-col :span="12" v-if="choice_other.type_ids && choice_other.type_ids.length">
|
<a-col :span="12" v-if="choice_other.type_ids && choice_other.type_ids.length">
|
||||||
<a-form-item
|
<a-form-item
|
||||||
:style="{ marginBottom: '5px' }"
|
:style="{ marginBottom: '5px' }"
|
||||||
label="属性"
|
:label="$t('cmdb.ciType.attributes')"
|
||||||
:label-col="{ span: 4 }"
|
:label-col="{ span: 4 }"
|
||||||
:wrapper-col="{ span: 20 }"
|
:wrapper-col="{ span: 20 }"
|
||||||
>
|
>
|
||||||
<treeselect
|
<treeselect
|
||||||
:disable-branch-nodes="true"
|
:disable-branch-nodes="true"
|
||||||
class="ops-setting-treeselect"
|
class="ops-setting-treeselect"
|
||||||
v-model="choice_other.attr_id"
|
v-model="choice_other.attr_id"
|
||||||
:multiple="false"
|
:multiple="false"
|
||||||
:clearable="true"
|
:clearable="true"
|
||||||
searchable
|
searchable
|
||||||
:options="typeAttrs"
|
:options="typeAttrs"
|
||||||
value-consists-of="LEAF_PRIORITY"
|
value-consists-of="LEAF_PRIORITY"
|
||||||
placeholder="请选择模型属性"
|
:placeholder="$t('cmdb.ciType.selectCITypeAttributes')"
|
||||||
:normalizer="
|
:normalizer="
|
||||||
(node) => {
|
(node) => {
|
||||||
return {
|
return {
|
||||||
id: node.id || -1,
|
id: node.id || -1,
|
||||||
label: node.alias || node.name || '其他',
|
label: node.alias || node.name || $t('other'),
|
||||||
title: node.alias || node.name || '其他',
|
title: node.alias || node.name || $t('other'),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
"
|
"
|
||||||
appendToBody
|
appendToBody
|
||||||
:zIndex="1050"
|
:zIndex="1050"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
:title="node.label"
|
:title="node.label"
|
||||||
slot="option-label"
|
slot="option-label"
|
||||||
slot-scope="{ node }"
|
slot-scope="{ node }"
|
||||||
:style="{ width: '100%', whiteSpace: 'nowrap', textOverflow: 'ellipsis', overflow: 'hidden' }"
|
:style="{ width: '100%', whiteSpace: 'nowrap', textOverflow: 'ellipsis', overflow: 'hidden' }"
|
||||||
>
|
>
|
||||||
{{ node.label }}
|
{{ node.label }}
|
||||||
</div>
|
</div>
|
||||||
</treeselect>
|
</treeselect>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
</a-col>
|
</a-col>
|
||||||
<a-col :span="24" v-if="choice_other.type_ids && choice_other.type_ids.length">
|
<a-col :span="24" v-if="choice_other.type_ids && choice_other.type_ids.length">
|
||||||
<a-form-item
|
<a-form-item
|
||||||
:style="{ marginBottom: '5px' }"
|
:style="{ marginBottom: '5px' }"
|
||||||
class="pre-value-filter"
|
class="pre-value-filter"
|
||||||
label="筛选"
|
:label="$t('cmdb.ciType.filter')"
|
||||||
:label-col="{ span: 2 }"
|
:label-col="{ span: 2 }"
|
||||||
:wrapper-col="{ span: 22 }"
|
:wrapper-col="{ span: 22 }"
|
||||||
>
|
>
|
||||||
<FilterComp
|
<FilterComp
|
||||||
ref="filterComp"
|
ref="filterComp"
|
||||||
:isDropdown="false"
|
:isDropdown="false"
|
||||||
:canSearchPreferenceAttrList="typeAttrs"
|
:canSearchPreferenceAttrList="typeAttrs"
|
||||||
@setExpFromFilter="setExpFromFilter"
|
@setExpFromFilter="setExpFromFilter"
|
||||||
:expression="filterExp ? `q=${filterExp}` : ''"
|
:expression="filterExp ? `q=${filterExp}` : ''"
|
||||||
/>
|
/>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
</a-col>
|
</a-col>
|
||||||
</a-row>
|
</a-row>
|
||||||
</a-tab-pane>
|
</a-tab-pane>
|
||||||
<a-tab-pane key="script" :disabled="disabled || !canDefineScript">
|
<a-tab-pane key="script" :disabled="disabled || !canDefineScript">
|
||||||
<span style="font-size:12px;" slot="tab">脚本</span>
|
<span style="font-size:12px;" slot="tab">{{ $t('cmdb.ciType.code') }}</span>
|
||||||
<CustomCodeMirror
|
<CustomCodeMirror
|
||||||
codeMirrorId="cmdb-pre-value"
|
codeMirrorId="cmdb-pre-value"
|
||||||
ref="codemirror"
|
ref="codemirror"
|
||||||
@changeCodeContent="changeCodeContent"
|
@changeCodeContent="changeCodeContent"
|
||||||
></CustomCodeMirror>
|
></CustomCodeMirror>
|
||||||
<!-- <codemirror style="z-index: 9999" :options="cmOptions" v-model="script"></codemirror> -->
|
<!-- <codemirror style="z-index: 9999" :options="cmOptions" v-model="script"></codemirror> -->
|
||||||
</a-tab-pane>
|
</a-tab-pane>
|
||||||
</a-tabs>
|
</a-tabs>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import _ from 'lodash'
|
import _ from 'lodash'
|
||||||
import draggable from 'vuedraggable'
|
import draggable from 'vuedraggable'
|
||||||
import PreValueTag from './preValueTag.vue'
|
import PreValueTag from './preValueTag.vue'
|
||||||
import { defautValueColor } from '../../utils/const'
|
import { defautValueColor } from '../../utils/const'
|
||||||
import ColorPicker from '../../components/colorPicker/index.vue'
|
import ColorPicker from '../../components/colorPicker/index.vue'
|
||||||
import Webhook from '../../components/webhook'
|
import Webhook from '../../components/webhook'
|
||||||
import { getCITypeGroups } from '../../api/ciTypeGroup'
|
import { getCITypeGroups } from '../../api/ciTypeGroup'
|
||||||
import { getCITypeCommonAttributesByTypeIds } from '../../api/CITypeAttr'
|
import { getCITypeCommonAttributesByTypeIds } from '../../api/CITypeAttr'
|
||||||
import FilterComp from '@/components/CMDBFilterComp'
|
import FilterComp from '@/components/CMDBFilterComp'
|
||||||
|
|
||||||
import CustomCodeMirror from '@/components/CustomCodeMirror'
|
import CustomCodeMirror from '@/components/CustomCodeMirror'
|
||||||
import 'codemirror/lib/codemirror.css'
|
import 'codemirror/lib/codemirror.css'
|
||||||
import 'codemirror/theme/monokai.css'
|
import 'codemirror/theme/monokai.css'
|
||||||
require('codemirror/mode/python/python.js')
|
require('codemirror/mode/python/python.js')
|
||||||
export default {
|
export default {
|
||||||
name: 'PreValueArea',
|
name: 'PreValueArea',
|
||||||
components: { draggable, PreValueTag, ColorPicker, Webhook, FilterComp, CustomCodeMirror },
|
components: { draggable, PreValueTag, ColorPicker, Webhook, FilterComp, CustomCodeMirror },
|
||||||
props: {
|
props: {
|
||||||
disabled: {
|
disabled: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: true,
|
default: true,
|
||||||
},
|
},
|
||||||
canDefineScript: {
|
canDefineScript: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: false,
|
default: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
defautValueColor,
|
defautValueColor,
|
||||||
activeKey: 'define', // define webhook
|
activeKey: 'define', // define webhook
|
||||||
valueList: [],
|
valueList: [],
|
||||||
form: {
|
form: {
|
||||||
ret_key: '',
|
ret_key: '',
|
||||||
},
|
},
|
||||||
choice_other: {
|
choice_other: {
|
||||||
type_ids: undefined,
|
type_ids: undefined,
|
||||||
attr_id: undefined,
|
attr_id: undefined,
|
||||||
},
|
},
|
||||||
ciTypeGroup: [],
|
ciTypeGroup: [],
|
||||||
typeAttrs: [],
|
typeAttrs: [],
|
||||||
filterExp: '',
|
filterExp: '',
|
||||||
script:
|
script:
|
||||||
'class ChoiceValue(object):\n @staticmethod\n def values():\n """\n 执行入口, 返回预定义值\n :return: 返回一个列表, 值的类型同属性的类型\n 例如:\n return ["在线", "下线"]\n """\n return []',
|
this.$t('cmdb.ciType.choiceScriptDemo'),
|
||||||
cmOptions: {
|
cmOptions: {
|
||||||
lineNumbers: true,
|
lineNumbers: true,
|
||||||
mode: 'python',
|
mode: 'python',
|
||||||
height: '200px',
|
height: '200px',
|
||||||
theme: 'monokai',
|
theme: 'monokai',
|
||||||
tabSize: 4,
|
tabSize: 4,
|
||||||
lineWrapping: true,
|
lineWrapping: true,
|
||||||
readOnly: this.disabled || !this.canDefineScript,
|
readOnly: this.disabled || !this.canDefineScript,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
disabled: {
|
disabled: {
|
||||||
immediate: false,
|
immediate: false,
|
||||||
handler(newValue) {
|
handler(newValue) {
|
||||||
const dom = document.querySelector('#preValueArea .ant-tabs-ink-bar')
|
const dom = document.querySelector('#preValueArea .ant-tabs-ink-bar')
|
||||||
if (newValue) {
|
if (newValue) {
|
||||||
// 如果是disabled 把tab 的ink-bar也置灰
|
// If it is disabled, the ink-bar of the tab will also be grayed out.
|
||||||
dom.style.backgroundColor = '#00000040'
|
dom.style.backgroundColor = '#00000040'
|
||||||
} else {
|
} else {
|
||||||
dom.style.backgroundColor = '#2f54eb'
|
dom.style.backgroundColor = '#2f54eb'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
'choice_other.type_ids': {
|
'choice_other.type_ids': {
|
||||||
handler(newValue) {
|
handler(newValue) {
|
||||||
if (newValue && newValue.length) {
|
if (newValue && newValue.length) {
|
||||||
getCITypeCommonAttributesByTypeIds({ type_ids: newValue.join(',') }).then((res) => {
|
getCITypeCommonAttributesByTypeIds({ type_ids: newValue.join(',') }).then((res) => {
|
||||||
this.typeAttrs = res.attributes
|
this.typeAttrs = res.attributes
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
created() {
|
created() {
|
||||||
getCITypeGroups({ need_other: true }).then((res) => {
|
getCITypeGroups({ need_other: true }).then((res) => {
|
||||||
this.ciTypeGroup = res
|
this.ciTypeGroup = res
|
||||||
.filter((item) => item.ci_types && item.ci_types.length)
|
.filter((item) => item.ci_types && item.ci_types.length)
|
||||||
.map((item) => {
|
.map((item) => {
|
||||||
item.id = `parent_${item.id || -1}`
|
item.id = `parent_${item.id || -1}`
|
||||||
return { ..._.cloneDeep(item) }
|
return { ..._.cloneDeep(item) }
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
addNewValue(newValue, newStyle, newIcon) {
|
addNewValue(newValue, newStyle, newIcon) {
|
||||||
if (newValue) {
|
if (newValue) {
|
||||||
const idx = this.valueList.findIndex((v) => v[0] === newValue)
|
const idx = this.valueList.findIndex((v) => v[0] === newValue)
|
||||||
if (idx > -1) {
|
if (idx > -1) {
|
||||||
this.$message.warning('当前值已存在!')
|
this.$message.warning(this.$t('cmdb.ciType.valueExisted'))
|
||||||
} else {
|
} else {
|
||||||
this.valueList.push([newValue, { style: newStyle, icon: { ...newIcon } }])
|
this.valueList.push([newValue, { style: newStyle, icon: { ...newIcon } }])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
deleteValue(item) {
|
deleteValue(item) {
|
||||||
const _valueList = _.cloneDeep(this.valueList)
|
const _valueList = _.cloneDeep(this.valueList)
|
||||||
const idx = _valueList.findIndex((v) => v[0] === item[0])
|
const idx = _valueList.findIndex((v) => v[0] === item[0])
|
||||||
if (idx > -1) {
|
if (idx > -1) {
|
||||||
_valueList.splice(idx, 1)
|
_valueList.splice(idx, 1)
|
||||||
this.valueList = _valueList
|
this.valueList = _valueList
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
editValue(item, newValue, newStyle, newIcon) {
|
editValue(item, newValue, newStyle, newIcon) {
|
||||||
const _valueList = _.cloneDeep(this.valueList)
|
const _valueList = _.cloneDeep(this.valueList)
|
||||||
const idx = _valueList.findIndex((v) => v[0] === item[0])
|
const idx = _valueList.findIndex((v) => v[0] === item[0])
|
||||||
if (idx > -1) {
|
if (idx > -1) {
|
||||||
_valueList[idx] = [newValue, { style: newStyle, icon: { ...newIcon } }]
|
_valueList[idx] = [newValue, { style: newStyle, icon: { ...newIcon } }]
|
||||||
this.valueList = _valueList
|
this.valueList = _valueList
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
getData() {
|
getData() {
|
||||||
if (this.activeKey === 'define') {
|
if (this.activeKey === 'define') {
|
||||||
return {
|
return {
|
||||||
choice_value: this.valueList,
|
choice_value: this.valueList,
|
||||||
choice_web_hook: null,
|
choice_web_hook: null,
|
||||||
choice_other: null,
|
choice_other: null,
|
||||||
}
|
}
|
||||||
} else if (this.activeKey === 'webhook') {
|
} else if (this.activeKey === 'webhook') {
|
||||||
const choice_web_hook = this.$refs.webhook.getParams()
|
const choice_web_hook = this.$refs.webhook.getParams()
|
||||||
choice_web_hook.ret_key = this.form.ret_key
|
choice_web_hook.ret_key = this.form.ret_key
|
||||||
return { choice_value: [], choice_web_hook, choice_other: null }
|
return { choice_value: [], choice_web_hook, choice_other: null }
|
||||||
} else if (this.activeKey === 'script') {
|
} else if (this.activeKey === 'script') {
|
||||||
return {
|
return {
|
||||||
choice_value: [],
|
choice_value: [],
|
||||||
choice_web_hook: null,
|
choice_web_hook: null,
|
||||||
choice_other: {
|
choice_other: {
|
||||||
script: this.script,
|
script: this.script,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
let choice_other = {}
|
let choice_other = {}
|
||||||
if (this.choice_other.type_ids && this.choice_other.type_ids.length) {
|
if (this.choice_other.type_ids && this.choice_other.type_ids.length) {
|
||||||
this.$refs.filterComp.handleSubmit()
|
this.$refs.filterComp.handleSubmit()
|
||||||
choice_other = { ...this.choice_other, filter: this.filterExp }
|
choice_other = { ...this.choice_other, filter: this.filterExp }
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
choice_value: [],
|
choice_value: [],
|
||||||
choice_web_hook: null,
|
choice_web_hook: null,
|
||||||
choice_other,
|
choice_other,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
setData({ choice_value, choice_web_hook, choice_other }) {
|
setData({ choice_value, choice_web_hook, choice_other }) {
|
||||||
if (choice_web_hook) {
|
if (choice_web_hook) {
|
||||||
this.activeKey = 'webhook'
|
this.activeKey = 'webhook'
|
||||||
this.$nextTick(() => {
|
this.$nextTick(() => {
|
||||||
this.$refs.webhook.setParams(choice_web_hook)
|
this.$refs.webhook.setParams(choice_web_hook)
|
||||||
this.form.ret_key = choice_web_hook.ret_key ?? ''
|
this.form.ret_key = choice_web_hook.ret_key ?? ''
|
||||||
})
|
})
|
||||||
} else if (choice_other) {
|
} else if (choice_other) {
|
||||||
if (choice_other.script) {
|
if (choice_other.script) {
|
||||||
this.activeKey = 'script'
|
this.activeKey = 'script'
|
||||||
this.script = choice_other.script
|
this.script = choice_other.script
|
||||||
this.$nextTick(() => {
|
this.$nextTick(() => {
|
||||||
this.$refs.codemirror.initCodeMirror(choice_other.script)
|
this.$refs.codemirror.initCodeMirror(choice_other.script)
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
this.activeKey = 'choice_other'
|
this.activeKey = 'choice_other'
|
||||||
const { type_ids, attr_id, filter } = choice_other
|
const { type_ids, attr_id, filter } = choice_other
|
||||||
this.choice_other = { type_ids, attr_id }
|
this.choice_other = { type_ids, attr_id }
|
||||||
this.filterExp = filter
|
this.filterExp = filter
|
||||||
if (type_ids && type_ids.length) {
|
if (type_ids && type_ids.length) {
|
||||||
this.$nextTick(() => {
|
this.$nextTick(() => {
|
||||||
this.$refs.filterComp.visibleChange(true, false)
|
this.$refs.filterComp.visibleChange(true, false)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
this.valueList = choice_value
|
this.valueList = choice_value
|
||||||
this.activeKey = 'define'
|
this.activeKey = 'define'
|
||||||
}
|
}
|
||||||
const dom = document.querySelector('#preValueArea .ant-tabs-ink-bar')
|
const dom = document.querySelector('#preValueArea .ant-tabs-ink-bar')
|
||||||
if (this.disabled) {
|
if (this.disabled) {
|
||||||
// 如果是disabled 把tab 的ink-bar也置灰
|
// If it is disabled, the ink-bar of the tab will also be grayed out.
|
||||||
dom.style.backgroundColor = '#00000040'
|
dom.style.backgroundColor = '#00000040'
|
||||||
} else {
|
} else {
|
||||||
dom.style.backgroundColor = '#2f54eb'
|
dom.style.backgroundColor = '#2f54eb'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
setExpFromFilter(filterExp) {
|
setExpFromFilter(filterExp) {
|
||||||
if (filterExp) {
|
if (filterExp) {
|
||||||
this.filterExp = `${filterExp}`
|
this.filterExp = `${filterExp}`
|
||||||
} else {
|
} else {
|
||||||
this.filterExp = ''
|
this.filterExp = ''
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
changeCodeContent(value) {
|
changeCodeContent(value) {
|
||||||
this.script = value && value.replace('\t', ' ')
|
this.script = value && value.replace('\t', ' ')
|
||||||
},
|
},
|
||||||
changeActiveKey(value) {
|
changeActiveKey(value) {
|
||||||
if (value === 'script') {
|
if (value === 'script') {
|
||||||
this.$nextTick(() => {
|
this.$nextTick(() => {
|
||||||
this.$refs.codemirror.initCodeMirror(this.script)
|
this.$refs.codemirror.initCodeMirror(this.script)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="less" scoped>
|
<style lang="less" scoped>
|
||||||
.pre-value-edit-color {
|
.pre-value-edit-color {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
.pre-value-edit-color-item {
|
.pre-value-edit-color-item {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
width: 25px;
|
width: 25px;
|
||||||
height: 20px;
|
height: 20px;
|
||||||
margin: 5px;
|
margin: 5px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<style lang="less">
|
<style lang="less">
|
||||||
.pre-value-filter {
|
.pre-value-filter {
|
||||||
.ant-form-item-control {
|
.ant-form-item-control {
|
||||||
line-height: 24px;
|
line-height: 24px;
|
||||||
}
|
}
|
||||||
.table-filter-add {
|
.table-filter-add {
|
||||||
line-height: 40px;
|
line-height: 40px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -11,9 +11,9 @@
|
||||||
>
|
>
|
||||||
</a-input>
|
</a-input>
|
||||||
<div ref="preValueEdit" slot="content">
|
<div ref="preValueEdit" slot="content">
|
||||||
<a-divider orientation="left" style="margin:8px 0;color:gray;font-size:10px;">图标</a-divider>
|
<a-divider orientation="left" style="margin:8px 0;color:gray;font-size:10px;">{{ $t('icon') }}</a-divider>
|
||||||
<IconArea ref="iconArea" />
|
<IconArea ref="iconArea" />
|
||||||
<a-divider orientation="left" style="margin:8px 0;color:gray;font-size:10px;">字体</a-divider>
|
<a-divider orientation="left" style="margin:8px 0;color:gray;font-size:10px;">{{ $t('cmdb.ciType.font') }}</a-divider>
|
||||||
<div :style="{ display: 'flex', justifyContent: 'space-around' }">
|
<div :style="{ display: 'flex', justifyContent: 'space-around' }">
|
||||||
<div
|
<div
|
||||||
@click="changeFontStyle('fontWeight', 'bold')"
|
@click="changeFontStyle('fontWeight', 'bold')"
|
||||||
|
@ -37,7 +37,7 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<a-divider orientation="left" style="margin:8px 0;color:gray;font-size:10px;">颜色</a-divider>
|
<a-divider orientation="left" style="margin:8px 0;color:gray;font-size:10px;">{{ $t('cmdb.ciType.color') }}</a-divider>
|
||||||
<div :style="{ display: 'flex', justifyContent: 'space-around' }">
|
<div :style="{ display: 'flex', justifyContent: 'space-around' }">
|
||||||
<div class="attributes-font-color">
|
<div class="attributes-font-color">
|
||||||
<a-icon type="font-colors" /><el-color-picker
|
<a-icon type="font-colors" /><el-color-picker
|
||||||
|
@ -56,11 +56,11 @@
|
||||||
</el-color-picker>
|
</el-color-picker>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<a-divider orientation="left" style="margin:8px 0;color:gray;font-size:10px;">操作</a-divider>
|
<a-divider orientation="left" style="margin:8px 0;color:gray;font-size:10px;">{{ $t('operation') }}</a-divider>
|
||||||
<div style="text-align:right;">
|
<div style="text-align:right;">
|
||||||
<a-tooltip
|
<a-tooltip
|
||||||
v-if="type !== 'add'"
|
v-if="type !== 'add'"
|
||||||
title="删除"
|
:title="$t('delete')"
|
||||||
><a
|
><a
|
||||||
><a-icon
|
><a-icon
|
||||||
@click="handleDelete"
|
@click="handleDelete"
|
||||||
|
@ -69,11 +69,11 @@
|
||||||
type="delete"/></a
|
type="delete"/></a
|
||||||
></a-tooltip>
|
></a-tooltip>
|
||||||
<a-tooltip
|
<a-tooltip
|
||||||
title="确定"
|
:title="$t('confirm')"
|
||||||
><a><a-icon @click="handleEditOk" style="margin-right:10px;color:green;" type="check"/></a
|
><a><a-icon @click="handleEditOk" style="margin-right:10px;color:green;" type="check"/></a
|
||||||
></a-tooltip>
|
></a-tooltip>
|
||||||
<a-tooltip
|
<a-tooltip
|
||||||
title="取消"
|
:title="$t('cancel')"
|
||||||
><a
|
><a
|
||||||
><a-icon
|
><a-icon
|
||||||
@click="
|
@click="
|
||||||
|
@ -137,6 +137,9 @@ import _ from 'lodash'
|
||||||
import { ColorPicker } from 'element-ui'
|
import { ColorPicker } from 'element-ui'
|
||||||
import { defautValueColor, defaultBGColors } from '../../utils/const'
|
import { defautValueColor, defaultBGColors } from '../../utils/const'
|
||||||
import IconArea from './iconArea.vue'
|
import IconArea from './iconArea.vue'
|
||||||
|
import lang from 'element-ui/lib/locale/lang/en'
|
||||||
|
import locale from 'element-ui/lib/locale'
|
||||||
|
locale.use(lang)
|
||||||
export default {
|
export default {
|
||||||
name: 'PreValueTag',
|
name: 'PreValueTag',
|
||||||
components: { ElColorPicker: ColorPicker, IconArea },
|
components: { ElColorPicker: ColorPicker, IconArea },
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
searchable
|
searchable
|
||||||
:options="ciTypeADTAttributes"
|
:options="ciTypeADTAttributes"
|
||||||
value-consists-of="LEAF_PRIORITY"
|
value-consists-of="LEAF_PRIORITY"
|
||||||
placeholder="请选择属性"
|
:placeholder="$t('cmdb.ciType.selectAttributes')"
|
||||||
:normalizer="
|
:normalizer="
|
||||||
(node) => {
|
(node) => {
|
||||||
return {
|
return {
|
||||||
|
@ -35,15 +35,15 @@
|
||||||
searchable
|
searchable
|
||||||
:options="ciTypeGroup"
|
:options="ciTypeGroup"
|
||||||
value-consists-of="LEAF_PRIORITY"
|
value-consists-of="LEAF_PRIORITY"
|
||||||
placeholder="请选择模型"
|
:placeholder="$t('cmdb.ciType.selectCIType')"
|
||||||
:disableBranchNodes="true"
|
:disableBranchNodes="true"
|
||||||
@select="changeType(item)"
|
@select="changeType(item)"
|
||||||
:normalizer="
|
:normalizer="
|
||||||
(node) => {
|
(node) => {
|
||||||
return {
|
return {
|
||||||
id: node.name || '其他',
|
id: node.name || $t('other'),
|
||||||
label: node.alias || node.name || '其他',
|
label: node.alias || node.name || $t('other'),
|
||||||
title: node.alias || node.name || '其他',
|
title: node.alias || node.name || $t('other'),
|
||||||
children: node.ci_types,
|
children: node.ci_types,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -67,7 +67,7 @@
|
||||||
searchable
|
searchable
|
||||||
:options="item.attributes"
|
:options="item.attributes"
|
||||||
value-consists-of="LEAF_PRIORITY"
|
value-consists-of="LEAF_PRIORITY"
|
||||||
placeholder="请选择属性"
|
:placeholder="$t('cmdb.ciType.selectAttributes')"
|
||||||
:normalizer="
|
:normalizer="
|
||||||
(node) => {
|
(node) => {
|
||||||
return {
|
return {
|
||||||
|
@ -89,7 +89,7 @@
|
||||||
</treeselect>
|
</treeselect>
|
||||||
</div>
|
</div>
|
||||||
<div class="relation-ad-footer">
|
<div class="relation-ad-footer">
|
||||||
<a-button type="primary" @click="handleSave">保存</a-button>
|
<a-button type="primary" @click="handleSave">{{ $t('save') }}</a-button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
@ -148,7 +148,7 @@ export default {
|
||||||
},
|
},
|
||||||
getCITypeDiscovery() {
|
getCITypeDiscovery() {
|
||||||
getCITypeDiscovery(this.CITypeId).then(async (res) => {
|
getCITypeDiscovery(this.CITypeId).then(async (res) => {
|
||||||
// 第一个下拉框的options
|
// Options for the first drop-down box
|
||||||
const _ciTypeADTAttributes = []
|
const _ciTypeADTAttributes = []
|
||||||
res
|
res
|
||||||
.filter((adt) => adt.adr_id)
|
.filter((adt) => adt.adr_id)
|
||||||
|
@ -160,7 +160,7 @@ export default {
|
||||||
})
|
})
|
||||||
console.log(_ciTypeADTAttributes)
|
console.log(_ciTypeADTAttributes)
|
||||||
this.ciTypeADTAttributes = _.uniqBy(_ciTypeADTAttributes, 'name')
|
this.ciTypeADTAttributes = _.uniqBy(_ciTypeADTAttributes, 'name')
|
||||||
// 第一个下拉框的options
|
// Options for the first drop-down box
|
||||||
const _find = res.find((adt) => !adt.adr_id)
|
const _find = res.find((adt) => !adt.adr_id)
|
||||||
if (_find) {
|
if (_find) {
|
||||||
this.adt_id = _find.id
|
this.adt_id = _find.id
|
||||||
|
@ -242,7 +242,7 @@ export default {
|
||||||
} else {
|
} else {
|
||||||
await postCITypeDiscovery(this.CITypeId, { relation: _relation })
|
await postCITypeDiscovery(this.CITypeId, { relation: _relation })
|
||||||
}
|
}
|
||||||
this.$message.success('保存成功')
|
this.$message.success(this.$t('saveSuccess'))
|
||||||
this.getCITypeDiscovery()
|
this.getCITypeDiscovery()
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
size="small"
|
size="small"
|
||||||
class="ops-button-primary"
|
class="ops-button-primary"
|
||||||
icon="plus"
|
icon="plus"
|
||||||
>新增关系</a-button
|
>{{ $t('cmdb.ciType.addRelation') }}</a-button
|
||||||
>
|
>
|
||||||
<vxe-table
|
<vxe-table
|
||||||
stripe
|
stripe
|
||||||
|
@ -20,15 +20,15 @@
|
||||||
class="ops-stripe-table"
|
class="ops-stripe-table"
|
||||||
:row-class-name="rowClass"
|
:row-class-name="rowClass"
|
||||||
>
|
>
|
||||||
<vxe-column field="source_ci_type_name" title="源模型英文名"></vxe-column>
|
<vxe-column field="source_ci_type_name" :title="$t('cmdb.ciType.sourceCIType')"></vxe-column>
|
||||||
<vxe-column field="relation_type" title="关联类型">
|
<vxe-column field="relation_type" :title="$t('cmdb.ciType.relationType')">
|
||||||
<template #default="{row}">
|
<template #default="{row}">
|
||||||
<span style="color:#2f54eb" v-if="row.isParent">被</span>
|
<span style="color:#2f54eb" v-if="row.isParent">{{ $t('cmdb.ciType.isParent') }}</span>
|
||||||
{{ row.relation_type }}
|
{{ row.relation_type }}
|
||||||
</template>
|
</template>
|
||||||
</vxe-column>
|
</vxe-column>
|
||||||
<vxe-column field="alias" title="目标模型名"></vxe-column>
|
<vxe-column field="alias" :title="$t('cmdb.ciType.dstCIType')"></vxe-column>
|
||||||
<vxe-column field="constraint" title="关系约束">
|
<vxe-column field="constraint" :title="$t('cmdb.ciType.relationConstraint')">
|
||||||
<template #default="{row}">
|
<template #default="{row}">
|
||||||
<span v-if="row.isParent && constraintMap[row.constraint]">{{
|
<span v-if="row.isParent && constraintMap[row.constraint]">{{
|
||||||
constraintMap[row.constraint]
|
constraintMap[row.constraint]
|
||||||
|
@ -39,11 +39,11 @@
|
||||||
<span v-else>{{ constraintMap[row.constraint] }}</span>
|
<span v-else>{{ constraintMap[row.constraint] }}</span>
|
||||||
</template>
|
</template>
|
||||||
</vxe-column>
|
</vxe-column>
|
||||||
<vxe-column field="operation" title="操作" width="100">
|
<vxe-column field="operation" :title="$t('operation')" width="100">
|
||||||
<template #default="{row}">
|
<template #default="{row}">
|
||||||
<a-space v-if="!row.isParent && row.source_ci_type_id">
|
<a-space v-if="!row.isParent && row.source_ci_type_id">
|
||||||
<a @click="handleOpenGrant(row)"><a-icon type="user-add"/></a>
|
<a @click="handleOpenGrant(row)"><a-icon type="user-add"/></a>
|
||||||
<a-popconfirm title="确认删除?" @confirm="handleDelete(row)">
|
<a-popconfirm :title="$t('cmdb.ciType.confirmDelete2')" @confirm="handleDelete(row)">
|
||||||
<a style="color: red;"><a-icon type="delete"/></a>
|
<a style="color: red;"><a-icon type="delete"/></a>
|
||||||
</a-popconfirm>
|
</a-popconfirm>
|
||||||
</a-space>
|
</a-space>
|
||||||
|
@ -52,7 +52,7 @@
|
||||||
<template #empty>
|
<template #empty>
|
||||||
<div>
|
<div>
|
||||||
<img :style="{ width: '100px' }" :src="require('@/assets/data_empty.png')" />
|
<img :style="{ width: '100px' }" :src="require('@/assets/data_empty.png')" />
|
||||||
<div>暂无数据</div>
|
<div>{{ $t('noData') }}</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</vxe-table>
|
</vxe-table>
|
||||||
|
@ -65,21 +65,24 @@
|
||||||
width="500px"
|
width="500px"
|
||||||
>
|
>
|
||||||
<a-form :form="form" @submit="handleSubmit" :label-col="{ span: 6 }" :wrapper-col="{ span: 14 }">
|
<a-form :form="form" @submit="handleSubmit" :label-col="{ span: 6 }" :wrapper-col="{ span: 14 }">
|
||||||
<a-form-item label="源模型">
|
<a-form-item :label="$t('cmdb.ciType.sourceCIType')">
|
||||||
<a-select
|
<a-select
|
||||||
name="source_ci_type_id"
|
name="source_ci_type_id"
|
||||||
v-decorator="['source_ci_type_id', { rules: [{ required: true, message: '请选择源模型' }] }]"
|
v-decorator="[
|
||||||
|
'source_ci_type_id',
|
||||||
|
{ rules: [{ required: true, message: $t('cmdb.ciType.sourceCITypeTips') }] },
|
||||||
|
]"
|
||||||
>
|
>
|
||||||
<a-select-option :value="CIType.id" :key="CIType.id" v-for="CIType in displayCITypes">{{
|
<a-select-option :value="CIType.id" :key="CIType.id" v-for="CIType in displayCITypes">{{
|
||||||
CIType.alias
|
CIType.alias
|
||||||
}}</a-select-option>
|
}}</a-select-option>
|
||||||
</a-select>
|
</a-select>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-form-item label="目标模型">
|
<a-form-item :label="$t('cmdb.ciType.dstCIType')">
|
||||||
<a-select
|
<a-select
|
||||||
showSearch
|
showSearch
|
||||||
name="ci_type_id"
|
name="ci_type_id"
|
||||||
v-decorator="['ci_type_id', { rules: [{ required: true, message: '请选择目标模型' }] }]"
|
v-decorator="['ci_type_id', { rules: [{ required: true, message: $t('cmdb.ciType.dstCITypeTips') }] }]"
|
||||||
:filterOption="filterOption"
|
:filterOption="filterOption"
|
||||||
>
|
>
|
||||||
<a-select-option :value="CIType.id" :key="CIType.id" v-for="CIType in CITypes">
|
<a-select-option :value="CIType.id" :key="CIType.id" v-for="CIType in CITypes">
|
||||||
|
@ -88,10 +91,13 @@
|
||||||
</a-select>
|
</a-select>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
|
|
||||||
<a-form-item label="关联关系">
|
<a-form-item :label="$t('cmdb.ciType.relationType')">
|
||||||
<a-select
|
<a-select
|
||||||
name="relation_type_id"
|
name="relation_type_id"
|
||||||
v-decorator="['relation_type_id', { rules: [{ required: true, message: '请选择关联关系' }] }]"
|
v-decorator="[
|
||||||
|
'relation_type_id',
|
||||||
|
{ rules: [{ required: true, message: $t('cmdb.ciType.relationTypeTips') }] },
|
||||||
|
]"
|
||||||
>
|
>
|
||||||
<a-select-option :value="relationType.id" :key="relationType.id" v-for="relationType in relationTypes">{{
|
<a-select-option :value="relationType.id" :key="relationType.id" v-for="relationType in relationTypes">{{
|
||||||
relationType.name
|
relationType.name
|
||||||
|
@ -99,11 +105,16 @@
|
||||||
</a-select>
|
</a-select>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
|
|
||||||
<a-form-item label="关联约束">
|
<a-form-item :label="$t('cmdb.ciType.relationConstraint')">
|
||||||
<a-select v-decorator="['constraint', { rules: [{ required: true, message: '请选择关联约束' }] }]">
|
<a-select
|
||||||
<a-select-option value="0">一对多</a-select-option>
|
v-decorator="[
|
||||||
<a-select-option value="1">一对一</a-select-option>
|
'constraint',
|
||||||
<a-select-option value="2">多对多</a-select-option>
|
{ rules: [{ required: true, message: $t('cmdb.ciType.relationConstraintTips') }] },
|
||||||
|
]"
|
||||||
|
>
|
||||||
|
<a-select-option value="0">{{ $t('cmdb.ciType.one2Many') }}</a-select-option>
|
||||||
|
<a-select-option value="1">{{ $t('cmdb.ciType.one2One') }}</a-select-option>
|
||||||
|
<a-select-option value="2">{{ $t('cmdb.ciType.many2Many') }}</a-select-option>
|
||||||
</a-select>
|
</a-select>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
</a-form>
|
</a-form>
|
||||||
|
@ -145,11 +156,6 @@ export default {
|
||||||
drawerTitle: '',
|
drawerTitle: '',
|
||||||
CITypes: [],
|
CITypes: [],
|
||||||
relationTypes: [],
|
relationTypes: [],
|
||||||
constraintMap: {
|
|
||||||
'0': '一对多',
|
|
||||||
'1': '一对一',
|
|
||||||
'2': '多对多',
|
|
||||||
},
|
|
||||||
tableData: [],
|
tableData: [],
|
||||||
parentTableData: [],
|
parentTableData: [],
|
||||||
}
|
}
|
||||||
|
@ -161,6 +167,13 @@ export default {
|
||||||
windowHeight() {
|
windowHeight() {
|
||||||
return this.$store.state.windowHeight
|
return this.$store.state.windowHeight
|
||||||
},
|
},
|
||||||
|
constraintMap() {
|
||||||
|
return {
|
||||||
|
'0': this.$t('cmdb.ciType.one2Many'),
|
||||||
|
'1': this.$t('cmdb.ciType.one2One'),
|
||||||
|
'2': this.$t('cmdb.ciType.many2Many'),
|
||||||
|
}
|
||||||
|
},
|
||||||
},
|
},
|
||||||
async mounted() {
|
async mounted() {
|
||||||
this.getCITypes()
|
this.getCITypes()
|
||||||
|
@ -209,7 +222,7 @@ export default {
|
||||||
},
|
},
|
||||||
handleDelete(record) {
|
handleDelete(record) {
|
||||||
deleteRelation(record.source_ci_type_id, record.id).then((res) => {
|
deleteRelation(record.source_ci_type_id, record.id).then((res) => {
|
||||||
this.$message.success(`删除成功!`)
|
this.$message.success(this.$t('deleteSuccess'))
|
||||||
this.handleOk()
|
this.handleOk()
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
@ -218,7 +231,7 @@ export default {
|
||||||
},
|
},
|
||||||
|
|
||||||
handleCreate() {
|
handleCreate() {
|
||||||
this.drawerTitle = '新增关系'
|
this.drawerTitle = this.$t('cmdb.ciType.addRelation')
|
||||||
this.visible = true
|
this.visible = true
|
||||||
this.$nextTick(() => {
|
this.$nextTick(() => {
|
||||||
this.form.setFieldsValue({
|
this.form.setFieldsValue({
|
||||||
|
@ -241,7 +254,7 @@ export default {
|
||||||
|
|
||||||
createRelation(values.source_ci_type_id, values.ci_type_id, values.relation_type_id, values.constraint).then(
|
createRelation(values.source_ci_type_id, values.ci_type_id, values.relation_type_id, values.constraint).then(
|
||||||
(res) => {
|
(res) => {
|
||||||
this.$message.success(`添加成功`)
|
this.$message.success(this.$t('addSuccess'))
|
||||||
this.onClose()
|
this.onClose()
|
||||||
this.handleOk()
|
this.handleOk()
|
||||||
}
|
}
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,159 +1,139 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="ci-types-triggers">
|
<div class="ci-types-triggers">
|
||||||
<div style="margin-bottom: 10px">
|
<div style="margin-bottom: 10px">
|
||||||
<a-button
|
<a-button
|
||||||
type="primary"
|
type="primary"
|
||||||
@click="handleAddTrigger"
|
@click="handleAddTrigger"
|
||||||
size="small"
|
size="small"
|
||||||
class="ops-button-primary"
|
class="ops-button-primary"
|
||||||
icon="plus"
|
icon="plus"
|
||||||
>新增触发器</a-button
|
>{{ $t('cmdb.ciType.newTrigger') }}</a-button
|
||||||
>
|
>
|
||||||
</div>
|
</div>
|
||||||
<vxe-table
|
<ops-table
|
||||||
stripe
|
stripe
|
||||||
:data="tableData"
|
:data="tableData"
|
||||||
size="small"
|
size="small"
|
||||||
show-overflow
|
show-overflow
|
||||||
highlight-hover-row
|
highlight-hover-row
|
||||||
keep-source
|
keep-source
|
||||||
:max-height="windowHeight - 180"
|
:max-height="windowHeight - 180"
|
||||||
class="ops-stripe-table"
|
class="ops-stripe-table"
|
||||||
>
|
>
|
||||||
<vxe-column field="option.name" title="名称"></vxe-column>
|
<vxe-column field="option.name" :title="$t('name')"></vxe-column>
|
||||||
<vxe-column field="option.description" title="备注"></vxe-column>
|
<vxe-column field="option.description" :title="$t('desc')"></vxe-column>
|
||||||
<vxe-column field="type" title="类型">
|
<vxe-column field="type" :title="$t('type')">
|
||||||
<template #default="{ row }">
|
<template #default="{ row }">
|
||||||
<span v-if="row.attr_id">日期属性</span>
|
<span v-if="row.attr_id">{{ $t('cmdb.ciType.triggerDate') }}</span>
|
||||||
<span v-else>数据变更</span>
|
<span v-else>{{ $t('cmdb.ciType.triggerDataChange') }}</span>
|
||||||
</template>
|
</template>
|
||||||
</vxe-column>
|
</vxe-column>
|
||||||
<vxe-column field="option.enable" title="开启">
|
<vxe-column field="option.enable" :title="$t('cmdb.ciType.triggerEnable')">
|
||||||
<template #default="{ row }">
|
<template #default="{ row }">
|
||||||
<a-switch :checked="row.option.enable" @click="changeEnable(row)"></a-switch>
|
<a-switch :checked="row.option.enable" @click="changeEnable(row)"></a-switch>
|
||||||
</template>
|
</template>
|
||||||
</vxe-column>
|
</vxe-column>
|
||||||
|
<vxe-column field="operation" :title="$t('operation')" width="100px" align="center">
|
||||||
<!-- <vxe-column field="attr_name" title="属性名"></vxe-column>
|
<template #default="{ row }">
|
||||||
<vxe-column field="option.subject" title="主题"></vxe-column>
|
<a-space>
|
||||||
<vxe-column field="option.body" title="内容"></vxe-column>
|
<a @click="handleEdit(row)"><a-icon type="edit"/></a>
|
||||||
<vxe-column field="option.wx_to" title="微信通知">
|
<a style="color:red;" @click="handleDetele(row.id)"><a-icon type="delete"/></a>
|
||||||
<template #default="{ row }">
|
</a-space>
|
||||||
<span v-for="(person, index) in row.option.wx_to" :key="person + index">[{{ person }}]</span>
|
</template>
|
||||||
</template>
|
</vxe-column>
|
||||||
</vxe-column>
|
</ops-table>
|
||||||
<vxe-column field="option.mail_to" title="邮件通知">
|
<TriggerForm ref="triggerForm" :CITypeId="CITypeId" />
|
||||||
<template #default="{ row }">
|
</div>
|
||||||
<span v-for="(email, index) in row.option.mail_to" :key="email + index">[{{ email }}]</span>
|
</template>
|
||||||
</template>
|
|
||||||
</vxe-column>
|
<script>
|
||||||
<vxe-column field="option.before_days" title="提前">
|
import _ from 'lodash'
|
||||||
<template #default="{ row }">
|
import { getTriggerList, deleteTrigger, updateTrigger } from '../../api/CIType'
|
||||||
<span v-if="row.option.before_days">{{ row.option.before_days }}天</span>
|
import { getCITypeAttributesById } from '../../api/CITypeAttr'
|
||||||
</template>
|
import TriggerForm from './triggerForm.vue'
|
||||||
</vxe-column>
|
|
||||||
<vxe-column field="option.notify_at" title="发送时间"></vxe-column> -->
|
export default {
|
||||||
<vxe-column field="operation" title="操作" width="80px" align="center">
|
name: 'TriggerTable',
|
||||||
<template #default="{ row }">
|
components: { TriggerForm },
|
||||||
<a-space>
|
props: {
|
||||||
<a @click="handleEdit(row)"><a-icon type="edit"/></a>
|
CITypeId: {
|
||||||
<a style="color:red;" @click="handleDetele(row.id)"><a-icon type="delete"/></a>
|
type: Number,
|
||||||
</a-space>
|
default: null,
|
||||||
</template>
|
},
|
||||||
</vxe-column>
|
},
|
||||||
</vxe-table>
|
data() {
|
||||||
<TriggerForm ref="triggerForm" :CITypeId="CITypeId" />
|
return {
|
||||||
</div>
|
tableData: [],
|
||||||
</template>
|
attrList: [],
|
||||||
|
}
|
||||||
<script>
|
},
|
||||||
import _ from 'lodash'
|
computed: {
|
||||||
import { getTriggerList, deleteTrigger, updateTrigger } from '../../api/CIType'
|
windowHeight() {
|
||||||
import { getCITypeAttributesById } from '../../api/CITypeAttr'
|
return this.$store.state.windowHeight
|
||||||
import TriggerForm from './triggerForm.vue'
|
},
|
||||||
|
},
|
||||||
export default {
|
provide() {
|
||||||
name: 'TriggerTable',
|
return {
|
||||||
components: { TriggerForm },
|
refresh: this.getTableData,
|
||||||
props: {
|
}
|
||||||
CITypeId: {
|
},
|
||||||
type: Number,
|
methods: {
|
||||||
default: null,
|
async getTableData() {
|
||||||
},
|
const [triggerList, attrList] = await Promise.all([
|
||||||
},
|
getTriggerList(this.CITypeId),
|
||||||
data() {
|
getCITypeAttributesById(this.CITypeId),
|
||||||
return {
|
])
|
||||||
tableData: [],
|
triggerList.forEach((trigger) => {
|
||||||
attrList: [],
|
const _find = attrList.attributes.find((attr) => attr.id === trigger.attr_id)
|
||||||
}
|
if (_find) {
|
||||||
},
|
trigger.attr_name = _find.alias || _find.name
|
||||||
computed: {
|
}
|
||||||
windowHeight() {
|
})
|
||||||
return this.$store.state.windowHeight
|
this.tableData = triggerList
|
||||||
},
|
this.attrList = attrList.attributes
|
||||||
},
|
},
|
||||||
provide() {
|
handleAddTrigger() {
|
||||||
return {
|
this.$refs.triggerForm.createFromTriggerTable(this.attrList)
|
||||||
refresh: this.getTableData,
|
},
|
||||||
}
|
handleDetele(id) {
|
||||||
},
|
const that = this
|
||||||
methods: {
|
this.$confirm({
|
||||||
async getTableData() {
|
title: that.$t('warning'),
|
||||||
const [triggerList, attrList] = await Promise.all([
|
content: that.$t('cmdb.ciType.confirmDeleteTrigger'),
|
||||||
getTriggerList(this.CITypeId),
|
onOk() {
|
||||||
getCITypeAttributesById(this.CITypeId),
|
deleteTrigger(that.CITypeId, id).then(() => {
|
||||||
])
|
that.$message.success(that.$t('deleteSuccess'))
|
||||||
triggerList.forEach((trigger) => {
|
that.getTableData()
|
||||||
const _find = attrList.attributes.find((attr) => attr.id === trigger.attr_id)
|
})
|
||||||
if (_find) {
|
},
|
||||||
trigger.attr_name = _find.alias || _find.name
|
})
|
||||||
}
|
},
|
||||||
})
|
handleEdit(row) {
|
||||||
this.tableData = triggerList
|
this.$refs.triggerForm.open(
|
||||||
this.attrList = attrList.attributes
|
{
|
||||||
},
|
id: row.attr_id,
|
||||||
handleAddTrigger() {
|
alias: row?.option?.name ?? '',
|
||||||
this.$refs.triggerForm.createFromTriggerTable(this.attrList)
|
trigger: { id: row.id, attr_id: row.attr_id, option: row.option },
|
||||||
},
|
has_trigger: true,
|
||||||
handleDetele(id) {
|
},
|
||||||
const that = this
|
this.attrList
|
||||||
this.$confirm({
|
)
|
||||||
title: '警告',
|
},
|
||||||
content: '确认删除该触发器吗?',
|
changeEnable(row) {
|
||||||
onOk() {
|
const _row = _.cloneDeep(row)
|
||||||
deleteTrigger(that.CITypeId, id).then(() => {
|
delete _row.id
|
||||||
that.$message.success('删除成功!')
|
const enable = row?.option?.enable ?? true
|
||||||
that.getTableData()
|
_row.option.enable = !enable
|
||||||
})
|
updateTrigger(this.CITypeId, row.id, _row).then(() => {
|
||||||
},
|
this.getTableData()
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
handleEdit(row) {
|
},
|
||||||
this.$refs.triggerForm.open(
|
}
|
||||||
{
|
</script>
|
||||||
id: row.attr_id,
|
|
||||||
alias: row?.option?.name ?? '',
|
<style lang="less" scoped>
|
||||||
trigger: { id: row.id, attr_id: row.attr_id, option: row.option },
|
.ci-types-triggers {
|
||||||
has_trigger: true,
|
padding: 16px 24px 24px;
|
||||||
},
|
}
|
||||||
this.attrList
|
</style>
|
||||||
)
|
|
||||||
},
|
|
||||||
changeEnable(row) {
|
|
||||||
const _row = _.cloneDeep(row)
|
|
||||||
delete _row.id
|
|
||||||
const enable = row?.option?.enable ?? true
|
|
||||||
_row.option.enable = !enable
|
|
||||||
updateTrigger(this.CITypeId, row.id, _row).then(() => {
|
|
||||||
this.getTableData()
|
|
||||||
})
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="less" scoped>
|
|
||||||
.ci-types-triggers {
|
|
||||||
padding: 16px 24px 24px;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
|
@ -7,9 +7,9 @@
|
||||||
icon="plus"
|
icon="plus"
|
||||||
size="small"
|
size="small"
|
||||||
:style="{ marginBottom: '10px' }"
|
:style="{ marginBottom: '10px' }"
|
||||||
>新增</a-button
|
>{{ $t('new') }}</a-button
|
||||||
>
|
>
|
||||||
<vxe-table
|
<ops-table
|
||||||
:loading="loading"
|
:loading="loading"
|
||||||
:data="tableData"
|
:data="tableData"
|
||||||
:edit-config="{ trigger: 'manual', mode: 'row', showIcon: false, autoClear: false, showStatus: true }"
|
:edit-config="{ trigger: 'manual', mode: 'row', showIcon: false, autoClear: false, showStatus: true }"
|
||||||
|
@ -18,8 +18,10 @@
|
||||||
ref="xTable"
|
ref="xTable"
|
||||||
size="mini"
|
size="mini"
|
||||||
keep-source
|
keep-source
|
||||||
|
stripe
|
||||||
|
class="ops-stripe-table"
|
||||||
>
|
>
|
||||||
<vxe-column field="attr_ids" title="属性" :edit-render="{}">
|
<vxe-column field="attr_ids" :title="$t('cmdb.ciType.attributes')" :edit-render="{}">
|
||||||
<template #default="{ row }">
|
<template #default="{ row }">
|
||||||
<template v-for="(attr, index) in row.attr_ids">
|
<template v-for="(attr, index) in row.attr_ids">
|
||||||
<span :key="attr" :style="{ color: '#2f54eb' }">{{ getDisplayName(attr) }}</span>
|
<span :key="attr" :style="{ color: '#2f54eb' }">{{ getDisplayName(attr) }}</span>
|
||||||
|
@ -37,9 +39,9 @@
|
||||||
</vxe-select>
|
</vxe-select>
|
||||||
</template>
|
</template>
|
||||||
</vxe-column>
|
</vxe-column>
|
||||||
<vxe-column filed="opeartion" title="操作" width="100">
|
<vxe-column filed="opeartion" :title="$t('operation')" width="100">
|
||||||
<template #default="{ row }">
|
<template #default="{ row }">
|
||||||
<template v-if="$refs.xTable.isActiveByRow(row)">
|
<template v-if="$refs.xTable.getVxetableRef().isActiveByRow(row)">
|
||||||
<a-space>
|
<a-space>
|
||||||
<a> <a-icon @click="saveRowEvent(row)" type="save"/></a>
|
<a> <a-icon @click="saveRowEvent(row)" type="save"/></a>
|
||||||
</a-space>
|
</a-space>
|
||||||
|
@ -47,14 +49,14 @@
|
||||||
<template v-else>
|
<template v-else>
|
||||||
<a-space>
|
<a-space>
|
||||||
<a> <a-icon @click="editRowEvent(row)" type="edit"/></a>
|
<a> <a-icon @click="editRowEvent(row)" type="edit"/></a>
|
||||||
<a-popconfirm title="确认删除?" @confirm="removeRowEvent(row)">
|
<a-popconfirm :title="$t('cmdb.ciType.confirmDelete2')" @confirm="removeRowEvent(row)">
|
||||||
<a :style="{ color: 'red' }"> <a-icon type="delete"/></a>
|
<a :style="{ color: 'red' }"> <a-icon type="delete"/></a>
|
||||||
</a-popconfirm>
|
</a-popconfirm>
|
||||||
</a-space>
|
</a-space>
|
||||||
</template>
|
</template>
|
||||||
</template>
|
</template>
|
||||||
</vxe-column>
|
</vxe-column>
|
||||||
</vxe-table>
|
</ops-table>
|
||||||
</a-modal>
|
</a-modal>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
@ -98,7 +100,7 @@ export default {
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
async handleAddUnique(row) {
|
async handleAddUnique(row) {
|
||||||
const $table = this.$refs.xTable
|
const $table = this.$refs.xTable.getVxetableRef()
|
||||||
const record = {
|
const record = {
|
||||||
attr_ids: [],
|
attr_ids: [],
|
||||||
}
|
}
|
||||||
|
@ -106,7 +108,7 @@ export default {
|
||||||
await $table.setActiveRow(newRow)
|
await $table.setActiveRow(newRow)
|
||||||
},
|
},
|
||||||
saveRowEvent(row) {
|
saveRowEvent(row) {
|
||||||
const $table = this.$refs.xTable
|
const $table = this.$refs.xTable.getVxetableRef()
|
||||||
$table.clearActived().then(() => {
|
$table.clearActived().then(() => {
|
||||||
if (row.id) {
|
if (row.id) {
|
||||||
updateUniqueConstraint(this.CITypeId, row.id, { attr_ids: row.attr_ids }).then((res) => {
|
updateUniqueConstraint(this.CITypeId, row.id, { attr_ids: row.attr_ids }).then((res) => {
|
||||||
|
@ -120,12 +122,12 @@ export default {
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
editRowEvent(row) {
|
editRowEvent(row) {
|
||||||
const $table = this.$refs.xTable
|
const $table = this.$refs.xTable.getVxetableRef()
|
||||||
$table.setActiveRow(row)
|
$table.setActiveRow(row)
|
||||||
},
|
},
|
||||||
removeRowEvent(row) {
|
removeRowEvent(row) {
|
||||||
deleteUniqueConstraint(this.CITypeId, row.id).then((res) => {
|
deleteUniqueConstraint(this.CITypeId, row.id).then((res) => {
|
||||||
this.$message.success('删除成功!')
|
this.$message.success(this.$t('deleteSuccess'))
|
||||||
this.getTableList()
|
this.getTableList()
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
|
@ -53,7 +53,7 @@
|
||||||
<span>{{ row[`key${index}`] }}</span>
|
<span>{{ row[`key${index}`] }}</span>
|
||||||
</template>
|
</template>
|
||||||
</vxe-column>
|
</vxe-column>
|
||||||
<vxe-column field="value" title="数量"></vxe-column>
|
<vxe-column field="value" :title="$t('cmdb.custom_dashboard.quantity')"></vxe-column>
|
||||||
</template>
|
</template>
|
||||||
</vxe-table>
|
</vxe-table>
|
||||||
<div
|
<div
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,7 +1,9 @@
|
||||||
|
import i18n from '@/lang'
|
||||||
|
|
||||||
export const category_1_bar_options = (data, options) => {
|
export const category_1_bar_options = (data, options) => {
|
||||||
// 计算一级分类
|
// Calculate first level classification
|
||||||
const xData = Object.keys(data)
|
const xData = Object.keys(data)
|
||||||
// 计算共有多少二级分类
|
// Calculate how many secondary categories there are
|
||||||
const secondCategory = {}
|
const secondCategory = {}
|
||||||
Object.keys(data).forEach(key => {
|
Object.keys(data).forEach(key => {
|
||||||
if (Object.prototype.toString.call(data[key]) === '[object Object]') {
|
if (Object.prototype.toString.call(data[key]) === '[object Object]') {
|
||||||
|
@ -9,7 +11,7 @@ export const category_1_bar_options = (data, options) => {
|
||||||
secondCategory[key1] = Array.from({ length: xData.length }).fill(0)
|
secondCategory[key1] = Array.from({ length: xData.length }).fill(0)
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
secondCategory['其他'] = Array.from({ length: xData.length }).fill(0)
|
secondCategory[i18n.t('other')] = Array.from({ length: xData.length }).fill(0)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
Object.keys(secondCategory).forEach(key => {
|
Object.keys(secondCategory).forEach(key => {
|
||||||
|
@ -18,7 +20,7 @@ export const category_1_bar_options = (data, options) => {
|
||||||
secondCategory[key][idx] = data[x][key]
|
secondCategory[key][idx] = data[x][key]
|
||||||
}
|
}
|
||||||
if (typeof data[x] === 'number') {
|
if (typeof data[x] === 'number') {
|
||||||
secondCategory['其他'][idx] = data[x]
|
secondCategory[i18n.t('other')][idx] = data[x]
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
@ -121,7 +123,7 @@ export const category_1_line_options = (data, options) => {
|
||||||
}, {
|
}, {
|
||||||
offset: 1, color: '#ffffff' // 100% 处的颜色
|
offset: 1, color: '#ffffff' // 100% 处的颜色
|
||||||
}],
|
}],
|
||||||
global: false // 缺省为 false
|
global: false // default is false
|
||||||
}
|
}
|
||||||
} : null
|
} : null
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,8 @@
|
||||||
export const dashboardCategory = {
|
import i18n from '@/lang'
|
||||||
1: { label: '默认' },
|
|
||||||
2: { label: '关系' }
|
export const dashboardCategory = () => {
|
||||||
|
return {
|
||||||
|
1: { label: i18n.t('cmdb.custom_dashboard.default') },
|
||||||
|
2: { label: i18n.t('cmdb.custom_dashboard.relation') }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
type="primary"
|
type="primary"
|
||||||
icon="plus-circle"
|
icon="plus-circle"
|
||||||
class="ops-button-primary"
|
class="ops-button-primary"
|
||||||
>新增图表</a-button
|
>{{ $t('cmdb.custom_dashboard.newChart') }}</a-button
|
||||||
>
|
>
|
||||||
</div>
|
</div>
|
||||||
<GridLayout
|
<GridLayout
|
||||||
|
@ -78,10 +78,10 @@
|
||||||
></a>
|
></a>
|
||||||
<a-menu slot="overlay">
|
<a-menu slot="overlay">
|
||||||
<a-menu-item>
|
<a-menu-item>
|
||||||
<a @click="() => openChartForm('edit', item)"><a-icon style="margin-right:5px" type="edit" />编辑</a>
|
<a @click="() => openChartForm('edit', item)"><a-icon style="margin-right:5px" type="edit" />{{ $t('edit') }}</a>
|
||||||
</a-menu-item>
|
</a-menu-item>
|
||||||
<a-menu-item>
|
<a-menu-item>
|
||||||
<a @click="deleteChart(item)"><a-icon style="margin-right:5px" type="delete" />删除</a>
|
<a @click="deleteChart(item)"><a-icon style="margin-right:5px" type="delete" />{{ $t('delete') }}</a>
|
||||||
</a-menu-item>
|
</a-menu-item>
|
||||||
</a-menu>
|
</a-menu>
|
||||||
</a-dropdown>
|
</a-dropdown>
|
||||||
|
@ -116,7 +116,7 @@
|
||||||
>
|
>
|
||||||
定制仪表盘
|
定制仪表盘
|
||||||
</a-button>
|
</a-button>
|
||||||
<span v-else>管理员暂未定制仪表盘</span>
|
<span v-else>{{ $t('cmdb.custom_dashboard.noCustomDashboard') }}</span>
|
||||||
</div>
|
</div>
|
||||||
<ChartForm ref="chartForm" @refresh="refresh" :ci_types="ci_types" :totalData="totalData" />
|
<ChartForm ref="chartForm" @refresh="refresh" :ci_types="ci_types" :totalData="totalData" />
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -32,7 +32,7 @@
|
||||||
/></a>
|
/></a>
|
||||||
</a-space>
|
</a-space>
|
||||||
<a v-else @click="handleEdit"><a-icon type="eye"/></a>
|
<a v-else @click="handleEdit"><a-icon type="eye"/></a>
|
||||||
<span>{{ rule.is_plugin ? 'Plugin' : '默认' }}</span>
|
<span>{{ rule.is_plugin ? 'Plugin' : $t('cmdb.custom_dashboard.default') }}</span>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</div>
|
</div>
|
||||||
|
@ -57,7 +57,7 @@ export default {
|
||||||
return this.rule?.option?.icon ?? { color: '', name: 'caise-wuliji' }
|
return this.rule?.option?.icon ?? { color: '', name: 'caise-wuliji' }
|
||||||
},
|
},
|
||||||
isDeletable() {
|
isDeletable() {
|
||||||
return !['物理机', '虚拟机', '网卡', '硬盘', 'server', 'vserver', 'NIC', 'harddisk'].includes(this.rule.name)
|
return ![this.$t('cmdb.ad.server'), this.$t('cmdb.ad.vserver'), this.$t('cmdb.ad.nic'), this.$t('cmdb.ad.disk'), 'server', 'vserver', 'NIC', 'harddisk'].includes(this.rule.name)
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
inject: {
|
inject: {
|
||||||
|
|
|
@ -1,344 +1,298 @@
|
||||||
<template>
|
<template>
|
||||||
<CustomDrawer width="800px" :title="title" :visible="visible" @close="handleClose">
|
<CustomDrawer width="800px" :title="title" :visible="visible" @close="handleClose">
|
||||||
<template v-if="adType === 'agent'">
|
<template v-if="adType === 'agent'">
|
||||||
<a-form-model
|
<a-form-model
|
||||||
ref="autoDiscoveryForm"
|
ref="autoDiscoveryForm"
|
||||||
:model="form"
|
:model="form"
|
||||||
:rules="rules"
|
:rules="rules"
|
||||||
:label-col="{ span: 2 }"
|
:label-col="{ span: 2 }"
|
||||||
:wrapper-col="{ span: 20 }"
|
:wrapper-col="{ span: 20 }"
|
||||||
>
|
>
|
||||||
<a-divider :style="{ margin: '5px 0' }">基础设置</a-divider>
|
<a-divider :style="{ margin: '5px 0' }">{{ $t('cmdb.ciType.basicConfig') }}</a-divider>
|
||||||
<a-form-model-item label="名称" prop="name">
|
<a-form-model-item :label="$t('name')" prop="name">
|
||||||
<a-input v-model="form.name" />
|
<a-input v-model="form.name" />
|
||||||
</a-form-model-item>
|
</a-form-model-item>
|
||||||
<a-form-model-item label="图标" v-if="is_inner">
|
<a-form-model-item :label="$t('icon')" v-if="is_inner">
|
||||||
<CustomIconSelect v-model="customIcon" :style="{ marginTop: '6px' }" />
|
<CustomIconSelect v-model="customIcon" :style="{ marginTop: '6px' }" />
|
||||||
</a-form-model-item>
|
</a-form-model-item>
|
||||||
<a-form-model-item label="模式" prop="is_plugin">
|
<a-form-model-item :label="$t('cmdb.ad.mode')" prop="is_plugin">
|
||||||
<a-radio-group v-model="form.is_plugin" @change="changeIsPlugin" :disabled="!is_inner">
|
<a-radio-group v-model="form.is_plugin" @change="changeIsPlugin" :disabled="!is_inner">
|
||||||
<a-radio :value="false">默认</a-radio>
|
<a-radio :value="false">{{ $t('cmdb.custom_dashboard.default') }}</a-radio>
|
||||||
<a-radio :value="true">plugin</a-radio>
|
<a-radio :value="true">plugin</a-radio>
|
||||||
</a-radio-group>
|
</a-radio-group>
|
||||||
</a-form-model-item>
|
</a-form-model-item>
|
||||||
</a-form-model>
|
</a-form-model>
|
||||||
<a-divider :style="{ margin: '5px 0' }">采集设置</a-divider>
|
<a-divider :style="{ margin: '5px 0' }">{{ $t('cmdb.ad.collectSettings') }}</a-divider>
|
||||||
<CustomCodeMirror
|
<CustomCodeMirror
|
||||||
codeMirrorId="cmdb-adt"
|
codeMirrorId="cmdb-adt"
|
||||||
v-if="form.is_plugin"
|
v-if="form.is_plugin"
|
||||||
ref="codemirror"
|
ref="codemirror"
|
||||||
@changeCodeContent="changeCodeContent"
|
@changeCodeContent="changeCodeContent"
|
||||||
></CustomCodeMirror>
|
></CustomCodeMirror>
|
||||||
<div style="margin:10px 0;text-align:right;">
|
<div style="margin:10px 0;text-align:right;">
|
||||||
<a-button
|
<a-button
|
||||||
v-show="form.is_plugin"
|
v-show="form.is_plugin"
|
||||||
size="small"
|
size="small"
|
||||||
type="primary"
|
type="primary"
|
||||||
ghost
|
ghost
|
||||||
@click="handleSubmit(true)"
|
@click="handleSubmit(true)"
|
||||||
>更新字段</a-button
|
>{{ $t('cmdb.ad.updateFields') }}</a-button
|
||||||
>
|
>
|
||||||
</div>
|
</div>
|
||||||
<a-button
|
<a-button
|
||||||
v-show="!form.is_plugin"
|
v-show="!form.is_plugin"
|
||||||
size="small"
|
size="small"
|
||||||
type="primary"
|
type="primary"
|
||||||
ghost
|
ghost
|
||||||
icon="plus"
|
icon="plus"
|
||||||
:style="{ marginBottom: '10px' }"
|
:style="{ marginBottom: '10px' }"
|
||||||
@click="insertEvent(-1)"
|
@click="insertEvent(-1)"
|
||||||
>新增</a-button
|
>{{ $t('new') }}</a-button
|
||||||
>
|
>
|
||||||
<vxe-table
|
<vxe-table
|
||||||
size="mini"
|
size="mini"
|
||||||
stripe
|
stripe
|
||||||
class="ops-stripe-table"
|
class="ops-stripe-table"
|
||||||
show-overflow
|
show-overflow
|
||||||
keep-source
|
keep-source
|
||||||
ref="xTable"
|
ref="xTable"
|
||||||
max-height="400"
|
max-height="400"
|
||||||
:data="tableData"
|
:data="tableData"
|
||||||
:edit-config="{ trigger: 'manual', mode: 'row' }"
|
:edit-config="{ trigger: 'manual', mode: 'row' }"
|
||||||
>
|
>
|
||||||
<vxe-column field="name" title="名称" :edit-render="{ autofocus: '.vxe-input--inner' }">
|
<vxe-column field="name" :title="$t('name')" :edit-render="{ autofocus: '.vxe-input--inner' }">
|
||||||
<template #edit="{ row }">
|
<template #edit="{ row }">
|
||||||
<vxe-input v-model="row.name" type="text"></vxe-input>
|
<vxe-input v-model="row.name" type="text"></vxe-input>
|
||||||
</template>
|
</template>
|
||||||
</vxe-column>
|
</vxe-column>
|
||||||
<vxe-column field="type" title="类型" :edit-render="{}">
|
<vxe-column field="type" :title="$t('type')" :edit-render="{}">
|
||||||
<template #edit="{ row }">
|
<template #edit="{ row }">
|
||||||
<vxe-select v-model="row.type" transfer>
|
<vxe-select v-model="row.type" transfer>
|
||||||
<vxe-option v-for="item in typeList" :key="item" :value="item" :label="item"></vxe-option>
|
<vxe-option v-for="item in typeList" :key="item" :value="item" :label="item"></vxe-option>
|
||||||
</vxe-select>
|
</vxe-select>
|
||||||
</template>
|
</template>
|
||||||
</vxe-column>
|
</vxe-column>
|
||||||
<vxe-column field="desc" title="描述" :edit-render="{ autofocus: '.vxe-input--inner' }">
|
<vxe-column field="desc" :title="$t('desc')" :edit-render="{ autofocus: '.vxe-input--inner' }">
|
||||||
<template #edit="{ row }">
|
<template #edit="{ row }">
|
||||||
<vxe-input v-model="row.desc" type="text"></vxe-input>
|
<vxe-input v-model="row.desc" type="text"></vxe-input>
|
||||||
</template>
|
</template>
|
||||||
</vxe-column>
|
</vxe-column>
|
||||||
<vxe-column title="操作" width="60" v-if="!form.is_plugin">
|
<vxe-column :title="$t('operation')" width="60" v-if="!form.is_plugin">
|
||||||
<template #default="{ row }">
|
<template #default="{ row }">
|
||||||
<a-space v-if="$refs.xTable.isActiveByRow(row)">
|
<a-space v-if="$refs.xTable.isActiveByRow(row)">
|
||||||
<a @click="saveRowEvent(row)"><a-icon type="save"/></a>
|
<a @click="saveRowEvent(row)"><a-icon type="save"/></a>
|
||||||
<a @click="cancelRowEvent(row)"><a-icon type="close"/></a>
|
<a @click="cancelRowEvent(row)"><a-icon type="close"/></a>
|
||||||
</a-space>
|
</a-space>
|
||||||
<a-space v-else>
|
<a-space v-else>
|
||||||
<a @click="editRowEvent(row)"><a-icon type="edit"/></a>
|
<a @click="editRowEvent(row)"><a-icon type="edit"/></a>
|
||||||
<a :style="{ color: 'red' }" @click="deleteRowEvent(row)"><a-icon type="delete"/></a>
|
<a :style="{ color: 'red' }" @click="deleteRowEvent(row)"><a-icon type="delete"/></a>
|
||||||
</a-space>
|
</a-space>
|
||||||
</template>
|
</template>
|
||||||
</vxe-column>
|
</vxe-column>
|
||||||
</vxe-table>
|
</vxe-table>
|
||||||
|
|
||||||
<div class="custom-drawer-bottom-action">
|
<div class="custom-drawer-bottom-action">
|
||||||
<a-button @click="handleClose">取消</a-button>
|
<a-button @click="handleClose">{{ $t('cancel') }}</a-button>
|
||||||
<a-button @click="handleSubmit(false)" type="primary">保存</a-button>
|
<a-button @click="handleSubmit(false)" type="primary">{{ $t('save') }}</a-button>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<template v-else>
|
<template v-else>
|
||||||
<HttpSnmpAD ref="httpSnmpAd" :ruleType="adType" :ruleName="ruleData.name" />
|
<HttpSnmpAD ref="httpSnmpAd" :ruleType="adType" :ruleName="ruleData.name" />
|
||||||
</template>
|
</template>
|
||||||
</CustomDrawer>
|
</CustomDrawer>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import CustomIconSelect from '@/components/CustomIconSelect'
|
import CustomIconSelect from '@/components/CustomIconSelect'
|
||||||
import { postDiscovery, putDiscovery } from '../../api/discovery'
|
import { postDiscovery, putDiscovery } from '../../api/discovery'
|
||||||
import HttpSnmpAD from '../../components/httpSnmpAD'
|
import HttpSnmpAD from '../../components/httpSnmpAD'
|
||||||
import CustomCodeMirror from '@/components/CustomCodeMirror'
|
import CustomCodeMirror from '@/components/CustomCodeMirror'
|
||||||
import 'codemirror/lib/codemirror.css'
|
import 'codemirror/lib/codemirror.css'
|
||||||
import 'codemirror/theme/monokai.css'
|
import 'codemirror/theme/monokai.css'
|
||||||
export default {
|
export default {
|
||||||
name: 'EditDrawer',
|
name: 'EditDrawer',
|
||||||
components: { CustomIconSelect, CustomCodeMirror, HttpSnmpAD },
|
components: { CustomIconSelect, CustomCodeMirror, HttpSnmpAD },
|
||||||
props: {
|
props: {
|
||||||
is_inner: {
|
is_inner: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: true,
|
default: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
const default_plugin_script = `# -*- coding:utf-8 -*-
|
const default_plugin_script = this.$t('cmdb.ad.pluginScript')
|
||||||
|
const typeList = ['String', 'Integer', 'Float', 'Date', 'DateTime', 'Time', 'JSON']
|
||||||
import json
|
return {
|
||||||
|
default_plugin_script,
|
||||||
|
typeList,
|
||||||
class AutoDiscovery(object):
|
visible: false,
|
||||||
|
ruleData: {},
|
||||||
@property
|
type: 'add',
|
||||||
def unique_key(self):
|
adType: '',
|
||||||
"""
|
form: { name: '', is_plugin: false },
|
||||||
|
rules: {},
|
||||||
:return: 返回唯一属性的名字
|
customIcon: { name: '', color: '' },
|
||||||
"""
|
tableData: [],
|
||||||
return
|
editDefaultTableData: [],
|
||||||
|
plugin_script: '',
|
||||||
@staticmethod
|
cmOptions: {
|
||||||
def attributes():
|
lineNumbers: true,
|
||||||
"""
|
mode: 'python',
|
||||||
定义属性字段
|
height: '200px',
|
||||||
:return: 返回属性字段列表, 列表项是(名称, 类型, 描述), 名称必须是英文
|
theme: 'monokai',
|
||||||
类型: String Integer Float Date DateTime Time JSON
|
tabSize: 4,
|
||||||
例如:
|
lineWrapping: true,
|
||||||
return [
|
},
|
||||||
("ci_type", "String", "模型名称"),
|
}
|
||||||
("private_ip", "String", "内网IP, 多值逗号分隔")
|
},
|
||||||
]
|
computed: {
|
||||||
"""
|
title() {
|
||||||
return []
|
if (this.adType === 'http' || this.adType === 'snmp') {
|
||||||
|
return this.ruleData.name
|
||||||
@staticmethod
|
}
|
||||||
def run():
|
if (this.type === 'edit') {
|
||||||
"""
|
return this.$t('edit') + `:${this.ruleData.name}`
|
||||||
执行入口, 返回采集的属性值
|
}
|
||||||
:return: 返回一个列表, 列表项是字典, 字典key是属性名称, value是属性值
|
return this.$t('new')
|
||||||
例如:
|
},
|
||||||
return [dict(ci_type="server", private_ip="192.168.1.1")]
|
},
|
||||||
"""
|
inject: {
|
||||||
return []
|
getDiscovery: {
|
||||||
|
from: 'getDiscovery',
|
||||||
|
default: () => {},
|
||||||
if __name__ == "__main__":
|
},
|
||||||
result = AutoDiscovery().run()
|
},
|
||||||
if isinstance(result, list):
|
methods: {
|
||||||
print("AutoDiscovery::Result::{}".format(json.dumps(result)))
|
open(data, type, adType) {
|
||||||
else:
|
this.visible = true
|
||||||
print("ERROR: 采集返回必须是列表")
|
this.type = type
|
||||||
`
|
this.ruleData = data
|
||||||
const typeList = ['String', 'Integer', 'Float', 'Date', 'DateTime', 'Time', 'JSON']
|
this.adType = adType
|
||||||
return {
|
if (!this.is_inner) {
|
||||||
default_plugin_script,
|
this.form = {
|
||||||
typeList,
|
name: '',
|
||||||
visible: false,
|
is_plugin: true,
|
||||||
ruleData: {},
|
}
|
||||||
type: 'add',
|
}
|
||||||
adType: '',
|
if (adType === 'http' || adType === 'snmp') {
|
||||||
form: { name: '', is_plugin: false },
|
return
|
||||||
rules: {},
|
}
|
||||||
customIcon: { name: '', color: '' },
|
this.$nextTick(() => {
|
||||||
tableData: [],
|
if (this.type === 'edit') {
|
||||||
editDefaultTableData: [],
|
this.form = {
|
||||||
plugin_script: '',
|
name: data.name,
|
||||||
cmOptions: {
|
is_plugin: data.is_plugin,
|
||||||
lineNumbers: true,
|
}
|
||||||
mode: 'python',
|
this.customIcon = data?.option?.icon ?? { name: 'caise-chajian', color: '' }
|
||||||
height: '200px',
|
this.tableData = data?.attributes ?? []
|
||||||
theme: 'monokai',
|
this.editDefaultTableData = data?.attributes ?? []
|
||||||
tabSize: 4,
|
this.plugin_script = data?.plugin_script ?? this.default_plugin_script
|
||||||
lineWrapping: true,
|
}
|
||||||
},
|
if (this.type === 'add') {
|
||||||
}
|
this.customIcon = { name: 'caise-chajian', color: '' }
|
||||||
},
|
// eslint-disable-next-line no-useless-escape
|
||||||
computed: {
|
this.plugin_script = this.default_plugin_script
|
||||||
title() {
|
}
|
||||||
if (this.adType === 'http' || this.adType === 'snmp') {
|
if (data?.is_plugin || !this.is_inner) {
|
||||||
return this.ruleData.name
|
this.$nextTick(() => {
|
||||||
}
|
this.$refs.codemirror.initCodeMirror(this.plugin_script)
|
||||||
if (this.type === 'edit') {
|
})
|
||||||
return `编辑:${this.ruleData.name}`
|
}
|
||||||
}
|
})
|
||||||
return '新建'
|
},
|
||||||
},
|
handleClose() {
|
||||||
},
|
this.tableData = []
|
||||||
inject: {
|
this.customIcon = { name: '', color: '' }
|
||||||
getDiscovery: {
|
this.form = { name: '', is_plugin: false }
|
||||||
from: 'getDiscovery',
|
if (this.adType === 'agent') {
|
||||||
default: () => {},
|
this.$refs.autoDiscoveryForm.clearValidate()
|
||||||
},
|
} else {
|
||||||
},
|
// this.$refs.httpSnmpAd.currentCate = ''
|
||||||
methods: {
|
}
|
||||||
open(data, type, adType) {
|
this.visible = false
|
||||||
this.visible = true
|
},
|
||||||
this.type = type
|
async insertEvent(row) {
|
||||||
this.ruleData = data
|
const $table = this.$refs.xTable
|
||||||
this.adType = adType
|
const record = {}
|
||||||
if (!this.is_inner) {
|
const { row: newRow } = await $table.insertAt(record, row)
|
||||||
this.form = {
|
await $table.setEditRow(newRow)
|
||||||
name: '',
|
},
|
||||||
is_plugin: true,
|
editRowEvent(row) {
|
||||||
}
|
const $table = this.$refs.xTable
|
||||||
}
|
$table.setActiveRow(row)
|
||||||
if (adType === 'http' || adType === 'snmp') {
|
},
|
||||||
return
|
saveRowEvent() {
|
||||||
}
|
const $table = this.$refs.xTable
|
||||||
this.$nextTick(() => {
|
$table.clearActived().then(() => {
|
||||||
if (this.type === 'edit') {
|
this.loading = true
|
||||||
this.form = {
|
setTimeout(() => {
|
||||||
name: data.name,
|
this.loading = false
|
||||||
is_plugin: data.is_plugin,
|
}, 300)
|
||||||
}
|
})
|
||||||
this.customIcon = data?.option?.icon ?? { name: 'caise-chajian', color: '' }
|
},
|
||||||
this.tableData = data?.attributes ?? []
|
cancelRowEvent(row) {
|
||||||
this.editDefaultTableData = data?.attributes ?? []
|
const $table = this.$refs.xTable
|
||||||
this.plugin_script = data?.plugin_script ?? this.default_plugin_script
|
$table.clearActived().then(() => {
|
||||||
}
|
// Restore row data
|
||||||
if (this.type === 'add') {
|
$table.revertData(row)
|
||||||
this.customIcon = { name: 'caise-chajian', color: '' }
|
})
|
||||||
// eslint-disable-next-line no-useless-escape
|
},
|
||||||
this.plugin_script = this.default_plugin_script
|
deleteRowEvent(row) {
|
||||||
}
|
const $table = this.$refs.xTable
|
||||||
if (data?.is_plugin || !this.is_inner) {
|
$table.remove(row)
|
||||||
this.$nextTick(() => {
|
},
|
||||||
this.$refs.codemirror.initCodeMirror(this.plugin_script)
|
async handleSubmit(isUpdateAttr = false) {
|
||||||
})
|
const $table = this.$refs.xTable
|
||||||
}
|
const { fullData: _tableData } = $table.getTableData()
|
||||||
})
|
console.log(_tableData)
|
||||||
},
|
const params = {
|
||||||
handleClose() {
|
...this.form,
|
||||||
this.tableData = []
|
type: this.adType,
|
||||||
this.customIcon = { name: '', color: '' }
|
is_inner: this.is_inner,
|
||||||
this.form = { name: '', is_plugin: false }
|
option: { icon: this.customIcon },
|
||||||
if (this.adType === 'agent') {
|
attributes: this.form.is_plugin
|
||||||
this.$refs.autoDiscoveryForm.clearValidate()
|
? undefined
|
||||||
} else {
|
: _tableData.map(({ name, alias, desc, type }) => {
|
||||||
// this.$refs.httpSnmpAd.currentCate = ''
|
return { name, alias, desc, type }
|
||||||
}
|
}),
|
||||||
this.visible = false
|
plugin_script: this.form.is_plugin ? this.plugin_script : undefined,
|
||||||
},
|
}
|
||||||
async insertEvent(row) {
|
let res
|
||||||
const $table = this.$refs.xTable
|
if (this.type === 'add') {
|
||||||
const record = {}
|
res = await postDiscovery(params)
|
||||||
const { row: newRow } = await $table.insertAt(record, row)
|
} else {
|
||||||
await $table.setEditRow(newRow)
|
res = await putDiscovery(this.ruleData.id, params)
|
||||||
},
|
}
|
||||||
editRowEvent(row) {
|
if (isUpdateAttr) {
|
||||||
const $table = this.$refs.xTable
|
this.tableData = res.attributes
|
||||||
$table.setActiveRow(row)
|
this.type = 'edit'
|
||||||
},
|
this.ruleData = res
|
||||||
saveRowEvent() {
|
this.$message.success(this.$t('updateSuccess'))
|
||||||
const $table = this.$refs.xTable
|
if (this.is_inner) {
|
||||||
$table.clearActived().then(() => {
|
this.getDiscovery()
|
||||||
this.loading = true
|
}
|
||||||
setTimeout(() => {
|
return
|
||||||
this.loading = false
|
}
|
||||||
}, 300)
|
this.handleClose()
|
||||||
})
|
console.log(this.is_inner)
|
||||||
},
|
if (this.is_inner) {
|
||||||
cancelRowEvent(row) {
|
this.$message.success(this.$t('saveSuccess'))
|
||||||
const $table = this.$refs.xTable
|
this.getDiscovery()
|
||||||
$table.clearActived().then(() => {
|
} else {
|
||||||
// 还原行数据
|
this.$emit('updateNotInner', res)
|
||||||
$table.revertData(row)
|
}
|
||||||
})
|
},
|
||||||
},
|
changeIsPlugin(e) {
|
||||||
deleteRowEvent(row) {
|
if (e.target.value) {
|
||||||
const $table = this.$refs.xTable
|
this.$nextTick(() => {
|
||||||
$table.remove(row)
|
this.$refs.codemirror.initCodeMirror(this.plugin_script)
|
||||||
},
|
})
|
||||||
async handleSubmit(isUpdateAttr = false) {
|
}
|
||||||
const $table = this.$refs.xTable
|
},
|
||||||
const { fullData: _tableData } = $table.getTableData()
|
changeCodeContent(value) {
|
||||||
console.log(_tableData)
|
this.plugin_script = value && value.replace('\t', ' ')
|
||||||
const params = {
|
},
|
||||||
...this.form,
|
},
|
||||||
type: this.adType,
|
}
|
||||||
is_inner: this.is_inner,
|
</script>
|
||||||
option: { icon: this.customIcon },
|
|
||||||
attributes: this.form.is_plugin
|
<style></style>
|
||||||
? undefined
|
|
||||||
: _tableData.map(({ name, alias, desc, type }) => {
|
|
||||||
return { name, alias, desc, type }
|
|
||||||
}),
|
|
||||||
plugin_script: this.form.is_plugin ? this.plugin_script : undefined,
|
|
||||||
}
|
|
||||||
let res
|
|
||||||
if (this.type === 'add') {
|
|
||||||
res = await postDiscovery(params)
|
|
||||||
} else {
|
|
||||||
res = await putDiscovery(this.ruleData.id, params)
|
|
||||||
}
|
|
||||||
if (isUpdateAttr) {
|
|
||||||
this.tableData = res.attributes
|
|
||||||
this.type = 'edit'
|
|
||||||
this.ruleData = res
|
|
||||||
this.$message.success('更新成功!')
|
|
||||||
if (this.is_inner) {
|
|
||||||
this.getDiscovery()
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
this.handleClose()
|
|
||||||
console.log(this.is_inner)
|
|
||||||
if (this.is_inner) {
|
|
||||||
this.$message.success('保存成功!')
|
|
||||||
this.getDiscovery()
|
|
||||||
} else {
|
|
||||||
this.$emit('updateNotInner', res)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
changeIsPlugin(e) {
|
|
||||||
if (e.target.value) {
|
|
||||||
this.$nextTick(() => {
|
|
||||||
this.$refs.codemirror.initCodeMirror(this.plugin_script)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
},
|
|
||||||
changeCodeContent(value) {
|
|
||||||
this.plugin_script = value && value.replace('\t', ' ')
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style></style>
|
|
||||||
|
|
|
@ -3,9 +3,9 @@
|
||||||
<div :style="{ textAlign: 'right' }">
|
<div :style="{ textAlign: 'right' }">
|
||||||
<a-space v-if="!isSelected">
|
<a-space v-if="!isSelected">
|
||||||
<a-upload name="file" :multiple="false" accept=".json" :fileList="[]" :beforeUpload="beforeUpload">
|
<a-upload name="file" :multiple="false" accept=".json" :fileList="[]" :beforeUpload="beforeUpload">
|
||||||
<a><a-icon type="upload" />规则导入</a>
|
<a><a-icon type="upload" />{{ $t('cmdb.ad.upload') }}</a>
|
||||||
</a-upload>
|
</a-upload>
|
||||||
<a @click="download"><a-icon type="download" />规则导出</a>
|
<a @click="download"><a-icon type="download" />{{ $t('cmdb.ad.download') }}</a>
|
||||||
</a-space>
|
</a-space>
|
||||||
</div>
|
</div>
|
||||||
<div v-for="{ type, label } in typeCategory" :key="type">
|
<div v-for="{ type, label } in typeCategory" :key="type">
|
||||||
|
@ -45,22 +45,26 @@ export default {
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
typeCategory: [
|
typeCategoryChildren: { agent: [], snmp: [], http: [] },
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
typeCategory() {
|
||||||
|
return [
|
||||||
{
|
{
|
||||||
type: 'agent',
|
type: 'agent',
|
||||||
label: '内置 & 插件',
|
label: this.$t('cmdb.ad.agent'),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: 'snmp',
|
type: 'snmp',
|
||||||
label: '网络设备',
|
label: this.$t('cmdb.ad.snmp'),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: 'http',
|
type: 'http',
|
||||||
label: '公有云资源',
|
label: this.$t('cmdb.ad.http'),
|
||||||
},
|
},
|
||||||
],
|
]
|
||||||
typeCategoryChildren: { agent: [], snmp: [], http: [] },
|
},
|
||||||
}
|
|
||||||
},
|
},
|
||||||
provide() {
|
provide() {
|
||||||
return {
|
return {
|
||||||
|
@ -87,11 +91,11 @@ export default {
|
||||||
deleteRule(rule) {
|
deleteRule(rule) {
|
||||||
const that = this
|
const that = this
|
||||||
this.$confirm({
|
this.$confirm({
|
||||||
title: '警告',
|
title: that.$t('warning'),
|
||||||
content: `确认删除 【${rule.name}】?`,
|
content: that.$t('confirmDelete', { name: `${rule.name}` }),
|
||||||
onOk() {
|
onOk() {
|
||||||
deleteDiscovery(rule.id).then(() => {
|
deleteDiscovery(rule.id).then(() => {
|
||||||
that.$message.success('删除成功!')
|
that.$message.success(that.$t('deleteSuccess'))
|
||||||
that.getDiscovery()
|
that.getDiscovery()
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
@ -99,13 +103,14 @@ export default {
|
||||||
},
|
},
|
||||||
download() {
|
download() {
|
||||||
const x = new XMLHttpRequest()
|
const x = new XMLHttpRequest()
|
||||||
|
const that = this
|
||||||
x.open('GET', `/api/v0.1/adr/template/export/file`, true)
|
x.open('GET', `/api/v0.1/adr/template/export/file`, true)
|
||||||
x.responseType = 'blob'
|
x.responseType = 'blob'
|
||||||
x.onload = function(e) {
|
x.onload = function(e) {
|
||||||
const url = window.URL.createObjectURL(x.response)
|
const url = window.URL.createObjectURL(x.response)
|
||||||
const a = document.createElement('a')
|
const a = document.createElement('a')
|
||||||
a.href = url
|
a.href = url
|
||||||
a.download = `自动发现规则`
|
a.download = that.$t('cmdb.ad.rule')
|
||||||
a.click()
|
a.click()
|
||||||
}
|
}
|
||||||
x.send()
|
x.send()
|
||||||
|
@ -120,13 +125,13 @@ export default {
|
||||||
const state = Number(xhr.readyState)
|
const state = Number(xhr.readyState)
|
||||||
if (state === 4) {
|
if (state === 4) {
|
||||||
if (xhr.status === 200) {
|
if (xhr.status === 200) {
|
||||||
that.$message.success('上传成功')
|
that.$message.success(that.$t('uploadSuccess'))
|
||||||
that.getDiscovery()
|
that.getDiscovery()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
xhr.ontimeout = function() {
|
xhr.ontimeout = function() {
|
||||||
that.$httpError('超时错误')
|
that.$httpError(that.$t('cmdb.ad.timeout'))
|
||||||
}
|
}
|
||||||
|
|
||||||
xhr.send(formData)
|
xhr.send(formData)
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
<template #one>
|
<template #one>
|
||||||
<div v-for="group in ci_types_list" :key="group.id">
|
<div v-for="group in ci_types_list" :key="group.id">
|
||||||
<div>
|
<div>
|
||||||
<strong>{{ group.name || '其他' }}</strong
|
<strong>{{ group.name || $t('other') }}</strong
|
||||||
><span :style="{ color: 'rgb(195, 205, 215)' }">({{ group.ci_types.length }})</span>
|
><span :style="{ color: 'rgb(195, 205, 215)' }">({{ group.ci_types.length }})</span>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
|
@ -33,17 +33,17 @@
|
||||||
<template #two>
|
<template #two>
|
||||||
<div id="discovery-ci">
|
<div id="discovery-ci">
|
||||||
<a-input-search
|
<a-input-search
|
||||||
placeholder="请查找"
|
:placeholder="$t('cmdb.components.pleaseSearch')"
|
||||||
class="ops-input ops-input-radius"
|
class="ops-input ops-input-radius"
|
||||||
:style="{ width: '200px', marginRight: '20px', marginBottom: '10px' }"
|
:style="{ width: '200px', marginRight: '20px', marginBottom: '10px' }"
|
||||||
@search="handleSearch"
|
@search="handleSearch"
|
||||||
allowClear
|
allowClear
|
||||||
/>
|
/>
|
||||||
<div class="ops-list-batch-action" :style="{ marginBottom: '10px' }" v-show="!!selectedRowKeys.length">
|
<div class="ops-list-batch-action" :style="{ marginBottom: '10px' }" v-show="!!selectedRowKeys.length">
|
||||||
<span @click="batchAccept">入库</span>
|
<span @click="batchAccept">{{ $t('cmdb.ad.accept') }}</span>
|
||||||
<a-divider type="vertical" />
|
<a-divider type="vertical" />
|
||||||
<span @click="batchDelete">删除</span>
|
<span @click="batchDelete">{{ $t('delete') }}</span>
|
||||||
<span>选取:{{ selectedRowKeys.length }} 项</span>
|
<span>{{ $t('cmdb.ci.selectRows', { rows: selectedRowKeys.length }) }}</span>
|
||||||
</div>
|
</div>
|
||||||
<ops-table
|
<ops-table
|
||||||
show-overflow
|
show-overflow
|
||||||
|
@ -79,33 +79,33 @@
|
||||||
<vxe-column
|
<vxe-column
|
||||||
align="center"
|
align="center"
|
||||||
field="is_accept"
|
field="is_accept"
|
||||||
title="是否入库"
|
:title="$t('cmdb.ad.isAccpet')"
|
||||||
v-bind="columns.length ? { width: '100px' } : { minWidth: '100px' }"
|
v-bind="columns.length ? { width: '100px' } : { minWidth: '100px' }"
|
||||||
:filters="[
|
:filters="[
|
||||||
{ label: '是', value: true },
|
{ label: $t('yes'), value: true },
|
||||||
{ label: '否', value: false },
|
{ label: $t('no'), value: false },
|
||||||
]"
|
]"
|
||||||
>
|
>
|
||||||
<template #default="{row}">
|
<template #default="{row}">
|
||||||
{{ row.is_accept ? '是' : '否' }}
|
{{ row.is_accept ? $t('yes') : $t('no') }}
|
||||||
</template>
|
</template>
|
||||||
</vxe-column>
|
</vxe-column>
|
||||||
<vxe-column
|
<vxe-column
|
||||||
field="accept_by"
|
field="accept_by"
|
||||||
title="入库人"
|
:title="$t('cmdb.ad.accpetBy')"
|
||||||
v-bind="columns.length ? { width: '80px' } : { minWidth: '80px' }"
|
v-bind="columns.length ? { width: '80px' } : { minWidth: '80px' }"
|
||||||
:filters="[]"
|
:filters="[]"
|
||||||
></vxe-column>
|
></vxe-column>
|
||||||
<vxe-column
|
<vxe-column
|
||||||
field="accept_time"
|
field="accept_time"
|
||||||
title="入库时间"
|
:title="$t('cmdb.ad.acceptTime')"
|
||||||
sortable
|
sortable
|
||||||
v-bind="columns.length ? { width: '130px' } : { minWidth: '130px' }"
|
v-bind="columns.length ? { width: '130px' } : { minWidth: '130px' }"
|
||||||
></vxe-column>
|
></vxe-column>
|
||||||
<vxe-column title="操作" v-bind="columns.length ? { width: '60px' } : { minWidth: '60px' }" align="center">
|
<vxe-column :title="$t('operation')" v-bind="columns.length ? { width: '60px' } : { minWidth: '60px' }" align="center">
|
||||||
<template #default="{row}">
|
<template #default="{row}">
|
||||||
<a-space>
|
<a-space>
|
||||||
<a-tooltip title="入库">
|
<a-tooltip :title="$t('cmdb.ad.accept')">
|
||||||
<a v-if="!row.is_accept" @click="accept(row)"><ops-icon type="icon-xianxing-edit"/></a>
|
<a v-if="!row.is_accept" @click="accept(row)"><ops-icon type="icon-xianxing-edit"/></a>
|
||||||
</a-tooltip>
|
</a-tooltip>
|
||||||
<a :style="{ color: 'red' }" @click="deleteADC(row)"><ops-icon type="icon-xianxing-delete"/></a>
|
<a :style="{ color: 'red' }" @click="deleteADC(row)"><ops-icon type="icon-xianxing-delete"/></a>
|
||||||
|
@ -115,7 +115,7 @@
|
||||||
<template #empty>
|
<template #empty>
|
||||||
<div>
|
<div>
|
||||||
<img :style="{ width: '200px' }" :src="require('@/assets/data_empty.png')" />
|
<img :style="{ width: '200px' }" :src="require('@/assets/data_empty.png')" />
|
||||||
<div>暂无数据</div>
|
<div>{{ $t('noData') }}</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</ops-table>
|
</ops-table>
|
||||||
|
@ -242,11 +242,11 @@ export default {
|
||||||
this.$refs.xTable.getVxetableRef().clearCheckboxReserve()
|
this.$refs.xTable.getVxetableRef().clearCheckboxReserve()
|
||||||
const that = this
|
const that = this
|
||||||
this.$confirm({
|
this.$confirm({
|
||||||
title: '警告',
|
title: that.$t('warning'),
|
||||||
content: `确认入库?`,
|
content: that.$t('cmdb.ad.confirmAccept'),
|
||||||
onOk() {
|
onOk() {
|
||||||
updateADCAccept(row.id).then(() => {
|
updateADCAccept(row.id).then(() => {
|
||||||
that.$message.success('入库成功')
|
that.$message.success(that.$t('cmdb.ad.accpetSuccess'))
|
||||||
that.getAdc(false)
|
that.getAdc(false)
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
@ -258,11 +258,11 @@ export default {
|
||||||
this.$refs.xTable.getVxetableRef().clearCheckboxReserve()
|
this.$refs.xTable.getVxetableRef().clearCheckboxReserve()
|
||||||
const that = this
|
const that = this
|
||||||
this.$confirm({
|
this.$confirm({
|
||||||
title: '警告',
|
title: that.$t('warning'),
|
||||||
content: `确认删除该条数据?`,
|
content: that.$t('cmdb.ad.deleteADC'),
|
||||||
onOk() {
|
onOk() {
|
||||||
deleteAdc(row.id).then(() => {
|
deleteAdc(row.id).then(() => {
|
||||||
that.$message.success('删除成功')
|
that.$message.success(that.$t('deleteSuccess'))
|
||||||
that.getAdc(false)
|
that.getAdc(false)
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
@ -273,7 +273,7 @@ export default {
|
||||||
for (let i = 0; i < this.selectedRowKeys.length; i++) {
|
for (let i = 0; i < this.selectedRowKeys.length; i++) {
|
||||||
await updateADCAccept(this.selectedRowKeys[i])
|
await updateADCAccept(this.selectedRowKeys[i])
|
||||||
}
|
}
|
||||||
this.$message.success('入库成功')
|
this.$message.success(this.$t('cmdb.ad.acceptSuccess'))
|
||||||
this.getAdc(false)
|
this.getAdc(false)
|
||||||
this.selectedRowKeys = []
|
this.selectedRowKeys = []
|
||||||
this.$refs.xTable.getVxetableRef().clearCheckboxRow()
|
this.$refs.xTable.getVxetableRef().clearCheckboxRow()
|
||||||
|
@ -283,13 +283,13 @@ export default {
|
||||||
async batchDelete() {
|
async batchDelete() {
|
||||||
const that = this
|
const that = this
|
||||||
this.$confirm({
|
this.$confirm({
|
||||||
title: '警告',
|
title: that.$t('warning'),
|
||||||
content: `确认删除这些数据?`,
|
content: that.$t('cmdb.ad.batchDelete'),
|
||||||
async onOk() {
|
async onOk() {
|
||||||
for (let i = 0; i < that.selectedRowKeys.length; i++) {
|
for (let i = 0; i < that.selectedRowKeys.length; i++) {
|
||||||
await deleteAdc(that.selectedRowKeys[i])
|
await deleteAdc(that.selectedRowKeys[i])
|
||||||
}
|
}
|
||||||
that.$message.success('删除成功')
|
that.$message.success(that.$t('deleteSuccess'))
|
||||||
that.getAdc(false)
|
that.getAdc(false)
|
||||||
that.selectedRowKeys = []
|
that.selectedRowKeys = []
|
||||||
that.$refs.xTable.getVxetableRef().clearCheckboxRow()
|
that.$refs.xTable.getVxetableRef().clearCheckboxRow()
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="model-relation">
|
<div class="model-relation">
|
||||||
<a-button @click="handleCreate" type="primary" style="margin-bottom: 15px;" icon="plus">新增关系</a-button>
|
<a-button @click="handleCreate" type="primary" style="margin-bottom: 15px;" icon="plus">{{
|
||||||
|
$t('cmdb.ciType.addRelation')
|
||||||
|
}}</a-button>
|
||||||
<model-relation-table ref="table"></model-relation-table>
|
<model-relation-table ref="table"></model-relation-table>
|
||||||
<a-modal
|
<a-modal
|
||||||
:closable="false"
|
:closable="false"
|
||||||
|
@ -11,11 +13,14 @@
|
||||||
width="500px"
|
width="500px"
|
||||||
>
|
>
|
||||||
<a-form :form="form" @submit="handleSubmit" :label-col="{ span: 6 }" :wrapper-col="{ span: 14 }">
|
<a-form :form="form" @submit="handleSubmit" :label-col="{ span: 6 }" :wrapper-col="{ span: 14 }">
|
||||||
<a-form-item label="源模型">
|
<a-form-item :label="$t('cmdb.ciType.sourceCIType')">
|
||||||
<a-select
|
<a-select
|
||||||
showSearch
|
showSearch
|
||||||
name="source_ci_type_id"
|
name="source_ci_type_id"
|
||||||
v-decorator="['source_ci_type_id', { rules: [{ required: true, message: '请选择源模型' }] }]"
|
v-decorator="[
|
||||||
|
'source_ci_type_id',
|
||||||
|
{ rules: [{ required: true, message: $t('cmdb.ciType.sourceCITypeTips') }] },
|
||||||
|
]"
|
||||||
@change="handleSourceTypeChange"
|
@change="handleSourceTypeChange"
|
||||||
:filterOption="filterOption"
|
:filterOption="filterOption"
|
||||||
>
|
>
|
||||||
|
@ -24,11 +29,11 @@
|
||||||
}}</a-select-option>
|
}}</a-select-option>
|
||||||
</a-select>
|
</a-select>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-form-item label="目标模型">
|
<a-form-item :label="$t('cmdb.ciType.dstCIType')">
|
||||||
<a-select
|
<a-select
|
||||||
showSearch
|
showSearch
|
||||||
name="ci_type_id"
|
name="ci_type_id"
|
||||||
v-decorator="['ci_type_id', { rules: [{ required: true, message: '请选择目标模型' }] }]"
|
v-decorator="['ci_type_id', { rules: [{ required: true, message: $t('cmdb.ciType.dstCITypeTips') }] }]"
|
||||||
@change="handleTargetTypeChange"
|
@change="handleTargetTypeChange"
|
||||||
:filterOption="filterOption"
|
:filterOption="filterOption"
|
||||||
>
|
>
|
||||||
|
@ -38,10 +43,13 @@
|
||||||
</a-select>
|
</a-select>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
|
|
||||||
<a-form-item label="关联关系">
|
<a-form-item :label="$t('cmdb.ciType.relationType')">
|
||||||
<a-select
|
<a-select
|
||||||
name="relation_type_id"
|
name="relation_type_id"
|
||||||
v-decorator="['relation_type_id', { rules: [{ required: true, message: '请选择关联关系' }] }]"
|
v-decorator="[
|
||||||
|
'relation_type_id',
|
||||||
|
{ rules: [{ required: true, message: $t('cmdb.ciType.relationTypeTips') }] },
|
||||||
|
]"
|
||||||
>
|
>
|
||||||
<a-select-option :value="relationType.id" :key="relationType.id" v-for="relationType in relationTypes">{{
|
<a-select-option :value="relationType.id" :key="relationType.id" v-for="relationType in relationTypes">{{
|
||||||
relationType.name
|
relationType.name
|
||||||
|
@ -49,11 +57,16 @@
|
||||||
</a-select>
|
</a-select>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
|
|
||||||
<a-form-item label="关联约束">
|
<a-form-item :label="$t('cmdb.ciType.relationConstraint')">
|
||||||
<a-select v-decorator="['constraint', { rules: [{ required: true, message: '请选择关联约束' }] }]">
|
<a-select
|
||||||
<a-select-option value="0">一对多</a-select-option>
|
v-decorator="[
|
||||||
<a-select-option value="1">一对一</a-select-option>
|
'constraint',
|
||||||
<a-select-option value="2">多对多</a-select-option>
|
{ rules: [{ required: true, message: $t('cmdb.ciType.relationConstraintTips') }] },
|
||||||
|
]"
|
||||||
|
>
|
||||||
|
<a-select-option value="0">{{ $t('cmdb.ciType.one2Many') }}</a-select-option>
|
||||||
|
<a-select-option value="1">{{ $t('cmdb.ciType.one2One') }}</a-select-option>
|
||||||
|
<a-select-option value="2">{{ $t('cmdb.ciType.many2Many') }}</a-select-option>
|
||||||
</a-select>
|
</a-select>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
</a-form>
|
</a-form>
|
||||||
|
@ -66,7 +79,7 @@ import ModelRelationTable from './modules/modelRelationTable.vue'
|
||||||
import { searchResourceType } from '@/modules/acl/api/resource'
|
import { searchResourceType } from '@/modules/acl/api/resource'
|
||||||
import { getCITypeGroupsConfig } from '@/modules/cmdb/api/ciTypeGroup'
|
import { getCITypeGroupsConfig } from '@/modules/cmdb/api/ciTypeGroup'
|
||||||
import { getCITypes } from '@/modules/cmdb/api/CIType'
|
import { getCITypes } from '@/modules/cmdb/api/CIType'
|
||||||
import { createRelation, deleteRelation, getRelationTypes } from '@/modules/cmdb/api/CITypeRelation'
|
import { createRelation, deleteRelation, getCITypeChildren, getRelationTypes } from '@/modules/cmdb/api/CITypeRelation'
|
||||||
export default {
|
export default {
|
||||||
name: 'Index',
|
name: 'Index',
|
||||||
components: {
|
components: {
|
||||||
|
@ -85,16 +98,40 @@ export default {
|
||||||
drawerTitle: '',
|
drawerTitle: '',
|
||||||
CITypes: [],
|
CITypes: [],
|
||||||
relationTypes: [],
|
relationTypes: [],
|
||||||
constraintMap: {
|
|
||||||
'0': '一对多',
|
|
||||||
'1': '一对一',
|
|
||||||
'2': '多对多',
|
|
||||||
},
|
|
||||||
|
|
||||||
sourceCITypeId: undefined,
|
sourceCITypeId: undefined,
|
||||||
targetCITypeId: undefined,
|
targetCITypeId: undefined,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
computed: {
|
||||||
|
currentCId() {
|
||||||
|
if (this.currentId) {
|
||||||
|
if (this.currentId.split('%')[1] !== 'null') {
|
||||||
|
return Number(this.currentId.split('%')[1])
|
||||||
|
}
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
return null
|
||||||
|
},
|
||||||
|
displayCITypes() {
|
||||||
|
return this.CITypes
|
||||||
|
// return this.CITypes.filter((c) => c.id !== this.targetCITypeId)
|
||||||
|
},
|
||||||
|
displayTargetCITypes() {
|
||||||
|
return this.CITypes
|
||||||
|
// return this.CITypes.filter((c) => c.id !== this.sourceCITypeId)
|
||||||
|
},
|
||||||
|
CITypeId() {
|
||||||
|
return this.currentCId
|
||||||
|
},
|
||||||
|
constraintMap() {
|
||||||
|
return {
|
||||||
|
'0': this.$t('cmdb.ciType.one2Many'),
|
||||||
|
'1': this.$t('cmdb.ciType.one2One'),
|
||||||
|
'2': this.$t('cmdb.ciType.many2Many'),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
provide() {
|
provide() {
|
||||||
return {
|
return {
|
||||||
resource_type: () => {
|
resource_type: () => {
|
||||||
|
@ -116,26 +153,6 @@ export default {
|
||||||
})
|
})
|
||||||
this.loadCITypes(!_currentId)
|
this.loadCITypes(!_currentId)
|
||||||
},
|
},
|
||||||
computed: {
|
|
||||||
currentCId() {
|
|
||||||
if (this.currentId) {
|
|
||||||
if (this.currentId.split('%')[1] !== 'null') {
|
|
||||||
return Number(this.currentId.split('%')[1])
|
|
||||||
}
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
return null
|
|
||||||
},
|
|
||||||
displayCITypes() {
|
|
||||||
return this.CITypes
|
|
||||||
},
|
|
||||||
displayTargetCITypes() {
|
|
||||||
return this.CITypes
|
|
||||||
},
|
|
||||||
CITypeId() {
|
|
||||||
return this.currentCId
|
|
||||||
},
|
|
||||||
},
|
|
||||||
methods: {
|
methods: {
|
||||||
async loadCITypes(isResetCurrentId = false) {
|
async loadCITypes(isResetCurrentId = false) {
|
||||||
const groups = await getCITypeGroupsConfig({ need_other: true })
|
const groups = await getCITypeGroupsConfig({ need_other: true })
|
||||||
|
@ -146,7 +163,6 @@ export default {
|
||||||
this.$nextTick(() => {
|
this.$nextTick(() => {
|
||||||
groups.forEach((g) => {
|
groups.forEach((g) => {
|
||||||
if (!g.id) {
|
if (!g.id) {
|
||||||
// 给未分组增加一个假的id
|
|
||||||
g.id = -1
|
g.id = -1
|
||||||
}
|
}
|
||||||
if (isResetCurrentId && !alreadyReset && g.ci_types && g.ci_types.length) {
|
if (isResetCurrentId && !alreadyReset && g.ci_types && g.ci_types.length) {
|
||||||
|
@ -172,7 +188,7 @@ export default {
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
handleCreate() {
|
handleCreate() {
|
||||||
this.drawerTitle = '新增关系'
|
this.drawerTitle = this.$t('cmdb.ciType.addRelation')
|
||||||
this.visible = true
|
this.visible = true
|
||||||
this.$nextTick(() => {
|
this.$nextTick(() => {
|
||||||
this.form.setFieldsValue({
|
this.form.setFieldsValue({
|
||||||
|
@ -192,7 +208,7 @@ export default {
|
||||||
if (!err) {
|
if (!err) {
|
||||||
createRelation(values.source_ci_type_id, values.ci_type_id, values.relation_type_id, values.constraint).then(
|
createRelation(values.source_ci_type_id, values.ci_type_id, values.relation_type_id, values.constraint).then(
|
||||||
(res) => {
|
(res) => {
|
||||||
this.$message.success(`添加成功`)
|
this.$message.success(this.$t('addSuccess'))
|
||||||
this.onClose()
|
this.onClose()
|
||||||
this.handleOk()
|
this.handleOk()
|
||||||
}
|
}
|
||||||
|
@ -207,7 +223,7 @@ export default {
|
||||||
},
|
},
|
||||||
handleDelete(record) {
|
handleDelete(record) {
|
||||||
deleteRelation(record.source_ci_type_id, record.id).then((res) => {
|
deleteRelation(record.source_ci_type_id, record.id).then((res) => {
|
||||||
this.$message.success(`删除成功!`)
|
this.$message.success(this.$t('deleteSuccess'))
|
||||||
|
|
||||||
this.handleOk()
|
this.handleOk()
|
||||||
})
|
})
|
||||||
|
|
|
@ -11,22 +11,27 @@
|
||||||
:data="tableData"
|
:data="tableData"
|
||||||
:sort-config="{ defaultSort: { field: 'created_at', order: 'desc' } }"
|
:sort-config="{ defaultSort: { field: 'created_at', order: 'desc' } }"
|
||||||
>
|
>
|
||||||
<vxe-column field="created_at" title="创建时间" sortable width="159px"></vxe-column>
|
<vxe-column field="created_at" :title="$t('created_at')" sortable width="159px"></vxe-column>
|
||||||
<vxe-column field="parent.alias" title="源模型"></vxe-column>
|
<vxe-column field="parent.alias" :title="$t('cmdb.ciType.sourceCIType')"></vxe-column>
|
||||||
<vxe-column field="relation_type_id" title="关系" :filters="[{ data: '' }]" :filter-multiple="false">
|
<vxe-column
|
||||||
|
field="relation_type_id"
|
||||||
|
:title="$t('cmdb.custom_dashboard.relation')"
|
||||||
|
:filters="[{ data: '' }]"
|
||||||
|
:filter-multiple="false"
|
||||||
|
>
|
||||||
<template #default="{ row }">
|
<template #default="{ row }">
|
||||||
<a-tag color="cyan">
|
<a-tag color="cyan">
|
||||||
{{ row.relation_type.name }}
|
{{ row.relation_type.name }}
|
||||||
</a-tag>
|
</a-tag>
|
||||||
</template>
|
</template>
|
||||||
</vxe-column>
|
</vxe-column>
|
||||||
<vxe-column field="child.alias" title="目标模型"></vxe-column>
|
<vxe-column field="child.alias" :title="$t('cmdb.ciType.dstCIType')"></vxe-column>
|
||||||
<vxe-column field="constraint" title="关联约束"></vxe-column>
|
<vxe-column field="constraint" :title="$t('cmdb.ciType.relationConstraint')"></vxe-column>
|
||||||
<vxe-column field="authorization" title="操作" width="89px">
|
<vxe-column field="authorization" :title="$t('operation')" width="89px">
|
||||||
<template #default="{ row }">
|
<template #default="{ row }">
|
||||||
<a-space>
|
<a-space>
|
||||||
<a @click="handleOpenGrant(row)"><a-icon type="user-add"/></a>
|
<a @click="handleOpenGrant(row)"><a-icon type="user-add"/></a>
|
||||||
<a-popconfirm title="确认删除?" @confirm="deleteRelation(row)">
|
<a-popconfirm :title="$t('cmdb.ciType.confirmDelete2')" @confirm="deleteRelation(row)">
|
||||||
<a :style="{ color: 'red' }"><ops-icon type="icon-xianxing-delete"/></a>
|
<a :style="{ color: 'red' }"><ops-icon type="icon-xianxing-delete"/></a>
|
||||||
</a-popconfirm>
|
</a-popconfirm>
|
||||||
</a-space>
|
</a-space>
|
||||||
|
@ -48,11 +53,6 @@ export default {
|
||||||
drawerVisible: false,
|
drawerVisible: false,
|
||||||
tableData: [],
|
tableData: [],
|
||||||
relationTypeList: null,
|
relationTypeList: null,
|
||||||
constraintMap: {
|
|
||||||
'0': '一对多',
|
|
||||||
'1': '一对一',
|
|
||||||
'2': '多对多',
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
components: {
|
components: {
|
||||||
|
@ -65,6 +65,13 @@ export default {
|
||||||
windowHeight() {
|
windowHeight() {
|
||||||
return this.$store.state.windowHeight
|
return this.$store.state.windowHeight
|
||||||
},
|
},
|
||||||
|
constraintMap() {
|
||||||
|
return {
|
||||||
|
'0': this.$t('cmdb.ciType.one2Many'),
|
||||||
|
'1': this.$t('cmdb.ciType.one2One'),
|
||||||
|
'2': this.$t('cmdb.ciType.many2Many'),
|
||||||
|
}
|
||||||
|
},
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
async refresh() {
|
async refresh() {
|
||||||
|
@ -103,7 +110,8 @@ export default {
|
||||||
},
|
},
|
||||||
deleteRelation(row) {
|
deleteRelation(row) {
|
||||||
deleteRelation(row.parent_id, row.child_id).then((res) => {
|
deleteRelation(row.parent_id, row.child_id).then((res) => {
|
||||||
this.$message.success(`删除成功!`)
|
this.$message.success(this.$t('deleteSuccess'))
|
||||||
|
this.getRelationTypes()
|
||||||
this.refresh()
|
this.refresh()
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,43 +1,43 @@
|
||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<a-card :bordered="false">
|
<a-card :bordered="false">
|
||||||
<a-tabs default-active-key="1">
|
<a-tabs default-active-key="1">
|
||||||
<a-tab-pane key="1" tab="CI变更">
|
<a-tab-pane key="1" :tab="$t('cmdb.history.ciChange')">
|
||||||
<ci-table></ci-table>
|
<ci-table></ci-table>
|
||||||
</a-tab-pane>
|
</a-tab-pane>
|
||||||
<a-tab-pane key="2" tab="关系变更">
|
<a-tab-pane key="2" :tab="$t('cmdb.history.relationChange')">
|
||||||
<relation-table></relation-table>
|
<relation-table></relation-table>
|
||||||
</a-tab-pane>
|
</a-tab-pane>
|
||||||
<a-tab-pane key="3" tab="模型变更">
|
<a-tab-pane key="3" :tab="$t('cmdb.history.ciTypeChange')">
|
||||||
<type-table></type-table>
|
<type-table></type-table>
|
||||||
</a-tab-pane>
|
</a-tab-pane>
|
||||||
<a-tab-pane key="4" tab="触发历史">
|
<a-tab-pane key="4" :tab="$t('cmdb.history.triggerHistory')">
|
||||||
<TriggerTable></TriggerTable>
|
<TriggerTable></TriggerTable>
|
||||||
</a-tab-pane>
|
</a-tab-pane>
|
||||||
</a-tabs>
|
</a-tabs>
|
||||||
</a-card>
|
</a-card>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import CiTable from './modules/ciTable.vue'
|
import CiTable from './modules/ciTable.vue'
|
||||||
import RelationTable from './modules/relation.vue'
|
import RelationTable from './modules/relation.vue'
|
||||||
import TypeTable from './modules/typeTable.vue'
|
import TypeTable from './modules/typeTable.vue'
|
||||||
import TriggerTable from './modules/triggerTable.vue'
|
import TriggerTable from './modules/triggerTable.vue'
|
||||||
export default {
|
export default {
|
||||||
name: 'OperationHistory',
|
name: 'OperationHistory',
|
||||||
components: {
|
components: {
|
||||||
CiTable,
|
CiTable,
|
||||||
RelationTable,
|
RelationTable,
|
||||||
TypeTable,
|
TypeTable,
|
||||||
TriggerTable,
|
TriggerTable,
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
userList: [],
|
userList: [],
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style></style>
|
<style></style>
|
||||||
|
|
|
@ -1,421 +1,407 @@
|
||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<search-form
|
<search-form
|
||||||
ref="child"
|
ref="child"
|
||||||
:attrList="ciTableAttrList"
|
:attrList="ciTableAttrList"
|
||||||
@expandChange="handleExpandChange"
|
@expandChange="handleExpandChange"
|
||||||
@search="handleSearch"
|
@search="handleSearch"
|
||||||
@searchFormReset="searchFormReset"
|
@searchFormReset="searchFormReset"
|
||||||
@searchFormChange="searchFormChange"
|
@searchFormChange="searchFormChange"
|
||||||
></search-form>
|
></search-form>
|
||||||
<vxe-table
|
<vxe-table
|
||||||
ref="xTable"
|
ref="xTable"
|
||||||
row-id="_XID"
|
row-id="_XID"
|
||||||
:loading="loading"
|
:loading="loading"
|
||||||
border
|
border
|
||||||
size="small"
|
size="small"
|
||||||
show-overflow="tooltip"
|
show-overflow="tooltip"
|
||||||
show-header-overflow="tooltip"
|
show-header-overflow="tooltip"
|
||||||
resizable
|
resizable
|
||||||
:data="tableData"
|
:data="tableData"
|
||||||
:max-height="`${windowHeight - windowHeightMinus}px`"
|
:max-height="`${windowHeight - windowHeightMinus}px`"
|
||||||
:span-method="mergeRowMethod"
|
:span-method="mergeRowMethod"
|
||||||
:scroll-y="{enabled: false}"
|
:scroll-y="{ enabled: false }"
|
||||||
class="ops-unstripe-table"
|
class="ops-unstripe-table"
|
||||||
>
|
>
|
||||||
<vxe-column field="created_at" width="159px" title="操作时间"></vxe-column>
|
<vxe-column field="created_at" width="159px" :title="$t('cmdb.history.opreateTime')"></vxe-column>
|
||||||
<vxe-column field="user" width="100px" title="用户">
|
<vxe-column field="user" width="100px" :title="$t('cmdb.history.user')">
|
||||||
<template #header="{ column }">
|
<template #header="{ column }">
|
||||||
<span>{{ column.title }}</span>
|
<span>{{ column.title }}</span>
|
||||||
<a-popover trigger="click" placement="bottom">
|
<a-popover trigger="click" placement="bottom">
|
||||||
<a-icon class="filter" type="filter" theme="filled"/>
|
<a-icon class="filter" type="filter" theme="filled" />
|
||||||
<a slot="content">
|
<a slot="content">
|
||||||
<a-input placeholder="输入筛选用户名" size="small" v-model="queryParams.username" style="width: 200px" allowClear/>
|
<a-input
|
||||||
<a-button type="link" class="filterButton" @click="filterUser">筛选</a-button>
|
:placeholder="$t('cmdb.history.userTips')"
|
||||||
<a-button type="link" class="filterResetButton" @click="filterUserReset">重置</a-button>
|
size="small"
|
||||||
</a>
|
v-model="queryParams.username"
|
||||||
</a-popover>
|
style="width: 200px"
|
||||||
</template>
|
allowClear
|
||||||
</vxe-column>
|
/>
|
||||||
<vxe-column field="type_id" width="100px" title="模型"></vxe-column>
|
<a-button type="link" class="filterButton" @click="filterUser">{{ $t('cmdb.history.filter') }}</a-button>
|
||||||
<vxe-column field="operate_type" width="89px" title="操作">
|
<a-button type="link" class="filterResetButton" @click="filterUserReset">{{ $t('reset') }}</a-button>
|
||||||
<template #header="{ column }">
|
</a>
|
||||||
<span>{{ column.title }}</span>
|
</a-popover>
|
||||||
<a-popover trigger="click" placement="bottom">
|
</template>
|
||||||
<a-icon class="filter" type="filter" theme="filled"/>
|
</vxe-column>
|
||||||
<a slot="content">
|
<vxe-column field="type_id" width="100px" :title="$t('cmdb.ciType.ciType')"></vxe-column>
|
||||||
<a-select
|
<vxe-column field="operate_type" width="89px" :title="$t('operation')">
|
||||||
v-model="queryParams.operate_type"
|
<template #header="{ column }">
|
||||||
placeholder="选择筛选操作"
|
<span>{{ column.title }}</span>
|
||||||
show-search
|
<a-popover trigger="click" placement="bottom">
|
||||||
style="width: 200px"
|
<a-icon class="filter" type="filter" theme="filled" />
|
||||||
:filter-option="filterOption"
|
<a slot="content">
|
||||||
allowClear
|
<a-select
|
||||||
>
|
v-model="queryParams.operate_type"
|
||||||
<a-select-option
|
:placeholder="$t('cmdb.history.filterOperate')"
|
||||||
:value="Object.values(choice)[0]"
|
show-search
|
||||||
:key="index"
|
style="width: 200px"
|
||||||
v-for="(choice, index) in ciTableAttrList[4].choice_value"
|
:filter-option="filterOption"
|
||||||
>
|
allowClear
|
||||||
{{ Object.keys(choice)[0] }}
|
>
|
||||||
</a-select-option
|
<a-select-option
|
||||||
>
|
:value="Object.values(choice)[0]"
|
||||||
</a-select>
|
:key="index"
|
||||||
<a-button type="link" class="filterButton" @click="filterOperate">筛选</a-button>
|
v-for="(choice, index) in ciTableAttrList[4].choice_value"
|
||||||
<a-button type="link" class="filterResetButton" @click="filterOperateReset">重置</a-button>
|
>
|
||||||
</a>
|
{{ Object.keys(choice)[0] }}
|
||||||
</a-popover>
|
</a-select-option>
|
||||||
</template>
|
</a-select>
|
||||||
<template #default="{ row }">
|
<a-button type="link" class="filterButton" @click="filterOperate">{{
|
||||||
<a-tag color="green" v-if="row.operate_type === '新增' ">
|
$t('cmdb.history.filter')
|
||||||
{{ row.operate_type }}
|
}}</a-button>
|
||||||
</a-tag>
|
<a-button type="link" class="filterResetButton" @click="filterOperateReset">{{ $t('reset') }}</a-button>
|
||||||
<a-tag color="orange" v-else-if="row.operate_type === '修改' ">
|
</a>
|
||||||
{{ row.operate_type }}
|
</a-popover>
|
||||||
</a-tag>
|
</template>
|
||||||
<a-tag color="red" v-else>
|
<template #default="{ row }">
|
||||||
{{ row.operate_type }}
|
<a-tag color="green" v-if="row.operate_type === $t('new')">
|
||||||
</a-tag>
|
{{ row.operate_type }}
|
||||||
</template>
|
</a-tag>
|
||||||
</vxe-column>
|
<a-tag color="orange" v-else-if="row.operate_type === $t('update')">
|
||||||
<vxe-column field="attr_alias" title="属性"></vxe-column>
|
{{ row.operate_type }}
|
||||||
<vxe-column field="old" title="旧"></vxe-column>
|
</a-tag>
|
||||||
<vxe-column field="new" title="新"></vxe-column>
|
<a-tag color="red" v-else>
|
||||||
</vxe-table>
|
{{ row.operate_type }}
|
||||||
<pager
|
</a-tag>
|
||||||
:current-page.sync="queryParams.page"
|
</template>
|
||||||
:page-size.sync="queryParams.page_size"
|
</vxe-column>
|
||||||
:page-sizes="[50,100,200]"
|
<vxe-column field="attr_alias" :title="$t('cmdb.history.attribute')"></vxe-column>
|
||||||
:total="total"
|
<vxe-column field="old" :title="$t('cmdb.history.old')"></vxe-column>
|
||||||
:isLoading="loading"
|
<vxe-column field="new" :title="$t('cmdb.history.new')"></vxe-column>
|
||||||
@change="onChange"
|
</vxe-table>
|
||||||
@showSizeChange="onShowSizeChange"
|
<pager
|
||||||
></pager>
|
:current-page.sync="queryParams.page"
|
||||||
</div>
|
:page-size.sync="queryParams.page_size"
|
||||||
</template>
|
:page-sizes="[50, 100, 200]"
|
||||||
<script>
|
:total="total"
|
||||||
import Pager from './pager.vue'
|
:isLoading="loading"
|
||||||
import SearchForm from './searchForm.vue'
|
@change="onChange"
|
||||||
import { getCIHistoryTable, getUsers } from '@/modules/cmdb/api/history'
|
@showSizeChange="onShowSizeChange"
|
||||||
import { getCITypes } from '@/modules/cmdb/api/CIType'
|
></pager>
|
||||||
import { getCITypeAttributesById } from '@/modules/cmdb/api/CITypeAttr'
|
</div>
|
||||||
export default {
|
</template>
|
||||||
name: 'CiTable',
|
<script>
|
||||||
components: { SearchForm, Pager },
|
import { mapState } from 'vuex'
|
||||||
data() {
|
import Pager from './pager.vue'
|
||||||
return {
|
import SearchForm from './searchForm.vue'
|
||||||
typeId: undefined,
|
import { getCIHistoryTable, getUsers } from '@/modules/cmdb/api/history'
|
||||||
operateTypeMap: new Map([
|
import { getCITypes } from '@/modules/cmdb/api/CIType'
|
||||||
['0', '新增'],
|
import { getCITypeAttributesById } from '@/modules/cmdb/api/CITypeAttr'
|
||||||
['1', '删除'],
|
export default {
|
||||||
['2', '修改'],
|
name: 'CiTable',
|
||||||
]),
|
components: { SearchForm, Pager },
|
||||||
loading: true,
|
inject: ['reload'],
|
||||||
typeList: null,
|
data() {
|
||||||
userList: [],
|
return {
|
||||||
tableData: [],
|
typeId: undefined,
|
||||||
total: 0,
|
loading: true,
|
||||||
isExpand: false,
|
typeList: null,
|
||||||
queryParams: {
|
userList: [],
|
||||||
page: 1,
|
tableData: [],
|
||||||
page_size: 50,
|
total: 0,
|
||||||
},
|
isExpand: false,
|
||||||
ciTableAttrList: [
|
queryParams: {
|
||||||
{
|
page: 1,
|
||||||
alias: '日期',
|
page_size: 50,
|
||||||
is_choice: false,
|
},
|
||||||
name: 'datetime',
|
ciTableAttrList: [
|
||||||
value_type: '3'
|
{
|
||||||
},
|
alias: this.$t('cmdb.ciType.date'),
|
||||||
{
|
is_choice: false,
|
||||||
alias: '用户',
|
name: 'datetime',
|
||||||
is_choice: true,
|
value_type: '3',
|
||||||
name: 'username',
|
},
|
||||||
value_type: '2',
|
{
|
||||||
choice_value: []
|
alias: this.$t('cmdb.history.user'),
|
||||||
},
|
is_choice: true,
|
||||||
{
|
name: 'username',
|
||||||
alias: '模型',
|
value_type: '2',
|
||||||
is_choice: true,
|
choice_value: [],
|
||||||
name: 'type_id',
|
},
|
||||||
value_type: '2',
|
{
|
||||||
choice_value: [],
|
alias: this.$t('cmdb.ciType.ciType'),
|
||||||
},
|
is_choice: true,
|
||||||
{
|
name: 'type_id',
|
||||||
alias: '属性',
|
value_type: '2',
|
||||||
is_choice: true,
|
choice_value: [],
|
||||||
name: 'attr_id',
|
},
|
||||||
value_type: '2',
|
{
|
||||||
choice_value: []
|
alias: this.$t('cmdb.history.attribute'),
|
||||||
},
|
is_choice: true,
|
||||||
{
|
name: 'attr_id',
|
||||||
alias: '操作',
|
value_type: '2',
|
||||||
is_choice: true,
|
choice_value: [],
|
||||||
name: 'operate_type',
|
},
|
||||||
value_type: '2',
|
{
|
||||||
choice_value: [
|
alias: this.$t('operation'),
|
||||||
{ '新增': 0 },
|
is_choice: true,
|
||||||
{ '删除': 1 },
|
name: 'operate_type',
|
||||||
{ '修改': 2 },
|
value_type: '2',
|
||||||
]
|
choice_value: [{ [this.$t('new')]: 0 }, { [this.$t('delete')]: 1 }, { [this.$t('update')]: 2 }],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
alias: 'CI_ID',
|
alias: 'CI_ID',
|
||||||
is_choice: false,
|
is_choice: false,
|
||||||
name: 'ci_id',
|
name: 'ci_id',
|
||||||
value_type: '2'
|
value_type: '2',
|
||||||
}
|
},
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
windowHeight() {
|
...mapState(['locale']),
|
||||||
return this.$store.state.windowHeight
|
windowHeight() {
|
||||||
},
|
return this.$store.state.windowHeight
|
||||||
windowHeightMinus() {
|
},
|
||||||
return this.isExpand ? 396 : 331
|
windowHeightMinus() {
|
||||||
}
|
return this.isExpand ? 396 : 331
|
||||||
},
|
},
|
||||||
async created() {
|
operateTypeMap() {
|
||||||
this.$watch(
|
return new Map([
|
||||||
function () {
|
['0', this.$t('new')],
|
||||||
return this.ciTableAttrList[3].choice_value
|
['1', this.$t('delete')],
|
||||||
},
|
['2', this.$t('update')],
|
||||||
function () {
|
])
|
||||||
delete this.$refs.child.queryParams.attr_id
|
},
|
||||||
}
|
},
|
||||||
)
|
watch: {
|
||||||
await Promise.all([
|
locale() {
|
||||||
this.getUserList(),
|
this.reload()
|
||||||
this.getTypes()
|
},
|
||||||
])
|
},
|
||||||
await this.getTable(this.queryParams)
|
async created() {
|
||||||
},
|
this.$watch(
|
||||||
updated() {
|
function() {
|
||||||
this.$refs.xTable.$el.querySelector('.vxe-table--body-wrapper').scrollTop = 0
|
return this.ciTableAttrList[3].choice_value
|
||||||
},
|
},
|
||||||
methods: {
|
function() {
|
||||||
// 获取表格数据
|
delete this.$refs.child.queryParams.attr_id
|
||||||
async getTable(queryParams) {
|
}
|
||||||
try {
|
)
|
||||||
this.loading = true
|
await Promise.all([this.getUserList(), this.getTypes()])
|
||||||
const res = await getCIHistoryTable(queryParams)
|
await this.getTable(this.queryParams)
|
||||||
const tempArr = []
|
},
|
||||||
res.records.forEach(item => {
|
updated() {
|
||||||
item[0].type_id = this.handleTypeId(item[0].type_id)
|
this.$refs.xTable.$el.querySelector('.vxe-table--body-wrapper').scrollTop = 0
|
||||||
item[1].forEach((subItem) => {
|
},
|
||||||
subItem.operate_type = this.handleOperateType(subItem.operate_type)
|
methods: {
|
||||||
const tempObj = Object.assign(subItem, item[0])
|
async getTable(queryParams) {
|
||||||
tempArr.push(tempObj)
|
try {
|
||||||
})
|
this.loading = true
|
||||||
})
|
const res = await getCIHistoryTable(queryParams)
|
||||||
this.tableData = tempArr
|
const tempArr = []
|
||||||
this.total = res.total
|
res.records.forEach((item) => {
|
||||||
} finally {
|
item[0].type_id = this.handleTypeId(item[0].type_id)
|
||||||
this.loading = false
|
item[1].forEach((subItem) => {
|
||||||
}
|
subItem.operate_type = this.handleOperateType(subItem.operate_type)
|
||||||
},
|
const tempObj = Object.assign(subItem, item[0])
|
||||||
// 获取用户列表
|
tempArr.push(tempObj)
|
||||||
async getUserList() {
|
})
|
||||||
const res = await getUsers()
|
})
|
||||||
this.userList = res.map(x => {
|
this.tableData = tempArr
|
||||||
const username = x.nickname
|
this.total = res.total
|
||||||
const obj = {
|
} finally {
|
||||||
[username]: username
|
this.loading = false
|
||||||
}
|
}
|
||||||
return obj
|
},
|
||||||
})
|
async getUserList() {
|
||||||
this.ciTableAttrList[1].choice_value = this.userList
|
const res = await getUsers()
|
||||||
},
|
this.userList = res.map((x) => {
|
||||||
// 获取模型
|
const username = x.nickname
|
||||||
async getTypes() {
|
const obj = {
|
||||||
const res = await getCITypes()
|
[username]: username,
|
||||||
const typesArr = []
|
}
|
||||||
const typesMap = new Map()
|
return obj
|
||||||
res.ci_types.forEach(item => {
|
})
|
||||||
const tempObj = {}
|
this.ciTableAttrList[1].choice_value = this.userList
|
||||||
tempObj[item.alias] = item.id
|
},
|
||||||
if (item.alias) {
|
async getTypes() {
|
||||||
typesArr.push(tempObj)
|
const res = await getCITypes()
|
||||||
typesMap.set(item.id, item.alias)
|
const typesArr = []
|
||||||
}
|
const typesMap = new Map()
|
||||||
})
|
res.ci_types.forEach((item) => {
|
||||||
this.typeList = typesMap
|
const tempObj = {}
|
||||||
this.ciTableAttrList[2].choice_value = typesArr
|
tempObj[item.alias] = item.id
|
||||||
},
|
if (item.alias) {
|
||||||
// 获取模型对应属性
|
typesArr.push(tempObj)
|
||||||
async getAttrs(type_id) {
|
typesMap.set(item.id, item.alias)
|
||||||
if (!type_id) {
|
}
|
||||||
this.ciTableAttrList[3].choice_value = []
|
})
|
||||||
return
|
this.typeList = typesMap
|
||||||
}
|
this.ciTableAttrList[2].choice_value = typesArr
|
||||||
const res = await getCITypeAttributesById(type_id)
|
},
|
||||||
const attrsArr = []
|
async getAttrs(type_id) {
|
||||||
res.attributes.forEach(item => {
|
if (!type_id) {
|
||||||
const tempObj = {}
|
this.ciTableAttrList[3].choice_value = []
|
||||||
tempObj[item.alias] = item.id
|
return
|
||||||
if (item.alias) {
|
}
|
||||||
attrsArr.push(tempObj)
|
const res = await getCITypeAttributesById(type_id)
|
||||||
}
|
const attrsArr = []
|
||||||
})
|
res.attributes.forEach((item) => {
|
||||||
this.ciTableAttrList[3].choice_value = attrsArr
|
const tempObj = {}
|
||||||
},
|
tempObj[item.alias] = item.id
|
||||||
onShowSizeChange(size) {
|
if (item.alias) {
|
||||||
this.queryParams.page_size = size
|
attrsArr.push(tempObj)
|
||||||
this.queryParams.page = 1
|
}
|
||||||
this.getTable(this.queryParams)
|
})
|
||||||
},
|
this.ciTableAttrList[3].choice_value = attrsArr
|
||||||
onChange(pageNum) {
|
},
|
||||||
this.queryParams.page = pageNum
|
onShowSizeChange(size) {
|
||||||
this.getTable(this.queryParams)
|
this.queryParams.page_size = size
|
||||||
},
|
this.queryParams.page = 1
|
||||||
handleExpandChange(expand) {
|
this.getTable(this.queryParams)
|
||||||
this.isExpand = expand
|
},
|
||||||
},
|
onChange(pageNum) {
|
||||||
// 处理查询
|
this.queryParams.page = pageNum
|
||||||
handleSearch(queryParams) {
|
this.getTable(this.queryParams)
|
||||||
this.queryParams = queryParams
|
},
|
||||||
this.getTable(this.queryParams)
|
handleExpandChange(expand) {
|
||||||
},
|
this.isExpand = expand
|
||||||
// 重置表单
|
},
|
||||||
searchFormReset() {
|
handleSearch(queryParams) {
|
||||||
this.queryParams = {
|
this.queryParams = queryParams
|
||||||
page: 1,
|
this.getTable(this.queryParams)
|
||||||
page_size: 50,
|
},
|
||||||
start: '',
|
searchFormReset() {
|
||||||
end: '',
|
this.queryParams = {
|
||||||
username: '',
|
page: 1,
|
||||||
ci_id: undefined,
|
page_size: 50,
|
||||||
attr_id: undefined,
|
start: '',
|
||||||
operate_type: undefined
|
end: '',
|
||||||
}
|
username: '',
|
||||||
// 将属性options重置
|
ci_id: undefined,
|
||||||
this.ciTableAttrList[3].choice_value = []
|
attr_id: undefined,
|
||||||
this.getTable(this.queryParams)
|
operate_type: undefined,
|
||||||
},
|
}
|
||||||
// 转换operate_type
|
this.ciTableAttrList[3].choice_value = []
|
||||||
handleOperateType(operate_type) {
|
this.getTable(this.queryParams)
|
||||||
return this.operateTypeMap.get(operate_type)
|
},
|
||||||
},
|
handleOperateType(operate_type) {
|
||||||
// 转换type_id
|
return this.operateTypeMap.get(operate_type)
|
||||||
handleTypeId(type_id) {
|
},
|
||||||
return this.typeList.get(type_id) ? this.typeList.get(type_id) : type_id
|
handleTypeId(type_id) {
|
||||||
},
|
return this.typeList.get(type_id) ? this.typeList.get(type_id) : type_id
|
||||||
// 表单改变,重新获取属性列表
|
},
|
||||||
searchFormChange(queryParams) {
|
searchFormChange(queryParams) {
|
||||||
if (this.typeId !== queryParams.type_id) {
|
if (this.typeId !== queryParams.type_id) {
|
||||||
this.typeId = queryParams.type_id
|
this.typeId = queryParams.type_id
|
||||||
this.getAttrs(queryParams.type_id)
|
this.getAttrs(queryParams.type_id)
|
||||||
}
|
}
|
||||||
if (queryParams.type_id === undefined) {
|
if (queryParams.type_id === undefined) {
|
||||||
this.typeId = undefined
|
this.typeId = undefined
|
||||||
this.$refs.child.queryParams.attr_id = undefined
|
this.$refs.child.queryParams.attr_id = undefined
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
// 合并表格
|
mergeRowMethod({ row, _rowIndex, column, visibleData }) {
|
||||||
mergeRowMethod ({ row, _rowIndex, column, visibleData }) {
|
const fields = ['created_at', 'user', 'type_id']
|
||||||
const fields = ['created_at', 'user', 'type_id']
|
const cellValue = row[column.property]
|
||||||
// 单元格值 = 行[列.属性] 确定一格
|
const created_at = row['created_at']
|
||||||
const cellValue = row[column.property]
|
if (column.property === 'created_at') {
|
||||||
const created_at = row['created_at']
|
if (cellValue && fields.includes(column.property)) {
|
||||||
// 如果单元格值不为空且作用域包含当前列
|
const prevRow = visibleData[_rowIndex - 1]
|
||||||
if (column.property === 'created_at') {
|
let nextRow = visibleData[_rowIndex + 1]
|
||||||
if (cellValue && fields.includes(column.property)) {
|
if (prevRow && prevRow[column.property] === cellValue) {
|
||||||
// 前一行
|
return { rowspan: 0, colspan: 0 }
|
||||||
const prevRow = visibleData[_rowIndex - 1]
|
} else {
|
||||||
// 下一行
|
let countRowspan = 1
|
||||||
let nextRow = visibleData[_rowIndex + 1]
|
while (nextRow && nextRow[column.property] === cellValue) {
|
||||||
// 如果前一行不为空且前一行单元格的值与cellValue相同
|
nextRow = visibleData[++countRowspan + _rowIndex]
|
||||||
if (prevRow && prevRow[column.property] === cellValue) {
|
}
|
||||||
return { rowspan: 0, colspan: 0 }
|
if (countRowspan > 1) {
|
||||||
} else {
|
return { rowspan: countRowspan, colspan: 1 }
|
||||||
let countRowspan = 1
|
}
|
||||||
while (nextRow && nextRow[column.property] === cellValue) {
|
}
|
||||||
nextRow = visibleData[++countRowspan + _rowIndex]
|
}
|
||||||
}
|
} else if (column.property === 'user') {
|
||||||
if (countRowspan > 1) {
|
if (cellValue && fields.includes(column.property)) {
|
||||||
return { rowspan: countRowspan, colspan: 1 }
|
const prevRow = visibleData[_rowIndex - 1]
|
||||||
}
|
let nextRow = visibleData[_rowIndex + 1]
|
||||||
}
|
if (prevRow && prevRow[column.property] === cellValue && prevRow['created_at'] === created_at) {
|
||||||
}
|
return { rowspan: 0, colspan: 0 }
|
||||||
} else if (column.property === 'user') {
|
} else {
|
||||||
if (cellValue && fields.includes(column.property)) {
|
let countRowspan = 1
|
||||||
// 前一行
|
while (nextRow && nextRow[column.property] === cellValue && nextRow['created_at'] === created_at) {
|
||||||
const prevRow = visibleData[_rowIndex - 1]
|
nextRow = visibleData[++countRowspan + _rowIndex]
|
||||||
// 下一行
|
}
|
||||||
let nextRow = visibleData[_rowIndex + 1]
|
if (countRowspan > 1) {
|
||||||
// 如果前一行不为空且前一行单元格的值与cellValue相同
|
return { rowspan: countRowspan, colspan: 1 }
|
||||||
if (prevRow && prevRow[column.property] === cellValue && prevRow['created_at'] === created_at) {
|
}
|
||||||
return { rowspan: 0, colspan: 0 }
|
}
|
||||||
} else {
|
}
|
||||||
let countRowspan = 1
|
} else if (column.property === 'type_id') {
|
||||||
while (nextRow && nextRow[column.property] === cellValue && nextRow['created_at'] === created_at) {
|
if (cellValue && fields.includes(column.property)) {
|
||||||
nextRow = visibleData[++countRowspan + _rowIndex]
|
const prevRow = visibleData[_rowIndex - 1]
|
||||||
}
|
let nextRow = visibleData[_rowIndex + 1]
|
||||||
if (countRowspan > 1) {
|
if (prevRow && prevRow[column.property] === cellValue && prevRow['created_at'] === created_at) {
|
||||||
return { rowspan: countRowspan, colspan: 1 }
|
return { rowspan: 0, colspan: 0 }
|
||||||
}
|
} else {
|
||||||
}
|
let countRowspan = 1
|
||||||
}
|
while (nextRow && nextRow[column.property] === cellValue && nextRow['created_at'] === created_at) {
|
||||||
} else if (column.property === 'type_id') {
|
nextRow = visibleData[++countRowspan + _rowIndex]
|
||||||
if (cellValue && fields.includes(column.property)) {
|
}
|
||||||
// 前一行
|
if (countRowspan > 1) {
|
||||||
const prevRow = visibleData[_rowIndex - 1]
|
return { rowspan: countRowspan, colspan: 1 }
|
||||||
// 下一行
|
}
|
||||||
let nextRow = visibleData[_rowIndex + 1]
|
}
|
||||||
// 如果前一行不为空且前一行单元格的值与cellValue相同
|
}
|
||||||
if (prevRow && prevRow[column.property] === cellValue && prevRow['created_at'] === created_at) {
|
}
|
||||||
return { rowspan: 0, colspan: 0 }
|
},
|
||||||
} else {
|
filterUser() {
|
||||||
let countRowspan = 1
|
this.queryParams.page = 1
|
||||||
while (nextRow && nextRow[column.property] === cellValue && nextRow['created_at'] === created_at) {
|
this.queryParams.page_size = 50
|
||||||
nextRow = visibleData[++countRowspan + _rowIndex]
|
this.getTable(this.queryParams)
|
||||||
}
|
},
|
||||||
if (countRowspan > 1) {
|
filterUserReset() {
|
||||||
return { rowspan: countRowspan, colspan: 1 }
|
this.queryParams.page = 1
|
||||||
}
|
this.queryParams.page_size = 50
|
||||||
}
|
this.queryParams.username = ''
|
||||||
}
|
this.getTable(this.queryParams)
|
||||||
}
|
},
|
||||||
},
|
filterOperate() {
|
||||||
filterUser() {
|
this.queryParams.page = 1
|
||||||
this.queryParams.page = 1
|
this.queryParams.page_size = 50
|
||||||
this.queryParams.page_size = 50
|
this.getTable(this.queryParams)
|
||||||
this.getTable(this.queryParams)
|
},
|
||||||
},
|
filterOperateReset() {
|
||||||
filterUserReset() {
|
this.queryParams.page = 1
|
||||||
this.queryParams.page = 1
|
this.queryParams.page_size = 50
|
||||||
this.queryParams.page_size = 50
|
this.queryParams.operate_type = undefined
|
||||||
this.queryParams.username = ''
|
this.getTable(this.queryParams)
|
||||||
this.getTable(this.queryParams)
|
},
|
||||||
},
|
filterOption(input, option) {
|
||||||
filterOperate() {
|
return option.componentOptions.children[0].text.indexOf(input) >= 0
|
||||||
this.queryParams.page = 1
|
},
|
||||||
this.queryParams.page_size = 50
|
},
|
||||||
this.getTable(this.queryParams)
|
}
|
||||||
},
|
</script>
|
||||||
filterOperateReset() {
|
|
||||||
this.queryParams.page = 1
|
<style lang="less" scoped>
|
||||||
this.queryParams.page_size = 50
|
.filter {
|
||||||
this.queryParams.operate_type = undefined
|
margin-left: 10px;
|
||||||
this.getTable(this.queryParams)
|
color: #c0c4cc;
|
||||||
},
|
cursor: pointer;
|
||||||
filterOption(input, option) {
|
&:hover {
|
||||||
return (
|
color: #606266;
|
||||||
option.componentOptions.children[0].text.indexOf(input) >= 0
|
}
|
||||||
)
|
}
|
||||||
}
|
</style>
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="less" scoped>
|
|
||||||
.filter{
|
|
||||||
margin-left: 10px;
|
|
||||||
color: #c0c4cc;
|
|
||||||
cursor: pointer;
|
|
||||||
&:hover{
|
|
||||||
color: #606266;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
|
@ -1,116 +1,116 @@
|
||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<a-row class="row" type="flex" justify="end">
|
<a-row class="row" type="flex" justify="end">
|
||||||
<a-col>
|
<a-col>
|
||||||
<a-space align="end">
|
<a-space align="end">
|
||||||
<a-button class="left-button" size="small" :disabled="prevIsDisabled" @click="prevPage"><a-icon type="left" /></a-button>
|
<a-button class="left-button" size="small" :disabled="prevIsDisabled" @click="prevPage"><a-icon type="left" /></a-button>
|
||||||
<a-button class="page-button" size="small" >{{ currentPage }}</a-button>
|
<a-button class="page-button" size="small" >{{ currentPage }}</a-button>
|
||||||
<a-button class="right-button" size="small" :disabled="nextIsDisabled" @click="nextPage"><a-icon type="right" /></a-button>
|
<a-button class="right-button" size="small" :disabled="nextIsDisabled" @click="nextPage"><a-icon type="right" /></a-button>
|
||||||
<a-dropdown class="dropdown" placement="topCenter" :trigger="['click']" :disabled="dropdownIsDisabled">
|
<a-dropdown class="dropdown" placement="topCenter" :trigger="['click']" :disabled="dropdownIsDisabled">
|
||||||
<a-menu slot="overlay">
|
<a-menu slot="overlay">
|
||||||
<a-menu-item v-for="(size,index) in pageSizes" :key="index" @click="handleItemClick(size)">
|
<a-menu-item v-for="(size,index) in pageSizes" :key="index" @click="handleItemClick(size)">
|
||||||
{{ size }}条/页
|
{{ size }}{{ $t('cmdb.history.itemsPerPage') }}
|
||||||
</a-menu-item>
|
</a-menu-item>
|
||||||
</a-menu>
|
</a-menu>
|
||||||
<a-button size="small"> {{ pageSize }}条/页 <a-icon type="down" /> </a-button>
|
<a-button size="small"> {{ pageSize }}{{ $t('cmdb.history.itemsPerPage') }} <a-icon type="down" /> </a-button>
|
||||||
</a-dropdown>
|
</a-dropdown>
|
||||||
</a-space>
|
</a-space>
|
||||||
</a-col>
|
</a-col>
|
||||||
</a-row>
|
</a-row>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
export default {
|
export default {
|
||||||
props: {
|
props: {
|
||||||
currentPage: {
|
currentPage: {
|
||||||
type: Number,
|
type: Number,
|
||||||
required: true
|
required: true
|
||||||
},
|
},
|
||||||
pageSize: {
|
pageSize: {
|
||||||
type: Number,
|
type: Number,
|
||||||
required: true
|
required: true
|
||||||
},
|
},
|
||||||
pageSizes: {
|
pageSizes: {
|
||||||
type: Array,
|
type: Array,
|
||||||
required: true
|
required: true
|
||||||
},
|
},
|
||||||
total: {
|
total: {
|
||||||
type: Number,
|
type: Number,
|
||||||
required: true
|
required: true
|
||||||
},
|
},
|
||||||
isLoading: {
|
isLoading: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
required: false
|
required: false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
dropdownIsDisabled: false,
|
dropdownIsDisabled: false,
|
||||||
prevIsDisabled: true,
|
prevIsDisabled: true,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
nextIsDisabled() {
|
nextIsDisabled() {
|
||||||
return this.isLoading || this.total < this.pageSize
|
return this.isLoading || this.total < this.pageSize
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
isLoading: {
|
isLoading: {
|
||||||
immediate: true,
|
immediate: true,
|
||||||
handler: function (val) {
|
handler: function (val) {
|
||||||
if (val === true) {
|
if (val === true) {
|
||||||
this.dropdownIsDisabled = true
|
this.dropdownIsDisabled = true
|
||||||
this.prevIsDisabled = true
|
this.prevIsDisabled = true
|
||||||
} else {
|
} else {
|
||||||
this.dropdownIsDisabled = false
|
this.dropdownIsDisabled = false
|
||||||
if (this.currentPage === 1) {
|
if (this.currentPage === 1) {
|
||||||
this.prevIsDisabled = true
|
this.prevIsDisabled = true
|
||||||
} else {
|
} else {
|
||||||
this.prevIsDisabled = false
|
this.prevIsDisabled = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
currentPage: {
|
currentPage: {
|
||||||
immediate: true,
|
immediate: true,
|
||||||
handler: function (val) {
|
handler: function (val) {
|
||||||
if (val === 1) {
|
if (val === 1) {
|
||||||
this.prevIsDisabled = true
|
this.prevIsDisabled = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
handleItemClick(size) {
|
handleItemClick(size) {
|
||||||
this.$emit('showSizeChange', size)
|
this.$emit('showSizeChange', size)
|
||||||
},
|
},
|
||||||
nextPage() {
|
nextPage() {
|
||||||
const pageNum = this.currentPage + 1
|
const pageNum = this.currentPage + 1
|
||||||
this.$emit('change', pageNum)
|
this.$emit('change', pageNum)
|
||||||
},
|
},
|
||||||
prevPage() {
|
prevPage() {
|
||||||
const pageNum = this.currentPage - 1
|
const pageNum = this.currentPage - 1
|
||||||
this.$emit('change', pageNum)
|
this.$emit('change', pageNum)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="less" scoped>
|
<style lang="less" scoped>
|
||||||
.row{
|
.row{
|
||||||
margin-top: 5px;
|
margin-top: 5px;
|
||||||
.left-button{
|
.left-button{
|
||||||
padding: 0;
|
padding: 0;
|
||||||
width: 24px;
|
width: 24px;
|
||||||
}
|
}
|
||||||
.right-button{
|
.right-button{
|
||||||
padding: 0;
|
padding: 0;
|
||||||
width: 24px;
|
width: 24px;
|
||||||
}
|
}
|
||||||
.page-button{
|
.page-button{
|
||||||
padding: 0;
|
padding: 0;
|
||||||
width: 24px;
|
width: 24px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -1,404 +1,395 @@
|
||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<search-form
|
<search-form
|
||||||
:attrList="relationTableAttrList"
|
:attrList="relationTableAttrList"
|
||||||
@expandChange="handleExpandChange"
|
@expandChange="handleExpandChange"
|
||||||
@search="handleSearch"
|
@search="handleSearch"
|
||||||
@searchFormReset="searchFormReset"
|
@searchFormReset="searchFormReset"
|
||||||
></search-form>
|
></search-form>
|
||||||
<vxe-table
|
<vxe-table
|
||||||
ref="xTable"
|
ref="xTable"
|
||||||
:loading="loading"
|
:loading="loading"
|
||||||
size="small"
|
size="small"
|
||||||
show-overflow="tooltip"
|
show-overflow="tooltip"
|
||||||
show-header-overflow="tooltip"
|
show-header-overflow="tooltip"
|
||||||
resizable
|
resizable
|
||||||
:data="tableData"
|
:data="tableData"
|
||||||
:max-height="`${windowHeight - windowHeightMinus}px`"
|
:max-height="`${windowHeight - windowHeightMinus}px`"
|
||||||
row-id="_XID"
|
row-id="_XID"
|
||||||
:scroll-y="{ enabled: false }"
|
:scroll-y="{ enabled: false }"
|
||||||
:span-method="mergeRowMethod"
|
:span-method="mergeRowMethod"
|
||||||
stripe
|
stripe
|
||||||
class="ops-stripe-table"
|
class="ops-stripe-table"
|
||||||
>
|
>
|
||||||
<vxe-column field="created_at" width="159px" title="操作时间"></vxe-column>
|
<vxe-column field="created_at" width="159px" :title="$t('cmdb.history.opreateTime')"></vxe-column>
|
||||||
<vxe-column field="user" width="100px" title="用户">
|
<vxe-column field="user" width="100px" :title="$t('cmdb.history.user')">
|
||||||
<template #header="{ column }">
|
<template #header="{ column }">
|
||||||
<span>{{ column.title }}</span>
|
<span>{{ column.title }}</span>
|
||||||
<a-popover trigger="click" placement="bottom">
|
<a-popover trigger="click" placement="bottom">
|
||||||
<a-icon class="filter" type="filter" theme="filled" />
|
<a-icon class="filter" type="filter" theme="filled" />
|
||||||
<a slot="content">
|
<a slot="content">
|
||||||
<a-input
|
<a-input
|
||||||
placeholder="输入筛选用户名"
|
:placeholder="$t('cmdb.history.userTips')"
|
||||||
size="small"
|
size="small"
|
||||||
v-model="queryParams.username"
|
v-model="queryParams.username"
|
||||||
style="width: 200px"
|
style="width: 200px"
|
||||||
allowClear
|
allowClear
|
||||||
/>
|
/>
|
||||||
<a-button type="link" class="filterButton" @click="filterUser">筛选</a-button>
|
<a-button type="link" class="filterButton" @click="filterUser">{{ $t('cmdb.history.filter') }}</a-button>
|
||||||
<a-button type="link" class="filterResetButton" @click="filterUserReset">重置</a-button>
|
<a-button type="link" class="filterResetButton" @click="filterUserReset">{{ $t('reset') }}</a-button>
|
||||||
</a>
|
</a>
|
||||||
</a-popover>
|
</a-popover>
|
||||||
</template>
|
</template>
|
||||||
</vxe-column>
|
</vxe-column>
|
||||||
<vxe-column field="operate_type" width="89px" title="操作">
|
<vxe-column field="operate_type" width="89px" :title="$t('operation')">
|
||||||
<template #header="{ column }">
|
<template #header="{ column }">
|
||||||
<span>{{ column.title }}</span>
|
<span>{{ column.title }}</span>
|
||||||
<a-popover trigger="click" placement="bottom">
|
<a-popover trigger="click" placement="bottom">
|
||||||
<a-icon class="filter" type="filter" theme="filled" />
|
<a-icon class="filter" type="filter" theme="filled" />
|
||||||
<a slot="content">
|
<a slot="content">
|
||||||
<a-select
|
<a-select
|
||||||
v-model="queryParams.operate_type"
|
v-model="queryParams.operate_type"
|
||||||
placeholder="选择筛选操作"
|
:placeholder="$t('cmdb.history.filterOperate')"
|
||||||
show-search
|
show-search
|
||||||
style="width: 200px"
|
style="width: 200px"
|
||||||
:filter-option="filterOption"
|
:filter-option="filterOption"
|
||||||
allowClear
|
allowClear
|
||||||
>
|
>
|
||||||
<a-select-option
|
<a-select-option
|
||||||
:value="Object.values(choice)[0]"
|
:value="Object.values(choice)[0]"
|
||||||
:key="index"
|
:key="index"
|
||||||
v-for="(choice, index) in relationTableAttrList[4].choice_value"
|
v-for="(choice, index) in relationTableAttrList[4].choice_value"
|
||||||
>
|
>
|
||||||
{{ Object.keys(choice)[0] }}
|
{{ Object.keys(choice)[0] }}
|
||||||
</a-select-option>
|
</a-select-option>
|
||||||
</a-select>
|
</a-select>
|
||||||
<a-button type="link" class="filterButton" @click="filterOperate">筛选</a-button>
|
<a-button type="link" class="filterButton" @click="filterOperate">{{
|
||||||
<a-button type="link" class="filterResetButton" @click="filterOperateReset">重置</a-button>
|
$t('cmdb.history.filter')
|
||||||
</a>
|
}}</a-button>
|
||||||
</a-popover>
|
<a-button type="link" class="filterResetButton" @click="filterOperateReset">{{ $t('reset') }}</a-button>
|
||||||
</template>
|
</a>
|
||||||
<template #default="{ row }">
|
</a-popover>
|
||||||
<a-tag color="green" v-if="row.operate_type.includes('新增')">
|
</template>
|
||||||
{{ row.operate_type }}
|
<template #default="{ row }">
|
||||||
</a-tag>
|
<a-tag color="green" v-if="row.operate_type.includes($t('new'))">
|
||||||
<a-tag color="orange" v-else-if="row.operate_type.includes('修改')">
|
{{ row.operate_type }}
|
||||||
{{ row.operate_type }}
|
</a-tag>
|
||||||
</a-tag>
|
<a-tag color="orange" v-else-if="row.operate_type.includes($t('update'))">
|
||||||
<a-tag color="red" v-else>
|
{{ row.operate_type }}
|
||||||
{{ row.operate_type }}
|
</a-tag>
|
||||||
</a-tag>
|
<a-tag color="red" v-else>
|
||||||
</template>
|
{{ row.operate_type }}
|
||||||
</vxe-column>
|
</a-tag>
|
||||||
<vxe-column field="changeDescription" title="描述">
|
</template>
|
||||||
<template #default="{ row }">
|
</vxe-column>
|
||||||
<a-tag v-if="row && row.first">
|
<vxe-column field="changeDescription" :title="$t('desc')">
|
||||||
{{
|
<template #default="{ row }">
|
||||||
`${row.first.ci_type_alias}${
|
<a-tag v-if="row && row.first">
|
||||||
row.first.unique_alias && row.first[row.first.unique]
|
{{
|
||||||
? `(${row.first.unique_alias}:${row.first[row.first.unique]})`
|
`${row.first.ci_type_alias}${
|
||||||
: ''
|
row.first.unique_alias && row.first[row.first.unique]
|
||||||
}`
|
? `(${row.first.unique_alias}:${row.first[row.first.unique]})`
|
||||||
}}
|
: ''
|
||||||
</a-tag>
|
}`
|
||||||
<a-tag v-if="row.changeDescription === '没有修改'">
|
}}
|
||||||
{{ row.relation_type_id }}
|
</a-tag>
|
||||||
</a-tag>
|
<a-tag v-if="row.changeDescription === $t('cmdb.history.noUpdate')">
|
||||||
<template v-else-if="row.operate_type.includes('修改')">
|
{{ row.relation_type_id }}
|
||||||
<a-tag :key="index" color="orange" v-for="(tag, index) in row.changeArr">
|
</a-tag>
|
||||||
{{ tag }}
|
<template v-else-if="row.operate_type.includes($t('update'))">
|
||||||
</a-tag>
|
<a-tag :key="index" color="orange" v-for="(tag, index) in row.changeArr">
|
||||||
</template>
|
{{ tag }}
|
||||||
<a-tag color="green" v-else-if="row.operate_type.includes('新增')" :style="{ fontWeight: 'bolder' }">
|
</a-tag>
|
||||||
{{ row.relation_type_id }}
|
</template>
|
||||||
</a-tag>
|
<a-tag color="green" v-else-if="row.operate_type.includes($t('new'))" :style="{ fontWeight: 'bolder' }">
|
||||||
<a-tag color="red" v-else-if="row.operate_type.includes('删除')">
|
{{ row.relation_type_id }}
|
||||||
{{ row.relation_type_id }}
|
</a-tag>
|
||||||
</a-tag>
|
<a-tag color="red" v-else-if="row.operate_type.includes($t('delete'))">
|
||||||
<a-tag v-if="row && row.second">
|
{{ row.relation_type_id }}
|
||||||
{{
|
</a-tag>
|
||||||
`${row.second.ci_type_alias}${
|
<a-tag v-if="row && row.second">
|
||||||
row.second.unique_alias && row.second[row.second.unique]
|
{{
|
||||||
? `(${row.second.unique_alias}:${row.second[row.second.unique]})`
|
`${row.second.ci_type_alias}${
|
||||||
: ''
|
row.second.unique_alias && row.second[row.second.unique]
|
||||||
}`
|
? `(${row.second.unique_alias}:${row.second[row.second.unique]})`
|
||||||
}}
|
: ''
|
||||||
</a-tag>
|
}`
|
||||||
</template>
|
}}
|
||||||
</vxe-column>
|
</a-tag>
|
||||||
</vxe-table>
|
</template>
|
||||||
<pager
|
</vxe-column>
|
||||||
:current-page.sync="queryParams.page"
|
</vxe-table>
|
||||||
:page-size.sync="queryParams.page_size"
|
<pager
|
||||||
:page-sizes="[50, 100, 200]"
|
:current-page.sync="queryParams.page"
|
||||||
:total="total"
|
:page-size.sync="queryParams.page_size"
|
||||||
:isLoading="loading"
|
:page-sizes="[50, 100, 200]"
|
||||||
@change="onChange"
|
:total="total"
|
||||||
@showSizeChange="onShowSizeChange"
|
:isLoading="loading"
|
||||||
></pager>
|
@change="onChange"
|
||||||
</div>
|
@showSizeChange="onShowSizeChange"
|
||||||
</template>
|
></pager>
|
||||||
|
</div>
|
||||||
<script>
|
</template>
|
||||||
import SearchForm from './searchForm'
|
|
||||||
import Pager from './pager.vue'
|
<script>
|
||||||
import { getCITypes } from '@/modules/cmdb/api/CIType'
|
import { mapState } from 'vuex'
|
||||||
import { getRelationTable, getUsers } from '@/modules/cmdb/api/history'
|
import SearchForm from './searchForm'
|
||||||
import { getRelationTypes } from '@/modules/cmdb/api/relationType'
|
import Pager from './pager.vue'
|
||||||
export default {
|
import { getCITypes } from '@/modules/cmdb/api/CIType'
|
||||||
name: 'RelationTable',
|
import { getRelationTable, getUsers } from '@/modules/cmdb/api/history'
|
||||||
components: { SearchForm, Pager },
|
import { getRelationTypes } from '@/modules/cmdb/api/relationType'
|
||||||
data() {
|
export default {
|
||||||
return {
|
name: 'RelationTable',
|
||||||
visible: false,
|
components: { SearchForm, Pager },
|
||||||
loading: true,
|
inject: ['reload'],
|
||||||
isExpand: false,
|
data() {
|
||||||
tableData: [],
|
return {
|
||||||
relationTypeList: null,
|
visible: false,
|
||||||
total: 0,
|
loading: true,
|
||||||
userList: [],
|
isExpand: false,
|
||||||
operateTypeMap: new Map([
|
tableData: [],
|
||||||
['0', '新增'],
|
relationTypeList: null,
|
||||||
['1', '删除'],
|
total: 0,
|
||||||
['2', '修改'],
|
userList: [],
|
||||||
]),
|
queryParams: {
|
||||||
queryParams: {
|
page: 1,
|
||||||
page: 1,
|
page_size: 50,
|
||||||
page_size: 50,
|
start: '',
|
||||||
start: '',
|
end: '',
|
||||||
end: '',
|
username: '',
|
||||||
username: '',
|
first_ci_id: undefined,
|
||||||
first_ci_id: undefined,
|
second_ci_id: undefined,
|
||||||
second_ci_id: undefined,
|
operate_type: undefined,
|
||||||
operate_type: undefined,
|
},
|
||||||
},
|
relationTableAttrList: [
|
||||||
relationTableAttrList: [
|
{
|
||||||
{
|
alias: this.$t('cmdb.ciType.date'),
|
||||||
alias: '日期',
|
is_choice: false,
|
||||||
is_choice: false,
|
name: 'datetime',
|
||||||
name: 'datetime',
|
value_type: '3',
|
||||||
value_type: '3',
|
},
|
||||||
},
|
{
|
||||||
{
|
alias: this.$t('cmdb.history.user'),
|
||||||
alias: '用户',
|
is_choice: true,
|
||||||
is_choice: true,
|
name: 'username',
|
||||||
name: 'username',
|
value_type: '2',
|
||||||
value_type: '2',
|
choice_value: [],
|
||||||
choice_value: [],
|
},
|
||||||
},
|
{
|
||||||
{
|
alias: 'FirstCI_ID',
|
||||||
alias: 'FirstCI_ID',
|
is_choice: false,
|
||||||
is_choice: false,
|
name: 'first_ci_id',
|
||||||
name: 'first_ci_id',
|
value_type: '2',
|
||||||
value_type: '2',
|
choice_value: [],
|
||||||
choice_value: [],
|
},
|
||||||
},
|
{
|
||||||
{
|
alias: 'SecondCI_ID',
|
||||||
alias: 'SecondCI_ID',
|
is_choice: false,
|
||||||
is_choice: false,
|
name: 'second_ci_id',
|
||||||
name: 'second_ci_id',
|
value_type: '2',
|
||||||
value_type: '2',
|
choice_value: [],
|
||||||
choice_value: [],
|
},
|
||||||
},
|
{
|
||||||
{
|
alias: this.$t('operation'),
|
||||||
alias: '操作',
|
is_choice: true,
|
||||||
is_choice: true,
|
name: 'operate_type',
|
||||||
name: 'operate_type',
|
value_type: '2',
|
||||||
value_type: '2',
|
choice_value: [{ [this.$t('new')]: 0 }, { [this.$t('delete')]: 1 }, { [this.$t('update')]: 2 }],
|
||||||
choice_value: [{ 新增: 0 }, { 删除: 1 }, { 修改: 2 }],
|
},
|
||||||
},
|
],
|
||||||
],
|
}
|
||||||
}
|
},
|
||||||
},
|
async created() {
|
||||||
async created() {
|
await Promise.all([this.getRelationTypes(), this.getUserList(), this.getTypes()])
|
||||||
await Promise.all([
|
await this.getTable(this.queryParams)
|
||||||
this.getRelationTypes(),
|
},
|
||||||
this.getUserList(),
|
updated() {
|
||||||
this.getTypes(),
|
this.$refs.xTable.$el.querySelector('.vxe-table--body-wrapper').scrollTop = 0
|
||||||
])
|
},
|
||||||
await this.getTable(this.queryParams)
|
computed: {
|
||||||
},
|
...mapState(['locale']),
|
||||||
updated() {
|
windowHeight() {
|
||||||
this.$refs.xTable.$el.querySelector('.vxe-table--body-wrapper').scrollTop = 0
|
return this.$store.state.windowHeight
|
||||||
},
|
},
|
||||||
computed: {
|
windowHeightMinus() {
|
||||||
windowHeight() {
|
return this.isExpand ? 396 : 331
|
||||||
return this.$store.state.windowHeight
|
},
|
||||||
},
|
operateTypeMap() {
|
||||||
windowHeightMinus() {
|
return new Map([
|
||||||
return this.isExpand ? 396 : 331
|
['0', this.$t('new')],
|
||||||
},
|
['1', this.$t('delete')],
|
||||||
},
|
['2', this.$t('update')],
|
||||||
methods: {
|
])
|
||||||
// 获取表格数据
|
},
|
||||||
async getTable(queryParams) {
|
},
|
||||||
try {
|
watch: {
|
||||||
this.loading = true
|
locale() {
|
||||||
const res = await getRelationTable(queryParams)
|
this.reload()
|
||||||
const tempArr = []
|
},
|
||||||
res.records.forEach((item) => {
|
},
|
||||||
item[1].forEach((subItem) => {
|
methods: {
|
||||||
subItem.operate_type = this.handleOperateType(subItem.operate_type)
|
async getTable(queryParams) {
|
||||||
subItem.relation_type_id = this.handleRelationType(subItem.relation_type_id)
|
try {
|
||||||
subItem.first = res.cis[String(subItem.first_ci_id)]
|
this.loading = true
|
||||||
subItem.second = res.cis[String(subItem.second_ci_id)]
|
const res = await getRelationTable(queryParams)
|
||||||
const tempObj = Object.assign(subItem, item[0])
|
const tempArr = []
|
||||||
tempArr.push(tempObj)
|
res.records.forEach((item) => {
|
||||||
})
|
item[1].forEach((subItem) => {
|
||||||
})
|
subItem.operate_type = this.handleOperateType(subItem.operate_type)
|
||||||
this.total = res.total
|
subItem.relation_type_id = this.handleRelationType(subItem.relation_type_id)
|
||||||
this.tableData = tempArr
|
subItem.first = res.cis[String(subItem.first_ci_id)]
|
||||||
} finally {
|
subItem.second = res.cis[String(subItem.second_ci_id)]
|
||||||
this.loading = false
|
const tempObj = Object.assign(subItem, item[0])
|
||||||
}
|
tempArr.push(tempObj)
|
||||||
},
|
})
|
||||||
// 获取用户列表
|
})
|
||||||
async getUserList() {
|
this.total = res.total
|
||||||
const res = await getUsers()
|
this.tableData = tempArr
|
||||||
this.userList = res.map((x) => {
|
} finally {
|
||||||
const username = x.nickname
|
this.loading = false
|
||||||
const obj = {
|
}
|
||||||
[username]: username,
|
},
|
||||||
}
|
async getUserList() {
|
||||||
return obj
|
const res = await getUsers()
|
||||||
})
|
this.userList = res.map((x) => {
|
||||||
this.relationTableAttrList[1].choice_value = this.userList
|
const username = x.nickname
|
||||||
},
|
const obj = {
|
||||||
// 获取模型
|
[username]: username,
|
||||||
async getTypes() {
|
}
|
||||||
const res = await getCITypes()
|
return obj
|
||||||
const typesArr = []
|
})
|
||||||
res.ci_types.forEach((item) => {
|
this.relationTableAttrList[1].choice_value = this.userList
|
||||||
const tempObj = {}
|
},
|
||||||
tempObj[item.alias] = item.id
|
async getTypes() {
|
||||||
if (item.alias) {
|
const res = await getCITypes()
|
||||||
typesArr.push(tempObj)
|
const typesArr = []
|
||||||
}
|
res.ci_types.forEach((item) => {
|
||||||
})
|
const tempObj = {}
|
||||||
this.relationTableAttrList[2].choice_value = typesArr
|
tempObj[item.alias] = item.id
|
||||||
this.relationTableAttrList[3].choice_value = typesArr
|
if (item.alias) {
|
||||||
},
|
typesArr.push(tempObj)
|
||||||
// 获取关系
|
}
|
||||||
async getRelationTypes() {
|
})
|
||||||
const res = await getRelationTypes()
|
this.relationTableAttrList[2].choice_value = typesArr
|
||||||
const relationTypeMap = new Map()
|
this.relationTableAttrList[3].choice_value = typesArr
|
||||||
res.forEach((item) => {
|
},
|
||||||
relationTypeMap.set(item.id, item.name)
|
async getRelationTypes() {
|
||||||
})
|
const res = await getRelationTypes()
|
||||||
this.relationTypeList = relationTypeMap
|
const relationTypeMap = new Map()
|
||||||
},
|
res.forEach((item) => {
|
||||||
onShowSizeChange(size) {
|
relationTypeMap.set(item.id, item.name)
|
||||||
this.queryParams.page_size = size
|
})
|
||||||
this.queryParams.page = 1
|
this.relationTypeList = relationTypeMap
|
||||||
this.getTable(this.queryParams)
|
},
|
||||||
},
|
onShowSizeChange(size) {
|
||||||
onChange(pageNum) {
|
this.queryParams.page_size = size
|
||||||
this.queryParams.page = pageNum
|
this.queryParams.page = 1
|
||||||
this.getTable(this.queryParams)
|
this.getTable(this.queryParams)
|
||||||
},
|
},
|
||||||
handleExpandChange(expand) {
|
onChange(pageNum) {
|
||||||
this.isExpand = expand
|
this.queryParams.page = pageNum
|
||||||
},
|
this.getTable(this.queryParams)
|
||||||
// 处理查询
|
},
|
||||||
handleSearch(queryParams) {
|
handleExpandChange(expand) {
|
||||||
this.queryParams = queryParams
|
this.isExpand = expand
|
||||||
this.getTable(queryParams)
|
},
|
||||||
},
|
handleSearch(queryParams) {
|
||||||
// 重置表单
|
this.queryParams = queryParams
|
||||||
searchFormReset() {
|
this.getTable(queryParams)
|
||||||
this.queryParams = {
|
},
|
||||||
page: 1,
|
searchFormReset() {
|
||||||
page_size: 50,
|
this.queryParams = {
|
||||||
start: '',
|
page: 1,
|
||||||
end: '',
|
page_size: 50,
|
||||||
username: '',
|
start: '',
|
||||||
first_ci_id: undefined,
|
end: '',
|
||||||
second_ci_id: undefined,
|
username: '',
|
||||||
operate_type: undefined,
|
first_ci_id: undefined,
|
||||||
}
|
second_ci_id: undefined,
|
||||||
this.getTable(this.queryParams)
|
operate_type: undefined,
|
||||||
},
|
}
|
||||||
// 转换operate_type
|
this.getTable(this.queryParams)
|
||||||
handleOperateType(operate_type) {
|
},
|
||||||
return this.operateTypeMap.get(operate_type)
|
handleOperateType(operate_type) {
|
||||||
},
|
return this.operateTypeMap.get(operate_type)
|
||||||
// 转换relation_type_id
|
},
|
||||||
handleRelationType(relation_type_id) {
|
handleRelationType(relation_type_id) {
|
||||||
return this.relationTypeList.get(relation_type_id)
|
return this.relationTypeList.get(relation_type_id)
|
||||||
},
|
},
|
||||||
// 合并表格
|
mergeRowMethod({ row, _rowIndex, column, visibleData }) {
|
||||||
mergeRowMethod({ row, _rowIndex, column, visibleData }) {
|
const fields = ['created_at', 'user']
|
||||||
const fields = ['created_at', 'user']
|
const cellValue = row[column.property]
|
||||||
// 单元格值 = 行[列.属性] 确定一格
|
const created_at = row['created_at']
|
||||||
const cellValue = row[column.property]
|
if (column.property === 'created_at') {
|
||||||
const created_at = row['created_at']
|
if (cellValue && fields.includes(column.property)) {
|
||||||
// 如果单元格值不为空且作用域包含当前列
|
const prevRow = visibleData[_rowIndex - 1]
|
||||||
if (column.property === 'created_at') {
|
let nextRow = visibleData[_rowIndex + 1]
|
||||||
if (cellValue && fields.includes(column.property)) {
|
if (prevRow && prevRow[column.property] === cellValue) {
|
||||||
// 前一行
|
return { rowspan: 0, colspan: 0 }
|
||||||
const prevRow = visibleData[_rowIndex - 1]
|
} else {
|
||||||
// 下一行
|
let countRowspan = 1
|
||||||
let nextRow = visibleData[_rowIndex + 1]
|
while (nextRow && nextRow[column.property] === cellValue) {
|
||||||
// 如果前一行不为空且前一行单元格的值与cellValue相同
|
nextRow = visibleData[++countRowspan + _rowIndex]
|
||||||
if (prevRow && prevRow[column.property] === cellValue) {
|
}
|
||||||
return { rowspan: 0, colspan: 0 }
|
if (countRowspan > 1) {
|
||||||
} else {
|
return { rowspan: countRowspan, colspan: 1 }
|
||||||
let countRowspan = 1
|
}
|
||||||
while (nextRow && nextRow[column.property] === cellValue) {
|
}
|
||||||
nextRow = visibleData[++countRowspan + _rowIndex]
|
}
|
||||||
}
|
} else if (column.property === 'user') {
|
||||||
if (countRowspan > 1) {
|
if (cellValue && fields.includes(column.property)) {
|
||||||
return { rowspan: countRowspan, colspan: 1 }
|
const prevRow = visibleData[_rowIndex - 1]
|
||||||
}
|
let nextRow = visibleData[_rowIndex + 1]
|
||||||
}
|
if (prevRow && prevRow[column.property] === cellValue && prevRow['created_at'] === created_at) {
|
||||||
}
|
return { rowspan: 0, colspan: 0 }
|
||||||
} else if (column.property === 'user') {
|
} else {
|
||||||
if (cellValue && fields.includes(column.property)) {
|
let countRowspan = 1
|
||||||
// 前一行
|
while (nextRow && nextRow[column.property] === cellValue && nextRow['created_at'] === created_at) {
|
||||||
const prevRow = visibleData[_rowIndex - 1]
|
nextRow = visibleData[++countRowspan + _rowIndex]
|
||||||
// 下一行
|
}
|
||||||
let nextRow = visibleData[_rowIndex + 1]
|
if (countRowspan > 1) {
|
||||||
// 如果前一行不为空且前一行单元格的值与cellValue相同
|
return { rowspan: countRowspan, colspan: 1 }
|
||||||
if (prevRow && prevRow[column.property] === cellValue && prevRow['created_at'] === created_at) {
|
}
|
||||||
return { rowspan: 0, colspan: 0 }
|
}
|
||||||
} else {
|
}
|
||||||
let countRowspan = 1
|
}
|
||||||
while (nextRow && nextRow[column.property] === cellValue && nextRow['created_at'] === created_at) {
|
},
|
||||||
nextRow = visibleData[++countRowspan + _rowIndex]
|
filterUser() {
|
||||||
}
|
this.queryParams.page = 1
|
||||||
if (countRowspan > 1) {
|
this.queryParams.page_size = 50
|
||||||
return { rowspan: countRowspan, colspan: 1 }
|
this.getTable(this.queryParams)
|
||||||
}
|
},
|
||||||
}
|
filterUserReset() {
|
||||||
}
|
this.queryParams.page = 1
|
||||||
}
|
this.queryParams.page_size = 50
|
||||||
},
|
this.queryParams.username = ''
|
||||||
filterUser() {
|
this.getTable(this.queryParams)
|
||||||
this.queryParams.page = 1
|
},
|
||||||
this.queryParams.page_size = 50
|
filterOperate() {
|
||||||
this.getTable(this.queryParams)
|
this.queryParams.page = 1
|
||||||
},
|
this.queryParams.page_size = 50
|
||||||
filterUserReset() {
|
this.getTable(this.queryParams)
|
||||||
this.queryParams.page = 1
|
},
|
||||||
this.queryParams.page_size = 50
|
filterOperateReset() {
|
||||||
this.queryParams.username = ''
|
this.queryParams.page = 1
|
||||||
this.getTable(this.queryParams)
|
this.queryParams.page_size = 50
|
||||||
},
|
this.queryParams.operate_type = undefined
|
||||||
filterOperate() {
|
this.getTable(this.queryParams)
|
||||||
this.queryParams.page = 1
|
},
|
||||||
this.queryParams.page_size = 50
|
filterOption(input, option) {
|
||||||
this.getTable(this.queryParams)
|
return option.componentOptions.children[0].text.indexOf(input) >= 0
|
||||||
},
|
},
|
||||||
filterOperateReset() {
|
},
|
||||||
this.queryParams.page = 1
|
}
|
||||||
this.queryParams.page_size = 50
|
</script>
|
||||||
this.queryParams.operate_type = undefined
|
|
||||||
this.getTable(this.queryParams)
|
<style lang="less" scoped>
|
||||||
},
|
.filter {
|
||||||
filterOption(input, option) {
|
margin-left: 10px;
|
||||||
return option.componentOptions.children[0].text.indexOf(input) >= 0
|
color: #c0c4cc;
|
||||||
},
|
cursor: pointer;
|
||||||
},
|
&:hover {
|
||||||
}
|
color: #606266;
|
||||||
</script>
|
}
|
||||||
|
}
|
||||||
<style lang="less" scoped>
|
</style>
|
||||||
.filter {
|
|
||||||
margin-left: 10px;
|
|
||||||
color: #c0c4cc;
|
|
||||||
cursor: pointer;
|
|
||||||
&:hover {
|
|
||||||
color: #606266;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
|
@ -1,191 +1,195 @@
|
||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<a-form :colon="false">
|
<a-form :colon="false">
|
||||||
<a-row :gutter="24">
|
<a-row :gutter="24">
|
||||||
<a-col
|
<a-col
|
||||||
:sm="24"
|
:sm="24"
|
||||||
:md="12"
|
:md="12"
|
||||||
:lg="12"
|
:lg="12"
|
||||||
:xl="8"
|
:xl="8"
|
||||||
v-for="attr in attrList.slice(0,3)"
|
v-for="attr in attrList.slice(0,3)"
|
||||||
:key="attr.name"
|
:key="attr.name"
|
||||||
>
|
>
|
||||||
<a-form-item
|
<a-form-item
|
||||||
:label="attr.alias || attr.name "
|
:label="attr.alias || attr.name "
|
||||||
:labelCol="{span:4}"
|
:labelCol="{span:4}"
|
||||||
:wrapperCol="{span:20}"
|
:wrapperCol="{span:20}"
|
||||||
labelAlign="right"
|
labelAlign="right"
|
||||||
>
|
>
|
||||||
<a-select
|
<a-select
|
||||||
v-model="queryParams[attr.name]"
|
v-model="queryParams[attr.name]"
|
||||||
placeholder="请选择"
|
:placeholder="$t('cmdb.history.pleaseSelect')"
|
||||||
v-if="attr.is_choice"
|
v-if="attr.is_choice"
|
||||||
show-search
|
show-search
|
||||||
:filter-option="filterOption"
|
:filter-option="filterOption"
|
||||||
allowClear
|
allowClear
|
||||||
>
|
>
|
||||||
<a-select-option
|
<a-select-option
|
||||||
:value="Object.values(choice)[0]"
|
:value="Object.values(choice)[0]"
|
||||||
v-for="(choice, index) in attr.choice_value"
|
v-for="(choice, index) in attr.choice_value"
|
||||||
:key="'Search_' + attr.name + index"
|
:key="'Search_' + attr.name + index"
|
||||||
>
|
>
|
||||||
{{ Object.keys(choice)[0] }}
|
{{ Object.keys(choice)[0] }}
|
||||||
</a-select-option>
|
</a-select-option>
|
||||||
</a-select>
|
</a-select>
|
||||||
<a-range-picker
|
<a-range-picker
|
||||||
v-model="date"
|
v-model="date"
|
||||||
@change="onChange"
|
@change="onChange"
|
||||||
:style="{width:'100%'}"
|
:style="{width:'100%'}"
|
||||||
format="YYYY-MM-DD HH:mm:ss"
|
format="YYYY-MM-DD HH:mm:ss"
|
||||||
:placeholder="['开始时间', '结束时间']"
|
:placeholder="[$t('cmdb.history.startTime'), $t('cmdb.history.endTime')]"
|
||||||
:show-time="{
|
:show-time="{
|
||||||
hideDisabledOptions: true,
|
hideDisabledOptions: true,
|
||||||
defaultValue: [moment('00:00:00', 'HH:mm:ss'), moment('23:59:59', 'HH:mm:ss')],
|
defaultValue: [moment('00:00:00', 'HH:mm:ss'), moment('23:59:59', 'HH:mm:ss')],
|
||||||
}"
|
}"
|
||||||
v-else-if="valueTypeMap[attr.value_type] == 'date' || valueTypeMap[attr.value_type] == 'datetime'"
|
v-else-if="valueTypeMap[attr.value_type] == 'date' || valueTypeMap[attr.value_type] == 'datetime'"
|
||||||
/>
|
/>
|
||||||
<a-input v-model="queryParams[attr.name]" style="width: 100%" allowClear v-else />
|
<a-input v-model="queryParams[attr.name]" style="width: 100%" allowClear v-else />
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
</a-col>
|
</a-col>
|
||||||
|
|
||||||
<template v-if="expand && attrList.length >= 4">
|
<template v-if="expand && attrList.length >= 4">
|
||||||
<a-col
|
<a-col
|
||||||
:sm="24"
|
:sm="24"
|
||||||
:md="12"
|
:md="12"
|
||||||
:lg="8"
|
:lg="8"
|
||||||
:xl="8"
|
:xl="8"
|
||||||
:key="'expand_' + item.name"
|
:key="'expand_' + item.name"
|
||||||
v-for="item in attrList.slice(3)"
|
v-for="item in attrList.slice(3)"
|
||||||
>
|
>
|
||||||
<a-form-item
|
<a-form-item
|
||||||
:label="item.alias || item.name"
|
:label="item.alias || item.name"
|
||||||
:label-col="{ span: 4 }"
|
:label-col="{ span: 4 }"
|
||||||
:wrapper-col="{ span: 20 }"
|
:wrapper-col="{ span: 20 }"
|
||||||
labelAlign="right"
|
labelAlign="right"
|
||||||
>
|
>
|
||||||
<a-select
|
<a-select
|
||||||
v-model="queryParams[item.name]"
|
v-model="queryParams[item.name]"
|
||||||
placeholder="请选择"
|
:placeholder="$t('cmdb.history.pleaseSelect')"
|
||||||
v-if="item.is_choice"
|
v-if="item.is_choice"
|
||||||
show-search
|
show-search
|
||||||
:filter-option="filterOption"
|
:filter-option="filterOption"
|
||||||
allowClear
|
allowClear
|
||||||
>
|
>
|
||||||
<a-select-option
|
<a-select-option
|
||||||
:value="Object.values(choice)[0]"
|
:value="Object.values(choice)[0]"
|
||||||
:key="'Search_' + item.name + index"
|
:key="'Search_' + item.name + index"
|
||||||
v-for="(choice, index) in item.choice_value"
|
v-for="(choice, index) in item.choice_value"
|
||||||
>
|
>
|
||||||
{{ Object.keys(choice)[0] }}
|
{{ Object.keys(choice)[0] }}
|
||||||
</a-select-option
|
</a-select-option
|
||||||
>
|
>
|
||||||
</a-select>
|
</a-select>
|
||||||
<a-range-picker
|
<a-range-picker
|
||||||
:style="{width:'100%'}"
|
:style="{width:'100%'}"
|
||||||
@change="onChange"
|
@change="onChange"
|
||||||
format="YYYY-MM-DD HH:mm"
|
format="YYYY-MM-DD HH:mm"
|
||||||
:placeholder="['开始时间', '结束时间']"
|
:placeholder="[$t('cmdb.history.startTime'), $t('cmdb.history.endTime')]"
|
||||||
v-else-if="valueTypeMap[item.value_type] == 'date' || valueTypeMap[item.value_type] == 'datetime'"
|
v-else-if="valueTypeMap[item.value_type] == 'date' || valueTypeMap[item.value_type] == 'datetime'"
|
||||||
:show-time="{
|
:show-time="{
|
||||||
hideDisabledOptions: true,
|
hideDisabledOptions: true,
|
||||||
defaultValue: [moment('00:00:00', 'HH:mm:ss'), moment('23:59:59', 'HH:mm:ss')],
|
defaultValue: [moment('00:00:00', 'HH:mm:ss'), moment('23:59:59', 'HH:mm:ss')],
|
||||||
}"
|
}"
|
||||||
/>
|
/>
|
||||||
<a-input v-model="queryParams[item.name]" style="width: 100%" allowClear v-else/>
|
<a-input v-model="queryParams[item.name]" style="width: 100%" allowClear v-else/>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
</a-col>
|
</a-col>
|
||||||
</template>
|
</template>
|
||||||
</a-row>
|
</a-row>
|
||||||
<a-row>
|
<a-row>
|
||||||
<a-col :span="24" :style="{ textAlign: 'right' , marginBottom: '10px' }">
|
<a-col :span="24" :style="{ textAlign: 'right' , marginBottom: '10px' }">
|
||||||
<a-button type="primary" html-type="submit" @click="handleSearch">
|
<a-button type="primary" html-type="submit" @click="handleSearch">
|
||||||
查询
|
{{ $t('query') }}
|
||||||
</a-button>
|
</a-button>
|
||||||
<a-button :style="{ marginLeft: '8px' }" @click="handleReset">
|
<a-button :style="{ marginLeft: '8px' }" @click="handleReset">
|
||||||
重置
|
{{ $t('reset') }}
|
||||||
</a-button>
|
</a-button>
|
||||||
<a :style="{ marginLeft: '8px', fontSize: '12px' }" @click="toggle" v-if="attrList.length >= 4">
|
<a :style="{ marginLeft: '8px', fontSize: '12px' }" @click="toggle" v-if="attrList.length >= 4">
|
||||||
{{ expand?'隐藏':'展开' }} <a-icon :type="expand ? 'up' : 'down'" />
|
{{ expand?$t('hide'):$t('expand') }} <a-icon :type="expand ? 'up' : 'down'" />
|
||||||
</a>
|
</a>
|
||||||
</a-col>
|
</a-col>
|
||||||
</a-row>
|
</a-row>
|
||||||
</a-form>
|
</a-form>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import moment from 'moment'
|
import moment from 'moment'
|
||||||
import { valueTypeMap } from '../../../utils/const'
|
import { valueTypeMap } from '../../../utils/const'
|
||||||
export default {
|
export default {
|
||||||
name: 'SearchForm',
|
name: 'SearchForm',
|
||||||
props: {
|
props: {
|
||||||
attrList: {
|
attrList: {
|
||||||
type: Array,
|
type: Array,
|
||||||
required: true
|
required: true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
valueTypeMap,
|
expand: false,
|
||||||
expand: false,
|
queryParams: {
|
||||||
queryParams: {
|
page: 1,
|
||||||
page: 1,
|
page_size: 50
|
||||||
page_size: 50
|
},
|
||||||
},
|
date: undefined
|
||||||
date: undefined
|
}
|
||||||
}
|
},
|
||||||
},
|
computed: {
|
||||||
watch: {
|
valueTypeMap() {
|
||||||
queryParams: {
|
return valueTypeMap()
|
||||||
deep: true,
|
},
|
||||||
handler: function (val) {
|
},
|
||||||
this.preProcessData()
|
watch: {
|
||||||
this.$emit('searchFormChange', val)
|
queryParams: {
|
||||||
}
|
deep: true,
|
||||||
},
|
handler: function (val) {
|
||||||
},
|
this.preProcessData()
|
||||||
methods: {
|
this.$emit('searchFormChange', val)
|
||||||
moment,
|
}
|
||||||
handleSearch() {
|
},
|
||||||
this.queryParams.page = 1
|
},
|
||||||
this.$emit('search', this.queryParams)
|
methods: {
|
||||||
},
|
moment,
|
||||||
|
handleSearch() {
|
||||||
handleReset() {
|
this.queryParams.page = 1
|
||||||
this.queryParams = {
|
this.$emit('search', this.queryParams)
|
||||||
page: 1,
|
},
|
||||||
page_size: 50
|
|
||||||
}
|
handleReset() {
|
||||||
this.date = undefined
|
this.queryParams = {
|
||||||
this.$emit('searchFormReset')
|
page: 1,
|
||||||
},
|
page_size: 50
|
||||||
|
}
|
||||||
toggle() {
|
this.date = undefined
|
||||||
this.expand = !this.expand
|
this.$emit('searchFormReset')
|
||||||
this.$emit('expandChange', this.expand)
|
},
|
||||||
},
|
|
||||||
|
toggle() {
|
||||||
onChange(date, dateString) {
|
this.expand = !this.expand
|
||||||
this.queryParams.start = dateString[0]
|
this.$emit('expandChange', this.expand)
|
||||||
this.queryParams.end = dateString[1]
|
},
|
||||||
},
|
|
||||||
filterOption(input, option) {
|
onChange(date, dateString) {
|
||||||
return (
|
this.queryParams.start = dateString[0]
|
||||||
option.componentOptions.children[0].text.indexOf(input) >= 0
|
this.queryParams.end = dateString[1]
|
||||||
)
|
},
|
||||||
},
|
filterOption(input, option) {
|
||||||
preProcessData() {
|
return (
|
||||||
Object.keys(this.queryParams).forEach(item => {
|
option.componentOptions.children[0].text.indexOf(input) >= 0
|
||||||
if (this.queryParams[item] === '' || this.queryParams[item] === undefined) {
|
)
|
||||||
delete this.queryParams[item]
|
},
|
||||||
}
|
preProcessData() {
|
||||||
})
|
Object.keys(this.queryParams).forEach(item => {
|
||||||
return this.queryParams
|
if (this.queryParams[item] === '' || this.queryParams[item] === undefined) {
|
||||||
},
|
delete this.queryParams[item]
|
||||||
},
|
}
|
||||||
}
|
})
|
||||||
</script>
|
return this.queryParams
|
||||||
|
},
|
||||||
<style>
|
},
|
||||||
|
}
|
||||||
</style>
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
|
||||||
|
</style>
|
||||||
|
|
|
@ -1,123 +1,123 @@
|
||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<vxe-table
|
<vxe-table
|
||||||
show-overflow
|
show-overflow
|
||||||
show-header-overflow
|
show-header-overflow
|
||||||
stripe
|
stripe
|
||||||
size="small"
|
size="small"
|
||||||
class="ops-stripe-table"
|
class="ops-stripe-table"
|
||||||
:data="tableData"
|
:data="tableData"
|
||||||
v-bind="ci_id ? { maxHeight: `${windowHeight - 94}px` } : { height: `${windowHeight - 225}px` }"
|
v-bind="ci_id ? { maxHeight: `${windowHeight - 94}px` } : { height: `${windowHeight - 225}px` }"
|
||||||
>
|
>
|
||||||
<vxe-column field="trigger_name" title="触发器名称"> </vxe-column>
|
<vxe-column field="trigger_name" :title="$t('cmdb.history.triggerName')"> </vxe-column>
|
||||||
<vxe-column field="type" title="类型">
|
<vxe-column field="type" :title="$t('type')">
|
||||||
<template #default="{ row }">
|
<template #default="{ row }">
|
||||||
<span v-if="row.trigger && row.trigger.attr_id">日期属性</span>
|
<span v-if="row.trigger && row.trigger.attr_id">{{ $t('cmdb.ciType.triggerDate') }}</span>
|
||||||
<span v-else-if="row.trigger && !row.trigger.attr_id">数据变更</span>
|
<span v-else-if="row.trigger && !row.trigger.attr_id">{{ $t('cmdb.ciType.triggerDataChange') }}</span>
|
||||||
</template>
|
</template>
|
||||||
</vxe-column>
|
</vxe-column>
|
||||||
<vxe-column title="事件">
|
<vxe-column :title="$t('cmdb.history.event')">
|
||||||
<template #default="{ row }">
|
<template #default="{ row }">
|
||||||
<span v-if="row.operate_type === '0'">新增实例</span>
|
<span v-if="row.operate_type === '0'">{{ $t('cmdb.ciType.addInstance') }}</span>
|
||||||
<span v-else-if="row.operate_type === '1'">删除实例</span>
|
<span v-else-if="row.operate_type === '1'">{{ $t('cmdb.ciType.deleteInstance') }}</span>
|
||||||
<span v-else-if="row.operate_type === '2'">实例变更</span>
|
<span v-else-if="row.operate_type === '2'">{{ $t('cmdb.ciType.changeInstance') }}</span>
|
||||||
</template>
|
</template>
|
||||||
</vxe-column>
|
</vxe-column>
|
||||||
<vxe-column title="动作">
|
<vxe-column :title="$t('cmdb.history.action')">
|
||||||
<template #default="{ row }">
|
<template #default="{ row }">
|
||||||
<span v-if="row.webhook">Webhook</span>
|
<span v-if="row.webhook">Webhook</span>
|
||||||
<span v-else-if="row.notify">通知</span>
|
<span v-else-if="row.notify">{{ $t('cmdb.ciType.notify') }}</span>
|
||||||
</template>
|
</template>
|
||||||
</vxe-column>
|
</vxe-column>
|
||||||
<vxe-column title="状态">
|
<vxe-column :title="$t('cmdb.history.status')">
|
||||||
<template #default="{ row }">
|
<template #default="{ row }">
|
||||||
<a-tag color="green" v-if="row.is_ok">已完成</a-tag>
|
<a-tag color="green" v-if="row.is_ok">{{ $t('cmdb.history.done') }}</a-tag>
|
||||||
<a-tag color="red" v-else>未完成</a-tag>
|
<a-tag color="red" v-else>{{ $t('cmdb.history.undone') }}</a-tag>
|
||||||
</template>
|
</template>
|
||||||
</vxe-column>
|
</vxe-column>
|
||||||
<vxe-column title="触发时间">
|
<vxe-column :title="$t('cmdb.history.triggerTime')">
|
||||||
<template #default="{row}">
|
<template #default="{row}">
|
||||||
{{ row.updated_at || row.created_at }}
|
{{ row.updated_at || row.created_at }}
|
||||||
</template>
|
</template>
|
||||||
</vxe-column>
|
</vxe-column>
|
||||||
</vxe-table>
|
</vxe-table>
|
||||||
<div :style="{ textAlign: 'right' }" v-if="!ci_id">
|
<div :style="{ textAlign: 'right' }" v-if="!ci_id">
|
||||||
<a-pagination
|
<a-pagination
|
||||||
size="small"
|
size="small"
|
||||||
show-size-changer
|
show-size-changer
|
||||||
show-quick-jumper
|
show-quick-jumper
|
||||||
:page-size-options="pageSizeOptions"
|
:page-size-options="pageSizeOptions"
|
||||||
:current="tablePage.currentPage"
|
:current="tablePage.currentPage"
|
||||||
:total="tablePage.totalResult"
|
:total="tablePage.totalResult"
|
||||||
:show-total="(total, range) => `共 ${total} 条记录`"
|
:show-total="(total, range) => $t('cmdb.history.totalItems', { total: total })"
|
||||||
:page-size="tablePage.pageSize"
|
:page-size="tablePage.pageSize"
|
||||||
:default-current="1"
|
:default-current="1"
|
||||||
@change="pageOrSizeChange"
|
@change="pageOrSizeChange"
|
||||||
@showSizeChange="pageOrSizeChange"
|
@showSizeChange="pageOrSizeChange"
|
||||||
>
|
>
|
||||||
</a-pagination>
|
</a-pagination>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { getCiTriggers, getCiTriggersByCiId } from '../../../api/history'
|
import { getCiTriggers, getCiTriggersByCiId } from '../../../api/history'
|
||||||
export default {
|
export default {
|
||||||
name: 'TriggerTable',
|
name: 'TriggerTable',
|
||||||
props: {
|
props: {
|
||||||
ci_id: {
|
ci_id: {
|
||||||
type: Number,
|
type: Number,
|
||||||
default: null,
|
default: null,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
tableData: [],
|
tableData: [],
|
||||||
tablePage: {
|
tablePage: {
|
||||||
currentPage: 1,
|
currentPage: 1,
|
||||||
pageSize: 50,
|
pageSize: 50,
|
||||||
totalResult: 0,
|
totalResult: 0,
|
||||||
},
|
},
|
||||||
pageSizeOptions: ['50', '100', '200'],
|
pageSizeOptions: ['50', '100', '200'],
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
windowHeight() {
|
windowHeight() {
|
||||||
return this.$store.state.windowHeight
|
return this.$store.state.windowHeight
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
this.updateTableData()
|
this.updateTableData()
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
updateTableData(currentPage = 1, pageSize = this.tablePage.pageSize) {
|
updateTableData(currentPage = 1, pageSize = this.tablePage.pageSize) {
|
||||||
const params = { page: currentPage, page_size: pageSize }
|
const params = { page: currentPage, page_size: pageSize }
|
||||||
if (this.ci_id) {
|
if (this.ci_id) {
|
||||||
getCiTriggersByCiId(this.ci_id, params).then((res) => {
|
getCiTriggersByCiId(this.ci_id, params).then((res) => {
|
||||||
this.tableData = res.items.map((item) => {
|
this.tableData = res.items.map((item) => {
|
||||||
return {
|
return {
|
||||||
...item,
|
...item,
|
||||||
trigger: res.id2trigger[item.trigger_id],
|
trigger: res.id2trigger[item.trigger_id],
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
getCiTriggers(params).then((res) => {
|
getCiTriggers(params).then((res) => {
|
||||||
this.tableData = res?.result || []
|
this.tableData = res?.result || []
|
||||||
this.tablePage = {
|
this.tablePage = {
|
||||||
...this.tablePage,
|
...this.tablePage,
|
||||||
currentPage: res.page,
|
currentPage: res.page,
|
||||||
pageSize: res.page_size,
|
pageSize: res.page_size,
|
||||||
totalResult: res.numfound,
|
totalResult: res.numfound,
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
pageOrSizeChange(currentPage, pageSize) {
|
pageOrSizeChange(currentPage, pageSize) {
|
||||||
this.updateTableData(currentPage, pageSize)
|
this.updateTableData(currentPage, pageSize)
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style></style>
|
<style></style>
|
||||||
|
|
|
@ -1,478 +1,484 @@
|
||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<search-form
|
<search-form
|
||||||
:attrList="typeTableAttrList"
|
:attrList="typeTableAttrList"
|
||||||
@expandChange="handleExpandChange"
|
@expandChange="handleExpandChange"
|
||||||
@search="handleSearch"
|
@search="handleSearch"
|
||||||
@searchFormReset="searchFormReset"
|
@searchFormReset="searchFormReset"
|
||||||
></search-form>
|
></search-form>
|
||||||
<vxe-table
|
<vxe-table
|
||||||
ref="xTable"
|
ref="xTable"
|
||||||
:loading="loading"
|
:loading="loading"
|
||||||
resizable
|
resizable
|
||||||
:data="tableData"
|
:data="tableData"
|
||||||
:max-height="`${windowHeight - windowHeightMinus}px`"
|
:max-height="`${windowHeight - windowHeightMinus}px`"
|
||||||
row-id="_XID"
|
row-id="_XID"
|
||||||
size="small"
|
size="small"
|
||||||
:row-config="{isHover: true}"
|
:row-config="{ isHover: true }"
|
||||||
stripe
|
stripe
|
||||||
class="ops-stripe-table"
|
class="ops-stripe-table"
|
||||||
>
|
>
|
||||||
<vxe-column field="created_at" width="159px" title="操作时间"></vxe-column>
|
<vxe-column field="created_at" width="159px" :title="$t('cmdb.history.opreateTime')"></vxe-column>
|
||||||
<vxe-column field="user" width="116px" title="用户"></vxe-column>
|
<vxe-column field="user" width="116px" :title="$t('cmdb.history.user')"></vxe-column>
|
||||||
<vxe-column field="operate_type" width="135px" title="操作">
|
<vxe-column field="operate_type" width="135px" :title="$t('operation')">
|
||||||
<template #header="{ column }">
|
<template #header="{ column }">
|
||||||
<span>{{ column.title }}</span>
|
<span>{{ column.title }}</span>
|
||||||
<a-popover trigger="click" placement="bottom">
|
<a-popover trigger="click" placement="bottom">
|
||||||
<a-icon class="filter" type="filter" theme="filled" />
|
<a-icon class="filter" type="filter" theme="filled" />
|
||||||
<a slot="content">
|
<a slot="content">
|
||||||
<a-select
|
<a-select
|
||||||
v-model="queryParams.operate_type"
|
v-model="queryParams.operate_type"
|
||||||
placeholder="选择筛选操作"
|
:placeholder="$t('cmdb.history.filterOperate')"
|
||||||
show-search
|
show-search
|
||||||
style="width: 200px"
|
style="width: 200px"
|
||||||
:filter-option="filterOption"
|
:filter-option="filterOption"
|
||||||
allowClear
|
allowClear
|
||||||
>
|
>
|
||||||
<a-select-option
|
<a-select-option
|
||||||
:value="Object.values(choice)[0]"
|
:value="Object.values(choice)[0]"
|
||||||
:key="index"
|
:key="index"
|
||||||
v-for="(choice, index) in typeTableAttrList[1].choice_value"
|
v-for="(choice, index) in typeTableAttrList[1].choice_value"
|
||||||
>
|
>
|
||||||
{{ Object.keys(choice)[0] }}
|
{{ Object.keys(choice)[0] }}
|
||||||
</a-select-option>
|
</a-select-option>
|
||||||
</a-select>
|
</a-select>
|
||||||
<a-button type="link" class="filterButton" @click="filterOperate">筛选</a-button>
|
<a-button type="link" class="filterButton" @click="filterOperate">{{
|
||||||
<a-button type="link" class="filterResetButton" @click="filterOperateReset">重置</a-button>
|
$t('cmdb.history.filter')
|
||||||
</a>
|
}}</a-button>
|
||||||
</a-popover>
|
<a-button type="link" class="filterResetButton" @click="filterOperateReset">{{ $t('reset') }}</a-button>
|
||||||
</template>
|
</a>
|
||||||
<template #default="{ row }">
|
</a-popover>
|
||||||
<a-tag color="green" v-if="row.operate_type.includes('新增')">
|
</template>
|
||||||
{{ row.operate_type }}
|
<template #default="{ row }">
|
||||||
</a-tag>
|
<a-tag color="green" v-if="row.operate_type.includes($t('new'))">
|
||||||
<a-tag color="orange" v-else-if="row.operate_type.includes('修改')">
|
{{ row.operate_type }}
|
||||||
{{ row.operate_type }}
|
</a-tag>
|
||||||
</a-tag>
|
<a-tag color="orange" v-else-if="row.operate_type.includes($t('update'))">
|
||||||
<a-tag color="red" v-else>
|
{{ row.operate_type }}
|
||||||
{{ row.operate_type }}
|
</a-tag>
|
||||||
</a-tag>
|
<a-tag color="red" v-else>
|
||||||
</template>
|
{{ row.operate_type }}
|
||||||
</vxe-column>
|
</a-tag>
|
||||||
<vxe-column field="type_id" title="模型" width="150px">
|
</template>
|
||||||
<template #default="{ row }">
|
</vxe-column>
|
||||||
{{ row.operate_type === '删除模型' ? row.change.alias : row.type_id }}
|
<vxe-column field="type_id" :title="$t('cmdb.ciType.ciType')" width="150px">
|
||||||
</template>
|
<template #default="{ row }">
|
||||||
</vxe-column>
|
{{ row.operate_type === $t('cmdb.history.deleteCIType') ? row.change.alias : row.type_id }}
|
||||||
<vxe-column field="changeDescription" title="描述">
|
</template>
|
||||||
<template #default="{ row }">
|
</vxe-column>
|
||||||
<p style="color:rgba(0, 0, 0, 0.65);" v-if="row.changeDescription === '没有修改'">
|
<vxe-column field="changeDescription" :title="$t('desc')">
|
||||||
{{ row.changeDescription }}
|
<template #default="{ row }">
|
||||||
</p>
|
<p style="color:rgba(0, 0, 0, 0.65);" v-if="row.changeDescription === $t('cmdb.history.noUpdate')">
|
||||||
<template v-else-if="row.operate_type.includes('修改')">
|
{{ row.changeDescription }}
|
||||||
<p :key="index" style="color:#fa8c16;" v-for="(tag, index) in row.changeArr">
|
</p>
|
||||||
{{ tag }}
|
<template v-else-if="row.operate_type.includes($t('update'))">
|
||||||
</p>
|
<p :key="index" style="color:#fa8c16;" v-for="(tag, index) in row.changeArr">
|
||||||
</template>
|
{{ tag }}
|
||||||
<p class="more-tag" style="color:#52c41a;" v-else-if="row.operate_type.includes('新增')">
|
</p>
|
||||||
{{ row.changeDescription }}
|
</template>
|
||||||
</p>
|
<p class="more-tag" style="color:#52c41a;" v-else-if="row.operate_type.includes($t('new'))">
|
||||||
<p style="color:#f5222d;" v-else-if="row.operate_type.includes('删除')">
|
{{ row.changeDescription }}
|
||||||
{{ row.changeDescription }}
|
</p>
|
||||||
</p>
|
<p style="color:#f5222d;" v-else-if="row.operate_type.includes($t('delete'))">
|
||||||
</template>
|
{{ row.changeDescription }}
|
||||||
</vxe-column>
|
</p>
|
||||||
</vxe-table>
|
</template>
|
||||||
<a-row class="row" type="flex" justify="end">
|
</vxe-column>
|
||||||
<a-col>
|
</vxe-table>
|
||||||
<a-pagination
|
<a-row class="row" type="flex" justify="end">
|
||||||
size="small"
|
<a-col>
|
||||||
v-model="current"
|
<a-pagination
|
||||||
:page-size-options="pageSizeOptions"
|
size="small"
|
||||||
:total="numfound"
|
v-model="current"
|
||||||
show-size-changer
|
:page-size-options="pageSizeOptions"
|
||||||
:page-size="pageSize"
|
:total="numfound"
|
||||||
@change="onChange"
|
show-size-changer
|
||||||
@showSizeChange="onShowSizeChange"
|
:page-size="pageSize"
|
||||||
:show-total="(total) => `共 ${total} 条记录`"
|
@change="onChange"
|
||||||
>
|
@showSizeChange="onShowSizeChange"
|
||||||
</a-pagination>
|
:show-total="(total) => $t('cmdb.history.totalItems', { total: total })"
|
||||||
</a-col>
|
>
|
||||||
</a-row>
|
</a-pagination>
|
||||||
</div>
|
</a-col>
|
||||||
</template>
|
</a-row>
|
||||||
|
</div>
|
||||||
<script>
|
</template>
|
||||||
import _ from 'lodash'
|
|
||||||
import SearchForm from './searchForm'
|
<script>
|
||||||
import { getCITypesTable, getUsers } from '@/modules/cmdb/api/history'
|
import _ from 'lodash'
|
||||||
import { getCITypes } from '@/modules/cmdb/api/CIType'
|
import { mapState } from 'vuex'
|
||||||
import { getRelationTypes } from '@/modules/cmdb/api/relationType'
|
import SearchForm from './searchForm'
|
||||||
export default {
|
import { getCITypesTable, getUsers } from '@/modules/cmdb/api/history'
|
||||||
name: 'TypeTable',
|
import { getCITypes } from '@/modules/cmdb/api/CIType'
|
||||||
components: { SearchForm },
|
import { getRelationTypes } from '@/modules/cmdb/api/relationType'
|
||||||
data() {
|
export default {
|
||||||
return {
|
name: 'TypeTable',
|
||||||
loading: true,
|
components: { SearchForm },
|
||||||
relationTypeList: null,
|
inject: ['reload'],
|
||||||
operateTypeMap: new Map([
|
data() {
|
||||||
['0', '新增模型'],
|
return {
|
||||||
['1', '修改模型'],
|
loading: true,
|
||||||
['2', '删除模型'],
|
relationTypeList: null,
|
||||||
['3', '新增属性'],
|
typeList: null,
|
||||||
['4', '修改属性'],
|
userList: [],
|
||||||
['5', '删除属性'],
|
pageSizeOptions: ['50', '100', '200'],
|
||||||
['6', '新增触发器'],
|
isExpand: false,
|
||||||
['7', '修改触发器'],
|
current: 1,
|
||||||
['8', '删除触发器'],
|
pageSize: 50,
|
||||||
['9', '新增联合唯一'],
|
total: 0,
|
||||||
['10', '修改联合唯一'],
|
numfound: 0,
|
||||||
['11', '删除联合唯一'],
|
tableData: [],
|
||||||
['12', '新增关系'],
|
queryParams: {
|
||||||
['13', '删除关系'],
|
page: 1,
|
||||||
]),
|
page_size: 50,
|
||||||
typeList: null,
|
type_id: undefined,
|
||||||
userList: [],
|
operate_type: undefined,
|
||||||
typeTableAttrList: [
|
},
|
||||||
{
|
typeTableAttrList: [
|
||||||
alias: '模型',
|
{
|
||||||
is_choice: true,
|
alias: this.$t('cmdb.ciType.ciType'),
|
||||||
name: 'type_id',
|
is_choice: true,
|
||||||
value_type: '2',
|
name: 'type_id',
|
||||||
choice_value: [],
|
value_type: '2',
|
||||||
},
|
choice_value: [],
|
||||||
{
|
},
|
||||||
alias: '操作',
|
{
|
||||||
is_choice: true,
|
alias: this.$t('operation'),
|
||||||
name: 'operate_type',
|
is_choice: true,
|
||||||
value_type: '2',
|
name: 'operate_type',
|
||||||
choice_value: [
|
value_type: '2',
|
||||||
{ 新增模型: 0 },
|
choice_value: [
|
||||||
{ 修改模型: 1 },
|
{ [this.$t('cmdb.history.addCIType')]: 0 },
|
||||||
{ 删除模型: 2 },
|
{ [this.$t('cmdb.history.updateCIType')]: 1 },
|
||||||
{ 新增属性: 3 },
|
{ [this.$t('cmdb.history.deleteCIType')]: 2 },
|
||||||
{ 修改属性: 4 },
|
{ [this.$t('cmdb.history.addAttribute')]: 3 },
|
||||||
{ 删除属性: 5 },
|
{ [this.$t('cmdb.history.updateAttribute')]: 4 },
|
||||||
{ 新增触发器: 6 },
|
{ [this.$t('cmdb.history.deleteAttribute')]: 5 },
|
||||||
{ 修改触发器: 7 },
|
{ [this.$t('cmdb.history.addTrigger')]: 6 },
|
||||||
{ 删除触发器: 8 },
|
{ [this.$t('cmdb.history.updateTrigger')]: 7 },
|
||||||
{ 新增联合唯一: 9 },
|
{ [this.$t('cmdb.history.deleteTrigger')]: 8 },
|
||||||
{ 修改联合唯一: 10 },
|
{ [this.$t('cmdb.history.addUniqueConstraint')]: 9 },
|
||||||
{ 删除联合唯一: 11 },
|
{ [this.$t('cmdb.history.updateUniqueConstraint')]: 10 },
|
||||||
{ 新增关系: 12 },
|
{ [this.$t('cmdb.history.deleteUniqueConstraint')]: 11 },
|
||||||
{ 删除关系: 13 },
|
{ [this.$t('cmdb.history.addRelation')]: 12 },
|
||||||
],
|
{ [this.$t('cmdb.history.deleteRelation')]: 13 },
|
||||||
},
|
],
|
||||||
],
|
},
|
||||||
pageSizeOptions: ['50', '100', '200'],
|
],
|
||||||
isExpand: false,
|
}
|
||||||
current: 1,
|
},
|
||||||
pageSize: 50,
|
async created() {
|
||||||
total: 0,
|
await Promise.all([this.getRelationTypes(), this.getTypes(), this.getUserList()])
|
||||||
numfound: 0,
|
await this.getTable(this.queryParams)
|
||||||
tableData: [],
|
},
|
||||||
queryParams: {
|
updated() {
|
||||||
page: 1,
|
this.$refs.xTable.$el.querySelector('.vxe-table--body-wrapper').scrollTop = 0
|
||||||
page_size: 50,
|
},
|
||||||
type_id: undefined,
|
computed: {
|
||||||
operate_type: undefined,
|
...mapState(['locale']),
|
||||||
},
|
windowHeight() {
|
||||||
}
|
return this.$store.state.windowHeight
|
||||||
},
|
},
|
||||||
async created() {
|
windowHeightMinus() {
|
||||||
await Promise.all([
|
return this.isExpand ? 396 : 335
|
||||||
this.getRelationTypes(),
|
},
|
||||||
this.getTypes(),
|
operateTypeMap() {
|
||||||
this.getUserList(),
|
return new Map([
|
||||||
])
|
['0', this.$t('cmdb.history.addCIType')],
|
||||||
await this.getTable(this.queryParams)
|
['1', this.$t('cmdb.history.updateCIType')],
|
||||||
},
|
['2', this.$t('cmdb.history.deleteCIType')],
|
||||||
updated() {
|
['3', this.$t('cmdb.history.addAttribute')],
|
||||||
this.$refs.xTable.$el.querySelector('.vxe-table--body-wrapper').scrollTop = 0
|
['4', this.$t('cmdb.history.updateAttribute')],
|
||||||
},
|
['5', this.$t('cmdb.history.deleteAttribute')],
|
||||||
computed: {
|
['6', this.$t('cmdb.history.addTrigger')],
|
||||||
windowHeight() {
|
['7', this.$t('cmdb.history.updateTrigger')],
|
||||||
return this.$store.state.windowHeight
|
['8', this.$t('cmdb.history.deleteTrigger')],
|
||||||
},
|
['9', this.$t('cmdb.history.addUniqueConstraint')],
|
||||||
windowHeightMinus() {
|
['10', this.$t('cmdb.history.updateUniqueConstraint')],
|
||||||
return this.isExpand ? 396 : 335
|
['11', this.$t('cmdb.history.deleteUniqueConstraint')],
|
||||||
},
|
['12', this.$t('cmdb.history.addRelation')],
|
||||||
},
|
['13', this.$t('cmdb.history.deleteRelation')],
|
||||||
watch: {
|
])
|
||||||
current(val) {
|
},
|
||||||
this.queryParams.page = val
|
},
|
||||||
},
|
watch: {
|
||||||
pageSize(val) {
|
current(val) {
|
||||||
this.queryParams.page_size = val
|
this.queryParams.page = val
|
||||||
},
|
},
|
||||||
},
|
pageSize(val) {
|
||||||
methods: {
|
this.queryParams.page_size = val
|
||||||
// 获取表格数据
|
},
|
||||||
async getTable(queryParams) {
|
locale() {
|
||||||
try {
|
this.reload()
|
||||||
this.loading = true
|
},
|
||||||
const res = await getCITypesTable(queryParams)
|
},
|
||||||
res.result.forEach((item) => {
|
methods: {
|
||||||
this.handleChangeDescription(item, item.operate_type)
|
async getTable(queryParams) {
|
||||||
item.operate_type = this.handleOperateType(item.operate_type)
|
try {
|
||||||
item.type_id = this.handleTypeId(item.type_id)
|
this.loading = true
|
||||||
item.uid = this.handleUID(item.uid)
|
const res = await getCITypesTable(queryParams)
|
||||||
})
|
res.result.forEach((item) => {
|
||||||
this.tableData = res.result
|
this.handleChangeDescription(item, item.operate_type)
|
||||||
this.pageSize = res.page_size
|
item.operate_type = this.handleOperateType(item.operate_type)
|
||||||
this.current = res.page
|
item.type_id = this.handleTypeId(item.type_id)
|
||||||
this.numfound = res.numfound
|
item.uid = this.handleUID(item.uid)
|
||||||
this.total = res.total
|
})
|
||||||
console.log(this.tableData)
|
this.tableData = res.result
|
||||||
} finally {
|
this.pageSize = res.page_size
|
||||||
this.loading = false
|
this.current = res.page
|
||||||
}
|
this.numfound = res.numfound
|
||||||
},
|
this.total = res.total
|
||||||
// 获取模型
|
console.log(this.tableData)
|
||||||
async getTypes() {
|
} finally {
|
||||||
const res = await getCITypes()
|
this.loading = false
|
||||||
const typesArr = []
|
}
|
||||||
const typesMap = new Map()
|
},
|
||||||
res.ci_types.forEach((item) => {
|
async getTypes() {
|
||||||
const tempObj = {}
|
const res = await getCITypes()
|
||||||
tempObj[item.alias] = item.id
|
const typesArr = []
|
||||||
if (item.alias) {
|
const typesMap = new Map()
|
||||||
typesMap.set(item.id, item.alias)
|
res.ci_types.forEach((item) => {
|
||||||
typesArr.push(tempObj)
|
const tempObj = {}
|
||||||
}
|
tempObj[item.alias] = item.id
|
||||||
})
|
if (item.alias) {
|
||||||
this.typeList = typesMap
|
typesMap.set(item.id, item.alias)
|
||||||
// 设置模型options选项
|
typesArr.push(tempObj)
|
||||||
this.typeTableAttrList[0].choice_value = typesArr
|
}
|
||||||
},
|
})
|
||||||
// 获取用户列表
|
this.typeList = typesMap
|
||||||
async getUserList() {
|
this.typeTableAttrList[0].choice_value = typesArr
|
||||||
const res = await getUsers()
|
},
|
||||||
const userListMap = new Map()
|
async getUserList() {
|
||||||
res.forEach((item) => {
|
const res = await getUsers()
|
||||||
userListMap.set(item.uid, item.nickname)
|
const userListMap = new Map()
|
||||||
})
|
res.forEach((item) => {
|
||||||
this.userList = userListMap
|
userListMap.set(item.uid, item.nickname)
|
||||||
},
|
})
|
||||||
// 获取关系
|
this.userList = userListMap
|
||||||
async getRelationTypes() {
|
},
|
||||||
const res = await getRelationTypes()
|
async getRelationTypes() {
|
||||||
const relationTypeMap = new Map()
|
const res = await getRelationTypes()
|
||||||
res.forEach((item) => {
|
const relationTypeMap = new Map()
|
||||||
relationTypeMap.set(item.id, item.name)
|
res.forEach((item) => {
|
||||||
})
|
relationTypeMap.set(item.id, item.name)
|
||||||
this.relationTypeList = relationTypeMap
|
})
|
||||||
},
|
this.relationTypeList = relationTypeMap
|
||||||
onChange(current) {
|
},
|
||||||
this.current = current
|
onChange(current) {
|
||||||
this.getTable(this.queryParams)
|
this.current = current
|
||||||
},
|
this.getTable(this.queryParams)
|
||||||
onShowSizeChange(current, size) {
|
},
|
||||||
this.current = 1
|
onShowSizeChange(current, size) {
|
||||||
this.pageSize = size
|
this.current = 1
|
||||||
this.getTable(this.queryParams)
|
this.pageSize = size
|
||||||
},
|
this.getTable(this.queryParams)
|
||||||
handleExpandChange(expand) {
|
},
|
||||||
this.isExpand = expand
|
handleExpandChange(expand) {
|
||||||
},
|
this.isExpand = expand
|
||||||
// 处理查询
|
},
|
||||||
handleSearch(queryParams) {
|
handleSearch(queryParams) {
|
||||||
this.current = 1
|
this.current = 1
|
||||||
this.queryParams = queryParams
|
this.queryParams = queryParams
|
||||||
this.getTable(this.queryParams)
|
this.getTable(this.queryParams)
|
||||||
},
|
},
|
||||||
// 重置表单
|
searchFormReset() {
|
||||||
searchFormReset() {
|
this.queryParams = {
|
||||||
this.queryParams = {
|
page: 1,
|
||||||
page: 1,
|
page_size: 50,
|
||||||
page_size: 50,
|
type_id: undefined,
|
||||||
type_id: undefined,
|
operate_type: undefined,
|
||||||
operate_type: undefined,
|
}
|
||||||
}
|
this.getTable(this.queryParams)
|
||||||
this.getTable(this.queryParams)
|
},
|
||||||
},
|
handleOperateType(operate_type) {
|
||||||
// 转换operate_type
|
return this.operateTypeMap.get(operate_type)
|
||||||
handleOperateType(operate_type) {
|
},
|
||||||
return this.operateTypeMap.get(operate_type)
|
handleTypeId(type_id) {
|
||||||
},
|
return this.typeList.get(type_id) ? this.typeList.get(type_id) : type_id
|
||||||
// 转换type_id
|
},
|
||||||
handleTypeId(type_id) {
|
handleUID(uid) {
|
||||||
return this.typeList.get(type_id) ? this.typeList.get(type_id) : type_id
|
return this.userList.get(uid)
|
||||||
},
|
},
|
||||||
// 转换uid
|
handleRelationType(relation_type_id) {
|
||||||
handleUID(uid) {
|
return this.relationTypeList.get(relation_type_id)
|
||||||
return this.userList.get(uid)
|
},
|
||||||
},
|
handleChangeDescription(item, operate_type) {
|
||||||
// 转换relation_type_id
|
switch (operate_type) {
|
||||||
handleRelationType(relation_type_id) {
|
// add CIType
|
||||||
return this.relationTypeList.get(relation_type_id)
|
case '0': {
|
||||||
},
|
item.changeDescription = this.$t('cmdb.history.addCIType') + ': ' + item.change.alias
|
||||||
// 处理改变描述
|
break
|
||||||
handleChangeDescription(item, operate_type) {
|
}
|
||||||
switch (operate_type) {
|
// update CIType
|
||||||
// 新增模型
|
case '1': {
|
||||||
case '0': {
|
item.changeArr = []
|
||||||
item.changeDescription = '新增模型:' + item.change.alias
|
for (const key in item.change.old) {
|
||||||
break
|
const newVal = item.change.new[key]
|
||||||
}
|
const oldVal = item.change.old[key]
|
||||||
// 修改模型
|
if (!_.isEqual(newVal, oldVal) && key !== 'updated_at') {
|
||||||
case '1': {
|
if (oldVal === null) {
|
||||||
item.changeArr = []
|
const str = ` [ ${key} : ${newVal || '""'} ] `
|
||||||
for (const key in item.change.old) {
|
item.changeDescription += str
|
||||||
const newVal = item.change.new[key]
|
item.changeArr.push(str)
|
||||||
const oldVal = item.change.old[key]
|
} else {
|
||||||
if (!_.isEqual(newVal, oldVal) && key !== 'updated_at') {
|
const str = ` [ ${key} : ${oldVal || '""'} -> ${newVal || '""'} ] `
|
||||||
if (oldVal === null) {
|
item.changeDescription += ` [ ${key} : ${oldVal || '""'} -> ${newVal || '""'} ] `
|
||||||
const str = ` [ ${key} : 改为 ${newVal || '""'} ] `
|
item.changeArr.push(str)
|
||||||
item.changeDescription += str
|
}
|
||||||
item.changeArr.push(str)
|
}
|
||||||
} else {
|
}
|
||||||
const str = ` [ ${key} : 由 ${oldVal || '""'} 改为 ${newVal || '""'} ] `
|
if (!item.changeDescription) item.changeDescription = this.$t('cmdb.history.noModifications')
|
||||||
item.changeDescription += ` [ ${key} : 由 ${oldVal || '""'} 改为 ${newVal || '""'} ] `
|
break
|
||||||
item.changeArr.push(str)
|
}
|
||||||
}
|
// delete CIType
|
||||||
}
|
case '2': {
|
||||||
}
|
item.changeDescription = this.$t('cmdb.history.addCIType') + ': ' + `${item.change.alias}`
|
||||||
if (!item.changeDescription) item.changeDescription = '没有修改'
|
break
|
||||||
break
|
}
|
||||||
}
|
// add Attribute
|
||||||
// 删除模型
|
case '3': {
|
||||||
case '2': {
|
item.changeDescription = `${this.$t('cmdb.history.attr')}:${item.change.alias}`
|
||||||
item.changeDescription = `删除模型:${item.change.alias}`
|
break
|
||||||
break
|
}
|
||||||
}
|
// update Attribute
|
||||||
// 新增属性
|
case '4': {
|
||||||
case '3': {
|
item.changeArr = []
|
||||||
item.changeDescription = `属性名:${item.change.alias}`
|
for (const key in item.change.old) {
|
||||||
break
|
if (!_.isEqual(item.change.new[key], item.change.old[key]) && key !== 'updated_at') {
|
||||||
}
|
let newStr = item.change.new[key]
|
||||||
// 修改属性
|
let oldStr = item.change.old[key]
|
||||||
case '4': {
|
if (key === 'choice_value') {
|
||||||
item.changeArr = []
|
newStr = newStr ? newStr.map((item) => item[0]).join(',') : ''
|
||||||
for (const key in item.change.old) {
|
oldStr = oldStr ? oldStr.map((item) => item[0]).join(',') : ''
|
||||||
if (!_.isEqual(item.change.new[key], item.change.old[key]) && key !== 'updated_at') {
|
}
|
||||||
let newStr = item.change.new[key]
|
if (Object.prototype.toString.call(newStr) === '[object Object]') {
|
||||||
let oldStr = item.change.old[key]
|
newStr = JSON.stringify(newStr)
|
||||||
if (key === 'choice_value') {
|
}
|
||||||
newStr = newStr ? newStr.map((item) => item[0]).join(',') : ''
|
if (Object.prototype.toString.call(oldStr) === '[object Object]') {
|
||||||
oldStr = oldStr ? oldStr.map((item) => item[0]).join(',') : ''
|
oldStr = JSON.stringify(oldStr)
|
||||||
}
|
}
|
||||||
if (Object.prototype.toString.call(newStr) === '[object Object]') {
|
const str = `${key} : ${oldStr ? ` ${oldStr || '""'} ` : ''} -> ${newStr || '""'}`
|
||||||
newStr = JSON.stringify(newStr)
|
item.changeDescription += ` [ ${str} ] `
|
||||||
}
|
item.changeArr.push(str)
|
||||||
if (Object.prototype.toString.call(oldStr) === '[object Object]') {
|
}
|
||||||
oldStr = JSON.stringify(oldStr)
|
}
|
||||||
}
|
if (!item.changeDescription) item.changeDescription = this.$t('cmdb.history.noModifications')
|
||||||
const str = `${key} : ${oldStr ? `由 ${oldStr || '""'} ` : ''} 改为 ${newStr || '""'}`
|
break
|
||||||
item.changeDescription += ` [ ${str} ] `
|
}
|
||||||
item.changeArr.push(str)
|
// delete Attribute
|
||||||
}
|
case '5': {
|
||||||
}
|
item.changeDescription = `${this.$t('delete')}:${item.change.alias}`
|
||||||
if (!item.changeDescription) item.changeDescription = '没有修改'
|
break
|
||||||
break
|
}
|
||||||
}
|
// add trigger
|
||||||
// 删除属性
|
case '6': {
|
||||||
case '5': {
|
item.changeDescription = this.$t('cmdb.history.noModifications', {
|
||||||
item.changeDescription = `删除:${item.change.alias}`
|
attr_id: item.change.attr_id,
|
||||||
break
|
before_days: item.change.option.before_days,
|
||||||
}
|
subject: item.change.option.subject,
|
||||||
// 新增触发器
|
body: item.change.option.body,
|
||||||
case '6': {
|
notify_at: item.change.option.notify_at,
|
||||||
item.changeDescription = `属性ID:${item.change.attr_id},提前:${item.change.option.before_days}天,主题:${item.change.option.subject}\n内容:${item.change.option.body}\n通知时间:${item.change.option.notify_at}`
|
})
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
// 修改触发器
|
// update trigger
|
||||||
case '7': {
|
case '7': {
|
||||||
item.changeArr = []
|
item.changeArr = []
|
||||||
for (const key in item.change.old.option) {
|
for (const key in item.change.old.option) {
|
||||||
const newVal = item.change.new.option[key]
|
const newVal = item.change.new.option[key]
|
||||||
const oldVal = item.change.old.option[key]
|
const oldVal = item.change.old.option[key]
|
||||||
if (!_.isEqual(newVal, oldVal) && key !== 'updated_at') {
|
if (!_.isEqual(newVal, oldVal) && key !== 'updated_at') {
|
||||||
const str = ` [ ${key} : 由 ${oldVal} 改为 ${newVal} ] `
|
const str = ` [ ${key} : ${oldVal} -> ${newVal} ] `
|
||||||
item.changeDescription += str
|
item.changeDescription += str
|
||||||
item.changeArr.push(str)
|
item.changeArr.push(str)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!item.changeDescription) item.changeDescription = '没有修改'
|
if (!item.changeDescription) item.changeDescription = this.$t('cmdb.history.noModifications')
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
// 删除触发器
|
// delete trigger
|
||||||
case '8': {
|
case '8': {
|
||||||
item.changeDescription = `属性ID:${item.change.attr_id},提前:${item.change.option.before_days}天,主题:${item.change.option.subject}\n内容:${item.change.option.body}\n通知时间:${item.change.option.notify_at}`
|
item.changeDescription = this.$t('cmdb.history.noModifications', {
|
||||||
break
|
attr_id: item.change.attr_id,
|
||||||
}
|
before_days: item.change.option.before_days,
|
||||||
// 新增联合唯一
|
subject: item.change.option.subject,
|
||||||
case '9': {
|
body: item.change.option.body,
|
||||||
item.changeDescription = `属性id:[${item.change.attr_ids}]`
|
notify_at: item.change.option.notify_at,
|
||||||
break
|
})
|
||||||
}
|
break
|
||||||
// 修改联合唯一
|
}
|
||||||
case '10': {
|
// add unique constraint
|
||||||
item.changeArr = []
|
case '9': {
|
||||||
const oldVal = item.change.old.attr_ids
|
item.changeDescription = `${this.$t('cmdb.history.attrId')}:[${item.change.attr_ids}]`
|
||||||
const newVal = item.change.new.attr_ids
|
break
|
||||||
const str = `属性id:[${oldVal}] -> [${newVal}]`
|
}
|
||||||
item.changeDescription = str
|
// update unique constraint
|
||||||
item.changeArr.push(str)
|
case '10': {
|
||||||
break
|
item.changeArr = []
|
||||||
}
|
const oldVal = item.change.old.attr_ids
|
||||||
// 删除联合唯一
|
const newVal = item.change.new.attr_ids
|
||||||
case '11': {
|
const str = `${this.$t('cmdb.history.attrId')}:[${oldVal}] -> [${newVal}]`
|
||||||
item.changeDescription = `属性id:[${item.change.attr_ids}]`
|
item.changeDescription = str
|
||||||
break
|
item.changeArr.push(str)
|
||||||
}
|
break
|
||||||
// 新增关系
|
}
|
||||||
case '12': {
|
// delete unique constraint
|
||||||
item.changeDescription = `新增:${item.change.parent.alias} -> ${this.handleRelationType(
|
case '11': {
|
||||||
item.change.relation_type_id
|
item.changeDescription = `${this.$t('cmdb.history.attrId')}:[${item.change.attr_ids}]`
|
||||||
)} -> ${item.change.child.alias}`
|
break
|
||||||
break
|
}
|
||||||
}
|
// add relation
|
||||||
// 删除关系
|
case '12': {
|
||||||
case '13': {
|
item.changeDescription = `${this.$t('new')}:${item.change.parent.alias} -> ${this.handleRelationType(
|
||||||
item.changeDescription = `删除:${item.change.parent_id.alias} -> ${this.handleRelationType(
|
item.change.relation_type_id
|
||||||
item.change.relation_type_id
|
)} -> ${item.change.child.alias}`
|
||||||
)} -> ${item.change.child.alias}`
|
break
|
||||||
break
|
}
|
||||||
}
|
// delete relation
|
||||||
}
|
case '13': {
|
||||||
},
|
item.changeDescription = `${this.$t('delete')}:${item.change.parent_id.alias} -> ${this.handleRelationType(
|
||||||
filterOperate() {
|
item.change.relation_type_id
|
||||||
this.queryParams.page = 1
|
)} -> ${item.change.child.alias}`
|
||||||
this.queryParams.page_size = 50
|
break
|
||||||
this.getTable(this.queryParams)
|
}
|
||||||
},
|
}
|
||||||
filterOperateReset() {
|
},
|
||||||
this.queryParams.page = 1
|
filterOperate() {
|
||||||
this.queryParams.page_size = 50
|
this.queryParams.page = 1
|
||||||
this.queryParams.operate_type = undefined
|
this.queryParams.page_size = 50
|
||||||
this.getTable(this.queryParams)
|
this.getTable(this.queryParams)
|
||||||
},
|
},
|
||||||
filterOption(input, option) {
|
filterOperateReset() {
|
||||||
return option.componentOptions.children[0].text.indexOf(input) >= 0
|
this.queryParams.page = 1
|
||||||
},
|
this.queryParams.page_size = 50
|
||||||
},
|
this.queryParams.operate_type = undefined
|
||||||
}
|
this.getTable(this.queryParams)
|
||||||
</script>
|
},
|
||||||
|
filterOption(input, option) {
|
||||||
<style lang="less" scoped>
|
return option.componentOptions.children[0].text.indexOf(input) >= 0
|
||||||
.row {
|
},
|
||||||
margin-top: 5px;
|
},
|
||||||
}
|
}
|
||||||
.filter {
|
</script>
|
||||||
margin-left: 10px;
|
|
||||||
color: #c0c4cc;
|
<style lang="less" scoped>
|
||||||
cursor: pointer;
|
.row {
|
||||||
&:hover {
|
margin-top: 5px;
|
||||||
color: #606266;
|
}
|
||||||
}
|
.filter {
|
||||||
}
|
margin-left: 10px;
|
||||||
.more-tag {
|
color: #c0c4cc;
|
||||||
max-width: 100%;
|
cursor: pointer;
|
||||||
overflow: hidden;
|
&:hover {
|
||||||
text-overflow:ellipsis;
|
color: #606266;
|
||||||
}
|
}
|
||||||
p {
|
}
|
||||||
margin-bottom: 0;
|
.more-tag {
|
||||||
}
|
max-width: 100%;
|
||||||
</style>
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
}
|
||||||
|
p {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
|
@ -2,10 +2,10 @@
|
||||||
<div class="cmdb-preference" :style="{ height: `${windowHeight - 40}px` }">
|
<div class="cmdb-preference" :style="{ height: `${windowHeight - 40}px` }">
|
||||||
<div class="cmdb-preference-left">
|
<div class="cmdb-preference-left">
|
||||||
<div class="cmdb-preference-left-card">
|
<div class="cmdb-preference-left-card">
|
||||||
<span class="cmdb-preference-left-card-title">我的订阅</span>
|
<span class="cmdb-preference-left-card-title">{{ $t('cmdb.preference.mySub') }}</span>
|
||||||
<span
|
<span
|
||||||
class="cmdb-preference-left-card-content"
|
class="cmdb-preference-left-card-content"
|
||||||
><ops-icon type="cmdb-ci" :style="{ marginRight: '5px' }" />资源数据:
|
><ops-icon type="cmdb-ci" :style="{ marginRight: '5px' }" />{{ $t('cmdb.menu.ciTable') }}:
|
||||||
<a-badge
|
<a-badge
|
||||||
showZero
|
showZero
|
||||||
:count="self.instance.length"
|
:count="self.instance.length"
|
||||||
|
@ -20,7 +20,7 @@
|
||||||
>
|
>
|
||||||
<span
|
<span
|
||||||
class="cmdb-preference-left-card-content"
|
class="cmdb-preference-left-card-content"
|
||||||
><ops-icon type="cmdb-tree" :style="{ marginRight: '5px' }" />资源层级:
|
><ops-icon type="cmdb-tree" :style="{ marginRight: '5px' }" />{{ $t('cmdb.menu.ciTree') }}:
|
||||||
<a-badge
|
<a-badge
|
||||||
showZero
|
showZero
|
||||||
:count="self.tree.length"
|
:count="self.tree.length"
|
||||||
|
@ -66,14 +66,14 @@
|
||||||
</div>
|
</div>
|
||||||
<span class="cmdb-preference-group-content-title">{{ ciType.alias || ciType.name }}</span>
|
<span class="cmdb-preference-group-content-title">{{ ciType.alias || ciType.name }}</span>
|
||||||
<span class="cmdb-preference-group-content-action">
|
<span class="cmdb-preference-group-content-action">
|
||||||
<a-tooltip title="取消订阅">
|
<a-tooltip :title="$t('cmdb.preference.cancelSub')">
|
||||||
<span
|
<span
|
||||||
@click="unsubscribe(ciType, group.type)"
|
@click="unsubscribe(ciType, group.type)"
|
||||||
><ops-icon type="cmdb-preference-cancel-subscribe" />
|
><ops-icon type="cmdb-preference-cancel-subscribe" />
|
||||||
</span>
|
</span>
|
||||||
</a-tooltip>
|
</a-tooltip>
|
||||||
<a-divider type="vertical" :style="{ margin: '0 3px' }" />
|
<a-divider type="vertical" :style="{ margin: '0 3px' }" />
|
||||||
<a-tooltip title="编辑订阅">
|
<a-tooltip :title="$t('cmdb.preference.editSub')">
|
||||||
<span
|
<span
|
||||||
@click="openSubscribeSetting(ciType, `${index + 1}`)"
|
@click="openSubscribeSetting(ciType, `${index + 1}`)"
|
||||||
><ops-icon
|
><ops-icon
|
||||||
|
@ -126,7 +126,8 @@
|
||||||
<div class="cmdb-preference-colleague">
|
<div class="cmdb-preference-colleague">
|
||||||
<template v-if="type_id2users[item.id] && type_id2users[item.id].length">
|
<template v-if="type_id2users[item.id] && type_id2users[item.id].length">
|
||||||
<span
|
<span
|
||||||
>{{ type_id2users[item.id].length > 99 ? '99+' : type_id2users[item.id].length }}位同事已订阅</span
|
>{{ type_id2users[item.id].length > 99 ? '99+' : type_id2users[item.id].length
|
||||||
|
}}{{ $t('cmdb.preference.peopleSub') }}</span
|
||||||
>
|
>
|
||||||
<span class="cmdb-preference-colleague-name">
|
<span class="cmdb-preference-colleague-name">
|
||||||
<span v-for="uid in type_id2users[item.id].slice(0, 4)" :key="uid">
|
<span v-for="uid in type_id2users[item.id].slice(0, 4)" :key="uid">
|
||||||
|
@ -135,11 +136,11 @@
|
||||||
<span class="cmdb-preference-colleague-ellipsis" v-if="type_id2users[item.id].length > 4">...</span>
|
<span class="cmdb-preference-colleague-ellipsis" v-if="type_id2users[item.id].length > 4">...</span>
|
||||||
</span>
|
</span>
|
||||||
</template>
|
</template>
|
||||||
<span v-else :style="{ marginLeft: 'auto' }">暂无同事订阅</span>
|
<span v-else :style="{ marginLeft: 'auto' }">{{ $t('cmdb.preference.noSub') }}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="cmdb-preference-progress">
|
<div class="cmdb-preference-progress">
|
||||||
<div class="cmdb-preference-progress-info">
|
<div class="cmdb-preference-progress-info">
|
||||||
<span>自动发现</span>
|
<span>{{ $t('cmdb.menu.ad') }}</span>
|
||||||
<span>{{ item.integrity }}%</span>
|
<span>{{ item.integrity }}%</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="cmdb-preference-progress-gray">
|
<div class="cmdb-preference-progress-gray">
|
||||||
|
@ -148,15 +149,13 @@
|
||||||
</div>
|
</div>
|
||||||
<a-divider :style="{ margin: '10px 0 3px 0' }" />
|
<a-divider :style="{ margin: '10px 0 3px 0' }" />
|
||||||
<div class="cmdb-preference-footor-subscribed" v-if="item.is_subscribed">
|
<div class="cmdb-preference-footor-subscribed" v-if="item.is_subscribed">
|
||||||
<span
|
<span><a-icon type="clock-circle" :style="{ marginRight: '3px' }" />{{ getsubscribedDays(item) }}</span>
|
||||||
><a-icon type="clock-circle" :style="{ marginRight: '3px' }" />{{ getsubscribedDays(item) }}订阅</span
|
|
||||||
>
|
|
||||||
<span>
|
<span>
|
||||||
<a-tooltip title="取消订阅">
|
<a-tooltip :title="$t('cmdb.preference.cancelSub')">
|
||||||
<span @click="unsubscribe(item)"><ops-icon type="cmdb-preference-cancel-subscribe" /> </span>
|
<span @click="unsubscribe(item)"><ops-icon type="cmdb-preference-cancel-subscribe" /> </span>
|
||||||
</a-tooltip>
|
</a-tooltip>
|
||||||
<a-divider type="vertical" :style="{ margin: '0 3px' }" />
|
<a-divider type="vertical" :style="{ margin: '0 3px' }" />
|
||||||
<a-tooltip title="编辑订阅">
|
<a-tooltip :title="$t('cmdb.preference.editSub')">
|
||||||
<span @click="openSubscribeSetting(item)"><ops-icon type="cmdb-preference-subscribe"/></span>
|
<span @click="openSubscribeSetting(item)"><ops-icon type="cmdb-preference-subscribe"/></span>
|
||||||
</a-tooltip>
|
</a-tooltip>
|
||||||
</span>
|
</span>
|
||||||
|
@ -164,7 +163,9 @@
|
||||||
<div v-else class="cmdb-preference-footor-unsubscribed">
|
<div v-else class="cmdb-preference-footor-unsubscribed">
|
||||||
<span
|
<span
|
||||||
@click="openSubscribeSetting(item)"
|
@click="openSubscribeSetting(item)"
|
||||||
><ops-icon :style="{ marginRight: '3px' }" type="cmdb-preference-subscribe" />订阅</span
|
><ops-icon :style="{ marginRight: '3px' }" type="cmdb-preference-subscribe" />{{
|
||||||
|
$t('cmdb.preference.sub')
|
||||||
|
}}</span
|
||||||
>
|
>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -242,7 +243,7 @@ export default {
|
||||||
}
|
}
|
||||||
if (!group.id) {
|
if (!group.id) {
|
||||||
group.id = -1
|
group.id = -1
|
||||||
group.name = '其他'
|
group.name = this.$t('other')
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
this.citypeData = ciTypeGroup
|
this.citypeData = ciTypeGroup
|
||||||
|
@ -251,7 +252,7 @@ export default {
|
||||||
this.type_id2users = type_id2users
|
this.type_id2users = type_id2users
|
||||||
const _myPreferences = [
|
const _myPreferences = [
|
||||||
{
|
{
|
||||||
name: '资源数据',
|
name: this.$t('cmdb.menu.ciTable'),
|
||||||
ci_types: self.instance.map((item) => {
|
ci_types: self.instance.map((item) => {
|
||||||
const _find = pref.find((ci) => ci.id === item)
|
const _find = pref.find((ci) => ci.id === item)
|
||||||
return _find
|
return _find
|
||||||
|
@ -260,7 +261,7 @@ export default {
|
||||||
type: 'ci',
|
type: 'ci',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: '资源层级',
|
name: this.$t('cmdb.menu.ciTree'),
|
||||||
ci_types: self.tree.map((item) => {
|
ci_types: self.tree.map((item) => {
|
||||||
const _find = pref.find((ci) => ci.id === item)
|
const _find = pref.find((ci) => ci.id === item)
|
||||||
return _find
|
return _find
|
||||||
|
@ -285,23 +286,28 @@ export default {
|
||||||
moment.duration(moment().diff(moment(subscribedTime)))
|
moment.duration(moment().diff(moment(subscribedTime)))
|
||||||
const day = moment().diff(moment(subscribedTime), 'day')
|
const day = moment().diff(moment(subscribedTime), 'day')
|
||||||
if (day > 0 && day < 1) {
|
if (day > 0 && day < 1) {
|
||||||
return `${moment().diff(moment(subscribedTime), 'hour')}小时前`
|
return `${moment().diff(moment(subscribedTime), 'hour')}` + this.$t('cmdb.preference.hoursAgo')
|
||||||
} else if (day >= 1 && day <= 31) {
|
} else if (day >= 1 && day <= 31) {
|
||||||
return `${day}天前`
|
return `${day} ` + this.$t('cmdb.preference.daysAgo')
|
||||||
} else if (day > 31 && day < 365) {
|
} else if (day > 31 && day < 365) {
|
||||||
return `${moment().diff(moment(subscribedTime), 'month')}月前`
|
return `${moment().diff(moment(subscribedTime), 'month')}` + this.$t('cmdb.preference.monthsAgo')
|
||||||
} else if (day >= 365) {
|
} else if (day >= 365) {
|
||||||
return `${moment().diff(moment(subscribedTime), 'year')}年前`
|
return `${moment().diff(moment(subscribedTime), 'year')}` + this.$t('cmdb.preference.yearsAgo')
|
||||||
}
|
}
|
||||||
return '刚刚'
|
return this.$t('cmdb.preference.just')
|
||||||
},
|
},
|
||||||
unsubscribe(ciType, type = 'all') {
|
unsubscribe(ciType, type = 'all') {
|
||||||
const that = this
|
const that = this
|
||||||
this.$confirm({
|
this.$confirm({
|
||||||
title: '警告',
|
title: that.$t('warning'),
|
||||||
content: `确认取消订阅 ${ciType.alias || ciType.name} ${
|
content:
|
||||||
type !== 'all' ? `的${type === 'ci' ? '资源数据' : '资源层级'}` : ''
|
that.$t('cmdb.preference.confirmcancelSub') +
|
||||||
} 吗?`,
|
` ${ciType.alias || ciType.name} ${
|
||||||
|
type !== 'all'
|
||||||
|
? that.$t('cmdb.preference.of') +
|
||||||
|
`${type === 'ci' ? this.$t('cmdb.menu.ciTable') : that.$t('cmdb.menu.ciTree')}`
|
||||||
|
: ''
|
||||||
|
} ?`,
|
||||||
onOk() {
|
onOk() {
|
||||||
const promises = []
|
const promises = []
|
||||||
if (type === 'all' || type === 'ci') {
|
if (type === 'all' || type === 'ci') {
|
||||||
|
@ -320,7 +326,7 @@ export default {
|
||||||
localStorage.setItem('ops_ci_typeid', '')
|
localStorage.setItem('ops_ci_typeid', '')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
that.$message.success('取消订阅成功')
|
that.$message.success(that.$t('cmdb.preference.cancelSubSuccess'))
|
||||||
that.resetRoute()
|
that.resetRoute()
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
|
@ -12,12 +12,12 @@
|
||||||
isEdit = true
|
isEdit = true
|
||||||
}
|
}
|
||||||
"
|
"
|
||||||
>新增业务关系</a-button
|
>{{ $t('cmdb.preference_relation.newServiceTree') }}</a-button
|
||||||
>
|
>
|
||||||
<template v-else>
|
<template v-else>
|
||||||
<a-input v-model="newRelationViewName" placeholder="新增业务关系名"></a-input>
|
<a-input v-model="newRelationViewName" :placeholder="$t('cmdb.preference_relation.serviceTreeName')"></a-input>
|
||||||
<a-checkbox v-model="is_public">公开</a-checkbox>
|
<a-checkbox v-model="is_public">{{ $t('cmdb.preference_relation.public') }}</a-checkbox>
|
||||||
<a-button type="primary" size="small" @click="handleSaveRelationViews">保存</a-button>
|
<a-button type="primary" size="small" @click="handleSaveRelationViews">{{ $t('save') }}</a-button>
|
||||||
<a-button
|
<a-button
|
||||||
type="primary"
|
type="primary"
|
||||||
size="small"
|
size="small"
|
||||||
|
@ -29,10 +29,10 @@
|
||||||
newRelationViewName = ''
|
newRelationViewName = ''
|
||||||
}
|
}
|
||||||
"
|
"
|
||||||
>取消</a-button
|
>{{ $t('cancel') }}</a-button
|
||||||
>
|
>
|
||||||
</template>
|
</template>
|
||||||
<a-button type="primary" size="small" @click="handleSave">保存布局</a-button>
|
<a-button type="primary" size="small" @click="handleSave">{{ $t('cmdb.preference_relation.saveLayout') }}</a-button>
|
||||||
</a-space>
|
</a-space>
|
||||||
</div>
|
</div>
|
||||||
<SeeksRelationGraph v-if="isPullConfig" ref="ciTypeRelationGraph" :options="graphOptions">
|
<SeeksRelationGraph v-if="isPullConfig" ref="ciTypeRelationGraph" :options="graphOptions">
|
||||||
|
@ -59,7 +59,7 @@
|
||||||
>
|
>
|
||||||
<div class="relation-views">
|
<div class="relation-views">
|
||||||
<h3 :style="{ padding: '10px 0 0 20px' }">{{ view }}</h3>
|
<h3 :style="{ padding: '10px 0 0 20px' }">{{ view }}</h3>
|
||||||
<a-popconfirm :title="`确认删除 ${view}?`" @confirm="confirmDelete(view)">
|
<a-popconfirm :title="$t('cmdb.ciType.confirmDelete', { name: `${view}` })" @confirm="confirmDelete(view)">
|
||||||
<a class="relation-views-close"><a-icon type="close"/></a>
|
<a class="relation-views-close"><a-icon type="close"/></a>
|
||||||
</a-popconfirm>
|
</a-popconfirm>
|
||||||
<div :style="{ height: '250px' }">
|
<div :style="{ height: '250px' }">
|
||||||
|
@ -246,7 +246,7 @@ export default {
|
||||||
if (e.target.checked) {
|
if (e.target.checked) {
|
||||||
const graph = this.$refs.ciTypeRelationGraph
|
const graph = this.$refs.ciTypeRelationGraph
|
||||||
if (!graph.getNodeById(node.id).targetTo.length) {
|
if (!graph.getNodeById(node.id).targetTo.length) {
|
||||||
this.$message.warning(`${node.text} 不存在子节点,不能形成业务关系,请重新选择!`)
|
this.$message.warning(`${node.text} ` + this.$t('cmdb.preference_relation.childNodesNotFound'))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if (!this.checkedNodes.length) {
|
if (!this.checkedNodes.length) {
|
||||||
|
@ -278,7 +278,7 @@ export default {
|
||||||
const idFrom = startNode.targetFrom.findIndex((item) => item.id === node.id)
|
const idFrom = startNode.targetFrom.findIndex((item) => item.id === node.id)
|
||||||
const idTo = endNode.targetTo.findIndex((item) => item.id === node.id)
|
const idTo = endNode.targetTo.findIndex((item) => item.id === node.id)
|
||||||
if (idFrom <= -1 && idTo <= -1) {
|
if (idFrom <= -1 && idTo <= -1) {
|
||||||
this.$message.warning(`${node.text} 不能与当前选中节点形成视图,请重新选择!`)
|
this.$message.warning(`${node.text} ` + this.$t('cmdb.preference_relation.tips1'))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if (idFrom > -1) {
|
if (idFrom > -1) {
|
||||||
|
@ -290,11 +290,11 @@ export default {
|
||||||
},
|
},
|
||||||
async handleSaveRelationViews() {
|
async handleSaveRelationViews() {
|
||||||
if (!this.newRelationViewName) {
|
if (!this.newRelationViewName) {
|
||||||
this.$message.warning('请输入新增业务关系名!')
|
this.$message.warning(this.$t('cmdb.preference_relation.tips2'))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if (this.checkedNodes.length < 2) {
|
if (this.checkedNodes.length < 2) {
|
||||||
this.$message.warning('请选择至少两个节点!')
|
this.$message.warning(this.$t('cmdb.preference_relation.tips3'))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// eslint-disable-next-line camelcase
|
// eslint-disable-next-line camelcase
|
||||||
|
@ -341,7 +341,7 @@ export default {
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
}).then((res) => {
|
}).then((res) => {
|
||||||
this.$message.success('保存成功!')
|
this.$message.success(this.$t('saveSuccess'))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,18 +1,18 @@
|
||||||
<template>
|
<template>
|
||||||
<CustomDrawer
|
<CustomDrawer
|
||||||
:closable="false"
|
:closable="false"
|
||||||
:title="drawerTitle"
|
:title="$t('cmdb.preference_relation.newServiceTree')"
|
||||||
:visible="drawerVisible"
|
:visible="drawerVisible"
|
||||||
@close="onClose"
|
@close="onClose"
|
||||||
placement="right"
|
placement="right"
|
||||||
width="30%"
|
width="30%"
|
||||||
>
|
>
|
||||||
<a-form :form="form" :layout="formLayout" @submit="handleSubmit">
|
<a-form :form="form" :layout="formLayout" @submit="handleSubmit">
|
||||||
<a-form-item :label-col="formItemLayout.labelCol" :wrapper-col="formItemLayout.wrapperCol" label="业务关系名">
|
<a-form-item :label-col="formItemLayout.labelCol" :wrapper-col="formItemLayout.wrapperCol" :label="$t('cmdb.preference_relation.serviceTreeName')">
|
||||||
<a-input
|
<a-input
|
||||||
name="name"
|
name="name"
|
||||||
placeholder
|
placeholder
|
||||||
v-decorator="['name', { rules: [{ required: true, message: '请输入类型名' }] }]"
|
v-decorator="['name', { rules: [{ required: true, message: $t('cmdb.preference_relation.tips2')}] }]"
|
||||||
/>
|
/>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
|
|
||||||
|
@ -21,8 +21,8 @@
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
|
|
||||||
<div class="custom-drawer-bottom-action">
|
<div class="custom-drawer-bottom-action">
|
||||||
<a-button @click="onClose">取消</a-button>
|
<a-button @click="onClose">{{ $t('cancel') }}</a-button>
|
||||||
<a-button @click="handleSubmit" type="primary">提交</a-button>
|
<a-button @click="handleSubmit" type="primary">{{ $t('submit') }}</a-button>
|
||||||
</div>
|
</div>
|
||||||
</a-form>
|
</a-form>
|
||||||
</CustomDrawer>
|
</CustomDrawer>
|
||||||
|
@ -35,7 +35,6 @@ export default {
|
||||||
name: 'RelationViewForm',
|
name: 'RelationViewForm',
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
drawerTitle: '新增业务关系',
|
|
||||||
drawerVisible: false,
|
drawerVisible: false,
|
||||||
formLayout: 'vertical',
|
formLayout: 'vertical',
|
||||||
crIds: [],
|
crIds: [],
|
||||||
|
@ -95,7 +94,7 @@ export default {
|
||||||
createRelationView(data) {
|
createRelationView(data) {
|
||||||
data.cr_ids = this.crIds
|
data.cr_ids = this.crIds
|
||||||
subscribeRelationView(data).then(res => {
|
subscribeRelationView(data).then(res => {
|
||||||
this.$message.success('新增成功!')
|
this.$message.success(this.$t('addSuccess'))
|
||||||
this.onClose()
|
this.onClose()
|
||||||
this.$emit('refresh')
|
this.$emit('refresh')
|
||||||
})
|
})
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<template>
|
<template>
|
||||||
<a-card :bordered="false">
|
<a-card :bordered="false">
|
||||||
<div class="action-btn">
|
<div class="action-btn">
|
||||||
<a-button @click="handleCreate" type="primary" style="margin-bottom: 15px;">新增关系类型</a-button>
|
<a-button @click="handleCreate" type="primary" style="margin-bottom: 15px;">{{ $t('cmdb.relation_type.addRelationType') }}</a-button>
|
||||||
</div>
|
</div>
|
||||||
<vxe-table
|
<vxe-table
|
||||||
ref="relationTypeTable"
|
ref="relationTypeTable"
|
||||||
|
@ -16,20 +16,20 @@
|
||||||
>
|
>
|
||||||
<vxe-table-column
|
<vxe-table-column
|
||||||
field="name"
|
field="name"
|
||||||
title="名称"
|
:title="$t('name')"
|
||||||
:edit-render="{ name: 'input', attrs: { type: 'text' }, events: { keyup: customCloseEdit } }"
|
:edit-render="{ name: 'input', attrs: { type: 'text' }, events: { keyup: customCloseEdit } }"
|
||||||
></vxe-table-column>
|
></vxe-table-column>
|
||||||
<vxe-table-column field="updateTime" title="更新时间">
|
<vxe-table-column field="updateTime" :title="$t('updated_at')">
|
||||||
<template #default="{row}">
|
<template #default="{row}">
|
||||||
{{ row.updated_at || row.created_at }}
|
{{ row.updated_at || row.created_at }}
|
||||||
</template>
|
</template>
|
||||||
</vxe-table-column>
|
</vxe-table-column>
|
||||||
<vxe-table-column field="operation" title="操作" align="center">
|
<vxe-table-column field="operation" :title="$t('operation')" align="center">
|
||||||
<template #default="{row}">
|
<template #default="{row}">
|
||||||
<template>
|
<template>
|
||||||
<a><a-icon type="edit" @click="handleEdit(row)"/></a>
|
<a><a-icon type="edit" @click="handleEdit(row)"/></a>
|
||||||
<a-divider type="vertical" />
|
<a-divider type="vertical" />
|
||||||
<a-popconfirm title="确认删除吗?" @confirm="handleDelete(row)" okText="是" cancelText="否">
|
<a-popconfirm :title="$t('confirmDelete')" @confirm="handleDelete(row)" :okText="$t('yes')" :cancelText="$t('no')">
|
||||||
<a :style="{ color: 'red' }"><a-icon type="delete"/></a>
|
<a :style="{ color: 'red' }"><a-icon type="delete"/></a>
|
||||||
</a-popconfirm>
|
</a-popconfirm>
|
||||||
</template>
|
</template>
|
||||||
|
@ -50,6 +50,7 @@ import {
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'RelationType',
|
name: 'RelationType',
|
||||||
|
components: {},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
tableData: [],
|
tableData: [],
|
||||||
|
@ -97,14 +98,14 @@ export default {
|
||||||
},
|
},
|
||||||
updateRelationType(id, data) {
|
updateRelationType(id, data) {
|
||||||
updateRelationType(id, data).then((res) => {
|
updateRelationType(id, data).then((res) => {
|
||||||
this.$message.success('更新成功!')
|
this.$message.success(this.$t('updateSuccess'))
|
||||||
this.loadData()
|
this.loadData()
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
createRelationType(data) {
|
createRelationType(data) {
|
||||||
addRelationType(data).then((res) => {
|
addRelationType(data).then((res) => {
|
||||||
this.$message.success('新增成功!')
|
this.$message.success(this.$t('addSuccess'))
|
||||||
this.loadData()
|
this.loadData()
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
@ -113,12 +114,12 @@ export default {
|
||||||
},
|
},
|
||||||
deleteRelationType(id) {
|
deleteRelationType(id) {
|
||||||
deleteRelationType(id).then((res) => {
|
deleteRelationType(id).then((res) => {
|
||||||
this.$message.success('删除成功!')
|
this.$message.success(this.$t('deleteSuccess'))
|
||||||
this.loadData()
|
this.loadData()
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
customCloseEdit(value, $event) {
|
customCloseEdit(value, $event) {
|
||||||
// 回车结束编辑
|
// enter, close edit
|
||||||
if ($event.keyCode === 13) {
|
if ($event.keyCode === 13) {
|
||||||
const $table = this.$refs.relationTypeTable
|
const $table = this.$refs.relationTypeTable
|
||||||
$table.clearActived()
|
$table.clearActived()
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -11,12 +11,24 @@
|
||||||
>
|
>
|
||||||
<div :style="{ width: '100%' }" id="add-table-modal">
|
<div :style="{ width: '100%' }" id="add-table-modal">
|
||||||
<a-spin :spinning="loading">
|
<a-spin :spinning="loading">
|
||||||
|
<!-- <a-input
|
||||||
|
v-model="expression"
|
||||||
|
class="ci-searchform-expression"
|
||||||
|
:style="{ width, marginBottom: '10px' }"
|
||||||
|
:placeholder="placeholder"
|
||||||
|
@focus="
|
||||||
|
() => {
|
||||||
|
isFocusExpression = true
|
||||||
|
}
|
||||||
|
"
|
||||||
|
/> -->
|
||||||
<SearchForm
|
<SearchForm
|
||||||
ref="searchForm"
|
ref="searchForm"
|
||||||
:typeId="addTypeId"
|
:typeId="addTypeId"
|
||||||
:preferenceAttrList="preferenceAttrList"
|
:preferenceAttrList="preferenceAttrList"
|
||||||
@refresh="handleSearch"
|
@refresh="handleSearch"
|
||||||
/>
|
/>
|
||||||
|
<!-- <a @click="handleSearch"><a-icon type="search"/></a> -->
|
||||||
<vxe-table
|
<vxe-table
|
||||||
ref="xTable"
|
ref="xTable"
|
||||||
row-id="_id"
|
row-id="_id"
|
||||||
|
@ -52,7 +64,14 @@
|
||||||
:total="totalNumber"
|
:total="totalNumber"
|
||||||
show-quick-jumper
|
show-quick-jumper
|
||||||
:page-size="50"
|
:page-size="50"
|
||||||
:show-total="(total, range) => `当前${range[0]}-${range[1]} 共 ${total}条记录`"
|
:show-total="
|
||||||
|
(total, range) =>
|
||||||
|
$t('pagination.total', {
|
||||||
|
range0: range[0],
|
||||||
|
range1: range[1],
|
||||||
|
total,
|
||||||
|
})
|
||||||
|
"
|
||||||
:style="{ textAlign: 'right', marginTop: '10px' }"
|
:style="{ textAlign: 'right', marginTop: '10px' }"
|
||||||
@change="handleChangePage"
|
@change="handleChangePage"
|
||||||
/>
|
/>
|
||||||
|
@ -94,7 +113,7 @@ export default {
|
||||||
return this.$store.state.windowHeight - 250
|
return this.$store.state.windowHeight - 250
|
||||||
},
|
},
|
||||||
placeholder() {
|
placeholder() {
|
||||||
return this.isFocusExpression ? '例:q=os_version:centos&sort=os_version' : '表达式搜索'
|
return this.isFocusExpression ? this.$t('cmdb.serviceTreetips1') : this.$t('cmdb.serviceTreetips2')
|
||||||
},
|
},
|
||||||
width() {
|
width() {
|
||||||
return this.isFocusExpression ? '500px' : '100px'
|
return this.isFocusExpression ? '500px' : '100px'
|
||||||
|
@ -103,6 +122,7 @@ export default {
|
||||||
watch: {},
|
watch: {},
|
||||||
methods: {
|
methods: {
|
||||||
async openModal(ciObj, ciId, addTypeId, type, ancestor_ids = undefined) {
|
async openModal(ciObj, ciId, addTypeId, type, ancestor_ids = undefined) {
|
||||||
|
console.log(ciObj, ciId, addTypeId, type)
|
||||||
this.visible = true
|
this.visible = true
|
||||||
this.ciObj = ciObj
|
this.ciObj = ciObj
|
||||||
this.ciId = ciId
|
this.ciId = ciId
|
||||||
|
@ -121,6 +141,10 @@ export default {
|
||||||
},
|
},
|
||||||
async fetchData(isInit) {
|
async fetchData(isInit) {
|
||||||
this.loading = true
|
this.loading = true
|
||||||
|
// if (isInit) {
|
||||||
|
// const subscribed = await getSubscribeAttributes(this.addTypeId)
|
||||||
|
// this.preferenceAttrList = subscribed.attributes // 已经订阅的全部列
|
||||||
|
// }
|
||||||
let sort, fuzzySearch, expression, exp
|
let sort, fuzzySearch, expression, exp
|
||||||
if (!isInit) {
|
if (!isInit) {
|
||||||
fuzzySearch = this.$refs['searchForm'].fuzzySearch
|
fuzzySearch = this.$refs['searchForm'].fuzzySearch
|
||||||
|
@ -179,7 +203,7 @@ export default {
|
||||||
await batchUpdateCIRelationParents(ciIds, [this.ciId])
|
await batchUpdateCIRelationParents(ciIds, [this.ciId])
|
||||||
}
|
}
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
this.$message.success('添加成功!')
|
this.$message.success(this.$t('addSuccess'))
|
||||||
this.handleClose()
|
this.handleClose()
|
||||||
this.$emit('reload')
|
this.$emit('reload')
|
||||||
}, 500)
|
}, 500)
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
<template>
|
<template>
|
||||||
<a-dropdown :trigger="['contextmenu']">
|
<a-dropdown :trigger="['contextmenu']">
|
||||||
<a-menu slot="overlay" @click="({ key: menuKey }) => this.onContextMenuClick(this.treeKey, menuKey)">
|
<a-menu slot="overlay" @click="({ key: menuKey }) => this.onContextMenuClick(this.treeKey, menuKey)">
|
||||||
<a-menu-item v-for="item in menuList" :key="item.id">新增{{ item.alias }}</a-menu-item>
|
<a-menu-item v-for="item in menuList" :key="item.id">{{ $t('new') }} {{ item.alias }}</a-menu-item>
|
||||||
<a-menu-item v-if="showDelete" key="delete">删除节点</a-menu-item>
|
<a-menu-item v-if="showDelete" key="delete">{{ $t('cmdb.serviceTree.deleteNode') }}</a-menu-item>
|
||||||
</a-menu>
|
</a-menu>
|
||||||
<div
|
<div
|
||||||
:style="{
|
:style="{
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue