feat: update model config

This commit is contained in:
songlh 2024-06-27 19:41:24 +08:00
parent 72c0fbcd11
commit e6f2aadc13
19 changed files with 3832 additions and 3131 deletions

View File

@ -54,6 +54,60 @@
<div class="content unicode" style="display: block;"> <div class="content unicode" style="display: block;">
<ul class="icon_lists dib-box"> <ul class="icon_lists dib-box">
<li class="dib">
<span class="icon iconfont">&#xe96a;</span>
<div class="name">veops-markdown</div>
<div class="code-name">&amp;#xe96a;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xe860;</span>
<div class="name">veops-bar_horizontal</div>
<div class="code-name">&amp;#xe860;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xe965;</span>
<div class="name">veops-gauge</div>
<div class="code-name">&amp;#xe965;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xe966;</span>
<div class="name">veops-heatmap</div>
<div class="code-name">&amp;#xe966;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xe967;</span>
<div class="name">veops-treemap</div>
<div class="code-name">&amp;#xe967;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xe968;</span>
<div class="name">veops-radar</div>
<div class="code-name">&amp;#xe968;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xe969;</span>
<div class="name">veops-data</div>
<div class="code-name">&amp;#xe969;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xe963;</span>
<div class="name">veops-import</div>
<div class="code-name">&amp;#xe963;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xe964;</span>
<div class="name">veops-batch_operation</div>
<div class="code-name">&amp;#xe964;</div>
</li>
<li class="dib"> <li class="dib">
<span class="icon iconfont">&#xe962;</span> <span class="icon iconfont">&#xe962;</span>
<div class="name">cmdb-enterprise_edition</div> <div class="name">cmdb-enterprise_edition</div>
@ -552,12 +606,6 @@
<div class="code-name">&amp;#xe862;</div> <div class="code-name">&amp;#xe862;</div>
</li> </li>
<li class="dib">
<span class="icon iconfont">&#xe860;</span>
<div class="name">veops-import</div>
<div class="code-name">&amp;#xe860;</div>
</li>
<li class="dib"> <li class="dib">
<span class="icon iconfont">&#xe807;</span> <span class="icon iconfont">&#xe807;</span>
<div class="name">monitor-ip (1)</div> <div class="name">monitor-ip (1)</div>
@ -5196,9 +5244,9 @@
<pre><code class="language-css" <pre><code class="language-css"
>@font-face { >@font-face {
font-family: 'iconfont'; font-family: 'iconfont';
src: url('iconfont.woff2?t=1719307117118') format('woff2'), src: url('iconfont.woff2?t=1719487341033') format('woff2'),
url('iconfont.woff?t=1719307117118') format('woff'), url('iconfont.woff?t=1719487341033') format('woff'),
url('iconfont.ttf?t=1719307117118') format('truetype'); url('iconfont.ttf?t=1719487341033') format('truetype');
} }
</code></pre> </code></pre>
<h3 id="-iconfont-">第二步:定义使用 iconfont 的样式</h3> <h3 id="-iconfont-">第二步:定义使用 iconfont 的样式</h3>
@ -5224,6 +5272,87 @@
<div class="content font-class"> <div class="content font-class">
<ul class="icon_lists dib-box"> <ul class="icon_lists dib-box">
<li class="dib">
<span class="icon iconfont veops-markdown"></span>
<div class="name">
veops-markdown
</div>
<div class="code-name">.veops-markdown
</div>
</li>
<li class="dib">
<span class="icon iconfont veops-bar_horizontal"></span>
<div class="name">
veops-bar_horizontal
</div>
<div class="code-name">.veops-bar_horizontal
</div>
</li>
<li class="dib">
<span class="icon iconfont veops-gauge"></span>
<div class="name">
veops-gauge
</div>
<div class="code-name">.veops-gauge
</div>
</li>
<li class="dib">
<span class="icon iconfont veops-heatmap"></span>
<div class="name">
veops-heatmap
</div>
<div class="code-name">.veops-heatmap
</div>
</li>
<li class="dib">
<span class="icon iconfont veops-treemap"></span>
<div class="name">
veops-treemap
</div>
<div class="code-name">.veops-treemap
</div>
</li>
<li class="dib">
<span class="icon iconfont veops-radar"></span>
<div class="name">
veops-radar
</div>
<div class="code-name">.veops-radar
</div>
</li>
<li class="dib">
<span class="icon iconfont veops-data"></span>
<div class="name">
veops-data
</div>
<div class="code-name">.veops-data
</div>
</li>
<li class="dib">
<span class="icon iconfont veops-import"></span>
<div class="name">
veops-import
</div>
<div class="code-name">.veops-import
</div>
</li>
<li class="dib">
<span class="icon iconfont veops-batch_operation"></span>
<div class="name">
veops-batch_operation
</div>
<div class="code-name">.veops-batch_operation
</div>
</li>
<li class="dib"> <li class="dib">
<span class="icon iconfont cmdb-enterprise_edition"></span> <span class="icon iconfont cmdb-enterprise_edition"></span>
<div class="name"> <div class="name">
@ -5738,11 +5867,11 @@
</li> </li>
<li class="dib"> <li class="dib">
<span class="icon iconfont a-Group427319324"></span> <span class="icon iconfont monitor-add2"></span>
<div class="name"> <div class="name">
monitor-add2 monitor-add2
</div> </div>
<div class="code-name">.a-Group427319324 <div class="code-name">.monitor-add2
</div> </div>
</li> </li>
@ -5971,15 +6100,6 @@
</div> </div>
</li> </li>
<li class="dib">
<span class="icon iconfont a-veops-import1"></span>
<div class="name">
veops-import
</div>
<div class="code-name">.a-veops-import1
</div>
</li>
<li class="dib"> <li class="dib">
<span class="icon iconfont monitor-ip"></span> <span class="icon iconfont monitor-ip"></span>
<div class="name"> <div class="name">
@ -12937,6 +13057,78 @@
<div class="content symbol"> <div class="content symbol">
<ul class="icon_lists dib-box"> <ul class="icon_lists dib-box">
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#veops-markdown"></use>
</svg>
<div class="name">veops-markdown</div>
<div class="code-name">#veops-markdown</div>
</li>
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#veops-bar_horizontal"></use>
</svg>
<div class="name">veops-bar_horizontal</div>
<div class="code-name">#veops-bar_horizontal</div>
</li>
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#veops-gauge"></use>
</svg>
<div class="name">veops-gauge</div>
<div class="code-name">#veops-gauge</div>
</li>
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#veops-heatmap"></use>
</svg>
<div class="name">veops-heatmap</div>
<div class="code-name">#veops-heatmap</div>
</li>
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#veops-treemap"></use>
</svg>
<div class="name">veops-treemap</div>
<div class="code-name">#veops-treemap</div>
</li>
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#veops-radar"></use>
</svg>
<div class="name">veops-radar</div>
<div class="code-name">#veops-radar</div>
</li>
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#veops-data"></use>
</svg>
<div class="name">veops-data</div>
<div class="code-name">#veops-data</div>
</li>
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#veops-import"></use>
</svg>
<div class="name">veops-import</div>
<div class="code-name">#veops-import</div>
</li>
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#veops-batch_operation"></use>
</svg>
<div class="name">veops-batch_operation</div>
<div class="code-name">#veops-batch_operation</div>
</li>
<li class="dib"> <li class="dib">
<svg class="icon svg-icon" aria-hidden="true"> <svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#cmdb-enterprise_edition"></use> <use xlink:href="#cmdb-enterprise_edition"></use>
@ -13395,10 +13587,10 @@
<li class="dib"> <li class="dib">
<svg class="icon svg-icon" aria-hidden="true"> <svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#a-Group427319324"></use> <use xlink:href="#monitor-add2"></use>
</svg> </svg>
<div class="name">monitor-add2</div> <div class="name">monitor-add2</div>
<div class="code-name">#a-Group427319324</div> <div class="code-name">#monitor-add2</div>
</li> </li>
<li class="dib"> <li class="dib">
@ -13601,14 +13793,6 @@
<div class="code-name">#veops-export</div> <div class="code-name">#veops-export</div>
</li> </li>
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#a-veops-import1"></use>
</svg>
<div class="name">veops-import</div>
<div class="code-name">#a-veops-import1</div>
</li>
<li class="dib"> <li class="dib">
<svg class="icon svg-icon" aria-hidden="true"> <svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#monitor-ip"></use> <use xlink:href="#monitor-ip"></use>

View File

@ -1,8 +1,8 @@
@font-face { @font-face {
font-family: "iconfont"; /* Project id 3857903 */ font-family: "iconfont"; /* Project id 3857903 */
src: url('iconfont.woff2?t=1719307117118') format('woff2'), src: url('iconfont.woff2?t=1719487341033') format('woff2'),
url('iconfont.woff?t=1719307117118') format('woff'), url('iconfont.woff?t=1719487341033') format('woff'),
url('iconfont.ttf?t=1719307117118') format('truetype'); url('iconfont.ttf?t=1719487341033') format('truetype');
} }
.iconfont { .iconfont {
@ -13,6 +13,42 @@
-moz-osx-font-smoothing: grayscale; -moz-osx-font-smoothing: grayscale;
} }
.veops-markdown:before {
content: "\e96a";
}
.veops-bar_horizontal:before {
content: "\e860";
}
.veops-gauge:before {
content: "\e965";
}
.veops-heatmap:before {
content: "\e966";
}
.veops-treemap:before {
content: "\e967";
}
.veops-radar:before {
content: "\e968";
}
.veops-data:before {
content: "\e969";
}
.veops-import:before {
content: "\e963";
}
.veops-batch_operation:before {
content: "\e964";
}
.cmdb-enterprise_edition:before { .cmdb-enterprise_edition:before {
content: "\e962"; content: "\e962";
} }
@ -241,7 +277,7 @@
content: "\e92a"; content: "\e92a";
} }
.a-Group427319324:before { .monitor-add2:before {
content: "\e929"; content: "\e929";
} }
@ -345,10 +381,6 @@
content: "\e862"; content: "\e862";
} }
.a-veops-import1:before {
content: "\e860";
}
.monitor-ip:before { .monitor-ip:before {
content: "\e807"; content: "\e807";
} }

File diff suppressed because one or more lines are too long

View File

@ -5,6 +5,69 @@
"css_prefix_text": "", "css_prefix_text": "",
"description": "", "description": "",
"glyphs": [ "glyphs": [
{
"icon_id": "40896913",
"name": "veops-markdown",
"font_class": "veops-markdown",
"unicode": "e96a",
"unicode_decimal": 59754
},
{
"icon_id": "40896859",
"name": "veops-bar_horizontal",
"font_class": "veops-bar_horizontal",
"unicode": "e860",
"unicode_decimal": 59488
},
{
"icon_id": "40896881",
"name": "veops-gauge",
"font_class": "veops-gauge",
"unicode": "e965",
"unicode_decimal": 59749
},
{
"icon_id": "40896882",
"name": "veops-heatmap",
"font_class": "veops-heatmap",
"unicode": "e966",
"unicode_decimal": 59750
},
{
"icon_id": "40896884",
"name": "veops-treemap",
"font_class": "veops-treemap",
"unicode": "e967",
"unicode_decimal": 59751
},
{
"icon_id": "40896887",
"name": "veops-radar",
"font_class": "veops-radar",
"unicode": "e968",
"unicode_decimal": 59752
},
{
"icon_id": "40896905",
"name": "veops-data",
"font_class": "veops-data",
"unicode": "e969",
"unicode_decimal": 59753
},
{
"icon_id": "40872369",
"name": "veops-import",
"font_class": "veops-import",
"unicode": "e963",
"unicode_decimal": 59747
},
{
"icon_id": "40872361",
"name": "veops-batch_operation",
"font_class": "veops-batch_operation",
"unicode": "e964",
"unicode_decimal": 59748
},
{ {
"icon_id": "40834860", "icon_id": "40834860",
"name": "cmdb-enterprise_edition", "name": "cmdb-enterprise_edition",
@ -407,7 +470,7 @@
{ {
"icon_id": "40372105", "icon_id": "40372105",
"name": "monitor-add2", "name": "monitor-add2",
"font_class": "a-Group427319324", "font_class": "monitor-add2",
"unicode": "e929", "unicode": "e929",
"unicode_decimal": 59689 "unicode_decimal": 59689
}, },
@ -586,13 +649,6 @@
"unicode": "e862", "unicode": "e862",
"unicode_decimal": 59490 "unicode_decimal": 59490
}, },
{
"icon_id": "40306881",
"name": "veops-import",
"font_class": "a-veops-import1",
"unicode": "e860",
"unicode_decimal": 59488
},
{ {
"icon_id": "40262335", "icon_id": "40262335",
"name": "monitor-ip (1)", "name": "monitor-ip (1)",

Binary file not shown.

View File

@ -50,3 +50,13 @@ export const putCITypeGroups = (data) => {
data: data data: data
}) })
} }
// 导出模型分组
export function exportCITypeGroups(params) {
return axios({
url: `${urlPrefix}/ci_types/template/export`,
method: 'GET',
params: params,
timeout: 30 * 1000,
})
}

View File

@ -37,6 +37,14 @@ const cmdb_en = {
editGroup: 'Edit Group', editGroup: 'Edit Group',
group: 'Group', group: 'Group',
attributeLibray: 'Attribute Library', attributeLibray: 'Attribute Library',
viewAttributeLibray: 'Attribute Library',
addGroup2: 'Add Group',
modelExport: 'Model Export',
filename: 'Filename',
filenameInputTips: 'Please enter filename',
selectModel: 'Select Model',
unselectModel: 'Unselected',
selectedModel: 'Selected',
addCITypeInGroup: 'Add a new CIType to the group', addCITypeInGroup: 'Add a new CIType to the group',
addCIType: 'Add CIType', addCIType: 'Add CIType',
editGroupName: 'Edit group name', editGroupName: 'Edit group name',
@ -76,6 +84,8 @@ const cmdb_en = {
byInterval: 'by interval', byInterval: 'by interval',
allNodes: 'All machines', allNodes: 'All machines',
specifyNodes: 'Specify machine', specifyNodes: 'Specify machine',
masterNode: 'Master machine',
masterNodeTip: 'The machine where OneMaster is installed',
specifyNodesTips: 'Please fill in the specify machine!', specifyNodesTips: 'Please fill in the specify machine!',
username: 'Username', username: 'Username',
password: 'Password', password: 'Password',

View File

@ -37,6 +37,14 @@ const cmdb_zh = {
editGroup: '修改分组', editGroup: '修改分组',
group: '分组', group: '分组',
attributeLibray: '属性库', attributeLibray: '属性库',
viewAttributeLibray: '查看属性库',
addGroup2: '添加分组',
modelExport: '模型导出',
filename: '文件名',
filenameInputTips: '请输入文件名',
selectModel: '请选择模型',
unselectModel: '未选',
selectedModel: '已选',
addCITypeInGroup: '在该组中新增CI模型', addCITypeInGroup: '在该组中新增CI模型',
addCIType: '新增CI模型', addCIType: '新增CI模型',
editGroupName: '重命名分组', editGroupName: '重命名分组',
@ -76,6 +84,8 @@ const cmdb_zh = {
byInterval: '按间隔', byInterval: '按间隔',
allNodes: '所有机器', allNodes: '所有机器',
specifyNodes: '指定机器', specifyNodes: '指定机器',
masterNode: 'Master机器',
masterNodeTip: '安装OneMaster的所在机器',
specifyNodesTips: '请填写指定机器!', specifyNodesTips: '请填写指定机器!',
username: '用户名', username: '用户名',
password: '密码', password: '密码',

View File

@ -101,10 +101,14 @@
:cell-style="getCellStyle" :cell-style="getCellStyle"
:scroll-y="{ enabled: true, gt: 20 }" :scroll-y="{ enabled: true, gt: 20 }"
:scroll-x="{ enabled: true, gt: 0 }" :scroll-x="{ enabled: true, gt: 0 }"
class="ops-unstripe-table" class="ops-unstripe-table checkbox-hover-table"
:custom-config="{ storage: true }" :custom-config="{ storage: true }"
> >
<vxe-column align="center" type="checkbox" width="60" :fixed="isCheckboxFixed ? 'left' : ''"></vxe-column> <vxe-column align="center" type="checkbox" width="60" :fixed="isCheckboxFixed ? 'left' : ''">
<template #default="{row}">
{{ getRowSeq(row) }}
</template>
</vxe-column>
<vxe-table-column <vxe-table-column
v-for="(col, index) in columns" v-for="(col, index) in columns"
:key="`${col.field}_${index}`" :key="`${col.field}_${index}`"
@ -1048,6 +1052,9 @@ export default {
this.visible = false this.visible = false
} }
}, },
getRowSeq(row) {
return this.$refs.xTable.getVxetableRef().getRowSeq(row)
}
}, },
} }
</script> </script>
@ -1065,4 +1072,33 @@ export default {
overflow: auto; overflow: auto;
margin-bottom: -24px; margin-bottom: -24px;
} }
.checkbox-hover-table {
/deep/ .vxe-table--body-wrapper {
.vxe-checkbox--label {
display: inline;
padding-left: 0px !important;
color: #bfbfbf;
}
.vxe-icon-checkbox-unchecked {
display: none;
}
.vxe-icon-checkbox-checked ~ .vxe-checkbox--label {
display: none;
}
.vxe-cell--checkbox {
&:hover {
.vxe-icon-checkbox-unchecked {
display: inline;
}
.vxe-checkbox--label {
display: none;
}
}
}
}
}
</style> </style>

View File

@ -69,6 +69,13 @@
> >
<a @click="handleOpenCmdb" slot="suffix"><a-icon type="menu"/></a> <a @click="handleOpenCmdb" slot="suffix"><a-icon type="menu"/></a>
</a-input> </a-input>
<span
v-show="agent_type === 'master'"
slot="extra_master"
class="radio-master-tip"
>
{{ $t('cmdb.ciType.masterNodeTip') }}
</span>
</CustomRadio> </CustomRadio>
</a-form-model-item> </a-form-model-item>
<a-form-model-item <a-form-model-item
@ -284,6 +291,10 @@ export default {
radios.unshift({ value: 'all', label: this.$t('cmdb.ciType.allNodes') }) radios.unshift({ value: 'all', label: this.$t('cmdb.ciType.allNodes') })
} }
if (this.adrType !== 'agent' || this?.currentAdr?.is_plugin) {
radios.unshift({ value: 'master', label: this.$t('cmdb.ciType.masterNode') })
}
return radios return radios
}, },
radioList() { radioList() {
@ -378,13 +389,13 @@ export default {
} }
this.form = { this.form = {
auto_accept: _findADT?.auto_accept || false, auto_accept: _findADT?.auto_accept || false,
agent_id: _findADT.agent_id || '', agent_id: _findADT?.agent_id && _findADT?.agent_id !== '0x0000' ? _findADT.agent_id : '',
query_expr: _findADT.query_expr || '', query_expr: _findADT.query_expr || '',
} }
if (_findADT.query_expr) { if (_findADT.query_expr) {
this.agent_type = 'query_expr' this.agent_type = 'query_expr'
} else if (_findADT.agent_id) { } else if (_findADT.agent_id) {
this.agent_type = 'agent_id' this.agent_type = _findADT.agent_id === '0x0000' ? 'master' : 'agent_id'
} else { } else {
this.agent_type = this.agentTypeRadioList[0].value this.agent_type = this.agentTypeRadioList[0].value
} }
@ -477,6 +488,10 @@ export default {
} }
} }
if (this.agent_type === 'master') {
params.agent_id = '0x0000'
}
if (!this.cron) { if (!this.cron) {
this.$message.error(this.$t('cmdb.ciType.cronRequiredTip')) this.$message.error(this.$t('cmdb.ciType.cronRequiredTip'))
return return
@ -578,6 +593,11 @@ export default {
margin-left: 17px; margin-left: 17px;
margin-bottom: 20px; margin-bottom: 20px;
} }
.radio-master-tip {
font-size: 12px;
color: #86909c;
}
} }
.attr-ad-snmp-form { .attr-ad-snmp-form {
.ant-form-item { .ant-form-item {

View File

@ -241,8 +241,8 @@ export default {
<style lang="less" scoped> <style lang="less" scoped>
.attribute-card { .attribute-card {
width: 182px; width: 172px;
height: 80px; height: 75px;
background: @primary-color_6; background: @primary-color_6;
border-radius: 2px; border-radius: 2px;
position: relative; position: relative;
@ -308,7 +308,7 @@ export default {
} }
} }
.attribute-card-footer { .attribute-card-footer {
width: 182px; width: 172px;
height: 30px; height: 30px;
padding: 0 8px; padding: 0 8px;
position: absolute; position: absolute;

View File

@ -104,7 +104,7 @@
:filter="'.filter-empty'" :filter="'.filter-empty'"
:animation="300" :animation="300"
tag="div" tag="div"
style="width: 100%; display: flex;flex-flow: wrap" style="width: 100%; display: flex; flex-flow: wrap; column-gap: 10px;"
handle=".handle" handle=".handle"
> >
<AttributeCard <AttributeCard
@ -146,7 +146,7 @@
} }
" "
:animation="300" :animation="300"
style="min-height: 2rem; width: 100%; display: flex; flex-flow: wrap" style="min-height: 2rem; width: 100%; display: flex; flex-flow: wrap; column-gap: 10px;"
handle=".handle" handle=".handle"
> >
<AttributeCard <AttributeCard

View File

@ -15,38 +15,40 @@
:triggerLength="18" :triggerLength="18"
> >
<template #one> <template #one>
<div class="ci-types-left">
<div class="ci-types-left-header">
<a-input <a-input
:placeholder="$t('cmdb.preference.searchPlaceholder')" :placeholder="$t('cmdb.preference.searchPlaceholder')"
class="cmdb-ci-types-left-input" class="ci-types-left-header-input"
@pressEnter="handleSearch" @pressEnter="handleSearch"
> >
<a-icon slot="prefix" type="search" /> <a-icon slot="prefix" type="search" />
</a-input> </a-input>
<div class="ci-types-left"> <a-dropdown>
<div class="ci-types-left-title"> <a-button class="ci-types-left-header-more">
<a-button <ops-icon type="veops-more" />
:disabled="!permissions.includes('admin') && !permissions.includes('cmdb_admin')" </a-button>
type="primary" <a-menu slot="overlay">
size="small" <a-menu-item @click="handleClickAddGroup" key="0">
ghost <ops-icon type="veops-increase"/>
@click="handleClickAddGroup" <span>
class="ops-button-ghost" {{ $t('cmdb.ciType.addGroup2') }}
><ops-icon type="veops-increase" />{{ $t('cmdb.ciType.group') }}</a-button </span>
> </a-menu-item>
<a-space> <a-menu-item
<span key="1"
:style="{ cursor: 'pointer' }"
@click=" @click="
() => { () => {
$refs.attributeStore.open() $refs.attributeStore.open()
} }
" "
>{{ $t('cmdb.ciType.attributeLibray') }} >
<ops-icon type="ops-menu"/>
<span>
{{ $t('cmdb.ciType.viewAttributeLibray') }}
</span> </span>
<a-dropdown v-if="permissions.includes('admin') || permissions.includes('cmdb_admin')"> </a-menu-item>
<ops-icon type="ops-menu" :style="{ cursor: 'pointer' }" /> <a-menu-item v-if="permissions.includes('admin') || permissions.includes('cmdb_admin')" key="2">
<a-menu slot="overlay">
<a-menu-item key="0">
<a-upload <a-upload
name="file" name="file"
accept=".json" accept=".json"
@ -55,19 +57,17 @@
action="/api/v0.1/ci_types/template/import/file" action="/api/v0.1/ci_types/template/import/file"
@change="changeUploadFile" @change="changeUploadFile"
> >
<a><a-icon type="upload"/></a><a> {{ $t('upload') }}</a> <ops-icon type="veops-import"/>
<span style="margin-left: 8px">{{ $t('upload') }}</span>
</a-upload> </a-upload>
</a-menu-item> </a-menu-item>
<a-menu-item key="1"> <a-menu-item @click="modelExportVisible = true" v-if="permissions.includes('admin') || permissions.includes('cmdb_admin')" key="3">
<a-space> <span>
<a href="/api/v0.1/ci_types/template/export/file"> <ops-icon type="veops-export" /> {{ $t('export') }}
<a-icon type="download" /> {{ $t('download') }} </span>
</a></a-space
>
</a-menu-item> </a-menu-item>
</a-menu> </a-menu>
</a-dropdown> </a-dropdown>
</a-space>
</div> </div>
<draggable class="ci-types-left-content" :list="computedCITypeGroups" @end="handleChangeGroups" filter=".undraggable"> <draggable class="ci-types-left-content" :list="computedCITypeGroups" @end="handleChangeGroups" filter=".undraggable">
<div v-for="g in computedCITypeGroups" :key="g.id || g.name"> <div v-for="g in computedCITypeGroups" :key="g.id || g.name">
@ -158,7 +158,6 @@
</a-menu-item> </a-menu-item>
<a-menu-item <a-menu-item
v-if="permissions.includes('admin') || permissions.includes('cmdb_admin')" v-if="permissions.includes('admin') || permissions.includes('cmdb_admin')"
:disabled="ci.inherited"
@click="(e) => handleDownloadCiType(e, ci)" @click="(e) => handleDownloadCiType(e, ci)"
> >
<a-icon type="download" /> <a-icon type="download" />
@ -378,6 +377,11 @@
</CustomDrawer> </CustomDrawer>
<CMDBGrant ref="cmdbGrant" resourceType="CIType" app_id="cmdb" /> <CMDBGrant ref="cmdbGrant" resourceType="CIType" app_id="cmdb" />
<AttributeStore ref="attributeStore" /> <AttributeStore ref="attributeStore" />
<ModelExport
:visible="modelExportVisible"
:CITypeGroups="CITypeGroups"
@cancel="() => modelExportVisible = false"
/>
</div> </div>
</template> </template>
@ -401,6 +405,7 @@ import {
putCITypeGroupByGId, putCITypeGroupByGId,
deleteCITypeGroup, deleteCITypeGroup,
putCITypeGroups, putCITypeGroups,
exportCITypeGroups
} from '@/modules/cmdb/api/ciTypeGroup' } from '@/modules/cmdb/api/ciTypeGroup'
import { searchAttributes, getCITypeAttributesById } from '@/modules/cmdb/api/CITypeAttr' import { searchAttributes, getCITypeAttributesById } from '@/modules/cmdb/api/CITypeAttr'
import CreateNewAttribute from './ceateNewAttribute.vue' import CreateNewAttribute from './ceateNewAttribute.vue'
@ -415,6 +420,7 @@ import { ops_move_icon as OpsMoveIcon } from '@/core/icons'
import AttributeStore from './attributeStore.vue' import AttributeStore from './attributeStore.vue'
import { getAllDepAndEmployee } from '@/api/company' import { getAllDepAndEmployee } from '@/api/company'
import CMDBTypeSelect from '../../components/cmdbTypeSelect' import CMDBTypeSelect from '../../components/cmdbTypeSelect'
import ModelExport from './modelExport.vue'
export default { export default {
name: 'CITypes', name: 'CITypes',
@ -430,6 +436,7 @@ export default {
OpsMoveIcon, OpsMoveIcon,
AttributeStore, AttributeStore,
CMDBTypeSelect, CMDBTypeSelect,
ModelExport
}, },
inject: ['reload'], inject: ['reload'],
data() { data() {
@ -476,6 +483,7 @@ export default {
unique_id: null, unique_id: null,
searchValue: '', searchValue: '',
modelExportVisible: false,
} }
}, },
computed: { computed: {
@ -916,20 +924,37 @@ export default {
}, },
}) })
}, },
handleDownloadCiType(e, ci) { async handleDownloadCiType(e, ci) {
e.domEvent.preventDefault() e.domEvent.preventDefault()
e.domEvent.stopPropagation() e.domEvent.stopPropagation()
const x = new XMLHttpRequest()
x.open('GET', `/api/v0.1/ci_types/${ci.id}/template/export`, true) const hide = this.$message.loading(this.$t('loading'), 0)
x.responseType = 'blob' try {
x.onload = function(e) { const res = await exportCITypeGroups({
const url = window.URL.createObjectURL(x.response) type_ids: ci.id
})
console.log('exportCITypeGroups res', res)
if (res) {
const jsonStr = JSON.stringify(res)
const blob = new Blob([jsonStr], { type: 'application/json' })
const url = URL.createObjectURL(blob)
const a = document.createElement('a') const a = document.createElement('a')
a.href = url a.href = url
a.download = `${ci.alias || ci.name}.json`
const fileName = `${ci.alias || ci.name}.json`
a.download = fileName
a.click() a.click()
URL.revokeObjectURL(url)
} }
x.send() } catch (error) {
console.log('exportCITypeGroups fail', error)
hide()
}
hide()
}, },
resetRoute() { resetRoute() {
resetRouter() resetRouter()
@ -1022,7 +1047,7 @@ export default {
this.reload() this.reload()
} }
if (file.status === 'error') { if (file.status === 'error') {
this.$message.error({ content: this.$t('cmdb.ciType.uploadFailed'), key, duration: 2 }) this.$message.error({ content: file?.response?.message || this.$t('cmdb.ciType.uploadFailed'), key, duration: 2 })
} }
}, },
handleChangeUnique(value) { handleChangeUnique(value) {
@ -1046,33 +1071,39 @@ export default {
top: 40%; top: 40%;
transform: translate(-50%, -50%); transform: translate(-50%, -50%);
} }
/deep/.cmdb-ci-types-left-input {
input {
background-color: transparent;
}
.ant-input:focus {
box-shadow: none;
}
}
.ci-types-left { .ci-types-left {
width: 100%; width: 100%;
overflow: auto; overflow: auto;
float: left; float: left;
&-header {
display: flex;
gap: 6px;
&-more {
flex-shrink: 0;
width: 32px;
padding: 0px;
}
/deep/ &-input {
.ant-input:focus {
box-shadow: none;
}
}
}
.ci-types-left-content { .ci-types-left-content {
max-height: calc(100% - 45px); max-height: calc(100% - 45px);
overflow: hidden; overflow: hidden;
margin-top: 10px;
&:hover { &:hover {
overflow: auto; overflow: auto;
} }
} }
.ci-types-left-title {
padding: 10px 0;
display: flex;
flex-direction: row;
justify-content: space-between;
color: @text-color_3;
}
.ci-types-left-group { .ci-types-left-group {
position: relative; position: relative;
padding: 8px 0 8px 14px; padding: 8px 0 8px 14px;

View File

@ -0,0 +1,200 @@
<template>
<a-modal
:visible="visible"
:title="$t('cmdb.ciType.modelExport')"
:width="560"
@cancel="handleCancel"
@ok="handleOK"
>
<a-form
:form="form"
:labelCol="{ span: 5 }"
:wrapperCol="{ span: 19 }"
>
<a-form-item
:label="$t('cmdb.ciType.filename')"
>
<a-input v-decorator="['name', { rules: [{ required: true, message: $t('cmdb.ciType.filenameInputTips') }], initialValue: 'cmdb_template' }]" />
</a-form-item>
<a-form-item
:label="$t('cmdb.ciType.selectModel')"
>
<a-transfer
class="model-export-transfer"
:dataSource="transferDataSource"
:targetKeys="targetKeys"
:render="item => item.title"
:titles="[$t('cmdb.ciType.unselectModel'), $t('cmdb.ciType.selectedModel')]"
:listStyle="{
width: '180px',
height: `262px`,
}"
@change="onChange"
>
<template
slot="children"
slot-scope="{ props: { direction, selectedKeys }, on: { itemSelect } }"
>
<a-tree
v-if="direction === 'left'"
blockNode
checkable
:checkedKeys="[...selectedKeys, ...targetKeys]"
:treeData="treeData"
:checkStrictly="true"
@check="
(_, props) => {
onChecked(_, props, [...selectedKeys, ...targetKeys], itemSelect);
}
"
@select="
(_, props) => {
onChecked(_, props, [...selectedKeys, ...targetKeys], itemSelect);
}
"
/>
</template>
</a-transfer>
</a-form-item>
</a-form>
</a-modal>
</template>
<script>
import _ from 'lodash'
import { exportCITypeGroups } from '@/modules/cmdb/api/ciTypeGroup'
export default {
name: 'ModelExport',
props: {
visible: {
type: Boolean,
default: false,
},
CITypeGroups: {
type: Array,
default: () => []
}
},
data() {
return {
form: this.$form.createForm(this, { name: 'model-export' }),
targetKeys: [],
btnLoading: false,
}
},
computed: {
transferDataSource() {
const dataSource = this.CITypeGroups.reduce((acc, item) => {
const types = _.cloneDeep(item?.ci_types || [])
types.forEach((item) => {
item.key = String(item.id)
item.title = item?.alias || item?.name || this.$t('other')
})
return acc.concat(types)
}, [])
return dataSource
},
treeData() {
const treeData = _.cloneDeep(this.CITypeGroups)
let newTreeData = treeData.map((item) => {
const childrenKeys = []
const children = (item.ci_types || []).map((child) => {
const key = String(child?.id)
const disabled = this.targetKeys.includes(key)
childrenKeys.push(key)
return {
key,
title: child?.alias || child?.name || this.$t('other'),
disabled,
checkable: true,
children: []
}
})
return {
key: String(item?.id),
title: item?.name || this.$t('other'),
children,
childrenKeys,
disabled: children.every((item) => item.disabled),
checkable: false,
selectable: false
}
})
console.log('treeData', newTreeData)
newTreeData = newTreeData.filter((item) => item.children.length > 0)
return newTreeData
}
},
methods: {
onChange(targetKeys, direction, moveKeys) {
this.targetKeys = targetKeys
},
onChecked(_, e, checkedKeys, itemSelect) {
const { eventKey } = e.node
const selected = checkedKeys.indexOf(eventKey) === -1
itemSelect(eventKey, selected)
},
handleCancel() {
this.$emit('cancel')
this.form.resetFields()
this.targetKeys = []
},
handleOK() {
this.form.validateFields(async (err, values) => {
if (err || !this.targetKeys.length || this.btnLoading) {
return
}
this.btnLoading = true
const hide = this.$message.loading(this.$t('loading'), 0)
try {
const typeIds = this.targetKeys.join(',')
const res = await exportCITypeGroups({
type_ids: typeIds
})
console.log('exportCITypeGroups res', res)
if (res) {
const jsonStr = JSON.stringify(res)
const blob = new Blob([jsonStr], { type: 'application/json' })
const url = URL.createObjectURL(blob)
const a = document.createElement('a')
a.href = url
const fileName = values.name
a.download = fileName
a.click()
URL.revokeObjectURL(url)
}
} catch (error) {
console.log('exportCITypeGroups fail', error)
hide()
this.btnLoading = false
}
hide()
this.btnLoading = false
})
}
}
}
</script>
<style lang="less" scoped>
.model-export-transfer {
/deep/ .ant-transfer-list-body {
overflow: auto;
}
/deep/ .ant-transfer-list-header-title {
color: @primary-color;
font-weight: 400;
font-size: 12px;
}
}
</style>

View File

@ -58,7 +58,7 @@
ref="xTable" ref="xTable"
size="mini" size="mini"
stripe stripe
class="ops-stripe-table" class="ops-stripe-table checkbox-hover-table"
:data="filterTableData" :data="filterTableData"
:height="tableHeight" :height="tableHeight"
:scroll-y="{ enabled: true, gt: 50 }" :scroll-y="{ enabled: true, gt: 50 }"
@ -74,7 +74,11 @@
type="checkbox" type="checkbox"
width="60" width="60"
fixed="left" fixed="left"
></vxe-column> >
<template #default="{row}">
{{ getRowSeq(row) }}
</template>
</vxe-column>
<vxe-column <vxe-column
v-for="(col, index) in columns" v-for="(col, index) in columns"
:key="`${col.field}_${index}`" :key="`${col.field}_${index}`"
@ -399,6 +403,9 @@ export default {
textEl.scrollTop = textEl.scrollHeight textEl.scrollTop = textEl.scrollHeight
} }
}) })
},
getRowSeq(row) {
return this.$refs.xTable.getVxetableRef().getRowSeq(row)
} }
}, },
} }
@ -462,6 +469,36 @@ export default {
align-items: center; align-items: center;
gap: 6px; gap: 6px;
} }
.checkbox-hover-table {
/deep/ .vxe-table--body-wrapper {
.vxe-checkbox--label {
display: inline;
padding-left: 0px !important;
color: #bfbfbf;
}
.vxe-icon-checkbox-unchecked {
display: none;
}
.vxe-icon-checkbox-checked ~ .vxe-checkbox--label {
display: none;
}
.vxe-cell--checkbox {
&:hover {
.vxe-icon-checkbox-unchecked {
display: inline;
}
.vxe-checkbox--label {
display: none;
}
}
}
}
}
} }
.log-modal-title { .log-modal-title {

View File

@ -190,10 +190,14 @@
:cell-style="getCellStyle" :cell-style="getCellStyle"
:scroll-y="{ enabled: true, gt: 20 }" :scroll-y="{ enabled: true, gt: 20 }"
:scroll-x="{ enabled: true, gt: 0 }" :scroll-x="{ enabled: true, gt: 0 }"
class="ops-unstripe-table" class="ops-unstripe-table checkbox-hover-table"
:custom-config="{ storage: true }" :custom-config="{ storage: true }"
> >
<vxe-column v-if="isLeaf" align="center" type="checkbox" width="50" fixed="left"></vxe-column> <vxe-column v-if="isLeaf" align="center" type="checkbox" width="50" fixed="left">
<template #default="{row}">
{{ getRowSeq(row) }}
</template>
</vxe-column>
<vxe-table-column <vxe-table-column
v-for="(col, index) in columns" v-for="(col, index) in columns"
:key="`${col.field}_${index}`" :key="`${col.field}_${index}`"
@ -1821,6 +1825,10 @@ export default {
}) })
return array return array
}, },
getRowSeq(row) {
return this.$refs.xTable.getRowSeq(row)
}
}, },
} }
</script> </script>
@ -1888,6 +1896,36 @@ export default {
background-color: #fff; background-color: #fff;
padding: 20px; padding: 20px;
border-radius: @border-radius-box; border-radius: @border-radius-box;
.checkbox-hover-table {
.vxe-table--body-wrapper {
.vxe-checkbox--label {
display: inline;
padding-left: 0px !important;
color: #bfbfbf;
}
.vxe-icon-checkbox-unchecked {
display: none;
}
.vxe-icon-checkbox-checked ~ .vxe-checkbox--label {
display: none;
}
.vxe-cell--checkbox {
&:hover {
.vxe-icon-checkbox-unchecked {
display: inline;
}
.vxe-checkbox--label {
display: none;
}
}
}
}
}
} }
} }
</style> </style>

View File

@ -172,10 +172,14 @@
@edit-closed="handleEditClose" @edit-closed="handleEditClose"
@edit-actived="handleEditActived" @edit-actived="handleEditActived"
:edit-config="{ trigger: 'dblclick', mode: 'row', showIcon: false }" :edit-config="{ trigger: 'dblclick', mode: 'row', showIcon: false }"
class="ops-unstripe-table" class="ops-unstripe-table checkbox-hover-table"
:custom-config="{ storage: true }" :custom-config="{ storage: true }"
> >
<vxe-column align="center" type="checkbox" width="60" :fixed="isCheckboxFixed ? 'left' : ''"></vxe-column> <vxe-column align="center" type="checkbox" width="60" :fixed="isCheckboxFixed ? 'left' : ''">
<template #default="{row}">
{{ getRowSeq(row) }}
</template>
</vxe-column>
<vxe-table-column <vxe-table-column
v-for="(col, index) in columns" v-for="(col, index) in columns"
:key="`${col.field}_${index}`" :key="`${col.field}_${index}`"
@ -1229,6 +1233,9 @@ export default {
} }
) )
}, },
getRowSeq(row) {
return this.$refs.xTable.getVxetableRef().getRowSeq(row)
}
}, },
} }
</script> </script>
@ -1337,6 +1344,36 @@ export default {
overflow: auto; overflow: auto;
width: 100%; width: 100%;
border-radius: @border-radius-box; border-radius: @border-radius-box;
.checkbox-hover-table {
.vxe-table--body-wrapper {
.vxe-checkbox--label {
display: inline;
padding-left: 0px !important;
color: #bfbfbf;
}
.vxe-icon-checkbox-unchecked {
display: none;
}
.vxe-icon-checkbox-checked ~ .vxe-checkbox--label {
display: none;
}
.vxe-cell--checkbox {
&:hover {
.vxe-icon-checkbox-unchecked {
display: inline;
}
.vxe-checkbox--label {
display: none;
}
}
}
}
}
} }
} }
</style> </style>