mirror of
https://github.com/veops/cmdb.git
synced 2025-09-22 05:19:19 +08:00
前后端全面升级
This commit is contained in:
140
cmdb-ui/src/views/setting/components/EditImage.vue
Normal file
140
cmdb-ui/src/views/setting/components/EditImage.vue
Normal file
@@ -0,0 +1,140 @@
|
||||
<template>
|
||||
<a-modal
|
||||
class="ops-modal"
|
||||
v-loading="loading"
|
||||
:title="title"
|
||||
width="600px"
|
||||
:append-to-body="true"
|
||||
:close-on-click-modal="false"
|
||||
:visible.sync="showDialog"
|
||||
@cancel="hiddenView"
|
||||
>
|
||||
<div class="ops-modal-cropper-box">
|
||||
<vueCropper
|
||||
ref="cropper"
|
||||
:can-move="true"
|
||||
:auto-crop="true"
|
||||
:fixed="true"
|
||||
:img="cropperImg"
|
||||
output-type="png"
|
||||
@realTime="realTime"
|
||||
v-bind="eidtImageOption"
|
||||
/>
|
||||
<div class="ops-modal-preview">
|
||||
<div class="ops-modal-preview-name">预览</div>
|
||||
<img
|
||||
:style="{
|
||||
width: eidtImageOption.previewWidth,
|
||||
height: eidtImageOption.previewHeight,
|
||||
border: '1px solid #f2f2f2',
|
||||
}"
|
||||
:src="previewImg"
|
||||
class="ops-modal-preview-img"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div slot="footer" class="ops-modal-dialog-footer">
|
||||
<a-button type="primary" @click="submitImage()">确定</a-button>
|
||||
</div>
|
||||
</a-modal>
|
||||
</template>
|
||||
<script type="text/javascript">
|
||||
import { VueCropper } from 'vue-cropper'
|
||||
|
||||
export default {
|
||||
name: 'EditImage', // 处理头像
|
||||
components: {
|
||||
VueCropper,
|
||||
},
|
||||
props: {
|
||||
title: {
|
||||
type: String,
|
||||
default: '编辑头像',
|
||||
},
|
||||
show: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
image: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
eidtImageOption: {
|
||||
type: Object,
|
||||
default: () => {},
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
loading: false,
|
||||
showDialog: false,
|
||||
cropperImg: '',
|
||||
previewImg: '',
|
||||
}
|
||||
},
|
||||
computed: {},
|
||||
watch: {
|
||||
show: {
|
||||
handler(val) {
|
||||
this.showDialog = val
|
||||
},
|
||||
deep: true,
|
||||
immediate: true,
|
||||
},
|
||||
image: function(val) {
|
||||
this.cropperImg = val
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
this.cropperImg = this.image
|
||||
},
|
||||
methods: {
|
||||
realTime(data) {
|
||||
this.$refs.cropper.getCropData((cropperData) => {
|
||||
this.previewImg = cropperData
|
||||
})
|
||||
},
|
||||
submitImage() {
|
||||
// 获取截图的blob数据
|
||||
this.$refs.cropper.getCropBlob((data) => {
|
||||
const form = new FormData()
|
||||
form.append('file', data)
|
||||
this.$emit('save', form)
|
||||
this.hiddenView()
|
||||
})
|
||||
},
|
||||
hiddenView() {
|
||||
this.$emit('close')
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
<style lang="less" scoped>
|
||||
.ops-modal {
|
||||
.ops-modal-cropper-box {
|
||||
position: relative;
|
||||
width: 300px;
|
||||
height: 300px;
|
||||
}
|
||||
|
||||
.ops-modal-preview {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 325px;
|
||||
.ops-modal-preview-name {
|
||||
margin-bottom: 8px;
|
||||
font-size: 13px;
|
||||
color: #666;
|
||||
}
|
||||
.ops-modal-preview-img {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
.ops-modal-content {
|
||||
position: relative;
|
||||
padding: 0 30px;
|
||||
}
|
||||
}
|
||||
</style>
|
80
cmdb-ui/src/views/setting/components/SearchForm.vue
Normal file
80
cmdb-ui/src/views/setting/components/SearchForm.vue
Normal file
@@ -0,0 +1,80 @@
|
||||
<template>
|
||||
<div>
|
||||
<div :style="{ marginLeft: '10px'}">
|
||||
<FilterComp
|
||||
ref="filterComp"
|
||||
:canSearchPreferenceAttrList="canSearchPreferenceAttrList"
|
||||
:placement="placement"
|
||||
@setExpFromFilter="setExpFromFilter"
|
||||
>
|
||||
<div slot="popover_item" class="search-form-bar-filter">
|
||||
<a-icon :class="filterExp.length ? 'search-form-bar-filter-icon' : 'search-form-bar-filter-icon_selected'" type="filter"/>
|
||||
条件过滤
|
||||
<a-icon :class="filterExp.length ? 'search-form-bar-filter-icon' : 'search-form-bar-filter-icon_selected'" type="down"/>
|
||||
</div>
|
||||
</FilterComp>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import FilterComp from './settingFilterComp'
|
||||
export default {
|
||||
name: 'SearchForm',
|
||||
components: {
|
||||
FilterComp,
|
||||
},
|
||||
props: {
|
||||
canSearchPreferenceAttrList: {
|
||||
type: Array,
|
||||
required: true,
|
||||
default: () => [],
|
||||
},
|
||||
placement: {
|
||||
type: String,
|
||||
default: 'bottomLeft'
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
filterExp: []
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
setExpFromFilter(filterExp) {
|
||||
// const regSort = /(?<=sort=).+/g
|
||||
// const expSort = this.expression.match(regSort) ? this.expression.match(regSort)[0] : undefined
|
||||
// let expression = ''
|
||||
// if (filterExp) {
|
||||
// expression = `q=${filterExp}`
|
||||
// }
|
||||
// if (expSort) {
|
||||
// expression += `&sort=${expSort}`
|
||||
// }
|
||||
this.filterExp = filterExp
|
||||
this.emitRefresh(filterExp)
|
||||
},
|
||||
emitRefresh(filterExp) {
|
||||
this.$nextTick(() => {
|
||||
this.$emit('refresh', filterExp)
|
||||
})
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
@import '~@/style/static.less';
|
||||
.search-form-bar-filter {
|
||||
background-color: rgb(240, 245, 255);
|
||||
.ops_display_wrapper();
|
||||
.search-form-bar-filter-icon {
|
||||
color: #custom_colors[color_1];
|
||||
font-size: 12px;
|
||||
}
|
||||
.search-form-bar-filter-icon_selected{
|
||||
color:#606266;
|
||||
font-size: 12px;
|
||||
}
|
||||
}
|
||||
</style>
|
@@ -0,0 +1,67 @@
|
||||
<template>
|
||||
<treeselect
|
||||
:multiple="false"
|
||||
:options="departemntTreeSelectOption"
|
||||
placeholder="请选择部门"
|
||||
v-model="treeValue"
|
||||
:normalizer="normalizer"
|
||||
noChildrenText="空"
|
||||
noOptionsText="空"
|
||||
class="ops-setting-treeselect"
|
||||
v-bind="$attrs"
|
||||
appendToBody
|
||||
:zIndex="1050"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Treeselect from '@riophae/vue-treeselect'
|
||||
export default {
|
||||
name: 'DepartmentTreeSelect',
|
||||
components: { Treeselect },
|
||||
model: {
|
||||
prop: 'value',
|
||||
event: 'change',
|
||||
},
|
||||
props: {
|
||||
value: {
|
||||
type: [String, Array, Number, null],
|
||||
default: null,
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
normalizer: (node) => {
|
||||
if (node.sub_departments && node.sub_departments.length) {
|
||||
return {
|
||||
id: node.department_id,
|
||||
label: node.department_name,
|
||||
children: node.sub_departments,
|
||||
}
|
||||
}
|
||||
return {
|
||||
id: node.department_id,
|
||||
label: node.department_name,
|
||||
}
|
||||
},
|
||||
}
|
||||
},
|
||||
inject: ['provide_allTreeDepartment'],
|
||||
computed: {
|
||||
departemntTreeSelectOption() {
|
||||
return this.provide_allTreeDepartment()
|
||||
},
|
||||
treeValue: {
|
||||
get() {
|
||||
return this.value
|
||||
},
|
||||
set(val) {
|
||||
this.$emit('change', val)
|
||||
return val
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style></style>
|
1841
cmdb-ui/src/views/setting/components/employeeTable.vue
Normal file
1841
cmdb-ui/src/views/setting/components/employeeTable.vue
Normal file
File diff suppressed because it is too large
Load Diff
74
cmdb-ui/src/views/setting/components/employeeTreeSelect.vue
Normal file
74
cmdb-ui/src/views/setting/components/employeeTreeSelect.vue
Normal file
@@ -0,0 +1,74 @@
|
||||
<template>
|
||||
<treeselect
|
||||
:disable-branch-nodes="multiple ? false : true"
|
||||
:multiple="multiple"
|
||||
:options="employeeTreeSelectOption"
|
||||
placeholder="请选择员工"
|
||||
v-model="treeValue"
|
||||
:max-height="200"
|
||||
noChildrenText="空"
|
||||
noOptionsText="空"
|
||||
:class="className ? className: 'ops-setting-treeselect'"
|
||||
value-consists-of="LEAF_PRIORITY"
|
||||
:limit="20"
|
||||
:limitText="(count) => `+ ${count}`"
|
||||
v-bind="$attrs"
|
||||
appendToBody
|
||||
:zIndex="1050"
|
||||
>
|
||||
</treeselect>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Treeselect from '@riophae/vue-treeselect'
|
||||
import { formatOption } from '@/utils/util'
|
||||
export default {
|
||||
name: 'EmployeeTreeSelect',
|
||||
components: {
|
||||
Treeselect,
|
||||
},
|
||||
model: {
|
||||
prop: 'value',
|
||||
event: 'change',
|
||||
},
|
||||
props: {
|
||||
value: {
|
||||
type: [String, Array, Number, null],
|
||||
default: null,
|
||||
},
|
||||
multiple: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
className: {
|
||||
type: String,
|
||||
default: 'ops-setting-treeselect'
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {}
|
||||
},
|
||||
inject: ['provide_allTreeDepAndEmp'],
|
||||
computed: {
|
||||
treeValue: {
|
||||
get() {
|
||||
return this.value
|
||||
},
|
||||
set(val) {
|
||||
this.$emit('change', val)
|
||||
return val
|
||||
},
|
||||
},
|
||||
allTreeDepAndEmp() {
|
||||
return this.provide_allTreeDepAndEmp()
|
||||
},
|
||||
employeeTreeSelectOption() {
|
||||
return formatOption(this.allTreeDepAndEmp)
|
||||
},
|
||||
},
|
||||
methods: {},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
</style>
|
37
cmdb-ui/src/views/setting/components/relateEmployee.vue
Normal file
37
cmdb-ui/src/views/setting/components/relateEmployee.vue
Normal file
@@ -0,0 +1,37 @@
|
||||
<template>
|
||||
<a-modal title="关联员工" :visible="visible" @cancel="handleCancel" @ok="handleOK">
|
||||
<EmployeeTreeSelect v-model="values" :multiple="true" />
|
||||
</a-modal>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import EmployeeTreeSelect from './employeeTreeSelect.vue'
|
||||
export default {
|
||||
name: 'RelateEmployee',
|
||||
components: { EmployeeTreeSelect },
|
||||
data() {
|
||||
return {
|
||||
visible: false,
|
||||
values: [],
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
open() {
|
||||
this.visible = true
|
||||
},
|
||||
handleCancel() {
|
||||
this.visible = false
|
||||
this.values = []
|
||||
},
|
||||
handleOK() {
|
||||
this.$emit('relate', {
|
||||
action: 'add',
|
||||
employee_id_list: this.values.filter((item) => String(item).includes('-')).map((item) => item.split('-')[1]),
|
||||
})
|
||||
this.handleCancel()
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style></style>
|
@@ -0,0 +1,33 @@
|
||||
export const ruleTypeList = [
|
||||
{ value: '&', label: '与' },
|
||||
{ value: '|', label: '或' },
|
||||
// { value: 'not', label: '非' },
|
||||
]
|
||||
|
||||
export const expList = [
|
||||
{ value: 1, label: '等于' },
|
||||
{ value: 2, label: '不等于' },
|
||||
// { value: 'contain', label: '包含' },
|
||||
// { value: '~contain', label: '不包含' },
|
||||
// { value: 'start_with', label: '以...开始' },
|
||||
// { value: '~start_with', label: '不以...开始' },
|
||||
// { value: 'end_with', label: '以...结束' },
|
||||
// { value: '~end_with', label: '不以...结束' },
|
||||
{ value: 7, label: '为空' }, // 为空的定义有点绕
|
||||
{ value: 8, label: '不为空' },
|
||||
]
|
||||
|
||||
export const advancedExpList = [
|
||||
// { value: 'in', label: 'in查询' },
|
||||
// { value: '~in', label: '非in查询' },
|
||||
// { value: 'range', label: '范围' },
|
||||
// { value: '~range', label: '范围外' },
|
||||
{ value: 'compare', label: '比较' },
|
||||
]
|
||||
|
||||
export const compareTypeList = [
|
||||
{ value: 5, label: '大于' },
|
||||
// { value: '2', label: '>=' },
|
||||
{ value: 6, label: '小于' },
|
||||
// { value: '4', label: '<=' },
|
||||
]
|
380
cmdb-ui/src/views/setting/components/settingFilterComp/index.vue
Normal file
380
cmdb-ui/src/views/setting/components/settingFilterComp/index.vue
Normal file
@@ -0,0 +1,380 @@
|
||||
<template>
|
||||
<a-popover
|
||||
v-model="visible"
|
||||
trigger="click"
|
||||
:placement="placement"
|
||||
overlayClassName="table-filter"
|
||||
@visibleChange="visibleChange"
|
||||
>
|
||||
<slot name="popover_item">
|
||||
<a-button type="primary" ghost>条件过滤<a-icon type="filter"/></a-button>
|
||||
</slot>
|
||||
<template slot="content">
|
||||
<svg
|
||||
:style="{ position: 'absolute', top: '0', left: '0', width: '110px', height: '100%', zIndex: '-1' }"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
version="1.1"
|
||||
height="100%"
|
||||
width="100%"
|
||||
id="svgDom"
|
||||
></svg>
|
||||
<a-space :style="{ display: 'flex', marginBottom: '10px' }" v-for="(item, index) in ruleList" :key="item.id">
|
||||
<div :style="{ width: '50px', height: '24px', position: 'relative' }">
|
||||
<treeselect
|
||||
v-if="index"
|
||||
class="custom-treeselect"
|
||||
:style="{ width: '50px', '--custom-height': '24px', position: 'absolute', top: '-17px', left: 0 }"
|
||||
v-model="item.relation"
|
||||
:multiple="false"
|
||||
:clearable="false"
|
||||
searchable
|
||||
:options="ruleTypeList"
|
||||
:normalizer="
|
||||
(node) => {
|
||||
return {
|
||||
id: node.value,
|
||||
label: node.label,
|
||||
children: node.children,
|
||||
}
|
||||
}
|
||||
"
|
||||
>
|
||||
</treeselect>
|
||||
</div>
|
||||
<treeselect
|
||||
class="custom-treeselect"
|
||||
:style="{ width: '130px', '--custom-height': '24px' }"
|
||||
v-model="item.column"
|
||||
:multiple="false"
|
||||
:clearable="false"
|
||||
searchable
|
||||
:options="canSearchPreferenceAttrList"
|
||||
:normalizer="
|
||||
(node) => {
|
||||
return {
|
||||
id: node.value,
|
||||
label: node.label,
|
||||
children: node.children,
|
||||
}
|
||||
}
|
||||
"
|
||||
>value
|
||||
<div
|
||||
:title="node.label"
|
||||
slot="option-label"
|
||||
slot-scope="{ node }"
|
||||
:style="{ width: '100%', whiteSpace: 'nowrap', textOverflow: 'ellipsis', overflow: 'hidden' }"
|
||||
>
|
||||
<!-- <ValueTypeMapIcon :attr="node.raw" /> -->
|
||||
{{ node.label }}
|
||||
</div>
|
||||
<div
|
||||
:style="{ width: '100%', whiteSpace: 'nowrap', textOverflow: 'ellipsis', overflow: 'hidden' }"
|
||||
slot="value-label"
|
||||
slot-scope="{ node }"
|
||||
>
|
||||
<!-- <ValueTypeMapIcon :attr="node.raw" /> -->
|
||||
{{ node.label }}
|
||||
</div>
|
||||
</treeselect>
|
||||
<treeselect
|
||||
class="custom-treeselect"
|
||||
:style="{ width: '100px', '--custom-height': '24px' }"
|
||||
v-model="item.operator"
|
||||
:multiple="false"
|
||||
:clearable="false"
|
||||
searchable
|
||||
:options="[...expList, ...compareTypeList]"
|
||||
:normalizer="
|
||||
(node) => {
|
||||
return {
|
||||
id: node.value,
|
||||
label: node.label,
|
||||
children: node.children,
|
||||
}
|
||||
}
|
||||
"
|
||||
@select="(value) => handleChangeExp(value, item, index)"
|
||||
>
|
||||
</treeselect>
|
||||
<treeselect
|
||||
class="custom-treeselect"
|
||||
:style="{ width: '175px', '--custom-height': '24px' }"
|
||||
v-model="item.value"
|
||||
:multiple="false"
|
||||
:clearable="false"
|
||||
searchable
|
||||
v-if="isChoiceByProperty(item.column) && (item.operator === 1 || item.operator === 2)"
|
||||
:options="getChoiceValueByProperty(item.column)"
|
||||
placeholder="请选择"
|
||||
:normalizer="
|
||||
(node) => {
|
||||
return {
|
||||
id: node.value,
|
||||
label: node.label,
|
||||
children: node.children,
|
||||
}
|
||||
}
|
||||
"
|
||||
>
|
||||
<div
|
||||
:title="node.label"
|
||||
slot="option-label"
|
||||
slot-scope="{ node }"
|
||||
:style="{ width: '100%', whiteSpace: 'nowrap', textOverflow: 'ellipsis', overflow: 'hidden' }"
|
||||
>
|
||||
{{ node.label }}
|
||||
</div>
|
||||
</treeselect>
|
||||
<div v-else-if="item.column === 'direct_supervisor_id' && (item.operator === 1 || item.operator === 2)" style="width: 175px">
|
||||
<EmployeeTreeSelect v-model="item.value" className="custom-treeselect"/>
|
||||
</div>
|
||||
<a-input
|
||||
v-else-if="item.operator !== 7 && item.operator !== 8"
|
||||
size="small"
|
||||
v-model="item.value"
|
||||
:placeholder="item.exp === 'in' || item.exp === '~in' ? '以 ; 分隔' : ''"
|
||||
class="ops-input"
|
||||
></a-input>
|
||||
<!-- <div v-else :style="{ width: '175px' }"></div> -->
|
||||
<a-tooltip title="复制">
|
||||
<a class="operation" @click="handleCopyRule(item)"><a-icon type="copy"/></a>
|
||||
</a-tooltip>
|
||||
<a-tooltip title="删除">
|
||||
<a class="operation" @click="handleDeleteRule(item)" :style="{ color: 'red' }"><a-icon type="delete"/></a>
|
||||
</a-tooltip>
|
||||
|
||||
</a-space>
|
||||
<div class="table-filter-add">
|
||||
<a @click="handleAddRule">+ 新增</a>
|
||||
</div>
|
||||
<a-divider :style="{ margin: '10px 0' }" />
|
||||
<div style="width:534px">
|
||||
<a-space :style="{ display: 'flex', justifyContent: 'flex-end' }">
|
||||
<a-button type="primary" size="small" @click="handleSubmit">确定</a-button>
|
||||
<a-button size="small" @click="handleClear">清空</a-button>
|
||||
</a-space>
|
||||
</div>
|
||||
</template>
|
||||
</a-popover>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import _ from 'lodash'
|
||||
import { v4 as uuidv4 } from 'uuid'
|
||||
import Treeselect from '@riophae/vue-treeselect'
|
||||
import { ruleTypeList, expList, advancedExpList, compareTypeList } from './constants'
|
||||
import DepartmentTreeSelect from '../../components/departmentTreeSelect.vue'
|
||||
import EmployeeTreeSelect from '../../components/employeeTreeSelect.vue'
|
||||
|
||||
export default {
|
||||
name: 'FilterComp',
|
||||
components: {
|
||||
// ValueTypeMapIcon,
|
||||
Treeselect,
|
||||
DepartmentTreeSelect,
|
||||
EmployeeTreeSelect },
|
||||
props: {
|
||||
canSearchPreferenceAttrList: {
|
||||
type: Array,
|
||||
required: true,
|
||||
default: () => [],
|
||||
},
|
||||
regQ: {
|
||||
type: String,
|
||||
default: '(?<=q=).+(?=&)|(?<=q=).+$',
|
||||
},
|
||||
placement: {
|
||||
type: String,
|
||||
default: 'bottomRight',
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
ruleTypeList,
|
||||
expList,
|
||||
advancedExpList,
|
||||
compareTypeList,
|
||||
visible: false,
|
||||
ruleList: [],
|
||||
filterExp: '',
|
||||
}
|
||||
},
|
||||
inject: ['provide_allFlatEmployees'],
|
||||
computed: {
|
||||
allFlatEmployees() {
|
||||
return this.provide_allFlatEmployees()
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
visibleChange(open) {
|
||||
// const regQ = /(?<=q=).+(?=&)|(?<=q=).+$/g
|
||||
const _exp = this.ruleList.length
|
||||
? this.ruleList
|
||||
: null
|
||||
if (open && _exp) {
|
||||
_exp.forEach((item, index) => {
|
||||
if (item.column === 'direct_supervisor_id' && item.value) {
|
||||
if (!(item.value + '').includes('-')) {
|
||||
const _find = this.allFlatEmployees.find((v) => v.employee_id === item.value)
|
||||
_exp[index].value = `${_find.department_id}-${item.value}`
|
||||
}
|
||||
}
|
||||
})
|
||||
this.ruleList = _exp
|
||||
} else if (open) {
|
||||
this.ruleList = [
|
||||
{
|
||||
id: uuidv4(),
|
||||
relation: '&',
|
||||
column: this.canSearchPreferenceAttrList[0].value,
|
||||
operator: 1,
|
||||
value: null,
|
||||
},
|
||||
]
|
||||
}
|
||||
},
|
||||
handleAddRule() {
|
||||
this.ruleList.push({
|
||||
id: uuidv4(),
|
||||
relation: '&',
|
||||
column: this.canSearchPreferenceAttrList[0].value,
|
||||
operator: 1,
|
||||
value: null,
|
||||
})
|
||||
},
|
||||
handleCopyRule(item) {
|
||||
this.ruleList.push({ ...item, id: uuidv4() })
|
||||
},
|
||||
handleDeleteRule(item) {
|
||||
const idx = this.ruleList.findIndex((r) => r.id === item.id)
|
||||
if (idx > -1) {
|
||||
this.ruleList.splice(idx, 1)
|
||||
}
|
||||
},
|
||||
handleClear() {
|
||||
this.ruleList = [
|
||||
{
|
||||
id: uuidv4(),
|
||||
relation: '&',
|
||||
column: this.canSearchPreferenceAttrList[0].value,
|
||||
operator: 1,
|
||||
value: null,
|
||||
},
|
||||
]
|
||||
this.filterExp = []
|
||||
this.visible = false
|
||||
this.$emit('setExpFromFilter', this.filterExp)
|
||||
},
|
||||
handleSubmit() {
|
||||
if (this.ruleList && this.ruleList.length) {
|
||||
const getDataFromRuleList = this.ruleList
|
||||
getDataFromRuleList.forEach((item, index) => {
|
||||
if (item.column === 'direct_supervisor_id') {
|
||||
getDataFromRuleList[index].value = item.value ? (item.value + '').includes('-') ? +item.value.split('-')[1] : +item.value : 0
|
||||
}
|
||||
})
|
||||
getDataFromRuleList[0].relation = '&' // 增删后,以防万一第一个不是and
|
||||
this.$emit('setExpFromFilter', getDataFromRuleList)
|
||||
} else {
|
||||
this.$emit('setExpFromFilter', '')
|
||||
}
|
||||
this.visible = false
|
||||
},
|
||||
handleChangeExp({ value }, item, index) {
|
||||
const _ruleList = _.cloneDeep(this.ruleList)
|
||||
if (value === 7 || value === 8) {
|
||||
_ruleList[index] = {
|
||||
..._ruleList[index],
|
||||
value: null,
|
||||
operator: value
|
||||
}
|
||||
} else {
|
||||
_ruleList[index] = {
|
||||
..._ruleList[index],
|
||||
operator: value,
|
||||
}
|
||||
}
|
||||
this.ruleList = _ruleList
|
||||
},
|
||||
filterOption(input, option) {
|
||||
return option.componentOptions.children[1].children[0].text.toLowerCase().indexOf(input.toLowerCase()) >= 0
|
||||
},
|
||||
// getExpListByProperty(column) {
|
||||
// if (column) {
|
||||
// const _find = this.canSearchPreferenceAttrList.find((item) => item.value === column)
|
||||
// if (_find && ['0', '1', '3', '4', '5'].includes(_find.value_type)) {
|
||||
// return [
|
||||
// { value: 'is', label: '等于' },
|
||||
// { value: '~is', label: '不等于' },
|
||||
// { value: '~value', label: '为空' }, // 为空的定义有点绕
|
||||
// { value: 'value', label: '不为空' },
|
||||
// ]
|
||||
// }
|
||||
// return this.expList
|
||||
// }
|
||||
// return this.expList
|
||||
// },
|
||||
isChoiceByProperty(column) {
|
||||
const _find = this.canSearchPreferenceAttrList.find((item) => item.value === column)
|
||||
if (_find) {
|
||||
return _find.is_choice
|
||||
}
|
||||
return false
|
||||
},
|
||||
getChoiceValueByProperty(column) {
|
||||
const _find = this.canSearchPreferenceAttrList.find((item) => item.value === column)
|
||||
if (_find) {
|
||||
return _find.choice_value
|
||||
}
|
||||
return []
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.table-filter {
|
||||
.table-filter-add {
|
||||
margin-top: 10px;
|
||||
& > a {
|
||||
padding: 2px 8px;
|
||||
&:hover {
|
||||
background-color: #f0faff;
|
||||
border-radius: 5px;
|
||||
}
|
||||
}
|
||||
}
|
||||
.table-filter-extra-icon {
|
||||
padding: 0px 2px;
|
||||
&:hover {
|
||||
display: inline-block;
|
||||
border-radius: 5px;
|
||||
background-color: #f0faff;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.table-filter-extra-operation {
|
||||
.ant-popover-inner-content {
|
||||
padding: 3px 4px;
|
||||
.operation {
|
||||
cursor: pointer;
|
||||
width: 90px;
|
||||
height: 30px;
|
||||
line-height: 30px;
|
||||
padding: 3px 4px;
|
||||
border-radius: 5px;
|
||||
transition: all 0.3s;
|
||||
&:hover {
|
||||
background-color: #f0faff;
|
||||
}
|
||||
> .anticon {
|
||||
margin-right: 10px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
32
cmdb-ui/src/views/setting/components/spanTitle.vue
Normal file
32
cmdb-ui/src/views/setting/components/spanTitle.vue
Normal file
@@ -0,0 +1,32 @@
|
||||
<template>
|
||||
<a-row>
|
||||
<a-col :span="span">
|
||||
<div class="ops-setting-spantitle"><slot></slot></div>
|
||||
</a-col>
|
||||
</a-row>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'SpanTitle',
|
||||
props: {
|
||||
span: {
|
||||
type: Number,
|
||||
default: 3,
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.ops-setting-spantitle {
|
||||
height: 28px;
|
||||
margin-bottom: 12px;
|
||||
line-height: 28px;
|
||||
padding-left: 24px;
|
||||
border-radius: 0px 20px 20px 0px;
|
||||
font-weight: 700;
|
||||
color: #0637bf;
|
||||
background-color: #e0e9ff;
|
||||
}
|
||||
</style>
|
Reference in New Issue
Block a user