mirror of
https://github.com/jumpserver/lina.git
synced 2025-08-28 19:32:01 +00:00
Merge remote-tracking branch 'origin/v3' into v3
This commit is contained in:
commit
ae7e8df986
@ -99,7 +99,7 @@ export default {
|
|||||||
},
|
},
|
||||||
push_now: {
|
push_now: {
|
||||||
hidden: () => {
|
hidden: () => {
|
||||||
return !this.platform.automation['push_account_enabled']
|
return !this.platform.automation?.['push_account_enabled']
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -112,7 +112,7 @@ export default {
|
|||||||
afterGetRemoteMeta(meta) {
|
afterGetRemoteMeta(meta) {
|
||||||
const choices = meta.secret_type.choices
|
const choices = meta.secret_type.choices
|
||||||
const secretTypes = []
|
const secretTypes = []
|
||||||
this.platform.protocols.forEach(p => {
|
this.platform.protocols?.forEach(p => {
|
||||||
secretTypes.push(...p['secret_types'])
|
secretTypes.push(...p['secret_types'])
|
||||||
})
|
})
|
||||||
if (!this.form.secret_type) {
|
if (!this.form.secret_type) {
|
||||||
|
@ -72,11 +72,11 @@ export default {
|
|||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
async getPlatform() {
|
async getPlatform() {
|
||||||
this.platform = await this.$axios.get(`/api/v1/assets/platforms/${this.asset.platform.id}/`)
|
const platformId = this.asset?.platform?.id || this.asset?.platform_id
|
||||||
console.log('Platform: ', this.platform)
|
this.platform = await this.$axios.get(`/api/v1/assets/platforms/${platformId}/`)
|
||||||
},
|
},
|
||||||
addAccount(form) {
|
addAccount(form) {
|
||||||
const data = { asset: this.asset.id, ...form }
|
const data = { asset: this.asset?.id || '', ...form }
|
||||||
this.$axios.post(`/api/v1/assets/accounts/`, data).then(() => {
|
this.$axios.post(`/api/v1/assets/accounts/`, data).then(() => {
|
||||||
this.iVisible = false
|
this.iVisible = false
|
||||||
this.$emit('add', true)
|
this.$emit('add', true)
|
||||||
|
75
src/components/AccountListTable/PasswordHistoryDialog.vue
Normal file
75
src/components/AccountListTable/PasswordHistoryDialog.vue
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
<template>
|
||||||
|
<GenericListTableDialog :visible.sync="iVisible" v-bind="config" />
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { GenericListTableDialog } from '@/layout/components'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
components: {
|
||||||
|
GenericListTableDialog
|
||||||
|
},
|
||||||
|
props: {
|
||||||
|
account: {
|
||||||
|
type: Object,
|
||||||
|
default: () => ({})
|
||||||
|
},
|
||||||
|
visible: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
config: {
|
||||||
|
title: this.$t('accounts.HistoryPassword'),
|
||||||
|
visible: false,
|
||||||
|
width: '60%',
|
||||||
|
tableConfig: {
|
||||||
|
url: `/api/v1/assets/accounts-historys?id=${this.account.id}`,
|
||||||
|
columns: [
|
||||||
|
'name', 'version', 'password', 'date_created'
|
||||||
|
],
|
||||||
|
columnsShow: {
|
||||||
|
min: ['name'],
|
||||||
|
default: [
|
||||||
|
'name', 'version', 'password', 'date_created'
|
||||||
|
]
|
||||||
|
},
|
||||||
|
columnsMeta: {
|
||||||
|
name: {
|
||||||
|
showOverflowTooltip: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
headerActions: {
|
||||||
|
hasImport: false,
|
||||||
|
hasExport: false,
|
||||||
|
hasLeftActions: false,
|
||||||
|
hasColumnSetting: false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
iVisible: {
|
||||||
|
get() {
|
||||||
|
return this.visible
|
||||||
|
},
|
||||||
|
set(val) {
|
||||||
|
this.$emit('update:visible', val)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
|
||||||
|
</style>
|
@ -17,17 +17,26 @@
|
|||||||
>
|
>
|
||||||
<div>
|
<div>
|
||||||
<el-form label-position="right" label-width="80px" :model="authInfo">
|
<el-form label-position="right" label-width="80px" :model="authInfo">
|
||||||
<el-form-item :label="this.$tc('assets.Name')">
|
<el-form-item :label="this.$t('assets.Name')">
|
||||||
<el-input v-model="account['name']" readonly />
|
<el-input v-model="account.asset.name" readonly />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item :label="this.$tc('assets.Username')">
|
<el-form-item :label="this.$tc('assets.Username')">
|
||||||
<el-input v-model="account['username']" readonly />
|
<el-input v-model="account['username']" readonly />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item v-if="account['secret_type'] === 'password'" :label="this.$tc('assets.Password')">
|
<el-form-item v-if="secretTypePassword" :label="this.$t('assets.Password')">
|
||||||
<el-input v-model="authInfo.secret" type="password" show-password />
|
<ShowKeyCopyFormatter v-model="authInfo.secret" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item v-else :label="this.$tc('assets.Key')">
|
<el-form-item v-else :label="this.$t('users.SSHKey')">
|
||||||
<el-input v-model="authInfo.secret" type="textarea" :rows="10" />
|
<el-input v-model="authInfo['private_key']" class="item-textarea" type="textarea" show-password readonly />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item :label="this.$t('common.DateCreated')">
|
||||||
|
<span>{{ $moment(authInfo.date_created, 'YYYY-MM-DD HH:mm:ss').format('YYYY-MM-DD HH:mm:ss') }}</span>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item :label="this.$t('common.DateUpdated')">
|
||||||
|
<span>{{ $moment(authInfo.date_updated, 'YYYY-MM-DD HH:mm:ss').format('YYYY-MM-DD HH:mm:ss') }}</span>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item :label="this.$t('accounts.PasswordRecord')">
|
||||||
|
<span>{{ authInfo.version }}</span>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-form>
|
</el-form>
|
||||||
</div>
|
</div>
|
||||||
@ -38,11 +47,14 @@
|
|||||||
<script>
|
<script>
|
||||||
import Dialog from '@/components/Dialog'
|
import Dialog from '@/components/Dialog'
|
||||||
import UserConfirmDialog from '@/components/UserConfirmDialog'
|
import UserConfirmDialog from '@/components/UserConfirmDialog'
|
||||||
|
import { ShowKeyCopyFormatter } from '@/components/TableFormatters'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'ShowSecretInfo',
|
name: 'ShowSecretInfo',
|
||||||
components: {
|
components: {
|
||||||
Dialog,
|
Dialog,
|
||||||
UserConfirmDialog
|
UserConfirmDialog,
|
||||||
|
ShowKeyCopyFormatter
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
account: {
|
account: {
|
||||||
@ -62,6 +74,11 @@ export default {
|
|||||||
url: `/api/v1/assets/account-secrets/${this.account.id}/`
|
url: `/api/v1/assets/account-secrets/${this.account.id}/`
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
computed: {
|
||||||
|
secretTypePassword() {
|
||||||
|
return this.authInfo.secret_type === 'password'
|
||||||
|
}
|
||||||
|
},
|
||||||
methods: {
|
methods: {
|
||||||
getAuthInfo() {
|
getAuthInfo() {
|
||||||
this.$axios.get(this.url, { disableFlashErrorMsg: true }).then(resp => {
|
this.$axios.get(this.url, { disableFlashErrorMsg: true }).then(resp => {
|
||||||
@ -76,8 +93,23 @@ export default {
|
|||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style lang="scss" scoped>
|
||||||
.item-textarea >>> .el-textarea__inner {
|
.item-textarea >>> .el-textarea__inner {
|
||||||
height: 110px;
|
height: 110px;
|
||||||
}
|
}
|
||||||
|
ul {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
li {
|
||||||
|
display: block;
|
||||||
|
font-size: 13px;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
.title {
|
||||||
|
color: #303133;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -15,6 +15,11 @@
|
|||||||
:account="account"
|
:account="account"
|
||||||
@add="addAccountSuccess"
|
@add="addAccountSuccess"
|
||||||
/>
|
/>
|
||||||
|
<PasswordHistoryDialog
|
||||||
|
v-if="showPasswordHistoryDialog"
|
||||||
|
:account="account"
|
||||||
|
:visible.sync="showPasswordHistoryDialog"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@ -27,12 +32,14 @@ import AddAccount from './AddAccount'
|
|||||||
import { connectivityMeta } from './const'
|
import { connectivityMeta } from './const'
|
||||||
import { openTaskPage } from '@/utils/jms'
|
import { openTaskPage } from '@/utils/jms'
|
||||||
import { hasUUID } from '@/utils/common'
|
import { hasUUID } from '@/utils/common'
|
||||||
|
import PasswordHistoryDialog from './PasswordHistoryDialog'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'AccountListTable',
|
name: 'AccountListTable',
|
||||||
components: {
|
components: {
|
||||||
ListTable,
|
ListTable,
|
||||||
UpdateSecretInfo,
|
UpdateSecretInfo,
|
||||||
|
PasswordHistoryDialog,
|
||||||
ViewSecret,
|
ViewSecret,
|
||||||
AddAccount
|
AddAccount
|
||||||
},
|
},
|
||||||
@ -61,7 +68,7 @@ export default {
|
|||||||
},
|
},
|
||||||
asset: {
|
asset: {
|
||||||
type: Object,
|
type: Object,
|
||||||
default: null
|
default: () => ({})
|
||||||
},
|
},
|
||||||
columns: {
|
columns: {
|
||||||
type: Array,
|
type: Array,
|
||||||
@ -71,6 +78,7 @@ export default {
|
|||||||
data() {
|
data() {
|
||||||
const vm = this
|
const vm = this
|
||||||
return {
|
return {
|
||||||
|
showPasswordHistoryDialog: false,
|
||||||
showViewSecretDialog: false,
|
showViewSecretDialog: false,
|
||||||
showUpdateSecretDialog: false,
|
showUpdateSecretDialog: false,
|
||||||
showAddDialog: false,
|
showAddDialog: false,
|
||||||
@ -171,11 +179,23 @@ export default {
|
|||||||
can: this.$hasPerm('assets.change_account') && !this.$store.getters.currentOrgIsRoot,
|
can: this.$hasPerm('assets.change_account') && !this.$store.getters.currentOrgIsRoot,
|
||||||
callback: ({ row }) => {
|
callback: ({ row }) => {
|
||||||
vm.account = row
|
vm.account = row
|
||||||
|
vm.$set(this.iAsset, 'platform_id', row.asset.platform_id)
|
||||||
vm.showAddDialog = false
|
vm.showAddDialog = false
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
vm.showAddDialog = true
|
vm.showAddDialog = true
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: this.$t('accounts.HistoryPassword'),
|
||||||
|
can: this.$hasPerm('assets.change_assetaccountsecret') && !this.$store.getters.currentOrgIsRoot,
|
||||||
|
callback: ({ row }) => {
|
||||||
|
vm.account = row
|
||||||
|
vm.showPasswordHistoryDialog = false
|
||||||
|
setTimeout(() => {
|
||||||
|
vm.showPasswordHistoryDialog = true
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@ -216,7 +236,7 @@ export default {
|
|||||||
this.$set(this.tableConfig, 'url', iNew)
|
this.$set(this.tableConfig, 'url', iNew)
|
||||||
this.$set(this.headerActions.exportOptions, 'url', iNew.replace('/accounts/', '/account-secrets/'))
|
this.$set(this.headerActions.exportOptions, 'url', iNew.replace('/accounts/', '/account-secrets/'))
|
||||||
},
|
},
|
||||||
'$route.query.assets': {
|
'$route.query.asset': {
|
||||||
immediate: true,
|
immediate: true,
|
||||||
handler() {
|
handler() {
|
||||||
this.hasAccountPermission()
|
this.hasAccountPermission()
|
||||||
@ -233,8 +253,6 @@ export default {
|
|||||||
actionColumn.formatterArgs.extraActions.push(item)
|
actionColumn.formatterArgs.extraActions.push(item)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log('Has perm: ', this.$hasPerm('assets.change_account'))
|
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
onUpdateAuthDone(account) {
|
onUpdateAuthDone(account) {
|
||||||
@ -243,11 +261,15 @@ export default {
|
|||||||
addAccountSuccess() {
|
addAccountSuccess() {
|
||||||
this.$refs.ListTable.reloadTable()
|
this.$refs.ListTable.reloadTable()
|
||||||
},
|
},
|
||||||
|
async getAssetDetail() {
|
||||||
|
const { query: { asset }} = this.$route
|
||||||
|
this.iAsset = await this.$axios.get(`/api/v1/assets/assets/${asset}/`)
|
||||||
|
},
|
||||||
hasAccountPermission() {
|
hasAccountPermission() {
|
||||||
const { path, query } = this.$route
|
const { path, query: { asset }} = this.$route
|
||||||
if (!hasUUID(path)) {
|
if (!hasUUID(path)) {
|
||||||
const hasPerm = this.$hasPerm('assets.add_account') && !!query.assets
|
if (asset) this.getAssetDetail()
|
||||||
this.iAsset = { id: query.assets }
|
const hasPerm = this.$hasPerm('assets.add_account') && !!asset
|
||||||
this.$set(this.headerActions.extraActions[0], 'can', hasPerm)
|
this.$set(this.headerActions.extraActions[0], 'can', hasPerm)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -27,7 +27,8 @@ import {
|
|||||||
DisplayFormatter,
|
DisplayFormatter,
|
||||||
ActionsFormatter,
|
ActionsFormatter,
|
||||||
ChoicesFormatter,
|
ChoicesFormatter,
|
||||||
ObjectRelatedFormatter
|
ObjectRelatedFormatter,
|
||||||
|
ChoicesDisplayFormatter
|
||||||
} from '@/components/TableFormatters'
|
} from '@/components/TableFormatters'
|
||||||
import i18n from '@/i18n/i18n'
|
import i18n from '@/i18n/i18n'
|
||||||
import ColumnSettingPopover from './components/ColumnSettingPopover'
|
import ColumnSettingPopover from './components/ColumnSettingPopover'
|
||||||
@ -136,6 +137,10 @@ export default {
|
|||||||
col.sortable = 'custom'
|
col.sortable = 'custom'
|
||||||
col.formatter = DisplayFormatter
|
col.formatter = DisplayFormatter
|
||||||
break
|
break
|
||||||
|
case 'labeled_choice':
|
||||||
|
col.sortable = 'custom'
|
||||||
|
col.formatter = ChoicesDisplayFormatter
|
||||||
|
break
|
||||||
case 'boolean':
|
case 'boolean':
|
||||||
col.formatter = ChoicesFormatter
|
col.formatter = ChoicesFormatter
|
||||||
col.align = 'center'
|
col.align = 'center'
|
||||||
|
@ -83,12 +83,24 @@ export default {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.dialog >>> .el-dialog__header {
|
.dialog >>> .el-dialog {
|
||||||
/*padding-top: 10px;*/
|
padding: 30px 40px 35px;
|
||||||
|
|
||||||
|
&__header {
|
||||||
|
padding: 0 10px 0 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__body {
|
||||||
|
padding: 15px 0 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__footer {
|
||||||
|
padding: 0 0 10px 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.dialog-footer {
|
.dialog-footer >>> button.el-button--small {
|
||||||
padding-right: 20px;
|
padding: 10px 21px;
|
||||||
|
font-size: 13px;
|
||||||
}
|
}
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
|
@ -5,14 +5,14 @@
|
|||||||
:destroy-on-close="true"
|
:destroy-on-close="true"
|
||||||
:close-on-click-modal="false"
|
:close-on-click-modal="false"
|
||||||
:loading-status="loadStatus"
|
:loading-status="loadStatus"
|
||||||
width="80%"
|
width="60%"
|
||||||
class="importDialog"
|
class="importDialog"
|
||||||
:show-cancel="false"
|
:show-cancel="false"
|
||||||
:show-confirm="false"
|
:show-confirm="false"
|
||||||
@close="handleImportCancel"
|
@close="handleImportCancel"
|
||||||
>
|
>
|
||||||
<el-form v-if="!showTable" label-position="left" style="padding-left: 50px">
|
<el-form v-if="!showTable" label-position="left">
|
||||||
<el-form-item :label="$t('common.Import' )" :label-width="'100px'">
|
<el-form-item :label="$tc('common.Import' )" :label-width="'100px'">
|
||||||
<el-radio v-if="canImportCreate" v-model="importOption" class="export-item" label="create">
|
<el-radio v-if="canImportCreate" v-model="importOption" class="export-item" label="create">
|
||||||
{{ this.$t('common.Create') }}
|
{{ this.$t('common.Create') }}
|
||||||
</el-radio>
|
</el-radio>
|
||||||
@ -22,12 +22,12 @@
|
|||||||
<div style="line-height: 1.5">
|
<div style="line-height: 1.5">
|
||||||
<span class="el-upload__tip">
|
<span class="el-upload__tip">
|
||||||
{{ downloadTemplateTitle }}
|
{{ downloadTemplateTitle }}
|
||||||
<el-link type="success" :underline="false" style="padding-left: 10px" @click="downloadTemplateFile('csv')"> CSV </el-link>
|
<el-link type="success" @click="downloadTemplateFile('csv')"> CSV </el-link>
|
||||||
<el-link type="success" :underline="false" style="padding-left: 10px" @click="downloadTemplateFile('xlsx')"> XLSX </el-link>
|
<el-link type="success" @click="downloadTemplateFile('xlsx')"> XLSX </el-link>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item :label="$t('common.Upload' )" :label-width="'100px'" class="file-uploader">
|
<el-form-item :label="$tc('common.Upload' )" :label-width="'100px'" class="file-uploader">
|
||||||
<el-upload
|
<el-upload
|
||||||
ref="upload"
|
ref="upload"
|
||||||
drag
|
drag
|
||||||
@ -40,9 +40,13 @@
|
|||||||
accept=".csv,.xlsx"
|
accept=".csv,.xlsx"
|
||||||
>
|
>
|
||||||
<i class="el-icon-upload" />
|
<i class="el-icon-upload" />
|
||||||
<div class="el-upload__text">{{ $t('common.imExport.dragUploadFileInfo') }}</div>
|
<div class="el-upload__text">
|
||||||
|
{{ $t('common.imExport.dragUploadFileInfo') }}
|
||||||
|
</div>
|
||||||
<div slot="tip" class="el-upload__tip">
|
<div slot="tip" class="el-upload__tip">
|
||||||
<span :class="{'hasError': hasFileFormatOrSizeError }">{{ $t('common.imExport.uploadCsvLth10MHelpText') }}</span>
|
<span :class="{'hasError': hasFileFormatOrSizeError }">
|
||||||
|
{{ $t('common.imExport.uploadCsvLth10MHelpText') }}
|
||||||
|
</span>
|
||||||
<div v-if="renderError" class="hasError">{{ renderError }}</div>
|
<div v-if="renderError" class="hasError">{{ renderError }}</div>
|
||||||
</div>
|
</div>
|
||||||
</el-upload>
|
</el-upload>
|
||||||
@ -168,7 +172,10 @@ export default {
|
|||||||
this.$axios.post(
|
this.$axios.post(
|
||||||
renderToJsonUrl,
|
renderToJsonUrl,
|
||||||
file.raw,
|
file.raw,
|
||||||
{ headers: { 'Content-Type': isCsv ? 'text/csv' : 'text/xlsx' }, disableFlashErrorMsg: true }
|
{
|
||||||
|
headers: { 'Content-Type': isCsv ? 'text/csv' : 'text/xlsx' },
|
||||||
|
disableFlashErrorMsg: true
|
||||||
|
}
|
||||||
).then(data => {
|
).then(data => {
|
||||||
this.jsonData = data
|
this.jsonData = data
|
||||||
this.showTable = true
|
this.showTable = true
|
||||||
@ -205,9 +212,8 @@ export default {
|
|||||||
}
|
}
|
||||||
return this.url.indexOf('?') === -1 ? `${this.url}?${query}` : `${this.url}&${query}`
|
return this.url.indexOf('?') === -1 ? `${this.url}?${query}` : `${this.url}&${query}`
|
||||||
},
|
},
|
||||||
// eslint-disable-next-line handle-callback-err
|
catchError(err) {
|
||||||
catchError(error) {
|
console.log(err)
|
||||||
// debug(error)
|
|
||||||
},
|
},
|
||||||
onSuccess(msg) {
|
onSuccess(msg) {
|
||||||
this.errorMsg = ''
|
this.errorMsg = ''
|
||||||
@ -220,7 +226,7 @@ export default {
|
|||||||
window.URL.revokeObjectURL(url)
|
window.URL.revokeObjectURL(url)
|
||||||
},
|
},
|
||||||
async handleImportConfirm() {
|
async handleImportConfirm() {
|
||||||
this.$refs['importTable'].performUpload()
|
await this.$refs['importTable'].performUpload()
|
||||||
},
|
},
|
||||||
handleImportCancel() {
|
handleImportCancel() {
|
||||||
this.showImportDialog = false
|
this.showImportDialog = false
|
||||||
@ -243,10 +249,6 @@ export default {
|
|||||||
overflow: auto
|
overflow: auto
|
||||||
}
|
}
|
||||||
|
|
||||||
.importDialog >>> .el-form-item.file-uploader {
|
|
||||||
padding-right: 150px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.file-uploader >>> .el-upload {
|
.file-uploader >>> .el-upload {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
//padding-right: 150px;
|
//padding-right: 150px;
|
||||||
@ -287,5 +289,9 @@ export default {
|
|||||||
.el-upload__tip {
|
.el-upload__tip {
|
||||||
line-height: 1.5;
|
line-height: 1.5;
|
||||||
padding-top: 0;
|
padding-top: 0;
|
||||||
|
|
||||||
|
.el-link {
|
||||||
|
margin-left: 10px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
<span>{{ currentValue }}</span>
|
<span>{{ currentValue }}</span>
|
||||||
<span class="right">
|
<span class="right">
|
||||||
<el-tooltip
|
<el-tooltip
|
||||||
|
v-if="hasShow"
|
||||||
effect="dark"
|
effect="dark"
|
||||||
placement="top"
|
placement="top"
|
||||||
:content="this.$t('common.View')"
|
:content="this.$t('common.View')"
|
||||||
@ -10,6 +11,7 @@
|
|||||||
<i class="el-icon-view" @click="onShow()" />
|
<i class="el-icon-view" @click="onShow()" />
|
||||||
</el-tooltip>
|
</el-tooltip>
|
||||||
<el-tooltip
|
<el-tooltip
|
||||||
|
v-if="hasCopy"
|
||||||
effect="dark"
|
effect="dark"
|
||||||
placement="top"
|
placement="top"
|
||||||
:content="this.$t('common.Copy')"
|
:content="this.$t('common.Copy')"
|
||||||
@ -21,15 +23,24 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import BaseFormatter from './base'
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'ShowKeyCopyFormatter',
|
name: 'ShowKeyCopyFormatter',
|
||||||
extends: BaseFormatter,
|
props: {
|
||||||
proops: {
|
value: {
|
||||||
cellValue: {
|
|
||||||
type: String,
|
type: String,
|
||||||
default: () => ''
|
default: () => ''
|
||||||
|
},
|
||||||
|
cellValue: {
|
||||||
|
type: [String, Number],
|
||||||
|
default: null
|
||||||
|
},
|
||||||
|
hasShow: {
|
||||||
|
type: Boolean,
|
||||||
|
default: true
|
||||||
|
},
|
||||||
|
hasCopy: {
|
||||||
|
type: Boolean,
|
||||||
|
default: true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
@ -37,18 +48,24 @@ export default {
|
|||||||
currentValue: this.switchShowValue()
|
currentValue: this.switchShowValue()
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
computed: {
|
||||||
|
iValue() {
|
||||||
|
return this.value || this.cellValue
|
||||||
|
}
|
||||||
|
},
|
||||||
methods: {
|
methods: {
|
||||||
switchShowValue() {
|
switchShowValue() {
|
||||||
return '******' + this.cellValue.replace(/[\w-]/g, '')
|
const value = this.value || this.cellValue
|
||||||
|
return '******' + value.replace(/[\s\S]/g, '')
|
||||||
},
|
},
|
||||||
onShow() {
|
onShow() {
|
||||||
const { currentValue, cellValue, switchShowValue } = this
|
const { currentValue, switchShowValue } = this
|
||||||
this.currentValue = currentValue === cellValue ? switchShowValue() : cellValue
|
this.currentValue = currentValue === this.iValue ? switchShowValue() : this.iValue
|
||||||
},
|
},
|
||||||
onCopy: _.throttle(function() {
|
onCopy: _.throttle(function() {
|
||||||
const inputDom = document.createElement('input')
|
const inputDom = document.createElement('input')
|
||||||
inputDom.id = 'creatInputDom'
|
inputDom.id = 'createInputDom'
|
||||||
inputDom.value = this.cellValue
|
inputDom.value = this.iValue
|
||||||
document.body.appendChild(inputDom)
|
document.body.appendChild(inputDom)
|
||||||
inputDom.select()
|
inputDom.select()
|
||||||
document?.execCommand('copy')
|
document?.execCommand('copy')
|
||||||
@ -74,7 +91,7 @@ export default {
|
|||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
.el-icon-view, .el-icon-copy-document {
|
.el-icon-view, .el-icon-copy-document {
|
||||||
&:hover {
|
&:hover {
|
||||||
color: #1c84c6;
|
color: var(--color-primary);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -44,6 +44,8 @@ import AutoDataZTree from '../AutoDataZTree'
|
|||||||
import Dialog from '@/components/Dialog'
|
import Dialog from '@/components/Dialog'
|
||||||
import ListTable from '../ListTable'
|
import ListTable from '../ListTable'
|
||||||
import IBox from '../IBox'
|
import IBox from '../IBox'
|
||||||
|
import { setUrlParam } from '@/utils/common'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'TreeTable',
|
name: 'TreeTable',
|
||||||
components: {
|
components: {
|
||||||
@ -88,8 +90,16 @@ export default {
|
|||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
// debug(this.treeSetting)
|
// debug(this.treeSetting)
|
||||||
|
this.initSetTableUrl()
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
initSetTableUrl() {
|
||||||
|
const { asset = '', node = '' } = this.$route.query || {}
|
||||||
|
let url = this.iTableConfig.url
|
||||||
|
url = setUrlParam(url, 'asset', asset)
|
||||||
|
url = setUrlParam(url, 'node', node)
|
||||||
|
this.$set(this.iTableConfig, 'url', url)
|
||||||
|
},
|
||||||
handleUrlChange(url) {
|
handleUrlChange(url) {
|
||||||
this.$set(this.iTableConfig, 'url', url)
|
this.$set(this.iTableConfig, 'url', url)
|
||||||
this.$emit('urlChange', url)
|
this.$emit('urlChange', url)
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
{
|
{
|
||||||
"": "",
|
"": "",
|
||||||
"accounts": {
|
"accounts": {
|
||||||
|
"HistoryPassword": "History password",
|
||||||
|
"PasswordRecord": "Password record",
|
||||||
"AccountHistableHelpMessage": "Record the historical version of the current account",
|
"AccountHistableHelpMessage": "Record the historical version of the current account",
|
||||||
"PleaseClickLeftAssetToViewAssetAccount": "Asset account list, please click on the assets on the left to view",
|
"PleaseClickLeftAssetToViewAssetAccount": "Asset account list, please click on the assets on the left to view",
|
||||||
"PleaseClickLeftApplicationToViewApplicationAccount": "Application account list, please click on the application on the left to view",
|
"PleaseClickLeftApplicationToViewApplicationAccount": "Application account list, please click on the application on the left to view",
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
{
|
{
|
||||||
"": "",
|
"": "",
|
||||||
"accounts": {
|
"accounts": {
|
||||||
|
"HistoryPassword": "履歴パスワード",
|
||||||
|
"PasswordRecord": "パスワードレコード",
|
||||||
"AccountHistableHelpMessage": "現在のアカウントの履歴バージョンを記録する",
|
"AccountHistableHelpMessage": "現在のアカウントの履歴バージョンを記録する",
|
||||||
"PleaseClickLeftAssetToViewAssetAccount": "資産のアカウントのリスト、左側の資産をクリックして表示します",
|
"PleaseClickLeftAssetToViewAssetAccount": "資産のアカウントのリスト、左側の資産をクリックして表示します",
|
||||||
"PleaseClickLeftApplicationToViewApplicationAccount": "アカウントのリストを適用して、左側のアプリケーションをクリックして表示します",
|
"PleaseClickLeftApplicationToViewApplicationAccount": "アカウントのリストを適用して、左側のアプリケーションをクリックして表示します",
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
{
|
{
|
||||||
"": "",
|
"": "",
|
||||||
"accounts": {
|
"accounts": {
|
||||||
|
"HistoryPassword": "历史密码",
|
||||||
|
"PasswordRecord": "密码记录",
|
||||||
"AccountHistableHelpMessage": "记录当前账号的历史版本",
|
"AccountHistableHelpMessage": "记录当前账号的历史版本",
|
||||||
"PleaseClickLeftAssetToViewAssetAccount": "资产账号列表,点击左侧资产进行查看",
|
"PleaseClickLeftAssetToViewAssetAccount": "资产账号列表,点击左侧资产进行查看",
|
||||||
"PleaseClickLeftApplicationToViewApplicationAccount": "应用账号列表,点击左侧应用进行查看",
|
"PleaseClickLeftApplicationToViewApplicationAccount": "应用账号列表,点击左侧应用进行查看",
|
||||||
@ -96,6 +98,7 @@
|
|||||||
"NoSQLProtocol": "非关系数据库"
|
"NoSQLProtocol": "非关系数据库"
|
||||||
},
|
},
|
||||||
"assets": {
|
"assets": {
|
||||||
|
"Address": "地址",
|
||||||
"PrivateKey": "密钥",
|
"PrivateKey": "密钥",
|
||||||
"Secret": "密码",
|
"Secret": "密码",
|
||||||
"Network": "网络",
|
"Network": "网络",
|
||||||
@ -406,6 +409,7 @@
|
|||||||
"Update": "更新",
|
"Update": "更新",
|
||||||
"Revise": "修改",
|
"Revise": "修改",
|
||||||
"Upload": "上传",
|
"Upload": "上传",
|
||||||
|
"OfflineUpload": "离线上传",
|
||||||
"Clone": "克隆",
|
"Clone": "克隆",
|
||||||
"Username": "用户名",
|
"Username": "用户名",
|
||||||
"Validity": "有效",
|
"Validity": "有效",
|
||||||
@ -707,6 +711,9 @@
|
|||||||
},
|
},
|
||||||
"route": {
|
"route": {
|
||||||
"": "",
|
"": "",
|
||||||
|
"AppletHostCreate": "添加远程应用发布机",
|
||||||
|
"AppletHostUpdate": "更新远程应用发布机",
|
||||||
|
"AppletCreate": "创建远程应用",
|
||||||
"CreateEndpoint": "创建端点",
|
"CreateEndpoint": "创建端点",
|
||||||
"UpdateEndpoint": "更新端点",
|
"UpdateEndpoint": "更新端点",
|
||||||
"CreateEndpointRule": "创建端点规则",
|
"CreateEndpointRule": "创建端点规则",
|
||||||
@ -887,6 +894,11 @@
|
|||||||
"rbac": {
|
"rbac": {
|
||||||
"Permissions": "权限"
|
"Permissions": "权限"
|
||||||
},
|
},
|
||||||
|
"terminal": {
|
||||||
|
"Applets": "远程应用",
|
||||||
|
"AppletHosts": "应用发布机",
|
||||||
|
"uploadZipTips": "请上传zip格式的文件"
|
||||||
|
},
|
||||||
"sessions": {
|
"sessions": {
|
||||||
"SetToDefaultStorage": "设置为默认存储",
|
"SetToDefaultStorage": "设置为默认存储",
|
||||||
"SetToDefault": "设为默认",
|
"SetToDefault": "设为默认",
|
||||||
@ -968,6 +980,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"setting": {
|
"setting": {
|
||||||
|
"Applets": "远程应用",
|
||||||
"EndpointListHelpMessage": "服务端点是用户访问服务的地址(端口),当用户在连接资产时,会根据端点规则和资产标签选择服务端点,作为访问入口建立连接,实现分布式连接资产",
|
"EndpointListHelpMessage": "服务端点是用户访问服务的地址(端口),当用户在连接资产时,会根据端点规则和资产标签选择服务端点,作为访问入口建立连接,实现分布式连接资产",
|
||||||
"EndpointRuleListHelpMessage": "对于服务端点选择策略,目前支持两种:<br>1、根据端点规则指定端点(当前页面);<br>2、通过资产标签选择端点,标签名固定是 endpoint,值是端点的名称。<br>两种方式优先使用标签匹配,因为 IP 段可能冲突,标签方式是作为规则的补充存在的。",
|
"EndpointRuleListHelpMessage": "对于服务端点选择策略,目前支持两种:<br>1、根据端点规则指定端点(当前页面);<br>2、通过资产标签选择端点,标签名固定是 endpoint,值是端点的名称。<br>两种方式优先使用标签匹配,因为 IP 段可能冲突,标签方式是作为规则的补充存在的。",
|
||||||
"EnableKoKoSSHHelpText": "开启时连接资产会显示 SSH Client 拉起方式",
|
"EnableKoKoSSHHelpText": "开启时连接资产会显示 SSH Client 拉起方式",
|
||||||
|
@ -199,6 +199,48 @@ export default {
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: '/settings/applets',
|
||||||
|
component: empty,
|
||||||
|
redirect: '',
|
||||||
|
meta: {
|
||||||
|
title: i18n.t('setting.Applets'),
|
||||||
|
app: 'terminal',
|
||||||
|
permissions: ['settings.change_terminal']
|
||||||
|
},
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
path: '',
|
||||||
|
name: 'Applets',
|
||||||
|
component: () => import('@/views/settings/Applet'),
|
||||||
|
meta: {
|
||||||
|
title: i18n.t('setting.Applets'),
|
||||||
|
icon: 'tasks',
|
||||||
|
permissions: ['settings.change_terminal']
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'hosts/create',
|
||||||
|
name: 'AppletHostCreate',
|
||||||
|
component: () => import('@/views/settings/Applet/AppletHosts/AppletHostCreateUpdate'),
|
||||||
|
hidden: true,
|
||||||
|
meta: {
|
||||||
|
title: i18n.t('route.AppletHostCreate'),
|
||||||
|
permissions: ['settings.change_terminal']
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'hosts/:id/update',
|
||||||
|
name: 'AppletHostUpdate',
|
||||||
|
component: () => import('@/views/settings/Applet/AppletHosts/AppletHostCreateUpdate'),
|
||||||
|
hidden: true,
|
||||||
|
meta: {
|
||||||
|
title: i18n.t('route.AppletHostUpdate'),
|
||||||
|
permissions: ['settings.change_terminal']
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
path: '/settings/security',
|
path: '/settings/security',
|
||||||
name: 'Security',
|
name: 'Security',
|
||||||
|
@ -42,48 +42,6 @@ export default {
|
|||||||
permissions: ['perms.view_myassets']
|
permissions: ['perms.view_myassets']
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
|
||||||
path: '/workbench/apps',
|
|
||||||
name: 'Apps',
|
|
||||||
component: empty,
|
|
||||||
redirect: 'remoteapp',
|
|
||||||
alwaysShow: true,
|
|
||||||
meta: {
|
|
||||||
title: i18n.t('route.MyApps'),
|
|
||||||
icon: 'th',
|
|
||||||
permissions: ['perms.view_myapps']
|
|
||||||
},
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
path: 'remote-apps',
|
|
||||||
name: 'MyRemoteApps',
|
|
||||||
component: () => import('@/views/myapps/RemoteApp'),
|
|
||||||
meta: {
|
|
||||||
title: i18n.t('route.RemoteApp'),
|
|
||||||
permissions: [],
|
|
||||||
licenseRequired: true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: 'databases',
|
|
||||||
name: 'MyDatabases',
|
|
||||||
component: () => import('@/views/myapps/DatabaseApp'),
|
|
||||||
meta: {
|
|
||||||
title: i18n.t('route.DatabaseApp'),
|
|
||||||
permissions: []
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: 'kubernetes',
|
|
||||||
name: 'MyKubernetes',
|
|
||||||
component: () => import('@/views/myapps/KubernetesApp'),
|
|
||||||
meta: {
|
|
||||||
title: i18n.t('route.KubernetesApp'),
|
|
||||||
permissions: []
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
path: '/workbench/ops',
|
path: '/workbench/ops',
|
||||||
component: empty,
|
component: empty,
|
||||||
|
@ -42,12 +42,12 @@ export default {
|
|||||||
let url = '/api/v1/assets/accounts/'
|
let url = '/api/v1/assets/accounts/'
|
||||||
if (treeNode.meta.type === 'node') {
|
if (treeNode.meta.type === 'node') {
|
||||||
const nodeId = treeNode.meta.data.id
|
const nodeId = treeNode.meta.data.id
|
||||||
url = setUrlParam(url, 'assets', '')
|
url = setUrlParam(url, 'asset', '')
|
||||||
url = setUrlParam(url, 'nodes', nodeId)
|
url = setUrlParam(url, 'node', nodeId)
|
||||||
} else if (treeNode.meta.type === 'asset') {
|
} else if (treeNode.meta.type === 'asset') {
|
||||||
const assetId = treeNode.meta.data.id
|
const assetId = treeNode.meta.data.id
|
||||||
url = setUrlParam(url, 'nodes', '')
|
url = setUrlParam(url, 'node', '')
|
||||||
url = setUrlParam(url, 'assets', assetId)
|
url = setUrlParam(url, 'asset', assetId)
|
||||||
}
|
}
|
||||||
|
|
||||||
this.$set(this.tableConfig, 'url', url)
|
this.$set(this.tableConfig, 'url', url)
|
||||||
|
@ -21,6 +21,14 @@ export default {
|
|||||||
addFieldsMeta: {
|
addFieldsMeta: {
|
||||||
type: Object,
|
type: Object,
|
||||||
default: () => ({})
|
default: () => ({})
|
||||||
|
},
|
||||||
|
createSuccessNextRoute: {
|
||||||
|
type: Object,
|
||||||
|
default: () => ({ name: 'AssetList' })
|
||||||
|
},
|
||||||
|
updateSuccessNextRoute: {
|
||||||
|
type: Object,
|
||||||
|
default: () => ({ name: 'AssetList' })
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
@ -31,8 +39,8 @@ export default {
|
|||||||
initial: {},
|
initial: {},
|
||||||
platform: {},
|
platform: {},
|
||||||
url: '/api/v1/assets/hosts/',
|
url: '/api/v1/assets/hosts/',
|
||||||
createSuccessNextRoute: { name: 'AssetList' },
|
createSuccessNextRoute: this.createSuccessNextRoute,
|
||||||
updateSuccessNextRoute: { name: 'AssetList' },
|
updateSuccessNextRoute: this.updateSuccessNextRoute,
|
||||||
hasDetailInMsg: false,
|
hasDetailInMsg: false,
|
||||||
fields: [
|
fields: [
|
||||||
[this.$t('common.Basic'), ['name', 'address', 'platform']],
|
[this.$t('common.Basic'), ['name', 'address', 'platform']],
|
||||||
|
@ -1,36 +1,37 @@
|
|||||||
<template>
|
<template>
|
||||||
<div v-if="isUpdate(this)">
|
<div>
|
||||||
在资产详情中更新账号信息
|
<div v-if="isUpdate(this)">
|
||||||
</div>
|
在资产详情中更新账号信息
|
||||||
<div v-else class="accounts">
|
</div>
|
||||||
<el-table :data="accounts" style="width: 100%">
|
<div v-else class="accounts">
|
||||||
<el-table-column prop="username" label="用户名" width="180" />
|
<el-table :data="accounts" style="width: 100%">
|
||||||
<el-table-column prop="privileged" label="特权账号">
|
<el-table-column prop="username" label="用户名" width="180" />
|
||||||
<template v-slot="scope">
|
<el-table-column prop="privileged" label="特权账号">
|
||||||
<i class="fa text-primary" :class="scope.row['privileged'] ? 'fa-check' : ''" />
|
<template v-slot="scope">
|
||||||
</template>
|
<i class="fa text-primary" :class="scope.row['privileged'] ? 'fa-check' : ''" />
|
||||||
</el-table-column>
|
</template>
|
||||||
<el-table-column fixed="right" align="right" label="操作" width="135" class-name="buttons">
|
</el-table-column>
|
||||||
<template v-slot="scope">
|
<el-table-column fixed="right" align="right" label="操作" width="135" class-name="buttons">
|
||||||
<el-button type="danger" icon="el-icon-minus" size="mini" @click="removeAccount(scope.row)" />
|
<template v-slot="scope">
|
||||||
<el-button type="primary" icon="el-icon-edit" size="mini" @click="onEditClick(scope.row)" />
|
<el-button type="danger" icon="el-icon-minus" size="mini" @click="removeAccount(scope.row)" />
|
||||||
</template>
|
<el-button type="primary" icon="el-icon-edit" size="mini" @click="onEditClick(scope.row)" />
|
||||||
</el-table-column>
|
</template>
|
||||||
</el-table>
|
</el-table-column>
|
||||||
<div class="actions">
|
</el-table>
|
||||||
<el-button size="mini" type="primary" @click="onAddClick">添加</el-button>
|
<div class="actions">
|
||||||
<el-button size="mini" type="success" @click="onAddFromTemplateClick">模版添加</el-button>
|
<el-button size="mini" type="primary" @click="onAddClick">添加</el-button>
|
||||||
|
<el-button size="mini" type="success" @click="onAddFromTemplateClick">模版添加</el-button>
|
||||||
|
</div>
|
||||||
|
<AddAccountDialog
|
||||||
|
:visible.sync="addAccountDialogVisible"
|
||||||
|
:platform="platform"
|
||||||
|
:account="account"
|
||||||
|
:accounts="accounts"
|
||||||
|
/>
|
||||||
|
<AccountTemplateDialog
|
||||||
|
:visible.sync="templateDialogVisible"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<AddAccountDialog
|
|
||||||
:visible.sync="addAccountDialogVisible"
|
|
||||||
:platform="platform"
|
|
||||||
:account="account"
|
|
||||||
:accounts="accounts"
|
|
||||||
/>
|
|
||||||
<AccountTemplateDialog
|
|
||||||
:visible.sync="templateDialogVisible"
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@ -61,11 +62,11 @@ export default {
|
|||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
addAccountDialogVisible: false,
|
|
||||||
templateDialogVisible: false,
|
|
||||||
accounts: [],
|
accounts: [],
|
||||||
account: {},
|
account: {},
|
||||||
initial: false
|
initial: false,
|
||||||
|
addAccountDialogVisible: false,
|
||||||
|
templateDialogVisible: false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
@ -91,7 +92,7 @@ export default {
|
|||||||
onEditClick(account) {
|
onEditClick(account) {
|
||||||
this.account = account
|
this.account = account
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
this.visible = true
|
this.addAccountDialogVisible = true
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
onAddClick() {
|
onAddClick() {
|
||||||
|
@ -110,8 +110,7 @@ export default {
|
|||||||
},
|
},
|
||||||
protocols: {
|
protocols: {
|
||||||
formatter: (row) => {
|
formatter: (row) => {
|
||||||
let data = row.protocols.map(item => item.name + '/' + item.port)
|
const data = row.protocols.map(p => <el-tag size='mini'>{p.name}/{p.port} </el-tag>)
|
||||||
data = data.join(', ')
|
|
||||||
return <span> {data} </span>
|
return <span> {data} </span>
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -14,7 +14,7 @@ export const platformFieldsMeta = (vm) => {
|
|||||||
'ansible_enabled', 'ansible_config',
|
'ansible_enabled', 'ansible_config',
|
||||||
'ping_enabled', 'ping_method',
|
'ping_enabled', 'ping_method',
|
||||||
'gather_facts_enabled', 'gather_facts_method',
|
'gather_facts_enabled', 'gather_facts_method',
|
||||||
'create_account_enabled', 'create_account_method',
|
'push_account_enabled', 'push_account_method',
|
||||||
'change_secret_enabled', 'change_secret_method',
|
'change_secret_enabled', 'change_secret_method',
|
||||||
'verify_account_enabled', 'verify_account_method'
|
'verify_account_enabled', 'verify_account_method'
|
||||||
],
|
],
|
||||||
@ -25,7 +25,7 @@ export const platformFieldsMeta = (vm) => {
|
|||||||
},
|
},
|
||||||
ping_method: {},
|
ping_method: {},
|
||||||
gather_facts_method: {},
|
gather_facts_method: {},
|
||||||
create_account_method: {},
|
push_account_method: {},
|
||||||
change_secret_method: {},
|
change_secret_method: {},
|
||||||
verify_account_method: {}
|
verify_account_method: {}
|
||||||
}
|
}
|
||||||
|
@ -1,96 +0,0 @@
|
|||||||
<template>
|
|
||||||
<Page>
|
|
||||||
<ListTable ref="ListTable" :table-config="tableConfig" :header-actions="headerActions" />
|
|
||||||
</Page>
|
|
||||||
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import ListTable from '@/components/ListTable'
|
|
||||||
import Page from '@/layout/components/Page'
|
|
||||||
import { ActionsFormatter } from '@/components/TableFormatters'
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: 'DatabaseApp',
|
|
||||||
components: {
|
|
||||||
ListTable,
|
|
||||||
Page
|
|
||||||
},
|
|
||||||
props: {
|
|
||||||
},
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
tableConfig: {
|
|
||||||
url: `/api/v1/perms/users/applications/?category=db`,
|
|
||||||
columns: [
|
|
||||||
{
|
|
||||||
prop: 'name',
|
|
||||||
align: 'center',
|
|
||||||
label: this.$t('assets.Name'),
|
|
||||||
sortable: true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
prop: 'type_display',
|
|
||||||
align: 'center',
|
|
||||||
label: this.$t('assets.Type')
|
|
||||||
},
|
|
||||||
{
|
|
||||||
prop: 'attrs.database',
|
|
||||||
align: 'center',
|
|
||||||
label: this.$t('assets.Database')
|
|
||||||
},
|
|
||||||
{
|
|
||||||
prop: 'comment',
|
|
||||||
align: 'center',
|
|
||||||
showOverflowTooltip: true,
|
|
||||||
label: this.$t('assets.Comment')
|
|
||||||
},
|
|
||||||
{
|
|
||||||
prop: 'id',
|
|
||||||
align: 'center',
|
|
||||||
label: this.$t('assets.Action'),
|
|
||||||
formatter: ActionsFormatter,
|
|
||||||
formatterArgs: {
|
|
||||||
hasDelete: false,
|
|
||||||
hasUpdate: false,
|
|
||||||
hasClone: false,
|
|
||||||
extraActions: [
|
|
||||||
{
|
|
||||||
name: 'connect',
|
|
||||||
fa: 'fa-terminal',
|
|
||||||
type: 'primary',
|
|
||||||
callback: function({ row }) {
|
|
||||||
window.open(`/luna/?type=database_app&login_to=${row.id}`, '_blank')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
headerActions: {
|
|
||||||
hasExport: false,
|
|
||||||
hasImport: false,
|
|
||||||
hasRefresh: true,
|
|
||||||
hasCreate: false,
|
|
||||||
hasBulkDelete: false,
|
|
||||||
hasBulkUpdate: false,
|
|
||||||
hasLeftActions: false,
|
|
||||||
hasSearch: true,
|
|
||||||
hasRightActions: true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
|
|
||||||
},
|
|
||||||
mounted() {
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang='less' scoped>
|
|
||||||
|
|
||||||
</style>
|
|
@ -1,96 +0,0 @@
|
|||||||
<template>
|
|
||||||
<Page>
|
|
||||||
<ListTable ref="ListTable" :table-config="tableConfig" :header-actions="headerActions" />
|
|
||||||
</Page>
|
|
||||||
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import ListTable from '@/components/ListTable'
|
|
||||||
import Page from '@/layout/components/Page'
|
|
||||||
import { ActionsFormatter } from '@/components/TableFormatters'
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: 'KubernetesApp',
|
|
||||||
components: {
|
|
||||||
ListTable,
|
|
||||||
Page
|
|
||||||
},
|
|
||||||
props: {
|
|
||||||
},
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
tableConfig: {
|
|
||||||
url: `/api/v1/perms/users/applications/?category=cloud`,
|
|
||||||
columns: [
|
|
||||||
{
|
|
||||||
prop: 'name',
|
|
||||||
align: 'center',
|
|
||||||
label: this.$t('assets.Name'),
|
|
||||||
sortable: true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
prop: 'type_display',
|
|
||||||
align: 'center',
|
|
||||||
label: this.$t('assets.Type')
|
|
||||||
},
|
|
||||||
{
|
|
||||||
prop: 'attrs.cluster',
|
|
||||||
align: 'center',
|
|
||||||
label: this.$t('applications.cluster')
|
|
||||||
},
|
|
||||||
{
|
|
||||||
prop: 'comment',
|
|
||||||
align: 'center',
|
|
||||||
showOverflowTooltip: true,
|
|
||||||
label: this.$t('assets.Comment')
|
|
||||||
},
|
|
||||||
{
|
|
||||||
prop: 'id',
|
|
||||||
align: 'center',
|
|
||||||
label: this.$t('assets.Action'),
|
|
||||||
formatter: ActionsFormatter,
|
|
||||||
formatterArgs: {
|
|
||||||
hasDelete: false,
|
|
||||||
hasUpdate: false,
|
|
||||||
hasClone: false,
|
|
||||||
extraActions: [
|
|
||||||
{
|
|
||||||
name: 'connect',
|
|
||||||
fa: 'fa-terminal',
|
|
||||||
type: 'primary',
|
|
||||||
callback: function({ row }) {
|
|
||||||
window.open(`/luna/?type=k8s_app&login_to=${row.id}`, '_blank')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
headerActions: {
|
|
||||||
hasExport: false,
|
|
||||||
hasImport: false,
|
|
||||||
hasRefresh: true,
|
|
||||||
hasCreate: false,
|
|
||||||
hasBulkDelete: false,
|
|
||||||
hasBulkUpdate: false,
|
|
||||||
hasLeftActions: false,
|
|
||||||
hasSearch: true,
|
|
||||||
hasRightActions: true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
|
|
||||||
},
|
|
||||||
mounted() {
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang='less' scoped>
|
|
||||||
|
|
||||||
</style>
|
|
@ -1,95 +0,0 @@
|
|||||||
<template>
|
|
||||||
<Page>
|
|
||||||
<ListTable ref="ListTable" :table-config="tableConfig" :header-actions="headerActions" />
|
|
||||||
</Page>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import ListTable from '@/components/ListTable'
|
|
||||||
import Page from '@/layout/components/Page'
|
|
||||||
import { ActionsFormatter } from '@/components/TableFormatters'
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: 'RemoteApp',
|
|
||||||
components: {
|
|
||||||
ListTable,
|
|
||||||
Page
|
|
||||||
},
|
|
||||||
props: {
|
|
||||||
},
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
tableConfig: {
|
|
||||||
url: `/api/v1/perms/users/applications/?category=remote_app`,
|
|
||||||
columns: [
|
|
||||||
{
|
|
||||||
prop: 'name',
|
|
||||||
align: 'center',
|
|
||||||
label: this.$t('assets.Name'),
|
|
||||||
sortable: true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
prop: 'type_display',
|
|
||||||
align: 'center',
|
|
||||||
label: this.$t('assets.Type')
|
|
||||||
},
|
|
||||||
{
|
|
||||||
prop: 'attrs.asset_info.hostname',
|
|
||||||
align: 'center',
|
|
||||||
label: this.$t('assets.Asset')
|
|
||||||
},
|
|
||||||
{
|
|
||||||
prop: 'comment',
|
|
||||||
align: 'center',
|
|
||||||
showOverflowTooltip: true,
|
|
||||||
label: this.$t('assets.Comment')
|
|
||||||
},
|
|
||||||
{
|
|
||||||
prop: 'id',
|
|
||||||
align: 'center',
|
|
||||||
label: this.$t('assets.Action'),
|
|
||||||
formatter: ActionsFormatter,
|
|
||||||
formatterArgs: {
|
|
||||||
hasDelete: false,
|
|
||||||
hasUpdate: false,
|
|
||||||
hasClone: false,
|
|
||||||
extraActions: [
|
|
||||||
{
|
|
||||||
name: 'connect',
|
|
||||||
fa: 'fa-terminal',
|
|
||||||
type: 'primary',
|
|
||||||
callback: function({ row }) {
|
|
||||||
window.open(`/luna/?type=remote_app&login_to=${row.id}`, '_blank')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
headerActions: {
|
|
||||||
hasExport: false,
|
|
||||||
hasImport: false,
|
|
||||||
hasRefresh: true,
|
|
||||||
hasCreate: false,
|
|
||||||
hasBulkDelete: false,
|
|
||||||
hasBulkUpdate: false,
|
|
||||||
hasLeftActions: false,
|
|
||||||
hasSearch: true,
|
|
||||||
hasRightActions: true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
|
|
||||||
},
|
|
||||||
mounted() {
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang='less' scoped>
|
|
||||||
|
|
||||||
</style>
|
|
@ -0,0 +1,48 @@
|
|||||||
|
<template>
|
||||||
|
<BaseAssetCreateUpdate v-if="!loading" v-bind="config" />
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import BaseAssetCreateUpdate from '@/views/assets/Asset/AssetCreateUpdate/BaseAssetCreateUpdate'
|
||||||
|
export default {
|
||||||
|
components: {
|
||||||
|
BaseAssetCreateUpdate
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
loading: true,
|
||||||
|
config: {
|
||||||
|
url: '/api/v1/terminal/applet-hosts/?oid=RemoteAppHost',
|
||||||
|
addFields: [
|
||||||
|
[this.$t('assets.Account'), ['account_automation']]
|
||||||
|
],
|
||||||
|
addFieldsMeta: {
|
||||||
|
platform: {
|
||||||
|
hidden: () => true
|
||||||
|
},
|
||||||
|
nodes: {
|
||||||
|
hidden: () => true
|
||||||
|
},
|
||||||
|
labels: {
|
||||||
|
hidden: () => true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
createSuccessNextRoute: { name: 'Applets' },
|
||||||
|
updateSuccessNextRoute: { name: 'Applets' }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
async mounted() {
|
||||||
|
const platform = await this.$axios.get('/api/v1/assets/platforms/RemoteAppHost/')
|
||||||
|
this.$route.query.platform = platform['id']
|
||||||
|
this.$route.query.oid = 'SYSTEM'
|
||||||
|
this.loading = false
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less" scoped>
|
||||||
|
|
||||||
|
</style>
|
55
src/views/settings/Applet/AppletHosts/AppletHostList.vue
Normal file
55
src/views/settings/Applet/AppletHosts/AppletHostList.vue
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
<template>
|
||||||
|
<ListTable class="applet-host" v-bind="$data" />
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { ListTable } from '@/components'
|
||||||
|
export default {
|
||||||
|
name: 'AppletHost',
|
||||||
|
components: {
|
||||||
|
ListTable
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
tableConfig: {
|
||||||
|
url: '/api/v1/terminal/applet-hosts/',
|
||||||
|
columns: [
|
||||||
|
'name', 'address', 'protocols',
|
||||||
|
'comment', 'date_created', 'date_updated', 'actions'
|
||||||
|
],
|
||||||
|
columnsShow: {
|
||||||
|
min: ['name', 'actions'],
|
||||||
|
default: [
|
||||||
|
'name', 'address', 'protocols',
|
||||||
|
'comment', 'actions'
|
||||||
|
]
|
||||||
|
},
|
||||||
|
columnsMeta: {
|
||||||
|
protocols: {
|
||||||
|
label: this.$t('assets.Protocols'),
|
||||||
|
formatter: (row) => {
|
||||||
|
return row.protocols.map(p => <el-tag size='mini' class='protocol'>{p.name}/{p.port} </el-tag>)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
actions: {
|
||||||
|
formatterArgs: {
|
||||||
|
updateRoute: 'AppletHostUpdate'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
headerActions: {
|
||||||
|
createRoute: 'AppletHostCreate'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.applet-host >>> .protocol {
|
||||||
|
margin-left: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
</style>
|
86
src/views/settings/Applet/Applets/AppletList.vue
Normal file
86
src/views/settings/Applet/Applets/AppletList.vue
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<ListTable v-bind="$data" />
|
||||||
|
<UploadDialog :visible.sync="uploadDialogVisible" />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { ListTable } from '@/components'
|
||||||
|
import UploadDialog from './UploadDialog'
|
||||||
|
export default {
|
||||||
|
name: 'Applets',
|
||||||
|
components: {
|
||||||
|
ListTable,
|
||||||
|
UploadDialog
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
uploadDialogVisible: false,
|
||||||
|
tableConfig: {
|
||||||
|
url: '/api/v1/terminal/applets/',
|
||||||
|
columns: [
|
||||||
|
'icon', 'name', 'version', 'author', 'protocols',
|
||||||
|
'type', 'comment', 'date_created', 'date_updated', 'actions'
|
||||||
|
],
|
||||||
|
columnsShow: {
|
||||||
|
min: ['icon', 'name', 'version', 'author', 'protocols', 'actions'],
|
||||||
|
default: [
|
||||||
|
'icon', 'name', 'version', 'author', 'protocols',
|
||||||
|
'type', 'comment', 'actions'
|
||||||
|
]
|
||||||
|
},
|
||||||
|
columnsMeta: {
|
||||||
|
icon: {
|
||||||
|
align: 'center',
|
||||||
|
width: '60px',
|
||||||
|
formatter: (row) => {
|
||||||
|
return <img src={row.icon} width='30' height='30' alt='icon'></img>
|
||||||
|
}
|
||||||
|
},
|
||||||
|
name: {
|
||||||
|
formatterArgs: {
|
||||||
|
getTitle: ({ row }) => row['display_name']
|
||||||
|
}
|
||||||
|
},
|
||||||
|
version: {
|
||||||
|
width: '80px'
|
||||||
|
},
|
||||||
|
type: {
|
||||||
|
width: '80px'
|
||||||
|
},
|
||||||
|
protocols: {
|
||||||
|
formatter: (row) => {
|
||||||
|
return row.protocols.map(tag => <el-tag size='mini'>{tag}</el-tag>)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
headerActions: {
|
||||||
|
onCreate: () => {
|
||||||
|
this.uploadDialogVisible = true
|
||||||
|
}
|
||||||
|
// moreCreates: {
|
||||||
|
// callback: (option) => {
|
||||||
|
// this.uploadDialogVisible = true
|
||||||
|
// },
|
||||||
|
// dropdown: [
|
||||||
|
// {
|
||||||
|
// title: this.$t('common.OfflineUpload'),
|
||||||
|
// name: 'ByUpload'
|
||||||
|
// }
|
||||||
|
// {
|
||||||
|
// title: this.$t('common.Online'),
|
||||||
|
// name: 'Online'
|
||||||
|
// }
|
||||||
|
// ]
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
|
||||||
|
</style>
|
100
src/views/settings/Applet/Applets/UploadDialog.vue
Normal file
100
src/views/settings/Applet/Applets/UploadDialog.vue
Normal file
@ -0,0 +1,100 @@
|
|||||||
|
<template>
|
||||||
|
<Dialog
|
||||||
|
title="离线上传"
|
||||||
|
v-bind="$attrs"
|
||||||
|
@confirm="onSubmit"
|
||||||
|
v-on="$listeners"
|
||||||
|
>
|
||||||
|
<el-form label-position="top">
|
||||||
|
<el-form-item
|
||||||
|
:label="$tc('common.Upload' )"
|
||||||
|
:label-width="'100px'"
|
||||||
|
class="file-uploader"
|
||||||
|
>
|
||||||
|
<el-upload
|
||||||
|
ref="upload"
|
||||||
|
drag
|
||||||
|
action="string"
|
||||||
|
list-type="text/csv"
|
||||||
|
:limit="1"
|
||||||
|
:auto-upload="false"
|
||||||
|
:on-change="onFileChange"
|
||||||
|
:before-upload="beforeUpload"
|
||||||
|
accept=".zip"
|
||||||
|
>
|
||||||
|
<i class="el-icon-upload" />
|
||||||
|
<div class="el-upload__text">
|
||||||
|
{{ $t('common.imExport.dragUploadFileInfo') }}
|
||||||
|
</div>
|
||||||
|
<div slot="tip" class="el-upload__tip">
|
||||||
|
<span :class="{'hasError': hasFileFormatOrSizeError }">
|
||||||
|
{{ $t('terminal.uploadZipTips') }}
|
||||||
|
</span>
|
||||||
|
<div v-if="renderError" class="hasError">{{ renderError }}</div>
|
||||||
|
</div>
|
||||||
|
</el-upload>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
</Dialog>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { Dialog } from '@/components'
|
||||||
|
export default {
|
||||||
|
name: 'UploadDialog',
|
||||||
|
components: {
|
||||||
|
Dialog
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
hasFileFormatOrSizeError: false,
|
||||||
|
renderError: '',
|
||||||
|
file: null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
onFileChange(file, fileList) {
|
||||||
|
if (file.status !== 'ready') {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
this.file = file
|
||||||
|
},
|
||||||
|
beforeUpload(file) {
|
||||||
|
},
|
||||||
|
onSubmit() {
|
||||||
|
if (!this.file) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const form = new FormData()
|
||||||
|
form.append('file', this.file.raw)
|
||||||
|
this.$axios.post(
|
||||||
|
'/api/v1/terminal/applets/upload/',
|
||||||
|
form,
|
||||||
|
{
|
||||||
|
headers: { 'Content-Type': 'multipart/form-data' },
|
||||||
|
disableFlashErrorMsg: true
|
||||||
|
}
|
||||||
|
).then(res => {
|
||||||
|
this.$message.success('上传成功')
|
||||||
|
this.$emit('update:visible', false)
|
||||||
|
}).catch(err => {
|
||||||
|
this.$message.error(err)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.file-uploader.el-form-item {
|
||||||
|
margin-bottom: 0;
|
||||||
|
|
||||||
|
>>> .el-upload {
|
||||||
|
width: 100%;
|
||||||
|
.el-upload-dragger {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
</style>
|
40
src/views/settings/Applet/index.vue
Normal file
40
src/views/settings/Applet/index.vue
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
<template>
|
||||||
|
<TabPage :submenu="submenu" :active-menu.sync="activeMenu">
|
||||||
|
<keep-alive>
|
||||||
|
<component :is="activeMenu" />
|
||||||
|
</keep-alive>
|
||||||
|
</TabPage>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { TabPage } from '@/layout/components'
|
||||||
|
import Applets from './Applets/AppletList'
|
||||||
|
import AppletHosts from './AppletHosts/AppletHostList'
|
||||||
|
export default {
|
||||||
|
name: 'Applet',
|
||||||
|
components: {
|
||||||
|
TabPage,
|
||||||
|
Applets,
|
||||||
|
AppletHosts
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
activeMenu: 'Applets',
|
||||||
|
submenu: [
|
||||||
|
{
|
||||||
|
title: this.$t('terminal.Applets'),
|
||||||
|
name: 'Applets'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: this.$t('terminal.AppletHosts'),
|
||||||
|
name: 'AppletHosts'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
|
||||||
|
</style>
|
@ -140,7 +140,7 @@ export default {
|
|||||||
return !this.currentOrgIsRoot && this.publicSettings.XPACK_LICENSE_IS_VALID
|
return !this.currentOrgIsRoot && this.publicSettings.XPACK_LICENSE_IS_VALID
|
||||||
},
|
},
|
||||||
can: () => vm.$hasPerm('users.invite_user'),
|
can: () => vm.$hasPerm('users.invite_user'),
|
||||||
callback: function() { this.InviteDialogSetting.InviteDialogVisible = true }.bind(this)
|
callback: () => { this.InviteDialogSetting.InviteDialogVisible = true }
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
extraMoreActions: [
|
extraMoreActions: [
|
||||||
|
Loading…
Reference in New Issue
Block a user