mirror of https://github.com/veops/cmdb.git
feat(ui):i18n (#347)
* feat(acl-ui):i18n * feat(base-ui):i18n * feat(cmdb-ui):i18n
This commit is contained in:
parent
ace160ae19
commit
e429ad59ff
|
@ -1,5 +1,5 @@
|
||||||
<template>
|
<template>
|
||||||
<a-config-provider :locale="locale">
|
<a-config-provider :locale="antdLocale">
|
||||||
<div id="app" :class="{ 'ops-fullscreen': isOpsFullScreen, 'ops-only-topmenu': isOpsOnlyTopMenu }">
|
<div id="app" :class="{ 'ops-fullscreen': isOpsFullScreen, 'ops-only-topmenu': isOpsOnlyTopMenu }">
|
||||||
<router-view v-if="alive" />
|
<router-view v-if="alive" />
|
||||||
</div>
|
</div>
|
||||||
|
@ -7,8 +7,9 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { mapActions } from 'vuex'
|
import { mapState, mapActions, mapMutations } from 'vuex'
|
||||||
import zhCN from 'ant-design-vue/lib/locale-provider/zh_CN'
|
import zhCN from 'ant-design-vue/lib/locale-provider/zh_CN'
|
||||||
|
import enUS from 'ant-design-vue/lib/locale-provider/en_US'
|
||||||
import { AppDeviceEnquire } from '@/utils/mixin'
|
import { AppDeviceEnquire } from '@/utils/mixin'
|
||||||
import { debounce } from './utils/util'
|
import { debounce } from './utils/util'
|
||||||
|
|
||||||
|
@ -24,20 +25,28 @@ export default {
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
locale: zhCN,
|
|
||||||
alive: true,
|
alive: true,
|
||||||
timer: null,
|
timer: null,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
...mapState(['locale']),
|
||||||
|
antdLocale() {
|
||||||
|
if (this.locale === 'zh') {
|
||||||
|
return zhCN
|
||||||
|
}
|
||||||
|
return enUS
|
||||||
|
},
|
||||||
isOpsFullScreen() {
|
isOpsFullScreen() {
|
||||||
return this.$route.name === 'cmdb_screen'
|
return ['cmdb_screen'].includes(this.$route.name)
|
||||||
},
|
},
|
||||||
isOpsOnlyTopMenu() {
|
isOpsOnlyTopMenu() {
|
||||||
return ['fullscreen_index', 'setting_person'].includes(this.$route.name)
|
return ['fullscreen_index', 'setting_person', 'notice_center'].includes(this.$route.name)
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
created() {
|
created() {
|
||||||
|
this.SET_LOCALE(localStorage.getItem('ops_locale') || 'zh')
|
||||||
|
this.$i18n.locale = localStorage.getItem('ops_locale') || 'zh'
|
||||||
this.timer = setInterval(() => {
|
this.timer = setInterval(() => {
|
||||||
this.setTime(new Date().getTime())
|
this.setTime(new Date().getTime())
|
||||||
}, 1000)
|
}, 1000)
|
||||||
|
@ -184,6 +193,7 @@ export default {
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
...mapActions(['setTime']),
|
...mapActions(['setTime']),
|
||||||
|
...mapMutations(['SET_LOCALE']),
|
||||||
reload() {
|
reload() {
|
||||||
this.alive = false
|
this.alive = false
|
||||||
this.$nextTick(() => {
|
this.$nextTick(() => {
|
||||||
|
|
|
@ -1,29 +1,37 @@
|
||||||
export const ruleTypeList = [
|
import i18n from '@/lang'
|
||||||
{ value: 'and', label: '与' },
|
|
||||||
{ value: 'or', label: '或' },
|
|
||||||
// { value: 'not', label: '非' },
|
|
||||||
]
|
|
||||||
|
|
||||||
export const expList = [
|
export const ruleTypeList = () => {
|
||||||
{ value: 'is', label: '等于' },
|
return [
|
||||||
{ value: '~is', label: '不等于' },
|
{ value: 'and', label: i18n.t('cmdbFilterComp.and') },
|
||||||
{ value: 'contain', label: '包含' },
|
{ value: 'or', label: i18n.t('cmdbFilterComp.or') },
|
||||||
{ value: '~contain', label: '不包含' },
|
// { value: 'not', label: '非' },
|
||||||
{ value: 'start_with', label: '以...开始' },
|
]
|
||||||
{ value: '~start_with', label: '不以...开始' },
|
}
|
||||||
{ value: 'end_with', label: '以...结束' },
|
|
||||||
{ value: '~end_with', label: '不以...结束' },
|
|
||||||
{ value: '~value', label: '为空' }, // 为空的定义有点绕
|
|
||||||
{ value: 'value', label: '不为空' },
|
|
||||||
]
|
|
||||||
|
|
||||||
export const advancedExpList = [
|
export const expList = () => {
|
||||||
{ value: 'in', label: 'in查询' },
|
return [
|
||||||
{ value: '~in', label: '非in查询' },
|
{ value: 'is', label: i18n.t('cmdbFilterComp.is') },
|
||||||
{ value: 'range', label: '范围' },
|
{ value: '~is', label: i18n.t('cmdbFilterComp.~is') },
|
||||||
{ value: '~range', label: '范围外' },
|
{ value: 'contain', label: i18n.t('cmdbFilterComp.contain') },
|
||||||
{ value: 'compare', label: '比较' },
|
{ value: '~contain', label: i18n.t('cmdbFilterComp.~contain') },
|
||||||
]
|
{ value: 'start_with', label: i18n.t('cmdbFilterComp.start_with') },
|
||||||
|
{ value: '~start_with', label: i18n.t('cmdbFilterComp.~start_with') },
|
||||||
|
{ value: 'end_with', label: i18n.t('cmdbFilterComp.end_with') },
|
||||||
|
{ value: '~end_with', label: i18n.t('cmdbFilterComp.~end_with') },
|
||||||
|
{ value: '~value', label: i18n.t('cmdbFilterComp.~value') }, // 为空的定义有点绕
|
||||||
|
{ value: 'value', label: i18n.t('cmdbFilterComp.value') },
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
export const advancedExpList = () => {
|
||||||
|
return [
|
||||||
|
{ value: 'in', label: i18n.t('cmdbFilterComp.in') },
|
||||||
|
{ value: '~in', label: i18n.t('cmdbFilterComp.~in') },
|
||||||
|
{ value: 'range', label: i18n.t('cmdbFilterComp.range') },
|
||||||
|
{ value: '~range', label: i18n.t('cmdbFilterComp.~range') },
|
||||||
|
{ value: 'compare', label: i18n.t('cmdbFilterComp.compare') },
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
export const compareTypeList = [
|
export const compareTypeList = [
|
||||||
{ value: '1', label: '>' },
|
{ value: '1', label: '>' },
|
||||||
|
|
|
@ -1,293 +1,332 @@
|
||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<a-space :style="{ display: 'flex', marginBottom: '10px' }" v-for="(item, index) in ruleList" :key="item.id">
|
<a-space :style="{ display: 'flex', marginBottom: '10px' }" v-for="(item, index) in ruleList" :key="item.id">
|
||||||
<div :style="{ width: '50px', height: '24px', position: 'relative' }">
|
<div :style="{ width: '70px', height: '24px', position: 'relative' }">
|
||||||
<treeselect
|
<treeselect
|
||||||
v-if="index"
|
v-if="index"
|
||||||
class="custom-treeselect"
|
class="custom-treeselect"
|
||||||
:style="{ width: '50px', '--custom-height': '24px', position: 'absolute', top: '-17px', left: 0 }"
|
:style="{ width: '70px', '--custom-height': '24px', position: 'absolute', top: '-17px', left: 0 }"
|
||||||
v-model="item.type"
|
v-model="item.type"
|
||||||
:multiple="false"
|
:multiple="false"
|
||||||
:clearable="false"
|
:clearable="false"
|
||||||
searchable
|
searchable
|
||||||
:options="ruleTypeList"
|
:options="ruleTypeList"
|
||||||
:normalizer="
|
:normalizer="
|
||||||
(node) => {
|
(node) => {
|
||||||
return {
|
return {
|
||||||
id: node.value,
|
id: node.value,
|
||||||
label: node.label,
|
label: node.label,
|
||||||
children: node.children,
|
children: node.children,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
"
|
"
|
||||||
>
|
>
|
||||||
</treeselect>
|
</treeselect>
|
||||||
</div>
|
</div>
|
||||||
<treeselect
|
<treeselect
|
||||||
class="custom-treeselect"
|
class="custom-treeselect"
|
||||||
:style="{ width: '130px', '--custom-height': '24px' }"
|
:style="{ width: '130px', '--custom-height': '24px' }"
|
||||||
v-model="item.property"
|
v-model="item.property"
|
||||||
:multiple="false"
|
:multiple="false"
|
||||||
:clearable="false"
|
:clearable="false"
|
||||||
searchable
|
searchable
|
||||||
:options="canSearchPreferenceAttrList"
|
:options="canSearchPreferenceAttrList"
|
||||||
:normalizer="
|
:normalizer="
|
||||||
(node) => {
|
(node) => {
|
||||||
return {
|
return {
|
||||||
id: node.name,
|
id: node.name,
|
||||||
label: node.alias || node.name,
|
label: node.alias || node.name,
|
||||||
children: node.children,
|
children: node.children,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
"
|
"
|
||||||
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' }"
|
||||||
>
|
>
|
||||||
<ValueTypeMapIcon :attr="node.raw" />
|
<ValueTypeMapIcon :attr="node.raw" />
|
||||||
{{ node.label }}
|
{{ node.label }}
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
:style="{ width: '100%', whiteSpace: 'nowrap', textOverflow: 'ellipsis', overflow: 'hidden' }"
|
:style="{ width: '100%', whiteSpace: 'nowrap', textOverflow: 'ellipsis', overflow: 'hidden' }"
|
||||||
slot="value-label"
|
slot="value-label"
|
||||||
slot-scope="{ node }"
|
slot-scope="{ node }"
|
||||||
>
|
>
|
||||||
<ValueTypeMapIcon :attr="node.raw" /> {{ node.label }}
|
<ValueTypeMapIcon :attr="node.raw" /> {{ node.label }}
|
||||||
</div>
|
</div>
|
||||||
</treeselect>
|
</treeselect>
|
||||||
<treeselect
|
<treeselect
|
||||||
class="custom-treeselect"
|
class="custom-treeselect"
|
||||||
:style="{ width: '100px', '--custom-height': '24px' }"
|
:style="{ width: '100px', '--custom-height': '24px' }"
|
||||||
v-model="item.exp"
|
v-model="item.exp"
|
||||||
:multiple="false"
|
:multiple="false"
|
||||||
:clearable="false"
|
:clearable="false"
|
||||||
searchable
|
searchable
|
||||||
:options="[...getExpListByProperty(item.property), ...advancedExpList]"
|
:options="[...getExpListByProperty(item.property), ...advancedExpList]"
|
||||||
:normalizer="
|
:normalizer="
|
||||||
(node) => {
|
(node) => {
|
||||||
return {
|
return {
|
||||||
id: node.value,
|
id: node.value,
|
||||||
label: node.label,
|
label: node.label,
|
||||||
children: node.children,
|
children: node.children,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
"
|
"
|
||||||
@select="(value) => handleChangeExp(value, item, index)"
|
@select="(value) => handleChangeExp(value, item, index)"
|
||||||
appendToBody
|
appendToBody
|
||||||
:zIndex="1050"
|
:zIndex="1050"
|
||||||
>
|
>
|
||||||
</treeselect>
|
</treeselect>
|
||||||
<treeselect
|
<treeselect
|
||||||
class="custom-treeselect"
|
class="custom-treeselect"
|
||||||
:style="{ width: '175px', '--custom-height': '24px' }"
|
:style="{ width: '175px', '--custom-height': '24px' }"
|
||||||
v-model="item.value"
|
v-model="item.value"
|
||||||
:multiple="false"
|
:multiple="false"
|
||||||
:clearable="false"
|
:clearable="false"
|
||||||
searchable
|
searchable
|
||||||
v-if="isChoiceByProperty(item.property) && (item.exp === 'is' || item.exp === '~is')"
|
v-if="isChoiceByProperty(item.property) && (item.exp === 'is' || item.exp === '~is')"
|
||||||
:options="getChoiceValueByProperty(item.property)"
|
:options="getChoiceValueByProperty(item.property)"
|
||||||
placeholder="请选择"
|
:placeholder="$t('placeholder2')"
|
||||||
:normalizer="
|
:normalizer="
|
||||||
(node) => {
|
(node) => {
|
||||||
return {
|
return {
|
||||||
id: node[0],
|
id: node[0],
|
||||||
label: node[0],
|
label: node[0],
|
||||||
children: node.children,
|
children: node.children,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
"
|
"
|
||||||
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-input-group
|
<a-input-group
|
||||||
size="small"
|
size="small"
|
||||||
compact
|
compact
|
||||||
v-else-if="item.exp === 'range' || item.exp === '~range'"
|
v-else-if="item.exp === 'range' || item.exp === '~range'"
|
||||||
:style="{ width: '175px' }"
|
:style="{ width: '175px' }"
|
||||||
>
|
>
|
||||||
<a-input class="ops-input" size="small" v-model="item.min" :style="{ width: '78px' }" placeholder="最小值" />
|
<a-input
|
||||||
~
|
class="ops-input"
|
||||||
<a-input class="ops-input" size="small" v-model="item.max" :style="{ width: '78px' }" placeholder="最大值" />
|
size="small"
|
||||||
</a-input-group>
|
v-model="item.min"
|
||||||
<a-input-group size="small" compact v-else-if="item.exp === 'compare'" :style="{ width: '175px' }">
|
:style="{ width: '78px' }"
|
||||||
<treeselect
|
:placeholder="$t('min')"
|
||||||
class="custom-treeselect"
|
/>
|
||||||
:style="{ width: '60px', '--custom-height': '24px' }"
|
~
|
||||||
v-model="item.compareType"
|
<a-input
|
||||||
:multiple="false"
|
class="ops-input"
|
||||||
:clearable="false"
|
size="small"
|
||||||
searchable
|
v-model="item.max"
|
||||||
:options="compareTypeList"
|
:style="{ width: '78px' }"
|
||||||
:normalizer="
|
:placeholder="$t('max')"
|
||||||
(node) => {
|
/>
|
||||||
return {
|
</a-input-group>
|
||||||
id: node.value,
|
<a-input-group size="small" compact v-else-if="item.exp === 'compare'" :style="{ width: '175px' }">
|
||||||
label: node.label,
|
<treeselect
|
||||||
children: node.children,
|
class="custom-treeselect"
|
||||||
}
|
:style="{ width: '60px', '--custom-height': '24px' }"
|
||||||
}
|
v-model="item.compareType"
|
||||||
"
|
:multiple="false"
|
||||||
appendToBody
|
:clearable="false"
|
||||||
:zIndex="1050"
|
searchable
|
||||||
>
|
:options="compareTypeList"
|
||||||
</treeselect>
|
:normalizer="
|
||||||
<a-input class="ops-input" v-model="item.value" size="small" style="width: 113px" />
|
(node) => {
|
||||||
</a-input-group>
|
return {
|
||||||
<a-input
|
id: node.value,
|
||||||
v-else-if="item.exp !== 'value' && item.exp !== '~value'"
|
label: node.label,
|
||||||
size="small"
|
children: node.children,
|
||||||
v-model="item.value"
|
}
|
||||||
:placeholder="item.exp === 'in' || item.exp === '~in' ? '以 ; 分隔' : ''"
|
}
|
||||||
class="ops-input"
|
"
|
||||||
></a-input>
|
appendToBody
|
||||||
<div v-else :style="{ width: '175px' }"></div>
|
:zIndex="1050"
|
||||||
<a-tooltip title="复制">
|
>
|
||||||
<a class="operation" @click="handleCopyRule(item)"><ops-icon type="icon-xianxing-copy"/></a>
|
</treeselect>
|
||||||
</a-tooltip>
|
<a-input class="ops-input" v-model="item.value" size="small" style="width: 113px" />
|
||||||
<a-tooltip title="删除">
|
</a-input-group>
|
||||||
<a class="operation" @click="handleDeleteRule(item)"><ops-icon type="icon-xianxing-delete"/></a>
|
<a-input
|
||||||
</a-tooltip>
|
v-else-if="item.exp !== 'value' && item.exp !== '~value'"
|
||||||
</a-space>
|
size="small"
|
||||||
<div class="table-filter-add">
|
v-model="item.value"
|
||||||
<a @click="handleAddRule">+ 新增</a>
|
:placeholder="item.exp === 'in' || item.exp === '~in' ? $t('cmdbFilterComp.split', { separator: ';' }) : ''"
|
||||||
</div>
|
class="ops-input"
|
||||||
</div>
|
:style="{ width: '175px' }"
|
||||||
</template>
|
></a-input>
|
||||||
|
<div v-else :style="{ width: '175px' }"></div>
|
||||||
<script>
|
<a-tooltip :title="$t('copy')">
|
||||||
import _ from 'lodash'
|
<a class="operation" @click="handleCopyRule(item)"><ops-icon type="icon-xianxing-copy"/></a>
|
||||||
import { v4 as uuidv4 } from 'uuid'
|
</a-tooltip>
|
||||||
import { ruleTypeList, expList, advancedExpList, compareTypeList } from './constants'
|
<a-tooltip :title="$t('delete')">
|
||||||
import ValueTypeMapIcon from '../CMDBValueTypeMapIcon'
|
<a class="operation" @click="handleDeleteRule(item)"><ops-icon type="icon-xianxing-delete"/></a>
|
||||||
|
</a-tooltip>
|
||||||
export default {
|
<a-tooltip :title="$t('cmdbFilterComp.addHere')" :needAddHere="needAddHere">
|
||||||
name: 'Expression',
|
<a class="operation" @click="handleAddRuleAt(item)"><a-icon type="plus-circle"/></a>
|
||||||
components: { ValueTypeMapIcon },
|
</a-tooltip>
|
||||||
model: {
|
</a-space>
|
||||||
prop: 'value',
|
<div class="table-filter-add">
|
||||||
event: 'change',
|
<a @click="handleAddRule">+ {{ $t('new') }}</a>
|
||||||
},
|
</div>
|
||||||
props: {
|
</div>
|
||||||
value: {
|
</template>
|
||||||
type: Array,
|
|
||||||
default: () => [],
|
<script>
|
||||||
},
|
import _ from 'lodash'
|
||||||
canSearchPreferenceAttrList: {
|
import { v4 as uuidv4 } from 'uuid'
|
||||||
type: Array,
|
import { ruleTypeList, expList, advancedExpList, compareTypeList } from './constants'
|
||||||
required: true,
|
import ValueTypeMapIcon from '../CMDBValueTypeMapIcon'
|
||||||
default: () => [],
|
|
||||||
},
|
export default {
|
||||||
},
|
name: 'Expression',
|
||||||
data() {
|
components: { ValueTypeMapIcon },
|
||||||
return {
|
model: {
|
||||||
ruleTypeList,
|
prop: 'value',
|
||||||
expList,
|
event: 'change',
|
||||||
advancedExpList,
|
},
|
||||||
compareTypeList,
|
props: {
|
||||||
}
|
value: {
|
||||||
},
|
type: Array,
|
||||||
computed: {
|
default: () => [],
|
||||||
ruleList: {
|
},
|
||||||
get() {
|
canSearchPreferenceAttrList: {
|
||||||
return this.value
|
type: Array,
|
||||||
},
|
required: true,
|
||||||
set(val) {
|
default: () => [],
|
||||||
this.$emit('change', val)
|
},
|
||||||
return val
|
needAddHere: {
|
||||||
},
|
type: Boolean,
|
||||||
},
|
default: false,
|
||||||
},
|
},
|
||||||
methods: {
|
},
|
||||||
getExpListByProperty(property) {
|
data() {
|
||||||
if (property) {
|
return {
|
||||||
const _find = this.canSearchPreferenceAttrList.find((item) => item.name === property)
|
compareTypeList,
|
||||||
if (_find && ['0', '1', '3', '4', '5'].includes(_find.value_type)) {
|
}
|
||||||
return [
|
},
|
||||||
{ value: 'is', label: '等于' },
|
computed: {
|
||||||
{ value: '~is', label: '不等于' },
|
ruleList: {
|
||||||
{ value: '~value', label: '为空' }, // 为空的定义有点绕
|
get() {
|
||||||
{ value: 'value', label: '不为空' },
|
return this.value
|
||||||
]
|
},
|
||||||
}
|
set(val) {
|
||||||
return this.expList
|
this.$emit('change', val)
|
||||||
}
|
return val
|
||||||
return this.expList
|
},
|
||||||
},
|
},
|
||||||
isChoiceByProperty(property) {
|
ruleTypeList() {
|
||||||
const _find = this.canSearchPreferenceAttrList.find((item) => item.name === property)
|
return ruleTypeList()
|
||||||
if (_find) {
|
},
|
||||||
return _find.is_choice
|
expList() {
|
||||||
}
|
return expList()
|
||||||
return false
|
},
|
||||||
},
|
advancedExpList() {
|
||||||
handleAddRule() {
|
return advancedExpList()
|
||||||
this.ruleList.push({
|
},
|
||||||
id: uuidv4(),
|
},
|
||||||
type: 'and',
|
methods: {
|
||||||
property: this.canSearchPreferenceAttrList[0]?.name,
|
getExpListByProperty(property) {
|
||||||
exp: 'is',
|
if (property) {
|
||||||
value: null,
|
const _find = this.canSearchPreferenceAttrList.find((item) => item.name === property)
|
||||||
})
|
if (_find && ['0', '1', '3', '4', '5'].includes(_find.value_type)) {
|
||||||
this.$emit('change', this.ruleList)
|
return [
|
||||||
},
|
{ value: 'is', label: this.$t('cmdbFilterComp.is') },
|
||||||
handleCopyRule(item) {
|
{ value: '~is', label: this.$t('cmdbFilterComp.~is') },
|
||||||
this.ruleList.push({ ...item, id: uuidv4() })
|
{ value: '~value', label: this.$t('cmdbFilterComp.~value') }, // 为空的定义有点绕
|
||||||
this.$emit('change', this.ruleList)
|
{ value: 'value', label: this.$t('cmdbFilterComp.value') },
|
||||||
},
|
]
|
||||||
handleDeleteRule(item) {
|
}
|
||||||
const idx = this.ruleList.findIndex((r) => r.id === item.id)
|
return this.expList
|
||||||
if (idx > -1) {
|
}
|
||||||
this.ruleList.splice(idx, 1)
|
return this.expList
|
||||||
}
|
},
|
||||||
this.$emit('change', this.ruleList)
|
isChoiceByProperty(property) {
|
||||||
},
|
const _find = this.canSearchPreferenceAttrList.find((item) => item.name === property)
|
||||||
getChoiceValueByProperty(property) {
|
if (_find) {
|
||||||
const _find = this.canSearchPreferenceAttrList.find((item) => item.name === property)
|
return _find.is_choice
|
||||||
if (_find) {
|
}
|
||||||
return _find.choice_value
|
return false
|
||||||
}
|
},
|
||||||
return []
|
handleAddRule() {
|
||||||
},
|
this.ruleList.push({
|
||||||
handleChangeExp({ value }, item, index) {
|
id: uuidv4(),
|
||||||
const _ruleList = _.cloneDeep(this.ruleList)
|
type: 'and',
|
||||||
if (value === 'range') {
|
property: this.canSearchPreferenceAttrList[0]?.name,
|
||||||
_ruleList[index] = {
|
exp: 'is',
|
||||||
..._ruleList[index],
|
value: null,
|
||||||
min: '',
|
})
|
||||||
max: '',
|
this.$emit('change', this.ruleList)
|
||||||
exp: value,
|
},
|
||||||
}
|
handleCopyRule(item) {
|
||||||
} else if (value === 'compare') {
|
this.ruleList.push({ ...item, id: uuidv4() })
|
||||||
_ruleList[index] = {
|
this.$emit('change', this.ruleList)
|
||||||
..._ruleList[index],
|
},
|
||||||
compareType: '1',
|
handleDeleteRule(item) {
|
||||||
exp: value,
|
const idx = this.ruleList.findIndex((r) => r.id === item.id)
|
||||||
}
|
if (idx > -1) {
|
||||||
} else {
|
this.ruleList.splice(idx, 1)
|
||||||
_ruleList[index] = {
|
}
|
||||||
..._ruleList[index],
|
this.$emit('change', this.ruleList)
|
||||||
exp: value,
|
},
|
||||||
}
|
handleAddRuleAt(item) {
|
||||||
}
|
const idx = this.ruleList.findIndex((r) => r.id === item.id)
|
||||||
this.ruleList = _ruleList
|
if (idx > -1) {
|
||||||
this.$emit('change', this.ruleList)
|
this.ruleList.splice(idx, 0, {
|
||||||
},
|
id: uuidv4(),
|
||||||
},
|
type: 'and',
|
||||||
}
|
property: this.canSearchPreferenceAttrList[0]?.name,
|
||||||
</script>
|
exp: 'is',
|
||||||
|
value: null,
|
||||||
<style></style>
|
})
|
||||||
|
}
|
||||||
|
this.$emit('change', this.ruleList)
|
||||||
|
},
|
||||||
|
getChoiceValueByProperty(property) {
|
||||||
|
const _find = this.canSearchPreferenceAttrList.find((item) => item.name === property)
|
||||||
|
if (_find) {
|
||||||
|
return _find.choice_value
|
||||||
|
}
|
||||||
|
return []
|
||||||
|
},
|
||||||
|
handleChangeExp({ value }, item, index) {
|
||||||
|
const _ruleList = _.cloneDeep(this.ruleList)
|
||||||
|
if (value === 'range') {
|
||||||
|
_ruleList[index] = {
|
||||||
|
..._ruleList[index],
|
||||||
|
min: '',
|
||||||
|
max: '',
|
||||||
|
exp: value,
|
||||||
|
}
|
||||||
|
} else if (value === 'compare') {
|
||||||
|
_ruleList[index] = {
|
||||||
|
..._ruleList[index],
|
||||||
|
compareType: '1',
|
||||||
|
exp: value,
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
_ruleList[index] = {
|
||||||
|
..._ruleList[index],
|
||||||
|
exp: value,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.ruleList = _ruleList
|
||||||
|
this.$emit('change', this.ruleList)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style></style>
|
||||||
|
|
|
@ -1,290 +1,296 @@
|
||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<a-popover
|
<a-popover
|
||||||
v-if="isDropdown"
|
v-if="isDropdown"
|
||||||
v-model="visible"
|
v-model="visible"
|
||||||
trigger="click"
|
trigger="click"
|
||||||
:placement="placement"
|
:placement="placement"
|
||||||
overlayClassName="table-filter"
|
overlayClassName="table-filter"
|
||||||
@visibleChange="visibleChange"
|
@visibleChange="visibleChange"
|
||||||
>
|
>
|
||||||
<slot name="popover_item">
|
<slot name="popover_item">
|
||||||
<a-button type="primary" ghost>条件过滤<a-icon type="filter"/></a-button>
|
<a-button type="primary" ghost>{{ $t('cmdbFilterComp.conditionFilter') }}<a-icon type="filter"/></a-button>
|
||||||
</slot>
|
</slot>
|
||||||
<template slot="content">
|
<template slot="content">
|
||||||
<Expression
|
<Expression
|
||||||
v-model="ruleList"
|
:needAddHere="needAddHere"
|
||||||
:canSearchPreferenceAttrList="canSearchPreferenceAttrList.filter((attr) => !attr.is_password)"
|
v-model="ruleList"
|
||||||
/>
|
:canSearchPreferenceAttrList="canSearchPreferenceAttrList.filter((attr) => !attr.is_password)"
|
||||||
<a-divider :style="{ margin: '10px 0' }" />
|
/>
|
||||||
<div style="width:534px">
|
<a-divider :style="{ margin: '10px 0' }" />
|
||||||
<a-space :style="{ display: 'flex', justifyContent: 'flex-end' }">
|
<div style="width:554px">
|
||||||
<a-button type="primary" size="small" @click="handleSubmit">确定</a-button>
|
<a-space :style="{ display: 'flex', justifyContent: 'flex-end' }">
|
||||||
<a-button size="small" @click="handleClear">清空</a-button>
|
<a-button type="primary" size="small" @click="handleSubmit">{{ $t('confirm') }}</a-button>
|
||||||
</a-space>
|
<a-button size="small" @click="handleClear">{{ $t('clear') }}</a-button>
|
||||||
</div>
|
</a-space>
|
||||||
</template>
|
</div>
|
||||||
</a-popover>
|
</template>
|
||||||
<Expression
|
</a-popover>
|
||||||
v-else
|
<Expression
|
||||||
v-model="ruleList"
|
:needAddHere="needAddHere"
|
||||||
:canSearchPreferenceAttrList="canSearchPreferenceAttrList.filter((attr) => !attr.is_password)"
|
v-else
|
||||||
/>
|
v-model="ruleList"
|
||||||
</div>
|
:canSearchPreferenceAttrList="canSearchPreferenceAttrList.filter((attr) => !attr.is_password)"
|
||||||
</template>
|
/>
|
||||||
|
</div>
|
||||||
<script>
|
</template>
|
||||||
import { v4 as uuidv4 } from 'uuid'
|
|
||||||
import Expression from './expression.vue'
|
<script>
|
||||||
import { advancedExpList, compareTypeList } from './constants'
|
import { v4 as uuidv4 } from 'uuid'
|
||||||
|
import Expression from './expression.vue'
|
||||||
export default {
|
import { advancedExpList, compareTypeList } from './constants'
|
||||||
name: 'FilterComp',
|
|
||||||
components: { Expression },
|
export default {
|
||||||
props: {
|
name: 'FilterComp',
|
||||||
canSearchPreferenceAttrList: {
|
components: { Expression },
|
||||||
type: Array,
|
props: {
|
||||||
required: true,
|
canSearchPreferenceAttrList: {
|
||||||
default: () => [],
|
type: Array,
|
||||||
},
|
required: true,
|
||||||
expression: {
|
default: () => [],
|
||||||
type: String,
|
},
|
||||||
default: '',
|
expression: {
|
||||||
},
|
type: String,
|
||||||
regQ: {
|
default: '',
|
||||||
type: String,
|
},
|
||||||
default: '(?<=q=).+(?=&)|(?<=q=).+$',
|
regQ: {
|
||||||
},
|
type: String,
|
||||||
placement: {
|
default: '(?<=q=).+(?=&)|(?<=q=).+$',
|
||||||
type: String,
|
},
|
||||||
default: 'bottomRight',
|
placement: {
|
||||||
},
|
type: String,
|
||||||
isDropdown: {
|
default: 'bottomRight',
|
||||||
type: Boolean,
|
},
|
||||||
default: true,
|
isDropdown: {
|
||||||
},
|
type: Boolean,
|
||||||
},
|
default: true,
|
||||||
data() {
|
},
|
||||||
return {
|
needAddHere: {
|
||||||
advancedExpList,
|
type: Boolean,
|
||||||
compareTypeList,
|
default: false,
|
||||||
visible: false,
|
},
|
||||||
ruleList: [],
|
},
|
||||||
filterExp: '',
|
data() {
|
||||||
}
|
return {
|
||||||
},
|
advancedExpList,
|
||||||
|
compareTypeList,
|
||||||
methods: {
|
visible: false,
|
||||||
visibleChange(open, isInitOne = true) {
|
ruleList: [],
|
||||||
// isInitOne 初始化exp为空时,ruleList是否默认给一条
|
filterExp: '',
|
||||||
// const regQ = /(?<=q=).+(?=&)|(?<=q=).+$/g
|
}
|
||||||
const exp = this.expression.match(new RegExp(this.regQ, 'g'))
|
},
|
||||||
? this.expression.match(new RegExp(this.regQ, 'g'))[0]
|
|
||||||
: null
|
methods: {
|
||||||
if (open && exp) {
|
visibleChange(open, isInitOne = true) {
|
||||||
const expArray = exp.split(',').map((item) => {
|
// isInitOne 初始化exp为空时,ruleList是否默认给一条
|
||||||
let has_not = ''
|
// const regQ = /(?<=q=).+(?=&)|(?<=q=).+$/g
|
||||||
const key = item.split(':')[0]
|
const exp = this.expression.match(new RegExp(this.regQ, 'g'))
|
||||||
const val = item
|
? this.expression.match(new RegExp(this.regQ, 'g'))[0]
|
||||||
.split(':')
|
: null
|
||||||
.slice(1)
|
if (open && exp) {
|
||||||
.join(':')
|
const expArray = exp.split(',').map((item) => {
|
||||||
let type, property, exp, value, min, max, compareType
|
let has_not = ''
|
||||||
if (key.includes('-')) {
|
const key = item.split(':')[0]
|
||||||
type = 'or'
|
const val = item
|
||||||
if (key.includes('~')) {
|
.split(':')
|
||||||
property = key.substring(2)
|
.slice(1)
|
||||||
has_not = '~'
|
.join(':')
|
||||||
} else {
|
let type, property, exp, value, min, max, compareType
|
||||||
property = key.substring(1)
|
if (key.includes('-')) {
|
||||||
}
|
type = 'or'
|
||||||
} else {
|
if (key.includes('~')) {
|
||||||
type = 'and'
|
property = key.substring(2)
|
||||||
if (key.includes('~')) {
|
has_not = '~'
|
||||||
property = key.substring(1)
|
} else {
|
||||||
has_not = '~'
|
property = key.substring(1)
|
||||||
} else {
|
}
|
||||||
property = key
|
} else {
|
||||||
}
|
type = 'and'
|
||||||
}
|
if (key.includes('~')) {
|
||||||
|
property = key.substring(1)
|
||||||
const in_reg = /(?<=\().+(?=\))/g
|
has_not = '~'
|
||||||
const range_reg = /(?<=\[).+(?=\])/g
|
} else {
|
||||||
const compare_reg = /(?<=>=|<=|>(?!=)|<(?!=)).+/
|
property = key
|
||||||
if (val === '*') {
|
}
|
||||||
exp = has_not + 'value'
|
}
|
||||||
value = ''
|
|
||||||
} else if (in_reg.test(val)) {
|
const in_reg = /(?<=\().+(?=\))/g
|
||||||
exp = has_not + 'in'
|
const range_reg = /(?<=\[).+(?=\])/g
|
||||||
value = val.match(in_reg)[0]
|
const compare_reg = /(?<=>=|<=|>(?!=)|<(?!=)).+/
|
||||||
} else if (range_reg.test(val)) {
|
if (val === '*') {
|
||||||
exp = has_not + 'range'
|
exp = has_not + 'value'
|
||||||
value = val.match(range_reg)[0]
|
value = ''
|
||||||
min = value.split('_TO_')[0]
|
} else if (in_reg.test(val)) {
|
||||||
max = value.split('_TO_')[1]
|
exp = has_not + 'in'
|
||||||
} else if (compare_reg.test(val)) {
|
value = val.match(in_reg)[0]
|
||||||
exp = has_not + 'compare'
|
} else if (range_reg.test(val)) {
|
||||||
value = val.match(compare_reg)[0]
|
exp = has_not + 'range'
|
||||||
const _compareType = val.substring(0, val.match(compare_reg)['index'])
|
value = val.match(range_reg)[0]
|
||||||
const idx = compareTypeList.findIndex((item) => item.label === _compareType)
|
min = value.split('_TO_')[0]
|
||||||
compareType = compareTypeList[idx].value
|
max = value.split('_TO_')[1]
|
||||||
} else if (!val.includes('*')) {
|
} else if (compare_reg.test(val)) {
|
||||||
exp = has_not + 'is'
|
exp = has_not + 'compare'
|
||||||
value = val
|
value = val.match(compare_reg)[0]
|
||||||
} else {
|
const _compareType = val.substring(0, val.match(compare_reg)['index'])
|
||||||
const resList = [
|
const idx = compareTypeList.findIndex((item) => item.label === _compareType)
|
||||||
['contain', /(?<=\*).*(?=\*)/g],
|
compareType = compareTypeList[idx].value
|
||||||
['end_with', /(?<=\*).+/g],
|
} else if (!val.includes('*')) {
|
||||||
['start_with', /.+(?=\*)/g],
|
exp = has_not + 'is'
|
||||||
]
|
value = val
|
||||||
for (let i = 0; i < 3; i++) {
|
} else {
|
||||||
const reg = resList[i]
|
const resList = [
|
||||||
if (reg[1].test(val)) {
|
['contain', /(?<=\*).*(?=\*)/g],
|
||||||
exp = has_not + reg[0]
|
['end_with', /(?<=\*).+/g],
|
||||||
value = val.match(reg[1])[0]
|
['start_with', /.+(?=\*)/g],
|
||||||
break
|
]
|
||||||
}
|
for (let i = 0; i < 3; i++) {
|
||||||
}
|
const reg = resList[i]
|
||||||
}
|
if (reg[1].test(val)) {
|
||||||
return {
|
exp = has_not + reg[0]
|
||||||
id: uuidv4(),
|
value = val.match(reg[1])[0]
|
||||||
type,
|
break
|
||||||
property,
|
}
|
||||||
exp,
|
}
|
||||||
value,
|
}
|
||||||
min,
|
return {
|
||||||
max,
|
id: uuidv4(),
|
||||||
compareType,
|
type,
|
||||||
}
|
property,
|
||||||
})
|
exp,
|
||||||
this.ruleList = [...expArray]
|
value,
|
||||||
} else if (open) {
|
min,
|
||||||
const _canSearchPreferenceAttrList = this.canSearchPreferenceAttrList.filter((attr) => !attr.is_password)
|
max,
|
||||||
this.ruleList = isInitOne
|
compareType,
|
||||||
? [
|
}
|
||||||
{
|
})
|
||||||
id: uuidv4(),
|
this.ruleList = [...expArray]
|
||||||
type: 'and',
|
} else if (open) {
|
||||||
property:
|
const _canSearchPreferenceAttrList = this.canSearchPreferenceAttrList.filter((attr) => !attr.is_password)
|
||||||
_canSearchPreferenceAttrList && _canSearchPreferenceAttrList.length
|
this.ruleList = isInitOne
|
||||||
? _canSearchPreferenceAttrList[0].name
|
? [
|
||||||
: undefined,
|
{
|
||||||
exp: 'is',
|
id: uuidv4(),
|
||||||
value: null,
|
type: 'and',
|
||||||
},
|
property:
|
||||||
]
|
_canSearchPreferenceAttrList && _canSearchPreferenceAttrList.length
|
||||||
: []
|
? _canSearchPreferenceAttrList[0].name
|
||||||
}
|
: undefined,
|
||||||
},
|
exp: 'is',
|
||||||
handleClear() {
|
value: null,
|
||||||
this.ruleList = [
|
},
|
||||||
{
|
]
|
||||||
id: uuidv4(),
|
: []
|
||||||
type: 'and',
|
}
|
||||||
property: this.canSearchPreferenceAttrList[0].name,
|
},
|
||||||
exp: 'is',
|
handleClear() {
|
||||||
value: null,
|
this.ruleList = [
|
||||||
},
|
{
|
||||||
]
|
id: uuidv4(),
|
||||||
this.filterExp = ''
|
type: 'and',
|
||||||
this.visible = false
|
property: this.canSearchPreferenceAttrList[0].name,
|
||||||
this.$emit('setExpFromFilter', this.filterExp)
|
exp: 'is',
|
||||||
},
|
value: null,
|
||||||
handleSubmit() {
|
},
|
||||||
if (this.ruleList && this.ruleList.length) {
|
]
|
||||||
this.ruleList[0].type = 'and' // 增删后,以防万一第一个不是and
|
this.filterExp = ''
|
||||||
this.filterExp = ''
|
this.visible = false
|
||||||
const expList = this.ruleList.map((rule) => {
|
this.$emit('setExpFromFilter', this.filterExp)
|
||||||
let singleRuleExp = ''
|
},
|
||||||
let _exp = rule.exp
|
handleSubmit() {
|
||||||
if (rule.type === 'or') {
|
if (this.ruleList && this.ruleList.length) {
|
||||||
singleRuleExp += '-'
|
this.ruleList[0].type = 'and' // 增删后,以防万一第一个不是and
|
||||||
}
|
this.filterExp = ''
|
||||||
if (rule.exp.includes('~')) {
|
const expList = this.ruleList.map((rule) => {
|
||||||
singleRuleExp += '~'
|
let singleRuleExp = ''
|
||||||
_exp = rule.exp.split('~')[1]
|
let _exp = rule.exp
|
||||||
}
|
if (rule.type === 'or') {
|
||||||
singleRuleExp += `${rule.property}:`
|
singleRuleExp += '-'
|
||||||
if (_exp === 'is') {
|
}
|
||||||
singleRuleExp += `${rule.value ?? ''}`
|
if (rule.exp.includes('~')) {
|
||||||
}
|
singleRuleExp += '~'
|
||||||
if (_exp === 'contain') {
|
_exp = rule.exp.split('~')[1]
|
||||||
singleRuleExp += `*${rule.value ?? ''}*`
|
}
|
||||||
}
|
singleRuleExp += `${rule.property}:`
|
||||||
if (_exp === 'start_with') {
|
if (_exp === 'is') {
|
||||||
singleRuleExp += `${rule.value ?? ''}*`
|
singleRuleExp += `${rule.value ?? ''}`
|
||||||
}
|
}
|
||||||
if (_exp === 'end_with') {
|
if (_exp === 'contain') {
|
||||||
singleRuleExp += `*${rule.value ?? ''}`
|
singleRuleExp += `*${rule.value ?? ''}*`
|
||||||
}
|
}
|
||||||
if (_exp === 'value') {
|
if (_exp === 'start_with') {
|
||||||
singleRuleExp += `*`
|
singleRuleExp += `${rule.value ?? ''}*`
|
||||||
}
|
}
|
||||||
if (_exp === 'in') {
|
if (_exp === 'end_with') {
|
||||||
singleRuleExp += `(${rule.value ?? ''})`
|
singleRuleExp += `*${rule.value ?? ''}`
|
||||||
}
|
}
|
||||||
if (_exp === 'range') {
|
if (_exp === 'value') {
|
||||||
singleRuleExp += `[${rule.min}_TO_${rule.max}]`
|
singleRuleExp += `*`
|
||||||
}
|
}
|
||||||
if (_exp === 'compare') {
|
if (_exp === 'in') {
|
||||||
const idx = compareTypeList.findIndex((item) => item.value === rule.compareType)
|
singleRuleExp += `(${rule.value ?? ''})`
|
||||||
singleRuleExp += `${compareTypeList[idx].label}${rule.value ?? ''}`
|
}
|
||||||
}
|
if (_exp === 'range') {
|
||||||
return singleRuleExp
|
singleRuleExp += `[${rule.min}_TO_${rule.max}]`
|
||||||
})
|
}
|
||||||
this.filterExp = expList.join(',')
|
if (_exp === 'compare') {
|
||||||
this.$emit('setExpFromFilter', this.filterExp)
|
const idx = compareTypeList.findIndex((item) => item.value === rule.compareType)
|
||||||
} else {
|
singleRuleExp += `${compareTypeList[idx].label}${rule.value ?? ''}`
|
||||||
this.$emit('setExpFromFilter', '')
|
}
|
||||||
}
|
return singleRuleExp
|
||||||
this.visible = false
|
})
|
||||||
},
|
this.filterExp = expList.join(',')
|
||||||
},
|
this.$emit('setExpFromFilter', this.filterExp)
|
||||||
}
|
} else {
|
||||||
</script>
|
this.$emit('setExpFromFilter', '')
|
||||||
|
}
|
||||||
<style lang="less" scoped>
|
this.visible = false
|
||||||
.table-filter {
|
},
|
||||||
.table-filter-add {
|
},
|
||||||
margin-top: 10px;
|
}
|
||||||
& > a {
|
</script>
|
||||||
padding: 2px 8px;
|
|
||||||
&:hover {
|
<style lang="less" scoped>
|
||||||
background-color: #f0faff;
|
.table-filter {
|
||||||
border-radius: 5px;
|
.table-filter-add {
|
||||||
}
|
margin-top: 10px;
|
||||||
}
|
& > a {
|
||||||
}
|
padding: 2px 8px;
|
||||||
.table-filter-extra-icon {
|
&:hover {
|
||||||
padding: 0px 2px;
|
background-color: #f0faff;
|
||||||
&:hover {
|
border-radius: 5px;
|
||||||
display: inline-block;
|
}
|
||||||
border-radius: 5px;
|
}
|
||||||
background-color: #f0faff;
|
}
|
||||||
}
|
.table-filter-extra-icon {
|
||||||
}
|
padding: 0px 2px;
|
||||||
}
|
&:hover {
|
||||||
</style>
|
display: inline-block;
|
||||||
|
border-radius: 5px;
|
||||||
<style lang="less">
|
background-color: #f0faff;
|
||||||
.table-filter-extra-operation {
|
}
|
||||||
.ant-popover-inner-content {
|
}
|
||||||
padding: 3px 4px;
|
}
|
||||||
.operation {
|
</style>
|
||||||
cursor: pointer;
|
|
||||||
width: 90px;
|
<style lang="less">
|
||||||
height: 30px;
|
.table-filter-extra-operation {
|
||||||
line-height: 30px;
|
.ant-popover-inner-content {
|
||||||
padding: 3px 4px;
|
padding: 3px 4px;
|
||||||
border-radius: 5px;
|
.operation {
|
||||||
transition: all 0.3s;
|
cursor: pointer;
|
||||||
&:hover {
|
width: 90px;
|
||||||
background-color: #f0faff;
|
height: 30px;
|
||||||
}
|
line-height: 30px;
|
||||||
> .anticon {
|
padding: 3px 4px;
|
||||||
margin-right: 10px;
|
border-radius: 5px;
|
||||||
}
|
transition: all 0.3s;
|
||||||
}
|
&:hover {
|
||||||
}
|
background-color: #f0faff;
|
||||||
}
|
}
|
||||||
</style>
|
> .anticon {
|
||||||
|
margin-right: 10px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
|
@ -1,8 +1,10 @@
|
||||||
export const iconTypeList = [
|
import i18n from '@/lang'
|
||||||
|
|
||||||
|
export const iconTypeList = () => [
|
||||||
// { value: '0', label: '常用' },
|
// { value: '0', label: '常用' },
|
||||||
{ value: '1', label: '线性' },
|
{ value: '1', label: i18n.t('customIconSelect.outlined') },
|
||||||
{ value: '2', label: '实底' },
|
{ value: '2', label: i18n.t('customIconSelect.filled') },
|
||||||
{ value: '3', label: '多色' }
|
{ value: '3', label: i18n.t('customIconSelect.multicolor') }
|
||||||
]
|
]
|
||||||
|
|
||||||
export const commonIconList = ['changyong-ubuntu',
|
export const commonIconList = ['changyong-ubuntu',
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
{{ item.label }}
|
{{ item.label }}
|
||||||
</div>
|
</div>
|
||||||
<div :class="`${currentIconType === '4' ? 'selected' : ''}`" @click="handleChangeIconType('4')">
|
<div :class="`${currentIconType === '4' ? 'selected' : ''}`" @click="handleChangeIconType('4')">
|
||||||
自定义
|
{{ this.$t('customIconSelect.custom') }}
|
||||||
</div>
|
</div>
|
||||||
<a-upload
|
<a-upload
|
||||||
slot="description"
|
slot="description"
|
||||||
|
@ -26,7 +26,7 @@
|
||||||
accept=".svg,.png,.jpg,.jpeg"
|
accept=".svg,.png,.jpg,.jpeg"
|
||||||
v-if="currentIconType === '4'"
|
v-if="currentIconType === '4'"
|
||||||
>
|
>
|
||||||
<a-button icon="plus" size="small" type="primary">添加</a-button>
|
<a-button icon="plus" size="small" type="primary">{{ $t('add') }}</a-button>
|
||||||
</a-upload>
|
</a-upload>
|
||||||
</div>
|
</div>
|
||||||
<div class="custom-icon-select-popover-content">
|
<div class="custom-icon-select-popover-content">
|
||||||
|
@ -55,11 +55,11 @@
|
||||||
@click="clickCustomIcon(icon)"
|
@click="clickCustomIcon(icon)"
|
||||||
>
|
>
|
||||||
<div class="custom-icon-select-popover-content-img-box">
|
<div class="custom-icon-select-popover-content-img-box">
|
||||||
<img :src="`/api/common-setting/v1/file/${icon.data.url}`" />
|
<img v-if="icon.data && icon.data.url" :src="`/api/common-setting/v1/file/${icon.data.url}`" />
|
||||||
<a-popconfirm
|
<a-popconfirm
|
||||||
overlayClassName="custom-icon-select-confirm-popover"
|
overlayClassName="custom-icon-select-confirm-popover"
|
||||||
:getPopupContainer="(trigger) => trigger.parentNode"
|
:getPopupContainer="(trigger) => trigger.parentNode"
|
||||||
title="确认删除?"
|
:title="$t('confirmDelete')"
|
||||||
@confirm="(e) => deleteIcon(e, icon)"
|
@confirm="(e) => deleteIcon(e, icon)"
|
||||||
@cancel="
|
@cancel="
|
||||||
(e) => {
|
(e) => {
|
||||||
|
@ -102,27 +102,27 @@
|
||||||
</template>
|
</template>
|
||||||
<a-form class="custom-icon-select-form" :form="form" v-show="currentIconType === '4' && formVisible">
|
<a-form class="custom-icon-select-form" :form="form" v-show="currentIconType === '4' && formVisible">
|
||||||
<a-form-item
|
<a-form-item
|
||||||
label="名称"
|
:label="$t('name')"
|
||||||
:labelCol="{ span: 4 }"
|
:labelCol="{ span: 4 }"
|
||||||
:wrapperCol="{ span: 16 }"
|
:wrapperCol="{ span: 16 }"
|
||||||
><a-input
|
><a-input
|
||||||
v-decorator="['name', { rules: [{ required: true, message: '请输入名称' }] }]"
|
v-decorator="['name', { rules: [{ required: true, message: $t('placeholder1') }] }]"
|
||||||
/></a-form-item>
|
/></a-form-item>
|
||||||
<a-form-item label="预览" :labelCol="{ span: 4 }">
|
<a-form-item :label="$t('customIconSelect.preview')" :labelCol="{ span: 4 }">
|
||||||
<div class="custom-icon-select-form-img">
|
<div class="custom-icon-select-form-img">
|
||||||
<img :src="formImg" />
|
<img :src="formImg" />
|
||||||
</div>
|
</div>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-form-item label=" " :colon="false" :labelCol="{ span: 16 }">
|
<a-form-item label=" " :colon="false" :labelCol="{ span: 16 }">
|
||||||
<a-space>
|
<a-space>
|
||||||
<a-button size="small" @click="handleCancel">取消</a-button>
|
<a-button size="small" @click="handleCancel">{{ $t('cancel') }}</a-button>
|
||||||
<a-button size="small" type="primary" @click="handleOk">确定</a-button>
|
<a-button size="small" type="primary" @click="handleOk">{{ $t('confirm') }}</a-button>
|
||||||
</a-space>
|
</a-space>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
</a-form>
|
</a-form>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="custom-icon-select-block" id="custom-icon-select-block" @click="showSelect">
|
<div class="custom-icon-select-block" :id="`custom-icon-select-block-${uuid}`" @click="showSelect">
|
||||||
<img v-if="value.id && value.url" :src="`/api/common-setting/v1/file/${value.url}`" />
|
<img v-if="value.id && value.url" :src="`/api/common-setting/v1/file/${value.url}`" />
|
||||||
<ops-icon
|
<ops-icon
|
||||||
v-else
|
v-else
|
||||||
|
@ -134,6 +134,7 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
import { v4 as uuidv4 } from 'uuid'
|
||||||
import { ColorPicker } from 'element-ui'
|
import { ColorPicker } from 'element-ui'
|
||||||
import {
|
import {
|
||||||
iconTypeList,
|
iconTypeList,
|
||||||
|
@ -166,7 +167,6 @@ export default {
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
form: this.$form.createForm(this),
|
form: this.$form.createForm(this),
|
||||||
iconTypeList,
|
|
||||||
commonIconList,
|
commonIconList,
|
||||||
linearIconList,
|
linearIconList,
|
||||||
fillIconList,
|
fillIconList,
|
||||||
|
@ -177,6 +177,7 @@ export default {
|
||||||
formVisible: false,
|
formVisible: false,
|
||||||
formImg: null,
|
formImg: null,
|
||||||
file: null,
|
file: null,
|
||||||
|
uuid: uuidv4(),
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
@ -200,6 +201,9 @@ export default {
|
||||||
const splitFileName = this.file.name.split('.')
|
const splitFileName = this.file.name.split('.')
|
||||||
return splitFileName.splice(0, splitFileName.length - 1).join('')
|
return splitFileName.splice(0, splitFileName.length - 1).join('')
|
||||||
},
|
},
|
||||||
|
iconTypeList() {
|
||||||
|
return iconTypeList()
|
||||||
|
},
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
document.addEventListener('click', this.eventListener)
|
document.addEventListener('click', this.eventListener)
|
||||||
|
@ -217,7 +221,7 @@ export default {
|
||||||
eventListener(e) {
|
eventListener(e) {
|
||||||
if (this.visible) {
|
if (this.visible) {
|
||||||
const dom = document.getElementById(`custom-icon-select-popover`)
|
const dom = document.getElementById(`custom-icon-select-popover`)
|
||||||
const dom_icon = document.getElementById(`custom-icon-select-block`)
|
const dom_icon = document.getElementById(`custom-icon-select-block-${this.uuid}`)
|
||||||
e.stopPropagation()
|
e.stopPropagation()
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
if (dom) {
|
if (dom) {
|
||||||
|
@ -249,12 +253,11 @@ export default {
|
||||||
color: '',
|
color: '',
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
this.$emit('change', { name: icon.data.name, id: icon.id, url: icon.data.url })
|
this.$emit('change', { name: icon.data.name, id: icon.id, url: icon?.data?.url })
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
showSelect() {
|
showSelect() {
|
||||||
this.visible = true
|
this.visible = true
|
||||||
console.log(this.value)
|
|
||||||
if (!this.value.name) {
|
if (!this.value.name) {
|
||||||
this.currentIconType = '3'
|
this.currentIconType = '3'
|
||||||
return
|
return
|
||||||
|
@ -278,7 +281,7 @@ export default {
|
||||||
beforeUpload(file) {
|
beforeUpload(file) {
|
||||||
const isLt2M = file.size / 1024 / 1024 < 2
|
const isLt2M = file.size / 1024 / 1024 < 2
|
||||||
if (!isLt2M) {
|
if (!isLt2M) {
|
||||||
this.$message.error('图片大小不可超过2MB!')
|
this.$message.error(this.$t('customIconSelect.sizeLimit'))
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -306,7 +309,7 @@ export default {
|
||||||
this.form.validateFields((err, values) => {
|
this.form.validateFields((err, values) => {
|
||||||
if (!err) {
|
if (!err) {
|
||||||
addFileData('ops-custom-icon', { data: { name: values.name, url: res.file_name } }).then(() => {
|
addFileData('ops-custom-icon', { data: { name: values.name, url: res.file_name } }).then(() => {
|
||||||
this.$message.success('上传成功!')
|
this.$message.success(this.$t('uploadSuccess'))
|
||||||
this.handleCancel()
|
this.handleCancel()
|
||||||
this.getFileData()
|
this.getFileData()
|
||||||
})
|
})
|
||||||
|
@ -318,7 +321,7 @@ export default {
|
||||||
e.stopPropagation()
|
e.stopPropagation()
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
deleteFileData('ops-custom-icon', icon.id).then(() => {
|
deleteFileData('ops-custom-icon', icon.id).then(() => {
|
||||||
this.$message.success('删除成功!')
|
this.$message.success(this.$t('deleteSuccess'))
|
||||||
this.handleCancel()
|
this.handleCancel()
|
||||||
this.getFileData()
|
this.getFileData()
|
||||||
})
|
})
|
||||||
|
|
|
@ -6,17 +6,17 @@
|
||||||
:flat="true"
|
:flat="true"
|
||||||
:multiple="true"
|
:multiple="true"
|
||||||
:options="employeeTreeSelectOption"
|
:options="employeeTreeSelectOption"
|
||||||
placeholder="请输入搜索内容"
|
:placeholder="$t('placeholderSearch')"
|
||||||
v-model="treeValue"
|
v-model="treeValue"
|
||||||
:max-height="height - 50"
|
:max-height="height - 50"
|
||||||
noChildrenText="空"
|
noChildrenText="空"
|
||||||
noOptionsText="空"
|
noOptionsText="空"
|
||||||
:clearable="false"
|
:clearable="false"
|
||||||
:always-open="true"
|
:always-open="true"
|
||||||
:default-expand-level="1"
|
:default-expand-level="showInternship ? 0 : 1"
|
||||||
:class="{ 'employee-transfer': true, 'employee-transfer-has-input': !!inputValue }"
|
:class="{ 'employee-transfer': true, 'employee-transfer-has-input': !!inputValue }"
|
||||||
@search-change="changeInputValue"
|
@search-change="changeInputValue"
|
||||||
noResultsText="暂无数据"
|
:noResultsText="$t('noData')"
|
||||||
openDirection="below"
|
openDirection="below"
|
||||||
>
|
>
|
||||||
</treeselect>
|
</treeselect>
|
||||||
|
@ -85,6 +85,10 @@ export default {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: false,
|
default: false,
|
||||||
},
|
},
|
||||||
|
showInternship: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
|
@ -99,13 +103,22 @@ export default {
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
employeeTreeSelectOption() {
|
employeeTreeSelectOption() {
|
||||||
return formatOption(
|
const formatOptions = formatOption(
|
||||||
this.allTreeDepAndEmp,
|
this.allTreeDepAndEmp,
|
||||||
2,
|
2,
|
||||||
this.isDisabledAllCompany,
|
this.isDisabledAllCompany,
|
||||||
this.uniqueKey || 'department_id',
|
this.uniqueKey || 'department_id',
|
||||||
this.uniqueKey || 'employee_id'
|
this.uniqueKey || 'employee_id'
|
||||||
)
|
)
|
||||||
|
if (this.showInternship) {
|
||||||
|
formatOptions.push(
|
||||||
|
...[
|
||||||
|
{ id: -2, label: '全职' },
|
||||||
|
{ id: -3, label: '实习生' },
|
||||||
|
]
|
||||||
|
)
|
||||||
|
}
|
||||||
|
return formatOptions
|
||||||
},
|
},
|
||||||
allTreeDepAndEmp() {
|
allTreeDepAndEmp() {
|
||||||
if (this.getDataBySelf) {
|
if (this.getDataBySelf) {
|
||||||
|
@ -148,11 +161,15 @@ export default {
|
||||||
const department = []
|
const department = []
|
||||||
const user = []
|
const user = []
|
||||||
this.rightData.forEach((item) => {
|
this.rightData.forEach((item) => {
|
||||||
const _split = item.split('-')
|
if (item === -2 || item === -3) {
|
||||||
if (_split[0] === 'department') {
|
department.push(item)
|
||||||
department.push(Number(_split[1]))
|
|
||||||
} else {
|
} else {
|
||||||
user.push(Number(_split[1]))
|
const _split = item.split('-')
|
||||||
|
if (_split[0] === 'department') {
|
||||||
|
department.push(Number(_split[1]))
|
||||||
|
} else {
|
||||||
|
user.push(Number(_split[1]))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
const _idx = department.findIndex((item) => item === 0)
|
const _idx = department.findIndex((item) => item === 0)
|
||||||
|
@ -191,6 +208,12 @@ export default {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
getLabel(id) {
|
getLabel(id) {
|
||||||
|
if (id === -2) {
|
||||||
|
return '全职'
|
||||||
|
}
|
||||||
|
if (id === -3) {
|
||||||
|
return '实习生'
|
||||||
|
}
|
||||||
const _split = id.split('-')
|
const _split = id.split('-')
|
||||||
const type = _split[0]
|
const type = _split[0]
|
||||||
const _id = Number(_split[1])
|
const _id = Number(_split[1])
|
||||||
|
|
|
@ -161,6 +161,9 @@ export default {
|
||||||
}
|
}
|
||||||
return null
|
return null
|
||||||
},
|
},
|
||||||
|
renderI18n(title) {
|
||||||
|
return this.$t(`${title}`)
|
||||||
|
},
|
||||||
renderMenuItem(menu) {
|
renderMenuItem(menu) {
|
||||||
const isShowDot = menu.path.substr(0, 22) === '/cmdb/instances/types/'
|
const isShowDot = menu.path.substr(0, 22) === '/cmdb/instances/types/'
|
||||||
const isShowGrant = menu.path.substr(0, 20) === '/cmdb/relationviews/'
|
const isShowGrant = menu.path.substr(0, 20) === '/cmdb/relationviews/'
|
||||||
|
@ -183,7 +186,7 @@ export default {
|
||||||
<tag {...{ props, attrs }}>
|
<tag {...{ props, attrs }}>
|
||||||
{this.renderIcon({ icon: menu.meta.icon, customIcon: menu.meta.customIcon, name: menu.meta.name, typeId: menu.meta.typeId, routeName: menu.name, selectedIcon: menu.meta.selectedIcon, })}
|
{this.renderIcon({ icon: menu.meta.icon, customIcon: menu.meta.customIcon, name: menu.meta.name, typeId: menu.meta.typeId, routeName: menu.name, selectedIcon: menu.meta.selectedIcon, })}
|
||||||
<span>
|
<span>
|
||||||
<span class={menu.meta.title.length > 10 ? 'scroll' : ''}>{menu.meta.title}</span>
|
<span class={this.renderI18n(menu.meta.title).length > 10 ? 'scroll' : ''}>{this.renderI18n(menu.meta.title)}</span>
|
||||||
{isShowDot &&
|
{isShowDot &&
|
||||||
<a-popover
|
<a-popover
|
||||||
overlayClassName="custom-menu-extra-submenu"
|
overlayClassName="custom-menu-extra-submenu"
|
||||||
|
@ -217,7 +220,7 @@ export default {
|
||||||
<SubMenu {...{ key: menu.path }}>
|
<SubMenu {...{ key: menu.path }}>
|
||||||
<span slot="title">
|
<span slot="title">
|
||||||
{this.renderIcon({ icon: menu.meta.icon, selectedIcon: menu.meta.selectedIcon, routeName: menu.name })}
|
{this.renderIcon({ icon: menu.meta.icon, selectedIcon: menu.meta.selectedIcon, routeName: menu.name })}
|
||||||
<span>{menu.meta.title}</span>
|
<span>{this.renderI18n(menu.meta.title)}</span>
|
||||||
</span>
|
</span>
|
||||||
{itemArr}
|
{itemArr}
|
||||||
</SubMenu>
|
</SubMenu>
|
||||||
|
|
|
@ -3,9 +3,9 @@
|
||||||
<slot></slot>
|
<slot></slot>
|
||||||
<template #empty>
|
<template #empty>
|
||||||
<slot name="empty">
|
<slot name="empty">
|
||||||
<div>
|
<div :style="{ paddingTop: '10px' }">
|
||||||
<img :style="{ width: '100px' }" :src="require('@/assets/data_empty.png')" />
|
<img :style="{ width: '100px', height: '90px' }" :src="require('@/assets/data_empty.png')" />
|
||||||
<div>暂无数据</div>
|
<div>{{ $t('noData') }}</div>
|
||||||
</div>
|
</div>
|
||||||
</slot>
|
</slot>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -3,12 +3,12 @@
|
||||||
<a-switch
|
<a-switch
|
||||||
class="role-transfer-switch"
|
class="role-transfer-switch"
|
||||||
v-model="isUserRole"
|
v-model="isUserRole"
|
||||||
checked-children="用户"
|
:checked-children="$t('user')"
|
||||||
un-checked-children="虚拟"
|
:un-checked-children="$t('visual')"
|
||||||
@change="loadRoles"
|
@change="loadRoles"
|
||||||
/>
|
/>
|
||||||
<div class="role-transfer-left">
|
<div class="role-transfer-left">
|
||||||
<a-input placeholder="请输入搜索内容" v-model="searchValue" />
|
<a-input :placeholder="$t('placeholderSearch')" v-model="searchValue" />
|
||||||
<div v-for="item in filterAllRoles" :key="item.id" @click="handleSelectedLeft(item.id)">
|
<div v-for="item in filterAllRoles" :key="item.id" @click="handleSelectedLeft(item.id)">
|
||||||
<a-checkbox :checked="selectedLeft.includes(item.id)" />
|
<a-checkbox :checked="selectedLeft.includes(item.id)" />
|
||||||
<div :title="item.name" class="role-transfer-left-role">{{ item.name }}</div>
|
<div :title="item.name" class="role-transfer-left-role">{{ item.name }}</div>
|
||||||
|
|
|
@ -10,9 +10,10 @@
|
||||||
>
|
>
|
||||||
<a-icon type="setting" />
|
<a-icon type="setting" />
|
||||||
</span>
|
</span>
|
||||||
|
<span class="locale" @click="changeLang">{{ locale === 'zh' ? 'English' : '中文' }}</span>
|
||||||
<a-popover
|
<a-popover
|
||||||
trigger="click"
|
trigger="click"
|
||||||
:overlayStyle="{ width: '120px' }"
|
:overlayStyle="{ width: '150px' }"
|
||||||
placement="bottomRight"
|
placement="bottomRight"
|
||||||
overlayClassName="custom-user"
|
overlayClassName="custom-user"
|
||||||
>
|
>
|
||||||
|
@ -20,12 +21,12 @@
|
||||||
<router-link :to="{ name: 'setting_person' }" :style="{ color: '#000000a6' }">
|
<router-link :to="{ name: 'setting_person' }" :style="{ color: '#000000a6' }">
|
||||||
<div class="custom-user-item">
|
<div class="custom-user-item">
|
||||||
<a-icon type="user" :style="{ marginRight: '10px' }" />
|
<a-icon type="user" :style="{ marginRight: '10px' }" />
|
||||||
<span>个人中心</span>
|
<span>{{ $t('topMenu.personalCenter') }}</span>
|
||||||
</div>
|
</div>
|
||||||
</router-link>
|
</router-link>
|
||||||
<div @click="handleLogout" class="custom-user-item">
|
<div @click="handleLogout" class="custom-user-item">
|
||||||
<a-icon type="logout" :style="{ marginRight: '10px' }" />
|
<a-icon type="logout" :style="{ marginRight: '10px' }" />
|
||||||
<span>退出登录</span>
|
<span>{{ $t('topMenu.logout') }}</span>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<span class="action ant-dropdown-link user-dropdown-menu">
|
<span class="action ant-dropdown-link user-dropdown-menu">
|
||||||
|
@ -44,8 +45,9 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
import { mapState, mapActions, mapGetters, mapMutations } from 'vuex'
|
||||||
import DocumentLink from './DocumentLink.vue'
|
import DocumentLink from './DocumentLink.vue'
|
||||||
import { mapState, mapActions, mapGetters } from 'vuex'
|
import { setDocumentTitle, domTitle } from '@/utils/domUtil'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'UserMenu',
|
name: 'UserMenu',
|
||||||
|
@ -53,21 +55,24 @@ export default {
|
||||||
DocumentLink,
|
DocumentLink,
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
...mapState(['user']),
|
...mapState(['user', 'locale']),
|
||||||
hasBackendPermission() {
|
hasBackendPermission() {
|
||||||
return this.user?.roles?.permissions.includes('acl_admin', 'backend_admin') || false
|
return this.user?.detailPermissions?.backend?.length
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
...mapActions(['Logout']),
|
...mapActions(['Logout']),
|
||||||
...mapGetters(['nickname', 'avatar']),
|
...mapGetters(['nickname', 'avatar']),
|
||||||
|
...mapMutations(['SET_LOCALE']),
|
||||||
handleLogout() {
|
handleLogout() {
|
||||||
const that = this
|
const that = this
|
||||||
|
|
||||||
this.$confirm({
|
this.$confirm({
|
||||||
title: '提示',
|
title: '提示',
|
||||||
content: '确认注销登录 ?',
|
content: '真的要注销登录吗 ?',
|
||||||
onOk() {
|
onOk() {
|
||||||
|
// localStorage.removeItem('ops_cityps_currentId')
|
||||||
|
localStorage.clear()
|
||||||
return that.Logout()
|
return that.Logout()
|
||||||
},
|
},
|
||||||
onCancel() {},
|
onCancel() {},
|
||||||
|
@ -76,9 +81,22 @@ export default {
|
||||||
handleClick() {
|
handleClick() {
|
||||||
this.$router.push('/setting')
|
this.$router.push('/setting')
|
||||||
},
|
},
|
||||||
|
changeLang() {
|
||||||
|
if (this.locale === 'zh') {
|
||||||
|
this.SET_LOCALE('en')
|
||||||
|
this.$i18n.locale = 'en'
|
||||||
|
} else {
|
||||||
|
this.SET_LOCALE('zh')
|
||||||
|
this.$i18n.locale = 'zh'
|
||||||
|
}
|
||||||
|
this.$nextTick(() => {
|
||||||
|
setDocumentTitle(`${this.$t(this.$route.meta.title)} - ${domTitle}`)
|
||||||
|
})
|
||||||
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="less">
|
<style lang="less">
|
||||||
@import '~@/style/static.less';
|
@import '~@/style/static.less';
|
||||||
.color {
|
.color {
|
||||||
|
@ -98,4 +116,11 @@ export default {
|
||||||
color: #000000a6;
|
color: #000000a6;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.locale {
|
||||||
|
cursor: pointer;
|
||||||
|
&:hover {
|
||||||
|
color: #custom_colors[color_1];
|
||||||
|
}
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -38,11 +38,18 @@ import CardTitle from '@/components/CardTitle'
|
||||||
import ElementUI from 'element-ui'
|
import ElementUI from 'element-ui'
|
||||||
import Treeselect from '@riophae/vue-treeselect'
|
import Treeselect from '@riophae/vue-treeselect'
|
||||||
import OpsTable from '@/components/OpsTable'
|
import OpsTable from '@/components/OpsTable'
|
||||||
|
import VueI18n from 'vue-i18n'
|
||||||
|
import i18n from '@/lang'
|
||||||
|
|
||||||
Vue.config.productionTip = false
|
Vue.config.productionTip = false
|
||||||
Vue.prototype.$bus = EventBus
|
Vue.prototype.$bus = EventBus
|
||||||
|
|
||||||
|
VXETable.setup({
|
||||||
|
i18n: (key, args) => i18n.t(key, args)
|
||||||
|
})
|
||||||
Vue.use(VXETable)
|
Vue.use(VXETable)
|
||||||
VXETable.use(VXETablePluginExportXLSX)
|
VXETable.use(VXETablePluginExportXLSX)
|
||||||
|
Vue.use(VueI18n)
|
||||||
|
|
||||||
Vue.config.productionTip = false
|
Vue.config.productionTip = false
|
||||||
|
|
||||||
|
@ -75,4 +82,3 @@ Vue.component('CustomRadio', CustomRadio)
|
||||||
Vue.component('CardTitle', CardTitle)
|
Vue.component('CardTitle', CardTitle)
|
||||||
Vue.component('Treeselect', Treeselect)
|
Vue.component('Treeselect', Treeselect)
|
||||||
Vue.component('OpsTable', OpsTable)
|
Vue.component('OpsTable', OpsTable)
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,7 @@ import NProgress from 'nprogress'
|
||||||
import 'nprogress/nprogress.css'
|
import 'nprogress/nprogress.css'
|
||||||
import { setDocumentTitle, domTitle } from '@/utils/domUtil'
|
import { setDocumentTitle, domTitle } from '@/utils/domUtil'
|
||||||
import { ACCESS_TOKEN } from './store/global/mutation-types'
|
import { ACCESS_TOKEN } from './store/global/mutation-types'
|
||||||
|
import i18n from '@/lang'
|
||||||
|
|
||||||
NProgress.configure({ showSpinner: false })
|
NProgress.configure({ showSpinner: false })
|
||||||
|
|
||||||
|
@ -17,7 +18,7 @@ const whitePath = ['/user/login', '/user/logout', '/user/register', '/api/sso/lo
|
||||||
// 登录页面处理处理 是否使用单点登录
|
// 登录页面处理处理 是否使用单点登录
|
||||||
router.beforeEach(async (to, from, next) => {
|
router.beforeEach(async (to, from, next) => {
|
||||||
NProgress.start() // start progress bar
|
NProgress.start() // start progress bar
|
||||||
to.meta && (!!to.meta.title && setDocumentTitle(`${to.meta.title} - ${domTitle}`))
|
to.meta && (!!to.meta.title && setDocumentTitle(`${i18n.t(to.meta.title)} - ${domTitle}`))
|
||||||
|
|
||||||
const authed = store.state.authed
|
const authed = store.state.authed
|
||||||
const auth_type = localStorage.getItem('ops_auth_type')
|
const auth_type = localStorage.getItem('ops_auth_type')
|
||||||
|
|
|
@ -0,0 +1,140 @@
|
||||||
|
import cmdb_en from '@/modules/cmdb/lang/en.js'
|
||||||
|
import cs_en from '../views/setting/lang/en.js'
|
||||||
|
import acl_en from '@/modules/acl/lang/en.js'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
screen: 'Big Screen',
|
||||||
|
dashboard: 'Dashboard',
|
||||||
|
admin: 'Admin',
|
||||||
|
user: 'User',
|
||||||
|
role: 'Role',
|
||||||
|
operation: 'Operation',
|
||||||
|
login: 'Login',
|
||||||
|
refresh: 'Refresh',
|
||||||
|
cancel: 'Cancel',
|
||||||
|
confirm: 'Confirm',
|
||||||
|
create: 'Create',
|
||||||
|
edit: 'Edit',
|
||||||
|
deleting: 'Deleting',
|
||||||
|
deletingTip: 'Deleting, total of {total}, {successNum} succeeded, {errorNum} failed',
|
||||||
|
grant: 'Grant',
|
||||||
|
login_at: 'Login At',
|
||||||
|
logout_at: 'Logout At',
|
||||||
|
createSuccess: 'Create Success',
|
||||||
|
editSuccess: 'edit Success',
|
||||||
|
warning: 'Warning',
|
||||||
|
export: 'Export',
|
||||||
|
placeholderSearch: 'Please Search',
|
||||||
|
success: 'Success',
|
||||||
|
fail: 'Fail',
|
||||||
|
browser: 'Browser',
|
||||||
|
status: 'Status',
|
||||||
|
type: 'Type',
|
||||||
|
description: 'Description',
|
||||||
|
new: 'New',
|
||||||
|
add: 'Add',
|
||||||
|
define: 'Define',
|
||||||
|
update: 'Update',
|
||||||
|
clear: 'Clear',
|
||||||
|
delete: 'Delete',
|
||||||
|
copy: 'Copy',
|
||||||
|
created_at: 'Created At',
|
||||||
|
updated_at: 'Updated At',
|
||||||
|
placeholder1: 'Please Input',
|
||||||
|
placeholder2: 'Please Select',
|
||||||
|
confirmDelete: 'Confirm delete?',
|
||||||
|
confirmDelete2: 'Confirm delete [{name}]?',
|
||||||
|
query: 'Query',
|
||||||
|
search: 'Search',
|
||||||
|
hide: 'Hide',
|
||||||
|
expand: 'Expand',
|
||||||
|
save: 'Save',
|
||||||
|
submit: 'Submit',
|
||||||
|
upload: 'Import',
|
||||||
|
download: 'Export',
|
||||||
|
name: 'Name',
|
||||||
|
alias: 'Alias',
|
||||||
|
desc: 'Description',
|
||||||
|
other: 'Other',
|
||||||
|
icon: 'Icon',
|
||||||
|
addSuccess: 'Added successfully',
|
||||||
|
uploadSuccess: 'Import successfully',
|
||||||
|
saveSuccess: 'Save successfully',
|
||||||
|
copySuccess: 'Copy successfully',
|
||||||
|
updateSuccess: 'Updated successfully',
|
||||||
|
deleteSuccess: 'Deleted successfully',
|
||||||
|
operateSuccess: 'The operation was successful',
|
||||||
|
noPermission: 'No Permission',
|
||||||
|
noData: 'No Data',
|
||||||
|
seconds: 'Seconds',
|
||||||
|
createdAt: 'Created At',
|
||||||
|
updatedAt: 'Updated At',
|
||||||
|
deletedAt: 'Deleted At',
|
||||||
|
required: 'required',
|
||||||
|
email: 'Email',
|
||||||
|
wechat: 'Wechat',
|
||||||
|
dingding: 'DingTalk',
|
||||||
|
feishu: 'Feishu',
|
||||||
|
bot: 'Robot',
|
||||||
|
checkAll: 'Select All',
|
||||||
|
loading: 'Loading...',
|
||||||
|
view: 'View',
|
||||||
|
reset: 'Reset',
|
||||||
|
yes: 'Yes',
|
||||||
|
no: 'No',
|
||||||
|
all: 'All',
|
||||||
|
selectRows: 'Selected: {rows} items',
|
||||||
|
itemsPerPage: '/page',
|
||||||
|
'星期一': 'Monday',
|
||||||
|
'星期二': 'Tuesday',
|
||||||
|
'星期三': 'Wednesday',
|
||||||
|
'星期四': 'Thursday',
|
||||||
|
'星期五': 'Friday',
|
||||||
|
'星期六': 'Saturday',
|
||||||
|
'星期日': 'Sunday',
|
||||||
|
hour: 'hour',
|
||||||
|
'items/page': '{items} items/page',
|
||||||
|
max: 'Max',
|
||||||
|
min: 'Min',
|
||||||
|
visual: 'Visual',
|
||||||
|
pagination: {
|
||||||
|
total: '{range0}-{range1} of {total} items'
|
||||||
|
},
|
||||||
|
topMenu: {
|
||||||
|
personalCenter: 'Personal Center',
|
||||||
|
logout: 'logout',
|
||||||
|
},
|
||||||
|
cmdbFilterComp: {
|
||||||
|
conditionFilter: 'Conditional filtering',
|
||||||
|
and: 'and',
|
||||||
|
or: 'or',
|
||||||
|
is: 'equal',
|
||||||
|
'~is': 'not equal',
|
||||||
|
contain: 'contain',
|
||||||
|
'~contain': 'not contain',
|
||||||
|
start_with: 'start_with',
|
||||||
|
'~start_with': 'not start_with',
|
||||||
|
end_with: 'end_with',
|
||||||
|
'~end_with': 'not end_with',
|
||||||
|
'~value': 'null',
|
||||||
|
value: 'not null',
|
||||||
|
in: 'in',
|
||||||
|
'~in': 'not in',
|
||||||
|
range: 'range',
|
||||||
|
'~range': 'out of range',
|
||||||
|
compare: 'compare',
|
||||||
|
addHere: 'Add Here',
|
||||||
|
split: 'split by {separator}'
|
||||||
|
},
|
||||||
|
customIconSelect: {
|
||||||
|
outlined: 'Outlined',
|
||||||
|
filled: 'Filled',
|
||||||
|
multicolor: 'Multicolor',
|
||||||
|
custom: 'Custom',
|
||||||
|
preview: 'Preview',
|
||||||
|
sizeLimit: 'The image size cannot exceed 2MB!'
|
||||||
|
},
|
||||||
|
cmdb: cmdb_en,
|
||||||
|
cs: cs_en,
|
||||||
|
acl: acl_en,
|
||||||
|
}
|
|
@ -0,0 +1,18 @@
|
||||||
|
import VueI18n from 'vue-i18n'
|
||||||
|
import zh from './zh'
|
||||||
|
import en from './en'
|
||||||
|
import Vue from 'vue'
|
||||||
|
import zhCN from 'vxe-table/lib/locale/lang/zh-CN'
|
||||||
|
import enUS from 'vxe-table/lib/locale/lang/en-US'
|
||||||
|
|
||||||
|
Vue.use(VueI18n)
|
||||||
|
const i18n = new VueI18n({
|
||||||
|
locale: 'zh', // 初始化中文
|
||||||
|
messages: {
|
||||||
|
'zh': { ...zh, ...zhCN },
|
||||||
|
'en': { ...en, ...enUS },
|
||||||
|
},
|
||||||
|
silentTranslationWarn: true
|
||||||
|
})
|
||||||
|
|
||||||
|
export default i18n
|
|
@ -0,0 +1,140 @@
|
||||||
|
import cmdb_zh from '@/modules/cmdb/lang/zh.js'
|
||||||
|
import cs_zh from '../views/setting/lang/zh.js'
|
||||||
|
import acl_zh from '@/modules/acl/lang/zh.js'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
screen: '大屏',
|
||||||
|
dashboard: '仪表盘',
|
||||||
|
admin: '管理员',
|
||||||
|
user: '用户',
|
||||||
|
role: '角色',
|
||||||
|
operation: '操作',
|
||||||
|
login: '登录',
|
||||||
|
refresh: '刷新',
|
||||||
|
cancel: '取消',
|
||||||
|
confirm: '确定',
|
||||||
|
create: '创建',
|
||||||
|
edit: '编辑',
|
||||||
|
deleting: '正在删除',
|
||||||
|
deletingTip: '正在删除,共{total}个,成功{successNum}个,失败{errorNum}个',
|
||||||
|
grant: '授权',
|
||||||
|
login_at: '登录时间',
|
||||||
|
logout_at: '登出时间',
|
||||||
|
createSuccess: '创建成功',
|
||||||
|
editSuccess: '修改成功',
|
||||||
|
warning: '警告',
|
||||||
|
export: '导出',
|
||||||
|
placeholderSearch: '请查找',
|
||||||
|
success: '成功',
|
||||||
|
fail: '失败',
|
||||||
|
browser: '浏览器',
|
||||||
|
status: '状态',
|
||||||
|
type: '类型',
|
||||||
|
description: '描述',
|
||||||
|
new: '新增',
|
||||||
|
add: '添加',
|
||||||
|
define: '定义',
|
||||||
|
update: '修改',
|
||||||
|
clear: '清空',
|
||||||
|
delete: '删除',
|
||||||
|
copy: '复制',
|
||||||
|
created_at: '创建日期',
|
||||||
|
updated_at: '更新日期',
|
||||||
|
placeholder1: '请输入',
|
||||||
|
placeholder2: '请选择',
|
||||||
|
confirmDelete: '确认删除?',
|
||||||
|
confirmDelete2: '确认删除【{name}】?',
|
||||||
|
query: '查询',
|
||||||
|
search: '搜索',
|
||||||
|
hide: '隐藏',
|
||||||
|
expand: '展开',
|
||||||
|
save: '保存',
|
||||||
|
submit: '提交',
|
||||||
|
upload: '导入',
|
||||||
|
download: '导出',
|
||||||
|
name: '名称',
|
||||||
|
alias: '别名',
|
||||||
|
desc: '描述',
|
||||||
|
other: '其他',
|
||||||
|
icon: '图标',
|
||||||
|
addSuccess: '新增成功',
|
||||||
|
uploadSuccess: '导入成功',
|
||||||
|
saveSuccess: '保存成功',
|
||||||
|
copySuccess: '复制成功',
|
||||||
|
updateSuccess: '更新成功',
|
||||||
|
deleteSuccess: '删除成功',
|
||||||
|
operateSuccess: '操作成功',
|
||||||
|
noPermission: '权限不足',
|
||||||
|
noData: '暂无数据',
|
||||||
|
seconds: '秒',
|
||||||
|
createdAt: '创建时间',
|
||||||
|
updatedAt: '更新时间',
|
||||||
|
deletedAt: '删除时间',
|
||||||
|
required: '必须',
|
||||||
|
email: '邮件',
|
||||||
|
wechat: '企业微信',
|
||||||
|
dingding: '钉钉',
|
||||||
|
feishu: '飞书',
|
||||||
|
bot: '机器人',
|
||||||
|
checkAll: '全选',
|
||||||
|
loading: '加载中...',
|
||||||
|
view: '查看',
|
||||||
|
reset: '重置',
|
||||||
|
yes: '是',
|
||||||
|
no: '否',
|
||||||
|
all: '全部',
|
||||||
|
selectRows: '选取:{rows} 项',
|
||||||
|
itemsPerPage: '/页',
|
||||||
|
'星期一': '星期一',
|
||||||
|
'星期二': '星期二',
|
||||||
|
'星期三': '星期三',
|
||||||
|
'星期四': '星期四',
|
||||||
|
'星期五': '星期五',
|
||||||
|
'星期六': '星期六',
|
||||||
|
'星期日': '星期日',
|
||||||
|
hour: '小时',
|
||||||
|
'items/page': '{items} 条/页',
|
||||||
|
max: '最大值',
|
||||||
|
min: '最小值',
|
||||||
|
visual: '虚拟',
|
||||||
|
pagination: {
|
||||||
|
total: '当前展示 {range0}-{range1} 条数据, 共 {total} 条'
|
||||||
|
},
|
||||||
|
topMenu: {
|
||||||
|
personalCenter: '个人中心',
|
||||||
|
logout: '退出登录',
|
||||||
|
},
|
||||||
|
cmdbFilterComp: {
|
||||||
|
conditionFilter: '条件过滤',
|
||||||
|
and: '与',
|
||||||
|
or: '或',
|
||||||
|
is: '等于',
|
||||||
|
'~is': '不等于',
|
||||||
|
contain: '包含',
|
||||||
|
'~contain': '不包含',
|
||||||
|
start_with: '以...开始',
|
||||||
|
'~start_with': '不以...开始',
|
||||||
|
end_with: '以...结束',
|
||||||
|
'~end_with': '不以...结束',
|
||||||
|
'~value': '为空',
|
||||||
|
value: '不为空',
|
||||||
|
in: 'in查询',
|
||||||
|
'~in': '非in查询',
|
||||||
|
range: '范围',
|
||||||
|
'~range': '范围外',
|
||||||
|
compare: '比较',
|
||||||
|
addHere: '在此处添加',
|
||||||
|
split: '以 {separator} 分隔'
|
||||||
|
},
|
||||||
|
customIconSelect: {
|
||||||
|
outlined: '线框',
|
||||||
|
filled: '实底',
|
||||||
|
multicolor: '多色',
|
||||||
|
custom: '自定义',
|
||||||
|
preview: '预览',
|
||||||
|
sizeLimit: '图片大小不可超过2MB!'
|
||||||
|
},
|
||||||
|
cmdb: cmdb_zh,
|
||||||
|
cs: cs_zh,
|
||||||
|
acl: acl_zh,
|
||||||
|
}
|
|
@ -10,6 +10,7 @@ import './guard' // guard permission control
|
||||||
import './utils/filter' // global filter
|
import './utils/filter' // global filter
|
||||||
import Setting from './config/setting'
|
import Setting from './config/setting'
|
||||||
import { Icon } from 'ant-design-vue'
|
import { Icon } from 'ant-design-vue'
|
||||||
|
import i18n from './lang'
|
||||||
|
|
||||||
import iconFont from '../public/iconfont/iconfont'
|
import iconFont from '../public/iconfont/iconfont'
|
||||||
|
|
||||||
|
@ -22,6 +23,7 @@ async function start() {
|
||||||
const _vue = new Vue({
|
const _vue = new Vue({
|
||||||
router,
|
router,
|
||||||
store,
|
store,
|
||||||
|
i18n,
|
||||||
created: bootstrap,
|
created: bootstrap,
|
||||||
render: h => h(App)
|
render: h => h(App)
|
||||||
}).$mount('#app')
|
}).$mount('#app')
|
||||||
|
|
|
@ -0,0 +1,125 @@
|
||||||
|
const acl_en = {
|
||||||
|
date: 'Date',
|
||||||
|
operator: 'Operator',
|
||||||
|
resource: 'Resource',
|
||||||
|
resourceType: 'Resource Type',
|
||||||
|
addResourceType: 'Add Resource Type',
|
||||||
|
app: 'App',
|
||||||
|
operateTime: 'Operate Time',
|
||||||
|
permission: 'Permission',
|
||||||
|
permission_placeholder: 'please select permission',
|
||||||
|
permissionList: 'Permission List',
|
||||||
|
summaryPermissions: 'Summary of permissions',
|
||||||
|
source: 'Source',
|
||||||
|
username: 'Username',
|
||||||
|
username_placeholder: 'please input username',
|
||||||
|
userList: 'User List',
|
||||||
|
groupUser: 'Group User',
|
||||||
|
addUser: 'Add User',
|
||||||
|
subordinateUsers: 'Subordinate Users',
|
||||||
|
nickname: 'Nickname',
|
||||||
|
nickname_placeholder: 'please input nickname',
|
||||||
|
password: 'Password',
|
||||||
|
password_placeholder: 'please input password',
|
||||||
|
department: 'Department',
|
||||||
|
group: 'Group',
|
||||||
|
email: 'Email',
|
||||||
|
email_placeholder: 'please input email',
|
||||||
|
mobile: 'Mobile',
|
||||||
|
isBlock: 'Is Block',
|
||||||
|
block: 'Block',
|
||||||
|
joined_at: 'Joined At',
|
||||||
|
role: 'Role',
|
||||||
|
role_placeholder1: 'please input role',
|
||||||
|
role_placeholder2: 'please select role',
|
||||||
|
role_placeholder3: 'please select a role name, multiple choices are allowed',
|
||||||
|
allRole: 'All Roles',
|
||||||
|
visualRole: 'Virtual Role',
|
||||||
|
addVisualRole: 'Add Virtual Role',
|
||||||
|
inheritedFrom: 'Inherited from',
|
||||||
|
heir: 'Inherit Roles',
|
||||||
|
permissionChange: 'Permissions',
|
||||||
|
roleChange: 'Roles',
|
||||||
|
resourceChange: 'Resources',
|
||||||
|
resourceTypeChange: 'Resource Type',
|
||||||
|
trigger: 'Triggers',
|
||||||
|
triggerNameInput: 'Please enter trigger name',
|
||||||
|
triggerChange: 'Triggers',
|
||||||
|
roleManage: 'Roles',
|
||||||
|
userManage: 'Users',
|
||||||
|
appManage: 'Applications',
|
||||||
|
resourceManage: 'Resources',
|
||||||
|
history: 'Audits',
|
||||||
|
userSecret: 'Secrets',
|
||||||
|
none: 'none',
|
||||||
|
danger: 'Dangerous',
|
||||||
|
confirmDeleteApp: 'Are you sure you want to delete this app?',
|
||||||
|
revoke: 'Revoke',
|
||||||
|
convenient: 'Quick Grant',
|
||||||
|
group2: 'Group',
|
||||||
|
groupName: 'Group Name',
|
||||||
|
resourceName: 'Resource Name',
|
||||||
|
creator: 'Creator',
|
||||||
|
member: 'Members',
|
||||||
|
viewAuth: 'view Auth',
|
||||||
|
addTypeTips: 'There is no type information yet, please add the resource type first!',
|
||||||
|
addResource: 'Add Resource',
|
||||||
|
resourceList: 'Resource List',
|
||||||
|
confirmResetSecret: 'Are you sure you want to reset the user secrets?',
|
||||||
|
addTrigger: 'Add Trigger',
|
||||||
|
deleteTrigger: 'Delete Trigger',
|
||||||
|
applyTrigger: 'Apply Trigger',
|
||||||
|
cancelTrigger: 'Cancel Trigger',
|
||||||
|
enable: 'Enable',
|
||||||
|
disable: 'Disable',
|
||||||
|
viewMatchResult: 'View regular matching results',
|
||||||
|
confirmDeleteTrigger: 'Are you sure you want to delete this trigger?',
|
||||||
|
ruleApply: 'Apply',
|
||||||
|
triggerTip1: 'Are you sure you want to apply this trigger?',
|
||||||
|
triggerTip2: 'Cancel applying this trigger?',
|
||||||
|
appNameInput: 'Please enter an application name',
|
||||||
|
descInput: 'Please enter a description',
|
||||||
|
addApp: 'Add',
|
||||||
|
updateApp: 'Update',
|
||||||
|
cancel: 'Cancel',
|
||||||
|
typeName: 'Name',
|
||||||
|
typeNameInput: 'Please enter a type name',
|
||||||
|
resourceNameInput: 'Please enter resource name',
|
||||||
|
pressEnter: 'Press Enter to confirm filtering',
|
||||||
|
groupMember: 'Group Members:',
|
||||||
|
isGroup: 'Group?',
|
||||||
|
errorTips: 'Error message',
|
||||||
|
roleList: 'Role List',
|
||||||
|
virtual: 'Virtual',
|
||||||
|
resourceBatchTips: 'Please enter the resource name, separated by newlines',
|
||||||
|
memberManage: 'Members: ',
|
||||||
|
newResource: 'New Resource: ',
|
||||||
|
deleteResource: 'Delete Resource: ',
|
||||||
|
deleteResourceType: 'Delete Resource Type: ',
|
||||||
|
noChange: 'No change',
|
||||||
|
batchOperate: 'Batch Operations',
|
||||||
|
batchGrant: 'Batch Grant',
|
||||||
|
batchRevoke: 'Batch Revoke',
|
||||||
|
editPerm: 'Add authorization: ',
|
||||||
|
permInput: 'Please enter permission name',
|
||||||
|
resourceTypeName: 'Resource Type Name',
|
||||||
|
selectedParents: 'Optionally inherit roles',
|
||||||
|
isAppAdmin: 'is app admin',
|
||||||
|
addRole: 'Add Role',
|
||||||
|
roleRelation: 'Role Relation',
|
||||||
|
roleRelationAdd: 'Add Role Relation',
|
||||||
|
roleRelationDelete: 'Delete Role Relation',
|
||||||
|
role2: 'Role',
|
||||||
|
admin: 'Admin',
|
||||||
|
involvingRP: 'Involving resources and permissions',
|
||||||
|
startAt: 'Start Time',
|
||||||
|
endAt: 'End Time',
|
||||||
|
triggerTips1: 'Priority regular pattern (secondary wildcard)',
|
||||||
|
pleaseSelectType: 'Please select resource type',
|
||||||
|
apply: 'Apply',
|
||||||
|
mobileTips: 'Please enter the correct phone number',
|
||||||
|
remove: 'Remove',
|
||||||
|
deleteUserConfirm: 'Are you sure you want to remove this user?',
|
||||||
|
copyResource: 'Copy resource name'
|
||||||
|
}
|
||||||
|
export default acl_en
|
|
@ -0,0 +1,125 @@
|
||||||
|
const acl_zh = {
|
||||||
|
date: '日期',
|
||||||
|
operator: '操作员',
|
||||||
|
resource: '资源',
|
||||||
|
resourceType: '资源类型',
|
||||||
|
addResourceType: '新增资源类型',
|
||||||
|
app: '应用',
|
||||||
|
operateTime: '操作时间',
|
||||||
|
permission: '权限',
|
||||||
|
permission_placeholder: '请选择权限',
|
||||||
|
permissionList: '权限列表',
|
||||||
|
summaryPermissions: '权限汇总',
|
||||||
|
source: '来源',
|
||||||
|
username: '用户名',
|
||||||
|
username_placeholder: '请输入用户名',
|
||||||
|
userList: '用户列表',
|
||||||
|
groupUser: '组用户',
|
||||||
|
addUser: '新增用户',
|
||||||
|
subordinateUsers: '下属用户',
|
||||||
|
nickname: '中文名',
|
||||||
|
nickname_placeholder: '请输入中文名',
|
||||||
|
password: '密码',
|
||||||
|
password_placeholder: '请输入密码',
|
||||||
|
department: '部门',
|
||||||
|
group: '小组',
|
||||||
|
email: '邮箱',
|
||||||
|
email_placeholder: '请输入邮箱',
|
||||||
|
mobile: '手机号',
|
||||||
|
isBlock: '是否锁定',
|
||||||
|
block: '锁定',
|
||||||
|
joined_at: '加入时间',
|
||||||
|
role: '角色名',
|
||||||
|
role_placeholder1: '请输入角色名',
|
||||||
|
role_placeholder2: '请选择角色名称',
|
||||||
|
role_placeholder3: '请选择角色名称,可多选',
|
||||||
|
allRole: '所有角色',
|
||||||
|
visualRole: '虚拟角色',
|
||||||
|
addVisualRole: '新增虚拟角色',
|
||||||
|
inheritedFrom: '继承自',
|
||||||
|
heir: '继承者',
|
||||||
|
permissionChange: '权限变更',
|
||||||
|
roleChange: '角色变更',
|
||||||
|
resourceChange: '资源变更',
|
||||||
|
resourceTypeChange: '资源类型变更',
|
||||||
|
trigger: '触发器',
|
||||||
|
triggerNameInput: '请输入触发器名',
|
||||||
|
triggerChange: '触发器变更',
|
||||||
|
roleManage: '角色管理',
|
||||||
|
userManage: '用户管理',
|
||||||
|
appManage: '应用管理',
|
||||||
|
resourceManage: '资源管理',
|
||||||
|
history: '操作审计',
|
||||||
|
userSecret: '用户密钥',
|
||||||
|
none: '无',
|
||||||
|
danger: '危险操作',
|
||||||
|
confirmDeleteApp: '确定要删除该App吗?',
|
||||||
|
revoke: '权限回收',
|
||||||
|
convenient: '便捷授权',
|
||||||
|
group2: '组',
|
||||||
|
groupName: '资源组名',
|
||||||
|
resourceName: '资源名',
|
||||||
|
creator: '创建者',
|
||||||
|
member: '成员',
|
||||||
|
viewAuth: '查看授权',
|
||||||
|
addTypeTips: '暂无类型信息,请先添加资源类型!',
|
||||||
|
addResource: '新增资源',
|
||||||
|
resourceList: '资源列表',
|
||||||
|
confirmResetSecret: '确定重置用户密钥?',
|
||||||
|
addTrigger: '新增触发器',
|
||||||
|
deleteTrigger: '删除触发器',
|
||||||
|
applyTrigger: '应用触发器',
|
||||||
|
cancelTrigger: '取消触发器',
|
||||||
|
enable: '启用',
|
||||||
|
disable: '禁用',
|
||||||
|
viewMatchResult: '查看正则匹配结果',
|
||||||
|
confirmDeleteTrigger: '确认删除该触发器吗?',
|
||||||
|
ruleApply: '规则应用',
|
||||||
|
triggerTip1: '是否确定应用该触发器?',
|
||||||
|
triggerTip2: '是否取消应用该触发器?',
|
||||||
|
appNameInput: '请输入应用名称',
|
||||||
|
descInput: '请输入描述',
|
||||||
|
addApp: '创建应用',
|
||||||
|
updateApp: '更新应用',
|
||||||
|
cancel: '撤销',
|
||||||
|
typeName: '类型名',
|
||||||
|
typeNameInput: '请输入类型名',
|
||||||
|
resourceNameInput: '请输入资源名',
|
||||||
|
pressEnter: '按回车确认筛选',
|
||||||
|
groupMember: '组成员:',
|
||||||
|
isGroup: '是否组',
|
||||||
|
errorTips: '错误提示',
|
||||||
|
roleList: '角色列表',
|
||||||
|
virtual: '虚拟',
|
||||||
|
resourceBatchTips: '请输入资源名,换行分隔',
|
||||||
|
memberManage: '成员管理:',
|
||||||
|
newResource: '新建资源:',
|
||||||
|
deleteResource: '删除资源:',
|
||||||
|
deleteResourceType: '删除资源类型:',
|
||||||
|
noChange: '没有修改',
|
||||||
|
batchOperate: '批量操作',
|
||||||
|
batchGrant: '批量授权',
|
||||||
|
batchRevoke: '批量权限回收',
|
||||||
|
editPerm: '添加授权:',
|
||||||
|
permInput: '请输入权限名',
|
||||||
|
resourceTypeName: '资源类型名',
|
||||||
|
selectedParents: '可选择继承角色',
|
||||||
|
isAppAdmin: '是否应用管理员',
|
||||||
|
addRole: '新增角色',
|
||||||
|
roleRelation: '角色关系',
|
||||||
|
roleRelationAdd: '添加角色关系',
|
||||||
|
roleRelationDelete: '删除角色关系',
|
||||||
|
role2: '角色',
|
||||||
|
admin: '管理员',
|
||||||
|
involvingRP: '涉及资源及权限',
|
||||||
|
startAt: '开始时间',
|
||||||
|
endAt: '结束时间',
|
||||||
|
triggerTips1: '优先正则模式(次通配符)',
|
||||||
|
pleaseSelectType: '请选择资源类型',
|
||||||
|
apply: '应用',
|
||||||
|
mobileTips: '请输入正确的手机号码',
|
||||||
|
remove: '移除',
|
||||||
|
deleteUserConfirm: '是否确定要移除该用户',
|
||||||
|
copyResource: '复制资源名'
|
||||||
|
}
|
||||||
|
export default acl_zh
|
|
@ -12,35 +12,35 @@ const genAppRoute = ({ name }) => {
|
||||||
name: `${name}_roles_acl`,
|
name: `${name}_roles_acl`,
|
||||||
hideChildrenInMenu: true,
|
hideChildrenInMenu: true,
|
||||||
component: () => import('../views/roles'),
|
component: () => import('../views/roles'),
|
||||||
meta: { title: '角色管理', icon: 'team', keepAlive: true }
|
meta: { title: 'acl.roleManage', icon: 'team', keepAlive: true }
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: `/acl/${name}/resources`,
|
path: `/acl/${name}/resources`,
|
||||||
name: `${name}_resources_acl`,
|
name: `${name}_resources_acl`,
|
||||||
hideChildrenInMenu: true,
|
hideChildrenInMenu: true,
|
||||||
component: () => import('../views/resources'),
|
component: () => import('../views/resources'),
|
||||||
meta: { title: '资源管理', icon: 'credit-card', keepAlive: false }
|
meta: { title: 'acl.resourceManage', icon: 'credit-card', keepAlive: false }
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: `/acl/${name}/resource_types`,
|
path: `/acl/${name}/resource_types`,
|
||||||
name: `${name}_resource_types_acl`,
|
name: `${name}_resource_types_acl`,
|
||||||
hideChildrenInMenu: true,
|
hideChildrenInMenu: true,
|
||||||
component: () => import('../views/resource_types'),
|
component: () => import('../views/resource_types'),
|
||||||
meta: { title: '资源类型', icon: 'file-text', keepAlive: true }
|
meta: { title: 'acl.resourceType', icon: 'file-text', keepAlive: true }
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: `/acl/${name}/trigger`,
|
path: `/acl/${name}/trigger`,
|
||||||
name: `${name}_trigger_acl`,
|
name: `${name}_trigger_acl`,
|
||||||
hideChildrenInMenu: true,
|
hideChildrenInMenu: true,
|
||||||
component: () => import('../views/trigger'),
|
component: () => import('../views/trigger'),
|
||||||
meta: { title: '触发器', icon: 'clock-circle', keepAlive: true }
|
meta: { title: 'acl.trigger', icon: 'clock-circle', keepAlive: true }
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: `/acl/${name}/history`,
|
path: `/acl/${name}/history`,
|
||||||
name: `${name}_history_acl`,
|
name: `${name}_history_acl`,
|
||||||
hideChildrenInMenu: true,
|
hideChildrenInMenu: true,
|
||||||
component: () => import('../views/history'),
|
component: () => import('../views/history'),
|
||||||
meta: { title: '操作审计', icon: 'search', keepAlive: false }
|
meta: { title: 'acl.history', icon: 'search', keepAlive: false }
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
@ -59,31 +59,31 @@ const genAclRoutes = async () => {
|
||||||
path: `/acl/secret_key`,
|
path: `/acl/secret_key`,
|
||||||
name: 'acl_secret_key',
|
name: 'acl_secret_key',
|
||||||
component: () => import('../views/secretKey'),
|
component: () => import('../views/secretKey'),
|
||||||
meta: { title: '用户密钥', icon: 'key' }
|
meta: { title: 'acl.userSecret', icon: 'key' }
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: `/acl/operate_history`,
|
path: `/acl/operate_history`,
|
||||||
name: 'acl_operate_history',
|
name: 'acl_operate_history',
|
||||||
component: () => import('../views/operation_history/index.vue'),
|
component: () => import('../views/operation_history/index.vue'),
|
||||||
meta: { title: '操作审计', icon: 'search', permission: ['acl_admin'] },
|
meta: { title: 'acl.history', icon: 'search', permission: ['acl_admin'] }
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: `/acl/user`,
|
path: `/acl/user`,
|
||||||
name: 'acl_user',
|
name: 'acl_user',
|
||||||
component: () => import('../views/users'),
|
component: () => import('../views/users'),
|
||||||
meta: { title: '用户管理', icon: 'user', permission: ['acl_admin'] }
|
meta: { title: 'acl.userManage', icon: 'user', permission: ['acl_admin'] }
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: `/acl/roles`,
|
path: `/acl/roles`,
|
||||||
name: `acl_roles`,
|
name: `acl_roles`,
|
||||||
component: () => import('../views/roles'),
|
component: () => import('../views/roles'),
|
||||||
meta: { title: '角色管理', icon: 'team', keepAlive: true, permission: ['acl_admin'] }
|
meta: { title: 'acl.roleManage', icon: 'team', keepAlive: true, permission: ['acl_admin'] }
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: `/acl/apps`,
|
path: `/acl/apps`,
|
||||||
name: 'acl_apps',
|
name: 'acl_apps',
|
||||||
component: () => import('../views/apps'),
|
component: () => import('../views/apps'),
|
||||||
meta: { title: '应用管理', icon: 'appstore', permission: ['acl_admin'] }
|
meta: { title: 'acl.appManage', icon: 'appstore', permission: ['acl_admin'] }
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
:xs="24">
|
:xs="24">
|
||||||
<a-card>
|
<a-card>
|
||||||
<a-card-meta :title="app.name">
|
<a-card-meta :title="app.name">
|
||||||
<div slot="description" :title="app.description || ''">{{ app.description || '无' }}</div>
|
<div slot="description" :title="app.description || ''">{{ app.description || $t('none') }}</div>
|
||||||
<a-avatar style="background-color: #5dc2f1" slot="avatar">{{ app.name[0].toUpperCase() }}</a-avatar>
|
<a-avatar style="background-color: #5dc2f1" slot="avatar">{{ app.name[0].toUpperCase() }}</a-avatar>
|
||||||
</a-card-meta>
|
</a-card-meta>
|
||||||
<template slot="actions">
|
<template slot="actions">
|
||||||
|
@ -65,11 +65,11 @@ export default {
|
||||||
handleDeleteApp(app) {
|
handleDeleteApp(app) {
|
||||||
const that = this
|
const that = this
|
||||||
this.$confirm({
|
this.$confirm({
|
||||||
title: '危险操作',
|
title: that.$t('danger'),
|
||||||
content: '确定要删除该App吗?',
|
content: that.$t('confirmDeleteApp'),
|
||||||
onOk() {
|
onOk() {
|
||||||
deleteApp(app.id).then((res) => {
|
deleteApp(app.id).then((res) => {
|
||||||
that.$message.success(`删除成功:${app.name}`)
|
that.$message.success(that.$t('deleteSuccess'))
|
||||||
that.loadApps()
|
that.loadApps()
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="acl-history">
|
<div class="acl-history">
|
||||||
<a-tabs default-active-key="1">
|
<a-tabs default-active-key="1">
|
||||||
<a-tab-pane key="1" tab="权限变更">
|
<a-tab-pane key="1" :tab="$t('acl.permissionChange')">
|
||||||
<permisson-history-table
|
<permisson-history-table
|
||||||
v-if="isloaded"
|
v-if="isloaded"
|
||||||
:allResourceTypes="allResourceTypes"
|
:allResourceTypes="allResourceTypes"
|
||||||
|
@ -17,7 +17,7 @@
|
||||||
@resourceClear="resourceClear"
|
@resourceClear="resourceClear"
|
||||||
></permisson-history-table>
|
></permisson-history-table>
|
||||||
</a-tab-pane>
|
</a-tab-pane>
|
||||||
<a-tab-pane key="2" tab="角色变更">
|
<a-tab-pane key="2" :tab="$t('acl.roleChange')">
|
||||||
<role-history-table
|
<role-history-table
|
||||||
v-if="isloaded"
|
v-if="isloaded"
|
||||||
:allUsers="allUsers"
|
:allUsers="allUsers"
|
||||||
|
@ -26,7 +26,7 @@
|
||||||
:allUsersMap="allUsersMap"
|
:allUsersMap="allUsersMap"
|
||||||
></role-history-table>
|
></role-history-table>
|
||||||
</a-tab-pane>
|
</a-tab-pane>
|
||||||
<a-tab-pane key="3" tab="资源变更">
|
<a-tab-pane key="3" :tab="$t('acl.resourceChange')">
|
||||||
<resource-history-table
|
<resource-history-table
|
||||||
v-if="isloaded"
|
v-if="isloaded"
|
||||||
:allResources="allResources"
|
:allResources="allResources"
|
||||||
|
@ -41,7 +41,7 @@
|
||||||
@resourceClear="resourceClear"
|
@resourceClear="resourceClear"
|
||||||
></resource-history-table>
|
></resource-history-table>
|
||||||
</a-tab-pane>
|
</a-tab-pane>
|
||||||
<a-tab-pane key="4" tab="资源类型变更">
|
<a-tab-pane key="4" :tab="$t('acl.resourceTypeChange')">
|
||||||
<resource-type-history-table
|
<resource-type-history-table
|
||||||
v-if="isloaded"
|
v-if="isloaded"
|
||||||
:allResourceTypes="allResourceTypes"
|
:allResourceTypes="allResourceTypes"
|
||||||
|
@ -52,7 +52,7 @@
|
||||||
:allResourceTypesMap="allResourceTypesMap"
|
:allResourceTypesMap="allResourceTypesMap"
|
||||||
></resource-type-history-table>
|
></resource-type-history-table>
|
||||||
</a-tab-pane>
|
</a-tab-pane>
|
||||||
<a-tab-pane key="5" tab="触发器变更">
|
<a-tab-pane key="5" :tab="$t('acl.triggerChange')">
|
||||||
<trigger-history-table
|
<trigger-history-table
|
||||||
v-if="isloaded"
|
v-if="isloaded"
|
||||||
:allTriggers="allTriggers"
|
:allTriggers="allTriggers"
|
||||||
|
|
|
@ -1,11 +1,12 @@
|
||||||
<template>
|
<template>
|
||||||
<CustomDrawer @close="handleClose" width="500" :title="title" :visible="visible" :closable="false">
|
<CustomDrawer @close="handleClose" width="500" :title="title" :visible="visible" :closable="false">
|
||||||
<a-form :form="form" :label-col="{ span: 6 }" :wrapper-col="{ span: 16 }">
|
<a-form :form="form" :label-col="{ span: 6 }" :wrapper-col="{ span: 16 }">
|
||||||
<a-form-item label="应用名称">
|
<a-form-item :label="$t('acl.app')">
|
||||||
<a-input v-decorator="['name', { rules: [{ required: true, message: '请输入应用名称' }] }]"> </a-input>
|
<a-input v-decorator="['name', { rules: [{ required: true, message: $t('acl.appNameInput') }] }]"> </a-input>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-form-item label="描述">
|
<a-form-item :label="$t('desc')">
|
||||||
<a-input v-decorator="['description', { rules: [{ required: true, message: '请输入描述' }] }]"> </a-input>
|
<a-input v-decorator="['description', { rules: [{ required: true, message: $t('acl.descInput') }] }]">
|
||||||
|
</a-input>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-form-item label="AppId">
|
<a-form-item label="AppId">
|
||||||
<a-input v-decorator="['app_id', { rules: [{ required: false }] }]" :disabled="mode === 'update'"> </a-input>
|
<a-input v-decorator="['app_id', { rules: [{ required: false }] }]" :disabled="mode === 'update'"> </a-input>
|
||||||
|
@ -19,8 +20,8 @@
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
</a-form>
|
</a-form>
|
||||||
<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" type="primary">提交</a-button>
|
<a-button @click="handleSubmit" type="primary">{{ $t('submit') }}</a-button>
|
||||||
</div>
|
</div>
|
||||||
</CustomDrawer>
|
</CustomDrawer>
|
||||||
</template>
|
</template>
|
||||||
|
@ -32,10 +33,14 @@ export default {
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
visible: false,
|
visible: false,
|
||||||
title: '创建应用',
|
|
||||||
mode: 'create',
|
mode: 'create',
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
computed: {
|
||||||
|
title() {
|
||||||
|
return this.$t('acl.addApp')
|
||||||
|
},
|
||||||
|
},
|
||||||
beforeCreate() {
|
beforeCreate() {
|
||||||
this.form = this.$form.createForm(this)
|
this.form = this.$form.createForm(this)
|
||||||
},
|
},
|
||||||
|
@ -43,7 +48,7 @@ export default {
|
||||||
handleEdit(ele) {
|
handleEdit(ele) {
|
||||||
this.visible = true
|
this.visible = true
|
||||||
if (ele) {
|
if (ele) {
|
||||||
this.title = '修改应用'
|
this.title = this.$t('updateApp')
|
||||||
this.mode = 'update'
|
this.mode = 'update'
|
||||||
console.log(ele)
|
console.log(ele)
|
||||||
const { name, description } = ele
|
const { name, description } = ele
|
||||||
|
@ -55,7 +60,7 @@ export default {
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
this.mode = 'create'
|
this.mode = 'create'
|
||||||
this.title = '创建应用'
|
this.title = this.$t('acl.addApp')
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
handleClose() {
|
handleClose() {
|
||||||
|
@ -69,11 +74,11 @@ export default {
|
||||||
}
|
}
|
||||||
if (values.id) {
|
if (values.id) {
|
||||||
await updateApp(values.id, values).then((res) => {
|
await updateApp(values.id, values).then((res) => {
|
||||||
this.$message.success('修改成功!')
|
this.$message.success(this.$t('updateSuccess'))
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
await addApp(values).then((res) => {
|
await addApp(values).then((res) => {
|
||||||
this.$message.success('创建成功!')
|
this.$message.success(this.$t('addSuccess'))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
this.handleClose()
|
this.handleClose()
|
||||||
|
|
|
@ -9,10 +9,10 @@
|
||||||
<a-dropdown class="dropdown" size="small" placement="topCenter" :trigger="['click']" :disabled="dropdownIsDisabled">
|
<a-dropdown class="dropdown" size="small" 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('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('itemsPerPage') }}<a-icon type="down" /> </a-button>
|
||||||
</a-dropdown>
|
</a-dropdown>
|
||||||
</a-space>
|
</a-space>
|
||||||
</a-col>
|
</a-col>
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
<template>
|
<template>
|
||||||
<CustomDrawer
|
<CustomDrawer
|
||||||
:title="`权限汇总: ${user.nickname}`"
|
:title="`${$t('acl.summaryPermissions')}: ${user.nickname}`"
|
||||||
:visible="visible"
|
:visible="visible"
|
||||||
placement="left"
|
placement="left"
|
||||||
width="100%"
|
width="100%"
|
||||||
|
@ -24,7 +24,7 @@
|
||||||
<vxe-table :max-height="`${windowHeight - 230}px`" :data="resources" ref="rTable">
|
<vxe-table :max-height="`${windowHeight - 230}px`" :data="resources" ref="rTable">
|
||||||
<vxe-column
|
<vxe-column
|
||||||
field="name"
|
field="name"
|
||||||
title="资源名"
|
:title="$t('acl.resourceName')"
|
||||||
width="30%"
|
width="30%"
|
||||||
:filters="[{ data: '' }]"
|
:filters="[{ data: '' }]"
|
||||||
:filter-method="filterNameMethod"
|
:filter-method="filterNameMethod"
|
||||||
|
@ -39,62 +39,17 @@
|
||||||
v-model="option.data"
|
v-model="option.data"
|
||||||
@input="$panel.changeOption($event, !!option.data, option)"
|
@input="$panel.changeOption($event, !!option.data, option)"
|
||||||
@keyup.enter="$panel.confirmFilter()"
|
@keyup.enter="$panel.confirmFilter()"
|
||||||
placeholder="按回车确认筛选"
|
:placeholder="$t('acl.pressEnter')"
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
</template>
|
</template>
|
||||||
</vxe-column>
|
</vxe-column>
|
||||||
<vxe-column field="permissions" title="权限列表" width="70%">
|
<vxe-column field="permissions" :title="$t('acl.permissionList')" width="70%">
|
||||||
<template #default="{row}">
|
<template #default="{row}">
|
||||||
<a-tag color="cyan" v-for="(r, index) in row.permissions" :key="index">{{ r }}</a-tag>
|
<a-tag color="cyan" v-for="(r, index) in row.permissions" :key="index">{{ r }}</a-tag>
|
||||||
</template>
|
</template>
|
||||||
</vxe-column>
|
</vxe-column>
|
||||||
</vxe-table>
|
</vxe-table>
|
||||||
<!-- <a-table
|
|
||||||
:columns="tableColumns"
|
|
||||||
:dataSource="resources"
|
|
||||||
:rowKey="record=>record.id"
|
|
||||||
:pagination="{ showTotal: (total, range) => `${range[0]}-${range[1]} 共 ${total} 条记录` }"
|
|
||||||
showPagination="auto"
|
|
||||||
ref="rTable"
|
|
||||||
size="middle">
|
|
||||||
<div slot="filterDropdown" slot-scope="{ setSelectedKeys, selectedKeys, confirm, clearFilters, column }" class="custom-filter-dropdown">
|
|
||||||
<a-input
|
|
||||||
v-ant-ref="c => searchInput = c"
|
|
||||||
:placeholder="` ${column.title}`"
|
|
||||||
:value="selectedKeys[0]"
|
|
||||||
@change="e => setSelectedKeys(e.target.value ? [e.target.value] : [])"
|
|
||||||
@pressEnter="() => handleSearch(selectedKeys, confirm, column)"
|
|
||||||
style="width: 188px; margin-bottom: 8px; display: block;"
|
|
||||||
/>
|
|
||||||
<a-button
|
|
||||||
type="primary"
|
|
||||||
@click="() => handleSearch(selectedKeys, confirm, column)"
|
|
||||||
icon="search"
|
|
||||||
size="small"
|
|
||||||
style="width: 90px; margin-right: 8px"
|
|
||||||
>搜索</a-button>
|
|
||||||
<a-button
|
|
||||||
@click="() => handleReset(clearFilters, column)"
|
|
||||||
size="small"
|
|
||||||
style="width: 90px"
|
|
||||||
>重置</a-button>
|
|
||||||
</div>
|
|
||||||
<a-icon slot="filterIcon" slot-scope="filtered" type="search" :style="{ color: filtered ? '#108ee9' : undefined }" />
|
|
||||||
|
|
||||||
<template slot="nameSearchRender" slot-scope="text">
|
|
||||||
<span v-if="columnSearchText.name">
|
|
||||||
<template v-for="(fragment, i) in text.toString().split(new RegExp(`(?<=${columnSearchText.name})|(?=${columnSearchText.name})`, 'i'))">
|
|
||||||
<mark v-if="fragment.toLowerCase() === columnSearchText.name.toLowerCase()" :key="i" class="highlight">{{ fragment }}</mark>
|
|
||||||
<template v-else>{{ fragment }}</template>
|
|
||||||
</template>
|
|
||||||
</span>
|
|
||||||
<template v-else>{{ text }}</template>
|
|
||||||
</template>
|
|
||||||
<template slot="permissions" slot-scope="record">
|
|
||||||
<a-tag color="cyan" v-for="(r, index) in record" :key="index">{{ r }}</a-tag>
|
|
||||||
</template>
|
|
||||||
</a-table> -->
|
|
||||||
</a-spin>
|
</a-spin>
|
||||||
</a-tab-pane>
|
</a-tab-pane>
|
||||||
</a-tabs>
|
</a-tabs>
|
||||||
|
@ -122,33 +77,6 @@ export default {
|
||||||
resourceTypes: [],
|
resourceTypes: [],
|
||||||
resourceTypePerms: [],
|
resourceTypePerms: [],
|
||||||
resources: [],
|
resources: [],
|
||||||
// tableColumns: [
|
|
||||||
// {
|
|
||||||
// title: '资源名',
|
|
||||||
// dataIndex: 'name',
|
|
||||||
// sorter: false,
|
|
||||||
// width: 150,
|
|
||||||
// // scopedSlots: {
|
|
||||||
// // customRender: 'nameSearchRender',
|
|
||||||
// // filterDropdown: 'filterDropdown',
|
|
||||||
// // filterIcon: 'filterIcon'
|
|
||||||
// // },
|
|
||||||
// // onFilter: (value, record) => record.name && record.name.toLowerCase().includes(value.toLowerCase()),
|
|
||||||
// // onFilterDropdownVisibleChange: (visible) => {
|
|
||||||
// // if (visible) {
|
|
||||||
// // setTimeout(() => {
|
|
||||||
// // this.searchInput.focus()
|
|
||||||
// // }, 0)
|
|
||||||
// // }
|
|
||||||
// // }
|
|
||||||
// },
|
|
||||||
// {
|
|
||||||
// title: '权限列表',
|
|
||||||
// dataIndex: 'permissions',
|
|
||||||
// width: 300,
|
|
||||||
// scopedSlots: { customRender: 'permissions' },
|
|
||||||
// },
|
|
||||||
// ],
|
|
||||||
columnSearchText: {
|
columnSearchText: {
|
||||||
name: '',
|
name: '',
|
||||||
},
|
},
|
||||||
|
@ -156,14 +84,14 @@ export default {
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
...mapState({
|
...mapState({
|
||||||
windowHeight: state => state.windowHeight,
|
windowHeight: (state) => state.windowHeight,
|
||||||
}),
|
}),
|
||||||
displayApps() {
|
displayApps() {
|
||||||
const roles = this.$store.state.user.roles.permissions
|
const roles = this.$store.state.user.roles.permissions
|
||||||
if (roles.includes('acl_admin')) {
|
if (roles.includes('acl_admin')) {
|
||||||
return this.apps
|
return this.apps
|
||||||
}
|
}
|
||||||
return this.apps.filter(item => {
|
return this.apps.filter((item) => {
|
||||||
if (roles.includes(`${item.name}_admin`)) {
|
if (roles.includes(`${item.name}_admin`)) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
@ -192,7 +120,7 @@ export default {
|
||||||
},
|
},
|
||||||
async loadRoles(_appId) {
|
async loadRoles(_appId) {
|
||||||
const res = await searchRole({ app_id: _appId, page_size: 9999, is_all: true })
|
const res = await searchRole({ app_id: _appId, page_size: 9999, is_all: true })
|
||||||
this.roles = res.roles.filter(item => item.uid)
|
this.roles = res.roles.filter((item) => item.uid)
|
||||||
},
|
},
|
||||||
async handleSwitchApp(appId) {
|
async handleSwitchApp(appId) {
|
||||||
this.currentAppId = appId
|
this.currentAppId = appId
|
||||||
|
@ -218,7 +146,7 @@ export default {
|
||||||
},
|
},
|
||||||
async loadResource() {
|
async loadResource() {
|
||||||
this.spinning = true
|
this.spinning = true
|
||||||
const fil = this.roles.filter(role => role.uid === this.user.uid)
|
const fil = this.roles.filter((role) => role.uid === this.user.uid)
|
||||||
if (!fil[0]) {
|
if (!fil[0]) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,29 +1,33 @@
|
||||||
<template>
|
<template>
|
||||||
<CustomDrawer
|
<CustomDrawer
|
||||||
:closable="false"
|
:closable="false"
|
||||||
:title="drawerTitle"
|
:title="$t('acl.addReourceType')"
|
||||||
: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('acl.typeName')">
|
||||||
<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('acl.resourceNameInput') }] }]"
|
||||||
/>
|
/>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
|
|
||||||
<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('desc')">
|
||||||
<a-textarea placeholder="请输入描述信息..." name="description" :rows="4" />
|
<a-textarea :placeholder="$t('acl.descInput')" name="description" :rows="4" />
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
|
|
||||||
<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('acl.permission')"
|
||||||
|
>
|
||||||
<div :style="{ borderBottom: '1px solid #E9E9E9' }">
|
<div :style="{ borderBottom: '1px solid #E9E9E9' }">
|
||||||
<a-checkbox :indeterminate="indeterminate" @change="onCheckAllChange" :checked="checkAll">
|
<a-checkbox :indeterminate="indeterminate" @change="onCheckAllChange" :checked="checkAll">
|
||||||
全选
|
{{ $t('checkAll') }}
|
||||||
</a-checkbox>
|
</a-checkbox>
|
||||||
</div>
|
</div>
|
||||||
<br />
|
<br />
|
||||||
|
@ -35,8 +39,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('confirm') }}</a-button>
|
||||||
</div>
|
</div>
|
||||||
</a-form>
|
</a-form>
|
||||||
</CustomDrawer>
|
</CustomDrawer>
|
||||||
|
@ -49,7 +53,6 @@ export default {
|
||||||
name: 'ResourceForm',
|
name: 'ResourceForm',
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
drawerTitle: '新增资源类型',
|
|
||||||
drawerVisible: false,
|
drawerVisible: false,
|
||||||
formLayout: 'vertical',
|
formLayout: 'vertical',
|
||||||
perms: ['1'],
|
perms: ['1'],
|
||||||
|
@ -142,8 +145,8 @@ export default {
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
updateResourceType(id, data) {
|
updateResourceType(id, data) {
|
||||||
updateResourceTypeById(id, data).then(res => {
|
updateResourceTypeById(id, data).then((res) => {
|
||||||
this.$message.success(`更新成功`)
|
this.$message.success(this.$t('updateSuccess'))
|
||||||
this.handleOk()
|
this.handleOk()
|
||||||
this.onClose()
|
this.onClose()
|
||||||
})
|
})
|
||||||
|
@ -151,18 +154,12 @@ export default {
|
||||||
},
|
},
|
||||||
|
|
||||||
createResourceType(data) {
|
createResourceType(data) {
|
||||||
addResourceType(data).then(res => {
|
addResourceType(data).then((res) => {
|
||||||
this.$message.success(`添加成功`)
|
this.$message.success(this.$t('addSuccess'))
|
||||||
this.handleOk()
|
this.handleOk()
|
||||||
this.onClose()
|
this.onClose()
|
||||||
})
|
})
|
||||||
// .catch(err => this.requestFailed(err))
|
|
||||||
},
|
},
|
||||||
|
|
||||||
// requestFailed (err) {
|
|
||||||
// const msg = ((err.response || {}).data || {}).message || '请求出现错误,请稍后再试'
|
|
||||||
// this.$message.error(`${msg}`)
|
|
||||||
// }
|
|
||||||
},
|
},
|
||||||
watch: {},
|
watch: {},
|
||||||
props: {
|
props: {
|
||||||
|
|
|
@ -21,22 +21,22 @@
|
||||||
:height="`${windowHeight - windowHeightMinus}px`"
|
:height="`${windowHeight - windowHeightMinus}px`"
|
||||||
:scroll-y="{ enabled: false }"
|
:scroll-y="{ enabled: false }"
|
||||||
>
|
>
|
||||||
<vxe-column field="created_at" width="144px" title="操作时间">
|
<vxe-column field="created_at" width="144px" :title="$t('acl.operateTime')">
|
||||||
<template #default="{ row }">
|
<template #default="{ row }">
|
||||||
<span>{{ row.deleted_at || row.updated_at || row.created_at }}</span>
|
<span>{{ row.deleted_at || row.updated_at || row.created_at }}</span>
|
||||||
</template>
|
</template>
|
||||||
</vxe-column>
|
</vxe-column>
|
||||||
<vxe-column field="operate_uid" width="130px" title="操作员"></vxe-column>
|
<vxe-column field="operate_uid" width="130px" :title="$t('acl.operator')"></vxe-column>
|
||||||
<vxe-column field="operate_type" width="80px" title="操作">
|
<vxe-column field="operate_type" width="100px" :title="$t('operation')">
|
||||||
<template #default="{ row }">
|
<template #default="{ row }">
|
||||||
<a-tag :color="row.operate_type === 'grant' ? 'green' : 'red'">{{
|
<a-tag :color="row.operate_type === 'grant' ? 'green' : 'red'">{{
|
||||||
operateTypeMap.get(row.operate_type)
|
operateTypeMap.get(row.operate_type)
|
||||||
}}</a-tag>
|
}}</a-tag>
|
||||||
</template>
|
</template>
|
||||||
</vxe-column>
|
</vxe-column>
|
||||||
<vxe-column field="rid" title="用户"></vxe-column>
|
<vxe-column field="rid" :title="$t('user')"></vxe-column>
|
||||||
<vxe-column field="resource_type_id" title="资源类型"></vxe-column>
|
<vxe-column field="resource_type_id" :title="$t('acl.resourceType')"></vxe-column>
|
||||||
<vxe-column field="resources" title="资源">
|
<vxe-column field="resources" :title="$t('acl.resource')">
|
||||||
<template #default="{ row }">
|
<template #default="{ row }">
|
||||||
<template v-if="row.resource_ids.length > 0">
|
<template v-if="row.resource_ids.length > 0">
|
||||||
<a-tooltip placement="top">
|
<a-tooltip placement="top">
|
||||||
|
@ -55,14 +55,14 @@
|
||||||
</template>
|
</template>
|
||||||
</template>
|
</template>
|
||||||
</vxe-column>
|
</vxe-column>
|
||||||
<vxe-column title="权限">
|
<vxe-column :title="$t('acl.permission')">
|
||||||
<template #default="{ row }">
|
<template #default="{ row }">
|
||||||
<a-tag v-for="(perm, index) in row.permission_ids" :key="'perms_' + perm + index">
|
<a-tag v-for="(perm, index) in row.permission_ids" :key="'perms_' + perm + index">
|
||||||
{{ perm }}
|
{{ perm }}
|
||||||
</a-tag>
|
</a-tag>
|
||||||
</template>
|
</template>
|
||||||
</vxe-column>
|
</vxe-column>
|
||||||
<vxe-column field="source" width="100px" title="来源"></vxe-column>
|
<vxe-column field="source" width="100px" :title="$t('acl.source')"></vxe-column>
|
||||||
</vxe-table>
|
</vxe-table>
|
||||||
<pager
|
<pager
|
||||||
:current-page.sync="queryParams.page"
|
:current-page.sync="queryParams.page"
|
||||||
|
@ -122,10 +122,6 @@ export default {
|
||||||
loading: true,
|
loading: true,
|
||||||
app_id: this.$route.name.split('_')[0],
|
app_id: this.$route.name.split('_')[0],
|
||||||
tableData: [],
|
tableData: [],
|
||||||
operateTypeMap: new Map([
|
|
||||||
['grant', '授权'],
|
|
||||||
['revoke', '撤销'],
|
|
||||||
]),
|
|
||||||
queryParams: {
|
queryParams: {
|
||||||
page: 1,
|
page: 1,
|
||||||
page_size: 50,
|
page_size: 50,
|
||||||
|
@ -133,49 +129,6 @@ export default {
|
||||||
start: '',
|
start: '',
|
||||||
end: '',
|
end: '',
|
||||||
},
|
},
|
||||||
permissionTableAttrList: [
|
|
||||||
{
|
|
||||||
alias: '日期',
|
|
||||||
is_choice: false,
|
|
||||||
name: 'datetime',
|
|
||||||
value_type: '3',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
alias: '操作员',
|
|
||||||
is_choice: true,
|
|
||||||
name: 'operate_uid',
|
|
||||||
value_type: '2',
|
|
||||||
choice_value: this.allUsers,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
alias: '用户',
|
|
||||||
is_choice: true,
|
|
||||||
name: 'rid',
|
|
||||||
value_type: '2',
|
|
||||||
choice_value: this.allRoles,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
alias: '资源类型',
|
|
||||||
is_choice: true,
|
|
||||||
name: 'resource_type_id',
|
|
||||||
value_type: '2',
|
|
||||||
choice_value: this.allResourceTypes,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
alias: '资源',
|
|
||||||
is_choice: true,
|
|
||||||
name: 'resource_id',
|
|
||||||
value_type: '2',
|
|
||||||
choice_value: this.allResources,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
alias: '操作',
|
|
||||||
is_choice: true,
|
|
||||||
name: 'operate_type',
|
|
||||||
value_type: '2',
|
|
||||||
choice_value: [{ 授权: 'grant' }, { 撤销: 'revoke' }],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
async created() {
|
async created() {
|
||||||
|
@ -198,6 +151,12 @@ export default {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
operateTypeMap() {
|
||||||
|
return new Map([
|
||||||
|
['grant', this.$t('grant')],
|
||||||
|
['revoke', this.$t('acl.cancel')],
|
||||||
|
])
|
||||||
|
},
|
||||||
windowHeight() {
|
windowHeight() {
|
||||||
return this.$store.state.windowHeight
|
return this.$store.state.windowHeight
|
||||||
},
|
},
|
||||||
|
@ -207,6 +166,51 @@ export default {
|
||||||
tableDataLength() {
|
tableDataLength() {
|
||||||
return this.tableData.length
|
return this.tableData.length
|
||||||
},
|
},
|
||||||
|
permissionTableAttrList() {
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
alias: this.$t('acl.date'),
|
||||||
|
is_choice: false,
|
||||||
|
name: 'datetime',
|
||||||
|
value_type: '3',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
alias: this.$t('acl.operator'),
|
||||||
|
is_choice: true,
|
||||||
|
name: 'operate_uid',
|
||||||
|
value_type: '2',
|
||||||
|
choice_value: this.allUsers,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
alias: this.$t('user'),
|
||||||
|
is_choice: true,
|
||||||
|
name: 'rid',
|
||||||
|
value_type: '2',
|
||||||
|
choice_value: this.allRoles,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
alias: this.$t('acl.resourceType'),
|
||||||
|
is_choice: true,
|
||||||
|
name: 'resource_type_id',
|
||||||
|
value_type: '2',
|
||||||
|
choice_value: this.allResourceTypes,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
alias: this.$t('acl.resource'),
|
||||||
|
is_choice: true,
|
||||||
|
name: 'resource_id',
|
||||||
|
value_type: '2',
|
||||||
|
choice_value: this.allResources,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
alias: this.$t('operation'),
|
||||||
|
is_choice: true,
|
||||||
|
name: 'operate_type',
|
||||||
|
value_type: '2',
|
||||||
|
choice_value: [{ [this.$t('grant')]: 'grant' }, { [this.$t('acl.cancel')]: 'revoke' }],
|
||||||
|
},
|
||||||
|
]
|
||||||
|
},
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
// 获取数据
|
// 获取数据
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
<template>
|
<template>
|
||||||
<CustomDrawer
|
<CustomDrawer
|
||||||
title="便捷授权"
|
:title="$t('acl.convenient')"
|
||||||
width="500px"
|
width="500px"
|
||||||
:maskClosable="false"
|
:maskClosable="false"
|
||||||
:closable="true"
|
:closable="true"
|
||||||
|
@ -10,12 +10,12 @@
|
||||||
<a-form :form="form">
|
<a-form :form="form">
|
||||||
<a-form-item>
|
<a-form-item>
|
||||||
<div slot="label" style="display: inline-block">
|
<div slot="label" style="display: inline-block">
|
||||||
<span>角色列表</span>
|
<span>{{ $t('acl.roleList') }}</span>
|
||||||
<a-divider type="vertical" />
|
<a-divider type="vertical" />
|
||||||
<a-switch
|
<a-switch
|
||||||
style="display: inline-block"
|
style="display: inline-block"
|
||||||
checked-children="用户"
|
:checked-children="$t('user')"
|
||||||
un-checked-children="虚拟"
|
:un-checked-children="$t('acl.virtual')"
|
||||||
@change="handleRoleTypeChange"
|
@change="handleRoleTypeChange"
|
||||||
v-model="roleType"
|
v-model="roleType"
|
||||||
/>
|
/>
|
||||||
|
@ -23,37 +23,37 @@
|
||||||
<el-select
|
<el-select
|
||||||
:style="{ width: '100%' }"
|
:style="{ width: '100%' }"
|
||||||
size="small"
|
size="small"
|
||||||
v-decorator="['roleIdList', { rules: [{ required: true, message: '请选择角色名称' }] }]"
|
v-decorator="['roleIdList', { rules: [{ required: true, message: $t('acl.role_placeholder2') }] }]"
|
||||||
multiple
|
multiple
|
||||||
filterable
|
filterable
|
||||||
placeholder="请选择角色名称,可多选!"
|
:placeholder="$t('acl.role_placeholder3')"
|
||||||
>
|
>
|
||||||
<el-option v-for="role in allRoles" :key="role.id" :value="role.id" :label="role.name"></el-option>
|
<el-option v-for="role in allRoles" :key="role.id" :value="role.id" :label="role.name"></el-option>
|
||||||
</el-select>
|
</el-select>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
|
|
||||||
<a-form-item label="权限列表">
|
<a-form-item :label="$t('acl.permissionList')">
|
||||||
<el-select
|
<el-select
|
||||||
:style="{ width: '100%' }"
|
:style="{ width: '100%' }"
|
||||||
size="small"
|
size="small"
|
||||||
name="permName"
|
name="permName"
|
||||||
v-decorator="['permName', { rules: [{ required: true, message: '请选择权限' }] }]"
|
v-decorator="['permName', { rules: [{ required: true, message: this.$t('acl.permission_placeholder') }] }]"
|
||||||
multiple
|
multiple
|
||||||
placeholder="请选择权限,可多选!"
|
:placeholder="this.$t('acl.permission_placeholder')"
|
||||||
>
|
>
|
||||||
<el-option v-for="perm in allPerms" :key="perm.name" :value="perm.name" :label="perm.name"></el-option>
|
<el-option v-for="perm in allPerms" :key="perm.name" :value="perm.name" :label="perm.name"></el-option>
|
||||||
</el-select>
|
</el-select>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-form-item label="资源名">
|
<a-form-item :label="$t('acl.resourceName')">
|
||||||
<a-textarea
|
<a-textarea
|
||||||
v-decorator="['resource_names', { rules: [{ required: true, message: '请输入资源名,换行分隔' }] }]"
|
v-decorator="['resource_names', { rules: [{ required: true, message: $t('acl.resourceBatchTips') }] }]"
|
||||||
:autoSize="{ minRows: 4 }"
|
:autoSize="{ minRows: 4 }"
|
||||||
placeholder="请输入资源名,换行分隔"
|
:placeholder="$t('acl.resourceBatchTips')"
|
||||||
/>
|
/>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<div class="custom-drawer-bottom-action">
|
<div class="custom-drawer-bottom-action">
|
||||||
<a-button @click="handleRevoke" type="danger" ghost>权限回收</a-button>
|
<a-button @click="handleRevoke" type="danger" ghost>{{ $t('acl.revoke') }}</a-button>
|
||||||
<a-button @click="handleSubmit" type="primary">授权</a-button>
|
<a-button @click="handleSubmit" type="primary">{{ $t('grant') }}</a-button>
|
||||||
</div>
|
</div>
|
||||||
</a-form>
|
</a-form>
|
||||||
</CustomDrawer>
|
</CustomDrawer>
|
||||||
|
@ -98,12 +98,12 @@ export default {
|
||||||
this.loadRoles(Number(target))
|
this.loadRoles(Number(target))
|
||||||
},
|
},
|
||||||
loadRoles(isUserRole) {
|
loadRoles(isUserRole) {
|
||||||
searchRole({ page_size: 9999, app_id: this.$route.name.split('_')[0], user_role: isUserRole }).then(res => {
|
searchRole({ page_size: 9999, app_id: this.$route.name.split('_')[0], user_role: isUserRole }).then((res) => {
|
||||||
this.allRoles = res.roles
|
this.allRoles = res.roles
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
loadPerm(resourceTypeId) {
|
loadPerm(resourceTypeId) {
|
||||||
getResourceTypePerms(resourceTypeId).then(res => {
|
getResourceTypePerms(resourceTypeId).then((res) => {
|
||||||
this.allPerms = res
|
this.allPerms = res
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
@ -111,13 +111,13 @@ export default {
|
||||||
this.form.validateFields((err, values) => {
|
this.form.validateFields((err, values) => {
|
||||||
if (!err) {
|
if (!err) {
|
||||||
console.log(values)
|
console.log(values)
|
||||||
values.roleIdList.forEach(roleId => {
|
values.roleIdList.forEach((roleId) => {
|
||||||
setBatchRoleResourceByResourceName(roleId, {
|
setBatchRoleResourceByResourceName(roleId, {
|
||||||
resource_names: values.resource_names.split('\n'),
|
resource_names: values.resource_names.split('\n'),
|
||||||
perms: values.permName,
|
perms: values.permName,
|
||||||
resource_type_id: this.resource_type_id,
|
resource_type_id: this.resource_type_id,
|
||||||
}).then(res => {
|
}).then((res) => {
|
||||||
this.$message.success('授权成功')
|
this.$message.success(this.$t('operateSuccess'))
|
||||||
this.form.resetFields()
|
this.form.resetFields()
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
@ -128,13 +128,13 @@ export default {
|
||||||
this.form.validateFields((err, values) => {
|
this.form.validateFields((err, values) => {
|
||||||
if (!err) {
|
if (!err) {
|
||||||
console.log(values)
|
console.log(values)
|
||||||
values.roleIdList.forEach(roleId => {
|
values.roleIdList.forEach((roleId) => {
|
||||||
setBatchRoleResourceRevokeByResourceName(roleId, {
|
setBatchRoleResourceRevokeByResourceName(roleId, {
|
||||||
resource_names: values.resource_names.split('\n'),
|
resource_names: values.resource_names.split('\n'),
|
||||||
perms: values.permName,
|
perms: values.permName,
|
||||||
resource_type_id: this.resource_type_id,
|
resource_type_id: this.resource_type_id,
|
||||||
}).then(res => {
|
}).then((res) => {
|
||||||
this.$message.success('权限回收成功')
|
this.$message.success(this.$t('operateSuccess'))
|
||||||
this.form.resetFields()
|
this.form.resetFields()
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
|
@ -8,27 +8,27 @@
|
||||||
width="30%"
|
width="30%"
|
||||||
>
|
>
|
||||||
<a-form :form="form" @submit="handleSubmit" :label-col="{ span: 6 }" :wrapper-col="{ span: 16 }">
|
<a-form :form="form" @submit="handleSubmit" :label-col="{ span: 6 }" :wrapper-col="{ span: 16 }">
|
||||||
<a-form-item label="资源名">
|
<a-form-item :label="$t('acl.resourceName')">
|
||||||
<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('acl.resourceNameInput') }] }]"
|
||||||
/>
|
/>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
|
|
||||||
<a-form-item label="资源类型">
|
<a-form-item :label="$t('acl.resourceType')">
|
||||||
<a-select v-model="selectedTypeId">
|
<a-select v-model="selectedTypeId">
|
||||||
<a-select-option v-for="type in allTypes" :key="type.id">{{ type.name }}</a-select-option>
|
<a-select-option v-for="type in allTypes" :key="type.id">{{ type.name }}</a-select-option>
|
||||||
</a-select>
|
</a-select>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
|
|
||||||
<a-form-item label="是否组">
|
<a-form-item :label="$t('acl.isGroup')">
|
||||||
<a-radio-group v-model="isGroup">
|
<a-radio-group v-model="isGroup">
|
||||||
<a-radio :value="true">
|
<a-radio :value="true">
|
||||||
是
|
{{ $t('yes') }}
|
||||||
</a-radio>
|
</a-radio>
|
||||||
<a-radio :value="false">
|
<a-radio :value="false">
|
||||||
否
|
{{ $t('no') }}
|
||||||
</a-radio>
|
</a-radio>
|
||||||
</a-radio-group>
|
</a-radio-group>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
|
@ -36,8 +36,8 @@
|
||||||
<a-input name="id" type="hidden" v-decorator="['id', { rules: [] }]" />
|
<a-input name="id" type="hidden" v-decorator="['id', { rules: [] }]" />
|
||||||
</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('confirm') }}</a-button>
|
||||||
</div>
|
</div>
|
||||||
</a-form>
|
</a-form>
|
||||||
</CustomDrawer>
|
</CustomDrawer>
|
||||||
|
@ -52,7 +52,6 @@ export default {
|
||||||
name: 'ResourceForm',
|
name: 'ResourceForm',
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
drawerTitle: '新增资源',
|
|
||||||
drawerVisible: false,
|
drawerVisible: false,
|
||||||
allTypes: [],
|
allTypes: [],
|
||||||
isGroup: false,
|
isGroup: false,
|
||||||
|
@ -68,7 +67,11 @@ export default {
|
||||||
this.getAllResourceTypes()
|
this.getAllResourceTypes()
|
||||||
},
|
},
|
||||||
|
|
||||||
computed: {},
|
computed: {
|
||||||
|
drawerTitle() {
|
||||||
|
return this.$t('acl.addResource')
|
||||||
|
},
|
||||||
|
},
|
||||||
mounted() {},
|
mounted() {},
|
||||||
methods: {
|
methods: {
|
||||||
getAllResourceTypes() {
|
getAllResourceTypes() {
|
||||||
|
@ -95,7 +98,7 @@ export default {
|
||||||
values.type_id = this.selectedTypeId
|
values.type_id = this.selectedTypeId
|
||||||
values.app_id = this.$route.name.split('_')[0]
|
values.app_id = this.$route.name.split('_')[0]
|
||||||
if (values.id) {
|
if (values.id) {
|
||||||
this.$message.error('错误提示')
|
this.$message.error(this.$t('acl.errorTips'))
|
||||||
} else {
|
} else {
|
||||||
this.createResource(values)
|
this.createResource(values)
|
||||||
}
|
}
|
||||||
|
@ -105,23 +108,17 @@ export default {
|
||||||
createResource(data) {
|
createResource(data) {
|
||||||
if (!this.isGroup) {
|
if (!this.isGroup) {
|
||||||
addResource(data).then((res) => {
|
addResource(data).then((res) => {
|
||||||
this.$message.success(`添加成功`)
|
this.$message.success(this.$t('addSuccess'))
|
||||||
this.onClose()
|
this.onClose()
|
||||||
})
|
})
|
||||||
// .catch(err => this.requestFailed(err))
|
// .catch(err => this.requestFailed(err))
|
||||||
} else {
|
} else {
|
||||||
addResourceGroup(data).then((res) => {
|
addResourceGroup(data).then((res) => {
|
||||||
this.$message.success(`添加成功`)
|
this.$message.success(this.$t('addSuccess'))
|
||||||
this.onClose()
|
this.onClose()
|
||||||
})
|
})
|
||||||
// .catch(err => this.requestFailed(err))
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
// requestFailed(err) {
|
|
||||||
// const msg = ((err.response || {}).data || {}).message || '请求出现错误,请稍后再试'
|
|
||||||
// this.$message.error(`${msg}`)
|
|
||||||
// },
|
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
'$route.name': function(newValue, oldValue) {
|
'$route.name': function(newValue, oldValue) {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<template>
|
<template>
|
||||||
<a-modal v-model="visible" :title="`组成员:${editRecord.name}`" :width="800" :footer="null">
|
<a-modal v-model="visible" :title="`${$t('acl.groupMember')}${editRecord.name}`" :width="800" :footer="null">
|
||||||
<div :style="{ maxHeight: '500px', overflow: 'auto' }">
|
<div :style="{ maxHeight: '500px', overflow: 'auto' }">
|
||||||
<a-tag :style="{ marginBottom: '5px' }" v-for="mem in members" :key="mem.name">
|
<a-tag :style="{ marginBottom: '5px' }" v-for="mem in members" :key="mem.name">
|
||||||
{{ mem.name }}
|
{{ mem.name }}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<template>
|
<template>
|
||||||
<a-modal v-model="visible" :title="`成员管理:${editRecord.name}`" @ok="handleSubmit" :width="690">
|
<a-modal v-model="visible" :title="`${$t('acl.memberManage')}${editRecord.name}`" @ok="handleSubmit" :width="690">
|
||||||
<!-- <CustomTransfer
|
<!-- <CustomTransfer
|
||||||
ref="customTransfer"
|
ref="customTransfer"
|
||||||
:show-search="true"
|
:show-search="true"
|
||||||
|
@ -26,7 +26,7 @@
|
||||||
@selectChange="selectChange"
|
@selectChange="selectChange"
|
||||||
:selectedKeys="selectedKeys"
|
:selectedKeys="selectedKeys"
|
||||||
>
|
>
|
||||||
<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'">
|
||||||
<div
|
<div
|
||||||
|
@ -104,7 +104,7 @@ export default {
|
||||||
})
|
})
|
||||||
updateResourceGroup(this.editRecord['id'], { items: items.join(',') }).then(() => {
|
updateResourceGroup(this.editRecord['id'], { items: items.join(',') }).then(() => {
|
||||||
this.visible = false
|
this.visible = false
|
||||||
this.$message.success('更新成功!')
|
this.$message.success(this.$t('updateSuccess'))
|
||||||
})
|
})
|
||||||
// .catch(err => this.$httpError(err))
|
// .catch(err => this.$httpError(err))
|
||||||
},
|
},
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
ref="child"
|
ref="child"
|
||||||
:attrList="resourceTableAttrList"
|
:attrList="resourceTableAttrList"
|
||||||
:hasSwitch="true"
|
:hasSwitch="true"
|
||||||
switchValue="组"
|
:switchValue="$t('acl.group2')"
|
||||||
@onSwitchChange="onSwitchChange"
|
@onSwitchChange="onSwitchChange"
|
||||||
@search="handleSearch"
|
@search="handleSearch"
|
||||||
@searchFormReset="searchFormReset"
|
@searchFormReset="searchFormReset"
|
||||||
|
@ -22,30 +22,30 @@
|
||||||
resizable
|
resizable
|
||||||
:height="`${windowHeight - 310}px`"
|
:height="`${windowHeight - 310}px`"
|
||||||
>
|
>
|
||||||
<vxe-column field="created_at" width="144px" title="操作时间"></vxe-column>
|
<vxe-column field="created_at" width="144px" :title="$t('acl.operateTime')"></vxe-column>
|
||||||
<vxe-column field="operate_uid" width="130px" title="操作员"></vxe-column>
|
<vxe-column field="operate_uid" width="130px" :title="$t('acl.operator')"></vxe-column>
|
||||||
<vxe-column field="operate_type" width="80px" title="操作">
|
<vxe-column field="operate_type" width="100px" :title="$t('operation')">
|
||||||
<template #default="{ row }">
|
<template #default="{ row }">
|
||||||
<a-tag :color="handleTagColor(row.operate_type)">
|
<a-tag :color="handleTagColor(row.operate_type)">
|
||||||
{{ operateTypeMap.get(row.operate_type) }}
|
{{ operateTypeMap.get(row.operate_type) }}
|
||||||
</a-tag>
|
</a-tag>
|
||||||
</template>
|
</template>
|
||||||
</vxe-column>
|
</vxe-column>
|
||||||
<vxe-column field="link_id" title="资源名">
|
<vxe-column field="link_id" :title="$t('acl.resourceName')">
|
||||||
<template #default="{ row }">
|
<template #default="{ row }">
|
||||||
<span>
|
<span>
|
||||||
{{ row.current.name || row.origin.name }}
|
{{ row.current.name || row.origin.name }}
|
||||||
</span>
|
</span>
|
||||||
</template>
|
</template>
|
||||||
</vxe-column>
|
</vxe-column>
|
||||||
<vxe-column title="描述">
|
<vxe-column :title="$t('desc')">
|
||||||
<template #default="{ row }">
|
<template #default="{ row }">
|
||||||
<p>
|
<p>
|
||||||
{{ row.description }}
|
{{ row.description }}
|
||||||
</p>
|
</p>
|
||||||
</template>
|
</template>
|
||||||
</vxe-column>
|
</vxe-column>
|
||||||
<vxe-column field="source" width="100px" title="来源"></vxe-column>
|
<vxe-column field="source" width="100px" :title="$t('acl.source')"></vxe-column>
|
||||||
</vxe-table>
|
</vxe-table>
|
||||||
<pager
|
<pager
|
||||||
:current-page.sync="queryParams.page"
|
:current-page.sync="queryParams.page"
|
||||||
|
@ -99,40 +99,6 @@ export default {
|
||||||
checked: false,
|
checked: false,
|
||||||
tableData: [],
|
tableData: [],
|
||||||
app_id: this.$route.name.split('_')[0],
|
app_id: this.$route.name.split('_')[0],
|
||||||
resourceTableAttrList: [
|
|
||||||
{
|
|
||||||
alias: '日期',
|
|
||||||
is_choice: false,
|
|
||||||
name: 'datetime',
|
|
||||||
value_type: '3',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
alias: '操作员',
|
|
||||||
is_choice: true,
|
|
||||||
name: 'operate_uid',
|
|
||||||
value_type: '2',
|
|
||||||
choice_value: this.allUsers,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
alias: '操作',
|
|
||||||
is_choice: true,
|
|
||||||
name: 'operate_type',
|
|
||||||
value_type: '2',
|
|
||||||
choice_value: [{ 新建: 'create' }, { 修改: 'update' }, { 删除: 'delete' }],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
alias: '资源名',
|
|
||||||
is_choice: true,
|
|
||||||
name: 'link_id',
|
|
||||||
value_type: '2',
|
|
||||||
choice_value: this.allResources,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
operateTypeMap: new Map([
|
|
||||||
['create', '新建'],
|
|
||||||
['update', '修改'],
|
|
||||||
['delete', '删除'],
|
|
||||||
]),
|
|
||||||
colorMap: new Map([
|
colorMap: new Map([
|
||||||
['create', 'green'],
|
['create', 'green'],
|
||||||
['update', 'orange'],
|
['update', 'orange'],
|
||||||
|
@ -170,9 +136,47 @@ export default {
|
||||||
windowHeight() {
|
windowHeight() {
|
||||||
return this.$store.state.windowHeight
|
return this.$store.state.windowHeight
|
||||||
},
|
},
|
||||||
|
operateTypeMap() {
|
||||||
|
return new Map([
|
||||||
|
['create', this.$t('create')],
|
||||||
|
['update', this.$t('update')],
|
||||||
|
['delete', this.$t('delete')],
|
||||||
|
])
|
||||||
|
},
|
||||||
tableDataLength() {
|
tableDataLength() {
|
||||||
return this.tableData.length
|
return this.tableData.length
|
||||||
},
|
},
|
||||||
|
resourceTableAttrList() {
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
alias: this.$t('acl.date'),
|
||||||
|
is_choice: false,
|
||||||
|
name: 'datetime',
|
||||||
|
value_type: '3',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
alias: this.$t('acl.operator'),
|
||||||
|
is_choice: true,
|
||||||
|
name: 'operate_uid',
|
||||||
|
value_type: '2',
|
||||||
|
choice_value: this.allUsers,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
alias: this.$t('operation'),
|
||||||
|
is_choice: true,
|
||||||
|
name: 'operate_type',
|
||||||
|
value_type: '2',
|
||||||
|
choice_value: [{ [this.$t('create')]: 'create' }, { [this.$t('update')]: 'update' }, { [this.$t('delete')]: 'delete' }],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
alias: this.$t('acl.resourceName'),
|
||||||
|
is_choice: true,
|
||||||
|
name: 'link_id',
|
||||||
|
value_type: '2',
|
||||||
|
choice_value: this.allResources,
|
||||||
|
},
|
||||||
|
]
|
||||||
|
},
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
async getTable(queryParams) {
|
async getTable(queryParams) {
|
||||||
|
@ -280,7 +284,7 @@ export default {
|
||||||
switch (operate_type) {
|
switch (operate_type) {
|
||||||
// create
|
// create
|
||||||
case 'create': {
|
case 'create': {
|
||||||
item.description = `新建资源:${item.current.name}`
|
item.description = `${this.$t('acl.newResource')}${item.current.name}`
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
case 'update': {
|
case 'update': {
|
||||||
|
@ -290,9 +294,9 @@ export default {
|
||||||
const oldVal = item.origin[key]
|
const oldVal = item.origin[key]
|
||||||
if (!_.isEqual(newVal, oldVal) && key !== 'updated_at' && key !== 'deleted_at' && key !== 'created_at') {
|
if (!_.isEqual(newVal, oldVal) && key !== 'updated_at' && key !== 'deleted_at' && key !== 'created_at') {
|
||||||
if (oldVal === null) {
|
if (oldVal === null) {
|
||||||
item.description += ` 【 ${key} : 改为 ${newVal} 】 `
|
item.description += ` 【 ${key} : -> ${newVal} 】 `
|
||||||
} else {
|
} else {
|
||||||
item.description += ` 【 ${key} : 由 ${oldVal} 改为 ${newVal} 】 `
|
item.description += ` 【 ${key} : ${oldVal} -> ${newVal} 】 `
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -300,18 +304,18 @@ export default {
|
||||||
const currentResource_ids = item.currentResource_ids
|
const currentResource_ids = item.currentResource_ids
|
||||||
if (!_.isEqual(originResource_ids, currentResource_ids)) {
|
if (!_.isEqual(originResource_ids, currentResource_ids)) {
|
||||||
if (originResource_ids.length === 0) {
|
if (originResource_ids.length === 0) {
|
||||||
const str = ` 【 resource_ids : 新增 ${currentResource_ids} 】 `
|
const str = ` 【 resource_ids : ${this.$t('new')} ${currentResource_ids} 】 `
|
||||||
item.description += str
|
item.description += str
|
||||||
} else {
|
} else {
|
||||||
const str = ` 【 resource_ids : 由 ${originResource_ids} 改为 ${currentResource_ids} 】 `
|
const str = ` 【 resource_ids : ${originResource_ids} -> ${currentResource_ids} 】 `
|
||||||
item.description += str
|
item.description += str
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!item.description) item.description = '没有修改'
|
if (!item.description) item.description = this.$t('acl.noChange')
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
case 'delete': {
|
case 'delete': {
|
||||||
item.description = `删除资源:${item.origin.name}`
|
item.description = `${this.$t('acl.deleteResource')}${item.origin.name}`
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
>
|
>
|
||||||
<vxe-column
|
<vxe-column
|
||||||
field="name"
|
field="name"
|
||||||
title="角色名"
|
:title="$t('acl.role')"
|
||||||
width="20%"
|
width="20%"
|
||||||
:filters="[{ data: '' }]"
|
:filters="[{ data: '' }]"
|
||||||
:filter-method="filterNameMethod"
|
:filter-method="filterNameMethod"
|
||||||
|
@ -32,19 +32,19 @@
|
||||||
v-model="option.data"
|
v-model="option.data"
|
||||||
@input="$panel.changeOption($event, !!option.data, option)"
|
@input="$panel.changeOption($event, !!option.data, option)"
|
||||||
@keyup.enter="$panel.confirmFilter()"
|
@keyup.enter="$panel.confirmFilter()"
|
||||||
placeholder="按回车确认筛选"
|
:placeholder="$t('acl.pressEnter')"
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
</template>
|
</template>
|
||||||
</vxe-column>
|
</vxe-column>
|
||||||
<vxe-column field="users" title="下属用户" width="35%">
|
<vxe-column field="users" :title="$t('acl.subordinateUsers')" width="35%">
|
||||||
<template #default="{row}">
|
<template #default="{row}">
|
||||||
<a-tag color="green" v-for="user in row.users" :key="user.nickname">
|
<a-tag color="green" v-for="user in row.users" :key="user.nickname">
|
||||||
{{ user.nickname }}
|
{{ user.nickname }}
|
||||||
</a-tag>
|
</a-tag>
|
||||||
</template>
|
</template>
|
||||||
</vxe-column>
|
</vxe-column>
|
||||||
<vxe-column field="perms" title="权限列表" width="35%">
|
<vxe-column field="perms" :title="$t('acl.permissionList')" width="35%">
|
||||||
<template #default="{row}">
|
<template #default="{row}">
|
||||||
<a-tag
|
<a-tag
|
||||||
closable
|
closable
|
||||||
|
@ -57,43 +57,18 @@
|
||||||
</a-tag>
|
</a-tag>
|
||||||
</template>
|
</template>
|
||||||
</vxe-column>
|
</vxe-column>
|
||||||
<vxe-column field="operate" title="批量操作">
|
<vxe-column field="operate" :title="$t('batchOperate')">
|
||||||
<template #default="{row}">
|
<template #default="{row}">
|
||||||
<a-button size="small" type="danger" @click="handleClearAll(row)">
|
<a-button size="small" type="danger" @click="handleClearAll(row)">
|
||||||
清空
|
{{ $t('clear') }}
|
||||||
</a-button>
|
</a-button>
|
||||||
</template>
|
</template>
|
||||||
</vxe-column>
|
</vxe-column>
|
||||||
<template slot="empty">
|
<template slot="empty">
|
||||||
<img :src="require(`@/assets/data_empty.png`)" />
|
<img :src="require(`@/assets/data_empty.png`)" />
|
||||||
<p style="font-size: 14px; line-height: 17px; color: rgba(0, 0, 0, 0.6)">暂无数据</p>
|
<p style="font-size: 14px; line-height: 17px; color: rgba(0, 0, 0, 0.6)">{{ $t('noData') }}</p>
|
||||||
</template>
|
</template>
|
||||||
</vxe-table>
|
</vxe-table>
|
||||||
<!-- <a-table
|
|
||||||
:columns="columns"
|
|
||||||
:dataSource="resPerms"
|
|
||||||
:rowKey="record => record.name"
|
|
||||||
:pagination="{ showTotal: (total, range) => `${range[0]}-${range[1]} 共 ${total} 条记录` }"
|
|
||||||
showPagination="auto"
|
|
||||||
ref="rTable"
|
|
||||||
size="middle"
|
|
||||||
>
|
|
||||||
<div slot="perms" slot-scope="text">
|
|
||||||
<a-tag closable color="cyan" v-for="perm in text" :key="perm.name" @close="deletePerm(perm.rid, perm.name)">
|
|
||||||
{{ perm.name }}
|
|
||||||
</a-tag>
|
|
||||||
</div>
|
|
||||||
<div slot="users" slot-scope="text">
|
|
||||||
<a-tag color="green" v-for="user in text" :key="user.nickname">
|
|
||||||
{{ user.nickname }}
|
|
||||||
</a-tag>
|
|
||||||
</div>
|
|
||||||
<div slot="operate" slot-scope="text">
|
|
||||||
<a-button size="small" type="danger" @click="handleClearAll(text)">
|
|
||||||
清空
|
|
||||||
</a-button>
|
|
||||||
</div>
|
|
||||||
</a-table> -->
|
|
||||||
</CustomDrawer>
|
</CustomDrawer>
|
||||||
</template>
|
</template>
|
||||||
<script>
|
<script>
|
||||||
|
@ -112,40 +87,11 @@ export default {
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
isGroup: false,
|
isGroup: false,
|
||||||
drawerTitle: '权限列表',
|
|
||||||
drawerVisible: false,
|
drawerVisible: false,
|
||||||
record: null,
|
record: null,
|
||||||
allPerms: [],
|
allPerms: [],
|
||||||
resPerms: [],
|
resPerms: [],
|
||||||
roleID: null,
|
roleID: null,
|
||||||
// columns: [
|
|
||||||
// {
|
|
||||||
// title: '角色名',
|
|
||||||
// dataIndex: 'name',
|
|
||||||
// sorter: false,
|
|
||||||
// width: 50,
|
|
||||||
// },
|
|
||||||
// {
|
|
||||||
// title: '下属用户',
|
|
||||||
// dataIndex: 'users',
|
|
||||||
// sorter: false,
|
|
||||||
// width: 150,
|
|
||||||
// scopedSlots: { customRender: 'users' },
|
|
||||||
// },
|
|
||||||
// {
|
|
||||||
// title: '权限列表',
|
|
||||||
// dataIndex: 'perms',
|
|
||||||
// sorter: false,
|
|
||||||
// width: 150,
|
|
||||||
// scopedSlots: { customRender: 'perms' },
|
|
||||||
// },
|
|
||||||
// {
|
|
||||||
// title: '批量操作',
|
|
||||||
// sorter: false,
|
|
||||||
// width: 50,
|
|
||||||
// scopedSlots: { customRender: 'operate' },
|
|
||||||
// },
|
|
||||||
// ],
|
|
||||||
childrenDrawer: false,
|
childrenDrawer: false,
|
||||||
allRoles: [],
|
allRoles: [],
|
||||||
}
|
}
|
||||||
|
@ -154,6 +100,9 @@ export default {
|
||||||
...mapState({
|
...mapState({
|
||||||
windowHeight: (state) => state.windowHeight,
|
windowHeight: (state) => state.windowHeight,
|
||||||
}),
|
}),
|
||||||
|
drawerTitle() {
|
||||||
|
return this.$t('acl.permissionList')
|
||||||
|
}
|
||||||
},
|
},
|
||||||
beforeCreate() {
|
beforeCreate() {
|
||||||
this.form = this.$form.createForm(this)
|
this.form = this.$form.createForm(this)
|
||||||
|
@ -175,7 +124,7 @@ export default {
|
||||||
perms: [],
|
perms: [],
|
||||||
app_id: this.$route.name.split('_')[0],
|
app_id: this.$route.name.split('_')[0],
|
||||||
}).then((res) => {
|
}).then((res) => {
|
||||||
this.$message.success('删除成功')
|
this.$message.success(this.$t('deleteSuccess'))
|
||||||
this.$nextTick(() => {
|
this.$nextTick(() => {
|
||||||
this.getResPerms(this.record.id)
|
this.getResPerms(this.record.id)
|
||||||
})
|
})
|
||||||
|
@ -185,7 +134,7 @@ export default {
|
||||||
perms: [],
|
perms: [],
|
||||||
app_id: this.$route.name.split('_')[0],
|
app_id: this.$route.name.split('_')[0],
|
||||||
}).then((res) => {
|
}).then((res) => {
|
||||||
this.$message.success('删除成功')
|
this.$message.success(this.$t('deleteSuccess'))
|
||||||
// for (let i = 0; i < this.resPerms.length; i++) {
|
// for (let i = 0; i < this.resPerms.length; i++) {
|
||||||
// if (this.resPerms[i].name === text.name) {
|
// if (this.resPerms[i].name === text.name) {
|
||||||
// this.resPerms[i].perms = []
|
// this.resPerms[i].perms = []
|
||||||
|
@ -227,7 +176,7 @@ export default {
|
||||||
perms: [permName],
|
perms: [permName],
|
||||||
app_id: this.$route.name.split('_')[0],
|
app_id: this.$route.name.split('_')[0],
|
||||||
}).then((res) => {
|
}).then((res) => {
|
||||||
this.$message.success(`删除成功`)
|
this.$message.success(this.$t('deleteSuccess'))
|
||||||
})
|
})
|
||||||
// .catch(err => this.requestFailed(err))
|
// .catch(err => this.requestFailed(err))
|
||||||
} else {
|
} else {
|
||||||
|
@ -235,18 +184,13 @@ export default {
|
||||||
perms: [permName],
|
perms: [permName],
|
||||||
app_id: this.$route.name.split('_')[0],
|
app_id: this.$route.name.split('_')[0],
|
||||||
}).then((res) => {
|
}).then((res) => {
|
||||||
this.$message.success(`删除成功`)
|
this.$message.success(this.$t('deleteSuccess'))
|
||||||
})
|
})
|
||||||
// .catch(err => this.requestFailed(err))
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
handleCancel(e) {
|
handleCancel(e) {
|
||||||
this.drawerVisible = false
|
this.drawerVisible = false
|
||||||
},
|
},
|
||||||
// requestFailed(err) {
|
|
||||||
// const msg = ((err.response || {}).data || {}).message || '请求出现错误,请稍后再试'
|
|
||||||
// this.$message.error(`${msg}`)
|
|
||||||
// },
|
|
||||||
filterNameMethod({ option, row }) {
|
filterNameMethod({ option, row }) {
|
||||||
return row.name.toLowerCase().includes(option.data.toLowerCase())
|
return row.name.toLowerCase().includes(option.data.toLowerCase())
|
||||||
},
|
},
|
||||||
|
|
|
@ -3,42 +3,42 @@
|
||||||
<a-form :form="form">
|
<a-form :form="form">
|
||||||
<a-form-item>
|
<a-form-item>
|
||||||
<div slot="label" style="display: inline-block">
|
<div slot="label" style="display: inline-block">
|
||||||
<span>角色列表</span>
|
<span>{{ $t('acl.roleList') }}</span>
|
||||||
<a-divider type="vertical" />
|
<a-divider type="vertical" />
|
||||||
<a-switch
|
<a-switch
|
||||||
style="display: inline-block"
|
style="display: inline-block"
|
||||||
checked-children="用户"
|
:checked-children="$t('user')"
|
||||||
un-checked-children="虚拟"
|
:un-checked-children="$t('acl.virtual')"
|
||||||
@change="handleRoleTypeChange"
|
@change="handleRoleTypeChange"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<el-select
|
<el-select
|
||||||
:style="{ width: '100%' }"
|
:style="{ width: '100%' }"
|
||||||
size="small"
|
size="small"
|
||||||
v-decorator="['roleIdList', { rules: [{ required: true, message: '请选择角色名称' }] }]"
|
v-decorator="['roleIdList', { rules: [{ required: true, message: $t('acl.role_placeholder2') }] }]"
|
||||||
multiple
|
multiple
|
||||||
filterable
|
filterable
|
||||||
placeholder="请选择角色名称,可多选!"
|
:placeholder="$t('acl.role_placeholder3')"
|
||||||
>
|
>
|
||||||
<el-option v-for="role in allRoles" :key="role.id" :value="role.id" :label="role.name"></el-option>
|
<el-option v-for="role in allRoles" :key="role.id" :value="role.id" :label="role.name"></el-option>
|
||||||
</el-select>
|
</el-select>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
|
|
||||||
<a-form-item label="权限列表">
|
<a-form-item :label="$t('acl.permissionList')">
|
||||||
<el-select
|
<el-select
|
||||||
:style="{ width: '100%' }"
|
:style="{ width: '100%' }"
|
||||||
size="small"
|
size="small"
|
||||||
name="permName"
|
name="permName"
|
||||||
v-decorator="['permName', { rules: [{ required: true, message: '请选择权限' }] }]"
|
v-decorator="['permName', { rules: [{ required: true, message: $t('acl.permission_placeholder') }] }]"
|
||||||
multiple
|
multiple
|
||||||
placeholder="请选择权限,可多选!"
|
:placeholder="$t('acl.permission_placeholder') "
|
||||||
>
|
>
|
||||||
<el-option v-for="perm in allPerms" :key="perm.name" :value="perm.name" :label="perm.name"></el-option>
|
<el-option v-for="perm in allPerms" :key="perm.name" :value="perm.name" :label="perm.name"></el-option>
|
||||||
</el-select>
|
</el-select>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<div class="custom-drawer-bottom-action">
|
<div class="custom-drawer-bottom-action">
|
||||||
<a-button @click="closeForm">取消</a-button>
|
<a-button @click="closeForm">{{ $t('cancel') }}</a-button>
|
||||||
<a-button @click="handleSubmit" type="primary" :loading="loading">确定</a-button>
|
<a-button @click="handleSubmit" type="primary" :loading="loading">{{ $t('confirm') }}</a-button>
|
||||||
</div>
|
</div>
|
||||||
</a-form>
|
</a-form>
|
||||||
</CustomDrawer>
|
</CustomDrawer>
|
||||||
|
@ -117,16 +117,12 @@ export default {
|
||||||
this.type = type
|
this.type = type
|
||||||
if (Array.isArray(record)) {
|
if (Array.isArray(record)) {
|
||||||
this.loadPerm(record[0]['resource_type_id'])
|
this.loadPerm(record[0]['resource_type_id'])
|
||||||
this.title = `${type === 'grant' ? '批量授权' : '批量权限回收'}`
|
this.title = `${type === 'grant' ? this.$t('acl.batchGrant') : this.$t('acl.batchRevoke')}`
|
||||||
} else {
|
} else {
|
||||||
this.title = `添加授权:${record.name}`
|
this.title = `${this.$t('acl.editPerm')}${record.name}`
|
||||||
this.loadPerm(record['resource_type_id'])
|
this.loadPerm(record['resource_type_id'])
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
// requestFailed(err) {
|
|
||||||
// const msg = ((err.response || {}).data || {}).message || '请求出现错误,请稍后再试'
|
|
||||||
// this.$message.error(`${msg}`)
|
|
||||||
// },
|
|
||||||
handleSubmit(e) {
|
handleSubmit(e) {
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
this.form.validateFields((err, values) => {
|
this.form.validateFields((err, values) => {
|
||||||
|
@ -136,16 +132,10 @@ export default {
|
||||||
this.loading = true
|
this.loading = true
|
||||||
if (!this.isGroup) {
|
if (!this.isGroup) {
|
||||||
if (Array.isArray(this.instance)) {
|
if (Array.isArray(this.instance)) {
|
||||||
// const promises = this.instance.map(item => {
|
|
||||||
// return setRoleResourcePerm(roleId, item.id, params)
|
|
||||||
// })
|
|
||||||
// Promise.all(promises).then(() => {
|
|
||||||
// this.$message.success('添加授权成功')
|
|
||||||
// })
|
|
||||||
if (this.type === 'grant') {
|
if (this.type === 'grant') {
|
||||||
setBatchRoleResourcePerm(roleId, { ...params, resource_ids: this.instance.map((a) => a.id) })
|
setBatchRoleResourcePerm(roleId, { ...params, resource_ids: this.instance.map((a) => a.id) })
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
this.$message.success('添加授权成功')
|
this.$message.success(this.$t('operateSuccess'))
|
||||||
})
|
})
|
||||||
.finally(() => {
|
.finally(() => {
|
||||||
this.loading = false
|
this.loading = false
|
||||||
|
@ -153,7 +143,7 @@ export default {
|
||||||
} else {
|
} else {
|
||||||
setBatchRoleResourceRevoke(roleId, { ...params, resource_ids: this.instance.map((a) => a.id) })
|
setBatchRoleResourceRevoke(roleId, { ...params, resource_ids: this.instance.map((a) => a.id) })
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
this.$message.success('批量权限回收成功')
|
this.$message.success(this.$t('operateSuccess'))
|
||||||
})
|
})
|
||||||
.finally(() => {
|
.finally(() => {
|
||||||
this.loading = false
|
this.loading = false
|
||||||
|
@ -162,7 +152,7 @@ export default {
|
||||||
} else {
|
} else {
|
||||||
setRoleResourcePerm(roleId, this.instance.id, params)
|
setRoleResourcePerm(roleId, this.instance.id, params)
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
this.$message.success('添加授权成功')
|
this.$message.success(this.$t('operateSuccess'))
|
||||||
})
|
})
|
||||||
.finally(() => {
|
.finally(() => {
|
||||||
this.loading = false
|
this.loading = false
|
||||||
|
@ -170,16 +160,10 @@ export default {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (Array.isArray(this.instance)) {
|
if (Array.isArray(this.instance)) {
|
||||||
// const promises = this.instance.map(item => {
|
|
||||||
// return setRoleResourceGroupPerm(roleId, item.id, params)
|
|
||||||
// })
|
|
||||||
// Promise.all(promises).then(() => {
|
|
||||||
// this.$message.success('添加授权成功')
|
|
||||||
// })
|
|
||||||
if (this.type === 'grant') {
|
if (this.type === 'grant') {
|
||||||
setBatchRoleResourceGroupPerm(roleId, { ...params, group_ids: this.instance.map((a) => a.id) })
|
setBatchRoleResourceGroupPerm(roleId, { ...params, group_ids: this.instance.map((a) => a.id) })
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
this.$message.success('添加授权成功')
|
this.$message.success(this.$t('operateSuccess'))
|
||||||
})
|
})
|
||||||
.finally(() => {
|
.finally(() => {
|
||||||
this.loading = false
|
this.loading = false
|
||||||
|
@ -190,7 +174,7 @@ export default {
|
||||||
group_ids: this.instance.map((a) => a.id),
|
group_ids: this.instance.map((a) => a.id),
|
||||||
})
|
})
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
this.$message.success('批量权限回收成功')
|
this.$message.success(this.$t('operateSuccess'))
|
||||||
})
|
})
|
||||||
.finally(() => {
|
.finally(() => {
|
||||||
this.loading = false
|
this.loading = false
|
||||||
|
@ -199,7 +183,7 @@ export default {
|
||||||
} else {
|
} else {
|
||||||
setRoleResourceGroupPerm(roleId, this.instance.id, params)
|
setRoleResourceGroupPerm(roleId, this.instance.id, params)
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
this.$message.success('添加授权成功')
|
this.$message.success(this.$t('operateSuccess'))
|
||||||
})
|
})
|
||||||
.finally(() => {
|
.finally(() => {
|
||||||
this.loading = false
|
this.loading = false
|
||||||
|
|
|
@ -1,32 +1,32 @@
|
||||||
<template>
|
<template>
|
||||||
<CustomDrawer
|
<CustomDrawer
|
||||||
:closable="false"
|
:closable="false"
|
||||||
:title="drawerTitle"
|
:title="$t('acl.addReourceType')"
|
||||||
:visible="drawerVisible"
|
:visible="drawerVisible"
|
||||||
@close="onClose"
|
@close="onClose"
|
||||||
placement="right"
|
placement="right"
|
||||||
width="500px"
|
width="500px"
|
||||||
>
|
>
|
||||||
<a-form :form="form" @submit="handleSubmit" :label-col="{ span: 6 }" :wrapper-col="{ span: 16 }">
|
<a-form :form="form" @submit="handleSubmit" :label-col="{ span: 6 }" :wrapper-col="{ span: 16 }">
|
||||||
<a-form-item label="类型名">
|
<a-form-item :label="$t('acl.typeName')">
|
||||||
<a-input
|
<a-input
|
||||||
name="name"
|
name="name"
|
||||||
placeholder="类型名称"
|
:placeholder="$t('acl.typeName')"
|
||||||
v-decorator="['name', { rules: [{ required: true, message: '请输入类型名' }] }]"
|
v-decorator="['name', { rules: [{ required: true, message: $t('acl.typeNameInput') }] }]"
|
||||||
/>
|
/>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
|
|
||||||
<a-form-item label="描述">
|
<a-form-item :label="$t('desc')">
|
||||||
<a-textarea
|
<a-textarea
|
||||||
placeholder="请输入描述信息..."
|
:placeholder="$t('acl.descInput')"
|
||||||
name="description"
|
name="description"
|
||||||
:rows="4"
|
:rows="4"
|
||||||
v-decorator="['description', { rules: [] }]"
|
v-decorator="['description', { rules: [] }]"
|
||||||
/>
|
/>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
|
|
||||||
<a-form-item label="权限">
|
<a-form-item :label="$t('acl.permission')">
|
||||||
<a-select mode="tags" v-model="perms" style="width: 100%" placeholder="请输入权限名..."> </a-select>
|
<a-select mode="tags" v-model="perms" style="width: 100%" :placeholder="$t('acl.permInput')"> </a-select>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
|
|
||||||
<a-form-item>
|
<a-form-item>
|
||||||
|
@ -34,8 +34,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('confirm') }}</a-button>
|
||||||
</div>
|
</div>
|
||||||
</a-form>
|
</a-form>
|
||||||
</CustomDrawer>
|
</CustomDrawer>
|
||||||
|
@ -48,7 +48,6 @@ export default {
|
||||||
name: 'ResourceForm',
|
name: 'ResourceForm',
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
drawerTitle: '新增资源类型',
|
|
||||||
drawerVisible: false,
|
drawerVisible: false,
|
||||||
perms: [],
|
perms: [],
|
||||||
}
|
}
|
||||||
|
@ -104,7 +103,7 @@ export default {
|
||||||
},
|
},
|
||||||
updateResourceType(id, data) {
|
updateResourceType(id, data) {
|
||||||
updateResourceTypeById(id, data).then((res) => {
|
updateResourceTypeById(id, data).then((res) => {
|
||||||
this.$message.success(`更新成功`)
|
this.$message.success(this.$t('updateSuccess'))
|
||||||
this.handleOk()
|
this.handleOk()
|
||||||
this.onClose()
|
this.onClose()
|
||||||
})
|
})
|
||||||
|
@ -113,17 +112,11 @@ export default {
|
||||||
|
|
||||||
createResourceType(data) {
|
createResourceType(data) {
|
||||||
addResourceType(data).then((res) => {
|
addResourceType(data).then((res) => {
|
||||||
this.$message.success(`添加成功`)
|
this.$message.success(this.$t('addSuccess'))
|
||||||
this.handleOk()
|
this.handleOk()
|
||||||
this.onClose()
|
this.onClose()
|
||||||
})
|
})
|
||||||
// .catch(err => this.requestFailed(err))
|
|
||||||
},
|
},
|
||||||
|
|
||||||
// requestFailed (err) {
|
|
||||||
// const msg = ((err.response || {}).data || {}).message || '请求出现错误,请稍后再试'
|
|
||||||
// this.$message.error(`${msg}`)
|
|
||||||
// }
|
|
||||||
},
|
},
|
||||||
watch: {},
|
watch: {},
|
||||||
props: {
|
props: {
|
||||||
|
|
|
@ -16,30 +16,30 @@
|
||||||
:loading="loading"
|
:loading="loading"
|
||||||
:height="`${windowHeight - 310}px`"
|
:height="`${windowHeight - 310}px`"
|
||||||
>
|
>
|
||||||
<vxe-column field="created_at" width="144px" title="操作时间"></vxe-column>
|
<vxe-column field="created_at" width="144px" :title="$t('acl.operateTime')"></vxe-column>
|
||||||
<vxe-column field="operate_uid" width="130px" title="操作员"></vxe-column>
|
<vxe-column field="operate_uid" width="130px" :title="$t('acl.operator')"></vxe-column>
|
||||||
<vxe-column field="operate_type" width="80px" title="操作">
|
<vxe-column field="operate_type" width="100px" :title="$t('operation')">
|
||||||
<template #default="{ row }">
|
<template #default="{ row }">
|
||||||
<a-tag :color="handleTagColor(row.operate_type)">
|
<a-tag :color="handleTagColor(row.operate_type)">
|
||||||
{{ operateTypeMap.get(row.operate_type) }}
|
{{ operateTypeMap.get(row.operate_type) }}
|
||||||
</a-tag>
|
</a-tag>
|
||||||
</template>
|
</template>
|
||||||
</vxe-column>
|
</vxe-column>
|
||||||
<vxe-column field="link_id" title="资源类型名">
|
<vxe-column field="link_id" :title="$t('acl.resourceTypeName')">
|
||||||
<template #default="{ row }">
|
<template #default="{ row }">
|
||||||
<span>
|
<span>
|
||||||
{{ row.current.name || row.origin.name }}
|
{{ row.current.name || row.origin.name }}
|
||||||
</span>
|
</span>
|
||||||
</template>
|
</template>
|
||||||
</vxe-column>
|
</vxe-column>
|
||||||
<vxe-column title="描述">
|
<vxe-column :title="$t('desc')">
|
||||||
<template #default="{ row }">
|
<template #default="{ row }">
|
||||||
<p>
|
<p>
|
||||||
{{ row.changeDescription }}
|
{{ row.changeDescription }}
|
||||||
</p>
|
</p>
|
||||||
</template>
|
</template>
|
||||||
</vxe-column>
|
</vxe-column>
|
||||||
<vxe-column field="source" width="100px" title="来源"></vxe-column>
|
<vxe-column field="source" width="100px" :title="$t('acl.source')"></vxe-column>
|
||||||
</vxe-table>
|
</vxe-table>
|
||||||
<pager
|
<pager
|
||||||
:current-page.sync="queryParams.page"
|
:current-page.sync="queryParams.page"
|
||||||
|
@ -93,40 +93,6 @@ export default {
|
||||||
checked: false,
|
checked: false,
|
||||||
tableData: [],
|
tableData: [],
|
||||||
app_id: this.$route.name.split('_')[0],
|
app_id: this.$route.name.split('_')[0],
|
||||||
resourceTableAttrList: [
|
|
||||||
{
|
|
||||||
alias: '日期',
|
|
||||||
is_choice: false,
|
|
||||||
name: 'datetime',
|
|
||||||
value_type: '3',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
alias: '操作员',
|
|
||||||
is_choice: true,
|
|
||||||
name: 'operate_uid',
|
|
||||||
value_type: '2',
|
|
||||||
choice_value: this.allUsers,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
alias: '操作',
|
|
||||||
is_choice: true,
|
|
||||||
name: 'operate_type',
|
|
||||||
value_type: '2',
|
|
||||||
choice_value: [{ 新建: 'create' }, { 修改: 'update' }, { 删除: 'delete' }],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
alias: '资源类型',
|
|
||||||
is_choice: true,
|
|
||||||
name: 'link_id',
|
|
||||||
value_type: '2',
|
|
||||||
choice_value: this.allResourceTypes,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
operateTypeMap: new Map([
|
|
||||||
['create', '新建'],
|
|
||||||
['update', '修改'],
|
|
||||||
['delete', '删除'],
|
|
||||||
]),
|
|
||||||
colorMap: new Map([
|
colorMap: new Map([
|
||||||
['create', 'green'],
|
['create', 'green'],
|
||||||
['update', 'orange'],
|
['update', 'orange'],
|
||||||
|
@ -155,12 +121,50 @@ export default {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
operateTypeMap() {
|
||||||
|
return new Map([
|
||||||
|
['create', this.$t('create')],
|
||||||
|
['update', this.$t('update')],
|
||||||
|
['delete', this.$t('delete')],
|
||||||
|
])
|
||||||
|
},
|
||||||
windowHeight() {
|
windowHeight() {
|
||||||
return this.$store.state.windowHeight
|
return this.$store.state.windowHeight
|
||||||
},
|
},
|
||||||
tableDataLength() {
|
tableDataLength() {
|
||||||
return this.tableData.length
|
return this.tableData.length
|
||||||
},
|
},
|
||||||
|
resourceTableAttrList() {
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
alias: this.$t('acl.date'),
|
||||||
|
is_choice: false,
|
||||||
|
name: 'datetime',
|
||||||
|
value_type: '3',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
alias: this.$t('acl.operator'),
|
||||||
|
is_choice: true,
|
||||||
|
name: 'operate_uid',
|
||||||
|
value_type: '2',
|
||||||
|
choice_value: this.allUsers,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
alias: this.$t('operation'),
|
||||||
|
is_choice: true,
|
||||||
|
name: 'operate_type',
|
||||||
|
value_type: '2',
|
||||||
|
choice_value: [{ [this.$t('create')]: 'create' }, { [this.$t('update')]: 'update' }, { [this.$t('delete')]: 'delete' }],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
alias: this.$t('acl.resourceType'),
|
||||||
|
is_choice: true,
|
||||||
|
name: 'link_id',
|
||||||
|
value_type: '2',
|
||||||
|
choice_value: this.allResourceTypes,
|
||||||
|
},
|
||||||
|
]
|
||||||
|
},
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
async getTable(queryParams) {
|
async getTable(queryParams) {
|
||||||
|
@ -236,7 +240,9 @@ export default {
|
||||||
switch (operate_type) {
|
switch (operate_type) {
|
||||||
// create
|
// create
|
||||||
case 'create': {
|
case 'create': {
|
||||||
item.changeDescription = `新增资源类型:${item.current.name}\n描述:${item.current.description}\n权限:${item.extra.permission_ids.current}`
|
item.changeDescription = `${this.$t('acl.addReourceType')}:${item.current.name}\n${this.$t('desc')}:${
|
||||||
|
item.current.description
|
||||||
|
}\n${this.$t('acl.permission')}: ${item.extra.permission_ids.current}`
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
case 'update': {
|
case 'update': {
|
||||||
|
@ -246,10 +252,10 @@ export default {
|
||||||
const oldVal = item.origin[key]
|
const oldVal = item.origin[key]
|
||||||
if (!_.isEqual(newVal, oldVal) && key !== 'updated_at' && key !== 'deleted_at' && key !== 'created_at') {
|
if (!_.isEqual(newVal, oldVal) && key !== 'updated_at' && key !== 'deleted_at' && key !== 'created_at') {
|
||||||
if (oldVal === null || oldVal === '') {
|
if (oldVal === null || oldVal === '') {
|
||||||
const str = ` 【 ${key} : 改为 ${newVal} 】 \n`
|
const str = ` 【 ${key} : -> ${newVal} 】 \n`
|
||||||
item.changeDescription += str
|
item.changeDescription += str
|
||||||
} else {
|
} else {
|
||||||
const str = ` 【 ${key} : 由 ${oldVal} 改为 ${newVal} 】 \n`
|
const str = ` 【 ${key} : ${oldVal} -> ${newVal} 】 \n`
|
||||||
item.changeDescription += str
|
item.changeDescription += str
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -257,13 +263,13 @@ export default {
|
||||||
const currentPerms = item.extra.permission_ids.current
|
const currentPerms = item.extra.permission_ids.current
|
||||||
const originPerms = item.extra.permission_ids.origin
|
const originPerms = item.extra.permission_ids.origin
|
||||||
if (!_.isEqual(currentPerms, originPerms)) {
|
if (!_.isEqual(currentPerms, originPerms)) {
|
||||||
item.changeDescription += ` 【 permission_ids : 由 ${originPerms} 改为 ${currentPerms} 】 `
|
item.changeDescription += ` 【 permission_ids : ${originPerms} -> ${currentPerms} 】 `
|
||||||
}
|
}
|
||||||
if (!item.changeDescription) item.changeDescription = '没有修改'
|
if (!item.changeDescription) item.changeDescription = this.$t('acl.noChange')
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
case 'delete': {
|
case 'delete': {
|
||||||
item.changeDescription = `删除资源类型:${item.origin.name}\n描述:${item.origin.description}\n权限:${item.extra.permission_ids.origin}`
|
item.changeDescription = `${this.$t('acl.deleteResourceType')}${item.origin.name}\n${this.$t('desc')}: ${item.origin.description}\n${this.$t('acl.permission')}: ${item.extra.permission_ids.origin}`
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,12 +2,12 @@
|
||||||
<CustomDrawer
|
<CustomDrawer
|
||||||
width="800px"
|
width="800px"
|
||||||
placement="left"
|
placement="left"
|
||||||
title="资源列表"
|
:title="$t('acl.resourceList')"
|
||||||
@close="handleCancel"
|
@close="handleCancel"
|
||||||
:visible="visible"
|
:visible="visible"
|
||||||
:hasFooter="false"
|
:hasFooter="false"
|
||||||
>
|
>
|
||||||
<a-form-item label="资源类型" :label-col="{ span: 2 }" :wrapper-col="{ span: 14 }">
|
<a-form-item :label="$t('acl.resourceType')" :label-col="{ span: 4 }" :wrapper-col="{ span: 14 }">
|
||||||
<a-select v-model="typeSelected" style="width:100%" @change="refresh">
|
<a-select v-model="typeSelected" style="width:100%" @change="refresh">
|
||||||
<a-select-option v-for="type in resourceTypes" :value="type.id" :key="type.id">{{ type.name }}</a-select-option>
|
<a-select-option v-for="type in resourceTypes" :value="type.id" :key="type.id">{{ type.name }}</a-select-option>
|
||||||
</a-select>
|
</a-select>
|
||||||
|
@ -22,7 +22,7 @@
|
||||||
>
|
>
|
||||||
<vxe-column
|
<vxe-column
|
||||||
field="name"
|
field="name"
|
||||||
title="资源名"
|
:title="$t('acl.resourceName')"
|
||||||
width="30%"
|
width="30%"
|
||||||
:filters="[{ data: '' }]"
|
:filters="[{ data: '' }]"
|
||||||
:filter-method="filterNameMethod"
|
:filter-method="filterNameMethod"
|
||||||
|
@ -30,7 +30,7 @@
|
||||||
>
|
>
|
||||||
<template #header="{ column }">
|
<template #header="{ column }">
|
||||||
<span>{{ column.title }}</span>
|
<span>{{ column.title }}</span>
|
||||||
<a-tooltip title="复制资源名">
|
<a-tooltip :title="$t('acl.copyResource')">
|
||||||
<a-icon @click="copyResourceName" class="resource-user-form-copy" theme="filled" type="copy" />
|
<a-icon @click="copyResourceName" class="resource-user-form-copy" theme="filled" type="copy" />
|
||||||
</a-tooltip>
|
</a-tooltip>
|
||||||
</template>
|
</template>
|
||||||
|
@ -48,7 +48,7 @@
|
||||||
</template>
|
</template>
|
||||||
</template>
|
</template>
|
||||||
</vxe-column>
|
</vxe-column>
|
||||||
<vxe-column field="permissions" title="权限列表" width="70%">
|
<vxe-column field="permissions" :title="$t('acl.permissionList')" width="70%">
|
||||||
<template #default="{row}">
|
<template #default="{row}">
|
||||||
<a-tag color="cyan" v-for="(r, index) in row.permissions" :key="index">{{ r }}</a-tag>
|
<a-tag color="cyan" v-for="(r, index) in row.permissions" :key="index">{{ r }}</a-tag>
|
||||||
</template>
|
</template>
|
||||||
|
@ -58,69 +58,6 @@
|
||||||
<p style="font-size: 14px; line-height: 17px; color: rgba(0, 0, 0, 0.6)">暂无数据</p>
|
<p style="font-size: 14px; line-height: 17px; color: rgba(0, 0, 0, 0.6)">暂无数据</p>
|
||||||
</template>
|
</template>
|
||||||
</vxe-table>
|
</vxe-table>
|
||||||
<!-- <a-table
|
|
||||||
:columns="columns"
|
|
||||||
:dataSource="records"
|
|
||||||
:rowKey="record => record.id"
|
|
||||||
:pagination="false"
|
|
||||||
ref="rTable"
|
|
||||||
size="middle"
|
|
||||||
:scroll="{ y: 300 }"
|
|
||||||
> -->
|
|
||||||
<!-- <div slot="filterDropdown" slot-scope="{ setSelectedKeys, selectedKeys, confirm, clearFilters, column }" class="custom-filter-dropdown">
|
|
||||||
<a-input
|
|
||||||
v-ant-ref="c => searchInput = c"
|
|
||||||
:placeholder="` ${column.title}`"
|
|
||||||
:value="selectedKeys[0]"
|
|
||||||
@change="e => setSelectedKeys(e.target.value ? [e.target.value] : [])"
|
|
||||||
@pressEnter="() => handleSearch(selectedKeys, confirm, column)"
|
|
||||||
style="width: 188px; margin-bottom: 8px; display: block;"
|
|
||||||
/>
|
|
||||||
<a-button
|
|
||||||
type="primary"
|
|
||||||
@click="() => handleSearch(selectedKeys, confirm, column)"
|
|
||||||
icon="search"
|
|
||||||
size="small"
|
|
||||||
style="width: 90px; margin-right: 8px"
|
|
||||||
>搜索</a-button>
|
|
||||||
<a-button
|
|
||||||
@click="() => handleReset(clearFilters, column)"
|
|
||||||
size="small"
|
|
||||||
style="width: 90px"
|
|
||||||
>重置</a-button>
|
|
||||||
</div>
|
|
||||||
<a-icon slot="filterIcon" slot-scope="filtered" type="search" :style="{ color: filtered ? '#108ee9' : undefined }" />
|
|
||||||
|
|
||||||
<template slot="nameSearchRender" slot-scope="text">
|
|
||||||
<span v-if="columnSearchText.name">
|
|
||||||
<template v-for="(fragment, i) in text.toString().split(new RegExp(`(?<=${columnSearchText.name})|(?=${columnSearchText.name})`, 'i'))">
|
|
||||||
<mark v-if="fragment.toLowerCase() === columnSearchText.name.toLowerCase()" :key="i" class="highlight">{{ fragment }}</mark>
|
|
||||||
<template v-else>{{ fragment }}</template>
|
|
||||||
</template>
|
|
||||||
</span>
|
|
||||||
<template v-else>{{ text }}</template>
|
|
||||||
</template> -->
|
|
||||||
<!-- <template slot="permissions" slot-scope="record">
|
|
||||||
<a-tag color="cyan" v-for="(r, index) in record" :key="index">{{ r }}</a-tag>
|
|
||||||
</template>
|
|
||||||
</a-table> -->
|
|
||||||
<!-- <div
|
|
||||||
:style="{
|
|
||||||
position: 'absolute',
|
|
||||||
left: 0,
|
|
||||||
bottom: 0,
|
|
||||||
width: '100%',
|
|
||||||
borderTop: '1px solid #e9e9e9',
|
|
||||||
padding: '10px 16px',
|
|
||||||
background: '#fff',
|
|
||||||
textAlign: 'right',
|
|
||||||
}"
|
|
||||||
>
|
|
||||||
<a-button :style="{marginRight: '8px'}" @click="handleCancel">
|
|
||||||
取消
|
|
||||||
</a-button>
|
|
||||||
<a-button @click="handleOk" type="primary">确定</a-button>
|
|
||||||
</div> -->
|
|
||||||
</CustomDrawer>
|
</CustomDrawer>
|
||||||
</template>
|
</template>
|
||||||
<script>
|
<script>
|
||||||
|
@ -141,33 +78,6 @@ export default {
|
||||||
name: '',
|
name: '',
|
||||||
},
|
},
|
||||||
filterName: '',
|
filterName: '',
|
||||||
// columns: [
|
|
||||||
// {
|
|
||||||
// title: '资源名',
|
|
||||||
// field: 'name',
|
|
||||||
// sorter: false,
|
|
||||||
// width: '30%',
|
|
||||||
// // scopedSlots: {
|
|
||||||
// // customRender: 'nameSearchRender',
|
|
||||||
// // filterDropdown: 'filterDropdown',
|
|
||||||
// // filterIcon: 'filterIcon'
|
|
||||||
// // },
|
|
||||||
// // onFilter: (value, record) => record.name && record.name.toLowerCase().includes(value.toLowerCase()),
|
|
||||||
// // onFilterDropdownVisibleChange: (visible) => {
|
|
||||||
// // if (visible) {
|
|
||||||
// // setTimeout(() => {
|
|
||||||
// // this.searchInput.focus()
|
|
||||||
// // }, 0)
|
|
||||||
// // }
|
|
||||||
// // }
|
|
||||||
// },
|
|
||||||
// {
|
|
||||||
// title: '权限列表',
|
|
||||||
// field: 'permissions',
|
|
||||||
// width: '70%',
|
|
||||||
// slots: { default: 'permissions_default' },
|
|
||||||
// },
|
|
||||||
// ],
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
@ -184,14 +94,6 @@ export default {
|
||||||
this.rid = record.id
|
this.rid = record.id
|
||||||
this.refresh()
|
this.refresh()
|
||||||
},
|
},
|
||||||
// handleSearch(selectedKeys, confirm, column) {
|
|
||||||
// confirm()
|
|
||||||
// this.columnSearchText[column.dataIndex] = selectedKeys[0]
|
|
||||||
// },
|
|
||||||
// handleReset(clearFilters, column) {
|
|
||||||
// clearFilters()
|
|
||||||
// this.columnSearchText[column.dataIndex] = ''
|
|
||||||
// },
|
|
||||||
loadResourceTypes() {
|
loadResourceTypes() {
|
||||||
this.resourceTypes = []
|
this.resourceTypes = []
|
||||||
const appId = this.$route.name.split('_')[0]
|
const appId = this.$route.name.split('_')[0]
|
||||||
|
@ -204,7 +106,6 @@ export default {
|
||||||
this.typeSelected = null
|
this.typeSelected = null
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
// .catch(err => this.$httpError(err))
|
|
||||||
},
|
},
|
||||||
handleOk() {
|
handleOk() {
|
||||||
this.visible = false
|
this.visible = false
|
||||||
|
@ -217,7 +118,6 @@ export default {
|
||||||
}).then(res => {
|
}).then(res => {
|
||||||
this.records = res.resources
|
this.records = res.resources
|
||||||
})
|
})
|
||||||
// .catch(err=>this.$httpError(err))
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
handleCancel() {
|
handleCancel() {
|
||||||
|
@ -238,7 +138,7 @@ export default {
|
||||||
.join('\n')
|
.join('\n')
|
||||||
|
|
||||||
this.copy(val, () => {
|
this.copy(val, () => {
|
||||||
this.$message.success('复制成功')
|
this.$message.success(this.$t('copySuccess'))
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
copy(value, cb) {
|
copy(value, cb) {
|
||||||
|
|
|
@ -8,40 +8,29 @@
|
||||||
width="500px"
|
width="500px"
|
||||||
>
|
>
|
||||||
<a-form :form="form" :label-col="{ span: 6 }" :wrapper-col="{ span: 16 }" @submit="handleSubmit">
|
<a-form :form="form" :label-col="{ span: 6 }" :wrapper-col="{ span: 16 }" @submit="handleSubmit">
|
||||||
<a-form-item label="角色名">
|
<a-form-item :label="$t('acl.role')">
|
||||||
<a-input
|
<a-input
|
||||||
name="name"
|
name="name"
|
||||||
placeholder="角色名"
|
:placeholder="$t('acl.role_placeholder1')"
|
||||||
v-decorator="['name', { rules: [{ required: true, message: '请输入角色名' }] }]"
|
v-decorator="['name', { rules: [{ required: true, message: $t('acl.role_placeholder1') }] }]"
|
||||||
/>
|
/>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-form-item v-if="$route.name.split('_')[0] !== 'acl'" label="密码">
|
<a-form-item v-if="$route.name.split('_')[0] !== 'acl'" :label="$t('acl.password')">
|
||||||
<a-input name="password" placeholder="密码" v-decorator="['password', { rules: [{ required: false }] }]" />
|
<a-input name="password" :placeholder="$t('acl.password')" v-decorator="['password', { rules: [{ required: false }] }]" />
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<!-- <a-form-item label="继承自">
|
<a-form-item :label="$t('acl.inheritedFrom')">
|
||||||
<a-select
|
|
||||||
showSearch
|
|
||||||
v-model="selectedParents"
|
|
||||||
:filterOption="false"
|
|
||||||
placeholder="可选择继承角色"
|
|
||||||
mode="multiple"
|
|
||||||
>
|
|
||||||
<a-select-option v-for="role in scrollData" :key="role.id">{{ role.name }}</a-select-option>
|
|
||||||
</a-select>
|
|
||||||
</a-form-item> -->
|
|
||||||
<a-form-item label="继承自">
|
|
||||||
<el-select
|
<el-select
|
||||||
:style="{ width: '100%' }"
|
:style="{ width: '100%' }"
|
||||||
size="small"
|
size="small"
|
||||||
v-model="selectedParents"
|
v-model="selectedParents"
|
||||||
multiple
|
multiple
|
||||||
filterable
|
filterable
|
||||||
placeholder="可选择继承角色"
|
:placeholder="$t('acl.selectedParents')"
|
||||||
>
|
>
|
||||||
<el-option v-for="role in allRoles" :key="role.id" :value="role.id" :label="role.name"></el-option>
|
<el-option v-for="role in allRoles" :key="role.id" :value="role.id" :label="role.name"></el-option>
|
||||||
</el-select>
|
</el-select>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-form-item label="是否应用管理员">
|
<a-form-item :label="$t('acl.isAppAdmin')">
|
||||||
<a-switch
|
<a-switch
|
||||||
@change="onChange"
|
@change="onChange"
|
||||||
name="is_app_admin"
|
name="is_app_admin"
|
||||||
|
@ -53,8 +42,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('confirm') }}</a-button>
|
||||||
</div>
|
</div>
|
||||||
</a-form>
|
</a-form>
|
||||||
</CustomDrawer>
|
</CustomDrawer>
|
||||||
|
@ -93,7 +82,7 @@ export default {
|
||||||
// return option.componentOptions.children[0].text.toLowerCase().indexOf(input.toLowerCase()) >= 0
|
// return option.componentOptions.children[0].text.toLowerCase().indexOf(input.toLowerCase()) >= 0
|
||||||
// },
|
// },
|
||||||
handleCreate() {
|
handleCreate() {
|
||||||
this.drawerTitle = '新增角色'
|
this.drawerTitle = this.$t('acl.addRole')
|
||||||
this.drawerVisible = true
|
this.drawerVisible = true
|
||||||
},
|
},
|
||||||
onClose() {
|
onClose() {
|
||||||
|
@ -107,7 +96,7 @@ export default {
|
||||||
},
|
},
|
||||||
|
|
||||||
handleEdit(record) {
|
handleEdit(record) {
|
||||||
this.drawerTitle = `编辑:${record.name}`
|
this.drawerTitle = `${this.$t('edit')}: ${record.name}`
|
||||||
this.drawerVisible = true
|
this.drawerVisible = true
|
||||||
this.current_id = record.id
|
this.current_id = record.id
|
||||||
const _parents = this.id2parents[record.id]
|
const _parents = this.id2parents[record.id]
|
||||||
|
@ -142,7 +131,7 @@ export default {
|
||||||
updateRole(id, data) {
|
updateRole(id, data) {
|
||||||
this.updateParents(id)
|
this.updateParents(id)
|
||||||
updateRoleById(id, { ...data, app_id: this.$route.name.split('_')[0] }).then((res) => {
|
updateRoleById(id, { ...data, app_id: this.$route.name.split('_')[0] }).then((res) => {
|
||||||
this.$message.success(`更新成功`)
|
this.$message.success(this.$t('updateSuccess'))
|
||||||
this.handleOk()
|
this.handleOk()
|
||||||
this.onClose()
|
this.onClose()
|
||||||
})
|
})
|
||||||
|
@ -151,7 +140,7 @@ export default {
|
||||||
|
|
||||||
createRole(data) {
|
createRole(data) {
|
||||||
addRole({ ...data, app_id: this.$route.name.split('_')[0] }).then((res) => {
|
addRole({ ...data, app_id: this.$route.name.split('_')[0] }).then((res) => {
|
||||||
this.$message.success(`添加成功`)
|
this.$message.success(this.$t('addSuccess'))
|
||||||
this.updateParents(res.id)
|
this.updateParents(res.id)
|
||||||
this.handleOk()
|
this.handleOk()
|
||||||
this.onClose()
|
this.onClose()
|
||||||
|
@ -171,16 +160,9 @@ export default {
|
||||||
child_ids: [id],
|
child_ids: [id],
|
||||||
app_id: this.$route.name.split('_')[0],
|
app_id: this.$route.name.split('_')[0],
|
||||||
})
|
})
|
||||||
// addParentRole(id, item, { app_id: this.$route.name.split('_')[0] })
|
|
||||||
// .catch(err => this.requestFailed(err))
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
// requestFailed(err) {
|
|
||||||
// console.log(err)
|
|
||||||
// const msg = ((err.response || {}).data || {}).message || '请求出现错误,请稍后再试'
|
|
||||||
// this.$message.error(`${msg}`)
|
|
||||||
// },
|
|
||||||
},
|
},
|
||||||
watch: {},
|
watch: {},
|
||||||
props: {
|
props: {
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
ref="child"
|
ref="child"
|
||||||
:attrList="roleTableAttrList"
|
:attrList="roleTableAttrList"
|
||||||
:hasSwitch="true"
|
:hasSwitch="true"
|
||||||
switchValue="角色关系"
|
:switchValue="$t('acl.roleRelation')"
|
||||||
@onSwitchChange="onSwitchChange"
|
@onSwitchChange="onSwitchChange"
|
||||||
@search="handleSearch"
|
@search="handleSearch"
|
||||||
@searchFormReset="searchFormReset"
|
@searchFormReset="searchFormReset"
|
||||||
|
@ -19,16 +19,16 @@
|
||||||
resizable
|
resizable
|
||||||
:height="`${windowHeight - 310}px`"
|
:height="`${windowHeight - 310}px`"
|
||||||
>
|
>
|
||||||
<vxe-column field="created_at" width="144px" title="操作时间"></vxe-column>
|
<vxe-column field="created_at" width="144px" :title="$t('acl.operateTime')"></vxe-column>
|
||||||
<vxe-column field="operate_uid" title="操作员" width="130px"></vxe-column>
|
<vxe-column field="operate_uid" :title="$t('acl.operator')" width="130px"></vxe-column>
|
||||||
<vxe-column field="operate_type" title="操作" width="112px">
|
<vxe-column field="operate_type" :title="$t('operation')" width="112px">
|
||||||
<template #default="{ row }">
|
<template #default="{ row }">
|
||||||
<template>
|
<template>
|
||||||
<a-tag :color="handleTagColor(row.operate_type)">{{ operateTypeMap.get(row.operate_type) }}</a-tag>
|
<a-tag :color="handleTagColor(row.operate_type)">{{ operateTypeMap.get(row.operate_type) }}</a-tag>
|
||||||
</template>
|
</template>
|
||||||
</template>
|
</template>
|
||||||
</vxe-column>
|
</vxe-column>
|
||||||
<vxe-column :title="checked ? '角色' : '角色'">
|
<vxe-column :title="checked ? $t('acl.role2') : $t('acl.role2')">
|
||||||
<template #default="{ row }">
|
<template #default="{ row }">
|
||||||
<template v-if="!checked">
|
<template v-if="!checked">
|
||||||
<a-tag color="blue">{{ row.current.name || row.origin.name }}</a-tag>
|
<a-tag color="blue">{{ row.current.name || row.origin.name }}</a-tag>
|
||||||
|
@ -40,7 +40,7 @@
|
||||||
</template>
|
</template>
|
||||||
</template>
|
</template>
|
||||||
</vxe-column>
|
</vxe-column>
|
||||||
<vxe-column :title="checked ? '继承自' : '管理员'" :width="checked ? '350px' : '80px'">
|
<vxe-column :title="checked ? $t('acl.inheritedFrom') : $t('acl.admin')" :width="checked ? '350px' : '80px'">
|
||||||
<template #default="{ row }">
|
<template #default="{ row }">
|
||||||
<template v-if="!checked">
|
<template v-if="!checked">
|
||||||
<a-icon type="check" v-if="row.current.is_app_admin" />
|
<a-icon type="check" v-if="row.current.is_app_admin" />
|
||||||
|
@ -52,14 +52,14 @@
|
||||||
</template>
|
</template>
|
||||||
</template>
|
</template>
|
||||||
</vxe-column>
|
</vxe-column>
|
||||||
<vxe-column title="描述" v-if="!checked">
|
<vxe-column :title="$t('desc')" v-if="!checked">
|
||||||
<template #default="{ row }">
|
<template #default="{ row }">
|
||||||
<p>
|
<p>
|
||||||
{{ row.description }}
|
{{ row.description }}
|
||||||
</p>
|
</p>
|
||||||
</template>
|
</template>
|
||||||
</vxe-column>
|
</vxe-column>
|
||||||
<vxe-column field="source" title="来源" width="100px"></vxe-column>
|
<vxe-column field="source" :title="$t('acl.source')" width="100px"></vxe-column>
|
||||||
</vxe-table>
|
</vxe-table>
|
||||||
<pager
|
<pager
|
||||||
:current-page.sync="queryParams.page"
|
:current-page.sync="queryParams.page"
|
||||||
|
@ -105,13 +105,6 @@ export default {
|
||||||
checked: false,
|
checked: false,
|
||||||
tableData: [],
|
tableData: [],
|
||||||
app_id: this.$route.name.split('_')[0],
|
app_id: this.$route.name.split('_')[0],
|
||||||
operateTypeMap: new Map([
|
|
||||||
['create', '新建'],
|
|
||||||
['delete', '删除'],
|
|
||||||
['update', '修改'],
|
|
||||||
['role_relation_add', '添加角色关系'],
|
|
||||||
['role_relation_delete', '删除角色关系'],
|
|
||||||
]),
|
|
||||||
colorMap: new Map([
|
colorMap: new Map([
|
||||||
['create', 'green'],
|
['create', 'green'],
|
||||||
['delete', 'red'],
|
['delete', 'red'],
|
||||||
|
@ -127,42 +120,53 @@ export default {
|
||||||
start: '',
|
start: '',
|
||||||
end: '',
|
end: '',
|
||||||
},
|
},
|
||||||
roleTableAttrList: [
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
operateTypeMap() {
|
||||||
|
return new Map([
|
||||||
|
['create', this.$t('create')],
|
||||||
|
['update', this.$t('update')],
|
||||||
|
['delete', this.$t('delete')],
|
||||||
|
['role_relation_add', this.$t('acl.roleRelationAdd')],
|
||||||
|
['role_relation_delete', this.$t('acl.roleRelationDelete')],
|
||||||
|
])
|
||||||
|
},
|
||||||
|
windowHeight() {
|
||||||
|
return this.$store.state.windowHeight
|
||||||
|
},
|
||||||
|
tableDataLength() {
|
||||||
|
return this.tableData.length
|
||||||
|
},
|
||||||
|
roleTableAttrList() {
|
||||||
|
return [
|
||||||
{
|
{
|
||||||
alias: '日期',
|
alias: this.$t('acl.date'),
|
||||||
is_choice: false,
|
is_choice: false,
|
||||||
name: 'datetime',
|
name: 'datetime',
|
||||||
value_type: '3',
|
value_type: '3',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
alias: '操作员',
|
alias: this.$t('acl.operator'),
|
||||||
is_choice: true,
|
is_choice: true,
|
||||||
name: 'operate_uid',
|
name: 'operate_uid',
|
||||||
value_type: '2',
|
value_type: '2',
|
||||||
choice_value: this.allUsers,
|
choice_value: this.allUsers,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
alias: '操作',
|
alias: this.$t('operation'),
|
||||||
is_choice: true,
|
is_choice: true,
|
||||||
name: 'operate_type',
|
name: 'operate_type',
|
||||||
value_type: '2',
|
value_type: '2',
|
||||||
choice_value: [
|
choice_value: [
|
||||||
{ 新建: 'create' },
|
{ [this.$t('create')]: 'create' },
|
||||||
{ 修改: 'update' },
|
{ [this.$t('update')]: 'update' },
|
||||||
{ 删除: 'delete' },
|
{ [this.$t('delete')]: 'delete' },
|
||||||
{ 添加角色关系: 'role_relation_add' },
|
{ [this.$t('acl.roleRelationAdd')]: 'role_relation_add' },
|
||||||
{ 删除角色关系: 'role_relation_delete' },
|
{ [this.$t('acl.roleRelationDelete')]: 'role_relation_delete' },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
],
|
]
|
||||||
}
|
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
windowHeight() {
|
|
||||||
return this.$store.state.windowHeight
|
|
||||||
},
|
|
||||||
tableDataLength() {
|
|
||||||
return this.tableData.length
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
async created() {
|
async created() {
|
||||||
|
@ -273,7 +277,7 @@ export default {
|
||||||
switch (operate_type) {
|
switch (operate_type) {
|
||||||
// create
|
// create
|
||||||
case 'create': {
|
case 'create': {
|
||||||
item.description = `新建角色:${item.current.name}`
|
item.description = `${this.$t('acl.addRole')}${item.current.name}`
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
case 'update': {
|
case 'update': {
|
||||||
|
@ -283,15 +287,15 @@ export default {
|
||||||
const oldVal = item.origin[key]
|
const oldVal = item.origin[key]
|
||||||
if (!_.isEqual(newVal, oldVal) && key !== 'updated_at' && key !== 'deleted_at' && key !== 'created_at') {
|
if (!_.isEqual(newVal, oldVal) && key !== 'updated_at' && key !== 'deleted_at' && key !== 'created_at') {
|
||||||
if (oldVal === null) {
|
if (oldVal === null) {
|
||||||
const str = ` 【 ${key} : 改为 ${newVal} 】 `
|
const str = ` 【 ${key} : -> ${newVal} 】 `
|
||||||
item.description += str
|
item.description += str
|
||||||
} else {
|
} else {
|
||||||
const str = ` 【 ${key} : 由 ${oldVal} 改为 ${newVal} 】 `
|
const str = ` 【 ${key} : ${oldVal} -> ${newVal} 】 `
|
||||||
item.description += str
|
item.description += ` 【 ${key} : ${oldVal} -> ${newVal} 】 `
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!item.description) item.description = '没有修改'
|
if (!item.description) item.description = this.$t('acl.noChange')
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
case 'delete': {
|
case 'delete': {
|
||||||
|
@ -321,7 +325,7 @@ export default {
|
||||||
resourceMap.forEach((value, key) => {
|
resourceMap.forEach((value, key) => {
|
||||||
permsArr.push(`${id2resources[key].name}:${value}`)
|
permsArr.push(`${id2resources[key].name}:${value}`)
|
||||||
})
|
})
|
||||||
item.description = `继承者:${child_ids}\n继承自:${parent_ids}\n涉及资源及权限:\n${permsArr.join(`\n`)}`
|
item.description = `${this.$t('acl.heir')}:${child_ids}\n${this.$t('acl.inheritedFrom')}:${parent_ids}\n${this.$t('acl.involvingRP')}:\n${permsArr.join(`\n`)}`
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,7 +19,7 @@
|
||||||
@popupScroll="loadMoreData(attr.name, $event)"
|
@popupScroll="loadMoreData(attr.name, $event)"
|
||||||
@search="(value) => fetchData(value, attr.name)"
|
@search="(value) => fetchData(value, attr.name)"
|
||||||
v-model="queryParams[attr.name]"
|
v-model="queryParams[attr.name]"
|
||||||
placeholder="请选择"
|
:placeholder="$t('placeholder2')"
|
||||||
v-if="attr.is_choice"
|
v-if="attr.is_choice"
|
||||||
show-search
|
show-search
|
||||||
:filter-option="filterOption"
|
:filter-option="filterOption"
|
||||||
|
@ -38,7 +38,6 @@
|
||||||
@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="['开始时间', '结束时间']"
|
|
||||||
: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')],
|
||||||
|
@ -67,7 +66,7 @@
|
||||||
@popupScroll="loadMoreData(item.name, $event)"
|
@popupScroll="loadMoreData(item.name, $event)"
|
||||||
@search="(value) => fetchData(value, item.name)"
|
@search="(value) => fetchData(value, item.name)"
|
||||||
v-model="queryParams[item.name]"
|
v-model="queryParams[item.name]"
|
||||||
placeholder="请选择"
|
:placeholder="$t('placeholder2')"
|
||||||
v-if="item.is_choice"
|
v-if="item.is_choice"
|
||||||
show-search
|
show-search
|
||||||
:filter-option="filterOption"
|
:filter-option="filterOption"
|
||||||
|
@ -85,7 +84,7 @@
|
||||||
: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('acl.startAt'), $t('acl.endAt')]"
|
||||||
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,
|
||||||
|
@ -107,13 +106,13 @@
|
||||||
v-model="checked"
|
v-model="checked"
|
||||||
/>
|
/>
|
||||||
<a-button :style="{ marginLeft: '8px' }" type="primary" html-type="submit" @click="handleSearch">
|
<a-button :style="{ marginLeft: '8px' }" 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 >= 5">
|
<a :style="{ marginLeft: '8px', fontSize: '12px' }" @click="toggle" v-if="attrList.length >= 5">
|
||||||
{{ expand ? '隐藏' : '展开' }} <a-icon :type="expand ? 'up' : 'down'" />
|
{{ expand ? $t('expand') : $t('expand') }} <a-icon :type="expand ? 'up' : 'down'" />
|
||||||
</a>
|
</a>
|
||||||
</a-col>
|
</a-col>
|
||||||
</a-row>
|
</a-row>
|
||||||
|
|
|
@ -2,30 +2,30 @@
|
||||||
<CustomDrawer
|
<CustomDrawer
|
||||||
@close="handleClose"
|
@close="handleClose"
|
||||||
width="500"
|
width="500"
|
||||||
:title="`${triggerId ? '修改' : '新建'}触发器`"
|
:title="`${triggerId ? $t('update') : $t('create')}${$t('acl.trigger')}`"
|
||||||
:visible="visible"
|
:visible="visible"
|
||||||
:maskClosable="false"
|
:maskClosable="false"
|
||||||
>
|
>
|
||||||
<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('name')">
|
||||||
<a-input size="large" v-decorator="['name', { rules: [{ required: true, message: '请输入触发器名' }] }]">
|
<a-input size="large" v-decorator="['name', { rules: [{ required: true, message: $t('acl.triggerNameInput') }] }]">
|
||||||
</a-input>
|
</a-input>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-form-item label="资源名">
|
<a-form-item :label="$t('acl.resourceName')">
|
||||||
<a-input size="large" v-decorator="['wildcard']" placeholder="优先正则模式(次通配符)"> </a-input>
|
<a-input size="large" v-decorator="['wildcard']" :placeholder="$t('acl.triggerTips1')"> </a-input>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-form-item label="创建人">
|
<a-form-item :label="$t('acl.creator')">
|
||||||
<el-select :style="{ width: '100%' }" filterable multiple v-decorator="['uid']">
|
<el-select :style="{ width: '100%' }" filterable multiple v-decorator="['uid']">
|
||||||
<template v-for="role in roles">
|
<template v-for="role in roles">
|
||||||
<el-option v-if="role.uid" :key="role.id" :value="role.uid" :label="role.name">{{ role.name }}</el-option>
|
<el-option v-if="role.uid" :key="role.id" :value="role.uid" :label="role.name">{{ role.name }}</el-option>
|
||||||
</template>
|
</template>
|
||||||
</el-select>
|
</el-select>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-form-item label="资源类型">
|
<a-form-item :label="$t('acl.resourceType')">
|
||||||
<el-select
|
<el-select
|
||||||
:style="{ width: '100%' }"
|
:style="{ width: '100%' }"
|
||||||
@change="handleRTChange"
|
@change="handleRTChange"
|
||||||
v-decorator="['resource_type_id', { rules: [{ required: true, message: '请选择资源类型' }] }]"
|
v-decorator="['resource_type_id', { rules: [{ required: true, message: $t('acl.pleaseSelectType') }] }]"
|
||||||
>
|
>
|
||||||
<el-option
|
<el-option
|
||||||
v-for="resourceType in resourceTypeList"
|
v-for="resourceType in resourceTypeList"
|
||||||
|
@ -34,25 +34,25 @@
|
||||||
:label="resourceType.name"
|
:label="resourceType.name"
|
||||||
></el-option>
|
></el-option>
|
||||||
</el-select>
|
</el-select>
|
||||||
<a-tooltip title="查看正则匹配结果">
|
<a-tooltip :title="$t('acl.viewMatchResult')">
|
||||||
<a class="trigger-form-pattern" @click="handlePattern"><a-icon type="eye"/></a>
|
<a class="trigger-form-pattern" @click="handlePattern"><a-icon type="eye"/></a>
|
||||||
</a-tooltip>
|
</a-tooltip>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-form-item label="角色">
|
<a-form-item :label="$t('acl.role2')">
|
||||||
<el-select
|
<el-select
|
||||||
:style="{ width: '100%' }"
|
:style="{ width: '100%' }"
|
||||||
filterable
|
filterable
|
||||||
multiple
|
multiple
|
||||||
v-decorator="['roles', { rules: [{ required: true, message: '请选择角色' }] }]"
|
v-decorator="['roles', { rules: [{ required: true, message: $t('acl.role_placeholder2') }] }]"
|
||||||
>
|
>
|
||||||
<el-option v-for="role in roles" :key="role.id" :value="role.id" :label="role.name"></el-option>
|
<el-option v-for="role in roles" :key="role.id" :value="role.id" :label="role.name"></el-option>
|
||||||
</el-select>
|
</el-select>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-form-item label="权限">
|
<a-form-item :label="$t('acl.permission')">
|
||||||
<el-select
|
<el-select
|
||||||
:style="{ width: '100%' }"
|
:style="{ width: '100%' }"
|
||||||
multiple
|
multiple
|
||||||
v-decorator="['permissions', { rules: [{ required: true, message: '请选择权限' }] }]"
|
v-decorator="['permissions', { rules: [{ required: true, message: $t('acl.permission_placeholder') }] }]"
|
||||||
>
|
>
|
||||||
<el-option
|
<el-option
|
||||||
v-for="perm in selectResourceTypePerms"
|
v-for="perm in selectResourceTypePerms"
|
||||||
|
@ -62,13 +62,13 @@
|
||||||
></el-option>
|
></el-option>
|
||||||
</el-select>
|
</el-select>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-form-item label="启用/禁用">
|
<a-form-item :label="$t('acl.enable')/$t('acl.disable')">
|
||||||
<a-switch v-decorator="['enabled', { rules: [], valuePropName: 'checked', initialValue: true }]" />
|
<a-switch v-decorator="['enabled', { rules: [], valuePropName: 'checked', initialValue: true }]" />
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
</a-form>
|
</a-form>
|
||||||
<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" type="primary">提交</a-button>
|
<a-button @click="handleSubmit" type="primary">{{ $t('submit') }}</a-button>
|
||||||
</div>
|
</div>
|
||||||
<TriggerPattern ref="triggerPattern" :roles="roles" />
|
<TriggerPattern ref="triggerPattern" :roles="roles" />
|
||||||
</CustomDrawer>
|
</CustomDrawer>
|
||||||
|
@ -159,13 +159,13 @@ export default {
|
||||||
if (this.triggerId) {
|
if (this.triggerId) {
|
||||||
updateTrigger(this.triggerId, { ...values, app_id: this.app_id }).then((res) => {
|
updateTrigger(this.triggerId, { ...values, app_id: this.app_id }).then((res) => {
|
||||||
this.visible = false
|
this.visible = false
|
||||||
this.$message.success('修改成功!')
|
this.$message.success(this.$t('updateSuccess'))
|
||||||
this.$emit('refresh')
|
this.$emit('refresh')
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
addTrigger({ ...values, app_id: this.app_id }).then((res) => {
|
addTrigger({ ...values, app_id: this.app_id }).then((res) => {
|
||||||
this.visible = false
|
this.visible = false
|
||||||
this.$message.success('创建成功!')
|
this.$message.success(this.$t('addSuccess'))
|
||||||
this.$emit('refresh')
|
this.$emit('refresh')
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,23 +16,23 @@
|
||||||
resizable
|
resizable
|
||||||
:height="`${windowHeight - 310}px`"
|
:height="`${windowHeight - 310}px`"
|
||||||
>
|
>
|
||||||
<vxe-column field="created_at" width="144px" title="操作时间"></vxe-column>
|
<vxe-column field="created_at" width="144px" :title="$t('acl.operateTime')"></vxe-column>
|
||||||
<vxe-column field="operate_uid" width="130px" title="操作员"></vxe-column>
|
<vxe-column field="operate_uid" width="130px" :title="$t('acl.operator')"></vxe-column>
|
||||||
<vxe-column field="operate_type" width="80px" title="操作">
|
<vxe-column field="operate_type" width="100px" :title="$t('operation')">
|
||||||
<template #default="{ row }">
|
<template #default="{ row }">
|
||||||
<a-tag :color="handleTagColor(row.operate_type)">
|
<a-tag :color="handleTagColor(row.operate_type)">
|
||||||
{{ operateTypeMap.get(row.operate_type) }}
|
{{ operateTypeMap.get(row.operate_type) }}
|
||||||
</a-tag>
|
</a-tag>
|
||||||
</template>
|
</template>
|
||||||
</vxe-column>
|
</vxe-column>
|
||||||
<vxe-column field="trigger_id" width="250px" title="触发器">
|
<vxe-column field="trigger_id" width="250px" :title="$t('acl.trigger')">
|
||||||
<template #default="{ row }">
|
<template #default="{ row }">
|
||||||
<span>
|
<span>
|
||||||
{{ row.current.name || row.origin.name }}
|
{{ row.current.name || row.origin.name }}
|
||||||
</span>
|
</span>
|
||||||
</template>
|
</template>
|
||||||
</vxe-column>
|
</vxe-column>
|
||||||
<vxe-column title="描述">
|
<vxe-column :title="$t('desc')">
|
||||||
<template #default="{ row }">
|
<template #default="{ row }">
|
||||||
<p>
|
<p>
|
||||||
{{ row.changeDescription }}
|
{{ row.changeDescription }}
|
||||||
|
@ -95,13 +95,6 @@ export default {
|
||||||
app_id: this.$route.name.split('_')[0],
|
app_id: this.$route.name.split('_')[0],
|
||||||
loading: true,
|
loading: true,
|
||||||
tableData: [],
|
tableData: [],
|
||||||
operateTypeMap: new Map([
|
|
||||||
['create', '新建'],
|
|
||||||
['update', '修改'],
|
|
||||||
['delete', '删除'],
|
|
||||||
['trigger_apply', '应用'],
|
|
||||||
['trigger_cancel', '取消'],
|
|
||||||
]),
|
|
||||||
colorMap: new Map([
|
colorMap: new Map([
|
||||||
['create', 'green'],
|
['create', 'green'],
|
||||||
['delete', 'red'],
|
['delete', 'red'],
|
||||||
|
@ -109,41 +102,6 @@ export default {
|
||||||
['trigger_apply', 'green'],
|
['trigger_apply', 'green'],
|
||||||
['trigger_cancel', 'red'],
|
['trigger_cancel', 'red'],
|
||||||
]),
|
]),
|
||||||
triggerTableAttrList: [
|
|
||||||
{
|
|
||||||
alias: '日期',
|
|
||||||
is_choice: false,
|
|
||||||
name: 'datetime',
|
|
||||||
value_type: '3',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
alias: '操作员',
|
|
||||||
is_choice: true,
|
|
||||||
name: 'operate_uid',
|
|
||||||
value_type: '2',
|
|
||||||
choice_value: this.allUsers,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
alias: '操作',
|
|
||||||
is_choice: true,
|
|
||||||
name: 'operate_type',
|
|
||||||
value_type: '2',
|
|
||||||
choice_value: [
|
|
||||||
{ 新建: 'create' },
|
|
||||||
{ 修改: 'update' },
|
|
||||||
{ 删除: 'delete' },
|
|
||||||
{ 应用: 'trigger_apply' },
|
|
||||||
{ 取消: 'trigger_cancel' },
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
alias: '触发器',
|
|
||||||
is_choice: true,
|
|
||||||
name: 'trigger_id',
|
|
||||||
value_type: '2',
|
|
||||||
choice_value: this.allTriggers,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
queryParams: {
|
queryParams: {
|
||||||
page: 1,
|
page: 1,
|
||||||
page_size: 50,
|
page_size: 50,
|
||||||
|
@ -164,12 +122,58 @@ export default {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
operateTypeMap() {
|
||||||
|
return new Map([
|
||||||
|
['create', this.$t('create')],
|
||||||
|
['update', this.$t('update')],
|
||||||
|
['delete', this.$t('delete')],
|
||||||
|
['trigger_apply', this.$t('acl.apply')],
|
||||||
|
['trigger_cancel', this.$t('cancel')],
|
||||||
|
])
|
||||||
|
},
|
||||||
windowHeight() {
|
windowHeight() {
|
||||||
return this.$store.state.windowHeight
|
return this.$store.state.windowHeight
|
||||||
},
|
},
|
||||||
tableDataLength() {
|
tableDataLength() {
|
||||||
return this.tableData.length
|
return this.tableData.length
|
||||||
},
|
},
|
||||||
|
triggerTableAttrList() {
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
alias: this.$t('acl.date'),
|
||||||
|
is_choice: false,
|
||||||
|
name: 'datetime',
|
||||||
|
value_type: '3',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
alias: this.$t('acl.operator'),
|
||||||
|
is_choice: true,
|
||||||
|
name: 'operate_uid',
|
||||||
|
value_type: '2',
|
||||||
|
choice_value: this.allUsers,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
alias: this.$t('operation'),
|
||||||
|
is_choice: true,
|
||||||
|
name: 'operate_type',
|
||||||
|
value_type: '2',
|
||||||
|
choice_value: [
|
||||||
|
{ [this.$t('create')]: 'create' },
|
||||||
|
{ [this.$t('update')]: 'update' },
|
||||||
|
{ [this.$t('delete')]: 'delete' },
|
||||||
|
{ [this.$t('acl.apply')]: 'trigger_apply' },
|
||||||
|
{ [this.$t('cancel')]: 'trigger_cancel' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
alias: this.$t('acl.trigger'),
|
||||||
|
is_choice: true,
|
||||||
|
name: 'trigger_id',
|
||||||
|
value_type: '2',
|
||||||
|
choice_value: this.allTriggers,
|
||||||
|
},
|
||||||
|
]
|
||||||
|
},
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
async getTable(queryParams) {
|
async getTable(queryParams) {
|
||||||
|
@ -220,9 +224,9 @@ export default {
|
||||||
const str = item.current.roles
|
const str = item.current.roles
|
||||||
const newArr = str.slice(1, str.length - 1).split(', ')
|
const newArr = str.slice(1, str.length - 1).split(', ')
|
||||||
const newStr = newArr.map((i) => this.allRolesMap.get(Number(i))).join(',')
|
const newStr = newArr.map((i) => this.allRolesMap.get(Number(i))).join(',')
|
||||||
item.changeDescription = `新增触发器:${item.current.name}\n资源类型:${this.allResourceTypesMap.get(
|
item.changeDescription = `${this.$t('acl.addTrigger')}: ${item.current.name}\n${this.$t('acl.resourceType')}: :${this.allResourceTypesMap.get(
|
||||||
item.current.resource_type_id
|
item.current.resource_type_id
|
||||||
)},资源名:${item.current.wildcard},角色:[${newStr}]\n权限:${item.current.permissions}\n状态:${
|
)},this.$t('acl.resourceName'):${item.current.wildcard},${this.$t('acl.role2')}: [${newStr}]\n${this.$t('acl.permission')}: ${item.current.permissions}\n${this.$t('status')}: ${
|
||||||
item.current.enabled
|
item.current.enabled
|
||||||
}`
|
}`
|
||||||
break
|
break
|
||||||
|
@ -234,24 +238,24 @@ export default {
|
||||||
const oldVal = item.origin[key]
|
const oldVal = item.origin[key]
|
||||||
if (!_.isEqual(newVal, oldVal) && key !== 'updated_at' && key !== 'deleted_at' && key !== 'created_at') {
|
if (!_.isEqual(newVal, oldVal) && key !== 'updated_at' && key !== 'deleted_at' && key !== 'created_at') {
|
||||||
if (oldVal === null) {
|
if (oldVal === null) {
|
||||||
const str = ` 【 ${key} : 改为 ${newVal} 】 `
|
const str = ` 【 ${key} : -> ${newVal} 】 `
|
||||||
item.changeDescription += str
|
item.changeDescription += str
|
||||||
} else {
|
} else {
|
||||||
const str = ` 【 ${key} : 由 ${oldVal} 改为 ${newVal} 】 `
|
const str = ` 【 ${key} : ${oldVal} -> ${newVal} 】 `
|
||||||
item.changeDescription += str
|
item.changeDescription += ` 【 ${key} : ${oldVal} -> ${newVal} 】 `
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!item.changeDescription) item.changeDescription = '没有修改'
|
if (!item.changeDescription) item.changeDescription = this.$t('acl.noChange')
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
case 'delete': {
|
case 'delete': {
|
||||||
const str = item.origin.roles
|
const str = item.origin.roles
|
||||||
const newArr = str.slice(1, str.length - 1).split(', ')
|
const newArr = str.slice(1, str.length - 1).split(', ')
|
||||||
const newStr = newArr.map((i) => this.allRolesMap.get(Number(i))).join(',')
|
const newStr = newArr.map((i) => this.allRolesMap.get(Number(i))).join(',')
|
||||||
item.changeDescription = `删除触发器:${item.origin.name}\n资源类型:${this.allResourceTypesMap.get(
|
item.changeDescription = `${this.$t('acl.deleteTrigger')}: ${item.origin.name}\n${this.$t('acl.resourceType')}: :${this.allResourceTypesMap.get(
|
||||||
item.origin.resource_type_id
|
item.origin.resource_type_id
|
||||||
)},资源名:${item.origin.wildcard},角色:[${newStr}]\n权限:${item.origin.permissions}\n状态:${
|
)},this.$t('acl.resourceName'):${item.origin.wildcard},${this.$t('acl.role2')}: [${newStr}]\n${this.$t('acl.permission')}: ${item.origin.permissions}\n${this.$t('status')}: ${
|
||||||
item.origin.enabled
|
item.origin.enabled
|
||||||
}`
|
}`
|
||||||
break
|
break
|
||||||
|
@ -260,9 +264,9 @@ export default {
|
||||||
const str = item.current.roles
|
const str = item.current.roles
|
||||||
const newArr = str.slice(1, str.length - 1).split(', ')
|
const newArr = str.slice(1, str.length - 1).split(', ')
|
||||||
const newStr = newArr.map((i) => this.allRolesMap.get(Number(i))).join(',')
|
const newStr = newArr.map((i) => this.allRolesMap.get(Number(i))).join(',')
|
||||||
item.changeDescription = `应用触发器:${item.current.name}\n资源类型:${this.allResourceTypesMap.get(
|
item.changeDescription = `${this.$t('acl.applyTrigger')}: ${item.current.name}\n${this.$t('acl.resourceType')}: :${this.allResourceTypesMap.get(
|
||||||
item.current.resource_type_id
|
item.current.resource_type_id
|
||||||
)},资源名:${item.current.wildcard},角色:[${newStr}]\n权限:${item.current.permissions}\n状态:${
|
)},this.$t('acl.resourceName'):${item.current.wildcard},${this.$t('acl.role2')}: [${newStr}]\n${this.$t('acl.permission')}: ${item.current.permissions}\n${this.$t('status')}: ${
|
||||||
item.current.enabled
|
item.current.enabled
|
||||||
}`
|
}`
|
||||||
break
|
break
|
||||||
|
@ -271,9 +275,9 @@ export default {
|
||||||
const str = item.current.roles
|
const str = item.current.roles
|
||||||
const newArr = str.slice(1, str.length - 1).split(', ')
|
const newArr = str.slice(1, str.length - 1).split(', ')
|
||||||
const newStr = newArr.map((i) => this.allRolesMap.get(Number(i))).join(',')
|
const newStr = newArr.map((i) => this.allRolesMap.get(Number(i))).join(',')
|
||||||
item.changeDescription = `取消触发器:${item.current.name}\n资源类型:${this.allResourceTypesMap.get(
|
item.changeDescription = `${this.$t('acl.cancelTrigger')}: ${item.current.name}\n${this.$t('acl.resourceType')}: :${this.allResourceTypesMap.get(
|
||||||
item.current.resource_type_id
|
item.current.resource_type_id
|
||||||
)},资源名:${item.current.wildcard},角色:[${newStr}]\n权限:${item.current.permissions}\n状态:${
|
)},this.$t('acl.resourceName'):${item.current.wildcard},${this.$t('acl.role2')}: [${newStr}]\n${this.$t('acl.permission')}: ${item.current.permissions}\n${this.$t('status')}: ${
|
||||||
item.current.enabled
|
item.current.enabled
|
||||||
}`
|
}`
|
||||||
break
|
break
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<template>
|
<template>
|
||||||
<CustomDrawer
|
<CustomDrawer
|
||||||
:hasFooter="false"
|
:hasFooter="false"
|
||||||
title="正则匹配结果"
|
:title="$t('acl.viewMatchResult')"
|
||||||
:visible="patternVisible"
|
:visible="patternVisible"
|
||||||
width="500"
|
width="500"
|
||||||
@close="
|
@close="
|
||||||
|
@ -16,16 +16,16 @@
|
||||||
class="ops-stripe-table"
|
class="ops-stripe-table"
|
||||||
:data="tableData"
|
:data="tableData"
|
||||||
:max-height="`${windowHeight - 110}px`">
|
:max-height="`${windowHeight - 110}px`">
|
||||||
<vxe-table-column field="name" title="资源名"></vxe-table-column>
|
<vxe-table-column field="name" :title="$t('acl.resourceName')"></vxe-table-column>
|
||||||
<vxe-table-column field="uid" title="创建人">
|
<vxe-table-column field="uid" :title="$t('acl.creator')">
|
||||||
<template #default="{row}">
|
<template #default="{row}">
|
||||||
{{ getRoleName(row.uid) }}
|
{{ getRoleName(row.uid) }}
|
||||||
</template>
|
</template>
|
||||||
</vxe-table-column>
|
</vxe-table-column>
|
||||||
<vxe-table-column field="created_at" title="创建时间"></vxe-table-column>
|
<vxe-table-column field="created_at" :title="$t('created_at')"></vxe-table-column>
|
||||||
<template slot="empty">
|
<template slot="empty">
|
||||||
<img :src="require(`@/assets/data_empty.png`)" />
|
<img :src="require(`@/assets/data_empty.png`)" />
|
||||||
<p style="font-size: 14px; line-height: 17px; color: rgba(0, 0, 0, 0.6)">暂无数据</p>
|
<p style="font-size: 14px; line-height: 17px; color: rgba(0, 0, 0, 0.6)">{{ $t('noData') }}</p>
|
||||||
</template>
|
</template>
|
||||||
</vxe-table>
|
</vxe-table>
|
||||||
</CustomDrawer>
|
</CustomDrawer>
|
||||||
|
|
|
@ -8,33 +8,38 @@
|
||||||
width="500px"
|
width="500px"
|
||||||
>
|
>
|
||||||
<a-form :form="form" @submit="handleSubmit" :label-col="{ span: 6 }" :wrapper-col="{ span: 16 }">
|
<a-form :form="form" @submit="handleSubmit" :label-col="{ span: 6 }" :wrapper-col="{ span: 16 }">
|
||||||
<a-form-item label="用户名(英文)">
|
<a-form-item :label="$t('acl.username')">
|
||||||
<a-input
|
<a-input
|
||||||
name="username"
|
name="username"
|
||||||
placeholder="英文名"
|
:placeholder="$t('acl.username_placeholder')"
|
||||||
v-decorator="['username', { rules: [{ required: true, message: '请输入用户名' }] }]"
|
v-decorator="['username', { rules: [{ required: true, message: $t('acl.username_placeholder') }] }]"
|
||||||
/>
|
/>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-form-item label="中文名">
|
<a-form-item :label="$t('acl.nickname')">
|
||||||
<a-input name="nickname" v-decorator="['nickname', { rules: [] }]" />
|
<a-input
|
||||||
|
name="nickname"
|
||||||
|
:placeholder="$t('acl.nickname_placeholder')"
|
||||||
|
v-decorator="['nickname', { rules: [] }]"
|
||||||
|
/>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-form-item label="密码">
|
<a-form-item :label="$t('acl.password')">
|
||||||
<a-input
|
<a-input
|
||||||
type="password"
|
type="password"
|
||||||
name="password"
|
name="password"
|
||||||
v-decorator="['password', { rules: [{ required: true, message: '请输入密码' }] }]"
|
:placeholder="$t('acl.password_placeholder')"
|
||||||
|
v-decorator="['password', { rules: [{ required: true, message: $t('acl.password_placeholder') }] }]"
|
||||||
/>
|
/>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
|
|
||||||
<a-form-item label="部门">
|
<a-form-item :label="$t('acl.department')">
|
||||||
<a-input name="department" v-decorator="['department', { rules: [] }]" />
|
<a-input name="department" v-decorator="['department', { rules: [] }]" />
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
|
|
||||||
<a-form-item label="小组">
|
<a-form-item :label="$t('acl.group')">
|
||||||
<a-input name="catalog" v-decorator="['catalog', { rules: [] }]" />
|
<a-input name="catalog" v-decorator="['catalog', { rules: [] }]" />
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
|
|
||||||
<a-form-item label="邮箱">
|
<a-form-item :label="$t('acl.email')">
|
||||||
<a-input
|
<a-input
|
||||||
name="email"
|
name="email"
|
||||||
v-decorator="[
|
v-decorator="[
|
||||||
|
@ -43,11 +48,11 @@
|
||||||
rules: [
|
rules: [
|
||||||
{
|
{
|
||||||
type: 'email',
|
type: 'email',
|
||||||
message: '请输入正确的邮箱!',
|
message: $t('acl.email_placeholder'),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
required: true,
|
required: true,
|
||||||
message: '请输入邮箱',
|
message: $t('acl.email_placeholder'),
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
@ -55,14 +60,14 @@
|
||||||
/>
|
/>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
|
|
||||||
<a-form-item label="手机号码">
|
<a-form-item :label="$t('acl.mobile')">
|
||||||
<a-input
|
<a-input
|
||||||
name="mobile"
|
name="mobile"
|
||||||
v-decorator="['mobile', { rules: [{ message: '请输入正确的手机号码', pattern: /^1\d{10}$/ }] }]"
|
v-decorator="['mobile', { rules: [{ message: $t('acl.mobileTips'), pattern: /^1\d{10}$/ }] }]"
|
||||||
/>
|
/>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
|
|
||||||
<a-form-item label="是否锁定">
|
<a-form-item :label="$t('acl.isBlock')">
|
||||||
<a-switch @change="onChange" name="block" v-decorator="['block', { rules: [], valuePropName: 'checked' }]" />
|
<a-switch @change="onChange" name="block" v-decorator="['block', { rules: [], valuePropName: 'checked' }]" />
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
|
|
||||||
|
@ -71,8 +76,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('confirm') }}</a-button>
|
||||||
</div>
|
</div>
|
||||||
</a-form>
|
</a-form>
|
||||||
</CustomDrawer>
|
</CustomDrawer>
|
||||||
|
@ -85,7 +90,6 @@ export default {
|
||||||
name: 'AttributeForm',
|
name: 'AttributeForm',
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
drawerTitle: '新增用户',
|
|
||||||
drawerVisible: false,
|
drawerVisible: false,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -94,7 +98,11 @@ export default {
|
||||||
this.form = this.$form.createForm(this)
|
this.form = this.$form.createForm(this)
|
||||||
},
|
},
|
||||||
|
|
||||||
computed: {},
|
computed: {
|
||||||
|
drawerTitle() {
|
||||||
|
return this.$t('acl.addUser')
|
||||||
|
},
|
||||||
|
},
|
||||||
mounted() {},
|
mounted() {},
|
||||||
methods: {
|
methods: {
|
||||||
handleCreate() {
|
handleCreate() {
|
||||||
|
@ -142,7 +150,7 @@ export default {
|
||||||
},
|
},
|
||||||
updateUser(attrId, data) {
|
updateUser(attrId, data) {
|
||||||
updateUserById(attrId, data).then((res) => {
|
updateUserById(attrId, data).then((res) => {
|
||||||
this.$message.success(`更新成功`)
|
this.$message.success(this.$t('updateSuccess'))
|
||||||
this.handleOk()
|
this.handleOk()
|
||||||
this.onClose()
|
this.onClose()
|
||||||
})
|
})
|
||||||
|
@ -151,17 +159,11 @@ export default {
|
||||||
|
|
||||||
createUser(data) {
|
createUser(data) {
|
||||||
addUser(data).then((res) => {
|
addUser(data).then((res) => {
|
||||||
this.$message.success(`添加成功`)
|
this.$message.success(this.$t('addSuccess'))
|
||||||
this.handleOk()
|
this.handleOk()
|
||||||
this.onClose()
|
this.onClose()
|
||||||
})
|
})
|
||||||
// .catch(err => this.requestFailed(err))
|
|
||||||
},
|
},
|
||||||
|
|
||||||
// requestFailed (err) {
|
|
||||||
// const msg = ((err.response || {}).data || {}).message || '请求出现错误,请稍后再试'
|
|
||||||
// this.$message.error(`${msg}`)
|
|
||||||
// }
|
|
||||||
},
|
},
|
||||||
watch: {},
|
watch: {},
|
||||||
props: {
|
props: {
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
<template>
|
<template>
|
||||||
<CustomDrawer :closable="true" :visible="visible" width="500px" @close="handleClose" title="组用户">
|
<CustomDrawer :closable="true" :visible="visible" width="500px" @close="handleClose" :title="$t('acl.groupUser')">
|
||||||
<a-form-item label="添加用户" :label-col="{ span: 4 }" :wrapper-col="{ span: 20 }">
|
<a-form-item :label="$t('acl.addUser')" :label-col="{ span: 4 }" :wrapper-col="{ span: 20 }">
|
||||||
<a-row>
|
<a-row>
|
||||||
<a-col span="15">
|
<a-col span="15">
|
||||||
<el-select v-model="selectedChildrenRole" multiple collapse-tags size="small" filterable>
|
<el-select v-model="selectedChildrenRole" multiple collapse-tags size="small" filterable>
|
||||||
|
@ -14,14 +14,14 @@
|
||||||
</el-select>
|
</el-select>
|
||||||
</a-col>
|
</a-col>
|
||||||
<a-col span="5" offset="1">
|
<a-col span="5" offset="1">
|
||||||
<a-button style="display: inline-block" @click="handleAddRole">确定</a-button>
|
<a-button style="display: inline-block" @click="handleAddRole">{{ $t('confirm') }}</a-button>
|
||||||
</a-col>
|
</a-col>
|
||||||
</a-row>
|
</a-row>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-card>
|
<a-card>
|
||||||
<a-row :gutter="24" v-for="(record, index) in records" :key="record.id" :style="{ marginBottom: '5px' }">
|
<a-row :gutter="24" v-for="(record, index) in records" :key="record.id" :style="{ marginBottom: '5px' }">
|
||||||
<a-col :span="20">{{ index + 1 }}、{{ record.nickname }}</a-col>
|
<a-col :span="20">{{ index + 1 }}、{{ record.nickname }}</a-col>
|
||||||
<a-col :span="4"><a-button type="danger" size="small" @click="handleRevokeUser(record)">移除</a-button></a-col>
|
<a-col :span="4"><a-button type="danger" size="small" @click="handleRevokeUser(record)">{{ $t('acl.remove') }}</a-button></a-col>
|
||||||
</a-row>
|
</a-row>
|
||||||
</a-card>
|
</a-card>
|
||||||
</CustomDrawer>
|
</CustomDrawer>
|
||||||
|
@ -63,34 +63,22 @@ export default {
|
||||||
this.visible = true
|
this.visible = true
|
||||||
this.loadRecords(roleId)
|
this.loadRecords(roleId)
|
||||||
},
|
},
|
||||||
// filterOption(input, option) {
|
|
||||||
// return option.componentOptions.children[0].text.toLowerCase().indexOf(input.toLowerCase()) >= 0
|
|
||||||
// },
|
|
||||||
async handleAddRole() {
|
async handleAddRole() {
|
||||||
// await this.selectedChildrenRole.forEach(item => {
|
|
||||||
// addParentRole(item, this.roleId, { app_id: this.$route.name.split('_')[0] }).then(res => {
|
|
||||||
// this.$message.success('添加成功')
|
|
||||||
// })
|
|
||||||
// // .catch(err=>{
|
|
||||||
// // this.$httpError(err)
|
|
||||||
// // })
|
|
||||||
|
|
||||||
// })
|
|
||||||
await addBatchParentRole(this.roleId, {
|
await addBatchParentRole(this.roleId, {
|
||||||
child_ids: this.selectedChildrenRole,
|
child_ids: this.selectedChildrenRole,
|
||||||
app_id: this.$route.name.split('_')[0],
|
app_id: this.$route.name.split('_')[0],
|
||||||
})
|
})
|
||||||
this.loadRecords(this.roleId)
|
this.loadRecords(this.roleId)
|
||||||
this.$message.success('添加完成')
|
this.$message.success(this.$t('addSuccess'))
|
||||||
this.selectedChildrenRole = []
|
this.selectedChildrenRole = []
|
||||||
},
|
},
|
||||||
handleRevokeUser(record) {
|
handleRevokeUser(record) {
|
||||||
const that = this
|
const that = this
|
||||||
this.$confirm({
|
this.$confirm({
|
||||||
content: '是否确定要移除该用户',
|
content: that.$t('acl.deleteUserConfirm'),
|
||||||
onOk() {
|
onOk() {
|
||||||
delParentRole(record.role.id, that.roleId, { app_id: that.$route.name.split('_')[0] }).then((res) => {
|
delParentRole(record.role.id, that.roleId, { app_id: that.$route.name.split('_')[0] }).then((res) => {
|
||||||
that.$message.success('删除成功!')
|
that.$message.success(that.$t('deleteSuccess'))
|
||||||
that.loadRecords(that.roleId)
|
that.loadRecords(that.roleId)
|
||||||
})
|
})
|
||||||
// .catch(err=>that.$httpError(err))
|
// .catch(err=>that.$httpError(err))
|
||||||
|
|
|
@ -1,19 +1,19 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="acl-operation-history">
|
<div class="acl-operation-history">
|
||||||
<a-tabs default-active-key="1">
|
<a-tabs default-active-key="1">
|
||||||
<a-tab-pane key="1" tab="权限变更">
|
<a-tab-pane key="1" :tab="$t('acl.permissionChange')">
|
||||||
<permisson-table></permisson-table>
|
<permisson-table></permisson-table>
|
||||||
</a-tab-pane>
|
</a-tab-pane>
|
||||||
<a-tab-pane key="2" tab="角色变更">
|
<a-tab-pane key="2" :tab="$t('acl.roleChange')">
|
||||||
<role-history-table></role-history-table>
|
<role-history-table></role-history-table>
|
||||||
</a-tab-pane>
|
</a-tab-pane>
|
||||||
<a-tab-pane key="3" tab="资源变更">
|
<a-tab-pane key="3" :tab="$t('acl.resourceChange')">
|
||||||
<resource-history-table></resource-history-table>
|
<resource-history-table></resource-history-table>
|
||||||
</a-tab-pane>
|
</a-tab-pane>
|
||||||
<a-tab-pane key="4" tab="资源类型变更">
|
<a-tab-pane key="4" :tab="$t('acl.resourceTypeChange')">
|
||||||
<resource-type-history-table></resource-type-history-table>
|
<resource-type-history-table></resource-type-history-table>
|
||||||
</a-tab-pane>
|
</a-tab-pane>
|
||||||
<a-tab-pane key="5" tab="触发器变更">
|
<a-tab-pane key="5" :tab="$t('acl.triggerChange')">
|
||||||
<trigger-history-table></trigger-history-table>
|
<trigger-history-table></trigger-history-table>
|
||||||
</a-tab-pane>
|
</a-tab-pane>
|
||||||
</a-tabs>
|
</a-tabs>
|
||||||
|
|
|
@ -22,22 +22,22 @@
|
||||||
:height="`${windowHeight - windowHeightMinus}px`"
|
:height="`${windowHeight - windowHeightMinus}px`"
|
||||||
:scroll-y="{ enabled: false }"
|
:scroll-y="{ enabled: false }"
|
||||||
>
|
>
|
||||||
<vxe-column field="created_at" width="144px" title="操作时间">
|
<vxe-column field="created_at" width="144px" :title="$t('acl.operateTime')">
|
||||||
<template #default="{ row }">
|
<template #default="{ row }">
|
||||||
<span>{{ row.deleted_at || row.updated_at || row.created_at }}</span>
|
<span>{{ row.deleted_at || row.updated_at || row.created_at }}</span>
|
||||||
</template>
|
</template>
|
||||||
</vxe-column>
|
</vxe-column>
|
||||||
<vxe-column field="operate_uid" width="130px" title="操作员"></vxe-column>
|
<vxe-column field="operate_uid" width="130px" :title="$t('acl.operator')"></vxe-column>
|
||||||
<vxe-column field="operate_type" width="80px" title="操作">
|
<vxe-column field="operate_type" width="100px" :title="$t('operation')">
|
||||||
<template #default="{ row }">
|
<template #default="{ row }">
|
||||||
<a-tag :color="row.operate_type === 'grant' ? 'green' : 'red'">{{
|
<a-tag :color="row.operate_type === 'grant' ? 'green' : 'red'">{{
|
||||||
operateTypeMap.get(row.operate_type)
|
operateTypeMap.get(row.operate_type)
|
||||||
}}</a-tag>
|
}}</a-tag>
|
||||||
</template>
|
</template>
|
||||||
</vxe-column>
|
</vxe-column>
|
||||||
<vxe-column field="rid" title="用户"></vxe-column>
|
<vxe-column field="rid" :title="$t('user')"></vxe-column>
|
||||||
<vxe-column field="resource_type_id" title="资源类型"></vxe-column>
|
<vxe-column field="resource_type_id" :title="$t('acl.resourceType')"></vxe-column>
|
||||||
<vxe-column field="resources" title="资源">
|
<vxe-column field="resources" :title="$t('acl.resource')">
|
||||||
<template #default="{ row }">
|
<template #default="{ row }">
|
||||||
<template v-if="row.resource_ids.length > 0">
|
<template v-if="row.resource_ids.length > 0">
|
||||||
<a-tooltip placement="top">
|
<a-tooltip placement="top">
|
||||||
|
@ -56,14 +56,14 @@
|
||||||
</template>
|
</template>
|
||||||
</template>
|
</template>
|
||||||
</vxe-column>
|
</vxe-column>
|
||||||
<vxe-column title="权限">
|
<vxe-column :title="$t('acl.permission')">
|
||||||
<template #default="{ row }">
|
<template #default="{ row }">
|
||||||
<a-tag v-for="(perm, index) in row.permission_ids" :key="'perms_' + perm + index">
|
<a-tag v-for="(perm, index) in row.permission_ids" :key="'perms_' + perm + index">
|
||||||
{{ perm }}
|
{{ perm }}
|
||||||
</a-tag>
|
</a-tag>
|
||||||
</template>
|
</template>
|
||||||
</vxe-column>
|
</vxe-column>
|
||||||
<vxe-column field="source" width="100px" title="来源"></vxe-column>
|
<vxe-column field="source" width="100px" :title="$t('acl.source')"></vxe-column>
|
||||||
</vxe-table>
|
</vxe-table>
|
||||||
<pager
|
<pager
|
||||||
:current-page.sync="queryParams.page"
|
:current-page.sync="queryParams.page"
|
||||||
|
@ -108,10 +108,6 @@ export default {
|
||||||
allRolesMap: new Map(),
|
allRolesMap: new Map(),
|
||||||
allUsersMap: new Map(),
|
allUsersMap: new Map(),
|
||||||
allResourceTypesMap: new Map(),
|
allResourceTypesMap: new Map(),
|
||||||
operateTypeMap: new Map([
|
|
||||||
['grant', '授权'],
|
|
||||||
['revoke', '撤销'],
|
|
||||||
]),
|
|
||||||
queryParams: {
|
queryParams: {
|
||||||
page: 1,
|
page: 1,
|
||||||
page_size: 50,
|
page_size: 50,
|
||||||
|
@ -120,57 +116,63 @@ export default {
|
||||||
},
|
},
|
||||||
permissionTableAttrList: [
|
permissionTableAttrList: [
|
||||||
{
|
{
|
||||||
alias: '日期',
|
alias: this.$t('acl.date'),
|
||||||
is_choice: false,
|
is_choice: false,
|
||||||
name: 'datetime',
|
name: 'datetime',
|
||||||
value_type: '3',
|
value_type: '3',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
alias: '应用',
|
alias: this.$t('acl.app'),
|
||||||
is_choice: true,
|
is_choice: true,
|
||||||
name: 'app_id',
|
name: 'app_id',
|
||||||
value_type: '2',
|
value_type: '2',
|
||||||
choice_value: [],
|
choice_value: [],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
alias: '操作员',
|
alias: this.$t('acl.operator'),
|
||||||
is_choice: true,
|
is_choice: true,
|
||||||
name: 'operate_uid',
|
name: 'operate_uid',
|
||||||
value_type: '2',
|
value_type: '2',
|
||||||
choice_value: [],
|
choice_value: [],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
alias: '用户',
|
alias: this.$t('user'),
|
||||||
is_choice: true,
|
is_choice: true,
|
||||||
name: 'rid',
|
name: 'rid',
|
||||||
value_type: '2',
|
value_type: '2',
|
||||||
choice_value: [],
|
choice_value: [],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
alias: '资源类型',
|
alias: this.$t('acl.resourceType'),
|
||||||
is_choice: true,
|
is_choice: true,
|
||||||
name: 'resource_type_id',
|
name: 'resource_type_id',
|
||||||
value_type: '2',
|
value_type: '2',
|
||||||
choice_value: [],
|
choice_value: [],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
alias: '资源',
|
alias: this.$t('acl.resource'),
|
||||||
is_choice: true,
|
is_choice: true,
|
||||||
name: 'resource_id',
|
name: 'resource_id',
|
||||||
value_type: '2',
|
value_type: '2',
|
||||||
choice_value: [],
|
choice_value: [],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
alias: '操作',
|
alias: this.$t('operation'),
|
||||||
is_choice: true,
|
is_choice: true,
|
||||||
name: 'operate_type',
|
name: 'operate_type',
|
||||||
value_type: '2',
|
value_type: '2',
|
||||||
choice_value: [{ 授权: 'grant' }, { 撤销: 'revoke' }],
|
choice_value: [{ [this.$t('grant')]: 'grant' }, { [this.$t('acl.cancel')]: 'revoke' }],
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
operateTypeMap() {
|
||||||
|
return new Map([
|
||||||
|
['grant', this.$t('grant')],
|
||||||
|
['revoke', this.$t('acl.cancel')],
|
||||||
|
])
|
||||||
|
},
|
||||||
windowHeight() {
|
windowHeight() {
|
||||||
return this.$store.state.windowHeight
|
return this.$store.state.windowHeight
|
||||||
},
|
},
|
||||||
|
@ -183,10 +185,10 @@ export default {
|
||||||
},
|
},
|
||||||
async created() {
|
async created() {
|
||||||
this.$watch(
|
this.$watch(
|
||||||
function() {
|
function () {
|
||||||
return this.permissionTableAttrList[3].choice_value
|
return this.permissionTableAttrList[3].choice_value
|
||||||
},
|
},
|
||||||
function() {
|
function () {
|
||||||
delete this.$refs.child.queryParams.rid
|
delete this.$refs.child.queryParams.rid
|
||||||
delete this.$refs.child.queryParams.resource_type_id
|
delete this.$refs.child.queryParams.resource_type_id
|
||||||
delete this.$refs.child.queryParams.resource_id
|
delete this.$refs.child.queryParams.resource_id
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
ref="child"
|
ref="child"
|
||||||
:attrList="resourceTableAttrList"
|
:attrList="resourceTableAttrList"
|
||||||
:hasSwitch="true"
|
:hasSwitch="true"
|
||||||
switchValue="组"
|
:switchValue="$t('acl.group2')"
|
||||||
@onSwitchChange="onSwitchChange"
|
@onSwitchChange="onSwitchChange"
|
||||||
@expandChange="handleExpandChange"
|
@expandChange="handleExpandChange"
|
||||||
@search="handleSearch"
|
@search="handleSearch"
|
||||||
|
@ -24,30 +24,30 @@
|
||||||
:data="tableData"
|
:data="tableData"
|
||||||
:height="`${windowHeight - windowHeightMinus}px`"
|
:height="`${windowHeight - windowHeightMinus}px`"
|
||||||
>
|
>
|
||||||
<vxe-column field="created_at" width="144px" title="操作时间"></vxe-column>
|
<vxe-column field="created_at" width="144px" :title="$t('acl.operateTime')"></vxe-column>
|
||||||
<vxe-column field="operate_uid" width="130px" title="操作员"></vxe-column>
|
<vxe-column field="operate_uid" width="130px" :title="$t('acl.operator')"></vxe-column>
|
||||||
<vxe-column field="operate_type" width="80px" title="操作">
|
<vxe-column field="operate_type" width="100px" :title="$t('operation')">
|
||||||
<template #default="{ row }">
|
<template #default="{ row }">
|
||||||
<a-tag :color="handleTagColor(row.operate_type)">
|
<a-tag :color="handleTagColor(row.operate_type)">
|
||||||
{{ operateTypeMap.get(row.operate_type) }}
|
{{ operateTypeMap.get(row.operate_type) }}
|
||||||
</a-tag>
|
</a-tag>
|
||||||
</template>
|
</template>
|
||||||
</vxe-column>
|
</vxe-column>
|
||||||
<vxe-column field="link_id" title="资源名">
|
<vxe-column field="link_id" :title="$t('acl.resouceName')">
|
||||||
<template #default="{ row }">
|
<template #default="{ row }">
|
||||||
<span>
|
<span>
|
||||||
{{ row.current.name || row.origin.name }}
|
{{ row.current.name || row.origin.name }}
|
||||||
</span>
|
</span>
|
||||||
</template>
|
</template>
|
||||||
</vxe-column>
|
</vxe-column>
|
||||||
<vxe-column title="描述">
|
<vxe-column :title="$t('desc')">
|
||||||
<template #default="{ row }">
|
<template #default="{ row }">
|
||||||
<p>
|
<p>
|
||||||
{{ row.description }}
|
{{ row.description }}
|
||||||
</p>
|
</p>
|
||||||
</template>
|
</template>
|
||||||
</vxe-column>
|
</vxe-column>
|
||||||
<vxe-column field="source" width="100px" title="来源"></vxe-column>
|
<vxe-column field="source" width="100px" :title="$t('acl.source')"></vxe-column>
|
||||||
</vxe-table>
|
</vxe-table>
|
||||||
<pager
|
<pager
|
||||||
:current-page.sync="queryParams.page"
|
:current-page.sync="queryParams.page"
|
||||||
|
@ -87,47 +87,6 @@ export default {
|
||||||
allApps: [],
|
allApps: [],
|
||||||
allUsersMap: new Map(),
|
allUsersMap: new Map(),
|
||||||
allResourcesMap: new Map(),
|
allResourcesMap: new Map(),
|
||||||
resourceTableAttrList: [
|
|
||||||
{
|
|
||||||
alias: '日期',
|
|
||||||
is_choice: false,
|
|
||||||
name: 'datetime',
|
|
||||||
value_type: '3',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
alias: '应用',
|
|
||||||
is_choice: true,
|
|
||||||
name: 'app_id',
|
|
||||||
value_type: '2',
|
|
||||||
choice_value: [],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
alias: '操作员',
|
|
||||||
is_choice: true,
|
|
||||||
name: 'operate_uid',
|
|
||||||
value_type: '2',
|
|
||||||
choice_value: [],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
alias: '资源名',
|
|
||||||
is_choice: true,
|
|
||||||
name: 'link_id',
|
|
||||||
value_type: '2',
|
|
||||||
choice_value: [],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
alias: '操作',
|
|
||||||
is_choice: true,
|
|
||||||
name: 'operate_type',
|
|
||||||
value_type: '2',
|
|
||||||
choice_value: [{ 新建: 'create' }, { 修改: 'update' }, { 删除: 'delete' }],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
operateTypeMap: new Map([
|
|
||||||
['create', '新建'],
|
|
||||||
['update', '修改'],
|
|
||||||
['delete', '删除'],
|
|
||||||
]),
|
|
||||||
colorMap: new Map([
|
colorMap: new Map([
|
||||||
['create', 'green'],
|
['create', 'green'],
|
||||||
['update', 'orange'],
|
['update', 'orange'],
|
||||||
|
@ -144,10 +103,10 @@ export default {
|
||||||
},
|
},
|
||||||
async created() {
|
async created() {
|
||||||
this.$watch(
|
this.$watch(
|
||||||
function() {
|
function () {
|
||||||
return this.resourceTableAttrList[3].choice_value
|
return this.resourceTableAttrList[3].choice_value
|
||||||
},
|
},
|
||||||
function() {
|
function () {
|
||||||
delete this.$refs.child.queryParams.link_id
|
delete this.$refs.child.queryParams.link_id
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
@ -158,6 +117,13 @@ export default {
|
||||||
this.$refs.xTable.$el.querySelector('.vxe-table--body-wrapper').scrollTop = 0
|
this.$refs.xTable.$el.querySelector('.vxe-table--body-wrapper').scrollTop = 0
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
operateTypeMap() {
|
||||||
|
return new Map([
|
||||||
|
['create', this.$t('create')],
|
||||||
|
['update', this.$t('update')],
|
||||||
|
['delete', this.$t('delete')],
|
||||||
|
])
|
||||||
|
},
|
||||||
windowHeight() {
|
windowHeight() {
|
||||||
return this.$store.state.windowHeight
|
return this.$store.state.windowHeight
|
||||||
},
|
},
|
||||||
|
@ -167,6 +133,44 @@ export default {
|
||||||
tableDataLength() {
|
tableDataLength() {
|
||||||
return this.tableData.length
|
return this.tableData.length
|
||||||
},
|
},
|
||||||
|
resourceTableAttrList() {
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
alias: this.$t('acl.date'),
|
||||||
|
is_choice: false,
|
||||||
|
name: 'datetime',
|
||||||
|
value_type: '3',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
alias: this.$t('acl.app'),
|
||||||
|
is_choice: true,
|
||||||
|
name: 'app_id',
|
||||||
|
value_type: '2',
|
||||||
|
choice_value: [],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
alias: this.$t('acl.operator'),
|
||||||
|
is_choice: true,
|
||||||
|
name: 'operate_uid',
|
||||||
|
value_type: '2',
|
||||||
|
choice_value: [],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
alias: this.$t('acl.resourceName'),
|
||||||
|
is_choice: true,
|
||||||
|
name: 'link_id',
|
||||||
|
value_type: '2',
|
||||||
|
choice_value: [],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
alias: this.$t('operation'),
|
||||||
|
is_choice: true,
|
||||||
|
name: 'operate_type',
|
||||||
|
value_type: '2',
|
||||||
|
choice_value: [{ [this.$t('create')]: 'create' }, { [this.$t('update')]: 'update' }, { [this.$t('delete')]: 'delete' }],
|
||||||
|
},
|
||||||
|
]
|
||||||
|
},
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
async getTable(queryParams) {
|
async getTable(queryParams) {
|
||||||
|
@ -347,7 +351,7 @@ export default {
|
||||||
switch (operate_type) {
|
switch (operate_type) {
|
||||||
// create
|
// create
|
||||||
case 'create': {
|
case 'create': {
|
||||||
item.description = `新建资源:${item.current.name}`
|
item.description = `${this.$t('acl.newResource')}${item.current.name}`
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
case 'update': {
|
case 'update': {
|
||||||
|
@ -357,10 +361,10 @@ export default {
|
||||||
const oldVal = item.origin[key]
|
const oldVal = item.origin[key]
|
||||||
if (!_.isEqual(newVal, oldVal) && key !== 'updated_at' && key !== 'deleted_at' && key !== 'created_at') {
|
if (!_.isEqual(newVal, oldVal) && key !== 'updated_at' && key !== 'deleted_at' && key !== 'created_at') {
|
||||||
if (oldVal === null) {
|
if (oldVal === null) {
|
||||||
const str = ` 【 ${key} : 改为 ${newVal} 】 `
|
const str = ` 【 ${key} : -> ${newVal} 】 `
|
||||||
item.description += str
|
item.description += str
|
||||||
} else {
|
} else {
|
||||||
const str = ` 【 ${key} : 由 ${oldVal} 改为 ${newVal} 】 `
|
const str = ` 【 ${key} : ${oldVal} -> ${newVal} 】 `
|
||||||
item.description += str
|
item.description += str
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -369,18 +373,18 @@ export default {
|
||||||
const currentResource_ids = item.currentResource_ids
|
const currentResource_ids = item.currentResource_ids
|
||||||
if (!_.isEqual(originResource_ids, currentResource_ids)) {
|
if (!_.isEqual(originResource_ids, currentResource_ids)) {
|
||||||
if (originResource_ids.length === 0) {
|
if (originResource_ids.length === 0) {
|
||||||
const str = ` 【 resource_ids : 新增 ${currentResource_ids} 】 `
|
const str = ` 【 resource_ids : ${this.$t('new')} ${currentResource_ids} 】 `
|
||||||
item.description += str
|
item.description += str
|
||||||
} else {
|
} else {
|
||||||
const str = ` 【 resource_ids : 由 ${originResource_ids} 改为 ${currentResource_ids} 】 `
|
const str = ` 【 resource_ids : ${originResource_ids} -> ${currentResource_ids} 】 `
|
||||||
item.description += str
|
item.description += str
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!item.description) item.description = '没有修改'
|
if (!item.description) item.description = this.$t('acl.noChange')
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
case 'delete': {
|
case 'delete': {
|
||||||
item.description = `删除资源:${item.origin.name}`
|
item.description = `${this.$t('acl.deleteResource')}${item.origin.name}`
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,30 +18,30 @@
|
||||||
:loading="loading"
|
:loading="loading"
|
||||||
:height="`${windowHeight - windowHeightMinus}px`"
|
:height="`${windowHeight - windowHeightMinus}px`"
|
||||||
>
|
>
|
||||||
<vxe-column field="created_at" width="144px" title="操作时间"></vxe-column>
|
<vxe-column field="created_at" width="144px" :title="$t('acl.operateTime')"></vxe-column>
|
||||||
<vxe-column field="operate_uid" width="130px" title="操作员"></vxe-column>
|
<vxe-column field="operate_uid" width="130px" :title="$t('acl.operator')"></vxe-column>
|
||||||
<vxe-column field="operate_type" width="80px" title="操作">
|
<vxe-column field="operate_type" width="100px" :title="$t('operation')">
|
||||||
<template #default="{ row }">
|
<template #default="{ row }">
|
||||||
<a-tag :color="handleTagColor(row.operate_type)">
|
<a-tag :color="handleTagColor(row.operate_type)">
|
||||||
{{ operateTypeMap.get(row.operate_type) }}
|
{{ operateTypeMap.get(row.operate_type) }}
|
||||||
</a-tag>
|
</a-tag>
|
||||||
</template>
|
</template>
|
||||||
</vxe-column>
|
</vxe-column>
|
||||||
<vxe-column field="link_id" width="159px" title="资源类型名">
|
<vxe-column field="link_id" width="159px" :title="$t('acl.resourceTypeName')">
|
||||||
<template #default="{ row }">
|
<template #default="{ row }">
|
||||||
<span>
|
<span>
|
||||||
{{ row.current.name || row.origin.name }}
|
{{ row.current.name || row.origin.name }}
|
||||||
</span>
|
</span>
|
||||||
</template>
|
</template>
|
||||||
</vxe-column>
|
</vxe-column>
|
||||||
<vxe-column title="描述">
|
<vxe-column :title="$t('desc')">
|
||||||
<template #default="{ row }">
|
<template #default="{ row }">
|
||||||
<p>
|
<p>
|
||||||
{{ row.changeDescription }}
|
{{ row.changeDescription }}
|
||||||
</p>
|
</p>
|
||||||
</template>
|
</template>
|
||||||
</vxe-column>
|
</vxe-column>
|
||||||
<vxe-column field="source" width="100px" title="来源"></vxe-column>
|
<vxe-column field="source" width="100px" :title="$t('acl.source')"></vxe-column>
|
||||||
</vxe-table>
|
</vxe-table>
|
||||||
<pager
|
<pager
|
||||||
:current-page.sync="queryParams.page"
|
:current-page.sync="queryParams.page"
|
||||||
|
@ -78,47 +78,6 @@ export default {
|
||||||
allApps: [],
|
allApps: [],
|
||||||
allUsersMap: new Map(),
|
allUsersMap: new Map(),
|
||||||
allResourcesMap: new Map(),
|
allResourcesMap: new Map(),
|
||||||
resourceTableAttrList: [
|
|
||||||
{
|
|
||||||
alias: '日期',
|
|
||||||
is_choice: false,
|
|
||||||
name: 'datetime',
|
|
||||||
value_type: '3',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
alias: '应用',
|
|
||||||
is_choice: true,
|
|
||||||
name: 'app_id',
|
|
||||||
value_type: '2',
|
|
||||||
choice_value: [],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
alias: '操作员',
|
|
||||||
is_choice: true,
|
|
||||||
name: 'operate_uid',
|
|
||||||
value_type: '2',
|
|
||||||
choice_value: [],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
alias: '资源类型',
|
|
||||||
is_choice: true,
|
|
||||||
name: 'link_id',
|
|
||||||
value_type: '2',
|
|
||||||
choice_value: [],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
alias: '操作',
|
|
||||||
is_choice: true,
|
|
||||||
name: 'operate_type',
|
|
||||||
value_type: '2',
|
|
||||||
choice_value: [{ 新建: 'create' }, { 修改: 'update' }, { 删除: 'delete' }],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
operateTypeMap: new Map([
|
|
||||||
['create', '新建'],
|
|
||||||
['update', '修改'],
|
|
||||||
['delete', '删除'],
|
|
||||||
]),
|
|
||||||
colorMap: new Map([
|
colorMap: new Map([
|
||||||
['create', 'green'],
|
['create', 'green'],
|
||||||
['update', 'orange'],
|
['update', 'orange'],
|
||||||
|
@ -135,10 +94,10 @@ export default {
|
||||||
},
|
},
|
||||||
async created() {
|
async created() {
|
||||||
this.$watch(
|
this.$watch(
|
||||||
function() {
|
function () {
|
||||||
return this.resourceTableAttrList[3].choice_value
|
return this.resourceTableAttrList[3].choice_value
|
||||||
},
|
},
|
||||||
function() {
|
function () {
|
||||||
delete this.$refs.child.queryParams.link_id
|
delete this.$refs.child.queryParams.link_id
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
@ -149,6 +108,13 @@ export default {
|
||||||
this.$refs.xTable.$el.querySelector('.vxe-table--body-wrapper').scrollTop = 0
|
this.$refs.xTable.$el.querySelector('.vxe-table--body-wrapper').scrollTop = 0
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
operateTypeMap() {
|
||||||
|
return new Map([
|
||||||
|
['create', this.$t('create')],
|
||||||
|
['update', this.$t('update')],
|
||||||
|
['delete', this.$t('delete')],
|
||||||
|
])
|
||||||
|
},
|
||||||
windowHeight() {
|
windowHeight() {
|
||||||
return this.$store.state.windowHeight
|
return this.$store.state.windowHeight
|
||||||
},
|
},
|
||||||
|
@ -158,6 +124,44 @@ export default {
|
||||||
tableDataLength() {
|
tableDataLength() {
|
||||||
return this.tableData.length
|
return this.tableData.length
|
||||||
},
|
},
|
||||||
|
resourceTableAttrList() {
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
alias: this.$t('acl.date'),
|
||||||
|
is_choice: false,
|
||||||
|
name: 'datetime',
|
||||||
|
value_type: '3',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
alias: this.$t('acl.app'),
|
||||||
|
is_choice: true,
|
||||||
|
name: 'app_id',
|
||||||
|
value_type: '2',
|
||||||
|
choice_value: [],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
alias: this.$t('acl.operator'),
|
||||||
|
is_choice: true,
|
||||||
|
name: 'operate_uid',
|
||||||
|
value_type: '2',
|
||||||
|
choice_value: [],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
alias: this.$t('acl.resourceType'),
|
||||||
|
is_choice: true,
|
||||||
|
name: 'link_id',
|
||||||
|
value_type: '2',
|
||||||
|
choice_value: [],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
alias: this.$t('operation'),
|
||||||
|
is_choice: true,
|
||||||
|
name: 'operate_type',
|
||||||
|
value_type: '2',
|
||||||
|
choice_value: [{ [this.$t('create')]: 'create' }, { [this.$t('update')]: 'update' }, { [this.$t('delete')]: 'delete' }],
|
||||||
|
},
|
||||||
|
]
|
||||||
|
},
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
async getTable(queryParams) {
|
async getTable(queryParams) {
|
||||||
|
@ -283,10 +287,12 @@ export default {
|
||||||
switch (operate_type) {
|
switch (operate_type) {
|
||||||
// create
|
// create
|
||||||
case 'create': {
|
case 'create': {
|
||||||
const description = item.current?.description === undefined ? '无' : item.current?.description
|
const description = item.current?.description === undefined ? this.$t('acl.none') : item.current?.description
|
||||||
const permission =
|
const permission =
|
||||||
item.extra.permission_ids?.current === undefined ? '无' : item.extra.permission_ids?.current
|
item.extra.permission_ids?.current === undefined ? this.$t('acl.none') : item.extra.permission_ids?.current
|
||||||
item.changeDescription = `新增资源类型:${item.current.name}\n描述:${description}\n权限:${permission}`
|
item.changeDescription = `${this.$t('acl.addReourceType')}:${item.current.name}\n${this.$t(
|
||||||
|
'desc'
|
||||||
|
)}:${description}\n${this.$t('acl.permission')}:${permission}`
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
case 'update': {
|
case 'update': {
|
||||||
|
@ -296,27 +302,29 @@ export default {
|
||||||
const oldVal = item.origin[key]
|
const oldVal = item.origin[key]
|
||||||
if (!_.isEqual(newVal, oldVal) && key !== 'updated_at' && key !== 'deleted_at' && key !== 'created_at') {
|
if (!_.isEqual(newVal, oldVal) && key !== 'updated_at' && key !== 'deleted_at' && key !== 'created_at') {
|
||||||
if (oldVal === null || oldVal === '') {
|
if (oldVal === null || oldVal === '') {
|
||||||
const str = ` 【 ${key} : 改为 ${newVal} 】 \n`
|
const str = ` 【 ${key} : -> ${newVal} 】 \n`
|
||||||
item.changeDescription += str
|
item.changeDescription += str
|
||||||
} else {
|
} else {
|
||||||
const str = ` 【 ${key} : 由 ${oldVal} 改为 ${newVal} 】 \n`
|
const str = ` 【 ${key} : ${oldVal} -> ${newVal} 】 \n`
|
||||||
item.changeDescription += str
|
item.changeDescription += str
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const currentPerms =
|
const currentPerms =
|
||||||
item.extra.permission_ids?.current === undefined ? '无' : item.extra.permission_ids?.current
|
item.extra.permission_ids?.current === undefined ? this.$t('acl.none') : item.extra.permission_ids?.current
|
||||||
const originPerms = item.extra.permission_ids?.origin === undefined ? '无' : item.extra.permission_ids?.origin
|
const originPerms = item.extra.permission_ids?.origin === undefined ? this.$t('acl.none') : item.extra.permission_ids?.origin
|
||||||
if (!_.isEqual(currentPerms, originPerms)) {
|
if (!_.isEqual(currentPerms, originPerms)) {
|
||||||
item.changeDescription += ` 【 permission_ids : 由 ${originPerms} 改为 ${currentPerms} 】 `
|
item.changeDescription += ` 【 permission_ids : ${originPerms} -> ${currentPerms} 】 `
|
||||||
}
|
}
|
||||||
if (!item.changeDescription) item.changeDescription = '没有修改'
|
if (!item.changeDescription) item.changeDescription = this.$t('acl.noChange')
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
case 'delete': {
|
case 'delete': {
|
||||||
const description = item.origin?.description === undefined ? '无' : item.origin?.description
|
const description = item.origin?.description === undefined ? this.$t('acl.none') : item.origin?.description
|
||||||
const permission = item.extra.permission_ids?.origin === undefined ? '无' : item.extra.permission_ids?.origin
|
const permission = item.extra.permission_ids?.origin === undefined ? this.$t('acl.none') : item.extra.permission_ids?.origin
|
||||||
item.changeDescription = `删除资源类型:${item.origin.name}\n描述:${description}\n权限:${permission}`
|
item.changeDescription = `${this.$t('acl.deleteResourceType')}: ${item.origin.name}\n${this.$t(
|
||||||
|
'desc'
|
||||||
|
)}:${description}\n${this.$t('acl.permission')}: ${permission}`
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
ref="child"
|
ref="child"
|
||||||
:attrList="roleTableAttrList"
|
:attrList="roleTableAttrList"
|
||||||
:hasSwitch="true"
|
:hasSwitch="true"
|
||||||
switchValue="角色关系"
|
:switchValue="$t('acl.roleRelation')"
|
||||||
@onSwitchChange="onSwitchChange"
|
@onSwitchChange="onSwitchChange"
|
||||||
@search="handleSearch"
|
@search="handleSearch"
|
||||||
@searchFormReset="searchFormReset"
|
@searchFormReset="searchFormReset"
|
||||||
|
@ -19,16 +19,16 @@
|
||||||
:loading="loading"
|
:loading="loading"
|
||||||
:height="`${windowHeight - 310}px`"
|
:height="`${windowHeight - 310}px`"
|
||||||
>
|
>
|
||||||
<vxe-column field="created_at" width="144px" title="操作时间"></vxe-column>
|
<vxe-column field="created_at" width="144px" :title="$t('acl.operateTime')"></vxe-column>
|
||||||
<vxe-column field="operate_uid" width="130px" title="操作员"></vxe-column>
|
<vxe-column field="operate_uid" width="130px" :title="$t('acl.operator')"></vxe-column>
|
||||||
<vxe-column field="operate_type" width="112px" title="操作">
|
<vxe-column field="operate_type" width="112px" :title="$t('operation')">
|
||||||
<template #default="{ row }">
|
<template #default="{ row }">
|
||||||
<template>
|
<template>
|
||||||
<a-tag :color="handleTagColor(row.operate_type)">{{ operateTypeMap.get(row.operate_type) }}</a-tag>
|
<a-tag :color="handleTagColor(row.operate_type)">{{ operateTypeMap.get(row.operate_type) }}</a-tag>
|
||||||
</template>
|
</template>
|
||||||
</template>
|
</template>
|
||||||
</vxe-column>
|
</vxe-column>
|
||||||
<vxe-column :title="checked ? '角色' : '角色'">
|
<vxe-column :title="checked ? $t('acl.role2') : $t('acl.role2')">
|
||||||
<template #default="{ row }">
|
<template #default="{ row }">
|
||||||
<template v-if="!checked">
|
<template v-if="!checked">
|
||||||
<a-tag color="blue">{{ row.current.name || row.origin.name }}</a-tag>
|
<a-tag color="blue">{{ row.current.name || row.origin.name }}</a-tag>
|
||||||
|
@ -40,7 +40,7 @@
|
||||||
</template>
|
</template>
|
||||||
</template>
|
</template>
|
||||||
</vxe-column>
|
</vxe-column>
|
||||||
<vxe-column :title="checked ? '继承自' : '管理员'" :width="checked ? '350px' : '80px'">
|
<vxe-column :title="checked ? $t('acl.inheritedFrom') : $t('acl.admin')" :width="checked ? '350px' : '80px'">
|
||||||
<template #default="{ row }">
|
<template #default="{ row }">
|
||||||
<template v-if="!checked">
|
<template v-if="!checked">
|
||||||
<a-icon type="check" v-if="row.current.is_app_admin" />
|
<a-icon type="check" v-if="row.current.is_app_admin" />
|
||||||
|
@ -52,14 +52,14 @@
|
||||||
</template>
|
</template>
|
||||||
</template>
|
</template>
|
||||||
</vxe-column>
|
</vxe-column>
|
||||||
<vxe-column title="描述" v-if="!checked">
|
<vxe-column :title="$t('desc')" v-if="!checked">
|
||||||
<template #default="{ row }">
|
<template #default="{ row }">
|
||||||
<p>
|
<p>
|
||||||
{{ row.description }}
|
{{ row.description }}
|
||||||
</p>
|
</p>
|
||||||
</template>
|
</template>
|
||||||
</vxe-column>
|
</vxe-column>
|
||||||
<vxe-column field="source" width="100px" title="来源"></vxe-column>
|
<vxe-column field="source" width="100px" :title="$t('acl.source')"></vxe-column>
|
||||||
</vxe-table>
|
</vxe-table>
|
||||||
<pager
|
<pager
|
||||||
:current-page.sync="queryParams.page"
|
:current-page.sync="queryParams.page"
|
||||||
|
@ -94,13 +94,6 @@ export default {
|
||||||
allRoles: [],
|
allRoles: [],
|
||||||
allRolesMap: new Map(),
|
allRolesMap: new Map(),
|
||||||
allUsersMap: new Map(),
|
allUsersMap: new Map(),
|
||||||
operateTypeMap: new Map([
|
|
||||||
['create', '新建'],
|
|
||||||
['delete', '删除'],
|
|
||||||
['update', '修改'],
|
|
||||||
['role_relation_add', '添加角色关系'],
|
|
||||||
['role_relation_delete', '删除角色关系'],
|
|
||||||
]),
|
|
||||||
colorMap: new Map([
|
colorMap: new Map([
|
||||||
['create', 'green'],
|
['create', 'green'],
|
||||||
['delete', 'red'],
|
['delete', 'red'],
|
||||||
|
@ -115,49 +108,60 @@ export default {
|
||||||
start: '',
|
start: '',
|
||||||
end: '',
|
end: '',
|
||||||
},
|
},
|
||||||
roleTableAttrList: [
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
operateTypeMap() {
|
||||||
|
return new Map([
|
||||||
|
['create', this.$t('create')],
|
||||||
|
['update', this.$t('update')],
|
||||||
|
['delete', this.$t('delete')],
|
||||||
|
['role_relation_add', this.$t('acl.roleRelationAdd')],
|
||||||
|
['role_relation_delete', this.$t('acl.roleRelationDelete')],
|
||||||
|
])
|
||||||
|
},
|
||||||
|
windowHeight() {
|
||||||
|
return this.$store.state.windowHeight
|
||||||
|
},
|
||||||
|
tableDataLength() {
|
||||||
|
return this.tableData.length
|
||||||
|
},
|
||||||
|
roleTableAttrList() {
|
||||||
|
return [
|
||||||
{
|
{
|
||||||
alias: '日期',
|
alias: this.$t('acl.date'),
|
||||||
is_choice: false,
|
is_choice: false,
|
||||||
name: 'datetime',
|
name: 'datetime',
|
||||||
value_type: '3',
|
value_type: '3',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
alias: '应用',
|
alias: this.$t('acl.app'),
|
||||||
is_choice: true,
|
is_choice: true,
|
||||||
name: 'app_id',
|
name: 'app_id',
|
||||||
value_type: '2',
|
value_type: '2',
|
||||||
choice_value: [],
|
choice_value: [],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
alias: '操作员',
|
alias: this.$t('acl.operator'),
|
||||||
is_choice: true,
|
is_choice: true,
|
||||||
name: 'operate_uid',
|
name: 'operate_uid',
|
||||||
value_type: '2',
|
value_type: '2',
|
||||||
choice_value: [],
|
choice_value: [],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
alias: '操作',
|
alias: this.$t('operation'),
|
||||||
is_choice: true,
|
is_choice: true,
|
||||||
name: 'operate_type',
|
name: 'operate_type',
|
||||||
value_type: '2',
|
value_type: '2',
|
||||||
choice_value: [
|
choice_value: [
|
||||||
{ 新建: 'create' },
|
{ [this.$t('create')]: 'create' },
|
||||||
{ 修改: 'update' },
|
{ [this.$t('update')]: 'update' },
|
||||||
{ 删除: 'delete' },
|
{ [this.$t('delete')]: 'delete' },
|
||||||
{ 添加角色关系: 'role_relation_add' },
|
{ [this.$t('acl.roleRelationAdd')]: 'role_relation_add' },
|
||||||
{ 删除角色关系: 'role_relation_delete' },
|
{ [this.$t('acl.roleRelationDelete')]: 'role_relation_delete' },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
],
|
]
|
||||||
}
|
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
windowHeight() {
|
|
||||||
return this.$store.state.windowHeight
|
|
||||||
},
|
|
||||||
tableDataLength() {
|
|
||||||
return this.tableData.length
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
async created() {
|
async created() {
|
||||||
|
@ -277,7 +281,7 @@ export default {
|
||||||
switch (operate_type) {
|
switch (operate_type) {
|
||||||
// create
|
// create
|
||||||
case 'create': {
|
case 'create': {
|
||||||
item.description = `新建角色:${item.current.name}`
|
item.description = `${this.$t('acl.addRole')}${item.current.name}`
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
case 'update': {
|
case 'update': {
|
||||||
|
@ -287,15 +291,15 @@ export default {
|
||||||
const oldVal = item.origin[key]
|
const oldVal = item.origin[key]
|
||||||
if (!_.isEqual(newVal, oldVal) && key !== 'updated_at' && key !== 'deleted_at' && key !== 'created_at') {
|
if (!_.isEqual(newVal, oldVal) && key !== 'updated_at' && key !== 'deleted_at' && key !== 'created_at') {
|
||||||
if (oldVal === null) {
|
if (oldVal === null) {
|
||||||
const str = ` 【 ${key} : 改为 ${newVal} 】 `
|
const str = ` 【 ${key} : -> ${newVal} 】 `
|
||||||
item.description += str
|
item.description += str
|
||||||
} else {
|
} else {
|
||||||
const str = ` 【 ${key} : 由 ${oldVal} 改为 ${newVal} 】 `
|
const str = ` 【 ${key} : ${oldVal} -> ${newVal} 】 `
|
||||||
item.description += str
|
item.description += ` 【 ${key} : ${oldVal} -> ${newVal} 】 `
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!item.description) item.description = '没有修改'
|
if (!item.description) item.description = this.$t('acl.noChange')
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
case 'delete': {
|
case 'delete': {
|
||||||
|
@ -325,7 +329,7 @@ export default {
|
||||||
resourceMap.forEach((value, key) => {
|
resourceMap.forEach((value, key) => {
|
||||||
permsArr.push(`${id2resources[key].name}:${value}`)
|
permsArr.push(`${id2resources[key].name}:${value}`)
|
||||||
})
|
})
|
||||||
item.description = `继承者:${child_ids}\n继承自:${parent_ids}\n涉及资源及权限:\n${permsArr.join(`\n`)}`
|
item.description = `${this.$t('acl.heir')}:${child_ids}\n${this.$t('acl.inheritedFrom')}:${parent_ids}\n${this.$t('acl.involvingRP')}:\n${permsArr.join(`\n`)}`
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,23 +18,23 @@
|
||||||
:loading="loading"
|
:loading="loading"
|
||||||
:height="`${windowHeight - windowHeightMinus}px`"
|
:height="`${windowHeight - windowHeightMinus}px`"
|
||||||
>
|
>
|
||||||
<vxe-column field="created_at" width="144px" title="操作时间"></vxe-column>
|
<vxe-column field="created_at" width="144px" :title="$t('acl.operateTime')"></vxe-column>
|
||||||
<vxe-column field="operate_uid" width="130px" title="操作员"></vxe-column>
|
<vxe-column field="operate_uid" width="130px" :title="$t('acl.operator')"></vxe-column>
|
||||||
<vxe-column field="operate_type" width="80px" title="操作">
|
<vxe-column field="operate_type" width="100px" :title="$t('operation')">
|
||||||
<template #default="{ row }">
|
<template #default="{ row }">
|
||||||
<a-tag :color="handleTagColor(row.operate_type)">
|
<a-tag :color="handleTagColor(row.operate_type)">
|
||||||
{{ operateTypeMap.get(row.operate_type) }}
|
{{ operateTypeMap.get(row.operate_type) }}
|
||||||
</a-tag>
|
</a-tag>
|
||||||
</template>
|
</template>
|
||||||
</vxe-column>
|
</vxe-column>
|
||||||
<vxe-column field="trigger_id" width="250px" title="触发器">
|
<vxe-column field="trigger_id" width="250px" :title="$t('acl.trigger')">
|
||||||
<template #default="{ row }">
|
<template #default="{ row }">
|
||||||
<span>
|
<span>
|
||||||
{{ row.current.name || row.origin.name }}
|
{{ row.current.name || row.origin.name }}
|
||||||
</span>
|
</span>
|
||||||
</template>
|
</template>
|
||||||
</vxe-column>
|
</vxe-column>
|
||||||
<vxe-column title="描述">
|
<vxe-column :title="$t('desc')">
|
||||||
<template #default="{ row }">
|
<template #default="{ row }">
|
||||||
<p>
|
<p>
|
||||||
{{ row.changeDescription }}
|
{{ row.changeDescription }}
|
||||||
|
@ -64,6 +64,7 @@ import { getTriggers } from '@/modules/acl/api/trigger'
|
||||||
import { searchUser } from '@/modules/acl/api/user'
|
import { searchUser } from '@/modules/acl/api/user'
|
||||||
import { searchApp } from '@/modules/acl/api/app'
|
import { searchApp } from '@/modules/acl/api/app'
|
||||||
export default {
|
export default {
|
||||||
|
name: 'TriggerHistoryTable',
|
||||||
components: { SearchForm, Pager },
|
components: { SearchForm, Pager },
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
|
@ -82,13 +83,6 @@ export default {
|
||||||
allResourceTypesMap: new Map(),
|
allResourceTypesMap: new Map(),
|
||||||
allResourcesMap: new Map(),
|
allResourcesMap: new Map(),
|
||||||
allTriggersMap: new Map(),
|
allTriggersMap: new Map(),
|
||||||
operateTypeMap: new Map([
|
|
||||||
['create', '新建'],
|
|
||||||
['update', '修改'],
|
|
||||||
['delete', '删除'],
|
|
||||||
['trigger_apply', '应用'],
|
|
||||||
['trigger_cancel', '取消'],
|
|
||||||
]),
|
|
||||||
colorMap: new Map([
|
colorMap: new Map([
|
||||||
['create', 'green'],
|
['create', 'green'],
|
||||||
['delete', 'red'],
|
['delete', 'red'],
|
||||||
|
@ -96,48 +90,6 @@ export default {
|
||||||
['trigger_apply', 'green'],
|
['trigger_apply', 'green'],
|
||||||
['trigger_cancel', 'red'],
|
['trigger_cancel', 'red'],
|
||||||
]),
|
]),
|
||||||
triggerTableAttrList: [
|
|
||||||
{
|
|
||||||
alias: '日期',
|
|
||||||
is_choice: false,
|
|
||||||
name: 'datetime',
|
|
||||||
value_type: '3',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
alias: '应用',
|
|
||||||
is_choice: true,
|
|
||||||
name: 'app_id',
|
|
||||||
value_type: '2',
|
|
||||||
choice_value: [],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
alias: '操作员',
|
|
||||||
is_choice: true,
|
|
||||||
name: 'operate_uid',
|
|
||||||
value_type: '2',
|
|
||||||
choice_value: [],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
alias: '触发器',
|
|
||||||
is_choice: true,
|
|
||||||
name: 'trigger_id',
|
|
||||||
value_type: '2',
|
|
||||||
choice_value: [],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
alias: '操作',
|
|
||||||
is_choice: true,
|
|
||||||
name: 'operate_type',
|
|
||||||
value_type: '2',
|
|
||||||
choice_value: [
|
|
||||||
{ 新建: 'create' },
|
|
||||||
{ 修改: 'update' },
|
|
||||||
{ 删除: 'delete' },
|
|
||||||
{ 应用: 'trigger_apply' },
|
|
||||||
{ 取消: 'trigger_cancel' },
|
|
||||||
],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
queryParams: {
|
queryParams: {
|
||||||
page: 1,
|
page: 1,
|
||||||
page_size: 50,
|
page_size: 50,
|
||||||
|
@ -162,6 +114,15 @@ export default {
|
||||||
this.$refs.xTable.$el.querySelector('.vxe-table--body-wrapper').scrollTop = 0
|
this.$refs.xTable.$el.querySelector('.vxe-table--body-wrapper').scrollTop = 0
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
operateTypeMap() {
|
||||||
|
return new Map([
|
||||||
|
['create', this.$t('create')],
|
||||||
|
['update', this.$t('update')],
|
||||||
|
['delete', this.$t('delete')],
|
||||||
|
['trigger_apply', this.$t('acl.apply')],
|
||||||
|
['trigger_cancel', this.$t('cancel')],
|
||||||
|
])
|
||||||
|
},
|
||||||
windowHeight() {
|
windowHeight() {
|
||||||
return this.$store.state.windowHeight
|
return this.$store.state.windowHeight
|
||||||
},
|
},
|
||||||
|
@ -171,6 +132,50 @@ export default {
|
||||||
tableDataLength() {
|
tableDataLength() {
|
||||||
return this.tableData.length
|
return this.tableData.length
|
||||||
},
|
},
|
||||||
|
triggerTableAttrList() {
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
alias: this.$t('acl.date'),
|
||||||
|
is_choice: false,
|
||||||
|
name: 'datetime',
|
||||||
|
value_type: '3',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
alias: this.$t('acl.app'),
|
||||||
|
is_choice: true,
|
||||||
|
name: 'app_id',
|
||||||
|
value_type: '2',
|
||||||
|
choice_value: [],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
alias: this.$t('acl.operator'),
|
||||||
|
is_choice: true,
|
||||||
|
name: 'operate_uid',
|
||||||
|
value_type: '2',
|
||||||
|
choice_value: [],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
alias: this.$t('acl.trigger'),
|
||||||
|
is_choice: true,
|
||||||
|
name: 'trigger_id',
|
||||||
|
value_type: '2',
|
||||||
|
choice_value: [],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
alias: this.$t('operation'),
|
||||||
|
is_choice: true,
|
||||||
|
name: 'operate_type',
|
||||||
|
value_type: '2',
|
||||||
|
choice_value: [
|
||||||
|
{ [this.$t('create')]: 'create' },
|
||||||
|
{ [this.$t('update')]: 'update' },
|
||||||
|
{ [this.$t('delete')]: 'delete' },
|
||||||
|
{ [this.$t('acl.apply')]: 'trigger_apply' },
|
||||||
|
{ [this.$t('cancel')]: 'trigger_cancel' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
]
|
||||||
|
},
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
async getTable(queryParams) {
|
async getTable(queryParams) {
|
||||||
|
@ -270,9 +275,11 @@ export default {
|
||||||
const newArr = str.slice(1, str.length - 1).split(', ')
|
const newArr = str.slice(1, str.length - 1).split(', ')
|
||||||
const newStr = newArr.map((i) => id2roles[i].name).join(',')
|
const newStr = newArr.map((i) => id2roles[i].name).join(',')
|
||||||
const { name, resource_type_id, wildcard, permissions, enabled } = item.current
|
const { name, resource_type_id, wildcard, permissions, enabled } = item.current
|
||||||
item.changeDescription = `新增触发器:${name}\n资源类型:${
|
item.changeDescription = `${this.$t('acl.addTrigger')}:${name}\n${this.$t('acl.resourceType')}: ${
|
||||||
id2resource_types[resource_type_id].name
|
id2resource_types[resource_type_id].name
|
||||||
},资源名:${wildcard || ''},角色:[${newStr}]\n权限:${permissions}\n状态:${enabled}`
|
},this.$t('acl.resourceName'):${wildcard || ''},${this.$t(
|
||||||
|
'acl.role2'
|
||||||
|
)}:[${newStr}]\nthis.$t('acl.permssion')}: ${permissions}\n${this.$t('status')}: ${enabled}`
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
case 'update': {
|
case 'update': {
|
||||||
|
@ -282,15 +289,15 @@ export default {
|
||||||
const oldVal = item.origin[key]
|
const oldVal = item.origin[key]
|
||||||
if (!_.isEqual(newVal, oldVal) && key !== 'updated_at' && key !== 'deleted_at' && key !== 'created_at') {
|
if (!_.isEqual(newVal, oldVal) && key !== 'updated_at' && key !== 'deleted_at' && key !== 'created_at') {
|
||||||
if (oldVal === null) {
|
if (oldVal === null) {
|
||||||
const str = ` 【 ${key} : 改为 ${newVal} 】 `
|
const str = ` 【 ${key} : -> ${newVal} 】 `
|
||||||
item.changeDescription += str
|
item.changeDescription += str
|
||||||
} else {
|
} else {
|
||||||
const str = ` 【 ${key} : 由 ${oldVal} 改为 ${newVal} 】 `
|
const str = ` 【 ${key} : ${oldVal} -> ${newVal} 】 `
|
||||||
item.changeDescription += str
|
item.changeDescription += ` 【 ${key} :${oldVal} -> ${newVal} 】 `
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!item.changeDescription) item.changeDescription = '没有修改'
|
if (!item.changeDescription) item.changeDescription = this.$t('acl.noChange')
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
case 'delete': {
|
case 'delete': {
|
||||||
|
@ -298,9 +305,11 @@ export default {
|
||||||
const newArr = str.slice(1, str.length - 1).split(', ')
|
const newArr = str.slice(1, str.length - 1).split(', ')
|
||||||
const newStr = newArr.map((i) => id2roles[i].name).join(',')
|
const newStr = newArr.map((i) => id2roles[i].name).join(',')
|
||||||
const { name, resource_type_id, wildcard, permissions, enabled } = item.origin
|
const { name, resource_type_id, wildcard, permissions, enabled } = item.origin
|
||||||
item.changeDescription = `删除触发器:${name}\n资源类型:${
|
item.changeDescription = `${this.$t('acl.deleteTrigger')}: ${name}\n${this.$t('acl.resourceType')}: ${
|
||||||
id2resource_types[resource_type_id].name
|
id2resource_types[resource_type_id].name
|
||||||
},资源名:${wildcard || ''},角色:[${newStr}]\n权限:${permissions}\n状态:${enabled}`
|
},${this.$t('acl.resourceName')}: ${wildcard || ''},${this.$t(
|
||||||
|
'acl.role2'
|
||||||
|
)}:[${newStr}]\nthis.$t('acl.permssion')}: ${permissions}\n${this.$t('status')}: ${enabled}`
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
case 'trigger_apply': {
|
case 'trigger_apply': {
|
||||||
|
@ -308,9 +317,11 @@ export default {
|
||||||
const newArr = str.slice(1, str.length - 1).split(', ')
|
const newArr = str.slice(1, str.length - 1).split(', ')
|
||||||
const newStr = newArr.map((i) => id2roles[i].name).join(',')
|
const newStr = newArr.map((i) => id2roles[i].name).join(',')
|
||||||
const { name, resource_type_id, wildcard, permissions, enabled } = item.current
|
const { name, resource_type_id, wildcard, permissions, enabled } = item.current
|
||||||
item.changeDescription = `应用触发器:${name}\n资源类型:${
|
item.changeDescription = `${this.$t('acl.applyTrigger')}: ${name}\n${this.$t('acl.resourceType')}: ${
|
||||||
id2resource_types[resource_type_id].name
|
id2resource_types[resource_type_id].name
|
||||||
},资源名:${wildcard || ''},角色:[${newStr}]\n权限:${permissions}\n状态:${enabled}`
|
},${this.$t('acl.resourceName')}: ${wildcard || ''},${this.$t(
|
||||||
|
'acl.role2'
|
||||||
|
)}:[${newStr}]\nthis.$t('acl.permssion')}: ${permissions}\n${this.$t('status')}: ${enabled}`
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
case 'trigger_cancel': {
|
case 'trigger_cancel': {
|
||||||
|
@ -318,9 +329,11 @@ export default {
|
||||||
const newArr = str.slice(1, str.length - 1).split(', ')
|
const newArr = str.slice(1, str.length - 1).split(', ')
|
||||||
const newStr = newArr.map((i) => id2roles[i].name).join(',')
|
const newStr = newArr.map((i) => id2roles[i].name).join(',')
|
||||||
const { name, resource_type_id, wildcard, permissions, enabled } = item.current
|
const { name, resource_type_id, wildcard, permissions, enabled } = item.current
|
||||||
item.changeDescription = `取消触发器:${name}\n资源类型:${
|
item.changeDescription = `${this.$t('acl.cancelTrigger')}: ${name}\n${this.$t('acl.resourceType')}: ${
|
||||||
id2resource_types[resource_type_id].name
|
id2resource_types[resource_type_id].name
|
||||||
},资源名:${wildcard || ''},角色:[${newStr}]\n权限:${permissions}\n状态:${enabled}`
|
},${this.$t('acl.resourceName')}: ${wildcard || ''},${this.$t(
|
||||||
|
'acl.role2'
|
||||||
|
)}:[${newStr}]\nthis.$t('acl.permssion')}: ${permissions}\n${this.$t('status')}: ${enabled}`
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,13 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="acl-resource-types">
|
<div class="acl-resource-types">
|
||||||
<div class="acl-resource-types-header">
|
<div class="acl-resource-types-header">
|
||||||
<a-button @click="handleCreate" type="primary" style="margin-right: 0.3rem">{{ btnName }}</a-button>
|
<a-button @click="handleCreate" type="primary" style="margin-right: 0.3rem">{{
|
||||||
|
$t('acl.addReourceType')
|
||||||
|
}}</a-button>
|
||||||
<a-input-search
|
<a-input-search
|
||||||
class="ops-input"
|
class="ops-input"
|
||||||
:style="{ display: 'inline', marginLeft: '10px', width: '200px' }"
|
:style="{ display: 'inline', marginLeft: '10px', width: '200px' }"
|
||||||
placeholder="搜索 | 资源类型名"
|
:placeholder="`${$t('search')} | ${$t('acl.resourceType')}`"
|
||||||
v-model="searchName"
|
v-model="searchName"
|
||||||
allowClear
|
allowClear
|
||||||
@search="
|
@search="
|
||||||
|
@ -28,28 +30,28 @@
|
||||||
<!-- 1 -->
|
<!-- 1 -->
|
||||||
<vxe-table-column
|
<vxe-table-column
|
||||||
field="name"
|
field="name"
|
||||||
title="资源类型名"
|
:title="$t('acl.resoureType')"
|
||||||
:min-width="175"
|
:min-width="175"
|
||||||
fixed="left"
|
fixed="left"
|
||||||
show-overflow
|
show-overflow
|
||||||
></vxe-table-column>
|
></vxe-table-column>
|
||||||
|
|
||||||
<!-- 2 -->
|
<!-- 2 -->
|
||||||
<vxe-table-column field="description" title="描述" :min-width="175"></vxe-table-column>
|
<vxe-table-column field="description" :title="$t('desc')" :min-width="175"></vxe-table-column>
|
||||||
|
|
||||||
<!-- 3 -->
|
<!-- 3 -->
|
||||||
<vxe-table-column field="id" title="权限" :min-width="300">
|
<vxe-table-column field="id" :title="$t('acl.permission')" :min-width="300">
|
||||||
<template #default="{ row }">
|
<template #default="{ row }">
|
||||||
<a-tag color="cyan" v-for="perm in id2perms[row.id]" :key="perm.id">{{ perm.name }}</a-tag>
|
<a-tag color="cyan" v-for="perm in id2perms[row.id]" :key="perm.id">{{ perm.name }}</a-tag>
|
||||||
</template>
|
</template>
|
||||||
</vxe-table-column>
|
</vxe-table-column>
|
||||||
|
|
||||||
<!-- 4 -->
|
<!-- 4 -->
|
||||||
<vxe-table-column field="action" title="操作" :width="100" fixed="right">
|
<vxe-table-column field="action" :title="$t('operation')" :width="100" fixed="right">
|
||||||
<template #default="{ row }">
|
<template #default="{ row }">
|
||||||
<a @click="handleEdit(row)"><a-icon type="edit"/></a>
|
<a @click="handleEdit(row)"><a-icon type="edit"/></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)">
|
||||||
<a style="color: red"><a-icon type="delete"/></a>
|
<a style="color: red"><a-icon type="delete"/></a>
|
||||||
</a-popconfirm>
|
</a-popconfirm>
|
||||||
</template>
|
</template>
|
||||||
|
@ -87,42 +89,12 @@ export default {
|
||||||
loading: false,
|
loading: false,
|
||||||
groups: [],
|
groups: [],
|
||||||
id2perms: {},
|
id2perms: {},
|
||||||
btnName: '新增资源类型',
|
|
||||||
pageSizeOptions: [10, 25, 50, 100],
|
pageSizeOptions: [10, 25, 50, 100],
|
||||||
tablePage: {
|
tablePage: {
|
||||||
total: 0,
|
total: 0,
|
||||||
currentPage: 1,
|
currentPage: 1,
|
||||||
pageSize: 50,
|
pageSize: 50,
|
||||||
},
|
},
|
||||||
tableColumns: [
|
|
||||||
{
|
|
||||||
title: '资源类型名',
|
|
||||||
field: 'name',
|
|
||||||
minWidth: '175px',
|
|
||||||
fixed: 'left',
|
|
||||||
showOverflow: 'tooltip',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: '描述',
|
|
||||||
field: 'description',
|
|
||||||
minWidth: '175px',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: '权限',
|
|
||||||
field: 'id',
|
|
||||||
minWidth: '300px',
|
|
||||||
slots: {
|
|
||||||
default: 'id_default',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: '操作',
|
|
||||||
field: 'action',
|
|
||||||
minWidth: '175px',
|
|
||||||
slots: { default: 'action_default' },
|
|
||||||
fixed: 'right',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
searchName: '',
|
searchName: '',
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -200,15 +172,10 @@ export default {
|
||||||
},
|
},
|
||||||
deleteResourceType(id) {
|
deleteResourceType(id) {
|
||||||
deleteResourceTypeById(id).then((res) => {
|
deleteResourceTypeById(id).then((res) => {
|
||||||
this.$message.success(`删除成功`)
|
this.$message.success(this.$t('deleteSuccess'))
|
||||||
this.handleOk()
|
this.handleOk()
|
||||||
})
|
})
|
||||||
// .catch(err => this.requestFailed(err))
|
|
||||||
},
|
},
|
||||||
// requestFailed(err) {
|
|
||||||
// const msg = ((err.response || {}).data || {}).message || '请求出现错误,请稍后再试'
|
|
||||||
// this.$message.error(`${msg}`)
|
|
||||||
// },
|
|
||||||
handlePageChange({ currentPage, pageSize }) {
|
handlePageChange({ currentPage, pageSize }) {
|
||||||
this.tablePage.currentPage = currentPage
|
this.tablePage.currentPage = currentPage
|
||||||
this.tablePage.pageSize = pageSize
|
this.tablePage.pageSize = pageSize
|
||||||
|
|
|
@ -6,10 +6,10 @@
|
||||||
</a-tabs>
|
</a-tabs>
|
||||||
<div class="acl-resources-header">
|
<div class="acl-resources-header">
|
||||||
<a-space>
|
<a-space>
|
||||||
<a-button @click="handleCreate" type="primary">{{ btnName }}</a-button>
|
<a-button @click="handleCreate" type="primary">{{ $t('acl.addResource') }}</a-button>
|
||||||
<a-input-search
|
<a-input-search
|
||||||
class="ops-input"
|
class="ops-input"
|
||||||
placeholder="搜索 | 资源名"
|
:placeholder="`${$t('search')} | ${$t('acl.resource')}`"
|
||||||
v-model="searchName"
|
v-model="searchName"
|
||||||
@search="
|
@search="
|
||||||
() => {
|
() => {
|
||||||
|
@ -20,10 +20,10 @@
|
||||||
></a-input-search>
|
></a-input-search>
|
||||||
|
|
||||||
<div v-if="!!selectedRows.length" class="ops-list-batch-action">
|
<div v-if="!!selectedRows.length" class="ops-list-batch-action">
|
||||||
<span @click="handleBatchPerm">授权</span>
|
<span @click="handleBatchPerm">{{ $t('grant') }}</span>
|
||||||
<a-divider type="vertical" />
|
<a-divider type="vertical" />
|
||||||
<span @click="handleBatchRevoke">权限回收</span>
|
<span @click="handleBatchRevoke">{{ $t('acl.revoke') }}</span>
|
||||||
<span>选取: {{ selectedRows.length }} 项</span>
|
<span>{{ $t('selectRows', { rows: selectedRows.length }) }}</span>
|
||||||
</div>
|
</div>
|
||||||
</a-space>
|
</a-space>
|
||||||
|
|
||||||
|
@ -36,7 +36,7 @@
|
||||||
$refs.resourceBatchPerm.open(currentType.id)
|
$refs.resourceBatchPerm.open(currentType.id)
|
||||||
}
|
}
|
||||||
"
|
"
|
||||||
>便捷授权</a-button
|
>{{ $t('acl.convenient') }}</a-button
|
||||||
>
|
>
|
||||||
<a-switch
|
<a-switch
|
||||||
v-model="isGroup"
|
v-model="isGroup"
|
||||||
|
@ -50,7 +50,7 @@
|
||||||
$refs.xTable && $refs.xTable.getVxetableRef().clearCheckboxReserve()
|
$refs.xTable && $refs.xTable.getVxetableRef().clearCheckboxReserve()
|
||||||
}
|
}
|
||||||
"
|
"
|
||||||
un-checked-children="组"
|
:un-checked-children="$t('acl.group2')"
|
||||||
></a-switch>
|
></a-switch>
|
||||||
</a-space>
|
</a-space>
|
||||||
</div>
|
</div>
|
||||||
|
@ -62,62 +62,63 @@
|
||||||
:data="tableData"
|
:data="tableData"
|
||||||
highlight-hover-row
|
highlight-hover-row
|
||||||
:height="`${windowHeight - 250}px`"
|
:height="`${windowHeight - 250}px`"
|
||||||
:checkbox-config="{ reserve: true }"
|
:checkbox-config="{ reserve: true, highlight: true, range: true }"
|
||||||
@checkbox-change="changeCheckbox"
|
@checkbox-change="changeCheckbox"
|
||||||
@checkbox-all="changeCheckbox"
|
@checkbox-all="changeCheckbox"
|
||||||
|
@checkbox-range-end="onSelectRangeEnd"
|
||||||
ref="xTable"
|
ref="xTable"
|
||||||
row-id="id"
|
row-id="id"
|
||||||
show-overflow
|
show-overflow
|
||||||
resizable
|
resizable
|
||||||
>
|
>
|
||||||
<!-- 1 -->
|
<!-- 1 -->
|
||||||
<vxe-table-column type="checkbox" fixed="left" :width="45"></vxe-table-column>
|
<vxe-table-column type="checkbox" fixed="left" :width="60"></vxe-table-column>
|
||||||
|
|
||||||
<!-- 2 -->
|
<!-- 2 -->
|
||||||
|
|
||||||
<vxe-table-column field="name" title="资源名" :min-widh="150" fixed="left" show-overflow>
|
<vxe-table-column field="name" :title="$t('acl.resourceName')" :min-widh="150" fixed="left" show-overflow>
|
||||||
<template #title="{ row }">
|
<template #title="{row}">
|
||||||
{{ row.isGroup ? '资源组名' : '资源名' }}
|
{{ row.isGroup ? $t('acl.groupName') : $t('acl.resourceName') }}
|
||||||
</template>
|
</template>
|
||||||
</vxe-table-column>
|
</vxe-table-column>
|
||||||
|
|
||||||
<!-- 3 -->
|
<!-- 3 -->
|
||||||
<vxe-table-column field="user" title="创建者" :min-widh="100"> </vxe-table-column>
|
<vxe-table-column field="user" :title="$t('acl.creator')" :min-widh="100"> </vxe-table-column>
|
||||||
|
|
||||||
<!-- 4 -->
|
<!-- 4 -->
|
||||||
<vxe-table-column field="created_at" title="创建时间" :min-widh="220" align="center"> </vxe-table-column>
|
<vxe-table-column field="created_at" :title="$t('created_at')" :min-widh="220" align="center"> </vxe-table-column>
|
||||||
|
|
||||||
<!-- 5 -->
|
<!-- 5 -->
|
||||||
<vxe-table-column field="updated_at" title="最后修改时间" :min-widh="220" fixed="center"> </vxe-table-column>
|
<vxe-table-column field="updated_at" :title="$t('updated_at')" :min-widh="220" fixed="center"> </vxe-table-column>
|
||||||
|
|
||||||
<!-- 6 -->
|
<!-- 6 -->
|
||||||
|
|
||||||
<vxe-table-column
|
<vxe-table-column
|
||||||
field="action"
|
field="action"
|
||||||
title="操作"
|
:title="$t('operation')"
|
||||||
:min-widh="200"
|
:min-widh="200"
|
||||||
fixed="right"
|
fixed="right"
|
||||||
align="center"
|
align="center"
|
||||||
show-overflow>
|
show-overflow>
|
||||||
<template #default="{ row }">
|
<template #default="{row}">
|
||||||
<span v-show="isGroup">
|
<span v-show="isGroup">
|
||||||
<a @click="handleDisplayMember(row)">成员</a>
|
<a @click="handleDisplayMember(row)">{{ $t('acl.member') }}</a>
|
||||||
<a-divider type="vertical" />
|
<a-divider type="vertical" />
|
||||||
<a @click="handleGroupEdit(row)">编辑</a>
|
<a @click="handleGroupEdit(row)">{{ $t('edit') }}</a>
|
||||||
<a-divider type="vertical" />
|
<a-divider type="vertical" />
|
||||||
</span>
|
</span>
|
||||||
<a-tooltip title="查看授权">
|
<a-tooltip :title="$t('acl.viewAuth')">
|
||||||
<a @click="handlePerm(row)"><a-icon type="eye" /></a>
|
<a @click="handlePerm(row)"><a-icon type="eye"/></a>
|
||||||
</a-tooltip>
|
</a-tooltip>
|
||||||
<a-divider type="vertical" />
|
<a-divider type="vertical" />
|
||||||
<a-tooltip title="授权">
|
<a-tooltip :title="$t('grant')">
|
||||||
<a :style="{ color: '#4bbb13' }" @click="handlePermManage(row)">
|
<a :style="{ color: '#4bbb13' }" @click="handlePermManage(row)">
|
||||||
<a-icon type="usergroup-add" />
|
<a-icon type="usergroup-add" />
|
||||||
</a>
|
</a>
|
||||||
</a-tooltip>
|
</a-tooltip>
|
||||||
<a-divider type="vertical" />
|
<a-divider type="vertical" />
|
||||||
<a-popconfirm title="确认删除?" @confirm="handleDelete(row)" @cancel="cancel" okText="是" cancelText="否">
|
<a-popconfirm :title="$t('confirmDelete')" @confirm="handleDelete(row)" @cancel="cancel" :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>
|
||||||
</vxe-table-column>
|
</vxe-table-column>
|
||||||
|
@ -135,9 +136,9 @@
|
||||||
</vxe-pager>
|
</vxe-pager>
|
||||||
</a-spin>
|
</a-spin>
|
||||||
</div>
|
</div>
|
||||||
<div v-else style="text-align: center; margin-top: 20%">
|
<div v-else style="text-align: center;margin-top:20%">
|
||||||
<a-icon style="font-size: 50px; margin-bottom: 20px; color: orange" type="info-circle" />
|
<a-icon style="font-size:50px; margin-bottom: 20px; color: orange" type="info-circle" />
|
||||||
<h3>暂无类型信息,请先添加资源类型!</h3>
|
<h3>{{ $t('acl.addTypeTips') }}</h3>
|
||||||
</div>
|
</div>
|
||||||
<resourceForm ref="resourceForm" @fresh="handleOk"> </resourceForm>
|
<resourceForm ref="resourceForm" @fresh="handleOk"> </resourceForm>
|
||||||
<resourcePermForm ref="resourcePermForm"> </resourcePermForm>
|
<resourcePermForm ref="resourcePermForm"> </resourcePermForm>
|
||||||
|
@ -187,7 +188,6 @@ export default {
|
||||||
pageSize: 50,
|
pageSize: 50,
|
||||||
},
|
},
|
||||||
tableData: [],
|
tableData: [],
|
||||||
btnName: '新增资源',
|
|
||||||
isGroup: false,
|
isGroup: false,
|
||||||
allResourceTypes: [],
|
allResourceTypes: [],
|
||||||
currentType: { id: 0 },
|
currentType: { id: 0 },
|
||||||
|
@ -196,7 +196,6 @@ export default {
|
||||||
selectedRows: [],
|
selectedRows: [],
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
beforeCreate() {
|
beforeCreate() {
|
||||||
this.form = this.$form.createForm(this)
|
this.form = this.$form.createForm(this)
|
||||||
},
|
},
|
||||||
|
@ -281,22 +280,16 @@ export default {
|
||||||
deleteResource(id) {
|
deleteResource(id) {
|
||||||
if (!this.isGroup) {
|
if (!this.isGroup) {
|
||||||
deleteResourceById(id, { app_id: this.$route.name.split('_')[0] }).then((res) => {
|
deleteResourceById(id, { app_id: this.$route.name.split('_')[0] }).then((res) => {
|
||||||
this.$message.success(`删除成功`)
|
this.$message.success(this.$t('deleteSuccess'))
|
||||||
this.handleOk()
|
this.handleOk()
|
||||||
})
|
})
|
||||||
// .catch(err => this.requestFailed(err))
|
|
||||||
} else {
|
} else {
|
||||||
deleteResourceGroup(id).then((res) => {
|
deleteResourceGroup(id).then((res) => {
|
||||||
this.$message.success(`删除成功`)
|
this.$message.success(this.$t('deleteSuccess'))
|
||||||
this.handleOk()
|
this.handleOk()
|
||||||
})
|
})
|
||||||
// .catch(err => this.requestFailed(err))
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
// requestFailed(err) {
|
|
||||||
// const msg = ((err.response || {}).data || {}).message || '请求出现错误,请稍后再试'
|
|
||||||
// this.$message.error(`${msg}`)
|
|
||||||
// },
|
|
||||||
cancel() {},
|
cancel() {},
|
||||||
handlePageChange({ currentPage, pageSize }) {
|
handlePageChange({ currentPage, pageSize }) {
|
||||||
this.tablePage.currentPage = currentPage
|
this.tablePage.currentPage = currentPage
|
||||||
|
@ -309,6 +302,10 @@ export default {
|
||||||
.getVxetableRef()
|
.getVxetableRef()
|
||||||
.getCheckboxRecords()
|
.getCheckboxRecords()
|
||||||
.concat(this.$refs.xTable.getVxetableRef().getCheckboxReserveRecords())
|
.concat(this.$refs.xTable.getVxetableRef().getCheckboxReserveRecords())
|
||||||
|
console.log(this.selectedRows)
|
||||||
|
},
|
||||||
|
onSelectRangeEnd({ records }) {
|
||||||
|
this.selectedRows = records
|
||||||
},
|
},
|
||||||
handleBatchPerm() {
|
handleBatchPerm() {
|
||||||
this.$refs['resourcePermManageForm'].editPerm(this.selectedRows, this.isGroup)
|
this.$refs['resourcePermManageForm'].editPerm(this.selectedRows, this.isGroup)
|
||||||
|
@ -322,7 +319,7 @@ export default {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
'$route.name': function (newName, oldName) {
|
'$route.name': function(newName, oldName) {
|
||||||
this.isGroup = false
|
this.isGroup = false
|
||||||
this.tablePage = {
|
this.tablePage = {
|
||||||
total: 0,
|
total: 0,
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="acl-roles">
|
<div class="acl-roles">
|
||||||
<div class="acl-roles-header">
|
<div class="acl-roles-header">
|
||||||
<a-button @click="handleCreate" type="primary">{{ btnName }}</a-button>
|
<a-button @click="handleCreate" type="primary">{{ $t('acl.addVisualRole') }}</a-button>
|
||||||
<a-input-search
|
<a-input-search
|
||||||
class="ops-input"
|
class="ops-input"
|
||||||
allowClear
|
allowClear
|
||||||
:style="{ display: 'inline', marginLeft: '10px', width: '200px' }"
|
:style="{ display: 'inline', marginLeft: '10px', width: '200px' }"
|
||||||
placeholder="搜索 | 角色名"
|
:placeholder="`${$t('search')} | ${$t('acl.role')}`"
|
||||||
v-model="searchName"
|
v-model="searchName"
|
||||||
@search="
|
@search="
|
||||||
() => {
|
() => {
|
||||||
|
@ -15,7 +15,7 @@
|
||||||
}
|
}
|
||||||
"
|
"
|
||||||
></a-input-search>
|
></a-input-search>
|
||||||
<a-checkbox :checked="is_all" @click="handleClickBoxChange">所有角色</a-checkbox>
|
<a-checkbox :checked="is_all" @click="handleClickBoxChange">{{ $t('acl.allRole') }}</a-checkbox>
|
||||||
</div>
|
</div>
|
||||||
<a-spin :spinning="loading">
|
<a-spin :spinning="loading">
|
||||||
<ops-table
|
<ops-table
|
||||||
|
@ -31,22 +31,23 @@
|
||||||
>
|
>
|
||||||
<vxe-table-column
|
<vxe-table-column
|
||||||
field="name"
|
field="name"
|
||||||
title="角色名"
|
:title="$t('acl.role')"
|
||||||
:min-width="150"
|
:min-width="150"
|
||||||
align="left"
|
align="left"
|
||||||
fixed="left"
|
fixed="left"
|
||||||
sortable
|
sortable
|
||||||
show-overflow>
|
show-overflow
|
||||||
|
>
|
||||||
</vxe-table-column>
|
</vxe-table-column>
|
||||||
|
|
||||||
<!-- 2 -->
|
<!-- 2 -->
|
||||||
<vxe-table-column field="is_app_admin" title="管理员" :min-width="100" align="center">
|
<vxe-table-column field="is_app_admin" :title="$t('admin')" :min-width="100" align="center">
|
||||||
<template #default="{row}">
|
<template #default="{row}">
|
||||||
<a-icon type="check" v-if="row.is_app_admin" />
|
<a-icon type="check" v-if="row.is_app_admin" />
|
||||||
</template>
|
</template>
|
||||||
</vxe-table-column>
|
</vxe-table-column>
|
||||||
|
|
||||||
<vxe-table-column field="id" title="继承自" :min-width="150">
|
<vxe-table-column field="id" :title="$t('acl.inheritedFrom')" :min-width="150">
|
||||||
<template #default="{row}">
|
<template #default="{row}">
|
||||||
<a-tag color="cyan" v-for="role in id2parents[row.id]" :key="role.id">{{ role.name }}</a-tag>
|
<a-tag color="cyan" v-for="role in id2parents[row.id]" :key="role.id">{{ role.name }}</a-tag>
|
||||||
</template>
|
</template>
|
||||||
|
@ -54,12 +55,12 @@
|
||||||
|
|
||||||
<vxe-table-column
|
<vxe-table-column
|
||||||
field="uid"
|
field="uid"
|
||||||
title="虚拟角色"
|
:title="$t('acl.visualRole')"
|
||||||
:width="100"
|
:width="120"
|
||||||
align="center"
|
align="center"
|
||||||
:filters="[
|
:filters="[
|
||||||
{ label: '是', value: 1 },
|
{ label: $t('yes'), value: 1 },
|
||||||
{ label: '否', value: 0 },
|
{ label: $t('no'), value: 0 },
|
||||||
]"
|
]"
|
||||||
:filterMultiple="false"
|
:filterMultiple="false"
|
||||||
:filter-method="
|
:filter-method="
|
||||||
|
@ -69,14 +70,14 @@
|
||||||
"
|
"
|
||||||
>
|
>
|
||||||
<template #default="{row}">
|
<template #default="{row}">
|
||||||
{{ row.uid ? '否' : '是' }}
|
{{ row.uid ? $t('no') : $t('yes') }}
|
||||||
</template>
|
</template>
|
||||||
</vxe-table-column>
|
</vxe-table-column>
|
||||||
|
|
||||||
<vxe-table-column field="action" title="操作" :width="120" fixed="right">
|
<vxe-table-column field="action" :title="$t('operation')" :width="120" fixed="right">
|
||||||
<template #default="{row}">
|
<template #default="{row}">
|
||||||
<a-space>
|
<a-space>
|
||||||
<a-tooltip title="资源列表">
|
<a-tooltip :title="$t('acl.resourceList')">
|
||||||
<a
|
<a
|
||||||
v-if="$route.name !== 'acl_roles'"
|
v-if="$route.name !== 'acl_roles'"
|
||||||
@click="handleDisplayUserResource(row)"
|
@click="handleDisplayUserResource(row)"
|
||||||
|
@ -85,12 +86,18 @@
|
||||||
/></a>
|
/></a>
|
||||||
</a-tooltip>
|
</a-tooltip>
|
||||||
<a-tooltip
|
<a-tooltip
|
||||||
title="用户列表"
|
:title="$t('acl.userList')"
|
||||||
v-if="!row.uid"
|
v-if="!row.uid"
|
||||||
><a @click="handleDisplayUserUnderRole(row)"><a-icon type="team"/></a
|
><a @click="handleDisplayUserUnderRole(row)"><a-icon type="team"/></a
|
||||||
></a-tooltip>
|
></a-tooltip>
|
||||||
<a @click="handleEdit(row)"><a-icon type="edit"/></a>
|
<a @click="handleEdit(row)"><a-icon type="edit"/></a>
|
||||||
<a-popconfirm title="确认删除?" @confirm="handleDelete(row)" @cancel="cancel" okText="是" cancelText="否">
|
<a-popconfirm
|
||||||
|
:title="$t('confirmDelete')"
|
||||||
|
@confirm="handleDelete(row)"
|
||||||
|
@cancel="cancel"
|
||||||
|
: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>
|
||||||
</a-space>
|
</a-space>
|
||||||
|
@ -138,52 +145,6 @@ export default {
|
||||||
currentPage: 1,
|
currentPage: 1,
|
||||||
pageSize: 50,
|
pageSize: 50,
|
||||||
},
|
},
|
||||||
tableColumns: [
|
|
||||||
{
|
|
||||||
title: '角色名',
|
|
||||||
field: 'name',
|
|
||||||
sortable: true,
|
|
||||||
minWidth: '150px',
|
|
||||||
fixed: 'left',
|
|
||||||
showOverflow: 'tooltip',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: '管理员',
|
|
||||||
field: 'is_app_admin',
|
|
||||||
minWidth: '100px',
|
|
||||||
align: 'center',
|
|
||||||
slots: { default: 'is_app_admin_default' },
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: '继承自',
|
|
||||||
field: 'id',
|
|
||||||
minWidth: '150px',
|
|
||||||
slots: { default: 'inherit_default' },
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: '虚拟角色',
|
|
||||||
field: 'uid',
|
|
||||||
minWidth: '100px',
|
|
||||||
align: 'center',
|
|
||||||
filters: [
|
|
||||||
{ label: '是', value: 1 },
|
|
||||||
{ label: '否', value: 0 },
|
|
||||||
],
|
|
||||||
filterMultiple: false,
|
|
||||||
filterMethod: ({ value, row }) => {
|
|
||||||
return value === !row.uid
|
|
||||||
},
|
|
||||||
slots: { default: 'isVisualRole_default' },
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: '操作',
|
|
||||||
minWidth: '280px',
|
|
||||||
field: 'action',
|
|
||||||
fixed: 'right',
|
|
||||||
slots: { default: 'action_default' },
|
|
||||||
},
|
|
||||||
],
|
|
||||||
btnName: '新增虚拟角色',
|
|
||||||
is_all: this.$route.name === 'acl_roles',
|
is_all: this.$route.name === 'acl_roles',
|
||||||
tableData: [],
|
tableData: [],
|
||||||
allRoles: [],
|
allRoles: [],
|
||||||
|
@ -286,15 +247,10 @@ export default {
|
||||||
|
|
||||||
deleteRole(id) {
|
deleteRole(id) {
|
||||||
deleteRoleById(id, { app_id: this.$route.name.split('_')[0] }).then((res) => {
|
deleteRoleById(id, { app_id: this.$route.name.split('_')[0] }).then((res) => {
|
||||||
this.$message.success(`删除成功`)
|
this.$message.success(this.$t('deleteSuccess'))
|
||||||
this.handleOk()
|
this.handleOk()
|
||||||
})
|
})
|
||||||
// .catch(err => this.requestFailed(err))
|
|
||||||
},
|
},
|
||||||
// requestFailed(err) {
|
|
||||||
// const msg = ((err.response || {}).data || {}).message || '请求出现错误,请稍后再试'
|
|
||||||
// this.$message.error(`${msg}`)
|
|
||||||
// },
|
|
||||||
cancel(e) {
|
cancel(e) {
|
||||||
return false
|
return false
|
||||||
},
|
},
|
||||||
|
|
|
@ -15,9 +15,9 @@
|
||||||
</a-form-model-item>
|
</a-form-model-item>
|
||||||
<a-form-model-item label=" " :colon="false">
|
<a-form-model-item label=" " :colon="false">
|
||||||
<a-space>
|
<a-space>
|
||||||
<a-button type="primary" @click="changeVisible">{{ !visible ? '查看' : '隐藏' }}</a-button>
|
<a-button type="primary" @click="changeVisible">{{ !visible ? $t('view') : $t('hide') }}</a-button>
|
||||||
<a-button type="danger" ghost @click="handleSumbit">重置</a-button>
|
<a-button type="danger" ghost @click="handleSumbit">{{ $t('reset') }}</a-button>
|
||||||
<!-- <a-button @click="handleCancel">取消</a-button> -->
|
<!-- <a-button @click="handleCancel">{{ $t('cancel') }}</a-button> -->
|
||||||
</a-space>
|
</a-space>
|
||||||
</a-form-model-item>
|
</a-form-model-item>
|
||||||
</a-form-model>
|
</a-form-model>
|
||||||
|
@ -62,13 +62,13 @@ export default {
|
||||||
handleSumbit() {
|
handleSumbit() {
|
||||||
const that = this
|
const that = this
|
||||||
this.$confirm({
|
this.$confirm({
|
||||||
title: '重置',
|
title: that.$t('reset'),
|
||||||
content: '确定重置用户密钥?',
|
content: that.$t('acl.confirmResetSecret'),
|
||||||
onOk() {
|
onOk() {
|
||||||
that.$refs.secretKeyForm.validate((valid) => {
|
that.$refs.secretKeyForm.validate((valid) => {
|
||||||
if (valid) {
|
if (valid) {
|
||||||
updateSecret().then((res) => {
|
updateSecret().then((res) => {
|
||||||
that.$message.success('重置成功')
|
that.$message.success(that.$t('operateSuccess'))
|
||||||
const { key, secret } = res
|
const { key, secret } = res
|
||||||
that.form = { key, secret }
|
that.form = { key, secret }
|
||||||
})
|
})
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="acl-trigger">
|
<div class="acl-trigger">
|
||||||
<div class="acl-trigger-header">
|
<div class="acl-trigger-header">
|
||||||
<a-button type="primary" @click="handleCreateTrigger">新增触发器</a-button>
|
<a-button type="primary" @click="handleCreateTrigger">{{ $t('acl.addTrigger') }}</a-button>
|
||||||
<a-input-search
|
<a-input-search
|
||||||
class="ops-input"
|
class="ops-input"
|
||||||
:style="{ display: 'inline', marginLeft: '10px', width: '200px' }"
|
:style="{ display: 'inline', marginLeft: '10px', width: '200px' }"
|
||||||
placeholder="搜索 | 名称"
|
:placeholder="`${$t('search')} | ${$t('name')}`"
|
||||||
v-model="searchName"
|
v-model="searchName"
|
||||||
allowClear
|
allowClear
|
||||||
@search="filter"
|
@search="filter"
|
||||||
|
@ -46,18 +46,18 @@
|
||||||
<a-tag v-for="(p, index) in row.permissions" :key="index">{{ p }}</a-tag>
|
<a-tag v-for="(p, index) in row.permissions" :key="index">{{ p }}</a-tag>
|
||||||
</template>
|
</template>
|
||||||
<template #enabled_default="{row}">
|
<template #enabled_default="{row}">
|
||||||
<a-tag v-if="row.enabled" color="#2db7f5">启用</a-tag>
|
<a-tag v-if="row.enabled" color="#2db7f5">{{ $t('acl.enable') }}</a-tag>
|
||||||
<a-tag v-else color="grey">禁用</a-tag>
|
<a-tag v-else color="grey">{{ $t('acl.disable') }}</a-tag>
|
||||||
</template>
|
</template>
|
||||||
<template #action_default="{row}">
|
<template #action_default="{row}">
|
||||||
<a-space>
|
<a-space>
|
||||||
<a-tooltip title="应用">
|
<a-tooltip :title="$t('acl.apply')">
|
||||||
<a @click="handleApplyTrigger(row)" :style="{ color: '#0f9d58' }"><a-icon type="appstore"/></a>
|
<a @click="handleApplyTrigger(row)" :style="{ color: '#0f9d58' }"><a-icon type="appstore"/></a>
|
||||||
</a-tooltip>
|
</a-tooltip>
|
||||||
<a-tooltip title="取消">
|
<a-tooltip :title="$t('cancel')">
|
||||||
<a @click="handleCancelTrigger(row)" :style="{ color: 'orange' }"><a-icon type="stop"/></a>
|
<a @click="handleCancelTrigger(row)" :style="{ color: 'orange' }"><a-icon type="stop"/></a>
|
||||||
</a-tooltip>
|
</a-tooltip>
|
||||||
<a-tooltip title="查看正则匹配结果">
|
<a-tooltip :title="$t('acl.viewMatchResult')">
|
||||||
<a @click="handlePattern(row)" :style="{ color: 'purple' }"><a-icon type="eye"/></a>
|
<a @click="handlePattern(row)" :style="{ color: 'purple' }"><a-icon type="eye"/></a>
|
||||||
</a-tooltip>
|
</a-tooltip>
|
||||||
<a @click="handleEditTrigger(row)"><a-icon type="edit"/></a>
|
<a @click="handleEditTrigger(row)"><a-icon type="edit"/></a>
|
||||||
|
@ -67,7 +67,7 @@
|
||||||
<template slot="empty">
|
<template slot="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-grid>
|
</vxe-grid>
|
||||||
|
@ -102,9 +102,19 @@ export default {
|
||||||
triggers: [],
|
triggers: [],
|
||||||
id2parents: [],
|
id2parents: [],
|
||||||
id2perms: {},
|
id2perms: {},
|
||||||
tableColumns: [
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
...mapState({
|
||||||
|
windowHeight: (state) => state.windowHeight,
|
||||||
|
}),
|
||||||
|
app_id() {
|
||||||
|
return this.$route.name.split('_')[0]
|
||||||
|
},
|
||||||
|
tableColumns() {
|
||||||
|
return [
|
||||||
{
|
{
|
||||||
title: '名称',
|
title: this.$t('name'),
|
||||||
field: 'name',
|
field: 'name',
|
||||||
sortable: true,
|
sortable: true,
|
||||||
minWidth: '150px',
|
minWidth: '150px',
|
||||||
|
@ -112,7 +122,7 @@ export default {
|
||||||
showOverflow: 'tooltip',
|
showOverflow: 'tooltip',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '资源名',
|
title: this.$t('acl.resource'),
|
||||||
field: 'wildcard',
|
field: 'wildcard',
|
||||||
minWidth: '250px',
|
minWidth: '250px',
|
||||||
showOverflow: 'tooltip',
|
showOverflow: 'tooltip',
|
||||||
|
@ -121,15 +131,15 @@ export default {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '资源类型',
|
title: this.$t('acl.resourceType'),
|
||||||
field: 'resource_type_id',
|
field: 'resource_type_id',
|
||||||
minWidth: '100px',
|
minWidth: '120px',
|
||||||
slots: {
|
slots: {
|
||||||
default: 'resourceTypeRender_default',
|
default: 'resourceTypeRender_default',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '创建人',
|
title: this.$t('acl.creator'),
|
||||||
field: 'users',
|
field: 'users',
|
||||||
minWidth: '150px',
|
minWidth: '150px',
|
||||||
showOverflow: 'tooltip',
|
showOverflow: 'tooltip',
|
||||||
|
@ -138,7 +148,7 @@ export default {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '角色',
|
title: this.$t('acl.allRole'),
|
||||||
field: 'roles',
|
field: 'roles',
|
||||||
minWidth: '150px',
|
minWidth: '150px',
|
||||||
slots: {
|
slots: {
|
||||||
|
@ -172,7 +182,7 @@ export default {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '权限',
|
title: this.$t('acl.permission'),
|
||||||
field: 'permissions',
|
field: 'permissions',
|
||||||
minWidth: '250px',
|
minWidth: '250px',
|
||||||
slots: {
|
slots: {
|
||||||
|
@ -180,7 +190,7 @@ export default {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '状态',
|
title: this.$t('status'),
|
||||||
field: 'enabled',
|
field: 'enabled',
|
||||||
minWidth: '100px',
|
minWidth: '100px',
|
||||||
slots: {
|
slots: {
|
||||||
|
@ -188,7 +198,7 @@ export default {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '操作',
|
title: this.$t('operation'),
|
||||||
field: 'action',
|
field: 'action',
|
||||||
width: '120px',
|
width: '120px',
|
||||||
fixed: 'right',
|
fixed: 'right',
|
||||||
|
@ -196,8 +206,8 @@ export default {
|
||||||
default: 'action_default',
|
default: 'action_default',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
],
|
]
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
created() {
|
created() {
|
||||||
this.loadRoles()
|
this.loadRoles()
|
||||||
|
@ -206,15 +216,6 @@ export default {
|
||||||
beforeMount() {
|
beforeMount() {
|
||||||
this.loadTriggers()
|
this.loadTriggers()
|
||||||
},
|
},
|
||||||
|
|
||||||
computed: {
|
|
||||||
...mapState({
|
|
||||||
windowHeight: (state) => state.windowHeight,
|
|
||||||
}),
|
|
||||||
app_id() {
|
|
||||||
return this.$route.name.split('_')[0]
|
|
||||||
},
|
|
||||||
},
|
|
||||||
methods: {
|
methods: {
|
||||||
loadTriggers() {
|
loadTriggers() {
|
||||||
this.searchName = ''
|
this.searchName = ''
|
||||||
|
@ -244,11 +245,11 @@ export default {
|
||||||
handleDeleteTrigger(record) {
|
handleDeleteTrigger(record) {
|
||||||
const that = this
|
const that = this
|
||||||
this.$confirm({
|
this.$confirm({
|
||||||
title: '删除',
|
title: that.$t('warning'),
|
||||||
content: '确认删除该触发器吗?',
|
content: that.$t('acl.confirmDeleteTrigger'),
|
||||||
onOk() {
|
onOk() {
|
||||||
deleteTrigger(record.id).then((res) => {
|
deleteTrigger(record.id).then((res) => {
|
||||||
that.$message.success('删除成功')
|
that.$message.success(that.$t('deleteSuccess'))
|
||||||
that.loadTriggers()
|
that.loadTriggers()
|
||||||
})
|
})
|
||||||
// .catch(err => that.$httpError(err))
|
// .catch(err => that.$httpError(err))
|
||||||
|
@ -258,11 +259,11 @@ export default {
|
||||||
handleApplyTrigger(record) {
|
handleApplyTrigger(record) {
|
||||||
const that = this
|
const that = this
|
||||||
this.$confirm({
|
this.$confirm({
|
||||||
title: '规则应用',
|
title: that.$t('acl.ruleApply'),
|
||||||
content: '是否确定应用该触发器?',
|
content: that.$t('acl.triggerTip1'),
|
||||||
onOk() {
|
onOk() {
|
||||||
applyTrigger(record.id).then((res) => {
|
applyTrigger(record.id).then((res) => {
|
||||||
that.$message.success('提交成功!')
|
that.$message.success(that.$t('operateSuccess'))
|
||||||
})
|
})
|
||||||
// .catch(err => that.$httpError(err))
|
// .catch(err => that.$httpError(err))
|
||||||
},
|
},
|
||||||
|
@ -271,11 +272,11 @@ export default {
|
||||||
handleCancelTrigger(record) {
|
handleCancelTrigger(record) {
|
||||||
const that = this
|
const that = this
|
||||||
this.$confirm({
|
this.$confirm({
|
||||||
title: '规则应用',
|
title: that.$t('acl.ruleApply'),
|
||||||
content: '是否取消应用该触发器?',
|
content: that.$t('acl.triggerTip2'),
|
||||||
onOk() {
|
onOk() {
|
||||||
cancelTrigger(record.id).then((res) => {
|
cancelTrigger(record.id).then((res) => {
|
||||||
that.$message.success('提交成功!')
|
that.$message.success(that.$t('operateSuccess'))
|
||||||
})
|
})
|
||||||
// .catch(err => that.$httpError(err))
|
// .catch(err => that.$httpError(err))
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,198 +1,202 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="acl-users">
|
<div class="acl-users">
|
||||||
<div class="acl-users-header">
|
<div class="acl-users-header">
|
||||||
<a-button v-if="isAclAdmin" @click="handleCreate" type="primary">{{ btnName }}</a-button>
|
<a-button v-if="isAclAdmin" @click="handleCreate" type="primary">{{ btnName }}</a-button>
|
||||||
<a-input-search
|
<a-input-search
|
||||||
class="ops-input"
|
class="ops-input"
|
||||||
allowClear
|
allowClear
|
||||||
:style="{ display: 'inline', marginLeft: '10px' }"
|
:style="{ width: '300px', display: 'inline', marginLeft: '10px' }"
|
||||||
placeholder="搜索 | 用户名、中文名"
|
:placeholder="`${$t('search')} | ${$t('acl.nickname')} 、 ${$t('acl.username')}`"
|
||||||
v-model="searchName"
|
v-model="searchName"
|
||||||
></a-input-search>
|
></a-input-search>
|
||||||
</div>
|
</div>
|
||||||
<a-spin :spinning="loading">
|
<a-spin :spinning="loading">
|
||||||
<vxe-grid
|
<vxe-grid
|
||||||
stripe
|
stripe
|
||||||
class="ops-stripe-table"
|
class="ops-stripe-table"
|
||||||
:columns="tableColumns"
|
:columns="tableColumns"
|
||||||
:data="tableData"
|
:data="tableData"
|
||||||
show-overflow
|
show-overflow
|
||||||
highlight-hover-row
|
highlight-hover-row
|
||||||
:height="`${windowHeight - 165}px`"
|
:height="`${windowHeight - 165}px`"
|
||||||
size="small"
|
size="small"
|
||||||
>
|
>
|
||||||
<template #block_default="{row}">
|
<template #block_default="{row}">
|
||||||
<a-icon type="lock" v-if="row.block" />
|
<a-icon type="lock" v-if="row.block" />
|
||||||
</template>
|
</template>
|
||||||
<template #action_default="{row}">
|
<template #action_default="{row}">
|
||||||
<a-space>
|
<a-space>
|
||||||
<a :disabled="isAclAdmin ? false : true" @click="handleEdit(row)">
|
<a :disabled="isAclAdmin ? false : true" @click="handleEdit(row)">
|
||||||
<a-icon type="edit" />
|
<a-icon type="edit" />
|
||||||
</a>
|
</a>
|
||||||
<a-tooltip title="权限汇总">
|
<a-tooltip :title="$t('acl.summaryPermissions')">
|
||||||
<a @click="handlePermCollect(row)"><a-icon type="solution"/></a>
|
<a @click="handlePermCollect(row)"><a-icon type="solution"/></a>
|
||||||
</a-tooltip>
|
</a-tooltip>
|
||||||
<a-popconfirm :title="`确认删除【${row.nickname || row.username}】?`" @confirm="deleteUser(row.uid)">
|
<a-popconfirm :title="$t('confirmDelete')" @confirm="deleteUser(row.uid)">
|
||||||
<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>
|
||||||
</template>
|
</template>
|
||||||
</vxe-grid>
|
</vxe-grid>
|
||||||
</a-spin>
|
</a-spin>
|
||||||
<userForm ref="userForm" :handleOk="handleOk"> </userForm>
|
<userForm ref="userForm" :handleOk="handleOk"> </userForm>
|
||||||
<perm-collect-form ref="permCollectForm"></perm-collect-form>
|
<perm-collect-form ref="permCollectForm"></perm-collect-form>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { mapState } from 'vuex'
|
import { mapState } from 'vuex'
|
||||||
import userForm from './module/userForm'
|
import userForm from './module/userForm'
|
||||||
import PermCollectForm from './module/permCollectForm'
|
import PermCollectForm from './module/permCollectForm'
|
||||||
import { deleteUserById, searchUser, getOnDutyUser } from '@/modules/acl/api/user'
|
import { deleteUserById, searchUser, getOnDutyUser } from '@/modules/acl/api/user'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'Users',
|
name: 'Users',
|
||||||
components: {
|
components: {
|
||||||
userForm,
|
userForm,
|
||||||
PermCollectForm,
|
PermCollectForm,
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
loading: false,
|
loading: false,
|
||||||
tableColumns: [
|
onDutuUids: [],
|
||||||
{
|
allUsers: [],
|
||||||
title: '用户名',
|
tableData: [],
|
||||||
field: 'username',
|
searchName: '',
|
||||||
sortable: true,
|
}
|
||||||
minWidth: '100px',
|
},
|
||||||
fixed: 'left',
|
beforeCreate() {
|
||||||
},
|
this.form = this.$form.createForm(this)
|
||||||
{
|
},
|
||||||
title: '中文名',
|
async beforeMount() {
|
||||||
field: 'nickname',
|
this.loading = true
|
||||||
minWidth: '100px',
|
await this.getOnDutyUser()
|
||||||
},
|
this.search()
|
||||||
{
|
},
|
||||||
title: '加入时间',
|
computed: {
|
||||||
field: 'date_joined',
|
...mapState({
|
||||||
minWidth: '160px',
|
windowHeight: (state) => state.windowHeight,
|
||||||
align: 'center',
|
}),
|
||||||
sortable: true,
|
isAclAdmin: function() {
|
||||||
},
|
if (this.$store.state.user.roles.permissions.filter((item) => item === 'acl_admin').length > 0) {
|
||||||
{
|
return true
|
||||||
title: '锁定',
|
} else {
|
||||||
field: 'block',
|
return false
|
||||||
width: '150px',
|
}
|
||||||
align: 'center',
|
},
|
||||||
slots: {
|
tableColumns() {
|
||||||
default: 'block_default',
|
return [
|
||||||
},
|
{
|
||||||
},
|
title: this.$t('acl.username'),
|
||||||
{
|
field: 'username',
|
||||||
title: '操作',
|
sortable: true,
|
||||||
field: 'action',
|
minWidth: '100px',
|
||||||
width: '150px',
|
fixed: 'left',
|
||||||
fixed: 'right',
|
},
|
||||||
align: 'center',
|
{
|
||||||
slots: {
|
title: this.$t('acl.nickname'),
|
||||||
default: 'action_default',
|
field: 'nickname',
|
||||||
},
|
minWidth: '100px',
|
||||||
},
|
},
|
||||||
],
|
{
|
||||||
onDutuUids: [],
|
title: this.$t('acl.joined_at'),
|
||||||
btnName: '新增用户',
|
field: 'date_joined',
|
||||||
allUsers: [],
|
minWidth: '160px',
|
||||||
tableData: [],
|
align: 'center',
|
||||||
searchName: '',
|
sortable: true,
|
||||||
}
|
},
|
||||||
},
|
{
|
||||||
beforeCreate() {
|
title: this.$t('acl.block'),
|
||||||
this.form = this.$form.createForm(this)
|
field: 'block',
|
||||||
},
|
width: '150px',
|
||||||
async beforeMount() {
|
align: 'center',
|
||||||
this.loading = true
|
slots: {
|
||||||
await this.getOnDutyUser()
|
default: 'block_default',
|
||||||
this.search()
|
},
|
||||||
},
|
},
|
||||||
computed: {
|
{
|
||||||
...mapState({
|
title: this.$t('operation'),
|
||||||
windowHeight: (state) => state.windowHeight,
|
field: 'action',
|
||||||
}),
|
width: '150px',
|
||||||
isAclAdmin: function() {
|
fixed: 'right',
|
||||||
if (this.$store.state.user.roles.permissions.filter((item) => item === 'acl_admin').length > 0) {
|
align: 'center',
|
||||||
return true
|
slots: {
|
||||||
} else {
|
default: 'action_default',
|
||||||
return false
|
},
|
||||||
}
|
},
|
||||||
},
|
]
|
||||||
},
|
},
|
||||||
watch: {
|
btnName() {
|
||||||
searchName: {
|
return this.$t('acl.addUser')
|
||||||
immediate: true,
|
},
|
||||||
handler(newVal, oldVal) {
|
},
|
||||||
if (newVal) {
|
watch: {
|
||||||
this.tableData = this.allUsers.filter(
|
searchName: {
|
||||||
(item) =>
|
immediate: true,
|
||||||
(item.username && item.username.toLowerCase().includes(newVal.toLowerCase())) ||
|
handler(newVal, oldVal) {
|
||||||
(item.nickname && item.nickname.toLowerCase().includes(newVal.toLowerCase()))
|
if (newVal) {
|
||||||
)
|
this.tableData = this.allUsers.filter(
|
||||||
} else {
|
(item) =>
|
||||||
this.tableData = this.allUsers
|
(item.username && item.username.toLowerCase().includes(newVal.toLowerCase())) ||
|
||||||
}
|
(item.nickname && item.nickname.toLowerCase().includes(newVal.toLowerCase()))
|
||||||
},
|
)
|
||||||
},
|
} else {
|
||||||
},
|
this.tableData = this.allUsers
|
||||||
mounted() {},
|
}
|
||||||
inject: ['reload'],
|
},
|
||||||
|
},
|
||||||
methods: {
|
},
|
||||||
async getOnDutyUser() {
|
mounted() {},
|
||||||
await getOnDutyUser().then((res) => {
|
inject: ['reload'],
|
||||||
this.onDutuUids = res.map((i) => i.uid)
|
|
||||||
})
|
methods: {
|
||||||
},
|
async getOnDutyUser() {
|
||||||
search() {
|
await getOnDutyUser().then((res) => {
|
||||||
searchUser({ page_size: 10000 }).then((res) => {
|
this.onDutuUids = res.map((i) => i.uid)
|
||||||
const ret = res.users.filter((u) => this.onDutuUids.includes(u.uid))
|
})
|
||||||
this.allUsers = ret
|
},
|
||||||
this.tableData = ret
|
search() {
|
||||||
this.loading = false
|
searchUser({ page_size: 10000 }).then((res) => {
|
||||||
})
|
const ret = res.users.filter((u) => this.onDutuUids.includes(u.uid))
|
||||||
},
|
this.allUsers = ret
|
||||||
handlePermCollect(record) {
|
this.tableData = ret
|
||||||
this.$refs['permCollectForm'].collect(record)
|
this.loading = false
|
||||||
},
|
})
|
||||||
handleEdit(record) {
|
},
|
||||||
this.$refs.userForm.handleEdit(record)
|
handlePermCollect(record) {
|
||||||
},
|
this.$refs['permCollectForm'].collect(record)
|
||||||
async handleOk() {
|
},
|
||||||
this.searchName = ''
|
handleEdit(record) {
|
||||||
await this.getOnDutyUser()
|
this.$refs.userForm.handleEdit(record)
|
||||||
this.search()
|
},
|
||||||
},
|
async handleOk() {
|
||||||
handleCreate() {
|
this.searchName = ''
|
||||||
this.$refs.userForm.handleCreate()
|
await this.getOnDutyUser()
|
||||||
},
|
this.search()
|
||||||
deleteUser(uid) {
|
},
|
||||||
deleteUserById(uid).then((res) => {
|
handleCreate() {
|
||||||
this.$message.success(`删除成功!`)
|
this.$refs.userForm.handleCreate()
|
||||||
this.handleOk()
|
},
|
||||||
})
|
deleteUser(uid) {
|
||||||
},
|
deleteUserById(uid).then((res) => {
|
||||||
},
|
this.$message.success(this.$t('deleteSuccess'))
|
||||||
}
|
this.handleOk()
|
||||||
</script>
|
})
|
||||||
|
},
|
||||||
<style lang="less" scoped>
|
},
|
||||||
.acl-users {
|
}
|
||||||
border-radius: 15px;
|
</script>
|
||||||
background-color: #fff;
|
|
||||||
height: calc(100vh - 64px);
|
<style lang="less" scoped>
|
||||||
margin-bottom: -24px;
|
.acl-users {
|
||||||
padding: 24px;
|
border-radius: 15px;
|
||||||
.acl-users-header {
|
background-color: #fff;
|
||||||
display: inline-flex;
|
height: calc(100vh - 64px);
|
||||||
margin-bottom: 15px;
|
margin-bottom: -24px;
|
||||||
}
|
padding: 24px;
|
||||||
}
|
.acl-users-header {
|
||||||
</style>
|
display: inline-flex;
|
||||||
|
margin-bottom: 15px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
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()
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue