Skip to content

Commit 4ce6368

Browse files
author
breezeli
authored
Merge pull request #2843 from joe511230/v3.2.x_bugfix
UI: 主机字符类型字段支持批量模糊查询 Former-commit-id: e94f2c0
2 parents 5fd9b20 + cc64aee commit 4ce6368

File tree

5 files changed

+154
-11
lines changed

5 files changed

+154
-11
lines changed

src/ui/src/assets/scss/common.scss

+2-1
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,8 @@ a:focus {
6262
display: none;
6363
}
6464

65-
input::-webkit-input-placeholder {
65+
input::-webkit-input-placeholder,
66+
textarea::-webkit-input-placeholder {
6667
color: #c3cdd7;
6768
font-size: 12px;
6869
}

src/ui/src/components/hosts/filter/_filter-field-operator.vue

+1-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
name: this.$t('Common[\'不等于\']')
1717
}],
1818
'char': [{
19-
id: '$regex',
19+
id: '$multilike',
2020
name: this.$t('Common[\'包含\']')
2121
}, {
2222
id: '$eq',

src/ui/src/components/hosts/filter/_filter.vue

+16-7
Original file line numberDiff line numberDiff line change
@@ -43,10 +43,10 @@
4343
v-else-if="property['bk_property_type'] === 'bool'"
4444
v-model="condition[property['bk_obj_id']][property['bk_property_id']]['value']">
4545
</cmdb-form-bool-input>
46-
<cmdb-form-associate-input class="filter-field-value filter-field-associate fr"
47-
v-else-if="['singleasst', 'multiasst'].includes(property['bk_property_type'])"
48-
v-model="condition[property['bk_obj_id']][property['bk_property_id']]['value']">
49-
</cmdb-form-associate-input>
46+
<cmdb-search-input class="filter-field-value fr"
47+
v-else-if="['singlechar', 'longchar'].includes(property.bk_property_type)"
48+
v-model="condition[property.bk_obj_id][property.bk_property_id].value">
49+
</cmdb-search-input>
5050
<component class="filter-field-value fr" :class="`filter-field-${property['bk_property_type']}`"
5151
v-else
5252
:is="`cmdb-form-${property['bk_property_type']}`"
@@ -313,14 +313,13 @@
313313
}
314314
// 填充必要模型查询参数
315315
const requiredObj = ['biz', 'host', 'set', 'module']
316-
const normalProperties = this.customFieldProperties.filter(property => !['singleasst', 'multiasst'].includes(property['bk_property_type']))
317316
requiredObj.forEach(objId => {
318317
const objParams = {
319318
'bk_obj_id': objId,
320319
condition: [],
321320
fields: []
322321
}
323-
const objProperties = normalProperties.filter(property => property['bk_obj_id'] === objId)
322+
const objProperties = this.customFieldProperties.filter(property => property['bk_obj_id'] === objId)
324323
objProperties.forEach(property => {
325324
const propertyCondition = this.condition[objId][property['bk_property_id']]
326325
// 必要模型参数合法时,填充对应模型的condition
@@ -329,6 +328,8 @@
329328
if (propertyCondition.operator === '$in') {
330329
let splitValue = [...(new Set(value.split(',').map(val => val.trim())))]
331330
value = splitValue.length > 1 ? [...splitValue, value] : splitValue
331+
} else if (propertyCondition.operator === '$multilike') {
332+
value = value.split('\n').filter(str => str.trim().length).map(str => str.trim())
332333
}
333334
objParams.condition.push({
334335
...propertyCondition,
@@ -377,9 +378,16 @@
377378
getPropertyCondition (property) {
378379
const objId = property['bk_obj_id']
379380
const propertyId = property['bk_property_id']
381+
const propertyType = property.bk_property_type
382+
let operator = '$eq'
383+
if (['bk_set_name', 'bk_module_name'].includes(propertyId)) {
384+
operator = '$in'
385+
} else if (['singlechar', 'longchar'].includes(propertyType)) {
386+
operator = '$multilike'
387+
}
380388
const condition = {
381389
field: propertyId,
382-
operator: '',
390+
operator: operator,
383391
value: ''
384392
}
385393
const collectionConditon = (this.applyingConditions[objId] || []).find(condition => condition.field === propertyId)
@@ -578,6 +586,7 @@
578586
&.sticky {
579587
border-top: 1px solid $cmdbBorderColor;
580588
padding: 10px 20px 0;
589+
z-index: 101;
581590
}
582591
.collection-button.collecting {
583592
color: #ffb400;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
<template>
2+
<div class="cmdb-search-input">
3+
<div class="search-input-wrapper">
4+
<textarea ref="textarea"
5+
v-model="localValue"
6+
:rows="rows"
7+
:placeholder="$t('请输入关键词')"
8+
@focus="handleFocus"
9+
@blur="handleBlur"
10+
@input="setValue"
11+
@keydown.enter="handleEnter"
12+
@keydown.delete="handleDelete">
13+
</textarea>
14+
<i class="bk-icon icon-close"
15+
v-show="focus && localValue.length"
16+
@click="handleClear">
17+
</i>
18+
</div>
19+
</div>
20+
</template>
21+
22+
<script>
23+
export default {
24+
name: 'cmdb-search-input',
25+
props: {
26+
value: {
27+
type: String,
28+
default: ''
29+
}
30+
},
31+
data () {
32+
return {
33+
localValue: this.value,
34+
rows: 1,
35+
timer: null,
36+
focus: false
37+
}
38+
},
39+
watch: {
40+
value (value) {
41+
this.setLocalValue()
42+
}
43+
},
44+
created () {
45+
this.setRows()
46+
},
47+
methods: {
48+
setLocalValue () {
49+
if (this.localValue !== this.value) {
50+
this.localValue = this.value
51+
}
52+
},
53+
setValue () {
54+
this.$emit('input', this.localValue)
55+
},
56+
handleClear () {
57+
this.timer && clearTimeout(this.timer)
58+
this.localValue = ''
59+
this.rows = 1
60+
this.$refs.textarea.focus()
61+
this.setValue()
62+
this.$emit('clear')
63+
},
64+
setRows () {
65+
const rows = this.localValue.split('\n').length
66+
this.rows = Math.min(5, Math.max(rows, 1))
67+
},
68+
handleFocus () {
69+
this.setRows()
70+
this.focus = true
71+
},
72+
handleBlur () {
73+
this.focus = false
74+
this.timer = setTimeout(() => {
75+
this.rows = 1
76+
this.$refs.textarea.scrollTop = 0
77+
}, 200)
78+
},
79+
handleEnter () {
80+
this.rows = Math.min(this.rows + 1, 5)
81+
},
82+
handleDelete () {
83+
this.$nextTick(() => {
84+
this.setRows()
85+
})
86+
}
87+
}
88+
}
89+
</script>
90+
<style lang="scss" scoped>
91+
.cmdb-search-input {
92+
position: relative;
93+
.search-input-wrapper {
94+
position: absolute;
95+
top: 0;
96+
left: 0;
97+
width: 100%;
98+
line-height: 24px;
99+
z-index: 100;
100+
textarea {
101+
display: block;
102+
width: 100%;
103+
padding: 5px 20px 5px 10px;
104+
border: 1px solid #c3cdd7;
105+
resize: none;
106+
font-size: 14px;
107+
@include scrollbar-y;
108+
}
109+
.icon-close {
110+
display: block;
111+
position: absolute;
112+
top: 50%;
113+
right: 4px;
114+
width: 28px;
115+
height: 28px;
116+
line-height: 28px;
117+
text-align: center;
118+
transform: translate3d(0, -50%, 0) scale(.5);
119+
font-size: 12px;
120+
border-radius: 50%;
121+
background-color: #C4C6CC;
122+
color: #fff;
123+
cursor: pointer;
124+
&:hover {
125+
background-color: #979BA5;
126+
}
127+
}
128+
}
129+
}
130+
</style>

src/ui/src/components/ui/index.js

+5-2
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import tree from './tree/tree.vue'
2525
import resize from './other/resize.vue'
2626
import collapseTransition from './transition/collapse.js'
2727
import collapse from './collapse/collapse'
28+
import searchInput from './form/search-input.vue'
2829
const install = (Vue, opts = {}) => {
2930
const components = [
3031
businessSelector,
@@ -52,7 +53,8 @@ const install = (Vue, opts = {}) => {
5253
tree,
5354
resize,
5455
collapseTransition,
55-
collapse
56+
collapse,
57+
searchInput
5658
]
5759
components.forEach(component => {
5860
Vue.component(component.name, component)
@@ -85,5 +87,6 @@ export default {
8587
associateInput,
8688
tree,
8789
resize,
88-
collapseTransition
90+
collapseTransition,
91+
searchInput
8992
}

0 commit comments

Comments
 (0)