perf: update asset create

This commit is contained in:
ibuler
2024-12-20 18:53:35 +08:00
parent 48e4027525
commit 28b4aa0d55
9 changed files with 358 additions and 307 deletions

View File

@@ -102,12 +102,14 @@ export default {
//flex-wrap: nowrap;
//flex-direction: column;
//justify-content: flex-start;
margin-right: 50px;
margin-left: 20px;
//margin-right: 50px;
//margin-left: 20px;
height: 100%;
.el-form-item {
//margin: 5px 0 5px 0;
padding-left: 2px;
&:last-child {
//margin-bottom: 10px;
//padding-bottom: 10px;

View File

@@ -2,7 +2,7 @@
<ElFormRender
:id="id"
ref="form"
:class="mobile ? 'mobile' : 'desktop'"
:class="[mobile ? 'mobile' : 'desktop', {'label-top': iLabelPosition === 'top'}]"
:content="fields"
:form="basicForm"
:label-position="iLabelPosition"
@@ -221,6 +221,14 @@ export default {
color: var(--color-text-primary);
}
&.label-top {
::v-deep .el-form-item {
.el-form-item__content {
width: 100%;
}
}
}
::v-deep .el-form-item {
margin-bottom: 10px;

View File

@@ -80,7 +80,12 @@ export default {
::v-deep {
.el-card.ibox {
//border: none;
border: none;
.el-card__body {
padding-top: 10px;
padding-bottom: 20px;
}
}
.el-drawer__header {

View File

@@ -129,7 +129,8 @@ export default {
},
onCreate() {
this.action = 'create'
this.drawerComponent = this.iCreateDrawer
console.log('DrawerComponent', this.createDrawer)
this.drawerComponent = this.createDrawer
this.$store.dispatch('common/setDrawerActionMeta', {
action: 'create'
}).then(() => {

View File

@@ -3,7 +3,12 @@
<el-alert v-if="helpMessage" show-icon type="info">
<span v-sanitize="helpMessage" class="announcement-main" />
</el-alert>
<ListTable ref="ListTable" :header-actions="iHeaderActions" :table-config="iTableConfig" />
<ListTable
ref="ListTable"
:create-drawer="createDrawer"
:header-actions="iHeaderActions"
:table-config="iTableConfig"
/>
<PlatformDialog :category="category" :visible.sync="showPlatform" @select-platform="createAsset" />
<AssetBulkUpdateDialog
v-if="updateSelectedDialogSetting.visible"
@@ -22,23 +27,12 @@
</template>
<script>
import { ListTable } from '@/components'
import {
ActionsFormatter,
ArrayFormatter,
ChoicesFormatter,
DetailFormatter,
PlatformFormatter,
ProtocolsFormatter
} from '@/components/Table/TableFormatters'
import ListTable from '@/components/Table/DrawerListTable'
import AssetBulkUpdateDialog from './AssetBulkUpdateDialog'
import { connectivityMeta } from '@/components/Apps/AccountListTable/const'
import PlatformDialog from '../components/PlatformDialog'
import GatewayDialog from '@/components/Apps/GatewayDialog'
import { openTaskPage } from '@/utils/jms'
import HostInfoFormatter from '@/components/Table/TableFormatters/HostInfoFormatter'
import AmountFormatter from '@/components/Table/TableFormatters/AmountFormatter.vue'
import AccountDiscoverDialog from './AccountDiscoverDialog.vue'
import { getDefaultConfig } from './const'
export default {
components: {
@@ -89,36 +83,9 @@ export default {
},
data() {
const vm = this
const onAction = (row, action) => {
let routeAction = action
if (action === 'Clone') {
routeAction = 'Create'
}
const routeName = _.capitalize(row.category.value) + routeAction
const route = {
name: routeName,
params: {},
query: {}
}
if (action === 'Clone') {
route.query.clone_from = row.id
} else if (action === 'Update') {
route.params.id = row.id
}
if (['Create', 'Update'].includes(routeAction)) {
route.query.platform = row.platform.id
route.query.type = row.type.value
route.query.category = row.type.category
}
const createInNewPage = this.$route.query.node_id
if (createInNewPage) {
const { href } = vm.$router.resolve(route)
window.open(href, '_blank')
} else {
this.$router.push(route)
}
}
const extraQuery = this.$route.params?.extraQuery || {}
const defaultConfig = getDefaultConfig(vm)
console.log('Default config: ', defaultConfig)
const recentPlatforms = [
{
name: 'linux',
@@ -145,242 +112,23 @@ export default {
dropdown: recentPlatforms
}
return {
createDrawer: '',
drawer: {
'host': () => import('@/views/assets/Asset/AssetCreateUpdate/HostCreateUpdate.vue'),
'web': () => import('@/views/assets/Asset/AssetCreateUpdate/WebCreateUpdate.vue'),
'custom': () => import('@/views/assets/Asset/AssetCreateUpdate/CustomCreateUpdate.vue'),
'cloud': () => import('@/views/assets/Asset/AssetCreateUpdate/CloudsPlatformCreateUpdate.vue'),
'device': () => import('@/views/assets/Asset/AssetCreateUpdate/DeviceCreateUpdate.vue'),
'database': () => import('@/views/assets/Asset/AssetCreateUpdate/DatabaseCreateUpdate.vue')
},
showPlatform: false,
recentPlatforms: recentPlatforms,
createAction: createAction,
gatewayPort: 0,
gatewayCell: '',
gatewayVisible: false,
defaultConfig: {
url: '/api/v1/assets/hosts/',
permissions: {
app: 'assets',
resource: 'asset'
},
extraQuery: {
...extraQuery,
...this.extraQuery
},
columnsExclude: ['spec_info', 'auto_config'],
columnsShow: {
min: ['name', 'address', 'actions'],
default: [
'name', 'address', 'accounts_amount', 'platform',
'connectivity', 'actions'
]
},
columnsMeta: {
type: { formatter: ChoicesFormatter, sortable: false },
category: { formatter: ChoicesFormatter, sortable: false },
name: {
formatter: DetailFormatter,
formatterArgs: {
route: 'AssetDetail'
},
sortable: true
},
platform: {
sortable: true,
formatter: PlatformFormatter
},
protocols: {
showFullContent: true,
formatter: ProtocolsFormatter
},
nodes_display: {
formatter: ArrayFormatter
},
address: {
minWidth: '200px'
},
gathered_info: {
label: this.$t('HardwareInfo'),
formatter: HostInfoFormatter,
formatterArgs: {
info: vm?.optionInfo,
can: vm.$hasPerm('assets.refresh_assethardwareinfo'),
getRoute({ row }) {
return {
name: 'AssetMoreInformationEdit',
params: { id: row.id }
}
}
}
},
accounts_amount: {
label: this.$t('Accounts'),
formatter: AmountFormatter,
width: '100px',
formatterArgs: {
async: true,
getItem(item) {
return `${item.name}(${item.username})`
},
getRoute({ row }) {
return {
name: 'AssetDetail',
params: {
id: row.id
},
query: {
tab: 'Account'
}
}
}
}
},
connectivity: connectivityMeta,
actions: {
formatter: ActionsFormatter,
formatterArgs: {
onUpdate: ({ row }) => onAction(row, 'Update'),
onClone: ({ row }) => onAction(row, 'Clone'),
performDelete: ({ row }) => {
const id = row.id
const url = `/api/v1/assets/assets/${id}/`
return this.$axios.delete(url)
},
extraActions: [
{
name: 'Test',
title: this.$t('Test'),
can: ({ row }) =>
this.$hasPerm('assets.test_assetconnectivity') &&
!this.$store.getters.currentOrgIsRoot &&
row?.auto_config?.ansible_enabled &&
row?.auto_config?.ping_enabled,
callback: ({ row }) => {
if (row.platform.name === 'Gateway') {
this.gatewayVisible = true
const port = row.protocols.find(item => item.name === 'ssh').port
if (!port) {
return this.$message.error(this.$tc('BadRequestErrorMsg'))
} else {
this.gatewayPort = port
this.gatewayCell = row.id
}
} else {
this.$axios.post(
`/api/v1/assets/assets/${row.id}/tasks/`,
{ action: 'test' }
).then(res => {
openTaskPage(res['task'])
})
}
}
},
{
name: 'AddAccount',
title: '添加账号',
divided: true
},
{
name: 'DiscoverAccounts',
title: 'Discover accounts',
callback: ({ row }) => {
console.log('Row: ', row)
vm.discoveryDialog.asset = row.id
console.log('vm.discoveryDialog.asset: ', vm.discoveryDialog)
setTimeout(() => {
vm.discoveryDialog.visible = true
}, 200)
}
},
...this.addExtraMoreColActions
]
}
}
}
},
defaultHeaderActions: {
onCreate: () => {
this.showPlatform = true
},
hasLabelSearch: true,
searchConfig: {
getUrlQuery: false
},
hasCreate: false,
extraMoreActions: [
{
name: 'TestSelected',
title: this.$t('TestSelected'),
type: 'primary',
can: ({ selectedRows }) =>
this.$hasPerm('assets.test_assetconnectivity') &&
!this.$store.getters.currentOrgIsRoot &&
selectedRows.length > 0 &&
selectedRows[0].auto_config?.ansible_enabled &&
selectedRows[0].auto_config?.ping_enabled,
callback: function({ selectedRows }) {
const ids = selectedRows.map(v => {
return v.id
})
this.$axios.post(
'/api/v1/assets/assets/tasks/',
{ action: 'test', assets: ids }).then(res => {
openTaskPage(res['task'])
}).catch(err => {
this.$message.error(this.$tc('common.bulkVerifyErrorMsg' + ' ' + err))
})
}.bind(this)
},
{
name: 'DeactiveSelected',
title: this.$t('DisableSelected'),
type: 'primary',
icon: 'fa fa-ban',
can: ({ selectedRows }) => {
return selectedRows.length > 0 && vm.$hasPerm('assets.change_asset')
},
callback: function({ selectedRows }) {
const ids = selectedRows.map((v) => {
return { pk: v.id, is_active: false }
})
this.$axios.patch(`/api/v1/assets/assets/`, ids).then(res => {
this.$message.success(this.$tc('UpdateSuccessMsg'))
this.$refs.ListTable.reloadTable()
}).catch(err => {
this.$message.error(this.$tc('UpdateErrorMsg' + ' ' + err))
})
}.bind(this)
},
{
name: 'ActiveSelected',
title: this.$t('ActivateSelected'),
type: 'primary',
icon: 'fa fa-check-circle-o',
can: ({ selectedRows }) => {
return selectedRows.length > 0 && vm.$hasPerm('assets.change_asset')
},
callback: function({ selectedRows }) {
const ids = selectedRows.map((v) => {
return { pk: v.id, is_active: true }
})
this.$axios.patch(`/api/v1/assets/assets/`, ids).then(res => {
this.$message.success(this.$tc('UpdateSuccessMsg'))
this.$refs.ListTable.reloadTable()
}).catch(err => {
this.$message.error(this.$tc('UpdateErrorMsg' + ' ' + err))
})
}.bind(this)
},
{
name: 'actionUpdateSelected',
title: this.$t('UpdateSelected'),
icon: 'batch-update',
can: ({ selectedRows }) => {
return selectedRows.length > 0 &&
!this.$store.getters.currentOrgIsRoot &&
vm.$hasPerm('assets.change_asset')
},
callback: ({ selectedRows }) => {
vm.updateSelectedDialogSetting.selectedRows = selectedRows
vm.updateSelectedDialogSetting.visible = true
}
}
]
},
defaultConfig: defaultConfig['tableConfig'],
defaultHeaderActions: defaultConfig['defaultHeaderActions'],
updateSelectedDialogSetting: {
visible: false,
category: this.category,
@@ -438,23 +186,26 @@ export default {
},
methods: {
createAsset(platform) {
const route = _.capitalize(platform.category.value) + 'Create' || 'HostCreate'
this.addToRecentPlatforms(platform)
this.iVisible = false
const query = {
node: this.$route.query?.node || this.$route.query?.node_id || '',
platform: platform.id,
type: platform.type.value,
category: platform.category.value
}
const router = { name: route, query }
if (this.$route.query.node_id) {
const { href } = this.$router.resolve(router)
window.open(href, '_blank')
} else {
this.$router.push(router)
}
this.createDrawer = this.drawer[platform.category.value]
setTimeout(() => {
this.$refs.ListTable.onCreate()
}, 200)
// const route = _.capitalize(platform.category.value) + 'Create' || 'HostCreate'
// this.iVisible = false
// const query = {
// node: this.$route.query?.node || this.$route.query?.node_id || '',
// platform: platform.id,
// type: platform.type.value,
// category: platform.category.value
// }
//
// const router = { name: route, query }
// if (this.$route.query.node_id) {
// const { href } = this.$router.resolve(router)
// window.open(href, '_blank')
// } else {
// this.$router.push(router)
// }
},
handleAssetBulkUpdate() {
this.updateSelectedDialogSetting.visible = false

View File

@@ -1,12 +1,12 @@
<template>
<Dialog
<el-drawer
v-if="iVisible"
:show-cancel="false"
:show-confirm="false"
:title="$tc('SelectPlatform')"
:visible.sync="iVisible"
size="600px"
top="1vh"
width="60%"
>
<div v-loading="loading" class="platform-content">
<el-row :gutter="20">
@@ -20,7 +20,7 @@
<el-col
v-for="(platform, index) of ps"
:key="platform.id"
:span="6"
:span="8"
>
<el-tooltip :content="platform.name">
<el-card
@@ -40,17 +40,14 @@
</el-collapse>
</el-row>
</div>
</Dialog>
</el-drawer>
</template>
<script>
import Dialog from '@/components/Dialog'
import { loadPlatformIcon } from '@/utils/jms'
export default {
name: 'PlatformDialog',
components: {
Dialog
},
name: 'PlatformDrawer',
components: {},
props: {
visible: {
type: Boolean,
@@ -126,6 +123,9 @@ export default {
this.loading = false
},
methods: {
createAsset(platform) {
this.$emit('select-platform', platform)
},
getPlatformLogo(platform) {
return loadPlatformIcon(platform.name, platform.type)
},
@@ -156,6 +156,11 @@ export default {
</script>
<style lang="scss" scoped>
::v-deep .el-drawer__body {
padding: 0 20px;
}
.platform-content {
padding: 0 10px;
}

View File

@@ -0,0 +1,281 @@
import {
ActionsFormatter,
ArrayFormatter,
ChoicesFormatter,
DetailFormatter,
PlatformFormatter,
ProtocolsFormatter
} from '@/components/Table/TableFormatters'
import HostInfoFormatter from '@/components/Table/TableFormatters/HostInfoFormatter.vue'
import AmountFormatter from '@/components/Table/TableFormatters/AmountFormatter.vue'
import { connectivityMeta } from '@/components/Apps/AccountListTable/const'
import { openTaskPage } from '@/utils/jms'
export function getDefaultConfig(vm) {
const onAction = (row, action) => {
let routeAction = action
if (action === 'Clone') {
routeAction = 'Create'
}
const routeName = _.capitalize(row.category.value) + routeAction
const route = {
name: routeName,
params: {},
query: {}
}
if (action === 'Clone') {
route.query.clone_from = row.id
} else if (action === 'Update') {
route.params.id = row.id
}
if (['Create', 'Update'].includes(routeAction)) {
route.query.platform = row.platform.id
route.query.type = row.type.value
route.query.category = row.type.category
}
const createInNewPage = vm.$route.query.node_id
if (createInNewPage) {
const { href } = vm.$router.resolve(route)
window.open(href, '_blank')
} else {
vm.$router.push(route)
}
}
const extraQuery = vm.$route.params?.extraQuery || {}
const defaultHeaderActions = {
onCreate: () => {
vm.showPlatform = true
},
hasLabelSearch: true,
searchConfig: {
getUrlQuery: false
},
hasCreate: false,
extraMoreActions: [
{
name: 'TestSelected',
title: vm.$t('TestSelected'),
type: 'primary',
can: ({ selectedRows }) =>
vm.$hasPerm('assets.test_assetconnectivity') &&
!vm.$store.getters.currentOrgIsRoot &&
selectedRows.length > 0 &&
selectedRows[0].auto_config?.ansible_enabled &&
selectedRows[0].auto_config?.ping_enabled,
callback: function({ selectedRows }) {
const ids = selectedRows.map(v => {
return v.id
})
vm.$axios.post(
'/api/v1/assets/assets/tasks/',
{ action: 'test', assets: ids }).then(res => {
openTaskPage(res['task'])
}).catch(err => {
vm.$message.error(vm.$tc('common.bulkVerifyErrorMsg' + ' ' + err))
})
}
},
{
name: 'DeactiveSelected',
title: vm.$t('DisableSelected'),
type: 'primary',
icon: 'fa fa-ban',
can: ({ selectedRows }) => {
return selectedRows.length > 0 && vm.$hasPerm('assets.change_asset')
},
callback: function({ selectedRows }) {
const ids = selectedRows.map((v) => {
return { pk: v.id, is_active: false }
})
vm.$axios.patch(`/api/v1/assets/assets/`, ids).then(res => {
vm.$message.success(vm.$tc('UpdateSuccessMsg'))
vm.$refs.ListTable.reloadTable()
}).catch(err => {
vm.$message.error(vm.$tc('UpdateErrorMsg' + ' ' + err))
})
}
},
{
name: 'ActiveSelected',
title: vm.$t('ActivateSelected'),
type: 'primary',
icon: 'fa fa-check-circle-o',
can: ({ selectedRows }) => {
return selectedRows.length > 0 && vm.$hasPerm('assets.change_asset')
},
callback: function({ selectedRows }) {
const ids = selectedRows.map((v) => {
return { pk: v.id, is_active: true }
})
vm.$axios.patch(`/api/v1/assets/assets/`, ids).then(res => {
vm.$message.success(vm.$tc('UpdateSuccessMsg'))
vm.$refs.ListTable.reloadTable()
}).catch(err => {
vm.$message.error(vm.$tc('UpdateErrorMsg' + ' ' + err))
})
}
},
{
name: 'actionUpdateSelected',
title: vm.$t('UpdateSelected'),
icon: 'batch-update',
can: ({ selectedRows }) => {
return selectedRows.length > 0 &&
!vm.$store.getters.currentOrgIsRoot &&
vm.$hasPerm('assets.change_asset')
},
callback: ({ selectedRows }) => {
vm.updateSelectedDialogSetting.selectedRows = selectedRows
vm.updateSelectedDialogSetting.visible = true
}
}
]
}
const tableConfig = {
url: '/api/v1/assets/hosts/',
permissions: {
app: 'assets',
resource: 'asset'
},
extraQuery: {
...extraQuery,
...vm.extraQuery
},
columnsExclude: ['spec_info', 'auto_config'],
columnsShow: {
min: ['name', 'address', 'actions'],
default: [
'name', 'address', 'accounts_amount', 'platform',
'connectivity', 'actions'
]
},
columnsMeta: {
type: { formatter: ChoicesFormatter, sortable: false },
category: { formatter: ChoicesFormatter, sortable: false },
name: {
formatter: DetailFormatter,
formatterArgs: {
route: 'AssetDetail'
},
sortable: true
},
platform: {
sortable: true,
formatter: PlatformFormatter
},
protocols: {
showFullContent: true,
formatter: ProtocolsFormatter
},
nodes_display: {
formatter: ArrayFormatter
},
address: {
minWidth: '200px'
},
gathered_info: {
label: vm.$t('HardwareInfo'),
formatter: HostInfoFormatter,
formatterArgs: {
info: vm?.optionInfo,
can: vm.$hasPerm('assets.refresh_assethardwareinfo'),
getRoute({ row }) {
return {
name: 'AssetMoreInformationEdit',
params: { id: row.id }
}
}
}
},
accounts_amount: {
label: vm.$t('Accounts'),
formatter: AmountFormatter,
width: '100px',
formatterArgs: {
async: true,
getItem(item) {
return `${item.name}(${item.username})`
},
getRoute({ row }) {
return {
name: 'AssetDetail',
params: {
id: row.id
},
query: {
tab: 'Account'
}
}
}
}
},
connectivity: connectivityMeta,
actions: {
formatter: ActionsFormatter,
formatterArgs: {
onUpdate: ({ row }) => onAction(row, 'Update'),
onClone: ({ row }) => onAction(row, 'Clone'),
performDelete: ({ row }) => {
const id = row.id
const url = `/api/v1/assets/assets/${id}/`
return vm.$axios.delete(url)
},
extraActions: [
{
name: 'Test',
title: vm.$t('Test'),
can: ({ row }) =>
vm.$hasPerm('assets.test_assetconnectivity') &&
!vm.$store.getters.currentOrgIsRoot &&
row?.auto_config?.ansible_enabled &&
row?.auto_config?.ping_enabled,
callback: ({ row }) => {
if (row.platform.name === 'Gateway') {
vm.gatewayVisible = true
const port = row.protocols.find(item => item.name === 'ssh').port
if (!port) {
return vm.$message.error(vm.$tc('BadRequestErrorMsg'))
} else {
vm.gatewayPort = port
vm.gatewayCell = row.id
}
} else {
vm.$axios.post(
`/api/v1/assets/assets/${row.id}/tasks/`,
{ action: 'test' }
).then(res => {
openTaskPage(res['task'])
})
}
}
},
{
name: 'AddAccount',
title: '添加账号',
divided: true
},
{
name: 'DiscoverAccounts',
title: 'Discover accounts',
callback: ({ row }) => {
console.log('Row: ', row)
vm.discoveryDialog.asset = row.id
console.log('vm.discoveryDialog.asset: ', vm.discoveryDialog)
setTimeout(() => {
vm.discoveryDialog.visible = true
}, 200)
}
},
...vm.addExtraMoreColActions
]
}
}
}
}
return {
tableConfig,
defaultHeaderActions
}
}

View File

@@ -44,8 +44,6 @@ export default {
return !vm.currentOrgIsRoot
}
return {
createDrawer: () => import('@/views/users/User/UserCreateUpdate.vue'),
detailDrawer: () => import('@/views/users/User/UserDetail/index.vue'),
quickFilters: [
{
label: '快速筛选',