999 lines
26 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>
<view>
<view class="fixedheader">
<headers :showBack="true">
<view class="headerName">
流程详情
</view>
</headers>
</view>
<view :style="{paddingTop: (mobileTopHeight + 50) * 1.5 + 'rpx'}" v-if="instanceData">
<scroll-view class="w-instace" scroll-y show-scrollbar @scroll="scroll"
:style="{height: contentHeight + 'px'}">
<view class="w-instace-header" v-if="instanceData.staterUser">
<Avatar :name="instanceData.staterUser.name" :src="getRes(instanceData.staterUser.avatar)" showY>
</Avatar>
<view>
<view style="display: flex; align-items: center;">
<text style="margin-right: 20rpx;">{{instanceData.processDefName}}</text>
<uni-tag circle="true" :text="instanceData.status"
:type="getProcTag(instanceData.result).type" inverted></uni-tag>
</view>
<view>编号{{instanceData.instanceId}}</view>
</view>
<image v-if="instanceData.statusImg" :src="instanceData.statusImg" mode="aspectFill"></image>
</view>
<view class="w-instace-form">
<view class="process-form" v-for="item in instanceData.formItems" :key="item.id">
<view>
{{ item.title }}
</view>
<view v-if="item.name == 'ImageUpload'">
<image v-for="ele in instanceData.formData[item.id]" :key="item.id"
@click="previewImg(url_config + 'image/' + ele.url)" style="width: 200rpx; height: 200rpx"
:src="url_config + 'image/' + ele.url" fit="cover"></image>
</view>
<view v-else-if="item.name == 'FileUpload'">
<view class="download" @click="downloadFn(item)"
v-for="item in instanceData.formData[item.id]" :key="item.id">
{{ item.name }}
</view>
</view>
<div style="display: flex; flex-wrap: wrap" v-else-if="item.name == 'UserPicker'">
<Avatar v-for="ele in instanceData.formData[item.id]" :key="ele.id" showY :name="ele.name"
:src="getRes(ele.avatar)" />
</div>
<view v-else>
{{ formDataFn(item) }}
</view>
</view>
<!-- <form-render :jsonConf="instanceData.formItems" v-model="instanceData.formData"></form-render> -->
</view>
<view class="w-instace-process">
<process-progress :progress="instanceData.progress" :status="instanceData.status"
:result="instanceData.result"></process-progress>
</view>
</scroll-view>
<view class="w-instace-action" v-if="instanceData.operationPerm || !instanceData.finishTime">
<view class="w-action">
<view @click="doAction('comment')">
<uni-icons2 type="chat" class="uni-icons_34"></uni-icons2>
<view>评论</view>
</view>
<!-- <view @click="showMore">
<uni-icons2 type="more-filled" class="uni-icons_34"></uni-icons2>
<view>更多</view>
</view> -->
<view class="w-action-main">
<button
v-if="instanceData.operationPerm && instanceData.operationPerm.refuse && instanceData.operationPerm.refuse.show"
@click="doAction('refuse')">
{{instanceData.operationPerm.refuse.alisa}}
</button>
<button type="primary"
v-if="instanceData.operationPerm && instanceData.operationPerm.agree && instanceData.operationPerm.agree.show"
@click="doAction('agree')">
{{instanceData.operationPerm.agree.alisa}}
</button>
</view>
</view>
</view>
<uni-popup ref="actionPopup" type="bottom" background-color="#fff">
<view class="w-more-title">选择您的审批操作</view>
<view class="w-action-mores">
<view
v-if="instanceData.operationPerm && instanceData.operationPerm.transfer && instanceData.operationPerm.transfer.show"
@click="doAction('transfer')">
<uni-icons2 type="staff" class="uni-icons_34"></uni-icons2>
<view>转交</view>
</view>
<view
v-if="instanceData.operationPerm && instanceData.operationPerm.recall && instanceData.operationPerm.recall.show"
@click="doAction('recall')">
<uni-icons2 type="undo" class="uni-icons_34"></uni-icons2>
<view>退回</view>
</view>
<view
v-if="instanceData.operationPerm && instanceData.operationPerm.afterAdd && instanceData.operationPerm.afterAdd.show"
@click="doAction('afterAdd')">
<uni-icons2 type="personadd" class="uni-icons_34"></uni-icons2>
<view>后加签</view>
</view>
<view v-if="enableCancel" @click="doAction('cancel')">
<uni-icons2 type="refreshempty" class="uni-icons_34"></uni-icons2>
<view>撤销</view>
</view>
</view>
<button class="w-more-close" type="default" @click="$refs.actionPopup.close()"> </button>
</uni-popup>
<uni-popup ref="doActionPopup" type="bottom" background-color="#fff">
<view class="w-more-title">{{action.title}}</view>
<view class="w-action-content">
<view style="display: flex; align-items: center;"
v-if="action.type === 'afterAdd' || action.type === 'transfer'">
<text>目标人员</text>
<view style="flex: 1;">
<UserPicker @update:modelValue="selectedUser= $event" position="bottom"></UserPicker>
</view>
</view>
<view style="display: flex; align-items: center;" v-else-if="action.type === 'recall'">
<text>回退节点</text>
<view style="flex: 1;">
<SelectPicker labelKey="nodeName" valueKey="nodeId"
@update:modelValue="handerParams.targetNode= $event" :options="recallNodes" />
</view>
</view>
<view style="display: flex; align-items: center;" v-if="activeTasks.length > 1">
<text>处理节点</text>
<view style="flex: 1;">
<select-picker placeholder="要处理哪个任务" valueKey="taskId" labelKey="name"
v-model="handerParams.taskId" :options="activeTasks" />
</view>
</view>
<uni-easyinput type="textarea" v-model="handerParams.comment.text" :placeholder="action.tip" />
<view style="margin: 32rpx 0;">
<FileUpload ref="attachFile" :formProps="{maxSize: 10, placeholder:'审批附件'}"
@update:modelValue="attachment.files= $event" />
<ImageUpload :formProps="{maxSize: 10, placeholder:'审批附图', maxNumber: 5}"
@update:modelValue="attachment.images = $event" />
<view style="margin-top: 32rpx;" v-if="showSignCt">
<sign-panel position="bottom" v-model="handerParams.signature" />
</view>
</view>
</view>
<view class="w-action-confirm">
<button type="default" @click="$refs.doActionPopup.close()">取消</button>
<button type="primary" @click="submitAction"> </button>
</view>
</uni-popup>
</view>
</view>
</template>
<script>
import {
getFormAndProcessProgress,
approvalTask,
getEnableRecallNodes,
getTaskNodeSettings
} from '@/api/task'
import {
$nEmpty,
debounce,
} from '@/utils/tool.js'
import {
getUserSign
} from "@/api/org";
import Avatar from '@/pages/projectEnd/safeSame/components/Avatar.vue'
import processProgress from '@/pages/projectEnd/safeSame/components/processProgress.vue'
import UserPicker from '@/pages/projectEnd/safeSame/components/UserPicker.vue'
import ImageUpload from "@/pages/projectEnd/safeSame/components/ImageUpload.vue";
import FileUpload from "@/pages/projectEnd/safeSame/components/FileUpload.vue";
import SelectPicker from "@/pages/projectEnd/safeSame/components/SelectPicker.vue";
export default {
components: {
Avatar,
processProgress,
ImageUpload,
FileUpload,
UserPicker,
SelectPicker
},
data() {
return {
nodeId: null,
instanceId: null,
instanceData: null,
selectedUser: [],
recallNodes: [],
showSign: false,
action: {
type: '',
title: null,
tip: null
},
attachment: {
files: [],
images: []
},
handerParams: {
instanceId: null,
taskId: null,
comment: {
text: null,
attachments: []
},
formData: {},
signature: null,
action: null,
updateSign: false,
targetNode: null,
targetUser: null,
userId: null,
},
workerListOptions: [], // 施工人员
cooperatorList: [], // 所有企业信息
deviceUnitList: [], // 装置列表
enterpriseTypeListFull: [], // 全部企业信息
classifyListUp: [], // 问题描述
xzProjectOrgList: [], // 组织列表
technicalExpertiseList: [{
id: 1,
name: '土建'
},
{
id: 2,
name: '管道'
},
{
id: 3,
name: '设备'
},
{
id: 4,
name: '电气'
},
{
id: 5,
name: '仪表'
},
{
id: 6,
name: '其他'
}
], // 涉及技术专业
projectSn: "",
mobileTopHeight: 0,
}
},
created() {
this.getWorkerInfo();
this.getCooperatorList();
this.projectGroupListFn();
this.getDeviceUnitList();
this.getDescribeClassifyList();
this.getXzProjectOrgList();
},
onLoad(v) {
this.nodeId = v.nodeId;
this.instanceId = v.instanceId;
this.getInstanceData(v.instanceId, v.nodeId);
this.projectSn = JSON.parse(uni.getStorageSync('projectDetail')).projectSn;
},
mounted() {
//当前登录的用户
this.userId = JSON.parse(uni.getStorageSync('userInfo')).userId;
var that = this
uni.getSystemInfo({
success(res) {
that.mobileTopHeight = res.statusBarHeight ? res.statusBarHeight : 0;
console.log(res)
}
})
},
onShow() {
},
computed: {
//获取文件访问路径
getRes() {
return (url) => {
if (url) {
const reg = /^(http:|https:).*/gi
return reg.test(url) ? url : this.url_config + 'image/' + url
} else {
return url
}
}
},
getProcTag() {
return (result) => {
switch (result) {
case 'RUNNING':
return {
text: '进行中', type: 'primary'
}
case 'COMPLETE':
return {
text: '已结束', type: 'primary'
}
case 'PASS':
return {
text: '审批通过', type: 'success'
}
case 'CANCEL':
return {
text: '已撤销', type: 'default'
}
case 'REFUSE':
return {
text: '审批驳回', type: 'error'
}
default:
return {
text: '未知状态', type: 'default'
}
}
}
},
showSignCt() {
return this.showSign && this.action.type === 'agree'
},
enableCancel() {
try {
return this.instanceData?.externSetting?.enableCancel
} catch (e) {
return false
}
},
//过滤本人下待处理的节点
activeTasks() {
let tasks = [];
(this.instanceData.progress || []).forEach(task => {
if (task.isFuture) return
if (task.users) {
task.users.forEach(tk => {
if (tk.user && tk.user.id === this.userId && !$nEmpty(tk
.finishTime)) {
tasks.push(tk)
}
})
} else {
if (task.user && task.user.id === this.userId && !$nEmpty(task.finishTime)) {
tasks.push(task)
}
}
})
return tasks;
},
contentHeight() {
const h = uni.getSystemInfoSync().windowHeight
return this.instanceData.finishTime ? h - 100 : h - 120
},
formDataFn() {
return (row) => {
const result = this.instanceData.formData;
console.log(11111, row.id, row.name)
if (row.name == 'SelectPlus') {
if (row.id == 'field8461427261832') {
return this.deviceUnitList
.filter(item => result[row.id].includes(item.id))
.map(item => item.deviceUnitName)
.join('、');
} else if (row.id == 'field2236827437883') {
return this.enterpriseTypeListFull
.filter(item => result[row.id].includes(item.id))
.map(item => item.projectGroupName)
.join('、');
} else if (row.id == 'field4800627374284' ||
row.id == 'field7608927385682' ||
row.id == 'field3317527412133' ||
row.id == 'field8417827396166' ||
row.id == 'field9019727475232') {
console.log(3333, result[row.id], this.cooperatorList)
return this.cooperatorList
.filter(item => result[row.id].includes(item.id))
.map(item => item.enterpriseName)
.join('、');
} else if (row.id == 'field3918219183947') {
return this.xzProjectOrgList
.filter(item => result[row.id].includes(item.id))
.map(item => item.deptName)
.join('、');
} else if (row.id == 'field5714131333262') {
return this.technicalExpertiseList
.filter(item => result[row.id].includes(item.id.toString()))
.map(item => item.name)
.join('、');
} else if (row.id == 'field7469574611447') {
return this.workerListOptions
.filter(item => result[row.id].includes(item.id))
.map(item => item.workerName)
.join('、');
}
return result[row.id];
} else if (row.name == 'DateTimeRange') {
console.log(result[row.id]);
return result[row.id].join(' - ');
} else if (row.name == 'CascaderSelect') {
if (row.id == 'field9069961325117' || row.id == 'field5281362911293') {
let resultList = result[row.id].split('-');
resultList = row.id == 'field9069961325117' ? [resultList[resultList.length - 1]] :
resultList;
return this.setData(this.classifyListUp, resultList, 'dangerName', 'content', '-');
}
return '';
}
if (Array.isArray(result[row.id])) {
return result[row.id].map(item => item.name).join('、')
}
return result[row.id];
};
},
},
watch: {
'handerParams.taskId': {
handler(newVal) {
this.getTaskSet()
},
}
},
methods: {
downloadFn(item) {
var that = this
uni.showModal({
title: '提示',
content: item.name,
confirmText: '下载',
success: function(res) {
if (res.confirm) {
uni.downloadFile({
url: that.url_config + 'image/' + item.url, //仅为示例,并非真实的资源
success: (res) => {
console.log(res)
if (res.statusCode === 200) {
// uni.showToast({
// title:'下载成功'
// })
var filePath = res.tempFilePath;
if (!filePath) return
uni.openDocument({
filePath: filePath,
success: function(res) {
console.log(res);
console.log('打开文档成功');
uni.showToast({
title: '打开文档成功'
})
}
});
} else {
uni.showToast({
title: '下载失败'
})
}
}
});
} else if (res.cancel) {
console.log('用户点击取消');
}
}
});
},
previewImg(img) {
console.log(img);
uni.previewImage({
urls: [img],
longPressActions: true
})
},
//获取问题描述 和 问题分类 下拉列表
getDescribeClassifyList() {
this.sendRequest({
url: 'xmgl/xzSecurityDangerTypeRecord/selectDangerTypeAndItemList',
method: "post",
data: {
projectSn: this.projectSn,
recordStatus: 0
},
success: res => {
if (res.code == 200) {
this.classifyListUp = this.classifyListFn(res.result);
}
}
})
},
classifyListFn(dataList, reduceList = []) {
dataList.forEach(item => {
reduceList.push(item);
if (item.children) {
this.classifyListFn(item.children, reduceList);
} else if (item.itemList) {
this.classifyListFn(item.itemList, reduceList);
}
});
return reduceList;
},
getDeviceUnitList() {
this.sendRequest({
url: 'xmgl/deviceUnit/page',
method: "get",
data: {
projectSn: this.projectSn,
pageNo: 1,
pageSize: -1,
seeI: 1,
},
success: res => {
if (res.code == 200) {
this.deviceUnitList = res.result.records;
}
}
})
},
getXzProjectOrgList() {
this.sendRequest({
url: 'xmgl/xzProjectOrg/list',
method: "get",
data: {
projectSn: this.projectSn,
pageNo: 1,
pageSize: -1
},
success: res => {
if (res.code == 200) {
this.xzProjectOrgList = res.result;
}
}
})
},
projectGroupListFn() {
this.sendRequest({
url: 'xmgl/projectGroup/page',
method: "get",
data: {
projectSn: this.projectSn,
pageNo: 1,
pageSize: -1
},
success: res => {
if (res.code == 200) {
this.enterpriseTypeListFull = res.result.records;
}
}
})
},
//获取列表数据
getCooperatorList() {
this.sendRequest({
url: 'xmgl/projectEnterprise/list',
method: "post",
data: {
projectSn: this.projectSn,
page: 1,
pageSize: -1,
},
success: res => {
if (res.code == 200) {
this.cooperatorList = res.result.records;
}
}
})
},
getWorkerInfo() {
this.sendRequest({
url: 'xmgl/workerInfo/selectWorkerInfoList',
method: "post",
data: {
projectSn: this.projectSn,
},
success: res => {
if (res.code == 200) {
this.workerListOptions = res.result.records;
}
}
})
},
//滚动延时去抖动
scDebounce() {
debounce(() => uni.$emit('showFp'), 500)
},
getTaskSet() {
getTaskNodeSettings(this.handerParams.taskId).then(rsp => {
this.showSign = rsp.data.enableSign || false
}).catch(e => {})
},
recursionFormItems(dataList, resultList = []) {
dataList.forEach(item => {
if (item.name == 'SpanLayout') {
this.recursionFormItems(item.props.items, resultList);
} else {
resultList.push(item);
}
});
return resultList;
},
getInstanceData(instId, nodeId) {
getFormAndProcessProgress(instId, nodeId).then(rsp => {
if (rsp.data.code == 200) {
this.instanceData = rsp.data.result;
this.instanceData.formItems = this.recursionFormItems(rsp.data.result.formItems);
//设置状态图标
switch (this.instanceData.result) {
case 'PASS':
this.instanceData.statusImg = '/static/image/agree.png'
break
case 'CANCEL':
this.instanceData.statusImg = '/static/image/recall.png'
break
case 'REFUSE':
this.instanceData.statusImg = '/static/image/refuse.png'
break
}
} else {
uni.showToast({
title: rsp.data.message,
icon: 'none'
})
}
})
},
showMore() {
this.$refs.actionPopup.open()
},
urging() {
uni.showModal({
title: '催办确认',
content: '您确认要提醒流程中人员尽快处理任务?',
success: function(res) {
if (res.confirm) {
uni.showToast({
icon: 'none',
title: '该功能暂未实现哈😘'
})
} else if (res.cancel) {
}
}
});
},
doAction(type) {
this.handerParams.taskId = this.getTask()
this.selectedUser = []
this.handerParams.targetUser = null
this.handerParams.comment.text = ''
this.handerParams.comment.attachments = []
switch (type) {
case 'comment':
this.action = {
type: type,
title: '添加评论',
tip: '评论内容'
}
break;
case 'transfer':
this.action = {
type: type,
title: '转交流程',
tip: '转交意见',
}
break;
case 'afterAdd':
this.action = {
type: type,
title: '流程节点加签',
tip: '加签意见'
}
break;
case 'recall':
this.action = {
type: type,
title: '退回流程',
tip: '退回意见'
}
this.getEnableRecallNode()
break;
case 'cancel':
this.action = {
type: type,
title: '撤销流程',
tip: '撤销原因'
}
break;
case 'agree':
this.action = {
type: type,
title: '审批同意',
tip: '审批意见'
}
break;
case 'refuse':
this.action = {
type: type,
title: '审批拒绝',
tip: '审批意见'
}
break;
}
this.$refs.doActionPopup.open()
//使文件选择生效
this.$nextTick(() => {
this.$refs.attachFile && this.$refs.attachFile.show()
})
},
loadBeforeSign() {
getUserSign().then(rsp => {
if (rsp.data === '') {
uni.showToast({
icon: 'none',
title: '您还没有保存过的签名'
})
} else {
this.handerParams.signature = rsp.data
}
})
},
//获取要处理的任务id
getTask() {
if ($nEmpty(this.handerParams.taskId)) {
return this.handerParams.taskId
} else if (this.activeTasks.length > 0) {
return this.activeTasks[0].taskId
} else if (this.action.type === 'cancel') {
const pg = this.instanceData.progress || [];
for (let i = 0; i < pg.length; i++) {
if (pg[i].users) {
for (let j = 0; j < pg[i].users.length; j++) {
if (!$nEmpty(pg[i].users[j].finishTime)) {
return pg[i].users[j].taskId
}
}
} else {
if (!$nEmpty(pg[i].finishTime)) {
return pg[i].taskId
}
}
}
}
return null
},
getEnableRecallNode() {
getEnableRecallNodes(this.instanceData.instanceId, this.getTask()).then(rsp => {
this.recallNodes = rsp.data
}).catch(err => {
uni.showToast({
icon: 'none',
title: '获取可回退节点失败'
})
})
},
submitAction() {
this.handerParams.instanceId = this.instanceData.instanceId
this.handerParams.action = this.action.type
this.handerParams.taskId = this.getTask()
this.handerParams.formData = this.instanceData.formData
this.handerParams.comment.attachments = [...this.attachment.files, ...this.attachment.images]
console.log(this.handerParams.comment.attachments)
if ((this.action.type === 'afterAdd' || this.action.type === 'transfer') && !this.selectedUser.length >
0) {
uni.showToast({
icon: 'none',
title: '请设置人员'
})
} else if (this.action.type === 'recall' && !$nEmpty(this.handerParams.targetNode)) {
uni.showToast({
icon: 'none',
title: '请选择回退节点'
})
} else if (this.showSignCt && !$nEmpty(this.handerParams.signature)) {
uni.showToast({
icon: 'none',
title: '请签字后再提交'
})
} else {
this.handerParams.targetUser = this.selectedUser?.[0]?.id
approvalTask(this.handerParams).then(rsp => {
uni.showToast({
icon: 'success',
title: '处理成功'
})
this.$refs.actionPopup.close()
this.$refs.doActionPopup.close()
if (this.action.type === 'comment') {
this.getInstanceData(this.instanceData.instanceId, this.nodeId)
} else {
// uni.reLaunch({
// url: '/pages/projectEnd/safeSame/list?type=1'
// })
this.getInstanceData(this.instanceId, this.nodeId);
}
}).catch(err => {
uni.showToast({
icon: 'none',
title: err.msg
})
})
return
}
},
scroll() {
// #ifdef APP-VUE
uni.$emit('wv:scorll');
// #endif
},
setData(dataList, id, name, name2, str) {
return dataList
.filter(item => id.includes(item.id))
.map(item => item[name] ? item[name] : item[name2])
.join(str);
}
}
}
</script>
<style lang="scss" scoped>
// .uni-popup :deep( view:has(>.uni-popup__wrapper-box)){
// background-color: white;
// }
.download {
color: #1684FC;
}
.uni-popup :deep(>view:last-child ){
background-color: white;
}
.process-form {
>view:first-child {
color: #606266;
}
>view {
min-height: 50rpx;
// line-height: 50rpx;
padding: 0 0;
font-size: 28rpx;
}
}
.fixedheader {
position: fixed;
top: 0;
left: 0;
width: 100%;
z-index: 2;
:deep(.headerBox ){
background: #2b8df3;
color: #fff;
}
}
page {
background-color: #F4F5F7;
}
:deep(.w-instace-form) {
.w-form-item {
margin-bottom: 0;
padding-bottom: 16rpx;
}
.w-form-item-r {
margin-bottom: 16rpx;
}
}
.w-instace {
height: calc(100vh - 88rpx) !important;
font-size: 32rpx;
padding-bottom: 144rpx;
.w-instace-header,
.w-instace-form,
.w-instace-process {
margin: 32rpx 0;
padding: 32rpx 16rpx;
background-color: white;
}
.w-instace-header {
margin-top: 0;
position: relative;
image {
position: absolute;
z-index: 2;
width: 160rpx;
height: 160rpx;
right: 32rpx;
bottom: -96rpx;
}
}
:deep(.w-instace-form) {
padding: 32rpx 16rpx;
.w-form-item-r {
padding-bottom: 0;
font-size: 26rpx;
.w-form-title :last-child {
font-size: 29rpx !important;
color: #848484;
}
}
}
.w-instace-header {
display: flex;
align-items: center;
font-size: 26rpx;
.uni-tag {
font-weight: 400;
}
}
}
.w-instace-action {
width: 100%;
height: 144rpx;
background-color: #EFEFEF;
display: flex;
justify-content: space-between;
position: fixed;
bottom: 0;
.w-action {
width: 100%;
display: flex;
align-items: center;
justify-content: space-between;
font-size: 25rpx;
text-align: center;
padding: 0 32rpx;
.w-action-main {
width: 40%;
display: flex;
right: 32rpx;
&>button {
// width: 128rpx;
font-size: 32rpx
}
}
}
}
.w-action-mores {
display: flex;
justify-content: space-between;
padding: 64rpx;
font-size: 32rpx;
&>view {
text-align: center;
}
}
.w-more-close {
background-color: #E8E8E8 !important;
border: none !important;
margin: 0 32rpx 32rpx 32rpx;
border-radius: 48rpx;
color: #848484;
}
.w-more-title {
font-size: 29rpx;
text-align: center;
margin-top: 16rpx;
color: #848484;
}
.w-action-content {
padding: 32rpx;
}
.w-action-confirm {
display: flex;
padding-bottom: 32rpx;
button {
width: 40%;
}
}
</style>