mirror of
https://github.com/jumpserver/lina.git
synced 2025-08-02 07:27:01 +00:00
perf(ticket): 优化工单细节
Closes https://github.com/orgs/jumpserver/projects/1
This commit is contained in:
parent
ee3dc30985
commit
6bf15655b7
@ -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: {
|
||||
|
@ -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": "已关闭"
|
||||
|
@ -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",
|
||||
|
@ -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
|
||||
},
|
||||
{
|
||||
|
@ -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,
|
||||
|
@ -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(
|
||||
() => {
|
||||
|
@ -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: {
|
||||
|
@ -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'/>
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -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() {
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user