Files
laws-sinotruk-client/src/components/ProcessDetailList.vue
T

625 lines
22 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<div class="page-box">
<div class="personnel-info">
<slot name="personnelInfo"></slot>
</div>
<div class="approval-list">
<!--查询区域-->
<div class="table-page-search-wrapper">
<a-form layout="inline" @keyup.enter.native="searchQuery">
<a-row :gutter="24">
<!--任务节点-->
<a-col :md="8" :sm="8">
<a-form-item :label="$t('workCenter.processDetail.taskNode')" :labelCol="labelCol" :wrapperCol="wrapperCol">
<a-input
:placeholder="$t('pleaseEnter') + $t('workCenter.processDetail.taskNode')"
v-model="queryParam.taskName"></a-input>
</a-form-item>
</a-col>
<!--任务受理人-->
<a-col :md="8" :sm="8">
<a-form-item :label="$t('workCenter.processDetail.taskHandler')" :labelCol="labelCol" :wrapperCol="wrapperCol">
<a-input
:placeholder="$t('pleaseEnter') + $t('workCenter.processDetail.taskHandler')"
v-model="queryParam.taskAcceptor"></a-input>
</a-form-item>
</a-col>
<template v-if="toggleSearchStatus">
<!--任务受理人组织机构-->
<a-col :md="8" :sm="8">
<a-form-item :label="$t('workCenter.processDetail.taskHandlerDept')" :labelCol="labelCol" :wrapperCol="wrapperCol">
<a-tree-select
tree-node-filter-prop="title"
v-model="queryParam.taskAcceptorDept"
allowClear
:getPopupContainer="triggerNode=> triggerNode.parentNode"
class="box-input"
style="width: 100%"
:tree-data="categoryTreeList"
show-search
:filterTreeNode="filterTreeOption"
:placeholder="$t('pleaseSelect') + $t('workCenter.processDetail.taskHandlerDept')"
/>
</a-form-item>
</a-col>
<!--状态-->
<a-col :md="8" :sm="8">
<a-form-item :label="$t('status')" :labelCol="labelCol" :wrapperCol="wrapperCol">
<j-dict-select-tag
:placeholder="$t('pleaseSelect') + $t('status')"
dict-code="prc_node_status"
v-model="queryParam.finishFlag"></j-dict-select-tag>
</a-form-item>
</a-col>
</template>
<div style="float: right;overflow: hidden;margin-right: 11px" class="table-page-search-submitButtons">
<a @click="handleToggleSearch">
{{ !toggleSearchStatus ? $t('open') : $t('putAway') }}
<a-icon :type="toggleSearchStatus ? 'up' : 'down'" />
</a>
<a-button class="box-button" type="primary" icon="search" @click="searchQuery">{{ $t('query') }}</a-button>
<a-button class="box-button" icon="reload" style="margin-left: 8px" @click="searchReset">{{ $t('reset') }}</a-button>
</div>
</a-row>
</a-form>
</div>
<div class="table-page-oper-submitButtons">
<!--催办-->
<a-button type="primary" @click="handleUrge" icon="bell" v-if="showUrgeButton">
{{ $t('workCenter.processDetail.urgeHandle') }}
</a-button>
<!--流程图-->
<!--<a-button type="primary" @click="viewFlowChart" icon="apartment" ghost>{{ $t('workCenter.processDetail.flowChart') }}</a-button>-->
</div>
<div>
<!-- rowKey加了id是因为强制撤回的记录没有taskId -->
<j-table
:columns="columns"
:dataSource="dataSource"
:can-drag="true"
:loading="loading"
:rowKey="record => {return record.id + ',' + (record.taskId || '')}"
:row-selection="{ selectedRowKeys: selectedRowKeys, onChange: onSelectChange }"
:pagination="ipagination"
:scroll="{x: '100%', y: yScrollHeight}"
@change="handleTableChange">
<!-- 耗时 -->
<!--<template v-slot:timeConsuming="{text, record}">-->
<!-- <a-tooltip overlay-class-name="tooltip-style">-->
<!-- <template slot="title">{{ record.endTime && record.createTime ? computedTimeConsuming(record) : global.emptyLine }}</template>-->
<!-- <div class="table-text">-->
<!-- {{ record.endTime && record.createTime ? computedTimeConsuming(record) : global.emptyLine }}-->
<!-- </div>-->
<!-- </a-tooltip>-->
<!--</template>-->
<!-- 任务节点 -->
<template v-slot:taskNode="{text, record}">
<a-tooltip overlay-class-name="tooltip-style">
<template slot="title">{{ text || text === 0 ? text : global.emptyLine }}</template>
<a v-if="text && record.snapshotId" class="link-a" @click="handleLookDetail(record)">{{ text }}</a>
<div v-else-if="text && !record.snapshotId" class="table-text">{{ text }}</div>
<div v-else class="table-text">{{ global.emptyLine }}</div>
</a-tooltip>
</template>
<!--审批意见-->
<template v-slot:approvalOpinion="{text, record}">
<a-tooltip overlay-class-name="tooltip-style">
<template slot="title">{{ text || text === 0 ? record.commitFlag_dictText : global.emptyLine }}</template>
<div class="table-text" :class="{'agree-color': record.commitFlag + '' === '1', 'reject-color': record.commitFlag + '' === '2'}">
{{ text || text === 0 ? record.commitFlag_dictText : global.emptyLine }}
</div>
</a-tooltip>
</template>
<!--附件-->
<template v-slot:file="{text, record}">
<a v-if="text" @click="fileLook(record)">{{ $t('view') }}</a>
<div v-else class="table-text">{{ global.emptyLine }}</div>
<!--<a-tooltip overlay-class-name="tooltip-style">-->
<!-- <template slot="title">{{ text || text === 0 ? text : global.emptyLine }}</template>-->
<!-- <div class="table-text can-click-table-text" v-if="text || text === 0" @click="handlePreview(record)">{{ text }}</div>-->
<!-- <div v-else class="table-text">{{ global.emptyLine }}</div>-->
<!--</a-tooltip>-->
</template>
</j-table>
</div>
<div id="images">
<div class="image" v-viewer="{movable: false}">
<img v-show="image" :src="imageUrl" alt="">
</div>
</div>
</div>
<flow-chart-modal ref="flowChartModal" />
<upload-file ref="uploadFile" disabled></upload-file>
</div>
</template>
<script>
import { JeroListMixin } from '../mixins/JeroListMixin.js'
import JTable from './jero/JTable.vue'
import Vue from 'vue'
import { ACCESS_TOKEN } from '../store/mutation-types.js'
import { downloadFile, getFileAccessHttpUrl, getAction } from '../api/manage.js'
import { previewPdf } from '../utils/previewPdf.js'
import FlowChartModal from './FlowChartModal.vue'
import UploadFile from './UploadFile'
import { filterObj } from '../utils/util'
import { kkFilePreview } from '../utils/kkFilePreview'
import { urgeProcessNode } from '../api/workCenter'
import { ProcessKey } from '../enums/commonEnums'
import { queryDepartTreeList } from '../api/api'
// 支持预览的文件后缀
const CAN_PREVIEW_FILE_SUFFIX = ['jpg', 'jpeg', 'png', 'pdf', 'doc', 'docx', 'xls', 'xlsx', 'ppt', 'pptx']
const FILE_TYPE_IMGS = ['jpg', 'jpeg', 'png', 'raw']
const FILE_TYPE_PDF = 'pdf'
export default {
name: 'ProcessDetailList',
components: { UploadFile, JTable, FlowChartModal },
mixins: [JeroListMixin],
props: {
// 需要有list属性,用于混入里的接口获取
url: {
type: Object,
required: false,
default: () => {
return {
list: '/workCenter/getApprovalRecordList'
}
}
},
// 催办按钮的权限
urgePermissionFlag: {
type: String,
required: false,
default: null
},
// 流程图按钮的权限
flowChartPermissionFlag: {
type: String,
required: false,
default: null
},
// 流程key
processKey: {
type: String,
required: false,
default: null
},
// 是否展示催办按钮
showUrgeButton: {
type: Boolean,
required: false,
default: false
},
// 是否可以点击节点名称跳转
nodeNameClick: {
type: Boolean,
required: false,
default: false
},
// 详情页从哪里点进来的(已办,已发还是监控流程)
detailFrom: {
type: String,
required: false,
default: ''
}
},
watch: {
nodeNameClick: {
immediate: true,
handler (val) {
if (val) {
this.columns[0].scopedSlots.customRender = 'taskNode'
} else {
this.columns[0].scopedSlots.customRender = 'text'
}
}
}
},
computed: {
yScrollHeight () {
/**
* 前几个使用变量是为了配合iframe嵌套,算出页面显示范围的高度
* 48px:分页器的高度
* 48pxa-card的padding(上24+下24
* 54px:表头行的高度
*/
return `calc(100vh - ${this.defaultHeight['user-info-height']} - ${this.defaultHeight['breadcrumb-height']} - ${this.defaultHeight.oneLineSearchHeight} - ${this.defaultHeight.oneLineOperationHeight} - 48px - 48px - 54px - 56px)`
}
},
data () {
return {
labelCol: {
span: 1
},
wrapperCol: {
span: 14
},
columns: [
// 任务节点
{
dataIndex: 'taskName',
title: this.$t('workCenter.processDetail.taskNode'),
width: 150,
scopedSlots: { customRender: 'taskNode' }
},
// 任务受理人
{
dataIndex: 'taskAcceptor',
title: this.$t('workCenter.processDetail.taskHandler'),
width: 120
},
// 创建时间
{
dataIndex: 'createTime',
title: this.$t('createTime'),
width: 150
},
// 完成时间
{
dataIndex: 'endTime',
title: this.$t('workCenter.processDetail.completionTime'),
width: 150
},
// 耗时
{
title: this.$t('workCenter.processDetail.timeConsuming'),
width: 150,
dataIndex: 'overTime',
scopedSlots: { customRender: 'text' }
},
// 审批意见
{
dataIndex: 'commitFlag',
title: this.$t('workCenter.processDetail.approvalOpinion'),
width: 100,
scopedSlots: { customRender: 'approvalOpinion' }
},
// 意见内容
{
dataIndex: 'commitText',
title: this.$t('workCenter.processDetail.opinionContent'),
width: 120
},
// 附件
{
dataIndex: 'commitFile',
title: this.$t('businessSupport.questionAnswer.attach'),
width: 160,
scopedSlots: { customRender: 'file' }
},
// 状态
{
dataIndex: 'finishFlag_dictText',
title: this.$t('status'),
width: 100
}
],
image: false,
imageUrl: null,
/* 排序参数 */
// 后端需要去掉
isorter: null,
toggleSearchStatus: false,
categoryTreeList: [] // 组织机构下拉框数据
}
},
mounted () {
this.getSysCategoryTree()
},
methods: {
// 获取组织机构树
getSysCategoryTree () {
queryDepartTreeList().then((res) => {
if (res.success) {
this.categoryTreeList = res.result
} else {
this.categoryTreeList = []
}
})
},
loadData (arg) {
if (!this.url.list) {
this.$message.warning('请设置url.list属性!')
return
}
if (arg === 1) {
this.ipagination.current = 1
}
const params = this.getQueryParams()// 查询条件
// 流程监控进详情,并且是已撤回的流程不查状态为进行中的任务
if (this.$route.query.source === 'monitorList' && this.$route.query.prcStatus === '3') {
params.finishFlagSearch = '2,3,4'
}
// 是已办,已发还是监控流程的查审批记录
if (this.detailFrom) {
params.type = this.detailFrom
}
if (this.$route.query.processInstanceId) {
params.processInstanceId = this.$route.query.processInstanceId
} else {
// 没有流程实例id,那就是新增,不用查
return
}
this.loading = true
getAction(this.url.list, params).then((res) => {
if (res.success) {
// update-begin---author:zhangyafei Date:20201118 for:适配不分页的数据列表------------
this.dataSource = res.result.records || res.result
if (res.result.total) {
this.ipagination.total = res.result.total
} else {
this.ipagination.total = 0
}
// update-end---author:zhangyafei Date:20201118 for:适配不分页的数据列表------------
} else {
this.$message.warning(res.message)
}
}).finally(() => {
this.loading = false
})
},
getQueryParams () {
// 获取查询条件
const sqp = {}
if (this.superQueryParams) {
sqp.superQueryParams = encodeURI(this.superQueryParams)
sqp.superQueryMatchType = this.superQueryMatchType
}
const param = Object.assign(sqp, this.queryParam, this.isorter, this.filters)
param.field = this.getQueryField()
param.pageNo = this.ipagination.current
param.pageSize = this.ipagination.pageSize
return filterObj(param)
},
// 计算耗时
computedTimeConsuming (record) {
// 结束时间和创建时间
const endTime = new Date(record.endTime)
const createTime = new Date(record.createTime)
// 计算时间差 转化为秒数
const time = parseInt((endTime.getTime() - createTime.getTime()) / 1000)
// 总秒数转化为对应的天数
const days = parseInt(time / (24 * 60 * 60))
// 计算小时
const hours = parseInt((time % (24 * 60 * 60)) / (60 * 60))
// 计算分钟
const minutes = parseInt((time % (60 * 60)) / 60)
// 计算秒
const seconds = time % 60
return (days ? days + '天 ' : '') + (hours ? hours + '小时 ' : '') +
(minutes ? minutes + '分钟 ' : '') + (seconds ? seconds + '秒' : '')
},
// 附件列的查看点击
fileLook (record) {
this.$refs.uploadFile.open(record.commitFile)
},
handleToggleSearch () {
this.toggleSearchStatus = !this.toggleSearchStatus
},
/**
* 催办
*/
handleUrge () {
if (!this.selectedRowKeys || this.selectedRowKeys.length === 0) {
this.$message.warning(this.$t('selectAtLeastOne'))
return
}
this.loading = true
const taskIds = this.selectedRowKeys.map(item => {
return item.split(',')[1]
})
urgeProcessNode({ taskId: taskIds.join(',') }).then(res => {
if (res.success) {
this.$message.success(res.message)
} else {
this.$message.warning(res.message)
}
}).finally(() => {
this.loading = false
})
},
/**
* 跳转流程图页面
*/
viewFlowChart () {
if (!this.processKey) {
return
}
this.$refs.flowChartModal.processKey = this.processKey
this.$refs.flowChartModal.open()
},
handlePreview (file) {
if (!file || !file.url) {
return
}
// 截取文件后缀名
const fileSuffix = file.fileName ? file.fileName.split('.')[file.fileName.split('.').length - 1] : ''
const canPreview = CAN_PREVIEW_FILE_SUFFIX.some(tt => fileSuffix.toLowerCase() === tt)
// 判断是否为可预览格式的文件
if (!canPreview) {
this.$message.loading('该文件类型不支持预览,正在为您准备下载...').then(() => {
this.handleDownload(file)
})
return
}
const fileFullUrl = `${window._CONFIG.domianWebSocketURL}/sys/common/view/${file.id}?at=${Vue.ls.get(ACCESS_TOKEN)}&fullfilename=${file.fileName}`
// 图片预览,使用自己添加的组件
if (canPreview && FILE_TYPE_IMGS.includes(fileSuffix.toLowerCase())) {
this.imageUrl = getFileAccessHttpUrl(file.id)
// 获取viewer实例
const viewer = this.$el.querySelector('.image').$viewer
// 调用show方法进行显示预览图
viewer.show()
// this.$refs.imagePreviewModal.open(file)
return
}
// pdf预览
if (canPreview && FILE_TYPE_PDF.includes(fileSuffix.toLowerCase())) {
const url = previewPdf(file.id)
window.open(url)
return
}
// 其余可预览文件仍使用KKFile进行预览
kkFilePreview(fileFullUrl)
},
// 跳转流程基本信息页面
handleLookDetail (record) {
let path = ''
console.log('-------processKey', this.$route.query.processKey)
// 跳转到对应流程页面
switch (this.$route.query.processKey + '') {
// 标准法规入库/变更流程
case ProcessKey.FB_ENTRY_CHANGE.value:
path = '/workCenter/StandardEntryOrChangeProcess'
break
// 标准征求意见流程
case ProcessKey.CONSULTATION.value:
path = '/workCenter/StandardConsultationProcess'
break
// 项目合规评估流程
case ProcessKey.PROJECT_COMPLIANCE_EVALUATION.value:
path = '/workCenter/ProjectComplianceEvaluationProcess'
break
// 未符合项跟踪流程
case ProcessKey.NO_MATCH_TRACKING.value:
path = '/workCenter/NoMatchTrackingProcess'
break
// 法规合规评估流程
case ProcessKey.REGULATORY_COMPLIANCE_ASSESSMENT.value:
path = '/workCenter/StandardComplianceProcess'
break
// 法规采购流程
case ProcessKey.LEGAL_PROCUREMENT.value:
path = '/workCenter/StandardProcurementProcess'
break
// 企标立项、变更计划
case ProcessKey.ES_INIT_CHANGE.value:
path = '/workCenter/enterpriseStandardInitChange/planApprovalChangeFlow'
break
// 年度制修订计划(各部门主动上报)
case ProcessKey.ES_ANNUAL_REPORT.value:
path = '/workCenter/annualRevisionPlanActivelyReport/revisionPlanActivelyReportFlow'
break
// 年度制修订计划(标准化发起)
case ProcessKey.ES_ANNUAL_INIT.value:
path = '/workCenter/annualRevisionPlanStandardizationInit/revisionPlanStandardizationInitFlow'
break
// 企标制修订流程
case ProcessKey.ES_EDIT.value:
path = '/workCenter/enterpriseStandardRevision/enterpriseStandardRevisionFlow'
break
// 企标更改流程
case ProcessKey.ES_CHANGE.value:
path = '/workCenter/enterpriseStandardChange/enterpriseStandardChangeFlow'
break
// 企标复审流程
case ProcessKey.ES_RECHECK.value:
path = '/workCenter/enterpriseStandardRecheck/enterpriseStandardRecheckFlow'
break
// 企标废止流程
case ProcessKey.ES_ABOLISH.value:
path = '/workCenter/enterpriseStandardAnnul/enterpriseStandardAnnulFlow'
break
// 企标封存流程
case ProcessKey.ES_ARCHIVE.value:
path = '/workCenter/enterpriseStandardSealSave/enterpriseStandardSealSaveFlow'
break
// 已封存企标启用流程
case ProcessKey.ES_ENABLE.value:
path = '/workCenter/enterpriseStandardStartUse/enterpriseStandardStartUseFlow'
break
// 企标稽查计划
case ProcessKey.ES_INSPECTION_PLAN.value:
path = '/workCenter/EnterpriseStandardInspectionPlan'
break
// 企标稽查流程
case ProcessKey.ES_INSPECTION_PROCESS.value:
path = '/workCenter/EnterpriseStandardInspectionProcess'
break
// 稽查延期申请流程
case ProcessKey.INSPECTION_EXTENSION_REQUEST_PROCESS.value:
path = '/workCenter/InspectionExtensionRequestProcess'
break
// 企标稽查整改
case ProcessKey.ES_INSPECTION_RECTIFICATION.value:
path = '/workCenter/EnterpriseStandardInspectionRectification'
break
// 权限申请流程
case ProcessKey.PERMISSION_APPLY.value:
path = '/workCenter/PermissionApplicationProcess'
break
// 标准宣贯流程
case ProcessKey.STANDARD_PROMOTION.value:
path = '/workCenter/StandardPromotionProcess'
break
// 会后管理流程
case ProcessKey.POST_MEETING_MANAGE.value:
path = '/workCenter/PostMeetingManageProcess'
break
}
const query = {}
query.taskName = record.taskName
query.taskId = record.taskId // 为了不影响部分节点的导出
query.snapshotId = record.snapshotId // 快照id
query.nodeId = record.nodeId // 节点的id
query.isLook = 1
this.$router.push({
path: path,
query: query
})
}
}
}
</script>
<style scoped lang="less">
.page-box {
height: 100%;
display: flex;
}
.personnel-info {
height: 100%;
width: 400px;
padding: 32px;
overflow: auto;
border-right: 1px solid #E5E6EB;
}
.approval-list {
height: 100%;
flex: 1;
width: 0;
overflow: auto;
padding: 32px 32px 0;
}
.agree-color {
color: #229B1F;
}
// 这个地方的颜色不用primary-color是因为拒绝永远是红色的
.reject-color {
color: #D52C26;
}
.table-page-oper-submitButtons {
.ant-btn {
margin-bottom: 20px;
}
}
/deep/ .ant-form-item-label {
min-width: 90px !important;
}
</style>