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"
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'
9099import { mapState } from ' vuex'
91100import ExcelJS from ' exceljs'
92101import FileSaver from ' file-saver'
93- import { searchCI , deleteCI } from ' @/modules/cmdb/api/ci'
102+ import { searchCI , deleteCI , updateCI } from ' @/modules/cmdb/api/ci'
94103import { getSubscribeAttributes } from ' @/modules/cmdb/api/preference'
95104import { getCITypeAttributesById } from ' @/modules/cmdb/api/CITypeAttr'
96105import { getCITableColumns } from ' @/modules/cmdb/utils/helper'
@@ -100,6 +109,7 @@ import CITable from '@/modules/cmdb/components/ciTable/index.vue'
100109import BatchDownload from ' @/modules/cmdb/components/batchDownload/batchDownload.vue'
101110import CIDetailDrawer from ' @/modules/cmdb/views/ci/modules/ciDetailDrawer.vue'
102111import EditAttrsPopover from ' @/modules/cmdb/views/ci/modules/editAttrsPopover.vue'
112+ import CreateInstanceForm from ' @/modules/cmdb/views/ci/modules/CreateInstanceForm'
103113
104114export 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