Skip to content

Commit 549056a

Browse files
committed
feat(ui): IPAM - ipSearch and subnetList add batch action group
1 parent 365fdf2 commit 549056a

2 files changed

Lines changed: 400 additions & 144 deletions

File tree

cmdb-ui/src/modules/cmdb/views/ipam/modules/ipSearch/index.vue

Lines changed: 200 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -1,79 +1,82 @@
11
<template>
22
<div ref="wrapRef">
3-
<div class="table-header">
4-
<SearchForm
5-
ref="search"
6-
:preferenceAttrList="preferenceAttrList"
7-
:typeId="addressCITypeId"
8-
@copyExpression="copyExpression"
9-
@refresh="handleSearch"
10-
/>
11-
12-
<div class="table-header-right">
13-
<EditAttrsPopover
3+
<a-spin :tip="loadTip" :spinning="loading" >
4+
<div class="table-header">
5+
<SearchForm
6+
ref="search"
7+
:preferenceAttrList="preferenceAttrList"
148
:typeId="addressCITypeId"
15-
@refresh="refreshAfterEditAttrs"
9+
:selectedRowKeys="selectedRowKeys"
10+
@copyExpression="copyExpression"
11+
@refresh="handleSearch"
1612
>
17-
<a-button
18-
type="primary"
19-
ghost
20-
class="ops-button-ghost"
13+
<div class="ops-list-batch-action" v-show="!!selectedRowKeys.length">
14+
<span @click="$refs.create.handleOpen(true, 'update')">{{ $t('update') }}</span>
15+
<a-divider type="vertical" />
16+
<span @click="openBatchDownload">{{ $t('download') }}</span>
17+
<a-divider type="vertical" />
18+
<span @click="batchDelete">{{ $t('delete') }}</span>
19+
<span>{{ $t('cmdb.ci.selectRows', { rows: selectedRowKeys.length }) }}</span>
20+
</div>
21+
</SearchForm>
22+
23+
<div class="table-header-right">
24+
<EditAttrsPopover
25+
:typeId="addressCITypeId"
26+
@refresh="refreshAfterEditAttrs"
2127
>
22-
<ops-icon type="veops-configuration_table" />
23-
{{ $t('cmdb.configTable') }}
24-
</a-button>
25-
</EditAttrsPopover>
26-
<a-button
27-
v-if="instanceList && instanceList.length"
28-
type="primary"
29-
class="ops-button-ghost"
30-
ghost
31-
@click="handleExport"
32-
>
33-
<ops-icon type="veops-export" />
34-
{{ $t('export') }}
35-
</a-button>
28+
<a-button
29+
type="primary"
30+
ghost
31+
class="ops-button-ghost"
32+
>
33+
<ops-icon type="veops-configuration_table" />
34+
{{ $t('cmdb.configTable') }}
35+
</a-button>
36+
</EditAttrsPopover>
37+
</div>
3638
</div>
37-
</div>
38-
39-
<CITable
40-
ref="xTable"
41-
:loading="loading"
42-
:attrList="preferenceAttrList"
43-
:columns="columns"
44-
:data="instanceList"
45-
:height="tableHeight"
46-
@sort-change="handleSortCol"
47-
@openDetail="openDetail"
48-
@deleteCI="deleteCI"
49-
/>
5039

51-
<div class="table-pagination">
52-
<a-pagination
53-
:showSizeChanger="true"
54-
:current="page"
55-
size="small"
56-
:total="totalNumber"
57-
show-quick-jumper
58-
:page-size="pageSize"
59-
:page-size-options="pageSizeOptions"
60-
:show-total="
61-
(total, range) =>
62-
$t('pagination.total', {
63-
range0: range[0],
64-
range1: range[1],
65-
total,
66-
})
67-
"
68-
@change="handleChangePage"
69-
@showSizeChange="onShowSizeChange"
70-
>
71-
<template slot="buildOptionText" slot-scope="props">
72-
<span v-if="props.value !== '100000'">{{ props.value }}{{ $t('itemsPerPage') }}</span>
73-
<span v-if="props.value === '100000'">{{ $t('cmdb.ci.all') }}</span>
74-
</template>
75-
</a-pagination>
76-
</div>
40+
<CITable
41+
ref="xTable"
42+
:loading="loading"
43+
:attrList="preferenceAttrList"
44+
:columns="columns"
45+
:data="instanceList"
46+
:height="tableHeight"
47+
@sort-change="handleSortCol"
48+
@openDetail="openDetail"
49+
@deleteCI="deleteCI"
50+
@onSelectChange="onSelectChange"
51+
/>
52+
53+
<div class="table-pagination">
54+
<a-pagination
55+
:showSizeChanger="true"
56+
:current="page"
57+
size="small"
58+
:total="totalNumber"
59+
show-quick-jumper
60+
:page-size="pageSize"
61+
:page-size-options="pageSizeOptions"
62+
:show-total="
63+
(total, range) =>
64+
$t('pagination.total', {
65+
range0: range[0],
66+
range1: range[1],
67+
total,
68+
})
69+
"
70+
@change="handleChangePage"
71+
@showSizeChange="onShowSizeChange"
72+
>
73+
<template slot="buildOptionText" slot-scope="props">
74+
<span v-if="props.value !== '100000'">{{ props.value }}{{ $t('itemsPerPage') }}</span>
75+
<span v-if="props.value === '100000'">{{ $t('cmdb.ci.all') }}</span>
76+
</template>
77+
</a-pagination>
78+
</div>
79+
</a-spin>
7780

7881
<BatchDownload
7982
ref="batchDownload"
@@ -82,6 +85,12 @@
8285
/>
8386

8487
<CIDetailDrawer ref="detail" :typeId="addressCITypeId" />
88+
89+
<CreateInstanceForm
90+
ref="create"
91+
:typeIdFromRelation="addressCITypeId"
92+
@submit="batchUpdate"
93+
/>
8594
</div>
8695
</template>
8796

@@ -90,7 +99,7 @@ import _ from 'lodash'
9099
import { mapState } from 'vuex'
91100
import ExcelJS from 'exceljs'
92101
import FileSaver from 'file-saver'
93-
import { searchCI, deleteCI } from '@/modules/cmdb/api/ci'
102+
import { searchCI, deleteCI, updateCI } from '@/modules/cmdb/api/ci'
94103
import { getSubscribeAttributes } from '@/modules/cmdb/api/preference'
95104
import { getCITypeAttributesById } from '@/modules/cmdb/api/CITypeAttr'
96105
import { getCITableColumns } from '@/modules/cmdb/utils/helper'
@@ -100,6 +109,7 @@ import CITable from '@/modules/cmdb/components/ciTable/index.vue'
100109
import BatchDownload from '@/modules/cmdb/components/batchDownload/batchDownload.vue'
101110
import CIDetailDrawer from '@/modules/cmdb/views/ci/modules/ciDetailDrawer.vue'
102111
import EditAttrsPopover from '@/modules/cmdb/views/ci/modules/editAttrsPopover.vue'
112+
import CreateInstanceForm from '@/modules/cmdb/views/ci/modules/CreateInstanceForm'
103113
104114
export default {
105115
name: 'IPSearch',
@@ -108,7 +118,8 @@ export default {
108118
CITable,
109119
BatchDownload,
110120
CIDetailDrawer,
111-
EditAttrsPopover
121+
EditAttrsPopover,
122+
CreateInstanceForm
112123
},
113124
props: {
114125
addressCIType: {
@@ -122,6 +133,7 @@ export default {
122133
pageSize: 50,
123134
pageSizeOptions: ['50', '100', '200'],
124135
loading: false,
136+
loadTip: '',
125137
sortByTable: undefined,
126138
127139
instanceList: [],
@@ -130,6 +142,7 @@ export default {
130142
preferenceAttrList: [],
131143
attrList: [],
132144
attributes: {},
145+
selectedRowKeys: [],
133146
}
134147
},
135148
computed: {
@@ -275,7 +288,7 @@ export default {
275288
})
276289
},
277290
278-
handleExport() {
291+
openBatchDownload() {
279292
this.$refs.batchDownload.open({
280293
preferenceAttrList: this.preferenceAttrList,
281294
ciTypeName: this.$t('cmdb.ipam.ipSearch') || '',
@@ -336,6 +349,7 @@ export default {
336349
FileSaver.saveAs(file, `${filename}.xlsx`)
337350
})
338351
352+
this.selectedRowKeys = []
339353
this.$refs.xTable.getVxetableRef().clearCheckboxRow()
340354
this.$refs.xTable.getVxetableRef().clearCheckboxReserve()
341355
},
@@ -361,6 +375,120 @@ export default {
361375
},
362376
})
363377
},
378+
379+
onSelectChange(records) {
380+
this.selectedRowKeys = records.map((i) => i.ci_id || i._id)
381+
},
382+
383+
batchDelete() {
384+
this.$confirm({
385+
title: this.$t('warning'),
386+
content: this.$t('confirmDelete'),
387+
onOk: () => {
388+
this.batchDeleteAsync()
389+
},
390+
})
391+
},
392+
393+
async batchDeleteAsync() {
394+
let successNum = 0
395+
let errorNum = 0
396+
this.loading = true
397+
this.loadTip = this.$t('cmdb.ci.batchDeleting')
398+
399+
const floor = Math.ceil(this.selectedRowKeys.length / 6)
400+
for (let i = 0; i < floor; i++) {
401+
const itemList = this.selectedRowKeys.slice(6 * i, 6 * i + 6)
402+
const promises = itemList.map((x) => deleteCI(x, false))
403+
await Promise.allSettled(promises)
404+
.then((res) => {
405+
res.forEach((r) => {
406+
if (r.status === 'fulfilled') {
407+
successNum += 1
408+
} else {
409+
errorNum += 1
410+
}
411+
})
412+
})
413+
.finally(() => {
414+
this.loadTip = this.$t('cmdb.ci.batchDeleting2', {
415+
total: this.selectedRowKeys.length,
416+
successNum: successNum,
417+
errorNum: errorNum,
418+
})
419+
})
420+
}
421+
422+
this.loading = false
423+
this.loadTip = ''
424+
this.selectedRowKeys = []
425+
this.$refs.xTable.getVxetableRef().clearCheckboxRow()
426+
this.$refs.xTable.getVxetableRef().clearCheckboxReserve()
427+
this.$nextTick(() => {
428+
this.page = 1
429+
this.getTableData()
430+
})
431+
},
432+
433+
batchUpdate(values) {
434+
this.$confirm({
435+
title: this.$t('warning'),
436+
content: this.$t('cmdb.ci.batchUpdateConfirm'),
437+
onOk: () => {
438+
this.batchUpdateAsync(values)
439+
},
440+
})
441+
},
442+
443+
async batchUpdateAsync(values) {
444+
let successNum = 0
445+
let errorNum = 0
446+
this.loading = true
447+
this.loadTip = this.$t('cmdb.ci.batchUpdateInProgress') + '...'
448+
449+
const payload = {}
450+
Object.keys(values).forEach((key) => {
451+
if (values[key] === undefined || values[key] === null) {
452+
payload[key] = null
453+
} else {
454+
payload[key] = values[key]
455+
}
456+
})
457+
this.$refs.create.visible = false
458+
const key = 'updatable'
459+
let errorMsg = ''
460+
461+
for (let i = 0; i < this.selectedRowKeys.length; i++) {
462+
await updateCI(this.selectedRowKeys[i], payload, false)
463+
.then(() => {
464+
successNum += 1
465+
})
466+
.catch((error) => {
467+
errorMsg = errorMsg + '\n' + `${this.selectedRowKeys[i]}:${error.response?.data?.message ?? ''}`
468+
this.$notification.warning({
469+
key,
470+
message: this.$t('warning'),
471+
description: errorMsg,
472+
duration: 0,
473+
style: { whiteSpace: 'break-spaces', overflow: 'auto', maxHeight: this.windowHeight - 80 + 'px' },
474+
})
475+
errorNum += 1
476+
})
477+
.finally(() => {
478+
this.loadTip = this.$t('cmdb.ci.batchUpdateInProgress2', {
479+
total: this.selectedRowKeys.length,
480+
successNum: successNum,
481+
errorNum: errorNum,
482+
})
483+
})
484+
}
485+
this.loading = false
486+
this.loadTip = ''
487+
this.selectedRowKeys = []
488+
this.$refs.xTable.getVxetableRef().clearCheckboxRow()
489+
this.$refs.xTable.getVxetableRef().clearCheckboxReserve()
490+
this.getTableData()
491+
},
364492
}
365493
}
366494
</script>

0 commit comments

Comments
 (0)