mirror of
https://github.com/jumpserver/lina.git
synced 2026-01-13 11:24:17 +00:00
perf: update draw
This commit is contained in:
@@ -6,35 +6,20 @@
|
||||
:disabled="disabled"
|
||||
:type="col.type || 'info'"
|
||||
class="detail"
|
||||
@click="goDetail"
|
||||
@click="handleClick"
|
||||
>
|
||||
<slot>
|
||||
{{ iTitle }}
|
||||
</slot>
|
||||
</el-link>
|
||||
|
||||
<Drawer v-if="showTableDetailDrawer" :title="drawerTitle" @close-drawer="showTableDetailDrawer = !showTableDetailDrawer">
|
||||
<component :is="currentTemplate" />
|
||||
</Drawer>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import BaseFormatter from './base.vue'
|
||||
import Drawer from '@/components/Drawer/index.vue'
|
||||
|
||||
export default {
|
||||
name: 'DetailFormatter',
|
||||
components: {
|
||||
Drawer,
|
||||
AssetDetail: () => import('@/views/assets/Asset/AssetDetail'),
|
||||
AssetAccountList: () => import('@/views/accounts/Account/AccountDetail/index.vue'),
|
||||
AccountPushDetail: () => import('@/views/accounts/AccountPush/AccountPushDetail/index.vue'),
|
||||
AccountDiscoverTaskDetail: () => import('@/views/accounts/AccountDiscover/TaskDetail/index'),
|
||||
AccountBackupDetail: () => import('@/views/accounts/AccountBackup/AccountBackupDetail/index.vue'),
|
||||
IntegrationApplicationDetail: () => import('@/views/pam/Integration/ApplicationDetail/index.vue'),
|
||||
AccountTemplateDetail: () => import('@/views/accounts/AccountTemplate/AccountTemplateDetail/index.vue')
|
||||
},
|
||||
extends: BaseFormatter,
|
||||
props: {
|
||||
formatterArgsDefault: {
|
||||
@@ -45,6 +30,7 @@ export default {
|
||||
getRoute: null,
|
||||
routeQuery: null,
|
||||
can: true,
|
||||
onClick: null,
|
||||
openInNewPage: false,
|
||||
removeColorOnClick: false,
|
||||
getTitle({ col, row, cellValue }) {
|
||||
@@ -91,6 +77,17 @@ export default {
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
handleClick() {
|
||||
if (this.formatterArgs.onClick) {
|
||||
this.formatterArgs.onClick({
|
||||
col: this.col,
|
||||
row: this.row,
|
||||
cellValue: this.cellValue
|
||||
})
|
||||
} else {
|
||||
this.goDetail()
|
||||
}
|
||||
},
|
||||
getDetailRoute() {
|
||||
// const defaultRoute = this.$route.name.replace('List', 'Detail')
|
||||
let route = this.formatterArgs.route
|
||||
|
||||
@@ -13,6 +13,7 @@ import { toSentenceCase } from '@/utils/common'
|
||||
router.beforeEach(async(to, from, next) => {
|
||||
// start progress bar
|
||||
// NProgress.start()
|
||||
await store.dispatch('common/setDrawerActionMeta', {})
|
||||
try {
|
||||
await startup({ to, from, next })
|
||||
next()
|
||||
|
||||
@@ -133,8 +133,13 @@ export default {
|
||||
submitMethod: {
|
||||
type: [Function, String],
|
||||
default: function() {
|
||||
const params = this.$route.params
|
||||
if (params.id) {
|
||||
const cloneFrom = this.getCloneId()
|
||||
console.log('Clone from: ', cloneFrom)
|
||||
if (cloneFrom) {
|
||||
return 'post'
|
||||
}
|
||||
const objectId = this.getUpdateId()
|
||||
if (objectId) {
|
||||
return 'put'
|
||||
} else {
|
||||
return 'post'
|
||||
@@ -145,13 +150,13 @@ export default {
|
||||
getUrl: {
|
||||
type: Function,
|
||||
default: function() {
|
||||
const params = this.$route.params
|
||||
const objectId = this.getUpdateId()
|
||||
let url = this.url
|
||||
if (params.id) {
|
||||
url = getUpdateObjURL(url, params.id)
|
||||
if (objectId) {
|
||||
url = getUpdateObjURL(url, objectId)
|
||||
}
|
||||
|
||||
const clone_from = this.$route.query['clone_from']
|
||||
const clone_from = this.getCloneId()
|
||||
const query = clone_from ? `clone_from=${clone_from}` : ''
|
||||
if (query) {
|
||||
if (url.indexOf('?') === -1) {
|
||||
@@ -268,7 +273,11 @@ export default {
|
||||
form: {},
|
||||
loading: true,
|
||||
isSubmitting: false,
|
||||
clone: false
|
||||
clone: false,
|
||||
drawer: false,
|
||||
action: '',
|
||||
actionId: '',
|
||||
row: {}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
@@ -297,19 +306,47 @@ export default {
|
||||
}
|
||||
},
|
||||
async created() {
|
||||
this.$log.debug('Object init is: ', this.object)
|
||||
const drawActionMeta = await this.$store.dispatch('common/getDrawerActionMeta')
|
||||
if (drawActionMeta) {
|
||||
this.drawer = true
|
||||
this.action = drawActionMeta.action
|
||||
this.row = drawActionMeta.row
|
||||
this.actionId = this.row?.id
|
||||
}
|
||||
this.$log.debug('Object init is: ', this.object, this.method)
|
||||
console.log('Action: ', this.action, this.actionId)
|
||||
|
||||
this.loading = true
|
||||
try {
|
||||
const values = await this.getFormValue()
|
||||
this.$log.debug('Final object is: ', values)
|
||||
const formValue = Object.assign(this.form, values)
|
||||
this.form = this.afterGetFormValue(formValue)
|
||||
console.log('Form: ', this.form)
|
||||
} finally {
|
||||
this.loading = false
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
getUpdateId() {
|
||||
if (this.actionId && this.action === 'update') {
|
||||
return this.actionId
|
||||
} else {
|
||||
return this.$route.params.id
|
||||
}
|
||||
},
|
||||
getAction() {
|
||||
return this.action
|
||||
},
|
||||
getCloneId() {
|
||||
if (this.actionId && this.action === 'clone') {
|
||||
return this.actionId
|
||||
} else {
|
||||
return this.$route.query['clone_from']
|
||||
}
|
||||
},
|
||||
isUpdateMethod() {
|
||||
console.log('This method: ', this.method)
|
||||
return ['put', 'patch'].indexOf(this.method.toLowerCase()) > -1
|
||||
},
|
||||
encryptFields(values) {
|
||||
@@ -352,27 +389,35 @@ export default {
|
||||
}, 200)
|
||||
})
|
||||
},
|
||||
async getUpdateForm() {
|
||||
|
||||
},
|
||||
async getCloneForm(cloneFrom) {
|
||||
const [curUrl, query] = this.url.split('?')
|
||||
const url = `${curUrl}${cloneFrom}/${query ? ('?' + query) : ''}`
|
||||
const object = await this.getObjectDetail(url)
|
||||
let name = ''
|
||||
let attr = ''
|
||||
if (object['name']) {
|
||||
name = object['name']
|
||||
attr = 'name'
|
||||
} else if (object['hostname']) {
|
||||
name = object['hostname']
|
||||
attr = 'hostname'
|
||||
}
|
||||
object[attr] = name + '-' + this.cloneNameSuffix.toString()
|
||||
return object
|
||||
},
|
||||
async getFormValue() {
|
||||
const cloneFrom = this.$route.query['clone_from']
|
||||
if ((!this.isUpdateMethod() && !cloneFrom) || !this.needGetObjectDetail) {
|
||||
const cloneFrom = this.getCloneId()
|
||||
const objectId = this.getUpdateId()
|
||||
if ((!objectId && !cloneFrom) || !this.needGetObjectDetail) {
|
||||
return Object.assign(this.form, this.initial)
|
||||
}
|
||||
let object = this.object
|
||||
if (!object || Object.keys(object).length === 0) {
|
||||
if (cloneFrom) {
|
||||
const [curUrl, query] = this.url.split('?')
|
||||
const url = `${curUrl}${cloneFrom}/${query ? ('?' + query) : ''}`
|
||||
object = await this.getObjectDetail(url)
|
||||
let name = ''
|
||||
let attr = ''
|
||||
if (object['name']) {
|
||||
name = object['name']
|
||||
attr = 'name'
|
||||
} else if (object['hostname']) {
|
||||
name = object['hostname']
|
||||
attr = 'hostname'
|
||||
}
|
||||
object[attr] = name + '-' + this.cloneNameSuffix.toString()
|
||||
object = await this.getCloneForm(cloneFrom)
|
||||
} else {
|
||||
object = await this.getObjectDetail(this.iUrl)
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<Page v-bind="$attrs">
|
||||
<Page :class="{drawer: drawer}" v-bind="$attrs">
|
||||
<IBox>
|
||||
<GenericCreateUpdateForm ref="createUpdateForm" v-bind="$attrs" v-on="$listeners" />
|
||||
</IBox>
|
||||
@@ -14,6 +14,19 @@ export default {
|
||||
name: 'GenericCreateUpdatePage',
|
||||
components: {
|
||||
Page, IBox, GenericCreateUpdateForm
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
drawer: false
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.$store.dispatch('common/getDrawerActionMeta').then((res) => {
|
||||
console.log('res: ', res)
|
||||
if (res.action) {
|
||||
this.drawer = true
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -27,4 +40,8 @@ export default {
|
||||
padding-bottom: 60px;
|
||||
}
|
||||
}
|
||||
|
||||
.drawer ::v-deep .page-heading {
|
||||
display: none;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -98,13 +98,7 @@ export default {
|
||||
},
|
||||
data() {
|
||||
const vm = this
|
||||
const detailApiUrl = (function() {
|
||||
if (vm.url) {
|
||||
return `${vm.url}/${vm.$route.params.id}/`
|
||||
} else {
|
||||
return getApiPath(vm)
|
||||
}
|
||||
}())
|
||||
const detailApiUrl = this.getDetailUrl()
|
||||
const defaultActions = {
|
||||
// Delete button
|
||||
canDelete: vm.$hasCurrentResAction('delete'),
|
||||
@@ -187,6 +181,14 @@ export default {
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
getDetailUrl() {
|
||||
const vm = this
|
||||
if (vm.url) {
|
||||
return `${vm.url}/${vm.$route.params.id}/`
|
||||
} else {
|
||||
return getApiPath(vm)
|
||||
}
|
||||
},
|
||||
defaultDelete() {
|
||||
const msg = this.$t('DeleteWarningMsg') + ' ' + this.iTitle + ' ?'
|
||||
const title = this.$t('Info')
|
||||
|
||||
67
src/layout/components/GenericListDrawerPage/Drawer.vue
Normal file
67
src/layout/components/GenericListDrawerPage/Drawer.vue
Normal file
@@ -0,0 +1,67 @@
|
||||
<template>
|
||||
<el-drawer
|
||||
:title="title"
|
||||
:visible.sync="iVisible"
|
||||
class="form-drawer"
|
||||
size="800px"
|
||||
>
|
||||
<component :is="component" v-bind="props" @close="closeDrawer" />
|
||||
</el-drawer>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: {
|
||||
visible: {
|
||||
type: Boolean,
|
||||
required: true
|
||||
},
|
||||
title: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
component: {
|
||||
type: [String, Function],
|
||||
required: true
|
||||
},
|
||||
props: {
|
||||
type: Object,
|
||||
default: () => ({})
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
iVisible: {
|
||||
get() {
|
||||
return this.visible
|
||||
},
|
||||
set(val) {
|
||||
this.$emit('update:visible', val)
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
console.log('Mounted: ',)
|
||||
},
|
||||
methods: {
|
||||
closeDrawer() {
|
||||
this.iVisible = false
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.form-drawer {
|
||||
/* 可自定义样式 */
|
||||
|
||||
::v-deep {
|
||||
.el-drawer__header {
|
||||
margin-bottom: 10px;
|
||||
padding-top: 10px;
|
||||
font-size: 16px;
|
||||
font-weight: 500;
|
||||
color: var(--color-text-primary);
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
181
src/layout/components/GenericListDrawerPage/index.vue
Normal file
181
src/layout/components/GenericListDrawerPage/index.vue
Normal file
@@ -0,0 +1,181 @@
|
||||
<template>
|
||||
<div>
|
||||
<Page v-bind="$attrs">
|
||||
<GenericListTable
|
||||
ref="ListTable"
|
||||
:header-actions="iHeaderActions"
|
||||
:table-config="iTableConfig"
|
||||
v-bind="$attrs"
|
||||
/>
|
||||
</Page>
|
||||
<Drawer
|
||||
v-if="drawerVisible"
|
||||
:component="drawerComponent"
|
||||
:props="drawerProps"
|
||||
:title="drawerTitle"
|
||||
:visible.sync="drawerVisible"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Page from '@/layout/components/Page'
|
||||
import GenericListTable from '@/layout/components/GenericListTable'
|
||||
import Drawer from './Drawer'
|
||||
import { toSentenceCase } from '@/utils/common'
|
||||
|
||||
const drawerType = [String, Function]
|
||||
|
||||
export default {
|
||||
name: 'GenericListPage',
|
||||
components: {
|
||||
Page, GenericListTable, Drawer
|
||||
},
|
||||
props: {
|
||||
detailDrawer: {
|
||||
type: drawerType,
|
||||
default: ''
|
||||
},
|
||||
createDrawer: {
|
||||
type: drawerType,
|
||||
default: ''
|
||||
},
|
||||
updateDrawer: {
|
||||
type: drawerType,
|
||||
default: ''
|
||||
},
|
||||
tableConfig: {
|
||||
type: Object,
|
||||
required: true
|
||||
},
|
||||
headerActions: {
|
||||
type: Object,
|
||||
required: true
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
visible: false,
|
||||
drawerVisible: false,
|
||||
drawerComponent: '',
|
||||
drawerProps: {},
|
||||
iHeaderActions: {},
|
||||
iTableConfig: {},
|
||||
action: '',
|
||||
iCreateDrawer: this.createDrawer,
|
||||
iUpdateDrawer: this.updateDrawer,
|
||||
iDetailDrawer: this.detailDrawer
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
drawerTitle() {
|
||||
let title = this.title || this.$route.meta.title
|
||||
if (!title) {
|
||||
title = this.$t('NoTitle')
|
||||
}
|
||||
title = toSentenceCase(this.action) + ' ' + title.toLowerCase()
|
||||
return title
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
visible(val) {
|
||||
if (!val) {
|
||||
this.$store.dispatch('common/cleanDrawerActionMeta')
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
if (!this.createDrawer) {
|
||||
this.iCreateDrawer = this.getDefaultDrawer('create')
|
||||
}
|
||||
if (!this.updateDrawer) {
|
||||
this.iUpdateDrawer = this.getDefaultDrawer('update')
|
||||
}
|
||||
if (!this.detailDrawer) {
|
||||
this.iDetailDrawer = this.getDefaultDrawer('detail')
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.iHeaderActions = {
|
||||
...this.headerActions,
|
||||
onCreate: this.onCreate
|
||||
}
|
||||
this.iTableConfig = {
|
||||
...this.tableConfig
|
||||
}
|
||||
_.set(this.iTableConfig, 'columnsMeta.actions.formatterArgs.onUpdate', this.onUpdate)
|
||||
_.set(this.iTableConfig, 'columnsMeta.actions.formatterArgs.onClone', this.onClone)
|
||||
_.set(this.iTableConfig, 'columnsMeta.name.formatterArgs.onClick', this.onDetail)
|
||||
},
|
||||
methods: {
|
||||
getDefaultDrawer(action) {
|
||||
const route = this.$route.name
|
||||
const actionRouteName = route.replace('List', toSentenceCase(action))
|
||||
return this.getRouteNameComponent(actionRouteName)
|
||||
},
|
||||
getRouteNameComponent(name) {
|
||||
const routes = this.$router.resolve({ name: name })
|
||||
if (!routes) {
|
||||
return
|
||||
}
|
||||
const matched = routes.resolved.matched.filter(item => item.name === name && item.components)
|
||||
if (matched.length === 0) {
|
||||
return
|
||||
}
|
||||
|
||||
if (matched[0] && matched[0].components?.default) {
|
||||
return matched[0].components.default
|
||||
}
|
||||
},
|
||||
onCreate() {
|
||||
this.action = 'create'
|
||||
this.drawerComponent = this.iCreateDrawer
|
||||
this.$store.dispatch('common/setDrawerActionMeta', {
|
||||
action: 'create'
|
||||
}).then(() => {
|
||||
this.drawerVisible = true
|
||||
})
|
||||
},
|
||||
reloadTable() {
|
||||
this.$refs.ListTable.reloadTable()
|
||||
},
|
||||
onClone({ row, col }) {
|
||||
this.drawerComponent = this.iCreateDrawer
|
||||
this.action = 'clone'
|
||||
this.$store.dispatch('common/setDrawerActionMeta', {
|
||||
action: 'clone',
|
||||
row: row,
|
||||
col: col
|
||||
}).then(() => {
|
||||
this.drawerVisible = true
|
||||
})
|
||||
},
|
||||
onUpdate({ row, col }) {
|
||||
this.action = 'update'
|
||||
let updateDrawer = this.iUpdateDrawer
|
||||
if (!updateDrawer) {
|
||||
updateDrawer = this.iCreateDrawer
|
||||
}
|
||||
this.drawerComponent = updateDrawer
|
||||
this.$store.dispatch('common/setDrawerActionMeta', {
|
||||
action: 'update',
|
||||
row: row,
|
||||
col: col
|
||||
}).then(() => {
|
||||
this.drawerVisible = true
|
||||
})
|
||||
},
|
||||
onDetail({ row, cellValue }) {
|
||||
this.action = 'detail'
|
||||
this.drawerComponent = this.iDetailDrawer
|
||||
this.$store.dispatch('common/setDrawerActionMeta', {
|
||||
action: 'detail',
|
||||
row: row,
|
||||
cellValue: cellValue
|
||||
}).then(() => {
|
||||
this.drawerVisible = true
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -7,7 +7,8 @@ const getDefaultState = () => {
|
||||
isRouterAlive: true,
|
||||
sqlQueryCounter: [],
|
||||
showSqlQueryCounter: true,
|
||||
confirmDialogVisible: false
|
||||
confirmDialogVisible: false,
|
||||
drawerActionMeta: {}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -85,6 +86,15 @@ const actions = {
|
||||
},
|
||||
showSqlQueryCounter({ commit, state }, show) {
|
||||
state.showSqlQueryCounter = show
|
||||
},
|
||||
setDrawerActionMeta({ commit, state }, meta) {
|
||||
state.drawerActionMeta = meta
|
||||
},
|
||||
getDrawerActionMeta({ commit, state }) {
|
||||
return state.drawerActionMeta
|
||||
},
|
||||
cleanDrawerActionMeta({ commit, state }) {
|
||||
state.drawerActionMeta = {}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -164,14 +164,6 @@ export default {
|
||||
el: {}
|
||||
}
|
||||
},
|
||||
submitMethod() {
|
||||
const params = this.$route.params
|
||||
if (params.id) {
|
||||
return 'put'
|
||||
} else {
|
||||
return 'post'
|
||||
}
|
||||
},
|
||||
afterGetFormValue(obj) {
|
||||
if (obj?.id) {
|
||||
obj.org_roles = obj.org_roles?.map(({ id }) => id)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<div>
|
||||
<GenericListPage
|
||||
<GenericListDrawerPage
|
||||
ref="GenericListPage"
|
||||
:header-actions="headerActions"
|
||||
:quick-filters="quickFilters"
|
||||
@@ -19,7 +19,8 @@
|
||||
|
||||
<script>
|
||||
import { mapGetters } from 'vuex'
|
||||
import { GenericListPage, GenericUpdateFormDialog } from '@/layout/components'
|
||||
import { GenericUpdateFormDialog } from '@/layout/components'
|
||||
import GenericListDrawerPage from '@/layout/components/GenericListDrawerPage/index.vue'
|
||||
import { createSourceIdCache } from '@/api/common'
|
||||
import { getDayFuture } from '@/utils/time'
|
||||
import InviteUsersDialog from './components/InviteUsersDialog'
|
||||
@@ -28,7 +29,7 @@ import AmountFormatter from '@/components/Table/TableFormatters/AmountFormatter.
|
||||
export default {
|
||||
components: {
|
||||
InviteUsersDialog,
|
||||
GenericListPage,
|
||||
GenericListDrawerPage,
|
||||
GenericUpdateFormDialog
|
||||
},
|
||||
data() {
|
||||
@@ -43,6 +44,8 @@ export default {
|
||||
return !vm.currentOrgIsRoot
|
||||
}
|
||||
return {
|
||||
createDrawer: () => import('@/views/users/User/UserCreateUpdate.vue'),
|
||||
detailDrawer: () => import('@/views/users/User/UserDetail/index.vue'),
|
||||
quickFilters: [
|
||||
{
|
||||
label: '快速筛选',
|
||||
|
||||
Reference in New Issue
Block a user