feat(ui): optimize batch operations for auto-discovery pool

This commit is contained in:
LH_R
2025-09-18 16:04:01 +08:00
parent 6661eb846d
commit e9342f1101
3 changed files with 198 additions and 152 deletions

View File

@@ -603,6 +603,8 @@ const cmdb_en = {
acceptTime: 'Accept Time', acceptTime: 'Accept Time',
confirmAccept: 'Confirm Accept?', confirmAccept: 'Confirm Accept?',
acceptSuccess: 'Accept successfully', acceptSuccess: 'Accept successfully',
batchAccept: 'Currently being stored...',
batchAccept2: 'Currently being stored: {total} items, {successNum} successful, {errorNum} failed',
isAccept: 'Accept', isAccept: 'Accept',
deleteADC: 'Confirm to delete this data?', deleteADC: 'Confirm to delete this data?',
batchDelete: 'Confirm to delete this data?', batchDelete: 'Confirm to delete this data?',

View File

@@ -603,6 +603,8 @@ const cmdb_zh = {
acceptTime: '入库时间', acceptTime: '入库时间',
confirmAccept: '确认入库?', confirmAccept: '确认入库?',
acceptSuccess: '入库成功', acceptSuccess: '入库成功',
batchAccept: '正在入库...',
batchAccept2: '正在入库,共{total}个,成功{successNum}个,失败{errorNum}个',
isAccept: '入库', isAccept: '入库',
deleteADC: '确认删除该条数据?', deleteADC: '确认删除该条数据?',
batchDelete: '确认删除这些数据?', batchDelete: '确认删除这些数据?',

View File

@@ -33,141 +33,142 @@
<template #two> <template #two>
<div id="discovery-ci"> <div id="discovery-ci">
<AdcCounter :typeId="currentType" /> <AdcCounter :typeId="currentType" />
<div class="discovery-ci-header"> <a-spin :tip="loadTip" :spinning="loading">
<a-input-search <div class="discovery-ci-header">
:placeholder="$t('cmdb.components.pleaseSearch')" <a-input-search
:style="{ width: '200px' }" :placeholder="$t('cmdb.components.pleaseSearch')"
@search="handleSearch" :style="{ width: '200px' }"
allowClear @search="handleSearch"
/> allowClear
<span class="ops-list-batch-action" v-show="selectedCount"> />
<span @click="batchAccept">{{ $t('cmdb.ad.accept') }}</span> <span class="ops-list-batch-action" v-show="selectedCount">
<a-divider type="vertical" /> <span @click="batchAccept">{{ $t('cmdb.ad.accept') }}</span>
<span @click="batchDelete">{{ $t('delete') }}</span> <a-divider type="vertical" />
<span>{{ $t('cmdb.ci.selectRows', { rows: selectedCount }) }}</span> <span @click="batchDelete">{{ $t('delete') }}</span>
</span> <span>{{ $t('cmdb.ci.selectRows', { rows: selectedCount }) }}</span>
<a-button </span>
type="primary" <a-button
class="ops-button-ghost" type="primary"
ghost class="ops-button-ghost"
@click="getAdc()" ghost
@click="getAdc()"
>
<ops-icon type="veops-refresh" />
{{ $t('refresh') }}
</a-button>
<a-button
type="primary"
ghost
class="ops-button-ghost discovery-ci-log"
@click="clickLog"
>
<ops-icon type="a-cmdb-log1" />
<span>{{ $t('cmdb.ad.log') }}</span>
</a-button>
</div>
<ops-table
show-overflow
show-header-overflow
resizable
ref="xTable"
size="mini"
stripe
class="ops-stripe-table checkbox-hover-table"
:data="filterTableData"
:height="tableHeight"
:scroll-y="{ enabled: true, gt: 50 }"
:scroll-x="{ enabled: true, gt: 0 }"
:checkbox-config="{ reserve: true, highlight: true, range: true }"
:sort-config="{ remote: false, trigger: 'cell' }"
@checkbox-change="onSelectChange"
@checkbox-all="onSelectChange"
@checkbox-range-end="onSelectChange"
> >
<ops-icon type="veops-refresh" /> <vxe-column
{{ $t('refresh') }} align="center"
</a-button> type="checkbox"
<a-button width="60"
type="primary" fixed="left"
ghost >
class="ops-button-ghost discovery-ci-log" <template #default="{row}">
@click="clickLog" {{ getRowSeq(row) }}
> </template>
<ops-icon type="a-cmdb-log1" /> </vxe-column>
<span>{{ $t('cmdb.ad.log') }}</span> <vxe-column
</a-button> v-for="(col, index) in columns"
</div> :key="`${col.field}_${index}`"
<ops-table :title="col.title"
show-overflow :field="col.field"
show-header-overflow :width="col.width"
resizable :sortable="col.sortable"
ref="xTable" >
size="mini" <template #default="{row}">
stripe <PasswordField
class="ops-stripe-table checkbox-hover-table" v-if="col.is_password"
:data="filterTableData" :password="row[col.field]"
:height="tableHeight" />
:scroll-y="{ enabled: true, gt: 50 }" <span>
:scroll-x="{ enabled: true, gt: 0 }" {{ typeof row[col.field] === 'object' ? JSON.stringify(row[col.field]) : row[col.field] }}
:loading="loading" </span>
@checkbox-change="onSelectChange" </template>
@checkbox-all="onSelectChange" </vxe-column>
@checkbox-range-end="onSelectChange" <vxe-column
:checkbox-config="{ reserve: true, highlight: true, range: true }" field="accept_by"
:sort-config="{ remote: false, trigger: 'cell' }" :title="$t('cmdb.ad.acceptBy')"
> v-bind="columns.length ? { width: '80px' } : { minWidth: '80px' }"
<vxe-column :filters="acceptByFilters"
align="center" ></vxe-column>
type="checkbox" <vxe-column
width="60" align="center"
fixed="left" field="is_accept"
> :title="$t('cmdb.ad.isAccept')"
<template #default="{row}"> v-bind="columns.length ? { width: '80px' } : { minWidth: '80px' }"
{{ getRowSeq(row) }} :filters="[
{ label: $t('yes'), value: true },
{ label: $t('no'), value: false },
]"
fixed="right"
>
<template #default="{row}">
<ops-icon
:type="row.is_accept ? 'cmdb-warehousing' : 'cmdb-not_warehousing'"
:style="{ color: row.is_accept ? '#00B42A' : '#A5A9BC' }"
/>
</template>
</vxe-column>
<vxe-column
field="accept_time"
:title="$t('cmdb.ad.acceptTime')"
sortable
v-bind="columns.length ? { width: '150px' } : { minWidth: '150px' }"
fixed="right"
></vxe-column>
<vxe-column
:title="$t('operation')"
v-bind="columns.length ? { width: '100px' } : { minWidth: '100px' }"
align="center"
fixed="right"
>
<template #default="{row}">
<a-space>
<a-tooltip :title="$t('cmdb.ad.accept')">
<a v-if="!row.is_accept" @click="accept(row)"><ops-icon type="cmdb-manual_warehousing"/></a>
</a-tooltip>
<a-tooltip :title="$t('cmdb.ad.viewRawData')">
<a @click="viewADC(row)"><a-icon type="eye"/></a>
</a-tooltip>
<a :style="{ color: 'red' }" @click="deleteADC(row)"><a-icon type="delete"/></a>
</a-space>
</template>
</vxe-column>
<template #empty>
<div>
<img :style="{ width: '200px' }" :src="require('@/assets/data_empty.png')" />
<div>{{ $t('noData') }}</div>
</div>
</template> </template>
</vxe-column> </ops-table>
<vxe-column </a-spin>
v-for="(col, index) in columns"
:key="`${col.field}_${index}`"
:title="col.title"
:field="col.field"
:width="col.width"
:sortable="col.sortable"
>
<template #default="{row}">
<PasswordField
v-if="col.is_password"
:password="row[col.field]"
/>
<span>
{{ typeof row[col.field] === 'object' ? JSON.stringify(row[col.field]) : row[col.field] }}
</span>
</template>
</vxe-column>
<vxe-column
field="accept_by"
:title="$t('cmdb.ad.acceptBy')"
v-bind="columns.length ? { width: '80px' } : { minWidth: '80px' }"
:filters="acceptByFilters"
></vxe-column>
<vxe-column
align="center"
field="is_accept"
:title="$t('cmdb.ad.isAccept')"
v-bind="columns.length ? { width: '80px' } : { minWidth: '80px' }"
:filters="[
{ label: $t('yes'), value: true },
{ label: $t('no'), value: false },
]"
fixed="right"
>
<template #default="{row}">
<ops-icon
:type="row.is_accept ? 'cmdb-warehousing' : 'cmdb-not_warehousing'"
:style="{ color: row.is_accept ? '#00B42A' : '#A5A9BC' }"
/>
</template>
</vxe-column>
<vxe-column
field="accept_time"
:title="$t('cmdb.ad.acceptTime')"
sortable
v-bind="columns.length ? { width: '150px' } : { minWidth: '150px' }"
fixed="right"
></vxe-column>
<vxe-column
:title="$t('operation')"
v-bind="columns.length ? { width: '100px' } : { minWidth: '100px' }"
align="center"
fixed="right"
>
<template #default="{row}">
<a-space>
<a-tooltip :title="$t('cmdb.ad.accept')">
<a v-if="!row.is_accept" @click="accept(row)"><ops-icon type="cmdb-manual_warehousing"/></a>
</a-tooltip>
<a-tooltip :title="$t('cmdb.ad.viewRawData')">
<a @click="viewADC(row)"><a-icon type="eye"/></a>
</a-tooltip>
<a :style="{ color: 'red' }" @click="deleteADC(row)"><a-icon type="delete"/></a>
</a-space>
</template>
</vxe-column>
<template #empty>
<div>
<img :style="{ width: '200px' }" :src="require('@/assets/data_empty.png')" />
<div>{{ $t('noData') }}</div>
</div>
</template>
</ops-table>
<a-modal <a-modal
v-model="logModalVisible" v-model="logModalVisible"
@@ -232,7 +233,8 @@ export default {
logTextArray: [], logTextArray: [],
acceptByFilters: [], acceptByFilters: [],
selectedCount: 0, selectedCount: 0,
loading: false loading: false,
loadTip: ''
} }
}, },
computed: { computed: {
@@ -301,6 +303,8 @@ export default {
}, },
getAdc(isInit) { getAdc(isInit) {
this.loading = true this.loading = true
this.loadTip = this.$t('loading')
getAdc({ getAdc({
type_id: this.currentType, type_id: this.currentType,
page_size: 100000, page_size: 100000,
@@ -380,35 +384,73 @@ export default {
}, },
async batchAccept() { async batchAccept() {
let successNum = 0
let errorNum = 0
this.loading = true
this.loadTip = this.$t('cmdb.ad.batchAccept')
for (let i = 0; i < this.selectedRowKeys.length; i++) { for (let i = 0; i < this.selectedRowKeys.length; i++) {
await updateADCAccept(this.selectedRowKeys[i]) await updateADCAccept(this.selectedRowKeys[i]).then((res) => {
successNum += 1
}).catch(() => {
errorNum += 1
}).finally(() => {
this.loadTip = this.$t('cmdb.ad.batchAccept2', {
total: this.selectedRowKeys.length,
successNum: successNum,
errorNum: errorNum,
})
})
} }
this.$message.success(this.$t('cmdb.ad.acceptSuccess'))
this.getAdc(false) this.loading = false
this.loadTip = ''
this.selectedRowKeys = [] this.selectedRowKeys = []
this.getAdc(false)
this.$refs.xTable.getVxetableRef().clearCheckboxRow() this.$refs.xTable.getVxetableRef().clearCheckboxRow()
this.$refs.xTable.getVxetableRef().clearCheckboxReserve() this.$refs.xTable.getVxetableRef().clearCheckboxReserve()
this.$refs.xTable.getVxetableRef().clearSort() this.$refs.xTable.getVxetableRef().clearSort()
}, },
async batchDelete() { async batchDelete() {
const that = this
this.$confirm({ this.$confirm({
title: that.$t('warning'), title: this.$t('warning'),
content: that.$t('cmdb.ad.batchDelete'), content: this.$t('cmdb.ad.batchDelete'),
async onOk() { onOk: () => {
for (let i = 0; i < that.selectedRowKeys.length; i++) { this.batchDeleteAsync()
await deleteAdc(that.selectedRowKeys[i]) }
}
that.$message.success(that.$t('deleteSuccess'))
that.getAdc(false)
that.selectedRowKeys = []
that.$refs.xTable.getVxetableRef().clearCheckboxRow()
that.$refs.xTable.getVxetableRef().clearCheckboxReserve()
that.$refs.xTable.getVxetableRef().clearSort()
},
onCancel() {},
}) })
}, },
async batchDeleteAsync() {
let successNum = 0
let errorNum = 0
this.loading = true
this.loadTip = this.$t('cmdb.ci.batchDeleting')
for (let i = 0; i < this.selectedRowKeys.length; i++) {
await deleteAdc(this.selectedRowKeys[i]).then((res) => {
successNum += 1
}).catch(() => {
errorNum += 1
}).finally(() => {
this.loadTip = this.$t('cmdb.ci.batchDeleting2', {
total: this.selectedRowKeys.length,
successNum: successNum,
errorNum: errorNum,
})
})
}
this.loading = false
this.loadTip = ''
this.selectedRowKeys = []
this.getAdc(false)
this.$refs.xTable.getVxetableRef().clearCheckboxRow()
this.$refs.xTable.getVxetableRef().clearCheckboxReserve()
this.$refs.xTable.getVxetableRef().clearSort()
},
onSelectChange({ records, checked }) { onSelectChange({ records, checked }) {
this.selectedRowKeys = records.map((item) => item.id) this.selectedRowKeys = records.map((item) => item.id)
}, },