@lambo-design/workflow-approve 1.0.0-beta.39 → 1.0.0-beta.40

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