perf(ticket): 优化工单细节

Closes https://github.com/orgs/jumpserver/projects/1
This commit is contained in:
OrangeM21 2020-08-06 18:30:55 +08:00 committed by 老广
parent ee3dc30985
commit 6bf15655b7
10 changed files with 83 additions and 42 deletions

View File

@ -8,7 +8,7 @@
<i v-if="item.fa" :class="'fa ' + item.fa" />{{ item.title }}
</span>
</el-button>
<el-dropdown v-if="iMoreActions.length > 0" trigger="click" @command="handleClick">
<el-dropdown v-if="iMoreActions.length > 0" trigger="click" :placement="moreActionsPlacement" @command="handleClick">
<el-button :size="size" :type="moreActionsType" class="btn-more-actions">
{{ iMoreActionsTitle }}<i class="el-icon-arrow-down el-icon--right" />
</el-button>
@ -52,6 +52,11 @@ export default {
moreActionsType: {
type: String,
default: 'default'
},
moreActionsPlacement: {
type: String,
default: 'bottom'
//
}
},
computed: {

View File

@ -148,7 +148,7 @@
},
"common": {
"Action": "动作",
"RequestTickets": "工单",
"RequestTickets": "请工单",
"Actions": "操作",
"Activate": "激活",
"Active": "激活中",
@ -187,6 +187,7 @@
"MFARequireForSecurity": "为了安全请输入MFA",
"Members": "成员",
"More": "更多",
"Message": "消息",
"MoreActions": "更多操作",
"Name": "名称",
"No": "否",
@ -227,6 +228,7 @@
"createdBy": "创建人",
"dateCreated": "创建日期",
"dateExpired": "失效日期",
"dateFinished": "完成日期",
"dateStart": "开始日期",
"deleteErrorMsg": "删除失败",
"deleteFailedMsg": "删除失败",
@ -490,6 +492,7 @@
"TaskMonitor": "任务监控",
"Terminal": "终端管理",
"TicketDetail": "工单详情",
"TicketCreate": "创建工单",
"Tickets": "工单管理",
"UserCreate": "创建用户",
"UserDetail": "用户详情",
@ -723,7 +726,7 @@
"SystemUser": "系统用户",
"RequestAssetPerm": "申请资产授权",
"Applicant": "申请人",
"Pending": "处理",
"Pending": "处理",
"Approved": "已同意",
"Rejected": "已拒绝",
"Closed": "已关闭"

View File

@ -187,6 +187,7 @@
"MFARequireForSecurity": "MFA required for security",
"Members": "Members",
"More": "More",
"Message": "Message",
"MoreActions": "Actions",
"Name": "Name",
"No": "No",
@ -226,6 +227,7 @@
"createSuccessMsg": "Create success",
"createdBy": "Created by",
"dateCreated": "Date created",
"dateFinished": "Date finished",
"dateExpired": "Date expired",
"dateStart": "Date start",
"deleteErrorMsg": "Delete failed",
@ -489,6 +491,7 @@
"TaskMonitor": "Task monitor",
"Terminal": "Terminal",
"TicketDetail": "Ticket detail",
"TicketCreate": "Ticket create",
"Tickets": "Tickets",
"UserCreate": "User create",
"UserDetail": "User detail",

View File

@ -17,7 +17,7 @@ export default [
path: 'tickets/request-asset-perm/create',
name: 'RequestAssetPermTicketCreateUpdate',
component: () => import('@/views/tickets/RequestAssetPerm/RequestAssetPermTicketCreateUpdate'),
meta: { title: i18n.t('route.TicketDetail'), activeMenu: '/tickets/tickets' },
meta: { title: i18n.t('route.TicketCreate'), activeMenu: '/tickets/tickets' },
hidden: true
},
{

View File

@ -6,13 +6,14 @@
:default-expand-all="true"
:default-checked-keys="value"
:props="defaultProps"
v-bind="$attrs"
@check="handleCheckChange"
/>
</template>
<script>
export default {
name: 'AssetPermissionFormActionFiel',
name: 'AssetPermissionFormActionField',
props: {
value: {
type: Array,

View File

@ -7,15 +7,18 @@
>
<IBox v-if="hasActionPerm&&object.status !== 'closed'" class="box">
<div slot="header" class="clearfix ibox-title">
<i class="fa fa-info-circle" /> {{ $t('common.Actions') }}
<i class="fa fa-edit" /> {{ $t('common.Actions') }}
</div>
<template>
<el-form ref="requestForm" :model="requestForm" label-width="140px" label-position="left" class="assets">
<el-form-item :label="$t('tickets.Asset')" required>
<Select2 ref="select2" v-model="requestForm.asset" v-bind="asset_select2" style="width: 30% !important" />
<Select2 v-model="requestForm.asset" v-bind="asset_select2" style="width: 30% !important" />
</el-form-item>
<el-form-item :label="$t('tickets.SystemUser')" required>
<Select2 ref="select2" v-model="requestForm.systemuser" v-bind="systemuser_select2" style="width: 30% !important" />
<Select2 v-model="requestForm.systemuser" v-bind="systemuser_select2" style="width: 30% !important" />
</el-form-item>
<el-form-item :label="$t('assets.Action')" required>
<AssetPermissionFormActionField v-model="requestForm.actions" style="width: 30% !important" />
</el-form-item>
</el-form>
</template>
@ -29,10 +32,11 @@ import { toSafeLocalDateStr } from '@/utils/common'
import { STATUS_MAP } from '../../const'
import Select2 from '@/components/Select2'
import IBox from '@/components/IBox'
import AssetPermissionFormActionField from '@/views/perms/AssetPermission/components/AssetPermissionFormActionField'
import GenericTicketDetail from '@/views/tickets/components/GenericTicketDetail'
export default {
name: '',
components: { GenericTicketDetail, IBox, Select2 },
components: { GenericTicketDetail, IBox, Select2, AssetPermissionFormActionField },
props: {
object: {
type: Object,
@ -44,7 +48,8 @@ export default {
statusMap: this.object.status === 'open' ? STATUS_MAP[this.object.status] : STATUS_MAP[this.object.action],
requestForm: {
asset: this.object.confirmed_assets,
systemuser: ''
systemuser: '',
actions: this.object.actions
},
comments: '',
assets: [],
@ -162,7 +167,8 @@ export default {
} else {
this.$axios.patch(`/api/v1/tickets/tickets/request-asset-perm/${this.object.id}/`, {
confirmed_system_user: this.requestForm.systemuser,
confirmed_assets: this.requestForm.asset
confirmed_assets: this.requestForm.asset,
actions: this.requestForm.actions
}).then(res => {
this.$axios.post(`/api/v1/tickets/tickets/request-asset-perm/${this.object.id}/approve/`).then(
() => {

View File

@ -6,6 +6,7 @@
import { GenericCreateUpdatePage } from '@/layout/components'
import Select2 from '@/components/Select2'
import { getDaysFuture } from '@/utils/common'
import AssetPermissionFormActionField from '@/views/perms/AssetPermission/components/AssetPermissionFormActionField'
export default {
components: {
GenericCreateUpdatePage
@ -20,11 +21,12 @@ export default {
ips_or_not: true,
date_expired: date_expired,
date_start: date_start,
org_id: 'DEFAULT'
org_id: 'DEFAULT',
actions: ['all', 'connect', 'updownload', 'upload_file', 'download_file']
},
fields: [
[this.$t('common.Basic'), ['title', 'org_id', 'assignees']],
[this.$t('tickets.RequestPerm'), ['ips', 'hostname', 'date_start', 'date_expired']]
[this.$t('tickets.RequestPerm'), ['ips', 'hostname', 'actions', 'date_start', 'date_expired']]
],
fieldsMeta: {
@ -34,6 +36,11 @@ export default {
hostname: {
helpText: '支持模糊匹配'
},
actions: {
label: this.$t('perms.Actions'),
component: AssetPermissionFormActionField,
helpText: this.$t('common.actionsTips')
},
org_id: {
component: Select2,
el: {

View File

@ -5,7 +5,6 @@
import ListTable from '@/components/ListTable'
import { DetailFormatter } from '@/components/ListTable/formatters'
import { toSafeLocalDateStr } from '@/utils/common'
export default {
name: 'TicketListTable',
components: {
@ -59,9 +58,19 @@ export default {
sortable: 'custom',
formatter: row => {
if (row.status === 'open') {
return <i class='fa fa-check-circle-o text-primary'/>
return <el-tag type='success' size='mini'style='align-items:center; display: flex; justify-content:center;'> { this.$t('tickets.Pending') }</el-tag>
}
if (row.status === 'closed') {
return <el-tag type='info' size='mini' style='align-items:center; display: flex; justify-content:center;'> { this.$t('tickets.Closed') }</el-tag>
}
switch (row.action) {
case 'approve':
return <el-tag type='primary' size='mini' style='align-items:center; display: flex; justify-content:center;'> { this.$t('tickets.Approved') }</el-tag>
case 'reject':
return <el-tag type='danger' size='mini' style='align-items:center; display: flex; justify-content:center;'> { this.$t('tickets.Rejected') }</el-tag>
case '':
return <el-tag type='info' size='mini' style='align-items:center; display: flex; justify-content:center;'> { this.$t('tickets.Closed') }</el-tag>
}
return <i class='fa fa-times-circle-o text-danger'/>
}
},
{

View File

@ -1,23 +1,7 @@
<template>
<IBox class="box">
<div slot="header" class="clearfix ibox-title">
<i class="fa fa-info-circle" /> {{ $t('common.Comment') }}
</div>
<div class="feed-activity-list">
<div class="feed-element">
<a href="#" class="pull-left">
<el-avatar :src="imageUrl" class="header-avatar" />
</a>
<div class="media-body ">
<strong>{{ object.user_display }}</strong>
<small class="text-muted"> {{ formatTime(object.date_created) }}</small>
<br>
<small class="text-muted">{{ toSafeLocalDateStr(object.date_created) }} </small>
<div style="padding-top: 10px">
<span v-html="object.body" />
</div>
</div>
</div>
<i class="fa fa-comments" /> {{ $t('common.Message') }}
</div>
<template v-if="comments">
<div v-for="item in comments" :key="item.user_display + item.body" class="feed-activity-list">
@ -74,7 +58,7 @@
size="small"
@click="handleComment"
>
<i class="fa fa-pencil" />{{ $t('tickets.Comment') }}
<i class="fa fa-pencil" />{{ $t('tickets.reply') }}
</el-button>
</el-form-item>
</el-form>
@ -116,6 +100,7 @@ export default {
const url = `/api/v1/tickets/tickets/${this.object.id}/comments/`
this.$axios.get(url).then(res => {
this.comments = res
console.log(this.comments)
}).catch(err => {
this.$message.error(err)
})
@ -152,7 +137,7 @@ export default {
})
},
handleApprove() {
const handler = this.approve() || this.defaultApprove()
const handler = this.approve || this.defaultApprove
handler()
},
handleReject() {

View File

@ -1,25 +1,37 @@
<template>
<IBox>
<div style="height: 350px;">
<el-steps direction="vertical" :active="ticketStatus">
<el-steps direction="vertical" :active="ticketSteps">
<el-step
:title="`${this.$t('tickets.OpenTicket')}${object.type_display}`"
:description="`${this.$t('tickets.Applicant')}${object.user_display}`"
/>
>
<div slot="description">
<div>{{ `${this.$t('tickets.Applicant')}${object.user_display}` }}</div>
<div>{{ `${this.$t('common.dateCreated')}: ${toSafeLocalDateStr(this.object.date_created)}` }}</div>
</div>
</el-step>
<el-step
:title="`${this.$t('tickets.HandleTicket')}`"
:description="`${this.$t('tickets.Assignees')}${object.assignees_display}`"
/>
<el-step
:title="`${this.$t('tickets.FinishedTicket')}`"
:description="`${this.$t('tickets.Assignee')}${object.assignee_display}`"
/>
:description="ticketSteps===STATUS.close ? `${this.$t('tickets.Assignee')}${object.assignee_display}`:'' "
>
<div v-if="ticketSteps===STATUS.close" slot="description">
<div>{{ `${this.$t('tickets.Assignee')}${object.assignee_display}` }}</div>
<div>{{ `${this.$t('common.dateFinished')}: ${toSafeLocalDateStr(this.object.date_updated)}` }}</div>
</div>
</el-step>
</el-steps>
</div>
</IBox>
</template>
<script>
import { formatTime, getDateTimeStamp } from '@/utils/index'
import { toSafeLocalDateStr } from '@/utils/common'
import IBox from '@/components/IBox'
export default {
name: 'Steps',
@ -31,11 +43,21 @@ export default {
}
},
data() {
return {}
return {
STATUS: { open: 2, close: 3 }
}
},
computed: {
ticketStatus() {
return this.object.status === 'open' ? 2 : 3
ticketSteps() {
return this.object.status === 'open' ? this.STATUS.open : this.STATUS.close
}
},
methods: {
formatTime(dateStr) {
return formatTime(getDateTimeStamp(dateStr))
},
toSafeLocalDateStr(dataStr) {
return toSafeLocalDateStr(dataStr)
}
}
}