mirror of
https://github.com/jumpserver/lina.git
synced 2025-11-12 05:09:13 +00:00
Compare commits
23 Commits
v4.10.0
...
perf_termi
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4917212fff | ||
|
|
d84a7c824b | ||
|
|
56f4f3f144 | ||
|
|
fea1d35981 | ||
|
|
d48cb6b1f3 | ||
|
|
945ff8fc44 | ||
|
|
3a823c786e | ||
|
|
68a474644c | ||
|
|
c8b2ec9cdb | ||
|
|
67d4fdd175 | ||
|
|
0f40b38abe | ||
|
|
714350d40e | ||
|
|
d6ac0db0e6 | ||
|
|
ddae51cefc | ||
|
|
eb9f7c6cb5 | ||
|
|
a22f46087f | ||
|
|
2eedb361a0 | ||
|
|
d893964947 | ||
|
|
13838f66a9 | ||
|
|
6dccdae9b4 | ||
|
|
3f31fa9810 | ||
|
|
a17025bd3a | ||
|
|
f08ce0ee1a |
@@ -74,7 +74,7 @@ export default {
|
||||
},
|
||||
|
||||
createWatermark() {
|
||||
if (this.currentUser?.username && this.publicSettings?.SECURITY_WATERMARK_ENABLED && this.$store.getters.hasValidLicense) {
|
||||
if (this.currentUser?.username && this.publicSettings?.SECURITY_WATERMARK_ENABLED) {
|
||||
this.watermark = new Watermark({
|
||||
content: this.getWaterMarkContent(),
|
||||
width: this.publicSettings?.SECURITY_WATERMARK_WIDTH,
|
||||
|
||||
1
src/assets/img/cloud/smartx.svg
Normal file
1
src/assets/img/cloud/smartx.svg
Normal file
@@ -0,0 +1 @@
|
||||
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1748326203303" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2853" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M10.24 605.184l839.168-481.28L1013.76 220.672v191.488L174.592 895.488 10.24 804.352z" fill="#0096FF" p-id="2854"></path><path d="M10.24 416.768V220.672l168.96-96.768 308.736 178.688-331.776 193.536zM541.184 717.312l331.264-195.072 141.312 88.064v194.048l-165.376 95.744z" fill="#25C764" p-id="2855"></path></svg>
|
||||
|
After Width: | Height: | Size: 645 B |
@@ -33,7 +33,7 @@
|
||||
<!-- eslint-disable-next-line -->
|
||||
<div class="divider"></div>
|
||||
<p>
|
||||
<MessageText :message="item.reasoning" />
|
||||
<MessageText :message="item.reasoning" @insert-code="handleInsertCode" />
|
||||
</p>
|
||||
</div>
|
||||
|
||||
@@ -41,7 +41,7 @@
|
||||
<span v-if="isServerError" class="error">
|
||||
{{ isServerError }}
|
||||
</span>
|
||||
<MessageText :message="item.result" />
|
||||
<MessageText :message="item.result" @insert-code="handleInsertCode" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -142,6 +142,9 @@ export default {
|
||||
if (value === 'copy') {
|
||||
copy(this.item.result.content)
|
||||
}
|
||||
},
|
||||
handleInsertCode(code) {
|
||||
this.$emit('insert-code', code)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -69,26 +69,61 @@ export default {
|
||||
this.markdown.use(mdKatex, { blockClass: 'katexmath-block rounded-md', errorColor: ' #cc0000' })
|
||||
},
|
||||
highlightBlock(str, lang) {
|
||||
return `<pre class="code-block-wrapper"><div class="code-block-header"><span class="code-block-header__lang">${lang}</span><span class="code-block-header__copy">${'Copy'}</span></div><code class="hljs code-block-body ${lang}">${str}</code></pre>`
|
||||
return `<pre class="code-block-wrapper">
|
||||
<div class="code-block-header">
|
||||
<span class="code-block-header__lang">${lang}</span>
|
||||
<span class="code-block-header__actions">
|
||||
<span class="code-block-header__insert">${'insert'}</span>
|
||||
<span class="code-block-header__copy">${'Copy'}</span>
|
||||
</span>
|
||||
</div>
|
||||
<code class="hljs code-block-body ${lang}">${str}</code></pre>`
|
||||
},
|
||||
addCopyEvents() {
|
||||
const copyBtn = document.querySelectorAll('.code-block-header__copy')
|
||||
copyBtn.forEach((btn) => {
|
||||
btn.addEventListener('click', () => {
|
||||
const code = btn.parentElement?.nextElementSibling?.textContent
|
||||
if (code) {
|
||||
copy(code)
|
||||
}
|
||||
this.addBtnClickEvents('.code-block-header__copy', this.handlerClickCopy)
|
||||
this.addBtnClickEvents('.code-block-header__insert', this.handlerClickInsert)
|
||||
},
|
||||
|
||||
handlerClickCopy(event) {
|
||||
const wrapper = event.target.closest('.code-block-wrapper')
|
||||
if (wrapper) {
|
||||
// 查找里面的 code 元素
|
||||
const codeElement = wrapper.querySelector('code.code-block-body')
|
||||
if (codeElement) {
|
||||
const codeText = codeElement.textContent
|
||||
copy(codeText)
|
||||
}
|
||||
}
|
||||
},
|
||||
handlerClickInsert(event) {
|
||||
const wrapper = event.target.closest('.code-block-wrapper')
|
||||
if (wrapper) {
|
||||
// 查找里面的 code 元素
|
||||
const codeElement = wrapper.querySelector('code.code-block-body')
|
||||
if (codeElement) {
|
||||
const codeText = codeElement.textContent
|
||||
console.log('insert code', codeText)
|
||||
this.$emit('insert-code', codeText)
|
||||
}
|
||||
}
|
||||
},
|
||||
addBtnClickEvents(selector, callback) {
|
||||
const buttons = this.$refs.textRef.querySelectorAll(selector)
|
||||
buttons.forEach((btn) => {
|
||||
btn.addEventListener('click', callback)
|
||||
})
|
||||
},
|
||||
removeBtnClickEvent(selector) {
|
||||
const buttons = this.$refs.textRef.querySelectorAll(selector)
|
||||
buttons.forEach((btn) => {
|
||||
btn.removeEventListener('click', () => {
|
||||
})
|
||||
})
|
||||
},
|
||||
removeCopyEvents() {
|
||||
if (this.$refs.textRef) {
|
||||
const copyBtn = this.$refs.textRef.querySelectorAll('.code-block-header__copy')
|
||||
copyBtn.forEach((btn) => {
|
||||
btn.removeEventListener('click', () => {
|
||||
})
|
||||
})
|
||||
this.removeBtnClickEvent('.code-block-header__copy')
|
||||
this.addBtnClickEvents('.code-block-header__insert')
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -115,26 +150,46 @@ export default {
|
||||
|
||||
&::v-deep .code-block-wrapper {
|
||||
background: #1F2329;
|
||||
padding: 2px 6px;
|
||||
padding: 0;
|
||||
margin: 5px 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow: hidden;
|
||||
|
||||
.code-block-body {
|
||||
padding: 5px 10px 0;
|
||||
padding: 5px 10px;
|
||||
}
|
||||
;
|
||||
|
||||
.code-block-header {
|
||||
margin-bottom: 4px;
|
||||
overflow: hidden;
|
||||
background: #353946;
|
||||
color: #c2d1e1;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 4px 8px;
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
|
||||
.code-block-header__copy {
|
||||
float: right;
|
||||
cursor: pointer;
|
||||
.code-block-header__actions {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
|
||||
&:hover {
|
||||
color: #6e747b;
|
||||
.code-block-header__copy {
|
||||
cursor: pointer;
|
||||
|
||||
&:hover {
|
||||
color: #6e747b;
|
||||
}
|
||||
}
|
||||
|
||||
.code-block-header__insert {
|
||||
cursor: pointer;
|
||||
|
||||
&:hover {
|
||||
color: #6e747b;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -178,6 +233,7 @@ export default {
|
||||
0% {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
100% {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<ChatMessage v-for="(item, index) in activeChat.chats" :key="index" :item="item" />
|
||||
<ChatMessage v-for="(item, index) in activeChat.chats" :key="index" :item="item" @insert-code="insertCode" />
|
||||
</div>
|
||||
<div class="input-box">
|
||||
<el-button
|
||||
@@ -60,6 +60,10 @@ export default {
|
||||
expanded: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
terminalContent: {
|
||||
type: Object,
|
||||
default: null
|
||||
}
|
||||
},
|
||||
data() {
|
||||
@@ -68,7 +72,8 @@ export default {
|
||||
prompt: '',
|
||||
conversationId: '',
|
||||
showIntroduction: false,
|
||||
introduction: []
|
||||
introduction: [],
|
||||
terminalContext: this.terminalContent || null
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
@@ -204,7 +209,11 @@ export default {
|
||||
sendIntroduction(item) {
|
||||
this.showIntroduction = false
|
||||
this.onSendHandle(item.content)
|
||||
},
|
||||
insertCode(code) {
|
||||
console.log(' receive insertCode', code)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -76,7 +76,8 @@ export default {
|
||||
robotUrl: require('@/assets/img/robot-assistant.png'),
|
||||
height: '400px',
|
||||
expanded: false,
|
||||
clientOffset: {}
|
||||
clientOffset: {},
|
||||
currentTerminalContent: {}
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
@@ -89,6 +90,15 @@ export default {
|
||||
window.addEventListener('message', (event) => {
|
||||
if (event.data === 'show-chat-panel') {
|
||||
this.$refs.drawer.show = true
|
||||
return
|
||||
}
|
||||
const msg = event.data
|
||||
switch (msg.name) {
|
||||
case 'current_terminal_content':
|
||||
// {content: '...', terminalId: '',sessionId: '',viewId: '',viewName: ''}
|
||||
this.$log.debug('current_terminal_content', msg)
|
||||
this.currentTerminalContent = msg.data
|
||||
break
|
||||
}
|
||||
})
|
||||
},
|
||||
@@ -96,6 +106,11 @@ export default {
|
||||
this.$refs.drawer.handleHeaderMoveDown(event)
|
||||
},
|
||||
handleMouseMoveUp(event) {
|
||||
// Prevent the new chat button from triggering the header move up
|
||||
const newButton = event.target.closest('.new')
|
||||
if (newButton) {
|
||||
return
|
||||
}
|
||||
this.$refs.drawer.handleHeaderMoveUp(event)
|
||||
},
|
||||
initWebSocket() {
|
||||
|
||||
@@ -42,11 +42,12 @@ export default {
|
||||
hasCreate: true,
|
||||
hasSearch: true,
|
||||
hasRefresh: true,
|
||||
hasBulkDelete: false,
|
||||
hasBulkDelete: true,
|
||||
hasBulkUpdate: false,
|
||||
hasLeftActions: true,
|
||||
hasRightActions: true,
|
||||
canCreate: this.$hasPerm('settings.change_security')
|
||||
canCreate: this.$hasPerm('settings.change_security'),
|
||||
canBulkDelete: this.$hasPerm('settings.change_security')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,13 +21,16 @@ export class TableColumnsGenerator {
|
||||
}
|
||||
|
||||
dynamicActionWidth() {
|
||||
if (i18n.locale === 'en') {
|
||||
console.log(i18n.locale)
|
||||
if (i18n.locale === 'zh-hans' || i18n.locale === 'zh-hant') {
|
||||
return '100px'
|
||||
}
|
||||
|
||||
if (i18n.locale === 'ja' || i18n.locale === 'ko') {
|
||||
return '120px'
|
||||
}
|
||||
if (i18n.locale === 'pt-br') {
|
||||
return '160px'
|
||||
}
|
||||
return '100px'
|
||||
|
||||
return '160px'
|
||||
}
|
||||
|
||||
generateColumns() {
|
||||
|
||||
@@ -178,7 +178,18 @@ export default {
|
||||
return
|
||||
}
|
||||
if (currentNode) {
|
||||
currentNode.name = currentNode.meta.data.value
|
||||
// 从节点名称中提取资产数量并保存
|
||||
const nameMatch = currentNode.name.match(/^(.+?)\s*\((\d+)\)$/)
|
||||
|
||||
if (nameMatch) {
|
||||
const pureName = nameMatch[1]
|
||||
const assetsAmount = parseInt(nameMatch[2])
|
||||
|
||||
currentNode.name = pureName
|
||||
currentNode.meta.data['assetsAmount'] = assetsAmount // 保存资产数量,确保重命名时不会丢失
|
||||
} else {
|
||||
currentNode.name = currentNode.meta.data.value
|
||||
}
|
||||
}
|
||||
this.zTree.editName(currentNode)
|
||||
},
|
||||
@@ -237,13 +248,14 @@ export default {
|
||||
if (isCancel) {
|
||||
return
|
||||
}
|
||||
|
||||
const originalAssetsAmount = treeNode.meta.data['assetsAmount'] || 0
|
||||
|
||||
this.$axios.patch(url, { 'value': treeNode.name }).then(res => {
|
||||
let assetsAmount = treeNode.meta.data['assetsAmount']
|
||||
if (!assetsAmount) {
|
||||
assetsAmount = 0
|
||||
}
|
||||
treeNode.name = treeNode.name + ' (' + assetsAmount + ')'
|
||||
treeNode.meta.data = res
|
||||
treeNode.name = treeNode.name + ' (' + originalAssetsAmount + ')'
|
||||
treeNode.meta.data = Object.assign({}, treeNode.meta.data, res)
|
||||
treeNode.meta.data['assetsAmount'] = originalAssetsAmount
|
||||
|
||||
this.zTree.updateNode(treeNode)
|
||||
this.$message.success(this.$tc('UpdateSuccessMsg'))
|
||||
}).finally(() => {
|
||||
|
||||
@@ -62,7 +62,7 @@ const actions = {
|
||||
link.href = faviconURL
|
||||
}
|
||||
// 动态修改Title
|
||||
document.title = data['INTERFACE']['login_title']
|
||||
document.title = data?.INTERFACE?.login_title || ''
|
||||
}
|
||||
const themeColors = data?.INTERFACE?.theme_info?.colors || {}
|
||||
commit('SET_PUBLIC_SETTINGS', data)
|
||||
|
||||
192
src/views/accounts/AccountChangeSecret/AccountList.vue
Normal file
192
src/views/accounts/AccountChangeSecret/AccountList.vue
Normal file
@@ -0,0 +1,192 @@
|
||||
<template>
|
||||
<div>
|
||||
<GenericListTable ref="ListTable" :header-actions="headerActions" :table-config="tableConfig" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { GenericListTable } from '@/layout/components'
|
||||
import { ActionsFormatter, DetailFormatter } from '@/components/Table/TableFormatters'
|
||||
|
||||
export default {
|
||||
name: 'AccountChangeSecret',
|
||||
components: {
|
||||
GenericListTable
|
||||
},
|
||||
data() {
|
||||
const vm = this
|
||||
return {
|
||||
secretUrl: '',
|
||||
showViewSecretDialog: false,
|
||||
tableConfig: {
|
||||
url: '/api/v1/accounts/change-secret-status/',
|
||||
columns: [
|
||||
'execution_id', 'asset', 'account', 'status', 'ttl', 'actions'
|
||||
],
|
||||
columnsMeta: {
|
||||
asset: {
|
||||
formatter: DetailFormatter,
|
||||
formatterArgs: {
|
||||
drawer: true,
|
||||
can: this.$hasPerm('assets.view_asset'),
|
||||
getTitle: ({ row }) => row.asset.name,
|
||||
getDrawerTitle: ({ row }) => row.asset.name,
|
||||
getRoute: ({ row }) => ({
|
||||
name: 'AssetDetail',
|
||||
params: { id: row.asset.id },
|
||||
query: { tab: 'Basic' }
|
||||
})
|
||||
}
|
||||
},
|
||||
account: {
|
||||
label: vm.$t('Username'),
|
||||
formatter: DetailFormatter,
|
||||
formatterArgs: {
|
||||
drawer: true,
|
||||
can: this.$hasPerm('accounts.view_account'),
|
||||
getTitle: ({ row }) => row.username,
|
||||
getDrawerTitle: ({ row }) => row.username,
|
||||
getRoute: ({ row }) => ({
|
||||
name: 'AssetAccountDetail',
|
||||
params: { id: row.id },
|
||||
query: { tab: 'Basic' }
|
||||
})
|
||||
}
|
||||
},
|
||||
ttl: {
|
||||
label: vm.$t('TTL')
|
||||
},
|
||||
execution_id: {
|
||||
width: '200px',
|
||||
label: vm.$t('ExecutionID'),
|
||||
formatter: DetailFormatter,
|
||||
formatterArgs: {
|
||||
drawer: true,
|
||||
can: true,
|
||||
getTitle: ({ row }) => row.meta?.execution_id ? row.meta.execution_id : '-',
|
||||
getDrawerTitle: ({ row }) => row.meta?.execution_id,
|
||||
getRoute: ({ row }) => ({
|
||||
name: 'AccountChangeSecretExecutionDetail',
|
||||
params: { id: row.meta?.execution_id }
|
||||
})
|
||||
}
|
||||
},
|
||||
status: {
|
||||
width: '100px',
|
||||
label: vm.$t('Status'),
|
||||
formatter: (row) => {
|
||||
const statusMap = {
|
||||
queued: 'Queued',
|
||||
ready: 'Ready',
|
||||
processing: 'Processing'
|
||||
}
|
||||
|
||||
if (statusMap[row.meta.status]) {
|
||||
return <span>{ vm.$t(statusMap[row.meta.status]) }</span>
|
||||
}
|
||||
return <span>–</span>
|
||||
}
|
||||
},
|
||||
actions: {
|
||||
formatter: ActionsFormatter,
|
||||
formatterArgs: {
|
||||
hasUpdate: false,
|
||||
hasDelete: false,
|
||||
hasClone: false,
|
||||
moreActionsTitle: this.$t('More'),
|
||||
extraActions: [
|
||||
{
|
||||
name: 'Delete',
|
||||
title: this.$t('Delete'),
|
||||
can: this.$hasPerm('accounts.add_changesecretexecution'),
|
||||
type: 'danger',
|
||||
callback: ({ row }) => {
|
||||
this.$axios.delete(
|
||||
'/api/v1/accounts/change-secret-status/',
|
||||
{
|
||||
data: {
|
||||
account_ids: [row.id]
|
||||
}
|
||||
}
|
||||
)
|
||||
vm.$refs.ListTable.reloadTable()
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
headerActions: {
|
||||
hasSearch: true,
|
||||
hasRefresh: true,
|
||||
hasLeftActions: true,
|
||||
hasRightActions: true,
|
||||
hasExport: false,
|
||||
hasImport: false,
|
||||
hasCreate: false,
|
||||
hasBulkDelete: false,
|
||||
hasBulkUpdate: false,
|
||||
searchConfig: {
|
||||
getUrlQuery: true,
|
||||
options: [
|
||||
{
|
||||
label: this.$t('AssetName'),
|
||||
value: 'asset_name'
|
||||
},
|
||||
{
|
||||
label: this.$t('ExecutionID'),
|
||||
value: 'execution_id'
|
||||
},
|
||||
{
|
||||
value: 'status',
|
||||
label: this.$t('Status'),
|
||||
type: 'choice',
|
||||
children: [
|
||||
{
|
||||
default: true,
|
||||
value: 'queued',
|
||||
label: this.$t('Queued')
|
||||
},
|
||||
{
|
||||
value: 'ready',
|
||||
label: this.$t('Ready')
|
||||
},
|
||||
{
|
||||
value: 'processing',
|
||||
label: this.$t('Processing')
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
extraMoreActions: [
|
||||
{
|
||||
name: 'DeleteSelected',
|
||||
title: this.$t('DeleteSelected'),
|
||||
type: 'primary',
|
||||
fa: 'fa-retweet',
|
||||
can: ({ selectedRows }) => {
|
||||
return selectedRows.length > 0
|
||||
},
|
||||
callback: function({ selectedRows }) {
|
||||
const ids = selectedRows.map(v => {
|
||||
return v.id
|
||||
})
|
||||
this.$axios.delete(
|
||||
'/api/v1/accounts/change-secret-status/',
|
||||
{
|
||||
data: {
|
||||
account_ids: ids
|
||||
}
|
||||
}
|
||||
)
|
||||
vm.$refs.ListTable.reloadTable()
|
||||
}.bind(this)
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -5,6 +5,7 @@
|
||||
<script>
|
||||
import { TabPage } from '@/layout/components'
|
||||
import { mapGetters } from 'vuex'
|
||||
import store from '@/store'
|
||||
|
||||
export default {
|
||||
name: 'Index',
|
||||
@@ -38,13 +39,22 @@ export default {
|
||||
name: 'ChangeSecretRecord',
|
||||
hidden: () => !this.$hasPerm('accounts.view_changesecretrecord'),
|
||||
component: () => import('@/views/accounts/AccountChangeSecret/ExecutionDetail/AccountChangeSecretRecord.vue')
|
||||
},
|
||||
{
|
||||
title: this.$t('ChangeSecretStatus'),
|
||||
name: 'ChangeSecretStatus',
|
||||
hidden: () => !this.$hasPerm('accounts.view_changesecretexecution') || !this.ChangeSecretAfterSessionEnd,
|
||||
component: () => import('@/views/accounts/AccountChangeSecret/AccountList.vue')
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapGetters(['hasValidLicense'])
|
||||
...mapGetters(['hasValidLicense']),
|
||||
ChangeSecretAfterSessionEnd() {
|
||||
return store.getters.publicSettings?.CHANGE_SECRET_AFTER_SESSION_END
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.$eventBus.$on('change-tab', this.handleChangeTab)
|
||||
|
||||
@@ -69,7 +69,35 @@ export default {
|
||||
updateSuccessNextRoute: { name: 'AccountTemplateList' }
|
||||
}
|
||||
},
|
||||
async mounted() {
|
||||
this.setSecretTypeOptions()
|
||||
},
|
||||
methods: {
|
||||
setSecretTypeOptions() {
|
||||
const choices = [
|
||||
{
|
||||
label: this.$t('Password'),
|
||||
value: 'password'
|
||||
},
|
||||
{
|
||||
label: this.$t('SSHKey'),
|
||||
value: 'ssh_key'
|
||||
},
|
||||
{
|
||||
label: this.$t('Token'),
|
||||
value: 'token'
|
||||
},
|
||||
{
|
||||
label: this.$t('AccessKey'),
|
||||
value: 'access_key'
|
||||
},
|
||||
{
|
||||
label: this.$t('ApiKey'),
|
||||
value: 'api_key'
|
||||
}
|
||||
]
|
||||
this.fieldsMeta.secret_type.options = choices
|
||||
},
|
||||
getObjectDone(obj) {
|
||||
if (['token', 'access_key', 'api_key'].includes(obj.secret_type.value)) {
|
||||
this.fieldsMeta.auto_push.el.disabled = true
|
||||
|
||||
@@ -163,6 +163,7 @@ export default {
|
||||
|
||||
::v-deep .el-drawer__body {
|
||||
padding: 0 20px;
|
||||
overflow-y: scroll;
|
||||
}
|
||||
|
||||
.platform-content {
|
||||
|
||||
@@ -28,19 +28,20 @@ export const fc = 'fc'
|
||||
export const scp = 'scp'
|
||||
export const apsara_stack = 'apsara_stack'
|
||||
export const lan = 'lan'
|
||||
export const smartx = 'smartx'
|
||||
|
||||
export const publicHostProviders = [
|
||||
aliyun, qcloud, qcloud_lighthouse, huaweicloud,
|
||||
baiducloud, jdcloud, kingsoftcloud, aws_china,
|
||||
aws_international, azure, azure_international,
|
||||
gcp, ucloud, volcengine
|
||||
gcp, ucloud, volcengine, smartx
|
||||
]
|
||||
|
||||
export const publicDBProviders = [aliyun]
|
||||
|
||||
export const privateCloudProviders = [
|
||||
vmware, qingcloud_private, huaweicloud_private, ctyun_private,
|
||||
openstack, zstack, nutanix, fc, scp, apsara_stack
|
||||
openstack, zstack, nutanix, fc, scp, apsara_stack, smartx
|
||||
]
|
||||
|
||||
export const ACCOUNT_PROVIDER_ATTRS_MAP = {
|
||||
@@ -164,6 +165,12 @@ export const ACCOUNT_PROVIDER_ATTRS_MAP = {
|
||||
attrs: ['access_key_id', 'access_key_secret', 'api_endpoint'],
|
||||
image: require('@/assets/img/cloud/zstack.svg')
|
||||
},
|
||||
[smartx]: {
|
||||
name: smartx,
|
||||
title: i18n.t('SmartX CloudTower'),
|
||||
attrs: ['username', 'password', 'api_endpoint'],
|
||||
image: require('@/assets/img/cloud/smartx.svg')
|
||||
},
|
||||
[fc]: {
|
||||
name: fc,
|
||||
title: i18n.t('FC'),
|
||||
|
||||
@@ -157,10 +157,6 @@ export default {
|
||||
assets: hosts,
|
||||
query: query
|
||||
}).then(data => {
|
||||
if (Array.isArray(data) && data.length === 0) {
|
||||
this.$message.info(`${this.$t('NoAccountFound')}`)
|
||||
return cb([])
|
||||
}
|
||||
const ns = data.map(item => {
|
||||
return { value: item.username }
|
||||
})
|
||||
|
||||
@@ -22,6 +22,19 @@ export default {
|
||||
component: BoolTextReadonly
|
||||
}
|
||||
}
|
||||
},
|
||||
basic: {
|
||||
fieldsMeta: {
|
||||
lang: {
|
||||
on: {
|
||||
change: ([value], updateForm) => {
|
||||
this.$axios.get(`/core/i18n/${value}/`).then(() => {
|
||||
window.location.reload()
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,7 +39,8 @@ export default {
|
||||
},
|
||||
columnsMeta: {
|
||||
type: Object,
|
||||
default: () => {}
|
||||
default: () => {
|
||||
}
|
||||
},
|
||||
columnsExclude: {
|
||||
type: Array,
|
||||
@@ -57,12 +58,15 @@ export default {
|
||||
id: {
|
||||
prop: 'id',
|
||||
label: this.$t('Number'),
|
||||
width: '80px',
|
||||
align: 'center',
|
||||
formatter: DetailFormatter,
|
||||
formatterArgs: {
|
||||
drawer: true,
|
||||
can: this.$hasPerm('assets.view_asset'),
|
||||
getTitle: ({ row, col, cellValue, index }) => { return index + 1 },
|
||||
getTitle: ({ row, col, cellValue, index }) => {
|
||||
return index + 1
|
||||
},
|
||||
getDrawerTitle: ({ row }) => {
|
||||
return row.id
|
||||
},
|
||||
@@ -78,7 +82,9 @@ export default {
|
||||
formatter: DetailFormatter,
|
||||
formatterArgs: {
|
||||
drawer: true,
|
||||
getTitle: ({ row }) => { return row.user },
|
||||
getTitle: ({ row }) => {
|
||||
return row.user
|
||||
},
|
||||
getRoute: ({ row }) => {
|
||||
return {
|
||||
name: 'UserDetail',
|
||||
|
||||
@@ -30,7 +30,8 @@ export default {
|
||||
this.$t('Basic'),
|
||||
[
|
||||
'SECURITY_PASSWORD_EXPIRATION_TIME',
|
||||
'OLD_PASSWORD_HISTORY_LIMIT_COUNT'
|
||||
'OLD_PASSWORD_HISTORY_LIMIT_COUNT',
|
||||
'SECURITY_EXPIRED_TOKEN_RECORD_KEEP_DAYS'
|
||||
]
|
||||
],
|
||||
[
|
||||
|
||||
@@ -58,7 +58,7 @@ export default {
|
||||
'SECURITY_WATERMARK_HEIGHT',
|
||||
'SECURITY_WATERMARK_WIDTH',
|
||||
'SECURITY_WATERMARK_ROTATE'
|
||||
] : []
|
||||
] : ['SECURITY_WATERMARK_ENABLED']
|
||||
]
|
||||
],
|
||||
fieldsMeta: {
|
||||
|
||||
@@ -43,7 +43,7 @@ export default {
|
||||
},
|
||||
{
|
||||
key: this.$t('LastPublishedTime'),
|
||||
value: this.object.last_published_time
|
||||
value: this.object.date_last_publish
|
||||
},
|
||||
{
|
||||
key: this.$t('Description'),
|
||||
|
||||
@@ -30,7 +30,7 @@ export default {
|
||||
'',
|
||||
[
|
||||
'mysql_port', 'mariadb_port', 'postgresql_port',
|
||||
'redis_port', 'sqlserver_port', 'oracle_port_range'
|
||||
'redis_port', 'sqlserver_port', 'oracle_port'
|
||||
]
|
||||
],
|
||||
[this.$t('Other'), ['is_active', 'comment']]
|
||||
@@ -39,7 +39,7 @@ export default {
|
||||
host: {
|
||||
disabled: this.$route.params.id === '00000000-0000-0000-0000-000000000001'
|
||||
},
|
||||
oracle_port_range: {
|
||||
oracle_port: {
|
||||
disabled: true
|
||||
},
|
||||
is_active: {
|
||||
|
||||
@@ -31,7 +31,7 @@ export default {
|
||||
'name', 'host', 'actions',
|
||||
'http_port', 'https_port', 'ssh_port', 'rdp_port', 'vnc_port',
|
||||
'mysql_port', 'mariadb_port', 'postgresql_port',
|
||||
'redis_port', 'sqlserver_port', 'oracle_port', 'is_active'
|
||||
'redis_port', 'sqlserver_port', 'oracle_port', 'mongodb_port', 'is_active'
|
||||
]
|
||||
},
|
||||
columnsMeta: {
|
||||
@@ -43,7 +43,8 @@ export default {
|
||||
canUpdate: this.$hasPerm('terminal.change_endpoint'),
|
||||
updateRoute: 'EndpointUpdate',
|
||||
cloneRoute: 'EndpointCreate',
|
||||
canDelete: ({ row }) => row.id !== '00000000-0000-0000-0000-000000000001' && this.$hasPerm('terminal.delete_endpoint')
|
||||
canDelete: ({ row }) => row.id !== '00000000-0000-0000-0000-000000000001' &&
|
||||
this.$hasPerm('terminal.delete_endpoint')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -134,7 +134,7 @@ export default {
|
||||
},
|
||||
onMonitor() {
|
||||
const joinUrl = `/luna/monitor/${this.session.id}?ticket_id=${this.object.id}`
|
||||
window.open(joinUrl, 'height=600, width=850, top=400, left=400, toolbar=no, menubar=no, scrollbars=no, location=no, status=no')
|
||||
window.open(joinUrl, '_blank', 'height=600, width=850, top=400, left=400, toolbar=no, menubar=no, scrollbars=no, location=no, status=no')
|
||||
},
|
||||
onToggleLock() {
|
||||
const url = '/api/v1/terminal/tasks/toggle-lock-session-for-ticket/'
|
||||
|
||||
Reference in New Issue
Block a user