perf: 基本完成应用正好改造

This commit is contained in:
ibuler
2021-07-27 14:18:37 +08:00
parent de4af07858
commit 0f76f6ad96
8 changed files with 363 additions and 64 deletions

View File

@@ -15,7 +15,7 @@ import { connectivityMeta } from './const'
import { openTaskPage } from '@/utils/jms'
export default {
name: 'Detail',
name: 'AccountListTable',
components: {
ListTable,
UpdateSecretInfo,

View File

@@ -0,0 +1,81 @@
<template>
<div>
<MFAVerifyDialog
@MFAVerifyDone="getAuthInfo"
@MFAVerifyCancel="exit"
/>
<Dialog
:title="dialogTitle"
:show-confirm="false"
:show-cancel="false"
:destroy-on-close="true"
:width="'50'"
:visible.sync="showAuthInfo"
v-bind="$attrs"
v-on="$listeners"
>
<div>
<el-form label-position="right" label-width="80px" :model="authInfo">
<el-form-item :label="this.$t('applications.appName')">
<el-input v-model="account['app_name']" readonly />
</el-form-item>
<el-form-item :label="this.$t('assets.Username')">
<el-input v-model="account['username']" readonly />
</el-form-item>
<el-form-item :label="this.$t('assets.Password')">
<el-input v-model="authInfo.password" type="password" show-password />
</el-form-item>
</el-form>
</div>
</Dialog>
</div>
</template>
<script>
import Dialog from '@/components/Dialog'
import MFAVerifyDialog from '@/components/MFAVerifyDialog'
export default {
name: 'ShowSecretInfo',
components: {
Dialog,
MFAVerifyDialog
},
props: {
account: {
type: Object,
default: () => ({})
},
visible: {
type: Boolean,
default: false
}
},
data() {
return {
dialogTitle: this.$t('common.ViewSecret'),
authInfo: {},
showAuthInfo: false
}
},
mounted() {
this.getAuthInfo()
},
methods: {
getAuthInfo() {
console.log(this.account)
const url = `/api/v1/applications/account-secrets/${this.account.uid}/`
this.$axios.get(url, { disableFlashErrorMsg: true }).then(resp => {
this.authInfo = resp
this.showAuthInfo = true
})
},
exit() {
this.$emit('update:visible', false)
}
}
}
</script>
<style scoped>
</style>

View File

@@ -0,0 +1,31 @@
import { ChoicesFormatter } from '@/components/TableFormatters'
import { toSafeLocalDateStr } from '@/utils/common'
import i18n from '@/i18n/i18n'
export const connectivityMeta = {
label: i18n.t('assets.Reachable'),
formatter: ChoicesFormatter,
formatterArgs: {
iconChoices: {
ok: 'fa-check text-primary',
failed: 'fa-times text-danger',
unknown: 'fa-circle text-warning'
},
hasTips: true,
getTips: ({ row, cellValue }) => {
const mapper = {
'ok': i18n.tc('assets.Reachable'),
'failed': i18n.tc('assets.Unreachable'),
'unknown': i18n.tc('assets.Unknown')
}
let tips = mapper[cellValue]
if (row['date_verified']) {
const datetime = toSafeLocalDateStr(row['date_verified'])
tips += '<br> ' + datetime
}
return tips
}
},
width: '90px',
align: 'center'
}

View File

@@ -0,0 +1,167 @@
<template>
<div>
<ListTable ref="ListTable" :table-config="tableConfig" :header-actions="headerActions" />
<ShowSecretInfo v-if="showViewSecretDialog" :visible.sync="showViewSecretDialog" :account="account" />
</div>
</template>
<script>
import ListTable from '@/components/ListTable/index'
import { ActionsFormatter, DetailFormatter } from '@/components/TableFormatters'
import ShowSecretInfo from './ShowSecretInfo'
export default {
name: 'Detail',
components: {
ListTable,
ShowSecretInfo
},
props: {
url: {
type: String,
required: true
},
exportUrl: {
type: String,
default() {
return this.url.replace('/applications/accounts/', '/applications/account-secrets/')
}
},
hasLeftActions: {
type: Boolean,
default: false
},
otherActions: {
type: Array,
default: null
},
hasClone: {
type: Boolean,
default: false
}
},
data() {
return {
showViewSecretDialog: false,
showUpdateSecretDialog: false,
account: {},
tableConfig: {
url: this.url,
columns: [
'app_name', 'username', 'app_category_display',
'app_type_display', 'systemuser', 'actions'
],
columnsMeta: {
app_name: {
showOverflowTooltip: true,
formatter: DetailFormatter,
formatterArgs: {
getRoute({ row }) {
switch (row['app_category']) {
case 'remote_app':
return {
name: 'RemoteAppDetail',
params: { id: row.app }
}
case 'db':
return {
name: 'DatabaseAppDetail',
params: { id: row.app }
}
default:
return {
name: 'KubernetesAppDetail',
params: { id: row.app }
}
}
}
}
},
username: {
showOverflowTooltip: true
},
systemuser: {
showOverflowTooltip: true,
formatter: DetailFormatter,
formatterArgs: {
getTitle({ row }) {
return row.systemuser_display
},
getRoute({ row }) {
return {
name: 'SystemUserDetail',
params: { id: row.systemuser }
}
}
}
},
actions: {
formatter: ActionsFormatter,
formatterArgs: {
hasUpdate: false, // can set function(row, value)
hasDelete: false, // can set function(row, value)
hasClone: this.hasClone,
moreActionsTitle: this.$t('common.More'),
extraActions: [
{
name: 'View',
title: this.$t('common.View'),
type: 'primary',
callback: function({ row }) {
this.account = row
this.showViewSecretDialog = true
}.bind(this)
},
{
name: 'Update',
title: this.$t('common.Update'),
can: !this.$store.getters.currentOrgIsRoot,
callback: function({ row }) {
this.$message.success(this.$tc('applications.updateAccountMsg'))
}.bind(this)
}
]
}
}
}
},
headerActions: {
hasLeftActions: this.hasLeftActions,
hasMoreActions: false,
hasImport: this.hasImport,
hasExport: this.hasExport,
exportOptions: {
url: this.exportUrl,
mfaVerifyRequired: true
},
searchConfig: {
exclude: ['systemuser', 'asset']
},
hasSearch: true
}
}
},
watch: {
url(iNew) {
this.$set(this.tableConfig, 'url', iNew)
}
},
mounted() {
if (this.otherActions) {
const actionColumn = this.tableConfig.columns[this.tableConfig.columns.length - 1]
for (const item of this.otherActions) {
actionColumn.formatterArgs.extraActions.push(item)
}
}
},
methods: {
onUpdateAuthDone(account) {
Object.assign(this.account, account)
}
}
}
</script>
<style lang='less' scoped>
</style>

View File

@@ -29,6 +29,7 @@
},
"applications": {
"": "",
"updateAccountMsg": "请更新系统用户的账号信息",
"RemoteApp": "远程应用",
"Database": "数据库",
"Cloud": "云",

View File

@@ -28,6 +28,7 @@
},
"applications": {
"": "",
"updateAccountMsg": "Please update system user account info",
"RemoteApp": "Remote app",
"Database": "Database",
"Cloud": "Cloud",

View File

@@ -38,57 +38,73 @@ export default [
]
},
{
path: 'database-apps',
path: 'databases',
name: 'DatabaseAppList',
component: () => import('@/views/applications/DatabaseApp/DatabaseAppList'),
meta: { title: i18n.t('route.DatabaseApp') }
component: empty,
meta: { title: i18n.t('route.DatabaseApp') },
children: [
{
path: '',
name: 'DatabaseAppList',
component: () => import('@/views/applications/DatabaseApp/DatabaseAppList'),
meta: { title: i18n.t('route.DatabaseApp') }
},
{
path: 'create',
name: 'DatabaseAppCreate',
component: () => import('@/views/applications/DatabaseApp/DatabaseAppCreateUpdate'),
meta: { title: i18n.t('route.DatabaseAppCreate'), activeMenu: '/applications/databases', action: 'create' },
hidden: true
},
{
path: ':id/update',
name: 'DatabaseAppUpdate',
component: () => import('@/views/applications/DatabaseApp/DatabaseAppCreateUpdate'),
meta: { title: i18n.t('route.DatabaseAppUpdate'), activeMenu: '/applications/databases', action: 'update' },
hidden: true
},
{
path: ':id',
name: 'DatabaseAppDetail',
component: () => import('@/views/applications/DatabaseApp/DatabaseAppDetail/index'),
meta: { title: i18n.t('route.DatabaseAppDetail'), activeMenu: '/applications/databases' },
hidden: true
}
]
},
{
path: 'database-apps/create',
name: 'DatabaseAppCreate',
component: () => import('@/views/applications/DatabaseApp/DatabaseAppCreateUpdate'),
meta: { title: i18n.t('route.DatabaseAppCreate'), activeMenu: '/applications/database-apps', action: 'create' },
hidden: true
},
{
path: 'database-apps/:id/update',
name: 'DatabaseAppUpdate',
component: () => import('@/views/applications/DatabaseApp/DatabaseAppCreateUpdate'),
meta: { title: i18n.t('route.DatabaseAppUpdate'), activeMenu: '/applications/database-apps', action: 'update' },
hidden: true
},
{
path: 'database-apps/:id',
name: 'DatabaseAppDetail',
component: () => import('@/views/applications/DatabaseApp/DatabaseAppDetail/index'),
meta: { title: i18n.t('route.DatabaseAppDetail'), activeMenu: '/applications/database-apps' },
hidden: true
},
{
path: 'kubernetes-apps',
path: 'kubernetes',
name: 'KubernetesAppList',
component: () => import('@/views/applications/KubernetesApp/KubernetesAppList'),
meta: { title: i18n.t('route.KubernetesApp') }
},
{
path: 'kubernetes-apps/create',
name: 'KubernetesAppCreate',
component: () => import('@/views/applications/KubernetesApp/KubernetesAppCreateUpdate'),
meta: { title: i18n.t('route.KubernetesAppCreate'), activeMenu: '/applications/kubernetes-apps', action: 'create' },
hidden: true
},
{
path: 'kubernetes-apps/:id/update',
name: 'KubernetesAppUpdate',
component: () => import('@/views/applications/KubernetesApp/KubernetesAppCreateUpdate'),
meta: { title: i18n.t('route.KubernetesAppUpdate'), activeMenu: '/applications/kubernetes-apps', action: 'update' },
hidden: true
},
{
path: 'kubernetes-apps/:id',
name: 'KubernetesAppDetail',
component: () => import('@/views/applications/KubernetesApp/KubernetesAppDetail/index'),
meta: { title: i18n.t('route.KubernetesAppDetail'), activeMenu: '/applications/kubernetes-apps' },
hidden: true
component: empty,
meta: { title: i18n.t('route.KubernetesApp') },
children: [
{
path: '',
name: 'KubernetesAppList',
component: () => import('@/views/applications/KubernetesApp/KubernetesAppList'),
meta: { title: i18n.t('route.KubernetesApp') }
},
{
path: 'create',
name: 'KubernetesAppCreate',
component: () => import('@/views/applications/KubernetesApp/KubernetesAppCreateUpdate'),
meta: { title: i18n.t('route.KubernetesAppCreate'), activeMenu: '/applications/kubernetes', action: 'create' },
hidden: true
},
{
path: ':id/update',
name: 'KubernetesAppUpdate',
component: () => import('@/views/applications/KubernetesApp/KubernetesAppCreateUpdate'),
meta: { title: i18n.t('route.KubernetesAppUpdate'), activeMenu: '/applications/kubernetes', action: 'update' },
hidden: true
},
{
path: ':id',
name: 'KubernetesAppDetail',
component: () => import('@/views/applications/KubernetesApp/KubernetesAppDetail/index'),
meta: { title: i18n.t('route.KubernetesAppDetail'), activeMenu: '/applications/kubernetes' },
hidden: true
}
]
}
]

View File

@@ -1,20 +1,20 @@
<template>
<GenericTreeListPage ref="TreeTablePage" :tree-setting="treeSetting">
<template #table>
<AccountListTable ref="table" :url="accountsUrl" />
<AppAccountListTable ref="table" :url="accountsUrl" />
</template>
</GenericTreeListPage>
</template>
<script>
import GenericTreeListPage from '@/layout/components/GenericTreeListPage'
import AccountListTable from '@/components/AccountListTable'
import AppAccountListTable from '@/components/AppAccountListTable'
import { setUrlParam } from '@/utils/common'
export default {
name: 'AssetAccountList',
components: {
GenericTreeListPage, AccountListTable
GenericTreeListPage, AppAccountListTable
},
data() {
const vm = this
@@ -22,25 +22,27 @@ export default {
isInit: true,
clickedRow: null,
iShowTree: true,
accountsUrl: '/api/v1/assets/accounts/',
accountsUrl: '/api/v1/applications/accounts/',
treeSetting: {
async: false,
showMenu: false,
showRefresh: true,
showAssets: false,
url: '/api/v1/assets/accounts/',
treeUrl: '/api/v1/applications/applications/tree/',
treeUrl: '/api/v1/applications/applications/tree/?show_count=0',
callback: {
onSelected: function(event, treeNode) {
let url = '/api/v1/assets/accounts/'
if (treeNode.meta.type === 'node') {
const nodeId = treeNode.meta.node.id
url = setUrlParam(url, 'asset', '')
url = setUrlParam(url, 'node', nodeId)
} else if (treeNode.meta.type === 'asset') {
const assetId = treeNode.meta.asset.id
url = setUrlParam(url, 'node', '')
url = setUrlParam(url, 'asset', assetId)
let url = '/api/v1/applications/accounts/'
const nodeId = treeNode.id
if (treeNode.meta.type === 'category') {
url = setUrlParam(url, 'app_category', nodeId)
url = setUrlParam(url, 'app_type', '')
} else if (treeNode.meta.type === 'type') {
url = setUrlParam(url, 'app_category', '')
url = setUrlParam(url, 'app_type', nodeId)
} else if (treeNode.meta.type === 'application') {
url = setUrlParam(url, 'app_category', '')
url = setUrlParam(url, 'app_type', '')
url = setUrlParam(url, 'app', nodeId)
}
setTimeout(() => {
vm.accountsUrl = url