[Update] merge

This commit is contained in:
ibuler
2020-04-08 20:04:09 +08:00
20 changed files with 528 additions and 294 deletions

9
src/api/sessions.js Normal file
View File

@@ -0,0 +1,9 @@
import request from '@/utils/request'
export function terminateSession(data) {
return request({
url: '/api/v1/terminal/tasks/kill-session/',
method: 'post',
data: data
})
}

View File

@@ -1,7 +1,5 @@
<template>
<ElDatableTable ref="table" class="el-table" v-bind="tableConfig" v-on="$listeners">
<slot />
</ElDatableTable>
<ElDatableTable ref="table" class="el-table" v-bind="tableConfig" v-on="$listeners" />
</template>
<script>

View File

@@ -7,8 +7,8 @@
<slot />
<div slot="footer" class="dialog-footer">
<slot name="footer">
<el-button size="small" @click="onCancel">{{ $t('Cancel') }}</el-button>
<el-button type="primary" size="small" @click="onConfirm">{{ $tc('Ok') }}</el-button>
<el-button size="small" @click="onCancel">{{ $tc('Cancel') }}</el-button>
<el-button type="primary" size="small" @click="onConfirm">{{ $tc('Confirm') }}</el-button>
</slot>
</div>
</el-dialog>

View File

@@ -0,0 +1,23 @@
<template>
<span>{{ getCellValueLength }}</span>
</template>
<script>
import BaseFormatter from './base'
export default {
name: 'LengthFormatter',
extends: BaseFormatter,
computed: {
getCellValueLength() {
if (this.cellValue instanceof Array) {
return this.cellValue.length
}
return this.cellValue
}
}
}
</script>
<style scoped>
</style>

View File

@@ -19,7 +19,7 @@ export default {
default: () => ({})
},
cellValue: {
type: [String, Boolean, Number, Object],
type: [String, Boolean, Number, Object, Array],
default: null
},
tableData: {

View File

@@ -3,3 +3,4 @@ export { default as DisplayFormatter } from './DisplayFormatter'
export { default as BooleanFormatter } from './ChoicesFormatter'
export { default as ActionsFormatter } from './ActionsFormatter'
export { default as ExpandPreFormatter } from './ExpandPreFormatter'
export { default as LengthFormatter } from './LengthFormatter'

View File

@@ -3,35 +3,35 @@
<TableAction :table-url="tableConfig.url" :search-table="search" v-bind="headerActions" :selected-rows="selectedRows" :reload-table="reloadTable" />
<el-card class="table-content" shadow="never">
<AutoDataTable ref="dataTable" :config="tableConfig" @selection-change="handleSelectionChange" />
<Dialog :title="$t('Export')" :visible.sync="showExportDialog" @comfirm="handleDialogConfirm('export')" @cancel="handleDialogCancel('export')">
<Dialog :title="$tc('Export')" :visible.sync="showExportDialog" center @comfirm="handleDialogConfirm('export')" @cancel="handleDialogCancel('export')">
<el-form>
<el-form-item label="导出范围" :label-width="'100px'">
<p>{{ $d(new Date(), 'short') }}</p>
<el-radio v-model="exportOption" class="export-item" label="1">导出全部</el-radio>
<el-radio v-model="exportOption" class="export-item" label="2">仅导出选中项</el-radio>
<el-radio v-model="exportOption" class="export-item" label="3">仅导出搜索项</el-radio>
<!-- <el-radio v-model="exportOption" class="export-item" label="3">仅导出搜索项</el-radio> -->
</el-form-item>
</el-form>
</Dialog>
<Dialog :title="$t('Import')" :visible.sync="showImportDialog" @comfirm="handleDialogConfirm('import')" @cancel="handleDialogCancel('import')">
<Dialog :title="importtitle" :visible.sync="showImportDialog" center @comfirm="handleDialogConfirm('import')" @cancel="handleDialogCancel('import')">
<el-form>
<el-form-item label="导入/更新" :label-width="'100px'">
<el-radio v-model="importOption" class="export-item" label="1">出全部</el-radio>
<el-radio v-model="importOption" class="export-item" label="2">仅导出选中项</el-radio>
<el-radio v-model="importOption" class="export-item" label="3">仅导出搜索项</el-radio>
<el-form-item :label="importtitle" :label-width="'100px'">
<el-radio v-model="importOption" class="export-item" label="1">入新资产</el-radio>
<el-radio v-model="importOption" class="export-item" label="2">更新资产</el-radio>
</el-form-item>
</el-form>
<div>
<div v-if="importOption==='1'" style="margin-bottom:20px;margin-left: 55px;">下载导入的模板或使用导出的csv格式 <a style="color: #428bca;" :href="downloadImportTempUrl">下载导入模板</a></div>
<div v-else style="margin-bottom:20px;margin-left: 55px;">下载更新的模板或使用导出的csv格式 <a style="color: #428bca;" @click="downloadUpdateTempUrl">下载更新模板</a></div>
<div style="margin-left:55px;">
<el-upload
class="upload-card"
:action="upLoadUrl"
:on-preview="handlePreview"
:on-remove="handleRemove"
:before-remove="beforeRemove"
:on-exceed="handleExceed"
action="string"
:http-request="upload"
list-type="text/csv"
:limit="1"
>
<el-button size="small" type="primary">点击上传</el-button>
<div slot="tip" class="el-upload__tip">只能上传jpg/png文件且不超过500kb</div>
<div slot="tip" class="el-upload__tip">只能上传CSV文件</div>
</el-upload>
</div>
</Dialog>
@@ -81,7 +81,13 @@ export default {
return this.selectedRows.length > 0
},
upLoadUrl() {
return process.env.VUE_APP_BASE_API + this.tableConfig.url
return this.tableConfig.url
},
importtitle() {
if (this.importOption === '1') { return this.$tc('Import') } else { return this.$tc('Update') }
},
downloadImportTempUrl() {
return process.env.VUE_APP_BASE_API + this.tableConfig.url + '?format=csv&template=import&limit=1'
}
},
mounted() {
@@ -93,6 +99,15 @@ export default {
})
},
methods: {
upload(item) {
console.log(item)
this.$axios.put(
this.upLoadUrl,
item.file
).then((res) =>
console.log(res)
)
},
downloadCsv(url) {
const a = document.createElement('a')
a.href = url
@@ -103,16 +118,16 @@ export default {
this.selectedRows = val
},
reloadTable() {
this.$refs.dataTable.getList()
this.$refs.dataTable.$refs.dataTable.getList()
},
search(attrs) {
return this.$refs.dataTable.search(attrs)
return this.$refs.dataTable.$refs.dataTable.search(attrs)
},
async handleExport() {
let data
var resources = []
if (this.exportOption === '1') {
data = this.$refs.dataTable.getData()
data = this.$refs.dataTable.$refs.dataTable.getData()
} else if (this.exportOption === '2') {
data = this.selectedRows
} else {
@@ -127,6 +142,16 @@ export default {
},
handleImport() {
},
async downloadUpdateTempUrl() {
var resources = []
const data = this.$refs.dataTable.$refs.dataTable.getData()
for (let index = 0; index < data.length; index++) {
resources.push(data[index].id)
}
const spm = await createSourceIdCache(resources)
const url = process.env.VUE_APP_BASE_API + `${this.tableConfig.url}?format=csv&template=update&spm=` + spm.spm
return this.downloadCsv(url)
},
async handleDialogConfirm(val) {
switch (val) {

View File

@@ -52,6 +52,12 @@ const cn = {
'Reset': '重置',
'This field is required': '这个字段是必填项',
'Validity': '有效性',
'confirm': '确认',
'Confirm': '确认',
'Cancel': '取消',
'cancel': '取消',
'Import': '导入',
'Export': '导出',
'Other': '其它'
},
route: {
@@ -73,8 +79,11 @@ const cn = {
'DatabaseApp': '数据库应用',
'Perms': '权限管理',
'AssetPermission': '资产授权',
'AssetPermissionCreate': '创建资产授权规则',
'RemoteAppPermission': '远程应用授权',
'RemoteAppPermissionCreate': '创建远程应用授权规则',
'DatabaseAppPermission': '数据库应用授权',
'DatabaseAppPermissionCreate': '创建数据库应用授权规则',
'Sessions': '会话管理',
'SessionOnline': '在线会话',
'SessionOffline': '历史会话',
@@ -339,20 +348,14 @@ const cn = {
'active': '激活中',
'users_and_user_groups': '用户或用户组',
'assets_and_node': '资产或节点',
'Basic': '基本',
'User': '用户',
'Asset': '资产',
'Actions': '动作',
//
'RemoteApp': '远程应用',
'remote_app_permission_list': '远程应用授权列表',
'remote_app_permission_detail': '远程应用授权详情',
'create_remote_app_permission': '创建远程应用授权规则',
'update_remote_app_permission': '更新远程应用授权规则',
'remote_app_count': '远程应用数量',
//
'DatabaseApp': '数据库应用',
'database_app_permission_list': '数据库应用授权列表',
'database_app_permission_detail': '数据库应用授权详情',
'create_database_app_permission': '创建数据库应用授权规则',
'update_database_app_permission': '更新数据库应用授权规则',
'database_app_count': '数据库应用数量'
'DatabaseApp': '数据库应用'
},
sessions: {
'id': 'ID',
@@ -376,7 +379,8 @@ const cn = {
'addr': '地址',
'active': '激活中',
'alive': '在线',
'StorageConfiguration': '存储配置'
'StorageConfiguration': '存储配置',
'join': '加入'
},
jobcenter: {
'RunTimes': '执行次数',

View File

@@ -288,7 +288,8 @@ const en = {
'quick_modify': 'Quick modify',
'terminate_session': 'Terminate session',
'confirm': 'Confirm',
'commands': 'Commands'
'commands': 'Commands',
'join': 'join'
},
setting: {
'setting': 'System Setting',

View File

@@ -214,17 +214,38 @@ export const constantRoutes = [
component: () => import('@/views/perms/AssetPermissionList'),
meta: { title: 'AssetPermission' }
},
{
path: 'asset-permissions/create',
component: () => import('@/views/perms/AssetPermissionCreateUpdate'), // Parent router-view
name: 'AssetPermissionCreate',
hidden: true,
meta: { title: 'AssetPermissionCreate', activeMenu: '/perms/asset-permissions' }
},
{
path: 'remote-app-permissions',
name: 'RemoteAppPermissionList',
component: () => import('@/views/perms/RemoteAppPermissionList'),
meta: { title: 'RemoteAppPermission' }
},
{
path: 'remote-app-permissions/create',
component: () => import('@/views/perms/RemoteAppPermissionCreateUpdate'), // Parent router-view
name: 'RemoteAppPermissionCreate',
hidden: true,
meta: { title: 'RemoteAppPermissionCreate', activeMenu: '/perms/remote-app-permissions' }
},
{
path: 'database-app-permissions',
name: 'DatabaseAppPermissionList',
component: () => import('@/views/perms/DatabaseAppPermissionList'),
meta: { title: 'DatabaseAppPermission' }
},
{
path: 'database-app-permissions/create',
component: () => import('@/views/perms/DatabaseAppPermissionCreateUpdate'), // Parent router-view
name: 'DatabaseAppPermissionCreate',
hidden: true,
meta: { title: 'DatabaseAppPermissionCreate', activeMenu: '/perms/database-app-permissions' }
}
]
},

78
src/utils/common.js Normal file
View File

@@ -0,0 +1,78 @@
function getTimeUnits(u) {
const units = {
'd': '天',
'h': '时',
'm': '分',
's': '秒'
}
if (getUserLang() === 'zh-CN') {
return units[u]
}
return u
}
export function timeOffset(a, b) {
const start = safeDate(a)
const end = safeDate(b)
const offset = (end - start) / 1000
return readableSecond(offset)
}
function readableSecond(offset) {
const days = offset / 3600 / 24
const hours = offset / 3600
const minutes = offset / 60
const seconds = offset
if (days > 1) {
return days.toFixed(1) + ' ' + getTimeUnits('d')
} else if (hours > 1) {
return hours.toFixed(1) + ' ' + getTimeUnits('h')
} else if (minutes > 1) {
return minutes.toFixed(1) + ' ' + getTimeUnits('m')
} else if (seconds > 1) {
return seconds.toFixed(1) + ' ' + getTimeUnits('s')
}
return ''
}
function getUserLang() {
const userLangEN = document.cookie.indexOf('django_language=en')
if (userLangEN === -1) {
return 'zh-CN'
} else {
return 'en-US'
}
}
function safeDate(s) {
s = cleanDateStr(s)
return new Date(s)
}
function cleanDateStr(d) {
for (let i = 0; i < 3; i++) {
if (!isNaN(Date.parse(d))) {
return d
}
if (!isNaN(Number(d))) {
return d
}
switch (i) {
case 0:
d = d.replaceAll('-', '/')
break
case 1:
d = d.split('+')[0].trimRight()
break
}
}
return null
}
export function toSafeLocalDateStr(d) {
const date = safeDate(d)
// var date_s = date.toLocaleString(getUserLang(), {hour12: false});
const date_s = date.toLocaleString(getUserLang(), { hourCycle: 'h23' })
return date_s.split('/').join('-')
}

View File

@@ -0,0 +1,69 @@
<template>
<GenericCreateUpdatePage :fields="fields" :form="form" :fields-meta="fieldsMeta" :url="url" />
</template>
<script>
import { GenericCreateUpdatePage } from '@/layout/components'
export default {
components: {
GenericCreateUpdatePage
},
data() {
return {
form: {
date_expired: '2099-12-31 00:00:00 +0800'
},
fields: [
[this.$t('perms.' + 'Basic'), ['name']],
[this.$t('perms.' + 'User'), ['users', 'user_groups']],
[this.$t('perms.' + 'Asset'), ['assets', 'nodes', 'system_users']],
[this.$tc('Action'), ['actions']],
[this.$tc('Other'), ['is_active', 'date_expired', 'comment']]
],
url: '/api/v1/perms/asset-permissions/',
fieldsMeta: {
users: {
el: {
value: [],
url: '/api/v1/users/users/'
}
},
user_groups: {
el: {
value: [],
url: '/api/v1/users/groups/'
}
},
assets: {
el: {
value: [],
url: '/api/v1/assets/nodes/children/tree/'
}
},
nodes: {
el: {
value: [],
url: '/api/v1/assets/nodes/'
}
},
system_users: {
el: {
value: [],
url: '/api/v1/assets/system-users/'
}
},
actions: {
label: this.$t('perms.Actions')
},
is_active: {
type: 'checkbox'
}
}
}
}
}
</script>
<style scoped>
</style>

View File

@@ -4,7 +4,7 @@
<script>
import { GenericListPage } from '@/layout/components'
import { DetailFormatter, ActionsFormatter, BooleanFormatter } from '@/components/ListTable/formatters/index'
import { LengthFormatter } from '@/components/ListTable/formatters/index'
export default {
components: {
@@ -14,59 +14,23 @@ export default {
return {
tableConfig: {
url: '/api/v1/perms/asset-permissions/',
columns: [
{
prop: 'name',
label: this.$t('common.name'),
formatter: DetailFormatter,
sortable: true,
route: 'AssetPermissionDetail'
columns: ['name', 'users', 'user_groups', 'assets', 'nodes', 'system_users', 'is_active', 'actions'],
columnsMeta: {
users: {
formatter: LengthFormatter
},
{
prop: 'users.length',
label: this.$t('perms.user')
user_groups: {
formatter: LengthFormatter
},
{
prop: 'user_groups.length',
label: this.$t('perms.userGroup')
assets: {
formatter: LengthFormatter
},
{
prop: 'assets.length',
label: this.$t('perms.asset')
nodes: {
formatter: LengthFormatter
},
{
prop: 'nodes.length',
label: this.$t('perms.node')
},
{
prop: 'system_users.length',
label: this.$t('perms.systemUser')
},
{
prop: 'is_active',
label: this.$t('perms.validity'),
formatter: BooleanFormatter,
align: 'center',
width: '80px'
},
{
prop: 'id',
label: this.$tc('Action'),
align: 'center',
formatter: ActionsFormatter,
width: '200px',
actions: {
performDelete: ({ row, col }) => {
const id = row.id
const url = `/api/v1/perms/asset-permissions/${id}/`
return this.$axios.delete(url)
}
}
system_users: {
formatter: LengthFormatter
}
],
tableActions: {
hasEdit: true,
editRoute: '404'
}
},
headerActions: {

View File

@@ -0,0 +1,63 @@
<template>
<GenericCreateUpdatePage :fields="fields" :form="form" :fields-meta="fieldsMeta" :url="url" />
</template>
<script>
import { GenericCreateUpdatePage } from '@/layout/components'
export default {
components: {
GenericCreateUpdatePage
},
data() {
return {
form: {
is_active: true,
date_expired: '2099-12-31 00:00:00 +0800'
},
fields: [
[this.$t('perms.' + 'Basic'), ['name']],
[this.$t('perms.' + 'User'), ['users', 'user_groups']],
[this.$t('perms.' + 'DatabaseApp'), ['database_apps', 'system_users']],
[this.$tc('Other'), ['is_active', 'date_expired', 'comment']]
],
url: '/api/v1/perms/database-app-permissions/',
fieldsMeta: {
users: {
el: {
value: [],
url: '/api/v1/users/users/'
}
},
user_groups: {
el: {
value: [],
url: '/api/v1/users/groups/'
}
},
database_apps: {
el: {
value: [],
url: '/api/v1/applications/database-apps/'
}
},
system_users: {
el: {
value: [],
url: '/api/v1/assets/system-users/'
}
},
actions: {
label: this.$t('perms.Actions')
},
is_active: {
type: 'checkbox'
}
}
}
}
}
</script>
<style scoped>
</style>

View File

@@ -4,8 +4,7 @@
<script>
import { GenericListPage } from '@/layout/components'
import { DetailFormatter, ActionsFormatter, BooleanFormatter } from '@/components/ListTable/formatters/index'
import { LengthFormatter } from '@/components/ListTable/formatters/index'
export default {
components: {
GenericListPage
@@ -14,52 +13,21 @@ export default {
return {
tableConfig: {
url: '/api/v1/perms/database-app-permissions/',
columns: [
{
prop: 'name',
label: this.$t('perms.name'),
formatter: DetailFormatter,
sortable: true,
route: 'DatabaseAppPermissionDetail'
columns: ['name', 'users', 'user_groups', 'database_apps', 'system_users', 'is_valid', 'actions'],
columnsMeta: {
users: {
formatter: LengthFormatter
},
{
prop: 'users.length',
label: this.$t('perms.user')
user_groups: {
formatter: LengthFormatter
},
{
prop: 'user_groups.length',
label: this.$t('perms.userGroup')
database_apps: {
formatter: LengthFormatter
},
{
prop: 'database_apps.length',
label: this.$t('perms.DatabaseApp')
},
{
prop: 'system_users.length',
label: this.$t('perms.systemUser')
},
{
prop: 'is_valid',
label: this.$t('perms.validity'),
formatter: BooleanFormatter,
align: 'center',
width: '80px'
},
{
prop: 'id',
label: this.$tc('Action'),
align: 'center',
formatter: ActionsFormatter,
width: '200px',
actions: {
performDelete: ({ row, col }) => {
const id = row.id
const url = `/api/v1/perms/database-app-permissions/${id}/`
return this.$axios.delete(url)
}
}
system_users: {
formatter: LengthFormatter
}
]
}
},
headerActions: {
hasBulkDelete: false,

View File

@@ -0,0 +1,63 @@
<template>
<GenericCreateUpdatePage :fields="fields" :form="form" :fields-meta="fieldsMeta" :url="url" />
</template>
<script>
import { GenericCreateUpdatePage } from '@/layout/components'
export default {
components: {
GenericCreateUpdatePage
},
data() {
return {
form: {
is_active: true,
date_expired: '2099-12-31 00:00:00 +0800'
},
fields: [
[this.$t('perms.' + 'Basic'), ['name']],
[this.$t('perms.' + 'User'), ['users', 'user_groups']],
[this.$t('perms.' + 'RemoteApp'), ['remote_apps', 'system_users']],
[this.$tc('Other'), ['is_active', 'date_expired', 'comment']]
],
url: '/api/v1/perms/remote-app-permissions/',
fieldsMeta: {
users: {
el: {
value: [],
url: '/api/v1/users/users/'
}
},
user_groups: {
el: {
value: [],
url: '/api/v1/users/groups/'
}
},
remote_apps: {
el: {
value: [],
url: '/api/v1/applications/remote-apps/'
}
},
system_users: {
el: {
value: [],
url: '/api/v1/assets/system-users/'
}
},
actions: {
label: this.$t('perms.Actions')
},
is_active: {
type: 'checkbox'
}
}
}
}
}
</script>
<style scoped>
</style>

View File

@@ -4,7 +4,7 @@
<script>
import { GenericListPage } from '@/layout/components'
import { DetailFormatter, ActionsFormatter, BooleanFormatter } from '@/components/ListTable/formatters/index'
import { LengthFormatter } from '@/components/ListTable/formatters/index'
export default {
components: {
@@ -14,52 +14,21 @@ export default {
return {
tableConfig: {
url: '/api/v1/perms/remote-app-permissions/',
columns: [
{
prop: 'name',
label: this.$t('perms.name'),
formatter: DetailFormatter,
sortable: true,
route: 'RemoteAppPermissionDetail'
columns: ['name', 'users', 'user_groups', 'remote_apps', 'system_users', 'is_valid', 'actions'],
columnsMeta: {
users: {
formatter: LengthFormatter
},
{
prop: 'users.length',
label: this.$t('perms.user')
user_groups: {
formatter: LengthFormatter
},
{
prop: 'user_groups.length',
label: this.$t('perms.userGroup')
remote_apps: {
formatter: LengthFormatter
},
{
prop: 'remote_apps.length',
label: this.$t('perms.RemoteApp')
},
{
prop: 'system_users.length',
label: this.$t('perms.systemUser')
},
{
prop: 'is_valid',
label: this.$t('perms.validity'),
formatter: BooleanFormatter,
align: 'center',
width: '80px'
},
{
prop: 'id',
label: this.$tc('Action'),
align: 'center',
formatter: ActionsFormatter,
width: '200px',
actions: {
performDelete: ({ row, col }) => {
const id = row.id
const url = `/api/v1/perms/database-app-permissions/${id}/`
return this.$axios.delete(url)
}
}
system_users: {
formatter: LengthFormatter
}
]
}
},
headerActions: {
hasBulkDelete: false,

View File

@@ -3,6 +3,7 @@
</template>
<script>
import { timeOffset, toSafeLocalDateStr } from '@/utils/common'
import { GenericListPage } from '@/layout/components'
import { ActionsFormatter } from '@/components/ListTable/formatters/index'
@@ -13,80 +14,72 @@ export default {
data() {
return {
tableConfig: {
axiosConfig: {
raw: 1,
params: {
display: 1,
is_finished: 1
}
},
url: '/api/v1/terminal/sessions/',
hasSelection: false,
url: '/api/v1/terminal/sessions/?is_finished=1',
columns: [
{
label: this.$t('sessions.id'),
type: 'index'
'index', 'user', 'asset', 'system_user', 'remote_addr', 'protocol', 'login_from',
'command_amount', 'date_start', 'duration', 'actions'
],
columnsMeta: {
index: {
type: 'index',
label: this.$t('sessions.id')
},
{
prop: 'user',
label: this.$t('sessions.user'),
sortable: 'custom'
},
{
prop: 'asset',
label: this.$t('sessions.asset'),
sortable: 'custom'
},
{
prop: 'system_user',
label: this.$t('sessions.systemUser'),
sortable: 'custom'
},
{
prop: 'remote_addr',
label: this.$t('sessions.remoteAddr'),
sortable: 'custom'
},
{
prop: 'protocol',
label: this.$t('sessions.protocol'),
sortable: 'custom'
},
{
prop: 'login_from_display',
label: this.$t('sessions.loginForm')
},
{
prop: 'command',
command_amount: {
label: this.$t('sessions.command')
},
{
prop: 'date_start',
label: this.$t('sessions.dateStart'),
sortable: 'custom'
login_from: {
label: this.$t('sessions.loginForm')
},
{
prop: 'duration',
label: this.$t('sessions.duration')
protocol: {
label: this.$t('sessions.protocol'),
formatter: null
},
{
date_start: {
formatter: function(row) {
return toSafeLocalDateStr(row.date_start)
}
},
duration: {
label: this.$t('sessions.duration'),
formatter: function(row) {
return timeOffset(row.date_start, row.date_end)
}
},
actions: {
prop: 'id',
label: this.$tc('Action'),
align: 'center',
formatter: ActionsFormatter,
width: '200px',
actions: {
hasEdit: false,
hasDelete: false,
hasUpdate: false,
extraActions: [
{
name: 'terminate',
title: this.$t('sessions.terminate'),
type: 'primary'
name: 'replay',
title: this.$t('sessions.replay'),
type: 'warning',
callback: function({ cellValue, tableData }) {
// 跳转到luna页面
const replayUrl = '/luna/replay/' + cellValue
window.open(replayUrl)
}
},
{
name: 'download',
title: this.$t('sessions.download'),
type: 'primary',
callback: function({ cellValue, tableData }) {
// 跳转下载页面
const downloadUrl = 'terminal/session/00000000-0000-0000-0000-000000000000/replay/download/'
.replace('00000000-0000-0000-0000-000000000000', cellValue)
window.open(downloadUrl)
}
}
]
}
}
]
}
},
headerActions: {
hasCreate: false,

View File

@@ -5,6 +5,8 @@
<script>
import { GenericListPage } from '@/layout/components'
import { ActionsFormatter } from '@/components/ListTable/formatters/index'
import { toSafeLocalDateStr } from '@/utils/common'
import { terminateSession } from '@/api/sessions'
export default {
components: {
@@ -13,85 +15,73 @@ export default {
data() {
return {
tableConfig: {
axiosConfig: {
raw: 1,
params: {
display: 1,
is_finished: 0
}
},
url: '/api/v1/terminal/sessions/',
url: '/api/v1/terminal/sessions/?is_finished=0',
columns: [
{
label: this.$t('sessions.id'),
type: 'index'
'index', 'user', 'asset', 'system_user', 'remote_addr', 'protocol', 'login_from',
'command_amount', 'date_start', 'duration', 'actions'
],
columnsMeta: {
index: {
type: 'index',
label: this.$t('sessions.id')
},
{
prop: 'user',
label: this.$t('sessions.user'),
sortable: 'custom'
},
{
prop: 'asset',
label: this.$t('sessions.asset'),
sortable: 'custom'
},
{
prop: 'system_user',
label: this.$t('sessions.systemUser'),
sortable: 'custom'
},
{
prop: 'remote_addr',
label: this.$t('sessions.remoteAddr'),
sortable: 'custom'
},
{
prop: 'protocol',
label: this.$t('sessions.protocol'),
sortable: 'custom'
},
{
prop: 'login_from_display',
label: this.$t('sessions.loginForm')
},
{
prop: 'command',
command_amount: {
label: this.$t('sessions.command')
},
{
prop: 'date_start',
label: this.$t('sessions.dateStart'),
sortable: 'custom'
login_from: {
label: this.$t('sessions.loginForm')
},
{
prop: 'duration',
label: this.$t('sessions.duration')
protocol: {
label: this.$t('sessions.protocol'),
formatter: null
},
{
date_start: {
formatter: function(row) {
return toSafeLocalDateStr(row.date_start)
}
},
duration: {
label: this.$t('sessions.duration'),
formatter: null
},
actions: {
prop: 'id',
label: this.$tc('Action'),
align: 'center',
formatter: ActionsFormatter,
width: '200px',
actions: {
hasEdit: false,
hasDelete: false,
hasUpdate: false,
extraActions: [
{
name: 'replay',
title: this.$t('sessions.replay'),
type: 'primary'
name: 'terminate',
title: this.$t('sessions.terminate'),
type: 'danger',
callback: function({ reload, cellValue, tableData }) {
// 终断 session reload
const data = [cellValue]
terminateSession(data).then(res => {
window.setTimeout(function() {
reload()
}, 50000)
}
)
}
},
{
name: 'replay',
title: this.$t('sessions.download'),
type: 'warning'
name: 'join',
title: this.$t('sessions.join'),
type: 'primary',
callback: function({ cellValue, tableData }) {
// 跳转到luna页面
const joinUrl = '/luna/join/?shareroom=' + cellValue
window.open(joinUrl, 'height=600, width=800, top=400, left=400, toolbar=no, menubar=no, scrollbars=no, location=no, status=no')
}
}
]
}
}
]
}
},
headerActions: {
hasCreate: false,

View File

@@ -4,7 +4,6 @@
<script>
import { GenericListPage } from '@/layout/components'
import { ExpandPreFormatter } from '@/components/ListTable/formatters'
export default {
components: {
@@ -18,10 +17,6 @@ export default {
columnsMeta: {
users_amount: {
label: this.$t('users.Users')
},
name: {
type: 'expand',
formatter: ExpandPreFormatter
}
},
detailRoute: 'UserGroupDetail'