mirror of
https://github.com/jumpserver/lina.git
synced 2025-11-09 03:14:48 +00:00
Compare commits
176 Commits
pr@dev@fix
...
v4.8
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c9c2a37f30 | ||
|
|
c1fda10620 | ||
|
|
df1a0228d9 | ||
|
|
959ae0bb2c | ||
|
|
2b22c90701 | ||
|
|
6d16473e4b | ||
|
|
c046c28f6d | ||
|
|
68030d98b2 | ||
|
|
9cbdfacfd2 | ||
|
|
2dec820a0a | ||
|
|
84a66d8c5a | ||
|
|
6eedfe994e | ||
|
|
f1982c2d8f | ||
|
|
4dac455575 | ||
|
|
affb9e405e | ||
|
|
2bf8090b60 | ||
|
|
266ddc7b51 | ||
|
|
5831940be0 | ||
|
|
8ae747b9a5 | ||
|
|
8b69f25e7b | ||
|
|
883d44cede | ||
|
|
024051df76 | ||
|
|
564e530a96 | ||
|
|
d3a0f69b4c | ||
|
|
69f263e491 | ||
|
|
ad82040a54 | ||
|
|
d994c60378 | ||
|
|
d7fddf405f | ||
|
|
ad9660b1f2 | ||
|
|
8a5c60a9bc | ||
|
|
1782c8af74 | ||
|
|
ad55f6f6a6 | ||
|
|
377d17b19d | ||
|
|
51e8b82bbf | ||
|
|
881e2d05c7 | ||
|
|
44c39de459 | ||
|
|
e2f87e62f2 | ||
|
|
f27d6f0e97 | ||
|
|
42d8414834 | ||
|
|
138bdad7ef | ||
|
|
9575936849 | ||
|
|
de3338c3f1 | ||
|
|
f95a78bec1 | ||
|
|
4be9e048e1 | ||
|
|
4f70bf770c | ||
|
|
3361b00bd1 | ||
|
|
ac6a0f49da | ||
|
|
c08f446464 | ||
|
|
849d2829f4 | ||
|
|
5d6b48831c | ||
|
|
d557957b34 | ||
|
|
08821663ce | ||
|
|
3d5ea46930 | ||
|
|
06c87b05cf | ||
|
|
24ba0e38c1 | ||
|
|
adc80ce74a | ||
|
|
d03fe5d95a | ||
|
|
05499d6430 | ||
|
|
74f619c961 | ||
|
|
b0aec69060 | ||
|
|
d7b7704b21 | ||
|
|
2f8480eea6 | ||
|
|
bdb5c83814 | ||
|
|
082ecb15f7 | ||
|
|
8981a8f74f | ||
|
|
b8efbf1e82 | ||
|
|
f7520b87bf | ||
|
|
a146c26e20 | ||
|
|
d0b8efc796 | ||
|
|
61e5b061e9 | ||
|
|
84bbe4de8b | ||
|
|
7c20d08ce2 | ||
|
|
1d288f6212 | ||
|
|
7664487a1c | ||
|
|
4502375ed0 | ||
|
|
6aab902762 | ||
|
|
597b5ac4cf | ||
|
|
e26fecfee8 | ||
|
|
661fc3a3d8 | ||
|
|
f601e25302 | ||
|
|
63e4776355 | ||
|
|
d67d275ae3 | ||
|
|
a8a1a56f3d | ||
|
|
f730611102 | ||
|
|
2344203563 | ||
|
|
f1a79cc36d | ||
|
|
194ea09cab | ||
|
|
b672288725 | ||
|
|
25974c7cf1 | ||
|
|
155da5aecd | ||
|
|
7c72bcf84a | ||
|
|
5a40280baa | ||
|
|
1254a4105a | ||
|
|
9a868ec50a | ||
|
|
534f784fda | ||
|
|
6d83b868ed | ||
|
|
e37b813028 | ||
|
|
01d44bc84e | ||
|
|
fa5f4348ea | ||
|
|
90b481c71d | ||
|
|
6e8b9b4df8 | ||
|
|
a861f77609 | ||
|
|
e58ec6057c | ||
|
|
7ab20c5885 | ||
|
|
e47ddb5355 | ||
|
|
56aa3caa83 | ||
|
|
19b1dc0dbc | ||
|
|
77ef172a23 | ||
|
|
4596887bf1 | ||
|
|
0a3dc30c85 | ||
|
|
51d24bc8e5 | ||
|
|
1b15a4d043 | ||
|
|
7d3f818242 | ||
|
|
4e26f18d77 | ||
|
|
b22613617a | ||
|
|
e971cbf4a8 | ||
|
|
4672abae35 | ||
|
|
ba36d72602 | ||
|
|
4bfbbba4c5 | ||
|
|
ea038ce43a | ||
|
|
e16b19666c | ||
|
|
c7f5409eb6 | ||
|
|
fdbd7d2222 | ||
|
|
ddbaeeafea | ||
|
|
efb0e9dacb | ||
|
|
f6f8301ad5 | ||
|
|
9a63ae63d4 | ||
|
|
1e007ccda3 | ||
|
|
d1d0b06b53 | ||
|
|
5fb70d2f24 | ||
|
|
b54a95430f | ||
|
|
4d8b4c45af | ||
|
|
a6d642df60 | ||
|
|
2e74f1522f | ||
|
|
fe615e0314 | ||
|
|
09f734e6fc | ||
|
|
3117046342 | ||
|
|
b68aecb5cc | ||
|
|
1c9b155d97 | ||
|
|
75b1be9864 | ||
|
|
615c3c1cf4 | ||
|
|
4d82231af4 | ||
|
|
c6cf6571b6 | ||
|
|
8ea990d070 | ||
|
|
f4a32170d5 | ||
|
|
073508675e | ||
|
|
1d6ca0a93a | ||
|
|
36aea652d6 | ||
|
|
1a42ce90ab | ||
|
|
31a401b55d | ||
|
|
582a84178d | ||
|
|
9b9f7c936c | ||
|
|
2a6100957f | ||
|
|
16606d6a27 | ||
|
|
0a612f50e6 | ||
|
|
fe36fa9390 | ||
|
|
ba109900ec | ||
|
|
ec7768267f | ||
|
|
cc58b374ab | ||
|
|
04ffbb8fd6 | ||
|
|
49880f6739 | ||
|
|
e6f98d58c4 | ||
|
|
fd1f16d43c | ||
|
|
968b2415b1 | ||
|
|
776090d6ba | ||
|
|
3a37952288 | ||
|
|
62b8fc0e3b | ||
|
|
b2028869cb | ||
|
|
5277a725f8 | ||
|
|
f137788c1a | ||
|
|
f7d17c8de7 | ||
|
|
feea70b0be | ||
|
|
04696ef3d6 | ||
|
|
1731f4f788 | ||
|
|
6f25d93909 | ||
|
|
46461ec324 |
@@ -24,7 +24,7 @@
|
||||
z-index: 9999;
|
||||
}
|
||||
|
||||
.spinner {
|
||||
#loading .spinner {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
border: 3px solid transparent;
|
||||
@@ -33,7 +33,7 @@
|
||||
animation: spin 1s linear infinite;
|
||||
}
|
||||
|
||||
.spinner::after {
|
||||
#loading .spinner::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: -3px;
|
||||
|
||||
@@ -234,6 +234,9 @@ export const accountFieldsMeta = (vm) => {
|
||||
el: {},
|
||||
hidden: (formValue) => {
|
||||
const automation = vm.iPlatform.automation || {}
|
||||
if (!vm.iPlatform.automation) {
|
||||
return true
|
||||
}
|
||||
vm.fieldsMeta.params.el.method = vm.iPlatform.automation.push_account_method
|
||||
vm.fieldsMeta.params.el.pushAccountParams = vm.iPlatform.automation.push_account_params
|
||||
return !formValue.push_now ||
|
||||
|
||||
@@ -184,7 +184,7 @@ export default {
|
||||
},
|
||||
handleCloseDrawer() {
|
||||
this.iVisible = false
|
||||
Reflect.deleteProperty(this.$route.query, 'flag')
|
||||
// Reflect.deleteProperty(this.$route.query, 'flag')
|
||||
},
|
||||
handleAccountOperation(id, path, data) {
|
||||
this.$axios.post(`/api/v1/accounts/accounts/${id}/${path}/`, data).then((res) => {
|
||||
|
||||
@@ -185,6 +185,10 @@ export default {
|
||||
width: '120px',
|
||||
formatterArgs: {
|
||||
can: () => vm.$hasPerm('accounts.view_account'),
|
||||
getRoute: ({ row }) => ({
|
||||
name: 'AccountDetail',
|
||||
params: { id: row.id }
|
||||
}),
|
||||
getDrawerTitle({ row }) {
|
||||
return `${row.username}@${row.asset.name}`
|
||||
}
|
||||
@@ -205,7 +209,6 @@ export default {
|
||||
formatter: AccountConnectFormatter,
|
||||
formatterArgs: {
|
||||
buttonIcon: 'fa fa-desktop',
|
||||
titleText: '可选协议',
|
||||
url: '/api/v1/assets/assets/{id}',
|
||||
can: () => this.currentUserIsSuperAdmin,
|
||||
connectUrlTemplate: (row) => `/luna/pam_connect/${row.id}/${row.username}/${row.asset.id}/${row.asset.name}/`,
|
||||
@@ -295,7 +298,7 @@ export default {
|
||||
type: 'primary',
|
||||
icon: 'plus',
|
||||
can: () => {
|
||||
return vm.$hasPerm('accounts.add_account') && !this.$store.getters.currentOrgIsRoot
|
||||
return vm.$hasPerm('accounts.add_account') && !vm.$store.getters.currentOrgIsRoot
|
||||
},
|
||||
callback: () => {
|
||||
setTimeout(() => {
|
||||
@@ -311,7 +314,7 @@ export default {
|
||||
title: this.$t('TemplateAdd'),
|
||||
has: !(this.platform || this.asset),
|
||||
can: () => {
|
||||
return vm.$hasPerm('accounts.add_account') && !this.$store.getters.currentOrgIsRoot
|
||||
return vm.$hasPerm('accounts.add_account') && !vm.$store.getters.currentOrgIsRoot
|
||||
},
|
||||
callback: async() => {
|
||||
await this.getAssetDetail()
|
||||
@@ -445,7 +448,7 @@ export default {
|
||||
Object.assign(this.account, account)
|
||||
},
|
||||
addAccountSuccess() {
|
||||
Reflect.deleteProperty(this.$route.query, 'flag')
|
||||
// Reflect.deleteProperty(this.$route.query, 'flag')
|
||||
this.isUpdateAccount = false
|
||||
this.$refs.ListTable.reloadTable()
|
||||
},
|
||||
|
||||
@@ -151,7 +151,7 @@ export const accountOtherActions = (vm) => [
|
||||
title: vm.$t('CopyToAsset'),
|
||||
type: 'primary',
|
||||
divided: true,
|
||||
can: () => vm.$hasPerm('accounts.create_account') && !vm.$store.getters.currentOrgIsRoot,
|
||||
can: () => vm.$hasPerm('accounts.add_account') && !vm.$store.getters.currentOrgIsRoot,
|
||||
has: () => {
|
||||
return !vm.asset
|
||||
},
|
||||
@@ -167,7 +167,7 @@ export const accountOtherActions = (vm) => [
|
||||
name: 'MoveToOther',
|
||||
title: vm.$t('MoveToAsset'),
|
||||
type: 'primary',
|
||||
can: () => vm.$hasPerm('accounts.create_account') && !vm.$store.getters.currentOrgIsRoot,
|
||||
can: () => vm.$hasPerm('accounts.add_account') && !vm.$store.getters.currentOrgIsRoot,
|
||||
has: () => {
|
||||
return !vm.asset
|
||||
},
|
||||
@@ -223,7 +223,7 @@ export const accountQuickFilters = (vm) => [
|
||||
{
|
||||
label: vm.$t('NoLoginLongTime'),
|
||||
filter: {
|
||||
risk: 'long_time_no_login'
|
||||
long_time_no_login: 'true'
|
||||
}
|
||||
},
|
||||
{
|
||||
|
||||
@@ -1,19 +1,19 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="summary-header">
|
||||
<el-tooltip :content="title" placement="top" :open-delay="500">
|
||||
<el-tooltip :content="title" :open-delay="500" placement="top">
|
||||
<span class="title">{{ title }}</span>
|
||||
</el-tooltip>
|
||||
</div>
|
||||
<slot>
|
||||
<h3 class="no-margins ">
|
||||
<span
|
||||
v-async="iCount"
|
||||
:class="{ 'can-direct': canDirect }"
|
||||
class="num"
|
||||
:class="{ 'can-direct': body.canDirect ? true : false }"
|
||||
@click="handleClick"
|
||||
>
|
||||
-
|
||||
<span v-if="count === null"> - </span>
|
||||
<span v-else>{{ count }}</span>
|
||||
</span>
|
||||
</h3>
|
||||
</slot>
|
||||
@@ -21,7 +21,6 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
export default {
|
||||
name: 'SummaryCard',
|
||||
props: {
|
||||
@@ -29,18 +28,18 @@ export default {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
body: {
|
||||
type: Object,
|
||||
default: () => ({})
|
||||
},
|
||||
count: {
|
||||
type: [Number, String, Promise],
|
||||
default: 0
|
||||
default: null
|
||||
},
|
||||
route: {
|
||||
type: [String, Object],
|
||||
default: ''
|
||||
},
|
||||
canDirect: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
callback: {
|
||||
type: Function,
|
||||
default: () => {
|
||||
@@ -54,25 +53,13 @@ export default {
|
||||
data() {
|
||||
return {}
|
||||
},
|
||||
computed: {
|
||||
iCount() {
|
||||
const count = this.body.count || this.count
|
||||
return count
|
||||
},
|
||||
iRoute() {
|
||||
return this.body.route || this.route
|
||||
},
|
||||
iDisabled() {
|
||||
return this.body.disabled === undefined ? this.disabled : this.body.disabled
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
handleClick() {
|
||||
if (this.iDisabled) {
|
||||
if (this.disabled) {
|
||||
return
|
||||
}
|
||||
if (this.iRoute) {
|
||||
this.$router.push(this.iRoute)
|
||||
if (this.route) {
|
||||
this.$router.push(this.route)
|
||||
return
|
||||
}
|
||||
this.callback.bind(this)()
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<div class="content">
|
||||
<el-row justify="space-between" type="flex">
|
||||
<el-col v-for="item of summaryItems" :key="item.title" :md="8" :sm="12" :xs="12">
|
||||
<SummaryCard :body="item.body" :title="item.title" />
|
||||
<SummaryCard :title="item.title" v-bind="item.body" />
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
|
||||
@@ -7,9 +7,9 @@
|
||||
<SummaryCard
|
||||
v-for="item of items"
|
||||
:key="item.title"
|
||||
:body="item.body"
|
||||
:title="item.title"
|
||||
class="summary-card"
|
||||
v-bind="item.body"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
:visible="iVisible"
|
||||
class="processing-dialog"
|
||||
height="300"
|
||||
title="Processing"
|
||||
:title="$tc('Processing')"
|
||||
width="300"
|
||||
@confirm="iVisible=false"
|
||||
>
|
||||
|
||||
@@ -30,6 +30,8 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { getDrawerWidth } from '@/utils/common'
|
||||
|
||||
export default {
|
||||
props: {
|
||||
title: {
|
||||
@@ -38,7 +40,9 @@ export default {
|
||||
},
|
||||
size: {
|
||||
type: String,
|
||||
default: '768px'
|
||||
default: () => {
|
||||
return getDrawerWidth()
|
||||
}
|
||||
},
|
||||
component: {
|
||||
type: [String, Function, Object],
|
||||
|
||||
@@ -89,7 +89,7 @@ export default {
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
// console.log('Method: ', this.method)
|
||||
// this.$log.debug('>>> Method: ', this.method)
|
||||
this.optionUrlMetaAndGenerateColumns()
|
||||
},
|
||||
methods: {
|
||||
|
||||
@@ -172,7 +172,10 @@ export default {
|
||||
const endVal = this.countIndex(end)
|
||||
for (let i = startVal; i < (endVal === 0 ? 48 : endVal); i++) {
|
||||
const curWeek = this.weekTimeData[idNum]
|
||||
curWeek.child[i].check = true
|
||||
const curChild = curWeek.child[i]
|
||||
if (curChild) {
|
||||
curChild.check = true
|
||||
}
|
||||
}
|
||||
},
|
||||
// 计算索引
|
||||
|
||||
@@ -1133,7 +1133,7 @@ export default {
|
||||
* @public
|
||||
*/
|
||||
clearSelection() {
|
||||
return this.selectStrategy.clearSelection()
|
||||
return this.selectStrategy?.clearSelection()
|
||||
},
|
||||
// 弹窗相关
|
||||
// 除非树形结构在操作列点击新增, 否则 row 是 MouseEvent
|
||||
|
||||
@@ -13,15 +13,28 @@ class StrategyAbstract {
|
||||
this.onSelect = this.onSelect.bind(this)
|
||||
this.onSelectAll = this.onSelectAll.bind(this)
|
||||
}
|
||||
|
||||
get elTable() {
|
||||
return this.elDataTable.$refs.table
|
||||
}
|
||||
onSelectionChange() {}
|
||||
onSelect() {}
|
||||
onSelectAll() {}
|
||||
toggleRowSelection() {}
|
||||
clearSelection() {}
|
||||
updateElTableSelection() {}
|
||||
|
||||
onSelectionChange() {
|
||||
}
|
||||
|
||||
onSelect() {
|
||||
}
|
||||
|
||||
onSelectAll() {
|
||||
}
|
||||
|
||||
toggleRowSelection() {
|
||||
}
|
||||
|
||||
clearSelection() {
|
||||
}
|
||||
|
||||
updateElTableSelection() {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -34,14 +47,16 @@ class StrategyNormal extends StrategyAbstract {
|
||||
onSelectionChange(val) {
|
||||
this.elDataTable.selected = val
|
||||
}
|
||||
|
||||
/**
|
||||
* toggleRowSelection和clearSelection的表现与el-table一致
|
||||
*/
|
||||
toggleRowSelection(...args) {
|
||||
return this.elTable.toggleRowSelection(...args)
|
||||
}
|
||||
|
||||
clearSelection() {
|
||||
return this.elTable.clearSelection()
|
||||
return this.elTable?.clearSelection()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -65,6 +80,7 @@ class StrategyPersistSelection extends StrategyAbstract {
|
||||
const isChosen = selection.indexOf(row) > -1
|
||||
this.toggleRowSelection(row, isChosen)
|
||||
}
|
||||
|
||||
/**
|
||||
* 用户切换当前页的多选
|
||||
*/
|
||||
@@ -85,7 +101,7 @@ class StrategyPersistSelection extends StrategyAbstract {
|
||||
// 判断是全选还是取消全选
|
||||
const shouldSelectAll = currentPageSelectedCount < selectableRows.length
|
||||
|
||||
this.elTable.clearSelection()
|
||||
this.elTable?.clearSelection()
|
||||
|
||||
if (shouldSelectAll) {
|
||||
selectableRows.forEach(row => {
|
||||
@@ -112,6 +128,7 @@ class StrategyPersistSelection extends StrategyAbstract {
|
||||
|
||||
this.elDataTable.$emit('selection-change', this.elDataTable.selected)
|
||||
}
|
||||
|
||||
/**
|
||||
* toggleRowSelection和clearSelection管理elDataTable的selected数组
|
||||
* 记得最后要将状态同步到el-table中
|
||||
@@ -133,10 +150,12 @@ class StrategyPersistSelection extends StrategyAbstract {
|
||||
this.elDataTable.$emit('toggle-row-selection', isSelected, row)
|
||||
this.updateElTableSelection()
|
||||
}
|
||||
|
||||
clearSelection() {
|
||||
this.elDataTable.selected = []
|
||||
this.updateElTableSelection()
|
||||
}
|
||||
|
||||
/**
|
||||
* 将selected状态同步到el-table中
|
||||
*/
|
||||
@@ -144,7 +163,7 @@ class StrategyPersistSelection extends StrategyAbstract {
|
||||
const { data, id, selected } = this.elDataTable
|
||||
const selectedIds = new Set(selected.map(r => r[id]))
|
||||
|
||||
this.elTable.clearSelection()
|
||||
this.elTable?.clearSelection()
|
||||
|
||||
data.forEach(row => {
|
||||
const shouldBeSelected = selectedIds.has(row[id])
|
||||
|
||||
@@ -129,7 +129,7 @@ export default {
|
||||
watch: {},
|
||||
methods: {
|
||||
getList() {
|
||||
this.$refs.table.clearSelection()
|
||||
this.$refs.table?.clearSelection()
|
||||
return this.$refs.table.getList()
|
||||
},
|
||||
getData() {
|
||||
|
||||
@@ -2,14 +2,11 @@
|
||||
<Drawer
|
||||
:component="component"
|
||||
:component-listeners="listener"
|
||||
:size="drawerSize"
|
||||
:title="title"
|
||||
:visible.sync="iVisible"
|
||||
append-to-body
|
||||
class="form-drawer"
|
||||
destroy-on-close
|
||||
v-bind="props"
|
||||
@close="closeDrawer"
|
||||
v-on="$listeners"
|
||||
/>
|
||||
</template>
|
||||
@@ -49,31 +46,26 @@ export default {
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
drawerSize() {
|
||||
const drawerWidth = localStorage.getItem('drawerWidth')
|
||||
if (drawerWidth && drawerWidth > 100 && drawerWidth < 2000) {
|
||||
return drawerWidth + 'px'
|
||||
}
|
||||
const width = window.innerWidth
|
||||
if (width >= 800) return '767px'
|
||||
return '90%'
|
||||
},
|
||||
iVisible: {
|
||||
get() {
|
||||
return this.visible
|
||||
},
|
||||
set(val) {
|
||||
this.$log.debug('>>> PageDrawer set to: ', val, this)
|
||||
this.$emit('update:visible', val)
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.$log.debug('>>> PageDrawer component: ', this.component)
|
||||
},
|
||||
methods: {
|
||||
closeDrawer() {
|
||||
this.iVisible = false
|
||||
// 关闭 Drawer 后,清空所有 params 参数
|
||||
Reflect.ownKeys(this.$route.params).forEach(key => {
|
||||
Reflect.deleteProperty(this.$route.params, key)
|
||||
})
|
||||
// Reflect.ownKeys(this.$route.params).forEach(key => {
|
||||
// Reflect.deleteProperty(this.$route.params, key)
|
||||
// })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,7 +6,8 @@
|
||||
:table-config="iTableConfig"
|
||||
v-bind="$attrs"
|
||||
/>
|
||||
<PageDrawer
|
||||
<Drawer
|
||||
v-if="drawerComponent"
|
||||
:action="action"
|
||||
:class="[action]"
|
||||
:component="drawerComponent"
|
||||
@@ -20,7 +21,7 @@
|
||||
|
||||
<script>
|
||||
import ListTable from '../ListTable'
|
||||
import PageDrawer from './PageDrawer.vue'
|
||||
import Drawer from '@/components/Drawer/index.vue'
|
||||
import { setUrlParam, toLowerCaseExcludeAbbr, toSentenceCase } from '@/utils/common'
|
||||
import { mapGetters } from 'vuex'
|
||||
|
||||
@@ -29,7 +30,7 @@ const drawerType = [String, Function]
|
||||
export default {
|
||||
name: 'GenericListPage',
|
||||
components: {
|
||||
ListTable, PageDrawer
|
||||
ListTable, Drawer
|
||||
},
|
||||
props: {
|
||||
detailDrawer: {
|
||||
@@ -71,18 +72,14 @@ export default {
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
title: '',
|
||||
drawerTitle: '',
|
||||
action: '',
|
||||
visible: false,
|
||||
drawerVisible: false,
|
||||
drawerComponent: ''
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapGetters(['inDrawer']),
|
||||
drawerTitle() {
|
||||
return this.getDefaultTitle()
|
||||
},
|
||||
iHeaderActions() {
|
||||
const actions = this.headerActions
|
||||
if (!actions.onCreate) {
|
||||
@@ -91,14 +88,11 @@ export default {
|
||||
return actions
|
||||
},
|
||||
iTableConfig() {
|
||||
const config = {
|
||||
...this.tableConfig
|
||||
}
|
||||
const config = _.cloneDeep(this.tableConfig)
|
||||
const actionMap = {
|
||||
'columnsMeta.actions.formatterArgs.onUpdate': this.onUpdate,
|
||||
'columnsMeta.actions.formatterArgs.onClone': this.onClone,
|
||||
'columnsMeta.name.formatterArgs.drawer': true,
|
||||
'columnsMeta.name.formatterArgs.drawerComponent': this.detailDrawer
|
||||
'columnsMeta.name.formatterArgs.onClick': this.onDetail
|
||||
}
|
||||
for (const [key, value] of Object.entries(actionMap)) {
|
||||
if (_.get(config, key)) {
|
||||
@@ -108,11 +102,13 @@ export default {
|
||||
}
|
||||
const columnsMeta = config.columnsMeta
|
||||
for (const value of Object.values(columnsMeta)) {
|
||||
if (
|
||||
value.formatter && value.formatter.name === 'AmountFormatter' &&
|
||||
value.formatterArgs && !value.formatterArgs.drawer
|
||||
) {
|
||||
value.formatterArgs.drawer = this.detailDrawer
|
||||
const formatter = value?.formatter
|
||||
const formatterArgs = value?.formatterArgs
|
||||
// console.log('>>> name: ', key)
|
||||
// console.log('>>> formatter: ', formatter)
|
||||
const detailFormaters = ['AmountFormatter', 'DetailFormatter']
|
||||
if (formatter && detailFormaters.includes(formatter.name) && formatterArgs.drawer !== false) {
|
||||
formatterArgs.onClick = this.onDetail
|
||||
}
|
||||
}
|
||||
return config
|
||||
@@ -127,12 +123,79 @@ export default {
|
||||
this.drawerVisible = false
|
||||
this.reloadTable()
|
||||
}
|
||||
},
|
||||
drawerVisible: {
|
||||
handler(val, oldVal) {
|
||||
this.$log.debug('>>> drawerVisible changed: ', oldVal, '->', val)
|
||||
if (!val && oldVal) {
|
||||
this.$nextTick(() => {
|
||||
this.afterCloseDrawer()
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.routeFreeze = {
|
||||
params: _.cloneDeep(this.$route.params),
|
||||
query: _.cloneDeep(this.$route.query)
|
||||
}
|
||||
this.$log.debug('>>> DrawerListTable mounted: ', this.routeFreeze)
|
||||
},
|
||||
destroyed() {
|
||||
this.$log.debug('>>> DrawerListTable destroyed')
|
||||
},
|
||||
activated() {
|
||||
this.$log.debug('>>> DrawerListTable activated')
|
||||
},
|
||||
deactivated() {
|
||||
this.$log.debug('>>> DrawerListTable deactivated')
|
||||
},
|
||||
methods: {
|
||||
getDefaultTitle() {
|
||||
afterCloseDrawer() {
|
||||
// 清空路由参数, 恢复路由参数
|
||||
for (const key of ['params', 'query']) {
|
||||
const curValue = this.$route[key] || {}
|
||||
for (const k in curValue) {
|
||||
this.$route[key][k] = ''
|
||||
}
|
||||
const value = this.routeFreeze[key] || {}
|
||||
for (const k in value) {
|
||||
this.$route[key][k] = value[k]
|
||||
}
|
||||
}
|
||||
this.drawerComponent = ''
|
||||
},
|
||||
getDetailDrawerTitle({ col, row, cellValue, payload = {}}) {
|
||||
this.$log.debug('>>> getDetailDrawerTitle: ', col, row, cellValue, payload)
|
||||
const { detailRoute = {}, formatterArgs = {}} = payload
|
||||
const getTitle = formatterArgs.getDrawerTitle
|
||||
this.$log.debug('>>> getTitle: ', getTitle)
|
||||
if (getTitle && typeof getTitle === 'function') {
|
||||
return getTitle({ col, row, cellValue })
|
||||
}
|
||||
if (formatterArgs.title) {
|
||||
return formatterArgs.title
|
||||
}
|
||||
const resolvedRoute = this.resolveRoute(detailRoute)
|
||||
let title = cellValue || row.name
|
||||
if (formatterArgs.getTitle) {
|
||||
title = formatterArgs.getTitle({ col, row, cellValue })
|
||||
}
|
||||
let resource = resolvedRoute?.meta?.title || resolvedRoute?.name || ''
|
||||
resource = resource.replace('Detail', '').replace('详情', '')
|
||||
|
||||
if (resource) {
|
||||
title = `${resource}: ${title}`
|
||||
}
|
||||
return title
|
||||
},
|
||||
getActionDrawerTitle({ action, row, col, cellValue, payload }) {
|
||||
if (action === 'detail') {
|
||||
return this.getDetailDrawerTitle({ col, row, cellValue, payload })
|
||||
}
|
||||
|
||||
let title = this.title
|
||||
let dispatchAction = ''
|
||||
if (!title && this.resource) {
|
||||
title = this.resource
|
||||
}
|
||||
@@ -144,13 +207,15 @@ export default {
|
||||
if (!title) {
|
||||
title = this.$t('NoTitle')
|
||||
}
|
||||
const action = this.action
|
||||
let actionLabel = ''
|
||||
if (action === 'clone' || action === 'create') {
|
||||
dispatchAction = this.$t('Create')
|
||||
actionLabel = this.$t('Create')
|
||||
} else if (action === 'update') {
|
||||
dispatchAction = this.$t('Update')
|
||||
actionLabel = this.$t('Update')
|
||||
} else if (action === 'detail') {
|
||||
actionLabel = this.$t('Detail')
|
||||
}
|
||||
title = dispatchAction + this.$t('WordSep') + toLowerCaseExcludeAbbr(title)
|
||||
title = actionLabel + this.$t('WordSep') + toLowerCaseExcludeAbbr(title)
|
||||
return title
|
||||
},
|
||||
getDefaultDrawer(action) {
|
||||
@@ -177,37 +242,103 @@ export default {
|
||||
return component
|
||||
}
|
||||
},
|
||||
async showDrawer(action) {
|
||||
this.action = action
|
||||
if (action === 'create') {
|
||||
this.drawerComponent = this.createDrawer
|
||||
} else if (action === 'update') {
|
||||
this.drawerComponent = this.updateDrawer || this.createDrawer
|
||||
} else if (action === 'detail') {
|
||||
this.drawerComponent = this.detailDrawer
|
||||
} else if (action === 'clone') {
|
||||
this.drawerComponent = this.createDrawer || this.getDefaultDrawer('create')
|
||||
} else {
|
||||
this.drawerComponent = this.createDrawer
|
||||
resolveRoute(route) {
|
||||
const routes = this.$router.resolve(route)
|
||||
if (!routes) {
|
||||
return
|
||||
}
|
||||
if (!this.drawerComponent) {
|
||||
this.drawerComponent = this.getDefaultDrawer(action)
|
||||
const matched = routes.resolved.matched.filter(item => item.name === route.name && item.components)
|
||||
if (matched.length === 0) {
|
||||
return
|
||||
}
|
||||
if (this.getDrawerTitle) {
|
||||
const actionMeta = await this.$store.getters['common/drawerActionMeta']
|
||||
this.title = this.getDrawerTitle({ action, ...actionMeta })
|
||||
if (matched[0] && matched[0].components?.default) {
|
||||
return matched[0]
|
||||
}
|
||||
this.drawerVisible = true
|
||||
},
|
||||
onCreate(meta) {
|
||||
if (!meta) {
|
||||
meta = {}
|
||||
getDetailComponent({ detailRoute }) {
|
||||
if (!detailRoute) {
|
||||
return this.detailDrawer
|
||||
}
|
||||
this.$log.debug('>>> getDetailComponent: ', detailRoute)
|
||||
const route = this.resolveRoute(detailRoute)
|
||||
let component = null
|
||||
if (route) {
|
||||
component = route.components.default
|
||||
}
|
||||
if (!component) {
|
||||
component = this.detailDrawer
|
||||
}
|
||||
return component
|
||||
},
|
||||
getDrawerComponent(action, payload) {
|
||||
this.$log.debug('>>> getDrawerComponent: ', action, payload)
|
||||
switch (action) {
|
||||
case 'create':
|
||||
return this.createDrawer
|
||||
case 'update':
|
||||
return this.updateDrawer || this.createDrawer
|
||||
case 'detail':
|
||||
return this.getDetailComponent(payload)
|
||||
case 'clone':
|
||||
return this.createDrawer || this.getDefaultDrawer('create')
|
||||
default:
|
||||
return this.createDrawer
|
||||
}
|
||||
},
|
||||
|
||||
async showDrawer(action, { row = {}, col = {}, query = {}, cellValue = '', payload = {}} = {}) {
|
||||
try {
|
||||
// 1. 先重置状态
|
||||
this.drawerVisible = false
|
||||
this.action = action
|
||||
|
||||
for (const key in query) {
|
||||
this.$route.query[key] = query[key]
|
||||
}
|
||||
|
||||
// 2. 等待下一个 tick,确保状态已重置
|
||||
await this.$nextTick()
|
||||
|
||||
// 3. 设置组件
|
||||
this.drawerComponent = this.getDrawerComponent(action, payload)
|
||||
this.$log.debug('>>> drawerComponent: ', this.drawerComponent)
|
||||
this.drawerTitle = this.getActionDrawerTitle({ action, row, col, cellValue, payload })
|
||||
|
||||
// 4. 如果没有组件,尝试获取默认组件
|
||||
if (!this.drawerComponent) {
|
||||
this.drawerComponent = this.getDefaultDrawer(action)
|
||||
}
|
||||
|
||||
// 5. 如果还是没有组件,报错
|
||||
if (!this.drawerComponent) {
|
||||
throw new Error(`No drawer component found for action: ${action}`)
|
||||
}
|
||||
|
||||
// 6. 获取标题
|
||||
if (this.getDrawerTitle) {
|
||||
const actionMeta = await this.$store.getters['common/drawerActionMeta']
|
||||
this.title = this.getDrawerTitle({ action, ...actionMeta })
|
||||
}
|
||||
|
||||
// 7. 等待下一个 tick,确保组件已设置
|
||||
await this.$nextTick()
|
||||
|
||||
// 8. 显示抽屉
|
||||
this.drawerVisible = true
|
||||
|
||||
this.$log.debug('Drawer initialized:', {
|
||||
title: this.title,
|
||||
visible: this.drawerVisible,
|
||||
component: this.drawerComponent,
|
||||
action: this.action,
|
||||
'this': this,
|
||||
'vm': this.vm
|
||||
})
|
||||
} catch (error) {
|
||||
console.error('Failed to show drawer:', error)
|
||||
this.drawerVisible = false
|
||||
this.drawerComponent = ''
|
||||
}
|
||||
this.$store.dispatch('common/setDrawerActionMeta', {
|
||||
action: 'create', ...meta
|
||||
}).then(() => {
|
||||
this.showDrawer('create')
|
||||
})
|
||||
},
|
||||
reloadTable() {
|
||||
if (this.reloadOrderQuery) {
|
||||
@@ -215,21 +346,47 @@ export default {
|
||||
}
|
||||
this.$refs.ListTable.reloadTable()
|
||||
},
|
||||
onClone({ row, col }) {
|
||||
this.$store.dispatch('common/setDrawerActionMeta', {
|
||||
action: 'clone', row: row, col: col, id: row.id
|
||||
}).then(() => {
|
||||
this.showDrawer('clone')
|
||||
async onDetail({ row, col, cellValue, detailRoute, formatterArgs }) {
|
||||
this.$log.debug('>>> onDetail: ', detailRoute, formatterArgs)
|
||||
this.$route.params.id = row.id
|
||||
// 因为使用 detail formatter 时,id 可能并非 row 的,比如 execution 的 task id
|
||||
const query = detailRoute?.query || {}
|
||||
const params = detailRoute?.params || {}
|
||||
for (const key in query) {
|
||||
this.$route.query[key] = query[key]
|
||||
}
|
||||
for (const key in params) {
|
||||
this.$route.params[key] = params[key]
|
||||
}
|
||||
// 有可能来自 params 或者 row
|
||||
const id = params.id || row.id
|
||||
await this.$store.dispatch('common/setDrawerActionMeta', {
|
||||
action: 'detail', row: row, col: col, id: id
|
||||
})
|
||||
await this.showDrawer('detail', { row, col, cellValue, payload: { detailRoute, formatterArgs }})
|
||||
},
|
||||
onUpdate({ row, col }) {
|
||||
async onCreate(meta) {
|
||||
if (!meta) {
|
||||
meta = {}
|
||||
}
|
||||
this.$route.params.id = ''
|
||||
await this.$store.dispatch('common/setDrawerActionMeta', { action: 'create', ...meta })
|
||||
await this.showDrawer('create', meta)
|
||||
},
|
||||
async onClone({ row, col, query = {}}) {
|
||||
this.$route.params.id = ''
|
||||
await this.$store.dispatch('common/setDrawerActionMeta', {
|
||||
action: 'clone', row: row, col: col, id: row.id
|
||||
})
|
||||
await this.showDrawer('clone', { query })
|
||||
},
|
||||
async onUpdate({ row, col, query = {}}) {
|
||||
this.$route.params.id = row.id
|
||||
this.$route.params.action = 'update'
|
||||
this.$store.dispatch('common/setDrawerActionMeta', {
|
||||
await this.$store.dispatch('common/setDrawerActionMeta', {
|
||||
action: 'update', row: row, col: col, id: row.id
|
||||
}).then(() => {
|
||||
this.showDrawer('update')
|
||||
})
|
||||
await this.showDrawer('update', { query })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -117,7 +117,7 @@ export default {
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
// console.log('Object: ', this.object)
|
||||
// this.$log.debug('>>> Object: ', this.object)
|
||||
},
|
||||
methods: {
|
||||
isDisabled(action) {
|
||||
|
||||
@@ -490,6 +490,9 @@ export default {
|
||||
}
|
||||
|
||||
.btn-groups {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
|
||||
::v-deep .el-button.is-disabled {
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
>
|
||||
{{ option.label }}
|
||||
<span v-if="option.hasCount">
|
||||
(<span v-async="getCount(option)">-</span>)
|
||||
<span>({{ option.count }})</span>
|
||||
</span>
|
||||
<!-- <i class="el-icon-circle-check" />-->
|
||||
</span>
|
||||
@@ -32,19 +32,13 @@
|
||||
<span v-for="item of iSummary" :key="item.title" class="summary-block">
|
||||
<SummaryCard
|
||||
:class="item.active ? 'active' : ''"
|
||||
:count="getCount(item)"
|
||||
:count="item.count"
|
||||
:title="item.title"
|
||||
@click="handleFilterClick(item)"
|
||||
/>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="expand-bar-wrap">
|
||||
<div class="expand-bar" @click="toggle">
|
||||
<i :class="isExpand ? 'expand': 'shrink' " class="fa fa-angle-double-up" />
|
||||
<span v-show="!isExpand"> 展开过滤器 </span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
@@ -76,10 +70,11 @@ export default {
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
iFilters: this.cleanFilters(),
|
||||
iSummary: this.cleanSummary(),
|
||||
iFilters: [],
|
||||
iSummary: [],
|
||||
filtered: {},
|
||||
activeFilters: []
|
||||
activeFilters: [],
|
||||
reCount: false
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
@@ -92,7 +87,32 @@ export default {
|
||||
}
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
tableUrl() {
|
||||
this.generateCount()
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.iFilters = this.cleanFilters()
|
||||
this.iSummary = this.cleanSummary()
|
||||
this.generateCount()
|
||||
},
|
||||
methods: {
|
||||
async generateCount() {
|
||||
this.iFilters.forEach(category => {
|
||||
category.options.forEach(option => {
|
||||
if (option.hasCount) {
|
||||
option.count = null
|
||||
this.getCount(option)
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
this.iSummary.forEach(item => {
|
||||
item.count = null
|
||||
this.getCount(item)
|
||||
})
|
||||
},
|
||||
async getCount(item) {
|
||||
if (item.count || item.count === 0) {
|
||||
return item.count
|
||||
@@ -117,6 +137,7 @@ export default {
|
||||
category: 'summary',
|
||||
label: item.title,
|
||||
...item,
|
||||
count: null,
|
||||
filter: item.filter || {},
|
||||
active: false
|
||||
}
|
||||
@@ -170,138 +191,138 @@ export default {
|
||||
}
|
||||
</script>
|
||||
<style lang='scss' scoped>
|
||||
.quick-filter {
|
||||
background: white;
|
||||
padding: 10px 10px 10px 20px;
|
||||
margin-bottom: 10px;
|
||||
display: flex;
|
||||
place-content: stretch flex-end;
|
||||
justify-content: center;
|
||||
align-content: stretch;
|
||||
box-shadow: 0 1px 1px 0 rgba(54, 58, 80, .32);
|
||||
.quick-filter {
|
||||
background: white;
|
||||
padding: 10px 10px 10px 20px;
|
||||
margin-bottom: 10px;
|
||||
display: flex;
|
||||
place-content: stretch flex-end;
|
||||
justify-content: center;
|
||||
align-content: stretch;
|
||||
box-shadow: 0 1px 1px 0 rgba(54, 58, 80, .32);
|
||||
|
||||
&.shrink {
|
||||
background: inherit;
|
||||
padding: 0;
|
||||
margin-bottom: 0;
|
||||
box-shadow: none;
|
||||
}
|
||||
&.shrink {
|
||||
background: inherit;
|
||||
padding: 0;
|
||||
margin-bottom: 0;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.quick-filter-wrap {
|
||||
display: inline-block;
|
||||
width: calc(100% - 70px);
|
||||
.quick-filter-wrap {
|
||||
display: inline-block;
|
||||
width: calc(100% - 70px);
|
||||
|
||||
.summary-zone {
|
||||
padding-top: 10px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
.summary-zone {
|
||||
padding-top: 10px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.summary-block {
|
||||
.active {
|
||||
::v-deep .no-margins .num {
|
||||
color: var(--color-primary);
|
||||
.summary-block {
|
||||
.active {
|
||||
::v-deep .no-margins .num {
|
||||
color: var(--color-primary);
|
||||
|
||||
&::after {
|
||||
content: "\e720";
|
||||
font-family: element-icons !important;
|
||||
font-size: 13px;
|
||||
line-height: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
&::after {
|
||||
content: "\e720";
|
||||
font-family: element-icons !important;
|
||||
font-size: 13px;
|
||||
line-height: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.quick-filter-zone {
|
||||
display: flex;
|
||||
justify-content: flex-start;
|
||||
flex-wrap: wrap; /* 允许 item-zone 换行 */
|
||||
gap: 10px;
|
||||
.quick-filter-zone {
|
||||
display: flex;
|
||||
justify-content: flex-start;
|
||||
flex-wrap: wrap; /* 允许 item-zone 换行 */
|
||||
gap: 10px;
|
||||
|
||||
h5 {
|
||||
font-weight: 600;
|
||||
text-transform: uppercase;
|
||||
font-size: 12px;
|
||||
margin-bottom: .5rem;
|
||||
line-height: 1.2;
|
||||
display: inline-block;
|
||||
}
|
||||
h5 {
|
||||
font-weight: 600;
|
||||
text-transform: uppercase;
|
||||
font-size: 12px;
|
||||
margin-bottom: .5rem;
|
||||
line-height: 1.2;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.item-zone {
|
||||
margin-right: 30px;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
.item-zone {
|
||||
margin-right: 30px;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.item {
|
||||
display: inline-block;
|
||||
margin-right: 8px;
|
||||
color: #303133;
|
||||
font-size: 12px;
|
||||
cursor: pointer;
|
||||
.item {
|
||||
display: inline-block;
|
||||
margin-right: 8px;
|
||||
color: #303133;
|
||||
font-size: 12px;
|
||||
cursor: pointer;
|
||||
|
||||
&::after {
|
||||
content: "";
|
||||
margin-left: 4px;
|
||||
margin-bottom: 2px;
|
||||
vertical-align: middle;
|
||||
width: 1px; /* 分割线宽度 */
|
||||
height: 8px; /* 分割线高度 */
|
||||
background-color: var(--color-icon-primary); /* 分割线颜色 */
|
||||
display: inline-block;
|
||||
}
|
||||
&::after {
|
||||
content: "";
|
||||
margin-left: 4px;
|
||||
margin-bottom: 2px;
|
||||
vertical-align: middle;
|
||||
width: 1px; /* 分割线宽度 */
|
||||
height: 8px; /* 分割线高度 */
|
||||
background-color: var(--color-icon-primary); /* 分割线颜色 */
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
&:last-child::after {
|
||||
display: none;
|
||||
}
|
||||
&:last-child::after {
|
||||
display: none;
|
||||
}
|
||||
|
||||
i {
|
||||
visibility: hidden;
|
||||
margin-left: -3px;
|
||||
}
|
||||
i {
|
||||
visibility: hidden;
|
||||
margin-left: -3px;
|
||||
}
|
||||
|
||||
&.active {
|
||||
color: var(--color-primary);
|
||||
&.active {
|
||||
color: var(--color-primary);
|
||||
|
||||
i {
|
||||
visibility: visible;
|
||||
}
|
||||
}
|
||||
i {
|
||||
visibility: visible;
|
||||
}
|
||||
}
|
||||
|
||||
&:hover {
|
||||
color: var(--color-primary);
|
||||
}
|
||||
}
|
||||
&:hover {
|
||||
color: var(--color-primary);
|
||||
}
|
||||
}
|
||||
|
||||
ul {
|
||||
list-style: none outside none;
|
||||
margin-block-start: 0;
|
||||
padding-left: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
ul {
|
||||
list-style: none outside none;
|
||||
margin-block-start: 0;
|
||||
padding-left: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.filter-options {
|
||||
display: block;
|
||||
}
|
||||
.filter-options {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.expand-bar-wrap {
|
||||
margin: auto 0;
|
||||
min-width: 60px;
|
||||
.expand-bar-wrap {
|
||||
margin: auto 0;
|
||||
min-width: 60px;
|
||||
|
||||
.expand-bar {
|
||||
float: right;
|
||||
display: block;
|
||||
cursor: pointer;
|
||||
.expand-bar {
|
||||
float: right;
|
||||
display: block;
|
||||
cursor: pointer;
|
||||
|
||||
i {
|
||||
padding: 5px;
|
||||
i {
|
||||
padding: 5px;
|
||||
|
||||
&.shrink {
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
&.shrink {
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
@@ -103,7 +103,8 @@ export default {
|
||||
initQuery: {},
|
||||
tablePath: new URL(this.tableConfig.url || '', 'http://127.0.0.1').pathname,
|
||||
objStorage: new ObjectLocalStorage('filterExpand'),
|
||||
iFilterExpand: null
|
||||
iFilterExpand: null,
|
||||
reloadTable: _.debounce(this._reloadTable, 300)
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
@@ -281,7 +282,7 @@ export default {
|
||||
handleSelectionChange(val) {
|
||||
this.selectedRows = val
|
||||
},
|
||||
reloadTable() {
|
||||
_reloadTable() {
|
||||
this.dataTable?.getList()
|
||||
},
|
||||
updateInitQuery(attrs) {
|
||||
|
||||
@@ -112,7 +112,7 @@ export default {
|
||||
const res = await this.$axios.get(url)
|
||||
|
||||
if (res && res.protocols.length > 0) {
|
||||
const protocol = res.protocols[0]
|
||||
const protocol = res.protocols.filter(protocol => protocol.name !== 'sftp')[0]
|
||||
|
||||
this.formatterArgs.setMapItem(this.row.id, protocol.name)
|
||||
this.handleWindowOpen(this.row, protocol.name)
|
||||
@@ -127,7 +127,8 @@ export default {
|
||||
const url = this.formatterArgs.url.replace('{id}', assetId)
|
||||
const res = await this.$axios.get(url)
|
||||
|
||||
if (res) this.protocols = res.protocols
|
||||
// 暂将 SFTP 过滤
|
||||
if (res) this.protocols = res.protocols.filter(protocol => protocol.name !== 'sftp')
|
||||
} catch (e) {
|
||||
throw new Error(`Error getting protocols: ${e}`)
|
||||
}
|
||||
|
||||
@@ -37,6 +37,22 @@ const defaultUpdateCallback = function({ row, col }) {
|
||||
this.$router.push(route)
|
||||
}
|
||||
|
||||
const defaultViewCallback = function({ row, col }) {
|
||||
const id = row.id
|
||||
let route = { params: { id: id }}
|
||||
const viewRoute = this.colActions.viewRoute
|
||||
|
||||
if (typeof updateRoute === 'object') {
|
||||
route = Object.assign(route, viewRoute)
|
||||
} else if (typeof updateRoute === 'function') {
|
||||
route = viewRoute({ row, col })
|
||||
} else {
|
||||
route.name = viewRoute
|
||||
}
|
||||
|
||||
this.$router.push(route)
|
||||
}
|
||||
|
||||
const defaultCloneCallback = function({ row, col }) {
|
||||
const id = row.id
|
||||
let route = { query: { clone_from: id }}
|
||||
@@ -105,6 +121,7 @@ export default {
|
||||
cloneRoute: this.$route.name.replace('List', 'Create'),
|
||||
performDelete: defaultPerformDelete,
|
||||
onUpdate: defaultUpdateCallback,
|
||||
onView: defaultViewCallback,
|
||||
onDelete: defaultDeleteCallback,
|
||||
onClone: defaultCloneCallback,
|
||||
extraActions: []
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<DetailFormatter :col="col" :row="row" :prevant-click="formatterArgs.prevantClick">
|
||||
<DetailFormatter :col="col" :row="row" :prevent-click="formatterArgs.preventClick">
|
||||
<template>
|
||||
<el-popover
|
||||
:disabled="!showItems"
|
||||
@@ -43,7 +43,7 @@ export default {
|
||||
async: false,
|
||||
ajax: {},
|
||||
title: '',
|
||||
prevantClick: false
|
||||
preventClick: false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
</slot>
|
||||
</el-link>
|
||||
<Drawer
|
||||
v-if="formatterArgs.drawer && drawerVisible"
|
||||
v-if="formatterArgs.drawer && drawerComponent && drawerVisible"
|
||||
:component="drawerComponent"
|
||||
:has-footer="false"
|
||||
:title="drawerTitle"
|
||||
@@ -56,7 +56,7 @@ export default {
|
||||
}
|
||||
}
|
||||
},
|
||||
prevantClick: {
|
||||
preventClick: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
@@ -85,7 +85,7 @@ export default {
|
||||
disabled() {
|
||||
let can = this.formatterArgs.can
|
||||
if (typeof can === 'function') {
|
||||
can = can(this.col)
|
||||
can = can({ col: this.col, row: this.row })
|
||||
}
|
||||
return !can
|
||||
},
|
||||
@@ -104,74 +104,21 @@ export default {
|
||||
}
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
drawerVisible(val) {
|
||||
this.$log.debug('>>> DetailFormatter drawerVisible: ', val)
|
||||
if (!val) {
|
||||
this.drawerComponent = ''
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
getResource() {
|
||||
const route = this.resolveRoute()
|
||||
if (!route) {
|
||||
return
|
||||
}
|
||||
const resource = route.meta.title || route.name
|
||||
return resource.replace(' details', '').replace('详情', '')
|
||||
},
|
||||
getDrawerTitle() {
|
||||
let title = this.cellValue || this.row.name
|
||||
|
||||
if (this.formatterArgs?.getDrawerTitle && typeof this.formatterArgs.getDrawerTitle === 'function') {
|
||||
title = this.formatterArgs.getDrawerTitle({
|
||||
col: this.col,
|
||||
row: this.row,
|
||||
cellValue: this.cellValue
|
||||
})
|
||||
}
|
||||
|
||||
const resource = this.getResource()
|
||||
|
||||
if (resource) {
|
||||
title = `${resource}: ${title}`
|
||||
}
|
||||
|
||||
return title
|
||||
},
|
||||
resolveRoute() {
|
||||
const route = this.getDetailRoute()
|
||||
const routes = this.$router.resolve(route)
|
||||
if (!routes) {
|
||||
return
|
||||
}
|
||||
const matched = routes.resolved.matched.filter(item => item.name === route.name && item.components)
|
||||
if (matched.length === 0) {
|
||||
return
|
||||
}
|
||||
if (matched[0] && matched[0].components?.default) {
|
||||
return matched[0]
|
||||
}
|
||||
},
|
||||
getRouteComponent() {
|
||||
const route = this.resolveRoute()
|
||||
if (route) {
|
||||
return route.components.default
|
||||
}
|
||||
},
|
||||
showDrawer() {
|
||||
if (this.formatterArgs.drawerComponent) {
|
||||
this.drawerComponent = this.formatterArgs.drawerComponent
|
||||
} else {
|
||||
this.drawerComponent = this.getRouteComponent()
|
||||
}
|
||||
const route = this.getDetailRoute()
|
||||
if (route?.query?.tab) {
|
||||
this.$cookie.set(route.name, route.query.tab, 1)
|
||||
this.$route.query.tab = route.query.tab
|
||||
}
|
||||
const payload = {
|
||||
action: 'detail',
|
||||
row: this.row,
|
||||
getTitle() {
|
||||
return this.formatterArgs.getTitle({
|
||||
col: this.col,
|
||||
id: route.params.id || this.row.id
|
||||
}
|
||||
this.$store.dispatch('common/setDrawerActionMeta', payload).then(() => {
|
||||
this.drawerTitle = this.getDrawerTitle(payload)
|
||||
this.drawerVisible = true
|
||||
row: this.row,
|
||||
cellValue: this.cellValue,
|
||||
index: this.index
|
||||
})
|
||||
},
|
||||
handleClick() {
|
||||
@@ -180,14 +127,10 @@ export default {
|
||||
}
|
||||
|
||||
if (this.formatterArgs.onClick) {
|
||||
return this.formatterArgs.onClick(this.callbackArgs)
|
||||
return this.formatterArgs.onClick({ ...this.callbackArgs, detailRoute: this.getDetailRoute(), formatterArgs: this.formatterArgs })
|
||||
}
|
||||
|
||||
if (this.formatterArgs.drawer) {
|
||||
return this.showDrawer()
|
||||
}
|
||||
|
||||
if (this.prevantClick) {
|
||||
if (this.preventClick) {
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@@ -97,12 +97,15 @@ export default {
|
||||
}
|
||||
this.processing = true
|
||||
this.$axios.post(`/api/v1/accounts/account-risks/handle/`, data).then(() => {
|
||||
if (cmd === 'add_account') {
|
||||
if (cmd === 'add_account' || cmd === 'change_password_add') {
|
||||
this.row.present = true
|
||||
}
|
||||
if (cmd === 'ignore') {
|
||||
this.row.status = { 'value': statusMap.ignored }
|
||||
}
|
||||
if (cmd === 'delete_remote') {
|
||||
this.row.remote_present = false
|
||||
}
|
||||
this.row.status = { 'value': statusMap.confirmed }
|
||||
}).finally(() => {
|
||||
setTimeout(() => {
|
||||
|
||||
@@ -171,6 +171,7 @@ export default {
|
||||
}
|
||||
},
|
||||
onEditBlur() {
|
||||
this.isEdit = false
|
||||
this.$emit('input', this.realValue)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -244,10 +244,12 @@ export default {
|
||||
delete routeFilter.search
|
||||
}
|
||||
const asFilterTags = _.cloneDeep(this.filterTags)
|
||||
this.filterTags = {
|
||||
...asFilterTags,
|
||||
...routeFilter
|
||||
}
|
||||
setTimeout(() => {
|
||||
this.filterTags = {
|
||||
...asFilterTags,
|
||||
...routeFilter
|
||||
}
|
||||
}, 100)
|
||||
},
|
||||
getValueLabel(key, value) {
|
||||
for (const field of this.options) {
|
||||
|
||||
@@ -7,7 +7,9 @@
|
||||
:style="{width: treeWidth}"
|
||||
class="left"
|
||||
>
|
||||
<span v-if="component === 'AutoDataZTree'" class="title">{{ $t('AssetTree') }}</span>
|
||||
<span v-if="component === 'AutoDataZTree'" class="title">
|
||||
{{ $t('AssetTree') }}
|
||||
</span>
|
||||
<component
|
||||
:is="component"
|
||||
:key="componentTreeKey"
|
||||
|
||||
@@ -53,24 +53,24 @@ export default {
|
||||
resizeObserver: null,
|
||||
span: 12,
|
||||
isShow: true,
|
||||
iValue: this.value
|
||||
iValue: this.sanitizeContent(this.value)
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
sanitizedValue() {
|
||||
// 转义特殊字符
|
||||
let content = this.iValue.replace(/\\/g, '\\\\').replace(/\$/g, '\\$')
|
||||
const content = this.iValue.replace(/\\/g, '\\\\').replace(/\$/g, '\\$')
|
||||
|
||||
// 使用 DOMPurify 进行 XSS 过滤
|
||||
content = DOMPurify.sanitize(content)
|
||||
|
||||
return content
|
||||
return this.sanitizeContent(content)
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
value(newVal) {
|
||||
this.iValue = this.sanitizeContent(newVal)
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.$nextTick(() => {
|
||||
this.resizeObserver = new ResizeObserver(entries => {
|
||||
// 监听高度变化
|
||||
const height = entries[0].target.offsetHeight
|
||||
if (height) {
|
||||
this.height = height
|
||||
@@ -90,8 +90,19 @@ export default {
|
||||
this.resizeObserver = null
|
||||
},
|
||||
methods: {
|
||||
sanitizeContent(content) {
|
||||
if (!content) return ''
|
||||
|
||||
return DOMPurify.sanitize(content, {
|
||||
ALLOWED_TAGS: ['p', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'ul', 'ol', 'li', 'strong', 'em', 'code', 'pre', 'blockquote', 'a', 'img'],
|
||||
FORBID_TAGS: ['script', 'style', 'iframe', 'frame', 'object', 'embed'],
|
||||
FORBID_ATTR: ['onerror', 'onload', 'onclick', 'onmouseover']
|
||||
})
|
||||
},
|
||||
onChange() {
|
||||
this.$emit('change', this.iValue)
|
||||
const sanitizedValue = this.sanitizeContent(this.iValue)
|
||||
this.iValue = sanitizedValue
|
||||
this.$emit('change', sanitizedValue)
|
||||
},
|
||||
onView() {
|
||||
this.isShow = !this.isShow
|
||||
|
||||
@@ -69,6 +69,8 @@ export const is_periodic = {
|
||||
}
|
||||
}
|
||||
|
||||
export const taskStatusFormatterMeta = {}
|
||||
|
||||
export const periodicMeta = {
|
||||
is_periodic,
|
||||
interval,
|
||||
|
||||
@@ -6,20 +6,23 @@ import store from '@/store'
|
||||
import { isSameView } from '@/utils/jms'
|
||||
import { toSentenceCase } from '@/utils/common'
|
||||
|
||||
// NProgress.configure({
|
||||
// showSpinner: false
|
||||
// }) // NProgress Configuration
|
||||
//
|
||||
function beforeRouteChange(to, from, next) {
|
||||
localStorage.setItem('activeTab', '')
|
||||
}
|
||||
|
||||
router.beforeEach(async(to, from, next) => {
|
||||
// start progress bar
|
||||
// NProgress.start()
|
||||
try {
|
||||
await store.dispatch('common/cleanDrawerActionMeta')
|
||||
await startup({ to, from, next })
|
||||
if (to.name && from.name && to.name !== from.name) {
|
||||
await beforeRouteChange(to, from, next)
|
||||
}
|
||||
next()
|
||||
} catch (e) {
|
||||
const msg = 'Start service error: ' + e
|
||||
// debug(e)
|
||||
console.log(msg)
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
@@ -134,14 +134,7 @@ export default {
|
||||
// 获取提交的方法
|
||||
submitMethod: {
|
||||
type: [Function, String],
|
||||
default: function() {
|
||||
const params = this.$route.params
|
||||
if (params.id) {
|
||||
return 'put'
|
||||
} else {
|
||||
return 'post'
|
||||
}
|
||||
}
|
||||
default: null
|
||||
},
|
||||
// 获取创建和更新的url function
|
||||
getUrl: {
|
||||
@@ -306,7 +299,7 @@ export default {
|
||||
this.$log.debug('Object init is: ', this.object, this.method)
|
||||
await this.setDrawerMeta()
|
||||
this.setMethod()
|
||||
// console.log('Set method: ', this.method, this.action)
|
||||
// this.$log.debug('Set method: ', this.method, this.action)
|
||||
|
||||
try {
|
||||
const values = await this.getFormValue()
|
||||
@@ -333,7 +326,10 @@ export default {
|
||||
} else {
|
||||
this.method = this.submitMethod
|
||||
}
|
||||
// console.log('Drawer: ', this.drawer, this.submitMethod)
|
||||
// this.$log.debug('Drawer: ', this.drawer, this.submitMethod, this.action)
|
||||
if (!this.drawer && !this.method) {
|
||||
this.method = this.$route.params['id'] ? 'put' : 'post'
|
||||
}
|
||||
if (this.drawer && !this.submitMethod) {
|
||||
if (this.action === 'clone' || this.action === 'create') {
|
||||
this.method = 'post'
|
||||
@@ -424,6 +420,7 @@ export default {
|
||||
if (needGetObjectDetail === null) {
|
||||
needGetObjectDetail = this.isUpdateMethod() || this.action === 'clone'
|
||||
}
|
||||
// this.$log.debug('Get form value: ', needGetObjectDetail, this.needGetObjectDetail, this.isUpdateMethod(), this.action)
|
||||
if (!needGetObjectDetail) {
|
||||
return Object.assign(this.form, this.initial)
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
<template>
|
||||
<TabPage
|
||||
v-if="!loading"
|
||||
:active-menu.sync="iActiveMenu"
|
||||
:submenu="iSubmenu"
|
||||
:title="iTitle"
|
||||
@@ -12,7 +11,9 @@
|
||||
<ActionsGroup slot="headingRightSide" :actions="pageActions" class="header-buttons" />
|
||||
</span>
|
||||
</template>
|
||||
<slot />
|
||||
<div v-if="!loading">
|
||||
<slot />
|
||||
</div>
|
||||
</TabPage>
|
||||
</template>
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<Page v-if="!loading" :title="title" class="tab-page" v-bind="$attrs">
|
||||
<Page :title="title" class="tab-page" v-bind="$attrs">
|
||||
<template #headingRightSide>
|
||||
<slot name="headingRightSide" />
|
||||
</template>
|
||||
@@ -45,7 +45,7 @@
|
||||
<el-alert v-if="helpMessage" type="success">
|
||||
<span v-sanitize="helpMessage" class="announcement-main" />
|
||||
</el-alert>
|
||||
<transition appear mode="out-in" name="fade-transform">
|
||||
<transition v-if="!loading" appear mode="out-in" name="fade-transform">
|
||||
<slot>
|
||||
<keep-alive>
|
||||
<component :is="computeActiveComponent" />
|
||||
@@ -124,6 +124,13 @@ export default {
|
||||
return needActiveComponent
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
activeMenu: {
|
||||
handler(newValue) {
|
||||
this.iActiveMenu = newValue
|
||||
}
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.iActiveMenu = this.getPropActiveTab()
|
||||
this.loading = false
|
||||
@@ -132,14 +139,14 @@ export default {
|
||||
handleTabClick(tab) {
|
||||
this.$emit('tab-click', tab)
|
||||
this.iActiveMenu = tab.name
|
||||
this.$cookie.set('activeTab', tab.name, 1)
|
||||
localStorage.setItem('activeTab', tab.name)
|
||||
},
|
||||
getPropActiveTab() {
|
||||
let activeTab = ''
|
||||
|
||||
const preActiveTabs = [
|
||||
this.$route.query['tab'],
|
||||
this.$cookie.get('activeTab'),
|
||||
localStorage.getItem('activeTab'),
|
||||
this.activeMenu
|
||||
]
|
||||
|
||||
|
||||
@@ -110,14 +110,14 @@ export default [
|
||||
action: 'update'
|
||||
},
|
||||
hidden: true
|
||||
},
|
||||
{
|
||||
path: ':id',
|
||||
component: () => import('@/views/accounts/AccountTemplate/Detail/index.vue'),
|
||||
name: 'AccountTemplateDetail',
|
||||
meta: { title: i18n.t('AccountTemplate') },
|
||||
hidden: true
|
||||
}
|
||||
// {
|
||||
// path: ':id',
|
||||
// component: () => import('@/views/accounts/AccountTemplate/AccountTemplateDetail/index.vue'),
|
||||
// name: 'AccountTemplateDetail',
|
||||
// meta: { title: i18n.t('AccountTemplate') },
|
||||
// hidden: true
|
||||
// }
|
||||
]
|
||||
}
|
||||
]
|
||||
|
||||
@@ -25,7 +25,8 @@ export default [
|
||||
title: i18n.t('UserLoginACLs'),
|
||||
app: 'acls',
|
||||
resource: 'loginacl',
|
||||
disableOrgsChange: true
|
||||
disableOrgsChange: true,
|
||||
licenseRequired: true
|
||||
},
|
||||
children: [
|
||||
{
|
||||
|
||||
@@ -28,7 +28,7 @@ export default [
|
||||
},
|
||||
{
|
||||
path: 'create',
|
||||
component: () => import('@/views/accounts/AccountDiscover/TaskCreateUpdate'),
|
||||
component: () => import('@/views/accounts/AccountDiscover/AccountDiscoverTaskCreateUpdate.vue'),
|
||||
name: 'AccountDiscoverTaskCreate',
|
||||
hidden: true,
|
||||
meta: {
|
||||
@@ -50,7 +50,7 @@ export default [
|
||||
},
|
||||
{
|
||||
path: ':id/update',
|
||||
component: () => import('@/views/accounts/AccountDiscover/TaskCreateUpdate'),
|
||||
component: () => import('@/views/accounts/AccountDiscover/AccountDiscoverTaskCreateUpdate.vue'),
|
||||
name: 'AccountDiscoverTaskUpdate',
|
||||
hidden: true,
|
||||
meta: {
|
||||
@@ -62,7 +62,7 @@ export default [
|
||||
},
|
||||
{
|
||||
path: 'executions',
|
||||
component: () => import('@/views/accounts/AccountDiscover/TaskExecutionList.vue'),
|
||||
component: () => import('@/views/accounts/AccountDiscover/AccountDiscoverExecutionList.vue'),
|
||||
name: 'AccountDiscoverTaskExecutionList',
|
||||
hidden: true,
|
||||
meta: {
|
||||
|
||||
@@ -44,8 +44,9 @@ const mutations = {
|
||||
const actions = {
|
||||
// get user info
|
||||
getUrlMeta({ commit, state }, { url }) {
|
||||
const ignoreCache = url.includes('_meta_cache')
|
||||
const meta = state.metaMap[url]
|
||||
if (meta) {
|
||||
if (meta && !ignoreCache) {
|
||||
return new Promise((resolve, reject) => {
|
||||
resolve(meta)
|
||||
})
|
||||
|
||||
@@ -702,3 +702,7 @@ li.rmenu i.fa {
|
||||
div.el-loading-parent--relative {
|
||||
min-height: 150px;
|
||||
}
|
||||
|
||||
.el-drawer__header .drawer-title {
|
||||
color: var(--color-text-primary);
|
||||
}
|
||||
|
||||
@@ -78,6 +78,18 @@ export function replaceAllUUID(string, replacement = '*') {
|
||||
return string
|
||||
}
|
||||
|
||||
// 写个函数, id 设置到路径中,而不是 query 中, 确保已 / 结尾, 如果已 / 结尾,则不添加
|
||||
export function setUrlId(url, id) {
|
||||
const urlArray = url.split('?')
|
||||
const baseUrl = _.trimEnd(urlArray[0], '/')
|
||||
if (urlArray.length === 1) {
|
||||
url = `${baseUrl}/${id}/`
|
||||
} else {
|
||||
url = `${baseUrl}/${id}/?${urlArray[1]}`
|
||||
}
|
||||
return url
|
||||
}
|
||||
|
||||
export function setUrlParam(url, name, value) {
|
||||
const urlArray = url.split('?')
|
||||
if (urlArray.length === 1) {
|
||||
@@ -374,6 +386,16 @@ export function openNewWindow(url) {
|
||||
window.open(url, '_blank', params)
|
||||
}
|
||||
|
||||
export function getDrawerWidth() {
|
||||
const drawerWidth = localStorage.getItem('drawerWidth')
|
||||
if (drawerWidth && drawerWidth > 100 && drawerWidth < 2000) {
|
||||
return drawerWidth + 'px'
|
||||
}
|
||||
const width = window.innerWidth
|
||||
if (width >= 1500) return '1080px'
|
||||
return '90%'
|
||||
}
|
||||
|
||||
export class ObjectLocalStorage {
|
||||
constructor(key) {
|
||||
this.key = key
|
||||
|
||||
@@ -1,140 +1,26 @@
|
||||
<template>
|
||||
<div>
|
||||
<GenericListTable :header-actions="headerActions" :table-config="tableConfig" />
|
||||
<ReportDialog :visible.sync="visible" :url="reportUrl" />
|
||||
</div>
|
||||
<BaseExecutionList
|
||||
:automation-route="automationRoute"
|
||||
:detail-route="detailRoute"
|
||||
:resource="resource"
|
||||
:url="url"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import GenericListTable from '@/layout/components/GenericListTable/index.vue'
|
||||
import { openTaskPage } from '@/utils/jms'
|
||||
import { DetailFormatter } from '@/components/Table/TableFormatters'
|
||||
import ReportDialog from '@/components/Dialog/ReportDialog.vue'
|
||||
import BaseExecutionList from '@/views/accounts/Automation/BaseExecutionList.vue'
|
||||
|
||||
export default {
|
||||
name: 'AccountBackupExecutionList',
|
||||
components: {
|
||||
GenericListTable,
|
||||
ReportDialog
|
||||
},
|
||||
props: {
|
||||
object: {
|
||||
type: Object,
|
||||
required: false,
|
||||
default: () => ({})
|
||||
}
|
||||
BaseExecutionList
|
||||
},
|
||||
data() {
|
||||
const vm = this
|
||||
return {
|
||||
visible: false,
|
||||
reportUrl: '',
|
||||
tableConfig: {
|
||||
url: '/api/v1/accounts/account-backup-plan-executions/',
|
||||
columns: [
|
||||
'automation', 'backup_name', 'trigger',
|
||||
'date_start', 'date_finished', 'duration', 'actions'
|
||||
],
|
||||
columnsShow: {
|
||||
default: [
|
||||
'automation', 'backup_name', 'trigger',
|
||||
'date_start', 'date_finished', 'actions'
|
||||
]
|
||||
},
|
||||
columnsMeta: {
|
||||
automation: {
|
||||
label: this.$t('ID'),
|
||||
formatter: DetailFormatter,
|
||||
formatterArgs: {
|
||||
route: 'AccountBackupExecutionDetail',
|
||||
getRoute: ({ row }) => ({
|
||||
name: 'AccountBackupExecutionDetail',
|
||||
params: { id: row.id }
|
||||
}),
|
||||
getDrawerTitle: ({ row }) => row.id,
|
||||
getTitle: ({ row }) => row.id.slice(0, 8),
|
||||
drawer: true,
|
||||
can: this.$hasPerm('accounts.view_backupaccountexecution')
|
||||
}
|
||||
},
|
||||
backup_name: {
|
||||
label: this.$t('DisplayName'),
|
||||
formatter: DetailFormatter,
|
||||
formatterArgs: {
|
||||
drawer: true,
|
||||
getTitle: ({ row }) => row.automation.name,
|
||||
getDrawerTitle: ({ row }) => row.automation.name,
|
||||
getRoute: ({ row }) => ({
|
||||
name: 'AccountBackupDetail',
|
||||
params: { id: row.automation.id }
|
||||
})
|
||||
},
|
||||
id: ({ row }) => row.automation
|
||||
},
|
||||
duration: {
|
||||
label: this.$t('TimeDelta'),
|
||||
formatter: function(row) {
|
||||
return row.duration + 's'
|
||||
}
|
||||
},
|
||||
actions: {
|
||||
formatterArgs: {
|
||||
hasDelete: false,
|
||||
hasUpdate: false,
|
||||
hasClone: false,
|
||||
extraActions: [
|
||||
{
|
||||
name: 'log',
|
||||
type: 'primary',
|
||||
can: this.$hasPerm('accounts.view_backupaccountexecution'),
|
||||
title: this.$t('Log'),
|
||||
callback: function({ row }) {
|
||||
openTaskPage(row['id'])
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'report',
|
||||
title: this.$t('Report'),
|
||||
type: 'success',
|
||||
can: this.$hasPerm('accounts.view_backupaccountexecution'),
|
||||
callback: function({ row }) {
|
||||
vm.visible = true
|
||||
vm.reportUrl = `/api/v1/accounts/account-backup-plan-executions/${row.id}/report/`
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
headerActions: {
|
||||
searchConfig: {
|
||||
getUrlQuery: true,
|
||||
options: [
|
||||
{
|
||||
label: this.$t('TaskID'),
|
||||
value: 'automation_id'
|
||||
},
|
||||
{
|
||||
label: this.$t('DisplayName'),
|
||||
value: 'automation__name'
|
||||
}
|
||||
]
|
||||
},
|
||||
hasRefresh: true,
|
||||
hasRightActions: true,
|
||||
hasLeftActions: false,
|
||||
hasMoreActions: false,
|
||||
hasExport: false,
|
||||
hasImport: false,
|
||||
hasCreate: false
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
const plan_id = this.$route.query.plan_id
|
||||
if (plan_id !== undefined) {
|
||||
this.tableConfig.url = `${this.tableConfig.url}?plan_id=${plan_id}`
|
||||
url: '/api/v1/accounts/account-backup-plan-executions/',
|
||||
detailRoute: 'AccountBackupExecutionDetail',
|
||||
automationRoute: 'AccountBackupDetail',
|
||||
resource: 'backupaccountexecution'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -67,7 +67,7 @@ export default {
|
||||
can: vm.$hasPerm('accounts.view_changesecretexecution'),
|
||||
getRoute({ row }) {
|
||||
return {
|
||||
name: 'AccountChangeSecretList',
|
||||
name: 'AccountChangeSecretDetail',
|
||||
query: {
|
||||
tab: 'AccountChangeSecretExecutionList',
|
||||
automation_id: row.id
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<TwoCol>
|
||||
<template>
|
||||
<GenericListTable
|
||||
<DrawerListTable
|
||||
ref="listTable"
|
||||
:header-actions="headerActions"
|
||||
:table-config="tableConfig"
|
||||
@@ -15,7 +15,7 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import GenericListTable from '@/layout/components/GenericListTable/index.vue'
|
||||
import DrawerListTable from '@/components/Table/DrawerListTable/index.vue'
|
||||
import RelationCard from '@/components/Cards/RelationCard/index.vue'
|
||||
import AssetRelationCard from '@/components/Apps/AssetRelationCard/index.vue'
|
||||
import { DeleteActionFormatter, DetailFormatter } from '@/components/Table/TableFormatters'
|
||||
@@ -24,8 +24,7 @@ import TwoCol from '@/layout/components/Page/TwoColPage.vue'
|
||||
export default {
|
||||
name: 'AccountChangeSecretAsset',
|
||||
components: {
|
||||
TwoCol,
|
||||
GenericListTable, RelationCard, AssetRelationCard
|
||||
TwoCol, DrawerListTable, RelationCard, AssetRelationCard
|
||||
},
|
||||
props: {
|
||||
object: {
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import GenericListTable from '@/layout/components/GenericListTable/index.vue'
|
||||
import { GenericListTable } from '@/layout/components'
|
||||
import { ActionsFormatter, DetailFormatter } from '@/components/Table/TableFormatters'
|
||||
import { openTaskPage } from '@/utils/jms'
|
||||
import RecordViewSecret from '@/components/Apps/ChangeSecret/RecordViewSecret.vue'
|
||||
@@ -40,7 +40,7 @@ export default {
|
||||
can: this.$hasPerm('assets.view_asset'),
|
||||
getTitle: ({ row }) => row.asset.name,
|
||||
getDrawerTitle: ({ row }) => row.asset.name,
|
||||
getRoute({ row }) {
|
||||
getRoute: ({ row }) => {
|
||||
return {
|
||||
name: 'AssetDetail',
|
||||
params: { id: row.asset.id }
|
||||
@@ -56,7 +56,7 @@ export default {
|
||||
can: this.$hasPerm('accounts.view_account'),
|
||||
getTitle: ({ row }) => row.account.username,
|
||||
getDrawerTitle: ({ row }) => row.account.username,
|
||||
getRoute({ row }) {
|
||||
getRoute: ({ row }) => {
|
||||
return {
|
||||
name: 'AssetAccountDetail',
|
||||
params: { id: row.account.id }
|
||||
|
||||
@@ -1,157 +1,43 @@
|
||||
<template>
|
||||
<div>
|
||||
<GenericListTable :header-actions="headerActions" :table-config="tableConfig" />
|
||||
<ReportDialog :visible.sync="visible" :url="reportUrl" />
|
||||
</div>
|
||||
<BaseExecutionList
|
||||
:automation-route="automationRoute"
|
||||
:custom-actions="customActions"
|
||||
:detail-route="detailRoute"
|
||||
:resource="resource"
|
||||
:url="url"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import GenericListTable from '@/layout/components/GenericListTable/index.vue'
|
||||
import { openTaskPage } from '@/utils/jms'
|
||||
import { DetailFormatter } from '@/components/Table/TableFormatters'
|
||||
import ReportDialog from '@/components/Dialog/ReportDialog.vue'
|
||||
import BaseExecutionList from '@/views/accounts/Automation/BaseExecutionList.vue'
|
||||
|
||||
export default {
|
||||
name: 'AccountChangeSecretExecutionList',
|
||||
components: {
|
||||
ReportDialog,
|
||||
GenericListTable
|
||||
BaseExecutionList
|
||||
},
|
||||
data() {
|
||||
const vm = this
|
||||
const params = new URLSearchParams(this.$route.params).toString()
|
||||
return {
|
||||
visible: false,
|
||||
reportUrl: '',
|
||||
tableConfig: {
|
||||
url: '/api/v1/accounts/change-secret-executions/',
|
||||
columns: [
|
||||
'automation', 'change_secret_name', 'asset_amount', 'node_amount', 'status',
|
||||
'trigger', 'date_start', 'date_finished', 'actions'
|
||||
],
|
||||
columnsShow: {
|
||||
default: [
|
||||
'automation', 'change_secret_name', 'trigger', 'status',
|
||||
'date_start', 'date_finished', 'actions'
|
||||
]
|
||||
},
|
||||
columnsMeta: {
|
||||
automation: {
|
||||
label: this.$t('ID'),
|
||||
formatter: DetailFormatter,
|
||||
formatterArgs: {
|
||||
route: 'AccountChangeSecretExecutionDetail',
|
||||
getRoute: ({ row }) => ({
|
||||
name: 'AccountChangeSecretExecutionDetail',
|
||||
params: { id: row.id }
|
||||
}),
|
||||
getDrawerTitle: ({ row }) => row.id,
|
||||
getTitle: ({ row }) => row.id.slice(0, 8),
|
||||
drawer: true,
|
||||
can: this.$hasPerm('accounts.view_changesecretexecution')
|
||||
url: `/api/v1/accounts/change-secret-executions/?${params}`,
|
||||
detailRoute: 'AccountChangeSecretExecutionDetail',
|
||||
automationRoute: 'AccountChangeSecretDetail',
|
||||
resource: 'changesecretexecution',
|
||||
customActions: {
|
||||
name: 'record',
|
||||
title: this.$t('Record'),
|
||||
can: this.$hasPerm('accounts.view_changesecretrecord'),
|
||||
callback: function({ row }) {
|
||||
return this.$router.push({
|
||||
name: 'AccountChangeSecretList',
|
||||
query: {
|
||||
tab: 'ChangeSecretRecord',
|
||||
execution_id: row.id
|
||||
}
|
||||
},
|
||||
change_secret_name: {
|
||||
label: this.$t('DisplayName'),
|
||||
formatter: DetailFormatter,
|
||||
formatterArgs: {
|
||||
drawer: true,
|
||||
getDrawerTitle({ row }) {
|
||||
return row.automation.name
|
||||
},
|
||||
getTitle: ({ row }) => row.automation.name,
|
||||
getRoute: ({ row }) => ({
|
||||
name: 'AccountChangeSecretDetail',
|
||||
params: { id: row.automation.id }
|
||||
})
|
||||
},
|
||||
id: ({ row }) => row.automation
|
||||
},
|
||||
asset_amount: {
|
||||
label: this.$t('AssetsOfNumber'),
|
||||
formatter: function(row) {
|
||||
return <span>{row.snapshot.asset_amount}</span>
|
||||
}
|
||||
},
|
||||
node_amount: {
|
||||
label: this.$t('NodeOfNumber'),
|
||||
formatter: function(row) {
|
||||
return <span>{row.snapshot.node_amount}</span>
|
||||
}
|
||||
},
|
||||
status: {
|
||||
label: this.$t('Result')
|
||||
},
|
||||
actions: {
|
||||
formatterArgs: {
|
||||
hasDelete: false,
|
||||
hasUpdate: false,
|
||||
hasClone: false,
|
||||
extraActions: [
|
||||
{
|
||||
name: 'log',
|
||||
type: 'primary',
|
||||
can: this.$hasPerm('accounts.view_changesecretexecution'),
|
||||
title: this.$t('Log'),
|
||||
callback: function({ row }) {
|
||||
openTaskPage(row['id'])
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'report',
|
||||
title: this.$t('Report'),
|
||||
type: 'success',
|
||||
can: this.$hasPerm('accounts.view_changesecretexecution'),
|
||||
callback: function({ row }) {
|
||||
vm.visible = true
|
||||
vm.reportUrl = `/api/v1/accounts/change-secret-executions/${row.id}/report/`
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'record',
|
||||
title: this.$t('Record'),
|
||||
can: this.$hasPerm('accounts.view_changesecretrecord'),
|
||||
callback: function({ row }) {
|
||||
return this.$router.push({
|
||||
name: 'AccountChangeSecretList',
|
||||
query: {
|
||||
tab: 'ChangeSecretRecord',
|
||||
execution_id: row.id
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
headerActions: {
|
||||
searchConfig: {
|
||||
getUrlQuery: true,
|
||||
options: [
|
||||
{
|
||||
label: this.$t('TaskID'),
|
||||
value: 'automation_id'
|
||||
},
|
||||
{
|
||||
label: this.$t('DisplayName'),
|
||||
value: 'automation__name'
|
||||
}
|
||||
]
|
||||
},
|
||||
hasLeftActions: false,
|
||||
hasMoreActions: false,
|
||||
hasExport: false,
|
||||
hasImport: false,
|
||||
hasCreate: false
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
const automation_id = this.$route.query.automation_id
|
||||
if (automation_id !== undefined) {
|
||||
this.tableConfig.url = `${this.tableConfig.url}?automation_id=${automation_id}`
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -49,9 +49,18 @@ export default {
|
||||
{
|
||||
title: this.$t('Total'),
|
||||
body: {
|
||||
route: { name: 'AccountChangeSecret', query: { tab: 'AccountChangeSecretList' }},
|
||||
canDirect: true,
|
||||
count: this.data.total_count_change_secrets
|
||||
count: this.data.total_count_change_secrets,
|
||||
callback: () => {
|
||||
this.$eventBus.$emit('change-tab',
|
||||
{
|
||||
name: 'AccountChangeSecretList',
|
||||
payload: {
|
||||
days: this.days
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -73,9 +82,16 @@ export default {
|
||||
{
|
||||
title: this.$t('Total'),
|
||||
body: {
|
||||
route: { name: 'AccountChangeSecret', query: { tab: 'AccountChangeSecretExecutionList' }},
|
||||
canDirect: true,
|
||||
count: this.data.total_count_change_secret_executions
|
||||
count: this.data.total_count_change_secret_executions,
|
||||
callback: () => {
|
||||
this.$eventBus.$emit('change-tab', {
|
||||
name: 'AccountChangeSecretExecutionList',
|
||||
payload: {
|
||||
days: this.days
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
|
||||
@@ -29,12 +29,13 @@ export default {
|
||||
data() {
|
||||
const vm = this
|
||||
return {
|
||||
url: '/api/v1/accounts/change-secret-records/dashboard/',
|
||||
showViewSecretDialog: false,
|
||||
cardConfig: {
|
||||
title: this.$tc('ChangeSecretFailAccounts')
|
||||
title: vm.$tc('ChangeSecretFailAccounts')
|
||||
},
|
||||
tableConfig: {
|
||||
url: `/api/v1/accounts/change-secret-records/dashboard/?days=${this.days}`,
|
||||
url: vm.tableUrl(),
|
||||
columns: [
|
||||
'asset', 'account', 'date_finished', 'is_success', 'error', 'actions'
|
||||
],
|
||||
@@ -138,6 +139,17 @@ export default {
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
days() {
|
||||
this.$refs.HomeCard.$refs.ListTable.tableConfig.url = this.tableUrl()
|
||||
this.$refs.HomeCard.$refs.ListTable.reloadTable()
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
tableUrl() {
|
||||
return `/api/v1/accounts/change-secret-records/dashboard/?days=${this.days}`
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -107,6 +107,10 @@ export default {
|
||||
::v-deep #HomeCard .el-card.no-border {
|
||||
height: 100%;
|
||||
margin-bottom: unset !important;
|
||||
|
||||
.ListTable .el-pagination {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -45,6 +45,18 @@ export default {
|
||||
},
|
||||
computed: {
|
||||
...mapGetters(['hasValidLicense'])
|
||||
},
|
||||
mounted() {
|
||||
this.$eventBus.$on('change-tab', this.handleChangeTab)
|
||||
},
|
||||
beforeDestroy() {
|
||||
this.$eventBus.$off('change-tab', this.handleChangeTab)
|
||||
},
|
||||
methods: {
|
||||
handleChangeTab({ name, payload }) {
|
||||
this.config.activeMenu = name
|
||||
Object.assign(this.$route.params, { ...payload })
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
<template>
|
||||
<BaseExecutionList
|
||||
:automation-route="automationRoute"
|
||||
:detail-route="detailRoute"
|
||||
:resource="resource"
|
||||
:url="url"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import BaseExecutionList from '@/views/accounts/Automation/BaseExecutionList.vue'
|
||||
|
||||
export default {
|
||||
name: 'AccountDiscoverTaskExecutionList',
|
||||
components: {
|
||||
BaseExecutionList
|
||||
},
|
||||
props: {
|
||||
object: {
|
||||
type: Object,
|
||||
required: false,
|
||||
default: () => ({})
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
url: '/api/v1/accounts/gather-account-executions/',
|
||||
detailRoute: 'AccountDiscoverExecutionDetail',
|
||||
automationRoute: 'AccountDiscoverTaskDetail',
|
||||
resource: 'gatheraccountsexecution'
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -21,7 +21,7 @@ export default {
|
||||
data() {
|
||||
const vm = this
|
||||
return {
|
||||
createDrawer: () => import('@/views/accounts/AccountDiscover/TaskCreateUpdate.vue'),
|
||||
createDrawer: () => import('@/views/accounts/AccountDiscover/AccountDiscoverTaskCreateUpdate.vue'),
|
||||
detailDrawer: () => import('@/views/accounts/AccountDiscover/TaskDetail/index.vue'),
|
||||
showViewSecretDialog: false,
|
||||
showTableUpdateDrawer: false,
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
<script>
|
||||
import { GenericDetailPage, TabPage } from '@/layout/components'
|
||||
import Detail from './Detail.vue'
|
||||
import TaskExecutionList from '../TaskExecutionList.vue'
|
||||
import TaskExecutionList from '../AccountDiscoverExecutionList.vue'
|
||||
|
||||
export default {
|
||||
name: 'AccountDiscoverTaskDetail',
|
||||
|
||||
@@ -35,7 +35,7 @@ export default {
|
||||
title: this.$t('ExecutionHistory'),
|
||||
name: 'AccountDiscoverTaskExecutionList',
|
||||
hidden: !this.$hasPerm('accounts.view_gatheraccountsexecution'),
|
||||
component: () => import('@/views/accounts/AccountDiscover/TaskExecutionList.vue')
|
||||
component: () => import('@/views/accounts/AccountDiscover/AccountDiscoverExecutionList.vue')
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -1,164 +1,46 @@
|
||||
<template>
|
||||
<div>
|
||||
<GenericListTable
|
||||
ref="listTable"
|
||||
:detail-drawer="detailDrawer"
|
||||
:header-actions="headerActions"
|
||||
:table-config="tableConfig"
|
||||
/>
|
||||
<ReportDialog :url="reportUrl" :visible.sync="visible" />
|
||||
</div>
|
||||
<BaseExecutionList
|
||||
:automation-route="automationRoute"
|
||||
:resource-label="resourceLabel"
|
||||
:custom-actions="customActions"
|
||||
:detail-drawer="detailDrawer"
|
||||
:detail-route="detailRoute"
|
||||
:resource="resource"
|
||||
:url="url"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import GenericListTable from '@/layout/components/GenericListTable/index.vue'
|
||||
import { openTaskPage } from '@/utils/jms'
|
||||
import { DetailFormatter } from '@/components/Table/TableFormatters'
|
||||
import ReportDialog from '@/components/Dialog/ReportDialog'
|
||||
import BaseExecutionList from '@/views/accounts/Automation/BaseExecutionList.vue'
|
||||
|
||||
export default {
|
||||
name: 'AccountPushExecutionList',
|
||||
components: {
|
||||
GenericListTable,
|
||||
ReportDialog
|
||||
BaseExecutionList
|
||||
},
|
||||
data() {
|
||||
const vm = this
|
||||
return {
|
||||
visible: false,
|
||||
reportUrl: '',
|
||||
url: '/api/v1/accounts/push-account-executions/',
|
||||
automationRoute: 'AccountPushDetail',
|
||||
detailRoute: 'AccountPushExecutionDetail',
|
||||
resource: 'pushaccountexecution',
|
||||
resourceLabel: this.$t('AccountPushExecution'),
|
||||
detailDrawer: () => import('@/views/accounts/AccountPush/ExecutionDetail/index.vue'),
|
||||
tableConfig: {
|
||||
url: '/api/v1/accounts/push-account-executions/',
|
||||
columns: [
|
||||
'automation', 'push_user_name', 'asset_amount', 'node_amount', 'status',
|
||||
'trigger', 'date_start', 'date_finished', 'actions'
|
||||
],
|
||||
columnsShow: {
|
||||
default: [
|
||||
'automation', 'push_user_name', 'trigger', 'status',
|
||||
'date_start', 'date_finished', 'actions'
|
||||
]
|
||||
},
|
||||
columnsMeta: {
|
||||
automation: {
|
||||
label: this.$t('ID'),
|
||||
formatter: DetailFormatter,
|
||||
formatterArgs: {
|
||||
route: 'AccountPushExecutionDetail',
|
||||
getRoute: ({ row }) => ({
|
||||
name: 'AccountPushExecutionDetail',
|
||||
params: { id: row.id }
|
||||
}),
|
||||
getDrawerTitle: ({ row }) => row.id,
|
||||
getTitle: ({ row }) => row.id.slice(0, 8),
|
||||
drawer: true,
|
||||
can: this.$hasPerm('accounts.view_pushaccountexecution')
|
||||
customActions: {
|
||||
name: 'record',
|
||||
title: this.$t('Record'),
|
||||
can: this.$hasPerm('accounts.view_changesecretrecord'),
|
||||
callback: function({ row }) {
|
||||
return this.$router.push({
|
||||
name: 'AccountPush',
|
||||
query: {
|
||||
tab: 'AccountPushRecord',
|
||||
execution_id: row.id
|
||||
}
|
||||
},
|
||||
push_user_name: {
|
||||
label: this.$t('DisplayName'),
|
||||
formatter: DetailFormatter,
|
||||
formatterArgs: {
|
||||
drawer: true,
|
||||
getTitle: ({ row }) => row.automation?.name,
|
||||
getRoute: ({ row }) => ({
|
||||
name: 'AccountPushDetail',
|
||||
params: { id: row.automation.id }
|
||||
}),
|
||||
getDrawerTitle({ row }) {
|
||||
return row.automation?.name
|
||||
}
|
||||
},
|
||||
id: ({ row }) => row.automation
|
||||
},
|
||||
asset_amount: {
|
||||
label: this.$t('AssetsOfNumber'),
|
||||
formatter: function(row) {
|
||||
return <span>{row.snapshot.asset_amount}</span>
|
||||
}
|
||||
},
|
||||
node_amount: {
|
||||
label: this.$t('NodeOfNumber'),
|
||||
formatter: function(row) {
|
||||
return <span>{row.snapshot.node_amount}</span>
|
||||
}
|
||||
},
|
||||
status: {
|
||||
label: this.$t('Result')
|
||||
},
|
||||
actions: {
|
||||
formatterArgs: {
|
||||
hasDelete: false,
|
||||
hasUpdate: false,
|
||||
hasClone: false,
|
||||
extraActions: [
|
||||
{
|
||||
name: 'log',
|
||||
type: 'primary',
|
||||
can: this.$hasPerm('accounts.view_pushaccountexecution'),
|
||||
title: this.$t('Log'),
|
||||
callback: function({ row }) {
|
||||
openTaskPage(row['id'])
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'report',
|
||||
title: this.$t('Report'),
|
||||
can: this.$hasPerm('accounts.view_pushaccountexecution'),
|
||||
callback: function({ row }) {
|
||||
vm.visible = true
|
||||
vm.reportUrl = `/api/v1/accounts/push-account-executions/${row.id}/report/`
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'record',
|
||||
title: this.$t('Record'),
|
||||
can: this.$hasPerm('accounts.view_pushsecretrecord'),
|
||||
callback: function({ row }) {
|
||||
return this.$router.push({
|
||||
name: 'AccountPushList',
|
||||
query: {
|
||||
tab: 'AccountPushRecord',
|
||||
execution_id: row.id
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
headerActions: {
|
||||
searchConfig: {
|
||||
getUrlQuery: true,
|
||||
options: [
|
||||
{
|
||||
label: this.$t('TaskID'),
|
||||
value: 'automation_id'
|
||||
},
|
||||
{
|
||||
label: this.$t('DisplayName'),
|
||||
value: 'automation__name'
|
||||
}
|
||||
]
|
||||
},
|
||||
hasSearch: true,
|
||||
hasRefresh: true,
|
||||
hasRightActions: true,
|
||||
hasLeftActions: false,
|
||||
hasMoreActions: false,
|
||||
hasExport: false,
|
||||
hasImport: false
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
const automation_id = this.$route.query.automation_id
|
||||
if (automation_id !== undefined) {
|
||||
this.tableConfig.url = `${this.tableConfig.url}?automation_id=${automation_id}`
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
:create-drawer="createDrawer"
|
||||
:detail-drawer="detailDrawer"
|
||||
:header-actions="headerActions"
|
||||
:resource="$tc('AccountTemplate')"
|
||||
:table-config="tableConfig"
|
||||
/>
|
||||
<ViewSecret
|
||||
@@ -23,6 +22,7 @@ import { ActionsFormatter } from '@/components/Table/TableFormatters'
|
||||
import ViewSecret from '@/components/Apps/AccountListTable/ViewSecret'
|
||||
// import { DrawerListTable as ListTable } from '@/components'
|
||||
import ListTable from '@/components/Table/DrawerListTable'
|
||||
import { DetailFormatter } from '@/components/Table/TableFormatters'
|
||||
|
||||
export default {
|
||||
name: 'AccountTemplateTable',
|
||||
@@ -47,6 +47,20 @@ export default {
|
||||
default: ['name', 'username', 'secret_type', 'has_secret', 'privileged', 'actions']
|
||||
},
|
||||
columnsMeta: {
|
||||
name: {
|
||||
formatter: DetailFormatter,
|
||||
formatterArgs: {
|
||||
getTitle: ({ row }) => {
|
||||
return row.name
|
||||
},
|
||||
getRoute: ({ row }) => {
|
||||
return {
|
||||
name: 'AccountTemplateDetail',
|
||||
params: { id: row.id }
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
privileged: {
|
||||
width: '120px',
|
||||
formatterArgs: {
|
||||
|
||||
@@ -1,12 +1,15 @@
|
||||
<template>
|
||||
<div>
|
||||
<GenericListTable :header-actions="headerActions" :table-config="tableConfig" />
|
||||
<ReportDialog :visible.sync="visible" :url="reportUrl" />
|
||||
<DrawerListTable
|
||||
:header-actions="headerActions"
|
||||
:table-config="tableConfig"
|
||||
/>
|
||||
<ReportDialog :url="reportUrl" :visible.sync="visible" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import GenericListTable from '@/layout/components/GenericListTable/index.vue'
|
||||
import DrawerListTable from '@/components/Table/DrawerListTable/index.vue'
|
||||
|
||||
import { openTaskPage } from '@/utils/jms'
|
||||
import { DetailFormatter } from '@/components/Table/TableFormatters'
|
||||
@@ -18,13 +21,28 @@ export default {
|
||||
name: 'AccountDiscoverTaskExecutionList',
|
||||
components: {
|
||||
ReportDialog,
|
||||
GenericListTable
|
||||
DrawerListTable
|
||||
},
|
||||
props: {
|
||||
object: {
|
||||
url: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
detailRoute: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
automationRoute: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
resource: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
customActions: {
|
||||
type: Object,
|
||||
required: false,
|
||||
default: () => ({})
|
||||
default: null
|
||||
}
|
||||
},
|
||||
data() {
|
||||
@@ -36,7 +54,7 @@ export default {
|
||||
currentTemplate: null,
|
||||
drawerTitle: '',
|
||||
tableConfig: {
|
||||
url: '/api/v1/accounts/gather-account-executions/',
|
||||
url: this.url,
|
||||
columns: [
|
||||
'id', 'automation', 'status', 'trigger',
|
||||
'date_start', 'date_finished', 'actions'
|
||||
@@ -45,10 +63,11 @@ export default {
|
||||
id: {
|
||||
label: this.$t('ID'),
|
||||
formatter: DetailFormatter,
|
||||
width: '100px',
|
||||
formatterArgs: {
|
||||
route: 'AccountDiscoverExecutionDetail',
|
||||
route: this.detailRoute,
|
||||
getRoute: ({ row }) => ({
|
||||
name: 'AccountDiscoverExecutionDetail',
|
||||
name: this.detailRoute,
|
||||
params: { id: row.id }
|
||||
}),
|
||||
getTitle: ({ row }) => row.id.slice(0, 8),
|
||||
@@ -64,19 +83,21 @@ export default {
|
||||
width: '135px'
|
||||
},
|
||||
automation: {
|
||||
label: this.$t('Name'),
|
||||
label: this.$t('Task'),
|
||||
formatter: DetailFormatter,
|
||||
minWidth: '180px',
|
||||
formatterArgs: {
|
||||
getTitle: ({ row }) => row.automation.name,
|
||||
getTitle: ({ row }) => row.snapshot.name,
|
||||
getDrawerTitle: ({ row }) => row.snapshot.name,
|
||||
getRoute: ({ row }) => ({
|
||||
name: 'AccountDiscoverTaskDetail',
|
||||
name: this.automationRoute,
|
||||
params: { id: row.automation.id }
|
||||
}),
|
||||
getDrawerTitle: ({ row }) => row.automation.name,
|
||||
can: ({ row }) => row.automation?.id,
|
||||
drawer: true
|
||||
},
|
||||
id: ({ row }) => row.automation,
|
||||
can: this.$hasPerm('accounts.view_gatheraccountsexecution')
|
||||
can: this.$hasPerm('accounts.view_' + this.resource)
|
||||
},
|
||||
date_start: {
|
||||
width: null
|
||||
@@ -99,10 +120,11 @@ export default {
|
||||
name: 'report',
|
||||
title: this.$t('Report'),
|
||||
type: 'success',
|
||||
can: this.$hasPerm('accounts.view_gatheraccountsexecution'),
|
||||
can: this.$hasPerm('accounts.view_' + this.resource),
|
||||
callback: function({ row }) {
|
||||
vm.visible = true
|
||||
vm.reportUrl = `/api/v1/accounts/gather-account-executions/${row.id}/report/`
|
||||
const url = this.url.split('?')[0]
|
||||
vm.reportUrl = `${url}${row.id}/report/`
|
||||
}
|
||||
}
|
||||
]
|
||||
@@ -137,14 +159,19 @@ export default {
|
||||
if (automation_id !== undefined) {
|
||||
this.tableConfig.url = `${this.tableConfig.url}?automation_id=${automation_id}`
|
||||
}
|
||||
|
||||
const defaultExtraActions = this.tableConfig.columnsMeta.actions.formatterArgs.extraActions
|
||||
|
||||
if (this.customActions) {
|
||||
this.tableConfig.columnsMeta.actions.formatterArgs.extraActions = [
|
||||
...defaultExtraActions,
|
||||
this.customActions
|
||||
]
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
handleDetailCallback(row) {
|
||||
this.$route.params.id = row.id
|
||||
|
||||
this.$route.query.type = 'pam'
|
||||
|
||||
this.currentTemplate = 'AccountDiscoverExecutionDetail'
|
||||
this.showTableUpdateDrawer = true
|
||||
}
|
||||
}
|
||||
@@ -22,14 +22,12 @@ export default {
|
||||
formatter: DetailFormatter,
|
||||
formatterArgs: {
|
||||
drawer: true,
|
||||
can: this.$hasPerm('assets.view_asset'),
|
||||
getTitle: ({ row }) => row.asset.name,
|
||||
getDrawerTitle: ({ row }) => row.asset.name,
|
||||
getRoute: ({ row }) => ({
|
||||
name: 'AssetDetail',
|
||||
params: { id: row.asset.id },
|
||||
query: { tab: 'Basic' }
|
||||
})
|
||||
params: { id: row.asset.id }
|
||||
}),
|
||||
can: this.$hasPerm('assets.view_asset'),
|
||||
getTitle: ({ row }) => row.asset.name
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,21 +1,19 @@
|
||||
<template>
|
||||
<div>
|
||||
<GenericListTable ref="listTable" :header-actions="headerActions" :table-config="tableConfig" />
|
||||
<ReportDialog :url="reportUrl" :visible.sync="visible" />
|
||||
</div>
|
||||
<BaseExecutionList
|
||||
:automation-route="automationRoute"
|
||||
:detail-route="detailRoute"
|
||||
:resource="resource"
|
||||
:url="url"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import GenericListTable from '@/layout/components/GenericListTable/index.vue'
|
||||
import { openTaskPage } from '@/utils/jms'
|
||||
import { DetailFormatter } from '@/components/Table/TableFormatters'
|
||||
import ReportDialog from '@/components/Dialog/ReportDialog.vue'
|
||||
import BaseExecutionList from '@/views/accounts/Automation/BaseExecutionList.vue'
|
||||
|
||||
export default {
|
||||
name: 'CheckAccountExecutionList',
|
||||
components: {
|
||||
ReportDialog,
|
||||
GenericListTable
|
||||
BaseExecutionList
|
||||
},
|
||||
props: {
|
||||
object: {
|
||||
@@ -25,124 +23,11 @@ export default {
|
||||
}
|
||||
},
|
||||
data() {
|
||||
const vm = this
|
||||
return {
|
||||
visible: false,
|
||||
reportUrl: '',
|
||||
tableConfig: {
|
||||
url: '/api/v1/accounts/check-account-executions/',
|
||||
columns: [
|
||||
'automation', 'task_name', 'asset_amount',
|
||||
'node_amount', 'status', 'trigger',
|
||||
'date_start', 'date_finished', 'actions'
|
||||
],
|
||||
columnsShow: {
|
||||
default: [
|
||||
'automation', 'task_name', 'status',
|
||||
'date_start', 'date_finished', 'actions'
|
||||
]
|
||||
},
|
||||
columnsMeta: {
|
||||
automation: {
|
||||
label: this.$t('ID'),
|
||||
formatter: DetailFormatter,
|
||||
formatterArgs: {
|
||||
getRoute: ({ row }) => ({
|
||||
name: 'RiskHistoryExecutionDetail',
|
||||
params: { id: row.id }
|
||||
}),
|
||||
getTitle: ({ row }) => row.id.slice(0, 8),
|
||||
getDrawerTitle: ({ row }) => row.id,
|
||||
drawer: true,
|
||||
can: this.$hasPerm('accounts.view_checkaccountexecution')
|
||||
}
|
||||
},
|
||||
task_name: {
|
||||
label: this.$t('DisplayName'),
|
||||
formatter: DetailFormatter,
|
||||
formatterArgs: {
|
||||
drawer: true,
|
||||
getTitle: ({ row }) => row.automation.name,
|
||||
getRoute: ({ row }) => ({
|
||||
name: 'AccountCheckDetail',
|
||||
params: { id: row.automation.id }
|
||||
}),
|
||||
getDrawerTitle: ({ row }) => row.automation.name
|
||||
},
|
||||
id: ({ row }) => row.automation
|
||||
},
|
||||
asset_amount: {
|
||||
label: this.$t('AssetsOfNumber'),
|
||||
formatter: function(row) {
|
||||
return <span>{row.snapshot.asset_amount}</span>
|
||||
}
|
||||
},
|
||||
node_amount: {
|
||||
label: this.$t('NodeOfNumber'),
|
||||
formatter: function(row) {
|
||||
return <span>{row.snapshot.node_amount}</span>
|
||||
}
|
||||
},
|
||||
status: {
|
||||
label: this.$t('Result')
|
||||
},
|
||||
actions: {
|
||||
formatterArgs: {
|
||||
hasDelete: false,
|
||||
hasUpdate: false,
|
||||
hasClone: false,
|
||||
extraActions: [
|
||||
{
|
||||
name: 'log',
|
||||
type: 'primary',
|
||||
can: this.$hasPerm('accounts.view_checkaccountexecution'),
|
||||
title: this.$t('Log'),
|
||||
callback: function({ row }) {
|
||||
openTaskPage(row['id'])
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'report',
|
||||
title: this.$t('Report'),
|
||||
type: 'success',
|
||||
can: this.$hasPerm('accounts.view_checkaccountexecution'),
|
||||
callback: function({ row }) {
|
||||
vm.visible = true
|
||||
vm.reportUrl = `/api/v1/accounts/check-account-executions/${row.id}/report/`
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
headerActions: {
|
||||
searchConfig: {
|
||||
options: [
|
||||
{
|
||||
label: this.$t('TaskID'),
|
||||
value: 'automation_id'
|
||||
},
|
||||
{
|
||||
label: this.$t('DisplayName'),
|
||||
value: 'automation__name'
|
||||
}
|
||||
]
|
||||
},
|
||||
hasSearch: true,
|
||||
hasRefresh: true,
|
||||
hasRightActions: true,
|
||||
hasLeftActions: false,
|
||||
hasMoreActions: false,
|
||||
hasExport: false,
|
||||
hasImport: false
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
const automation_id = this.$route.query.automation_id
|
||||
if (automation_id !== undefined) {
|
||||
this.tableConfig.url = `${this.tableConfig.url}?automation_id=${automation_id}`
|
||||
url: '/api/v1/accounts/check-account-executions/',
|
||||
automationRoute: 'AccountCheckDetail',
|
||||
detailRoute: 'RiskHistoryExecutionDetail',
|
||||
resource: 'checkaccountexecution'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -44,7 +44,7 @@ export default {
|
||||
formatterArgs: {
|
||||
async: false,
|
||||
drawer: false,
|
||||
prevantClick: true
|
||||
preventClick: true
|
||||
}
|
||||
},
|
||||
nodes: {
|
||||
@@ -52,7 +52,7 @@ export default {
|
||||
formatterArgs: {
|
||||
async: false,
|
||||
drawer: false,
|
||||
prevantClick: true
|
||||
preventClick: true
|
||||
}
|
||||
},
|
||||
secret_strategy: {
|
||||
|
||||
@@ -113,6 +113,7 @@ export default {
|
||||
}
|
||||
},
|
||||
username: {
|
||||
label: this.$t('Account'),
|
||||
width: '120px'
|
||||
},
|
||||
risk: {
|
||||
|
||||
@@ -1,12 +1,33 @@
|
||||
import i18n from '@/i18n/i18n'
|
||||
const accountExistCache = new Map()
|
||||
|
||||
async function checkUserExist() {
|
||||
if (!this.row.username) {
|
||||
return false
|
||||
async function checkAccountExist(username, asset) {
|
||||
const cacheKey = `${username}-${asset}`
|
||||
if (accountExistCache.has(cacheKey)) {
|
||||
return accountExistCache.get(cacheKey)
|
||||
}
|
||||
const url = `/api/v1/accounts/accounts/?username=${encodeURIComponent(this.row.username)}&asset=${this.row.asset.id}`
|
||||
const url = `/api/v1/accounts/accounts/?username=${encodeURIComponent(username)}&asset=${asset}`
|
||||
const data = await this.$axios.get(url)
|
||||
return data.length > 0
|
||||
const result = data.length > 0
|
||||
accountExistCache.set(cacheKey, result)
|
||||
return result
|
||||
}
|
||||
|
||||
async function checkAccountsExist() {
|
||||
// 批量选择,所有都存在返回 true
|
||||
if (this.rows.length > 0) {
|
||||
for (const row of this.rows) {
|
||||
if (!await checkAccountExist.call(this, row.username, row.asset.id)) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
// 单个选择
|
||||
if (this.row.username) {
|
||||
return await checkAccountExist.call(this, this.row.username, this.row.asset.id)
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
export const riskActions = [
|
||||
@@ -30,7 +51,7 @@ export const riskActions = [
|
||||
label: i18n.t('AddAccount'),
|
||||
has: ['new_found'],
|
||||
disabled: async function() {
|
||||
return await checkUserExist.call(this)
|
||||
return await checkAccountsExist.call(this)
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -38,15 +59,26 @@ export const riskActions = [
|
||||
label: i18n.t('AddAccountAfterChangingPassword'),
|
||||
has: async function() {
|
||||
const risks = ['new_found', 'long_time_password', 'password_expired']
|
||||
return risks.includes(this.row.risk.value) && !await checkUserExist.call(this)
|
||||
return risks.includes(this.row.risk.value) && !await checkAccountsExist.call(this)
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'change_password',
|
||||
label: i18n.t('ChangePassword'),
|
||||
has: async function() {
|
||||
const risks = ['long_time_password', 'weak_password', 'password_expired', 'leaked_password', 'repeated_password']
|
||||
return risks.includes(this.row.risk.value) && await checkUserExist.call(this)
|
||||
const risks = [
|
||||
'long_time_password', 'weak_password', 'password_expired',
|
||||
'leaked_password', 'repeated_password'
|
||||
]
|
||||
return risks.includes(this.row.risk.value) && await checkAccountsExist.call(this)
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'delete_account',
|
||||
label: i18n.t('DeleteAccount'),
|
||||
has: async function() {
|
||||
const risks = ['account_deleted']
|
||||
return risks.includes(this.row.risk.value) && await checkAccountsExist.call(this)
|
||||
}
|
||||
},
|
||||
// {
|
||||
|
||||
@@ -164,7 +164,6 @@ export default {
|
||||
data
|
||||
)
|
||||
} catch (e) {
|
||||
row.status = { value: '4', label: this.$t('Failed') }
|
||||
this.$emit('processDone', { index: i, row })
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -32,12 +32,12 @@ export default {
|
||||
title: this.$t('Basic'),
|
||||
name: 'AccountPushExecutionInfo',
|
||||
hidden: () => !this.$hasPerm('accounts.view_pushaccountexecution')
|
||||
},
|
||||
{
|
||||
title: this.$t('TaskList'),
|
||||
name: 'AccountPushExecutionTaskList',
|
||||
hidden: () => !this.$hasPerm('accounts.view_changesecretrecord')
|
||||
}
|
||||
// {
|
||||
// title: this.$t('TaskList'),
|
||||
// name: 'AccountPushExecutionTaskList',
|
||||
// hidden: () => !this.$hasPerm('accounts.view_changesecretrecord')
|
||||
// }
|
||||
],
|
||||
getTitle: this.getExecutionTitle
|
||||
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
import { toSafeLocalDateStr } from '@/utils/time'
|
||||
import { ActionsFormatter, DetailFormatter, DiscoverConfirmFormatter } from '@/components/Table/TableFormatters'
|
||||
|
||||
export const statusMap = {
|
||||
pending: '0',
|
||||
confirmed: '1',
|
||||
ignored: '2'
|
||||
}
|
||||
export const gatherAccountTableConfig = (vm, url) => {
|
||||
if (!url) {
|
||||
url = '/api/v1/accounts/gathered-accounts/'
|
||||
@@ -37,6 +41,7 @@ export const gatherAccountTableConfig = (vm, url) => {
|
||||
}
|
||||
},
|
||||
username: {
|
||||
label: vm.$t('Account'),
|
||||
formatter: DetailFormatter,
|
||||
formatterArgs: {
|
||||
can: true,
|
||||
@@ -70,9 +75,9 @@ export const gatherAccountTableConfig = (vm, url) => {
|
||||
confirm: ({ row }) => {
|
||||
vm.$axios.put(
|
||||
`/api/v1/accounts/gathered-accounts/status/`,
|
||||
{ status: 'confirmed', ids: [row.id] }
|
||||
{ status: statusMap.confirmed, ids: [row.id] }
|
||||
).then(res => {
|
||||
row.status = 'confirmed'
|
||||
row.status = statusMap.confirmed
|
||||
}).catch(() => {
|
||||
row.status = vm.$t('Error')
|
||||
})
|
||||
@@ -80,9 +85,9 @@ export const gatherAccountTableConfig = (vm, url) => {
|
||||
ignore: ({ row }) => {
|
||||
vm.$axios.put(
|
||||
`/api/v1/accounts/gathered-accounts/status/`,
|
||||
{ status: 'ignored', ids: [row.id] }
|
||||
{ status: statusMap.ignored, ids: [row.id] }
|
||||
).then(res => {
|
||||
row.status = 'ignored'
|
||||
row.status = statusMap.ignored
|
||||
}).catch(() => {
|
||||
row.status = vm.$t('Error')
|
||||
})
|
||||
@@ -138,7 +143,7 @@ export const gatherAccountHeaderActions = (vm) => {
|
||||
})
|
||||
vm.$axios.put(
|
||||
`/api/v1/accounts/gathered-accounts/status/`,
|
||||
{ ids: ids, status: 'confirmed' }
|
||||
{ ids: ids, status: statusMap.confirmed }
|
||||
).then(() => {
|
||||
vm.$message.success(vm.$tc('SyncSuccessMsg'))
|
||||
}).catch(err => {
|
||||
|
||||
@@ -54,12 +54,12 @@ export default {
|
||||
'name', 'user_display',
|
||||
{
|
||||
key: vm.$t('IpGroup'),
|
||||
value: () => vm.object.rules.ip_group.toString()
|
||||
value: vm.object.rules.ip_group.join(', ')
|
||||
},
|
||||
'dataVal', 'action_display', 'priority', 'date_created', 'created_by',
|
||||
{
|
||||
key: vm.$t('LoginConfirmUser'),
|
||||
value: () => vm.object.reviewers.map(item => item.name).join(', ')
|
||||
value: vm.object.reviewers.map(item => item.name).join(', ')
|
||||
},
|
||||
'comment'
|
||||
]
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
<ListTable
|
||||
ref="listTable"
|
||||
:create-drawer="createDrawer"
|
||||
:detail-drawer="detailDrawer"
|
||||
:header-actions="headerActions"
|
||||
:resource="$t('UserLoginACL')"
|
||||
:table-config="tableConfig"
|
||||
@@ -23,6 +24,8 @@ export default {
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
createDrawer: () => import('./UserLoginACLCreateUpdate.vue'),
|
||||
detailDrawer: () => import('./UserDetail/index.vue'),
|
||||
tableConfig: {
|
||||
url: this.url,
|
||||
columnsExclude: ['rules', 'users'],
|
||||
@@ -63,8 +66,7 @@ export default {
|
||||
hasImport: false,
|
||||
hasMoreActions: false,
|
||||
createRoute: 'UserLoginACLCreate'
|
||||
},
|
||||
createDrawer: () => import('./UserLoginACLCreateUpdate.vue')
|
||||
}
|
||||
}
|
||||
},
|
||||
activated() {
|
||||
|
||||
@@ -44,7 +44,6 @@ export default {
|
||||
}
|
||||
},
|
||||
data() {
|
||||
const vm = this
|
||||
return {
|
||||
loading: true,
|
||||
platform: {},
|
||||
@@ -68,16 +67,15 @@ export default {
|
||||
fieldsMeta: {},
|
||||
performSubmit(validValues) {
|
||||
let url = this.url
|
||||
const { id = '', action } = vm.meta
|
||||
const { id = '' } = this.$route.params
|
||||
const values = _.cloneDeep(validValues)
|
||||
|
||||
let submitMethod = id ? 'put' : 'post'
|
||||
const submitMethod = id ? 'put' : 'post'
|
||||
|
||||
if (values.nodes && values.nodes.length === 0) {
|
||||
delete values['nodes']
|
||||
}
|
||||
|
||||
if (action === 'update') {
|
||||
if (submitMethod === 'put') {
|
||||
url = getUpdateObjURL(url, id)
|
||||
delete values['accounts']
|
||||
} else {
|
||||
@@ -87,12 +85,6 @@ export default {
|
||||
return item
|
||||
})
|
||||
}
|
||||
|
||||
if (vm.meta?.payload === 'pam_asset_clone' || vm.meta.row?.payload === 'pam_asset_clone') {
|
||||
submitMethod = 'post'
|
||||
url = this.url
|
||||
}
|
||||
|
||||
return this.$axios[submitMethod](url, values)
|
||||
}
|
||||
}
|
||||
@@ -104,7 +96,6 @@ export default {
|
||||
methods: {
|
||||
async init() {
|
||||
try {
|
||||
await this.getMeta()
|
||||
await this.genConfig()
|
||||
await this.setInitial()
|
||||
await this.setPlatformConstrains()
|
||||
@@ -114,11 +105,11 @@ export default {
|
||||
},
|
||||
async genConfig() {
|
||||
const { addFields, addFieldsMeta, defaultConfig } = this
|
||||
defaultConfig.fieldsMeta = assetFieldsMeta(this, this.meta.type)
|
||||
defaultConfig.fieldsMeta = assetFieldsMeta(this, this.$route.query.type)
|
||||
let url = this.url
|
||||
const { id = '' } = this.meta
|
||||
if (this.meta.platform && !id) {
|
||||
url = setUrlParam(url, 'platform', this.meta.platform)
|
||||
const { id = '', platform } = this.$route.query
|
||||
if (platform && !id) {
|
||||
url = setUrlParam(url, 'platform', platform)
|
||||
}
|
||||
// 过滤类型为:null, undefined 的元素
|
||||
defaultConfig.fields = defaultConfig.fields.filter(Boolean)
|
||||
@@ -141,31 +132,18 @@ export default {
|
||||
}
|
||||
this.iConfig = config
|
||||
},
|
||||
async getMeta() {
|
||||
let meta = await this.$store.dispatch('common/getDrawerActionMeta')
|
||||
if (!meta || !meta.action) {
|
||||
meta = {
|
||||
action: 'create',
|
||||
platform: this.$route.query.platform || '',
|
||||
type: this.$route.query.type || '',
|
||||
category: this.$route.query.category || '',
|
||||
node: this.$route.query.node || this.$route.query.node_id || ''
|
||||
}
|
||||
}
|
||||
this.meta = meta
|
||||
},
|
||||
async setInitial() {
|
||||
const { defaultConfig } = this
|
||||
const { node, platform } = this.meta
|
||||
const { node, platform } = this.$route.query
|
||||
const nodesInitial = node ? [node] : []
|
||||
const platformId = this.changePlatformID ? this.changePlatformID : (platform || 'Linux')
|
||||
const platformId = this.changePlatformID || this.$route.query.platform || (platform || 'Linux')
|
||||
const url = `/api/v1/assets/platforms/${platformId}/`
|
||||
this.platform = await this.$axios.get(url)
|
||||
const initial = {
|
||||
labels: [],
|
||||
is_active: true,
|
||||
nodes: nodesInitial,
|
||||
platform: parseInt(platformId),
|
||||
platform: parseInt(this.platform.id),
|
||||
protocols: []
|
||||
}
|
||||
if (this.updateInitial) {
|
||||
|
||||
@@ -110,7 +110,7 @@ export default {
|
||||
},
|
||||
computed: {
|
||||
refTable() {
|
||||
return this.$refs.listTable.$refs.dataTable.$refs.dataTable
|
||||
return this.$refs.listTable.$refs.ListTable.$refs.dataTable.$refs.dataTable
|
||||
},
|
||||
iVisible: {
|
||||
get() {
|
||||
|
||||
@@ -78,7 +78,3 @@ export default {
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
|
||||
@@ -57,16 +57,26 @@
|
||||
:visible.sync="templateDialogVisible"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<Drawer
|
||||
:title="$t('Account')"
|
||||
:component="drawerComponent"
|
||||
:has-footer="false"
|
||||
:visible.sync="drawerVisible"
|
||||
class="detail-drawer"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import AddAccountDialog from './AddAccountDialog'
|
||||
import Drawer from '@/components/Drawer/index.vue'
|
||||
import AccountTemplateDialog from './AccountTemplateDialog'
|
||||
|
||||
export default {
|
||||
name: 'AssetAccounts',
|
||||
components: {
|
||||
Drawer,
|
||||
AddAccountDialog,
|
||||
AccountTemplateDialog
|
||||
},
|
||||
@@ -92,10 +102,11 @@ export default {
|
||||
accounts: accounts,
|
||||
drawerRefName: null,
|
||||
account: {},
|
||||
pamDrawerShow: false,
|
||||
drawerVisible: false,
|
||||
initial: false,
|
||||
addAccountDialogVisible: false,
|
||||
templateDialogVisible: false
|
||||
templateDialogVisible: false,
|
||||
drawerComponent: () => import('@/views/assets/Asset/AssetDetail')
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
@@ -156,13 +167,11 @@ export default {
|
||||
return
|
||||
}
|
||||
|
||||
this.$router.push({
|
||||
name: 'AssetDetail',
|
||||
params: { id: assetId },
|
||||
query: {
|
||||
tab: 'Account'
|
||||
}
|
||||
this.$store.dispatch('common/setDrawerActionMeta', {
|
||||
action: 'detail', row: {}, col: {}, id: assetId
|
||||
})
|
||||
|
||||
this.drawerVisible = true
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -242,4 +251,13 @@ export default {
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.detail-drawer {
|
||||
::v-deep {
|
||||
.el-drawer__header {
|
||||
border-bottom: none;
|
||||
padding-bottom: 1px;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -59,7 +59,7 @@ export default {
|
||||
return {
|
||||
title: this.$t('Test'),
|
||||
templateDialogVisible: false,
|
||||
columnsDefault: ['name', 'username', 'asset'],
|
||||
columnsDefault: ['name', 'username', 'asset', 'connect'],
|
||||
headerExtraActions: [
|
||||
{
|
||||
name: this.$t('AccountTemplate'),
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import ListTable from '@/components/Table/ListTable'
|
||||
import { DrawerListTable as ListTable } from '@/components'
|
||||
import { GenericListTableDialog } from '@/layout/components'
|
||||
import { DetailFormatter } from '@/components/Table/TableFormatters'
|
||||
import PermUserGroupCard from './components/PermUserGroupCard'
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
<script>
|
||||
import BaseList from './components/BaseList'
|
||||
import { ActionsFormatter } from '@/components/Table/TableFormatters'
|
||||
import GatewayDialog from '@/components/Apps/GatewayDialog'
|
||||
import GatewayDialog from '@/components/Apps/GatewayTestDialog'
|
||||
import { openTaskPage } from '@/utils/jms'
|
||||
|
||||
export default {
|
||||
|
||||
@@ -43,7 +43,7 @@
|
||||
import ListTable from '@/components/Table/DrawerListTable'
|
||||
import AssetBulkUpdateDialog from './AssetBulkUpdateDialog'
|
||||
import PlatformDialog from '../components/PlatformDialog'
|
||||
import GatewayDialog from '@/components/Apps/GatewayDialog'
|
||||
import GatewayDialog from '@/components/Apps/GatewayTestDialog'
|
||||
import AccountDiscoverDialog from './AccountDiscoverDialog.vue'
|
||||
import AccountCreateUpdate from '@/components/Apps/AccountListTable/AccountCreateUpdate.vue'
|
||||
import { getDefaultConfig } from './const'
|
||||
@@ -121,7 +121,7 @@ export default {
|
||||
]
|
||||
const createAction = {
|
||||
name: 'create',
|
||||
title: 'Create',
|
||||
title: this.$t('Create'),
|
||||
type: 'primary',
|
||||
icon: '',
|
||||
split: true,
|
||||
@@ -215,23 +215,19 @@ export default {
|
||||
},
|
||||
methods: {
|
||||
async updateOrCloneAsset(row, action) {
|
||||
if (action === 'update') {
|
||||
this.$route.params.id = row.id
|
||||
}
|
||||
const meta = {
|
||||
action: action,
|
||||
id: row.id,
|
||||
this.createDrawer = this.drawer[row.category.value]
|
||||
|
||||
const query = {
|
||||
platform: row.platform.id,
|
||||
type: row.type.value,
|
||||
category: row.category.value,
|
||||
row: row,
|
||||
payload: row.payload
|
||||
category: row.category.value
|
||||
}
|
||||
await this.$store.dispatch('common/setDrawerActionMeta', meta)
|
||||
this.createDrawer = this.drawer[row.category.value]
|
||||
setTimeout(() => {
|
||||
this.$refs.ListTable.showDrawer(action)
|
||||
}, 100)
|
||||
|
||||
if (action === 'clone') {
|
||||
return this.$refs.ListTable.onClone({ row, query })
|
||||
}
|
||||
|
||||
this.$refs.ListTable.onUpdate({ row, query })
|
||||
},
|
||||
createAsset(platform) {
|
||||
this.showPlatform = false
|
||||
@@ -242,15 +238,8 @@ export default {
|
||||
category: platform.category.value,
|
||||
node: this.$route.query?.node || this.$route.query?.node_id || ''
|
||||
}
|
||||
for (const key in createProps) {
|
||||
this.$route.query[key] = createProps[key]
|
||||
}
|
||||
this.$store.dispatch('common/setDrawerActionMeta', {
|
||||
action: 'create',
|
||||
...createProps
|
||||
}).then(() => {
|
||||
this.$refs.ListTable.showDrawer('create')
|
||||
})
|
||||
this.$log.debug('createProps', createProps)
|
||||
this.$refs.ListTable.onCreate({ query: createProps })
|
||||
},
|
||||
handleAssetBulkUpdate() {
|
||||
this.updateSelectedDialogSetting.visible = false
|
||||
|
||||
@@ -194,7 +194,7 @@ export function getDefaultConfig(vm) {
|
||||
formatter: ActionsFormatter,
|
||||
formatterArgs: {
|
||||
onUpdate: ({ row }) => onAction(row, 'Update'),
|
||||
onClone: ({ row }) => onAction({ ...row, payload: 'pam_asset_clone' }, 'Clone'),
|
||||
onClone: ({ row }) => onAction(row, 'Clone'),
|
||||
performDelete: ({ row }) => {
|
||||
const id = row.id
|
||||
const url = `/api/v1/assets/assets/${id}/`
|
||||
@@ -235,7 +235,7 @@ export function getDefaultConfig(vm) {
|
||||
divided: true,
|
||||
can: ({ row }) => !vm.$store.getters.currentOrgIsRoot,
|
||||
callback: ({ row }) => {
|
||||
vm.asset.id = row.id
|
||||
vm.asset = row
|
||||
vm.showAddDialog = true
|
||||
}
|
||||
},
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
/>
|
||||
<SyncDialog
|
||||
v-if="onlineSyncVisible"
|
||||
:object="object"
|
||||
:visible.sync="onlineSyncVisible"
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -120,9 +120,6 @@ export default {
|
||||
action: 'sync_task', account_id: this.object.id
|
||||
}))
|
||||
}
|
||||
this.ws.onclose = () => {
|
||||
this.$emit('update:visible', false)
|
||||
}
|
||||
this.ws.onerror = () => {
|
||||
this.$message.error(this.$tc('ConnectWebSocketError'))
|
||||
}
|
||||
|
||||
@@ -9,7 +9,6 @@
|
||||
:title="$tc('CloudSyncConfig')"
|
||||
:visible.sync="iVisible"
|
||||
v-bind="$attrs"
|
||||
width="1051px"
|
||||
v-on="$listeners"
|
||||
>
|
||||
<el-row :gutter="5" style="padding: 10px">
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<div class="cloud-select-wrap">
|
||||
<el-row :gutter="12">
|
||||
<el-col v-for="p in providers" :key="p.name" :style="p.imageCSS ? p.imageCSS : ''">
|
||||
<el-col v-for="p in providers" :key="p.name">
|
||||
<el-card
|
||||
:body-style="{ display: 'flex', alignItems: 'center', justifyContent: 'flex-start' }"
|
||||
:class="selected === p.name ? 'active': ''"
|
||||
@@ -79,7 +79,7 @@ export default {
|
||||
|
||||
<style lang='scss' scoped>
|
||||
.buttons {
|
||||
margin-top: 10px;
|
||||
margin-top: 30px;
|
||||
}
|
||||
|
||||
.cloud-select-wrap {
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
:close-on-press-escape="false"
|
||||
:destroy-on-close="true"
|
||||
:show-buttons="false"
|
||||
:show-close="false"
|
||||
:title="$tc('SyncOnline')"
|
||||
:visible.sync="iVisible"
|
||||
v-on="$listeners"
|
||||
|
||||
@@ -19,7 +19,7 @@ export const volcengine = 'volcengine'
|
||||
|
||||
export const qingcloud_private = 'qingcloud_private'
|
||||
export const huaweicloud_private = 'huaweicloud_private'
|
||||
export const state_private = 'state_private'
|
||||
export const ctyun_private = 'ctyun_private'
|
||||
export const openstack = 'openstack'
|
||||
export const zstack = 'zstack'
|
||||
export const nutanix = 'nutanix'
|
||||
@@ -37,7 +37,7 @@ export const publicCloudProviders = [
|
||||
]
|
||||
|
||||
export const privateCloudProviders = [
|
||||
vmware, qingcloud_private, huaweicloud_private, state_private,
|
||||
vmware, qingcloud_private, huaweicloud_private, ctyun_private,
|
||||
openstack, zstack, nutanix, fc, scp, apsara_stack
|
||||
]
|
||||
|
||||
@@ -168,9 +168,9 @@ export const ACCOUNT_PROVIDER_ATTRS_MAP = {
|
||||
attrs: ['api_endpoint', 'username', 'password'],
|
||||
image: require('@/assets/img/cloud/huawei.svg')
|
||||
},
|
||||
[state_private]: {
|
||||
name: state_private,
|
||||
title: i18n.t('StatePrivate'),
|
||||
[ctyun_private]: {
|
||||
name: ctyun_private,
|
||||
title: i18n.t('CTYunPrivate'),
|
||||
attrs: ['access_key_id', 'access_key_secret', 'api_endpoint', 'cert_file', 'key_file'],
|
||||
image: require('@/assets/img/cloud/state.svg')
|
||||
},
|
||||
@@ -191,7 +191,7 @@ export const ACCOUNT_PROVIDER_ATTRS_MAP = {
|
||||
title: i18n.t('LAN'),
|
||||
attrs: ['ip_group', 'test_port', 'test_timeout', 'hostname_prefix'],
|
||||
image: require('@/assets/img/cloud/lan.svg'),
|
||||
imageCSS: { height: '250px' }
|
||||
imageCSS: {}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import BaseList from '../../Asset/AssetList/components/BaseList'
|
||||
import BaseList from '@/views/assets/Asset/AssetList/components/BaseList'
|
||||
import AddAssetDialog from '@/views/assets/Domain/components/AddAssetDialog.vue'
|
||||
import TwoCol from '@/layout/components/Page/TwoColPage.vue'
|
||||
|
||||
@@ -60,9 +60,13 @@ export default {
|
||||
name: 'AddAsset',
|
||||
title: this.$t('Add'),
|
||||
type: 'primary',
|
||||
can: !this.$store.getters.currentOrgIsRoot,
|
||||
callback: () => {
|
||||
this.$route.params.id = this.object.id
|
||||
this.addAssetSetting.addAssetDialogVisible = true
|
||||
setTimeout(() => {
|
||||
this.$route.params.id = null
|
||||
}, 500)
|
||||
}
|
||||
}
|
||||
]
|
||||
@@ -100,6 +104,7 @@ export default {
|
||||
methods: {
|
||||
handleAddAssetDialogClose() {
|
||||
this.addAssetSetting.addAssetDialogVisible = false
|
||||
this.$route.params.id = null
|
||||
this.reloadTable()
|
||||
},
|
||||
removeAsset(rows) {
|
||||
|
||||
@@ -5,18 +5,18 @@
|
||||
:create-drawer="createDrawer"
|
||||
:detail-drawer="detailDrawer"
|
||||
:header-actions="headerActions"
|
||||
:table-config="tableConfig"
|
||||
:resource="$tc('Gateway')"
|
||||
:table-config="tableConfig"
|
||||
/>
|
||||
<GatewayDialog
|
||||
:cell="cell"
|
||||
:port="port"
|
||||
:visible.sync="visible"
|
||||
<GatewayTestDialog
|
||||
:cell="testConfig.cell"
|
||||
:port="testConfig.port"
|
||||
:visible.sync="testConfig.visible"
|
||||
/>
|
||||
<AddGatewayDialog
|
||||
v-if="AddGatewaySetting.addGatewayDialogVisible"
|
||||
v-if="addGatewaySetting.addGatewayDialogVisible"
|
||||
:object="transObject"
|
||||
:setting="AddGatewaySetting"
|
||||
:setting="addGatewaySetting"
|
||||
@close="handleAddGatewayDialogClose"
|
||||
/>
|
||||
</TwoCol>
|
||||
@@ -24,7 +24,7 @@
|
||||
|
||||
<script>
|
||||
import { GenericListTable } from '@/layout/components'
|
||||
import GatewayDialog from '@/components/Apps/GatewayDialog'
|
||||
import GatewayTestDialog from '@/components/Apps/GatewayTestDialog'
|
||||
import { connectivityMeta } from '@/components/Apps/AccountListTable/const'
|
||||
import { ArrayFormatter, ChoicesFormatter, DetailFormatter, TagsFormatter } from '@/components/Table/TableFormatters'
|
||||
import AddGatewayDialog from '@/views/assets/Domain/components/AddGatewayDialog'
|
||||
@@ -34,7 +34,7 @@ export default {
|
||||
components: {
|
||||
TwoCol,
|
||||
GenericListTable,
|
||||
GatewayDialog,
|
||||
GatewayTestDialog,
|
||||
AddGatewayDialog
|
||||
},
|
||||
props: {
|
||||
@@ -51,6 +51,11 @@ export default {
|
||||
createDrawer: () => import('@/views/assets/Domain/DomainDetail/GatewayCreateUpdate.vue'),
|
||||
detailDrawer: () => import('@/views/assets/Asset/AssetDetail'),
|
||||
transObject: {},
|
||||
testConfig: {
|
||||
port: 0,
|
||||
visible: false,
|
||||
cell: ''
|
||||
},
|
||||
tableConfig: {
|
||||
url: `/api/v1/assets/gateways/?domain=${this.object.id}`,
|
||||
columnsExclude: [
|
||||
@@ -133,20 +138,19 @@ export default {
|
||||
can: this.$hasPerm('assets.test_assetconnectivity') && !this.$store.getters.currentOrgIsRoot,
|
||||
title: this.$t('TestConnection'),
|
||||
callback: function(val) {
|
||||
this.visible = true
|
||||
vm.testConfig.visible = true
|
||||
const port = val.row.protocols.find(item => item.name === 'ssh').port
|
||||
if (!port) {
|
||||
return this.$message.error(this.$tc('BadRequestErrorMsg'))
|
||||
} else {
|
||||
this.port = port
|
||||
this.cell = val.row.id
|
||||
vm.testConfig.port = port
|
||||
vm.testConfig.cell = val.row.id
|
||||
}
|
||||
}.bind(this)
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
},
|
||||
headerActions: {
|
||||
@@ -170,6 +174,7 @@ export default {
|
||||
{
|
||||
name: 'GatewayAdd',
|
||||
title: this.$t('Add'),
|
||||
can: !this.$store.getters.currentOrgIsRoot,
|
||||
callback: async() => {
|
||||
// 由于修改成为了抽屉形式,导致传入到 AddGateway 组件中的 obj 任然为最初的数量,就会导致新增的 item 依然会出现可选的情况
|
||||
// 此时修改为在打开 AddGateway 额外从 tableConfig.url 的接口中获取最新的 gateways 数目
|
||||
@@ -192,23 +197,16 @@ export default {
|
||||
}
|
||||
|
||||
vm.$nextTick(() => {
|
||||
this.AddGatewaySetting.addGatewayDialogVisible = true
|
||||
this.addGatewaySetting.addGatewayDialogVisible = true
|
||||
})
|
||||
}
|
||||
}
|
||||
],
|
||||
onCreate: () => {
|
||||
vm.$route.query.domain = vm.object.id
|
||||
vm.$route.query.platform_type = 'linux'
|
||||
vm.$route.query.category = 'host'
|
||||
|
||||
vm.$refs.ListTable.onCreate()
|
||||
vm.$refs.ListTable.onCreate({ query: { domain: vm.object.id, platform_type: 'linux', category: 'host' }})
|
||||
}
|
||||
},
|
||||
port: 0,
|
||||
cell: '',
|
||||
visible: false,
|
||||
AddGatewaySetting: {
|
||||
addGatewaySetting: {
|
||||
addGatewayDialogVisible: false
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,7 +25,7 @@ export default {
|
||||
TaskDetail: {},
|
||||
config: {
|
||||
activeMenu: 'Detail',
|
||||
url: '/api/v1/assets/domains',
|
||||
url: '/api/v1/assets/domains/',
|
||||
submenu: [
|
||||
{
|
||||
title: this.$t('Basic'),
|
||||
|
||||
@@ -42,6 +42,7 @@ export default {
|
||||
}
|
||||
},
|
||||
data() {
|
||||
const vm = this
|
||||
return {
|
||||
formConfig: {
|
||||
getUrl: () => {
|
||||
@@ -74,7 +75,7 @@ export default {
|
||||
cleanFormValue(values) {
|
||||
const data = []
|
||||
values.assets.forEach(item => {
|
||||
const d = { id: item, domain: this.$route.params.id }
|
||||
const d = { id: item, domain: vm.object.id }
|
||||
data.push(d)
|
||||
})
|
||||
return data
|
||||
|
||||
@@ -124,8 +124,8 @@ export default {
|
||||
this.initial.su_method = this.suMethodLimits[0]
|
||||
},
|
||||
async setCategories() {
|
||||
const category = this.$route.query._category
|
||||
const type = this.$route.query._type
|
||||
const category = this.$route.query.category
|
||||
const type = this.$route.query.type
|
||||
const state = await this.$store.dispatch('assets/getAssetCategories')
|
||||
this.fieldsMeta.category_type.el.options = state.assetCategoriesCascader
|
||||
if (category && type) {
|
||||
@@ -135,8 +135,8 @@ export default {
|
||||
return new Promise((resolve, reject) => resolve(true))
|
||||
},
|
||||
async setConstraints() {
|
||||
const category = this.$route.query._category
|
||||
const type = this.$route.query._type
|
||||
const category = this.$route.query.category
|
||||
const type = this.$route.query.type
|
||||
const url = `/api/v1/assets/categories/constraints/?category=${category}&type=${type}`
|
||||
const constraints = await this.$axios.get(url)
|
||||
this.defaultOptions = constraints
|
||||
|
||||
@@ -5,9 +5,10 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import IBox from '../../../../components/Common/IBox'
|
||||
import IBox from '@/components/Common/IBox'
|
||||
import { GenericCreateUpdateForm } from '@/layout/components'
|
||||
import { platformFieldsMeta, setAutomations, updateAutomationParams } from '../const'
|
||||
import { setUrlId } from '@/utils/common'
|
||||
import { mapGetters } from 'vuex'
|
||||
|
||||
export default {
|
||||
@@ -30,7 +31,7 @@ export default {
|
||||
ansible_enabled: true
|
||||
}
|
||||
},
|
||||
url: `/api/v1/assets/platforms/${this.object.id}/`,
|
||||
url: `/api/v1/assets/platforms/?_meta_cache=0`,
|
||||
disabled: !canEdit,
|
||||
hasReset: false,
|
||||
hasDetailInMsg: false,
|
||||
@@ -67,7 +68,8 @@ export default {
|
||||
if (!this.canSubmit || !this.isSystemAdmin) {
|
||||
return this.$message.error(this.$tc('NoPermission'))
|
||||
}
|
||||
this.$axios.patch(`${this.url}${this.object.id}/`, validValues).then(() => {
|
||||
const url = setUrlId(this.url, this.object.id)
|
||||
this.$axios.patch(url, validValues).then(() => {
|
||||
this.$message.success(this.$tc('UpdateSuccessMsg'))
|
||||
})
|
||||
}
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
<script>
|
||||
import { IBox } from '@/components'
|
||||
import AutoDetailCard from '@/components/Cards/DetailCard/auto'
|
||||
import QuickActions from '../../../../components/Common/QuickActions'
|
||||
import QuickActions from '@/components/Common/QuickActions'
|
||||
import PlatformDetailUpdateDialog from './PlatformDetailUpdateDialog'
|
||||
import ProtocolSelector from '@/components/Form/FormFields/ProtocolSelector'
|
||||
import TwoCol from '@/layout/components/Page/TwoColPage.vue'
|
||||
|
||||
@@ -38,7 +38,7 @@ export default {
|
||||
name: 'Assets'
|
||||
},
|
||||
{
|
||||
title: this.$t('Automations'),
|
||||
title: this.$t('Automation'),
|
||||
name: 'Automation'
|
||||
}
|
||||
],
|
||||
@@ -72,7 +72,3 @@ export default {
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
|
||||
@@ -109,12 +109,13 @@ export default {
|
||||
actions: {
|
||||
formatterArgs: {
|
||||
canClone: () => vm.$hasPerm('assets.add_platform'),
|
||||
onClone({ row }) {
|
||||
vm.$refs.genericListTable.onClone({ row, query: { type: row.type.value, category: row.category.value }})
|
||||
},
|
||||
canUpdate: ({ row }) => !row.internal && vm.$hasPerm('assets.change_platform'),
|
||||
canDelete: ({ row }) => !row.internal && vm.$hasPerm('assets.delete_platform'),
|
||||
onUpdate({ row, col }) {
|
||||
vm.$route.query._type = row.type.value
|
||||
vm.$route.query._category = row.category.value
|
||||
vm.$refs.genericListTable.onUpdate({ row, col })
|
||||
vm.$refs.genericListTable.onUpdate({ row, col, query: { type: row.type.value, category: row.category.value }})
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -135,10 +136,7 @@ export default {
|
||||
},
|
||||
moreCreates: {
|
||||
callback: (item) => {
|
||||
this.$router.push({
|
||||
query: { _type: item.name, _category: item.category }
|
||||
})
|
||||
this.$refs.genericListTable.onCreate()
|
||||
this.$refs.genericListTable.onCreate({ query: { type: item.name, category: item.category }})
|
||||
},
|
||||
dropdown: []
|
||||
}
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"module": "commonjs",
|
||||
"target": "es5",
|
||||
"sourceMap": true
|
||||
},
|
||||
"exclude": [
|
||||
"node_modules"
|
||||
]
|
||||
}
|
||||
@@ -42,8 +42,9 @@ function updatePlatformProtocols(vm, platformType, updateForm, isPlatformChanged
|
||||
'username_selector': setting.username_selector
|
||||
})
|
||||
}
|
||||
// 这里不能清空,比如 gateway 切换时,protocol 没有变化,就会出现 bug, tapd: 1053282
|
||||
// updateForm({ protocols: [] })
|
||||
vm.iConfig.fieldsMeta.protocols.el.choices = platformProtocols
|
||||
updateForm({ protocols: [] })
|
||||
}), 100)
|
||||
}
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<div class="content">
|
||||
<el-row justify="space-between" type="flex">
|
||||
<el-col v-for="item of summaryItems" :key="item.title" :md="8" :sm="12" :xs="12">
|
||||
<SummaryCard :body="item.body" :title="item.title" />
|
||||
<SummaryCard :title="item.title" v-bind="item.body" />
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
|
||||
@@ -24,9 +24,10 @@ export default {
|
||||
counter: {
|
||||
total_long_time_no_login_accounts: '.',
|
||||
total_new_found_accounts: '.',
|
||||
total_group_changed_accounts: '.',
|
||||
total_sudo_changed_accounts: '.',
|
||||
total_groups_changed_accounts: '.',
|
||||
total_sudoers_changed_accounts: '.',
|
||||
total_authorized_keys_changed_accounts: '.',
|
||||
total_account_deleted_accounts: '.',
|
||||
total_password_expired_accounts: '.',
|
||||
total_long_time_password_accounts: '.',
|
||||
total_weak_password_accounts: '.',
|
||||
@@ -50,20 +51,25 @@ export default {
|
||||
value: this.counter.total_new_found_accounts
|
||||
},
|
||||
{
|
||||
description: 'group_changed',
|
||||
name: this.$t('GroupChanged'),
|
||||
value: this.counter.total_group_changed_accounts
|
||||
description: 'groups_changed',
|
||||
name: this.$t('GroupsChanged'),
|
||||
value: this.counter.total_groups_changed_accounts
|
||||
},
|
||||
{
|
||||
description: 'sudo_changed',
|
||||
name: this.$t('SudoChanged'),
|
||||
value: this.counter.total_sudo_changed_accounts
|
||||
description: 'sudoers_changed',
|
||||
name: this.$t('SudoersChanged'),
|
||||
value: this.counter.total_sudoers_changed_accounts
|
||||
},
|
||||
{
|
||||
description: 'authorized_keys_changed',
|
||||
name: this.$t('AuthorizedKeysChanged'),
|
||||
value: this.counter.total_authorized_keys_changed_accounts
|
||||
},
|
||||
{
|
||||
description: 'account_deleted',
|
||||
name: this.$t('AccountDeleted'),
|
||||
value: this.counter.total_account_deleted_accounts
|
||||
},
|
||||
{
|
||||
description: 'password_expired',
|
||||
name: this.$t('PasswordExpired'),
|
||||
@@ -204,9 +210,10 @@ export default {
|
||||
params: {
|
||||
total_long_time_no_login_accounts: 1,
|
||||
total_new_found_accounts: 1,
|
||||
total_group_changed_accounts: 1,
|
||||
total_sudo_changed_accounts: 1,
|
||||
total_groups_changed_accounts: 1,
|
||||
total_sudoers_changed_accounts: 1,
|
||||
total_authorized_keys_changed_accounts: 1,
|
||||
total_account_deleted_accounts: 1,
|
||||
total_password_expired_accounts: 1,
|
||||
total_long_time_password_accounts: 1,
|
||||
total_weak_password_accounts: 1,
|
||||
|
||||
@@ -12,12 +12,11 @@
|
||||
<MissionSummery class="mission-summery" />
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="14" :xs="24">
|
||||
<el-col v-if="$store.getters.hasValidLicense" :span="14" :xs="24">
|
||||
<AccountSecretSummary class="account-secret-summary" />
|
||||
</el-col>
|
||||
<el-col :span="10" :xs="24">
|
||||
<el-col :span="$store.getters.hasValidLicense ? 10: 24" :xs="24">
|
||||
<RiskSummary class="risk-summary" />
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
@@ -245,22 +245,17 @@ export default {
|
||||
this.initial.runAfterSave = true
|
||||
this.instantTask = true
|
||||
this.createSuccessNextRoute = { name: 'Adhoc' }
|
||||
this.ready = true
|
||||
})
|
||||
} else {
|
||||
this.ready = true
|
||||
}
|
||||
break
|
||||
case 'playbook':
|
||||
this.initial.type = 'playbook'
|
||||
if (this.$route.query.id) {
|
||||
this.initial.playbook = this.$route.query.id
|
||||
this.ready = true
|
||||
} else {
|
||||
this.ready = true
|
||||
}
|
||||
break
|
||||
}
|
||||
this.ready = true
|
||||
},
|
||||
methods: {
|
||||
submitForm(form, btn) {
|
||||
|
||||
@@ -105,10 +105,7 @@ export default {
|
||||
canUpdate: this.$hasPerm('ops.change_job') && !this.$store.getters.currentOrgIsRoot,
|
||||
updateRoute: 'JobUpdate',
|
||||
onUpdate: ({ row, col }) => {
|
||||
vm.$router.push({
|
||||
query: { _type: this.type }
|
||||
})
|
||||
vm.$refs.ListTable.onUpdate({ row, col })
|
||||
vm.$refs.ListTable.onUpdate({ row, col, query: { _type: this.type }})
|
||||
},
|
||||
hasDelete: true,
|
||||
canDelete: this.$hasPerm('ops.delete_job'),
|
||||
@@ -141,10 +138,7 @@ export default {
|
||||
},
|
||||
headerActions: {
|
||||
onCreate: () => {
|
||||
vm.$router.push({
|
||||
query: { _type: this.type }
|
||||
})
|
||||
vm.$refs.ListTable.onCreate()
|
||||
vm.$refs.ListTable.onCreate({ query: { _type: this.type }})
|
||||
},
|
||||
hasRefresh: true,
|
||||
hasExport: false,
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user