@lambo-design/workflow-approve 1.0.0-beta.6 → 1.0.0-beta.60

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src/portrait.vue CHANGED
@@ -1,1036 +1,1811 @@
1
- <template>
2
- <LamboPageContainer>
3
- <template slot="page-title">
4
- {{ title }}
5
- </template>
6
- <template slot="page-extend">
7
- <Button type="primary" ghost @click="pageGoBack">返回</Button>
8
- </template>
9
- <div class="portrait-lambo-indicator-card" :style="{float: 'left', width: isExpanded ? `calc(100% - ${portraitWidth+10}px)` : '99%'}">
10
- <slot name="business-content">
11
- </slot>
12
- </div>
13
-
14
- <a @click="isExpanded = !isExpanded" class="arrow-button-container" :style="{right: isExpanded ? portraitWidth+10 + 'px' : '10px'}">
15
- <Icon class="icon-class" v-if="isExpanded" type="ios-arrow-forward"/>
16
- <Icon class="icon-class" v-if="!isExpanded" type="ios-arrow-back"/>
17
- </a>
18
- <transition name="draw" @before-enter="beforeFlowInfoEnter" @enter="flowInfoEnter"
19
- @before-leave="beforeFlowInfoLeave" @leave="flowInfoLeave">
20
- <lamboIndicatorCard v-if="isExpanded" class="portrait-lambo-indicator-card" :style="{width: portraitWidth + 'px', float: 'right'}" :hasExtend="false">
21
- <div slot="content-title">流程信息</div>
22
- <a v-if="!isDetail" @click="auditShow = !auditShow">
23
- <Title v-if="!handleButtons || handleButtons.includes('auditOpinion') || handleButtons.includes('attachmentFile')">
24
- <a style="color: #989898">
25
- <Icon v-if="auditShow" type="ios-arrow-down"/>
26
- <Icon v-if="!auditShow" type="ios-arrow-up"/>
27
- 审批信息
28
- </a>
29
- </Title>
30
- </a>
31
- <transition v-if="!isDetail" name="draw" @before-enter="beforeEnter" @enter="enter" @before-leave="beforeLeave" @leave="leave">
32
- <div class="box" v-show="auditShow">
33
- <Form ref="auditOpinion" justify="center" :label-width="100" :model="form"
34
- v-if="!handleButtons || handleButtons.includes('auditOpinion')"
35
- style="margin: 10px 0 0 10px;" :rules="ruleValidate">
36
- <FormItem label="审批意见:" prop="auditOpinion" >
37
- <AuditOpinion v-model="form.auditOpinion" :attachment-file="handleButtons.includes('attachmentFile')"
38
- :attachmentdata="fileList" :smart-flow-server-context="smartFlowServerContext"></AuditOpinion>
39
- </FormItem>
40
- </Form>
41
- <Form ref="auditOpinion" justify="center" :label-width="100"
42
- v-if="handleButtons && !handleButtons.includes('auditOpinion') && handleButtons.includes('attachmentFile')"
43
- style="margin: 10px 0 0 10px;">
44
- <FormItem style="min-height: 70px">
45
- <Tooltip placement="bottom" max-width="200">
46
- <div style="font-size: smaller" slot="content">支持扩展名:.pdf .doc .docx .txt .xls .xlsx .jpg .jpeg .png .gif</div>
47
- <UploadFile @upload-result="uploadFile" :multiple="true"
48
- :oss-server-context="smartFlowServerContext" :oss-file-put-url="ossFilePutUrl"></UploadFile>
49
- </Tooltip>
50
- </FormItem>
51
- </Form>
52
- </div>
53
- </transition>
54
- <a v-if="isDetail && hisAuditOpinion[0].auditOpinion" @click="auditShow = !auditShow">
55
- <Title v-if="!handleButtons || handleButtons.includes('auditOpinion') || handleButtons.includes('attachmentFile')">
56
- <a style="color: #989898">
57
- <Icon v-if="auditShow" type="ios-arrow-down"/>
58
- <Icon v-if="!auditShow" type="ios-arrow-up"/>
59
- 审批信息
60
- </a>
61
- </Title>
62
- </a>
63
- <transition v-if="isDetail && hisAuditOpinion[0].auditOpinion" name="draw" @before-enter="beforeEnter" @enter="enter" @before-leave="beforeLeave" @leave="leave">
64
- <div class="box" v-show="auditShow">
65
- <Form ref="auditOpinion" justify="center" :model="form"
66
- v-if="!handleButtons || handleButtons.includes('auditOpinion')"
67
- style="margin: 10px 0 0 10px;" :rules="ruleValidate">
68
- <FormItem style="margin-left: -60px">
69
- <Card v-for="(item, index) in hisAuditOpinion" :key="index">
70
- <Row>
71
- <Col span="12" style="word-wrap: break-word">{{ item.auditOpinion }}</Col>
72
- <Col span="2"></Col>
73
- <Col span="10">{{ item.auditTime }}</Col>
74
- </Row>
75
- </Card>
76
- </FormItem>
77
- </Form>
78
- </div>
79
- </transition>
80
- <a @click="historyShow = !historyShow">
81
- <Title v-if="!handleButtons || handleButtons.includes('auditHistory')">
82
- <a style="color: #989898">
83
- <Icon v-if="historyShow" type="ios-arrow-down"/>
84
- <Icon v-if="!historyShow" type="ios-arrow-up"/>
85
- 审批记录
86
- </a>
87
- </Title>
88
- </a>
89
- <transition name="draw" @before-enter="beforeEnter" @enter="enter" @before-leave="beforeLeave" @leave="leave">
90
- <div class="box" v-show="historyShow">
91
- <Card class="process-history" dis-hover :bordered="false"
92
- v-if="!handleButtons || handleButtons.includes('auditHistory')">
93
- <processHistory :portrait-width="portraitWidth" :list="processHistory" :done-page="isDetail"
94
- :smart-flow-server-context="smartFlowServerContext"></processHistory>
95
- </Card>
96
- </div>
97
- </transition>
98
-
99
- <a @click="attachListShow = !attachListShow">
100
- <Title v-if="(!handleButtons || handleButtons.includes('attachmentFile')) && attachmentList.length > 0">
101
- <a style="color: #989898">
102
- <Icon v-if="attachListShow" type="ios-arrow-down"/>
103
- <Icon v-if="!attachListShow" type="ios-arrow-up"/>
104
- 查看附件
105
- </a>
106
- </Title>
107
- </a>
108
- <transition name="draw" @before-enter="beforeEnter" @enter="enter" @before-leave="beforeLeave" @leave="leave">
109
- <div class="box" v-show="(!handleButtons || handleButtons.includes('attachmentFile')) && attachmentList.length > 0 && attachListShow">
110
- <div v-for="(item, index) in attachmentList" :key="index">
111
- <Card dis-hover class="attach-card">
112
- <List item-layout="vertical">
113
- <ListItem style="margin-top: -8px">
114
- <Row style="display: flex; align-items: center;">
115
- <!-- 左边:图片 -->
116
- <Col span="4" style="margin-top: -25px">
117
- <avatar v-if="item.fileType === 'image'" icon="ios-image-outline" class="attach-avatar" style="background-color: #005aff" :style="portraitWidth >= 600 ? 'margin-left: 10px' : ''"
118
- :size="portraitWidth >= 600 ? 'middle' : 'small'"></avatar>
119
- <avatar v-else-if="item.fileType === 'doc'" icon="ios-document-outline" class="attach-avatar" style="background-color: #005aff" :style="portraitWidth >= 600 ? 'margin-left: 10px' : ''"
120
- :size="portraitWidth >= 600 ? 'middle' : 'small'">
121
- </avatar>
122
- <avatar v-else-if="item.fileType === 'xlsx'" icon="ios-document-outline" class="attach-avatar" style="background-color: #19be6b" :style="portraitWidth >= 600 ? 'margin-left: 10px' : ''"
123
- :size="portraitWidth >= 600 ? 'middle' : 'small'"></avatar>
124
- <avatar v-else-if="item.fileType === 'pdf'" icon="ios-document-outline" class="attach-avatar" style="background-color: #ed4014" :style="portraitWidth >= 600 ? 'margin-left: 10px' : ''"
125
- :size="portraitWidth >= 600 ? 'middle' : 'small'"></avatar>
126
- <avatar v-else icon="ios-document-outline" class="attach-avatar" :style="portraitWidth >= 600 ? 'margin-left: 10px' : ''"
127
- :size="portraitWidth >= 600 ? 'middle' : 'small'"></avatar>
128
- </Col>
129
- <!-- 右边:附件信息 -->
130
- <Col span="20">
131
- <Row>
132
- <tooltip>
133
- <span class="attach-name-style"> {{ item.attachName }}</span>
134
- <div slot="content" style="white-space: normal"> {{ item.attachName }}</div>
135
- </tooltip>
136
- </Row>
137
- <Row style="margin-top: 3px">
138
- <span style="color: #005aff; font-size: 13px;">{{ item.uploadUserName }}</span>
139
- <Divider style="background-color:#808695;height: 1em;margin: 4px 9px 0 6px;"
140
- type="vertical"/>
141
- <span style="color: #808695;font-size: 13px"
142
- >{{ showTaskNode(item.taskId) }}</span>
143
- </Row>
144
- <Row style="margin-bottom: -10px; margin-top: 10px">
145
- <template>
146
- <Button @click="getAttach(item)" size="small">下载</Button>
147
- <Button v-if="item.showPreview" ghost type="primary" @click="preViewAttach(item)"
148
- style="margin-left: 10px" size="small">预览
149
- </Button>
150
- </template>
151
- </Row>
152
- </Col>
153
- </Row>
154
-
155
- </ListItem>
156
- </List>
157
- </Card>
158
- </div>
159
- </div>
160
- </transition>
161
- <Modal title="查看附件" v-model="modalVisible" fullscreen scrollable :mask="false">
162
- <img :src="imageUrl" v-if="modalVisible" alt="" style="width: 100%">
163
- <div slot="footer">
164
- <Button type="primary" @click="modalVisible = false">关闭</Button>
165
- </div>
166
- </Modal>
167
- <Modal title="查看附件" v-model="modalDocx" fullscreen scrollable :mask="false">
168
- <div ref="file" ></div>
169
- </Modal>
170
- <Modal v-model="modal1" title="选择节点"
171
- @on-cancel="cancel"
172
- @on-ok="ok">
173
- <Table border
174
- :data="allNode"
175
- :columns="nodeColumn"
176
- highlight-row
177
- @on-current-change="selectNode">
178
- </Table>
179
- </Modal>
180
- <assigneeBox ref="assigneeHelpBox" :executionCompleted="executionCompleted" @update-selected="handleSelectedUser"
181
- :data="assigneeBoxData" :smart-flow-server-context="smartFlowServerContext" :upms-server-context="upmsServerContext"/>
182
- <Modal v-model="modalBoxShow" width="1000" title="流程跟踪图">
183
- <Workflow_Diagram ref="processTrace" :instanceId="process.instanceId" :applyId="process.applyId"
184
- :procId="process.procId"
185
- :tableData="process.tableData" :hisAudit="hisAudit"
186
- :smart-flow-server-context="smartFlowServerContext">
187
- </Workflow_Diagram>
188
- </Modal>
189
- </lamboIndicatorCard>
190
- </transition>
191
- <template slot="page-footer">
192
- <div>
193
- <slot name="footer-button"></slot>
194
- <Button style="margin-left: 10px;" v-if="(!handleButtons || handleButtons.includes('auditTo70')) && !isDetail"
195
- :disabled="disable" :loading="loading" @click="audit('70')">驳回到原点
196
- </Button>
197
- <Button style="margin-left: 10px;" v-if="(!handleButtons || handleButtons.includes('auditTo40')) && !isDetail"
198
- :disabled="disable" :loading="loading" @click="audit('40')">驳回到上一级
199
- </Button>
200
- <Button style="margin-left: 10px;" v-if="(!handleButtons || handleButtons.includes('auditTo90')) && !isDetail"
201
- :disabled="disable" :loading="loading" @click="audit('90')">驳回指定节点
202
- </Button>
203
- <Button style="margin-left: 10px;" v-if="(!handleButtons || handleButtons.includes('auditTo80')) && !isDetail"
204
- :disabled="disable" :loading="loading" @click="audit('80')">跳转指定节点
205
- </Button>
206
- <Button style="margin-left: 10px;" v-if="(!handleButtons || handleButtons.includes('auditTo82')) && !isDetail"
207
- :disabled="disable" :loading="loading" @click="audit('82')">指定他人处理
208
- </Button>
209
- <Button style="margin-left: 10px;" v-if="(!handleButtons || handleButtons.includes('auditTo50')) && !isDetail"
210
- :disabled="disable" :loading="loading" @click="audit('50')">直接结束流程
211
- </Button>
212
- <Button style="margin-left: 10px;" v-if="!handleButtons || handleButtons.includes('processTrace')"
213
- @click="processPrint" >流程跟踪图</Button>
214
- <Button style="margin-left: 10px;" v-if="(!handleButtons || handleButtons.includes('auditTo30')) && !isDetail"
215
- :disabled="disable" :loading="loading" type="primary" @click="audit('30')">通过
216
- </Button>
217
- </div>
218
- </template>
219
- </LamboPageContainer>
220
- </template>
221
-
222
-
223
- <script>
224
- import LamboPageContainer from '@lambo-design/page-container'
225
- import LamboIndicatorCard from '@lambo-design/indicator-card'
226
- import Workflow_Diagram from './workflow-diagram'
227
- import ajax from "@lambo-design/shared/utils/ajax";
228
- import bus from '@lambo-design/shared/utils/bus';
229
- import Title from "./components/title";
230
- import processHistory from "./components/history";
231
- import assigneeBox from "./components/assignee-box";
232
- import LamboPagingTable from "@lambo-design/paging-table";
233
- import AuditOpinion from "./components/opinion";
234
- import axios from "axios";
235
- import UploadFile from "@lambo-design/upload-file";
236
- import {timestampToTime} from "@lambo-design/shared/utils/date";
237
-
238
- // 引入docx-preview插件
239
- let docx = require('docx-preview');
240
-
241
-
242
- export default {
243
- props: {
244
- isDetail: {
245
- type: Boolean,
246
- default: false
247
- },
248
- width: {
249
- type: Number,
250
- required: false,
251
- default: 400
252
- },
253
- procId: {
254
- type: String,
255
- required: true,
256
- },
257
- taskNode: {
258
- type: String,
259
- required: true,
260
- },
261
- applyId: {
262
- type: String,
263
- required: true,
264
- },
265
- //业务表单保存方法
266
- businessFormSave: {
267
- type: Function,
268
- required: false
269
- },
270
- //按钮执行完毕回调方法
271
- executionCompleted: {
272
- type: Function,
273
- required: false,
274
- },
275
- title:{
276
- type: String,
277
- default: "流程办理"
278
- },
279
- smartFlowServerContext: {
280
- type: String,
281
- default: '/api/smart-flow-server',
282
- },
283
- upmsServerContext: {
284
- type: String,
285
- default: '/api/upms-server',
286
- },
287
- },
288
- components: {
289
- Title,
290
- LamboPageContainer,
291
- Workflow_Diagram,
292
- processHistory,
293
- assigneeBox,
294
- LamboPagingTable,
295
- AuditOpinion,
296
- LamboIndicatorCard,
297
- UploadFile
298
- },
299
- data() {
300
- return {
301
- isExpanded: true,
302
- portraitWidth: 0,
303
- requestSuccessCodes: [200, "200"],
304
- auditShow: true,
305
- historyShow: true,
306
- attachListShow: true,
307
- attachmentList: [],
308
- modalVisible: false,
309
- modalDocx: false,
310
- imageUrl: '',
311
- assigneeBoxData: {},
312
- selectedUserId: '',
313
- targetTaskNode: '',
314
- allNode: [],
315
- auditParams: {},
316
- modal1: false,
317
- modalBoxShow: false,
318
- hisNode: [],
319
- processHistory: [],
320
- ruleValidate: {
321
- auditOpinion: [{required: true, trigger: "blur", message: "审批意见不能为空"}]
322
- },
323
- form: {
324
- auditOpinion: '',
325
- },
326
- loading: false,
327
- disable: false,
328
- instanceId: '',
329
- taskId: '',
330
- handleButtons: [],
331
- auditResult: '',
332
- custChange: 'auditInfo',
333
- auditInfo: "auditInfo",
334
- auditProcess: "auditProcess",
335
- fileList: [],
336
- ossFilePutUrl: '/manage/oss/file/put',
337
- hisAudit: [],
338
- hisAuditOpinion: [{
339
- auditOpinion: '',
340
- auditTime: '',
341
- }],
342
- datas: {
343
- orgName: "",
344
- orgId: ""
345
- },
346
- editForm: {
347
- approvalCost: '',
348
- cost: '',
349
- activityDate: []
350
- },
351
- process: {
352
- tableData: [],
353
- instanceId: '',
354
- applyId: '',
355
- procId: ''
356
- },
357
- handleButtonsNames: {
358
- '30': '同意',
359
- '70': '驳回原点',
360
- '40': '驳回上一节点',
361
- '90': '驳回指定节点',
362
- '80': '跳转指定节点',
363
- '82': '转办',
364
- '50': '人工终止'
365
- },
366
- }
367
-
368
- },
369
-
370
- mounted() {
371
- this.getWidth()
372
- if (this.procId){
373
- this.initData()
374
- }
375
-
376
- },
377
- computed: {
378
- nodeColumn: function () {
379
- let column = []
380
- column.push({title: '序号', type: 'index', width: 70, align: 'center', fixed: 'left'});
381
- column.push({title: '节点名称', key: 'taskName', minWidth: 150, align: 'center', fixed: 'left'})
382
-
383
- column.push({
384
- title: '节点状态', key: 'auditResult', minWidth: 150, align: 'center', fixed: 'left',
385
- render: (h, params) => {
386
- if (params.row.taskNode == this.taskNode) {
387
- return h('div', [
388
- h('tag', {
389
- props: {
390
- color: '#ff9900'
391
- }
392
- }, '当前节点')
393
- ])
394
- } else if (!params.row.auditResult) {
395
- return h('div', [
396
- h('tag', {
397
- props: {
398
- color: '#ff9900'
399
- }
400
- }, '未审批')
401
- ])
402
- } else {
403
- if (params.row.auditResult == '30' && params.row.taskNode != this.taskNode) {
404
- return h('div', [
405
- h('tag', {
406
- props: {
407
- color: '#19be6b'
408
- }
409
- }, '已审批通过')
410
- ])
411
- } else if (params.row.auditResult == '40' && params.row.taskNode != this.taskNode) {
412
- return h('div', [
413
- h('tag', {
414
- props: {
415
- color: '#ed4014'
416
- }
417
- }, '已驳回到上一节点')
418
- ])
419
- } else if (params.row.auditResult == '60' && params.row.taskNode != this.taskNode) {
420
- return h('div', [
421
- h('tag', {
422
- props: {
423
- color: '#ed4014'
424
- }
425
- }, '已撤回')
426
- ])
427
- } else if (params.row.auditResult == '80' && params.row.taskNode != this.taskNode) {
428
- return h('div', [
429
- h('tag', {
430
- props: {
431
- color: '#19be6b'
432
- }
433
- }, '已跳转到指定节点')
434
- ])
435
- } else if (params.row.auditResult == '80' && params.row.taskNode != this.taskNode) {
436
- return h('div', [
437
- h('tag', {
438
- props: {
439
- color: '#19be6b'
440
- }
441
- }, '已驳回到指定节点')
442
- ])
443
- }
444
- }
445
- }
446
- })
447
- column.push({
448
- title: "操作", width: 100, align: 'center',
449
- render: (h, params) => {
450
- return h('div', [
451
- h('Button', {
452
- props: {
453
- type: 'primary',
454
- size: 'small'
455
- },
456
- style: {
457
- marginRight: '5px'
458
- },
459
- on: {
460
- click: () => {
461
- this.selectNode(params.row)
462
- }
463
- }
464
- }, '选择')
465
- ])
466
- },
467
- })
468
- return column
469
- },
470
-
471
- },
472
- provide() {
473
- return {
474
- toBeDoneListDoSearch: this.doSearch
475
- };
476
- },
477
- methods: {
478
- getWidth() {
479
- if (this.width && this.width < 400) {
480
- this.portraitWidth = 400
481
- }
482
- this.portraitWidth = this.width
483
- },
484
- initData(){
485
- this.getAttachList()
486
- if (!this.isDetail){
487
- this.getTodoTaskId()
488
- } else {
489
- this.getDoneTaskId()
490
- }
491
- this.getHandleButtons()
492
- this.getHisAudit();
493
- this.getProcessHistory();
494
- },
495
- saveBusinessForm() {
496
- this.businessFormSave(() => {
497
- })
498
- },
499
- getAttachList() {
500
- const self = this
501
- const param = {
502
- procId: this.procId,
503
- applyId: this.applyId
504
- }
505
- ajax.get(self.smartFlowServerContext + '/manage/processDone/getAttachmentList', {params: param}).then(function (resp) {
506
- self.attachmentList = resp.data.data.rows
507
- self.attachmentList.forEach(item => {
508
- const index = item.fileName.lastIndexOf(".")
509
- const fileType = item.fileName.substr(index + 1).toLowerCase()
510
- const imageList = ['jpg', 'gif', 'png', 'svg']
511
- const docList = ['doc', 'docx']
512
- const zipList = ['rar', 'zip']
513
- const typeList = ['jpg', 'gif', 'png', 'docx']
514
- item.fileType = imageList.indexOf(fileType) !== -1 ? 'image' : docList.indexOf(fileType) !== -1 ? 'doc' : zipList.indexOf(fileType) !== -1 ? 'zip' : fileType
515
- item.showPreview = typeList.indexOf(fileType) !== -1
516
- })
517
- }).catch(err => {
518
- console.log(err);
519
- })
520
- },
521
- getTodoTaskId() {
522
- const self = this
523
- let param = {
524
- procId: this.procId,
525
- applyId: this.applyId,
526
- taskNode:this.taskNode
527
- }
528
- ajax.get(self.smartFlowServerContext + "/manage/processTodo/list", {params: param}).then(function (resp) {
529
- if (resp.data.code === '200') {
530
- self.taskId = resp.data.data.rows[0].taskId
531
- self.instanceId = resp.data.data.rows[0].procInstanceId
532
- } else {
533
- self.$Message.error(resp.data.message)
534
- }
535
- }).catch((err) => {
536
- console.log(err)
537
- })
538
- },
539
- getDoneTaskId() {
540
- const self = this
541
- let param = {
542
- procId: this.procId,
543
- applyId: this.applyId,
544
- taskNode:this.taskNode
545
- }
546
- ajax.get(self.smartFlowServerContext + "/manage/processDone/getDoneDetail", {params: param}).then(function (resp) {
547
- if (resp.data.code === '200') {
548
- let rows = resp.data.data.rows
549
- if (rows.length > 0) {
550
- self.hisAuditOpinion = []
551
- let taskList = resp.data.data.rows
552
- taskList.forEach(item => {
553
- self.hisAuditOpinion.push({
554
- auditOpinion: item.auditComment,
555
- auditTime: timestampToTime(item.auditDate)
556
- })
557
- })
558
- self.taskId = taskList[0].taskId
559
- self.instanceId = taskList[0].procInstanceId
560
- } else {
561
- ajax.get(self.smartFlowServerContext + "/manage/processTodo/list", {params: param}).then(function (todoResp) {
562
- if (todoResp.data.code === '200') {
563
- self.taskId = todoResp.data.data.rows[0].taskId
564
- self.instanceId = todoResp.data.data.rows[0].procInstanceId
565
- } else {
566
- self.$Message.error(todoResp.data.message)
567
- }
568
- }).catch((err) => {
569
- console.log(err)
570
- })
571
- }
572
- } else {
573
- self.$Message.error(resp.data.message)
574
- }
575
- }).catch((err) => {
576
- console.log(err)
577
- })
578
- },
579
- getHandleButtons() {
580
- const self = this
581
- let param = {
582
- procId: this.procId,
583
- taskNode: this.taskNode
584
- }
585
- ajax.post(self.smartFlowServerContext + '/manage/approvalCenter/getNodeData', param).then(function (resp) {
586
- if (resp.data.code === '200') {
587
- self.handleButtons = resp.data.data[0].handleButtons
588
- } else {
589
- self.$Message.error(resp.data.message)
590
- }
591
- }).catch((err) => {
592
- console.log(err)
593
- })
594
- },
595
- handleSaveResult(saveResult) {
596
- if (saveResult) {
597
- this.executeButtonAction((execResult, instanceId, taskId) => {
598
- if (this.executionCompleted) {
599
- this.executionCompleted(execResult, instanceId, taskId);
600
- }
601
- });
602
- } else {
603
- console.error('保存失败');
604
- }
605
- },
606
- executeButtonAction(callback) {
607
- const self = this;
608
- if (self.auditResult == '82') {
609
- self.assigneeBoxData = self.auditParams
610
- self.$refs.assigneeHelpBox.toggleShowHelpBox();
611
- } else if (self.auditResult == '80') {
612
- self.getNodesBehind()
613
- } else if (self.auditResult == '90') {
614
- self.getAllPreNodes()
615
- } else if (self.auditResult == '40') {
616
- self.loading = true
617
- self.disable = true
618
- let url = self.smartFlowServerContext + '/manage/processTodo/getPreNode'
619
- ajax.post(url, self.auditParams).then(function (resp) {
620
- let result = resp.data
621
- if (result.code == '30010') {
622
- self.$Modal.confirm({
623
- title: "提示",
624
- content: result.message,
625
- onOk: () => {
626
- self.auditParams.auditResult = '70'
627
- let url = self.smartFlowServerContext + '/manage/processTodo/audit'
628
- ajax.post(url, self.auditParams).then(function (resp) {
629
- let result = resp.data
630
- if (result.code == '200') {
631
- self.loading = false
632
- self.disable = false
633
- self.$Message.success(result.message);
634
- //后端没有返回数据
635
- callback(true, null, null);
636
- bus.$emit('triggerTimer')
637
- } else {
638
- self.loading = false
639
- self.disable = false
640
- self.$Message.error(result.message)
641
- callback(false, null, null);
642
- }
643
- bus.$emit('triggerTimer')
644
- })
645
- },
646
- onCancel: () => {
647
- self.loading = false
648
- self.disable = false
649
- }
650
- })
651
- } else {
652
- self.loading = true
653
- self.disable = true
654
- let url = self.smartFlowServerContext + '/manage/processTodo/audit'
655
- ajax.post(url, self.auditParams).then(function (resp) {
656
- let result = resp.data
657
- if (result.code == '200') {
658
- self.loading = false
659
- self.disable = false
660
- self.$Message.success(result.message);
661
- if (result.data){
662
- callback(true, result.data.processInstanceId, result.data.id)
663
- }else {
664
- callback(true, null, null)
665
- }
666
- } else {
667
- self.loading = false
668
- self.disable = false
669
- self.$Message.error(result.message)
670
- callback(false, null, null);
671
- }
672
- bus.$emit('triggerTimer')
673
- })
674
- }
675
- })
676
- } else {
677
- self.loading = true
678
- self.disable = true
679
- let url = self.smartFlowServerContext + '/manage/processTodo/audit'
680
- ajax.post(url, self.auditParams).then(function (resp) {
681
- let result = resp.data
682
- if (result.code == '200') {
683
- self.loading = false
684
- self.disable = false
685
- if (result.data){
686
- callback(true, result.data.processInstanceId, result.data.id)
687
- }else {
688
- callback(true, null, null)
689
- }
690
- self.$Message.success(result.message);
691
- } else if (result.code == '20002') {
692
- // 流程结束
693
- self.loading = false
694
- self.disable = false
695
- callback(true, null, null)
696
- self.$Message.success(result.message)
697
- } else {
698
- self.loading = false
699
- self.disable = false
700
- callback(false, null, null)
701
- self.$Message.error(result.message)
702
- }
703
- bus.$emit('triggerTimer')
704
- })
705
-
706
- }
707
- },
708
-
709
- doSearch() {
710
- //不需要实现,是子组件assigneeBox要求使用父组件的这个方法
711
- },
712
- tabsChange(tab) {
713
- console.log(tab)
714
- },
715
- audit: function (auditResult) {
716
- let self = this
717
- self.auditResult = auditResult
718
- self.submit()
719
- },
720
- getAttach(row) {
721
- window.open(this.smartFlowServerContext + "/manage/oss/file/get/" + row.fileId, "_blank");
722
- },
723
- preViewAttach(row) {
724
- let reg = /\.(gif|jpg|jpeg|bmp|png|PNG)$/
725
- let regs = /\.(pdf)$/
726
- if (reg.test(row.fileName)) {
727
- let url = this.smartFlowServerContext + "/manage/oss/file/get/" + row.fileId;
728
- this.imgPreview(url);
729
- } else if (regs.test(row.fileName)) {
730
- window.open(this.smartFlowServerContext + "/manage/oss/file/getFileStream?fileId=" + row.fileId, "_blank");
731
- } else {
732
- this.modalDocx = true
733
- axios({
734
- method: 'get',
735
- responseType: 'blob', // 因为是流文件,所以要指定blob类型
736
- url: this.smartFlowServerContext + "/manage/oss/file/get/" + row.fileId// 一个word下载文件的接口
737
- }).then(({data}) => {
738
- docx.renderAsync(data, this.$refs.file, null, {
739
- className: "docx", //默认和文档样式类的类名/前缀
740
- inWrapper: true, //启用围绕文档内容呈现包装器
741
- ignoreWidth: false, //禁用页面的渲染宽度
742
- ignoreHeight: false, //禁用页面的渲染高度
743
- ignoreFonts: false, //禁用字体渲染
744
- breakPages: true, //在分页符上启用分页
745
- ignoreLastRenderedPageBreak: true, //在lastRenderedPageBreak元素上禁用分页
746
- experimental: false, //启用实验功能(制表符停止计算)
747
- trimXmlDeclaration: true, //如果为true,则在解析之前将从xml文档中删除xml声明
748
- useBase64URL: false, //如果为true,图像、字体等将转换为base 64 URL,否则使用URL.createObjectURL
749
- useMathMLPolyfill: false, //包括用于铬、边等的MathML多填充。
750
- showChanges: false, //启用文档更改的实验渲染(插入/删除)
751
- debug: false, //启用额外的日志记录
752
- })
753
- }
754
- )
755
- }
756
- },
757
- imgPreview(url) {
758
- this.imageUrl = url;
759
- this.modalVisible = true;
760
- },
761
- submit() {
762
- let self = this;
763
-
764
- self.auditParams = {
765
- procId: self.procId,
766
- applyId: self.applyId,
767
- taskId: self.taskId,
768
- auditOpinion: self.form.auditOpinion,
769
- fileListStr: JSON.stringify(self.fileList),
770
- auditResult: self.auditResult,
771
- params: JSON.stringify(self.datas),
772
- targetTaskNode: self.targetTaskNode,
773
- selectedUserId: self.selectedUserId,
774
- }
775
- if (self.auditResult == '' || self.auditResult == null) {
776
- self.$Message.error("请选择审批结果!");
777
- return;
778
- }
779
- if (self.form.auditOpinion == '' || self.form.auditOpinion == null) {
780
- if (!self.handleButtons || self.handleButtons.includes('auditOpinion')) {
781
- self.$Message.error("请输入审批意见!")
782
- return;
783
- } else {
784
- self.auditParams.auditOpinion = self.handleButtonsNames[self.auditResult];
785
- }
786
- }
787
-
788
- self.businessFormSave ? self.businessFormSave(self.handleSaveResult) : self.handleSaveResult(true)
789
- },
790
-
791
- //打印流程图信息
792
- processPrint() {
793
- let self = this
794
- let params = {
795
- applyId: self.applyId,
796
- instanceId: self.instanceId,
797
- procId: self.procId,
798
- taskId: self.taskId,
799
- }
800
- ajax.get(self.smartFlowServerContext + '/manage/processTodo/getPrintData', {params: params}).then(function (resp) {
801
- let result = resp.data.data
802
- if (resp.data.code === '200') {
803
- let tableData = result
804
- self.process.tableData = tableData
805
- self.process.applyId = self.applyId
806
- self.process.instanceId = self.instanceId
807
- self.process.procId = self.procId
808
- self.datas.orgId = tableData[0].orgId
809
- self.datas.orgName = tableData[0].orgName
810
- self.modalBoxShow = true
811
- }
812
- })
813
- },
814
-
815
- pageGoBack() {
816
- bus.$emit('triggerTimer')
817
- window.history.back()
818
- },
819
-
820
- getHisAudit() {
821
- let self = this
822
- let params = {
823
- applyId: self.applyId,
824
- instanceId: self.instanceId,
825
- procId: self.procId,
826
- taskId: self.taskId
827
- }
828
- ajax.get(self.smartFlowServerContext + '/manage/processTodo/getHisAudit', {params: params}).then(function (resp) {
829
- if (resp.data.code === '200') {
830
- self.hisAudit = resp.data.data
831
- let uniqueDataMap = {};
832
- self.hisAudit.forEach((item) => {
833
- uniqueDataMap[item["taskNode"]] = item;
834
- })
835
- self.hisNode = Object.values(uniqueDataMap);
836
-
837
- }
838
- })
839
- },
840
- showTaskNode(taskId) {
841
- if (this.processHistory.length > 0) {
842
- let task = null
843
- this.processHistory.some(itemList => {
844
- task = itemList.find(item => item.taskId === taskId);
845
- return task !== undefined;
846
- });
847
- return task ? task.taskName : ''
848
- }
849
- return ''
850
- },
851
- getProcessHistory() {
852
- let self = this
853
- let params = {
854
- applyId: self.applyId,
855
- instanceId: self.instanceId,
856
- procId: self.procId,
857
- taskId: self.taskId
858
- }
859
- ajax.get(self.smartFlowServerContext + '/manage/processTodo/getProcessHis', {params: params}).then(function (resp) {
860
- if (resp.data.code === '200') {
861
- self.processHistory = resp.data.data
862
- }
863
- })
864
- },
865
- cancel() {
866
- this.modal = false
867
- this.auditResult = '';
868
- },
869
- ok() {
870
- this.modal = false
871
- if (this.targetTaskNode == '' || this.targetTaskNode == null) {
872
- this.auditResult = '';
873
- this.$Message.error("请选择审批节点!");
874
- } else {
875
- let self = this;
876
-
877
- self.auditParams = {
878
- procId: self.procId,
879
- applyId: self.applyId,
880
- taskId: self.taskId,
881
- auditOpinion: self.form.auditOpinion,
882
- fileListStr: JSON.stringify(self.fileList),
883
- auditResult: self.auditResult,
884
- params: JSON.stringify(self.datas),
885
- targetTaskNode: self.targetTaskNode,
886
- selectedUserId: self.selectedUserId,
887
- }
888
- self.loading = true
889
- self.disable = true
890
-
891
- let url = self.smartFlowServerContext + '/manage/processTodo/audit'
892
- ajax.post(url, self.auditParams).then(function (resp) {
893
- let result = resp.data
894
- if (result.code === '200') {
895
- setTimeout(() => {
896
- self.loading = false
897
- self.disable = false
898
- self.$Message.success("审批成功");
899
- if (self.executionCompleted) {
900
- self.executionCompleted(true, result.data.processInstanceId, result.data.id);
901
- }
902
- bus.$emit('triggerTimer')
903
- }, 500)
904
- } else {
905
- self.loading = false
906
- self.disable = false
907
- self.$Message.error(result.message)
908
- if (self.executionCompleted) {
909
- self.executionCompleted(false, null, null);
910
- }
911
- }
912
- })
913
- }
914
- },
915
- selectNode(currentRow, oldCurrentRow) {
916
- let self = this
917
- self.targetTaskNode = currentRow.taskNode
918
- },
919
- getAllPreNodes() {
920
- let self = this
921
- let params = {
922
- processDefId: self.procId,
923
- taskId: self.taskId,
924
- }
925
- ajax.get(self.smartFlowServerContext + '/manage/processTodo/getAllPreNodes', {params: params}).then(function (resp) {
926
- if (resp.data.code === '200') {
927
- if (resp.data.data.length > 0){
928
- self.allNode = resp.data.data
929
- self.modal1 = true
930
- }else {
931
- self.$Message.warning('当前流程无前序节点')
932
- }
933
- } else {
934
- self.$Message.error(resp.data.message)
935
- }
936
- })
937
- },
938
- getNodesBehind() {
939
- let self = this
940
- let params = {
941
- processDefId: self.procId,
942
- taskId: self.taskId,
943
- }
944
- ajax.get(self.smartFlowServerContext + '/manage/processTodo/getNodesBehind', {params: params}).then(function (resp) {
945
- if (resp.data.code === '200') {
946
- if (resp.data.data.length > 0){
947
- self.allNode = resp.data.data
948
- self.modal1 = true
949
- }else {
950
- self.$Message.warning('当前流程无后续节点')
951
- }
952
- } else {
953
- self.$Message.error(resp.data.message)
954
- }
955
- })
956
- },
957
- handleSelectedUser(userId) {
958
- this.selectedUserId = userId;
959
- },
960
-
961
- //折叠动画效果
962
- beforeEnter(el) {
963
- el.style.height = '0';
964
- },
965
- enter(el, done) {
966
- setTimeout(() => {
967
- el.style.height = el.scrollHeight + 'px';
968
- }, 0);
969
-
970
- el.addEventListener('transitionend', done);
971
- },
972
- beforeLeave(el) {
973
- el.style.height = el.scrollHeight + 'px';
974
- },
975
- leave(el, done) {
976
- setTimeout(() => {
977
- el.style.height = '0';
978
- }, 0);
979
-
980
- el.addEventListener('transitionend', done);
981
- },
982
-
983
- beforeFlowInfoEnter(el) {
984
- el.style.transform = 'translateX(100%)';
985
- },
986
- flowInfoEnter(el, done) {
987
- const transitionDuration = 0.5;
988
- el.style.transition = `transform ${transitionDuration}s`;
989
- el.style.transform = 'translateX(0)';
990
- el.addEventListener('transitionend', done);
991
- },
992
- beforeFlowInfoLeave(el) {
993
- el.style.transform = 'translateX(0)';
994
- },
995
- flowInfoLeave(el, done) {
996
- const transitionDuration = 0.5;
997
- el.style.transition = `transform ${transitionDuration}s`;
998
- el.style.transform = 'translateX(100%)';
999
- el.addEventListener('transitionend', done);
1000
- },
1001
- uploadFile(file){
1002
- const self = this;
1003
- self.fileList = []
1004
- file.forEach(item => {
1005
- self.fileList.push({
1006
- fileName: item.fileName,
1007
- fileId: item.fileCode,
1008
- });
1009
- })
1010
- },
1011
- },
1012
- watch: {
1013
- auditOpinionText(label) {
1014
- this.form.auditOpinion = label;
1015
- },
1016
- procId(val) {
1017
- this.procId = val;
1018
- this.initData()
1019
- },
1020
- }
1021
- }
1022
- </script>
1023
-
1024
- <style lang="less" scoped>
1025
- @import "./styles/css/index.less";
1026
- /deep/ .ivu-table-row-highlight td {
1027
- background-color: #50c1ff !important;
1028
- color: #fff !important;
1029
- }
1030
- /deep/ .ivu-card-body{
1031
- padding: 10px;
1032
- }
1033
- .page-info /deep/ .page-body{
1034
- overflow-y: hidden;
1035
- }
1036
- </style>
1
+ <template>
2
+ <LamboPageContainer>
3
+ <template slot="page-title">
4
+ {{ title }}
5
+ </template>
6
+ <template slot="page-extend">
7
+ <slot name="return-button"></slot>
8
+ </template>
9
+ <div class="portrait-lambo-indicator-card"
10
+ :style="{float: 'left', width: isExpanded && showProcessInfo ? `calc(100% - ${portraitWidth+10}px)` : '99%'}">
11
+ <slot name="business-content">
12
+ </slot>
13
+ </div>
14
+
15
+ <a v-if="showProcessInfo" @click="isExpanded = !isExpanded" class="arrow-button-container"
16
+ :style="{right: isExpanded ? portraitWidth+10 + 'px' : '10px'}">
17
+ <Icon class="icon-class" v-if="isExpanded" type="ios-arrow-forward"/>
18
+ <Icon class="icon-class" v-if="!isExpanded" type="ios-arrow-back"/>
19
+ </a>
20
+ <transition v-if="showProcessInfo" name="draw" @before-enter="beforeFlowInfoEnter" @enter="flowInfoEnter"
21
+ @before-leave="beforeFlowInfoLeave" @leave="flowInfoLeave">
22
+ <lamboIndicatorCard v-show="isExpanded" class="portrait-lambo-indicator-card"
23
+ :style="{width: portraitWidth + 'px', float: 'right'}" :hasExtend="false">
24
+ <div slot="content-title">流程信息</div>
25
+ <a v-if="!isDetail" @click="auditShow = !auditShow">
26
+ <Title
27
+ v-if="handleButtons && (handleButtons.includes('auditOpinion') || handleButtons.includes('attachmentFile'))">
28
+ <a style="color: #989898">
29
+ <Icon v-if="auditShow" type="ios-arrow-down"/>
30
+ <Icon v-if="!auditShow" type="ios-arrow-up"/>
31
+ {{ handleName }}信息
32
+ </a>
33
+ </Title>
34
+ </a>
35
+ <transition v-if="!isDetail" name="draw" @before-enter="beforeEnter" @enter="enter" @before-leave="beforeLeave"
36
+ @leave="leave">
37
+ <div class="box" v-show="auditShow">
38
+ <Form ref="auditOpinion" justify="center" :label-width="100" :model="form"
39
+ v-if="handleButtons && handleButtons.includes('auditOpinion')"
40
+ style="margin: 10px 0 0 10px;" :rules="ruleValidate">
41
+ <FormItem :label="auditOpinionTitle" prop="auditOpinion">
42
+ <AuditOpinion v-model="form.auditOpinion" :attachment-file="handleButtons.includes('attachmentFile')"
43
+ :attachmentdata="fileList" :default-audit-opinion="defaultAuditOpinion"
44
+ :smart-flow-server-context="smartFlowServerContext"></AuditOpinion>
45
+ </FormItem>
46
+ </Form>
47
+ <Form ref="auditOpinion" justify="center" :label-width="100"
48
+ v-if="handleButtons && !handleButtons.includes('auditOpinion') && handleButtons.includes('attachmentFile')"
49
+ style="margin: 10px 0 0 10px;">
50
+ <FormItem style="min-height: 70px">
51
+ <Tooltip placement="bottom" max-width="200">
52
+ <div style="font-size: smaller" slot="content">支持扩展名:.pdf .doc .docx .txt .xls .xlsx .jpg .jpeg
53
+ .png .gif
54
+ </div>
55
+ <UploadFile @upload-result="uploadFile" :multiple="true"
56
+ :oss-server-context="smartFlowServerContext"
57
+ :oss-file-put-url="ossFilePutUrl"></UploadFile>
58
+ </Tooltip>
59
+ </FormItem>
60
+ </Form>
61
+ </div>
62
+ </transition>
63
+ <a v-if="taskNode && isDetail && hisAuditOpinion[0].auditOpinion" @click="auditShow = !auditShow">
64
+ <Title
65
+ v-if="handleButtons && (handleButtons.includes('auditOpinion') || handleButtons.includes('attachmentFile'))">
66
+ <a style="color: #989898">
67
+ <Icon v-if="auditShow" type="ios-arrow-down"/>
68
+ <Icon v-if="!auditShow" type="ios-arrow-up"/>
69
+ {{ handleName }}信息
70
+ </a>
71
+ </Title>
72
+ </a>
73
+ <transition v-if="taskNode && isDetail && hisAuditOpinion[0].auditOpinion" name="draw"
74
+ @before-enter="beforeEnter"
75
+ @enter="enter" @before-leave="beforeLeave" @leave="leave">
76
+ <div class="box" v-show="auditShow">
77
+ <Form ref="auditOpinion" justify="center" :model="form"
78
+ v-if="handleButtons && handleButtons.includes('auditOpinion')"
79
+ style="margin: 10px 0 0 10px;" :rules="ruleValidate">
80
+ <FormItem style="margin-left: -60px">
81
+ <Card v-for="(item, index) in hisAuditOpinion" :key="index">
82
+ <Row>
83
+ <Col span="12" style="word-wrap: break-word">{{ item.auditOpinion }}</Col>
84
+ <Col span="2"></Col>
85
+ <Col span="10">{{ item.auditTime }}</Col>
86
+ </Row>
87
+ </Card>
88
+ </FormItem>
89
+ </Form>
90
+ </div>
91
+ </transition>
92
+ <a @click="historyShow = !historyShow">
93
+ <Title v-if="handleButtons && handleButtons.includes('auditHistory')">
94
+ <a style="color: #989898">
95
+ <Icon v-if="historyShow" type="ios-arrow-down"/>
96
+ <Icon v-if="!historyShow" type="ios-arrow-up"/>
97
+ {{ handleName }}记录
98
+ </a>
99
+ </Title>
100
+ </a>
101
+ <transition name="draw" @before-enter="beforeEnter" @enter="enter" @before-leave="beforeLeave" @leave="leave">
102
+ <div class="box" v-show="historyShow">
103
+ <Card class="process-history" :style="processHistoryHeight" dis-hover :bordered="false"
104
+ v-if="handleButtons && handleButtons.includes('auditHistory')">
105
+ <processHistory :portrait-width="portraitWidth" :list="processHistory" :done-page="isDetail"
106
+ :push-button="pushButton"
107
+ :smart-flow-server-context="smartFlowServerContext"></processHistory>
108
+ </Card>
109
+ </div>
110
+ </transition>
111
+
112
+ <a @click="attachListShow = !attachListShow">
113
+ <Title v-if="handleButtons && handleButtons.includes('attachmentFile') && attachmentList.length > 0">
114
+ <a style="color: #989898">
115
+ <Icon v-if="attachListShow" type="ios-arrow-down"/>
116
+ <Icon v-if="!attachListShow" type="ios-arrow-up"/>
117
+ 查看附件
118
+ </a>
119
+ </Title>
120
+ </a>
121
+ <transition name="draw" @before-enter="beforeEnter" @enter="enter" @before-leave="beforeLeave" @leave="leave">
122
+ <div class="box"
123
+ v-show="handleButtons && handleButtons.includes('auditHistory') && attachmentList.length > 0 && attachListShow">
124
+ <div v-for="(item, index) in attachmentList" :key="index">
125
+ <Card dis-hover class="attach-card">
126
+ <List item-layout="vertical">
127
+ <ListItem style="margin-top: -8px">
128
+ <Row style="display: flex; align-items: center;">
129
+ <!-- 左边:图片 -->
130
+ <Col span="4" style="margin-top: -25px">
131
+ <avatar v-if="item.fileType === 'image'" icon="ios-image-outline" class="attach-avatar"
132
+ style="background-color: #005aff"
133
+ :style="portraitWidth >= 600 ? 'margin-left: 10px' : ''"
134
+ :size="portraitWidth >= 600 ? 'middle' : 'small'"></avatar>
135
+ <avatar v-else-if="item.fileType === 'doc'" icon="ios-document-outline" class="attach-avatar"
136
+ style="background-color: #005aff"
137
+ :style="portraitWidth >= 600 ? 'margin-left: 10px' : ''"
138
+ :size="portraitWidth >= 600 ? 'middle' : 'small'">
139
+ </avatar>
140
+ <avatar v-else-if="item.fileType === 'xlsx'" icon="ios-document-outline" class="attach-avatar"
141
+ style="background-color: #19be6b"
142
+ :style="portraitWidth >= 600 ? 'margin-left: 10px' : ''"
143
+ :size="portraitWidth >= 600 ? 'middle' : 'small'"></avatar>
144
+ <avatar v-else-if="item.fileType === 'pdf'" icon="ios-document-outline" class="attach-avatar"
145
+ style="background-color: #ed4014"
146
+ :style="portraitWidth >= 600 ? 'margin-left: 10px' : ''"
147
+ :size="portraitWidth >= 600 ? 'middle' : 'small'"></avatar>
148
+ <avatar v-else icon="ios-document-outline" class="attach-avatar"
149
+ :style="portraitWidth >= 600 ? 'margin-left: 10px' : ''"
150
+ :size="portraitWidth >= 600 ? 'middle' : 'small'"></avatar>
151
+ </Col>
152
+ <!-- 右边:附件信息 -->
153
+ <Col span="20">
154
+ <Row>
155
+ <tooltip>
156
+ <span class="attach-name-style"> {{ item.attachName }}</span>
157
+ <div slot="content" style="white-space: normal"> {{ item.attachName }}</div>
158
+ </tooltip>
159
+ </Row>
160
+ <Row style="margin-top: 3px">
161
+ <span style="color: #005aff; font-size: 13px;">{{ item.uploadUserName }}</span>
162
+ <Divider style="background-color:#808695;height: 1em;margin: 4px 9px 0 6px;"
163
+ type="vertical"/>
164
+ <span style="color: #808695;font-size: 13px"
165
+ >{{ showTaskNode(item.taskId) }}</span>
166
+ </Row>
167
+ <Row style="margin-bottom: -10px; margin-top: 10px">
168
+ <template>
169
+ <Button @click="getAttach(item)" size="small">下载</Button>
170
+ <Button v-if="item.showPreview" ghost type="primary" @click="preViewAttach(item)"
171
+ style="margin-left: 10px" size="small">预览
172
+ </Button>
173
+ </template>
174
+ </Row>
175
+ </Col>
176
+ </Row>
177
+
178
+ </ListItem>
179
+ </List>
180
+ </Card>
181
+ </div>
182
+ </div>
183
+ </transition>
184
+ <Modal title="查看附件" v-model="modalVisible" fullscreen scrollable :mask="false">
185
+ <img :src="imageUrl" v-if="modalVisible" alt="" style="width: 100%">
186
+ <div slot="footer">
187
+ <Button type="primary" @click="modalVisible = false">关闭</Button>
188
+ </div>
189
+ </Modal>
190
+ <Modal title="查看附件" v-model="modalDocx" fullscreen scrollable :mask="false">
191
+ <div ref="file"></div>
192
+ </Modal>
193
+ </lamboIndicatorCard>
194
+ </transition>
195
+
196
+ <Modal v-model="modal1" title="选择节点"
197
+ @on-cancel="cancel"
198
+ @on-ok="doPass">
199
+ <Table border
200
+ :data="allNode"
201
+ :columns="nodeColumn"
202
+ highlight-row
203
+ @on-current-change="selectNode">
204
+ </Table>
205
+ </Modal>
206
+ <assigneeBox ref="assigneeHelpBox" :execution-completed="executionCompleted"
207
+ @update-selected="handleSelectedUser" @update-next-node-assignee="updateNextNodeAssignee"
208
+ @add-multitask-instance="addMultitaskInstance" @delegate-task-assignee="delegateTask"
209
+ :data="assigneeBoxData" :smart-flow-server-context="smartFlowServerContext"
210
+ :upms-server-context="upmsServerContext"/>
211
+ <Modal ref="processTraceModal" v-model="modalBoxShow" width="1000" title="流程跟踪图">
212
+ <Workflow_Diagram ref="processTrace" :instanceId="process.instanceId" :applyId="process.applyId"
213
+ :procId="process.procId" :table-columns="diagramTableColumns" :scroll-element="scrollElement"
214
+ :tableData="process.tableData" :hisAudit="hisAudit"
215
+ :approve-detail-show-way="approveDetailShowWay"
216
+ :smart-flow-server-context="smartFlowServerContext">
217
+ </Workflow_Diagram>
218
+ </Modal>
219
+ <Modal v-model="reductionMultitaskInstanceModal" title="选择减签人员"
220
+ @on-cancel="reductionModalCancel"
221
+ @on-ok="reductionMultitaskInstance">
222
+ <Table border
223
+ :data="unapprovedAssigneeList"
224
+ :columns="reductionColumn"
225
+ @on-selection-change="selectAssignee">
226
+ </Table>
227
+ </Modal>
228
+ <Modal v-model="appointBoxShow" title="下一环节设置"
229
+ @on-cancel="appointBoxShow = false" width="600"
230
+ @on-ok="appointOk">
231
+ <Card v-for="(item,index) of nextNodesFormList" :key="index" style="margin-bottom: 10px"
232
+ v-if="handleButtons && (handleButtons.includes('appointHandler') || handleButtons.includes('appointTimeoutTime'))">
233
+ <Form ref="appointBox" justify="center" :label-width="100" :model="item"
234
+ style="margin: 10px 0 0 10px;" :rules="ruleValidate">
235
+ <div v-if="handleButtons && handleButtons.includes('appointHandler')">
236
+ <FormItem label="下一环节:">
237
+ {{ item.name }}
238
+ </FormItem>
239
+ <FormItem label="人员类型:" v-if="!item.isMultiInstance">
240
+ <RadioGroup v-model="item.actionType">
241
+ <Radio label="ASSIGNEE">办理人</Radio>
242
+ <Radio label="CAND">候选人</Radio>
243
+ </RadioGroup>
244
+ </FormItem>
245
+ <FormItem label="办理人员:" prop="assignee" v-if="!item.isMultiInstance && item.actionType === 'ASSIGNEE'">
246
+ <Input v-model="item.assigneeName"
247
+ placeholder="请选择办理人"
248
+ style="width: 68%"
249
+ icon="md-apps"
250
+ @on-focus="readingRangeClick(item)"
251
+ @on-click="readingRangeClick(item)"/>
252
+ </FormItem>
253
+ <FormItem label="候选人员:" prop="candidateGroups"
254
+ v-if="!item.isMultiInstance && item.actionType === 'CAND'">
255
+ <Input v-model="item.candidateNames"
256
+ placeholder="请选择候选人"
257
+ style="width: 68%"
258
+ icon="md-apps"
259
+ @on-focus="candidateGroupsReadingRangeClick(item)"
260
+ @on-click="candidateGroupsReadingRangeClick(item)"/>
261
+ </FormItem>
262
+ <FormItem label="候选人员:" prop="candidateGroups"
263
+ v-if="item.isMultiInstance && item.actionType === 'CAND'">
264
+ </FormItem>
265
+
266
+ <countersingersBox style="margin-bottom: 10px" v-model="item.candidateNames"
267
+ v-if="item.isMultiInstance && item.actionType === 'CAND'"
268
+ :item="item" :permScope="permScope" @update-cand-groups="updateCandGroups"
269
+ :upms-server-context="upmsServerContext"
270
+ :smart-flow-server-context="smartFlowServerContext"/>
271
+ </div>
272
+ <div v-if="handleButtons && handleButtons.includes('appointTimeoutTime')">
273
+ <Row>
274
+ <Col span="12">
275
+ <FormItem label="停留时间:">
276
+ <Input v-model="item.remainDay" style="width: 100px" type="number" :min="0"></Input>
277
+
278
+ </FormItem>
279
+ </Col>
280
+ <Col span="12">
281
+ <FormItem>
282
+ <Input v-model="item.remainTime" style="margin-left: -140px; width: 100px" type="number"
283
+ :min="0"></Input>
284
+ 小时 自动处理
285
+ </FormItem>
286
+ </Col>
287
+ </Row>
288
+ <Row>
289
+ <Col span="12">
290
+ <FormItem label="任务提前:">
291
+ <Input v-model="item.inAdvanceDay" style="width: 100px" type="number" :min="0"></Input>
292
+
293
+ </FormItem>
294
+ </Col>
295
+ <Col span="12">
296
+ <FormItem>
297
+ <Input v-model="item.inAdvanceTime" style="margin-left: -140px;width: 100px" type="number"
298
+ :min="0"></Input>
299
+ 小时 标红预警
300
+ </FormItem>
301
+ </Col>
302
+ </Row>
303
+ <FormItem label="处理方式:">
304
+ <Select v-model="item.processing" style="width:200px" placeholder="自动同意">
305
+ <Option v-for="item in handleTypeList" :value="item.value" :key="item.value">
306
+ {{ item.label }}
307
+ </Option>
308
+ </Select>
309
+ </FormItem>
310
+ </div>
311
+ </Form>
312
+ </Card>
313
+ </Modal>
314
+ <candidateGroupsHelpBox ref="candidateGroupsHelpBox" :show="candidateGroupsHelpBoxShow"
315
+ @update-cand-groups="updateCandGroups"
316
+ :upms-server-context="upmsServerContext"
317
+ :smart-flow-server-context="smartFlowServerContext"/>
318
+ <template slot="page-footer">
319
+ <div>
320
+ <slot name="footer-button"></slot>
321
+ <Button style="margin-left: 10px;" v-if="handleButtons && handleButtons.includes('auditTo70') && !isDetail && !appointTask"
322
+ :disabled="disable" :loading="loading" @click="audit('70')">驳回到原点
323
+ </Button>
324
+ <Button style="margin-left: 10px;" v-if="handleButtons && handleButtons.includes('auditTo40') && !isDetail && !appointTask"
325
+ :disabled="disable" :loading="loading" @click="audit('40')">驳回上一节点
326
+ </Button>
327
+ <Button style="margin-left: 10px;" v-if="handleButtons && handleButtons.includes('auditTo90') && !isDetail && !appointTask"
328
+ :disabled="disable" :loading="loading" @click="audit('90')">驳回指定节点
329
+ </Button>
330
+ <Button style="margin-left: 10px;" v-if="handleButtons && handleButtons.includes('auditTo80') && !isDetail && !appointTask"
331
+ :disabled="disable" :loading="loading" @click="audit('80')">跳转指定节点
332
+ </Button>
333
+ <Button style="margin-left: 10px;" v-if="handleButtons && handleButtons.includes('auditTo82') && !isDetail && !appointTask"
334
+ :disabled="disable" :loading="loading" @click="audit('82')">指定他人处理
335
+ </Button>
336
+ <Button style="margin-left: 10px;"
337
+ v-if="curNodeType === 'userTask' && handleButtons && handleButtons.includes('delegateTask') && !isDetail && !appointTask"
338
+ :disabled="disable" :loading="loading" @click="audit('84')">委派
339
+ </Button>
340
+ <Button style="margin-left: 10px;"
341
+ v-if="curNodeType === 'multiNode' && handleButtons && handleButtons.includes('addMultitaskInstance') && !isDetail && !appointTask"
342
+ :disabled="disable" :loading="loading" @click="showUpdateMultitaskInstanceModal('81')">加签
343
+ </Button>
344
+ <Button style="margin-left: 10px;"
345
+ v-if="curNodeType === 'multiNode' && handleButtons && handleButtons.includes('reductionMultitaskInstance') && !isDetail && !appointTask"
346
+ :disabled="disable" :loading="loading" @click="showUpdateMultitaskInstanceModal('83')">减签
347
+ </Button>
348
+ <Button style="margin-left: 10px;" v-if="handleButtons && handleButtons.includes('auditTo50') && !isDetail && !appointTask"
349
+ :disabled="disable" :loading="loading" @click="audit('50')">直接结束流程
350
+ </Button>
351
+ <Button style="margin-left: 10px;" v-if="handleButtons && handleButtons.includes('processTrace')"
352
+ @click="processPrint">流程跟踪图
353
+ </Button>
354
+ <Button style="margin-left: 10px;" v-if="handleButtons && handleButtons.includes('auditTo30') && !isDetail && !appointTask"
355
+ :disabled="disable" :loading="loading" type="primary" @click="audit('30')">通过
356
+ </Button>
357
+ <Button style="margin-left: 10px;" v-if="revokeDelegateTask"
358
+ :disabled="!revokeDelegateTask && disable" :loading="loading" @click="audit('62')">撤回委派
359
+ </Button>
360
+ <Button style="margin-left: 10px;" v-if="appointTask" :disabled="disable" :loading="loading" type="primary" @click="audit('61')">交回</Button>
361
+ </div>
362
+ </template>
363
+ </LamboPageContainer>
364
+ </template>
365
+
366
+
367
+ <script>
368
+ import LamboPageContainer from '@lambo-design/page-container'
369
+ import LamboIndicatorCard from '@lambo-design/indicator-card'
370
+ import Workflow_Diagram from './workflow-diagram'
371
+ import ajax from '@lambo-design/shared/utils/ajax'
372
+ import bus from '@lambo-design/shared/utils/bus'
373
+ import Title from './components/title'
374
+ import processHistory from './components/history'
375
+ import assigneeBox from './components/assignee-box'
376
+ import CandidateGroupsHelpBox from './components/candidate-groups-box'
377
+ import CountersingersBox from './components/countersigners-box'
378
+ import LamboPagingTable from '@lambo-design/paging-table'
379
+ import AuditOpinion from './components/opinion'
380
+ import axios from 'axios'
381
+ import UploadFile from '@lambo-design/upload-file'
382
+ import { timestampToTime } from '@lambo-design/shared/utils/date'
383
+
384
+ // 引入docx-preview插件
385
+ let docx = require('docx-preview')
386
+
387
+ export default {
388
+ props: {
389
+ isDetail: {
390
+ type: Boolean,
391
+ required: false,
392
+ default: false
393
+ },
394
+ width: {
395
+ type: Number,
396
+ required: false,
397
+ default: 400
398
+ },
399
+ procId: {
400
+ type: String,
401
+ required: true,
402
+ },
403
+ taskNode: {
404
+ type: String,
405
+ required: true,
406
+ },
407
+ applyId: {
408
+ type: String,
409
+ required: true,
410
+ },
411
+ taskId: {
412
+ type: String,
413
+ required: false,
414
+ default: '',
415
+ },
416
+ auditGroup: {
417
+ type: String,
418
+ required: false,
419
+ default: '',
420
+ },
421
+ defaultAuditOpinion: {
422
+ type: String,
423
+ required: false,
424
+ default: '',
425
+ },
426
+ //详情页催办按钮
427
+ pushButton: {
428
+ type: Boolean,
429
+ required: false,
430
+ default: true,
431
+ },
432
+ //流程跟踪图附件列
433
+ showAttachmentFile: {
434
+ type: Boolean,
435
+ required: false,
436
+ default: true,
437
+ },
438
+ //流程跟踪图审批详情触发方式
439
+ approveDetailShowWay: {
440
+ type: String,
441
+ required: false,
442
+ default: 'click',
443
+ },
444
+ //业务表单保存方法
445
+ businessFormSave: {
446
+ type: Function,
447
+ required: false
448
+ },
449
+ //按钮执行完毕回调方法
450
+ executionCompleted: {
451
+ type: Function,
452
+ required: false,
453
+ default: () => {
454
+ }
455
+ },
456
+ title: {
457
+ type: String,
458
+ default: '流程办理'
459
+ },
460
+ smartFlowServerContext: {
461
+ type: String,
462
+ default: '/api/smart-flow-server',
463
+ },
464
+ upmsServerContext: {
465
+ type: String,
466
+ default: '/api/upms-server',
467
+ },
468
+ },
469
+ components: {
470
+ Title,
471
+ LamboPageContainer,
472
+ Workflow_Diagram,
473
+ processHistory,
474
+ assigneeBox,
475
+ LamboPagingTable,
476
+ AuditOpinion,
477
+ LamboIndicatorCard,
478
+ UploadFile,
479
+ CandidateGroupsHelpBox,
480
+ CountersingersBox
481
+ },
482
+ data() {
483
+ return {
484
+ isExpanded: true,
485
+ showProcessInfo: true,
486
+ portraitWidth: 0,
487
+ requestSuccessCodes: [200, '200'],
488
+ auditShow: true,
489
+ historyShow: true,
490
+ attachListShow: true,
491
+ attachmentList: [],
492
+ modalVisible: false,
493
+ modalDocx: false,
494
+ imageUrl: '',
495
+ assigneeBoxData: {},
496
+ selectedUserId: '',
497
+ targetTaskNode: '',
498
+ allNode: [],
499
+ auditParams: {},
500
+ scrollElement: null,
501
+ modal1: false,
502
+ modalBoxShow: false,
503
+ reductionMultitaskInstanceModal: false,
504
+ candidateGroupsHelpBoxShow: false,
505
+ appointBoxShow: false,
506
+ autoOpenNode: '0',
507
+ unapprovedAssigneeList: [],
508
+ reductionAssigneeList: [],
509
+ nextNodesOldSettings: [],
510
+ nextNodesFormList: [],
511
+ hisNode: [],
512
+ processHistory: [],
513
+ permScope: '',
514
+ organTreeType: '00',
515
+ defaultOrganTreeType: '00',
516
+ ruleValidate: {
517
+ auditOpinion: [{ required: true, trigger: 'blur', message: '意见不能为空' }],
518
+ assignee: [{ required: true, trigger: 'blur', message: '办理人不能为空' }],
519
+ candidateGroups: [{ required: true, trigger: 'blur', message: '候选人不能为空' }],
520
+ },
521
+ form: {
522
+ auditOpinion: '',
523
+ },
524
+ loading: false,
525
+ disable: false,
526
+ revokeDelegateTask: false,
527
+ appointTask: false,
528
+ instanceId: '',
529
+ curTaskId: '',
530
+ curNodeType: 'userTask',
531
+ handleButtons: [],
532
+ handleName: '',
533
+ auditOpinionTitle: '',
534
+ auditResult: '',
535
+ curAuditGroup: '',
536
+ custChange: 'auditInfo',
537
+ auditInfo: 'auditInfo',
538
+ auditProcess: 'auditProcess',
539
+ fileList: [],
540
+ ossFilePutUrl: '/manage/oss/file/put',
541
+ hisAudit: [],
542
+ hisAuditOpinion: [{
543
+ auditOpinion: '',
544
+ auditTime: '',
545
+ }],
546
+ datas: {
547
+ orgName: '',
548
+ orgId: ''
549
+ },
550
+ editForm: {
551
+ approvalCost: '',
552
+ cost: '',
553
+ activityDate: []
554
+ },
555
+ process: {
556
+ tableData: [],
557
+ instanceId: '',
558
+ applyId: '',
559
+ procId: ''
560
+ },
561
+ handleButtonsNames: {
562
+ '30': '通过',
563
+ '70': '驳回到原点',
564
+ '40': '驳回上一节点',
565
+ '90': '驳回指定节点',
566
+ '80': '跳转指定节点',
567
+ '82': '指定他人处理',
568
+ '50': '直接结束流程',
569
+ '84': '委派任务',
570
+ '61': '交回委派任务',
571
+ '62': '撤回委派任务',
572
+ },
573
+ handleTypeList: [
574
+ {
575
+ value: '00',
576
+ label: '只预警不处理'
577
+ },
578
+ {
579
+ value: '10',
580
+ label: '自动同意'
581
+ },
582
+ {
583
+ value: '20',
584
+ label: '直接终止流程'
585
+ },
586
+ {
587
+ value: '90',
588
+ label: '自动驳回'
589
+ }
590
+ ],
591
+ }
592
+
593
+ },
594
+
595
+ mounted() {
596
+ this.getWidth()
597
+ if (this.procId) {
598
+ this.initData()
599
+ }
600
+ let modalElement = this.$refs.processTraceModal.$el
601
+ for (let i = 0; i < modalElement.children.length; i++) {
602
+ //找到滚动的目标element
603
+ let targetElement = modalElement.children[i]
604
+ if (targetElement.classList.toString().includes('-wrap')){
605
+ this.scrollElement = targetElement
606
+ break
607
+ }
608
+ }
609
+ },
610
+ computed: {
611
+ processHistoryHeight() {
612
+ let str = ''
613
+ const hasAuditOpinion = this.taskNode && this.handleButtons && this.handleButtons.includes('auditOpinion')
614
+ const hasAttachmentFile = this.handleButtons && this.handleButtons.includes('auditHistory') && this.attachmentList.length > 0
615
+ const isDetail = this.isDetail && !this.hisAuditOpinion[0].auditOpinion.length > 0
616
+ if (hasAuditOpinion && !hasAttachmentFile && !isDetail) {
617
+ str += 'height: 43vh'
618
+ } else if (hasAuditOpinion && hasAttachmentFile && !isDetail) {
619
+ str += 'height: 40vh'
620
+ } else {
621
+ str += 'height: 67vh'
622
+ }
623
+ return str
624
+ },
625
+ nodeColumn: function () {
626
+ let column = []
627
+ column.push({ title: '序号', type: 'index', width: 70, align: 'center', fixed: 'left' })
628
+ column.push({ title: '节点名称', key: 'taskName', minWidth: 150, align: 'center', fixed: 'left' })
629
+
630
+ column.push({
631
+ title: '节点状态', key: 'auditResult', minWidth: 150, align: 'center', fixed: 'left',
632
+ render: (h, params) => {
633
+ if (params.row.taskNode == this.taskNode) {
634
+ return h('div', [
635
+ h('tag', {
636
+ props: {
637
+ color: '#ff9900'
638
+ }
639
+ }, '当前节点')
640
+ ])
641
+ } else if (!params.row.auditResult) {
642
+ return h('div', [
643
+ h('tag', {
644
+ props: {
645
+ color: '#ff9900'
646
+ }
647
+ }, `未${params.row.handleName ? params.row.handleName : '审批'}`)
648
+ ])
649
+ } else {
650
+ if (params.row.auditResult == '30' && params.row.taskNode != this.taskNode) {
651
+ return h('div', [
652
+ h('tag', {
653
+ props: {
654
+ color: '#19be6b'
655
+ }
656
+ }, `已${params.row.handleName ? params.row.handleName : '审批'}通过`)
657
+ ])
658
+ } else if (params.row.auditResult == '40' && params.row.taskNode != this.taskNode) {
659
+ return h('div', [
660
+ h('tag', {
661
+ props: {
662
+ color: '#ed4014'
663
+ }
664
+ }, '已驳回到上一节点')
665
+ ])
666
+ } else if (params.row.auditResult == '60' && params.row.taskNode != this.taskNode) {
667
+ return h('div', [
668
+ h('tag', {
669
+ props: {
670
+ color: '#ed4014'
671
+ }
672
+ }, '已撤回')
673
+ ])
674
+ } else if (params.row.auditResult == '61' && params.row.taskNode != this.taskNode) {
675
+ return h('div', [
676
+ h('tag', {
677
+ props: {
678
+ color: '#19be6b'
679
+ }
680
+ }, '已交回委派任务')
681
+ ])
682
+ } else if (params.row.auditResult == '62' && params.row.taskNode != this.taskNode) {
683
+ return h('div', [
684
+ h('tag', {
685
+ props: {
686
+ color: '#ed4014'
687
+ }
688
+ }, '委派任务已撤回')
689
+ ])
690
+ } else if (params.row.auditResult == '80' && params.row.taskNode != this.taskNode) {
691
+ return h('div', [
692
+ h('tag', {
693
+ props: {
694
+ color: '#19be6b'
695
+ }
696
+ }, '已跳转到指定节点')
697
+ ])
698
+ } else if (params.row.auditResult == '90' && params.row.taskNode != this.taskNode) {
699
+ return h('div', [
700
+ h('tag', {
701
+ props: {
702
+ color: '#19be6b'
703
+ }
704
+ }, '已驳回到指定节点')
705
+ ])
706
+ }
707
+ }
708
+ }
709
+ })
710
+ column.push({
711
+ title: '操作', width: 100, align: 'center',
712
+ render: (h, params) => {
713
+ return h('div', [
714
+ h('Button', {
715
+ props: {
716
+ type: 'primary',
717
+ size: 'small'
718
+ },
719
+ style: {
720
+ marginRight: '5px'
721
+ },
722
+ on: {
723
+ click: () => {
724
+ this.selectNode(params.row)
725
+ }
726
+ }
727
+ }, '选择')
728
+ ])
729
+ },
730
+ })
731
+ return column
732
+ },
733
+ reductionColumn: function () {
734
+ let column = []
735
+ column.push({ title: '#', key: 'selectId', type: 'selection', align: 'center', width: 55 })
736
+ column.push({ title: '账号', key: 'auditId', align: 'center' })
737
+ column.push({ title: '姓名', key: 'auditName', align: 'center' })
738
+ return column
739
+ },
740
+ diagramTableColumns: function () {
741
+ let column = []
742
+ column.push({ title: '序号', type: 'index', width: 60 })
743
+ column.push({ title: `${this.handleName}节点`, key: 'taskName', minWidth: 130 })
744
+ column.push({ title: `${this.handleName}人`, key: 'auditName', minWidth: 150, tooltip: true })
745
+ column.push({
746
+ title: `${this.handleName}结果`, key: 'auditResult', minWidth: 150, align: 'center',
747
+ render: (h, { row, column, index }) => {
748
+ let label = ''
749
+ let tagColor = ''
750
+ if (row.auditResult == '00') {
751
+ label = '流程发起'
752
+ tagColor = 'green' // 绿色
753
+ } else if (row.auditResult == '10') {
754
+ label = '自动跳过'
755
+ tagColor = 'green' // 绿色
756
+ } else if (row.auditResult == '30') {
757
+ label = '通过'
758
+ tagColor = 'green' // 绿色
759
+ } else if (row.auditResult == '40') {
760
+ label = '驳回到上一级'
761
+ tagColor = 'volcano' // 火红色
762
+ } else if (row.auditResult == '50') {
763
+ label = '驳回到原点'
764
+ tagColor = 'red' // 红色
765
+ } else if (row.auditResult == '51') {
766
+ label = '流程终止'
767
+ tagColor = 'purple' // 紫色
768
+ } else if (row.auditResult == '60') {
769
+ label = '撤回'
770
+ tagColor = 'blue' // 蓝色
771
+ } else if (row.auditResult == '61') {
772
+ label = '交回委派任务'
773
+ tagColor = 'green' // 绿色
774
+ } else if (row.auditResult == '62') {
775
+ label = '委派任务被撤回'
776
+ tagColor = 'blue' // 蓝色
777
+ } else if (row.auditResult == '80') {
778
+ label = '跳转到指定节点'
779
+ tagColor = 'cyan' // 青色
780
+ } else if (row.auditResult == '82') {
781
+ label = '指定他人处理'
782
+ tagColor = 'cyan' // 青色
783
+ } else if (row.auditResult == '83') {
784
+ label = '会签减签'
785
+ tagColor = 'red' // 红色
786
+ } else if (row.auditResult == '90') {
787
+ label = '驳回到指定节点'
788
+ tagColor = 'magenta' // 品红色
789
+ } else {
790
+ label = '待审核'
791
+ tagColor = 'orange' // 默认橙色
792
+ }
793
+ return h('Tag', {
794
+ props: {
795
+ color: tagColor,
796
+ value: row.auditResult
797
+ }
798
+ }, label)
799
+ }
800
+ })
801
+ column.push({
802
+ title: `${this.handleName}时间`, key: 'auditTime', minWidth: 150,
803
+ render: (h, { row }) => {
804
+ const displayDate = row.startDate || row.auditDate
805
+ return h('span', displayDate)
806
+ }
807
+ })
808
+ column.push({
809
+ title: `${this.handleName}意见`, key: 'auditComment', minWidth: 180, tooltip: true,
810
+ render: (h, { row, column, index }) => {
811
+ let label = ''
812
+ if (row.auditComment == '' || row.auditComment == null) {
813
+ label = '无'
814
+ } else {
815
+ label = row.auditComment
816
+ }
817
+ return h('Label', {
818
+ props: {
819
+ value: row.auditComment
820
+ }
821
+ }, label)
822
+ }
823
+ })
824
+ if (this.showAttachmentFile) {
825
+ column.push({
826
+ title: `附件`, key: 'fileList', minWidth: 200,
827
+ render: (h, { row }) => {
828
+ if (!row.fileList || row.fileList.length === 0) {
829
+ return h('span', '') // 如果没有附件,显示“无”
830
+ }
831
+
832
+ //显示所有附件
833
+ return h('div', row.fileList.map(file => {
834
+ return h('a', {
835
+ style: {
836
+ display: 'block',
837
+ marginTop: '5px',
838
+ marginRight: '5px',
839
+ whiteSpace: 'nowrap',
840
+ overflow: 'hidden',
841
+ textOverflow: 'ellipsis',
842
+ maxWidth: '100px',
843
+ },
844
+ attrs: {
845
+ title: file.attachName // 鼠标悬停时显示完整名称
846
+ },
847
+ on: {
848
+ click: () => {
849
+ this.getAttach(file)
850
+ }
851
+ },
852
+ }, file.attachName)
853
+ }))
854
+ }
855
+ })
856
+ }
857
+
858
+ return column
859
+ },
860
+ },
861
+ provide() {
862
+ return {
863
+ toBeDoneListDoSearch: this.doSearch
864
+ }
865
+ },
866
+ methods: {
867
+ getWidth() {
868
+ if (this.width && this.width < 400) {
869
+ this.portraitWidth = 400
870
+ }
871
+ this.portraitWidth = this.width
872
+ },
873
+ initData() {
874
+ if (!this.isDetail) {
875
+ this.getTodoTask()
876
+ } else {
877
+ this.getDoneTask()
878
+ }
879
+ this.getHandleButtons()
880
+ },
881
+ getTodoTask() {
882
+ const self = this
883
+ let param = {
884
+ procId: this.procId,
885
+ applyId: this.applyId,
886
+ taskNode: this.taskNode,
887
+ taskId: this.taskId,
888
+ auditGroup: this.auditGroup
889
+ }
890
+ ajax.get(self.smartFlowServerContext + '/manage/processTodo/list', { params: param }).then(function (resp) {
891
+ if (resp.data.code === '200') {
892
+ let todoData = resp.data.data.rows[0]
893
+ self.curTaskId = todoData.taskId
894
+ self.instanceId = todoData.procInstanceId
895
+ self.curAuditGroup = todoData.auditGroup
896
+ self.revokeDelegateTask = todoData.delegateStatus ? todoData.delegateStatus === '10' : false
897
+ self.appointTask = todoData.delegateStatus ? todoData.delegateStatus === '20' : false
898
+ if (self.revokeDelegateTask) self.disable = true
899
+ let procType = todoData.procType
900
+ ajax.get(self.smartFlowServerContext + '/manage/processType/lists?proType=' + procType)
901
+ .then(resp => {
902
+ let data = resp.data.data.rows
903
+ self.permScope = data[0].permScope
904
+ self.defaultOrganTreeType = data[0].organTreeType ? data[0].organTreeType : '00'
905
+ self.getNodeOrganTreeType(procType)
906
+ }).catch(err => {
907
+ console.log(err)
908
+ })
909
+ self.getAttachList(self.curTaskId)
910
+ self.getHisAudit(self.curTaskId)
911
+ self.getProcessHistory(self.curTaskId)
912
+ } else {
913
+ self.$Message.error(resp.data.message)
914
+ }
915
+ }).catch((err) => {
916
+ console.log(err)
917
+ })
918
+ },
919
+ getNodeOrganTreeType(procType) {
920
+ const self = this
921
+ let param = {
922
+ procType: procType,
923
+ procId: this.procId,
924
+ taskNode: this.taskNode
925
+ }
926
+ ajax.get(self.smartFlowServerContext + '/manage/processTodo/getNodeOrganTreeType', { params: param }).then(function (resp) {
927
+ if (resp.data.code === '200') {
928
+ self.organTreeType = resp.data.data ? resp.data.data : self.defaultOrganTreeType
929
+ } else {
930
+ self.$Message.error(resp.data.message)
931
+ }
932
+ }).catch((err) => {
933
+ console.log(err)
934
+ })
935
+ },
936
+ getDoneTask() {
937
+ const self = this
938
+ let param = {
939
+ procId: this.procId,
940
+ applyId: this.applyId,
941
+ taskNode: this.taskNode,
942
+ taskId: this.taskId,
943
+ auditGroup: this.auditGroup
944
+ }
945
+ ajax.get(self.smartFlowServerContext + '/manage/processDone/getDoneDetail', { params: param }).then(function (resp) {
946
+ if (resp.data.code === '200') {
947
+ let rows = resp.data.data.rows
948
+ if (rows.length > 0) {
949
+ self.curAuditGroup = rows[0].auditGroup
950
+ self.hisAuditOpinion = []
951
+ let taskList = resp.data.data.rows
952
+ taskList.forEach(item => {
953
+ self.hisAuditOpinion.push({
954
+ auditOpinion: item.auditComment,
955
+ auditTime: timestampToTime(item.auditDate)
956
+ })
957
+ })
958
+ self.curTaskId = taskList[0].taskId
959
+ self.instanceId = taskList[0].procInstanceId
960
+ } else {
961
+ ajax.get(self.smartFlowServerContext + '/manage/processTodo/list', { params: param }).then(function (todoResp) {
962
+ if (todoResp.data.code === '200') {
963
+ self.curTaskId = todoResp.data.data.rows[0].taskId
964
+ self.instanceId = todoResp.data.data.rows[0].procInstanceId
965
+ self.curAuditGroup = todoResp.data.data.rows[0].auditGroup
966
+ } else {
967
+ self.$Message.error(todoResp.data.message)
968
+ }
969
+ }).catch((err) => {
970
+ console.log(err)
971
+ })
972
+ }
973
+ self.getAttachList(self.curTaskId)
974
+ self.getHisAudit(self.curTaskId)
975
+ self.getProcessHistory(self.curTaskId)
976
+ } else {
977
+ self.$Message.error(resp.data.message)
978
+ }
979
+ }).catch((err) => {
980
+ console.log(err)
981
+ })
982
+ },
983
+ getHandleButtons() {
984
+ const self = this
985
+ let param = {
986
+ procId: this.procId,
987
+ taskNode: this.taskNode
988
+ }
989
+ ajax.post(self.smartFlowServerContext + '/manage/approvalCenter/getNodeData', param).then(function (resp) {
990
+ if (resp.data.code === '200') {
991
+ self.handleButtons = resp.data.data[0].handleButtons
992
+ if (resp.data.data[0].hasOwnProperty('isSequential')) {
993
+ self.curNodeType = resp.data.data[0].isSequential ? 'sequentialMultiNode' : 'multiNode'
994
+ }
995
+ self.handleName = resp.data.data[0].handleName ? resp.data.data[0].handleName : '审批'
996
+ self.auditOpinionTitle = resp.data.data[0].handleName ? resp.data.data[0].handleName + '意见' : '审批意见'
997
+ if (!self.handleButtons || (!self.handleButtons.includes('auditOpinion') && !self.handleButtons.includes('attachmentFile') && !self.handleButtons.includes('auditHistory'))) {
998
+ self.showProcessInfo = false
999
+ }
1000
+ } else {
1001
+ self.$Message.error(resp.data.message)
1002
+ }
1003
+ }).catch((err) => {
1004
+ console.log(err)
1005
+ })
1006
+ },
1007
+ getNextNodes() {
1008
+ const self = this
1009
+ self.nextNodesFormList = []
1010
+ self.nextNodesOldSettings = []
1011
+ let param = {
1012
+ procId: this.procId,
1013
+ taskNode: this.taskNode
1014
+ }
1015
+ ajax.post(self.smartFlowServerContext + '/manage/processTodo/getNextNodes', param).then(function (resp) {
1016
+ if (resp.data.code === '200') {
1017
+ let nextNodeForm = {}
1018
+ let nextNodeOldForm = {}
1019
+ let data = resp.data.data
1020
+ for (let i = 0; i < data.length; i++) {
1021
+ nextNodeOldForm = {
1022
+ id: data[i].id,
1023
+ assignee: data[i].assignee ? data[i].assignee.id : '',
1024
+ timeLimit: data[i].timeLimit,
1025
+ }
1026
+ nextNodeForm = {
1027
+ id: data[i].id,
1028
+ name: data[i].name,
1029
+ orgTreeType: data[i].orgTreeType,
1030
+ assignee: data[i].assignee ? data[i].assignee.id : '',
1031
+ assigneeName: data[i].assignee ? data[i].assignee.name : '',
1032
+ candidateGroups: '',
1033
+ isMultiInstance: data[i].isMultiInstance,
1034
+ actionType: 'ASSIGNEE',
1035
+ remainDay: 0,
1036
+ remainTime: 0,
1037
+ inAdvanceDay: 0,
1038
+ inAdvanceTime: 0,
1039
+ processing: '00'
1040
+ }
1041
+ //显示具体候选人信息
1042
+ if (data[i].candidateGroups) {
1043
+ nextNodeForm.actionType = 'CAND'
1044
+ let names = []
1045
+ let candidates = {}
1046
+ for (let groupName in data[i].candidateGroups) {
1047
+ if (data[i].candidateGroups.hasOwnProperty(groupName)) {
1048
+ let group = data[i].candidateGroups[groupName]
1049
+ group.forEach(item => {
1050
+ names.push(item.name)
1051
+ })
1052
+ candidates[groupName] = group.map(item => item.id + ':' + item.name).join(',')
1053
+ }
1054
+ }
1055
+ nextNodeForm.candidateNames = names.join(',')
1056
+ nextNodeForm.candidates = candidates
1057
+ nextNodeOldForm.candidates = candidates
1058
+ }
1059
+ if (data[i].timeLimit) {
1060
+ let expireTime = data[i].timeLimit.split(';')[0].split(':')[1]
1061
+ let warningTime = data[i].timeLimit.split(';')[1].split(':')[1]
1062
+ let handleType = data[i].timeLimit.split(';')[2].split(':')[1]
1063
+ let days = expireTime.slice(0, expireTime.indexOf('D')) //过期天
1064
+ let hourOfDay = expireTime.slice(expireTime.indexOf('D') + 1, expireTime.indexOf('H')) //过期小时
1065
+ let daysWarn = warningTime.slice(0, warningTime.indexOf('D')) //警告天
1066
+ let hourOfDayWarn = warningTime.slice(warningTime.indexOf('D') + 1, warningTime.indexOf('H')) //警告小时
1067
+ nextNodeForm.remainDay = parseInt(days)
1068
+ nextNodeForm.remainTime = parseInt(hourOfDay)
1069
+ nextNodeForm.inAdvanceDay = parseInt(daysWarn)
1070
+ nextNodeForm.inAdvanceTime = parseInt(hourOfDayWarn)
1071
+ nextNodeForm.processing = handleType
1072
+ }
1073
+ self.nextNodesFormList.push(nextNodeForm)
1074
+ self.nextNodesOldSettings.push(nextNodeOldForm)
1075
+ }
1076
+ } else {
1077
+ self.$Message.error(resp.data.message)
1078
+ }
1079
+ }).catch((err) => {
1080
+ console.log(err)
1081
+ })
1082
+ },
1083
+ getAttachList(taskId) {
1084
+ const self = this
1085
+ const param = {
1086
+ taskId: taskId,
1087
+ procId: this.procId,
1088
+ applyId: this.applyId
1089
+ }
1090
+ ajax.get(self.smartFlowServerContext + '/manage/processDone/getAttachmentList', { params: param }).then(function (resp) {
1091
+ self.attachmentList = resp.data.data.rows
1092
+ self.attachmentList.forEach(item => {
1093
+ const index = item.fileName.lastIndexOf('.')
1094
+ const fileType = item.fileName.substr(index + 1).toLowerCase()
1095
+ const imageList = ['jpg', 'gif', 'png', 'svg']
1096
+ const docList = ['doc', 'docx']
1097
+ const zipList = ['rar', 'zip']
1098
+ const typeList = ['jpg', 'gif', 'png', 'docx']
1099
+ item.fileType = imageList.indexOf(fileType) !== -1 ? 'image' : docList.indexOf(fileType) !== -1 ? 'doc' : zipList.indexOf(fileType) !== -1 ? 'zip' : fileType
1100
+ item.showPreview = typeList.indexOf(fileType) !== -1
1101
+ })
1102
+ }).catch(err => {
1103
+ console.log(err)
1104
+ })
1105
+ },
1106
+ getHisAudit(taskId) {
1107
+ let self = this
1108
+ let params = {
1109
+ applyId: self.applyId,
1110
+ instanceId: self.instanceId,
1111
+ procId: self.procId,
1112
+ taskId: taskId
1113
+ }
1114
+ ajax.get(self.smartFlowServerContext + '/manage/processTodo/getHisAudit', { params: params }).then(function (resp) {
1115
+ if (resp.data.code === '200') {
1116
+ self.hisAudit = resp.data.data
1117
+ let uniqueDataMap = {}
1118
+ self.hisAudit.forEach((item) => {
1119
+ uniqueDataMap[item['taskNode']] = item
1120
+ })
1121
+ self.hisNode = Object.values(uniqueDataMap)
1122
+
1123
+ }
1124
+ })
1125
+ },
1126
+ getProcessHistory(taskId) {
1127
+ let self = this
1128
+ let params = {
1129
+ applyId: self.applyId,
1130
+ instanceId: self.instanceId,
1131
+ procId: self.procId,
1132
+ taskId: taskId
1133
+ }
1134
+ ajax.get(self.smartFlowServerContext + '/manage/processTodo/getProcessHis', { params: params }).then(function (resp) {
1135
+ if (resp.data.code === '200') {
1136
+ self.processHistory = resp.data.data
1137
+ }
1138
+ })
1139
+ },
1140
+
1141
+ audit: function (auditResult) {
1142
+ let self = this
1143
+ self.auditResult = auditResult
1144
+ self.submit()
1145
+ },
1146
+ submit() {
1147
+ let self = this
1148
+ self.auditParams = {
1149
+ procId: self.procId,
1150
+ applyId: self.applyId,
1151
+ taskId: self.curTaskId,
1152
+ auditOpinion: self.form.auditOpinion,
1153
+ fileListStr: JSON.stringify(self.fileList),
1154
+ auditResult: self.auditResult,
1155
+ params: JSON.stringify(self.datas),
1156
+ targetTaskNode: self.targetTaskNode,
1157
+ selectedUserId: self.selectedUserId,
1158
+ }
1159
+ if (self.auditResult == '' || self.auditResult == null) {
1160
+ self.$Message.error(`请选择${self.handleName}结果!`)
1161
+ return
1162
+ }
1163
+ if (self.form.auditOpinion == '' || self.form.auditOpinion == null) {
1164
+ if (self.auditResult === '30') {
1165
+ self.auditParams.auditOpinion = '通过'
1166
+ self.businessFormSave ? self.businessFormSave(self.handleSaveResult) : self.handleSaveResult(true)
1167
+ return
1168
+ }
1169
+ if ((!self.handleButtons || self.handleButtons.includes('auditOpinion')) && self.auditResult !== '84') {
1170
+ self.$Message.error(`请输入${self.handleName}意见!`)
1171
+ return
1172
+ } else {
1173
+ self.auditParams.auditOpinion = self.handleButtonsNames[self.auditResult]
1174
+ }
1175
+ }
1176
+ self.businessFormSave ? self.businessFormSave(self.handleSaveResult) : self.handleSaveResult(true)
1177
+ },
1178
+ handleSaveResult(saveResult, businessParams) {
1179
+ if (saveResult) {
1180
+ this.executeButtonAction(businessParams)
1181
+ } else {
1182
+ console.error('保存失败')
1183
+ }
1184
+ },
1185
+ executeButtonAction(businessParams) {
1186
+ const self = this
1187
+ if (businessParams) {
1188
+ Object.assign(self.datas, businessParams)
1189
+ self.auditParams.params = JSON.stringify(self.datas)
1190
+ }
1191
+ let auditResult = {
1192
+ code: self.auditResult,
1193
+ name: self.handleButtonsNames[self.auditResult]
1194
+ }
1195
+ if (self.auditResult === '82') {
1196
+ //指定他人处理
1197
+ self.assigneeBoxData = self.auditParams
1198
+ self.assigneeBoxData.auditResultName = self.handleButtonsNames[self.auditResult]
1199
+ self.assigneeBoxData.instanceId = self.instanceId
1200
+ self.$refs.assigneeHelpBox.toggleShowHelpBox(self.organTreeType, '', 'transferCurTask')
1201
+ } else if (self.auditResult === '84') {
1202
+ //委派任务
1203
+ self.$refs.assigneeHelpBox.toggleShowHelpBox(self.organTreeType, '', 'delegateTask')
1204
+ } else if (self.auditResult === '62') {
1205
+ //撤回委派任务
1206
+ ajax.post(self.smartFlowServerContext + '/manage/processTodo/audit', self.auditParams).then(resp => {
1207
+ let result = resp.data
1208
+ if (result.code == '200') {
1209
+ self.loading = false
1210
+ self.disable = false
1211
+ self.revokeDelegateTask = false
1212
+ self.$Message.success('撤回委派成功')
1213
+ } else {
1214
+ self.loading = false
1215
+ self.disable = false
1216
+ self.$Message.error(result.message)
1217
+ }
1218
+ })
1219
+ } else if (self.auditResult === '61') {
1220
+ //交回委派任务
1221
+ ajax.post(self.smartFlowServerContext + '/manage/processTodo/audit', self.auditParams).then(resp => {
1222
+ let result = resp.data
1223
+ if (result.code == '200') {
1224
+ self.loading = false
1225
+ self.disable = false
1226
+ self.$Message.success('交回委派任务成功')
1227
+ if (result.data) {
1228
+ let taskIds = result.data.id ? result.data.id : result.data.map(item => item.id).join(',')
1229
+ setTimeout(() => {
1230
+ self.executionCompleted(true, result.data.id ? result.data.processInstanceId : result.data[0].processInstanceId, taskIds, auditResult, self.curTaskId)
1231
+ }, 1000)
1232
+ }
1233
+ } else {
1234
+ self.loading = false
1235
+ self.disable = false
1236
+ self.$Message.error(result.message)
1237
+ }
1238
+ })
1239
+ } else if (self.auditResult === '80') {
1240
+ //跳转到后序指定节点
1241
+ self.getNodesBehind()
1242
+ } else if (self.auditResult === '90') {
1243
+ //驳回到前序指定节点
1244
+ self.getAllPreNodes()
1245
+ } else if (self.auditResult === '40') {
1246
+ //驳回到上一级
1247
+ self.loading = true
1248
+ self.disable = true
1249
+ let url = self.smartFlowServerContext + '/manage/processTodo/getPreNode'
1250
+ ajax.post(url, self.auditParams).then(function (resp) {
1251
+ let result = resp.data
1252
+ if (result.code == '30013' || result.code == '30014') {
1253
+ //前序节点为子流程或当前节点为子流程第一个节点不可驳回上一级节点
1254
+ self.$Message.warning(result.message)
1255
+ //避免未提示消息直接回调
1256
+ setTimeout(() => {
1257
+ self.executionCompleted(false, null, null, auditResult, self.curTaskId)
1258
+ }, 1000)
1259
+ } else if (result.code == '30010') {
1260
+ self.$Modal.confirm({
1261
+ title: '提示',
1262
+ content: result.message,
1263
+ onOk: () => {
1264
+ self.auditParams.auditResult = '70'
1265
+ let url = self.smartFlowServerContext + '/manage/processTodo/audit'
1266
+ ajax.post(url, self.auditParams).then(function (resp) {
1267
+ let result = resp.data
1268
+ if (result.code == '200') {
1269
+ self.loading = false
1270
+ self.disable = false
1271
+ self.$Message.success(result.message)
1272
+ //后端没有返回数据
1273
+ setTimeout(() => {
1274
+ self.executionCompleted(true, null, null, auditResult, self.curTaskId)
1275
+ }, 1000)
1276
+ bus.$emit('triggerTimer')
1277
+ } else {
1278
+ self.loading = false
1279
+ self.disable = false
1280
+ self.$Message.error(result.message)
1281
+ setTimeout(() => {
1282
+ self.executionCompleted(false, null, null, auditResult, self.curTaskId)
1283
+ }, 1000)
1284
+ }
1285
+ bus.$emit('triggerTimer')
1286
+ })
1287
+ },
1288
+ onCancel: () => {
1289
+ self.loading = false
1290
+ self.disable = false
1291
+ }
1292
+ })
1293
+ } else if (result.code == '10012') {
1294
+ // 数据同步
1295
+ self.loading = false
1296
+ self.disable = false
1297
+ self.$Message.warning(result.message)
1298
+ setTimeout(() => {
1299
+ self.executionCompleted(true, null, null, auditResult, self.curTaskId)
1300
+ }, 1000)
1301
+ } else {
1302
+ self.loading = true
1303
+ self.disable = true
1304
+ let url = self.smartFlowServerContext + '/manage/processTodo/audit'
1305
+ ajax.post(url, self.auditParams).then(function (resp) {
1306
+ let result = resp.data
1307
+ if (result.code == '200') {
1308
+ self.loading = false
1309
+ self.disable = false
1310
+ self.$Message.success(result.message)
1311
+ setTimeout(() => {
1312
+ if (result.data) {
1313
+ let taskIds = result.data.map(item => item.id).join(',')
1314
+ self.executionCompleted(true, result.data[0].processInstanceId, taskIds, auditResult, self.curTaskId)
1315
+ } else {
1316
+ self.executionCompleted(true, null, null, auditResult, self.curTaskId)
1317
+ }
1318
+ }, 1000)
1319
+ } else {
1320
+ self.loading = false
1321
+ self.disable = false
1322
+ self.$Message.error(result.message)
1323
+ setTimeout(() => {
1324
+ self.executionCompleted(false, null, null, auditResult, self.curTaskId)
1325
+ }, 1000)
1326
+ }
1327
+ bus.$emit('triggerTimer')
1328
+ })
1329
+ }
1330
+ })
1331
+ } else {
1332
+ if (self.auditResult === '30' && (!self.handleButtons || self.handleButtons.includes('appointHandler') || self.handleButtons.includes('appointTimeoutTime'))) {
1333
+ self.getNextNodes()
1334
+ self.appointBoxShow = true
1335
+ } else {
1336
+ self.doPass()
1337
+ }
1338
+ }
1339
+ },
1340
+ doPass() {
1341
+ let self = this
1342
+ this.modal = false
1343
+ let auditResult = {
1344
+ code: self.auditResult,
1345
+ name: self.handleButtonsNames[self.auditResult]
1346
+ }
1347
+ if (self.auditResult === '82' && (self.targetTaskNode == '' || self.targetTaskNode == null)) {
1348
+ self.auditResult = ''
1349
+ self.$Message.error(`请选择${self.handleName}节点!`)
1350
+ } else {
1351
+ self.loading = true
1352
+ self.disable = true
1353
+ self.auditParams.targetTaskNode = self.targetTaskNode
1354
+ let url = self.smartFlowServerContext + '/manage/processTodo/audit'
1355
+ ajax.post(url, self.auditParams).then(function (resp) {
1356
+ let result = resp.data
1357
+ if (result.code == '200') {
1358
+ self.loading = false
1359
+ self.disable = false
1360
+ self.$Message.success(result.message ? result.message : `${self.handleName}成功`)
1361
+ if (result.data) {
1362
+ let taskIds = result.data.id ? result.data.id : result.data.map(item => item.id).join(',')
1363
+ setTimeout(() => {
1364
+ self.executionCompleted(true, result.data.id ? result.data.processInstanceId : result.data[0].processInstanceId, taskIds, auditResult, self.curTaskId)
1365
+ }, 1000)
1366
+ } else {
1367
+ setTimeout(() => {
1368
+ self.executionCompleted(true, null, null, auditResult, self.curTaskId)
1369
+ }, 1000)
1370
+ }
1371
+ } else if (result.code == '10012') {
1372
+ // 数据同步
1373
+ self.loading = false
1374
+ self.disable = false
1375
+ self.$Message.warning(result.message)
1376
+ setTimeout(() => {
1377
+ self.executionCompleted(true, null, null, auditResult, self.curTaskId)
1378
+ }, 1000)
1379
+ } else if (result.code == '20002') {
1380
+ // 流程结束
1381
+ self.loading = false
1382
+ self.disable = false
1383
+ self.$Message.success(result.message)
1384
+ setTimeout(() => {
1385
+ self.executionCompleted(true, '流程已结束', '流程已结束', auditResult, self.curTaskId)
1386
+ }, 1000)
1387
+ } else {
1388
+ self.loading = false
1389
+ self.disable = false
1390
+ self.$Message.error(result.message ? result.message : `${self.handleName}失败`)
1391
+ setTimeout(() => {
1392
+ self.executionCompleted(false, null, null, auditResult, self.curTaskId)
1393
+ }, 1000)
1394
+ }
1395
+ bus.$emit('triggerTimer')
1396
+ })
1397
+ }
1398
+ },
1399
+ showUpdateMultitaskInstanceModal(updateType) {
1400
+ const self = this
1401
+ if (updateType === '81') {
1402
+ this.$refs.assigneeHelpBox.toggleShowHelpBox(this.organTreeType, '', 'addMultitaskInstance')
1403
+ } else if (updateType === '83') {
1404
+ ajax.get(self.smartFlowServerContext + '/manage/processTodo/getUnapprovedListOfMultiNode?taskId=' + self.curTaskId).then(function (resp) {
1405
+ if (resp.data.code === '200') {
1406
+ self.unapprovedAssigneeList = resp.data.data
1407
+ self.reductionMultitaskInstanceModal = true
1408
+ } else {
1409
+ self.$Message.error(resp.data.message)
1410
+ }
1411
+ }).catch(err => {
1412
+ console.log(err)
1413
+ })
1414
+ }
1415
+ },
1416
+ updateMultitaskInstance(updateType, assignees) {
1417
+ const self = this
1418
+ self.loading = true
1419
+ self.disable = true
1420
+ let param = {
1421
+ taskId: self.curTaskId,
1422
+ applyId: self.applyId,
1423
+ assignees: assignees,
1424
+ updateType: updateType
1425
+ }
1426
+ ajax.post(self.smartFlowServerContext + '/manage/processTodo/updateMultitaskInstance', param).then(resp => {
1427
+ let result = resp.data
1428
+ if (result.code == '200') {
1429
+ self.loading = false
1430
+ self.disable = false
1431
+ self.$Message.success(result.message)
1432
+ } else {
1433
+ self.loading = false
1434
+ self.disable = false
1435
+ self.$Message.error(result.message)
1436
+ }
1437
+ }).catch(err => {
1438
+ console.log(err)
1439
+ })
1440
+ },
1441
+ //委派
1442
+ delegateTask(assignee) {
1443
+ const self = this
1444
+ if (!assignee){
1445
+ self.$Message.error('请选择加签人员')
1446
+ return
1447
+ }
1448
+ let auditResult = {
1449
+ code: self.auditResult,
1450
+ name: self.handleButtonsNames[self.auditResult]
1451
+ }
1452
+ self.auditParams.selectedUserId = assignee
1453
+ ajax.post(self.smartFlowServerContext + '/manage/processTodo/audit', self.auditParams).then(resp => {
1454
+ let result = resp.data
1455
+ if (result.code == '200') {
1456
+ self.loading = false
1457
+ self.disable = false
1458
+ self.$Message.success('委派成功')
1459
+ if (result.data) {
1460
+ let taskIds = result.data.id ? result.data.id : result.data.map(item => item.id).join(',')
1461
+ setTimeout(() => {
1462
+ self.executionCompleted(true, result.data.id ? result.data.processInstanceId : result.data[0].processInstanceId, taskIds, auditResult, self.curTaskId)
1463
+ }, 1000)
1464
+ }
1465
+ } else {
1466
+ self.loading = false
1467
+ self.disable = false
1468
+ self.$Message.error(result.message)
1469
+ }
1470
+ }).catch(err => {
1471
+ console.log(err)
1472
+ })
1473
+ },
1474
+ //加签
1475
+ addMultitaskInstance(assingeeList) {
1476
+ const assingees = assingeeList.join(',')
1477
+ this.updateMultitaskInstance('81', assingees)
1478
+ },
1479
+ //减签
1480
+ reductionMultitaskInstance() {
1481
+ if (this.reductionAssigneeList.length === 0) {
1482
+ this.$Message.error('请选择减签人员')
1483
+ return
1484
+ }
1485
+ const assingees = this.reductionAssigneeList.map(item => item.auditId).join(',')
1486
+ this.updateMultitaskInstance('83', assingees)
1487
+ },
1488
+
1489
+ doSearch() {
1490
+ //不需要实现,是子组件assigneeBox要求使用父组件的这个方法
1491
+ },
1492
+ tabsChange(tab) {
1493
+ console.log(tab)
1494
+ },
1495
+ getAttach(row) {
1496
+ window.open(this.smartFlowServerContext + '/manage/oss/file/get/' + row.fileId, '_blank')
1497
+ },
1498
+ preViewAttach(row) {
1499
+ let reg = /\.(gif|jpg|jpeg|bmp|png|PNG)$/
1500
+ let regs = /\.(pdf)$/
1501
+ if (reg.test(row.fileName)) {
1502
+ let url = this.smartFlowServerContext + '/manage/oss/file/get/' + row.fileId
1503
+ this.imgPreview(url)
1504
+ } else if (regs.test(row.fileName)) {
1505
+ window.open(this.smartFlowServerContext + '/manage/oss/file/getFileStream?fileId=' + row.fileId, '_blank')
1506
+ } else {
1507
+ this.modalDocx = true
1508
+ axios({
1509
+ method: 'get',
1510
+ responseType: 'blob', // 因为是流文件,所以要指定blob类型
1511
+ url: this.smartFlowServerContext + '/manage/oss/file/get/' + row.fileId// 一个word下载文件的接口
1512
+ }).then(({ data }) => {
1513
+ docx.renderAsync(data, this.$refs.file, null, {
1514
+ className: 'docx', //默认和文档样式类的类名/前缀
1515
+ inWrapper: true, //启用围绕文档内容呈现包装器
1516
+ ignoreWidth: false, //禁用页面的渲染宽度
1517
+ ignoreHeight: false, //禁用页面的渲染高度
1518
+ ignoreFonts: false, //禁用字体渲染
1519
+ breakPages: true, //在分页符上启用分页
1520
+ ignoreLastRenderedPageBreak: true, //在lastRenderedPageBreak元素上禁用分页
1521
+ experimental: false, //启用实验功能(制表符停止计算)
1522
+ trimXmlDeclaration: true, //如果为true,则在解析之前将从xml文档中删除xml声明
1523
+ useBase64URL: false, //如果为true,图像、字体等将转换为base 64 URL,否则使用URL.createObjectURL
1524
+ useMathMLPolyfill: false, //包括用于铬、边等的MathML多填充。
1525
+ showChanges: false, //启用文档更改的实验渲染(插入/删除)
1526
+ debug: false, //启用额外的日志记录
1527
+ })
1528
+ }
1529
+ )
1530
+ }
1531
+ },
1532
+ imgPreview(url) {
1533
+ this.imageUrl = url
1534
+ this.modalVisible = true
1535
+ },
1536
+
1537
+ //打印流程图信息
1538
+ processPrint() {
1539
+ let self = this
1540
+ let params = {
1541
+ applyId: self.applyId,
1542
+ instanceId: self.instanceId,
1543
+ procId: self.procId,
1544
+ taskId: self.curTaskId,
1545
+ }
1546
+ ajax.get(self.smartFlowServerContext + '/manage/processTodo/getPrintData', { params: params }).then(function (resp) {
1547
+ let result = resp.data.data
1548
+ if (resp.data.code === '200') {
1549
+ let tableData = result
1550
+ self.process.tableData = tableData
1551
+ self.process.applyId = self.applyId
1552
+ self.process.instanceId = self.instanceId
1553
+ self.process.procId = self.procId
1554
+ self.datas.orgId = tableData[0].orgId
1555
+ self.datas.orgName = tableData[0].orgName
1556
+ self.modalBoxShow = true
1557
+ }
1558
+ })
1559
+ },
1560
+
1561
+ showTaskNode(taskId) {
1562
+ if (this.processHistory.length > 0) {
1563
+ let task = null
1564
+ this.processHistory.some(itemList => {
1565
+ task = itemList.find(item => item.taskId === taskId)
1566
+ return task !== undefined
1567
+ })
1568
+ return task ? task.taskName : ''
1569
+ }
1570
+ return ''
1571
+ },
1572
+ cancel() {
1573
+ this.modal = false
1574
+ this.auditResult = ''
1575
+ },
1576
+ reductionModalCancel() {
1577
+ this.reductionMultitaskInstanceModal = false
1578
+ this.reductionAssigneeList = []
1579
+ },
1580
+ selectAssignee(selection) {
1581
+ this.reductionAssigneeList = selection
1582
+ },
1583
+ selectNode(currentRow, oldCurrentRow) {
1584
+ let self = this
1585
+ self.targetTaskNode = currentRow.taskNode
1586
+ },
1587
+ getAllPreNodes() {
1588
+ let self = this
1589
+ let params = {
1590
+ processDefId: self.procId,
1591
+ taskId: self.curTaskId,
1592
+ }
1593
+ ajax.get(self.smartFlowServerContext + '/manage/processTodo/getAllPreNodes', { params: params }).then(function (resp) {
1594
+ if (resp.data.code === '200') {
1595
+ if (resp.data.data.length > 0) {
1596
+ self.allNode = resp.data.data
1597
+ self.modal1 = true
1598
+ } else {
1599
+ self.$Message.warning('当前流程无前序节点')
1600
+ }
1601
+ } else {
1602
+ self.$Message.error(resp.data.message)
1603
+ }
1604
+ })
1605
+ },
1606
+ getNodesBehind() {
1607
+ let self = this
1608
+ let params = {
1609
+ processDefId: self.procId,
1610
+ taskId: self.curTaskId,
1611
+ }
1612
+ ajax.get(self.smartFlowServerContext + '/manage/processTodo/getNodesBehind', { params: params }).then(function (resp) {
1613
+ if (resp.data.code === '200') {
1614
+ if (resp.data.data.length > 0) {
1615
+ self.allNode = resp.data.data
1616
+ self.modal1 = true
1617
+ } else {
1618
+ self.$Message.warning('当前流程无后续节点')
1619
+ }
1620
+ } else {
1621
+ self.$Message.error(resp.data.message)
1622
+ }
1623
+ })
1624
+ },
1625
+ handleSelectedUser(userId) {
1626
+ this.selectedUserId = userId
1627
+ },
1628
+
1629
+ //折叠动画效果
1630
+ beforeEnter(el) {
1631
+ el.style.height = '0'
1632
+ },
1633
+ enter(el, done) {
1634
+ setTimeout(() => {
1635
+ el.style.height = el.scrollHeight + 'px'
1636
+ }, 0)
1637
+
1638
+ el.addEventListener('transitionend', done)
1639
+ },
1640
+ beforeLeave(el) {
1641
+ el.style.height = el.scrollHeight + 'px'
1642
+ },
1643
+ leave(el, done) {
1644
+ setTimeout(() => {
1645
+ el.style.height = '0'
1646
+ }, 0)
1647
+
1648
+ el.addEventListener('transitionend', done)
1649
+ },
1650
+
1651
+ beforeFlowInfoEnter(el) {
1652
+ el.style.transform = 'translateX(100%)'
1653
+ },
1654
+ flowInfoEnter(el, done) {
1655
+ const transitionDuration = 0.5
1656
+ el.style.transition = `transform ${transitionDuration}s`
1657
+ el.style.transform = 'translateX(0)'
1658
+ el.addEventListener('transitionend', done)
1659
+ },
1660
+ beforeFlowInfoLeave(el) {
1661
+ el.style.transform = 'translateX(0)'
1662
+ },
1663
+ flowInfoLeave(el, done) {
1664
+ const transitionDuration = 0.5
1665
+ el.style.transition = `transform ${transitionDuration}s`
1666
+ el.style.transform = 'translateX(100%)'
1667
+ el.addEventListener('transitionend', done)
1668
+ },
1669
+ uploadFile(file) {
1670
+ const self = this
1671
+ self.fileList = []
1672
+ file.forEach(item => {
1673
+ self.fileList.push({
1674
+ fileName: item.fileName,
1675
+ fileId: item.fileCode,
1676
+ })
1677
+ })
1678
+ },
1679
+
1680
+ appointOk() {
1681
+ const self = this
1682
+ let oldSettings
1683
+ let params = this.nextNodesFormList.reduce((acc, item) => {
1684
+ acc[item.id] = {
1685
+ needUpdate: 'false',
1686
+ }
1687
+ item.assignee ? acc[item.id].assignee = item.assignee : ''
1688
+ item.candidateGroups ? acc[item.id].candidateGroup = item.candidateGroups : ''
1689
+ let timeLimit = 'expireTime:0D0H;warningTime:0D0H;handleType:00'
1690
+ if (!(item.remainDay === 0 && item.remainTime === 0 && item.inAdvanceDay === 0 && item.inAdvanceTime === 0)) {
1691
+ timeLimit = 'expireTime:' + parseInt(item.remainDay) + 'D' + parseInt(item.remainTime) + 'H' + ';warningTime:' + parseInt(item.inAdvanceDay) + 'D' + parseInt(item.inAdvanceTime) + 'H;' + 'handleType:' + item.processing
1692
+ acc[item.id].timeLimit = timeLimit
1693
+ } else {
1694
+ acc[item.id].timeLimit = ''
1695
+ }
1696
+ oldSettings = self.nextNodesOldSettings.filter(oldSetting => oldSetting.id === item.id)[0]
1697
+ if (oldSettings.assignee !== item.assignee || self.checkGroupsUpdate(oldSettings.candidates, item.candidateGroups, item.isMultiInstance) || self.checkTimeLimitUpdate(oldSettings.timeLimit, timeLimit)) {
1698
+ acc[item.id].needUpdate = 'true'
1699
+ }
1700
+ return acc
1701
+ }, {})
1702
+ self.auditParams.nodeConfigMaps = JSON.stringify(params)
1703
+ self.doPass((execResult, instanceId, taskIds, auditResult, curTaskId) => {
1704
+ if (this.executionCompleted) {
1705
+ this.executionCompleted(execResult, instanceId, taskIds, auditResult, curTaskId)
1706
+ }
1707
+ })
1708
+ },
1709
+ checkGroupsUpdate(oldSetting, newSetting, isMultiInstance) {
1710
+ if (oldSetting && newSetting) {
1711
+ let oldIdList = []
1712
+ for (let [key, value] of Object.entries(oldSetting)) {
1713
+ if (value) {
1714
+ value.split(',').forEach(part => {
1715
+ const [id] = part.split(':')
1716
+ if (id) {
1717
+ oldIdList.push(id)
1718
+ }
1719
+ })
1720
+ }
1721
+ }
1722
+ const regex = /(?:O:|U:|P:|R:|T:)([^,]+)/g
1723
+ let match
1724
+ const newIds = []
1725
+ while ((match = regex.exec(newSetting)) !== null) {
1726
+ newIds.push(...match[1].split(';'))
1727
+ }
1728
+
1729
+ if (isMultiInstance) {
1730
+ //串签的情况下可能只有顺序发生了变化
1731
+ const oldStr = oldIdList.join(',')
1732
+ const newStr = newIds.join(',')
1733
+ return oldStr !== newStr
1734
+ }else {
1735
+ const allInString = oldIdList.every(item => newIds.includes(item));
1736
+ const hasExtra = newIds.some(item => !oldIdList.includes(item));
1737
+ return !allInString || hasExtra
1738
+ }
1739
+
1740
+ }
1741
+ return false
1742
+ },
1743
+ checkTimeLimitUpdate(oldSetting, newSetting) {
1744
+ if (oldSetting && newSetting) {
1745
+ return oldSetting !== newSetting
1746
+ }
1747
+ if (!oldSetting) {
1748
+ return newSetting !== 'expireTime:0D0H;warningTime:0D0H;handleType:00'
1749
+ }
1750
+ return false
1751
+ },
1752
+ readingRangeClick(item) {
1753
+ let permScope = item.orgTreeType === this.defaultOrganTreeType ? this.permScope : 'all'
1754
+ let orgTreeType = item.orgTreeType ? item.orgTreeType : this.defaultOrganTreeType
1755
+ this.$refs.assigneeHelpBox.toggleShowHelpBox(orgTreeType, permScope, 'transferNextTask', item.id)
1756
+ },
1757
+ candidateGroupsReadingRangeClick(item) {
1758
+ let permScope = item.orgTreeType === this.defaultOrganTreeType ? this.permScope : 'all'
1759
+ let orgTreeType = item.orgTreeType ? item.orgTreeType : this.defaultOrganTreeType
1760
+ this.$refs.candidateGroupsHelpBox.toggleShowHelpBox(permScope, item.candidates, orgTreeType, item.id)
1761
+ },
1762
+ updateCandGroups(newCandGroups, nameStr, detail, nodeId) {
1763
+ let oldSettings = this.nextNodesOldSettings.filter(item => item.id === nodeId)[0]
1764
+ if (JSON.stringify(oldSettings.candidates) != JSON.stringify(detail)) {
1765
+ let node = this.nextNodesFormList.filter(item => item.id === nodeId)[0]
1766
+ node.candidateGroups = newCandGroups
1767
+ node.candidateNames = nameStr
1768
+ node.candidates = detail
1769
+ node.needUpdate = true
1770
+ this.$forceUpdate()
1771
+ }
1772
+ },
1773
+ updateNextNodeAssignee(selectedAssigneeId, selectedAssigneeName, nodeId) {
1774
+ let oldSettings = this.nextNodesOldSettings.filter(item => item.id === nodeId)[0]
1775
+ if (oldSettings.assignee != selectedAssigneeId) {
1776
+ let node = this.nextNodesFormList.filter(item => item.id === nodeId)[0]
1777
+ node.assignee = selectedAssigneeId
1778
+ node.assigneeName = selectedAssigneeName
1779
+ node.needUpdate = true
1780
+ this.$forceUpdate()
1781
+ }
1782
+ },
1783
+ },
1784
+ watch: {
1785
+ auditOpinionText(label) {
1786
+ this.form.auditOpinion = label
1787
+ },
1788
+ procId(val) {
1789
+ this.procId = val
1790
+ this.initData()
1791
+ },
1792
+ }
1793
+ }
1794
+ </script>
1795
+
1796
+ <style lang="less" scoped>
1797
+ @import "./styles/css/index.less";
1798
+
1799
+ /deep/ .ivu-table-row-highlight td {
1800
+ background-color: #50c1ff !important;
1801
+ color: #fff !important;
1802
+ }
1803
+
1804
+ /deep/ .ivu-card-body {
1805
+ padding: 10px;
1806
+ }
1807
+
1808
+ .page-info /deep/ .page-body {
1809
+ overflow-y: hidden;
1810
+ }
1811
+ </style>