mirror of
https://github.com/jumpserver/lina.git
synced 2025-08-17 22:37:18 +00:00
merge: with dev
This commit is contained in:
commit
c0d4ec7dba
@ -33,7 +33,7 @@
|
|||||||
"crypto-js": "^4.1.1",
|
"crypto-js": "^4.1.1",
|
||||||
"css-color-function": "^1.3.3",
|
"css-color-function": "^1.3.3",
|
||||||
"deepmerge": "^4.2.2",
|
"deepmerge": "^4.2.2",
|
||||||
"echarts": "^4.7.0",
|
"echarts": "4.7.0",
|
||||||
"element-ui": "2.13.2",
|
"element-ui": "2.13.2",
|
||||||
"eslint-plugin-html": "^6.0.0",
|
"eslint-plugin-html": "^6.0.0",
|
||||||
"highlight.js": "^11.9.0",
|
"highlight.js": "^11.9.0",
|
||||||
|
@ -27,6 +27,9 @@
|
|||||||
if(pathname.indexOf('/ui') === -1) {
|
if(pathname.indexOf('/ui') === -1) {
|
||||||
window.location.href = window.location.origin + '/ui/#' + pathname
|
window.location.href = window.location.origin + '/ui/#' + pathname
|
||||||
}
|
}
|
||||||
|
if (pathname.startsWith('/ui/#/chat')) {
|
||||||
|
window.location.href = window.location.origin + pathname
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
<div id="app"></div>
|
<div id="app"></div>
|
||||||
|
191
src/components/Apps/AccountCreateUpdateForm/const.js
Normal file
191
src/components/Apps/AccountCreateUpdateForm/const.js
Normal file
@ -0,0 +1,191 @@
|
|||||||
|
import { UpdateToken, UploadSecret } from '@/components/Form/FormFields'
|
||||||
|
import Select2 from '@/components/Form/FormFields/Select2.vue'
|
||||||
|
import AssetSelect from '@/components/Apps/AssetSelect/index.vue'
|
||||||
|
import { Required, RequiredChange } from '@/components/Form/DataForm/rules'
|
||||||
|
import AutomationParamsForm from '@/views/assets/Platform/AutomationParamsSetting.vue'
|
||||||
|
|
||||||
|
export const accountFieldsMeta = (vm) => {
|
||||||
|
const defaultPrivilegedAccounts = ['root', 'administrator']
|
||||||
|
return {
|
||||||
|
assets: {
|
||||||
|
rules: [Required],
|
||||||
|
component: AssetSelect,
|
||||||
|
label: vm.$t('assets.Asset'),
|
||||||
|
el: {
|
||||||
|
multiple: false
|
||||||
|
},
|
||||||
|
hidden: () => {
|
||||||
|
return vm.platform || vm.asset
|
||||||
|
}
|
||||||
|
},
|
||||||
|
template: {
|
||||||
|
component: Select2,
|
||||||
|
rules: [Required],
|
||||||
|
el: {
|
||||||
|
multiple: false,
|
||||||
|
ajax: {
|
||||||
|
url: '/api/v1/accounts/account-templates/',
|
||||||
|
transformOption: (item) => {
|
||||||
|
return { label: item.name, value: item.id }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
hidden: () => {
|
||||||
|
return vm.platform || vm.asset || !vm.addTemplate
|
||||||
|
}
|
||||||
|
},
|
||||||
|
on_invalid: {
|
||||||
|
rules: [Required],
|
||||||
|
label: vm.$t('accounts.AccountPolicy'),
|
||||||
|
helpText: vm.$t('accounts.BulkCreateStrategy'),
|
||||||
|
hidden: () => {
|
||||||
|
return vm.platform || vm.asset
|
||||||
|
}
|
||||||
|
},
|
||||||
|
name: {
|
||||||
|
label: vm.$t('common.Name'),
|
||||||
|
rules: [RequiredChange],
|
||||||
|
on: {
|
||||||
|
input: ([value], updateForm) => {
|
||||||
|
if (!vm.usernameChanged) {
|
||||||
|
if (!vm.account?.name) {
|
||||||
|
updateForm({ username: value })
|
||||||
|
}
|
||||||
|
const maybePrivileged = defaultPrivilegedAccounts.includes(value)
|
||||||
|
if (maybePrivileged) {
|
||||||
|
updateForm({ privileged: true })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
hidden: () => {
|
||||||
|
return vm.addTemplate
|
||||||
|
}
|
||||||
|
},
|
||||||
|
username: {
|
||||||
|
el: {
|
||||||
|
disabled: !!vm.account?.name
|
||||||
|
},
|
||||||
|
on: {
|
||||||
|
input: ([value], updateForm) => {
|
||||||
|
vm.usernameChanged = true
|
||||||
|
},
|
||||||
|
change: ([value], updateForm) => {
|
||||||
|
const maybePrivileged = defaultPrivilegedAccounts.includes(value)
|
||||||
|
if (maybePrivileged) {
|
||||||
|
updateForm({ privileged: true })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
hidden: () => {
|
||||||
|
return vm.addTemplate
|
||||||
|
}
|
||||||
|
},
|
||||||
|
privileged: {
|
||||||
|
label: vm.$t('assets.Privileged'),
|
||||||
|
hidden: () => {
|
||||||
|
return vm.addTemplate
|
||||||
|
}
|
||||||
|
},
|
||||||
|
su_from: {
|
||||||
|
component: Select2,
|
||||||
|
hidden: (formValue) => {
|
||||||
|
return !vm.asset?.id || !vm.iPlatform.su_enabled
|
||||||
|
},
|
||||||
|
el: {
|
||||||
|
multiple: false,
|
||||||
|
clearable: true,
|
||||||
|
ajax: {
|
||||||
|
url: `/api/v1/accounts/accounts/su-from-accounts/?account=${vm.account?.id || ''}&asset=${vm.asset?.id || ''}`,
|
||||||
|
transformOption: (item) => {
|
||||||
|
return { label: `${item.name}(${item.username})`, value: item.id }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
su_from_username: {
|
||||||
|
label: vm.$t('assets.UserSwitchFrom'),
|
||||||
|
hidden: (formValue) => {
|
||||||
|
return vm.platform || vm.asset || vm.addTemplate
|
||||||
|
}
|
||||||
|
},
|
||||||
|
password: {
|
||||||
|
label: vm.$t('assets.Password'),
|
||||||
|
component: UpdateToken,
|
||||||
|
hidden: (formValue) => {
|
||||||
|
console.log('formValue: ', formValue)
|
||||||
|
return formValue.secret_type !== 'password' || vm.addTemplate
|
||||||
|
}
|
||||||
|
},
|
||||||
|
ssh_key: {
|
||||||
|
label: vm.$t('assets.PrivateKey'),
|
||||||
|
component: UploadSecret,
|
||||||
|
hidden: (formValue) => formValue.secret_type !== 'ssh_key' || vm.addTemplate
|
||||||
|
},
|
||||||
|
passphrase: {
|
||||||
|
label: vm.$t('assets.Passphrase'),
|
||||||
|
component: UpdateToken,
|
||||||
|
hidden: (formValue) => formValue.secret_type !== 'ssh_key' || vm.addTemplate
|
||||||
|
},
|
||||||
|
token: {
|
||||||
|
label: vm.$t('assets.Token'),
|
||||||
|
component: UploadSecret,
|
||||||
|
hidden: (formValue) => formValue.secret_type !== 'token' || vm.addTemplate
|
||||||
|
},
|
||||||
|
access_key: {
|
||||||
|
id: 'access_key',
|
||||||
|
label: vm.$t('assets.AccessKey'),
|
||||||
|
component: UploadSecret,
|
||||||
|
hidden: (formValue) => formValue.secret_type !== 'access_key' || vm.addTemplate
|
||||||
|
},
|
||||||
|
api_key: {
|
||||||
|
id: 'api_key',
|
||||||
|
label: vm.$t('assets.ApiKey'),
|
||||||
|
component: UploadSecret,
|
||||||
|
hidden: (formValue) => formValue.secret_type !== 'api_key' || vm.addTemplate
|
||||||
|
},
|
||||||
|
secret_type: {
|
||||||
|
type: 'radio-group',
|
||||||
|
options: [],
|
||||||
|
hidden: () => {
|
||||||
|
return vm.addTemplate
|
||||||
|
}
|
||||||
|
},
|
||||||
|
push_now: {
|
||||||
|
helpText: vm.$t('accounts.AccountPush.WindowsPushHelpText'),
|
||||||
|
hidden: (formValue) => {
|
||||||
|
const automation = vm.iPlatform.automation || {}
|
||||||
|
return !automation.push_account_enabled ||
|
||||||
|
!automation.ansible_enabled ||
|
||||||
|
!vm.$hasPerm('accounts.push_account') ||
|
||||||
|
(formValue.secret_type === 'ssh_key' && vm.iPlatform.type.value === 'windows') ||
|
||||||
|
vm.addTemplate
|
||||||
|
}
|
||||||
|
},
|
||||||
|
params: {
|
||||||
|
label: vm.$t('assets.PushParams'),
|
||||||
|
component: AutomationParamsForm,
|
||||||
|
el: {
|
||||||
|
method: vm.asset?.auto_config?.push_account_method
|
||||||
|
},
|
||||||
|
hidden: (formValue) => {
|
||||||
|
const automation = vm.iPlatform.automation || {}
|
||||||
|
return !formValue.push_now ||
|
||||||
|
!automation.push_account_enabled ||
|
||||||
|
!automation.ansible_enabled ||
|
||||||
|
(formValue.secret_type === 'ssh_key' && vm.iPlatform.type.value === 'windows') ||
|
||||||
|
!vm.$hasPerm('accounts.push_account') ||
|
||||||
|
vm.addTemplate
|
||||||
|
}
|
||||||
|
},
|
||||||
|
is_active: {
|
||||||
|
label: vm.$t('common.IsActive')
|
||||||
|
},
|
||||||
|
comment: {
|
||||||
|
label: vm.$t('common.Comment'),
|
||||||
|
hidden: () => {
|
||||||
|
return vm.addTemplate
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -9,12 +9,8 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
import AutoDataForm from '@/components/Form/AutoDataForm/index.vue'
|
import AutoDataForm from '@/components/Form/AutoDataForm/index.vue'
|
||||||
import { UpdateToken, UploadSecret } from '@/components/Form/FormFields'
|
|
||||||
import Select2 from '@/components/Form/FormFields/Select2.vue'
|
|
||||||
import AssetSelect from '@/components/Apps/AssetSelect/index.vue'
|
|
||||||
import { encryptPassword } from '@/utils/crypto'
|
import { encryptPassword } from '@/utils/crypto'
|
||||||
import { Required, RequiredChange } from '@/components/Form/DataForm/rules'
|
import { accountFieldsMeta } from '@/components/Apps/AccountCreateUpdateForm/const'
|
||||||
import AutomationParamsForm from '@/views/assets/Platform/AutomationParamsSetting.vue'
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'AccountCreateForm',
|
name: 'AccountCreateForm',
|
||||||
@ -48,7 +44,6 @@ export default {
|
|||||||
return {
|
return {
|
||||||
loading: true,
|
loading: true,
|
||||||
usernameChanged: false,
|
usernameChanged: false,
|
||||||
defaultPrivilegedAccounts: ['root', 'administrator'],
|
|
||||||
iPlatform: {
|
iPlatform: {
|
||||||
automation: {},
|
automation: {},
|
||||||
su_enabled: false,
|
su_enabled: false,
|
||||||
@ -72,179 +67,7 @@ export default {
|
|||||||
]],
|
]],
|
||||||
[this.$t('Other'), ['push_now', 'params', 'on_invalid', 'is_active', 'comment']]
|
[this.$t('Other'), ['push_now', 'params', 'on_invalid', 'is_active', 'comment']]
|
||||||
],
|
],
|
||||||
fieldsMeta: {
|
fieldsMeta: accountFieldsMeta(this),
|
||||||
assets: {
|
|
||||||
rules: [Required],
|
|
||||||
component: AssetSelect,
|
|
||||||
label: this.$t('Asset'),
|
|
||||||
el: {
|
|
||||||
multiple: false
|
|
||||||
},
|
|
||||||
hidden: () => {
|
|
||||||
return this.platform || this.asset
|
|
||||||
}
|
|
||||||
},
|
|
||||||
template: {
|
|
||||||
component: Select2,
|
|
||||||
rules: [Required],
|
|
||||||
el: {
|
|
||||||
multiple: false,
|
|
||||||
ajax: {
|
|
||||||
url: '/api/v1/accounts/account-templates/',
|
|
||||||
transformOption: (item) => {
|
|
||||||
return { label: item.name, value: item.id }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
hidden: () => {
|
|
||||||
return this.platform || this.asset || !this.addTemplate
|
|
||||||
}
|
|
||||||
},
|
|
||||||
on_invalid: {
|
|
||||||
rules: [Required],
|
|
||||||
label: this.$t('AccountPolicy'),
|
|
||||||
helpText: this.$t('BulkCreateStrategy'),
|
|
||||||
hidden: () => {
|
|
||||||
return this.platform || this.asset
|
|
||||||
}
|
|
||||||
},
|
|
||||||
name: {
|
|
||||||
rules: [RequiredChange],
|
|
||||||
on: {
|
|
||||||
input: ([value], updateForm) => {
|
|
||||||
if (!this.usernameChanged) {
|
|
||||||
if (!this.account?.name) {
|
|
||||||
updateForm({ username: value })
|
|
||||||
}
|
|
||||||
const maybePrivileged = this.defaultPrivilegedAccounts.includes(value)
|
|
||||||
if (maybePrivileged) {
|
|
||||||
updateForm({ privileged: true })
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
hidden: () => {
|
|
||||||
return this.addTemplate
|
|
||||||
}
|
|
||||||
},
|
|
||||||
username: {
|
|
||||||
el: {
|
|
||||||
disabled: !!this.account?.name
|
|
||||||
},
|
|
||||||
on: {
|
|
||||||
input: ([value], updateForm) => {
|
|
||||||
this.usernameChanged = true
|
|
||||||
},
|
|
||||||
change: ([value], updateForm) => {
|
|
||||||
const maybePrivileged = this.defaultPrivilegedAccounts.includes(value)
|
|
||||||
if (maybePrivileged) {
|
|
||||||
updateForm({ privileged: true })
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
hidden: () => {
|
|
||||||
return this.addTemplate
|
|
||||||
}
|
|
||||||
},
|
|
||||||
privileged: {
|
|
||||||
hidden: () => {
|
|
||||||
return this.addTemplate
|
|
||||||
}
|
|
||||||
},
|
|
||||||
su_from: {
|
|
||||||
component: Select2,
|
|
||||||
hidden: (formValue) => {
|
|
||||||
return !this.asset?.id || !this.iPlatform.su_enabled
|
|
||||||
},
|
|
||||||
el: {
|
|
||||||
multiple: false,
|
|
||||||
clearable: true,
|
|
||||||
ajax: {
|
|
||||||
url: `/api/v1/accounts/accounts/su-from-accounts/?account=${this.account?.id || ''}&asset=${this.asset?.id || ''}`,
|
|
||||||
transformOption: (item) => {
|
|
||||||
return { label: `${item.name}(${item.username})`, value: item.id }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
su_from_username: {
|
|
||||||
label: this.$t('SwitchFrom'),
|
|
||||||
hidden: (formValue) => {
|
|
||||||
return this.platform || this.asset || this.addTemplate
|
|
||||||
}
|
|
||||||
},
|
|
||||||
password: {
|
|
||||||
label: this.$t('Password'),
|
|
||||||
component: UpdateToken,
|
|
||||||
hidden: (formValue) => formValue.secret_type !== 'password' || this.addTemplate
|
|
||||||
},
|
|
||||||
ssh_key: {
|
|
||||||
label: this.$t('PrivateKey'),
|
|
||||||
component: UploadSecret,
|
|
||||||
hidden: (formValue) => formValue.secret_type !== 'ssh_key' || this.addTemplate
|
|
||||||
},
|
|
||||||
passphrase: {
|
|
||||||
label: this.$t('Passphrase'),
|
|
||||||
component: UpdateToken,
|
|
||||||
hidden: (formValue) => formValue.secret_type !== 'ssh_key' || this.addTemplate
|
|
||||||
},
|
|
||||||
token: {
|
|
||||||
label: this.$t('Token'),
|
|
||||||
component: UploadSecret,
|
|
||||||
hidden: (formValue) => formValue.secret_type !== 'token' || this.addTemplate
|
|
||||||
},
|
|
||||||
access_key: {
|
|
||||||
id: 'access_key',
|
|
||||||
label: this.$t('AccessKey'),
|
|
||||||
component: UploadSecret,
|
|
||||||
hidden: (formValue) => formValue.secret_type !== 'access_key' || this.addTemplate
|
|
||||||
},
|
|
||||||
api_key: {
|
|
||||||
id: 'api_key',
|
|
||||||
label: this.$t('ApiKey'),
|
|
||||||
component: UploadSecret,
|
|
||||||
hidden: (formValue) => formValue.secret_type !== 'api_key' || this.addTemplate
|
|
||||||
},
|
|
||||||
secret_type: {
|
|
||||||
type: 'radio-group',
|
|
||||||
options: [],
|
|
||||||
hidden: () => {
|
|
||||||
return this.addTemplate
|
|
||||||
}
|
|
||||||
},
|
|
||||||
push_now: {
|
|
||||||
helpText: this.$t('WindowsPushHelpText'),
|
|
||||||
hidden: (formValue) => {
|
|
||||||
const automation = this.iPlatform.automation || {}
|
|
||||||
return !automation.push_account_enabled ||
|
|
||||||
!automation.ansible_enabled ||
|
|
||||||
!this.$hasPerm('accounts.push_account') ||
|
|
||||||
(formValue.secret_type === 'ssh_key' && this.iPlatform.type.value === 'windows') ||
|
|
||||||
this.addTemplate
|
|
||||||
}
|
|
||||||
},
|
|
||||||
params: {
|
|
||||||
label: this.$t('PushParams'),
|
|
||||||
component: AutomationParamsForm,
|
|
||||||
el: {
|
|
||||||
method: this.asset?.auto_config?.push_account_method
|
|
||||||
},
|
|
||||||
hidden: (formValue) => {
|
|
||||||
const automation = this.iPlatform.automation || {}
|
|
||||||
return !formValue.push_now ||
|
|
||||||
!automation.push_account_enabled ||
|
|
||||||
!automation.ansible_enabled ||
|
|
||||||
(formValue.secret_type === 'ssh_key' && this.iPlatform.type.value === 'windows') ||
|
|
||||||
!this.$hasPerm('accounts.push_account') ||
|
|
||||||
this.addTemplate
|
|
||||||
}
|
|
||||||
},
|
|
||||||
comment: {
|
|
||||||
hidden: () => {
|
|
||||||
return this.addTemplate
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
hasSaveContinue: false
|
hasSaveContinue: false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -0,0 +1,87 @@
|
|||||||
|
<template>
|
||||||
|
<GenericUpdateFormDialog
|
||||||
|
v-if="visible"
|
||||||
|
:form-setting="formSetting"
|
||||||
|
:selected-rows="selectedRows"
|
||||||
|
:visible="visible"
|
||||||
|
v-on="$listeners"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { GenericUpdateFormDialog } from '@/layout/components'
|
||||||
|
import { accountFieldsMeta } from '@/components/Apps/AccountCreateUpdateForm/const'
|
||||||
|
import { encryptPassword } from '@/utils/crypto'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'AccountBulkUpdateDialog',
|
||||||
|
components: {
|
||||||
|
GenericUpdateFormDialog
|
||||||
|
},
|
||||||
|
props: {
|
||||||
|
visible: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
},
|
||||||
|
selectedRows: {
|
||||||
|
type: Array,
|
||||||
|
default: () => ([])
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
formSetting: {
|
||||||
|
url: '/api/v1/accounts/accounts/',
|
||||||
|
hasSaveContinue: false,
|
||||||
|
fields: [],
|
||||||
|
fieldsMeta: accountFieldsMeta(this),
|
||||||
|
cleanOtherFormValue: (formValue) => {
|
||||||
|
for (const value of formValue) {
|
||||||
|
Object.keys(value).forEach((item, index, arr) => {
|
||||||
|
if (['ssh_key', 'token', 'access_key', 'api_key', 'password'].includes(item)) {
|
||||||
|
value['secret'] = encryptPassword(value[item])
|
||||||
|
delete value[item]
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return formValue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
this.filterFieldsMeta()
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
filterFieldsMeta() {
|
||||||
|
let fields = ['privileged']
|
||||||
|
const fieldsMeta = {}
|
||||||
|
const secretFields = ['password', 'ssh_key', 'passphrase', 'token', 'access_key', 'api_key']
|
||||||
|
const secret_type = this.selectedRows[0].secret_type?.value || 'password'
|
||||||
|
for (const field of secretFields) {
|
||||||
|
if (secret_type === 'ssh_key' && field === 'passphrase') {
|
||||||
|
fields.push('passphrase')
|
||||||
|
this.formSetting.fieldsMeta['passphrase'].hidden = () => false
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if (secret_type === field) {
|
||||||
|
fields.push(field)
|
||||||
|
this.formSetting.fieldsMeta[field].hidden = () => false
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
delete this.formSetting.fieldsMeta[field]
|
||||||
|
}
|
||||||
|
fields = fields.concat(['is_active', 'comment'])
|
||||||
|
for (const field of fields) {
|
||||||
|
fieldsMeta[field] = this.formSetting.fieldsMeta[field]
|
||||||
|
}
|
||||||
|
this.formSetting.fields = fields
|
||||||
|
this.formSetting.fieldsMeta = fieldsMeta
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
|
||||||
|
</style>
|
@ -37,6 +37,12 @@
|
|||||||
:result="createAccountResults"
|
:result="createAccountResults"
|
||||||
:visible.sync="showResultDialog"
|
:visible.sync="showResultDialog"
|
||||||
/>
|
/>
|
||||||
|
<AccountBulkUpdateDialog
|
||||||
|
v-if="updateSelectedDialogSetting.visible"
|
||||||
|
:visible.sync="updateSelectedDialogSetting.visible"
|
||||||
|
v-bind="updateSelectedDialogSetting"
|
||||||
|
@update="handleAccountBulkUpdate"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@ -49,10 +55,12 @@ import AccountCreateUpdate from './AccountCreateUpdate.vue'
|
|||||||
import { connectivityMeta } from './const'
|
import { connectivityMeta } from './const'
|
||||||
import { openTaskPage } from '@/utils/jms'
|
import { openTaskPage } from '@/utils/jms'
|
||||||
import ResultDialog from './BulkCreateResultDialog.vue'
|
import ResultDialog from './BulkCreateResultDialog.vue'
|
||||||
|
import AccountBulkUpdateDialog from '@/components/Apps/AccountListTable/AccountBulkUpdateDialog.vue'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'AccountListTable',
|
name: 'AccountListTable',
|
||||||
components: {
|
components: {
|
||||||
|
AccountBulkUpdateDialog,
|
||||||
ResultDialog,
|
ResultDialog,
|
||||||
ListTable,
|
ListTable,
|
||||||
UpdateSecretInfo,
|
UpdateSecretInfo,
|
||||||
@ -116,6 +124,10 @@ export default {
|
|||||||
headerExtraActions: {
|
headerExtraActions: {
|
||||||
type: Array,
|
type: Array,
|
||||||
default: () => []
|
default: () => []
|
||||||
|
},
|
||||||
|
extraQuery: {
|
||||||
|
type: Object,
|
||||||
|
default: () => ({})
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
@ -137,9 +149,7 @@ export default {
|
|||||||
app: 'assets',
|
app: 'assets',
|
||||||
resource: 'account'
|
resource: 'account'
|
||||||
},
|
},
|
||||||
extraQuery: {
|
extraQuery: this.extraQuery,
|
||||||
order: '-date_updated'
|
|
||||||
},
|
|
||||||
columnsExclude: ['spec_info'],
|
columnsExclude: ['spec_info'],
|
||||||
columnsShow: {
|
columnsShow: {
|
||||||
min: ['name', 'username', 'actions'],
|
min: ['name', 'username', 'actions'],
|
||||||
@ -336,6 +346,25 @@ export default {
|
|||||||
...this.headerExtraActions
|
...this.headerExtraActions
|
||||||
],
|
],
|
||||||
extraMoreActions: [
|
extraMoreActions: [
|
||||||
|
{
|
||||||
|
name: 'BulkVerify',
|
||||||
|
title: this.$t('accounts.BulkVerify'),
|
||||||
|
type: 'primary',
|
||||||
|
fa: 'fa-handshake-o',
|
||||||
|
can: ({ selectedRows }) => {
|
||||||
|
return selectedRows.length > 0
|
||||||
|
},
|
||||||
|
callback: function({ selectedRows }) {
|
||||||
|
const ids = selectedRows.map(v => { return v.id })
|
||||||
|
this.$axios.post(
|
||||||
|
'/api/v1/accounts/accounts/tasks/',
|
||||||
|
{ action: 'verify', accounts: ids }).then(res => {
|
||||||
|
openTaskPage(res['task'])
|
||||||
|
}).catch(err => {
|
||||||
|
this.$message.error(this.$tc('common.bulkVerifyErrorMsg' + ' ' + err))
|
||||||
|
})
|
||||||
|
}.bind(this)
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: 'ClearSecrets',
|
name: 'ClearSecrets',
|
||||||
title: this.$t('ClearSecret'),
|
title: this.$t('ClearSecret'),
|
||||||
@ -354,6 +383,21 @@ export default {
|
|||||||
this.$message.error(this.$tc('BulkClearErrorMsg' + ' ' + err))
|
this.$message.error(this.$tc('BulkClearErrorMsg' + ' ' + err))
|
||||||
})
|
})
|
||||||
}.bind(this)
|
}.bind(this)
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'actionUpdateSelected',
|
||||||
|
title: this.$t('accounts.AccountBatchUpdate'),
|
||||||
|
fa: 'batch-update',
|
||||||
|
can: ({ selectedRows }) => {
|
||||||
|
return selectedRows.length > 0 &&
|
||||||
|
!this.$store.getters.currentOrgIsRoot &&
|
||||||
|
vm.$hasPerm('accounts.change_account') &&
|
||||||
|
selectedRows.every(i => i.secret_type.value === selectedRows[0].secret_type.value)
|
||||||
|
},
|
||||||
|
callback: ({ selectedRows }) => {
|
||||||
|
vm.updateSelectedDialogSetting.selectedRows = selectedRows
|
||||||
|
vm.updateSelectedDialogSetting.visible = true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
canBulkDelete: vm.$hasPerm('accounts.delete_account'),
|
canBulkDelete: vm.$hasPerm('accounts.delete_account'),
|
||||||
@ -362,6 +406,10 @@ export default {
|
|||||||
exclude: ['asset']
|
exclude: ['asset']
|
||||||
},
|
},
|
||||||
hasSearch: true
|
hasSearch: true
|
||||||
|
},
|
||||||
|
updateSelectedDialogSetting: {
|
||||||
|
visible: false,
|
||||||
|
selectedRows: []
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -429,6 +477,10 @@ export default {
|
|||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
this.showResultDialog = true
|
this.showResultDialog = true
|
||||||
}, 100)
|
}, 100)
|
||||||
|
},
|
||||||
|
handleAccountBulkUpdate() {
|
||||||
|
this.updateSelectedDialogSetting.visible = false
|
||||||
|
this.$refs.ListTable.reloadTable()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<Dialog
|
<Dialog
|
||||||
|
:close-on-click-modal="false"
|
||||||
:title="$tc('Assets')"
|
:title="$tc('Assets')"
|
||||||
custom-class="asset-select-dialog"
|
custom-class="asset-select-dialog"
|
||||||
top="2vh"
|
top="2vh"
|
||||||
@ -109,6 +110,7 @@ export default {
|
|||||||
headerActions: {
|
headerActions: {
|
||||||
hasLeftActions: false,
|
hasLeftActions: false,
|
||||||
hasRightActions: false,
|
hasRightActions: false,
|
||||||
|
hasLabelSearch: true,
|
||||||
searchConfig: {
|
searchConfig: {
|
||||||
getUrlQuery: false
|
getUrlQuery: false
|
||||||
}
|
}
|
||||||
|
@ -60,6 +60,7 @@ export default {
|
|||||||
const showAssets = this.treeSetting?.showAssets || this.showAssets
|
const showAssets = this.treeSetting?.showAssets || this.showAssets
|
||||||
const treeUrlQuery = this.setTreeUrlQuery()
|
const treeUrlQuery = this.setTreeUrlQuery()
|
||||||
const assetTreeUrl = `${this.treeUrl}?assets=${showAssets ? '1' : '0'}&${treeUrlQuery}`
|
const assetTreeUrl = `${this.treeUrl}?assets=${showAssets ? '1' : '0'}&${treeUrlQuery}`
|
||||||
|
const vm = this
|
||||||
|
|
||||||
return {
|
return {
|
||||||
treeTabConfig: {
|
treeTabConfig: {
|
||||||
@ -81,7 +82,13 @@ export default {
|
|||||||
nodeUrl: this.nodeUrl,
|
nodeUrl: this.nodeUrl,
|
||||||
treeUrl: assetTreeUrl,
|
treeUrl: assetTreeUrl,
|
||||||
callback: {
|
callback: {
|
||||||
onSelected: (event, treeNode) => this.getAssetsUrl(treeNode)
|
onSelected: (event, treeNode) => this.getAssetsUrl(treeNode),
|
||||||
|
beforeRefresh: () => {
|
||||||
|
const query = { ...this.$route.query, node_id: '', asset_id: '' }
|
||||||
|
setTimeout(() => {
|
||||||
|
vm.$router.replace({ query: query })
|
||||||
|
}, 100)
|
||||||
|
}
|
||||||
},
|
},
|
||||||
...this.treeSetting
|
...this.treeSetting
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<div class="close-sidebar">
|
<div class="close-sidebar">
|
||||||
<i class="el-icon-close" @click="onClose" />
|
<i v-if="hasClose" class="el-icon-close" @click="onClose" />
|
||||||
</div>
|
</div>
|
||||||
<el-tabs v-model="active" :tab-position="'right'" @tab-click="handleClick">
|
<el-tabs v-model="active" :tab-position="'right'" @tab-click="handleClick">
|
||||||
<el-tab-pane v-for="(item) in submenu" :key="item.name" :name="item.name">
|
<el-tab-pane v-for="(item) in submenu" :key="item.name" :name="item.name">
|
||||||
@ -22,6 +22,10 @@ export default {
|
|||||||
type: String,
|
type: String,
|
||||||
default: 'chat'
|
default: 'chat'
|
||||||
},
|
},
|
||||||
|
hasClose: {
|
||||||
|
type: Boolean,
|
||||||
|
default: true
|
||||||
|
},
|
||||||
submenu: {
|
submenu: {
|
||||||
type: Array,
|
type: Array,
|
||||||
default: () => []
|
default: () => []
|
||||||
@ -48,9 +52,10 @@ export default {
|
|||||||
height: 100%;
|
height: 100%;
|
||||||
background-color: #f0f1f5;
|
background-color: #f0f1f5;
|
||||||
.close-sidebar {
|
.close-sidebar {
|
||||||
|
height: 48px;
|
||||||
|
padding: 12px 0;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
padding: 12px 0;
|
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
i {
|
i {
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
|
@ -18,7 +18,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="sidebar">
|
<div class="sidebar">
|
||||||
<Sidebar :active.sync="active" :submenu="submenu" />
|
<Sidebar v-bind="$attrs" :active.sync="active" :submenu="submenu" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@ -62,11 +62,14 @@ export default {
|
|||||||
watch: {
|
watch: {
|
||||||
drawerPanelVisible(value) {
|
drawerPanelVisible(value) {
|
||||||
if (value && !ws) {
|
if (value && !ws) {
|
||||||
this.$refs.component?.init()
|
this.initWebSocket()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
initWebSocket() {
|
||||||
|
this.$refs.component?.init()
|
||||||
|
},
|
||||||
onClose() {
|
onClose() {
|
||||||
this.$parent.show = false
|
this.$parent.show = false
|
||||||
},
|
},
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
<script type="text/jsx">
|
<script type="text/jsx">
|
||||||
import TreeTable from '../../Table/TreeTable/index.vue'
|
import TreeTable from '../../Table/TreeTable/index.vue'
|
||||||
import { DetailFormatter } from '@/components/Table/TableFormatters'
|
import { DetailFormatter } from '@/components/Table/TableFormatters'
|
||||||
|
import { connectivityMeta } from '@/components/Apps/AccountListTable/const'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'GrantedAssets',
|
name: 'GrantedAssets',
|
||||||
@ -58,9 +59,9 @@ export default {
|
|||||||
url: this.tableUrl,
|
url: this.tableUrl,
|
||||||
hasTree: true,
|
hasTree: true,
|
||||||
columnsExclude: ['spec_info'],
|
columnsExclude: ['spec_info'],
|
||||||
columnShow: {
|
columnsShow: {
|
||||||
min: ['name', 'address', 'accounts'],
|
min: ['name', 'address', 'accounts'],
|
||||||
default: ['name', 'address', 'accounts', 'actions']
|
default: ['name', 'address', 'platform', 'connectivity']
|
||||||
},
|
},
|
||||||
columnsMeta: {
|
columnsMeta: {
|
||||||
name: {
|
name: {
|
||||||
@ -71,7 +72,8 @@ export default {
|
|||||||
},
|
},
|
||||||
actions: {
|
actions: {
|
||||||
has: false
|
has: false
|
||||||
}
|
},
|
||||||
|
connectivity: connectivityMeta
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
headerActions: {
|
headerActions: {
|
||||||
|
@ -7,7 +7,6 @@ import BasicTree from '@/components/Form/FormFields/BasicTree.vue'
|
|||||||
import JsonEditor from '@/components/Form/FormFields/JsonEditor.vue'
|
import JsonEditor from '@/components/Form/FormFields/JsonEditor.vue'
|
||||||
import { assignIfNot, capitalizeFirst } from '@/utils/common'
|
import { assignIfNot, capitalizeFirst } from '@/utils/common'
|
||||||
import TagInput from '@/components/Form/FormFields/TagInput.vue'
|
import TagInput from '@/components/Form/FormFields/TagInput.vue'
|
||||||
import Select2 from '@/components/Form/FormFields/Select2.vue'
|
|
||||||
import TransferSelect from '@/components/Form/FormFields/TransferSelect.vue'
|
import TransferSelect from '@/components/Form/FormFields/TransferSelect.vue'
|
||||||
|
|
||||||
export class FormFieldGenerator {
|
export class FormFieldGenerator {
|
||||||
@ -46,7 +45,7 @@ export class FormFieldGenerator {
|
|||||||
break
|
break
|
||||||
case 'field':
|
case 'field':
|
||||||
type = ''
|
type = ''
|
||||||
field.component = Select2
|
field.component = ObjectSelect2
|
||||||
if (fieldRemoteMeta.required) {
|
if (fieldRemoteMeta.required) {
|
||||||
field.el.clearable = false
|
field.el.clearable = false
|
||||||
}
|
}
|
||||||
@ -77,7 +76,7 @@ export class FormFieldGenerator {
|
|||||||
field.component = ObjectSelect2
|
field.component = ObjectSelect2
|
||||||
break
|
break
|
||||||
case 'm2m_related_field':
|
case 'm2m_related_field':
|
||||||
field.component = Select2
|
field.component = ObjectSelect2
|
||||||
field.el.label = field.label
|
field.el.label = field.label
|
||||||
break
|
break
|
||||||
case 'nested object':
|
case 'nested object':
|
||||||
|
@ -100,7 +100,7 @@
|
|||||||
<div style="font-size: 13px;">{{ contabValueString }}</div>
|
<div style="font-size: 13px;">{{ contabValueString }}</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<CrontabResult :ex="contabValueString" />
|
<CrontabResult :ex="contabValueString" @crontabDiffChange="crontabDiffChangeHandle" />
|
||||||
|
|
||||||
<div class="pop_btn">
|
<div class="pop_btn">
|
||||||
<el-button
|
<el-button
|
||||||
@ -167,7 +167,8 @@ export default {
|
|||||||
week: '*'
|
week: '*'
|
||||||
// year: "",
|
// year: "",
|
||||||
},
|
},
|
||||||
newContabValueString: ''
|
newContabValueString: '',
|
||||||
|
crontabDiff: 0
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
@ -364,6 +365,12 @@ export default {
|
|||||||
},
|
},
|
||||||
// 填充表达式
|
// 填充表达式
|
||||||
submitFill() {
|
submitFill() {
|
||||||
|
const crontabDiffMin = this.crontabDiff / 1000 / 60
|
||||||
|
if (crontabDiffMin > 0 && crontabDiffMin < 10) {
|
||||||
|
const msg = this.$tc('common.crontabDiffError')
|
||||||
|
this.$message.error(msg)
|
||||||
|
return
|
||||||
|
}
|
||||||
this.$emit('fill', this.contabValueString)
|
this.$emit('fill', this.contabValueString)
|
||||||
this.hidePopup()
|
this.hidePopup()
|
||||||
},
|
},
|
||||||
@ -381,6 +388,9 @@ export default {
|
|||||||
for (const j in this.contabValueObj) {
|
for (const j in this.contabValueObj) {
|
||||||
this.changeRadio(j, this.contabValueObj[j])
|
this.changeRadio(j, this.contabValueObj[j])
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
crontabDiffChangeHandle(diff) {
|
||||||
|
this.crontabDiff = diff
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -454,7 +464,7 @@ export default {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.crontab-panel {
|
.crontab-panel {
|
||||||
>>> .el-input-number {
|
> > > .el-input-number {
|
||||||
margin: 0 5px
|
margin: 0 5px
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -52,6 +52,10 @@ export default {
|
|||||||
const cur = interval.next().toString()
|
const cur = interval.next().toString()
|
||||||
this.resultList.push(toSafeLocalDateStr(cur))
|
this.resultList.push(toSafeLocalDateStr(cur))
|
||||||
}
|
}
|
||||||
|
const first = new Date(this.resultList[0])
|
||||||
|
const second = new Date(this.resultList[1])
|
||||||
|
const diff = Math.abs(second - first)
|
||||||
|
this.$emit('crontabDiffChange', diff)
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
this.isShow = false
|
this.isShow = false
|
||||||
// debug(error, 'error')
|
// debug(error, 'error')
|
||||||
|
@ -7,13 +7,11 @@
|
|||||||
v-bind="data.attrs"
|
v-bind="data.attrs"
|
||||||
>
|
>
|
||||||
<template v-if="data.helpTips" #label>
|
<template v-if="data.helpTips" #label>
|
||||||
|
{{ data.label }}
|
||||||
<el-tooltip placement="top" effect="light" popper-class="help-tips">
|
<el-tooltip placement="top" effect="light" popper-class="help-tips">
|
||||||
<div slot="content" v-html="data.helpTips" />
|
<div slot="content" v-html="data.helpTips" />
|
||||||
<el-button style="padding: 0">
|
<i class="fa fa-question-circle-o" />
|
||||||
<i class="fa fa-question-circle" />
|
|
||||||
</el-button>
|
|
||||||
</el-tooltip>
|
</el-tooltip>
|
||||||
{{ data.label }}
|
|
||||||
</template>
|
</template>
|
||||||
<template v-if="readonly && hasReadonlyContent">
|
<template v-if="readonly && hasReadonlyContent">
|
||||||
<div
|
<div
|
||||||
@ -70,7 +68,8 @@
|
|||||||
:key="opt.label"
|
:key="opt.label"
|
||||||
v-bind="opt"
|
v-bind="opt"
|
||||||
:label="'value' in opt ? opt.value : opt.label"
|
:label="'value' in opt ? opt.value : opt.label"
|
||||||
>{{ opt.label }}</el-radio>
|
>{{ opt.label }}
|
||||||
|
</el-radio>
|
||||||
</template>
|
</template>
|
||||||
</custom-component>
|
</custom-component>
|
||||||
<div v-if="data.helpText" class="help-block" v-html="data.helpText" />
|
<div v-if="data.helpText" class="help-block" v-html="data.helpText" />
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
<div class="code-editor" style="font-size: 12px">
|
<div class="code-editor" style="font-size: 12px">
|
||||||
<div class="toolbar">
|
<div class="toolbar">
|
||||||
<div
|
<div
|
||||||
v-for="(item,index) in toolbar.left"
|
v-for="(item,index) in iActions"
|
||||||
:key="index"
|
:key="index"
|
||||||
style="display: inline-block; margin: 0 2px"
|
style="display: inline-block; margin: 0 2px"
|
||||||
>
|
>
|
||||||
@ -93,6 +93,16 @@
|
|||||||
</el-tooltip>
|
</el-tooltip>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div v-if="toolbar.hasOwnProperty('fold')" class="fold">
|
||||||
|
<el-tooltip :content="$tc('common.MoreActions')" placement="top">
|
||||||
|
<i
|
||||||
|
class="fa"
|
||||||
|
:class="[isFold ? 'fa-angle-double-right': 'fa-angle-double-down']"
|
||||||
|
@click="onChangeFold"
|
||||||
|
/>
|
||||||
|
</el-tooltip>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="right-side" style="float: right">
|
<div class="right-side" style="float: right">
|
||||||
<div
|
<div
|
||||||
v-for="(item,index) in toolbar.right"
|
v-for="(item,index) in toolbar.right"
|
||||||
@ -154,9 +164,19 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {}
|
return {
|
||||||
|
isFold: true
|
||||||
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
iActions() {
|
||||||
|
let actions = this.toolbar.left || {}
|
||||||
|
const fold = this.toolbar.fold || {}
|
||||||
|
if (!this.isFold) {
|
||||||
|
actions = { ...actions, ...fold }
|
||||||
|
}
|
||||||
|
return actions
|
||||||
|
},
|
||||||
iValue: {
|
iValue: {
|
||||||
get() {
|
get() {
|
||||||
return this.value
|
return this.value
|
||||||
@ -179,6 +199,9 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
onChangeFold() {
|
||||||
|
this.isFold = !this.isFold
|
||||||
|
},
|
||||||
getLabel(value, items) {
|
getLabel(value, items) {
|
||||||
for (const item of items) {
|
for (const item of items) {
|
||||||
if (item.value === value) {
|
if (item.value === value) {
|
||||||
@ -205,6 +228,16 @@ export default {
|
|||||||
margin-bottom: 5px;
|
margin-bottom: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.fold {
|
||||||
|
display: inline-block;
|
||||||
|
padding-left: 4px;
|
||||||
|
i {
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 15px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
> > > .CodeMirror pre.CodeMirror-line,
|
> > > .CodeMirror pre.CodeMirror-line,
|
||||||
> > > .CodeMirror-linenumber.CodeMirror-gutter-elt {
|
> > > .CodeMirror-linenumber.CodeMirror-gutter-elt {
|
||||||
line-height: 18px !important;
|
line-height: 18px !important;
|
||||||
|
@ -24,6 +24,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
import { mapGetters } from 'vuex'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'PhoneInput',
|
name: 'PhoneInput',
|
||||||
@ -35,21 +36,7 @@ export default {
|
|||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
rawValue: {},
|
rawValue: {}
|
||||||
countries: [
|
|
||||||
{ name: 'China(中国)', value: '+86' },
|
|
||||||
{ name: 'HongKong(中国香港)', value: '+852' },
|
|
||||||
{ name: 'Macao(中国澳门)', value: '+853' },
|
|
||||||
{ name: 'Taiwan(中国台湾)', value: '+886' },
|
|
||||||
{ name: 'America(America)', value: '+1' },
|
|
||||||
{ name: 'Russia(Россия)', value: '+7' },
|
|
||||||
{ name: 'France(français)', value: '+33' },
|
|
||||||
{ name: 'Britain(Britain)', value: '+44' },
|
|
||||||
{ name: 'Germany(Deutschland)', value: '+49' },
|
|
||||||
{ name: 'Japan(日本)', value: '+81' },
|
|
||||||
{ name: 'Korea(한국)', value: '+82' },
|
|
||||||
{ name: 'India(भारत)', value: '+91' }
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
@ -58,7 +45,13 @@ export default {
|
|||||||
return ''
|
return ''
|
||||||
}
|
}
|
||||||
return `${this.rawValue.code}${this.rawValue.phone}`
|
return `${this.rawValue.code}${this.rawValue.phone}`
|
||||||
}
|
},
|
||||||
|
countries: {
|
||||||
|
get() {
|
||||||
|
return this.publicSettings.COUNTRY_CALLING_CODES
|
||||||
|
}
|
||||||
|
},
|
||||||
|
...mapGetters(['publicSettings'])
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
this.rawValue = this.value || { code: '+86', phone: '' }
|
this.rawValue = this.value || { code: '+86', phone: '' }
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
v-if="showTransfer"
|
v-if="showTransfer"
|
||||||
:title="label"
|
:title="label"
|
||||||
:visible.sync="showTransfer"
|
:visible.sync="showTransfer"
|
||||||
|
:close-on-click-modal="false"
|
||||||
width="730px"
|
width="730px"
|
||||||
@cancel="handleTransCancel"
|
@cancel="handleTransCancel"
|
||||||
@confirm="handleTransConfirm"
|
@confirm="handleTransConfirm"
|
||||||
@ -125,13 +126,17 @@ export default {
|
|||||||
return _.uniq(value)
|
return _.uniq(value)
|
||||||
},
|
},
|
||||||
set(val) {
|
set(val) {
|
||||||
this.$emit('input', val)
|
this.emit(val)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
emit(val) {
|
||||||
|
const value = _.uniq(val)
|
||||||
|
this.$emit('input', value)
|
||||||
|
},
|
||||||
onInputChange(val) {
|
onInputChange(val) {
|
||||||
this.$emit('input', val)
|
this.emit(val)
|
||||||
},
|
},
|
||||||
handleFocus() {
|
handleFocus() {
|
||||||
this.$refs.select2.selectRef.blur()
|
this.$refs.select2.selectRef.blur()
|
||||||
@ -154,7 +159,7 @@ export default {
|
|||||||
return { value: item.id, label: item.label }
|
return { value: item.id, label: item.label }
|
||||||
})
|
})
|
||||||
this.select2.options = options
|
this.select2.options = options
|
||||||
this.$emit('input', options.map(item => item.value))
|
this.emit(options.map(item => item.value))
|
||||||
this.showTransfer = false
|
this.showTransfer = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -204,7 +204,12 @@ export default {
|
|||||||
},
|
},
|
||||||
formatWeektime(col) {
|
formatWeektime(col) {
|
||||||
const timeStamp = 1542384000000 // '2018-11-17 00:00:00'
|
const timeStamp = 1542384000000 // '2018-11-17 00:00:00'
|
||||||
const beginStamp = timeStamp + col * 1800000 // col * 30 * 60 * 1000
|
const timezone = 8
|
||||||
|
const offsetGMT = new Date().getTimezoneOffset() // 本地时间和格林威治的时间差,单位为分钟
|
||||||
|
const nowDate = new Date(timeStamp).getTime()
|
||||||
|
const targetStamp = new Date(nowDate + offsetGMT * 60 * 1000 + timezone * 60 * 60 * 1000).getTime()
|
||||||
|
|
||||||
|
const beginStamp = targetStamp + col * 1800000 // col * 30 * 60 * 1000
|
||||||
const endStamp = beginStamp + 1800000
|
const endStamp = beginStamp + 1800000
|
||||||
|
|
||||||
const begin = this.formatDate(new Date(beginStamp), 'hh:mm')
|
const begin = this.formatDate(new Date(beginStamp), 'hh:mm')
|
||||||
|
@ -68,6 +68,9 @@ export default {
|
|||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
handleTagSearch(tags) {
|
handleTagSearch(tags) {
|
||||||
|
if (_.isEqual(tags, this.tags)) {
|
||||||
|
return
|
||||||
|
}
|
||||||
this.tags = tags
|
this.tags = tags
|
||||||
if (tags.length === 0) {
|
if (tags.length === 0) {
|
||||||
this.manualSearch = false
|
this.manualSearch = false
|
||||||
|
@ -209,6 +209,12 @@ export default {
|
|||||||
.left-side {
|
.left-side {
|
||||||
float: left;
|
float: left;
|
||||||
display: block;
|
display: block;
|
||||||
|
&>>> .action-item.el-dropdown {
|
||||||
|
height: 33px;
|
||||||
|
&> .el-button {
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.right-side {
|
.right-side {
|
||||||
|
@ -3,17 +3,19 @@
|
|||||||
<template>
|
<template>
|
||||||
<el-popover
|
<el-popover
|
||||||
:disabled="!showItems"
|
:disabled="!showItems"
|
||||||
|
:open-delay="500"
|
||||||
:title="title"
|
:title="title"
|
||||||
placement="top-start"
|
placement="top-start"
|
||||||
trigger="hover"
|
trigger="hover"
|
||||||
width="400"
|
width="400"
|
||||||
|
@show="getAsyncItems"
|
||||||
>
|
>
|
||||||
<div class="detail-content">
|
<div class="detail-content">
|
||||||
<div v-for="item of items" :key="getKey(item)" class="detail-item">
|
<div v-for="item of items" :key="getKey(item)" class="detail-item">
|
||||||
<span class="detail-item-name">{{ item }}</span>
|
<span class="detail-item-name">{{ item }}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<span slot="reference">{{ items && items.length }}</span>
|
<span slot="reference">{{ amount }}</span>
|
||||||
</el-popover>
|
</el-popover>
|
||||||
</template>
|
</template>
|
||||||
</DetailFormatter>
|
</DetailFormatter>
|
||||||
@ -37,41 +39,73 @@ export default {
|
|||||||
showItems: true,
|
showItems: true,
|
||||||
getItem(item) {
|
getItem(item) {
|
||||||
return item.name
|
return item.name
|
||||||
}
|
},
|
||||||
|
async: false,
|
||||||
|
ajax: {},
|
||||||
|
title: ''
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
|
const formatterArgs = Object.assign(this.formatterArgsDefault, this.col.formatterArgs || {})
|
||||||
return {
|
return {
|
||||||
formatterArgs: Object.assign(this.formatterArgsDefault, this.col.formatterArgs || {})
|
formatterArgs: formatterArgs,
|
||||||
|
data: formatterArgs.async ? [] : (this.cellValue || []),
|
||||||
|
amount: '',
|
||||||
|
asyncGetDone: false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
title() {
|
title() {
|
||||||
return this.formatterArgs.title || ''
|
return this.formatterArgs.title || this.col.label.replace('amount', '').replace('数量', '')
|
||||||
},
|
},
|
||||||
items() {
|
items() {
|
||||||
|
if (this.formatterArgs.async && !this.asyncGetDone) {
|
||||||
|
return [this.$t('common.tree.Loading') + '...']
|
||||||
|
}
|
||||||
const getItem = this.formatterArgs.getItem || (item => item.name)
|
const getItem = this.formatterArgs.getItem || (item => item.name)
|
||||||
let data = this.cellValue?.map(item => getItem(item)) || []
|
let data = this.data.map(item => getItem(item)) || []
|
||||||
data = data.filter(Boolean)
|
data = data.filter(Boolean)
|
||||||
return data
|
return data
|
||||||
},
|
},
|
||||||
showItems() {
|
showItems() {
|
||||||
return this.formatterArgs.showItems !== false && this.cellValue?.length > 0
|
return this.amount !== 0 && this.amount !== ''
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
async mounted() {
|
||||||
|
this.amount = this.formatterArgs.async ? this.cellValue : (this.cellValue || []).length
|
||||||
|
},
|
||||||
methods: {
|
methods: {
|
||||||
getKey(item) {
|
getKey(item) {
|
||||||
const id = Math.random().toString(36).substring(2)
|
const id = Math.random().toString(36).substring(16)
|
||||||
return id + item
|
return id + item
|
||||||
|
},
|
||||||
|
getDefaultUrl() {
|
||||||
|
const url = new URL(this.url, location.origin)
|
||||||
|
url.pathname += this.row.id + '/'
|
||||||
|
return url.pathname
|
||||||
|
},
|
||||||
|
async getAsyncItems() {
|
||||||
|
if (!this.formatterArgs.async) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (this.asyncGetDone) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const url = this.formatterArgs.ajax.url || this.getDefaultUrl()
|
||||||
|
const params = this.formatterArgs.ajax.params || {}
|
||||||
|
const transform = this.formatterArgs.ajax.transform || (resp => resp[this.col.prop.replace('_amount', '')])
|
||||||
|
const response = await this.$axios.get(url, { params: params })
|
||||||
|
this.data = transform(response)
|
||||||
|
this.asyncGetDone = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.detail-content {
|
.detail-content {
|
||||||
padding: 20px 10px;
|
padding: 5px 10px;
|
||||||
max-height: 60vh;
|
max-height: 60vh;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
}
|
}
|
||||||
@ -86,6 +120,6 @@ export default {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.detail-item:first-child {
|
.detail-item:first-child {
|
||||||
border-top: 1px solid #EBEEF5;
|
//border-top: 1px solid #EBEEF5;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -167,6 +167,9 @@ export default {
|
|||||||
},
|
},
|
||||||
async refresh() {
|
async refresh() {
|
||||||
this.treeSearchValue = ''
|
this.treeSearchValue = ''
|
||||||
|
if (this.treeSetting?.callback?.beforeRefresh) {
|
||||||
|
this.treeSetting.callback.beforeRefresh()
|
||||||
|
}
|
||||||
if (this.treeSetting?.callback?.refresh) {
|
if (this.treeSetting?.callback?.refresh) {
|
||||||
await this.treeSetting.callback.refresh()
|
await this.treeSetting.callback.refresh()
|
||||||
}
|
}
|
||||||
|
@ -1 +1 @@
|
|||||||
<svg t="1687315588323" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="3119" width="11" height="11"><path d="M302.545455 116.363636h409.6a27.927273 27.927273 0 0 0 0-55.854545h-409.6a27.927273 27.927273 0 1 0 0 55.854545z m-93.09091 102.4h595.781819a27.927273 27.927273 0 0 0 0-55.854545h-595.781819a27.927273 27.927273 0 1 0 0 55.854545z m670.254546 55.854546h-735.418182c-51.414109 0-93.090909 41.686109-93.090909 93.090909v512c0 51.414109 41.6768 93.090909 93.090909 93.090909h735.418182c51.414109 0 93.090909-41.6768 93.090909-93.090909v-512c0-51.4048-41.6768-93.090909-93.090909-93.090909z m37.236364 594.3296a46.545455 46.545455 0 0 1-46.545455 46.545454h-716.8a46.545455 46.545455 0 0 1-46.545455-46.545454V386.327273a46.545455 46.545455 0 0 1 46.545455-46.545455h716.8a46.545455 46.545455 0 0 1 46.545455 46.545455v482.620509zM602.177164 522.621673l-68.9152-64.474764a4.747636 4.747636 0 0 0-1.405673-1.349818 9.234618 9.234618 0 0 0-1.396364-1.163636 11.776 11.776 0 0 0-3.006836-1.7408c-0.996073-0.577164-1.796655-0.772655-2.802036-1.163637-0.605091-0.195491-1.200873-0.390982-2.010764-0.577163-0.390982 0-0.586473-0.195491-0.996073-0.195491-2.196945-0.577164-4.012218-0.577164-5.008291-0.577164h-0.400291c-0.996073 0-3.006836 0-5.408581 0.577164-0.400291 0-0.595782 0.195491-0.996073 0.195491-0.400291 0.195491-1.005382 0.195491-1.405673 0.390981a15.555491 15.555491 0 0 0-3.006836 1.163637c-0.195491 0-0.195491 0.195491-0.400291 0.195491 0 0.195491-0.195491 0.195491-0.195491 0.195491-1.200873 0.577164-2.606545 1.349818-3.611927 2.122472l-0.195491 0.195491a7.000436 7.000436 0 0 0-2.401746 1.7408l-67.314036 64.660946c-4.803491 4.449745-7.614836 10.426182-7.614836 16.7936-0.195491 6.376727 2.606545 12.744145 7.214545 17.370763s10.826473 7.335564 17.435927 7.335564 13.218909-2.513455 18.031709-7.149382l24.641164-23.738182v266.267928c0 13.312 11.226764 24.129164 25.041455 24.129163s25.041455-10.817164 25.041454-24.129163V532.452073l26.046836 24.520145c4.608 4.626618 10.817164 6.953891 17.640728 6.953891 6.795636 0 13.014109-2.513455 17.836218-7.149382l0.186182-0.195491c9.616291-9.644218 9.4208-24.510836-0.400291-33.773381l-0.223418-0.186182z" fill="#2c2c2c" p-id="3120"></path></svg>
|
<svg t="1704873961556" viewBox="0 0 1124 1224" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="8913" width="14" height="14"><path stroke-width="150" d="M302.545455 116.363636h409.6a27.927273 27.927273 0 0 0 0-55.854545h-409.6a27.927273 27.927273 0 1 0 0 55.854545z m-93.09091 102.4h595.781819a27.927273 27.927273 0 0 0 0-55.854545h-595.781819a27.927273 27.927273 0 1 0 0 55.854545z m670.254546 55.854546h-735.418182c-51.414109 0-93.090909 41.686109-93.090909 93.090909v512c0 51.414109 41.6768 93.090909 93.090909 93.090909h735.418182c51.414109 0 93.090909-41.6768 93.090909-93.090909v-512c0-51.4048-41.6768-93.090909-93.090909-93.090909z m37.236364 594.3296a46.545455 46.545455 0 0 1-46.545455 46.545454h-716.8a46.545455 46.545455 0 0 1-46.545455-46.545454V386.327273a46.545455 46.545455 0 0 1 46.545455-46.545455h716.8a46.545455 46.545455 0 0 1 46.545455 46.545455v482.620509zM602.177164 522.621673l-68.9152-64.474764a4.747636 4.747636 0 0 0-1.405673-1.349818 9.234618 9.234618 0 0 0-1.396364-1.163636 11.776 11.776 0 0 0-3.006836-1.7408c-0.996073-0.577164-1.796655-0.772655-2.802036-1.163637-0.605091-0.195491-1.200873-0.390982-2.010764-0.577163-0.390982 0-0.586473-0.195491-0.996073-0.195491-2.196945-0.577164-4.012218-0.577164-5.008291-0.577164h-0.400291c-0.996073 0-3.006836 0-5.408581 0.577164-0.400291 0-0.595782 0.195491-0.996073 0.195491-0.400291 0.195491-1.005382 0.195491-1.405673 0.390981a15.555491 15.555491 0 0 0-3.006836 1.163637c-0.195491 0-0.195491 0.195491-0.400291 0.195491 0 0.195491-0.195491 0.195491-0.195491 0.195491-1.200873 0.577164-2.606545 1.349818-3.611927 2.122472l-0.195491 0.195491a7.000436 7.000436 0 0 0-2.401746 1.7408l-67.314036 64.660946c-4.803491 4.449745-7.614836 10.426182-7.614836 16.7936-0.195491 6.376727 2.606545 12.744145 7.214545 17.370763s10.826473 7.335564 17.435927 7.335564 13.218909-2.513455 18.031709-7.149382l24.641164-23.738182v266.267928c0 13.312 11.226764 24.129164 25.041455 24.129163s25.041455-10.817164 25.041454-24.129163V532.452073l26.046836 24.520145c4.608 4.626618 10.817164 6.953891 17.640728 6.953891 6.795636 0 13.014109-2.513455 17.836218-7.149382l0.186182-0.195491c9.616291-9.644218 9.4208-24.510836-0.400291-33.773381l-0.223418-0.186182z" fill="#2c2c2c" p-id="8914"></path></svg>
|
Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 2.2 KiB |
1
src/icons/svg/help.svg
Normal file
1
src/icons/svg/help.svg
Normal file
@ -0,0 +1 @@
|
|||||||
|
<svg t="1705571985818" class="icon" viewBox="0 0 1028 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="19018" width="13" height="13"><path d="M983.678752 314.585575c-25.849513-60.781287-62.777388-115.474464-109.785575-162.482651s-101.701365-83.936062-162.482651-109.785575C648.433528 15.569591 581.663938 1.996101 512.998051 1.996101c-68.665887 0-135.435478 13.573489-198.412476 40.321248-60.781287 25.849513-115.474464 62.777388-162.482651 109.785575s-83.936062 101.701365-109.785575 162.482651C15.569591 377.562573 1.996101 444.332164 1.996101 512.998051c0 68.665887 13.573489 135.435478 40.321248 198.412475 25.849513 60.781287 62.777388 115.474464 109.785575 162.482651s101.701365 83.936062 162.482651 109.785575c62.976998 26.747758 129.746589 40.321248 198.412476 40.321248 68.665887 0 135.435478-13.573489 198.412475-40.321248 60.781287-25.849513 115.474464-62.777388 162.482651-109.785575s83.936062-101.701365 109.785575-162.482651c26.747758-62.976998 40.321248-129.746589 40.321248-198.412475 0-68.665887-13.573489-135.435478-40.321248-198.412476zM673.684211 894.752437c-51.00039 21.6577-105.094737 32.636257-160.68616 32.636257s-109.68577-10.978558-160.68616-32.636257c-49.403509-21.058869-93.816764-51.100195-131.9423-89.125926-38.125536-38.125536-68.067057-82.438986-89.125926-131.9423-21.6577-51.00039-32.636257-105.094737-32.636258-160.68616s10.978558-109.68577 32.636258-160.68616c21.058869-49.403509 51.100195-93.816764 89.125926-131.9423 38.125536-38.125536 82.438986-68.067057 131.9423-89.125926 51.00039-21.6577 105.094737-32.636257 160.68616-32.636258s109.68577 10.978558 160.68616 32.636258c49.403509 21.058869 93.816764 51.100195 131.9423 89.125926 38.125536 38.125536 68.067057 82.438986 89.125926 131.9423 21.6577 51.00039 32.636257 105.094737 32.636257 160.68616s-10.978558 109.68577-32.636257 160.68616c-21.058869 49.403509-51.100195 93.816764-89.125926 131.9423-38.125536 38.025731-82.538791 68.067057-131.9423 89.125926z" p-id="19019" fill="#080606"></path><path d="M476.868616 808.820273h74.554386c8.283821 0 14.97076-6.68694 14.97076-14.97076v-68.366472c0-8.283821-6.68694-14.97076-14.97076-14.97076h-74.554386c-8.283821 0-14.97076 6.68694-14.97076 14.97076v68.366472c0 8.283821 6.68694 14.97076 14.97076 14.97076zM687.557115 373.270955c-3.293567-51.299805-19.262378-90.922417-47.307602-117.869785-28.045224-26.947368-68.266667-41.119688-119.566472-42.217544h-0.998051c-58.585575 2.195712-104.096686 19.461988-135.235867 51.100195-31.039376 31.638207-47.906433 77.847953-50.102144 137.331774-0.299415 8.483431 6.487329 15.469786 14.97076 15.469785h65.272514c8.084211 0 14.77115-6.487329 14.970761-14.57154 1.896296-72.558285 30.440546-107.490058 90.024171-109.68577h1.297466c48.904483 2.095906 73.65614 26.947368 77.548538 77.947758 0 0.499025 0.099805 1.097856 0 1.596882-0.59883 26.548148-19.961014 59.0846-57.687329 96.810916-51.100195 48.904483-75.951657 93.118129-75.951657 135.036257v55.990643c0 8.283821 6.68694 14.97076 14.97076 14.970761h68.366472c8.283821 0 14.97076-6.68694 14.97076-14.970761v-65.272514c0-11.377778 7.8846-32.736062 45.211696-70.162963 52.497466-50.301754 79.145419-101.002729 79.145419-150.605848l0.099805-0.898246z" p-id="19020" fill="#080606"></path></svg>
|
After Width: | Height: | Size: 3.2 KiB |
1
src/icons/svg/load-file.svg
Normal file
1
src/icons/svg/load-file.svg
Normal file
@ -0,0 +1 @@
|
|||||||
|
<svg t="1705572472151" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="27270" width="13" height="13"><path d="M896.64 63.872v132.224c0 137.216-88.64 260.48-197.76 327.296 109.12 66.752 197.76 189.056 197.76 326.336V960h28.8a32 32 0 0 1 0 64H99.136a32 32 0 1 1 0-64h28.416v-110.272c0-137.28 92.8-259.584 201.856-326.4C220.16 456.576 127.488 333.376 127.488 196.16V63.872h-31.616A31.872 31.872 0 0 1 63.936 32 32 32 0 0 1 96 0h832.128a32 32 0 0 1 0 63.872h-31.36z m-703.04 0v132.224c0 135.424 117.824 253.312 243.84 286.336a39.68 39.68 0 0 1 15.936 8.384 43.712 43.712 0 0 1-1.344 66.176 42.24 42.24 0 0 1-16.064 7.68c-125.248 33.6-242.368 150.08-242.368 285.056V960h638.272v-110.272c0-135.488-119.808-252.352-245.76-285.44a43.712 43.712 0 0 1-22.784-15.872 42.56 42.56 0 0 1-7.424-18.24c-2.368-23.04 10.24-42.56 30.08-47.68 126.08-33.088 245.888-150.976 245.888-286.4V63.872H193.6zM511.872 458.24a107.264 107.264 0 0 0-14.848-16l-2.88-2.496-2.304-2.048-2.56-1.728a104.448 104.448 0 0 0-35.2-16.768c-65.28-17.088-113.664-67.392-135.744-135.936h387.264C683.52 351.744 634.88 402.048 569.408 419.2c-23.552 6.144-43.52 20.288-57.6 38.976z m-17.472 146.24l2.944-2.368c2.112-1.92 3.776-3.456 5.376-5.12l2.112-2.24 2.944-3.456 2.944-3.712s1.024-1.472 1.024-1.6l6.016 9.152 2.56 1.408 0.832 0.768a82.752 82.752 0 0 0 29.248 19.392l3.136 1.088c1.408 0.512 2.816 0.96 4.288 1.344 72.96 20.48 117.568 80.96 117.568 177.024v18.56H348.608v-18.56c0-95.36 43.776-155.52 115.648-176.64 8.704-2.176 16.96-5.888 24.576-11.008l1.664-0.896 3.84-3.136z" fill="#000000" p-id="27271"></path></svg>
|
After Width: | Height: | Size: 1.6 KiB |
1
src/icons/svg/save-line.svg
Normal file
1
src/icons/svg/save-line.svg
Normal file
@ -0,0 +1 @@
|
|||||||
|
<svg t="1705571586044" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="17569" width="13" height="13"><path d="M925.248 356.928l-258.176-258.176a64 64 0 0 0-45.248-18.752H144a64 64 0 0 0-64 64v736a64 64 0 0 0 64 64h736a64 64 0 0 0 64-64V402.176a64 64 0 0 0-18.752-45.248zM288 144h192V256H288V144z m448 736H288V736h448v144z m144 0H800V704a32 32 0 0 0-32-32H256a32 32 0 0 0-32 32v176H144v-736H224V288a32 32 0 0 0 32 32h256a32 32 0 0 0 32-32V144h77.824l258.176 258.176V880z" p-id="17570"></path></svg>
|
After Width: | Height: | Size: 541 B |
@ -89,7 +89,7 @@ export default {
|
|||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
const defaultFormSetting = this.getDefaultFormSetting()
|
const defaultFormSetting = this.getDefaultFormSetting()
|
||||||
this.iFormSetting = Object.assign({}, this.formSetting, defaultFormSetting)
|
this.iFormSetting = Object.assign({}, defaultFormSetting, this.formSetting)
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
handleCheckedFieldsChange(values) {
|
handleCheckedFieldsChange(values) {
|
||||||
@ -107,6 +107,7 @@ export default {
|
|||||||
return {
|
return {
|
||||||
needGetObjectDetail: false,
|
needGetObjectDetail: false,
|
||||||
submitMethod: () => 'patch',
|
submitMethod: () => 'patch',
|
||||||
|
cleanOtherFormValue: (formValue) => formValue,
|
||||||
cleanFormValue: (value) => {
|
cleanFormValue: (value) => {
|
||||||
const filterValue = {}
|
const filterValue = {}
|
||||||
Object.keys(value)
|
Object.keys(value)
|
||||||
@ -114,12 +115,15 @@ export default {
|
|||||||
.forEach((key) => {
|
.forEach((key) => {
|
||||||
filterValue[key] = value[key]
|
filterValue[key] = value[key]
|
||||||
})
|
})
|
||||||
const formValue = []
|
let formValue = []
|
||||||
let object = {}
|
let object = {}
|
||||||
for (const row of vm.selectedRows) {
|
for (const row of vm.selectedRows) {
|
||||||
object = Object.assign({}, filterValue, { id: row.id })
|
object = Object.assign({}, filterValue, { id: row.id })
|
||||||
formValue.push(object)
|
formValue.push(object)
|
||||||
}
|
}
|
||||||
|
if (typeof this.iFormSetting.cleanOtherFormValue === 'function') {
|
||||||
|
formValue = this.iFormSetting.cleanOtherFormValue(formValue)
|
||||||
|
}
|
||||||
return formValue
|
return formValue
|
||||||
},
|
},
|
||||||
onSubmit: function(validValues) {
|
onSubmit: function(validValues) {
|
||||||
|
@ -66,6 +66,9 @@ export default {
|
|||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
line-height: 32px;
|
line-height: 32px;
|
||||||
color: #1F2329;
|
color: #1F2329;
|
||||||
|
overflow: hidden;
|
||||||
|
white-space: nowrap;
|
||||||
|
text-overflow: ellipsis;
|
||||||
}
|
}
|
||||||
|
|
||||||
.page-heading-right {
|
.page-heading-right {
|
||||||
|
@ -31,7 +31,17 @@ export default [
|
|||||||
name: 'TaskLog',
|
name: 'TaskLog',
|
||||||
hidden: true,
|
hidden: true,
|
||||||
meta: {
|
meta: {
|
||||||
title: i18n.t('CeleryTaskLog'),
|
title: i18n.t('route.CeleryTaskLog'),
|
||||||
|
permissions: []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/chat/chat-ai/',
|
||||||
|
component: () => import('@/views/chat/ChatAi'),
|
||||||
|
name: 'ChatAi',
|
||||||
|
hidden: true,
|
||||||
|
meta: {
|
||||||
|
title: i18n.t('ChatAI'),
|
||||||
permissions: []
|
permissions: []
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -2,12 +2,10 @@
|
|||||||
import store from '@/store'
|
import store from '@/store'
|
||||||
import router, { resetRouter } from '@/router'
|
import router, { resetRouter } from '@/router'
|
||||||
import Vue from 'vue'
|
import Vue from 'vue'
|
||||||
import VueCookie from 'vue-cookie'
|
|
||||||
import { message } from '@/utils/message'
|
import { message } from '@/utils/message'
|
||||||
import orgUtil from '@/utils/org'
|
import orgUtil from '@/utils/org'
|
||||||
import orgs from '@/api/orgs'
|
import orgs from '@/api/orgs'
|
||||||
import { getPropView, isViewHasOrgs } from '@/utils/jms'
|
import { getPropView, isViewHasOrgs } from '@/utils/jms'
|
||||||
import request from '@/utils/request'
|
|
||||||
|
|
||||||
const whiteList = ['/login', process.env.VUE_APP_LOGIN_PATH] // no redirect whitelist
|
const whiteList = ['/login', process.env.VUE_APP_LOGIN_PATH] // no redirect whitelist
|
||||||
|
|
||||||
@ -15,44 +13,11 @@ function reject(msg) {
|
|||||||
return new Promise((resolve, reject) => reject(msg))
|
return new Promise((resolve, reject) => reject(msg))
|
||||||
}
|
}
|
||||||
|
|
||||||
function isRenewalExpired(renewalTime) {
|
|
||||||
const currentTimeStamp = Math.floor(new Date().getTime() / 1000)
|
|
||||||
const sessionExpireTimestamp = VueCookie.get('jms_session_expire_timestamp')
|
|
||||||
|
|
||||||
if (!sessionExpireTimestamp) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
const timeDifferenceInSeconds = currentTimeStamp - parseInt(sessionExpireTimestamp, 10)
|
|
||||||
return timeDifferenceInSeconds > renewalTime
|
|
||||||
}
|
|
||||||
|
|
||||||
async function checkLogin({ to, from, next }) {
|
async function checkLogin({ to, from, next }) {
|
||||||
if (whiteList.indexOf(to.path) !== -1) {
|
if (whiteList.indexOf(to.path) !== -1) {
|
||||||
next()
|
next()
|
||||||
}
|
}
|
||||||
// Determine whether the user has logged in
|
|
||||||
const sessionExpire = VueCookie.get('jms_session_expire')
|
|
||||||
if (!sessionExpire) {
|
|
||||||
request.get(process.env['VUE_APP_LOGOUT_PATH']).finally(() => {
|
|
||||||
window.location = process.env.VUE_APP_LOGIN_PATH
|
|
||||||
})
|
|
||||||
return reject('No session mark found in cookie')
|
|
||||||
} else if (sessionExpire === 'close') {
|
|
||||||
let startTime = new Date().getTime()
|
|
||||||
const intervalId = setInterval(() => {
|
|
||||||
const endTime = new Date().getTime()
|
|
||||||
const delta = (endTime - startTime)
|
|
||||||
startTime = endTime
|
|
||||||
Vue.$log.debug('Set session expire: ', delta)
|
|
||||||
if (!isRenewalExpired(120)) {
|
|
||||||
VueCookie.set('jms_session_expire', 'close', { expires: '2m' })
|
|
||||||
} else {
|
|
||||||
clearInterval(intervalId)
|
|
||||||
}
|
|
||||||
}, 10 * 1000)
|
|
||||||
} else if (sessionExpire === 'age') {
|
|
||||||
Vue.$log.debug('Session expire on age')
|
|
||||||
}
|
|
||||||
try {
|
try {
|
||||||
return await store.dispatch('users/getProfile')
|
return await store.dispatch('users/getProfile')
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
@ -104,7 +104,7 @@ export default {
|
|||||||
this.$axios.post(
|
this.$axios.post(
|
||||||
`/api/v1/accounts/accounts/tasks/`,
|
`/api/v1/accounts/accounts/tasks/`,
|
||||||
{
|
{
|
||||||
action: 'test',
|
action: 'verify',
|
||||||
accounts: [this.object.id]
|
accounts: [this.object.id]
|
||||||
}
|
}
|
||||||
).then(res => {
|
).then(res => {
|
||||||
|
@ -53,7 +53,7 @@ export default {
|
|||||||
formatterArgs: {
|
formatterArgs: {
|
||||||
showFalse: false
|
showFalse: false
|
||||||
},
|
},
|
||||||
width: '80px'
|
width: '152px'
|
||||||
},
|
},
|
||||||
periodic_display: {
|
periodic_display: {
|
||||||
width: '150px'
|
width: '150px'
|
||||||
|
@ -52,8 +52,7 @@ export default {
|
|||||||
formatterArgs: {
|
formatterArgs: {
|
||||||
showFalse: false
|
showFalse: false
|
||||||
},
|
},
|
||||||
filterable: false,
|
width: '152px'
|
||||||
width: '120px'
|
|
||||||
},
|
},
|
||||||
periodic_display: {
|
periodic_display: {
|
||||||
},
|
},
|
||||||
|
@ -63,6 +63,9 @@ export default {
|
|||||||
label: vm.$t('NodeAmount'),
|
label: vm.$t('NodeAmount'),
|
||||||
width: '80px'
|
width: '80px'
|
||||||
},
|
},
|
||||||
|
is_periodic: {
|
||||||
|
width: '152px'
|
||||||
|
},
|
||||||
periodic_display: {
|
periodic_display: {
|
||||||
width: '150px'
|
width: '150px'
|
||||||
},
|
},
|
||||||
|
@ -83,9 +83,13 @@ export default {
|
|||||||
},
|
},
|
||||||
headerActions: {
|
headerActions: {
|
||||||
hasRefresh: true,
|
hasRefresh: true,
|
||||||
hasExport: false,
|
hasExport: this.$hasPerm('accounts.view_accounttemplatesecret'),
|
||||||
hasImport: false,
|
|
||||||
hasMoreActions: false,
|
hasMoreActions: false,
|
||||||
|
exportOptions: {
|
||||||
|
url: '/api/v1/accounts/account-template-secrets/',
|
||||||
|
mfaVerifyRequired: true,
|
||||||
|
tips: this.$t('accounts.AccountExportTips')
|
||||||
|
},
|
||||||
createRoute: () => {
|
createRoute: () => {
|
||||||
return {
|
return {
|
||||||
name: 'AccountTemplateCreate'
|
name: 'AccountTemplateCreate'
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { getUuidUpdateFromUrl } from '@/utils/common'
|
import { getUuidUpdateFromUrl } from '@/utils/common'
|
||||||
import { PasswordRule, UpdateToken } from '@/components/Form/FormFields'
|
import { PasswordRule, UpdateToken, UploadSecret } from '@/components/Form/FormFields'
|
||||||
import Select2 from '@/components/Form/FormFields/Select2'
|
import Select2 from '@/components/Form/FormFields/Select2'
|
||||||
import AutomationParams from '@/components/Apps/AutomationParams'
|
import AutomationParams from '@/components/Apps/AutomationParams'
|
||||||
import i18n from '@/i18n/i18n'
|
import i18n from '@/i18n/i18n'
|
||||||
@ -68,6 +68,7 @@ export const templateFieldsMeta = (vm) => {
|
|||||||
type: 'textarea',
|
type: 'textarea',
|
||||||
rows: 4
|
rows: 4
|
||||||
},
|
},
|
||||||
|
component: UploadSecret,
|
||||||
hidden: (formValue) => formValue.secret_type !== 'ssh_key' || formValue.secret_strategy === 'random'
|
hidden: (formValue) => formValue.secret_type !== 'ssh_key' || formValue.secret_strategy === 'random'
|
||||||
},
|
},
|
||||||
passphrase: {
|
passphrase: {
|
||||||
|
@ -59,7 +59,7 @@ export default {
|
|||||||
[this.$t('Basic'), ['name', 'address', 'platform', 'nodes']],
|
[this.$t('Basic'), ['name', 'address', 'platform', 'nodes']],
|
||||||
[this.$t('Protocol'), ['protocols']],
|
[this.$t('Protocol'), ['protocols']],
|
||||||
[this.$t('Account'), ['accounts']],
|
[this.$t('Account'), ['accounts']],
|
||||||
[this.$t('Other'), ['domain', 'is_active', 'comment']]
|
[this.$t('Other'), ['domain', 'labels', 'is_active', 'comment']]
|
||||||
],
|
],
|
||||||
fieldsMeta: assetFieldsMeta(this),
|
fieldsMeta: assetFieldsMeta(this),
|
||||||
performSubmit(validValues) {
|
performSubmit(validValues) {
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<el-row :gutter="24">
|
<el-row :gutter="24">
|
||||||
<el-col :md="24" :sm="24">
|
<el-col :md="14" :sm="24">
|
||||||
<AccountListTable
|
<AccountListTable
|
||||||
ref="ListTable"
|
ref="ListTable"
|
||||||
:asset="object"
|
:asset="object"
|
||||||
@ -20,17 +20,23 @@
|
|||||||
@onConfirm="onConfirm"
|
@onConfirm="onConfirm"
|
||||||
/>
|
/>
|
||||||
</el-col>
|
</el-col>
|
||||||
|
<el-col :md="10" :sm="24">
|
||||||
|
<QuickActions :actions="quickActions" :title="title" type="primary" />
|
||||||
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { AccountListTable } from '@/components'
|
import { AccountListTable } from '@/components'
|
||||||
|
import QuickActions from '@/components/QuickActions'
|
||||||
import AccountTemplateDialog from '@/views/assets/Asset/AssetCreateUpdate/components/AccountTemplateDialog'
|
import AccountTemplateDialog from '@/views/assets/Asset/AssetCreateUpdate/components/AccountTemplateDialog'
|
||||||
|
import { openTaskPage } from '@/utils/jms'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'Detail',
|
name: 'Detail',
|
||||||
components: {
|
components: {
|
||||||
|
QuickActions,
|
||||||
AccountListTable,
|
AccountListTable,
|
||||||
AccountTemplateDialog
|
AccountTemplateDialog
|
||||||
},
|
},
|
||||||
@ -46,6 +52,7 @@ export default {
|
|||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
|
title: this.$t('accounts.QuickTest'),
|
||||||
templateDialogVisible: false,
|
templateDialogVisible: false,
|
||||||
headerExtraActions: [
|
headerExtraActions: [
|
||||||
{
|
{
|
||||||
@ -56,6 +63,25 @@ export default {
|
|||||||
this.templateDialogVisible = true
|
this.templateDialogVisible = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
],
|
||||||
|
quickActions: [
|
||||||
|
{
|
||||||
|
title: this.$t('accounts.BulkVerify'),
|
||||||
|
attrs: {
|
||||||
|
type: 'primary',
|
||||||
|
label: this.$tc('accounts.Test')
|
||||||
|
},
|
||||||
|
callbacks: Object.freeze({
|
||||||
|
click: () => {
|
||||||
|
this.$axios.post(
|
||||||
|
`/api/v1/accounts/accounts/tasks/`,
|
||||||
|
{ action: 'verify', assets: [this.object.id] }
|
||||||
|
).then(res => {
|
||||||
|
openTaskPage(res['task'])
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -97,8 +97,13 @@ export default {
|
|||||||
route.query.type = row.type.value
|
route.query.type = row.type.value
|
||||||
route.query.category = row.type.category
|
route.query.category = row.type.category
|
||||||
}
|
}
|
||||||
const { href } = vm.$router.resolve(route)
|
const createInNewPage = this.$route.query.node_id && routeAction === 'Create'
|
||||||
window.open(href, '_blank')
|
if (createInNewPage) {
|
||||||
|
const { href } = vm.$router.resolve(route)
|
||||||
|
window.open(href, '_blank')
|
||||||
|
} else {
|
||||||
|
this.$router.push(route)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
const extraQuery = this.$route.params?.extraQuery || {}
|
const extraQuery = this.$route.params?.extraQuery || {}
|
||||||
return {
|
return {
|
||||||
|
@ -160,8 +160,12 @@ export default {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const router = { name: route, query }
|
const router = { name: route, query }
|
||||||
const { href } = this.$router.resolve(router)
|
if (this.$route.query.node_id) {
|
||||||
window.open(href, '_blank')
|
const { href } = this.$router.resolve(router)
|
||||||
|
window.open(href, '_blank')
|
||||||
|
} else {
|
||||||
|
this.$router.push(router)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
39
src/views/assets/Domain/DomainDetail/AssetList.vue
Normal file
39
src/views/assets/Domain/DomainDetail/AssetList.vue
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
<template>
|
||||||
|
<BaseList v-bind="tableConfig" />
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import BaseList from '../../Asset/AssetList/components/BaseList'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
components: {
|
||||||
|
BaseList
|
||||||
|
},
|
||||||
|
props: {
|
||||||
|
object: {
|
||||||
|
type: Object,
|
||||||
|
default: () => {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
tableConfig: {
|
||||||
|
category: 'all',
|
||||||
|
url: `/api/v1/assets/assets/?domain=${this.$route.params.id}`,
|
||||||
|
headerActions: {
|
||||||
|
hasCreate: false,
|
||||||
|
hasRefresh: true,
|
||||||
|
hasExport: false,
|
||||||
|
hasImport: false,
|
||||||
|
hasMoreActions: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
|
||||||
|
</style>
|
@ -10,13 +10,15 @@
|
|||||||
import { GenericDetailPage, TabPage } from '@/layout/components'
|
import { GenericDetailPage, TabPage } from '@/layout/components'
|
||||||
import Detail from './Detail.vue'
|
import Detail from './Detail.vue'
|
||||||
import GatewayList from './GatewayList.vue'
|
import GatewayList from './GatewayList.vue'
|
||||||
|
import AssetList from './AssetList.vue'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
GenericDetailPage,
|
GenericDetailPage,
|
||||||
TabPage,
|
TabPage,
|
||||||
Detail,
|
Detail,
|
||||||
GatewayList
|
GatewayList,
|
||||||
|
AssetList
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
@ -32,6 +34,11 @@ export default {
|
|||||||
title: this.$t('GatewayList'),
|
title: this.$t('GatewayList'),
|
||||||
name: 'GatewayList',
|
name: 'GatewayList',
|
||||||
hidden: () => !this.$hasPerm('assets.view_gateway')
|
hidden: () => !this.$hasPerm('assets.view_gateway')
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: this.$t('assets.AssetList'),
|
||||||
|
name: 'AssetList',
|
||||||
|
hidden: () => !this.$hasPerm('assets.view_asset')
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
hasRightSide: true
|
hasRightSide: true
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { GenericListPage } from '@/layout/components'
|
import { GenericListPage } from '@/layout/components'
|
||||||
import { DetailFormatter } from '@/components/Table/TableFormatters'
|
import AmountFormatter from '@/components/Table/TableFormatters/AmountFormatter.vue'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
@ -15,7 +15,7 @@ export default {
|
|||||||
tableConfig: {
|
tableConfig: {
|
||||||
url: '/api/v1/assets/domains/',
|
url: '/api/v1/assets/domains/',
|
||||||
columnsExclude: ['gateway'],
|
columnsExclude: ['gateway'],
|
||||||
columnsExtra: ['gateway_count'],
|
columnsExtra: ['gateways'],
|
||||||
columns: ['name', 'assets_amount', 'gateways', 'comment', 'actions'],
|
columns: ['name', 'assets_amount', 'gateways', 'comment', 'actions'],
|
||||||
columnsShow: {
|
columnsShow: {
|
||||||
min: ['name', 'actions'],
|
min: ['name', 'actions'],
|
||||||
@ -24,17 +24,22 @@ export default {
|
|||||||
columnsMeta: {
|
columnsMeta: {
|
||||||
assets_amount: {
|
assets_amount: {
|
||||||
width: '160px',
|
width: '160px',
|
||||||
formatter: DetailFormatter
|
formatter: AmountFormatter,
|
||||||
|
formatterArgs: {
|
||||||
|
async: true,
|
||||||
|
permissions: 'assets.view_asset',
|
||||||
|
routeQuery: {
|
||||||
|
activeTab: 'AssetList'
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
gateways: {
|
gateways: {
|
||||||
formatter: DetailFormatter,
|
label: this.$t('assets.Gateway'),
|
||||||
|
formatter: AmountFormatter,
|
||||||
formatterArgs: {
|
formatterArgs: {
|
||||||
permissions: 'assets.view_gateway',
|
permissions: 'assets.view_gateway',
|
||||||
routeQuery: {
|
routeQuery: {
|
||||||
activeTab: 'GatewayList'
|
activeTab: 'GatewayList'
|
||||||
},
|
|
||||||
getTitle: function({ row }) {
|
|
||||||
return row.gateways.length
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -121,6 +121,7 @@ export const assetFieldsMeta = (vm) => {
|
|||||||
name: 'labels',
|
name: 'labels',
|
||||||
label: vm.$t('Label'),
|
label: vm.$t('Label'),
|
||||||
type: 'm2m',
|
type: 'm2m',
|
||||||
|
component: Select2,
|
||||||
el: {
|
el: {
|
||||||
multiple: true,
|
multiple: true,
|
||||||
url: '/api/v1/labels/labels/',
|
url: '/api/v1/labels/labels/',
|
||||||
|
@ -34,7 +34,8 @@ export default {
|
|||||||
min: ['user', 'resource'],
|
min: ['user', 'resource'],
|
||||||
default: [
|
default: [
|
||||||
'user', 'action_display', 'resource_type_display',
|
'user', 'action_display', 'resource_type_display',
|
||||||
'resource', 'remote_addr', 'datetime', 'actions'
|
'resource', 'remote_addr', 'datetime', 'action',
|
||||||
|
'resource_type', 'actions'
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
columnsMeta: {
|
columnsMeta: {
|
||||||
|
29
src/views/chat/ChatAi/index.vue
Normal file
29
src/views/chat/ChatAi/index.vue
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
<template>
|
||||||
|
<div class="chat-container">
|
||||||
|
<ChatAi ref="chat" :drawer-panel-visible="true" :has-close="false" />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import ChatAi from '@/components/Apps/ChatAi'
|
||||||
|
export default {
|
||||||
|
components: {
|
||||||
|
ChatAi
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
this.$refs.chat.initWebSocket()
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.chat-container {
|
||||||
|
height: 100vh;
|
||||||
|
}
|
||||||
|
</style>
|
@ -20,8 +20,8 @@ export default {
|
|||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
config: {
|
config: {
|
||||||
title: this.$t('UserLoginTrend'),
|
title: this.$t('SessionConnectTrend'),
|
||||||
tip: this.$t('UserLoginTrend')
|
tip: this.$t('SessionConnectTrend')
|
||||||
},
|
},
|
||||||
columnChartConfig: {
|
columnChartConfig: {
|
||||||
datesMetrics: [],
|
datesMetrics: [],
|
||||||
@ -43,7 +43,7 @@ export default {
|
|||||||
const data = await this.$axios.get(`/api/v1/index/?dates_metrics=1&days=${this.days}`)
|
const data = await this.$axios.get(`/api/v1/index/?dates_metrics=1&days=${this.days}`)
|
||||||
const loginTotal = data?.dates_metrics_total_count_login
|
const loginTotal = data?.dates_metrics_total_count_login
|
||||||
this.columnChartConfig.datesMetrics = data.dates_metrics_date
|
this.columnChartConfig.datesMetrics = data.dates_metrics_date
|
||||||
if (loginTotal.length > 1) {
|
if (loginTotal.length > 0) {
|
||||||
this.columnChartConfig.primaryData = loginTotal
|
this.columnChartConfig.primaryData = loginTotal
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -65,7 +65,7 @@ export default {
|
|||||||
border-radius: 4px!important;
|
border-radius: 4px!important;
|
||||||
padding: 4px 0!important;
|
padding: 4px 0!important;
|
||||||
.el-radio-button__inner {
|
.el-radio-button__inner {
|
||||||
color: var(--color-primary)!important;
|
color: black!important;
|
||||||
background-color: #FFF!important;
|
background-color: #FFF!important;
|
||||||
border-radius: 4px!important;
|
border-radius: 4px!important;
|
||||||
}
|
}
|
||||||
|
@ -33,7 +33,7 @@ export default {
|
|||||||
{
|
{
|
||||||
prop: 'total',
|
prop: 'total',
|
||||||
label: this.$t('LoginCount'),
|
label: this.$t('LoginCount'),
|
||||||
width: '80px'
|
width: '120px'
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
@ -50,7 +50,7 @@ export default {
|
|||||||
{
|
{
|
||||||
prop: 'total',
|
prop: 'total',
|
||||||
label: this.$t('NumberOfVisits'),
|
label: this.$t('NumberOfVisits'),
|
||||||
width: '80px'
|
width: '140px'
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
@ -28,7 +28,7 @@ export default {
|
|||||||
lineChartConfig: {
|
lineChartConfig: {
|
||||||
datesMetrics: [],
|
datesMetrics: [],
|
||||||
primaryData: [0],
|
primaryData: [0],
|
||||||
primaryName: this.$t('LoginUsers'),
|
primaryName: this.$t('ActiveUsers'),
|
||||||
secondaryData: [0],
|
secondaryData: [0],
|
||||||
secondaryName: this.$t('LoginAssets')
|
secondaryName: this.$t('LoginAssets')
|
||||||
}
|
}
|
||||||
|
@ -44,7 +44,7 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: this.$t('CurrentConnections'),
|
title: this.$t('CurrentConnectionUsers'),
|
||||||
body: {
|
body: {
|
||||||
route: { name: `SessionList`, params: { activeMenu: 'OnlineList' }},
|
route: { name: `SessionList`, params: { activeMenu: 'OnlineList' }},
|
||||||
count: this.counter.total_count_online_users,
|
count: this.counter.total_count_online_users,
|
||||||
|
@ -51,7 +51,7 @@ export default {
|
|||||||
fontSize: 24,
|
fontSize: 24,
|
||||||
color: '#646A73'
|
color: '#646A73'
|
||||||
},
|
},
|
||||||
subtext: this.$t('Proportion') + percentage + '%',
|
subtext: this.$t('Proportion') + ' ' + percentage + '%',
|
||||||
subtextStyle: {
|
subtextStyle: {
|
||||||
fontSize: 12,
|
fontSize: 12,
|
||||||
color: '#646A73'
|
color: '#646A73'
|
||||||
|
@ -74,7 +74,7 @@ export default {
|
|||||||
box-shadow: 2px 1px 2px rgba(0 0 0 / 8%);
|
box-shadow: 2px 1px 2px rgba(0 0 0 / 8%);
|
||||||
|
|
||||||
.el-radio-button__inner {
|
.el-radio-button__inner {
|
||||||
color: var(--color-primary);
|
color: black;
|
||||||
background-color: #FFF;
|
background-color: #FFF;
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
box-shadow: 0 2px 2px rgb(90 97 105 / 31%)!important;
|
box-shadow: 0 2px 2px rgb(90 97 105 / 31%)!important;
|
||||||
|
@ -43,6 +43,9 @@ export default {
|
|||||||
hasImport: false,
|
hasImport: false,
|
||||||
onCreate: () => {
|
onCreate: () => {
|
||||||
this.$emit('addResource')
|
this.$emit('addResource')
|
||||||
|
},
|
||||||
|
searchConfig: {
|
||||||
|
getUrlQuery: false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -34,7 +34,7 @@
|
|||||||
<span>{{ executionInfo.timeCost.toFixed(2) }}</span>
|
<span>{{ executionInfo.timeCost.toFixed(2) }}</span>
|
||||||
</span>
|
</span>
|
||||||
</span>
|
</span>
|
||||||
<div style="padding-left: 30px; background-color: rgb(247 247 247)">
|
<div class="xterm-container">
|
||||||
<Term
|
<Term
|
||||||
ref="xterm"
|
ref="xterm"
|
||||||
:show-tool-bar="true"
|
:show-tool-bar="true"
|
||||||
@ -193,7 +193,9 @@ export default {
|
|||||||
this.cmOptions.mode = option === 'win_shell' ? 'powershell' : option
|
this.cmOptions.mode = option === 'win_shell' ? 'powershell' : option
|
||||||
this.module = option
|
this.module = option
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
|
},
|
||||||
|
fold: {
|
||||||
timeout: {
|
timeout: {
|
||||||
type: 'select',
|
type: 'select',
|
||||||
name: this.$t('Timeout'),
|
name: this.$t('Timeout'),
|
||||||
@ -224,7 +226,7 @@ export default {
|
|||||||
openCommand: {
|
openCommand: {
|
||||||
type: 'button',
|
type: 'button',
|
||||||
align: 'right',
|
align: 'right',
|
||||||
icon: 'fa-folder-open',
|
icon: 'load-file',
|
||||||
tip: this.$t('OpenCommand'),
|
tip: this.$t('OpenCommand'),
|
||||||
callback: (val, setting) => {
|
callback: (val, setting) => {
|
||||||
this.showOpenAdhocDialog = true
|
this.showOpenAdhocDialog = true
|
||||||
@ -233,7 +235,7 @@ export default {
|
|||||||
saveCommand: {
|
saveCommand: {
|
||||||
type: 'button',
|
type: 'button',
|
||||||
align: 'right',
|
align: 'right',
|
||||||
icon: 'save',
|
icon: 'save-line',
|
||||||
tip: this.$t('SaveCommand'),
|
tip: this.$t('SaveCommand'),
|
||||||
callback: (val, setting) => {
|
callback: (val, setting) => {
|
||||||
if (!this.command) {
|
if (!this.command) {
|
||||||
@ -246,7 +248,7 @@ export default {
|
|||||||
help: {
|
help: {
|
||||||
type: 'button',
|
type: 'button',
|
||||||
align: 'right',
|
align: 'right',
|
||||||
icon: 'fa fa-question-circle',
|
icon: 'help',
|
||||||
tip: this.$t('Help'),
|
tip: this.$t('Help'),
|
||||||
callback: (val, setting) => {
|
callback: (val, setting) => {
|
||||||
this.showHelpDialog = true
|
this.showHelpDialog = true
|
||||||
@ -440,6 +442,19 @@ export default {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
|
.xterm-container {
|
||||||
|
padding-left: 30px;
|
||||||
|
background-color: rgb(247, 247, 247);
|
||||||
|
height: calc(100vh - 549px);
|
||||||
|
overflow: hidden;
|
||||||
|
& > div {
|
||||||
|
height: 100%;
|
||||||
|
&>>> .xterm {
|
||||||
|
height: calc(100% - 8px);
|
||||||
|
overflow-y: auto;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
.mini-button {
|
.mini-button {
|
||||||
width: 12px;
|
width: 12px;
|
||||||
float: right;
|
float: right;
|
||||||
|
@ -21,7 +21,6 @@ import PermBulkUpdateDialog from './components/PermBulkUpdateDialog'
|
|||||||
import AmountFormatter from '@/components/Table/TableFormatters/AmountFormatter'
|
import AmountFormatter from '@/components/Table/TableFormatters/AmountFormatter'
|
||||||
import { mapGetters } from 'vuex'
|
import { mapGetters } from 'vuex'
|
||||||
import { AccountLabelMapper, AssetPermissionListPageSearchConfigOptions } from '../const'
|
import { AccountLabelMapper, AssetPermissionListPageSearchConfigOptions } from '../const'
|
||||||
import { DetailFormatter } from '@/components/Table/TableFormatters'
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
@ -87,32 +86,38 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
users_amount: {
|
users_amount: {
|
||||||
formatter: DetailFormatter,
|
formatter: AmountFormatter,
|
||||||
formatterArgs: {
|
formatterArgs: {
|
||||||
|
async: true,
|
||||||
routeQuery: {
|
routeQuery: {
|
||||||
activeTab: 'AssetPermissionUser'
|
activeTab: 'AssetPermissionUser'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
user_groups_amount: {
|
user_groups_amount: {
|
||||||
formatter: DetailFormatter,
|
formatter: AmountFormatter,
|
||||||
formatterArgs: {
|
formatterArgs: {
|
||||||
|
async: true,
|
||||||
routeQuery: {
|
routeQuery: {
|
||||||
activeTab: 'AssetPermissionUser'
|
activeTab: 'AssetPermissionUser'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
assets_amount: {
|
assets_amount: {
|
||||||
formatter: DetailFormatter,
|
formatter: AmountFormatter,
|
||||||
formatterArgs: {
|
formatterArgs: {
|
||||||
|
async: true,
|
||||||
routeQuery: {
|
routeQuery: {
|
||||||
activeTab: 'AssetPermissionAsset'
|
activeTab: 'AssetPermissionAsset'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
nodes_amount: {
|
nodes_amount: {
|
||||||
formatter: DetailFormatter,
|
label: this.$t('perms.Node'),
|
||||||
|
width: '60px',
|
||||||
|
formatter: AmountFormatter,
|
||||||
formatterArgs: {
|
formatterArgs: {
|
||||||
|
async: true,
|
||||||
routeQuery: {
|
routeQuery: {
|
||||||
activeTab: 'AssetPermissionAsset'
|
activeTab: 'AssetPermissionAsset'
|
||||||
}
|
}
|
||||||
@ -146,11 +151,17 @@ export default {
|
|||||||
headerActions: {
|
headerActions: {
|
||||||
hasLabelSearch: true,
|
hasLabelSearch: true,
|
||||||
hasBulkDelete: true,
|
hasBulkDelete: true,
|
||||||
createRoute() {
|
onCreate: () => {
|
||||||
return {
|
const route = {
|
||||||
name: 'AssetPermissionCreate',
|
name: 'AssetPermissionCreate',
|
||||||
query: this.$route.query
|
query: this.$route.query
|
||||||
}
|
}
|
||||||
|
if (vm.$route.query.node_id) {
|
||||||
|
const { href } = this.$router.resolve(route)
|
||||||
|
window.open(href, '_blank')
|
||||||
|
} else {
|
||||||
|
this.$router.push(route)
|
||||||
|
}
|
||||||
},
|
},
|
||||||
handleImportClick: ({ selectedRows }) => {
|
handleImportClick: ({ selectedRows }) => {
|
||||||
this.$eventBus.$emit('showImportDialog', {
|
this.$eventBus.$emit('showImportDialog', {
|
||||||
@ -158,7 +169,6 @@ export default {
|
|||||||
url: '/api/v1/perms/asset-permissions/'
|
url: '/api/v1/perms/asset-permissions/'
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
createInNewPage: true,
|
|
||||||
searchConfig: {
|
searchConfig: {
|
||||||
url: '',
|
url: '',
|
||||||
options: AssetPermissionListPageSearchConfigOptions
|
options: AssetPermissionListPageSearchConfigOptions
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<el-form>
|
<el-form @submit.native.prevent>
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
<el-checkbox-group v-model="choicesSelected">
|
<el-checkbox-group v-model="choicesSelected">
|
||||||
<el-checkbox
|
<el-checkbox
|
||||||
|
@ -29,6 +29,7 @@ export default {
|
|||||||
activeMenu: 'ProfileUpdate',
|
activeMenu: 'ProfileUpdate',
|
||||||
submenu: this.getSubmenu(),
|
submenu: this.getSubmenu(),
|
||||||
hasRightSide: false,
|
hasRightSide: false,
|
||||||
|
hasActivity: false,
|
||||||
actions: {
|
actions: {
|
||||||
detailApiUrl: '/api/v1/users/profile/'
|
detailApiUrl: '/api/v1/users/profile/'
|
||||||
}
|
}
|
||||||
|
82
src/views/sessions/SessionDetail/SessionFTPLogs.vue
Normal file
82
src/views/sessions/SessionDetail/SessionFTPLogs.vue
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
<template>
|
||||||
|
<el-row :gutter="20">
|
||||||
|
<el-col :md="16" :sm="24">
|
||||||
|
<ListTable :header-actions="headerActions" :table-config="tableConfig" />
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import ListTable from '@/components/Table/ListTable'
|
||||||
|
import { download } from '@/utils/common'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'SessionFTPLogs',
|
||||||
|
components: {
|
||||||
|
ListTable
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
tableConfig: {
|
||||||
|
hasSelection: false,
|
||||||
|
url: `/api/v1/audits/ftp-logs/?session_id=${this.$route.params.id}`,
|
||||||
|
columnsShow: {
|
||||||
|
default: [
|
||||||
|
'id', 'user', 'remote_addr', 'asset', 'account', 'operate',
|
||||||
|
'filename', 'date_start', 'is_success', 'actions'
|
||||||
|
]
|
||||||
|
},
|
||||||
|
columnsMeta: {
|
||||||
|
remote_addr: {
|
||||||
|
width: '140px'
|
||||||
|
},
|
||||||
|
operate: {
|
||||||
|
width: '100px'
|
||||||
|
},
|
||||||
|
is_success: {
|
||||||
|
width: '80px'
|
||||||
|
},
|
||||||
|
actions: {
|
||||||
|
width: '82px',
|
||||||
|
formatterArgs: {
|
||||||
|
hasUpdate: false,
|
||||||
|
hasDelete: false,
|
||||||
|
hasClone: false,
|
||||||
|
extraActions: [
|
||||||
|
{
|
||||||
|
name: 'download',
|
||||||
|
title: this.$t('sessions.download'),
|
||||||
|
type: 'primary',
|
||||||
|
can: ({ row }) => { return row.has_file },
|
||||||
|
tip: ({ row }) => {
|
||||||
|
return row.has_file ? this.$t('sessions.download') : this.$t('sessions.DownloadFTPFileTip')
|
||||||
|
},
|
||||||
|
callback: function({ row }) {
|
||||||
|
// 跳转下载页面
|
||||||
|
download(`/api/v1/audits/ftp-logs/${row.id}/file/download/`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
headerActions: {
|
||||||
|
hasExport: false,
|
||||||
|
hasImport: false,
|
||||||
|
hasRefresh: false,
|
||||||
|
hasCreate: false,
|
||||||
|
hasBulkDelete: false,
|
||||||
|
hasBulkUpdate: false,
|
||||||
|
hasLeftActions: false,
|
||||||
|
hasSearch: false,
|
||||||
|
hasRightActions: false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
</style>
|
@ -15,6 +15,7 @@ import { GenericDetailPage } from '@/layout/components'
|
|||||||
import SessionCommands from './SessionCommands'
|
import SessionCommands from './SessionCommands'
|
||||||
import SessionDetailInfo from './SessionDetailInfo'
|
import SessionDetailInfo from './SessionDetailInfo'
|
||||||
import SessionJoinRecords from './SessionJoinRecords'
|
import SessionJoinRecords from './SessionJoinRecords'
|
||||||
|
import SessionFTPLogs from './SessionFTPLogs'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'SessionDetail',
|
name: 'SessionDetail',
|
||||||
@ -22,7 +23,8 @@ export default {
|
|||||||
GenericDetailPage,
|
GenericDetailPage,
|
||||||
SessionCommands,
|
SessionCommands,
|
||||||
SessionDetailInfo,
|
SessionDetailInfo,
|
||||||
SessionJoinRecords
|
SessionJoinRecords,
|
||||||
|
SessionFTPLogs
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
@ -40,6 +42,11 @@ export default {
|
|||||||
name: 'SessionCommands',
|
name: 'SessionCommands',
|
||||||
hidden: () => !this.$hasPerm('terminal.view_command')
|
hidden: () => !this.$hasPerm('terminal.view_command')
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
title: this.$t('FileTransfer'),
|
||||||
|
name: 'SessionFTPLogs',
|
||||||
|
hidden: () => !this.$hasPerm('terminal.view_ftplog')
|
||||||
|
},
|
||||||
{
|
{
|
||||||
title: this.$t('Activity'),
|
title: this.$t('Activity'),
|
||||||
name: 'SessionJoinRecords',
|
name: 'SessionJoinRecords',
|
||||||
|
@ -34,7 +34,7 @@ export default {
|
|||||||
settings: {
|
settings: {
|
||||||
visible: false,
|
visible: false,
|
||||||
url: '/api/v1/settings/setting/?category=ldap',
|
url: '/api/v1/settings/setting/?category=ldap',
|
||||||
fields: ['AUTH_LDAP_SYNC_ORG_IDS', 'AUTH_LDAP_SYNC_IS_PERIODIC', 'AUTH_LDAP_SYNC_CRONTAB', 'AUTH_LDAP_SYNC_INTERVAL'],
|
fields: ['AUTH_LDAP_SYNC_ORG_IDS', 'AUTH_LDAP_SYNC_IS_PERIODIC', 'AUTH_LDAP_SYNC_CRONTAB', 'AUTH_LDAP_SYNC_INTERVAL', 'AUTH_LDAP_SYNC_RECEIVERS'],
|
||||||
fieldsMeta: {
|
fieldsMeta: {
|
||||||
AUTH_LDAP_SYNC_ORG_IDS: {
|
AUTH_LDAP_SYNC_ORG_IDS: {
|
||||||
component: Select2,
|
component: Select2,
|
||||||
@ -63,6 +63,20 @@ export default {
|
|||||||
AUTH_LDAP_SYNC_INTERVAL: {
|
AUTH_LDAP_SYNC_INTERVAL: {
|
||||||
rules: [Required],
|
rules: [Required],
|
||||||
helpText: this.$t('IntervalOfCreateUpdatePage')
|
helpText: this.$t('IntervalOfCreateUpdatePage')
|
||||||
|
},
|
||||||
|
AUTH_LDAP_SYNC_RECEIVERS: {
|
||||||
|
component: Select2,
|
||||||
|
label: this.$t('AccountChangeSecret.Addressee'),
|
||||||
|
el: {
|
||||||
|
value: [],
|
||||||
|
multiple: true,
|
||||||
|
ajax: {
|
||||||
|
url: '/api/v1/users/users/?fields_size=mini&oid=ROOT',
|
||||||
|
transformOption: (item) => {
|
||||||
|
return { label: item.name + '(' + item.username + ')', value: item.id }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
submitMethod: () => 'patch'
|
submitMethod: () => 'patch'
|
||||||
|
@ -112,8 +112,8 @@ export default {
|
|||||||
},
|
},
|
||||||
hidden: (form) => {
|
hidden: (form) => {
|
||||||
const fieldsMeta = this.fieldsMeta
|
const fieldsMeta = this.fieldsMeta
|
||||||
fieldsMeta.apply_assets.el.ajax.url = `/api/v1/assets/assets/suggestions/?oid=${form['org_id']}`
|
fieldsMeta.apply_assets.el.ajax.url = `/api/v1/tickets/apply-assets/suggestions/?oid=${form['org_id']}`
|
||||||
fieldsMeta.apply_nodes.el.ajax.url = `/api/v1/assets/nodes/suggestions/?oid=${form['org_id']}`
|
fieldsMeta.apply_nodes.el.ajax.url = `/api/v1/tickets/apply-nodes/suggestions/?oid=${form['org_id']}`
|
||||||
fieldsMeta.apply_accounts.el.oid = form['org_id']
|
fieldsMeta.apply_accounts.el.oid = form['org_id']
|
||||||
},
|
},
|
||||||
on: {
|
on: {
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { GenericListPage } from '@/layout/components'
|
import { GenericListPage } from '@/layout/components'
|
||||||
import { DetailFormatter } from '@/components/Table/TableFormatters'
|
import AmountFormatter from '@/components/Table/TableFormatters/AmountFormatter.vue'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
@ -22,8 +22,9 @@ export default {
|
|||||||
columnsMeta: {
|
columnsMeta: {
|
||||||
users_amount: {
|
users_amount: {
|
||||||
width: '120px',
|
width: '120px',
|
||||||
formatter: DetailFormatter,
|
formatter: AmountFormatter,
|
||||||
formatterArgs: {
|
formatterArgs: {
|
||||||
|
async: true,
|
||||||
getRoute({ row }) {
|
getRoute({ row }) {
|
||||||
return {
|
return {
|
||||||
name: 'UserGroupDetail',
|
name: 'UserGroupDetail',
|
||||||
|
@ -113,6 +113,7 @@ export default {
|
|||||||
},
|
},
|
||||||
org_roles: {
|
org_roles: {
|
||||||
component: Select2,
|
component: Select2,
|
||||||
|
label: this.$t('users.OrgRoles'),
|
||||||
rules: this.$store.getters.currentOrgIsRoot ? [] : [rules.RequiredChange],
|
rules: this.$store.getters.currentOrgIsRoot ? [] : [rules.RequiredChange],
|
||||||
el: {
|
el: {
|
||||||
multiple: true,
|
multiple: true,
|
||||||
@ -144,6 +145,10 @@ export default {
|
|||||||
},
|
},
|
||||||
phone: {
|
phone: {
|
||||||
component: PhoneInput
|
component: PhoneInput
|
||||||
|
},
|
||||||
|
is_active: {
|
||||||
|
label: this.$t('users.IsActive'),
|
||||||
|
el: {}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
submitMethod() {
|
submitMethod() {
|
||||||
@ -180,7 +185,7 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
...mapGetters(['currentOrgIsRoot'])
|
...mapGetters(['currentOrgIsRoot', 'currentUser'])
|
||||||
},
|
},
|
||||||
async mounted() {
|
async mounted() {
|
||||||
if (this.currentOrgIsRoot) {
|
if (this.currentOrgIsRoot) {
|
||||||
@ -192,6 +197,14 @@ export default {
|
|||||||
methods: {
|
methods: {
|
||||||
afterGetUser(user) {
|
afterGetUser(user) {
|
||||||
this.user = user
|
this.user = user
|
||||||
|
if (this.user.id === this.currentUser.id) {
|
||||||
|
const fieldsToUpdate = ['system_roles', 'org_roles', 'is_active']
|
||||||
|
fieldsToUpdate.forEach(field => {
|
||||||
|
const msg = this.$t('users.disallowSelfUpdateFields', { attr: this.fieldsMeta[field]['label'] })
|
||||||
|
this.fieldsMeta[field].el.disabled = true
|
||||||
|
this.fieldsMeta[field].helpTips = msg
|
||||||
|
})
|
||||||
|
}
|
||||||
this.fieldsMeta.password.el.userIsOrgAdmin = user['is_org_admin']
|
this.fieldsMeta.password.el.userIsOrgAdmin = user['is_org_admin']
|
||||||
if (this.$route.query.clone_from) {
|
if (this.$route.query.clone_from) {
|
||||||
this.user.groups = []
|
this.user.groups = []
|
||||||
|
Loading…
Reference in New Issue
Block a user