mirror of
https://github.com/jumpserver/lina.git
synced 2026-01-13 19:35:24 +00:00
feat: 支持批量审批工单 (#3273)
This commit is contained in:
@@ -1726,6 +1726,8 @@
|
||||
"basicTools": "Basic tool"
|
||||
},
|
||||
"tickets": {
|
||||
"BatchApproval": "Batch approval",
|
||||
"BatchReject": "Batch reject",
|
||||
"ApplyAsset": "Apply asset",
|
||||
"LoginConfirm": "User login confirm",
|
||||
"CommandConfirm": "Command confirm",
|
||||
|
||||
@@ -1719,6 +1719,8 @@
|
||||
"Applets": "リモート アプリケーション"
|
||||
},
|
||||
"tickets": {
|
||||
"BatchApproval": "大量承認です",
|
||||
"BatchReject": "一括拒否です",
|
||||
"ApplyAsset": "リソースの適用",
|
||||
"LoginConfirm": "ユーザーログインの確認",
|
||||
"CommandConfirm": "コマンドの確認",
|
||||
|
||||
@@ -1711,6 +1711,8 @@
|
||||
"testHelpText": "请输入目的地址进行测试"
|
||||
},
|
||||
"tickets": {
|
||||
"BatchApproval": "批量审批",
|
||||
"BatchReject": "批量拒绝",
|
||||
"ApplyAsset": "申请资产",
|
||||
"LoginConfirm": "用户登录复核",
|
||||
"CommandConfirm": "命令复核",
|
||||
|
||||
@@ -1,15 +1,59 @@
|
||||
<template>
|
||||
<BaseTicketList :url="url" />
|
||||
<div>
|
||||
<BaseTicketList ref="BaseTicketList" :url="url" v-bind="$data" />
|
||||
<Dialog
|
||||
v-if="isVisible"
|
||||
width="70%"
|
||||
:title="$tc('tickets.BatchApproval')"
|
||||
:visible.sync="isVisible"
|
||||
:cancel-title="$tc('tickets.BatchReject')"
|
||||
:confirm-title="$tc('tickets.BatchApproval')"
|
||||
:destroy-on-close="true"
|
||||
@cancel="onCancel"
|
||||
@confirm="onConfirm"
|
||||
>
|
||||
<div v-for="d in ticketData" :key="d.id">
|
||||
<AutoDetailCard :url="detailUrl" :fields="getDetailFields(d)" :object="d" :title="`${d.title}(${d.type.label})`" />
|
||||
</div>
|
||||
</Dialog>
|
||||
</div>
|
||||
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import BaseTicketList from './BaseTicketList'
|
||||
import { mapGetters } from 'vuex'
|
||||
import AutoDetailCard from '@/components/DetailCard/auto'
|
||||
import Dialog from '@/components/Dialog'
|
||||
export default {
|
||||
name: 'AssignedTicketList',
|
||||
components: {
|
||||
Dialog,
|
||||
AutoDetailCard,
|
||||
BaseTicketList
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
ticketData: [],
|
||||
detailUrl: `/api/v1/tickets/tickets/`,
|
||||
isVisible: false,
|
||||
extraTicketAction: {
|
||||
hasCreate: false,
|
||||
hasMoreActions: true,
|
||||
extraMoreActions: [
|
||||
{
|
||||
name: 'BatchApproval',
|
||||
title: this.$t('tickets.BatchApproval'),
|
||||
can: ({ selectedRows }) => { return selectedRows.length > 0 },
|
||||
callback: function({ selectedRows }) {
|
||||
this.isVisible = true
|
||||
this.ticketData = selectedRows
|
||||
}.bind(this)
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
url() {
|
||||
return `/api/v1/tickets/tickets/?assignees__id=${this.currentUser.id}`
|
||||
@@ -17,10 +61,117 @@ export default {
|
||||
...mapGetters([
|
||||
'currentUser'
|
||||
])
|
||||
},
|
||||
methods: {
|
||||
getAjaxData() {
|
||||
let ticketType
|
||||
const data = {}
|
||||
this.ticketData.map(item => {
|
||||
switch (item.type.value) {
|
||||
case 'apply_asset':
|
||||
ticketType = 'apply-asset-tickets'
|
||||
break
|
||||
case 'login_confirm':
|
||||
ticketType = 'apply-login-tickets'
|
||||
break
|
||||
case 'command_confirm':
|
||||
ticketType = 'apply-command-tickets'
|
||||
break
|
||||
case 'login_asset_confirm':
|
||||
ticketType = 'apply-login-asset-tickets'
|
||||
break
|
||||
}
|
||||
if (!data.hasOwnProperty(ticketType)) {
|
||||
data[ticketType] = []
|
||||
}
|
||||
data[ticketType].push(item.id)
|
||||
})
|
||||
return data
|
||||
},
|
||||
onConfirm() {
|
||||
this.bulk('approve')
|
||||
},
|
||||
onCancel() {
|
||||
this.bulk('reject')
|
||||
},
|
||||
bulk(action) {
|
||||
let current = 0
|
||||
const data = this.getAjaxData()
|
||||
const dataLength = Object.keys(data).length
|
||||
for (const ticketType in data) {
|
||||
current += 1
|
||||
this.$axios.put(
|
||||
`/api/v1/tickets/${ticketType}/bulk/?action=${action}`,
|
||||
{ tickets: data[ticketType] }
|
||||
).then(res => {
|
||||
this.$message.success(this.$tc('common.updateSuccessMsg'))
|
||||
if (current === dataLength) {
|
||||
this.$refs.BaseTicketList.reloadTable()
|
||||
this.isVisible = false
|
||||
}
|
||||
}).catch(err => {
|
||||
const errMsg = Object.values(err.response.data).join(', ')
|
||||
this.$message.error(this.$tc('common.updateErrorMsg') + ' ' + errMsg)
|
||||
})
|
||||
}
|
||||
},
|
||||
getDetailFields(item) {
|
||||
const ticketType = item?.type?.value
|
||||
let detailFields = [
|
||||
{
|
||||
key: this.$t('tickets.Applicant'),
|
||||
value: item?.applicant?.name
|
||||
}
|
||||
]
|
||||
if (ticketType === 'command_confirm') {
|
||||
detailFields = detailFields.concat(
|
||||
[
|
||||
{
|
||||
key: this.$t('tickets.ApplyFromCMDFilterRule'),
|
||||
value: item?.rel_snapshot?.apply_from_cmd_filter_acl
|
||||
},
|
||||
{
|
||||
key: this.$t('tickets.ApplyFromSession'),
|
||||
value: item?.rel_snapshot?.apply_from_session
|
||||
},
|
||||
{
|
||||
key: this.$t('tickets.ApplyRunUser'),
|
||||
value: item?.rel_snapshot?.apply_run_user
|
||||
}
|
||||
]
|
||||
)
|
||||
} else if (ticketType === 'apply_asset') {
|
||||
detailFields = detailFields.concat(
|
||||
[
|
||||
{
|
||||
key: this.$t('assets.Asset'),
|
||||
value: item?.rel_snapshot?.apply_assets.join(', ')
|
||||
},
|
||||
{
|
||||
key: this.$t('assets.Node'),
|
||||
value: item?.rel_snapshot?.apply_nodes.join(', ')
|
||||
}
|
||||
]
|
||||
)
|
||||
} else if (ticketType === 'login_asset_confirm') {
|
||||
detailFields = detailFields.concat(
|
||||
[
|
||||
{
|
||||
key: this.$t('acl.apply_login_asset'),
|
||||
value: item?.rel_snapshot?.apply_login_asset
|
||||
},
|
||||
{
|
||||
key: this.$t('acl.apply_login_user'),
|
||||
value: item?.rel_snapshot?.apply_login_user
|
||||
}
|
||||
]
|
||||
)
|
||||
}
|
||||
return detailFields
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
<template>
|
||||
<GenericListPage
|
||||
ref="ListPage"
|
||||
v-loading="loading"
|
||||
:header-actions="ticketActions"
|
||||
:header-actions="iTicketAction"
|
||||
:table-config="ticketTableConfig"
|
||||
/>
|
||||
</template>
|
||||
@@ -22,9 +23,9 @@ export default {
|
||||
type: String,
|
||||
default: '/api/v1/tickets/tickets/'
|
||||
},
|
||||
hasMoreActions: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
extraTicketAction: {
|
||||
type: Object,
|
||||
default: () => ({})
|
||||
},
|
||||
extraQuery: {
|
||||
type: Object,
|
||||
@@ -132,9 +133,10 @@ export default {
|
||||
}
|
||||
}
|
||||
},
|
||||
ticketActions: {
|
||||
defaultTicketActions: {
|
||||
hasExport: false,
|
||||
hasLeftActions: this.hasMoreActions,
|
||||
hasMoreActions: false,
|
||||
hasLeftActions: true,
|
||||
canCreate: this.$hasPerm('tickets.view_ticket'),
|
||||
hasBulkDelete: false,
|
||||
searchConfig: {
|
||||
@@ -217,28 +219,25 @@ export default {
|
||||
}
|
||||
]
|
||||
},
|
||||
createTitle: this.$t('common.RequestTickets'),
|
||||
hasMoreActions: false,
|
||||
moreCreates: {
|
||||
dropdown: [
|
||||
{
|
||||
name: 'RequestAssetPerm',
|
||||
title: this.$t('tickets.RequestAssetPerm'),
|
||||
callback: () => this.$router.push({
|
||||
name: 'RequestAssetPermTicketCreateUpdate'
|
||||
})
|
||||
}
|
||||
]
|
||||
}
|
||||
createTitle: this.$t('common.RequestTickets')
|
||||
}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
iTicketAction() {
|
||||
return Object.assign({}, this.defaultTicketActions, this.extraTicketAction)
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
setTimeout(() => {
|
||||
this.loading = false
|
||||
}, 500)
|
||||
},
|
||||
methods: {}
|
||||
methods: {
|
||||
reloadTable() {
|
||||
this.$refs.ListPage.$refs.ListTable.$refs.ListTable.reloadTable()
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<BaseTicketList :url="url" :has-more-actions="true" />
|
||||
<BaseTicketList :url="url" v-bind="$data" />
|
||||
</template>
|
||||
|
||||
<script>
|
||||
@@ -12,6 +12,19 @@ export default {
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
extraTicketAction: {
|
||||
moreCreates: {
|
||||
dropdown: [
|
||||
{
|
||||
name: 'RequestAssetPerm',
|
||||
title: this.$t('tickets.RequestAssetPerm'),
|
||||
callback: () => this.$router.push({
|
||||
name: 'RequestAssetPermTicketCreateUpdate'
|
||||
})
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
|
||||
Reference in New Issue
Block a user